heyspex 0.2.6 → 0.2.7

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 (85) hide show
  1. package/bin/hs.mjs +85 -25
  2. package/bin/spexcode.mjs +31 -0
  3. package/dev-factory/lib/local-firecrawl.mjs +294 -0
  4. package/dev-factory/lib/seat-context.mjs +20 -4
  5. package/dev-factory/model-catalog.json +222 -222
  6. package/dev-factory/spexcrawl/firecrawl-cli.mjs +755 -0
  7. package/dist/cli/hs-connect.mjs +20 -2
  8. package/dist/cli/hs-defer.mjs +19 -1
  9. package/dist/cli/hs-index-rebuild.mjs +19 -1
  10. package/dist/cli/hs-index-reconcile.mjs +19 -1
  11. package/dist/cli/hs-init.mjs +2 -2
  12. package/dist/cli/hs-install.mjs +2 -2
  13. package/dist/cli/hs-join.mjs +20 -2
  14. package/dist/cli/hs-next-launch.mjs +89 -10
  15. package/dist/cli/hs-spawn.mjs +27 -1
  16. package/dist/cli/hs-vault-pull.mjs +19 -1
  17. package/dist/cli/hs-vault-push.mjs +19 -1
  18. package/dist/cli/hs-vault.mjs +21 -7
  19. package/dist/cli/hs-workspace.mjs +19 -1
  20. package/dist/cli-templates/customer-vault/specs/entity-model.md +1728 -1728
  21. package/dist/cli-templates/customer-vault/specs/protocols/canonical-frontmatter-templates.md +464 -464
  22. package/dist/cli-templates/customer-vault/specs/protocols/destructive-action-checklist.md +122 -122
  23. package/dist/cli-templates/customer-vault/specs/protocols/memory-protocol.md +46 -46
  24. package/dist/cli-templates/customer-vault/specs/protocols/spec-hierarchy.md +530 -530
  25. package/dist/cli-templates/customer-vault/specs/protocols/spec-summary-authoring.md +83 -83
  26. package/dist/cli-templates/harness-commands/claude/hs-backfill.md +28 -28
  27. package/dist/cli-templates/harness-commands/claude/hs-capture.md +62 -62
  28. package/dist/cli-templates/harness-commands/claude/hs-defer.md +29 -29
  29. package/dist/cli-templates/harness-commands/claude/hs-ground.md +30 -30
  30. package/dist/cli-templates/harness-commands/claude/hs-next.md +29 -29
  31. package/dist/cli-templates/harness-commands/claude/hs-promote.md +70 -70
  32. package/dist/cli-templates/harness-commands/claude/hs-push.md +35 -35
  33. package/dist/cli-templates/harness-commands/claude/hs-qc.md +27 -27
  34. package/dist/cli-templates/harness-commands/claude/hs-res.md +20 -8
  35. package/dist/cli-templates/harness-commands/claude/hs-resolve.md +23 -23
  36. package/dist/cli-templates/harness-commands/claude/hs-view.md +28 -28
  37. package/dist/cli-templates/harness-commands/claude/kill-ports.md +32 -32
  38. package/dist/cli-templates/harness-commands/claude/prototype.md +91 -91
  39. package/dist/cli-templates/harness-commands/cursor/hs-backfill.md +22 -22
  40. package/dist/cli-templates/harness-commands/cursor/hs-capture.md +56 -56
  41. package/dist/cli-templates/harness-commands/cursor/hs-defer.md +23 -23
  42. package/dist/cli-templates/harness-commands/cursor/hs-ground.md +24 -24
  43. package/dist/cli-templates/harness-commands/cursor/hs-next.md +23 -23
  44. package/dist/cli-templates/harness-commands/cursor/hs-promote.md +64 -64
  45. package/dist/cli-templates/harness-commands/cursor/hs-push.md +29 -29
  46. package/dist/cli-templates/harness-commands/cursor/hs-qc.md +21 -21
  47. package/dist/cli-templates/harness-commands/cursor/hs-res.md +20 -8
  48. package/dist/cli-templates/harness-commands/cursor/hs-resolve.md +17 -17
  49. package/dist/cli-templates/harness-commands/cursor/hs-view.md +23 -23
  50. package/dist/cli-templates/harness-commands/cursor/kill-ports.md +26 -26
  51. package/dist/cli-templates/harness-commands/cursor/prototype.md +86 -86
  52. package/docs/copilot-plugin-install.md +7 -0
  53. package/docs/mcp-client-config.md +6 -0
  54. package/package.json +7 -2
  55. package/plugins/heyspex/README.md +6 -0
  56. package/plugins/heyspex/bin/launch-mcp.mjs +17 -0
  57. package/plugins/heyspex/hooks/hooks.json +418 -418
  58. package/scripts/claude-hooks/_intent-classifier-semantic.mjs +2 -2
  59. package/scripts/hs-companion.mjs +38 -8
  60. package/scripts/lib/companion-install.mjs +768 -0
  61. package/scripts/lib/customer-kit.mjs +5 -3
  62. package/scripts/lib/hs-companion-settings.mjs +1 -0
  63. package/scripts/lib/hs-source-push.mjs +386 -386
  64. package/spexharness/doctrine/baseline/SPEXCODE-DOCTRINE.baseline.json +29 -29
  65. package/spexharness/src/adapters/copilot-models.mjs +179 -0
  66. package/spexharness/src/adapters/harness-detect.mjs +148 -0
  67. package/spexharness/src/gates/directive-obligation-gate.decide.mjs +132 -132
  68. package/spexharness/src/gates/vault-write-tier-guard.decide.mjs +153 -125
  69. package/spexharness/src/seat-context.mjs +10 -5
  70. package/spexharness/src/session-bootstrap.mjs +6 -3
  71. package/vendor/heyspex-mcp/cli.mjs +6 -1
  72. package/vendor/heyspex-mcp/config-seed.yaml +15 -15
  73. package/vendor/heyspex-mcp/dev-factory-overlay.mjs +142 -0
  74. package/vendor/heyspex-mcp/memory-tools.mjs +523 -523
  75. package/vendor/heyspex-mcp/on-deck-scheduler.mjs +1708 -1708
  76. package/vendor/heyspex-mcp/procedure-handlers.mjs +327 -327
  77. package/vendor/heyspex-mcp/procedure-tools.mjs +1209 -1181
  78. package/vendor/heyspex-mcp/research-tools.mjs +22 -2
  79. package/vendor/heyspex-mcp/seat-assign-cli.mjs +242 -0
  80. package/vendor/heyspex-mcp/seat-assignment-rules.mjs +96 -0
  81. package/vendor/heyspex-mcp/seat-assignments-client.mjs +265 -0
  82. package/vendor/heyspex-mcp/seat-defaults-cli.mjs +45 -0
  83. package/vendor/heyspex-mcp/seat-defaults.mjs +232 -0
  84. package/vendor/heyspex-mcp/seat-identity.mjs +171 -0
  85. package/vendor/heyspex-mcp/vault-io.mjs +720 -720
