@sayknow-cli/coding-agent 0.3.7 → 0.3.9

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 (272) hide show
  1. package/dist/types/append-only-mode.d.ts +31 -0
  2. package/dist/types/capability/rule.d.ts +8 -0
  3. package/dist/types/cli/completion-cli.d.ts +41 -0
  4. package/dist/types/cli/config-cli.d.ts +1 -0
  5. package/dist/types/cli/fixture-report.d.ts +20 -0
  6. package/dist/types/cli/fixture-report.test.d.ts +1 -0
  7. package/dist/types/cli/nofile-limit.d.ts +11 -0
  8. package/dist/types/cli/notify-cli.d.ts +7 -0
  9. package/dist/types/cli/update-cli.d.ts +22 -0
  10. package/dist/types/cli.d.ts +124 -1
  11. package/dist/types/commands/completion.d.ts +29 -0
  12. package/dist/types/commands/config.d.ts +3 -0
  13. package/dist/types/commands/deep-interview.d.ts +3 -0
  14. package/dist/types/config/file-lock.d.ts +7 -6
  15. package/dist/types/config/keybindings.d.ts +2 -2
  16. package/dist/types/config/model-profile-activation.d.ts +6 -0
  17. package/dist/types/config/model-profiles.d.ts +1 -0
  18. package/dist/types/config/settings-schema.d.ts +119 -1
  19. package/dist/types/config/settings.d.ts +8 -0
  20. package/dist/types/discovery/index.d.ts +1 -0
  21. package/dist/types/export/html/template.generated.d.ts +1 -1
  22. package/dist/types/export/ttsr.d.ts +14 -3
  23. package/dist/types/extensibility/extensions/runner.d.ts +2 -1
  24. package/dist/types/extensibility/extensions/types.d.ts +8 -0
  25. package/dist/types/goals/runtime.d.ts +1 -0
  26. package/dist/types/hooks/native-skill-hook.d.ts +12 -0
  27. package/dist/types/main.d.ts +4 -1
  28. package/dist/types/modes/components/assistant-message.d.ts +5 -1
  29. package/dist/types/modes/components/model-selector.d.ts +4 -0
  30. package/dist/types/modes/components/queued-message-selector.d.ts +12 -0
  31. package/dist/types/modes/components/settings-selector.d.ts +2 -0
  32. package/dist/types/modes/components/status-line.d.ts +9 -0
  33. package/dist/types/modes/components/thinking-selector.d.ts +2 -2
  34. package/dist/types/modes/controllers/command-controller.d.ts +1 -0
  35. package/dist/types/modes/controllers/event-controller.d.ts +5 -0
  36. package/dist/types/modes/controllers/input-controller.d.ts +1 -3
  37. package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
  38. package/dist/types/modes/interactive-mode.d.ts +4 -0
  39. package/dist/types/modes/print-mode.d.ts +13 -1
  40. package/dist/types/modes/prompt-action-autocomplete.d.ts +1 -1
  41. package/dist/types/modes/rpc/rpc-mode.d.ts +1 -3
  42. package/dist/types/modes/rpc/rpc-socket-security.d.ts +3 -0
  43. package/dist/types/modes/rpc/rpc-types.d.ts +14 -0
  44. package/dist/types/modes/shared/agent-wire/event-contract.d.ts +19 -0
  45. package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +23 -1
  46. package/dist/types/modes/types.d.ts +3 -0
  47. package/dist/types/modes/utils/injected-user-submission.d.ts +52 -0
  48. package/dist/types/modes/utils/ui-helpers.d.ts +1 -0
  49. package/dist/types/notifications/config-commands.d.ts +9 -0
  50. package/dist/types/notifications/config.d.ts +30 -1
  51. package/dist/types/notifications/daemon-paths.d.ts +1 -0
  52. package/dist/types/notifications/index.d.ts +8 -3
  53. package/dist/types/notifications/lifecycle-commands.d.ts +12 -3
  54. package/dist/types/notifications/lifecycle-control-runtime.d.ts +2 -1
  55. package/dist/types/notifications/reply-sent-store.d.ts +53 -0
  56. package/dist/types/notifications/rich-draft.d.ts +68 -0
  57. package/dist/types/notifications/rich-render.d.ts +90 -0
  58. package/dist/types/notifications/telegram-daemon.d.ts +45 -3
  59. package/dist/types/notifications/telegram-reference.d.ts +7 -5
  60. package/dist/types/notifications/threaded-render.d.ts +14 -0
  61. package/dist/types/runtime-api-key.d.ts +7 -0
  62. package/dist/types/sdk.d.ts +3 -0
  63. package/dist/types/session/agent-session.d.ts +61 -6
  64. package/dist/types/session/agent-storage.d.ts +1 -0
  65. package/dist/types/session/file-mention-pruning.d.ts +8 -0
  66. package/dist/types/session/messages.d.ts +4 -0
  67. package/dist/types/session/session-manager.d.ts +17 -1
  68. package/dist/types/skc-runtime/deep-interview-ambiguity.d.ts +39 -0
  69. package/dist/types/skc-runtime/deep-interview-recorder.d.ts +10 -1
  70. package/dist/types/skc-runtime/deep-interview-state.d.ts +17 -2
  71. package/dist/types/skc-runtime/session-state-sidecar.d.ts +7 -0
  72. package/dist/types/skc-runtime/state-writer.d.ts +3 -0
  73. package/dist/types/skc-runtime/tmux-common.d.ts +1 -0
  74. package/dist/types/skc-runtime/ultragoal-receipt-freshness.d.ts +42 -0
  75. package/dist/types/skc-runtime/ultragoal-runtime.d.ts +120 -13
  76. package/dist/types/skill-state/active-state.d.ts +18 -1
  77. package/dist/types/system-prompt.d.ts +18 -2
  78. package/dist/types/task/executor.d.ts +3 -0
  79. package/dist/types/task/fork-context-budget.d.ts +7 -0
  80. package/dist/types/task/token-log.d.ts +30 -0
  81. package/dist/types/task/token-log.test.d.ts +1 -0
  82. package/dist/types/tools/bisect.d.ts +81 -0
  83. package/dist/types/tools/computer.d.ts +2 -2
  84. package/dist/types/tools/index.d.ts +1 -0
  85. package/dist/types/tools/search.d.ts +2 -2
  86. package/dist/types/tools/ultragoal-ask-guard.d.ts +9 -2
  87. package/dist/types/utils/file-mentions.d.ts +14 -0
  88. package/dist/types/utils/git.d.ts +32 -0
  89. package/dist/types/utils/pasted-image-path.d.ts +30 -0
  90. package/dist/types/web/scrapers/youtube.d.ts +8 -0
  91. package/dist/types/workflow/workflow-intent-diff.d.ts +8 -2
  92. package/dist/types/workflow/workflow-intent-report-consumer.d.ts +50 -0
  93. package/dist/types/workflow/workflow-intent-report-schema.d.ts +2 -0
  94. package/dist/types/workflow/workflow-intent-report.d.ts +48 -0
  95. package/package.json +8 -8
  96. package/src/append-only-mode.ts +58 -0
  97. package/src/autoresearch/prompt.md +1 -1
  98. package/src/autoresearch/tools/log-experiment.ts +1 -1
  99. package/src/capability/rule.ts +9 -0
  100. package/src/cli/completion-cli.ts +234 -0
  101. package/src/cli/config-cli.ts +61 -9
  102. package/src/cli/fast-help.ts +1 -0
  103. package/src/cli/fixture-report.test.ts +230 -0
  104. package/src/cli/fixture-report.ts +171 -0
  105. package/src/cli/nofile-limit.ts +48 -0
  106. package/src/cli/notify-cli.ts +103 -17
  107. package/src/cli/telegram-cli.ts +1 -1
  108. package/src/cli/update-cli.ts +148 -33
  109. package/src/cli.ts +29 -1
  110. package/src/commands/completion.ts +84 -0
  111. package/src/commands/config.ts +2 -0
  112. package/src/commands/contribution-prep.ts +1 -1
  113. package/src/commands/deep-interview.ts +2 -1
  114. package/src/config/file-lock.ts +73 -34
  115. package/src/config/keybindings.ts +3 -3
  116. package/src/config/model-profile-activation.ts +65 -0
  117. package/src/config/model-profiles.ts +31 -2
  118. package/src/config/settings-schema.ts +76 -1
  119. package/src/config/settings.ts +22 -0
  120. package/src/defaults/skc/skills/team/SKILL.md +17 -14
  121. package/src/defaults/skc/skills/ultragoal/SKILL.md +59 -4
  122. package/src/defaults/skc/skills/ultragoal/pipeline-validation-contracts.md +30 -0
  123. package/src/defaults/skc-defaults.ts +9 -0
  124. package/src/discovery/helpers.ts +10 -0
  125. package/src/discovery/index.ts +1 -0
  126. package/src/export/html/template.generated.ts +1 -1
  127. package/src/export/html/template.js +60 -2
  128. package/src/export/ttsr.ts +96 -18
  129. package/src/extensibility/extensions/runner.ts +183 -219
  130. package/src/extensibility/extensions/types.ts +9 -0
  131. package/src/extensibility/skc-plugins/runtime-adapters.ts +156 -44
  132. package/src/goals/runtime.ts +10 -2
  133. package/src/hindsight/backend.ts +1 -3
  134. package/src/hooks/native-skill-hook.ts +124 -4
  135. package/src/internal-urls/docs-index.generated.ts +17 -8
  136. package/src/lsp/client.ts +1 -0
  137. package/src/main.ts +95 -43
  138. package/src/memories/index.ts +12 -1
  139. package/src/modes/components/assistant-message.ts +241 -82
  140. package/src/modes/components/custom-editor.ts +1 -0
  141. package/src/modes/components/footer.ts +7 -2
  142. package/src/modes/components/model-selector.ts +54 -11
  143. package/src/modes/components/queued-message-selector.ts +92 -0
  144. package/src/modes/components/settings-selector.ts +4 -0
  145. package/src/modes/components/status-line.ts +167 -54
  146. package/src/modes/components/thinking-selector.ts +10 -8
  147. package/src/modes/components/tool-execution.ts +44 -19
  148. package/src/modes/components/welcome.ts +181 -44
  149. package/src/modes/controllers/command-controller.ts +40 -4
  150. package/src/modes/controllers/event-controller.ts +77 -49
  151. package/src/modes/controllers/extension-ui-controller.ts +12 -11
  152. package/src/modes/controllers/input-controller.ts +192 -35
  153. package/src/modes/controllers/selector-controller.ts +168 -24
  154. package/src/modes/interactive-mode.ts +56 -16
  155. package/src/modes/print-mode.ts +43 -4
  156. package/src/modes/prompt-action-autocomplete.ts +21 -20
  157. package/src/modes/rpc/rpc-mode.ts +32 -12
  158. package/src/modes/rpc/rpc-socket-security.ts +13 -1
  159. package/src/modes/rpc/rpc-types.ts +9 -0
  160. package/src/modes/shared/agent-wire/command-validation.ts +4 -0
  161. package/src/modes/shared/agent-wire/event-contract.ts +22 -0
  162. package/src/modes/shared/agent-wire/event-envelope.ts +82 -0
  163. package/src/modes/shared/agent-wire/scopes.ts +1 -0
  164. package/src/modes/types.ts +3 -0
  165. package/src/modes/utils/hotkeys-markdown.ts +1 -0
  166. package/src/modes/utils/injected-user-submission.ts +94 -0
  167. package/src/modes/utils/ui-helpers.ts +20 -7
  168. package/src/notifications/config-commands.ts +20 -0
  169. package/src/notifications/config.ts +52 -5
  170. package/src/notifications/daemon-paths.ts +2 -0
  171. package/src/notifications/index.ts +144 -18
  172. package/src/notifications/lifecycle-commands.ts +74 -23
  173. package/src/notifications/lifecycle-control-runtime.ts +8 -3
  174. package/src/notifications/lifecycle-orchestrator.ts +19 -6
  175. package/src/notifications/reply-sent-store.ts +134 -0
  176. package/src/notifications/rich-draft.ts +107 -0
  177. package/src/notifications/rich-render.ts +142 -0
  178. package/src/notifications/telegram-daemon-control.ts +5 -3
  179. package/src/notifications/telegram-daemon.ts +606 -98
  180. package/src/notifications/telegram-reference.ts +17 -16
  181. package/src/notifications/threaded-render.ts +45 -2
  182. package/src/prompts/agents/architect.md +19 -10
  183. package/src/prompts/agents/critic.md +16 -18
  184. package/src/prompts/agents/executor.md +14 -11
  185. package/src/prompts/agents/planner.md +18 -13
  186. package/src/prompts/ci-green-request.md +3 -8
  187. package/src/prompts/goals/goal-continuation.md +0 -5
  188. package/src/prompts/goals/goal-mode-active.md +0 -5
  189. package/src/prompts/system/agent-creation-architect.md +2 -2
  190. package/src/prompts/system/plan-mode-active.md +1 -1
  191. package/src/prompts/system/plan-mode-subagent.md +3 -3
  192. package/src/prompts/system/project-prompt.md +0 -13
  193. package/src/prompts/system/subagent-system-prompt.md +3 -2
  194. package/src/prompts/system/system-prompt.md +29 -17
  195. package/src/prompts/system/volatile-project-context.md +10 -0
  196. package/src/prompts/system/web-search.md +4 -7
  197. package/src/prompts/tools/apply-patch.md +6 -0
  198. package/src/prompts/tools/ast-edit.md +1 -0
  199. package/src/prompts/tools/bash.md +1 -1
  200. package/src/prompts/tools/bisect.md +22 -0
  201. package/src/prompts/tools/browser.md +1 -1
  202. package/src/prompts/tools/computer.md +2 -2
  203. package/src/prompts/tools/cron.md +0 -2
  204. package/src/prompts/tools/eval.md +2 -2
  205. package/src/prompts/tools/find.md +1 -1
  206. package/src/prompts/tools/github.md +6 -6
  207. package/src/prompts/tools/goal.md +1 -3
  208. package/src/prompts/tools/image-gen.md +12 -5
  209. package/src/prompts/tools/irc.md +5 -4
  210. package/src/prompts/tools/job.md +2 -2
  211. package/src/prompts/tools/lsp.md +1 -1
  212. package/src/prompts/tools/monitor.md +2 -2
  213. package/src/prompts/tools/patch.md +2 -2
  214. package/src/prompts/tools/replace.md +2 -21
  215. package/src/prompts/tools/rewind.md +1 -1
  216. package/src/prompts/tools/search-tool-bm25.md +6 -11
  217. package/src/prompts/tools/search.md +1 -1
  218. package/src/prompts/tools/skill.md +3 -2
  219. package/src/prompts/tools/ssh.md +2 -1
  220. package/src/prompts/tools/subagent.md +2 -2
  221. package/src/prompts/tools/task.md +4 -5
  222. package/src/prompts/tools/todo-write.md +1 -1
  223. package/src/prompts/tools/vim.md +1 -0
  224. package/src/prompts/tools/web-search.md +2 -0
  225. package/src/prompts/tools/write.md +8 -2
  226. package/src/runtime-api-key.ts +16 -0
  227. package/src/sdk.ts +88 -36
  228. package/src/session/agent-session.ts +1013 -141
  229. package/src/session/agent-storage.ts +4 -0
  230. package/src/session/file-mention-pruning.ts +64 -0
  231. package/src/session/messages.ts +4 -0
  232. package/src/session/session-manager.ts +103 -4
  233. package/src/skc-runtime/deep-interview-ambiguity.ts +206 -0
  234. package/src/skc-runtime/deep-interview-recorder.ts +62 -8
  235. package/src/skc-runtime/deep-interview-state.ts +44 -2
  236. package/src/skc-runtime/session-state-sidecar.ts +263 -20
  237. package/src/skc-runtime/state-runtime.ts +12 -2
  238. package/src/skc-runtime/state-writer.ts +15 -0
  239. package/src/skc-runtime/tmux-common.ts +1 -0
  240. package/src/skc-runtime/ultragoal-guard.ts +55 -66
  241. package/src/skc-runtime/ultragoal-receipt-freshness.ts +315 -0
  242. package/src/skc-runtime/ultragoal-runtime.ts +1672 -159
  243. package/src/skc-runtime/workflow-manifest.generated.json +113 -2
  244. package/src/skc-runtime/workflow-manifest.ts +74 -1
  245. package/src/skill-state/active-state.ts +141 -5
  246. package/src/skill-state/deep-interview-mutation-guard.ts +67 -3
  247. package/src/slash-commands/builtin-registry.ts +296 -72
  248. package/src/system-prompt.ts +57 -16
  249. package/src/task/executor.ts +132 -24
  250. package/src/task/fork-context-advisory.ts +2 -7
  251. package/src/task/fork-context-budget.ts +9 -0
  252. package/src/task/index.ts +13 -6
  253. package/src/task/output-manager.ts +20 -8
  254. package/src/task/receipt.ts +26 -7
  255. package/src/task/token-log.test.ts +188 -0
  256. package/src/task/token-log.ts +179 -0
  257. package/src/tools/bisect.ts +367 -0
  258. package/src/tools/computer.ts +246 -43
  259. package/src/tools/index.ts +3 -0
  260. package/src/tools/output-meta.ts +116 -4
  261. package/src/tools/search.ts +8 -2
  262. package/src/tools/skill.ts +15 -0
  263. package/src/tools/telegram-send.ts +6 -0
  264. package/src/tools/ultragoal-ask-guard.ts +39 -5
  265. package/src/utils/file-mentions.ts +39 -7
  266. package/src/utils/git.ts +73 -0
  267. package/src/utils/pasted-image-path.ts +170 -0
  268. package/src/web/scrapers/youtube.ts +24 -12
  269. package/src/workflow/workflow-intent-diff.ts +29 -6
  270. package/src/workflow/workflow-intent-report-consumer.ts +221 -0
  271. package/src/workflow/workflow-intent-report-schema.ts +129 -0
  272. package/src/workflow/workflow-intent-report.ts +135 -0
