@astrosheep/keiyaku 1.0.0 → 1.0.2

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 (123) hide show
  1. package/README.md +73 -56
  2. package/build/.tsbuildinfo +1 -1
  3. package/build/agents/call-terms_v2.js +103 -0
  4. package/build/agents/harness/activity-values.js +54 -0
  5. package/build/agents/harness/event-channel.js +55 -20
  6. package/build/agents/harness/events.js +47 -1
  7. package/build/agents/harness/execution-handle.js +292 -61
  8. package/build/agents/harness/index.js +103 -121
  9. package/build/agents/harness/pump.js +36 -47
  10. package/build/agents/harness/runtime.js +3 -0
  11. package/build/agents/launch-snapshot_v2.js +348 -0
  12. package/build/agents/opencode-sdk.js +42 -169
  13. package/build/agents/providers/claude-agent-sdk.js +240 -79
  14. package/build/agents/providers/codex-app-server.js +280 -72
  15. package/build/agents/providers/codex-sdk.js +159 -41
  16. package/build/agents/providers/event-type-tail.js +16 -0
  17. package/build/agents/providers/opencode-sdk.js +165 -59
  18. package/build/agents/providers/pi.js +254 -42
  19. package/build/agents/selector_v2.js +122 -0
  20. package/build/cli/commands/akuma.js +120 -42
  21. package/build/cli/completion.js +6 -7
  22. package/build/cli/flags.js +36 -10
  23. package/build/cli/help.js +42 -26
  24. package/build/cli/index.js +225 -93
  25. package/build/cli/parse.js +194 -75
  26. package/build/cli/projection-address.js +11 -0
  27. package/build/cli/render/address.js +88 -0
  28. package/build/cli/render/arc.js +10 -10
  29. package/build/cli/render/call.js +59 -0
  30. package/build/cli/render/compact-text.js +3 -0
  31. package/build/cli/render/errors.js +4 -2
  32. package/build/cli/render/format.js +6 -0
  33. package/build/cli/render/line-width.js +70 -0
  34. package/build/cli/render/misc.js +7 -4
  35. package/build/cli/render/petition.js +4 -3
  36. package/build/cli/render/projection-activity.js +201 -0
  37. package/build/cli/render/shared.js +46 -12
  38. package/build/cli/render/status.js +59 -10
  39. package/build/cli/render/tool-ledger-rollup.js +74 -0
  40. package/build/cli/render/tool-presentation.js +97 -0
  41. package/build/cli/render/wait.js +229 -0
  42. package/build/cli/skills-install.js +42 -24
  43. package/build/cli/subagent-guard.js +1 -1
  44. package/build/config/akuma-loader_v2.js +222 -0
  45. package/build/config/env-keys.js +0 -4
  46. package/build/config/env.js +0 -6
  47. package/build/config/settings.js +325 -12
  48. package/build/core/addressing.js +224 -0
  49. package/build/core/amend.js +30 -47
  50. package/build/core/arc.js +68 -60
  51. package/build/core/bind.js +105 -25
  52. package/build/core/call-persist.js +69 -0
  53. package/build/core/call.js +658 -0
  54. package/build/core/claim.js +72 -44
  55. package/build/core/command-io.js +19 -19
  56. package/build/core/context.js +11 -36
  57. package/build/core/draft.js +2 -3
  58. package/build/core/entry.js +101 -6
  59. package/build/core/execution-coordinate.js +62 -0
  60. package/build/core/execution-pact.js +141 -0
  61. package/build/core/forfeit.js +2 -3
  62. package/build/core/hints.js +10 -10
  63. package/build/core/ids.js +6 -0
  64. package/build/core/ledger.js +16 -1
  65. package/build/core/petition-claim-gates.js +14 -12
  66. package/build/core/petition-claim.js +1 -0
  67. package/build/core/petition-run.js +6 -2
  68. package/build/core/petition.js +63 -21
  69. package/build/core/places.js +106 -13
  70. package/build/core/projection/generation.js +412 -0
  71. package/build/core/projection/heart.js +316 -0
  72. package/build/core/projection/identity.js +81 -0
  73. package/build/core/projection/leash.js +87 -0
  74. package/build/core/projection/mint.js +154 -0
  75. package/build/core/projection-activity.js +219 -0
  76. package/build/core/projection-coordinate.js +35 -0
  77. package/build/core/projection-core.js +69 -463
  78. package/build/core/projection-generation-continuation.js +31 -0
  79. package/build/core/projection-generation-execution.js +148 -0
  80. package/build/core/projection-generation-identity.js +17 -0
  81. package/build/core/projection-generation-launcher.js +90 -0
  82. package/build/core/projection-generation-process.js +43 -0
  83. package/build/core/projection-generation-runner.js +144 -0
  84. package/build/core/projection-generation-runtime.js +15 -0
  85. package/build/core/projection-generation-store.js +707 -0
  86. package/build/core/projection-identity.js +11 -0
  87. package/build/core/projection-life-observer.js +87 -0
  88. package/build/core/projection-life-protocol.js +95 -0
  89. package/build/core/projection-mint.js +96 -24
  90. package/build/core/projection-runner-lock.js +230 -0
  91. package/build/core/projection-status.js +207 -107
  92. package/build/core/projection-tells.js +401 -0
  93. package/build/core/projection-wait.js +155 -0
  94. package/build/core/projection-wake.js +109 -231
  95. package/build/core/queue_v2.js +342 -0
  96. package/build/core/registry.js +6 -3
  97. package/build/core/render.js +63 -1
  98. package/build/core/renew.js +80 -53
  99. package/build/core/scope.js +186 -137
  100. package/build/core/seal.js +16 -19
  101. package/build/core/status.js +88 -25
  102. package/build/core/stored-agent-event.js +101 -0
  103. package/build/core/transcripts.js +214 -228
  104. package/build/core/verdict.js +27 -15
  105. package/build/core/worktree-bootstrap.js +187 -0
  106. package/build/core/worktree-path.js +72 -18
  107. package/build/flow-error.js +4 -6
  108. package/build/generated/version.js +1 -1
  109. package/build/git/branches.js +6 -1
  110. package/build/index.js +8 -5
  111. package/build/keiyaku.js +1 -3
  112. package/package.json +6 -5
  113. package/skills/keiyaku/SKILL.md +6 -47
  114. package/skills/keiyaku-akuma/SKILL.md +75 -0
  115. package/build/agents/effective-policy.js +0 -32
  116. package/build/agents/index.js +0 -114
  117. package/build/agents/selector.js +0 -28
  118. package/build/cli/render/summon.js +0 -17
  119. package/build/cli/render/tell.js +0 -11
  120. package/build/config/akuma-loader.js +0 -268
  121. package/build/core/queue.js +0 -73
  122. package/build/core/summon-persist.js +0 -73
  123. package/build/core/summon.js +0 -377
