hstack 0.16.0 → 0.17.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 (132) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +73 -163
  3. package/VERSION +1 -1
  4. package/dist/commands/doctor.js +18 -8
  5. package/dist/commands/doctor.js.map +1 -1
  6. package/dist/commands/init.js +7 -3
  7. package/dist/commands/init.js.map +1 -1
  8. package/dist/commands/update.js +9 -2
  9. package/dist/commands/update.js.map +1 -1
  10. package/dist/lib/descriptions.js +10 -17
  11. package/dist/lib/descriptions.js.map +1 -1
  12. package/dist/lib/wire.js +166 -138
  13. package/dist/lib/wire.js.map +1 -1
  14. package/dist/manifest.js +41 -29
  15. package/dist/manifest.js.map +1 -1
  16. package/package.json +3 -4
  17. package/template/.claude/agents/adversarial-reviewer.md +42 -50
  18. package/template/.claude/agents/app-architect.md +44 -96
  19. package/template/.claude/agents/data-architect.md +46 -89
  20. package/template/.claude/agents/test-strategist.md +39 -68
  21. package/template/.claude/skills/hstack-adr-new/SKILL.md +23 -73
  22. package/template/.claude/skills/hstack-adversarial-review/SKILL.md +46 -152
  23. package/template/.claude/skills/hstack-adversarial-review/references/finding-categories.md +80 -103
  24. package/template/.claude/skills/hstack-app-architecture/SKILL.md +43 -68
  25. package/template/.claude/skills/hstack-commit/SKILL.md +27 -68
  26. package/template/.claude/skills/hstack-data-architecture/SKILL.md +34 -56
  27. package/template/.claude/skills/hstack-promote/SKILL.md +55 -0
  28. package/template/.claude/skills/hstack-story/SKILL.md +58 -0
  29. package/template/.claude/skills/hstack-test-audit/SKILL.md +64 -0
  30. package/template/.claude/skills/hstack-wrap/SKILL.md +48 -0
  31. package/template/.claude/skills/hstack-wrap/references/pr-description.md +45 -0
  32. package/template/KERNEL.md +75 -318
  33. package/template/templates/adr.md +2 -18
  34. package/template/templates/app-architecture.md +38 -50
  35. package/template/templates/data-architecture.md +38 -89
  36. package/template/templates/infrastructure.md +54 -148
  37. package/template/templates/roadmap.md +6 -12
  38. package/template/templates/story.md +7 -13
  39. package/template/templates/tech-debt.md +2 -37
  40. package/template/templates/tech-stack.md +2 -12
  41. package/template/.claude/agents/data-specialist.md +0 -81
  42. package/template/.claude/agents/implementer.md +0 -97
  43. package/template/.claude/agents/kernel-fit-analyst.md +0 -129
  44. package/template/.claude/agents/planner.md +0 -75
  45. package/template/.claude/agents/product-discovery.md +0 -129
  46. package/template/.claude/agents/product-manager.md +0 -76
  47. package/template/.claude/agents/researcher.md +0 -87
  48. package/template/.claude/agents/security-reviewer.md +0 -88
  49. package/template/.claude/agents/spec-author.md +0 -89
  50. package/template/.claude/agents/stack-architect.md +0 -108
  51. package/template/.claude/agents/ui-ux-briefer.md +0 -75
  52. package/template/.claude/agents/verifier.md +0 -81
  53. package/template/.claude/skills/hstack-branch/SKILL.md +0 -76
  54. package/template/.claude/skills/hstack-brownfield-init/SKILL.md +0 -131
  55. package/template/.claude/skills/hstack-change-new/SKILL.md +0 -84
  56. package/template/.claude/skills/hstack-change-plan/SKILL.md +0 -108
  57. package/template/.claude/skills/hstack-configure/SKILL.md +0 -99
  58. package/template/.claude/skills/hstack-coord/SKILL.md +0 -95
  59. package/template/.claude/skills/hstack-data-review/SKILL.md +0 -93
  60. package/template/.claude/skills/hstack-finalize/SKILL.md +0 -140
  61. package/template/.claude/skills/hstack-flag/SKILL.md +0 -99
  62. package/template/.claude/skills/hstack-greenfield-init/SKILL.md +0 -148
  63. package/template/.claude/skills/hstack-help/SKILL.md +0 -153
  64. package/template/.claude/skills/hstack-implement/SKILL.md +0 -155
  65. package/template/.claude/skills/hstack-kernel-fit-promote/SKILL.md +0 -125
  66. package/template/.claude/skills/hstack-kernel-fit-scan/SKILL.md +0 -142
  67. package/template/.claude/skills/hstack-kernel-fit-scan/references/slack-setup.md +0 -42
  68. package/template/.claude/skills/hstack-kernel-fit-triage/SKILL.md +0 -121
  69. package/template/.claude/skills/hstack-module-spec/SKILL.md +0 -78
  70. package/template/.claude/skills/hstack-product-discovery/SKILL.md +0 -75
  71. package/template/.claude/skills/hstack-research/SKILL.md +0 -115
  72. package/template/.claude/skills/hstack-scaffold/SKILL.md +0 -113
  73. package/template/.claude/skills/hstack-security-review/SKILL.md +0 -95
  74. package/template/.claude/skills/hstack-ship/SKILL.md +0 -119
  75. package/template/.claude/skills/hstack-stack-decide/SKILL.md +0 -81
  76. package/template/.claude/skills/hstack-story-draft/SKILL.md +0 -92
  77. package/template/.claude/skills/hstack-tech-debt-new/SKILL.md +0 -95
  78. package/template/.claude/skills/hstack-tech-debt-resolve/SKILL.md +0 -123
  79. package/template/.claude/skills/hstack-tech-debt-stale/SKILL.md +0 -86
  80. package/template/.claude/skills/hstack-tech-debt-wontfix/SKILL.md +0 -77
  81. package/template/.claude/skills/hstack-telemetry/SKILL.md +0 -73
  82. package/template/.claude/skills/hstack-test-plan/SKILL.md +0 -159
  83. package/template/.claude/skills/hstack-ui-brief/SKILL.md +0 -81
  84. package/template/.claude/skills/hstack-verify/SKILL.md +0 -128
  85. package/template/scripts/compute-merge-readiness.mjs +0 -780
  86. package/template/scripts/coord/coord_scan.py +0 -681
  87. package/template/scripts/run-gates.sh +0 -388
  88. package/template/scripts/telemetry/__init__.py +0 -6
  89. package/template/scripts/telemetry/insights/__init__.py +0 -0
  90. package/template/scripts/telemetry/insights/contract_drift.py +0 -137
  91. package/template/scripts/telemetry/insights/kernel_fit.py +0 -438
  92. package/template/scripts/telemetry/insights/overengineering.py +0 -115
  93. package/template/scripts/telemetry/insights/quality_outcomes.py +0 -131
  94. package/template/scripts/telemetry/insights/token_economics.py +0 -302
  95. package/template/scripts/telemetry/insights/workflow_shape.py +0 -198
  96. package/template/scripts/telemetry/parsers/__init__.py +0 -0
  97. package/template/scripts/telemetry/parsers/bodies.py +0 -87
  98. package/template/scripts/telemetry/parsers/commits.py +0 -219
  99. package/template/scripts/telemetry/parsers/frontmatter.py +0 -322
  100. package/template/scripts/telemetry/parsers/sidecars.py +0 -61
  101. package/template/scripts/telemetry/parsers/transcripts.py +0 -294
  102. package/template/scripts/telemetry/render.py +0 -460
  103. package/template/scripts/telemetry/report.py +0 -150
  104. package/template/scripts/telemetry/run_kernel_fit.py +0 -95
  105. package/template/scripts/telemetry/session_id.py +0 -139
  106. package/template/scripts/validate-spec.mjs +0 -3303
  107. package/template/templates/adversarial-review.md +0 -54
  108. package/template/templates/bootstrap.md +0 -105
  109. package/template/templates/change-spec.md +0 -82
  110. package/template/templates/ci-cd.md +0 -41
  111. package/template/templates/coord-message.md +0 -56
  112. package/template/templates/data-review.md +0 -54
  113. package/template/templates/discovery/brainstorm.md +0 -69
  114. package/template/templates/discovery/forcing-questions.md +0 -76
  115. package/template/templates/discovery/project-brief.md +0 -53
  116. package/template/templates/figma-handoff.md +0 -38
  117. package/template/templates/glossary.md +0 -20
  118. package/template/templates/hardening-checklist.md +0 -73
  119. package/template/templates/incident-runbook.md +0 -57
  120. package/template/templates/kernel-fit-finding.md +0 -63
  121. package/template/templates/kernel-fit-flag.md +0 -52
  122. package/template/templates/module-spec.md +0 -49
  123. package/template/templates/persona.md +0 -38
  124. package/template/templates/plan.md +0 -53
  125. package/template/templates/product-brief.md +0 -56
  126. package/template/templates/security-review.md +0 -63
  127. package/template/templates/telemetry-sidecar.md +0 -227
  128. package/template/templates/test-plan.md +0 -119
  129. package/template/templates/threat-model.md +0 -54
  130. package/template/templates/ui-brief.md +0 -49
  131. package/template/templates/verification.md +0 -63
  132. package/template/templates/vision.md +0 -34
