hstack 0.7.0 → 0.16.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 (99) hide show
  1. package/CHANGELOG.md +277 -0
  2. package/README.md +39 -13
  3. package/VERSION +1 -1
  4. package/dist/commands/doctor.js +51 -1
  5. package/dist/commands/doctor.js.map +1 -1
  6. package/dist/commands/update.js +8 -2
  7. package/dist/commands/update.js.map +1 -1
  8. package/dist/lib/descriptions.js +167 -0
  9. package/dist/lib/descriptions.js.map +1 -0
  10. package/dist/lib/diff.js +1 -1
  11. package/dist/lib/git.js +16 -0
  12. package/dist/lib/git.js.map +1 -1
  13. package/dist/lib/wire.js +108 -4
  14. package/dist/lib/wire.js.map +1 -1
  15. package/dist/manifest.js +17 -2
  16. package/dist/manifest.js.map +1 -1
  17. package/package.json +3 -1
  18. package/template/.claude/agents/adversarial-reviewer.md +16 -64
  19. package/template/.claude/agents/app-architect.md +12 -49
  20. package/template/.claude/agents/data-architect.md +13 -51
  21. package/template/.claude/agents/data-specialist.md +5 -50
  22. package/template/.claude/agents/implementer.md +8 -65
  23. package/template/.claude/agents/kernel-fit-analyst.md +7 -68
  24. package/template/.claude/agents/planner.md +7 -42
  25. package/template/.claude/agents/product-discovery.md +12 -48
  26. package/template/.claude/agents/product-manager.md +8 -43
  27. package/template/.claude/agents/researcher.md +5 -41
  28. package/template/.claude/agents/security-reviewer.md +19 -54
  29. package/template/.claude/agents/spec-author.md +18 -52
  30. package/template/.claude/agents/stack-architect.md +14 -43
  31. package/template/.claude/agents/test-strategist.md +16 -57
  32. package/template/.claude/agents/ui-ux-briefer.md +6 -36
  33. package/template/.claude/agents/verifier.md +13 -45
  34. package/template/.claude/skills/hstack-adr-new/SKILL.md +6 -33
  35. package/template/.claude/skills/hstack-adversarial-review/SKILL.md +31 -52
  36. package/template/.claude/skills/hstack-adversarial-review/references/finding-categories.md +157 -0
  37. package/template/.claude/skills/hstack-app-architecture/SKILL.md +2 -29
  38. package/template/.claude/skills/hstack-branch/SKILL.md +4 -31
  39. package/template/.claude/skills/hstack-brownfield-init/SKILL.md +10 -37
  40. package/template/.claude/skills/hstack-change-new/SKILL.md +4 -31
  41. package/template/.claude/skills/hstack-change-plan/SKILL.md +21 -32
  42. package/template/.claude/skills/hstack-commit/SKILL.md +7 -35
  43. package/template/.claude/skills/hstack-configure/SKILL.md +7 -34
  44. package/template/.claude/skills/hstack-coord/SKILL.md +3 -39
  45. package/template/.claude/skills/hstack-data-architecture/SKILL.md +4 -30
  46. package/template/.claude/skills/hstack-data-review/SKILL.md +3 -42
  47. package/template/.claude/skills/hstack-finalize/SKILL.md +30 -49
  48. package/template/.claude/skills/hstack-flag/SKILL.md +9 -48
  49. package/template/.claude/skills/hstack-greenfield-init/SKILL.md +9 -36
  50. package/template/.claude/skills/hstack-help/SKILL.md +11 -37
  51. package/template/.claude/skills/hstack-implement/SKILL.md +28 -58
  52. package/template/.claude/skills/hstack-kernel-fit-promote/SKILL.md +7 -46
  53. package/template/.claude/skills/hstack-kernel-fit-scan/SKILL.md +5 -60
  54. package/template/.claude/skills/hstack-kernel-fit-scan/references/slack-setup.md +42 -0
  55. package/template/.claude/skills/hstack-kernel-fit-triage/SKILL.md +12 -50
  56. package/template/.claude/skills/hstack-module-spec/SKILL.md +5 -32
  57. package/template/.claude/skills/hstack-product-discovery/SKILL.md +5 -31
  58. package/template/.claude/skills/hstack-research/SKILL.md +3 -33
  59. package/template/.claude/skills/hstack-scaffold/SKILL.md +2 -29
  60. package/template/.claude/skills/hstack-security-review/SKILL.md +5 -43
  61. package/template/.claude/skills/hstack-ship/SKILL.md +43 -53
  62. package/template/.claude/skills/hstack-stack-decide/SKILL.md +3 -30
  63. package/template/.claude/skills/hstack-story-draft/SKILL.md +6 -33
  64. package/template/.claude/skills/hstack-tech-debt-new/SKILL.md +4 -31
  65. package/template/.claude/skills/hstack-tech-debt-resolve/SKILL.md +9 -44
  66. package/template/.claude/skills/hstack-tech-debt-stale/SKILL.md +10 -37
  67. package/template/.claude/skills/hstack-tech-debt-wontfix/SKILL.md +8 -35
  68. package/template/.claude/skills/hstack-telemetry/SKILL.md +5 -30
  69. package/template/.claude/skills/hstack-test-plan/SKILL.md +23 -46
  70. package/template/.claude/skills/hstack-ui-brief/SKILL.md +3 -30
  71. package/template/.claude/skills/hstack-verify/SKILL.md +26 -48
  72. package/template/KERNEL.md +410 -0
  73. package/template/scripts/compute-merge-readiness.mjs +780 -0
  74. package/template/scripts/coord/coord_scan.py +121 -22
  75. package/template/scripts/run-gates.sh +388 -0
  76. package/template/scripts/telemetry/insights/kernel_fit.py +1 -1
  77. package/template/scripts/telemetry/insights/token_economics.py +181 -8
  78. package/template/scripts/telemetry/parsers/sidecars.py +61 -0
  79. package/template/scripts/telemetry/parsers/transcripts.py +135 -22
  80. package/template/scripts/telemetry/render.py +68 -3
  81. package/template/scripts/telemetry/report.py +16 -4
  82. package/template/scripts/telemetry/run_kernel_fit.py +6 -2
  83. package/template/scripts/telemetry/session_id.py +139 -0
  84. package/template/scripts/validate-spec.mjs +3303 -0
  85. package/template/templates/adr.md +7 -0
  86. package/template/templates/adversarial-review.md +5 -5
  87. package/template/templates/ci-cd.md +14 -0
  88. package/template/templates/coord-message.md +3 -2
  89. package/template/templates/data-architecture.md +3 -6
  90. package/template/templates/kernel-fit-finding.md +2 -2
  91. package/template/templates/kernel-fit-flag.md +2 -2
  92. package/template/templates/plan.md +4 -0
  93. package/template/templates/product-brief.md +2 -2
  94. package/template/templates/roadmap.md +41 -0
  95. package/template/templates/security-review.md +1 -1
  96. package/template/templates/telemetry-sidecar.md +56 -13
  97. package/template/templates/test-plan.md +1 -1
  98. package/template/CLAUDE.md +0 -443
  99. package/template/templates/mvp-scope.md +0 -34
