@sayknow-cli/coding-agent 0.2.4 → 0.2.5

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 (149) hide show
  1. package/dist/types/cli/migrate-cli.d.ts +20 -0
  2. package/dist/types/cli/update-cli.d.ts +3 -0
  3. package/dist/types/commands/migrate.d.ts +33 -0
  4. package/dist/types/config/keybindings.d.ts +4 -0
  5. package/dist/types/config/model-registry.d.ts +3 -0
  6. package/dist/types/config/models-config-schema.d.ts +5 -0
  7. package/dist/types/config/settings-schema.d.ts +27 -0
  8. package/dist/types/harness-control-plane/storage.d.ts +2 -1
  9. package/dist/types/hooks/skill-state.d.ts +12 -4
  10. package/dist/types/lsp/startup-events.d.ts +1 -0
  11. package/dist/types/migrate/action-planner.d.ts +11 -0
  12. package/dist/types/migrate/adapters/claude-code.d.ts +2 -0
  13. package/dist/types/migrate/adapters/codex.d.ts +5 -0
  14. package/dist/types/migrate/adapters/index.d.ts +45 -0
  15. package/dist/types/migrate/adapters/opencode.d.ts +2 -0
  16. package/dist/types/migrate/executor.d.ts +2 -0
  17. package/dist/types/migrate/mcp-mapper.d.ts +20 -0
  18. package/dist/types/migrate/report.d.ts +18 -0
  19. package/dist/types/migrate/skill-normalizer.d.ts +27 -0
  20. package/dist/types/migrate/types.d.ts +126 -0
  21. package/dist/types/modes/components/custom-editor.d.ts +1 -1
  22. package/dist/types/modes/components/welcome.d.ts +3 -1
  23. package/dist/types/modes/interactive-mode.d.ts +3 -0
  24. package/dist/types/modes/prompt-action-autocomplete.d.ts +1 -0
  25. package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +1 -1
  26. package/dist/types/research-plan/index.d.ts +1 -0
  27. package/dist/types/research-plan/ledger.d.ts +33 -0
  28. package/dist/types/rlm/artifacts.d.ts +1 -1
  29. package/dist/types/runtime-mcp/config-writer.d.ts +26 -0
  30. package/dist/types/skc-runtime/deep-interview-recorder.d.ts +2 -0
  31. package/dist/types/skc-runtime/deep-interview-runtime.d.ts +2 -2
  32. package/dist/types/skc-runtime/goal-mode-request.d.ts +1 -1
  33. package/dist/types/skc-runtime/session-layout.d.ts +59 -0
  34. package/dist/types/skc-runtime/session-resolution.d.ts +47 -0
  35. package/dist/types/skc-runtime/state-graph.d.ts +1 -1
  36. package/dist/types/skc-runtime/state-runtime.d.ts +5 -4
  37. package/dist/types/skc-runtime/state-schema.d.ts +2 -0
  38. package/dist/types/skc-runtime/state-writer.d.ts +36 -7
  39. package/dist/types/skc-runtime/tmux-sessions.d.ts +2 -0
  40. package/dist/types/skc-runtime/ultragoal-runtime.d.ts +7 -4
  41. package/dist/types/skc-runtime/workflow-command-ref.d.ts +1 -1
  42. package/dist/types/skc-runtime/workflow-manifest.d.ts +1 -1
  43. package/dist/types/skill-state/active-state.d.ts +6 -11
  44. package/dist/types/skill-state/canonical-skills.d.ts +3 -0
  45. package/dist/types/skill-state/deep-interview-mutation-guard.d.ts +5 -0
  46. package/dist/types/skill-state/workflow-hud.d.ts +2 -0
  47. package/dist/types/task/spawn-gate.d.ts +1 -10
  48. package/package.json +7 -7
  49. package/scripts/build-binary.ts +0 -7
  50. package/src/cli/migrate-cli.ts +106 -0
  51. package/src/cli/setup-cli.ts +14 -1
  52. package/src/cli/update-cli.ts +53 -3
  53. package/src/cli.ts +1 -0
  54. package/src/commands/deep-interview.ts +2 -2
  55. package/src/commands/launch.ts +1 -1
  56. package/src/commands/migrate.ts +46 -0
  57. package/src/commands/state.ts +2 -1
  58. package/src/commands/team.ts +7 -3
  59. package/src/config/model-registry.ts +9 -2
  60. package/src/config/model-resolver.ts +13 -2
  61. package/src/config/models-config-schema.ts +1 -0
  62. package/src/config/settings-schema.ts +17 -0
  63. package/src/coordinator-mcp/policy.ts +10 -2
  64. package/src/defaults/skc/extensions/grok-cli-vendor/biome.json +0 -1
  65. package/src/defaults/skc/skills/deep-interview/SKILL.md +30 -24
  66. package/src/defaults/skc/skills/ralplan/SKILL.md +10 -4
  67. package/src/defaults/skc/skills/team/SKILL.md +51 -47
  68. package/src/defaults/skc/skills/ultragoal/SKILL.md +17 -13
  69. package/src/exec/bash-executor.ts +3 -1
  70. package/src/extensibility/custom-commands/loader.ts +0 -7
  71. package/src/extensibility/skc-plugins/injection.ts +23 -4
  72. package/src/extensibility/skc-plugins/state.ts +16 -1
  73. package/src/harness-control-plane/storage.ts +14 -4
  74. package/src/hooks/native-skill-hook.ts +38 -12
  75. package/src/hooks/skill-state.ts +178 -83
  76. package/src/internal-urls/docs-index.generated.ts +11 -9
  77. package/src/lsp/startup-events.ts +24 -0
  78. package/src/migrate/action-planner.ts +318 -0
  79. package/src/migrate/adapters/claude-code.ts +39 -0
  80. package/src/migrate/adapters/codex.ts +70 -0
  81. package/src/migrate/adapters/index.ts +277 -0
  82. package/src/migrate/adapters/opencode.ts +52 -0
  83. package/src/migrate/executor.ts +81 -0
  84. package/src/migrate/mcp-mapper.ts +152 -0
  85. package/src/migrate/report.ts +104 -0
  86. package/src/migrate/skill-normalizer.ts +80 -0
  87. package/src/migrate/types.ts +163 -0
  88. package/src/modes/bridge/bridge-mode.ts +2 -2
  89. package/src/modes/components/custom-editor.ts +30 -20
  90. package/src/modes/components/welcome.ts +20 -9
  91. package/src/modes/controllers/input-controller.ts +21 -3
  92. package/src/modes/interactive-mode.ts +27 -19
  93. package/src/modes/prompt-action-autocomplete.ts +11 -1
  94. package/src/modes/rpc/rpc-mode.ts +2 -2
  95. package/src/modes/shared/agent-wire/unattended-audit.ts +3 -2
  96. package/src/prompts/agents/init.md +1 -1
  97. package/src/prompts/system/plan-mode-active.md +1 -1
  98. package/src/prompts/tools/ast-grep.md +1 -1
  99. package/src/prompts/tools/search.md +1 -1
  100. package/src/prompts/tools/task.md +1 -2
  101. package/src/research-plan/index.ts +1 -0
  102. package/src/research-plan/ledger.ts +177 -0
  103. package/src/rlm/artifacts.ts +12 -3
  104. package/src/rlm/index.ts +7 -0
  105. package/src/runtime-mcp/config-writer.ts +46 -0
  106. package/src/session/agent-session.ts +43 -41
  107. package/src/session/session-manager.ts +19 -2
  108. package/src/setup/hermes/templates/operator-instructions.v1.md +8 -0
  109. package/src/setup/hermes-setup.ts +1 -1
  110. package/src/skc-runtime/deep-interview-recorder.ts +51 -18
  111. package/src/skc-runtime/deep-interview-runtime.ts +49 -23
  112. package/src/skc-runtime/goal-mode-request.ts +26 -11
  113. package/src/skc-runtime/launch-tmux.ts +68 -15
  114. package/src/skc-runtime/ralplan-runtime.ts +79 -50
  115. package/src/skc-runtime/session-layout.ts +180 -0
  116. package/src/skc-runtime/session-resolution.ts +217 -0
  117. package/src/skc-runtime/state-graph.ts +1 -2
  118. package/src/skc-runtime/state-migrations.ts +1 -0
  119. package/src/skc-runtime/state-runtime.ts +237 -114
  120. package/src/skc-runtime/state-schema.ts +2 -0
  121. package/src/skc-runtime/state-writer.ts +310 -42
  122. package/src/skc-runtime/team-runtime.ts +43 -19
  123. package/src/skc-runtime/tmux-sessions.ts +43 -2
  124. package/src/skc-runtime/ultragoal-guard.ts +45 -2
  125. package/src/skc-runtime/ultragoal-runtime.ts +121 -41
  126. package/src/skc-runtime/workflow-command-ref.ts +1 -2
  127. package/src/skc-runtime/workflow-manifest.ts +1 -2
  128. package/src/skill-state/active-state.ts +116 -129
  129. package/src/skill-state/canonical-skills.ts +4 -0
  130. package/src/skill-state/deep-interview-mutation-guard.ts +238 -111
  131. package/src/skill-state/workflow-hud.ts +4 -2
  132. package/src/skill-state/workflow-state-contract.ts +3 -3
  133. package/src/slash-commands/builtin-registry.ts +8 -4
  134. package/src/system-prompt.ts +11 -9
  135. package/src/task/agents.ts +1 -22
  136. package/src/task/index.ts +1 -41
  137. package/src/task/spawn-gate.ts +1 -38
  138. package/src/task/types.ts +1 -1
  139. package/src/tools/ask.ts +34 -12
  140. package/src/tools/ast-edit.ts +2 -2
  141. package/src/tools/computer.ts +58 -4
  142. package/src/utils/edit-mode.ts +1 -1
  143. package/dist/types/extensibility/custom-commands/bundled/review/index.d.ts +0 -10
  144. package/src/extensibility/custom-commands/bundled/review/index.ts +0 -456
  145. package/src/prompts/agents/explore.md +0 -58
  146. package/src/prompts/agents/plan.md +0 -49
  147. package/src/prompts/agents/reviewer.md +0 -141
  148. package/src/prompts/agents/task.md +0 -16
  149. package/src/prompts/review-request.md +0 -70
