* fix(#2914): never persist a spent emitted-drift ack on next tests/emitted-drift-ack.json held 34 spent #2834 entries merged via #2900. Every entry is scoped to the diff that introduced it (#2789), so once merged to next it is at the base by definition -- spent and inert. Its presence is still load-bearing though: each PR rewrites the paths map wholesale, making a persistent base copy a shared cell. Five of six conflicting PRs in the open queue collided on this file and nothing else. Deletes the stale document and adds a push-to-next guard asserting it stays absent. The guard is deliberately NOT wired into lint:ci -- a PR-lane check against the base is the #2768 shape #2789 exists to end. Closes #2914 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore(#2914): backfill changeset pr number Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(#2914): per-PR ack fragments instead of one shared mutable file The emitted-drift acknowledgment lived in a single tests/emitted-drift-ack.json whose paths map every PR rewrote wholesale. That is a shared mutable cell: any two PRs needing an ack edit the same lines and conflict. Five of six conflicting PRs in the open queue collided on this file and nothing else. Acks now live as per-PR fragments under tests/emitted-drift-acks/, the same shape .changeset/ already uses to solve this exact problem. Two PRs pick different filenames, so they cannot collide, and fragments lingering on next are harmless rather than toxic. The legacy file's 35 entries are MIGRATED into a fragment, not deleted. An earlier delete-only attempt failed verification twice: the ratchet lost the spec-phase.md acknowledgment from #2779 and reported a 10-byte growth with no ack. Relocating preserves every acknowledgment. The legacy single file is still READ (unioned with the fragments) because five open PRs carry it; dropping support would break all of them. A duplicate path key across sources is a hard error, never last-wins. The push-to-next guard is retargeted accordingly: it now asserts only that the legacy SHARED file never reappears on next. Fragments may persist harmlessly. Closes #2914 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -773,23 +773,50 @@ what your PR changed against `next` and requires every emitted-artifact hash tha
|
||||
to be attributable to your diff. If it is not, the check fails and names the paths.
|
||||
|
||||
Legitimate cases where emitted bytes move for a reason your diff cannot show directly —
|
||||
a converter change, for example — go through `tests/emitted-drift-ack.json` (name the
|
||||
path, say why); see `CONTEXT.md`'s `### Emitted Artifact Provenance` entry for the full
|
||||
model. Growth in a `gsd-core/workflows/*.md` or `agents/gsd-*.md` file is reported with
|
||||
its exact byte delta and needs the same acknowledgment; the outer tier hard caps in
|
||||
a converter change, for example — go through a **per-PR fragment** under
|
||||
`tests/emitted-drift-acks/` (#2914; name the path, say why); see `CONTEXT.md`'s
|
||||
`### Emitted Artifact Provenance` entry for the full model. Growth in a
|
||||
`gsd-core/workflows/*.md` or `agents/gsd-*.md` file is reported with its exact byte delta
|
||||
and needs the same acknowledgment; the outer tier hard caps in
|
||||
`tests/workflow-size-budget.test.cjs` / `tests/agent-size-budget.test.cjs` are unaffected
|
||||
and still apply.
|
||||
and still apply. The legacy single `tests/emitted-drift-ack.json` is still read and
|
||||
unioned in for any branch that still carries it, but new acknowledgments go in a NEW
|
||||
fragment, never that file.
|
||||
|
||||
You do not need to memorize any of this. **The failure output names its own remedy** — it
|
||||
tells you the file to create, that it does not exist yet, which key to use, and prints a
|
||||
minimal valid document you can paste. Note the two key spaces, because the message says
|
||||
which one applies: an unattributable **hash** ripple is keyed on the emitted path
|
||||
tells you to create a new fragment under `tests/emitted-drift-acks/` (with a name nobody
|
||||
else is using — include your issue or PR number), which key to use, and prints a minimal
|
||||
valid document you can paste. Note the two key spaces, because the message says which one
|
||||
applies: an unattributable **hash** ripple is keyed on the emitted path
|
||||
(`skills/gsd-add-tests/SKILL.md`), while **growth** is keyed on the bare filename as it
|
||||
appears under `gsd-core/workflows/` or `agents/` (`explore.md`). When you remove the last
|
||||
entry from `tests/emitted-drift-ack.json`, delete the file too — its presence is the
|
||||
alarm, so an empty one signals nothing. Nothing here is regenerated: if you find yourself
|
||||
looking for a baseline file to re-run a generator over, that file was deleted by #2724 and
|
||||
is not coming back.
|
||||
entry from your fragment, delete the fragment file too — its presence is the alarm, so an
|
||||
empty one signals nothing. Nothing here is regenerated: if you find yourself looking for a
|
||||
baseline file to re-run a generator over, that file was deleted by #2724 and is not coming
|
||||
back.
|
||||
|
||||
**Why fragments, not one file (#2914):** every PR needing an acknowledgment used to
|
||||
rewrite `tests/emitted-drift-ack.json`'s `paths` map wholesale — a single shared mutable
|
||||
file every such PR touches guarantees a merge conflict between any two of them (5 of 6
|
||||
conflicting PRs in one open queue collided on this file and nothing else), and it means
|
||||
spent, already-merged entries pile up on `next`. A fragment per PR — the same shape
|
||||
`.changeset/` already uses for the identical problem — means two PRs can never conflict on
|
||||
this seam again, and a fragment left on `next` after merge is inert rather than a shared
|
||||
cell. Two ack sources (two fragments, or a fragment and the legacy file) may **never** name
|
||||
the same path; that is a hard, loudly-reported error, not a silent last-wins.
|
||||
|
||||
`tests/emitted-drift-ack.json` (the legacy single file, specifically — NOT the fragment
|
||||
directory) must never persist on `next` (#2914): every entry is scoped to the diff that
|
||||
introduced it, so once merged it is, by definition, already at the base — spent and inert,
|
||||
regardless of shape, and its persistence is what makes it a shared merge-conflict cell. A
|
||||
fragment persisting on `next` is harmless, since fragments are independently named and
|
||||
cannot conflict with anything, so this guard is deliberately scoped to the legacy file
|
||||
alone. This is enforced only on `next` itself, by the `guard-no-ack-on-next` job in
|
||||
`.github/workflows/test.yml` (push-to-`next` trigger,
|
||||
`scripts/lint-emitted-drift-ack.cjs --guard-next`), never as a PR-lane check — a PR-lane
|
||||
"base ack must be absent" check would red every open PR the moment one landed (the #2768
|
||||
shape #2789 exists to prevent). If you ever see the legacy file present on `next`, delete
|
||||
it; do not try to make it well-formed.
|
||||
|
||||
`npm run regen:derived` still exists for the artifacts that ARE committed and derived —
|
||||
`sync-manifest-versions`, the ADR index, the capability matrix, the inventory manifest,
|
||||
@@ -929,8 +956,9 @@ gsd-core/
|
||||
Per-file growth is caught by the differential
|
||||
attribution check (tests/emitted-attribution.test.cjs,
|
||||
ADR-2719) — it reports the exact byte delta and
|
||||
requires an entry in tests/emitted-drift-ack.json,
|
||||
no committed snapshot to regenerate. Loose tier
|
||||
requires a per-PR fragment in
|
||||
tests/emitted-drift-acks/ (#2914), no committed
|
||||
snapshot to regenerate. Loose tier
|
||||
hard caps remain in tests/workflow-size-budget.test.cjs.
|
||||
The same applies to agent files (agents/gsd-*.md,
|
||||
tests/agent-size-budget.test.cjs). Full how-to +
|
||||
|
||||
Reference in New Issue
Block a user