@astrosheep/keiyaku 2.9.9 → 2.9.10
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 +50 -182
- package/build/.tsbuildinfo +1 -1
- package/build/agents/harness/control-types.js +18 -1
- package/build/agents/harness/index.js +2 -0
- package/build/agents/harness/outcome-error.js +81 -0
- package/build/agents/harness/projection.js +2 -1
- package/build/agents/harness/router.js +5 -1
- package/build/agents/providers/claude-agent-sdk/adapter.js +18 -4
- package/build/agents/providers/claude-agent-sdk/registration.js +11 -1
- package/build/agents/providers/claude-agent-sdk/session.js +19 -5
- package/build/agents/providers/codex-app-server/adapter.js +11 -6
- package/build/agents/providers/codex-app-server/events.js +67 -6
- package/build/agents/providers/codex-app-server/registration.js +11 -1
- package/build/agents/providers/opencode-sdk/adapter.js +8 -1
- package/build/agents/providers/opencode-sdk/events.js +24 -2
- package/build/agents/providers/opencode-sdk/registration.js +11 -1
- package/build/agents/providers/pi/checkpoint.js +9 -1
- package/build/agents/providers/pi/events.js +2 -0
- package/build/agents/providers/pi/registration.js +14 -1
- package/build/cli/commands/akuma/akuma/handler.js +1 -1
- package/build/cli/commands/akuma/akuma/meta.js +3 -3
- package/build/cli/commands/akuma/catalog.js +2 -2
- package/build/cli/commands/akuma/{view → show}/handler.js +5 -5
- package/build/cli/commands/akuma/{view → show}/meta.js +3 -3
- package/build/cli/commands/akuma.js +1 -1
- package/build/cli/commands/contract/amend/handler.js +5 -4
- package/build/cli/commands/contract/arc/handler.js +5 -4
- package/build/cli/commands/contract/audit/handler.js +2 -2
- package/build/cli/commands/contract/bind/handler.js +12 -3
- package/build/cli/commands/contract/bind/meta.js +45 -15
- package/build/cli/commands/contract/forfeit/handler.js +9 -5
- package/build/cli/commands/contract/log/handler.js +2 -2
- package/build/cli/commands/contract/petition/handler.js +34 -7
- package/build/cli/commands/contract/renew/handler.js +7 -7
- package/build/cli/commands/contract/renew/meta.js +3 -3
- package/build/cli/commands/metadata.js +10 -6
- package/build/cli/commands/projection/call/meta.js +1 -1
- package/build/cli/commands/projection/catalog.js +2 -0
- package/build/cli/commands/projection/history/handler.js +21 -0
- package/build/cli/commands/projection/history/meta.js +9 -0
- package/build/cli/commands/projection/shared.js +3 -4
- package/build/cli/commands/projection/status/handler.js +3 -3
- package/build/cli/commands/projection/wait/handler.js +20 -11
- package/build/cli/commands/task/add/handler.js +14 -5
- package/build/cli/commands/task/add/meta.js +2 -2
- package/build/cli/commands/task/catalog.js +4 -0
- package/build/cli/commands/task/done/handler.js +1 -4
- package/build/cli/commands/task/done/meta.js +1 -1
- package/build/cli/commands/task/drop/meta.js +1 -1
- package/build/cli/commands/task/hold/handler.js +3 -0
- package/build/cli/commands/task/hold/meta.js +8 -0
- package/build/cli/commands/task/log/handler.js +1 -1
- package/build/cli/commands/task/log/meta.js +2 -2
- package/build/cli/commands/task/resume/handler.js +3 -0
- package/build/cli/commands/task/resume/meta.js +8 -0
- package/build/cli/commands/task/shared.js +39 -14
- package/build/cli/commands/task/show/handler.js +1 -1
- package/build/cli/commands/task/show/meta.js +1 -1
- package/build/cli/commands/task/start/meta.js +1 -1
- package/build/cli/commands/task/stop/handler.js +1 -4
- package/build/cli/commands/task/stop/meta.js +1 -1
- package/build/cli/commands/task/update/handler.js +11 -3
- package/build/cli/commands/task/update/meta.js +3 -3
- package/build/cli/completion.js +3 -2
- package/build/cli/flags.js +51 -14
- package/build/cli/help.js +4 -1
- package/build/cli/index.js +40 -25
- package/build/cli/parse-flags.js +40 -7
- package/build/cli/parse-metadata.js +5 -2
- package/build/cli/parse-selectors.js +2 -3
- package/build/cli/parse.js +40 -6
- package/build/cli/projection-address.js +12 -10
- package/build/cli/render/amendment-warning.js +8 -0
- package/build/cli/render/arc.js +6 -2
- package/build/cli/render/audit.js +400 -81
- package/build/cli/render/kanshi.js +6 -1
- package/build/cli/render/lifecycle.js +56 -0
- package/build/cli/render/misc.js +24 -28
- package/build/cli/render/petition.js +5 -0
- package/build/cli/render/projection-activity.js +3 -2
- package/build/cli/render/projection-history.js +64 -0
- package/build/cli/render/shared.js +23 -9
- package/build/cli/render/status.js +9 -16
- package/build/cli/render/task.js +51 -26
- package/build/cli/render/terminal-failure.js +3 -1
- package/build/cli/render/wait.js +3 -5
- package/build/cli/subagent-guard.js +1 -1
- package/build/cli/types.js +1 -1
- package/build/config/env-keys.js +2 -0
- package/build/config/env.js +23 -0
- package/build/config/settings/schema.js +3 -1
- package/build/core/address-carrier.js +89 -0
- package/build/core/addressing.js +255 -196
- package/build/core/amend.js +115 -38
- package/build/core/amendment-criteria.js +17 -0
- package/build/core/amendment-warning.js +10 -0
- package/build/core/arc.js +184 -83
- package/build/core/audit/candidate.js +110 -9
- package/build/core/audit/coordinates.js +120 -65
- package/build/core/audit/evidence.js +19 -23
- package/build/core/audit/facade.js +34 -11
- package/build/core/audit/report.js +5 -5
- package/build/core/bind-reconciliation.js +390 -0
- package/build/core/bind-workspace.js +12 -20
- package/build/core/bind.js +242 -273
- package/build/core/call/call.js +1 -0
- package/build/core/call/context.js +46 -71
- package/build/core/call/prompt.js +6 -3
- package/build/core/context.js +49 -35
- package/build/core/contract-carrier-runtime.js +408 -0
- package/build/core/contract-carrier.js +270 -0
- package/build/core/contract-view.js +33 -27
- package/build/core/contract.js +5 -1
- package/build/core/derived-replay.js +207 -0
- package/build/core/draft.js +125 -57
- package/build/core/forfeit.js +113 -56
- package/build/core/identifier-slug.js +63 -13
- package/build/core/ids.js +4 -4
- package/build/core/lifecycle-history.js +35 -0
- package/build/core/lifecycle-recovery.js +117 -0
- package/build/core/lifecycle-runner.js +377 -0
- package/build/core/log.js +37 -11
- package/build/core/outcome-base.js +181 -0
- package/build/core/process-group.js +139 -0
- package/build/core/projection/generation/database.js +82 -7
- package/build/core/projection/generation/model.js +9 -36
- package/build/core/projection/generation/projection-generation-continuation.js +10 -22
- package/build/core/projection/generation/projection-generation-execution.js +6 -5
- package/build/core/projection/index.js +5 -4
- package/build/core/projection/projection-activity.js +27 -8
- package/build/core/projection/projection-alias.js +23 -10
- package/build/core/projection/projection-core.js +21 -7
- package/build/core/projection/projection-execution-observer.js +91 -39
- package/build/core/projection/projection-history.js +474 -0
- package/build/core/projection/projection-runner-lock.js +12 -0
- package/build/core/projection/projection-status-observation.js +365 -0
- package/build/core/projection/projection-status.js +21 -358
- package/build/core/projection/projection-terminal-failure.js +13 -8
- package/build/core/projection/projection-wait.js +7 -2
- package/build/core/projection/tell/launch-store.js +244 -0
- package/build/core/projection/tell/model.js +3 -3
- package/build/core/projection/tell/store.js +70 -118
- package/build/core/registry.js +22 -87
- package/build/core/renew-build.js +424 -0
- package/build/core/renew-plan.js +239 -0
- package/build/core/renew-rewrite.js +77 -0
- package/build/core/renew.js +295 -520
- package/build/core/repository-ledger/accepted-fold-read.js +19 -0
- package/build/core/repository-ledger/accepted-tail.js +116 -0
- package/build/core/repository-ledger/admission.js +38 -0
- package/build/core/repository-ledger/authoritative-transaction.js +1 -0
- package/build/core/repository-ledger/claim-evidence.js +147 -0
- package/build/core/repository-ledger/codec.js +297 -0
- package/build/core/repository-ledger/current-state-store.js +853 -0
- package/build/core/repository-ledger/fold-repository.js +375 -0
- package/build/core/repository-ledger/fold.js +248 -0
- package/build/core/repository-ledger/git-object-store.js +243 -0
- package/build/core/repository-ledger/history-read.js +15 -0
- package/build/core/repository-ledger/incremental-read.js +153 -0
- package/build/core/repository-ledger/index.js +15 -0
- package/build/core/repository-ledger/inventory-plan.js +75 -0
- package/build/core/repository-ledger/inventory.js +310 -0
- package/build/core/repository-ledger/publication-admission.js +125 -0
- package/build/core/repository-ledger/publication.js +353 -0
- package/build/core/repository-ledger/read-model.js +469 -0
- package/build/core/repository-ledger/transaction-membership.js +78 -0
- package/build/core/repository-ledger/traversal.js +404 -0
- package/build/core/repository-ledger/write-transaction.js +339 -0
- package/build/core/seal.js +168 -161
- package/build/core/settlement/claim-delivery.js +42 -215
- package/build/core/settlement/claim.js +235 -153
- package/build/core/settlement/index.js +4 -4
- package/build/core/settlement/petition-claim-gates.js +52 -33
- package/build/core/settlement/petition-forfeit.js +12 -5
- package/build/core/settlement/petition-head-guard.js +8 -5
- package/build/core/settlement/petition-preview.js +68 -56
- package/build/core/settlement/petition-window.js +50 -0
- package/build/core/settlement/petition.js +252 -131
- package/build/core/settlement/queue-read-model.js +72 -95
- package/build/core/settlement/queue-seat-allocation.js +35 -126
- package/build/core/settlement/queue.js +1 -1
- package/build/core/settlement/settlement.js +172 -80
- package/build/core/settlement/verdict.js +112 -66
- package/build/core/settlement/verification-coordination.js +305 -0
- package/build/core/settlement/verification-supervisor.js +275 -0
- package/build/core/settlement/verification.js +398 -31
- package/build/core/status/board.js +114 -119
- package/build/core/status/lifecycle.js +7 -80
- package/build/core/structured-query.js +23 -0
- package/build/core/target-ref.js +1 -1
- package/build/core/task/board.js +59 -24
- package/build/core/task/commands.js +181 -33
- package/build/core/task/coordinate.js +56 -0
- package/build/core/task/document.js +25 -9
- package/build/core/task/index.js +7 -4
- package/build/core/task/query.js +17 -27
- package/build/core/task/settlement-git.js +164 -179
- package/build/core/task/settlement-policy.js +15 -11
- package/build/core/task/source-board.js +31 -13
- package/build/core/task/task-bind-preparation.js +193 -0
- package/build/core/task/task-contract.js +102 -193
- package/build/core/task/task-file-transaction.js +171 -0
- package/build/core/task/task-git-runtime.js +76 -14
- package/build/core/task/task-git-store.js +68 -169
- package/build/core/task/task-store-repository.js +13 -6
- package/build/core/task/task-worktree.js +6 -33
- package/build/core/task/task.js +1 -1
- package/build/core/task/tree.js +3 -3
- package/build/core/task/validation.js +4 -3
- package/build/core/transcripts.js +93 -1
- package/build/core/worktree-bootstrap.js +44 -36
- package/build/core/worktree-path.js +210 -77
- package/build/flow-error.js +7 -7
- package/build/generated/version.js +2 -2
- package/build/git/core.js +76 -13
- package/build/git/refs.js +168 -46
- package/build/git/streaming-batch.js +73 -13
- package/package.json +1 -1
- package/skills/keiyaku/SKILL.md +1 -1
- package/skills/keiyaku-akuma/SKILL.md +3 -3
- package/skills/keiyaku-task/SKILL.md +4 -2
- package/skills/keiyaku-workflow/SKILL.md +88 -203
- package/build/core/entry.js +0 -305
- package/build/core/ledger-batch.js +0 -194
- package/build/core/ledger.js +0 -84
- package/build/core/projection/leash.js +0 -87
- package/build/core/ref-log.js +0 -119
- package/build/core/renew-session.js +0 -128
- package/build/core/status/ledger-batch.js +0 -1
- package/build/core/status/reconciliation.js +0 -137
package/build/cli/render/misc.js
CHANGED
|
@@ -3,6 +3,7 @@ import { RESPONSE_MARKERS } from "./response-style.js";
|
|
|
3
3
|
import { formatReview, HINTS_LIST_MAX_ITEMS, REVIEW_SECTION_TITLE, toReviewPayload, } from "./shared.js";
|
|
4
4
|
import { prependAddressReceipt, renderAddressCarrier } from "./address.js";
|
|
5
5
|
import { commissionSlug } from "../../core/ids.js";
|
|
6
|
+
import { renderAmendmentWarning } from "./amendment-warning.js";
|
|
6
7
|
export function buildErrorResponse(input) {
|
|
7
8
|
const shouldRaiseProtocolError = input.errorType === "runtime_error";
|
|
8
9
|
const text = input.errorCode === "PROJECTION_INCOMPATIBLE"
|
|
@@ -28,14 +29,17 @@ export function buildErrorResponse(input) {
|
|
|
28
29
|
}
|
|
29
30
|
function buildErrorText(input) {
|
|
30
31
|
const errorSection = buildSection("Error", input.message);
|
|
31
|
-
const
|
|
32
|
-
? buildSection("
|
|
32
|
+
const conflictSection = input.facts?.kind === "renew_conflict_scratch"
|
|
33
|
+
? buildSection("Conflict scratch", [
|
|
34
|
+
input.facts.scratchPath,
|
|
35
|
+
"",
|
|
33
36
|
"Conflicting paths:",
|
|
34
37
|
...input.facts.conflictPaths.map((filePath) => ` ${filePath}`),
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
"",
|
|
39
|
+
`Ledger: ${input.facts.observedLedgerHead}`,
|
|
40
|
+
`Delivery: ${input.facts.deliveryRef} at ${input.facts.oldHead}`,
|
|
41
|
+
`Target: ${input.facts.targetRef} at ${input.facts.newBase}`,
|
|
42
|
+
"Authoritative ledger and delivery refs were unchanged.",
|
|
39
43
|
].join("\n"))
|
|
40
44
|
: null;
|
|
41
45
|
const reviewSection = input.review ? buildSection(REVIEW_SECTION_TITLE, formatReview(input.review)) : null;
|
|
@@ -43,32 +47,22 @@ function buildErrorText(input) {
|
|
|
43
47
|
&& input.addressCarrier.binding.kind === "commission"
|
|
44
48
|
? input.addressCarrier
|
|
45
49
|
: undefined;
|
|
46
|
-
const
|
|
50
|
+
const renewAddress = commissionedCarrier
|
|
47
51
|
? `@${commissionedCarrier.place.display ?? commissionSlug(commissionedCarrier.binding.commissionId)}`
|
|
48
|
-
:
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"Or restore the pre-renew delivery:",
|
|
57
|
-
`» keiyaku ${recoveryAddress} renew --abort`,
|
|
58
|
-
]
|
|
59
|
-
: input.facts.nextAction === "continue-or-abort" ? [
|
|
60
|
-
`» keiyaku ${recoveryAddress} renew --continue`,
|
|
61
|
-
`» keiyaku ${recoveryAddress} renew --abort`,
|
|
62
|
-
] : [`» keiyaku ${recoveryAddress} renew --abort`])
|
|
52
|
+
: undefined;
|
|
53
|
+
const nextActionSection = input.facts?.kind === "renew_conflict_scratch" && renewAddress
|
|
54
|
+
? buildSection("Next action", [
|
|
55
|
+
"Resolve files in the conflict scratch, then:",
|
|
56
|
+
`» keiyaku ${renewAddress} renew --continue`,
|
|
57
|
+
"Or discard the conflict scratch:",
|
|
58
|
+
`» keiyaku ${renewAddress} renew --abort`,
|
|
59
|
+
])
|
|
63
60
|
: null;
|
|
64
|
-
const hints = input.facts?.kind === "
|
|
61
|
+
const hints = input.facts?.kind === "renew_conflict_scratch"
|
|
65
62
|
? []
|
|
66
63
|
: formatHints(input.hints, { maxItems: HINTS_LIST_MAX_ITEMS, maxItemChars: FORMAT_LIST_MAX_ITEM_CHARS });
|
|
67
|
-
if (input.facts?.kind === "renew_conflict") {
|
|
68
|
-
hints.push("your old head survives:", `» git log ${input.facts.recoveryRef}`);
|
|
69
|
-
}
|
|
70
64
|
const hintsSection = buildSection("Hints", hints);
|
|
71
|
-
const body = assembleResponse(colorizeErrorStatus(`${RESPONSE_MARKERS.failure} Failed [${input.errorCode}]`), "Request could not be completed.", [errorSection,
|
|
65
|
+
const body = assembleResponse(colorizeErrorStatus(`${RESPONSE_MARKERS.failure} Failed [${input.errorCode}]`), "Request could not be completed.", [errorSection, conflictSection, nextActionSection, reviewSection, hintsSection].filter((section) => section !== null));
|
|
72
66
|
return input.addressCarrier ? `${renderAddressCarrier(input.addressCarrier)}\n${body}` : body;
|
|
73
67
|
}
|
|
74
68
|
export function buildHelpResponse(input) {
|
|
@@ -82,7 +76,9 @@ export function buildLogResponse(result) {
|
|
|
82
76
|
const { address: _address, ...resultData } = result;
|
|
83
77
|
const payload = resultData;
|
|
84
78
|
return prependAddressReceipt({
|
|
85
|
-
text: result.
|
|
79
|
+
text: result.amendmentWarning
|
|
80
|
+
? `${result.markdown.trimEnd()}\n\nWarning\n${renderAmendmentWarning(result.amendmentWarning)}\n`
|
|
81
|
+
: result.markdown,
|
|
86
82
|
payload: buildPayload(payload),
|
|
87
83
|
}, result.address);
|
|
88
84
|
}
|
|
@@ -8,6 +8,11 @@ import { prependAddressReceipt } from "./address.js";
|
|
|
8
8
|
export function renderPetitionRenewedConsequence(input) {
|
|
9
9
|
return `renewed onto ${input.newBase.slice(0, 8)} · ${input.sealed?.receipts.length ?? 0} receipts replayed`;
|
|
10
10
|
}
|
|
11
|
+
export function renderPetitionRetryConsequence(reason) {
|
|
12
|
+
return reason === "target-drift"
|
|
13
|
+
? "rejected petition after target drift · contract active"
|
|
14
|
+
: "rejected petition after delivery drift · contract active";
|
|
15
|
+
}
|
|
11
16
|
function formatPetitionSealSource(source) {
|
|
12
17
|
return source.arc === null
|
|
13
18
|
? `no open arc · fence ${source.fence}`
|
|
@@ -210,6 +210,7 @@ export function renderProjectionActivity(activity, input) {
|
|
|
210
210
|
let priorCompletedRan;
|
|
211
211
|
let hasEndAnchor = false;
|
|
212
212
|
let lastRunningTool;
|
|
213
|
+
const interrupted = input.state === "dead" || input.state === "lost" || input.state === "dismissed";
|
|
213
214
|
const maxColumns = input.maxColumns ?? resolveLineColumns();
|
|
214
215
|
const entries = timelineEntries(activity);
|
|
215
216
|
const gapBeforeOrder = input.leadingOmittedCount ? activity.window[0]?.order : undefined;
|
|
@@ -244,14 +245,14 @@ export function renderProjectionActivity(activity, input) {
|
|
|
244
245
|
priorMinute = minute;
|
|
245
246
|
const spine = row.kind === "turn"
|
|
246
247
|
? "├"
|
|
247
|
-
:
|
|
248
|
+
: interrupted
|
|
248
249
|
? "┆"
|
|
249
250
|
: "│";
|
|
250
251
|
if (row.kind === "ran") {
|
|
251
252
|
const duration = formatActionDuration(row.durationMs);
|
|
252
253
|
const activityState = row.state === "completed"
|
|
253
254
|
? "completed"
|
|
254
|
-
:
|
|
255
|
+
: interrupted
|
|
255
256
|
? "interrupted"
|
|
256
257
|
: input.state === "stalled" || input.state === "unknown"
|
|
257
258
|
? "unresolved"
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { renderProjectionActivity } from "./projection-activity.js";
|
|
2
|
+
function fact(value) {
|
|
3
|
+
return value ?? "unavailable";
|
|
4
|
+
}
|
|
5
|
+
function consequenceLines(run) {
|
|
6
|
+
const consequences = run.consequences;
|
|
7
|
+
if (consequences === null)
|
|
8
|
+
return [];
|
|
9
|
+
if (consequences.retention === "unavailable") {
|
|
10
|
+
return [`consequences: unavailable · ${consequences.reason}`];
|
|
11
|
+
}
|
|
12
|
+
const retained = (name, value, detail) => value.retention === "retained" ? `${name}: retained · ${detail}` : `${name}: unavailable · ${value.reason}`;
|
|
13
|
+
return [
|
|
14
|
+
`review: unavailable · ${consequences.review.reason}`,
|
|
15
|
+
retained("petition", consequences.petition, consequences.petition.retention === "retained" ? `${consequences.petition.intent} · ${consequences.petition.objectId}` : ""),
|
|
16
|
+
retained("verdict", consequences.verdict, consequences.verdict.retention === "retained" ? `${consequences.verdict.result} · ${consequences.verdict.objectId}` : ""),
|
|
17
|
+
retained("claim", consequences.claim, consequences.claim.retention === "retained" ? `${consequences.claim.objectId} · ${consequences.claim.mergeCommit}` : ""),
|
|
18
|
+
retained("landed commit", consequences.landedCommit, consequences.landedCommit.retention === "retained" ? consequences.landedCommit.commit : ""),
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
function runLines(run) {
|
|
22
|
+
return [
|
|
23
|
+
`${run.id}${run.alias ? ` (${run.alias})` : ""} · ${run.outcome}`,
|
|
24
|
+
`akuma: ${fact(run.akuma)} · provider: ${fact(run.provider)}${run.pid === null ? "" : ` · pid: ${run.pid}`} · role: ${run.role}`,
|
|
25
|
+
`contract: ${fact(run.contractId)}`,
|
|
26
|
+
`created: ${fact(run.mintedAt)}${run.terminalAt ? ` · terminal: ${run.terminalAt}` : ""}`,
|
|
27
|
+
...(run.generation ? [`generation: ${run.generation.executionId} · created: ${run.generation.createdAt}${run.generation.adoptedAt ? ` · adopted: ${run.generation.adoptedAt}` : ""}`] : []),
|
|
28
|
+
`activity: ${run.activityRetention} · ${run.activityCount} retained${run.activityRange ? ` · ${run.activityRange.first}-${run.activityRange.last}` : ""}`,
|
|
29
|
+
...(run.telemetry ? [`telemetry: ${run.telemetry.inputTokens} in · ${run.telemetry.outputTokens} out${run.telemetry.cachedInputTokens !== undefined ? ` · ${run.telemetry.cachedInputTokens} cached` : ""}${run.telemetry.costUsd !== undefined ? ` · $${run.telemetry.costUsd.toFixed(2)}` : ""}`] : []),
|
|
30
|
+
...(run.artifact ? [`artifact: ${fact(run.artifact.id)} · ${run.artifact.retention}${run.artifact.path ? ` · path: ${run.artifact.path}` : ""}`] : []),
|
|
31
|
+
...consequenceLines(run),
|
|
32
|
+
...run.diagnostics.map((diagnostic) => `diagnostic: ${diagnostic}`),
|
|
33
|
+
];
|
|
34
|
+
}
|
|
35
|
+
export function renderProjectionHistoryList(runs) {
|
|
36
|
+
return runs.flatMap((run, index) => index === 0 ? runLines(run) : ["", ...runLines(run)]).join("\n");
|
|
37
|
+
}
|
|
38
|
+
export function renderProjectionHistoryDetail(detail) {
|
|
39
|
+
const lines = runLines(detail);
|
|
40
|
+
if (!detail.activity || detail.activity.retainedTimeline.length === 0)
|
|
41
|
+
return lines.join("\n");
|
|
42
|
+
const state = detail.outcome === "done" ? "returned"
|
|
43
|
+
: detail.outcome === "out" ? "running"
|
|
44
|
+
: detail.outcome === "failed" || detail.outcome === "dead" ? "dead"
|
|
45
|
+
: detail.outcome === "lost" ? "lost"
|
|
46
|
+
: detail.outcome === "killed" || detail.outcome === "dismissed" ? "dismissed"
|
|
47
|
+
: detail.outcome === "startup-timeout" ? "stalled"
|
|
48
|
+
: "unknown";
|
|
49
|
+
const activity = renderProjectionActivity({
|
|
50
|
+
...detail.activity,
|
|
51
|
+
timeline: detail.activity.retainedTimeline,
|
|
52
|
+
omittedSettledCount: 0,
|
|
53
|
+
}, {
|
|
54
|
+
anchorMs: Date.now(),
|
|
55
|
+
state,
|
|
56
|
+
showPlan: false,
|
|
57
|
+
showSilence: false,
|
|
58
|
+
showTerminalFiles: false,
|
|
59
|
+
});
|
|
60
|
+
return [...lines, "", ...activity.lines].join("\n");
|
|
61
|
+
}
|
|
62
|
+
export function projectionHistoryJson(value) {
|
|
63
|
+
return `${JSON.stringify(value)}\n`;
|
|
64
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { KEIYAKU_FILE } from "../../keiyaku.js";
|
|
2
|
+
import { isCompleteLifecycleOutcome } from "../../core/outcome-base.js";
|
|
2
3
|
import { commissionSlug, formatCommissionCoordinate } from "../../core/ids.js";
|
|
3
4
|
import { assembleResponse, buildSection, DISPLAY_TEXT_MAX_CHARS, FORMAT_LIST_MAX_ITEM_CHARS, FORMAT_LIST_MAX_ITEMS, formatMaybe, formatWarnings, shellQuote, truncateForDisplay, } from "./format.js";
|
|
4
5
|
import { WARNING_SECTION_TITLE } from "./response-style.js";
|
|
@@ -63,6 +64,26 @@ export function buildBindResponse(result, cwd) {
|
|
|
63
64
|
...(overlapWarnings.length > 0 ? ["Warnings:", ...overlapWarnings] : []),
|
|
64
65
|
].join("\n"), payload);
|
|
65
66
|
}
|
|
67
|
+
export function buildContainedBindResponse(result) {
|
|
68
|
+
const payload = {
|
|
69
|
+
family: result.family,
|
|
70
|
+
completion: result.completion,
|
|
71
|
+
committed: result.committed,
|
|
72
|
+
heads: result.heads,
|
|
73
|
+
reconciliationKey: result.reconciliationKey,
|
|
74
|
+
prerequisites: result.prerequisites,
|
|
75
|
+
downstream: result.downstream,
|
|
76
|
+
replay: result.replay,
|
|
77
|
+
carrier: result.carrier,
|
|
78
|
+
cancellationObserved: result.cancellationObserved,
|
|
79
|
+
};
|
|
80
|
+
return coreTextResponse(`Bind committed with incomplete replay · head ${result.committed.head} · reconcile ${result.reconciliationKey}`, payload);
|
|
81
|
+
}
|
|
82
|
+
export function buildBindOutcomeResponse(result, cwd) {
|
|
83
|
+
return isCompleteLifecycleOutcome(result)
|
|
84
|
+
? buildBindResponse(result, cwd)
|
|
85
|
+
: buildContainedBindResponse(result);
|
|
86
|
+
}
|
|
66
87
|
function renderScopeOverlapWarnings(overlaps) {
|
|
67
88
|
const overlapsByCounterparty = new Map();
|
|
68
89
|
for (const overlap of overlaps) {
|
|
@@ -105,10 +126,8 @@ export function buildForfeitResponse(result) {
|
|
|
105
126
|
`Could not remove contract worktree ${result.cleanup.worktreeRemoveFailure.path}: ${result.cleanup.worktreeRemoveFailure.reason}`,
|
|
106
127
|
]
|
|
107
128
|
: []),
|
|
108
|
-
...(result.cleanup.
|
|
109
|
-
? [
|
|
110
|
-
`Could not delete contract branch: ${redactBranchReference(result.cleanup.branchDeleteFailure.reason, result.cleanup.branchDeleteFailure.name)}`,
|
|
111
|
-
]
|
|
129
|
+
...(result.cleanup.deliveryRef.status === "mismatch"
|
|
130
|
+
? [`Delivery ref ${result.cleanup.deliveryRef.mismatch.ref} remains present at ${result.cleanup.deliveryRef.mismatch.observed.head}; terminal replay preserved it as a projected-surface mismatch.`]
|
|
112
131
|
: []),
|
|
113
132
|
];
|
|
114
133
|
if (warnings.length === 0) {
|
|
@@ -117,11 +136,6 @@ export function buildForfeitResponse(result) {
|
|
|
117
136
|
const warningSection = buildSection(WARNING_SECTION_TITLE, formatWarnings(warnings));
|
|
118
137
|
return prependAddressReceipt(coreTextResponse(assembleResponse(base, "", [warningSection].filter((section) => section !== null)), payload), result.address);
|
|
119
138
|
}
|
|
120
|
-
function redactBranchReference(message, branch) {
|
|
121
|
-
return message
|
|
122
|
-
.replaceAll(`refs/heads/${branch}`, "contract branch")
|
|
123
|
-
.replaceAll(branch, "contract branch");
|
|
124
|
-
}
|
|
125
139
|
export const RULES_SECTION_MAX_CHARS = 5000;
|
|
126
140
|
export const INFO_SECTION_TITLE = "Info";
|
|
127
141
|
export const HINTS_SECTION_TITLE = "Hints";
|
|
@@ -7,7 +7,6 @@ import { renderTerminalFailureFace, terminalFailureCodeSuffix } from "./terminal
|
|
|
7
7
|
import { formatTellCommand } from "./shared.js";
|
|
8
8
|
export const STATUS_DISEASES_SECTION_TITLE = "Diseases";
|
|
9
9
|
export const STATUS_PROJECTION_SECTION_TITLE = "akuma";
|
|
10
|
-
export const STATUS_CLAIM_RECEIPTS_SECTION_TITLE = "claim receipts";
|
|
11
10
|
function projectionGlyph(state) {
|
|
12
11
|
switch (state) {
|
|
13
12
|
case "out":
|
|
@@ -37,15 +36,19 @@ export function renderSettingsDiseasesSection(diseases, taskDiseases = []) {
|
|
|
37
36
|
return `${STATUS_DISEASES_SECTION_TITLE}\n${lines.join("\n")}\n`;
|
|
38
37
|
}
|
|
39
38
|
function renderTaskStatusSection(tasks) {
|
|
40
|
-
if (!tasks || tasks.inProgress + tasks.ready + tasks.blocked === 0)
|
|
39
|
+
if (!tasks || tasks.inProgress + tasks.onHold + tasks.ready + tasks.blocked === 0)
|
|
41
40
|
return "";
|
|
42
41
|
const segments = [
|
|
43
42
|
tasks.inProgress > 0 ? `${tasks.inProgress} in_progress` : undefined,
|
|
43
|
+
tasks.onHold > 0 ? `${tasks.onHold} on hold` : undefined,
|
|
44
44
|
tasks.ready > 0 ? `${tasks.ready} ready` : undefined,
|
|
45
45
|
tasks.blocked > 0 ? `${tasks.blocked} blocked` : undefined,
|
|
46
46
|
].filter((segment) => segment !== undefined);
|
|
47
47
|
const lines = [`tasks · ${segments.join(" / ")}`];
|
|
48
|
-
lines.push(...tasks.topTasks.map((task) =>
|
|
48
|
+
lines.push(...tasks.topTasks.map((task) => {
|
|
49
|
+
const onHold = task.state === "on_hold";
|
|
50
|
+
return ` ${task.id} · P${task.pri} · ${onHold ? "on hold" : "in_progress"} · age ${formatAgeMs(task.ageMs)} · ${onHold ? "updated" : "active"} ${formatAgeMs(task.activityAgeMs)} · ${task.title}`;
|
|
51
|
+
}));
|
|
49
52
|
if (tasks.omitted > 0) {
|
|
50
53
|
lines.push(` · +${tasks.omitted} more — keiyaku task ls`);
|
|
51
54
|
}
|
|
@@ -99,10 +102,9 @@ function renderProjectionAge(row) {
|
|
|
99
102
|
return facts;
|
|
100
103
|
}
|
|
101
104
|
function renderProjectionTellCounts(row) {
|
|
102
|
-
const { inbox, inflight, submitted, consumed } = row.tellCounts;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return ` tell ${inbox}▸${inflight}▸${submitted}▸${consumed}`;
|
|
105
|
+
const { inbox, inflight, submitted, seen, consumed } = row.tellCounts;
|
|
106
|
+
const total = inbox + inflight + submitted + seen + consumed;
|
|
107
|
+
return total === 0 ? "" : ` tell ${total} told`;
|
|
106
108
|
}
|
|
107
109
|
function projectionActivityState(row) {
|
|
108
110
|
switch (row.state) {
|
|
@@ -194,15 +196,6 @@ export function renderProjectionStatusSection(board) {
|
|
|
194
196
|
lines.push(omission);
|
|
195
197
|
return `${STATUS_PROJECTION_SECTION_TITLE}\n${lines.join("\n")}\n`;
|
|
196
198
|
}
|
|
197
|
-
function renderClaimReconciliationSection(recon) {
|
|
198
|
-
if (!recon)
|
|
199
|
-
return "";
|
|
200
|
-
const lines = recon.unclaimedSegments.map((seg) => `${recon.defaultBranch} ${shortCommitHash(seg.oldHead)}▸${shortCommitHash(seg.newHead)} · ${seg.commitCount} commits · 无 claim 收据`);
|
|
201
|
-
lines.push(...recon.receiptIssues.map((issue) => `receipt line ${issue.line} · ${issue.reason}`));
|
|
202
|
-
if (lines.length === 0)
|
|
203
|
-
return "";
|
|
204
|
-
return `${STATUS_CLAIM_RECEIPTS_SECTION_TITLE}\n${lines.join("\n")}\n`;
|
|
205
|
-
}
|
|
206
199
|
/**
|
|
207
200
|
* Status mouth: kanshi board plus optional diseases section.
|
|
208
201
|
* Healthy boards (no diseases) are byte-identical to renderKanshiBoard alone.
|
package/build/cli/render/task.js
CHANGED
|
@@ -8,13 +8,29 @@ export function deriveTaskDisplay(task) {
|
|
|
8
8
|
return display === "bound" ? `bound(${shortContractId(task.contractId)})` : display;
|
|
9
9
|
}
|
|
10
10
|
function renderTaskRowWithId(task, id) {
|
|
11
|
-
return `${id} · P${task.pri} · ${deriveTaskDisplay(task)} · ${task.title}`;
|
|
11
|
+
return `${id} · ${task.namespace ?? "hub"} · P${task.pri} · ${deriveTaskDisplay(task)} · ${task.title}`;
|
|
12
12
|
}
|
|
13
13
|
export function renderTaskListRow(task) {
|
|
14
|
-
return renderTaskRowWithId(task, task.
|
|
14
|
+
return renderTaskRowWithId(task, task.coordinate);
|
|
15
15
|
}
|
|
16
16
|
export function renderTaskMutationRow(task) {
|
|
17
|
-
return renderTaskRowWithId(task, task.
|
|
17
|
+
return renderTaskRowWithId(task, task.coordinate);
|
|
18
|
+
}
|
|
19
|
+
export function renderTaskUpdate(result) {
|
|
20
|
+
const lines = [renderTaskMutationRow(result.task)];
|
|
21
|
+
if (result.bodyChange) {
|
|
22
|
+
lines.push(`body · +${result.bodyChange.diffstat.additions} −${result.bodyChange.diffstat.deletions} lines`);
|
|
23
|
+
for (const section of result.bodyChange.removedSections) {
|
|
24
|
+
lines.push(`▲ section removed: ${section}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return lines.join("\n");
|
|
28
|
+
}
|
|
29
|
+
export function renderTaskUpdateJson(result) {
|
|
30
|
+
return JSON.stringify({
|
|
31
|
+
...taskJson(result.task),
|
|
32
|
+
...(result.bodyChange === undefined ? {} : { bodyChange: result.bodyChange }),
|
|
33
|
+
});
|
|
18
34
|
}
|
|
19
35
|
export function renderTaskRow(task, completeId = false) {
|
|
20
36
|
return completeId ? renderTaskMutationRow(task) : renderTaskListRow(task);
|
|
@@ -28,24 +44,20 @@ export function renderTaskList(tasks, options = {}) {
|
|
|
28
44
|
export function renderSelectedTaskList(tasks) {
|
|
29
45
|
return tasks.map(renderTaskListRow).join("\n");
|
|
30
46
|
}
|
|
31
|
-
function renderIds(ids) {
|
|
32
|
-
return ids.length === 0 ? "(none)" : ids.join(", ");
|
|
33
|
-
}
|
|
34
47
|
function renderTaskDetails(task) {
|
|
35
48
|
const released = new Set(task.releasedNeeds);
|
|
36
|
-
const needs = task.needs.length === 0
|
|
37
|
-
? "(none)"
|
|
38
|
-
: task.needs
|
|
39
|
-
.map((id) => `${id}${released.has(id) ? " (dropped)" : ""}`)
|
|
40
|
-
.join(", ");
|
|
41
49
|
return [
|
|
42
|
-
`${task.
|
|
50
|
+
`${task.coordinate} · ${task.title}`,
|
|
51
|
+
`namespace: ${task.namespace ?? "(hub)"}`,
|
|
43
52
|
`state: ${deriveTaskDisplay(task)}`,
|
|
44
53
|
`priority: ${task.pri}`,
|
|
45
|
-
`needs: ${needs}
|
|
46
|
-
`blocks: ${
|
|
47
|
-
|
|
48
|
-
`from: ${
|
|
54
|
+
...(task.needs.length === 0 ? [] : [`needs: ${task.needs.map((id) => `${id}${released.has(id) ? " (dropped)" : ""}`).join(", ")}`]),
|
|
55
|
+
...(task.blocks.length === 0 ? [] : [`blocks: ${task.blocks.join(", ")}`]),
|
|
56
|
+
...(task.parent === null ? [] : [`parent: ${task.parent}`]),
|
|
57
|
+
...(task.from.length === 0 ? [] : [`from: ${task.from.join(", ")}`]),
|
|
58
|
+
...(task.supersedes.length === 0 ? [] : [`supersedes: ${task.supersedes.join(", ")}`]),
|
|
59
|
+
...(task.supersededBy.length === 0 ? [] : [`superseded by: ${task.supersededBy.join(", ")}`]),
|
|
60
|
+
...(task.relatedTasks.length === 0 ? [] : [`relates to: ${task.relatedTasks.join(", ")}`]),
|
|
49
61
|
`created: ${task.createdAt} by ${task.creator}`,
|
|
50
62
|
"",
|
|
51
63
|
task.body,
|
|
@@ -55,16 +67,24 @@ function renderTreeNode(node, prefix, last) {
|
|
|
55
67
|
const branch = last ? "`- " : "|- ";
|
|
56
68
|
const nestedPrefix = `${prefix}${last ? " " : "| "}`;
|
|
57
69
|
const task = node.task;
|
|
58
|
-
const released = new Set(task.releasedNeeds);
|
|
59
|
-
const needs = task.needs.length === 0
|
|
60
|
-
? "(none)"
|
|
61
|
-
: task.needs.map((id) => `${id}${released.has(id) ? " (dropped)" : ""}`).join(", ");
|
|
62
70
|
const lines = [
|
|
63
|
-
`${prefix}${branch}${task.
|
|
64
|
-
`${nestedPrefix}needs: ${needs}`,
|
|
65
|
-
`${nestedPrefix}blocks: ${renderIds(task.blocks)}`,
|
|
66
|
-
`${nestedPrefix}from: ${renderIds(task.from)}`,
|
|
71
|
+
`${prefix}${branch}${task.coordinate} · ${deriveTaskDisplay(task)} · P${task.pri} · ${task.title}`,
|
|
67
72
|
];
|
|
73
|
+
const released = new Set(task.releasedNeeds);
|
|
74
|
+
if (task.needs.length > 0)
|
|
75
|
+
lines.push(`${nestedPrefix}needs: ${task.needs.map((id) => `${id}${released.has(id) ? " (dropped)" : ""}`).join(", ")}`);
|
|
76
|
+
if (task.blocks.length > 0)
|
|
77
|
+
lines.push(`${nestedPrefix}blocks: ${task.blocks.join(", ")}`);
|
|
78
|
+
if (task.parent !== null)
|
|
79
|
+
lines.push(`${nestedPrefix}parent: ${task.parent}`);
|
|
80
|
+
if (task.from.length > 0)
|
|
81
|
+
lines.push(`${nestedPrefix}from: ${task.from.join(", ")}`);
|
|
82
|
+
if (task.supersedes.length > 0)
|
|
83
|
+
lines.push(`${nestedPrefix}supersedes: ${task.supersedes.join(", ")}`);
|
|
84
|
+
if (task.supersededBy.length > 0)
|
|
85
|
+
lines.push(`${nestedPrefix}superseded by: ${task.supersededBy.join(", ")}`);
|
|
86
|
+
if (task.relatedTasks.length > 0)
|
|
87
|
+
lines.push(`${nestedPrefix}relates to: ${task.relatedTasks.join(", ")}`);
|
|
68
88
|
node.children.forEach((child, index) => lines.push(...renderTreeNode(child, nestedPrefix, index === node.children.length - 1)));
|
|
69
89
|
return lines;
|
|
70
90
|
}
|
|
@@ -74,15 +94,17 @@ function treeDiagnostic(diagnostic) {
|
|
|
74
94
|
}
|
|
75
95
|
export function renderTaskShow(task, tree) {
|
|
76
96
|
const treeLines = tree.descendants.length === 0
|
|
77
|
-
? [
|
|
97
|
+
? []
|
|
78
98
|
: ["children tree:", ...tree.descendants.flatMap((node, index) => renderTreeNode(node, "", index === tree.descendants.length - 1))];
|
|
79
99
|
if (tree.diagnostics.length > 0)
|
|
80
100
|
treeLines.push("tree diagnostics:", ...tree.diagnostics.map(treeDiagnostic));
|
|
81
|
-
return [...renderTaskDetails(task), "", ...treeLines].join("\n");
|
|
101
|
+
return [...renderTaskDetails(task), ...(treeLines.length === 0 ? [] : ["", ...treeLines])].join("\n");
|
|
82
102
|
}
|
|
83
103
|
export function taskJson(task) {
|
|
84
104
|
return {
|
|
85
105
|
id: task.id,
|
|
106
|
+
namespace: task.namespace,
|
|
107
|
+
coordinate: task.coordinate,
|
|
86
108
|
title: task.title,
|
|
87
109
|
state: task.state,
|
|
88
110
|
display: deriveTaskDisplay(task),
|
|
@@ -91,6 +113,9 @@ export function taskJson(task) {
|
|
|
91
113
|
blocks: [...task.blocks],
|
|
92
114
|
parent: task.parent,
|
|
93
115
|
from: [...task.from],
|
|
116
|
+
supersedes: [...task.supersedes],
|
|
117
|
+
supersededBy: [...task.supersededBy],
|
|
118
|
+
relatesTo: [...task.relatedTasks],
|
|
94
119
|
contractId: task.contractId ?? null,
|
|
95
120
|
createdAt: task.createdAt,
|
|
96
121
|
updatedAt: task.updatedAt ?? task.createdAt,
|
|
@@ -3,7 +3,7 @@ export function terminalFailureCodeSuffix(code) {
|
|
|
3
3
|
return code.startsWith("SUBAGENT_") ? code.slice("SUBAGENT_".length) : code;
|
|
4
4
|
}
|
|
5
5
|
export function terminalFailureColdStatement(failure) {
|
|
6
|
-
if (failure.publicCause?.
|
|
6
|
+
if (failure.publicCause?.code === "rate_limit_exhausted") {
|
|
7
7
|
return "the provider rate limit is exhausted";
|
|
8
8
|
}
|
|
9
9
|
if (failure.class === "runner") {
|
|
@@ -33,6 +33,8 @@ function terminalFailureEvidence(failure, statement) {
|
|
|
33
33
|
&& failure.code === "SUBAGENT_NON_ZERO_EXIT"
|
|
34
34
|
&& failure.exitCode !== undefined;
|
|
35
35
|
const parts = [];
|
|
36
|
+
if (failure.message)
|
|
37
|
+
parts.push(failure.message);
|
|
36
38
|
if (failure.timeoutMs !== undefined) {
|
|
37
39
|
parts.push(failure.code === "SUBAGENT_POLICY_BUDGET" ? `budget ${failure.timeoutMs}ms` : `idle ${failure.timeoutMs}ms`);
|
|
38
40
|
}
|
package/build/cli/render/wait.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { formatTimelineDuration, renderPendingProjectionTell, renderProjectionActivity, } from "./projection-activity.js";
|
|
2
2
|
import { displayColumns, resolveLineColumns, truncateColumns } from "./line-width.js";
|
|
3
|
-
import { formatTellCommand, projectionRejoinHintLines, textResponse } from "./shared.js";
|
|
3
|
+
import { coreTextResponse, formatTellCommand, projectionRejoinHintLines, textResponse } from "./shared.js";
|
|
4
4
|
import { renderTerminalFailureFace } from "./terminal-failure.js";
|
|
5
|
-
const WAIT_HEADER_MAX_COLUMNS = 60;
|
|
6
5
|
function shortAddress(projectionId) {
|
|
7
6
|
return /\/([0-9a-f]{8})$/.exec(projectionId)?.[1] ?? projectionId;
|
|
8
7
|
}
|
|
@@ -35,8 +34,7 @@ function projectionIdentityParts(projectionId) {
|
|
|
35
34
|
const match = /^(.*)\/([0-9a-f]{8})$/.exec(projectionId);
|
|
36
35
|
return match ? { slug: match[1], shortId: match[2] } : { slug: "", shortId: projectionId };
|
|
37
36
|
}
|
|
38
|
-
function waitHeader(projectionId, akuma, snapshot,
|
|
39
|
-
const maxColumns = Math.min(WAIT_HEADER_MAX_COLUMNS, outputColumns);
|
|
37
|
+
function waitHeader(projectionId, akuma, snapshot, maxColumns) {
|
|
40
38
|
const state = waitStateText(snapshot);
|
|
41
39
|
const identity = projectionIdentityParts(projectionId);
|
|
42
40
|
// Slug often mirrors the Akuma name; print once when they are the same fact.
|
|
@@ -237,7 +235,7 @@ export function buildWaitResponse(projectionId, result, options = {}) {
|
|
|
237
235
|
if (nextActions.length > 0)
|
|
238
236
|
lines.push("");
|
|
239
237
|
lines.push(...nextActions);
|
|
240
|
-
const response =
|
|
238
|
+
const response = coreTextResponse(lines.join("\n"), result);
|
|
241
239
|
if (snapshot.phase === "dismissed")
|
|
242
240
|
return { ...response, exitCode: 130 };
|
|
243
241
|
if (["failed", "lost", "startup-timeout", "unknown"].includes(snapshot.phase)) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const SUBAGENT_SAFE_COMMANDS = new Set(["status", "log", "guide", "dump-env", "wait"]);
|
|
1
|
+
const SUBAGENT_SAFE_COMMANDS = new Set(["status", "history", "log", "guide", "dump-env", "wait"]);
|
|
2
2
|
const SUBAGENT_SAFE_FLAGS = new Set(["--help", "-h", "--version"]);
|
|
3
3
|
function isSubagentSafeCommand(args) {
|
|
4
4
|
if (args.length === 0)
|
package/build/cli/types.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const TASK_SUBCOMMANDS = ["add", "show", "ls", "log", "start", "stop", "done", "drop", "update", "doctor"];
|
|
1
|
+
export const TASK_SUBCOMMANDS = ["add", "show", "ls", "log", "start", "stop", "hold", "resume", "done", "drop", "update", "doctor"];
|
package/build/config/env-keys.js
CHANGED
|
@@ -22,6 +22,7 @@ export const ENV_KEYS = {
|
|
|
22
22
|
REVIEW_ENABLED: "KEIYAKU_REVIEW_ENABLED",
|
|
23
23
|
REVIEW_MIN_LINES: "KEIYAKU_REVIEW_MIN_LINES",
|
|
24
24
|
REVIEW_RESUME_SESSION: "KEIYAKU_REVIEW_RESUME_SESSION",
|
|
25
|
+
AMENDMENT_WARNING_THRESHOLD: "KEIYAKU_AMENDMENT_WARNING_THRESHOLD",
|
|
25
26
|
};
|
|
26
27
|
const ENV_KEY_ENTRIES = [
|
|
27
28
|
{ key: ENV_KEYS.AGENT_OVERRIDE, defaultValue: "", description: "Override default agent name", category: "subagent" },
|
|
@@ -34,6 +35,7 @@ const ENV_KEY_ENTRIES = [
|
|
|
34
35
|
{ key: ENV_KEYS.REVIEW_ENABLED, defaultValue: "1", description: "Run the reviewer gate when set to 1", category: "workflow" },
|
|
35
36
|
{ key: ENV_KEYS.REVIEW_MIN_LINES, defaultValue: "200", description: "Minimum changed lines required before running the reviewer gate", category: "workflow" },
|
|
36
37
|
{ key: ENV_KEYS.REVIEW_RESUME_SESSION, defaultValue: "1", description: "Resume reviewer sessions from the prior persisted response path when set to 1", category: "workflow" },
|
|
38
|
+
{ key: ENV_KEYS.AMENDMENT_WARNING_THRESHOLD, defaultValue: "5", description: "Advisory amendment-count threshold for open contracts", category: "workflow" },
|
|
37
39
|
{ key: ENV_KEYS.DEBUG_LOG_PATH, defaultValue: "", description: "Optional debug log output file path", category: "debug" },
|
|
38
40
|
{ key: ENV_KEYS.TEST_SILENT, defaultValue: "0", description: "Suppress progress logs during tests when set to 1", category: "debug" },
|
|
39
41
|
{ key: ENV_KEYS.GIT_TIMEOUT_MS, defaultValue: "15000", description: "Git command timeout in milliseconds", category: "git" },
|
package/build/config/env.js
CHANGED
|
@@ -95,6 +95,22 @@ function positiveIntEnv(key) {
|
|
|
95
95
|
}
|
|
96
96
|
});
|
|
97
97
|
}
|
|
98
|
+
function strictPositiveIntEnv(key) {
|
|
99
|
+
return z
|
|
100
|
+
.string()
|
|
101
|
+
.default(getEnvDefaultValue(key))
|
|
102
|
+
.transform((value, ctx) => {
|
|
103
|
+
const trimmed = value.trim();
|
|
104
|
+
const parsed = Number(trimmed);
|
|
105
|
+
if (/^\d+$/.test(trimmed) && Number.isSafeInteger(parsed) && parsed > 0)
|
|
106
|
+
return parsed;
|
|
107
|
+
ctx.addIssue({
|
|
108
|
+
code: z.ZodIssueCode.custom,
|
|
109
|
+
message: `${key} must be a positive integer, received '${value}'.`,
|
|
110
|
+
});
|
|
111
|
+
return z.NEVER;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
98
114
|
function parseNonNegativeInt(value, key) {
|
|
99
115
|
const trimmed = value.trim();
|
|
100
116
|
const parsed = Number.parseInt(trimmed, 10);
|
|
@@ -166,6 +182,9 @@ const reviewSchema = z.object({
|
|
|
166
182
|
minLines: nonNegativeIntEnv(ENV_KEYS.REVIEW_MIN_LINES),
|
|
167
183
|
resumeSession: booleanFlagEnv(ENV_KEYS.REVIEW_RESUME_SESSION),
|
|
168
184
|
});
|
|
185
|
+
const amendmentWarningSchema = z.object({
|
|
186
|
+
threshold: strictPositiveIntEnv(ENV_KEYS.AMENDMENT_WARNING_THRESHOLD),
|
|
187
|
+
});
|
|
169
188
|
const terminalSchema = z.object({
|
|
170
189
|
noColor: z.string().optional(),
|
|
171
190
|
forceColor: z.string().optional(),
|
|
@@ -188,6 +207,7 @@ const envSchema = z
|
|
|
188
207
|
[ENV_KEYS.REVIEW_ENABLED]: z.string().optional(),
|
|
189
208
|
[ENV_KEYS.REVIEW_MIN_LINES]: z.string().optional(),
|
|
190
209
|
[ENV_KEYS.REVIEW_RESUME_SESSION]: z.string().optional(),
|
|
210
|
+
[ENV_KEYS.AMENDMENT_WARNING_THRESHOLD]: z.string().optional(),
|
|
191
211
|
NO_COLOR: z.string().optional(),
|
|
192
212
|
FORCE_COLOR: z.string().optional(),
|
|
193
213
|
TERM: z.string().optional(),
|
|
@@ -222,6 +242,9 @@ const envSchema = z
|
|
|
222
242
|
minLines: rawEnv[ENV_KEYS.REVIEW_MIN_LINES],
|
|
223
243
|
resumeSession: rawEnv[ENV_KEYS.REVIEW_RESUME_SESSION],
|
|
224
244
|
}),
|
|
245
|
+
amendmentWarning: amendmentWarningSchema.parse({
|
|
246
|
+
threshold: rawEnv[ENV_KEYS.AMENDMENT_WARNING_THRESHOLD],
|
|
247
|
+
}),
|
|
225
248
|
terminal: terminalSchema.parse({
|
|
226
249
|
noColor: rawEnv.NO_COLOR,
|
|
227
250
|
forceColor: rawEnv.FORCE_COLOR,
|
|
@@ -55,8 +55,10 @@ const gateCommandSchema = z
|
|
|
55
55
|
const gateSchema = z
|
|
56
56
|
.object({
|
|
57
57
|
commands: z.array(gateCommandSchema).optional(),
|
|
58
|
+
timeoutMs: z.number().int("timeoutMs must be an integer.").min(1).max(3_600_000).optional(),
|
|
58
59
|
})
|
|
59
|
-
.strict()
|
|
60
|
+
.strict()
|
|
61
|
+
.transform((value) => ({ ...value, timeoutMs: value.timeoutMs ?? 300_000 }));
|
|
60
62
|
const WORKTREE_BOOTSTRAP_DEFAULT_TIMEOUT_MS = 300_000;
|
|
61
63
|
const WORKTREE_BOOTSTRAP_MIN_TIMEOUT_MS = 1;
|
|
62
64
|
const WORKTREE_BOOTSTRAP_MAX_TIMEOUT_MS = 3_600_000;
|