@@ -23,7 +23,7 @@ Ralplan is the consensus planning workflow. It triggers iterative planning with
23
23
  - `--deliberate`: Forces deliberate mode for high-risk work. Adds pre-mortem (3 scenarios) and expanded test planning (unit/integration/e2e/observability). Without this flag, deliberate mode can still auto-enable when the request explicitly signals high risk (auth/security, migrations, destructive changes, production incidents, compliance/PII, public API breakage).
24
24
  - `--architect openai-code`: Use OpenAI code for the Architect pass when OpenAI code CLI is available. Otherwise, briefly note the fallback and keep the default SKC Architect review.
25
25
  - `--critic openai-code`: Use OpenAI code for the Critic pass when OpenAI code CLI is available. Otherwise, briefly note the fallback and keep the default SKC Critic review.
26
- - `--write --stage <type> --stage_n <N> --artifact <markdown file path or markdown string>`: Native artifact write path persisting Planner, Architect, Critic, revision, ADR, and final pending-approval plan markdown under `.skc/plans/ralplan/<run-id>/`. Use this instead of editing `.skc/` files directly.
26
+ - `--write --stage <type> --stage_n <N> --artifact <markdown file path or markdown string>`: Native artifact write path persisting Planner, Architect, Critic, revision, ADR, and final pending-approval plan markdown under `.skc/_session-{sessionid}/plans/ralplan/<run-id>/`. Use this instead of editing `.skc/` files directly.
27
27
 
28
28
  ## Usage with interactive mode
29
29
 
@@ -31,6 +31,10 @@ Ralplan is the consensus planning workflow. It triggers iterative planning with
31
31
  /skill:ralplan --interactive "task description"
32
32
  ```
33
33
 
34
+ ## Corrupt current-session state recovery
35
+
36
+ When ralplan detects its own current-session state is corrupt, tampered, unreadable, or stale on resume, run `skc state clear --force --mode ralplan` before reseeding or restarting. Scope the clear to the current session via `--session-id`, the command payload, or `SKC_SESSION_ID`; it clears only ralplan state for that session and never clears other skills or sessions.
37
+
34
38
  ## Behavior
35
39
 
36
40
  ## Planning/Execution Boundary
@@ -43,7 +47,9 @@ Planning artifacts and stage handoffs MUST be persisted through the ralplan CLI
43
47
  skc ralplan --write --stage <type> --stage_n <N> --artifact "markdown file path or markdown string"
44
48
  ```
45
49
 
46
- Use stage values that match the producer or artifact kind, such as `planner`, `architect`, `critic`, `revision`, `adr`, or `final`. Increment `--stage_n` for each consensus-loop pass. The `--artifact` value may be either a markdown file path prepared outside `.skc/` for ingestion or the markdown content string itself. The native `--write` handler persists markdown under `.skc/plans/ralplan/<run-id>/stage-<NN>-<stage>.md`, maintains an `index.jsonl` audit log, and for `final` stages additionally writes a `pending-approval.md` copy. Direct `write`, `edit`, or `ast_edit` calls against `.skc/specs`, `.skc/plans`, `.skc/state`, or any other `.skc/` path are forbidden unless an explicit force override is active.
50
+ Use stage values that match the producer or artifact kind, such as `planner`, `architect`, `critic`, `revision`, `adr`, or `final`. Increment `--stage_n` for each consensus-loop pass. The `--artifact` value may be either a markdown file path prepared outside `.skc/` for ingestion or the markdown content string itself. The native `--write` handler persists markdown under `.skc/_session-{sessionid}/plans/ralplan/<run-id>/stage-<NN>-<stage>.md`, maintains an `index.jsonl` audit log, and for `final` stages additionally writes a `pending-approval.md` copy. Direct `write`, `edit`, or `ast_edit` calls against `.skc/_session-{sessionid}/specs`, `.skc/_session-{sessionid}/plans`, `.skc/_session-{sessionid}/state`, or any other `.skc/` path are forbidden unless an explicit force override is active.
51
+
52
+ While ralplan is active it is a pre-approval planning phase: product-code mutation tools (`write`/`edit`/`ast_edit`) and product-mutating `bash` (e.g. `tee src/...`, redirects into the project tree) are blocked, exactly like deep-interview. Prefer passing the `--artifact` markdown **inline** (the content string) so no scratch file is needed; this is mandatory for restricted role agents (see below). Only the leader, and only when an artifact is too large to pass inline, may stage it as a file in a system temp directory (`os.tmpdir()`/`$TMPDIR`, `/tmp`, `/var/tmp`) outside the project tree and pass that path — never write scratch files into the repo or `.skc/`. Product code is mutated only after the plan is approved and execution begins.
47
53
 
48
54
  Restricted read-only role agents (`planner`, `architect`, and `critic`) must pass markdown content directly in `--artifact`; their restricted bash environment intentionally disables artifact file-path ingestion so a verdict command cannot persist arbitrary file contents.
49
55
 
@@ -74,7 +80,7 @@ The consensus workflow:
74
80
  d. Return to Critic evaluation
75
81
  e. Repeat this loop until Critic returns `APPROVE` or 5 iterations are reached
76
82
  f. If 5 iterations are reached without `APPROVE`, present the best version to the user
