Skip to content

Features as a directory; drop the -NNN suffix#6

Merged
adamlutz merged 1 commit into
mainfrom
chore/harness-features
May 20, 2026
Merged

Features as a directory; drop the -NNN suffix#6
adamlutz merged 1 commit into
mainfrom
chore/harness-features

Conversation

@adamlutz

Copy link
Copy Markdown
Member

Eliminates the conflict source that every previous PR has hit on `feature_list.json`. Replaces the single shared array with one JSON file per feature, and replaces meaningless `-NNN` numbering with meaningful `-` IDs.

What changed

Before After
`feature_list.json` (one array, N writers) `features/` directory, one file per feature
`harness-001`, `harness-002`, `e2e-001`, `ci-001`, `ui-001`, `ui-002` `harness-init`, `harness-simplify`, `e2e-maestro`, `ci-actions`, `ui-home`, `ui-feature-list`
Validator parsed a JSON array Validator globs `features/*.json`, enforces filename↔id
Branch regex: `/--` Branch regex: `/`

7 feature files now in `features/` (1 new for this work). 6 from prior PRs, all preserved with their statuses + commitShas. The new ID lives in both the filename and the JSON `id` field; validator catches any drift.

Why this works

Two parallel branches that add different features now touch different files. No collision possible. The `feature_list.json` array was the single point of contention for every prior PR (#2/#3, #3/#4, #5/#3 all hit it).

WIP=1 is enforced per-branch by the validator. The honest trade-off: if two branches each mark a different feature `in_progress` and both merge, main will transiently show 2 in_progress until the next session resolves. Documented in `docs/HARNESS.md` → Features as files.

Files touched

23 files changed (+337/−221). The bulk is the seven new `features/*.json` files and the deletion of the old array. Everything else is plumbing:

  • `scripts/feature-list-check.js` rewritten for directory globbing
  • `scripts/harness-ci-checks.sh` step 6 (branch name) updated for new shape
  • `docs/HARNESS.md` — naming standard rewritten + new "Features as files" section
  • `DECISIONS.md` — new entry 2026-05-20 logging the choice
  • All other doc/script/workflow files — `feature_list.json` references updated

Bookkeeping fix included

`ci-actions` (was `ci-001`) was still `in_progress` on main after PR #3 merged — the closing flip never landed. Fixed here: `features/ci-actions.json` is `done` with `commitSha: c8bb4c9` (the merge commit). WIP=1 preserved.

Verification

  • `npm run verify` → green; validator reports `features: ok (7 features — todo:3 in_progress:1 blocked:0 done:3)`
  • `bash scripts/harness-ci-checks.sh` → all 6 invariants green on `chore/harness-features`
  • `bash scripts/check-clean-state.sh` → green (after this commit is in)

Follow-up: PR #5 needs a small rebase

PR #5 (`docs/docs-001-template`) still has the old `feature_list.json` with its `docs-001` entry. After this lands it needs:

  1. Delete the `feature_list.json` change
  2. Create `features/docs-template.json` (renamed from `docs-001`)
  3. Update its commit message

Single commit. I can handle it once this merges.

🤖 Generated with Claude Code

Eliminates the parallel-branch merge conflicts that have been a
recurring source of friction.

WHAT CHANGED

- feature_list.json (a single shared array) → features/ directory,
  one JSON file per feature. Two branches that add different features
  now touch different files — they can't conflict.
- Feature IDs lose the meaningless -NNN suffix in favour of a
  meaningful <category>-<slug>:
    harness-001       → harness-init
    harness-002       → harness-simplify
    e2e-001           → e2e-maestro
    ci-001            → ci-actions
    ui-001            → ui-home
    ui-002            → ui-feature-list
- Validator (scripts/feature-list-check.js) globs features/*.json,
  enforces filename↔id, validates the same per-feature shape as
  before plus WIP=1 across the set.
- harness-ci-checks.sh step 6 (branch-name) updated for the new
  shape: <type>/<feature-id> with no -NNN, and the feature-existence
  check now walks features/ rather than parsing the JSON array.
- docs/HARNESS.md "Naming standard" section rewritten. New "Features
  as files" section explains the trade-off (WIP=1 per-branch only;
  merge-time may transiently show 2 in_progress until resolved).
- PROGRESS.md, AGENTS.md, CLAUDE.md, README, init.sh, verify.sh,
  docs/{SESSION,ARCHITECTURE,RN_PLATFORM}.md, .maestro/README.md,
  .github/workflows/harness.yml — all `feature_list.json` references
  updated.
- DECISIONS.md — new entry 2026-05-20.

CLOSING ci-actions (was ci-001)

Bookkeeping gap: PR #3 merged but the feature was never flipped to
done on main. Fixed: features/ci-actions.json status=done with
commitSha=c8bb4c9 (the merge commit). 3 features done now; WIP=1
preserved (harness-features is the one in_progress on this branch).

WHY THIS WAS WORTH DOING

Every previous PR conflicted on feature_list.json:
  - PR #2 merge → PR #3 needed rebase
  - PR #3 merge → PR #5 needed rebase
  - PR #4 merge → PR #3 needed rebase
The cause was structural (one shared array, N parallel writers), not
a workflow lapse. Per-file scope primitives + meaningful IDs remove
that surface entirely. PROGRESS.md still has a small conflict
surface but it's narrow (the "Next steps" block).

FOLLOW-UP REQUIRED

PR #5 (docs-template, was docs-001) still has the old
feature_list.json. It needs a small rebase after this lands:
  1. delete its feature_list.json edit
  2. rename id docs-001 → docs-template
  3. create features/docs-template.json

Mechanical — should be a single commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@adamlutz adamlutz merged commit 75ee682 into main May 20, 2026
2 checks passed
@adamlutz adamlutz deleted the chore/harness-features branch May 20, 2026 16:04
adamlutz added a commit that referenced this pull request May 20, 2026
Per user direction: PROGRESS.md's only durable value (the next-best-step
pointer) is derivable from features/ — pick the highest-priority
in_progress feature, else the first todo. Everything else PROGRESS.md
tried to carry was duplicated elsewhere (status in features/, history
in git log, decisions in DECISIONS.md, per-branch context in PR
descriptions).

WHAT'S REMOVED
- PROGRESS.md (deleted)
- All references across AGENTS.md, CLAUDE.md, README.md, init.sh,
  docs/{HARNESS,SESSION,ARCHITECTURE}.md, scripts/check-clean-state.sh,
  scripts/harness-ci-checks.sh

WHAT'S NEW: CLOSE-BEFORE-MERGE CONVENTION
The in-flight feature's status is flipped to `done` in the LAST commit
on the branch BEFORE the merge, with `commitSha` set to that commit
(the latest implementation commit). The PR's merge then carries the
closed feature into main as part of its own diff. No follow-up
bookkeeping commit.

This is the harness's answer to the recurring post-merge bookkeeping
gap that bit ci-actions (PR #3), harness-features (PR #6), and
docs-template (PR #7) — three consecutive PRs, same shape, same fix
forgotten every time.

Documented in docs/SESSION.md → "The close-before-merge convention"
and surfaced in AGENTS.md's End-of-session steps. scripts/check-clean-state.sh
check 4 now warns if the in-flight feature is still in_progress
(soft warning — the work may legitimately not be ready to merge).

OTHER CHANGES
- init.sh: 7 steps → 6 (no PROGRESS tail at the end)
- scripts/harness-ci-checks.sh: 6 checks → 5 (dropped PROGRESS-has-Next-steps)
- scripts/check-clean-state.sh: check 4 reshaped to check feature status
- DECISIONS.md: replaced the 'trim PROGRESS.md' entry with the
  'remove PROGRESS.md' decision documenting the convention

NOTE ON THIS PR'S OWN CLOSE-BEFORE-MERGE
This commit is the implementation. The close-before-merge flip
happens in the next commit on this branch (referencing this commit's
SHA as commitSha).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant