@akagilnc/pi-workflow-roles 0.1.5153 → 0.1.5196
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 -2
- package/README.zh-CN.md +2 -2
- package/dist/acp-host/production-host.js +13086 -13034
- package/dist/archivist-record-entry.js +4 -20
- package/dist/archivist-record-pointer.js +28 -0
- package/dist/audit-escalation.js +3 -119
- package/dist/auditor-soul.js +32 -0
- package/dist/doctor-auditor.js +26 -0
- package/dist/headless-host/production-host.js +11218 -11166
- package/dist/judge-role.js +73 -0
- package/dist/migrate-book-topology.js +8 -0
- package/dist/package-contracts/judge-output.js +1 -18
- package/dist/package-contracts/terminating-tools.js +2 -2
- package/dist/public-cli/cli.js +2 -2
- package/dist/public-cli/countersign-run.js +11 -0
- package/dist/public-cli/instruction-seat-run.js +428 -48
- package/dist/public-cli/invocation.js +10 -5
- package/dist/public-cli/main.js +10049 -8911
- package/dist/public-cli/settlement.js +28 -8
- package/dist/public-role-summons.js +6 -4
- package/dist/submission-errors.js +1 -1
- package/dist/submission-gate.js +165 -0
- package/dist/submission-ledger.js +0 -27
- package/dist/worker-submission-contracts.js +8 -0
- package/package.json +1 -1
- package/src/archivist-record-entry.ts +5 -49
- package/src/archivist-record-pointer.ts +49 -0
- package/src/audit-escalation.ts +4 -217
- package/src/auditor-soul.ts +33 -0
- package/src/doctor-role.ts +11 -5
- package/src/gatekeeper-role.ts +2 -2
- package/src/host-contracts.ts +0 -25
- package/src/judge-role.ts +63 -90
- package/src/package-contracts/judge-output.ts +0 -17
- package/src/package-contracts/terminating-tools.ts +0 -2
- package/src/pi/adapter.ts +1 -33
- package/src/public-cli/cli.ts +2 -2
- package/src/public-cli/countersign-run.ts +11 -0
- package/src/public-cli/instruction-seat-run.ts +433 -16
- package/src/public-cli/invocation.ts +9 -3
- package/src/public-cli/post-admission.ts +0 -1
- package/src/public-cli/settlement.ts +32 -8
- package/src/public-role-summons.ts +9 -6
- package/src/role-envelope.ts +0 -32
- package/src/role-runtime-dependencies.ts +0 -4
- package/src/role-runtime.ts +15 -218
- package/src/submission-errors.ts +1 -1
- package/src/submission-gate.ts +46 -10
- package/src/submission-ledger.ts +0 -27
- package/src/worker-role.ts +23 -102
- package/src/worker-submission-contracts.ts +8 -0
- package/src/worker-submission-gates.ts +2 -2
package/src/submission-gate.ts
CHANGED
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
* Owns officer-pointer book + host abort/non-pass faces + review queue loop.
|
|
4
4
|
* Role modules only project via projectGatekeeperRun / runGatekeeper — no book, no catch.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* converged →
|
|
9
|
-
* continue → raw officer receipt
|
|
10
|
-
* escalate →
|
|
6
|
+
* Public continuation after submission settlement (#753 / #756 / #750):
|
|
7
|
+
* accepted submission → summon officer → read conclusion field
|
|
8
|
+
* converged → continue remaining review and settle
|
|
9
|
+
* continue → raw officer receipt; caller resumes the submitted seat for revision
|
|
10
|
+
* escalate → return the officer run so the caller can resume that officer directly
|
|
11
11
|
* unrecognized status → resume officer with plain-language re-ask (no round cap)
|
|
12
12
|
* transport / no_receipt → present honestly
|
|
13
13
|
* Four pairs: countersign↔notary, judge↔auditor, worker↔inspector, secretariat↔countersign (#969).
|
|
14
14
|
* Code does not judge content, map next-step for parent, or label unreadable/unusable.
|
|
15
15
|
*/
|
|
16
16
|
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
17
|
-
import { bookDirectOfficerRunPointer } from "./archivist-record-
|
|
17
|
+
import { bookDirectOfficerRunPointer } from "./archivist-record-pointer.ts";
|
|
18
18
|
import type { HostContext, RoleTurnHost } from "./host-contracts.ts";
|
|
19
19
|
import {
|
|
20
20
|
GatekeeperDecisionError,
|
|
@@ -27,7 +27,31 @@ import {
|
|
|
27
27
|
type GateOfficerSummon,
|
|
28
28
|
} from "./gatekeeper-role.ts";
|
|
29
29
|
import type { PublicSummonResult } from "./public-role-summons.ts";
|
|
30
|
+
import type { TerminalResult } from "./public-cli/terminal.ts";
|
|
30
31
|
|
|
32
|
+
/** Queue word of the latest this-terminal payload. History does not outrank it. */
|
|
33
|
+
export function latestQueueStatus(terminal: TerminalResult | undefined): string | undefined {
|
|
34
|
+
const outcome = terminal?.roleOutcome;
|
|
35
|
+
if (outcome === undefined) return undefined;
|
|
36
|
+
if (outcome.kind === "audit_escalation") return "escalate";
|
|
37
|
+
if (outcome.kind !== "accepted") return undefined;
|
|
38
|
+
const latest = outcome.payloads?.[outcome.payloads.length - 1];
|
|
39
|
+
if (latest !== null && typeof latest === "object" && !Array.isArray(latest)) {
|
|
40
|
+
const status = (latest as { status?: unknown }).status;
|
|
41
|
+
if (typeof status === "string" && status.trim() !== "") return status;
|
|
42
|
+
}
|
|
43
|
+
return typeof outcome.status === "string" && outcome.status.trim() !== ""
|
|
44
|
+
? outcome.status
|
|
45
|
+
: undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function latestQueuePayload(terminal: TerminalResult | undefined): unknown {
|
|
49
|
+
const outcome = terminal?.roleOutcome;
|
|
50
|
+
if (outcome === undefined) return undefined;
|
|
51
|
+
if (outcome.kind !== "accepted" && outcome.kind !== "audit_escalation") return undefined;
|
|
52
|
+
const payloads = outcome.payloads ?? [];
|
|
53
|
+
return payloads.length === 0 ? undefined : payloads[payloads.length - 1];
|
|
54
|
+
}
|
|
31
55
|
import { sessionFileFromPublicSummon } from "./session-assistant-usage.ts";
|
|
32
56
|
|
|
33
57
|
/**
|
|
@@ -38,6 +62,7 @@ export function createDefaultGateOfficerSummon(options: {
|
|
|
38
62
|
readonly cwd: string;
|
|
39
63
|
readonly home?: string;
|
|
40
64
|
readonly packageRoot?: string;
|
|
65
|
+
readonly io?: import("./public-cli/cli-io.ts").CliIo;
|
|
41
66
|
readonly roleTurnHost?: RoleTurnHost;
|
|
42
67
|
/** Composition-root adapters for nested court stations (tests / #969). */
|
|
43
68
|
readonly hostAdapters?: readonly import("./public-cli/role-turn-host-resolution.ts").NamedRoleTurnHostAdapter[];
|
|
@@ -54,6 +79,7 @@ export function createDefaultGateOfficerSummon(options: {
|
|
|
54
79
|
...(submission === undefined ? {} : { submission }),
|
|
55
80
|
...(options.home === undefined ? {} : { home: options.home }),
|
|
56
81
|
...(options.packageRoot === undefined ? {} : { packageRoot: options.packageRoot }),
|
|
82
|
+
...(options.io === undefined ? {} : { io: options.io }),
|
|
57
83
|
...(options.roleTurnHost === undefined ? {} : { roleTurnHost: options.roleTurnHost }),
|
|
58
84
|
...(options.hostAdapters === undefined ? {} : { hostAdapters: options.hostAdapters }),
|
|
59
85
|
...(options.createRunId === undefined ? {} : { createRunId: options.createRunId }),
|
|
@@ -103,10 +129,11 @@ function bookDirectOfficerPointer(
|
|
|
103
129
|
* public terminal without a second authority.
|
|
104
130
|
*/
|
|
105
131
|
export type SubmissionGateOutcome = {
|
|
106
|
-
readonly status: "converged" | "continue";
|
|
132
|
+
readonly status: "converged" | "continue" | "escalate";
|
|
107
133
|
readonly officer: GateOfficer;
|
|
108
134
|
readonly receipt: unknown;
|
|
109
135
|
readonly runId?: string;
|
|
136
|
+
readonly runDirectory?: string;
|
|
110
137
|
};
|
|
111
138
|
|
|
112
139
|
/**
|
|
@@ -189,10 +216,19 @@ export async function requireSubmissionGate(options: {
|
|
|
189
216
|
});
|
|
190
217
|
options.hostActions.failInfrastructure(failure, options.context, options.toolCallId);
|
|
191
218
|
}
|
|
192
|
-
// Escalation ends the parent without a correctable tool error or resubmission.
|
|
193
|
-
// Each caller projects the existing audit_escalation terminal.
|
|
194
219
|
if (gatekeeper.status === "escalate") {
|
|
195
|
-
|
|
220
|
+
return {
|
|
221
|
+
status: "escalate",
|
|
222
|
+
officer: projected.officer,
|
|
223
|
+
receipt: gatekeeper.receipt,
|
|
224
|
+
...(typeof gatekeeper.runId === "string" && gatekeeper.runId.trim() !== ""
|
|
225
|
+
? { runId: gatekeeper.runId }
|
|
226
|
+
: {}),
|
|
227
|
+
...(typeof projected.summoned?.runDirectory === "string"
|
|
228
|
+
&& projected.summoned.runDirectory.trim() !== ""
|
|
229
|
+
? { runDirectory: projected.summoned.runDirectory }
|
|
230
|
+
: {}),
|
|
231
|
+
};
|
|
196
232
|
}
|
|
197
233
|
// no_receipt: keep the lifecycle failure channel; continue is an ordinary
|
|
198
234
|
// nonterminal tool result above, not an exception or correctable rejection.
|
package/src/submission-ledger.ts
CHANGED
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
type HostToolResult,
|
|
12
12
|
type RoleHost,
|
|
13
13
|
} from "./host-contracts.ts";
|
|
14
|
-
import { isAuditEscalationProjection } from "./audit-escalation.ts";
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
import { runIdFromRunDirectory } from "./run-terminal-artifacts.ts";
|
|
@@ -730,32 +729,6 @@ export function createSubmissionLedgerHost(
|
|
|
730
729
|
}
|
|
731
730
|
// #836: ledger authority is the LLM tool-call params as-is (角色原话), never result.details.
|
|
732
731
|
// Machine facts on result.details stay on the tool-result face returned to the model.
|
|
733
|
-
if (isAuditEscalationProjection(result.details) || isAuditEscalationProjection(params)) {
|
|
734
|
-
const audit = isAuditEscalationProjection(result.details)
|
|
735
|
-
&& typeof result.details.audit === "object"
|
|
736
|
-
&& result.details.audit !== null
|
|
737
|
-
? result.details.audit as Record<string, unknown>
|
|
738
|
-
: undefined;
|
|
739
|
-
const closed: ClosedSubmission = {
|
|
740
|
-
role,
|
|
741
|
-
kind: "audit_escalation",
|
|
742
|
-
accepted: params,
|
|
743
|
-
};
|
|
744
|
-
append({
|
|
745
|
-
type: "outcome",
|
|
746
|
-
attemptId,
|
|
747
|
-
toolCallId,
|
|
748
|
-
outcome: "audit-escalation",
|
|
749
|
-
role,
|
|
750
|
-
accepted: params,
|
|
751
|
-
...(audit !== undefined && (Object.hasOwn(audit, "receipt") || Object.hasOwn(audit, "conflicts"))
|
|
752
|
-
? { auditReceipt: Object.hasOwn(audit, "receipt") ? audit.receipt : audit.conflicts }
|
|
753
|
-
: {}),
|
|
754
|
-
...(audit !== undefined && Object.hasOwn(audit, "officer") ? { auditOfficer: audit.officer } : {}),
|
|
755
|
-
});
|
|
756
|
-
await projectClosure(closed, context);
|
|
757
|
-
return result;
|
|
758
|
-
}
|
|
759
732
|
// A continuing gate leaves the candidate recorded but has not accepted it.
|
|
760
733
|
if (result.terminate === false) return result;
|
|
761
734
|
const closed: ClosedSubmission = {
|
package/src/worker-role.ts
CHANGED
|
@@ -3,9 +3,6 @@ import { Type, type Static } from "typebox";
|
|
|
3
3
|
import { openToolObjectFromUnion } from "./open-tool-schema.ts";
|
|
4
4
|
import { withTerminatingOutputDeclarations } from "./package-contracts/terminating-infrastructure.ts";
|
|
5
5
|
|
|
6
|
-
import { readableGateItem } from "./readable-gate-item.ts";
|
|
7
|
-
import { projectGatekeeperEscalation } from "./audit-escalation.ts";
|
|
8
|
-
import { GatekeeperDecisionError, ParentQueueReaskError, unreadableDiscriminatorNotice } from "./submission-errors.ts";
|
|
9
6
|
import {
|
|
10
7
|
CODER_OUTPUT_TOOL_NAME,
|
|
11
8
|
FIXER_OUTPUT_TOOL_NAME,
|
|
@@ -23,7 +20,6 @@ import {
|
|
|
23
20
|
} from "./package-contracts/fixer-packet.ts";
|
|
24
21
|
import {
|
|
25
22
|
createWorkerSubmissionGate,
|
|
26
|
-
WORKER_DONE_STATUSES,
|
|
27
23
|
WorkerCommitReminderError,
|
|
28
24
|
WorkerPrefixReminderError,
|
|
29
25
|
WorkerUnfinishedReasonReminderError,
|
|
@@ -127,15 +123,6 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
|
|
127
123
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
128
124
|
}
|
|
129
125
|
|
|
130
|
-
/** Routing words shared by Coder and Fixer; provider schemas remain open. */
|
|
131
|
-
const WORKER_ROUTING_STATUSES = new Set([
|
|
132
|
-
"planned",
|
|
133
|
-
"completed",
|
|
134
|
-
"refused",
|
|
135
|
-
"partially_completed",
|
|
136
|
-
"unfinished",
|
|
137
|
-
]);
|
|
138
|
-
|
|
139
126
|
/** Read only the field that selects the worker's next package-owned path. */
|
|
140
127
|
function workerStatusOf(output: WorkerOutput): string | undefined {
|
|
141
128
|
return isRecord(output) && typeof output.status === "string"
|
|
@@ -143,14 +130,6 @@ function workerStatusOf(output: WorkerOutput): string | undefined {
|
|
|
143
130
|
: undefined;
|
|
144
131
|
}
|
|
145
132
|
|
|
146
|
-
function requireReadableWorkerStatus(output: WorkerOutput): string {
|
|
147
|
-
const status = workerStatusOf(output);
|
|
148
|
-
if (status === undefined || !WORKER_ROUTING_STATUSES.has(status)) {
|
|
149
|
-
throw new ParentQueueReaskError(unreadableDiscriminatorNotice("status", isRecord(output) ? output.status : undefined));
|
|
150
|
-
}
|
|
151
|
-
return status;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
133
|
function deepFreeze<T>(value: T): T {
|
|
155
134
|
if (typeof value !== "object" || value === null || Object.isFrozen(value)) return value;
|
|
156
135
|
for (const child of Object.values(value)) deepFreeze(child);
|
|
@@ -262,47 +241,18 @@ export function createFixerRoleRuntime(
|
|
|
262
241
|
throw new Error("修内司修理包与阶段未装载");
|
|
263
242
|
}
|
|
264
243
|
const output = deepFreeze(validateFixerOutput(parameters, phase));
|
|
265
|
-
const status =
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
try {
|
|
276
|
-
pass = WORKER_DONE_STATUSES.has(status)
|
|
277
|
-
? await pi.requireSubmissionGate!({
|
|
278
|
-
context: ctx,
|
|
279
|
-
subject: { kind: "worker_completion" },
|
|
280
|
-
...(_signal === undefined ? {} : { signal: _signal }),
|
|
281
|
-
hostActions,
|
|
282
|
-
toolCallId,
|
|
283
|
-
// #879: this-turn typed payload — identity-bound at submit site.
|
|
284
|
-
submission: output,
|
|
285
|
-
})
|
|
286
|
-
: undefined;
|
|
287
|
-
} catch (error) {
|
|
288
|
-
if (error instanceof GatekeeperDecisionError && error.result.status === "escalate") {
|
|
289
|
-
return projectGatekeeperEscalation(error.result, output);
|
|
290
|
-
}
|
|
291
|
-
throw error;
|
|
292
|
-
}
|
|
293
|
-
if (pass?.status === "continue") {
|
|
294
|
-
return {
|
|
295
|
-
content: [{ type: "text" as const, text: readableGateItem(pass.receipt) }],
|
|
296
|
-
details: output,
|
|
297
|
-
terminate: false,
|
|
298
|
-
};
|
|
244
|
+
const status = workerStatusOf(output);
|
|
245
|
+
if (status !== undefined) {
|
|
246
|
+
assertAcceptableThroughHost(
|
|
247
|
+
submissionGate,
|
|
248
|
+
status,
|
|
249
|
+
output,
|
|
250
|
+
hostActions,
|
|
251
|
+
ctx,
|
|
252
|
+
toolCallId,
|
|
253
|
+
);
|
|
299
254
|
}
|
|
300
|
-
|
|
301
|
-
return {
|
|
302
|
-
content: pass === undefined ? [] : [{ type: "text" as const, text: readableGateItem(pass.receipt) }],
|
|
303
|
-
details: acceptedDetails,
|
|
304
|
-
terminate: true as const,
|
|
305
|
-
};
|
|
255
|
+
return { content: [], details: output, terminate: true as const };
|
|
306
256
|
},
|
|
307
257
|
});
|
|
308
258
|
pi.on("tool_call", (event) => {
|
|
@@ -389,49 +339,20 @@ export function createCoderRoleRuntime(
|
|
|
389
339
|
throw new Error("将作监任务与阶段未装载");
|
|
390
340
|
}
|
|
391
341
|
const output = validateWorkerOutput(parameters, phase, "Coder");
|
|
392
|
-
const status =
|
|
342
|
+
const status = workerStatusOf(output);
|
|
393
343
|
// #836: skill-expansion evidence rejection deleted (陛下「2.4/5 删」).
|
|
394
|
-
//
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
try {
|
|
405
|
-
pass = WORKER_DONE_STATUSES.has(status)
|
|
406
|
-
? await pi.requireSubmissionGate!({
|
|
407
|
-
context: ctx,
|
|
408
|
-
subject: { kind: "worker_completion" },
|
|
409
|
-
...(_signal === undefined ? {} : { signal: _signal }),
|
|
410
|
-
hostActions,
|
|
411
|
-
toolCallId,
|
|
412
|
-
// #879: this-turn typed payload — identity-bound at submit site.
|
|
413
|
-
submission: output,
|
|
414
|
-
})
|
|
415
|
-
: undefined;
|
|
416
|
-
} catch (error) {
|
|
417
|
-
if (error instanceof GatekeeperDecisionError && error.result.status === "escalate") {
|
|
418
|
-
return projectGatekeeperEscalation(error.result, output);
|
|
419
|
-
}
|
|
420
|
-
throw error;
|
|
421
|
-
}
|
|
422
|
-
if (pass?.status === "continue") {
|
|
423
|
-
return {
|
|
424
|
-
content: [{ type: "text" as const, text: readableGateItem(pass.receipt) }],
|
|
425
|
-
details: output,
|
|
426
|
-
terminate: false,
|
|
427
|
-
};
|
|
344
|
+
// Skill still ships with the package (ADR 0052); code no longer refuses on it.
|
|
345
|
+
if (status !== undefined) {
|
|
346
|
+
assertAcceptableThroughHost(
|
|
347
|
+
submissionGate,
|
|
348
|
+
status,
|
|
349
|
+
output,
|
|
350
|
+
hostActions,
|
|
351
|
+
ctx,
|
|
352
|
+
toolCallId,
|
|
353
|
+
);
|
|
428
354
|
}
|
|
429
|
-
|
|
430
|
-
return {
|
|
431
|
-
content: pass === undefined ? [] : [{ type: "text" as const, text: readableGateItem(pass.receipt) }],
|
|
432
|
-
details: acceptedDetails,
|
|
433
|
-
terminate: true as const,
|
|
434
|
-
};
|
|
355
|
+
return { content: [], details: output, terminate: true as const };
|
|
435
356
|
},
|
|
436
357
|
});
|
|
437
358
|
pi.on("before_agent_start", (event, ctx) => {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Statuses that enter the worker officer submission gate (ADR 0066):
|
|
3
|
+
* completed/partially_completed enter gate ①; planned/refused/unfinished do not.
|
|
4
|
+
*/
|
|
5
|
+
export const WORKER_DONE_STATUSES: ReadonlySet<string> = new Set([
|
|
6
|
+
"completed",
|
|
7
|
+
"partially_completed",
|
|
8
|
+
]);
|
|
@@ -15,16 +15,16 @@ import {
|
|
|
15
15
|
WorkerPrefixReminderError,
|
|
16
16
|
WorkerUnfinishedReasonReminderError,
|
|
17
17
|
} from "./submission-errors.ts";
|
|
18
|
+
import { WORKER_DONE_STATUSES } from "./worker-submission-contracts.ts";
|
|
18
19
|
|
|
19
20
|
export { WorkerCommitReminderError, WorkerPrefixReminderError, WorkerUnfinishedReasonReminderError } from "./submission-errors.ts";
|
|
21
|
+
export { WORKER_DONE_STATUSES } from "./worker-submission-contracts.ts";
|
|
20
22
|
|
|
21
23
|
export const WORKER_SUBMISSION_GATE_RECORD_KIND = WORKER_SUBMISSION_GATE_KIND;
|
|
22
24
|
export const WORKER_COMMIT_BASELINE_ENTRY_TYPE = "commit-baseline";
|
|
23
25
|
export const WORKER_COMMIT_REMINDER_BOUNCE_ENTRY_TYPE = "commit-reminder-bounce";
|
|
24
26
|
export const WORKER_PREFIX_REMINDER_BOUNCE_ENTRY_TYPE = "prefix-reminder-bounce";
|
|
25
27
|
|
|
26
|
-
/** Statuses that enter the officer submission gate (ADR 0066: completed/partially_completed 进闸①;planned/refused/unfinished 零 commit 合法). */
|
|
27
|
-
export const WORKER_DONE_STATUSES: ReadonlySet<string> = new Set(["completed", "partially_completed"]);
|
|
28
28
|
/** Historical package hook ownership marker — uninstall criterion only. */
|
|
29
29
|
const HOOK_MARKER = "ak-roles: worker-submission-gates reference-transaction";
|
|
30
30
|
const HOOKS_DIR = "ak-roles-hooks";
|