@@ -1,166 +1,60 @@
1
1
  ---
2
2
  name: hstack-adversarial-review
3
- description: Use only in a fresh Claude Code session — separate from the one that ran the implementeronce `verification.md` is at `passed` and the change is at `ready-for-review`. Orchestrates the `adversarial-reviewer`, which reads the change cold.
4
- tools:
5
- - Read
6
- - Write
7
- - Edit
8
- - Grep
9
- - Glob
10
- - Bash
11
- - Task
12
- - "node hstack/scripts/validate-spec.mjs — validates adversarial-review frontmatter and AR-01..AR-06"
13
- - "{{TODO-OTHER: fresh-session-attestation — in v1, the subagent self-attests the session is fresh; v2 substrate captures and compares Claude Code session ids automatically}}"
3
+ description: "Use in a fresh session — never the one that wrote the changeto review a PR that touches a sensitive surface. Findings land as a PR comment; the author is the one who fixes them."
14
4
  ---
15
5
 
16
6
  ## Purpose
17
7
 
18
- `hstack-adversarial-review` produces `adversarial-review.md` by orchestrating the `adversarial-reviewer` subagent in a Claude Code session separate from the one that ran the implementer. The subagent reads the change cold, and "no problems" is a claim it has to defend rather than a default it may fall into. In v1, fresh-session separation is honor-system; the Skill's first job is to remind the engineer of that.
8
+ `/hstack-adversarial-review <pr-number>` reads an open PR cold and reports what is wrong, missing,
9
+ drifted or weakened. It orchestrates the `adversarial-reviewer` subagent and posts the findings on
10
+ the PR. It writes no file and changes no code.
19
11
 
20
- Per ADR-0014 the review is not scored on its finding count. `findings-floor` stays in frontmatter as the area's expectation and lands in the telemetry sidecar, but nothing gates on it; the one count the artifact must argue for is zero (AR-01).
12
+ Reviews are judgments, not evidence (kernel § Review). An empty findings list means the reviewer
13
+ found nothing, not that nothing is there — which is why an empty result is defended rather than
14
+ returned.
21
15
 
22
16
  ## When to invoke
23
17
 
