@akagilnc/pi-workflow-roles 0.1.5368 → 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 +1192 -1195
- package/dist/activation-ledger-git.js +2 -2
- package/dist/activation-ledger-topology.js +1 -7
- package/dist/analyst-entry.js +4 -8
- package/dist/analyst-gate-cycles-read.js +3 -11
- package/dist/analyst-index.js +3 -9
- package/dist/analyst-ledger.js +1 -11
- package/dist/analyst-metric-families/acceptance-success-rework.js +1 -3
- package/dist/analyst-metric-families/round-timeline.js +1 -3
- package/dist/analyst-page.js +2 -2
- package/dist/archivist-record-topology.js +2 -2
- package/dist/audit-escalation.js +2 -1
- package/dist/auditor-soul.js +2 -1
- package/dist/collector-config.js +6 -8
- package/dist/collector-tool-schemas.js +18 -0
- package/dist/compliance-transport.js +2 -1
- package/dist/countersign-contracts.js +2 -1
- package/dist/diarist-contracts.js +29 -2
- package/dist/doctor-contracts.js +1 -3
- package/dist/doctor-evidence.js +7 -8
- package/dist/dossier-resolution.js +1 -3
- package/dist/engine-detour-usage.js +1 -3
- package/dist/filed-submission.js +28 -0
- package/dist/gatekeeper-role.js +8 -19
- package/dist/gleaner-left-contracts.js +18 -1
- package/dist/headless-host/description.js +14 -17
- package/dist/headless-host/production-host.js +1210 -1215
- package/dist/host-session-record.js +3 -2
- package/dist/inspector-contracts.js +2 -1
- package/dist/judge-role.js +8 -16
- package/dist/ledger-session-read.js +1 -3
- package/dist/merger-contracts.js +9 -9
- package/dist/migrate-book-topology.js +610 -321
- package/dist/navigator-attendance.js +9 -11
- package/dist/navigator-invocation-identity.js +3 -2
- package/dist/navigator-public-session.js +3 -5
- package/dist/navigator-session-contracts.js +8 -10
- package/dist/navigator-work-base.js +5 -8
- package/dist/notary-contracts.js +3 -5
- package/dist/package-contracts/auditor-output.js +1 -3
- package/dist/package-contracts/fixer-packet.js +3 -6
- package/dist/package-contracts/gatekeeper-output.js +1 -3
- package/dist/package-contracts/navigator-output.js +8 -8
- package/dist/package-contracts/reviewer-output.js +16 -0
- package/dist/package-contracts/terminating-infrastructure.js +5 -9
- package/dist/package-contracts/terminating-tools.js +4 -3
- package/dist/package-contracts/worker-output.js +18 -2
- package/dist/public-cli/analyst-run.js +3 -2
- package/dist/public-cli/auto-resume.js +3 -8
- package/dist/public-cli/cli.js +9 -8
- package/dist/public-cli/config.js +8 -11
- package/dist/public-cli/countersign-run.js +1 -3
- package/dist/public-cli/host-providers.js +7 -14
- package/dist/public-cli/instruction-seat-run.js +12 -14
- package/dist/public-cli/invocation.js +9 -8
- package/dist/public-cli/main.js +1820 -1599
- package/dist/public-cli/post-admission.js +4 -3
- package/dist/public-cli/run-lifecycle.js +14 -26
- package/dist/public-cli/settlement.js +10 -26
- package/dist/public-role-summons.js +3 -2
- package/dist/receipt-delivery-policy.js +1 -3
- package/dist/role-run-placement.js +3 -5
- package/dist/role-run-relocation.js +12 -19
- package/dist/role-submission-declarations.js +131 -0
- package/dist/run-terminal-artifacts.js +1 -11
- package/dist/run-ticket-number.js +2 -4
- package/dist/secretariat-contracts.js +23 -1
- package/dist/session-assistant-usage.js +2 -1
- package/dist/session-dialogue.js +1 -14
- package/dist/sitian-reader.js +2 -4
- package/dist/submission-correctable-error.js +2 -1
- package/dist/submission-errors.js +2 -1
- package/dist/submission-gate.js +6 -8
- package/dist/submission-ledger.js +4 -5
- package/dist/ticket-provenance-contracts.js +1 -3
- package/dist/ticket-provenance.js +2 -1
- package/dist/typed-provider-http.js +4 -7
- package/dist/unknown-value.js +28 -0
- package/dist/user-dialogue-stdin.js +2 -1
- package/package.json +1 -1
- package/src/acp-host/role-turn-host.ts +4 -2
- package/src/activation-ledger-git.ts +3 -2
- package/src/activation-ledger-topology.ts +4 -12
- package/src/analyst-entry.ts +3 -11
- package/src/analyst-gate-cycles-read.ts +3 -15
- package/src/analyst-index.ts +3 -13
- package/src/analyst-ledger.ts +2 -16
- package/src/analyst-metric-families/acceptance-success-rework.ts +2 -4
- package/src/analyst-metric-families/round-timeline.ts +2 -4
- package/src/analyst-page.ts +2 -2
- package/src/archivist-record-topology.ts +2 -2
- package/src/audit-escalation.ts +2 -1
- package/src/auditor-role.ts +2 -8
- package/src/auditor-soul.ts +3 -1
- package/src/book-topology-migration-placement.ts +5 -16
- package/src/book-topology-migrators-t11.ts +16 -15
- package/src/book-topology-mixed-volume-migrators.ts +3 -6
- package/src/book-topology-record-class-migrators.ts +7 -10
- package/src/book-topology-runs-migrator.ts +4 -3
- package/src/collector-config.ts +7 -9
- package/src/collector-role.ts +5 -28
- package/src/compliance-transport.ts +2 -1
- package/src/countersign-contracts.ts +2 -1
- package/src/countersign-role.ts +2 -7
- package/src/diarist-contracts.ts +40 -2
- package/src/diarist-role.ts +4 -44
- package/src/doctor-contracts.ts +3 -1
- package/src/doctor-evidence.ts +8 -7
- package/src/doctor-role.ts +20 -13
- package/src/dossier-resolution.ts +2 -4
- package/src/engine-detour-tool.ts +0 -2
- package/src/engine-detour-usage.ts +2 -4
- package/src/external-host-turn-loop.ts +3 -1
- package/src/factory-board.ts +1 -8
- package/src/filed-submission.ts +44 -0
- package/src/gatekeeper-role.ts +8 -24
- package/src/gleaner-left-contracts.ts +29 -2
- package/src/gleaner-left-role.ts +4 -32
- package/src/headless-host/description.ts +15 -18
- package/src/headless-host/role-turn-host.ts +10 -9
- package/src/host-session-record.ts +4 -2
- package/src/inspector-contracts.ts +2 -1
- package/src/inspector-role.ts +2 -7
- package/src/judge-role.ts +12 -24
- package/src/ledger-session-read.ts +2 -5
- package/src/merger-contracts.ts +10 -9
- package/src/merger-role.ts +5 -8
- package/src/navigator-attendance.ts +10 -12
- package/src/navigator-invocation-identity.ts +3 -2
- package/src/navigator-public-session.ts +4 -6
- package/src/navigator-role.ts +2 -8
- package/src/navigator-session-contracts.ts +8 -11
- package/src/navigator-work-base.ts +5 -8
- package/src/navigator-work-context.ts +2 -1
- package/src/notary-contracts.ts +4 -6
- package/src/notary-role.ts +5 -20
- package/src/oauth-keepalive.ts +5 -18
- package/src/package-contracts/auditor-output.ts +2 -4
- package/src/package-contracts/fixer-packet.ts +4 -6
- package/src/package-contracts/gatekeeper-output.ts +2 -4
- package/src/package-contracts/judge-output.ts +0 -1
- package/src/package-contracts/navigator-output.ts +8 -8
- package/src/package-contracts/reviewer-output.ts +25 -0
- package/src/package-contracts/terminating-infrastructure.ts +6 -20
- package/src/package-contracts/terminating-tools.ts +8 -12
- package/src/package-contracts/worker-output.ts +43 -5
- package/src/pi/adapter.ts +0 -1
- package/src/pi/role-turn-host.ts +0 -1
- package/src/public-cli/analyst-run.ts +4 -2
- package/src/public-cli/auto-resume.ts +4 -11
- package/src/public-cli/cli.ts +10 -10
- package/src/public-cli/config.ts +8 -27
- package/src/public-cli/countersign-run.ts +2 -4
- package/src/public-cli/host-providers.ts +10 -27
- package/src/public-cli/instruction-seat-run.ts +14 -15
- package/src/public-cli/invocation.ts +11 -10
- package/src/public-cli/post-admission.ts +5 -3
- package/src/public-cli/run-lifecycle.ts +20 -41
- package/src/public-cli/settlement.ts +11 -33
- package/src/public-role-summons.ts +4 -3
- package/src/receipt-delivery-policy.ts +1 -4
- package/src/reviewer-role.ts +7 -36
- package/src/role-envelope.ts +5 -3
- package/src/role-run-placement.ts +4 -10
- package/src/role-run-relocation.ts +13 -23
- package/src/role-runtime.ts +16 -50
- package/src/role-submission-declarations.ts +143 -0
- package/src/run-terminal-artifacts.ts +2 -16
- package/src/run-ticket-number.ts +4 -10
- package/src/secretariat-contracts.ts +35 -0
- package/src/secretariat-role.ts +4 -40
- package/src/session-assistant-usage.ts +3 -1
- package/src/session-dialogue.ts +1 -4
- package/src/session-identity.ts +0 -1
- package/src/sitian-reader.ts +2 -4
- package/src/submission-correctable-error.ts +3 -1
- package/src/submission-errors.ts +2 -1
- package/src/submission-gate.ts +10 -9
- package/src/submission-ledger.ts +5 -6
- package/src/ticket-provenance-contracts.ts +1 -4
- package/src/ticket-provenance.ts +3 -1
- package/src/ticket-snapshot.ts +2 -4
- package/src/ticket-trajectory.ts +1 -8
- package/src/typed-provider-http.ts +5 -15
- package/src/unknown-value.ts +34 -0
- package/src/user-dialogue-stdin.ts +3 -1
- package/src/worker-role.ts +63 -83
- package/src/worker-submission-gates.ts +8 -7
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>;
|
|
@@ -7,6 +7,8 @@ import { join } from "node:path";
|
|
|
7
7
|
|
|
8
8
|
import type { PublicSummonResult } from "./public-role-summons.ts";
|
|
9
9
|
|
|
10
|
+
import { errorText } from "./unknown-value.ts";
|
|
11
|
+
|
|
10
12
|
export async function readAssistantUsageFromSessionFile(
|
|
11
13
|
sessionFile: string,
|
|
12
14
|
): Promise<Usage | undefined> {
|
|
@@ -30,7 +32,7 @@ export async function readAssistantUsageFromSessionFile(
|
|
|
30
32
|
});
|
|
31
33
|
} catch (error) {
|
|
32
34
|
throw new Error(
|
|
33
|
-
`session usage parse failed (${sessionFile}): ${
|
|
35
|
+
`session usage parse failed (${sessionFile}): ${errorText(error)}`,
|
|
34
36
|
{ cause: error },
|
|
35
37
|
);
|
|
36
38
|
}
|
package/src/session-dialogue.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isRecord } from "./unknown-value.ts";
|
|
1
2
|
/**
|
|
2
3
|
* 对话事实适配(ADR 0075 `dialogue-only` / `no-tool-output` / `speaker-required`)。
|
|
3
4
|
*
|
|
@@ -20,10 +21,6 @@ export type DialogueEvent = {
|
|
|
20
21
|
readonly id?: string;
|
|
21
22
|
};
|
|
22
23
|
|
|
23
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
24
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
24
|
/**
|
|
28
25
|
* 原生 id:行级或消息体级主键的单一实现(bound 解析与落盘共用)。
|
|
29
26
|
* Pi/CC:行上 `uuid`/`id`;Codex:`response_item.payload.id`(或 `message.id`)。
|
package/src/session-identity.ts
CHANGED
package/src/sitian-reader.ts
CHANGED
|
@@ -15,9 +15,7 @@ import type {
|
|
|
15
15
|
SitianRecord,
|
|
16
16
|
} from "./sitian-contracts.ts";
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20
|
-
}
|
|
18
|
+
import { isRecord, errorText } from "./unknown-value.ts";
|
|
21
19
|
|
|
22
20
|
/** Read a Sitian record volume with full traversal and non-destructive diagnostics. */
|
|
23
21
|
export async function readSitianRecords(recordFile: string): Promise<SitianReadResult> {
|
|
@@ -53,7 +51,7 @@ export async function readSitianRecords(recordFile: string): Promise<SitianReadR
|
|
|
53
51
|
kind: "malformed",
|
|
54
52
|
line: index + 1,
|
|
55
53
|
raw: line,
|
|
56
|
-
error:
|
|
54
|
+
error: errorText(error),
|
|
57
55
|
});
|
|
58
56
|
}
|
|
59
57
|
}
|
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
WorkerUnfinishedReasonReminderError,
|
|
7
7
|
} from "./submission-errors.ts";
|
|
8
8
|
|
|
9
|
+
import { errorText } from "./unknown-value.ts";
|
|
10
|
+
|
|
9
11
|
/** Shared, unforgeable identity for submission errors that the same session may correct. */
|
|
10
12
|
const correctableSubmissionErrorBrand = Symbol("ak-roles.correctable-submission-error");
|
|
11
13
|
|
|
@@ -49,7 +51,7 @@ export type CorrectableExecuteRejectionProjection = {
|
|
|
49
51
|
export function projectCorrectableExecuteRejection(
|
|
50
52
|
error: unknown,
|
|
51
53
|
): CorrectableExecuteRejectionProjection {
|
|
52
|
-
const diagnostic =
|
|
54
|
+
const diagnostic = errorText(error);
|
|
53
55
|
if (error instanceof GatekeeperDecisionError) {
|
|
54
56
|
return { diagnostic, details: { ...(error.result as Record<string, unknown>) } };
|
|
55
57
|
}
|
package/src/submission-errors.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { SubmissionGateNonPassResult } from "./gatekeeper-role.ts";
|
|
2
2
|
import { readableGateItem } from "./readable-gate-item.ts";
|
|
3
|
+
import { isRecord } from "./unknown-value.ts";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Tool-result text the parent model sees (#753 / #750 evidence).
|
|
@@ -69,7 +70,7 @@ export function unreadableDiscriminatorNotice(field: string, received: unknown):
|
|
|
69
70
|
|
|
70
71
|
/** The received discriminator only — never the rest of the receipt. */
|
|
71
72
|
export function receivedDiscriminator(receipt: unknown, field: string): unknown {
|
|
72
|
-
if (
|
|
73
|
+
if (!isRecord(receipt)) return undefined;
|
|
73
74
|
if (!Object.hasOwn(receipt, field)) return undefined;
|
|
74
75
|
return (receipt as Record<string, unknown>)[field];
|
|
75
76
|
}
|
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 (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 {
|
|
@@ -54,6 +53,8 @@ export function latestQueuePayload(terminal: TerminalResult | undefined): unknow
|
|
|
54
53
|
}
|
|
55
54
|
import { sessionFileFromPublicSummon } from "./session-assistant-usage.ts";
|
|
56
55
|
|
|
56
|
+
import { isRecord } from "./unknown-value.ts";
|
|
57
|
+
|
|
57
58
|
/**
|
|
58
59
|
* Shared-envelope default officer summon (ADR 0018).
|
|
59
60
|
* Role modules must not own this drive seam — only project results.
|
|
@@ -129,7 +130,7 @@ function bookDirectOfficerPointer(
|
|
|
129
130
|
* public terminal without a second authority.
|
|
130
131
|
*/
|
|
131
132
|
export type SubmissionGateOutcome = {
|
|
132
|
-
readonly status:
|
|
133
|
+
readonly status: ReviewQueueWord;
|
|
133
134
|
readonly officer: GateOfficer;
|
|
134
135
|
readonly receipt: unknown;
|
|
135
136
|
readonly runId?: string;
|
package/src/submission-ledger.ts
CHANGED
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
type RoleHost,
|
|
13
13
|
} from "./host-contracts.ts";
|
|
14
14
|
|
|
15
|
-
|
|
16
15
|
import { runIdFromRunDirectory } from "./run-terminal-artifacts.ts";
|
|
17
16
|
import { readSitianRecords, resolveSitianRecordPathInLedger, sitianReport, type RecordPointer } from "./sitian-facade.ts";
|
|
18
17
|
import type { SitianRecord } from "./sitian-contracts.ts";
|
|
@@ -22,6 +21,8 @@ import { isCorrectableExecuteError } from "./submission-correctable-error.ts";
|
|
|
22
21
|
import { failOnInfrastructureFailureDeclaration, infrastructureFailureDiagnostic } from "./package-contracts/terminating-infrastructure.ts";
|
|
23
22
|
import { REVIEW_SUBMISSION_OUTPUT_TOOL_NAME } from "./review-submission.ts";
|
|
24
23
|
|
|
24
|
+
import { isRecord, errorText } from "./unknown-value.ts";
|
|
25
|
+
|
|
25
26
|
export type SubmissionCall = { readonly id: string; readonly name: string };
|
|
26
27
|
export type SubmissionOutcomeKind = "correctable-rejection" | "audit-escalation" | "infrastructure";
|
|
27
28
|
/** Typed correctable-rejection codes — bounce/reminder paths only (#836: no sole/non-terminate reject). */
|
|
@@ -662,9 +663,7 @@ export function createSubmissionLedgerHost(
|
|
|
662
663
|
// host-failure seam. Tool identity comes from the registry map.
|
|
663
664
|
const reviewEscalate = tool.name === REVIEW_SUBMISSION_OUTPUT_TOOL_NAME
|
|
664
665
|
&& infrastructureFailureDiagnostic(params) !== undefined
|
|
665
|
-
&& params
|
|
666
|
-
&& typeof params === "object"
|
|
667
|
-
&& !Array.isArray(params)
|
|
666
|
+
&& isRecord(params)
|
|
668
667
|
&& (params as Record<string, unknown>).status === "escalate";
|
|
669
668
|
if (!reviewEscalate) {
|
|
670
669
|
failOnInfrastructureFailureDeclaration(
|
|
@@ -688,7 +687,7 @@ export function createSubmissionLedgerHost(
|
|
|
688
687
|
toolCallId,
|
|
689
688
|
outcome: "correctable-rejection",
|
|
690
689
|
code: "typed-bounce",
|
|
691
|
-
diagnostic:
|
|
690
|
+
diagnostic: errorText(error),
|
|
692
691
|
role,
|
|
693
692
|
accepted: params,
|
|
694
693
|
});
|
|
@@ -699,7 +698,7 @@ export function createSubmissionLedgerHost(
|
|
|
699
698
|
attemptId,
|
|
700
699
|
toolCallId,
|
|
701
700
|
outcome: "infrastructure",
|
|
702
|
-
diagnostic:
|
|
701
|
+
diagnostic: errorText(error),
|
|
703
702
|
role,
|
|
704
703
|
accepted: params,
|
|
705
704
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isRecord } from "./unknown-value.ts";
|
|
1
2
|
/**
|
|
2
3
|
* 起居录(ticket-provenance)typed 形状 —— ADR 0075 / ADR 0081 / #1090。
|
|
3
4
|
*
|
|
@@ -61,10 +62,6 @@ export type TicketProvenanceLine = {
|
|
|
61
62
|
readonly text: string;
|
|
62
63
|
};
|
|
63
64
|
|
|
64
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
65
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
65
|
function positiveInteger(value: unknown): number | undefined {
|
|
69
66
|
if (typeof value === "number" && Number.isSafeInteger(value) && value >= 1) return value;
|
|
70
67
|
if (typeof value === "string" && /^[1-9][0-9]*$/.test(value)) {
|
package/src/ticket-provenance.ts
CHANGED
|
@@ -32,6 +32,8 @@ import {
|
|
|
32
32
|
type TicketProvenanceSession,
|
|
33
33
|
} from "./ticket-provenance-contracts.ts";
|
|
34
34
|
|
|
35
|
+
import { errorText } from "./unknown-value.ts";
|
|
36
|
+
|
|
35
37
|
/**
|
|
36
38
|
* Typed input failure for diarist bounds/session path (reask, not infrastructure).
|
|
37
39
|
* Accept hook discriminates with instanceof — never Error.message prefixes.
|
|
@@ -281,7 +283,7 @@ async function projectSessionRanges(input: {
|
|
|
281
283
|
if (error instanceof TicketProvenanceInputError) throw error;
|
|
282
284
|
const code = errnoCode(error);
|
|
283
285
|
if (code === "ENOENT" || code === "ENOTDIR" || code === "EISDIR") {
|
|
284
|
-
const detail =
|
|
286
|
+
const detail = errorText(error);
|
|
285
287
|
throw new TicketProvenanceInputError(
|
|
286
288
|
`session unreadable: ${input.session.path} (${detail})`,
|
|
287
289
|
{ cause: error },
|
package/src/ticket-snapshot.ts
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { createGhApiRunner, type GhApiRunner } from "./gh-api-runner.ts";
|
|
15
15
|
|
|
16
|
+
import { isRecord } from "./unknown-value.ts";
|
|
17
|
+
|
|
16
18
|
export type BookRepoBinding = {
|
|
17
19
|
bookKey: string;
|
|
18
20
|
owner: string;
|
|
@@ -92,10 +94,6 @@ export class TicketSnapshotApiError extends Error {
|
|
|
92
94
|
}
|
|
93
95
|
}
|
|
94
96
|
|
|
95
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
96
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
97
|
function requireNonEmpty(value: string, label: string): string {
|
|
100
98
|
const trimmed = value.trim();
|
|
101
99
|
if (!trimmed) throw new Error(`${label} must be a non-empty string`);
|
package/src/ticket-trajectory.ts
CHANGED
|
@@ -46,6 +46,7 @@ import {
|
|
|
46
46
|
} from "./package-contracts/terminating-tools.ts";
|
|
47
47
|
import { LEGACY_REVIEW_OUTPUT_ROLES, PACKAGED_ROLE_REGISTRY } from "./packaged-role-registry.ts";
|
|
48
48
|
|
|
49
|
+
import { isRecord, isMissingPathError } from "./unknown-value.ts";
|
|
49
50
|
|
|
50
51
|
/** Declared refresh bound for the same viewing surface (seconds). */
|
|
51
52
|
export const DEFAULT_REFRESH_BOUNDARY_SECONDS = 30;
|
|
@@ -122,14 +123,6 @@ export type TicketTrajectoryRun = {
|
|
|
122
123
|
|
|
123
124
|
type ParsedRun = TicketTrajectoryRun;
|
|
124
125
|
|
|
125
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
126
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function isMissingPathError(error: unknown): boolean {
|
|
130
|
-
return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
|
|
131
|
-
}
|
|
132
|
-
|
|
133
126
|
/** realpath when the node exists; lexical path only for recognized absence — never for other errors. */
|
|
134
127
|
async function realpathOrLexicalIfMissing(path: string): Promise<string> {
|
|
135
128
|
try {
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
import { readFile, unlink, writeFile } from "node:fs/promises";
|
|
6
6
|
import { join } from "node:path";
|
|
7
7
|
|
|
8
|
+
import { isEnoent, isRecord } from "./unknown-value.ts";
|
|
9
|
+
|
|
8
10
|
const TYPED_HTTP_FILE = "typed-provider-http.json";
|
|
9
11
|
|
|
10
12
|
export type TypedProviderHttpObservation = {
|
|
@@ -27,13 +29,7 @@ export async function clearTypedProviderHttpObservation(
|
|
|
27
29
|
try {
|
|
28
30
|
await unlink(typedProviderHttpPath(runDirectory));
|
|
29
31
|
} catch (error) {
|
|
30
|
-
if (
|
|
31
|
-
error instanceof Error &&
|
|
32
|
-
"code" in error &&
|
|
33
|
-
(error as { code?: unknown }).code === "ENOENT"
|
|
34
|
-
) {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
32
|
+
if (isEnoent(error)) return;
|
|
37
33
|
throw error;
|
|
38
34
|
}
|
|
39
35
|
}
|
|
@@ -75,17 +71,11 @@ export async function readLatestTypedProviderHttpObservation(
|
|
|
75
71
|
try {
|
|
76
72
|
text = await readFile(typedProviderHttpPath(runDirectory), "utf8");
|
|
77
73
|
} catch (error) {
|
|
78
|
-
if (
|
|
79
|
-
error instanceof Error &&
|
|
80
|
-
"code" in error &&
|
|
81
|
-
(error as { code?: unknown }).code === "ENOENT"
|
|
82
|
-
) {
|
|
83
|
-
return undefined;
|
|
84
|
-
}
|
|
74
|
+
if (isEnoent(error)) return undefined;
|
|
85
75
|
throw error;
|
|
86
76
|
}
|
|
87
77
|
const raw: unknown = JSON.parse(text);
|
|
88
|
-
if (
|
|
78
|
+
if (!isRecord(raw)) {
|
|
89
79
|
throw new Error("typed provider HTTP observation must be a JSON object");
|
|
90
80
|
}
|
|
91
81
|
const record = raw as Record<string, unknown>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Guard } from "typebox/guard";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Sole readers for a plain object, a Node errno, and an Error message.
|
|
5
|
+
* Callers choose which codes count; ENOTDIR is not ENOENT.
|
|
6
|
+
* Plain objects are TypeBox `Guard.IsObjectNotArray`.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export function isRecord(value: unknown): value is Record<string, unknown> {
|
|
10
|
+
return Guard.IsObjectNotArray(value);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function errnoCode(error: unknown): string | undefined {
|
|
14
|
+
return error !== null && typeof error === "object" && "code" in error
|
|
15
|
+
&& typeof (error as { code: unknown }).code === "string"
|
|
16
|
+
? (error as { code: string }).code
|
|
17
|
+
: undefined;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** `Error.message`, otherwise `String(value)`. */
|
|
21
|
+
export function errorText(error: unknown): string {
|
|
22
|
+
return error instanceof Error ? error.message : String(error);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** True only for ENOENT on an Error. ENOTDIR and every other code stay distinct. */
|
|
26
|
+
export function isEnoent(error: unknown): boolean {
|
|
27
|
+
return error instanceof Error && errnoCode(error) === "ENOENT";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** ENOENT or ENOTDIR on an Error. */
|
|
31
|
+
export function isMissingPathError(error: unknown): boolean {
|
|
32
|
+
const code = errnoCode(error);
|
|
33
|
+
return error instanceof Error && (code === "ENOENT" || code === "ENOTDIR");
|
|
34
|
+
}
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* Pi's piped-stdin reader trims the wrapper; the body field keeps original bytes.
|
|
4
4
|
* No size cap and no path/pointer substitute — the whole dialogue rides the envelope.
|
|
5
5
|
*/
|
|
6
|
+
import { isRecord } from "./unknown-value.ts";
|
|
7
|
+
|
|
6
8
|
export const USER_DIALOGUE_STDIN_KIND = "ak-user-dialogue" as const;
|
|
7
9
|
|
|
8
10
|
export type UserDialogueStdinEnvelope = {
|
|
@@ -15,7 +17,7 @@ export function encodeUserDialogueStdin(body: string): string {
|
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
function isUserDialogueEnvelope(value: unknown): value is UserDialogueStdinEnvelope {
|
|
18
|
-
if (
|
|
20
|
+
if (!isRecord(value)) return false;
|
|
19
21
|
const record = value as { kind?: unknown; body?: unknown };
|
|
20
22
|
return record.kind === USER_DIALOGUE_STDIN_KIND && typeof record.body === "string";
|
|
21
23
|
}
|
package/src/worker-role.ts
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
import type { RoleHost, HostContext,
|
|
2
|
-
import { Type, type Static } from "typebox";
|
|
3
|
-
import { openToolObject } from "./open-tool-schema.ts";
|
|
4
|
-
import { withTerminatingOutputDeclarations } from "./package-contracts/terminating-infrastructure.ts";
|
|
1
|
+
import type { RoleHost, HostContext, HostGatekeeperActions } from "./host-contracts.ts";
|
|
5
2
|
|
|
6
3
|
import {
|
|
7
|
-
CODER_OUTPUT_TOOL_NAME,
|
|
8
|
-
FIXER_OUTPUT_TOOL_NAME,
|
|
9
4
|
validateAcceptedWorkerDetails,
|
|
10
5
|
type CoderOutput,
|
|
11
6
|
type FixerOutput,
|
|
12
7
|
type WorkerOutput,
|
|
13
8
|
type WorkerRoleLabel,
|
|
14
9
|
} from "./package-contracts/worker-output.ts";
|
|
15
|
-
import {
|
|
10
|
+
import { validateFixerOutput, type FixerPhase } from "./package-contracts/fixer-output.ts";
|
|
11
|
+
import { registerFiledSubmissionTool } from "./filed-submission.ts";
|
|
12
|
+
import { roleSubmissionDeclaration } from "./role-submission-declarations.ts";
|
|
16
13
|
import {
|
|
17
14
|
FixerPacketValidationError,
|
|
18
15
|
parseFixerPrerequisites,
|
|
@@ -23,37 +20,22 @@ import {
|
|
|
23
20
|
WorkerCommitReminderError,
|
|
24
21
|
WorkerPrefixReminderError,
|
|
25
22
|
WorkerUnfinishedReasonReminderError,
|
|
23
|
+
type WorkerSubmissionGate,
|
|
26
24
|
} from "./worker-submission-gates.ts";
|
|
27
25
|
import {
|
|
28
26
|
fixerBashSeatbeltDenyReason,
|
|
29
27
|
matchFixerBashForbiddenLiteral,
|
|
30
28
|
} from "./fixer-bash-seatbelt.ts";
|
|
31
29
|
|
|
30
|
+
import { isRecord } from "./unknown-value.ts";
|
|
31
|
+
|
|
32
32
|
export {
|
|
33
33
|
CODER_OUTPUT_TOOL_NAME,
|
|
34
34
|
FIXER_OUTPUT_TOOL_NAME,
|
|
35
|
+
coderOutputSchema,
|
|
35
36
|
validateAcceptedWorkerDetails,
|
|
36
|
-
};
|
|
37
|
-
export type { WorkerOutput };
|
|
38
|
-
|
|
39
|
-
// status 的合法词写在 description。WORKER_DONE_STATUSES 只让 completed /
|
|
40
|
-
// partially_completed 进入提交闸。unfinished 且未见理由说明时,运行时同 run 催全
|
|
41
|
-
// (ADR 0050);理由在不在不按 JSON 类型判,也不在派发前用长度拒收。
|
|
42
|
-
// report / remainingScope / reason 的声明只留字段名和语义。
|
|
43
|
-
const CODER_STATUS_DESCRIPTION =
|
|
44
|
-
`planned | completed | refused | partially_completed | unfinished。unfinished:缺前置或违宪约束致本局未完成。${PARTIALLY_COMPLETED_DEFINITION}` as const;
|
|
45
|
-
const coderOutputObject = Type.Object({
|
|
46
|
-
status: Type.Unknown({ description: CODER_STATUS_DESCRIPTION }),
|
|
47
|
-
report: Type.Unknown({ description: "如实结果报告" }),
|
|
48
|
-
remainingScope: Type.Unknown({ description: "本局后剩余工作" }),
|
|
49
|
-
reason: Type.Unknown({
|
|
50
|
-
description: "阻断原因:缺前置或违宪约束。缺待决 owner 决定或答复属缺前置。",
|
|
51
|
-
}),
|
|
52
|
-
});
|
|
53
|
-
export const coderOutputSchema = withTerminatingOutputDeclarations(
|
|
54
|
-
openToolObject(coderOutputObject),
|
|
55
|
-
);
|
|
56
|
-
export type { FixerOutput, CoderOutput };
|
|
37
|
+
} from "./package-contracts/worker-output.ts";
|
|
38
|
+
export type { WorkerOutput, FixerOutput, CoderOutput };
|
|
57
39
|
export const FIXER_FLAG_DEFINITIONS = {
|
|
58
40
|
packet: {
|
|
59
41
|
name: "ak-fix-packet",
|
|
@@ -104,10 +86,6 @@ export type WorkerRoleRuntime = {
|
|
|
104
86
|
armSubmissionGate(cwd: string, parent: { getSessionFile(): string | undefined }): void;
|
|
105
87
|
};
|
|
106
88
|
|
|
107
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
108
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
89
|
/** Read only the field that selects the worker's next package-owned path. */
|
|
112
90
|
function workerStatusOf(output: WorkerOutput): string | undefined {
|
|
113
91
|
return isRecord(output) && typeof output.status === "string"
|
|
@@ -130,10 +108,48 @@ export function validateWorkerOutput(
|
|
|
130
108
|
return validateAcceptedWorkerDetails(output, "Coder") as CoderOutput;
|
|
131
109
|
}
|
|
132
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Coder and fixer share one submission sequence: record via the shared tool,
|
|
113
|
+
* then read status and bounce through the same reminder gate.
|
|
114
|
+
* Seat differences stay in the ready check and the projection.
|
|
115
|
+
*/
|
|
116
|
+
function registerWorkerSubmission(
|
|
117
|
+
pi: RoleHost,
|
|
118
|
+
role: "coder" | "fixer",
|
|
119
|
+
options: {
|
|
120
|
+
readonly notReady: string;
|
|
121
|
+
readonly ready: () => boolean;
|
|
122
|
+
readonly phase: () => WorkerPhase | undefined;
|
|
123
|
+
readonly project: (parameters: unknown, phase: WorkerPhase) => WorkerOutput;
|
|
124
|
+
readonly submissionGate: WorkerSubmissionGate;
|
|
125
|
+
readonly hostActions: WorkerRoleHostActions;
|
|
126
|
+
},
|
|
127
|
+
): void {
|
|
128
|
+
registerFiledSubmissionTool(pi, roleSubmissionDeclaration(role), {
|
|
129
|
+
readyError: () => (options.ready() ? undefined : options.notReady),
|
|
130
|
+
beforeAccept: async ({ toolCallId, parameters, ctx }) => {
|
|
131
|
+
const phase = options.phase();
|
|
132
|
+
if (phase === undefined) throw new Error(options.notReady);
|
|
133
|
+
const output = options.project(parameters, phase);
|
|
134
|
+
const status = workerStatusOf(output);
|
|
135
|
+
if (status !== undefined) {
|
|
136
|
+
assertAcceptableThroughHost(
|
|
137
|
+
options.submissionGate,
|
|
138
|
+
status,
|
|
139
|
+
output,
|
|
140
|
+
options.hostActions,
|
|
141
|
+
ctx,
|
|
142
|
+
toolCallId,
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
return output;
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
}
|
|
133
149
|
|
|
134
150
|
/** Reminder bounces stay typed rejects; IO/infrastructure keep identity via host failInfrastructure. */
|
|
135
151
|
function assertAcceptableThroughHost(
|
|
136
|
-
submissionGate:
|
|
152
|
+
submissionGate: WorkerSubmissionGate,
|
|
137
153
|
status: string,
|
|
138
154
|
details: unknown,
|
|
139
155
|
hostActions: WorkerRoleHostActions,
|
|
@@ -215,30 +231,13 @@ export function createFixerRoleRuntime(
|
|
|
215
231
|
|
|
216
232
|
if (!lifecycleRegistered) {
|
|
217
233
|
lifecycleRegistered = true;
|
|
218
|
-
pi
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
if (packet === undefined || phase === undefined) {
|
|
226
|
-
throw new Error("修内司修理包与阶段未装载");
|
|
227
|
-
}
|
|
228
|
-
const output = deepFreeze(validateFixerOutput(parameters, phase));
|
|
229
|
-
const status = workerStatusOf(output);
|
|
230
|
-
if (status !== undefined) {
|
|
231
|
-
assertAcceptableThroughHost(
|
|
232
|
-
submissionGate,
|
|
233
|
-
status,
|
|
234
|
-
output,
|
|
235
|
-
hostActions,
|
|
236
|
-
ctx,
|
|
237
|
-
toolCallId,
|
|
238
|
-
);
|
|
239
|
-
}
|
|
240
|
-
return { content: [], details: output, terminate: true as const };
|
|
241
|
-
},
|
|
234
|
+
registerWorkerSubmission(pi, "fixer", {
|
|
235
|
+
notReady: "修内司修理包与阶段未装载",
|
|
236
|
+
ready: () => packet !== undefined && phase !== undefined,
|
|
237
|
+
phase: () => phase,
|
|
238
|
+
project: (parameters, current) => deepFreeze(validateFixerOutput(parameters, current)),
|
|
239
|
+
submissionGate,
|
|
240
|
+
hostActions,
|
|
242
241
|
});
|
|
243
242
|
pi.on("tool_call", (event) => {
|
|
244
243
|
if (event.toolName !== "bash") return;
|
|
@@ -313,32 +312,13 @@ export function createCoderRoleRuntime(
|
|
|
313
312
|
|
|
314
313
|
if (!lifecycleRegistered) {
|
|
315
314
|
lifecycleRegistered = true;
|
|
316
|
-
pi
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
if (task === undefined || phase === undefined) {
|
|
324
|
-
throw new Error("将作监任务与阶段未装载");
|
|
325
|
-
}
|
|
326
|
-
const output = validateWorkerOutput(parameters, phase, "Coder");
|
|
327
|
-
const status = workerStatusOf(output);
|
|
328
|
-
// #836: skill-expansion evidence rejection deleted (陛下「2.4/5 删」).
|
|
329
|
-
// Skill still ships with the package (ADR 0052); code no longer refuses on it.
|
|
330
|
-
if (status !== undefined) {
|
|
331
|
-
assertAcceptableThroughHost(
|
|
332
|
-
submissionGate,
|
|
333
|
-
status,
|
|
334
|
-
output,
|
|
335
|
-
hostActions,
|
|
336
|
-
ctx,
|
|
337
|
-
toolCallId,
|
|
338
|
-
);
|
|
339
|
-
}
|
|
340
|
-
return { content: [], details: output, terminate: true as const };
|
|
341
|
-
},
|
|
315
|
+
registerWorkerSubmission(pi, "coder", {
|
|
316
|
+
notReady: "将作监任务与阶段未装载",
|
|
317
|
+
ready: () => task !== undefined && phase !== undefined,
|
|
318
|
+
phase: () => phase,
|
|
319
|
+
project: (parameters, current) => validateWorkerOutput(parameters, current, "Coder"),
|
|
320
|
+
submissionGate,
|
|
321
|
+
hostActions,
|
|
342
322
|
});
|
|
343
323
|
pi.on("before_agent_start", (event, ctx) => {
|
|
344
324
|
if (soul === undefined) throw new Error("将作监职分未装载");
|