@astrosheep/keiyaku 4.6.7 → 4.6.8

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 (165) hide show
  1. package/README.md +6 -2
  2. package/build/plugins/pi/keiyaku.ts +0 -5
  3. package/build/src/akuma/akuma-call.d.ts +2 -0
  4. package/build/src/akuma/akuma-call.js +8 -2
  5. package/build/src/akuma/akuma-instance.d.ts +12 -1
  6. package/build/src/akuma/akuma-instance.js +27 -7
  7. package/build/src/akuma/akuma-observe.js +2 -0
  8. package/build/src/akuma/akuma-owner.d.ts +3 -0
  9. package/build/src/akuma/akuma-owner.js +4 -0
  10. package/build/src/akuma/akuma.d.ts +35 -5
  11. package/build/src/akuma/akuma.js +8 -10
  12. package/build/src/akuma/archetype.d.ts +7 -15
  13. package/build/src/akuma/archetype.js +36 -35
  14. package/build/src/akuma/body.d.ts +5 -3
  15. package/build/src/akuma/body.js +29 -7
  16. package/build/src/akuma/call-request.d.ts +18 -10
  17. package/build/src/akuma/call-request.js +10 -3
  18. package/build/src/akuma/caller.d.ts +39 -0
  19. package/build/src/akuma/caller.js +36 -0
  20. package/build/src/akuma/dispatch-association.d.ts +0 -1
  21. package/build/src/akuma/dispatch-association.js +0 -3
  22. package/build/src/akuma/heart/facts.d.ts +16 -12
  23. package/build/src/akuma/heart/facts.js +8 -0
  24. package/build/src/akuma/heart/index.d.ts +2 -7
  25. package/build/src/akuma/heart/index.js +3 -17
  26. package/build/src/akuma/heart/rows.d.ts +3 -3
  27. package/build/src/akuma/heart/soul.d.ts +1 -1
  28. package/build/src/akuma/heart/soul.js +5 -24
  29. package/build/src/akuma/heart/storage.d.ts +5 -0
  30. package/build/src/akuma/heart/storage.js +7 -3
  31. package/build/src/akuma/identity.d.ts +0 -1
  32. package/build/src/akuma/identity.js +2 -5
  33. package/build/src/akuma/index.d.ts +5 -2
  34. package/build/src/akuma/index.js +1 -0
  35. package/build/src/akuma/nuke.js +6 -28
  36. package/build/src/akuma/projection.d.ts +0 -11
  37. package/build/src/akuma/provider-recipe.d.ts +7 -6
  38. package/build/src/akuma/provider-recipe.js +1 -1
  39. package/build/src/akuma/provider.d.ts +6 -10
  40. package/build/src/akuma/provider.js +6 -7
  41. package/build/src/akuma/providers/acp/events.js +5 -18
  42. package/build/src/akuma/providers/acp/index.js +2 -3
  43. package/build/src/akuma/providers/claude/events.js +35 -60
  44. package/build/src/akuma/providers/claude/index.d.ts +2 -2
  45. package/build/src/akuma/providers/claude/index.js +2 -3
  46. package/build/src/akuma/providers/codex-app-server/index.js +2 -2
  47. package/build/src/akuma/providers/decode.d.ts +25 -0
  48. package/build/src/akuma/providers/decode.js +44 -0
  49. package/build/src/akuma/providers/execution-environment.d.ts +2 -1
  50. package/build/src/akuma/providers/execution-environment.js +3 -0
  51. package/build/src/akuma/providers/grok-build/index.js +6 -22
  52. package/build/src/akuma/providers/index.js +2 -0
  53. package/build/src/akuma/providers/lifecycle.d.ts +9 -0
  54. package/build/src/akuma/providers/lifecycle.js +10 -0
  55. package/build/src/akuma/providers/opencode-sdk/events.js +1 -14
  56. package/build/src/akuma/providers/opencode-sdk/index.js +10 -17
  57. package/build/src/akuma/providers/opencode-sdk/session.js +1 -3
  58. package/build/src/akuma/providers/paseo/events.d.ts +25 -0
  59. package/build/src/akuma/providers/paseo/events.js +157 -0
  60. package/build/src/akuma/providers/paseo/index.d.ts +9 -0
  61. package/build/src/akuma/providers/paseo/index.js +353 -0
  62. package/build/src/akuma/providers/pi/events.js +5 -15
  63. package/build/src/akuma/publication.d.ts +2 -0
  64. package/build/src/akuma/publication.js +5 -0
  65. package/build/src/akuma/request-lifecycle.d.ts +3 -0
  66. package/build/src/akuma/request-lifecycle.js +25 -4
  67. package/build/src/akuma/requests.d.ts +3 -1
  68. package/build/src/akuma/requests.js +32 -0
  69. package/build/src/akuma/selection-observation.d.ts +72 -2
  70. package/build/src/akuma/selection-observation.js +0 -6
  71. package/build/src/akuma/turn-drive.js +2 -5
  72. package/build/src/cli/akuma-caller.d.ts +3 -0
  73. package/build/src/cli/akuma-caller.js +21 -0
  74. package/build/src/cli/commands/akuma-grammar.js +7 -12
  75. package/build/src/cli/commands/akuma.js +12 -4
  76. package/build/src/cli/commands/contract-grammar.d.ts +2 -1
  77. package/build/src/cli/commands/contract-grammar.js +13 -15
  78. package/build/src/cli/commands/contract-help.d.ts +2 -1
  79. package/build/src/cli/commands/contract-help.js +31 -1
  80. package/build/src/cli/commands/contract.js +24 -53
  81. package/build/src/cli/commands/task.js +18 -35
  82. package/build/src/cli/parse.d.ts +2 -2
  83. package/build/src/cli/render/catalog.d.ts +2 -5
  84. package/build/src/cli/render/contract-history.js +3 -6
  85. package/build/src/cli/render/contract.js +15 -50
  86. package/build/src/cli/render/receipt.js +3 -10
  87. package/build/src/cli/render/task.d.ts +4 -6
  88. package/build/src/cli/render/task.js +9 -26
  89. package/build/src/cli/runtime.d.ts +1 -1
  90. package/build/src/cli/runtime.js +11 -17
  91. package/build/src/cli/selectors.d.ts +3 -6
  92. package/build/src/cli/selectors.js +22 -53
  93. package/build/src/dispatch/index.d.ts +3 -3
  94. package/build/src/dispatch/index.js +1 -2
  95. package/build/src/git/observe.d.ts +6 -2
  96. package/build/src/git/observe.js +6 -2
  97. package/build/src/index.d.ts +6 -6
  98. package/build/src/index.js +2 -2
  99. package/build/src/kanshi/index.d.ts +1 -1
  100. package/build/src/kanshi/read.js +21 -6
  101. package/build/src/library/address.js +2 -4
  102. package/build/src/library/akuma-creation.d.ts +5 -1
  103. package/build/src/library/akuma-creation.js +27 -47
  104. package/build/src/library/akumas.d.ts +5 -4
  105. package/build/src/library/akumas.js +13 -9
  106. package/build/src/library/bind.d.ts +14 -14
  107. package/build/src/library/bind.js +11 -7
  108. package/build/src/library/contract-address.d.ts +9 -0
  109. package/build/src/library/contract-address.js +71 -0
  110. package/build/src/library/contract-composition.d.ts +4 -7
  111. package/build/src/library/contract-composition.js +6 -18
  112. package/build/src/library/contract-creation.d.ts +3 -5
  113. package/build/src/library/contract-creation.js +19 -17
  114. package/build/src/library/contract-execution.js +18 -23
  115. package/build/src/library/contract-outcomes.d.ts +2 -14
  116. package/build/src/library/contract-outcomes.js +2 -13
  117. package/build/src/library/contract-types.d.ts +36 -2
  118. package/build/src/library/delivery.d.ts +0 -2
  119. package/build/src/library/delivery.js +2 -5
  120. package/build/src/library/keiyaku.d.ts +0 -5
  121. package/build/src/library/keiyaku.js +6 -12
  122. package/build/src/library/outcome.d.ts +500 -499
  123. package/build/src/library/outcome.js +10 -0
  124. package/build/src/library/reconcile.js +8 -16
  125. package/build/src/library/refusal.d.ts +2 -2
  126. package/build/src/library/repo.d.ts +3 -2
  127. package/build/src/library/repo.js +10 -5
  128. package/build/src/library/selection.d.ts +4 -4
  129. package/build/src/library/selection.js +12 -12
  130. package/build/src/plugin/akuma-signals.d.ts +2 -0
  131. package/build/src/plugin/akuma-signals.js +4 -0
  132. package/build/src/plugin/public.d.ts +27 -2
  133. package/build/src/plugin/runtime.js +2 -2
  134. package/build/src/protocol/amend.js +3 -2
  135. package/build/src/protocol/attempt.js +3 -8
  136. package/build/src/protocol/bind.d.ts +2 -2
  137. package/build/src/protocol/bind.js +1 -1
  138. package/build/src/protocol/deliver.js +3 -3
  139. package/build/src/protocol/operations.d.ts +1 -3
  140. package/build/src/protocol/operations.js +0 -8
  141. package/build/src/protocol/outcome.d.ts +1 -2
  142. package/build/src/protocol/outcome.js +1 -13
  143. package/build/src/protocol/placement.js +3 -10
  144. package/build/src/protocol/read/status.js +31 -70
  145. package/build/src/protocol/reintegrate.js +3 -10
  146. package/build/src/protocol/review.js +3 -3
  147. package/build/src/protocol/run.d.ts +5 -1
  148. package/build/src/protocol/run.js +3 -3
  149. package/build/src/runtime/proc/windows-launch.exe +0 -0
  150. package/package.json +8 -4
  151. package/plugins/pi/keiyaku.ts +57 -0
  152. package/skills/keiyaku/SKILL.md +44 -0
  153. package/skills/keiyaku-akuma/SKILL.md +130 -0
  154. package/skills/keiyaku-akuma/references/automation.md +269 -0
  155. package/skills/keiyaku-babysit/SKILL.md +65 -0
  156. package/skills/keiyaku-bind/SKILL.md +216 -0
  157. package/skills/keiyaku-bind/agents/openai.yaml +4 -0
  158. package/skills/keiyaku-task/SKILL.md +104 -0
  159. package/skills/keiyaku-workflow/SKILL.md +129 -0
  160. package/build/src/cli/commands/amend.d.ts +0 -12
  161. package/build/src/cli/commands/amend.js +0 -10
  162. package/build/src/cli/commands/bind.d.ts +0 -11
  163. package/build/src/cli/commands/bind.js +0 -23
  164. package/build/src/dispatch/association.d.ts +0 -1
  165. package/build/src/dispatch/association.js +0 -1
