Skip to content

feat: artifact versioning, draft+confirm auto-refresh, retro roll-up & command contract lint - #46

Merged
MCKRUZ merged 2 commits into
MCKRUZ:masterfrom
splashthree:artifact-auto-versioning
Aug 7, 2026
Merged

feat: artifact versioning, draft+confirm auto-refresh, retro roll-up & command contract lint#46
MCKRUZ merged 2 commits into
MCKRUZ:masterfrom
splashthree:artifact-auto-versioning

Conversation

@splashthree

Copy link
Copy Markdown
Contributor

What this adds

Four additive, advisory layers on top of the 1.3.0 artifact update & audit layer. Protected core is byte-for-byte unchanged; audit_artifacts.py's existing record/impact/report output is byte-identical (enforced by invariant tests); everything exits 0 on every path.

1. Content versioning (/sdlc-version)

version {list,show,diff,rollback,gc} folded into audit_artifacts.py. Version identity is derived from the change-ledger's existing 16-hex SHA-256 hashes via one new pure module (version_model.py) — the content-addressed object store (.sdlc/versions/objects/<xx>/<16hex>, gitignored) is just those hashes rehydrated to bytes, so there is no second index to drift. Rollback is preview → named-human confirm (--actor + echoed diffhash, --ack-signoff for signed-off artifacts), append-only ("restored from vX"), torn-write-safe with idempotent recovery. gc is cross-ledger refcounted and protects anything whose sign-off it can't prove.

2. Draft+confirm auto-refresh (/sdlc-refresh)

refresh {detect,scan,draft,apply,reject,status} — reverse propagation: a merged spec's shipped reality flows back up into requirements.md/epics.md/feature-brief.md/business-rules.md. Review-first and divergence-aware (a faithful spec drafts nothing without --draft); the discipline agent edits only a .proposed; a named human echoes the reviewed diffhash to apply (the One Rule); the refresh lands as a rollback-able refreshed version attributed via a source_spec rider key (artifact_model.py unchanged).

3. Cross-ledger retro roll-up (/sdlc-retro)

retro_report.py — read-only report across the ledgers for retro input: recurring findings (permanent-check candidates), repeat-stale artifacts, the refresh funnel per spec and per stem (the tuning signal for the divergence heuristic), and a disposition-debt rollup naming each source ledger. Same discipline as the scorecard: "no data" over fabricated zeros, patterns keyed by category/artifact/stem and never by actor, refuses activity metrics.

4. Command contract lint

scripts/tests/test_command_contracts.py — the static half of a command-prose safety harness: extracts every uv run … scripts/<name>.py invocation from fenced blocks in commands/*.md and validates script existence, subcommand chains, and every --flag against live --help (cached subprocesses), plus agent-name and references//templates/ cross-references. Conservative (ambiguous → skipped, never a false violation), with self-tests proving each detection class fires. It found zero drift in the existing 25 command docs and already caught one malformed invocation during this PR's own authoring.

1.3.0 integration

  • Rebased on master (clean; the only overlapping file was audit_artifacts.py, where the _glyph fix and this PR's additions touch disjoint regions).
  • All new output routed through the _glyph() Windows-console fallback introduced in 1.3.0 — verified under a forced cp1252 stdout.
  • The three new commands registered in docs/commands.md; the count-word vocabulary in test_registry_docs_consistency.py extended (Thirteen–Eighteen) since the additional-commands table outgrew "Twelve".

Also included

  • Multi-machine honesty: every "content not captured" message now explains why (local, gitignored store — fresh clone/CI, gc prune, or store fault) and what to do.
  • Docs for endpoint-only capture semantics ("What a version is (and isn't)") and a team-portable .gitignore override.

Testing

  • 807 passed, 1 skipped on the rebased tree (~192 new tests).
  • New invariant tests assert: protected core untouched, report/impact JSON byte-identical with the version store deleted, no state.yaml writes from the new verbs, the ledger stays its own JSONL with no gate_results rows, and the .gitignore entries exist.
  • See references/artifact-versioning.md for the design (R1–R6, canonical mutate order, gc policy, deletability caveat).

🤖 Generated with Claude Code

splashthree and others added 2 commits August 7, 2026 07:01
…& command contract lint

Four additive, advisory layers — protected core byte-for-byte unchanged, exit 0
on every path, existing record/impact/report output byte-identical:

- Content versioning: version {list,show,diff,rollback,gc} folded into
  audit_artifacts.py, keyed to the change-ledger's existing 16-hex hashes via
  one pure module (version_model.py) — the gitignored object store is the
  ledger rehydrated to bytes, no second index. Rollback is preview ->
  named-human confirm, append-only, torn-write-safe.
- Draft+confirm auto-refresh: refresh {detect,scan,draft,apply,reject,status}
  back-propagates a merged spec's shipped reality into pre-Build artifacts.
  Review-first/divergence-aware; agent edits only a .proposed; a named human
  echoes the reviewed diffhash to apply (One Rule); lands as a rollback-able
  refreshed version attributed via a source_spec rider key.
- Cross-ledger retro roll-up: retro_report.py + /sdlc-retro — recurring
  findings, repeat-stale artifacts, the refresh funnel (divergence-heuristic
  tuning signal), disposition-debt rollup. Patterns, not people; no data over
  fabricated zeros.
- Command contract lint: test_command_contracts.py validates every command
  doc's script invocations against live --help, plus agent/file cross-refs,
  with self-tests proving each detection class fires.

Plus multi-machine honesty on every "content not captured" path, docs for
endpoint-only capture semantics, and 1.3.0 integration: the three new
commands registered in docs/commands.md (count-word vocabulary extended in
its guard test) and all new output routed through the _glyph() Windows-
console fallback. 807 tests passing on the rebased tree.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The versioning suite asserts on exact file bytes — `version show` returns what
the store captured, byte for byte. But the fixture helpers wrote their corpus
in text mode, which expands newlines to CRLF on Windows. So the assertions
compared LF literals against CRLF content and failed on Windows while passing
on Linux CI.

The product code is not at fault: every content path in audit_artifacts.py
already reads and writes bytes. Only the fixtures were platform-dependent.
Routing every artifact-content write through the _write helper, which now
pins LF, makes the corpus byte-identical on both platforms.

Also adds a windows-latest CI job. The plugin is authored on Windows and
ships PowerShell hooks, but CI ran only on Linux — this is the second
Windows-only defect to reach master unseen, after the cp1252 console fault
fixed in 1.3.0. It is a separate job rather than a matrix on `test` so the
existing required check name is unchanged, and it keeps the runner's default
CRLF checkout because that mirrors the machine it exists to protect.

Verified on Windows: 801 passed, 7 skipped (was 799 passed, 2 failed).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@MCKRUZ
MCKRUZ merged commit ca8a4b5 into MCKRUZ:master Aug 7, 2026
4 checks passed
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