@astrosheep/keiyaku 2.9.12 → 2.9.13

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 (212) hide show
  1. package/README.md +22 -18
  2. package/build/.tsbuildinfo +1 -1
  3. package/build/agents/call-terms.js +1 -0
  4. package/build/agents/providers/claude-agent-sdk/adapter.js +2 -2
  5. package/build/cli/commands/akuma/akuma/handler.js +2 -1
  6. package/build/cli/commands/akuma/akuma/meta.js +4 -3
  7. package/build/cli/commands/akuma/catalog.js +2 -0
  8. package/build/cli/commands/akuma/list/handler.js +1 -1
  9. package/build/cli/commands/akuma/list/meta-list.js +12 -0
  10. package/build/cli/commands/akuma/list/meta-ls.js +2 -2
  11. package/build/cli/commands/akuma.js +5 -0
  12. package/build/cli/commands/contract/amend/meta.js +4 -3
  13. package/build/cli/commands/contract/arc/meta.js +2 -0
  14. package/build/cli/commands/contract/audit/handler.js +28 -2
  15. package/build/cli/commands/contract/audit/meta.js +4 -3
  16. package/build/cli/commands/contract/petition/handler.js +2 -1
  17. package/build/cli/commands/contract/petition/meta.js +2 -2
  18. package/build/cli/commands/contract/renew/handler.js +44 -3
  19. package/build/cli/commands/contract/renew/meta.js +5 -4
  20. package/build/cli/commands/metadata.js +12 -9
  21. package/build/cli/commands/projection/call/handler.js +1 -1
  22. package/build/cli/commands/projection/call/meta.js +1 -1
  23. package/build/cli/commands/projection/catalog.js +2 -2
  24. package/build/cli/commands/projection/{revive → fork}/handler.js +10 -5
  25. package/build/cli/commands/projection/fork/meta.js +12 -0
  26. package/build/cli/commands/projection/history/handler.js +46 -2
  27. package/build/cli/commands/projection/history/meta.js +3 -3
  28. package/build/cli/commands/projection/kill/meta.js +2 -2
  29. package/build/cli/commands/projection/status/handler.js +29 -13
  30. package/build/cli/commands/projection/status/meta.js +14 -3
  31. package/build/cli/commands/projection/tell/handler.js +8 -4
  32. package/build/cli/commands/projection/tell/meta.js +1 -1
  33. package/build/cli/commands/projection/wait/handler.js +45 -20
  34. package/build/cli/commands/projection/wait/meta.js +1 -1
  35. package/build/cli/commands/shared.js +1 -1
  36. package/build/cli/commands/system/catalog.js +2 -0
  37. package/build/cli/commands/task/add/handler.js +28 -12
  38. package/build/cli/commands/task/add/meta.js +18 -6
  39. package/build/cli/commands/task/catalog.js +2 -0
  40. package/build/cli/commands/task/compose/handler.js +2 -2
  41. package/build/cli/commands/task/compose/meta.js +2 -2
  42. package/build/cli/commands/task/doctor/handler.js +2 -3
  43. package/build/cli/commands/task/doctor/meta.js +2 -2
  44. package/build/cli/commands/task/done/meta.js +2 -2
  45. package/build/cli/commands/task/drop/handler.js +7 -2
  46. package/build/cli/commands/task/drop/meta.js +6 -3
  47. package/build/cli/commands/task/hold/meta.js +2 -2
  48. package/build/cli/commands/task/log/meta.js +2 -2
  49. package/build/cli/commands/task/ls/meta.js +2 -2
  50. package/build/cli/commands/task/note/handler.js +6 -0
  51. package/build/cli/commands/task/note/meta.js +11 -0
  52. package/build/cli/commands/task/resume/meta.js +2 -2
  53. package/build/cli/commands/task/shared.js +29 -15
  54. package/build/cli/commands/task/show/meta.js +2 -2
  55. package/build/cli/commands/task/start/meta.js +2 -2
  56. package/build/cli/commands/task/stop/meta.js +2 -2
  57. package/build/cli/commands/task/update/meta.js +3 -2
  58. package/build/cli/commands/verification/handler.js +43 -0
  59. package/build/cli/commands/verification/meta.js +13 -0
  60. package/build/cli/completion.js +16 -13
  61. package/build/cli/flags.js +43 -11
  62. package/build/cli/help.js +29 -30
  63. package/build/cli/index.js +6 -5
  64. package/build/cli/parse-flags.js +39 -0
  65. package/build/cli/parse-metadata.js +5 -2
  66. package/build/cli/parse-selectors.js +18 -0
  67. package/build/cli/parse.js +21 -8
  68. package/build/cli/render/arc.js +12 -3
  69. package/build/cli/render/audit.js +2 -2
  70. package/build/cli/render/call.js +4 -4
  71. package/build/cli/render/kanshi.js +122 -85
  72. package/build/cli/render/misc.js +2 -2
  73. package/build/cli/render/petition.js +16 -1
  74. package/build/cli/render/projection-history.js +17 -4
  75. package/build/cli/render/shared.js +5 -5
  76. package/build/cli/render/status-indicator.js +47 -0
  77. package/build/cli/render/status.js +106 -76
  78. package/build/cli/render/success-response.js +20 -5
  79. package/build/cli/render/task.js +6 -5
  80. package/build/cli/render/tell.js +10 -4
  81. package/build/cli/render/tool-command-normalization.js +137 -0
  82. package/build/cli/render/tool-presentation.js +2 -1
  83. package/build/cli/render/verification.js +23 -0
  84. package/build/cli/render/wait.js +101 -33
  85. package/build/cli/types.js +2 -1
  86. package/build/config/akuma-loader.js +21 -1
  87. package/build/config/settings/knobs.js +7 -1
  88. package/build/config/settings/schema.js +10 -5
  89. package/build/core/amend.js +102 -17
  90. package/build/core/arc.js +4 -4
  91. package/build/core/audit/candidate.js +10 -18
  92. package/build/core/audit/coordinates.js +12 -17
  93. package/build/core/audit/evidence.js +6 -4
  94. package/build/core/audit/facade.js +3 -3
  95. package/build/core/audit/report.js +1 -1
  96. package/build/core/bind-reconciliation.js +42 -23
  97. package/build/core/bind.js +182 -81
  98. package/build/core/call/call.js +6 -7
  99. package/build/core/call/context.js +43 -30
  100. package/build/core/call/execution.js +21 -6
  101. package/build/core/call/prompt.js +11 -42
  102. package/build/core/contract-carrier-runtime.js +209 -105
  103. package/build/core/contract-carrier.js +156 -73
  104. package/build/core/contract-view.js +42 -5
  105. package/build/core/contract.js +2 -1
  106. package/build/core/derived-replay.js +168 -35
  107. package/build/core/draft.js +9 -5
  108. package/build/core/forfeit.js +1 -1
  109. package/build/core/lifecycle-history.js +13 -0
  110. package/build/core/lifecycle-recovery.js +32 -27
  111. package/build/core/lifecycle-runner.js +14 -14
  112. package/build/core/log.js +1 -1
  113. package/build/core/outcome-base.js +2 -2
  114. package/build/core/projection/akuma-name.js +43 -0
  115. package/build/core/projection/generation/database.js +141 -79
  116. package/build/core/projection/generation/ledger.js +91 -0
  117. package/build/core/projection/generation/model.js +18 -13
  118. package/build/core/projection/generation/projection-generation-continuation.js +1 -1
  119. package/build/core/projection/generation/projection-generation-doorbell.js +88 -0
  120. package/build/core/projection/generation/projection-generation-execution.js +24 -0
  121. package/build/core/projection/generation/projection-generation-identity.js +4 -0
  122. package/build/core/projection/generation/projection-generation-launcher.js +72 -138
  123. package/build/core/projection/generation/projection-generation-process.js +16 -15
  124. package/build/core/projection/generation/projection-generation-runner.js +125 -79
  125. package/build/core/projection/generation/projection-generation-runtime.js +10 -61
  126. package/build/core/projection/generation/protocol.js +68 -0
  127. package/build/core/projection/generation/store.js +17 -7
  128. package/build/core/projection/generation/transitions.js +14 -14
  129. package/build/core/projection/index.js +5 -5
  130. package/build/core/projection/projection-core.js +6 -2
  131. package/build/core/projection/projection-execution-observer.js +1 -1
  132. package/build/core/projection/projection-history.js +7 -7
  133. package/build/core/projection/projection-kill.js +15 -6
  134. package/build/core/projection/projection-life-observer.js +8 -8
  135. package/build/core/projection/projection-mint.js +6 -8
  136. package/build/core/projection/projection-status-observation.js +77 -8
  137. package/build/core/projection/projection-status.js +151 -4
  138. package/build/core/projection/projection-wait.js +46 -27
  139. package/build/core/projection/projection-wake.js +27 -89
  140. package/build/core/projection/tell/launch-store.js +1 -1
  141. package/build/core/projection/tell/store.js +1 -1
  142. package/build/core/renew-build.js +204 -74
  143. package/build/core/renew-plan.js +34 -9
  144. package/build/core/renew-rewrite.js +56 -15
  145. package/build/core/renew.js +39 -35
  146. package/build/core/repository-ledger/accepted-fold-read.js +6 -3
  147. package/build/core/repository-ledger/codec.js +11 -5
  148. package/build/core/repository-ledger/current-state-store.js +13 -16
  149. package/build/core/repository-ledger/fold-repository.js +5 -6
  150. package/build/core/repository-ledger/identity.js +60 -0
  151. package/build/core/repository-ledger/inventory.js +3 -3
  152. package/build/core/repository-ledger/read-model.js +54 -6
  153. package/build/core/repository-ledger/write-transaction.js +9 -4
  154. package/build/core/run-control/connection-bound-close.js +41 -0
  155. package/build/core/run-control/detached-lease-bootstrap.js +208 -0
  156. package/build/core/run-control/detached-process.js +14 -0
  157. package/build/core/run-control/index.js +6 -0
  158. package/build/core/{process-group.js → run-control/process-tree.js} +1 -1
  159. package/build/core/run-control/runner-lease.js +172 -0
  160. package/build/core/{sqlite-process-lifetime-lock.js → run-control/sqlite-process-lifetime-lock.js} +4 -24
  161. package/build/core/seal.js +44 -32
  162. package/build/core/settlement/claim-delivery.js +22 -9
  163. package/build/core/settlement/claim.js +8 -6
  164. package/build/core/settlement/petition-claim-gates.js +9 -8
  165. package/build/core/settlement/petition-head-guard.js +5 -6
  166. package/build/core/settlement/petition-preview.js +21 -5
  167. package/build/core/settlement/petition.js +51 -17
  168. package/build/core/settlement/settlement.js +20 -15
  169. package/build/core/settlement/verdict.js +2 -2
  170. package/build/core/settlement/verification.js +492 -364
  171. package/build/core/status/board.js +184 -75
  172. package/build/core/status/drift.js +8 -10
  173. package/build/core/task/board.js +1 -0
  174. package/build/core/task/commands.js +25 -0
  175. package/build/core/task/compose.js +3 -2
  176. package/build/core/task/document.js +102 -39
  177. package/build/core/task/index.js +3 -3
  178. package/build/core/task/settlement-git.js +1 -4
  179. package/build/core/task/settlement-policy.js +27 -14
  180. package/build/core/task/source-board.js +1 -0
  181. package/build/core/task/task-bind-preparation.js +59 -9
  182. package/build/core/task/task-contract.js +2 -2
  183. package/build/core/task/task-store-repository.js +1 -0
  184. package/build/core/task/task.js +2 -2
  185. package/build/core/transcripts.js +4 -4
  186. package/build/core/verification-declaration.js +95 -0
  187. package/build/core/worktree-bootstrap.js +1 -1
  188. package/build/core/worktree-path.js +7 -11
  189. package/build/flow-error.js +9 -1
  190. package/build/generated/version.js +2 -2
  191. package/build/git/branches.js +41 -70
  192. package/build/git/commits.js +92 -21
  193. package/build/git/core.js +9 -161
  194. package/build/git/diff/preview.js +4 -4
  195. package/build/git/diff/read.js +4 -4
  196. package/build/git/diff/structured.js +5 -5
  197. package/build/git/process.js +229 -0
  198. package/build/git/refs.js +30 -5
  199. package/build/git/staging.js +39 -115
  200. package/build/git/streaming-batch.js +9 -16
  201. package/build/git/worktree.js +104 -91
  202. package/build/index.js +7 -0
  203. package/package.json +1 -1
  204. package/skills/keiyaku-akuma/SKILL.md +21 -20
  205. package/skills/keiyaku-task/SKILL.md +38 -4
  206. package/skills/keiyaku-workflow/SKILL.md +51 -11
  207. package/build/cli/commands/projection/revive/meta.js +0 -12
  208. package/build/core/projection/projection-life-protocol.js +0 -115
  209. package/build/core/projection/projection-runner-lock.js +0 -211
  210. package/build/core/projection/tell/database.js +0 -127
  211. package/build/core/settlement/verification-coordination.js +0 -305
  212. package/build/core/settlement/verification-supervisor.js +0 -275
