hstack 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +73 -163
  3. package/VERSION +1 -1
  4. package/dist/commands/doctor.js +18 -8
  5. package/dist/commands/doctor.js.map +1 -1
  6. package/dist/commands/init.js +7 -3
  7. package/dist/commands/init.js.map +1 -1
  8. package/dist/commands/update.js +9 -2
  9. package/dist/commands/update.js.map +1 -1
  10. package/dist/lib/descriptions.js +10 -17
  11. package/dist/lib/descriptions.js.map +1 -1
  12. package/dist/lib/wire.js +166 -138
  13. package/dist/lib/wire.js.map +1 -1
  14. package/dist/manifest.js +41 -29
  15. package/dist/manifest.js.map +1 -1
  16. package/package.json +3 -4
  17. package/template/.claude/agents/adversarial-reviewer.md +42 -50
  18. package/template/.claude/agents/app-architect.md +44 -96
  19. package/template/.claude/agents/data-architect.md +46 -89
  20. package/template/.claude/agents/test-strategist.md +39 -68
  21. package/template/.claude/skills/hstack-adr-new/SKILL.md +23 -73
  22. package/template/.claude/skills/hstack-adversarial-review/SKILL.md +46 -152
  23. package/template/.claude/skills/hstack-adversarial-review/references/finding-categories.md +80 -103
  24. package/template/.claude/skills/hstack-app-architecture/SKILL.md +43 -68
  25. package/template/.claude/skills/hstack-commit/SKILL.md +27 -68
  26. package/template/.claude/skills/hstack-data-architecture/SKILL.md +34 -56
  27. package/template/.claude/skills/hstack-promote/SKILL.md +55 -0
  28. package/template/.claude/skills/hstack-story/SKILL.md +58 -0
  29. package/template/.claude/skills/hstack-test-audit/SKILL.md +64 -0
  30. package/template/.claude/skills/hstack-wrap/SKILL.md +48 -0
  31. package/template/.claude/skills/hstack-wrap/references/pr-description.md +45 -0
  32. package/template/KERNEL.md +75 -318
  33. package/template/templates/adr.md +2 -18
  34. package/template/templates/app-architecture.md +38 -50
  35. package/template/templates/data-architecture.md +38 -89
  36. package/template/templates/infrastructure.md +54 -148
  37. package/template/templates/roadmap.md +6 -12
  38. package/template/templates/story.md +7 -13
  39. package/template/templates/tech-debt.md +2 -37
  40. package/template/templates/tech-stack.md +2 -12
  41. package/template/.claude/agents/data-specialist.md +0 -81
  42. package/template/.claude/agents/implementer.md +0 -97
  43. package/template/.claude/agents/kernel-fit-analyst.md +0 -129
  44. package/template/.claude/agents/planner.md +0 -75
  45. package/template/.claude/agents/product-discovery.md +0 -129
  46. package/template/.claude/agents/product-manager.md +0 -76
  47. package/template/.claude/agents/researcher.md +0 -87
  48. package/template/.claude/agents/security-reviewer.md +0 -88
  49. package/template/.claude/agents/spec-author.md +0 -89
  50. package/template/.claude/agents/stack-architect.md +0 -108
  51. package/template/.claude/agents/ui-ux-briefer.md +0 -75
  52. package/template/.claude/agents/verifier.md +0 -81
  53. package/template/.claude/skills/hstack-branch/SKILL.md +0 -76
  54. package/template/.claude/skills/hstack-brownfield-init/SKILL.md +0 -131
  55. package/template/.claude/skills/hstack-change-new/SKILL.md +0 -84
  56. package/template/.claude/skills/hstack-change-plan/SKILL.md +0 -108
  57. package/template/.claude/skills/hstack-configure/SKILL.md +0 -99
  58. package/template/.claude/skills/hstack-coord/SKILL.md +0 -95
  59. package/template/.claude/skills/hstack-data-review/SKILL.md +0 -93
  60. package/template/.claude/skills/hstack-finalize/SKILL.md +0 -140
  61. package/template/.claude/skills/hstack-flag/SKILL.md +0 -99
  62. package/template/.claude/skills/hstack-greenfield-init/SKILL.md +0 -148
  63. package/template/.claude/skills/hstack-help/SKILL.md +0 -153
  64. package/template/.claude/skills/hstack-implement/SKILL.md +0 -155
  65. package/template/.claude/skills/hstack-kernel-fit-promote/SKILL.md +0 -125
  66. package/template/.claude/skills/hstack-kernel-fit-scan/SKILL.md +0 -142
  67. package/template/.claude/skills/hstack-kernel-fit-scan/references/slack-setup.md +0 -42
  68. package/template/.claude/skills/hstack-kernel-fit-triage/SKILL.md +0 -121
  69. package/template/.claude/skills/hstack-module-spec/SKILL.md +0 -78
  70. package/template/.claude/skills/hstack-product-discovery/SKILL.md +0 -75
  71. package/template/.claude/skills/hstack-research/SKILL.md +0 -115
  72. package/template/.claude/skills/hstack-scaffold/SKILL.md +0 -113
  73. package/template/.claude/skills/hstack-security-review/SKILL.md +0 -95
  74. package/template/.claude/skills/hstack-ship/SKILL.md +0 -119
  75. package/template/.claude/skills/hstack-stack-decide/SKILL.md +0 -81
  76. package/template/.claude/skills/hstack-story-draft/SKILL.md +0 -92
  77. package/template/.claude/skills/hstack-tech-debt-new/SKILL.md +0 -95
  78. package/template/.claude/skills/hstack-tech-debt-resolve/SKILL.md +0 -123
  79. package/template/.claude/skills/hstack-tech-debt-stale/SKILL.md +0 -86
  80. package/template/.claude/skills/hstack-tech-debt-wontfix/SKILL.md +0 -77
  81. package/template/.claude/skills/hstack-telemetry/SKILL.md +0 -73
  82. package/template/.claude/skills/hstack-test-plan/SKILL.md +0 -159
  83. package/template/.claude/skills/hstack-ui-brief/SKILL.md +0 -81
  84. package/template/.claude/skills/hstack-verify/SKILL.md +0 -128
  85. package/template/scripts/compute-merge-readiness.mjs +0 -780
  86. package/template/scripts/coord/coord_scan.py +0 -681
  87. package/template/scripts/run-gates.sh +0 -388
  88. package/template/scripts/telemetry/__init__.py +0 -6
  89. package/template/scripts/telemetry/insights/__init__.py +0 -0
  90. package/template/scripts/telemetry/insights/contract_drift.py +0 -137
  91. package/template/scripts/telemetry/insights/kernel_fit.py +0 -438
  92. package/template/scripts/telemetry/insights/overengineering.py +0 -115
  93. package/template/scripts/telemetry/insights/quality_outcomes.py +0 -131
  94. package/template/scripts/telemetry/insights/token_economics.py +0 -302
  95. package/template/scripts/telemetry/insights/workflow_shape.py +0 -198
  96. package/template/scripts/telemetry/parsers/__init__.py +0 -0
  97. package/template/scripts/telemetry/parsers/bodies.py +0 -87
  98. package/template/scripts/telemetry/parsers/commits.py +0 -219
  99. package/template/scripts/telemetry/parsers/frontmatter.py +0 -322
  100. package/template/scripts/telemetry/parsers/sidecars.py +0 -61
  101. package/template/scripts/telemetry/parsers/transcripts.py +0 -294
  102. package/template/scripts/telemetry/render.py +0 -460
  103. package/template/scripts/telemetry/report.py +0 -150
  104. package/template/scripts/telemetry/run_kernel_fit.py +0 -95
  105. package/template/scripts/telemetry/session_id.py +0 -139
  106. package/template/scripts/validate-spec.mjs +0 -3303
  107. package/template/templates/adversarial-review.md +0 -54
  108. package/template/templates/bootstrap.md +0 -105
  109. package/template/templates/change-spec.md +0 -82
  110. package/template/templates/ci-cd.md +0 -41
  111. package/template/templates/coord-message.md +0 -56
  112. package/template/templates/data-review.md +0 -54
  113. package/template/templates/discovery/brainstorm.md +0 -69
  114. package/template/templates/discovery/forcing-questions.md +0 -76
  115. package/template/templates/discovery/project-brief.md +0 -53
  116. package/template/templates/figma-handoff.md +0 -38
  117. package/template/templates/glossary.md +0 -20
  118. package/template/templates/hardening-checklist.md +0 -73
  119. package/template/templates/incident-runbook.md +0 -57
  120. package/template/templates/kernel-fit-finding.md +0 -63
  121. package/template/templates/kernel-fit-flag.md +0 -52
  122. package/template/templates/module-spec.md +0 -49
  123. package/template/templates/persona.md +0 -38
  124. package/template/templates/plan.md +0 -53
  125. package/template/templates/product-brief.md +0 -56
  126. package/template/templates/security-review.md +0 -63
  127. package/template/templates/telemetry-sidecar.md +0 -227
  128. package/template/templates/test-plan.md +0 -119
  129. package/template/templates/threat-model.md +0 -54
  130. package/template/templates/ui-brief.md +0 -49
  131. package/template/templates/verification.md +0 -63
  132. package/template/templates/vision.md +0 -34