@@ -0,0 +1,9 @@
1
+ import type { ContractRow } from "../protocol/read/status.js";
2
+ import type { ContractResolution, ContractResolveInput } from "./contract-types.js";
3
+ /** Pure Contract membership shared with mixed Address; no cross-family judgment. */
4
+ export declare function matchContractCandidates(rows: readonly ContractRow[], selection: Readonly<{
5
+ selector: string;
6
+ }> | Readonly<{
7
+ cwd: string;
8
+ }>): readonly ContractRow[];
9
+ export declare function resolveContract(input: ContractResolveInput): Promise<ContractResolution>;
@@ -0,0 +1,71 @@
1
+ import { realpath, stat } from "node:fs/promises";
2
+ import { isAbsolute, normalize } from "node:path";
3
+ import { contractId } from "../core/facts/types.js";
4
+ import { withGitDecodeChannel } from "../git/read-observation.js";
5
+ import { contractsOperation } from "../protocol/operations.js";
6
+ import { requireInput } from "./input.js";
7
+ import { readContractValue } from "./outcome.js";
8
+ import { scopeForRepo } from "./repo.js";
9
+ /** Pure Contract membership shared with mixed Address; no cross-family judgment. */
10
+ export function matchContractCandidates(rows, selection) {
11
+ return rows.filter((row) => row.disposition === "active" &&
12
+ row.workspace === "worktree" &&
13
+ row.worktreePath !== null &&
14
+ ("selector" in selection
15
+ ? `@${row.id.slice("kei/".length)}` === selection.selector
16
+ : normalize(row.worktreePath) === selection.cwd));
17
+ }
18
+ export async function resolveContract(input) {
19
+ const values = requireInput(input, "Keiyaku.with().resolve input", ["repo", "selector", "cwd"]);
20
+ const scope = scopeForRepo(values.repo);
21
+ const selector = values.selector;
22
+ if (selector !== undefined && typeof selector !== "string")
23
+ throw new TypeError("selector must be a string");
24
+ const suppliedCwd = values.cwd;
25
+ if (suppliedCwd !== undefined && (typeof suppliedCwd !== "string" || !isAbsolute(suppliedCwd)))
26
+ throw new TypeError("cwd must be an absolute directory coordinate");
27
+ let cwd = scope.invocationWorktree;
28
+ if (typeof suppliedCwd === "string") {
29
+ try {
30
+ cwd = await realpath(suppliedCwd);
31
+ if (!(await stat(cwd)).isDirectory())
32
+ throw new TypeError("cwd must be a directory");
33
+ }
34
+ catch (cause) {
35
+ throw new TypeError("cwd must be an absolute directory coordinate", { cause });
36
+ }
37
+ }
38
+ if (selector !== undefined) {
39
+ if (selector.startsWith("@kei/"))
40
+ return { kind: "refused", refusal: { kind: "redundant-short-selector", selector } };
41
+ try {
42
+ const id = contractId(selector.startsWith("@") ? `kei/${selector.slice(1)}` : selector);
43
+ if (!selector.startsWith("@"))
44
+ return { kind: "resolved", id };
45
+ }
46
+ catch (error) {
47
+ return {
48
+ kind: "refused",
49
+ refusal: {
50
+ kind: "invalid-selector",
51
+ selector,
52
+ diagnostic: error instanceof Error ? error.message : String(error),
53
+ },
54
+ };
55
+ }
56
+ }
57
+ const board = await readContractValue(() => withGitDecodeChannel(scope, (channel) => contractsOperation({ scope, channel })));
58
+ const candidates = matchContractCandidates(board.rows, selector === undefined ? { cwd } : { selector });
59
+ if (candidates.length === 1)
60
+ return { kind: "resolved", id: candidates[0].id };
61
+ if (selector === undefined) {
62
+ return {
63
+ kind: "refused",
64
+ refusal: candidates.length === 0 ? { kind: "no-contextual-match", cwd } : { kind: "ambiguous-selector", cwd },
65
+ };
66
+ }
67
+ return {
68
+ kind: "refused",
69
+ refusal: candidates.length === 0 ? { kind: "unknown-short-selector", selector } : { kind: "ambiguous-selector", selector },
70
+ };
71
+ }
@@ -1,9 +1,8 @@
1
1
  /** @architectureCompositionRoot */
