@akagilnc/pi-workflow-roles 0.1.3572 → 0.1.3621
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 +20239 -10556
- package/dist/analyst-gate-cycles-read.js +387 -0
- package/dist/archivist-record-entry.js +22 -1
- package/dist/audit-escalation.js +6 -0
- package/dist/auditor-soul.js +74 -0
- package/dist/collector-config.js +86 -0
- package/dist/collector-evidence.js +316 -0
- package/dist/collector-github.js +527 -0
- package/dist/collector-ledger.js +853 -0
- package/dist/collector-tool-schemas.js +33 -0
- package/dist/compliance-transport.js +104 -52
- package/dist/diarist-mechanical.js +411 -0
- package/dist/diarist-ticket-resolution.js +177 -0
- package/dist/diarist.js +311 -0
- package/dist/doctor-auditor.js +25 -0
- package/dist/doctor-contracts.js +2 -0
- package/dist/doctor-evidence.js +142 -0
- package/dist/gatekeeper-role.js +104 -81
- package/dist/host-transition-prior-native.js +78 -0
- package/dist/institutional-resolution.js +1 -95
- package/dist/judge-auditor.js +26 -0
- package/dist/ledger-session-read.js +227 -0
- package/dist/merger-git-state.js +78 -0
- package/dist/navigator-attendance.js +15 -7
- package/dist/navigator-public-session.js +170 -0
- package/dist/navigator-session-contracts.js +36 -40
- package/dist/notary-source-run.js +122 -0
- package/dist/package-contracts/auditor-output.js +66 -0
- package/dist/package-contracts/evidence-child-output.js +34 -0
- package/dist/package-contracts/judge-output.js +2 -0
- package/dist/package-contracts/terminating-tools.js +25 -2
- package/dist/package-resources/method-skill.js +254 -0
- package/dist/packaged-role-registry.js +36 -0
- package/dist/pi/durable-principal.js +61 -0
- package/dist/pi/in-process-session.js +25 -6
- package/dist/pi/known-failure.js +52 -0
- package/dist/pi/role-turn-host.js +430 -0
- package/dist/public-cli/auto-resume.js +414 -0
- package/dist/public-cli/cli-errors.js +8 -0
- package/dist/public-cli/cli-io.js +1 -0
- package/dist/public-cli/command-renderer.js +5 -0
- package/dist/public-cli/doctor-run.js +84 -0
- package/dist/public-cli/inspector-run.js +136 -0
- package/dist/public-cli/instruction-seat-run.js +256 -0
- package/dist/public-cli/invocation.js +2225 -0
- package/dist/public-cli/judge-run.js +118 -0
- package/dist/public-cli/load-production-acp-host.js +40 -0
- package/dist/public-cli/main.js +1140 -652
- package/dist/public-cli/notary-run.js +161 -0
- package/dist/public-cli/option-definitions.js +1192 -0
- package/dist/public-cli/post-admission.js +667 -0
- package/dist/public-cli/public-run-credentials.js +49 -0
- package/dist/public-cli/registry.js +4 -1
- package/dist/public-cli/reviewer-dispatch-rejection.js +77 -0
- package/dist/public-cli/run-lifecycle.js +1344 -0
- package/dist/public-cli/seat-ticket-binding.js +113 -0
- package/dist/public-cli/settlement.js +3441 -0
- package/dist/public-cli/terminal.js +135 -0
- package/dist/public-cli/turn-request.js +25 -0
- package/dist/public-role-summons.js +301 -0
- package/dist/receipt-delivery-policy.js +10 -0
- package/dist/reviewer-child-executor.js +80 -8
- package/dist/reviewer-execution-ledger.js +2 -1
- package/dist/run-terminal-artifacts.js +195 -0
- package/dist/run-ticket-number.js +40 -0
- package/dist/session-assistant-usage.js +107 -0
- package/dist/shape-unreadable-failure.js +34 -0
- package/dist/submission-errors.js +3 -0
- package/dist/submission-ledger.js +388 -0
- package/dist/ticket-provenance-contracts.js +115 -0
- package/dist/ticket-provenance.js +340 -0
- package/extensions/role-runtime.ts +7 -0
- package/package.json +1 -1
- package/scripts/build-package.mjs +2 -1
- package/souls/doctor-auditor.md +1 -0
- package/souls/evidence-child.md +1 -0
- package/src/acp-host/production-host.ts +3 -0
- package/src/acp-host/role-envelope.ts +2 -2
- package/src/acp-host/role-turn-host.ts +9 -1
- package/src/analyst-gate-cycles-read.ts +37 -2
- package/src/archivist-record-entry.ts +45 -1
- package/src/audit-escalation.ts +17 -0
- package/src/auditor-role.ts +22 -0
- package/src/auditor-soul.ts +42 -0
- package/src/compliance-transport.ts +177 -66
- package/src/doctor-auditor.ts +10 -14
- package/src/doctor-contracts.ts +1 -0
- package/src/doctor-role.ts +2 -2
- package/src/evidence-child-role.ts +22 -0
- package/src/gatekeeper-pass-envelope.ts +109 -0
- package/src/gatekeeper-role.ts +145 -104
- package/src/host-contracts.ts +9 -1
- package/src/institutional-resolution.ts +8 -163
- package/src/judge-auditor.ts +10 -15
- package/src/judge-role.ts +8 -0
- package/src/navigator-attendance.ts +25 -9
- package/src/navigator-public-session.ts +217 -0
- package/src/navigator-session-contracts.ts +61 -54
- package/src/notary-source-run.ts +3 -1
- package/src/package-contracts/auditor-output.ts +82 -0
- package/src/package-contracts/evidence-child-output.ts +51 -0
- package/src/package-contracts/judge-output.ts +1 -0
- package/src/package-contracts/reviewer-output.ts +2 -2
- package/src/package-contracts/terminating-tools.ts +31 -1
- package/src/packaged-role-registry.ts +43 -0
- package/src/pi/adapter.ts +2 -1
- package/src/pi/in-process-session.ts +38 -12
- package/src/pi/role-turn-host.ts +34 -0
- package/src/public-cli/cli.ts +14 -6
- package/src/public-cli/instruction-seat-run.ts +289 -50
- package/src/public-cli/invocation.ts +66 -25
- package/src/public-cli/option-definitions.ts +61 -0
- package/src/public-cli/post-admission.ts +7 -1
- package/src/public-cli/registry.ts +4 -1
- package/src/public-cli/run-lifecycle.ts +22 -3
- package/src/public-cli/settlement.ts +120 -5
- package/src/public-cli/terminal.ts +2 -0
- package/src/public-role-summons.ts +431 -0
- package/src/receipt-delivery-policy.ts +10 -0
- package/src/reviewer-agent.ts +1 -1
- package/src/reviewer-child-executor.ts +114 -12
- package/src/reviewer-execution-ledger.ts +3 -2
- package/src/role-runtime.ts +158 -17
- package/src/session-assistant-usage.ts +119 -0
- package/src/session-opening-materials.ts +1 -1
- package/src/shape-unreadable-failure.ts +49 -0
- package/src/submission-errors.ts +3 -0
- package/dist/evidence-child-executor.js +0 -829
- package/src/evidence-child-executor.ts +0 -1140
package/src/role-runtime.ts
CHANGED
|
@@ -92,6 +92,16 @@ import {
|
|
|
92
92
|
NAVIGATOR_TOOL_SPEC,
|
|
93
93
|
type NavigatorRuntimeDependencies,
|
|
94
94
|
} from "./navigator-role.ts";
|
|
95
|
+
import {
|
|
96
|
+
AUDITOR_TOOL_SPEC,
|
|
97
|
+
type AuditorRuntimeDependencies,
|
|
98
|
+
} from "./auditor-role.ts";
|
|
99
|
+
import { AUDITOR_ACCEPTED_TEXT } from "./package-contracts/auditor-output.ts";
|
|
100
|
+
import {
|
|
101
|
+
EVIDENCE_CHILD_TOOL_SPEC,
|
|
102
|
+
type EvidenceChildRuntimeDependencies,
|
|
103
|
+
} from "./evidence-child-role.ts";
|
|
104
|
+
import { EVIDENCE_CHILD_ACCEPTED_TEXT } from "./package-contracts/evidence-child-output.ts";
|
|
95
105
|
import { GATEKEEPER_ACCEPTED_TEXT } from "./package-contracts/gatekeeper-output.ts";
|
|
96
106
|
import { NAVIGATOR_ACCEPTED_TEXT } from "./package-contracts/navigator-output.ts";
|
|
97
107
|
import { decorateSettlementWithNavigation, formatNavigatorReport, NAVIGATOR_EVENT_TYPE, navigatorSubjectKey, navigatorUnavailableError, subjectPath, type NavigatorAttendance, type NavigatorAttendanceOptions, type NavigatorEvent, type NavigatorPhase, type NavigatorReport, type NavigatorSettlement, type NavigatorSubjectProvenance, type NavigatorTargetRole, type NavigatorWorkContext } from "./navigator-attendance.ts";
|
|
@@ -349,14 +359,11 @@ export {
|
|
|
349
359
|
writeToolExecutionObservationRecord,
|
|
350
360
|
} from "./tool-execution-observation.ts";
|
|
351
361
|
export type { ToolExecutionObservationRecord, ToolExecutionObservationWriter } from "./tool-execution-observation.ts";
|
|
352
|
-
export { executeAuditorChild } from "./evidence-child-executor.ts";
|
|
353
|
-
export type { AuditorDecisionTool } from "./evidence-child-executor.ts";
|
|
354
362
|
export {
|
|
355
363
|
NOTARY_OUTPUT_TOOL,
|
|
356
364
|
INSPECTOR_OUTPUT_TOOL,
|
|
357
365
|
GatekeeperDecisionError,
|
|
358
366
|
createGatekeeperOutputTool,
|
|
359
|
-
createOfficerDecisionTool,
|
|
360
367
|
runGatekeeper,
|
|
361
368
|
} from "./gatekeeper-role.ts";
|
|
362
369
|
export type { GatekeeperResult, GatekeeperSubject, GatekeeperNonPassResult, RunGatekeeperOptions } from "./gatekeeper-role.ts";
|
|
@@ -397,7 +404,13 @@ export { fixerPrerequisiteSchema, fixerPrerequisitesSchema, parseFixerPrerequisi
|
|
|
397
404
|
export type { FixerInvocationInput, FixerPrerequisite } from "./package-contracts/fixer-packet.ts";
|
|
398
405
|
export { AUDIT_ESCALATION_KIND, buildAuditEscalationResult, disposeComplianceDecision, isAuditEscalationResult, projectAuditEscalation } from "./audit-escalation.ts";
|
|
399
406
|
export type { AuditEscalationResult, AuditEscalationToolResult, ComplianceDecisionHandlers } from "./audit-escalation.ts";
|
|
400
|
-
export {
|
|
407
|
+
export {
|
|
408
|
+
AUDITOR_SOUL_ROLES,
|
|
409
|
+
AK_ROLE_AUDITOR_SUBJECT_ENV,
|
|
410
|
+
loadAuditorSoul,
|
|
411
|
+
loadAuditorSoulFromSubjectInput,
|
|
412
|
+
resolveAuditorSubject,
|
|
413
|
+
} from "./auditor-soul.ts";
|
|
401
414
|
export type { AuditorSoulRole } from "./auditor-soul.ts";
|
|
402
415
|
export { JUDGE_AUDIT_TOOL_NAME, SOUL_AUDIT_TOOL_NAME, createPiJudgeAuditor } from "./judge-auditor.ts";
|
|
403
416
|
export { DOCTOR_AUDIT_TOOL_NAME, createPiDoctorAuditor } from "./doctor-auditor.ts";
|
|
@@ -461,6 +474,8 @@ type ActivationRuntime = {
|
|
|
461
474
|
inspector: { activate(): Promise<void> };
|
|
462
475
|
gatekeeper: { activate(): Promise<void> };
|
|
463
476
|
navigator: { activate(): Promise<void> };
|
|
477
|
+
auditor: { activate(): Promise<void> };
|
|
478
|
+
evidenceChild: { activate(): Promise<void> };
|
|
464
479
|
diarist: { activate(): Promise<void> };
|
|
465
480
|
merger(): Promise<void>;
|
|
466
481
|
};
|
|
@@ -510,6 +525,8 @@ function activationStage(role: PackagedRole, runtime: ActivationRuntime): { id:
|
|
|
510
525
|
case "inspector": return { id: "load-and-install", run: async () => runtime.inspector.activate() };
|
|
511
526
|
case "gatekeeper": return { id: "load-and-install", run: async () => runtime.gatekeeper.activate() };
|
|
512
527
|
case "navigator": return { id: "load-and-install", run: async () => runtime.navigator.activate() };
|
|
528
|
+
case "auditor": return { id: "load-and-install", run: async () => runtime.auditor.activate() };
|
|
529
|
+
case "evidence-child": return { id: "load-and-install", run: async () => runtime.evidenceChild.activate() };
|
|
513
530
|
case "diarist": return { id: "load-and-install", run: async () => runtime.diarist.activate() };
|
|
514
531
|
case "merger": return { id: "prepare-git-and-install", run: async () => runtime.merger() };
|
|
515
532
|
}
|
|
@@ -618,6 +635,8 @@ export type RoleRuntimeDependencies = {
|
|
|
618
635
|
loadInspectorSoul?(): Promise<string>;
|
|
619
636
|
loadGatekeeperSoul?(): Promise<string>;
|
|
620
637
|
loadNavigatorSoul?(): Promise<string>;
|
|
638
|
+
loadAuditorSoul?(): Promise<string>;
|
|
639
|
+
loadEvidenceChildSoul?(): Promise<string>;
|
|
621
640
|
loadDiaristSoul?(): Promise<string>;
|
|
622
641
|
loadDoctorCase?(path: string): Promise<import("./doctor-contracts.ts").DoctorCase>;
|
|
623
642
|
loadMergerSoul?(): Promise<string>;
|
|
@@ -879,6 +898,41 @@ export function createNavigatorRoleRuntime(
|
|
|
879
898
|
);
|
|
880
899
|
}
|
|
881
900
|
|
|
901
|
+
/** #675: public 审刑院 seat on the shared filed-officer envelope. */
|
|
902
|
+
export function createAuditorRoleRuntime(
|
|
903
|
+
roleHost: RoleHost,
|
|
904
|
+
dependencies: AuditorRuntimeDependencies,
|
|
905
|
+
) {
|
|
906
|
+
const base = createFiledOfficerRuntime(
|
|
907
|
+
roleHost,
|
|
908
|
+
{
|
|
909
|
+
role: "auditor",
|
|
910
|
+
tool: AUDITOR_TOOL_SPEC,
|
|
911
|
+
acceptedText: AUDITOR_ACCEPTED_TEXT,
|
|
912
|
+
soulTag: "auditor",
|
|
913
|
+
},
|
|
914
|
+
dependencies,
|
|
915
|
+
);
|
|
916
|
+
return {
|
|
917
|
+
async activate() {
|
|
918
|
+
await base.activate();
|
|
919
|
+
// Same tools whether nested or direct (#675): dossier tool always registered.
|
|
920
|
+
// Source run: only the shared --source-run input face (never own-run fallback).
|
|
921
|
+
const { createAuditorDossierTool, AUDITOR_DOSSIER_TOOL_NAME } =
|
|
922
|
+
await import("./auditor-dossier-tool.ts");
|
|
923
|
+
const { AK_ROLE_AUDITOR_SOURCE_RUN_ENV } = await import("./auditor-soul.ts");
|
|
924
|
+
const already = roleHost.getAllTools().some((tool) => tool.name === AUDITOR_DOSSIER_TOOL_NAME);
|
|
925
|
+
if (already) return;
|
|
926
|
+
const sourceRun =
|
|
927
|
+
typeof process.env[AK_ROLE_AUDITOR_SOURCE_RUN_ENV] === "string"
|
|
928
|
+
&& process.env[AK_ROLE_AUDITOR_SOURCE_RUN_ENV].trim() !== ""
|
|
929
|
+
? process.env[AK_ROLE_AUDITOR_SOURCE_RUN_ENV].trim()
|
|
930
|
+
: undefined;
|
|
931
|
+
roleHost.registerTool(createAuditorDossierTool(sourceRun) as never);
|
|
932
|
+
},
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
|
|
882
936
|
/**
|
|
883
937
|
* #708: 起居郎 public seat on the shared filed-officer envelope.
|
|
884
938
|
* Semantic collection happened in this role's own turn; the accept hook runs the
|
|
@@ -946,6 +1000,23 @@ function loadFrozenDiaristCatalog(
|
|
|
946
1000
|
return loadDiaristSourceCatalog(raw);
|
|
947
1001
|
}
|
|
948
1002
|
|
|
1003
|
+
/** #675: public evidence-child seat on the shared filed-officer envelope. */
|
|
1004
|
+
export function createEvidenceChildRoleRuntime(
|
|
1005
|
+
roleHost: RoleHost,
|
|
1006
|
+
dependencies: EvidenceChildRuntimeDependencies,
|
|
1007
|
+
) {
|
|
1008
|
+
return createFiledOfficerRuntime(
|
|
1009
|
+
roleHost,
|
|
1010
|
+
{
|
|
1011
|
+
role: "evidence-child",
|
|
1012
|
+
tool: EVIDENCE_CHILD_TOOL_SPEC,
|
|
1013
|
+
acceptedText: EVIDENCE_CHILD_ACCEPTED_TEXT,
|
|
1014
|
+
soulTag: "evidence-child",
|
|
1015
|
+
},
|
|
1016
|
+
dependencies,
|
|
1017
|
+
);
|
|
1018
|
+
}
|
|
1019
|
+
|
|
949
1020
|
export function createCountersignRoleRuntime(
|
|
950
1021
|
roleHost: RoleHost,
|
|
951
1022
|
dependencies: CountersignRuntimeDependencies,
|
|
@@ -1027,6 +1098,9 @@ export function createRoleRuntimeExtension(
|
|
|
1027
1098
|
// terminating-tool rejections and mechanical delivery requests share two turns.
|
|
1028
1099
|
let receiptDelivery = createReceiptDeliveryPolicy();
|
|
1029
1100
|
let noReceiptRecorded = false;
|
|
1101
|
+
// Public-run fetch observation (in-process-session statusAwareFetch face).
|
|
1102
|
+
let priorFetch: typeof globalThis.fetch | undefined;
|
|
1103
|
+
let fetchWrapped = false;
|
|
1030
1104
|
const settleNavigatorProjection = async (settlement: NavigatorSettlement | undefined) => {
|
|
1031
1105
|
const attendance = navigatorAttendance;
|
|
1032
1106
|
if (settlement === undefined || attendance === undefined) return;
|
|
@@ -1037,6 +1111,9 @@ export function createRoleRuntimeExtension(
|
|
|
1037
1111
|
return;
|
|
1038
1112
|
}
|
|
1039
1113
|
const settlePromise = attendance.settle(settlement);
|
|
1114
|
+
// Attach catch immediately so a late rejection after grace timeout cannot
|
|
1115
|
+
// surface as unhandledRejection / stale-ctx after session dispose (#675).
|
|
1116
|
+
void settlePromise.catch(() => undefined);
|
|
1040
1117
|
const raced = await raceNavigatorGrace(settlePromise, NAVIGATOR_POST_ROLE_GRACE_MS);
|
|
1041
1118
|
if (raced.status !== "timeout") return;
|
|
1042
1119
|
if (pendingNavigatorPresentation === undefined) {
|
|
@@ -1063,7 +1140,6 @@ export function createRoleRuntimeExtension(
|
|
|
1063
1140
|
pendingNavigatorPresentation = { event, report };
|
|
1064
1141
|
}
|
|
1065
1142
|
await attendance.dispose();
|
|
1066
|
-
void settlePromise.catch(() => undefined);
|
|
1067
1143
|
})();
|
|
1068
1144
|
pendingNavigatorSettlement = pending;
|
|
1069
1145
|
await pending;
|
|
@@ -1290,6 +1366,11 @@ export function createRoleRuntimeExtension(
|
|
|
1290
1366
|
roleHost.on("session_shutdown", async () => {
|
|
1291
1367
|
// #351: stop OAuth keepalive first so shutdown yields zero further ticks.
|
|
1292
1368
|
envelopeHost.stopKeepalive();
|
|
1369
|
+
if (fetchWrapped && priorFetch !== undefined) {
|
|
1370
|
+
globalThis.fetch = priorFetch;
|
|
1371
|
+
priorFetch = undefined;
|
|
1372
|
+
fetchWrapped = false;
|
|
1373
|
+
}
|
|
1293
1374
|
// Flush any still-pending affirmative attendance before teardown. Accepted
|
|
1294
1375
|
// grace-timeout paths normally emit on agent_settled; abort can skip that hook.
|
|
1295
1376
|
const presentation = pendingNavigatorPresentation;
|
|
@@ -1458,6 +1539,18 @@ export function createRoleRuntimeExtension(
|
|
|
1458
1539
|
return dependencies.loadNavigatorSoul();
|
|
1459
1540
|
},
|
|
1460
1541
|
});
|
|
1542
|
+
const auditor = createAuditorRoleRuntime(roleHost, {
|
|
1543
|
+
async loadSoul() {
|
|
1544
|
+
if (!dependencies.loadAuditorSoul) throw new Error("Auditor runtime dependencies are not configured");
|
|
1545
|
+
return dependencies.loadAuditorSoul();
|
|
1546
|
+
},
|
|
1547
|
+
});
|
|
1548
|
+
const evidenceChild = createEvidenceChildRoleRuntime(roleHost, {
|
|
1549
|
+
async loadSoul() {
|
|
1550
|
+
if (!dependencies.loadEvidenceChildSoul) throw new Error("Evidence-child runtime dependencies are not configured");
|
|
1551
|
+
return dependencies.loadEvidenceChildSoul();
|
|
1552
|
+
},
|
|
1553
|
+
});
|
|
1461
1554
|
const diarist = createDiaristRoleRuntime(
|
|
1462
1555
|
roleHost,
|
|
1463
1556
|
{
|
|
@@ -1553,20 +1646,19 @@ export function createRoleRuntimeExtension(
|
|
|
1553
1646
|
});
|
|
1554
1647
|
|
|
1555
1648
|
// Public Role run: record typed non-success HTTP for error evidence + v1 resume.
|
|
1556
|
-
//
|
|
1557
|
-
//
|
|
1558
|
-
|
|
1649
|
+
// Same observation owner as in-process-session statusAwareFetch → typed-provider-http
|
|
1650
|
+
// sidecar (settlement already merges observation.httpStatus into knownFailure).
|
|
1651
|
+
// after_provider_response covers the success-path onResponse face; fetch wrap covers
|
|
1652
|
+
// non-2xx Responses where openai-completions throws before onResponse (#675).
|
|
1653
|
+
const recordHttpObservation = async (
|
|
1654
|
+
status: number,
|
|
1655
|
+
provider: string,
|
|
1656
|
+
ctx: HostContext,
|
|
1657
|
+
): Promise<void> => {
|
|
1559
1658
|
const runDir = process.env.AK_ROLE_RUN_DIR;
|
|
1560
1659
|
if (typeof runDir !== "string" || runDir.trim() === "") return;
|
|
1561
|
-
const provider = ctx.model?.provider;
|
|
1562
|
-
if (typeof provider !== "string" || provider.trim() === "") return;
|
|
1563
|
-
const status = event.status;
|
|
1564
|
-
if (typeof status !== "number") return;
|
|
1565
1660
|
try {
|
|
1566
|
-
await recordTypedProviderHttpStatus(runDir, {
|
|
1567
|
-
httpStatus: status,
|
|
1568
|
-
provider,
|
|
1569
|
-
});
|
|
1661
|
+
await recordTypedProviderHttpStatus(runDir, { httpStatus: status, provider });
|
|
1570
1662
|
} catch (error) {
|
|
1571
1663
|
if (
|
|
1572
1664
|
status >= 200 &&
|
|
@@ -1579,9 +1671,49 @@ export function createRoleRuntimeExtension(
|
|
|
1579
1671
|
}
|
|
1580
1672
|
failInfrastructure(error, ctx);
|
|
1581
1673
|
}
|
|
1674
|
+
};
|
|
1675
|
+
roleHost.on("after_provider_response", async (event, ctx) => {
|
|
1676
|
+
const status = event.status;
|
|
1677
|
+
if (typeof status !== "number") return;
|
|
1678
|
+
const fromCtx = ctx.model?.provider;
|
|
1679
|
+
const provider =
|
|
1680
|
+
typeof fromCtx === "string" && fromCtx.trim() !== ""
|
|
1681
|
+
? fromCtx
|
|
1682
|
+
: "unknown";
|
|
1683
|
+
await recordHttpObservation(status, provider, ctx);
|
|
1582
1684
|
});
|
|
1583
1685
|
|
|
1584
1686
|
roleHost.on("session_start", async (event, ctx) => {
|
|
1687
|
+
// Scope fetch observation to this public run (in-process-session statusAwareFetch face).
|
|
1688
|
+
if (!fetchWrapped && typeof globalThis.fetch === "function") {
|
|
1689
|
+
priorFetch = globalThis.fetch.bind(globalThis);
|
|
1690
|
+
const underlying = priorFetch;
|
|
1691
|
+
globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => {
|
|
1692
|
+
const response = await underlying(input, init);
|
|
1693
|
+
const runDir = process.env.AK_ROLE_RUN_DIR;
|
|
1694
|
+
if (
|
|
1695
|
+
typeof runDir === "string"
|
|
1696
|
+
&& runDir.trim() !== ""
|
|
1697
|
+
&& typeof response?.status === "number"
|
|
1698
|
+
&& (response.status < 200 || response.status >= 300)
|
|
1699
|
+
) {
|
|
1700
|
+
const provider =
|
|
1701
|
+
typeof ctx.model?.provider === "string" && ctx.model.provider.trim() !== ""
|
|
1702
|
+
? ctx.model.provider
|
|
1703
|
+
: "unknown";
|
|
1704
|
+
try {
|
|
1705
|
+
await recordTypedProviderHttpStatus(runDir, {
|
|
1706
|
+
httpStatus: response.status,
|
|
1707
|
+
provider,
|
|
1708
|
+
});
|
|
1709
|
+
} catch {
|
|
1710
|
+
// Observation must not break the provider stream (same as in-process-session).
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
return response;
|
|
1714
|
+
}) as typeof globalThis.fetch;
|
|
1715
|
+
fetchWrapped = true;
|
|
1716
|
+
}
|
|
1585
1717
|
admitted = false;
|
|
1586
1718
|
selectedRole = undefined;
|
|
1587
1719
|
activeReviewerParent = undefined;
|
|
@@ -1634,6 +1766,8 @@ export function createRoleRuntimeExtension(
|
|
|
1634
1766
|
inspector,
|
|
1635
1767
|
gatekeeper,
|
|
1636
1768
|
navigator,
|
|
1769
|
+
auditor,
|
|
1770
|
+
evidenceChild,
|
|
1637
1771
|
diarist,
|
|
1638
1772
|
merger: async () => {
|
|
1639
1773
|
if (dependencies.mergerGitState === undefined) {
|
|
@@ -1653,7 +1787,14 @@ export function createRoleRuntimeExtension(
|
|
|
1653
1787
|
const ledgerHome = resolveActivationLedgerHomeForPath(sessionFile);
|
|
1654
1788
|
const session = durableSessionPointer(ctx.sessionManager);
|
|
1655
1789
|
|
|
1656
|
-
|
|
1790
|
+
// Same public activation face for every role (#675 / owner 09-06): no nested-env
|
|
1791
|
+
// skip, no work-role whitelist. Attendance attaches when the envelope supplies it.
|
|
1792
|
+
// Navigator seat never re-attaches itself — prepare turns already ARE the navigator
|
|
1793
|
+
// public activation (prevents summonPublicRole navigator ↔ attendance recursion).
|
|
1794
|
+
if (
|
|
1795
|
+
dependencies.createNavigatorAttendance !== undefined
|
|
1796
|
+
&& entry.role !== "navigator"
|
|
1797
|
+
) {
|
|
1657
1798
|
let work: NavigatorWorkContext;
|
|
1658
1799
|
let contextError: unknown;
|
|
1659
1800
|
if (dependencies.loadNavigatorWorkContext === undefined) {
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sum assistant-message usage rows from a session.jsonl (nested public summons).
|
|
3
|
+
* Accumulates real cost when rows carry it; never invents cost zeros (#675).
|
|
4
|
+
*/
|
|
5
|
+
import type { Usage } from "@earendil-works/pi-ai";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
|
|
8
|
+
import type { PublicSummonResult } from "./public-role-summons.ts";
|
|
9
|
+
|
|
10
|
+
export async function readAssistantUsageFromSessionFile(
|
|
11
|
+
sessionFile: string,
|
|
12
|
+
): Promise<Usage | undefined> {
|
|
13
|
+
const { readFile } = await import("node:fs/promises");
|
|
14
|
+
let text: string;
|
|
15
|
+
try {
|
|
16
|
+
text = await readFile(sessionFile, "utf8");
|
|
17
|
+
} catch (error) {
|
|
18
|
+
if ((error as NodeJS.ErrnoException)?.code === "ENOENT") return undefined;
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
let rows: Array<{ type?: string; message?: { role?: string; usage?: Usage } }>;
|
|
22
|
+
try {
|
|
23
|
+
rows = text
|
|
24
|
+
.trim()
|
|
25
|
+
.split("\n")
|
|
26
|
+
.filter(Boolean)
|
|
27
|
+
.map((line) => JSON.parse(line) as {
|
|
28
|
+
type?: string;
|
|
29
|
+
message?: { role?: string; usage?: Usage };
|
|
30
|
+
});
|
|
31
|
+
} catch (error) {
|
|
32
|
+
throw new Error(
|
|
33
|
+
`session usage parse failed (${sessionFile}): ${error instanceof Error ? error.message : String(error)}`,
|
|
34
|
+
{ cause: error },
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
let total = 0;
|
|
38
|
+
let input = 0;
|
|
39
|
+
let output = 0;
|
|
40
|
+
let cacheRead = 0;
|
|
41
|
+
let cacheWrite = 0;
|
|
42
|
+
let costInput = 0;
|
|
43
|
+
let costOutput = 0;
|
|
44
|
+
let costCacheRead = 0;
|
|
45
|
+
let costCacheWrite = 0;
|
|
46
|
+
let costTotal = 0;
|
|
47
|
+
let sawCost = false;
|
|
48
|
+
for (const row of rows) {
|
|
49
|
+
if (row.type !== "message" || row.message?.role !== "assistant") continue;
|
|
50
|
+
const usage = row.message.usage;
|
|
51
|
+
if (usage === undefined) continue;
|
|
52
|
+
total += usage.totalTokens ?? 0;
|
|
53
|
+
input += usage.input ?? 0;
|
|
54
|
+
output += usage.output ?? 0;
|
|
55
|
+
cacheRead += usage.cacheRead ?? 0;
|
|
56
|
+
cacheWrite += usage.cacheWrite ?? 0;
|
|
57
|
+
if (usage.cost !== undefined) {
|
|
58
|
+
sawCost = true;
|
|
59
|
+
costInput += usage.cost.input ?? 0;
|
|
60
|
+
costOutput += usage.cost.output ?? 0;
|
|
61
|
+
costCacheRead += usage.cost.cacheRead ?? 0;
|
|
62
|
+
costCacheWrite += usage.cost.cacheWrite ?? 0;
|
|
63
|
+
costTotal += usage.cost.total ?? 0;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (total <= 0 && input <= 0 && output <= 0) return undefined;
|
|
67
|
+
const base = {
|
|
68
|
+
input,
|
|
69
|
+
output,
|
|
70
|
+
cacheRead,
|
|
71
|
+
cacheWrite,
|
|
72
|
+
totalTokens: total > 0 ? total : input + output + cacheRead + cacheWrite,
|
|
73
|
+
};
|
|
74
|
+
// Cost only when session rows carried it — unknown stays absent (not zero).
|
|
75
|
+
if (!sawCost) return base as Usage;
|
|
76
|
+
return {
|
|
77
|
+
...base,
|
|
78
|
+
cost: {
|
|
79
|
+
input: costInput,
|
|
80
|
+
output: costOutput,
|
|
81
|
+
cacheRead: costCacheRead,
|
|
82
|
+
cacheWrite: costCacheWrite,
|
|
83
|
+
total: costTotal,
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Resolve the independent role run's session.jsonl from a public summon result.
|
|
90
|
+
* Prefers explicit runDirectory, then terminal artifacts, then no_receipt runPointer.
|
|
91
|
+
*/
|
|
92
|
+
export function sessionFileFromPublicSummon(
|
|
93
|
+
summoned: PublicSummonResult,
|
|
94
|
+
): string | undefined {
|
|
95
|
+
if (typeof summoned.runDirectory === "string" && summoned.runDirectory.trim() !== "") {
|
|
96
|
+
return join(summoned.runDirectory, "session", "session.jsonl");
|
|
97
|
+
}
|
|
98
|
+
const fromArtifacts = summoned.terminal?.artifacts
|
|
99
|
+
?.map((a) => (a as { path?: string }).path)
|
|
100
|
+
.find((p): p is string => typeof p === "string" && p.endsWith("session.jsonl"));
|
|
101
|
+
if (fromArtifacts !== undefined) return fromArtifacts;
|
|
102
|
+
const outcome = summoned.terminal?.roleOutcome;
|
|
103
|
+
if (outcome === undefined) return undefined;
|
|
104
|
+
const facts = (outcome as { decisiveFacts?: Record<string, unknown> }).decisiveFacts;
|
|
105
|
+
const pointer = facts?.runPointer;
|
|
106
|
+
if (typeof pointer === "string" && pointer.trim() !== "") {
|
|
107
|
+
return join(pointer, "session", "session.jsonl");
|
|
108
|
+
}
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Shared usage projection for nested public summons — undefined when unknown. */
|
|
113
|
+
export async function usageFromPublicSummon(
|
|
114
|
+
summoned: PublicSummonResult,
|
|
115
|
+
): Promise<Usage | undefined> {
|
|
116
|
+
const sessionFile = sessionFileFromPublicSummon(summoned);
|
|
117
|
+
if (sessionFile === undefined) return undefined;
|
|
118
|
+
return readAssistantUsageFromSessionFile(sessionFile);
|
|
119
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* errors. Main-role materials derive from PUBLIC_ROLE_RECORDS (including
|
|
4
4
|
* gatekeeper and navigator). Province map reuses that public gatekeeper record
|
|
5
5
|
* plus officer material constants (notary shared). Auditor composition stays in
|
|
6
|
-
* loadAuditorSoul; loaders share joinPackageMaterials.
|
|
6
|
+
* loadAuditorSoul(subject); loaders share joinPackageMaterials.
|
|
7
7
|
*/
|
|
8
8
|
import { existsSync } from "node:fs";
|
|
9
9
|
import { readFile } from "node:fs/promises";
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single authoritative shape-unreadable marker (#675 / ADR 0055).
|
|
3
|
+
* Settlement stamps it; consumers only read it — never re-derive from cause=output.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const SHAPE_UNREADABLE_KEY = "shapeUnreadable" as const;
|
|
7
|
+
|
|
8
|
+
export type ShapeUnreadableStamp = {
|
|
9
|
+
readonly [SHAPE_UNREADABLE_KEY]: true;
|
|
10
|
+
readonly candidate: unknown;
|
|
11
|
+
readonly acceptedReceipt: false;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
15
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Settlement seat path: stamp retained candidate as shape-unreadable (not infrastructure). */
|
|
19
|
+
export function stampShapeUnreadableDetails(candidate: unknown): ShapeUnreadableStamp {
|
|
20
|
+
return {
|
|
21
|
+
[SHAPE_UNREADABLE_KEY]: true,
|
|
22
|
+
candidate,
|
|
23
|
+
acceptedReceipt: false,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Marker presence, decided independently of the candidate value: a stamped
|
|
29
|
+
* `undefined` candidate is a shape-unreadable decision, not an absent marker.
|
|
30
|
+
*/
|
|
31
|
+
export type RetainedShapeUnreadable = { readonly candidate: unknown };
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Read the settlement-stamped shape candidate from a failure decisiveFacts payload.
|
|
35
|
+
* Looks at root and secondaryEvidence only for the typed marker — no cause inference.
|
|
36
|
+
*/
|
|
37
|
+
export function retainedShapeUnreadable(decisiveFacts: unknown): RetainedShapeUnreadable | undefined {
|
|
38
|
+
if (!isRecord(decisiveFacts)) return undefined;
|
|
39
|
+
if (decisiveFacts[SHAPE_UNREADABLE_KEY] === true) {
|
|
40
|
+
return { candidate: decisiveFacts.candidate };
|
|
41
|
+
}
|
|
42
|
+
const secondary = isRecord(decisiveFacts.secondaryEvidence)
|
|
43
|
+
? decisiveFacts.secondaryEvidence
|
|
44
|
+
: undefined;
|
|
45
|
+
if (secondary !== undefined && secondary[SHAPE_UNREADABLE_KEY] === true) {
|
|
46
|
+
return { candidate: secondary.candidate };
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
package/src/submission-errors.ts
CHANGED
|
@@ -5,6 +5,9 @@ function gatekeeperNonPassMessage(result: GatekeeperNonPassResult): string {
|
|
|
5
5
|
const findings = result.findings.length === 0 ? "(无 findings)" : result.findings.join("; ");
|
|
6
6
|
return `门下省打回重写,findings:${findings}`;
|
|
7
7
|
}
|
|
8
|
+
if (result.status === "unreadable") {
|
|
9
|
+
return `门下省官回执形状不可读(${result.officer}):${result.reason}`;
|
|
10
|
+
}
|
|
8
11
|
return `门下省 ${result.status}(${result.stage}):${result.reason}`;
|
|
9
12
|
}
|
|
10
13
|
|