Skip to content

feat(capture): --pin flag writes installed versions into the manifest#145

Merged
Artexis10 merged 2 commits into
mainfrom
feat/capture-pin
Jul 10, 2026
Merged

feat(capture): --pin flag writes installed versions into the manifest#145
Artexis10 merged 2 commits into
mainfrom
feat/capture-pin

Conversation

@Artexis10

Copy link
Copy Markdown
Owner

Implements OpenSpec change capture-pin — wedge blocker #1 from the 2026-07 market brief. Capture already parsed installed winget versions during its display-name pass and discarded them; the entire downstream stack (manifest App.Version, winget install --version, apply --repin) was shipped but dormant. This activates it.

What

  • capture --pin (opt-in): writes each app's installed version into the emitted manifest's per-app version field. Best-effort — a missing version omits the field; a failed winget list degrades to no versions; capture never fails over version data. Without --pin, fresh-capture output is byte-identical to before.
  • One snapshot pass, two maps: the seam swap (getDisplayNameMapFnlistInstalledFn = snapshot.TakeSnapshot) derives display names and versions from the single existing winget list — no new winget invocation, no extra lock-contention exposure.
  • --update merge fix: existing entries' version/driver fields were silently dropped by the merge (non-destructive-defaults violation; the realizer path already preserved them). Now preserved; under --update --pin a pin is refreshed only on a non-empty installed-version lookup — skew never blanks a declared pin.
  • Sanitize copies version/driver through (realizer parity); sanitized shared manifests can be reproducible.
  • Capability advert: --pin in commands.capture.flags + mirrored in docs/contracts/cli-json-contract.md (additive, no schema bump).
  • Realizer (Nix/brew) path: --pin accepted as a no-op — versions were already recorded unconditionally there.

Review

Dual-pass review (ContractGuard + code review, both Opus): 0 blockers, 0 majors; all minors addressed in this diff (realizer no-op test coverage, key-sensitive never-blank test, empty-version-map warning under --pin, spec wording scoped to fresh capture, truncated-Id caveat documented in design.md).

Tests

11 new hermetic tests (pin emission, skew/error degradation, sanitize, update preserve/refresh/never-blank/new-app, realizer no-op, capabilities advert). go test ./... green; npm run openspec:validate 80/80.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WjiYqx7LVvR2Yr883PMKYr

Artexis10 and others added 2 commits July 10, 2026 15:14
OpenSpec change: capture --pin writes installed winget versions into
the emitted manifest's per-app version field; capture --update stops
dropping declared version/driver through the merge. Extends the
windows-version-capture-pinning capability.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WjiYqx7LVvR2Yr883PMKYr
One winget list pass now feeds both the display-name map and a version
map (seam swap: getDisplayNameMapFn -> listInstalledFn); under --pin the
conversion loop records each app's installed version, best-effort and
never fatal. The --update merge stops silently dropping declared
version/driver fields and, under --pin, refreshes a pin only on a
non-empty lookup so skew never blanks declared state. Sanitize copies
version/driver through (realizer-path parity). --pin advertised in
capabilities and the CLI JSON contract.

Implements openspec/changes/capture-pin.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WjiYqx7LVvR2Yr883PMKYr
@Artexis10 Artexis10 merged commit 947b733 into main Jul 10, 2026
3 checks passed
@Artexis10 Artexis10 deleted the feat/capture-pin 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