@@ -1,26 +1,42 @@
1
1
  import { readKanshiBoard } from "../../../../core/status/board.js";
2
2
  import { normalizeTargetRef } from "../../../../core/target-ref.js";
3
- import { isProjectionId } from "../../../../core/projection/index.js";
4
- import { FlowError } from "../../../../flow-error.js";
5
- import { renderProjectionFilteredStatus, renderStatusBoard } from "../../../render/status.js";
3
+ import { buildStatusPayload, renderAkumaRosterStatus, renderProjectionFilteredStatus, renderStatusBoard, renderStatusJson, } from "../../../render/status.js";
6
4
  import { coreTextResponse } from "../../../render/shared.js";
7
5
  import { projectDirectory, repositoryDirectory } from "../../shared.js";
8
6
  export const handler = async (_stdin, flags, _signal, positional) => {
9
- const [projectionId] = positional;
10
- if (projectionId !== undefined && !isProjectionId(projectionId)) {
11
- throw new FlowError("EMPTY_PARAM", `invalid projection id: ${projectionId}`);
12
- }
7
+ const [projectionAddress] = positional;
13
8
  // Status is read-only and must open outside Git. projectDirectory still
14
9
  // honors --repo as a repository coordinate when the operator names one.
15
- const cwd = flags.target === undefined
10
+ const cwd = flags.target === undefined && flags.contractId === undefined
16
11
  ? await projectDirectory(flags, "status")
17
- : await repositoryDirectory(flags, "status target filtering");
12
+ : await repositoryDirectory(flags, flags.contractId === undefined ? "status target filtering" : "status commission filtering");
18
13
  const target = flags.target === undefined ? undefined : normalizeTargetRef(flags.target);
19
14
  const board = await readKanshiBoard(cwd, Date.now(), {
20
15
  ...(target === undefined ? {} : { target }),
21
- ...(projectionId === undefined ? {} : { projectionId }),
16
+ ...(projectionAddress === undefined ? {} : { projectionAddress }),
17
+ ...(flags.akumaRoster ? {
18
+ roster: true,
19
+ ...(flags.historyLimit === undefined ? {} : { rosterLimit: flags.historyLimit }),
20
+ ...(flags.historyOffset === undefined ? {} : { rosterOffset: flags.historyOffset }),
21
+ } : {}),
22
+ ...(flags.contractId === undefined ? {} : {
23
+ commission: {
24
+ raw: flags.contractId,
25
+ source: flags.contractAddressSource ?? "explicit-flag",
26
+ },
27
+ }),
22
28
  });
23
- if (projectionId === undefined)
24
- return coreTextResponse(renderStatusBoard(board), board);
25
- return coreTextResponse(renderProjectionFilteredStatus(board, projectionId), board);
29
+ const selectedProjection = projectionAddress === undefined ? undefined : board.projections?.rows[0];
30
+ const unknown = projectionAddress !== undefined
31
+ && (selectedProjection === undefined || selectedProjection.state === "lost" || selectedProjection.state === "unknown");
32
+ const payload = buildStatusPayload(board);
33
+ if (flags.json)
34
+ return { ...coreTextResponse(renderStatusJson(payload), payload), ...(unknown ? { exitCode: 4 } : {}) };
35
+ if (projectionAddress === undefined) {
36
+ return coreTextResponse(flags.akumaRoster ? renderAkumaRosterStatus(board) : renderStatusBoard(board), payload);
37
+ }
38
+ return {
39
+ ...coreTextResponse(renderProjectionFilteredStatus(board, projectionAddress), payload),
40
+ ...(unknown ? { exitCode: 4 } : {}),
41
+ };
26
42
  };