77
- 6. On Critic approval, mark the plan `pending approval` unless explicit execution approval has already been captured, persist the ADR/final plan via `skc ralplan --write --stage final --stage_n <N> --artifact "..."`, and do not directly edit `.skc/plans`. *(--interactive only)* If `--interactive` is set, use the `ask` tool to present the plan with approval options (Approve execution via ultragoal (Recommended) / Approve execution via team (only when tmux-based interactive worker parallelization is required) / Compact then return for execution approval / Request changes / Reject). Final plan must include ADR (Decision, Drivers, Alternatives considered, Why chosen, Consequences, Follow-ups). Otherwise, output the final plan and stop before any mutation or delegation.
83
+ 6. On Critic approval, mark the plan `pending approval` unless explicit execution approval has already been captured, persist the ADR/final plan via `skc ralplan --write --stage final --stage_n <N> --artifact "..."`, and do not directly edit `.skc/_session-{sessionid}/plans`. *(--interactive only)* If `--interactive` is set, use the `ask` tool to present the plan with approval options (Approve execution via ultragoal (Recommended) / Approve execution via team (only when tmux-based interactive worker parallelization is required) / Compact then return for execution approval / Request changes / Reject). Final plan must include ADR (Decision, Drivers, Alternatives considered, Why chosen, Consequences, Follow-ups). Otherwise, output the final plan and stop before any mutation or delegation.
78
84
  7. *(--interactive only)* User chooses: Approve ultragoal execution (recommended), Approve team execution (tmux parallelization only), Request changes, or Reject
79
85
  8. *(--interactive only)* On approval: invoke `/skill:ultragoal` for execution by default; invoke `/skill:team` only when the user explicitly needs tmux-based interactive worker parallelization -- never implement directly
80
86
 
@@ -84,7 +90,7 @@ The consensus workflow:
84
90
  skc state ralplan write --input '{"current_phase":"handoff"}' --json
