Skip to content

chore(specsync): archive accepted change records - #23

Open
corvid-agent wants to merge 4 commits into
mainfrom
cos/archive-specsync-accepted
Open

corvid-agent wants to merge 4 commits into
mainfrom
cos/archive-specsync-accepted

Conversation

@corvid-agent

Copy link
Copy Markdown

Summary

  • Archive accepted SpecSync change records CHG-0001 through CHG-0005 (SpecSync/Trust adopt leftovers).

Test plan

  • Confirm .specsync/changes/ no longer contains CHG-0001..0005
  • Confirm archive entries under .specsync/archive/
  • Do not merge until reviewed

Archive accepted SpecSync adopt leftovers (CHG-0001..0005).

@corvid-agent corvid-agent left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Archive-only SpecSync ledger move: accepted change records renamed into .specsync/archive/changes/… with state: archived / archived state.json, product code untouched.

CI is green on this head. Same-actor last-push (corvid-agent), so I cannot approve — needs a human or other reviewer to merge.

@0xLeif 0xLeif left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 on the current head: authenticated archive snapshots are present while the repository still declares SpecSync 5.0.1, so the archive cannot be reproduced by the declared tool. Regenerate the archive with matching lifecycle evidence before merge.

@0xLeif 0xLeif left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The archive move itself is correct and lossless, but the commit carries one transient lifecycle file that must not be tracked, and the green Trust check was produced by the pre-#24 gate, so it is not evidence under the pins main enforces today.

Blocking

1. .specsync/change.lock is committed as a new tracked file (0 bytes)

diff --git a/.specsync/change.lock b/.specsync/change.lock
new file mode 100644
index 0000000..e69de29

e69de29 is the empty blob, and I confirmed the size is 0 with git cat-file -s. This file is a transient lifecycle lock, not archive evidence, and upstream SpecSync says so explicitly:

  • specsync init generates the .specsync/.gitignore contents in src/commands/init.rs (CorvidLabs/spec-sync, default branch), and that generated list is backup-3x/, config.local.toml, hashes.json, change.lock, change-transaction.json.
  • spec-sync's own repository does not track .specsync/change.lock. I queried repos/CorvidLabs/spec-sync/contents/.specsync/change.lock and got a 404.
  • This repo's .specsync/.gitignore was written by an older version and only contains backup-3x/, config.local.toml, hashes.json, which is why the lock slipped through.
  • The repo's own governance says the same thing. .specsync/sdd.json lists .specsync/change.lock under ignored_paths, and the acceptance criterion recorded in CHG-0003 reads "transient lifecycle files remain excluded".

Once this is tracked on main, every local specsync lifecycle command that takes the lock dirties the working tree and shows up as a spurious diff, and a fresh clone starts with a lock artifact in place. It is also unrelated to the stated scope of this PR.

Requested fix: git rm --cached .specsync/change.lock on the branch, and append change.lock and change-transaction.json to .specsync/.gitignore so it cannot recur.

2. The passing Trust check is stale evidence, not current-gate evidence

gh pr checks 23 is all green, but I checked what actually ran. Run 33843838989 has head_sha 206864125af514d585417ec3fcd75df65581e8d6, which is this branch's only commit, so the workflow used the branch's own .github/workflows/trust.yml. On this branch that file still reads:

uses: CorvidLabs/spec-sync@59bbfa766c6cce01ab815ab47db195b0629cc014 # v5.0.1
uses: CorvidLabs/trust@9d32b5786d2e9e4d39fc581c0091c721ee3d4226 # v1.0.0

