hstack 0.7.0 → 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.
Files changed (99) hide show
  1. package/CHANGELOG.md +277 -0
  2. package/README.md +39 -13
  3. package/VERSION +1 -1
  4. package/dist/commands/doctor.js +51 -1
  5. package/dist/commands/doctor.js.map +1 -1
  6. package/dist/commands/update.js +8 -2
  7. package/dist/commands/update.js.map +1 -1
  8. package/dist/lib/descriptions.js +167 -0
  9. package/dist/lib/descriptions.js.map +1 -0
  10. package/dist/lib/diff.js +1 -1
  11. package/dist/lib/git.js +16 -0
  12. package/dist/lib/git.js.map +1 -1
  13. package/dist/lib/wire.js +108 -4
  14. package/dist/lib/wire.js.map +1 -1
  15. package/dist/manifest.js +17 -2
  16. package/dist/manifest.js.map +1 -1
  17. package/package.json +3 -1
  18. package/template/.claude/agents/adversarial-reviewer.md +16 -64
  19. package/template/.claude/agents/app-architect.md +12 -49
  20. package/template/.claude/agents/data-architect.md +13 -51
  21. package/template/.claude/agents/data-specialist.md +5 -50
  22. package/template/.claude/agents/implementer.md +8 -65
  23. package/template/.claude/agents/kernel-fit-analyst.md +7 -68
  24. package/template/.claude/agents/planner.md +7 -42
  25. package/template/.claude/agents/product-discovery.md +12 -48
  26. package/template/.claude/agents/product-manager.md +8 -43
  27. package/template/.claude/agents/researcher.md +5 -41
  28. package/template/.claude/agents/security-reviewer.md +19 -54
  29. package/template/.claude/agents/spec-author.md +18 -52
  30. package/template/.claude/agents/stack-architect.md +14 -43
  31. package/template/.claude/agents/test-strategist.md +16 -57
  32. package/template/.claude/agents/ui-ux-briefer.md +6 -36
  33. package/template/.claude/agents/verifier.md +13 -45
  34. package/template/.claude/skills/hstack-adr-new/SKILL.md +6 -33
  35. package/template/.claude/skills/hstack-adversarial-review/SKILL.md +31 -52
  36. package/template/.claude/skills/hstack-adversarial-review/references/finding-categories.md +157 -0
  37. package/template/.claude/skills/hstack-app-architecture/SKILL.md +2 -29
  38. package/template/.claude/skills/hstack-branch/SKILL.md +4 -31
  39. package/template/.claude/skills/hstack-brownfield-init/SKILL.md +10 -37
  40. package/template/.claude/skills/hstack-change-new/SKILL.md +4 -31
  41. package/template/.claude/skills/hstack-change-plan/SKILL.md +21 -32
  42. package/template/.claude/skills/hstack-commit/SKILL.md +7 -35
  43. package/template/.claude/skills/hstack-configure/SKILL.md +7 -34
  44. package/template/.claude/skills/hstack-coord/SKILL.md +3 -39
  45. package/template/.claude/skills/hstack-data-architecture/SKILL.md +4 -30
  46. package/template/.claude/skills/hstack-data-review/SKILL.md +3 -42
  47. package/template/.claude/skills/hstack-finalize/SKILL.md +30 -49
  48. package/template/.claude/skills/hstack-flag/SKILL.md +9 -48
  49. package/template/.claude/skills/hstack-greenfield-init/SKILL.md +9 -36
  50. package/template/.claude/skills/hstack-help/SKILL.md +11 -37
  51. package/template/.claude/skills/hstack-implement/SKILL.md +28 -58
  52. package/template/.claude/skills/hstack-kernel-fit-promote/SKILL.md +7 -46
  53. package/template/.claude/skills/hstack-kernel-fit-scan/SKILL.md +5 -60
  54. package/template/.claude/skills/hstack-kernel-fit-scan/references/slack-setup.md +42 -0
  55. package/template/.claude/skills/hstack-kernel-fit-triage/SKILL.md +12 -50
  56. package/template/.claude/skills/hstack-module-spec/SKILL.md +5 -32
  57. package/template/.claude/skills/hstack-product-discovery/SKILL.md +5 -31
  58. package/template/.claude/skills/hstack-research/SKILL.md +3 -33
  59. package/template/.claude/skills/hstack-scaffold/SKILL.md +2 -29
  60. package/template/.claude/skills/hstack-security-review/SKILL.md +5 -43
  61. package/template/.claude/skills/hstack-ship/SKILL.md +43 -53
  62. package/template/.claude/skills/hstack-stack-decide/SKILL.md +3 -30
  63. package/template/.claude/skills/hstack-story-draft/SKILL.md +6 -33
  64. package/template/.claude/skills/hstack-tech-debt-new/SKILL.md +4 -31
  65. package/template/.claude/skills/hstack-tech-debt-resolve/SKILL.md +9 -44
  66. package/template/.claude/skills/hstack-tech-debt-stale/SKILL.md +10 -37
  67. package/template/.claude/skills/hstack-tech-debt-wontfix/SKILL.md +8 -35
  68. package/template/.claude/skills/hstack-telemetry/SKILL.md +5 -30
  69. package/template/.claude/skills/hstack-test-plan/SKILL.md +23 -46
  70. package/template/.claude/skills/hstack-ui-brief/SKILL.md +3 -30
  71. package/template/.claude/skills/hstack-verify/SKILL.md +26 -48
  72. package/template/KERNEL.md +410 -0
  73. package/template/scripts/compute-merge-readiness.mjs +780 -0
  74. package/template/scripts/coord/coord_scan.py +121 -22
  75. package/template/scripts/run-gates.sh +388 -0
  76. package/template/scripts/telemetry/insights/kernel_fit.py +1 -1
  77. package/template/scripts/telemetry/insights/token_economics.py +181 -8
  78. package/template/scripts/telemetry/parsers/sidecars.py +61 -0
  79. package/template/scripts/telemetry/parsers/transcripts.py +135 -22
  80. package/template/scripts/telemetry/render.py +68 -3
  81. package/template/scripts/telemetry/report.py +16 -4
  82. package/template/scripts/telemetry/run_kernel_fit.py +6 -2
  83. package/template/scripts/telemetry/session_id.py +139 -0
  84. package/template/scripts/validate-spec.mjs +3303 -0
  85. package/template/templates/adr.md +7 -0
  86. package/template/templates/adversarial-review.md +5 -5
  87. package/template/templates/ci-cd.md +14 -0
  88. package/template/templates/coord-message.md +3 -2
  89. package/template/templates/data-architecture.md +3 -6
  90. package/template/templates/kernel-fit-finding.md +2 -2
  91. package/template/templates/kernel-fit-flag.md +2 -2
  92. package/template/templates/plan.md +4 -0
  93. package/template/templates/product-brief.md +2 -2
  94. package/template/templates/roadmap.md +41 -0
  95. package/template/templates/security-review.md +1 -1
  96. package/template/templates/telemetry-sidecar.md +56 -13
  97. package/template/templates/test-plan.md +1 -1
  98. package/template/CLAUDE.md +0 -443
  99. package/template/templates/mvp-scope.md +0 -34
@@ -1,38 +1,20 @@
1
1
  ---
2
2
  name: hstack-ship
3
- description: |
4
- Use this skill when every artifact for a change is at terminal status and the engineer wants the final merge-readiness scorecard and a generated PR description. The Skill is the merge gate's prelude — it checks that every CI gate's preconditions are met, computes the scorecard, and produces the PR description body. It does not perform the merge; the engineer opens or marks the PR ready-for-review themselves. Examples:
5
-
6
- <example>
7
- Context: Every artifact for the billing-overage change is at terminal status and the engineer wants to open the PR.
8
- user: "/hstack:ship 2026-05-billing-overage-warning"
9
- assistant: "I'll compute the scorecard: spec at ready-to-ship, test-plan passed, plan completed, security-review passed, ui-brief drafted, figma-handoff ready, data-review passed, verification passed, adversarial-review findings-resolved, resolves-tech-debt items at in-progress (GT-11). PR description will land in hstack/specs/changes/<id>/pr-body.md for you to paste; after merge, run /hstack:finalize to flip the TD to resolved."
10
- <commentary>
11
- The Skill is mechanical — it reads frontmatter and computes the gate result. No subagent is invoked. If any gate fails, the Skill names the failing artifact and halts.
12
- </commentary>
13
- </example>
14
-
15
- <example>
16
- Context: The engineer tries to ship a change whose adversarial-review is still at findings-open.
17
- user: "/hstack:ship 2026-06-knowledge-citations"
18
- assistant: "I'll halt — adversarial-review is at findings-open. Three findings still at status: open with no resolution. Resolve those via the existing adversarial-review.md before re-running ship."
19
- <commentary>
20
- The Skill names the exact blocker and the exact remediation path. It does not advance any status itself; ship is read-only across the artifact set.
21
- </commentary>
22
- </example>
3
+ description: Use when every artifact for a change is at terminal status and the change needs its merge-readiness scorecard and a generated PR body. Read-only — it does not merge, and post-merge cleanup is `/hstack:finalize`.
23
4
  tools:
