@astrosheep/keiyaku 4.6.11 → 4.6.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 (138) hide show
  1. package/build/plugins/claude/skills/keiyaku/SKILL.md +3 -1
  2. package/build/plugins/claude/skills/keiyaku-babysit/SKILL.md +1 -1
  3. package/build/plugins/claude/skills/keiyaku-bind/SKILL.md +3 -2
  4. package/build/plugins/claude/skills/keiyaku-workflow/SKILL.md +9 -8
  5. package/build/plugins/codex/skills/keiyaku/SKILL.md +3 -1
  6. package/build/plugins/codex/skills/keiyaku-babysit/SKILL.md +1 -1
  7. package/build/plugins/codex/skills/keiyaku-bind/SKILL.md +3 -2
  8. package/build/plugins/codex/skills/keiyaku-workflow/SKILL.md +9 -8
  9. package/build/plugins/opencode/skills/keiyaku/SKILL.md +3 -1
  10. package/build/plugins/opencode/skills/keiyaku-babysit/SKILL.md +1 -1
  11. package/build/plugins/opencode/skills/keiyaku-bind/SKILL.md +3 -2
  12. package/build/plugins/opencode/skills/keiyaku-workflow/SKILL.md +9 -8
  13. package/build/skills/keiyaku/SKILL.md +3 -1
  14. package/build/skills/keiyaku-babysit/SKILL.md +1 -1
  15. package/build/skills/keiyaku-bind/SKILL.md +3 -2
  16. package/build/skills/keiyaku-workflow/SKILL.md +9 -8
  17. package/build/src/akuma/akuma-errors.d.ts +5 -0
  18. package/build/src/akuma/akuma-errors.js +9 -0
  19. package/build/src/akuma/akuma-owner.d.ts +14 -19
  20. package/build/src/akuma/akuma-owner.js +56 -54
  21. package/build/src/akuma/akuma-selection-execution.d.ts +5 -4
  22. package/build/src/akuma/akuma-selection-execution.js +59 -17
  23. package/build/src/akuma/akuma.d.ts +1 -2
  24. package/build/src/akuma/allowed.d.ts +2 -3
  25. package/build/src/akuma/allowed.js +1 -3
  26. package/build/src/akuma/body.js +17 -7
  27. package/build/src/akuma/call-initial-tell.d.ts +18 -0
  28. package/build/src/akuma/call-initial-tell.js +18 -0
  29. package/build/src/akuma/call-request.d.ts +20 -4
  30. package/build/src/akuma/heart/facts.d.ts +13 -0
  31. package/build/src/akuma/heart/facts.js +6 -0
  32. package/build/src/akuma/heart/index.d.ts +29 -14
  33. package/build/src/akuma/heart/index.js +75 -29
  34. package/build/src/akuma/heart/rows.d.ts +9 -2
  35. package/build/src/akuma/heart/rows.js +72 -11
  36. package/build/src/akuma/heart/storage.d.ts +2 -8
  37. package/build/src/akuma/heart/storage.js +13 -13
  38. package/build/src/akuma/heart/tells.d.ts +3 -1
  39. package/build/src/akuma/heart/tells.js +18 -2
  40. package/build/src/akuma/provider.d.ts +2 -4
  41. package/build/src/akuma/provider.js +29 -6
  42. package/build/src/akuma/providers/acp/core.js +23 -21
  43. package/build/src/akuma/providers/claude/index.js +0 -8
  44. package/build/src/akuma/providers/codex-app-server/index.js +9 -8
  45. package/build/src/akuma/providers/execution-environment.d.ts +1 -1
  46. package/build/src/akuma/providers/execution-environment.js +1 -0
  47. package/build/src/akuma/providers/opencode-sdk/events.js +111 -81
  48. package/build/src/akuma/providers/opencode-sdk/index.js +179 -150
  49. package/build/src/akuma/providers/opencode-sdk/native-http.js +7 -3
  50. package/build/src/akuma/providers/opencode-sdk/session.d.ts +5 -3
  51. package/build/src/akuma/providers/opencode-sdk/session.js +32 -27
  52. package/build/src/akuma/providers/paseo/index.js +0 -2
  53. package/build/src/akuma/providers/pi/index.js +23 -20
  54. package/build/src/akuma/selection-observation.d.ts +78 -9
  55. package/build/src/akuma/selection-owner-port.d.ts +2 -1
  56. package/build/src/akuma/selection-owner-port.js +6 -1
  57. package/build/src/akuma/selection-request.d.ts +1 -1
  58. package/build/src/akuma/selection-request.js +8 -3
  59. package/build/src/akuma/turn-drive.js +79 -48
  60. package/build/src/akuma-body.js +5 -3
  61. package/build/src/cli/commands/akuma-grammar.js +2 -2
  62. package/build/src/cli/commands/akuma.js +24 -16
  63. package/build/src/cli/commands/contract-grammar.d.ts +3 -7
  64. package/build/src/cli/commands/contract-grammar.js +12 -10
  65. package/build/src/cli/commands/contract-help.d.ts +3 -13
  66. package/build/src/cli/commands/contract-help.js +7 -16
  67. package/build/src/cli/commands/contract.js +19 -35
  68. package/build/src/cli/commands/debt.js +30 -29
  69. package/build/src/cli/parse.js +0 -1
  70. package/build/src/cli/render/akuma-activity.d.ts +36 -9
  71. package/build/src/cli/render/akuma-activity.js +142 -65
  72. package/build/src/cli/render/akuma.d.ts +6 -0
  73. package/build/src/cli/render/akuma.js +67 -24
  74. package/build/src/cli/render/catalog.js +0 -1
  75. package/build/src/cli/render/contract-observation.d.ts +16 -3
  76. package/build/src/cli/render/contract-observation.js +3 -0
  77. package/build/src/cli/render/contract.d.ts +2 -2
  78. package/build/src/cli/render/contract.js +4 -4
  79. package/build/src/cli/render/delivery-preview.d.ts +7 -0
  80. package/build/src/cli/render/{audit.js → delivery-preview.js} +29 -27
  81. package/build/src/cli/render/kanshi-akuma.d.ts +3 -1
  82. package/build/src/cli/render/kanshi-akuma.js +23 -8
  83. package/build/src/cli/render/kanshi.js +4 -1
  84. package/build/src/cli/render/receipt.js +3 -3
  85. package/build/src/cli/render/refusal.js +2 -2
  86. package/build/src/cli/render/terminal.d.ts +0 -1
  87. package/build/src/cli/render/terminal.js +1 -1
  88. package/build/src/cli/square-identity.d.ts +15 -0
  89. package/build/src/cli/square-identity.js +180 -0
  90. package/build/src/contract-worktree.js +1 -1
  91. package/build/src/core/verbs/placement.d.ts +2 -1
  92. package/build/src/core/verbs/placement.js +1 -1
  93. package/build/src/debt/context.d.ts +0 -5
  94. package/build/src/debt/context.js +32 -44
  95. package/build/src/git/process.d.ts +1 -0
  96. package/build/src/git/process.js +18 -1
  97. package/build/src/git/read-observation.js +2 -1
  98. package/build/src/git/scratch.d.ts +5 -1
  99. package/build/src/git/scratch.js +41 -12
  100. package/build/src/git/target-placement.d.ts +22 -4
  101. package/build/src/git/target-placement.js +44 -20
  102. package/build/src/index.d.ts +2 -2
  103. package/build/src/kanshi/read.js +187 -105
  104. package/build/src/kanshi/report.d.ts +5 -0
  105. package/build/src/library/address.d.ts +18 -4
  106. package/build/src/library/address.js +27 -6
  107. package/build/src/library/contract-address.d.ts +6 -0
  108. package/build/src/library/contract-address.js +12 -1
  109. package/build/src/library/contract-execution.d.ts +2 -2
  110. package/build/src/library/contract-execution.js +13 -17
  111. package/build/src/library/contract-operations.d.ts +59 -94
  112. package/build/src/library/contract-operations.js +23 -19
  113. package/build/src/library/contract-outcomes.d.ts +3 -3
  114. package/build/src/library/contract-settings.d.ts +1 -0
  115. package/build/src/library/contract-settings.js +1 -1
  116. package/build/src/library/invocation.d.ts +2 -2
  117. package/build/src/library/invocation.js +1 -1
  118. package/build/src/library/keiyaku.d.ts +2 -2
  119. package/build/src/library/keiyaku.js +2 -2
  120. package/build/src/library/outcome.d.ts +148 -268
  121. package/build/src/library/outcome.js +4 -8
  122. package/build/src/library/refusal.d.ts +2 -2
  123. package/build/src/library/refusal.js +2 -2
  124. package/build/src/plugin/runtime.js +15 -19
  125. package/build/src/protocol/{audit.d.ts → delivery-preview.d.ts} +62 -97
  126. package/build/src/protocol/delivery-preview.js +167 -0
  127. package/build/src/protocol/progress.d.ts +1 -1
  128. package/build/src/runtime/proc/run.js +22 -4
  129. package/build/src/runtime/proc/windows-launch.exe +0 -0
  130. package/build/src/verification/execution.d.ts +1 -1
  131. package/build/src/verification/execution.js +5 -3
  132. package/package.json +5 -2
  133. package/skills/keiyaku/SKILL.md +3 -1
  134. package/skills/keiyaku-babysit/SKILL.md +1 -1
  135. package/skills/keiyaku-bind/SKILL.md +3 -2
  136. package/skills/keiyaku-workflow/SKILL.md +9 -8
  137. package/build/src/cli/render/audit.d.ts +0 -7
  138. package/build/src/protocol/audit.js +0 -203
