@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/dist/submission-gate.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { bookDirectOfficerRunPointer } from "./archivist-record-pointer.js";
|
|
2
2
|
import { GatekeeperDecisionError, officerConclusionReask, projectGatekeeperRun, } from "./gatekeeper-role.js";
|
|
3
|
-
|
|
3
|
+
import { receivedDiscriminator } from "./submission-errors.js";
|
|
4
|
+
/** Received discriminator of the latest payload, retained verbatim for re-ask. */
|
|
4
5
|
export function latestQueueStatus(terminal) {
|
|
5
6
|
const outcome = terminal?.roleOutcome;
|
|
6
7
|
if (outcome === undefined)
|
|
@@ -10,14 +11,10 @@ export function latestQueueStatus(terminal) {
|
|
|
10
11
|
if (outcome.kind !== "accepted")
|
|
11
12
|
return undefined;
|
|
12
13
|
const latest = outcome.payloads?.[outcome.payloads.length - 1];
|
|
13
|
-
if (isRecord(latest)) {
|
|
14
|
-
|
|
15
|
-
if (typeof status === "string" && status.trim() !== "")
|
|
16
|
-
return status;
|
|
14
|
+
if (isRecord(latest) && Object.hasOwn(latest, "status")) {
|
|
15
|
+
return receivedDiscriminator(latest, "status");
|
|
17
16
|
}
|
|
18
|
-
return
|
|
19
|
-
? outcome.status
|
|
20
|
-
: undefined;
|
|
17
|
+
return outcome.status;
|
|
21
18
|
}
|
|
22
19
|
export function latestQueuePayload(terminal) {
|
|
23
20
|
const outcome = terminal?.roleOutcome;
|
package/package.json
CHANGED
package/src/auditor-role.ts
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import {
|
|
5
5
|
AUDITOR_OUTPUT_TOOL_NAME,
|
|
6
|
-
auditorOutputSchema,
|
|
7
6
|
} from "./package-contracts/auditor-output.ts";
|
|
7
|
+
import { roleSubmissionDeclaration } from "./role-submission-declarations.ts";
|
|
8
8
|
|
|
9
9
|
export { AUDITOR_OUTPUT_TOOL_NAME };
|
|
10
10
|
|
|
@@ -12,10 +12,4 @@ export type AuditorRuntimeDependencies = {
|
|
|
12
12
|
loadSoul(): Promise<string>;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
export const AUDITOR_TOOL_SPEC =
|
|
16
|
-
name: AUDITOR_OUTPUT_TOOL_NAME,
|
|
17
|
-
label: "审刑院输出",
|
|
18
|
-
description: "审刑院终局回执,status 为 converged、continue 或 escalate。",
|
|
19
|
-
promptSnippet: "审刑院终局回执",
|
|
20
|
-
parameters: auditorOutputSchema,
|
|
21
|
-
} as const;
|
|
15
|
+
export const AUDITOR_TOOL_SPEC = roleSubmissionDeclaration("auditor");
|
package/src/collector-role.ts
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* #1088: code no longer observes/requests/merges GitHub findings — the LLM
|
|
4
4
|
* uses host CLI tools. Envelope owns host-surface + construction seatbelt.
|
|
5
5
|
*/
|
|
6
|
-
import type { RoleHost, HostContext
|
|
7
|
-
import
|
|
6
|
+
import type { RoleHost, HostContext } from "./host-contracts.ts";
|
|
7
|
+
import { registerFiledSubmissionTool } from "./filed-submission.ts";
|
|
8
|
+
import { roleSubmissionDeclaration } from "./role-submission-declarations.ts";
|
|
8
9
|
|
|
9
10
|
import {
|
|
10
11
|
emptyCollectorManifest,
|
|
@@ -17,8 +18,6 @@ import {
|
|
|
17
18
|
import {
|
|
18
19
|
COLLECTOR_OUTPUT_TOOL,
|
|
19
20
|
} from "./package-contracts/collector-output.ts";
|
|
20
|
-
import { collectorOutputArgsSchema } from "./collector-tool-schemas.ts";
|
|
21
|
-
|
|
22
21
|
export { COLLECTOR_OUTPUT_TOOL };
|
|
23
22
|
|
|
24
23
|
export const COLLECTOR_REQUIRED_TOOLS = [COLLECTOR_OUTPUT_TOOL] as const;
|
|
@@ -54,8 +53,6 @@ export const COLLECTOR_TRANSPORT_FLAGS = Object.freeze([
|
|
|
54
53
|
}),
|
|
55
54
|
] as const);
|
|
56
55
|
|
|
57
|
-
const outputSchema = collectorOutputArgsSchema;
|
|
58
|
-
type OutputParams = Static<typeof outputSchema>;
|
|
59
56
|
|
|
60
57
|
export type CollectorRoleDependencies = {
|
|
61
58
|
loadSoul(): Promise<string>;
|
|
@@ -164,28 +161,8 @@ export function createCollectorRoleRuntime(
|
|
|
164
161
|
if (toolsRegistered) return;
|
|
165
162
|
toolsRegistered = true;
|
|
166
163
|
|
|
167
|
-
pi
|
|
168
|
-
|
|
169
|
-
label: "通进司输出",
|
|
170
|
-
description: "提交通进司回执。",
|
|
171
|
-
promptSnippet: "提交通进司回执",
|
|
172
|
-
parameters: outputSchema,
|
|
173
|
-
async execute(
|
|
174
|
-
_toolCallId: string,
|
|
175
|
-
params: OutputParams,
|
|
176
|
-
_signal: AbortSignal | undefined,
|
|
177
|
-
_onUpdate: unknown,
|
|
178
|
-
_ctx: HostContext,
|
|
179
|
-
): Promise<HostToolResult<unknown>> {
|
|
180
|
-
const activation = getActivation();
|
|
181
|
-
if (activation === undefined) throw new Error("通进司未激活");
|
|
182
|
-
// #1088 / #836: record as submitted — runtime does not merge findings.
|
|
183
|
-
return {
|
|
184
|
-
content: [],
|
|
185
|
-
details: params,
|
|
186
|
-
terminate: true as const,
|
|
187
|
-
};
|
|
188
|
-
},
|
|
164
|
+
registerFiledSubmissionTool(pi, roleSubmissionDeclaration("collector"), {
|
|
165
|
+
readyError: () => (getActivation() === undefined ? "通进司未激活" : undefined),
|
|
189
166
|
});
|
|
190
167
|
},
|
|
191
168
|
};
|
package/src/countersign-role.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { reviewSubmissionSchema } from "./review-submission.ts";
|
|
2
|
+
import { roleSubmissionDeclaration } from "./role-submission-declarations.ts";
|
|
2
3
|
import {
|
|
3
4
|
COUNTERSIGN_OUTPUT_TOOL_NAME,
|
|
4
5
|
validateRecordedCountersignOutput,
|
|
@@ -26,10 +27,4 @@ export type CountersignRuntimeDependencies = {
|
|
|
26
27
|
* 决定工具规格。生命周期装配(注册、activate、prompt 注入、singleton 检查、
|
|
27
28
|
* terminate)归注册信封 owner——src/role-runtime.ts(ADR 0018 / #572 R2 判词)。
|
|
28
29
|
*/
|
|
29
|
-
export const COUNTERSIGN_TOOL_SPEC =
|
|
30
|
-
name: COUNTERSIGN_OUTPUT_TOOL_NAME,
|
|
31
|
-
label: "给事中输出",
|
|
32
|
-
description: "给事中决议。",
|
|
33
|
-
promptSnippet: "给事中决议",
|
|
34
|
-
parameters: countersignVerdictSchema,
|
|
35
|
-
} as const;
|
|
30
|
+
export const COUNTERSIGN_TOOL_SPEC = roleSubmissionDeclaration("countersign");
|
package/src/diarist-contracts.ts
CHANGED
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
* #901: LLM submits bounds; the mechanical layer projects source bytes.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import { Type } from "typebox";
|
|
11
|
+
|
|
12
|
+
import { openToolObject } from "./open-tool-schema.ts";
|
|
13
|
+
import { withTerminatingOutputDeclarations } from "./package-contracts/terminating-infrastructure.ts";
|
|
10
14
|
import {
|
|
11
15
|
projectTicketProvenanceSessions,
|
|
12
16
|
type TicketProvenanceSession,
|
|
@@ -88,3 +92,36 @@ export function projectDiaristTicketSessions(
|
|
|
88
92
|
}
|
|
89
93
|
return Array.from(perTicket, ([ticketNumber, sessions]) => ({ ticketNumber, sessions }));
|
|
90
94
|
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* 起居郎交卷形状。
|
|
98
|
+
* #901:交边界(sessions);正文与不可解析原字节由机械投影。
|
|
99
|
+
* status 的合法词(completed | escalate)写在 description,结算认这些词。
|
|
100
|
+
* sessions / ticketSessions 是投影所读的边界:卷路径或端点读不出时走既有 reask,不中止本轮。
|
|
101
|
+
* 声明只留字段名和语义说明,不留类型、嵌套、长度、必填。
|
|
102
|
+
*/
|
|
103
|
+
const DIARIST_SESSIONS_DESCRIPTION =
|
|
104
|
+
"对话边界。每卷含 path(会话卷绝对或可读路径)与 ranges(本卷本轮各区间)。每段区间含 from / to;起点与终点各写 id(原生 id)或 line(本轮行号),二选一。空列表=本轮无对话可划。端点无法指名时走 reask,不中止。" as const;
|
|
105
|
+
|
|
106
|
+
export const diaristOutputSchema = withTerminatingOutputDeclarations(
|
|
107
|
+
openToolObject(
|
|
108
|
+
Type.Object({
|
|
109
|
+
status: Type.Unknown({
|
|
110
|
+
description: "completed | escalate",
|
|
111
|
+
}),
|
|
112
|
+
ticketNumber: Type.Optional(
|
|
113
|
+
Type.Unknown({
|
|
114
|
+
description:
|
|
115
|
+
"本庭对象票号(正整数)或 null/省略=真无票;下游走 typed 键;认不出用 status=escalate,不洗成无录。机械层不重判。",
|
|
116
|
+
}),
|
|
117
|
+
),
|
|
118
|
+
reason: Type.Unknown({
|
|
119
|
+
description: "status 为 escalate 时:认不出本庭对象的原因",
|
|
120
|
+
}),
|
|
121
|
+
sessions: Type.Optional(Type.Unknown({ description: DIARIST_SESSIONS_DESCRIPTION })),
|
|
122
|
+
ticketSessions: Type.Unknown({
|
|
123
|
+
description: `多票庭逐票对话边界;每票含 ticketNumber(本条边界所归票号,正整数)与 sessions(${DIARIST_SESSIONS_DESCRIPTION})。一次交卷各票各自分录。与单票 sessions 二选一。`,
|
|
124
|
+
}),
|
|
125
|
+
}),
|
|
126
|
+
),
|
|
127
|
+
);
|
package/src/diarist-role.ts
CHANGED
|
@@ -1,53 +1,20 @@
|
|
|
1
1
|
import type { Static } from "typebox";
|
|
2
|
-
import { Type } from "typebox";
|
|
3
2
|
|
|
4
|
-
import { openToolObject } from "./open-tool-schema.ts";
|
|
5
|
-
import { withTerminatingOutputDeclarations } from "./package-contracts/terminating-infrastructure.ts";
|
|
6
3
|
import {
|
|
7
4
|
DIARIST_OUTPUT_TOOL_NAME,
|
|
5
|
+
diaristOutputSchema,
|
|
8
6
|
validateRecordedDiaristOutput,
|
|
9
7
|
type DiaristOutput,
|
|
10
8
|
} from "./diarist-contracts.ts";
|
|
9
|
+
import { roleSubmissionDeclaration } from "./role-submission-declarations.ts";
|
|
11
10
|
|
|
12
11
|
export {
|
|
13
12
|
DIARIST_OUTPUT_TOOL_NAME,
|
|
13
|
+
diaristOutputSchema,
|
|
14
14
|
} from "./diarist-contracts.ts";
|
|
15
15
|
export type { DiaristOutput };
|
|
16
16
|
export { validateRecordedDiaristOutput };
|
|
17
17
|
|
|
18
|
-
/**
|
|
19
|
-
* 起居郎交卷形状。
|
|
20
|
-
* #901:交边界(sessions);正文与不可解析原字节由机械投影。
|
|
21
|
-
* status 的合法词(completed | escalate)写在 description,结算认这些词。
|
|
22
|
-
* sessions / ticketSessions 是投影所读的边界:卷路径或端点读不出时走既有 reask,不中止本轮。
|
|
23
|
-
* 声明只留字段名和语义说明,不留类型、嵌套、长度、必填。
|
|
24
|
-
*/
|
|
25
|
-
const DIARIST_SESSIONS_DESCRIPTION =
|
|
26
|
-
"对话边界。每卷含 path(会话卷绝对或可读路径)与 ranges(本卷本轮各区间)。每段区间含 from / to;起点与终点各写 id(原生 id)或 line(本轮行号),二选一。空列表=本轮无对话可划。端点无法指名时走 reask,不中止。" as const;
|
|
27
|
-
|
|
28
|
-
export const diaristOutputSchema = withTerminatingOutputDeclarations(
|
|
29
|
-
openToolObject(
|
|
30
|
-
Type.Object({
|
|
31
|
-
status: Type.Unknown({
|
|
32
|
-
description: "completed | escalate",
|
|
33
|
-
}),
|
|
34
|
-
ticketNumber: Type.Optional(
|
|
35
|
-
Type.Unknown({
|
|
36
|
-
description:
|
|
37
|
-
"本庭对象票号(正整数)或 null/省略=真无票;下游走 typed 键;认不出用 status=escalate,不洗成无录。机械层不重判。",
|
|
38
|
-
}),
|
|
39
|
-
),
|
|
40
|
-
reason: Type.Unknown({
|
|
41
|
-
description: "status 为 escalate 时:认不出本庭对象的原因",
|
|
42
|
-
}),
|
|
43
|
-
sessions: Type.Optional(Type.Unknown({ description: DIARIST_SESSIONS_DESCRIPTION })),
|
|
44
|
-
ticketSessions: Type.Unknown({
|
|
45
|
-
description: `多票庭逐票对话边界;每票含 ticketNumber(本条边界所归票号,正整数)与 sessions(${DIARIST_SESSIONS_DESCRIPTION})。一次交卷各票各自分录。与单票 sessions 二选一。`,
|
|
46
|
-
}),
|
|
47
|
-
}),
|
|
48
|
-
),
|
|
49
|
-
);
|
|
50
|
-
|
|
51
18
|
export type DiaristOutputParameters = Static<typeof diaristOutputSchema>;
|
|
52
19
|
|
|
53
20
|
export type DiaristRuntimeDependencies = {
|
|
@@ -57,11 +24,4 @@ export type DiaristRuntimeDependencies = {
|
|
|
57
24
|
/**
|
|
58
25
|
* 决定工具规格。生命周期装配归注册信封 owner——src/role-runtime.ts(ADR 0018)。
|
|
59
26
|
*/
|
|
60
|
-
export const DIARIST_TOOL_SPEC =
|
|
61
|
-
name: DIARIST_OUTPUT_TOOL_NAME,
|
|
62
|
-
label: "起居郎输出",
|
|
63
|
-
description:
|
|
64
|
-
"起居郎交单票 sessions 或多票逐票 ticketSessions 边界;认不出本庭对象则 escalate。",
|
|
65
|
-
promptSnippet: "起居郎交边界",
|
|
66
|
-
parameters: diaristOutputSchema,
|
|
67
|
-
} as const;
|
|
27
|
+
export const DIARIST_TOOL_SPEC = roleSubmissionDeclaration("diarist");
|
package/src/doctor-role.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
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
|
import { ComplianceResponseRetentionError } from "./compliance-transport.ts";
|
|
3
5
|
import { DOCTOR_CANDIDATE_ENTRY_TYPE } from "./dossier-resolution.ts";
|
|
4
|
-
import { DOCTOR_EVIDENCE_TOOL_NAME,
|
|
6
|
+
import { DOCTOR_EVIDENCE_TOOL_NAME, DOCTOR_OUTPUT_TOOL_NAME, DoctorEvidenceStore, doctorEvidenceReadSchema, validateDoctorOutput, type DoctorCase } from "./doctor-contracts.ts";
|
|
5
7
|
|
|
6
8
|
import { sitianReport } from "./sitian-facade.ts";
|
|
7
9
|
|
|
@@ -36,15 +38,18 @@ export function createDoctorRoleRuntime(pi: RoleHost, dependencies: DoctorRoleDe
|
|
|
36
38
|
let activation: { soul: string; patient: DoctorCase; store: DoctorEvidenceStore } | undefined; let registered = false; pi.registerFlag(DOCTOR_CASE_FLAG.name, DOCTOR_CASE_FLAG.definition);
|
|
37
39
|
return { async activate() { const path = pi.getFlag(DOCTOR_CASE_FLAG.name); if (typeof path !== "string" || !path.trim()) throw new Error("Doctor requires --ak-doctor-case"); const soul = (await dependencies.loadSoul()).trim(); if (!soul) throw new Error("Doctor soul is empty"); const patient = await dependencies.loadCase(path); activation = { soul, patient, store: new DoctorEvidenceStore(patient) };
|
|
38
40
|
if (!registered) { registered = true; pi.registerTool({ name: DOCTOR_EVIDENCE_TOOL_NAME, label: "太医署证据", description: "分页读取留存的 Pi session 字节。", parameters: doctorEvidenceReadSchema, async execute(_id: string, params: { evidenceId: string; offset?: number; limit?: number }) { if (!activation) throw new Error("太医署未激活"); const details = activation.store.read(params.evidenceId, params.offset, params.limit); return { content: [{ type: "text" as const, text: JSON.stringify(details) }], details }; } });
|
|
39
|
-
pi
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
registerFiledSubmissionTool(pi, roleSubmissionDeclaration("doctor"), {
|
|
42
|
+
readyError: () => (activation === undefined ? "太医署未激活" : undefined),
|
|
43
|
+
beforeAccept: async ({ toolCallId, parameters, ctx }) => {
|
|
44
|
+
if (activation === undefined) throw new Error("太医署未激活");
|
|
45
|
+
const active = activation;
|
|
46
|
+
const testimony = validateDoctorOutput(parameters, active.patient, active.store);
|
|
47
|
+
try {
|
|
48
|
+
appendCandidate(ctx, { version: 1, testimony, cost: active.patient.cost, readRecord: active.store.readRecord(), patientIdentity: active.patient.identity });
|
|
49
|
+
} catch (error) { host.failInfrastructure(error, ctx, toolCallId); }
|
|
50
|
+
return testimony;
|
|
51
|
+
},
|
|
52
|
+
});
|
|
48
53
|
pi.on("before_agent_start", (event) => { if (!activation) throw new Error("太医署未激活"); const catalog = { version: activation.patient.version, identity: activation.patient.identity, admittedMetrics: { cost: activation.patient.cost }, lawfulTargetKeys: ["case", ...activation.patient.cost.invocations.sources], evidence: activation.patient.evidence.map(({ id, kind, sha256, byteLength, contentLength }) => ({ id, kind, sha256, byteLength, contentLength })) }; return { systemPrompt: `${event.systemPrompt}\n\n<doctor_soul>\n${activation.soul}\n</doctor_soul>\n\n<doctor_case>\n${JSON.stringify(catalog)}\n</doctor_case>` }; }); }
|
|
49
54
|
const required = [DOCTOR_EVIDENCE_TOOL_NAME, DOCTOR_OUTPUT_TOOL_NAME]; const names = pi.getAllTools().map((tool) => tool.name); for (const name of required) if (names.filter((item) => item === name).length !== 1) throw new Error(`Doctor required tool collision or missing: ${name}`); pi.setActiveTools(required); const active = pi.getActiveTools?.() ?? required; if (active.length !== 2 || !required.every((name) => active.includes(name))) throw new Error("Doctor active tool narrowing failed"); } };
|
|
50
55
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { HostContext, HostToolResult, RoleHost } from "./host-contracts.ts";
|
|
2
|
+
import type { RoleSubmissionDeclaration } from "./role-submission-declarations.ts";
|
|
3
|
+
|
|
4
|
+
export type FiledSubmissionBeforeAccept = (input: {
|
|
5
|
+
readonly toolCallId: string;
|
|
6
|
+
readonly parameters: unknown;
|
|
7
|
+
readonly signal: AbortSignal | undefined;
|
|
8
|
+
readonly ctx: HostContext;
|
|
9
|
+
}) => Promise<unknown>;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* One host-neutral submission execute for every public seat.
|
|
13
|
+
* Records nothing itself — the ledger seam already appends the original payload.
|
|
14
|
+
* Ends this tool call. Does not summon an auditor and does not end the role run.
|
|
15
|
+
* Shape is not an admission gate (ADR 0055). Seat reminders stay on beforeAccept.
|
|
16
|
+
*/
|
|
17
|
+
export function registerFiledSubmissionTool(
|
|
18
|
+
roleHost: RoleHost,
|
|
19
|
+
tool: RoleSubmissionDeclaration,
|
|
20
|
+
options: {
|
|
21
|
+
readonly readyError: () => string | undefined;
|
|
22
|
+
readonly beforeAccept?: FiledSubmissionBeforeAccept;
|
|
23
|
+
},
|
|
24
|
+
): void {
|
|
25
|
+
roleHost.registerTool({
|
|
26
|
+
name: tool.name,
|
|
27
|
+
label: tool.label,
|
|
28
|
+
description: tool.description,
|
|
29
|
+
...(tool.promptSnippet === undefined ? {} : { promptSnippet: tool.promptSnippet }),
|
|
30
|
+
parameters: tool.parameters as never,
|
|
31
|
+
async execute(toolCallId, parameters, signal, _onUpdate, ctx): Promise<HostToolResult<unknown>> {
|
|
32
|
+
const blocked = options.readyError();
|
|
33
|
+
if (blocked !== undefined) throw new Error(blocked);
|
|
34
|
+
const projected = options.beforeAccept === undefined
|
|
35
|
+
? undefined
|
|
36
|
+
: await options.beforeAccept({ toolCallId, parameters, signal, ctx });
|
|
37
|
+
return {
|
|
38
|
+
content: [],
|
|
39
|
+
details: projected === undefined ? parameters : projected,
|
|
40
|
+
terminate: true as const,
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
package/src/gatekeeper-role.ts
CHANGED
|
@@ -7,10 +7,8 @@ import type { NoReceiptLifecycleFacts } from "./receipt-delivery-policy.ts";
|
|
|
7
7
|
import { GatekeeperDecisionError, receivedDiscriminator, unreadableDiscriminatorNotice } from "./submission-errors.ts";
|
|
8
8
|
import { INSPECTOR_OUTPUT_TOOL_NAME } from "./inspector-contracts.ts";
|
|
9
9
|
import { REVIEW_QUEUE_STATUSES, REVIEW_SUBMISSION_OUTPUT_TOOL_NAME } from "./review-submission.ts";
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
gatekeeperOutputSchema,
|
|
13
|
-
} from "./package-contracts/gatekeeper-output.ts";
|
|
10
|
+
import { GATEKEEPER_OUTPUT_TOOL_NAME } from "./package-contracts/gatekeeper-output.ts";
|
|
11
|
+
import { roleSubmissionDeclaration } from "./role-submission-declarations.ts";
|
|
14
12
|
import type { PublicSummonResult } from "./public-role-summons.ts";
|
|
15
13
|
import type { TerminalResult } from "./public-cli/terminal.ts";
|
|
16
14
|
import { runIdFromRunDirectory } from "./run-terminal-artifacts.ts";
|
|
@@ -158,13 +156,7 @@ export type SubmissionGateHostActions = {
|
|
|
158
156
|
* registration envelope — src/role-runtime.ts (ADR 0018). Schema authority is
|
|
159
157
|
* the shared contract module (with infrastructure-failure declaration).
|
|
160
158
|
*/
|
|
161
|
-
export const GATEKEEPER_TOOL_SPEC =
|
|
162
|
-
name: GATEKEEPER_OUTPUT_TOOL_NAME,
|
|
163
|
-
label: "门下省决议",
|
|
164
|
-
description: "门下省终局决议。status 为 dispatch 或 pass。",
|
|
165
|
-
promptSnippet: "门下省决议",
|
|
166
|
-
parameters: gatekeeperOutputSchema,
|
|
167
|
-
} as const;
|
|
159
|
+
export const GATEKEEPER_TOOL_SPEC = roleSubmissionDeclaration("gatekeeper");
|
|
168
160
|
|
|
169
161
|
export type GatekeeperRuntimeDependencies = {
|
|
170
162
|
loadSoul(): Promise<string>;
|
|
@@ -199,9 +191,9 @@ function projectOfficerDecision(
|
|
|
199
191
|
): GatekeeperResult {
|
|
200
192
|
const receipt = retainedReceipt(decision);
|
|
201
193
|
const record = isRecord(decision) ? decision : undefined;
|
|
202
|
-
const status =
|
|
203
|
-
(record
|
|
204
|
-
|
|
194
|
+
const status = record !== undefined && Object.hasOwn(record, "status")
|
|
195
|
+
? receivedDiscriminator(record, "status")
|
|
196
|
+
: fallbackStatus;
|
|
205
197
|
const queueStatus = typeof status === "string" ? reviewQueueStatus(status) : undefined;
|
|
206
198
|
if (queueStatus === "converged") {
|
|
207
199
|
return { status: "converged", officer, receipt };
|
|
@@ -4,10 +4,36 @@
|
|
|
4
4
|
* No bounce / verdict channel (言不为狱). 原卷保真 (ADR 0055).
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { Type } from "typebox";
|
|
8
|
+
|
|
9
|
+
import { openToolObject } from "./open-tool-schema.ts";
|
|
10
|
+
import { withTerminatingOutputDeclarations } from "./package-contracts/terminating-infrastructure.ts";
|
|
7
11
|
import { isRecord } from "./unknown-value.ts";
|
|
8
12
|
|
|
9
13
|
export const GLEANER_LEFT_OUTPUT_TOOL_NAME = "ak_gleaner_left_output";
|
|
10
14
|
|
|
15
|
+
// #836 r16 class 1: pointer/statement are LLM/human-read narrative content — no
|
|
16
|
+
// code branches on their presence.
|
|
17
|
+
// #1134: `status` alone is the trajectory field (src/gleaner-left-contracts.ts:38
|
|
18
|
+
// recognizes completed to settle); its word rides the description. findings is
|
|
19
|
+
// narrative content declared name + semantic description only — the array type
|
|
20
|
+
// and the nested pointer/statement object shape are deleted, because the package
|
|
21
|
+
// declaration IS the host's pre-dispatch validator. An empty findings list stays
|
|
22
|
+
// a lawful completion; an omitted one is now expressible too.
|
|
23
|
+
export const gleanerLeftOutputSchema = withTerminatingOutputDeclarations(
|
|
24
|
+
openToolObject(
|
|
25
|
+
Type.Object({
|
|
26
|
+
status: Type.Unknown({
|
|
27
|
+
description: "completed",
|
|
28
|
+
}),
|
|
29
|
+
findings: Type.Unknown({
|
|
30
|
+
description:
|
|
31
|
+
"弹章列表;每条可含 pointer(文件/行指针)与 statement(疑点陈述),原样留存。空列表合法完局;机器不判弹章是否成立。",
|
|
32
|
+
}),
|
|
33
|
+
}),
|
|
34
|
+
),
|
|
35
|
+
);
|
|
36
|
+
|
|
11
37
|
/** Internal transport: comparison-base revision for the unanchored merge-candidate diff. */
|
|
12
38
|
export const GLEANER_LEFT_BASE_FLAG = {
|
|
13
39
|
name: "ak-gleaner-left-base",
|
|
@@ -42,4 +68,3 @@ export function validateRecordedGleanerLeftOutput(value: unknown): GleanerLeftOu
|
|
|
42
68
|
}
|
|
43
69
|
throw new Error("Gleaner-left output has no execution discriminator");
|
|
44
70
|
}
|
|
45
|
-
|
package/src/gleaner-left-role.ts
CHANGED
|
@@ -1,42 +1,20 @@
|
|
|
1
1
|
import type { Static } from "typebox";
|
|
2
|
-
import { Type } from "typebox";
|
|
3
2
|
|
|
4
|
-
import { openToolObject } from "./open-tool-schema.ts";
|
|
5
|
-
import { withTerminatingOutputDeclarations } from "./package-contracts/terminating-infrastructure.ts";
|
|
6
3
|
import {
|
|
7
4
|
GLEANER_LEFT_OUTPUT_TOOL_NAME,
|
|
5
|
+
gleanerLeftOutputSchema,
|
|
8
6
|
validateRecordedGleanerLeftOutput,
|
|
9
7
|
type GleanerLeftOutput,
|
|
10
8
|
} from "./gleaner-left-contracts.ts";
|
|
9
|
+
import { roleSubmissionDeclaration } from "./role-submission-declarations.ts";
|
|
11
10
|
|
|
12
11
|
export {
|
|
13
12
|
GLEANER_LEFT_OUTPUT_TOOL_NAME,
|
|
13
|
+
gleanerLeftOutputSchema,
|
|
14
14
|
} from "./gleaner-left-contracts.ts";
|
|
15
15
|
export type { GleanerLeftOutput };
|
|
16
16
|
export { validateRecordedGleanerLeftOutput };
|
|
17
17
|
|
|
18
|
-
// #836 r16 class 1: pointer/statement are LLM/human-read narrative content — no
|
|
19
|
-
// code branches on their presence.
|
|
20
|
-
// #1134: `status` alone is the trajectory field (src/gleaner-left-contracts.ts:38
|
|
21
|
-
// recognizes completed to settle); its word rides the description. findings is
|
|
22
|
-
// narrative content declared name + semantic description only — the array type
|
|
23
|
-
// and the nested pointer/statement object shape are deleted, because the package
|
|
24
|
-
// declaration IS the host's pre-dispatch validator. An empty findings list stays
|
|
25
|
-
// a lawful completion; an omitted one is now expressible too.
|
|
26
|
-
export const gleanerLeftOutputSchema = withTerminatingOutputDeclarations(
|
|
27
|
-
openToolObject(
|
|
28
|
-
Type.Object({
|
|
29
|
-
status: Type.Unknown({
|
|
30
|
-
description: "completed",
|
|
31
|
-
}),
|
|
32
|
-
findings: Type.Unknown({
|
|
33
|
-
description:
|
|
34
|
-
"弹章列表;每条可含 pointer(文件/行指针)与 statement(疑点陈述),原样留存。空列表合法完局;机器不判弹章是否成立。",
|
|
35
|
-
}),
|
|
36
|
-
}),
|
|
37
|
-
),
|
|
38
|
-
);
|
|
39
|
-
|
|
40
18
|
export type GleanerLeftOutputParameters = Static<typeof gleanerLeftOutputSchema>;
|
|
41
19
|
|
|
42
20
|
export type GleanerLeftRuntimeDependencies = {
|
|
@@ -46,10 +24,4 @@ export type GleanerLeftRuntimeDependencies = {
|
|
|
46
24
|
/**
|
|
47
25
|
* 决定工具规格。生命周期装配归注册信封 owner——src/role-runtime.ts(ADR 0018)。
|
|
48
26
|
*/
|
|
49
|
-
export const GLEANER_LEFT_TOOL_SPEC =
|
|
50
|
-
name: GLEANER_LEFT_OUTPUT_TOOL_NAME,
|
|
51
|
-
label: "左拾遗输出",
|
|
52
|
-
description: "左拾遗弹章。",
|
|
53
|
-
promptSnippet: "左拾遗弹章",
|
|
54
|
-
parameters: gleanerLeftOutputSchema,
|
|
55
|
-
} as const;
|
|
27
|
+
export const GLEANER_LEFT_TOOL_SPEC = roleSubmissionDeclaration("gleaner-left");
|
package/src/inspector-role.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Static } from "typebox";
|
|
2
2
|
import { reviewSubmissionSchema } from "./review-submission.ts";
|
|
3
|
+
import { roleSubmissionDeclaration } from "./role-submission-declarations.ts";
|
|
3
4
|
import {
|
|
4
5
|
INSPECTOR_OUTPUT_TOOL_NAME,
|
|
5
6
|
validateRecordedInspectorOutput,
|
|
@@ -25,10 +26,4 @@ export type InspectorRuntimeDependencies = {
|
|
|
25
26
|
/**
|
|
26
27
|
* 决定工具规格。生命周期装配归注册信封 owner——src/role-runtime.ts(ADR 0018)。
|
|
27
28
|
*/
|
|
28
|
-
export const INSPECTOR_TOOL_SPEC =
|
|
29
|
-
name: INSPECTOR_OUTPUT_TOOL_NAME,
|
|
30
|
-
label: "台院输出",
|
|
31
|
-
description: "台院终局回执,状态为 converged、continue 或 escalate。",
|
|
32
|
-
promptSnippet: "台院终局回执",
|
|
33
|
-
parameters: inspectorOutputSchema,
|
|
34
|
-
} as const;
|
|
29
|
+
export const INSPECTOR_TOOL_SPEC = roleSubmissionDeclaration("inspector");
|
package/src/judge-role.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
} from "./host-contracts.ts";
|
|
6
|
-
import type { Static } from "typebox";
|
|
7
|
-
import { reviewSubmissionSchema } from "./review-submission.ts";
|
|
1
|
+
import { type RoleHost } from "./host-contracts.ts";
|
|
2
|
+
import { REVIEW_QUEUE_STATUSES, reviewSubmissionSchema, type ReviewQueueWord } from "./review-submission.ts";
|
|
3
|
+
import { registerFiledSubmissionTool } from "./filed-submission.ts";
|
|
4
|
+
import { roleSubmissionDeclaration } from "./role-submission-declarations.ts";
|
|
8
5
|
import { type GatekeeperSubject } from "./gatekeeper-role.ts";
|
|
9
6
|
import {
|
|
10
7
|
JUDGE_OUTPUT_TOOL_NAME,
|
|
@@ -31,10 +28,10 @@ export async function runJudgeGates(input: {
|
|
|
31
28
|
readonly runDirectory?: string;
|
|
32
29
|
} | void>;
|
|
33
30
|
}): Promise<{
|
|
34
|
-
readonly status:
|
|
31
|
+
readonly status: ReviewQueueWord;
|
|
35
32
|
readonly passes: readonly {
|
|
36
33
|
readonly subject: GatekeeperSubject;
|
|
37
|
-
readonly status:
|
|
34
|
+
readonly status: ReviewQueueWord;
|
|
38
35
|
readonly receipt: unknown;
|
|
39
36
|
readonly runId?: string;
|
|
40
37
|
readonly runDirectory?: string;
|
|
@@ -42,7 +39,7 @@ export async function runJudgeGates(input: {
|
|
|
42
39
|
}> {
|
|
43
40
|
const passes: {
|
|
44
41
|
subject: GatekeeperSubject;
|
|
45
|
-
status:
|
|
42
|
+
status: ReviewQueueWord;
|
|
46
43
|
receipt: unknown;
|
|
47
44
|
runId?: string;
|
|
48
45
|
runDirectory?: string;
|
|
@@ -50,10 +47,11 @@ export async function runJudgeGates(input: {
|
|
|
50
47
|
for (const subject of JUDGE_GATES) {
|
|
51
48
|
if (await input.gateAlreadyConverged(subject)) continue;
|
|
52
49
|
const pass = await input.runGate(subject);
|
|
53
|
-
const
|
|
54
|
-
if (pass === undefined ||
|
|
50
|
+
const received = pass?.status;
|
|
51
|
+
if (pass === undefined || typeof received !== "string" || !REVIEW_QUEUE_STATUSES.has(received)) {
|
|
55
52
|
throw new Error("judge gate returned no conclusion");
|
|
56
53
|
}
|
|
54
|
+
const status = received as ReviewQueueWord;
|
|
57
55
|
passes.push({
|
|
58
56
|
subject,
|
|
59
57
|
status,
|
|
@@ -90,18 +88,8 @@ export function createJudgeRoleRuntime(
|
|
|
90
88
|
if (soul.length === 0) throw new Error("Judge soul is empty");
|
|
91
89
|
if (!lifecycleRegistered) {
|
|
92
90
|
lifecycleRegistered = true;
|
|
93
|
-
pi
|
|
94
|
-
|
|
95
|
-
label: "大理寺输出",
|
|
96
|
-
description: "提交大理寺终局判词;交卷调用结束后,由公开调用接缝按判词状态执行适用审核。",
|
|
97
|
-
promptSnippet: "提交大理寺终局判词",
|
|
98
|
-
parameters: judgeVerdictSchema,
|
|
99
|
-
async execute(toolCallId: string, parameters: Static<typeof judgeVerdictSchema>, signal: AbortSignal | undefined, _onUpdate: unknown, ctx: HostContext): Promise<HostToolResult<unknown>> {
|
|
100
|
-
if (soul === undefined) throw new Error("大理寺职分未装载");
|
|
101
|
-
// ADR 0003: record the original receipt and end the tool call first.
|
|
102
|
-
// The public seam reads status and chooses the next route.
|
|
103
|
-
return { content: [], details: parameters, terminate: true };
|
|
104
|
-
},
|
|
91
|
+
registerFiledSubmissionTool(pi, roleSubmissionDeclaration("judge"), {
|
|
92
|
+
readyError: () => (soul === undefined ? "大理寺职分未装载" : undefined),
|
|
105
93
|
});
|
|
106
94
|
pi.on("before_agent_start", (event) => {
|
|
107
95
|
if (soul === undefined) throw new Error("大理寺职分未装载");
|
package/src/merger-role.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { RoleHost
|
|
1
|
+
import type { RoleHost } from "./host-contracts.ts";
|
|
2
2
|
import {
|
|
3
3
|
MERGER_OUTPUT_TOOL_NAME,
|
|
4
|
-
mergerOutputSchema,
|
|
5
4
|
validateMergerInput,
|
|
6
5
|
type MergerInput,
|
|
7
6
|
} from "./merger-contracts.ts";
|
|
7
|
+
import { registerFiledSubmissionTool } from "./filed-submission.ts";
|
|
8
|
+
import { roleSubmissionDeclaration } from "./role-submission-declarations.ts";
|
|
8
9
|
import { exactUtf8 } from "./exact-utf8.ts";
|
|
9
10
|
|
|
10
11
|
export { MERGER_OUTPUT_TOOL_NAME };
|
|
@@ -35,12 +36,8 @@ export function createMergerRoleRuntime(pi: RoleHost, dependencies: MergerRoleDe
|
|
|
35
36
|
activation = { soul, input };
|
|
36
37
|
if (!registered) {
|
|
37
38
|
registered = true;
|
|
38
|
-
pi
|
|
39
|
-
|
|
40
|
-
async execute(_id: string, params: unknown, _signal: AbortSignal | undefined, _update: unknown, _ctx: HostContext) {
|
|
41
|
-
if (!activation) throw new Error("校书郎未激活");
|
|
42
|
-
return { content: [], details: params, terminate: true as const };
|
|
43
|
-
},
|
|
39
|
+
registerFiledSubmissionTool(pi, roleSubmissionDeclaration("merger"), {
|
|
40
|
+
readyError: () => (activation === undefined ? "校书郎未激活" : undefined),
|
|
44
41
|
});
|
|
45
42
|
pi.on("before_agent_start", (event) => {
|
|
46
43
|
if (!activation) throw new Error("校书郎未激活");
|
package/src/navigator-role.ts
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { roleSubmissionDeclaration } from "./role-submission-declarations.ts";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* 决定工具规格。生命周期装配归注册信封 owner——src/role-runtime.ts(ADR 0018)。
|
|
5
5
|
* #959: navigator speaks free-form prose; tool is a lifecycle vehicle only.
|
|
6
6
|
*/
|
|
7
|
-
export const NAVIGATOR_TOOL_SPEC =
|
|
8
|
-
name: NAVIGATOR_OUTPUT_TOOL_NAME,
|
|
9
|
-
label: "游奕使建议",
|
|
10
|
-
description: "游奕使终局回执:散文建议,原样呈现。",
|
|
11
|
-
promptSnippet: "游奕使建议",
|
|
12
|
-
parameters: navigatorOutputSchema,
|
|
13
|
-
} as const;
|
|
7
|
+
export const NAVIGATOR_TOOL_SPEC = roleSubmissionDeclaration("navigator");
|
|
14
8
|
|
|
15
9
|
export type NavigatorRuntimeDependencies = {
|
|
16
10
|
loadSoul(): Promise<string>;
|