@akagilnc/pi-workflow-roles 0.1.5483 → 0.1.5571
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 +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/acp-host/production-host.js +6312 -6376
- package/dist/analyst-gate-cycles-read.js +28 -78
- package/dist/analyst-ledger.js +26 -42
- package/dist/analyst-metric-families/acceptance-success-rework.js +25 -1
- package/dist/analyst-metric-families/round-timeline.js +2 -5
- package/dist/archivist-record-entry.js +4 -3
- package/dist/archivist-record-pointer.js +71 -36
- package/dist/atomic-write.js +2 -2
- package/dist/auditor-dossier-tool.js +11 -6
- package/dist/auditor-soul.js +5 -12
- package/dist/collector-config.js +6 -5
- package/dist/doctor-evidence.js +8 -4
- package/dist/engine-detour-usage.js +8 -22
- package/dist/headless-host/production-host.js +5969 -6011
- package/dist/host-descriptions.js +0 -4
- package/dist/host-session-record.js +266 -267
- package/dist/ledger-session-read.js +5 -0
- package/dist/migrate-book-topology.js +1369 -722
- package/dist/navigator-public-session.js +13 -17
- package/dist/notary-source-run.js +8 -16
- package/dist/packaged-role-registry.js +5 -56
- package/dist/pi/durable-principal.js +2 -3
- package/dist/pi/role-turn-host.js +79 -15
- package/dist/public-cli/auto-resume.js +8 -47
- package/dist/public-cli/instruction-seat-run.js +9 -7
- package/dist/public-cli/invocation.js +67 -100
- package/dist/public-cli/main.js +2689 -2532
- package/dist/public-cli/post-admission.js +96 -55
- package/dist/public-cli/run-lifecycle.js +44 -100
- package/dist/public-cli/settlement.js +184 -429
- package/dist/public-cli/terminal.js +0 -12
- package/dist/role-run-placement.js +53 -16
- package/dist/role-run-relocation.js +111 -52
- package/dist/run-dossier-files.js +30 -0
- package/dist/run-dossier.js +322 -0
- package/dist/run-terminal-artifacts.js +69 -202
- package/dist/run-ticket-number.js +49 -7
- package/dist/session-assistant-usage.js +9 -18
- package/dist/session-identity.js +49 -19
- package/dist/sitian-appender.js +29 -18
- package/dist/sitian-facade.js +11 -0
- package/dist/sitian-reader.js +44 -29
- package/dist/submission-gate.js +1 -1
- package/dist/submission-ledger.js +4 -4
- package/dist/ticket-provenance-contracts.js +2 -8
- package/dist/ticket-provenance.js +25 -9
- package/package.json +1 -1
- package/scripts/build-package.mjs +2 -0
- package/src/acp-host/production-host.ts +1 -1
- package/src/acp-host/role-turn-host.ts +11 -4
- package/src/analyst-gate-cycles-read.ts +31 -88
- package/src/analyst-ledger.ts +36 -51
- package/src/analyst-metric-families/acceptance-success-rework.ts +24 -1
- package/src/analyst-metric-families/gate-cycles.ts +1 -1
- package/src/analyst-metric-families/round-timeline.ts +2 -5
- package/src/analyst-page.ts +3 -3
- package/src/archivist-record-entry.ts +6 -5
- package/src/archivist-record-pointer.ts +92 -42
- package/src/atomic-write.ts +3 -1
- package/src/auditor-dossier-tool.ts +14 -8
- package/src/auditor-soul.ts +5 -10
- package/src/book-topology-migration-placement.ts +16 -3
- package/src/book-topology-record-class-migrators.ts +4 -2
- package/src/book-topology-runs-migrator.ts +6 -3
- package/src/collector-config.ts +5 -3
- package/src/doctor-contracts.ts +1 -1
- package/src/doctor-evidence.ts +7 -3
- package/src/engine-detour-tool.ts +1 -1
- package/src/engine-detour-usage.ts +12 -25
- package/src/external-host-turn-loop.ts +25 -0
- package/src/factory-board.ts +16 -81
- package/src/headless-host/production-host.ts +1 -4
- package/src/headless-host/role-turn-host.ts +56 -21
- package/src/host-descriptions.ts +0 -6
- package/src/host-session-record.ts +224 -140
- package/src/ledger-session-read.ts +6 -0
- package/src/navigator-public-session.ts +13 -18
- package/src/navigator-work-context.ts +3 -1
- package/src/notary-role.ts +2 -1
- package/src/notary-source-run.ts +8 -18
- package/src/packaged-role-registry.ts +1 -65
- package/src/pi/adapter.ts +50 -7
- package/src/pi/durable-principal.ts +2 -4
- package/src/pi/role-turn-host.ts +85 -14
- package/src/public-cli/auto-resume.ts +7 -43
- package/src/public-cli/instruction-seat-run.ts +13 -6
- package/src/public-cli/invocation.ts +90 -144
- package/src/public-cli/post-admission.ts +111 -72
- package/src/public-cli/run-lifecycle.ts +47 -115
- package/src/public-cli/settlement.ts +221 -589
- package/src/public-cli/terminal.ts +1 -61
- package/src/role-envelope.ts +4 -2
- package/src/role-run-placement.ts +65 -17
- package/src/role-run-relocation.ts +110 -70
- package/src/role-runtime.ts +46 -69
- package/src/run-dossier-files.ts +33 -0
- package/src/run-dossier.ts +357 -0
- package/src/run-terminal-artifacts.ts +84 -240
- package/src/run-ticket-number.ts +82 -14
- package/src/session-assistant-usage.ts +8 -20
- package/src/session-identity.ts +52 -21
- package/src/sitian-appender.ts +33 -26
- package/src/sitian-facade.ts +22 -0
- package/src/sitian-reader.ts +62 -32
- package/src/submission-gate.ts +1 -1
- package/src/submission-ledger.ts +4 -4
- package/src/ticket-provenance-contracts.ts +3 -6
- package/src/ticket-provenance.ts +23 -11
- package/src/ticket-snapshot.ts +3 -2
- package/src/ticket-trajectory.ts +95 -109
|
@@ -85,18 +85,6 @@ export function formatTerminalResult(result) {
|
|
|
85
85
|
for (const artifact of result.artifacts) {
|
|
86
86
|
lines.push(`artifact\t${artifact.kind}\t${encodeTerminalField(artifact.path)}`);
|
|
87
87
|
}
|
|
88
|
-
// Gate region is unfrozen presentation of typed facts (ADR 0052) — machines
|
|
89
|
-
// read result.gate, never these row labels.
|
|
90
|
-
if (result.gate !== undefined) {
|
|
91
|
-
lines.push(`gate\t${encodeTerminalField(result.gate.actualSeats.join(","))}\t${result.gate.rounds.length}`);
|
|
92
|
-
for (const round of result.gate.rounds) {
|
|
93
|
-
const reason = round.dispatch.kind === "historical_dispatch"
|
|
94
|
-
&& round.dispatch.reason !== undefined
|
|
95
|
-
? encodeTerminalField(round.dispatch.reason)
|
|
96
|
-
: "";
|
|
97
|
-
lines.push(`gate-round\t${round.roundIndex}\t${round.dispatch.kind}\t${round.dispatch.officer}\t${reason}\t${round.officer.seat}\t${encodeTerminalField(round.officer.status)}\t${encodeTerminalField(JSON.stringify(round.officer.findings))}`);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
88
|
if (result.reviewerChildOutcomes !== undefined) {
|
|
101
89
|
for (const axis of ["completeness", "correctness"]) {
|
|
102
90
|
const child = result.reviewerChildOutcomes[axis];
|
|
@@ -1,11 +1,35 @@
|
|
|
1
1
|
import { readdir } from "node:fs/promises";
|
|
2
|
-
import { join } from "node:path";
|
|
2
|
+
import { basename, dirname, join } from "node:path";
|
|
3
3
|
import {
|
|
4
4
|
activationBookDirectory,
|
|
5
5
|
ensureRealDirectoryTree
|
|
6
6
|
} from "./activation-ledger-topology.js";
|
|
7
7
|
import { requireSafePositiveTicketNumber } from "./run-ticket-number.js";
|
|
8
8
|
import { isEnoent } from "./unknown-value.js";
|
|
9
|
+
function formatRunLeaf(runId, role) {
|
|
10
|
+
return `${runId}@${role}`;
|
|
11
|
+
}
|
|
12
|
+
function parseRunLeaf(name) {
|
|
13
|
+
const at = name.lastIndexOf("@");
|
|
14
|
+
if (at <= 0 || at === name.length - 1) return void 0;
|
|
15
|
+
return { runId: name.slice(0, at), role: name.slice(at + 1) };
|
|
16
|
+
}
|
|
17
|
+
function sessionDirectoryOf(runDirectory) {
|
|
18
|
+
return join(runDirectory, "session");
|
|
19
|
+
}
|
|
20
|
+
const ROLE_RUN_SESSION_FILENAME = "session.jsonl";
|
|
21
|
+
function sessionFileIn(sessionDirectory) {
|
|
22
|
+
return join(sessionDirectory, ROLE_RUN_SESSION_FILENAME);
|
|
23
|
+
}
|
|
24
|
+
function sessionFileOf(runDirectory) {
|
|
25
|
+
return sessionFileIn(sessionDirectoryOf(runDirectory));
|
|
26
|
+
}
|
|
27
|
+
function runDirectoryOfSessionFile(sessionFile) {
|
|
28
|
+
return dirname(dirname(sessionFile));
|
|
29
|
+
}
|
|
30
|
+
function runDirectoryFromSessionDirectory(sessionDirectory) {
|
|
31
|
+
return dirname(sessionDirectory);
|
|
32
|
+
}
|
|
9
33
|
async function listBookRunDirectories(bookDir) {
|
|
10
34
|
const out = [];
|
|
11
35
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -39,6 +63,20 @@ async function listBookRunDirectories(bookDir) {
|
|
|
39
63
|
}
|
|
40
64
|
return out.sort();
|
|
41
65
|
}
|
|
66
|
+
async function findRoleRunDirectory(bookDirectories, runId, onlyRole) {
|
|
67
|
+
const matches = [];
|
|
68
|
+
for (const bookDirectory of bookDirectories) {
|
|
69
|
+
for (const runDirectory of await listBookRunDirectories(bookDirectory)) {
|
|
70
|
+
const parsed = parseRunLeaf(basename(runDirectory));
|
|
71
|
+
if (parsed === void 0 || parsed.runId !== runId) continue;
|
|
72
|
+
if (onlyRole !== void 0 && parsed.role !== onlyRole) continue;
|
|
73
|
+
matches.push(runDirectory);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (matches.length === 0) return void 0;
|
|
77
|
+
if (matches.length === 1) return matches[0];
|
|
78
|
+
throw new Error(`ambiguous role run id ${runId}: ${matches.join(", ")}`);
|
|
79
|
+
}
|
|
42
80
|
function roleRunPlacement(ledgerHome, input) {
|
|
43
81
|
const subjectDirectory = "ticketNumber" in input.subject ? String(requireSafePositiveTicketNumber(
|
|
44
82
|
input.subject.ticketNumber,
|
|
@@ -48,20 +86,16 @@ function roleRunPlacement(ledgerHome, input) {
|
|
|
48
86
|
activationBookDirectory(ledgerHome, input.bookKey),
|
|
49
87
|
subjectDirectory,
|
|
50
88
|
"runs",
|
|
51
|
-
|
|
89
|
+
formatRunLeaf(input.runId, input.role)
|
|
52
90
|
);
|
|
53
|
-
const sessionDirectory =
|
|
91
|
+
const sessionDirectory = sessionDirectoryOf(runDirectory);
|
|
54
92
|
return {
|
|
55
93
|
runDirectory,
|
|
56
94
|
sessionDirectory,
|
|
57
|
-
sessionFile:
|
|
58
|
-
artifactsDirectory: roleRunArtifactsDirectory(runDirectory),
|
|
95
|
+
sessionFile: sessionFileIn(sessionDirectory),
|
|
59
96
|
attachmentsDirectory: join(runDirectory, "attachments")
|
|
60
97
|
};
|
|
61
98
|
}
|
|
62
|
-
function roleRunArtifactsDirectory(runDirectory) {
|
|
63
|
-
return join(runDirectory, "artifacts");
|
|
64
|
-
}
|
|
65
99
|
function isUnboundRunDirectory(runDirectory) {
|
|
66
100
|
return runDirectory.replaceAll("\\", "/").includes("/unbound/runs/");
|
|
67
101
|
}
|
|
@@ -69,18 +103,21 @@ function ensureRoleRunDirectory(ledgerHome, directory) {
|
|
|
69
103
|
return ensureRealDirectoryTree(ledgerHome, directory);
|
|
70
104
|
}
|
|
71
105
|
function ensureRoleRunPlacement(ledgerHome, placement) {
|
|
72
|
-
|
|
73
|
-
placement.sessionDirectory,
|
|
74
|
-
placement.attachmentsDirectory
|
|
75
|
-
]) {
|
|
76
|
-
ensureRoleRunDirectory(ledgerHome, directory);
|
|
77
|
-
}
|
|
106
|
+
ensureRoleRunDirectory(ledgerHome, placement.sessionDirectory);
|
|
78
107
|
}
|
|
79
108
|
export {
|
|
109
|
+
ROLE_RUN_SESSION_FILENAME,
|
|
80
110
|
ensureRoleRunDirectory,
|
|
81
111
|
ensureRoleRunPlacement,
|
|
112
|
+
findRoleRunDirectory,
|
|
113
|
+
formatRunLeaf,
|
|
82
114
|
isUnboundRunDirectory,
|
|
83
115
|
listBookRunDirectories,
|
|
84
|
-
|
|
85
|
-
roleRunPlacement
|
|
116
|
+
parseRunLeaf,
|
|
117
|
+
roleRunPlacement,
|
|
118
|
+
runDirectoryFromSessionDirectory,
|
|
119
|
+
runDirectoryOfSessionFile,
|
|
120
|
+
sessionDirectoryOf,
|
|
121
|
+
sessionFileIn,
|
|
122
|
+
sessionFileOf
|
|
86
123
|
};
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Single authority for rewriting durable run pages after a run directory moves.
|
|
3
|
-
* Live
|
|
3
|
+
* Live callers project typed fields; only historical migrators walk durable pages.
|
|
4
4
|
*
|
|
5
5
|
* Scope is typed machine-consumed path fields only — never free text, never
|
|
6
6
|
* frozen attachment/artifact bytes. Nested walk is confined to package-owned
|
|
7
7
|
* `session/` seams.
|
|
8
8
|
*/
|
|
9
|
-
import { existsSync } from "node:fs";
|
|
10
9
|
import { readdir, readFile, writeFile } from "node:fs/promises";
|
|
11
|
-
import { join, sep } from "node:path";
|
|
10
|
+
import { dirname, join, sep } from "node:path";
|
|
11
|
+
import { activationBookDirectory, physicalPathIdentity } from "./activation-ledger-topology.js";
|
|
12
|
+
import { readRoleRunIdentity } from "./public-cli/run-lifecycle.js";
|
|
13
|
+
import { findRoleRunDirectory, roleRunPlacement } from "./role-run-placement.js";
|
|
12
14
|
import { AUDITOR_PARENT_ATTEMPT_BINDING_ENTRY_TYPE } from "./compliance-transport.js";
|
|
15
|
+
import { readPageSync, updateSectionSync } from "./run-dossier.js";
|
|
13
16
|
import { isRecord, isEnoent } from "./unknown-value.js";
|
|
14
17
|
const ADMITTED_PAGE_FIELDS = [
|
|
15
18
|
"runDirectory",
|
|
16
|
-
"admittedRequestPath",
|
|
19
|
+
"admittedRequestPath", // pre-#1161 pages only
|
|
17
20
|
"sessionDirectory",
|
|
18
21
|
"sessionFile",
|
|
19
22
|
"taskPath",
|
|
@@ -30,7 +33,7 @@ const INVOCATION_PAGE_FIELDS = [
|
|
|
30
33
|
];
|
|
31
34
|
const RUN_STATE_PAGE_FIELDS = [
|
|
32
35
|
"runDirectory",
|
|
33
|
-
"admittedRequestPath",
|
|
36
|
+
"admittedRequestPath", // pre-#1161 pages only
|
|
34
37
|
"sessionDirectory",
|
|
35
38
|
"sessionFile",
|
|
36
39
|
];
|
|
@@ -52,6 +55,40 @@ export function rewriteRunDirectoryPathValue(value, oldRunDirectory, newRunDirec
|
|
|
52
55
|
}
|
|
53
56
|
return value;
|
|
54
57
|
}
|
|
58
|
+
/** Match physical aliases or a normal unbound→ticket bind, never historical migration layouts. */
|
|
59
|
+
export async function retainedRunPathsMatch(recordedPath, currentPath, currentRunDirectory) {
|
|
60
|
+
if (recordedPath === currentPath)
|
|
61
|
+
return true;
|
|
62
|
+
if (typeof recordedPath !== "string")
|
|
63
|
+
return false;
|
|
64
|
+
const recordedPathIdentity = physicalPathIdentity(recordedPath);
|
|
65
|
+
const currentPathIdentity = physicalPathIdentity(currentPath);
|
|
66
|
+
if (recordedPathIdentity === currentPathIdentity)
|
|
67
|
+
return true;
|
|
68
|
+
if (currentRunDirectory === undefined)
|
|
69
|
+
return false;
|
|
70
|
+
const runDirectory = physicalPathIdentity(currentRunDirectory);
|
|
71
|
+
const identity = await readRoleRunIdentity(runDirectory);
|
|
72
|
+
if (identity === undefined)
|
|
73
|
+
return false;
|
|
74
|
+
for (let directory = runDirectory; dirname(directory) !== directory; directory = dirname(directory)) {
|
|
75
|
+
const ledgerHome = dirname(dirname(directory));
|
|
76
|
+
if (directory !== activationBookDirectory(ledgerHome, identity.bookKey))
|
|
77
|
+
continue;
|
|
78
|
+
const unbound = roleRunPlacement(ledgerHome, {
|
|
79
|
+
bookKey: identity.bookKey,
|
|
80
|
+
subject: { unbound: true },
|
|
81
|
+
runId: identity.runId,
|
|
82
|
+
role: identity.role,
|
|
83
|
+
});
|
|
84
|
+
if (rewriteRunDirectoryPathValue(recordedPathIdentity, unbound.runDirectory, runDirectory) !== currentPathIdentity) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
const placed = await findRoleRunDirectory([directory], identity.runId, identity.role);
|
|
88
|
+
return placed !== undefined && physicalPathIdentity(placed) === runDirectory;
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
55
92
|
/**
|
|
56
93
|
* Apply the longest matching oldRunDirectory rewrite. Longer keys win so a
|
|
57
94
|
* nested run path is not partially claimed by a shorter sibling prefix.
|
|
@@ -139,25 +176,26 @@ export function rewriteAdmittedRoleRunPage(page, rewrites) {
|
|
|
139
176
|
rewriteRunDirectoryPathFieldsAgainstRewrites(page.principal, ["sessionDirectory", "sessionFile"], rewrites);
|
|
140
177
|
}
|
|
141
178
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
return;
|
|
179
|
+
/** Pre-#1161 `session/auditor-roles/<officer>.pointer.json` (migrator input only). */
|
|
180
|
+
async function rewriteLegacyOfficerPointerFile(path, rewrites) {
|
|
145
181
|
const page = JSON.parse(await readFile(path, "utf8"));
|
|
146
|
-
if (!isRecord(page))
|
|
147
|
-
return;
|
|
148
|
-
// Only the typed direct-officer pointer shape — never arbitrary .pointer.json.
|
|
149
|
-
if (page.kind !== "direct-officer-run-pointer")
|
|
182
|
+
if (!isRecord(page) || page.kind !== "direct-officer-run-pointer")
|
|
150
183
|
return;
|
|
151
184
|
const before = JSON.stringify(page);
|
|
152
185
|
rewriteRunDirectoryPathFieldsAgainstRewrites(page, OFFICER_POINTER_FIELDS, rewrites);
|
|
153
|
-
if (JSON.stringify(page) !== before)
|
|
186
|
+
if (JSON.stringify(page) !== before)
|
|
154
187
|
await writeFile(path, `${JSON.stringify(page)}\n`, "utf8");
|
|
155
|
-
}
|
|
156
188
|
}
|
|
157
189
|
async function rewriteSitianRecordsJsonl(path, rewrites) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
190
|
+
let raw;
|
|
191
|
+
try {
|
|
192
|
+
raw = await readFile(path, "utf8");
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
if (isEnoent(error))
|
|
196
|
+
return;
|
|
197
|
+
throw error;
|
|
198
|
+
}
|
|
161
199
|
if (raw.length === 0)
|
|
162
200
|
return;
|
|
163
201
|
const endsWithNewline = raw.endsWith("\n");
|
|
@@ -207,9 +245,15 @@ async function rewriteSitianRecordsJsonl(path, rewrites) {
|
|
|
207
245
|
* ak_auditor_parent_attempt_binding data.parent.sessionFile. Never message text.
|
|
208
246
|
*/
|
|
209
247
|
async function rewriteSessionTranscriptBindings(path, rewrites) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
248
|
+
let raw;
|
|
249
|
+
try {
|
|
250
|
+
raw = await readFile(path, "utf8");
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
if (isEnoent(error))
|
|
254
|
+
return;
|
|
255
|
+
throw error;
|
|
256
|
+
}
|
|
213
257
|
if (raw.length === 0)
|
|
214
258
|
return;
|
|
215
259
|
const endsWithNewline = raw.endsWith("\n");
|
|
@@ -266,8 +310,8 @@ async function rewriteSessionTranscriptBindings(path, rewrites) {
|
|
|
266
310
|
}
|
|
267
311
|
/**
|
|
268
312
|
* Package-owned nested seams under session/ only:
|
|
269
|
-
*
|
|
270
|
-
* session transcript typed parent bindings. Never walks attachments
|
|
313
|
+
* sitian records.jsonl,
|
|
314
|
+
* session transcript typed parent bindings. Never walks attachments/.
|
|
271
315
|
*/
|
|
272
316
|
async function rewriteNestedMachinePathPages(pagesDirectory, rewrites) {
|
|
273
317
|
const sessionRoot = join(pagesDirectory, "session");
|
|
@@ -290,7 +334,7 @@ async function rewriteNestedMachinePathPages(pagesDirectory, rewrites) {
|
|
|
290
334
|
if (!entry.isFile())
|
|
291
335
|
continue;
|
|
292
336
|
if (entry.name.endsWith(".pointer.json")) {
|
|
293
|
-
await
|
|
337
|
+
await rewriteLegacyOfficerPointerFile(path, rewrites);
|
|
294
338
|
}
|
|
295
339
|
else if (entry.name === "records.jsonl") {
|
|
296
340
|
await rewriteSitianRecordsJsonl(path, rewrites);
|
|
@@ -303,7 +347,7 @@ async function rewriteNestedMachinePathPages(pagesDirectory, rewrites) {
|
|
|
303
347
|
await walk(sessionRoot);
|
|
304
348
|
}
|
|
305
349
|
/**
|
|
306
|
-
* Rewrite admitted
|
|
350
|
+
* Rewrite the admitted / invocation / runState fact rows (path fields: attachment
|
|
307
351
|
* frozenPath / summons.attachmentPaths pointers only), then nested package-owned
|
|
308
352
|
* session seams. Callers may rewrite before or after the filesystem move/copy:
|
|
309
353
|
* `pagesDirectory` is where the pages currently live on disk; path strings that
|
|
@@ -313,38 +357,53 @@ async function rewriteNestedMachinePathPages(pagesDirectory, rewrites) {
|
|
|
313
357
|
export async function rewriteRoleRunDurablePages(input) {
|
|
314
358
|
const { pagesDirectory } = input;
|
|
315
359
|
const rewrites = collectRewrites(input);
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
360
|
+
// One rewriter per page kind; each keeps its own field list.
|
|
361
|
+
const pageRewriters = {
|
|
362
|
+
admitted: (page) => rewriteAdmittedRoleRunPage(page, rewrites),
|
|
363
|
+
invocation: (page) => rewriteRunDirectoryPathFieldsAgainstRewrites(page, INVOCATION_PAGE_FIELDS, rewrites),
|
|
364
|
+
runState: (page) => {
|
|
365
|
+
rewriteRunDirectoryPathFieldsAgainstRewrites(page, RUN_STATE_PAGE_FIELDS, rewrites);
|
|
366
|
+
if (isRecord(page.principal)) {
|
|
367
|
+
rewriteRunDirectoryPathFieldsAgainstRewrites(page.principal, ["sessionDirectory", "sessionFile"], rewrites);
|
|
368
|
+
}
|
|
369
|
+
// Open court summons: source-run locators + frozen attachment path pointers.
|
|
370
|
+
if (isRecord(page.currentCourt)) {
|
|
371
|
+
rewriteSummonsMaterials(page.currentCourt.summons, rewrites);
|
|
372
|
+
}
|
|
373
|
+
},
|
|
374
|
+
};
|
|
375
|
+
// A page is rewritten only when its fact row exists — never gate on the rendering.
|
|
376
|
+
for (const [section, rewrite] of Object.entries(pageRewriters)) {
|
|
377
|
+
if (readPageSync(pagesDirectory, section) === undefined)
|
|
378
|
+
continue;
|
|
379
|
+
updateSectionSync(pagesDirectory, section, (current) => {
|
|
380
|
+
const page = structuredClone(current);
|
|
381
|
+
rewrite(page);
|
|
382
|
+
return JSON.stringify(page) === JSON.stringify(current) ? undefined : page;
|
|
383
|
+
});
|
|
333
384
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
385
|
+
// Runs from before #1161 (the one-shot book-topology migrator's input) keep these
|
|
386
|
+
// as separate page files; the same rewriters apply. Nothing live writes them.
|
|
387
|
+
for (const [file, rewrite] of [
|
|
388
|
+
["admitted-request.json", pageRewriters.admitted],
|
|
389
|
+
["invocation.json", pageRewriters.invocation],
|
|
390
|
+
["run-state.json", pageRewriters.runState],
|
|
391
|
+
]) {
|
|
392
|
+
const path = join(pagesDirectory, file);
|
|
393
|
+
let raw;
|
|
394
|
+
try {
|
|
395
|
+
raw = await readFile(path, "utf8");
|
|
341
396
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
397
|
+
catch (error) {
|
|
398
|
+
if (isEnoent(error))
|
|
399
|
+
continue;
|
|
400
|
+
throw error;
|
|
345
401
|
}
|
|
402
|
+
const page = JSON.parse(raw);
|
|
403
|
+
const before = JSON.stringify(page);
|
|
404
|
+
rewrite(page);
|
|
346
405
|
if (JSON.stringify(page) !== before) {
|
|
347
|
-
await writeFile(
|
|
406
|
+
await writeFile(path, `${JSON.stringify(page, null, 2)}\n`, "utf8");
|
|
348
407
|
}
|
|
349
408
|
}
|
|
350
409
|
await rewriteNestedMachinePathPages(pagesDirectory, rewrites);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Names in a run directory (docs/dossier-topology.md, #1161). Constants only, so
|
|
3
|
+
* the appender and the `current.json` renderer can both import them.
|
|
4
|
+
*/
|
|
5
|
+
export const RUN_CURRENT_FILE = "current.json";
|
|
6
|
+
export const RUN_HISTORY_FILE = "history.jsonl";
|
|
7
|
+
export const RUN_LOG_FILE = "log.jsonl";
|
|
8
|
+
export const RUN_STATE_FILE = "state.jsonl";
|
|
9
|
+
/**
|
|
10
|
+
* Record kinds that make a leg's history: they land in `history.jsonl`. The
|
|
11
|
+
* original submission ledger and attempt history, the prompt/schema each turn was
|
|
12
|
+
* started with, and officer pointers.
|
|
13
|
+
*/
|
|
14
|
+
export const RUN_HISTORY_KINDS = new Set([
|
|
15
|
+
"candidate", "roundContext", "outcome", "sealed", "post-seal-anomaly",
|
|
16
|
+
"attempt-history", "turn-delivery", "officer-pointer",
|
|
17
|
+
]);
|
|
18
|
+
/** History record kind of a booked officer pointer (appender routes it to history.jsonl). */
|
|
19
|
+
export const OFFICER_POINTER_RECORD_KIND = "officer-pointer";
|
|
20
|
+
/**
|
|
21
|
+
* The facts a run cannot go on without land in `state.jsonl`: the four whole pages only the
|
|
22
|
+
* public call knows, and the native session id a host binds (a resume needs it). A
|
|
23
|
+
* different volume than the submission ledger and than the auxiliary stream, as the
|
|
24
|
+
* files they replaced were (a page write failure throws; a ledger volume that cannot
|
|
25
|
+
* be written does not stop a resume; a stream line that cannot be written is noted).
|
|
26
|
+
* Every other kind lands in `log.jsonl`.
|
|
27
|
+
*/
|
|
28
|
+
export const RUN_STATE_KINDS = new Set([
|
|
29
|
+
"invocation", "admitted-request", "run-state", "terminal", "host-session-id",
|
|
30
|
+
]);
|