24
- Invoke after `verification.md` reaches `status: passed`, in a **fresh Claude Code session**. The Skill opens with a clear instruction to the engineer naming the requirement. If the engineer reports they are in the same session as the implementer, halt and ask them to start a new session.
25
-
26
- ## Inputs
27
-
28
- - `<change-id>` (required, positional): the change-spec id.
29
-
30
- ## Preconditions
31
-
32
- Before any work:
33
-
34
- - **Fresh-session attestation.** The Skill's first action is to print: "This Skill must run in a Claude Code session separate from the one that ran `hstack-implement`. The kernel's authoring-and-review-never-share-a-session principle is honor-system in v1; v2 substrate will verify via session-id comparison. Confirm you are in a fresh session before I proceed." Halt until the engineer confirms.
35
- - Verify the change-spec exists and is at `status: ready-for-review`.
36
- - Verify every required upstream artifact is at terminal status:
37
- - test-plan at `passed` or `concerns-acknowledged`
38
- - plan at `completed`
39
- - security-review at `passed` or `concerns-acknowledged`
40
- - data-review at `passed` or `concerns-acknowledged` when applicable
41
- - ui-brief at `drafted` and figma-handoff at `ready` when applicable
42
- - verification at `passed`
43
- - Set `findings-floor`: 3 default; 5 when `change-spec.area` is in {agent, auth, billing} per AR-06. It is recorded, not enforced.
44
-
45
- ## Orchestration steps
46
-
47
- 0. **Open the phase window (mechanical, no LLM turn, no commit).** The moment the preconditions above pass and *before* any subagent invocation, run `python3 hstack/scripts/telemetry/session_id.py` and keep its `session_id` and `now` values — they become `session_id` and `phase_opened_at` in the sidecar below (ADR-0009). On failure or a null session id, hold `null` for both and continue.
48
-
49
- 1. **Open with the fresh-session reminder.** Print the message verbatim; wait for the engineer's confirmation.
50
-
51
- 2. **Invoke `adversarial-reviewer`.** Use the Task tool with `subagent_type: adversarial-reviewer` and context = [kernel, `hstack/templates/adversarial-review.md`, change-spec, plan, test-plan, ui-brief and figma-handoff when present, security-review, data-review when present, verification, full diff, module-spec, threat-model, hardening-checklist, data-architecture, tech-stack]. Explicitly NOT included: any implementer conversation transcript or scratchpad.
52
-
53
- 3. **Findings generation across six categories.** The subagent sweeps security, scope-drift, invariant-breach, spec-compliance, data-integrity, and code-quality and reports what the sweep found — the categories are lenses, not buckets, and a change whose risk genuinely lives in one dimension produces findings in one category. `references/finding-categories.md`, alongside this file, is the calibration rubric (what each category means, what a real finding looks like, what filler looks like); the subagent reads it on demand, not on every run. Test-plan adherence is a first-class lens: missing edge-case tests surface as spec-compliance findings; missing tenant-isolation tests surface as data-integrity findings; unmet performance budgets surface as code-quality or data-integrity findings depending on cause; unmapped invariants in `verification.test-plan-coverage` surface as spec-compliance findings. **Test-immutability audit:** the subagent diffs every pre-existing test file against the branch base; any modification, deletion, or snapshot update without a matching `Ok to change/delete/update/refresh ...` authorization echo in a commit message is a mandatory finding under spec-compliance at minimum `severity: high`. Bulk snapshot-update flags visible in the diff or in CI logs escalate to `severity: critical`. This audit is mandatory and is not subject to the subagent's judgment about whether the finding is worth filing.
54
-
55
- 4. **The empty result is the one the artifact defends.** Per AR-01, a review that reaches `findings-open` or `findings-resolved` with an empty `findings` array must set `findings-fewer-than-floor: true` and write a defended `justification-when-fewer` plus a filled Findings Floor Justification section, enumerating what was looked for and why each sweep came back clean. "The change is small" alone is insufficient. Any count above zero passes AR-01; `findings_count` against `findings_floor` is reported to telemetry and read in aggregate, never as a per-review gate.
56
-
57
- 5. **Resolution discipline.** Each finding's `resolution` is one of:
58
- - `commit:<hash>` — must reference an existing commit on the change's branch (AR-04).
59
- - `tech-debt:<id>` — must reference an existing tech-debt artifact at `open` or `in-progress` (AR-05). When the engineer chooses this path, they invoke `hstack-tech-debt-new` to create the tech-debt artifact before this review terminates.
60
- - `justified-in-prose` — reserved for low-severity findings only. High-severity findings routed to `justified-in-prose` halt the Skill.
61
-
62
- 6. **Fresh-session attestation in frontmatter.** The subagent writes `fresh-session-attestation: "session <id>; opened <timestamp>; no prior implementer context loaded"`. v1 records this as honor-system text; v2 substrate captures the actual session id from Claude Code's session file.
63
-
64
- 7. **Findings-open is non-terminal.** The subagent does not advance `status: findings-resolved` until every finding has `status: resolved` and a `resolution` value.
65
-
66
- 8. **Owner response loop.** For each finding, the engineer (the change owner) responds with a resolution. The Resolution Log section records each response. The Skill walks the engineer through every finding sequentially.
67
-
68
- 9. **Validate.** Run `node hstack/scripts/validate-spec.mjs <path>` — AR-01 through AR-06.
69
-
70
- 10. **Change-spec advance (mechanical, only on `findings-resolved`, Skill-orchestrator write per ADR-0002).** When and only when the subagent returned with `adversarial-review.md` at `status: findings-resolved`, read `hstack/specs/changes/<change-id>/spec.md` and inspect its `status` frontmatter. If `status: ready-for-review`, print a proposed-diff preview of the change-spec edit (`status: ready-for-review → ready-to-ship`; `updated: <today>`) and prompt "Proceed with this change-spec advance? (Y/n)". Default Yes. On confirmation, perform the edit via the `Edit` tool, run `node hstack/scripts/validate-spec.mjs <path>` against the change-spec, then `git add` and commit with message `change-spec(<change-id>): ready-to-ship`. This is a separate commit from the adversarial-review transition commits, matching the verify and finalize precedents. If the change-spec is already at `ready-to-ship` or any downstream status (`shipped`, `archived`), this step is a no-op (idempotent on re-runs). When adversarial-review status is `findings-open` or `in-progress`, this step does not run — the change-spec remains at `ready-for-review` until every finding is resolved. The `adversarial-reviewer` subagent retains its critique-only lane and writes only `adversarial-review.md`; the cross-artifact advance is the Skill orchestrator's own write, per ADR-0002.
71
-
72
- ## Outputs
73
-
74
- - `hstack/specs/changes/<change-id>/adversarial-review.md` at `status: findings-resolved`.
75
- - When `adversarial-review.md` lands at `findings-resolved` and the change-spec was at `ready-for-review`: an edit to `hstack/specs/changes/<change-id>/spec.md` advancing `status: ready-for-review → ready-to-ship` and bumping `updated:` (per ADR-0002, written by the Skill orchestrator).
76
- - Optional new tech-debt artifacts produced via `hstack-tech-debt-new` invocations when findings route to `tech-debt:<id>`.
77
- - Optional new commits on the change's branch when findings route to `commit:<hash>` and the implementer is re-invoked (separately, via `hstack-implement`) to make the fix.
78
-
79
- ## Auto-commit triggers
80
-
81
- - Status transition to `in-progress` after Methodology lands.
82
- - Status transition to `findings-open` after all findings are written.
83
- - Status transition to `findings-resolved` when every finding has `status: resolved`.
84
- - Edits to the `findings` array.
85
- - Edits to any finding's `resolution`.
86
- - **Change-spec status transition `ready-for-review` → `ready-to-ship`** (per ADR-0002, Skill-orchestrator write). When `adversarial-review.md` reaches `findings-resolved`, the Skill orchestrator performs the change-spec advance directly via `Edit` (orchestration step 10), in a separate auto-commit with message `change-spec(<change-id>): ready-to-ship`. The change-spec becomes eligible for `hstack-ship` only after this commit lands. `hstack-ship` itself remains read-only across artifact statuses — it reads the already-written `ready-to-ship` and computes the merge-readiness scorecard. The `adversarial-reviewer` subagent does not write this transition; it stays in its critique-only lane.
87
-
88
- ## Telemetry sidecar
89
-
90
- At the change-spec advance commit (only when adversarial-review status is `findings-resolved`), write `hstack/specs/changes/<change-id>/.telemetry/adversarial-review.json` in the same `git add && git commit` as the change-spec advance. The sidecar is derivative of git + frontmatter (see `hstack/templates/telemetry-sidecar.md`). Schema:
91
-
92
- ```json
93
- {
94
- "schema_version": 2,
95
- "skill": "hstack-adversarial-review",
96
- "change_id": "<change-id>",
97
- "session_id": "<session id from step 0, or null>",
98
- "phase_opened_at": "<ISO-8601 from step 0, or null>",
99
- "phase_closed_at": "<ISO-8601, now — same write as this sidecar, or null>",
100
- "reviewed_at": "<ISO-8601, when status reached findings-resolved>",
101
- "findings_floor": <int, 3 or 5 per AR-06>,
102
- "findings_count": <int, length of frontmatter findings array>,
103
- "findings_fewer_than_floor": <bool>,
104
- "category_counts": {
105
- "security": <int>,
106
- "scope-drift": <int>,
107
- "invariant-breach": <int>,
108
- "spec-compliance": <int>,
109
- "data-integrity": <int>,
110
- "code-quality": <int>
111
- },
112
- "severity_counts": {
113
- "critical": <int>,
114
- "high": <int>,
115
- "medium": <int>,
116
- "low": <int>
117
- },
118
- "resolution_mix": {
119
- "commit": <int>,
120
- "tech-debt": <int>,
121
- "justified-in-prose": <int>
122
- },
123
- "fresh_session_attestation": "<verbatim copy of frontmatter field>",
124
- "halt_reasons": [<kernel halt-sentinel enum values, if any>]
125
- }
126
- ```
127
-
128
- When the review ends at `findings-open` or `in-progress` (no change-spec advance), the sidecar still lands with the same shape on whichever transition commit terminates the current run; `findings_fewer_than_floor` reflects the current value. `.telemetry/` is git-ignored. If the sidecar write fails, log and continue; the canonical commit must still land. Since ADR-0014 removed the quota this sidecar stopped being a fraud detector and became a description: `findings_count` against `findings_floor`, `category_counts`, `severity_counts` and `resolution_mix` describe what reviews are finding, and shifts in the joint distribution are the instrument for judging whether the judgment-based framing reads changes better or worse than the count did.
129
-
130
- The three phase-window fields (`session_id`, `phase_opened_at`, `phase_closed_at`) come from step 0 and from this write. Their rules — best-effort, unmeasured rather than zero, never a halt — are stated once in `hstack/templates/telemetry-sidecar.md` § The phase window, which is the canonical schema and wins over any Skill.
131
-
132
- ## Session boundary
133
-
134
- `adversarial-review` is a natural session cut: the auto-commit above left `adversarial-review.md` at its terminal status 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:
135
-
136
- ```
137
- HSTACK-CUT: adversarial-review complete — cut recommended before ship.
138
- ```
139
-
140
- and the next command, `/hstack:ship <change-id>`.
141
-
142
- ## Idempotency contract
143
-
144
- - Re-running on a `findings-resolved` review: the subagent reads the existing artifact and produces a no-op aside from `updated` timestamps, unless new code or artifacts have landed since the prior run (in which case new findings may be generated and the status drops back to `findings-open`).
145
- - Re-running mid-resolution after a halt: the subagent reads the partial artifact and resumes with the first finding still at `status: open`.
146
- - The change-spec advance step (step 10) is idempotent: a re-run against a change-spec already at `ready-to-ship` (or `shipped`, `archived`) produces a no-op for that step. The Skill does not re-advance and does not regress.
18
+ On a PR touching one of the sensitive surfaces the kernel § Review names. Every PR already gets
19
+ `/review` and `/security-review` through `/wrap`; this is the deep pass on top, and its whole value
20
+ is that the session running it never saw the change being written.
21
+
22
+ **In a fresh session.** State it in one sentence before starting — "this session has not seen the
23
+ implementation conversation" — and if that is not true, stop and open a new one. This is
24
+ honor-system, as the kernel says; a sentence is the whole protocol.
25
+
26
+ ## Steps
27
+
28
+ 1. **Load the change.** `gh pr view <n>` for the description, `gh pr diff <n>` for the diff, plus
29
+ the base commit so pre-existing files can be diffed. Read the living docs the diff touches,
30
+ `hstack/context/invariants.md`, and the frozen `threat-model.md`. Do not load, ask for, or
31
+ reconstruct the conversation that produced the change.
32
+ 2. **Invoke `adversarial-reviewer`** with that material. The subagent sweeps six lenses and returns
33
+ findings; it does not resolve them and does not touch the code.
34
+ 3. **The test-immutability audit is mandatory** and is not subject to anyone's judgment about
35
+ whether it is worth filing. Every test file that existed at the base is diffed; a modification
36
+ or deletion without its canonical authorization echo — `Ok to change test <name>` /
37
+ `Ok to delete test <name>`, in a commit message or the PR description is a finding at `high`
38
+ minimum. A bulk snapshot update is `critical`.
39
+ 4. **Post the findings** with `gh pr comment <n>`, or as a GitHub review when they are anchored to
40
+ lines. Each finding carries a severity, a category, the evidence in the diff, and what would
41
+ resolve it.
42
+ 5. **Resolution belongs to the author**: a corrective commit on the branch, or a tech-debt file
43
+ written in the same PR (kernel § Tech-debt). The reviewer never pushes the fix.
44
+
45
+ ## Output
46
+
47
+ One PR comment. No artifact, no status, no file in the repo.
147
48
 
