@akagilnc/pi-workflow-roles 0.1.4992 → 0.1.4999
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/dist/acp-host/production-host.js +71 -64
- package/dist/analyst-ledger.js +13 -23
- package/dist/analyst-metric-families/acceptance-success-rework.js +1 -1
- package/dist/analyst-metric-families/round-timeline.js +2 -9
- package/dist/headless-host/production-host.js +71 -64
- package/dist/notary-source-run.js +14 -2
- package/dist/pi/role-turn-host.js +7 -10
- package/dist/public-cli/main.js +66 -62
- package/dist/public-cli/post-admission.js +1 -1
- package/dist/public-cli/run-lifecycle.js +31 -22
- package/dist/public-role-summons.js +3 -1
- package/package.json +1 -1
- package/souls/countersign.md +1 -1
- package/src/analyst-ledger.ts +12 -23
- package/src/analyst-metric-families/acceptance-success-rework.ts +1 -1
- package/src/analyst-metric-families/round-timeline.ts +2 -8
- package/src/analyst-page.ts +1 -0
- package/src/collector-role.ts +4 -1
- package/src/notary-source-run.ts +13 -2
- package/src/pi/role-turn-host.ts +7 -9
- package/src/public-cli/post-admission.ts +1 -1
- package/src/public-cli/run-lifecycle.ts +41 -24
- package/src/public-role-summons.ts +2 -0
|
@@ -8,6 +8,18 @@ import { lstat, realpath } from "node:fs/promises";
|
|
|
8
8
|
import { resolveBookKeyFromGit } from "./activation-ledger-git.js";
|
|
9
9
|
import { activationBookDirectory, physicalPathIdentity, resolveActivationLedgerHome, } from "./activation-ledger-topology.js";
|
|
10
10
|
import { findRunDirectoryById, readRoleRunIdentity } from "./public-cli/run-lifecycle.js";
|
|
11
|
+
async function readRetainedIdentity(runDirectory) {
|
|
12
|
+
try {
|
|
13
|
+
return await readRoleRunIdentity(runDirectory);
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
if (!(error instanceof TypeError || error instanceof SyntaxError))
|
|
17
|
+
throw error;
|
|
18
|
+
throw new NotarySourceRunError("notary --source-run has invalid retained run-state identity", {
|
|
19
|
+
cause: error,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
11
23
|
// Run directory leaf: <runId>@<role>. Production uses uuidv7 runIds; offline tracers
|
|
12
24
|
// may use deterministic non-uuid leaves. Role token stays identifier-shaped.
|
|
13
25
|
const RUN_DIR_NAME = /^([A-Za-z0-9][A-Za-z0-9._-]*)@([A-Za-z][A-Za-z0-9_-]*)$/;
|
|
@@ -94,7 +106,7 @@ export async function resolveNotarySourceRunLocator(options) {
|
|
|
94
106
|
}
|
|
95
107
|
// Authoritative retained record only — legal role/state via shared reader (DRY #14).
|
|
96
108
|
// Identity envelope only: principal payload is not interpreted here.
|
|
97
|
-
const runState = await
|
|
109
|
+
const runState = await readRetainedIdentity(real);
|
|
98
110
|
if (runState === undefined) {
|
|
99
111
|
throw new NotarySourceRunError("notary --source-run lacks retained run-state identity");
|
|
100
112
|
}
|
|
@@ -117,7 +129,7 @@ export async function resolveNotarySourceRunLocator(options) {
|
|
|
117
129
|
export async function loadNotarySourceRunLocator(path) {
|
|
118
130
|
const real = await requireRunDirectory(path, path);
|
|
119
131
|
const identity = parseRunDirectoryName(basename(real));
|
|
120
|
-
const runState = await
|
|
132
|
+
const runState = await readRetainedIdentity(real);
|
|
121
133
|
if (runState === undefined) {
|
|
122
134
|
throw new NotarySourceRunError("notary source-run lacks retained run-state identity");
|
|
123
135
|
}
|
|
@@ -401,14 +401,11 @@ export async function appendPiSessionCustomEntry(authority, principal, customTyp
|
|
|
401
401
|
timestamp,
|
|
402
402
|
})}\n`;
|
|
403
403
|
await appendFile(sessionFile, pointerLine, "utf8");
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
catch { }
|
|
404
|
+
sitianReport({
|
|
405
|
+
level: "event",
|
|
406
|
+
kind: "dispatch-error",
|
|
407
|
+
sessionParent: sessionFile,
|
|
408
|
+
payload: { customType, data },
|
|
409
|
+
source: "pi-role-turn-host",
|
|
410
|
+
});
|
|
414
411
|
}
|
package/dist/public-cli/main.js
CHANGED
|
@@ -17654,16 +17654,13 @@ async function appendPiSessionCustomEntry(authority, principal, customType, data
|
|
|
17654
17654
|
})}
|
|
17655
17655
|
`;
|
|
17656
17656
|
await appendFile(sessionFile, pointerLine, "utf8");
|
|
17657
|
-
|
|
17658
|
-
|
|
17659
|
-
|
|
17660
|
-
|
|
17661
|
-
|
|
17662
|
-
|
|
17663
|
-
|
|
17664
|
-
});
|
|
17665
|
-
} catch {
|
|
17666
|
-
}
|
|
17657
|
+
sitianReport({
|
|
17658
|
+
level: "event",
|
|
17659
|
+
kind: "dispatch-error",
|
|
17660
|
+
sessionParent: sessionFile,
|
|
17661
|
+
payload: { customType, data },
|
|
17662
|
+
source: "pi-role-turn-host"
|
|
17663
|
+
});
|
|
17667
17664
|
}
|
|
17668
17665
|
var INTERNAL_ROLE_ENTRYPOINT_RELATIVE2, EXPLICIT_INTERNAL_LOAD_PROBE_ARGS, execFileAsync;
|
|
17669
17666
|
var init_role_turn_host = __esm({
|
|
@@ -19004,7 +19001,7 @@ function parseCurrentCourtState(raw) {
|
|
|
19004
19001
|
...summons === void 0 ? {} : { summons }
|
|
19005
19002
|
};
|
|
19006
19003
|
}
|
|
19007
|
-
async function
|
|
19004
|
+
async function readRoleRunStateRaw(runDirectory) {
|
|
19008
19005
|
let raw;
|
|
19009
19006
|
try {
|
|
19010
19007
|
raw = JSON.parse(await readFile12(join15(runDirectory, RUN_STATE_FILE), "utf8"));
|
|
@@ -19012,24 +19009,40 @@ async function readRoleRunStateDisk(runDirectory) {
|
|
|
19012
19009
|
if (errorCodeOf2(error) === "ENOENT") return void 0;
|
|
19013
19010
|
throw error;
|
|
19014
19011
|
}
|
|
19012
|
+
return raw;
|
|
19013
|
+
}
|
|
19014
|
+
function parseRoleRunIdentity(raw, runDirectory) {
|
|
19015
19015
|
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
19016
|
-
|
|
19016
|
+
throw new TypeError("Invalid run-state.json");
|
|
19017
19017
|
}
|
|
19018
19018
|
const record4 = raw;
|
|
19019
19019
|
if (typeof record4.runId !== "string" || record4.runId.trim() === "") {
|
|
19020
|
-
|
|
19020
|
+
throw new TypeError("Invalid run-state.json");
|
|
19021
19021
|
}
|
|
19022
19022
|
const role = typeof record4.role === "string" ? packagedRoleMetadata(record4.role)?.role : void 0;
|
|
19023
19023
|
if (role === void 0) {
|
|
19024
|
-
|
|
19024
|
+
throw new TypeError("Invalid run-state.json");
|
|
19025
19025
|
}
|
|
19026
19026
|
if (record4.state !== "admitted" && record4.state !== "running" && record4.state !== "resumable" && record4.state !== "terminal") {
|
|
19027
|
-
|
|
19027
|
+
throw new TypeError("Invalid run-state.json");
|
|
19028
19028
|
}
|
|
19029
|
-
if (typeof record4.bookKey !== "string")
|
|
19030
|
-
|
|
19031
|
-
|
|
19032
|
-
|
|
19029
|
+
if (typeof record4.bookKey !== "string") throw new TypeError("Invalid run-state.json");
|
|
19030
|
+
return {
|
|
19031
|
+
runId: record4.runId,
|
|
19032
|
+
role,
|
|
19033
|
+
state: record4.state,
|
|
19034
|
+
bookKey: record4.bookKey,
|
|
19035
|
+
runDirectory
|
|
19036
|
+
};
|
|
19037
|
+
}
|
|
19038
|
+
async function readRoleRunStateDisk(runDirectory) {
|
|
19039
|
+
const raw = await readRoleRunStateRaw(runDirectory);
|
|
19040
|
+
if (raw === void 0) return void 0;
|
|
19041
|
+
const identity = parseRoleRunIdentity(raw, runDirectory);
|
|
19042
|
+
const record4 = raw;
|
|
19043
|
+
if (typeof record4.projectRoot !== "string") throw new TypeError("Invalid run-state.json");
|
|
19044
|
+
if (typeof record4.sessionDirectory !== "string") throw new TypeError("Invalid run-state.json");
|
|
19045
|
+
if (typeof record4.admittedRequestPath !== "string") throw new TypeError("Invalid run-state.json");
|
|
19033
19046
|
const storedRunDirectory = typeof record4.runDirectory === "string" && record4.runDirectory.trim() !== "" ? record4.runDirectory : runDirectory;
|
|
19034
19047
|
const runDir = runDirectory;
|
|
19035
19048
|
const principalWire = {
|
|
@@ -19052,10 +19065,10 @@ async function readRoleRunStateDisk(runDirectory) {
|
|
|
19052
19065
|
const phase = record4.phase === "plan" || record4.phase === "apply" ? record4.phase : void 0;
|
|
19053
19066
|
const currentCourt = parseCurrentCourtState(record4.currentCourt);
|
|
19054
19067
|
return {
|
|
19055
|
-
runId:
|
|
19056
|
-
role,
|
|
19057
|
-
state:
|
|
19058
|
-
bookKey:
|
|
19068
|
+
runId: identity.runId,
|
|
19069
|
+
role: identity.role,
|
|
19070
|
+
state: identity.state,
|
|
19071
|
+
bookKey: identity.bookKey,
|
|
19059
19072
|
projectRoot: record4.projectRoot,
|
|
19060
19073
|
runDirectory: runDir,
|
|
19061
19074
|
admittedRequestPath: rewriteRunDirectoryPathValue(
|
|
@@ -19115,15 +19128,8 @@ function materializeRoleRunFromDisk(disk, authority) {
|
|
|
19115
19128
|
}
|
|
19116
19129
|
}
|
|
19117
19130
|
async function readRoleRunIdentity(runDirectory) {
|
|
19118
|
-
const
|
|
19119
|
-
|
|
19120
|
-
return {
|
|
19121
|
-
runId: disk.runId,
|
|
19122
|
-
role: disk.role,
|
|
19123
|
-
bookKey: disk.bookKey,
|
|
19124
|
-
runDirectory: disk.runDirectory,
|
|
19125
|
-
state: disk.state
|
|
19126
|
-
};
|
|
19131
|
+
const raw = await readRoleRunStateRaw(runDirectory);
|
|
19132
|
+
return raw === void 0 ? void 0 : parseRoleRunIdentity(raw, runDirectory);
|
|
19127
19133
|
}
|
|
19128
19134
|
async function markRunAdmitted(admitted, authority) {
|
|
19129
19135
|
const { sessionDirectory, sessionFile } = authority.decode(admitted.principal);
|
|
@@ -20126,6 +20132,16 @@ var init_run_lifecycle = __esm({
|
|
|
20126
20132
|
// src/notary-source-run.ts
|
|
20127
20133
|
import { dirname as dirname10, isAbsolute as isAbsolute6, join as join16, resolve as resolve7, basename as basename7 } from "node:path";
|
|
20128
20134
|
import { lstat as lstat3, realpath as realpath3 } from "node:fs/promises";
|
|
20135
|
+
async function readRetainedIdentity(runDirectory) {
|
|
20136
|
+
try {
|
|
20137
|
+
return await readRoleRunIdentity(runDirectory);
|
|
20138
|
+
} catch (error) {
|
|
20139
|
+
if (!(error instanceof TypeError || error instanceof SyntaxError)) throw error;
|
|
20140
|
+
throw new NotarySourceRunError("notary --source-run has invalid retained run-state identity", {
|
|
20141
|
+
cause: error
|
|
20142
|
+
});
|
|
20143
|
+
}
|
|
20144
|
+
}
|
|
20129
20145
|
function parseRunDirectoryName(name) {
|
|
20130
20146
|
const match = RUN_DIR_NAME.exec(name);
|
|
20131
20147
|
if (match === null) return void 0;
|
|
@@ -20200,7 +20216,7 @@ async function resolveNotarySourceRunLocator(options) {
|
|
|
20200
20216
|
"notary --source-run must resolve to a retained run under the project machine-ledger book"
|
|
20201
20217
|
);
|
|
20202
20218
|
}
|
|
20203
|
-
const runState = await
|
|
20219
|
+
const runState = await readRetainedIdentity(real);
|
|
20204
20220
|
if (runState === void 0) {
|
|
20205
20221
|
throw new NotarySourceRunError(
|
|
20206
20222
|
"notary --source-run lacks retained run-state identity"
|
|
@@ -27694,7 +27710,7 @@ function resumeTurnRequestProjectionOptions(admitted, request, env, summonsPrepa
|
|
|
27694
27710
|
};
|
|
27695
27711
|
}
|
|
27696
27712
|
function roleTurnOptions(env, admitted, continuation) {
|
|
27697
|
-
const correlationId =
|
|
27713
|
+
const correlationId = env.correlationId ?? admitted.correlationId;
|
|
27698
27714
|
return {
|
|
27699
27715
|
packageRoot: env.packageRoot,
|
|
27700
27716
|
home: env.home,
|
|
@@ -28296,10 +28312,12 @@ async function summonPublicRole(options) {
|
|
|
28296
28312
|
const {
|
|
28297
28313
|
loadCredentialProviders: loadCredentialProviders2,
|
|
28298
28314
|
loadPublicCliConfig: loadPublicCliConfig2,
|
|
28299
|
-
resolveEffectiveSeat: resolveEffectiveSeat2
|
|
28315
|
+
resolveEffectiveSeat: resolveEffectiveSeat2,
|
|
28316
|
+
validatePublicCliConfigAxes: validatePublicCliConfigAxes2
|
|
28300
28317
|
} = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
28301
28318
|
const credentials = options.credentials ?? await loadCredentialProviders2(agentDir);
|
|
28302
28319
|
const config = await loadPublicCliConfig2(home);
|
|
28320
|
+
validatePublicCliConfigAxes2(config, packageRoot2);
|
|
28303
28321
|
const resolvedSeat = resolveEffectiveSeat2(config, options.role, credentials);
|
|
28304
28322
|
const inheritedSelection = options.model === void 0 ? void 0 : {
|
|
28305
28323
|
provider: options.model.provider,
|
|
@@ -29914,15 +29932,7 @@ function isRecord12(value) {
|
|
|
29914
29932
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
29915
29933
|
}
|
|
29916
29934
|
async function readExistingRunLifecycleState(runDirectory) {
|
|
29917
|
-
|
|
29918
|
-
const raw = JSON.parse(
|
|
29919
|
-
await readFile20(join34(runDirectory, "run-state.json"), "utf8")
|
|
29920
|
-
);
|
|
29921
|
-
if (!isRecord12(raw) || typeof raw.state !== "string") return void 0;
|
|
29922
|
-
return raw.state;
|
|
29923
|
-
} catch {
|
|
29924
|
-
return void 0;
|
|
29925
|
-
}
|
|
29935
|
+
return (await readRoleRunIdentity(runDirectory))?.state;
|
|
29926
29936
|
}
|
|
29927
29937
|
function ghostLeaseCheckFromAutopsy(autopsy) {
|
|
29928
29938
|
switch (autopsy.verdict) {
|
|
@@ -29957,13 +29967,6 @@ function parseRunDirectoryName2(name) {
|
|
|
29957
29967
|
if (at <= 0 || at === name.length - 1) return void 0;
|
|
29958
29968
|
return { runId: name.slice(0, at), role: name.slice(at + 1) };
|
|
29959
29969
|
}
|
|
29960
|
-
function tryResolveBookKeyFromProjectRoot(projectRoot) {
|
|
29961
|
-
try {
|
|
29962
|
-
return resolveBookKeyFromGit(projectRoot);
|
|
29963
|
-
} catch {
|
|
29964
|
-
return void 0;
|
|
29965
|
-
}
|
|
29966
|
-
}
|
|
29967
29970
|
async function listLedgerBookNames(booksRoot) {
|
|
29968
29971
|
try {
|
|
29969
29972
|
const entries = await readdir8(booksRoot, { withFileTypes: true });
|
|
@@ -30144,7 +30147,13 @@ async function classifyScopedRun(input) {
|
|
|
30144
30147
|
reasons.push(errorText3(error));
|
|
30145
30148
|
}
|
|
30146
30149
|
}
|
|
30147
|
-
|
|
30150
|
+
let lifecycle;
|
|
30151
|
+
try {
|
|
30152
|
+
lifecycle = await readExistingRunLifecycleState(input.runDirectory);
|
|
30153
|
+
} catch (error) {
|
|
30154
|
+
missingSources.push("run-state");
|
|
30155
|
+
reasons.push(errorText3(error));
|
|
30156
|
+
}
|
|
30148
30157
|
let ghostLeg;
|
|
30149
30158
|
if (lifecycle === "admitted" || lifecycle === "running") {
|
|
30150
30159
|
const ghost = await classifyGhostCandidate({
|
|
@@ -30253,8 +30262,8 @@ async function scanAnalystIssueRuns(input) {
|
|
|
30253
30262
|
wholeBook = true;
|
|
30254
30263
|
}
|
|
30255
30264
|
} else if (input.projectRoot !== void 0) {
|
|
30256
|
-
const resolved =
|
|
30257
|
-
if (resolved
|
|
30265
|
+
const resolved = resolveAnalystBookKey(input.projectRoot);
|
|
30266
|
+
if (!isSyntheticAnalystBookKey(resolved)) {
|
|
30258
30267
|
bookNames = [resolved];
|
|
30259
30268
|
wholeBook = true;
|
|
30260
30269
|
} else {
|
|
@@ -30330,7 +30339,7 @@ var LIVE_RUN_STATES;
|
|
|
30330
30339
|
var init_analyst_ledger = __esm({
|
|
30331
30340
|
"src/analyst-ledger.ts"() {
|
|
30332
30341
|
"use strict";
|
|
30333
|
-
|
|
30342
|
+
init_analyst_book_key();
|
|
30334
30343
|
init_activation_ledger_topology();
|
|
30335
30344
|
init_role_run_placement();
|
|
30336
30345
|
init_run_lifecycle();
|
|
@@ -30998,12 +31007,6 @@ function isRecord14(value) {
|
|
|
30998
31007
|
function wallMsFromSpan2(startedAt, endedAt) {
|
|
30999
31008
|
return Date.parse(endedAt) - Date.parse(startedAt);
|
|
31000
31009
|
}
|
|
31001
|
-
function readOutcomeStatus(body) {
|
|
31002
|
-
if (!isRecord14(body.outcome)) return void 0;
|
|
31003
|
-
const status = body.outcome.status;
|
|
31004
|
-
if (typeof status !== "string" || status.trim() === "") return void 0;
|
|
31005
|
-
return status;
|
|
31006
|
-
}
|
|
31007
31010
|
function readClassCount(body) {
|
|
31008
31011
|
if (!isRecord14(body.outcome)) return void 0;
|
|
31009
31012
|
if (!isRecord14(body.outcome.decisiveFacts)) return void 0;
|
|
@@ -31023,7 +31026,7 @@ function projectTerminal(facts) {
|
|
|
31023
31026
|
if (facts.terminal.file === "audit-incomplete.json") {
|
|
31024
31027
|
return { kind: "death", channel: "audit-incomplete" };
|
|
31025
31028
|
}
|
|
31026
|
-
const status =
|
|
31029
|
+
const status = extractStatus(facts.terminal.body);
|
|
31027
31030
|
const classCount = readClassCount(facts.terminal.body);
|
|
31028
31031
|
const receiptStatus = status ?? "unparsed";
|
|
31029
31032
|
if (classCount === void 0) {
|
|
@@ -31092,6 +31095,7 @@ var roundTimelineFamily, round_timeline_default;
|
|
|
31092
31095
|
var init_round_timeline = __esm({
|
|
31093
31096
|
"src/analyst-metric-families/round-timeline.ts"() {
|
|
31094
31097
|
"use strict";
|
|
31098
|
+
init_acceptance_success_rework();
|
|
31095
31099
|
roundTimelineFamily = {
|
|
31096
31100
|
id: "round-timeline",
|
|
31097
31101
|
contribute(input) {
|
|
@@ -877,7 +877,7 @@ export function resumeTurnRequestProjectionOptions(admitted, request, env, summo
|
|
|
877
877
|
}
|
|
878
878
|
/** Shared new-turn and in-call auto-resume projection. Seat code supplies prompt and activation. */
|
|
879
879
|
export function roleTurnOptions(env, admitted, continuation) {
|
|
880
|
-
const correlationId =
|
|
880
|
+
const correlationId = env.correlationId ?? admitted.correlationId;
|
|
881
881
|
return {
|
|
882
882
|
packageRoot: env.packageRoot,
|
|
883
883
|
home: env.home,
|
|
@@ -132,7 +132,7 @@ function parseCurrentCourtState(raw) {
|
|
|
132
132
|
...(summons === undefined ? {} : { summons }),
|
|
133
133
|
};
|
|
134
134
|
}
|
|
135
|
-
async function
|
|
135
|
+
async function readRoleRunStateRaw(runDirectory) {
|
|
136
136
|
let raw;
|
|
137
137
|
try {
|
|
138
138
|
raw = JSON.parse(await readFile(join(runDirectory, RUN_STATE_FILE), "utf8"));
|
|
@@ -148,31 +148,48 @@ async function readRoleRunStateDisk(runDirectory) {
|
|
|
148
148
|
return undefined;
|
|
149
149
|
throw error;
|
|
150
150
|
}
|
|
151
|
+
return raw;
|
|
152
|
+
}
|
|
153
|
+
function parseRoleRunIdentity(raw, runDirectory) {
|
|
151
154
|
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
152
|
-
|
|
155
|
+
throw new TypeError("Invalid run-state.json");
|
|
153
156
|
}
|
|
154
157
|
const record = raw;
|
|
155
158
|
if (typeof record.runId !== "string" || record.runId.trim() === "") {
|
|
156
|
-
|
|
159
|
+
throw new TypeError("Invalid run-state.json");
|
|
157
160
|
}
|
|
158
161
|
const role = typeof record.role === "string" ? packagedRoleMetadata(record.role)?.role : undefined;
|
|
159
162
|
if (role === undefined) {
|
|
160
|
-
|
|
163
|
+
throw new TypeError("Invalid run-state.json");
|
|
161
164
|
}
|
|
162
165
|
if (record.state !== "admitted" &&
|
|
163
166
|
record.state !== "running" &&
|
|
164
167
|
record.state !== "resumable" &&
|
|
165
168
|
record.state !== "terminal") {
|
|
166
|
-
|
|
169
|
+
throw new TypeError("Invalid run-state.json");
|
|
167
170
|
}
|
|
168
171
|
if (typeof record.bookKey !== "string")
|
|
172
|
+
throw new TypeError("Invalid run-state.json");
|
|
173
|
+
return {
|
|
174
|
+
runId: record.runId,
|
|
175
|
+
role,
|
|
176
|
+
state: record.state,
|
|
177
|
+
bookKey: record.bookKey,
|
|
178
|
+
runDirectory,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
async function readRoleRunStateDisk(runDirectory) {
|
|
182
|
+
const raw = await readRoleRunStateRaw(runDirectory);
|
|
183
|
+
if (raw === undefined)
|
|
169
184
|
return undefined;
|
|
185
|
+
const identity = parseRoleRunIdentity(raw, runDirectory);
|
|
186
|
+
const record = raw;
|
|
170
187
|
if (typeof record.projectRoot !== "string")
|
|
171
|
-
|
|
188
|
+
throw new TypeError("Invalid run-state.json");
|
|
172
189
|
if (typeof record.sessionDirectory !== "string")
|
|
173
|
-
|
|
190
|
+
throw new TypeError("Invalid run-state.json");
|
|
174
191
|
if (typeof record.admittedRequestPath !== "string")
|
|
175
|
-
|
|
192
|
+
throw new TypeError("Invalid run-state.json");
|
|
176
193
|
const storedRunDirectory = typeof record.runDirectory === "string" && record.runDirectory.trim() !== ""
|
|
177
194
|
? record.runDirectory
|
|
178
195
|
: runDirectory;
|
|
@@ -201,10 +218,10 @@ async function readRoleRunStateDisk(runDirectory) {
|
|
|
201
218
|
: undefined;
|
|
202
219
|
const currentCourt = parseCurrentCourtState(record.currentCourt);
|
|
203
220
|
return {
|
|
204
|
-
runId:
|
|
205
|
-
role,
|
|
206
|
-
state:
|
|
207
|
-
bookKey:
|
|
221
|
+
runId: identity.runId,
|
|
222
|
+
role: identity.role,
|
|
223
|
+
state: identity.state,
|
|
224
|
+
bookKey: identity.bookKey,
|
|
208
225
|
projectRoot: record.projectRoot,
|
|
209
226
|
runDirectory: runDir,
|
|
210
227
|
admittedRequestPath: rewriteRunDirectoryPathValue(record.admittedRequestPath, storedRunDirectory, runDirectory),
|
|
@@ -273,16 +290,8 @@ export async function readRoleRunState(runDirectory, authority) {
|
|
|
273
290
|
* Used by notary locator / role peek that never consume session coordinates.
|
|
274
291
|
*/
|
|
275
292
|
export async function readRoleRunIdentity(runDirectory) {
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
return undefined;
|
|
279
|
-
return {
|
|
280
|
-
runId: disk.runId,
|
|
281
|
-
role: disk.role,
|
|
282
|
-
bookKey: disk.bookKey,
|
|
283
|
-
runDirectory: disk.runDirectory,
|
|
284
|
-
state: disk.state,
|
|
285
|
-
};
|
|
293
|
+
const raw = await readRoleRunStateRaw(runDirectory);
|
|
294
|
+
return raw === undefined ? undefined : parseRoleRunIdentity(raw, runDirectory);
|
|
286
295
|
}
|
|
287
296
|
export async function markRunAdmitted(admitted, authority) {
|
|
288
297
|
const { sessionDirectory, sessionFile } = authority.decode(admitted.principal);
|
|
@@ -148,10 +148,12 @@ async function summonPublicRole(options) {
|
|
|
148
148
|
const {
|
|
149
149
|
loadCredentialProviders,
|
|
150
150
|
loadPublicCliConfig,
|
|
151
|
-
resolveEffectiveSeat
|
|
151
|
+
resolveEffectiveSeat,
|
|
152
|
+
validatePublicCliConfigAxes
|
|
152
153
|
} = await import("./public-cli/config.js");
|
|
153
154
|
const credentials = options.credentials ?? await loadCredentialProviders(agentDir);
|
|
154
155
|
const config = await loadPublicCliConfig(home);
|
|
156
|
+
validatePublicCliConfigAxes(config, packageRoot);
|
|
155
157
|
const resolvedSeat = resolveEffectiveSeat(config, options.role, credentials);
|
|
156
158
|
const inheritedSelection = options.model === void 0 ? void 0 : {
|
|
157
159
|
provider: options.model.provider,
|
package/package.json
CHANGED
package/souls/countersign.md
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
**三、相抵** 票面,相关票与在飞分支与法源有无抵触。
|
|
26
26
|
|
|
27
|
-
**四、缺失**
|
|
27
|
+
**四、缺失** 法源要求的,票面有没有漏:适用法只查两类:票面与某条 ADR 决定相抵的,和把某条决定留给别的票承接的,票面须写明该条与「由 #x 承接」;这两类之外的 ADR 没引不算缺失,不得为此封驳;验收面须覆盖票面每条主张;票面里每一条行为都须答得出《送庭前三问》第一问——由哪条接缝、哪条 run 担它:暂停的是谁、resume 谁、谁接着走这类没有名字的行为,即缺失;前置产物、决定、答复须在;承重主张的源头不存在、不支持、已过时,同为缺失。缺失列表在能力范围内一次扫完,尽量避免因缺失导致多轮往返。
|
|
28
28
|
|
|
29
29
|
**五、擅加** 票面有没有超出法源的机制、约束、验收、术语。
|
|
30
30
|
|
package/src/analyst-ledger.ts
CHANGED
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
import { readdir, readFile } from "node:fs/promises";
|
|
16
16
|
import { basename, join } from "node:path";
|
|
17
17
|
|
|
18
|
-
import {
|
|
18
|
+
import { isSyntheticAnalystBookKey, resolveAnalystBookKey } from "./analyst-book-key.ts";
|
|
19
19
|
import {
|
|
20
20
|
pathContainedIn,
|
|
21
21
|
physicalPathIdentity,
|
|
22
22
|
resolveActivationLedgerHome,
|
|
23
23
|
} from "./activation-ledger-topology.ts";
|
|
24
24
|
import { listBookRunDirectories } from "./role-run-placement.ts";
|
|
25
|
-
import { autopsyWriterLock } from "./public-cli/run-lifecycle.ts";
|
|
25
|
+
import { autopsyWriterLock, readRoleRunIdentity } from "./public-cli/run-lifecycle.ts";
|
|
26
26
|
import { readRunTicketNumber } from "./run-ticket-number.ts";
|
|
27
27
|
import {
|
|
28
28
|
extractSessionModelSequence,
|
|
@@ -77,15 +77,7 @@ const LIVE_RUN_STATES = new Set(["admitted", "running", "resumable"]);
|
|
|
77
77
|
async function readExistingRunLifecycleState(
|
|
78
78
|
runDirectory: string,
|
|
79
79
|
): Promise<string | undefined> {
|
|
80
|
-
|
|
81
|
-
const raw: unknown = JSON.parse(
|
|
82
|
-
await readFile(join(runDirectory, "run-state.json"), "utf8"),
|
|
83
|
-
);
|
|
84
|
-
if (!isRecord(raw) || typeof raw.state !== "string") return undefined;
|
|
85
|
-
return raw.state;
|
|
86
|
-
} catch {
|
|
87
|
-
return undefined;
|
|
88
|
-
}
|
|
80
|
+
return (await readRoleRunIdentity(runDirectory))?.state;
|
|
89
81
|
}
|
|
90
82
|
|
|
91
83
|
/**
|
|
@@ -165,15 +157,6 @@ type InvocationScopeFields = {
|
|
|
165
157
|
readonly ticketNumber?: number;
|
|
166
158
|
};
|
|
167
159
|
|
|
168
|
-
/** Best-effort book key from a projectRoot git common-dir; undefined when not a git tree. */
|
|
169
|
-
function tryResolveBookKeyFromProjectRoot(projectRoot: string): string | undefined {
|
|
170
|
-
try {
|
|
171
|
-
return resolveBookKeyFromGit(projectRoot);
|
|
172
|
-
} catch {
|
|
173
|
-
return undefined;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
160
|
async function listLedgerBookNames(booksRoot: string): Promise<string[]> {
|
|
178
161
|
try {
|
|
179
162
|
const entries = await readdir(booksRoot, { withFileTypes: true });
|
|
@@ -509,7 +492,13 @@ async function classifyScopedRun(input: {
|
|
|
509
492
|
// #855: writer-lease ghost check is independent of terminal artifact status.
|
|
510
493
|
// present → still emit metrics; unreadable → still enter missingSources;
|
|
511
494
|
// admitted|running + non-live lease → still list in ghostLegs (ticket #4).
|
|
512
|
-
|
|
495
|
+
let lifecycle: string | undefined;
|
|
496
|
+
try {
|
|
497
|
+
lifecycle = await readExistingRunLifecycleState(input.runDirectory);
|
|
498
|
+
} catch (error) {
|
|
499
|
+
missingSources.push("run-state");
|
|
500
|
+
reasons.push(errorText(error));
|
|
501
|
+
}
|
|
513
502
|
let ghostLeg: AnalystGhostLeg | undefined;
|
|
514
503
|
if (lifecycle === "admitted" || lifecycle === "running") {
|
|
515
504
|
const ghost = await classifyGhostCandidate({
|
|
@@ -667,8 +656,8 @@ export async function scanAnalystIssueRuns(input: {
|
|
|
667
656
|
wholeBook = true;
|
|
668
657
|
}
|
|
669
658
|
} else if (input.projectRoot !== undefined) {
|
|
670
|
-
const resolved =
|
|
671
|
-
if (resolved
|
|
659
|
+
const resolved = resolveAnalystBookKey(input.projectRoot);
|
|
660
|
+
if (!isSyntheticAnalystBookKey(resolved)) {
|
|
672
661
|
bookNames = [resolved];
|
|
673
662
|
wholeBook = true;
|
|
674
663
|
} else {
|
|
@@ -117,7 +117,7 @@ function findCollectorGroups(body: Record<string, unknown>): unknown {
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
/** Extract role receipt status from canonical terminal body faces. */
|
|
120
|
-
function extractStatus(body: Record<string, unknown>): string | undefined {
|
|
120
|
+
export function extractStatus(body: Record<string, unknown>): string | undefined {
|
|
121
121
|
const outcome = body.outcome;
|
|
122
122
|
if (isRecord(outcome) && typeof outcome.status === "string" && outcome.status.trim() !== "") {
|
|
123
123
|
return outcome.status;
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { AnalystReadableRunFacts } from "../analyst-ledger.ts";
|
|
12
12
|
import type { AnalystMetricFamilyModule } from "../analyst-metric-family.ts";
|
|
13
|
+
import { extractStatus } from "./acceptance-success-rework.ts";
|
|
13
14
|
import type {
|
|
14
15
|
AnalystFirstFrameAt,
|
|
15
16
|
AnalystMissingSource,
|
|
@@ -73,13 +74,6 @@ function wallMsFromSpan(startedAt: string, endedAt: string): number {
|
|
|
73
74
|
return Date.parse(endedAt) - Date.parse(startedAt);
|
|
74
75
|
}
|
|
75
76
|
|
|
76
|
-
function readOutcomeStatus(body: Record<string, unknown>): string | undefined {
|
|
77
|
-
if (!isRecord(body.outcome)) return undefined;
|
|
78
|
-
const status = body.outcome.status;
|
|
79
|
-
if (typeof status !== "string" || status.trim() === "") return undefined;
|
|
80
|
-
return status;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
77
|
function readClassCount(body: Record<string, unknown>): number | undefined {
|
|
84
78
|
if (!isRecord(body.outcome)) return undefined;
|
|
85
79
|
if (!isRecord(body.outcome.decisiveFacts)) return undefined;
|
|
@@ -101,7 +95,7 @@ function projectTerminal(facts: AnalystReadableRunFacts): AnalystRoundTimelineTe
|
|
|
101
95
|
return { kind: "death", channel: "audit-incomplete" };
|
|
102
96
|
}
|
|
103
97
|
// report.json — receipt face; classCount only when producer wrote a number.
|
|
104
|
-
const status =
|
|
98
|
+
const status = extractStatus(facts.terminal.body);
|
|
105
99
|
const classCount = readClassCount(facts.terminal.body);
|
|
106
100
|
const receiptStatus = status ?? "unparsed";
|
|
107
101
|
if (classCount === undefined) {
|
package/src/analyst-page.ts
CHANGED
|
@@ -21,6 +21,7 @@ import { composeAnalystMetricFamilySections } from "./analyst-metric-family.ts";
|
|
|
21
21
|
|
|
22
22
|
/** Required run sources that may render a loud unreadable exclusion. */
|
|
23
23
|
export type AnalystMissingSource =
|
|
24
|
+
| "run-state"
|
|
24
25
|
| "session-timeline"
|
|
25
26
|
| "tool-association"
|
|
26
27
|
| "terminal-artifact"
|
package/src/collector-role.ts
CHANGED
|
@@ -217,7 +217,10 @@ function buildMethodContext(activation: CollectorActivation): string {
|
|
|
217
217
|
function parsePositiveTicket(raw: unknown, label: string): number | undefined {
|
|
218
218
|
if (raw === undefined || raw === null) return undefined;
|
|
219
219
|
if (typeof raw === "number" && Number.isSafeInteger(raw) && raw >= 1) return raw;
|
|
220
|
-
if (typeof raw === "string" && /^[1-9]\d*$/.test(raw.trim()))
|
|
220
|
+
if (typeof raw === "string" && /^[1-9]\d*$/.test(raw.trim())) {
|
|
221
|
+
const value = Number(raw.trim());
|
|
222
|
+
if (Number.isSafeInteger(value)) return value;
|
|
223
|
+
}
|
|
221
224
|
throw new CollectorTargetBindError(`通进司绑定 ${label} 须为正安全整数`);
|
|
222
225
|
}
|
|
223
226
|
|
package/src/notary-source-run.ts
CHANGED
|
@@ -15,6 +15,17 @@ import {
|
|
|
15
15
|
import type { NotarySourceRunLocator } from "./notary-contracts.ts";
|
|
16
16
|
import { findRunDirectoryById, readRoleRunIdentity } from "./public-cli/run-lifecycle.ts";
|
|
17
17
|
|
|
18
|
+
async function readRetainedIdentity(runDirectory: string) {
|
|
19
|
+
try {
|
|
20
|
+
return await readRoleRunIdentity(runDirectory);
|
|
21
|
+
} catch (error) {
|
|
22
|
+
if (!(error instanceof TypeError || error instanceof SyntaxError)) throw error;
|
|
23
|
+
throw new NotarySourceRunError("notary --source-run has invalid retained run-state identity", {
|
|
24
|
+
cause: error,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
18
29
|
// Run directory leaf: <runId>@<role>. Production uses uuidv7 runIds; offline tracers
|
|
19
30
|
// may use deterministic non-uuid leaves. Role token stays identifier-shaped.
|
|
20
31
|
const RUN_DIR_NAME =
|
|
@@ -131,7 +142,7 @@ export async function resolveNotarySourceRunLocator(options: {
|
|
|
131
142
|
|
|
132
143
|
// Authoritative retained record only — legal role/state via shared reader (DRY #14).
|
|
133
144
|
// Identity envelope only: principal payload is not interpreted here.
|
|
134
|
-
const runState = await
|
|
145
|
+
const runState = await readRetainedIdentity(real);
|
|
135
146
|
if (runState === undefined) {
|
|
136
147
|
throw new NotarySourceRunError(
|
|
137
148
|
"notary --source-run lacks retained run-state identity",
|
|
@@ -166,7 +177,7 @@ export async function loadNotarySourceRunLocator(
|
|
|
166
177
|
): Promise<NotarySourceRunLocator> {
|
|
167
178
|
const real = await requireRunDirectory(path, path);
|
|
168
179
|
const identity = parseRunDirectoryName(basename(real))!;
|
|
169
|
-
const runState = await
|
|
180
|
+
const runState = await readRetainedIdentity(real);
|
|
170
181
|
if (runState === undefined) {
|
|
171
182
|
throw new NotarySourceRunError(
|
|
172
183
|
"notary source-run lacks retained run-state identity",
|
package/src/pi/role-turn-host.ts
CHANGED
|
@@ -521,13 +521,11 @@ export async function appendPiSessionCustomEntry(
|
|
|
521
521
|
timestamp,
|
|
522
522
|
})}\n`;
|
|
523
523
|
await appendFile(sessionFile, pointerLine, "utf8");
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
});
|
|
532
|
-
} catch {}
|
|
524
|
+
sitianReport({
|
|
525
|
+
level: "event",
|
|
526
|
+
kind: "dispatch-error",
|
|
527
|
+
sessionParent: sessionFile,
|
|
528
|
+
payload: { customType, data },
|
|
529
|
+
source: "pi-role-turn-host",
|
|
530
|
+
});
|
|
533
531
|
}
|