@akagilnc/pi-workflow-roles 0.1.3565 → 0.1.3572
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 +4 -1
- package/README.zh-CN.md +1 -1
- package/dist/acp-host/production-host.js +755 -60
- package/dist/diarist-contracts.js +72 -0
- package/dist/package-contracts/terminating-tools.js +20 -2
- package/dist/packaged-role-registry.js +20 -0
- package/dist/public-cli/main.js +533 -634
- package/dist/public-cli/registry.js +4 -1
- package/extensions/role-runtime.ts +1 -0
- package/package.json +1 -1
- package/resources/diarist-collect.md +6 -10
- package/souls/diarist.md +9 -0
- package/src/acp-host/production-host.ts +1 -0
- package/src/acp-host/role-envelope.ts +2 -1
- package/src/diarist-contracts.ts +88 -0
- package/src/diarist-role.ts +60 -0
- package/src/diarist.ts +253 -179
- package/src/host-contracts.ts +6 -1
- package/src/package-contracts/terminating-tools.ts +22 -2
- package/src/packaged-role-registry.ts +20 -0
- package/src/pi/role-turn-host.ts +8 -0
- package/src/public-cli/cli.ts +29 -0
- package/src/public-cli/countersign-run.ts +9 -129
- package/src/public-cli/diarist-run.ts +312 -0
- package/src/public-cli/invocation.ts +23 -2
- package/src/public-cli/option-definitions.ts +18 -0
- package/src/public-cli/post-admission.ts +2 -2
- package/src/public-cli/registry.ts +3 -0
- package/src/public-cli/run-lifecycle.ts +31 -3
- package/src/public-cli/settlement.ts +50 -2
- package/src/public-cli/terminal.ts +2 -1
- package/src/role-runtime.ts +117 -6
- package/src/ticket-provenance-contracts.ts +1 -0
- package/src/ticket-provenance.ts +0 -23
- package/src/diarist-llm-collector.ts +0 -324
|
@@ -324,8 +324,8 @@ export async function dispatchPostAdmissionTurn<
|
|
|
324
324
|
|
|
325
325
|
await markRunRunning(admitted.runDirectory, env.model, effectiveEngine, env.host);
|
|
326
326
|
await clearTypedProviderHttpObservation(admitted.runDirectory);
|
|
327
|
-
// beforeDispatch (
|
|
328
|
-
//
|
|
327
|
+
// beforeDispatch (seat-owned pre-turn work) runs after running is marked —
|
|
328
|
+
// its failures must settle the run, not leave it permanently running.
|
|
329
329
|
if (adapters.beforeDispatch !== undefined) {
|
|
330
330
|
try {
|
|
331
331
|
await adapters.beforeDispatch(admitted);
|
|
@@ -106,6 +106,9 @@ const STARTUP_CANDIDATES: Record<PublicConfigurableSeat, readonly ModelRef[]> =
|
|
|
106
106
|
{ provider: "openai-codex", model: "gpt-5.6-luna", thinking: "medium" },
|
|
107
107
|
{ provider: "xai", model: "grok-4.5", thinking: "high" },
|
|
108
108
|
],
|
|
109
|
+
// #708 `diarist-seat-default`: owner-set initial value; changed in the seat
|
|
110
|
+
// table like any other seat. No engine axis, package-default host.
|
|
111
|
+
diarist: [{ provider: "xai", model: "grok-4.5", thinking: "medium" }],
|
|
109
112
|
};
|
|
110
113
|
|
|
111
114
|
export function publicStartupCandidates(
|
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
type AdmittedCoderInvocation,
|
|
45
45
|
type AdmittedCountersignInvocation,
|
|
46
46
|
type AdmittedCollectorInvocation,
|
|
47
|
+
type AdmittedDiaristInvocation,
|
|
47
48
|
type AdmittedDoctorInvocation,
|
|
48
49
|
type AdmittedInspectorInvocation,
|
|
49
50
|
type AdmittedNotaryInvocation,
|
|
@@ -95,7 +96,8 @@ export type RoleRunRecord = {
|
|
|
95
96
|
| "gleaner-left"
|
|
96
97
|
| "inspector"
|
|
97
98
|
| "gatekeeper"
|
|
98
|
-
| "navigator"
|
|
99
|
+
| "navigator"
|
|
100
|
+
| "diarist";
|
|
99
101
|
readonly state: RoleRunState;
|
|
100
102
|
readonly bookKey: string;
|
|
101
103
|
readonly projectRoot: string;
|
|
@@ -348,7 +350,8 @@ async function readRoleRunStateDisk(
|
|
|
348
350
|
record.role !== "gleaner-left" &&
|
|
349
351
|
record.role !== "inspector" &&
|
|
350
352
|
record.role !== "gatekeeper" &&
|
|
351
|
-
record.role !== "navigator"
|
|
353
|
+
record.role !== "navigator" &&
|
|
354
|
+
record.role !== "diarist"
|
|
352
355
|
) {
|
|
353
356
|
return undefined;
|
|
354
357
|
}
|
|
@@ -1444,6 +1447,12 @@ export type LoadedResumableGleanerLeftRun = {
|
|
|
1444
1447
|
readonly observation?: TypedHttp429Observation;
|
|
1445
1448
|
};
|
|
1446
1449
|
|
|
1450
|
+
export type LoadedResumableDiaristRun = {
|
|
1451
|
+
readonly admitted: AdmittedDiaristInvocation;
|
|
1452
|
+
readonly run: RoleRunRecord;
|
|
1453
|
+
readonly observation?: TypedHttp429Observation;
|
|
1454
|
+
};
|
|
1455
|
+
|
|
1447
1456
|
export type LoadedResumableInstructionSeatRun = {
|
|
1448
1457
|
readonly admitted: AdmittedGatekeeperInvocation | AdmittedNavigatorInvocation;
|
|
1449
1458
|
readonly run: RoleRunRecord;
|
|
@@ -1637,7 +1646,7 @@ export async function loadResumableReviewerRun(
|
|
|
1637
1646
|
|
|
1638
1647
|
/**
|
|
1639
1648
|
* Load a resumable Countersign run for resume (#599). Ticket binding and
|
|
1640
|
-
* attachments restore from the admitted request
|
|
1649
|
+
* attachments restore from the admitted request.
|
|
1641
1650
|
*/
|
|
1642
1651
|
export async function loadResumableCountersignRun(
|
|
1643
1652
|
home: string,
|
|
@@ -1704,6 +1713,24 @@ export async function loadResumableGleanerLeftRun(
|
|
|
1704
1713
|
return seatLoadedResult(loaded, admitted);
|
|
1705
1714
|
}
|
|
1706
1715
|
|
|
1716
|
+
export async function loadResumableDiaristRun(
|
|
1717
|
+
home: string,
|
|
1718
|
+
runId: string,
|
|
1719
|
+
authority: DurablePrincipalAuthority,
|
|
1720
|
+
): Promise<LoadedResumableDiaristRun> {
|
|
1721
|
+
const loaded = await loadResumableRunRecord(home, runId, authority);
|
|
1722
|
+
if (loaded.run.role !== "diarist") {
|
|
1723
|
+
throw new CliUsageError(
|
|
1724
|
+
`role run ${runId} belongs to ${loaded.run.role}, not diarist`,
|
|
1725
|
+
);
|
|
1726
|
+
}
|
|
1727
|
+
const admitted: AdmittedDiaristInvocation = {
|
|
1728
|
+
role: "diarist",
|
|
1729
|
+
...resumedBaseAdmitted(loaded),
|
|
1730
|
+
};
|
|
1731
|
+
return seatLoadedResult(loaded, admitted);
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1707
1734
|
export type LoadedResumableMergerRun = {
|
|
1708
1735
|
readonly admitted: AdmittedMergerInvocation;
|
|
1709
1736
|
readonly run: RoleRunRecord;
|
|
@@ -1929,6 +1956,7 @@ export async function peekRoleRunRole(
|
|
|
1929
1956
|
| "inspector"
|
|
1930
1957
|
| "gatekeeper"
|
|
1931
1958
|
| "navigator"
|
|
1959
|
+
| "diarist"
|
|
1932
1960
|
| undefined
|
|
1933
1961
|
> {
|
|
1934
1962
|
const runDirectory = await findRunDirectoryById(home, runId);
|
|
@@ -98,6 +98,11 @@ import {
|
|
|
98
98
|
gleanerLeftDecisiveFacts,
|
|
99
99
|
validateRecordedGleanerLeftOutput,
|
|
100
100
|
} from "../gleaner-left-contracts.ts";
|
|
101
|
+
import {
|
|
102
|
+
DIARIST_OUTPUT_TOOL_NAME,
|
|
103
|
+
diaristDecisiveFacts,
|
|
104
|
+
validateRecordedDiaristOutput,
|
|
105
|
+
} from "../diarist-contracts.ts";
|
|
101
106
|
import {
|
|
102
107
|
INSPECTOR_OUTPUT_TOOL_NAME,
|
|
103
108
|
inspectorDecisiveFacts,
|
|
@@ -145,6 +150,7 @@ import {
|
|
|
145
150
|
type AdmittedJudgeInvocation,
|
|
146
151
|
type AdmittedMergerInvocation,
|
|
147
152
|
type AdmittedCountersignInvocation,
|
|
153
|
+
type AdmittedDiaristInvocation,
|
|
148
154
|
type AdmittedGleanerLeftInvocation,
|
|
149
155
|
type AdmittedInspectorInvocation,
|
|
150
156
|
type AdmittedGatekeeperInvocation,
|
|
@@ -3360,7 +3366,8 @@ type SeatAcceptedSettlementSpec = {
|
|
|
3360
3366
|
| "gleaner-left"
|
|
3361
3367
|
| "inspector"
|
|
3362
3368
|
| "gatekeeper"
|
|
3363
|
-
| "navigator"
|
|
3369
|
+
| "navigator"
|
|
3370
|
+
| "diarist";
|
|
3364
3371
|
readonly toolName: string;
|
|
3365
3372
|
readonly nonUsableDiagnostic: string;
|
|
3366
3373
|
readonly projectAccepted: (
|
|
@@ -3387,7 +3394,8 @@ async function settleLawfulSeatAcceptedTerminalResult(
|
|
|
3387
3394
|
| AdmittedGleanerLeftInvocation
|
|
3388
3395
|
| AdmittedInspectorInvocation
|
|
3389
3396
|
| AdmittedGatekeeperInvocation
|
|
3390
|
-
| AdmittedNavigatorInvocation
|
|
3397
|
+
| AdmittedNavigatorInvocation
|
|
3398
|
+
| AdmittedDiaristInvocation,
|
|
3391
3399
|
authority: DurablePrincipalAuthority,
|
|
3392
3400
|
spec: SeatAcceptedSettlementSpec,
|
|
3393
3401
|
scope?: SettlementCourtScope,
|
|
@@ -3651,6 +3659,46 @@ export async function trySettleGleanerLeftTerminalResult(
|
|
|
3651
3659
|
return settleLawfulGleanerLeftTerminalResult(admitted, authority, scope);
|
|
3652
3660
|
}
|
|
3653
3661
|
|
|
3662
|
+
/** Lawful Diarist accepted outcome (completed 入录选择, #708). */
|
|
3663
|
+
export type LawfulDiaristRoleOutcome = {
|
|
3664
|
+
kind: "accepted";
|
|
3665
|
+
role: "diarist";
|
|
3666
|
+
status: string;
|
|
3667
|
+
decisiveFacts: Readonly<Record<string, unknown>>;
|
|
3668
|
+
};
|
|
3669
|
+
|
|
3670
|
+
async function settleLawfulDiaristTerminalResult(
|
|
3671
|
+
admitted: AdmittedDiaristInvocation,
|
|
3672
|
+
authority: DurablePrincipalAuthority,
|
|
3673
|
+
scope?: SettlementCourtScope,
|
|
3674
|
+
): Promise<TerminalResult | undefined> {
|
|
3675
|
+
return settleLawfulSeatAcceptedTerminalResult(admitted, authority, {
|
|
3676
|
+
role: "diarist",
|
|
3677
|
+
toolName: DIARIST_OUTPUT_TOOL_NAME,
|
|
3678
|
+
nonUsableDiagnostic: "起居郎回执无显式 completed",
|
|
3679
|
+
tryAcceptDetails: tryAcceptWithValidator(validateRecordedDiaristOutput),
|
|
3680
|
+
projectAccepted: (sealed) => {
|
|
3681
|
+
const output = validateRecordedDiaristOutput(sealed.decisiveFacts);
|
|
3682
|
+
const accepted: LawfulDiaristRoleOutcome = {
|
|
3683
|
+
kind: "accepted",
|
|
3684
|
+
role: "diarist",
|
|
3685
|
+
status: sealed.status,
|
|
3686
|
+
decisiveFacts: diaristDecisiveFacts(output),
|
|
3687
|
+
};
|
|
3688
|
+
return accepted;
|
|
3689
|
+
},
|
|
3690
|
+
}, scope);
|
|
3691
|
+
}
|
|
3692
|
+
|
|
3693
|
+
/** Try to settle a lawful Diarist Terminal; undefined only for genuine absence. */
|
|
3694
|
+
export async function trySettleDiaristTerminalResult(
|
|
3695
|
+
admitted: AdmittedDiaristInvocation,
|
|
3696
|
+
authority: DurablePrincipalAuthority,
|
|
3697
|
+
scope?: SettlementCourtScope,
|
|
3698
|
+
): Promise<TerminalResult | undefined> {
|
|
3699
|
+
return settleLawfulDiaristTerminalResult(admitted, authority, scope);
|
|
3700
|
+
}
|
|
3701
|
+
|
|
3654
3702
|
/** Lawful Inspector accepted outcome (pass/bounce/escalate). */
|
|
3655
3703
|
export type LawfulInspectorRoleOutcome = {
|
|
3656
3704
|
kind: "accepted";
|
|
@@ -40,7 +40,8 @@ export type TerminalRoleName =
|
|
|
40
40
|
| "gleaner-left"
|
|
41
41
|
| "inspector"
|
|
42
42
|
| "gatekeeper"
|
|
43
|
-
| "navigator"
|
|
43
|
+
| "navigator"
|
|
44
|
+
| "diarist";
|
|
44
45
|
|
|
45
46
|
/** Merger/Collector residual only — Notary/audit residual abolished (#475). */
|
|
46
47
|
export type ResidualIncompleteTerminalOutcome = {
|
package/src/role-runtime.ts
CHANGED
|
@@ -70,6 +70,20 @@ import {
|
|
|
70
70
|
type InspectorRuntimeDependencies,
|
|
71
71
|
} from "./inspector-role.ts";
|
|
72
72
|
import { INSPECTOR_ACCEPTED_TEXT } from "./inspector-contracts.ts";
|
|
73
|
+
import {
|
|
74
|
+
DIARIST_TOOL_SPEC,
|
|
75
|
+
type DiaristRuntimeDependencies,
|
|
76
|
+
} from "./diarist-role.ts";
|
|
77
|
+
import {
|
|
78
|
+
DIARIST_ACCEPTED_TEXT,
|
|
79
|
+
DIARIST_SOURCES_FLAG,
|
|
80
|
+
projectDiaristSelections,
|
|
81
|
+
} from "./diarist-contracts.ts";
|
|
82
|
+
import {
|
|
83
|
+
commitDiaristSelections,
|
|
84
|
+
loadDiaristSourceCatalog,
|
|
85
|
+
type DiaristSourceCatalog,
|
|
86
|
+
} from "./diarist.ts";
|
|
73
87
|
import {
|
|
74
88
|
GATEKEEPER_TOOL_SPEC,
|
|
75
89
|
type GatekeeperRuntimeDependencies,
|
|
@@ -159,6 +173,14 @@ const GLEANER_LEFT_TRANSPORT_FLAGS = Object.freeze([
|
|
|
159
173
|
}),
|
|
160
174
|
] as const);
|
|
161
175
|
|
|
176
|
+
/** Diarist private transport: frozen source catalog path (ADR 0018 / #708). */
|
|
177
|
+
const DIARIST_TRANSPORT_FLAGS = Object.freeze([
|
|
178
|
+
Object.freeze({
|
|
179
|
+
name: DIARIST_SOURCES_FLAG.name,
|
|
180
|
+
definition: DIARIST_SOURCES_FLAG.definition,
|
|
181
|
+
}),
|
|
182
|
+
] as const);
|
|
183
|
+
|
|
162
184
|
/**
|
|
163
185
|
* Decode private transport flags into frozen admitted inputs.
|
|
164
186
|
* Envelope-owned; necessary JSON decode only (public --authority-ref owns grammar).
|
|
@@ -439,6 +461,7 @@ type ActivationRuntime = {
|
|
|
439
461
|
inspector: { activate(): Promise<void> };
|
|
440
462
|
gatekeeper: { activate(): Promise<void> };
|
|
441
463
|
navigator: { activate(): Promise<void> };
|
|
464
|
+
diarist: { activate(): Promise<void> };
|
|
442
465
|
merger(): Promise<void>;
|
|
443
466
|
};
|
|
444
467
|
|
|
@@ -487,6 +510,7 @@ function activationStage(role: PackagedRole, runtime: ActivationRuntime): { id:
|
|
|
487
510
|
case "inspector": return { id: "load-and-install", run: async () => runtime.inspector.activate() };
|
|
488
511
|
case "gatekeeper": return { id: "load-and-install", run: async () => runtime.gatekeeper.activate() };
|
|
489
512
|
case "navigator": return { id: "load-and-install", run: async () => runtime.navigator.activate() };
|
|
513
|
+
case "diarist": return { id: "load-and-install", run: async () => runtime.diarist.activate() };
|
|
490
514
|
case "merger": return { id: "prepare-git-and-install", run: async () => runtime.merger() };
|
|
491
515
|
}
|
|
492
516
|
}
|
|
@@ -594,6 +618,7 @@ export type RoleRuntimeDependencies = {
|
|
|
594
618
|
loadInspectorSoul?(): Promise<string>;
|
|
595
619
|
loadGatekeeperSoul?(): Promise<string>;
|
|
596
620
|
loadNavigatorSoul?(): Promise<string>;
|
|
621
|
+
loadDiaristSoul?(): Promise<string>;
|
|
597
622
|
loadDoctorCase?(path: string): Promise<import("./doctor-contracts.ts").DoctorCase>;
|
|
598
623
|
loadMergerSoul?(): Promise<string>;
|
|
599
624
|
loadMergerInput?(path: string): Promise<unknown>;
|
|
@@ -707,13 +732,17 @@ export async function projectClosedSubmissionLifecycle(
|
|
|
707
732
|
await settle(publicNavigatorSettlement(projection.role, phase, closure));
|
|
708
733
|
}
|
|
709
734
|
|
|
710
|
-
/**
|
|
735
|
+
/**
|
|
736
|
+
* Optional pre-accept hook on the shared filed-officer envelope (ADR 0075).
|
|
737
|
+
* May return a details projection (envelope-owned machine facts recorded next to
|
|
738
|
+
* the submitted parameters); undefined keeps the parameters as submitted.
|
|
739
|
+
*/
|
|
711
740
|
type FiledOfficerBeforeAccept = (input: {
|
|
712
741
|
readonly toolCallId: string;
|
|
713
742
|
readonly parameters: unknown;
|
|
714
743
|
readonly signal: AbortSignal | undefined;
|
|
715
744
|
readonly ctx: HostContext;
|
|
716
|
-
}) => Promise<
|
|
745
|
+
}) => Promise<unknown>;
|
|
717
746
|
|
|
718
747
|
/**
|
|
719
748
|
* Shared registration envelope for filed officers (ADR 0018 / #572):
|
|
@@ -749,14 +778,15 @@ function createFiledOfficerRuntime(
|
|
|
749
778
|
parameters: spec.tool.parameters as never,
|
|
750
779
|
async execute(toolCallId, parameters, signal, _onUpdate, ctx): Promise<HostToolResult<unknown>> {
|
|
751
780
|
if (soul === undefined) throw new Error(`${spec.role} 职分未装载`);
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
781
|
+
const projected =
|
|
782
|
+
spec.beforeAccept === undefined
|
|
783
|
+
? undefined
|
|
784
|
+
: await spec.beforeAccept({ toolCallId, parameters, signal, ctx });
|
|
755
785
|
// Accept-as-is + terminate only. Shape is not an admission gate
|
|
756
786
|
// (第 0 条 / ADR 0055); sole-final barrier is ledger-owned (#575).
|
|
757
787
|
return {
|
|
758
788
|
content: [{ type: "text" as const, text: spec.acceptedText }],
|
|
759
|
-
details: parameters,
|
|
789
|
+
details: projected === undefined ? parameters : projected,
|
|
760
790
|
terminate: true as const,
|
|
761
791
|
};
|
|
762
792
|
},
|
|
@@ -849,6 +879,73 @@ export function createNavigatorRoleRuntime(
|
|
|
849
879
|
);
|
|
850
880
|
}
|
|
851
881
|
|
|
882
|
+
/**
|
|
883
|
+
* #708: 起居郎 public seat on the shared filed-officer envelope.
|
|
884
|
+
* Semantic collection happened in this role's own turn; the accept hook runs the
|
|
885
|
+
* mechanical band (verbatim reverse-verify → idempotent sitian append →
|
|
886
|
+
* watermark) and records the resulting sitian facts next to the receipt.
|
|
887
|
+
* Machine facts never come from model self-report (锚定宪法).
|
|
888
|
+
*/
|
|
889
|
+
export function createDiaristRoleRuntime(
|
|
890
|
+
roleHost: RoleHost,
|
|
891
|
+
dependencies: DiaristRuntimeDependencies,
|
|
892
|
+
getSourcesFlag: () => unknown,
|
|
893
|
+
) {
|
|
894
|
+
// This turn's catalog, snapshotted at activate: the candidateIndexes the role
|
|
895
|
+
// saw and the rows accept commits are the same bytes. Accept never re-reads
|
|
896
|
+
// the file, so anything written to it mid-turn cannot become a diary entry.
|
|
897
|
+
let catalog: DiaristSourceCatalog | undefined;
|
|
898
|
+
const runtime = createFiledOfficerRuntime(
|
|
899
|
+
roleHost,
|
|
900
|
+
{
|
|
901
|
+
role: "diarist",
|
|
902
|
+
tool: DIARIST_TOOL_SPEC,
|
|
903
|
+
acceptedText: DIARIST_ACCEPTED_TEXT,
|
|
904
|
+
soulTag: "diarist",
|
|
905
|
+
beforeAccept: async ({ parameters }) => {
|
|
906
|
+
const submitted =
|
|
907
|
+
parameters !== null && typeof parameters === "object" && !Array.isArray(parameters)
|
|
908
|
+
? (parameters as Record<string, unknown>)
|
|
909
|
+
: undefined;
|
|
910
|
+
// True-unbound summons: no ticket, no catalog, no diary committed — so
|
|
911
|
+
// this turn produced no sitian facts. A self-reported `sitian` is not
|
|
912
|
+
// one (锚定宪法); drop it rather than let it ride into decisiveFacts.
|
|
913
|
+
// Carrying the field is not a reason to bounce the receipt (第 0 条).
|
|
914
|
+
if (catalog === undefined) {
|
|
915
|
+
if (submitted === undefined || !("sitian" in submitted)) return undefined;
|
|
916
|
+
const stripped = { ...submitted };
|
|
917
|
+
delete stripped.sitian;
|
|
918
|
+
return stripped;
|
|
919
|
+
}
|
|
920
|
+
const facts = await commitDiaristSelections({
|
|
921
|
+
catalog,
|
|
922
|
+
selections: projectDiaristSelections(parameters),
|
|
923
|
+
});
|
|
924
|
+
return { ...(submitted ?? { receipt: parameters }), sitian: facts };
|
|
925
|
+
},
|
|
926
|
+
},
|
|
927
|
+
dependencies,
|
|
928
|
+
);
|
|
929
|
+
return {
|
|
930
|
+
async activate() {
|
|
931
|
+
catalog = loadFrozenDiaristCatalog(getSourcesFlag);
|
|
932
|
+
return runtime.activate();
|
|
933
|
+
},
|
|
934
|
+
};
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
/** Envelope-owned decode + one-shot load of the frozen catalog (ADR 0018). */
|
|
938
|
+
function loadFrozenDiaristCatalog(
|
|
939
|
+
getFlag: () => unknown,
|
|
940
|
+
): DiaristSourceCatalog | undefined {
|
|
941
|
+
const raw = getFlag();
|
|
942
|
+
if (raw === undefined) return undefined;
|
|
943
|
+
if (typeof raw !== "string" || raw.trim() === "") {
|
|
944
|
+
throw new Error("Diarist source catalog flag must be a nonempty path");
|
|
945
|
+
}
|
|
946
|
+
return loadDiaristSourceCatalog(raw);
|
|
947
|
+
}
|
|
948
|
+
|
|
852
949
|
export function createCountersignRoleRuntime(
|
|
853
950
|
roleHost: RoleHost,
|
|
854
951
|
dependencies: CountersignRuntimeDependencies,
|
|
@@ -905,6 +1002,9 @@ export function createRoleRuntimeExtension(
|
|
|
905
1002
|
for (const flag of GLEANER_LEFT_TRANSPORT_FLAGS) {
|
|
906
1003
|
roleHost.registerFlag(flag.name, flag.definition);
|
|
907
1004
|
}
|
|
1005
|
+
for (const flag of DIARIST_TRANSPORT_FLAGS) {
|
|
1006
|
+
roleHost.registerFlag(flag.name, flag.definition);
|
|
1007
|
+
}
|
|
908
1008
|
|
|
909
1009
|
let admitted = false;
|
|
910
1010
|
let selectedRole: string | undefined;
|
|
@@ -1358,6 +1458,16 @@ export function createRoleRuntimeExtension(
|
|
|
1358
1458
|
return dependencies.loadNavigatorSoul();
|
|
1359
1459
|
},
|
|
1360
1460
|
});
|
|
1461
|
+
const diarist = createDiaristRoleRuntime(
|
|
1462
|
+
roleHost,
|
|
1463
|
+
{
|
|
1464
|
+
async loadSoul() {
|
|
1465
|
+
if (!dependencies.loadDiaristSoul) throw new Error("Diarist runtime dependencies are not configured");
|
|
1466
|
+
return dependencies.loadDiaristSoul();
|
|
1467
|
+
},
|
|
1468
|
+
},
|
|
1469
|
+
() => envelopeHost.host.getFlag(DIARIST_SOURCES_FLAG.name),
|
|
1470
|
+
);
|
|
1361
1471
|
let sessionMergerGitState = dependencies.mergerGitState;
|
|
1362
1472
|
const merger = createMergerRoleRuntime(roleHost, {
|
|
1363
1473
|
async loadSoul() { if (!dependencies.loadMergerSoul) throw new Error("Merger runtime dependencies are not configured"); return dependencies.loadMergerSoul(); },
|
|
@@ -1524,6 +1634,7 @@ export function createRoleRuntimeExtension(
|
|
|
1524
1634
|
inspector,
|
|
1525
1635
|
gatekeeper,
|
|
1526
1636
|
navigator,
|
|
1637
|
+
diarist,
|
|
1527
1638
|
merger: async () => {
|
|
1528
1639
|
if (dependencies.mergerGitState === undefined) {
|
|
1529
1640
|
sessionMergerGitState = dependencies.createMergerGitState?.(ctx.cwd);
|
|
@@ -66,6 +66,7 @@ export type TicketProvenanceEntry = {
|
|
|
66
66
|
* Separated by recordClass discriminator — never disguised as a source entry.
|
|
67
67
|
*/
|
|
68
68
|
export type TicketProvenanceDiagnosticKind =
|
|
69
|
+
/** Historical rows only — the diarist turn's own failure settles the run (#708). */
|
|
69
70
|
| "collector-failed"
|
|
70
71
|
| "issue-source-failed"
|
|
71
72
|
| "quote-verify-failed";
|
package/src/ticket-provenance.ts
CHANGED
|
@@ -408,29 +408,6 @@ export function appendTicketProvenanceDiagnostic(input: {
|
|
|
408
408
|
});
|
|
409
409
|
}
|
|
410
410
|
|
|
411
|
-
/** Collector/engine failure true cause — typed diagnostic, not a diary entry. */
|
|
412
|
-
export function appendCollectorFailureDiagnostic(input: {
|
|
413
|
-
readonly ticketNumber: number;
|
|
414
|
-
readonly cwd: string;
|
|
415
|
-
readonly home?: string;
|
|
416
|
-
readonly collectorError: string;
|
|
417
|
-
readonly recordedAt?: string;
|
|
418
|
-
}): RecordPointer {
|
|
419
|
-
const recordedAt = input.recordedAt ?? new Date().toISOString();
|
|
420
|
-
return appendTicketProvenanceDiagnostic({
|
|
421
|
-
ticketNumber: input.ticketNumber,
|
|
422
|
-
cwd: input.cwd,
|
|
423
|
-
...(input.home === undefined ? {} : { home: input.home }),
|
|
424
|
-
source: "diarist-collector-fail",
|
|
425
|
-
diagnostic: {
|
|
426
|
-
recordClass: TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC,
|
|
427
|
-
diagnosticKind: "collector-failed",
|
|
428
|
-
cause: input.collectorError,
|
|
429
|
-
recordedAt,
|
|
430
|
-
},
|
|
431
|
-
});
|
|
432
|
-
}
|
|
433
|
-
|
|
434
411
|
/** Issue-face source acquisition failure — typed diagnostic on the ticket volume. */
|
|
435
412
|
export function appendIssueSourceFailureDiagnostic(input: {
|
|
436
413
|
readonly ticketNumber: number;
|