Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ Paste bullets for `CHANGELOG.md` Unreleased (or N/A):
- [ ] `CHANGELOG.md` updated (or N/A)
- [ ] `docs/VISION.md` updated if this is a product decision

## Numbered acceptance ledger

<!-- Required for a multi-item request. Preserve the user's numbering and give
one outcome/evidence line per requested item. Do not merge distinct items into
generic bullets. Delete this section only for a genuinely single-item change. -->

1. …

- [ ] Every requested item appears once and is implemented or explicitly named
as deferred with its reason.
- [ ] This ledger is ready to be copied into the GitHub Release notes unchanged.

## Verification

- [ ] `npm run typecheck`
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- GitHub Releases now require the complete numbered acceptance ledger from a
multi-item request, plus artifact and verification evidence. Generated
commit summaries can no longer replace the user-facing change list.
- The retained Apple Silicon release host now owns the complete macOS path:
clean build, signing, notarization, public-download installation, launch,
smoke verification, and Application Support preservation.

## [0.0.10] - 2026-07-25

### Fixed
Expand Down
3 changes: 3 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ welcome through GitHub issues and pull requests.
| [docs/GOVERNANCE.md](./docs/GOVERNANCE.md) | Authority, branches, quality bar |
| [docs/release-lifecycle.md](./docs/release-lifecycle.md) | Idea → PR → deploy |
| [docs/release-checklist.md](./docs/release-checklist.md) | Ship verification commands |
| [docs/release-notes-template.md](./docs/release-notes-template.md) | Complete public release record |
| [CHANGELOG.md](./CHANGELOG.md) | User/operator-facing history |
| [docs/VISION.md](./docs/VISION.md) | Product decisions and build record |

Expand Down Expand Up @@ -49,6 +50,8 @@ assignment; contributors retain copyright in contributions they author.
5. Record durable decisions in `docs/VISION.md`.
6. Use the merge method selected by the maintainer; delete the head branch.
7. For a named ship: version bump + [release-checklist.md](./docs/release-checklist.md).
8. For a multi-item ship, preserve the numbered acceptance ledger in the PR
and GitHub Release; generated notes are not a replacement.

### Security

Expand Down
12 changes: 12 additions & 0 deletions docs/GOVERNANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,25 @@ contract as the slice hardens.
5. No secrets, operator hosts/paths, real provider keys, or `data/` SQLite dumps.
6. Significant product decisions recorded in `docs/VISION.md`.
7. User-visible changes noted under `CHANGELOG.md` → `## [Unreleased]`.
8. A multi-item user request retains a numbered acceptance ledger in the pull
request and GitHub Release. Do not collapse completed items into a generic
summary or rely on generated commit notes as the user-facing release record.
9. The retained Apple Silicon release host owns both artifact production and
public-download installed-app verification.

## Versioning

- Semantic versioning on `package.json`.
- **Do not** reuse a published version tag for different bits.
- A release requires a unique version, changelog, exact tag, verified public
artifact, and platform-appropriate clean installation evidence.
- GitHub Release notes are a first-class product artifact. They must enumerate
every user-visible fix and feature accepted for that release, using the same
numbered ledger as the originating request when one exists. A short summary
can introduce that ledger but cannot replace it.
- macOS verification must use the exact publicly downloaded artifact, preserve
Application Support, and prove signature/ticket/Gatekeeper, launch, version,
loopback behavior, and retained state on the retained release host.

Never hand-edit only a deployment target to fix the product. Fix in git,
review, merge, and redeploy the exact source commit.
Expand Down
27 changes: 23 additions & 4 deletions docs/release-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ git switch -c <branch-name>

Implement, update tests, `docs/VISION.md` if needed, and `CHANGELOG.md` Unreleased.

For a multi-item request, copy its numbering into the PR acceptance ledger and
keep one result/evidence line per item. That ledger must survive unchanged into
the GitHub Release notes; do not replace it with a shorter commit summary.

When this branch will be a named release:

```bash
Expand All @@ -44,7 +48,7 @@ Run any feature-specific suites (e.g. `npm run test:native` when that script exi

```bash
git push -u origin HEAD
gh pr create --fill # use template
gh pr create --fill # use template, including the acceptance ledger
```

## 4. Merge
Expand All @@ -66,11 +70,22 @@ git push origin "refs/tags/v${VERSION}"
HEADLESS="dist/1Helm-${VERSION}-linux-node.tgz"
DMG="dist/1Helm-${VERSION}-arm64.dmg"
UPDATE_ZIP="dist/1Helm-${VERSION}-mac-arm64.zip"
gh release create "v${VERSION}" "$DMG" "$UPDATE_ZIP" "$HEADLESS" --title "1Helm ${VERSION}" --generate-notes --draft
RELEASE_NOTES="dist/1Helm-${VERSION}-release-notes.md"
# Author RELEASE_NOTES from docs/release-notes-template.md. It must contain the
# complete numbered acceptance ledger, artifact digests, and verification.
test -s "$RELEASE_NOTES"
rg -q '^1\. ' "$RELEASE_NOTES" # multi-item ships must retain a numbered ledger
gh release create "v${VERSION}" "$DMG" "$UPDATE_ZIP" "$HEADLESS" --title "1Helm ${VERSION}" --notes-file "$RELEASE_NOTES" --draft
# review notes, then:
gh release edit "v${VERSION}" --draft=false
```