@@ -37,3 +37,10 @@ _Positive, negative, and neutral outcomes. Particularly the trade-offs accepted.
37
37
  ## Alternatives Considered
38
38
 
39
39
  _What was on the table; why each was rejected. One paragraph per alternative._
40
+
41
+ ## Forecloses / Enables
42
+
43
+ _Against `hstack/context/roadmap.md`: which Next/Later item does this decision make more expensive (foreclose) or cheaper (enable)? One line each. "None" is a valid answer. When the roadmap is missing or stale, write `n/a — roadmap stale/missing` instead of guessing. Advisory — never a merge gate._
44
+
45
+ - Forecloses:
46
+ - Enables:
@@ -4,10 +4,10 @@ type: adversarial-review
4
4
  status: draft # draft | in-progress | findings-open | findings-resolved | superseded
5
5
  owner: <git-handle>
6
6
  parent-change: <change-spec-id>
7
- findings-floor: 3 # 3 default; 5 when change-spec.area in {agent, auth, billing}
7
+ findings-floor: 3 # AR-06: 3 default; 5 when change-spec.area in {agent, auth, billing}. The area's expected finding count — measured by telemetry, gated by nothing (ADR-0014)
8
8
  findings: [] # array of finding records; see below
9
- findings-fewer-than-floor: false
10
- justification-when-fewer: null # required when findings-fewer-than-floor: true
9
+ findings-fewer-than-floor: false # true when the review came in under the expectation; must be true when `findings` is empty
10
+ justification-when-fewer: null # required when findings-fewer-than-floor: true, and non-negotiable when `findings` is empty (AR-01)
11
11
  fresh-session-attestation: <session-id; opened <ISO-8601>; no implementer transcript loaded>
