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
89 changes: 89 additions & 0 deletions .dev/features/release-0-6-0/GRILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# GRILL — `release-0-6-0`

- Plan: `.dev/features/release-0-6-0/PLAN.md`
- Spec-hash check: PLAN `bca940a5ad247c120e6d8a3acba119d0d8df51dca275964d0e54c48d729d3c4e` matches live
`sha256(ARCHITECTURE.md)` — **no drift**.
- Registered grillers: 0 (count-grillers.mjs returned `{"registered":0,"grillers":[]}`)

---

## Findings

### Axis: Honest scope / missing file (P7)

```yaml
- type: FINDING
rule_id: P7
severity: important
file: ".dev/features/release-0-6-0/PLAN.md:43"
problem: "`package-lock.json` is omitted from `## Files` but it carries the version string in two
places (`version` at the root and under `packages[\"\"]`); both read `0.5.0` live. A direct edit
of `package.json` without updating the lock file leaves the two out of sync — cosmetically
misleading and a latent CI confusion risk (e.g. a `npm ci --strict-peer-deps` run that reads the
lock version for provenance logging)."
evidence: "\"## Files\" lists only `package.json` and `CHANGELOG.md`; `package-lock.json`
is not mentioned."
```

**Grounding (P6 — live, not memory):** `python3 -c "import json; d=json.load(open('package-lock.json')); print(d.get('version'), d['packages']['']['version'])"` → `0.5.0 0.5.0`. The field exists in both locations and requires updating.

**Fix:** Add `package-lock.json` to `## Files` in the plan and update both `"version"` occurrences to `"0.6.0"` during `/pharn-dev-build`. Alternatively, run `npm version 0.6.0 --no-git-tag-version` (which updates both atomically) and verify no unintended changes land.

---

### Axis: Determinism / heading format inconsistency (P5)

```yaml
- type: FINDING
rule_id: P5
severity: minor
file: ".dev/features/release-0-6-0/PLAN.md:28"
problem: "The plan proposes `## [0.6.0] — 2026-09-25` (em-dash U+2014), but the immediately
preceding version heading `## [0.5.0] - 2026-09-10` uses a plain ASCII hyphen-minus (U+002D).
A deterministic rule should choose one character consistently; the inconsistency is cosmetic but
could confuse a reader diffing headings."
evidence: "PLAN line 28: `## [0.6.0] — 2026-09-25`; live CHANGELOG.md L69:
`## [0.5.0] - 2026-09-10`."
```

**Fix (advisory recommendation):** Match the separator used in `[0.5.0]` — use `## [0.6.0] - 2026-09-25`. Alternatively, adopt the em-dash consistently (all prior versions from `[0.4.0]` down use it), and state the choice explicitly.

---

## No other findings

The remaining axes are clean:

- **P0 (guarantee audit):** All four claims in the plan's `## Guarantee audit` carry correct labels
(`advisory` or a named CI floor gate). No guarantee is asserted without a floor reduction.
- **P1 (eval coverage):** The P1 waiver is explicit and reasoned — this increment adds no behavior in
`src/**`; the "no product behavior → no eval" argument is sound. Nothing to surface.
- **P2 (trust audit):** No untrusted artifact is ingested. Both edited files are in-repo, human-authored.
- **P3 (one axis of change):** Both files change for the same reason (release 0.6.0 prep); the axis
is singular. No sibling-import violation.
- **P6 (discovery):** The plan's live-state claims (version string, CHANGELOG line numbers, link defs,
lint result) were independently verified this run and match.
- **P7 (honest scope):** The increment is the minimum release-prep unit. No speculation.

---

## Summary

Two concerns, neither blocking:

1. **`package-lock.json` omitted from `## Files`** (important) — the lock file carries the version
string in two places; leaving it unmentioned risks an out-of-sync build artifact. The fix is one
line in the plan's `## Files` list and two field edits during build.

2. **Heading separator inconsistency** (minor) — the plan uses an em-dash while `[0.5.0]` uses a
hyphen-minus. Cosmetic, but a deterministic rule should choose one.

Neither finding is blocking. The plan's structure, guarantee audit, trust audit, and scope are sound.
The human should read this before `/pharn-dev-build` and decide whether to update the plan or proceed
as-is (e.g. accepting the em-dash if prior consistency with `[0.4.0]` and below is preferred).

---

ADVISORY VERDICT: 2 concerns raised (0 blocking-severity, 1 important, 1 minor) — for the human to
weigh before `/pharn-dev-build`. This is not a guarantee, a gate, or an approval. `/pharn-dev-grill` is
advisory end-to-end.
83 changes: 83 additions & 0 deletions .dev/features/release-0-6-0/PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# PLAN — release 0.6.0 prep