85
91
  ```
86
92
 
87
- The skill tool then dispatches the execution skill same-turn and runs `skc state ralplan handoff --to <team|ultragoal> --json` in-process to atomically demote ralplan, promote the callee, and sync both `skill-active-state.json` files. You do not need to run the handoff verb yourself.
93
+ The skill tool then dispatches the execution skill same-turn and runs `skc state ralplan handoff --to <team|ultragoal> --json` in-process to atomically demote ralplan, promote the callee, and sync `.skc/_session-{sessionid}/state/skill-active-state.json`. You do not need to run the handoff verb yourself.
88
94
 
89
95
  > **Important:** Steps 3 and 4 MUST run sequentially. Do NOT issue both agent Task calls in the same parallel batch. Always await the Architect result before issuing the Critic Task.
90
96
 
@@ -7,10 +7,14 @@ source: "forked from upstream team skill and rebranded for SKC"
7
7
 
8
8
  # Team Skill
9
9
 
10
- `$team` is the tmux-based multi-worker execution mode for SKC. It starts real SKC worker CLI sessions by splitting the current tmux leader window and coordinates them through `.skc/state/team/...` files plus CLI team interop (`skc team api ...`) and state files.
10
+ `$team` is the tmux-based multi-worker execution mode for SKC. It starts real SKC worker CLI sessions by splitting the current tmux leader window and coordinates them through `.skc/_session-{sessionid}/state/team/...` files plus CLI team interop (`skc team api ...`) and state files.
11
11
 
12
12
  This skill is operationally sensitive. Treat it as an operator workflow, not a generic prompt pattern. In SKC App or plain outside-tmux sessions, do not present `$team` / `skc team` as directly available; launch SKC CLI from shell first, or stay on the nearest app-safe surface until the user explicitly wants the tmux runtime.
13
13
 
14
+ ## Corrupt current-session state recovery
15
+
16
+ When team detects its own current-session state is corrupt, tampered, unreadable, or stale on resume, run `skc state clear --force --mode team` before reseeding or restarting. Scope the clear to the current session via `--session-id`, the command payload, or `SKC_SESSION_ID`; it clears only team state for that session and never clears other skills or sessions.
17
+
14
18
  ## Team vs Native Subagents
15
19
 
16
20
  - Use **SKC native subagents** for bounded, in-session parallelism where one leader thread can fan out a few independent subtasks and wait for them directly.
@@ -62,9 +66,9 @@ requiring a separate linked execution loop up front. SKC team supports current-w
62
66
 
63
67
  ### Team + Ultragoal bridge
64
68
 
65
- Use `$ultragoal` for durable leader-owned goal/ledger tracking and `$team` for parallel visible tmux execution lanes. When Team is launched with an active `.skc/ultragoal/goals.json`, worker task/status context may include leader-owned Ultragoal context: `.skc/ultragoal/goals.json`, `.skc/ultragoal/ledger.jsonl`, the active goal id, SKC goal mode, and the `fresh_leader_goal_get_required` checkpoint policy.
69
+ Use `$ultragoal` for durable leader-owned goal/ledger tracking and `$team` for parallel visible tmux execution lanes. When Team is launched with an active `.skc/_session-{sessionid}/ultragoal/goals.json`, worker task/status context may include leader-owned Ultragoal context: `.skc/_session-{sessionid}/ultragoal/goals.json`, `.skc/_session-{sessionid}/ultragoal/ledger.jsonl`, the active goal id, SKC goal mode, and the `fresh_leader_goal_get_required` checkpoint policy.
66
70
 
67
- Workers provide task status and verification evidence only. They do not own Ultragoal goal state, create worker ledgers, mutate `.skc/ultragoal`, auto-launch Team from Ultragoal, or perform hidden SKC goal mutation. Workers must not run `skc ultragoal checkpoint`; checkpoint authority stays with the leader after worker tasks are terminal. Ultragoal does not auto-launch Team and performs no hidden goal mutation. The leader uses terminal Team evidence plus a fresh `goal({"op":"get"})` snapshot and strict quality gate to run `skc ultragoal checkpoint --goal-id <id> --status complete --evidence "<team evidence mentioning .skc/ultragoal and <id>>" --skc-goal-json <fresh-goal-get-json-or-path> --quality-gate-json <quality-gate-json-or-path>`.
71
+ Workers provide task status and verification evidence only. They do not own Ultragoal goal state, create worker ledgers, mutate `.skc/_session-{sessionid}/ultragoal`, auto-launch Team from Ultragoal, or perform hidden SKC goal mutation. Workers must not run `skc ultragoal checkpoint`; checkpoint authority stays with the leader after worker tasks are terminal. Ultragoal does not auto-launch Team and performs no hidden goal mutation. The leader uses terminal Team evidence plus a fresh `goal({"op":"get"})` snapshot and strict quality gate to run `skc ultragoal checkpoint --goal-id <id> --status complete --evidence "<team evidence mentioning .skc/_session-{sessionid}/ultragoal and <id>>" --skc-goal-json <fresh-goal-get-json-or-path> --quality-gate-json <quality-gate-json-or-path>`.
68
72
 
69
73
  ### Worker command override
70
74
 
@@ -107,12 +111,12 @@ Before launching `skc team`, require a grounded context snapshot:
107
111
  - constraints
108
112
  - unknowns/open questions
109
113
  - likely codebase touchpoints
110
- 4. If ambiguity remains high, run `explore` first for brownfield facts, then run `$deep-interview --quick <task>` before team launch.
114
+ 4. If ambiguity remains high, gather brownfield facts with focused repo inspection or a canonical read-only role agent first, then run `$deep-interview --quick <task>` before team launch.
111
115
  5. If current correctness depends on official docs, version-aware framework guidance, best practices, or external dependency behavior, auto-delegate `researcher` as an evidence lane before or alongside worker launch instead of relying on repo-local recall alone.
112
116
 
113
117
  Do not start the worker pane until this gate is satisfied; if forced to proceed quickly, state explicit scope/risk limitations in the launch report.
114
118
 
115
- For simple read-only brownfield lookups during intake, follow active session guidance: when `USE_SKC_EXPLORE_CMD` is enabled, prefer `skc explore` with narrow, concrete prompts; otherwise use the richer normal explore path and fall back normally if `skc explore` is unavailable.
119
+ For simple read-only brownfield lookups during intake, use narrow repo inspection first; for broader mapping, delegate to `planner` or `architect` with a concrete fact-finding assignment.
116
120
 
117
121
  ## Follow-up Staffing Contract
118
122
 
@@ -141,19 +145,19 @@ When `$team` is used as a follow-up mode from ralplan, carry forward the approve
141
145
  1. Parse args (`N`, `agent-type`, task), default to 3 workers, and cap workers at 20.
142
146
  2. Non-dry-run: detect the current tmux leader context with `display-message -p "#S:#I #{pane_id}"` before creating state or worktrees.
143
147
  3. Initialize team state:
144
- - `.skc/state/team/<team>/config.json`
145
- - `.skc/state/team/<team>/manifest.v2.json`
146
- - `.skc/state/team/<team>/tasks/task-*.json` (one per explicit lane section, otherwise one worker-owned compatibility task per worker)
147
- - `.skc/state/team/<team>/mailbox/worker-1.json`
148
- - `.skc/state/team/<team>/workers/<worker>/status.json`
149
- - `.skc/state/team/<team>/workers/<worker>/lifecycle.json`
150
- - `.skc/state/team/<team>/workers/<worker>/heartbeat.json`
148
+ - `.skc/_session-{sessionid}/state/team/<team>/config.json`
149
+ - `.skc/_session-{sessionid}/state/team/<team>/manifest.v2.json`
150
+ - `.skc/_session-{sessionid}/state/team/<team>/tasks/task-*.json` (one per explicit lane section, otherwise one worker-owned compatibility task per worker)
151
+ - `.skc/_session-{sessionid}/state/team/<team>/mailbox/worker-1.json`
152
+ - `.skc/_session-{sessionid}/state/team/<team>/workers/<worker>/status.json`
153
+ - `.skc/_session-{sessionid}/state/team/<team>/workers/<worker>/lifecycle.json`
154
+ - `.skc/_session-{sessionid}/state/team/<team>/workers/<worker>/heartbeat.json`
151
155
  4. Resolve the worker command from `SKC_TEAM_WORKER_COMMAND` or the active `skc` entrypoint.
152
156
  5. Split the current tmux window like SKC team: worker 1 is split horizontally to the right of the leader, workers 2..N are vertically stacked in the right column, then `select-layout main-vertical` and `main-pane-width` keep leader-left/worker-right at roughly 50/50.
153
157
  6. Launch the worker with:
154
158
  - `SKC_TEAM_NAME=<team>`
155
159
  - `SKC_TEAM_WORKER_ID=worker-1`
156
- - `SKC_TEAM_STATE_ROOT=<leader-cwd>/.skc/state/team`
160
+ - `SKC_TEAM_STATE_ROOT=<leader-cwd>/.skc/_session-{sessionid}/state/team`
157
161
  - optional `SKC_TEAM_WORKTREE_PATH=<path>` when worktree mode is active
158
162
  7. Automatically integrate worker worktree commits during leader monitoring:
159
163
  - dirty worker worktrees are auto-checkpointed before integration
@@ -216,7 +220,7 @@ Semantics:
216
220
  - `list`: pure read path; lists known teams without integrating worker commits.
217
221
  - API/read-only snapshot operations are pure unless explicitly documented as a monitor path.
218
222
  - `claim-task`: mutating task path; before granting a new claim, it recovers expired claims and rejects claims from workers already classified as not live.
219
- - `shutdown`: writes per-worker graceful `shutdown-request.json`, moves lifecycle through `draining` to `stopped`, kills the recorded worker pane when it still belongs to the stored tmux target, removes clean created worktrees, marks worker runtime status stopped, and sets phase from task, lifecycle, and integration state: `complete` only when all tasks have verified `completion_evidence`, every worker has matching graceful shutdown lifecycle evidence, and no integration request/conflict is pending; `awaiting_integration` when tasks and lifecycle are complete but leader integration still requires action; `failed` when tasks failed/blocked or completed tasks lack valid evidence; and `cancelled` when work remains pending or in progress. It preserves `.skc/state/team/<team>` as evidence.
223
+ - `shutdown`: writes per-worker graceful `shutdown-request.json`, moves lifecycle through `draining` to `stopped`, kills the recorded worker pane when it still belongs to the stored tmux target, removes clean created worktrees, marks worker runtime status stopped, and sets phase from task, lifecycle, and integration state: `complete` only when all tasks have verified `completion_evidence`, every worker has matching graceful shutdown lifecycle evidence, and no integration request/conflict is pending; `awaiting_integration` when tasks and lifecycle are complete but leader integration still requires action; `failed` when tasks failed/blocked or completed tasks lack valid evidence; and `cancelled` when work remains pending or in progress. It preserves `.skc/_session-{sessionid}/state/team/<team>` as evidence.
220
224
 
221
225
  ## Data Plane and Control Plane
222
226
 
@@ -228,26 +232,26 @@ Semantics:
228
232
 
229
233
  ### Data Plane
230
234
 
231
- - `.skc/state/team/<team>/config.json`
232
- - `.skc/state/team/<team>/manifest.v2.json`
233
- - `.skc/state/team/<team>/phase.json`
234
- - `.skc/state/team/<team>/events.jsonl`
235
- - `.skc/state/team/<team>/trace.jsonl`
236
- - `.skc/state/team/<team>/trace-errors.jsonl`
237
- - `.skc/state/team/<team>/telemetry.jsonl`
238
- - `.skc/state/team/<team>/monitor-snapshot.json`
239
- - `.skc/state/team/<team>/integration-report.md`
240
- - `.skc/state/team/<team>/tasks/task-1.json` (includes structured `completion_evidence` after completed transitions)
241
- - `.skc/state/team/<team>/mailbox/worker-1/<message-id>.json`
242
- - `.skc/state/team/<team>/mailbox/worker-1.json` (legacy compatibility view)
243
- - `.skc/state/team/<team>/notifications/<notification-id>.json`
244
- - `.skc/state/team/<team>/workers/<worker>/startup-ack.json`
245
- - `.skc/state/team/<team>/workers/<worker>/status.json`
246
- - `.skc/state/team/<team>/workers/<worker>/lifecycle.json`
247
- - `.skc/state/team/<team>/workers/<worker>/heartbeat.json`
248
- - `.skc/state/team/<team>/workers/<worker>/shutdown-request.json`
249
- - `.skc/state/team/<team>/workers/<worker>/nudges/<fingerprint>.json`
250
- - `.skc/reports/team-commit-hygiene/<team>.ledger.json`
235
+ - `.skc/_session-{sessionid}/state/team/<team>/config.json`
236
+ - `.skc/_session-{sessionid}/state/team/<team>/manifest.v2.json`
237
+ - `.skc/_session-{sessionid}/state/team/<team>/phase.json`
238
+ - `.skc/_session-{sessionid}/state/team/<team>/events.jsonl`
239
+ - `.skc/_session-{sessionid}/state/team/<team>/trace.jsonl`
240
+ - `.skc/_session-{sessionid}/state/team/<team>/trace-errors.jsonl`
241
+ - `.skc/_session-{sessionid}/state/team/<team>/telemetry.jsonl`
242
+ - `.skc/_session-{sessionid}/state/team/<team>/monitor-snapshot.json`
243
+ - `.skc/_session-{sessionid}/state/team/<team>/integration-report.md`
244
+ - `.skc/_session-{sessionid}/state/team/<team>/tasks/task-1.json` (includes structured `completion_evidence` after completed transitions)
245
+ - `.skc/_session-{sessionid}/state/team/<team>/mailbox/worker-1/<message-id>.json`
246
+ - `.skc/_session-{sessionid}/state/team/<team>/mailbox/worker-1.json` (legacy compatibility view)
247
+ - `.skc/_session-{sessionid}/state/team/<team>/notifications/<notification-id>.json`
248
+ - `.skc/_session-{sessionid}/state/team/<team>/workers/<worker>/startup-ack.json`
249
+ - `.skc/_session-{sessionid}/state/team/<team>/workers/<worker>/status.json`
250
+ - `.skc/_session-{sessionid}/state/team/<team>/workers/<worker>/lifecycle.json`
251
+ - `.skc/_session-{sessionid}/state/team/<team>/workers/<worker>/heartbeat.json`
252
+ - `.skc/_session-{sessionid}/state/team/<team>/workers/<worker>/shutdown-request.json`
253
+ - `.skc/_session-{sessionid}/state/team/<team>/workers/<worker>/nudges/<fingerprint>.json`
254
+ - `.skc/_session-{sessionid}/reports/team-commit-hygiene/<team>.ledger.json`
251
255
 
252
256
  ## Team Mutation Interop (CLI-first)
253
257
 
@@ -285,10 +289,10 @@ SKC ports team-mode concepts from `../../oh-my-codex`, not code or OMX/Codex-spe
285
289
 
286
290
  | Concept | SKC-native equivalent |
287
291
  |---------|-----------------------|
288
- | Worker identity/inbox/mailbox paths | `.skc/state/team/<team>/workers/<worker>/identity.json`, `inbox.md`, and per-message mailbox records under `.skc/state/team/<team>/mailbox/<worker>/`. |
292
+ | Worker identity/inbox/mailbox paths | `.skc/_session-{sessionid}/state/team/<team>/workers/<worker>/identity.json`, `inbox.md`, and per-message mailbox records under `.skc/_session-{sessionid}/state/team/<team>/mailbox/<worker>/`. |
289
293
  | Startup ACK | `skc team api worker-startup-ack`, persisted as `workers/<worker>/startup-ack.json`. |
290
294
  | Claim-safe lifecycle APIs | `claim-task`, `transition-task-status`, and `release-task-claim` with worker ownership and claim-token guards. |
291
- | Delivery states and deferred pane attempts | Native notification records under `.skc/state/team/<team>/notifications/` with `pending`, `sent`, `queued`, `deferred`, `failed`, `delivered`, and `acknowledged` states. |
295
+ | Delivery states and deferred pane attempts | Native notification records under `.skc/_session-{sessionid}/state/team/<team>/notifications/` with `pending`, `sent`, `queued`, `deferred`, `failed`, `delivered`, and `acknowledged` states. |
292
296
  | Non-destructive leader nudges | Lifecycle nudge records under `workers/<worker>/nudges/`; SKC suggests inspection/relaunch but never auto-kills or auto-relaunches workers. |
293
297
 
294
298
  Forbidden assumptions: do not copy OMX paths, Codex notify payload formats, OMX process names, or source code directly. Keep tmux as the current runtime; native split-worker TUI remains roadmap-only.
@@ -300,7 +304,7 @@ Worker protocol:
300
304
  - Claim pending work with `claim-task`.
301
305
  - Transition the task to `completed`, `failed`, or `blocked` with `transition-task-status`, including claim token and evidence for completion.
302
306
  - Commit or leave worktree changes in the worker worktree; the leader `monitor`/`resume` path will auto-checkpoint dirty worktrees and integrate committed history where possible.
303
- - Record implementation/verification evidence in normal task output and state files; leader integration/conflict notifications are delivered through `.skc/state/team/<team>/mailbox/leader-fixed.json`.
307
+ - Record implementation/verification evidence in normal task output and state files; leader integration/conflict notifications are delivered through `.skc/_session-{sessionid}/state/team/<team>/mailbox/leader-fixed.json`.
304
308
 
305
309
  ## Environment Knobs
306
310
 
@@ -312,7 +316,7 @@ Useful runtime env vars:
312
316
  - `SKC_TEAM_WORKER_COMMAND`
313
317
  - worker command override (default resolves to active SKC entrypoint or `skc`)
314
318
  - `SKC_TEAM_STATE_ROOT`
315
- - team state root override (default `<cwd>/.skc/state/team`)
319
+ - team state root override (default `<cwd>/.skc/_session-{sessionid}/state/team`)
316
320
 
317
321
  ## Failure Modes and Diagnosis
318
322
 
@@ -325,18 +329,18 @@ Operator note (important for SKC panes):
325
329
 
326
330
  - **Outside tmux:** non-dry-run launch fails before team state or worktrees are created. Start `skc team` from an attached tmux leader pane.
327
331
  - **Split failure:** startup records a failed phase if state was already initialized, rolls back created worktrees, and never kills the leader tmux session.
328
- - **Worker API ENOENT:** team state is missing or `SKC_TEAM_STATE_ROOT` points somewhere else. Check `.skc/state/team/<team>/` before assuming worker failure.
332
+ - **Worker API ENOENT:** team state is missing or `SKC_TEAM_STATE_ROOT` points somewhere else. Check `.skc/_session-{sessionid}/state/team/<team>/` before assuming worker failure.
329
333
  - **Stale pane on shutdown:** shutdown only kills a recorded worker pane when it still belongs to the stored `tmux_target` and is not the leader pane. Stale panes outside that target require manual inspection.
330
- - **Integration conflict:** `skc team monitor <team>` / `resume` aborts the failing merge, cherry-pick, or worker rebase; `skc team status <team>` is read-only inspection. Inspect `.skc/state/team/<team>/integration-report.md`, `.skc/state/team/<team>/events.jsonl`, `.skc/state/team/<team>/mailbox/leader-fixed.json`, and `.skc/reports/team-commit-hygiene/<team>.ledger.json`.
334
+ - **Integration conflict:** `skc team monitor <team>` / `resume` aborts the failing merge, cherry-pick, or worker rebase; `skc team status <team>` is read-only inspection. Inspect `.skc/_session-{sessionid}/state/team/<team>/integration-report.md`, `.skc/_session-{sessionid}/state/team/<team>/events.jsonl`, `.skc/_session-{sessionid}/state/team/<team>/mailbox/leader-fixed.json`, and `.skc/_session-{sessionid}/reports/team-commit-hygiene/<team>.ledger.json`.
331
335
 
332
336
  ### Safe Manual Intervention (last resort)
333
337
 
334
338
  Use only after checking `skc team status <team>` and state evidence:
335
339
 
336
340
  1. Inspect team files:
337
- - `.skc/state/team/<team>/config.json`
338
- - `.skc/state/team/<team>/tasks/task-1.json`
339
- - `.skc/state/team/<team>/mailbox/worker-1.json`
341
+ - `.skc/_session-{sessionid}/state/team/<team>/config.json`
342
+ - `.skc/_session-{sessionid}/state/team/<team>/tasks/task-1.json`
343
+ - `.skc/_session-{sessionid}/state/team/<team>/mailbox/worker-1.json`
340
344
  2. Capture pane tail to confirm current worker state:
341
345
  - `tmux capture-pane -t %<worker-pane> -p -S -120`
342
346
  - If a larger-tail read or bounded summary would help, prefer explicit opt-in inspection via `skc sparkshell --tmux-pane %<worker-pane> --tail-lines 400` before improvising extra tmux commands.
@@ -385,7 +389,7 @@ When operating this skill, provide concrete progress evidence:
385
389
 
386
390
  1. Team started line (`Team started: <name>`)
387
391
  2. tmux target and worker pane id
388
- 3. task state from read-only `skc team status <team>`, mutating `skc team monitor <team>`, or `.skc/state/team/<team>/tasks/task-1.json`
392
+ 3. task state from read-only `skc team status <team>`, mutating `skc team monitor <team>`, or `.skc/_session-{sessionid}/state/team/<team>/tasks/task-1.json`
389
393
  4. shutdown outcome (`phase=complete`, worker status `stopped`) when the run is terminal; incomplete shutdowns must report `phase=cancelled`/`failed`, and integration-blocked shutdowns must report `phase=awaiting_integration`
390
394
 
391
395
  Do not claim success without file/pane evidence.
@@ -399,13 +403,13 @@ Use the `skc team ...` CLI as the supported team-launch surface. For automation,
399
403
  ### Supported current surfaces
400
404
 
401
405
  - **`skc team ...` CLI** — Primary method for interactive or automated team orchestration. Use this when you want direct tmux-pane visibility or a scriptable launch path.
402
- - **Team state files** — Inspect `.skc/state/team/<team>/` when you need status, task, or mailbox evidence after launch.
406
+ - **Team state files** — Inspect `.skc/_session-{sessionid}/state/team/<team>/` when you need status, task, or mailbox evidence after launch.
403
407
 
404
408
  ### Cleanup distinction
405
409
 
406
410
  Two cleanup paths exist and must not be confused:
407
411
 
408
- - `team_cleanup` (**state-server**): Deletes team state **files** on disk (`.skc/state/team/<team>/`). Use after a team run is fully complete.
412
+ - `team_cleanup` (**state-server**): Deletes team state **files** on disk (`.skc/_session-{sessionid}/state/team/<team>/`). Use after a team run is fully complete.
409
413
  - tmux/session cleanup: Use the documented `skc team` shutdown / cleanup flow when you need to stop the worker pane or clean up an interrupted run.
410
414
 
411
415
  ### Automation example
@@ -439,4 +443,4 @@ When the team task-set completes OR the user requests return to planning/persist
439
443
  skc state team write --input '{"current_phase":"handoff"}' --json
440
444
  ```