148
49
  ## Stop conditions
149
50
 
150
- Beyond the kernel's general stop conditions:
151
-
152
- - Engineer has not confirmed they are in a fresh Claude Code session.
153
- - A required upstream artifact is non-terminal.
154
- - A high-severity security or tenant-isolation finding would route to `justified-in-prose`. Halt.
155
- - A `commit:<hash>` resolution would reference a commit not on the change's branch.
156
- - A `tech-debt:<id>` resolution would reference a non-existent tech-debt artifact (the engineer must invoke `hstack-tech-debt-new` first).
157
- - The review found nothing and the empty-result defence cannot be written honestly. Halt and surface; a defence nobody believes is worse than an open review.
158
- - The diff includes changes outside `change-spec.in-scope` that CI did not catch — surface a scope-drift finding and halt the CI gap as a separate concern.
159
- - An implementer transcript or scratchpad is visible in the session.
160
-
161
- ## Failure modes
51
+ Beyond the kernel's:
162
52
 
163
- - **Engineer claims fresh session but conversation shows prior implementer transcripts.** Halt; ask the engineer to truly start a new session.
164
- - **The review comes back empty and the defence feels thin.** Walk the six categories against `references/finding-categories.md` once more; if the sweep is still clean, the empty result is defended explicitly and on the record, not waved through.
165
- - **A finding routes to `tech-debt:<id>` but the engineer hasn't created the tech-debt artifact.** The Skill prompts to invoke `hstack-tech-debt-new`; the review does not terminate until the artifact exists.
166
- - **A commit hash named in `resolution` does not exist on the change's branch.** Halt — the engineer either re-references the correct commit or the resolution is reconsidered.
53
+ - The session has seen the implementation conversation. Halt and ask for a fresh one.
54
+ - The PR cannot be read, or its diff is unavailable.
55
+ - A living doc the review depends on is missing or stale. Say so in the findings; never invent its
56
+ content (kernel § Context docs).
57
+ - The sweep came back empty and the defence cannot be written honestly. Halt and surface it — a
58
+ defence nobody believes is worse than an open review.
59
+ - A high-severity finding is waved away without a fix or a tech-debt file. Do not silently retract:
60
+ restate it with the evidence, and leave it in the comment.
@@ -1,157 +1,134 @@
1
1
  # The six finding categories — a calibration rubric