- spec_content_hash: bca940a5ad247c120e6d8a3acba119d0d8df51dca275964d0e54c48d729d3c4e # fix #4
- increment: Bump `package.json` version from `0.5.0` to `0.6.0`, fold `CHANGELOG.md`'s
`[Unreleased]` section (L8–L68) into `## [0.6.0] — 2026-09-25`, restore an empty
`[Unreleased]` scaffold, and update the link definitions.
- layer(s): repo-meta — release documentation + package metadata. This increment touches **no**
layer of the `ARCHITECTURE.md §4` capability tree, no `src/**`, no `tests/**`, and no
`pharn-contracts` schema. Stated so the layer field is honest rather than forced (P7).
- constitution_refs: [P4, P5, P7]

## Context (P6 — grounded in live state, not memory)

Verified this run:

- `package.json` `version`: **`0.5.0`**
- `CHANGELOG.md` `## [Unreleased]` span: **L8–L68** (60 lines; `## [0.5.0] - 2026-09-10` at L69)
- Link definitions (L1394–L1401): `[Unreleased]` points at `compare/v0.5.0...HEAD`; no `[0.6.0]:`
definition exists.
- `markdownlint-cli2 CHANGELOG.md` → **0 issues** — the file is already lint-clean; no style fixes
are needed alongside the fold.
- `git tag` → no `v0.6.0` tag exists; the tag is created by the human when cutting the GitHub Release
(out of scope for this increment).

The release flow per `docs/RELEASING.md`: bump `version` + fold changelog → merge to `main` → human
cuts GitHub Release tagged `vX.Y.Z`. Steps 3–4 are the human's; this increment is steps 1–2 only.

## Files

- `package.json` — change `"version": "0.5.0"` → `"0.6.0"` — layer repo-meta
- `package-lock.json` — update both `"version"` fields from `"0.5.0"` to `"0.6.0"` — layer repo-meta
- `CHANGELOG.md` — rename `## [Unreleased]` → `## [0.6.0] — 2026-09-25`, insert a new empty
`[Unreleased]` scaffold above it, and update link definitions — layer repo-meta

The fold is a **pure mechanical transform** (P5):

1. Replace the `## [Unreleased]` heading at L8 with `## [Unreleased]\n\n## [0.6.0] — 2026-09-25`
(insert empty scaffold; rename the old heading).
2. At the link definitions block:
- Replace `[Unreleased]: …compare/v0.5.0...HEAD` → `compare/v0.6.0...HEAD`
- Insert `[0.6.0]: https://github.com/pharn-dev/pharn-cli/compare/v0.5.0...v0.6.0`
immediately below it.

No entry body is touched; no lines are reordered; the section content is preserved verbatim.

## Contracts satisfied

None — this increment touches no `pharn-contracts` schema. `docs/RELEASING.md` prescribes exactly
this fold (step 2); this increment executes those steps. Cite, don't restate (P4).

## Evals to write (P1)

None — there is no behavior change in `src/**` or `tests/**`. The transform is mechanical (a version
string + two heading/link edits); an eval would test the script, not the product. The existing
`tests/ci-workflow.test.ts` and the `lint:md` gate will cover the structural correctness of the
result (the lint gate rejects a dangling reference; the format check catches JSON drift).

Stated explicitly so P1 is not silently waived: P1 requires a test for every behavior. This increment
has **no** product behavior — it is release metadata. A test asserting `package.json` `version` equals
`"0.6.0"` would be pinning metadata, not testing behavior, and would break on the next release
without protecting anything. Absent, not forgotten.

## Guarantee audit (P0)

- **`package.json` version is bumped** → advisory (the file is written by this increment and
read by the human before the PR merges; no floor mechanism enforces the value is "correct").
- **`CHANGELOG.md` fold is lossless** → advisory. The mechanical rule (above) is deterministic and
stated; a human reviews the diff at the PR gate. No floor checker verifies changelog content.
- **`markdownlint-cli2 CHANGELOG.md` stays at 0 issues** → floor: `npm run lint:md` is a required
CI gate (`.github/workflows/ci.yml` `Markdown lint` job). A dangling reference or duplicate heading
introduced by the fold would fail that gate before merge.
- **`npm run check` stays green** → floor: the CI gates (format:check, lint, lint:md, typecheck,
test, build) are all required status checks on `main`.

## Trust audit (P2)

No untrusted artifact is ingested. All files being edited (`package.json`, `package-lock.json`,
`CHANGELOG.md`) are in-repo, human-authored content. No fetch, no clone, no remote read.

## Open questions (HALT)

