@akagilnc/pi-workflow-roles 0.1.2139 → 0.1.2148
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/doctor-contracts.js +10 -2
- package/dist/engine-labor-fallback.js +129 -114
- package/dist/merger-contracts.js +9 -2
- package/dist/navigator-attendance.js +9 -1
- package/dist/package-contracts/judge-output.js +8 -1
- package/dist/package-contracts/reviewer-output.js +9 -1
- package/dist/package-contracts/terminating-tools.js +14 -5
- package/dist/public-cli/main.js +116 -64
- package/package.json +1 -1
- package/resources/engines/grok-4.6.md +5 -0
- package/scripts/build-package.mjs +2 -0
- package/src/doctor-contracts.ts +19 -3
- package/src/engine-labor-fallback.ts +100 -2
- package/src/factory-board.ts +6 -2
- package/src/merger-contracts.ts +18 -3
- package/src/navigator-attendance.ts +16 -1
- package/src/package-contracts/judge-output.ts +25 -2
- package/src/package-contracts/reviewer-output.ts +23 -2
- package/src/package-contracts/terminating-tools.ts +22 -6
- package/src/package-contracts/worker-output.ts +10 -2
- package/src/public-cli/settlement.ts +51 -17
- package/src/role-runtime.ts +8 -1
- package/src/taishi-metric-families/acceptance-success-rework.ts +6 -3
package/dist/public-cli/main.js
CHANGED
|
@@ -136,6 +136,54 @@ var init_collector_output = __esm({
|
|
|
136
136
|
}
|
|
137
137
|
});
|
|
138
138
|
|
|
139
|
+
// src/engine-labor-fallback.ts
|
|
140
|
+
function buildEngineLaborFallbackField(input) {
|
|
141
|
+
return Object.freeze({
|
|
142
|
+
engineLaborFallback: Object.freeze({
|
|
143
|
+
engine: input.engine,
|
|
144
|
+
failure: input.failure,
|
|
145
|
+
laborBy: "seat"
|
|
146
|
+
})
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
function isSeatFallbackTaintedStatus(status) {
|
|
150
|
+
return status.endsWith(SEAT_FALLBACK_STATUS_SUFFIX);
|
|
151
|
+
}
|
|
152
|
+
function seatFallbackBaseStatus(status) {
|
|
153
|
+
return isSeatFallbackTaintedStatus(status) ? status.slice(0, -SEAT_FALLBACK_STATUS_SUFFIX.length) : status;
|
|
154
|
+
}
|
|
155
|
+
function seatFallbackStatusHasLawfulEvidence(status, source) {
|
|
156
|
+
if (!isSeatFallbackTaintedStatus(status)) return true;
|
|
157
|
+
return readEngineLaborFallbackFieldFrom(source) !== void 0;
|
|
158
|
+
}
|
|
159
|
+
function readEngineLaborFallbackFieldFrom(source) {
|
|
160
|
+
if (typeof source !== "object" || source === null || Array.isArray(source)) {
|
|
161
|
+
return void 0;
|
|
162
|
+
}
|
|
163
|
+
let raw;
|
|
164
|
+
try {
|
|
165
|
+
raw = source.engineLaborFallback;
|
|
166
|
+
} catch {
|
|
167
|
+
return void 0;
|
|
168
|
+
}
|
|
169
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return void 0;
|
|
170
|
+
const rec = raw;
|
|
171
|
+
if (typeof rec.engine !== "string" || typeof rec.failure !== "string" || rec.laborBy !== "seat") {
|
|
172
|
+
return void 0;
|
|
173
|
+
}
|
|
174
|
+
return buildEngineLaborFallbackField({
|
|
175
|
+
engine: rec.engine,
|
|
176
|
+
failure: rec.failure
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
var SEAT_FALLBACK_STATUS_SUFFIX;
|
|
180
|
+
var init_engine_labor_fallback = __esm({
|
|
181
|
+
"src/engine-labor-fallback.ts"() {
|
|
182
|
+
"use strict";
|
|
183
|
+
SEAT_FALLBACK_STATUS_SUFFIX = "-by-fallback";
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
139
187
|
// src/package-contracts/judge-output.ts
|
|
140
188
|
function validateAcceptedJudgeDetails(verdict) {
|
|
141
189
|
if (verdict === null || typeof verdict !== "object" || Array.isArray(verdict)) throw new Error("Judge verdict has no execution discriminator");
|
|
@@ -145,13 +193,20 @@ function validateAcceptedJudgeDetails(verdict) {
|
|
|
145
193
|
} catch {
|
|
146
194
|
throw new Error("Judge verdict has no execution discriminator");
|
|
147
195
|
}
|
|
148
|
-
if (
|
|
196
|
+
if (typeof judgeStatus !== "string") {
|
|
197
|
+
throw new Error("Judge verdict has no execution discriminator");
|
|
198
|
+
}
|
|
199
|
+
const base = seatFallbackBaseStatus(judgeStatus);
|
|
200
|
+
if (["converged", "continue", "escalate"].includes(base) && seatFallbackStatusHasLawfulEvidence(judgeStatus, verdict)) {
|
|
201
|
+
return verdict;
|
|
202
|
+
}
|
|
149
203
|
throw new Error("Judge verdict has no execution discriminator");
|
|
150
204
|
}
|
|
151
205
|
var JUDGE_OUTPUT_TOOL_NAME;
|
|
152
206
|
var init_judge_output = __esm({
|
|
153
207
|
"src/package-contracts/judge-output.ts"() {
|
|
154
208
|
"use strict";
|
|
209
|
+
init_engine_labor_fallback();
|
|
155
210
|
JUDGE_OUTPUT_TOOL_NAME = "ak_judge_output";
|
|
156
211
|
}
|
|
157
212
|
});
|
|
@@ -169,6 +224,10 @@ function read(value, key) {
|
|
|
169
224
|
}
|
|
170
225
|
}
|
|
171
226
|
function validateRuntimeReviewerReceipt(output) {
|
|
227
|
+
const status = read(output, "status");
|
|
228
|
+
if (typeof status === "string" && !seatFallbackStatusHasLawfulEvidence(status, output)) {
|
|
229
|
+
throw new Error("Reviewer receipt has no recognized execution discriminator");
|
|
230
|
+
}
|
|
172
231
|
const acceptedBatch = read(output, "acceptedBatch");
|
|
173
232
|
const identities = read(output, "identities");
|
|
174
233
|
const construction = read(identities, "construction");
|
|
@@ -199,11 +258,11 @@ function validateRuntimeReviewerReceipt(output) {
|
|
|
199
258
|
const expectedPrompt = read(read(legs[index], "prompt"), "text");
|
|
200
259
|
const actualPrompt = read(read(outcome, "prompt"), "text");
|
|
201
260
|
if (expectedPrompt !== actualPrompt) throw new Error("Reviewer outcome prompt disagrees with accepted leg");
|
|
202
|
-
const
|
|
261
|
+
const status2 = read(outcome, "status");
|
|
203
262
|
const report = read(reports, axis);
|
|
204
|
-
if (
|
|
263
|
+
if (status2 === "successful" && report === void 0)
|
|
205
264
|
throw new Error("Successful Reviewer outcome lacks report");
|
|
206
|
-
if (
|
|
265
|
+
if (status2 === "failed" && report !== void 0) throw new Error("Failed Reviewer outcome cannot bind a report");
|
|
207
266
|
}
|
|
208
267
|
const specDisposition = read(output, "specDisposition");
|
|
209
268
|
if (specDisposition === "launched") {
|
|
@@ -224,6 +283,7 @@ var REVIEWER_OUTPUT_TOOL_NAME;
|
|
|
224
283
|
var init_reviewer_output = __esm({
|
|
225
284
|
"src/package-contracts/reviewer-output.ts"() {
|
|
226
285
|
"use strict";
|
|
286
|
+
init_engine_labor_fallback();
|
|
227
287
|
REVIEWER_OUTPUT_TOOL_NAME = "ak_reviewer_output";
|
|
228
288
|
}
|
|
229
289
|
});
|
|
@@ -14086,12 +14146,18 @@ function read2(value, key) {
|
|
|
14086
14146
|
}
|
|
14087
14147
|
function validateDoctorSubmissionShape(value) {
|
|
14088
14148
|
const status = read2(value, "status");
|
|
14089
|
-
|
|
14149
|
+
const base = typeof status === "string" ? seatFallbackBaseStatus(status) : status;
|
|
14150
|
+
if (base !== "completed" && base !== "refused") throw new DoctorSubmissionContractError("Doctor submission has no recognized execution status");
|
|
14151
|
+
if (typeof status === "string" && !seatFallbackStatusHasLawfulEvidence(status, value)) {
|
|
14152
|
+
throw new DoctorSubmissionContractError("Doctor submission has no recognized execution status");
|
|
14153
|
+
}
|
|
14090
14154
|
return value;
|
|
14091
14155
|
}
|
|
14092
14156
|
function validateRecordedDoctorOutput(value) {
|
|
14093
14157
|
const output = validateDoctorSubmissionShape(value);
|
|
14094
|
-
|
|
14158
|
+
const status = read2(output, "status");
|
|
14159
|
+
const base = typeof status === "string" ? seatFallbackBaseStatus(status) : status;
|
|
14160
|
+
if (base === "completed" && read2(output, "cost") === void 0) throw new Error("Completed Doctor receipt has no runtime-owned cost testimony");
|
|
14095
14161
|
return output;
|
|
14096
14162
|
}
|
|
14097
14163
|
var DOCTOR_OUTPUT_TOOL_NAME, DOCTOR_TARGET_KINDS, nonblank, count, evidenceIds, guardrail, lastRealBite, assetKinds, findingBody, finding, caseIdentity, cost, doctorSubmissionVariants, doctorSubmissionSchema, doctorOutputSchema, doctorEvidenceReadSchema, DoctorSubmissionContractError;
|
|
@@ -14100,6 +14166,7 @@ var init_doctor_contracts = __esm({
|
|
|
14100
14166
|
"use strict";
|
|
14101
14167
|
init_build();
|
|
14102
14168
|
init_canonical_json();
|
|
14169
|
+
init_engine_labor_fallback();
|
|
14103
14170
|
init_open_tool_schema();
|
|
14104
14171
|
DOCTOR_OUTPUT_TOOL_NAME = "ak_doctor_output";
|
|
14105
14172
|
DOCTOR_TARGET_KINDS = ["law", "gate", "template", "station", "seat"];
|
|
@@ -14243,8 +14310,13 @@ function validateMergerInput(value) {
|
|
|
14243
14310
|
}
|
|
14244
14311
|
function validateMergerOutput(value, expectedAttemptId) {
|
|
14245
14312
|
if (!record(value) || expectedAttemptId !== void 0 && value.attemptId !== expectedAttemptId) throw new Error("Merger output attempt mismatch");
|
|
14246
|
-
|
|
14247
|
-
|
|
14313
|
+
const status = typeof value.status === "string" ? value.status : void 0;
|
|
14314
|
+
const statusBase = status !== void 0 ? seatFallbackBaseStatus(status) : void 0;
|
|
14315
|
+
if (status !== void 0 && !seatFallbackStatusHasLawfulEvidence(status, value)) {
|
|
14316
|
+
throw new Error("Merger output has no recognized execution discriminator");
|
|
14317
|
+
}
|
|
14318
|
+
if (statusBase === "completed" && isFullGitObjectId(value.mergeCommitId)) return structuredClone(value);
|
|
14319
|
+
if (statusBase === "escalate") return structuredClone(value);
|
|
14248
14320
|
throw new Error("Merger output has no recognized execution discriminator");
|
|
14249
14321
|
}
|
|
14250
14322
|
var oidPattern, materialSchema, checkSchema, mergerInputSchema, mergerOutputVariants, mergerOutputSchema, MERGER_OUTPUT_TOOL_NAME, record, blank, MergerInputContractError;
|
|
@@ -14254,6 +14326,7 @@ var init_merger_contracts = __esm({
|
|
|
14254
14326
|
init_build();
|
|
14255
14327
|
init_git_object_id();
|
|
14256
14328
|
init_exact_utf8();
|
|
14329
|
+
init_engine_labor_fallback();
|
|
14257
14330
|
init_sha256();
|
|
14258
14331
|
init_open_tool_schema();
|
|
14259
14332
|
oidPattern = "^(?:[0-9a-f]{40}|[0-9a-f]{64})$";
|
|
@@ -15190,8 +15263,10 @@ function validateAcceptedDetails(toolName, details) {
|
|
|
15190
15263
|
[MERGER_OUTPUT_TOOL_NAME]: ["completed", "escalate"]
|
|
15191
15264
|
};
|
|
15192
15265
|
const collectorDiscriminator = toolName === COLLECTOR_OUTPUT_TOOL && Array.isArray(candidate?.groups);
|
|
15193
|
-
const
|
|
15194
|
-
|
|
15266
|
+
const baseDiscriminator = typeof discriminator === "string" ? seatFallbackBaseStatus(discriminator) : discriminator;
|
|
15267
|
+
const taintedWithoutEvidence = typeof discriminator === "string" && !seatFallbackStatusHasLawfulEvidence(discriminator, details);
|
|
15268
|
+
const runtimeBindingMissing = toolName === DOCTOR_OUTPUT_TOOL_NAME && baseDiscriminator === "completed" && !(candidate?.cost !== null && typeof candidate?.cost === "object") || toolName === REVIEWER_OUTPUT_TOOL_NAME && candidate?.version !== 2;
|
|
15269
|
+
if (taintedWithoutEvidence || runtimeBindingMissing || !collectorDiscriminator && (typeof discriminator !== "string" || !lawfulStatuses[toolName].includes(baseDiscriminator))) {
|
|
15195
15270
|
throw new AcceptedDetailsContractError("terminating receipt has no recognized execution discriminator");
|
|
15196
15271
|
}
|
|
15197
15272
|
try {
|
|
@@ -15227,7 +15302,8 @@ function acceptedFacts(toolName, details) {
|
|
|
15227
15302
|
return { status: details.judgeStatus };
|
|
15228
15303
|
case MERGER_OUTPUT_TOOL_NAME: {
|
|
15229
15304
|
const output = details;
|
|
15230
|
-
|
|
15305
|
+
const status = output.status;
|
|
15306
|
+
return { status, ...seatFallbackBaseStatus(status) === "completed" && typeof output.mergeCommitId === "string" ? { commit: output.mergeCommitId } : {} };
|
|
15231
15307
|
}
|
|
15232
15308
|
case COLLECTOR_OUTPUT_TOOL:
|
|
15233
15309
|
return { status: "collected" };
|
|
@@ -15241,6 +15317,7 @@ var init_terminating_tools = __esm({
|
|
|
15241
15317
|
init_judge_output();
|
|
15242
15318
|
init_reviewer_output();
|
|
15243
15319
|
init_audit_escalation();
|
|
15320
|
+
init_engine_labor_fallback();
|
|
15244
15321
|
init_doctor_contracts();
|
|
15245
15322
|
init_merger_contracts();
|
|
15246
15323
|
init_worker_output();
|
|
@@ -19266,42 +19343,6 @@ var init_auditor_dossier_tool = __esm({
|
|
|
19266
19343
|
}
|
|
19267
19344
|
});
|
|
19268
19345
|
|
|
19269
|
-
// src/engine-labor-fallback.ts
|
|
19270
|
-
function buildEngineLaborFallbackField(input) {
|
|
19271
|
-
return Object.freeze({
|
|
19272
|
-
engineLaborFallback: Object.freeze({
|
|
19273
|
-
engine: input.engine,
|
|
19274
|
-
failure: input.failure,
|
|
19275
|
-
laborBy: "seat"
|
|
19276
|
-
})
|
|
19277
|
-
});
|
|
19278
|
-
}
|
|
19279
|
-
function readEngineLaborFallbackFieldFrom(source) {
|
|
19280
|
-
if (typeof source !== "object" || source === null || Array.isArray(source)) {
|
|
19281
|
-
return void 0;
|
|
19282
|
-
}
|
|
19283
|
-
let raw;
|
|
19284
|
-
try {
|
|
19285
|
-
raw = source.engineLaborFallback;
|
|
19286
|
-
} catch {
|
|
19287
|
-
return void 0;
|
|
19288
|
-
}
|
|
19289
|
-
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return void 0;
|
|
19290
|
-
const rec = raw;
|
|
19291
|
-
if (typeof rec.engine !== "string" || typeof rec.failure !== "string" || rec.laborBy !== "seat") {
|
|
19292
|
-
return void 0;
|
|
19293
|
-
}
|
|
19294
|
-
return buildEngineLaborFallbackField({
|
|
19295
|
-
engine: rec.engine,
|
|
19296
|
-
failure: rec.failure
|
|
19297
|
-
});
|
|
19298
|
-
}
|
|
19299
|
-
var init_engine_labor_fallback = __esm({
|
|
19300
|
-
"src/engine-labor-fallback.ts"() {
|
|
19301
|
-
"use strict";
|
|
19302
|
-
}
|
|
19303
|
-
});
|
|
19304
|
-
|
|
19305
19346
|
// src/engine-detour-tool.ts
|
|
19306
19347
|
var engineDetourArgsSchema;
|
|
19307
19348
|
var init_engine_detour_tool = __esm({
|
|
@@ -20403,7 +20444,8 @@ function judgeDecisiveFacts(verdict, judgeStatus) {
|
|
|
20403
20444
|
// #380: spread sole-built field; do not re-key here (S1).
|
|
20404
20445
|
...readEngineLaborFallbackFieldFrom(verdict)
|
|
20405
20446
|
};
|
|
20406
|
-
|
|
20447
|
+
const statusBase = seatFallbackBaseStatus(judgeStatus);
|
|
20448
|
+
if (statusBase === "continue") {
|
|
20407
20449
|
const fix = safelyRead(verdict, "fix");
|
|
20408
20450
|
if (fix.readable && isRecord5(fix.value)) {
|
|
20409
20451
|
const summary = safelyRead(fix.value, "summary");
|
|
@@ -20428,7 +20470,7 @@ function judgeDecisiveFacts(verdict, judgeStatus) {
|
|
|
20428
20470
|
}
|
|
20429
20471
|
}
|
|
20430
20472
|
}
|
|
20431
|
-
if (
|
|
20473
|
+
if (statusBase === "escalate") {
|
|
20432
20474
|
const gate = safelyRead(verdict, "decisionGate");
|
|
20433
20475
|
if (gate.readable && isRecord5(gate.value)) {
|
|
20434
20476
|
const question = safelyRead(gate.value, "question");
|
|
@@ -20452,10 +20494,11 @@ function coderDecisiveFacts(output) {
|
|
|
20452
20494
|
const status = safelyRead(candidate, "status");
|
|
20453
20495
|
const facts = {};
|
|
20454
20496
|
if (status.readable && typeof status.value === "string") facts.coderStatus = status.value;
|
|
20497
|
+
const statusBase = status.readable && typeof status.value === "string" ? seatFallbackBaseStatus(status.value) : void 0;
|
|
20455
20498
|
const remainingScope = safelyRead(candidate, "remainingScope");
|
|
20456
|
-
if (
|
|
20499
|
+
if (statusBase === "unfinished" && remainingScope.readable && typeof remainingScope.value === "string") facts.remainingScope = remainingScope.value;
|
|
20457
20500
|
const reason = safelyRead(candidate, "reason");
|
|
20458
|
-
if (
|
|
20501
|
+
if (statusBase === "unfinished" && reason.readable && typeof reason.value === "string" && reason.value.trim().length > 0) {
|
|
20459
20502
|
facts.reason = reason.value;
|
|
20460
20503
|
}
|
|
20461
20504
|
const report = safelyRead(candidate, "report");
|
|
@@ -20467,14 +20510,15 @@ function fixerDecisiveFacts(output) {
|
|
|
20467
20510
|
const status = safelyRead(candidate, "status");
|
|
20468
20511
|
const facts = {};
|
|
20469
20512
|
if (status.readable && typeof status.value === "string") facts.fixerStatus = status.value;
|
|
20513
|
+
const statusBase = status.readable && typeof status.value === "string" ? seatFallbackBaseStatus(status.value) : void 0;
|
|
20470
20514
|
const remainingScope = safelyRead(candidate, "remainingScope");
|
|
20471
|
-
if (
|
|
20515
|
+
if ((statusBase === "unfinished" || statusBase === "refused") && remainingScope.readable && typeof remainingScope.value === "string") facts.remainingScope = remainingScope.value;
|
|
20472
20516
|
const reason = safelyRead(candidate, "reason");
|
|
20473
|
-
if (
|
|
20517
|
+
if (statusBase === "unfinished" && reason.readable && typeof reason.value === "string" && reason.value.trim().length > 0) {
|
|
20474
20518
|
facts.reason = reason.value;
|
|
20475
20519
|
}
|
|
20476
20520
|
const blockerRead = safelyRead(candidate, "blocker");
|
|
20477
|
-
if (
|
|
20521
|
+
if (statusBase === "refused" && blockerRead.readable && isRecord5(blockerRead.value)) {
|
|
20478
20522
|
const cause = safelyRead(blockerRead.value, "cause");
|
|
20479
20523
|
if (cause.readable && typeof cause.value === "string") facts.blockerCause = cause.value;
|
|
20480
20524
|
const prerequisiteId = safelyRead(blockerRead.value, "prerequisiteId");
|
|
@@ -20550,7 +20594,8 @@ function doctorDecisiveFacts(output) {
|
|
|
20550
20594
|
const status = safelyRead(candidate, "status");
|
|
20551
20595
|
const facts = { ...auditNoReceiptDecisiveFact(candidate) };
|
|
20552
20596
|
if (status.readable && typeof status.value === "string") facts.doctorStatus = status.value;
|
|
20553
|
-
|
|
20597
|
+
const statusBase = status.readable && typeof status.value === "string" ? seatFallbackBaseStatus(status.value) : void 0;
|
|
20598
|
+
if (statusBase === "refused") {
|
|
20554
20599
|
const reason = safelyRead(candidate, "reason");
|
|
20555
20600
|
if (reason.readable && reason.value !== void 0) facts.reason = reason.value;
|
|
20556
20601
|
const missing = safelyRead(candidate, "missingEvidence");
|
|
@@ -20597,7 +20642,8 @@ function reviewerDecisiveFacts(output) {
|
|
|
20597
20642
|
facts.specDisposition = specDisposition.value;
|
|
20598
20643
|
}
|
|
20599
20644
|
const diagnostic = safelyRead(candidate, "diagnostic");
|
|
20600
|
-
|
|
20645
|
+
const statusBase = status.readable && typeof status.value === "string" ? seatFallbackBaseStatus(status.value) : void 0;
|
|
20646
|
+
if (statusBase === "refused" && diagnostic.readable) {
|
|
20601
20647
|
facts.diagnosticPresent = typeof diagnostic.value === "string" && diagnostic.value.trim().length > 0;
|
|
20602
20648
|
}
|
|
20603
20649
|
return facts;
|
|
@@ -21038,9 +21084,11 @@ function extractJudgeRoleOutcome(entries) {
|
|
|
21038
21084
|
if (isUnboundAuditEscalationFace(details)) continue;
|
|
21039
21085
|
if (!isRecord5(details)) continue;
|
|
21040
21086
|
const statusRead = safelyRead(details, "judgeStatus");
|
|
21041
|
-
if (!statusRead.readable) continue;
|
|
21087
|
+
if (!statusRead.readable || typeof statusRead.value !== "string") continue;
|
|
21042
21088
|
const judgeStatus = statusRead.value;
|
|
21043
|
-
|
|
21089
|
+
const statusBase = seatFallbackBaseStatus(judgeStatus);
|
|
21090
|
+
if (statusBase !== "converged" && statusBase !== "continue" && statusBase !== "escalate") continue;
|
|
21091
|
+
if (!seatFallbackStatusHasLawfulEvidence(judgeStatus, details)) continue;
|
|
21044
21092
|
return {
|
|
21045
21093
|
kind: "accepted",
|
|
21046
21094
|
role: "judge",
|
|
@@ -21730,8 +21778,9 @@ async function settleLawfulDoctorTerminalResult(admitted) {
|
|
|
21730
21778
|
if (entries === void 0) return void 0;
|
|
21731
21779
|
const extracted = extractDoctorRoleOutcome(entries);
|
|
21732
21780
|
if (extracted === void 0) return void 0;
|
|
21733
|
-
if (extracted.output !== void 0 && extracted.output.status === "completed") {
|
|
21734
|
-
|
|
21781
|
+
if (extracted.output !== void 0 && seatFallbackBaseStatus(String(extracted.output.status)) === "completed") {
|
|
21782
|
+
const completedCase = extracted.output.case;
|
|
21783
|
+
if (completedCase.issueNumber !== admitted.caseIdentity.issueNumber || completedCase.runsPath !== admitted.caseIdentity.runsPath) {
|
|
21735
21784
|
const error = new Error(
|
|
21736
21785
|
"Doctor receipt case identity does not match admitted case identity"
|
|
21737
21786
|
);
|
|
@@ -21945,7 +21994,8 @@ function mergerDecisiveFacts(output) {
|
|
|
21945
21994
|
const attemptId = safelyRead(candidate, "attemptId");
|
|
21946
21995
|
if (status.readable && typeof status.value === "string") facts.mergerStatus = status.value;
|
|
21947
21996
|
if (attemptId.readable && attemptId.value !== void 0) facts.attemptId = attemptId.value;
|
|
21948
|
-
const
|
|
21997
|
+
const statusBase = status.readable && typeof status.value === "string" ? seatFallbackBaseStatus(status.value) : void 0;
|
|
21998
|
+
const decisiveKey = statusBase === "completed" ? "mergeCommitId" : "diagnosis";
|
|
21949
21999
|
const decisive = safelyRead(candidate, decisiveKey);
|
|
21950
22000
|
if (decisive.readable && decisive.value !== void 0) facts[decisiveKey] = decisive.value;
|
|
21951
22001
|
return facts;
|
|
@@ -25881,8 +25931,9 @@ function mapTerminal(role, terminal) {
|
|
|
25881
25931
|
noReceipt: false
|
|
25882
25932
|
};
|
|
25883
25933
|
}
|
|
25934
|
+
const statusBase = seatFallbackBaseStatus(status);
|
|
25884
25935
|
const acceptedSet = ACCEPTED_STATUS[role];
|
|
25885
|
-
if (acceptedSet === void 0 || !acceptedSet.has(
|
|
25936
|
+
if (acceptedSet === void 0 || !acceptedSet.has(statusBase)) {
|
|
25886
25937
|
return {
|
|
25887
25938
|
terminalLabel: status,
|
|
25888
25939
|
accepted: false,
|
|
@@ -25891,9 +25942,9 @@ function mapTerminal(role, terminal) {
|
|
|
25891
25942
|
noReceipt: false
|
|
25892
25943
|
};
|
|
25893
25944
|
}
|
|
25894
|
-
const plannedDuty = WORKER_ROLES.has(role) &&
|
|
25945
|
+
const plannedDuty = WORKER_ROLES.has(role) && statusBase === "planned";
|
|
25895
25946
|
const successSet = SUCCESS_STATUS[role] ?? /* @__PURE__ */ new Set();
|
|
25896
|
-
const success = !plannedDuty && successSet.has(
|
|
25947
|
+
const success = !plannedDuty && successSet.has(statusBase);
|
|
25897
25948
|
const successEligible = !plannedDuty;
|
|
25898
25949
|
return {
|
|
25899
25950
|
terminalLabel: status,
|
|
@@ -26015,6 +26066,7 @@ var WORKER_ROLES, ACCEPTED_STATUS, SUCCESS_STATUS, acceptanceSuccessReworkFamily
|
|
|
26015
26066
|
var init_acceptance_success_rework = __esm({
|
|
26016
26067
|
"src/taishi-metric-families/acceptance-success-rework.ts"() {
|
|
26017
26068
|
"use strict";
|
|
26069
|
+
init_engine_labor_fallback();
|
|
26018
26070
|
init_taishi_median();
|
|
26019
26071
|
WORKER_ROLES = /* @__PURE__ */ new Set(["coder", "fixer"]);
|
|
26020
26072
|
ACCEPTED_STATUS = {
|
package/package.json
CHANGED
|
@@ -37,6 +37,11 @@ grok --prompt-file /path/to/labor-prompt.md -m grok-4.6 --always-approve --outpu
|
|
|
37
37
|
alias `--effort`; a low-tier run completed correctly). If the mandate names
|
|
38
38
|
no tier, use the seat's ordered thinking tier; never omit the flag — the
|
|
39
39
|
CLI default is not guaranteed to match the ordered tier.
|
|
40
|
+
- **Labor prompt must be seat-authored**: write the complete task brief into a
|
|
41
|
+
temp file and pass it via `--prompt-file`. Attachments/receipt JSON are
|
|
42
|
+
evidence material, not the prompt body — feeding them directly is rejected
|
|
43
|
+
by the CLI as non-ACP JSON (`JSON object must have a type field`;
|
|
44
|
+
live-verified 2026-08-21).
|
|
40
45
|
|
|
41
46
|
## Failure handling
|
|
42
47
|
|
|
@@ -9,6 +9,8 @@ const entries = [
|
|
|
9
9
|
"work-subject-identity",
|
|
10
10
|
"navigator-invocation-identity",
|
|
11
11
|
"navigator-attendance",
|
|
12
|
+
// Navigator package-graph dependency (seat-fallback base status / ADR 0071).
|
|
13
|
+
"engine-labor-fallback",
|
|
12
14
|
"activation-ledger-git",
|
|
13
15
|
"activation-ledger-topology",
|
|
14
16
|
"activation-reconciliation",
|
package/src/doctor-contracts.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
import { canonicalJson } from "./canonical-json.ts";
|
|
3
|
+
import {
|
|
4
|
+
seatFallbackBaseStatus,
|
|
5
|
+
seatFallbackStatusHasLawfulEvidence,
|
|
6
|
+
type WithEngineLaborFallback,
|
|
7
|
+
} from "./engine-labor-fallback.ts";
|
|
3
8
|
import { openToolObjectFromUnion } from "./open-tool-schema.ts";
|
|
4
9
|
|
|
5
10
|
export const DOCTOR_EVIDENCE_TOOL_NAME = "ak_doctor_evidence";
|
|
@@ -37,9 +42,13 @@ export type DoctorFinding =
|
|
|
37
42
|
export type DoctorSubmission =
|
|
38
43
|
| { status: "completed"; case: DoctorCaseIdentity; findings: DoctorFinding[] }
|
|
39
44
|
| { status: "refused"; reason: string; missingEvidence: Array<{ need: string; targetKeys: string[] }> };
|
|
40
|
-
|
|
45
|
+
type DoctorOutputClean =
|
|
41
46
|
| { status: "completed"; case: DoctorCaseIdentity; findings: DoctorFinding[]; cost: DoctorCaseCost }
|
|
42
47
|
| Extract<DoctorSubmission, { status: "refused" }>;
|
|
48
|
+
/** Clean recorded shape or seat-fallback tainted accepted receipt (ADR 0071). */
|
|
49
|
+
export type DoctorOutput =
|
|
50
|
+
| DoctorOutputClean
|
|
51
|
+
| WithEngineLaborFallback<DoctorOutputClean>;
|
|
43
52
|
export type DoctorEvidenceEntry = { id: string; kind: "session" | "stderr"; byteLength: number; contentLength: number; sha256: string; content: string };
|
|
44
53
|
export type DoctorCase = { version: 1; identity: DoctorCaseIdentity; evidence: DoctorEvidenceEntry[]; cost: DoctorCaseCost };
|
|
45
54
|
|
|
@@ -96,12 +105,19 @@ function isRecord(value: unknown): value is Record<string, unknown> { return typ
|
|
|
96
105
|
function read(value: unknown, key: string): unknown { if (!isRecord(value)) return undefined; try { return value[key]; } catch { return undefined; } }
|
|
97
106
|
export function validateDoctorSubmissionShape(value: unknown): DoctorSubmission {
|
|
98
107
|
const status = read(value, "status");
|
|
99
|
-
|
|
108
|
+
const base = typeof status === "string" ? seatFallbackBaseStatus(status) : status;
|
|
109
|
+
if (base !== "completed" && base !== "refused") throw new DoctorSubmissionContractError("Doctor submission has no recognized execution status");
|
|
110
|
+
// ADR 0071: tainted status requires latch-shaped engineLaborFallback evidence.
|
|
111
|
+
if (typeof status === "string" && !seatFallbackStatusHasLawfulEvidence(status, value)) {
|
|
112
|
+
throw new DoctorSubmissionContractError("Doctor submission has no recognized execution status");
|
|
113
|
+
}
|
|
100
114
|
return value as DoctorSubmission;
|
|
101
115
|
}
|
|
102
116
|
export function validateRecordedDoctorOutput(value: unknown): DoctorOutput {
|
|
103
117
|
const output = validateDoctorSubmissionShape(value);
|
|
104
|
-
|
|
118
|
+
const status = read(output, "status");
|
|
119
|
+
const base = typeof status === "string" ? seatFallbackBaseStatus(status) : status;
|
|
120
|
+
if (base === "completed" && read(output, "cost") === undefined) throw new Error("Completed Doctor receipt has no runtime-owned cost testimony");
|
|
105
121
|
return output as DoctorOutput;
|
|
106
122
|
}
|
|
107
123
|
|
|
@@ -32,6 +32,87 @@ export type EngineLaborFallbackField = ReturnType<
|
|
|
32
32
|
typeof buildEngineLaborFallbackField
|
|
33
33
|
>;
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Seat-fallback status taint suffix.
|
|
37
|
+
* When engineLaborFallback is declared, typed status discriminators
|
|
38
|
+
* (judgeStatus / status) must not remain clean values like converged/completed.
|
|
39
|
+
* Mechanical form: `${base}-by-fallback` — readable on the status line alone.
|
|
40
|
+
*/
|
|
41
|
+
export const SEAT_FALLBACK_STATUS_SUFFIX = "-by-fallback" as const;
|
|
42
|
+
|
|
43
|
+
export function isSeatFallbackTaintedStatus(status: string): boolean {
|
|
44
|
+
return status.endsWith(SEAT_FALLBACK_STATUS_SUFFIX);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Strip seat-fallback taint for semantic routing / acceptance matching. */
|
|
48
|
+
export function seatFallbackBaseStatus(status: string): string {
|
|
49
|
+
return isSeatFallbackTaintedStatus(status)
|
|
50
|
+
? status.slice(0, -SEAT_FALLBACK_STATUS_SUFFIX.length)
|
|
51
|
+
: status;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* ADR 0071: `-by-fallback` is lawful only with a valid `engineLaborFallback`
|
|
56
|
+
* declaration (latch-shaped triple). Clean statuses do not need the field.
|
|
57
|
+
*/
|
|
58
|
+
export function seatFallbackStatusHasLawfulEvidence(
|
|
59
|
+
status: string,
|
|
60
|
+
source: unknown,
|
|
61
|
+
): boolean {
|
|
62
|
+
if (!isSeatFallbackTaintedStatus(status)) return true;
|
|
63
|
+
return readEngineLaborFallbackFieldFrom(source) !== undefined;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Idempotent taint: clean → `${clean}-by-fallback`; already tainted stays. */
|
|
67
|
+
export function taintStatusForSeatFallback(status: string): string {
|
|
68
|
+
if (status.length === 0 || isSeatFallbackTaintedStatus(status)) return status;
|
|
69
|
+
return `${status}${SEAT_FALLBACK_STATUS_SUFFIX}`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Clean status literal or its seat-fallback tainted form. */
|
|
73
|
+
export type SeatFallbackTaintedStatus<S extends string = string> =
|
|
74
|
+
| S
|
|
75
|
+
| `${S}${typeof SEAT_FALLBACK_STATUS_SUFFIX}`;
|
|
76
|
+
|
|
77
|
+
type TaintDiscriminatorFields<T> = {
|
|
78
|
+
[K in keyof T]: K extends "status" | "judgeStatus"
|
|
79
|
+
? T[K] extends string
|
|
80
|
+
? SeatFallbackTaintedStatus<Extract<T[K], string>>
|
|
81
|
+
: T[K]
|
|
82
|
+
: T[K];
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/** Receipt shape after sole-built field attach + status taint (runtime truth). */
|
|
86
|
+
export type WithEngineLaborFallback<T extends object> = T extends unknown
|
|
87
|
+
? TaintDiscriminatorFields<T> & EngineLaborFallbackField
|
|
88
|
+
: never;
|
|
89
|
+
|
|
90
|
+
const STATUS_DISCRIMINATOR_KEYS = ["judgeStatus", "status"] as const;
|
|
91
|
+
|
|
92
|
+
/** Rewrite known status discriminators on a receipt when seat fallback is declared. */
|
|
93
|
+
function taintReceiptStatusDiscriminators<T extends object>(
|
|
94
|
+
receipt: T,
|
|
95
|
+
): TaintDiscriminatorFields<T> {
|
|
96
|
+
let next: Record<string, unknown> | undefined;
|
|
97
|
+
for (const key of STATUS_DISCRIMINATOR_KEYS) {
|
|
98
|
+
if (!Object.prototype.hasOwnProperty.call(receipt, key)) continue;
|
|
99
|
+
let value: unknown;
|
|
100
|
+
try {
|
|
101
|
+
value = (receipt as Record<string, unknown>)[key];
|
|
102
|
+
} catch {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (typeof value !== "string" || value.length === 0) continue;
|
|
106
|
+
const tainted = taintStatusForSeatFallback(value);
|
|
107
|
+
if (tainted === value) continue;
|
|
108
|
+
if (next === undefined) {
|
|
109
|
+
next = { ...(receipt as object as Record<string, unknown>) };
|
|
110
|
+
}
|
|
111
|
+
next[key] = tainted;
|
|
112
|
+
}
|
|
113
|
+
return (next === undefined ? receipt : next) as TaintDiscriminatorFields<T>;
|
|
114
|
+
}
|
|
115
|
+
|
|
35
116
|
export type EngineLaborFallbackLatch = {
|
|
36
117
|
field: EngineLaborFallbackField | undefined;
|
|
37
118
|
};
|
|
@@ -62,14 +143,31 @@ export function readEngineLaborFallbackField(
|
|
|
62
143
|
/**
|
|
63
144
|
* Merge sole-built field into typed receipt details.
|
|
64
145
|
* Spread only — must not construct the field key again (S1).
|
|
146
|
+
* When the field is present, also taint typed status discriminators so a
|
|
147
|
+
* status-line-only reader cannot mistake seat labor for clean engine labor.
|
|
65
148
|
* Without a mechanical latch, strip any model-injected reserved key (no forged declaration).
|
|
149
|
+
* Return type widens when field is attached: discriminators may carry `-by-fallback`
|
|
150
|
+
* and the sole-built field is present (callers must not assume clean-only unions).
|
|
66
151
|
*/
|
|
152
|
+
export function withEngineLaborFallbackField<T extends object>(
|
|
153
|
+
receipt: T,
|
|
154
|
+
field: EngineLaborFallbackField,
|
|
155
|
+
): WithEngineLaborFallback<T>;
|
|
156
|
+
export function withEngineLaborFallbackField<T extends object>(
|
|
157
|
+
receipt: T,
|
|
158
|
+
field: undefined,
|
|
159
|
+
): T;
|
|
160
|
+
export function withEngineLaborFallbackField<T extends object>(
|
|
161
|
+
receipt: T,
|
|
162
|
+
field: EngineLaborFallbackField | undefined,
|
|
163
|
+
): T | WithEngineLaborFallback<T>;
|
|
67
164
|
export function withEngineLaborFallbackField<T extends object>(
|
|
68
165
|
receipt: T,
|
|
69
166
|
field: EngineLaborFallbackField | undefined,
|
|
70
|
-
): T {
|
|
167
|
+
): T | WithEngineLaborFallback<T> {
|
|
71
168
|
if (field !== undefined) {
|
|
72
|
-
|
|
169
|
+
const taintedReceipt = taintReceiptStatusDiscriminators(receipt);
|
|
170
|
+
return { ...taintedReceipt, ...field } as WithEngineLaborFallback<T>;
|
|
73
171
|
}
|
|
74
172
|
if (
|
|
75
173
|
!Object.prototype.hasOwnProperty.call(receipt, "engineLaborFallback")
|
package/src/factory-board.ts
CHANGED
|
@@ -20,6 +20,7 @@ import { randomUUID } from "node:crypto";
|
|
|
20
20
|
import { lstat, mkdir, realpath, rename, rm, writeFile } from "node:fs/promises";
|
|
21
21
|
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
22
22
|
|
|
23
|
+
import { seatFallbackBaseStatus } from "./engine-labor-fallback.ts";
|
|
23
24
|
import {
|
|
24
25
|
formatDurationZh,
|
|
25
26
|
formatLocalDateTime,
|
|
@@ -176,7 +177,8 @@ export function decideTicketCurrentState(input: {
|
|
|
176
177
|
const latest = sortRunsByStart(input.runs).at(-1)!;
|
|
177
178
|
if (!latest.hasResult) return unacceptedBand(latest.mtimeMs, input.now.getTime());
|
|
178
179
|
// Escalate is an awaiting overlay: same placement and sort band, distinct state.
|
|
179
|
-
|
|
180
|
+
// Seat-fallback taint (`escalate-by-fallback`) keeps escalate base semantics.
|
|
181
|
+
if (seatFallbackBaseStatus(latest.resultStatus) === "escalate") return "escalate-awaiting";
|
|
180
182
|
return "accepted-awaiting";
|
|
181
183
|
}
|
|
182
184
|
|
|
@@ -843,7 +845,9 @@ function buildBreadcrumbSteps(runs: readonly TicketTrajectoryRun[]): BreadcrumbS
|
|
|
843
845
|
const isReturn = seen.has(group.station);
|
|
844
846
|
seen.add(group.station);
|
|
845
847
|
const isRejected = group.runs.some(
|
|
846
|
-
(run) =>
|
|
848
|
+
(run) =>
|
|
849
|
+
run.hasResult &&
|
|
850
|
+
REJECTED_RESULT_STATUSES.has(seatFallbackBaseStatus(run.resultStatus)),
|
|
847
851
|
);
|
|
848
852
|
steps.push({
|
|
849
853
|
station: group.station,
|
package/src/merger-contracts.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { Type, type Static } from "typebox";
|
|
2
2
|
import { isFullGitObjectId } from "./git-object-id.ts";
|
|
3
3
|
import { exactUtf8 } from "./exact-utf8.ts";
|
|
4
|
+
import {
|
|
5
|
+
seatFallbackBaseStatus,
|
|
6
|
+
seatFallbackStatusHasLawfulEvidence,
|
|
7
|
+
type WithEngineLaborFallback,
|
|
8
|
+
} from "./engine-labor-fallback.ts";
|
|
4
9
|
import { sha256Hex } from "./sha256.ts";
|
|
5
10
|
import { openToolObjectFromUnion } from "./open-tool-schema.ts";
|
|
6
11
|
|
|
@@ -24,9 +29,13 @@ export const mergerOutputSchema = openToolObjectFromUnion(mergerOutputVariants);
|
|
|
24
29
|
export type DeepReadonly<T> = T extends (...args: never[]) => unknown ? T : T extends readonly (infer U)[] ? readonly DeepReadonly<U>[] : T extends object ? { readonly [K in keyof T]: DeepReadonly<T[K]> } : T;
|
|
25
30
|
export type MergerMaterial = DeepReadonly<Static<typeof materialSchema>>;
|
|
26
31
|
export type MergerInput = DeepReadonly<Static<typeof mergerInputSchema>>;
|
|
27
|
-
|
|
32
|
+
type MergerOutputClean =
|
|
28
33
|
| { status: "completed"; attemptId: string; report: string; mergeCommitId: string }
|
|
29
34
|
| { status: "escalate"; attemptId: string; diagnosis: string; report: string };
|
|
35
|
+
/** Clean submission shape or seat-fallback tainted accepted receipt (ADR 0071). */
|
|
36
|
+
export type MergerOutput =
|
|
37
|
+
| MergerOutputClean
|
|
38
|
+
| WithEngineLaborFallback<MergerOutputClean>;
|
|
30
39
|
export const MERGER_OUTPUT_TOOL_NAME = "ak_merger_output";
|
|
31
40
|
export const MERGER_ACCEPTED_TEXT = "Merger output accepted";
|
|
32
41
|
|
|
@@ -65,7 +74,13 @@ export function validateMergerInput(value: unknown): MergerInput {
|
|
|
65
74
|
|
|
66
75
|
export function validateMergerOutput(value: unknown, expectedAttemptId?: string): MergerOutput {
|
|
67
76
|
if (!record(value) || (expectedAttemptId !== undefined && value.attemptId !== expectedAttemptId)) throw new Error("Merger output attempt mismatch");
|
|
68
|
-
|
|
69
|
-
|
|
77
|
+
const status = typeof value.status === "string" ? value.status : undefined;
|
|
78
|
+
const statusBase = status !== undefined ? seatFallbackBaseStatus(status) : undefined;
|
|
79
|
+
// ADR 0071: tainted status requires latch-shaped engineLaborFallback evidence.
|
|
80
|
+
if (status !== undefined && !seatFallbackStatusHasLawfulEvidence(status, value)) {
|
|
81
|
+
throw new Error("Merger output has no recognized execution discriminator");
|
|
82
|
+
}
|
|
83
|
+
if (statusBase === "completed" && isFullGitObjectId(value.mergeCommitId)) return structuredClone(value) as MergerOutput;
|
|
84
|
+
if (statusBase === "escalate") return structuredClone(value) as MergerOutput;
|
|
70
85
|
throw new Error("Merger output has no recognized execution discriminator");
|
|
71
86
|
}
|