hstack 0.7.1 → 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.
- package/CHANGELOG.md +308 -0
- package/README.md +90 -154
- package/VERSION +1 -1
- package/dist/commands/doctor.js +69 -9
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.js +7 -3
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/update.js +17 -4
- package/dist/commands/update.js.map +1 -1
- package/dist/lib/descriptions.js +160 -0
- package/dist/lib/descriptions.js.map +1 -0
- package/dist/lib/diff.js +1 -1
- package/dist/lib/git.js +16 -0
- package/dist/lib/git.js.map +1 -1
- package/dist/lib/wire.js +274 -142
- package/dist/lib/wire.js.map +1 -1
- package/dist/manifest.js +49 -22
- package/dist/manifest.js.map +1 -1
- package/package.json +4 -3
- package/template/.claude/agents/adversarial-reviewer.md +42 -98
- package/template/.claude/agents/app-architect.md +44 -133
- package/template/.claude/agents/data-architect.md +46 -127
- package/template/.claude/agents/test-strategist.md +39 -109
- package/template/.claude/skills/hstack-adr-new/SKILL.md +23 -100
- package/template/.claude/skills/hstack-adversarial-review/SKILL.md +47 -174
- package/template/.claude/skills/hstack-adversarial-review/references/finding-categories.md +134 -0
- package/template/.claude/skills/hstack-app-architecture/SKILL.md +43 -95
- package/template/.claude/skills/hstack-commit/SKILL.md +28 -97
- package/template/.claude/skills/hstack-data-architecture/SKILL.md +34 -82
- package/template/.claude/skills/hstack-promote/SKILL.md +55 -0
- package/template/.claude/skills/hstack-story/SKILL.md +58 -0
- package/template/.claude/skills/hstack-test-audit/SKILL.md +64 -0
- package/template/.claude/skills/hstack-wrap/SKILL.md +48 -0
- package/template/.claude/skills/hstack-wrap/references/pr-description.md +45 -0
- package/template/KERNEL.md +167 -0
- package/template/templates/adr.md +9 -18
- package/template/templates/app-architecture.md +38 -50
- package/template/templates/data-architecture.md +39 -93
- package/template/templates/infrastructure.md +54 -148
- package/template/templates/roadmap.md +35 -0
- package/template/templates/story.md +7 -13
- package/template/templates/tech-debt.md +2 -37
- package/template/templates/tech-stack.md +2 -12
- package/template/.claude/agents/data-specialist.md +0 -126
- package/template/.claude/agents/implementer.md +0 -154
- package/template/.claude/agents/kernel-fit-analyst.md +0 -190
- package/template/.claude/agents/planner.md +0 -110
- package/template/.claude/agents/product-discovery.md +0 -165
- package/template/.claude/agents/product-manager.md +0 -111
- package/template/.claude/agents/researcher.md +0 -123
- package/template/.claude/agents/security-reviewer.md +0 -123
- package/template/.claude/agents/spec-author.md +0 -123
- package/template/.claude/agents/stack-architect.md +0 -137
- package/template/.claude/agents/ui-ux-briefer.md +0 -105
- package/template/.claude/agents/verifier.md +0 -113
- package/template/.claude/skills/hstack-branch/SKILL.md +0 -103
- package/template/.claude/skills/hstack-brownfield-init/SKILL.md +0 -158
- package/template/.claude/skills/hstack-change-new/SKILL.md +0 -111
- package/template/.claude/skills/hstack-change-plan/SKILL.md +0 -119
- package/template/.claude/skills/hstack-configure/SKILL.md +0 -126
- package/template/.claude/skills/hstack-coord/SKILL.md +0 -131
- package/template/.claude/skills/hstack-data-review/SKILL.md +0 -132
- package/template/.claude/skills/hstack-finalize/SKILL.md +0 -159
- package/template/.claude/skills/hstack-flag/SKILL.md +0 -138
- package/template/.claude/skills/hstack-greenfield-init/SKILL.md +0 -175
- package/template/.claude/skills/hstack-help/SKILL.md +0 -179
- package/template/.claude/skills/hstack-implement/SKILL.md +0 -185
- package/template/.claude/skills/hstack-kernel-fit-promote/SKILL.md +0 -164
- package/template/.claude/skills/hstack-kernel-fit-scan/SKILL.md +0 -197
- package/template/.claude/skills/hstack-kernel-fit-triage/SKILL.md +0 -159
- package/template/.claude/skills/hstack-module-spec/SKILL.md +0 -105
- package/template/.claude/skills/hstack-product-discovery/SKILL.md +0 -101
- package/template/.claude/skills/hstack-research/SKILL.md +0 -145
- package/template/.claude/skills/hstack-scaffold/SKILL.md +0 -140
- package/template/.claude/skills/hstack-security-review/SKILL.md +0 -133
- package/template/.claude/skills/hstack-ship/SKILL.md +0 -129
- package/template/.claude/skills/hstack-stack-decide/SKILL.md +0 -108
- package/template/.claude/skills/hstack-story-draft/SKILL.md +0 -119
- package/template/.claude/skills/hstack-tech-debt-new/SKILL.md +0 -122
- package/template/.claude/skills/hstack-tech-debt-resolve/SKILL.md +0 -158
- package/template/.claude/skills/hstack-tech-debt-stale/SKILL.md +0 -113
- package/template/.claude/skills/hstack-tech-debt-wontfix/SKILL.md +0 -104
- package/template/.claude/skills/hstack-telemetry/SKILL.md +0 -98
- package/template/.claude/skills/hstack-test-plan/SKILL.md +0 -182
- package/template/.claude/skills/hstack-ui-brief/SKILL.md +0 -108
- package/template/.claude/skills/hstack-verify/SKILL.md +0 -150
- package/template/CLAUDE.md +0 -443
- package/template/scripts/coord/coord_scan.py +0 -681
- package/template/scripts/telemetry/__init__.py +0 -6
- package/template/scripts/telemetry/insights/__init__.py +0 -0
- package/template/scripts/telemetry/insights/contract_drift.py +0 -137
- package/template/scripts/telemetry/insights/kernel_fit.py +0 -438
- package/template/scripts/telemetry/insights/overengineering.py +0 -115
- package/template/scripts/telemetry/insights/quality_outcomes.py +0 -131
- package/template/scripts/telemetry/insights/token_economics.py +0 -129
- package/template/scripts/telemetry/insights/workflow_shape.py +0 -198
- package/template/scripts/telemetry/parsers/__init__.py +0 -0
- package/template/scripts/telemetry/parsers/bodies.py +0 -87
- package/template/scripts/telemetry/parsers/commits.py +0 -219
- package/template/scripts/telemetry/parsers/frontmatter.py +0 -322
- package/template/scripts/telemetry/parsers/transcripts.py +0 -181
- package/template/scripts/telemetry/render.py +0 -395
- package/template/scripts/telemetry/report.py +0 -138
- package/template/scripts/telemetry/run_kernel_fit.py +0 -91
- package/template/templates/adversarial-review.md +0 -54
- package/template/templates/bootstrap.md +0 -105
- package/template/templates/change-spec.md +0 -82
- package/template/templates/ci-cd.md +0 -27
- package/template/templates/coord-message.md +0 -55
- package/template/templates/data-review.md +0 -54
- package/template/templates/discovery/brainstorm.md +0 -69
- package/template/templates/discovery/forcing-questions.md +0 -76
- package/template/templates/discovery/project-brief.md +0 -53
- package/template/templates/figma-handoff.md +0 -38
- package/template/templates/glossary.md +0 -20
- package/template/templates/hardening-checklist.md +0 -73
- package/template/templates/incident-runbook.md +0 -57
- package/template/templates/kernel-fit-finding.md +0 -63
- package/template/templates/kernel-fit-flag.md +0 -52
- package/template/templates/module-spec.md +0 -49
- package/template/templates/mvp-scope.md +0 -34
- package/template/templates/persona.md +0 -38
- package/template/templates/plan.md +0 -49
- package/template/templates/product-brief.md +0 -56
- package/template/templates/security-review.md +0 -63
- package/template/templates/telemetry-sidecar.md +0 -184
- package/template/templates/test-plan.md +0 -119
- package/template/templates/threat-model.md +0 -54
- package/template/templates/ui-brief.md +0 -49
- package/template/templates/verification.md +0 -63
- package/template/templates/vision.md +0 -34
|
@@ -1,187 +1,60 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: hstack-adversarial-review
|
|
3
|
-
description:
|
|
4
|
-
Use this skill only in a fresh Claude Code session — separate from the session that ran the implementer — after verification has landed at `status: passed` and the change is at `ready-for-review`. The Skill orchestrates the `adversarial-reviewer` subagent to produce a quota-driven critique. v1 fresh-session enforcement is honor-system; the Skill emits a clear instruction reminding the engineer that the v2 substrate will verify via session-id comparison. Examples:
|
|
5
|
-
|
|
6
|
-
<example>
|
|
7
|
-
Context: The implementer finished the last phase of a billing change; verification passed; the engineer has opened a fresh session for adversarial review.
|
|
8
|
-
user: "I've opened a new session. /hstack:adversarial-review 2026-05-billing-overage-warning"
|
|
9
|
-
assistant: "I'll invoke adversarial-reviewer. Findings floor is 5 because area=billing. I'll load every change artifact and the full diff; no implementer transcripts. Minimum 5 findings or a defended sub-floor justification — 'no issues found' is not a terminal state."
|
|
10
|
-
<commentary>
|
|
11
|
-
AR-06 raises the findings floor to 5 for changes in {agent, auth, billing}. The reviewer must spread findings across categories — clustering all findings in one category is a smell unless flagged in Methodology.
|
|
12
|
-
</commentary>
|
|
13
|
-
</example>
|
|
14
|
-
|
|
15
|
-
<example>
|
|
16
|
-
Context: A small copy-fix change has been verified and the reviewer can only honestly produce two findings.
|
|
17
|
-
user: "/hstack:adversarial-review 2026-05-billing-copy-tweak"
|
|
18
|
-
assistant: "I'll invoke adversarial-reviewer. If I can only honestly produce two findings, I'll set findings-fewer-than-floor: true and write a defended justification in section 4 — enumerate every category considered and explain why each produced no honest finding."
|
|
19
|
-
<commentary>
|
|
20
|
-
The sub-floor path is explicit and rare. AR-01 demands `findings` length ≥ `findings-floor` OR `findings-fewer-than-floor: true` plus non-empty `justification-when-fewer`. "The change is small" alone is insufficient.
|
|
21
|
-
</commentary>
|
|
22
|
-
</example>
|
|
23
|
-
|
|
24
|
-
<example>
|
|
25
|
-
Context: The adversarial reviewer finds a high-severity tenant-isolation issue the security review missed.
|
|
26
|
-
user: "/hstack:adversarial-review 2026-06-retrieval-rpc-rewrite"
|
|
27
|
-
assistant: "I'll invoke adversarial-reviewer with the new pgvector RPC under scrutiny. If a severity:high tenant-isolation finding lands, the resolution must be commit:<hash> or tech-debt:<id> — not justified-in-prose. High-severity security routed to justified-in-prose is a smell and I'll halt."
|
|
28
|
-
<commentary>
|
|
29
|
-
Resolution discipline matters: `commit:<hash>` for code fixes, `tech-debt:<id>` for deliberate deferral, `justified-in-prose` only for low-severity findings where in-prose reasoning is genuinely right. High-severity security via justified-in-prose is a halt condition.
|
|
30
|
-
</commentary>
|
|
31
|
-
</example>
|
|
32
|
-
tools:
|
|
33
|
-
- Read
|
|
34
|
-
- Write
|
|
35
|
-
- Edit
|
|
36
|
-
- Grep
|
|
37
|
-
- Glob
|
|
38
|
-
- Bash
|
|
39
|
-
- Task
|
|
40
|
-
- "{{TODO-SCRIPT: hstack/scripts/validate-spec.ts — validates adversarial-review frontmatter and AR-01..AR-06}}"
|
|
41
|
-
- "{{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 change — to review a PR that touches a sensitive surface. Findings land as a PR comment; the author is the one who fixes them."
|
|
42
4
|
---
|
|
43
5
|
|
|
44
6
|
## Purpose
|
|
45
7
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
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.
|
|
51
|
-
|
|
52
|
-
## Inputs
|
|
53
|
-
|
|
54
|
-
- `<change-id>` (required, positional): the change-spec id.
|
|
55
|
-
|
|
56
|
-
## Preconditions
|
|
57
|
-
|
|
58
|
-
Before any work:
|
|
59
|
-
|
|
60
|
-
- **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.
|
|
61
|
-
- Verify the change-spec exists and is at `status: ready-for-review`.
|
|
62
|
-
- Verify every required upstream artifact is at terminal status:
|
|
63
|
-
- test-plan at `passed` or `concerns-acknowledged`
|
|
64
|
-
- plan at `completed`
|
|
65
|
-
- security-review at `passed` or `concerns-acknowledged`
|
|
66
|
-
- data-review at `passed` or `concerns-acknowledged` when applicable
|
|
67
|
-
- ui-brief at `drafted` and figma-handoff at `ready` when applicable
|
|
68
|
-
- verification at `passed`
|
|
69
|
-
- Determine the findings floor: 3 default; 5 when `change-spec.area` is in {agent, auth, billing} per AR-06.
|
|
70
|
-
|
|
71
|
-
## Orchestration steps
|
|
72
|
-
|
|
73
|
-
1. **Open with the fresh-session reminder.** Print the message verbatim; wait for the engineer's confirmation.
|
|
74
|
-
|
|
75
|
-
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.
|
|
76
|
-
|
|
77
|
-
3. **Findings generation across six categories.** The subagent produces findings in security, scope-drift, invariant-breach, spec-compliance, data-integrity, and code-quality. Clustering in one category is a smell — when it happens, the subagent flags the clustering in Methodology and explains why the change genuinely lives in one risk dimension. 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`. These findings are filed even when they push the total over the findings-floor.
|
|
78
|
-
|
|
79
|
-
4. **Findings-floor compliance.** Per AR-01, `findings` length must be ≥ `findings-floor`. If the subagent honestly cannot produce the floor, it sets `findings-fewer-than-floor: true` and writes a defended `justification-when-fewer` enumerating every category considered and why each produced no honest finding. "The change is small" alone is insufficient.
|
|
80
|
-
|
|
81
|
-
5. **Resolution discipline.** Each finding's `resolution` is one of:
|
|
82
|
-
- `commit:<hash>` — must reference an existing commit on the change's branch (AR-04).
|
|
83
|
-
- `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.
|
|
84
|
-
- `justified-in-prose` — reserved for low-severity findings only. High-severity findings routed to `justified-in-prose` halt the Skill.
|
|
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.
|
|
85
11
|
|
|
86
|
-
|
|
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.
|
|
87
15
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
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.
|
|
91
|
-
|
|
92
|
-
9. **Validate.** Run `{{TODO-SCRIPT: hstack/scripts/validate-spec.ts}}` — AR-01 through AR-06.
|
|
93
|
-
|
|
94
|
-
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 `{{TODO-SCRIPT: hstack/scripts/validate-spec.ts}}` 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. Do NOT invoke `spec-author` and do NOT delegate the write to the `adversarial-reviewer` subagent; per the kernel's Mechanical operations section and ADR-0002, the value to write is fully determined by the adversarial-review postcondition and the change-spec's current status, so the Skill orchestrator writes directly. The `adversarial-reviewer` subagent retains its critique-only lane and writes only `adversarial-review.md`.
|
|
95
|
-
|
|
96
|
-
## Outputs
|
|
97
|
-
|
|
98
|
-
- `hstack/specs/changes/<change-id>/adversarial-review.md` at `status: findings-resolved`.
|
|
99
|
-
- 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).
|
|
100
|
-
- Optional new tech-debt artifacts produced via `hstack-tech-debt-new` invocations when findings route to `tech-debt:<id>`.
|
|
101
|
-
- 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.
|
|
102
|
-
|
|
103
|
-
## Auto-commit triggers
|
|
104
|
-
|
|
105
|
-
- Status transition to `in-progress` after Methodology lands.
|
|
106
|
-
- Status transition to `findings-open` after all findings are written.
|
|
107
|
-
- Status transition to `findings-resolved` when every finding has `status: resolved`.
|
|
108
|
-
- Edits to the `findings` array.
|
|
109
|
-
- Edits to any finding's `resolution`.
|
|
110
|
-
- **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.
|
|
111
|
-
|
|
112
|
-
## Telemetry sidecar
|
|
113
|
-
|
|
114
|
-
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:
|
|
115
|
-
|
|
116
|
-
```json
|
|
117
|
-
{
|
|
118
|
-
"schema_version": 1,
|
|
119
|
-
"skill": "hstack-adversarial-review",
|
|
120
|
-
"change_id": "<change-id>",
|
|
121
|
-
"reviewed_at": "<ISO-8601, when status reached findings-resolved>",
|
|
122
|
-
"findings_floor": <int, 3 or 5 per AR-06>,
|
|
123
|
-
"findings_count": <int, length of frontmatter findings array>,
|
|
124
|
-
"findings_fewer_than_floor": <bool>,
|
|
125
|
-
"category_counts": {
|
|
126
|
-
"security": <int>,
|
|
127
|
-
"scope-drift": <int>,
|
|
128
|
-
"invariant-breach": <int>,
|
|
129
|
-
"spec-compliance": <int>,
|
|
130
|
-
"data-integrity": <int>,
|
|
131
|
-
"code-quality": <int>
|
|
132
|
-
},
|
|
133
|
-
"severity_counts": {
|
|
134
|
-
"critical": <int>,
|
|
135
|
-
"high": <int>,
|
|
136
|
-
"medium": <int>,
|
|
137
|
-
"low": <int>
|
|
138
|
-
},
|
|
139
|
-
"resolution_mix": {
|
|
140
|
-
"commit": <int>,
|
|
141
|
-
"tech-debt": <int>,
|
|
142
|
-
"justified-in-prose": <int>
|
|
143
|
-
},
|
|
144
|
-
"fresh_session_attestation": "<verbatim copy of frontmatter field>",
|
|
145
|
-
"halt_reasons": [<kernel halt-sentinel enum values, if any>]
|
|
146
|
-
}
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
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. This is the most directly Goodhart-resistant of the five v1 sidecars — `category_counts` + `severity_counts` + `resolution_mix` jointly surface findings-quota-gaming patterns no single field could detect.
|
|
150
|
-
|
|
151
|
-
## Idempotency contract
|
|
16
|
+
## When to invoke
|
|
152
17
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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.
|
|
156
48
|
|
|
157
49
|
## Stop conditions
|
|
158
50
|
|
|
159
|
-
Beyond the kernel's
|
|
160
|
-
|
|
161
|
-
- Engineer has not confirmed they are in a fresh Claude Code session.
|
|
162
|
-
- A required upstream artifact is non-terminal.
|
|
163
|
-
- A high-severity security or tenant-isolation finding would route to `justified-in-prose`. Halt.
|
|
164
|
-
- A `commit:<hash>` resolution would reference a commit not on the change's branch.
|
|
165
|
-
- A `tech-debt:<id>` resolution would reference a non-existent tech-debt artifact (the engineer must invoke `hstack-tech-debt-new` first).
|
|
166
|
-
- The findings floor cannot honestly be met and the sub-floor justification cannot be defended.
|
|
167
|
-
- 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.
|
|
168
|
-
- An implementer transcript or scratchpad is visible in the session.
|
|
169
|
-
|
|
170
|
-
## Failure modes
|
|
171
|
-
|
|
172
|
-
- **Engineer claims fresh session but conversation shows prior implementer transcripts.** Halt; ask the engineer to truly start a new session.
|
|
173
|
-
- **Reviewer cannot produce honest findings to meet the floor and the sub-floor justification feels thin.** Re-prompt for each category; if still under floor, the engineer must defend the sub-floor explicitly.
|
|
174
|
-
- **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.
|
|
175
|
-
- **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.
|
|
176
|
-
|
|
177
|
-
## Anti-patterns
|
|
51
|
+
Beyond the kernel's:
|
|
178
52
|
|
|
179
|
-
-
|
|
180
|
-
-
|
|
181
|
-
-
|
|
182
|
-
|
|
183
|
-
-
|
|
184
|
-
|
|
185
|
-
-
|
|
186
|
-
|
|
187
|
-
- Never load implementer transcripts. If visible, halt.
|
|
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.
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# The six finding categories — a calibration rubric
|
|
2
|
+
|
|
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).
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## security
|
|
12
|
+
|
|
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.
|
|
16
|
+
|
|
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.
|
|
21
|
+
|
|
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.
|
|
25
|
+
|
|
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.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## scope-drift
|
|
33
|
+
|
|
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.
|
|
36
|
+
|
|
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.
|
|
40
|
+
|
|
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.
|
|
43
|
+
|
|
44
|
+
**Severity.** Usually `medium`. It escalates when the drift lands on a path `invariants.md` covers,
|
|
45
|
+
because then it is also `invariant-breach`.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## invariant-breach
|
|
50
|
+
|
|
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.
|
|
53
|
+
|
|
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.
|
|
58
|
+
|
|
59
|
+
**Filler looks like.** Paraphrasing an invariant back and calling it a risk. Naming an invariant the
|
|
60
|
+
diff does not touch.
|
|
61
|
+
|
|
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.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## intent-compliance
|
|
68
|
+
|
|
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.
|
|
72
|
+
|
|
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.
|
|
79
|
+
|
|
80
|
+
**Filler looks like.** "The description could have been clearer." Style disagreements with how the
|
|
81
|
+
work was sequenced.
|
|
82
|
+
|
|
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.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## data-integrity
|
|
90
|
+
|
|
91
|
+
**What it means.** Data can end up wrong, lost, or visible to the wrong tenant without anybody
|
|
92
|
+
attacking anything.
|
|
93
|
+
|
|
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.
|
|
99
|
+
|
|
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.
|
|
102
|
+
|
|
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`.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## code-quality
|
|
109
|
+
|
|
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.
|
|
112
|
+
|
|
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.
|
|
116
|
+
|
|
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.
|
|
119
|
+
|
|
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`.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Resolution
|
|
126
|
+
|
|
127
|
+
Independent of category, a finding names what would resolve it:
|
|
128
|
+
|
|
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,109 +1,57 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: hstack-app-architecture
|
|
3
|
-
description:
|
|
4
|
-
Use this skill when the engineer wants to produce or refresh `hstack/context/app-architecture.md` — the five-section internal-architecture design (Module Map, Agent Orchestration, Deterministic-vs-LLM Split, State Ownership, Surface Boundaries). The Skill is Phase 3 of `/hstack:greenfield-init`, the app-architecture step of `/hstack:brownfield-init`, or a standalone atom for refreshing a single section. At terminal state the atom auto-scaffolds `hstack/specs/<module>/spec.md` stubs at `status: draft` for each declared module and updates `hstack/config.yaml`'s `surfaces` enum to match Section 5. Examples:
|
|
5
|
-
|
|
6
|
-
<example>
|
|
7
|
-
Context: Phase 3 of greenfield-init opens after data-architecture is current.
|
|
8
|
-
user: "/hstack:app-architecture"
|
|
9
|
-
assistant: "Loading product-brief, data-architecture, vision, mvp-scope. Stack-agnostic interview — I won't ask about frameworks here; that's Phase 4. Section 3 (Deterministic-vs-LLM Split) is the load-bearing AI-native decision: per user-facing flow, what's code and what's prompt, with rationale tied to a measurable property."
|
|
10
|
-
<commentary>
|
|
11
|
-
Internal architecture is stack-agnostic by design. Section 3 is where AI-native teams most often get architecture wrong by leaving the LLM/code split implicit. The atom forces per-step declaration.
|
|
12
|
-
</commentary>
|
|
13
|
-
</example>
|
|
14
|
-
|
|
15
|
-
<example>
|
|
16
|
-
Context: A brownfield repo's modules have evolved; the engineer wants the artifact refreshed against current code.
|
|
17
|
-
user: "/hstack:app-architecture --mode extract"
|
|
18
|
-
assistant: "Extract mode. Scanning src/, app/, lib/ via Glob; reading exports and dependencies. Proposing the Module Map from code-evidence. The drift challenge runs at the end of Section 1: does any module own state a persona never interacts with?"
|
|
19
|
-
<commentary>
|
|
20
|
-
Extract mode reads code-evidence to propose modules; the engineer confirms or revises. The orphan-module challenge catches modules that have grown beyond their persona-named purpose.
|
|
21
|
-
</commentary>
|
|
22
|
-
</example>
|
|
23
|
-
tools:
|
|
24
|
-
- Read
|
|
25
|
-
- Write
|
|
26
|
-
- Edit
|
|
27
|
-
- Grep
|
|
28
|
-
- Glob
|
|
29
|
-
- Bash
|
|
30
|
-
- Task
|
|
31
|
-
- "{{TODO-SCRIPT: hstack/scripts/validate-spec.ts — 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."
|
|
32
4
|
---
|
|
33
5
|
|
|
34
6
|
## Purpose
|
|
35
7
|
|
|
36
|
-
|
|
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.
|
|
37
12
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
- Standalone via `/hstack:app-architecture [--mode extract|elicit] [--section <name>]` for refresh or single-section edits.
|
|
43
|
-
- 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.
|
|
44
17
|
|
|
45
18
|
## Inputs
|
|
46
19
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
##
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
- `hstack/config.yaml` with updated `surfaces` enum.
|
|
75
|
-
- `hstack/.session-state/<session-id>.yaml` (transient).
|
|
76
|
-
|
|
77
|
-
## Auto-commit triggers
|
|
78
|
-
|
|
79
|
-
- Each confirmed section writes immediately and auto-commits.
|
|
80
|
-
- Per-flow row in Section 3 commits individually (not full-section batch).
|
|
81
|
-
- Terminal-state side effects (artifact + stubs + config) land in one atomic commit.
|
|
82
|
-
|
|
83
|
-
## Idempotency contract
|
|
84
|
-
|
|
85
|
-
- Artifact at `current` + no `--section` + no `--force`: print summary, exit no-op.
|
|
86
|
-
- Artifact at `draft` or partial: resume at next non-confirmed section.
|
|
87
|
-
- Artifact at `needs-refresh`: walk all sections in confirm-or-revise mode.
|
|
88
|
-
- 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.
|
|
89
47
|
|
|
90
48
|
## Stop conditions
|
|
91
49
|
|
|
92
|
-
|
|
93
|
-
- A module in Section 1 has no trace to brief or data-architecture entities.
|
|
94
|
-
- A Section 3 flow step has no declared mechanism or no measurable-property rationale.
|
|
95
|
-
- A drift challenge surfaces an unresolved contradiction.
|
|
96
|
-
- Extract mode invoked but no source tree reachable.
|
|
97
|
-
|
|
98
|
-
## Failure modes
|
|
99
|
-
|
|
100
|
-
- **Subagent unreachable.** Persist session state; retry later.
|
|
101
|
-
- **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.
|
|
102
|
-
|
|
103
|
-
## Anti-patterns
|
|
50
|
+
Beyond the kernel's:
|
|
104
51
|
|
|
105
|
-
-
|
|
106
|
-
-
|
|
107
|
-
-
|
|
108
|
-
|
|
109
|
-
-
|
|
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.
|