`--generate-notes` is not an acceptable replacement for the authored notes.
Generated commit/PR lists may be appended as secondary metadata, but the public
body must lead with the complete user-visible acceptance ledger. Before
publication, compare the notes item-by-item with the originating request and
the versioned `CHANGELOG.md` entry.

## 6. Local verify

```bash
Expand All @@ -88,7 +103,10 @@ Expect first-run / needs_setup on empty data dir.

- Verify the native ZIP was created only after the app was notarized and stapled; extract it and repeat strict signature, ticket, and Gatekeeper checks.
- Confirm the public Electron feed selects that ZIP for the prior Mac version and returns no update for the new version.
- On an independent Mac with preserved Application Support, use Profile to make the host download the update, wait for **Restart & install**, install it, and verify the new version, loopback health, resident state, and data-directory identity.
- On the same retained Apple Silicon release host used for the clean build,
install the **publicly downloaded** DMG/update with preserved Application
Support, then verify the new version, loopback health, resident state, and
data-directory identity.
- Upload the exact `npm run package:linux` artifact and require GitHub's recorded `sha256:` digest before publication.
- In a disposable systemd host running the prior release, invoke the same Captain host-update action, observe checking/downloading/installing/restarting, verify the new version and `/var/lib/1helm` identity, and exercise rollback with an intentionally unhealthy disposable fixture.

Expand All @@ -106,9 +124,10 @@ Expect first-run / needs_setup on empty data dir.
Version: <package version>
Merged commit: <origin/main SHA>
Tag/Release: <if any>
Release notes: complete numbered acceptance ledger reviewed against request
Local setup: needs_setup verified on clean CTRL_DATA_DIR
Clean deploy: <pass / skipped + reason>
Mac host update:<old → new, updater feed + state preserved>
Mac host update:<public artifact installed on release host + state preserved>
Linux update: <old → new, digest + health + state preserved>
CI: Actions green on main
```
18 changes: 14 additions & 4 deletions docs/release-lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Process contract from intent to verified deploy. Commands: [release-checklist.md
version bump on the release branch
v
tag · signed DMG + updater ZIP + Linux host artifact · deploy target(s)
full numbered notes · tag · signed DMG + updater ZIP + Linux host artifact
v
verify (local health + clean install + public artifact)
Expand Down Expand Up @@ -61,7 +61,10 @@ Feature branches that introduce `test/native-world.mjs` (or similar) must run th

## 4. Pull request

Use the PR template: summary, type, changelog bullets, verification checklist.
Use the PR template: summary, type, changelog bullets, numbered acceptance
ledger, and verification checklist. For a multi-item request, preserve its
numbering and record one concrete outcome per item. The ledger is the source
for the GitHub Release; a commit title or generated summary is not a substitute.

Draft PRs are allowed for long slices; mark ready only when the quality bar is met.

Expand All @@ -77,7 +80,14 @@ Draft PRs are allowed for long slices; mark ready only when the quality bar is m
2. `npm version patch|minor|major --no-git-tag-version` (or edit `package.json`).
3. Commit the versioned source on the release branch before merge.
4. After merge, tag the exact verified `main` commit and push the tag.
5. Publish the verified DMG, native updater ZIP, Linux host artifact, and release notes through one GitHub Release.
5. Author release notes from the PR acceptance ledger using
[release-notes-template.md](./release-notes-template.md). Every accepted
user-visible item must appear once, with the same numbering as the request
when available. Include additional fixes, artifacts/digests, and verification
evidence in their own sections.
6. Publish the verified DMG, native updater ZIP, Linux host artifact, and those
complete release notes through one GitHub Release. Do not use GitHub's
generated notes as the sole or primary body.

## 7. Deploy

Expand All @@ -103,7 +113,7 @@ workspace state.
| Code landed | On `origin/main`, CI green |
| Behavior fixed | Tests + manual/API check |
| Install path still works | Clean `CTRL_DATA_DIR` boot through the wizard plus platform acceptance |
| Named release | Version, changelog, exact tag, verified public artifact, and clean installation |
| Named release | Version, changelog, full numbered notes, exact tag, verified public artifact, and clean installation |
| Native host update | Published updater ZIP feed, installed-old-to-new Mac acceptance, and preserved Application Support |
| Linux host update | Digest-qualified artifact, real systemd old-to-new update, health check, and preserved `/var/lib/1helm` |

Expand Down
49 changes: 49 additions & 0 deletions docs/release-notes-template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# 1Helm x.y.z

Short outcome-first summary of this release.

## What changed

For a multi-item request, preserve the original numbered acceptance ledger and
write one user-visible outcome per requested item. Do not combine distinct requests into
generic bullets. If an item was deliberately deferred, keep its number and say
so plainly instead of silently omitting it.

1. **Feature or fix name** — concrete user-visible outcome.
2. **Feature or fix name** — concrete user-visible outcome.

## Additional changes

- Include work added after the original numbered request.
- Include material licensing, migration, compatibility, or operational changes.

## Downloads and integrity

| Artifact | SHA-256 |
| --- | --- |
| `1Helm-x.y.z-arm64.dmg` | `<digest>` |
| Other published artifact, or `Not applicable` | `<digest>` |

Source commit: `<full merged SHA>`

## Verification

- Name the exact automated suites and pass counts.
- Name public demo/site/API checks when applicable.
- For macOS, state Developer ID signature, Apple notarization, stapling,
Gatekeeper, public-download installation on the retained release host, app
launch/smoke behavior, and Application Support preservation.
- Name anything skipped or incomplete; do not call an incomplete release fully
verified.

## Licensing

State the license for this version and any release-boundary notice that users
need to understand.

---

Before publication, compare this file line-by-line with the originating user
request/issue, PR acceptance ledger, `CHANGELOG.md`, published artifact list,
and final verification evidence. GitHub-generated notes are optional secondary
metadata and must never replace this authored record.
2 changes: 1 addition & 1 deletion scripts/run-test-suite.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const suites = [
"test/routing.mjs", "test/routing-disabled-account.mjs", "test/desktop.mjs", "test/update-service.mjs",
"test/channel-computers.mjs", "test/channel-computers-isolated-backends.mjs", "test/channel-computers-backend-migration.mjs",
"test/cloudflare-worker.mjs", "test/connectors.mjs", "test/chatgpt-image.mjs", "test/autonomy-platform.mjs",
"test/feedback.mjs", "test/feedback-browser.mjs", "test/gmail.mjs", "test/photon.mjs", "test/site.mjs", "test/release-license.mjs",
"test/feedback.mjs", "test/feedback-browser.mjs", "test/gmail.mjs", "test/photon.mjs", "test/site.mjs", "test/release-license.mjs", "test/release-governance.mjs",
"test/channel-surfaces.mjs", "test/workspace-interactions.mjs", "test/sweep-fleet-telemetry.mjs", "test/sweep-server-integration.mjs", "test/thread-followup-chat.mjs",
"test/notifications.mjs", "test/terminal-reconnect-contract.mjs", "test/terminal-reconnect-browser.mjs", "test/web-research.mjs", "test/workflows.mjs"],
];
Expand Down
38 changes: 38 additions & 0 deletions test/release-governance.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import test from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { join } from "node:path";