12
12
  created: <YYYY-MM-DD>
13
13
  updated: <YYYY-MM-DD>
@@ -29,7 +29,7 @@ _Fresh-session attestation; what artifacts were loaded; how findings were genera
29
29
 
30
30
  ## Findings
31
31
 
32
- _One subsection per finding (F-01..F-N). Mandate: at least `findings-floor` findings across categories, or `findings-fewer-than-floor: true` with justification._
32
+ _One subsection per finding (F-01..F-N). The six categories are lenses to sweep, not buckets to fill — file what the sweep found, at the severity it has. Calibration rubric: `hstack/.claude/skills/hstack-adversarial-review/references/finding-categories.md`._
33
33
 
34
34
  ### F-01
35
35
 
@@ -51,4 +51,4 @@ _Append-only record of how each finding was resolved. Written by `owner` in resp
51
51
 
52
52
  ## Findings Floor Justification
53
53
 
54
- _Populated only when `findings-fewer-than-floor: true`. Explain why fewer than the floor is the honest answer._
54
+ _Populated when `findings-fewer-than-floor: true`, and mandatory when `findings` is empty (AR-01). Reading a change cold and reporting nothing is a claim: enumerate what was looked for in each of the six categories and why each sweep came back clean. "The change is small" is not a defence._
@@ -18,6 +18,20 @@ _Every check in `.github/workflows/hstack-gates.yml` plus pre-existing CI checks
18
18
 
19
19
  -
20
20
 
21
+ ## Canonical Commands
22
+
23
+ _The exact commands `hstack/scripts/run-gates.sh` executes — the verifier runs every one of them and nothing else. The fenced `hstack-gates` block below is the machine-readable half; the prose above it is for humans. One `suite: command` pair per line. Suite keys mirror `verification.test-results`: `unit`, `integration`, `e2e`, `lint`, `typecheck`. Omit a line, or set it to `none`, for a suite this repo does not have — an omitted suite is not run and not scored. `unit` / `integration` / `e2e` are subject to V-05 (a suite that executes zero tests is recorded `not-run`, never `pass`); `lint` and `typecheck` are exempt._
24
+
25
+ _Extending this set is `/hstack:configure --interview ci-cd`, never an ad-hoc addition at verify time._
26
+
27
+ ```hstack-gates
28
+ unit: <command>
29
+ integration: <command>
30
+ e2e: none
31
+ lint: <command>
32
+ typecheck: <command>
33
+ ```
34
+
21
35
  ## Deploy targets
22
36
 
23
37
  _Preview, staging, production. What promotes to what. Manual vs automatic._
@@ -31,8 +31,9 @@ context, a decision, a heads-up — with `refs` pointing at the committed
31
31
  artifacts that carry the authoritative detail. The body summarizes; the refs
32
32
  are the source of truth.
33
33
 
34
- Validator rules (enforced by the proposed-diff preview in v1; validate-spec.ts
35
- is still a {{TODO-SCRIPT}} placeholder):
34
+ Validator rules (`node hstack/scripts/validate-spec.mjs <path>`; CM-02
35
+ immutability is a git-history claim the validator cannot see — it stays with
36
+ the Skill and the reviewer):
36
37
 
37
38
  - CM-01: at send-time, `from-repo`, `from-branch`, `to-repo`, and `subject`
