diff --git a/.dev/features/release-0-7-0/GRILL.md b/.dev/features/release-0-7-0/GRILL.md new file mode 100644 index 0000000..0ffad5e --- /dev/null +++ b/.dev/features/release-0-7-0/GRILL.md @@ -0,0 +1,49 @@ +# GRILL — release-0-7-0 + +Plan: `.dev/features/release-0-7-0/PLAN.md`. Spec hash recomputed: +`bca940a5ad247c120e6d8a3acba119d0d8df51dca275964d0e54c48d729d3c4e` — **matches**. Registered +grillers: `{"registered":0,"grillers":[]}` → inline axes only. The plan is `trust: untrusted`; nothing +in it read as an instruction. + +## Findings + +### Honest scope (P7) + +```yaml +- type: FINDING + rule_id: 'P7' + severity: important + file: '.dev/features/release-0-7-0/PLAN.md:26' + problem: 'The version is not free to choose: shipped code and docs from #231 already name 0.7.0 as the boundary ("the format pharn wrote before 0.7.0" — src/lib/models-update.ts, update.ts''s note, status.ts, docs/commands/update.md, docs/reference/pharn-config.md, docs/troubleshooting.md). Releasing under any other number would make every one of those sentences false. 0.7.0 is consistent; the plan should say that this consistency is why the number is fixed, not only that it was given.' + evidence: 'Version: **0.7.0** as the maintainer specified' +``` + +### Guarantee audit (P0) + +```yaml +- type: FINDING + rule_id: 'P0' + severity: minor + file: '.dev/features/release-0-7-0/PLAN.md:61' + problem: 'The tag-equals-version floor fires at release time, after this PR merges, so a wrong bump would be caught only when the release is cut. It is still a floor (the publish run fails before npm ci and publishes nothing), which the plan states correctly; the PR diff is the earlier, advisory check.' + evidence: 'backstopped at release time by `publish.yml`''s floor' +``` + +### Ordering (P6) + +```yaml +- type: FINDING + rule_id: 'P6' + severity: minor + file: '.dev/features/release-0-7-0/PLAN.md:25' + problem: 'pharn-oss will raise MIN_CLI to 0.7.0 only once npm serves 0.7.0 — otherwise every released CLI would be told to upgrade to a version that cannot be installed. That check (`npm view @pharn-dev/pharn version` → 0.7.0) belongs after the publish watch, and the final report must say whether it passed.' + evidence: 'The Release (`gh release create v0.7.0 --target main`) and the publish watch follow its merge' +``` + +## Summary + +A mechanical release fold. The one substantive point: 0.7.0 is fixed by the code it releases, which +already names 0.7.0 as the format boundary. + +ADVISORY VERDICT: 3 concerns raised (0 blocking-severity, 1 important, 2 minor) — for the human to +weigh before /pharn-dev-build. None changes the files or the fold. diff --git a/.dev/features/release-0-7-0/PLAN.md b/.dev/features/release-0-7-0/PLAN.md new file mode 100644 index 0000000..2db660c --- /dev/null +++ b/.dev/features/release-0-7-0/PLAN.md @@ -0,0 +1,63 @@ +# PLAN — release 0.7.0 prep + +- spec_content_hash: bca940a5ad247c120e6d8a3acba119d0d8df51dca275964d0e54c48d729d3c4e # fix #4 +- increment: Bump `package.json` / `package-lock.json` from `0.6.0` to `0.7.0`, fold `CHANGELOG.md`'s + `[Unreleased]` section into `## [0.7.0] — 2026-09-26`, restore an empty `[Unreleased]` scaffold, + and update the link definitions — the release half of roadmap Phase 2.0, after #231. +- layer(s): repo-meta — release documentation + package metadata. No `src/**`, no `tests/**`, no + `pharn-contracts` schema, no layer of the `ARCHITECTURE.md §4` tree (P7: the field is honest, not + forced). +- constitution_refs: [P4, P5, P7] + +## Context (P6 — verified this run, on `origin/main` @ `9bd4e30`, #231 merged) + +- `package.json` `version`: **`0.6.0`**; `package-lock.json` carries it twice (L3, L9). +- `CHANGELOG.md` `## [Unreleased]` spans **L8–L27** (the #231 entries: `### Changed`, `### Fixed`); + `## [0.6.0] — 2026-09-25` at L28. +- Link definitions: L1416 `[Unreleased]` → `compare/v0.6.0...HEAD`; L1417 `[0.6.0]`; no `[0.7.0]:`. +- `git tag -l 'v0.7*'` → none; `gh release list` → latest `v0.6.0`; `npm view @pharn-dev/pharn version` + → `0.6.0`. +- Release flow (`CLAUDE.md` "Releasing", `docs/RELEASING.md`): bump + fold → merge to `main` → GitHub + Release `vX.Y.Z` → `publish.yml` publishes via OIDC. This increment is the bump + fold only. The + Release (`gh release create v0.7.0 --target main`) and the publish watch follow its merge; the + maintainer authorized both on 2026-09-25. +- Version: **0.7.0** as the maintainer specified (a minor bump — #231 changes what `init` writes and + what `update` does to an existing config). Date: **2026-09-26**, today. + +## Files + +- `package.json` — `"version": "0.6.0"` → `"0.7.0"` — layer repo-meta +- `package-lock.json` — both `"version"` fields `"0.6.0"` → `"0.7.0"` — layer repo-meta +- `CHANGELOG.md` — `## [Unreleased]` → a new empty `## [Unreleased]` + `## [0.7.0] — 2026-09-26`; + `[Unreleased]:` → `compare/v0.7.0...HEAD`; insert `[0.7.0]: …compare/v0.6.0...v0.7.0` — layer + repo-meta + +The fold is mechanical (P5): one heading inserted, two link lines touched, no entry body changed or +reordered. + +## Contracts satisfied + +None — no `pharn-contracts` schema is touched. `docs/RELEASING.md` steps 1–2, executed (cited, P4). + +## Evals to write (P1) + +None, stated rather than skipped: the increment changes release metadata, not behavior. A test +pinning `version === "0.7.0"` would pin metadata and break on the next release while protecting +nothing. The structure is still gated: `lint:md` (a dangling link reference fails it), and +`publish.yml`'s own guard refuses a tag that is not exactly `v` + `package.json` `version`. + +## Guarantee audit (P0) + +- **The version is bumped in both files** → advisory (read at the PR), backstopped at release time by + `publish.yml`'s floor: the tag must equal `package.json` `version` or the run fails before `npm ci`. +- **The fold is lossless** → advisory (the diff is reviewed; no checker reads changelog content). +- **`CHANGELOG.md` stays lint-clean** → floor: the required `Markdown lint` CI gate. +- **`npm run check` stays green** → floor: the six required CI gates. + +## Trust audit (P2) + +No untrusted input: three in-repo, human-authored files. No fetch, no clone. + +## Open questions (HALT) + +None. The version was given by the maintainer; the date is today's; the fold rule is fixed above. diff --git a/.dev/features/release-0-7-0/REGRESSION.md b/.dev/features/release-0-7-0/REGRESSION.md new file mode 100644 index 0000000..001ed05 --- /dev/null +++ b/.dev/features/release-0-7-0/REGRESSION.md @@ -0,0 +1,30 @@ +# REGRESSION — release-0-7-0 + +The verdict below is computed by `.dev/floor/check-regress.mjs`, not by this stage's judgment. + +## Base and partition + +- **base:** `9bd4e3052e4a998dfa8b5815801219fd4df5561d` (`HEAD` = `origin/main` after #231; the build is + an uncommitted working tree on top of it). +- **inside:** `CHANGELOG.md`, `package-lock.json`, `package.json` — each declared in `PLAN.md` + `## Files`. `scope` exited **0**, `escaped: []`. +- **outside gates:** the 46 stdlib `*.test.mjs` / `*.test.cjs` files (754 tests) + whole-repo + `validate`; 0 committed eval pairs. No shared style config touched, so the style gates are skipped + on both sides. The base ran in a fresh detached worktree; proxy variables unset on both sides. + +## Per-gate exit codes + +| gate | base | head | flipped? | +| ---------- | ---- | ---- | -------- | +| `tests` | 0 | 0 | no | +| `validate` | 0 | 0 | no | + +- `regressions[]`: **empty** +- `pre_existing[]`: **empty** + +## Verdict + +**REGRESSIONS: none — no deterministically-detectable breakage outside the feature.** +(`regression-report.json` `.verdict` = `no-regressions`.) + +Residual (P0/P7): this catches exactly what its suite catches, nothing more. diff --git a/.dev/features/release-0-7-0/REVIEW.md b/.dev/features/release-0-7-0/REVIEW.md new file mode 100644 index 0000000..108b76d --- /dev/null +++ b/.dev/features/release-0-7-0/REVIEW.md @@ -0,0 +1,25 @@ +# REVIEW — release-0-7-0 + +Floor first: `node .dev/floor/validate.mjs .` → `FLOOR: GREEN`. Everything below is **advisory**. The +increment was read as `trust: untrusted`. + +## Floor-gate findings (blocking) + +None. + +## Advisory findings + +- **L-floor (P0):** no guarantee is claimed beyond the plan's audit. The tag↔version check is + `publish.yml`'s floor at release time; the fold's losslessness is advisory and holds on the diff: + one heading inserted, `[Unreleased]:` repointed to `v0.7.0...HEAD`, `[0.7.0]:` added; no entry body + moved or edited. +- **L-eval (P1):** no behavior changed, so no eval is owed; the omission is stated in the plan, not + silent. +- **L-trust (P2):** no untrusted input. +- **L-axis (P3):** three repo-meta files, one reason (the release). +- **Consistency (P7, from the grill):** 0.7.0 matches every "before 0.7.0" sentence #231 shipped in + code and docs. + +## Verdict + +GREEN floor; 0 floor-gate findings; nothing advisory to fix. diff --git a/.dev/features/release-0-7-0/SHIP.md b/.dev/features/release-0-7-0/SHIP.md new file mode 100644 index 0000000..809a370 --- /dev/null +++ b/.dev/features/release-0-7-0/SHIP.md @@ -0,0 +1,47 @@ +# SHIP — release-0-7-0 + +Gated mode. Increment: bump `package.json` / `package-lock.json` from `0.6.0` to `0.7.0` and fold +`CHANGELOG.md`'s `[Unreleased]` into `## [0.7.0] — 2026-09-26` — the release half of roadmap Phase 2.0 +(#231). + +## Gate decisions — model decisions under delegation, NOT human approvals + +The maintainer delegated plan approval (GATE 1) and the merge/fix decision (GATE 2) to the model on +2026-09-25, and authorized cutting the GitHub release that publishes to npm. Both gates below were +decided by the model (`claude-opus-5-5`) under that delegation; no human approved them. + +| gate | decision (model, under delegation) | +| ------ | ------------------------------------------------------------------------------------------------- | +| GATE 1 | Plan approved as written (version fixed by the maintainer and by #231's "before 0.7.0" wording). | +| GATE 2 | **Merge** once the PR's required checks are green; then `gh release create v0.7.0 --target main`. | + +## Stages run, in order + +| # | stage | outcome | +| --- | -------------------- | ----------------------------------------------- | +| 1 | `/pharn-dev-plan` | `PLAN.md`; GATE 1 (delegated) | +| 2 | `/pharn-dev-grill` | `GRILL.md` — 3 advisory concerns, none blocking | +| 3 | `/pharn-dev-build` | 3 files; `npm run check` GREEN | +| 4 | `/pharn-dev-regress` | `regression-report.json` | +| 5 | `/pharn-dev-verify` | `verify-report.json` | +| 6 | `/pharn-dev-review` | `REVIEW.md`; GATE 2 (delegated) | + +## Structural verdicts read, verbatim + +| stage | verdict source | value | +| -------------------- | ------------------------------------------ | ------------------ | +| `/pharn-dev-build` | `node .dev/floor/validate.mjs .` exit code | `0` | +| `/pharn-dev-regress` | `regression-report.json` `.verdict` | `"no-regressions"` | +| `/pharn-dev-verify` | `verify-report.json` `.verdict` | `"PASS"` | + +This repo has no `pharn.config.json`, so no `models` block assigns stage models: every stage ran on the +session model, `claude-opus-5-5`. + +Pointers: `REVIEW.md` (GATE 2), `GRILL.md` (advisory), `REGRESSION.md` / `VERIFY.md`. + +--- + +The chain ran; the named floor verdicts are as shown — this is NOT a judgment that the increment is +good or wise; that is the human's call at the post-review gate, made here by the model under the +maintainer's explicit delegation and recorded as such. Nothing here is a `PHARN ✓ reviewed` seal, an +approval, or a self-issued "shipped". diff --git a/.dev/features/release-0-7-0/VERIFY.md b/.dev/features/release-0-7-0/VERIFY.md new file mode 100644 index 0000000..0f8be71 --- /dev/null +++ b/.dev/features/release-0-7-0/VERIFY.md @@ -0,0 +1,23 @@ +# VERIFY — release-0-7-0 + +The verdict is computed by `.dev/floor/check-verify.mjs` from gate exit codes. + +| gate | exit | +| -------------- | ---- | +| `test` | 0 | +| `validate` | 0 | +| `lint` | 0 | +| `format:check` | 0 | +| `lint:md` | 0 | +| `typecheck` | 0 | + +`test`: 69 files, 1818 passed, 1 skipped. `npm run build` succeeds and the built CLI prints `0.7.0`. + +**VERIFIED: floor gates PASS** (`verify-report.json` `.verdict` = `PASS`, `failing_gates: []`). + +No verifiers registered — floor gates only. + +--- + +Verified = the named gates passed; this is NOT a guarantee of correctness beyond what those gates +check. diff --git a/.dev/features/release-0-7-0/regression-report.json b/.dev/features/release-0-7-0/regression-report.json new file mode 100644 index 0000000..0516bf1 --- /dev/null +++ b/.dev/features/release-0-7-0/regression-report.json @@ -0,0 +1,21 @@ +{ + "base": "9bd4e3052e4a998dfa8b5815801219fd4df5561d", + "inside": [ + "CHANGELOG.md", + "package-lock.json", + "package.json" + ], + "outside_gates": { + "tests": { + "base": 0, + "head": 0 + }, + "validate": { + "base": 0, + "head": 0 + } + }, + "regressions": [], + "pre_existing": [], + "verdict": "no-regressions" +} diff --git a/.dev/features/release-0-7-0/verify-report.json b/.dev/features/release-0-7-0/verify-report.json new file mode 100644 index 0000000..c662a53 --- /dev/null +++ b/.dev/features/release-0-7-0/verify-report.json @@ -0,0 +1,17 @@ +{ + "feature": "release-0-7-0", + "gates": { + "format:check": 0, + "lint": 0, + "lint:md": 0, + "test": 0, + "typecheck": 0, + "validate": 0 + }, + "verdict": "PASS", + "failing_gates": [], + "verifiers": { + "registered": 0, + "findings": [] + } +} diff --git a/.pharn/writes-scope.json b/.pharn/writes-scope.json index 8d83bba..b872810 100644 --- a/.pharn/writes-scope.json +++ b/.pharn/writes-scope.json @@ -1,7 +1,7 @@ { "scope": [ - ".dev/features/models-pharn-oss-owned/SHIP.md" + ".dev/features/release-0-7-0/SHIP.md" ], "set_by": ".claude/commands/pharn-dev-ship.md", - "set_at": "2026-09-25T22:41:27.905Z" + "set_at": "2026-09-25T22:46:34.573Z" } diff --git a/CHANGELOG.md b/CHANGELOG.md index cf41a2f..2af5290 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] +## [0.7.0] — 2026-09-26 + ### Changed - **The `models` block in `pharn.config.json` now belongs to pharn-oss — its schema and its defaults.** `pharn init` copies pharn-oss's own block, verbatim, from the root `pharn.config.json` of the commit it installs, instead of writing a default of its own. When pharn-oss ships no block, `init` writes none. The CLI's own model ids, effort levels and stage list are gone. The block is checked against pharn-oss's rules instead, through a copy of pharn-oss's checker (`pharn/floor/check-model-config.mjs`) that a test runs against the real one: @@ -1413,7 +1415,8 @@ Next.js project. Exposes both `pharn-cli` and `pharn` bins. `pharn.config.json`. It does not yet install npm packages or scaffold the stack — that is planned for v0.2 (see `docs/roadmap.md` and the `TODO(v0.2)` markers). -[Unreleased]: https://github.com/pharn-dev/pharn-cli/compare/v0.6.0...HEAD +[Unreleased]: https://github.com/pharn-dev/pharn-cli/compare/v0.7.0...HEAD +[0.7.0]: https://github.com/pharn-dev/pharn-cli/compare/v0.6.0...v0.7.0 [0.6.0]: https://github.com/pharn-dev/pharn-cli/compare/v0.5.0...v0.6.0 [0.5.0]: https://github.com/pharn-dev/pharn-cli/compare/v0.4.0...v0.5.0 [0.4.0]: https://github.com/pharn-dev/pharn-cli/compare/v0.3.2...v0.4.0 diff --git a/package-lock.json b/package-lock.json index 3cf8bb9..1f8e9fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pharn-dev/pharn", - "version": "0.6.0", + "version": "0.7.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pharn-dev/pharn", - "version": "0.6.0", + "version": "0.7.0", "license": "Apache-2.0", "dependencies": { "@clack/prompts": "^1.8.1", diff --git a/package.json b/package.json index e35bd14..2b8c24f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@pharn-dev/pharn", - "version": "0.6.0", + "version": "0.7.0", "description": "Audit-grade AI development methodology for Claude Code — spec, plan, grill, build, regress, verify, ship.", "keywords": [ "claude-code",