const root = join(import.meta.dirname, "..");
const read = (path) => readFileSync(join(root, path), "utf8");

test("multi-item releases retain the complete numbered acceptance ledger", () => {
const checklist = read("docs/release-checklist.md");
const lifecycle = read("docs/release-lifecycle.md");
const governance = read("docs/GOVERNANCE.md");
const pullRequest = read(".github/pull_request_template.md");
const notesTemplate = read("docs/release-notes-template.md");

for (const source of [checklist, lifecycle, governance, pullRequest, notesTemplate]) {
assert.match(source, /numbered acceptance\s+ledger/i);
}
assert.match(checklist, /--notes-file "\$RELEASE_NOTES"/);
assert.doesNotMatch(checklist, /gh release create[^\n]+--generate-notes/);
assert.match(notesTemplate, /^1\. \*\*Feature or fix name\*\*/m);
assert.match(notesTemplate, /artifact/i);
assert.match(notesTemplate, /verification/i);
});

test("one retained Mac Studio owns the complete macOS release gate", () => {
const tracked = [
read("docs/release-checklist.md"),
read("docs/release-lifecycle.md"),
read("docs/GOVERNANCE.md"),
read("docs/release-notes-template.md"),
read("CHANGELOG.md"),
].join("\n");

assert.match(tracked, /same retained Apple Silicon release host/i);
assert.match(tracked, /publicly downloaded/i);
assert.match(tracked, /Application Support preservation/i);
});
Loading