@@ -14,6 +14,7 @@ import { settings } from "./settings.js";
14
14
  import { Debts } from "./debt/index.js";
15
15
  import { debtMutationRequestCommands } from "./debt/mutation.js";
16
16
  import { World } from "./world.js";
17
+ import { readSoul } from "./akuma/heart/index.js";
17
18
  async function contractDependencies(repoRoot, processConfiguration) {
18
19
  const repo = await Repo.at({
19
20
  path: repoRoot,
@@ -39,9 +40,9 @@ function contractChannel(repo, contractId, requester, configuration) {
39
40
  }
40
41
  function contractUpstream(processConfiguration) {
41
42
  return {
42
- audit: async (input) => {
43
+ previewDelivery: async (input) => {
43
44
  const [repo, configuration] = await contractDependencies(input.repoRoot, processConfiguration);
44
- return await contractChannel(repo, input.contractId, input.requester, configuration).audit({
45
+ return await contractChannel(repo, input.contractId, input.requester, configuration).previewDelivery({
45
46
  includeDirty: input.includeDirty,
46
47
  showDiff: input.showDiff,
47
48
  signal: input.signal,
@@ -96,11 +97,12 @@ function debtMutationRequestPort() {
96
97
  }
97
98
  export async function externalRequestCommandsFor(launch, processConfiguration) {
98
99
  const world = await World.prove(worldRootForAkumaPaths(launch.paths));
100
+ const servingBody = launch.seed?.id ?? (await readSoul(launch.paths))?.id;
99
101
  return {
100
102
  world,
101
103
  commands: composeRequestCommands(selectionRequestCommands(selectionRequestPort(world, (message) => {
102
104
  void recordPluginDiagnostic(launch.paths, "outcome observation", message);
103
- })), contractRequestCommands(contractUpstream(processConfiguration)), debtMutationRequestCommands(debtMutationRequestPort())),
105
+ }, servingBody)), contractRequestCommands(contractUpstream(processConfiguration)), debtMutationRequestCommands(debtMutationRequestPort())),
104
106
  };
105
107
  }
106
108
  function bodyProcessConfiguration() {
@@ -61,7 +61,7 @@ const AKUMA_COMMAND_SPECS = {
61
61
  purpose: "Tell an Akuma something without waiting for its answer.",
62
62
  details: [
63
63
  "Give <prompt> as one argument, or use - to read stdin.",
64
- "--interrupt ends the Akuma's current work before accepting the new prompt and waking it again.",
64
+ "--interrupt durably admits the new Tell while asking the current Body to yield; admission remains even if completion cannot be proven.",
65
65
  "Use ask to block for the answer or supply a schema.",
66
66
  ].join("\n"),
67
67
  },
@@ -73,7 +73,7 @@ const AKUMA_COMMAND_SPECS = {
73
73
  purpose: "Ask an Akuma and block until it answers.",
74
74
  details: [
75
75
  "Give <prompt> as one argument, or use - to read stdin.",
76
- "--interrupt ends the Akuma's current work before accepting the new prompt and waking it again.",
76
+ "--interrupt durably admits the new Tell while asking the current Body to yield; admission remains even if completion cannot be proven.",
77
77
  "--schema reads a JSON Schema file for the answer contract; stdin remains the prompt source.",
78
78
  "--wait bounds how long to block for the answer; the Tell stays admitted past the deadline.",
79
79
  "Completed activity streams on stderr and the final answer is written to stdout once.",
@@ -2,7 +2,7 @@ import { akumaCallerFromEnvironment } from "../akuma-caller.js";
2
2
  import { CliUsageError, isBlankInput } from "../usage.js";
3
3
  import { readFile } from "node:fs/promises";
4
4
  import { resolve } from "node:path";
5
- import { squareAssignedParticipantName } from "@astrosheep/square";
5
+ import { squareSeat } from "../square-identity.js";
6
6
  import { emitPluginSignal } from "../../plugin/akuma-signals.js";
7
7
  import { canonicalBirthCwd } from "../../akuma/call-input.js";
8
8
  import { Schema } from "../../akuma/index.js";
@@ -14,9 +14,9 @@ import { World } from "../../world.js";
14
14
  import { contractFromInput } from "../selectors.js";
15
15
  import { ActivityDriver } from "../activity.js";
16
16
  import { displayContext, emit, resultContext, writeJson, writeStderr, writeStdout } from "../streams.js";
17
- import { callObservationStream, inputWaitStream } from "../render/akuma-activity.js";
17
+ import { callObservationStream } from "../render/akuma-activity.js";
18
18
  import { askRawAnswer, callRawAnswer, historyRawAnswer, historyText, tellText, waitText, } from "../render/akuma-activity.js";
19
- import { askExitCode, askProgressStream, callExitCode, callObservationHead, forkExitCode, historyExitCode, killExitCode, renderCallText, renderForkText, renderKillText, tellExitCode, waitedTellProgress, } from "../render/akuma.js";
19
+ import { askExitCode, askProgressStream, callExitCode, callObservationHead, forkExitCode, historyExitCode, killExitCode, renderCallText, renderFailedCallObservation, renderForkText, renderKillText, tellExitCode, waitedTellProgress, } from "../render/akuma.js";
20
20
  export { isParsedAkumaCommand, renderAkumaHelp } from "./akuma-grammar.js";
21
21
  // ---------------------------------------------------------------------------
22
22
  // Leaf dispatch: acquisition, one public SDK invocation, direct rendering
@@ -50,12 +50,23 @@ async function promptBody(action, command, input) {
50
50
  throw new CliUsageError(`${action} requires a nonblank prompt`);
51
51
  return bytes;
52
52
  }
53
- async function inputInitiator(input) {
54
- let initiator;
53
+ /**
54
+ * A generic integration initiator outranks any Square guess; otherwise the Square
55
+ * edge selects. Identity selection is optional, so it never refuses the operation.
56
+ */
57
+ async function submittingInitiator(input) {
58
+ const declared = input.environment.KEIYAKU_INITIATOR?.trim();
59
+ if (declared !== undefined && declared !== "")
60
+ return declared;
55
61
  try {
56
- initiator = squareAssignedParticipantName(input.environment);
62
+ return await squareSeat({ path: input.path, environment: input.environment }, { ...(input.signal === undefined ? {} : { signal: input.signal }) });
63
+ }
64
+ catch {
65
+ return undefined;
57
66
  }
58
- catch { }
67
+ }
68
+ async function inputInitiator(input) {
69
+ const initiator = await submittingInitiator(input);
59
70
  if (initiator === undefined)
60
71
  return {};
61
72
  // Identity preparation needs established plugin custody, not just a candidate.
@@ -104,9 +115,11 @@ async function runCall(command, input) {
104
115
  const observe = observing
105
116
  ? {
106
117
  admitted: (tell, id, head) => {
107
- stream = callObservationStream(resultContext(), callObservationHead({ akuma: id, ...head }), {
108
- admittedAt: tell.row.at,
109
- });
118
+ stream = callObservationStream(resultContext(), callObservationHead({
119
+ akuma: id,
120
+ ...head,
121
+ ...(input.executionCwd === undefined ? {} : { cwd: input.executionCwd }),
122
+ }), { admittedAt: tell.row.at });
110
123
  driver.redraw(stream.frame());
111
124
  },
112
125
  observe: (observation) => {
@@ -126,12 +139,7 @@ async function runCall(command, input) {
126
139
  driver.conclude(stream.conclude(result.observation));
127
140
  }
128
141
  else if (observing && result.observation.kind === "failed") {
129
- const fallback = inputWaitStream(resultContext(), () => callObservationHead({
130
- akuma: result.akuma,
131
- dispatch: result.dispatch,
132
- alias: result.alias,
133
- }), { cursor: "empty", answerSeparator: true });
134
- writeStderr(fallback.conclude({ kind: "failed", diagnostic: result.observation.failure.diagnostic }));
142
+ writeStderr(renderFailedCallObservation(result, resultContext()));
135
143
  streamed = true;
136
144
  }
137
145
  if (command.output === "json") {
@@ -40,6 +40,8 @@ export type ParsedAmend = Output & Actor & Readonly<{
40
40
  export type ParsedDeliver = Output & Readonly<{
41
41
  command: "deliver";
42
42
  contract?: string;
43
+ dryRun: boolean;
44
+ showDiff: boolean;
43
45
  message?: string;
44
46
  includeDirty: boolean;
45
47
  materializeConflict: boolean;
@@ -90,12 +92,6 @@ export type ParsedLs = Output & Readonly<{
90
92
  command: "ls";
91
93
  query: CatalogQuery;
92
94
  }>;
93
- export type ParsedAudit = Output & Readonly<{
94
- command: "audit";
95
- contract?: string;
96
- includeDirty: boolean;
97
- showDiff: boolean;
98
- }>;
99
95
  export type ParsedReconcile = Output & Readonly<{
100
96
  command: "reconcile";
101
97
  contract?: string;
@@ -121,7 +117,7 @@ export type ParsedContractParts = Readonly<{
121
117
  output: "text" | "json";
122
118
  actor?: string;
123
119
  }>;
124
- export type ParsedContractCommand = ParsedBind | ParsedAmend | ParsedDeliver | ParsedReview | ParsedArc | ParsedAbandon | ParsedShow | ParsedStatus | ParsedLs | ParsedAudit | ParsedReconcile | ParsedNuke | ParsedSettings | ParsedRegion;
120
+ export type ParsedContractCommand = ParsedBind | ParsedAmend | ParsedDeliver | ParsedReview | ParsedArc | ParsedAbandon | ParsedShow | ParsedStatus | ParsedLs | ParsedReconcile | ParsedNuke | ParsedSettings | ParsedRegion;
125
121
  export type StatusCategory = "akuma" | "contract";
126
122
  export declare function parseContractCommand(parts: ParsedContractParts): ParsedContractCommand;
127
123
  export {};
@@ -105,8 +105,20 @@ function parseAmend(parts) {
105
105
  function parseDeliver(parts) {
106
106
  const contract = parts.positionals[0];
107
107
  const message = optionalFlag(parts.flags, "message");
108
+ const dryRun = parts.flags["dry-run"] === true;
109
+ if (dryRun) {
110
+ for (const flag of ["materialize-conflict", "overwrite", "message"]) {
111
+ if (parts.flags[flag] !== undefined)
112
+ refuse("deliver", `--${flag} is not valid with --dry-run`);
113
+ }
114
+ }
115
+ else if (parts.flags["show-diff"] === true) {
116
+ refuse("deliver", "--show-diff requires --dry-run");
117
+ }
108
118
  return {
109
119
  command: "deliver",
120
+ dryRun,
121
+ showDiff: parts.flags["show-diff"] === true,
110
122
  ...(contract === undefined ? {} : { contract }),
111
123
  ...(message === undefined ? {} : { message }),
112
124
  includeDirty: parts.flags["include-dirty"] === true,
@@ -284,16 +296,6 @@ export function parseContractCommand(parts) {
284
296
  return parseStatus(parts);
285
297
  case "ls":
286
298
  return parseLs(parts);
287
- case "audit": {
288
- const contract = parts.positionals[0];
289
- return {
290
- command: "audit",
291
- ...(contract === undefined ? {} : { contract }),
292
- includeDirty: parts.flags["include-dirty"] === true,
293
- showDiff: parts.flags["show-diff"] === true,
294
- output: parts.output,
295
- };
296
- }
297
299
  case "reconcile": {
298
300
  const contract = parts.positionals[0];
299
301
  return {
@@ -44,12 +44,14 @@ export declare const CONTRACT_COMMAND_SPECS: {
44
44
  readonly stdin: "none";
45
45
  readonly flags: {
46
46
  readonly message: "value";
47
+ readonly "dry-run": "boolean";
48
+ readonly "show-diff": "boolean";
47
49
  readonly "include-dirty": "boolean";
48
50
  readonly "materialize-conflict": "boolean";
49
51
  readonly overwrite: "boolean";
50
52
  readonly json: "boolean";
51
53
  };
52
- readonly usage: "deliver [<contract>|@<contract>] [--message <text>] [--include-dirty] [--materialize-conflict] [--overwrite]";
54
+ readonly usage: "deliver [<contract>|@<contract>] [--message <text>] [--include-dirty] [--materialize-conflict] [--overwrite] | deliver [<contract>|@<contract>] --dry-run [--include-dirty] [--show-diff]";
53
55
  readonly purpose: "Submit work for a Contract and integrate it when its requirements are met.";
54
56
  readonly details: string;
55
57
  };
@@ -121,18 +123,6 @@ export declare const CONTRACT_COMMAND_SPECS: {
121
123
  readonly purpose: "List debts (ls debt), contracts (ls kei), or akumas (ls aku).";
122
124
  readonly details: string;
123
125
  };
124
- readonly audit: {
125
- readonly positional: "optional";
126
- readonly stdin: "none";
127
- readonly flags: {
128
- readonly "include-dirty": "boolean";
129
- readonly "show-diff": "boolean";
130
- readonly json: "boolean";
131
- };
132
- readonly usage: "audit [<contract>|@<contract>] [--include-dirty] [--show-diff]";
133
- readonly purpose: "Preview what would happen if you delivered a Contract now.";
134
- readonly details: string;
135
- };
136
126
  readonly reconcile: {
137
127
  readonly positional: "optional";
138
128
  readonly stdin: "none";
@@ -90,12 +90,14 @@ export const CONTRACT_COMMAND_SPECS = {
90
90
  stdin: "none",
91
91
  flags: {
92
92
  message: "value",
93
+ "dry-run": "boolean",
94
+ "show-diff": "boolean",
93
95
  "include-dirty": "boolean",
94
96
  "materialize-conflict": "boolean",
95
97
  overwrite: "boolean",
96
98
  json: "boolean",
97
99
  },
98
- usage: "deliver [<contract>|@<contract>] [--message <text>] [--include-dirty] [--materialize-conflict] [--overwrite]",
100
+ usage: "deliver [<contract>|@<contract>] [--message <text>] [--include-dirty] [--materialize-conflict] [--overwrite] | deliver [<contract>|@<contract>] --dry-run [--include-dirty] [--show-diff]",
99
101
  purpose: "Submit work for a Contract and integrate it when its requirements are met.",
100
102
  details: [
101
103
  "The Contract, not the current Arc, sets what delivery must satisfy. An Arc records progress; it does not narrow acceptance.",
@@ -106,6 +108,9 @@ export const CONTRACT_COMMAND_SPECS = {
106
108
  "Delivery requests integration. If prerequisites and gates pass, it integrates now and accepts the Contract; otherwise the candidate remains waiting.",
107
109
  "Only changed candidate work invalidates earlier review. If Verification did not finish, repeating delivery resumes that candidate; --overwrite replaces it.",
108
110
  "Delivery never counts as an independent review verdict.",
111
+ "--dry-run observes the candidate, preparation conflicts, standing Verification evidence and target followability without submitting work. It never runs Verification or hooks, places, reconciles, settles, or continues dependents. Real delivery observes again; a prepared candidate is not a promise of acceptance.",
112
+ "--show-diff includes the proposed diff and requires --dry-run. --message, --materialize-conflict and --overwrite are refused with --dry-run.",
113
+ "Preview may create ref-free Git objects and a transient private index; refs, the real index, worktree bytes and worktree registrations are preserved.",
109
114
  "Content identity names the change's content hash, never a commit; it survives rebase and Git cannot look it up.",
110
115
  "",
111
116
  " --materialize-conflict Write the observed integration conflict into the worktree as an uncommitted merge.",
@@ -186,20 +191,6 @@ export const CONTRACT_COMMAND_SPECS = {
186
191
  'ls "aku/<name>/*" is the same living set in glob form; ls "aku/*/*" lists every living Akuma.',
187
192
  ].join("\n"),
188
193
  },
189
- audit: {
190
- positional: "optional",
191
- stdin: "none",
192
- flags: { "include-dirty": "boolean", "show-diff": "boolean", json: "boolean" },
193
- usage: "audit [<contract>|@<contract>] [--include-dirty] [--show-diff]",
194
- purpose: "Preview what would happen if you delivered a Contract now.",
195
- details: [
196
- "--include-dirty checks all non-ignored worktree changes, staged or not.",
197
- "--show-diff includes the proposed candidate diff when one can be prepared.",
198
- "Verification runs only with the verified gate; without it the section is inert text.",
199
- "Content identity names the change's content hash, never a commit; it survives rebase and Git cannot look it up.",
200
- "Progress appears on stderr; stdout contains one final result.",
201
- ].join("\n"),
202
- },
203
194
  reconcile: {
204
195
  positional: "optional",
205
196
  stdin: "none",
@@ -247,7 +238,7 @@ export function renderContractHelp(command) {
247
238
  "Recognized settings:",
248
239
  " gates named gate groups selected by bind and amend",
249
240
  " worktree commands run when worktrees are created or destroyed",
250
- " git.requireBranchesToBeUpToDate whether deliver and audit require up-to-date target branches",
241
+ " git.requireBranchesToBeUpToDate whether delivery and its preview require up-to-date target branches",
251
242
  " providers the available Akuma and how each is run",
252
243
  "",
253
244
  "Each entry is validated by the feature that reads it. A rejected",
@@ -1,7 +1,7 @@
1
1
  import { executionChannel } from "../../akuma/requests.js";
2
2
  import { Akumas, Keiyaku, KeiyakuError, kanshiCategory, listArchetypeDefinitions, nuke } from "../../index.js";
3
- import { kanshi, observeKanshi, selectRegion } from "../../kanshi/index.js";
4
- import { resolveNamedAddress } from "../../library/address.js";
3
+ import { kanshi, selectRegion } from "../../kanshi/index.js";
4
+ import { observeNamedAddress, resolveNamedAddress } from "../../library/address.js";
5
5
  import { composeContractLibrary, observeKeiyaku } from "../../library/contract-composition.js";
6
6
  import { validateArcMarkdown, validateContractMarkdown } from "../../library/input.js";
7
7
  import { createKeiyakuHandle } from "../../library/keiyaku.js";
@@ -35,11 +35,11 @@ async function settingsAt(root, home) {
35
35
  }
36
36
  /**
37
37
  * The process edge loads one Settings value and hands it to the private composition.
38
- * A forwarded audit/deliver/review is served by its parent, which loads its own.
38
+ * A forwarded preview/deliver/review is served by its parent, which loads its own.
39
39
  */
40
40
  async function contractSettings(command, execution, world, home) {
41
41
  const forwarded = executionChannel(execution).kind === "body-request" &&
42
- (command.command === "audit" || command.command === "deliver" || command.command === "review");
42
+ (command.command === "deliver" || command.command === "review");
43
43
  if (forwarded)
44
44
  return undefined;
45
45
  return await settingsAt(world ?? undefined, home);
@@ -125,7 +125,7 @@ async function existingSeat(command, coordinates, runtime, library) {
125
125
  }
126
126
  /** One composition for every mutation leaf; gates, hooks, and freshness derive lazily inside it. */
127
127
  async function contractLibrary(command, execution, configuration, runtime) {
128
- const actor = executionChannel(execution).kind === "local" && ["audit", "deliver", "review"].includes(command.command)
128
+ const actor = executionChannel(execution).kind === "local" && ["deliver", "review"].includes(command.command)
129
129
  ? actorFromEdge(undefined, runtime.environment)
130
130
  : undefined;
131
131
  return composeContractLibrary(execution, createKeiyakuHandle, {
@@ -191,6 +191,8 @@ async function runAmend(command, input, seat) {
191
191
  return await finishContractAnswer(answer, command.output);
192
192
  }
193
193
  async function runDeliver(command, runtime, seat) {
194
+ if (command.dryRun)
195
+ return await runDeliveryPreview(command, runtime, seat);
194
196
  const driver = command.output === "text" ? await runtime.progress() : undefined;
195
197
  let answer;
196
198
  try {
@@ -253,11 +255,11 @@ async function runAbandon(command, seat) {
253
255
  });
254
256
  return await finishContractAnswer(answer, command.output);
255
257
  }
256
- async function runAudit(command, runtime, seat) {
258
+ async function runDeliveryPreview(command, runtime, seat) {
257
259
  const driver = command.output === "text" ? await runtime.progress() : undefined;
258
260
  let answer;
259
261
  try {
260
- answer = await seat.contract.audit({
262
+ answer = await seat.contract.previewDelivery({
261
263
  includeDirty: command.includeDirty,
262
264
  showDiff: command.showDiff,
263
265
  ...(runtime.signal === undefined ? {} : { signal: runtime.signal }),
@@ -285,8 +287,6 @@ async function runContractMutation(command, input) {
285
287
  return await runArc(command, input.runtime, seat);
286
288
  case "abandon":
287
289
  return await runAbandon(command, seat);
288
- case "audit":
289
- return await runAudit(command, input.runtime, seat);
290
290
  }
291
291
  }
292
292
  function statusRefusal(operation, contract) {
@@ -352,28 +352,18 @@ async function readAkumaStatus(akuma, alias, coordinates) {
352
352
  project: () => snapshotText(status, displayContext(), ...(alias === undefined ? [{}] : [{ alias }])),
353
353
  };
354
354
  }
355
- async function readContractStatus(selector, coordinates, named) {
355
+ async function readContractStatus(selector, coordinates) {
356
356
  const repo = requiredRepo(coordinates);
357
- if (selector !== undefined && selector.startsWith("@")) {
358
- if (named === undefined)
359
- throw new CliUsageError("cannot resolve a named status selector");
360
- const address = resolveNamedAddress({ selector, report: named.report, aliases: named.aliases });
361
- if (address.kind === "akuma")
362
- throw new CliUsageError("named status selector resolved to an Akuma");
363
- const report = await kanshi({ world: coordinates.world, repo, contract: address.id });
364
- return { value: report, project: () => renderKanshiText(report, displayContext(), "contract") };
365
- }
366
357
  const contract = selector === undefined ? undefined : canonicalContractSelector(selector);
367
358
  const report = await kanshi({ world: coordinates.world, repo, ...(contract === undefined ? {} : { contract }) });
368
359
  return { value: report, project: () => renderKanshiText(report, displayContext(), "contract") };
369
360
  }
370
- async function namedStatus(selector, coordinates, named) {
371
- if (named === undefined)
372
- throw new CliUsageError("cannot resolve a named status selector");
373
- const address = resolveNamedAddress({ selector, report: named.report, aliases: named.aliases });
361
+ /** Identity comes from the complete candidate observation; display detail is requested only after it. */
362
+ async function namedStatus(selector, coordinates, authority) {
363
+ const address = resolveNamedAddress({ selector, contracts: authority.contracts, aliases: authority.aliases });
374
364
  if (address.kind === "akuma")
375
365
  return await readAkumaStatus(address.id, selector, coordinates);
376
- return await readContractStatus(address.id, coordinates, named);
366
+ return await readContractStatus(address.id, coordinates);
377
367
  }
378
368
  async function runShow(command, coordinates) {
379
369
  const repo = coordinates.repo;
@@ -394,11 +384,8 @@ async function runStatusSelection(command, coordinates) {
394
384
  if (selectors.some((selector) => !selector.startsWith("aku/") && !selector.startsWith("@")) &&
395
385
  coordinates.repo === undefined)
396
386
  throw new CliUsageError("cannot select a contract while the Contract world is absent");
397
- const named = selectors.some((selector) => selector.startsWith("@"))
398
- ? await observeKanshi({
399
- world: coordinates.world,
400
- ...(coordinates.repo === undefined ? {} : { repo: coordinates.repo }),
401
- })
387
+ const authority = selectors.some((selector) => selector.startsWith("@"))
388
+ ? await observeNamedAddress({ world: coordinates.world, repo: coordinates.repo ?? null })
402
389
  : undefined;
403
390
  const values = [];
404
391
  const blocks = [];
@@ -406,8 +393,8 @@ async function runStatusSelection(command, coordinates) {
406
393
  const resolved = selector.startsWith("aku/")
407
394
  ? await readAkumaStatus(selector, undefined, coordinates)
408
395
  : selector.startsWith("@")
409
- ? await namedStatus(selector, coordinates, named)
410
- : await readContractStatus(selector, coordinates, named);
396
+ ? await namedStatus(selector, coordinates, authority)
397
+ : await readContractStatus(selector, coordinates);
411
398
  values.push(resolved.value);
412
399
  if (command.output === "text")
413
400
  blocks.push(resolved.project());
@@ -434,10 +421,7 @@ async function runStatusIdentity(command, coordinates) {
434
421
  return emit(command.output, report, () => renderKanshiText(report, displayContext(), "world"), 0);
435
422
  }
436
423
  if (command.contract.startsWith("@")) {
437
- const resolved = await namedStatus(command.contract, coordinates, await observeKanshi({
438
- world: coordinates.world,
439
- ...(coordinates.repo === undefined ? {} : { repo: coordinates.repo }),
440
- }));
424
+ const resolved = await namedStatus(command.contract, coordinates, await observeNamedAddress({ world: coordinates.world, repo: coordinates.repo ?? null }));
441
425
  return emit(command.output, resolved.value, () => resolved.project(), 0);
442
426
  }
443
427
  if (command.contract.startsWith("kei/")) {
@@ -242,7 +242,7 @@ async function runBatchLifecycle(debts, command, verb) {
242
242
  return emit(command.output, result, () => renderDebtLifecycle(verb, result, displayContext()), debtExitCode(result));
243
243
  }
244
244
  async function runMutation(input) {
245
- const { debts, command, current } = input;
245
+ const { debts, command } = input;
246
246
  if (isWorldObservationAction(command) || command.action === "tree")
247
247
  return await runRead(input);
248
248
  switch (command.action) {
@@ -257,24 +257,6 @@ async function runMutation(input) {
257
257
  case "done":
258
258
  case "drop":
259
259
  return await runBatchLifecycle(debts, command, command.action);
260
- case "context": {
261
- const selected = namespace(command.positionals[0]);
262
- if (selected !== undefined) {
263
- await installNamespaceContext(input.context.writeRoot ?? input.context.directory, selected);
264
- const resolved = await resolveDebtNamespaceContext(input.context);
265
- if (typeof resolved === "object" && "kind" in resolved) {
266
- const result = { kind: "refused", refusal: resolved };
267
- return emit(command.output, result, () => renderDebtContext(result, displayContext()), debtExitCode(result));
268
- }
269
- const result = { kind: "accepted", value: resolved };
270
- return emit(command.output, result, () => renderDebtContext(result, displayContext()), debtExitCode(result));
271
- }
272
- const result = {
273
- kind: "accepted",
274
- value: { namespace: current ?? [], source: "default-root" },
275
- };
276
- return emit(command.output, result, () => renderDebtContext(result, displayContext()), debtExitCode(result));
277
- }
278
260
  default:
279
261
  throw new Error(`debt action has no invocation: ${command.action}`);
280
262
  }
@@ -298,12 +280,35 @@ function refuseNamespace(command, refusal) {
298
280
  }
299
281
  case "add":
300
282
  return emit(command.output, result, () => renderDebtMutation("add", result, displayContext()), debtExitCode(result));
301
- case "context":
302
- return emit(command.output, result, () => renderDebtContext(result, displayContext()), debtExitCode(result));
303
283
  default:
304
284
  throw new Error(`debt action has no namespace refusal: ${command.action}`);
305
285
  }
306
286
  }
287
+ /**
288
+ * `debt context` adapted once. An omitted selector observes the default, so it reads the installed
289
+ * context. An explicit selector replaces it without consulting the context it supersedes, so malformed
290
+ * old bytes cannot block a deliberate change. The owner validates the supplied namespace, and every
291
+ * answer is the readback of the default a later caller would resolve.
292
+ */
293
+ async function runContext(command, context) {
294
+ const selected = namespace(command.positionals[0]);
295
+ if (selected !== undefined) {
296
+ try {
297
+ await installNamespaceContext(context.writeRoot ?? context.directory, selected);
298
+ }
299
+ catch (error) {
300
+ // A namespace the owner refuses to install is caller input, never an internal fault.
301
+ if (error instanceof TypeError)
302
+ throw new CliUsageError(error.message);
303
+ throw error;
304
+ }
305
+ }
306
+ const resolved = await resolveDebtNamespaceContext(context);
307
+ const result = typeof resolved === "object" && "kind" in resolved
308
+ ? { kind: "refused", refusal: resolved }
309
+ : { kind: "accepted", value: resolved };
310
+ return emit(command.output, result, () => renderDebtContext(result, displayContext()), debtExitCode(result));
311
+ }
307
312
  // eslint-disable-next-line complexity -- this is the single CLI edge ordering world, context, forwarding, and local execution.
308
313
  export async function runDebtCommand(command, coordinates, runtime) {
309
314
  validateDebtRowView(command);
@@ -316,31 +321,27 @@ export async function runDebtCommand(command, coordinates, runtime) {
316
321
  const world = coordinates.world ?? (establishesWorld(command) ? await coordinates.establishWorld() : null);
317
322
  if (world === null)
318
323
  return missingWorld(command);
324
+ if (command.action === "context")
325
+ return await runContext(command, coordinates.debtContext);
319
326
  const debts = debtsWithExecution(world, runtime.execution);
320
- const contextSensitive = command.action === "context" ||
321
- (command.action === "add" && explicitNamespace === undefined) ||
327
+ const consumesDefaultNamespace = (command.action === "add" && explicitNamespace === undefined) ||
322
328
  (((command.action === "ls" && explicitListNamespace(command) === undefined) ||
323
329
  command.action === "ready" ||
324
330
  command.action === "blocked" ||
325
331
  command.action === "query") &&
326
332
  command.flags.world !== true);
327
333
  let current;
328
- if (contextSensitive) {
334
+ if (consumesDefaultNamespace) {
329
335
  const resolved = await resolveDebtNamespaceContext(coordinates.debtContext);
330
336
  if (typeof resolved === "object" && "kind" in resolved)
331
337
  return refuseNamespace(command, resolved);
332
338
  current = resolved.namespace;
333
- if (command.action === "context" && command.positionals.length === 0) {
334
- const result = { kind: "accepted", value: resolved };
335
- return emit(command.output, result, () => renderDebtContext(result, displayContext()), debtExitCode(result));
336
- }
337
339
  }
338
340
  if (command.action === "show")
339
341
  return await runShow(command, debts);
340
342
  return await runMutation({
341
343
  debts,
342
344
  command,
343
- context: coordinates.debtContext,
344
345
  ...(actor === undefined ? {} : { actor }),
345
346
  ...(current === undefined ? {} : { current }),
346
347
  ...(stdin === undefined ? {} : { stdin }),
@@ -95,7 +95,6 @@ export function commandRepoPolicy(command) {
95
95
  case "review":
96
96
  case "arc":
97
97
  case "abandon":
98
- case "audit":
99
98
  case "reconcile":
100
99
  case "region":
101
100
  case "show":
@@ -8,24 +8,41 @@ import type { AkumaHistoryResult } from "../../library/selection.js";
8
8
  import { type TextRenderContext } from "./terminal.js";
9
9
  export declare const DEFAULT_CONTEXT: TextRenderContext;
10
10
  /**
11
- * The one blessed ruler: a run of U+2500 exactly as wide as the frame head's
12
- * widest line, marking the boundary between an observation frame and its content.
11
+ * The one blessed ruler: a run of U+2500 as wide as the frame head's widest line,
12
+ * never wider than the terminal, marking the boundary between an observation
13
+ * frame and its content.
13
14
  */
14
- export declare function frameRule(headLines: readonly string[]): string;
15
+ export declare function frameRule(headLines: readonly string[], columns?: number): string;
15
16
  type StatusTimeline = AkumaObservation["status"]["timeline"];
16
17
  type RenderedSnapshot = StatusTimeline;
17
18
  type RenderedActivity = Readonly<{
18
19
  snapshot: RenderedSnapshot;
19
20
  rows: readonly ActivityRow[];
20
21
  }>;
21
- export declare function associatedIdentity(id: string, alias?: string, contract?: DispatchAssociation): string;
22
- export declare function snapshotHeading(id: string, alias: string | undefined, contract: DispatchAssociation | undefined): readonly string[];
22
+ /** Indent already-decided supporting lines one level, for every caller of this family. */
23
+ export declare function subordinateLines(lines: readonly string[]): readonly string[];
24
+ /**
25
+ * Identity and its static coordinates. The execution directory and any already-exposed effective
26
+ * actions belong above the content boundary; an absent coordinate is an absent line.
27
+ */
28
+ export declare function panelHead(id: string, alias: string | undefined, contract: DispatchAssociation | undefined, context?: readonly string[]): readonly string[];
29
+ /**
30
+ * One action receipt: the verdict and the complete subject on the first line, every supporting fact
31
+ * indented beneath it. Identity and evidence are never merged into one punctuation run.
32
+ */
33
+ export declare function actionReceipt(input: Readonly<{
34
+ mark: "✓" | "⧗" | "!";
35
+ verb: string;
36
+ id: string;
37
+ alias?: string;
38
+ evidence?: readonly string[];
39
+ }>): readonly string[];
23
40
  /**
24
41
  * The one place row prefixes live: time, mark, verb, content.
25
42
  */
26
43
  type RowLayout = Readonly<{
27
44
  head: (time: string | undefined, glyph: string, verb: string, columns: number) => string;
28
- continuation: () => string;
45
+ continuation: (verb: string) => string;
29
46
  marker: (count: number) => string;
30
47
  history?: true;
31
48
  compactRun?: true;
@@ -71,10 +88,14 @@ export type ObservedCallHead = Readonly<{
71
88
  alias?: string;
72
89
  contract: DispatchAssociation;
73
90
  facts: readonly string[];
91
+ /** A directory the invocation already resolved; never read here to fill the panel. */
92
+ cwd?: string;
74
93
  }>;
75
94
  export type InputWaitConclusion = Readonly<{
76
95
  kind: "failed";
77
96
  diagnostic: string;
97
+ /** Already-decided evidence rows, such as a Tell admitted before the failure. */
98
+ evidence?: readonly string[];
78
99
  }> | Readonly<{
79
100
  kind: "observed";
80
101
  observation: AkumaAskObservation;
@@ -147,7 +168,13 @@ export declare function historyText(result: AkumaHistoryResult, presentation: Ak
147
168
  id?: string;
148
169
  last?: boolean;
149
170
  }>, context: TextRenderContext): string;
150
- export declare function tellText(result: AkumaTellResult, alias: string | undefined, context: TextRenderContext, options?: Readonly<{
151
- identity?: boolean;
152
- }>): string;
171
+ /** One bounded preview of a submitted Tell, indented once beneath its verdict or evidence. */
172
+ export declare function tellPayloadLines(text: string, context: TextRenderContext): readonly string[];
173
+ /** One admitted Tell as a timeline row inside a shared input panel; the panel owns the identity. */
174
+ export declare function tellAdmissionRow(tell: AkumaTellResult["tell"], context: TextRenderContext): string;
175
+ /**
176
+ * One Tell action receipt: the delivery verdict and complete subject, then the submitted payload
177
+ * once. A held Tell keeps neutral vocabulary; a failed delivery keeps its own concrete diagnosis.
178
+ */
179
+ export declare function tellText(result: AkumaTellResult, alias: string | undefined, context: TextRenderContext): string;
153
180
  export {};