None. The version number (`0.6.0`) was given by the human in the task description. The date
(`2026-09-25`) is today's date. The fold rule is unambiguous given the live state verified above.
39 changes: 39 additions & 0 deletions .dev/features/release-0-6-0/REGRESSION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# REGRESSION — release-0-6-0

## Base

`4de071bd0b9a0afb47533777252773ab989c4f99` (HEAD — working-tree dogfood build, base = HEAD per Step 1 rule)

## Inside / Outside Partition

**Inside** (the changed scope):
- `package.json`
- `CHANGELOG.md`
- `package-lock.json`

**Outside tests** (node --test, 46 files): all `.test.mjs` and `.test.cjs` files in `.claude/hooks/` and `.dev/floor/`.

**Outside eval pairs**: none.

**Style gates**: SKIPPED — `inside` does not touch any shared style config (`eslint.config.mjs`, `.prettierrc.json`, `.prettierignore`, `.markdownlint-cli2.jsonc`).

## Per-gate exit codes

| gate | base | head |
| --- | --- | --- |
| `tests` | 0 | 0 |
| `validate` | 0 | 0 |

## Regressions

None.

## Pre-existing failures

None in the outside gate set. (Note: 6 vitest `.test.ts` failures exist in the working tree at both baseline and HEAD — `tests/bounded-read.test.ts` × 1 and `tests/update.test.ts` × 5, all due to `CAP_DAC_OVERRIDE` / root environment — but the vitest suite is not in the outside gates for this increment, which uses `node --test` over the `.test.mjs` / `.test.cjs` files only.)

## Deterministic verdict

**REGRESSIONS: none — no deterministically-detectable breakage outside the feature.**

Honest residual: this verdict catches exactly what the suite catches — nothing more. A regression no deterministic check covers is invisible. The claim is "deterministically-detectable breakage outside the feature is caught," not "nothing broke."
62 changes: 62 additions & 0 deletions .dev/features/release-0-6-0/REVIEW.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# REVIEW — release-0-6-0

**Advisory only. No finding here is a blocking gate. The human decides at GATE 2.**

## Lens 1 — Correctness

The three changed files:

- `package.json`: `"version": "0.5.0"` → `"0.6.0"` — single-field bump, correct.
- `package-lock.json`: both `"version"` fields at root and under `packages[""]` updated to `"0.6.0"` —
lock file is internally consistent with `package.json`.
- `CHANGELOG.md`: `## [Unreleased]` preserved as a scaffold at the top, with the old content moved under
`## [0.6.0] — 2026-09-25`. Link definitions updated: `[Unreleased]` now points at
`compare/v0.6.0...HEAD`, `[0.6.0]` definition added (`compare/v0.5.0...v0.6.0`). No entry body was
touched or reordered.

No correctness finding.

## Lens 2 — Constitution compliance

- **P4 (docs cite code)**: `CHANGELOG.md` documents `0.6.0` features; these match the `src/` changes
in the prior increment (hook-wiring diff, bounded-read, engine floor, etc.). No undocumented behavior.
- **P5 (determinism)**: the version transform is purely mechanical; no branches.
- **P7 (honest scope)**: the version bump and changelog fold are the complete increment. Nothing speculative added.

No violation.

## Lens 3 — Security / trust

No untrusted input is ingested. All three files are in-repo metadata. No network call, no deserialization
of external content, no path join. No security finding.

## Lens 4 — Release-readiness

- `package.json` `version` matches `package-lock.json` versions: both `0.6.0`. ✓
- `CHANGELOG.md` heading separator: `## [0.6.0] — 2026-09-25` uses em-dash (`—`), consistent with
`[0.4.0]` and earlier; `[0.5.0]` uses hyphen-minus (`-`). The separator is cosmetically inconsistent
across the file, but the GRILL found this as a minor advisory and `markdownlint-cli2` permits both.
The style guide for this project is silent on which to use. **Advisory, not blocking.**
- The `[Unreleased]` scaffold is empty — correct for a release commit; it accumulates entries for the
next release after this one.
- No `v0.6.0` tag exists yet — correct; the tag is cut by the human when publishing the GitHub Release
(out of scope for this increment, per `docs/RELEASING.md`).

**One advisory finding:**

```yaml
- type: FINDING
rule_id: P4
severity: minor
file: "CHANGELOG.md"
problem: "Heading separator style is inconsistent: [0.6.0] uses em-dash (—) while [0.5.0] uses hyphen-minus (-); cosmetic only, no behavioral impact."
evidence: "## [0.6.0] — 2026-09-25 vs ## [0.5.0] - 2026-09-10"
```

## Summary

