@akagilnc/pi-workflow-roles 0.1.5375 → 0.1.5406
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/README.md +2 -0
- package/README.zh-CN.md +2 -0
- package/dist/acp-host/production-host.js +6381 -5684
- package/dist/archivist-record-pointer.js +38 -0
- package/dist/collector-tool-schemas.js +18 -0
- package/dist/compliance-transport.js +5 -0
- package/dist/diarist-contracts.js +26 -0
- package/dist/doctor-auditor.js +1 -0
- package/dist/engine-detour-usage.js +6 -6
- 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 +1644 -947
- package/dist/judge-role.js +21 -16
- package/dist/migrate-book-topology.js +452 -81
- package/dist/navigator-attendance.js +10 -9
- package/dist/navigator-invocation-identity.js +18 -0
- package/dist/package-contracts/reviewer-output.js +16 -0
- package/dist/package-contracts/worker-output.js +18 -2
- package/dist/pi/role-turn-host.js +9 -0
- package/dist/public-cli/cli.js +1 -0
- package/dist/public-cli/instruction-seat-run.js +258 -55
- package/dist/public-cli/main.js +1209 -346
- package/dist/public-cli/post-admission.js +427 -244
- package/dist/public-cli/settlement.js +111 -48
- package/dist/public-cli/terminal.js +12 -1
- package/dist/public-cli/turn-request.js +3 -0
- package/dist/receipt-delivery-policy.js +152 -17
- package/dist/role-submission-declarations.js +131 -0
- package/dist/secretariat-contracts.js +23 -1
- package/dist/submission-errors.js +11 -1
- package/dist/submission-gate.js +32 -12
- package/package.json +1 -1
- package/src/archivist-record-pointer.ts +48 -0
- package/src/auditor-role.ts +2 -8
- package/src/collector-role.ts +5 -28
- package/src/compliance-transport.ts +10 -2
- package/src/countersign-role.ts +2 -7
- package/src/diarist-contracts.ts +37 -0
- package/src/diarist-role.ts +4 -44
- package/src/doctor-auditor.ts +3 -0
- package/src/doctor-role.ts +16 -11
- package/src/engine-detour-usage.ts +7 -6
- package/src/external-host-turn-loop.ts +24 -12
- package/src/filed-submission.ts +44 -0
- package/src/gatekeeper-role.ts +8 -16
- package/src/gleaner-left-contracts.ts +26 -1
- package/src/gleaner-left-role.ts +4 -32
- package/src/host-contracts.ts +7 -0
- package/src/inspector-role.ts +2 -7
- package/src/judge-role.ts +31 -24
- package/src/merger-role.ts +5 -8
- package/src/navigator-attendance.ts +17 -12
- package/src/navigator-invocation-identity.ts +31 -0
- 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/pi/adapter.ts +33 -8
- package/src/pi/role-turn-host.ts +7 -0
- package/src/public-cli/cli.ts +1 -0
- package/src/public-cli/instruction-seat-run.ts +292 -61
- package/src/public-cli/post-admission.ts +556 -324
- package/src/public-cli/settlement.ts +112 -50
- package/src/public-cli/terminal.ts +16 -4
- package/src/public-cli/turn-request.ts +10 -1
- package/src/receipt-delivery-policy.ts +209 -17
- package/src/reviewer-role.ts +7 -35
- package/src/role-envelope.ts +5 -1
- package/src/role-runtime-dependencies.ts +1 -0
- package/src/role-runtime.ts +72 -56
- 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-correctable-error.ts +5 -2
- package/src/submission-errors.ts +12 -1
- package/src/submission-gate.ts +41 -12
- package/src/worker-role.ts +81 -86
- package/src/worker-submission-gates.ts +32 -7
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";
|
|
@@ -60,8 +58,8 @@ export type GatekeeperResult =
|
|
|
60
58
|
| {
|
|
61
59
|
/**
|
|
62
60
|
* Accepted reply whose conclusion is not converged|continue|escalate.
|
|
63
|
-
* Envelope
|
|
64
|
-
*
|
|
61
|
+
* Envelope reasks the officer in plain language against the configured
|
|
62
|
+
* ceiling, then keeps this receipt. Never parent-stands, never forges continue.
|
|
65
63
|
*/
|
|
66
64
|
readonly status: "needs_reask";
|
|
67
65
|
readonly officer: GateOfficer;
|
|
@@ -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/host-contracts.ts
CHANGED
|
@@ -198,6 +198,13 @@ export type RoleTurnRequest = {
|
|
|
198
198
|
readonly host?: string;
|
|
199
199
|
/** Station child role run (#840): omit automatic navigator attendance. */
|
|
200
200
|
readonly stationChild?: boolean;
|
|
201
|
+
/**
|
|
202
|
+
* #1132: the effective delivery-request ceiling resolved once by the caller
|
|
203
|
+
* from the single configured `autoResumeLimit` value and projected here, so
|
|
204
|
+
* the AK execution seam and the host adapter's own re-ask loop share one
|
|
205
|
+
* number. Absent = package default. Never re-read from disk downstream.
|
|
206
|
+
*/
|
|
207
|
+
readonly deliveryRequestLimit?: number;
|
|
201
208
|
};
|
|
202
209
|
|
|
203
210
|
/** Turn result — only fields upper layers currently consume. */
|
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,15 +1,13 @@
|
|
|
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,
|
|
11
8
|
type JudgeVerdict,
|
|
12
9
|
} from "./package-contracts/judge-output.ts";
|
|
10
|
+
import type { TerminalResult } from "./public-cli/terminal.ts";
|
|
13
11
|
|
|
14
12
|
export { JUDGE_OUTPUT_TOOL_NAME };
|
|
15
13
|
export type { JudgeVerdict };
|
|
@@ -29,31 +27,50 @@ export async function runJudgeGates(input: {
|
|
|
29
27
|
readonly receipt?: unknown;
|
|
30
28
|
readonly runId?: string;
|
|
31
29
|
readonly runDirectory?: string;
|
|
30
|
+
readonly terminal?: TerminalResult;
|
|
32
31
|
} | void>;
|
|
33
32
|
}): Promise<{
|
|
34
|
-
readonly status:
|
|
33
|
+
readonly status: ReviewQueueWord | "needs_reask";
|
|
35
34
|
readonly passes: readonly {
|
|
36
35
|
readonly subject: GatekeeperSubject;
|
|
37
|
-
readonly status:
|
|
36
|
+
readonly status: ReviewQueueWord | "needs_reask";
|
|
38
37
|
readonly receipt: unknown;
|
|
39
38
|
readonly runId?: string;
|
|
40
39
|
readonly runDirectory?: string;
|
|
40
|
+
readonly terminal?: TerminalResult;
|
|
41
41
|
}[];
|
|
42
42
|
}> {
|
|
43
43
|
const passes: {
|
|
44
44
|
subject: GatekeeperSubject;
|
|
45
|
-
status:
|
|
45
|
+
status: ReviewQueueWord | "needs_reask";
|
|
46
46
|
receipt: unknown;
|
|
47
47
|
runId?: string;
|
|
48
48
|
runDirectory?: string;
|
|
49
|
+
terminal?: TerminalResult;
|
|
49
50
|
}[] = [];
|
|
50
51
|
for (const subject of JUDGE_GATES) {
|
|
51
52
|
if (await input.gateAlreadyConverged(subject)) continue;
|
|
52
53
|
const pass = await input.runGate(subject);
|
|
53
|
-
const
|
|
54
|
-
if (pass === undefined || (
|
|
54
|
+
const received = pass?.status;
|
|
55
|
+
if (pass === undefined || (
|
|
56
|
+
typeof received !== "string" || (!REVIEW_QUEUE_STATUSES.has(received) && received !== "needs_reask")
|
|
57
|
+
)) {
|
|
55
58
|
throw new Error("judge gate returned no conclusion");
|
|
56
59
|
}
|
|
60
|
+
const status = received as ReviewQueueWord | "needs_reask";
|
|
61
|
+
if (status === "needs_reask") {
|
|
62
|
+
return {
|
|
63
|
+
status,
|
|
64
|
+
passes: [{
|
|
65
|
+
subject,
|
|
66
|
+
status,
|
|
67
|
+
receipt: pass.receipt,
|
|
68
|
+
...(pass.runId === undefined ? {} : { runId: pass.runId }),
|
|
69
|
+
...(pass.runDirectory === undefined ? {} : { runDirectory: pass.runDirectory }),
|
|
70
|
+
...(pass.terminal === undefined ? {} : { terminal: pass.terminal }),
|
|
71
|
+
}],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
57
74
|
passes.push({
|
|
58
75
|
subject,
|
|
59
76
|
status,
|
|
@@ -90,18 +107,8 @@ export function createJudgeRoleRuntime(
|
|
|
90
107
|
if (soul.length === 0) throw new Error("Judge soul is empty");
|
|
91
108
|
if (!lifecycleRegistered) {
|
|
92
109
|
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
|
-
},
|
|
110
|
+
registerFiledSubmissionTool(pi, roleSubmissionDeclaration("judge"), {
|
|
111
|
+
readyError: () => (soul === undefined ? "大理寺职分未装载" : undefined),
|
|
105
112
|
});
|
|
106
113
|
pi.on("before_agent_start", (event) => {
|
|
107
114
|
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("校书郎未激活");
|
|
@@ -59,7 +59,10 @@ export {
|
|
|
59
59
|
export { createNativeNavigatorSessionFactory };
|
|
60
60
|
export { resolveNavigatorSeatSelection };
|
|
61
61
|
import { issueRoot, subjectPath } from "./work-subject-identity.ts";
|
|
62
|
-
import {
|
|
62
|
+
import {
|
|
63
|
+
createReceiptDeliveryPolicy,
|
|
64
|
+
NO_RECEIPT_LIFECYCLE_ENTRY_TYPE,
|
|
65
|
+
} from "./receipt-delivery-policy.ts";
|
|
63
66
|
import { navigatorProseFromUnknown } from "./package-contracts/navigator-output.ts";
|
|
64
67
|
import { persistNavigatorWorkBase } from "./navigator-work-base.ts";
|
|
65
68
|
|
|
@@ -156,6 +159,8 @@ export type NavigatorAttendanceOptions = {
|
|
|
156
159
|
contextError?: unknown;
|
|
157
160
|
/** Exact principal owned by shared role lifecycle; attendance never overrides it. */
|
|
158
161
|
invocationId?: string;
|
|
162
|
+
/** Effective ceiling already resolved for this turn (#1132). */
|
|
163
|
+
deliveryRequestLimit?: number;
|
|
159
164
|
onEvent: (event: NavigatorEvent, report: NavigatorReport) => void | Promise<void>;
|
|
160
165
|
};
|
|
161
166
|
|
|
@@ -416,11 +421,12 @@ export function createNavigatorAttendance(options: NavigatorAttendanceOptions) {
|
|
|
416
421
|
try {
|
|
417
422
|
try {
|
|
418
423
|
if (disposed) throw navigatorUnavailableError("session", new Error("Navigator attendance was disposed"));
|
|
419
|
-
|
|
424
|
+
// #1132: the ceiling this turn already resolved. Absent = package default.
|
|
425
|
+
const delivery = createReceiptDeliveryPolicy(options.deliveryRequestLimit);
|
|
420
426
|
// Production prose arrives only via nested summon → prepare tool.execute
|
|
421
427
|
// (navigator-public-session). No assistant-entry harvest — entries() is
|
|
422
428
|
// archivist custom-only on the wired factory (#959).
|
|
423
|
-
const promptAllowingRejectedPrepare = async (text: string
|
|
429
|
+
const promptAllowingRejectedPrepare = async (text: string) => {
|
|
424
430
|
await persistNavigatorWorkBase(activeSession.recordPointer(), { subject, authority });
|
|
425
431
|
const entryStart = activeSession.entries().length;
|
|
426
432
|
prepareBatchRejected = false;
|
|
@@ -440,31 +446,30 @@ export function createNavigatorAttendance(options: NavigatorAttendanceOptions) {
|
|
|
440
446
|
// ineligible for publication before the correction turn starts.
|
|
441
447
|
output = undefined;
|
|
442
448
|
prepareBatchRejected = true;
|
|
449
|
+
// The correction prompt below is the one spend for this rejection.
|
|
443
450
|
delivery.recordRejected(rejectedReason);
|
|
444
451
|
return;
|
|
445
452
|
}
|
|
446
453
|
if (promptFailure !== undefined) throw promptFailure;
|
|
447
454
|
const sessionNoReceipt = activeSession.noReceipt?.();
|
|
448
455
|
if (sessionNoReceipt !== undefined) {
|
|
449
|
-
// This session already settled without an accepted receipt
|
|
450
|
-
//
|
|
451
|
-
//
|
|
456
|
+
// This session already settled without an accepted receipt. Keep the
|
|
457
|
+
// larger issued count and stop; a nested zero must not wipe prompts
|
|
458
|
+
// this layer already sent (#675 / #1132).
|
|
452
459
|
delivery.recordNestedNoReceipt(sessionNoReceipt);
|
|
453
460
|
return;
|
|
454
461
|
}
|
|
455
|
-
if (deliveryRequest && output === undefined) delivery.recordDeliveryRequest();
|
|
456
462
|
};
|
|
457
|
-
await promptAllowingRejectedPrepare(request
|
|
463
|
+
await promptAllowingRejectedPrepare(request);
|
|
458
464
|
// Bound output only: correction after rejected prepare. Early ready-wait
|
|
459
465
|
// does not 催交 final advice (owner: prepare then wait for settlement feed).
|
|
460
466
|
if (boundSettlement !== undefined) {
|
|
461
467
|
while (output === undefined && prepareBatchRejected && delivery.nextAction() === "request-delivery") {
|
|
462
|
-
|
|
468
|
+
delivery.recordDeliveryRequest();
|
|
469
|
+
await promptAllowingRejectedPrepare(JSON.stringify(delivery.deliveryState()));
|
|
463
470
|
}
|
|
464
471
|
if (output === undefined && delivery.nextAction() === "request-delivery") {
|
|
465
|
-
|
|
466
|
-
delivery.recordDeliveryRequest();
|
|
467
|
-
}
|
|
472
|
+
delivery.closeBudget();
|
|
468
473
|
}
|
|
469
474
|
if (output === undefined && delivery.nextAction() === "no-receipt" && activeSession.providerFailure?.() === undefined) {
|
|
470
475
|
const facts = delivery.facts({ runPointer: activeSession.recordPointer(), attemptPointer: invocationId });
|
|
@@ -214,6 +214,37 @@ export type PackagedRoleTerminalMessage = {
|
|
|
214
214
|
readonly details?: unknown;
|
|
215
215
|
};
|
|
216
216
|
|
|
217
|
+
/**
|
|
218
|
+
* Durable rejection of a packaged output tool.
|
|
219
|
+
* Unknown tools and infrastructure failures are not receipt rejections.
|
|
220
|
+
* Empty text is still a rejection. Undefined means "not this fact".
|
|
221
|
+
*/
|
|
222
|
+
export function packagedRoleOutputRejectionReason(message: {
|
|
223
|
+
readonly toolName?: unknown;
|
|
224
|
+
readonly isError?: unknown;
|
|
225
|
+
readonly details?: unknown;
|
|
226
|
+
readonly content?: unknown;
|
|
227
|
+
}): string | undefined {
|
|
228
|
+
if (typeof message.toolName !== "string") return undefined;
|
|
229
|
+
if (!PACKAGED_ROLE_OUTPUT_TOOLS.has(message.toolName) && message.toolName !== "ak_submission_output") {
|
|
230
|
+
return undefined;
|
|
231
|
+
}
|
|
232
|
+
if (message.isError !== true) return undefined;
|
|
233
|
+
if (classifyPackagedRoleTerminalResult(message).kind !== "nonterminal") return undefined;
|
|
234
|
+
const content = message.content;
|
|
235
|
+
if (typeof content === "string") return content.trim();
|
|
236
|
+
if (!Array.isArray(content)) return "";
|
|
237
|
+
return content.map((part) => {
|
|
238
|
+
if (
|
|
239
|
+
isRecord(part) && part.type === "text"
|
|
240
|
+
&& typeof part.text === "string"
|
|
241
|
+
) {
|
|
242
|
+
return part.text;
|
|
243
|
+
}
|
|
244
|
+
return "";
|
|
245
|
+
}).join("").trim();
|
|
246
|
+
}
|
|
247
|
+
|
|
217
248
|
/**
|
|
218
249
|
* One shared typed terminal classifier for packaged role output toolResults.
|
|
219
250
|
* Consumed by lifecycle principal completion, publicNavigatorSettlement, and
|
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>;
|
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
|
+
);
|
package/src/pi/adapter.ts
CHANGED
|
@@ -18,6 +18,12 @@ import type {
|
|
|
18
18
|
import { createOAuthKeepalive, type OAuthKeepaliveOptions } from "../oauth-keepalive.ts";
|
|
19
19
|
import { createRoleRuntimeExtension, type RoleRuntimeDependencies } from "../role-runtime.ts";
|
|
20
20
|
import { renderAgentStartMaterials } from "../agent-start-materials.ts";
|
|
21
|
+
import { projectCorrectableExecuteRejection } from "../submission-correctable-error.ts";
|
|
22
|
+
import {
|
|
23
|
+
WorkerCommitReminderError,
|
|
24
|
+
WorkerPrefixReminderError,
|
|
25
|
+
WorkerUnfinishedReasonReminderError,
|
|
26
|
+
} from "../submission-errors.ts";
|
|
21
27
|
import { readUserDialogueStdin } from "../user-dialogue-stdin.ts";
|
|
22
28
|
|
|
23
29
|
export type PiRoleHostAdapter = RoleEnvelopeHost;
|
|
@@ -106,14 +112,33 @@ function toPiToolDefinition<S extends TSchema, D>(
|
|
|
106
112
|
description: tool.description,
|
|
107
113
|
...(tool.promptSnippet === undefined ? {} : { promptSnippet: tool.promptSnippet }),
|
|
108
114
|
parameters: tool.parameters,
|
|
109
|
-
execute: async (toolCallId, params, signal, update, context) =>
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
execute: async (toolCallId, params, signal, update, context) => {
|
|
116
|
+
try {
|
|
117
|
+
return toPiResult(await tool.execute(
|
|
118
|
+
toolCallId,
|
|
119
|
+
params as Static<S>,
|
|
120
|
+
signal,
|
|
121
|
+
update === undefined ? undefined : (result) => update(toPiResult(result)),
|
|
122
|
+
projectContext(context),
|
|
123
|
+
));
|
|
124
|
+
} catch (error) {
|
|
125
|
+
// The worker gate owns these one-shot reminders. Returning them as
|
|
126
|
+
// isError keeps the code on the tool result so催交 can record the
|
|
127
|
+
// fact without spending the reminder itself. Other correctable
|
|
128
|
+
// errors stay native throws.
|
|
129
|
+
if (!(
|
|
130
|
+
error instanceof WorkerUnfinishedReasonReminderError
|
|
131
|
+
|| error instanceof WorkerCommitReminderError
|
|
132
|
+
|| error instanceof WorkerPrefixReminderError
|
|
133
|
+
)) throw error;
|
|
134
|
+
const projected = projectCorrectableExecuteRejection(error);
|
|
135
|
+
return {
|
|
136
|
+
content: [{ type: "text" as const, text: projected.diagnostic }],
|
|
137
|
+
details: projected.details as D,
|
|
138
|
+
isError: true as const,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
},
|
|
117
142
|
};
|
|
118
143
|
}
|
|
119
144
|
|