@@ -1,9 +1,20 @@
1
1
  export const meta = {
2
2
  command: "status",
3
3
  summary: "Show the Kanshi board",
4
- usage: ["keiyaku status [PROJECTION] [-C|--cwd DIR] [--repo DIR] [--target REF]"],
4
+ usage: [
5
+ "keiyaku status [PROJECTION|ALIAS] [-C|--cwd DIR] [--repo DIR] [--target REF]",
6
+ "keiyaku status --akuma [PROJECTION|ALIAS] [--limit COUNT] [--offset COUNT] [-C|--cwd DIR] [--repo DIR]",
7
+ "keiyaku status --contract ADDR [-C|--cwd DIR] [--repo DIR] [--target REF]",
8
+ "keiyaku @addr status [-C|--cwd DIR] [--repo DIR] [--target REF]",
9
+ ],
5
10
  stdin: { mode: "argument" },
6
- flags: ["cwd", "repo", "target"],
7
- purpose: "Read the Kanshi board or filter it to one projection without mutation.",
11
+ flags: ["cwd", "repo", "contract", "target", "akuma", "limit", "offset", "json"],
12
+ flagUsages: {
13
+ akuma: "--akuma",
14
+ },
15
+ flagDescriptions: {
16
+ akuma: "Show the complete Akuma projection roster; optionally address one projection or alias.",
17
+ },
18
+ purpose: "Read the Kanshi board or filter it to one projection or commission without mutation.",
8
19
  completionRank: 14,
9
20
  };
@@ -1,8 +1,8 @@
1
1
  import { FlowError } from "../../../../flow-error.js";
2
- import { assertTellEffortSupported, interruptProjectionGeneration, tellProjection, writeInboxTell } from "../../../../core/projection/index.js";
2
+ import { assertTellEffortSupported, interruptProjectionGeneration, readProjectionAlias, tellProjection, writeInboxTell } from "../../../../core/projection/index.js";
3
3
  import { waitForProjection } from "../../../../core/projection/index.js";
