@astrosheep/keiyaku 4.5.11 → 4.5.13
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/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +135 -377
- package/build/integrations/pi/keiyaku.ts +11 -116
- package/build/src/akuma/akuma-errors.d.ts +1 -0
- package/build/src/akuma/akuma-errors.js +1 -0
- package/build/src/akuma/akuma-handle.d.ts +1 -0
- package/build/src/akuma/akuma-handle.js +6 -7
- package/build/src/akuma/akuma-product.d.ts +6 -8
- package/build/src/akuma/akuma-product.js +141 -57
- package/build/src/akuma/akuma.d.ts +5 -7
- package/build/src/akuma/akuma.js +1 -22
- package/build/src/akuma/archetype.d.ts +6 -5
- package/build/src/akuma/archetype.js +137 -38
- package/build/src/akuma/body.d.ts +5 -5
- package/build/src/akuma/body.js +223 -63
- package/build/src/akuma/call-input.d.ts +4 -0
- package/build/src/akuma/call-input.js +21 -0
- package/build/src/akuma/call-request.d.ts +5 -8
- package/build/src/akuma/call-request.js +28 -73
- package/build/src/akuma/fleet-execution.d.ts +26 -0
- package/build/src/akuma/fleet-execution.js +109 -0
- package/build/src/{library/fleet-result.d.ts → akuma/fleet-observation.d.ts} +13 -57
- package/build/src/{library/fleet-result.js → akuma/fleet-observation.js} +4 -25
- package/build/src/akuma/fleet-request.d.ts +122 -0
- package/build/src/akuma/fleet-request.js +168 -0
- package/build/src/akuma/heart/facts.d.ts +23 -0
- package/build/src/akuma/heart/facts.js +7 -0
- package/build/src/akuma/heart/index.d.ts +43 -4
- package/build/src/akuma/heart/index.js +107 -7
- package/build/src/akuma/heart/request-authority.d.ts +2 -0
- package/build/src/akuma/heart/request-authority.js +28 -3
- package/build/src/akuma/heart/request-rows.d.ts +2 -0
- package/build/src/akuma/heart/request-rows.js +24 -5
- package/build/src/akuma/heart/rows.d.ts +4 -1
- package/build/src/akuma/heart/rows.js +46 -19
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +28 -6
- package/build/src/akuma/heart/storage.d.ts +1 -1
- package/build/src/akuma/heart/tells.d.ts +29 -0
- package/build/src/akuma/heart/tells.js +136 -5
- package/build/src/akuma/heart/timeline.js +9 -3
- package/build/src/akuma/projection-read.js +36 -3
- package/build/src/akuma/projection.js +3 -4
- package/build/src/akuma/provider.d.ts +4 -0
- package/build/src/akuma/provider.js +56 -3
- package/build/src/akuma/providers/claude/index.js +3 -0
- package/build/src/akuma/providers/codex-app-server/index.js +14 -12
- package/build/src/akuma/providers/pi/index.js +7 -1
- package/build/src/akuma/publication.js +65 -49
- package/build/src/akuma/request-lifecycle.d.ts +5 -4
- package/build/src/akuma/request-lifecycle.js +29 -16
- package/build/src/akuma/request-rendezvous.d.ts +15 -12
- package/build/src/akuma/request-rendezvous.js +80 -51
- package/build/src/akuma/request-serve.d.ts +1 -2
- package/build/src/akuma/request-serve.js +94 -39
- package/build/src/akuma/request-wire.d.ts +57 -26
- package/build/src/akuma/request-wire.js +64 -25
- package/build/src/akuma/turn-drive.d.ts +5 -4
- package/build/src/akuma/turn-drive.js +27 -11
- package/build/src/akuma-body.d.ts +4 -6
- package/build/src/akuma-body.js +19 -17
- package/build/src/bounded-list.d.ts +8 -0
- package/build/src/bounded-list.js +14 -0
- package/build/src/cli/accepted.d.ts +1 -1
- package/build/src/cli/accepted.js +1 -0
- package/build/src/cli/commands/akuma-invoke.js +1 -25
- package/build/src/cli/commands/contract-help.d.ts +5 -2
- package/build/src/cli/commands/contract-help.js +62 -12
- package/build/src/cli/commands/contract-invoke.d.ts +5 -0
- package/build/src/cli/commands/contract-invoke.js +26 -1
- package/build/src/cli/commands/contract.js +50 -18
- package/build/src/cli/commands/task-invoke.js +10 -2
- package/build/src/cli/commands/task-query.js +3 -4
- package/build/src/cli/coordinates.d.ts +13 -0
- package/build/src/cli/coordinates.js +38 -24
- package/build/src/cli/draft.d.ts +1 -1
- package/build/src/cli/invoke.js +14 -1
- package/build/src/cli/render/akuma-activity.d.ts +0 -1
- package/build/src/cli/render/akuma-activity.js +5 -38
- package/build/src/cli/render/akuma.js +4 -1
- package/build/src/cli/render/audit.js +4 -1
- package/build/src/cli/render/catalog.js +13 -39
- package/build/src/cli/render/contract.js +4 -14
- package/build/src/cli/render/kanshi-akuma.js +3 -8
- package/build/src/cli/render/kanshi.js +8 -34
- package/build/src/cli/render/nuke.js +7 -3
- package/build/src/cli/render/receipt.d.ts +1 -0
- package/build/src/cli/render/receipt.js +8 -0
- package/build/src/cli/render/refusal.js +4 -3
- package/build/src/cli/render/task.js +4 -37
- package/build/src/cli/render/terminal.d.ts +2 -6
- package/build/src/cli/render/terminal.js +4 -9
- package/build/src/cli/result.d.ts +2 -1
- package/build/src/contract-guidance.js +13 -3
- package/build/src/contract-worktree.d.ts +1 -0
- package/build/src/contract-worktree.js +26 -2
- package/build/src/core/facts/codec.d.ts +2 -1
- package/build/src/core/facts/codec.js +3 -0
- package/build/src/core/facts/gate.d.ts +2 -1
- package/build/src/core/facts/gate.js +63 -0
- package/build/src/core/verbs/abandon.d.ts +2 -1
- package/build/src/core/verbs/abandon.js +16 -0
- package/build/src/core/verbs/amend.d.ts +2 -1
- package/build/src/core/verbs/amend.js +20 -0
- package/build/src/core/verbs/arc.d.ts +2 -1
- package/build/src/core/verbs/arc.js +16 -0
- package/build/src/core/verbs/attestation.d.ts +2 -1
- package/build/src/core/verbs/attestation.js +16 -0
- package/build/src/core/verbs/bind.d.ts +2 -1
- package/build/src/core/verbs/bind.js +16 -0
- package/build/src/core/verbs/deliver.d.ts +2 -1
- package/build/src/core/verbs/deliver.js +16 -0
- package/build/src/core/verbs/placement.d.ts +2 -1
- package/build/src/core/verbs/placement.js +58 -1
- package/build/src/dispatch/association.d.ts +13 -0
- package/build/src/dispatch/association.js +20 -0
- package/build/src/dispatch/index.d.ts +6 -0
- package/build/src/dispatch/index.js +27 -3
- package/build/src/git/hooks.d.ts +9 -1
- package/build/src/git/hooks.js +79 -1
- package/build/src/git/nuke.d.ts +2 -1
- package/build/src/git/nuke.js +6 -11
- package/build/src/git/private-state-seat.d.ts +26 -1
- package/build/src/git/private-state-seat.js +78 -13
- package/build/src/git/process.d.ts +2 -0
- package/build/src/git/reconcile.d.ts +1 -2
- package/build/src/git/reconcile.js +0 -6
- package/build/src/git/repository.d.ts +0 -2
- package/build/src/git/repository.js +27 -25
- package/build/src/git/result-codec.d.ts +29 -0
- package/build/src/git/result-codec.js +306 -0
- package/build/src/git/target-placement.js +2 -8
- package/build/src/git/workspace.d.ts +2 -0
- package/build/src/git/workspace.js +4 -0
- package/build/src/index.d.ts +1 -0
- package/build/src/kanshi/fleet.js +1 -1
- package/build/src/kanshi/read.js +55 -28
- package/build/src/kanshi/report.d.ts +4 -3
- package/build/src/kanshi/select.js +14 -1
- package/build/src/library/address.d.ts +1 -0
- package/build/src/library/address.js +4 -7
- package/build/src/library/akuma-creation.d.ts +5 -3
- package/build/src/library/akuma-creation.js +90 -33
- package/build/src/library/audit.js +2 -1
- package/build/src/library/catalog.d.ts +10 -2
- package/build/src/library/catalog.js +65 -25
- package/build/src/library/composition.d.ts +1 -0
- package/build/src/library/composition.js +1 -0
- package/build/src/library/configuration.d.ts +4 -21
- package/build/src/library/configuration.js +2 -158
- package/build/src/library/continuation.d.ts +20 -1
- package/build/src/library/continuation.js +36 -0
- package/build/src/library/contract-bind.d.ts +1 -0
- package/build/src/library/contract-bind.js +16 -5
- package/build/src/library/contract-forwarding.d.ts +2 -2
- package/build/src/library/contract-forwarding.js +18 -4
- package/build/src/library/contract-handle.js +4 -3
- package/build/src/library/contract-operations.d.ts +5 -9
- package/build/src/library/contract-operations.js +34 -47
- package/build/src/library/contract.d.ts +11 -2
- package/build/src/library/contract.js +21 -1
- package/build/src/library/delivery.d.ts +4 -1
- package/build/src/library/delivery.js +47 -0
- package/build/src/library/fleet.d.ts +4 -136
- package/build/src/library/fleet.js +31 -315
- package/build/src/library/keiyaku.d.ts +7 -3
- package/build/src/library/keiyaku.js +1 -0
- package/build/src/library/mutation.d.ts +431 -3
- package/build/src/library/mutation.js +192 -19
- package/build/src/library/nuke.d.ts +7 -1
- package/build/src/library/nuke.js +18 -4
- package/build/src/library/reconcile.d.ts +14 -0
- package/build/src/library/reconcile.js +22 -8
- package/build/src/library/refusal.d.ts +9 -1
- package/build/src/library/refusal.js +76 -0
- package/build/src/library/region.d.ts +0 -8
- package/build/src/library/region.js +1 -29
- package/build/src/library/result-codec.d.ts +2 -0
- package/build/src/library/result-codec.js +12 -0
- package/build/src/markdown/lex.js +9 -2
- package/build/src/markdown/types.d.ts +2 -1
- package/build/src/markdown/types.js +3 -1
- package/build/src/plugin/akuma-signals.d.ts +12 -0
- package/build/src/plugin/akuma-signals.js +14 -0
- package/build/src/plugin/public.d.ts +51 -0
- package/build/src/plugin/public.js +1 -0
- package/build/src/plugin/runtime.d.ts +14 -0
- package/build/src/plugin/runtime.js +357 -0
- package/build/src/protocol/amend.js +3 -3
- package/build/src/protocol/attempt.d.ts +2 -1
- package/build/src/protocol/attempt.js +1 -1
- package/build/src/protocol/audit.d.ts +1 -1
- package/build/src/protocol/audit.js +1 -1
- package/build/src/protocol/bind.d.ts +3 -1
- package/build/src/protocol/bind.js +26 -0
- package/build/src/protocol/completion.js +0 -1
- package/build/src/protocol/deliver.d.ts +1 -1
- package/build/src/protocol/deliver.js +136 -57
- package/build/src/protocol/intent.d.ts +0 -1
- package/build/src/protocol/intent.js +0 -1
- package/build/src/protocol/operations.d.ts +9 -2
- package/build/src/protocol/operations.js +16 -1
- package/build/src/protocol/outcome.d.ts +3 -0
- package/build/src/protocol/outcome.js +17 -1
- package/build/src/protocol/placement.js +10 -3
- package/build/src/protocol/read/status.d.ts +8 -0
- package/build/src/protocol/read/status.js +49 -0
- package/build/src/protocol/reintegrate.js +10 -3
- package/build/src/protocol/result-codec.d.ts +22 -0
- package/build/src/protocol/result-codec.js +442 -0
- package/build/src/protocol/review.d.ts +1 -1
- package/build/src/protocol/review.js +81 -46
- package/build/src/protocol/run.d.ts +22 -2
- package/build/src/protocol/run.js +119 -29
- package/build/src/runtime/proc/lifecycle.js +1 -1
- package/build/src/runtime/proc/line-rpc.d.ts +7 -1
- package/build/src/runtime/proc/line-rpc.js +49 -9
- package/build/src/runtime/proc/run.d.ts +0 -1
- package/build/src/runtime/proc/run.js +1 -11
- package/build/src/runtime/proc/termination.d.ts +1 -0
- package/build/src/runtime/proc/termination.js +63 -18
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/build/src/settings.d.ts +10 -0
- package/build/src/settings.js +88 -2
- package/build/src/settlement/result-codec.d.ts +2 -0
- package/build/src/settlement/result-codec.js +56 -0
- package/build/src/settlement/settle.d.ts +5 -12
- package/build/src/settlement/settle.js +60 -55
- package/build/src/task/board.d.ts +3 -0
- package/build/src/task/board.js +22 -4
- package/build/src/task/catalog.d.ts +13 -2
- package/build/src/task/catalog.js +59 -5
- package/build/src/task/compose.d.ts +4 -2
- package/build/src/task/compose.js +56 -30
- package/build/src/task/created-observation.d.ts +39 -0
- package/build/src/task/created-observation.js +26 -0
- package/build/src/task/identity.d.ts +6 -0
- package/build/src/task/identity.js +48 -7
- package/build/src/task/index.d.ts +4 -3
- package/build/src/task/index.js +19 -16
- package/build/src/task/input.d.ts +3 -1
- package/build/src/task/input.js +7 -4
- package/build/src/task/lifecycle-operations.d.ts +6 -0
- package/build/src/task/lifecycle-operations.js +116 -0
- package/build/src/task/mutation-result.d.ts +762 -20
- package/build/src/task/mutation-result.js +34 -9
- package/build/src/task/mutation.d.ts +4 -9
- package/build/src/task/mutation.js +17 -52
- package/build/src/task/operation-types.d.ts +114 -0
- package/build/src/task/operation-types.js +1 -0
- package/build/src/task/operations.d.ts +6 -113
- package/build/src/task/operations.js +75 -117
- package/build/src/task/query.d.ts +8 -11
- package/build/src/task/query.js +7 -14
- package/build/src/task/store.d.ts +11 -1
- package/build/src/task/store.js +169 -55
- package/build/src/task/view.d.ts +4 -0
- package/build/src/task/view.js +7 -0
- package/build/src/verification/declaration.d.ts +1 -0
- package/build/src/verification/declaration.js +18 -1
- package/build/src/verification/execution.d.ts +0 -1
- package/build/src/verification/execution.js +5 -5
- package/build/src/world.d.ts +0 -2
- package/build/src/world.js +3 -7
- package/package.json +17 -5
- package/build/src/cli/square-edge.d.ts +0 -7
- package/build/src/cli/square-edge.js +0 -159
- package/build/src/git/ref-migration.d.ts +0 -22
- package/build/src/git/ref-migration.js +0 -55
- package/build/src/library/contract-forwarding-reconciliation-result.d.ts +0 -102
- package/build/src/library/contract-forwarding-reconciliation-result.js +0 -92
- package/build/src/library/contract-forwarding-result.d.ts +0 -4270
- package/build/src/library/contract-forwarding-result.js +0 -521
|
@@ -11,7 +11,6 @@ function targetLine(row, abbreviations) {
|
|
|
11
11
|
: undefined;
|
|
12
12
|
return [`target ${target}`, ...(lag === undefined ? [] : [lag]), ...targetMovementFacts(row, abbreviations)].join(" · ");
|
|
13
13
|
}
|
|
14
|
-
const CATALOG_VISIBLE_AKUMA = 10;
|
|
15
14
|
function akumaMark(life) {
|
|
16
15
|
if (life === "running")
|
|
17
16
|
return "●";
|
|
@@ -23,15 +22,6 @@ function akumaMark(life) {
|
|
|
23
22
|
return "!";
|
|
24
23
|
return "?";
|
|
25
24
|
}
|
|
26
|
-
function akumaUpdatedAt(row) {
|
|
27
|
-
const lifeAt = "lifeAt" in row ? row.lifeAt : null;
|
|
28
|
-
const activityAt = "lastActivityAt" in row ? row.lastActivityAt : null;
|
|
29
|
-
if (lifeAt === null)
|
|
30
|
-
return activityAt;
|
|
31
|
-
if (activityAt === null)
|
|
32
|
-
return lifeAt;
|
|
33
|
-
return lifeAt > activityAt ? lifeAt : activityAt;
|
|
34
|
-
}
|
|
35
25
|
function relativeAge(source, observedAt) {
|
|
36
26
|
if (source === null)
|
|
37
27
|
return null;
|
|
@@ -49,20 +39,9 @@ function relativeAge(source, observedAt) {
|
|
|
49
39
|
return `${Math.floor(hours / 24)}d`;
|
|
50
40
|
}
|
|
51
41
|
function renderAkumaCatalog(catalog) {
|
|
52
|
-
const
|
|
53
|
-
const leftAt = akumaUpdatedAt(left);
|
|
54
|
-
const rightAt = akumaUpdatedAt(right);
|
|
55
|
-
if (leftAt === rightAt)
|
|
56
|
-
return 0;
|
|
57
|
-
if (leftAt === null)
|
|
58
|
-
return 1;
|
|
59
|
-
if (rightAt === null)
|
|
60
|
-
return -1;
|
|
61
|
-
return leftAt > rightAt ? -1 : 1;
|
|
62
|
-
});
|
|
63
|
-
const rows = ordered.slice(0, CATALOG_VISIBLE_AKUMA);
|
|
42
|
+
const rows = catalog.rows;
|
|
64
43
|
const lines = [
|
|
65
|
-
`akuma instances ${rows.length}
|
|
44
|
+
`akuma instances ${rows.length} recent`,
|
|
66
45
|
...(catalog.archetype === null ? [] : [` scope ${safeText(catalog.archetype)}`]),
|
|
67
46
|
"",
|
|
68
47
|
];
|
|
@@ -72,10 +51,8 @@ function renderAkumaCatalog(catalog) {
|
|
|
72
51
|
const ages = [relativeAge(lifeAt, catalog.observedAt), relativeAge(activityAt, catalog.observedAt)].filter((age) => age !== null);
|
|
73
52
|
lines.push(`${akumaMark(row.life)} ${safeText(row.id)} · ${row.life}${ages.length === 0 ? "" : ` · ${ages.join(" · ")}`}`);
|
|
74
53
|
}
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
lines.push("", ` + ${ordered.length - rows.length} more akuma not shown`, ` keiyaku ls ${selector}`);
|
|
78
|
-
}
|
|
54
|
+
if (catalog.hasMore)
|
|
55
|
+
lines.push("…");
|
|
79
56
|
return lines.join("\n");
|
|
80
57
|
}
|
|
81
58
|
function catalogMark(row) {
|
|
@@ -110,14 +87,10 @@ function renderContractCatalog(catalog) {
|
|
|
110
87
|
...(catalog.state === null ? [] : [catalog.state]),
|
|
111
88
|
...catalog.rows.flatMap(gitIdsInRow),
|
|
112
89
|
]);
|
|
113
|
-
const rows = catalog.rows
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
catalog.state === null
|
|
118
|
-
? `observedAt ${catalog.observedAt}`
|
|
119
|
-
: `contract state ${displayGitId(catalog.state, abbreviations)} · observedAt ${catalog.observedAt}`,
|
|
120
|
-
];
|
|
90
|
+
const rows = catalog.rows;
|
|
91
|
+
const header = catalog.state === null
|
|
92
|
+
? `observedAt ${catalog.observedAt}`
|
|
93
|
+
: `contract state ${displayGitId(catalog.state, abbreviations)} · observedAt ${catalog.observedAt}`;
|
|
121
94
|
const blocks = rows.map((row) => {
|
|
122
95
|
const lines = [
|
|
123
96
|
`${catalogMark(row)} ${safeText(row.id)} · ${row.phase} · ${formatAge(row.phaseAt, catalog.observedAt)} · ${safeText(row.title ?? "title unavailable")}`,
|
|
@@ -128,13 +101,14 @@ function renderContractCatalog(catalog) {
|
|
|
128
101
|
];
|
|
129
102
|
return lines.join("\n");
|
|
130
103
|
});
|
|
131
|
-
return [
|
|
104
|
+
return [header, ...(blocks.length === 0 ? [] : ["", ...blocks]), ...(catalog.hasMore ? ["…"] : [])].join("\n");
|
|
132
105
|
}
|
|
133
106
|
export function renderCatalogText(catalog) {
|
|
134
107
|
if (catalog.kind === "tasks") {
|
|
135
|
-
return
|
|
136
|
-
.map((row) => `${safeText(row.id)} - P${row.priority} - ${row.disposition} - ${safeText(row.title)}`)
|
|
137
|
-
.
|
|
108
|
+
return [
|
|
109
|
+
...catalog.rows.map((row) => `${safeText(row.id)} - P${row.priority} - ${row.disposition} - ${safeText(row.title)}`),
|
|
110
|
+
...(catalog.hasMore ? ["…"] : []),
|
|
111
|
+
].join("\n");
|
|
138
112
|
}
|
|
139
113
|
if (catalog.kind === "contracts")
|
|
140
114
|
return renderContractCatalog(catalog);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { renderAcceptedAudit } from "./audit.js";
|
|
2
|
-
import { appendHookPayload, cleanupLines, hookFailureSummary, leakLines, outcomeLines, receiptPayload, receiptRow, reuseLines, stopLines, titleLines, } from "./receipt.js";
|
|
2
|
+
import { appendHookPayload, cleanupLines, hookFailureSummary, leakLines, outcomeLines, seatCloseLines, receiptPayload, receiptRow, reuseLines, stopLines, titleLines, } from "./receipt.js";
|
|
3
3
|
import { gitShortStat, renderOpaqueBlock } from "./terminal.js";
|
|
4
4
|
const HANG = " ";
|
|
5
5
|
function isRecord(value) {
|
|
@@ -11,16 +11,6 @@ function retryLines(detail, indent, columns) {
|
|
|
11
11
|
}
|
|
12
12
|
return renderOpaqueBlock(detail.kind, indent, columns);
|
|
13
13
|
}
|
|
14
|
-
function refMigrationConflictRows(lag, columns) {
|
|
15
|
-
const lines = [];
|
|
16
|
-
receiptRow(lines, "!", "lag", [
|
|
17
|
-
{
|
|
18
|
-
text: `ref-migration-conflict legacy=${lag.legacyRef}@${lag.legacyOid} current=${lag.currentRef}@${lag.currentOid}`,
|
|
19
|
-
opaque: true,
|
|
20
|
-
},
|
|
21
|
-
], columns);
|
|
22
|
-
return lines;
|
|
23
|
-
}
|
|
24
14
|
function lagRows(lag, columns) {
|
|
25
15
|
const lines = [];
|
|
26
16
|
if (lag.kind === "worktree-retained") {
|
|
@@ -59,9 +49,6 @@ function lagRows(lag, columns) {
|
|
|
59
49
|
receiptRow(lines, "!", "lag", [{ text: `contract-file-failed ${lag.worktree} ${lag.path}`, opaque: true }], columns);
|
|
60
50
|
receiptPayload(lines, "diagnostic", lag.diagnostic);
|
|
61
51
|
}
|
|
62
|
-
else if (lag.kind === "ref-migration-conflict") {
|
|
63
|
-
return refMigrationConflictRows(lag, columns);
|
|
64
|
-
}
|
|
65
52
|
else {
|
|
66
53
|
receiptRow(lines, "!", "lag", [{ text: `reconcile-failed ${lag.stage}`, opaque: true }], columns);
|
|
67
54
|
receiptPayload(lines, "diagnostic", lag.diagnostic);
|
|
@@ -144,6 +131,9 @@ function acceptedLagRows(result, columns) {
|
|
|
144
131
|
for (const lag of result.settlementLags) {
|
|
145
132
|
pushBlock(obligations, settlementLagRows(lag, columns));
|
|
146
133
|
}
|
|
134
|
+
if (result.seatClose !== undefined && result.seatClose.length > 0) {
|
|
135
|
+
pushBlock(obligations, seatCloseLines(result.seatClose, columns));
|
|
136
|
+
}
|
|
147
137
|
return obligations;
|
|
148
138
|
}
|
|
149
139
|
function indentRecord(lines) {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { visibleFleetRows } from "../../kanshi/fleet.js";
|
|
2
1
|
import { boundedActivity, elapsedMilliseconds, entityLines, identityLine, plumbFacts, RECENT_TONE_MS, renderSectionBlock, safeText, tone, } from "./terminal.js";
|
|
3
2
|
const PLUMB = " │ ";
|
|
4
3
|
const NARROW_COLUMNS = 72;
|
|
@@ -67,7 +66,7 @@ function renderAkuma(report, context) {
|
|
|
67
66
|
return ["AKUMA // absent", "", `${PLUMB}akuma absent`];
|
|
68
67
|
if (section.kind === "failed")
|
|
69
68
|
return ["AKUMA // unavailable", "", tone(`! ${safeText(section.failure.message)}`, "alert", context.color)];
|
|
70
|
-
const rows =
|
|
69
|
+
const rows = section.value.rows;
|
|
71
70
|
const rowLines = rows.map((row) => {
|
|
72
71
|
const statusTone = akumaStatusTone(row, report.observedAt);
|
|
73
72
|
const mark = statusTone === null ? akumaMark(row.life) : tone(akumaMark(row.life), statusTone, context.color);
|
|
@@ -101,15 +100,11 @@ function renderAkuma(report, context) {
|
|
|
101
100
|
? lines
|
|
102
101
|
: [...lines, ...plumbFacts([boundedActivity(snapshot, context.columns, PLUMB)], context.columns)];
|
|
103
102
|
});
|
|
104
|
-
const header = `AKUMA // ${rows.length} recent
|
|
103
|
+
const header = `AKUMA // ${rows.length} recent`;
|
|
105
104
|
const rendered = renderSectionBlock({
|
|
106
105
|
name: "AKUMA",
|
|
107
|
-
unit: "akuma",
|
|
108
|
-
selector: "aku",
|
|
109
|
-
continuation: 'keiyaku ls "aku/*/*"',
|
|
110
106
|
rows: rowLines,
|
|
111
|
-
|
|
112
|
-
neutral: true,
|
|
107
|
+
hasMore: section.value.hasMore,
|
|
113
108
|
});
|
|
114
109
|
return [header, ...rendered.slice(1)];
|
|
115
110
|
}
|
|
@@ -2,7 +2,6 @@ import { abbreviateGitIds, afterWording, candidateFact, dependentWording, displa
|
|
|
2
2
|
import { entityLines, elapsedMilliseconds, identityLine, plumbFacts, RECENT_TONE_MS, renderTextBlock, renderSectionBlock, safeText, tone, } from "./terminal.js";
|
|
3
3
|
import { akumaMark, endpointFact, formatAge, NARROW_COLUMNS, renderAkuma } from "./kanshi-akuma.js";
|
|
4
4
|
const PLUMB = " │ ";
|
|
5
|
-
const MAX_VISIBLE_ROWS = 10;
|
|
6
5
|
const REVIEW_ATTENTION_MS = 15 * 60 * 1_000;
|
|
7
6
|
const PENDING_ATTENTION_MS = 60 * 60 * 1_000;
|
|
8
7
|
function contractHasError(row) {
|
|
@@ -201,6 +200,8 @@ function semanticBlock(name, facts, context) {
|
|
|
201
200
|
return lines;
|
|
202
201
|
}
|
|
203
202
|
function namespaceTaskFacts(row) {
|
|
203
|
+
if (row.namespaceTasks === undefined)
|
|
204
|
+
return [];
|
|
204
205
|
if (row.namespaceTasks.kind === "absent")
|
|
205
206
|
return [];
|
|
206
207
|
if (row.namespaceTasks.kind === "failed") {
|
|
@@ -257,12 +258,6 @@ function candidateFacts(row, abbreviations) {
|
|
|
257
258
|
`change ${delivery.integration.changeId}`,
|
|
258
259
|
];
|
|
259
260
|
}
|
|
260
|
-
function isTerminalContract(row) {
|
|
261
|
-
return row.phase === "claimed" || row.phase === "abandoned";
|
|
262
|
-
}
|
|
263
|
-
function isTerminalTask(row) {
|
|
264
|
-
return row.disposition === "done" || row.disposition === "drop";
|
|
265
|
-
}
|
|
266
261
|
function renderWorldContractRow(row, report, context) {
|
|
267
262
|
const title = row.title ?? "title unavailable";
|
|
268
263
|
const contractFacts = [
|
|
@@ -287,35 +282,18 @@ function renderWorldContractRow(row, report, context) {
|
|
|
287
282
|
context,
|
|
288
283
|
}).concat(plumbFacts(linkedFacts, context.columns));
|
|
289
284
|
}
|
|
290
|
-
function selectRecentRows(rows, timestamp) {
|
|
291
|
-
return [...rows]
|
|
292
|
-
.sort((left, right) => {
|
|
293
|
-
const leftAt = timestamp(left);
|
|
294
|
-
const rightAt = timestamp(right);
|
|
295
|
-
if (leftAt === rightAt)
|
|
296
|
-
return 0;
|
|
297
|
-
return leftAt > rightAt ? -1 : 1;
|
|
298
|
-
})
|
|
299
|
-
.slice(0, MAX_VISIBLE_ROWS);
|
|
300
|
-
}
|
|
301
285
|
function renderContracts(report, context) {
|
|
302
286
|
const section = report.contracts;
|
|
303
287
|
if (section.kind === "absent")
|
|
304
288
|
return ["CONTRACTS // absent", "", `${PLUMB}contracts absent`];
|
|
305
289
|
if (section.kind === "failed")
|
|
306
290
|
return ["CONTRACTS // unavailable", "", tone(`! ${safeText(section.failure.message)}`, "alert", context.color)];
|
|
307
|
-
const live = section.value.rows.filter((row) => !isTerminalContract(row));
|
|
308
|
-
const rows = selectRecentRows(live, (row) => row.lastJournalAt);
|
|
309
|
-
const candidates = live.filter((row) => row.delivery !== null).length;
|
|
310
291
|
const rendered = renderSectionBlock({
|
|
311
292
|
name: "CONTRACTS",
|
|
312
|
-
|
|
313
|
-
selector: "kei",
|
|
314
|
-
rows: rows.map((row) => renderWorldContractRow(row, report, context)),
|
|
315
|
-
total: live.length,
|
|
293
|
+
rows: section.value.rows.map((row) => renderWorldContractRow(row, report, context)),
|
|
316
294
|
});
|
|
317
|
-
const header =
|
|
318
|
-
return [header, ...rendered.slice(1)];
|
|
295
|
+
const header = "CONTRACTS // recent";
|
|
296
|
+
return [header, ...rendered.slice(1), ...(section.value.hasMore === true ? ["…"] : [])];
|
|
319
297
|
}
|
|
320
298
|
function renderSelectedContract(report, context) {
|
|
321
299
|
const section = report.contracts;
|
|
@@ -334,8 +312,7 @@ function renderTasks(report, context) {
|
|
|
334
312
|
return ["TASKS // absent", "", `${PLUMB}tasks absent`];
|
|
335
313
|
if (section.kind === "failed")
|
|
336
314
|
return ["TASKS // unavailable", "", tone(`! ${safeText(section.failure.message)}`, "alert", context.color)];
|
|
337
|
-
const
|
|
338
|
-
const rows = selectRecentRows(live, (row) => row.updatedAt);
|
|
315
|
+
const rows = section.value.rows;
|
|
339
316
|
const rowLines = rows.map((row) => {
|
|
340
317
|
const relation = row.contract === undefined ? ["unbound"] : [endpointFact(row.contract.id, row.contract.observed)];
|
|
341
318
|
const childFacts = row.children === undefined ? [] : [`children ${row.children.live} live · ${row.children.total} total`];
|
|
@@ -356,15 +333,12 @@ function renderTasks(report, context) {
|
|
|
356
333
|
});
|
|
357
334
|
});
|
|
358
335
|
return [
|
|
359
|
-
|
|
336
|
+
"TASKS // recent",
|
|
360
337
|
...renderSectionBlock({
|
|
361
338
|
name: "TASKS",
|
|
362
|
-
unit: "task",
|
|
363
|
-
selector: "task",
|
|
364
|
-
continuation: "keiyaku task ls --world",
|
|
365
339
|
rows: rowLines,
|
|
366
|
-
total: live.length,
|
|
367
340
|
}).slice(1),
|
|
341
|
+
...(section.value.hasMore ? ["…"] : []),
|
|
368
342
|
];
|
|
369
343
|
}
|
|
370
344
|
export function renderKanshiText(report, context = { columns: 80, color: false }, selection = "world") {
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
export function renderNukeText(result) {
|
|
2
|
-
|
|
3
|
-
?
|
|
4
|
-
: `
|
|
2
|
+
const seatClose = result.seatClose === undefined || result.seatClose.length === 0
|
|
3
|
+
? []
|
|
4
|
+
: result.seatClose.flatMap((lag) => [`lag ${lag.kind}`, `diagnostic ${lag.diagnostic}`]);
|
|
5
|
+
if (result.kind === "success") {
|
|
6
|
+
return [`nuke success ${result.world}`, ...seatClose].join("\n");
|
|
7
|
+
}
|
|
8
|
+
return [`nuke failed ${result.world}`, result.diagnostic, ...seatClose].join("\n");
|
|
5
9
|
}
|
|
6
10
|
export function nukeExitCode(result) {
|
|
7
11
|
return result.kind === "failed" ? 2 : 0;
|
|
@@ -17,4 +17,5 @@ export declare function reuseLines(reuse: VerificationReuse | undefined, columns
|
|
|
17
17
|
export declare function stopLines(stop: VerificationStop | PlacementStop, columns: number, addressed: string, dependent?: string): readonly string[];
|
|
18
18
|
export declare function cleanupLines(cleanup: NonNullable<AcceptedDeliverResult["cleanup"]>, columns: number): readonly string[];
|
|
19
19
|
export declare function leakLines(leak: NonNullable<AcceptedDeliverResult["leak"]>, columns: number): readonly string[];
|
|
20
|
+
export declare function seatCloseLines(seatClose: NonNullable<AcceptedDeliverResult["seatClose"]>, columns: number): readonly string[];
|
|
20
21
|
export {};
|
|
@@ -186,3 +186,11 @@ export function leakLines(leak, columns) {
|
|
|
186
186
|
receiptPayload(lines, "diagnostic", leak.diagnostic);
|
|
187
187
|
return lines;
|
|
188
188
|
}
|
|
189
|
+
export function seatCloseLines(seatClose, columns) {
|
|
190
|
+
const lines = [];
|
|
191
|
+
for (const lag of seatClose) {
|
|
192
|
+
receiptRow(lines, "!", "lag", [{ text: lag.kind }], columns);
|
|
193
|
+
receiptPayload(lines, "diagnostic", lag.diagnostic);
|
|
194
|
+
}
|
|
195
|
+
return lines;
|
|
196
|
+
}
|
|
@@ -28,13 +28,14 @@ function refusalHead(kind, identity, details) {
|
|
|
28
28
|
function renderDirtyRefusal(refusal, indent, columns, identity) {
|
|
29
29
|
const lines = [];
|
|
30
30
|
wrap(lines, refusalHead(refusal.kind, identity, []), indent, columns);
|
|
31
|
+
wrap(lines, "reason worktree has uncommitted changes", indent, columns);
|
|
31
32
|
for (const name of ["staged", "unstaged", "untracked", "submodules"]) {
|
|
32
33
|
lines.push(...collectionLines(name, refusal[name], indent, columns));
|
|
33
34
|
}
|
|
34
35
|
wrap(lines, gitShortStat(refusal.shortStat), indent, columns);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
wrap(lines, "--include-dirty captures all non-ignored worktree bytes in the candidate", indent, columns);
|
|
37
|
+
if (refusal.option?.available === false)
|
|
38
|
+
wrap(lines, "--include-dirty unavailable while submodules have changes", indent, columns);
|
|
38
39
|
return lines;
|
|
39
40
|
}
|
|
40
41
|
export function renderRefusalFacts(refusal, indent, columns, addressed) {
|
|
@@ -87,10 +87,8 @@ function edge(label, ref, mark) {
|
|
|
87
87
|
const prefix = mark === undefined ? ` ${label}` : ` ${mark} ${label}`;
|
|
88
88
|
return `${prefix} ${ref.id} · ${ref.state}`;
|
|
89
89
|
}
|
|
90
|
-
function pageHeading(view
|
|
91
|
-
|
|
92
|
-
return `${view} ${page.returned} of ${page.total} · limit ${page.returned}`;
|
|
93
|
-
return `${view} ${page.returned}`;
|
|
90
|
+
function pageHeading(view) {
|
|
91
|
+
return view;
|
|
94
92
|
}
|
|
95
93
|
function updatedAge(updatedAt) {
|
|
96
94
|
const elapsed = Math.max(0, performance.timeOrigin + performance.now() - Date.parse(updatedAt));
|
|
@@ -126,42 +124,11 @@ function renderListRow(item, columns, omitDisposition) {
|
|
|
126
124
|
}
|
|
127
125
|
return lines;
|
|
128
126
|
}
|
|
129
|
-
function shellQuote(value) {
|
|
130
|
-
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
131
|
-
}
|
|
132
|
-
function recoveryCommand(command, total) {
|
|
133
|
-
const parts = ["keiyaku", "task", command.action];
|
|
134
|
-
if (command.action === "ls") {
|
|
135
|
-
if (command.positionals.length > 0)
|
|
136
|
-
parts.push(command.positionals[0]);
|
|
137
|
-
if (command.flags.closed === true)
|
|
138
|
-
parts.push("--closed");
|
|
139
|
-
if (command.flags.all === true)
|
|
140
|
-
parts.push("--all");
|
|
141
|
-
}
|
|
142
|
-
if (command.flags.world === true)
|
|
143
|
-
parts.push("--world");
|
|
144
|
-
if ((command.action === "ready" || command.action === "blocked") && typeof command.flags.parent === "string") {
|
|
145
|
-
parts.push("--parent", command.flags.parent);
|
|
146
|
-
}
|
|
147
|
-
if (command.action === "query" && typeof command.flags.where === "string")
|
|
148
|
-
parts.push("--where", shellQuote(command.flags.where));
|
|
149
|
-
if (command.action === "query" && typeof command.flags.sort === "string")
|
|
150
|
-
parts.push("--sort", command.flags.sort);
|
|
151
|
-
parts.push("--limit", String(total));
|
|
152
|
-
return parts.join(" ");
|
|
153
|
-
}
|
|
154
127
|
function renderRows(command, result, columns) {
|
|
155
128
|
if (result.kind !== "accepted")
|
|
156
129
|
return renderFailure(command.action, result, columns);
|
|
157
130
|
const view = command.action === "ls" ? "tasks" : command.action;
|
|
158
|
-
const footer = result.value.
|
|
159
|
-
? [
|
|
160
|
-
"",
|
|
161
|
-
` + ${result.value.total - result.value.returned} more not shown`,
|
|
162
|
-
` ${recoveryCommand(command, result.value.total)}`,
|
|
163
|
-
]
|
|
164
|
-
: [];
|
|
131
|
+
const footer = result.value.hasMore ? ["…"] : [];
|
|
165
132
|
const scope = command.action === "ls"
|
|
166
133
|
? command.flags.world === true
|
|
167
134
|
? "world"
|
|
@@ -169,7 +136,7 @@ function renderRows(command, result, columns) {
|
|
|
169
136
|
? `namespace ${command.positionals[0].replace(/^task\//u, "").replace(/\/$/u, "") || "root"}`
|
|
170
137
|
: "current namespace"
|
|
171
138
|
: undefined;
|
|
172
|
-
const heading = scope === undefined ? pageHeading(view
|
|
139
|
+
const heading = scope === undefined ? pageHeading(view) : `${pageHeading(view)} · ${scope}`;
|
|
173
140
|
return [
|
|
174
141
|
heading,
|
|
175
142
|
...result.value.rows.flatMap((item) => renderListRow(item, columns, command.action === "ready")),
|
|
@@ -47,13 +47,9 @@ export declare function entityLines(entity: Readonly<{
|
|
|
47
47
|
facts: readonly string[];
|
|
48
48
|
context: TextRenderContext;
|
|
49
49
|
}>): readonly string[];
|
|
50
|
-
export declare function renderSectionBlock({ name,
|
|
50
|
+
export declare function renderSectionBlock({ name, rows, hasMore, }: Readonly<{
|
|
51
51
|
name: string;
|
|
52
|
-
unit: string;
|
|
53
|
-
selector: string;
|
|
54
|
-
continuation?: string;
|
|
55
52
|
rows: readonly (readonly string[])[];
|
|
56
|
-
|
|
57
|
-
neutral?: boolean;
|
|
53
|
+
hasMore?: boolean;
|
|
58
54
|
}>): readonly string[];
|
|
59
55
|
export {};
|
|
@@ -242,14 +242,9 @@ export function entityLines(entity) {
|
|
|
242
242
|
...plumbFacts(facts, context.columns),
|
|
243
243
|
];
|
|
244
244
|
}
|
|
245
|
-
export function renderSectionBlock({ name,
|
|
246
|
-
const lines = [`[ ${name} ]
|
|
247
|
-
if (
|
|
248
|
-
lines.push("");
|
|
249
|
-
lines.push(rows.length === total
|
|
250
|
-
? ` (all ${total}${neutral ? "" : " live"} ${unit} shown)`
|
|
251
|
-
: ` + ${total - rows.length} more${neutral ? "" : " live"} ${unit} not shown`);
|
|
252
|
-
if (rows.length !== total)
|
|
253
|
-
lines.push(` ${continuation ?? `keiyaku ls ${selector}/`}`);
|
|
245
|
+
export function renderSectionBlock({ name, rows, hasMore = false, }) {
|
|
246
|
+
const lines = [`[ ${name} ]`, "", ...rows.flat()];
|
|
247
|
+
if (hasMore)
|
|
248
|
+
lines.push("…");
|
|
254
249
|
return lines;
|
|
255
250
|
}
|
|
@@ -27,7 +27,7 @@ export type AcceptedFact = (AcceptedFactEnvelope & Readonly<{
|
|
|
27
27
|
}>["data"];
|
|
28
28
|
}>);
|
|
29
29
|
export type Lag = ReconcileReport["lag"][number];
|
|
30
|
-
type MutationEnvelope = Pick<MutationResult<unknown>, "head" | "settlementLags" | "recoverySnapshot">;
|
|
30
|
+
type MutationEnvelope = Pick<MutationResult<unknown>, "head" | "settlementLags" | "recoverySnapshot" | "seatClose">;
|
|
31
31
|
export type AcceptedEnvelope = Readonly<{
|
|
32
32
|
kind: "accepted";
|
|
33
33
|
contract: ContractId;
|
|
@@ -36,6 +36,7 @@ export type AcceptedEnvelope = Readonly<{
|
|
|
36
36
|
settlementLags: MutationEnvelope["settlementLags"];
|
|
37
37
|
recoverySnapshot?: MutationEnvelope["recoverySnapshot"];
|
|
38
38
|
lag?: readonly [Lag, ...Lag[]];
|
|
39
|
+
seatClose?: MutationEnvelope["seatClose"];
|
|
39
40
|
}>;
|
|
40
41
|
export type AcceptedBindResult = AcceptedEnvelope & Readonly<{
|
|
41
42
|
verb: "bind";
|
|
@@ -21,14 +21,16 @@ export const CONTRACT_DELIVERER_SKILL = [
|
|
|
21
21
|
"",
|
|
22
22
|
"`deliver` creates the immutable candidate commit and prepares its integration with the target as it exists for that invocation. It runs or reuses Verification, records the candidate, and requests placement. If the target moves, run `deliver` again; Keiyaku recomputes the current-target integration. A manual rebase is optional candidate shaping, not target refresh.",
|
|
23
23
|
"",
|
|
24
|
-
"
|
|
24
|
+
"`keiyaku deliver` submits the current state of the whole worktree as the Contract's candidate.",
|
|
25
|
+
"",
|
|
26
|
+
"When the finished worktree itself is the candidate, use `deliver --include-dirty`; Keiyaku captures its complete non-ignored state without moving this worktree's HEAD or real index. When materializing a conflict, the same flag preserves those bytes as the handoff base before projecting the judged conflict.",
|
|
25
27
|
"",
|
|
26
28
|
"```bash",
|
|
27
29
|
"keiyaku deliver <contract> --include-dirty",
|
|
28
|
-
"keiyaku deliver <contract> --materialize-conflict",
|
|
30
|
+
"keiyaku deliver <contract> --materialize-conflict --include-dirty",
|
|
29
31
|
"```",
|
|
30
32
|
"",
|
|
31
|
-
"If delivery reports an integration conflict, materialize that judged conflict
|
|
33
|
+
"If delivery reports an integration conflict, materialize that judged conflict with `--include-dirty`; Keiyaku preserves the complete non-ignored worktree bytes as the handoff base before projecting the conflict. Resolve it in this worktree, then deliver the resolved bytes with `--include-dirty`. Deliver when the candidate is ready and the evidence is in place; delivery records and requests placement, while the Reviewer independently judges any declared review gate.",
|
|
32
34
|
]
|
|
33
35
|
.join("\n")
|
|
34
36
|
.concat("\n");
|
|
@@ -61,6 +63,14 @@ export const CONTRACT_REVIEWER_SKILL = [
|
|
|
61
63
|
"",
|
|
62
64
|
"## Review",
|
|
63
65
|
"",
|
|
66
|
+
"`keiyaku review` records a verdict on the whole Contract.",
|
|
67
|
+
"",
|
|
68
|
+
"Record `--satisfied` when you have verified two things and hold the evidence: the current worktree meets every Criterion, and the result actually achieves what the Objective set out to do. Criteria are the written checks; the Objective is the intent behind them — work that passes every check but misses the intent is not satisfied. If a delivered candidate, prerequisites, and all declared gates are in place, the Contract is claimed immediately and cannot be reopened.",
|
|
69
|
+
"",
|
|
70
|
+
"Record `--unsatisfied` when any Criterion is unmet, the work is incomplete, or the result does not achieve the Objective's intent — and state what is missing.",
|
|
71
|
+
"",
|
|
72
|
+
"If the commission asked for findings rather than a verdict, report them in your reply without running `keiyaku review`.",
|
|
73
|
+
"",
|
|
64
74
|
"```bash",
|
|
65
75
|
"keiyaku review <contract> --satisfied --summary <conclusion>",
|
|
66
76
|
"keiyaku review <contract> --unsatisfied --summary <finding>",
|
|
@@ -24,6 +24,7 @@ export type ContractFileLag = Readonly<{
|
|
|
24
24
|
path: string;
|
|
25
25
|
diagnostic: string;
|
|
26
26
|
}>;
|
|
27
|
+
export declare function decodeContractFileLag(value: unknown): ContractFileLag;
|
|
27
28
|
export type ContractWorktreeResult = Readonly<{
|
|
28
29
|
effects: readonly ContractFileEffect[];
|
|
29
30
|
lag: readonly ContractFileLag[];
|
|
@@ -8,6 +8,8 @@ import { worktreeGitDirectory, worktreeRoot } from "./git/repository.js";
|
|
|
8
8
|
import { GitPlumbingError, runGit } from "./git/process.js";
|
|
9
9
|
import { worktreePath } from "./git/workspace.js";
|
|
10
10
|
import { appointmentFor, placeRegisterPath } from "./workspace-place.js";
|
|
11
|
+
import { repairNamespaceContext } from "./task/context.js";
|
|
12
|
+
import { contractNamespace } from "./task/identity.js";
|
|
11
13
|
const IGNORE_BYTES = ".gitignore\nKEIYAKU.md\n";
|
|
12
14
|
const PRIMARY_IGNORE_BYTES = "*\n!settings.json\n!tasks/\n!tasks/**\n";
|
|
13
15
|
const SEAT_IGNORE_BYTES = ".gitignore\nSKILL.md\n";
|
|
@@ -15,6 +17,22 @@ const SEAT_SKILLS = [
|
|
|
15
17
|
["keiyaku-deliver", CONTRACT_DELIVERER_SKILL],
|
|
16
18
|
["keiyaku-review", CONTRACT_REVIEWER_SKILL],
|
|
17
19
|
];
|
|
20
|
+
export function decodeContractFileLag(value) {
|
|
21
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
22
|
+
throw new Error("malformed contract-file lag");
|
|
23
|
+
const object = value;
|
|
24
|
+
if (object.kind !== "contract-file-failed")
|
|
25
|
+
throw new Error("malformed contract-file lag");
|
|
26
|
+
if (Object.keys(object).some((key) => key !== "kind" && key !== "worktree" && key !== "path" && key !== "diagnostic"))
|
|
27
|
+
throw new Error("malformed contract-file lag");
|
|
28
|
+
if (typeof object.worktree !== "string" || object.worktree.trim() === "")
|
|
29
|
+
throw new Error("malformed contract-file lag");
|
|
30
|
+
if (typeof object.path !== "string" || object.path.trim() === "")
|
|
31
|
+
throw new Error("malformed contract-file lag");
|
|
32
|
+
if (typeof object.diagnostic !== "string" || object.diagnostic.trim() === "")
|
|
33
|
+
throw new Error("malformed contract-file lag");
|
|
34
|
+
return { kind: "contract-file-failed", worktree: object.worktree, path: object.path, diagnostic: object.diagnostic };
|
|
35
|
+
}
|
|
18
36
|
async function isTracked(repository, relativePath) {
|
|
19
37
|
try {
|
|
20
38
|
await runGit(repository, ["ls-files", "--error-unmatch", "--", relativePath]);
|
|
@@ -110,7 +128,7 @@ async function materializeSeatSkill(repository, worktree, seat, bytes) {
|
|
|
110
128
|
await repair(repository, worktree, skill, bytes),
|
|
111
129
|
];
|
|
112
130
|
}
|
|
113
|
-
async function materialize(repository, worktree, guidance) {
|
|
131
|
+
async function materialize(repository, worktree, guidance, namespace) {
|
|
114
132
|
const effects = [];
|
|
115
133
|
const failed = (target, path, error) => ({
|
|
116
134
|
effects,
|
|
@@ -148,6 +166,12 @@ async function materialize(repository, worktree, guidance) {
|
|
|
148
166
|
};
|
|
149
167
|
}
|
|
150
168
|
const scoped = { ...repository, effectiveCwd: worktree };
|
|
169
|
+
try {
|
|
170
|
+
await repairNamespaceContext(worktree, namespace);
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
return failed(worktree, join(worktree, ".keiyaku", "namespace", "current"), error);
|
|
174
|
+
}
|
|
151
175
|
for (const [relativePath, bytes] of [
|
|
152
176
|
[".keiyaku/.gitignore", IGNORE_BYTES],
|
|
153
177
|
[".keiyaku/KEIYAKU.md", guidance],
|
|
@@ -186,5 +210,5 @@ export async function projectContractWorktree(repository, state, register, _onCo
|
|
|
186
210
|
],
|
|
187
211
|
};
|
|
188
212
|
}
|
|
189
|
-
return await materialize(repository, worktreePath(repository, appointed.place), renderContractGuidance(state));
|
|
213
|
+
return await materialize(repository, worktreePath(repository, appointed.place), renderContractGuidance(state), contractNamespace(state.id));
|
|
190
214
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { JournalEntry } from "./types.js";
|
|
1
|
+
import type { DeliverData, JournalEntry } from "./types.js";
|
|
2
2
|
/** Validate one in-memory journal value with the persisted-fact authority. */
|
|
3
3
|
export declare function decodeJournalEntry(value: unknown): JournalEntry;
|
|
4
|
+
export declare function decodeDeliverData(value: unknown): DeliverData;
|
|
4
5
|
export declare function encodeEntry(entry: JournalEntry): string;
|
|
5
6
|
export declare function decodeJournal(journal: string): JournalEntry[];
|
|
@@ -239,6 +239,9 @@ function validateEntry(value) {
|
|
|
239
239
|
export function decodeJournalEntry(value) {
|
|
240
240
|
return validateEntry(value);
|
|
241
241
|
}
|
|
242
|
+
export function decodeDeliverData(value) {
|
|
243
|
+
return validateData("deliver", value);
|
|
244
|
+
}
|
|
242
245
|
function canonicalValue(value) {
|
|
243
246
|
if (value === null)
|
|
244
247
|
return "null";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AttestationEntry, type ContractState, type Gate } from "./types.js";
|
|
2
2
|
export type GateCurrent = Readonly<{
|
|
3
3
|
kind: "attested";
|
|
4
4
|
verdict: "satisfied" | "unsatisfied";
|
|
@@ -14,6 +14,7 @@ export type GateReport = Readonly<{
|
|
|
14
14
|
gate: Gate;
|
|
15
15
|
current: GateCurrent;
|
|
16
16
|
}>;
|
|
17
|
+
export declare function decodeGateReport(value: unknown): GateReport;
|
|
17
18
|
export type GateReports = Readonly<{
|
|
18
19
|
reports: readonly GateReport[];
|
|
19
20
|
satisfied: boolean;
|
|
@@ -1,4 +1,67 @@
|
|
|
1
1
|
import { currentSubjectPredicate } from "../subject.js";
|
|
2
|
+
import { gate } from "./types.js";
|
|
3
|
+
function fail() {
|
|
4
|
+
throw new Error("malformed gate report");
|
|
5
|
+
}
|
|
6
|
+
function object(value) {
|
|
7
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
8
|
+
fail();
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
function decodeAttestedGateCurrent(current) {
|
|
12
|
+
for (const key of Object.keys(current)) {
|
|
13
|
+
if (key !== "kind" && key !== "verdict" && key !== "at" && key !== "summary")
|
|
14
|
+
fail();
|
|
15
|
+
}
|
|
16
|
+
if (current.kind !== "attested")
|
|
17
|
+
fail();
|
|
18
|
+
if (current.verdict !== "satisfied" && current.verdict !== "unsatisfied")
|
|
19
|
+
fail();
|
|
20
|
+
if (typeof current.at !== "string")
|
|
21
|
+
fail();
|
|
22
|
+
return {
|
|
23
|
+
kind: "attested",
|
|
24
|
+
verdict: current.verdict,
|
|
25
|
+
at: current.at,
|
|
26
|
+
...(current.summary === undefined
|
|
27
|
+
? {}
|
|
28
|
+
: { summary: typeof current.summary === "string" ? current.summary : fail() }),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function decodeGateCurrent(value) {
|
|
32
|
+
const current = object(value);
|
|
33
|
+
if (current.kind === "missing") {
|
|
34
|
+
if (Object.keys(current).length !== 1)
|
|
35
|
+
fail();
|
|
36
|
+
return { kind: "missing" };
|
|
37
|
+
}
|
|
38
|
+
if (current.kind === "stale") {
|
|
39
|
+
if (current.priorVerdict !== "satisfied" && current.priorVerdict !== "unsatisfied")
|
|
40
|
+
fail();
|
|
41
|
+
if (Object.keys(current).length !== 2)
|
|
42
|
+
fail();
|
|
43
|
+
return { kind: "stale", priorVerdict: current.priorVerdict };
|
|
44
|
+
}
|
|
45
|
+
return decodeAttestedGateCurrent(current);
|
|
46
|
+
}
|
|
47
|
+
export function decodeGateReport(value) {
|
|
48
|
+
const record = object(value);
|
|
49
|
+
if (!("gate" in record) || !("current" in record))
|
|
50
|
+
fail();
|
|
51
|
+
for (const key of Object.keys(record))
|
|
52
|
+
if (key !== "gate" && key !== "current")
|
|
53
|
+
fail();
|
|
54
|
+
let decodedGate;
|
|
55
|
+
try {
|
|
56
|
+
if (typeof record.gate !== "string")
|
|
57
|
+
fail();
|
|
58
|
+
decodedGate = gate(record.gate);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
fail();
|
|
62
|
+
}
|
|
63
|
+
return { gate: decodedGate, current: decodeGateCurrent(record.current) };
|
|
64
|
+
}
|
|
2
65
|
/** Resolve the latest testimony for each requested gate and current subject. */
|
|
3
66
|
export function latestCurrentAttestations(state, requested) {
|
|
4
67
|
const attestations = new Map();
|