@@ -1,77 +1,76 @@
1
1
  ---
2
2
  id: app-architecture
3
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
4
  updated: <YYYY-MM-DD>
10
- schema-version: 1
11
5
  ---
12
6
 
13
7
  ## 1. Module Map
14
8
 
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._
9
+ _The modules, what each owns, and what reaches them. `Critical: yes` means the kernel's
10
+ mandatory-test rule applies to this module's paths._
16
11
 
17
- **Modules**
12
+ _The **Exposure** column is the exposure map. One line per entry point: `path` · kind (`page`,
13
+ `api`, `action`, `job`, `webhook`) · status (`live`, `routable`, `off` — kernel § Context docs).
14
+ A module owning no entry point of its own names the ones that reach it; a module no live entry
15
+ point reaches is `dormant`, which is derived, not a fourth status. Updated in the PR that changes
16
+ exposure, verified at `/promote`, and checkable by diffing these paths against the real routes._
18
17
 
19
- | Module | Owns | Traces to |
20
- | --- | --- | --- |
21
- | <module-name> | <one-line statement of what this module owns> | <persona-action OR entity-cluster> |
18
+ | Module | Owns | Critical | Traces to | Exposure — entry points |
19
+ | --- | --- | --- | --- | --- |
20
+ | <module> | <what it owns, one line> | yes \| no | <user action OR entity cluster> | `app/(app)/<x>/page.tsx` · page · **live**<br>`app/api/<x>/route.ts` · api · **live**<br>`jobs/<x>.ts` · job · **off** |
21
+ | <module> | ... | no | ... | _no entry point of its own — reached by `<module>` (live)_ |
22
+ | <module> | ... | no | ... | _dormant — no live entry point reaches it_ |
23
+
24
+ _This column grades the **product** severity of a finding, never its security severity. Every
25
+ routable entry point is covered by the kernel's security checklist whatever the status says._
22
26
 
