hstack 0.3.0 → 0.5.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 +60 -0
- package/README.md +56 -14
- package/VERSION +1 -1
- package/dist/lib/wire.js +18 -0
- package/dist/lib/wire.js.map +1 -1
- package/package.json +1 -1
- package/template/.claude/agents/app-architect.md +154 -0
- package/template/.claude/agents/data-architect.md +147 -0
- package/template/.claude/agents/kernel-fit-analyst.md +53 -0
- package/template/.claude/agents/product-discovery.md +165 -0
- package/template/.claude/agents/stack-architect.md +137 -0
- package/template/.claude/skills/hstack-app-architecture/SKILL.md +109 -0
- package/template/.claude/skills/{hstack-init → hstack-brownfield-init}/SKILL.md +17 -11
- package/template/.claude/skills/hstack-data-architecture/SKILL.md +100 -0
- package/template/.claude/skills/hstack-flag/SKILL.md +138 -0
- package/template/.claude/skills/hstack-greenfield-init/SKILL.md +150 -0
- package/template/.claude/skills/hstack-kernel-fit-scan/SKILL.md +31 -14
- package/template/.claude/skills/hstack-product-discovery/SKILL.md +101 -0
- package/template/.claude/skills/hstack-scaffold/SKILL.md +140 -0
- package/template/.claude/skills/hstack-stack-decide/SKILL.md +108 -0
- package/template/CLAUDE.md +23 -7
- package/template/templates/app-architecture.md +102 -0
- package/template/templates/bootstrap.md +105 -0
- package/template/templates/data-architecture.md +147 -13
- package/template/templates/discovery/brainstorm.md +69 -0
- package/template/templates/discovery/forcing-questions.md +76 -0
- package/template/templates/discovery/project-brief.md +53 -0
- package/template/templates/kernel-fit-finding.md +1 -0
- package/template/templates/kernel-fit-flag.md +52 -0
- package/template/templates/product-brief.md +56 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hstack-scaffold
|
|
3
|
+
description: |
|
|
4
|
+
Use this skill as Phase 6 of `/hstack:greenfield-init` to bootstrap the consuming repository from empty to bootable. The Skill generates a **bootstrap change-spec** from `hstack/templates/bootstrap.md` (a change-spec variant with `area: bootstrap`, `surfaces: [infra]`), enumerates `in-scope` explicitly from the upstream artifacts (Module Map from app-architecture, Migration Sketches from data-architecture, stack ADRs from Phase 4), runs `data-review` and `security-review` in `--mode foundational` against the proposed posture, then drives the implementer through the planner's phased execution to produce the actual source files, migrations, CI config, and module shells. This is the only Skill (besides `/hstack:greenfield-init` which composes it) that ends with executable code landing in the consuming repo as part of init. Examples:
|
|
5
|
+
|
|
6
|
+
<example>
|
|
7
|
+
Context: Phases 1–5 of greenfield-init are complete; all context artifacts and stack ADRs are at terminal status.
|
|
8
|
+
user: "/hstack:scaffold"
|
|
9
|
+
assistant: "Generating bootstrap change-spec at hstack/specs/changes/<YYYY-MM>-bootstrap/spec.md. in-scope enumerated from app-architecture Section 1 (module shells) + data-architecture Section 5 (migration files) + standard infra files (package.json, tsconfig, CI workflow). Running foundational-mode security-review and data-review against the proposed posture. Then planner phases → implementer phase-by-phase → verifier. At terminal state the repo is bootable; build and test commands exit 0."
|
|
10
|
+
<commentary>
|
|
11
|
+
Scaffold's distinct property: it scores against a proposed posture (no diff yet) using --mode foundational on security-reviewer and data-specialist. After the bootstrap ships, those reviewers go back to per-change diff-scoring mode.
|
|
12
|
+
</commentary>
|
|
13
|
+
</example>
|
|
14
|
+
|
|
15
|
+
<example>
|
|
16
|
+
Context: Scaffold was started two days ago; phase-3 (module shells) landed but phase-4 (CI workflow) hit a verifier failure.
|
|
17
|
+
user: "/hstack:scaffold"
|
|
18
|
+
assistant: "Resuming the bootstrap change-spec. plan.md shows phase-3 complete; phase-4 had verifier discrepancies. Re-running /hstack:verify on phase-4 outputs to identify what failed; then either re-implementing phase-4 (if the implementer's output was incorrect) or revising the plan (if the expectation was wrong)."
|
|
19
|
+
<commentary>
|
|
20
|
+
Scaffold inherits the standard per-change idempotency contract because bootstrap IS a change-spec. The planner and implementer's existing resume semantics apply unchanged.
|
|
21
|
+
</commentary>
|
|
22
|
+
</example>
|
|
23
|
+
tools:
|
|
24
|
+
- Read
|
|
25
|
+
- Write
|
|
26
|
+
- Edit
|
|
27
|
+
- Grep
|
|
28
|
+
- Glob
|
|
29
|
+
- Bash
|
|
30
|
+
- Task
|
|
31
|
+
- "{{TODO-SKILL: /hstack:change-new — scaffolds the bootstrap change-spec folder}}"
|
|
32
|
+
- "{{TODO-SKILL: /hstack:test-plan — produces test-plan.md for the bootstrap}}"
|
|
33
|
+
- "{{TODO-SKILL: /hstack:security-review — invoked in --mode foundational}}"
|
|
34
|
+
- "{{TODO-SKILL: /hstack:data-review — invoked in --mode foundational}}"
|
|
35
|
+
- "{{TODO-SKILL: /hstack:change-plan — invokes planner}}"
|
|
36
|
+
- "{{TODO-SKILL: /hstack:implement — invokes implementer phase-by-phase}}"
|
|
37
|
+
- "{{TODO-SKILL: /hstack:verify — invokes verifier after the last implement phase}}"
|
|
38
|
+
- "{{TODO-SKILL: /hstack:adversarial-review — runs in a fresh session for the bootstrap}}"
|
|
39
|
+
- "{{TODO-SKILL: /hstack:ship — final scorecard; bootstrap ships with a PR like any change}}"
|
|
40
|
+
- "{{TODO-SKILL: /hstack:finalize — post-merge cleanup}}"
|
|
41
|
+
- "{{TODO-SCRIPT: hstack/scripts/validate-spec.ts — frontmatter validator}}"
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Purpose
|
|
45
|
+
|
|
46
|
+
`hstack-scaffold` is the Phase 6 execution Skill of `/hstack:greenfield-init`. It bridges discovery to working code: the upstream phases (product-brief, data-architecture, app-architecture, stack ADRs, threat-model, hardening-checklist, infrastructure, incident-runbook) declare the design; this Skill executes it. The execution path is the **standard per-change workflow** applied to a one-off change-spec with `area: bootstrap` — there is no special-cased "bootstrap workflow"; the kernel's per-change discipline applies in full, with two adjustments: (a) `security-review` and `data-review` run in `--mode foundational` (score against proposed posture, not diff), and (b) the change-spec uses the `hstack/templates/bootstrap.md` variant.
|
|
47
|
+
|
|
48
|
+
## When to invoke
|
|
49
|
+
|
|
50
|
+
- Phase 6 of `/hstack:greenfield-init` (the orchestrator calls this Skill after Phase 5 terminates).
|
|
51
|
+
- Standalone is **not** supported in v1 — scaffold runs once per project lifetime and assumes the full upstream discovery layer is at terminal status. Standalone invocation halts with a directive to run `/hstack:greenfield-init` instead.
|
|
52
|
+
|
|
53
|
+
## Inputs
|
|
54
|
+
|
|
55
|
+
- No positional arguments. The Skill reads upstream artifacts and the bootstrap-change-spec scaffolding from disk.
|
|
56
|
+
|
|
57
|
+
## Preconditions
|
|
58
|
+
|
|
59
|
+
- All of the following at `status: current`:
|
|
60
|
+
- `hstack/context/product/product-brief.md`
|
|
61
|
+
- `hstack/context/data-architecture.md`
|
|
62
|
+
- `hstack/context/app-architecture.md`
|
|
63
|
+
- `hstack/context/threat-model.md`, `hardening-checklist.md`, `infrastructure.md`, `incident-runbook.md`
|
|
64
|
+
- `hstack/context/tech-stack.md`, `ci-cd.md`
|
|
65
|
+
- Stack ADRs from Phase 4 at `status: accepted`.
|
|
66
|
+
- `hstack/templates/bootstrap.md` present.
|
|
67
|
+
- The consuming repo has no source code beyond `hstack/` and standard hidden files. If non-empty, halt — scaffold is a greenfield-only operation.
|
|
68
|
+
|
|
69
|
+
## Orchestration steps
|
|
70
|
+
|
|
71
|
+
1. **Generate the bootstrap change-spec.** Invoke `/hstack:change-new` with `area: bootstrap` and a derived id (`<YYYY-MM>-bootstrap`). The change-spec folder is scaffolded with `spec.md` pre-populated from `hstack/templates/bootstrap.md`. The Skill then performs mechanical writes to populate:
|
|
72
|
+
- `in-scope`: enumerated from app-architecture Module Map (one entry per module directory) + data-architecture Migration Sketches (one entry per `m_NNNN_*.sql`) + standard infra files (`package.json`, `tsconfig.json`, build config, CI workflow path, etc.). The enumeration is explicit; `["."]` is not permitted.
|
|
73
|
+
- `related-adrs`: the full list of Phase 4 stack ADRs.
|
|
74
|
+
- `threat-model-delta: true`.
|
|
75
|
+
The change-spec lands at `status: draft` after this step; `spec-author` walks it to `ready-to-plan` via a confirmation interview (the engineer reviews the enumerated `in-scope` and confirms or revises).
|
|
76
|
+
|
|
77
|
+
2. **Test plan.** Invoke `/hstack:test-plan` for the bootstrap. The test-strategist produces `test-plan.md` covering build / lint / typecheck / migration / RLS-enforcement smoke tests. Bootstrap test plans bias toward operational-correctness assertions (build exits 0, migrations apply cleanly, RLS denies cross-tenant access) rather than feature behavior.
|
|
78
|
+
|
|
79
|
+
3. **Foundational-mode security-review.** Invoke `/hstack:security-review` with the security-reviewer in `--mode foundational`. The reviewer scores against the proposed posture (threat-model + hardening-checklist + the stack ADRs) rather than against a diff. Output: `security-review.md` at `status: passed` or `concerns-noted` per the standard contract.
|
|
80
|
+
|
|
81
|
+
4. **Foundational-mode data-review.** Invoke `/hstack:data-review` with the data-specialist in `--mode foundational`. The reviewer scores the migration sketches from data-architecture Section 5 against RLS coverage rules (DR-02) and tenant-isolation rules (DR-03), scoring proposed-DDL rather than live schema. Output: `data-review.md` at `status: passed` or `concerns-noted`.
|
|
82
|
+
|
|
83
|
+
5. **Plan.** Invoke `/hstack:change-plan`. The planner produces `plan.md` with atomic phases. A typical bootstrap plan sequence:
|
|
84
|
+
- Phase 1: install dependencies (`npm install` / `pnpm install` / equivalent).
|
|
85
|
+
- Phase 2: initialize framework scaffold (e.g., Next.js boilerplate, tsconfig, eslint config).
|
|
86
|
+
- Phase 3: land migration files in `supabase/migrations/` per data-architecture Section 5.
|
|
87
|
+
- Phase 4: scaffold module shells per app-architecture Section 1 (one directory per module with index.ts plus any per-module config).
|
|
88
|
+
- Phase 5: wire CI workflow per `ci-cd.md`.
|
|
89
|
+
- Phase 6: smoke tests (build, lint, typecheck, run RLS-denial test).
|
|
90
|
+
Each phase declares its verifier expectations explicitly.
|
|
91
|
+
|
|
92
|
+
6. **Implement.** Invoke `/hstack:implement <bootstrap-id> <phase-id>` once per plan phase. Each invocation runs the implementer scope-locked to the `in-scope` enumeration. The implementer creates files (no edits — bootstrap is greenfield) and auto-commits at phase completion.
|
|
93
|
+
|
|
94
|
+
7. **Verify.** Invoke `/hstack:verify` after the last implement phase. The verifier runs the canonical commands from `ci-cd.md` and compares against per-phase Verifier Expectations.
|
|
95
|
+
|
|
96
|
+
8. **Adversarial review.** Direct the engineer to open a fresh Claude Code session and run `/hstack:adversarial-review`. Bootstrap inherits the standard fresh-session contract (kernel rule).
|
|
97
|
+
|
|
98
|
+
9. **Ship + finalize.** After adversarial review reaches `findings-resolved`, `/hstack:ship` produces the PR description. The engineer opens the PR, gets it merged, then runs `/hstack:finalize` to advance the bootstrap change-spec from `ready-to-ship` to `shipped` (no tech-debt resolution applies for bootstrap). `hstack/config.yaml`'s `init-status` flips to `complete` in the same finalize commit.
|
|
99
|
+
|
|
100
|
+
## Outputs
|
|
101
|
+
|
|
102
|
+
- A complete bootstrap change-spec folder at `hstack/specs/changes/<YYYY-MM>-bootstrap/` with `spec.md`, `test-plan.md`, `security-review.md`, `data-review.md`, `plan.md`, `verification.md`, `adversarial-review.md`, `pr-body.md`.
|
|
103
|
+
- The consuming repo's actual source files, migrations, CI workflow, build config, and per-module shells.
|
|
104
|
+
- `hstack/config.yaml` at `init-status: complete`.
|
|
105
|
+
|
|
106
|
+
## Auto-commit triggers
|
|
107
|
+
|
|
108
|
+
- Bootstrap change-spec advances through standard status transitions (`draft → ready-to-plan → ready-for-implementation → ready-for-review → ready-to-ship → shipped`); each transition auto-commits per the kernel.
|
|
109
|
+
- Each plan phase auto-commits when implementer completes it.
|
|
110
|
+
- `hstack/config.yaml` flips to `init-status: complete` in the finalize commit alongside the change-spec's advance to `shipped`.
|
|
111
|
+
|
|
112
|
+
## Idempotency contract
|
|
113
|
+
|
|
114
|
+
Scaffold inherits the standard per-change idempotency contract because bootstrap IS a change-spec:
|
|
115
|
+
|
|
116
|
+
- Re-running `/hstack:scaffold` reads the bootstrap change-spec's status and resumes at the next non-terminal artifact.
|
|
117
|
+
- Plan phases that have committed are skipped; only the first incomplete phase runs.
|
|
118
|
+
- A failed verifier produces `verification.md` at `status: failed-with-discrepancies`; re-running `/hstack:scaffold` does NOT silently retry — it surfaces the discrepancies and waits for the engineer to either re-implement the failing phase or revise the plan.
|
|
119
|
+
|
|
120
|
+
## Stop conditions
|
|
121
|
+
|
|
122
|
+
- Any upstream artifact at non-terminal status.
|
|
123
|
+
- The consuming repo is non-empty at scaffold start.
|
|
124
|
+
- Foundational-mode security-review or data-review lands at `concerns-noted` with unresolved CONCERNS. The engineer either resolves the concerns (revises threat-model / hardening / migration sketches) or accepts them via the standard concerns-acknowledgement path.
|
|
125
|
+
- Implementer halts mid-phase (file already exists outside in-scope, verifier expectation unsatisfiable, etc.). Standard implementer halt semantics apply.
|
|
126
|
+
- The engineer signals end-of-session — the standard per-change idempotency picks up on resume.
|
|
127
|
+
|
|
128
|
+
## Failure modes
|
|
129
|
+
|
|
130
|
+
- **Foundational-mode reviewer halts.** Foundational mode is honor-system in v1 — the reviewer is asked to score a proposed posture, not a diff. If the reviewer cannot honestly score (e.g., the threat-model is too thin), the reviewer halts with `HSTACK-HALT: reason=upstream-non-terminal` and routes the engineer back to `/hstack:configure threat-model`.
|
|
131
|
+
- **Implementer scope-lock fires on a path NOT in the enumerated in-scope.** This is a scaffold-spec gap, not an implementer bug. The Skill halts; the engineer revises `in-scope` (mechanical edit by the engineer per the kernel's scope-amendment path) and re-runs `/hstack:implement` for the affected phase.
|
|
132
|
+
- **CI runs from `ci-cd.md` haven't been authored yet for fresh projects.** The bootstrap change-spec's test-plan must define the canonical commands; otherwise verifier has nothing to run. The Skill checks this at preconditions.
|
|
133
|
+
|
|
134
|
+
## Anti-patterns
|
|
135
|
+
|
|
136
|
+
- Never run scaffold against a non-empty repo. Scaffold is greenfield-only; mixing modes produces incoherent in-scope enumeration.
|
|
137
|
+
- Never set `in-scope: ["."]`. Explicit file enumeration is the contract; the implementer's scope-lock does meaningful work only against an explicit list.
|
|
138
|
+
- Never skip foundational-mode security-review / data-review to "save time." Those gates are the v1 substrate for getting hardening and RLS posture right from line zero.
|
|
139
|
+
- Never bypass adversarial-review for the bootstrap. Bootstrap inherits the fresh-session contract from the kernel; ship without it is forbidden.
|
|
140
|
+
- Never flip `init-status: complete` while the bootstrap change-spec is below `shipped`.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hstack-stack-decide
|
|
3
|
+
description: |
|
|
4
|
+
Use this skill when the engineer wants to decide stack choices and capture each as an ADR. The Skill is Phase 4 of `/hstack:greenfield-init`, the stack-decision step of `/hstack:brownfield-init` when stack ADRs are missing, or a standalone atom for mid-project layer swaps (replacing auth, switching the database, rotating the hosting provider). It invokes the `stack-architect` subagent for the technical-discovery interview, then routes each layer's decision through `/hstack:adr-new` (which invokes `spec-author`) with pre-populated Context / Decision / Alternatives. The Consequences challenge prompt fires fresh on every ADR regardless of pre-population. Examples:
|
|
5
|
+
|
|
6
|
+
<example>
|
|
7
|
+
Context: Phase 4 of greenfield-init opens after app-architecture is current. hstack/config.yaml's default-stack declaration is set.
|
|
8
|
+
user: "/hstack:stack-decide"
|
|
9
|
+
assistant: "Loading brief, data-architecture, app-architecture, default-stack declaration. Defaults cover framework / database / hosting / auth — I'll fast-path those to a single rollup ADR. Observability is undeclared in config; I'll deep-dive on that layer. Expected: 2 ADRs (rollup + observability) routed through spec-author."
|
|
10
|
+
<commentary>
|
|
11
|
+
Default-stack fast-path collapses 80% of the interview when defaults match. Only layers explicitly flagged for deep-dive or undeclared in config get the full constraint interview.
|
|
12
|
+
</commentary>
|
|
13
|
+
</example>
|
|
14
|
+
|
|
15
|
+
<example>
|
|
16
|
+
Context: Mid-project, the team decides to replace Supabase Auth with Clerk.
|
|
17
|
+
user: "/hstack:stack-decide --layer auth"
|
|
18
|
+
assistant: "Standalone mode. Loading the existing auth ADR, threat-model, hardening-checklist. Constraint interview first (engineering capacity, scale horizon, compliance posture), then surfacing 2–3 Clerk alternatives, then routing to spec-author for the new ADR with supersedes: [<predecessor>]. The predecessor's reciprocal superseded-by writes atomically with the new ADR."
|
|
19
|
+
<commentary>
|
|
20
|
+
Standalone mode runs against a single layer. The supersedes / superseded-by reciprocal pair is mandatory; spec-author handles both halves atomically per the kernel's reciprocal-pair atomicity rule.
|
|
21
|
+
</commentary>
|
|
22
|
+
</example>
|
|
23
|
+
tools:
|
|
24
|
+
- Read
|
|
25
|
+
- Write
|
|
26
|
+
- Edit
|
|
27
|
+
- Grep
|
|
28
|
+
- Glob
|
|
29
|
+
- Bash
|
|
30
|
+
- Task
|
|
31
|
+
- "{{TODO-SKILL: /hstack:adr-new — invoked via spec-author handoff for ADR authoring}}"
|
|
32
|
+
- "{{TODO-SKILL: /hstack:research — invoked for unfamiliar-territory deep-dives}}"
|
|
33
|
+
- "{{TODO-SCRIPT: hstack/scripts/validate-spec.ts — frontmatter validator}}"
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Purpose
|
|
37
|
+
|
|
38
|
+
`hstack-stack-decide` is the atom that produces stack ADRs via the `stack-architect` subagent. It does NOT write to `hstack/adr/` directly; the kernel rule reserves ADR authoring for `spec-author`. Stack-architect produces pre-populated Context / Decision / Alternatives content; spec-author runs the Nygard interview in confirm-or-revise mode with the Consequences challenge firing fresh.
|
|
39
|
+
|
|
40
|
+
## When to invoke
|
|
41
|
+
|
|
42
|
+
- Phase 4 of `/hstack:greenfield-init`.
|
|
43
|
+
- The stack-decision step of `/hstack:brownfield-init` when no stack ADRs exist.
|
|
44
|
+
- Standalone via `/hstack:stack-decide [--layer <name>]` for mid-project layer swaps.
|
|
45
|
+
|
|
46
|
+
## Inputs
|
|
47
|
+
|
|
48
|
+
- `--layer <name>` — optional, standalone mode. Runs against a single declared layer (`framework | database | auth | hosting | observability | <custom>`). In greenfield/brownfield mode, the Skill walks all declared layers.
|
|
49
|
+
|
|
50
|
+
## Preconditions
|
|
51
|
+
|
|
52
|
+
- `hstack/config.yaml` at `init-status: minimal-complete` or later, with the default-stack declaration present (set in greenfield-init Phase 0 or via `/hstack:configure default-stack`).
|
|
53
|
+
- `hstack/context/app-architecture.md` at `status: current` (greenfield/brownfield mode). In standalone mode, the atom may run without app-architecture only if the layer being swapped doesn't depend on architecture decisions (rare).
|
|
54
|
+
- `hstack/templates/adr.md` present.
|
|
55
|
+
- Existing ADRs read at session start to set the next sequential ADR id and detect supersession candidates.
|
|
56
|
+
|
|
57
|
+
## Orchestration steps
|
|
58
|
+
|
|
59
|
+
1. **Detect mode.** Greenfield/brownfield: walk all declared layers. Standalone: run against the named `--layer`.
|
|
60
|
+
2. **Invoke `stack-architect` subagent.** Via the Task tool with `subagent_type: stack-architect`. Pass mode, layer scope, the canonical session-start context.
|
|
61
|
+
3. **For each layer (greenfield/brownfield mode):**
|
|
62
|
+
- **Default check.** stack-architect reads `hstack/config.yaml`'s declared default for this layer.
|
|
63
|
+
- **Fast-path confirmation.** If the engineer accepts the default, the layer is added to a pending rollup ADR.
|
|
64
|
+
- **Deep-dive.** If the engineer chooses to deep-dive, stack-architect runs the constraint interview (scale, ops capacity, compliance, AI-native specifics), surfaces 2–3 candidate options with tradeoff axes, and lets the engineer choose.
|
|
65
|
+
- **ADR handoff.** stack-architect prepares the Context / Decision / Alternatives sections, then invokes `/hstack:adr-new` via the Task tool (which invokes `spec-author`). spec-author runs confirm-or-revise on the prepared content. The Consequences challenge prompt fires fresh per the kernel's Nygard challenge rule.
|
|
66
|
+
4. **Rollup ADR (greenfield/brownfield mode).** After per-layer ADRs land, the Skill produces one rollup ADR via `/hstack:adr-new` naming every defaulted layer with the constraint check that confirmed each.
|
|
67
|
+
5. **Standalone mode** runs the same constraint interview + spec-author handoff for the single `--layer`. The new ADR carries `supersedes: [<predecessor>]`; the predecessor gets the reciprocal `superseded-by` written atomically by spec-author.
|
|
68
|
+
6. **Config update (optional).** After ADRs land, the Skill asks the engineer whether any layer's choice diverged from the prior default in a way they want project-wide. If yes, the Skill proposes a `hstack/config.yaml` update via the proposed-diff preview + Y/n gate, then commits the config update as a mechanical operation.
|
|
69
|
+
|
|
70
|
+
## Outputs
|
|
71
|
+
|
|
72
|
+
- One rollup ADR plus N per-layer ADRs (greenfield/brownfield mode), or one new ADR with `supersedes` (standalone mode), all at `status: accepted`.
|
|
73
|
+
- Updated `hstack/config.yaml` default-stack declaration (optional, only if changed).
|
|
74
|
+
- `hstack/.session-state/<session-id>.yaml` (transient).
|
|
75
|
+
|
|
76
|
+
## Auto-commit triggers
|
|
77
|
+
|
|
78
|
+
- Each ADR commits via `/hstack:adr-new`'s standard pattern (single auto-commit per ADR).
|
|
79
|
+
- Standalone mode's supersedes / superseded-by reciprocal pair commits atomically in one git commit per the kernel.
|
|
80
|
+
- Config update (if any) commits as a separate mechanical operation.
|
|
81
|
+
|
|
82
|
+
## Idempotency contract
|
|
83
|
+
|
|
84
|
+
- If a layer's current ADR is at `accepted` and the engineer's constraints + default-stack haven't changed: skip the layer.
|
|
85
|
+
- If a deep-dive interview was started but no ADR landed (engineer parked mid-interview): resume the interview from session-state.
|
|
86
|
+
- Re-running standalone mode for a layer whose ADR is already at `accepted` and no supersession is requested: print summary, exit no-op.
|
|
87
|
+
|
|
88
|
+
## Stop conditions
|
|
89
|
+
|
|
90
|
+
- App-architecture at non-terminal status (greenfield/brownfield mode).
|
|
91
|
+
- A chosen option contradicts an upstream invariant (e.g., DB without RLS conflicts with `data-architecture.md`'s tenant-scoped posture). Halt with `HSTACK-HALT: reason=upstream-drift`.
|
|
92
|
+
- A research session is needed (unfamiliar territory) but the engineer has not authorized `/hstack:research`.
|
|
93
|
+
- Standalone mode supersedes an ADR at a non-accepted status.
|
|
94
|
+
- The Postgres assumption in `data-architecture.md` is being contradicted. Halt and surface.
|
|
95
|
+
|
|
96
|
+
## Failure modes
|
|
97
|
+
|
|
98
|
+
- **spec-author handoff fails partway** (e.g., Consequences challenge produces a finding the engineer doesn't accept). The pending ADR sits at `draft`; the engineer either revises or routes through `/hstack:configure adr-author <id>` per spec-author's recovery path.
|
|
99
|
+
- **Research subagent unavailable when needed.** Persist constraint interview state; resume later.
|
|
100
|
+
|
|
101
|
+
## Anti-patterns
|
|
102
|
+
|
|
103
|
+
- Never write to `hstack/adr/` from this Skill directly. ADR authoring is `spec-author`'s exclusive ownership per kernel rule.
|
|
104
|
+
- Never let pre-population skip the Consequences challenge prompt. Pre-population covers Context / Decision / Alternatives; Consequences fires fresh.
|
|
105
|
+
- Never propose stack options before constraints are concrete.
|
|
106
|
+
- Never bypass the upstream check (app-architecture must be `current` in greenfield/brownfield mode).
|
|
107
|
+
- Never silently honor a non-Postgres DB choice when `data-architecture.md`'s `assumes-database: postgres` says otherwise. Halt and surface.
|
|
108
|
+
- Never split the supersedes / superseded-by reciprocal pair across two commits in standalone mode.
|
package/template/CLAUDE.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
hstack-version: v0.
|
|
2
|
+
hstack-version: v0.5.0
|
|
3
3
|
authority: kernel
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -139,12 +139,13 @@ Naming rules: `id` is kebab-case and immutable once written; dates are ISO 8601;
|
|
|
139
139
|
|
|
140
140
|
**Change-spec carries an optional `revisits-change` array.** When a new change-spec is filed to fix a defect, regression, or missed adversarial-review finding from a prior shipped change, the engineer populates `revisits-change: [<predecessor-change-id>]` so post-merge defect correlation is computable (`/hstack:telemetry` § QO-6 when promoted from watch-list to dashboard). Default empty. The field is informational, not gating — no Skill refuses to advance because the array is empty or non-empty.
|
|
141
141
|
|
|
142
|
-
**Change-spec carries `internal-tooling` (Category A)
|
|
142
|
+
**Change-spec carries `internal-tooling` (Category A), `enables` (Category B), and `area: bootstrap` (Category C) as the three no-story carve-outs.** A change-spec with no driving user story must declare one of three categories before status advances past `draft` (SP-09):
|
|
143
143
|
|
|
144
144
|
- **Category A — `internal-tooling: true`.** Engineering-only code that never ships on a user path: CI tooling, dev scripts, repo automation, internal dashboards. No `enables` linkage exists because no downstream user-facing change is teed up.
|
|
145
145
|
- **Category B — `enables: [<downstream-change-spec-id>, ...]`.** Production code that ships, but user value is realized by a named downstream change-spec that consumes this one's output. Typical case: schema or plumbing landed ahead of the UI that surfaces it. The reciprocal field `enabled-by: []` on the downstream spec is written atomically with `enables`.
|
|
146
|
+
- **Category C — `area: bootstrap`.** The one-time greenfield scaffold change-spec. The code ships on user paths, but the explicit `enables` list would be degenerate (every future change-spec would be a target) and `internal-tooling: true` would be dishonest. The `area: bootstrap` value satisfies SP-09 as the third carve-out. Bootstrap is produced by `/hstack:scaffold` (Phase 6 of `/hstack:greenfield-init`) and runs at most once per project lifetime; the canonical template is `hstack/templates/bootstrap.md`.
|
|
146
147
|
|
|
147
|
-
The
|
|
148
|
+
The three flags are mutually exclusive (SP-13): a change is Category A, Category B, or Category C — never two. If none applies, `user-stories` must be non-empty. The audit query *"what's the user value of this change?"* follows the `enables` chain (Category B) until it hits a spec with `user-stories` non-empty, terminates at Category A with "none, it's internal", or terminates at Category C with "it bootstraps the project; all subsequent changes inherit from it." Forward references are permitted at authoring time — if `enables` names a not-yet-scaffolded id, `/hstack:change-new` reconciles the reciprocal `enabled-by` when the downstream spec is later scaffolded. Reciprocity (`change-spec.enables ↔ change-spec.enabled-by`) is enforced by SP-14 and lands in a single atomic commit, matching the kernel's other reciprocal-pair rules.
|
|
148
149
|
|
|
149
150
|
---
|
|
150
151
|
|
|
@@ -198,6 +199,8 @@ Subagents are expensive. Each fresh subagent invocation pays the cost of its sys
|
|
|
198
199
|
|
|
199
200
|
The kernel rule reading: *"spec-author is the only **subagent** permitted to write under `hstack/specs/`, `hstack/adr/`, and `hstack/tech-debt/`."* The Skill orchestrator running in the main Claude Code session is not a subagent. Skills are therefore permitted to perform mechanical frontmatter writes directly, without invoking a subagent. ADR-0001 documents the decision.
|
|
200
201
|
|
|
202
|
+
**Narrow carve-out for `app-architect`.** The `app-architect` subagent may scaffold `hstack/specs/<module>/spec.md` **stubs** (headers only, `status: draft`, body note pointing to `/hstack:module-spec`) at the terminal state of its own atom, as pre-allocation for downstream `spec-author` work. The carve-out is scoped narrowly: stubs are not authored content (no body prose, no filled sections), they land in one atomic commit alongside `app-architecture.md` advancing to `current`, and the engineer's first invocation of `/hstack:module-spec <module>` reverse-engineers the stub into authored content via the normal `spec-author` interview. Any other subagent attempting to write under `hstack/specs/` is rejected per the original rule.
|
|
203
|
+
|
|
201
204
|
**What counts as a mechanical operation.** Operations where no open-ended interview is required — values are determined by the Skill's preconditions, the engineer's invocation arguments, or a structured-elicitation loop with a fixed question set and bounded answer shape:
|
|
202
205
|
|
|
203
206
|
- **Status flips** — advancing an artifact's `status` field along the lifecycle. The engineer's invocation of the Skill (and any acknowledgement gate the Skill carries) is the confirmation.
|
|
@@ -216,6 +219,9 @@ The kernel rule reading: *"spec-author is the only **subagent** permitted to wri
|
|
|
216
219
|
- `/hstack:tech-debt-wontfix` — TD `open → wontfix`; `wontfix-reason` and `wontfix-accepted-alternative` writes; Resolution Log append.
|
|
217
220
|
- `/hstack:tech-debt-stale` — TD `open → stale-no-longer-reproducible`; `stale-verified-at` and `stale-verification-method` writes; Resolution Log append.
|
|
218
221
|
- `/hstack:tech-debt-new` — reciprocal `creates-tech-debt` write on the originating change-spec after `spec-author` finishes the TD authoring interview.
|
|
222
|
+
- `/hstack:app-architecture` — at terminal state, three-file atomic commit: `app-architecture.md` advances to `status: current`; one `hstack/specs/<module>/spec.md` stub per module from Section 1 (under the `app-architect` carve-out above); `hstack/config.yaml`'s `surfaces` enum updated to match Section 5. All three writes land in one git commit; the proposed-diff preview runs before commit per the standard mechanical-operations contract.
|
|
223
|
+
- `/hstack:stack-decide` — optional `hstack/config.yaml` default-stack update after per-layer ADRs land, when the engineer wants a layer's choice to become the project-wide default. Mechanical write, proposed-diff preview, single commit.
|
|
224
|
+
- `/hstack:scaffold` — generates the bootstrap change-spec's `in-scope` enumeration (from app-architecture Module Map + data-architecture Migration Sketches + standard infra files) and pre-populates `related-adrs` from Phase 4 ADRs. The change-spec lands at `status: draft`; `spec-author` walks the engineer through confirm-or-revise to reach `ready-to-plan`. After that, the standard per-change workflow Skills run unchanged.
|
|
219
225
|
|
|
220
226
|
**Discipline preserved.** Skills doing direct writes still honor:
|
|
221
227
|
|
|
@@ -297,11 +303,13 @@ Subagents and Skills in v1 must not falsely assert v2 guarantees. The `security-
|
|
|
297
303
|
|
|
298
304
|
The product context layer lives at `hstack/context/`:
|
|
299
305
|
|
|
306
|
+
- `product/product-brief.md` — the durable thinking artifact capturing the project's product reasoning. Produced by `product-discovery` via one of three techniques (Brainstorm, Forcing-Questions, Project-Brief). Upstream of `vision.md`, `mvp-scope.md`, `personas/`, `glossary.md` — those are refreshed from the brief by `product-manager` via auto-route.
|
|
300
307
|
- `vision.md` — what the product is, what it does, what it is not.
|
|
301
308
|
- `glossary.md` — terms with non-obvious meaning.
|
|
302
309
|
- `mvp-scope.md` — in MVP, in v2, deferred.
|
|
303
310
|
- `personas/` — one file per persona, or one row per persona in the configured store.
|
|
304
|
-
- `data-architecture.md` —
|
|
311
|
+
- `data-architecture.md` — five-section foundational design (Tenancy, Entities, RLS, RAG, Migration Sketches). Produced by `data-architect`. Carries `assumes-database: postgres` in frontmatter (or alternative with explicit rationale).
|
|
312
|
+
- `app-architecture.md` — five-section internal-architecture design (Module Map, Agent Orchestration, Deterministic-vs-LLM Split, State-Ownership, Surface Boundaries). Produced by `app-architect`. Stack-agnostic by design; does not name frameworks.
|
|
305
313
|
- `tech-stack.md` — canonical languages, frameworks, libraries.
|
|
306
314
|
- `ci-cd.md` — CI/CD setup of the consuming repo.
|
|
307
315
|
- `infrastructure.md` — operational truth: hosting, networking, secrets, environments, deploy pipeline, observability, cost, disaster recovery, blast-radius matrix, access control, compliance posture, third-party dependencies. Truth-gathering, not policy — `threat-model.md` and `hardening-checklist.md` carry the policy and score against this file.
|
|
@@ -311,7 +319,11 @@ The product context layer lives at `hstack/context/`:
|
|
|
311
319
|
|
|
312
320
|
Load-at-session-start rules by subagent:
|
|
313
321
|
|
|
314
|
-
- `product-
|
|
322
|
+
- `product-discovery`: kernel, the chosen technique script (`hstack/templates/discovery/<technique>.md`), `product-brief.md` if it exists (resume mode), and in extract mode any source documents the engineer points at.
|
|
323
|
+
- `product-manager`: vision, personas, mvp-scope, glossary. In auto-route from `product-discovery`: also the brief.
|
|
324
|
+
- `data-architect`: kernel, product-brief, vision, mvp-scope, personas, glossary, data-architecture if it exists. In extract mode: live schema via Supabase MCP and `supabase/migrations/`.
|
|
325
|
+
- `app-architect`: kernel, product-brief, data-architecture, vision, mvp-scope, personas, glossary, app-architecture if it exists. Explicitly NOT `tech-stack.md` — app-architecture is stack-agnostic by design. In extract mode: consuming-repo source tree.
|
|
326
|
+
- `stack-architect`: kernel, product-brief, data-architecture, app-architecture, `hstack/config.yaml`'s default-stack declaration, all existing ADRs, threat-model and hardening-checklist if they exist. In standalone mode (`--layer <name>`): additionally `infrastructure.md`.
|
|
315
327
|
- `spec-author`: glossary, tech-stack, the relevant module-spec.
|
|
316
328
|
- `test-strategist`: change-spec, module-spec, tech-stack, ci-cd, data-architecture (when surfaces includes db), existing test files within in-scope.
|
|
317
329
|
- `planner`: change-spec, test-plan, ui-brief, figma-handoff, data-review (when present).
|
|
@@ -362,7 +374,9 @@ When a Skill or subagent halts at any of the stop conditions above, it emits one
|
|
|
362
374
|
HSTACK-HALT: reason=<enum>
|
|
363
375
|
```
|
|
364
376
|
|
|
365
|
-
Where `<enum>` is one of: `scope-amendment | upstream-non-terminal | mcp-unreachable | forbidden-tool | test-immutability-protocol | missing-context | ambiguous-spec | environment-misconfig | branch-mismatch | other`.
|
|
377
|
+
Where `<enum>` is one of: `scope-amendment | upstream-non-terminal | mcp-unreachable | forbidden-tool | test-immutability-protocol | missing-context | ambiguous-spec | environment-misconfig | branch-mismatch | upstream-drift | other`.
|
|
378
|
+
|
|
379
|
+
The `upstream-drift` value is emitted by discovery atoms (`product-discovery`, `data-architect`, `app-architect`, `stack-architect`) when a section's drift challenge surfaces a contradiction with an upstream artifact (e.g., a data-architecture entity that has no trace to a persona in the product-brief, or an app-architecture flow whose state-ownership requires an entity the data-architecture doesn't have). Distinct from `upstream-non-terminal` (which means an upstream artifact is still at `draft`) and from `scope-amendment` (which means an in-scope file is missing). Drift is bidirectional: a downstream atom finding an upstream gap reroutes through `/hstack:configure <upstream-atom>`, the upstream refreshes, the downstream resumes.
|
|
366
380
|
|
|
367
381
|
The sentinel is a single line, costs zero LLM tokens to emit, and makes post-hoc halt-frequency analysis cheap (see `/hstack:telemetry` § WS-6). The sentinel is appended to the auto-commit body when a halt coincides with a status-flip commit; otherwise it appears in the conversation alone (the telemetry parser reads both transcript text and commit bodies). Halting still includes the prose explanation of the situation — the sentinel does not replace the human-readable reason, it complements it.
|
|
368
382
|
|
|
@@ -405,7 +419,9 @@ hstack ships a closed-loop system for detecting when the kernel itself — this
|
|
|
405
419
|
|
|
406
420
|
- **The analyst never writes ADRs, change-specs, or edits existing findings** (one carve-out: it may set `status: superseded` on a prior finding when restating it more cleanly). Promotion is engineer-initiated and routes through the established authoring Skills. Auto-creation of ADRs is forbidden — the kernel's "AI writes, humans confirm" contract applies most forcefully at the kernel-modification layer, where the cost of a bad ADR cascades through every subsequent change.
|
|
407
421
|
|
|
408
|
-
|
|
422
|
+
- **Engineer-triggered flags feed the loop with in-the-moment friction signal.** `/hstack:flag [hint]` is a one-shot Skill that drops a tiny frontmatter-only pin to `hstack/kernel-fit/flags/pending/` carrying session-id, transcript path, branch, HEAD, and timestamp. No interview, no confirmation, no commit, sub-second wall-clock. The next `/hstack:kernel-fit-scan` reads each pin, opens the referenced Claude Code session transcript, classifies the friction (`friction | missing-guardrail | kernel-vs-practice-mismatch | not-actionable | transcript-truncated`), then folds the signal into an existing finding or emits a new one with `detected-via: flag`. The pin carries no engineer interpretation of the friction — the analyst forms its classification from the transcript window, preserving the no-contamination contract. Pins are gitignored in the consuming repo (derivative signal, mirroring `.telemetry/` sidecars); the audit trail lives at the finding layer once the analyst processes them. Phase-1 of ADR-0005 ships the Skill and pin template; phase-2 ships the analyst processing extension — until phase-2 lands, pins accumulate harmlessly on disk. See ADR-0005 for the rationale and the trade-offs.
|
|
423
|
+
|
|
424
|
+
The loop is the smallest expression of the kernel reasoning about itself without auto-modifying itself. v1 honesty: the analyst's output is an LLM-strategized judgment, not measured truth; the counter-explanation challenge is the false-positive mitigation. Same framing rule as `test-strategist` and `security-reviewer`. See ADR-0004 for the detector-side rationale, ADR-0005 for the engineer-trigger side; see `template/templates/kernel-fit-finding.md` and `template/templates/kernel-fit-flag.md` for the artifact schemas.
|
|
409
425
|
|
|
410
426
|
---
|
|
411
427
|
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: app-architecture
|
|
3
|
+
type: app-architecture
|
|
4
|
+
status: draft # draft | current | needs-refresh | archived
|
|
5
|
+
owner: <git-handle>
|
|
6
|
+
derived-from: [product-brief, data-architecture]
|
|
7
|
+
downstream: [threat-model, hardening-checklist, tech-stack, module-spec/*]
|
|
8
|
+
created: <YYYY-MM-DD>
|
|
9
|
+
updated: <YYYY-MM-DD>
|
|
10
|
+
schema-version: 1
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. Module Map
|
|
14
|
+
|
|
15
|
+
_The set of modules and what each owns. Each module must trace to either a persona-named action in `product-brief.md` or to a logical clustering of entities from `data-architecture.md`. Orphan modules (no trace) halt the section with the drift challenge._
|
|
16
|
+
|
|
17
|
+
**Modules**
|
|
18
|
+
|
|
19
|
+
| Module | Owns | Traces to |
|
|
20
|
+
| --- | --- | --- |
|
|
21
|
+
| <module-name> | <one-line statement of what this module owns> | <persona-action OR entity-cluster> |
|
|
22
|
+
|
|
23
|
+
**Drift challenge answered**
|
|
24
|
+
|
|
25
|
+
_"Does any module here own state a persona never interacts with, OR does any persona's journey traverse modules in a way the boundaries don't support?"_
|
|
26
|
+
|
|
27
|
+
## 2. Agent Orchestration Model
|
|
28
|
+
|
|
29
|
+
_How LLM calls compose. Which modules call the LLM, what each call returns, how downstream modules consume the output. Tool boundaries. Where prompts live. For an AI-native SaaS, this is the meaty section — implicit "the LLM handles it" answers are rejected; named call sites and downstream consumers are required._
|
|
30
|
+
|
|
31
|
+
**LLM call sites**
|
|
32
|
+
|
|
33
|
+
| Call site (module.fn) | Trigger | Model | Returns | Downstream consumer |
|
|
34
|
+
| --- | --- | --- | --- | --- |
|
|
35
|
+
| <module>.<function> | <what triggers this call> | <model identifier> | <structured-output schema or one-line description> | <module that consumes> |
|
|
36
|
+
|
|
37
|
+
**Tool boundaries**
|
|
38
|
+
|
|
39
|
+
_Which tools each call site can invoke, and which are explicitly out-of-bounds. Names the kill switches for LLM-driven actions._
|
|
40
|
+
|
|
41
|
+
**Drift challenge answered**
|
|
42
|
+
|
|
43
|
+
_"Does any LLM call site bypass the tool boundaries declared, or have an unnamed retry / fallback path?"_
|
|
44
|
+
|
|
45
|
+
## 3. Deterministic-vs-LLM Split
|
|
46
|
+
|
|
47
|
+
_Per user-facing flow, the per-step decision: code or prompt, with a rationale that ties to a measurable property (determinism, cost, latency, capability). Implicit "AI handles it end-to-end" answers are rejected; per-step declaration is mandatory._
|
|
48
|
+
|
|
49
|
+
**Flow tables**
|
|
50
|
+
|
|
51
|
+
For each flow named in the brief's persona vignettes:
|
|
52
|
+
|
|
53
|
+
### Flow: <flow-name>
|
|
54
|
+
|
|
55
|
+
_From <persona>'s Tuesday-morning workflow._
|
|
56
|
+
|
|
57
|
+
| Step | Mechanism | Rationale (ties to measurable property) |
|
|
58
|
+
| --- | --- | --- |
|
|
59
|
+
| 1. <step description> | deterministic \| llm | <one sentence — property: determinism \| cost \| latency \| capability> |
|
|
60
|
+
| 2. ... | ... | ... |
|
|
61
|
+
|
|
62
|
+
**Drift challenge answered**
|
|
63
|
+
|
|
64
|
+
_"Does any flow have a step where the mechanism is undeclared, or a rationale that doesn't tie to a measurable property?"_
|
|
65
|
+
|
|
66
|
+
## 4. State-Ownership Map
|
|
67
|
+
|
|
68
|
+
_Where conversation state lives, workspace state lives, 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._
|
|
69
|
+
|
|
70
|
+
**State classes**
|
|
71
|
+
|
|
72
|
+
| State class | Owning module | Persistence layer | Lifetime |
|
|
73
|
+
| --- | --- | --- | --- |
|
|
74
|
+
| <e.g., conversation history> | <module from §1> | <entity from data-architecture OR "ephemeral"> | <durable \| session \| request> |
|
|
75
|
+
|
|
76
|
+
**Drift challenge answered**
|
|
77
|
+
|
|
78
|
+
_"Does any state class lack an owning module from Section 1?"_
|
|
79
|
+
|
|
80
|
+
## 5. Surface Boundaries
|
|
81
|
+
|
|
82
|
+
_What the project's `surfaces` enum contains. The canonical floor is `[ui, api, agent, db, auth, infra]`; projects may add (e.g., `payments`) or omit (e.g., no `auth` if relying on a host system). Each declared surface is mapped to at least one module from Section 1._
|
|
83
|
+
|
|
84
|
+
**Surface declaration**
|
|
85
|
+
|
|
86
|
+
| Surface | In v1? | Modules carrying this surface | Deferred to |
|
|
87
|
+
| --- | --- | --- | --- |
|
|
88
|
+
| ui | yes/no | <module names> | <v2 \| later \| N/A> |
|
|
89
|
+
| api | ... | ... | ... |
|
|
90
|
+
| agent | ... | ... | ... |
|
|
91
|
+
| db | ... | ... | ... |
|
|
92
|
+
| auth | ... | ... | ... |
|
|
93
|
+
| infra | ... | ... | ... |
|
|
94
|
+
| <custom> | ... | ... | ... |
|
|
95
|
+
|
|
96
|
+
**Drift challenge answered**
|
|
97
|
+
|
|
98
|
+
_"Does any surface in the enum have no module from Section 1 mapped to it?"_
|
|
99
|
+
|
|
100
|
+
## Coherence check (end-of-atom)
|
|
101
|
+
|
|
102
|
+
_When the atom reaches terminal state, the agent re-runs all five drift challenges to ensure section-targeted edits did not silently break other sections. The coherence check is fatal — any unanswered challenge halts the commit._
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: <YYYY-MM-bootstrap> # canonical bootstrap change-id; one per project
|
|
3
|
+
type: change-spec # bootstrap is a change-spec variant, not a new type
|
|
4
|
+
status: draft
|
|
5
|
+
owner: <git-handle>
|
|
6
|
+
area: bootstrap # the no-story carve-out for the bootstrap variant; SP-09 satisfied via this
|
|
7
|
+
surfaces: [infra] # bootstrap is infra-only; UI / agent / api work begins post-bootstrap
|
|
8
|
+
user-stories: [] # bootstrap has no user-story; the area: bootstrap field satisfies SP-09 as a third carve-out alongside internal-tooling and enables
|
|
9
|
+
related-spec: bootstrap # equals area
|
|
10
|
+
related-adrs: [] # populated with every stack ADR from Phase 4
|
|
11
|
+
creates-tech-debt: []
|
|
12
|
+
resolves-tech-debt: []
|
|
13
|
+
parent-change: null
|
|
14
|
+
children: []
|
|
15
|
+
revisits-change: []
|
|
16
|
+
internal-tooling: false # bootstrap is NOT internal-tooling — the code ships on the user path
|
|
17
|
+
enables: [] # bootstrap implicitly enables every downstream change-spec; the explicit list would be degenerate, so we leave it empty and rely on area: bootstrap as the SP-09 carve-out
|
|
18
|
+
enabled-by: []
|
|
19
|
+
trivial: false
|
|
20
|
+
in-scope: [] # explicit file enumeration — NOT ["."]
|
|
21
|
+
out-of-scope: [] # required, may be empty
|
|
22
|
+
threat-model-delta: true # bootstrap always touches threat-model (auth posture, RLS defaults, secret handling)
|
|
23
|
+
created: <YYYY-MM-DD>
|
|
24
|
+
updated: <YYYY-MM-DD>
|
|
25
|
+
schema-version: 1
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Problem
|
|
29
|
+
|
|
30
|
+
_What this change is doing: standing up the repo from empty. One paragraph._
|
|
31
|
+
|
|
32
|
+
This change scaffolds the project from an empty repository to a bootable, tested, and ready-to-ship state. It is the only change in the project's history with `area: bootstrap`; subsequent changes target real modules.
|
|
33
|
+
|
|
34
|
+
## Current Behavior
|
|
35
|
+
|
|
36
|
+
_N/A for bootstrap — there is no current state. Repository is empty (or contains only `hstack/` after greenfield-init Phases 1–5)._
|
|
37
|
+
|
|
38
|
+
- N/A.
|
|
39
|
+
|
|
40
|
+
## Target Behavior
|
|
41
|
+
|
|
42
|
+
_What shipping looks like, observably. Bootstrap's targets are bootability and gate-passing, not feature behavior._
|
|
43
|
+
|
|
44
|
+
- The repository builds: `<configured-build-command>` exits 0.
|
|
45
|
+
- The repository's test suite runs and passes: `<configured-test-command>` exits 0.
|
|
46
|
+
- Every module declared in `app-architecture.md` Section 1 has a corresponding source directory with the minimal shell required for the module-spec to be reverse-engineered post-merge.
|
|
47
|
+
- The initial migration sequence sketched in `data-architecture.md` Section 5 lands as actual `.sql` files under `supabase/migrations/` (or the chosen DB's migration directory) in the order: schema → RLS → pgvector → seeds.
|
|
48
|
+
- CI runs the canonical commands from `ci-cd.md` and the gates pass.
|
|
49
|
+
|
|
50
|
+
## Acceptance Criteria
|
|
51
|
+
|
|
52
|
+
_GIVEN / WHEN / THEN. Bootstrap's acceptance is gate-based, not user-flow-based._
|
|
53
|
+
|
|
54
|
+
GIVEN the repository at HEAD
|
|
55
|
+
WHEN the engineer runs `<configured-build-command>` and `<configured-test-command>`
|
|
56
|
+
THEN both exit 0 and no test is skipped.
|
|
57
|
+
|
|
58
|
+
GIVEN the database after `m_0002_rls_policies.sql` has run
|
|
59
|
+
WHEN any tenant-scoped table is queried without setting `app.<tenant-column>`
|
|
60
|
+
THEN the query returns zero rows (RLS enforced from line zero).
|
|
61
|
+
|
|
62
|
+
GIVEN the repository at HEAD
|
|
63
|
+
WHEN a downstream engineer runs `/hstack:module-spec <module>` for any module from `app-architecture.md` Section 1
|
|
64
|
+
THEN the Skill finds a target directory to reverse-engineer against and does not halt on missing source.
|
|
65
|
+
|
|
66
|
+
## Invariants
|
|
67
|
+
|
|
68
|
+
_Three or more bullets per SP-04. Bootstrap's invariants name the foundational guarantees that must survive every future change._
|
|
69
|
+
|
|
70
|
+
- **RLS-enforced from line zero.** Every tenant-scoped table created by `m_0001_initial_schema.sql` has its RLS policy applied in `m_0002_rls_policies.sql` BEFORE any data lands. The migration ordering is a contract, not a convenience.
|
|
71
|
+
- **Module boundaries match the declaration.** Every module in `app-architecture.md` Section 1 has a corresponding source directory; no module is silently dropped or renamed during scaffold. Future changes cannot add modules without updating the declaration first.
|
|
72
|
+
- **Stack ADRs are authoritative.** Every choice in this scaffold (framework, DB client, auth integration, hosting deploy file, observability wiring) traces to an ADR from Phase 4. No silent stack divergence.
|
|
73
|
+
|
|
74
|
+
## Scope Boundaries
|
|
75
|
+
|
|
76
|
+
_Pointer to `in-scope` and `out-of-scope` frontmatter arrays. Bootstrap's `in-scope` is an explicit enumeration of every file being created. Wildcards are permitted but the engineer must list every top-level destination explicitly so the implementer's scope-lock does meaningful work._
|
|
77
|
+
|
|
78
|
+
The `in-scope` enumeration is the contract: the implementer creates exactly the listed files and no others. Files appearing in the final scaffold but not in `in-scope` indicate a scaffold-spec gap and require a scope amendment.
|
|
79
|
+
|
|
80
|
+
## Surfaces
|
|
81
|
+
|
|
82
|
+
_Pointer to `surfaces` frontmatter. Bootstrap is `[infra]` only — UI / agent / api / db / auth surface work begins with the first feature change-spec after bootstrap merges._
|
|
83
|
+
|
|
84
|
+
- **infra**: build configuration, dependency manifest, CI workflow, DB migration tooling setup, deployment configuration, observability wiring.
|
|
85
|
+
|
|
86
|
+
UI work begins post-bootstrap; the scaffold ships only the minimum shell (layout, theme tokens) needed for the build to pass.
|
|
87
|
+
|
|
88
|
+
## Linked Stories and Personas
|
|
89
|
+
|
|
90
|
+
_N/A — bootstrap has `user-stories: []` and satisfies SP-09 via `area: bootstrap`. The bootstrap variant is a third carve-out alongside `internal-tooling: true` (Category A) and `enables: [...]` (Category B); `area: bootstrap` is mutually exclusive with both. See kernel addendum for the rule._
|
|
91
|
+
|
|
92
|
+
## Related ADRs and Tech-Debt
|
|
93
|
+
|
|
94
|
+
_Every stack ADR from Phase 4 (greenfield-init) goes here as a pointer with one-sentence justification. Examples:_
|
|
95
|
+
|
|
96
|
+
- ADR-NNNN — Stack defaults adopted: <list>. Adopted as the project foundation.
|
|
97
|
+
- ADR-NNNN+1 — Observability stack: PostHog + Sentry. Configured in this scaffold.
|
|
98
|
+
|
|
99
|
+
## Resolves Tech-Debt
|
|
100
|
+
|
|
101
|
+
_N/A — bootstrap creates the project; it does not resolve prior tech-debt._
|
|
102
|
+
|
|
103
|
+
## Open Questions
|
|
104
|
+
|
|
105
|
+
_Populated when status moves from draft to ready-to-plan. Bootstrap-specific examples: "Do we lint the migration SQL via sqlfluff or via Supabase's built-in lint?" "Do we vendor a UI component library in the initial commit or wait for the first UI feature?"_
|