24
5
  - Read
25
6
  - Write
26
7
  - Grep
27
8
  - Glob
28
9
  - Bash
29
- - "{{TODO-SCRIPT: hstack/scripts/validate-spec.ts — validates every artifact's frontmatter}}"
30
- - "{{TODO-SCRIPT: hstack/scripts/compute-merge-readiness.ts — computes the nine-gate scorecard from artifact frontmatter}}"
10
+ - "node hstack/scripts/validate-spec.mjs — validates every artifact's frontmatter"
11
+ - "node hstack/scripts/compute-merge-readiness.mjs — computes the twelve-gate scorecard from frontmatter and git"
12
+ - "hstack/scripts/run-gates.sh — runs the pattern lints GT-03 reads the exit code of"
31
13
  ---
32
14
 
33
15
  ## Purpose
34
16
 
35
- `hstack-ship` is the final merge-readiness Skill. It reads every artifact's frontmatter for the change, computes the nine-gate scorecard from `hstack-gates.yml`, and generates a PR description body. It does not invoke any subagent and does not write to any artifact — `ship` is read-only across the change-spec, plan, reviews, and verification.
17
+ `hstack-ship` is the final merge-readiness Skill. It runs the twelve-gate merge-readiness scorecard over the change's artifacts and the PR diff, and generates a PR description body. It does not invoke any subagent and does not write to any artifact — `ship` is read-only across the change-spec, plan, reviews, and verification.
36
18
 
37
19
  ## When to invoke
38
20
 
@@ -53,23 +35,30 @@ The Skill does not pre-halt on artifact non-terminal status — that is what the
53
35
 
54
36
  ## Orchestration steps
55
37
 
56
- 1. **Read every change artifact.** Read `spec.md`, `plan.md`, `test-plan.md`, `security-review.md`, `data-review.md` (when surfaces includes db), `ui-brief.md` and `figma-handoff.md` (when surfaces includes ui), `verification.md`, `adversarial-review.md`. Capture each artifact's `status` and key gating fields.
38
+ 1. **Run the pattern lints.** `hstack/scripts/run-gates.sh --change <change-id> --suite lint` when `hstack/lints/` carries rule files. Keep the exit code GT-03 is computed from it and from nothing else.
57
39
 
58
- 2. **Compute the twelve-gate scorecard.** Run `{{TODO-SCRIPT: hstack/scripts/compute-merge-readiness.ts}}` against the artifact set, or inline the equivalent logic:
59
- - GT-01: spec presence — change folder exists with non-draft change-spec, or PR carries `trivial: true`.
60
- - GT-02: diff within scope — every file in the PR diff (against the merge target) is a subset of `change-spec.in-scope`.
61
- - GT-03: pattern lints — every `hstack/lints/*.yaml` rule passes (the Skill runs `{{TODO-SCRIPT: hstack/scripts/run-gates.sh}}` for this and reads the exit code).
62
- - GT-04: adversarial-review at `findings-resolved`.
63
- - GT-05: security-review at `passed` or `concerns-acknowledged`.
64
- - GT-06: data-review at `passed` or `concerns-acknowledged` (when applicable).
65
- - GT-07: ui-brief at `drafted` and figma-handoff at `ready` (when applicable).
66
- - GT-08: `user-stories` non-empty UNLESS `internal-tooling: true` (Category A) UNLESS `enables` non-empty (Category B). The audit-chain assumption: a Category-B spec's user value lives in one of the change-specs named in `enables`; this gate does not transitively verify that downstream spec has `user-stories` non-empty — that's the downstream's GT-08 check, run at its own ship time.
67
- - GT-09: every cross-reference rule (CG-01..CG-04) passes.
68
- - GT-10: test-plan at `passed` or `concerns-acknowledged`, and `verification.test-plan-coverage` shows no missing tenant-isolation tests and no out-of-budget performance assertions.
69
- - GT-11: When `change-spec.resolves-tech-debt` is non-empty: (a) every referenced tech-debt must exist and be at `status: in-progress` with `resolution-attempted-at` set; (b) the adversarial-review must contain the AR-07 Acceptance-satisfied confirmation enumerating each TD's Acceptance bullets against the diff; (c) no referenced tech-debt may have a non-null `resolved-by` already (that would indicate a double-resolution attempt). When `resolves-tech-debt` is empty, GT-11 is `not-applicable`.
70
- - GT-12 (SP-13 mutual exclusion): `internal-tooling: true` AND `enables` non-empty is forbidden. Hard FAIL. Reciprocity (SP-14): for every id in `enables`, the named downstream spec must exist on disk and must list this change-id in its `enabled-by` array. Missing downstream specs are a FAIL (forward references are only legal at authoring time — by ship time, the downstream must be scaffolded so reciprocity holds). The reverse direction (`enabled-by` entries that point at non-existent or non-listing upstream specs) is also FAIL.
40
+ 2. **Compute the twelve-gate scorecard.** Run `node hstack/scripts/compute-merge-readiness.mjs <change-id> --json [--gates-exit <code from step 1>]`. The script reads every artifact's frontmatter, the diff against the merge target, and the git branch, and returns one verdict per gate — `pass`, `fail`, `unknown`, `not-applicable` or `deferred`. `fail` and `unknown` block; "not evaluated" is not "passed".
71
41
 
72
- 3. **Frontmatter validation.** Run `{{TODO-SCRIPT: hstack/scripts/validate-spec.ts}}` across every artifact. Any FM-* or per-type validation failure blocks ship.
42
+ Do not re-derive any gate in prose. The gates below are the **contract** what each gate means, one line each — and `compute-merge-readiness.mjs` is the **only** place they are computed. `--gates` prints the same registry from the script itself.
43
+
44
+ | Gate | Contract |
45
+ | --- | --- |
46
+ | GT-01 | Spec presence: change folder exists with a change-spec past `draft`, or the change carries `trivial: true`. |
47
+ | GT-02 | Diff within scope: every changed file is a subset of `change-spec.in-scope`, plus hstack's own artifact trail. Mandatory even for `trivial: true`. |
48
+ | GT-03 | Pattern lints: every `hstack/lints/*.yaml` rule passes, read from `run-gates.sh`'s exit code. |
49
+ | GT-04 | `adversarial-review.md` at `findings-resolved`. |
50
+ | GT-05 | `security-review.md` at `passed` or `concerns-acknowledged`. |
51
+ | GT-06 | `data-review.md` at `passed` or `concerns-acknowledged`, when `surfaces` includes `db`. |
52
+ | GT-07 | `ui-brief.md` at `drafted` and `figma-handoff.md` at `ready`, when `surfaces` includes `ui`. |
53
+ | GT-08 | `user-stories` non-empty, unless exactly one carve-out is declared: `internal-tooling: true` (A), non-empty `enables` (B), `area: bootstrap` (C). Category B is an audit chain, not a transitive check — the downstream spec's user value is the downstream's own GT-08. |
54
+ | GT-09 | Every cross-reference rule CG-01..CG-04 passes. **Deferred**: the range is named but the four rules are stated nowhere, so the script reports `deferred` with that reason rather than inventing them. |
55
+ | GT-10 | `test-plan.md` at `passed` or `concerns-acknowledged`, and `verification.test-plan-coverage` shows no missing tenant-isolation tests and no out-of-budget performance assertions. |
56
+ | GT-11 | When `resolves-tech-debt` is non-empty: every referenced tech-debt exists at `status: in-progress` with `resolution-attempted-at` set, none already carries a `resolved-by`, and the adversarial-review carries its AR-07 Acceptance-satisfied confirmation. `not-applicable` when the array is empty. |
57
+ | GT-12 | SP-13 mutual exclusion (`internal-tooling: true` **and** non-empty `enables` is a hard FAIL) plus SP-14 reciprocity in both directions — a dangling `enables` or a non-reciprocating `enabled-by` is a FAIL, because by ship time the downstream must be scaffolded. |
58
+
59
+ Eleven of the twelve are computed from frontmatter, the diff and the branch alone — no artifact body is read (kernel § Reading artifacts). GT-11's AR-07 half is the single exception, and the script reads that one subsection rather than that file.
60
+
61
+ 3. **Frontmatter validation.** Run `node hstack/scripts/validate-spec.mjs` across every artifact. Any FM-* or per-type validation failure blocks ship.
73
62
 
