@astrosheep/keiyaku 4.0.4 → 4.0.6

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 (233) hide show
  1. package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +1 -1
  2. package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +1 -1
  3. package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
  4. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +4 -4
  5. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +15 -7
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +5 -3
  7. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +24 -4
  8. package/build/src/akuma/akuma.d.ts +2 -1
  9. package/build/src/akuma/akuma.js +27 -9
  10. package/build/src/akuma/allowed.d.ts +1 -1
  11. package/build/src/akuma/allowed.js +3 -10
  12. package/build/src/akuma/archetype.d.ts +3 -1
  13. package/build/src/akuma/archetype.js +11 -6
  14. package/build/src/akuma/body-turn.d.ts +64 -0
  15. package/build/src/akuma/body-turn.js +449 -0
  16. package/build/src/akuma/body.d.ts +4 -5
  17. package/build/src/akuma/body.js +9 -414
  18. package/build/src/akuma/heart/facts.d.ts +37 -9
  19. package/build/src/akuma/heart/facts.js +3 -1
  20. package/build/src/akuma/heart/index.d.ts +4 -13
  21. package/build/src/akuma/heart/index.js +14 -135
  22. package/build/src/akuma/heart/request-authority.d.ts +12 -0
  23. package/build/src/akuma/heart/request-authority.js +119 -0
  24. package/build/src/akuma/heart/request-rows.d.ts +16 -0
  25. package/build/src/akuma/heart/request-rows.js +88 -0
  26. package/build/src/akuma/heart/rows.d.ts +1 -28
  27. package/build/src/akuma/heart/rows.js +4 -138
  28. package/build/src/akuma/heart/schema.d.ts +1 -1
  29. package/build/src/akuma/heart/schema.js +11 -3
  30. package/build/src/akuma/heart/soul.js +0 -36
  31. package/build/src/akuma/heart/timeline.d.ts +1 -0
  32. package/build/src/akuma/heart/timeline.js +19 -0
  33. package/build/src/akuma/index.d.ts +1 -1
  34. package/build/src/akuma/nuke.d.ts +2 -0
  35. package/build/src/akuma/nuke.js +152 -0
  36. package/build/src/akuma/provider-recipe.js +1 -11
  37. package/build/src/akuma/provider.d.ts +4 -7
  38. package/build/src/akuma/providers/acp/config.d.ts +8 -0
  39. package/build/src/akuma/providers/acp/config.js +37 -0
  40. package/build/src/akuma/providers/acp/core.js +12 -2
  41. package/build/src/akuma/providers/acp/index.d.ts +1 -8
  42. package/build/src/akuma/providers/acp/index.js +2 -38
  43. package/build/src/akuma/providers/claude/index.d.ts +0 -4
  44. package/build/src/akuma/providers/claude/index.js +12 -3
  45. package/build/src/akuma/providers/codex-app-server/index.d.ts +2 -27
  46. package/build/src/akuma/providers/codex-app-server/index.js +5 -2
  47. package/build/src/akuma/providers/grok-build/index.js +1 -2
  48. package/build/src/akuma/providers/index.d.ts +3 -2
  49. package/build/src/akuma/providers/index.js +36 -36
  50. package/build/src/akuma/providers/opencode-sdk/index.d.ts +2 -28
  51. package/build/src/akuma/providers/opencode-sdk/index.js +14 -4
  52. package/build/src/akuma/providers/opencode-sdk/session.d.ts +2 -2
  53. package/build/src/akuma/providers/opencode-sdk/session.js +2 -2
  54. package/build/src/akuma/providers/pi/index.d.ts +1 -1
  55. package/build/src/akuma/providers/pi/index.js +29 -6
  56. package/build/src/akuma/request-serve.d.ts +88 -0
  57. package/build/src/akuma/request-serve.js +484 -0
  58. package/build/src/akuma/request-wire.d.ts +125 -0
  59. package/build/src/akuma/request-wire.js +383 -0
  60. package/build/src/akuma/requests.d.ts +28 -94
  61. package/build/src/akuma/requests.js +52 -562
  62. package/build/src/akuma-body.d.ts +7 -0
  63. package/build/src/akuma-body.js +69 -2
  64. package/build/src/alias/index.d.ts +1 -0
  65. package/build/src/alias/index.js +34 -1
  66. package/build/src/body/arc.js +4 -29
  67. package/build/src/body/decode.js +5 -39
  68. package/build/src/body/envelope.d.ts +7 -0
  69. package/build/src/body/envelope.js +37 -0
  70. package/build/src/cli/accepted.js +21 -9
  71. package/build/src/cli/commands/akuma-invoke.js +1 -0
  72. package/build/src/cli/commands/akuma.d.ts +1 -0
  73. package/build/src/cli/commands/akuma.js +13 -10
  74. package/build/src/cli/commands/contract.d.ts +28 -17
  75. package/build/src/cli/commands/contract.js +23 -17
  76. package/build/src/cli/commands/install.d.ts +2 -2
  77. package/build/src/cli/commands/install.js +6 -6
  78. package/build/src/cli/commands/nuke.d.ts +10 -0
  79. package/build/src/cli/commands/nuke.js +20 -0
  80. package/build/src/cli/commands/task-invoke.d.ts +15 -0
  81. package/build/src/cli/commands/task-invoke.js +144 -24
  82. package/build/src/cli/commands/task-query.d.ts +2 -2
  83. package/build/src/cli/commands/task-query.js +1 -2
  84. package/build/src/cli/commands/task.js +22 -22
  85. package/build/src/cli/coordinates.d.ts +6 -2
  86. package/build/src/cli/coordinates.js +12 -56
  87. package/build/src/cli/invoke.d.ts +5 -4
  88. package/build/src/cli/invoke.js +112 -58
  89. package/build/src/cli/main.d.ts +0 -2
  90. package/build/src/cli/main.js +4 -140
  91. package/build/src/cli/parse.d.ts +17 -4
  92. package/build/src/cli/parse.js +93 -15
  93. package/build/src/cli/render/akuma.js +111 -53
  94. package/build/src/cli/render/audit.js +2 -6
  95. package/build/src/cli/render/contract.js +61 -20
  96. package/build/src/cli/render/kanshi.js +15 -5
  97. package/build/src/cli/render/nuke.d.ts +3 -0
  98. package/build/src/cli/render/nuke.js +8 -0
  99. package/build/src/cli/render/receipt.js +28 -1
  100. package/build/src/cli/render/refusal.d.ts +2 -1
  101. package/build/src/cli/render/refusal.js +31 -0
  102. package/build/src/cli/render/terminal.d.ts +0 -2
  103. package/build/src/cli/render/terminal.js +0 -29
  104. package/build/src/cli/render/text.js +6 -1
  105. package/build/src/cli/result.d.ts +36 -9
  106. package/build/src/cli/runtime.d.ts +2 -0
  107. package/build/src/cli/runtime.js +140 -0
  108. package/build/src/cli/usage.d.ts +0 -2
  109. package/build/src/cli/usage.js +0 -4
  110. package/build/src/contract-worktree.d.ts +29 -14
  111. package/build/src/contract-worktree.js +131 -70
  112. package/build/src/core/facts/codec.js +9 -0
  113. package/build/src/core/facts/fold.js +13 -1
  114. package/build/src/core/facts/types.d.ts +8 -1
  115. package/build/src/core/subject.js +4 -3
  116. package/build/src/core/verbs/placement.d.ts +9 -1
  117. package/build/src/core/verbs/placement.js +24 -6
  118. package/build/src/core/verbs/reintegrate.d.ts +13 -0
  119. package/build/src/core/verbs/reintegrate.js +24 -0
  120. package/build/src/dispatch/index.d.ts +1 -1
  121. package/build/src/git/admission.d.ts +2 -1
  122. package/build/src/git/hooks.d.ts +2 -0
  123. package/build/src/git/hooks.js +34 -1
  124. package/build/src/git/integration.d.ts +9 -2
  125. package/build/src/git/integration.js +92 -1
  126. package/build/src/git/nuke.d.ts +2 -0
  127. package/build/src/git/nuke.js +97 -0
  128. package/build/src/git/observe.d.ts +2 -1
  129. package/build/src/git/observe.js +6 -5
  130. package/build/src/git/process.d.ts +28 -0
  131. package/build/src/git/process.js +94 -0
  132. package/build/src/git/read-observation.d.ts +2 -1
  133. package/build/src/git/read-observation.js +3 -2
  134. package/build/src/git/reconcile.d.ts +4 -1
  135. package/build/src/git/reconcile.js +42 -8
  136. package/build/src/git/repository.d.ts +2 -29
  137. package/build/src/git/repository.js +7 -118
  138. package/build/src/git/scratch.d.ts +1 -1
  139. package/build/src/git/scratch.js +1 -1
  140. package/build/src/git/target-placement.d.ts +3 -2
  141. package/build/src/git/target-placement.js +15 -14
  142. package/build/src/git/tender.d.ts +2 -1
  143. package/build/src/git/tender.js +4 -3
  144. package/build/src/git/terminal-seal.d.ts +2 -2
  145. package/build/src/git/terminal-seal.js +3 -6
  146. package/build/src/git/workspace.d.ts +4 -1
  147. package/build/src/git/workspace.js +1 -1
  148. package/build/src/index.d.ts +1 -2
  149. package/build/src/index.js +1 -1
  150. package/build/src/kanshi/read.js +5 -1
  151. package/build/src/library/address.js +7 -1
  152. package/build/src/library/akuma-creation.d.ts +1 -0
  153. package/build/src/library/akuma-creation.js +8 -1
  154. package/build/src/library/audit.d.ts +3 -1
  155. package/build/src/library/audit.js +2 -1
  156. package/build/src/library/bind.d.ts +2 -1
  157. package/build/src/library/bind.js +1 -1
  158. package/build/src/library/configuration.d.ts +1 -1
  159. package/build/src/library/configuration.js +52 -18
  160. package/build/src/library/contract.d.ts +59 -4
  161. package/build/src/library/contract.js +195 -34
  162. package/build/src/library/delivery.d.ts +4 -2
  163. package/build/src/library/fleet.d.ts +27 -7
  164. package/build/src/library/fleet.js +79 -39
  165. package/build/src/library/input.d.ts +0 -1
  166. package/build/src/library/input.js +0 -5
  167. package/build/src/library/keiyaku.d.ts +6 -2
  168. package/build/src/library/keiyaku.js +2 -0
  169. package/build/src/library/mutation.d.ts +3 -1
  170. package/build/src/library/mutation.js +3 -0
  171. package/build/src/library/nuke.d.ts +14 -0
  172. package/build/src/library/nuke.js +54 -0
  173. package/build/src/library/reconcile.d.ts +2 -1
  174. package/build/src/library/reconcile.js +8 -3
  175. package/build/src/library/refusal.d.ts +10 -1
  176. package/build/src/library/region.d.ts +1 -1
  177. package/build/src/library/repo.d.ts +4 -1
  178. package/build/src/library/repo.js +10 -4
  179. package/build/src/protocol/abandon.d.ts +9 -0
  180. package/build/src/protocol/abandon.js +15 -0
  181. package/build/src/protocol/amend.d.ts +16 -0
  182. package/build/src/protocol/amend.js +77 -0
  183. package/build/src/protocol/arc.d.ts +6 -0
  184. package/build/src/protocol/arc.js +12 -0
  185. package/build/src/protocol/attempt.d.ts +2 -1
  186. package/build/src/protocol/audit.d.ts +53 -0
  187. package/build/src/protocol/audit.js +147 -0
  188. package/build/src/protocol/bind.d.ts +1 -1
  189. package/build/src/protocol/completion.d.ts +42 -0
  190. package/build/src/protocol/completion.js +183 -0
  191. package/build/src/protocol/deliver.d.ts +49 -0
  192. package/build/src/protocol/deliver.js +261 -0
  193. package/build/src/protocol/intent.d.ts +2 -1
  194. package/build/src/protocol/intent.js +8 -2
  195. package/build/src/protocol/operations.d.ts +93 -202
  196. package/build/src/protocol/operations.js +23 -642
  197. package/build/src/protocol/placement.d.ts +12 -13
  198. package/build/src/protocol/placement.js +8 -19
  199. package/build/src/protocol/read/status.d.ts +17 -5
  200. package/build/src/protocol/read/status.js +57 -13
  201. package/build/src/protocol/reconcile.d.ts +35 -0
  202. package/build/src/protocol/reconcile.js +41 -0
  203. package/build/src/protocol/reintegrate.d.ts +31 -0
  204. package/build/src/protocol/reintegrate.js +74 -0
  205. package/build/src/protocol/review.d.ts +34 -0
  206. package/build/src/protocol/review.js +156 -0
  207. package/build/src/protocol/run.d.ts +1 -1
  208. package/build/src/runtime/proc/run.js +9 -5
  209. package/build/src/settlement/fence.d.ts +3 -1
  210. package/build/src/settlement/fence.js +24 -0
  211. package/build/src/settlement/holder.d.ts +1 -1
  212. package/build/src/settlement/settle.d.ts +1 -1
  213. package/build/src/settlement/settle.js +1 -2
  214. package/build/src/task/board.d.ts +0 -1
  215. package/build/src/task/board.js +0 -3
  216. package/build/src/task/compose.d.ts +2 -2
  217. package/build/src/task/compose.js +13 -11
  218. package/build/src/task/context.d.ts +14 -2
  219. package/build/src/task/context.js +30 -7
  220. package/build/src/task/index.d.ts +7 -6
  221. package/build/src/task/index.js +17 -145
  222. package/build/src/task/input.d.ts +18 -0
  223. package/build/src/task/input.js +189 -0
  224. package/build/src/task/mutation.d.ts +44 -0
  225. package/build/src/task/mutation.js +93 -0
  226. package/build/src/task/operations.d.ts +14 -6
  227. package/build/src/task/operations.js +57 -57
  228. package/build/src/task/store.d.ts +1 -0
  229. package/build/src/task/store.js +91 -3
  230. package/build/src/verification/execution.d.ts +1 -1
  231. package/build/src/workspace-place.d.ts +3 -4
  232. package/build/src/workspace-place.js +26 -15
  233. package/package.json +3 -3
