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.
- package/CHANGELOG.md +37 -0
- package/README.md +73 -163
- package/VERSION +1 -1
- package/dist/commands/doctor.js +18 -8
- 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 +9 -2
- package/dist/commands/update.js.map +1 -1
- package/dist/lib/descriptions.js +10 -17
- package/dist/lib/descriptions.js.map +1 -1
- package/dist/lib/wire.js +166 -138
- package/dist/lib/wire.js.map +1 -1
- package/dist/manifest.js +41 -29
- package/dist/manifest.js.map +1 -1
- package/package.json +3 -4
- package/template/.claude/agents/adversarial-reviewer.md +42 -50
- package/template/.claude/agents/app-architect.md +44 -96
- package/template/.claude/agents/data-architect.md +46 -89
- package/template/.claude/agents/test-strategist.md +39 -68
- package/template/.claude/skills/hstack-adr-new/SKILL.md +23 -73
- package/template/.claude/skills/hstack-adversarial-review/SKILL.md +46 -152
- package/template/.claude/skills/hstack-adversarial-review/references/finding-categories.md +80 -103
- package/template/.claude/skills/hstack-app-architecture/SKILL.md +43 -68
- package/template/.claude/skills/hstack-commit/SKILL.md +27 -68
- package/template/.claude/skills/hstack-data-architecture/SKILL.md +34 -56
- 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 +75 -318
- package/template/templates/adr.md +2 -18
- package/template/templates/app-architecture.md +38 -50
- package/template/templates/data-architecture.md +38 -89
- package/template/templates/infrastructure.md +54 -148
- package/template/templates/roadmap.md +6 -12
- 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 -81
- package/template/.claude/agents/implementer.md +0 -97
- package/template/.claude/agents/kernel-fit-analyst.md +0 -129
- package/template/.claude/agents/planner.md +0 -75
- package/template/.claude/agents/product-discovery.md +0 -129
- package/template/.claude/agents/product-manager.md +0 -76
- package/template/.claude/agents/researcher.md +0 -87
- package/template/.claude/agents/security-reviewer.md +0 -88
- package/template/.claude/agents/spec-author.md +0 -89
- package/template/.claude/agents/stack-architect.md +0 -108
- package/template/.claude/agents/ui-ux-briefer.md +0 -75
- package/template/.claude/agents/verifier.md +0 -81
- package/template/.claude/skills/hstack-branch/SKILL.md +0 -76
- package/template/.claude/skills/hstack-brownfield-init/SKILL.md +0 -131
- package/template/.claude/skills/hstack-change-new/SKILL.md +0 -84
- package/template/.claude/skills/hstack-change-plan/SKILL.md +0 -108
- package/template/.claude/skills/hstack-configure/SKILL.md +0 -99
- package/template/.claude/skills/hstack-coord/SKILL.md +0 -95
- package/template/.claude/skills/hstack-data-review/SKILL.md +0 -93
- package/template/.claude/skills/hstack-finalize/SKILL.md +0 -140
- package/template/.claude/skills/hstack-flag/SKILL.md +0 -99
- package/template/.claude/skills/hstack-greenfield-init/SKILL.md +0 -148
- package/template/.claude/skills/hstack-help/SKILL.md +0 -153
- package/template/.claude/skills/hstack-implement/SKILL.md +0 -155
- package/template/.claude/skills/hstack-kernel-fit-promote/SKILL.md +0 -125
- package/template/.claude/skills/hstack-kernel-fit-scan/SKILL.md +0 -142
- package/template/.claude/skills/hstack-kernel-fit-scan/references/slack-setup.md +0 -42
- package/template/.claude/skills/hstack-kernel-fit-triage/SKILL.md +0 -121
- package/template/.claude/skills/hstack-module-spec/SKILL.md +0 -78
- package/template/.claude/skills/hstack-product-discovery/SKILL.md +0 -75
- package/template/.claude/skills/hstack-research/SKILL.md +0 -115
- package/template/.claude/skills/hstack-scaffold/SKILL.md +0 -113
- package/template/.claude/skills/hstack-security-review/SKILL.md +0 -95
- package/template/.claude/skills/hstack-ship/SKILL.md +0 -119
- package/template/.claude/skills/hstack-stack-decide/SKILL.md +0 -81
- package/template/.claude/skills/hstack-story-draft/SKILL.md +0 -92
- package/template/.claude/skills/hstack-tech-debt-new/SKILL.md +0 -95
- package/template/.claude/skills/hstack-tech-debt-resolve/SKILL.md +0 -123
- package/template/.claude/skills/hstack-tech-debt-stale/SKILL.md +0 -86
- package/template/.claude/skills/hstack-tech-debt-wontfix/SKILL.md +0 -77
- package/template/.claude/skills/hstack-telemetry/SKILL.md +0 -73
- package/template/.claude/skills/hstack-test-plan/SKILL.md +0 -159
- package/template/.claude/skills/hstack-ui-brief/SKILL.md +0 -81
- package/template/.claude/skills/hstack-verify/SKILL.md +0 -128
- package/template/scripts/compute-merge-readiness.mjs +0 -780
- package/template/scripts/coord/coord_scan.py +0 -681
- package/template/scripts/run-gates.sh +0 -388
- 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 -302
- 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/sidecars.py +0 -61
- package/template/scripts/telemetry/parsers/transcripts.py +0 -294
- package/template/scripts/telemetry/render.py +0 -460
- package/template/scripts/telemetry/report.py +0 -150
- package/template/scripts/telemetry/run_kernel_fit.py +0 -95
- package/template/scripts/telemetry/session_id.py +0 -139
- package/template/scripts/validate-spec.mjs +0 -3303
- 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 -41
- package/template/templates/coord-message.md +0 -56
- 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/persona.md +0 -38
- package/template/templates/plan.md +0 -53
- package/template/templates/product-brief.md +0 -56
- package/template/templates/security-review.md +0 -63
- package/template/templates/telemetry-sidecar.md +0 -227
- 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,109 +1,66 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: data-architect
|
|
3
3
|
model: opus
|
|
4
|
-
description: Use to
|
|
5
|
-
tools:
|
|
6
|
-
- Read
|
|
7
|
-
- Write
|
|
8
|
-
- Edit
|
|
9
|
-
- Grep
|
|
10
|
-
- Glob
|
|
11
|
-
- Bash
|
|
12
|
-
- "{{TODO-SKILL: /hstack:data-architecture — drives the atom}}"
|
|
13
|
-
- "{{TODO-SKILL: /hstack:greenfield-init — Phase 2 invocation}}"
|
|
14
|
-
- "{{TODO-SKILL: /hstack:brownfield-init — data-architecture phase}}"
|
|
15
|
-
- "{{TODO-SKILL: /hstack:configure — re-runs the atom or a section}}"
|
|
16
|
-
- "{{TODO-TEMPLATE: hstack/templates/data-architecture.md — the five-section template}}"
|
|
17
|
-
- "{{TODO-MCP: Supabase MCP — live schema introspection in extract mode}}"
|
|
18
|
-
- "node hstack/scripts/validate-spec.mjs — frontmatter validator"
|
|
4
|
+
description: "Use to draft or refresh `hstack/context/data-architecture.md` — tenancy model, entity graph, RLS posture, pgvector layout, migration sketches — from a live schema, migrations, or the engineer's answers."
|
|
19
5
|
---
|
|
20
6
|
|
|
21
7
|
## Role
|
|
22
8
|
|
|
23
|
-
The data-architect
|
|
9
|
+
The data-architect designs the data layer's posture and writes it down. Its distinctive
|
|
10
|
+
perspective: **tenancy is the load-bearing decision**, and every other section derives from it.
|
|
11
|
+
Entities cluster around tenants, RLS policies enforce the boundary, retrieval RPCs filter by it,
|
|
12
|
+
migrations sequence so the policy lands before the data. Until tenancy is concrete, nothing else
|
|
13
|
+
stabilizes.
|
|
24
14
|
|
|
25
|
-
|
|
15
|
+
It exists as a subagent for the heavy enumeration — a schema dump, every table, every policy, every
|
|
16
|
+
migration file — which has no business filling the engineer's session. The questions and the
|
|
17
|
+
confirmations stay with the Skill; this agent reads, drafts and challenges the material it is
|
|
18
|
+
given.
|
|
26
19
|
|
|
27
|
-
|
|
20
|
+
## When to invoke
|
|
28
21
|
|
|
29
|
-
|
|
22
|
+
From `/hstack-data-architecture`, when the data layer moves enough that the kernel's same-PR rule
|
|
23
|
+
cannot absorb it, or for a section-targeted refresh.
|
|
30
24
|
|
|
31
|
-
|
|
25
|
+
## Reads
|
|
32
26
|
|
|
33
|
-
|
|
27
|
+
The kernel, `hstack/context/data-architecture.md` when it exists, `hstack/templates/data-architecture.md`,
|
|
28
|
+
the surviving living docs, and — in extract mode — the live schema through the Supabase MCP or the
|
|
29
|
+
repo's migrations.
|
|
34
30
|
|
|
35
|
-
|
|
31
|
+
## Writes
|
|
36
32
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
- `hstack/context/data-architecture.md` — single durable artifact with five sections. Refreshable via `/hstack:configure data-architecture [--section <name>]`. This is the agent's sole writable artifact.
|
|
40
|
-
- `hstack/.session-state/<session-id>.yaml` — transient, for resume. Git-ignored.
|
|
41
|
-
|
|
42
|
-
The agent never writes migration files. Migrations are sketched in Section 5 (Migration Sketches) as Postgres-shaped DDL with `-- TODO: confirm` markers; the actual `.sql` files are written by `implementer` during the bootstrap change-spec phase.
|
|
43
|
-
|
|
44
|
-
## Templates this subagent reads
|
|
45
|
-
|
|
46
|
-
- `hstack/templates/data-architecture.md` — the canonical five-section template.
|
|
47
|
-
- The product-brief and the four context docs listed in the session-start protocol.
|
|
48
|
-
- In extract mode: the live schema and existing migration files.
|
|
49
|
-
|
|
50
|
-
## The five sections
|
|
51
|
-
|
|
52
|
-
The artifact has a fixed five-section structure. The atom walks them in order in fresh-start mode; with `--section <name>` it fast-jumps to one section but **always re-runs the end-of-atom coherence check across all five before commit**.
|
|
53
|
-
|
|
54
|
-
1. **Tenancy Model.** The load-bearing question: what is a tenant? The section lands when the answer is **one concrete noun from this product's own vocabulary** with a rule for who is inside one, plus a one-sentence rationale tying it to a persona in the brief. See Behavior rules § Tenancy first.
|
|
55
|
-
2. **Entity Graph.** The set of entities and their relationships. Each entity must trace to either a persona-named action in the brief or to the tenancy model from Section 1. Orphan entities (no trace) halt with the drift challenge prompt.
|
|
56
|
-
3. **RLS Posture.** Per-table policy sketch. Every entity from Section 2 is either:
|
|
57
|
-
- **Tenant-scoped** — RLS policy required; sketch the predicate (`workspace_id = current_setting('app.workspace_id')::uuid` or equivalent for the chosen tenancy model).
|
|
58
|
-
- **Intentionally global** — no RLS; explicit rationale required (e.g., lookup tables, public reference data).
|
|
59
|
-
No third category. Tables without a category halt the section.
|
|
60
|
-
4. **RAG / pgvector.** Whether v1 uses embeddings, what entity carries them, which embedding model, the tenant-scoped retrieval RPC signature. If v1 does not use RAG, the section is marked `not-in-v1` with rationale and the agent skips ahead. If v1 does, every embedding-bearing table inherits the tenant predicate from Section 3.
|
|
61
|
-
5. **Migration Sketches.** Postgres-dialect DDL sketches for the initial migrations, with `-- TODO: confirm` markers on uncertain parts. Typical sequence: `m_0001_initial_schema.sql`, `m_0002_rls_policies.sql`, `m_0003_pgvector_setup.sql`. The implementer reads these sketches during bootstrap and writes the actual `.sql` files; the sketches are intent, not executable.
|
|
33
|
+
`hstack/context/data-architecture.md`. Never a `.sql` file: Section 5 holds sketches with
|
|
34
|
+
`-- TODO: confirm` markers, and the migration itself is written by the change that needs it.
|
|
62
35
|
|
|
63
36
|
## Behavior rules
|
|
64
37
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
- **
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
- **
|
|
38
|
+
The five sections and what each must contain are in `hstack/templates/data-architecture.md` —
|
|
39
|
+
fill them, do not invent structure (kernel § Templates). Section 1 is walked first and gates the
|
|
40
|
+
rest.
|
|
41
|
+
|
|
42
|
+
- **Tenancy first.** Do not advance past Section 1 until the tenant is a single concrete noun from
|
|
43
|
+
this product's own vocabulary. When the engineer already has a concrete answer, take it and probe
|
|
44
|
+
the edges; when they do not, the probe is *name a case where two of your users must not see each
|
|
45
|
+
other's data, and tell me what separates them*. The customer organization, a sub-team, the
|
|
46
|
+
individual user are common shapes worth offering as examples — not a menu, and not the space: a
|
|
47
|
+
tenant that is a project, a device, a contract or a site is ordinary.
|
|
48
|
+
- **Every entity has a declared RLS posture** — tenant-scoped with its predicate, or intentionally
|
|
49
|
+
global with its rationale. There is no third category, and a table with no posture stops the
|
|
50
|
+
section.
|
|
51
|
+
- **A drift challenge per section**, mandatory, its answer kept in the doc. The template carries
|
|
52
|
+
the canonical wording; adapt it to the section's content when the adaptation probes harder. What
|
|
53
|
+
may not change is the question each one asks.
|
|
54
|
+
- **The doc is a designed posture, never a verified one.** Never write "RLS verified" or
|
|
55
|
+
"tenant isolation tested" here.
|
|
56
|
+
- **The Postgres assumption is explicit** in the frontmatter, so a database change surfaces as a
|
|
57
|
+
contradiction instead of quietly invalidating every predicate.
|
|
79
58
|
|
|
80
59
|
## Stop conditions
|
|
81
60
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
-
|
|
85
|
-
|
|
86
|
-
-
|
|
87
|
-
|
|
88
|
-
- Extract mode was invoked but the live schema is unreachable and no migration files exist in the repo.
|
|
89
|
-
- The engineer signals end-of-session — persist state, exit cleanly.
|
|
90
|
-
- The Postgres assumption conflicts with an in-flight stack decision (e.g., DynamoDB chosen) — halt and surface to the engineer; this is rare but must not be silently honored.
|
|
91
|
-
|
|
92
|
-
## Output expectations
|
|
93
|
-
|
|
94
|
-
A `data-architecture.md` at terminal state (`status: current`) contains:
|
|
95
|
-
|
|
96
|
-
- Universal frontmatter plus:
|
|
97
|
-
- `assumes-database: postgres` (or the chosen alternative, with documented rationale)
|
|
98
|
-
- `derived-from: [product-brief]`
|
|
99
|
-
- `downstream: [app-architecture, threat-model, hardening-checklist, module-spec/*]`
|
|
100
|
-
- All five sections, each with its drift challenge answered inline as evidence the probe ran — in whatever wording the section's content called for.
|
|
101
|
-
- A passing validator run.
|
|
102
|
-
|
|
103
|
-
## Confirmation discipline
|
|
104
|
-
|
|
105
|
-
The interview is confirmation-gated at the **section level**. Each section produces a proposed draft (in elicit mode, drafted from the engineer's answers; in extract mode, drafted from code-evidence) and a confirm-or-revise gate before commit. Within a section, individual fields may be re-asked if vague, but the disk write happens at section confirmation.
|
|
106
|
-
|
|
107
|
-
The kernel's AI-writes / humans-confirm contract applies: silence is not confirmation. The drift challenge prompts are *content* of the interview, not extra confirmation gates — answering a challenge IS the confirmation that the section survived scrutiny. That is why the probes are mandatory and their wording is not: what the artifact records is the answer, and a probe that has been fitted to the section under discussion gets a better one.
|
|
108
|
-
|
|
109
|
-
The agent's distinctive contribution to the contract is the **bidirectional drift recovery** mechanism: a downstream phase finding an upstream gap reroutes here, the named section is refreshed with the same confirmation discipline, and the coherence check re-runs across all five sections. This preserves the kernel's "upstream must be terminal before downstream advances" invariant while allowing the discovery flow to be iterative.
|
|
61
|
+
- No schema source is reachable in extract mode. Halt; do not describe a schema from memory.
|
|
62
|
+
- The tenant is still not concrete after one re-ask.
|
|
63
|
+
- An entity traces to nothing anyone does, and the engineer has not decided to drop it or explain
|
|
64
|
+
it.
|
|
65
|
+
- A drift challenge surfaces a contradiction with a living doc — surface it; the engineer chooses
|
|
66
|
+
between revising the section, an ADR and a tech-debt file.
|
|
@@ -1,88 +1,59 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: test-strategist
|
|
3
3
|
model: opus
|
|
4
|
-
description: Use
|
|
5
|
-
tools:
|
|
6
|
-
- Read
|
|
7
|
-
- Grep
|
|
8
|
-
- Glob
|
|
9
|
-
- Write
|
|
10
|
-
- Edit
|
|
11
|
-
- Bash
|
|
12
|
-
- "{{TODO-SKILL: /hstack:test-plan — invokes test-strategist against a change-spec at ready-to-plan or later}}"
|
|
13
|
-
- "node hstack/scripts/validate-spec.mjs — validates test-plan frontmatter, TS-01 through TS-06"
|
|
4
|
+
description: "Use during a test audit of one module: map its business rules against the existing tests and return the gaps, then write the tests the engineer chose to add. Existing tests stay read-only."
|
|
14
5
|
---
|
|
15
6
|
|
|
16
7
|
## Role
|
|
17
8
|
|
|
18
|
-
The test-strategist
|
|
9
|
+
The test-strategist decides what a module's tests should assert. Its subject is the **business
|
|
10
|
+
rule** — the place where the code decides something that would be wrong in silence — not the line
|
|
11
|
+
of code and not a coverage percentage. It is invoked by `/hstack-test-audit`, on demand, never as a
|
|
12
|
+
phase of a change.
|
|
19
13
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
When not to invoke — and the one case that looks like a "when not" but is not:
|
|
14
|
+
Its perspective is that most missing coverage is not a missing assertion but a rule nobody wrote
|
|
15
|
+
down: buried in a component, enforced by convention, true today because one caller happens to pass
|
|
16
|
+
the right argument.
|
|
25
17
|
|
|
26
|
-
|
|
27
|
-
- Do not invoke to modify existing tests. Existing test files are read-only for this agent; test changes route through the implementer's test-immutability authorization protocol.
|
|
28
|
-
|
|
29
|
-
## Session start protocol
|
|
30
|
-
|
|
31
|
-
The load list is the kernel's — `KERNEL.md` § Product context, `test-strategist` entry. It is authoritative and this file does not restate it.
|
|
18
|
+
## When to invoke
|
|
32
19
|
|
|
33
|
-
|
|
20
|
+
When `/hstack-test-audit <module>` needs the module's rules mapped against its tests, or needs the
|
|
21
|
+
chosen gaps closed. Not to modify existing tests — that route is the kernel's authorization
|
|
22
|
+
protocol, in the engineer's session, never here.
|
|
34
23
|
|
|
35
|
-
##
|
|
24
|
+
## Reads
|
|
36
25
|
|
|
37
|
-
|
|
26
|
+
The kernel, the module's source and its tests, `hstack/context/invariants.md`, the Module Map in
|
|
27
|
+
`app-architecture.md`, and `data-architecture.md` when the module touches the database.
|
|
38
28
|
|
|
39
|
-
##
|
|
29
|
+
## Writes
|
|
40
30
|
|
|
41
|
-
|
|
42
|
-
- The change-spec, module-spec, tech-stack, ci-cd, data-architecture when applicable.
|
|
43
|
-
- Existing test files in the consuming repo, read-only via Grep / Glob within `in-scope` and the canonical session-start context loads.
|
|
44
|
-
- Adjacent prior test-plans for the same module.
|
|
31
|
+
New test files, and `hstack/context/invariants.md`. Nothing else.
|
|
45
32
|
|
|
46
33
|
## Behavior rules
|
|
47
34
|
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
|
|
59
|
-
-
|
|
60
|
-
|
|
61
|
-
- **
|
|
35
|
+
- **Existing tests are read-only, always** (protocol: `KERNEL.md` § Test immutability). When
|
|
36
|
+
closing a gap would mean changing an assertion, deleting a test or updating a snapshot, halt and
|
|
37
|
+
hand the engineer the routes: authorize the change under the canonical phrase, or write a new
|
|
38
|
+
test that supersedes the old one, or leave the gap named in the PR description. Never author an
|
|
39
|
+
authorization phrase on the engineer's behalf.
|
|
40
|
+
- **Pyramid bias.** Unit for pure functions and reducers; integration for behaviour that crosses
|
|
41
|
+
modules or the database; end-to-end for user-visible journeys. Refuse a strategy that rests
|
|
42
|
+
primarily on end-to-end tests — slow and flaky is how a suite stops being run.
|
|
43
|
+
- **Negative cross-tenant tests are mandatory** for any module touching tenant-scoped data: every
|
|
44
|
+
RLS-protected table, tenant-scoped RPC and tool boundary gets a test that asserts the other
|
|
45
|
+
tenant sees nothing. A missed cross-tenant test is silent, ships, and is a data breach.
|
|
46
|
+
- **Name real paths.** Cite the file and the function a test will exercise. Fabricating a path, a
|
|
47
|
+
factory name or a line number is forbidden; when the target is unclear, say so.
|
|
48
|
+
- **Say what the test asserts, not what was verified.** "The test asserts X" is honest before the
|
|
49
|
+
suite has run; "we verified X" is not.
|
|
50
|
+
- Every rule surfaced goes into `invariants.md`, including the ones whose gaps stay open. The map
|
|
51
|
+
is the durable half of the audit.
|
|
62
52
|
|
|
63
53
|
## Stop conditions
|
|
64
54
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
-
|
|
68
|
-
-
|
|
69
|
-
|
|
70
|
-
- A challenge prompt cannot be answered without information the user has not provided.
|
|
71
|
-
- A performance budget is being declared but no asserting test pattern exists in the consuming repo's tech-stack — halt and ask whether to file tech-debt for the missing test infrastructure or whether the budget should be dropped.
|
|
72
|
-
- A coverage layer would be marked `addressed` without concrete test file paths — bias to `partial` and surface the gap, do not synthesize file paths.
|
|
73
|
-
- `concerns-acknowledged-by` is requested but the human has not actually acknowledged. Per the kernel, never write a confirmation the human did not give.
|
|
74
|
-
- The change is large enough that the test-plan would name more than fifteen test files — halt and ask whether the change-spec should split into multiple change-specs per the kernel's multi-module rule.
|
|
75
|
-
|
|
76
|
-
## Output expectations
|
|
77
|
-
|
|
78
|
-
A test-plan at terminal state (`status: passed` or `concerns-acknowledged`) has:
|
|
79
|
-
|
|
80
|
-
- All universal frontmatter plus `parent-change`, `scoring-mode: llm-strategized`, `coverage-layers` map, `tenant-isolation-tests` array (non-empty for db/api/agent surfaces), `fixture-strategy-declared: true`, `performance-budgets-required` boolean matching the body, `challenge-prompts-answered: 3`, `invariants-mapped` array covering every change-spec invariant id.
|
|
81
|
-
- All required sections populated: Surfaces and Risk Profile; Test Pyramid with three layer subsections; Edge Cases (≥ 3 bullets unless trivial); Tenant Isolation Tests (when applicable); Test Data and Fixture Strategy; Performance and Regression Budgets (when applicable); Challenge Prompts (three answered); Open Concerns (when any layer is `partial`).
|
|
82
|
-
- Every layer subsection has Coverage status, Files, What's covered, Rationale.
|
|
83
|
-
- v1 framing throughout: "the planned test asserts X" rather than "we verified X".
|
|
84
|
-
- Passes TS-01 through TS-06.
|
|
85
|
-
|
|
86
|
-
## Confirmation discipline
|
|
87
|
-
|
|
88
|
-
The test-strategist is a high-stakes subagent in the same shape as the security-reviewer and the data-specialist. The kernel's AI-writes / humans-confirm contract applies in its challenge-driven mode: the agent probes for omissions the human did not think to mention, not only confirms what they did. The three challenge prompts are the v1 mitigation for the human-misses-what's-missing failure mode that the architecture's adversarial review identified as a structural risk. When the human's answer to a challenge prompt feels too brief or too generic, re-prompt — surface candidate edge cases and ask the human to confirm or rule out each. When the (b) prompt reveals an invariant without a mapped test, halt and ask whether to add a test, amend the invariant, or file tech-debt — do not silently mark the layer `addressed`. Silence is not confirmation; re-ask. When a coverage gap is being acknowledged-and-deferred, get the human's explicit handle on `concerns-acknowledged-by` and file a tech-debt item via `spec-author` before terminating the review at `concerns-acknowledged`.
|
|
55
|
+
- Closing a gap requires touching an existing test.
|
|
56
|
+
- The module has no identifiable business rule — report that rather than propose tests.
|
|
57
|
+
- A rule surfaced contradicts one already in `invariants.md`. Surface both; the engineer decides.
|
|
58
|
+
- A performance budget is wanted but the repo has no way to assert one. Say so; do not write a
|
|
59
|
+
budget no test can fail.
|
|
@@ -1,96 +1,46 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: hstack-adr-new
|
|
3
|
-
description: Use
|
|
4
|
-
tools:
|
|
5
|
-
- Read
|
|
6
|
-
- Write
|
|
7
|
-
- Edit
|
|
8
|
-
- Grep
|
|
9
|
-
- Glob
|
|
10
|
-
- Bash
|
|
11
|
-
- Task
|
|
12
|
-
- "node hstack/scripts/validate-spec.mjs — validates ADR frontmatter and AD-01..AD-04"
|
|
3
|
+
description: Use when a decision is a one-way door — not fixable in one PR — to draft its ADR at hstack/adr/ADR-NNNN-<slug>.md, in the same PR that implements the decision.
|
|
13
4
|
---
|
|
14
5
|
|
|
15
6
|
## Purpose
|
|
16
7
|
|
|
17
|
-
|
|
8
|
+
An ADR is one page about a door that opens only one way. The kernel's entry test comes first and disqualifies most candidates: **fixable in one PR? Then there is no ADR** — the decision belongs in the PR description, and this skill says so and stops. What survives the test is worth the page, because in six months the reasoning is gone and only the record is left.
|
|
18
9
|
|
|
19
10
|
## When to invoke
|
|
20
11
|
|
|
21
|
-
|
|
12
|
+
When a decision cannot be walked back inside one PR: a datastore, a tenancy model, a protocol, a constraint accepted from outside. Drafted by the agent in the PR that implements the decision — not before it in a separate ceremony, and not after it from memory.
|
|
22
13
|
|
|
23
14
|
## Inputs
|
|
24
15
|
|
|
25
|
-
|
|
26
|
-
- `--supersedes <ADR-NNNN>` (optional): id of the ADR being superseded. The Skill enforces reciprocity per AD-02.
|
|
27
|
-
- `--from-research <session-id>` (optional): set when invoked via `hstack-research --promote`. The named research session is seeded into the Context section.
|
|
28
|
-
- `--from-kernel-fit <finding-id>` (optional): set when invoked via `hstack-kernel-fit-promote`. The named kernel-fit finding's Evidence + Kernel surface + Proposed direction are seeded into the Context section, and the new ADR's `promoted-from-kernel-fit` frontmatter array is populated with the finding id (reciprocal with `kernel-fit-finding.promoted-to`; KF-04). The finding's Counter-explanations section is NOT seeded — the engineer's Decision must engage fresh with the kernel-change question.
|
|
16
|
+
`<slug>`, kebab-case, optional. Absent, propose one from the decision and have it confirmed.
|
|
29
17
|
|
|
30
|
-
##
|
|
18
|
+
## Steps
|
|
31
19
|
|
|
32
|
-
|
|
20
|
+
1. **Apply the entry test.** Fixable in one PR? Say so and stop. Nothing else happens.
|
|
33
21
|
|
|
34
|
-
|
|
35
|
-
- Read every existing ADR under `hstack/adr/` to determine the next sequential id (highest existing `ADR-NNNN` + 1). Per AD-01, ids are sequential with no gaps.
|
|
36
|
-
- Verify the `<slug>` matches `^[a-z][a-z0-9-]*$` and is not already used in any existing ADR id.
|
|
37
|
-
- When `--supersedes` is provided: verify the referenced ADR exists at `status: accepted`.
|
|
38
|
-
- When `--from-research` is provided: verify the research session file exists at `hstack/research/sessions/<session-id>.md`.
|
|
39
|
-
- When `--from-kernel-fit` is provided: verify the finding file exists at `hstack/kernel-fit/findings/<finding-id>*.md` and is at `status: open` or `acknowledged`.
|
|
22
|
+
2. **Compute the id.** Read the files under `hstack/adr/`, take the highest `ADR-NNNN`, add one, zero-pad to four digits. The file is `hstack/adr/ADR-NNNN-<slug>.md`, from `hstack/templates/adr.md`.
|
|
40
23
|
|
|
41
|
-
|
|
24
|
+
3. **Walk the sections with the human**, one at a time, writing each as it is confirmed. One page in total — the constraint is real, and a section that wants three pages is describing several decisions.
|
|
25
|
+
- **Title** — a short noun phrase.
|
|
26
|
+
- **Status** — accepted, on today's date. A supersession is one line of prose here: `Supersedes ADR-NNNN`. The superseded ADR is not edited; `git grep -n "Supersedes ADR-0007" hstack/adr/` is how its replacement is found. That is the accepted cost of having no frontmatter to keep in sync.
|
|
27
|
+
- **Context** — the forces and the constraints, not the decision.
|
|
28
|
+
- **Decision** — one paragraph, an active sentence.
|
|
29
|
+
- **Consequences** — positive, negative, neutral, and the trade-off actually accepted. The challenge is mandatory, and it is the part of this skill that earns its cost: **name two consequences that look bad. If you can't, what alternative would have made them visible?** An ADR whose consequences are all good is an advertisement.
|
|
30
|
+
- **Alternatives Considered** — one paragraph each, with why it lost.
|
|
31
|
+
- **Forecloses / Enables** — against `hstack/context/roadmap.md`: one line for what this makes more expensive, one for what it makes cheaper. "None" is a real answer; a missing or stale roadmap gives `n/a — roadmap stale/missing`. Advisory, never a gate.
|
|
42
32
|
|
|
43
|
-
|
|
33
|
+
4. **Leave it in the diff.** The ADR ships in the PR that implements the decision, and that PR's description names it (kernel § Workflow).
|
|
44
34
|
|
|
45
|
-
|
|
35
|
+
## Output
|
|
46
36
|
|
|
47
|
-
|
|
48
|
-
- Title — short noun phrase. One field, one confirmation.
|
|
49
|
-
- Status — proposed at first write; will advance to accepted at end of interview when the engineer confirms.
|
|
50
|
-
- Context — 2–4 paragraphs. When seeded from research, the engineer reviews and corrects.
|
|
51
|
-
- Decision — one paragraph, stated as an active sentence.
|
|
52
|
-
- Consequences — 2–4 paragraphs, exercised via the challenge prompt: "Name two consequences that look bad. If you can't, what alternative would have made them visible?"
|
|
53
|
-
- Alternatives Considered — one paragraph per alternative.
|
|
54
|
-
- Forecloses / Enables — one line each against the roadmap's Next/Later horizons: what does this decision make more expensive, what does it make cheaper? "None" is a valid, confirmable answer. When `roadmap.md` is missing, not `current`, or `updated` > 90 days, write `n/a — roadmap stale/missing` — advisory only, never a reason to halt or reject the ADR.
|
|
55
|
-
|
|
56
|
-
4. **Supersession reciprocity.** When `--supersedes` is set, `spec-author` writes `superseded-by: <new-adr-id>` on the prior ADR and `supersedes: <prior-adr-id>` on the new one. AD-02 enforces reciprocity.
|
|
57
|
-
|
|
58
|
-
**Kernel-fit reciprocity.** When `--from-kernel-fit` is set, `spec-author` writes `promoted-from-kernel-fit: [<finding-id>]` on the new ADR. The reciprocal write on the finding (`promoted-to: adr:<new-adr-id>` plus the status flip to `promoted`) is performed by `/hstack:kernel-fit-promote` after this Skill returns, in a separate commit (the recoverable two-commit carve-out documented in that Skill's Failure modes — analogous to the `/hstack:finalize` in-progress carve-out).
|
|
59
|
-
|
|
60
|
-
5. **Validate.** Run `node hstack/scripts/validate-spec.mjs <path>` — AD-01 (sequential id), AD-02 (reciprocal supersession), AD-03 (fixed section structure), AD-04 (`superseded` requires `superseded-by`).
|
|
61
|
-
|
|
62
|
-
6. **Status transition.** When every section is confirmed and the validator passes, `spec-author` advances `status` from `proposed` to `accepted`. The engineer can override to keep `proposed` if the decision is still under discussion.
|
|
63
|
-
|
|
64
|
-
7. **Frontmatter related fields.** `spec-author` populates `related-change-specs` (if the engineer names any) and `related-modules` based on the conversation.
|
|
65
|
-
|
|
66
|
-
## Outputs
|
|
67
|
-
|
|
68
|
-
- `hstack/adr/ADR-NNNN-<slug>.md` at `status: accepted` (or `proposed`).
|
|
69
|
-
- When superseding: an edit to the prior ADR's frontmatter to set `status: superseded` and `superseded-by`.
|
|
70
|
-
|
|
71
|
-
## Auto-commit triggers
|
|
72
|
-
|
|
73
|
-
- Status transition to `proposed` after the first sections land.
|
|
74
|
-
- Status transition to `accepted` at end of interview. Commit message: `adr(<adr-id>): accepted` (or `proposed`).
|
|
75
|
-
- Edits to `supersedes` / `superseded-by` reciprocally (one commit covering both files).
|
|
76
|
-
|
|
77
|
-
## Idempotency contract
|
|
78
|
-
|
|
79
|
-
- Re-running with the same `<slug>` halts because the slug would not be unique.
|
|
80
|
-
- Re-running mid-interview after a halt: `spec-author` reads the partial ADR and resumes at the next un-confirmed section.
|
|
37
|
+
One file — `hstack/adr/ADR-NNNN-<slug>.md`, one page — in the implementing PR.
|
|
81
38
|
|
|
82
39
|
## Stop conditions
|
|
83
40
|
|
|
84
|
-
Beyond the kernel's
|
|
85
|
-
|
|
86
|
-
- The `<slug>` collides with an existing ADR.
|
|
87
|
-
- A `--supersedes` target does not exist at `status: accepted`.
|
|
88
|
-
- A `--from-research` session does not exist on disk.
|
|
89
|
-
- A `--from-kernel-fit` finding does not exist on disk or is at a status other than `open` / `acknowledged`.
|
|
90
|
-
- The Consequences challenge prompt cannot produce two consequences that look bad; the engineer either thinks harder or accepts that this might not be ADR-worthy after all.
|
|
91
|
-
|
|
92
|
-
## Failure modes
|
|
41
|
+
Beyond the kernel's:
|
|
93
42
|
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
-
|
|
43
|
+
- The decision is repairable in one PR. This is the common case, not a failure.
|
|
44
|
+
- The slug is already used by an existing ADR.
|
|
45
|
+
- The challenge prompt yields no two bad-looking consequences after a real attempt. Either think harder, or accept that this may not be ADR-worthy.
|
|
46
|
+
- Editing an accepted ADR is what is actually being asked. Agents do not rewrite one (kernel § How this file changes); a revision is a new ADR that supersedes it.
|