@astrosheep/keiyaku 4.6.2 → 4.6.3
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 +93 -45
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +3 -2
- package/build/src/akuma/providers/pi/events.js +3 -2
- package/build/src/body/render.d.ts +9 -1
- package/build/src/body/render.js +11 -0
- package/build/src/cli/commands/akuma-grammar.js +12 -3
- package/build/src/cli/commands/akuma.js +6 -0
- package/build/src/cli/commands/contract-grammar.js +7 -0
- package/build/src/cli/commands/contract-help.d.ts +1 -1
- package/build/src/cli/commands/contract-help.js +21 -9
- package/build/src/cli/commands/contract.js +3 -1
- package/build/src/cli/commands/task-grammar.js +9 -7
- package/build/src/cli/parse.js +5 -0
- package/build/src/cli/render/akuma-activity.d.ts +26 -6
- package/build/src/cli/render/akuma-activity.js +128 -118
- package/build/src/cli/render/akuma-tool.js +1 -1
- package/build/src/cli/render/audit.js +4 -6
- package/build/src/cli/render/catalog.js +7 -4
- package/build/src/cli/render/contract-history.js +8 -18
- package/build/src/cli/render/contract.js +5 -10
- package/build/src/cli/render/kanshi-akuma.js +1 -1
- package/build/src/cli/render/kanshi.js +24 -30
- package/build/src/cli/render/receipt.d.ts +1 -2
- package/build/src/cli/render/receipt.js +1 -6
- package/build/src/cli/render/refusal.js +2 -1
- package/build/src/cli/render/task.js +2 -1
- package/build/src/core/facts/codec.js +0 -6
- package/build/src/core/facts/fold.js +0 -7
- package/build/src/core/facts/types.d.ts +1 -4
- package/build/src/core/verbs/deliver.js +2 -14
- package/build/src/library/bind.d.ts +20 -20
- package/build/src/library/bind.js +2 -1
- package/build/src/library/contract-composition.d.ts +5 -2
- package/build/src/library/contract-composition.js +5 -3
- package/build/src/library/contract-creation.d.ts +7 -1
- package/build/src/library/contract-creation.js +19 -9
- package/build/src/library/contract-execution.d.ts +1 -0
- package/build/src/library/contract-execution.js +12 -4
- package/build/src/library/contract-settings.d.ts +2 -2
- package/build/src/library/contract-settings.js +21 -12
- package/build/src/library/outcome.d.ts +476 -652
- package/build/src/library/refusal.d.ts +2 -2
- package/build/src/protocol/bind.d.ts +1 -1
- package/build/src/protocol/deliver.js +1 -1
- package/build/src/protocol/execution-observation.d.ts +0 -8
- package/build/src/protocol/intent.js +2 -2
- package/build/src/protocol/operations.d.ts +1 -1
- package/build/src/protocol/read/status.d.ts +1 -1
- package/build/src/protocol/read/status.js +0 -2
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/build/src/world.d.ts +1 -0
- package/build/src/world.js +14 -0
- package/package.json +3 -3
|
@@ -19,9 +19,9 @@ function contractStatusTone(row, observedAt) {
|
|
|
19
19
|
if (contractHasError(row))
|
|
20
20
|
return "alert";
|
|
21
21
|
const phaseAge = elapsedMilliseconds(row.phaseAt, observedAt);
|
|
22
|
-
if (row.phase === "
|
|
22
|
+
if (row.phase === "bound" && row.delivery !== null && phaseAge !== null && phaseAge >= REVIEW_ATTENTION_MS)
|
|
23
23
|
return "attention";
|
|
24
|
-
if (row.phase === "bound" && phaseAge !== null && phaseAge >= PENDING_ATTENTION_MS)
|
|
24
|
+
if (row.phase === "bound" && row.delivery === null && phaseAge !== null && phaseAge >= PENDING_ATTENTION_MS)
|
|
25
25
|
return "attention";
|
|
26
26
|
const journalAge = elapsedMilliseconds(row.lastJournalAt, observedAt);
|
|
27
27
|
return journalAge !== null && journalAge <= RECENT_TONE_MS ? "recent" : null;
|
|
@@ -153,34 +153,28 @@ function renderSelectedContractRow(row, report, context, abbreviations) {
|
|
|
153
153
|
lines.push(...outcome.map((fact) => (fact.startsWith(" ") ? fact : ` ${safeText(fact)}`)));
|
|
154
154
|
return lines;
|
|
155
155
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
if (row.delivery !== null) {
|
|
170
|
-
lines.push(...semanticBlock("candidate", [
|
|
171
|
-
`candidate ${displayGitId(row.delivery.tenderSnapshot, abbreviations)}`,
|
|
172
|
-
`integration result ${displayGitId(row.delivery.integration.snapshot, abbreviations)}${row.verification?.kind === "recorded" && row.verification.snapshot === row.delivery.integration.snapshot ? ` · verification ${row.verification.verdict}` : ""}${row.targetObservation?.drift === true ? " · target moved since" : ""}`,
|
|
173
|
-
...(row.targetObservation?.drift === true ? targetMovementFacts(row, abbreviations) : []),
|
|
174
|
-
], context));
|
|
175
|
-
}
|
|
156
|
+
const deniedReview = row.gates.reports.find((gate) => gate.gate === "reviewed" && gate.current.kind === "attested" && gate.current.verdict === "unsatisfied");
|
|
157
|
+
lines.push(...semanticBlock("ball", [progressStrip(row)], context));
|
|
158
|
+
lines.push(...semanticBlock("gates", row.gates.reports
|
|
159
|
+
.filter((gate) => gate.current.kind !== "missing")
|
|
160
|
+
.filter((gate) => gate !== deniedReview || gate.current.kind !== "attested" || gate.current.summary === undefined)
|
|
161
|
+
.map(gateFact), context));
|
|
162
|
+
lines.push(...semanticBlock("prerequisites", row.after.filter((edge) => edge.endpoint.kind !== "claimed").map(afterWording), context));
|
|
163
|
+
if (row.delivery !== null) {
|
|
164
|
+
lines.push(...semanticBlock("candidate", [
|
|
165
|
+
`candidate ${displayGitId(row.delivery.tenderSnapshot, abbreviations)}`,
|
|
166
|
+
`integration result ${displayGitId(row.delivery.integration.snapshot, abbreviations)}${row.verification?.kind === "recorded" && row.verification.snapshot === row.delivery.integration.snapshot ? ` · verification ${row.verification.verdict}` : ""}${row.targetObservation?.drift === true ? " · target moved since" : ""}`,
|
|
167
|
+
...(row.targetObservation?.drift === true ? targetMovementFacts(row, abbreviations) : []),
|
|
168
|
+
], context));
|
|
176
169
|
lines.push(...semanticBlock("verification", staleVerificationFacts(row), context));
|
|
177
|
-
const deniedReview = row.gates.reports.find((gate) => gate.gate === "reviewed" && gate.current.kind === "attested" && gate.current.verdict === "unsatisfied");
|
|
178
|
-
lines.push(...semanticBlock("gates", row.gates.reports
|
|
179
|
-
.filter((gate) => gate !== deniedReview || gate.current.kind !== "attested" || gate.current.summary === undefined)
|
|
180
|
-
.map(gateFact), context));
|
|
181
|
-
if (deniedReview?.current.kind === "attested" && deniedReview.current.summary !== undefined)
|
|
182
|
-
lines.push(...payload("review ×", deniedReview.current.summary, context));
|
|
183
170
|
}
|
|
171
|
+
if (deniedReview?.current.kind === "attested" && deniedReview.current.summary !== undefined)
|
|
172
|
+
lines.push(...payload("review ×", deniedReview.current.summary, context));
|
|
173
|
+
const akuma = linkedAkumaSummary(row, report);
|
|
174
|
+
if (akuma !== undefined)
|
|
175
|
+
lines.push(...semanticBlock("akuma", [akuma], context));
|
|
176
|
+
if (row.worktreePath !== null)
|
|
177
|
+
lines.push(...semanticBlock("worktree", [`worktree ${row.worktreePath}`], context));
|
|
184
178
|
lines.push(...semanticBlock("alarms", liveAlarms(row, report), context));
|
|
185
179
|
return lines;
|
|
186
180
|
}
|
|
@@ -209,7 +203,7 @@ function renderWorldContractRow(row, report, context) {
|
|
|
209
203
|
function renderContracts(report, context) {
|
|
210
204
|
const section = report.contracts;
|
|
211
205
|
if (section.kind === "absent")
|
|
212
|
-
return ["CONTRACTS // absent"
|
|
206
|
+
return ["CONTRACTS // absent"];
|
|
213
207
|
if (section.kind === "failed")
|
|
214
208
|
return ["CONTRACTS // unavailable", "", tone(`! ${safeText(section.failure.message)}`, "alert", context.color)];
|
|
215
209
|
if (section.value.rows.length === 0)
|
|
@@ -238,7 +232,7 @@ function taskFailureFact(failure) {
|
|
|
238
232
|
function renderTasks(report, context) {
|
|
239
233
|
const section = report.tasks;
|
|
240
234
|
if (section.kind === "absent")
|
|
241
|
-
return ["TASKS // absent"
|
|
235
|
+
return ["TASKS // absent"];
|
|
242
236
|
if (section.kind === "failed")
|
|
243
237
|
return [
|
|
244
238
|
"TASKS // unavailable",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ExecutionCleanup, ExecutionStop, PartialOutcomeEnvelope, ReconciliationLag } from "../../index.js";
|
|
2
|
-
import type { PlacementStop,
|
|
2
|
+
import type { PlacementStop, VerificationStop } from "../../index.js";
|
|
3
3
|
export type ReceiptSegment = Readonly<{
|
|
4
4
|
text: string;
|
|
5
5
|
opaque?: boolean;
|
|
@@ -14,7 +14,6 @@ export declare function refusalLines(verb: string, facts: readonly string[], col
|
|
|
14
14
|
export declare function titleLines(mark: string, title: string, contract: string, columns?: number): string[];
|
|
15
15
|
export declare function hookFailureSummary(failure: HookFailure): string;
|
|
16
16
|
export declare function appendHookPayload(lines: string[], failure: HookFailure): void;
|
|
17
|
-
export declare function reuseLines(reuse: VerificationReuse | undefined, columns: number): readonly string[];
|
|
18
17
|
/**
|
|
19
18
|
* The pending margin statement: the not-yet-happened requirements a refused placement awaits. A gate in stale
|
|
20
19
|
* state awaits the same event; when every unmet gate already holds a recorded verdict there is nothing pending and
|
|
@@ -64,11 +64,6 @@ export function appendHookPayload(lines, failure) {
|
|
|
64
64
|
if (failure.stderr !== undefined && failure.stderr.length > 0)
|
|
65
65
|
receiptPayload(lines, "stderr", failure.stderr);
|
|
66
66
|
}
|
|
67
|
-
export function reuseLines(reuse, columns) {
|
|
68
|
-
if (reuse === undefined)
|
|
69
|
-
return [];
|
|
70
|
-
return renderOpaqueBlock(`reuse verified · ${reuse.verdict}`, " ", columns);
|
|
71
|
-
}
|
|
72
67
|
function prerequisiteRows(stop, columns) {
|
|
73
68
|
if (!("refusal" in stop) || stop.refusal?.kind !== "prerequisites-unsatisfied")
|
|
74
69
|
return [];
|
|
@@ -97,7 +92,7 @@ function gateAlarmRows(stop, columns) {
|
|
|
97
92
|
continue;
|
|
98
93
|
receiptRow(lines, "!", eventNoun(gate), [{ text: `· ${current.verdict}` }, { text: `· at ${current.at}` }], columns);
|
|
99
94
|
if (current.summary !== undefined)
|
|
100
|
-
receiptPayload(lines,
|
|
95
|
+
receiptPayload(lines, " summary", current.summary);
|
|
101
96
|
}
|
|
102
97
|
return lines;
|
|
103
98
|
}
|
|
@@ -104,7 +104,8 @@ function refusalFacts(refusal, indent, columns, addressed) {
|
|
|
104
104
|
if (identity !== undefined)
|
|
105
105
|
lines.push(`${indent}contract ${safeText(identity)}`);
|
|
106
106
|
if ("diagnostic" in refusal && typeof refusal.diagnostic === "string")
|
|
107
|
-
|
|
107
|
+
for (const detail of refusal.diagnostic.split("\n"))
|
|
108
|
+
lines.push(`${indent}detail ${safeText(detail)}`);
|
|
108
109
|
return lines;
|
|
109
110
|
}
|
|
110
111
|
export function renderRefusalFacts(refusal, indent, columns, addressed) {
|
|
@@ -246,7 +246,8 @@ function renderBatchItem(verb, item, columns) {
|
|
|
246
246
|
if (item.outcome.kind === "retry")
|
|
247
247
|
return `? ${verb} ${item.id} ${item.outcome.reason}`;
|
|
248
248
|
const facts = projectRefusal(item.outcome.refusal);
|
|
249
|
-
|
|
249
|
+
const rest = (facts.facts ?? []).filter((fact) => fact !== `task ${item.id}`);
|
|
250
|
+
return refusalLines(verb, [`task ${item.id}`, `reason ${facts.diagnostic}`, ...rest], columns).join("\n");
|
|
250
251
|
}
|
|
251
252
|
function renderBatch(verb, batch, columns) {
|
|
252
253
|
return batch.items.map((item) => renderBatchItem(verb, item, columns)).join("\n");
|
|
@@ -4,7 +4,6 @@ import { changeId, actorId, contractId, documentKey, documentSegmentKey, entryUl
|
|
|
4
4
|
const VERSION_BY_KIND = {
|
|
5
5
|
bind: 1,
|
|
6
6
|
amend: 1,
|
|
7
|
-
bound: 1,
|
|
8
7
|
deliver: 1,
|
|
9
8
|
reintegrated: 1,
|
|
10
9
|
attestation: 1,
|
|
@@ -158,11 +157,6 @@ function validateData(kind, value) {
|
|
|
158
157
|
}
|
|
159
158
|
case "amend":
|
|
160
159
|
return termsValue(value, path);
|
|
161
|
-
case "bound": {
|
|
162
|
-
const object = requireRecord(value, path);
|
|
163
|
-
requireKeys(object, [], path);
|
|
164
|
-
return {};
|
|
165
|
-
}
|
|
166
160
|
case "deliver": {
|
|
167
161
|
const object = requireRecord(value, path);
|
|
168
162
|
requireKeys(object, ["tenderSnapshot", "integration", "method", "policy"], path);
|
|
@@ -22,7 +22,6 @@ function stateFromBind(id, head, bind, attestations) {
|
|
|
22
22
|
head,
|
|
23
23
|
coordinates: cloneCoordinates(bind.data.coordinates),
|
|
24
24
|
terms: cloneTerms(bind.data.terms),
|
|
25
|
-
bound: null,
|
|
26
25
|
delivery: null,
|
|
27
26
|
currentIntegration: null,
|
|
28
27
|
attestations,
|
|
@@ -49,13 +48,7 @@ function foldEntry(state, entry, attestations) {
|
|
|
49
48
|
foldError("bind may appear only once");
|
|
50
49
|
case "amend":
|
|
51
50
|
return { ...state, terms: cloneTerms(entry.data) };
|
|
52
|
-
case "bound":
|
|
53
|
-
if (state.bound !== null)
|
|
54
|
-
foldError("bound may appear only once");
|
|
55
|
-
return { ...state, bound: entry };
|
|
56
51
|
case "deliver":
|
|
57
|
-
if (state.bound === null)
|
|
58
|
-
foldError("deliver requires bound");
|
|
59
52
|
return { ...state, delivery: entry, currentIntegration: { ...entry.data.integration } };
|
|
60
53
|
case "reintegrated":
|
|
61
54
|
if (state.delivery === null)
|
|
@@ -72,7 +72,6 @@ export type BindData = Readonly<{
|
|
|
72
72
|
terms: ContractTerms;
|
|
73
73
|
}>;
|
|
74
74
|
export type AmendData = ContractTerms;
|
|
75
|
-
export type BoundData = Readonly<Record<string, never>>;
|
|
76
75
|
export type DeliverData = Readonly<{
|
|
77
76
|
tenderSnapshot: SnapshotId;
|
|
78
77
|
integration: Readonly<{
|
|
@@ -118,14 +117,13 @@ type JournalEnvelope<Kind extends string, Data> = Readonly<{
|
|
|
118
117
|
}>;
|
|
119
118
|
export type BindEntry = JournalEnvelope<"bind", BindData>;
|
|
120
119
|
type AmendEntry = JournalEnvelope<"amend", AmendData>;
|
|
121
|
-
type BoundEntry = JournalEnvelope<"bound", BoundData>;
|
|
122
120
|
type DeliverEntry = JournalEnvelope<"deliver", DeliverData>;
|
|
123
121
|
export type ReintegratedEntry = JournalEnvelope<"reintegrated", ReintegratedData>;
|
|
124
122
|
export type AttestationEntry = JournalEnvelope<"attestation", AttestationData>;
|
|
125
123
|
type ClaimedEntry = JournalEnvelope<"claimed", ClaimedData>;
|
|
126
124
|
export type ArcEntry = JournalEnvelope<"arc", ArcData>;
|
|
127
125
|
type AbandonedEntry = JournalEnvelope<"abandoned", AbandonedData>;
|
|
128
|
-
export type JournalEntry = BindEntry | AmendEntry |
|
|
126
|
+
export type JournalEntry = BindEntry | AmendEntry | DeliverEntry | ReintegratedEntry | AttestationEntry | ClaimedEntry | ArcEntry | AbandonedEntry;
|
|
129
127
|
export type FactKind = JournalEntry["kind"];
|
|
130
128
|
type ContractTerminal = ClaimedEntry | AbandonedEntry;
|
|
131
129
|
export type ContractState = Readonly<{
|
|
@@ -133,7 +131,6 @@ export type ContractState = Readonly<{
|
|
|
133
131
|
head: ContractHead | null;
|
|
134
132
|
coordinates: ContractCoordinates;
|
|
135
133
|
terms: ContractTerms;
|
|
136
|
-
bound: BoundEntry | null;
|
|
137
134
|
delivery: DeliverEntry | null;
|
|
138
135
|
currentIntegration: CurrentIntegration | null;
|
|
139
136
|
attestations: readonly AttestationEntry[];
|
|
@@ -11,26 +11,14 @@ export function decideDeliver({ input, attempt, observation, }) {
|
|
|
11
11
|
}
|
|
12
12
|
if (input.preparation.kind === "refused")
|
|
13
13
|
return { kind: "refused", refusal: input.preparation.refusal };
|
|
14
|
-
const entries = [];
|
|
15
|
-
if (state.bound === null)
|
|
16
|
-
entries.push({
|
|
17
|
-
v: 1,
|
|
18
|
-
kind: "bound",
|
|
19
|
-
contract: input.contractId,
|
|
20
|
-
entry: attempt.entryUlids[0],
|
|
21
|
-
at: input.at,
|
|
22
|
-
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
23
|
-
data: {},
|
|
24
|
-
});
|
|
25
14
|
const deliver = {
|
|
26
15
|
v: 1,
|
|
27
16
|
kind: "deliver",
|
|
28
17
|
contract: input.contractId,
|
|
29
|
-
entry: attempt.entryUlids[
|
|
18
|
+
entry: attempt.entryUlids[0],
|
|
30
19
|
at: input.at,
|
|
31
20
|
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
32
21
|
data: input.preparation.data,
|
|
33
22
|
};
|
|
34
|
-
entries
|
|
35
|
-
return { kind: "offer", offer: { facts: [{ contractId: input.contractId, entries }] } };
|
|
23
|
+
return { kind: "offer", offer: { facts: [{ contractId: input.contractId, entries: [deliver] }] } };
|
|
36
24
|
}
|
|
@@ -26,16 +26,16 @@ type BindAttemptInput = Readonly<{
|
|
|
26
26
|
export declare function admitBindWithAppointment(input: BindAttemptInput): Promise<IntentOutcome<Readonly<{
|
|
27
27
|
contractId: ContractId;
|
|
28
28
|
}>, {
|
|
29
|
+
kind: "contract-exists" | "invalid-after" | "unknown-prerequisite";
|
|
30
|
+
contractId: ContractId;
|
|
31
|
+
} | {
|
|
29
32
|
kind: "verification-declaration-invalid";
|
|
30
33
|
contractId?: ContractId | undefined;
|
|
31
|
-
} | {
|
|
32
|
-
kind: "target-missing" | "unborn-head" | "invalid-target";
|
|
33
34
|
} | {
|
|
34
35
|
kind: "fork-source-moved";
|
|
35
36
|
contractId: ContractId;
|
|
36
37
|
} | {
|
|
37
|
-
kind: "
|
|
38
|
-
contractId: ContractId;
|
|
38
|
+
kind: "unborn-head" | "target-missing" | "invalid-target";
|
|
39
39
|
} | {
|
|
40
40
|
kind: "fork-source-missing" | "fork-source-unavailable";
|
|
41
41
|
contractId: ContractId;
|
|
@@ -76,16 +76,16 @@ export declare function admitMarkdownBind(input: Readonly<{
|
|
|
76
76
|
}>): Promise<IntentOutcome<Readonly<{
|
|
77
77
|
contractId: ContractId;
|
|
78
78
|
}>, {
|
|
79
|
+
kind: "contract-exists" | "invalid-after" | "unknown-prerequisite";
|
|
80
|
+
contractId: ContractId;
|
|
81
|
+
} | {
|
|
79
82
|
kind: "verification-declaration-invalid";
|
|
80
83
|
contractId?: ContractId | undefined;
|
|
81
|
-
} | {
|
|
82
|
-
kind: "target-missing" | "unborn-head" | "invalid-target";
|
|
83
84
|
} | {
|
|
84
85
|
kind: "fork-source-moved";
|
|
85
86
|
contractId: ContractId;
|
|
86
87
|
} | {
|
|
87
|
-
kind: "
|
|
88
|
-
contractId: ContractId;
|
|
88
|
+
kind: "unborn-head" | "target-missing" | "invalid-target";
|
|
89
89
|
} | {
|
|
90
90
|
kind: "fork-source-missing" | "fork-source-unavailable";
|
|
91
91
|
contractId: ContractId;
|
|
@@ -107,16 +107,16 @@ export declare function prepareMarkdownBind(input: Readonly<{
|
|
|
107
107
|
result: IntentOutcome<Readonly<{
|
|
108
108
|
contractId: ContractId;
|
|
109
109
|
}>, {
|
|
110
|
+
kind: "contract-exists" | "invalid-after" | "unknown-prerequisite";
|
|
111
|
+
contractId: ContractId;
|
|
112
|
+
} | {
|
|
110
113
|
kind: "verification-declaration-invalid";
|
|
111
114
|
contractId?: ContractId | undefined;
|
|
112
|
-
} | {
|
|
113
|
-
kind: "target-missing" | "unborn-head" | "invalid-target";
|
|
114
115
|
} | {
|
|
115
116
|
kind: "fork-source-moved";
|
|
116
117
|
contractId: ContractId;
|
|
117
118
|
} | {
|
|
118
|
-
kind: "
|
|
119
|
-
contractId: ContractId;
|
|
119
|
+
kind: "unborn-head" | "target-missing" | "invalid-target";
|
|
120
120
|
} | {
|
|
121
121
|
kind: "fork-source-missing" | "fork-source-unavailable";
|
|
122
122
|
contractId: ContractId;
|
|
@@ -126,16 +126,16 @@ export declare function prepareMarkdownBind(input: Readonly<{
|
|
|
126
126
|
result: IntentOutcome<Readonly<{
|
|
127
127
|
contractId: ContractId;
|
|
128
128
|
}>, {
|
|
129
|
+
kind: "contract-exists" | "invalid-after" | "unknown-prerequisite";
|
|
130
|
+
contractId: ContractId;
|
|
131
|
+
} | {
|
|
129
132
|
kind: "verification-declaration-invalid";
|
|
130
133
|
contractId?: ContractId | undefined;
|
|
131
|
-
} | {
|
|
132
|
-
kind: "target-missing" | "unborn-head" | "invalid-target";
|
|
133
134
|
} | {
|
|
134
135
|
kind: "fork-source-moved";
|
|
135
136
|
contractId: ContractId;
|
|
136
137
|
} | {
|
|
137
|
-
kind: "
|
|
138
|
-
contractId: ContractId;
|
|
138
|
+
kind: "unborn-head" | "target-missing" | "invalid-target";
|
|
139
139
|
} | {
|
|
140
140
|
kind: "fork-source-missing" | "fork-source-unavailable";
|
|
141
141
|
contractId: ContractId;
|
|
@@ -146,16 +146,16 @@ export declare function prepareMarkdownBind(input: Readonly<{
|
|
|
146
146
|
result: IntentOutcome<Readonly<{
|
|
147
147
|
contractId: ContractId;
|
|
148
148
|
}>, {
|
|
149
|
+
kind: "contract-exists" | "invalid-after" | "unknown-prerequisite";
|
|
150
|
+
contractId: ContractId;
|
|
151
|
+
} | {
|
|
149
152
|
kind: "verification-declaration-invalid";
|
|
150
153
|
contractId?: ContractId | undefined;
|
|
151
|
-
} | {
|
|
152
|
-
kind: "target-missing" | "unborn-head" | "invalid-target";
|
|
153
154
|
} | {
|
|
154
155
|
kind: "fork-source-moved";
|
|
155
156
|
contractId: ContractId;
|
|
156
157
|
} | {
|
|
157
|
-
kind: "
|
|
158
|
-
contractId: ContractId;
|
|
158
|
+
kind: "unborn-head" | "target-missing" | "invalid-target";
|
|
159
159
|
} | {
|
|
160
160
|
kind: "fork-source-missing" | "fork-source-unavailable";
|
|
161
161
|
contractId: ContractId;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
2
|
import { decodeContractDocument } from "../body/decode.js";
|
|
3
|
+
import { decodeCanonicalContractDocument } from "../body/render.js";
|
|
3
4
|
import { contractIdFromSegment } from "../core/facts/types.js";
|
|
4
5
|
import { AuthorityCorruptionError } from "../core/facts/errors.js";
|
|
5
6
|
import { mintIdentitySegment } from "../identity/mint.js";
|
|
@@ -92,7 +93,7 @@ export async function admitForkBindWithAppointment(input) {
|
|
|
92
93
|
});
|
|
93
94
|
}
|
|
94
95
|
const markdown = sourceDocument.document.bytes.replace(/^\s*#\s*[^\r\n]*(?:\r?\n|$)/u, `# Fork · ${sourceDocument.title}${sourceDocument.document.bytes.includes("\r\n") ? "\r\n" : "\n"}`);
|
|
95
|
-
const document =
|
|
96
|
+
const document = decodeCanonicalContractDocument(markdown, { requireTimeout: true });
|
|
96
97
|
const terms = contractTerms(document, source.terms.gates, source.terms.after);
|
|
97
98
|
const admission = await attemptCandidates({
|
|
98
99
|
scope: input.scope,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** @architectureCompositionRoot */
|
|
2
2
|
import { type LibraryExecution } from "../akuma/requests.js";
|
|
3
|
+
import type { BindTargetSelection } from "../protocol/bind.js";
|
|
3
4
|
import type { ContractObservation } from "../protocol/read/status.js";
|
|
4
5
|
import type { BindOutcome } from "./contract-outcomes.js";
|
|
5
6
|
import type { BindInput, ContractList, ContractListInput, ContractObservationInput, KeiyakuSelectInput, LocalContractComposition } from "./contract-types.js";
|
|
@@ -31,9 +32,11 @@ export type KeiyakuLibrary = Readonly<{
|
|
|
31
32
|
* The one private Contract composition constructor. `Keiyaku.with` fixes local execution; CLI and
|
|
32
33
|
* Body pass their captured internal channel explicitly here instead of a second constructor. The
|
|
33
34
|
* carrier is a positional argument, never a field of the public construction input, so no runtime
|
|
34
|
-
* value reaching the public surface can select a private channel.
|
|
35
|
+
* value reaching the public surface can select a private channel. `omittedMarkdownTarget` is the
|
|
36
|
+
* internal bind intent an edge supplies for a Markdown bind whose caller omitted the target; the
|
|
37
|
+
* public package-root composition leaves it targetless.
|
|
35
38
|
*/
|
|
36
|
-
export declare function composeContractLibrary(execution: LibraryExecution, createHandle: typeof createKeiyakuHandle, input?: LocalContractComposition): KeiyakuLibrary;
|
|
39
|
+
export declare function composeContractLibrary(execution: LibraryExecution, createHandle: typeof createKeiyakuHandle, input?: LocalContractComposition, omittedMarkdownTarget?: BindTargetSelection): KeiyakuLibrary;
|
|
37
40
|
export declare function listKeiyaku(input: ContractListInput): Promise<ContractList>;
|
|
38
41
|
export declare function observeKeiyaku(input: ContractObservationInput): Promise<ContractObservation>;
|
|
39
42
|
export declare function readContractValue<Value>(operation: () => Promise<Value>): Promise<Value>;
|
|
@@ -13,12 +13,14 @@ import { scopeForRepo } from "./repo.js";
|
|
|
13
13
|
* The one private Contract composition constructor. `Keiyaku.with` fixes local execution; CLI and
|
|
14
14
|
* Body pass their captured internal channel explicitly here instead of a second constructor. The
|
|
15
15
|
* carrier is a positional argument, never a field of the public construction input, so no runtime
|
|
16
|
-
* value reaching the public surface can select a private channel.
|
|
16
|
+
* value reaching the public surface can select a private channel. `omittedMarkdownTarget` is the
|
|
17
|
+
* internal bind intent an edge supplies for a Markdown bind whose caller omitted the target; the
|
|
18
|
+
* public package-root composition leaves it targetless.
|
|
17
19
|
*/
|
|
18
|
-
export function composeContractLibrary(execution, createHandle, input) {
|
|
20
|
+
export function composeContractLibrary(execution, createHandle, input, omittedMarkdownTarget = { kind: "targetless" }) {
|
|
19
21
|
const composition = captureLocalContractComposition(input);
|
|
20
22
|
return Object.freeze({
|
|
21
|
-
bind: (operation) => bindKeiyaku(operation, createHandle, execution, composition),
|
|
23
|
+
bind: (operation) => bindKeiyaku(operation, createHandle, execution, composition, omittedMarkdownTarget),
|
|
22
24
|
select: (operation) => selectKeiyaku(operation, createHandle, execution, composition),
|
|
23
25
|
list: (operation) => listKeiyaku(operation),
|
|
24
26
|
observe: (operation) => observeKeiyaku(operation),
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
/** @architectureCompositionRoot */
|
|
2
2
|
import { type ExecutionContext } from "../akuma/requests.js";
|
|
3
|
+
import type { BindTargetSelection } from "../protocol/bind.js";
|
|
3
4
|
import type { BindOutcome } from "./contract-outcomes.js";
|
|
4
5
|
import { type LocalContractCompositionCapture } from "./contract-settings.js";
|
|
5
6
|
import type { BindInput } from "./contract-types.js";
|
|
6
7
|
import type { createKeiyakuHandle } from "./keiyaku.js";
|
|
7
|
-
|
|
8
|
+
/**
|
|
9
|
+
* One Contract bind. `omittedMarkdownTarget` is the internal composition input an edge
|
|
10
|
+
* supplies for a Markdown bind whose caller omitted the target: the public package-root
|
|
11
|
+
* composition leaves it targetless, while the CLI names the invocation branch.
|
|
12
|
+
*/
|
|
13
|
+
export declare function bindKeiyaku(input: BindInput, createHandle: typeof createKeiyakuHandle, execution?: ExecutionContext, composition?: LocalContractCompositionCapture, omittedMarkdownTarget?: BindTargetSelection): Promise<BindOutcome>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @architectureCompositionRoot */
|
|
2
2
|
import { localExecutionContext } from "../akuma/requests.js";
|
|
3
|
-
import {
|
|
3
|
+
import { decodeCanonicalContractDocument } from "../body/render.js";
|
|
4
4
|
import { regionWarnings } from "../body/region.js";
|
|
5
5
|
import { contractId } from "../core/facts/types.js";
|
|
6
6
|
import { withGitDecodeChannel } from "../git/read-observation.js";
|
|
@@ -33,6 +33,7 @@ function bindInput(input, composition) {
|
|
|
33
33
|
if (typeof forkOf !== "string")
|
|
34
34
|
throw new TypeError("forkOf must be a ContractId");
|
|
35
35
|
}
|
|
36
|
+
const derived = forkOf === undefined ? derivedGates(composition, gateNames(values.gates)) : undefined;
|
|
36
37
|
return {
|
|
37
38
|
forkOf: forkOf === undefined ? undefined : contractId(forkOf),
|
|
38
39
|
scope: scopeForRepo(values.repo),
|
|
@@ -40,12 +41,17 @@ function bindInput(input, composition) {
|
|
|
40
41
|
actor,
|
|
41
42
|
target: values.target,
|
|
42
43
|
task: forkOf === undefined ? taskOption(values.task) : undefined,
|
|
43
|
-
gates:
|
|
44
|
+
gates: derived,
|
|
44
45
|
after: forkOf === undefined ? normalizedList(values.after, "after", contractId) : undefined,
|
|
45
46
|
};
|
|
46
47
|
});
|
|
47
48
|
}
|
|
48
|
-
|
|
49
|
+
/**
|
|
50
|
+
* One Contract bind. `omittedMarkdownTarget` is the internal composition input an edge
|
|
51
|
+
* supplies for a Markdown bind whose caller omitted the target: the public package-root
|
|
52
|
+
* composition leaves it targetless, while the CLI names the invocation branch.
|
|
53
|
+
*/
|
|
54
|
+
export async function bindKeiyaku(input, createHandle, execution = localExecutionContext(), composition = captureLocalContractComposition(), omittedMarkdownTarget = { kind: "targetless" }) {
|
|
49
55
|
const prepared = bindInput(input, composition);
|
|
50
56
|
const hooks = derivedHooks(composition);
|
|
51
57
|
const { forkOf, scope, document, target, actor } = prepared;
|
|
@@ -78,7 +84,7 @@ export async function bindKeiyaku(input, createHandle, execution = localExecutio
|
|
|
78
84
|
}
|
|
79
85
|
if (document === undefined)
|
|
80
86
|
throw new Error("Markdown bind requires its prepared document");
|
|
81
|
-
return await markdownBind(prepared, document, hooks, scope, channel, accumulator, handle);
|
|
87
|
+
return await markdownBind(prepared, document, hooks, scope, channel, accumulator, handle, omittedMarkdownTarget);
|
|
82
88
|
})();
|
|
83
89
|
return completed;
|
|
84
90
|
}, (error) => {
|
|
@@ -162,11 +168,11 @@ async function reconcileAll(accumulator, id, scope, channel, hooks) {
|
|
|
162
168
|
}
|
|
163
169
|
}
|
|
164
170
|
// eslint-disable-next-line max-params -- Keep this local operation's custody, admission, and policy witnesses explicit.
|
|
165
|
-
async function markdownBind(prepared, document, hooks, scope, channel, accumulator, handle) {
|
|
171
|
+
async function markdownBind(prepared, document, hooks, scope, channel, accumulator, handle, omittedMarkdownTarget) {
|
|
166
172
|
const { task, target, actor, gates, after } = prepared;
|
|
167
173
|
if (gates === undefined || after === undefined)
|
|
168
174
|
throw new Error("Markdown bind requires prepared terms");
|
|
169
|
-
const targetSelection = target !== undefined ? { kind: "explicit", target } :
|
|
175
|
+
const targetSelection = target !== undefined ? { kind: "explicit", target } : omittedMarkdownTarget;
|
|
170
176
|
const admission = await prepareMarkdownBind({
|
|
171
177
|
scope,
|
|
172
178
|
channel,
|
|
@@ -183,10 +189,14 @@ async function markdownBind(prepared, document, hooks, scope, channel, accumulat
|
|
|
183
189
|
if (leading.kind !== "accepted")
|
|
184
190
|
return expected(undefined, leading);
|
|
185
191
|
const id = leading.value.contractId;
|
|
186
|
-
|
|
187
|
-
|
|
192
|
+
const warnings = regionWarnings(document.region);
|
|
193
|
+
accumulator.extendConclusions(id, {
|
|
194
|
+
keiyaku: handle(id),
|
|
195
|
+
warnings,
|
|
196
|
+
});
|
|
197
|
+
const value = await bindComplete(accumulator, id, scope, channel, leading, hooks, async () => bindValue(handle(id), await observeRegion(scope, channel, id, document.region), warnings));
|
|
188
198
|
return acceptedOutcome("bind", id, accumulator, value);
|
|
189
199
|
}
|
|
190
200
|
function parseMarkdown(markdown) {
|
|
191
|
-
return
|
|
201
|
+
return decodeCanonicalContractDocument(markdown, { requireTimeout: true });
|
|
192
202
|
}
|
|
@@ -16,6 +16,7 @@ export declare class ContractExecution {
|
|
|
16
16
|
private get scope();
|
|
17
17
|
private get execution();
|
|
18
18
|
private get composition();
|
|
19
|
+
private amendInput;
|
|
19
20
|
amend(input: AmendInput): Promise<AmendOutcome>;
|
|
20
21
|
/** One promise with an optional observation callback; observation never delays custody. */
|
|
21
22
|
deliver(input?: DeliverInput, options?: MutationObservation): Promise<DeliverOutcome>;
|
|
@@ -44,16 +44,20 @@ export class ContractExecution {
|
|
|
44
44
|
get composition() {
|
|
45
45
|
return this.seat.composition;
|
|
46
46
|
}
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
amendInput(input) {
|
|
48
|
+
return validated(() => {
|
|
49
49
|
const values = requireInput(input, "amend input", ["actor", "markdown", "gates", "after"]);
|
|
50
|
+
const derived = values.gates === undefined ? undefined : derivedGates(this.composition, gateNames(values.gates));
|
|
50
51
|
return {
|
|
51
52
|
markdown: values.markdown === undefined ? undefined : requireMarkdown(values.markdown),
|
|
52
|
-
gates:
|
|
53
|
+
gates: derived,
|
|
53
54
|
prerequisites: values.after === undefined ? undefined : normalizedList(values.after, "after", contractId),
|
|
54
55
|
actor: actorOption(values.actor).actor,
|
|
55
56
|
};
|
|
56
57
|
});
|
|
58
|
+
}
|
|
59
|
+
async amend(input) {
|
|
60
|
+
const { markdown, gates, prerequisites, actor } = this.amendInput(input);
|
|
57
61
|
const hooks = derivedHooks(this.composition);
|
|
58
62
|
const amendmentPlan = markdown === undefined ? undefined : validated(() => prepareAmendDocument(markdown));
|
|
59
63
|
validated(() => {
|
|
@@ -97,7 +101,11 @@ export class ContractExecution {
|
|
|
97
101
|
leading: accepted,
|
|
98
102
|
hooks,
|
|
99
103
|
verificationResidueRecorded: false,
|
|
100
|
-
value: () => ({
|
|
104
|
+
value: () => ({
|
|
105
|
+
documentDiff: diff,
|
|
106
|
+
changes,
|
|
107
|
+
...region,
|
|
108
|
+
}),
|
|
101
109
|
});
|
|
102
110
|
return acceptedOutcome("amend", this.id, accumulator, value);
|
|
103
111
|
});
|
|
@@ -11,7 +11,7 @@ export type LocalContractCompositionCapture = Readonly<{
|
|
|
11
11
|
/**
|
|
12
12
|
* Hooks, freshness, and gate bundles are read from the captured Settings only at the operation
|
|
13
13
|
* that consumes them. Bare core (omitted Settings) keeps empty hooks, false freshness, and
|
|
14
|
-
*
|
|
14
|
+
* built-in gate words; a broken selected namespace fails before any admission.
|
|
15
15
|
*/
|
|
16
16
|
export declare function derivedHooks(composition: LocalContractCompositionCapture): WorktreeHooks;
|
|
17
17
|
/** The two Settings-derived Contract policies one mutating operation may consume. */
|
|
@@ -20,6 +20,6 @@ export declare function derivedContractPolicy(composition: LocalContractComposit
|
|
|
20
20
|
requireBranchesToBeUpToDate: boolean;
|
|
21
21
|
}>;
|
|
22
22
|
export declare function gateNames(value: unknown): readonly string[] | undefined;
|
|
23
|
-
/**
|
|
23
|
+
/** Built-in words and configured bundles share validation, first-seen accumulation, and freezing. */
|
|
24
24
|
export declare function derivedGates(composition: LocalContractCompositionCapture, names: readonly string[] | undefined): readonly Gate[];
|
|
25
25
|
export declare function captureLocalContractComposition(input?: LocalContractComposition): LocalContractCompositionCapture;
|