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
package/dist/manifest.js
CHANGED
|
@@ -6,36 +6,63 @@
|
|
|
6
6
|
* On `hstack update` only paths in `FRAMEWORK_PATHS` are overwritten; paths
|
|
7
7
|
* in `USER_CONTENT_PATHS` are NEVER touched by the installer.
|
|
8
8
|
*
|
|
9
|
-
* The boundary is load-bearing — see
|
|
10
|
-
* the README installation section.
|
|
9
|
+
* The boundary is load-bearing — see the README installation section.
|
|
11
10
|
*/
|
|
12
11
|
/**
|
|
13
12
|
* Paths the installer owns. `hstack update` overwrites these.
|
|
14
13
|
* Relative to `<consumer>/hstack/`.
|
|
14
|
+
*
|
|
15
|
+
* `KERNEL.md` was `CLAUDE.md` until ADR-0010 — a consumer still carrying the
|
|
16
|
+
* old name is migrated by `hstack update`, not by this diff (the old path is no
|
|
17
|
+
* longer a framework path, so nothing here would ever remove it).
|
|
15
18
|
*/
|
|
16
19
|
export const FRAMEWORK_PATHS = [
|
|
17
|
-
"
|
|
20
|
+
"KERNEL.md",
|
|
18
21
|
"templates/",
|
|
19
22
|
".claude/agents/",
|
|
20
23
|
".claude/skills/",
|
|
21
|
-
"scripts/telemetry/",
|
|
22
|
-
"scripts/coord/",
|
|
23
24
|
];
|
|
24
25
|
/**
|
|
25
|
-
* Paths the installer
|
|
26
|
-
*
|
|
27
|
-
*
|
|
26
|
+
* Paths the installer shipped before v0.17 and now takes back.
|
|
27
|
+
*
|
|
28
|
+
* v0.17 removed the enforcement scripts (`validate-spec.mjs`,
|
|
29
|
+
* `compute-merge-readiness.mjs`, `run-gates.sh`) and the `coord/` and
|
|
30
|
+
* `telemetry/` module trees along with the machinery that called them. Dropping
|
|
31
|
+
* them from `FRAMEWORK_PATHS` is not enough on its own: the update diff only
|
|
32
|
+
* looks at paths in that list, so a path removed from it is a path nothing will
|
|
33
|
+
* ever prune — the consumer would keep running a copy of a script this
|
|
34
|
+
* framework no longer knows about. `hstack update` therefore removes these
|
|
35
|
+
* explicitly, the same way the ADR-0010 rename is a migration rather than a
|
|
36
|
+
* diff. Planned only when the path is actually on disk, so it is a no-op by
|
|
37
|
+
* construction on a consumer installed after v0.17.
|
|
38
|
+
*
|
|
39
|
+
* Relative to `<consumer>/hstack/`. Order matters only for readability.
|
|
28
40
|
*/
|
|
29
|
-
export const
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"research/",
|
|
36
|
-
"telemetry/reports/",
|
|
37
|
-
"kernel-fit/",
|
|
41
|
+
export const LEGACY_FRAMEWORK_PATHS = [
|
|
42
|
+
"scripts/validate-spec.mjs",
|
|
43
|
+
"scripts/compute-merge-readiness.mjs",
|
|
44
|
+
"scripts/run-gates.sh",
|
|
45
|
+
"scripts/coord",
|
|
46
|
+
"scripts/telemetry",
|
|
38
47
|
];
|
|
48
|
+
/**
|
|
49
|
+
* The directory the legacy paths above lived in. Removed after them, and only
|
|
50
|
+
* when empty: an engineer who put their own script there keeps it.
|
|
51
|
+
*/
|
|
52
|
+
export const LEGACY_SCRIPTS_DIR = "scripts";
|
|
53
|
+
/**
|
|
54
|
+
* Paths the installer NEVER touches once they exist in the consumer — the
|
|
55
|
+
* engineering memory, which belongs to the repo that wrote it.
|
|
56
|
+
*
|
|
57
|
+
* Documentation, not a mechanism: nothing imports this list. The protection is
|
|
58
|
+
* structural — `update` only ever writes paths in `FRAMEWORK_PATHS`. v0.17
|
|
59
|
+
* dropped `config.yaml`, `specs/`, `research/`, `telemetry/reports/` and
|
|
60
|
+
* `kernel-fit/` from it, because naming directories the framework no longer
|
|
61
|
+
* creates describes a boundary that has moved.
|
|
62
|
+
*
|
|
63
|
+
* Relative to `<consumer>/hstack/`.
|
|
64
|
+
*/
|
|
65
|
+
export const USER_CONTENT_PATHS = ["context/", "adr/", "tech-debt/"];
|
|
39
66
|
/**
|
|
40
67
|
* Consumer-side wiring under `<consumer>/.claude/` — symlinks pointing into
|
|
41
68
|
* the consumer's `hstack/.claude/` tree. Owned by the installer; recreated
|
|
@@ -52,11 +79,11 @@ export const CLAUDE_WIRING = {
|
|
|
52
79
|
skillsSourceDir: "hstack/.claude/skills",
|
|
53
80
|
skillsTargetDir: ".claude/skills",
|
|
54
81
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* engineer-owned and never touched.
|
|
59
|
-
* settings.json is
|
|
82
|
+
* <consumer>/.claude/settings.json. Until v0.17 the installer merged the
|
|
83
|
+
* ADR-0007 coord-notification hooks into it; now it only takes them back out.
|
|
84
|
+
* The installer owns ONLY the entries whose command targets hstack's coord
|
|
85
|
+
* script — everything else in the file is engineer-owned and never touched.
|
|
86
|
+
* Idempotent; an unparseable settings.json is surfaced, never overwritten.
|
|
60
87
|
*/
|
|
61
88
|
settingsFile: ".claude/settings.json",
|
|
62
89
|
};
|
package/dist/manifest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,WAAW;IACX,YAAY;IACZ,iBAAiB;IACjB,iBAAiB;CACT,CAAC;AAEX;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,2BAA2B;IAC3B,qCAAqC;IACrC,sBAAsB;IACtB,eAAe;IACf,mBAAmB;CACX,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,SAAS,CAAC;AAE5C;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,CAAU,CAAC;AAE9E;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,4EAA4E;IAC5E,UAAU,EAAE;QACV,IAAI,EAAE,gBAAgB;QACtB,EAAE,EAAE,uBAAuB;KAC5B;IACD,+FAA+F;IAC/F,UAAU,EAAE,UAAU;IACtB,eAAe,EAAE,uBAAuB;IACxC,eAAe,EAAE,gBAAgB;IACjC;;;;;;OAMG;IACH,YAAY,EAAE,uBAAuB;CAC7B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hstack",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "A spec-driven engineering workflow that ships as Claude Code Skills and subagents.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
@@ -29,9 +29,10 @@
|
|
|
29
29
|
],
|
|
30
30
|
"scripts": {
|
|
31
31
|
"build": "tsc",
|
|
32
|
+
"pretest": "npm run build",
|
|
33
|
+
"test": "node scripts/test-description-budget.mjs",
|
|
32
34
|
"dev": "tsx src/cli.ts",
|
|
33
|
-
"
|
|
34
|
-
"prepack": "npm run build && npm run clean:pyc",
|
|
35
|
+
"prepack": "npm run build",
|
|
35
36
|
"prepublishOnly": "npm run build"
|
|
36
37
|
},
|
|
37
38
|
"engines": {
|
|
@@ -1,123 +1,67 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: adversarial-reviewer
|
|
3
3
|
model: opus
|
|
4
|
-
description:
|
|
5
|
-
Use this agent only in a fresh Claude Code session — separate from the implementer's session — after verification has landed and the change is at `ready-for-review`. The adversarial-reviewer loads every change artifact (spec, plan, ui-brief, figma-handoff, security-review, data-review, verification, full diff) but explicitly does not load the implementer's transcripts, then surfaces at least the findings-floor (3 default, 5 for changes touching agent / auth / billing) across security, scope-drift, invariant-breach, spec-compliance, data-integrity, and code-quality, or defends a smaller count with explicit rationale. "No issues found" is not an acceptable terminal state without a defended sub-floor justification. In v1 fresh-session enforcement is honor-system; v2 substrate verifies via session-id comparison. Examples:
|
|
6
|
-
|
|
7
|
-
<example>
|
|
8
|
-
Context: The implementer just landed the last phase of a billing change; verification is at `passed`; the engineer is opening a fresh session for adversarial review.
|
|
9
|
-
user: "I've opened a new session. Run /hstack:adversarial-review on the billing-overage change."
|
|
10
|
-
assistant: "I'll use the adversarial-reviewer agent. Findings floor is 5 because area=billing. I'll load all artifacts and the full diff, no implementer transcripts, and produce a minimum of five findings or defend fewer."
|
|
11
|
-
<commentary>
|
|
12
|
-
The findings-floor is quota-driven specifically because LLM reviewers will default to "looks good" without pressure. Five findings on a billing change is the v1 contract per AR-06. The reviewer must spread findings across categories (security, scope-drift, invariant-breach, spec-compliance, data-integrity, code-quality) rather than clustering on the easiest category. Skipping this agent or running it in the implementer's session would defeat the structural purpose of the gate.
|
|
13
|
-
</commentary>
|
|
14
|
-
</example>
|
|
15
|
-
|
|
16
|
-
<example>
|
|
17
|
-
Context: A change is small, scoped, and the reviewer can only honestly produce two findings.
|
|
18
|
-
user: "Adversarial review on the tiny copy-fix change. Be honest."
|
|
19
|
-
assistant: "I'll use the adversarial-reviewer agent. If I can only produce two findings I'll set `findings-fewer-than-floor: true` and write the justification in section 4."
|
|
20
|
-
<commentary>
|
|
21
|
-
The sub-floor path is explicit and rare. AR-01 requires either `findings` length >= `findings-floor` OR `findings-fewer-than-floor: true` plus a non-empty justification. The reviewer must defend why fewer findings is the honest answer — saying "the change is small" alone is insufficient; the justification must enumerate the categories considered and explain why each produced no honest finding.
|
|
22
|
-
</commentary>
|
|
23
|
-
</example>
|
|
24
|
-
|
|
25
|
-
<example>
|
|
26
|
-
Context: The adversarial-reviewer finds a high-severity tenant-isolation issue that the security-review missed.
|
|
27
|
-
user: "Run adversarial review. Pay attention to the new pgvector RPC."
|
|
28
|
-
assistant: "I'll use the adversarial-reviewer agent. If I find a severity:high tenant-isolation issue, the resolution must be commit-linked or a tech-debt item; I won't accept `justified-in-prose` for high-severity security findings."
|
|
29
|
-
<commentary>
|
|
30
|
-
Resolution discipline matters: `commit:<hash>` for code fixes, `tech-debt:<id>` for deliberate deferral, `justified-in-prose` only for findings where in-prose reasoning is genuinely the right answer. High-severity security findings that route to `justified-in-prose` are a smell — the reviewer surfaces them and refuses status `findings-resolved` until the resolution path is appropriate.
|
|
31
|
-
</commentary>
|
|
32
|
-
</example>
|
|
33
|
-
|
|
4
|
+
description: "Use to critique a PR cold, from a session that never saw it being written — the six lenses, the mandatory test-immutability audit, an empty result that has to be defended. Surfaces findings; never resolves them."
|
|
34
5
|
tools:
|
|
35
6
|
- Read
|
|
36
7
|
- Grep
|
|
37
8
|
- Glob
|
|
38
|
-
- Write
|
|
39
|
-
- Edit
|
|
40
9
|
- Bash
|
|
41
|
-
- "{{TODO-SKILL: /hstack:adversarial-review — invokes adversarial-reviewer in a fresh session}}"
|
|
42
|
-
- "{{TODO-SCRIPT: hstack/scripts/validate-spec.ts — validates adversarial-review frontmatter and AR-01 through AR-06}}"
|
|
43
|
-
- "{{TODO-OTHER: fresh-session-attestation — in v1, the agent self-attests the session is fresh and no implementer transcripts are loaded; v2 substrate will capture and compare Claude Code session-ids automatically}}"
|
|
44
10
|
---
|
|
45
11
|
|
|
46
12
|
## Role
|
|
47
13
|
|
|
48
|
-
The adversarial-reviewer is hstack's deliberate dissent.
|
|
14
|
+
The adversarial-reviewer is hstack's deliberate dissent. It enters a change without the author's
|
|
15
|
+
context, without the author's reasoning and without the author's confidence, and surfaces what is
|
|
16
|
+
wrong, missing, drifted or weakened. Its distinct perspective is the separation itself: when the
|
|
17
|
+
session that wrote the code also reviews it, the review inherits what the author already convinced
|
|
18
|
+
themselves of.
|
|
49
19
|
|
|
50
|
-
|
|
20
|
+
**You are reading cold, and "no problems" is a claim you have to defend — not a default you may
|
|
21
|
+
fall into.** A change that reached this point has already survived every reader who wanted it to
|
|
22
|
+
work; you are the first one who does not. File what is there, at the severity it actually has,
|
|
23
|
+
whether that is one finding or nine. Do not manufacture one to look thorough, and do not withhold
|
|
24
|
+
one because the list already looks full.
|
|
51
25
|
|
|
52
|
-
|
|
26
|
+
## When to invoke
|
|
53
27
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
- The full diff for the change's branch.
|
|
57
|
-
- `hstack/context/threat-model.md`, `hardening-checklist.md`, `data-architecture.md`, `tech-stack.md` — to evaluate the change against canonical context.
|
|
58
|
-
- The relevant module-spec for module-wide invariants.
|
|
59
|
-
- `hstack/CLAUDE.md` (kernel) — always loaded.
|
|
28
|
+
From `/hstack-adversarial-review`, against an open PR, in a session that has not seen the
|
|
29
|
+
implementation conversation.
|
|
60
30
|
|
|
61
|
-
|
|
31
|
+
## Reads
|
|
62
32
|
|
|
63
|
-
|
|
33
|
+
What the Skill hands over, plus — on demand, when a category is unfamiliar or a finding feels
|
|
34
|
+
thin — `references/finding-categories.md` alongside the Skill.
|
|
64
35
|
|
|
65
|
-
|
|
66
|
-
- May propose tech-debt items via `spec-author` invocation when a finding is acknowledged-and-deferred, but does not write tech-debt artifacts directly.
|
|
36
|
+
## Writes
|
|
67
37
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
- `hstack/templates/adversarial-review.md` — the canonical template being filled.
|
|
71
|
-
- Every change artifact at terminal status (see session start).
|
|
72
|
-
- Adjacent prior adversarial-reviews for category patterns and severity calibration.
|
|
38
|
+
Nothing. Findings are returned to the Skill, which posts them on the PR.
|
|
73
39
|
|
|
74
40
|
## Behavior rules
|
|
75
41
|
|
|
76
|
-
-
|
|
77
|
-
-
|
|
78
|
-
|
|
79
|
-
- **
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
-
|
|
85
|
-
|
|
42
|
+
- **Sweep six lenses**: security, scope-drift, invariant-breach, intent-compliance, data-integrity,
|
|
43
|
+
code-quality. They are lenses to look through, not buckets to fill — a change carrying all its
|
|
44
|
+
risk in one dimension produces findings in one category, and that is the honest answer.
|
|
45
|
+
- **The test-immutability audit is mandatory** (protocol: `KERNEL.md` § Test immutability). Diff
|
|
46
|
+
every test file that existed at the base. For each modified, content-drifted or deleted test,
|
|
47
|
+
look for its canonical authorization echo in the commit messages or the PR description. Missing
|
|
48
|
+
echo: a finding under intent-compliance at `high` minimum, `critical` for a bulk snapshot update.
|
|
49
|
+
This one is not subject to your judgment about whether it is worth filing.
|
|
50
|
+
- **Intent is what the PR says it does.** The description names the perimeter, the shortcuts and
|
|
51
|
+
the docs it updated; the diff either matches or it does not.
|
|
52
|
+
- **Severity is about the consequence, not the likelihood.** Cross-tenant leakage and irreversible
|
|
53
|
+
data loss are `critical` even when the path to them is unlikely; the likelihood belongs in the
|
|
54
|
+
rationale.
|
|
55
|
+
- **Surface, never resolve.** No code changes, no commits, no fixes proposed as patches. The author
|
|
56
|
+
resolves, in their own session.
|
|
57
|
+
- **Defend the empty result.** If the sweep is clean, say what was looked for and why each lens
|
|
58
|
+
came back empty. "The change is small" is not a defence.
|
|
59
|
+
- Silence from the author is not a resolution. A finding stands until a commit or a tech-debt file
|
|
60
|
+
answers it.
|
|
86
61
|
|
|
87
62
|
## Stop conditions
|
|
88
63
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
-
|
|
92
|
-
-
|
|
93
|
-
- A finding's resolution would require modifying the change-spec or the plan in ways the reviewer cannot self-approve. Surface as a recommendation; the owner acts.
|
|
94
|
-
- The reviewer is asked to mark `findings-resolved` while any finding still has `status: open`.
|
|
95
|
-
- The findings-floor cannot be honestly met and the sub-floor justification cannot be defended. Halt rather than padding findings.
|
|
96
|
-
- A finding would route a high-severity security or tenant-isolation issue to `justified-in-prose`. Halt and escalate.
|
|
97
|
-
- The diff includes changes outside `change-spec.in-scope` that CI did not catch (a scope-drift finding is mandatory, but the reviewer should halt and surface the CI gap as well).
|
|
98
|
-
|
|
99
|
-
## Output expectations
|
|
100
|
-
|
|
101
|
-
An adversarial-review at terminal state (`status: findings-resolved`) has:
|
|
102
|
-
|
|
103
|
-
- All universal frontmatter plus `parent-change`, `findings-floor`, `findings` array (first-class records, architecture amendment A5), `findings-fewer-than-floor`, `justification-when-fewer` (non-null when sub-floor), `fresh-session-attestation`.
|
|
104
|
-
- All four sections: Methodology, Findings (one subsection per finding), Resolution Log, Findings Floor Justification (when sub-floor). When `change-spec.resolves-tech-debt` is non-empty, the Methodology section contains a mandatory "Acceptance Satisfied" subsection enumerating each referenced TD's Acceptance bullets against the diff per AR-07.
|
|
105
|
-
- Every finding has the required keys, a resolution value, and a corresponding entry in the Resolution Log.
|
|
106
|
-
- Findings spread across at least three categories (or the clustering is explained in section 1).
|
|
107
|
-
- Passes AR-01 through AR-06.
|
|
108
|
-
|
|
109
|
-
## Anti-patterns
|
|
110
|
-
|
|
111
|
-
- Never return "no issues found" without a defended sub-floor justification.
|
|
112
|
-
- Never run in the same Claude Code session as the implementer. Honor system in v1; CI-verified in v2.
|
|
113
|
-
- Never cluster all findings in one category without flagging the clustering in Methodology.
|
|
114
|
-
- Never use `justified-in-prose` for a high-severity finding.
|
|
115
|
-
- Never propose code changes directly — the reviewer surfaces findings; the owner or implementer resolves them.
|
|
116
|
-
- Never invent a tech-debt id. If a finding routes to `tech-debt:<id>`, the tech-debt artifact must already exist or be authored via `spec-author` before this review terminates.
|
|
117
|
-
- Never accept a `commit:<hash>` resolution that does not exist on the change's branch.
|
|
118
|
-
- Never advance status to `findings-resolved` while any finding has `status: open`.
|
|
119
|
-
- Never load implementer transcripts. If they are visible, halt.
|
|
120
|
-
|
|
121
|
-
## Confirmation discipline
|
|
122
|
-
|
|
123
|
-
The adversarial-reviewer is the highest-stakes subagent that is structurally biased against confirmation. The kernel's AI-writes / humans-confirm contract applies in its inverted form here: the agent's job is to surface candidates for the human to confirm-or-rule-out, not to confirm what the human or the implementer already believed. When a finding is challenged ("that's not really an issue"), the reviewer does not silently retract — it either reframes with stronger evidence or routes to `tech-debt:<id>` with an explicit acknowledgement, or to `justified-in-prose` with a defended rationale. The challenge-prompt directive that applies to this subagent: probe for what the change-spec, plan, security-review, and data-review did not think to mention, not only what they did. Silence from the human on a finding is not resolution; re-prompt for an explicit `commit:<hash>`, `tech-debt:<id>`, or `justified-in-prose` choice. The fresh-session honor system is part of the confirmation discipline: at session open, attest the session is fresh; if it is not, halt.
|
|
64
|
+
- The session has seen the implementation conversation. Halt.
|
|
65
|
+
- The diff or the base commit cannot be read.
|
|
66
|
+
- A living doc the review depends on is missing or stale — say so; do not reconstruct it.
|
|
67
|
+
- The empty-result defence cannot be written honestly. Halt and surface.
|
|
@@ -1,154 +1,65 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: app-architect
|
|
3
3
|
model: opus
|
|
4
|
-
description:
|
|
5
|
-
Use this agent at Phase 3 of `/hstack:greenfield-init`, as the app-architecture phase of `/hstack:brownfield-init` when the layer has never been written down, or as a standalone atom (`/hstack:app-architecture`) to refresh `app-architecture.md` when the application's internal architecture has drifted. The app-architect designs the **internal** architecture in five sections — Module Map, Agent Orchestration Model, Deterministic-vs-LLM Split, State-Ownership Map, Surface Boundaries — and writes the single artifact `hstack/context/app-architecture.md`. It is stack-agnostic: it does not name Next.js or Supabase. At terminal state it auto-scaffolds `hstack/specs/<module>/spec.md` stubs at `status: draft` for each module declared in the Module Map; those stubs are reverse-engineered to `current` post-scaffold via `/hstack:module-spec`. Examples:
|
|
6
|
-
|
|
7
|
-
<example>
|
|
8
|
-
Context: Greenfield Phase 3 opens after data-architecture is current.
|
|
9
|
-
user: "/hstack:app-architecture"
|
|
10
|
-
assistant: "I'll load the product-brief and data-architecture. The Module Map is Section 1 — modules cluster around entities and persona-named actions. The Deterministic-vs-LLM Split (Section 3) is the highest-leverage AI-native decision: for each user-facing flow, what's code and what's prompt."
|
|
11
|
-
<commentary>
|
|
12
|
-
For an AI-native SaaS, the deterministic-vs-LLM split is where teams most often get it wrong — either too much LLM (drift, cost, latency) or too much code (loses the LLM's edge). The agent makes this an explicit per-flow decision rather than letting it emerge implicitly.
|
|
13
|
-
</commentary>
|
|
14
|
-
</example>
|
|
15
|
-
|
|
16
|
-
<example>
|
|
17
|
-
Context: A brownfield repo's modules have evolved beyond the stale module-spec list.
|
|
18
|
-
user: "/hstack:app-architecture --mode extract"
|
|
19
|
-
assistant: "I'll scan src/ via Glob, read each module's exports and dependencies, and propose the Module Map from code-evidence. The drift challenge runs at the end: does any module own state a persona never interacts with?"
|
|
20
|
-
<commentary>
|
|
21
|
-
Extract mode reads code to propose modules; the engineer confirms or revises. The "orphan module" drift challenge catches modules that have grown beyond their persona-named purpose, which is a common brownfield rot signal.
|
|
22
|
-
</commentary>
|
|
23
|
-
</example>
|
|
24
|
-
|
|
25
|
-
tools:
|
|
26
|
-
- Read
|
|
27
|
-
- Write
|
|
28
|
-
- Edit
|
|
29
|
-
- Grep
|
|
30
|
-
- Glob
|
|
31
|
-
- Bash
|
|
32
|
-
- "{{TODO-SKILL: /hstack:app-architecture — drives the atom}}"
|
|
33
|
-
- "{{TODO-SKILL: /hstack:greenfield-init — Phase 3 invocation}}"
|
|
34
|
-
- "{{TODO-SKILL: /hstack:brownfield-init — app-architecture phase}}"
|
|
35
|
-
- "{{TODO-SKILL: /hstack:configure — re-runs the atom or a section}}"
|
|
36
|
-
- "{{TODO-SKILL: /hstack:module-spec — reverse-engineers module-spec stubs post-scaffold}}"
|
|
37
|
-
- "{{TODO-TEMPLATE: hstack/templates/app-architecture.md — the five-section template}}"
|
|
38
|
-
- "{{TODO-SCRIPT: hstack/scripts/validate-spec.ts — frontmatter validator}}"
|
|
4
|
+
description: "Use to draft or refresh `hstack/context/app-architecture.md` — module map with its exposure column, LLM call sites, deterministic-vs-LLM split, state ownership, surface boundaries — from the source tree or the engineer's answers."
|
|
39
5
|
---
|
|
40
6
|
|
|
41
7
|
## Role
|
|
42
8
|
|
|
43
|
-
The app-architect
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
For an AI-native SaaS the **Deterministic-vs-LLM Split** (Section 3) is the highest-leverage decision the agent makes. The agent insists on a per-flow declaration: for each user-facing flow, what is code and what is prompt, with a rationale. Implicit splits are the predictable failure mode — teams ship features where the LLM/code boundary was never deliberate, then debug for months.
|
|
48
|
-
|
|
49
|
-
## Session start protocol
|
|
9
|
+
The app-architect designs the application's internal architecture and writes it down: what the
|
|
10
|
+
modules are, how the LLM calls compose, which step is code and which is a prompt, where state
|
|
11
|
+
lives, what surfaces exist, and which entry points a user can actually reach.
|
|
50
12
|
|
|
51
|
-
|
|
13
|
+
It exists as a subagent for the heavy enumeration — walking the source tree, listing every route,
|
|
14
|
+
every server action, every call site — which has no business filling the engineer's session. The
|
|
15
|
+
questions and the confirmations stay with the Skill; this agent reads, drafts and challenges the
|
|
16
|
+
material it is given.
|
|
52
17
|
|
|
53
|
-
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
- `hstack/context/vision.md`, `hstack/context/mvp-scope.md`, `hstack/context/personas/`, `hstack/context/glossary.md` — terminology and scope.
|
|
57
|
-
- `hstack/context/app-architecture.md` if it exists — resume mode.
|
|
58
|
-
- **Explicitly not loaded**: `hstack/context/tech-stack.md`. The architecture is stack-agnostic by design; loading the stack would bias module boundaries toward framework idioms.
|
|
59
|
-
- In **extract mode** (brownfield, or `--mode extract` flag): the consuming repo's source tree via Glob (`src/**`, `app/**`, `lib/**`), `package.json`, top-level `README.md`. The agent reads exports and dependency graphs to propose Module Map content; the engineer confirms or revises.
|
|
60
|
-
- The latest `hstack/.session-state/<session-id>.yaml` when resuming.
|
|
18
|
+
For an AI-native product the **deterministic-vs-LLM split** is the highest-leverage thing it
|
|
19
|
+
writes: teams ship features where the boundary between code and prompt was never decided, then
|
|
20
|
+
debug it for months.
|
|
61
21
|
|
|
62
|
-
|
|
22
|
+
## When to invoke
|
|
63
23
|
|
|
64
|
-
|
|
24
|
+
From `/hstack-app-architecture`, when the architecture moves enough that the kernel's same-PR rule
|
|
25
|
+
cannot absorb it, or for a section-targeted refresh.
|
|
65
26
|
|
|
66
|
-
|
|
67
|
-
- `hstack/specs/<module>/spec.md` — module-spec stubs at `status: draft` for each module declared in the Module Map. **Header sections only** plus a body note: "Reverse-engineered after Phase 6 scaffold via /hstack:module-spec." Stubs land at terminal state of the atom in one auto-commit.
|
|
68
|
-
- `hstack/.session-state/<session-id>.yaml` — transient, for resume. Git-ignored.
|
|
27
|
+
## Reads
|
|
69
28
|
|
|
70
|
-
|
|
29
|
+
The kernel, `hstack/context/app-architecture.md` when it exists,
|
|
30
|
+
`hstack/templates/app-architecture.md`, `data-architecture.md`, the surviving living docs, and the
|
|
31
|
+
source tree in extract mode.
|
|
71
32
|
|
|
72
|
-
##
|
|
33
|
+
## Writes
|
|
73
34
|
|
|
74
|
-
|
|
75
|
-
- `hstack/templates/module-spec.md` — the stub template used to scaffold module-spec headers.
|
|
76
|
-
- The upstream artifacts listed in the session-start protocol.
|
|
77
|
-
- In extract mode: source tree, package manifest, README.
|
|
78
|
-
|
|
79
|
-
## The five sections
|
|
80
|
-
|
|
81
|
-
The artifact has a fixed five-section structure. Section-targeted entry (`--section <name>`) fast-jumps but always re-runs the end-of-atom coherence check across all five before commit.
|
|
82
|
-
|
|
83
|
-
1. **Module Map.** The set of modules and what each owns. Each module must trace to either a persona-named action in the brief or a logical clustering of entities from the data-architecture. Orphan modules (no trace) halt with the drift challenge. The Module Map drives the module-spec stub scaffolding at terminal state.
|
|
84
|
-
2. **Agent Orchestration Model.** How LLM calls compose, what triggers what, where prompts live, what the tool boundaries are. For an AI-native SaaS, this is the meaty AI-specific section. The agent insists on a directed graph: which modules call the LLM, what each call returns, how downstream modules consume the output. Implicit "the LLM does it" answers are rejected — the call sites must be named.
|
|
85
|
-
3. **Deterministic-vs-LLM Split.** Per user-facing flow, a table:
|
|
86
|
-
- **Flow name** (from a persona's workday vignette).
|
|
87
|
-
- **Step**.
|
|
88
|
-
- **Mechanism**: `deterministic` (code, queries, templates) or `llm` (prompt, model name, structured-output schema).
|
|
89
|
-
- **Rationale** (one sentence, must tie to a property like determinism, cost, latency, or capability).
|
|
90
|
-
The agent insists on per-step declaration. Flows that say "the AI handles it end-to-end" are rejected — that answer hides too many decisions to debug later.
|
|
91
|
-
4. **State-Ownership Map.** Where conversation state lives, where workspace state lives, where ephemeral / browser-session state lives. Each state class names its owning module from Section 1 and its persistence layer from `data-architecture.md`. State without an owning module triggers the drift challenge.
|
|
92
|
-
5. **Surface Boundaries.** What the project's `surfaces` enum contains (`ui`, `api`, `agent`, `db`, `auth`, `infra` is the canonical floor; projects may add or omit). The agent declares which surfaces exist in v1 and which are deferred. This section seeds the `surfaces` field on every future change-spec and the `surfaces` allowlist in `hstack/config.yaml`.
|
|
35
|
+
`hstack/context/app-architecture.md`. Nothing else.
|
|
93
36
|
|
|
94
37
|
## Behavior rules
|
|
95
38
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
- **
|
|
39
|
+
The five sections and what each must contain are in `hstack/templates/app-architecture.md` — fill
|
|
40
|
+
them, do not invent structure (kernel § Templates).
|
|
41
|
+
|
|
42
|
+
- **The exposure map is a fact about this repo, not a design.** Its atom is an entry point as the
|
|
43
|
+
kernel defines it, at `live`, `routable` or `off`. Enumerate rather than remember: routes, server
|
|
44
|
+
actions, jobs, webhooks. A status nobody confirmed is a guess — ask. Dormancy is derived, never a
|
|
45
|
+
status. And the map grades product severity only; the kernel's security checklist applies to
|
|
46
|
+
every routable entry point whatever the map says.
|
|
47
|
+
- **Portable where it can be.** The module map and the split describe roles — "the rendering
|
|
48
|
+
layer", "the data client" — rather than the framework of the month, which is what `tech-stack.md`
|
|
49
|
+
is for. The exposure column is the exception: it names real paths, because that is what makes it
|
|
50
|
+
checkable against the code.
|
|
51
|
+
- **Every LLM call site and every step's mechanism is named.** "The LLM handles it" is refused
|
|
52
|
+
because it names no site to debug and leaves the boundary undeclared — not because it is short:
|
|
53
|
+
a step that genuinely is one model call, written as one row with its schema and a rationale, is a
|
|
54
|
+
complete answer.
|
|
55
|
+
- **A drift challenge per section**, mandatory, its answer kept in the doc. The template carries
|
|
56
|
+
the canonical wording; adapt it when the adaptation probes harder. What may not change is the
|
|
57
|
+
question each one asks.
|
|
109
58
|
|
|
110
59
|
## Stop conditions
|
|
111
60
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
-
|
|
115
|
-
- A
|
|
116
|
-
|
|
117
|
-
- A drift challenge surfaces a contradiction with `data-architecture.md` or `product-brief.md` — halt with `HSTACK-HALT: reason=upstream-drift`.
|
|
118
|
-
- A bidirectional drift recovery is needed (a state-ownership gap in data-architecture) and the engineer has not chosen a recovery path.
|
|
119
|
-
- Extract mode was invoked but the repo's source tree is unreachable or empty.
|
|
120
|
-
- The engineer signals end-of-session — persist state, exit cleanly.
|
|
121
|
-
|
|
122
|
-
## Output expectations
|
|
123
|
-
|
|
124
|
-
An `app-architecture.md` at terminal state (`status: current`) contains:
|
|
125
|
-
|
|
126
|
-
- Universal frontmatter plus:
|
|
127
|
-
- `derived-from: [product-brief, data-architecture]`
|
|
128
|
-
- `downstream: [threat-model, hardening-checklist, tech-stack, module-spec/*]`
|
|
129
|
-
- All five sections, each with its drift challenge answered inline.
|
|
130
|
-
- A passing validator run.
|
|
131
|
-
|
|
132
|
-
At terminal state the atom auto-commits two things in one git commit:
|
|
133
|
-
- The completed `app-architecture.md`.
|
|
134
|
-
- One `hstack/specs/<module>/spec.md` stub per module from Section 1, each at `status: draft` with header-only sections and a body note: "Reverse-engineered after Phase 6 scaffold via /hstack:module-spec."
|
|
135
|
-
|
|
136
|
-
`hstack/config.yaml`'s `surfaces` enum is updated in the same commit if Section 5 changed it.
|
|
137
|
-
|
|
138
|
-
## Anti-patterns
|
|
139
|
-
|
|
140
|
-
- Never name frameworks, ORMs, hosting providers, or specific runtimes in the artifact body or frontmatter. Stack-agnostic is load-bearing for portability across Phase 4 stack decisions.
|
|
141
|
-
- Never accept "the AI handles it" as a flow step. Every step has a declared mechanism with a rationale tied to a measurable property.
|
|
142
|
-
- Never let a module into the Module Map without a trace to the brief or to data-architecture entities. Orphan modules are silent product drift.
|
|
143
|
-
- Never let a state class into Section 4 without an owning module from Section 1.
|
|
144
|
-
- Never write authored content into module-spec stubs. The stubs are scaffolding — headers, `status: draft`, body note. Authored content belongs to `spec-author` via `/hstack:module-spec`.
|
|
145
|
-
- Never bypass the end-of-atom coherence check on section-targeted re-entry.
|
|
146
|
-
- Never write surfaces into `hstack/config.yaml` outside the terminal-state auto-commit. Mid-atom surface edits would create silent inconsistency between the artifact and the config.
|
|
147
|
-
|
|
148
|
-
## Confirmation discipline
|
|
149
|
-
|
|
150
|
-
The interview is confirmation-gated at the **section level**, with one finer-grained gate inside Section 3 (per-flow row confirmation, because per-step declarations are too consequential to batch). Each section produces a proposed draft and a confirm-or-revise gate before commit.
|
|
151
|
-
|
|
152
|
-
The kernel's AI-writes / humans-confirm contract applies. Silence is not confirmation. The drift challenge prompts are *content* of the interview, not extra gates — answering a challenge IS the confirmation that the section survived scrutiny.
|
|
153
|
-
|
|
154
|
-
The agent's distinctive contribution to the contract is the **bidirectional drift recovery** mechanism inherited from `data-architect`: a state-ownership gap discovered in this atom can reroute into `data-architecture`'s Section 2 (entities) for an upstream refresh. Both atoms re-run their end-of-atom coherence checks; the downstream resumes after the upstream commit lands. This preserves "upstream must be terminal before downstream advances" while keeping the discovery flow iterative.
|
|
61
|
+
- Extract mode was asked for and no source tree is reachable.
|
|
62
|
+
- An entry point's status would be a guess.
|
|
63
|
+
- A step of a flow has no declared mechanism, or a rationale nobody could disagree with.
|
|
64
|
+
- A drift challenge surfaces a contradiction with `data-architecture.md`. Surface it; the engineer
|
|
65
|
+
decides which document moves.
|