@@ -1,20 +1,26 @@
1
- export const AMEND_MINIMAL_STDIN_HELP = [
2
- "minimal stdin:",
3
- " ## Replace: Design",
4
- " <complete replacement>",
1
+ export const AMEND_OPERATIONS_HELP = [
2
+ "stdin operations (H2 sections only, no H1):",
3
+ " ## Replace: Context|Objective|Design|Region|Criteria|Verification|<extension>",
4
+ " ## Append: Context|Objective|Design|Criteria|<extension>",
5
+ " ## Add: Criteria|<new-extension-title>",
6
+ " ## Update: Criterion <existing-title>|<existing-extension-title>",
7
+ " ## Remove: Criterion <existing-title>|<existing-extension-title>",
8
+ "",
9
+ "full operation grammar: docs/document.md, Amend Operations",
5
10
  ].join("\n");
6
11
  export const CONTRACT_COMMAND_SPECS = {
7
- bind: { positional: "none", stdin: "required", flags: { actor: "value", task: "value", target: "value", here: "boolean", after: "repeat-value", gates: "value", json: "boolean" }, usage: "bind [--task <task/...>] [--target <ref>] [--here] [--after <kei/...> ...] [--gates <name>] [--actor <actor>] [--json] -", purpose: "Create one Contract from stdin Markdown." },
8
- amend: { positional: "optional", stdin: "optional", flags: { actor: "value", after: "repeat-value", "clear-after": "boolean", gates: "value", json: "boolean" }, usage: "amend [<contract>|@<contract>] [--after <kei/...> ... | --clear-after] [--gates <name>] [--actor <actor>] [--json] [-]", purpose: "Amend one Contract's document operations or structured terms." },
9
- deliver: { positional: "optional", stdin: "none", flags: { actor: "value", message: "value", "include-dirty": "boolean", json: "boolean" }, usage: "deliver [<contract>|@<contract>] [--message <text>] [--include-dirty] [--actor <actor>] [--json]", purpose: "Deliver one Contract candidate." },
10
- review: { positional: "optional", stdin: "optional", flags: { actor: "value", satisfied: "boolean", unsatisfied: "boolean", summary: "value", json: "boolean" }, usage: "review [<contract>|@<contract>] (--satisfied | --unsatisfied) (--summary <text> | -) [--actor <actor>] [--json]", purpose: "Record one review verdict." },
11
- arc: { positional: "optional", stdin: "required", flags: { actor: "value", json: "boolean" }, usage: "arc [<contract>|@<contract>] [--actor <actor>] [--json] -", purpose: "Record stdin arc Markdown for one Contract." },
12
- abandon: { positional: "optional", stdin: "none", flags: { actor: "value", note: "value", json: "boolean" }, usage: "abandon [<contract>|@<contract>] [--note <text>] [--actor <actor>] [--json]", purpose: "Abandon one Contract with an optional note." },
13
- status: { positional: "optional", stdin: "none", flags: { json: "boolean" }, usage: "status [<contract>|@name|<aku/...>] [--json]", purpose: "Read the world status board or one Contract projection." },
14
- show: { positional: "optional", stdin: "none", flags: { json: "boolean" }, usage: "show [<contract>|@<contract>] [--json]", purpose: "Read one Contract guidance projection." },
15
- ls: { positional: "optional", stdin: "none", flags: { json: "boolean" }, usage: "ls task/ [--json]\n keiyaku ls kei/ [--json]\n keiyaku ls aku/ [--json]\n keiyaku ls aku/<akuma>/ [--json]\n keiyaku ls \"aku/*/*\" [--json]", purpose: "List one identity directory." },
16
- audit: { positional: "optional", stdin: "none", flags: { "include-dirty": "boolean", diff: "boolean", actor: "value", json: "boolean" }, usage: "audit [<contract>|@<contract>] [--include-dirty] [--diff] [--actor <actor>] [--json]", purpose: "Ask what candidate preparation, Verification, and target placement would do." },
17
- reconcile: { positional: "optional", stdin: "none", flags: { "retry-hooks": "boolean", json: "boolean" }, usage: "reconcile [<contract>|@<contract>] [--retry-hooks] [--json]", purpose: "Reconcile one Contract or the invocation world." },
18
- settings: { positional: "none", stdin: "none", flags: { json: "boolean" }, usage: "settings [--json]", purpose: "Read user and project Settings resources." },
19
- region: { positional: "optional", stdin: "none", flags: { overlap: "boolean", path: "value", json: "boolean" }, usage: "region [<contract>] [--overlap] [--json]\n region --path <repo-relative-path> [--json]", purpose: "Read active declared Contract Regions." },
12
+ bind: { positional: "none", stdin: "required", flags: { actor: "value", task: "value", target: "value", here: "boolean", after: "repeat-value", gates: "raw-value", json: "boolean" }, usage: "bind [--task <task/...>] [--target <ref>] [--here] [--after <kei/...> ...] [--gates <name,...>] [--actor <actor>] -", purpose: "Create one Contract from stdin Markdown." },
13
+ amend: { positional: "optional", stdin: "optional", flags: { actor: "value", after: "repeat-value", "clear-after": "boolean", gates: "raw-value", json: "boolean" }, usage: "amend [<contract>|@<contract>] [--after <kei/...> ... | --clear-after] [--gates <name,...>] [--actor <actor>] [-]", purpose: "Amend one Contract's document operations or structured terms." },
14
+ deliver: { positional: "optional", stdin: "none", flags: { actor: "value", message: "value", "include-dirty": "boolean", "materialize-conflict": "boolean", json: "boolean" }, usage: "deliver [<contract>|@<contract>] [--message <text>] [--include-dirty] [--materialize-conflict] [--actor <actor>]", purpose: "Deliver one Contract candidate." },
15
+ review: { positional: "optional", stdin: "optional", flags: { actor: "value", satisfied: "boolean", unsatisfied: "boolean", summary: "value", json: "boolean" }, usage: "review [<contract>|@<contract>] (--satisfied | --unsatisfied) (--summary <text> | -) [--actor <actor>]", purpose: "Record one review verdict." },
16
+ arc: { positional: "optional", stdin: "required", flags: { actor: "value", json: "boolean" }, usage: "arc [<contract>|@<contract>] [--actor <actor>] -", purpose: "Record stdin arc Markdown for one Contract." },
17
+ abandon: { positional: "optional", stdin: "none", flags: { actor: "value", note: "value", json: "boolean" }, usage: "abandon [<contract>|@<contract>] [--note <text>] [--actor <actor>]", purpose: "Abandon one Contract with an optional note." },
18
+ status: { positional: "optional", stdin: "none", flags: { json: "boolean" }, usage: "status [<contract>|@name|<aku/...>]", purpose: "Read the world status board or one Contract projection." },
19
+ show: { positional: "optional", stdin: "none", flags: { json: "boolean" }, usage: "show [<contract>|@<contract>]", purpose: "Read one Contract guidance projection." },
20
+ ls: { positional: "optional", stdin: "none", flags: { json: "boolean" }, usage: "ls task[/]\n keiyaku ls kei[/]\n keiyaku ls aku[/]\n keiyaku ls aku/<akuma>[/]\n keiyaku ls \"aku/*/*\"", purpose: "List one identity directory." },
21
+ audit: { positional: "optional", stdin: "none", flags: { "include-dirty": "boolean", diff: "boolean", actor: "value", json: "boolean" }, usage: "audit [<contract>|@<contract>] [--include-dirty] [--diff] [--actor <actor>]", purpose: "Ask what candidate preparation, Verification, and target placement would do." },
22
+ reconcile: { positional: "optional", stdin: "none", flags: { "retry-hooks": "boolean", json: "boolean" }, usage: "reconcile [<contract>|@<contract>] [--retry-hooks]", purpose: "Reconcile one Contract or the invocation world." },
23
+ nuke: { positional: "none", stdin: "none", flags: { confirm: "value", json: "boolean" }, usage: "nuke [--confirm <WorldRoot>]", purpose: "Remove Keiyaku-owned data from one confirmed World." },
24
+ settings: { positional: "none", stdin: "none", flags: { json: "boolean" }, usage: "settings", purpose: "Read user and project Settings resources." },
25
+ region: { positional: "optional", stdin: "none", flags: { overlap: "boolean", path: "value", json: "boolean" }, usage: "region [<contract>] [--overlap]\n region --path <repo-relative-path>", purpose: "Read active declared Contract Regions." },
20
26
  };
@@ -1,4 +1,4 @@
1
- import { type ProcessInput, type ProcessOutcome } from "../../runtime/proc/run.js";
1
+ import type { ProcessInput, ProcessOutcome } from "../../runtime/proc/run.js";
2
2
  export declare const HARNESS_NAMES: readonly ["codex", "claude", "opencode", "pi"];
3
3
  export type HarnessName = typeof HARNESS_NAMES[number];
4
4
  export type ParsedInstallCommand = Readonly<{
@@ -16,7 +16,7 @@ export type InstallInvocationResult = Readonly<{
16
16
  results: readonly HarnessInstallResult[];
17
17
  }>;
18
18
  export type InstallRunner = (input: ProcessInput) => Promise<ProcessOutcome>;
19
- export declare const INSTALL_USAGE = "install <codex|claude|opencode|pi> [--json]\n install --all [--json]";
19
+ export declare const INSTALL_USAGE = "install <codex|claude|opencode|pi>\n install --all";
20
20
  export declare function parseInstallCommand(argv: readonly string[]): ParsedInstallCommand;
21
21
  export declare function renderInstallHelp(): string;
22
22
  export declare function installAssetsRoot(): string;
@@ -1,9 +1,8 @@
1
1
  import { dirname, resolve } from "node:path";
2
2
  import { fileURLToPath } from "node:url";
3
- import { runCrossPlatformProcess } from "../../runtime/proc/run.js";
4
- import { CliUsageError, usageLine, withJsonAutomationHelp } from "../usage.js";
3
+ import { CliUsageError, usageLine } from "../usage.js";
5
4
  export const HARNESS_NAMES = ["codex", "claude", "opencode", "pi"];
6
- export const INSTALL_USAGE = "install <codex|claude|opencode|pi> [--json]\n install --all [--json]";
5
+ export const INSTALL_USAGE = "install <codex|claude|opencode|pi>\n install --all";
7
6
  function isHarness(value) {
8
7
  return value !== undefined && HARNESS_NAMES.includes(value);
9
8
  }
@@ -43,7 +42,7 @@ export function parseInstallCommand(argv) {
43
42
  };
44
43
  }
45
44
  export function renderInstallHelp() {
46
- return withJsonAutomationHelp(`Install the Keiyaku skills into one or more agent harnesses.\n\n${usageLine(INSTALL_USAGE)}`);
45
+ return `Install the Keiyaku skills into one or more agent harnesses.\n\n${usageLine(INSTALL_USAGE)}`;
47
46
  }
48
47
  const INSTALL_TIMEOUT_MS = 5 * 60 * 1000;
49
48
  const ASSET_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../../../integrations/marketplace");
@@ -80,12 +79,13 @@ function diagnostic(argv, outcome) {
80
79
  export function installAssetsRoot() {
81
80
  return ASSET_ROOT;
82
81
  }
83
- export async function installHarnesses(harnesses, environment, runner = runCrossPlatformProcess) {
82
+ export async function installHarnesses(harnesses, environment, runner) {
83
+ const run = runner ?? (await import("../../runtime/proc/run.js")).runCrossPlatformProcess;
84
84
  const results = [];
85
85
  for (const harness of harnesses) {
86
86
  let failure;
87
87
  for (const argv of recipes(harness)) {
88
- const detail = diagnostic(argv, await runner({ argv, env: environment, timeoutMs: INSTALL_TIMEOUT_MS }));
88
+ const detail = diagnostic(argv, await run({ argv, env: environment, timeoutMs: INSTALL_TIMEOUT_MS }));
89
89
  if (detail.length > 0) {
90
90
  failure = detail;
91
91
  break;
@@ -0,0 +1,10 @@
1
+ import { type NukeResult } from "../../index.js";
2
+ import type { WorldRoot } from "../../world.js";
3
+ import { type ParsedCommand } from "../parse.js";
4
+ import type { InvocationResult } from "../result.js";
5
+ export declare function invokeNuke(command: Extract<ParsedCommand, {
6
+ command: "nuke";
7
+ }>, world: WorldRoot | null): Promise<Readonly<{
8
+ kind: "nuke";
9
+ result: NukeResult;
10
+ }> | InvocationResult>;
@@ -0,0 +1,20 @@
1
+ import { Keiyaku, KeiyakuRefused } from "../../index.js";
2
+ import { CliUsageError } from "../parse.js";
3
+ export async function invokeNuke(command, world) {
4
+ if (world === null)
5
+ throw new CliUsageError("no Keiyaku world contains the invocation cwd");
6
+ try {
7
+ return {
8
+ kind: "nuke",
9
+ result: await Keiyaku.nuke({
10
+ world,
11
+ ...(command.confirm === undefined ? {} : { confirm: command.confirm }),
12
+ }),
13
+ };
14
+ }
15
+ catch (error) {
16
+ if (error instanceof KeiyakuRefused)
17
+ return { kind: "refused", verb: "nuke", refusal: error.refusal };
18
+ throw error;
19
+ }
20
+ }
@@ -16,9 +16,24 @@ export type TaskWorldObservation = Readonly<{
16
16
  }>;
17
17
  type TaskInput = Readonly<{
18
18
  world: WorldRoot | null;
19
+ context: Readonly<{
20
+ directory: string;
21
+ boundary: string;
22
+ }>;
19
23
  establish(): Promise<WorldRoot>;
20
24
  readStdin(): Promise<string>;
21
25
  actor?: string;
22
26
  }>;
27
+ export declare function invokeTaskFromEdge(input: Readonly<{
28
+ parsed: ParsedTaskCommand;
29
+ world: WorldRoot | null;
30
+ context: Readonly<{
31
+ directory: string;
32
+ boundary: string;
33
+ }>;
34
+ establish: () => Promise<WorldRoot>;
35
+ readStdin: () => Promise<string>;
36
+ actor: string | undefined;
37
+ }>): Promise<TaskInvocationResult>;
23
38
  export declare function invokeTask(command: ParsedTaskCommand, input: TaskInput): Promise<TaskInvocationResult>;
24
39
  export {};
@@ -1,4 +1,24 @@
1
1
  import { Tasks, } from "../../task/index.js";
2
+ import { injectedBodyRequests, requestBodyTask } from "../../akuma/requests.js";
3
+ import { decodeTaskMutationRequest } from "../../task/mutation.js";
4
+ import { resolveTaskNamespaceContext, writeTaskNamespaceContext } from "../../task/context.js";
5
+ import { CliUsageError } from "../usage.js";
6
+ export async function invokeTaskFromEdge(input) {
7
+ try {
8
+ return await invokeTask(input.parsed, {
9
+ world: input.world,
10
+ context: input.context,
11
+ establish: input.establish,
12
+ readStdin: input.readStdin,
13
+ ...(input.actor === undefined ? {} : { actor: input.actor }),
14
+ });
15
+ }
16
+ catch (error) {
17
+ if (error instanceof TypeError)
18
+ throw new CliUsageError(error.message);
19
+ throw error;
20
+ }
21
+ }
2
22
  function value(command, name) {
3
23
  const item = command.flags[name];
4
24
  return typeof item === "string" ? item : undefined;
@@ -17,8 +37,8 @@ function priority(raw) {
17
37
  function state(raw) { return raw; }
18
38
  function ids(items) { return items; }
19
39
  function limit(command) { const raw = value(command, "limit"); return raw === undefined ? undefined : Number(raw); }
20
- async function invokeAdd(tasks, command, input) {
21
- const selectedNamespace = namespace(value(command, "namespace"));
40
+ async function invokeAdd(tasks, command, input, current) {
41
+ const selectedNamespace = namespace(value(command, "namespace")) ?? current;
22
42
  const actor = input.actor;
23
43
  if (command.stdin === "document") {
24
44
  return tasks.addDocument({
@@ -54,17 +74,96 @@ async function invokeUpdate(tasks, command, readStdin) {
54
74
  ...(addRelates === undefined ? {} : { addRelates }), ...(dropRelates === undefined ? {} : { dropRelates }),
55
75
  });
56
76
  }
57
- async function invokeRead(tasks, command) {
77
+ async function addMutationRequest(command, input, current) {
78
+ const selectedNamespace = namespace(value(command, "namespace")) ?? current;
79
+ if (command.stdin === "document")
80
+ return { action: "task.addDocument", input: {
81
+ markdown: await input.readStdin(),
82
+ namespace: selectedNamespace,
83
+ } };
84
+ const body = value(command, "body"), note = value(command, "note");
85
+ const initialState = state(value(command, "state")), selectedPriority = priority(value(command, "priority"));
86
+ const needs = ids(values(command, "needs")), parent = value(command, "parent");
87
+ const supersedes = ids(values(command, "supersedes")), relates = ids(values(command, "relates"));
88
+ return { action: "task.add", input: {
89
+ title: command.positionals[0], namespace: selectedNamespace,
90
+ ...(body === undefined ? {} : { body }), ...(note === undefined ? {} : { note }),
91
+ ...(initialState === undefined ? {} : { state: initialState }),
92
+ ...(selectedPriority === undefined ? {} : { priority: selectedPriority }),
93
+ ...(needs === undefined ? {} : { needs }), ...(parent === undefined ? {} : { parent: parent }),
94
+ ...(supersedes === undefined ? {} : { supersedes }), ...(relates === undefined ? {} : { relates }),
95
+ } };
96
+ }
97
+ async function updateMutationRequest(command, input) {
98
+ const body = command.stdin === "body" ? await input.readStdin() : value(command, "body");
99
+ const appendBody = command.stdin === "append" ? await input.readStdin() : value(command, "append");
100
+ const note = command.stdin === "note" ? await input.readStdin() : value(command, "note");
101
+ const title = value(command, "title"), selectedPriority = priority(value(command, "priority"));
102
+ const addNeeds = ids(values(command, "needs")), dropNeeds = ids(values(command, "drop-needs"));
103
+ const parent = value(command, "parent"), addSupersedes = ids(values(command, "supersedes"));
104
+ const dropSupersedes = ids(values(command, "drop-supersedes")), addRelates = ids(values(command, "relates"));
105
+ const dropRelates = ids(values(command, "drop-relates"));
106
+ return { action: "task.update", id: command.positionals[0], input: {
107
+ ...(title === undefined ? {} : { title }), ...(body === undefined ? {} : { body }),
108
+ ...(appendBody === undefined ? {} : { appendBody }), ...(note === undefined ? {} : { note }),
109
+ ...(selectedPriority === undefined ? {} : { priority: selectedPriority }),
110
+ ...(addNeeds === undefined ? {} : { addNeeds }), ...(dropNeeds === undefined ? {} : { dropNeeds }),
111
+ ...(command.flags["no-parent"] === true ? { parent: null }
112
+ : parent === undefined ? {} : { parent: parent }),
113
+ ...(addSupersedes === undefined ? {} : { addSupersedes }),
114
+ ...(dropSupersedes === undefined ? {} : { dropSupersedes }),
115
+ ...(addRelates === undefined ? {} : { addRelates }), ...(dropRelates === undefined ? {} : { dropRelates }),
116
+ } };
117
+ }
118
+ function lifecycleMutationRequest(command) {
119
+ const id = command.positionals[0];
120
+ switch (command.action) {
121
+ case "start": return { action: "task.start", id };
122
+ case "stop": return { action: "task.stop", id };
123
+ case "resume": return { action: "task.resume", id };
124
+ case "hold": return { action: "task.hold", ids: command.positionals };
125
+ case "done": return { action: "task.done", ids: command.positionals, ...(value(command, "note") === undefined ? {} : { note: value(command, "note") }) };
126
+ case "drop": return { action: "task.drop", ids: command.positionals, ...(value(command, "note") === undefined ? {} : { note: value(command, "note") }) };
127
+ default: throw new Error(`task action cannot forward: ${command.action}`);
128
+ }
129
+ }
130
+ async function mutationRequest(command, input, current) {
131
+ if (command.action === "add")
132
+ return await addMutationRequest(command, input, current);
133
+ if (command.action === "compose")
134
+ return { action: "task.compose", markdown: await input.readStdin(), namespace: current };
135
+ if (command.action === "update")
136
+ return await updateMutationRequest(command, input);
137
+ return lifecycleMutationRequest(command);
138
+ }
139
+ function validatedMutationRequest(request) {
140
+ switch (request.action) {
141
+ case "task.add":
142
+ case "task.addDocument": return decodeTaskMutationRequest(request.action, { input: request.input });
143
+ case "task.compose": return decodeTaskMutationRequest(request.action, { markdown: request.markdown, namespace: request.namespace });
144
+ case "task.update": return decodeTaskMutationRequest(request.action, { id: request.id, input: request.input });
145
+ case "task.start":
146
+ case "task.stop":
147
+ case "task.resume": return decodeTaskMutationRequest(request.action, { id: request.id });
148
+ case "task.hold": return decodeTaskMutationRequest(request.action, { ids: request.ids });
149
+ case "task.done":
150
+ case "task.drop": return decodeTaskMutationRequest(request.action, { ids: request.ids, ...(request.note === undefined ? {} : { note: request.note }) });
151
+ }
152
+ }
153
+ function readScope(command, current) {
154
+ return command.flags.world === true ? { scope: "world" } : { namespace: current ?? [] };
155
+ }
156
+ async function invokeRead(tasks, command, current) {
58
157
  const id = command.positionals[0];
59
158
  switch (command.action) {
60
159
  case "show": {
61
160
  const detail = await tasks.task({ id }).read();
62
161
  return detail ?? { kind: "refused", refusal: { kind: "task-missing", taskId: id } };
63
162
  }
64
- case "ls": return tasks.list({ selection: command.flags.all === true ? "all" : command.flags.closed === true ? "closed" : "active", ...(command.flags.world === true ? { scope: "world" } : {}), ...(limit(command) === undefined ? {} : { limit: limit(command) }) });
65
- case "ready": return tasks.ready({ ...(command.flags.world === true ? { scope: "world" } : {}), ...(value(command, "parent") === undefined ? {} : { parent: value(command, "parent") }), ...(limit(command) === undefined ? {} : { limit: limit(command) }) });
66
- case "blocked": return tasks.blocked({ ...(command.flags.world === true ? { scope: "world" } : {}), ...(value(command, "parent") === undefined ? {} : { parent: value(command, "parent") }), ...(limit(command) === undefined ? {} : { limit: limit(command) }) });
67
- case "query": return tasks.query({ ...(command.where === undefined ? {} : { where: command.where }), ...(command.flags.world === true ? { scope: "world" } : {}), ...(value(command, "sort") === undefined ? {} : { sort: value(command, "sort") }), ...(limit(command) === undefined ? {} : { limit: limit(command) }) });
163
+ case "ls": return tasks.list({ selection: command.flags.all === true ? "all" : command.flags.closed === true ? "closed" : "active", ...readScope(command, current), ...(limit(command) === undefined ? {} : { limit: limit(command) }) });
164
+ case "ready": return tasks.ready({ ...readScope(command, current), ...(value(command, "parent") === undefined ? {} : { parent: value(command, "parent") }), ...(limit(command) === undefined ? {} : { limit: limit(command) }) });
165
+ case "blocked": return tasks.blocked({ ...readScope(command, current), ...(value(command, "parent") === undefined ? {} : { parent: value(command, "parent") }), ...(limit(command) === undefined ? {} : { limit: limit(command) }) });
166
+ case "query": return tasks.query({ ...(command.where === undefined ? {} : { where: command.where }), ...readScope(command, current), ...(value(command, "sort") === undefined ? {} : { sort: value(command, "sort") }), ...(limit(command) === undefined ? {} : { limit: limit(command) }) });
68
167
  case "tree": return tasks.task({ id }).tree();
69
168
  case "doctor": return tasks.doctor();
70
169
  default: throw new Error(`task action is not a read: ${command.action}`);
@@ -75,9 +174,9 @@ function isWorldObservation(command) {
75
174
  || command.action === "query" || command.action === "doctor";
76
175
  }
77
176
  function diagnostic(error) { return error instanceof Error ? error.message : String(error); }
78
- async function observeWorldRead(tasks, command) {
177
+ async function observeWorldRead(tasks, command, current) {
79
178
  try {
80
- return { kind: "present", value: await invokeRead(tasks, command) };
179
+ return { kind: "present", value: await invokeRead(tasks, command, current) };
81
180
  }
82
181
  catch (error) {
83
182
  return { kind: "failed", failure: { message: diagnostic(error) } };
@@ -97,21 +196,13 @@ function missingWorld(command) {
97
196
  }
98
197
  return missing(command.positionals[0]);
99
198
  }
100
- export async function invokeTask(command, input) {
101
- let world = input.world;
102
- if (world === null && (command.action === "add" || command.action === "compose"
103
- || (command.action === "namespace" && command.positionals.length > 0))) {
104
- world = await input.establish();
105
- }
106
- if (world === null)
107
- return missingWorld(command);
108
- const tasks = Tasks.of(world);
199
+ async function invokeLocalMutation(tasks, command, input, current) {
109
200
  if (isWorldObservation(command))
110
- return observeWorldRead(tasks, command);
201
+ return observeWorldRead(tasks, command, current);
111
202
  if (command.action === "show" || command.action === "tree")
112
- return invokeRead(tasks, command);
203
+ return invokeRead(tasks, command, current);
113
204
  if (command.action === "add")
114
- return await invokeAdd(tasks, command, input);
205
+ return await invokeAdd(tasks, command, input, current ?? []);
115
206
  if (command.action === "update")
116
207
  return await invokeUpdate(tasks, command, input.readStdin);
117
208
  const id = command.positionals[0];
@@ -131,10 +222,39 @@ export async function invokeTask(command, input) {
131
222
  case "namespace": {
132
223
  const selected = namespace(command.positionals[0]);
133
224
  if (selected !== undefined)
134
- await tasks.setNamespace({ namespace: selected });
135
- return tasks.namespace();
225
+ await writeTaskNamespaceContext(input.context.directory, selected);
226
+ return { kind: "accepted", value: selected ?? current ?? [] };
136
227
  }
137
- case "compose": return tasks.compose({ markdown: await input.readStdin(), ...(input.actor === undefined ? {} : { actor: input.actor }) });
228
+ case "compose": return tasks.compose({ markdown: await input.readStdin(), namespace: current ?? [], ...(input.actor === undefined ? {} : { actor: input.actor }) });
138
229
  default: throw new Error(`task action has no invocation: ${command.action}`);
139
230
  }
140
231
  }
232
+ function establishesWorld(command) {
233
+ return command.action === "add" || command.action === "compose"
234
+ || (command.action === "namespace" && command.positionals.length > 0);
235
+ }
236
+ function forwardsMutation(command) {
237
+ return command.action !== "show" && command.action !== "tree"
238
+ && command.action !== "namespace" && !isWorldObservation(command);
239
+ }
240
+ export async function invokeTask(command, input) {
241
+ const world = input.world ?? (establishesWorld(command) ? await input.establish() : null);
242
+ if (world === null)
243
+ return missingWorld(command);
244
+ const tasks = Tasks.of(world);
245
+ const contextSensitive = command.action === "namespace" || command.action === "add" || command.action === "compose"
246
+ || ((command.action === "ls" || command.action === "ready" || command.action === "blocked" || command.action === "query") && command.flags.world !== true);
247
+ let current;
248
+ if (contextSensitive) {
249
+ const resolved = await resolveTaskNamespaceContext(input.context);
250
+ if (typeof resolved === "object" && "kind" in resolved)
251
+ return { kind: "refused", refusal: resolved };
252
+ current = resolved;
253
+ }
254
+ const requests = injectedBodyRequests();
255
+ if (requests !== null && forwardsMutation(command)) {
256
+ const request = validatedMutationRequest(await mutationRequest(command, input, current ?? []));
257
+ return await requestBodyTask({ directory: requests, world, request });
258
+ }
259
+ return await invokeLocalMutation(tasks, command, input, current);
260
+ }
@@ -1,5 +1,5 @@
1
- import { type TaskQueryExpression } from "../../task/index.js";
2
- export type { TaskQueryExpression } from "../../task/index.js";
1
+ import { type TaskQueryExpression } from "../../task/query.js";
2
+ export type { TaskQueryExpression } from "../../task/query.js";
3
3
  export declare function parseTaskQueryExpression(source: string): TaskQueryExpression;
4
4
  export declare function validateTaskLimit(source: string): void;
5
5
  export declare function validateTaskParent(source: string): void;
@@ -1,5 +1,4 @@
1
- import { TASK_RELATION_PREDICATE_FIELDS, } from "../../task/index.js";
2
- import { MAX_TASK_LIMIT, normalizeTaskQuery } from "../../task/query.js";
1
+ import { MAX_TASK_LIMIT, TASK_RELATION_PREDICATE_FIELDS, normalizeTaskQuery, } from "../../task/query.js";
3
2
  function syntax(message, offset) { throw new Error(`${message} at column ${offset + 1}`); }
4
3
  function scanString(source, offset) {
5
4
  let index = offset + 1;
@@ -1,4 +1,4 @@
1
- import { CliUsageError, isBlankInput, usageLine, withJsonAutomationHelp } from "../usage.js";
1
+ import { CliUsageError, isBlankInput, usageLine } from "../usage.js";
2
2
  import { parseTaskQueryExpression, validateTaskLimit, validateTaskParent, } from "./task-query.js";
3
3
  const COMMON = { json: "boolean" };
4
4
  const TASK_COMMAND_SPECS = {
@@ -9,18 +9,18 @@ const TASK_COMMAND_SPECS = {
9
9
  [--note <text>] [--actor <actor>]
10
10
  [--needs <TaskId>]... [--parent <TaskId>]
11
11
  [--supersedes <TaskId>]... [--relates <TaskId>]...
12
- [--body <text>] [--json]
13
- task add [--namespace <ns>] [--actor <actor>] [--json] -`,
12
+ [--body <text>]
13
+ task add [--namespace <ns>] [--actor <actor>] -`,
14
14
  purpose: "Create one Task from flags or a canonical stdin document.",
15
15
  },
16
- show: { arity: [1, 1], flags: COMMON, usage: "task show <TaskId> [--json]", purpose: "Read one Task and its relationships." },
17
- ls: { arity: [0, 0], flags: { ...COMMON, closed: "boolean", all: "boolean", world: "boolean", limit: "value" }, usage: "task ls [--closed | --all] [--world] [--limit <n>] [--json]", purpose: "List Tasks in the selected scope." },
18
- ready: { arity: [0, 0], flags: { ...COMMON, world: "boolean", parent: "value", limit: "value" }, usage: "task ready [--world] [--parent <TaskId>] [--limit <n>] [--json]", purpose: "List open Tasks whose every need is terminal." },
19
- blocked: { arity: [0, 0], flags: { ...COMMON, world: "boolean", parent: "value", limit: "value" }, usage: "task blocked [--world] [--parent <TaskId>] [--limit <n>] [--json]", purpose: "List Tasks blocked by dependencies." },
16
+ show: { arity: [1, 1], flags: COMMON, usage: "task show <TaskId>", purpose: "Read one Task and its relationships." },
17
+ ls: { arity: [0, 0], flags: { ...COMMON, closed: "boolean", all: "boolean", world: "boolean", limit: "value" }, usage: "task ls [--closed | --all] [--world] [--limit <n>]", purpose: "List Tasks in the selected scope." },
18
+ ready: { arity: [0, 0], flags: { ...COMMON, world: "boolean", parent: "value", limit: "value" }, usage: "task ready [--world] [--parent <TaskId>] [--limit <n>]", purpose: "List open Tasks whose every need is terminal." },
19
+ blocked: { arity: [0, 0], flags: { ...COMMON, world: "boolean", parent: "value", limit: "value" }, usage: "task blocked [--world] [--parent <TaskId>] [--limit <n>]", purpose: "List Tasks blocked by dependencies." },
20
20
  query: { arity: [0, 0], flags: { ...COMMON, where: "value", world: "boolean", sort: "value", limit: "value" }, usage: `task query [--where <expression>] [--world]
21
- [--sort priority|created|updated|id] [--limit <n>] [--json]`, purpose: "Query Task facts with a typed boolean expression." },
22
- tree: { arity: [1, 1], flags: COMMON, usage: "task tree <TaskId> [--json]", purpose: "Read one Task parent decomposition tree." },
23
- doctor: { arity: [0, 0], flags: COMMON, usage: "task doctor [--json]", purpose: "Inspect Task authority without repairing it." },
21
+ [--sort priority|created|updated|id] [--limit <n>]`, purpose: "Query Task facts with a typed boolean expression." },
22
+ tree: { arity: [1, 1], flags: COMMON, usage: "task tree <TaskId>", purpose: "Read one Task parent decomposition tree." },
23
+ doctor: { arity: [0, 0], flags: COMMON, usage: "task doctor", purpose: "Inspect Task authority without repairing it." },
24
24
  update: {
25
25
  arity: [1, 1], flags: { ...COMMON, title: "value", body: "value", append: "value", note: "value", priority: "value", needs: "repeat", "drop-needs": "repeat", parent: "value", "no-parent": "boolean", supersedes: "repeat", "drop-supersedes": "repeat", relates: "repeat", "drop-relates": "repeat" },
26
26
  usage: `task update <TaskId> [--title <text>] [--body <text>|- | --append <text>|-]
@@ -28,17 +28,17 @@ task add [--namespace <ns>] [--actor <actor>] [--json] -`,
28
28
  [--priority 0..3] [--needs <TaskId>]... [--drop-needs <TaskId>]...
29
29
  [--parent <TaskId> | --no-parent]
30
30
  [--supersedes <TaskId>]... [--drop-supersedes <TaskId>]...
31
- [--relates <TaskId>]... [--drop-relates <TaskId>]... [--json]`,
31
+ [--relates <TaskId>]... [--drop-relates <TaskId>]...`,
32
32
  purpose: "Apply one or more patches to a Task.",
33
33
  },
34
- start: { arity: [1, 1], flags: COMMON, usage: "task start <TaskId> [--json]", purpose: "Move one open Task into progress." },
35
- stop: { arity: [1, 1], flags: COMMON, usage: "task stop <TaskId> [--json]", purpose: "Return one in-progress Task to open." },
36
- hold: { arity: [1, Number.POSITIVE_INFINITY], flags: COMMON, usage: "task hold <TaskId>... [--json]", purpose: "Put one or more Tasks on hold." },
37
- resume: { arity: [1, 1], flags: COMMON, usage: "task resume <TaskId> [--json]", purpose: "Return one held Task to open." },
38
- done: { arity: [1, Number.POSITIVE_INFINITY], flags: { ...COMMON, note: "value" }, usage: "task done <TaskId>... [--note <text>] [--json]", purpose: "Mark one or more Tasks done." },
39
- drop: { arity: [1, Number.POSITIVE_INFINITY], flags: { ...COMMON, note: "value" }, usage: "task drop <TaskId>... [--note <text>] [--json]", purpose: "Drop one or more Tasks." },
40
- namespace: { arity: [0, 1], flags: COMMON, usage: "task namespace [<namespace>] [--json]", purpose: "Read or replace the current Task namespace." },
41
- compose: { arity: [0, 0], stdin: "compose", flags: { ...COMMON, actor: "value" }, usage: "task compose [--actor <actor>] [--json] -", purpose: "Admit Task documents independently; partial admission has no cross-file atomicity or rollback." },
34
+ start: { arity: [1, 1], flags: COMMON, usage: "task start <TaskId>", purpose: "Move one open Task into progress." },
35
+ stop: { arity: [1, 1], flags: COMMON, usage: "task stop <TaskId>", purpose: "Return one in-progress Task to open." },
36
+ hold: { arity: [1, Number.POSITIVE_INFINITY], flags: COMMON, usage: "task hold <TaskId>...", purpose: "Put one or more Tasks on hold." },
37
+ resume: { arity: [1, 1], flags: COMMON, usage: "task resume <TaskId>", purpose: "Return one held Task to open." },
38
+ done: { arity: [1, Number.POSITIVE_INFINITY], flags: { ...COMMON, note: "value" }, usage: "task done <TaskId>... [--note <text>]", purpose: "Mark one or more Tasks done." },
39
+ drop: { arity: [1, Number.POSITIVE_INFINITY], flags: { ...COMMON, note: "value" }, usage: "task drop <TaskId>... [--note <text>]", purpose: "Drop one or more Tasks." },
40
+ namespace: { arity: [0, 1], flags: COMMON, usage: "task namespace [<namespace>]", purpose: "Read or replace the current Task namespace." },
41
+ compose: { arity: [0, 0], stdin: "compose", flags: { ...COMMON, actor: "value" }, usage: "task compose [--actor <actor>] -", purpose: "Admit Task documents independently; partial admission has no cross-file atomicity or rollback." },
42
42
  };
43
43
  export function isTaskAction(value) {
44
44
  return value !== undefined && Object.hasOwn(TASK_COMMAND_SPECS, value);
@@ -46,14 +46,14 @@ export function isTaskAction(value) {
46
46
  export function renderTaskHelp(action) {
47
47
  if (action !== undefined) {
48
48
  const spec = TASK_COMMAND_SPECS[action];
49
- return withJsonAutomationHelp(`${spec.purpose}\n\n${usageLine(spec.usage)}`);
49
+ return `${spec.purpose}\n\n${usageLine(spec.usage)}`;
50
50
  }
51
- return withJsonAutomationHelp([
51
+ return [
52
52
  "usage: keiyaku task <command> ...",
53
53
  "",
54
54
  "commands:",
55
55
  ...Object.values(TASK_COMMAND_SPECS).flatMap((spec) => spec.usage.split("\n").map((line) => ` ${line}`).concat(` ${spec.purpose}`)),
56
- ].join("\n"));
56
+ ].join("\n");
57
57
  }
58
58
  export function renderTaskUsage(action) {
59
59
  return usageLine(TASK_COMMAND_SPECS[action].usage);
@@ -1,4 +1,4 @@
1
- import { Repo } from "../index.js";
1
+ import { Repo } from "../library/repo.js";
2
2
  import { type WorldRoot } from "../world.js";
3
3
  import { type ParsedCommand } from "./parse.js";
4
4
  export type CliCoordinates = Readonly<{
@@ -7,13 +7,17 @@ export type CliCoordinates = Readonly<{
7
7
  repo?: Repo;
8
8
  world: WorldRoot | null;
9
9
  candidateWorld: WorldRoot | null;
10
+ taskContext: Readonly<{
11
+ directory: string;
12
+ boundary: string;
13
+ }>;
10
14
  establishWorld: () => Promise<WorldRoot>;
11
15
  }>;
12
16
  export type CliCoordinateInput = Readonly<{
13
17
  processCwd?: string;
14
18
  cwd?: string;
15
19
  repo?: string;
20
+ gitPath?: string;
16
21
  command: ParsedCommand;
17
22
  }>;
18
- export declare function assertExplicitRepoUse(command: ParsedCommand, repo: string | undefined): void;
19
23
  export declare function resolveCliCoordinates(input: CliCoordinateInput): Promise<CliCoordinates>;
@@ -1,8 +1,8 @@
1
1
  import { realpath } from "node:fs/promises";
2
2
  import { resolve } from "node:path";
3
- import { NoGitWorldError, Repo } from "../index.js";
3
+ import { NoGitWorldError, Repo } from "../library/repo.js";
4
4
  import { World, WorldError } from "../world.js";
5
- import { CliUsageError } from "./parse.js";
5
+ import { CliUsageError, commandRepoPolicy } from "./parse.js";
6
6
  async function canonicalInvocationCwd(input) {
7
7
  try {
8
8
  return await realpath(input);
@@ -11,9 +11,12 @@ async function canonicalInvocationCwd(input) {
11
11
  throw new CliUsageError(`invocation cwd is not an existing directory: ${input}`);
12
12
  }
13
13
  }
14
- async function discoverRepoAt(coordinate) {
14
+ async function discoverRepoAt(coordinate, gitPath) {
15
15
  try {
16
- return { kind: "present", repo: await Repo.at({ path: coordinate }) };
16
+ return {
17
+ kind: "present",
18
+ repo: await Repo.at({ path: coordinate, ...(gitPath === undefined ? {} : { gitPath }) }),
19
+ };
17
20
  }
18
21
  catch (error) {
19
22
  if (error instanceof NoGitWorldError)
@@ -21,55 +24,6 @@ async function discoverRepoAt(coordinate) {
21
24
  throw error;
22
25
  }
23
26
  }
24
- function repoPolicy(command) {
25
- switch (command.command) {
26
- case "bind":
27
- case "amend":
28
- case "deliver":
29
- case "review":
30
- case "arc":
31
- case "abandon":
32
- case "audit":
33
- case "reconcile":
34
- case "show":
35
- case "region":
36
- return { use: "required", acceptsExplicit: true };
37
- case "ls":
38
- return { use: command.query.kind === "contracts" ? "required" : "none", acceptsExplicit: false };
39
- case "status":
40
- case "tell":
41
- return { use: "optional", acceptsExplicit: false };
42
- case "history":
43
- return "contract" in command
44
- ? { use: "required", acceptsExplicit: true }
45
- : { use: "optional", acceptsExplicit: false };
46
- case "fork":
47
- return { use: "optional", acceptsExplicit: true };
48
- case "wait":
49
- case "kill": {
50
- const contractSelector = command.akuma.some((selector) => selector.startsWith("kei/"));
51
- return { use: contractSelector ? "required" : "optional", acceptsExplicit: contractSelector };
52
- }
53
- case "call":
54
- return {
55
- use: command.contract === undefined ? "none" : "required",
56
- acceptsExplicit: command.contract !== undefined,
57
- };
58
- case "settings":
59
- case "task":
60
- case "install":
61
- return { use: "none", acceptsExplicit: false };
62
- }
63
- }
64
- function refuseUnusedRepo(command) {
65
- if (command.command === "call")
66
- throw new CliUsageError("--repo has no consumer without --contract");
67
- throw new CliUsageError(`--repo has no consumer for ${command.command}`);
68
- }
69
- export function assertExplicitRepoUse(command, repo) {
70
- if (repo !== undefined && !repoPolicy(command).acceptsExplicit)
71
- refuseUnusedRepo(command);
72
- }
73
27
  function repoFor(use, discovery) {
74
28
  if (use === "none")
75
29
  return undefined;
@@ -106,19 +60,21 @@ async function resolveWorld(cwd, repo) {
106
60
  export async function resolveCliCoordinates(input) {
107
61
  const processCwd = resolve(input.processCwd ?? ".");
108
62
  const cwd = await canonicalInvocationCwd(resolve(processCwd, input.cwd ?? "."));
109
- const invocationRepo = await discoverRepoAt(cwd);
63
+ const invocationRepo = await discoverRepoAt(cwd, input.gitPath);
110
64
  const selectedRepo = input.repo === undefined
111
65
  ? invocationRepo
112
- : await discoverRepoAt(resolve(cwd, input.repo));
66
+ : await discoverRepoAt(resolve(cwd, input.repo), input.gitPath);
113
67
  const worldRepo = invocationRepo.kind === "present" ? invocationRepo.repo : undefined;
114
- const repo = repoFor(repoPolicy(input.command).use, selectedRepo);
68
+ const repo = repoFor(commandRepoPolicy(input.command).use, selectedRepo);
115
69
  const world = await resolveWorld(cwd, worldRepo);
70
+ const boundary = worldRepo === undefined ? world.root ?? world.candidate ?? cwd : worldRepo.cwd;
116
71
  return {
117
72
  cwd,
118
73
  cwdSource: input.cwd === undefined ? "process" : "input",
119
74
  ...(repo === undefined ? {} : { repo }),
120
75
  world: world.root,
121
76
  candidateWorld: world.candidate,
77
+ taskContext: { directory: cwd, boundary },
122
78
  establishWorld: world.establish,
123
79
  };
124
80
  }