@akagilnc/pi-workflow-roles 0.1.3932 → 0.1.3975
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/CLAUDE.md +1 -1
- package/dist/acp-host/production-host.js +2389 -6018
- package/dist/analyst-gate-cycles-read.js +15 -19
- package/dist/audit-escalation.js +16 -46
- package/dist/auditor-dossier-tool.js +7 -62
- package/dist/collector-identity.js +0 -157
- package/dist/collector-ledger.js +2 -42
- package/dist/compliance-transport.js +40 -14
- package/dist/diarist-contracts.js +2 -40
- package/dist/doctor-contracts.js +39 -108
- package/dist/doctor-evidence.js +1 -5
- package/dist/engine-detour-tool.js +1 -1
- package/dist/gatekeeper-role.js +49 -38
- package/dist/headless-host/production-host.js +4814 -8450
- package/dist/host-contracts.js +0 -5
- package/dist/merger-contracts.js +4 -6
- package/dist/navigator-attendance.js +30 -52
- package/dist/navigator-invocation-identity.js +0 -1
- package/dist/navigator-public-session.js +2 -1
- package/dist/notary-contracts.js +4 -10
- package/dist/package-contracts/auditor-output.js +5 -23
- package/dist/package-contracts/fixer-output.js +25 -49
- package/dist/package-contracts/gatekeeper-output.js +3 -13
- package/dist/package-contracts/navigator-output.js +4 -7
- package/dist/package-contracts/reviewer-output.js +1 -95
- package/dist/package-contracts/terminating-tools.js +33 -144
- package/dist/package-contracts/worker-output.js +1 -3
- package/dist/public-cli/auto-resume.js +30 -68
- package/dist/public-cli/case-dossier-delivery.js +5 -17
- package/dist/public-cli/diarist-run.js +9 -4
- package/dist/public-cli/inspector-run.js +2 -8
- package/dist/public-cli/instruction-seat-run.js +3 -7
- package/dist/public-cli/invocation.js +5 -2
- package/dist/public-cli/main.js +6068 -6964
- package/dist/public-cli/notary-run.js +1 -8
- package/dist/public-cli/post-admission.js +314 -113
- package/dist/public-cli/run-lifecycle.js +14 -38
- package/dist/public-cli/settlement.js +209 -390
- package/dist/public-cli/terminal.js +51 -45
- package/dist/public-role-summons.js +1 -12
- package/dist/reviewer-dispatch.js +12 -258
- package/dist/submission-correctable-error.js +0 -12
- package/dist/submission-errors.js +6 -1
- package/dist/submission-ledger.js +125 -168
- package/dist/ticket-provenance-contracts.js +2 -49
- package/dist/ticket-provenance.js +82 -31
- package/extensions/role-runtime.ts +1 -6
- package/package.json +1 -1
- package/resources/836-deleted-machine-instruction-inventory.md +18 -0
- package/src/acp-host/role-turn-host.ts +8 -3
- package/src/analyst-gate-cycles-read.ts +17 -29
- package/src/audit-escalation.ts +20 -50
- package/src/auditor-dossier-tool.ts +5 -103
- package/src/canonical-skill-binding.ts +3 -2
- package/src/collector-identity.ts +0 -179
- package/src/collector-ledger.ts +3 -46
- package/src/collector-role.ts +32 -61
- package/src/collector-tool-schemas.ts +20 -14
- package/src/compliance-transport.ts +55 -17
- package/src/countersign-role.ts +17 -8
- package/src/diarist-contracts.ts +3 -36
- package/src/diarist-role.ts +13 -7
- package/src/diarist.ts +4 -16
- package/src/doctor-contracts.ts +73 -94
- package/src/doctor-evidence.ts +1 -1
- package/src/doctor-role.ts +3 -3
- package/src/engine-detour-tool.ts +4 -1
- package/src/external-host-turn-loop.ts +9 -3
- package/src/gatekeeper-pass-envelope.ts +7 -12
- package/src/gatekeeper-role.ts +56 -50
- package/src/gleaner-left-role.ts +4 -2
- package/src/headless-host/role-turn-host.ts +4 -5
- package/src/host-contracts.ts +3 -8
- package/src/judge-role.ts +19 -13
- package/src/merger-contracts.ts +10 -6
- package/src/merger-role.ts +1 -5
- package/src/navigator-attendance.ts +37 -74
- package/src/navigator-invocation-identity.ts +0 -6
- package/src/navigator-public-session.ts +2 -1
- package/src/notary-contracts.ts +7 -10
- package/src/package-contracts/auditor-output.ts +4 -21
- package/src/package-contracts/fixer-output.ts +34 -52
- package/src/package-contracts/gatekeeper-output.ts +5 -22
- package/src/package-contracts/navigator-output.ts +7 -7
- package/src/package-contracts/reviewer-output.ts +2 -150
- package/src/package-contracts/terminating-tools.ts +32 -147
- package/src/package-contracts/worker-output.ts +0 -1
- package/src/pi/adapter.ts +3 -8
- package/src/public-cli/auto-resume.ts +41 -94
- package/src/public-cli/case-dossier-delivery.ts +5 -15
- package/src/public-cli/countersign-run.ts +14 -6
- package/src/public-cli/diarist-run.ts +11 -9
- package/src/public-cli/inspector-run.ts +2 -18
- package/src/public-cli/instruction-seat-run.ts +3 -17
- package/src/public-cli/invocation.ts +5 -2
- package/src/public-cli/merger-run.ts +1 -1
- package/src/public-cli/notary-run.ts +1 -18
- package/src/public-cli/post-admission.ts +385 -115
- package/src/public-cli/run-lifecycle.ts +13 -44
- package/src/public-cli/settlement.ts +314 -562
- package/src/public-cli/terminal.ts +66 -72
- package/src/public-role-summons.ts +5 -30
- package/src/reviewer-dispatch.ts +29 -331
- package/src/reviewer-role.ts +16 -83
- package/src/role-envelope.ts +16 -24
- package/src/role-runtime-dependencies.ts +1 -6
- package/src/role-runtime.ts +65 -201
- package/src/submission-correctable-error.ts +0 -14
- package/src/submission-errors.ts +6 -1
- package/src/submission-ledger.ts +187 -187
- package/src/ticket-provenance-contracts.ts +4 -60
- package/src/ticket-provenance.ts +98 -32
- package/src/worker-role.ts +35 -36
- package/dist/activation-ledger-session.js +0 -105
- package/dist/activation-ledger.js +0 -139
- package/dist/activation-trace.js +0 -33
- package/dist/atomic-write.js +0 -23
- package/dist/auditor-role.js +0 -12
- package/dist/canonical-skill-binding.js +0 -61
- package/dist/collector-handbook.js +0 -142
- package/dist/collector-receipt.js +0 -107
- package/dist/collector-role.js +0 -566
- package/dist/collector-tool-schemas.js +0 -107
- package/dist/countersign-role.js +0 -28
- package/dist/diarist-role.js +0 -44
- package/dist/diarist.js +0 -66
- package/dist/doctor-role.js +0 -75
- package/dist/fixer-bash-seatbelt.js +0 -13
- package/dist/gatekeeper-pass-envelope.js +0 -77
- package/dist/gleaner-left-role.js +0 -26
- package/dist/inspector-role.js +0 -29
- package/dist/judge-role.js +0 -104
- package/dist/merger-role.js +0 -55
- package/dist/navigator-role.js +0 -12
- package/dist/notary-role.js +0 -134
- package/dist/oauth-keepalive.js +0 -158
- package/dist/pi/adapter.js +0 -223
- package/dist/reviewer-agent.js +0 -122
- package/dist/reviewer-child-executor.js +0 -194
- package/dist/reviewer-construction.js +0 -103
- package/dist/reviewer-execution-ledger.js +0 -166
- package/dist/reviewer-failure-diagnostic.js +0 -17
- package/dist/reviewer-role.js +0 -159
- package/dist/reviewer-scope-prompt.js +0 -21
- package/dist/reviewer-settlement.js +0 -66
- package/dist/reviewer-workspace.js +0 -132
- package/dist/role-runtime.js +0 -1604
- package/dist/stderr-jsonl.js +0 -26
- package/dist/tool-execution-observation.js +0 -141
- package/dist/worker-role.js +0 -345
- package/dist/worker-submission-gates.js +0 -305
- package/src/collector-receipt.ts +0 -140
- package/src/diagnostic-tail.ts +0 -18
- package/src/reviewer-agent.ts +0 -135
- package/src/reviewer-child-executor.ts +0 -252
- package/src/reviewer-construction.ts +0 -195
- package/src/reviewer-execution-ledger.ts +0 -212
- package/src/reviewer-failure-diagnostic.ts +0 -18
- package/src/reviewer-scope-prompt.ts +0 -24
- package/src/reviewer-settlement.ts +0 -74
- package/src/reviewer-workspace.ts +0 -105
- package/src/shape-unreadable-failure.ts +0 -49
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { COLLECTOR_ACCEPTED_TEXT, COLLECTOR_OUTPUT_TOOL, validateAcceptedCollectorReceipt, } from "./collector-output.js";
|
|
6
6
|
import { JUDGE_ACCEPTED_TEXT, JUDGE_OUTPUT_TOOL_NAME, validateAcceptedJudgeDetails, } from "./judge-output.js";
|
|
7
|
-
import { REVIEWER_ACCEPTED_TEXT, REVIEWER_OUTPUT_TOOL_NAME,
|
|
8
|
-
import { isAuditEscalationResult } from "../audit-escalation.js";
|
|
7
|
+
import { REVIEWER_ACCEPTED_TEXT, REVIEWER_OUTPUT_TOOL_NAME, validateReviewerIntent, } from "./reviewer-output.js";
|
|
9
8
|
import { CorrectableSubmissionError } from "../submission-correctable-error.js";
|
|
10
9
|
import { DOCTOR_ACCEPTED_TEXT, DOCTOR_OUTPUT_TOOL_NAME, validateDoctorSubmissionShape, validateRecordedDoctorOutput } from "../doctor-contracts.js";
|
|
11
10
|
import { GATEKEEPER_ACCEPTED_TEXT, GATEKEEPER_OUTPUT_TOOL_NAME, validateRecordedGatekeeperOutput } from "./gatekeeper-output.js";
|
|
@@ -18,7 +17,7 @@ import { GLEANER_LEFT_ACCEPTED_TEXT, GLEANER_LEFT_OUTPUT_TOOL_NAME, validateReco
|
|
|
18
17
|
import { INSPECTOR_ACCEPTED_TEXT, INSPECTOR_OUTPUT_TOOL_NAME, validateRecordedInspectorOutput } from "../inspector-contracts.js";
|
|
19
18
|
import { DIARIST_ACCEPTED_TEXT, DIARIST_OUTPUT_TOOL_NAME, validateRecordedDiaristOutput } from "../diarist-contracts.js";
|
|
20
19
|
import { CODER_ACCEPTED_TEXT, CODER_OUTPUT_TOOL_NAME, FIXER_ACCEPTED_TEXT, FIXER_OUTPUT_TOOL_NAME, validateAcceptedWorkerDetails, } from "./worker-output.js";
|
|
21
|
-
export { CODER_ACCEPTED_TEXT, CODER_OUTPUT_TOOL_NAME, COLLECTOR_ACCEPTED_TEXT, COLLECTOR_OUTPUT_TOOL, FIXER_ACCEPTED_TEXT, FIXER_OUTPUT_TOOL_NAME, JUDGE_ACCEPTED_TEXT, JUDGE_OUTPUT_TOOL_NAME, REVIEWER_ACCEPTED_TEXT, REVIEWER_OUTPUT_TOOL_NAME, MERGER_ACCEPTED_TEXT, MERGER_OUTPUT_TOOL_NAME, validateAcceptedCollectorReceipt, validateAcceptedJudgeDetails,
|
|
20
|
+
export { CODER_ACCEPTED_TEXT, CODER_OUTPUT_TOOL_NAME, COLLECTOR_ACCEPTED_TEXT, COLLECTOR_OUTPUT_TOOL, FIXER_ACCEPTED_TEXT, FIXER_OUTPUT_TOOL_NAME, JUDGE_ACCEPTED_TEXT, JUDGE_OUTPUT_TOOL_NAME, REVIEWER_ACCEPTED_TEXT, REVIEWER_OUTPUT_TOOL_NAME, MERGER_ACCEPTED_TEXT, MERGER_OUTPUT_TOOL_NAME, validateAcceptedCollectorReceipt, validateAcceptedJudgeDetails, validateReviewerIntent, validateAcceptedWorkerDetails, validateDoctorSubmissionShape, validateRecordedDoctorOutput, validateMergerOutput, validateRecordedNotaryOutput, validateRecordedCountersignOutput, validateRecordedGleanerLeftOutput, validateRecordedInspectorOutput, validateRecordedGatekeeperOutput, validateRecordedNavigatorOutput, validateRecordedAuditorOutput, validateRecordedDiaristOutput, };
|
|
22
21
|
export const TERMINATING_TOOL_NAMES = [
|
|
23
22
|
CODER_OUTPUT_TOOL_NAME,
|
|
24
23
|
FIXER_OUTPUT_TOOL_NAME,
|
|
@@ -80,155 +79,45 @@ export class AcceptedDetailsContractError extends CorrectableSubmissionError {
|
|
|
80
79
|
this.name = "AcceptedDetailsContractError";
|
|
81
80
|
}
|
|
82
81
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
export function validateAcceptedDetails(toolName, details) {
|
|
92
|
-
const candidate = details !== null && typeof details === "object" && !Array.isArray(details)
|
|
93
|
-
? details
|
|
94
|
-
: undefined;
|
|
95
|
-
let auditEscalation = false;
|
|
96
|
-
try {
|
|
97
|
-
auditEscalation = isAuditEscalationResult(details);
|
|
98
|
-
}
|
|
99
|
-
catch {
|
|
100
|
-
// Hostile getters are not recognizable audit escalation evidence.
|
|
101
|
-
}
|
|
102
|
-
if (auditEscalation || safeProperty(candidate, "kind") === "audit_escalation") {
|
|
103
|
-
throw new AcceptedDetailsContractError("audit escalation is not an accepted role receipt");
|
|
104
|
-
}
|
|
105
|
-
const statusKey = toolName === JUDGE_OUTPUT_TOOL_NAME
|
|
106
|
-
? "judgeStatus"
|
|
107
|
-
: toolName === COUNTERSIGN_OUTPUT_TOOL_NAME
|
|
108
|
-
? "countersignStatus"
|
|
109
|
-
: "status";
|
|
110
|
-
const discriminator = safeProperty(candidate, statusKey);
|
|
111
|
-
const lawfulStatuses = {
|
|
112
|
-
[CODER_OUTPUT_TOOL_NAME]: ["planned", "completed", "refused", "unfinished"],
|
|
113
|
-
[FIXER_OUTPUT_TOOL_NAME]: ["planned", "completed", "refused", "partially_completed", "unfinished"],
|
|
114
|
-
[REVIEWER_OUTPUT_TOOL_NAME]: ["completed", "refused"],
|
|
115
|
-
[JUDGE_OUTPUT_TOOL_NAME]: ["converged", "continue", "escalate"],
|
|
116
|
-
[COLLECTOR_OUTPUT_TOOL]: [],
|
|
117
|
-
[DOCTOR_OUTPUT_TOOL_NAME]: ["completed", "refused"],
|
|
118
|
-
[MERGER_OUTPUT_TOOL_NAME]: ["completed", "escalate"],
|
|
119
|
-
[NOTARY_OUTPUT_TOOL_NAME]: ["pass", "bounce", "escalate"],
|
|
120
|
-
[COUNTERSIGN_OUTPUT_TOOL_NAME]: ["converged", "continue", "escalate"],
|
|
121
|
-
[GLEANER_LEFT_OUTPUT_TOOL_NAME]: ["completed"],
|
|
122
|
-
[INSPECTOR_OUTPUT_TOOL_NAME]: ["pass", "bounce", "escalate"],
|
|
123
|
-
[GATEKEEPER_OUTPUT_TOOL_NAME]: ["dispatch", "pass"],
|
|
124
|
-
[NAVIGATOR_OUTPUT_TOOL_NAME]: ["advice"],
|
|
125
|
-
[AUDITOR_OUTPUT_TOOL_NAME]: ["pass", "bounce", "escalate"],
|
|
126
|
-
[DIARIST_OUTPUT_TOOL_NAME]: ["completed", "escalate"],
|
|
127
|
-
};
|
|
128
|
-
const collectorDiscriminator = toolName === COLLECTOR_OUTPUT_TOOL && Array.isArray(candidate?.groups);
|
|
129
|
-
const baseDiscriminator = discriminator;
|
|
130
|
-
const runtimeBindingMissing = (toolName === DOCTOR_OUTPUT_TOOL_NAME && baseDiscriminator === "completed" && !(candidate?.cost !== null && typeof candidate?.cost === "object")) ||
|
|
131
|
-
(toolName === REVIEWER_OUTPUT_TOOL_NAME && candidate?.version !== 2);
|
|
132
|
-
if (runtimeBindingMissing ||
|
|
133
|
-
(!collectorDiscriminator && (typeof discriminator !== "string" || !lawfulStatuses[toolName].includes(baseDiscriminator)))) {
|
|
134
|
-
throw new AcceptedDetailsContractError("terminating receipt has no recognized execution discriminator");
|
|
135
|
-
}
|
|
136
|
-
try {
|
|
137
|
-
switch (toolName) {
|
|
138
|
-
case CODER_OUTPUT_TOOL_NAME:
|
|
139
|
-
return validateAcceptedWorkerDetails(details, "Coder");
|
|
140
|
-
case FIXER_OUTPUT_TOOL_NAME:
|
|
141
|
-
return validateAcceptedWorkerDetails(details, "Fixer");
|
|
142
|
-
case REVIEWER_OUTPUT_TOOL_NAME:
|
|
143
|
-
return validateRuntimeReviewerReceipt(details);
|
|
144
|
-
case JUDGE_OUTPUT_TOOL_NAME:
|
|
145
|
-
return validateAcceptedJudgeDetails(details);
|
|
146
|
-
case COLLECTOR_OUTPUT_TOOL:
|
|
147
|
-
return validateAcceptedCollectorReceipt(details);
|
|
148
|
-
case DOCTOR_OUTPUT_TOOL_NAME:
|
|
149
|
-
return validateRecordedDoctorOutput(details);
|
|
150
|
-
case MERGER_OUTPUT_TOOL_NAME:
|
|
151
|
-
return validateMergerOutput(details);
|
|
152
|
-
case NOTARY_OUTPUT_TOOL_NAME:
|
|
153
|
-
return validateRecordedNotaryOutput(details);
|
|
154
|
-
case COUNTERSIGN_OUTPUT_TOOL_NAME:
|
|
155
|
-
return validateRecordedCountersignOutput(details);
|
|
156
|
-
case GLEANER_LEFT_OUTPUT_TOOL_NAME:
|
|
157
|
-
return validateRecordedGleanerLeftOutput(details);
|
|
158
|
-
case INSPECTOR_OUTPUT_TOOL_NAME:
|
|
159
|
-
return validateRecordedInspectorOutput(details);
|
|
160
|
-
case GATEKEEPER_OUTPUT_TOOL_NAME:
|
|
161
|
-
return validateRecordedGatekeeperOutput(details);
|
|
162
|
-
case NAVIGATOR_OUTPUT_TOOL_NAME:
|
|
163
|
-
return validateRecordedNavigatorOutput(details);
|
|
164
|
-
case AUDITOR_OUTPUT_TOOL_NAME:
|
|
165
|
-
return validateRecordedAuditorOutput(details);
|
|
166
|
-
case DIARIST_OUTPUT_TOOL_NAME:
|
|
167
|
-
return validateRecordedDiaristOutput(details);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
catch (error) {
|
|
171
|
-
if (error instanceof Error && error.constructor === Error)
|
|
172
|
-
throw new AcceptedDetailsContractError(error.message, { cause: error });
|
|
173
|
-
throw error;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
export function validateAcceptedLifecycle(toolName, argumentsValue, detailsValue) {
|
|
177
|
-
const details = validateAcceptedDetails(toolName, detailsValue);
|
|
178
|
-
if (toolName === DOCTOR_OUTPUT_TOOL_NAME) {
|
|
179
|
-
const testimony = validateDoctorSubmissionShape(argumentsValue);
|
|
180
|
-
if ((String(testimony.status)) === "refused") {
|
|
181
|
-
if (!deepEqual(testimony, details))
|
|
182
|
-
throw new Error("accepted tool lifecycle details mismatch");
|
|
183
|
-
return details;
|
|
184
|
-
}
|
|
185
|
-
const receipt = details;
|
|
186
|
-
if ((String(receipt.status)) !== "completed") {
|
|
187
|
-
throw new Error("accepted tool lifecycle details mismatch");
|
|
188
|
-
}
|
|
189
|
-
const { cost: _runtimeCost, ...projected } = receipt;
|
|
190
|
-
if (!deepEqual(testimony, projected))
|
|
191
|
-
throw new Error("accepted tool lifecycle details mismatch");
|
|
192
|
-
return details;
|
|
193
|
-
}
|
|
194
|
-
if (toolName === DIARIST_OUTPUT_TOOL_NAME) {
|
|
195
|
-
// Envelope-owned mechanical sitian facts are runtime-bound on details only
|
|
196
|
-
// (same shape as the Doctor runtime cost); the submitted arguments carry the
|
|
197
|
-
// role's own entries. Machine facts never come from model self-report.
|
|
198
|
-
const { sitian: _mechanical, ...submitted } = details;
|
|
199
|
-
const testimony = validateAcceptedDetails(toolName, argumentsValue);
|
|
200
|
-
if (!deepEqual(testimony, submitted))
|
|
201
|
-
throw new Error("accepted tool lifecycle details mismatch");
|
|
82
|
+
/**
|
|
83
|
+
* #836: status allowlist rejection deleted. Original object is the receipt.
|
|
84
|
+
* Callers that need a typed view may still cast; code must not bounce on status.
|
|
85
|
+
*/
|
|
86
|
+
export function validateAcceptedDetails(_toolName, details) {
|
|
87
|
+
if (details !== null && typeof details === "object" && !Array.isArray(details)) {
|
|
202
88
|
return details;
|
|
203
89
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
90
|
+
// Non-object payload still records as empty object rather than rejecting.
|
|
91
|
+
return {};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* #836: args↔details equality rejection deleted. Details are recorded as submitted.
|
|
95
|
+
*/
|
|
96
|
+
export function validateAcceptedLifecycle(toolName, _argumentsValue, detailsValue) {
|
|
97
|
+
return validateAcceptedDetails(toolName, detailsValue);
|
|
208
98
|
}
|
|
99
|
+
/** Read status/commit leaves the role wrote — never invent defaults (#836). */
|
|
209
100
|
export function acceptedFacts(toolName, details) {
|
|
101
|
+
const record = details;
|
|
210
102
|
switch (toolName) {
|
|
211
|
-
case
|
|
212
|
-
|
|
213
|
-
case
|
|
214
|
-
|
|
215
|
-
case NOTARY_OUTPUT_TOOL_NAME:
|
|
216
|
-
case GLEANER_LEFT_OUTPUT_TOOL_NAME:
|
|
217
|
-
case INSPECTOR_OUTPUT_TOOL_NAME:
|
|
218
|
-
case GATEKEEPER_OUTPUT_TOOL_NAME:
|
|
219
|
-
case NAVIGATOR_OUTPUT_TOOL_NAME:
|
|
220
|
-
case AUDITOR_OUTPUT_TOOL_NAME:
|
|
221
|
-
return { status: details.status };
|
|
222
|
-
case DIARIST_OUTPUT_TOOL_NAME: return { status: details.status };
|
|
223
|
-
case JUDGE_OUTPUT_TOOL_NAME: return { status: details.judgeStatus };
|
|
224
|
-
case COUNTERSIGN_OUTPUT_TOOL_NAME: return { status: details.countersignStatus };
|
|
103
|
+
case JUDGE_OUTPUT_TOOL_NAME:
|
|
104
|
+
return typeof record.judgeStatus === "string" ? { status: record.judgeStatus } : {};
|
|
105
|
+
case COUNTERSIGN_OUTPUT_TOOL_NAME:
|
|
106
|
+
return typeof record.countersignStatus === "string" ? { status: record.countersignStatus } : {};
|
|
225
107
|
case MERGER_OUTPUT_TOOL_NAME: {
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
108
|
+
const status = typeof record.status === "string" ? record.status : undefined;
|
|
109
|
+
return {
|
|
110
|
+
...(status === undefined ? {} : { status }),
|
|
111
|
+
...(status === "completed" && typeof record.mergeCommitId === "string"
|
|
112
|
+
? { commit: record.mergeCommitId }
|
|
113
|
+
: {}),
|
|
114
|
+
};
|
|
229
115
|
}
|
|
230
116
|
case COLLECTOR_OUTPUT_TOOL:
|
|
231
|
-
|
|
117
|
+
// Collector has no status leaf — do not invent "collected".
|
|
118
|
+
return typeof record.status === "string" ? { status: record.status } : {};
|
|
119
|
+
default:
|
|
120
|
+
return typeof record.status === "string" ? { status: record.status } : {};
|
|
232
121
|
}
|
|
233
122
|
}
|
|
234
123
|
/** Deep structural equality for lifecycle agreement checks. */
|
|
@@ -2,8 +2,7 @@ import {
|
|
|
2
2
|
FIXER_ACCEPTED_TEXT,
|
|
3
3
|
FIXER_OUTPUT_TOOL_NAME,
|
|
4
4
|
fixerOutputSchema,
|
|
5
|
-
validateFixerOutput
|
|
6
|
-
validateFixerOutputForPacket
|
|
5
|
+
validateFixerOutput
|
|
7
6
|
} from "./fixer-output.js";
|
|
8
7
|
import { fixerPrerequisiteSchema, fixerPrerequisitesSchema, parseFixerPrerequisites, validateFixerPrerequisites } from "./fixer-packet.js";
|
|
9
8
|
import { validateFixerOutput as validateFixerOutput2 } from "./fixer-output.js";
|
|
@@ -27,6 +26,5 @@ export {
|
|
|
27
26
|
validateAcceptedCoderDetails,
|
|
28
27
|
validateAcceptedWorkerDetails,
|
|
29
28
|
validateFixerOutput,
|
|
30
|
-
validateFixerOutputForPacket,
|
|
31
29
|
validateFixerPrerequisites
|
|
32
30
|
};
|
|
@@ -208,29 +208,35 @@ function jsonSafeReplacer() {
|
|
|
208
208
|
* open (O_EXCL) with a per-attempt unique name enforces 史必追加 (#419): a later
|
|
209
209
|
* attempt can never overwrite an earlier attempt's file.
|
|
210
210
|
*/
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
// O_EXCL: exclusive create — the retention history is append-only by
|
|
222
|
-
// construction; a colliding name fails loudly instead of overwriting.
|
|
223
|
-
// O_NOFOLLOW when the platform provides it keeps a planted symlink from
|
|
224
|
-
// being followed; on platforms without it, exclusivity still holds.
|
|
225
|
-
// AK artifact owner stays here; only the session JSONL pointer uses Pi codec.
|
|
211
|
+
/**
|
|
212
|
+
* Hardened create-once JSON write shared by every durable artifact this loop
|
|
213
|
+
* retains directly (dispatch-error dumps, lawful-persist-failure error/
|
|
214
|
+
* evidence records): O_EXCL (fail loud on a colliding name, never overwrite)
|
|
215
|
+
* + O_NOFOLLOW where the platform provides it (a planted symlink is never
|
|
216
|
+
* followed) — mirrors settlement.ts's own hardened artifact writers.
|
|
217
|
+
*/
|
|
218
|
+
async function writeHardenedArtifactFile(artifactsDir, namePrefix, payload) {
|
|
219
|
+
const filePath = join(artifactsDir, `${namePrefix}-${randomUUID()}.json`);
|
|
220
|
+
const body = `${JSON.stringify(payload, jsonSafeReplacer(), 2)}\n`;
|
|
226
221
|
const noFollowFlag = typeof fsConstants.O_NOFOLLOW === "number" ? fsConstants.O_NOFOLLOW : 0;
|
|
227
222
|
const handle = await open(filePath, fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | noFollowFlag, 0o600);
|
|
228
223
|
try {
|
|
229
|
-
await handle.writeFile(
|
|
224
|
+
await handle.writeFile(body, "utf8");
|
|
230
225
|
}
|
|
231
226
|
finally {
|
|
232
227
|
await handle.close();
|
|
233
228
|
}
|
|
229
|
+
return filePath;
|
|
230
|
+
}
|
|
231
|
+
async function retainDispatchError(admitted, principalAuthority, sessionAppender, attempt, error) {
|
|
232
|
+
const artifactsDir = await ensureRealArtifactsDirectory(admitted.runDirectory);
|
|
233
|
+
// Whole-object dump: everything the thrown value carries, nothing picked.
|
|
234
|
+
const filePath = await writeHardenedArtifactFile(artifactsDir, `dispatch-error-attempt-${attempt}`, {
|
|
235
|
+
version: 1,
|
|
236
|
+
attempt,
|
|
237
|
+
recordedAt: new Date().toISOString(),
|
|
238
|
+
error: serializeThrownValue(error),
|
|
239
|
+
});
|
|
234
240
|
// Addressable pointer in the dossier (卷宗): Pi session custom-entry codec
|
|
235
241
|
// (appendPiSessionCustomEntry). Lease still owned here with run-writer.
|
|
236
242
|
let pointerLease;
|
|
@@ -380,7 +386,14 @@ export async function runWithAutoResumeLoop(options) {
|
|
|
380
386
|
}
|
|
381
387
|
}
|
|
382
388
|
dispatchOrdinal += 1;
|
|
383
|
-
|
|
389
|
+
// #836 r12 class 3: run-state persist for a dispatch that deferred it
|
|
390
|
+
// (needsPersist) is settled by the dispatch closure itself, before this
|
|
391
|
+
// loop ever sees the result — through the single existing
|
|
392
|
+
// presentControlledFailure / settleFailureTerminalResult authority (ADR
|
|
393
|
+
// 0080), never a second hand-rolled classify/artifact/Terminal here. This
|
|
394
|
+
// loop only ever sees the already-resolved outcome: a lawful/failure
|
|
395
|
+
// Terminal (with skipAutoResume set when persist failed after an
|
|
396
|
+
// already-settled result) or the original non-lawful result unchanged.
|
|
384
397
|
if (result !== undefined) {
|
|
385
398
|
everyAttemptThrew = false;
|
|
386
399
|
const terminal = result.terminal;
|
|
@@ -388,21 +401,6 @@ export async function runWithAutoResumeLoop(options) {
|
|
|
388
401
|
terminal.autoResumeCount = autoResumeAttempts;
|
|
389
402
|
}
|
|
390
403
|
const lawful = terminal !== undefined && isLawfulTypedTerminalOutcome(terminal.roleOutcome);
|
|
391
|
-
if (result.needsPersist === true) {
|
|
392
|
-
// Persist on the loop seam, not inside retried dispatch.
|
|
393
|
-
try {
|
|
394
|
-
await persistReturnedRunState(options.admitted, { isAvailable: isPrincipalAvailable }, lawful ? { lawful: true } : undefined);
|
|
395
|
-
}
|
|
396
|
-
catch (persistError) {
|
|
397
|
-
// Lawful persist stays loud (no fake terminal). Non-lawful persist is
|
|
398
|
-
// not a host-turn failure — do not auto-resume it — but sealed stop
|
|
399
|
-
// must still see the already-settled result (#648).
|
|
400
|
-
if (lawful)
|
|
401
|
-
throw persistError;
|
|
402
|
-
persistFailure = { error: persistError };
|
|
403
|
-
lastThrownError = persistError;
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
404
|
if (lawful) {
|
|
407
405
|
if (terminal !== undefined) {
|
|
408
406
|
// Present lawful terminal once to real io (dummy was used inside dispatch)
|
|
@@ -416,42 +414,6 @@ export async function runWithAutoResumeLoop(options) {
|
|
|
416
414
|
return result;
|
|
417
415
|
}
|
|
418
416
|
}
|
|
419
|
-
// Settlement-owned sealed disposition before any redispatch (#648 / #672):
|
|
420
|
-
// shared for non-lawful return and direct throw. Only entry presentation
|
|
421
|
-
// differs (present returned terminal vs throw-path synthetic).
|
|
422
|
-
if (options.sealedAcceptanceDisposition !== undefined) {
|
|
423
|
-
const disposition = await options.sealedAcceptanceDisposition();
|
|
424
|
-
if (disposition.kind === "block") {
|
|
425
|
-
if (disposition.reason === "sealed-accepted" && result !== undefined) {
|
|
426
|
-
const terminal = result.terminal;
|
|
427
|
-
if (terminal !== undefined)
|
|
428
|
-
presentTerminal(terminal, options.io);
|
|
429
|
-
return result;
|
|
430
|
-
}
|
|
431
|
-
const terminal = dispatchExceptionFailureTerminal({
|
|
432
|
-
role: options.admitted.role,
|
|
433
|
-
runId: options.admitted.runId,
|
|
434
|
-
causeError: disposition.reason === "authority-failed"
|
|
435
|
-
? disposition.cause
|
|
436
|
-
: lastThrownError,
|
|
437
|
-
errorFiles: retainedErrorFiles,
|
|
438
|
-
autoResumeAttempts,
|
|
439
|
-
endReason: disposition.reason === "authority-failed"
|
|
440
|
-
? "sealed-acceptance authority failed closed"
|
|
441
|
-
: "sealed accepted projection already present",
|
|
442
|
-
everyAttemptThrew,
|
|
443
|
-
});
|
|
444
|
-
await finalizeExceptionRunBestEffort(options.admitted.runDirectory, options.io);
|
|
445
|
-
presentTerminal(terminal, options.io);
|
|
446
|
-
return {
|
|
447
|
-
exitCode: 1,
|
|
448
|
-
terminal,
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
if (persistFailure !== undefined) {
|
|
453
|
-
throw persistFailure.error;
|
|
454
|
-
}
|
|
455
417
|
if (result !== undefined) {
|
|
456
418
|
const terminal = result.terminal;
|
|
457
419
|
if (autoResumeAttempts >= limit) {
|
|
@@ -7,24 +7,12 @@
|
|
|
7
7
|
*
|
|
8
8
|
* 递送挂载点唯一:`post-admission` 在 beforeDispatch 之后为每个公共入口追加本段。
|
|
9
9
|
*/
|
|
10
|
-
import { stat } from "node:fs/promises";
|
|
11
10
|
import { resolveTicketProvenanceVolume } from "../ticket-provenance.js";
|
|
12
11
|
/** Section heading of the system-delivered dossier pointer (presentation only). */
|
|
13
12
|
const CASE_DOSSIER_SECTION_HEADING = "## 本票起居录(系统随案提供)";
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const stats = await stat(path);
|
|
18
|
-
if (!stats.isFile())
|
|
19
|
-
return `不可读(非普通文件):${path}`;
|
|
20
|
-
return path;
|
|
21
|
-
}
|
|
22
|
-
catch (error) {
|
|
23
|
-
const code = error.code;
|
|
24
|
-
if (code === "ENOENT")
|
|
25
|
-
return `尚未生成:${path}`;
|
|
26
|
-
return `不可读(${code ?? "未知错误"}):${path}`;
|
|
27
|
-
}
|
|
13
|
+
/** Pointer only — presence/absence is for the role to observe at the path. */
|
|
14
|
+
function describeDossierFile(path) {
|
|
15
|
+
return path;
|
|
28
16
|
}
|
|
29
17
|
/**
|
|
30
18
|
* Pointer section for a bound ticket's existing 起居录, or undefined when the
|
|
@@ -40,7 +28,7 @@ export async function projectCaseDossierPointerSection(input) {
|
|
|
40
28
|
CASE_DOSSIER_SECTION_HEADING,
|
|
41
29
|
"",
|
|
42
30
|
`票号:#${input.ticketNumber}`,
|
|
43
|
-
`人读视图:${
|
|
44
|
-
`记录卷宗:${
|
|
31
|
+
`人读视图:${describeDossierFile(volume.humanViewFile)}`,
|
|
32
|
+
`记录卷宗:${describeDossierFile(volume.recordFile)}`,
|
|
45
33
|
].join("\n");
|
|
46
34
|
}
|
|
@@ -5,6 +5,7 @@ import { prepareSummonsResumeMaterials, runPostAdmissionOneShot, runPostAdmissio
|
|
|
5
5
|
import { loadResumableDiaristRun, markRunAdmitted, } from "./run-lifecycle.js";
|
|
6
6
|
import { tryResumeSameTicketSeatRun } from "./seat-ticket-binding.js";
|
|
7
7
|
import { presentStructuralRejection, trySettleDiaristTerminalResult, } from "./settlement.js";
|
|
8
|
+
import { lastRolePayloadRecord } from "./terminal.js";
|
|
8
9
|
import { projectRoleTurnRequest, } from "./turn-request.js";
|
|
9
10
|
/** Project admitted invocation onto the host-neutral turn request. */
|
|
10
11
|
export function buildDiaristTurnRequest(admitted, options) {
|
|
@@ -114,13 +115,17 @@ export async function runPublicDiarist(argv, env, io, parseDiaristArgv) {
|
|
|
114
115
|
// leak an unverified ticketNumber into the caller-visible typed key.
|
|
115
116
|
if (admitted.ticketNumber === undefined && result.admitted !== undefined) {
|
|
116
117
|
const roleOutcome = result.terminal?.roleOutcome;
|
|
118
|
+
const facts = roleOutcome?.kind === "accepted"
|
|
119
|
+
? lastRolePayloadRecord(roleOutcome.payloads ?? [])
|
|
120
|
+
: undefined;
|
|
117
121
|
if (roleOutcome !== undefined &&
|
|
118
122
|
roleOutcome.kind === "accepted" &&
|
|
119
|
-
|
|
120
|
-
const
|
|
121
|
-
const raw = typeof facts.ticketNumber === "number"
|
|
123
|
+
facts?.status !== "escalate") {
|
|
124
|
+
const raw = typeof facts?.ticketNumber === "number"
|
|
122
125
|
? facts.ticketNumber
|
|
123
|
-
: typeof facts
|
|
126
|
+
: typeof facts?.sitian === "object"
|
|
127
|
+
&& facts.sitian !== null
|
|
128
|
+
&& typeof facts.sitian.ticketNumber === "number"
|
|
124
129
|
? facts.sitian.ticketNumber
|
|
125
130
|
: undefined;
|
|
126
131
|
if (typeof raw === "number" && Number.isSafeInteger(raw) && raw >= 1) {
|
|
@@ -34,8 +34,9 @@ export async function runPublicInspector(argv, env, io, parseInspectorArgv) {
|
|
|
34
34
|
// #753/#786: gate re-ask / verbatim submission body ride summons.instruction on resume.
|
|
35
35
|
const parentRunPath = parentRunPathFromGatePointerInstruction(parsed.instruction);
|
|
36
36
|
if (parentRunPath !== undefined) {
|
|
37
|
-
const resumeInstruction = env.reviewReask
|
|
37
|
+
const resumeInstruction = env.reviewReask;
|
|
38
38
|
const summons = {
|
|
39
|
+
sourceRunPath: parentRunPath,
|
|
39
40
|
...(resumeInstruction === undefined
|
|
40
41
|
? {
|
|
41
42
|
instruction: parsed.instruction,
|
|
@@ -55,13 +56,6 @@ export async function runPublicInspector(argv, env, io, parseInspectorArgv) {
|
|
|
55
56
|
});
|
|
56
57
|
if (resumed !== undefined)
|
|
57
58
|
return resumed;
|
|
58
|
-
// Reask without a prior same-parent run cannot deliver the plain-language ask
|
|
59
|
-
// on a fresh mint without inventing a second prompt path — fail loud (#753).
|
|
60
|
-
// gateReviewInstruction (verbatim body) alone is resume-only; fresh mint keeps argv 卷宗指针.
|
|
61
|
-
if (env.reviewReask !== undefined) {
|
|
62
|
-
presentStructuralRejection(new CliUsageError("inspector review reask requires a prior same-parent run to resume"), io);
|
|
63
|
-
return { exitCode: 2 };
|
|
64
|
-
}
|
|
65
59
|
}
|
|
66
60
|
let admitted;
|
|
67
61
|
try {
|
|
@@ -151,7 +151,7 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
|
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
153
|
// #756/#786: auditor reask / verbatim submission body ride summons.instruction on resume.
|
|
154
|
-
const resumeInstruction = env.reviewReask
|
|
154
|
+
const resumeInstruction = env.reviewReask;
|
|
155
155
|
const summons = {
|
|
156
156
|
...(resumeInstruction === undefined
|
|
157
157
|
? {
|
|
@@ -177,12 +177,8 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
|
|
|
177
177
|
});
|
|
178
178
|
if (resumed !== undefined)
|
|
179
179
|
return resumed;
|
|
180
|
-
//
|
|
181
|
-
//
|
|
182
|
-
if (env.reviewReask !== undefined) {
|
|
183
|
-
presentStructuralRejection(new CliUsageError("auditor review reask requires a prior same-parent run to resume"), io);
|
|
184
|
-
return { exitCode: 2 };
|
|
185
|
-
}
|
|
180
|
+
// #836: reask without a prior same-parent run still mints; summons.instruction
|
|
181
|
+
// already carries the reask text. Do not structurally terminate the queue.
|
|
186
182
|
}
|
|
187
183
|
let admitted;
|
|
188
184
|
try {
|
|
@@ -1816,13 +1816,16 @@ export async function admitReviewerInvocation(options) {
|
|
|
1816
1816
|
}
|
|
1817
1817
|
/**
|
|
1818
1818
|
* Build the Pi prompt transport for an admitted Reviewer request.
|
|
1819
|
-
*
|
|
1820
|
-
*
|
|
1819
|
+
* #836: caller instruction is no longer dropped (A3.5).
|
|
1820
|
+
* Fixed base + optional caller words + engine material.
|
|
1821
1821
|
*/
|
|
1822
1822
|
export function buildReviewerTransportPrompt(admitted, engineMaterial) {
|
|
1823
1823
|
const lines = [
|
|
1824
1824
|
`本次审查的固定基点:${admitted.baseRevision}`,
|
|
1825
1825
|
];
|
|
1826
|
+
if (!admitted.instructionEmpty && admitted.instruction.trim() !== "") {
|
|
1827
|
+
lines.push("", admitted.instruction);
|
|
1828
|
+
}
|
|
1826
1829
|
return appendEngineSessionMaterial(lines, engineMaterial).join("\n");
|
|
1827
1830
|
}
|
|
1828
1831
|
/**
|