Skip to content

feat(rebuild): one-command fresh-machine flow from a capture bundle or manifest#146

Merged
Artexis10 merged 3 commits into
mainfrom
feat/endstate-rebuild
Jul 10, 2026
Merged

feat(rebuild): one-command fresh-machine flow from a capture bundle or manifest#146
Artexis10 merged 3 commits into
mainfrom
feat/endstate-rebuild

Conversation

@Artexis10

Copy link
Copy Markdown
Owner

Implements OpenSpec change endstate-rebuild — wedge blocker #2 from the 2026-07 market brief. The capture zip the engine produces was not consumable by the Go engine at all: the "apply from zip" behavior in openspec/specs/capture-bundle-zip.md was only ever implemented in the retired PowerShell engine, and bundle.ExtractBundle/IsBundle were dead code. This wires them into a single command.

What

  • endstate rebuild --from <bundle.zip|manifest.jsonc> — composes the existing plan → install → restore → verify pipeline in one command. A .zip extracts to a temp dir whose lifetime spans the full pipeline (deferred cleanup covers every return path); a bare .jsonc runs the same pipeline without extraction.
  • Zero apply-side path rewriting needed — the bundle is already self-describing: CreateBundle rewrites restore sources to ./configs/<module>/<leaf> at capture time and apply resolves them against the extraction dir. The resolution chain is now documented in design.md and locked by a capture→rebuild round-trip test (restored bytes == captured bytes).
  • Safety posture — restore is ON by default (that's rebuild's purpose); a live run requires explicit --confirm, refused before any mutation with the new CONFIRMATION_REQUIRED error code. --dry-run / --no-restore need no confirmation. A MODIFIED delta for restore-opt-in reconciles Core Invariant chore(main): release 1.6.0 #6: consent stays explicit, command-line-only, never defaulted or supplied by bundle content.
  • Verify failures are data — success envelope, exit 0 (precedent: schedule run); only infrastructure/input errors flip success.
  • Capability advertcommands.rebuild with its flag set (the GUI's one-click-rebuild gate); URL input rejected NOT_SUPPORTED (v0 is local-file only).
  • Contract docs (cli-json-contract rebuild section + error code, event-contract composed-streams note), README fresh-machine quickstart + commands-table row.

Review

Dual-pass review (ContractGuard + code review, both Opus). ContractGuard's MAJOR — restore-by-default vs the governed restore-opt-in spec with no reconciling delta — is fixed via the MODIFIED delta + design rationale. All MINORs addressed: stale flat capture-bundle-zip spec updated to name rebuild as the zip path, double-verification documented as accepted v0 cost, archive-ordering dependency noted, refusal-precedes-extraction now proven against a real zip, and a post-extraction manifest-parse-error lane locks temp cleanup on the envelope-error return path.

Tests

12 hermetic tests: round-trip restore-content match, bare-manifest lane, confirmation gate (zero installs + no extraction), dry-run, no-restore, input-validation quartet, temp cleanup ×3 (success / install error / parse-error envelope return), event phase-first/summary-last, capabilities advert, verify-failure-is-data. Full suite green; npm run openspec:validate passes.

Note for merge sequencing: independent of #145 (capture --pin) — branched off main; rebuild consumes pinned manifests when present but does not require them. Archive capture-bundle-zip before archiving this change (MODIFIED-delta ordering).

🤖 Generated with Claude Code

https://claude.ai/code/session_01WjiYqx7LVvR2Yr883PMKYr

Artexis10 and others added 3 commits July 10, 2026 15:38
Author the OpenSpec change for `endstate rebuild --from
<bundle.zip|manifest.jsonc>`: proposal, design, the endstate-rebuild delta
spec, a capture-bundle-zip MODIFIED delta, and tasks.

Documents the restore-path resolution chain (payload -> configs rewriting at
capture, ManifestDir-relative source resolution at apply), the
refuse-before-mutation confirmation gate (new CONFIRMATION_REQUIRED code),
temp-dir lifetime, verify-as-data semantics, and URL input as a v0 non-goal.
The MODIFIED delta reframes capture-bundle-zip's "Apply from zip" requirement
so the Go engine's supported zip-consumption path is `rebuild`.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WjiYqx7LVvR2Yr883PMKYr
Add `endstate rebuild --from <bundle.zip|manifest.jsonc>` composing the
existing plan -> install -> restore -> verify pipeline into one command, and
wire the previously-dead bundle extraction (bundle.ExtractBundle/IsBundle)
into production so a capture zip is finally consumable by the Go engine
(fulfilling the PowerShell-only "apply from zip" behavior in
openspec/specs/capture-bundle-zip.md).

- RunRebuild (new commands/rebuild.go): validate --from (empty ->
  MANIFEST_VALIDATION_ERROR; URL -> NOT_SUPPORTED; missing -> MANIFEST_NOT_FOUND;
  bad zip -> MANIFEST_PARSE_ERROR); confirmation gate before any mutation;
  extract bundle with deferred temp cleanup spanning the whole pipeline;
  delegate to RunApply then RunVerify. Bundle restore sources resolve from
  configs/<module>/ inside the extraction dir with zero apply-side rewriting.
- Restore is on by default; a live run (not --dry-run/--no-restore) requires
  --confirm, refused via the new CONFIRMATION_REQUIRED code. Verify failures
  are data: success envelope, exit 0.
- CLI wiring (main.go: --from/--no-restore parse, usage, dispatch), capability
  advert (capabilities.go), and docs (cli-json-contract rebuild section +
  CONFIRMATION_REQUIRED; event-contract composition note; readme quickstart +
  command row).
- Hermetic tests (rebuild_test.go): capture->rebuild round-trip, bare manifest,
  confirmation gate, dry-run/no-restore lanes, input validation, temp cleanup
  (success + mid-pipeline error), event ordering, verify-failure-is-data,
  capabilities advert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WjiYqx7LVvR2Yr883PMKYr
Dual-review follow-ups: MODIFIED delta for restore-opt-in naming
rebuild's --confirm as the consent primitive (Core Invariant #6 kept:
consent is explicit, command-line-only, refused before mutation);
flat capture-bundle-zip spec updated to name rebuild as the Go
engine's zip-consumption path; design notes for the accepted double
verification and the capture-bundle-zip archive-ordering dependency;
event-contract wording caveats the empty-stream early-error lane;
restore field documented as posture, not execution. Tests: no-confirm
refusal now proven against a zip (no extraction dir created) and a
post-extraction manifest-parse-error lane locks temp cleanup on the
envelope-error return path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WjiYqx7LVvR2Yr883PMKYr
@Artexis10 Artexis10 merged commit 9769869 into main Jul 10, 2026
3 checks passed
@Artexis10 Artexis10 deleted the feat/endstate-rebuild branch July 10, 2026 19:37
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