2
2
  import { type LibraryExecution } from "../akuma/requests.js";
3
- import type { BindTargetSelection } from "../protocol/bind.js";
4
3
  import type { ContractObservation } from "../protocol/read/status.js";
5
4
  import type { BindOutcome } from "./contract-outcomes.js";
6
- import type { BindInput, ContractList, ContractListInput, ContractObservationInput, KeiyakuSelectInput, LocalContractComposition } from "./contract-types.js";
5
+ import type { BindInput, ContractList, ContractListInput, ContractObservationInput, ContractResolveInput, ContractResolution, KeiyakuSelectInput, LocalContractComposition } from "./contract-types.js";
7
6
  import type { Keiyaku, createKeiyakuHandle } from "./keiyaku.js";
8
7
  import { type ReconcileCompletion, type RepoReconcileReport } from "./reconcile.js";
9
8
  import { type Repo } from "./repo.js";
@@ -24,6 +23,7 @@ interface KeiyakuLibraryReconcile {
24
23
  export type KeiyakuLibrary = Readonly<{
25
24
  bind(input: BindInput): Promise<BindOutcome>;
26
25
  select(input: KeiyakuSelectInput): Keiyaku;
26
+ resolve(input: ContractResolveInput): Promise<ContractResolution>;
27
27
  list(input: ContractListInput): Promise<ContractList>;
28
28
  observe(input: ContractObservationInput): Promise<ContractObservation>;
29
29
  reconcile: KeiyakuLibraryReconcile;
@@ -32,12 +32,9 @@ export type KeiyakuLibrary = Readonly<{
32
32
  * The one private Contract composition constructor. `Keiyaku.with` fixes local execution; CLI and
33
33
  * Body pass their captured internal channel explicitly here instead of a second constructor. The
34
34
  * carrier is a positional argument, never a field of the public construction input, so no runtime
35
- * value reaching the public surface can select a private channel. `omittedMarkdownTarget` is the
36
- * internal bind intent an edge supplies for a Markdown bind whose caller omitted the target; the
37
- * public package-root composition leaves it targetless.
35
+ * value reaching the public surface can select a private channel.
38
36
  */
39
- export declare function composeContractLibrary(execution: LibraryExecution, createHandle: typeof createKeiyakuHandle, input?: LocalContractComposition, omittedMarkdownTarget?: BindTargetSelection): KeiyakuLibrary;
37
+ export declare function composeContractLibrary(execution: LibraryExecution, createHandle: typeof createKeiyakuHandle, input?: LocalContractComposition): KeiyakuLibrary;
40
38
  export declare function listKeiyaku(input: ContractListInput): Promise<ContractList>;
41
39
  export declare function observeKeiyaku(input: ContractObservationInput): Promise<ContractObservation>;
42
- export declare function readContractValue<Value>(operation: () => Promise<Value>): Promise<Value>;
43
40
  export {};
@@ -3,25 +3,25 @@ import { localExecutionContext } from "../akuma/requests.js";
3
3
  import { contractId } from "../core/facts/types.js";
4
4
  import { withGitDecodeChannel } from "../git/read-observation.js";
5
5
  import { contractCatalogueOperation, contractObservationOperation, contractsOperation, } from "../protocol/operations.js";
6
+ import { resolveContract } from "./contract-address.js";
6
7
  import { bindKeiyaku } from "./contract-creation.js";
7
8
  import { captureLocalContractComposition, derivedHooks, } from "./contract-settings.js";
8
9
  import { requireInput } from "./input.js";
9
- import { KeiyakuError, errorCategory } from "./outcome.js";
10
+ import { readContractValue } from "./outcome.js";
10
11
  import { completeReconcile, completeRepoReconcile, } from "./reconcile.js";
11
12
  import { scopeForRepo } from "./repo.js";
12
13
  /**
13
14
  * The one private Contract composition constructor. `Keiyaku.with` fixes local execution; CLI and
14
15
  * Body pass their captured internal channel explicitly here instead of a second constructor. The
15
16
  * carrier is a positional argument, never a field of the public construction input, so no runtime
16
- * value reaching the public surface can select a private channel. `omittedMarkdownTarget` is the
17
- * internal bind intent an edge supplies for a Markdown bind whose caller omitted the target; the
18
- * public package-root composition leaves it targetless.
17
+ * value reaching the public surface can select a private channel.
19
18
  */
20
- export function composeContractLibrary(execution, createHandle, input, omittedMarkdownTarget = { kind: "targetless" }) {
19
+ export function composeContractLibrary(execution, createHandle, input) {
21
20
  const composition = captureLocalContractComposition(input);
22
21
  return Object.freeze({
23
- bind: (operation) => bindKeiyaku(operation, createHandle, execution, composition, omittedMarkdownTarget),
22
+ bind: (operation) => bindKeiyaku(operation, createHandle, execution, composition),
24
23
  select: (operation) => selectKeiyaku(operation, createHandle, execution, composition),
24
+ resolve: resolveContract,
25
25
  list: (operation) => listKeiyaku(operation),
26
26
  observe: (operation) => observeKeiyaku(operation),
27
27
  reconcile: reconcileOperation(composition),
@@ -93,15 +93,3 @@ export async function observeKeiyaku(input) {
93
93
  }
94
94
  return readContractValue(() => withGitDecodeChannel(scope, (channel) => contractObservationOperation({ scope, channel, contractId: id })));
95
95
  }
96
- export async function readContractValue(operation) {
97
- try {
98
- return await operation();
99
- }
100
- catch (error) {
101
- if (error instanceof KeiyakuError)
102
- throw error;
103
- throw new KeiyakuError(errorCategory(error), error instanceof Error ? error.message : String(error), {
104
- cause: error,
105
- });
106
- }
107
- }
@@ -1,13 +1,11 @@
1
1
  /** @architectureCompositionRoot */
2
2
  import { type ExecutionContext } from "../akuma/requests.js";
3
- import type { BindTargetSelection } from "../protocol/bind.js";
4
3
  import type { BindOutcome } from "./contract-outcomes.js";
5
4
  import { type LocalContractCompositionCapture } from "./contract-settings.js";
6
5
  import type { BindInput } from "./contract-types.js";
7
6
  import type { createKeiyakuHandle } from "./keiyaku.js";
8
7
  /**
9
- * One Contract bind. `omittedMarkdownTarget` is the internal composition input an edge
10
- * supplies for a Markdown bind whose caller omitted the target: the public package-root
11
- * composition leaves it targetless, while the CLI names the invocation branch.
8
+ * One Contract bind. An omitted Markdown target names the current branch of the caller's explicit
9
+ * Repo worktree coordinate, `null` is deliberately targetless, and a string is that literal target.
12
10
  */
13
- export declare function bindKeiyaku(input: BindInput, createHandle: typeof createKeiyakuHandle, execution?: ExecutionContext, composition?: LocalContractCompositionCapture, omittedMarkdownTarget?: BindTargetSelection): Promise<BindOutcome>;
11
+ export declare function bindKeiyaku(input: BindInput, createHandle: typeof createKeiyakuHandle, execution?: ExecutionContext, composition?: LocalContractCompositionCapture): Promise<BindOutcome>;
@@ -7,7 +7,7 @@ import { withGitDecodeChannel } from "../git/read-observation.js";
7
7
  import { executionStop, isOperationalFailure, isOperationalStop } from "../protocol/progress.js";
8
8
  import { readManagedWorktreeAppointment } from "../workspace-place.js";
9
9
  import { admitForkBindWithAppointment, prepareMarkdownBind } from "./bind.js";
10
- import { acceptedOutcome, conclusions, expected, retainAdmission } from "./contract-outcomes.js";
10
+ import { acceptedOutcome, expected, retainAdmission } from "./contract-outcomes.js";
11
11
  import { captureLocalContractComposition, derivedGates, derivedHooks, gateNames, } from "./contract-settings.js";
12
12
  import { actorOption, normalizedList, requireInput, requireMarkdown, taskOption } from "./input.js";
13
13
  import { InvocationAccumulator } from "./invocation.js";
@@ -15,6 +15,12 @@ import { project, validated } from "./outcome.js";
15
15
  import { reconcileAffectedContracts } from "./reconcile.js";
16
16
  import { observeRegion } from "./region.js";
17
17
  import { scopeForRepo } from "./repo.js";
18
+ /** The one place a caller's omitted target becomes product behavior. */
19
+ function bindTargetSelection(target) {
20
+ if (target === undefined)
21
+ return { kind: "current-branch" };
22
+ return target === null ? { kind: "targetless" } : { kind: "explicit", target };
23
+ }
18
24
  function bindInput(input, composition) {
19
25
  return validated(() => {
20
26
  const values = requireInput(input, "Keiyaku.bind input");
@@ -25,8 +31,8 @@ function bindInput(input, composition) {
25
31
  requireInput(input, "Keiyaku.bind input", allowed);
26
32
  if ((values.workspace ?? "worktree") !== "worktree")
27
33
  throw new TypeError("workspace must be worktree");
28
- if (values.target !== undefined && typeof values.target !== "string")
29
- throw new TypeError("target must be a string");
34
+ if (values.target !== undefined && values.target !== null && typeof values.target !== "string")
35
+ throw new TypeError("target must be a string or null");
30
36
  const actor = actorOption(values.actor);
31
37
  const document = forkOf === undefined ? parseMarkdown(requireMarkdown(values.markdown)) : undefined;
32
38
  if (forkOf !== undefined) {
@@ -47,11 +53,10 @@ function bindInput(input, composition) {
47
53
  });
48
54
  }
49
55
  /**
50
- * One Contract bind. `omittedMarkdownTarget` is the internal composition input an edge
51
- * supplies for a Markdown bind whose caller omitted the target: the public package-root
52
- * composition leaves it targetless, while the CLI names the invocation branch.
56
+ * One Contract bind. An omitted Markdown target names the current branch of the caller's explicit
57
+ * Repo worktree coordinate, `null` is deliberately targetless, and a string is that literal target.
53
58
  */
54
- export async function bindKeiyaku(input, createHandle, execution = localExecutionContext(), composition = captureLocalContractComposition(), omittedMarkdownTarget = { kind: "targetless" }) {
59
+ export async function bindKeiyaku(input, createHandle, execution = localExecutionContext(), composition = captureLocalContractComposition()) {
55
60
  const prepared = bindInput(input, composition);
56
61
  const hooks = derivedHooks(composition);
57
62
  const { forkOf, scope, document, target, actor } = prepared;
@@ -84,7 +89,7 @@ export async function bindKeiyaku(input, createHandle, execution = localExecutio
84
89
  }
85
90
  if (document === undefined)
86
91
  throw new Error("Markdown bind requires its prepared document");
87
- return await markdownBind(prepared, document, hooks, scope, channel, accumulator, handle, omittedMarkdownTarget);
92
+ return await markdownBind(prepared, document, hooks, scope, channel, accumulator, handle);
88
93
  })();
89
94
  return completed;
90
95
  }, (error) => {
@@ -109,19 +114,16 @@ export async function bindKeiyaku(input, createHandle, execution = localExecutio
109
114
  throw projected.error;
110
115
  return projected.outcome;
111
116
  }
112
- function bindValue(keiyaku, region, warnings, workspace, appointmentLag) {
113
- const base = {
117
+ function bindValue(keiyaku, region, warnings) {
118
+ return {
114
119
  keiyaku,
115
- ...(workspace === undefined ? {} : { workspace }),
116
120
  ...(warnings.length === 0 ? {} : { warnings }),
117
121
  ...region,
118
122
  };
119
- void appointmentLag;
120
- return base;
121
123
  }
122
124
  // eslint-disable-next-line max-params -- Keep this local operation's custody, admission, and policy witnesses explicit.
123
125
  async function bindComplete(accumulator, id, scope, channel, leading, hooks, value) {
124
- retainAdmission(accumulator, id, leading, false);
126
+ retainAdmission(accumulator, id, leading);
125
127
  await reconcileAffectedContracts(accumulator, id, scope, channel, hooks);
126
128
  try {
127
129
  const appointment = await readManagedWorktreeAppointment(scope, id);
@@ -136,15 +138,15 @@ async function bindComplete(accumulator, id, scope, channel, leading, hooks, val
136
138
  accumulator.recordStop(executionStop(id, "reconciliation", error, scope.signal));
137
139
  }
138
140
  const built = { ...(await value()), ...accumulator.conclusions(id) };
139
- accumulator.extendConclusions(id, conclusions(built));
141
+ accumulator.extendConclusions(id, built);
140
142
  return built;
141
143
  }
142
144
  // eslint-disable-next-line max-params -- Keep this local operation's custody, admission, and policy witnesses explicit.
143
- async function markdownBind(prepared, document, hooks, scope, channel, accumulator, handle, omittedMarkdownTarget) {
145
+ async function markdownBind(prepared, document, hooks, scope, channel, accumulator, handle) {
144
146
  const { task, target, actor, gates, after } = prepared;
145
147
  if (gates === undefined || after === undefined)
146
148
  throw new Error("Markdown bind requires prepared terms");
147
- const targetSelection = target !== undefined ? { kind: "explicit", target } : omittedMarkdownTarget;
149
+ const targetSelection = bindTargetSelection(target);
148
150
  const admission = await prepareMarkdownBind({
149
151
  scope,
150
152
  channel,
@@ -19,7 +19,7 @@ import { admitReviewOperation } from "../protocol/review.js";
19
19
  import { releaseTaskHolder, releaseTaskHolderWithFence, taskHolderObservationSelection } from "../settlement/holder.js";
20
20
  import { continueDeliveredDependents } from "./continuation.js";
21
21
  import { requestForwardedContractLive } from "./contract-operations.js";
22
- import { acceptedOutcome, admissionOf, conclusions, expected, retainAdmission } from "./contract-outcomes.js";
22
+ import { acceptedOutcome, expected, retainAdmission } from "./contract-outcomes.js";
23
23
  import { derivedContractPolicy, derivedGates, derivedHooks, gateNames, } from "./contract-settings.js";
24
24
  import { deliveryForContract } from "./delivery.js";
25
25
  import { actorOption, contractTerms, documentDerivation, normalizedList, optionalBoolean, optionalNonblank, optionalSignal, requireInput, requireMarkdown, } from "./input.js";
@@ -66,7 +66,7 @@ export class ContractExecution {
66
66
  });
67
67
  let changedSections;
68
68
  return await this.local("amend", async (accumulator, channel, scope) => {
69
- const admission = admissionOf(await amendOperation({
69
+ const admission = await amendOperation({
70
70
  scope,
71
71
  channel,
72
72
  contractId: this.id,
@@ -87,20 +87,18 @@ export class ContractExecution {
87
87
  : contractTerms(amended, gates ?? source.gates, prerequisites ?? source.after);
88
88
  return { terms, verification: documentDerivation(amended, terms.gates, this.id).verification };
89
89
  },
90
- }));
90
+ });
91
91
  if (admission.kind !== "accepted")
92
92
  return expected(this.id, admission);
93
- const accepted = admission.accepted;
94
- const changes = changedAmendTerms(accepted.value.source, accepted.value.terms);
95
- const diff = documentDiff("before", "after", accepted.value.source.document.bytes, accepted.value.terms.document.bytes);
93
+ const changes = changedAmendTerms(admission.value.source, admission.value.terms);
94
+ const diff = documentDiff("before", "after", admission.value.source.document.bytes, admission.value.terms.document.bytes);
96
95
  accumulator.extendConclusions(this.id, { documentDiff: diff, changes });
97
- const region = await observeChangedRegion(scope, this.id, changedSections, decodeContractDocument(accepted.value.terms.document.bytes).region);
96
+ const region = await observeChangedRegion(scope, this.id, changedSections, decodeContractDocument(admission.value.terms.document.bytes).region);
98
97
  const value = await this.conclude(accumulator, {
99
98
  scope,
100
99
  channel,
101
- leading: accepted,
100
+ leading: admission,
102
101
  hooks,
103
- verificationResidueRecorded: false,
104
102
  value: () => ({
105
103
  documentDiff: diff,
106
104
  changes,
@@ -247,7 +245,7 @@ export class ContractExecution {
247
245
  });
248
246
  const hooks = derivedHooks(this.composition);
249
247
  return await this.local("abandon", async (accumulator, channel, scope) => {
250
- const admission = admissionOf((await releaseTaskHolderWithFence(scope, channel, this.id, () => abandonOperation({
248
+ const admission = (await releaseTaskHolderWithFence(scope, channel, this.id, () => abandonOperation({
251
249
  scope,
252
250
  channel,
253
251
  contractId: this.id,
@@ -259,15 +257,14 @@ export class ContractExecution {
259
257
  const companion = await releaseTaskHolder(channel, observation, owner);
260
258
  return companion === null ? [] : [companion];
261
259
  },
262
- }))).result);
260
+ }))).result;
263
261
  if (admission.kind !== "accepted")
264
262
  return expected(this.id, admission);
265
263
  await this.conclude(accumulator, {
266
264
  scope,
267
265
  channel,
268
- leading: admission.accepted,
266
+ leading: admission,
269
267
  hooks,
270
- verificationResidueRecorded: false,
271
268
  value: () => ({}),
272
269
  });
273
270
  return acceptedOutcome("abandon", this.id, accumulator, undefined);
@@ -283,22 +280,21 @@ export class ContractExecution {
283
280
  });
284
281
  const hooks = derivedHooks(this.composition);
285
282
  return await this.local("arc", async (accumulator, channel, scope) => {
286
- const admission = admissionOf(await arcOperation({
283
+ const admission = await arcOperation({
287
284
  scope,
288
285
  channel,
289
286
  contractId: this.id,
290
287
  ...actor,
291
288
  chapter,
292
289
  progress: accumulator,
293
- }));
290
+ });
294
291
  if (admission.kind !== "accepted")
295
292
  return expected(this.id, admission);
296
293
  await this.conclude(accumulator, {
297
294
  scope,
298
295
  channel,
299
- leading: admission.accepted,
296
+ leading: admission,
300
297
  hooks,
301
- verificationResidueRecorded: false,
302
298
  value: () => ({}),
303
299
  });
304
300
  return acceptedOutcome("arc", this.id, accumulator, undefined);
@@ -327,7 +323,7 @@ export class ContractExecution {
327
323
  });
328
324
  const { hooks, requireBranchesToBeUpToDate } = derivedContractPolicy(this.composition);
329
325
  return await this.local("audit", async (accumulator, localChannel, scope) => {
330
- const admission = admissionOf(await auditOperation({
326
+ const admission = await auditOperation({
331
327
  scope,
332
328
  channel: localChannel,
333
329
  progress: accumulator,
@@ -338,15 +334,14 @@ export class ContractExecution {
338
334
  requireBranchesToBeUpToDate,
339
335
  ...(signal === undefined ? {} : { signal }),
340
336
  ...(this.composition.actor === undefined ? {} : { actor: this.composition.actor }),
341
- }));
337
+ });
342
338
  if (admission.kind !== "accepted")
343
339
  return expected(this.id, admission);
344
340
  const report = await this.conclude(accumulator, {
345
341
  scope,
346
342
  channel: localChannel,
347
- leading: admission.accepted,
343
+ leading: admission,
348
344
  hooks,
349
- verificationResidueRecorded: false,
350
345
  value: (value) => value,
351
346
  });
352
347
  return acceptedOutcome("audit", this.id, accumulator, report);
@@ -380,9 +375,9 @@ export class ContractExecution {
380
375
  return projected.outcome;
381
376
  }
382
377
  async conclude(accumulator, input) {
383
- retainAdmission(accumulator, this.id, input.leading, input.verificationResidueRecorded);
378
+ retainAdmission(accumulator, this.id, input.leading);
384
379
  const value = input.value(input.leading.value);
385
- accumulator.extendConclusions(this.id, conclusions(value));
380
+ accumulator.extendConclusions(this.id, value);
386
381
  await reconcileAffectedContracts(accumulator, this.id, input.scope, input.channel, input.hooks);
387
382
  return value;
388
383
  }
@@ -41,17 +41,6 @@ export type BindResult = BindOutcome;
41
41
  type AcceptedIntent<Value> = Extract<IntentOutcome<Value>, {
42
42
  kind: "accepted";
43
43
  }>;
44
- type Admission<Value, Refusal> = Readonly<{
45
- kind: "accepted";
46
- accepted: AcceptedIntent<Value>;
47
- }> | Readonly<{
48
- kind: "refused";
49
- refusal: Refusal;
50
- }> | Readonly<{
51
- kind: "retry";
52
- reason: IntentRetry;
53
- }>;
54
- export declare function admissionOf<Value, Refusal>(outcome: IntentOutcome<Value, Refusal>): Admission<Value, Refusal>;
55
44
  /** The refused/retry arms are value-agnostic, so every operation can return them unchanged. */
56
45
  type ExpectedProjection<Refusal> = Readonly<{
57
46
  kind: "refused";
@@ -62,10 +51,9 @@ type ExpectedProjection<Refusal> = Readonly<{
62
51
  contract?: ContractId;
63
52
  reason: IntentRetry;
64
53
  }>;
65
- export declare function expected<Refusal>(contract: ContractId | undefined, admission: Exclude<Admission<unknown, Refusal>, {
54
+ export declare function expected<Refusal>(contract: ContractId | undefined, admission: Exclude<IntentOutcome<unknown, Refusal>, {
66
55
  kind: "accepted";
67
56
  }>): ExpectedProjection<Refusal>;
68
57
  export declare function acceptedOutcome<Operation extends ContractVerb, Value>(operation: Operation, contract: ContractId, accumulator: InvocationAccumulator, value: Value): OutcomeProjection<Operation, Value, never>;
69
- export declare function conclusions(value: object): Readonly<Record<string, unknown>>;
70
- export declare function retainAdmission<Value>(accumulator: InvocationAccumulator, contract: ContractId, leading: AcceptedIntent<Value>, verificationResidueRecorded: boolean): void;
58
+ export declare function retainAdmission<Value>(accumulator: InvocationAccumulator, contract: ContractId, leading: AcceptedIntent<Value>): void;
71
59
  export {};
@@ -1,10 +1,3 @@
1
- export function admissionOf(outcome) {
2
- if (outcome.kind === "accepted")
3
- return { kind: "accepted", accepted: outcome };
4
- return outcome.kind === "refused"
5
- ? { kind: "refused", refusal: outcome.refusal }
6
- : { kind: "retry", reason: outcome.reason };
7
- }
8
1
  export function expected(contract, admission) {
9
2
  return admission.kind === "refused"
10
3
  ? {
@@ -21,12 +14,8 @@ export function acceptedOutcome(operation, contract, accumulator, value) {
21
14
  throw new Error("missing leading admission receipt");
22
15
  return { kind: "accepted", contract, head, value };
23
16
  }
24
- export function conclusions(value) {
25
- return value;
26
- }
27
- export function retainAdmission(accumulator, contract, leading, verificationResidueRecorded) {
17
+ export function retainAdmission(accumulator, contract, leading) {
28
18
  accumulator.recordPublication(contract, leading.head, leading.facts);
29
19
  accumulator.recordResidue(contract, leading);
30
- if (!verificationResidueRecorded)
31
- accumulator.recordVerification(contract, undefined, leading);
20
+ accumulator.recordVerification(contract, undefined, leading);
32
21
  }
@@ -26,7 +26,8 @@ type MarkdownBindInput = Readonly<{
26
26
  repo: Repo;
27
27
  markdown: string;
28
28
  task?: TaskId;
29
- target?: string;
29
+ /** A literal target branch; `null` is deliberately targetless; omitted is the Repo worktree's current branch. */
30
+ target?: string | null;
30
31
  workspace?: "worktree";
31
32
  actor?: string;
32
33
  after?: readonly ContractId[];
@@ -35,7 +36,8 @@ type MarkdownBindInput = Readonly<{
35
36
  type ForkBindInput = Readonly<{
36
37
  repo: Repo;
37
38
  forkOf: ContractId;
38
- target?: string;
39
+ /** A literal target branch; `null` clears the source target; omitted inherits it. */
40
+ target?: string | null;
39
41
  workspace?: "worktree";
40
42
  actor?: string;
41
43
  }>;
@@ -72,6 +74,38 @@ export type KeiyakuSelectInput = Readonly<{
72
74
  repo: Repo;
73
75
  id: ContractId;
74
76
  }>;
77
+ export type ContractResolveInput = Readonly<{
78
+ repo: Repo;
79
+ selector?: string;
80
+ cwd?: string;
81
+ }>;
82
+ export type ContractSelectorRefusal = Readonly<{
83
+ kind: "invalid-selector";
84
+ selector: string;
85
+ diagnostic: string;
86
+ }> | Readonly<{
87
+ kind: "redundant-short-selector";
88
+ selector: string;
89
+ }> | Readonly<{
90
+ kind: "unknown-short-selector";
91
+ selector: string;
92
+ }> | Readonly<{
93
+ kind: "ambiguous-selector";
94
+ selector: string;
95
+ }> | Readonly<{
96
+ kind: "ambiguous-selector";
97
+ cwd: string;
98
+ }> | Readonly<{
99
+ kind: "no-contextual-match";
100
+ cwd: string;
101
+ }>;
102
+ export type ContractResolution = Readonly<{
103
+ kind: "resolved";
104
+ id: ContractId;
105
+ }> | Readonly<{
106
+ kind: "refused";
107
+ refusal: ContractSelectorRefusal;
108
+ }>;
75
109
  export type ReviewInput = ActorOptions & Readonly<{
76
110
  verdict: AttestationData["verdict"];
77
111
  summary?: string;
@@ -544,8 +544,6 @@ type HandleType<T extends object> = Readonly<{
544
544
  [Symbol.hasInstance](value: unknown): boolean;
545
545
  }>;
546
546
  export declare const Delivery: HandleType<DeliveryHandle>;
547
- export declare function deliveryHandle(delivery: DeliveryValue, readDiff: () => Promise<string | null>): Delivery & DeliveryValue;
548
- export declare function deliveryHandle(delivery: Pick<DeliveryValue, "tenderSnapshot" | "integration" | "method" | "policy"> & Partial<DeliveryValue>, readDiff: () => Promise<string | null>): Delivery;
549
547
  export declare function deliveryForContract(scope: RepositoryScope, delivery: DeliveryValue): Delivery & DeliveryValue;
550
548
  export declare function deliveryForContract(scope: RepositoryScope, delivery: Pick<DeliveryValue, "tenderSnapshot" | "integration" | "method" | "policy">): Delivery;
551
549
  export {};
@@ -30,13 +30,10 @@ export const Delivery = Object.freeze({
30
30
  prototype: DeliveryHandle.prototype,
31
31
  [Symbol.hasInstance]: (value) => value instanceof DeliveryHandle,
32
32
  });
33
- export function deliveryHandle(delivery, readDiff) {
34
- return new DeliveryHandle(delivery, readDiff, delivery);
35
- }
36
33
  export function deliveryForContract(scope, delivery) {
37
- return deliveryHandle(delivery, () => deliveryDiffOperation({
34
+ return new DeliveryHandle(delivery, () => deliveryDiffOperation({
38
35
  scope,
39
36
  integrationPredecessor: delivery.integration.predecessor,
40
37
  integrationSnapshot: delivery.integration.snapshot,
41
- }));
38
+ }), delivery);
42
39
  }
@@ -32,11 +32,6 @@ export declare class Keiyaku {
32
32
  abandon(input?: AbandonInput): Promise<AbandonOutcome>;
33
33
  arc(input: ArcInput): Promise<ArcOutcome>;
34
34
  audit(input?: AuditInput, options?: MutationObservation): Promise<AuditOutcome>;
35
- /**
36
- * Reads answer with a value or `null` for legitimate absence. Corrupt authority stays exceptional
37
- * and keeps its original native cause instead of being disguised as a raw native exception.
38
- */
39
- private read;
40
35
  }
41
36
  /** Internal constructor capability; callers select a Contract through Keiyaku.with. */
42
37
  export declare function createKeiyakuHandle(id: ContractId, scope: RepositoryScope, execution: ExecutionContext, composition: LocalContractCompositionCapture): Keiyaku;
@@ -7,7 +7,8 @@ import { observeContractsForAdmissionInObservationAt } from "../git/observe.js";
7
7
  import { withGitDecodeChannel, withGitReadObservation } from "../git/read-observation.js";
8
8
  import { contractObservationOperation, deliveryOperation, stateOperation, } from "../protocol/operations.js";
9
9
  import { readManagedWorktreeAppointment } from "../workspace-place.js";
10
- import { composeContractLibrary, readContractValue } from "./contract-composition.js";
10
+ import { composeContractLibrary } from "./contract-composition.js";
11
+ import { readContractValue } from "./outcome.js";
11
12
  import { ContractExecution } from "./contract-execution.js";
12
13
  import { deliveryForContract } from "./delivery.js";
13
14
  const KEIYAKU_HANDLE = Symbol("Keiyaku handle");
@@ -41,10 +42,10 @@ export class Keiyaku {
41
42
  return { contract: this.id };
42
43
  }
43
44
  async state() {
44
- return await this.read(() => withGitDecodeChannel(this.scope, (channel) => stateOperation({ scope: this.scope, channel, contractId: this.id })));
45
+ return await readContractValue(() => withGitDecodeChannel(this.scope, (channel) => stateOperation({ scope: this.scope, channel, contractId: this.id })));
45
46
  }
46
47
  async history() {
47
- return await this.read(() => withGitDecodeChannel(this.scope, (channel) => withGitReadObservation(this.scope, channel, async (observation) => {
48
+ return await readContractValue(() => withGitDecodeChannel(this.scope, (channel) => withGitReadObservation(this.scope, channel, async (observation) => {
48
49
  const [journals, dispatches] = await Promise.all([
49
50
  observeContractsForAdmissionInObservationAt(observation, [this.id]),
50
51
  readDispatchesAt(observation),
@@ -84,7 +85,7 @@ export class Keiyaku {
84
85
  })));
85
86
  }
86
87
  async guidance() {
87
- return await this.read(() => withGitDecodeChannel(this.scope, async (channel) => {
88
+ return await readContractValue(() => withGitDecodeChannel(this.scope, async (channel) => {
88
89
  const observed = await contractObservationOperation({ scope: this.scope, channel, contractId: this.id });
89
90
  if (observed.kind === "missing")
90
91
  return null;
@@ -93,7 +94,7 @@ export class Keiyaku {
93
94
  }));
94
95
  }
95
96
  async delivery() {
96
- const delivery = await this.read(() => withGitDecodeChannel(this.scope, (channel) => deliveryOperation({ scope: this.scope, channel, contractId: this.id })));
97
+ const delivery = await readContractValue(() => withGitDecodeChannel(this.scope, (channel) => deliveryOperation({ scope: this.scope, channel, contractId: this.id })));
97
98
  return delivery === null ? null : deliveryForContract(this.scope, delivery);
98
99
  }
99
100
  async amend(input) {
@@ -114,13 +115,6 @@ export class Keiyaku {
114
115
  async audit(input, options) {
115
116
  return await this.operations.audit(input, options);
116
117
  }
117
- /**
118
- * Reads answer with a value or `null` for legitimate absence. Corrupt authority stays exceptional
119
- * and keeps its original native cause instead of being disguised as a raw native exception.
120
- */
121
- async read(operation) {
122
- return await readContractValue(operation);
123
- }
124
118
  }
125
119
  /** Internal constructor capability; callers select a Contract through Keiyaku.with. */
126
120
  export function createKeiyakuHandle(id, scope, execution, composition) {