@@ -1435,6 +1435,13 @@
1435
1435
  "name": "skc-goal-mode",
1436
1436
  "type": "enum"
1437
1437
  },
1438
+ {
1439
+ "appliesToVerbs": [
1440
+ "create-goals"
1441
+ ],
1442
+ "name": "validation-batch-json",
1443
+ "type": "string"
1444
+ },
1438
1445
  {
1439
1446
  "appliesToVerbs": [
1440
1447
  "complete-goals"
@@ -1473,12 +1480,93 @@
1473
1480
  "checkpoint",
1474
1481
  "record-review-blockers",
1475
1482
  "steer",
1476
- "classify-blocker"
1483
+ "classify-blocker",
1484
+ "rebaseline-pipeline-overlap"
1477
1485
  ],
1478
1486
  "name": "evidence",
1479
1487
  "required": true,
1480
1488
  "type": "string"
1481
1489
  },
1490
+ {
1491
+ "appliesToVerbs": [
1492
+ "create-goals"
1493
+ ],
1494
+ "name": "goal-metadata-json",
1495
+ "type": "string"
1496
+ },
1497
+ {
1498
+ "appliesToVerbs": [
1499
+ "start-pipeline-overlap"
1500
+ ],
1501
+ "name": "prior-goal-id",
1502
+ "required": true,
1503
+ "type": "string"
1504
+ },
1505
+ {
1506
+ "appliesToVerbs": [
1507
+ "start-pipeline-overlap"
1508
+ ],
1509
+ "name": "next-goal-id",
1510
+ "required": true,
1511
+ "type": "string"
1512
+ },
1513
+ {
1514
+ "appliesToVerbs": [
1515
+ "start-pipeline-overlap"
1516
+ ],
1517
+ "name": "review-handles-json",
1518
+ "required": true,
1519
+ "type": "string"
1520
+ },
1521
+ {
1522
+ "appliesToVerbs": [
1523
+ "start-pipeline-overlap"
1524
+ ],
1525
+ "name": "qa-handles-json",
1526
+ "required": true,
1527
+ "type": "string"
1528
+ },
1529
+ {
1530
+ "appliesToVerbs": [
1531
+ "start-pipeline-overlap"
1532
+ ],
1533
+ "name": "implementation-handle-json",
1534
+ "required": true,
1535
+ "type": "string"
1536
+ },
1537
+ {
1538
+ "appliesToVerbs": [
1539
+ "join-pipeline-overlap",
1540
+ "rebaseline-pipeline-overlap"
1541
+ ],
1542
+ "name": "overlap-id",
1543
+ "required": true,
1544
+ "type": "string"
1545
+ },
1546
+ {
1547
+ "appliesToVerbs": [
1548
+ "join-pipeline-overlap"
1549
+ ],
1550
+ "name": "review-result-json",
1551
+ "required": true,
1552
+ "type": "string"
1553
+ },
1554
+ {
1555
+ "appliesToVerbs": [
1556
+ "join-pipeline-overlap"
1557
+ ],
1558
+ "name": "qa-result-json",
1559
+ "required": true,
1560
+ "type": "string"
1561
+ },
1562
+ {
1563
+ "appliesToVerbs": [
1564
+ "rebaseline-pipeline-overlap"
1565
+ ],
1566
+ "name": "target-state-json",
1567
+ "required": true,
1568
+ "type": "string"
1569
+ },
1482
1570
  {
1483
1571
  "appliesToVerbs": [
1484
1572
  "checkpoint"
@@ -1500,6 +1588,14 @@
1500
1588
  "name": "goal-id",
1501
1589
  "type": "string"
1502
1590
  },
1591
+ {
1592
+ "appliesToVerbs": [
1593
+ "rebaseline-pipeline-overlap"
1594
+ ],
1595
+ "name": "goal-id",
1596
+ "required": true,
1597
+ "type": "string"
1598
+ },
1503
1599
  {
1504
1600
  "appliesToVerbs": [
1505
1601
  "classify-blocker"
@@ -1612,7 +1708,10 @@
1612
1708
  "checkpoint",
1613
1709
  "record-review-blockers",
1614
1710
  "steer",
1615
- "classify-blocker"
1711
+ "classify-blocker",
1712
+ "start-pipeline-overlap",
1713
+ "join-pipeline-overlap",
1714
+ "rebaseline-pipeline-overlap"
1616
1715
  ],
1617
1716
  "name": "json",
1618
1717
  "type": "boolean"
@@ -1697,6 +1796,18 @@
1697
1796
  "name": "classify-blocker",
1698
1797
  "surface": "command-positional"
1699
1798
  },
1799
+ {
1800
+ "name": "start-pipeline-overlap",
1801
+ "surface": "command-positional"
1802
+ },
1803
+ {
1804
+ "name": "join-pipeline-overlap",
1805
+ "surface": "command-positional"
1806
+ },
1807
+ {
1808
+ "name": "rebaseline-pipeline-overlap",
1809
+ "surface": "command-positional"
1810
+ },
1700
1811
  {
1701
1812
  "name": "graph",
1702
1813
  "planned": true,
@@ -243,6 +243,9 @@ export const WORKFLOW_MANIFEST: Record<CanonicalSkcWorkflowSkill, SkillManifest>
243
243
  "record-review-blockers",
244
244
  "steer",
245
245
  "classify-blocker",
246
+ "start-pipeline-overlap",
247
+ "join-pipeline-overlap",
248
+ "rebaseline-pipeline-overlap",
246
249
  ]),