4
4
  import { prependAddressReceipt } from "../../../render/address.js";
5
- import { buildSilentTellResponse } from "../../../render/tell.js";
5
+ import { buildTellAcceptedResponse } from "../../../render/tell.js";
6
6
  import { buildWaitResponse } from "../../../render/wait.js";
7
7
  import { resolveProjectionCommandTarget, runProjectionCommand, } from "../shared.js";
8
8
  export const handler = async (body, flags, signal, positional) => runProjectionCommand(flags, "tell", async (ctx) => {
@@ -23,6 +23,10 @@ export const handler = async (body, flags, signal, positional) => runProjectionC
23
23
  await tellProjection(projection.directory, projection.id, flags.effort);
24
24
  }
25
25
  if (flags.timeoutMs === undefined)
26
- return buildSilentTellResponse();
27
- return prependAddressReceipt(buildWaitResponse(projection.id, await waitForProjection({ projectionDirectory: projection.directory, timeoutMs: flags.timeoutMs, signal }), { alias: projection.alias }), ctx.address, { projectionId: projection.id, projectionAlias: projection.alias });
26
+ return buildTellAcceptedResponse(projection.id, projectionAddress, projection.alias);
27
+ const alias = projection.alias
28
+ && await readProjectionAlias(ctx.address?.repo.stableRoot ?? ctx.cwd, projection.alias) === projection.id
29
+ ? projection.alias
30
+ : undefined;
31
+ return prependAddressReceipt(buildWaitResponse(projection.id, await waitForProjection({ projectionDirectory: projection.directory, timeoutMs: flags.timeoutMs, signal }), { alias, inputToken: projectionAddress }), ctx.address, { projectionId: projection.id, projectionAlias: alias });
28
32
  });
@@ -6,7 +6,7 @@ export const meta = {
6
6
  mode: "argument",
7
7
  selector: { kind: "positional", index: 1, required: true, rejectBlank: true },
8
8
  },
9
- flags: ["cwd", "repo", "contract", "effort", "interrupt", "wait"],
9
+ flags: ["cwd", "repo", "contract", "effort", "interrupt", "wait", "json"],
10
10
  purpose: "Write intent to the mailbox; --interrupt terminates the active turn before successor wake.",
11
11
  completionRank: 3,
12
12
  };
@@ -1,30 +1,50 @@
1
- import { projectionDirAtCoordinate, resolveProjectionCoordinate, snapshotCommissionProjectionIdsAtCoordinate, waitForProjection, waitForProjectionSet, } from "../../../../core/projection/index.js";
1
+ import { projectionDirAtCoordinate, projectionAliasRootAtCoordinate, readProjectionAliasAtRoot, resolveProjectionCoordinate, snapshotCommissionProjectionIdsAtCoordinate, waitForProjection, waitForProjectionSet, } from "../../../../core/projection/index.js";
2
2
  import { FlowError } from "../../../../flow-error.js";
3
- import { prependAddressReceipt } from "../../../render/address.js";
4
3
  import { buildProjectionWaitSetResponse, buildWaitResponse } from "../../../render/wait.js";
5
- import { resolveProjectionCommandAddress, resolveProjectionCommandTarget, runProjectionCommand, } from "../shared.js";
4
+ import { resolveProjectionCommandAddress, runProjectionCommand, } from "../shared.js";
6
5
  import { WAIT_SET_SELECTION_ERROR } from "./meta.js";