441
445
 
442
- The skill tool then dispatches `/skill:ralplan`, `/skill:deep-interview`, or `/skill:ultragoal` same-turn and runs `skc state team handoff --to <ralplan|deep-interview|ultragoal> --json` in-process to atomically demote team, promote the callee, and sync both `skill-active-state.json` files. You do not need to run the handoff verb yourself.
446
+ The skill tool then dispatches `/skill:ralplan`, `/skill:deep-interview`, or `/skill:ultragoal` same-turn and runs `skc state team handoff --to <ralplan|deep-interview|ultragoal> --json` in-process to atomically demote team, promote the callee, and sync both `.skc/_session-{sessionid}/state/skill-active-state.json` files. You do not need to run the handoff verb yourself.
@@ -11,14 +11,18 @@ Use when the user asks for `ultragoal`, `create-goals`, `complete-goals`, durabl
11
11
 
12
12
  ## Purpose
13
13
 
14
- `ultragoal` turns a brief into repo-native artifacts and then drives a SKC goal safely through the unified `goal` tool. New plans default to a stable pointer-style aggregate SKC goal for the whole durable plan in `.skc/ultragoal/goals.json`, including later accepted/appended stories under the original brief constraints, while SKC tracks G001/G002 story progress in the ledger. Ultragoal does not require any `/goal` slash-command between runs. For back-to-back ultragoal runs in one session/thread, call `goal({"op":"drop"})` only when `goal({"op":"get"})` still reports an active aggregate; then call `goal({"op":"create"})`. The goal tool stays armed across drop so the next create works in-session, and no slash-command cleanup exists or is required.
14
+ `ultragoal` turns a brief into repo-native artifacts and then drives a SKC goal safely through the unified `goal` tool. New plans default to a stable pointer-style aggregate SKC goal for the whole durable plan in `.skc/_session-{sessionid}/ultragoal/goals.json`, including later accepted/appended stories under the original brief constraints, while SKC tracks G001/G002 story progress in the ledger. Ultragoal does not require any `/goal` slash-command between runs. For back-to-back ultragoal runs in one session/thread, call `goal({"op":"drop"})` only when `goal({"op":"get"})` still reports an active aggregate; then call `goal({"op":"create"})`. The goal tool stays armed across drop so the next create works in-session, and no slash-command cleanup exists or is required.
15
15
 