247
250
  ...plannedVerbs(PLANNED_ADMIN_VERBS),
248
251
  ],
@@ -256,6 +259,7 @@ export const WORKFLOW_MANIFEST: Record<CanonicalSkcWorkflowSkill, SkillManifest>
256
259
  enumValues: ["aggregate", "per-story"],
257
260
  appliesToVerbs: ["create-goals"],
258
261
  },
262
+ { name: "validation-batch-json", type: "string", appliesToVerbs: ["create-goals"] },
259
263
  { name: "retry-failed", type: "boolean", appliesToVerbs: ["complete-goals"] },
260
264
  { name: "goal-id", type: "string", required: true, appliesToVerbs: ["checkpoint", "record-review-blockers"] },
261
265
  {
@@ -269,11 +273,77 @@ export const WORKFLOW_MANIFEST: Record<CanonicalSkcWorkflowSkill, SkillManifest>
269
273
  name: "evidence",
270
274
  type: "string",
271
275
  required: true,
272
- appliesToVerbs: ["checkpoint", "record-review-blockers", "steer", "classify-blocker"],
276
+ appliesToVerbs: [
277
+ "checkpoint",
278
+ "record-review-blockers",
279
+ "steer",
280
+ "classify-blocker",
281
+ "rebaseline-pipeline-overlap",
282
+ ],
283
+ },
284
+ {
285
+ name: "goal-metadata-json",
286
+ type: "string",
287
+ appliesToVerbs: ["create-goals"],
288
+ },
289
+ {
290
+ name: "prior-goal-id",
291
+ type: "string",
292
+ required: true,
293
+ appliesToVerbs: ["start-pipeline-overlap"],
294
+ },
295
+ {
296
+ name: "next-goal-id",
297
+ type: "string",
298
+ required: true,
299
+ appliesToVerbs: ["start-pipeline-overlap"],
300
+ },
301
+ {
302
+ name: "review-handles-json",
303
+ type: "string",
304
+ required: true,
305
+ appliesToVerbs: ["start-pipeline-overlap"],
306
+ },
307
+ {
308
+ name: "qa-handles-json",
309
+ type: "string",
310
+ required: true,
311
+ appliesToVerbs: ["start-pipeline-overlap"],
312
+ },
313
+ {
314
+ name: "implementation-handle-json",
315
+ type: "string",
316
+ required: true,
317
+ appliesToVerbs: ["start-pipeline-overlap"],
318
+ },
319
+ {
320
+ name: "overlap-id",
321
+ type: "string",
322
+ required: true,
323
+ appliesToVerbs: ["join-pipeline-overlap", "rebaseline-pipeline-overlap"],
324
+ },
325
+ {
326
+ name: "review-result-json",
327
+ type: "string",
328
+ required: true,
329
+ appliesToVerbs: ["join-pipeline-overlap"],
330
+ },
331
+ {
332
+ name: "qa-result-json",
333
+ type: "string",
334
+ required: true,
335
+ appliesToVerbs: ["join-pipeline-overlap"],
336
+ },
337
+ {
338
+ name: "target-state-json",
339
+ type: "string",
340
+ required: true,
341
+ appliesToVerbs: ["rebaseline-pipeline-overlap"],
273
342
  },
