@akagilnc/pi-workflow-roles 0.1.5068 → 0.1.5096
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 +429 -383
- package/dist/atomic-write.js +13 -19
- package/dist/auditor-soul.js +2 -1
- package/dist/compliance-transport.js +3 -2
- package/dist/countersign-contracts.js +2 -2
- package/dist/doctor-contracts.js +1 -1
- package/dist/gatekeeper-role.js +14 -35
- package/dist/headless-host/production-host.js +461 -415
- package/dist/inspector-contracts.js +5 -2
- package/dist/merger-contracts.js +1 -1
- package/dist/migrate-book-topology.js +49 -33
- package/dist/navigator-attendance.js +28 -143
- package/dist/navigator-invocation-identity.js +2 -0
- package/dist/navigator-public-session.js +13 -1
- package/dist/navigator-work-base.js +113 -0
- package/dist/notary-contracts.js +0 -2
- package/dist/open-tool-schema.js +4 -1
- package/dist/package-contracts/fixer-output.js +1 -1
- package/dist/package-contracts/gatekeeper-output.js +1 -1
- package/dist/package-contracts/judge-output.js +2 -2
- package/dist/package-contracts/navigator-output.js +1 -1
- package/dist/package-contracts/terminating-infrastructure.js +7 -4
- package/dist/packaged-role-registry.js +9 -5
- package/dist/public-cli/countersign-run.js +1 -1
- package/dist/public-cli/invocation.js +6 -3
- package/dist/public-cli/main.js +78 -41
- package/dist/public-cli/settlement.js +20 -1
- package/dist/receipt-delivery-policy.js +9 -2
- package/dist/review-submission.js +19 -8
- package/dist/submission-errors.js +17 -0
- package/dist/submission-ledger.js +18 -6
- package/docs/adr/0057-schema-narrowing-cuts-the-required-set-not-the-declared-set.md +9 -0
- package/extensions/role-runtime.ts +0 -27
- package/package.json +2 -1
- package/resources/836-deleted-machine-instruction-inventory.md +3 -3
- package/resources/collector-bot-handbook.md +4 -0
- package/resources/navigator-route-playbook.md +4 -6
- package/scripts/build-package.mjs +4 -0
- package/souls/coder-output-guide.md +1 -0
- package/src/auditor-soul.ts +2 -1
- package/src/collector-role.ts +6 -7
- package/src/collector-tool-schemas.ts +5 -5
- package/src/compliance-transport.ts +3 -2
- package/src/countersign-contracts.ts +2 -2
- package/src/countersign-role.ts +3 -7
- package/src/diarist-role.ts +2 -2
- package/src/doctor-contracts.ts +1 -1
- package/src/gatekeeper-role.ts +15 -36
- package/src/gleaner-left-role.ts +2 -2
- package/src/inspector-contracts.ts +5 -2
- package/src/inspector-role.ts +1 -1
- package/src/judge-role.ts +14 -22
- package/src/merger-contracts.ts +1 -1
- package/src/navigator-attendance.ts +38 -164
- package/src/navigator-invocation-identity.ts +2 -0
- package/src/navigator-public-session.ts +17 -1
- package/src/navigator-role.ts +4 -0
- package/src/navigator-session-contracts.ts +2 -0
- package/src/navigator-work-base.ts +123 -0
- package/src/notary-contracts.ts +0 -4
- package/src/open-tool-schema.ts +9 -4
- package/src/package-contracts/fixer-output.ts +1 -1
- package/src/package-contracts/gatekeeper-output.ts +3 -3
- package/src/package-contracts/judge-output.ts +2 -4
- package/src/package-contracts/navigator-output.ts +1 -1
- package/src/package-contracts/terminating-infrastructure.ts +12 -10
- package/src/packaged-role-registry.ts +5 -1
- package/src/public-cli/countersign-run.ts +1 -1
- package/src/public-cli/invocation.ts +6 -3
- package/src/public-cli/settlement.ts +21 -0
- package/src/receipt-delivery-policy.ts +9 -1
- package/src/review-submission.ts +24 -10
- package/src/reviewer-role.ts +3 -3
- package/src/role-runtime-dependencies.ts +1 -5
- package/src/role-runtime.ts +61 -63
- package/src/secretariat-role.ts +3 -3
- package/src/submission-errors.ts +16 -0
- package/src/submission-gate.ts +2 -1
- package/src/submission-ledger.ts +23 -11
- package/src/worker-role.ts +7 -9
package/src/role-runtime.ts
CHANGED
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
durableSessionPointer,
|
|
24
24
|
resolveBookKeyFromGit,
|
|
25
25
|
} from "./activation-ledger.ts";
|
|
26
|
+
import { readPackageMaterial } from "./session-opening-materials.ts";
|
|
26
27
|
import { writeStderrJsonlRecord } from "./stderr-jsonl.ts";
|
|
27
28
|
import {
|
|
28
29
|
createToolExecutionObservationFace,
|
|
@@ -38,7 +39,7 @@ import {
|
|
|
38
39
|
} from "./engine-detour.ts";
|
|
39
40
|
import { engineSessionMaterialFromOptions } from "./package-resources/engine-material.ts";
|
|
40
41
|
import { registerEngineDetourTool } from "./engine-detour-tool.ts";
|
|
41
|
-
import { createReceiptDeliveryPolicy, NO_RECEIPT_LIFECYCLE_ENTRY_TYPE
|
|
42
|
+
import { createReceiptDeliveryPolicy, NO_RECEIPT_LIFECYCLE_ENTRY_TYPE } from "./receipt-delivery-policy.ts";
|
|
42
43
|
import type { CollectorClock } from "./collector-evidence.ts";
|
|
43
44
|
import type { CollectorGitHubTransport } from "./collector-github.ts";
|
|
44
45
|
import {
|
|
@@ -98,7 +99,8 @@ import {
|
|
|
98
99
|
type AuditorRuntimeDependencies,
|
|
99
100
|
} from "./auditor-role.ts";
|
|
100
101
|
|
|
101
|
-
import { formatNavigatorReport, NAVIGATOR_EVENT_TYPE, navigatorSubjectKey, navigatorUnavailableError, subjectPath, type NavigatorAttendance, type NavigatorAttendanceOptions, type NavigatorEvent, type NavigatorPhase, type NavigatorReport, type NavigatorSettlement, type NavigatorSubjectProvenance, type
|
|
102
|
+
import { formatNavigatorReport, NAVIGATOR_EVENT_TYPE, NAVIGATOR_ROUTE_PLAYBOOK_FAILURE_ENTRY, navigatorSubjectKey, navigatorUnavailableError, subjectPath, type NavigatorAttendance, type NavigatorAttendanceOptions, type NavigatorEvent, type NavigatorPhase, type NavigatorReport, type NavigatorSettlement, type NavigatorSubjectProvenance, type NavigatorWorkContext } from "./navigator-attendance.ts";
|
|
103
|
+
import { loadNavigatorWorkBaseSuffix } from "./navigator-work-base.ts";
|
|
102
104
|
import {
|
|
103
105
|
buildNavigatorInfrastructureFailureFact,
|
|
104
106
|
classifyPackagedRoleTerminalResult,
|
|
@@ -108,7 +110,7 @@ import {
|
|
|
108
110
|
} from "./navigator-invocation-identity.ts";
|
|
109
111
|
import { recordTypedProviderHttpStatus } from "./typed-provider-http.ts";
|
|
110
112
|
import { NAVIGATOR_POST_ROLE_GRACE_MS, raceNavigatorGrace } from "./public-cli/settlement.ts";
|
|
111
|
-
import { PACKAGED_ROLE_REGISTRY, isOfficerReviewSeat, packagedRoleActivationFlags,
|
|
113
|
+
import { PACKAGED_ROLE_REGISTRY, isOfficerReviewSeat, packagedRoleActivationFlags, packagedRoleMetadata, packagedRoleOutputTool, packagedRolePhaseFlag, type PackagedRole } from "./packaged-role-registry.ts";
|
|
112
114
|
import { isAuditEscalationProjection } from "./audit-escalation.ts";
|
|
113
115
|
import {
|
|
114
116
|
createJudgeRoleRuntime,
|
|
@@ -301,7 +303,6 @@ import {
|
|
|
301
303
|
NOTARY_OUTPUT_TOOL,
|
|
302
304
|
INSPECTOR_OUTPUT_TOOL,
|
|
303
305
|
GatekeeperDecisionError,
|
|
304
|
-
createGatekeeperOutputTool,
|
|
305
306
|
runGatekeeper,
|
|
306
307
|
gateOfficerForSubject,
|
|
307
308
|
} from "./gatekeeper-role.ts";
|
|
@@ -309,12 +310,12 @@ export {
|
|
|
309
310
|
NOTARY_OUTPUT_TOOL,
|
|
310
311
|
INSPECTOR_OUTPUT_TOOL,
|
|
311
312
|
GatekeeperDecisionError,
|
|
312
|
-
createGatekeeperOutputTool,
|
|
313
313
|
runGatekeeper,
|
|
314
314
|
gateOfficerForSubject,
|
|
315
315
|
};
|
|
316
316
|
export type { GatekeeperResult, GatekeeperSubject, SubmissionGateNonPassResult, GateOfficer, RunGatekeeperOptions } from "./gatekeeper-role.ts";
|
|
317
|
-
import { ParentQueueReaskError } from "./submission-errors.ts";
|
|
317
|
+
import { ParentQueueReaskError, unreadableDiscriminatorNotice } from "./submission-errors.ts";
|
|
318
|
+
import { REVIEW_QUEUE_STATUSES } from "./review-submission.ts";
|
|
318
319
|
|
|
319
320
|
export {
|
|
320
321
|
DOCTOR_EVIDENCE_TOOL_NAME,
|
|
@@ -451,29 +452,7 @@ export const ROLE_FLAG = {
|
|
|
451
452
|
},
|
|
452
453
|
} as const;
|
|
453
454
|
|
|
454
|
-
|
|
455
|
-
export function formatNavigatorRoleHelp(role: NavigatorTargetRole): string {
|
|
456
|
-
const metadata = packagedRoleMetadata(role);
|
|
457
|
-
const lines = [
|
|
458
|
-
`Usage: ak-role ${role}`,
|
|
459
|
-
ROLE_FLAG.definition.description,
|
|
460
|
-
];
|
|
461
|
-
const inputFlag = packagedRoleInputFlag(role);
|
|
462
|
-
if (inputFlag !== undefined) {
|
|
463
|
-
lines.push(` --${inputFlag} <value> ${role} input material`);
|
|
464
|
-
}
|
|
465
|
-
const phaseFlag = packagedRolePhaseFlag(role);
|
|
466
|
-
if (phaseFlag !== undefined && metadata !== undefined) {
|
|
467
|
-
lines.push(
|
|
468
|
-
` --${phaseFlag} <value> ${role} phase: ${(metadata.phases.filter((p) => p !== null) as string[]).join(" | ")}`,
|
|
469
|
-
);
|
|
470
|
-
}
|
|
471
|
-
lines.push(`Public next-command form: ak-role ${role}`);
|
|
472
|
-
return lines.join("\n");
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
type NavigatorAttendanceDependency = Omit<NavigatorAttendance, "knownRoutePlaybookReadFailure"> &
|
|
476
|
-
Partial<Pick<NavigatorAttendance, "knownRoutePlaybookReadFailure">>;
|
|
455
|
+
type NavigatorAttendanceDependency = NavigatorAttendance;
|
|
477
456
|
|
|
478
457
|
export type RoleRuntimeDependencies = {
|
|
479
458
|
/** Package root for packaged engine-note resolution (#879). */
|
|
@@ -753,7 +732,7 @@ export function createNavigatorRoleRuntime(
|
|
|
753
732
|
roleHost: RoleHost,
|
|
754
733
|
dependencies: NavigatorRuntimeDependencies,
|
|
755
734
|
) {
|
|
756
|
-
|
|
735
|
+
const base = createFiledOfficerRuntime(
|
|
757
736
|
roleHost,
|
|
758
737
|
{
|
|
759
738
|
role: "navigator",
|
|
@@ -762,6 +741,43 @@ export function createNavigatorRoleRuntime(
|
|
|
762
741
|
},
|
|
763
742
|
dependencies,
|
|
764
743
|
);
|
|
744
|
+
let playbookBound = false;
|
|
745
|
+
return {
|
|
746
|
+
async activate() {
|
|
747
|
+
await base.activate();
|
|
748
|
+
if (playbookBound) return;
|
|
749
|
+
playbookBound = true;
|
|
750
|
+
// Standing system prompt, not a per-turn user message. Native read failure
|
|
751
|
+
// is the explanation (ADR 0061); no code-written sentence.
|
|
752
|
+
const loadRoutePlaybook = dependencies.loadRoutePlaybook
|
|
753
|
+
?? (() => readPackageMaterial("resources/navigator-route-playbook.md"));
|
|
754
|
+
let playbookRead: Promise<string> | undefined;
|
|
755
|
+
roleHost.on("before_agent_start", async (event) => {
|
|
756
|
+
const basePrompt = typeof event.systemPrompt === "string" ? event.systemPrompt : "";
|
|
757
|
+
const parts: string[] = [];
|
|
758
|
+
try {
|
|
759
|
+
playbookRead ??= loadRoutePlaybook();
|
|
760
|
+
const content = await playbookRead;
|
|
761
|
+
dependencies.recordRoutePlaybookReadFailure?.(undefined);
|
|
762
|
+
if (content.trim() !== "") parts.push(content);
|
|
763
|
+
} catch (error) {
|
|
764
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
765
|
+
if (message.trim() !== "") {
|
|
766
|
+
dependencies.recordRoutePlaybookReadFailure?.(message);
|
|
767
|
+
parts.push(message);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
const prompt = typeof event.prompt === "string" ? event.prompt : "";
|
|
771
|
+
const work = await loadNavigatorWorkBaseSuffix(prompt);
|
|
772
|
+
if (work !== undefined && work.trim() !== "") parts.push(work);
|
|
773
|
+
if (parts.length === 0) return;
|
|
774
|
+
const text = parts.join("\n\n");
|
|
775
|
+
return {
|
|
776
|
+
systemPrompt: basePrompt.trim() === "" ? text : `${basePrompt}\n\n${text}`,
|
|
777
|
+
};
|
|
778
|
+
});
|
|
779
|
+
},
|
|
780
|
+
};
|
|
765
781
|
}
|
|
766
782
|
|
|
767
783
|
/** #675: public 审刑院 seat on the shared filed-officer envelope. */
|
|
@@ -872,8 +888,6 @@ function readDiaristRunCoordinates(ctx: HostContext): {
|
|
|
872
888
|
const DIARIST_BOUNDS_REASK =
|
|
873
889
|
"边界无法使用。请重交 sessions:每卷 path + ranges,每端以原生 id 或本轮行号二选一指名。" as const;
|
|
874
890
|
const DIARIST_ROUTING_STATUSES = new Set(["completed", "escalate"]);
|
|
875
|
-
const DIARIST_STATUS_REASK =
|
|
876
|
-
"status 不是 completed、escalate 之一。请重新交卷,status 写明其一。" as const;
|
|
877
891
|
|
|
878
892
|
/**
|
|
879
893
|
* #708 / #779 / #901: 起居郎 public seat on the shared filed-officer envelope.
|
|
@@ -900,7 +914,7 @@ export function createDiaristRoleRuntime(
|
|
|
900
914
|
// before interpreting any other submitted field; caller-owned data stays open.
|
|
901
915
|
const status = submitted?.status;
|
|
902
916
|
if (typeof status !== "string" || !DIARIST_ROUTING_STATUSES.has(status)) {
|
|
903
|
-
throw new ParentQueueReaskError(
|
|
917
|
+
throw new ParentQueueReaskError(unreadableDiscriminatorNotice("status", submitted?.status));
|
|
904
918
|
}
|
|
905
919
|
if (status === "escalate") return parameters;
|
|
906
920
|
const assertion = readDiaristTicketAssertion(submitted);
|
|
@@ -943,26 +957,9 @@ export function createDiaristRoleRuntime(
|
|
|
943
957
|
);
|
|
944
958
|
}
|
|
945
959
|
|
|
946
|
-
/**
|
|
947
|
-
const COUNTERSIGN_QUEUE_STATUSES = new Set(["converged", "continue", "escalate"]);
|
|
948
|
-
|
|
949
|
-
/**
|
|
950
|
-
* Plain-language re-ask when status is not a known queue word.
|
|
951
|
-
* Back to countersign itself — notary is not summoned (#753).
|
|
952
|
-
*/
|
|
953
|
-
const COUNTERSIGN_STATUS_REASK =
|
|
954
|
-
"status 不是 converged、continue、escalate 三态之一。请重新交卷,status 写明其一。" as const;
|
|
955
|
-
|
|
956
|
-
/** Secretariat status words the submission gate reads. */
|
|
960
|
+
/** Secretariat status words the submission gate reads. Not the review three-state field. */
|
|
957
961
|
const SECRETARIAT_QUEUE_STATUSES = new Set(["converged", "escalate"]);
|
|
958
962
|
|
|
959
|
-
/**
|
|
960
|
-
* Plain-language re-ask when secretariatStatus is not a known queue word.
|
|
961
|
-
* Back to secretariat itself — 给事中 is not summoned for escalation.
|
|
962
|
-
*/
|
|
963
|
-
const SECRETARIAT_STATUS_REASK =
|
|
964
|
-
"secretariatStatus 不是 converged、escalate 之一。请重新交卷,status 写明其一。" as const;
|
|
965
|
-
|
|
966
963
|
/**
|
|
967
964
|
* Secretariat output is terminal; converged submissions enter the shared
|
|
968
965
|
* submission gate on every host that mounts gatekeeper actions.
|
|
@@ -989,7 +986,9 @@ export function createSecretariatRoleRuntime(
|
|
|
989
986
|
? record.secretariatStatus
|
|
990
987
|
: undefined;
|
|
991
988
|
if (status === undefined || !SECRETARIAT_QUEUE_STATUSES.has(status)) {
|
|
992
|
-
throw new ParentQueueReaskError(
|
|
989
|
+
throw new ParentQueueReaskError(
|
|
990
|
+
unreadableDiscriminatorNotice("secretariatStatus", record?.secretariatStatus),
|
|
991
|
+
);
|
|
993
992
|
}
|
|
994
993
|
if (status === "escalate") {
|
|
995
994
|
// Parent escalate → throw to caller as-is; countersign does not attend.
|
|
@@ -1132,10 +1131,10 @@ export function createCountersignRoleRuntime(
|
|
|
1132
1131
|
record !== undefined && typeof record.status === "string"
|
|
1133
1132
|
? record.status
|
|
1134
1133
|
: undefined;
|
|
1135
|
-
if (status === undefined || !
|
|
1134
|
+
if (status === undefined || !REVIEW_QUEUE_STATUSES.has(status)) {
|
|
1136
1135
|
// Parent status unreadable → back to countersign itself; do not summon notary,
|
|
1137
1136
|
// do not forge an officer bounce face (#753).
|
|
1138
|
-
throw new ParentQueueReaskError(
|
|
1137
|
+
throw new ParentQueueReaskError(unreadableDiscriminatorNotice("status", record?.status));
|
|
1139
1138
|
}
|
|
1140
1139
|
if (status === "escalate") {
|
|
1141
1140
|
// Parent escalate → throw to caller as-is; notary does not attend (#753).
|
|
@@ -1327,13 +1326,11 @@ export function createRoleRuntimeExtension(
|
|
|
1327
1326
|
const raced = await raceNavigatorGrace(settlePromise, NAVIGATOR_POST_ROLE_GRACE_MS);
|
|
1328
1327
|
if (raced.status !== "timeout") return;
|
|
1329
1328
|
if (pendingNavigatorPresentation === undefined) {
|
|
1330
|
-
const routePlaybookReadFailure = attendance.knownRoutePlaybookReadFailure?.();
|
|
1331
1329
|
const report: NavigatorReport = {
|
|
1332
1330
|
disposition: "unavailable",
|
|
1333
1331
|
unavailableReason: "Navigator exceeded post-role delivery grace",
|
|
1334
1332
|
unavailableSource: "unknown",
|
|
1335
1333
|
unavailableCause: "unknown",
|
|
1336
|
-
...(routePlaybookReadFailure === undefined ? {} : { routePlaybookReadFailure }),
|
|
1337
1334
|
};
|
|
1338
1335
|
const event: NavigatorEvent = {
|
|
1339
1336
|
version: 1,
|
|
@@ -1345,7 +1342,6 @@ export function createRoleRuntimeExtension(
|
|
|
1345
1342
|
unavailableReason: "Navigator exceeded post-role delivery grace",
|
|
1346
1343
|
unavailableSource: "unknown",
|
|
1347
1344
|
unavailableCause: "unknown",
|
|
1348
|
-
...(routePlaybookReadFailure === undefined ? {} : { routePlaybookReadFailure }),
|
|
1349
1345
|
};
|
|
1350
1346
|
pendingNavigatorPresentation = { event, report };
|
|
1351
1347
|
}
|
|
@@ -1616,7 +1612,7 @@ export function createRoleRuntimeExtension(
|
|
|
1616
1612
|
} catch {}
|
|
1617
1613
|
envelopeHost.sendMessage({
|
|
1618
1614
|
customType: "ak-receipt-delivery-prompt",
|
|
1619
|
-
content:
|
|
1615
|
+
content: JSON.stringify(receiptDelivery.deliveryState()),
|
|
1620
1616
|
display: false,
|
|
1621
1617
|
}, { triggerTurn: true, deliverAs: "followUp" });
|
|
1622
1618
|
} else if (receiptDelivery.nextAction() === "no-receipt" && !noReceiptRecorded) {
|
|
@@ -1789,6 +1785,11 @@ export function createRoleRuntimeExtension(
|
|
|
1789
1785
|
});
|
|
1790
1786
|
const navigator = createNavigatorRoleRuntime(roleHost, {
|
|
1791
1787
|
loadSoul: () => requireRoleSoul("navigator"),
|
|
1788
|
+
recordRoutePlaybookReadFailure: (message) => {
|
|
1789
|
+
envelopeHost.appendEntry(NAVIGATOR_ROUTE_PLAYBOOK_FAILURE_ENTRY, {
|
|
1790
|
+
message: message ?? "",
|
|
1791
|
+
});
|
|
1792
|
+
},
|
|
1792
1793
|
});
|
|
1793
1794
|
const auditor = createAuditorRoleRuntime(roleHost, {
|
|
1794
1795
|
loadSoul: () => requireRoleSoul("auditor"),
|
|
@@ -2175,11 +2176,8 @@ export function createRoleRuntimeExtension(
|
|
|
2175
2176
|
pendingNavigatorPresentation = { event: navigatorEvent, report };
|
|
2176
2177
|
},
|
|
2177
2178
|
});
|
|
2178
|
-
//
|
|
2179
|
-
//
|
|
2180
|
-
// overlaps the role run. Placeholder subjects wait for before_agent_start
|
|
2181
|
-
// (user prompt may replace the subject key) but still inherit warm help.
|
|
2182
|
-
navigatorAttendance.warmHelp?.();
|
|
2179
|
+
// Concrete work context starts standby attendance (record only, no model).
|
|
2180
|
+
// Placeholder subjects wait for before_agent_start (user prompt may replace the subject key).
|
|
2183
2181
|
if (
|
|
2184
2182
|
navigatorWorkContext.contextError === undefined &&
|
|
2185
2183
|
navigatorWorkContext.subjectProvenance !== "placeholder"
|
package/src/secretariat-role.ts
CHANGED
|
@@ -12,12 +12,12 @@ import { SECRETARIAT_OUTPUT_TOOL_NAME, type SecretariatVerdict } from "./secreta
|
|
|
12
12
|
export { SECRETARIAT_OUTPUT_TOOL_NAME } from "./secretariat-contracts.ts";
|
|
13
13
|
export type { SecretariatVerdict };
|
|
14
14
|
|
|
15
|
-
/**
|
|
15
|
+
/** 中书省终局回执形状。 */
|
|
16
16
|
export const secretariatVerdictSchema = withTerminatingOutputDeclarations(
|
|
17
17
|
Type.Object(
|
|
18
18
|
{
|
|
19
19
|
secretariatStatus: Type.Unknown({
|
|
20
|
-
description: "converged | escalate
|
|
20
|
+
description: "converged | escalate",
|
|
21
21
|
}),
|
|
22
22
|
ticketNumber: Type.Optional(
|
|
23
23
|
Type.Number({ description: "本票号;署时指向最终正文所在票" }),
|
|
@@ -44,7 +44,7 @@ export type SecretariatVerdictParameters = Static<typeof secretariatVerdictSchem
|
|
|
44
44
|
export const SECRETARIAT_OUTPUT_TOOL_SPEC = {
|
|
45
45
|
name: SECRETARIAT_OUTPUT_TOOL_NAME,
|
|
46
46
|
label: "中书省输出",
|
|
47
|
-
description: "
|
|
47
|
+
description: "中书省终局回执。",
|
|
48
48
|
promptSnippet: "中书省终局回执",
|
|
49
49
|
parameters: secretariatVerdictSchema,
|
|
50
50
|
} as const;
|
package/src/submission-errors.ts
CHANGED
|
@@ -58,6 +58,22 @@ export class WorkerUnfinishedReasonReminderError extends Error {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Host constraint missed a routing discriminator (#1055).
|
|
63
|
+
* Names live only in the submission schema. This notice carries the field and the received value.
|
|
64
|
+
*/
|
|
65
|
+
export function unreadableDiscriminatorNotice(field: string, received: unknown): string {
|
|
66
|
+
if (received === undefined) return `读不出 ${field}`;
|
|
67
|
+
return `读不出 ${field}:${readableGateItem(received)}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** The received discriminator only — never the rest of the receipt. */
|
|
71
|
+
export function receivedDiscriminator(receipt: unknown, field: string): unknown {
|
|
72
|
+
if (receipt === null || typeof receipt !== "object" || Array.isArray(receipt)) return undefined;
|
|
73
|
+
if (!Object.hasOwn(receipt, field)) return undefined;
|
|
74
|
+
return (receipt as Record<string, unknown>)[field];
|
|
75
|
+
}
|
|
76
|
+
|
|
61
77
|
/**
|
|
62
78
|
* Parent seat status unreadable for queueing (#753).
|
|
63
79
|
* Correctable back to the parent itself — not a gate officer bounce, no officer field.
|
package/src/submission-gate.ts
CHANGED
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
type GateOfficerSummon,
|
|
28
28
|
} from "./gatekeeper-role.ts";
|
|
29
29
|
import type { PublicSummonResult } from "./public-role-summons.ts";
|
|
30
|
+
|
|
30
31
|
import { sessionFileFromPublicSummon } from "./session-assistant-usage.ts";
|
|
31
32
|
|
|
32
33
|
/**
|
|
@@ -178,7 +179,7 @@ export async function requireSubmissionGate(options: {
|
|
|
178
179
|
};
|
|
179
180
|
}
|
|
180
181
|
if (gatekeeper.status === "needs_reask") {
|
|
181
|
-
reask = officerConclusionReask(
|
|
182
|
+
reask = officerConclusionReask(gatekeeper.receivedStatus);
|
|
182
183
|
continue;
|
|
183
184
|
}
|
|
184
185
|
if (gatekeeper.status === "transport_failure") {
|
package/src/submission-ledger.ts
CHANGED
|
@@ -20,7 +20,8 @@ import type { SitianRecord } from "./sitian-contracts.ts";
|
|
|
20
20
|
import { findRunDirectoryById } from "./public-cli/run-lifecycle.ts";
|
|
21
21
|
import type { TerminalRoleName } from "./public-cli/terminal.ts";
|
|
22
22
|
import { isCorrectableExecuteError } from "./submission-correctable-error.ts";
|
|
23
|
-
import { failOnInfrastructureFailureDeclaration } from "./package-contracts/terminating-infrastructure.ts";
|
|
23
|
+
import { failOnInfrastructureFailureDeclaration, infrastructureFailureDiagnostic } from "./package-contracts/terminating-infrastructure.ts";
|
|
24
|
+
import { REVIEW_SUBMISSION_OUTPUT_TOOL_NAME } from "./review-submission.ts";
|
|
24
25
|
|
|
25
26
|
export type SubmissionCall = { readonly id: string; readonly name: string };
|
|
26
27
|
export type SubmissionOutcomeKind = "correctable-rejection" | "audit-escalation" | "infrastructure";
|
|
@@ -678,17 +679,28 @@ export function createSubmissionLedgerHost(
|
|
|
678
679
|
});
|
|
679
680
|
let result: HostToolResult<unknown>;
|
|
680
681
|
try {
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
682
|
+
// A review escalate that carries the failure declaration is the
|
|
683
|
+
// seat's own submission. Every other declaration stays on the
|
|
684
|
+
// host-failure seam. Tool identity comes from the registry map.
|
|
685
|
+
const reviewEscalate = tool.name === REVIEW_SUBMISSION_OUTPUT_TOOL_NAME
|
|
686
|
+
&& infrastructureFailureDiagnostic(params) !== undefined
|
|
687
|
+
&& params !== null
|
|
688
|
+
&& typeof params === "object"
|
|
689
|
+
&& !Array.isArray(params)
|
|
690
|
+
&& (params as Record<string, unknown>).status === "escalate";
|
|
691
|
+
if (!reviewEscalate) {
|
|
692
|
+
failOnInfrastructureFailureDeclaration(
|
|
693
|
+
params,
|
|
694
|
+
{
|
|
695
|
+
failInfrastructure(error, ctx) {
|
|
696
|
+
failInfrastructure(error, ctx);
|
|
697
|
+
},
|
|
686
698
|
},
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
699
|
+
context,
|
|
700
|
+
toolCallId,
|
|
701
|
+
tool.bounceInfrastructureDeclaration,
|
|
702
|
+
);
|
|
703
|
+
}
|
|
692
704
|
result = await tool.execute(toolCallId, params, signal, update, context);
|
|
693
705
|
} catch (error) {
|
|
694
706
|
if (isCorrectableExecuteError(error)) {
|
package/src/worker-role.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { withTerminatingOutputDeclarations } from "./package-contracts/terminati
|
|
|
5
5
|
|
|
6
6
|
import { readableGateItem } from "./readable-gate-item.ts";
|
|
7
7
|
import { projectGatekeeperEscalation } from "./audit-escalation.ts";
|
|
8
|
-
import { GatekeeperDecisionError, ParentQueueReaskError } from "./submission-errors.ts";
|
|
8
|
+
import { GatekeeperDecisionError, ParentQueueReaskError, unreadableDiscriminatorNotice } from "./submission-errors.ts";
|
|
9
9
|
import {
|
|
10
10
|
CODER_OUTPUT_TOOL_NAME,
|
|
11
11
|
FIXER_OUTPUT_TOOL_NAME,
|
|
@@ -44,11 +44,11 @@ export type { WorkerOutput };
|
|
|
44
44
|
// no code branches on their length. `reason` alone keeps minLength: the worker
|
|
45
45
|
// gate reads `reason.trim().length > 0` to pick typed-reminder-bounce vs accept
|
|
46
46
|
// (src/worker-submission-gates.ts:159-163,297-302).
|
|
47
|
-
//
|
|
48
|
-
//
|
|
47
|
+
// Worker status is not the review three-state field (#1055): schema stays open.
|
|
48
|
+
// One shared description across every variant
|
|
49
49
|
// so openToolObjectFromUnion's identical-declaration collapse drops none of it.
|
|
50
50
|
const CODER_STATUS_DESCRIPTION =
|
|
51
|
-
"planned | completed | refused | partially_completed | unfinished
|
|
51
|
+
"planned | completed | refused | partially_completed | unfinished。unfinished:缺前置或违宪约束致本局未完成。" as const;
|
|
52
52
|
const coderOutputVariants = Type.Union([
|
|
53
53
|
Type.Object({
|
|
54
54
|
status: Type.Unknown({ description: CODER_STATUS_DESCRIPTION }),
|
|
@@ -135,8 +135,6 @@ const WORKER_ROUTING_STATUSES = new Set([
|
|
|
135
135
|
"partially_completed",
|
|
136
136
|
"unfinished",
|
|
137
137
|
]);
|
|
138
|
-
const WORKER_STATUS_REASK =
|
|
139
|
-
"status 不是 planned、completed、refused、partially_completed、unfinished 之一。请重新交卷,status 写明其一。" as const;
|
|
140
138
|
|
|
141
139
|
/** Read only the field that selects the worker's next package-owned path. */
|
|
142
140
|
function workerStatusOf(output: WorkerOutput): string | undefined {
|
|
@@ -148,7 +146,7 @@ function workerStatusOf(output: WorkerOutput): string | undefined {
|
|
|
148
146
|
function requireReadableWorkerStatus(output: WorkerOutput): string {
|
|
149
147
|
const status = workerStatusOf(output);
|
|
150
148
|
if (status === undefined || !WORKER_ROUTING_STATUSES.has(status)) {
|
|
151
|
-
throw new ParentQueueReaskError(
|
|
149
|
+
throw new ParentQueueReaskError(unreadableDiscriminatorNotice("status", isRecord(output) ? output.status : undefined));
|
|
152
150
|
}
|
|
153
151
|
return status;
|
|
154
152
|
}
|
|
@@ -256,7 +254,7 @@ export function createFixerRoleRuntime(
|
|
|
256
254
|
pi.registerTool({
|
|
257
255
|
name: FIXER_OUTPUT_TOOL_NAME,
|
|
258
256
|
label: "修内司输出",
|
|
259
|
-
description: "
|
|
257
|
+
description: "提交修内司终局回执。",
|
|
260
258
|
promptSnippet: "提交修内司终局回执",
|
|
261
259
|
parameters: fixerOutputSchema,
|
|
262
260
|
async execute(toolCallId: string, parameters: unknown, _signal: AbortSignal | undefined, _onUpdate: unknown, ctx: HostContext): Promise<HostToolResult<unknown>> {
|
|
@@ -383,7 +381,7 @@ export function createCoderRoleRuntime(
|
|
|
383
381
|
pi.registerTool({
|
|
384
382
|
name: CODER_OUTPUT_TOOL_NAME,
|
|
385
383
|
label: "将作监输出",
|
|
386
|
-
description: "
|
|
384
|
+
description: "提交将作监终局回执。",
|
|
387
385
|
promptSnippet: "提交将作监终局回执",
|
|
388
386
|
parameters: coderOutputSchema,
|
|
389
387
|
async execute(toolCallId: string, parameters: unknown, _signal: AbortSignal | undefined, _onUpdate: unknown, ctx: HostContext): Promise<HostToolResult<unknown>> {
|