The branch base is 4d0cc51, and main has since moved to b42c8ac ("Update: pin Trust 1.2.0 and SpecSync 6.0.0", #24), which replaced those with spec-sync@3c2ed4972c8c53ae02ab5dd5775beccd6da3eeb8 # v6.0.0 and trust@fcc889f54d8b4892a81af463c5a0250e2be66fc5 # v1.2.0. So the green lane validated this archive layout under SpecSync 5.0.1 and Trust 1.0.0, not under the 6.0.0 / 1.2.0 lifecycle that now guards main.

To be clear about what this is not: the PR does not touch trust.yml, so it does not regress the pins. I test-merged origin/cos/archive-specsync-accepted into origin/main locally and the merge is clean, with main's 1.2.0 / 6.0.0 workflow surviving intact. The ask is just to rebase onto b42c8ac and let the current gate re-run before merge, since evidence hygiene is the entire point of this change.

What I verified and found clean

  • The archive layout is genuine tool output, not hand-rolled. A code search over CorvidLabs/spec-sync shows the same shape in its own repository: .specsync/archive/changes/<YYYY-MM-DD>-<CHG-id>/ holding accepted-state.json next to a rewritten state.json, plus the untouched artifact files.
  • Nothing was lost in the move. For all five records I diffed the archived accepted-state.json against the new state.json with sorted-key JSON normalization. The only differences anywhere are "state": "accepted" becoming "archived" and a bumped updated_at. approvals.json and verification.json are 100 percent similarity renames, so the approval chain, the reopening records with their superseded approvals, and the verification digests all survive byte for byte.
  • The change.md front matter edits match. Each of the five is exactly -state: accepted / +state: archived, consistent with its state.json.
  • CHG-0002 having fewer artifacts is correct, not a dropped file. Its selected_artifacts is ["context", "docs"], and git ls-tree origin/main -- .specsync/changes/CHG-0002-... confirms that directory only ever held approvals.json, change.md, context.md, docs.md, state.json, verification.json.
  • Timestamps are self-consistent. The new updated_at values run 1788502701 to 1788502716, which is 2026-09-04T06:18:21Z to 06:18:36Z, matching the 2026-09-04 directory prefix and the 06:18:40Z PR creation time. This was generated seconds before the push rather than edited by hand.
  • No dangling references. grep -rn for specsync/changes and CHG-000 across the whole tree outside .specsync/ returns nothing, so no workflow, spec, or doc points at the old paths.
  • The PR's own test plan holds. .specsync/changes/ is gone entirely from the branch tree and all five records are present under .specsync/archive/changes/.
  • .specsync/version correctly stays at 5.0.1. That file is a layout schema stamp, not a binary selector, and specsync init on the 6.0.0 binary writes 5.0.0. Nobody should "fix" it as part of the rebase.

Advisory

  • .specsync/sdd.json lists .specsync/changes/, .specsync/change.lock, and .specsync/hashes.json under ignored_paths, but says nothing about .specsync/archive/. Today that is harmless, because the archive path is in neither ignored_paths nor meaningful_paths, so it does not pull in a change-record requirement. If the intent is that archived evidence is never itself subject to change coverage, adding .specsync/archive/ to ignored_paths would state that explicitly instead of relying on the absence of a rule.
  • Once .specsync/changes/ is empty the directory disappears from the tree. That is fine for git, but worth a sanity check on the first specsync change new after this lands, to confirm the tooling recreates it rather than erroring on a missing parent.

Risk: low. This is evidence relocation with no product code touched, no CI gate softened, no dependency or action pin moved, and no permission widened. Fix finding 1, rebase for finding 2, and it is ready.

@0xLeif

0xLeif commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Diagnosis: nothing is red. The blocker is branch protection plus a stale green.

Reported state, verified: mergeStateStatus: BEHIND, mergeable: MERGEABLE. cos/archive-specsync-accepted is 1 ahead / 1 behind main, no file conflicts. main protection has required_status_checks.strict = true ("require branches to be up to date"), required context trust. That is what holds the merge, not a failing check.

The green on this PR does not describe the gate that will decide it

The 5 passing checks ran at head 2068641, created 2026-09-04T06:18:42Z. At that commit .github/workflows/trust.yml pinned:

uses: CorvidLabs/spec-sync@59bbfa766c6cce01ab815ab47db195b0629cc014 # v5.0.1
  version: "5.0.1"
uses: CorvidLabs/trust@9d32b5786d2e9e4d39fc581c0091c721ee3d4226 # v1.0.0

main moved on 2026-09-10 with #24 (b42c8ac) to spec-sync@3c2ed497 # v6.0.0 (version: "6.0.0") and trust@fcc889f5 # v1.2.0. So this PR has never been evaluated under Trust 1.2.0 / SpecSync 6.0.0. b42c8ac touches only trust.yml and 5 spec files, none of which this PR touches, hence the clean-but-behind state.

What I verified locally with the real SpecSync 6.0.0 binary

Using specsync-macos-aarch64 from the CorvidLabs/spec-sync v6.0.0 release, against this branch updated onto main (tested three ways: merge, rebase, and the squash result that would actually land, since squash is the only merge method enabled here):

$ specsync check --strict --force --require-coverage 100   # the `specsync` task in fledge.toml [lanes.trust]
10 specs checked: 10 passed, 0 warning(s), 0 failed
File coverage: 16/16 (100%)
LOC coverage:  2185/2185 (100%)

$ specsync change audit
Auditing active changes (0)... audit passed (0 active)

All five archived packages authenticate under 6.0.0 (specsync change show <id> returns State: archived, Next: no further action). The SpecSync 5.0.1-era archive layout, including the accepted-state.json snapshots, is read correctly by 6.0.0 as a legacy workflow-v1 archive. After the update the tree carries trust@fcc889f5 v1.2.0 with an explicit version: "6.0.0", and .specsync/version correctly stays 5.0.1 (layout stamp, not a binary selector). No gate, pin or threshold changes.

So: update the branch and it should go green.

Do not close and recreate this. It is no longer reproducible from main

Worth knowing, because main is currently in a broken lifecycle state that only this PR clears. On main tip b42c8ac today:

$ specsync change audit
Auditing active changes (5)...
error: CHG-0001-adopt-trust-1-and-specsync-5: accepted change verification is stale for current
  delivery inputs: exact-only delivery input `.github/workflows/trust.yml` changed after acceptance
  and requires an audited reopen; run `specsync change reopen CHG-0001-adopt-trust-1-and-specsync-5`
error: CHG-0002-assign-stable-requirement-ids: ... exact-only delivery input
  `specs/loader-swift/loader-swift.spec.md` changed after acceptance ...
error: CHG-0004-... and CHG-0005-...: ... `.github/workflows/trust.yml` ...

and the archive operation itself now refuses:

$ specsync change archive CHG-0001-adopt-trust-1-and-specsync-5
error: exact-only delivery input `.github/workflows/trust.yml` changed after acceptance and
requires an audited reopen

Cause: #24 edited .github/workflows/trust.yml (a delivery input of CHG-0001/0004/0005) and specs/loader-swift/loader-swift.spec.md (a delivery input of CHG-0002) while those changes were still accepted but unarchived. SpecSync 6.0.0 names this rule itself in change ship-status: merging first "orphans its verification evidence AND blocks every earlier accepted change sharing a delivery input from archiving, until this one is finalized or those are reopened".

This PR's archive commit predates #24, so it still carries evidence matching the tree at acceptance time, and it authenticates. Recreating the archive from main instead would require specsync change reopen on all four stale changes first, with actor and reason. Updating and merging this branch avoids that.

Concrete action

  1. Click Update branch (or git fetch origin && git merge origin/main on cos/archive-specsync-accepted). Conflict free, verified.
  2. Let trust re-run under Trust 1.2.0 / SpecSync 6.0.0. That run is the one that counts; the current green is from the 1.0.0 / 5.0.1 gate.

One non-blocking nit, worth folding into that same push

.specsync/change.lock is added here as a new empty tracked file (e69de29). It is a transient local lock SpecSync writes during ordinary local runs; I hit it during this investigation, where a stray untracked .specsync/change.lock aborted a git checkout. SpecSync 6.0.0's own specsync init now ignores it:

# .specsync/.gitignore as written by specsync 6.0.0 init
backup-3x/
config.local.toml
hashes.json
change.lock
change-transaction.json

This repo's .specsync/.gitignore is the 3-line 5.0.1-era version, ending at line 3 (hashes.json). Suggested fix, append:

change.lock
change-transaction.json

and drop the file from the commit with git rm --cached .specsync/change.lock. It is listed under ignored_paths in .specsync/sdd.json, so it does not affect coverage and will not fail the gate. It is just tracked churn that will keep dirtying working trees.

Not requesting changes; nothing here blocks. Everything above was read-only verification against the pinned toolchain.

@corvid-agent

Copy link
Copy Markdown
Author

CoS follow-up

Applied the concrete asks from the diagnosis:

  1. Updated branch onto main (b42c8ac / Trust 1.2.0 + SpecSync 6.0.0 pins) — merge was clean.
  2. Dropped tracked .specsync/change.lock and appended change.lock + change-transaction.json to .specsync/.gitignore (SpecSync 6.0.0 init shape).

Tip is now 50f4005. Waiting on the fresh trust run under the current gate before any merge call. Not merging from this pass.

@corvid-agent corvid-agent left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review (corvid-agent, same-actor → comment only)

Head: 50f4005af0e3 (prior comment was on 206864125af5) — trust + CodeQL green.

SpecSync lifecycle looks right on this tip: accepted change packages moved under .specsync/archive/changes/… with state: archived, accepted-state.json preserved, and change.lock / change-transaction.json ignored.

Merge guidance: use a merge commit (not squash) so archive history stays attributable; do not leave active .specsync/changes/CHG-* behind on main after merge.

Same-actor: comment only.

This branch has not been deployed

No deployments
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.

2 participants