@@ -7,67 +7,67 @@ description: Promote whatever doc you hand it to its next stage — a capture (H
7
7
 
8
8
  **Usage:** `/hs-promote <HS-CAP-XXXX[,HS-CAP-YYYY...] | HS-RES-XXXX> [rest of args depend on which — see below]`
9
9
 
10
- > **Platform asymmetry — read this, it is load-bearing.** Claude Code delivers only the **first whitespace token** of an MCP prompt's argument (GitHub [#14210](https://github.com/anthropics/claude-code/issues/14210), closed *not planned*), so the namespaced MCP prompts (`/hs-promote-capture`, `/hs-promote-research`) can each carry at most a single token. This **native project command** is the only IDE surface that receives full `$ARGUMENTS`.
11
- >
12
- > **Why one command instead of two.** `/hs-promote-capture` and `/hs-promote-research` used to be separate commands — which meant typing the word "promote" twice (`/hs-promote-capture HS-CAP-XXXX promote`) when the command name already said what it does. There's exactly one verb here — *promote whatever doc you hand it to its next stage* — so there's one command. The **id prefix alone** tells you which flow applies (`HS-CAP-*` vs `HS-RES-*` are mutually exclusive and mechanical to detect); the two flows underneath are otherwise unrelated (different tools, different payload shapes, different two-phase mechanics) and stay fully separate below — only the entrypoint is shared.
13
-
14
- ## Step 0 — identify the doc
15
-
16
- Read the **leading token** of `$ARGUMENTS` (case-insensitive; captures may be a comma/whitespace-separated list):
17
- - Contains `-CAP` as its type label (legacy `HS-CAP-XXXX` or era-3 `HS-<fileKey>-<familyKey>-CAP-<slug>`) → go to **§A. Capture → research**.
18
- - Contains `-RES` the same way → go to **§A2. Research → milestone**.
19
- - **Era-3 short/display forms carry NO type label** — `HS-XV4W` (short id) and `HS-XV4W-HV6H` (file key + family key, the form humans see rendered) name a spec without saying its kind. Resolve the kind by fetching it: `heyspex_active_capture({ spec_id })` succeeding → it's a capture, §A. Otherwise treat it as research and try §A2. The tools accept any of these forms and collapse them to the stored short id themselves — never tell the user their id is wrong just because it carries (or lacks) the family key.
20
- - None of the above → ask the user which doc they mean (don't guess).
21
-
22
- If the capture tools are not already available in this session, call `heyspex_load_tools` first so `heyspex_active_capture` / `heyspex_promote_capture` / `heyspex_promote_capture_to_diagnose` are callable.
23
-
24
- ---
25
-
26
- ## §A. Capture → research (`HS-CAP-*`)
27
-
28
- **1. Parse the rest of `$ARGUMENTS`:**
29
- - Leading token(s) matching `HS-CAP-[A-Z0-9-]{3,}` (comma- and/or whitespace-separated) → `capture_ids` (1 or more).
30
- - Next token: `HS-RES-[A-Z0-9-]{3,}` → `target_research` = that id. Or the literal word `new`/`NEW` (also the default when this token is omitted entirely) → `target_research = "NEW"`; any remaining words up to an `enhances:` token → `new_research_name`.
31
- - A token shaped `enhances:HS-MIL-XXXX` anywhere in the string → `enhances`.
32
-
33
- **2. Route by kind:**
34
- - For each `capture_id`, read its `kind:` via `heyspex_active_capture({ spec_id: capture_id })`.
35
- - Exactly one capture_id AND its `kind: bug-fix` → `heyspex_promote_capture_to_diagnose({ capture_id })` (creates `HS-DIAG-*`). Never mix a bug-fix capture into a multi-capture research promote.
36
- - Otherwise → `heyspex_promote_capture({ capture_ids, target_research, new_research_name?, enhances? })`:
37
- - `target_research === "NEW"` is **two-phase**: first call **omits** `accepted_outline` — it returns a proposed `{ name, outline, tags, enhances_suggestion }`. **Show it to the user and confirm** before calling again with the same args plus `accepted_outline` (Phase 2 performs the writes). Never skip straight to Phase 2.
38
- - An existing `target_research` id is single-phase (direct, idempotent append) — no outline confirm needed.
39
- - A `CAPTURE_INSUFFICIENT` error names the missing elements (core-idea, example, done-criteria, kind, user-stories) — the correct response is to elicit that detail from the user and improve the capture, not to pass `force_promote: true` unless the human explicitly says to promote anyway.
40
- - **Check the outline against the capture's own Notes before presenting it.** Before showing `proposed_outline` (AI-proposed or agent-authored) to the user, walk every verbatim quote in the capture's `## Notes` and state plainly whether the outline addresses it. If a quote asks for something the outline doesn't cover, add a section for it or say so before asking for confirm — a missed verbatim quote is exactly what got two real items dropped from a milestone in this vault's own history ([[HS-GDT5-F16L-DIAG-promote-flow-drafts-research-and-stubs]]).
41
- - **Outline confirm ≠ research done.** Phase 2 only writes the research **stub** — every section body is the literal placeholder `_TBD — fill in this section._`. Confirming the outline approves its *shape* (section headings), not its findings. As the very next step after Phase 2 creates the file, fill in every section with real content **by running the `/hs-res` method** (SpexCrawl gather via the Companion + DeepSeek synthesis — see `.claude/commands/hs-res.md`); **never author the research yourself in the main session** — main-session self-research skips the routed research seats and burns the expensive model on work the fleet owns. Do not report the research as complete, and do not move on to `/hs-promote-research`, until the TBD placeholders are gone. (`heyspex_promote_research` mechanically refuses with `RESEARCH_STILL_STUB` while any remain, but don't rely on that gate — write the research because it's the point of the flow, not because a check will otherwise fail.)
42
-
43
- **3. Report the result** — the research id (created or extended) or diagnose id created, and confirm the capture(s)' `promoted_to` now points at it.
44
-
45
- ---
46
-
47
- ## §A2. Research → milestone (`HS-RES-*`)
48
-
49
- **1. Parse the rest of `$ARGUMENTS`:**
50
- - `research_id` is the leading `HS-RES-*` token (already identified in Step 0).
51
- - Next word matching `spawn|augment|both` → `intent`. Default `spawn` when omitted.
52
- - Next token: `HS-MIL-[A-Z0-9-]{3,}` → `target_milestone` = that id. Or the literal word `new`/`NEW` (also the default when this token is omitted entirely) → `target_milestone = "NEW"`; remaining words → `new_milestone_name`.
53
- - If `intent` includes `augment`, any remaining `HS-EPIC-[A-Z0-9-]{3,}` tokens → `augment_epic_ids` (required in that case — ask for them if `augment` was requested but none were given).
54
-
55
- **2. Default policy:** `target_milestone: "NEW"` unless the user names an **existing `status: open`** milestone that clearly extends the same thesis. Spawning into an `in_progress` milestone is blocked unless the owner explicitly passes `attach_to_in_progress_milestone: true` + `attach_override_reason` (≥40 chars audit trail) — never default to this path or infer the override on the agent's own judgment.
56
-
57
- **3. Phase 1 — proposal.** Call `heyspex_promote_research({ research_id, target_milestone, new_milestone_name?, intent, spawn_epic_count?, augment_epic_ids? })` **without** `accepted_stubs`. Show the user the returned `proposed_stubs[]` and let them edit/remove/approve.
58
- - **If `ai_proposal.ok === false` (e.g. `reason: "no_api_key"`), `proposed_stubs` comes back empty — the agent must author the stubs itself.** This is NOT a shortcut to skip the confirm step; it makes the confirm step *more* necessary, not less, because nothing upstream has vetted these stubs yet. Author them from the research doc's actual content, present them to the user exactly as you would an AI proposal (name/kind/effort/rationale per stub), and wait for a real approval turn before calling Phase 2. **Do not call Phase 2 in the same turn you authored the stubs in** — that is precisely the failure this line exists to prevent (observed 2026-08-12: an agent self-authored 3 epic stubs and executed `accepted_stubs` in the same tool-call batch with no human turn in between).
59
- - **Check the stubs against the SOURCE CAPTURE's own Notes before presenting them.** Before showing `proposed_stubs` (AI-proposed or agent-authored) to the user, walk every verbatim quote in the source capture's `## Notes` — the capture(s) named in the research doc's `sources_captures`, not just the research doc's own prose, since a two-hop drift can lose fidelity the research doc's text won't show — and confirm each is addressed by a stub or explicitly named as out of scope. This check caught two real gaps missed by an agent-authored stub list in this vault's own history ([[HS-GDT5-F16L-DIAG-promote-flow-drafts-research-and-stubs]]).
60
-
61
- **4. Phase 2 — execute (after human confirms).** Call again with the same args plus `accepted_stubs: [...]` (the confirmed, possibly-edited subset) to perform the transactional write.
62
-
63
- **5. Report the result** — the milestone id (new or existing) plus spawned epic ids, or the augmented epic ids. Note that research stays `status: open` (research is evergreen) — only its `enhances:`/`spawned_epics:` links change.
64
-
65
- ---
66
-
67
- ## Hard prohibitions
68
-
69
- - **Never** execute a Phase-2 write (`accepted_outline` or `accepted_stubs`) without the human having seen and confirmed the Phase-1 proposal. For `accepted_stubs` the tool now refuses this mechanically: the proposal turn leaves a marker keyed on the research id, and an execute turn without one returns `STUB_REVIEW_REQUIRED`. If the human replaced every proposed stub, pass `stub_edit_note` (≥40 chars) saying what they changed — otherwise a fully-drifted execute returns `STUB_REVIEW_DRIFT`. As with `RESEARCH_STILL_STUB`, treat the mechanical refusal as the backstop, not the first line of defense.
70
- - **Never** call `heyspex_promote_research` against a research doc that still carries `_TBD — fill in this section._` placeholders — fill it in via the `/hs-res` method first (§A step 2 above), never by authoring the research yourself in the main session. The tool refuses this mechanically (`RESEARCH_STILL_STUB`) but the agent should never rely on that as the first line of defense.
71
- - **Never** route a bug-fix capture through `heyspex_promote_capture` — it goes to `heyspex_promote_capture_to_diagnose` instead.
72
- - **Never** attach a research promote to an `in_progress` milestone without an explicit owner override (`attach_to_in_progress_milestone` + `attach_override_reason`).
73
- - **Never** commit or push.
10
+ > **Platform asymmetry — read this, it is load-bearing.** Claude Code delivers only the **first whitespace token** of an MCP prompt's argument (GitHub [#14210](https://github.com/anthropics/claude-code/issues/14210), closed *not planned*), so the namespaced MCP prompts (`/hs-promote-capture`, `/hs-promote-research`) can each carry at most a single token. This **native project command** is the only IDE surface that receives full `$ARGUMENTS`.
11
+ >
12
+ > **Why one command instead of two.** `/hs-promote-capture` and `/hs-promote-research` used to be separate commands — which meant typing the word "promote" twice (`/hs-promote-capture HS-CAP-XXXX promote`) when the command name already said what it does. There's exactly one verb here — *promote whatever doc you hand it to its next stage* — so there's one command. The **id prefix alone** tells you which flow applies (`HS-CAP-*` vs `HS-RES-*` are mutually exclusive and mechanical to detect); the two flows underneath are otherwise unrelated (different tools, different payload shapes, different two-phase mechanics) and stay fully separate below — only the entrypoint is shared.
13
+
14
+ ## Step 0 — identify the doc
15
+
16
+ Read the **leading token** of `$ARGUMENTS` (case-insensitive; captures may be a comma/whitespace-separated list):
17
+ - Contains `-CAP` as its type label (legacy `HS-CAP-XXXX` or era-3 `HS-<fileKey>-<familyKey>-CAP-<slug>`) → go to **§A. Capture → research**.
18
+ - Contains `-RES` the same way → go to **§A2. Research → milestone**.
19
+ - **Era-3 short/display forms carry NO type label** — `HS-XV4W` (short id) and `HS-XV4W-HV6H` (file key + family key, the form humans see rendered) name a spec without saying its kind. Resolve the kind by fetching it: `heyspex_active_capture({ spec_id })` succeeding → it's a capture, §A. Otherwise treat it as research and try §A2. The tools accept any of these forms and collapse them to the stored short id themselves — never tell the user their id is wrong just because it carries (or lacks) the family key.
20
+ - None of the above → ask the user which doc they mean (don't guess).
21
+
22
+ If the capture tools are not already available in this session, call `heyspex_load_tools` first so `heyspex_active_capture` / `heyspex_promote_capture` / `heyspex_promote_capture_to_diagnose` are callable.
23
+
24
+ ---
25
+
26
+ ## §A. Capture → research (`HS-CAP-*`)
27
+
28
+ **1. Parse the rest of `$ARGUMENTS`:**
29
+ - Leading token(s) matching `HS-CAP-[A-Z0-9-]{3,}` (comma- and/or whitespace-separated) → `capture_ids` (1 or more).
30
+ - Next token: `HS-RES-[A-Z0-9-]{3,}` → `target_research` = that id. Or the literal word `new`/`NEW` (also the default when this token is omitted entirely) → `target_research = "NEW"`; any remaining words up to an `enhances:` token → `new_research_name`.
31
+ - A token shaped `enhances:HS-MIL-XXXX` anywhere in the string → `enhances`.
32
+
33
+ **2. Route by kind:**
34
+ - For each `capture_id`, read its `kind:` via `heyspex_active_capture({ spec_id: capture_id })`.
35
+ - Exactly one capture_id AND its `kind: bug-fix` → `heyspex_promote_capture_to_diagnose({ capture_id })` (creates `HS-DIAG-*`). Never mix a bug-fix capture into a multi-capture research promote.
36
+ - Otherwise → `heyspex_promote_capture({ capture_ids, target_research, new_research_name?, enhances? })`:
37
+ - `target_research === "NEW"` is **two-phase**: first call **omits** `accepted_outline` — it returns a proposed `{ name, outline, tags, enhances_suggestion }`. **Show it to the user and confirm** before calling again with the same args plus `accepted_outline` (Phase 2 performs the writes). Never skip straight to Phase 2.
38
+ - An existing `target_research` id is single-phase (direct, idempotent append) — no outline confirm needed.
39
+ - A `CAPTURE_INSUFFICIENT` error names the missing elements (core-idea, example, done-criteria, kind, user-stories) — the correct response is to elicit that detail from the user and improve the capture, not to pass `force_promote: true` unless the human explicitly says to promote anyway.
40
+ - **Check the outline against the capture's own Notes before presenting it.** Before showing `proposed_outline` (AI-proposed or agent-authored) to the user, walk every verbatim quote in the capture's `## Notes` and state plainly whether the outline addresses it. If a quote asks for something the outline doesn't cover, add a section for it or say so before asking for confirm — a missed verbatim quote is exactly what got two real items dropped from a milestone in this vault's own history ([[HS-GDT5-F16L-DIAG-promote-flow-drafts-research-and-stubs]]).
41
+ - **Outline confirm ≠ research done.** Phase 2 only writes the research **stub** — every section body is the literal placeholder `_TBD — fill in this section._`. Confirming the outline approves its *shape* (section headings), not its findings. As the very next step after Phase 2 creates the file, fill in every section with real content **by running the `/hs-res` method** (SpexCrawl gather via the Companion + DeepSeek synthesis — see `.claude/commands/hs-res.md`); **never author the research yourself in the main session** — main-session self-research skips the routed research seats and burns the expensive model on work the fleet owns. Do not report the research as complete, and do not move on to `/hs-promote-research`, until the TBD placeholders are gone. (`heyspex_promote_research` mechanically refuses with `RESEARCH_STILL_STUB` while any remain, but don't rely on that gate — write the research because it's the point of the flow, not because a check will otherwise fail.)
42
+
43
+ **3. Report the result** — the research id (created or extended) or diagnose id created, and confirm the capture(s)' `promoted_to` now points at it.
44
+
45
+ ---
46
+
47
+ ## §A2. Research → milestone (`HS-RES-*`)
48
+
49
+ **1. Parse the rest of `$ARGUMENTS`:**
50
+ - `research_id` is the leading `HS-RES-*` token (already identified in Step 0).
51
+ - Next word matching `spawn|augment|both` → `intent`. Default `spawn` when omitted.
52
+ - Next token: `HS-MIL-[A-Z0-9-]{3,}` → `target_milestone` = that id. Or the literal word `new`/`NEW` (also the default when this token is omitted entirely) → `target_milestone = "NEW"`; remaining words → `new_milestone_name`.
53
+ - If `intent` includes `augment`, any remaining `HS-EPIC-[A-Z0-9-]{3,}` tokens → `augment_epic_ids` (required in that case — ask for them if `augment` was requested but none were given).
54
+
55
+ **2. Default policy:** `target_milestone: "NEW"` unless the user names an **existing `status: open`** milestone that clearly extends the same thesis. Spawning into an `in_progress` milestone is blocked unless the owner explicitly passes `attach_to_in_progress_milestone: true` + `attach_override_reason` (≥40 chars audit trail) — never default to this path or infer the override on the agent's own judgment.
56
+
57
+ **3. Phase 1 — proposal.** Call `heyspex_promote_research({ research_id, target_milestone, new_milestone_name?, intent, spawn_epic_count?, augment_epic_ids? })` **without** `accepted_stubs`. Show the user the returned `proposed_stubs[]` and let them edit/remove/approve.
58
+ - **If `ai_proposal.ok === false` (e.g. `reason: "no_api_key"`), `proposed_stubs` comes back empty — the agent must author the stubs itself.** This is NOT a shortcut to skip the confirm step; it makes the confirm step *more* necessary, not less, because nothing upstream has vetted these stubs yet. Author them from the research doc's actual content, present them to the user exactly as you would an AI proposal (name/kind/effort/rationale per stub), and wait for a real approval turn before calling Phase 2. **Do not call Phase 2 in the same turn you authored the stubs in** — that is precisely the failure this line exists to prevent (observed 2026-08-12: an agent self-authored 3 epic stubs and executed `accepted_stubs` in the same tool-call batch with no human turn in between).
59
+ - **Check the stubs against the SOURCE CAPTURE's own Notes before presenting them.** Before showing `proposed_stubs` (AI-proposed or agent-authored) to the user, walk every verbatim quote in the source capture's `## Notes` — the capture(s) named in the research doc's `sources_captures`, not just the research doc's own prose, since a two-hop drift can lose fidelity the research doc's text won't show — and confirm each is addressed by a stub or explicitly named as out of scope. This check caught two real gaps missed by an agent-authored stub list in this vault's own history ([[HS-GDT5-F16L-DIAG-promote-flow-drafts-research-and-stubs]]).
60
+
61
+ **4. Phase 2 — execute (after human confirms).** Call again with the same args plus `accepted_stubs: [...]` (the confirmed, possibly-edited subset) to perform the transactional write.
62
+
63
+ **5. Report the result** — the milestone id (new or existing) plus spawned epic ids, or the augmented epic ids. Note that research stays `status: open` (research is evergreen) — only its `enhances:`/`spawned_epics:` links change.
64
+
65
+ ---
66
+
67
+ ## Hard prohibitions
68
+
69
+ - **Never** execute a Phase-2 write (`accepted_outline` or `accepted_stubs`) without the human having seen and confirmed the Phase-1 proposal. For `accepted_stubs` the tool now refuses this mechanically: the proposal turn leaves a marker keyed on the research id, and an execute turn without one returns `STUB_REVIEW_REQUIRED`. If the human replaced every proposed stub, pass `stub_edit_note` (≥40 chars) saying what they changed — otherwise a fully-drifted execute returns `STUB_REVIEW_DRIFT`. As with `RESEARCH_STILL_STUB`, treat the mechanical refusal as the backstop, not the first line of defense.
70
+ - **Never** call `heyspex_promote_research` against a research doc that still carries `_TBD — fill in this section._` placeholders — fill it in via the `/hs-res` method first (§A step 2 above), never by authoring the research yourself in the main session. The tool refuses this mechanically (`RESEARCH_STILL_STUB`) but the agent should never rely on that as the first line of defense.
71
+ - **Never** route a bug-fix capture through `heyspex_promote_capture` — it goes to `heyspex_promote_capture_to_diagnose` instead.
72
+ - **Never** attach a research promote to an `in_progress` milestone without an explicit owner override (`attach_to_in_progress_milestone` + `attach_override_reason`).
73
+ - **Never** commit or push.
@@ -7,32 +7,32 @@ description: Push an epic implementation plan into the HeySpex vault, optionally
7
7
 
8
8
  **Usage:** `/hs-push [<epic name>] [--next] [--reason <focus reason>]`
9
9
 
10
- > **Platform asymmetry — read this, it is load-bearing.** Claude Code delivers only the **first whitespace token** of an MCP prompt's argument (GitHub [#14210](https://github.com/anthropics/claude-code/issues/14210), closed *not planned*), so the namespaced MCP prompts `/hs-push` / `/hs-push-next` can each carry at most a single token — never an epic name plus a `--next` flag plus a focus reason together. This **native project command** is the only IDE surface that receives full `$ARGUMENTS`. It also **consolidates** the old two-prompt split (`hs-push` vs `hs-push-next`) into one command: both ultimately call the same `heyspex_push_plan` tool with only `on_deck` differing, so there is no behavior lost by merging them here — just one flag instead of two command names.
11
-
12
- ## What to do
13
-
14
- **1. Parse `$ARGUMENTS`:**
15
- - `--next` (anywhere, case-insensitive) → `on_deck = true`. Absent → `on_deck = false` (file the epic without pinning focus).
16
- - `--reason <text>` → `focus_reason` (only meaningful when `on_deck` is true; rest of that flag's value up to the next `--` flag or end of string).
17
- - Remaining leading, non-flag text → an `epic_name` hint. Optional — if omitted, derive the title from the plan under discussion in chat.
18
-
19
- **2. Gather the rest of the payload from the conversation** (a Cursor/proprietary `.plan.md` the user pasted or referenced, or a plan already discussed in chat):
20
- - `summary` — required plain-language frontmatter summary (spec-summary-authoring contract).
21
- - `plan_markdown` — epic body markdown (goal, phases, acceptance criteria).
22
- - `milestone` — **required**: the parent `HS-MIL-*` wikilink. Ask the user if it isn't obvious from context; the tool call fails without it.
23
- - `source_plan_paths` — any `.plan.md` file paths referenced (auto-detected from `plan_markdown` too).
24
- - `kind` / `effort` / `tags` / `related` — optional scheduler/classification fields.
25
-
26
- **3. Call** `heyspex_push_plan({ epic_name, summary, plan_markdown, milestone, on_deck, focus_reason?, source_plan_paths?, kind?, effort?, tags?, related? })`. This writes the epic **only** — `children: []`; tasks are never filed here, only later via `/hs-next` breakdown.
27
-
28
- **4. After the call:**
29
- - `on_deck: true` → the epic is set `in_progress`, `.heyspex/focus.yaml` is written, and a NEXT STEP block is added. Tell the user to run `/hs-next` next.
30
- - `on_deck: false` → tell the user to re-run `/hs-push --next` (or `/hs-next <the new epic id>`) when ready to start work.
31
-
32
- **5. Conflict handling:** if the tool returns a behavioral-conflict block against `related` specs and `on_deck` was requested, the write is blocked by default (no files written, no focus pinned). Surface the conflicts to the user — only pass `skip_conflict_check: true` on their explicit say-so, and note a `conflict_override` should be recorded afterward.
33
-
34
- ## Hard prohibitions
35
-
36
- - **Never** file tasks here — epics only (`children: []`); tasks are just-in-time via `/hs-next` breakdown.
37
- - **Never** silently bypass a conflict block — surface it and let the human decide.
38
- - **Never** commit or push git.
10
+ > **Platform asymmetry — read this, it is load-bearing.** Claude Code delivers only the **first whitespace token** of an MCP prompt's argument (GitHub [#14210](https://github.com/anthropics/claude-code/issues/14210), closed *not planned*), so the namespaced MCP prompts `/hs-push` / `/hs-push-next` can each carry at most a single token — never an epic name plus a `--next` flag plus a focus reason together. This **native project command** is the only IDE surface that receives full `$ARGUMENTS`. It also **consolidates** the old two-prompt split (`hs-push` vs `hs-push-next`) into one command: both ultimately call the same `heyspex_push_plan` tool with only `on_deck` differing, so there is no behavior lost by merging them here — just one flag instead of two command names.
11
+
12
+ ## What to do
13
+
14
+ **1. Parse `$ARGUMENTS`:**
15
+ - `--next` (anywhere, case-insensitive) → `on_deck = true`. Absent → `on_deck = false` (file the epic without pinning focus).
16
+ - `--reason <text>` → `focus_reason` (only meaningful when `on_deck` is true; rest of that flag's value up to the next `--` flag or end of string).
17
+ - Remaining leading, non-flag text → an `epic_name` hint. Optional — if omitted, derive the title from the plan under discussion in chat.
18
+
19
+ **2. Gather the rest of the payload from the conversation** (a Cursor/proprietary `.plan.md` the user pasted or referenced, or a plan already discussed in chat):
20
+ - `summary` — required plain-language frontmatter summary (spec-summary-authoring contract).
21
+ - `plan_markdown` — epic body markdown (goal, phases, acceptance criteria).
22
+ - `milestone` — **required**: the parent `HS-MIL-*` wikilink. Ask the user if it isn't obvious from context; the tool call fails without it.
23
+ - `source_plan_paths` — any `.plan.md` file paths referenced (auto-detected from `plan_markdown` too).
24
+ - `kind` / `effort` / `tags` / `related` — optional scheduler/classification fields.
25
+
26
+ **3. Call** `heyspex_push_plan({ epic_name, summary, plan_markdown, milestone, on_deck, focus_reason?, source_plan_paths?, kind?, effort?, tags?, related? })`. This writes the epic **only** — `children: []`; tasks are never filed here, only later via `/hs-next` breakdown.
27
+
28
+ **4. After the call:**
29
+ - `on_deck: true` → the epic is set `in_progress`, `.heyspex/focus.yaml` is written, and a NEXT STEP block is added. Tell the user to run `/hs-next` next.
30
+ - `on_deck: false` → tell the user to re-run `/hs-push --next` (or `/hs-next <the new epic id>`) when ready to start work.
31
+
32
+ **5. Conflict handling:** if the tool returns a behavioral-conflict block against `related` specs and `on_deck` was requested, the write is blocked by default (no files written, no focus pinned). Surface the conflicts to the user — only pass `skip_conflict_check: true` on their explicit say-so, and note a `conflict_override` should be recorded afterward.
33
+
34
+ ## Hard prohibitions
35
+
36
+ - **Never** file tasks here — epics only (`children: []`); tasks are just-in-time via `/hs-next` breakdown.
37
+ - **Never** silently bypass a conflict block — surface it and let the human decide.
38
+ - **Never** commit or push git.
@@ -7,24 +7,24 @@ description: Post-plan QC gut-check — stress-test a drafted plan before execut
7
7
 
8
8
  **Usage:** `/hs-qc [--plan <path>] (defaults to the most recent plan)`
9
9
 
10
- > **Where this sits.** `/hs-ground` (pre-plan) → draft → `heyspex_plan_review` → **`/hs-qc`** → `ExitPlanMode`. Both plan-review + QC markers required ([[HS-R4OY]]).
11
-
12
- ## What to do
13
-
14
- **0. Mandatory drift passes** — Axis A (as-built code) + Axis B (design supersession per [[drift-is-two-axes-as-built-and-design-supersession]]). Re-run `heyspex_plan_review`; read `axis_b_drift`. Do not trust parent epic AC over newer memory decisions.
15
-
16
- **0b. When `axis_b_drift` is non-empty — ask the user before recording QC:**
17
-
18
- Present each conflict. **Default (Recommended):** re-scope the plan (remove dead work). **Override:** user explicitly confirms proceed anyway → `heyspex_plan_qc({ axis_b_user_confirmed: true, axis_b_confirmation_note: "…" })`. Tool returns `QC_AXIS_B_DRIFT` until resolved or user-confirmed. **The override is currently broken** per [[HS-EP8E-C1L2-DIAG-heyspex-plan-qc-override-path-ignores-ax]] (reproduced twice) — until fixed, `HEYSPEX_PLAN_QC_GATE_OFF=1` is the only working escape, and its use should be reported to the owner.
19
-
20
- **1. Run the gut-check (verbatim — the owner's standard).**
21
-
22
- Wonderful work! Can you please do a quality check and a gut-check? … *(full questions unchanged)*
23
-
24
- **2. Act on what you find.** Fold findings into the plan; re-run `heyspex_plan_review` if material.
25
-
26
- **3. Record Proof-of-Use.** `heyspex_plan_qc` with substantive `findings_summary` including **`Axis B:`** line.
27
-
28
- **4. Then `ExitPlanMode`.**
29
-
30
- (Break-glass: `HEYSPEX_PLAN_QC_GATE_OFF=1`.)
10
+ > **Where this sits.** `/hs-ground` (pre-plan) → draft → `heyspex_plan_review` → **`/hs-qc`** → `ExitPlanMode`. Both plan-review + QC markers required ([[HS-R4OY]]).
11
+
12
+ ## What to do
13
+
14
+ **0. Mandatory drift passes** — Axis A (as-built code) + Axis B (design supersession per [[drift-is-two-axes-as-built-and-design-supersession]]). Re-run `heyspex_plan_review`; read `axis_b_drift`. Do not trust parent epic AC over newer memory decisions.
15
+
16
+ **0b. When `axis_b_drift` is non-empty — ask the user before recording QC:**
17
+
18
+ Present each conflict. **Default (Recommended):** re-scope the plan (remove dead work). **Override:** user explicitly confirms proceed anyway → `heyspex_plan_qc({ axis_b_user_confirmed: true, axis_b_confirmation_note: "…" })`. Tool returns `QC_AXIS_B_DRIFT` until resolved or user-confirmed. **The override is currently broken** per [[HS-EP8E-C1L2-DIAG-heyspex-plan-qc-override-path-ignores-ax]] (reproduced twice) — until fixed, `HEYSPEX_PLAN_QC_GATE_OFF=1` is the only working escape, and its use should be reported to the owner.
19
+
20
+ **1. Run the gut-check (verbatim — the owner's standard).**
21
+
22
+ Wonderful work! Can you please do a quality check and a gut-check? … *(full questions unchanged)*
23
+
24
+ **2. Act on what you find.** Fold findings into the plan; re-run `heyspex_plan_review` if material.
25
+
26
+ **3. Record Proof-of-Use.** `heyspex_plan_qc` with substantive `findings_summary` including **`Axis B:`** line.
27
+
28
+ **4. Then `ExitPlanMode`.**
29
+
30
+ (Break-glass: `HEYSPEX_PLAN_QC_GATE_OFF=1`.)
@@ -36,20 +36,32 @@ description: Confidence-ladder research method's entrypoint — SpexCrawl via th
36
36
  2026-08-22).** When the SpexCrawl path malfunctions, times out, hits a gate, or is otherwise
37
37
  unavailable, fall back immediately: `node dev-factory/spexcrawl/firecrawl-cli.mjs
38
38
  search "<query>" --json` and `node dev-factory/spexcrawl/firecrawl-cli.mjs scrape
39
- "<url>" --json`. May run on any fleet machine (coffee-geek, basement-geek, spec-ops) —
39
+ "<url>" --json`. May run on any self-hosted fleet machine or this machine's own Docker —
40
40
  prefer other reachable machines over the one the orchestrating session runs on; check
41
41
  `docker info`, start Docker/the stack if needed, poll the real endpoint for readiness before
42
42
  use. If this task's changed/claimed files are SpexCrawl-related, skip SpexCrawl entirely and
43
43
  go straight to Firecrawl. Hosted `api.firecrawl.dev` credits are unchanged — still
44
44
  ask-before-spend every time. Full contract: `.commandcode/skills/hs-res/SKILL.md`.
45
45
 
46
- **In a repo that uses the `heyspex` npm package** (not a HeySpex platform checkout): the
47
- package ships only the SpexCrawl client (`dev-factory/spexcrawl/spexcrawl-cli.mjs` under
48
- `node_modules/heyspex/`). It needs the HeySpex Companion, which the npm package does not
49
- distribute yet, so it usually exits 3 `SPEXCRAWL_UNAVAILABLE`. The Firecrawl fallback and
50
- the DeepSeek synthesis CLI (`firecrawl-cli.mjs`, `synthesize-cli.mjs`) are HeySpex-platform
51
- only and are not in the package. When a CLI named in steps 2 or 4 is missing or reports
52
- unavailable, stop and tell the user this research method is not available in their install.
46
+ **In a repo that uses the `heyspex` npm package** (not a HeySpex platform checkout — the
47
+ CLIs above resolve under `node_modules/heyspex/`; owner ruling 2026-10-17). Prerequisite:
48
+ Docker Desktop running a self-hosted Firecrawl stack on this machine. No env var and no API
49
+ key: the Firecrawl CLI finds it by itself (`docker ps`, then localhost:3002). The method is
50
+ Firecrawl for URLs, SpexCrawl for pages, your own model for the write-up:
51
+ 1. **Find URLs** — `node dev-factory/spexcrawl/firecrawl-cli.mjs search "<query>" --json`
52
+ per angle.
53
+ 2. **Fetch every URL you will cite** with SpexCrawl:
54
+ `node dev-factory/spexcrawl/spexcrawl-cli.mjs scrape "<url>" --json`.
55
+ SpexCrawl needs the HeySpex Companion; when it exits 3
56
+ `SPEXCRAWL_UNAVAILABLE`, fetch the same URL from the same local Firecrawl:
57
+ `node dev-factory/spexcrawl/firecrawl-cli.mjs scrape "<url>" --json`.
58
+ 3. **Synthesize yourself** — skip steps 3–4 below (the DeepSeek CLI `synthesize-cli.mjs` is
59
+ HeySpex-platform only and not in the package). From the fetched pages only, write a
60
+ cited **Executive Summary** (every claim tagged `[S1]`, `[S2]`, …) and a numbered
61
+ **Sources** list (title + URL per `[Sn]`).
62
+ 4. **Save** as in step 5, `sources` filled from the fetched URLs.
63
+ If the Firecrawl CLI exits 3 `FIRECRAWL_UNAVAILABLE`, stop and relay its message to the
64
+ user (it says to start Docker Desktop and the Firecrawl stack, with the steps).
53
65
 
54
66
  3. **Assemble a numbered sources block** (`[S1]`, `[S2]`, …) from the gathered
55
67
  `{title, url, snippet, markdown}` results, write it plus the question and cite-only
@@ -7,20 +7,20 @@ description: Pull the top open item from the HeySpex Resolution lane (conflicts,
7
7
 
8
8
  **Usage:** `/hs-resolve [HS-XXXX-EPIC | <item-key> | --ignore-focus]`
9
9
 
10
- Invoke the `heyspex_next_resolution` MCP tool to fetch the top open resolution item from the HeySpex vault, then paste the returned `prompt_markdown` verbatim so the user can act on the fix brief.
11
-
12
- Argument parsing for `$ARGUMENTS` (all optional; if empty, call the tool with no parameters):
13
-
14
- - A token containing `:` (e.g. `dangling_ref:hs-epic-x:hs-task-y`) → pass as `item_key` (fetch that specific item's brief; bypasses the focus pin).
15
- - A bare spec id matching `HS-EPIC-*` / `HS-TASK-*` / `HS-MIL-*` / `HS-*-*` → pass as `scope` (deck-aware: restrict detection to that spec so its gating prerequisite/conflicts surface). This is what the On-Deck `resolve_command: /hs-resolve <epic-id>` passes.
16
- - `--ignore-focus` → set `ignore_focus: true` (skip the Neon resolution focus pin; lead with the top-ranked open item).
17
-
18
- Resolution precedence (built into the tool — do not re-implement): `item_key` → `scope`/`ignore_focus` (top-ranked of the open list) → the Neon focus pin (server-applied) → top-ranked open item. Items are ordered with **gating** and **errors first** (`orderResolutionItems`).
19
-
20
- After the tool returns, output the `prompt_markdown` field as-is, then on a final line state the source: `_Source: {source} · {item.kind} · {item.key}_`. Do not summarize, paraphrase, or start executing actions from the brief without the user's go-ahead.
21
-
22
- This is the surviving `/hs-resolve` (the legacy conflict-only prompt that errored **"Not an Epic"** on a milestone has been retired — the resolver is item-centric and never type-checks the target). Authority from the brief's resolution menu: **Re-scan / clear** is agent-autonomous; **Switch to this**, **Defer**, **edge removal**, and **override** require explicit user confirmation. `stale_index` items expose **only** re-scan/clear — never an edge-mutating action.
23
-
24
- Detection is HTTP-only (the tool reads the console aggregator — the one detection path — it does not re-detect). If the tool errors with `CONSOLE_UNREACHABLE`, tell the user to **start the console dev server (port 3000, or run `hs server status` to see which port it actually bound)** — this only happens on a dev machine; SaaS console is always up. On `CONSOLE_TIMEOUT`, suggest retrying shortly (the server may be cold-compiling). On `ITEM_NOT_FOUND`, the `item_key` is not in the open set — list items with `/hs-resolve` (no args).
25
-
26
- This skill does NOT claim or build anything; it presents the fix brief. Sibling skills: `/hs-next` (build pipeline), `/hs-review` (review pipeline), `/hs-resolve` (this — resolution lane). See [[HS-0EJ6-RMCP-EPIC-hs-resolve-mcp-tool-and-skill]] and [[HS-I8FM-RSRF-EPIC-resolution-surface-api-and-pin]].
10
+ Invoke the `heyspex_next_resolution` MCP tool to fetch the top open resolution item from the HeySpex vault, then paste the returned `prompt_markdown` verbatim so the user can act on the fix brief.
11
+
12
+ Argument parsing for `$ARGUMENTS` (all optional; if empty, call the tool with no parameters):
13
+
14
+ - A token containing `:` (e.g. `dangling_ref:hs-epic-x:hs-task-y`) → pass as `item_key` (fetch that specific item's brief; bypasses the focus pin).
15
+ - A bare spec id matching `HS-EPIC-*` / `HS-TASK-*` / `HS-MIL-*` / `HS-*-*` → pass as `scope` (deck-aware: restrict detection to that spec so its gating prerequisite/conflicts surface). This is what the On-Deck `resolve_command: /hs-resolve <epic-id>` passes.
16
+ - `--ignore-focus` → set `ignore_focus: true` (skip the Neon resolution focus pin; lead with the top-ranked open item).
17
+
18
+ Resolution precedence (built into the tool — do not re-implement): `item_key` → `scope`/`ignore_focus` (top-ranked of the open list) → the Neon focus pin (server-applied) → top-ranked open item. Items are ordered with **gating** and **errors first** (`orderResolutionItems`).
19
+
20
+ After the tool returns, output the `prompt_markdown` field as-is, then on a final line state the source: `_Source: {source} · {item.kind} · {item.key}_`. Do not summarize, paraphrase, or start executing actions from the brief without the user's go-ahead.
21
+
22
+ This is the surviving `/hs-resolve` (the legacy conflict-only prompt that errored **"Not an Epic"** on a milestone has been retired — the resolver is item-centric and never type-checks the target). Authority from the brief's resolution menu: **Re-scan / clear** is agent-autonomous; **Switch to this**, **Defer**, **edge removal**, and **override** require explicit user confirmation. `stale_index` items expose **only** re-scan/clear — never an edge-mutating action.
23
+
24
+ Detection is HTTP-only (the tool reads the console aggregator — the one detection path — it does not re-detect). If the tool errors with `CONSOLE_UNREACHABLE`, tell the user to **start the console dev server (port 3000, or run `hs server status` to see which port it actually bound)** — this only happens on a dev machine; SaaS console is always up. On `CONSOLE_TIMEOUT`, suggest retrying shortly (the server may be cold-compiling). On `ITEM_NOT_FOUND`, the `item_key` is not in the open set — list items with `/hs-resolve` (no args).
25
+
26
+ This skill does NOT claim or build anything; it presents the fix brief. Sibling skills: `/hs-next` (build pipeline), `/hs-review` (review pipeline), `/hs-resolve` (this — resolution lane). See [[HS-0EJ6-RMCP-EPIC-hs-resolve-mcp-tool-and-skill]] and [[HS-I8FM-RSRF-EPIC-resolution-surface-api-and-pin]].
@@ -7,26 +7,26 @@ description: Open one console surface in a chromeless app-mode browser window (s
7
7
 
8
8
  **Usage:** `/hs-view [surface] [doc id] [--width N] [--height N] [--browser edge|chrome]`
9
9
 
10
- # HeySpex solo-surface viewer (`/hs-view`)
11
-
12
- > Parity: `.commandcode/skills/hs-view/SKILL.md` · `.cursor/skills/hs-view/SKILL.md` · `.agents/skills/hs-view/SKILL.md`
13
-
14
- Optional macro over the one core ([[capability-three-faces-no-per-capability-slash]]): shell to `hs view`, never reimplement it. Design: [[HS-RU2R-I87U-RES-solo-surface-cli-launcher-single]].
15
-
16
- ## What to do
17
-
18
- 1. **Resolve `$ARGUMENTS` by smart first-token detection** — grammar is positional, token-identical with the CLI:
19
- - First token is not a surface slug → it is the doc id, in any form (`hlfj`, `hs-hlfj`, `HS-HLFJ`, a full basename); opens the inspector on its Pipeline tab. Pass it through as typed — the CLI normalises it.
20
- - First token is a surface slug (`inspector`, `docs`, `whats-next`, `captures`, `session-log`, `settings`) → second token, if present, is the doc id (anchors `inspector` and `docs` only).
21
- - `pipeline` is accepted but is not its own window: it is the inspector on its Pipeline tab.
22
- - `docs` opens two panes: the doc beside the inspector on its Pipeline tab.
23
- - No arguments → the inspector on its Pipeline tab, anchored on the focus pin (live-follow).
24
- - Pass `--width` / `--height` / `--browser edge|chrome` through unchanged.
25
- 2. **Run it yourself** from the repo root:
26
- ```bash
27
- node bin/hs.mjs view [<surface>] [<doc-id>] [flags]
28
- ```
29
- 3. The verb probes ground-truth dev-server status first — if the console is down, relay its message and offer `npm run dev` (don't start the server unprompted).
30
- 4. Relay the one-line result (URL + window size); closing the window closes it, re-running reopens it.
31
-
32
- Never hand-build `msedge --app=…` invocations — the CLI verb owns server probing, URL resolution, and browser mechanics.
10
+ # HeySpex solo-surface viewer (`/hs-view`)
11
+
12
+ > Parity: `.commandcode/skills/hs-view/SKILL.md` · `.cursor/skills/hs-view/SKILL.md` · `.agents/skills/hs-view/SKILL.md`
13
+
14
+ Optional macro over the one core ([[capability-three-faces-no-per-capability-slash]]): shell to `hs view`, never reimplement it. Design: [[HS-RU2R-I87U-RES-solo-surface-cli-launcher-single]].
15
+
16
+ ## What to do
17
+
18
+ 1. **Resolve `$ARGUMENTS` by smart first-token detection** — grammar is positional, token-identical with the CLI:
19
+ - First token is not a surface slug → it is the doc id, in any form (`hlfj`, `hs-hlfj`, `HS-HLFJ`, a full basename); opens the inspector on its Pipeline tab. Pass it through as typed — the CLI normalises it.
20
+ - First token is a surface slug (`inspector`, `docs`, `whats-next`, `captures`, `session-log`, `settings`) → second token, if present, is the doc id (anchors `inspector` and `docs` only).
21
+ - `pipeline` is accepted but is not its own window: it is the inspector on its Pipeline tab.
22
+ - `docs` opens two panes: the doc beside the inspector on its Pipeline tab.
23
+ - No arguments → the inspector on its Pipeline tab, anchored on the focus pin (live-follow).
24
+ - Pass `--width` / `--height` / `--browser edge|chrome` through unchanged.
25
+ 2. **Run it yourself** from the repo root:
26
+ ```bash
27
+ node bin/hs.mjs view [<surface>] [<doc-id>] [flags]
28
+ ```
29
+ 3. The verb probes ground-truth dev-server status first — if the console is down, relay its message and offer `npm run dev` (don't start the server unprompted).
30
+ 4. Relay the one-line result (URL + window size); closing the window closes it, re-running reopens it.
31
+
32
+ Never hand-build `msedge --app=…` invocations — the CLI verb owns server probing, URL resolution, and browser mechanics.
@@ -7,29 +7,29 @@ description: Kill every process listening on a TCP port in the range 3000–5999
7
7
 
8
8
  **Usage:** `/kill-ports (no arguments)`
9
9
 
10
- **Always use the PowerShell tool for this command — never the Bash tool.** Bash routes to a POSIX shell in this environment and the PowerShell syntax below will fail there.
11
-
12
- Kill all processes that are **listening** on TCP ports in the range **3000–5999** inclusive. This clears orphaned dev servers (Next.js, console, companion bridges, etc.) that are holding ports.
13
-
14
- Run this single command via the **PowerShell** tool. It discovers the listening connections in range, reports each `port → pid (process name)` it is about to kill, then force-kills the unique owning PIDs and confirms:
15
-
16
- ```powershell
17
- $conns = Get-NetTCPConnection -State Listen -ErrorAction SilentlyContinue |
18
- Where-Object { $_.LocalPort -ge 3000 -and $_.LocalPort -le 5999 }
19
- if (-not $conns) { Write-Output 'No listeners on ports 3000-5999. Nothing to kill.'; return }
20
- $pids = $conns | Select-Object -ExpandProperty OwningProcess -Unique
21
- foreach ($c in $conns) {
22
- $p = Get-Process -Id $c.OwningProcess -ErrorAction SilentlyContinue
23
- $name = if ($p) { $p.ProcessName } else { '?' }
24
- Write-Output ("port {0,-5} -> pid {1} ({2})" -f $c.LocalPort, $c.OwningProcess, $name)
25
- }
26
- foreach ($procId in $pids) {
27
- try { Stop-Process -Id $procId -Force -ErrorAction Stop; Write-Output ("killed pid {0}" -f $procId) }
28
- catch { Write-Output ("could not kill pid {0}: {1}" -f $procId, $_.Exception.Message) }
29
- }
30
- ```
31
-
32
- Notes:
33
- - Only TCP **listeners** are targeted, so client/outbound connections in that range are left alone.
34
- - If `Stop-Process` fails on a PID (e.g. a Windows system process like `svchost`, which needs admin and shouldn't be killed anyway, or a process that already exited), report the `Access is denied` / error and continue with the rest — do not abort the whole run.
35
- - After running, briefly summarize how many ports were freed.
10
+ **Always use the PowerShell tool for this command — never the Bash tool.** Bash routes to a POSIX shell in this environment and the PowerShell syntax below will fail there.
11
+
12
+ Kill all processes that are **listening** on TCP ports in the range **3000–5999** inclusive. This clears orphaned dev servers (Next.js, console, companion bridges, etc.) that are holding ports.
13
+
14
+ Run this single command via the **PowerShell** tool. It discovers the listening connections in range, reports each `port → pid (process name)` it is about to kill, then force-kills the unique owning PIDs and confirms:
15
+
16
+ ```powershell
17
+ $conns = Get-NetTCPConnection -State Listen -ErrorAction SilentlyContinue |
18
+ Where-Object { $_.LocalPort -ge 3000 -and $_.LocalPort -le 5999 }
19
+ if (-not $conns) { Write-Output 'No listeners on ports 3000-5999. Nothing to kill.'; return }
20
+ $pids = $conns | Select-Object -ExpandProperty OwningProcess -Unique
21
+ foreach ($c in $conns) {
22
+ $p = Get-Process -Id $c.OwningProcess -ErrorAction SilentlyContinue
23
+ $name = if ($p) { $p.ProcessName } else { '?' }
24
+ Write-Output ("port {0,-5} -> pid {1} ({2})" -f $c.LocalPort, $c.OwningProcess, $name)
25
+ }
26
+ foreach ($procId in $pids) {
27
+ try { Stop-Process -Id $procId -Force -ErrorAction Stop; Write-Output ("killed pid {0}" -f $procId) }
28
+ catch { Write-Output ("could not kill pid {0}: {1}" -f $procId, $_.Exception.Message) }
29
+ }
30
+ ```
31
+
32
+ Notes:
33
+ - Only TCP **listeners** are targeted, so client/outbound connections in that range are left alone.
34
+ - If `Stop-Process` fails on a PID (e.g. a Windows system process like `svchost`, which needs admin and shouldn't be killed anyway, or a process that already exited), report the `Access is denied` / error and continue with the rest — do not abort the whole run.
35
+ - After running, briefly summarize how many ports were freed.