38
39
  are non-null. `status` is `sent` and never changes.
@@ -17,16 +17,13 @@ schema-version: 1
17
17
 
18
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._
19
19
 
20
- **Pattern** one of:
20
+ **A tenant is a ...**
21
21
 
22
- - **A. Tenant = the customer organization** single workspace per paying customer; users inside share visibility.
23
- - **B. Tenant = a sub-team within the customer organization** — multi-workspace per customer.
24
- - **C. Tenant = the individual user** — workspace-per-user.
25
- - **D. Custom** — document the pattern explicitly and explain why none of A/B/C fit.
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._
26
23
 
27
24
  **Rationale**
28
25
 
29
- _One sentence tying the chosen pattern to the persona in `product-brief.md`. Example: "Pattern A because Maya (Director of CS) shares visibility with her 6 reps; sub-team isolation isn't requested by any v1 persona."_
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."_
30
27
 
31
28
  **Tenant identifier**
32
29
 
@@ -12,7 +12,7 @@ evidence-row-count: 0 # integer; must equal len(evidence-rows)
12
12
  evidence-rows: [] # YAML array of {change|adr|td, signal} dicts; one entry per row counted above
13
13
  related-findings: [] # KF ids — prior or adjacent findings on the same kernel surface
14
14
  promoted-to: null # `adr:<ADR-NNNN-slug>` | `tech-debt:<TD-NNNN-slug>` | null; reciprocal with the target artifact's `promoted-from-kernel-fit`; required when status: promoted
15
- dismissed-reason: null # ≥50 chars of prose; required when status: dismissed (per KF-05)
15
+ dismissed-reason: null # required when status: dismissed (KF-05); says what about the finding is wrong, specifically enough to be re-evaluated later
16
16
  superseded-by: null # KF id when status: superseded
17
17
  created: <YYYY-MM-DD>
18
18
  updated: <YYYY-MM-DD>
@@ -36,7 +36,7 @@ _Per evidence row, a 2–3 sentence prose summary with at least one inline citat
36
36
 
37
37
  ## Kernel surface implicated
38
38
 
39
- _Single-sentence pointer to the kernel section, template, validator rule, or Skill flow that the finding suggests revising. Examples: "`template/CLAUDE.md § Frontmatter contract` — the `internal-tooling` field"; "`template/templates/change-spec.md` frontmatter — `surfaces` enum"; "`/hstack:adversarial-review` precondition check at SKILL.md line 61"._
39
+ _Single-sentence pointer to the kernel section, template, validator rule, or Skill flow that the finding suggests revising. Examples: "`template/KERNEL.md § Frontmatter contract` — the `internal-tooling` field"; "`template/templates/change-spec.md` frontmatter — `surfaces` enum"; "`/hstack:adversarial-review` precondition check at SKILL.md line 61"._
40
40
 
41
41
  ## Proposed direction
42
42
 
@@ -24,8 +24,8 @@ A kernel-fit-flag is a frontmatter-only pin. There is no body. Engineer
24
24
  interpretation of the friction is deliberately excluded — the analyst reads
25
25
  the transcript window and forms its own classification at processing time.
26
26
 
27
- Validator rules (enforced by the proposed-diff preview in v1; validate-spec.ts
28
- is still a {{TODO-SCRIPT}} placeholder):
27
+ Validator rules (`node hstack/scripts/validate-spec.mjs <path>`; the pin itself
28
+ lands regardless see `/hstack:flag` § does NOT halt on):
29
29
 
30
30
  - FL-01: at pin-time (status: pending) every field marked above as
31
31
  "non-null at pin-time" must be populated. `hint` may be null; the four
@@ -12,6 +12,10 @@ updated: <YYYY-MM-DD>
12
12
  schema-version: 1
13
13
  ---
14
14
 
15
+ ## Roadmap Alignment
16
+
17
+ _One line, written by the planner against `hstack/context/roadmap.md`: does this change serve a Now/Next item, and does any phase foreclose a Next/Later item? When the roadmap is missing, not `current`, or `updated` > 90 days ago, write `n/a — roadmap stale/missing (<detail>)`. Advisory — never a gate._
18
+
15
19
  ## Phase Overview