23
27
  **Drift challenge answered**
24
28
 
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?"_
29
+ _"Does any module own something no user ever reaches, or does any user journey cross boundaries
30
+ this map does not support?"_
26
31
 
27
32
  ## 2. Agent Orchestration Model
28
33
 
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**
34
+ _How the LLM calls compose: which module calls, what comes back, who consumes it, where the prompts
35
+ live. Named call sites, not "the LLM handles it"._
32
36
 
33
37
  | Call site (module.fn) | Trigger | Model | Returns | Downstream consumer |
34
38
  | --- | --- | --- | --- | --- |
35
- | <module>.<function> | <what triggers this call> | <model identifier> | <structured-output schema or one-line description> | <module that consumes> |
39
+ | <module>.<function> | <what triggers it> | <model id> | <schema or one line> | <module> |
36
40
 
37
41
  **Tool boundaries**
38
42
 
39
- _Which tools each call site can invoke, and which are explicitly out-of-bounds. Names the kill switches for LLM-driven actions._
43
+ _Which tools each call site may invoke, which are out of bounds, and where the kill switch is._
40
44
 
41
45
  **Drift challenge answered**
42
46
 
43
- _"Does any LLM call site bypass the tool boundaries declared, or have an unnamed retry / fallback path?"_
47
+ _"Does any LLM call site bypass its declared tool boundaries, or have an unnamed retry or fallback
48
+ path?"_
44
49
 
45
50
  ## 3. Deterministic-vs-LLM Split
46
51
 
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
+ _Per flow, per step: code or prompt, and why. A flow that genuinely is one model call is one row
53
+ with its schema and its rationale — the rule is against the undeclared boundary, not against short
54
+ tables._
52
55
 
53
56
  ### Flow: <flow-name>
54
57
 
55
- _From <persona>'s Tuesday-morning workflow._
56
-
57
- | Step | Mechanism | Rationale (ties to measurable property) |
58
+ | Step | Mechanism | Rationale (names a property) |
58
59
  | --- | --- | --- |
59
- | 1. <step description> | deterministic \| llm | <one sentence — property: determinism \| cost \| latency \| capability> |
60
- | 2. ... | ... | ... |
60
+ | 1. <step> | deterministic \| llm | <one sentence — determinism \| cost \| latency \| capability> |
61
61
 
62
62
  **Drift challenge answered**
63
63
 
64
- _"Does any flow have a step where the mechanism is undeclared, or a rationale that doesn't tie to a measurable property?"_
64
+ _"Does any flow have a step whose mechanism is undeclared, or a rationale tied to no property?"_
65
65
 
66
66
  ## 4. State-Ownership Map
67
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**
68
+ _Where conversation state, workspace state and ephemeral state live. Each names its owning module
69
+ from Section 1 and its persistence layer from `data-architecture.md`._
71
70
 
72
71
  | State class | Owning module | Persistence layer | Lifetime |
73
72
  | --- | --- | --- | --- |
74
- | <e.g., conversation history> | <module from §1> | <entity from data-architecture OR "ephemeral"> | <durable \| session \| request> |
73
+ | <e.g. conversation history> | <module> | <entity OR "ephemeral"> | durable \| session \| request |
75
74
 
76
75
  **Drift challenge answered**
77
76
 
@@ -79,24 +78,13 @@ _"Does any state class lack an owning module from Section 1?"_
79
78
 
80
79
  ## 5. Surface Boundaries
81
80
 
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**
81
+ _Which surfaces this application has, and which module carries each. The usual set is `ui`, `api`,
82
+ `agent`, `db`, `auth`, `infra`; add or omit as the product requires._
85
83
 
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> | ... | ... | ... |
84
+ | Surface | Present? | Modules carrying it |
85
+ | --- | --- | --- |
86
+ | <surface> | yes \| no | <modules> |
95
87
 
96
88
  **Drift challenge answered**
97
89
 
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._
90
+ _"Does any surface have no module mapped to it?"_
@@ -1,127 +1,103 @@
1
1
  ---
2
2
  id: data-architecture
3
3
  type: data-architecture
4
- status: draft # draft | current | needs-refresh | archived
5
- owner: <git-handle>
6
- assumes-database: postgres # explicit so Phase 4 stack-decide can flag drift
4
+ assumes-database: postgres # explicit, so a database change surfaces as a contradiction
7
5
  schema-snapshot-date: <YYYY-MM-DD>