2
2
 
3
- Reference file for `hstack-adversarial-review` and the `adversarial-reviewer`
4
- subagent. Read it when a category is unfamiliar, when a finding feels thin and
5
- you want to know whether it is real, or when calibrating severity against
6
- precedent. It is **not** a checklist: nothing here says how many findings a
7
- review should produce, and a review that lands entirely in one category is a
8
- correct outcome when the change carries its risk in one dimension (ADR-0014).
9
-
10
- The `category` value in a finding record is a controlled enum — the six names
11
- below, exactly — and AR-02 rejects anything else.
3
+ Reference file for `hstack-adversarial-review` and the `adversarial-reviewer` subagent. Read it
4
+ when a category is unfamiliar, when a finding feels thin and you want to know whether it is real,
5
+ or when calibrating a severity. It is **not** a checklist: nothing here says how many findings a
6
+ review should produce, and a review landing entirely in one category is the correct outcome when
7
+ the change carries its risk in one dimension (ADR-0014).
12
8
 
13
9
  ---
14
10
 
15
11
  ## security
16
12
 
17
- **What it means.** The change creates or widens a path an attacker can use, or
18
- weakens a control that was closing one. Distinct from `data-integrity`: this is
19
- about an adversary, not about accidental corruption.
13
+ **What it means.** The change creates or widens a path an attacker can use, or weakens a control
14
+ that was closing one. Distinct from `data-integrity`: this is about an adversary, not about
15
+ accidental corruption.
20
16
 
21
- **Real findings look like.** A new endpoint that reads a user-supplied id and
22
- queries by it without re-deriving the caller's scope. A prompt that
23
- concatenates retrieved document text into a system message. A secret moved from
24
- an env read to a literal. An auth check that runs after the side effect. A
25
- dependency bump that pulls a package with a known CVE the security-review did
26
- not see because the lockfile changed outside `in-scope`.
17
+ **Real findings look like.** A new endpoint that reads a user-supplied id and queries by it without
18
+ re-deriving the caller's scope. A prompt that concatenates retrieved document text into a system
19
+ message. A secret moved from an env read to a literal. An auth check that runs after the side
20
+ effect. A dependency bump that pulls a package with a known CVE.
27
21
 
28
- **Filler looks like.** "Consider adding rate limiting" on a change that touches
29
- no network surface. Restating a hardening-checklist item the security-review
30
- already scored `pass`, with no evidence from the diff that the score is wrong.
22
+ **Filler looks like.** "Consider adding rate limiting" on a change that touches no network surface.
23
+ Restating an item of the kernel's security checklist with no evidence from the diff that it was
24
+ missed.
31
25
 
32
- **Severity.** Anything exploitable by a non-authenticated caller, or that
33
- crosses a tenant boundary, is `critical` or `high` — never `medium` because it
34
- is unlikely. Likelihood belongs in the severity rationale, not in the level.
26
+ **Severity.** Anything exploitable by an unauthenticated caller, or that crosses a tenant boundary,
27
+ is `critical` or `high` — never `medium` because it is unlikely. Likelihood belongs in the severity
28
+ rationale, not in the level.
35
29
 
36
30
  ---
37
31
 
38
32
  ## scope-drift
39
33
 
40
- **What it means.** The diff touches things `change-spec.in-scope` does not
41
- name, or the change quietly grew a second purpose.
34
+ **What it means.** The diff touches things the PR description's announced perimeter does not name
35
+ (kernel § Scope rules), or the change quietly grew a second purpose.
42
36
 