274
343
  { name: "quality-gate-json", type: "string", appliesToVerbs: ["checkpoint"] },
275
344
  { name: "goal-id", type: "string", appliesToVerbs: ["steer"] },
276
345
  { name: "goal-id", type: "string", appliesToVerbs: ["classify-blocker"] },
346
+ { name: "goal-id", type: "string", required: true, appliesToVerbs: ["rebaseline-pipeline-overlap"] },
277
347
  {
278
348
  name: "classification",
279
349
  type: "enum",
@@ -321,6 +391,9 @@ export const WORKFLOW_MANIFEST: Record<CanonicalSkcWorkflowSkill, SkillManifest>
321
391
  "record-review-blockers",
322
392
  "steer",
323
393
  "classify-blocker",
394
+ "start-pipeline-overlap",
395
+ "join-pipeline-overlap",
396
+ "rebaseline-pipeline-overlap",
324
397
  ],
325
398
  },
326
399
  { name: "directive-json", type: "string", appliesToVerbs: ["steer"], planned: true },
@@ -1,11 +1,19 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as path from "node:path";
1
3
  import * as logger from "@sayknow-cli/utils/logger";
2
- import { activeSnapshotPath, assertNonEmptySkcSessionId, modeStatePath } from "../skc-runtime/session-layout";
4
+ import {
5
+ activeSnapshotPath,
6
+ activeStateDir,
7
+ assertNonEmptySkcSessionId,
8
+ modeStatePath,
9
+ } from "../skc-runtime/session-layout";
3
10
  import { resolveSkcSessionForRead, SessionResolutionError } from "../skc-runtime/session-resolution";