8
- rag-architecture-version: 1
9
- derived-from: [product-brief]
10
- downstream: [app-architecture, threat-model, hardening-checklist, module-spec/*]
11
- created: <YYYY-MM-DD>
12
6
  updated: <YYYY-MM-DD>
13
- schema-version: 1
14
7
  ---
15
8
 
16
9
  ## 1. Tenancy Model
17
10
 
18
- _The load-bearing question. The data-architect refuses to advance past this section until the tenant definition is concrete and ties to a persona in the brief._
11
+ _The load-bearing question. Nothing downstream stabilizes until this one is concrete._
19
12
 
20
13
  **A tenant is a ...**
21
14
 
22
- _One concrete noun from this product's own vocabulary, plus the rule for who is inside one and who is not. Common shapes, offered as examples rather than as a menu: the customer organization (one workspace per paying customer, users inside share visibility); a sub-team within that organization (multi-workspace per customer); the individual user (workspace-per-user). Products whose tenant is a project, a device, a contract, a site, a case or a season are ordinary and none of those three fit them — name yours._
15
+ _One concrete noun from this product's own vocabulary, plus the rule for who is inside one and who
16
+ is not. Common shapes, offered as examples rather than as a menu: the customer organization (users
17
+ inside share visibility); a sub-team within it; the individual user. Products whose tenant is a
18
+ project, a device, a contract, a site or a case are ordinary and none of those three fit them —
19
+ name yours._
23
20
 
24
21
  **Rationale**
25
22
 
26
- _One sentence tying the tenant to a persona in `product-brief.md`. Example: "The tenant is the customer organization, because Maya (Director of CS) shares visibility with her 6 reps and no v1 persona asks for sub-team isolation."_
23
+ _One sentence tying the tenant to a real user. Example: "The tenant is the customer organization,
24
+ because Maya shares visibility with her 6 reps and nobody has asked for sub-team isolation."_
27
25
 
28
26
  **Tenant identifier**
29
27
 
30
- _The column name and type used to scope every tenant-scoped table (`workspace_id uuid`, `org_id text`, etc.). All downstream RLS predicates reference this column._
28
+ _The column name and type scoping every tenant-scoped table (`workspace_id uuid`, `org_id text`).
29
+ Every RLS predicate below references this column._
31
30
 
32
31
  ## 2. Entity Graph
33
32
 
34
- _The set of entities and their relationships. Each entity must trace to either a persona-named action in `product-brief.md` or to the tenancy model from Section 1. Orphan entities halt with the drift challenge._
35
-
36
- **Entities**
33
+ _The entities and their relationships. Each entity traces to something a user does, or to the
34
+ tenancy model above._
37
35
 
38
36
  | Entity | Owns | Traces to | Relationships |
39
37
  | --- | --- | --- | --- |
40
- | <entity-name> | <one-line statement> | <persona-action OR tenancy-derived> | <FK refs> |
38
+ | <entity-name> | <one-line statement> | <user action OR tenancy-derived> | <FK refs> |
41
39
 
42
- **Conventions** (subsumed from prior template)
40
+ **Conventions**
43
41
 
44
- _Naming (snake_case, plural tables), timestamps (`created_at`, `updated_at` on every table, ISO 8601), soft-deletes vs hard-deletes per entity, UUID vs serial choice with rationale, audit fields if any._
42
+ _Naming (snake_case, plural tables), timestamps (`created_at`, `updated_at`, ISO 8601), soft- vs
43
+ hard-deletes per entity, UUID vs serial with rationale, audit fields if any._
45
44
 
46
45
  **Drift challenge answered**
47
46
 
48
- _"Does any entity here have no trace to a persona or feature in the brief? Name it."_
47
+ _"Does any entity here trace to nothing a user does? Name it."_
49
48
 
50
49
  ## 3. RLS Posture
51
50
 
52
- _Per-table policy sketch. Every entity from Section 2 falls into one of two categories — no third._
51
+ _Every entity from Section 2 falls into one of two categories — there is no third._
53
52
 
54
53
  **Tenant-scoped tables**
55
54
 
56
55
  | Table | Policy predicate sketch | Notes |
57
56
  | --- | --- | --- |
58
- | <table> | `<tenant-column> = current_setting('app.<tenant-column>')::uuid` | <e.g., RPC-only writes, no direct INSERT> |
57
+ | <table> | `<tenant-column> = current_setting('app.<tenant-column>')::uuid` | <e.g. RPC-only writes> |
59
58
 
60
59
  **Intentionally global tables**
61
60
 
62
61
  | Table | Why no RLS | Rationale |
63
62
  | --- | --- | --- |
64
- | <table> | <lookup data \| public reference \| ...> | <one sentence> |
63
+ | <table> | <lookup data \| public reference> | <one sentence> |
65
64
 
66
65
  **Drift challenge answered**
67
66
 
68
- _"Does any tenant-scoped entity have an RLS policy that the chosen tenancy model wouldn't enforce? Name it."_
67
+ _"Does any tenant-scoped entity have a policy the tenancy model would not enforce? Name it."_
69
68
 
70
69
  ## 4. RAG / pgvector
71
70
 
72
- _Whether v1 uses embeddings, what entity carries them, which embedding model, the tenant-scoped retrieval RPC signature. If v1 does not use RAG, mark this section `not-in-v1` with rationale and skip ahead._
73
-
74
- **Use in v1**
75
-
76
- _`yes` or `not-in-v1`. If not-in-v1, justify in one sentence (e.g., "v1 ships change-awareness without semantic retrieval; pgvector is a v2 layer")._
77
-
78
- **Embedding-bearing entities**
71
+ _Whether embeddings are in use, what carries them, which model, and the tenant-scoped retrieval
72
+ RPC. If they are not in use, say so in one sentence and skip ahead._
79
73
 
80
74
  | Entity | Embedding column | Model | Dimensions | Tenant-scoped retrieval RPC |
81
75
  | --- | --- | --- | --- | --- |
82
- | <entity> | <column name> | <e.g., openai:text-embedding-3-small> | <e.g., 1536> | <RPC signature with tenant predicate> |
83
-
84
- **Tenant-scoping requirement**
76
+ | <entity> | <column> | <e.g. openai:text-embedding-3-small> | <e.g. 1536> | <RPC signature with the tenant predicate> |
85
77
 
86
- _Every retrieval RPC MUST filter by the Section 1 tenant identifier. The drift challenge verifies this._
78
+ _Every retrieval RPC filters by the Section 1 tenant identifier, inside the similarity search and
79
+ not after it._
87
80
 
88
81
  **Drift challenge answered**
89
82
 
90
- _"Does any embedding-bearing entity have a retrieval RPC that bypasses tenant scoping? Name it."_
83
+ _"Does any embedding-bearing entity have a retrieval path that bypasses tenant scoping?"_
91
84
 
92
85
  ## 5. Migration Sketches
93
86
 
94
- _Postgres-dialect DDL sketches for the initial migrations, with `-- TODO: confirm` markers on uncertain parts. The implementer reads these during bootstrap and writes the actual `.sql` files; the sketches are intent, not executable. Typical ordering: schema → RLS → pgvector. Data must never land before RLS._
95
-
96
- **Migration sequence**
97
-
98
- ```
99
- m_0001_initial_schema.sql -- Section 2 entities, tables + FKs, no policies yet
100
- m_0002_rls_policies.sql -- Section 3 policies, applied per tenant-scoped table
101
- m_0003_pgvector_setup.sql -- Section 4 RPCs and indexes (skip if not-in-v1)
102
- m_0004_seed_global_data.sql -- Section 3 intentionally-global table seeds (optional)
103
- ```
104
-
105
- **Sketch — m_0001_initial_schema.sql**
87
+ _Postgres-dialect sketches with `-- TODO: confirm` markers. The migration that ships is written by
88
+ the change that needs it; these are intent, not executable. Ordering: schema → RLS → pgvector. Data
89
+ never lands before its policy._
106
90
 
107
91
  ```sql
108
- -- TODO: confirm UUID extension is enabled
109
- create extension if not exists "uuid-ossp";
110
-
111
- -- TODO: confirm column types and FK ON DELETE behaviors per entity
92
+ -- schema
112
93
  create table <entity> (
113
- id uuid primary key default uuid_generate_v4(),
94
+ id uuid primary key default gen_random_uuid(),
114
95
  <tenant-column> uuid not null references <tenant-table>(id) on delete cascade,
115
- -- entity-specific columns
116
96
  created_at timestamptz not null default now(),
117
97
  updated_at timestamptz not null default now()
118
98
  );
119
- ```
120
-
121
- **Sketch — m_0002_rls_policies.sql**
122
99
 
123
- ```sql
124
- -- TODO: confirm session-variable name matches app convention
100
+ -- policy, in the same migration as the table (kernel § Security checklist)
125
101
  alter table <entity> enable row level security;
126
102
 
127
103
  create policy <entity>_tenant_isolation on <entity>
@@ -129,38 +105,11 @@ create policy <entity>_tenant_isolation on <entity>
129
105
  using (<tenant-column> = current_setting('app.<tenant-column>')::uuid);
130
106
  ```
131
107
 
132
- **Sketch — m_0003_pgvector_setup.sql** (skip if Section 4 is `not-in-v1`)
133
-
134
- ```sql
135
- -- TODO: confirm pgvector version compatible with embedding model dimensions
136
- create extension if not exists vector;
137
-
138
- alter table <embedding-bearing-entity>
139
- add column embedding vector(<dimensions>);
140
-
141
- create index on <embedding-bearing-entity> using ivfflat (embedding vector_cosine_ops);
142
-
143
- -- TODO: confirm RPC signature and tenant predicate
144
- create or replace function nearest_<entity>(query_embedding vector, k int, p_<tenant-column> uuid)
145
- returns table (id uuid, score float4)
146
- language sql stable
147
- as $$
148
- select id, embedding <=> query_embedding as score
149
- from <embedding-bearing-entity>
150
- where <tenant-column> = p_<tenant-column>
151
- order by score
152
- limit k;
153
- $$;
154
- ```
155
-
156
- **Data lifecycle** (subsumed from prior template)
108
+ **Data lifecycle**
157
109
 
158
- _Retention windows per entity (e.g., "interactions: 18 months hot, archived after"), archival path, deletion guarantees (hard-delete vs soft-delete vs anonymize-and-retain). Lifecycle differences per tenant tier (free vs paid) noted here._
110
+ _Retention per entity, archival path, deletion guarantees (hard-delete, soft-delete, or
111
+ anonymize-and-retain)._
159
112
 
160
113
  **Drift challenge answered**
161
114
 
162
- _"Does any migration in the sketch sequence land data before its RLS policy? Name it."_
163
-
164
- ## Coherence check (end-of-atom)
165
-
166
- _When the atom reaches terminal state, the agent re-runs all five drift challenges. Any unanswered challenge halts the commit._
115
+ _"Does any migration in this sequence land data before its policy? Name it."_
@@ -1,190 +1,96 @@
1
- ---
2
- id: infrastructure
3
- type: infrastructure
4
- status: drafted # drafted | current | needs-refresh | archived
5
- owner: <git-handle>
6
- last-quarterly-review: <YYYY-MM-DD>
7
- created: <YYYY-MM-DD>
8
- updated: <YYYY-MM-DD>
9
- schema-version: 1
10
- ---
1
+ _Where things run, why the couplings are what they are, and the traps. Operational truth, not policy — read it before touching env, deploy or dependencies (kernel § Context docs), and update it in the PR that makes it wrong. An honest "we don't have this yet" is the right answer whenever it is the true one._
11
2
 
12
- _Operational truth about how the consuming repo's product runs. Truth-gathering, not policy — `threat-model.md` and `hardening-checklist.md` carry the policy. This file is what `security-reviewer`, `data-specialist`, and any future `infra-specialist` read to ground change-time review in the system's actual shape. Length norm: 600–1500 lines once filled; shorter is honest for pre-prod, longer is a smell. Every H2 below must be present (validator rule INF-01); the Unknowns section must be present even when empty (INF-02); the Blast-Radius Matrix must list at least one row when status moves to `current` (INF-03); no MCP server may be wired with always-on write capability against prod (INF-04); LLM-driven sessions with a write-capable MCP active must not read user-generated content in the same session (INF-05)._
3
+ ## Where things run
13
4
 
14
- ## Hosting & Compute
5
+ _One row per distinct runtime — app, edge functions, workers, cron, queue consumers. Names copied from the provider console, not paraphrased._
15
6
 
16
- _Where each runtime lives. Provider, region(s), service tier/plan, instance class or function memory. Names must match the cloud console exactly — copy them, do not paraphrase. One row per distinct runtime (app, edge functions, workers, cron, queue consumers)._
17
-
18
- | Runtime | Provider | Region(s) | Tier / Plan | Notes |
7
+ | Runtime | Provider | Region(s) | Plan / tier | Notes |
19
8
  |---|---|---|---|---|
20
9
  | | | | | |
21
10
 
22
- ## Networking
23
-
24
- _DNS provider and zone, custom domains, TLS/SSL provisioning, CDN / edge cache, load balancing, ingress rules. Note which records are managed in code (IaC) vs the provider console._
25
-
26
- - **DNS provider.**
27
- - **Domains in use.**
28
- - **TLS provisioning.**
29
- - **CDN / edge.**
30
- - **Load balancing.**
31
- - **Egress controls.**
11
+ - **Domains, DNS, TLS, CDN.**
12
+ - **Declared in code vs clicked in a console.** List the clicked resources explicitly — each one is a load-bearing piece of tribal knowledge.
32
13
 
33
- ## Data Layer
14
+ ## Data & storage
34
15
 
35
- _Database hosting, connection pooling, backup cadence, point-in-time recovery window, read replicas, retention policy. Defers schema and RLS to `data-architecture.md`; this section is operational (where and how, not what)._
16
+ _Operational only. Schema, tenancy and RLS live in `data-architecture.md`._
36
17
 
37
- - **Primary database.**
38
- - **Connection pooling.**
39
- - **Backups.**
40
- - **Point-in-time recovery.**
18
+ - **Primary database** — host, plan, connection pooling.
19
+ - **Backups** — cadence, retention, point-in-time-recovery window.
20
+ - **Last restore drill** — date, and what it proved. An untested backup is a wish.
41
21
  - **Replicas / failover.**
42
- - **Retention.**
43
- - **Vector / search infrastructure.**
44
-
45
- ## Storage
46
-
47
- _Object storage, file uploads, presigned-URL flows, lifecycle and retention. One row per bucket / container._
48
-
49
- | Bucket | Provider | Purpose | Public? | Lifecycle | Notes |
50
- |---|---|---|---|---|---|
51
- | | | | | | |
52
-
53
- ## Secrets & Configuration
54
-
55
- _Where secrets live, how they are injected at runtime, rotation cadence, who has access. **The runbook for rotation lives in `incident-runbook.md`; this section names the system, not the steps.**_
56
-
57
- - **Secret store.**
58
- - **Injection mechanism.**
59
- - **Rotation cadence.**
60
- - **Access control.**
61
- - **Audit trail.**
62
-
63
- ## Environment Separation
64
-
65
- _What dev, staging (if present), and production look like, and what differs between them. Data-promotion rules (does prod data ever flow downstream? if so, with what redaction?). Connection-string isolation. **Test-against-prod is a kernel-level forbidden tool; flag any violation here as tech-debt.**_
66
-
67
- - **Dev.**
68
- - **Staging.**
69
- - **Production.**
70
- - **Data-promotion rules.**
71
- - **Cross-environment guardrails.**
72
-
73
- ## IaC Inventory
74
-
75
- _What infrastructure is declared in code vs configured by click in a console. Path to IaC files. Tool (Terraform, Pulumi, CDK, OpenTofu, Supabase migrations, GitHub Actions YAML, Dockerfile). Who can apply. **Click-configured infra is not forbidden, but every clicked resource is a load-bearing tribal-knowledge item; list each one explicitly so it can be promoted to IaC over time.**_
76
-
77
- | Resource | Source-of-truth | Path / location | Applier(s) | Notes |
78
- |---|---|---|---|---|
79
- | | | | | |
80
-
81
- ## Deploy Pipeline
82
-
83
- _How code reaches each environment. References `ci-cd.md` for the build pipeline; this section captures the deploy half — promotion mechanics, rollout strategy (instant cutover, canary, blue/green), rollback procedure, who can trigger a deploy._
84
-
85
- - **Build → deploy handoff.**
86
- - **Promotion path.**
87
- - **Rollout strategy.**
88
- - **Rollback procedure.**
89
- - **Deploy authorization.**
90
-
91
- ## Observability
22
+ - **Vector or search infrastructure.**
23
+ - **Buckets** one line each: purpose, public or not, lifecycle.
92
24
 
93
- _Logs, metrics, traces, error tracking, uptime monitoring. Where each lives, retention window, who reads them. Alert routing — which alerts wake whom, on which channel. **An observability gap is a production-readiness gap; an honest "we don't have this yet" entry is the right answer when true.**_
25
+ ## Environments
94
26
 
95
- - **Logs.**
96
- - **Metrics.**
97
- - **Traces.**
98
- - **Error tracking.**
99
- - **Uptime monitoring.**
100
- - **Alert routing.**
101
-
102
- ## Cost & Capacity
103
-
104
- _Current monthly spend per service (approximate is fine). Budget alerts. Scaling triggers and ceilings. Rate-limiting posture (per-route, per-tenant). **Cost is a security and reliability concern, not just a finance concern: an unbounded scale ceiling is a billing-DoS vector.**_
27
+ _What dev, preview and production are, and what actually differs between them._
105
28
 
106
- | Service | Monthly spend (approx) | Budget alert at | Scale ceiling | Notes |
29
+ | Environment | App URL | Database it points at | Seed data | Notes |
107
30
  |---|---|---|---|---|
108
31
  | | | | | |
109
32
 
110
- - **Rate limits.**
111
- - **Per-tenant quotas.**
33
+ - **Source of truth for environment variables**, and how they are scoped per environment.
34
+ - **Does production data ever flow downstream?** If so, with what redaction.
35
+ - **Cross-environment guardrails.** Testing against production is a kernel-forbidden path; a violation found here is a tech-debt file, not a footnote.
112
36
 
113
- ## Disaster Recovery
114
-
115
- _Recovery Point Objective (RPO) and Recovery Time Objective (RTO) targets per critical resource. Backup restore procedure (high level — full steps live in `incident-runbook.md`). Drill cadence — when was the last successful restore test, and when is the next scheduled. **An untested backup is a wish, not a recovery plan.**_
116
-
117
- | Resource | RPO target | RTO target | Last drill | Next drill |
118
- |---|---|---|---|---|
119
- | | | | | |
37
+ ## Secrets
120
38
 
121
- ## Blast-Radius Matrix
39
+ - **Where they live.** The one store that is authoritative.
40
+ - **How they reach the runtime.**
41
+ - **Who has access**, and how that is reviewed.
42
+ - **Rotation** — cadence, and where the steps are written down.
122
43
 
123
- _Per critical resource: what depends on it, what dies if it dies, and who is notified. This is the table that `security-reviewer` reads when scoring an infra-surface change; it must list at least one row when status moves to `current` (INF-03)._
44
+ ## Deploy Pipeline
124
45
 
125
- | Resource | Depends on | What dies if this dies | Notification path | Mitigation |
126
- |---|---|---|---|---|
127
- | | | | | |
46
+ _How code reaches production, and the exact commands `/hstack-promote` will look for here. A command left blank halts the promotion — which is the correct outcome, because guessing a production command is how the wrong project gets migrated._
128
47
 
129
- ## Access & Change Control
48
+ | What `/hstack-promote` needs | Command |
49
+ |---|---|
50
+ | Apply a pending migration to production | |
51
+ | List deployments and their state | |
52
+ | Smoke-test a specific deployment URL | |
53
+ | Read production logs | |
54
+ | Promote a deployment | |
55
+ | Roll back to the previous deployment | |
130
56
 
131
- _Who has production console access per provider. MFA enforcement. Audit log location and retention. Deploy authorization — who can push to prod, who can apply IaC, who can rotate secrets. **The principle of least privilege applies here; list humans by name and access scope, not role abstractions.**_
57
+ - **Promotion path.** How a merge becomes an unpromoted production build, and what promotes it. Auto-assignment of the production domain must be off for the staged flow to exist at all.
58
+ - **Who may promote.**
59
+ - **Rollback.** What re-promoting the previous deployment does and does not undo — migrations are additive, so they stay.
132
60
 
133
- | Human | Provider | Scope | MFA enforced | Last access review |
134
- |---|---|---|---|---|
135
- | | | | | |
61
+ ## Observability
136
62
 
137
- - **Audit log location.**
138
- - **Audit log retention.**
139
- - **Access review cadence.**
63
+ _Where `/hstack-promote` looks in its post-promotion window, and where a daily glance happens._
140
64
 
141
- ## MCP Access Policy
65
+ - **Logs** where, retention.
66
+ - **Error tracking** — tool, project, who watches it.
67
+ - **Uptime monitoring.**
68
+ - **Alert routing** — which alert reaches whom, on which channel. "Nobody is paged" is an answer; write it down rather than implying one.
142
69
 
143
- _Which MCP servers are wired, where they point, what they can do. MCP access is a security boundary equivalent to the access token it carries — an LLM-driven session with tool access to a project-scoped token has the project's full blast radius. The kernel already forbids `service_role` Supabase keys and `supabase db push` / `db reset` against remote environments; MCP write access against prod is the analogous capability and follows the same rule. One row per MCP server per project it points at._
70
+ ## Couplings & gotchas
144
71
 
145
- | MCP server | Wired at | Points at | Access mode | Token storage | Rotation cadence | Notes |
146
- |---|---|---|---|---|---|---|
147
- | | | | | | | |
72
+ _The section that earns this file. Everything a newcomer human or agent would otherwise learn by breaking production: a region that must match another region, a version pinned because the next one broke us, a service that must be deployed before another, a quota that bites at a specific hour._
148
73
 
149
- **Rule (INF-04).** No MCP server may be wired with write capability against the production project. Read-only mode (the server's `--read-only` flag or equivalent) is the floor for any MCP that points at prod. When a write-capable MCP must exist against prod for an operational reason (one-off migration applied through the MCP, e.g.), the row above carries a `--write-justified-by: <change-spec-id or ADR id>` note and the MCP is disabled by default — enabled only inside the named change window, then immediately disabled. Always-on write-capable prod MCPs are forbidden.
74
+ -
150
75
 
151
- **Rule (INF-05).** Any LLM-driven session that has a write-capable MCP tool active must not, in the same session, read user-generated content from a tenant-scoped table. This is the prompt-injection mitigation: prevents stored content (customer support rows, webhook payloads, user-submitted fields) from steering the LLM into destructive tool calls. List each session pattern below — subagent name, Skill, or ad-hoc and which side of this boundary it sits on.
76
+ _External services this depends on at runtime. Criticality: `hard` = the product is down, `soft` = degraded, `optional` = no user impact._
152
77
 
153
- | Session pattern | Write-capable MCP tools active? | Reads tenant-scoped content? | Compliant? |
78
+ | Provider | Purpose | Criticality | What happens when it is down |
154
79
  |---|---|---|---|
155
80
  | | | | |
156
81
 
157
- **Per-MCP detail.**
158
-
159
- - **Supabase MCP.** Dev project, staging project, production project — each on its own row. "Not wired" is an acceptable and often preferred value, especially for production.
160
- - **Other MCPs** (Notion, GitHub, Linear, Figma, Slack, etc.). Each with its own access scope, token location, rotation. Notion and Slack MCPs in particular often surface external user-generated content into the session — flag them explicitly under INF-05.
161
-
162
- ## Compliance & Data Residency
163
-
164
- _Regions where customer data lives at rest. GDPR-relevant flows (subject-access, deletion, export). Encryption at rest and in transit per data class. SOC 2 readiness gaps (this is honest enumeration, not a claim of posture). **v1 hstack does not by itself deliver SOC 2 or GDPR posture; the kernel says so explicitly. This section catalogs the gap, it does not close it.**_
82
+ ## MCP access
165
83
 
166
- - **Data residency.**
167
- - **GDPR flows.**
168
- - **Encryption at rest.**
169
- - **Encryption in transit.**
170
- - **Known compliance gaps.**
84
+ _Which MCP servers are wired, where they point, what they can do. An MCP is a security boundary equivalent to the token it carries: a session with a project-scoped token has that project's full blast radius. The rules — no write-capable MCP against production outside `/hstack-promote`, and no write-capable MCP active in a session that reads user-generated tenant-scoped content — belong to the kernel § Stop conditions. This table is the inventory those rules are applied to._
171
85
 
172
- ## Third-party Dependencies
173
-
174
- _External SaaS the system depends on at runtime. One row per provider. Criticality reflects what happens if the provider is unavailable: `hard` = product is down, `soft` = degraded, `optional` = no user impact._
175
-
176
- | Provider | Purpose | Criticality | Contractual SLO | Failure-mode behavior |
86
+ | MCP server | Points at | Access mode | Token storage | Notes |
177
87
  |---|---|---|---|---|
178
88
  | | | | | |
179
89
 
180
- ## Known Gaps
181
-
182
- _Open tech-debt items pointing to infrastructure shortcomings. Each entry is a link to a `hstack/tech-debt/TD-NNNN-<slug>.md` file. This section is the bridge between the operational truth captured above and the workflow's tech-debt machinery — every honest gap surfaced during the interview should land as a TD via `/hstack:tech-debt-new --origin <change-id>`._
183
-
184
- -
90
+ _"Not wired" is an acceptable value, and often the preferred one for production._
185
91
 
186
- ## Unknowns
92
+ ## Known gaps
187
93
 
188
- _Challenge prompt: what infrastructure dependency does the team not yet have a documented mitigation for? Name the dependency, name the failure mode, name the gap. This section must be present even when empty, to make the absence explicit (validator rule INF-02)._
94
+ _What is missing or unknown, named rather than implied. A gap with a shape is a file under `hstack/tech-debt/`; link it here. A gap without one a dependency whose failure mode nobody has thought through is a line here until someone does._
189
95
 
190
96
  -
@@ -1,18 +1,12 @@
1
1
  ---
2
- id: roadmap
3
- type: roadmap
4
- status: drafted # drafted | current | needs-refresh | archived
5
- owner: <git-handle>
6
- source: local # local | rhizome — who owns the truth; when rhizome, local edits are refused and the sync is authoritative
7
- reviewed-on: <YYYY-MM-DD> # planner treats the roadmap as stale beyond 90 days
8
- created: <YYYY-MM-DD>
9
- updated: <YYYY-MM-DD>
10
- schema-version: 1
2
+ reviewed-on: <YYYY-MM-DD> # past 90 days, treat this roadmap as stale rather than current
11
3
  ---
12
4
 
5
+ _Advisory only, never a gate (kernel § Context docs). It informs one-way-door decisions and the Forecloses / Enables section of an ADR; it never decides whether a change ships._
6
+
13
7
  ## Now
14
8
 
15
- _What we are committed to shipping. During the MVP phase, Now IS the MVP scope. Each item: one product line, one architectural-implication line. Implications are proposed by app-architect / data-architect and confirmed by the engineer — vague fortune-telling ("might need to scale") is worse than absence._
9
+ _What we are committed to shipping. Each item: one product line, one architectural-implication line. Vague fortune-telling ("might need to scale") is worse than absence._
16
10
 
17
11
  - <item> — **architectural implication:** <one line>
18
12
 
@@ -30,12 +24,12 @@ _Plausible futures. These influence one-way-door decisions ONLY — never day-to
30
24
 
31
25
  ## Not on the path
32
26
 
33
- _Explicit renouncements, with the reason. Absorbs the old "Deferred" list._
27
+ _Explicit renouncements, with the reason._
34
28
 
35
29
  - <item> — <why not>
36
30
 
37
31
  ## Success criteria for the current horizon
38
32
 
39
- _Concrete observable indicators that Now is done and Next gets promoted. Bullets._
33
+ _Concrete observable indicators that Now is done and Next gets promoted._
40
34
 
41
35
  -