@@ -0,0 +1,219 @@
1
+ export const AGENT_ACTIVITY_WINDOW_SIZE = 10;
2
+ function eventTime(value) {
3
+ const parsed = Date.parse(value);
4
+ return Number.isFinite(parsed) ? parsed : undefined;
5
+ }
6
+ function duration(first, last) {
7
+ if (first === undefined || last === undefined)
8
+ return undefined;
9
+ return Math.max(0, last - first);
10
+ }
11
+ function warningIdentity(warning) {
12
+ return JSON.stringify({
13
+ reason: warning.reason,
14
+ originalModel: warning.originalModel,
15
+ fallbackModel: warning.fallbackModel,
16
+ direction: warning.direction,
17
+ signerModel: warning.signerModel,
18
+ });
19
+ }
20
+ function sortEvents(events) {
21
+ return events
22
+ .map((event, index) => ({
23
+ event,
24
+ order: Number.isFinite(event.seq) ? event.seq : index,
25
+ sourceIndex: index,
26
+ }))
27
+ .sort((left, right) => left.order - right.order || left.sourceIndex - right.sourceIndex)
28
+ .map(({ event, order }) => ({ event, order }));
29
+ }
30
+ /** Fold the provider-neutral event ledger once into the bounded UI activity model. */
31
+ export function foldAgentActivity(events) {
32
+ const sorted = sortEvents(events);
33
+ const latestActivity = new Map();
34
+ const firstActivityCall = new Map();
35
+ const activityObservations = new Map();
36
+ const firstActivityAt = new Map();
37
+ const latestThought = new Map();
38
+ const firstThoughtAt = new Map();
39
+ const thoughtEventCount = new Map();
40
+ const warnings = new Map();
41
+ const usageByTurn = new Map();
42
+ const turns = [];
43
+ let latestPlan;
44
+ let diagnostic;
45
+ let failure;
46
+ for (const indexed of sorted) {
47
+ const event = indexed.event;
48
+ switch (event.type) {
49
+ case "activity": {
50
+ latestActivity.set(event.id, indexed);
51
+ if (event.phase !== "updated" && !firstActivityCall.has(event.id))
52
+ firstActivityCall.set(event.id, event.call);
53
+ const observations = activityObservations.get(event.id) ?? [];
54
+ observations.push({
55
+ order: indexed.order,
56
+ at: event.at,
57
+ phase: event.phase,
58
+ ...(event.result === undefined ? {} : { result: event.result }),
59
+ });
60
+ activityObservations.set(event.id, observations);
61
+ const at = eventTime(event.at);
62
+ if (at !== undefined && !firstActivityAt.has(event.id))
63
+ firstActivityAt.set(event.id, at);
64
+ break;
65
+ }
66
+ case "thought": {
67
+ latestThought.set(event.id, indexed);
68
+ thoughtEventCount.set(event.id, (thoughtEventCount.get(event.id) ?? 0) + 1);
69
+ const at = eventTime(event.at);
70
+ if (at !== undefined && !firstThoughtAt.has(event.id))
71
+ firstThoughtAt.set(event.id, at);
72
+ break;
73
+ }
74
+ case "warning": {
75
+ const identity = warningIdentity(event.warning);
76
+ const prior = warnings.get(identity);
77
+ warnings.set(identity, { latest: indexed, count: (prior?.count ?? 0) + 1 });
78
+ break;
79
+ }
80
+ case "usage":
81
+ usageByTurn.set(event.turn, event);
82
+ break;
83
+ case "plan":
84
+ latestPlan = indexed;
85
+ break;
86
+ case "diagnostic":
87
+ diagnostic = { at: event.at, text: event.text };
88
+ break;
89
+ case "fail":
90
+ failure = { at: event.at, message: event.message };
91
+ break;
92
+ }
93
+ }
94
+ const settled = [];
95
+ const pinned = [];
96
+ const ledgerActivities = [];
97
+ for (const indexed of sorted) {
98
+ const event = indexed.event;
99
+ if (event.type === "message") {
100
+ settled.push({ kind: "said", order: indexed.order, at: event.at, turn: event.turn, text: event.text, settled: true });
101
+ continue;
102
+ }
103
+ if (event.type === "activity" && latestActivity.get(event.id) === indexed) {
104
+ const startedAtMs = firstActivityAt.get(event.id);
105
+ const observations = activityObservations.get(event.id) ?? [];
106
+ const call = firstActivityCall.get(event.id) ?? event.call;
107
+ const elapsed = observations.some((observation) => observation.phase === "started")
108
+ && observations.some((observation) => observation.phase === "completed")
109
+ ? duration(startedAtMs, eventTime(event.at))
110
+ : undefined;
111
+ const row = {
112
+ kind: "ran",
113
+ order: indexed.order,
114
+ at: event.at,
115
+ turn: event.turn,
116
+ id: event.id,
117
+ tool: event.tool,
118
+ call,
119
+ ...(event.result === undefined ? {} : { result: event.result }),
120
+ truncated: event.truncated === true,
121
+ observations,
122
+ state: event.phase === "completed" ? "completed" : "running",
123
+ ...(startedAtMs !== undefined ? { startedAtMs } : {}),
124
+ ...(elapsed !== undefined ? { durationMs: elapsed } : {}),
125
+ settled: event.phase === "completed",
126
+ };
127
+ ledgerActivities.push(row);
128
+ (row.settled ? settled : pinned).push(row);
129
+ continue;
130
+ }
131
+ if (event.type === "thought" && latestThought.get(event.id) === indexed) {
132
+ const startedAtMs = firstThoughtAt.get(event.id);
133
+ const elapsed = thoughtEventCount.get(event.id) >= 2
134
+ ? duration(startedAtMs, eventTime(event.at))
135
+ : undefined;
136
+ const row = {
137
+ kind: "thought",
138
+ order: indexed.order,
139
+ at: event.at,
140
+ turn: event.turn,
141
+ id: event.id,
142
+ text: event.text,
143
+ final: event.final,
144
+ truncated: event.truncated === true,
145
+ ...(startedAtMs !== undefined ? { startedAtMs } : {}),
146
+ ...(elapsed !== undefined ? { durationMs: elapsed } : {}),
147
+ settled: event.final,
148
+ };
149
+ (row.settled ? settled : pinned).push(row);
150
+ continue;
151
+ }
152
+ if (event.type === "warning") {
153
+ const aggregate = warnings.get(warningIdentity(event.warning));
154
+ if (aggregate?.latest !== indexed)
155
+ continue;
156
+ settled.push({
157
+ kind: "warning",
158
+ order: indexed.order,
159
+ at: event.at,
160
+ turn: event.turn,
161
+ warning: event.warning,
162
+ count: aggregate.count,
163
+ settled: true,
164
+ });
165
+ continue;
166
+ }
167
+ if (event.type === "turn" && event.phase === "completed") {
168
+ const usage = usageByTurn.get(event.turn);
169
+ turns.push({
170
+ kind: "turn",
171
+ order: indexed.order,
172
+ at: event.at,
173
+ turn: event.turn,
174
+ ...(usage
175
+ ? {
176
+ inputTokens: usage.inputTokens,
177
+ outputTokens: usage.outputTokens,
178
+ ...(usage.cachedInputTokens !== undefined ? { cachedInputTokens: usage.cachedInputTokens } : {}),
179
+ ...(usage.costUsd !== undefined ? { costUsd: usage.costUsd } : {}),
180
+ ...(usage.model !== undefined ? { model: usage.model } : {}),
181
+ }
182
+ : {}),
183
+ settled: true,
184
+ });
185
+ }
186
+ }
187
+ settled.sort((left, right) => left.order - right.order);
188
+ pinned.sort((left, right) => left.order - right.order);
189
+ const window = settled.slice(-AGENT_ACTIVITY_WINDOW_SIZE);
190
+ const visibleOrders = [...window, ...pinned].map((row) => row.order);
191
+ const relevantTurns = visibleOrders.length === 0
192
+ ? turns.slice(-1)
193
+ : turns.filter((row) => row.order >= Math.min(...visibleOrders));
194
+ const timeline = [...window, ...relevantTurns, ...pinned].sort((left, right) => left.order - right.order);
195
+ let plan;
196
+ if (latestPlan?.event.type === "plan") {
197
+ const event = latestPlan.event;
198
+ const active = event.items.find((item) => item.active === true) ?? event.items.find((item) => !item.done);
199
+ plan = {
200
+ order: latestPlan.order,
201
+ at: event.at,
202
+ turn: event.turn,
203
+ id: event.id,
204
+ done: event.items.filter((item) => item.done).length,
205
+ total: event.items.length,
206
+ ...(active ? { activeItem: active.text } : {}),
207
+ };
208
+ }
209
+ return {
210
+ window,
211
+ pinned,
212
+ timeline,
213
+ ledgerActivities,
214
+ ledgerTurns: turns,
215
+ ...(plan ? { plan } : {}),
216
+ ...(diagnostic ? { diagnostic } : {}),
217
+ ...(failure ? { failure } : {}),
218
+ };
219
+ }
@@ -0,0 +1,35 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import * as path from "node:path";
3
+ import { ProjectionStateError } from "./atomic-publish.js";
4
+ /**
5
+ * Select the filesystem authority for repository projection state.
6
+ *
7
+ * A non-bare repository uses the parent of its absolute common Git directory,
8
+ * so every linked worktree shares one coordinate. Repo-free callers retain the
9
+ * existing cwd-local authority until its replacement is legislated.
10
+ */
11
+ export function projectionCoordinateRoot(cwd) {
12
+ const result = spawnSync("git", ["rev-parse", "--is-bare-repository", "--path-format=absolute", "--git-common-dir"], {
13
+ cwd,
14
+ encoding: "utf8",
15
+ env: {
16
+ ...process.env,
17
+ GIT_TERMINAL_PROMPT: "0",
18
+ LC_ALL: "C",
19
+ },
20
+ stdio: ["ignore", "pipe", "pipe"],
21
+ });
22
+ if (result.error) {
23
+ throw new ProjectionStateError(`cannot resolve projection repository coordinate: ${result.error.message}`);
24
+ }
25
+ if (result.status !== 0) {
26
+ const detail = result.stderr.trim();
27
+ if (detail.includes("not a git repository"))
28
+ return cwd;
29
+ throw new ProjectionStateError(`cannot resolve projection repository coordinate${detail ? `: ${detail}` : ` (git exited ${String(result.status)})`}`);
30
+ }
31
+ const [bare, commonDir] = result.stdout.trim().split(/\r?\n/);
32
+ if (bare !== "false" || !commonDir || !path.isAbsolute(commonDir))
33
+ return cwd;
34
+ return path.dirname(commonDir);
35
+ }