@akagilnc/pi-workflow-roles 0.1.2068 → 0.1.2076
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/navigator-attendance.js +27 -24
- package/dist/public-cli/main.js +30 -166
- package/package.json +1 -1
- package/src/navigator-attendance.ts +51 -54
- package/src/public-cli/settlement.ts +33 -144
- package/src/role-runtime.ts +1 -3
- package/src/worker-role.ts +2 -0
- package/src/worker-submission-gates.ts +185 -132
|
@@ -90,13 +90,6 @@ function navigatorUnavailableError(source, error, cause = source) {
|
|
|
90
90
|
const message = error instanceof Error ? error.message : String(error);
|
|
91
91
|
return error instanceof NavigatorUnavailableError ? error : new NavigatorUnavailableError(source, message, cause, error);
|
|
92
92
|
}
|
|
93
|
-
function navigatorAdviceConsistentWithSettlement(next, settlement) {
|
|
94
|
-
if (settlement.kind !== "accepted") return true;
|
|
95
|
-
if (settlement.status === "unfinished" && next.role === "judge") return false;
|
|
96
|
-
if (settlement.role === "fixer" && settlement.phase === "apply" && settlement.status === "completed" && next.role === "fixer" && next.phase === "apply") return false;
|
|
97
|
-
if (next.role !== "merger") return true;
|
|
98
|
-
return settlement.role === "judge" && settlement.status === "converged";
|
|
99
|
-
}
|
|
100
93
|
const prepareSchema = Type.Object({}, { additionalProperties: true });
|
|
101
94
|
const ROUTE_ENTRY = "ak-navigator-route";
|
|
102
95
|
const CONTEXT_ENTRY = "ak-navigator-context";
|
|
@@ -269,17 +262,29 @@ function selectNavigatorCandidate(candidates, settlement) {
|
|
|
269
262
|
if (settlement.kind !== "accepted") return void 0;
|
|
270
263
|
const usable = candidates.filter((candidate) => candidate.next !== void 0);
|
|
271
264
|
if (usable.length === 0) return void 0;
|
|
272
|
-
const
|
|
265
|
+
const rolePhaseMatched = usable.filter(
|
|
273
266
|
(candidate) => candidate.matches !== void 0 && candidate.matches.role === settlement.role && candidate.matches.phase === settlement.phase
|
|
274
267
|
);
|
|
275
|
-
if (
|
|
268
|
+
if (rolePhaseMatched.length > 0) {
|
|
276
269
|
if (settlement.status !== void 0) {
|
|
277
|
-
const statusSpecific =
|
|
278
|
-
|
|
270
|
+
const statusSpecific = rolePhaseMatched.find(
|
|
271
|
+
(candidate) => candidate.matches?.statuses?.includes(settlement.status) === true
|
|
272
|
+
);
|
|
273
|
+
if (statusSpecific !== void 0) {
|
|
274
|
+
return { candidate: statusSpecific, matchedToSettlement: true };
|
|
275
|
+
}
|
|
279
276
|
}
|
|
280
|
-
|
|
277
|
+
const rolePhaseGeneric = rolePhaseMatched.find(
|
|
278
|
+
(candidate) => candidate.matches?.statuses === void 0
|
|
279
|
+
);
|
|
280
|
+
if (rolePhaseGeneric !== void 0) {
|
|
281
|
+
return { candidate: rolePhaseGeneric, matchedToSettlement: true };
|
|
282
|
+
}
|
|
283
|
+
return void 0;
|
|
281
284
|
}
|
|
282
|
-
|
|
285
|
+
const unbound = usable.find((candidate) => candidate.matches === void 0);
|
|
286
|
+
if (unbound === void 0) return void 0;
|
|
287
|
+
return { candidate: unbound, matchedToSettlement: false };
|
|
283
288
|
}
|
|
284
289
|
function formatNavigatorReport(report) {
|
|
285
290
|
const playbookFailure = report.routePlaybookReadFailure === void 0 ? [] : [`\u8DEF\u4E66\u8BFB\u53D6\u5931\u8D25\uFF1A${oneLine(report.routePlaybookReadFailure)}`];
|
|
@@ -375,6 +380,7 @@ function createNavigatorAttendance(options) {
|
|
|
375
380
|
const prepare = async () => {
|
|
376
381
|
const boundSettlement = prepareBoundSettlement;
|
|
377
382
|
prepareBoundSettlement = void 0;
|
|
383
|
+
preparationNoReceipt = false;
|
|
378
384
|
const invocationId = invocationPrincipal;
|
|
379
385
|
activeInvocationId = invocationId;
|
|
380
386
|
if (contextError !== void 0) throw navigatorUnavailableError("context", contextError);
|
|
@@ -704,27 +710,25 @@ ${helpContext}
|
|
|
704
710
|
let prepared = await preparation;
|
|
705
711
|
session?.appendEntry(SETTLEMENT_ENTRY, { invocationId, subjectKey, role: settlement.role, phase: settlement.phase, kind: settlement.kind, ...settlement.status === void 0 ? {} : { status: settlement.status } });
|
|
706
712
|
let selected = selectNavigatorCandidate(prepared, settlement);
|
|
707
|
-
if (selected?.next !== void 0 && !
|
|
713
|
+
if (selected?.candidate.next !== void 0 && !selected.matchedToSettlement) {
|
|
708
714
|
prepareBoundSettlement = settlement;
|
|
709
715
|
prepared = await prepare();
|
|
710
716
|
selected = selectNavigatorCandidate(prepared, settlement);
|
|
711
|
-
if (selected?.next !== void 0 && !navigatorAdviceConsistentWithSettlement(selected.next, settlement)) {
|
|
712
|
-
throw new Error("Navigator advice contradicts the accepted settlement");
|
|
713
|
-
}
|
|
714
717
|
}
|
|
715
|
-
|
|
718
|
+
const selectedCandidate = selected?.candidate;
|
|
719
|
+
if (selectedCandidate?.next === void 0 && preparationNoReceipt) {
|
|
716
720
|
report = { disposition: "no-advice" };
|
|
717
|
-
} else if (
|
|
721
|
+
} else if (selectedCandidate?.next === void 0) {
|
|
718
722
|
throw new Error("Navigator prepared no machine-usable next direction");
|
|
719
723
|
} else {
|
|
720
|
-
const selectedRoute =
|
|
724
|
+
const selectedRoute = selectedCandidate.route;
|
|
721
725
|
const routeChanged = selectedRoute !== void 0 && !routeEqual(previousRoute, selectedRoute);
|
|
722
|
-
const command = renderPublicAkRoleCommand(
|
|
726
|
+
const command = renderPublicAkRoleCommand(selectedCandidate.next);
|
|
723
727
|
report = {
|
|
724
728
|
disposition: "recommendation",
|
|
725
729
|
...routeChanged ? { route: selectedRoute } : {},
|
|
726
|
-
next:
|
|
727
|
-
...
|
|
730
|
+
next: selectedCandidate.next,
|
|
731
|
+
...selectedCandidate.reason === void 0 ? {} : { reason: oneLine(selectedCandidate.reason) },
|
|
728
732
|
...command === void 0 ? {} : { command }
|
|
729
733
|
};
|
|
730
734
|
if (selectedRoute !== void 0) {
|
|
@@ -1056,7 +1060,6 @@ export {
|
|
|
1056
1060
|
createNavigatorPrepareTool,
|
|
1057
1061
|
decorateSettlementWithNavigation,
|
|
1058
1062
|
formatNavigatorReport,
|
|
1059
|
-
navigatorAdviceConsistentWithSettlement,
|
|
1060
1063
|
navigatorModelSettingPath,
|
|
1061
1064
|
navigatorProviderFailure,
|
|
1062
1065
|
navigatorProviderFailureFromError,
|
package/dist/public-cli/main.js
CHANGED
|
@@ -14295,9 +14295,6 @@ var init_merger_contracts = __esm({
|
|
|
14295
14295
|
});
|
|
14296
14296
|
|
|
14297
14297
|
// src/packaged-role-registry.ts
|
|
14298
|
-
function packagedRoleMetadata(role) {
|
|
14299
|
-
return PACKAGED_ROLE_REGISTRY.find((entry) => entry.role === role);
|
|
14300
|
-
}
|
|
14301
14298
|
var PACKAGED_ROLE_REGISTRY;
|
|
14302
14299
|
var init_packaged_role_registry = __esm({
|
|
14303
14300
|
"src/packaged-role-registry.ts"() {
|
|
@@ -14812,9 +14809,6 @@ function physicalPathIdentity(path) {
|
|
|
14812
14809
|
}
|
|
14813
14810
|
}
|
|
14814
14811
|
}
|
|
14815
|
-
function physicallyContainedIn(root, candidate) {
|
|
14816
|
-
return pathContainedIn(physicalPathIdentity(root), physicalPathIdentity(candidate));
|
|
14817
|
-
}
|
|
14818
14812
|
function errnoCode(error) {
|
|
14819
14813
|
return error !== null && typeof error === "object" && "code" in error && typeof error.code === "string" ? error.code : void 0;
|
|
14820
14814
|
}
|
|
@@ -19428,48 +19422,6 @@ var init_engine_detour = __esm({
|
|
|
19428
19422
|
});
|
|
19429
19423
|
|
|
19430
19424
|
// src/work-subject-identity.ts
|
|
19431
|
-
import { resolve as resolve6 } from "node:path";
|
|
19432
|
-
function issueRoot(value) {
|
|
19433
|
-
const normalized = value.replaceAll("\\", "/");
|
|
19434
|
-
const marker = ".ak/work/issues/";
|
|
19435
|
-
const index = normalized.indexOf(marker);
|
|
19436
|
-
if (index < 0) return void 0;
|
|
19437
|
-
const issue = normalized.slice(index + marker.length).split("/")[0]?.split("#")[0];
|
|
19438
|
-
return issue === void 0 || issue === "" ? void 0 : normalized.slice(0, index + marker.length) + issue;
|
|
19439
|
-
}
|
|
19440
|
-
function workIdentityFromCwd(cwd) {
|
|
19441
|
-
const resolvedCwd = resolve6(cwd, ".");
|
|
19442
|
-
const cwdIssue = issueRoot(resolvedCwd);
|
|
19443
|
-
if (cwdIssue !== void 0) return cwdIssue;
|
|
19444
|
-
if (resolvedCwd.includes("/.ak/work/")) return resolvedCwd;
|
|
19445
|
-
return void 0;
|
|
19446
|
-
}
|
|
19447
|
-
function isMachineLedgerSessionPath(sessionPath) {
|
|
19448
|
-
return physicallyContainedIn(resolveActivationLedgerHome(), sessionPath);
|
|
19449
|
-
}
|
|
19450
|
-
function subjectPath(sessionDir, cwd = process.cwd()) {
|
|
19451
|
-
if (sessionDir === "") {
|
|
19452
|
-
return workIdentityFromCwd(cwd) ?? resolve6(cwd, ".ak/work");
|
|
19453
|
-
}
|
|
19454
|
-
const resolvedSession = resolve6(cwd, sessionDir || ".ak/work");
|
|
19455
|
-
if (isMachineLedgerSessionPath(resolvedSession)) {
|
|
19456
|
-
return workIdentityFromCwd(cwd) ?? resolve6(cwd, ".ak/work");
|
|
19457
|
-
}
|
|
19458
|
-
const issue = issueRoot(resolvedSession);
|
|
19459
|
-
if (issue !== void 0) return issue;
|
|
19460
|
-
const runsMarker = "/runs/";
|
|
19461
|
-
const runsIndex = resolvedSession.indexOf(runsMarker);
|
|
19462
|
-
if (runsIndex >= 0) {
|
|
19463
|
-
return resolvedSession.slice(0, runsIndex);
|
|
19464
|
-
}
|
|
19465
|
-
return resolvedSession;
|
|
19466
|
-
}
|
|
19467
|
-
function workSubjectKeyFromProjectRoot(projectRoot) {
|
|
19468
|
-
return subjectPath("", projectRoot);
|
|
19469
|
-
}
|
|
19470
|
-
function workSubjectKeysEqual(left, right) {
|
|
19471
|
-
return physicalPathIdentity(left) === physicalPathIdentity(right);
|
|
19472
|
-
}
|
|
19473
19425
|
var init_work_subject_identity = __esm({
|
|
19474
19426
|
"src/work-subject-identity.ts"() {
|
|
19475
19427
|
"use strict";
|
|
@@ -19510,18 +19462,6 @@ function parseInvocationMarkerIdentity(data) {
|
|
|
19510
19462
|
subjectKey: record4.subjectKey
|
|
19511
19463
|
};
|
|
19512
19464
|
}
|
|
19513
|
-
function markerMatchesExpectedIdentity(marker, expected) {
|
|
19514
|
-
if (marker.role !== expected.role) return false;
|
|
19515
|
-
if (expected.phase !== void 0) {
|
|
19516
|
-
if (marker.phase !== expected.phase) return false;
|
|
19517
|
-
} else if (expected.allowedPhases !== void 0) {
|
|
19518
|
-
if (!expected.allowedPhases.includes(marker.phase)) return false;
|
|
19519
|
-
}
|
|
19520
|
-
if (expected.subjectKey !== void 0) {
|
|
19521
|
-
if (!workSubjectKeysEqual(marker.subjectKey, expected.subjectKey)) return false;
|
|
19522
|
-
}
|
|
19523
|
-
return true;
|
|
19524
|
-
}
|
|
19525
19465
|
function classifyPackagedRoleTerminalResult(message) {
|
|
19526
19466
|
if (typeof message.toolName !== "string") return { kind: "nonterminal" };
|
|
19527
19467
|
if (!PACKAGED_ROLE_OUTPUT_TOOLS.has(message.toolName)) return { kind: "nonterminal" };
|
|
@@ -21011,55 +20951,9 @@ function navigatorPhaseValue(value) {
|
|
|
21011
20951
|
if (value === "plan" || value === "apply") return value;
|
|
21012
20952
|
return null;
|
|
21013
20953
|
}
|
|
21014
|
-
function
|
|
21015
|
-
|
|
21016
|
-
if (admitted.role === "coder" || admitted.role === "fixer") {
|
|
21017
|
-
return { phase: admitted.phase, subjectKey };
|
|
21018
|
-
}
|
|
21019
|
-
return { phase: null, subjectKey };
|
|
21020
|
-
}
|
|
21021
|
-
function independentExpectedIdentity(entries, terminalRole, supplied) {
|
|
21022
|
-
let subjectKey;
|
|
21023
|
-
for (const entry of entries) {
|
|
21024
|
-
if (entry?.type !== "session") continue;
|
|
21025
|
-
if (typeof entry.cwd === "string" && entry.cwd.trim() !== "") {
|
|
21026
|
-
subjectKey = workSubjectKeyFromProjectRoot(entry.cwd);
|
|
21027
|
-
}
|
|
21028
|
-
break;
|
|
21029
|
-
}
|
|
21030
|
-
if (typeof supplied?.subjectKey === "string") {
|
|
21031
|
-
subjectKey = supplied.subjectKey;
|
|
21032
|
-
}
|
|
21033
|
-
let phase;
|
|
21034
|
-
let allowedPhases;
|
|
21035
|
-
if (supplied !== void 0 && Object.hasOwn(supplied, "phase")) {
|
|
21036
|
-
phase = supplied.phase ?? null;
|
|
21037
|
-
} else {
|
|
21038
|
-
const meta = packagedRoleMetadata(terminalRole);
|
|
21039
|
-
if (meta !== void 0) {
|
|
21040
|
-
if (meta.phases.length === 1) {
|
|
21041
|
-
phase = meta.phases[0];
|
|
21042
|
-
} else {
|
|
21043
|
-
allowedPhases = meta.phases;
|
|
21044
|
-
}
|
|
21045
|
-
}
|
|
21046
|
-
}
|
|
21047
|
-
return {
|
|
21048
|
-
role: terminalRole,
|
|
21049
|
-
...phase !== void 0 ? { phase } : {},
|
|
21050
|
-
...allowedPhases !== void 0 ? { allowedPhases } : {},
|
|
21051
|
-
...subjectKey !== void 0 ? { subjectKey } : {}
|
|
21052
|
-
};
|
|
21053
|
-
}
|
|
21054
|
-
function navigatorAttendanceCorrelatedWithBoundMarker(details, attendanceIndex, terminal, marker) {
|
|
21055
|
-
if (attendanceIndex <= terminal.index) return false;
|
|
21056
|
-
if (details.version !== 1) return false;
|
|
21057
|
-
if (details.role !== terminal.role) return false;
|
|
21058
|
-
if (details.role !== marker.role) return false;
|
|
20954
|
+
function navigatorAttendanceCorrelatedWithBoundMarker(details, attendanceIndex, terminalIndex, marker) {
|
|
20955
|
+
if (attendanceIndex <= terminalIndex) return false;
|
|
21059
20956
|
if (details.invocationId !== marker.invocationId) return false;
|
|
21060
|
-
if (details.phase !== marker.phase) return false;
|
|
21061
|
-
if (typeof details.subjectKey !== "string") return false;
|
|
21062
|
-
if (!workSubjectKeysEqual(details.subjectKey, marker.subjectKey)) return false;
|
|
21063
20957
|
return true;
|
|
21064
20958
|
}
|
|
21065
20959
|
function parseNavigatorAttendanceDetails(details) {
|
|
@@ -21110,39 +21004,32 @@ function parseNavigatorAttendanceDetails(details) {
|
|
|
21110
21004
|
reason: "Navigator attendance disposition is unparseable"
|
|
21111
21005
|
};
|
|
21112
21006
|
}
|
|
21113
|
-
function extractNavigatorFact(entries
|
|
21114
|
-
const
|
|
21115
|
-
if (
|
|
21007
|
+
function extractNavigatorFact(entries) {
|
|
21008
|
+
const terminal = findLatestDurablePackagedRoleTerminal(entries);
|
|
21009
|
+
if (terminal === void 0) {
|
|
21116
21010
|
return {
|
|
21117
21011
|
disposition: "unavailable",
|
|
21118
21012
|
source: "unknown",
|
|
21119
21013
|
reason: "Navigator attendance has no durable packaged role terminal"
|
|
21120
21014
|
};
|
|
21121
21015
|
}
|
|
21122
|
-
|
|
21123
|
-
|
|
21124
|
-
|
|
21125
|
-
|
|
21126
|
-
|
|
21127
|
-
|
|
21128
|
-
|
|
21129
|
-
if (binding.kind === "unbound") {
|
|
21130
|
-
return {
|
|
21131
|
-
disposition: "unavailable",
|
|
21132
|
-
source: "unknown",
|
|
21133
|
-
reason: "Navigator attendance is uncorrelated with session invocation facts"
|
|
21134
|
-
};
|
|
21016
|
+
let markerIndex = -1;
|
|
21017
|
+
for (let i = terminal.index - 1; i >= 0; i -= 1) {
|
|
21018
|
+
const entry = entries[i];
|
|
21019
|
+
if (entry?.type === "custom" && entry.customType === NAVIGATOR_INVOCATION_ENTRY) {
|
|
21020
|
+
markerIndex = i;
|
|
21021
|
+
break;
|
|
21022
|
+
}
|
|
21135
21023
|
}
|
|
21136
|
-
|
|
21137
|
-
if (marker.role !== terminal.role) {
|
|
21024
|
+
if (markerIndex < 0) {
|
|
21138
21025
|
return {
|
|
21139
21026
|
disposition: "unavailable",
|
|
21140
21027
|
source: "unknown",
|
|
21141
21028
|
reason: "Navigator attendance is uncorrelated with session invocation facts"
|
|
21142
21029
|
};
|
|
21143
21030
|
}
|
|
21144
|
-
const
|
|
21145
|
-
if (
|
|
21031
|
+
const marker = parseInvocationMarkerIdentity(entries[markerIndex]?.data);
|
|
21032
|
+
if (marker === void 0) {
|
|
21146
21033
|
return {
|
|
21147
21034
|
disposition: "unavailable",
|
|
21148
21035
|
source: "unknown",
|
|
@@ -21163,7 +21050,7 @@ function extractNavigatorFact(entries, identity) {
|
|
|
21163
21050
|
if (!navigatorAttendanceCorrelatedWithBoundMarker(
|
|
21164
21051
|
details,
|
|
21165
21052
|
i,
|
|
21166
|
-
|
|
21053
|
+
terminal.index,
|
|
21167
21054
|
marker
|
|
21168
21055
|
)) {
|
|
21169
21056
|
return {
|
|
@@ -21184,7 +21071,7 @@ function extractNavigatorFact(entries, identity) {
|
|
|
21184
21071
|
async function extractNavigatorFactFromAdmittedSession(admitted) {
|
|
21185
21072
|
try {
|
|
21186
21073
|
const entries = await readBoundSessionEntries(admitted.sessionFile);
|
|
21187
|
-
return extractNavigatorFact(entries
|
|
21074
|
+
return extractNavigatorFact(entries);
|
|
21188
21075
|
} catch (error) {
|
|
21189
21076
|
if (isMissingPathError2(error)) {
|
|
21190
21077
|
return {
|
|
@@ -21347,10 +21234,7 @@ async function settleLawfulJudgeTerminalResult(admitted) {
|
|
|
21347
21234
|
if (roleOutcome === void 0) {
|
|
21348
21235
|
return void 0;
|
|
21349
21236
|
}
|
|
21350
|
-
const navigator = extractNavigatorFact(
|
|
21351
|
-
entries,
|
|
21352
|
-
attendanceIdentityFromAdmitted(admitted)
|
|
21353
|
-
);
|
|
21237
|
+
const navigator = extractNavigatorFact(entries);
|
|
21354
21238
|
const artifacts = await publishJudgeArtifacts(
|
|
21355
21239
|
admitted,
|
|
21356
21240
|
roleOutcome,
|
|
@@ -21371,10 +21255,7 @@ async function settleLawfulCoderTerminalResult(admitted, options = {}) {
|
|
|
21371
21255
|
if (entries === void 0) return void 0;
|
|
21372
21256
|
const extracted = extractCoderRoleOutcome(entries);
|
|
21373
21257
|
if (extracted === void 0) return void 0;
|
|
21374
|
-
const navigator = extractNavigatorFact(
|
|
21375
|
-
entries,
|
|
21376
|
-
attendanceIdentityFromAdmitted(admitted)
|
|
21377
|
-
);
|
|
21258
|
+
const navigator = extractNavigatorFact(entries);
|
|
21378
21259
|
const artifacts = await publishCoderArtifacts(
|
|
21379
21260
|
admitted,
|
|
21380
21261
|
extracted.outcome,
|
|
@@ -21506,10 +21387,7 @@ async function settleLawfulFixerTerminalResult(admitted, options) {
|
|
|
21506
21387
|
if (entries === void 0) return void 0;
|
|
21507
21388
|
const extracted = extractFixerRoleOutcome(entries);
|
|
21508
21389
|
if (extracted === void 0) return void 0;
|
|
21509
|
-
const navigator = extractNavigatorFact(
|
|
21510
|
-
entries,
|
|
21511
|
-
attendanceIdentityFromAdmitted(admitted)
|
|
21512
|
-
);
|
|
21390
|
+
const navigator = extractNavigatorFact(entries);
|
|
21513
21391
|
const methodInvocations = extractFixerMethodInvocations(entries, {
|
|
21514
21392
|
allowedLocations: [
|
|
21515
21393
|
options.methodSkillPath,
|
|
@@ -21635,10 +21513,7 @@ async function settleLawfulCollectorTerminalResult(admitted) {
|
|
|
21635
21513
|
return void 0;
|
|
21636
21514
|
}
|
|
21637
21515
|
assertCollectorReceiptMatchesAdmitted(extracted.receipt, admitted);
|
|
21638
|
-
const navigator = extractNavigatorFact(
|
|
21639
|
-
entries,
|
|
21640
|
-
attendanceIdentityFromAdmitted(admitted)
|
|
21641
|
-
);
|
|
21516
|
+
const navigator = extractNavigatorFact(entries);
|
|
21642
21517
|
const artifacts = await publishCollectorArtifacts(
|
|
21643
21518
|
admitted,
|
|
21644
21519
|
extracted.outcome,
|
|
@@ -21762,10 +21637,7 @@ async function settleLawfulDoctorTerminalResult(admitted) {
|
|
|
21762
21637
|
throw error;
|
|
21763
21638
|
}
|
|
21764
21639
|
}
|
|
21765
|
-
const navigator = extractNavigatorFact(
|
|
21766
|
-
entries,
|
|
21767
|
-
attendanceIdentityFromAdmitted(admitted)
|
|
21768
|
-
);
|
|
21640
|
+
const navigator = extractNavigatorFact(entries);
|
|
21769
21641
|
const artifacts = await publishDoctorArtifacts(
|
|
21770
21642
|
admitted,
|
|
21771
21643
|
extracted.outcome,
|
|
@@ -21926,10 +21798,7 @@ async function settleLawfulReviewerTerminalResult(admitted, options) {
|
|
|
21926
21798
|
if (entries === void 0) return void 0;
|
|
21927
21799
|
const extracted = extractReviewerRoleOutcome(entries);
|
|
21928
21800
|
if (extracted === void 0) return void 0;
|
|
21929
|
-
const navigator = extractNavigatorFact(
|
|
21930
|
-
entries,
|
|
21931
|
-
attendanceIdentityFromAdmitted(admitted)
|
|
21932
|
-
);
|
|
21801
|
+
const navigator = extractNavigatorFact(entries);
|
|
21933
21802
|
const methodInvocations = extractReviewerMethodInvocations(entries, {
|
|
21934
21803
|
allowedLocations: [
|
|
21935
21804
|
options.methodSkillPath,
|
|
@@ -22109,10 +21978,7 @@ async function settleLawfulMergerTerminalResult(admitted, options) {
|
|
|
22109
21978
|
]
|
|
22110
21979
|
});
|
|
22111
21980
|
if (methodInvocations.length === 0) return void 0;
|
|
22112
|
-
const navigator = extractNavigatorFact(
|
|
22113
|
-
entries,
|
|
22114
|
-
attendanceIdentityFromAdmitted(admitted)
|
|
22115
|
-
);
|
|
21981
|
+
const navigator = extractNavigatorFact(entries);
|
|
22116
21982
|
const artifacts = await publishMergerArtifacts(
|
|
22117
21983
|
admitted,
|
|
22118
21984
|
extracted.outcome,
|
|
@@ -22439,8 +22305,6 @@ var init_settlement = __esm({
|
|
|
22439
22305
|
init_method_skill();
|
|
22440
22306
|
init_navigator_invocation_identity();
|
|
22441
22307
|
init_receipt_delivery_policy();
|
|
22442
|
-
init_packaged_role_registry();
|
|
22443
|
-
init_work_subject_identity();
|
|
22444
22308
|
init_invocation();
|
|
22445
22309
|
init_terminal();
|
|
22446
22310
|
CONCISE_DIAGNOSTIC_MAX_CHARS = 480;
|
|
@@ -24040,7 +23904,7 @@ var init_judge_run = __esm({
|
|
|
24040
23904
|
|
|
24041
23905
|
// src/public-cli/merger-run.ts
|
|
24042
23906
|
import { mkdir as mkdir4, writeFile as writeFile11 } from "node:fs/promises";
|
|
24043
|
-
import { join as join17, resolve as
|
|
23907
|
+
import { join as join17, resolve as resolve6 } from "node:path";
|
|
24044
23908
|
function buildMergerActivationExtraArgs(admitted, options) {
|
|
24045
23909
|
const prompt = buildMergerTransportPrompt(admitted);
|
|
24046
23910
|
const skillPath = resolvePackagedMethodSkillPath(
|
|
@@ -24265,7 +24129,7 @@ async function loadMergerMethodMaterial(packageRoot2) {
|
|
|
24265
24129
|
);
|
|
24266
24130
|
}
|
|
24267
24131
|
async function admitMergerShellForActivationFailure(options) {
|
|
24268
|
-
const projectRoot =
|
|
24132
|
+
const projectRoot = resolve6(options.project ?? options.cwd);
|
|
24269
24133
|
const runId = (options.createRunId ?? uuidv7)();
|
|
24270
24134
|
const { ledgerHome, bookKey, runDirectory, sessionDirectory, sessionFile } = roleRunSessionCoordinates({ cwd: projectRoot, runId, role: "merger", home: options.home });
|
|
24271
24135
|
ensureRealDirectoryTree(ledgerHome, sessionDirectory);
|
|
@@ -24920,8 +24784,8 @@ var init_atomic_write = __esm({
|
|
|
24920
24784
|
import { open as open3, readFile as readFile10, unlink as unlink4 } from "node:fs/promises";
|
|
24921
24785
|
import { dirname as dirname8, join as join20 } from "node:path";
|
|
24922
24786
|
function sleep(ms) {
|
|
24923
|
-
return new Promise((
|
|
24924
|
-
setTimeout(
|
|
24787
|
+
return new Promise((resolve8) => {
|
|
24788
|
+
setTimeout(resolve8, ms);
|
|
24925
24789
|
});
|
|
24926
24790
|
}
|
|
24927
24791
|
async function withTaishiLibraryIndexLock(ledgerHome, fn) {
|
|
@@ -26808,7 +26672,7 @@ var init_taishi_entry = __esm({
|
|
|
26808
26672
|
|
|
26809
26673
|
// src/public-cli/taishi-run.ts
|
|
26810
26674
|
import { readFile as readFile15 } from "node:fs/promises";
|
|
26811
|
-
import { isAbsolute as isAbsolute5, resolve as
|
|
26675
|
+
import { isAbsolute as isAbsolute5, resolve as resolve7 } from "node:path";
|
|
26812
26676
|
async function buildTaishiIssueModeInputFromPublicArgv(parsed, ledgerHome) {
|
|
26813
26677
|
const ticket = parsed.ticket;
|
|
26814
26678
|
const directRoot = parsed.projectRoot;
|
|
@@ -26854,7 +26718,7 @@ async function buildTaishiSweepModeInputFromAttachmentPaths(attachmentPaths) {
|
|
|
26854
26718
|
);
|
|
26855
26719
|
}
|
|
26856
26720
|
const sourcePath = attachmentPaths[0];
|
|
26857
|
-
const absolute = isAbsolute5(sourcePath) ? sourcePath :
|
|
26721
|
+
const absolute = isAbsolute5(sourcePath) ? sourcePath : resolve7(sourcePath);
|
|
26858
26722
|
let bytes;
|
|
26859
26723
|
try {
|
|
26860
26724
|
bytes = await readFile15(absolute);
|
package/package.json
CHANGED
|
@@ -197,33 +197,6 @@ export type NavigatorContextProjection = {
|
|
|
197
197
|
liveRoleHelp: Array<{ role: NavigatorTargetRole; help: string }>;
|
|
198
198
|
};
|
|
199
199
|
|
|
200
|
-
/**
|
|
201
|
-
* Shared terminal-internal consistency for Navigator advice vs the just-accepted
|
|
202
|
-
* settlement (family #224/#226/#227). One table for all seats — not per-role guards.
|
|
203
|
-
*
|
|
204
|
-
* Merger closes delivery. It is only consistent immediately after judge converged.
|
|
205
|
-
* Fresh accepted work from any other seat must not skip to merger.
|
|
206
|
-
*
|
|
207
|
-
* Unfinished is an open handoff (ADR 0050): recommending judge would send half-done
|
|
208
|
-
* work to audit. Machine criterion anchors only status=unfinished — refused and
|
|
209
|
-
* partially_completed remain settled terminals whose judge path stays lawful.
|
|
210
|
-
* Positive continuation is free-form via rebind + status-matched candidates
|
|
211
|
-
* (ADR 0010/0061); this only suppresses self-contradictory typed emission.
|
|
212
|
-
*/
|
|
213
|
-
export function navigatorAdviceConsistentWithSettlement(
|
|
214
|
-
next: NavigatorRouteTarget,
|
|
215
|
-
settlement: NavigatorSettlement,
|
|
216
|
-
): boolean {
|
|
217
|
-
if (settlement.kind !== "accepted") return true;
|
|
218
|
-
// #227: open unfinished handoff must not be typed as next=judge.
|
|
219
|
-
if (settlement.status === "unfinished" && next.role === "judge") return false;
|
|
220
|
-
// #265: completed Fixer apply must not be sent back to repeat the same work.
|
|
221
|
-
if (settlement.role === "fixer" && settlement.phase === "apply" && settlement.status === "completed"
|
|
222
|
-
&& next.role === "fixer" && next.phase === "apply") return false;
|
|
223
|
-
if (next.role !== "merger") return true;
|
|
224
|
-
return settlement.role === "judge" && settlement.status === "converged";
|
|
225
|
-
}
|
|
226
|
-
|
|
227
200
|
// Provider admission is ADR 0060 object root only. Nested advisory shape
|
|
228
201
|
// (candidates/next/route/matches/reason/command) is never a gate — every object
|
|
229
202
|
// root reaches the unique execute/normalize path exactly once.
|
|
@@ -478,25 +451,52 @@ export function createNavigatorPrepareTool(onOutput: (value: PrepareOutput) => v
|
|
|
478
451
|
});
|
|
479
452
|
}
|
|
480
453
|
|
|
481
|
-
|
|
454
|
+
/**
|
|
455
|
+
* Candidate pick plus whether matches keyed it to this settlement.
|
|
456
|
+
* Single owner for role/phase/status match truth (selection ranking + stale-context rebind).
|
|
457
|
+
* Structural only — never inspects next.role for routing legality.
|
|
458
|
+
*/
|
|
459
|
+
export type NavigatorCandidateSelection = {
|
|
460
|
+
readonly candidate: NavigatorCandidate;
|
|
461
|
+
/** True when matches keyed this candidate to the settlement (no stale-context rebind). */
|
|
462
|
+
readonly matchedToSettlement: boolean;
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
export function selectNavigatorCandidate(
|
|
466
|
+
candidates: readonly NavigatorCandidate[],
|
|
467
|
+
settlement: NavigatorSettlement,
|
|
468
|
+
): NavigatorCandidateSelection | undefined {
|
|
482
469
|
if (settlement.kind !== "accepted") return undefined;
|
|
483
470
|
const usable = candidates.filter((candidate) => candidate.next !== undefined);
|
|
484
471
|
if (usable.length === 0) return undefined;
|
|
485
|
-
const
|
|
472
|
+
const rolePhaseMatched = usable.filter((candidate) =>
|
|
486
473
|
candidate.matches !== undefined
|
|
487
474
|
&& candidate.matches.role === settlement.role
|
|
488
475
|
&& candidate.matches.phase === settlement.phase,
|
|
489
476
|
);
|
|
490
477
|
// Status-specific candidates outrank role/phase generics regardless of declaration order.
|
|
491
|
-
if (
|
|
478
|
+
if (rolePhaseMatched.length > 0) {
|
|
492
479
|
if (settlement.status !== undefined) {
|
|
493
|
-
const statusSpecific =
|
|
494
|
-
|
|
480
|
+
const statusSpecific = rolePhaseMatched.find(
|
|
481
|
+
(candidate) => candidate.matches?.statuses?.includes(settlement.status!) === true,
|
|
482
|
+
);
|
|
483
|
+
if (statusSpecific !== undefined) {
|
|
484
|
+
return { candidate: statusSpecific, matchedToSettlement: true };
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
const rolePhaseGeneric = rolePhaseMatched.find(
|
|
488
|
+
(candidate) => candidate.matches?.statuses === undefined,
|
|
489
|
+
);
|
|
490
|
+
if (rolePhaseGeneric !== undefined) {
|
|
491
|
+
return { candidate: rolePhaseGeneric, matchedToSettlement: true };
|
|
495
492
|
}
|
|
496
|
-
return
|
|
493
|
+
return undefined;
|
|
497
494
|
}
|
|
498
495
|
// v1 direction-only / broken matches: absent match metadata must not drop a usable next.
|
|
499
|
-
|
|
496
|
+
// Not settlement-keyed → caller may run one stale-context rebind.
|
|
497
|
+
const unbound = usable.find((candidate) => candidate.matches === undefined);
|
|
498
|
+
if (unbound === undefined) return undefined;
|
|
499
|
+
return { candidate: unbound, matchedToSettlement: false };
|
|
500
500
|
}
|
|
501
501
|
|
|
502
502
|
export function formatNavigatorReport(report: NavigatorReport): string {
|
|
@@ -631,6 +631,9 @@ export function createNavigatorAttendance(options: NavigatorAttendanceOptions) {
|
|
|
631
631
|
// pi.appendEntry at lifecycle start — not optional sessionManager probing.
|
|
632
632
|
const boundSettlement = prepareBoundSettlement;
|
|
633
633
|
prepareBoundSettlement = undefined;
|
|
634
|
+
// Each prepare owns the no-receipt flag; a later settlement-bound rebind must
|
|
635
|
+
// not inherit a speculative no-receipt outcome.
|
|
636
|
+
preparationNoReceipt = false;
|
|
634
637
|
const invocationId = invocationPrincipal;
|
|
635
638
|
activeInvocationId = invocationId;
|
|
636
639
|
if (contextError !== undefined) throw navigatorUnavailableError("context", contextError);
|
|
@@ -958,40 +961,34 @@ export function createNavigatorAttendance(options: NavigatorAttendanceOptions) {
|
|
|
958
961
|
let prepared = await preparation;
|
|
959
962
|
session?.appendEntry(SETTLEMENT_ENTRY, { invocationId, subjectKey, role: settlement.role, phase: settlement.phase, kind: settlement.kind, ...(settlement.status === undefined ? {} : { status: settlement.status }) });
|
|
960
963
|
let selected = selectNavigatorCandidate(prepared, settlement);
|
|
961
|
-
//
|
|
962
|
-
//
|
|
963
|
-
//
|
|
964
|
-
//
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
) {
|
|
964
|
+
// Speculative prepare runs before this terminal exists and may treat prior
|
|
965
|
+
// history as decisive. When selection provenance says matches did not key
|
|
966
|
+
// this candidate to the settlement, rebind once with currentSettlement.
|
|
967
|
+
// Stale-context repair only — reachable without any next.role legality
|
|
968
|
+
// table. After selection (speculative or rebound), advice is passed
|
|
969
|
+
// through as-is (ADR 0010 / ADR 0061: caller may ignore).
|
|
970
|
+
if (selected?.candidate.next !== undefined && !selected.matchedToSettlement) {
|
|
969
971
|
prepareBoundSettlement = settlement;
|
|
970
972
|
prepared = await prepare();
|
|
971
973
|
selected = selectNavigatorCandidate(prepared, settlement);
|
|
972
|
-
if (
|
|
973
|
-
selected?.next !== undefined
|
|
974
|
-
&& !navigatorAdviceConsistentWithSettlement(selected.next, settlement)
|
|
975
|
-
) {
|
|
976
|
-
throw new Error("Navigator advice contradicts the accepted settlement");
|
|
977
|
-
}
|
|
978
974
|
}
|
|
979
975
|
// Budget exhaustion is affirmative typed no-advice; malformed submitted
|
|
980
976
|
// advice remains the existing unavailable path.
|
|
981
|
-
|
|
977
|
+
const selectedCandidate = selected?.candidate;
|
|
978
|
+
if (selectedCandidate?.next === undefined && preparationNoReceipt) {
|
|
982
979
|
report = { disposition: "no-advice" };
|
|
983
|
-
} else if (
|
|
980
|
+
} else if (selectedCandidate?.next === undefined) {
|
|
984
981
|
throw new Error("Navigator prepared no machine-usable next direction");
|
|
985
982
|
} else {
|
|
986
|
-
const selectedRoute =
|
|
983
|
+
const selectedRoute = selectedCandidate.route;
|
|
987
984
|
const routeChanged = selectedRoute !== undefined && !routeEqual(previousRoute, selectedRoute);
|
|
988
985
|
// Single owner: public registry renderer (ADR 0052). Model command prose is never authority.
|
|
989
|
-
const command = renderPublicAkRoleCommand(
|
|
986
|
+
const command = renderPublicAkRoleCommand(selectedCandidate.next);
|
|
990
987
|
report = {
|
|
991
988
|
disposition: "recommendation",
|
|
992
989
|
...(routeChanged ? { route: selectedRoute } : {}),
|
|
993
|
-
next:
|
|
994
|
-
...(
|
|
990
|
+
next: selectedCandidate.next,
|
|
991
|
+
...(selectedCandidate.reason === undefined ? {} : { reason: oneLine(selectedCandidate.reason) }),
|
|
995
992
|
...(command === undefined ? {} : { command }),
|
|
996
993
|
};
|
|
997
994
|
if (selectedRoute !== undefined) {
|