74
63
  4. **Generate the PR description body.** Write `hstack/specs/changes/<change-id>/pr-body.md` containing:
75
64
  - Title: the change-spec's `Problem` first sentence, prefixed with the change id.
@@ -99,31 +88,32 @@ The Skill does not auto-commit any artifact status transitions. `pr-body.md` is
99
88
 
100
89
  - One commit when `pr-body.md` is written or updated. Commit message: `ship(<change-id>): pr-body`.
101
90
 
91
+ ## Session boundary
92
+
93
+ `ship` is a natural session cut: the auto-commit above left `pr-body.md` and the scorecard on disk, so the conversation holds nothing the next phase needs. The cut-notice format, the kickoff-prompt template and the context-block rules are in `KERNEL.md` § Session boundaries; this Skill's two variables are:
94
+
95
+ ```
96
+ HSTACK-CUT: ship complete — cut recommended before the merge, then finalize.
97
+ ```
98
+
99
+ and the next command, `/hstack:finalize <change-id>`.
100
+
102
101
  ## Idempotency contract
103
102
 
104
- - Re-running on the same change: re-reads every artifact and recomputes the scorecard. `pr-body.md` is rewritten if any artifact has changed since the prior run; otherwise a no-op.
103
+ - Re-running on the same change: re-reads every artifact and recomputes the scorecard. `pr-body.md` is rewritten if any artifact has changed since the prior run; otherwise a no-op. When the existing `pr-body.md` carries engineer edits beyond the generated template, surface a diff and ask before rewriting — never silently overwrite hand-written PR prose.
105
104
  - Re-running after fixing a failing gate: the scorecard reports the new state.
106
105
 
107
106
  ## Stop conditions
108
107
 
109
108
  Beyond the kernel's general stop conditions:
110
109
 
111
- - A required artifact is missing on disk.
112
- - Any artifact's frontmatter cannot be parsed.
110
+ - The change folder or the change-spec is missing on disk, or any artifact's frontmatter cannot be parsed. Both exit `compute-merge-readiness.mjs` with code 2 and a named cause — surface it verbatim rather than scoring a partial set.
113
111
  - GT-02 (diff within scope) fails — this is a hard halt with a clear message naming the out-of-scope files; the engineer either reshapes the change-spec via `spec-author` or splits via the multi-module pattern.
112
+ - GT-02 reports `unknown` because HEAD is the merge target. There is no PR diff to score from the default branch; check out `change/<change-id>` (`/hstack:branch <change-id>`) and re-run.
114
113
 
115
114
  ## Failure modes
116
115
 
117
116
  - **Trivial PRs.** When the change-spec carries `trivial: true`, several gates are skipped per the kernel. The Skill still computes the diff-within-scope and pattern-lint gates (GT-02 and GT-03 remain mandatory even for trivial PRs).
118
- - **Parent-change (multi-module) records.** When the change-spec is a coordination record (`children` non-empty), the Skill computes scorecards for every child and produces a parent-level summary. The parent reaches ready-to-ship only when every child does.
119
- - **Pattern-lint failure.** Surface the failing rule and the offending lines. The fix is via a new `hstack-implement` invocation against an appropriate phase (or a scope amendment if the lint surfaced new in-scope needs).
120
-
121
- ## Anti-patterns
122
-
123
- - Never write status transitions on any artifact from this Skill. Ship is read-only across the artifact set.
124
- - Never call `gh pr create` or perform the merge. The engineer opens the PR.
125
- - Never silently pass a gate. Every FAIL names the artifact and field.
126
- - Never collapse the twelve gates into a single PASS / FAIL. The scorecard is per-gate.
127
- - Never flip a tech-debt status from this Skill. That is `/hstack:finalize`'s job and only runs post-merge. Ship surfaces the directive; it does not perform the write.
128
- - Never extend `change-spec.in-scope` to make GT-02 pass — the scope amendment goes through `spec-author`, not this Skill.
129
- - Never overwrite `pr-body.md` content the engineer has hand-edited without confirmation. If the file exists with edits beyond the template, surface a diff and ask before rewriting.
117
+ - **Parent-change (multi-module) records.** When the change-spec is a coordination record (`children` non-empty), run the script once per child id and produce a parent-level summary. The parent reaches ready-to-ship only when every child does.
118
+ - **Pattern-lint failure.** Surface the failing rule and the offending lines from the captured output. The fix is via a new `hstack-implement` invocation against an appropriate phase (or a scope amendment if the lint surfaced new in-scope needs).
119
+ - **A gate reports `unknown`.** Something could not be evaluated — git is unavailable, the merge target does not resolve, or the lint runner was not run. `unknown` blocks exactly like `fail`: report what was not evaluated and why, and do not present the change as ready.
@@ -1,25 +1,6 @@
1
1
  ---
2
2
  name: hstack-stack-decide
3
- description: |
4
- Use this skill when the engineer wants to decide stack choices and capture each as an ADR. The Skill is Phase 4 of `/hstack:greenfield-init`, the stack-decision step of `/hstack:brownfield-init` when stack ADRs are missing, or a standalone atom for mid-project layer swaps (replacing auth, switching the database, rotating the hosting provider). It invokes the `stack-architect` subagent for the technical-discovery interview, then routes each layer's decision through `/hstack:adr-new` (which invokes `spec-author`) with pre-populated Context / Decision / Alternatives. The Consequences challenge prompt fires fresh on every ADR regardless of pre-population. Examples:
5
-
6
- <example>
7
- Context: Phase 4 of greenfield-init opens after app-architecture is current. hstack/config.yaml's default-stack declaration is set.
8
- user: "/hstack:stack-decide"
9
- assistant: "Loading brief, data-architecture, app-architecture, default-stack declaration. Defaults cover framework / database / hosting / auth — I'll fast-path those to a single rollup ADR. Observability is undeclared in config; I'll deep-dive on that layer. Expected: 2 ADRs (rollup + observability) routed through spec-author."
10
- <commentary>
11
- Default-stack fast-path collapses 80% of the interview when defaults match. Only layers explicitly flagged for deep-dive or undeclared in config get the full constraint interview.
12
- </commentary>
13
- </example>
14
-
15
- <example>
16
- Context: Mid-project, the team decides to replace Supabase Auth with Clerk.
17
- user: "/hstack:stack-decide --layer auth"
18
- assistant: "Standalone mode. Loading the existing auth ADR, threat-model, hardening-checklist. Constraint interview first (engineering capacity, scale horizon, compliance posture), then surfacing 2–3 Clerk alternatives, then routing to spec-author for the new ADR with supersedes: [<predecessor>]. The predecessor's reciprocal superseded-by writes atomically with the new ADR."
19
- <commentary>
20
- Standalone mode runs against a single layer. The supersedes / superseded-by reciprocal pair is mandatory; spec-author handles both halves atomically per the kernel's reciprocal-pair atomicity rule.
21
- </commentary>
22
- </example>
3
+ description: Use to decide stack layers — framework, database, auth, hosting, observability — and capture each as an ADR. Greenfield Phase 4, the brownfield stack step when stack ADRs are missing, or a standalone mid-project layer swap.
23
4
  tools:
24
5
  - Read
25
6
  - Write
@@ -30,7 +11,7 @@ tools:
30
11
  - Task
31
12
  - "{{TODO-SKILL: /hstack:adr-new — invoked via spec-author handoff for ADR authoring}}"
32
13
  - "{{TODO-SKILL: /hstack:research — invoked for unfamiliar-territory deep-dives}}"
33
- - "{{TODO-SCRIPT: hstack/scripts/validate-spec.ts — frontmatter validator}}"
14
+ - "node hstack/scripts/validate-spec.mjs — frontmatter validator"
34
15
  ---
35
16
 
36
17
  ## Purpose
@@ -52,6 +33,7 @@ tools:
52
33
  - `hstack/config.yaml` at `init-status: minimal-complete` or later, with the default-stack declaration present (set in greenfield-init Phase 0 or via `/hstack:configure default-stack`).
