hstack 0.7.1 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +271 -0
- package/README.md +39 -13
- package/VERSION +1 -1
- package/dist/commands/doctor.js +51 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/update.js +8 -2
- package/dist/commands/update.js.map +1 -1
- package/dist/lib/descriptions.js +167 -0
- package/dist/lib/descriptions.js.map +1 -0
- package/dist/lib/diff.js +1 -1
- package/dist/lib/git.js +16 -0
- package/dist/lib/git.js.map +1 -1
- package/dist/lib/wire.js +108 -4
- package/dist/lib/wire.js.map +1 -1
- package/dist/manifest.js +17 -2
- package/dist/manifest.js.map +1 -1
- package/package.json +3 -1
- package/template/.claude/agents/adversarial-reviewer.md +16 -64
- package/template/.claude/agents/app-architect.md +12 -49
- package/template/.claude/agents/data-architect.md +13 -51
- package/template/.claude/agents/data-specialist.md +5 -50
- package/template/.claude/agents/implementer.md +8 -65
- package/template/.claude/agents/kernel-fit-analyst.md +7 -68
- package/template/.claude/agents/planner.md +7 -42
- package/template/.claude/agents/product-discovery.md +12 -48
- package/template/.claude/agents/product-manager.md +8 -43
- package/template/.claude/agents/researcher.md +5 -41
- package/template/.claude/agents/security-reviewer.md +19 -54
- package/template/.claude/agents/spec-author.md +18 -52
- package/template/.claude/agents/stack-architect.md +14 -43
- package/template/.claude/agents/test-strategist.md +16 -57
- package/template/.claude/agents/ui-ux-briefer.md +6 -36
- package/template/.claude/agents/verifier.md +13 -45
- package/template/.claude/skills/hstack-adr-new/SKILL.md +6 -33
- package/template/.claude/skills/hstack-adversarial-review/SKILL.md +31 -52
- package/template/.claude/skills/hstack-adversarial-review/references/finding-categories.md +157 -0
- package/template/.claude/skills/hstack-app-architecture/SKILL.md +2 -29
- package/template/.claude/skills/hstack-branch/SKILL.md +4 -31
- package/template/.claude/skills/hstack-brownfield-init/SKILL.md +10 -37
- package/template/.claude/skills/hstack-change-new/SKILL.md +4 -31
- package/template/.claude/skills/hstack-change-plan/SKILL.md +21 -32
- package/template/.claude/skills/hstack-commit/SKILL.md +7 -35
- package/template/.claude/skills/hstack-configure/SKILL.md +7 -34
- package/template/.claude/skills/hstack-coord/SKILL.md +3 -39
- package/template/.claude/skills/hstack-data-architecture/SKILL.md +4 -30
- package/template/.claude/skills/hstack-data-review/SKILL.md +3 -42
- package/template/.claude/skills/hstack-finalize/SKILL.md +30 -49
- package/template/.claude/skills/hstack-flag/SKILL.md +9 -48
- package/template/.claude/skills/hstack-greenfield-init/SKILL.md +9 -36
- package/template/.claude/skills/hstack-help/SKILL.md +11 -37
- package/template/.claude/skills/hstack-implement/SKILL.md +28 -58
- package/template/.claude/skills/hstack-kernel-fit-promote/SKILL.md +7 -46
- package/template/.claude/skills/hstack-kernel-fit-scan/SKILL.md +5 -60
- package/template/.claude/skills/hstack-kernel-fit-scan/references/slack-setup.md +42 -0
- package/template/.claude/skills/hstack-kernel-fit-triage/SKILL.md +12 -50
- package/template/.claude/skills/hstack-module-spec/SKILL.md +5 -32
- package/template/.claude/skills/hstack-product-discovery/SKILL.md +5 -31
- package/template/.claude/skills/hstack-research/SKILL.md +3 -33
- package/template/.claude/skills/hstack-scaffold/SKILL.md +2 -29
- package/template/.claude/skills/hstack-security-review/SKILL.md +5 -43
- package/template/.claude/skills/hstack-ship/SKILL.md +43 -53
- package/template/.claude/skills/hstack-stack-decide/SKILL.md +3 -30
- package/template/.claude/skills/hstack-story-draft/SKILL.md +6 -33
- package/template/.claude/skills/hstack-tech-debt-new/SKILL.md +4 -31
- package/template/.claude/skills/hstack-tech-debt-resolve/SKILL.md +9 -44
- package/template/.claude/skills/hstack-tech-debt-stale/SKILL.md +10 -37
- package/template/.claude/skills/hstack-tech-debt-wontfix/SKILL.md +8 -35
- package/template/.claude/skills/hstack-telemetry/SKILL.md +5 -30
- package/template/.claude/skills/hstack-test-plan/SKILL.md +23 -46
- package/template/.claude/skills/hstack-ui-brief/SKILL.md +3 -30
- package/template/.claude/skills/hstack-verify/SKILL.md +26 -48
- package/template/KERNEL.md +410 -0
- package/template/scripts/compute-merge-readiness.mjs +780 -0
- package/template/scripts/run-gates.sh +388 -0
- package/template/scripts/telemetry/insights/kernel_fit.py +1 -1
- package/template/scripts/telemetry/insights/token_economics.py +181 -8
- package/template/scripts/telemetry/parsers/sidecars.py +61 -0
- package/template/scripts/telemetry/parsers/transcripts.py +135 -22
- package/template/scripts/telemetry/render.py +68 -3
- package/template/scripts/telemetry/report.py +16 -4
- package/template/scripts/telemetry/run_kernel_fit.py +6 -2
- package/template/scripts/telemetry/session_id.py +139 -0
- package/template/scripts/validate-spec.mjs +3303 -0
- package/template/templates/adr.md +7 -0
- package/template/templates/adversarial-review.md +5 -5
- package/template/templates/ci-cd.md +14 -0
- package/template/templates/coord-message.md +3 -2
- package/template/templates/data-architecture.md +3 -6
- package/template/templates/kernel-fit-finding.md +2 -2
- package/template/templates/kernel-fit-flag.md +2 -2
- package/template/templates/plan.md +4 -0
- package/template/templates/product-brief.md +2 -2
- package/template/templates/roadmap.md +41 -0
- package/template/templates/security-review.md +1 -1
- package/template/templates/telemetry-sidecar.md +56 -13
- package/template/templates/test-plan.md +1 -1
- package/template/CLAUDE.md +0 -443
- package/template/templates/mvp-scope.md +0 -34
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,277 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to hstack are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning follows [SemVer](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## [0.16.0] - 2026-08-21
|
|
6
|
+
|
|
7
|
+
The micro-prescriptions come out (ADR-0014). hstack's prose carried a layer of instruction written for a model that needed to be told how to think — a findings quota, character thresholds standing in for substance, keyword blocklists standing in for intent, and interview scripts that had to be read out even when they did not fit the product. Fifteen prescriptions across five families are each replaced by one of three things: **a stated goal**, **a rubric loaded on demand**, or **an executable rule in the validator**. The ledger records which form each took and why.
|
|
8
|
+
|
|
9
|
+
This is the first release in the context-engineering sequence that changes what the models **produce**, not only what they read. ADR-0010 through ADR-0013 moved bytes between files and the artifacts came out the same shape. This one changes the contract on three artifact types and the interview shape of two discovery atoms — which is why it ships **one commit per family**, so ADR-0009's per-phase instrumentation can attribute a regression to a family rather than to the release.
|
|
10
|
+
|
|
11
|
+
**What does not move is named and closed.** The article's carve-out (*except in highly important areas*) is applied by an operational test: a prescription is kept verbatim when the exact wording **is** the mechanism, not a description of one. Untouched: test immutability and its four canonical authorization phrases, the implementer's scope-lock, tenant isolation (DR-03 / TS-03), implementer-vs-reviewer session isolation, forbidden tools, and the human gate on kernel changes. Two keyword blocklists are removed and a third is kept — the distinguishing test is whether the listed strings are the hazard (`service_role` in agent code) or a correlate of it (`next quarter` in a wontfix rationale).
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- **The findings floor stops being a gate (AR-01).** The rule no longer counts. It fires on the one count that is a claim: a review reaching `findings-open` / `findings-resolved` with an **empty** `findings` array must set `findings-fewer-than-floor: true` and defend the empty result. Any count above zero passes. The file admitted its own motive — *"LLM reviewers will default to 'looks good' without pressure"* — and the quota needed three counter-mechanisms to survive it: the sub-floor escape ritual, the category-spread distribution rule, and a `halt rather than padding findings` stop condition warning against the incentive stated two rules above it. All three come out with the quota. `findings-floor`, `findings-fewer-than-floor` and `justification-when-fewer` stay in frontmatter and in the sidecar so ADR-0009's time series keeps its keys across the 0.15 / 0.16 boundary; **AR-06 is unchanged** and keeps the declared value honest. The twelve merge gates are untouched — GT-04 reads the review's status, never its finding count.
|
|
16
|
+
- **Three substance proxies lose their character bounds.** `dismissed-reason >= 50` (KF-05) is demonstrably weak in both directions: `"not relevant"` four times over is 51 characters and passes, while `"the kernel gives a norm here, not a bound"` is 41, is the whole answer, and fails. It becomes a re-evaluability judgment in `/hstack:kernel-fit-triage`. `wontfix-reason <= 200` and `stale-verification-method <= 300` go the same way, and the stale Skill's *"if you can't tighten it below 300, it is probably a wontfix"* heuristic is replaced by the test it was proxying: could a third party run, read or look up what the answer names?
|
|
17
|
+
- **The two tech-debt closure Skills state the intent instead of listing eleven words.** The lists failed in both directions — *"we accept the 50ms until the v2 substrate lands next quarter"* is a correct wontfix that trips them, and *"the cost-benefit does not favour action"* is a deferral that clears them; the wontfix Skill's own step 4 offers a model answer whose sibling would trip its own step 3. Now: **wontfix** = the problem is real and we are choosing to live with it, so an answer that describes a future in which we fix it leaves the item `open`. **stale** = the problem no longer exists and a third party could verify that.
|
|
18
|
+
- **`data-architect` and `app-architect` follow the `stack-architect` pattern**, which was already the right shape in the corpus — goal-shaped rules, prompts labelled as *Example prompts*, and one named reasoned exception. `data-architect`'s tenancy taxonomy stops being a mandatory walk: the goal is unchanged and still hard (one concrete noun from this product's own vocabulary, with a rule for who is inside one, tied to a persona), but A/B/C become examples offered when they help. A product whose tenant is a project, a device, a contract or a site is ordinary and none of the three fit it. `app-architect`'s *"flows that say the AI handles it end-to-end are rejected"* is restated against the defect it aimed at — the undeclared boundary — with the exception spelled out. `data-architecture.md`'s Pattern A/B/C/D block is rewritten to match. The RLS two-category rule is untouched; it is a tenant-isolation guard.
|
|
19
|
+
- **The three challenge prompts stay mandatory and stop being verbatim.** SR-02, TS-02 and `product-discovery`'s three forcing reframes remain exactly as required as they were. What goes is the word *verbatim* — verified in code before removing it, since both rules locate answers by the `(a)` / `(b)` / `(c)` heading prefix and never match prompt text. A probe that cannot adapt probes worse: *"cite the line of code that enforces tenant isolation"* has no referent on a change touching no tenant-scoped path, where the sharper question is which call site would have to move for that to stop being true. The templates' wording becomes the canonical form; the heading records what was actually asked, and the prefix stays.
|
|
20
|
+
- **The adversarial-review telemetry sidecar stops describing itself as a fraud detector.** Its three joint fields existed to *"surface findings-quota-gaming patterns no single field could detect"*. With the quota gone they are a description of what reviews find, and the `findings_count / findings_floor` distribution is the primary read.
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- **`hstack/.claude/skills/hstack-adversarial-review/references/finding-categories.md`** — the six-category calibration rubric, loaded on demand rather than carried inline. What each category means, what a real finding in it looks like, what filler looks like, and how severity calibrates. Second instance of the `references/` pattern after `hstack-kernel-fit-scan/references/slack-setup.md`.
|
|
25
|
+
- **FL-01 mechanizes the `hint` cap.** The flag hint was named as a format constraint (one token, <= 32 chars) in `/hstack:flag` and enforced nowhere. It is now checked, along with the single-token shape, on every validator run. No new rule id; one clause on an existing rule and one fixture.
|
|
26
|
+
|
|
27
|
+
### Known limitations
|
|
28
|
+
|
|
29
|
+
- **The failure mode of this release is invisible in the diff.** Every previous ADR in the sequence could be checked by reading — the bytes either moved correctly or they did not. Whether a reviewer told *"'no problems' is a claim you have to defend"* finds fewer real problems than one told *"produce three"* cannot be read off the diff and cannot be measured until enough reviews have run in moso-app for `findings_count` to have a distribution.
|
|
30
|
+
- **The floor was doing something, and "it induced filler" is an argument, not a measurement.** No review has ever landed under floor with a defended justification, so the escape hatch has never been exercised and the padding it was written against has never been observed. Both the rule and its removal rest on the same absence of evidence — and a reviewer that now returns two low-severity findings on an `auth` change passes AR-01 where it previously would not have.
|
|
31
|
+
- **Freeing the prompt wording removes the only thing that made a weak answer visible.** With the canonical prompt in the heading, a reader comparing two security-reviews could see that one answered an easier question. Adapted-to-probe-harder and adapted-to-probe-softer now produce the same artifact shape.
|
|
32
|
+
- **This release makes the corpus bigger; the previous four made it smaller.** Measured against `main`: agent and Skill bodies **+1,340 words**, templates **+297**, the validator's rule descriptions **+209**, plus **1,104 words** of new on-demand rubric. `KERNEL.md` is flat — the one word that changed (`quota` -> `cold read`) is a wash, so the always-loaded surface pays nothing. Goal-framing is simply more verbose than a number, and ~2.1k tokens come back onto the invocation path.
|
|
33
|
+
- **`hstack-adversarial-review`'s description still says "quota-driven".** Zero bytes of `description:` change in this release, by constraint — the ADR-0011 routing surface is not something a behavioural PR should touch. The consequence is a routing trigger that describes a mechanism the Skill no longer has, and it stays wrong until a description pass picks it up.
|
|
34
|
+
- **`npm test` is 223 checks, up from 222.** The delta is one new fixture for the newly-mechanized `hint` cap. The AR-01 and KF-05 fixtures were rewritten in place to match their rules' new contracts — below the floor and a too-short reason are now passing states.
|
|
35
|
+
|
|
36
|
+
## [0.15.0] - 2026-08-21
|
|
37
|
+
|
|
38
|
+
Three enforcements that were decided and never shipped. No new ADR — each contract already existed in the repo, stated in one place and enforced in none: GT-01..GT-12 named by `hstack-ship` and deferred by the validator registry to "the PR diff and the CI run"; `run-gates.sh` stubbed as `{{TODO-SCRIPT}}` in `verifier` and `hstack-verify`; ADR-0011's Option F, a `description-budget` finding, deliberately held back because "a linter for a size that no file currently respects would flag 52 findings on day one". The rewrite shipped in 0.14.0, so day one has passed.
|
|
39
|
+
|
|
40
|
+
Two of the three replace prose with a script. `hstack-ship` was carrying ~700 words of frontmatter arithmetic that a Skill had to execute by reading; `verifier` — which runs on haiku — was carrying a 300-word paragraph teaching it to parse Jest, Playwright and pytest summary lines by eye. Both were scripts written in prose. The Skills keep the gates as a **contract** (one line per gate); the scripts carry the computation, so the two cannot drift into two different answers.
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
- **`hstack/scripts/compute-merge-readiness.mjs` — the twelve-gate merge-readiness scorecard.** Computes GT-01..GT-12 from artifact frontmatter, the diff against the merge target, and the git branch. Same shape as `validate-spec.mjs`: dependency-free ESM, a declarative registry (`--gates` prints it), `--json`, exit 0/1/2. The declared name was `.ts`; renamed to `.mjs` on the ADR-0001 reasoning that made `validate-spec` plain ESM — consuming repos have no `node_modules` for hstack, so a `.ts` entrypoint would impose a runtime on every consumer. All references renamed in the same pass. Five verdicts rather than two: `pass`, `fail`, `not-applicable`, `deferred`, and `unknown` — and `unknown` blocks exactly like `fail`, because "not evaluated" is not "passed" (the rule V-05 applies to a suite that executed zero tests).
|
|
45
|
+
- **`hstack/scripts/run-gates.sh` — the canonical test / lint / typecheck runner.** Reads the commands from `ci-cd.md` § Canonical Commands, runs every one and nothing else, captures combined stdout/stderr to the pointer file `verification.artifacts.test-output` names, and emits an **observed-test-count per suite** for V-05. POSIX tools only — no jq, no node — for the same dependency-free reason. "Executed" is `passed + failed`, not `total`: a run that collected fifteen tests and skipped all fifteen executed nothing, which is the case V-05 exists for.
|
|
46
|
+
- **`ci-cd.md` § Canonical Commands.** A fenced `hstack-gates` block, one `suite: command` pair per line, that `run-gates.sh` parses. The fence is the contract: the rest of `ci-cd.md` is prose written for humans, and a runner that guessed at prose would produce a confident wrong answer about what the repo's tests are. A consumer whose `ci-cd.md` predates the block gets exit 2 and a message naming `/hstack:configure --interview ci-cd` — degradation with a stated cause, never a guess.
|
|
47
|
+
- **`hstack doctor` finding: `description-budget` (ADR-0011 Option F).** Flags any Skill or subagent description over 40 words (or 300 characters — the ADR's "~250" with its tilde honoured), level `warn`, with one named carve-out in code: `hstack-coord`, at 84 words, the only description that routes with no human typing anything. Measured against the **package** template, not the consumer's copy: the consumer's files are framework files `framework-drift` already diffs, and a budget finding there would be a second report of the same thing. Zero findings on the current template.
|
|
48
|
+
- **Three test suites, 117 new checks** (`test-merge-readiness.mjs`, `test-run-gates.mjs`, `test-description-budget.mjs`), and the same meta-check `test-validate-spec.mjs` uses: a gate with no failing fixture fails the suite. The canonical clean tree moved to `scripts/fixtures/clean-tree.mjs` so the gate suite and the rule suite score the same artifacts instead of drifting apart on the first schema change. `npm test` now builds first (`pretest`) — the description scanner is TypeScript.
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- **`hstack-ship` step 2 is an invocation, not an arithmetic lesson.** The twelve gates stay in the Skill as a one-line-each contract table, with `compute-merge-readiness.mjs` named as the only place they are computed. The Category-B audit-chain assumption and the SP-13/SP-14 halves are stated once, in the script's registry, and surfaced verbatim in its output.
|
|
53
|
+
- **`verifier`'s V-05 rule stops teaching runner parsing.** The rule keeps its whole meaning — zero executed tests is `not-run`, `not-run` blocks `status: passed`, lint and typecheck are exempt — and delegates the measurement. Its stop conditions gain the "no `hstack-gates` block" case.
|
|
54
|
+
- **`src/manifest.ts`** ships `scripts/compute-merge-readiness.mjs` and `scripts/run-gates.sh` alongside `scripts/validate-spec.mjs`; the executable bit survives the copy.
|
|
55
|
+
- **The validator's deferred registry tells the truth about where GT-* went.** `GT-01..GT-12` now points at `compute-merge-readiness.mjs --gates` rather than at a named follow-up.
|
|
56
|
+
|
|
57
|
+
### Known limitations
|
|
58
|
+
|
|
59
|
+
- **CG-01..CG-04 are still unimplementable, and that is now a two-release fact.** `hstack-ship` names the range (`GT-09: every cross-reference rule (CG-01..CG-04) passes`); no source in the repo states what the four rules are. GT-09 reports `deferred` with that reason rather than inventing them or silently passing. Defining the four statements is a kernel change — after two enforcement passes have declined to guess, it is a **kernel-fit candidate**, not a TODO in a script.
|
|
60
|
+
- **GT-03 is `not-applicable` in every consumer today.** No repo ships `hstack/lints/*.yaml`; moso-app has the directory and it is empty. The gate is wired end-to-end (`run-gates.sh` exit code → `--gates-exit`) and will start scoring the moment a rule file exists, but it is enforcing nothing right now and the scorecard says so.
|
|
61
|
+
- **GT-02's workflow-owned carve-out is a judgment, not a derivation.** `hstack/specs/changes/<this-id>/`, `adr/`, `tech-debt/`, `kernel-fit/`, `coord/`, `research/` and `telemetry/reports/` are exempt from the in-scope check because every Skill's auto-commit lands in one of them; a gate that failed on the artifacts the workflow just wrote would be switched off within a week. The list is named in code so it is reviewable, but it is wider than the kernel's § Scope rules text, which speaks only of the implementer's write boundary.
|
|
62
|
+
- **`compute-merge-readiness.mjs` reads the working tree, not the PR.** It diffs against the merge-base including uncommitted and untracked files, because ship runs *before* the PR exists. A first real run against moso-app scored three shipped changes correctly and flagged an untracked `.env.preview` as out-of-scope on all three — right by the gate's definition, noisy on a post-merge tree. The honest reading is that the gate is built for pre-merge use and reports faithfully outside it.
|
|
63
|
+
- **The description budget cannot see the thing it is protecting.** ADR-0011 already recorded this: cutting descriptions optimises the typed routing path at the expense of the described one, and ADR-0009's attribution counts only structured markers, which *are* the typed path. This finding stops the size regressing; it says nothing about whether routing works.
|
|
64
|
+
|
|
65
|
+
## [0.14.0] - 2026-08-21
|
|
66
|
+
|
|
67
|
+
The kernel keeps ownership of every rule and gives up the mode d'emploi (ADR-0013). ADR-0012 established that the kernel **owns** each rule; this release fixes what OWNS costs: the statement of authority — what the rule is, why it is load-bearing, what its carve-outs are — plus a pointer to the file that runs it. Not the step-by-step. `KERNEL.md` goes from **8,940 words / 66,213 bytes / ≈ 13.7k tokens to 6,370 / 45,748 / ≈ 9.5k (−28.7%)** — the only body in the corpus with no progressive disclosure at all, loaded at turn zero of every session and again in full inside every one of the 16 subagents. A change that spawns five subagents pays it six times, so the per-change saving is ≈ 25k tokens, not ≈ 4.2k.
|
|
68
|
+
|
|
69
|
+
This **amends ADR-0012; it does not contradict it.** OWNS / STATES / REFERENCES is unchanged. Nothing ADR-0012 consolidated into the kernel one commit earlier — the 16 reconciled session-start load lists, § Session boundaries, § Halt sentinel — was a candidate.
|
|
70
|
+
|
|
71
|
+
No rule is deleted. Every passage removed from the kernel is present in its destination file in the same commit, and every rule id that left the kernel is present in the validator registry or at its enforcement point (5 ids: CM-02, GT-01, GT-12, TD-06, TD-07 — all verified).
|
|
72
|
+
|
|
73
|
+
### Changed
|
|
74
|
+
|
|
75
|
+
- **§ Tech-debt resolution: 1,067 → 328 words.** The kernel keeps the three terminal exit paths, both reciprocal pairs with their atomicity, the ban on hand-editing the status machine, TD-03 immutability and the ruling that partial resolution is unsupported. The six-step resolution flow, the wontfix two-question interview and the stale one-question interview are `hstack-tech-debt-resolve` / `-wontfix` / `-stale` / `hstack-finalize`'s orchestration steps, already stated there.
|
|
76
|
+
- **§ Mechanical operations: 1,600 → 735 words.** Keeps the boundary (*if the Skill knows the value before invoking, the Skill writes; if it comes from a conversation, `spec-author` runs it*), the subagent-vs-orchestrator reading, the `app-architect` stub carve-out, the taxonomy, and the discipline rules. Drops the twelve-bullet enumeration of which Skill writes which field, the worked structured-elicitation examples, the paragraph describing the validator's own capabilities (`--rules` prints it from the registry that enforces it), and the telemetry-sidecar paragraph. The `Atomicity for reciprocal pairs` label is preserved verbatim — `hstack-kernel-fit-promote` cites it by name.
|
|
77
|
+
- **§ How hstack improves itself: 649 → 246 words.** Keeps the non-negotiable contract (the human gates promotion; the analyst never authors an ADR) and the named Slack carve-out from the MCP-unreachable stop condition. The five layer descriptions restated the three kernel-fit Skills, `hstack-flag` and `kernel-fit-analyst.md`.
|
|
78
|
+
- **§ Cross-session coordination: 535 → 342 words.** Keeps pull-over-committed-state, message immutability, the *committed-and-auditable, not delivered* guarantee, and the whole Boundaries paragraph — it binds subagents. The registry path, `hstack/coord/NAME` resolution, scan invocation, ack cursor, hook wiring and `events.jsonl` are `hstack-coord`'s.
|
|
79
|
+
- **§ Frontmatter contract: 487 → 332 words.** Keeps the shared floor, the naming rules, `revisits-change`, and the three no-story carve-outs by name with SP-13 mutual exclusion and the audit query. The per-category prose moves to `spec-author`, which runs the interview.
|
|
80
|
+
- **§ Consuming-repo wiring: 215 → 88 words.** The symlink add / remove / rename table had no home outside the kernel, so it lands in `README.md` § Maintenance in the same commit. The kernel keeps the obligation that fires it.
|
|
81
|
+
- **§ Test immutability: 719 → 671 words — substantially kept, deliberately.** The arbitration is recorded in ADR-0013: this rule has no validator id (not even a deferred one — it constrains behaviour, not artifacts), its violation is silent and ships, and ADR-0012 thinned it from 17 statements to 2 one commit ago. Only the **Enforcers** map moves, to a one-sentence index; all four duties are stated in full in `implementer.md`, `verifier.md`, `adversarial-reviewer.md` and `test-strategist.md`.
|
|
82
|
+
- **Eight smaller compressions:** Product context's document catalogue and promotion-routing paragraph (**the reconciled session-start load lists below them are untouched**), § Status lifecycle's Skill enumeration, § AI writes / humans confirm's restatement of the mechanical contract, § Resumability's harness-behaviour paragraph, § Branch hygiene's three enforcement moments, § Stop conditions' INF-04/INF-05 prose, § What hstack is, § v1 / v2 split.
|
|
83
|
+
- **Frontmatter descriptions are untouched.** Zero bytes changed across all 52 files, verified byte-for-byte.
|
|
84
|
+
|
|
85
|
+
### Added
|
|
86
|
+
|
|
87
|
+
- **`KERNEL.md` § Reading artifacts (new, ~70 words).** Frontmatter first, then the sections the task needs; a whole-artifact read requires a reason, and the reason is that the task is about the whole artifact. The kernel already required this for a *peer's* committed state and said nothing about the local tree — a transcript audit found 277 reads over 8k characters, 28% of total session text volume, with `spec.md` read end-to-end 41 times where the reader needed `status` and `in-scope`. The rule names its legitimate full-read cases in the same breath (the adversarial-reviewer's audit, code within `in-scope`, a subagent's session-start loads, the print-a-TD-in-full step). Applied at `hstack-help --change`, `hstack-ship` step 1 and `hstack-implement`'s precondition sweep.
|
|
88
|
+
- **`README.md` § Maintenance → Adding or removing a Skill or subagent.** The per-symlink obligations, as a table.
|
|
89
|
+
|
|
90
|
+
### Fixed
|
|
91
|
+
|
|
92
|
+
- **The Notion "template schemas" doc loses its authority.** The kernel cited it three times, once as a hard gate (*"Read it before any template instance is authored"*). An audit on 2026-08-15 found it pre-dates the Categories work, still carries `mvp-scope` (removed by ADR-0008), and is missing ~9 artifact types the repo ships templates for. v0.12.0's validator registry had already ruled independently — its deferred entries for AR-03 and SP-01..SP-03 say those ids *"exist only in the diverged Notion schema doc, which is not authoritative."* The kernel and the validator disagreed; the validator was right. `hstack/templates/<type>.md` (structure) and `validate-spec.mjs --rules` (mechanized rules + named deferrals) are now explicitly canonical. The gate is deleted, the schema link removed from References, and the architecture doc and adversarial review marked non-authoritative. `spec-author`, `hstack-help` and `README.md` carry the same correction.
|
|
93
|
+
- **A sixteenth diverged copy, found by doing this pass.** `spec-author`'s no-story interview is the pre-Categories version — its "(C)" is *"there is actually a user story"*, not `area: bootstrap` — and its SP-09 output expectation omits Category C entirely. `hstack-ship`'s GT-08 has the same gap. Both corrected *before* the kernel's copy was thinned, per ADR-0012's reconciliation-before-deletion rule. ADR-0012's audit did not look at this side of the pair.
|
|
94
|
+
- **`hstack-tech-debt-stale` no longer says TD-07 must pass "once the validator ships".** It shipped in 0.12.0.
|
|
95
|
+
- **`hstack-version: v0.6.0` removed from the kernel's frontmatter.** Wrong through seven releases, which is the evidence that nothing reads it — no Skill, no subagent, no script, no installer greps for it. The root `VERSION` file is the single source and `hstack update` diffs the tree, not the field. Deleted rather than corrected: a stale version string answers "what version is this?" confidently and wrongly. `authority: kernel` stays.
|
|
96
|
+
|
|
97
|
+
### Known limitations
|
|
98
|
+
|
|
99
|
+
- **Second consecutive PR thinning the same corpus, with no measurement between them.** 0.13.0 shipped the same day and has not been exercised in a real change run. If adherence regressed there, this release is layered on an unvalidated one and ADR-0009's instrumentation will attribute the pair, not each half.
|
|
100
|
+
- **The kernel is loaded by every subagent, which is why some of its bloat was load-bearing.** A passage moved to a `SKILL.md` is invisible to all 16. Each ledger row carries an explicit subagent check; it found three cases where the passage stayed. It cannot prove it found all of them.
|
|
101
|
+
- **The read-discipline rule is evidenced on cost, not on harm.** 277 oversized reads is a token fact; nothing shows any of them produced a worse outcome. Under-reading a spec is silent and produces a plausible wrong answer; over-reading costs tokens and produces a right one. The asymmetry does not favour the rule, which is why it ships with its carve-outs named inline.
|
|
102
|
+
- **The target was ~4,500 words and this lands at 6,370.** The gap is the two blocks ADR-0013 declines to touch — § Test immutability (671) and the 16 reconciled session-start load lists (~590) — plus ~600 that would have to come out of § Mechanical operations' carve-outs. Reported as found, not met. If 4,500 is still wanted, the honest route is splitting the kernel (ADR-0013 Option B), not a deeper cut here.
|
|
103
|
+
|
|
104
|
+
### Consumer action required
|
|
105
|
+
|
|
106
|
+
- Run `npx hstack@latest update`, then commit. `KERNEL.md`, `README.md` and 6 framework files are overwritten in place. No installer change, no manifest change, no symlink change, no `doctor` finding.
|
|
107
|
+
|
|
108
|
+
## [0.13.0] - 2026-08-21
|
|
109
|
+
|
|
110
|
+
Every rule in the corpus has exactly one normative statement (ADR-0012). The kernel **owns** each rule, the single file where the rule can actually be violated **states** it operationally, and every other file **references** it in one line. The 52 `## Anti-patterns` sections are gone, and the duplicated protocol restatements, session-start load lists, session-boundary blocks and telemetry-sidecar paragraphs collapse to their canonical home. No rule is deleted, no gate moves, no status lifecycle changes. Unblocked by 0.12.0: the artifact validator makes every rule with an id executable, so the repeated prose that was compensating for its absence is no longer the enforcement net.
|
|
111
|
+
|
|
112
|
+
The finding that carried the change: **15 of the 16 session-start load lists had already diverged** between `KERNEL.md` and their agent file, and in two cases each side named a load the other was missing. Those were reconciled into the kernel *before* any copy was deleted.
|
|
113
|
+
|
|
114
|
+
### Changed
|
|
115
|
+
|
|
116
|
+
- **`template/KERNEL.md` § Product context — the load lists are reconciled and authoritative.** `security-reviewer` gains the change-spec and the In-Scope diff (the kernel named 5 documents; the agent file named 8). `implementer` gains the tech-debt artifacts named by `resolves-tech-debt` — AR-07 audits the diff against their Acceptance section — and the relevant module-spec, and keeps `infrastructure.md`, which the agent file had dropped; neither list was a superset of the other. Thirteen further entries gain their mode-conditional loads (session-state on resume, extract-mode sources, precedent artifacts, MCP-derived state). "The kernel is loaded by every subagent, always" is now stated once instead of being asserted in 12 of 16 agent files and 5 of 16 kernel entries. `stack-architect` needed no change — the only list of the sixteen whose two copies agreed.
|
|
117
|
+
- **`template/KERNEL.md` § Session boundaries (new).** Takes ownership of the cut-notice format, the kickoff-prompt template, the context-block rules and the never-cut-mid-phase rule — a 1,491-byte block that was byte-identical in 7 Skills with no owner anywhere in the corpus. Each Skill keeps its own cut notice and next command.
|
|
118
|
+
- **`template/KERNEL.md` § Mechanical operations — Resolution Log appends gains the defensive log-header clause.** Six Skills carried that paragraph inline in four slightly different wordings; they now carry six identical one-line actions.
|
|
119
|
+
- **`template/templates/telemetry-sidecar.md` stops describing itself as a document the five Skills restate.** It already declared itself canonical and predicted the copies would disagree. The five emitting Skills keep their own JSON schema block and the executable step-0 call, and reference it for the field rules. Per ADR-0009 the three phase-window fields must read identically in all five, so all five carry the same pointer sentence byte-for-byte.
|
|
120
|
+
- **16 subagent bodies: 24,828 → 21,540 words (−13.2%).** Anti-patterns sections removed; session-start lists replaced by a pointer to the reconciled kernel list, keeping only what the kernel does not carry (the ui-ux-briefer's per-source design-system resolution, the data-specialist's MCP access-mode check, the kernel-fit-analyst's detector-blob shape, each file's own halt clause). Test immutability is now stated once, at its enforcement point (`implementer.md`); `verifier`, `adversarial-reviewer` and `test-strategist` keep their own detection duties and point at the kernel for the protocol and the canonical authorization phrases — 17 restatements become 1 statement plus 3 duties. Session-isolation and v1/v2 framing appear once per file instead of 5–6 times.
|
|
121
|
+
- **36 `SKILL.md` bodies: 48,690 → 42,914 words (−11.9%).** Anti-patterns sections removed; `finalize`'s TDs-first ordering argued once instead of 5 times; the "never invoke `spec-author`, it costs ~25k tokens" justification returns to the kernel alone; `hstack-implement`'s scope-lock stated twice (the Files-Touched precondition and the subagent invocation) instead of 7 times.
|
|
122
|
+
- **Frontmatter descriptions are untouched.** ADR-0011 settled that surface; reopening it here would confound two changes. All 52 files parse, every `name` and `description` is byte-identical to 0.12.0.
|
|
123
|
+
|
|
124
|
+
### Fixed
|
|
125
|
+
|
|
126
|
+
- **`hstack-implement` had two orchestration steps numbered 8.** Corrected while editing the section.
|
|
127
|
+
|
|
128
|
+
### Known limitations
|
|
129
|
+
|
|
130
|
+
- **The validator's coverage is narrower than the deletion.** It backs artifact-shape rules only. Test immutability, scope-lock, the forbidden-tools enumeration and session isolation have no validator id — the registry names why — so for those the prose is still the only net. This release thins that prose from N statements to one on the argument that N statements were not N nets, and that argument is sound but untested. If adherence regresses, the fix is a mechanism (a hook, a CI check on test-file diffs, a validator extension against git history), not restoring the copies.
|
|
131
|
+
- **The reconciliation step is a behaviour change inside a dedup.** Fifteen load lists got a winner picked; two of those changes alter what a subagent actually reads. The PR ledger names every arbitration; prose read by a human is the weakest enforcement the framework has.
|
|
132
|
+
- **One duplicate is kept deliberately.** The forbidden-tools enumeration appears in both `hstack-implement` and `implementer.md`. The Skill orchestrator runs in the main session and does not load the agent file, so a pointer there would not resolve, and moving the list to the kernel would grow a 100%-loaded file to shrink one that is not.
|
|
133
|
+
|
|
134
|
+
### Consumer action required
|
|
135
|
+
|
|
136
|
+
- Run `npx hstack@latest update`, then commit. All 52 framework files plus `KERNEL.md` and `templates/telemetry-sidecar.md` are overwritten in place. No installer change, no manifest change, no symlink change, no `doctor` finding.
|
|
137
|
+
|
|
138
|
+
## [0.12.0] - 2026-08-19
|
|
139
|
+
|
|
140
|
+
`hstack/scripts/validate-spec.mjs` exists. Since ADR-0001 the kernel has said "run `validate-spec.ts` after every write" while the file was a `{{TODO-SCRIPT}}` placeholder referenced from 46 framework files — every one of the ~90 validation rules was prose the model had to remember and self-check, and ADR-0001 named the validator its blocker-priority follow-up. This release ships it: a dependency-free ESM script with a declarative rule registry covering 68 rule ids, plus an explicit deferred list naming the rules that are *not* mechanized and why.
|
|
141
|
+
|
|
142
|
+
### Added
|
|
143
|
+
|
|
144
|
+
- **`template/scripts/validate-spec.mjs`** — the artifact validator. Zero dependencies, plain ESM, runs on `node >= 18` with no install, no build step, and no network. `node hstack/scripts/validate-spec.mjs` validates the whole `hstack/` tree; passing paths validates named artifacts; `--json` for machine consumers; `--strict` to fail on warnings; `--rules` to print the registry. Exit 0 clean, 1 findings, 2 usage error.
|
|
145
|
+
- **A declarative rule registry, not ad-hoc code.** Every mechanized rule is one `{ id, type, description, check }` entry in `RULES`, and every rule the validator deliberately does *not* mechanize is one `{ id, type, reason }` entry in `DEFERRED_RULES`. The registry is the inventory: `hstack doctor` and the ship-time CI gate can import it rather than re-deriving the rule set. Nothing disappears between "documented in the kernel" and "enforced by a tool" — a rule is either checked or listed with its cause.
|
|
146
|
+
- **Coverage.** The shared frontmatter floor (`FM-01`: required fields, id shapes, ISO dates, case-sensitive enums, YAML arrays that are not comma-separated strings); per-type conditional schemas (`TD-05/06/07`, `SR-04/05`, `TS-04/05`, `AD-04`, `KF-04/05`, `V-02..V-05`, `DR-02/03/06`, `ST-02/03`, `FL-01/02`, `CM-01`); reciprocal pairs checked from **both** halves so a one-sided write is caught wherever the validator is pointed (`TD-01`, `TD-04`, `SP-14` `enables`↔`enabled-by`, `AD-02` `supersedes`↔`superseded-by`, `KF-04` `promoted-to`↔`promoted-from-kernel-fit`); and structural section rules (`SP-04` and `MS-03` ≥3 invariants, `AD-03` Nygard sections, `INF-01/02/03`, `PL-02..PL-05` phase-id and Files-Touched consistency, `AR-01/02/05/06/07`).
|
|
147
|
+
- **`scripts/test-validate-spec.mjs`** — 105 fixture checks, no runner, following `scripts/test-telemetry-parsers.py`. One complete valid hstack tree is the passing fixture for every rule (it puts each rule in its triggering condition: a `wontfix` tech-debt with both rationale fields, a `promoted` kernel-fit finding with its reciprocal ADR, a `risky` data-review with a filled Migration Safety section). Each failing fixture mutates that tree in exactly one way and asserts the expected rule id fires. The suite ends by cross-checking the registry: a rule with no failing fixture fails the run. `npm test` runs it.
|
|
148
|
+
|
|
149
|
+
### Changed
|
|
150
|
+
|
|
151
|
+
- **`.mjs`, not `.ts` — the name changes and all 46 referencing files change with it.** Consuming repos have no `node_modules` for hstack; the framework is copied files. Keeping `validate-spec.ts` would have imposed `node >= 22.6` with `--experimental-strip-types`, or `npx tsx` with its network fetch, on every mechanical write in every consumer. Plain ESM runs on the node that already installed hstack, stays importable from `src/`, and matches the dependency-free precedent set by `scripts/telemetry/` and `scripts/coord/`.
|
|
152
|
+
- **`template/KERNEL.md` § Mechanical operations — the "v1 honesty note" is gone** because the thing it was honest about has shipped. The proposed-diff preview stays and is no longer described as "the only mechanical contract check": the preview is the human's consent to a specific diff, the validator is the machine's check that the resulting artifact satisfies its contract, and the anti-pattern list now says that skipping either one leaves a real class of error uncaught. The section also states what the validator does *not* do — no git history, no PR diff, no prose scoring.
|
|
153
|
+
- **`{{TODO-SCRIPT: hstack/scripts/validate-spec.ts}}` replaced with the real invocation in 46 files** (36 `SKILL.md`, 10 agent files) plus the prose mentions in `hstack-flag`, `hstack-finalize`, `hstack-tech-debt-resolve`, `hstack-kernel-fit-triage`, `templates/kernel-fit-flag.md`, and `templates/coord-message.md`. Nothing else in those bodies moves — the deduplication pass is the next change and depends on this one.
|
|
154
|
+
- **`src/manifest.ts`** — `scripts/validate-spec.mjs` joins `FRAMEWORK_PATHS`, so `hstack update` ships and refreshes it.
|
|
155
|
+
|
|
156
|
+
### Known limitations
|
|
157
|
+
|
|
158
|
+
- **Rules that read git history are named, not implemented.** `TD-03` (no field rewrites on a terminal tech-debt) and `CM-02` (coord-message immutability) are claims about history, invisible to a working-tree validator; diffing every terminal artifact against its state at the resolving commit on every post-write run is disproportionate. `AR-04` (`commit:<hash>` exists on the change's branch) needs a branch the validator cannot infer. All three are in `DEFERRED_RULES` with the reason, and belong to the CI gate that already has the ref range.
|
|
159
|
+
- **Judgment stays with the subagents.** Whether a challenge-prompt answer probes for real omissions, whether an adversarial finding is genuine or quota-filler, whether a severity is calibrated — a validator scoring these would be an LLM, and the kernel already has one in the loop.
|
|
160
|
+
- **`CG-01..CG-04` cannot be implemented.** `GT-09` names the range; no repo source states what the four cross-reference rules are. Assigning them statements is a kernel change, not a validator change. Same for `SP-01..SP-03`, `SP-07`, `SP-08`, `SP-10..SP-12` and `AR-03`: those ids exist only in the diverged Notion schema doc, and inventing them would be worse than leaving them named and empty.
|
|
161
|
+
- **`SP-06` and `SR-01` are inferred.** Repo sources name `SP-05`/`SP-06` jointly ("Scope Boundaries is non-empty"), split here into a frontmatter half and a body half; no source states `SR-01` at all, so it is implemented by analogy with `TS-01`/`PL-01` plus the security-reviewer's Definition of Done. Both carry `inferred: true` in the registry and say so in `--rules` output.
|
|
162
|
+
- **Three checks are heuristics and report as warnings, not errors.** `TS-06` (change-spec invariants carry no ids in the template, so count parity against the parent's Invariants bullets is the proxy), `DR-01` (the Schema Changes section is prose; table names are extracted from a "new table" phrase), and `TD-02` (documented as surfacing-only in v1).
|
|
163
|
+
- **Merge gates are out of scope by design.** `GT-01..GT-12` read the PR diff and the CI run, not the artifact tree; they belong to `run-gates.sh` / `compute-merge-readiness.ts`, the named immediate follow-up. `GT-08` restates `SP-09` and `GT-12` restates `SP-13`/`SP-14`, and those halves are enforced here.
|
|
164
|
+
|
|
165
|
+
### Consumer action required
|
|
166
|
+
|
|
167
|
+
- Run `npx hstack@latest update`, then commit. The validator lands at `hstack/scripts/validate-spec.mjs` and the 46 framework files pick up the real invocation.
|
|
168
|
+
- **Expect findings on an established repo.** A read-only run against moso-app (1,571 artifacts) reported **550 errors and 172 warnings**. The clusters are template-vs-practice drift accumulated while nothing was checking: 167 `V-02` (verification `test-results` using `passed` / `not-applicable`, neither in the template's `pass | fail | pending | not-run` enum), 145 `CM-01` (coord-message subjects over the 80-character cap — warnings), 133 `PL-05` (plans predating ADR-0008's Roadmap Alignment section), 48 `FM-01` (a missing `owner`, `cost: low`/`high` against the template's `small | medium | large`), 35 `AD-03` (ADRs predating the schema-version-2 Forecloses / Enables section). Nothing blocks on these today — the validator is a Skill-time and opt-in check, not yet a CI gate. Reading them as a backlog, and deciding per cluster whether the template or the practice is wrong, is the point.
|
|
169
|
+
|
|
170
|
+
## [0.11.0] - 2026-08-19
|
|
171
|
+
|
|
172
|
+
A Skill or subagent `description` is a routing trigger, not documentation (ADR-0011). The harness injects every installed description into every session unconditionally — that is the routing index, and hstack was spending **~30k tokens** on it, roughly twice the kernel that ADR-0010 spent a release removing, mostly to inform decisions a typed `/hstack:<skill>` command or a literal `subagent_type` had already made. The 52 descriptions are now one sentence each naming the state that should cause invocation. Nothing else moves: no rule, no gate, no invariant, no halt condition, no status lifecycle.
|
|
173
|
+
|
|
174
|
+
### Changed
|
|
175
|
+
|
|
176
|
+
- **All 52 frontmatter descriptions rightsized to a one-sentence routing trigger** under a 40-word / ~250-character budget (36 `SKILL.md`, 16 agent files). Landed at **19,422 → 4,136 words** and **146,184 → 32,150 bytes** across the frontmatter blocks — **≈30.3k → ≈6.7k tokens** at ADR-0011's 4.83 bytes/token calibration, **≈23.6k recovered at turn zero of every session in every consuming repo**, including sessions that invoke no Skill at all. Sequenced as two commits — subagents first (the half where routing is already deterministic; 20 `SKILL.md` files name a literal `subagent_type`), Skills second — so a routing regression is attributable to one half from the git history.
|
|
177
|
+
- **All 123 `<example>` / `<commentary>` blocks removed from frontmatter.** Each contained scripted `user:` / `assistant:` turns that pre-wrote the first response before the model had read the actual change-spec. 117 were provable duplicates of a body line in the same file (or of the subagent body the Skill orchestrates); the PR carries the per-block migration table with the proof line for each.
|
|
178
|
+
- **Six boundary cases migrated into bodies** rather than deleted, because the body did not already carry them: `product-discovery` (extract mode does not bypass the forcing prompts → Behavior rules); `security-reviewer` (halt when SR-03 requires a threat-model-delta that cannot be produced → Stop conditions; a refactor declaring no security-sensitive surfaces is still reviewed → new `## When to invoke`); `stack-architect` (standalone `--layer` needs an explicit deliberate-swap confirmation → new `## When to invoke`); `test-strategist` (a behaviour-preserving refactor still gets a test-plan → new `## When to invoke`); `hstack-change-plan` (the halt-because-`data-review.md`-is-missing case — the gate was in Preconditions, the remedy pointer was not → a "when not to invoke" sub-list naming the db, ui, and test-plan remedies).
|
|
179
|
+
- **`hstack-coord` keeps an expanded description** per ADR-0011's named carve-out: the "ALWAYS invoke `check` mode when the `HSTACK-COORD:` pointer line appears" instruction plus the four-mode list. It is the only Skill that routes with nothing typed, so the description is the only surface that can carry the trigger. Its own three example blocks were still removed.
|
|
180
|
+
- **Confusable families keep one distinguishing clause each** — `tech-debt-{new,resolve,wontfix,stale}`, `kernel-fit-{scan,triage,promote}`, `{greenfield,brownfield}-init`, `{change-new,change-plan}`, and `data-architect` vs `data-specialist`. Routing errors live between siblings, and the clause is cheaper than the error.
|
|
181
|
+
|
|
182
|
+
### Added
|
|
183
|
+
|
|
184
|
+
- **`.claude/skills/hstack-kernel-fit-scan/references/slack-setup.md`** — the consumer-side Slack wiring (MCP + `chat:write`, the `kernel-fit` config block, the `--no-slack` dry-run) moves out of the Skill body into a reference read on demand. The Skill keeps a pointer that names when *not* to read it. `hstack-kernel-fit-scan` was the one body at or over the 5k-token per-Skill guidance, and truncation keeps the head — the tail was disappearing in silence after compaction. Now 20,742 → 16,594 bytes: ~3.4k tokens at 4.83 bytes/token, ~4.1k at the conservative 4.0 estimator, against ~4.3k / ~5.2k before.
|
|
185
|
+
|
|
186
|
+
### Consumer action required
|
|
187
|
+
|
|
188
|
+
- Run `npx hstack@latest update`, then commit. **Zero migration surface**: descriptions and the new reference file live in framework-owned files under `.claude/`, which `update` overwrites, and `wire.ts` symlinks each skill *directory* — so the reference travels with the Skill. No installer change, no manifest change, no symlink change, no `doctor` finding, nothing under `src/`.
|
|
189
|
+
- Consumers diverge until they run `update`, the same window ADR-0010 opened. Cross-repo token comparisons are not meaningful inside it.
|
|
190
|
+
|
|
191
|
+
### Known limitations
|
|
192
|
+
|
|
193
|
+
- **This is a behavioural change with no test.** Nothing in the repo asserts routing correctness; `doctor` can detect a missing file, not a bad sentence. Verbose descriptions do help when an engineer *describes* a situation instead of typing the command, and ADR-0009's attribution counts only structured markers — which are the typed path. The surface most at risk is the one the instrument cannot see.
|
|
194
|
+
- **A `description-budget` `doctor` finding is the correct follow-up** (ADR-0011 Option F) and is deliberately not in this release: a linter for a size no file respected would have flagged 52 findings on day one. The rule is established by the rewrite first, enforced by a tool second.
|
|
195
|
+
|
|
196
|
+
## [0.10.0] - 2026-08-18
|
|
197
|
+
|
|
198
|
+
Phase cost becomes measurable (ADR-0009). The five sidecar-emitting Skills now stamp a session id and a phase time-window on their sidecar; the telemetry parser sums the transcript's assistant-turn usage between those bounds; and Skill attribution stops matching free text. "What did this phase cost?" and "what did this change cost?" are answerable from data the harness already writes — no new measurement channel, two timestamps and an id written where a file was already being written.
|
|
199
|
+
|
|
200
|
+
### Added
|
|
201
|
+
|
|
202
|
+
- **Phase window on every sidecar — `session_id`, `phase_opened_at`, `phase_closed_at`** (`templates/telemetry-sidecar.md`, `schema_version: 2`, plus the five emitting Skills: `test-plan`, `implement`, `verify`, `adversarial-review`, `finalize`). `phase_opened_at` is stamped the moment preconditions pass, before any subagent invocation; `phase_closed_at` at the terminal state, in the same write that lands the sidecar. Best-effort by contract: an unresolvable session id writes `null` and the phase reports as **unmeasured, never as zero** — a phase whose transcript was swept still spent tokens, and a zero would fold it into the averages as if it were free. The sidecar stays derivative, gitignored, never authoritative, and rides the commit that was happening anyway.
|
|
203
|
+
- **`scripts/telemetry/session_id.py`** — the session-id heuristic as shared code instead of prose duplicated per Skill. Prints `session_id`, `transcript_path`, `message_count` and a UTC `now` stamp in one read, so a Skill opening a phase gets both fields from one call. `/hstack:flag` now calls it rather than carrying its own copy of the heuristic (ADR-0005's v1 mechanism is unchanged — it just lives in one file, which is where the v2 harness-exposed session id will land).
|
|
204
|
+
- **`parsers/transcripts.py:phase_usage(sidecar)`** — opens the transcript named by `session_id` and sums `input + cache_creation_input + cache_read_input + output` over assistant records whose `timestamp` falls in `[phase_opened_at, phase_closed_at]`. Returns `null` on a missing transcript, a null session id, a v1 sidecar, or an inverted window. Read-only.
|
|
205
|
+
- **`parsers/sidecars.py`** — loads `hstack/specs/changes/*/.telemetry/*.json`. A malformed sidecar is skipped, never repaired.
|
|
206
|
+
- **TE-4 (cost per phase) and TE-5 (cost per change)** in `insights/token_economics.py`, rendered in the markdown report and the JSON twin. Both print an explicit **coverage fraction** — measured phases over emitted sidecars — because only five of the 27 Skills emit: `change-new`, `change-plan`, `security-review`, `data-review`, `ship` and the whole `configure` family contribute nothing to these sums, and subagent spend still lands in its host's window. Both notes point the reader at QO-4 and WS-2: cost without an outcome beside it can only argue for spending less, never for spending well. A new watch-list line fires when any emitted sidecar is unmeasured, so partial coverage is surfaced rather than inferred.
|
|
207
|
+
- **`scripts/test-telemetry-parsers.py`** (dev repo only, not shipped) — fixture tests for the bounded summation, the four null paths, and the structured-marker classifier. The dev repo is not a consumer, so these fixtures are the only place the parsers run against known-answer input.
|
|
208
|
+
|
|
209
|
+
### Fixed
|
|
210
|
+
|
|
211
|
+
- **Skill attribution no longer matches prose.** `classify_session` dropped the `/hstack:([a-z…])` regex over message text; it reads only structured markers the harness emits — `<command-name>` tags and `Skill` tool_use blocks — and classifies a session with neither as `(unattributed)`. Measured on 30 days of moso-app transcripts (760 sessions): 104 sessions move out of Skill buckets they never invoked, and the buckets built almost entirely from prose collapse — `tech-debt-new` 37 → 6 sessions, `finalize` 31 → 3, `configure` 27 → 1, `ship` 15 → 2, `tech-debt-stale` 3 → 0. On the hstack dev repo — which discusses these commands constantly and invokes none of them — every bucket goes to zero, including `/hstack:flag`'s phantom 35.5M tokens across 247 turns.
|
|
212
|
+
- **Honest correction to ADR-0009's own prediction:** `coord` does **not** shrink. It goes 81 → 92 sessions, because ADR-0007's hook makes the agent genuinely invoke `/hstack:coord` at session start — a real structured marker, not a quoted string. What credits `coord` with half the measured cache-read tokens is the missing end marker, not the regex; that is what TE-4/TE-5 supersede, and TE-1/TE-2 now say so in their notes rather than implying a per-Skill total.
|
|
213
|
+
|
|
214
|
+
### Changed
|
|
215
|
+
|
|
216
|
+
- **TE-1 and TE-2 keep their shape and gain a session-scoped note** naming what they can and cannot answer, the unattributed count, and their supersession by TE-4/TE-5 wherever sidecars exist. TE-2's `(non-hstack)` bucket is renamed `(unattributed)` — it now holds hstack sessions with no structured marker as well as plain non-hstack work.
|
|
217
|
+
- **JSON twin `schema_version` 1 → 2** (`counts.phase_sidecars`, `te_4_cost_per_phase`, `te_5_cost_per_change`). Additive: every v1 key keeps its shape.
|
|
218
|
+
- **`ui/lib/report.ts`** — `TelemetryReport` carries the new blocks as optional so a v1 report on disk still renders; `ui/components/repo-dashboard.tsx` renders TE-4/TE-5 cards with the coverage fraction in the card description, not below the table.
|
|
219
|
+
- **`hstack-telemetry` Skill** — the six-bucket summary names TE-4/TE-5, their coverage caveat, and the unmeasured-never-zero rule.
|
|
220
|
+
|
|
221
|
+
### Consumer action required
|
|
222
|
+
|
|
223
|
+
- Run `npx hstack@latest update`, then commit. No migration: sidecars written before this release stay at `schema_version: 1`, carry no window, and read as unmeasured — the timestamps they would need were never recorded. Coverage climbs from zero as new phases land.
|
|
224
|
+
- If `.telemetry/` is not gitignored in your repo, fix that before the next phase lands: sidecars now carry a local session id, and the discipline that keeps it out of git history is that one line.
|
|
225
|
+
- Transcript retention is now load-bearing for history. `cleanupPeriodDays` defaults to 30 days; a repo left at the default cannot recompute phase cost for changes older than a month, and the sidecar keeps pointing at a file that no longer exists (reported as unmeasured, never as zero).
|
|
226
|
+
|
|
227
|
+
## [0.9.0] - 2026-08-15
|
|
228
|
+
|
|
229
|
+
The consumer-side kernel is renamed `hstack/CLAUDE.md` → `hstack/KERNEL.md` (ADR-0010). Claude Code was loading it twice: once via the `@hstack/CLAUDE.md` import in the consumer's root `CLAUDE.md` (expanded at launch) and again via nested-`CLAUDE.md` discovery, which keys on the literal filename and injects the whole file on the first read of *any* artifact under `hstack/`. Measured at ~15k tokens in 46% of sessions on a real workload. Discovery cannot see `KERNEL.md`, so the import is now the single load path — the one that survives compaction and that subagents inherit. Filename only: the kernel's authority, content, precedence, and the "everything under `hstack/`" layout rule are unchanged.
|
|
230
|
+
|
|
231
|
+
### Changed
|
|
232
|
+
|
|
233
|
+
- **`template/CLAUDE.md` → `template/KERNEL.md`**, and `KERNEL.md` replaces `CLAUDE.md` in `FRAMEWORK_PATHS` (`src/manifest.ts`).
|
|
234
|
+
- **`src/lib/wire.ts`** — the appended import line becomes `See @hstack/KERNEL.md.` and the idempotency probe becomes `@hstack/KERNEL.md`, on both the `init` and `update` call sites. The old strings survive as `LEGACY_KERNEL_IMPORT_PROBE` / `LEGACY_KERNEL_PATH_PROBE` for the migration and for `doctor`.
|
|
235
|
+
- **~40 path references across 25 files** now point at the new name: the 14 subagent session-start context-load lists, the Skills that name the kernel (notably `hstack-brownfield-init`, `hstack-kernel-fit-scan`, `hstack-greenfield-init`, `hstack-configure`, `hstack-product-discovery`, `hstack-help`), the kernel's own heading and `kernel-fit-analyst` reading list, the telemetry renderer and templates, and `README.md`. The telemetry entry points (`report.py`, `run_kernel_fit.py`) accept either filename when run against an hstack-shaped tree, so an un-migrated repo keeps reporting.
|
|
236
|
+
|
|
237
|
+
### Added
|
|
238
|
+
|
|
239
|
+
- **`hstack update` migrates a pre-ADR-0010 install** — `git mv hstack/CLAUDE.md hstack/KERNEL.md` (falling back to a plain rename when the file is untracked) plus a probe-matched rewrite of the import line in the root `CLAUDE.md`. The rewrite is a substring swap of `@hstack/CLAUDE.md` → `@hstack/KERNEL.md`: everything else in that engineer-owned file is preserved verbatim. Both halves are one action so they land in one commit — a repo with the file renamed but the import still pointing at the old path has no kernel in context at all. The migration is planned only when the legacy state is on disk, so re-running `update` is a no-op. A hand-edited import that the probe does not match is **never** rewritten: `update` warns and `doctor` keeps flagging it, mirroring ADR-0007's settings-ownership contract.
|
|
240
|
+
- **`hstack doctor` finding `kernel-filename`** (level `error`) — fires when `hstack/CLAUDE.md` is still present (nested discovery still injects a second copy of the kernel) or when the root import still points at `@hstack/CLAUDE.md`, with the one-command fix `npx hstack update`. A root `CLAUDE.md` that mentions `hstack/CLAUDE.md` in a form the migration will not rewrite gets a distinct finding naming the manual fix.
|
|
241
|
+
- **New ADR** `adr/ADR-0010-kernel-file-renamed-to-avoid-double-load.md` — the measurements behind both load paths, why `claudeMdExcludes` was tested and rejected (it suppresses both paths rather than deduplicating), and the honest cost: the redundancy being removed was an accidental fail-safe, so a broken import now means an unkerneled session that looks completely normal.
|
|
242
|
+
|
|
243
|
+
### Consumer action required
|
|
244
|
+
|
|
245
|
+
- Run `npx hstack@latest update`, then commit. The rename, the import-line rewrite, and the framework sync land in that single commit. Verify with `npx hstack doctor` — a clean run means no `kernel-filename` finding.
|
|
246
|
+
- If `update` warns that it left your `CLAUDE.md` untouched, the import line was hand-edited: point it at `@hstack/KERNEL.md` yourself. `doctor` flags it until you do.
|
|
247
|
+
|
|
248
|
+
## [0.8.0] - 2026-07-29
|
|
249
|
+
|
|
250
|
+
`roadmap.md` replaces `mvp-scope.md` and enters the daily loop (ADR-0008): the medium-term product trajectory now reaches the moments where one-way-door architecture decisions are made — planning, ADR authoring, stack decisions — as advisory context with visible staleness, never a gate.
|
|
251
|
+
|
|
252
|
+
### Added
|
|
253
|
+
|
|
254
|
+
- **`templates/roadmap.md`** — fuzzy horizons Now / Next / Later / Not on the path, each item carrying a one-line **architectural implication** (proposed by `app-architect` / `data-architect` for their halves, confirmed by the engineer). No dates. During the MVP phase, Now IS the MVP scope — the artifact survives past MVP where mvp-scope died. Frontmatter `source: local | rhizome` marks who owns the truth (anticipating rhizome as the external product brain); `reviewed-on` feeds the 90-day staleness threshold.
|
|
255
|
+
- **`Forecloses / Enables` section on `templates/adr.md`** — which roadmap Next/Later item does this decision make more expensive or cheaper? "None" is a valid answer; a missing or stale roadmap reads `n/a — roadmap stale/missing`. Advisory — no validator rule blocks an ADR on roadmap grounds.
|
|
256
|
+
- **`Roadmap Alignment` section on `templates/plan.md`** — one honest line written by the `planner`; stale/missing roadmap yields `n/a — roadmap stale/missing (<detail>)` instead of pretending. This visible line is the staleness heartbeat mvp-scope never had.
|
|
257
|
+
- **Daily-loop reading-list entries** — `planner`, `spec-author` (when authoring an ADR), and `stack-architect` load `roadmap.md` at session start. Explicit carve-out from the kernel's missing-context halt rule: a stale or absent roadmap is surfaced in the output line, never a halt.
|
|
258
|
+
- **Brain signal "Roadmap earning its place"** (`brain/ANALYSIS.md`) — Forecloses/Enables fill-rate, `n/a` alignment lines, and per-repo roadmap staleness. If a quarter of data shows the artifact not earning its tokens, the recommendation is to kill or reshape it knowingly — unlike mvp-scope, which died unobserved.
|
|
259
|
+
- **New ADR** `adr/ADR-0008-roadmap-replaces-mvp-scope.md` — the autopsy of mvp-scope (in the reading lists of init-time atoms only; the daily loop loaded no product context; nothing ever surfaced its staleness) and the three design lessons baked into the replacement.
|
|
260
|
+
|
|
261
|
+
### Changed
|
|
262
|
+
|
|
263
|
+
- **Kernel § Product context** — `mvp-scope.md` entry replaced by `roadmap.md`; load-at-session-start rules updated for `product-manager`, `data-architect`, `app-architect`, `stack-architect`, `spec-author`, `planner`.
|
|
264
|
+
- **All `mvp-scope` references** (~30 across kernel, 8 subagents, 12 Skills, README) now point at `roadmap` — including `product-manager`'s story-drift check, which now flags stories drifting outside the **Now** horizon.
|
|
265
|
+
- **`product-manager`** — owns `roadmap.md` when `source: local`; refuses local edits when `source: rhizome`. Product lines are the engineer's; architectural-implication lines are proposed by the architect agents, never invented ("empty is better than vague").
|
|
266
|
+
|
|
267
|
+
### Removed
|
|
268
|
+
|
|
269
|
+
- **`templates/mvp-scope.md`** — superseded by `templates/roadmap.md`. `hstack update` removes the framework copy in consuming repos; the user-content `hstack/context/mvp-scope.md` is never touched by the installer (see migration below).
|
|
270
|
+
|
|
271
|
+
### Consumer action required
|
|
272
|
+
|
|
273
|
+
- Run `npx hstack@latest update` to receive the new template, kernel, agent, and Skill updates (this also removes the now-orphan `hstack/templates/mvp-scope.md`).
|
|
274
|
+
- Then run `/hstack:configure roadmap` — when a legacy `hstack/context/mvp-scope.md` exists with no `roadmap.md`, `product-manager` offers an extract+confirm conversion (In MVP → Now, v2 → Next, Deferred → Later or Not on the path) and prompts deletion of the legacy file once the roadmap lands at `current`.
|
|
275
|
+
|
|
5
276
|
## [0.7.1] - 2026-07-25
|
|
6
277
|
|
|
7
278
|
### Fixed
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ hstack sits between an engineer's intent and a merged commit. Scoping, gating, a
|
|
|
6
6
|
|
|
7
7
|
## What hstack is
|
|
8
8
|
|
|
9
|
-
A thin, opinionated layer on top of Claude Code that governs how engineers and AI agents collaborate on a codebase. ~34 Skills, ~16 subagents, ~32 canonical templates, and one kernel (`
|
|
9
|
+
A thin, opinionated layer on top of Claude Code that governs how engineers and AI agents collaborate on a codebase. ~34 Skills, ~16 subagents, ~32 canonical templates, and one kernel (`KERNEL.md`) that wins every conflict. AI writes; humans confirm. Artifacts on disk are the state machine — no parallel tracker, no separate dashboard.
|
|
10
10
|
|
|
11
11
|
Two entry points cover the project lifecycle:
|
|
12
12
|
|
|
@@ -42,10 +42,12 @@ The CLI ships three commands:
|
|
|
42
42
|
| Command | What it does |
|
|
43
43
|
| --- | --- |
|
|
44
44
|
| `npx hstack init` | First-time install. Halts if `<consumer>/hstack/` already exists. |
|
|
45
|
-
| `npx hstack update` | Sync framework files to the package version. Preserves user content (`context/`, `specs/`, `adr/`, `tech-debt/`, `research/`, `config.yaml`, `telemetry/reports/`). Surfaces a diff plan before writing. |
|
|
46
|
-
| `npx hstack doctor` | Read-only health check. Reports version drift, framework file drift, missing or orphan symlinks, missing wiring lines, missing coord-notification hooks. Exits 1 on any finding. |
|
|
45
|
+
| `npx hstack update` | Sync framework files to the package version. Preserves user content (`context/`, `specs/`, `adr/`, `tech-debt/`, `research/`, `config.yaml`, `telemetry/reports/`). Surfaces a diff plan before writing. Migrates a pre-ADR-0010 install (`hstack/CLAUDE.md` → `hstack/KERNEL.md` plus the import line). |
|
|
46
|
+
| `npx hstack doctor` | Read-only health check. Reports version drift, framework file drift, missing or orphan symlinks, missing wiring lines, missing coord-notification hooks, a stale pre-ADR-0010 kernel filename, and any Skill / subagent description over the ADR-0011 routing-trigger budget. Exits 1 on any finding. |
|
|
47
47
|
|
|
48
|
-
The
|
|
48
|
+
The kernel is installed at `hstack/KERNEL.md`, not `hstack/CLAUDE.md` (ADR-0010): Claude Code discovers *any* nested file named `CLAUDE.md` and injects it on the first read of a file in its directory, which loaded the whole kernel a second time on top of the `@`-import. The import in the consumer's root `CLAUDE.md` is the single load path — it fires at launch, survives compaction, and is inherited by subagents.
|
|
49
|
+
|
|
50
|
+
The framework-vs-user-content boundary is canonical in `src/manifest.ts`. **What `init` and `update` write**: `hstack/KERNEL.md`, `hstack/templates/`, `hstack/.claude/agents/`, `hstack/.claude/skills/`, `hstack/scripts/telemetry/`, `hstack/scripts/coord/`, `hstack/scripts/validate-spec.mjs`, `hstack/scripts/compute-merge-readiness.mjs`, `hstack/scripts/run-gates.sh`, `hstack/VERSION`, plus the two probe-matched hook entries in `.claude/settings.json`. **What they never touch**: anything under the user-content paths above, and every engineer-owned key in `settings.json`.
|
|
49
51
|
|
|
50
52
|
### Manual install (legacy)
|
|
51
53
|
|
|
@@ -60,7 +62,7 @@ for d in hstack/.claude/skills/hstack-*/; do
|
|
|
60
62
|
name=$(basename "$d")
|
|
61
63
|
ln -s "../../hstack/.claude/skills/$name" ".claude/skills/$name"
|
|
62
64
|
done
|
|
63
|
-
echo '> **Engineering workflow:** all changes in this repo are governed by hstack. See @hstack/
|
|
65
|
+
echo '> **Engineering workflow:** all changes in this repo are governed by hstack. See @hstack/KERNEL.md.' >> CLAUDE.md
|
|
64
66
|
echo '**/.telemetry/' >> .gitignore
|
|
65
67
|
git add hstack .claude CLAUDE.md .gitignore && git commit -m "vendor hstack"
|
|
66
68
|
```
|
|
@@ -106,6 +108,19 @@ Run `npx hstack@latest update` whenever you want to pull the latest framework ve
|
|
|
106
108
|
|
|
107
109
|
Run `npx hstack doctor` to audit health without making changes — useful for CI checks, audits before opening a PR against the consumer repo, or onboarding a new contributor.
|
|
108
110
|
|
|
111
|
+
#### Adding or removing a Skill or subagent
|
|
112
|
+
|
|
113
|
+
`hstack update` handles this for a consumer pulling a release. A session working *in the framework source* carries the obligation manually, and lands the wiring change in the same PR as the Skill or subagent change (the kernel states the obligation under § Consuming-repo wiring; the commands are here):
|
|
114
|
+
|
|
115
|
+
| Change | Consumer-side action |
|
|
116
|
+
|---|---|
|
|
117
|
+
| New Skill at `.claude/skills/hstack-<name>/` | Create the symlink: `ln -s ../../hstack/.claude/skills/hstack-<name> <consumer-root>/.claude/skills/hstack-<name>` |
|
|
118
|
+
| Skill removed | Remove the matching symlink. Orphan symlinks are silent failures. |
|
|
119
|
+
| Skill renamed | Treat as removal + addition, in both source and consumer. |
|
|
120
|
+
| New subagent at `.claude/agents/<name>.md` | None. `.claude/agents/` is a dir-level symlink under the recommended pattern, so the file appears automatically. |
|
|
121
|
+
| Subagent removed | None, same reason. |
|
|
122
|
+
| Copy-based consumer (copied `.claude/` instead of symlinking) | Mirror every add / remove / rename by hand. The drift cost is why symlinks are recommended. |
|
|
123
|
+
|
|
109
124
|
#### Telemetry
|
|
110
125
|
|
|
111
126
|
`hstack/scripts/telemetry/` ships with the framework and is installed by `hstack init` automatically. The `/hstack:telemetry` Skill shells out to `python3 hstack/scripts/telemetry/report.py --window 30`, generating a markdown report at `hstack/telemetry/reports/<YYYY-MM-DD>.md`. The reports directory is git-tracked; per-change `.telemetry/` sidecar dirs are git-ignored (`hstack init` adds the `**/.telemetry/` line for you).
|
|
@@ -130,7 +145,7 @@ Open a fresh Claude Code session in the consuming repo. Pick the right entry poi
|
|
|
130
145
|
|
|
131
146
|
Six phases of conversational design, each ending at a commit point. Total elapsed time is founder-paced — typically 4–8 hours of conversation across multiple sessions. Phases:
|
|
132
147
|
|
|
133
|
-
1. **Product discovery** — `product-discovery` agent runs one of three techniques (Brainstorm, Forcing-Questions, Project-Brief) and produces `hstack/context/product/product-brief.md`, then auto-routes to `product-manager` to refresh vision,
|
|
148
|
+
1. **Product discovery** — `product-discovery` agent runs one of three techniques (Brainstorm, Forcing-Questions, Project-Brief) and produces `hstack/context/product/product-brief.md`, then auto-routes to `product-manager` to refresh vision, roadmap, personas, glossary.
|
|
134
149
|
2. **Data architecture** — `data-architect` agent walks five sections (Tenancy, Entities, RLS, RAG, Migration Sketches) and produces a deeper `hstack/context/data-architecture.md`.
|
|
135
150
|
3. **App architecture** — `app-architect` agent walks five sections (Module Map, Agent Orchestration, Deterministic-vs-LLM Split, State-Ownership, Surface Boundaries) and produces `hstack/context/app-architecture.md`. Scaffolds module-spec stubs.
|
|
136
151
|
4. **Stack decisions** — `stack-architect` agent runs the constraint interview, routes ADRs through `spec-author` with pre-populated Context / Decision / Alternatives. Default-stack fast-path collapses confirmed defaults into one rollup ADR.
|
|
@@ -145,7 +160,7 @@ Six phases of conversational design, each ending at a commit point. Total elapse
|
|
|
145
160
|
|
|
146
161
|
Conversational, split into mini-sessions of ten-to-fifteen minutes each — one per product-context document. Each mini-session ends at a commit point. Total elapsed time is 60–90 minutes for a fresh adoption. No other per-change Skill runs until init completes.
|
|
147
162
|
|
|
148
|
-
Brownfield-init produces `hstack/config.yaml` and every required document under `hstack/context/`: vision, glossary,
|
|
163
|
+
Brownfield-init produces `hstack/config.yaml` and every required document under `hstack/context/`: vision, glossary, roadmap, personas (via `product-manager` reading existing docs in extract+confirm mode), data-architecture and app-architecture (delegated to the standalone atoms running in extract mode against the live schema and source tree), tech-stack, ci-cd, threat-model, hardening-checklist, infrastructure, incident-runbook. If the consuming repo has existing source documents (Notion pages, repo markdown, Google Docs), point the agents at them and they will map content into the canonical templates before walking field-by-field confirmation.
|
|
149
164
|
|
|
150
165
|
After brownfield-init, run `/hstack:module-spec <area>` once per critical module to reverse-engineer baseline module-specs from the stubs scaffolded by `/hstack:app-architecture`.
|
|
151
166
|
|
|
@@ -192,14 +207,14 @@ After init the consuming repo has:
|
|
|
192
207
|
```
|
|
193
208
|
hstack/
|
|
194
209
|
config.yaml # repo-level configuration
|
|
195
|
-
|
|
210
|
+
KERNEL.md # the kernel (authority)
|
|
196
211
|
README.md # this file
|
|
197
212
|
context/ # slow-changing product context
|
|
198
213
|
product/
|
|
199
214
|
product-brief.md # discovery synthesis (Phase 1 output)
|
|
200
215
|
app-architecture.md # internal architecture (Phase 3 output)
|
|
201
216
|
data-architecture.md # five-section foundational data design (Phase 2 output)
|
|
202
|
-
... # vision,
|
|
217
|
+
... # vision, roadmap, personas, glossary, tech-stack, ci-cd, infrastructure, threat-model, hardening-checklist, incident-runbook
|
|
203
218
|
specs/
|
|
204
219
|
<module>/spec.md # module baseline (stubs scaffolded by app-architect; reverse-engineered post-bootstrap)
|
|
205
220
|
changes/<id>/ # per-change artifacts (including the one-time bootstrap change-spec)
|
|
@@ -234,11 +249,22 @@ The full v2 roadmap lives in the architecture document.
|
|
|
234
249
|
|
|
235
250
|
## Reference
|
|
236
251
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
- [
|
|
252
|
+
Authoritative, in the repo:
|
|
253
|
+
|
|
254
|
+
- [`template/KERNEL.md`](./template/KERNEL.md) — the kernel. Authority over every Skill, subagent, and template.
|
|
255
|
+
- [`template/templates/`](./template/templates/) — the canonical structure of every artifact type: fields, sections, lifecycle.
|
|
256
|
+
- `node template/scripts/validate-spec.mjs --rules` — the canonical list of mechanized artifact rules, and of the rules deliberately left to a human or to CI, with the reason for each.
|
|
257
|
+
- `node template/scripts/compute-merge-readiness.mjs --gates` — the twelve merge gates `/hstack:ship` scores, and the one deferred because no source states what it means.
|
|
258
|
+
|
|
259
|
+
Non-authoritative historical companions, written before the framework shipped its own enforcement. Where they disagree with the three above, they are wrong:
|
|
260
|
+
|
|
261
|
+
- [Architecture document](https://www.notion.so/360d6791656c813d955af822cb8814d1) — long-form companion to the kernel, pre-v1.
|
|
240
262
|
- [Adversarial review of the architecture](https://www.notion.so/361d6791656c81f78eb3c97ba4aecbb4) — the 21-finding pressure test that shaped the v1 / v2 split.
|
|
241
263
|
|
|
264
|
+
The former "template schemas and frontmatter contracts" page is no longer listed: it has diverged from the repo and is superseded by the templates directory and the validator registry (ADR-0013).
|
|
265
|
+
|
|
242
266
|
## Status
|
|
243
267
|
|
|
244
|
-
hstack v0.x.x. ~34 Skills, ~16 subagents, ~32 templates, the kernel. Greenfield workflow added
|
|
268
|
+
hstack v0.x.x. ~34 Skills, ~16 subagents, ~32 templates, the kernel. Greenfield workflow added earlier (four discovery-atom subagents — product-discovery, data-architect, app-architect, stack-architect — plus seven new skills: greenfield-init, the four atoms, scaffold). `/hstack:init` was renamed to `/hstack:brownfield-init`; consumers on the renamed version run `npx hstack update` to reconcile per-skill symlinks.
|
|
269
|
+
|
|
270
|
+
The three enforcement scripts have landed: `validate-spec.mjs` (artifact contracts), `compute-merge-readiness.mjs` (the twelve merge gates) and `run-gates.sh` (canonical test / lint / typecheck runs with a per-suite observed-test-count for V-05). Pattern-based lint rules (`hstack/lints/`) are still sketched, so GT-03 reports `not-applicable` in a repo that declares none. First real use of the greenfield path against a fresh project is the next milestone.
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.16.0
|
package/dist/commands/doctor.js
CHANGED
|
@@ -4,7 +4,8 @@ import { readFileSync } from "node:fs";
|
|
|
4
4
|
import { resolve, basename } from "node:path";
|
|
5
5
|
import { findGitRoot } from "../lib/git.js";
|
|
6
6
|
import { packageTemplateDir, packageVersionFile } from "../lib/paths.js";
|
|
7
|
-
import { planUpdate, pruneNoopActions, coordHooksState } from "../lib/wire.js";
|
|
7
|
+
import { planUpdate, pruneNoopActions, coordHooksState, kernelFilenameState, KERNEL_IMPORT_PROBE, LEGACY_KERNEL_IMPORT_PROBE, LEGACY_KERNEL_PATH_PROBE, } from "../lib/wire.js";
|
|
8
|
+
import { descriptionsOverBudget, WORD_BUDGET, CHAR_BUDGET, } from "../lib/descriptions.js";
|
|
8
9
|
function readPackageVersion() {
|
|
9
10
|
return readFileSync(packageVersionFile(), "utf8").trim();
|
|
10
11
|
}
|
|
@@ -50,6 +51,34 @@ export async function runDoctor(opts) {
|
|
|
50
51
|
message: `installed v${installedVersion}, package v${packageVersion} — run \`npx hstack update\``,
|
|
51
52
|
});
|
|
52
53
|
}
|
|
54
|
+
// Kernel filename (ADR-0010). An `hstack/CLAUDE.md` left on disk is loaded a
|
|
55
|
+
// second time by nested-CLAUDE.md discovery on the first read of anything
|
|
56
|
+
// under hstack/ (~15k tokens); an import line still pointing at the old path
|
|
57
|
+
// means the kernel may not be loaded at all once the file is renamed. Both
|
|
58
|
+
// are errors, not drift.
|
|
59
|
+
const kernelFile = await kernelFilenameState(gitRoot);
|
|
60
|
+
if (kernelFile.legacyKernelFile || kernelFile.legacyImport) {
|
|
61
|
+
const parts = [];
|
|
62
|
+
if (kernelFile.legacyKernelFile) {
|
|
63
|
+
parts.push("hstack/CLAUDE.md is still present — nested-CLAUDE.md discovery injects a second full copy of the kernel");
|
|
64
|
+
}
|
|
65
|
+
if (kernelFile.legacyImport) {
|
|
66
|
+
parts.push(`the root CLAUDE.md import still points at ${LEGACY_KERNEL_IMPORT_PROBE}`);
|
|
67
|
+
}
|
|
68
|
+
findings.push({
|
|
69
|
+
level: "error",
|
|
70
|
+
category: "kernel-filename",
|
|
71
|
+
message: `${parts.join("; ")} (ADR-0010) — fix: \`npx hstack update\``,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
else if (kernelFile.legacyImportUnrewritable) {
|
|
75
|
+
findings.push({
|
|
76
|
+
level: "error",
|
|
77
|
+
category: "kernel-filename",
|
|
78
|
+
message: `CLAUDE.md references the old kernel path \`${LEGACY_KERNEL_PATH_PROBE}\` in a form hstack will not rewrite (ADR-0010) — ` +
|
|
79
|
+
`fix by hand: the import must read \`${KERNEL_IMPORT_PROBE}\``,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
53
82
|
const overwrites = actions.filter((a) => a.kind === "overwrite-file");
|
|
54
83
|
if (overwrites.length > 0) {
|
|
55
84
|
findings.push({
|
|
@@ -119,6 +148,27 @@ export async function runDoctor(opts) {
|
|
|
119
148
|
message: `${file} is missing the required hstack line`,
|
|
120
149
|
});
|
|
121
150
|
}
|
|
151
|
+
// Description budget (ADR-0011, Option F). Descriptions are the always-loaded
|
|
152
|
+
// routing index — ~3k tokens at 40 words each, ~29.7k before the rewrite —
|
|
153
|
+
// paid at turn zero of every session in every consuming repo, including
|
|
154
|
+
// sessions that invoke nothing. The rule shipped with the rewrite; this
|
|
155
|
+
// finding is what stops it regressing. Measured against the package template,
|
|
156
|
+
// because the consumer's copies are framework files `framework-drift` already
|
|
157
|
+
// covers.
|
|
158
|
+
const overBudget = descriptionsOverBudget(templateDir);
|
|
159
|
+
if (overBudget.length > 0) {
|
|
160
|
+
findings.push({
|
|
161
|
+
level: "warn",
|
|
162
|
+
category: "description-budget",
|
|
163
|
+
message: `${overBudget.length} skill/agent description(s) over the ${WORD_BUDGET}-word budget ` +
|
|
164
|
+
`(ADR-0011) — a description names the trigger, the body carries the rest`,
|
|
165
|
+
detail: overBudget
|
|
166
|
+
.map((d) => ` ${d.name} — ${d.words} words, ${d.chars} chars` +
|
|
167
|
+
(d.chars > CHAR_BUDGET && d.words <= WORD_BUDGET ? " (over the character ceiling)" : "") +
|
|
168
|
+
` [${d.relpath}]`)
|
|
169
|
+
.join("\n"),
|
|
170
|
+
});
|
|
171
|
+
}
|
|
122
172
|
// merge-hooks actions survive pruneNoopActions when the coord notification
|
|
123
173
|
// hooks are missing from .claude/settings.json, or when that file is
|
|
124
174
|
// unparseable (which update refuses to touch).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|