16
- - `.skc/ultragoal/brief.md`
17
- - `.skc/ultragoal/goals.json`
18
- - `.skc/ultragoal/ledger.jsonl` (checkpoint and structured steering audit events)
16
+ - `.skc/_session-{sessionid}/ultragoal/brief.md`
17
+ - `.skc/_session-{sessionid}/ultragoal/goals.json`
18
+ - `.skc/_session-{sessionid}/ultragoal/ledger.jsonl` (checkpoint and structured steering audit events)
19
19
 
20
20
  Existing aggregate plans with the legacy enumerated objective are migrated to the stable pointer objective on read, persisted to `goals.json`, retained in `skcObjectiveAliases` for already-active hidden goal reconciliation, and audited with an `aggregate_objective_migrated` ledger entry.
21
21
 
22
+ ## Corrupt current-session state recovery
23
+
24
+ When ultragoal detects its own current-session state is corrupt, tampered, unreadable, or stale on resume, run `skc state clear --force --mode ultragoal` before reseeding or restarting. Scope the clear to the current session via `--session-id`, the command payload, or `SKC_SESSION_ID`; it clears only ultragoal state for that session and never clears other skills or sessions.
25
+
22
26
  ## Always-used command examples
23
27
 
24
28
  Use these exact `skc ultragoal` commands before spending tool calls rediscovering syntax:
@@ -81,7 +85,7 @@ Use `goal({"op":"get"})` snapshots inside Ultragoal for ledger reconciliation. T
81
85
  - `skc ultragoal create-goals --brief-file <path>`
82
86
  - `cat <brief> | skc ultragoal create-goals --from-stdin`
83
87
  - `skc ultragoal create-goals --skc-goal-mode per-story --brief "<brief>"` only when one SKC goal context per story is explicitly preferred
84
- 3. Inspect `.skc/ultragoal/goals.json` and refine if needed.
88
+ 3. Inspect `.skc/_session-{sessionid}/ultragoal/goals.json` and refine if needed.
85
89
 
86
90
  ## Complete goals
87
91
 
@@ -131,9 +135,9 @@ skc ultragoal steer --kind mark_blocked_superseded --goal-id G004 --evidence "Th
131
135
 
132
136
  Steering invariants:
133
137
 
134
- - Do not edit the aggregate goal objective, original brief constraints, quality gates, or completion status. The aggregate objective is a stable pointer to `.skc/ultragoal/goals.json` and `.skc/ultragoal/ledger.jsonl`, not an enumeration of initial goal ids.
135
- - Do not hard-delete goals, auto-complete work, weaken verification, or silently mutate `.skc/ultragoal`.
136
- - Accepted and rejected attempts append structured audit entries to `.skc/ultragoal/ledger.jsonl`.
138
+ - Do not edit the aggregate goal objective, original brief constraints, quality gates, or completion status. The aggregate objective is a stable pointer to `.skc/_session-{sessionid}/ultragoal/goals.json` and `.skc/_session-{sessionid}/ultragoal/ledger.jsonl`, not an enumeration of initial goal ids.
139
+ - Do not hard-delete goals, auto-complete work, weaken verification, or silently mutate `.skc/_session-{sessionid}/ultragoal`.
140
+ - Accepted and rejected attempts append structured audit entries to `.skc/_session-{sessionid}/ultragoal/ledger.jsonl`.
137
141
  - Superseded goals remain in `goals.json` with steering metadata and are skipped for scheduling.
138
142
  - Blocked goals without replacements are skipped for scheduling but still block final completion until later explicit steering replaces or supersedes them.
139
143
 
@@ -152,18 +156,18 @@ When delegating with native subagents, an await timeout only limits the leader's
152
156
 
153
157
  If an Ultragoal request has no approved plan or consensus artifact, run `ralplan` first and preserve its PRD, test spec, role roster, and verification guidance in the Ultragoal ledger. Do not silently substitute ad-hoc execution for missing planning.
154
158
 
155
- The Ultragoal leader owns `.skc/ultragoal/goals.json` and `.skc/ultragoal/ledger.jsonl`. Role agents return implementation/review evidence; they do not checkpoint Ultragoal or mutate goal state.
159
+ The Ultragoal leader owns `.skc/_session-{sessionid}/ultragoal/goals.json` and `.skc/_session-{sessionid}/ultragoal/ledger.jsonl`. Role agents return implementation/review evidence; they do not checkpoint Ultragoal or mutate goal state.
156
160
 
157
- For large subgoals with independent slices, the Ultragoal leader must spawn parallel `executor` subagents instead of doing serial solo work. Split only cleanly separable files/surfaces, give each executor bounded targets and acceptance criteria, and keep checkpoint ownership in the leader. Use `architect` / `critic` review lanes after integration; do not let worker agents mutate `.skc/ultragoal` or call goal tools.
161
+ For large subgoals with independent slices, the Ultragoal leader must spawn parallel `executor` subagents instead of doing serial solo work. Split only cleanly separable files/surfaces, give each executor bounded targets and acceptance criteria, and keep checkpoint ownership in the leader. Use `architect` / `critic` review lanes after integration; do not let worker agents mutate `.skc/_session-{sessionid}/ultragoal` or call goal tools.
158
162
 