16
20
 
17
21
  _Table of phases. Three columns max._
@@ -5,7 +5,7 @@ status: draft # draft | current | needs-refresh | archi
5
5
  owner: <git-handle>
6
6
  technique-used: <brainstorm | forcing-questions | project-brief>
7
7
  derived-from: [] # always empty — product-brief is Phase 1, no upstream
8
- downstream: [vision, mvp-scope, personas, glossary]
8
+ downstream: [vision, roadmap, personas, glossary]
9
9
  created: <YYYY-MM-DD>
10
10
  updated: <YYYY-MM-DD>
11
11
  schema-version: 1
@@ -44,7 +44,7 @@ _The things that could make this product fail. The forcing-prompt "What would yo
44
44
 
45
45
  ## Forcing-Prompt Answers
46
46
 
47
- _Evidence that the three required reframes ran. Logged inline as confirmation the probes were not skipped._
47
+ _Evidence that the three required reframes ran. Logged inline as confirmation the probes were not skipped. The headings below are the canonical wording — record what was actually asked when a reframe was fitted to this product._
48
48
 
49
49
  **Who specifically pays for this?**
50
50
  _The named user / buyer plus the rationale ("Director of CS, because retention is their KPI")._
@@ -0,0 +1,41 @@
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
11
+ ---
12
+
13
+ ## Now
14
+
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._
16
+
17
+ - <item> — **architectural implication:** <one line>
18
+
19
+ ## Next
20
+
21
+ _Likely within ~2 quarters. A direction, not a commitment. No dates._
22
+
23
+ - <item> — **architectural implication:** <one line>
24
+
25
+ ## Later
26
+
27
+ _Plausible futures. These influence one-way-door decisions ONLY — never day-to-day scoping._
28
+
29
+ - <item> — **architectural implication:** <one line>
30
+
31
+ ## Not on the path
32
+
33
+ _Explicit renouncements, with the reason. Absorbs the old "Deferred" list._
34
+
35
+ - <item> — <why not>
36
+
37
+ ## Success criteria for the current horizon
38
+
39
+ _Concrete observable indicators that Now is done and Next gets promoted. Bullets._
40
+
41
+ -
@@ -50,7 +50,7 @@ _Required when `threat-model-delta-required: true`. One paragraph delta against
50
50
 
51
51
  ## Challenge Prompts
52
52
 
53
- _All three required. Each answer must be at least one paragraph._
53
+ _All three required. Each answer must be at least one paragraph. The questions below are the canonical wording — adapt one to the change under review when the adaptation probes harder, and record what was actually asked in the heading. Keep the `(a)` / `(b)` / `(c)` prefixes: SR-02 locates the answers by them._
54
54
 
55
55
  ### (a) What attack vector did the In-Scope diff create that is NOT covered by the hardening checklist? If none, justify.
56
56
 
@@ -1,6 +1,8 @@
1
1
  # Telemetry sidecar — schema and discipline
2
2
 
3
- This document describes the JSON sidecar files three hstack Skills emit alongside their canonical artifact writes, to make per-change telemetry attribution cheap. Sidecars are **derivative** of git + frontmatter — re-runnable from source, never authoritative. The kernel's "no parallel tracker" rule is preserved by this derivative property.
3
+ This document describes the JSON sidecar files five hstack Skills emit alongside their canonical artifact writes, to make per-change telemetry attribution cheap. Sidecars are **derivative** of git + frontmatter + transcripts — re-runnable from source, never authoritative. The kernel's "no parallel tracker" rule is preserved by this derivative property.
4
+
5
+ This file is the canonical schema and the only place the field rules are stated. The five emitting Skills reference it: each carries its own JSON schema block (its Skill-specific payload) and the executable step that opens the phase window, and points here for everything else. Per ADR-0012 they do not restate the rules below.
4
6
 
5
7
  ## Where sidecars live
6
8
 
@@ -27,12 +29,40 @@ The `.telemetry/` directory is **git-ignored** at the consuming-repo level. Side
27
29
 
