@akagilnc/pi-workflow-roles 0.1.5504 → 0.1.5575
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 +5965 -5994
- package/dist/analyst-gate-cycles-read.js +23 -55
- package/dist/analyst-ledger.js +21 -35
- 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-pointer.js +38 -30
- package/dist/auditor-dossier-tool.js +4 -3
- package/dist/auditor-soul.js +3 -11
- package/dist/doctor-evidence.js +3 -3
- package/dist/engine-detour-usage.js +6 -14
- package/dist/headless-host/production-host.js +5316 -5324
- package/dist/host-descriptions.js +0 -4
- package/dist/host-session-record.js +266 -267
- package/dist/migrate-book-topology.js +1314 -696
- package/dist/notary-source-run.js +1 -1
- package/dist/packaged-role-registry.js +5 -44
- package/dist/pi/role-turn-host.js +53 -3
- package/dist/public-cli/auto-resume.js +8 -47
- package/dist/public-cli/instruction-seat-run.js +5 -3
- package/dist/public-cli/invocation.js +51 -56
- package/dist/public-cli/main.js +1916 -1748
- package/dist/public-cli/post-admission.js +96 -55
- package/dist/public-cli/run-lifecycle.js +27 -53
- package/dist/public-cli/settlement.js +157 -302
- package/dist/role-run-placement.js +1 -11
- package/dist/role-run-relocation.js +72 -50
- package/dist/run-dossier-files.js +30 -0
- package/dist/run-dossier.js +322 -0
- package/dist/run-terminal-artifacts.js +68 -197
- package/dist/run-ticket-number.js +16 -3
- package/dist/session-identity.js +49 -18
- package/dist/sitian-appender.js +13 -16
- package/dist/sitian-facade.js +11 -0
- package/dist/sitian-reader.js +44 -29
- package/dist/submission-gate.js +1 -1
- package/dist/ticket-provenance.js +22 -7
- 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 +9 -2
- package/src/analyst-gate-cycles-read.ts +26 -60
- package/src/analyst-ledger.ts +27 -42
- 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 +2 -2
- package/src/archivist-record-pointer.ts +50 -36
- package/src/auditor-dossier-tool.ts +7 -5
- package/src/auditor-soul.ts +3 -9
- 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/doctor-contracts.ts +1 -1
- package/src/doctor-evidence.ts +2 -2
- package/src/engine-detour-tool.ts +1 -1
- package/src/engine-detour-usage.ts +6 -16
- package/src/external-host-turn-loop.ts +25 -0
- package/src/headless-host/production-host.ts +1 -4
- package/src/headless-host/role-turn-host.ts +54 -20
- package/src/host-descriptions.ts +0 -6
- package/src/host-session-record.ts +224 -140
- package/src/notary-source-run.ts +1 -1
- package/src/packaged-role-registry.ts +1 -50
- package/src/pi/adapter.ts +50 -7
- package/src/pi/role-turn-host.ts +51 -3
- package/src/public-cli/auto-resume.ts +7 -43
- package/src/public-cli/instruction-seat-run.ts +9 -2
- package/src/public-cli/invocation.ts +61 -87
- package/src/public-cli/post-admission.ts +111 -72
- package/src/public-cli/run-lifecycle.ts +27 -72
- package/src/public-cli/settlement.ts +193 -418
- package/src/public-cli/terminal.ts +1 -1
- package/src/role-run-placement.ts +2 -13
- package/src/role-run-relocation.ts +71 -68
- package/src/role-runtime.ts +6 -10
- package/src/run-dossier-files.ts +33 -0
- package/src/run-dossier.ts +357 -0
- package/src/run-terminal-artifacts.ts +83 -237
- package/src/run-ticket-number.ts +41 -11
- package/src/session-identity.ts +52 -20
- package/src/sitian-appender.ts +17 -18
- package/src/sitian-facade.ts +22 -0
- package/src/sitian-reader.ts +62 -32
- package/src/submission-gate.ts +1 -1
- package/src/ticket-provenance.ts +20 -7
- package/src/ticket-trajectory.ts +10 -10
package/src/sitian-reader.ts
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
* - Zero whitewashing, zero deduplication.
|
|
7
7
|
* - Canonical rows after malformed lines are always reachable.
|
|
8
8
|
*/
|
|
9
|
-
import { existsSync } from "node:fs";
|
|
10
9
|
import { readFile } from "node:fs/promises";
|
|
11
10
|
|
|
12
11
|
import type {
|
|
@@ -15,46 +14,77 @@ import type {
|
|
|
15
14
|
SitianRecord,
|
|
16
15
|
} from "./sitian-contracts.ts";
|
|
17
16
|
|
|
18
|
-
import { isRecord, errorText } from "./unknown-value.ts";
|
|
17
|
+
import { isRecord, errorText, isEnoent } from "./unknown-value.ts";
|
|
19
18
|
|
|
20
|
-
/**
|
|
21
|
-
export
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
/** One non-blank JSONL line through the sole Sitian decoder. Blank → undefined. */
|
|
20
|
+
export type SitianLineDecode =
|
|
21
|
+
| { readonly ok: true; readonly record: SitianRecord }
|
|
22
|
+
| { readonly ok: false; readonly diagnostic: SitianMalformedDiagnostic };
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Decode one Sitian JSONL line. Callers that must keep original bytes use this
|
|
26
|
+
* with the source line; volume readers fold it into records + diagnostics.
|
|
27
|
+
*/
|
|
28
|
+
export function decodeSitianRecordLine(
|
|
29
|
+
line: string,
|
|
30
|
+
lineNumber: number,
|
|
31
|
+
): SitianLineDecode | undefined {
|
|
32
|
+
if (!line.trim()) return undefined;
|
|
33
|
+
try {
|
|
34
|
+
const parsed = JSON.parse(line);
|
|
35
|
+
if (isRecord(parsed)) {
|
|
36
|
+
return { ok: true, record: parsed as unknown as SitianRecord };
|
|
37
|
+
}
|
|
38
|
+
const typeDesc = parsed === null ? "null" : Array.isArray(parsed) ? "array" : typeof parsed;
|
|
39
|
+
return {
|
|
40
|
+
ok: false,
|
|
41
|
+
diagnostic: {
|
|
42
|
+
kind: "malformed",
|
|
43
|
+
line: lineNumber,
|
|
44
|
+
raw: line,
|
|
45
|
+
error: `expected JSON object, got ${typeDesc}`,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
} catch (error) {
|
|
49
|
+
return {
|
|
50
|
+
ok: false,
|
|
51
|
+
diagnostic: {
|
|
52
|
+
kind: "malformed",
|
|
53
|
+
line: lineNumber,
|
|
54
|
+
raw: line,
|
|
55
|
+
error: errorText(error),
|
|
56
|
+
},
|
|
57
|
+
};
|
|
24
58
|
}
|
|
59
|
+
}
|
|
25
60
|
|
|
26
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Sole decoder for one Sitian JSONL volume's text. Sync so the run-dossier
|
|
63
|
+
* renderer and the async file reader share one implementation.
|
|
64
|
+
*/
|
|
65
|
+
export function parseSitianRecordText(text: string): SitianReadResult {
|
|
27
66
|
const lines = text.split("\n");
|
|
28
|
-
|
|
29
67
|
const records: SitianRecord[] = [];
|
|
30
68
|
const diagnostics: SitianMalformedDiagnostic[] = [];
|
|
31
69
|
|
|
32
70
|
for (let index = 0; index < lines.length; index += 1) {
|
|
33
|
-
const
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const parsed = JSON.parse(line);
|
|
38
|
-
if (isRecord(parsed)) {
|
|
39
|
-
records.push(parsed as unknown as SitianRecord);
|
|
40
|
-
} else {
|
|
41
|
-
const typeDesc = parsed === null ? "null" : Array.isArray(parsed) ? "array" : typeof parsed;
|
|
42
|
-
diagnostics.push({
|
|
43
|
-
kind: "malformed",
|
|
44
|
-
line: index + 1,
|
|
45
|
-
raw: line,
|
|
46
|
-
error: `expected JSON object, got ${typeDesc}`,
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
} catch (error) {
|
|
50
|
-
diagnostics.push({
|
|
51
|
-
kind: "malformed",
|
|
52
|
-
line: index + 1,
|
|
53
|
-
raw: line,
|
|
54
|
-
error: errorText(error),
|
|
55
|
-
});
|
|
56
|
-
}
|
|
71
|
+
const decoded = decodeSitianRecordLine(lines[index]!, index + 1);
|
|
72
|
+
if (decoded === undefined) continue;
|
|
73
|
+
if (decoded.ok) records.push(decoded.record);
|
|
74
|
+
else diagnostics.push(decoded.diagnostic);
|
|
57
75
|
}
|
|
58
76
|
|
|
59
77
|
return { records, diagnostics };
|
|
60
78
|
}
|
|
79
|
+
|
|
80
|
+
/** Read a Sitian record volume with full traversal and non-destructive diagnostics. */
|
|
81
|
+
export async function readSitianRecords(recordFile: string): Promise<SitianReadResult> {
|
|
82
|
+
// Direct read: only ENOENT is absence. EACCES/EPERM and other IO keep their cause
|
|
83
|
+
// (Node fs docs: do not existsSync/access before open — #1161 C3).
|
|
84
|
+
try {
|
|
85
|
+
return parseSitianRecordText(await readFile(recordFile, "utf8"));
|
|
86
|
+
} catch (error) {
|
|
87
|
+
if (isEnoent(error)) return { records: [], diagnostics: [] };
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
}
|
package/src/submission-gate.ts
CHANGED
|
@@ -91,7 +91,7 @@ export function createDefaultGateOfficerSummon(options: {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
|
-
* Book a typed pointer
|
|
94
|
+
* Book a typed pointer in the parent run's current.json officers section.
|
|
95
95
|
* Offline mocks without a real session leave no nested volume (lawful zero).
|
|
96
96
|
*/
|
|
97
97
|
function bookDirectOfficerPointer(
|
package/src/ticket-provenance.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* 一册=一个追加式 records.jsonl。每轮新投影经司天台 appender 追加为不可变提交;
|
|
4
4
|
* 纯追加、不回读历史去重、不折叠。
|
|
5
5
|
*/
|
|
6
|
-
import { readFile
|
|
6
|
+
import { readFile } from "node:fs/promises";
|
|
7
7
|
import { join, resolve } from "node:path";
|
|
8
8
|
|
|
9
9
|
import {
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
} from "./ledger-session-read.ts";
|
|
19
19
|
import { isSafePositiveTicketNumber } from "./run-ticket-number.ts";
|
|
20
20
|
import { runDirectoryOfSessionFile, sessionFileOf } from "./role-run-placement.ts";
|
|
21
|
-
import {
|
|
21
|
+
import { RUN_HISTORY_FILE } from "./run-dossier-files.ts";
|
|
22
22
|
import { adaptSessionDialogue, nativeEventId } from "./session-dialogue.ts";
|
|
23
23
|
import {
|
|
24
24
|
appendSitianRecordBlock,
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
resolveSitianRecordPath,
|
|
27
27
|
type SitianRecordInput,
|
|
28
28
|
} from "./sitian-facade.ts";
|
|
29
|
+
import { decodeSitianRecordLine } from "./sitian-reader.ts";
|
|
29
30
|
import {
|
|
30
31
|
TICKET_PROVENANCE_KIND,
|
|
31
32
|
type TicketProvenanceBound,
|
|
@@ -151,16 +152,28 @@ export async function rehomeUnboundTicketProvenance(
|
|
|
151
152
|
cwd: string,
|
|
152
153
|
home: string,
|
|
153
154
|
): Promise<void> {
|
|
154
|
-
const
|
|
155
|
-
|
|
155
|
+
const ticketInput = ticketProvenanceRecordInput(ticketNumber, cwd, home);
|
|
156
|
+
|
|
157
|
+
// Live staging: ticket-provenance rows in the run's history.jsonl. Append-only
|
|
158
|
+
// history keeps the staging rows; the ticket-root diary is the home.
|
|
159
|
+
// Old run/records.jsonl is not a runtime input (#1161); only migration tools read it.
|
|
160
|
+
let history: string;
|
|
156
161
|
try {
|
|
157
|
-
|
|
162
|
+
history = await readFile(join(runDirectory, RUN_HISTORY_FILE), "utf8");
|
|
158
163
|
} catch (error) {
|
|
159
164
|
if (errnoCode(error) === "ENOENT") return;
|
|
160
165
|
throw error;
|
|
161
166
|
}
|
|
162
|
-
|
|
163
|
-
|
|
167
|
+
const block = history
|
|
168
|
+
.split("\n")
|
|
169
|
+
.flatMap((line, index) => {
|
|
170
|
+
const decoded = decodeSitianRecordLine(line, index + 1);
|
|
171
|
+
if (decoded === undefined || !decoded.ok) return [];
|
|
172
|
+
if (decoded.record.kind !== TICKET_PROVENANCE_KIND) return [];
|
|
173
|
+
return [`${line}\n`];
|
|
174
|
+
})
|
|
175
|
+
.join("");
|
|
176
|
+
if (block !== "") appendSitianRecordBlock(ticketInput, block);
|
|
164
177
|
}
|
|
165
178
|
|
|
166
179
|
/**
|
package/src/ticket-trajectory.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Station resolution (four-layer fallback):
|
|
8
8
|
* 1) terminating tool name inside the session (ak_<role>_output)
|
|
9
|
-
* 2)
|
|
9
|
+
* 2) current.json invocation role
|
|
10
10
|
* 3) run-directory name heuristic
|
|
11
11
|
* 4) unknown (still listed; never dropped)
|
|
12
12
|
*
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* write does not advertise refresh. Regeneration faults surface the original
|
|
19
19
|
* cause via handle.closed / stop(). Caller stops the handle.
|
|
20
20
|
*/
|
|
21
|
+
import { readSectionSync } from "./run-dossier.ts";
|
|
21
22
|
import { lstat, mkdir, readdir, readFile, realpath } from "node:fs/promises";
|
|
22
23
|
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
23
24
|
import { pathToFileURL } from "node:url";
|
|
@@ -286,9 +287,8 @@ type InvocationInfo = {
|
|
|
286
287
|
|
|
287
288
|
async function readInvocation(runDir: string): Promise<InvocationInfo | undefined> {
|
|
288
289
|
try {
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
if (!isRecord(parsed)) return undefined;
|
|
290
|
+
const parsed = readSectionSync(runDir, "invocation");
|
|
291
|
+
if (parsed === undefined) return undefined;
|
|
292
292
|
const info: InvocationInfo = {};
|
|
293
293
|
if (typeof parsed.role === "string" && parsed.role.trim()) info.role = parsed.role.trim();
|
|
294
294
|
if (typeof parsed.thinking === "string" && parsed.thinking.trim()) info.thinking = parsed.thinking.trim();
|
|
@@ -432,7 +432,7 @@ async function parseRunDirectory(runDir: string, ledgerCoord: string): Promise<P
|
|
|
432
432
|
...(invocation?.role !== undefined ? { invocationRole: invocation.role } : {}),
|
|
433
433
|
});
|
|
434
434
|
|
|
435
|
-
// Session mechanical fields win; invocation
|
|
435
|
+
// Session mechanical fields win; the invocation section fills gaps only.
|
|
436
436
|
let { model, provider, thinking } = models;
|
|
437
437
|
if (invocation) {
|
|
438
438
|
if (!thinking && invocation.thinking) thinking = invocation.thinking;
|
|
@@ -660,12 +660,12 @@ ${stationBlocks || "<p data-empty=\"true\">no runs</p>"}
|
|
|
660
660
|
* Factory board reuses this — no parallel receipt parser.
|
|
661
661
|
*
|
|
662
662
|
* Book-run attribution (#176 / #859): read typed `ticketNumber` from each run's
|
|
663
|
-
*
|
|
663
|
+
* current.json invocation section under listBookRunDirectories (flat legacy `runs/` + subject-tree
|
|
664
664
|
* `<ticket|unbound>/runs/`). Legacy `issues/<N>/runs` remains a read-only
|
|
665
665
|
* compatibility entrance. Unbound runs never join a ticket.
|
|
666
666
|
*/
|
|
667
667
|
|
|
668
|
-
/** One book run's typed binding projection from invocation.
|
|
668
|
+
/** One book run's typed binding projection from the invocation section. */
|
|
669
669
|
export type FlatRunTicketBinding = {
|
|
670
670
|
readonly runDir: string;
|
|
671
671
|
readonly runFolder: string;
|
|
@@ -678,10 +678,10 @@ export type FlatRunTicketBinding = {
|
|
|
678
678
|
|
|
679
679
|
/**
|
|
680
680
|
* Book-level run index built once per lane/render and reused per ticket.
|
|
681
|
-
* Pure derived view of book runs'
|
|
681
|
+
* Pure derived view of book runs' current.json invocation sections — not a parallel ledger.
|
|
682
682
|
*/
|
|
683
683
|
export type TicketTrajectoryBookIndex = {
|
|
684
|
-
/** ticket number → runs bound via invocation
|
|
684
|
+
/** ticket number → runs bound via invocation ticketNumber. */
|
|
685
685
|
readonly runsByTicket: ReadonlyMap<number, readonly FlatRunTicketBinding[]>;
|
|
686
686
|
/** Runs with no typed ticketNumber (unknown/unbound seam). */
|
|
687
687
|
readonly unboundRuns: readonly FlatRunTicketBinding[];
|
|
@@ -774,7 +774,7 @@ export async function loadTicketTrajectoryRuns(
|
|
|
774
774
|
runs.push(parsed);
|
|
775
775
|
}
|
|
776
776
|
|
|
777
|
-
// Book runs (flat + subject-tree) bound by typed invocation
|
|
777
|
+
// Book runs (flat + subject-tree) bound by typed invocation ticketNumber.
|
|
778
778
|
const flatBindings = index.runsByTicket.get(issueNumber) ?? [];
|
|
779
779
|
for (const binding of flatBindings) {
|
|
780
780
|
const resolvedRunDir = resolve(binding.runDir);
|