@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
|
@@ -1,114 +1,433 @@
|
|
|
1
1
|
import { asMessage, FlowError } from "../../flow-error.js";
|
|
2
|
-
|
|
2
|
+
import { shortCommitHash } from "../../git/commits.js";
|
|
3
|
+
function shortRef(ref) {
|
|
4
|
+
return ref.replace(/^refs\/heads\//, "");
|
|
5
|
+
}
|
|
6
|
+
function formatDuration(ms) {
|
|
7
|
+
if (ms < 1000)
|
|
8
|
+
return `${ms}ms`;
|
|
9
|
+
const seconds = ms / 1000;
|
|
10
|
+
if (seconds < 60)
|
|
11
|
+
return `${seconds.toFixed(seconds < 10 ? 1 : 0)}s`;
|
|
12
|
+
const minutes = Math.floor(seconds / 60);
|
|
13
|
+
const rem = Math.round(seconds % 60);
|
|
14
|
+
return `${minutes}m${rem.toString().padStart(2, "0")}s`;
|
|
15
|
+
}
|
|
16
|
+
function formatBytes(bytes) {
|
|
17
|
+
if (bytes < 1024)
|
|
18
|
+
return `${bytes} bytes`;
|
|
19
|
+
const kib = bytes / 1024;
|
|
20
|
+
if (kib < 1024)
|
|
21
|
+
return `${kib < 10 ? kib.toFixed(1) : Math.round(kib)} KiB`;
|
|
22
|
+
const mib = kib / 1024;
|
|
23
|
+
return `${mib < 10 ? mib.toFixed(1) : Math.round(mib)} MiB`;
|
|
24
|
+
}
|
|
25
|
+
function padLabel(label, width) {
|
|
26
|
+
return label.length >= width ? label : `${label}${" ".repeat(width - label.length)}`;
|
|
27
|
+
}
|
|
28
|
+
function scopeMatchLabel(file) {
|
|
29
|
+
if (file.matcher.decisivePattern) {
|
|
30
|
+
const effect = file.matcher.decisivePattern.effect === "exclude" ? "excluded by" : "matched";
|
|
31
|
+
return `${effect}: ${file.matcher.decisivePattern.pattern}`;
|
|
32
|
+
}
|
|
33
|
+
if (file.class === "downgraded")
|
|
34
|
+
return "no declared term · explained companions only";
|
|
35
|
+
return "no declared term";
|
|
36
|
+
}
|
|
37
|
+
function explanationLine(item) {
|
|
38
|
+
if (item.kind === "file-rename")
|
|
39
|
+
return `rename ${item.from} -> ${item.to} (${item.similarity}%)`;
|
|
40
|
+
if (item.kind === "symbol-rename") {
|
|
41
|
+
return `symbol rename ${item.from} -> ${item.to} · h${item.hunk} old:${item.oldLine ?? "-"} new:${item.newLine ?? "-"}`;
|
|
42
|
+
}
|
|
43
|
+
return `import · h${item.hunk} old:${item.oldLine ?? "-"} new:${item.newLine ?? "-"}`;
|
|
44
|
+
}
|
|
45
|
+
function residueSummary(file) {
|
|
46
|
+
if (file.class !== "violated" || file.residue.length === 0)
|
|
47
|
+
return null;
|
|
48
|
+
const hunks = [...new Set(file.residue.map((item) => item.hunk).filter((hunk) => hunk >= 0))].sort((a, b) => a - b);
|
|
49
|
+
if (file.residue.some((item) => item.kind === "binary")) {
|
|
50
|
+
return `unexplained: binary content changed`;
|
|
51
|
+
}
|
|
52
|
+
if (hunks.length === 0)
|
|
53
|
+
return `unexplained: ${file.residue.length} changes`;
|
|
54
|
+
return `unexplained: ${file.residue.length} lines across hunk ${hunks.join(", ")}`;
|
|
55
|
+
}
|
|
56
|
+
function indentBlock(text, prefix = " ") {
|
|
57
|
+
return text.split("\n").map((line) => `${prefix}${line}`);
|
|
58
|
+
}
|
|
59
|
+
function selectedFor(file, report) {
|
|
60
|
+
return report.presentation?.selected.filter((item) => item.path === file.path) ?? [];
|
|
61
|
+
}
|
|
62
|
+
function omissionsFor(file, report) {
|
|
63
|
+
return report.presentation?.omissions.filter((item) => item.path === file.path) ?? [];
|
|
64
|
+
}
|
|
65
|
+
function renderFileBlock(file, report) {
|
|
66
|
+
const rename = file.oldPath ? `${file.oldPath} -> ` : "";
|
|
67
|
+
const header = ` ${file.status} ${rename}${file.path}`.padEnd(62) + `+${file.stats.insertions} -${file.stats.deletions}`;
|
|
68
|
+
const lines = [header, ` ${scopeMatchLabel(file)}`];
|
|
69
|
+
for (const explanation of file.explanations)
|
|
70
|
+
lines.push(` ${explanationLine(explanation)}`);
|
|
71
|
+
const residue = residueSummary(file);
|
|
72
|
+
if (residue)
|
|
73
|
+
lines.push(` ${residue}`);
|
|
74
|
+
const selected = selectedFor(file, report);
|
|
75
|
+
const omissions = omissionsFor(file, report);
|
|
76
|
+
for (const item of selected) {
|
|
77
|
+
if (item.hunk === null)
|
|
78
|
+
continue;
|
|
79
|
+
lines.push("");
|
|
80
|
+
lines.push(...indentBlock(item.content));
|
|
81
|
+
}
|
|
82
|
+
if (omissions.length > 0) {
|
|
83
|
+
const omittedHunks = omissions.filter((item) => item.hunk !== null).length;
|
|
84
|
+
const omittedBytes = omissions.reduce((sum, item) => sum + item.bytes, 0);
|
|
85
|
+
const subject = omissions.every((item) => item.hunk === null)
|
|
86
|
+
? "file content omitted"
|
|
87
|
+
: `${omittedHunks} hunk${omittedHunks === 1 ? "" : "s"} omitted`;
|
|
88
|
+
lines.push("");
|
|
89
|
+
lines.push(` [${subject} · ${formatBytes(omittedBytes)}]`);
|
|
90
|
+
}
|
|
91
|
+
return lines;
|
|
92
|
+
}
|
|
93
|
+
function classRank(value) {
|
|
94
|
+
if (value === "violated")
|
|
95
|
+
return 0;
|
|
96
|
+
if (value === "downgraded")
|
|
97
|
+
return 1;
|
|
98
|
+
return 2;
|
|
99
|
+
}
|
|
100
|
+
function orderedFiles(report) {
|
|
101
|
+
return [...(report.files ?? [])].sort((left, right) => {
|
|
102
|
+
const rank = classRank(left.class) - classRank(right.class);
|
|
103
|
+
return rank || left.path.localeCompare(right.path);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
function hasCoordinateRace(report) {
|
|
107
|
+
return report.findings.some((finding) => finding.code === "COORDINATE_RACE");
|
|
108
|
+
}
|
|
109
|
+
function isMatchedScope(file) {
|
|
110
|
+
return file.class === "in-scope" || file.matcher.matched;
|
|
111
|
+
}
|
|
112
|
+
function renderChanges(report) {
|
|
113
|
+
if (!report.diff || !report.presentation || !report.files) {
|
|
114
|
+
return [hasCoordinateRace(report) || report.rehearsal.status === "conflict" || report.rehearsal.status === "unknown" ? "—" : "not evaluated"];
|
|
115
|
+
}
|
|
116
|
+
const files = orderedFiles(report);
|
|
117
|
+
const outside = files.filter((file) => !isMatchedScope(file));
|
|
118
|
+
const declared = files.filter((file) => isMatchedScope(file));
|
|
119
|
+
const lines = [
|
|
120
|
+
`${report.diff.stat.filesChanged} files · +${report.diff.stat.insertions} -${report.diff.stat.deletions}`,
|
|
121
|
+
];
|
|
122
|
+
if (outside.length > 0) {
|
|
123
|
+
lines.push("", "Outside declared write set", "");
|
|
124
|
+
for (const file of outside) {
|
|
125
|
+
lines.push(...renderFileBlock(file, report), "");
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (declared.length > 0) {
|
|
129
|
+
lines.push("", "Declared changes", "");
|
|
130
|
+
for (const file of declared) {
|
|
131
|
+
lines.push(...renderFileBlock(file, report), "");
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const selectedCount = report.presentation.selected.filter((item) => item.hunk !== null).length;
|
|
135
|
+
const omittedCount = report.presentation.omissions.filter((item) => item.hunk !== null).length;
|
|
136
|
+
const totalHunks = selectedCount + omittedCount;
|
|
137
|
+
if (totalHunks > 0 || report.presentation.budget.limit === 0) {
|
|
138
|
+
lines.push(`Shown ${selectedCount} of ${totalHunks || selectedCount} hunks · ${formatBytes(report.presentation.budget.limit)} presentation limit`);
|
|
139
|
+
}
|
|
140
|
+
while (lines.at(-1) === "")
|
|
141
|
+
lines.pop();
|
|
142
|
+
return lines;
|
|
143
|
+
}
|
|
144
|
+
function shouldExpandResult(result) {
|
|
145
|
+
if (result.status === "runner_failed")
|
|
146
|
+
return true;
|
|
147
|
+
if (result.status === "executed" && result.exitCode !== 0)
|
|
148
|
+
return true;
|
|
149
|
+
return [result.stdout, result.stderr].some((stream) => stream.truncated || stream.tail.length > 0);
|
|
150
|
+
}
|
|
151
|
+
function streamDetail(name, result, forceEmpty) {
|
|
3
152
|
const stream = result[name];
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
153
|
+
if (!forceEmpty && !stream.truncated && stream.tail.length === 0)
|
|
154
|
+
return [];
|
|
155
|
+
const mark = stream.truncated ? `truncated · ${formatBytes(stream.omittedBytes)} omitted` : "complete";
|
|
156
|
+
return [` ${name} (${mark})`, ...indentBlock(stream.tail || "(empty)", " ")];
|
|
157
|
+
}
|
|
158
|
+
function verificationStatus(result) {
|
|
159
|
+
if (result.status === "runner_failed")
|
|
160
|
+
return "unknown";
|
|
161
|
+
return result.exitCode === 0 ? "passed" : "failed";
|
|
162
|
+
}
|
|
163
|
+
function sourceHeading(source) {
|
|
164
|
+
return source === "contract" ? "contract" : "repository gate";
|
|
165
|
+
}
|
|
166
|
+
function preparationReason(reason) {
|
|
167
|
+
if (reason === "verification_not_configured")
|
|
168
|
+
return "no verification plan";
|
|
169
|
+
if (reason === "verification_plan_unavailable")
|
|
170
|
+
return "verification plan unavailable";
|
|
171
|
+
if (reason === "coordinate_race")
|
|
172
|
+
return "coordinate change";
|
|
173
|
+
return "candidate unavailable";
|
|
174
|
+
}
|
|
175
|
+
function preparationResult(result) {
|
|
176
|
+
if (result.kind === "exit")
|
|
177
|
+
return `exit ${result.code}`;
|
|
178
|
+
if (result.kind === "signal")
|
|
179
|
+
return `signal ${result.signal}`;
|
|
180
|
+
if (result.kind === "timeout")
|
|
181
|
+
return "timeout";
|
|
182
|
+
return `spawn · ${result.message}`;
|
|
183
|
+
}
|
|
184
|
+
function preparationStreams(preparation) {
|
|
185
|
+
const lines = [];
|
|
186
|
+
for (const stream of ["stdout", "stderr"]) {
|
|
187
|
+
const tail = preparation[`${stream}Tail`];
|
|
188
|
+
const truncated = preparation[`${stream}Truncated`];
|
|
189
|
+
if (tail === undefined && !truncated)
|
|
190
|
+
continue;
|
|
191
|
+
lines.push(` ${stream} (${truncated ? "truncated" : "complete"})`);
|
|
192
|
+
lines.push(...indentBlock(tail || "(empty)", " "));
|
|
193
|
+
}
|
|
194
|
+
return lines;
|
|
195
|
+
}
|
|
196
|
+
function renderCandidatePreparation(report) {
|
|
197
|
+
const preparation = report.candidatePreparation;
|
|
198
|
+
if (preparation.status === "not-required")
|
|
199
|
+
return [` preparation not required · ${preparationReason(preparation.reason)}`];
|
|
200
|
+
if (preparation.status === "not-configured")
|
|
201
|
+
return [" preparation not configured · no bind bootstrap plan"];
|
|
202
|
+
const command = JSON.stringify(preparation.plan.command);
|
|
203
|
+
if (preparation.status === "succeeded") {
|
|
204
|
+
return [
|
|
205
|
+
` preparation passed ${padLabel(formatDuration(preparation.durationMs), 6)} ${command}`,
|
|
206
|
+
...preparationStreams(preparation),
|
|
207
|
+
];
|
|
208
|
+
}
|
|
209
|
+
const lines = [
|
|
210
|
+
` preparation failed ${padLabel(formatDuration(preparation.durationMs), 6)} ${preparationResult(preparation.result)}`,
|
|
211
|
+
` ${preparation.cause.code}: ${preparation.cause.message}`,
|
|
212
|
+
` argv ${command} · timeout ${preparation.plan.timeoutMs}ms`,
|
|
7
213
|
];
|
|
214
|
+
if (preparation.integrity) {
|
|
215
|
+
lines.push(` integrity head=${preparation.integrity.head ?? "unknown"} · tree=${preparation.integrity.tree ?? "unknown"} · tracked=${preparation.integrity.trackedChanges.length}`);
|
|
216
|
+
}
|
|
217
|
+
lines.push(...preparationStreams(preparation));
|
|
218
|
+
return lines;
|
|
8
219
|
}
|
|
9
|
-
function
|
|
220
|
+
function renderVerificationResults(report) {
|
|
10
221
|
if (report.verification.status === "not_configured")
|
|
11
222
|
return ["not configured"];
|
|
12
|
-
if (report.verification.status === "not_evaluated")
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
223
|
+
if (report.verification.status === "not_evaluated") {
|
|
224
|
+
if (hasCoordinateRace(report) || report.verification.reason === "renew_conflict" || report.verification.reason === "renew_unknown") {
|
|
225
|
+
return ["—"];
|
|
226
|
+
}
|
|
227
|
+
return [`not evaluated · ${report.verification.reason.replaceAll("_", " ")}`];
|
|
228
|
+
}
|
|
229
|
+
if (report.verification.status === "unknown") {
|
|
230
|
+
return [`unknown · ${report.verification.cause.code}: ${report.verification.cause.message}`];
|
|
231
|
+
}
|
|
232
|
+
const labels = report.verification.results.map((result) => result.label);
|
|
233
|
+
const width = Math.max(8, ...labels.map((label) => label.length));
|
|
16
234
|
const lines = [];
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
235
|
+
const groups = ["contract", "repository-gate"];
|
|
236
|
+
for (const source of groups) {
|
|
237
|
+
const results = report.verification.results.filter((result) => result.source === source);
|
|
238
|
+
if (results.length === 0)
|
|
21
239
|
continue;
|
|
240
|
+
lines.push(` ${sourceHeading(source)}`);
|
|
241
|
+
for (const result of results) {
|
|
242
|
+
const status = padLabel(verificationStatus(result), 7);
|
|
243
|
+
const duration = formatDuration(result.durationMs);
|
|
244
|
+
lines.push(` ${padLabel(result.label, width)} ${status} ${padLabel(duration, 6)} ${result.declaration}`);
|
|
245
|
+
if (result.status === "runner_failed") {
|
|
246
|
+
lines.push(` ${result.cause.code}: ${result.cause.message}`);
|
|
247
|
+
}
|
|
248
|
+
if (shouldExpandResult(result)) {
|
|
249
|
+
const forceEmpty = result.status === "runner_failed" || (result.status === "executed" && result.exitCode !== 0);
|
|
250
|
+
lines.push(...streamDetail("stdout", result, forceEmpty), ...streamDetail("stderr", result, forceEmpty));
|
|
251
|
+
}
|
|
22
252
|
}
|
|
23
|
-
lines.push(`\`\`\`${result.executor}`, result.body, "\`\`\`", `exit ${result.exitCode} · duration ${result.durationMs}ms`, ...streamLines("stdout", result), ...streamLines("stderr", result), "");
|
|
24
253
|
}
|
|
25
254
|
return lines;
|
|
26
255
|
}
|
|
27
|
-
function
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
256
|
+
function renderVerification(report) {
|
|
257
|
+
const preparation = renderCandidatePreparation(report);
|
|
258
|
+
const results = renderVerificationResults(report);
|
|
259
|
+
return [...preparation, "", ...results];
|
|
260
|
+
}
|
|
261
|
+
function residueParts(readiness) {
|
|
262
|
+
const residue = readiness.deliveryResidue;
|
|
263
|
+
const parts = [];
|
|
264
|
+
if (residue.staged.length > 0)
|
|
265
|
+
parts.push(`${residue.staged.length} staged`);
|
|
266
|
+
if (residue.unstaged.length > 0)
|
|
267
|
+
parts.push(`${residue.unstaged.length} unstaged`);
|
|
268
|
+
if (residue.untracked.length > 0)
|
|
269
|
+
parts.push(`${residue.untracked.length} untracked`);
|
|
270
|
+
if (parts.length === 0 && residue.tracked.length > 0)
|
|
271
|
+
parts.push(`${residue.tracked.length} tracked dirty`);
|
|
272
|
+
return parts.join(" · ");
|
|
44
273
|
}
|
|
45
|
-
function
|
|
274
|
+
function renderDeliveryContext(report) {
|
|
275
|
+
const race = report.findings.find((finding) => finding.code === "COORDINATE_RACE");
|
|
276
|
+
if (race)
|
|
277
|
+
return renderCoordinateRace(race);
|
|
46
278
|
const readiness = report.readiness;
|
|
47
279
|
if (!readiness)
|
|
48
|
-
return ["not evaluated
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
280
|
+
return ["not evaluated"];
|
|
281
|
+
const lines = [];
|
|
282
|
+
const residue = residueParts(readiness);
|
|
283
|
+
lines.push(` worktree ${residue || "clean"}`);
|
|
284
|
+
const arcBits = [`max ${readiness.arc.max}`];
|
|
285
|
+
if (readiness.arc.open !== null)
|
|
286
|
+
arcBits.unshift(`open ${readiness.arc.open}`);
|
|
287
|
+
if (readiness.arc.fence)
|
|
288
|
+
arcBits.push(`fence ${shortCommitHash(readiness.arc.fence)}`);
|
|
289
|
+
if (readiness.arc.looseCommits.length > 0)
|
|
290
|
+
arcBits.push(`${readiness.arc.looseCommits.length} loose`);
|
|
291
|
+
lines.push(` arc ${arcBits.join(" · ")}`);
|
|
292
|
+
lines.push(` projection ${readiness.rewriteGuard.liveProjection ? "active" : "none"}`);
|
|
293
|
+
if (readiness.dependencies.length === 0) {
|
|
294
|
+
lines.push(" dependencies none");
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
const deps = readiness.dependencies
|
|
298
|
+
.map((item) => `${item.id} ${item.satisfied ? "settled" : item.state}`)
|
|
299
|
+
.join(" · ");
|
|
300
|
+
lines.push(` dependencies ${deps}`);
|
|
301
|
+
}
|
|
302
|
+
if (readiness.petition.queue) {
|
|
303
|
+
const position = readiness.petition.queue.position ?? "?";
|
|
304
|
+
lines.push(` petition ${readiness.petition.state} · queue ${position}/${readiness.petition.queue.length}`);
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
lines.push(` petition ${readiness.petition.state}`);
|
|
308
|
+
}
|
|
309
|
+
return lines;
|
|
310
|
+
}
|
|
311
|
+
function formatRaceValue(value) {
|
|
312
|
+
if (typeof value === "string") {
|
|
313
|
+
return /^[0-9a-f]{40}$/i.test(value) ? shortCommitHash(value) : value;
|
|
314
|
+
}
|
|
315
|
+
if (value === null || value === undefined)
|
|
316
|
+
return String(value);
|
|
317
|
+
if (typeof value !== "object" || Array.isArray(value))
|
|
318
|
+
return JSON.stringify(value);
|
|
319
|
+
const record = value;
|
|
320
|
+
const preferred = ["cwd", "ref", "head", "tree", "residueFingerprint"];
|
|
321
|
+
const parts = [];
|
|
322
|
+
for (const key of preferred) {
|
|
323
|
+
if (!(key in record))
|
|
324
|
+
continue;
|
|
325
|
+
const raw = record[key];
|
|
326
|
+
if (raw === undefined)
|
|
327
|
+
continue;
|
|
328
|
+
if (key === "head" || key === "tree" || key === "residueFingerprint") {
|
|
329
|
+
parts.push(`${key}=${typeof raw === "string" ? (key === "residueFingerprint" ? raw.slice(0, 12) : formatRaceValue(raw)) : JSON.stringify(raw)}`);
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
if (key === "ref" && typeof raw === "string") {
|
|
333
|
+
parts.push(`${key}=${shortRef(raw)}`);
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
parts.push(`${key}=${typeof raw === "string" ? raw : JSON.stringify(raw)}`);
|
|
337
|
+
}
|
|
338
|
+
if (parts.length === 0)
|
|
339
|
+
return JSON.stringify(value);
|
|
340
|
+
return parts.join(" · ");
|
|
57
341
|
}
|
|
58
|
-
function
|
|
59
|
-
const
|
|
60
|
-
|
|
342
|
+
function renderCoordinateRace(finding) {
|
|
343
|
+
const lines = [` coordinate change observed`, ` ${finding.detail}`];
|
|
344
|
+
const race = finding.race;
|
|
345
|
+
if (!race)
|
|
346
|
+
return lines;
|
|
347
|
+
lines.push(` which ${race.which}`);
|
|
348
|
+
lines.push(` pinned ${formatRaceValue(race.pinned)}`);
|
|
349
|
+
lines.push(` observed ${formatRaceValue(race.observed)}`);
|
|
350
|
+
return lines;
|
|
61
351
|
}
|
|
62
|
-
function
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
352
|
+
function renderRehearsal(report) {
|
|
353
|
+
const rehearsal = report.rehearsal;
|
|
354
|
+
if (rehearsal.status === "fresh")
|
|
355
|
+
return "fresh";
|
|
356
|
+
if (rehearsal.status === "clean") {
|
|
357
|
+
return `clean onto ${shortRef(report.coordinates.target.ref)}@${shortCommitHash(rehearsal.newBase)}`;
|
|
358
|
+
}
|
|
359
|
+
if (rehearsal.status === "conflict") {
|
|
360
|
+
const paths = rehearsal.paths.length > 0 ? rehearsal.paths.join(", ") : "paths unavailable";
|
|
361
|
+
return `conflict · ${paths}`;
|
|
362
|
+
}
|
|
363
|
+
return `unknown · ${rehearsal.cause.code}: ${rehearsal.cause.message}`;
|
|
364
|
+
}
|
|
365
|
+
function renderCandidate(report) {
|
|
366
|
+
const target = `${shortRef(report.coordinates.target.ref)}@${shortCommitHash(report.coordinates.target.head)}`;
|
|
367
|
+
const delivery = `${shortRef(report.coordinates.delivery.ref)}@${shortCommitHash(report.coordinates.delivery.head)}`;
|
|
368
|
+
const lines = [];
|
|
369
|
+
if (report.candidate) {
|
|
370
|
+
const candidateHead = shortCommitHash(report.candidate.head);
|
|
371
|
+
const candidateBase = shortCommitHash(report.candidate.base);
|
|
372
|
+
if (report.candidate.kind === "renew-rehearsal") {
|
|
373
|
+
lines.push(` ${candidateBase}..${candidateHead} · renew rehearsal`);
|
|
374
|
+
lines.push(` delivery ${delivery}`);
|
|
375
|
+
lines.push(` target ${target}`);
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
lines.push(` ${target}..${candidateHead}`);
|
|
379
|
+
if (report.candidate.head !== report.coordinates.delivery.head) {
|
|
380
|
+
lines.push(` delivery ${delivery}`);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
lines.push(` ${target}..${delivery}`);
|
|
386
|
+
}
|
|
387
|
+
if (report.diff) {
|
|
388
|
+
lines.push(` ${report.diff.stat.filesChanged} files · +${report.diff.stat.insertions} -${report.diff.stat.deletions}`);
|
|
389
|
+
}
|
|
390
|
+
else if (report.findings.some((finding) => finding.code === "COORDINATE_RACE")) {
|
|
391
|
+
lines.push(" evidence not evaluated · coordinate change");
|
|
392
|
+
}
|
|
393
|
+
else if (report.rehearsal.status === "conflict") {
|
|
394
|
+
lines.push(" evidence not evaluated · renew conflict");
|
|
395
|
+
}
|
|
396
|
+
else if (report.rehearsal.status === "unknown") {
|
|
397
|
+
lines.push(" evidence not evaluated · renew unknown");
|
|
398
|
+
}
|
|
399
|
+
lines.push(` rehearsal: ${renderRehearsal(report)}`);
|
|
400
|
+
lines.push(` ledger ${shortCommitHash(report.coordinates.ledger.head)}`);
|
|
401
|
+
return lines;
|
|
402
|
+
}
|
|
403
|
+
function renderAcceptance(report) {
|
|
404
|
+
if (report.terms.criteria.length === 0)
|
|
405
|
+
return [" (none)"];
|
|
406
|
+
return report.terms.criteria.map((term, index) => ` ${index + 1}. ${term}`);
|
|
75
407
|
}
|
|
76
408
|
export function buildAuditResponse(report, json) {
|
|
77
409
|
const payload = report;
|
|
78
410
|
if (json)
|
|
79
411
|
return { text: JSON.stringify(report), payload };
|
|
80
|
-
const
|
|
412
|
+
const sections = [
|
|
81
413
|
`Audit ${report.contract}`,
|
|
82
414
|
"",
|
|
83
|
-
"
|
|
84
|
-
|
|
85
|
-
`delivery ${report.coordinates.delivery.ref} ${report.coordinates.delivery.head} tree ${report.coordinates.delivery.tree}`,
|
|
86
|
-
`target ${report.coordinates.target.ref} ${report.coordinates.target.head} tree ${report.coordinates.target.tree}`,
|
|
87
|
-
"",
|
|
88
|
-
"Criteria",
|
|
89
|
-
...report.terms.criteria.map((term) => `criterion ${term}`),
|
|
90
|
-
...report.terms.scope.map((term) => `scope ${term}`),
|
|
91
|
-
...report.terms.appendScope.map((term) => `append-scope ${term}`),
|
|
415
|
+
"Candidate",
|
|
416
|
+
...renderCandidate(report),
|
|
92
417
|
"",
|
|
93
|
-
"
|
|
94
|
-
|
|
418
|
+
"Acceptance",
|
|
419
|
+
...renderAcceptance(report),
|
|
95
420
|
"",
|
|
96
|
-
"
|
|
97
|
-
...
|
|
98
|
-
`counts files=${report.counts.files} selected=${report.counts.selected} omitted=${report.counts.omitted} in-scope=${report.counts.inScope} downgraded=${report.counts.downgraded} violated=${report.counts.violated} findings=${report.counts.findings}`,
|
|
99
|
-
"",
|
|
100
|
-
"Scope",
|
|
101
|
-
...renderScope(report),
|
|
421
|
+
"Changes",
|
|
422
|
+
...renderChanges(report),
|
|
102
423
|
"",
|
|
103
424
|
"Verification",
|
|
104
425
|
...renderVerification(report),
|
|
105
|
-
"Readiness",
|
|
106
|
-
...renderReadiness(report),
|
|
107
426
|
"",
|
|
108
|
-
"
|
|
109
|
-
...(report
|
|
110
|
-
]
|
|
111
|
-
return { text, payload };
|
|
427
|
+
"Delivery Context",
|
|
428
|
+
...renderDeliveryContext(report),
|
|
429
|
+
];
|
|
430
|
+
return { text: sections.join("\n"), payload };
|
|
112
431
|
}
|
|
113
432
|
export function buildAuditConstructionFailure(error, json) {
|
|
114
433
|
const cause = { code: error instanceof FlowError ? error.code : "INTERNAL_STATE", message: asMessage(error) };
|
|
@@ -117,6 +117,10 @@ function renderKeiyakuSection(board, width) {
|
|
|
117
117
|
facts: contractFacts(contract),
|
|
118
118
|
width,
|
|
119
119
|
}));
|
|
120
|
+
if (contract.replayBlockers.length > 0) {
|
|
121
|
+
lines.push(` ! incomplete replay · ${contract.replayBlockers.map((blocker) => blocker.surface).join(", ")}`);
|
|
122
|
+
lines.push(` • ${contract.replayBlockers[0].recoveryCommand}`);
|
|
123
|
+
}
|
|
120
124
|
}
|
|
121
125
|
return lines.join("\n");
|
|
122
126
|
}
|
|
@@ -231,13 +235,14 @@ function renderTaskSection(tasks, width) {
|
|
|
231
235
|
lines.push(alignedBoardRow({
|
|
232
236
|
prefix: "▶",
|
|
233
237
|
title: taskLabel(task),
|
|
234
|
-
facts: [{ text:
|
|
238
|
+
facts: [{ text: `${task.state === "on_hold" ? "on hold · updated" : "in_progress · active"} ${formatAgeMs(task.activityAgeMs) ?? "0s"}` }],
|
|
235
239
|
width,
|
|
236
240
|
}));
|
|
237
241
|
}
|
|
238
242
|
const folded = [
|
|
239
243
|
tasks.ready > 0 ? `${tasks.ready} ready` : undefined,
|
|
240
244
|
tasks.blocked > 0 ? `${tasks.blocked} blocked` : undefined,
|
|
245
|
+
tasks.onHold > 0 ? `${tasks.onHold} on hold` : undefined,
|
|
241
246
|
].filter((fact) => fact !== undefined);
|
|
242
247
|
if (folded.length > 0)
|
|
243
248
|
lines.push(tone(`+ ${folded.join(" · ")}`, "description"));
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { attachAddressCarrier } from "../../core/addressing.js";
|
|
2
|
+
import { isCompleteLifecycleOutcome } from "../../core/outcome-base.js";
|
|
3
|
+
import { FlowError } from "../../flow-error.js";
|
|
4
|
+
import { handleCliError } from "./errors.js";
|
|
5
|
+
import { coreTextResponse } from "./shared.js";
|
|
6
|
+
function isSuccessfulDerivedCleanup(result) {
|
|
7
|
+
return result.family === "precommit-effects-only"
|
|
8
|
+
&& "status" in result
|
|
9
|
+
&& result.status === "success"
|
|
10
|
+
&& "cleanup" in result
|
|
11
|
+
&& typeof result.cleanup === "object"
|
|
12
|
+
&& result.cleanup !== null
|
|
13
|
+
&& "status" in result.cleanup
|
|
14
|
+
&& result.cleanup.status === "succeeded"
|
|
15
|
+
&& [...result.prerequisites, ...result.downstream].every((row) => row.status !== "failed");
|
|
16
|
+
}
|
|
17
|
+
export async function buildLifecycleOutcomeResponse(result, context) {
|
|
18
|
+
if (result.family === "committed") {
|
|
19
|
+
return coreTextResponse(`lifecycle committed at ${result.committed.head}${result.replay.action === "reconcile" ? "; downstream reconciliation required" : ""}`, result);
|
|
20
|
+
}
|
|
21
|
+
const cause = result.family === "cancelled-before-effects"
|
|
22
|
+
? result.cancellation
|
|
23
|
+
: result.family === "refused-before-effects"
|
|
24
|
+
? result.failedInvariant
|
|
25
|
+
: [...result.prerequisites, ...result.downstream].find((row) => row.status === "failed")?.cause
|
|
26
|
+
?? { code: "INTERNAL_STATE", message: "durable prerequisite effects require lifecycle reconciliation" };
|
|
27
|
+
if (!context) {
|
|
28
|
+
return { ...coreTextResponse(cause.message, result), exitCode: result.family === "cancelled-before-effects" ? 130 : 1 };
|
|
29
|
+
}
|
|
30
|
+
const facts = "facts" in cause ? cause.facts : undefined;
|
|
31
|
+
const error = new FlowError(cause.code, cause.message, {
|
|
32
|
+
...(facts ? { facts: facts } : {}),
|
|
33
|
+
});
|
|
34
|
+
const rendered = await handleCliError({
|
|
35
|
+
error: context.address ? attachAddressCarrier(error, context.address) : error,
|
|
36
|
+
cwd: context.cwd,
|
|
37
|
+
logLabel: "lifecycle",
|
|
38
|
+
});
|
|
39
|
+
return {
|
|
40
|
+
...rendered,
|
|
41
|
+
payload: result,
|
|
42
|
+
isDomainFailure: true,
|
|
43
|
+
exitCode: result.family === "cancelled-before-effects" ? 130 : 1,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export async function renderLifecycleResult(work, render, context) {
|
|
47
|
+
const value = await work;
|
|
48
|
+
if (isCompleteLifecycleOutcome(value))
|
|
49
|
+
return render(value);
|
|
50
|
+
if (isSuccessfulDerivedCleanup(value)) {
|
|
51
|
+
// Derived cleanup is a successful verb result, but deliberately is not a
|
|
52
|
+
// committed lifecycle result. The verb renderer owns that exact payload.
|
|
53
|
+
return render(value);
|
|
54
|
+
}
|
|
55
|
+
return buildLifecycleOutcomeResponse(value, context);
|
|
56
|
+
}
|