@astrosheep/keiyaku 2.8.5 → 2.9.0
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.
- package/README.md +35 -15
- package/build/.tsbuildinfo +1 -1
- package/build/agents/{call-terms_v2.js → call-terms.js} +12 -8
- package/build/agents/harness/control-types.js +1 -0
- package/build/agents/harness/execution-handle.js +23 -3
- package/build/agents/harness/index.js +6 -607
- package/build/agents/harness/outcome.js +141 -0
- package/build/agents/harness/projection.js +310 -0
- package/build/agents/harness/router.js +201 -0
- package/build/agents/harness/runtime.js +2 -1
- package/build/agents/{launch-snapshot_v2.js → launch-snapshot/model.js} +69 -74
- package/build/agents/launch-snapshot/resolve.js +72 -0
- package/build/agents/opencode-sdk.js +24 -3
- package/build/agents/providers/{claude-agent-sdk.js → claude-agent-sdk/adapter.js} +46 -368
- package/build/agents/providers/claude-agent-sdk/events.js +218 -0
- package/build/agents/providers/claude-agent-sdk/session.js +158 -0
- package/build/agents/providers/codex-app-server/adapter.js +347 -0
- package/build/agents/providers/codex-app-server/events.js +352 -0
- package/build/agents/providers/codex-app-server/session.js +266 -0
- package/build/agents/providers/codex-sdk.js +23 -5
- package/build/agents/providers/opencode-sdk/adapter.js +344 -0
- package/build/agents/providers/opencode-sdk/events.js +354 -0
- package/build/agents/providers/opencode-sdk/session.js +180 -0
- package/build/agents/providers/pi/adapter.js +269 -0
- package/build/agents/providers/pi/checkpoint.js +41 -0
- package/build/agents/providers/pi/events.js +282 -0
- package/build/agents/{selector_v2.js → selector.js} +8 -6
- package/build/cli/commands/akuma/akuma/handler.js +4 -0
- package/build/cli/commands/akuma/akuma/meta.js +16 -0
- package/build/cli/commands/akuma/catalog.js +8 -0
- package/build/cli/commands/akuma/list/handler.js +15 -0
- package/build/cli/commands/akuma/list/meta-ls.js +9 -0
- package/build/cli/commands/akuma/view/handler.js +34 -0
- package/build/cli/commands/akuma/view/meta.js +8 -0
- package/build/cli/commands/akuma.js +1 -1
- package/build/cli/commands/contract/amend/handler.js +10 -0
- package/build/cli/commands/contract/amend/meta.js +12 -0
- package/build/cli/commands/contract/arc/handler.js +9 -0
- package/build/cli/commands/contract/arc/meta.js +26 -0
- package/build/cli/commands/contract/bind/handler.js +23 -0
- package/build/cli/commands/contract/bind/meta.js +30 -0
- package/build/cli/commands/contract/catalog.js +16 -0
- package/build/cli/commands/contract/forfeit/handler.js +13 -0
- package/build/cli/commands/contract/forfeit/meta.js +12 -0
- package/build/cli/commands/contract/log/handler.js +12 -0
- package/build/cli/commands/contract/log/meta.js +12 -0
- package/build/cli/commands/contract/petition/handler.js +26 -0
- package/build/cli/commands/contract/petition/meta.js +23 -0
- package/build/cli/commands/contract/renew/handler.js +10 -0
- package/build/cli/commands/contract/renew/meta.js +17 -0
- package/build/cli/commands/projection/call/handler.js +39 -0
- package/build/cli/commands/projection/call/meta.js +9 -0
- package/build/cli/commands/projection/catalog.js +14 -0
- package/build/cli/commands/projection/kill/handler.js +35 -0
- package/build/cli/commands/projection/kill/meta.js +11 -0
- package/build/cli/commands/projection/revive/handler.js +53 -0
- package/build/cli/commands/projection/revive/meta.js +9 -0
- package/build/cli/commands/projection/status/handler.js +23 -0
- package/build/cli/commands/projection/status/meta.js +9 -0
- package/build/cli/commands/projection/tell/handler.js +34 -0
- package/build/cli/commands/projection/tell/meta.js +9 -0
- package/build/cli/commands/projection/wait/handler.js +21 -0
- package/build/cli/commands/projection/wait/meta.js +11 -0
- package/build/cli/commands/registry.js +100 -0
- package/build/cli/commands/shared.js +71 -0
- package/build/cli/commands/skills/catalog.js +6 -0
- package/build/cli/commands/skills/install/handler.js +10 -0
- package/build/cli/commands/skills/install/meta.js +9 -0
- package/build/cli/commands/skills/skills/handler.js +4 -0
- package/build/cli/commands/skills/skills/meta.js +10 -0
- package/build/cli/commands/system/catalog.js +8 -0
- package/build/cli/commands/system/completion/handler.js +10 -0
- package/build/cli/commands/system/completion/meta.js +9 -0
- package/build/cli/commands/system/dump-env/handler.js +3 -0
- package/build/cli/commands/system/dump-env/meta.js +10 -0
- package/build/cli/commands/system/guide/handler.js +4 -0
- package/build/cli/commands/system/guide/meta.js +9 -0
- package/build/cli/commands/task/add/handler.js +21 -0
- package/build/cli/commands/task/add/meta.js +8 -0
- package/build/cli/commands/task/catalog.js +22 -0
- package/build/cli/commands/task/doctor/handler.js +4 -0
- package/build/cli/commands/task/doctor/meta.js +8 -0
- package/build/cli/commands/task/done/handler.js +17 -0
- package/build/cli/commands/task/done/meta.js +8 -0
- package/build/cli/commands/task/drop/handler.js +6 -0
- package/build/cli/commands/task/drop/meta.js +8 -0
- package/build/cli/commands/task/ls/handler.js +13 -0
- package/build/cli/commands/task/ls/meta.js +8 -0
- package/build/cli/commands/task/shared.js +131 -0
- package/build/cli/commands/task/start/handler.js +6 -0
- package/build/cli/commands/task/start/meta.js +8 -0
- package/build/cli/commands/task/stop/handler.js +17 -0
- package/build/cli/commands/task/stop/meta.js +8 -0
- package/build/cli/commands/task/task/handler.js +5 -0
- package/build/cli/commands/task/task/meta.js +11 -0
- package/build/cli/commands/task/update/handler.js +18 -0
- package/build/cli/commands/task/update/meta.js +8 -0
- package/build/cli/commands/task/view/handler.js +14 -0
- package/build/cli/commands/task/view/meta.js +8 -0
- package/build/cli/completion.js +26 -27
- package/build/cli/flags.js +79 -2
- package/build/cli/help.js +27 -49
- package/build/cli/index.js +121 -374
- package/build/cli/output-stream-error-policy.js +17 -0
- package/build/cli/parse.js +159 -72
- package/build/cli/projection-address.js +5 -0
- package/build/cli/render/arc.js +1 -1
- package/build/cli/render/errors.js +4 -3
- package/build/cli/render/format.js +14 -0
- package/build/cli/render/kanshi.js +106 -0
- package/build/cli/render/petition.js +24 -1
- package/build/cli/render/projection-activity.js +5 -1
- package/build/cli/render/shared.js +2 -2
- package/build/cli/render/status.js +79 -13
- package/build/cli/render/task.js +113 -0
- package/build/cli/render/wait.js +23 -3
- package/build/cli/types.js +1 -1
- package/build/config/{akuma-loader_v2.js → akuma-loader.js} +2 -2
- package/build/config/env.js +9 -4
- package/build/config/settings/disease.js +26 -0
- package/build/config/settings/knobs.js +8 -0
- package/build/config/settings/loader.js +244 -0
- package/build/config/settings/schema.js +276 -0
- package/build/core/addressing.js +1 -1
- package/build/core/amend.js +3 -3
- package/build/core/arc.js +5 -4
- package/build/core/bind-workspace.js +123 -0
- package/build/core/bind.js +75 -155
- package/build/core/call/call.js +224 -0
- package/build/core/call/context.js +238 -0
- package/build/core/call/execution.js +217 -0
- package/build/core/call/prompt.js +42 -0
- package/build/core/call/reference.js +24 -0
- package/build/core/call-persist.js +1 -1
- package/build/core/claim-delivery.js +247 -0
- package/build/core/claim.js +39 -277
- package/build/core/context.js +2 -1
- package/build/core/{render.js → contract-view.js} +12 -140
- package/build/core/draft.js +107 -9
- package/build/core/entry.js +9 -1
- package/build/core/execution-coordinate.js +4 -20
- package/build/core/execution-pact.js +16 -31
- package/build/core/forfeit.js +35 -22
- package/build/core/hints.js +2 -2
- package/build/core/log.js +2 -2
- package/build/core/petition-claim-gates.js +8 -6
- package/build/core/petition-preview.js +97 -0
- package/build/core/petition-run.js +3 -2
- package/build/core/petition.js +39 -26
- package/build/core/projection/generation/database.js +306 -0
- package/build/core/projection/generation/identity.js +84 -0
- package/build/core/projection/generation/model.js +201 -0
- package/build/core/projection/generation/store.js +73 -0
- package/build/core/projection/generation/transitions.js +258 -0
- package/build/core/projection/heart.js +0 -307
- package/build/core/projection/tell/database.js +109 -0
- package/build/core/projection/tell/model.js +97 -0
- package/build/core/{projection-tells.js → projection/tell/store.js} +3 -158
- package/build/core/projection-activity.js +23 -2
- package/build/core/projection-core.js +2 -1
- package/build/core/projection-execution-observer.js +259 -0
- package/build/core/projection-generation-continuation.js +1 -1
- package/build/core/projection-generation-execution.js +90 -20
- package/build/core/projection-generation-launcher.js +1 -1
- package/build/core/projection-generation-runner.js +198 -4
- package/build/core/projection-identity.js +1 -1
- package/build/core/projection-kill.js +50 -17
- package/build/core/projection-life-observer.js +1 -1
- package/build/core/projection-life-protocol.js +10 -0
- package/build/core/projection-mint.js +1 -1
- package/build/core/projection-status.js +45 -32
- package/build/core/projection-wait.js +12 -2
- package/build/core/projection-wake.js +5 -2
- package/build/core/{queue_v2.js → queue.js} +2 -1
- package/build/core/registry.js +1 -1
- package/build/core/renew.js +7 -7
- package/build/core/response-artifact-catalog-sqlite.js +112 -0
- package/build/core/response-artifact-catalog.js +7 -0
- package/build/core/seal.js +44 -16
- package/build/core/status/board.js +286 -0
- package/build/core/status/drift.js +99 -0
- package/build/core/status/lifecycle.js +84 -0
- package/build/core/status/reconciliation.js +131 -0
- package/build/core/stored-agent-event.js +28 -4
- package/build/core/target-ref.js +10 -0
- package/build/core/task/board.js +175 -0
- package/build/core/task/commands.js +211 -0
- package/build/core/task/document.js +189 -0
- package/build/core/task/model.js +1 -0
- package/build/core/task/settlement-git.js +207 -0
- package/build/core/task/settlement-policy.js +82 -0
- package/build/core/task/source-board.js +84 -0
- package/build/core/task/source-model.js +1 -0
- package/build/core/task/validation.js +44 -0
- package/build/core/task-contract.js +224 -0
- package/build/core/task-doctor.js +14 -0
- package/build/core/task-git-actor.js +38 -0
- package/build/core/task-git-runtime.js +34 -0
- package/build/core/task-git-store.js +375 -0
- package/build/core/task-repository.js +1 -0
- package/build/core/task-store-repository.js +86 -0
- package/build/core/task-store.js +1 -0
- package/build/core/task-worktree.js +51 -0
- package/build/core/task.js +4 -0
- package/build/core/transcripts.js +138 -56
- package/build/core/validation.js +17 -0
- package/build/core/verdict.js +2 -2
- package/build/core/worktree-path.js +24 -6
- package/build/flow-error.js +3 -2
- package/build/git/commits.js +3 -0
- package/build/git/diff/parsers.js +0 -94
- package/build/index.js +2 -0
- package/build/keiyaku-constants.js +2 -0
- package/build/keiyaku.js +4 -3
- package/package.json +3 -2
- package/skills/keiyaku/SKILL.md +1 -1
- package/skills/keiyaku-akuma/SKILL.md +11 -6
- package/build/agents/harness/pump.js +0 -158
- package/build/agents/providers/codex-app-server.js +0 -864
- package/build/agents/providers/opencode-sdk.js +0 -363
- package/build/agents/providers/pi.js +0 -557
- package/build/config/settings.js +0 -533
- package/build/core/call.js +0 -686
- package/build/core/projection/generation.js +0 -412
- package/build/core/projection/identity.js +0 -81
- package/build/core/projection/mint.js +0 -174
- package/build/core/projection-generation-store.js +0 -707
- package/build/core/status.js +0 -539
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { shortCommitHash } from "../git/commits.js";
|
|
2
|
+
import { deriveContractState } from "./status/lifecycle.js";
|
|
2
3
|
const VERB_COLUMN_WIDTH = 11;
|
|
3
4
|
const TIME_COLUMN_WIDTH = 6;
|
|
4
5
|
const ACTOR_COLUMN_WIDTH = 11;
|
|
5
|
-
export function shortCommitHash(hash) {
|
|
6
|
-
return hash.slice(0, 12);
|
|
7
|
-
}
|
|
8
6
|
function compactWhitespace(value) {
|
|
9
7
|
return value.replace(/\s+/g, " ").trim();
|
|
10
8
|
}
|
|
@@ -245,144 +243,18 @@ export function renderContractView(input) {
|
|
|
245
243
|
"scope:",
|
|
246
244
|
...bind.data.scope.map((pattern) => `- ${pattern}`),
|
|
247
245
|
"",
|
|
246
|
+
"checks:",
|
|
247
|
+
...bind.data.checks.map((check) => `- ${check}`),
|
|
248
|
+
"",
|
|
249
|
+
...(bind.data.extensions.length > 0
|
|
250
|
+
? [
|
|
251
|
+
...bind.data.extensions.flatMap((extension) => extension.content.length > 0
|
|
252
|
+
? [`## ${extension.title}`, extension.content, ""]
|
|
253
|
+
: [`## ${extension.title}`, ""]),
|
|
254
|
+
]
|
|
255
|
+
: []),
|
|
248
256
|
"log:",
|
|
249
257
|
renderVerticalLog(input),
|
|
250
258
|
"",
|
|
251
259
|
].join("\n");
|
|
252
260
|
}
|
|
253
|
-
function shortHead(hash) {
|
|
254
|
-
if (!hash)
|
|
255
|
-
return "????????";
|
|
256
|
-
return hash.slice(0, 7);
|
|
257
|
-
}
|
|
258
|
-
export function formatAgeMs(ms) {
|
|
259
|
-
if (ms === undefined)
|
|
260
|
-
return undefined;
|
|
261
|
-
const seconds = Math.max(0, Math.floor(ms / 1_000));
|
|
262
|
-
if (seconds < 60)
|
|
263
|
-
return `${seconds}s`;
|
|
264
|
-
const minutes = Math.floor(seconds / 60);
|
|
265
|
-
if (minutes < 60)
|
|
266
|
-
return `${minutes}m`;
|
|
267
|
-
const hours = Math.floor(minutes / 60);
|
|
268
|
-
if (hours < 24)
|
|
269
|
-
return `${hours}h`;
|
|
270
|
-
return `${Math.floor(hours / 24)}d`;
|
|
271
|
-
}
|
|
272
|
-
function arcSparkline(arcs) {
|
|
273
|
-
if (arcs <= 0)
|
|
274
|
-
return "";
|
|
275
|
-
return Array.from({ length: arcs }, () => "·").join("──");
|
|
276
|
-
}
|
|
277
|
-
function pendingAfterIds(contract) {
|
|
278
|
-
return contract.after.filter((item) => !item.terminal).map((item) => item.id);
|
|
279
|
-
}
|
|
280
|
-
function kanshiGlyph(contract) {
|
|
281
|
-
if (contract.state.state === "corrupt")
|
|
282
|
-
return "×";
|
|
283
|
-
if (pendingAfterIds(contract).length > 0)
|
|
284
|
-
return "○";
|
|
285
|
-
if (contract.state.state === "petitioned")
|
|
286
|
-
return "◎";
|
|
287
|
-
return "●";
|
|
288
|
-
}
|
|
289
|
-
export function projectionGlyph(state) {
|
|
290
|
-
switch (state) {
|
|
291
|
-
case "out":
|
|
292
|
-
return "●";
|
|
293
|
-
case "lost":
|
|
294
|
-
return "○";
|
|
295
|
-
case "done":
|
|
296
|
-
return "◎";
|
|
297
|
-
case "dismissed":
|
|
298
|
-
return "×";
|
|
299
|
-
case "dead":
|
|
300
|
-
return "✕";
|
|
301
|
-
case "minting":
|
|
302
|
-
return "…";
|
|
303
|
-
case "startup-timeout":
|
|
304
|
-
return "!";
|
|
305
|
-
case "unknown":
|
|
306
|
-
return "?";
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
function renderDriftMark(drift) {
|
|
310
|
-
if (drift.state === "drift")
|
|
311
|
-
return `▲${drift.behindBy}`;
|
|
312
|
-
if (drift.state === "orphaned")
|
|
313
|
-
return "▲orphaned";
|
|
314
|
-
return undefined;
|
|
315
|
-
}
|
|
316
|
-
export function renderKanshiBoard(status) {
|
|
317
|
-
const head = shortHead(status.defaultHead);
|
|
318
|
-
if (status.contracts.length === 0) {
|
|
319
|
-
if (status.targetFilter !== null) {
|
|
320
|
-
return `現世 ${head} · target ${status.targetFilter}\nno commissions on target ${status.targetFilter}\n`;
|
|
321
|
-
}
|
|
322
|
-
return `現世 ${head} 无在飞契约\n`;
|
|
323
|
-
}
|
|
324
|
-
const header = status.targetFilter !== null
|
|
325
|
-
? `現世 ${head} · target ${status.targetFilter}`
|
|
326
|
-
: `現世 ${head}`;
|
|
327
|
-
const lines = [header, ""];
|
|
328
|
-
for (const contract of status.contracts) {
|
|
329
|
-
const glyph = kanshiGlyph(contract);
|
|
330
|
-
const name = contract.slug;
|
|
331
|
-
const spark = arcSparkline(contract.arcs);
|
|
332
|
-
const facts = [];
|
|
333
|
-
const lifecycle = contract.state.state;
|
|
334
|
-
if (lifecycle === "bound" || lifecycle === "active" || lifecycle === "petitioned") {
|
|
335
|
-
facts.push(lifecycle);
|
|
336
|
-
}
|
|
337
|
-
if (contract.place) {
|
|
338
|
-
facts.push(`@${contract.place}`);
|
|
339
|
-
}
|
|
340
|
-
const arcObjective = compactWhitespace(contract.currentArc.objective || "(no arc objective)");
|
|
341
|
-
const arcMark = contract.currentArc.state === "open"
|
|
342
|
-
? `a${contract.currentArc.number}+`
|
|
343
|
-
: `a${contract.currentArc.number}`;
|
|
344
|
-
facts.push(`${arcMark} ${arcObjective}`);
|
|
345
|
-
facts.push(`next ${contract.nextStep.detail}`);
|
|
346
|
-
const age = formatAgeMs(contract.lastActiveMs);
|
|
347
|
-
if (age)
|
|
348
|
-
facts.push(age);
|
|
349
|
-
if (contract.queuePosition)
|
|
350
|
-
facts.push(`Q${contract.queuePosition}`);
|
|
351
|
-
const drift = renderDriftMark(contract.baseDrift);
|
|
352
|
-
if (drift)
|
|
353
|
-
facts.push(drift);
|
|
354
|
-
if (contract.nextStep.hint)
|
|
355
|
-
facts.push(contract.nextStep.hint);
|
|
356
|
-
const pending = pendingAfterIds(contract);
|
|
357
|
-
if (pending.length > 0) {
|
|
358
|
-
facts.push(`⧗ ${pending.map((id) => {
|
|
359
|
-
const dot = id.indexOf(".");
|
|
360
|
-
return dot > 0 ? id.slice(0, dot) : id;
|
|
361
|
-
}).join(",")}`);
|
|
362
|
-
}
|
|
363
|
-
if (contract.state.state === "corrupt") {
|
|
364
|
-
facts.push(`corrupt (${contract.state.reason ?? contract.corruptReason ?? "unknown"})`);
|
|
365
|
-
}
|
|
366
|
-
if (contract.queueHeadStalled) {
|
|
367
|
-
facts.push("朱 stall 去广场");
|
|
368
|
-
}
|
|
369
|
-
const sparkCol = spark.padEnd(14);
|
|
370
|
-
const factText = facts.join(" · ");
|
|
371
|
-
lines.push(`${glyph} ${name.padEnd(18)} ${sparkCol} ${factText}`.trimEnd());
|
|
372
|
-
if (contract.bootstrapDiagnostics.some((diagnostic) => diagnostic.kind === "plan-without-result")) {
|
|
373
|
-
lines.push(" ! bootstrap · no result recorded · forfeit and re-bind");
|
|
374
|
-
}
|
|
375
|
-
for (const diagnostic of contract.queueDiagnostics) {
|
|
376
|
-
if (diagnostic.kind === "legacy-petition") {
|
|
377
|
-
lines.push(" ! legacy petition · no seat · reject then re-petition");
|
|
378
|
-
continue;
|
|
379
|
-
}
|
|
380
|
-
if (diagnostic.kind === "duplicate-seat") {
|
|
381
|
-
lines.push(` ! seat ${diagnostic.seat} duplicated with ${diagnostic.with} · ordered by contract id`);
|
|
382
|
-
continue;
|
|
383
|
-
}
|
|
384
|
-
lines.push(` ! target mismatch · petitioned ${diagnostic.petitioned} · derived ${diagnostic.derived}`);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
return `${lines.join("\n")}\n`;
|
|
388
|
-
}
|
package/build/core/draft.js
CHANGED
|
@@ -1,14 +1,34 @@
|
|
|
1
1
|
import { FlowError } from "../flow-error.js";
|
|
2
2
|
import { extractListItems, parseToAST, renderSectionContent } from "./markdown/parser.js";
|
|
3
3
|
import { normalizeScopePattern } from "./scope.js";
|
|
4
|
-
const KNOWN_SECTIONS = new Set(["objective", "scope"]);
|
|
4
|
+
const KNOWN_SECTIONS = new Set(["objective", "scope", "checks"]);
|
|
5
5
|
function invalidBindDraft(message) {
|
|
6
6
|
throw new FlowError("INVALID_KEIYAKU_DRAFT", `INVALID_BIND_DRAFT: ${message}`);
|
|
7
7
|
}
|
|
8
8
|
function normalizeSectionName(name) {
|
|
9
9
|
return name.trim().toLowerCase();
|
|
10
10
|
}
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Canonicalize extension Markdown by dropping only leading/trailing blank
|
|
13
|
+
* physical lines. Retained lines keep every byte (indentation, trailing
|
|
14
|
+
* spaces, fences, internal blanks). Entirely blank input becomes "".
|
|
15
|
+
*/
|
|
16
|
+
function normalizeExtensionContent(content) {
|
|
17
|
+
const lines = content.split(/\r?\n/);
|
|
18
|
+
let start = 0;
|
|
19
|
+
while (start < lines.length && lines[start].trim().length === 0) {
|
|
20
|
+
start += 1;
|
|
21
|
+
}
|
|
22
|
+
let end = lines.length;
|
|
23
|
+
while (end > start && lines[end - 1].trim().length === 0) {
|
|
24
|
+
end -= 1;
|
|
25
|
+
}
|
|
26
|
+
if (start >= end) {
|
|
27
|
+
return "";
|
|
28
|
+
}
|
|
29
|
+
return lines.slice(start, end).join("\n");
|
|
30
|
+
}
|
|
31
|
+
function findUnexpectedListOnlyLine(section) {
|
|
12
32
|
for (const child of section.children) {
|
|
13
33
|
if (child.type === "list")
|
|
14
34
|
continue;
|
|
@@ -27,40 +47,78 @@ function findUnexpectedScopeLine(section) {
|
|
|
27
47
|
}
|
|
28
48
|
return null;
|
|
29
49
|
}
|
|
50
|
+
function extractSingleLineChecks(section) {
|
|
51
|
+
const unexpected = findUnexpectedListOnlyLine(section);
|
|
52
|
+
if (unexpected) {
|
|
53
|
+
invalidBindDraft(`Checks must be a bullet list; found '${unexpected}'`);
|
|
54
|
+
}
|
|
55
|
+
const items = extractListItems(section);
|
|
56
|
+
if (items.length === 0) {
|
|
57
|
+
const hasListNode = section.children.some((child) => child.type === "list");
|
|
58
|
+
if (hasListNode) {
|
|
59
|
+
invalidBindDraft("empty check in bind draft");
|
|
60
|
+
}
|
|
61
|
+
invalidBindDraft("Checks must be a bullet list; found empty Checks section");
|
|
62
|
+
}
|
|
63
|
+
return items.map((item) => {
|
|
64
|
+
const trimmed = item.trim();
|
|
65
|
+
if (trimmed.length === 0) {
|
|
66
|
+
invalidBindDraft("empty check in bind draft");
|
|
67
|
+
}
|
|
68
|
+
if (item.includes("\n") || item.includes("\r")) {
|
|
69
|
+
invalidBindDraft("check items must be a single line");
|
|
70
|
+
}
|
|
71
|
+
return trimmed;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
30
74
|
export function parseBindDraft(content) {
|
|
31
75
|
const ast = parseToAST(content);
|
|
32
76
|
let name;
|
|
77
|
+
let seenH1 = false;
|
|
33
78
|
const sections = new Map();
|
|
79
|
+
const extensions = [];
|
|
34
80
|
for (const node of ast.children) {
|
|
35
81
|
if (node.type !== "section")
|
|
36
82
|
continue;
|
|
37
|
-
if (node.level === 1
|
|
83
|
+
if (node.level === 1) {
|
|
84
|
+
if (seenH1) {
|
|
85
|
+
invalidBindDraft("bind draft allows exactly one H1 heading");
|
|
86
|
+
}
|
|
87
|
+
seenH1 = true;
|
|
38
88
|
name = node.title.trim() || undefined;
|
|
39
89
|
continue;
|
|
40
90
|
}
|
|
41
91
|
if (node.level !== 2)
|
|
42
92
|
continue;
|
|
43
93
|
const normalized = normalizeSectionName(node.title);
|
|
44
|
-
if (
|
|
94
|
+
if (KNOWN_SECTIONS.has(normalized)) {
|
|
95
|
+
if (sections.has(normalized)) {
|
|
96
|
+
invalidBindDraft(`duplicate section '${node.title}' in bind draft`);
|
|
97
|
+
}
|
|
98
|
+
sections.set(normalized, node);
|
|
45
99
|
continue;
|
|
46
|
-
if (sections.has(normalized)) {
|
|
47
|
-
invalidBindDraft(`duplicate section '${node.title}' in bind draft`);
|
|
48
100
|
}
|
|
49
|
-
|
|
101
|
+
extensions.push({
|
|
102
|
+
title: node.title.trim(),
|
|
103
|
+
content: normalizeExtensionContent(renderSectionContent(node)),
|
|
104
|
+
});
|
|
50
105
|
}
|
|
51
106
|
if (!name) {
|
|
52
|
-
invalidBindDraft("missing H1 in bind draft; expected '# <name>' followed by '## Objective' and '##
|
|
107
|
+
invalidBindDraft("missing H1 in bind draft; expected '# <name>' followed by '## Objective', '## Scope', and '## Checks'");
|
|
53
108
|
}
|
|
54
109
|
const objective = sections.get("objective");
|
|
55
110
|
const scope = sections.get("scope");
|
|
111
|
+
const checks = sections.get("checks");
|
|
56
112
|
if (!objective)
|
|
57
113
|
invalidBindDraft("missing Objective section in bind draft");
|
|
58
114
|
if (!scope)
|
|
59
115
|
invalidBindDraft("missing Scope section in bind draft");
|
|
116
|
+
if (!checks)
|
|
117
|
+
invalidBindDraft("missing Checks section in bind draft");
|
|
60
118
|
const objectiveText = renderSectionContent(objective).trim();
|
|
61
119
|
if (!objectiveText)
|
|
62
120
|
invalidBindDraft("Objective section cannot be empty");
|
|
63
|
-
const unexpectedScopeLine =
|
|
121
|
+
const unexpectedScopeLine = findUnexpectedListOnlyLine(scope);
|
|
64
122
|
if (unexpectedScopeLine) {
|
|
65
123
|
invalidBindDraft(`Scope must be a bullet list; found '${unexpectedScopeLine}'`);
|
|
66
124
|
}
|
|
@@ -77,5 +135,45 @@ export function parseBindDraft(content) {
|
|
|
77
135
|
}
|
|
78
136
|
return normalizeScopePattern(item);
|
|
79
137
|
}),
|
|
138
|
+
checks: extractSingleLineChecks(checks),
|
|
139
|
+
extensions,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
export function renderBindDraft(draft) {
|
|
143
|
+
const sections = [
|
|
144
|
+
`# ${draft.name}`,
|
|
145
|
+
`## Objective\n${draft.objective}`,
|
|
146
|
+
`## Scope\n${draft.scope.map((pattern) => `- ${pattern}`).join("\n")}`,
|
|
147
|
+
`## Checks\n${draft.checks.map((check) => `- ${check}`).join("\n")}`,
|
|
148
|
+
];
|
|
149
|
+
for (const extension of draft.extensions) {
|
|
150
|
+
const content = normalizeExtensionContent(extension.content);
|
|
151
|
+
if (content.length > 0) {
|
|
152
|
+
sections.push(`## ${extension.title}\n${content}`);
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
sections.push(`## ${extension.title}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return `${sections.join("\n\n")}\n`;
|
|
159
|
+
}
|
|
160
|
+
export function compileBindDraftFlags(input) {
|
|
161
|
+
for (const [flag, value] of [
|
|
162
|
+
["--place", input.place],
|
|
163
|
+
["--objective", input.objective],
|
|
164
|
+
["--scope", input.scope],
|
|
165
|
+
["--checks", input.checks],
|
|
166
|
+
]) {
|
|
167
|
+
if (value.includes("\n") || value.includes("\r")) {
|
|
168
|
+
throw new FlowError("EMPTY_PARAM", `${flag} must be a single line`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const draft = {
|
|
172
|
+
name: input.place,
|
|
173
|
+
objective: input.objective,
|
|
174
|
+
scope: [input.scope],
|
|
175
|
+
checks: [input.checks],
|
|
176
|
+
extensions: [],
|
|
80
177
|
};
|
|
178
|
+
return renderBindDraft(parseBindDraft(renderBindDraft(draft)));
|
|
81
179
|
}
|
package/build/core/entry.js
CHANGED
|
@@ -52,6 +52,14 @@ export const bindEntryDataSchema = z
|
|
|
52
52
|
name: nonEmptyString,
|
|
53
53
|
objective: nonEmptyString,
|
|
54
54
|
scope: z.array(scopePatternString).min(1),
|
|
55
|
+
checks: z.array(nonBlankString).min(1),
|
|
56
|
+
extensions: z
|
|
57
|
+
.array(z
|
|
58
|
+
.object({
|
|
59
|
+
title: nonBlankString,
|
|
60
|
+
content: z.string(),
|
|
61
|
+
})
|
|
62
|
+
.strict()),
|
|
55
63
|
base: shaSchema,
|
|
56
64
|
target: fullBranchRefSchema,
|
|
57
65
|
workspace: z.enum(["worktree", "here"]),
|
|
@@ -111,7 +119,7 @@ export const arcEntryDataSchema = z
|
|
|
111
119
|
.strict();
|
|
112
120
|
export const sealEntryDataSchema = z
|
|
113
121
|
.object({
|
|
114
|
-
arc: z.number().int().
|
|
122
|
+
arc: z.number().int().nonnegative(),
|
|
115
123
|
sealedBy: z.enum(["arc", "renew", "petition"]),
|
|
116
124
|
oldFence: shaSchema,
|
|
117
125
|
newFence: shaSchema,
|
|
@@ -1,23 +1,7 @@
|
|
|
1
1
|
import { isCommissionId } from "./ids.js";
|
|
2
|
-
|
|
3
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
4
|
-
}
|
|
5
|
-
function assertExactFields(value, required, optional, prefix, invalid) {
|
|
6
|
-
for (const field of required) {
|
|
7
|
-
if (!(field in value))
|
|
8
|
-
throw invalid(prefix ? `${prefix}.${field}` : field, "is missing");
|
|
9
|
-
}
|
|
10
|
-
const allowed = new Set([...required, ...optional]);
|
|
11
|
-
const unknown = Object.keys(value).filter((field) => !allowed.has(field)).sort()[0];
|
|
12
|
-
if (unknown !== undefined)
|
|
13
|
-
throw invalid(prefix ? `${prefix}.${unknown}` : unknown, "is unknown");
|
|
14
|
-
}
|
|
15
|
-
function requireNonBlank(value, field, invalid) {
|
|
16
|
-
if (typeof value !== "string" || value.trim() === "")
|
|
17
|
-
throw invalid(field, "must be a non-blank string");
|
|
18
|
-
}
|
|
2
|
+
import { assertExactFields, assertNonBlankString, isPlainRecord, } from "./validation.js";
|
|
19
3
|
export function parseExecutionAuthority(value, invalid) {
|
|
20
|
-
if (!
|
|
4
|
+
if (!isPlainRecord(value))
|
|
21
5
|
throw invalid("authority", "must be an object");
|
|
22
6
|
if (!("kind" in value))
|
|
23
7
|
throw invalid("authority.kind", "is missing");
|
|
@@ -34,13 +18,13 @@ export function parseExecutionAuthority(value, invalid) {
|
|
|
34
18
|
throw invalid("authority.kind", "must be 'repository' or 'user'");
|
|
35
19
|
}
|
|
36
20
|
export function parseExecutionBinding(value, invalid) {
|
|
37
|
-
if (!
|
|
21
|
+
if (!isPlainRecord(value))
|
|
38
22
|
throw invalid("binding", "must be an object");
|
|
39
23
|
if (!("kind" in value))
|
|
40
24
|
throw invalid("binding.kind", "is missing");
|
|
41
25
|
if (value.kind === "commission") {
|
|
42
26
|
assertExactFields(value, ["kind", "commissionId"], [], "binding", invalid);
|
|
43
|
-
|
|
27
|
+
assertNonBlankString(value.commissionId, "binding.commissionId", invalid);
|
|
44
28
|
if (!isCommissionId(value.commissionId))
|
|
45
29
|
throw invalid("binding.commissionId", "must be a full commission ID");
|
|
46
30
|
return { kind: "commission", commissionId: value.commissionId };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import { ProjectionStateError } from "./atomic-publish.js";
|
|
3
3
|
import { parseExecutionBinding as parseCanonicalExecutionBinding, parseExecutionCoordinates, } from "./execution-coordinate.js";
|
|
4
|
+
import { assertExactFields, assertNonBlankString, isPlainRecord, } from "./validation.js";
|
|
4
5
|
const TOP_LEVEL_FIELDS = [
|
|
5
6
|
"version",
|
|
6
7
|
"pid",
|
|
@@ -16,31 +17,14 @@ const PACT_FIELD_NAMES = TOP_LEVEL_FIELDS.filter((field) => field !== "authority
|
|
|
16
17
|
function pactError(pactPath, field, reason) {
|
|
17
18
|
return new ProjectionStateError(`invalid projection pact at ${pactPath}: field '${field}' ${reason}`);
|
|
18
19
|
}
|
|
19
|
-
function
|
|
20
|
-
return
|
|
21
|
-
}
|
|
22
|
-
function assertExactFields(value, required, optional, pactPath, fieldPrefix) {
|
|
23
|
-
for (const field of required) {
|
|
24
|
-
if (!(field in value)) {
|
|
25
|
-
throw pactError(pactPath, fieldPrefix ? `${fieldPrefix}.${field}` : field, "is missing");
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
const allowed = new Set([...required, ...optional]);
|
|
29
|
-
const unknown = Object.keys(value).filter((field) => !allowed.has(field)).sort()[0];
|
|
30
|
-
if (unknown !== undefined) {
|
|
31
|
-
throw pactError(pactPath, fieldPrefix ? `${fieldPrefix}.${unknown}` : unknown, "is unknown");
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
function assertNonBlankString(value, pactPath, field) {
|
|
35
|
-
if (typeof value !== "string" || value.trim() === "") {
|
|
36
|
-
throw pactError(pactPath, field, "must be a non-blank string");
|
|
37
|
-
}
|
|
20
|
+
function pactInvalid(pactPath) {
|
|
21
|
+
return (field, reason) => pactError(pactPath, field, reason);
|
|
38
22
|
}
|
|
39
23
|
/** Parse the pre-publication authority choice without inventing a durable identity. */
|
|
40
24
|
export function parseExecutionAuthoritySelection(value, pactPath = "projection identity", expectedKind) {
|
|
41
|
-
if (!
|
|
25
|
+
if (!isPlainRecord(value))
|
|
42
26
|
throw pactError(pactPath, "authority", "must be an object");
|
|
43
|
-
assertExactFields(value, ["kind"], [],
|
|
27
|
+
assertExactFields(value, ["kind"], [], "authority", pactInvalid(pactPath));
|
|
44
28
|
if (value.kind !== "repository" && value.kind !== "user") {
|
|
45
29
|
throw pactError(pactPath, "authority.kind", "must be 'repository' or 'user'");
|
|
46
30
|
}
|
|
@@ -57,9 +41,9 @@ export function assertExecutionPactCoordinates(authorityValue, bindingValue, pac
|
|
|
57
41
|
return parseExecutionCoordinates(authorityValue, bindingValue, (field, reason) => pactError(pactPath, field, reason));
|
|
58
42
|
}
|
|
59
43
|
function parseEffectivePolicy(value, pactPath) {
|
|
60
|
-
if (!
|
|
44
|
+
if (!isPlainRecord(value))
|
|
61
45
|
throw pactError(pactPath, "effectivePolicy", "must be an object");
|
|
62
|
-
assertExactFields(value, [], ["access", "network", "webSearch"],
|
|
46
|
+
assertExactFields(value, [], ["access", "network", "webSearch"], "effectivePolicy", pactInvalid(pactPath));
|
|
63
47
|
if (value.access !== undefined && value.access !== "read" && value.access !== "write" && value.access !== "auto") {
|
|
64
48
|
throw pactError(pactPath, "effectivePolicy.access", "must be 'read', 'write', or 'auto'");
|
|
65
49
|
}
|
|
@@ -77,14 +61,15 @@ function parseExecutionPactFieldsRecord(value, pactPath) {
|
|
|
77
61
|
if (!Number.isInteger(value.pid) || value.pid < 0) {
|
|
78
62
|
throw pactError(pactPath, "pid", "must be a non-negative integer");
|
|
79
63
|
}
|
|
80
|
-
|
|
81
|
-
assertNonBlankString(value.
|
|
82
|
-
assertNonBlankString(value.
|
|
64
|
+
const invalid = pactInvalid(pactPath);
|
|
65
|
+
assertNonBlankString(value.akuma, "akuma", invalid);
|
|
66
|
+
assertNonBlankString(value.provider, "provider", invalid);
|
|
67
|
+
assertNonBlankString(value.mintedAt, "mintedAt", invalid);
|
|
83
68
|
const mintedAtMs = Date.parse(value.mintedAt);
|
|
84
69
|
if (!Number.isFinite(mintedAtMs) || new Date(mintedAtMs).toISOString() !== value.mintedAt) {
|
|
85
70
|
throw pactError(pactPath, "mintedAt", "must be an ISO-8601 timestamp");
|
|
86
71
|
}
|
|
87
|
-
assertNonBlankString(value.workspaceRoot,
|
|
72
|
+
assertNonBlankString(value.workspaceRoot, "workspaceRoot", invalid);
|
|
88
73
|
if (!path.isAbsolute(value.workspaceRoot)) {
|
|
89
74
|
throw pactError(pactPath, "workspaceRoot", "must be an absolute path");
|
|
90
75
|
}
|
|
@@ -104,15 +89,15 @@ function parseExecutionPactFieldsRecord(value, pactPath) {
|
|
|
104
89
|
}
|
|
105
90
|
/** Validate every pact field that exists before a repository identity is minted. */
|
|
106
91
|
export function parseExecutionPactFields(value, pactPath = "projection identity") {
|
|
107
|
-
if (!
|
|
92
|
+
if (!isPlainRecord(value))
|
|
108
93
|
throw pactError(pactPath, "$", "must be an object");
|
|
109
|
-
assertExactFields(value, PACT_FIELD_NAMES, TOP_LEVEL_OPTIONAL_FIELDS,
|
|
94
|
+
assertExactFields(value, PACT_FIELD_NAMES, TOP_LEVEL_OPTIONAL_FIELDS, "", pactInvalid(pactPath));
|
|
110
95
|
return parseExecutionPactFieldsRecord(value, pactPath);
|
|
111
96
|
}
|
|
112
97
|
export function parseExecutionPact(value, pactPath = "projection identity") {
|
|
113
|
-
if (!
|
|
98
|
+
if (!isPlainRecord(value))
|
|
114
99
|
throw pactError(pactPath, "$", "must be an object");
|
|
115
|
-
assertExactFields(value, TOP_LEVEL_FIELDS, TOP_LEVEL_OPTIONAL_FIELDS,
|
|
100
|
+
assertExactFields(value, TOP_LEVEL_FIELDS, TOP_LEVEL_OPTIONAL_FIELDS, "", pactInvalid(pactPath));
|
|
116
101
|
const fields = parseExecutionPactFieldsRecord(value, pactPath);
|
|
117
102
|
const { authority, binding } = assertExecutionPactCoordinates(value.authority, fields.binding, pactPath);
|
|
118
103
|
return {
|
package/build/core/forfeit.js
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
import { FlowError } from "../flow-error.js";
|
|
2
2
|
import { activeLedgerRef, appendWithRetry, readLedger } from "./ledger.js";
|
|
3
3
|
import { releaseScope } from "./registry.js";
|
|
4
|
-
import { deriveContractState, isTerminalState } from "./status.js";
|
|
4
|
+
import { deriveContractState, isTerminalState } from "./status/lifecycle.js";
|
|
5
|
+
import { reconcileTaskForfeit } from "./task-contract.js";
|
|
5
6
|
import { cleanupContractWorkspace, stableRepoRoot } from "./worktree-path.js";
|
|
6
7
|
async function cleanupForfeit(cwd, contractId, actor, at) {
|
|
7
8
|
const stableRoot = await stableRepoRoot(cwd);
|
|
8
9
|
await releaseScope(stableRoot, { contractId, actor, at });
|
|
9
10
|
return await cleanupContractWorkspace(stableRoot, contractId);
|
|
10
11
|
}
|
|
11
|
-
export async function forfeitContract(input) {
|
|
12
|
+
export async function forfeitContract(input, deps = {}) {
|
|
12
13
|
const at = new Date(input.nowMs).toISOString();
|
|
13
|
-
const
|
|
14
|
+
const stableRoot = await stableRepoRoot(input.cwd);
|
|
15
|
+
const ledger = await readLedger(stableRoot, input.contractId);
|
|
14
16
|
if (ledger) {
|
|
15
17
|
const state = deriveContractState(ledger.entries);
|
|
16
18
|
if (state.state === "forfeited") {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
await reconcileTaskForfeit({
|
|
20
|
+
cwd: stableRoot,
|
|
21
|
+
contractId: input.contractId,
|
|
22
|
+
publishLedger: async () => undefined,
|
|
23
|
+
});
|
|
24
|
+
const cleanup = await (deps.cleanupForfeit ?? cleanupForfeit)(stableRoot, input.contractId, input.actor, at);
|
|
19
25
|
return { contractId: input.contractId, cleanup };
|
|
20
26
|
}
|
|
21
27
|
}
|
|
@@ -26,25 +32,32 @@ export async function forfeitContract(input) {
|
|
|
26
32
|
if (state.state === "corrupt" || isTerminalState(state)) {
|
|
27
33
|
throw new FlowError("INTERNAL_STATE", `contract ${input.contractId} cannot forfeit from state ${state.state}`);
|
|
28
34
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
await reconcileTaskForfeit({
|
|
36
|
+
cwd: stableRoot,
|
|
37
|
+
contractId: input.contractId,
|
|
38
|
+
publishLedger: async () => {
|
|
39
|
+
const result = await appendWithRetry(stableRoot, activeLedgerRef(input.contractId), () => {
|
|
40
|
+
const entry = {
|
|
41
|
+
v: 1,
|
|
42
|
+
kind: "forfeit",
|
|
43
|
+
contract: input.contractId,
|
|
44
|
+
at,
|
|
45
|
+
actor: input.actor,
|
|
46
|
+
data: {
|
|
47
|
+
reason: input.reason,
|
|
48
|
+
by: input.actor,
|
|
49
|
+
...(input.note?.trim() ? { note: input.note.trim() } : {}),
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
return entry;
|
|
53
|
+
});
|
|
54
|
+
if (!result.ok)
|
|
55
|
+
throw new FlowError("INTERNAL_STATE", `failed to forfeit ${input.contractId}: ${result.reason}`);
|
|
56
|
+
return result;
|
|
57
|
+
},
|
|
43
58
|
});
|
|
44
|
-
if (!result.ok)
|
|
45
|
-
throw new FlowError("INTERNAL_STATE", `failed to forfeit ${input.contractId}: ${result.reason}`);
|
|
46
59
|
// Forfeit entry naturally removes membership; no dequeue record.
|
|
47
|
-
const cleanup = await cleanupForfeit(
|
|
60
|
+
const cleanup = await (deps.cleanupForfeit ?? cleanupForfeit)(stableRoot, input.contractId, input.actor, at);
|
|
48
61
|
return { contractId: input.contractId, cleanup };
|
|
49
62
|
}
|
|
50
63
|
export async function forfeitContractCommand(input) {
|
package/build/core/hints.js
CHANGED
|
@@ -9,7 +9,7 @@ const HELP_BODY_TEMPLATE = [
|
|
|
9
9
|
`- **\${bind}**: Create the active contract ledger and workspace files from Markdown stdin. The worktree must be clean; call it once per Keiyaku.`,
|
|
10
10
|
`- **\${arc}**: Record the delivery arc title, objective, and brief before work starts. It seals any open arc and does not run agents or mutate delivery code.`,
|
|
11
11
|
`- **\${call}**: Call a ${ACTOR_IDENTITY} for bounded work. An open arc supplies scoped context; the caller still owns review, integration, and commits.`,
|
|
12
|
-
`- **akuma
|
|
12
|
+
`- **akuma ls / akuma view**: Inspect available ${ACTOR_IDENTITY_PLURAL} and their resolved provider/executable before choosing \`keiyaku call NAME\`.`,
|
|
13
13
|
"- **delivery commits**: Commit the actual code or documentation changes in git before sealing them.",
|
|
14
14
|
`- **\${renew}**: Capture receipts, update delivery onto the default branch, seal the open arc, and record the new base.`,
|
|
15
15
|
`- **\${amend}**: Update the Keiyaku when scope, rules, criteria, or intent changed.`,
|
|
@@ -22,7 +22,7 @@ const HELP_BODY_TEMPLATE = [
|
|
|
22
22
|
`- \`\${arc}\` and \`\${renew}\` are ledger operations; they do not call agents and do not edit delivery code.`,
|
|
23
23
|
`- \`\${call}\` can run outside a Keiyaku, but an open arc gives the ${ACTOR_IDENTITY} better context.`,
|
|
24
24
|
`- \`\${call}\` starts a new session. Use \`keiyaku revive ARTIFACT_ID\` to continue a prior response artifact.`,
|
|
25
|
-
"- `akuma
|
|
25
|
+
"- `akuma ls` and `akuma view <name>` are read-only inspection commands; they do not start a helper.",
|
|
26
26
|
"- `keiyaku revive` restores the agent from the response artifact; `--incognito` calls cannot be revived later.",
|
|
27
27
|
"- Premature `petition` requests are rejected; continue with `${arc}`, `${call}`, or `${renew}` until the work is verified.",
|
|
28
28
|
"",
|
package/build/core/log.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FlowError } from "../flow-error.js";
|
|
2
2
|
import { readLedger } from "./ledger.js";
|
|
3
|
-
import { renderContractView } from "./
|
|
4
|
-
import { deriveContractState } from "./status.js";
|
|
3
|
+
import { renderContractView } from "./contract-view.js";
|
|
4
|
+
import { deriveContractState } from "./status/lifecycle.js";
|
|
5
5
|
export async function readContractLog(input) {
|
|
6
6
|
const ledger = await readLedger(input.cwd, input.contractId);
|
|
7
7
|
if (!ledger) {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { getConfig } from "../config/env.js";
|
|
3
|
-
import { assertSettingsKnobUsable
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { assertSettingsKnobUsable } from "../config/settings/disease.js";
|
|
4
|
+
import { resolveReviewerAgentName } from "../config/settings/knobs.js";
|
|
5
|
+
import { loadKeiyakuSettings } from "../config/settings/loader.js";
|
|
6
|
+
import { loadAkumaCatalog } from "../config/akuma-loader.js";
|
|
7
|
+
import { formatAvailableAgentNames } from "../agents/selector.js";
|
|
6
8
|
import { getDiffStats } from "../git/diff/preview.js";
|
|
7
9
|
import { readDiff } from "../git/diff/read.js";
|
|
8
10
|
import { getCurrentBranch } from "../git/branches.js";
|
|
@@ -11,7 +13,7 @@ import { DIFF_PREVIEW_TEXT_MAX_CHARS } from "../keiyaku.js";
|
|
|
11
13
|
import { FlowError } from "../flow-error.js";
|
|
12
14
|
import { persistResponseHistory } from "./transcripts.js";
|
|
13
15
|
import { logInfo } from "../telemetry/logger.js";
|
|
14
|
-
import { execSubagent } from "./call.js";
|
|
16
|
+
import { execSubagent } from "./call/call.js";
|
|
15
17
|
import { readContractLog } from "./log.js";
|
|
16
18
|
import { buildVerificationFailureHints } from "./hints.js";
|
|
17
19
|
const CLAIM_VERIFICATION_OUTPUT_MAX_CHARS = 1200;
|
|
@@ -168,10 +170,10 @@ export function createAgentReviewGate() {
|
|
|
168
170
|
}
|
|
169
171
|
const settings = loaded.knobs;
|
|
170
172
|
const reviewerAgentName = resolveReviewerAgentName(settings);
|
|
171
|
-
const catalog = await
|
|
173
|
+
const catalog = await loadAkumaCatalog(cwd);
|
|
172
174
|
const availableNames = Object.keys(catalog.selected);
|
|
173
175
|
if (catalog.selected[reviewerAgentName] === undefined) {
|
|
174
|
-
throw new FlowError("UNKNOWN_SUBAGENT", `Unknown agent '${reviewerAgentName}'. Expected one of: ${
|
|
176
|
+
throw new FlowError("UNKNOWN_SUBAGENT", `Unknown agent '${reviewerAgentName}'. Expected one of: ${formatAvailableAgentNames(availableNames)}`);
|
|
175
177
|
}
|
|
176
178
|
const [contractLog, diffStat, fullDiff, currentBranch, headRef] = await Promise.all([
|
|
177
179
|
readContractLog({ cwd, contractId }),
|