28
30
  The other 22 Skills do **not** emit sidecars in v1. Their data is reconstructible from git + frontmatter + transcripts; the five emissions above target the highest-signal events across the change lifecycle: test discipline up front (`test-plan`), per-phase scope-locked execution (`implement`), promised-vs-observed (`verify`), gate-firing critique (`adversarial-review`), lifecycle close (`finalize`).
29
31
 
32
+ ## The phase window — every sidecar, every Skill (schema_version 2)
33
+
34
+ Every sidecar carries three fields on top of its Skill-specific payload. They exist so the telemetry parser can answer "what did this phase cost?" — see ADR-0009.
35
+
36
+ ```json
37
+ {
38
+ "session_id": "062b8fe8-649f-4d73-b4fb-b0a28a800552",
39
+ "phase_opened_at": "2026-08-15T09:12:44Z",
40
+ "phase_closed_at": "2026-08-15T11:03:07Z"
41
+ }
42
+ ```
43
+
44
+ Field rules — one statement, applying identically to all five Skills:
45
+
46
+ - `session_id` — the active Claude Code session, resolved by `hstack/scripts/telemetry/session_id.py` (the most recently modified `*.jsonl` under `~/.claude/projects/<encoded-cwd>/`). One shared resolver, not a per-Skill heuristic. Unresolvable → `null`.
47
+ - `phase_opened_at` — stamped when the Skill's preconditions pass, **before any subagent invocation**. Same script call as `session_id`, so both come from one read. The script is read-only, takes milliseconds, and never halts; if it fails or reports `"session_id": null`, the Skill holds `null` for both and continues.
48
+ - `phase_closed_at` — stamped at the Skill's terminal state, in the same write that lands the sidecar.
49
+ - All three are **best-effort by contract**. Any of them `null`, unparseable, or inverted makes the phase *unmeasured*: `parsers/transcripts.py:phase_usage` returns `null`, and TE-4/TE-5 print `unmeasured`. **Never zero** — a phase whose window cannot be honoured still spent tokens, and a zero would fold it into the averages as if it were free.
50
+ - A sidecar write failure never blocks the canonical commit, and the window is never a halt condition. Measurement never gates the workflow.
51
+ - ISO-8601, UTC, second precision, `Z` suffix — the format `session_id.py` emits.
52
+
53
+ Sidecars at `schema_version: 1` (written before ADR-0009) carry no window and read as unmeasured. Nothing migrates them: the transcript timestamps they would need were never recorded.
54
+
55
+ The window measures *what the session spent while the phase was open* — not what the phase required. A detour taken between `phase_opened_at` and `phase_closed_at` is counted, and subagent spend lands in its host's window (`isSidechain: false` throughout the transcripts). Narrow, not exact.
56
+
30
57
  ## Schema — `test-plan.json`
31
58
 
32
59
  ```json
33
60
  {
34
- "schema_version": 1,
61
+ "schema_version": 2,
35
62
  "skill": "hstack-test-plan",
63
+ "session_id": "<session id, or null>",
64
+ "phase_opened_at": "<ISO-8601 at precondition pass, or null>",
65
+ "phase_closed_at": "<ISO-8601 at terminal state, or null>",
36
66
  "change_id": "2026-05-billing-overage-warning",
37
67
  "completed_at": "2026-05-22T11:14:00Z",
38
68
  "status": "passed",
@@ -61,8 +91,11 @@ Field rules:
61
91
 
62
92
  ```json