43
- **Real findings look like.** A refactor of a shared util that no phase in
44
- `plan.md` asked for. A migration that alters a table outside the change's
45
- module. A "while I was in there" rename that makes the diff unreviewable. A new
46
- dependency added to satisfy a convenience the spec never asked for.
37
+ **Real findings look like.** A refactor of a shared util nothing in the change asked for. A
38
+ migration altering a table outside the change's module. A "while I was in there" rename that makes
39
+ the diff unreviewable. A new dependency satisfying a convenience nobody asked for.
47
40
 
48
- **Filler looks like.** Flagging a file the change-spec's globs do cover on a
49
- literal reading. Flagging generated files, lockfiles, or formatter output that
50
- the repo's conventions produce automatically.
41
+ **Filler looks like.** Flagging a file the announced perimeter does cover. Flagging generated
42
+ files, lockfiles or formatter output the repo's conventions produce automatically.
51
43
 
52
- **Severity.** Usually `medium`. It escalates when the drift lands in a module
53
- with its own module-spec invariants, because then it is also `invariant-breach`
54
- and CI's scope gate did not catch it.
44
+ **Severity.** Usually `medium`. It escalates when the drift lands on a path `invariants.md` covers,
45
+ because then it is also `invariant-breach`.
55
46
 
56
47
  ---
57
48
 
58
49
  ## invariant-breach
59
50
 
60
- **What it means.** Something the change-spec or the relevant module-spec
61
- declares as always-true is no longer always-true after this diff.
51
+ **What it means.** Something `hstack/context/invariants.md` or a living doc declares as always-true
52
+ is no longer always-true after this diff.
62
53
 
63
- **Real findings look like.** A module-spec that says "no direct SQL outside this
64
- module" and a new query in an adjacent file. A change-spec invariant about
65
- ordering that the new code path can violate under concurrency. An invariant
66
- that is still true but is now enforced by convention where it used to be
67
- enforced by a type or a constraint.
54
+ **Real findings look like.** An invariant about ordering that the new code path can violate under
55
+ concurrency. An invariant still true but now enforced by convention where it used to be enforced by
56
+ a type or a database constraint. A boundary a living doc describes — "no direct SQL outside this
57
+ module" and a new query in an adjacent file.
68
58
 
69
- **Filler looks like.** Paraphrasing an invariant back and calling it a risk.
70
- Naming an invariant the diff does not touch.
59
+ **Filler looks like.** Paraphrasing an invariant back and calling it a risk. Naming an invariant the
60
+ diff does not touch.
71
61
 
72
- **Severity.** `high` by default — an invariant that can break silently is worse
73
- than a bug that throws. Drop to `medium` only when the breach is caught by an
74
- existing test that will fail loudly.
62
+ **Severity.** `high` by default — an invariant that breaks silently is worse than a bug that throws.
63
+ Drop to `medium` only when an existing test fails loudly on the breach.
75
64
 
76
65
  ---
77
66
 
78
- ## spec-compliance
67
+ ## intent-compliance
79
68
 
80
- **What it means.** The diff and the artifacts disagree. This is the category
81
- with the widest surface and the one most often under-used.
69
+ **What it means.** The diff and what the PR says it does disagree. The widest category and the one
70
+ most often under-used. The PR description is the contract here: it names the perimeter, the Notion
71
+ feature, the shortcuts taken, the living docs updated.
82
72
 
83
- **Real findings look like.** An acceptance criterion in the change-spec with no
84
- corresponding behaviour in the diff. An edge case the `test-plan` promised and
85
- the diff did not land. A tenant-isolation test named in the test-plan and
86
- absent from the branch. An invariant in the change-spec that
87
- `verification.test-plan-coverage` maps to no observed test. Behaviour the
88
- implementation added that no artifact anticipated undeclared scope is a
89
- compliance gap in the other direction. **Any test-file modification without its
90
- canonical authorization echo** (see `KERNEL.md` § Test immutability); this one
91
- is mandatory and never subject to judgment about whether it is worth filing.
92
- When `resolves-tech-debt` is non-empty, any Acceptance bullet the diff leaves
93
- `partial` or `not-satisfied` (AR-07).
73
+ **Real findings look like.** Behaviour the description promises and the diff does not land.
74
+ Behaviour the diff adds that no line of the description anticipated — undeclared scope is a
75
+ compliance gap in the other direction. A living doc the change invalidated and left untouched
76
+ (kernel § Context docs). A conscious shortcut visible in the code and named nowhere. **Any
77
+ test-file modification without its canonical authorization echo** (`KERNEL.md` § Test immutability);
78
+ this one is mandatory and never subject to judgment about whether it is worth filing.
94
79
 
95
- **Filler looks like.** "The spec could have been clearer." Style disagreements
96
- with the plan's phase decomposition.
80
+ **Filler looks like.** "The description could have been clearer." Style disagreements with how the
81
+ work was sequenced.
97
82
 
98
- **Severity.** Unauthorized test changes: `high` minimum, `critical` for bulk
99
- snapshot updates. Unmet Acceptance bullets: `high`, `critical` once the change
100
- is at `ready-to-ship`. Everything else: judgment.
83
+ **Severity.** Unauthorized test changes: `high` minimum, `critical` for a bulk snapshot update. A
84
+ stale living doc: `high`, because the next session will read it and believe it. Everything else:
85
+ judgment.
101
86
 
102
87
  ---
103
88
 
104
89
  ## data-integrity
105
90
 
106
- **What it means.** Data can end up wrong, lost, or visible to the wrong tenant
107
- without anybody attacking anything.
91
+ **What it means.** Data can end up wrong, lost, or visible to the wrong tenant without anybody
92
+ attacking anything.
108
93
 
109
- **Real findings look like.** A migration that adds a NOT NULL column without a
110
- default or a backfill. A destructive DDL with no stated rollback. An RLS policy
111
- whose predicate does not match the tenancy model in `data-architecture.md`. A
112
- tenant-scoped RPC missing its `tenant_id` filter. A write path that is
113
- not idempotent under retry. A pgvector retrieval that filters after the
114
- similarity search rather than inside it.
94
+ **Real findings look like.** A migration adding a NOT NULL column with no default and no backfill.
95
+ A destructive DDL with no stated rollback. An RLS policy whose predicate does not match the tenancy
96
+ model in `data-architecture.md`. A tenant-scoped RPC missing its tenant filter. A write path that
97
+ is not idempotent under retry. A pgvector retrieval filtering after the similarity search rather
98
+ than inside it.
115
99
 
