Seal hash simplification
Simplify the contract seal system from git-commit-based verification to content-hash-based verification. This eliminates the post-commit `.saves.json` fixup that makes the file permanently dirty and blocks branch switches on every pipeline run.
verdict PASSscore 13 / 13findings 4 (0 risk · 0 debt · 4 obs)duration 29mrejection cycles 0shipped Apr 26, 2026surface cli
Pipeline timeline
Intent to proven code in 29m across Think, Plan, Build, and Verify.
Think7m
Plan7m
Build17m
Verify6m
Assertion ledger
13 claims, each independently verified. Showing 8 — show all →
| ID | Says | Matcher | |
|---|---|---|---|
| A001 | An unchanged contract is verified as intact | verified | ok |
| A002 | A modified contract is detected as tampered | verified | ok |
| A003 | A tampered contract blocks saving the verify report | verified | ok |
| A004 | Tag search finds tests changed since the feature branch diverged | verified | ok |
| A005 | Tag search falls back to global when merge-base is unavailable | verified | ok |
| A006 | A missing saves file makes the seal unverifiable | verified | ok |
| A007 | New proof chain entries record no commit hash | verified | ok |
| A008 | The commit field is no longer written to saves metadata | verified | ok |
Findings 4 total
obspackages/cli/tests/commands/artifact.test.ts→ closed
Stale commit assertion passes trivially: `artifact.test.ts:1233,1242` — the "appends to existing .saves.json" test saves `scope.commit` and later asserts it's unchanged. Since `writeSaveMetadata` no longer writes `commit`, both values are `undefined`, so `expect(undefined).toBe(undefined)` passes without testing anything. The test still verifies scope entry survives a spec save via `toBeDefined()` at line 1239, but the commit-specific line is dead weight. Next cycle touching this test should remove lines 1233 and 1242.
obspackages/cli/src/commands/verify.ts→ closed
`execSync` import retained but usage reduced: `verify.ts:17` — `execSync` is still imported and used for the merge-base/diff commands (lines 150-157). The old `git show` call was the fragile one (required exact commit hash). The remaining `execSync` calls use merge-base, which is robust. Not a problem — just noting that the file still has a child-process dependency for the scoped search path.
obsana.json→ closed
A005 fallback test triggers via missing ana.json, not missing branch: `verify.test.ts:548-590` — the fallback test causes `readArtifactBranch` to throw by omitting `ana.json` entirely. This is a valid trigger but tests a different failure mode than "artifact branch exists but merge-base fails" (e.g., on a repo with no shared history). Both paths hit the same catch block, so the behavioral coverage is equivalent. A future cycle could add a test where `ana.json` exists but `git merge-base` fails (orphan branches, shallow clones).
obspackages/cli/tests/commands/pr.test.ts→ closed
pr.test.ts fixture retains old `commit` fields: `pr.test.ts:278` — the fixture has `commit: 'def456'` on the contract entry. This represents old-format data and is harmless (JSON.parse ignores extra properties), but it means the pr.test.ts fixture doesn't reflect what current code produces. If a future test asserts on the shape of `.saves.json` entries, this fixture would give a false impression. Low priority.
Integrity seal
scopesha256:c78c7724c4754...
contractsha256:10f28abd1a9f7...
plansha256:e9f97d3db2537...
specsha256:4017622839f92...
build-reportsha256:6d369a73eb8dd...
verify-reportsha256:21a60d89904c6...
audit cmd$ ana proof audit seal-hash-simplification → all hashes match