63
93
  {
64
- "schema_version": 1,
94
+ "schema_version": 2,
65
95
  "skill": "hstack-implement",
96
+ "session_id": "062b8fe8-649f-4d73-b4fb-b0a28a800552",
97
+ "phase_opened_at": "2026-05-22T13:58:12Z",
98
+ "phase_closed_at": "2026-05-22T14:18:42Z",
66
99
  "change_id": "2026-05-billing-overage-warning",
67
100
  "phase_id": "phase-3-component",
68
101
  "started_at": "2026-05-22T14:00:00Z",
@@ -77,19 +110,22 @@ Field rules:
77
110
 
78
111
  Field rules:
79
112
 
80
- - `started_at`, `completed_at` — ISO-8601. The implementer records them from session timestamps.
113
+ - `started_at`, `completed_at` — ISO-8601. The implementer records them from session timestamps. They describe the phase; `phase_opened_at` / `phase_closed_at` bound the *measurement window* and come from the shared resolver. They will usually be within seconds of each other; when they disagree, the window fields are the ones the parser reads.
81
114
  - `files_touched_count` — count of distinct files modified by the phase's commit. Computed mechanically; not a judgment.
82
115
  - `tests_written_count` — count of test files newly created in the phase (kernel test-immutability rule allows new tests without authorization).
83
116
  - `scope_amendment_emitted` — `true` only when the implementer halted and surfaced a scope-amendment request during this phase.
84
- - `halt_reasons` — array of enum values from the kernel halt sentinel (see CLAUDE.md § Halt sentinel).
117
+ - `halt_reasons` — array of enum values from the kernel halt sentinel (see KERNEL.md § Halt sentinel).
85
118
  - `test_immutability_authorizations` — array of canonical authorization phrases echoed during this phase (e.g., `"Ok to change test foo"`).
86
119
 
87
120
  ## Schema — `verify.json`
88
121
 
89
122
  ```json
90
123
  {
91
- "schema_version": 1,
124
+ "schema_version": 2,
92
125
  "skill": "hstack-verify",
126
+ "session_id": "062b8fe8-649f-4d73-b4fb-b0a28a800552",
127
+ "phase_opened_at": "2026-05-22T15:19:41Z",
128
+ "phase_closed_at": "2026-05-22T15:32:00Z",
93
129
  "change_id": "2026-05-billing-overage-warning",
94
130
  "ran_at": "2026-05-22T15:32:00Z",
95
131
  "test_suite_runtime_s": 187.4,
@@ -114,8 +150,11 @@ Field rules:
114
150
 
115
151
  ```json
116
152
  {
117
- "schema_version": 1,
153
+ "schema_version": 2,
118
154
  "skill": "hstack-adversarial-review",
155
+ "session_id": "9f41c0aa-2f5e-4c31-9a77-6d0b1b0e2c14",
156
+ "phase_opened_at": "2026-05-22T16:40:03Z",
157
+ "phase_closed_at": "2026-05-22T16:42:00Z",
119
158
  "change_id": "2026-05-billing-overage-warning",
120
159
  "reviewed_at": "2026-05-22T16:42:00Z",
121
160
  "findings_floor": 5,
@@ -138,17 +177,20 @@ Field rules:
138
177
 
139
178
  Field rules:
140
179
 
141
- - `findings_floor` is `3` by default, `5` when `change-spec.area` is in `{agent, auth, billing}` per AR-06.
142
- - `findings_count` < `findings_floor` is permitted only when `findings_fewer_than_floor: true` (with a defended justification in the canonical artifact's Findings Floor Justification section). Aggregating across changes: a rising `findings_fewer_than_floor: true` rate means either the floors are wrong or the reviewer is gaming the escape hatch.
143
- - `category_counts` clustering — e.g., 5 of 5 findings in `code-quality` — is the quota-gaming smell the kernel's "spread findings across categories" guidance is designed to detect. The telemetry layer surfaces it via OE-7.
180
+ - `findings_floor` is `3` by default, `5` when `change-spec.area` is in `{agent, auth, billing}` per AR-06. Since ADR-0014 it is the area's *expected* finding count and gates nothing — it is carried here so `findings_count` has a denominator to be read against.
181
+ - `findings_count` below `findings_floor` is an ordinary outcome, not a violation. The one count the canonical artifact must argue for is zero: AR-01 requires `findings_fewer_than_floor: true` with a defended justification when `findings` is empty. Aggregating across changes: the `findings_count / findings_floor` distribution is the primary read, and a rate of empty reviews that climbs while `severity_counts` stays flat is the signal worth acting on.
182
+ - `category_counts` clustering — e.g., 5 of 5 findings in `code-quality` — is a description of where a change carried its risk, not a smell in itself. It is worth reading against the change's `surfaces`: a `db`-surface change with every finding in `code-quality` is a review that did not look where the risk was. Surfaced via OE-7.
144
183
  - `severity_counts.high + critical` paired with `resolution_mix.justified-in-prose > 0` is a high-severity-in-prose smell flagged by QO-2. The Skill's stop condition should have caught it before terminal status; sidecar presence indicates a bypass.
145
184
 
146
185
  ## Schema — `finalize.json`
147
186
 
148
187
  ```json
149
188
  {
150
- "schema_version": 1,
189
+ "schema_version": 2,
151
190
  "skill": "hstack-finalize",
191
+ "session_id": "c7d2e5b1-88a4-4f0d-b3ce-51a9f7d6e8b2",
192
+ "phase_opened_at": "2026-05-23T10:11:26Z",
193
+ "phase_closed_at": "2026-05-23T10:14:00Z",
152
194
  "change_id": "2026-05-billing-overage-warning",
153
195
  "shipped_at": "2026-05-23T10:14:00Z",
154
196
  "merge_commit_sha": "abc1234567890",
@@ -169,8 +211,9 @@ Per the kernel § Mechanical operations § Discipline preserved:
169
211
 
170
212
  - **Atomic with the canonical commit.** Each sidecar is written and `git add`-ed in the same commit as the canonical artifact write. No separate commit. The sidecar piggybacks on a commit that was happening anyway — zero new LLM turns, zero new confirmation gates.
171
213
  - **Idempotency.** Re-running a Skill on a phase that already landed produces a no-op on the sidecar (file already present, content unchanged aside from `schema_version` bumps if any).
172
- - **Derivative property.** Every value in every sidecar is reconstructible from git + frontmatter + transcripts. The sidecar is a cache, not a source. Deleting a sidecar is harmless — the next `/hstack:telemetry` run will compute the same metrics from the slower path.
173
- - **Schema versioning.** `schema_version: 1` in v1. Bumping to `2` requires either a backward-compatible additive change (new optional field) or a migration in `scripts/telemetry/parsers/`.
214
+ - **Derivative property.** Every value in every sidecar is reconstructible from git + frontmatter + transcripts. The sidecar is a cache, not a source. Deleting a sidecar is harmless — the next `/hstack:telemetry` run will compute the same metrics from the slower path. The phase window is the one field group with a shelf life: it points at a transcript that `cleanupPeriodDays` will eventually sweep (365 days on some machines, 30 by default), after which the phase reads as unmeasured. Deleting the sidecar loses the window for good, since nothing else records it.
215
+ - **Schema versioning.** `schema_version: 2` since ADR-0009 (the phase window). The bump is additive: every v1 field keeps its name and meaning, and a v1 sidecar still parses — it simply reports as unmeasured. No migration exists or is planned.
216
+ - **No local identifiers in git.** `session_id` is a local machine identifier. `.telemetry/` is gitignored in the consuming repo, so it never lands in history — but the discipline now depends on that gitignore line holding. A consumer that commits `.telemetry/` publishes its session ids.
174
217
 
175
218
  ## What sidecars are NOT
176
219
 
@@ -106,7 +106,7 @@ _Required when `performance-budgets-required: true`. For each hot path the chang
106
106
 
107
107
  ## Challenge Prompts
108
108
 
109
- _All three required. Each answer must be at least one paragraph. These exist because the v1 mitigation for "humans miss what's missing" is to force the strategist to name gaps the planner and the implementer will not._
109
+ _All three required. Each answer must be at least one paragraph. These exist because the v1 mitigation for "humans miss what's missing" is to force the strategist to name gaps the planner and the implementer will not. The questions below are the canonical wording — adapt one to the change when the adaptation probes harder, and record what was actually asked in the heading. Keep the `(a)` / `(b)` / `(c)` prefixes: TS-02 locates the answers by them._
110
110
 
111
111
  ### (a) What behavior in this change would silently pass the test suite but break in production? Name the test that would catch it, or declare that no such test is planned and justify.
112
112