116
- **Filler looks like.** Speculating about scale on a table with a bounded row
117
- count. Recommending an index with no query to justify it.
100
+ **Filler looks like.** Speculating about scale on a table with a bounded row count. Recommending an
101
+ index with no query to justify it.
118
102
 
119
- **Severity.** Cross-tenant leakage is `critical` — always, including when the
120
- leak needs an unlikely sequence to trigger. Irreversible data loss is
121
- `critical`. Recoverable inconsistency is `high`.
103
+ **Severity.** Cross-tenant leakage is `critical` — always, including when the leak needs an unlikely
104
+ sequence to trigger. Irreversible data loss is `critical`. Recoverable inconsistency is `high`.
122
105
 
123
106
  ---
124
107
 
125
108
  ## code-quality
126
109
 
127
- **What it means.** The change works and will cost more than it should to live
128
- with. The weakest category and the easiest to pad, which is why it is worth
129
- being strict about what belongs here.
110
+ **What it means.** The change works and will cost more than it should to live with. The weakest
111
+ category and the easiest to pad, which is why it is worth being strict about what belongs here.
130
112
 
131
- **Real findings look like.** A third copy of logic that already exists twice,
132
- where the copies have started to disagree. Error handling that swallows a
133
- failure the caller needs. A function whose behaviour depends on call order with
134
- nothing that documents or enforces it. A performance budget in the test-plan
135
- that the implementation cannot meet as written.
113
+ **Real findings look like.** A third copy of logic that already exists twice, where the copies have
114
+ started to disagree. Error handling that swallows a failure the caller needs. A function whose
115
+ behaviour depends on call order with nothing that documents or enforces it.
136
116
 
137
- **Filler looks like.** Naming preferences. Suggested comments. Requests to
138
- extract a function that is used once. Anything a formatter or a linter would
139
- have said, since `run-gates.sh` already ran.
117
+ **Filler looks like.** Naming preferences. Suggested comments. Requests to extract a function used
118
+ once. Anything a formatter or a linter would have said.
140
119
 
141
- **Severity.** `low` or `medium`. A `code-quality` finding at `high` is usually
142
- mis-categorized — look again at whether it is really `invariant-breach` or
143
- `data-integrity`.
120
+ **Severity.** `low` or `medium`. A `code-quality` finding at `high` is usually mis-categorized —
121
+ look again at whether it is really `invariant-breach` or `data-integrity`.
144
122
 
145
123
  ---
146
124
 
147
- ## Resolution routing
125
+ ## Resolution
148
126
 
149
- Independent of category:
127
+ Independent of category, a finding names what would resolve it:
150
128
 
151
- - `commit:<hash>` fixed on the branch. The hash must exist there (AR-04).
152
- - `tech-debt:<id>`acknowledged and deferred, against a tech-debt artifact
153
- that exists at `open` or `in-progress` at write time (AR-05).
154
- - `justified-in-prose` — the finding is real and the right answer is to explain
155
- why nothing changes. Reserved for `low` severity. A `high`-severity finding
156
- routed here is a halt, and a security or tenant-isolation finding routed here
157
- is a halt with escalation.
129
+ - **A corrective commit on the branch** the author fixes it before the merge.
130
+ - **A tech-debt file in the same PR** the finding is real and is being lived with, on the record
131
+ and grep-able by `related-modules` (kernel § Tech-debt).
132
+ - **An argument in the comment thread** — the finding is real and the right answer is to explain
133
+ why nothing changes. Fine for a `low`; a `high` answered this way stays open, and a security or
134
+ tenant-isolation finding answered this way is escalated, not closed.
@@ -1,82 +1,57 @@
1
1
  ---
2
2
  name: hstack-app-architecture
3
- description: Use to produce or refresh `hstack/context/app-architecture.md` module map, agent orchestration, deterministic-vs-LLM split, state ownership, surface boundaries. Greenfield Phase 3, the brownfield app-architecture step, or a standalone section refresh.
4
- tools:
5
- - Read
6
- - Write
7
- - Edit
8
- - Grep
9
- - Glob
10
- - Bash
11
- - Task
12
- - "node hstack/scripts/validate-spec.mjs — frontmatter validator"
3
+ description: "Use when the application architecture really moves modules, LLM call sites, state ownership, surfaces, or what a user can reach to write or refresh `hstack/context/app-architecture.md`, exposure map included."
13
4
  ---
14
5
 
15
6
  ## Purpose
16
7
 
17
- `hstack-app-architecture` is the atom that produces or refreshes `hstack/context/app-architecture.md` via the `app-architect` subagent. The artifact captures the internal architecture in five sections; subsequent module-spec authoring and per-change-spec `surfaces` declarations depend on it.
8
+ `/hstack-app-architecture` writes or refreshes `hstack/context/app-architecture.md`: the module map
9
+ with its exposure column, the agent orchestration model, the deterministic-vs-LLM split, the
10
+ state-ownership map, the surface boundaries. It is what the next session reads to know what exists
11
+ and what a user can reach.
18
12
 
19
- ## When to invoke
20
-
21
- - Phase 3 of `/hstack:greenfield-init` (elicit mode).
22
- - Delegated by `/hstack:brownfield-init` mini-session 5b (extract mode).
23
- - Standalone via `/hstack:app-architecture [--mode extract|elicit] [--section <name>]` for refresh or single-section edits.
24
- - Routed-into-from-downstream when `/hstack:stack-decide` finds a stack constraint that contradicts the architecture (rare).
13
+ It is not how the doc stays current day to day — a change that adds a route updates the map in its
14
+ own PR, which is the kernel's rule and costs nothing. This Skill is for the moves that rule cannot
15
+ absorb: the first write, a module boundary that no longer matches the code, an exposure map that
16
+ has drifted away from the real routes.
25
17
 
26
18
  ## Inputs
27
19
 
