@akagilnc/pi-workflow-roles 0.1.5375 → 0.1.5382
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 +479 -425
- package/dist/collector-tool-schemas.js +18 -0
- package/dist/diarist-contracts.js +26 -0
- package/dist/filed-submission.js +28 -0
- package/dist/gatekeeper-role.js +6 -10
- package/dist/gleaner-left-contracts.js +16 -0
- package/dist/headless-host/production-host.js +495 -441
- package/dist/judge-role.js +8 -16
- package/dist/migrate-book-topology.js +262 -7
- package/dist/package-contracts/reviewer-output.js +16 -0
- package/dist/package-contracts/worker-output.js +18 -2
- package/dist/public-cli/instruction-seat-run.js +9 -12
- package/dist/public-cli/main.js +283 -26
- package/dist/role-submission-declarations.js +131 -0
- package/dist/secretariat-contracts.js +23 -1
- package/dist/submission-gate.js +5 -8
- package/package.json +1 -1
- package/src/auditor-role.ts +2 -8
- package/src/collector-role.ts +5 -28
- package/src/countersign-role.ts +2 -7
- package/src/diarist-contracts.ts +37 -0
- package/src/diarist-role.ts +4 -44
- package/src/doctor-role.ts +16 -11
- package/src/filed-submission.ts +44 -0
- package/src/gatekeeper-role.ts +6 -14
- package/src/gleaner-left-contracts.ts +26 -1
- package/src/gleaner-left-role.ts +4 -32
- package/src/inspector-role.ts +2 -7
- package/src/judge-role.ts +12 -24
- package/src/merger-role.ts +5 -8
- package/src/navigator-role.ts +2 -8
- package/src/notary-role.ts +5 -20
- package/src/package-contracts/reviewer-output.ts +25 -0
- package/src/package-contracts/worker-output.ts +43 -5
- package/src/public-cli/instruction-seat-run.ts +10 -13
- package/src/reviewer-role.ts +7 -35
- package/src/role-runtime.ts +7 -35
- package/src/role-submission-declarations.ts +143 -0
- package/src/secretariat-contracts.ts +35 -0
- package/src/secretariat-role.ts +4 -40
- package/src/submission-gate.ts +8 -9
- package/src/worker-role.ts +62 -79
- package/src/worker-submission-gates.ts +3 -0
package/src/notary-role.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type { RoleHost, HostContext
|
|
1
|
+
import type { RoleHost, HostContext } from "./host-contracts.ts";
|
|
2
|
+
import { registerFiledSubmissionTool } from "./filed-submission.ts";
|
|
3
|
+
import { roleSubmissionDeclaration } from "./role-submission-declarations.ts";
|
|
2
4
|
/**
|
|
3
5
|
* Public Notary role runtime — direct officer seat (not through Gatekeeper province).
|
|
4
6
|
* Caller supplies only a source-run locator; Notary self-fetches authoritative materials.
|
|
@@ -10,7 +12,6 @@ import {
|
|
|
10
12
|
NOTARY_OUTPUT_TOOL_NAME,
|
|
11
13
|
NOTARY_SOURCE_RUN_FLAG,
|
|
12
14
|
NOTARY_TICKET_FLAG,
|
|
13
|
-
notaryOutputSchema,
|
|
14
15
|
type NotarySourceRunLocator,
|
|
15
16
|
} from "./notary-contracts.ts";
|
|
16
17
|
|
|
@@ -156,24 +157,8 @@ export function createNotaryRoleRuntime(
|
|
|
156
157
|
|
|
157
158
|
if (!registered) {
|
|
158
159
|
registered = true;
|
|
159
|
-
pi
|
|
160
|
-
|
|
161
|
-
label: "符宝郎输出",
|
|
162
|
-
description: "提交引文保真与票面对齐的 converged/continue/escalate 决议。",
|
|
163
|
-
promptSnippet: "提交符宝郎决议",
|
|
164
|
-
parameters: notaryOutputSchema,
|
|
165
|
-
async execute(toolCallId: string, parameters: unknown, _signal: AbortSignal | undefined, _onUpdate: unknown, ctx: HostContext, ): Promise<HostToolResult<unknown>> {
|
|
166
|
-
if (activation === undefined) {
|
|
167
|
-
throw new Error("符宝郎未激活");
|
|
168
|
-
}
|
|
169
|
-
// #753: handler only records — params as submitted, no findings/disposition rewrite.
|
|
170
|
-
// #541 infra declaration + sole-final barrier are ledger-owned (#575).
|
|
171
|
-
return {
|
|
172
|
-
content: [],
|
|
173
|
-
details: parameters,
|
|
174
|
-
terminate: true as const,
|
|
175
|
-
};
|
|
176
|
-
},
|
|
160
|
+
registerFiledSubmissionTool(pi, roleSubmissionDeclaration("notary"), {
|
|
161
|
+
readyError: () => (activation === undefined ? "符宝郎未激活" : undefined),
|
|
177
162
|
});
|
|
178
163
|
// Evidence assembly only (ADR 0018): soul + bound projection.
|
|
179
164
|
// Ticket value is envelope-admitted at activate — not re-read from flags here.
|
|
@@ -1,7 +1,32 @@
|
|
|
1
1
|
/** Package-owned Reviewer intent — original role payload only (#836 删 8). */
|
|
2
2
|
|
|
3
|
+
import { Type } from "typebox";
|
|
4
|
+
|
|
5
|
+
import { openToolObject } from "../open-tool-schema.ts";
|
|
6
|
+
import { withTerminatingOutputDeclarations } from "./terminating-infrastructure.ts";
|
|
7
|
+
|
|
3
8
|
export const REVIEWER_OUTPUT_TOOL_NAME = "ak_reviewer_output";
|
|
4
9
|
|
|
10
|
+
const REVIEWER_AMENDMENTS_DESCRIPTION =
|
|
11
|
+
"已运行 lens 的 amendments 承载 candidates、逐条处置与 verdict 的完整报告(非仅 verdict 行);显式单轴时另一轴可省略(completeness / correctness)。hard-stop/usage error 为 refused 时,已产出报告仍照录对应 lens 字段。" as const;
|
|
12
|
+
// #1134: `status` alone is the trajectory field (#917 §6 two normal lens verdicts →
|
|
13
|
+
// completed; hard-stop / usage error → refused); its words ride the description.
|
|
14
|
+
// amendments/diagnostic are LLM/human-read narrative content returned as
|
|
15
|
+
// submitted — declaration keeps name + semantic description only, no nested
|
|
16
|
+
// object shape, no string type, no required constraint.
|
|
17
|
+
const REVIEWER_STATUS_DESCRIPTION =
|
|
18
|
+
"completed | refused。两种正常 lens verdict(completeness / correctness)均 completed;hard-stop 与 usage error 为 refused(已产出报告仍照录进所选 lens amendments)。" as const;
|
|
19
|
+
const reviewerOutputObject = Type.Object({
|
|
20
|
+
status: Type.Unknown({ description: REVIEWER_STATUS_DESCRIPTION }),
|
|
21
|
+
amendments: Type.Unknown({ description: REVIEWER_AMENDMENTS_DESCRIPTION }),
|
|
22
|
+
diagnostic: Type.Unknown({
|
|
23
|
+
description: "拒绝诊断说明;hard-stop/usage error 原因进此字段,已产出报告另照录 amendments",
|
|
24
|
+
}),
|
|
25
|
+
});
|
|
26
|
+
export const reviewerOutputSchema = withTerminatingOutputDeclarations(
|
|
27
|
+
openToolObject(reviewerOutputObject),
|
|
28
|
+
);
|
|
29
|
+
|
|
5
30
|
/** Seat-owned per-lens finding body text (completeness / correctness). */
|
|
6
31
|
export type ReviewerAmendments = Readonly<
|
|
7
32
|
Partial<Record<"completeness" | "correctness", string>>
|
|
@@ -1,19 +1,39 @@
|
|
|
1
1
|
/** Package-owned independent Coder and Fixer output leaves. */
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { Type } from "typebox";
|
|
4
|
+
|
|
5
|
+
import { openToolObject } from "../open-tool-schema.ts";
|
|
6
|
+
import {
|
|
4
7
|
FIXER_OUTPUT_TOOL_NAME,
|
|
5
8
|
fixerOutputSchema,
|
|
9
|
+
PARTIALLY_COMPLETED_DEFINITION,
|
|
6
10
|
validateFixerOutput,
|
|
11
|
+
type FixerBlocker,
|
|
12
|
+
type FixerClassResult,
|
|
13
|
+
type FixerOutput,
|
|
14
|
+
type FixerPhase,
|
|
7
15
|
} from "./fixer-output.ts";
|
|
16
|
+
import { fixerPrerequisiteSchema, fixerPrerequisitesSchema, parseFixerPrerequisites, validateFixerPrerequisites } from "./fixer-packet.ts";
|
|
17
|
+
import type { FixerInvocationInput, FixerPrerequisite } from "./fixer-packet.ts";
|
|
18
|
+
import { withTerminatingOutputDeclarations } from "./terminating-infrastructure.ts";
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
FIXER_OUTPUT_TOOL_NAME,
|
|
22
|
+
fixerOutputSchema,
|
|
23
|
+
validateFixerOutput,
|
|
24
|
+
fixerPrerequisiteSchema,
|
|
25
|
+
fixerPrerequisitesSchema,
|
|
26
|
+
parseFixerPrerequisites,
|
|
27
|
+
validateFixerPrerequisites,
|
|
28
|
+
};
|
|
8
29
|
export type {
|
|
9
30
|
FixerBlocker,
|
|
10
31
|
FixerClassResult,
|
|
11
32
|
FixerOutput,
|
|
12
33
|
FixerPhase,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
import { validateFixerOutput, type FixerOutput } from "./fixer-output.ts";
|
|
34
|
+
FixerInvocationInput,
|
|
35
|
+
FixerPrerequisite,
|
|
36
|
+
};
|
|
17
37
|
|
|
18
38
|
export const CODER_OUTPUT_TOOL_NAME = "ak_coder_output";
|
|
19
39
|
export type WorkerRoleLabel = "Coder" | "Fixer";
|
|
@@ -31,3 +51,21 @@ export function validateAcceptedCoderDetails(output: unknown): CoderOutput {
|
|
|
31
51
|
export function validateAcceptedWorkerDetails(output: unknown, roleLabel: WorkerRoleLabel = "Coder"): WorkerOutput {
|
|
32
52
|
return roleLabel === "Fixer" ? validateFixerOutput(output) : validateAcceptedCoderDetails(output);
|
|
33
53
|
}
|
|
54
|
+
|
|
55
|
+
// status 的合法词写在 description。WORKER_DONE_STATUSES 只让 completed /
|
|
56
|
+
// partially_completed 进入提交闸。unfinished 且未见理由说明时,运行时同 run 催全
|
|
57
|
+
// (ADR 0050);理由在不在不按 JSON 类型判,也不在派发前用长度拒收。
|
|
58
|
+
// report / remainingScope / reason 的声明只留字段名和语义。
|
|
59
|
+
const CODER_STATUS_DESCRIPTION =
|
|
60
|
+
`planned | completed | refused | partially_completed | unfinished。unfinished:缺前置或违宪约束致本局未完成。${PARTIALLY_COMPLETED_DEFINITION}` as const;
|
|
61
|
+
const coderOutputObject = Type.Object({
|
|
62
|
+
status: Type.Unknown({ description: CODER_STATUS_DESCRIPTION }),
|
|
63
|
+
report: Type.Unknown({ description: "如实结果报告" }),
|
|
64
|
+
remainingScope: Type.Unknown({ description: "本局后剩余工作" }),
|
|
65
|
+
reason: Type.Unknown({
|
|
66
|
+
description: "阻断原因:缺前置或违宪约束。缺待决 owner 决定或答复属缺前置。",
|
|
67
|
+
}),
|
|
68
|
+
});
|
|
69
|
+
export const coderOutputSchema = withTerminatingOutputDeclarations(
|
|
70
|
+
openToolObject(coderOutputObject),
|
|
71
|
+
);
|
|
@@ -11,6 +11,8 @@ import { createPiDoctorAuditor } from "../doctor-auditor.ts";
|
|
|
11
11
|
|
|
12
12
|
import type { DurablePrincipalAuthority, HostContext, RoleTurnRequest } from "../host-contracts.ts";
|
|
13
13
|
import { officerConclusionReask, gateOfficerForSubject } from "../gatekeeper-role.ts";
|
|
14
|
+
import { receivedDiscriminator } from "../submission-errors.ts";
|
|
15
|
+
import { REVIEW_QUEUE_STATUSES } from "../review-submission.ts";
|
|
14
16
|
import { runJudgeGates } from "../judge-role.ts";
|
|
15
17
|
import { WORKER_DONE_STATUSES } from "../worker-submission-contracts.ts";
|
|
16
18
|
import { SECRETARIAT_GATE_OFFICER_ENTRY_TYPE } from "../secretariat-contracts.ts";
|
|
@@ -116,7 +118,6 @@ type SeatRunResult = {
|
|
|
116
118
|
|
|
117
119
|
const AUDITED_ROLES = new Set<PackagedRole>(["judge", "fixer", "coder", "secretariat", "countersign", "doctor"]);
|
|
118
120
|
const SECRETARIAT_STATUS_REASK = "secretariatStatus 不是 converged、escalate 之一。请重新交卷,secretariatStatus 写明其一。";
|
|
119
|
-
const COUNTERSIGN_STATUS_REASK = "status 不是 converged、continue、escalate 三态之一。请重新交卷,status 写明其一。";
|
|
120
121
|
const WORKER_ROUTING_STATUSES: ReadonlySet<string> = new Set([
|
|
121
122
|
"planned", "completed", "refused", "partially_completed", "unfinished",
|
|
122
123
|
]);
|
|
@@ -127,11 +128,10 @@ const DOCTOR_STATUS_REASK =
|
|
|
127
128
|
"status 不是 completed、refused 之一。请重新交卷,status 写明其一。";
|
|
128
129
|
const POST_SUBMISSION_ROUTING: Partial<Record<PackagedRole, {
|
|
129
130
|
readonly statuses: ReadonlySet<string>;
|
|
130
|
-
readonly reask
|
|
131
|
+
readonly reask?: string;
|
|
131
132
|
}>> = {
|
|
132
133
|
judge: {
|
|
133
|
-
statuses:
|
|
134
|
-
reask: "status 不是 converged、continue、escalate 三态之一。请重新交卷,status 写明其一。",
|
|
134
|
+
statuses: REVIEW_QUEUE_STATUSES,
|
|
135
135
|
},
|
|
136
136
|
coder: {
|
|
137
137
|
statuses: WORKER_ROUTING_STATUSES,
|
|
@@ -161,12 +161,10 @@ function unreadablePostSubmissionStatus(
|
|
|
161
161
|
const route = POST_SUBMISSION_ROUTING[admitted.role];
|
|
162
162
|
if (route === undefined) return undefined;
|
|
163
163
|
const payload = terminal.roleOutcome.payloads?.at(-1);
|
|
164
|
-
const status =
|
|
165
|
-
? (payload as Record<string, unknown>).status
|
|
166
|
-
: undefined;
|
|
164
|
+
const status = receivedDiscriminator(payload, "status");
|
|
167
165
|
return typeof status === "string" && route.statuses.has(status)
|
|
168
166
|
? undefined
|
|
169
|
-
: route.reask;
|
|
167
|
+
: route.reask ?? officerConclusionReask(status);
|
|
170
168
|
}
|
|
171
169
|
|
|
172
170
|
async function reaskUnreadablePostSubmissionStatus(
|
|
@@ -908,7 +906,6 @@ export async function runPublicInstructionSeatResume(
|
|
|
908
906
|
return resume();
|
|
909
907
|
}
|
|
910
908
|
|
|
911
|
-
const QUEUE_CONCLUSIONS = new Set(["converged", "continue", "escalate"]);
|
|
912
909
|
const GATE_CHILD_ROLES = new Set(["notary", "auditor", "inspector", "countersign"]);
|
|
913
910
|
|
|
914
911
|
/**
|
|
@@ -933,7 +930,7 @@ async function queueConclusionFromChild(
|
|
|
933
930
|
undefined,
|
|
934
931
|
);
|
|
935
932
|
const status = latestQueueStatus(terminal);
|
|
936
|
-
if (terminal !== undefined && status
|
|
933
|
+
if (terminal !== undefined && typeof status === "string" && REVIEW_QUEUE_STATUSES.has(status)) {
|
|
937
934
|
return { admitted: current, terminal, status };
|
|
938
935
|
}
|
|
939
936
|
const reasked = await runPublicInstructionSeatResume({
|
|
@@ -944,7 +941,7 @@ async function queueConclusionFromChild(
|
|
|
944
941
|
return { stop: reasked };
|
|
945
942
|
}
|
|
946
943
|
const reaskedStatus = latestQueueStatus(reasked.terminal);
|
|
947
|
-
if (reaskedStatus
|
|
944
|
+
if (typeof reaskedStatus === "string" && REVIEW_QUEUE_STATUSES.has(reaskedStatus)) {
|
|
948
945
|
return { admitted: reasked.admitted, terminal: reasked.terminal, status: reaskedStatus };
|
|
949
946
|
}
|
|
950
947
|
if (latestPayloadEscalated(reasked.terminal.roleOutcome)) return { stop: reasked };
|
|
@@ -1006,8 +1003,8 @@ async function auditSubmittedRole(
|
|
|
1006
1003
|
return runPublicInstructionSeatResume({ runId: admitted.runId, message: SECRETARIAT_STATUS_REASK },
|
|
1007
1004
|
{ ...env, autoResumeLimit: 0 }, io);
|
|
1008
1005
|
}
|
|
1009
|
-
if (admitted.role === "countersign" && (typeof status !== "string" || !
|
|
1010
|
-
return runPublicInstructionSeatResume({ runId: admitted.runId, message:
|
|
1006
|
+
if (admitted.role === "countersign" && (typeof status !== "string" || !REVIEW_QUEUE_STATUSES.has(status))) {
|
|
1007
|
+
return runPublicInstructionSeatResume({ runId: admitted.runId, message: officerConclusionReask(status) },
|
|
1011
1008
|
{ ...env, autoResumeLimit: 0 }, io);
|
|
1012
1009
|
}
|
|
1013
1010
|
// Self-escalation is a valid open routing state for these seats only.
|
package/src/reviewer-role.ts
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import type { RoleHost, HostContext
|
|
2
|
-
import { Type } from "typebox";
|
|
3
|
-
import { openToolObject } from "./open-tool-schema.ts";
|
|
4
|
-
import { withTerminatingOutputDeclarations } from "./package-contracts/terminating-infrastructure.ts";
|
|
1
|
+
import type { RoleHost, HostContext } from "./host-contracts.ts";
|
|
5
2
|
|
|
6
|
-
import {
|
|
3
|
+
import { registerFiledSubmissionTool } from "./filed-submission.ts";
|
|
4
|
+
import { roleSubmissionDeclaration } from "./role-submission-declarations.ts";
|
|
7
5
|
|
|
8
|
-
export { REVIEWER_OUTPUT_TOOL_NAME };
|
|
9
|
-
export type { ReviewerIntent };
|
|
6
|
+
export { REVIEWER_OUTPUT_TOOL_NAME, reviewerOutputSchema, type ReviewerIntent } from "./package-contracts/reviewer-output.ts";
|
|
10
7
|
|
|
11
8
|
/** Frozen admitted inputs the behavior layer may consume — no flag surface. */
|
|
12
9
|
export type ReviewerAdmittedInputs = Readonly<{
|
|
@@ -17,25 +14,6 @@ export type ReviewerAdmittedInputs = Readonly<{
|
|
|
17
14
|
ticketNumber?: number;
|
|
18
15
|
}>;
|
|
19
16
|
|
|
20
|
-
const REVIEWER_AMENDMENTS_DESCRIPTION =
|
|
21
|
-
"已运行 lens 的 amendments 承载 candidates、逐条处置与 verdict 的完整报告(非仅 verdict 行);显式单轴时另一轴可省略(completeness / correctness)。hard-stop/usage error 为 refused 时,已产出报告仍照录对应 lens 字段。" as const;
|
|
22
|
-
// #1134: `status` alone is the trajectory field (#917 §6 two normal lens verdicts →
|
|
23
|
-
// completed; hard-stop / usage error → refused); its words ride the description.
|
|
24
|
-
// amendments/diagnostic are LLM/human-read narrative content returned as
|
|
25
|
-
// submitted — declaration keeps name + semantic description only, no nested
|
|
26
|
-
// object shape, no string type, no required constraint.
|
|
27
|
-
const REVIEWER_STATUS_DESCRIPTION =
|
|
28
|
-
"completed | refused。两种正常 lens verdict(completeness / correctness)均 completed;hard-stop 与 usage error 为 refused(已产出报告仍照录进所选 lens amendments)。" as const;
|
|
29
|
-
const reviewerOutputObject = Type.Object({
|
|
30
|
-
status: Type.Unknown({ description: REVIEWER_STATUS_DESCRIPTION }),
|
|
31
|
-
amendments: Type.Unknown({ description: REVIEWER_AMENDMENTS_DESCRIPTION }),
|
|
32
|
-
diagnostic: Type.Unknown({
|
|
33
|
-
description: "拒绝诊断说明;hard-stop/usage error 原因进此字段,已产出报告另照录 amendments",
|
|
34
|
-
}),
|
|
35
|
-
});
|
|
36
|
-
export const reviewerOutputSchema = withTerminatingOutputDeclarations(
|
|
37
|
-
openToolObject(reviewerOutputObject),
|
|
38
|
-
);
|
|
39
17
|
export type ReviewerRoleDependencies = {
|
|
40
18
|
loadSoul(): Promise<string>;
|
|
41
19
|
};
|
|
@@ -70,15 +48,9 @@ export function createReviewerRoleRuntime(
|
|
|
70
48
|
|
|
71
49
|
if (!registered) {
|
|
72
50
|
registered = true;
|
|
73
|
-
pi
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return {
|
|
77
|
-
content: [],
|
|
78
|
-
details: parameters,
|
|
79
|
-
terminate: true as const,
|
|
80
|
-
};
|
|
81
|
-
} });
|
|
51
|
+
registerFiledSubmissionTool(pi, roleSubmissionDeclaration("reviewer"), {
|
|
52
|
+
readyError: () => (soul === undefined || soul.length === 0 ? "御史台输入未装载" : undefined),
|
|
53
|
+
});
|
|
82
54
|
}
|
|
83
55
|
const activatedSoul = soul;
|
|
84
56
|
const activatedBase = fixedBaseRevision;
|
package/src/role-runtime.ts
CHANGED
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
|
|
7
7
|
runDirectoryFromHostContext,
|
|
8
8
|
type HostContext,
|
|
9
|
-
type HostToolResult,
|
|
10
9
|
type RoleEnvelopeHost,
|
|
11
10
|
type RoleHost,
|
|
12
11
|
} from "./host-contracts.ts";
|
|
@@ -14,6 +13,8 @@ import {
|
|
|
14
13
|
import { Value } from "typebox/value";
|
|
15
14
|
import { sitianReport } from "./sitian-facade.ts";
|
|
16
15
|
import { createSubmissionLedgerHost, sealAcceptedSubmission } from "./submission-ledger.ts";
|
|
16
|
+
import { registerFiledSubmissionTool, type FiledSubmissionBeforeAccept } from "./filed-submission.ts";
|
|
17
|
+
import type { RoleSubmissionDeclaration } from "./role-submission-declarations.ts";
|
|
17
18
|
|
|
18
19
|
import { activationTraceRecordSchema, namedActivationCause, type ActivationTraceRecord, type ActivationTraceWriter } from "./activation-trace.ts";
|
|
19
20
|
import { homeFromRunDirectory } from "./activation-ledger-topology.ts";
|
|
@@ -547,18 +548,6 @@ export async function projectClosedSubmissionLifecycle(
|
|
|
547
548
|
}
|
|
548
549
|
}
|
|
549
550
|
|
|
550
|
-
/**
|
|
551
|
-
* Optional pre-accept hook on the shared filed-officer envelope (ADR 0075).
|
|
552
|
-
* May return a details projection (envelope-owned machine facts recorded next to
|
|
553
|
-
* the submitted parameters); undefined keeps the parameters as submitted.
|
|
554
|
-
*/
|
|
555
|
-
type FiledOfficerBeforeAccept = (input: {
|
|
556
|
-
readonly toolCallId: string;
|
|
557
|
-
readonly parameters: unknown;
|
|
558
|
-
readonly signal: AbortSignal | undefined;
|
|
559
|
-
readonly ctx: HostContext;
|
|
560
|
-
}) => Promise<unknown>;
|
|
561
|
-
|
|
562
551
|
/**
|
|
563
552
|
* Shared registration envelope for filed officers (ADR 0018 / #572):
|
|
564
553
|
* activate, tool register, before_agent_start prompt, inventory check.
|
|
@@ -569,9 +558,9 @@ function createFiledOfficerRuntime(
|
|
|
569
558
|
roleHost: RoleHost,
|
|
570
559
|
spec: {
|
|
571
560
|
role: PackagedRole;
|
|
572
|
-
tool:
|
|
561
|
+
tool: RoleSubmissionDeclaration;
|
|
573
562
|
soulTag: string;
|
|
574
|
-
beforeAccept?:
|
|
563
|
+
beforeAccept?: FiledSubmissionBeforeAccept;
|
|
575
564
|
},
|
|
576
565
|
dependencies: { loadSoul(): Promise<string> },
|
|
577
566
|
) {
|
|
@@ -584,26 +573,9 @@ function createFiledOfficerRuntime(
|
|
|
584
573
|
soul = loaded;
|
|
585
574
|
if (!registered) {
|
|
586
575
|
registered = true;
|
|
587
|
-
roleHost.
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
description: spec.tool.description,
|
|
591
|
-
promptSnippet: spec.tool.promptSnippet,
|
|
592
|
-
parameters: spec.tool.parameters as never,
|
|
593
|
-
async execute(toolCallId, parameters, signal, _onUpdate, ctx): Promise<HostToolResult<unknown>> {
|
|
594
|
-
if (soul === undefined) throw new Error(`${spec.role} 职分未装载`);
|
|
595
|
-
const projected =
|
|
596
|
-
spec.beforeAccept === undefined
|
|
597
|
-
? undefined
|
|
598
|
-
: await spec.beforeAccept({ toolCallId, parameters, signal, ctx });
|
|
599
|
-
// Accept-as-is + terminate only. Shape is not an admission gate
|
|
600
|
-
// (第 0 条 / ADR 0055); sole-final barrier is ledger-owned (#575).
|
|
601
|
-
return {
|
|
602
|
-
content: [],
|
|
603
|
-
details: projected === undefined ? parameters : projected,
|
|
604
|
-
terminate: true as const,
|
|
605
|
-
};
|
|
606
|
-
},
|
|
576
|
+
registerFiledSubmissionTool(roleHost, spec.tool, {
|
|
577
|
+
readyError: () => (soul === undefined ? `${spec.role} 职分未装载` : undefined),
|
|
578
|
+
...(spec.beforeAccept === undefined ? {} : { beforeAccept: spec.beforeAccept }),
|
|
607
579
|
});
|
|
608
580
|
roleHost.on("before_agent_start", (event) => {
|
|
609
581
|
if (soul === undefined) throw new Error(`${spec.role} 职分未装载`);
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Field guidance for each public seat's submission tool (#1031).
|
|
3
|
+
* The tool name is the role registry's outputTool. This module does not restate it.
|
|
4
|
+
* Review seats keep the #1028 schema. Other seats keep their own field guidance.
|
|
5
|
+
* Execute lives in filed-submission.ts.
|
|
6
|
+
*/
|
|
7
|
+
import { packagedRoleOutputTool, type PackagedRole } from "./packaged-role-registry.ts";
|
|
8
|
+
import { reviewSubmissionSchema } from "./review-submission.ts";
|
|
9
|
+
import { collectorOutputArgsSchema } from "./collector-tool-schemas.ts";
|
|
10
|
+
import { diaristOutputSchema } from "./diarist-contracts.ts";
|
|
11
|
+
import { doctorSubmissionSchema, DOCTOR_OUTPUT_TOOL_DESCRIPTION } from "./doctor-contracts.ts";
|
|
12
|
+
import { fixerOutputSchema } from "./package-contracts/fixer-output.ts";
|
|
13
|
+
import { gatekeeperOutputSchema } from "./package-contracts/gatekeeper-output.ts";
|
|
14
|
+
import { gleanerLeftOutputSchema } from "./gleaner-left-contracts.ts";
|
|
15
|
+
import { mergerOutputSchema } from "./merger-contracts.ts";
|
|
16
|
+
import { navigatorOutputSchema } from "./package-contracts/navigator-output.ts";
|
|
17
|
+
import { reviewerOutputSchema } from "./package-contracts/reviewer-output.ts";
|
|
18
|
+
import { secretariatVerdictSchema } from "./secretariat-contracts.ts";
|
|
19
|
+
import { coderOutputSchema } from "./package-contracts/worker-output.ts";
|
|
20
|
+
|
|
21
|
+
export type RoleSubmissionDeclaration = {
|
|
22
|
+
readonly role: PackagedRole;
|
|
23
|
+
readonly name: string;
|
|
24
|
+
readonly label: string;
|
|
25
|
+
readonly description: string;
|
|
26
|
+
readonly promptSnippet?: string;
|
|
27
|
+
readonly parameters: unknown;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
type SubmissionFace = Omit<RoleSubmissionDeclaration, "role" | "name">;
|
|
31
|
+
|
|
32
|
+
const SUBMISSION_FACE = {
|
|
33
|
+
judge: {
|
|
34
|
+
label: "大理寺输出",
|
|
35
|
+
description: "提交大理寺终局判词;交卷调用结束后,由公开调用接缝按判词状态执行适用审核。",
|
|
36
|
+
promptSnippet: "提交大理寺终局判词",
|
|
37
|
+
parameters: reviewSubmissionSchema,
|
|
38
|
+
},
|
|
39
|
+
fixer: {
|
|
40
|
+
label: "修内司输出",
|
|
41
|
+
description: "提交修内司终局回执。",
|
|
42
|
+
promptSnippet: "提交修内司终局回执",
|
|
43
|
+
parameters: fixerOutputSchema,
|
|
44
|
+
},
|
|
45
|
+
coder: {
|
|
46
|
+
label: "将作监输出",
|
|
47
|
+
description: "提交将作监终局回执。",
|
|
48
|
+
promptSnippet: "提交将作监终局回执",
|
|
49
|
+
parameters: coderOutputSchema,
|
|
50
|
+
},
|
|
51
|
+
reviewer: {
|
|
52
|
+
label: "御史台输出",
|
|
53
|
+
description: "提交御史台终局回执。",
|
|
54
|
+
promptSnippet: "提交御史台终局回执",
|
|
55
|
+
parameters: reviewerOutputSchema,
|
|
56
|
+
},
|
|
57
|
+
collector: {
|
|
58
|
+
label: "通进司输出",
|
|
59
|
+
description: "提交通进司回执。",
|
|
60
|
+
promptSnippet: "提交通进司回执",
|
|
61
|
+
parameters: collectorOutputArgsSchema,
|
|
62
|
+
},
|
|
63
|
+
doctor: {
|
|
64
|
+
label: "太医署输出",
|
|
65
|
+
description: DOCTOR_OUTPUT_TOOL_DESCRIPTION,
|
|
66
|
+
parameters: doctorSubmissionSchema,
|
|
67
|
+
},
|
|
68
|
+
merger: {
|
|
69
|
+
label: "合并输出",
|
|
70
|
+
description: "提交合并结果;输出分支为 completed 与 escalate。",
|
|
71
|
+
promptSnippet: "提交合并结果",
|
|
72
|
+
parameters: mergerOutputSchema,
|
|
73
|
+
},
|
|
74
|
+
notary: {
|
|
75
|
+
label: "符宝郎输出",
|
|
76
|
+
description: "提交引文保真与票面对齐的 converged/continue/escalate 决议。",
|
|
77
|
+
promptSnippet: "提交符宝郎决议",
|
|
78
|
+
parameters: reviewSubmissionSchema,
|
|
79
|
+
},
|
|
80
|
+
countersign: {
|
|
81
|
+
label: "给事中输出",
|
|
82
|
+
description: "给事中决议。",
|
|
83
|
+
promptSnippet: "给事中决议",
|
|
84
|
+
parameters: reviewSubmissionSchema,
|
|
85
|
+
},
|
|
86
|
+
secretariat: {
|
|
87
|
+
label: "中书省输出",
|
|
88
|
+
description: "中书省终局回执。",
|
|
89
|
+
promptSnippet: "中书省终局回执",
|
|
90
|
+
parameters: secretariatVerdictSchema,
|
|
91
|
+
},
|
|
92
|
+
"gleaner-left": {
|
|
93
|
+
label: "左拾遗输出",
|
|
94
|
+
description: "左拾遗弹章。",
|
|
95
|
+
promptSnippet: "左拾遗弹章",
|
|
96
|
+
parameters: gleanerLeftOutputSchema,
|
|
97
|
+
},
|
|
98
|
+
inspector: {
|
|
99
|
+
label: "台院输出",
|
|
100
|
+
description: "台院终局回执,状态为 converged、continue 或 escalate。",
|
|
101
|
+
promptSnippet: "台院终局回执",
|
|
102
|
+
parameters: reviewSubmissionSchema,
|
|
103
|
+
},
|
|
104
|
+
gatekeeper: {
|
|
105
|
+
label: "门下省决议",
|
|
106
|
+
description: "门下省终局决议。status 为 dispatch 或 pass。",
|
|
107
|
+
promptSnippet: "门下省决议",
|
|
108
|
+
parameters: gatekeeperOutputSchema,
|
|
109
|
+
},
|
|
110
|
+
navigator: {
|
|
111
|
+
label: "游奕使建议",
|
|
112
|
+
description: "游奕使终局回执:散文建议,原样呈现。",
|
|
113
|
+
promptSnippet: "游奕使建议",
|
|
114
|
+
parameters: navigatorOutputSchema,
|
|
115
|
+
},
|
|
116
|
+
auditor: {
|
|
117
|
+
label: "审刑院输出",
|
|
118
|
+
description: "审刑院终局回执,status 为 converged、continue 或 escalate。",
|
|
119
|
+
promptSnippet: "审刑院终局回执",
|
|
120
|
+
parameters: reviewSubmissionSchema,
|
|
121
|
+
},
|
|
122
|
+
diarist: {
|
|
123
|
+
label: "起居郎输出",
|
|
124
|
+
description: "起居郎交单票 sessions 或多票逐票 ticketSessions 边界;认不出本庭对象则 escalate。",
|
|
125
|
+
promptSnippet: "起居郎交边界",
|
|
126
|
+
parameters: diaristOutputSchema,
|
|
127
|
+
},
|
|
128
|
+
} as const satisfies Record<PackagedRole, SubmissionFace>;
|
|
129
|
+
|
|
130
|
+
/** Tool name comes from the registry record. Label and schema stay on this face. */
|
|
131
|
+
export function roleSubmissionDeclaration(role: PackagedRole): RoleSubmissionDeclaration {
|
|
132
|
+
const name = packagedRoleOutputTool(role);
|
|
133
|
+
if (name === undefined) throw new Error(`${role} output tool is not declared`);
|
|
134
|
+
const face = SUBMISSION_FACE[role];
|
|
135
|
+
return {
|
|
136
|
+
role,
|
|
137
|
+
name,
|
|
138
|
+
label: face.label,
|
|
139
|
+
description: face.description,
|
|
140
|
+
...("promptSnippet" in face ? { promptSnippet: face.promptSnippet } : {}),
|
|
141
|
+
parameters: face.parameters,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
@@ -7,7 +7,42 @@
|
|
|
7
7
|
* is defaulted, rewritten, or dropped (ADR 0055).
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import { Type } from "typebox";
|
|
11
|
+
|
|
12
|
+
import { withTerminatingOutputDeclarations } from "./package-contracts/terminating-infrastructure.ts";
|
|
13
|
+
|
|
10
14
|
export const SECRETARIAT_OUTPUT_TOOL_NAME = "ak_secretariat_output";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 中书省终局回执形状。
|
|
18
|
+
* #1134: `secretariatStatus` alone is the trajectory field
|
|
19
|
+
* (src/packaged-role-registry.ts receiptStatusKey; the public settlement reads
|
|
20
|
+
* converged | escalate to route); its words ride the description. note/evidence/
|
|
21
|
+
* decisionGate are declared name + semantic description only — the string type, the
|
|
22
|
+
* number type, the nested question/options object shape and the required constraint
|
|
23
|
+
* are deleted, because the package declaration IS the host's pre-dispatch validator.
|
|
24
|
+
* (ticketNumber keeps its own declaration: it is the declared seat identity the
|
|
25
|
+
* activation flag and settlement read, not narrative content.)
|
|
26
|
+
*/
|
|
27
|
+
export const secretariatVerdictSchema = withTerminatingOutputDeclarations(
|
|
28
|
+
Type.Object(
|
|
29
|
+
{
|
|
30
|
+
secretariatStatus: Type.Unknown({
|
|
31
|
+
description: "converged | escalate",
|
|
32
|
+
}),
|
|
33
|
+
ticketNumber: Type.Optional(
|
|
34
|
+
Type.Unknown({ description: "本票号;署时指向最终正文所在票" }),
|
|
35
|
+
),
|
|
36
|
+
note: Type.Unknown({ description: "附注" }),
|
|
37
|
+
evidence: Type.Optional(Type.Unknown({ description: "留存证据" })),
|
|
38
|
+
decisionGate: Type.Unknown({
|
|
39
|
+
description: "需陛下处置的问题与选项;可写 question 与 options,原样留存。",
|
|
40
|
+
}),
|
|
41
|
+
},
|
|
42
|
+
{ additionalProperties: true },
|
|
43
|
+
),
|
|
44
|
+
);
|
|
45
|
+
(secretariatVerdictSchema as unknown as { required: string[] }).required = [];
|
|
11
46
|
/**
|
|
12
47
|
* #969 durable custom entry: 给事中 terminal (署|上呈) for seat settlement projection.
|
|
13
48
|
* Carries original receipt bytes + nested runId. Envelope persists custom entries
|
package/src/secretariat-role.ts
CHANGED
|
@@ -4,54 +4,18 @@
|
|
|
4
4
|
* shared envelope — src/role-runtime.ts (ADR 0018 / #924).
|
|
5
5
|
*/
|
|
6
6
|
import type { Static } from "typebox";
|
|
7
|
-
import { Type } from "typebox";
|
|
8
7
|
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
8
|
+
import { SECRETARIAT_OUTPUT_TOOL_NAME, secretariatVerdictSchema, type SecretariatVerdict } from "./secretariat-contracts.ts";
|
|
9
|
+
import { roleSubmissionDeclaration } from "./role-submission-declarations.ts";
|
|
11
10
|
|
|
12
11
|
export { SECRETARIAT_OUTPUT_TOOL_NAME } from "./secretariat-contracts.ts";
|
|
13
12
|
export type { SecretariatVerdict };
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
* 中书省终局回执形状。
|
|
17
|
-
* #1134: `secretariatStatus` alone is the trajectory field
|
|
18
|
-
* (src/packaged-role-registry.ts:406 receiptStatusKey; the public settlement reads
|
|
19
|
-
* converged | escalate to route); its words ride the description. note/evidence/
|
|
20
|
-
* decisionGate are declared name + semantic description only — the string type, the
|
|
21
|
-
* number type, the nested question/options object shape and the required constraint
|
|
22
|
-
* are deleted, because the package declaration IS the host's pre-dispatch validator.
|
|
23
|
-
* (ticketNumber keeps its own declaration: it is the declared seat identity the
|
|
24
|
-
* activation flag and settlement read, not narrative content.)
|
|
25
|
-
*/
|
|
26
|
-
export const secretariatVerdictSchema = withTerminatingOutputDeclarations(
|
|
27
|
-
Type.Object(
|
|
28
|
-
{
|
|
29
|
-
secretariatStatus: Type.Unknown({
|
|
30
|
-
description: "converged | escalate",
|
|
31
|
-
}),
|
|
32
|
-
ticketNumber: Type.Optional(
|
|
33
|
-
Type.Unknown({ description: "本票号;署时指向最终正文所在票" }),
|
|
34
|
-
),
|
|
35
|
-
note: Type.Unknown({ description: "附注" }),
|
|
36
|
-
evidence: Type.Optional(Type.Unknown({ description: "留存证据" })),
|
|
37
|
-
decisionGate: Type.Unknown({
|
|
38
|
-
description: "需陛下处置的问题与选项;可写 question 与 options,原样留存。",
|
|
39
|
-
}),
|
|
40
|
-
},
|
|
41
|
-
{ additionalProperties: true },
|
|
42
|
-
),
|
|
43
|
-
);
|
|
44
|
-
(secretariatVerdictSchema as unknown as { required: string[] }).required = [];
|
|
14
|
+
export { secretariatVerdictSchema } from "./secretariat-contracts.ts";
|
|
45
15
|
|
|
46
16
|
export type SecretariatVerdictParameters = Static<typeof secretariatVerdictSchema>;
|
|
47
17
|
|
|
48
|
-
export const SECRETARIAT_OUTPUT_TOOL_SPEC =
|
|
49
|
-
name: SECRETARIAT_OUTPUT_TOOL_NAME,
|
|
50
|
-
label: "中书省输出",
|
|
51
|
-
description: "中书省终局回执。",
|
|
52
|
-
promptSnippet: "中书省终局回执",
|
|
53
|
-
parameters: secretariatVerdictSchema,
|
|
54
|
-
} as const;
|
|
18
|
+
export const SECRETARIAT_OUTPUT_TOOL_SPEC = roleSubmissionDeclaration("secretariat");
|
|
55
19
|
|
|
56
20
|
export type SecretariatRuntimeDependencies = {
|
|
57
21
|
loadSoul(): Promise<string>;
|
package/src/submission-gate.ts
CHANGED
|
@@ -28,21 +28,20 @@ import {
|
|
|
28
28
|
} from "./gatekeeper-role.ts";
|
|
29
29
|
import type { PublicSummonResult } from "./public-role-summons.ts";
|
|
30
30
|
import type { TerminalResult } from "./public-cli/terminal.ts";
|
|
31
|
+
import { receivedDiscriminator } from "./submission-errors.ts";
|
|
32
|
+
import type { ReviewQueueWord } from "./review-submission.ts";
|
|
31
33
|
|
|
32
|
-
/**
|
|
33
|
-
export function latestQueueStatus(terminal: TerminalResult | undefined):
|
|
34
|
+
/** Received discriminator of the latest payload, retained verbatim for re-ask. */
|
|
35
|
+
export function latestQueueStatus(terminal: TerminalResult | undefined): unknown {
|
|
34
36
|
const outcome = terminal?.roleOutcome;
|
|
35
37
|
if (outcome === undefined) return undefined;
|
|
36
38
|
if (outcome.kind === "audit_escalation") return "escalate";
|
|
37
39
|
if (outcome.kind !== "accepted") return undefined;
|
|
38
40
|
const latest = outcome.payloads?.[outcome.payloads.length - 1];
|
|
39
|
-
if (isRecord(latest)) {
|
|
40
|
-
|
|
41
|
-
if (typeof status === "string" && status.trim() !== "") return status;
|
|
41
|
+
if (isRecord(latest) && Object.hasOwn(latest, "status")) {
|
|
42
|
+
return receivedDiscriminator(latest, "status");
|
|
42
43
|
}
|
|
43
|
-
return
|
|
44
|
-
? outcome.status
|
|
45
|
-
: undefined;
|
|
44
|
+
return outcome.status;
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
export function latestQueuePayload(terminal: TerminalResult | undefined): unknown {
|
|
@@ -131,7 +130,7 @@ function bookDirectOfficerPointer(
|
|
|
131
130
|
* public terminal without a second authority.
|
|
132
131
|
*/
|
|
133
132
|
export type SubmissionGateOutcome = {
|
|
134
|
-
readonly status:
|
|
133
|
+
readonly status: ReviewQueueWord;
|
|
135
134
|
readonly officer: GateOfficer;
|
|
136
135
|
readonly receipt: unknown;
|
|
137
136
|
readonly runId?: string;
|