6
+ async function refreshWaitAddresses(result, coordinate) {
7
+ const aliasRoot = projectionAliasRootAtCoordinate(coordinate);
8
+ return {
9
+ ...result,
10
+ results: await Promise.all(result.results.map(async (member) => {
11
+ const { alias: admittedAlias, inputToken: admittedToken, ...rest } = member;
12
+ const alias = admittedAlias && await readProjectionAliasAtRoot(aliasRoot, admittedAlias) === member.id
13
+ ? admittedAlias
14
+ : undefined;
15
+ const inputToken = admittedToken === admittedAlias && alias === undefined
16
+ ? member.id
17
+ : admittedToken;
18
+ return {
19
+ ...rest,
20
+ ...(inputToken ? { inputToken } : {}),
21
+ ...(alias ? { alias } : {}),
22
+ };
23
+ })),
24
+ };
25
+ }
7
26
  export const handler = async (_stdin, flags, signal, positional) => runProjectionCommand(flags, "wait", async (ctx) => {
27
+ const coordinate = ctx.address
28
+ ? {
29
+ physicalRoot: ctx.address.repo.stableRoot,
30
+ authority: { kind: "repository", stableRoot: ctx.address.repo.stableRoot },
31
+ }
32
+ : await resolveProjectionCoordinate(ctx.cwd);
8
33
  // Selection modes only govern admitted sets with more than one explicit member.
9
34
  if (positional.length === 1) {
10
- const projection = await resolveProjectionCommandTarget(ctx, positional[0], "wait");
11
- return prependAddressReceipt(buildWaitResponse(projection.id, await waitForProjection({
35
+ const projection = await resolveProjectionCommandAddress(ctx, positional[0], "wait", coordinate);
36
+ const result = await waitForProjection({
12
37
  projectionDirectory: projection.directory,
13
38
  timeoutMs: flags.timeoutMs,
14
39
  signal,
15
- }), { alias: projection.alias }), ctx.address, { projectionId: projection.id, projectionAlias: projection.alias });
40
+ });
41
+ const alias = projection.alias
42
+ && await readProjectionAliasAtRoot(projectionAliasRootAtCoordinate(coordinate), projection.alias) === projection.id
43
+ ? projection.alias
44
+ : undefined;
45
+ return buildWaitResponse(projection.id, result, { alias, inputToken: positional[0] });
16
46
  }
17
47
  const selected = new Map();
18
- let coordinate;
19
- if (ctx.address) {
20
- coordinate = {
21
- physicalRoot: ctx.address.repo.stableRoot,
22
- authority: { kind: "repository", stableRoot: ctx.address.repo.stableRoot },
23
- };
24
- }
25
- else {
26
- coordinate = await resolveProjectionCoordinate(ctx.cwd);
27
- }
28
48
  if (positional.length === 0) {
29
49
  if (ctx.address?.binding.kind === "commission") {
30
50
  for (const id of await snapshotCommissionProjectionIdsAtCoordinate(coordinate, ctx.address.binding.commissionId)) {
@@ -36,20 +56,25 @@ export const handler = async (_stdin, flags, signal, positional) => runProjectio
36
56
  // Resolve in argument order so multiple bad coordinates have one stable failure.
37
57
  for (const projectionAddress of positional) {
38
58
  const projection = await resolveProjectionCommandAddress(ctx, projectionAddress, "wait", coordinate);
39
- selected.set(projection.id, { id: projection.id, projectionDirectory: projection.directory });
59
+ selected.set(projection.id, {
60
+ id: projection.id,
61
+ projectionDirectory: projection.directory,
62
+ inputToken: projectionAddress,
63
+ ...(projection.alias ? { alias: projection.alias } : {}),
64
+ });
40
65
  }
41
66
  }
42
- const projections = [...selected.values()].sort((left, right) => left.id.localeCompare(right.id));
67
+ const projections = [...selected.values()];
43
68
  if (projections.length === 0) {
44
69
  throw new FlowError("EMPTY_PARAM", "wait commission snapshot contains no projections");
45
70
  }
46
71
  if (!flags.any && !flags.all) {
47
72
  throw new FlowError("EMPTY_PARAM", WAIT_SET_SELECTION_ERROR);
48
73
  }
49
- return prependAddressReceipt(buildProjectionWaitSetResponse(await waitForProjectionSet({
74
+ return buildProjectionWaitSetResponse(await refreshWaitAddresses(await waitForProjectionSet({
50
75
  projections,
51
76
  selection: flags.any ? "any" : "all",
52
77
  timeoutMs: flags.timeoutMs,
53
78
  signal,
54
- })), ctx.address);
79
+ }), coordinate));
55
80
  });
@@ -8,7 +8,7 @@ export const meta = {
8
8
  "keiyaku @addr wait [<projection-address>...] (--any|--all) [--timeout DURATION]",
9
9
  ],
10
10
  stdin: { mode: "argument" },
11
- flags: ["cwd", "repo", "contract", "timeout", "any", "all"],
11
+ flags: ["cwd", "repo", "contract", "timeout", "any", "all", "json"],
12
12
  flagDescriptions: {
13
13
  all: "For a projection set, return only after every admitted member reaches a terminal state.",
14
14
  },
@@ -39,7 +39,7 @@ export function buildCallInput(content, flags, mode = "call", platform = process
39
39
  ...(mode === "call" && flags.alias !== undefined ? { alias: assertProjectionAlias(flags.alias) } : {}),
40
40
  };
41
41
  }
42
- export function revivePrompt(stdin) {
42
+ export function forkPrompt(stdin) {
43
43
  return stdin.trim() ? stdin : "Continue from the previous response.";
44
44
  }
45
45
  export function effectiveDirectory(flags, platform = process.platform) {
@@ -1,7 +1,9 @@
1
1
  import { meta as guideMeta } from "./guide/meta.js";
2
2
  import { meta as completionMeta } from "./completion/meta.js";
3
3
  import { meta as dumpEnvMeta } from "./dump-env/meta.js";
4
+ import { meta as verificationMeta } from "../verification/meta.js";
4
5
  export const systemCatalog = [
6
+ { meta: verificationMeta, load: async () => await import("../verification/handler.js") },
5
7
  { meta: guideMeta, load: () => import("./guide/handler.js") },
6
8
  { meta: completionMeta, load: () => import("./completion/handler.js") },
7
9
  { meta: dumpEnvMeta, load: () => import("./dump-env/handler.js") },
@@ -1,22 +1,38 @@
1
- import { createTask, openTaskMutationContext, resolveTaskCreator, } from "../../../../core/task/index.js";
1
+ import { createTask, openTaskMutationContext, parseTaskCreationDocument, resolveTaskCreator, } from "../../../../core/task/index.js";
2
+ import { FlowError } from "../../../../flow-error.js";
2
3
  import { renderTaskMutationRow } from "../../../render/task.js";
3
4
  import { textResponse } from "../../../render/shared.js";
4
- import { effectiveDirectory } from "../../shared.js";
5
- import { parseTaskAddInput } from "../shared.js";
6
- export const handler = async (stdin, flags, signal) => {
7
- const input = parseTaskAddInput(stdin);
8
- const cwd = effectiveDirectory(flags);
5
+ import { taskCommandDirectory } from "../shared.js";
6
+ function hasCreationFlags(flags) {
7
+ return flags.taskPri !== undefined
8
+ || flags.taskNeeds !== undefined
9
+ || flags.taskParent !== undefined
10
+ || flags.taskFrom !== undefined
11
+ || flags.taskSupersedes !== undefined
12
+ || flags.taskRelatesTo !== undefined;
13
+ }
14
+ export const handler = async (stdin, flags, signal, positional) => {
15
+ const fromStdin = positional[0] === "-";
16
+ if (fromStdin && hasCreationFlags(flags)) {
17
+ throw new FlowError("INVALID_USAGE", "task add accepts either a stdin task document or creation flags, not both");
18
+ }
19
+ const input = fromStdin
20
+ ? parseTaskCreationDocument({ path: "stdin", text: stdin })
21
+ : { title: stdin };
22
+ const cwd = await taskCommandDirectory(flags);
9
23
  const context = await openTaskMutationContext(cwd, signal);
10
24
  const task = await createTask(context.repository, {
11
25
  ...input,
12
26
  namespace: context.namespace,
13
27
  creator: await resolveTaskCreator(cwd),
14
- ...(flags.taskPri === undefined ? {} : { pri: flags.taskPri }),
15
- needs: flags.taskNeeds ?? [],
16
- parent: flags.taskParent ?? null,
17
- from: flags.taskFrom ?? [],
18
- supersedes: flags.taskSupersedes ?? [],
19
- relatesTo: flags.taskRelatesTo ?? [],
28
+ ...(fromStdin ? {} : {
29
+ ...(flags.taskPri === undefined ? {} : { pri: flags.taskPri }),
30
+ needs: flags.taskNeeds ?? [],
31
+ parent: flags.taskParent ?? null,
32
+ from: flags.taskFrom ?? [],
33
+ supersedes: flags.taskSupersedes ?? [],
34
+ relatesTo: flags.taskRelatesTo ?? [],
35
+ }),
20
36
  }, { now: () => new Date() });
21
37
  return textResponse(renderTaskMutationRow(task));
22
38
  };
@@ -1,19 +1,31 @@
1
- const TASK_ADD_USAGE_PREFIX = "keiyaku task add [-C|--cwd DIR] [--needs COORDINATE]... [--parent COORDINATE] [--from COORDINATE]... [--supersedes COORDINATE]... [--relates-to COORDINATE]... [--pri 0-3]";
1
+ const TASK_ADD_USAGE_PREFIX = "keiyaku task add [-C|--cwd DIR] [--contract ADDR]";
2
+ const TASK_ADD_CREATION_FLAGS = "[--needs COORDINATE]... [--parent COORDINATE] [--from COORDINATE]... [--supersedes COORDINATE]... [--relates-to COORDINATE]... [--pri 0-3]";
3
+ export const TASK_ADD_INPUT_SHAPE_ERROR = "task add accepts exactly one <TITLE|->; use `keiyaku task add \"title\"` or `keiyaku task add - < task.md`";
2
4
  export const meta = {
3
5
  command: "task add",
4
6
  summary: "Add a task",
5
7
  usage: [
6
- `${TASK_ADD_USAGE_PREFIX} <BODY>`,
8
+ `${TASK_ADD_USAGE_PREFIX} ${TASK_ADD_CREATION_FLAGS} <TITLE>`,
7
9
  `${TASK_ADD_USAGE_PREFIX} - < task.md`,
8
10
  ],
9
11
  stdin: {
10
12
  mode: "argument",
11
13
  selector: { kind: "positional", index: 0, required: true, rejectBlank: true },
12
14
  },
13
- flags: ["cwd", "needs", "parent", "from", "supersedes", "relates-to", "pri"],
14
- purpose: "Create a lightweight task from a title and optional body.",
15
+ flags: ["cwd", "contract", "needs", "parent", "from", "supersedes", "relates-to", "pri"],
16
+ purpose: "Create a lightweight task from a title or one canonical task document.",
17
+ input: [
18
+ "---",
19
+ "title: Extract task parser",
20
+ "pri: 1",
21
+ "needs:",
22
+ " - task-model",
23
+ "---",
24
+ "Markdown body.",
25
+ ],
15
26
  notes: [
16
- "<BODY> and literal - are mutually exclusive body selectors. Use literal - with stdin for multiline prose.",
17
- "Only literal - reads stdin; unselected piped bytes are ignored and never change a literal <BODY>.",
27
+ "Literal - reads one canonical task document. It may declare title, pri, needs, parent, from, supersedes, relatesTo, and Markdown body.",
28
+ "Creation-owned fields (id, state, timestamps, creator, startedAt, contractId) are rejected. Stdin documents and creation flags are mutually exclusive.",
29
+ "Only literal - reads stdin; unselected piped bytes are ignored and never change a literal <TITLE>.",
18
30
  ],
19
31
  };
@@ -9,6 +9,7 @@ import { meta as stopMeta } from "./stop/meta.js";
9
9
  import { meta as holdMeta } from "./hold/meta.js";
10
10
  import { meta as resumeMeta } from "./resume/meta.js";
11
11
  import { meta as doneMeta } from "./done/meta.js";
12
+ import { meta as noteMeta } from "./note/meta.js";
12
13
  import { meta as dropMeta } from "./drop/meta.js";
13
14
  import { meta as updateMeta } from "./update/meta.js";
14
15
  import { meta as doctorMeta } from "./doctor/meta.js";
@@ -24,6 +25,7 @@ export const taskCatalog = [
24
25
  { meta: holdMeta, load: () => import("./hold/handler.js") },
25
26
  { meta: resumeMeta, load: () => import("./resume/handler.js") },
26
27
  { meta: doneMeta, load: () => import("./done/handler.js") },
28
+ { meta: noteMeta, load: () => import("./note/handler.js") },
27
29
  { meta: dropMeta, load: () => import("./drop/handler.js") },
28
30
  { meta: updateMeta, load: () => import("./update/handler.js") },
29
31
  { meta: doctorMeta, load: () => import("./doctor/handler.js") },
@@ -1,9 +1,9 @@
1
1
  import { composeTasks, openTaskMutationContext, planTaskComposition, resolveTaskCreator, } from "../../../../core/task/index.js";
2
2
  import { renderTaskComposition, renderTaskCompositionJson } from "../../../render/task.js";
3
3
  import { textResponse } from "../../../render/shared.js";
4
- import { effectiveDirectory } from "../../shared.js";
4
+ import { taskCommandDirectory } from "../shared.js";
5
5
  export const handler = async (stdin, flags, signal) => {
6
- const cwd = effectiveDirectory(flags);
6
+ const cwd = await taskCommandDirectory(flags);
7
7
  const context = await openTaskMutationContext(cwd, signal);
8
8
  const input = {
9
9
  sketch: stdin,
@@ -1,9 +1,9 @@
1
1
  export const meta = {
2
2
  command: "task compose",
3
3
  summary: "Atomically compose tasks from a tree sketch",
4
- usage: ["keiyaku task compose [-C|--cwd DIR] [--check] - < sketch.md"],
4
+ usage: ["keiyaku task compose [-C|--cwd DIR] [--contract ADDR] [--check] - < sketch.md"],
5
5
  stdin: { mode: "document", selector: { kind: "positional", index: 0, required: true, rejectBlank: true } },
6
- flags: ["cwd", "check", "json"],
6
+ flags: ["cwd", "contract", "check", "json"],
7
7
  purpose: "Atomically create and rewire tasks from one validated tree sketch.",
8
8
  input: ["Each task line is two-space indented + title or @COORDINATE, followed by whitespace-separated parent=, needs=@a,@b, supersedes=@c, or relates=@d declarations. Bare prose is allowed only in a nested + task body."],
9
9
  notes: ["Nesting assigns parent. Top-level references preserve their parent; parent= clears it. Omitted relation declarations preserve their current complete set, while an explicit empty declaration clears that set."],
@@ -1,4 +1,3 @@
1
1
  import { textResponse } from "../../../render/shared.js";
2
- import { effectiveDirectory } from "../../shared.js";
3
- import { renderTaskDoctor } from "../shared.js";
4
- export const handler = async (_stdin, flags) => textResponse(await renderTaskDoctor(effectiveDirectory(flags)));
2
+ import { renderTaskDoctor, taskCommandDirectory } from "../shared.js";
3
+ export const handler = async (_stdin, flags) => textResponse(await renderTaskDoctor(await taskCommandDirectory(flags)));
@@ -1,8 +1,8 @@
1
1
  export const meta = {
2
2
  command: "task doctor",
3
3
  summary: "Diagnose the task board",
4
- usage: ["keiyaku task doctor [-C|--cwd DIR]"],
4
+ usage: ["keiyaku task doctor [-C|--cwd DIR] [--contract ADDR]"],
5
5
  stdin: { mode: "argument" },
6
- flags: ["cwd"],
6
+ flags: ["cwd", "contract"],
7
7
  purpose: "Report task state counts, supported board diseases, and lock state without repair.",
8
8
  };
@@ -1,8 +1,8 @@
1
1
  export const meta = {
2
2
  command: "task done",
3
3
  summary: "Complete a task",
4
- usage: ["keiyaku task done [-C|--cwd DIR] [COORDINATE]"],
4
+ usage: ["keiyaku task done [-C|--cwd DIR] [--contract ADDR] [COORDINATE]"],
5
5
  stdin: { mode: "argument" },
6
- flags: ["cwd"],
6
+ flags: ["cwd", "contract"],
7
7
  purpose: "Complete an open or in-progress task.",
8
8
  };
@@ -1,3 +1,8 @@
1
- import { dropTask } from "../../../../core/task/index.js";
1
+ import { dropTask, dropTaskWithNote, resolveTaskCreator } from "../../../../core/task/index.js";
2
2
  import { runTaskMutationCommand } from "../shared.js";
3
- export const handler = async (_stdin, flags, _signal, positional) => runTaskMutationCommand(flags, (repository) => dropTask(repository, positional[0]));
3
+ export const handler = async (_stdin, flags, _signal, positional) => runTaskMutationCommand(flags, async (repository, cwd) => flags.taskNote === undefined
4
+ ? dropTask(repository, positional[0])
5
+ : dropTaskWithNote(repository, positional[0], {
6
+ actor: await resolveTaskCreator(cwd),
7
+ text: flags.taskNote,
8
+ }));
@@ -1,8 +1,11 @@
1
1
  export const meta = {
2
2
  command: "task drop",
3
3
  summary: "Drop a task",
4
- usage: ["keiyaku task drop [-C|--cwd DIR] COORDINATE"],
5
- stdin: { mode: "argument" },
6
- flags: ["cwd"],
4
+ usage: ["keiyaku task drop [-C|--cwd DIR] [--contract ADDR] COORDINATE [--note TEXT|-]"],
5
+ stdin: {
6
+ mode: "argument",
7
+ selector: { kind: "flag", names: ["taskNote"], required: false, rejectBlank: true },
8
+ },
9
+ flags: ["cwd", "contract", "note"],
7
10
  purpose: "Abandon an open or in-progress task.",
8
11
  };
@@ -1,8 +1,8 @@
1
1
  export const meta = {
2
2
  command: "task hold",
3
3
  summary: "Put a task on hold",
4
- usage: ["keiyaku task hold [-C|--cwd DIR] COORDINATE"],
4
+ usage: ["keiyaku task hold [-C|--cwd DIR] [--contract ADDR] COORDINATE"],
5
5
  stdin: { mode: "argument" },
6
- flags: ["cwd"],
6
+ flags: ["cwd", "contract"],
7
7
  purpose: "Move an open or in-progress task to on hold.",
8
8
  };
@@ -1,8 +1,8 @@
1
1
  export const meta = {
2
2
  command: "task log",
3
3
  summary: "Show one task's Git history",
4
- usage: ["keiyaku task log [-C|--cwd DIR] COORDINATE"],
4
+ usage: ["keiyaku task log [-C|--cwd DIR] [--contract ADDR] COORDINATE"],
5
5
  stdin: { mode: "argument" },
6
- flags: ["cwd"],
6
+ flags: ["cwd", "contract"],
7
7
  purpose: "Read the current checkout branch's task micro-commit history.",
8
8
  };
@@ -1,8 +1,8 @@
1
1
  export const meta = {
2
2
  command: "task ls",
3
3
  summary: "List tasks",
4
- usage: ["keiyaku task ls [-C|--cwd DIR] [--all|--done] [--filter EXPR] [--sort KEYS] [--json]"],
4
+ usage: ["keiyaku task ls [-C|--cwd DIR] [--contract ADDR] [--all|--done] [--filter EXPR] [--sort KEYS] [--json]"],
5
5
  stdin: { mode: "argument" },
6
- flags: ["cwd", "all", "done", "filter", "sort", "json"],
6
+ flags: ["cwd", "contract", "all", "done", "filter", "sort", "json"],
7
7
  purpose: "List tasks from the working-tree board.",
8
8
  };
@@ -0,0 +1,6 @@
1
+ import { appendTaskNote, resolveTaskCreator } from "../../../../core/task/index.js";
2
+ import { runTaskMutationCommand } from "../shared.js";
3
+ export const handler = async (stdin, flags, _signal, positional) => runTaskMutationCommand(flags, async (repository, cwd) => appendTaskNote(repository, positional[0], {
4
+ actor: await resolveTaskCreator(cwd),
5
+ text: stdin,
6
+ }));
@@ -0,0 +1,11 @@
1
+ export const meta = {
2
+ command: "task note",
3
+ summary: "Append an immutable task note",
4
+ usage: ["keiyaku task note [-C|--cwd DIR] [--contract ADDR] COORDINATE TEXT|-"],
5
+ stdin: {
6
+ mode: "argument",
7
+ selector: { kind: "positional", index: 1, required: true, rejectBlank: true },
8
+ },
9
+ flags: ["cwd", "contract"],
10
+ purpose: "Record an append-only task journal fact.",
11
+ };
@@ -1,8 +1,8 @@
1
1
  export const meta = {
2
2
  command: "task resume",
3
3
  summary: "Resume a task on hold",
4
- usage: ["keiyaku task resume [-C|--cwd DIR] COORDINATE"],
4
+ usage: ["keiyaku task resume [-C|--cwd DIR] [--contract ADDR] COORDINATE"],
5
5
  stdin: { mode: "argument" },
6
- flags: ["cwd"],
6
+ flags: ["cwd", "contract"],
7
7
  purpose: "Return an on-hold task to open.",
8
8
  };
@@ -1,30 +1,44 @@
1
1
  import { FlowError } from "../../../flow-error.js";
2
+ import { attachAddressCarrier, resolveExplicitContractAddressFromRead } from "../../../core/addressing.js";
3
+ import { readRepositoryLifecycle } from "../../../core/repository-ledger/read-model.js";
4
+ import { findRegisteredContractWorktreePathFromModel, stableRepoRoot } from "../../../core/worktree-path.js";
2
5
  import { openTaskCommandRepository, parseTaskDocument, readTaskDoctor, taskCoordinateFromSourcePath, } from "../../../core/task/index.js";
3
6
  import { deriveTaskDisplay, renderTaskList, renderTaskMutationRow, } from "../../render/task.js";
4
7
  import { textResponse } from "../../render/shared.js";
5
8
  import { effectiveDirectory } from "../shared.js";
6
- /** Open the task command repository for flags.cwd and run the verb. */
7
- export async function withTaskCommandRepository(flags, run) {
9
+ /** Resolve --contract to its one ledger-owned checkout before task access. */
10
+ export async function taskCommandDirectory(flags) {
8
11
  const cwd = effectiveDirectory(flags);
12
+ if (flags.contractId === undefined)
13
+ return cwd;
14
+ const stableRoot = await stableRepoRoot(cwd);
15
+ const admitted = resolveExplicitContractAddressFromRead({
16
+ read: await readRepositoryLifecycle(stableRoot),
17
+ stableRoot,
18
+ workdir: cwd,
19
+ raw: flags.contractId,
20
+ source: flags.contractAddressSource ?? "explicit-flag",
21
+ });
22
+ const worktree = admitted.model.resources.worktree;
23
+ const lifecycle = admitted.model.phase;
24
+ if (!worktree || worktree.state !== "held") {
25
+ throw attachAddressCarrier(new FlowError("CONTRACT_WORKSPACE_UNAVAILABLE", `contract ${admitted.model.contract} has no materialized workspace for task commands (${lifecycle})`, { facts: { kind: "task_contract_workspace", contractId: admitted.model.contract, lifecycle, reason: "not-materialized" } }), admitted.address);
26
+ }
27
+ const registered = await findRegisteredContractWorktreePathFromModel(stableRoot, admitted.model);
28
+ if (!registered) {
29
+ throw attachAddressCarrier(new FlowError("CONTRACT_WORKSPACE_UNAVAILABLE", `contract ${admitted.model.contract} worktree is not a verified ledger-owned materialized checkout`, { facts: { kind: "task_contract_workspace", contractId: admitted.model.contract, lifecycle, reason: "unregistered" } }), admitted.address);
30
+ }
31
+ return registered;
32
+ }
33
+ /** Open the selected task command repository and run the verb. */
34
+ export async function withTaskCommandRepository(flags, run) {
35
+ const cwd = await taskCommandDirectory(flags);
9
36
  return run(await openTaskCommandRepository(cwd), cwd);
10
37
  }
11
38
  /** Shared shell: open repository → mutate → renderTaskMutationRow receipt. */
12
39
  export async function runTaskMutationCommand(flags, mutate) {
13
40
  return textResponse(renderTaskMutationRow(await withTaskCommandRepository(flags, mutate)));
14
41
  }
15
- export function parseTaskAddInput(input) {
16
- if (!input.trim())
17
- throw new FlowError("EMPTY_PARAM", "task add input cannot be blank");
18
- const lines = input.split(/\r?\n/);
19
- const firstLine = lines[0]?.startsWith("# ") ? lines[0].slice(2) : lines[0];
20
- const title = firstLine?.trim() ?? "";
21
- if (!title)
22
- throw new FlowError("EMPTY_PARAM", "task title cannot be blank");
23
- if (lines.length > 1 && lines[1].trim() !== "") {
24
- throw new FlowError("EMPTY_PARAM", "task add body must follow the title after a blank line");
25
- }
26
- return { title, body: lines.slice(2).join("\n") };
27
- }
28
42
  export function taskSelection(flags) {
29
43
  return flags.all ? "all" : flags.done ? "done" : "default";
30
44
  }
@@ -1,8 +1,8 @@
1
1
  export const meta = {
2
2
  command: "task show",
3
3
  summary: "Show one task and its children tree",
4
- usage: ["keiyaku task show [-C|--cwd DIR] COORDINATE [--json]"],
4
+ usage: ["keiyaku task show [-C|--cwd DIR] [--contract ADDR] COORDINATE [--json]"],
5
5
  stdin: { mode: "argument" },
6
- flags: ["cwd", "json"],
6
+ flags: ["cwd", "contract", "json"],
7
7
  purpose: "Read one task and every descendant linked by parent edges.",
8
8
  };
@@ -1,8 +1,8 @@
1
1
  export const meta = {
2
2
  command: "task start",
3
3
  summary: "Start a task",
4
- usage: ["keiyaku task start [-C|--cwd DIR] COORDINATE"],
4
+ usage: ["keiyaku task start [-C|--cwd DIR] [--contract ADDR] COORDINATE"],
5
5
  stdin: { mode: "argument" },
6
- flags: ["cwd"],
6
+ flags: ["cwd", "contract"],
7
7
  purpose: "Move an open task to in_progress.",
8
8
  };
@@ -1,8 +1,8 @@
1
1
  export const meta = {
2
2
  command: "task stop",
3
3
  summary: "Stop a task",
4
- usage: ["keiyaku task stop [-C|--cwd DIR] [COORDINATE]"],
4
+ usage: ["keiyaku task stop [-C|--cwd DIR] [--contract ADDR] [COORDINATE]"],
5
5
  stdin: { mode: "argument" },
6
- flags: ["cwd"],
6
+ flags: ["cwd", "contract"],
7
7
  purpose: "Return an in-progress task to open.",
8
8
  };