53
34
  - `hstack/context/app-architecture.md` at `status: current` (greenfield/brownfield mode). In standalone mode, the atom may run without app-architecture only if the layer being swapped doesn't depend on architecture decisions (rare).
54
35
  - `hstack/templates/adr.md` present.
36
+ - No layer choice contradicts `data-architecture.md`'s `assumes-database`. A non-Postgres choice against `assumes-database: postgres` is never honored silently — halt and surface, and the engineer either refreshes the upstream atom or revises the constraint.
55
37
  - Existing ADRs read at session start to set the next sequential ADR id and detect supersession candidates.
56
38
 
57
39
  ## Orchestration steps
@@ -97,12 +79,3 @@ tools:
97
79
 
98
80
  - **spec-author handoff fails partway** (e.g., Consequences challenge produces a finding the engineer doesn't accept). The pending ADR sits at `draft`; the engineer either revises or routes through `/hstack:configure adr-author <id>` per spec-author's recovery path.
99
81
  - **Research subagent unavailable when needed.** Persist constraint interview state; resume later.
100
-
101
- ## Anti-patterns
102
-
103
- - Never write to `hstack/adr/` from this Skill directly. ADR authoring is `spec-author`'s exclusive ownership per kernel rule.
104
- - Never let pre-population skip the Consequences challenge prompt. Pre-population covers Context / Decision / Alternatives; Consequences fires fresh.
105
- - Never propose stack options before constraints are concrete.
106
- - Never bypass the upstream check (app-architecture must be `current` in greenfield/brownfield mode).
107
- - Never silently honor a non-Postgres DB choice when `data-architecture.md`'s `assumes-database: postgres` says otherwise. Halt and surface.
108
- - Never split the supersedes / superseded-by reciprocal pair across two commits in standalone mode.
@@ -1,25 +1,6 @@
1
1
  ---
2
2
  name: hstack-story-draft
3
- description: |
4
- Use this skill when a user-facing change needs a story drafted or refined, anchored on an existing persona, with a concrete success metric and the user-visible edge cases enumerated. The Skill orchestrates the `product-manager` subagent and is conditional — it does not run when the parent change-spec is Category A (`internal-tooling: true`) or Category B (`enables` non-empty), since both carve-outs satisfy SP-09 without a story. Examples:
5
-
6
- <example>
7
- Context: The engineer just scaffolded a billing-overage change-spec and needs a linked user story before SP-09 lets the spec advance past draft.
8
- user: "Draft a story for the billing overage warning, anchored on the growth-marketer persona."
9
- assistant: "I'll invoke product-manager to walk the five story sections with the growth-marketer persona as the anchor. The story id will land in the configured story store; the change-spec's user-stories array updates reciprocally."
10
- <commentary>
11
- Stories are gated by SP-09 (`user-stories` non-empty UNLESS `internal-tooling: true` UNLESS `enables` non-empty). The Skill produces the story before the change-spec can advance, and writes the reciprocal `linked-change-specs` entry on the story.
12
- </commentary>
13
- </example>
14
-
15
- <example>
16
- Context: A story exists but the engineer wants to refine the success metric, which the product-manager flagged as too vague.
17
- user: "Refine STORY-2026-05-014 — sharpen the success metric."
18
- assistant: "I'll invoke product-manager with the existing story as the proposal layer. The other sections are accept-or-correct; the success-metric field gets the full interview treatment."
19
- <commentary>
20
- Refinement reuses the same orchestration with the existing story as the proposal context. The Skill does not re-walk every field; the subagent reads the existing content and targets the field the engineer named.
21
- </commentary>
22
- </example>
3
+ description: "Use when a user-facing change needs a story drafted or refined against an existing persona. Conditional — skipped when the parent change-spec is `internal-tooling: true` or has a non-empty `enables` array."
23
4
  tools:
24
5
  - Read
25
6
  - Write
@@ -31,7 +12,7 @@ tools:
31
12
  - "{{TODO-MCP: Notion MCP — required when configured story store is Notion}}"
32
13
  - "{{TODO-MCP: Linear MCP — required when configured story store is Linear}}"
33
14
  - "{{TODO-MCP: GitHub MCP — required when configured story store is GitHub Issues}}"
34
- - "{{TODO-SCRIPT: hstack/scripts/validate-spec.ts — validates story frontmatter and ST-01/ST-02/ST-03}}"
15
+ - "node hstack/scripts/validate-spec.mjs — validates story frontmatter and ST-01/ST-02/ST-03"
35
16
  ---
36
17
 
37
18
  ## Purpose
@@ -59,13 +40,13 @@ Before any work:
59
40
  - If the parent change-spec carries `internal-tooling: true`, halt and surface: "Story not required — change is Category A (internal tooling, never on a user path)."
60
41
  - If the parent change-spec carries `enables` non-empty, halt and surface: "Story not required — change is Category B (foundational prerequisite; user value lives in <enables-ids>). Draft a story against the downstream spec instead."
61
42
  - If the parent change-spec carries BOTH `internal-tooling: true` AND `enables` non-empty, halt with SP-13 violation: "Categories A and B are mutually exclusive. Pick one via `spec-author`."
62
- - Read `hstack/context/vision.md`, `mvp-scope.md`, and the personas index (required by `product-manager`'s session-start protocol).
43
+ - Read `hstack/context/vision.md`, `roadmap.md`, and the personas index (required by `product-manager`'s session-start protocol).
63
44
 
64
45
  ## Orchestration steps
65
46
 
66
47
  1. **Determine mode.** Draft a new story (no `--story` argument) or refine an existing one (`--story <id>` argument). Read the existing story when refining.
67
48
 
68
- 2. **Invoke `product-manager`.** Use the Task tool with `subagent_type: product-manager` and context = [kernel, `hstack/templates/story.md`, vision, mvp-scope, personas store, parent change-spec when known, existing story when refining]. The subagent runs the five-section interview — Who and Why, What Shipping Looks Like, Success Metric, Edge Cases the User Cares About, Out of Scope for This Story — with confirmation gates.
49
+ 2. **Invoke `product-manager`.** Use the Task tool with `subagent_type: product-manager` and context = [kernel, `hstack/templates/story.md`, vision, roadmap, personas store, parent change-spec when known, existing story when refining]. The subagent runs the five-section interview — Who and Why, What Shipping Looks Like, Success Metric, Edge Cases the User Cares About, Out of Scope for This Story — with confirmation gates.
69
50
 
70
51
  3. **Verify the persona anchor exists.** Per ST-01, the story's `persona` field must reference an existing persona at `current`. If the engineer names a persona that does not exist, `product-manager` halts and runs a sub-interview to author it first (or the engineer chooses an existing one).
71
52
 
@@ -75,7 +56,7 @@ Before any work:
75
56
 
76
57
  6. **Persist.** When the story store is external (Notion/Linear/GitHub), `product-manager` writes via the MCP and produces a local sync stub at `hstack/stories/<id>.md` referencing the external record. When the store is `hstack/stories/`, the file is written directly.
77
58
 
78
- 7. **Validate.** Run `{{TODO-SCRIPT: hstack/scripts/validate-spec.ts}}` against the story — ST-01 (persona references existing), ST-02 (linked-change-specs non-empty at `in-flight`), ST-03 (success metric non-empty string).
59
+ 7. **Validate.** Run `node hstack/scripts/validate-spec.mjs <path>` against the story — ST-01 (persona references existing), ST-02 (linked-change-specs non-empty at `in-flight`), ST-03 (success metric non-empty string).
79
60
 
80
61
  ## Outputs
81
62
 
@@ -102,18 +83,10 @@ Beyond the kernel's general stop conditions:
102
83
  - The configured story-store MCP is unreachable. Halt.
103
84
  - The named persona does not exist and the engineer declines the sub-interview to author it.
104
85
  - The success metric the engineer offers is not concretely measurable. `product-manager` re-prompts; the Skill halts after a reasonable number of re-prompts.
105
- - The story would drift outside `mvp-scope.md`. `product-manager` flags; the Skill asks whether to update mvp-scope (via `hstack-configure --interview mvp-scope`) or defer the story.
86
+ - The story would drift outside the roadmap's Now horizon. `product-manager` flags; the Skill asks whether to update the roadmap (via `hstack-configure --interview roadmap`) or defer the story.
106
87
 
107
88
  ## Failure modes
108
89
 
109
90
  - **Parent change-spec is `internal-tooling: true` (Category A) or `enables` non-empty (Category B).** Halt early; the story is unnecessary. For Category B, redirect the engineer to draft a story against the downstream change-spec named in `enables`.
110
91
  - **Reciprocal write to the parent change-spec would advance its status.** It should not — the reciprocal write only touches the `user-stories` array. If the validator detects a status change, halt and ask.
111
92
  - **Validator fails.** Halt and surface; the engineer rewords the failing field.
112
-
113
- ## Anti-patterns
114
-
115
- - Never anchor a story on an invented persona. The persona either exists at `current` or is authored first via a sub-interview.
116
- - Never bypass the Edge Cases challenge prompt, even on refinement.
117
- - Never write a story without a concretely measurable success metric.
118
- - Never silently fall back to a local story file when the configured external store's MCP is unreachable.
119
- - Never write reciprocal `user-stories` entries to a change-spec at a non-draft status without going through the `spec-author`'s field-change machinery — except for the array-append case explicitly carved out by `product-manager`'s contract.
@@ -1,25 +1,6 @@
1
1
  ---
2
2
  name: hstack-tech-debt-new
3
- description: |
4
- Use this skill when the engineer needs to capture a tech-debt item — a known compromise the team agreed to live with for now. The Skill orchestrates the `spec-author` subagent through a six-section interview for the TD body (genuine open-ended authoring); the reciprocal `creates-tech-debt` write on the originating change-spec is performed by the Skill directly per ADR-0001 (no second spec-author invocation). Both halves of the reciprocal pair (TD-01) land in a single atomic commit; spec-author defers its terminal-state auto-commit when invoked under this Skill so the Skill can include both files in one commit. Examples:
5
-
6
- <example>
7
- Context: The billing-overage change shipped with a one-off Tailwind class for warning-yellow because the design token isn't yet exposed; the engineer wants to log it.
8
- user: "/hstack:tech-debt-new --origin 2026-05-billing-overage-warning overage-banner-tailwind-class"
9
- assistant: "I'll invoke spec-author for the tech-debt interview. The six sections cover Title, Why we took the shortcut, What it costs us, Fix sketch, Pre-conditions for fixing, Acceptance. Reciprocally, I'll add this tech-debt id to the change-spec's creates-tech-debt array."
10
- <commentary>
11
- Reciprocity per TD-01 is load-bearing. Without the back-reference, audit queries cannot answer "who put this here?" without grepping every change-spec. Per ADR-0001, the TD body is authored by spec-author (interview) and the reciprocal `creates-tech-debt` write on the change-spec is performed by the Skill directly; both files land in one atomic commit.
12
- </commentary>
13
- </example>
14
-
15
- <example>
16
- Context: The adversarial-reviewer surfaced a deliberate trade-off that should be tracked as tech-debt rather than fixed in the change.
17
- user: "F-03 routes to tech-debt. /hstack:tech-debt-new --origin 2026-06-knowledge-citations cookie-samesite-attributes"
18
- assistant: "I'll invoke spec-author. The reciprocal write lands on the change-spec; the adversarial-review's finding gets resolution: tech-debt:<this-td-id> once the artifact is created."
19
- <commentary>
20
- This is the routing the adversarial-review's resolution discipline assumes. The tech-debt is created here, then referenced from the adversarial-review's `findings[].resolution`. The Skill is the only path because spec-author owns reciprocal writes.
21
- </commentary>
22
- </example>
3
+ description: Use to capture a new tech-debt item — a compromise the team is agreeing to live with for now — with its reciprocal back-reference on the originating change-spec. Capture only; the three closure paths are separate Skills.
23
4
  tools:
24
5
  - Read
25
6
  - Write
@@ -28,7 +9,7 @@ tools:
28
9
  - Glob
29
10
  - Bash
30
11
  - Task
31
- - "{{TODO-SCRIPT: hstack/scripts/validate-spec.ts — validates tech-debt frontmatter and TD-01..TD-03}}"
12
+ - "node hstack/scripts/validate-spec.mjs — validates tech-debt frontmatter and TD-01..TD-03"
32
13
  ---
33
14
 
34
15
  ## Purpose
@@ -77,9 +58,9 @@ Before any work:
77
58
 
78
59
  6. **Proposed-diff preview (confirmation gate).** Per the kernel's AI-writes-humans-confirm contract for mechanical operations, print the proposed reciprocal-write diff (the `creates-tech-debt` array append on the change-spec, the `updated` bump) and ask "Proceed with these writes? (Y/n)". Default Yes. On `n`, halt without staging the change-spec edit; the TD file remains unstaged so the engineer can `git checkout -- <td-file>` to discard.
79
60
 
80
- 7. **Validate and atomic-commit both files.** Run `{{TODO-SCRIPT: hstack/scripts/validate-spec.ts}}` against the new TD and (when `--origin` is set) the modified change-spec. TD-01 (reciprocity), TD-02 (severity:critical requires target-resolve-by — v1 surfaces only), TD-03 (no field rewrites once resolved; v1 informational) all checked. On validation pass, `git add` both files and commit with message `tech-debt(TD-NNNN): open` (with `(introduced-by: <change-spec-id>)` appended when applicable). The reciprocal pair (TD `introduced-by` ↔ change-spec `creates-tech-debt`) lands in this single atomic commit. On validation failure, halt; both files remain unstaged for the engineer to inspect or discard.
61
+ 7. **Validate and atomic-commit both files.** Run `node hstack/scripts/validate-spec.mjs <path>` against the new TD and (when `--origin` is set) the modified change-spec. TD-01 (reciprocity), TD-02 (severity:critical requires target-resolve-by — v1 surfaces only), TD-03 (no field rewrites once resolved; v1 informational) all checked. On validation pass, `git add` both files and commit with message `tech-debt(TD-NNNN): open` (with `(introduced-by: <change-spec-id>)` appended when applicable). The reciprocal pair (TD `introduced-by` ↔ change-spec `creates-tech-debt`) lands in this single atomic commit. On validation failure, halt; both files remain unstaged for the engineer to inspect or discard.
81
62
 
82
- 8. **Status note.** The new artifact lands at `status: open`. Advancing to `in-progress` or `resolved` is a separate later operation, not this Skill's domain.
63
+ 8. **Status note.** The new artifact lands at `status: open`. Advancing to `in-progress` or `resolved` is a separate later operation, not this Skill's domain. Nor does this Skill ever overwrite an existing tech-debt item: a body revision on an item being actively worked goes through a direct `spec-author` invocation.
83
64
 
84
65
  ## Outputs
85
66
 
@@ -112,11 +93,3 @@ Beyond the kernel's general stop conditions:
112
93
  - **Reciprocal write to the change-spec fails (e.g., the change-spec's frontmatter is broken).** Halt before commit; the TD authoring half also rolls back unstaged. The engineer fixes the change-spec frontmatter manually (broken YAML is hand-fixed and validated; if the change-spec body needs prose authoring corrections, `spec-author` can resume the change-spec since change-spec body editing is interview-driven, but `spec-author` cannot touch the `creates-tech-debt` reciprocal field per kernel — the Skill performs that append on the re-run). Then re-run `/hstack:tech-debt-new` — the Skill is idempotent on the TD half (spec-author resumes the existing partial file) and idempotent on the reciprocal append (a no-op if the TD id is already in the array).
113
94
  - **The change-spec is at `shipped` or `archived` status.** TD-03 forbids rewrites on resolved items, but the change-spec at `shipped` may still accept `creates-tech-debt` array appends — surface and confirm with the engineer before writing.
114
95
  - **Validator fails TD-01.** Halt before commit; the partial state on disk is unstaged. The engineer reconciles by running the Skill again — the reciprocal half is idempotent and the TD half resumes from the existing file.
115
-
116
- ## Anti-patterns
117
-
118
- - Never invent a tech-debt id. Sequential per the implicit rule.
119
- - Never write a tech-debt item without the Why-we-took-the-shortcut section. Debt without context is paperwork.
120
- - Never write `origin: <change-spec-id>` without the reciprocal `creates-tech-debt` write on that change-spec.
121
- - Never advance status past `open` from this Skill. Status transitions happen on the fix side, not the capture side.
122
- - Never overwrite an existing tech-debt item from this Skill. Updates happen via direct `spec-author` invocation when the item is being actively worked on.
@@ -1,34 +1,6 @@
1
1
  ---
2
2
  name: hstack-tech-debt-resolve
3
- description: |
4
- Use this skill when the engineer wants to start work on resolving a known tech-debt item. The Skill is the canonical entry point into the resolution flow: it prints the tech-debt's full body, walks each Pre-condition for engineer confirmation (a structured-elicitation loop per the kernel's Mechanical operations section), halts on any unmet pre-condition, and on confirmation performs direct mechanical writes (per ADR-0001, no spec-author invocation): flips the tech-debt to `in-progress`, scaffolds a resolution change folder with `resolves-tech-debt` pre-populated and the Acceptance section quoted into Target Behavior. Both halves of the reciprocal pair (TD ↔ change-spec) land in a single atomic commit. Examples:
5
-
6
- <example>
7
- Context: The team agreed to live with a hardcoded Tailwind class until the design token system exposed `--warning-yellow-300`. The token landed yesterday; now the team wants to fix TD-0042.
8
- user: "/hstack:tech-debt-resolve TD-0042-overage-banner-tailwind-class"
9
- assistant: "I'll print TD-0042 in full, walk each Pre-condition for your confirmation (the design token bullet should now be met), then flip the TD to in-progress and scaffold the resolution change-spec with the Acceptance section quoted into Target Behavior. After the scaffold, continue with /hstack:test-plan."
10
- <commentary>
11
- The Skill is the only authoring path that flips a tech-debt out of `open`. The kernel forbids manual frontmatter edits to tech-debt status. Pre-conditions are prose in v1 and require engineer confirmation; the Skill logs that confirmation into the scaffolded change-spec's Open Questions section so the adversarial-reviewer can later verify the team didn't rationalize away an unmet pre-condition.
12
- </commentary>
13
- </example>
14
-
15
- <example>
16
- Context: An engineer attempts to start resolving a tech-debt whose Pre-conditions reference an ADR that has not been accepted.
17
- user: "/hstack:tech-debt-resolve TD-0019-event-ordering-fallback"
18
- assistant: "I'll halt — TD-0019's Pre-conditions name 'ADR-0034 must be accepted before we pick a strategy', and ADR-0034 is at `proposed`. Resolve that first via /hstack:adr-new or by advancing ADR-0034 to `accepted`."
19
- <commentary>
20
- Some pre-conditions are mechanically checkable (ADR exists at `accepted`, file exists, related TD at `resolved`). The Skill checks those mechanically and halts on failure. Prose pre-conditions still require engineer confirmation. Mechanical halts cannot be overridden by engineer confirmation — the upstream artifact must actually change state first.
21
- </commentary>
22
- </example>
23
-
24
- <example>
25
- Context: An engineer wants to resolve a tech-debt but only partially — the change addresses 2 of 3 Acceptance bullets.
26
- user: "/hstack:tech-debt-resolve TD-0027-rls-cleanup --partial"
27
- assistant: "I'll halt — partial resolution is not supported in v1. Either author a new tech-debt via /hstack:tech-debt-new for the portion this change will fix and leave TD-0027 at `open`, or expand the change's scope to satisfy all Acceptance bullets."
28
- <commentary>
29
- Per the kernel's tech-debt resolution rules, a change-spec either fully resolves a TD or it doesn't. Partial work creates audit ambiguity ("did this fix it?") and breaks the AR-07 Acceptance-satisfied finding lens. The Skill refuses --partial flags and forces the engineer to make the split explicit.
30
- </commentary>
31
- </example>
3
+ description: Use to start fixing an `open` tech-debt item — walks its Pre-conditions, flips it to `in-progress`, and scaffolds the resolution change-spec. The fix path, as opposed to the wontfix and stale closure paths.
32
4
  tools:
33
5
  - Read
34
6
  - Write
@@ -37,7 +9,7 @@ tools:
37
9
  - Glob
38
10
  - Bash
39
11
  - Task
40
- - "{{TODO-SCRIPT: hstack/scripts/validate-spec.ts — validates the TD frontmatter flip and the scaffolded change-spec frontmatter}}"
12
+ - "node hstack/scripts/validate-spec.mjs — validates the TD frontmatter flip and the scaffolded change-spec frontmatter"
41
13
  ---
42
14
 
43
15
  ## Purpose
@@ -59,7 +31,7 @@ Optional:
59
31
  - `--area <module>`: override the area for the scaffolded change-spec. Default: the TD's `related-modules[0]` if non-empty; otherwise the Skill asks.
60
32
  - `--slug <slug>`: override the slug for the resolution change-spec. Default: `resolve-<td-slug-suffix>` (e.g., `resolve-overage-banner-tailwind-class`).
61
33
 
62
- The `--partial` flag is explicitly rejected v1 does not support partial resolution.
34
+ The `--partial` flag is explicitly rejected. Partial resolution is not supported in v1: a change-spec either fully resolves a tech-debt item (listed in `resolves-tech-debt`, satisfying every Acceptance bullet) or it does not. A change that addresses only some of the Acceptance bullets stays off the `resolves-tech-debt` list and the TD remains at `in-progress` for a follow-up change. This is the kernel's "one change-spec, one bounded contract" discipline. An engineer tempted to split a TD into smaller pieces authors multiple TDs via `/hstack:tech-debt-new` instead.
63
35
 
64
36
  ## Preconditions
65
37
 
@@ -93,10 +65,10 @@ Mechanical halts cannot be overridden by engineer confirmation; the upstream art
93
65
  Ask "Proceed with these writes? (Y/n)". Default Yes. On `n`, halt.
94
66
 
95
67
  6. **Write the TD (direct write + immediate validation).** Edit `hstack/tech-debt/<td-id>.md`:
96
- - **Defensive Resolution Log check.** If `## Resolution Log` is not present in the file (legacy TDs authored before the template included this section), append `\n## Resolution Log\n` to the end of the file first.
68
+ - Defensive log-header check per the kernel: if `## Resolution Log` is absent, append it before writing the entry.
97
69
  - Edit frontmatter: `status: open → in-progress`, `resolution-attempted-at: <today>`, `updated: <today>`.
98
70
  - Append the Resolution Log entry: `status: open → in-progress on <today> by <owner>. Resolution change-spec: <change-id>.`
99
- - Run `{{TODO-SCRIPT: hstack/scripts/validate-spec.ts}}` against the file. On validation failure, halt — do NOT proceed to step 7. Unstaged changes can be reverted via `git checkout -- <td-file>`.
71
+ - Run `node hstack/scripts/validate-spec.mjs <path>` against the file. On validation failure, halt — do NOT proceed to step 7. Unstaged changes can be reverted via `git checkout -- <td-file>`.
100
72
 
101
73
  7. **Scaffold the resolution change folder.** (Do not call `/hstack:change-new` to avoid duplicate interview prompts.)
102
74
  - Create `hstack/specs/changes/<change-id>/`.
@@ -104,7 +76,7 @@ Mechanical halts cannot be overridden by engineer confirmation; the upstream art
104
76
  - Pre-populate the "Resolves Tech-Debt" prose section: a pointer to `../../tech-debt/<td-id>.md` followed by the TD's Acceptance section quoted verbatim under the heading "Acceptance from TD-NNNN".
105
77
  - Pre-populate the Open Questions section with the Pre-conditions confirmation log from step 2 (the `(bullet, met, justification)` triples), so the adversarial-reviewer can later verify the team did not rationalize away an unmet pre-condition.
106
78
  - Pre-populate Problem section opener: "Resolves [<td-id>](../../tech-debt/<td-id>.md): <TD Title>. The TD was introduced by <introduced-by> and has been at `open` since <created>."
107
- - Run `{{TODO-SCRIPT: hstack/scripts/validate-spec.ts}}` against the seeded change-spec. On validation failure, halt — the TD write from step 6 must be reverted manually via `git checkout -- <td-file>` before re-running the Skill.
79
+ - Run `node hstack/scripts/validate-spec.mjs <path>` against the seeded change-spec. On validation failure, halt — the TD write from step 6 must be reverted manually via `git checkout -- <td-file>` before re-running the Skill.
108
80
 
109
81
  8. **Offer branch creation.** Mirror `/hstack:change-new`'s branch hygiene step: offer to create `change/<change-id>` from the current branch. Default Yes.
110
82
 
@@ -112,6 +84,8 @@ Mechanical halts cannot be overridden by engineer confirmation; the upstream art
112
84
 
113
85
  10. **Direct engineer to next step.** Print: "Resolution change scaffolded at `hstack/specs/changes/<change-id>/`. Continue with `/hstack:test-plan <change-id>` when ready. The TD is now at `in-progress` and will be flipped to `resolved` by `/hstack:finalize` after the resolving change is merged."
114
86
 
87
+ From here the change runs the normal per-change workflow unchanged — test-plan → security-review → data-review (when `db` in `surfaces`) → plan → implement → verify → adversarial-review → ship → finalize. Two points in that sequence are tech-debt-specific and are enforced by their own Skills: the `adversarial-reviewer` produces the mandatory Acceptance-satisfied confirmation (AR-07) because `resolves-tech-debt` is non-empty, and `/hstack:ship` checks GT-11 — every referenced TD at `in-progress`, and that confirmation present in the adversarial-review.
88
+
115
89
  ## Outputs
116
90
 
117
91
  - `hstack/tech-debt/<td-id>.md` advanced to `status: in-progress` with `resolution-attempted-at` and an appended Resolution Log entry.
@@ -127,7 +101,7 @@ Mechanical halts cannot be overridden by engineer confirmation; the upstream art
127
101
 
128
102
  - Re-running on a TD already at `in-progress`: the Skill reads the TD's Resolution Log to find the existing resolving change-spec id, verifies the change folder exists, and reports its current state ("Resolution in progress at `<change-id>`; current change-spec status: `<status>`. Continue with `<next-skill>`."). No new scaffold is created.
129
103
  - Re-running mid-interview after a halt: the Skill reads `hstack/.session-state/td-resolve-<td-id>.yaml` and resumes at the next un-confirmed Pre-condition.
130
- - Re-running after the TD's `resolved-by` is set but status is still `in-progress` (an inconsistent state): the Skill halts and surfaces the inconsistency. Reconciliation is manual: either (a) `git checkout HEAD -- hstack/tech-debt/<td-id>.md` to revert to the prior committed state if the inconsistency came from an interrupted finalize, or (b) directly edit the TD frontmatter to set `resolved-by: null` and re-run `validate-spec.ts`. Do not invoke `spec-author` for this reconciliation — the kernel forbids it for reciprocal-back-reference writes.
104
+ - Re-running after the TD's `resolved-by` is set but status is still `in-progress` (an inconsistent state): the Skill halts and surfaces the inconsistency. Reconciliation is manual: either (a) `git checkout HEAD -- hstack/tech-debt/<td-id>.md` to revert to the prior committed state if the inconsistency came from an interrupted finalize, or (b) directly edit the TD frontmatter to set `resolved-by: null` and re-run `node hstack/scripts/validate-spec.mjs <path>`.
131
105
 
132
106
  ## Stop conditions
133
107
 
@@ -147,12 +121,3 @@ Beyond the kernel's general stop conditions:
147
121
  - **TD's Acceptance is too vague to satisfy mechanically.** The Skill scaffolds anyway but flags in the change-spec's Open Questions that the adversarial-reviewer will need to interpret. The engineer is reminded that AR-07 makes Acceptance-satisfied a mandatory finding lens.
148
122
  - **Pre-condition confirmation session interrupted.** Resumable via the session-state file; engineer continues from the next un-confirmed bullet.
149
123
  - **A direct write fails mid-scaffold.** Halt before any commit. Per the new ordering (step 6 writes TD, step 7 writes change-spec, step 9 commits both atomically), no partial commit is possible — the failure leaves both files unstaged for the engineer to inspect or discard via `git checkout -- <file>`.
150
-
151
- ## Anti-patterns
152
-
153
- - Never invoke `spec-author` for the TD status flip. Per the kernel's Mechanical operations section (ADR-0001), this Skill performs the flip directly via the `Edit` tool. The kernel's "spec-author is the only subagent permitted to write" rule applies to subagents; this Skill runs in the main session.
154
- - Never accept blanket "all pre-conditions are met" confirmations. Each bullet must be individually confirmed with a one-sentence justification.
155
- - Never silently downgrade a mechanical halt to a soft warning. Mechanical halts represent upstream state that must actually change.
156
- - Never scaffold without quoting the TD's Acceptance into the change-spec's Resolves Tech-Debt section. The quote is what AR-07 checks against.
157
- - Never accept `--partial`. Direct the engineer to split the TD via `/hstack:tech-debt-new` instead.
158
- - Never proceed when the TD is at a terminal status. Resolved is resolved; wontfix is final.
@@ -1,25 +1,6 @@
1
1
  ---
2
2
  name: hstack-tech-debt-stale
3
- description: |
4
- Use this skill when a tech-debt item's original claim no longer reproduces because the surrounding code was rewritten, a dependency was upgraded, the bug was fixed incidentally as part of unrelated work, or the system the TD described no longer exists. This is distinct from `/hstack:tech-debt-wontfix`: wontfix says "the problem is still real but we choose to live with it"; stale-no-longer-reproducible says "the problem no longer exists, verifiably." The Skill runs a one-question structured-elicitation loop (a per-kernel Mechanical operations pattern), captures the verification evidence into the TD's frontmatter, and performs direct mechanical writes (per ADR-0001, no spec-author invocation): writes `stale-verified-at` and `stale-verification-method`, flips status `open → stale-no-longer-reproducible`, appends a Resolution Log entry, all in a single atomic commit. The new status is terminal — per TD-03, no field rewrites are permitted afterwards. Examples:
5
-
6
- <example>
7
- Context: TD-0042 captured a workaround needed because a Tiptap plugin had a known bug. The team upgraded Tiptap last week and the bug is fixed upstream; the workaround is still in the codebase but the underlying claim no longer holds.
8
- user: "/hstack:tech-debt-stale TD-0042-tiptap-paste-workaround"
9
- assistant: "I'll ask one question: what evidence shows the original claim no longer reproduces? On confirmation, the Skill writes stale-verified-at and stale-verification-method directly (per ADR-0001, no spec-author invocation), flips status to stale-no-longer-reproducible, and commits atomically. The new status is terminal."
10
- <commentary>
11
- Stale-no-longer-reproducible is the controlled exit for organic-decay closures. The kernel requires the verification evidence because "we don't reproduce it anymore" without an artefact is the kind of silent backlog-clearing that lets real debt slip through unaudited. Future engineers reading the TD see the explicit verification rather than just an unexplained closure.
12
- </commentary>
13
- </example>
14
-
15
- <example>
16
- Context: An engineer wants to use this Skill on a TD whose original problem IS still real but they no longer want to fix it.
17
- user: "/hstack:tech-debt-stale TD-0017-prompt-template-string-concat"
18
- assistant: "Wait — this is wontfix territory, not stale. Stale-no-longer-reproducible means the problem has verifiably gone away. If the prompt-template string-concat is still in the codebase and still has the original issue, the team is choosing to live with it (wontfix), not observing that it no longer exists (stale). I'll halt and direct you to /hstack:tech-debt-wontfix instead, OR you can show me evidence the string-concat code was actually removed and I'll proceed with stale."
19
- <commentary>
20
- The Skill applies a deliberate semantic check at the verification step. Misusing stale for a deferral-flavored closure corrupts the audit signal that distinguishes deliberate-deferral (wontfix) from organic-decay (stale). The engineer's verification evidence must describe an absence, not a preference.
21
- </commentary>
22
- </example>
3
+ description: Use to close a tech-debt item whose original claim no longer reproduces — the code was rewritten, a dependency shipped a fix, the system is gone. Stale describes a verified absence; `/hstack:tech-debt-wontfix` describes a choice.
23
4
  tools:
24
5
  - Read
25
6
  - Write
@@ -27,7 +8,7 @@ tools:
27
8
  - Grep
28
9
  - Glob
29
10
  - Bash
30
- - "{{TODO-SCRIPT: hstack/scripts/validate-spec.ts — validates the TD status flip and TD-07 (stale requires both verification fields non-null)}}"
11
+ - "node hstack/scripts/validate-spec.mjs — validates the TD status flip and TD-07 (stale requires both verification fields non-null)"
31
12
  ---
32
13
 
33
14
  ## Purpose
@@ -45,7 +26,7 @@ Invoke when a tech-debt item at `status: open` has a claim that no longer reprod
45
26
  - The bug was fixed incidentally as part of an unrelated change.
46
27
  - The system, module, or call path the TD described no longer exists.
47
28
 
48
- Do NOT invoke for deferrals ("we won't get to this") — those go to `/hstack:tech-debt-wontfix`. Do NOT invoke for TDs that are still observably true but the team is choosing not to fix — also `/hstack:tech-debt-wontfix`. The semantic distinction is load-bearing: stale describes an absence, wontfix describes a choice.
29
+ Do NOT invoke for deferrals ("we won't get to this") — those go to `/hstack:tech-debt-wontfix`. Do NOT invoke for TDs that are still observably true but the team is choosing not to fix — also `/hstack:tech-debt-wontfix`. The semantic distinction is load-bearing: stale describes an absence, wontfix describes a choice. Misusing `wontfix` for a claim that has aged out corrupts the audit signal that separates deliberate deferral from organic decay — the two statuses answer different retrospective questions, and a corpus that conflates them can answer neither.
49
30
 
50
31
  ## Inputs
51
32
 
@@ -59,20 +40,20 @@ Do NOT invoke for deferrals ("we won't get to this") — those go to `/hstack:te
59
40
 
60
41
  1. **Print the TD in full.** Read `hstack/tech-debt/<td-id>.md` and print Title, Why we took the shortcut, What it costs us, Fix sketch, Pre-conditions, Acceptance to the conversation. The engineer should re-read before committing to a stale-no-longer-reproducible closure; the verification step depends on understanding what the original claim actually was.
61
42
 
62
- 2. **Ask the verification question.** "What evidence shows this TD's claim no longer reproduces? Be specific — a grep result that returns nothing, a git log showing the dependent code was removed, a dependency upgrade that fixes the issue upstream, etc. (one sentence, 300 characters)". Capture the answer.
43
+ 2. **Ask the verification question.** "What evidence shows this TD's claim no longer reproduces?" The answer has to be checkable by someone who was not in the room — a command that returns nothing, a commit that removed the dependent code, a dependency version that carries the upstream fix, a system that no longer exists. Capture it as written; no length bound.
63
44
 
64
- 3. **Semantic check.** If the answer reads like a deferral or a preference rather than an absence ("we don't care anymore", "not worth it", "moved on", "low priority", "not blocking us"), halt with: "That reads like a wontfix rationale, not stale-no-longer-reproducible. Stale means the original problem has verifiably gone away — code removed, dependency upgraded, system retired. If the problem is still observably present and the team is choosing not to fix it, use /hstack:tech-debt-wontfix instead." The Skill does not write anything in this case.
45
+ 3. **Semantic check.** Stale means the problem no longer exists and someone else could verify that. The answer has to be a fact about the code, the dependency tree, or the deployed system — not a position on the problem. A sentence that says how the team now feels about the compromise is a wontfix rationale however it is phrased, and a sentence that names a removed call path is a stale verification however casually it is written. When it reads as a preference, halt with: "That reads like a wontfix rationale, not stale-no-longer-reproducible. Stale means the original problem has verifiably gone away — code removed, dependency upgraded, system retired. If the problem is still observably present and the team is choosing not to fix it, use /hstack:tech-debt-wontfix instead." The Skill does not write anything in this case.
65
46
 
66
47
  4. **Confirm.** Print the captured verification method and ask "Mark TD-NNNN as stale-no-longer-reproducible with this evidence? (Y/n)". Default Yes. Include a one-line summary of what will be written to disk so the engineer sees the proposed-diff before committing (per the kernel's AI writes / humans confirm contract for mechanical operations).
67
48
 
68
- 5. **Verify the answer length.** If the answer exceeds 300 characters, ask for a tighter version stale verification methods are short, specific, and load-bearing. If the engineer cannot tighten below 300 chars without losing evidence, the verification probably isn't structural enough to qualify as stale; consider whether wontfix is the right path.
49
+ 5. **Verify the answer is a fact, not a story.** Read it back against one test: could a third party run, read, or look up what it names and reach the same conclusion? If it names something checkable, it qualifies — one clause or four. If it is an account of why the problem stopped mattering, the problem is still there and this is a wontfix; surface that recommendation rather than writing the stale closure.
69
50
 
70
51
  6. **Write the stale transition (direct write).** Per the kernel's Mechanical operations section, this Skill performs the writes itself via the `Edit` tool — no `spec-author` invocation. Edit `hstack/tech-debt/<td-id>.md`:
71
- - **Defensive Resolution Log check.** If `## Resolution Log` is not present in the file (legacy TDs authored before the template included this section), append `\n## Resolution Log\n` to the end of the file first.
52
+ - Defensive log-header check per the kernel: if `## Resolution Log` is absent, append it before writing the entry.
72
53
  - Edit frontmatter: `stale-verified-at: <today>`, `stale-verification-method: <answer>`, `status: open → stale-no-longer-reproducible`, `updated: <today>`.
73
54
  - Append to the Resolution Log section: `status: open → stale-no-longer-reproducible on <today> by <owner>. Verification method: <answer>.`
74
55
 
75
- Run `{{TODO-SCRIPT: hstack/scripts/validate-spec.ts}}` against the file. TD-07 (stale-no-longer-reproducible requires both `stale-verified-at` and `stale-verification-method` non-null) must pass once the validator ships; until then, the proposed-diff preview in step 4 is the v1 substitute per the kernel's AI writes / humans confirm clause. On validation pass (or v1 proposed-diff acknowledgement), `git add` the file and commit with message `tech-debt(<td-id>): stale-no-longer-reproducible`. The three frontmatter writes plus the log append land in this single auto-commit, preserving atomicity. On validation failure, halt; unstaged changes can be reverted via `git checkout -- <td-file>`.
56
+ Run `node hstack/scripts/validate-spec.mjs <path>` against the file. TD-07 (stale-no-longer-reproducible requires both `stale-verified-at` and `stale-verification-method` non-null) must pass. On validation pass, `git add` the file and commit with message `tech-debt(<td-id>): stale-no-longer-reproducible`. The three frontmatter writes plus the log append land in this single auto-commit, preserving atomicity. On validation failure, halt; unstaged changes can be reverted via `git checkout -- <td-file>`.
76
57
 
77
58
  7. **Confirm completion.** Print: "TD-NNNN is now `stale-no-longer-reproducible`. Per TD-03, no further field rewrites are permitted on this artifact. If the original claim ever reappears, author a new tech-debt via `/hstack:tech-debt-new` rather than re-opening this one."
78
59
 
@@ -95,19 +76,11 @@ Do NOT invoke for deferrals ("we won't get to this") — those go to `/hstack:te
95
76
  Beyond the kernel's general stop conditions:
96
77
 
97
78
  - The TD does not exist or is at a non-`open` status. Halt with the status named.
98
- - The verification answer reads as a deferral or preference (per step 3). The Skill refuses to write and surfaces the wontfix recommendation.
99
- - The answer exceeds 300 characters and the engineer cannot tighten it without losing evidence. Halt and surface the wontfix recommendation — overly long stale verifications usually indicate the claim isn't actually absent.
79
+ - The verification answer is a preference about the problem rather than a fact about its absence (per step 3). The Skill refuses to write and surfaces the wontfix recommendation.
80
+ - The answer names nothing a third party could check. Halt and surface the wontfix recommendation — a verification that cannot be re-run by someone else is a preference about the problem, not evidence of its absence.
100
81
  - The engineer declines confirmation at step 4.
101
82
 
102
83
  ## Failure modes
103
84
 
104
85
  - **Direct write fails (filesystem, validator, or git).** Halt; the four frontmatter writes plus the Resolution Log append must land in a single auto-commit. Partial writes are not possible if the Skill aborts on validator failure before staging. Concrete recovery: `git checkout -- hstack/tech-debt/<td-id>.md` to revert to the prior committed state.
105
86
  - **Stale claim turns out to be reproducible after closure.** Per TD-03 the closed TD is immutable; the engineer authors a new tech-debt via `/hstack:tech-debt-new` describing the reappeared claim. The new TD references the closed one in its Title or Why-we-took-the-shortcut for audit-trail continuity.
106
-
107
- ## Anti-patterns
108
-
109
- - Never accept a stale verification that reads as a deferral. The check is mandatory and is the v1 defense against misusing stale to clear backlog without an actual claim-absence verification.
110
- - Never write `status: stale-no-longer-reproducible` without both `stale-verified-at` and `stale-verification-method` non-null. TD-07 enforces this at validation (once the validator ships); the Skill's structured-elicitation loop enforces it at write time.
111
- - Never invoke `spec-author` for this transition. Per the kernel's Mechanical operations section (ADR-0001), this Skill performs the writes directly. The status flip, two field writes, and Resolution Log append land atomically in a single Skill-driven commit.
112
- - Never re-open a stale-no-longer-reproducible TD. Per TD-03, the status is terminal — author a new TD instead if the claim reappears.
113
- - Never use this Skill as a faster path to `wontfix`. The semantic distinction (absence vs choice) is load-bearing for audit signal honesty. If the engineer is tempted to bypass `wontfix`'s two-question discipline by routing through stale, the Skill's semantic check (step 3) is the v1 defense.