The increment is a clean, mechanical release-prep commit: version bump + changelog fold. All floor gates
pass; no regressions. The one advisory finding (heading separator inconsistency) is cosmetic and inherited
from the prior changelog entry's style.

**ADVISORY VERDICT: 1 minor finding — for the human to weigh at GATE 2. No blocking issues.**
51 changes: 51 additions & 0 deletions .dev/features/release-0-6-0/SHIP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# SHIP — `release-0-6-0`

Gated mode (no `--loop`). Increment: bump `package.json` / `package-lock.json` version from `0.5.0`
to `0.6.0`, fold `CHANGELOG.md`'s `[Unreleased]` section into `## [0.6.0] — 2026-09-25`, restore
an empty `[Unreleased]` scaffold, and update link definitions.

**Note:** mid-chain restart. The initial PLAN.md omitted `package-lock.json` from `## Files`, which
caused a scope breach detected by `/pharn-dev-regress`. The human chose "Update PLAN.md and restart
build." PLAN.md was updated to include `package-lock.json`; the writes-scope was re-set; the build
files were already correct. The pipeline then ran cleanly from `/pharn-dev-regress` onwards.

## Stages run, in order

| # | stage | outcome |
| --- | --- | --- |
| 1 | `/pharn-dev-plan` | `PLAN.md` written; **GATE 1** pre-approved by human |
| 2 | `/pharn-dev-grill` | `GRILL.md` written — advisory, gates nothing |
| 3 | `/pharn-dev-build` | files written, floor GREEN |
| 3a | PLAN.md updated | `package-lock.json` added to `## Files`; scope reset |
| 4 | `/pharn-dev-regress` | `regression-report.json` + `REGRESSION.md` |
| 5 | `/pharn-dev-verify` | `verify-report.json` + `VERIFY.md` |
| 6 | `/pharn-dev-review` | `REVIEW.md` |

**Where the run ended: GATE 2** — the post-review human decision.

## 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"`** |

`/pharn-dev-regress` `.regressions[]` is empty; `/pharn-dev-verify` `.failing_gates[]` is empty and
`verifiers.registered` is `0`.

`/pharn-dev-review` has **no** structural verdict and this command did not invent one. Its four lenses
are advisory; the human reads `REVIEW.md` at GATE 2.

## Pointers

- `.dev/features/release-0-6-0/REVIEW.md` — **read this at GATE 2**; one minor advisory finding
(heading separator cosmetic inconsistency).
- `.dev/features/release-0-6-0/GRILL.md` — advisory pre-build interrogation.
- `.dev/features/release-0-6-0/REGRESSION.md` / `VERIFY.md` — human renders of the two floor verdicts.

---

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. Nothing here is a `PHARN ✓ reviewed`
seal, an approval, or a self-issued "shipped".
21 changes: 21 additions & 0 deletions .dev/features/release-0-6-0/VERIFY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# VERIFY — release-0-6-0

## Floor gates

| gate | exit |
| --- | --- |
| `format:check` | 0 |
| `lint` | 0 |
| `lint:md` | 0 |
| `typecheck` | 0 |
| `validate` | 0 |

## Verifiers

Registered: **0** (no `role: verifier` capabilities in this repo).

## Verdict

**PASS** — all floor gates exit 0; no verifiers registered.

Honest scope: "PASS" means the named gates passed. It does not mean the feature is correct — correctness beyond what those gates check is the human's call at GATE 2.
21 changes: 21 additions & 0 deletions .dev/features/release-0-6-0/regression-report.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"base": "4de071bd0b9a0afb47533777252773ab989c4f99",
"inside": [
"package.json",
"CHANGELOG.md",
"package-lock.json"
],
"outside_gates": {
"tests": {
"base": 0,
"head": 0
},
"validate": {
"base": 0,
"head": 0
}
},
"regressions": [],
"pre_existing": [],
"verdict": "no-regressions"
}
16 changes: 16 additions & 0 deletions .dev/features/release-0-6-0/verify-report.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"feature": "release-0-6-0",
"gates": {
"format:check": 0,
"lint": 0,
"lint:md": 0,
"typecheck": 0,
"validate": 0
},
"verdict": "PASS",
"failing_gates": [],
"verifiers": {
"registered": 0,
"findings": []
}
}
4 changes: 2 additions & 2 deletions .pharn/writes-scope.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"scope": [
".dev/features/init-preflight-first/SHIP.md"
".dev/features/release-0-6-0/SHIP.md"
],
"set_by": ".claude/commands/pharn-dev-ship.md",
"set_at": "2026-09-25T13:42:47.768Z"
"set_at": "2026-09-25T14:32:21.445Z"
}
Loading
Loading