28
- - `--mode extract | elicit` defaults: `extract` if a `src/`, `app/`, or `lib/` tree exists in the consuming repo; `elicit` if the repo is empty (greenfield).
29
- - `--section <name>` — one of `modules | orchestration | split | state | surfaces`. Fast-jumps but re-runs end-of-atom coherence.
30
-
31
- ## Preconditions
32
-
33
- - `hstack/config.yaml` at `init-status: minimal-complete` or later.
34
- - `hstack/context/product/product-brief.md` and `hstack/context/data-architecture.md` both at `status: current`. App architecture is downstream of both. If either is at non-terminal status, halt with `HSTACK-HALT: reason=upstream-non-terminal`.
35
- - `hstack/templates/app-architecture.md` and `hstack/templates/module-spec.md` present.
36
- - In extract mode, a source tree (`src/`, `app/`, or `lib/`) is reachable; otherwise halt.
37
-
38
- ## Orchestration steps
39
-
40
- 1. **Detect mode + entry.** Read disk state. If artifact at `current` and no `--section` and no `--force`: print summary, exit no-op.
41
- 2. **Invoke `app-architect` subagent.** Via the Task tool with `subagent_type: app-architect`. Pass mode, optional section, the canonical session-start context. Explicitly DO NOT pass `tech-stack.md` — the architecture is stack-agnostic.
42
- 3. **Walk sections.** The subagent walks all five sections in order in fresh-start mode. Section 3 (Deterministic-vs-LLM Split) is walked per-flow with per-step confirmation; this is the only section with finer-than-section confirmation gates because per-step declarations are too consequential to batch.
43
- 4. **Run drift challenge prompts.** Each section ends with a drift challenge. A real drift halts with `HSTACK-HALT: reason=upstream-drift` and offers (a) revise this section, (b) re-enter the upstream atom (typically `/hstack:data-architecture --section entities` for state-ownership gaps), (c) log as ADR.
44
- 5. **End-of-atom coherence check.** Even on section-targeted entry, the subagent re-runs all five drift challenges before terminal commit.
45
- 6. **Terminal-state side effects (one atomic commit).** When the artifact reaches `status: current`, the Skill performs three mechanical writes in a single commit:
46
- - The completed `app-architecture.md`.
47
- - One `hstack/specs/<module>/spec.md` stub per module from Section 1 (header sections only, `status: draft`, body note pointing to `/hstack:module-spec`).
48
- - `hstack/config.yaml` updated to set the `surfaces` enum to match Section 5.
49
- The proposed-diff preview runs before this commit lands per the kernel's mechanical-operations rule.
50
-
51
- ## Outputs
52
-
53
- - `hstack/context/app-architecture.md` at `status: current`.
54
- - One `hstack/specs/<module>/spec.md` per module at `status: draft`.
55
- - `hstack/config.yaml` with updated `surfaces` enum.
56
- - `hstack/.session-state/<session-id>.yaml` (transient).
57
-
58
- ## Auto-commit triggers
59
-
60
- - Each confirmed section writes immediately and auto-commits.
61
- - Per-flow row in Section 3 commits individually (not full-section batch).
62
- - Terminal-state side effects (artifact + stubs + config) land in one atomic commit.
63
-
64
- ## Idempotency contract
65
-
66
- - Artifact at `current` + no `--section` + no `--force`: print summary, exit no-op.
67
- - Artifact at `draft` or partial: resume at next non-confirmed section.
68
- - Artifact at `needs-refresh`: walk all sections in confirm-or-revise mode.
69
- - Module-spec stubs at `status: draft`: the atom does NOT overwrite stubs on re-run; if Section 1 added a module on refresh, the new stub lands additively; if Section 1 removed a module, the orphan stub is flagged for engineer review (the engineer either deletes it or routes the deletion through `/hstack:tech-debt-stale`).
20
+ `--section modules | orchestration | split | state | surfaces`, optional refreshes one section.
21
+
22
+ ## Steps
23
+
24
+ 1. **Extract or elicit.** Extract when a source tree exists; elicit when the repo is empty.
25
+ 2. **Invoke `app-architect`** with the material. It reads the tree, drafts each section and
26
+ challenges it. The questions and the confirmations happen here, in this session a subagent
27
+ cannot interview.
28
+ 3. **Fill the exposure column in extract mode.** Entry points are enumerable: `app/**/page.tsx` and
29
+ `app/**/route.ts` for the App Router, files carrying `'use server'` for server actions, plus the
30
+ job and webhook registrations. Enumerate them, attach each to the module it serves, and ask the
31
+ engineer for a status per entry point — `live`, `routable` or `off`, as the kernel defines them.
32
+ A module reached only through another module's entry point names that one instead; a module no
33
+ live entry point reaches is `dormant`, which is derived and never a fourth status.
34
+ 4. **One line the map carries, not this Skill's to restate:** it grades the **product** severity of
35
+ a finding, never its security severity. Every routable entry point is covered by the kernel's
36
+ security checklist whatever the map says.
37
+ 5. **Each section ends with its drift challenge**, and the answer stays in the doc as evidence the
38
+ probe ran. A challenge that surfaces a real contradiction stops the section: the engineer
39
+ revises it, files an ADR, or writes a tech-debt file.
40
+ 6. **A section-targeted refresh re-reads the other four challenges** before the PR — a module
41
+ renamed in Section 1 and left standing in Section 4 is the failure this catches.
42
+
43
+ ## Output
44
+
45
+ `hstack/context/app-architecture.md`, updated in the PR that changes it. Nothing else: no module
46
+ spec stubs, no config file, no status.
70
47
 
71
48
  ## Stop conditions
72
49
 
73
- - Product-brief or data-architecture at non-terminal status.
74
- - A module in Section 1 has no trace to brief or data-architecture entities.
75
- - A Section 3 flow step has no declared mechanism or no measurable-property rationale.
76
- - A drift challenge surfaces an unresolved contradiction.
77
- - Extract mode invoked but no source tree reachable.
78
-
79
- ## Failure modes
50
+ Beyond the kernel's:
80
51
 
81
- - **Subagent unreachable.** Persist session state; retry later.
82
- - **Terminal-state side-effect commit fails partway** (e.g., one stub fails validator). The atom rolls back the in-progress write and halts with the validator error; the engineer fixes or routes through `/hstack:configure`. The artifact stays at `current` only when ALL three side effects land successfully.
52
+ - Extract mode was asked for and no source tree is reachable.
53
+ - An entry point's status is a guess. Ask; a wrong `off` is how a live surface stops being reviewed.
54
+ - A step of a flow has no declared mechanism, or a rationale that names no property anyone could
55
+ disagree with.
56
+ - A drift challenge surfaces a contradiction with `data-architecture.md` — typically a state class
57
+ with nowhere to live. Surface it; the engineer decides whether the data doc moves.