159
163
  ## Use Ultragoal and Team together
160
164
 
161
- Use ultragoal and team together for a durable Ultragoal story that benefits from one visible tmux worker session. Ultragoal remains leader-owned: `.skc/ultragoal/goals.json` stores the story plan and `.skc/ultragoal/ledger.jsonl` stores checkpoints. Team is the single-worker tmux execution engine and returns task/evidence status to the leader.
165
+ Use ultragoal and team together for a durable Ultragoal story that benefits from one visible tmux worker session. Ultragoal remains leader-owned: `.skc/_session-{sessionid}/ultragoal/goals.json` stores the story plan and `.skc/_session-{sessionid}/ultragoal/ledger.jsonl` stores checkpoints. Team is the single-worker tmux execution engine and returns task/evidence status to the leader.
162
166
 
163
167
  The leader checkpoints Ultragoal from Team evidence with a fresh `goal({"op":"get"})` snapshot:
164
168
 
165
169
  ```sh
166
- skc ultragoal checkpoint --goal-id <id> --status complete --evidence "<team evidence mentioning .skc/ultragoal and <id>>" --skc-goal-json <fresh-goal-get-json-or-path> --quality-gate-json <quality-gate-json-or-path>
170
+ skc ultragoal checkpoint --goal-id <id> --status complete --evidence "<team evidence mentioning .skc/_session-{sessionid}/ultragoal and <id>>" --skc-goal-json <fresh-goal-get-json-or-path> --quality-gate-json <quality-gate-json-or-path>
167
171
  ```
168
172
 
169
173
  Workers do not own ultragoal goal state, do not create worker ultragoal ledgers, and do not checkpoint Ultragoal. Workers must not run `skc ultragoal checkpoint`; checkpoint authority stays with the leader after worker tasks are terminal. Team launch remains explicit; Ultragoal does not auto-launch Team and performs no hidden goal mutation.
@@ -335,7 +339,7 @@ When the aggregate ultragoal is complete OR the user requests return to planning
335
339
  skc state ultragoal write --input '{"current_phase":"handoff"}' --json
