@astrosheep/keiyaku 4.6.1 → 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/akuma/providers/pi/index.d.ts +3 -4
- package/build/src/akuma/providers/pi/index.js +30 -26
- 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
|
@@ -13,9 +13,8 @@ export function frameRule(headLines) {
|
|
|
13
13
|
const width = headLines.reduce((widest, line) => Math.max(widest, displayColumns(line)), 0);
|
|
14
14
|
return "─".repeat(width);
|
|
15
15
|
}
|
|
16
|
-
/** Tool rows
|
|
17
|
-
const
|
|
18
|
-
const RECENT_TOOL_BUDGET = 2;
|
|
16
|
+
/** Tool rows an activity view prints after each say or Tell checkpoint; the surplus folds in place. */
|
|
17
|
+
const TOOL_BUDGET = 3;
|
|
19
18
|
function identity(id, alias) {
|
|
20
19
|
return `${id}${alias === undefined ? "" : ` (${alias})`}`;
|
|
21
20
|
}
|
|
@@ -434,57 +433,6 @@ function inFlightSay(activity, row) {
|
|
|
434
433
|
}
|
|
435
434
|
return newest !== undefined && newest.sequence === row.sequence;
|
|
436
435
|
}
|
|
437
|
-
function coalesceDeferredGaps(state) {
|
|
438
|
-
state.deferred = state.deferred.reduce((entries, entry) => {
|
|
439
|
-
const previous = entries.at(-1);
|
|
440
|
-
if (entry.kind === "gap" && previous?.kind === "gap") {
|
|
441
|
-
entries[entries.length - 1] = { kind: "gap", count: previous.count + entry.count };
|
|
442
|
-
}
|
|
443
|
-
else {
|
|
444
|
-
entries.push(entry);
|
|
445
|
-
}
|
|
446
|
-
return entries;
|
|
447
|
-
}, []);
|
|
448
|
-
}
|
|
449
|
-
function omitOldestDeferredTool(state) {
|
|
450
|
-
const index = state.deferred.findIndex((entry) => entry.kind === "row" && isBoundedStreamTool(entry.row));
|
|
451
|
-
if (index === -1)
|
|
452
|
-
throw new Error("activity tail lost its pending tool");
|
|
453
|
-
state.deferred[index] = { kind: "gap", count: 1 };
|
|
454
|
-
coalesceDeferredGaps(state);
|
|
455
|
-
}
|
|
456
|
-
/** A say is a checkpoint: only tools after the last say may occupy the recent tail. */
|
|
457
|
-
function omitPreSayTools(state) {
|
|
458
|
-
state.deferred = state.deferred.map((entry) => entry.kind === "row" && isBoundedStreamTool(entry.row) ? { kind: "gap", count: 1 } : entry);
|
|
459
|
-
coalesceDeferredGaps(state);
|
|
460
|
-
}
|
|
461
|
-
/** Emit only a prefix whose omission runs can no longer join an unresolved tail tool. */
|
|
462
|
-
function flushSafeActivityPrefix(state, lines, context, layout) {
|
|
463
|
-
for (;;) {
|
|
464
|
-
const first = state.deferred[0];
|
|
465
|
-
if (first === undefined || (first.kind === "row" && isBoundedStreamTool(first.row)))
|
|
466
|
-
return;
|
|
467
|
-
if (first.kind === "row") {
|
|
468
|
-
state.deferred.shift();
|
|
469
|
-
renderStreamRow(state, first.row, lines, { context, layout, inFlightSay: first.inFlightSay });
|
|
470
|
-
continue;
|
|
471
|
-
}
|
|
472
|
-
const next = state.deferred[1];
|
|
473
|
-
if (next === undefined || (next.kind === "row" && isBoundedStreamTool(next.row)))
|
|
474
|
-
return;
|
|
475
|
-
state.deferred.shift();
|
|
476
|
-
lines.push(layout.marker(first.count));
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
function renderCurrentTurnBoundary(state, activity, lines, context, layout) {
|
|
480
|
-
const boundary = currentTurnBoundary(activity);
|
|
481
|
-
if (boundary !== undefined && !state.renderedBoundaries.has(boundary.turnSequence)) {
|
|
482
|
-
state.renderedBoundaries.add(boundary.turnSequence);
|
|
483
|
-
if (boundary.row.kind !== "thought")
|
|
484
|
-
renderStreamRow(state, boundary.row, lines, { context, layout });
|
|
485
|
-
}
|
|
486
|
-
return boundary;
|
|
487
|
-
}
|
|
488
436
|
function rememberLiveRows(state, activity) {
|
|
489
437
|
for (const row of activity.rows) {
|
|
490
438
|
if (row.kind === "tool" && row.state === "active")
|
|
@@ -503,8 +451,28 @@ function rememberLiveRows(state, activity) {
|
|
|
503
451
|
state.liveRows.delete(row.sequence);
|
|
504
452
|
}
|
|
505
453
|
}
|
|
506
|
-
|
|
507
|
-
|
|
454
|
+
/** A visible row first releases the untimed omission count accumulated before it. */
|
|
455
|
+
function emitRow(state, emissions, emission) {
|
|
456
|
+
if (state.omitted > 0)
|
|
457
|
+
emissions.push({ kind: "gap", count: state.omitted });
|
|
458
|
+
state.omitted = 0;
|
|
459
|
+
emissions.push(emission);
|
|
460
|
+
}
|
|
461
|
+
function emitCurrentTurnBoundary(state, activity, emissions) {
|
|
462
|
+
const boundary = currentTurnBoundary(activity);
|
|
463
|
+
if (boundary !== undefined && !state.renderedBoundaries.has(boundary.turnSequence)) {
|
|
464
|
+
state.renderedBoundaries.add(boundary.turnSequence);
|
|
465
|
+
if (boundary.row.kind !== "thought")
|
|
466
|
+
emitRow(state, emissions, { kind: "row", row: boundary.row });
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Decide each newly settled row once, when first observed: it prints now or
|
|
471
|
+
* becomes part of an untimed omission count. No timestamped row is held for a
|
|
472
|
+
* later observation, so concurrent streams merge without moving backward.
|
|
473
|
+
*/
|
|
474
|
+
function observeActivitySnapshot(state, activity) {
|
|
475
|
+
const emissions = [];
|
|
508
476
|
const boundary = currentTurnBoundary(activity);
|
|
509
477
|
rememberPendingTells(state, activity);
|
|
510
478
|
// A row newly selected as this Turn's typed opening must still respect the
|
|
@@ -522,54 +490,48 @@ function observeActivitySnapshot(state, activity, context, layout) {
|
|
|
522
490
|
row.sequence > state.newestSettledSequence);
|
|
523
491
|
rememberLiveRows(state, activity);
|
|
524
492
|
if (observedRows.length === 0)
|
|
525
|
-
return
|
|
493
|
+
return emissions;
|
|
526
494
|
for (const row of observedRows)
|
|
527
495
|
state.pendingTellSequences.delete(row.sequence);
|
|
528
496
|
state.newestSettledSequence = observedRows.reduce((newest, row) => Math.max(newest, row.sequence), state.newestSettledSequence ?? observedRows[0].sequence);
|
|
529
|
-
const
|
|
530
|
-
|
|
531
|
-
if (row.kind === "said") {
|
|
532
|
-
omitPreSayTools(state);
|
|
533
|
-
lines.push(...flushActivityTail(state, context, layout));
|
|
534
|
-
renderStreamRow(state, row, lines, { context, layout, inFlightSay: inFlightSay(activity, row) });
|
|
535
|
-
continue;
|
|
536
|
-
}
|
|
537
|
-
if (isBoundedStreamTool(row) && state.openingTools < OPENING_TOOL_BUDGET) {
|
|
538
|
-
state.openingTools += 1;
|
|
539
|
-
renderStreamRow(state, row, lines, { context, layout, inFlightSay: inFlightSay(activity, row) });
|
|
497
|
+
for (const row of observedRows) {
|
|
498
|
+
if (row.kind === "thought")
|
|
540
499
|
continue;
|
|
500
|
+
// A failed tool is evidence, not routine progress, so it always prints and spends no budget.
|
|
501
|
+
const failed = row.kind === "tool" && typeof row.state === "object" && row.state.status === "error";
|
|
502
|
+
if (isBoundedStreamTool(row) && !failed) {
|
|
503
|
+
if (state.checkpointTools >= TOOL_BUDGET) {
|
|
504
|
+
state.omitted += 1;
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
state.checkpointTools += 1;
|
|
541
508
|
}
|
|
542
|
-
if (
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
}
|
|
546
|
-
state.deferred.push({ kind: "row", row, inFlightSay: inFlightSay(activity, row) });
|
|
547
|
-
if (isBoundedStreamTool(row)) {
|
|
548
|
-
const pendingTools = state.deferred.filter((entry) => entry.kind === "row" && isBoundedStreamTool(entry.row)).length;
|
|
549
|
-
if (pendingTools > RECENT_TOOL_BUDGET)
|
|
550
|
-
omitOldestDeferredTool(state);
|
|
551
|
-
}
|
|
552
|
-
flushSafeActivityPrefix(state, lines, context, layout);
|
|
509
|
+
else if (row.kind === "said" || row.kind === "tell")
|
|
510
|
+
state.checkpointTools = 0;
|
|
511
|
+
emitRow(state, emissions, { kind: "row", row, inFlightSay: inFlightSay(activity, row) });
|
|
553
512
|
}
|
|
554
|
-
return
|
|
513
|
+
return emissions;
|
|
555
514
|
}
|
|
556
|
-
function
|
|
515
|
+
function renderEmissions(state, emissions, context, layout) {
|
|
557
516
|
const lines = [];
|
|
558
|
-
for (const
|
|
559
|
-
if (
|
|
560
|
-
lines.push(layout.marker(
|
|
517
|
+
for (const emission of emissions) {
|
|
518
|
+
if (emission.kind === "gap")
|
|
519
|
+
lines.push(layout.marker(emission.count));
|
|
561
520
|
else
|
|
562
|
-
renderStreamRow(state,
|
|
521
|
+
renderStreamRow(state, emission.row, lines, {
|
|
522
|
+
context,
|
|
523
|
+
layout,
|
|
524
|
+
...(emission.inFlightSay === undefined ? {} : { inFlightSay: emission.inFlightSay }),
|
|
525
|
+
...(emission.unsettled === undefined ? {} : { unsettled: emission.unsettled }),
|
|
526
|
+
});
|
|
563
527
|
}
|
|
564
|
-
state.deferred = [];
|
|
565
528
|
return lines;
|
|
566
529
|
}
|
|
567
530
|
/**
|
|
568
|
-
* Append-only live view over one command's successive settled snapshots.
|
|
569
|
-
*
|
|
570
|
-
*
|
|
571
|
-
*
|
|
572
|
-
* in place. Other narrative rows wait behind undecided tail tools.
|
|
531
|
+
* Append-only live view over one command's successive settled snapshots.
|
|
532
|
+
* After each say or Tell, the first three tools print as they settle; later
|
|
533
|
+
* tools until the next checkpoint fold into one omission marker. Failed tools
|
|
534
|
+
* always print.
|
|
573
535
|
*/
|
|
574
536
|
export function activityStream(context, layout = plainLayout()) {
|
|
575
537
|
const state = {
|
|
@@ -579,12 +541,12 @@ export function activityStream(context, layout = plainLayout()) {
|
|
|
579
541
|
previousClock: undefined,
|
|
580
542
|
renderedBoundaries: new Set(),
|
|
581
543
|
admittedTellSequences: new Set(),
|
|
582
|
-
|
|
583
|
-
|
|
544
|
+
checkpointTools: 0,
|
|
545
|
+
omitted: 0,
|
|
584
546
|
liveRows: new Map(),
|
|
585
547
|
};
|
|
586
548
|
const seed = (activity, alreadyRenderedSequence) => {
|
|
587
|
-
const
|
|
549
|
+
const emissions = [];
|
|
588
550
|
if (alreadyRenderedSequence !== undefined) {
|
|
589
551
|
state.admissionSequence = alreadyRenderedSequence;
|
|
590
552
|
state.admittedTellSequences.add(alreadyRenderedSequence);
|
|
@@ -595,46 +557,54 @@ export function activityStream(context, layout = plainLayout()) {
|
|
|
595
557
|
if (alreadyRenderedSequence !== undefined && boundary.row.sequence > alreadyRenderedSequence) {
|
|
596
558
|
const beforeBoundary = baselineOmissionCount(activity, alreadyRenderedSequence, boundary.row.sequence);
|
|
597
559
|
if (beforeBoundary > 0)
|
|
598
|
-
|
|
560
|
+
emissions.push({ kind: "gap", count: beforeBoundary });
|
|
599
561
|
}
|
|
600
562
|
if (alreadyRenderedSequence !== undefined && boundary.row.sequence <= alreadyRenderedSequence)
|
|
601
563
|
state.renderedBoundaries.add(boundary.turnSequence);
|
|
602
564
|
else
|
|
603
|
-
|
|
565
|
+
emitCurrentTurnBoundary(state, activity, emissions);
|
|
604
566
|
rememberLiveRows(state, activity);
|
|
605
567
|
const omitted = baselineOmissionCount(activity, alreadyRenderedSequence === undefined
|
|
606
568
|
? boundary.row.sequence
|
|
607
569
|
: Math.max(boundary.row.sequence, alreadyRenderedSequence));
|
|
608
570
|
if (omitted > 0)
|
|
609
|
-
|
|
571
|
+
emissions.push({ kind: "gap", count: omitted });
|
|
610
572
|
}
|
|
611
573
|
rememberPendingTells(state, activity);
|
|
612
574
|
rememberLiveRows(state, activity);
|
|
613
575
|
const rows = settledRows(activity);
|
|
614
576
|
if (rows.length > 0)
|
|
615
577
|
state.newestSettledSequence = rows.reduce((newest, row) => Math.max(newest, row.sequence), rows[0].sequence);
|
|
616
|
-
return
|
|
578
|
+
return emissions;
|
|
617
579
|
};
|
|
618
|
-
const observe = (activity) => observeActivitySnapshot(state, activity, context, layout);
|
|
619
|
-
const frame = () => groupedEntries([...state.liveRows.values()]
|
|
620
|
-
.sort((left, right) => left.sequence - right.sequence)
|
|
621
|
-
.map((row) => ({ kind: "row", row })), context, layout, { live: true, inFlightSay: (row) => row.kind === "said" });
|
|
622
580
|
const flush = () => {
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
581
|
+
const emissions = [];
|
|
582
|
+
if (state.omitted > 0)
|
|
583
|
+
emissions.push({ kind: "gap", count: state.omitted });
|
|
584
|
+
state.omitted = 0;
|
|
626
585
|
for (const row of [...state.liveRows.values()].sort((left, right) => left.sequence - right.sequence)) {
|
|
627
586
|
const unresolved = row.kind === "tool" && row.state === "active" ? { ...row, state: "unsettled" } : row;
|
|
628
|
-
|
|
629
|
-
context,
|
|
630
|
-
layout,
|
|
631
|
-
unsettled: true,
|
|
632
|
-
});
|
|
587
|
+
emissions.push({ kind: "row", row: unresolved, unsettled: true });
|
|
633
588
|
}
|
|
634
589
|
state.liveRows.clear();
|
|
635
|
-
return
|
|
590
|
+
return emissions;
|
|
636
591
|
};
|
|
637
|
-
|
|
592
|
+
const render = (emissions) => renderEmissions(state, emissions, context, layout);
|
|
593
|
+
const frame = () => groupedEntries([...state.liveRows.values()]
|
|
594
|
+
.sort((left, right) => left.sequence - right.sequence)
|
|
595
|
+
.map((row) => ({ kind: "row", row })), context, layout, { live: true, inFlightSay: (row) => row.kind === "said" });
|
|
596
|
+
const observe = (activity) => render(observeActivitySnapshot(state, activity));
|
|
597
|
+
return Object.assign(observe, {
|
|
598
|
+
seed: (activity, alreadyRenderedSequence) => render(seed(activity, alreadyRenderedSequence)),
|
|
599
|
+
frame,
|
|
600
|
+
flush: () => render(flush()),
|
|
601
|
+
emissions: {
|
|
602
|
+
observe: (activity) => observeActivitySnapshot(state, activity),
|
|
603
|
+
seed,
|
|
604
|
+
flush,
|
|
605
|
+
},
|
|
606
|
+
render,
|
|
607
|
+
});
|
|
638
608
|
}
|
|
639
609
|
function conclusionMarkVerb(status, outcome) {
|
|
640
610
|
if (outcome === "failed" || (status !== undefined && failedOutcomeDiagnostic(status) !== undefined))
|
|
@@ -773,10 +743,11 @@ function observeWaitRound(state, round, context, now) {
|
|
|
773
743
|
lines.push(...snapshotHeading(sole.status.id, sole.alias, sole.contract));
|
|
774
744
|
}
|
|
775
745
|
}
|
|
746
|
+
const parts = [];
|
|
776
747
|
for (const { status, rows } of round) {
|
|
777
748
|
const known = state.streams.get(status.id);
|
|
778
749
|
if (known !== undefined) {
|
|
779
|
-
|
|
750
|
+
parts.push({ stream: known, emissions: known.emissions.observe({ snapshot: status.timeline, rows }) });
|
|
780
751
|
}
|
|
781
752
|
else {
|
|
782
753
|
// Only a plural wait attributes its rows; a single-target stream keeps the plain row grammar.
|
|
@@ -785,13 +756,51 @@ function observeWaitRound(state, round, context, now) {
|
|
|
785
756
|
: plainLayout());
|
|
786
757
|
state.streams.set(status.id, stream);
|
|
787
758
|
// Seed marks skipped retained evidence without spending this command's live tool budget.
|
|
788
|
-
|
|
759
|
+
parts.push({ stream, emissions: stream.emissions.seed({ snapshot: status.timeline, rows }) });
|
|
789
760
|
}
|
|
790
761
|
if (!state.settledAt.has(status.id) && defaultWaitComplete(status))
|
|
791
762
|
state.settledAt.set(status.id, settleMoment(status) ?? now());
|
|
792
763
|
}
|
|
764
|
+
lines.push(...mergeStreamEmissions(parts));
|
|
793
765
|
return lines;
|
|
794
766
|
}
|
|
767
|
+
/**
|
|
768
|
+
* Merge one observation's decided output across sources by row time. Each
|
|
769
|
+
* source keeps its own order; an omission count travels with the row after it,
|
|
770
|
+
* or with the row before it when it trails. Ties keep selection order.
|
|
771
|
+
*/
|
|
772
|
+
function mergeStreamEmissions(parts) {
|
|
773
|
+
const queues = parts.map(({ stream, emissions }) => {
|
|
774
|
+
const units = [];
|
|
775
|
+
let pending = [];
|
|
776
|
+
for (const emission of emissions) {
|
|
777
|
+
pending.push(emission);
|
|
778
|
+
if (emission.kind !== "row")
|
|
779
|
+
continue;
|
|
780
|
+
const at = Date.parse(emission.row.at);
|
|
781
|
+
units.push({ at: Number.isFinite(at) ? at : (units.at(-1)?.at ?? Number.NEGATIVE_INFINITY), emissions: pending });
|
|
782
|
+
pending = [];
|
|
783
|
+
}
|
|
784
|
+
if (pending.length > 0) {
|
|
785
|
+
const last = units.at(-1);
|
|
786
|
+
if (last === undefined)
|
|
787
|
+
units.push({ at: Number.NEGATIVE_INFINITY, emissions: pending });
|
|
788
|
+
else
|
|
789
|
+
last.emissions.push(...pending);
|
|
790
|
+
}
|
|
791
|
+
return { stream, units };
|
|
792
|
+
});
|
|
793
|
+
const lines = [];
|
|
794
|
+
for (;;) {
|
|
795
|
+
let next;
|
|
796
|
+
for (const queue of queues)
|
|
797
|
+
if (queue.units.length > 0 && (next === undefined || queue.units[0].at < next.units[0].at))
|
|
798
|
+
next = queue;
|
|
799
|
+
if (next === undefined)
|
|
800
|
+
return lines;
|
|
801
|
+
lines.push(...next.stream.render(next.units.shift().emissions));
|
|
802
|
+
}
|
|
803
|
+
}
|
|
795
804
|
/**
|
|
796
805
|
* A conclusion clause asserts real waiting: a target that settled at or after
|
|
797
806
|
* this wait began keeps its duration, a target already settled names no
|
|
@@ -851,10 +860,11 @@ function orderedWaitIds(state, result) {
|
|
|
851
860
|
}
|
|
852
861
|
return ids;
|
|
853
862
|
}
|
|
863
|
+
function flushWaitStreams(state) {
|
|
864
|
+
return mergeStreamEmissions([...state.streams.values()].map((stream) => ({ stream, emissions: stream.emissions.flush() })));
|
|
865
|
+
}
|
|
854
866
|
function concludeWaitStream(state, result, startedAt, now) {
|
|
855
|
-
const tail =
|
|
856
|
-
for (const stream of state.streams.values())
|
|
857
|
-
tail.push(...stream.flush());
|
|
867
|
+
const tail = flushWaitStreams(state);
|
|
858
868
|
const end = now();
|
|
859
869
|
for (const observation of result.observations)
|
|
860
870
|
registerWaitSource(state, observation.status.id, undefined, observation.contract);
|
|
@@ -913,7 +923,7 @@ export function waitObservationStream(context, options = {}) {
|
|
|
913
923
|
};
|
|
914
924
|
const observe = (round) => observeWaitRound(state, round, context, now);
|
|
915
925
|
const frame = () => [...state.streams.values()].flatMap((stream) => stream.frame());
|
|
916
|
-
const flush = () =>
|
|
926
|
+
const flush = () => flushWaitStreams(state);
|
|
917
927
|
const conclude = (result) => concludeWaitStream(state, result, startedAt, now);
|
|
918
928
|
return { select, observe, frame, flush, conclude, streamed: () => state.observed };
|
|
919
929
|
}
|
|
@@ -98,7 +98,7 @@ function readText(call) {
|
|
|
98
98
|
: call.offset !== undefined
|
|
99
99
|
? ` · from L${call.offset}`
|
|
100
100
|
: call.limit !== undefined
|
|
101
|
-
? ` · ${call.limit} lines`
|
|
101
|
+
? ` · ${call.limit} ${call.limit === 1 ? "line" : "lines"}`
|
|
102
102
|
: "";
|
|
103
103
|
return { label: "read", text: `${path}${detail}`, pathPreview: { before: "", path, detail } };
|
|
104
104
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { effectCleanup, effectExecutionStops } from "./effects.js";
|
|
2
|
-
import { executionCleanupLines, executionStopLines, receiptPayload, receiptRow,
|
|
2
|
+
import { executionCleanupLines, executionStopLines, receiptPayload, receiptRow, stopLines, titleLines, } from "./receipt.js";
|
|
3
3
|
import { renderRefusalFacts } from "./refusal.js";
|
|
4
4
|
import { abbreviateGitIds, displayGitId } from "./contract-observation.js";
|
|
5
5
|
import { DEFAULT_CLI_COLUMNS, gitShortStat, renderTextBlock, safeText } from "./terminal.js";
|
|
@@ -16,11 +16,10 @@ function candidateLines(report, columns, addressed, abbreviations) {
|
|
|
16
16
|
return lines;
|
|
17
17
|
}
|
|
18
18
|
const identity = candidate.identity;
|
|
19
|
-
receiptRow(lines, " ", "candidate", [{ text: "ready" }], columns);
|
|
20
|
-
lines.push(`${CHILD}candidate ${displayGitId(identity.tenderSnapshot, abbreviations)}`);
|
|
19
|
+
receiptRow(lines, " ", "candidate", [{ text: "ready" }, { text: displayGitId(identity.tenderSnapshot, abbreviations), opaque: true }], columns);
|
|
21
20
|
lines.push(`${CHILD}integration result ${displayGitId(identity.integration.snapshot, abbreviations)}`);
|
|
22
21
|
if (!/^0{40}$/u.test(identity.integration.changeId))
|
|
23
|
-
lines.push(`${CHILD}content identity
|
|
22
|
+
lines.push(`${CHILD}content identity ${displayGitId(identity.integration.changeId, abbreviations)}`);
|
|
24
23
|
lines.push(...workspaceEvidence(candidate.workspace));
|
|
25
24
|
lines.push(...renderTextBlock(gitShortStat(candidate.scope), CHILD, columns));
|
|
26
25
|
if (candidate.scope.paths !== undefined) {
|
|
@@ -47,7 +46,6 @@ function verificationLines(verification, columns, addressed) {
|
|
|
47
46
|
}
|
|
48
47
|
if (verification.kind === "reused") {
|
|
49
48
|
receiptRow(lines, " ", "verification", [{ text: "reused" }, { text: verification.verdict }], columns);
|
|
50
|
-
lines.push(...reuseLines(verification, columns));
|
|
51
49
|
if (verification.summary !== undefined)
|
|
52
50
|
receiptPayload(lines, "summary", auditSummary(verification.summary));
|
|
53
51
|
return lines;
|
|
@@ -77,7 +75,7 @@ function targetLines(report, columns, addressed, abbreviations) {
|
|
|
77
75
|
const target = report.target;
|
|
78
76
|
const lines = [];
|
|
79
77
|
if (target.kind === "not-observed") {
|
|
80
|
-
receiptRow(lines, " ", "target", [{ text: "
|
|
78
|
+
receiptRow(lines, " ", "target", [{ text: "none" }], columns);
|
|
81
79
|
return lines;
|
|
82
80
|
}
|
|
83
81
|
if (target.kind === "placeable") {
|
|
@@ -81,10 +81,13 @@ export function renderArchetypeCatalogue(list) {
|
|
|
81
81
|
? []
|
|
82
82
|
: [
|
|
83
83
|
"",
|
|
84
|
-
...list.rows.flatMap((row) =>
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
...list.rows.flatMap((row) => {
|
|
85
|
+
const facts = [
|
|
86
|
+
...(row.model === undefined ? [] : [safeText(row.model)]),
|
|
87
|
+
...(row.description === undefined ? [] : [safeText(row.description)]),
|
|
88
|
+
];
|
|
89
|
+
return [safeText(row.name), ...(facts.length === 0 ? [] : [` ${facts.join(" — ")}`])];
|
|
90
|
+
}),
|
|
88
91
|
...(list.hasMore ? ["…"] : []),
|
|
89
92
|
]),
|
|
90
93
|
].join("\n");
|
|
@@ -47,15 +47,13 @@ function journalBody(fact, workspace) {
|
|
|
47
47
|
}
|
|
48
48
|
case "amend":
|
|
49
49
|
return [...listFact("gates", fact.data.gates), ...listFact("after", fact.data.after)];
|
|
50
|
-
case "bound":
|
|
51
|
-
return [];
|
|
52
50
|
case "deliver": {
|
|
53
51
|
const { tenderSnapshot, integration, method, policy } = fact.data;
|
|
54
52
|
return [
|
|
55
53
|
` candidate ${shortGitId(tenderSnapshot)}`,
|
|
56
54
|
` predecessor commit ${shortGitId(integration.predecessor)}`,
|
|
57
55
|
` integration result ${shortGitId(integration.snapshot)}`,
|
|
58
|
-
` content identity
|
|
56
|
+
` content identity ${integration.changeId}`,
|
|
59
57
|
` method ${method}`,
|
|
60
58
|
` require branches up to date ${String(policy.requireBranchesToBeUpToDate)}`,
|
|
61
59
|
];
|
|
@@ -160,6 +158,7 @@ function latestVerification(beat) {
|
|
|
160
158
|
}
|
|
161
159
|
return latest;
|
|
162
160
|
}
|
|
161
|
+
const lineCount = (count) => `${count} line${count === 1 ? "" : "s"}`;
|
|
163
162
|
function skeletonBeatLines(beat, history) {
|
|
164
163
|
const first = beat.events[0];
|
|
165
164
|
if (first === undefined)
|
|
@@ -167,9 +166,9 @@ function skeletonBeatLines(beat, history) {
|
|
|
167
166
|
const full = beat.events.flatMap((event) => fullEventLines(event, history.workspace));
|
|
168
167
|
const evidenceSuffix = () => {
|
|
169
168
|
const count = foldedPayloadLines(full);
|
|
170
|
-
return count > 0 ? ` · ${count}
|
|
169
|
+
return count > 0 ? ` · ${lineCount(count)}` : "";
|
|
171
170
|
};
|
|
172
|
-
const payloadSuffix = (rendered) => rendered.length > 0 ? ` · ${rendered.length}
|
|
171
|
+
const payloadSuffix = (rendered) => rendered.length > 0 ? ` · ${lineCount(rendered.length)}` : "";
|
|
173
172
|
if (first.source === "dispatch")
|
|
174
173
|
return [`${clock(first)} dispatch · ${first.dispatch.akuId}`];
|
|
175
174
|
const fact = first.fact;
|
|
@@ -178,8 +177,6 @@ function skeletonBeatLines(beat, history) {
|
|
|
178
177
|
const dispatch = beat.events.find((event) => event.source === "dispatch");
|
|
179
178
|
return [`${clock(first)} ${bindLine(fact, dispatch)}`];
|
|
180
179
|
}
|
|
181
|
-
case "bound":
|
|
182
|
-
return [`${clock(first)} bound`];
|
|
183
180
|
case "deliver": {
|
|
184
181
|
const verdict = latestVerification(beat)?.data.verdict;
|
|
185
182
|
return [
|
|
@@ -213,7 +210,7 @@ function skeletonBeatLines(beat, history) {
|
|
|
213
210
|
];
|
|
214
211
|
default: {
|
|
215
212
|
const folded = foldedPayloadLines(full);
|
|
216
|
-
return [`${clock(first)} ${eventKind(first)}${folded > 0 ? ` · ${folded}
|
|
213
|
+
return [`${clock(first)} ${eventKind(first)}${folded > 0 ? ` · ${lineCount(folded)}` : ""}`];
|
|
217
214
|
}
|
|
218
215
|
}
|
|
219
216
|
}
|
|
@@ -227,8 +224,6 @@ function skeletonState(history) {
|
|
|
227
224
|
return lifecycleWord("claimed");
|
|
228
225
|
if (journal.some((event) => event.fact.kind === "abandoned"))
|
|
229
226
|
return "abandoned";
|
|
230
|
-
if (journal.some((event) => event.fact.kind === "deliver" || event.fact.kind === "reintegrated"))
|
|
231
|
-
return "delivered";
|
|
232
227
|
return "bound";
|
|
233
228
|
}
|
|
234
229
|
function skeletonBeats(history) {
|
|
@@ -244,15 +239,10 @@ function skeletonBeats(history) {
|
|
|
244
239
|
if (event.source === "journal" && event.fact.kind === "bind") {
|
|
245
240
|
for (let next = index + 1; next < events.length; next += 1) {
|
|
246
241
|
const candidate = events[next];
|
|
247
|
-
if (candidate.source
|
|
248
|
-
grouped.push(candidate);
|
|
249
|
-
consumed.add(next);
|
|
242
|
+
if (candidate.source !== "dispatch")
|
|
250
243
|
break;
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
grouped.push(candidate);
|
|
254
|
-
consumed.add(next);
|
|
255
|
-
}
|
|
244
|
+
grouped.push(candidate);
|
|
245
|
+
consumed.add(next);
|
|
256
246
|
}
|
|
257
247
|
}
|
|
258
248
|
if (event.source === "journal" && (event.fact.kind === "deliver" || event.fact.kind === "reintegrated")) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { effectCleanup, effectExecutionStops, effectLags, effectRecoverySnapshot, effectRetainedCheckouts, effectRetainedWorktrees, effectRetiredWorktrees, effectSettlementLags, } from "./effects.js";
|
|
2
2
|
import { renderAcceptedAudit } from "./audit.js";
|
|
3
|
-
import { appendHookPayload, executionCleanupLines, executionStopLines, gatesAwaitLines, hookFailureSummary, outcomeLines, receiptPayload, receiptRow,
|
|
3
|
+
import { appendHookPayload, executionCleanupLines, executionStopLines, gatesAwaitLines, hookFailureSummary, outcomeLines, receiptPayload, receiptRow, stopLines, titleLines, } from "./receipt.js";
|
|
4
4
|
import { abbreviateGitIds, displayGitId, lifecycleWord } from "./contract-observation.js";
|
|
5
5
|
import { renderDiffstat } from "./akuma-tool.js";
|
|
6
6
|
import { DEFAULT_CLI_COLUMNS, renderOpaqueBlock, safeText, tone } from "./terminal.js";
|
|
@@ -163,9 +163,6 @@ function acceptedRecord(result, columns) {
|
|
|
163
163
|
const recoverySnapshot = effectRecoverySnapshot(result.effects);
|
|
164
164
|
if (recoverySnapshot !== undefined)
|
|
165
165
|
receiptRow(record, " ", "recovery snapshot", [{ text: recoverySnapshot, opaque: true }], columns);
|
|
166
|
-
if (result.operation === "deliver") {
|
|
167
|
-
pushBlock(record, reuseLines(result.value.verificationReuse, columns));
|
|
168
|
-
}
|
|
169
166
|
return record;
|
|
170
167
|
}
|
|
171
168
|
function acceptedLagRows(result, columns) {
|
|
@@ -367,14 +364,14 @@ function renderAcceptedAmend(result, columns, color) {
|
|
|
367
364
|
lines.push(...acceptedDeviations(result, columns, color), ...recordBlock(result, columns));
|
|
368
365
|
return lines.join("\n");
|
|
369
366
|
}
|
|
370
|
-
function deliverIdentityLines(result, abbreviations, columns) {
|
|
367
|
+
function deliverIdentityLines(result, abbreviations, columns, kept) {
|
|
371
368
|
const lines = [];
|
|
372
369
|
if (result.value.leading !== undefined && result.value.leading.kind === "already-admitted")
|
|
373
370
|
receiptRow(lines, " ", "leading", [{ text: result.value.leading.kind.replaceAll("-", " ") }], columns);
|
|
374
371
|
if (result.value.tenderSnapshot !== undefined)
|
|
375
|
-
receiptRow(lines, " ", "candidate", [{ text: displayGitId(result.value.tenderSnapshot, abbreviations)
|
|
372
|
+
receiptRow(lines, " ", "candidate", [{ text: `${displayGitId(result.value.tenderSnapshot, abbreviations)}${kept ? " · kept" : ""}`, opaque: true }], columns);
|
|
376
373
|
if (result.value.integration !== undefined && !/^0{40}$/u.test(result.value.integration.changeId))
|
|
377
|
-
receiptRow(lines, " ", "content identity
|
|
374
|
+
receiptRow(lines, " ", "content identity", [{ text: displayGitId(result.value.integration.changeId, abbreviations), opaque: true }], columns);
|
|
378
375
|
return lines;
|
|
379
376
|
}
|
|
380
377
|
function renderAcceptedDeliver(result, columns) {
|
|
@@ -387,7 +384,7 @@ function renderAcceptedDeliver(result, columns) {
|
|
|
387
384
|
result.value.completion?.predecessor ?? "",
|
|
388
385
|
result.value.completion?.integration ?? "",
|
|
389
386
|
]);
|
|
390
|
-
lines.push(...deliverIdentityLines(result, abbreviations, columns));
|
|
387
|
+
lines.push(...deliverIdentityLines(result, abbreviations, columns, !complete));
|
|
391
388
|
if (complete)
|
|
392
389
|
lines.push(...completedPlacementLines(result, columns));
|
|
393
390
|
else {
|
|
@@ -404,8 +401,6 @@ function renderAcceptedDeliver(result, columns) {
|
|
|
404
401
|
lines.push(...stopLines(result.value.verification, columns, result.contract));
|
|
405
402
|
if (!complete && result.value.placement !== undefined)
|
|
406
403
|
lines.push(...stopLines(result.value.placement, columns, result.contract));
|
|
407
|
-
if (!complete)
|
|
408
|
-
receiptRow(lines, " ", "candidate", [{ text: "kept" }], columns);
|
|
409
404
|
lines.push(...continuationLines(result, columns), ...(complete ? obligationLines(result, columns) : recordBlock(result, columns)), ...worktreeRetirementLines(result, columns), ...gatesAwaitLines(result.value.placement));
|
|
410
405
|
return lines.join("\n");
|
|
411
406
|
}
|
|
@@ -41,7 +41,7 @@ function endpointFact(id, observed) {
|
|
|
41
41
|
function renderAkuma(report, context) {
|
|
42
42
|
const section = report.akuma;
|
|
43
43
|
if (section.kind === "absent")
|
|
44
|
-
return ["AKUMA // absent"
|
|
44
|
+
return ["AKUMA // absent"];
|
|
45
45
|
if (section.kind === "failed")
|
|
46
46
|
return ["AKUMA // unavailable", "", tone(`! ${safeText(section.failure.message)}`, "alert", context.color)];
|
|
47
47
|
const rows = section.value.rows;
|