diff --git a/BEARING.md b/BEARING.md index b42c8c2..08a4805 100644 --- a/BEARING.md +++ b/BEARING.md @@ -14,13 +14,14 @@ timeline ## Current State -`v6.5.3` shipped on `2026-07-19`. Application asset, bundle, page, cache, +`v6.5.4` shipped on `2026-07-26`. Application asset, bundle, page, cache, expiry, witness, and repository-diagnostics APIs sit above mutable root sets and the low-level CAS pipeline. Direct bundle-reference reads and bounded immutable metadata/page reuse, bounded Git object sessions, page batches, and -deterministic resource closure are published. npm plus GitHub Releases are the -active publication surfaces. JSR validation is healthy, but JSR publication -remains outside the release workflow. +deterministic resource closure are published. The versioned v6.5.5 candidate +makes internal commits independent of ambient Git identity. npm plus GitHub +Releases are the active publication surfaces. JSR validation is healthy, but +JSR publication remains outside the release workflow. What exists now: @@ -77,10 +78,13 @@ What exists now: still retires `mktree` after a bounded bulk write because Git's quick lookup cannot discover a pack created after that process prepared its object database. -- **Batched workspace page retention.** The v6.5.4 candidate adds +- **Batched workspace page retention.** v6.5.4 adds `workspace.pages.putBatch()` so one bounded ordered page group is written and retained under one exact workspace generation instead of rewriting a growing root set for every page. +- **Self-contained internal commit identity.** The v6.5.5 candidate supplies a + stable git-cas author and committer for root-set, publication, and vault + commits without mutating repository or global Git configuration. - **Migration script.** `scripts/migrate-encryption.js` upgrades legacy v1/v2 manifests to the current scheme identifiers. @@ -136,15 +140,15 @@ These were the active tensions from the previous bearing. All resolved. ## Next Horizon -With v6.5.3 shipped and the versioned v6.5.4 release candidate being prepared, +With v6.5.4 shipped and the versioned v6.5.5 release candidate being prepared, active work is tracked in GitHub Issues and Milestones. Repo docs hold design and evidence records, not the active queue. The latest landed design is -[0054-batched-page-retention](./docs/design/0054-batched-page-retention/batched-page-retention.md). +[0055-internal-commit-identity](./docs/design/0055-internal-commit-identity/internal-commit-identity.md). Its release evidence is attached to -[#99](https://github.com/git-stunts/git-cas/issues/99) and the -[`v6.5.4` milestone](https://github.com/git-stunts/git-cas/milestone/14). Tag +[#102](https://github.com/git-stunts/git-cas/issues/102) and the +[`v6.5.5` milestone](https://github.com/git-stunts/git-cas/milestone/15). Tag and publication evidence remain pending; no later design is selected here. The broader horizon remains: diff --git a/CHANGELOG.md b/CHANGELOG.md index 67032d4..8725362 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [6.5.5] — 2026-07-26 + ### Fixed - **Self-contained internal Git commits** - root-set, publication, and vault diff --git a/README.md b/README.md index 71c27e0..9af316c 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Unlike traditional LFS which moves files to external servers, `git-cas` treats t Existing v5 users should read [UPGRADING.md](./UPGRADING.md) and run `npm run upgrade` in dry-run mode before restoring old encrypted vault entries. For the release overview, see the -[v6.5.4 Release Notes](./docs/releases/v6.5.4.md). +[v6.5.5 Release Notes](./docs/releases/v6.5.5.md). ### 1. CLI Usage @@ -221,6 +221,8 @@ All three runtimes are tested in CI on every push. The hexagonal architecture is persistent Git object sessions across compatible immutable writes. - **[v6.5.4 Release Notes](./docs/releases/v6.5.4.md)**: Ordered page batches retained under one exact staging-workspace generation. +- **[v6.5.5 Release Notes](./docs/releases/v6.5.5.md)**: Self-contained + identity for git-cas-owned commits in unconfigured bare repositories. - **[Upgrading](./UPGRADING.md)**: Migration guide for v5 → v6. - **[Changelog](./CHANGELOG.md)**: Version history and migration notes. diff --git a/ROADMAP.md b/ROADMAP.md index 63e417e..075b68d 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -42,6 +42,7 @@ GitHub wins and this file should be corrected. | [`v6.5.2`](https://github.com/git-stunts/git-cas/milestone/12) | Persistent bounded Git object sessions | [#90](https://github.com/git-stunts/git-cas/issues/90) | | [`v6.5.3`](https://github.com/git-stunts/git-cas/milestone/13) | Coherent Git object sessions across immutable writes | [#94](https://github.com/git-stunts/git-cas/issues/94) | | [`v6.5.4`](https://github.com/git-stunts/git-cas/milestone/14) | Batched staging-workspace page retention | [#99](https://github.com/git-stunts/git-cas/issues/99) | +| [`v6.5.5`](https://github.com/git-stunts/git-cas/milestone/15) | Identity-independent internal Git commits | [#102](https://github.com/git-stunts/git-cas/issues/102) | | [`v6.6.0`](https://github.com/git-stunts/git-cas/milestone/9) | Operator TUI and agent automation follow-through | [#39](https://github.com/git-stunts/git-cas/issues/39), [#40](https://github.com/git-stunts/git-cas/issues/40) | | [`v6.7.0`](https://github.com/git-stunts/git-cas/milestone/10) | Browser and edge read-path exploration | [#41](https://github.com/git-stunts/git-cas/issues/41) | | [`v7.0.0`](https://github.com/git-stunts/git-cas/milestone/6) | Protocol break only if audit requires it | [#42](https://github.com/git-stunts/git-cas/issues/42), only when justified | @@ -50,10 +51,10 @@ GitHub wins and this file should be corrected. The latest landed design record is: -- [0054-batched-page-retention](./docs/design/0054-batched-page-retention/batched-page-retention.md) +- [0055-internal-commit-identity](./docs/design/0055-internal-commit-identity/internal-commit-identity.md) Its GitHub goalpost issue, -[#99](https://github.com/git-stunts/git-cas/issues/99), owns the release +[#102](https://github.com/git-stunts/git-cas/issues/102), owns the release evidence. The design doc is the durable contract; GitHub records completion. The `v6.2.0` slice record is: diff --git a/STATUS.md b/STATUS.md index 2339434..55fdcf1 100644 --- a/STATUS.md +++ b/STATUS.md @@ -1,8 +1,8 @@ # STATUS -**Last tagged release:** `v6.5.3` (`2026-07-19`) -**Current release state:** `v6.5.4` release candidate; tag, npm publication, and GitHub Release remain pending the reviewed tag workflow. -**Latest verification:** the versioned `v6.5.4` candidate passed 14/14 release-verifier steps with 6,844 observed tests across Node, Bun, Deno, and all three real-Git integration suites; tag and publication verification remain pending. +**Last tagged release:** `v6.5.4` (`2026-07-26`) +**Current release state:** `v6.5.5` release candidate; tag, npm publication, and GitHub Release remain pending the reviewed tag workflow. +**Latest verification:** the versioned `v6.5.5` candidate passed 14/14 release-verifier steps with 6,850 observed tests across Node, Bun, Deno, and all three real-Git integration suites; tag and publication verification remain pending. **Playback truth:** `main` **Runtimes:** Node.js 22.x, Bun, Deno **Current planning method:** [WORKFLOW.md](./WORKFLOW.md) @@ -18,13 +18,20 @@ - The machine-facing `git cas agent` surface exists and now supports OS-keychain passphrase sources for vault-derived key flows, but parity and portability are still partial. -- **v6.5.4 candidate posture** — batched staging-workspace page retention - merged through reviewed commit `e6c58f10` under - [#99](https://github.com/git-stunts/git-cas/issues/99). npm, JSR, and runtime - version metadata identify `6.5.4`; tag and registry artifacts remain - deliberately absent until release-candidate review completes. +- **v6.5.5 candidate posture** — internal root-set, publication, and vault + commits now supply a git-cas-owned author and committer identity instead of + depending on ambient Git user configuration. Implementation PR + [#103](https://github.com/git-stunts/git-cas/pull/103) merged as + `fa3d5f64`; npm, JSR, and runtime metadata identify `6.5.5`, while tag and + registry artifacts remain deliberately absent pending release review. +- **v6.5.4 artifact posture** — signed tag `v6.5.4` resolves to reviewed merge + `a2d23f5b`; npm reports `@git-stunts/git-cas@6.5.4` as `latest` with SLSA + provenance, and release workflow `30205009357` published the final GitHub + Release. Batched staging-workspace page retention is shipped. JSR dry-run + validation is healthy, but JSR publication is not part of the release + workflow. - **v6.5.3 artifact posture** — signed tag `v6.5.3` resolves to reviewed merge - `00df6077`; npm reports `@git-stunts/git-cas@6.5.3` as `latest` with SLSA + `00df6077`; npm retains `@git-stunts/git-cas@6.5.3` with SLSA provenance, and release workflow `29696131557` published the final GitHub Release. Coherent Git object sessions are shipped. JSR dry-run validation is healthy, but JSR publication is not part of the release workflow. @@ -139,7 +146,7 @@ under the [`v6.6.0` milestone](https://github.com/git-stunts/git-cas/milestone/9). - The latest landed design record is - [0054-batched-page-retention](./docs/design/0054-batched-page-retention/batched-page-retention.md). + [0055-internal-commit-identity](./docs/design/0055-internal-commit-identity/internal-commit-identity.md). ## Read Next diff --git a/UPGRADING.md b/UPGRADING.md index d0944d5..b6ade9e 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -2,6 +2,22 @@ v6.0.0 is a major release that simplifies the encryption model, hardens security defaults, and cleans up the architecture. This guide covers every breaking change and what you need to do. +## v6.5.4 To v6.5.5 + +v6.5.5 changes no public API and requires no stored-data migration. New +git-cas-owned root-set, publication, and vault commits carry a stable internal +author and committer identity, so writes no longer depend on repository-local +or global `user.name` and `user.email` configuration. + +Existing refs, stored objects, and handles remain valid. Because Git commit +identity contributes to commit bytes, a newly created internal commit may have +a different OID than the same tree, parents, message, and timestamp would have +produced under an operator's ambient identity. Applications must continue to +treat these commits as opaque storage generations. + +See [v6.5.5 Release Notes](./docs/releases/v6.5.5.md) for the exact identity +contract and clean-bare-repository verification. + ## v6.5.3 To v6.5.4 v6.5.4 adds `workspace.pages.putBatch()` and requires no stored-data migration. diff --git a/docs/design/0054-batched-page-retention/witness/release-publication.md b/docs/design/0054-batched-page-retention/witness/release-publication.md new file mode 100644 index 0000000..238c09f --- /dev/null +++ b/docs/design/0054-batched-page-retention/witness/release-publication.md @@ -0,0 +1,63 @@ +# PERF-0054 v6.5.4 Publication Witness + +Date: 2026-07-26 + +Issue: #99 + +## Immutable Release Identity + +- Feature PR: [#100](https://github.com/git-stunts/git-cas/pull/100) +- Release PR: [#101](https://github.com/git-stunts/git-cas/pull/101) +- Reviewed merge commit: `a2d23f5bfc5d00eecab897eadd9072dab4aff534` +- Signed annotated tag: `v6.5.4` +- Tag object: `554d552ed957d5bbe2ad1c685309ae64359ff7ea` +- Peeled tag target: `a2d23f5bfc5d00eecab897eadd9072dab4aff534` +- Signing key: `01A63D8E9DBEEDE32918AF9C39560E0406CA9135` +- GitHub Release: + [v6.5.4](https://github.com/git-stunts/git-cas/releases/tag/v6.5.4) + (final, not a draft or prerelease; published `2026-07-26T14:00:02Z`) + +Local `git tag -v v6.5.4` reported a good signature. The tag peels to the +reviewed release merge exactly. + +## Release Workflow + +[Release run 30205009357](https://github.com/git-stunts/git-cas/actions/runs/30205009357) +completed successfully against `v6.5.4`: + +| Job | Result | Evidence | +| -------------- | ------ | ---------------------------------------------- | +| Validate | pass | Tag version matched `package.json` | +| Test | pass | Lint, unit, Node/Bun/Deno real-Git integration | +| Publish npm | pass | OIDC trusted publication completed | +| GitHub Release | pass | Final release created after npm publication | + +Before tagging, the release candidate passed all 14 verifier steps with 6,844 +observed tests, public type compatibility, examples, build stamping, and npm +and JSR dry-runs. + +## npm Registry Evidence + +Independent registry queries after the workflow completed reported: + +| Field | Value | +| ------------- | ------------------------------------------------------------------------------------------------- | +| Package | `@git-stunts/git-cas@6.5.4` | +| Published | `2026-07-26T13:59:48.429Z` | +| Dist-tag | `latest` -> `6.5.4` | +| Integrity | `sha512-3C7kWprQl6cPz0P1DPIW/T04ujucn276LJv0zK+QmwI83t6smTx2PLDulOTlpumlP4SVOFY2cUTyd/1gtgbgkA==` | +| Shasum | `bcf4784d4c05a08a8bb95f03038f680dc5ed90a8` | +| File count | `255` | +| Unpacked size | `2,209,770` bytes | +| Tarball | `https://registry.npmjs.org/@git-stunts/git-cas/-/git-cas-6.5.4.tgz` | + +The registry exposes the package-version +[attestation endpoint](https://registry.npmjs.org/-/npm/v1/attestations/@git-stunts%2fgit-cas@6.5.4) +with npm publish and `https://slsa.dev/provenance/v1` predicates. + +## Downstream Gate + +The v6.5.4 artifact supplies the batch-retention dependency required by +git-warp's migration implementation. It does not by itself prove that the +complete retained-substrate migration succeeds. That executable downstream +obligation remains with git-warp v19. diff --git a/docs/design/0055-internal-commit-identity/internal-commit-identity.md b/docs/design/0055-internal-commit-identity/internal-commit-identity.md index 70d0ce9..ed7ee00 100644 --- a/docs/design/0055-internal-commit-identity/internal-commit-identity.md +++ b/docs/design/0055-internal-commit-identity/internal-commit-identity.md @@ -7,7 +7,7 @@ release_home: "v6.5.5" issue: "https://github.com/git-stunts/git-cas/issues/102" goalpost_issue: "none" tracker_source: "github" -status: "active" +status: "landed" base_commit: "a2d23f5bfc5d00eecab897eadd9072dab4aff534" owners: - "@git-stunts" @@ -263,7 +263,8 @@ Use option C. Pass an immutable internal identity map on every adapter-owned - [x] Bare root-set write records the internal identity. - [x] Full unit and integration suites are green. - [x] Changelog and issue are linked. -- [ ] CI is green and the patch package is published. +- [x] Implementation CI is green. +- [ ] The patch package is published. - [ ] git-warp's clean-Linux migration verification passes on the patch. ## Validation Plan @@ -315,5 +316,6 @@ commits, or a general public commit-author API. The adapter proved to be the narrow ownership boundary: one environment map covers root-set, publication, and vault commits without repository -configuration or caller coupling. Local cross-runtime verification is green. -PR, release, and downstream verification remain pending. +configuration or caller coupling. PR #103 merged after local and GitHub +cross-runtime verification passed. Release and downstream verification remain +pending. diff --git a/docs/design/0055-internal-commit-identity/witness/release-candidate.md b/docs/design/0055-internal-commit-identity/witness/release-candidate.md new file mode 100644 index 0000000..107d8d4 --- /dev/null +++ b/docs/design/0055-internal-commit-identity/witness/release-candidate.md @@ -0,0 +1,77 @@ +# INFRA-0055 v6.5.5 Release Candidate Witness + +Date: 2026-07-26 + +Issue: #102 + +Implementation review: #103 + +Release review: #104 + +## Scope + +This witness records the pre-publication candidate for identity-independent +git-cas-owned commits. It does not claim that a `v6.5.5` tag, npm artifact, or +GitHub Release exists. This is an explicitly unpublished candidate. + +The candidate: + +- sets npm, JSR, and runtime package metadata to `6.5.5`; +- moves the internal-identity repair from `Unreleased` to `6.5.5`; +- packages and links `docs/releases/v6.5.5.md`; +- records v6.5.4 publication evidence as immutable history; +- marks design 0055 landed after implementation PR #103; and +- leaves v6.5.5 tag and registry claims deliberately absent. + +## Implementation Provenance + +| Capability | Review anchor | Commit | +| ------------------------------------- | ------------- | ------------------------------------------ | +| Identity-independent internal commits | #103 | `6b7f0a60d2ab9a6f776d63d50b6c4e995cffb239` | +| Reviewed implementation merge | #103 | `fa3d5f6479b66bc09578487b33d1a55dec9e02b4` | + +The adapter supplies a stable author and committer only to internal +`commit-tree` operations. It does not mutate Git configuration or extend the +public API. + +## Failure Witness + +A clean Linux WARP migration rehearsal promoted retained state into an +authoritative bare repository with no ambient Git identity. The subsequent +root-set write failed at `git commit-tree` with `Author identity unknown`. + +The RED adapter test observed no command environment. The GREEN test observes +all four identity values, and native Git integration verifies both resulting +commit headers. + +## Verification + +The versioned candidate passed the complete `pnpm run release:verify` method: + +| Gate | Result | Observed tests | +| -------------------------- | ---------------- | -------------: | +| Lint | PASS | - | +| Unit tests (Node) | PASS | 2,088 | +| Unit tests (Bun) | PASS | 2,087 | +| Unit tests (Deno) | PASS | 2,078 | +| Public type compatibility | PASS | - | +| Integration tests (Node) | PASS | 199 | +| Integration tests (Bun) | PASS | 199 | +| Integration tests (Deno) | PASS | 199 | +| Examples and build stamp | PASS | - | +| npm and JSR dry-runs | PASS | - | +| **Release method summary** | **PASS (14/14)** | **6,850** | + +Tag and publication evidence remain deliberately absent from this candidate +witness. + +## Publication Gate + +Publication remains blocked until the versioned candidate passes every local +and GitHub gate, the release PR is merged, a signed annotated `v6.5.5` tag +points at that reviewed merge, and the release workflow publishes npm and the +final GitHub Release. + +After publication, git-warp must consume `6.5.5` and rerun the exact +clean-Linux retained-substrate migration proof. That downstream result is a +git-warp v19 release gate. diff --git a/docs/design/README.md b/docs/design/README.md index 29f6afa..c8b6f87 100644 --- a/docs/design/README.md +++ b/docs/design/README.md @@ -11,7 +11,6 @@ process in [docs/method/process.md](../method/process.md). ## Active METHOD Cycles -- [0055-internal-commit-identity - internal-commit-identity](./0055-internal-commit-identity/internal-commit-identity.md) - [0054-batched-page-retention - batched-page-retention](./0054-batched-page-retention/batched-page-retention.md) - [0050-lazy-bundle-reference-reads - lazy-bundle-reference-reads](./0050-lazy-bundle-reference-reads/lazy-bundle-reference-reads.md) - [0049-scoped-staging-workspaces — scoped-staging-workspaces](./0049-scoped-staging-workspaces/scoped-staging-workspaces.md) @@ -45,6 +44,7 @@ process in [docs/method/process.md](../method/process.md). ## Landed METHOD Cycles +- [0055-internal-commit-identity - internal-commit-identity](./0055-internal-commit-identity/internal-commit-identity.md) - [0053-git-object-session-coherence - git-object-session-coherence](./0053-git-object-session-coherence/git-object-session-coherence.md) - [0052-persistent-git-object-sessions - persistent-git-object-sessions](./0052-persistent-git-object-sessions/persistent-git-object-sessions.md) - [0051-bounded-page-payload-reuse - bounded-page-payload-reuse](./0051-bounded-page-payload-reuse/bounded-page-payload-reuse.md) diff --git a/docs/releases/v6.5.5.md b/docs/releases/v6.5.5.md new file mode 100644 index 0000000..bdf42f6 --- /dev/null +++ b/docs/releases/v6.5.5.md @@ -0,0 +1,43 @@ +# git-cas v6.5.5 Release Notes + +v6.5.5 makes every git-cas-owned Git commit independent of ambient user +configuration. Root-set, publication, and vault writes now work in a clean bare +repository without configuring a personal author or committer. + +## Self-Contained Commit Identity + +`GitRefAdapter.createCommit()` supplies this stable identity to each internal +`git commit-tree` operation: + +```text +git-cas +``` + +The identity is scoped to the individual Git command. git-cas does not invoke +`git config`, mutate repository or global settings, or require applications to +provide personal identity. + +This fixes storage writes performed against bare or automation-owned +repositories where `user.name` and `user.email` are deliberately absent. The +failure was exposed by a clean-Linux retained-substrate migration rehearsal: +post-promotion root-set retention reached `git commit-tree`, which otherwise +stopped with `Author identity unknown`. + +## Verification + +Unit coverage observes all four author and committer environment variables. +Real-Git integration reads a root-set commit through native Git and verifies +both headers exactly. The versioned release candidate passed the complete +Node, Bun, and Deno unit and integration matrix, public type compatibility, +examples, lint, build stamping, and package dry-runs. + +## Compatibility + +This release changes no public API or stored-data schema and requires no +migration. Existing refs, objects, handles, and retained generations remain +valid. + +Git identity is part of commit bytes, so newly created internal commit OIDs may +differ from commits that previously inherited an operator identity. Internal +commit OIDs remain opaque generations; callers must not derive them in advance +or interpret personal attribution from them. diff --git a/jsr.json b/jsr.json index 1ea3d21..1374224 100644 --- a/jsr.json +++ b/jsr.json @@ -1,6 +1,6 @@ { "name": "@git-stunts/git-cas", - "version": "6.5.4", + "version": "6.5.5", "exports": { ".": "./index.js", "./service": "./src/domain/services/CasService.js", diff --git a/package.json b/package.json index 491971d..9354422 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@git-stunts/git-cas", - "version": "6.5.4", + "version": "6.5.5", "description": "Content-addressed storage backed by Git's object database, with optional encryption and pluggable codecs", "type": "module", "main": "index.js", @@ -41,6 +41,7 @@ "docs/releases/v6.5.2.md", "docs/releases/v6.5.3.md", "docs/releases/v6.5.4.md", + "docs/releases/v6.5.5.md", "docs/THREAT_MODEL.md", "docs/VAULT_INTERNALS.md", "docs/WALKTHROUGH.md", diff --git a/src/package-version.js b/src/package-version.js index 8e63844..907439f 100644 --- a/src/package-version.js +++ b/src/package-version.js @@ -1 +1 @@ -export const PACKAGE_VERSION = '6.5.4'; +export const PACKAGE_VERSION = '6.5.5'; diff --git a/test/unit/docs/package-docs.test.js b/test/unit/docs/package-docs.test.js index 3cc7e6a..66b32e6 100644 --- a/test/unit/docs/package-docs.test.js +++ b/test/unit/docs/package-docs.test.js @@ -19,6 +19,7 @@ const requiredStandardDocs = [ 'docs/releases/v6.5.2.md', 'docs/releases/v6.5.3.md', 'docs/releases/v6.5.4.md', + 'docs/releases/v6.5.5.md', ]; const forbiddenPackagePrefixes = ['docs/audit/', 'docs/archive/', 'docs/method/']; const forbiddenPackageFiles = ['docs/cli.gif', 'docs/vault.gif']; @@ -94,6 +95,7 @@ function publicPackagedMarkdownFiles(files) { 'docs/releases/v6.5.2.md', 'docs/releases/v6.5.3.md', 'docs/releases/v6.5.4.md', + 'docs/releases/v6.5.5.md', 'docs/THREAT_MODEL.md', 'docs/WALKTHROUGH.md', ].filter((file) => files.has(file)); diff --git a/test/unit/docs/release-state.test.js b/test/unit/docs/release-state.test.js index ba926c4..bc844af 100644 --- a/test/unit/docs/release-state.test.js +++ b/test/unit/docs/release-state.test.js @@ -4,8 +4,10 @@ import path from 'node:path'; const repoRoot = process.cwd(); const v653PublishedMarker = '**v6.5.3 artifact posture**'; -const v654CandidatePath = - 'docs/design/0054-batched-page-retention/witness/release-candidate.md'; +const v655CandidatePath = 'docs/design/0055-internal-commit-identity/witness/release-candidate.md'; +const v654CandidatePath = 'docs/design/0054-batched-page-retention/witness/release-candidate.md'; +const v654PublicationPath = + 'docs/design/0054-batched-page-retention/witness/release-publication.md'; const v653CandidatePath = 'docs/design/0053-git-object-session-coherence/witness/release-candidate.md'; const v653PublicationPath = @@ -31,6 +33,29 @@ function v6Heading(changelog) { return changelog.match(/^## \[6\.0\.0\] — (.+)$/m)?.[1]; } +function expectNoV655PublicationEvidence(...documents) { + const forbiddenMarkers = [ + '**Last tagged release:** `v6.5.5`', + '**Current release state:** `v6.5.5` is published', + '- Signed annotated tag: `v6.5.5`', + 'https://github.com/git-stunts/git-cas/releases/tag/v6.5.5', + '## npm Registry Evidence', + /\| Package\s+\| `@git-stunts\/git-cas@6\.5\.5`\s+\|/, + /\| Dist-tag\s+\| `latest` -> `6\.5\.5`\s+\|/, + 'attestations/@git-stunts%2fgit-cas@6.5.5', + ]; + + for (const document of documents) { + for (const marker of forbiddenMarkers) { + if (marker instanceof RegExp) { + expect(document).not.toMatch(marker); + } else { + expect(document).not.toContain(marker); + } + } + } +} + function expectNoV654PublicationEvidence(...documents) { const forbiddenMarkers = [ '**Last tagged release:** `v6.5.4`', @@ -134,9 +159,7 @@ function expectV653CandidateEvidence(candidate) { expectNoV653PublicationEvidence(candidate); } -function expectV654CandidateEvidence(status, candidate) { - expect(status).toContain('**Last tagged release:** `v6.5.3` (`2026-07-19`)'); - expect(status).toContain('**Current release state:** `v6.5.4` release candidate'); +function expectV654CandidateEvidence(candidate) { expect(candidate).toContain('# PERF-0054 v6.5.4 Release Candidate Witness'); expect(candidate).toContain('Implementation review: #100'); expect(candidate).toContain('Release review: #101'); @@ -144,11 +167,45 @@ function expectV654CandidateEvidence(status, candidate) { expect(candidate).toContain('**PASS (14/14)**'); expect(candidate).toContain('**6,844**'); expect(candidate).toMatch(/explicitly\s+unpublished\s+candidate/); - expectNoV654PublicationEvidence(status, candidate); + expectNoV654PublicationEvidence(candidate); +} + +function expectV654PublishedEvidence(status, publication) { + expect(status).toContain('**Last tagged release:** `v6.5.4` (`2026-07-26`)'); + expect(status).toContain('**v6.5.4 artifact posture**'); + expect(status).toContain('a2d23f5b'); + expect(status).toContain('30205009357'); + expect(publication).toContain('# PERF-0054 v6.5.4 Publication Witness'); + expect(publication).toContain('a2d23f5bfc5d00eecab897eadd9072dab4aff534'); + expect(publication).toContain('554d552ed957d5bbe2ad1c685309ae64359ff7ea'); + expect(publication).toContain('01A63D8E9DBEEDE32918AF9C39560E0406CA9135'); + expect(publication).toContain('- Signed annotated tag: `v6.5.4`'); + expect(publication).toContain('https://github.com/git-stunts/git-cas/releases/tag/v6.5.4'); + expect(publication).toContain('actions/runs/30205009357'); + expect(publication).toMatch(/\| Package\s+\| `@git-stunts\/git-cas@6\.5\.4`\s+\|/); + expect(publication).toMatch(/\| Dist-tag\s+\| `latest` -> `6\.5\.4`\s+\|/); + expect(publication).toContain( + 'sha512-3C7kWprQl6cPz0P1DPIW/T04ujucn276LJv0zK+QmwI83t6smTx2PLDulOTlpumlP4SVOFY2cUTyd/1gtgbgkA==' + ); + expect(publication).toContain('bcf4784d4c05a08a8bb95f03038f680dc5ed90a8'); + expect(publication).toContain('2,209,770'); + expect(publication).toContain('attestations/@git-stunts%2fgit-cas@6.5.4'); +} + +function expectV655CandidateEvidence(status, candidate) { + expect(status).toContain('**Last tagged release:** `v6.5.4` (`2026-07-26`)'); + expect(status).toContain('**Current release state:** `v6.5.5` release candidate'); + expect(candidate).toContain('# INFRA-0055 v6.5.5 Release Candidate Witness'); + expect(candidate).toContain('Implementation review: #103'); + expect(candidate).toContain('Release review: #104'); + expect(candidate).toContain('fa3d5f6479b66bc09578487b33d1a55dec9e02b4'); + expect(candidate).toContain('**PASS (14/14)**'); + expect(candidate).toContain('**6,850**'); + expect(candidate).toMatch(/explicitly\s+unpublished\s+candidate/); + expectNoV655PublicationEvidence(status, candidate); } function expectV653PublishedEvidence(status, publication) { - expect(status).toContain('**Last tagged release:** `v6.5.3` (`2026-07-19`)'); expect(status).toContain(v653PublishedMarker); expect(status).toContain('00df6077'); expect(status).toContain('29696131557'); @@ -272,9 +329,11 @@ function expectCurrentV640PublicationEvidence(publication) { } describe('release state docs', () => { - it('enforces the v6.5.4 candidate while preserving published evidence', () => { + it('enforces the v6.5.5 candidate while preserving published evidence', () => { const status = read('STATUS.md'); + const v655Candidate = read(v655CandidatePath); const v654Candidate = read(v654CandidatePath); + const v654Publication = read(v654PublicationPath); const candidate = read(v653CandidatePath); const v653Publication = read(v653PublicationPath); const v652Candidate = read(v652CandidatePath); @@ -282,12 +341,15 @@ describe('release state docs', () => { const v651Candidate = read(v651CandidatePath); const v653ReleaseNotes = read('docs/releases/v6.5.3.md'); const v654ReleaseNotes = read('docs/releases/v6.5.4.md'); + const v655ReleaseNotes = read('docs/releases/v6.5.5.md'); const v652ReleaseNotes = read('docs/releases/v6.5.2.md'); const publication = read(v651PublicationPath); const v650Publication = read(v650PublicationPath); const v640Publication = read(v640PublicationPath); - expectV654CandidateEvidence(status, v654Candidate); + expectV655CandidateEvidence(status, v655Candidate); + expectV654CandidateEvidence(v654Candidate); + expectV654PublishedEvidence(status, v654Publication); expectV653CandidateEvidence(candidate); expectV653PublishedEvidence(status, v653Publication); expectV652CandidateEvidence(v652Candidate); @@ -296,13 +358,14 @@ describe('release state docs', () => { expectV651PublishedEvidence(status, publication); expect(v653ReleaseNotes).toContain('release verifier passed all 14 steps with 6,829'); expect(v654ReleaseNotes).toContain('full release verifier passed all 14 steps with 6,844'); + expect(v655ReleaseNotes).toMatch(/requires no\s+migration/); expect(v652ReleaseNotes).toContain('passed all 14 release-verifier steps with 6,817 observed'); expectV650PublishedEvidence(status, v650Publication); expectCurrentV640PublicationEvidence(v640Publication); expect(status).toContain('Current release goalpost:'); expect(status).toContain('#39 v6.6.0: Operator TUI'); expect(status).toContain('#40 v6.6.0: Agent automation follow-through'); - expect(status).toContain('0054-batched-page-retention'); + expect(status).toContain('0055-internal-commit-identity'); expect(v640Publication).toContain('https://slsa.dev/provenance/v1'); expect(v640Publication).toContain('https://github.com/git-stunts/git-cas/releases/tag/v6.4.0'); }); diff --git a/test/unit/docs/release-truth.test.js b/test/unit/docs/release-truth.test.js index 08ac241..52cbc7b 100644 --- a/test/unit/docs/release-truth.test.js +++ b/test/unit/docs/release-truth.test.js @@ -293,6 +293,21 @@ describe('batched workspace page retention release documentation', () => { }); }); +describe('internal commit identity release documentation', () => { + it('ships and links the v6.5.5 clean-bare-repository contract', () => { + const readme = read('README.md'); + const upgrading = read('UPGRADING.md'); + const releaseNotes = read('docs/releases/v6.5.5.md'); + + expect(readme).toContain('[v6.5.5 Release Notes](./docs/releases/v6.5.5.md)'); + expect(upgrading).toContain('## v6.5.4 To v6.5.5'); + expect(upgrading).toMatch(/requires no stored-data migration/); + expect(releaseNotes).toContain('# git-cas v6.5.5 Release Notes'); + expect(releaseNotes).toContain('git-cas '); + expect(releaseNotes).toMatch(/does not invoke\s+`git config`/); + }); +}); + describe('advanced guide rendering', () => { it('keeps the table of contents rendered as Markdown links', () => { const advancedGuide = read('ADVANCED_GUIDE.md');