336
340
  ```
337
341
 
338
- The skill tool then dispatches `/skill:ralplan` or `/skill:deep-interview` same-turn and runs `skc state ultragoal handoff --to <ralplan|deep-interview> --json` in-process to atomically demote ultragoal, promote the callee, and sync both `skill-active-state.json` files. You do not need to run the handoff verb yourself.
342
+ The skill tool then dispatches `/skill:ralplan` or `/skill:deep-interview` same-turn and runs `skc state ultragoal handoff --to <ralplan|deep-interview> --json` in-process to atomically demote ultragoal, promote the callee, and sync both `.skc/_session-{sessionid}/state/skill-active-state.json` files. You do not need to run the handoff verb yourself.
339
343
 
340
344
  ## Constraints
341
345
 
@@ -66,7 +66,9 @@ export interface BashResult {
66
66
  const shellSessions = new Map<string, Shell>();
67
67
  const brokenShellSessions = new Set<string>();
68
68
  const retiringShellSessions = new Set<Shell>();
69
- const CANCEL_CLEANUP_WAIT_MS = 250;
69
+ // Cover pi-shell's normal cancellation kill waves without turning a stalled
70
+ // native cleanup into a multi-second JavaScript tool stall.
71
+ const CANCEL_CLEANUP_WAIT_MS = 400;
70
72
 
71
73
  /** Number of persistent shell sessions currently retained (owner gauge). */
72
74
  export function getShellSessionCount(): number {
@@ -12,7 +12,6 @@ import { getConfigDirs } from "../../config";
12
12
  import { execCommand } from "../../exec/exec";
13
13
  import * as typebox from "../typebox";
14
14
  import { GreenCommand } from "./bundled/ci-green";
15
- import { ReviewCommand } from "./bundled/review";
16
15
  import type {
17
16
  CustomCommand,
18
17
  CustomCommandAPI,
@@ -155,12 +154,6 @@ function loadBundledCommands(sharedApi: CustomCommandAPI): LoadedCustomCommand[]
155
154
  command: new GreenCommand(sharedApi),
156
155
  source: "bundled",
157
156
  });
158
- bundled.push({
159
- path: "bundled:review",
160
- resolvedPath: "bundled:review",
161
- command: new ReviewCommand(sharedApi),
162
- source: "bundled",
163
- });
164
157
 
165
158
  return bundled;
166
159
  }
@@ -1,3 +1,16 @@
1
+ import { resolveSkcSessionForRead, SessionResolutionError } from "../../skc-runtime/session-resolution";
2
+
3
+ async function resolveBoundarySessionId(cwd: string, sessionId?: string): Promise<string | undefined> {
4
+ const normalizedSessionId = sessionId?.trim();
5
+ if (normalizedSessionId) return normalizedSessionId;
6
+ try {
7
+ return (await resolveSkcSessionForRead(cwd, { envSessionId: process.env.SKC_SESSION_ID })).skcSessionId;
8
+ } catch (error) {
9
+ if (error instanceof SessionResolutionError && error.code === "no_session") return undefined;
10
+ throw error;
11
+ }
12
+ }
13
+
1
14
  import { readVisibleSkillActiveState } from "../../skill-state/active-state";
2
15
  import { initialPhaseForSkill } from "../../skill-state/initial-phase";
3
16
  import { readActiveSubskillsForParent } from "./state";
@@ -35,7 +48,8 @@ export async function resolveCurrentPhaseForParent(input: {
35
48
  const explicitPhase = input.explicitPhase?.trim();
36
49
  if (explicitPhase) return explicitPhase;
37
50
 
38
- const state = await readVisibleSkillActiveState(input.cwd, input.sessionId);
51
+ const resolvedSessionId = await resolveBoundarySessionId(input.cwd, input.sessionId);
52
+ const state = resolvedSessionId ? await readVisibleSkillActiveState(input.cwd, resolvedSessionId) : null;
39
53
  const persistedPhase = state?.active_skills?.find(entry => entry.skill === input.parent)?.phase?.trim();
40
54
  if (persistedPhase) return persistedPhase;
41
55
 
@@ -54,9 +68,10 @@ export async function buildSubskillInjection(input: {
54
68
  activation?: LoadedSubskillActivation;
55
69
  currentPhase?: string;
56
70
  }): Promise<{ block: string; details?: LoadedSubskillActivation } | null> {
71
+ const resolvedSessionId = await resolveBoundarySessionId(input.cwd, input.sessionId);
57
72
  const resolvedPhase = await resolveCurrentPhaseForParent({
58
73
  cwd: input.cwd,
59
- sessionId: input.sessionId,
74
+ sessionId: resolvedSessionId,
60
75
  parent: input.skillName,
61
76
  explicitPhase: input.currentPhase,
62
77
  });
@@ -67,9 +82,11 @@ export async function buildSubskillInjection(input: {
67
82
  return { block: wrapSubskillBlock(directActivation, body), details: directActivation };
68
83
  }
69
84
 
85
+ if (!resolvedSessionId) return null;
86
+
70
87
  const [entry] = await readActiveSubskillsForParent({
71
88
  cwd: input.cwd,
72
- sessionId: input.sessionId,
89
+ sessionId: resolvedSessionId,
73
90
  parent: input.skillName,
74
91
  phase: resolvedPhase,
75
92
  });
@@ -96,9 +113,11 @@ export async function buildAgentSubskillInjection(input: {
96
113
  }): Promise<string> {
97
114
  if (!(SKC_SUBSKILL_PARENT_AGENTS as readonly string[]).includes(input.agentName)) return "";
98
115
 
116
+ const resolvedSessionId = await resolveBoundarySessionId(input.cwd, input.sessionId);
117
+ if (!resolvedSessionId) return "";
99
118
  const entries = await readActiveSubskillsForParent({
100
119
  cwd: input.cwd,
101
- sessionId: input.sessionId,
120
+ sessionId: resolvedSessionId,
102
121
  parent: input.agentName,
103
122
  phase: "prompt",
104
123
  });
@@ -1,3 +1,16 @@
1
+ import { resolveSkcSessionForRead, SessionResolutionError } from "../../skc-runtime/session-resolution";
2
+
3
+ async function resolveBoundarySessionId(cwd: string, sessionId?: string): Promise<string | undefined> {
4
+ const normalizedSessionId = sessionId?.trim();
5
+ if (normalizedSessionId) return normalizedSessionId;
6
+ try {
7
+ return (await resolveSkcSessionForRead(cwd, { envSessionId: process.env.SKC_SESSION_ID })).skcSessionId;
8
+ } catch (error) {
9
+ if (error instanceof SessionResolutionError && error.code === "no_session") return undefined;
10
+ throw error;
11
+ }
12
+ }
13
+
1
14
  import type { ActiveSubskillEntry } from "../../skill-state/active-state";
2
15
  import { readVisibleSkillActiveState } from "../../skill-state/active-state";
3
16
  import type { LoadedSubskillActivation } from "./types";
@@ -21,7 +34,9 @@ export async function readActiveSubskillsForParent(input: {
21
34
  parent: string;
22
35
  phase: string;
23
36
  }): Promise<ActiveSubskillEntry[]> {
24
- const state = await readVisibleSkillActiveState(input.cwd, input.sessionId);
37
+ const resolvedSessionId = await resolveBoundarySessionId(input.cwd, input.sessionId);
38
+ if (!resolvedSessionId) return [];
39
+ const state = await readVisibleSkillActiveState(input.cwd, resolvedSessionId);
25
40
  const parent = input.parent.trim();
26
41
  const phase = input.phase.trim();
27
42
  if (!state || !parent || !phase) return [];
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Session-scoped storage for the harness control plane.
3
3
  *
4
- * Layout (under the harness state root, default `<cwd>/.skc/state/harness`):
4
+ * Layout (under the harness state root, default `<cwd>/.skc/_session-{sessionid}/state/harness`):
5
5
  * sessions/<encoded-id>/state.json lifecycle + handle (atomic)
6
6
  * sessions/<encoded-id>/lease.json owner lease (M3)
7
7
  * sessions/<encoded-id>/events.jsonl owner-only severity envelopes
@@ -18,6 +18,7 @@ import * as fsSync from "node:fs";
18
18
  import * as fs from "node:fs/promises";
19
19
  import * as os from "node:os";
20
20
  import * as path from "node:path";
21
+ import { harnessStateRoot } from "../skc-runtime/session-layout";
21
22
  import { appendReceiptToConfiguredSpool } from "./receipt-spool";
22
23
  import type { ReceiptEnvelope } from "./receipts";
23
24
  import type { EventEnvelope, ReceiptFamily, SessionState } from "./types";
@@ -232,13 +233,22 @@ export class StorageError extends Error {
232
233
  }
233
234
  }
234
235
 
235
- /** Resolve the harness state root from explicit value, env, or cwd default. */
236
- export function resolveHarnessRoot(opts?: { root?: string; cwd?: string; env?: NodeJS.ProcessEnv }): string {
236
+ /** Resolve the harness state root from explicit value, env, or cwd/session default. */
237
+ export function resolveHarnessRoot(opts?: {
238
+ root?: string;
239
+ cwd?: string;
240
+ env?: NodeJS.ProcessEnv;
241
+ skcSessionId?: string;
242
+ }): string {
237
243
  const env = opts?.env ?? process.env;
238
244
  if (opts?.root) return path.resolve(opts.root);
239
245
  const fromEnv = env.SKC_HARNESS_STATE_ROOT;
240
246
  if (fromEnv?.trim()) return path.resolve(fromEnv.trim());
241
- return path.join(opts?.cwd ?? process.cwd(), ".skc", "state", "harness");
247
+ const skcSessionId = opts?.skcSessionId ?? env.SKC_SESSION_ID?.trim();
248
+ if (!skcSessionId) {
249
+ throw new StorageError("SKC session id is required for default harness state root", "missing_skc_session_id");
250
+ }
251
+ return harnessStateRoot(opts?.cwd ?? process.cwd(), skcSessionId);
242
252
  }
243
253
 
244
254
  export function assertSafeSessionId(id: string): void {
@@ -4,10 +4,13 @@ import * as path from "node:path";
4
4
  import { YAML } from "bun";
5
5
  import type { SkillDiscoverySettings } from "../config/skill-settings-defaults";
6
6
  import { DEFAULT_DISABLED_EXTENSIONS, DEFAULT_SKILL_DISCOVERY_SETTINGS } from "../config/skill-settings-defaults";
7
+ import { sessionLogsDir } from "../skc-runtime/session-layout";
7
8
  import {
8
9
  buildActiveUltragoalPromptContext,
9
10
  buildSkillActivationAdditionalContext,
10
11
  buildSkillStopOutput,
12
+ buildStateRecoveryDiagnosticsContext,
13
+ collectUserPromptStateRecoveryDiagnostics,
11
14
  type EffectiveSkillConfigInput,
12
15
  recordSkillActivation,
13
16
  } from "./skill-state";
@@ -169,6 +172,15 @@ export async function dispatchSkcNativeSkillHook(
169
172
  const hookEventName = readHookEventName(payload);
170
173
  const cwd = (options.cwd ?? safeString(payload.cwd).trim()) || process.cwd();
171
174
  if (hookEventName === "UserPromptSubmit") {
175
+ const recoveryDiagnostics = await collectUserPromptStateRecoveryDiagnostics({
176
+ cwd,
177
+ sessionId: readSessionId(payload),
178
+ threadId: readThreadId(payload),
179
+ stateDir: options.stateDir,
180
+ prompt: readPromptText(payload),
181
+ sessionFile: readSessionFile(payload),
182
+ });
183
+ const recoveryContext = buildStateRecoveryDiagnosticsContext(recoveryDiagnostics);
172
184
  const prompt = readPromptText(payload);
173
185
  const skillState = prompt
174
186
  ? await recordSkillActivation({
@@ -206,19 +218,22 @@ export async function dispatchSkcNativeSkillHook(
206
218
  },
207
219
  };
208
220
  }
221
+ const additionalContext = [
222
+ skillState ? buildSkillActivationAdditionalContext(skillState, effectiveSkillConfig) : activeUltragoalContext,
223
+ recoveryContext,
224
+ ]
225
+ .filter((value): value is string => Boolean(value))
226
+ .join(" ");
209
227
  return {
210
228
  hookEventName,
211
- outputJson:
212
- skillState || activeUltragoalContext
213
- ? {
214
- hookSpecificOutput: {
215
- hookEventName,
216
- additionalContext: skillState
217
- ? buildSkillActivationAdditionalContext(skillState, effectiveSkillConfig)
218
- : activeUltragoalContext,
219
- },
220
- }
221
- : null,
229
+ outputJson: additionalContext
230
+ ? {
231
+ hookSpecificOutput: {
232
+ hookEventName,
233
+ additionalContext,
234
+ },
235
+ }
236
+ : null,
222
237
  };
223
238
  }
224
239
 
@@ -253,7 +268,18 @@ async function readStdinJson(): Promise<{ payload: HookPayload; parseError: Erro
253
268
  }
254
269
 
255
270
  async function logHookError(cwd: string, type: string, error: unknown): Promise<void> {
256
- const logsDir = path.join(cwd, ".skc", "logs");
271
+ const skcSessionId = process.env.SKC_SESSION_ID?.trim();
272
+ if (!skcSessionId) {
273
+ console.error(
274
+ JSON.stringify({
275
+ timestamp: new Date().toISOString(),
276
+ type,
277
+ error: error instanceof Error ? error.message : String(error),
278
+ }),
279
+ );
280
+ return;
281
+ }
282
+ const logsDir = sessionLogsDir(cwd, skcSessionId);
257
283
  await mkdir(logsDir, { recursive: true }).catch(() => {});
258
284
  await appendFile(
259
285
  path.join(logsDir, `native-hook-${new Date().toISOString().split("T")[0]}.jsonl`),