ASDD Wave 3: apply path, closure gate, fork-vs-hook ADR#7
Merged
Conversation
Finalize the fork-vs-hook decision for ASDD Phase 1+. Adopt option (a): hook-layer only as the v1 strategy. Defer option (c) (upstream backend knob) until adoption justifies the maintenance commitment. Treat option (b) (fork) as a last resort. Adds: - docs/design/adr/0001-spec-kit-integration-strategy.md - Decisions section in docs/design/asdd-whitepaper.md cross-linking the ADR Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds `gemba spec close-check` plus the underlying `internal/spec/hooks` package. The gate walks every Story anchor in spec.md, looks up its mapped bd bead via the lockfile, queries bd status through reconcile.BeadLister, and refuses the close when any mapped story is neither bd-closed nor lockfile-resolved=wontdo. - Backwards-compatible Mapping.Resolution string field (omitempty); legacy lockfiles continue to load (covered by TestLoad_Legacy...). - Force=true with non-empty Reason emits a spec.close.gate.bypass slog audit event and returns Allow=true. - scripts/bd-pre-close.sh wraps the CLI for operators to wire into bd's pre-close hook directory; doc block at the top of the script explains the symlink-based install path. Tests: 386 pass. go build clean.
Adds internal/spec/apply/ — the executor that turns a reconcile.Plan into real bd mutations under an X-GEMBA-Confirm nonce gate. Refuses stale-nonce plans (ErrNonceStale), takes a pre-apply snapshot when requested, and rolls back prior successes on any mid-apply failure. The BDMutator emulates header propagation via a (nonce, anchor, kind) sidecar log (.gemba/.apply.log.jsonl) so the same plan can be safely replayed after a partial success — already-applied tuples are skipped. Wires `gemba spec apply <spec.md>` into the CLI with --dry-run, --prune, --lockfile, --bd-stub, --force-nonce, --no-snapshot, --apply-log, --json. Lockfile save is deferred until every op succeeds (atomic at the spec- reconcile boundary). Audit hook (spec.apply.start/op/complete/failed) emits via a narrow Auditor interface; failures there never block apply. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Wave 3 of the ASDD core. Stacked on top of #6 (wave 2). Three beads closed.
internal/spec/apply/+gemba spec apply). Idempotency via.gemba/.apply.log.jsonlkeyed on(nonce, anchor, kind). Mid-apply failure triggersRollback: reverses creates by closing withrollback:note, reverts updates from capturedFieldChange.From. Lockfile save only on success path — atomic at spec-reconcile boundary. Refuses ifPlan.NonceStaleunless--force-nonce.internal/spec/hooks/+gemba spec close-check+scripts/bd-pre-close.sh). Refuses epic close if any mapped story bead is still open and not markedResolution: wontdoin the lockfile.--force --reason "..."bypass emitsspec.close.gate.bypassvia slog. Lockfile gains aMapping.Resolutionfield (backward-compatible — old lockfiles parse fine).Test plan
go build ./...cleango test ./internal/spec/... ./internal/cli/...— 395 tests pass in 16 packagesgemba spec apply --dry-runshows planned ops without mutatinggemba spec applyreplayed with same nonce is a no-op (idempotency)gemba spec close-check --epic <id>refuses when stories openscripts/bd-pre-close.shsymlinked into a bd hook dir gates realbd closeMerge order
Wave 2 (#6) must merge first — this PR's base is
feat/asdd-wave-2.Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com