4
11
  import {
5
12
  type ActiveSessionScope,
6
13
  readActiveEntries,
7
14
  rebuildActiveSnapshot,
8
15
  removeActiveEntry,
16
+ setActiveStateCacheInvalidator,
9
17
  writeActiveEntry,
10
18
  } from "../skc-runtime/state-writer";
11
19
  import { CANONICAL_SKC_WORKFLOW_SKILLS, type CanonicalSkcWorkflowSkill } from "./canonical-skills";
@@ -614,14 +622,108 @@ async function mergeVisibleEntries(
614
622
  return collapsePlanningPipeline(visibleEntries).toSorted(comparePipelineEntry);
615
623
  }
616
624
 
617
- export async function readVisibleSkillActiveState(cwd: string, sessionId?: string): Promise<SkillActiveState | null> {
618
- let resolvedSessionId: string;
625
+ export type VisibleSkillActiveStateCacheTier = "security" | "hud";
626
+ export interface ReadVisibleSkillActiveStateOptions {
627
+ tier?: VisibleSkillActiveStateCacheTier;
628
+ }
629
+
630
+ interface ActiveStateStatSignature {
631
+ path: string;
632
+ mtimeMs: number;
633
+ size: number;
634
+ }
635
+
636
+ interface ActiveStateSignature {
637
+ sessionPath: ActiveStateStatSignature | null;
638
+ activeDir: ActiveStateStatSignature | null;
639
+ activeEntries: ActiveStateStatSignature[];
640
+ ralplanModeState: ActiveStateStatSignature | null;
641
+ }
642
+
643
+ interface VisibleSkillActiveStateCacheEntry {
644
+ signature: ActiveStateSignature;
645
+ value: SkillActiveState | null;
646
+ cachedAtMs: number;
647
+ }
648
+
649
+ const HUD_VISIBLE_STATE_TTL_MS = 500;
650
+ const SECURITY_VISIBLE_STATE_TTL_MS = 30_000;
651
+ const visibleSkillActiveStateCache = new Map<string, VisibleSkillActiveStateCacheEntry>();
652
+
653
+ async function statSignature(filePath: string): Promise<ActiveStateStatSignature | null> {
619
654
  try {
620
- resolvedSessionId = await resolveBoundarySessionId(cwd, sessionId);
655
+ const stat = await fs.stat(filePath);
656
+ return { path: filePath, mtimeMs: stat.mtimeMs, size: stat.size };
621
657
  } catch (error) {
622
- if (error instanceof SessionResolutionError && error.code === "no_session") return null;
658
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return null;
623
659
  throw error;
624
660
  }
661
+ }
662
+
663
+ function signaturesEqual(a: ActiveStateSignature, b: ActiveStateSignature): boolean {
664
+ const statEqual = (left: ActiveStateStatSignature | null, right: ActiveStateStatSignature | null): boolean =>
665
+ left === right ||
666
+ (Boolean(left) &&
667
+ Boolean(right) &&
668
+ left?.path === right?.path &&
669
+ left?.mtimeMs === right?.mtimeMs &&
670
+ left?.size === right?.size);
671
+ if (!statEqual(a.sessionPath, b.sessionPath)) return false;
672
+ if (!statEqual(a.activeDir, b.activeDir)) return false;
673
+ if (!statEqual(a.ralplanModeState, b.ralplanModeState)) return false;
674
+ if (a.activeEntries.length !== b.activeEntries.length) return false;
675
+ return a.activeEntries.every((entry, index) => statEqual(entry, b.activeEntries[index] ?? null));
676
+ }
677
+
678
+ export async function computeActiveStateSignature(cwd: string, sessionId: string): Promise<ActiveStateSignature> {
679
+ const resolvedCwd = path.resolve(cwd);
680
+ const { sessionPath } = getSkillActiveStatePaths(resolvedCwd, sessionId);
681
+ const activeDirPath = activeStateDir(resolvedCwd, sessionId);
682
+ const activeDir = await statSignature(activeDirPath);
683
+ let activeEntries: ActiveStateStatSignature[] = [];
684
+ try {
685
+ const names = await fs.readdir(activeDirPath);
686
+ activeEntries = (
687
+ await Promise.all(
688
+ names
689
+ .filter(name => name.endsWith(".json"))
690
+ .sort()
691
+ .map(name => statSignature(path.join(activeDirPath, name))),
692
+ )
693
+ ).filter((entry): entry is ActiveStateStatSignature => entry !== null);
694
+ } catch (error) {
695
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
696
+ }
697
+ return {
698
+ sessionPath: await statSignature(sessionPath),
699
+ activeDir,
700
+ activeEntries,
701
+ ralplanModeState: await statSignature(modeStatePath(resolvedCwd, sessionId, "ralplan")),
702
+ };
703
+ }
704
+
705
+ function visibleActiveStateCacheKey(cwd: string, sessionId: string): string {
706
+ return `${path.resolve(cwd)}\0${sessionId}`;
707
+ }
708
+
709
+ export function invalidateVisibleSkillActiveStateCache(cwd?: string, sessionId?: string): void {
710
+ if (!cwd && !sessionId) {
711
+ visibleSkillActiveStateCache.clear();
712
+ return;
713
+ }
714
+ const resolvedCwd = cwd ? path.resolve(cwd) : undefined;
715
+ const suffix = sessionId ? `\0${sessionId}` : undefined;
716
+ for (const key of [...visibleSkillActiveStateCache.keys()]) {
717
+ if (resolvedCwd && !key.startsWith(`${resolvedCwd}\0`)) continue;
718
+ if (suffix && !key.endsWith(suffix)) continue;
719
+ visibleSkillActiveStateCache.delete(key);
720
+ }
721
+ }
722
+
723
+ async function readVisibleSkillActiveStateUncached(
724
+ cwd: string,
725
+ resolvedSessionId: string,
726
+ ): Promise<SkillActiveState | null> {
625
727
  const { sessionPath } = getSkillActiveStatePaths(cwd, resolvedSessionId);
626
728
  const sessionState = await readRawActiveStateForHandoff(sessionPath, false);
627
729
  const activeSkills = await mergeVisibleEntries(cwd, sessionState, resolvedSessionId);
@@ -639,6 +741,40 @@ export async function readVisibleSkillActiveState(cwd: string, sessionId?: strin
639
741
  };
640
742
  }
641
743
 
744
+ setActiveStateCacheInvalidator(invalidateVisibleSkillActiveStateCache);
745
+
746
+ export async function readVisibleSkillActiveState(
747
+ cwd: string,
748
+ sessionId?: string,
749
+ opts?: ReadVisibleSkillActiveStateOptions,
750
+ ): Promise<SkillActiveState | null> {
751
+ let resolvedSessionId: string;
752
+ try {
753
+ resolvedSessionId = await resolveBoundarySessionId(cwd, sessionId);
754
+ } catch (error) {
755
+ if (error instanceof SessionResolutionError && error.code === "no_session") return null;
756
+ throw error;
757
+ }
758
+ const resolvedCwd = path.resolve(cwd);
759
+ const cacheKey = visibleActiveStateCacheKey(resolvedCwd, resolvedSessionId);
760
+ const tier = opts?.tier ?? "security";
761
+ const now = Date.now();
762
+ const cached = visibleSkillActiveStateCache.get(cacheKey);
763
+ if (tier === "hud" && cached && now - cached.cachedAtMs < HUD_VISIBLE_STATE_TTL_MS) return cached.value;
764
+
765
+ const signature = await computeActiveStateSignature(resolvedCwd, resolvedSessionId);
766
+ if (
767
+ cached &&
768
+ signaturesEqual(cached.signature, signature) &&
769
+ (tier === "hud" || now - cached.cachedAtMs < SECURITY_VISIBLE_STATE_TTL_MS)
770
+ ) {
771
+ return cached.value;
772
+ }
773
+ const value = await readVisibleSkillActiveStateUncached(resolvedCwd, resolvedSessionId);
774
+ visibleSkillActiveStateCache.set(cacheKey, { signature, value, cachedAtMs: now });
775
+ return value;
776
+ }
777
+
642
778
  function activeStateWriterAudit(verb: string, sessionScope?: ActiveSessionScope | string) {
643
779
  const sessionId = typeof sessionScope === "string" ? sessionScope : sessionScope?.sessionId;
644
780
  return { category: "state" as const, verb, owner: "skc-runtime" as const, ...(sessionId ? { sessionId } : {}) };
@@ -33,10 +33,18 @@ function planningPhaseBlockMessage(skill: CanonicalSkcWorkflowSkill): string {
33
33
  return DEEP_INTERVIEW_MUTATION_BLOCK_MESSAGE;
34
34
  }
35
35
 
36
- const BLOCKED_TOOL_NAMES = new Set(["edit", "write", "ast_edit"]);
36
+ const BLOCKED_TOOL_NAMES = new Set(["edit", "write", "ast_edit", "bash"]);
37
37
  const ARCHIVE_OR_SQLITE_BASE_RE = /^(.+?\.(?:tar\.gz|sqlite3|sqlite|db3|zip|tgz|tar|db))(?:$|:)/i;
38
38
  const INTERNAL_SCHEME_RE = /^[a-z][a-z0-9+.-]*:\/\//i;
39
39
  const VIM_FILE_SWITCH_RE = /^\s*:(?:e|e!|edit|edit!)(?:\s+([^<\r\n]+))?(?:<CR>|\r|\n|$)/i;
40
+ const BASH_MUTATION_COMMAND_RE =
41
+ /(?:^|[;&|\n])\s*(?:\w+=[^\s]+\s+)*(?:sudo\s+)?(?:tee|touch|rm|mkdir|cp|mv|install|truncate)\b([^;&|\n]*)|(?:^|[^<>])(?:>>?|\d>>?)\s*([^\s;&|]+)/gi;
42
+ const BASH_IN_PLACE_MUTATION_COMMAND_RE = /(?:^|[;&|\n])\s*(?:\w+=[^\s]+\s+)*(?:sudo\s+)?(?:sed|perl)\b([^;&|\n]*)/gi;
43
+ const BASH_OPAQUE_INTERPRETER_WRITE_RE =
44
+ /(?:^|[;&|\n])\s*(?:\w+=[^\s]+\s+)*(?:sudo\s+)?(?:python3?|node|ruby)\b[^;&|\n]*(?:-c|-e)\b[^;&|\n]*(?:open\s*\(|writeFile(?:Sync)?\s*\(|\.write\s*\()/i;
45
+ const BASH_HEREDOC_OPAQUE_INTERPRETER_WRITE_RE =
46
+ /(?:^|[;&|\n])\s*(?:\w+=[^\s]+\s+)*(?:sudo\s+)?(?:python3?|node|ruby)\b[^;&|\n]*(?:<<[-]?\s*['"]?\w+['"]?)[\s\S]*(?:open\s*\(|writeFile(?:Sync)?\s*\(|\.write\s*\()/i;
47
+ const BASH_DD_OUTPUT_RE = /(?:^|[;&|\n])\s*(?:\w+=[^\s]+\s+)*(?:sudo\s+)?dd\b([^;&|\n]*)/gi;
40
48
 
41
49
  type ToolWithEditMode = AgentTool & {
42
50
  mode?: unknown;
@@ -214,7 +222,7 @@ async function getActivePlanningSkill(
214
222
  ): Promise<ActivePlanningSkill | null> {
215
223
  const resolvedSessionId = await resolveBoundarySessionId(cwd, sessionId);
216
224
  if (!resolvedSessionId) return null;
217
- const skillState = await readVisibleSkillActiveState(cwd, resolvedSessionId);
225
+ const skillState = await readVisibleSkillActiveState(cwd, resolvedSessionId, { tier: "security" });
218
226
  if (!skillState) return null;
219
227
  const activeEntries = listActiveSkills(skillState).filter(entry =>
220
228
  entryMatchesContext(entry, resolvedSessionId, threadId),
@@ -329,11 +337,66 @@ function extractEditTargets(args: unknown, tool: ToolWithEditMode): ExtractedTar
329
337
  if (targets.paths.length === 0) targets.unknown = true;
330
338
  return targets;
331
339
  }
340
+ function shellWords(argsText: string): string[] {
341
+ return argsText.match(/(?:[^\s'"\\]+|'[^']*'|"[^"]*")+/g) ?? [];
342
+ }
343
+
344
+ function cleanShellWord(value: string): string {
345
+ return value.replace(/^['"]|['"]$/g, "");
346
+ }
332
347
 
348
+ function extractBashTargets(args: unknown): ExtractedTargets {
349
+ const record = getRecord(args);
350
+ const command = safeString(record?.command);
351
+ const targets: ExtractedTargets = { paths: [], unknown: false };
352
+ if (!command.trim()) {
353
+ targets.unknown = true;
354
+ return targets;
355
+ }
356
+ if (BASH_OPAQUE_INTERPRETER_WRITE_RE.test(command) || BASH_HEREDOC_OPAQUE_INTERPRETER_WRITE_RE.test(command)) {
357
+ targets.unknown = true;
358
+ }
359
+ for (const match of command.matchAll(BASH_DD_OUTPUT_RE)) {
360
+ const parts = shellWords(match[1] ?? "").map(cleanShellWord);
361
+ const output = parts.find(part => part.startsWith("of="));
362
+ if (output) addPath(targets, output.slice(3));
363
+ else targets.unknown = true;
364
+ }
365
+ for (const match of command.matchAll(BASH_IN_PLACE_MUTATION_COMMAND_RE)) {
366
+ const parts = shellWords(match[1] ?? "").map(cleanShellWord);
367
+ const hasInPlaceFlag = parts.some(part => /^-.*i/.test(part));
368
+ if (!hasInPlaceFlag) continue;
369
+ const target = [...parts].reverse().find(part => part && !part.startsWith("-"));
370
+ if (target) addPath(targets, target);
371
+ else targets.unknown = true;
372
+ }
373
+ for (const match of command.matchAll(BASH_MUTATION_COMMAND_RE)) {
374
+ const redirected = match[2]?.trim();
375
+ if (redirected) {
376
+ addPath(targets, cleanShellWord(redirected));
377
+ continue;
378
+ }
379
+ const parts = shellWords(match[1] ?? "");
380
+ const commandName = match[0]
381
+ ?.match(/(?:^|[;&|\n])\s*(?:\w+=[^\s]+\s+)*(?:sudo\s+)?(tee|touch|rm|mkdir|cp|mv|install|truncate)\b/i)?.[1]
382
+ ?.toLowerCase();
383
+ const targetParts =
384
+ commandName === "cp" || commandName === "mv" || commandName === "install" || commandName === "truncate"
385
+ ? parts.slice(-1)
386
+ : parts;
387
+ for (const part of targetParts) {
388
+ const cleaned = cleanShellWord(part);
389
+ if (!cleaned || cleaned.startsWith("-")) continue;
390
+ addPath(targets, cleaned);
391
+ }
392
+ }
393
+ return targets;
394
+ }
333
395
  function extractTargets(tool: ToolWithEditMode, args: unknown): ExtractedTargets {
334
396
  if (tool.name === "write") return extractWriteTargets(args);
335
397
  if (tool.name === "ast_edit") return extractAstEditTargets(args);
336
398
  if (tool.name === "edit") return extractEditTargets(args, tool);
399
+ if (tool.name === "bash") return extractBashTargets(args);
337
400
  return { paths: [], unknown: true };
338
401
  }
339
402
 
@@ -490,6 +553,7 @@ async function isNeutralTempPath(cwd: string, rawPath: string): Promise<boolean>
490
553
  async function planningBlockedTargets(cwd: string, targets: ExtractedTargets): Promise<string[]> {
491
554
  const blocked: string[] = [];
492
555
  for (const rawPath of targets.paths) {
556
+ if (isAllowlistedPath(cwd, rawPath)) continue;
493
557
  if (!(await isNeutralTempPath(cwd, rawPath))) blocked.push(rawPath);
494
558
  }
495
559
  return blocked;
@@ -523,7 +587,7 @@ export async function getDeepInterviewMutationDecision(
523
587
  ): Promise<DeepInterviewMutationDecision> {
524
588
  if (!BLOCKED_TOOL_NAMES.has(input.tool.name)) return { blocked: false, targets: [] };
525
589
  const targets = extractTargets(input.tool, input.args);
526
- if (input.enforceWorkflowState !== false && hasBlockedSkcTarget(input.cwd, targets)) {
590
+ if (input.tool.name !== "bash" && input.enforceWorkflowState !== false && hasBlockedSkcTarget(input.cwd, targets)) {
527
591
  const stateSkill = firstBlockedWorkflowStateSkill(input.cwd, targets);
528
592
  const command = stateSkill ? sanctionedWorkflowStateCommand(stateSkill) : "skc <workflow-command>";
529
593
  return {