@akagilnc/pi-workflow-roles 0.1.5593 → 0.1.5598
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/acp-host/production-host.js +168 -394
- package/dist/headless-host/production-host.js +168 -394
- package/dist/merger-contracts.js +6 -2
- package/dist/migrate-book-topology.js +4846 -10449
- package/dist/package-contracts/worker-output.js +1 -6
- package/dist/packaged-role-registry.js +5 -4
- package/dist/public-cli/invocation.js +20 -53
- package/dist/public-cli/main.js +18046 -18197
- package/dist/public-cli/option-definitions.js +2 -2
- package/dist/public-cli/post-admission.js +2 -2
- package/dist/public-cli/run-lifecycle.js +2 -29
- package/dist/role-run-relocation.js +3 -4
- package/package.json +1 -1
- package/scripts/build-package.mjs +0 -1
- package/src/host-contracts.ts +0 -3
- package/src/merger-contracts.ts +6 -2
- package/src/merger-role.ts +11 -1
- package/src/navigator-attendance.ts +2 -2
- package/src/package-contracts/worker-output.ts +0 -8
- package/src/packaged-role-registry.ts +4 -3
- package/src/public-cli/invocation.ts +25 -72
- package/src/public-cli/option-definitions.ts +2 -2
- package/src/public-cli/post-admission.ts +2 -2
- package/src/public-cli/run-lifecycle.ts +2 -39
- package/src/role-run-relocation.ts +3 -4
- package/src/role-runtime-dependencies.ts +0 -2
- package/src/role-runtime.ts +0 -16
- package/src/worker-role.ts +11 -78
- package/dist/package-contracts/fixer-packet.js +0 -77
- package/packets/fixer-prerequisites.json +0 -6
- package/src/package-contracts/fixer-packet.ts +0 -91
|
@@ -370,8 +370,8 @@ const FIXER_OPTIONS = [
|
|
|
370
370
|
repeatable: false,
|
|
371
371
|
form: "option",
|
|
372
372
|
description: {
|
|
373
|
-
en: "
|
|
374
|
-
zh: "
|
|
373
|
+
en: "Caller prerequisites path passed as-is to the role. Package does not read, copy, or validate; use an absolute path when cwd differs from --project.",
|
|
374
|
+
zh: "调用方前置条件文件路径原样递给衙门。包不读、不复制、不校验;调用方当前目录与 --project 不同时请给绝对路径。",
|
|
375
375
|
},
|
|
376
376
|
},
|
|
377
377
|
];
|
|
@@ -49,12 +49,12 @@ function projectRelocatedTurnIdentity(request, result, admitted, relocation) {
|
|
|
49
49
|
mutableRequest.principal = admitted.principal;
|
|
50
50
|
const activation = mutableRequest.activation;
|
|
51
51
|
if (isRecord(activation)) {
|
|
52
|
-
for (const field of ["
|
|
52
|
+
for (const field of ["inputPath"]) {
|
|
53
53
|
const record = activation;
|
|
54
54
|
if (field in record)
|
|
55
55
|
record[field] = rewrite(record[field]);
|
|
56
56
|
}
|
|
57
|
-
// #1165:
|
|
57
|
+
// #1165/#1168: caller file-flag paths are not activation fields to rewrite.
|
|
58
58
|
}
|
|
59
59
|
if (result.terminal !== undefined) {
|
|
60
60
|
for (const artifact of result.terminal.artifacts) {
|
|
@@ -766,10 +766,7 @@ async function loadResumableRunRecord(home, runId, authority) {
|
|
|
766
766
|
let instructionEmpty = true;
|
|
767
767
|
let attachments = [];
|
|
768
768
|
let phase;
|
|
769
|
-
let taskPath;
|
|
770
|
-
let packetPath;
|
|
771
769
|
let prerequisitesPath;
|
|
772
|
-
let prerequisites;
|
|
773
770
|
let baseRevision;
|
|
774
771
|
let lens;
|
|
775
772
|
let authorityRefs;
|
|
@@ -813,19 +810,10 @@ async function loadResumableRunRecord(home, runId, authority) {
|
|
|
813
810
|
if (record.phase === "plan" || record.phase === "apply") {
|
|
814
811
|
phase = record.phase;
|
|
815
812
|
}
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
}
|
|
819
|
-
if (typeof record.packetPath === "string" && record.packetPath.trim() !== "") {
|
|
820
|
-
packetPath = record.packetPath;
|
|
821
|
-
}
|
|
822
|
-
if (typeof record.prerequisitesPath === "string" &&
|
|
823
|
-
record.prerequisitesPath.trim() !== "") {
|
|
813
|
+
// #1168: opaque caller path on resume — do not trim-filter provided values.
|
|
814
|
+
if (typeof record.prerequisitesPath === "string") {
|
|
824
815
|
prerequisitesPath = record.prerequisitesPath;
|
|
825
816
|
}
|
|
826
|
-
if (Array.isArray(record.prerequisites)) {
|
|
827
|
-
prerequisites = record.prerequisites;
|
|
828
|
-
}
|
|
829
817
|
if (typeof record.baseRevision === "string" &&
|
|
830
818
|
record.baseRevision.trim() !== "") {
|
|
831
819
|
baseRevision = record.baseRevision;
|
|
@@ -974,10 +962,7 @@ async function loadResumableRunRecord(home, runId, authority) {
|
|
|
974
962
|
instructionEmpty,
|
|
975
963
|
attachments,
|
|
976
964
|
...(phase === undefined ? {} : { phase }),
|
|
977
|
-
...(taskPath === undefined ? {} : { taskPath }),
|
|
978
|
-
...(packetPath === undefined ? {} : { packetPath }),
|
|
979
965
|
...(prerequisitesPath === undefined ? {} : { prerequisitesPath }),
|
|
980
|
-
...(prerequisites === undefined ? {} : { prerequisites }),
|
|
981
966
|
...(baseRevision === undefined ? {} : { baseRevision }),
|
|
982
967
|
...(lens === undefined ? {} : { lens }),
|
|
983
968
|
...(authorityRefs === undefined ? {} : { authorityRefs }),
|
|
@@ -1079,10 +1064,6 @@ function admitResumedRole(loaded) {
|
|
|
1079
1064
|
}
|
|
1080
1065
|
case "worker-task": {
|
|
1081
1066
|
const phase = resumedWorkerPhase(fields.phase ?? loaded.run.phase, record.phases, role, runId);
|
|
1082
|
-
const taskPath = fields.taskPath;
|
|
1083
|
-
if (taskPath === undefined) {
|
|
1084
|
-
throw new CliUsageError(`role run admitted coder task path is missing: ${runId}`);
|
|
1085
|
-
}
|
|
1086
1067
|
if (fields.instruction.trim() === "") {
|
|
1087
1068
|
throw new CliUsageError(`role run admitted coder task is blank: ${runId}`);
|
|
1088
1069
|
}
|
|
@@ -1091,30 +1072,22 @@ function admitResumedRole(loaded) {
|
|
|
1091
1072
|
phase,
|
|
1092
1073
|
...base,
|
|
1093
1074
|
instructionEmpty: false,
|
|
1094
|
-
taskPath,
|
|
1095
1075
|
};
|
|
1096
1076
|
return admitted;
|
|
1097
1077
|
}
|
|
1098
1078
|
case "worker-packet": {
|
|
1099
1079
|
const phase = resumedWorkerPhase(fields.phase ?? loaded.run.phase, record.phases, role, runId);
|
|
1100
|
-
const packetPath = fields.packetPath;
|
|
1101
|
-
if (packetPath === undefined) {
|
|
1102
|
-
throw new CliUsageError(`role run admitted fixer packet path is missing: ${runId}`);
|
|
1103
|
-
}
|
|
1104
1080
|
if (fields.instruction.trim() === "") {
|
|
1105
1081
|
throw new CliUsageError(`role run admitted fixer instruction is blank: ${runId}`);
|
|
1106
1082
|
}
|
|
1107
|
-
const prerequisites = fields.prerequisites ?? Object.freeze([]);
|
|
1108
1083
|
const admitted = {
|
|
1109
1084
|
role: "fixer",
|
|
1110
1085
|
phase,
|
|
1111
1086
|
...base,
|
|
1112
1087
|
instructionEmpty: false,
|
|
1113
|
-
packetPath,
|
|
1114
1088
|
...(fields.prerequisitesPath === undefined
|
|
1115
1089
|
? {}
|
|
1116
1090
|
: { prerequisitesPath: fields.prerequisitesPath }),
|
|
1117
|
-
prerequisites,
|
|
1118
1091
|
};
|
|
1119
1092
|
return admitted;
|
|
1120
1093
|
}
|
|
@@ -19,10 +19,9 @@ const ADMITTED_PAGE_FIELDS = [
|
|
|
19
19
|
"admittedRequestPath", // pre-#1161 pages only
|
|
20
20
|
"sessionDirectory",
|
|
21
21
|
"sessionFile",
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
// #1165: requestManifestPath is a caller path — never rewrite.
|
|
22
|
+
// #1165/#1168: caller file-flag paths (requestManifestPath, prerequisitesPath)
|
|
23
|
+
// stay as given. Obsolete copy fields (taskPath/packetPath) are not rewritten —
|
|
24
|
+
// stock volumes keep their bytes; live relocate no longer maintains them.
|
|
26
25
|
"mergerInputPath",
|
|
27
26
|
"sourceRunPath",
|
|
28
27
|
];
|
package/package.json
CHANGED
|
@@ -55,7 +55,6 @@ const entries = [
|
|
|
55
55
|
"open-tool-schema",
|
|
56
56
|
"package-contracts/collector-output",
|
|
57
57
|
"package-contracts/fixer-output",
|
|
58
|
-
"package-contracts/fixer-packet",
|
|
59
58
|
"package-contracts/gatekeeper-output",
|
|
60
59
|
"package-contracts/judge-output",
|
|
61
60
|
"package-contracts/navigator-output",
|
package/src/host-contracts.ts
CHANGED
|
@@ -87,13 +87,10 @@ export type RoleTurnActivation =
|
|
|
87
87
|
| {
|
|
88
88
|
readonly role: "coder";
|
|
89
89
|
readonly phase: string;
|
|
90
|
-
readonly taskPath: string;
|
|
91
90
|
}
|
|
92
91
|
| {
|
|
93
92
|
readonly role: "fixer";
|
|
94
93
|
readonly phase: string;
|
|
95
|
-
readonly packetPath: string;
|
|
96
|
-
readonly prerequisitesPath?: string;
|
|
97
94
|
}
|
|
98
95
|
| {
|
|
99
96
|
readonly role: "reviewer";
|
package/src/merger-contracts.ts
CHANGED
|
@@ -11,7 +11,8 @@ export const mergerInputSchema = Type.Object({
|
|
|
11
11
|
attemptId: Type.String({ minLength: 1, description: "对账 attempt 身份(transport)" }),
|
|
12
12
|
targetObjectId: Type.String({ description: "材料:target parent OID;可空" }),
|
|
13
13
|
sourceObjectId: Type.String({ description: "材料:source parent OID;可空" }),
|
|
14
|
-
|
|
14
|
+
// #1168: task/authority dispatch copies removed; git-fact intents remain.
|
|
15
|
+
materials: Type.Object({ targetIntent: materialSchema, sourceIntent: materialSchema }),
|
|
15
16
|
expectedConflictPaths: Type.Array(Type.String(), { description: "材料:当前未合并路径;可空" }),
|
|
16
17
|
resolutionScope: Type.Array(Type.String(), { description: "材料:解析范围提示;可空" }),
|
|
17
18
|
authorizedChecks: Type.Array(checkSchema),
|
|
@@ -62,7 +63,10 @@ function readMaterial(value: unknown, label: string): MergerMaterial {
|
|
|
62
63
|
export function validateMergerInput(value: unknown): MergerInput {
|
|
63
64
|
if (!isRecord(value) || blank(value.attemptId)) fail("Merger input requires a non-empty attemptId for accounting");
|
|
64
65
|
if (!isRecord(value.materials)) fail("Merger materials are missing");
|
|
65
|
-
const materials = {
|
|
66
|
+
const materials = {
|
|
67
|
+
targetIntent: readMaterial(value.materials.targetIntent, "targetIntent"),
|
|
68
|
+
sourceIntent: readMaterial(value.materials.sourceIntent, "sourceIntent"),
|
|
69
|
+
};
|
|
66
70
|
const authorizedChecks = Array.isArray(value.authorizedChecks) ? value.authorizedChecks.filter((check): check is Record<string, unknown> => isRecord(check)).map(c => ({ name: asString(c.name), argv: asStringArray(c.argv).filter(a => a.trim().length > 0) })).filter(c => c.name.trim().length > 0 && c.argv.length > 0) : [];
|
|
67
71
|
return deepFreeze(structuredClone({ attemptId: (value.attemptId as string).trim(), targetObjectId: asString(value.targetObjectId), sourceObjectId: asString(value.sourceObjectId), materials, expectedConflictPaths: asStringArray(value.expectedConflictPaths), resolutionScope: asStringArray(value.resolutionScope), authorizedChecks }) as MergerInput);
|
|
68
72
|
}
|
package/src/merger-role.ts
CHANGED
|
@@ -21,6 +21,7 @@ function materialText(input: MergerInput, key: keyof MergerInput["materials"]):
|
|
|
21
21
|
* Merger (校书郎) role runtime.
|
|
22
22
|
* Submission tool records every call (#836); host end is the final.
|
|
23
23
|
* Git state / completion verification are not attendance or rejection gates (#827).
|
|
24
|
+
* #1168: dispatch text is the first message; assignment carries git facts only.
|
|
24
25
|
*/
|
|
25
26
|
export function createMergerRoleRuntime(pi: RoleHost, dependencies: MergerRoleDependencies) {
|
|
26
27
|
let activation: { soul: string; input: Readonly<MergerInput> } | undefined;
|
|
@@ -41,7 +42,16 @@ export function createMergerRoleRuntime(pi: RoleHost, dependencies: MergerRoleDe
|
|
|
41
42
|
});
|
|
42
43
|
pi.on("before_agent_start", (event) => {
|
|
43
44
|
if (!activation) throw new Error("校书郎未激活");
|
|
44
|
-
const admitted = {
|
|
45
|
+
const admitted = {
|
|
46
|
+
attemptId: activation.input.attemptId,
|
|
47
|
+
targetObjectId: activation.input.targetObjectId,
|
|
48
|
+
sourceObjectId: activation.input.sourceObjectId,
|
|
49
|
+
targetIntent: materialText(activation.input, "targetIntent"),
|
|
50
|
+
sourceIntent: materialText(activation.input, "sourceIntent"),
|
|
51
|
+
expectedConflictPaths: activation.input.expectedConflictPaths,
|
|
52
|
+
resolutionScope: activation.input.resolutionScope,
|
|
53
|
+
authorizedChecks: activation.input.authorizedChecks,
|
|
54
|
+
};
|
|
45
55
|
return { systemPrompt: `${event.systemPrompt}\n\n<merger_soul>\n${activation.soul}\n</merger_soul>\n\n<merger_assignment>\n${JSON.stringify(admitted)}\n</merger_assignment>` };
|
|
46
56
|
});
|
|
47
57
|
}
|
|
@@ -229,14 +229,14 @@ export function navigatorSubjectKey(
|
|
|
229
229
|
/**
|
|
230
230
|
* Role inputs for one ad-hoc work item live below role-specific run folders.
|
|
231
231
|
* The folder and filename are transport, not identity: the shared work root
|
|
232
|
-
* keeps
|
|
232
|
+
* keeps natural inputs on one subject.
|
|
233
233
|
*/
|
|
234
234
|
export function navigatorSubjectKeyForInput(subjectRoot: string, reference: string, cwd = process.cwd()): string {
|
|
235
235
|
if (issueRoot(subjectRoot) !== undefined || !subjectRoot.includes("/.ak/work/")) return subjectRoot;
|
|
236
236
|
const resolvedReference = resolve(cwd, reference);
|
|
237
237
|
const marker = "/runs/";
|
|
238
238
|
if (resolvedReference.includes(marker)) {
|
|
239
|
-
// The work root, not
|
|
239
|
+
// The work root, not a role-input filename, is the stable subject.
|
|
240
240
|
// Different roots remain isolated without inventing a filename convention.
|
|
241
241
|
return subjectRoot;
|
|
242
242
|
}
|
|
@@ -13,26 +13,18 @@ import {
|
|
|
13
13
|
type FixerOutput,
|
|
14
14
|
type FixerPhase,
|
|
15
15
|
} from "./fixer-output.ts";
|
|
16
|
-
import { fixerPrerequisiteSchema, fixerPrerequisitesSchema, parseFixerPrerequisites, validateFixerPrerequisites } from "./fixer-packet.ts";
|
|
17
|
-
import type { FixerInvocationInput, FixerPrerequisite } from "./fixer-packet.ts";
|
|
18
16
|
import { withTerminatingOutputDeclarations } from "./terminating-infrastructure.ts";
|
|
19
17
|
|
|
20
18
|
export {
|
|
21
19
|
FIXER_OUTPUT_TOOL_NAME,
|
|
22
20
|
fixerOutputSchema,
|
|
23
21
|
validateFixerOutput,
|
|
24
|
-
fixerPrerequisiteSchema,
|
|
25
|
-
fixerPrerequisitesSchema,
|
|
26
|
-
parseFixerPrerequisites,
|
|
27
|
-
validateFixerPrerequisites,
|
|
28
22
|
};
|
|
29
23
|
export type {
|
|
30
24
|
FixerBlocker,
|
|
31
25
|
FixerClassResult,
|
|
32
26
|
FixerOutput,
|
|
33
27
|
FixerPhase,
|
|
34
|
-
FixerInvocationInput,
|
|
35
|
-
FixerPrerequisite,
|
|
36
28
|
};
|
|
37
29
|
|
|
38
30
|
export const CODER_OUTPUT_TOOL_NAME = "ak_coder_output";
|
|
@@ -115,10 +115,10 @@ export const PUBLIC_ROLE_RECORDS = [
|
|
|
115
115
|
reportPhase: true,
|
|
116
116
|
},
|
|
117
117
|
boardPlacement: "marshal",
|
|
118
|
+
/** #1168: dispatch is first message; navigator reads admitted instruction. */
|
|
119
|
+
navigatorSubject: "public-instruction",
|
|
118
120
|
activationFlags: [
|
|
119
|
-
{ field: "packetPath", flag: "ak-fix-packet", binds: "input" },
|
|
120
121
|
{ field: "phase", flag: "ak-fixer-phase", binds: "phase" },
|
|
121
|
-
{ field: "prerequisitesPath", flag: "ak-fixer-prerequisites" },
|
|
122
122
|
],
|
|
123
123
|
activationStage: "load-and-install",
|
|
124
124
|
sessionMaterials: [
|
|
@@ -145,8 +145,9 @@ export const PUBLIC_ROLE_RECORDS = [
|
|
|
145
145
|
artifactFace: {
|
|
146
146
|
reportPhase: true,
|
|
147
147
|
},
|
|
148
|
+
/** #1168: dispatch is first message; navigator reads admitted instruction. */
|
|
149
|
+
navigatorSubject: "public-instruction",
|
|
148
150
|
activationFlags: [
|
|
149
|
-
{ field: "taskPath", flag: "ak-coder-task", binds: "input" },
|
|
150
151
|
{ field: "phase", flag: "ak-coder-phase", binds: "phase" },
|
|
151
152
|
],
|
|
152
153
|
activationStage: "load-and-install",
|
|
@@ -65,11 +65,6 @@ import {
|
|
|
65
65
|
type CollectorRepository,
|
|
66
66
|
} from "../collector-config.ts";
|
|
67
67
|
import { ownerRepoFromGitHubRemoteUrl } from "./github-remote.ts";
|
|
68
|
-
import {
|
|
69
|
-
FixerPacketValidationError,
|
|
70
|
-
parseFixerPrerequisites,
|
|
71
|
-
type FixerPrerequisite,
|
|
72
|
-
} from "../package-contracts/fixer-packet.ts";
|
|
73
68
|
import type { FixerPhase } from "../package-contracts/fixer-output.ts";
|
|
74
69
|
import { createProductionMergerGitState } from "../merger-git-state.ts";
|
|
75
70
|
import type { MergerGitState } from "../merger-git-state.ts";
|
|
@@ -204,20 +199,14 @@ export type AdmittedCoderInvocation = AdmittedRoleInvocationBase & {
|
|
|
204
199
|
readonly role: "coder";
|
|
205
200
|
/** Explicit plan or default apply — preserved through admission and continuation. */
|
|
206
201
|
readonly phase: CoderPhase;
|
|
207
|
-
/** Durable task file path consumed by internal --ak-coder-task. */
|
|
208
|
-
readonly taskPath: string;
|
|
209
202
|
};
|
|
210
203
|
|
|
211
204
|
export type AdmittedFixerInvocation = AdmittedRoleInvocationBase & {
|
|
212
205
|
readonly role: "fixer";
|
|
213
206
|
/** Explicit plan or default apply — preserved through admission and continuation. */
|
|
214
207
|
readonly phase: FixerPhase;
|
|
215
|
-
/**
|
|
216
|
-
readonly packetPath: string;
|
|
217
|
-
/** Optional durable prerequisites JSON path for --ak-fixer-prerequisites. */
|
|
208
|
+
/** Optional caller --prerequisites path as-is (#1168; package does not read it). */
|
|
218
209
|
readonly prerequisitesPath?: string;
|
|
219
|
-
/** Structurally validated prerequisite declarations frozen at admission. */
|
|
220
|
-
readonly prerequisites: readonly FixerPrerequisite[];
|
|
221
210
|
};
|
|
222
211
|
|
|
223
212
|
export type AdmittedCollectorInvocation = AdmittedRoleInvocationBase & {
|
|
@@ -622,15 +611,13 @@ export async function relocateAdmittedRunToTicket(
|
|
|
622
611
|
admittedRecord,
|
|
623
612
|
[
|
|
624
613
|
"runDirectory",
|
|
625
|
-
"taskPath",
|
|
626
|
-
"packetPath",
|
|
627
|
-
"prerequisitesPath",
|
|
628
614
|
"mergerInputPath",
|
|
629
615
|
],
|
|
630
616
|
oldRunDirectory,
|
|
631
617
|
target.runDirectory,
|
|
632
618
|
);
|
|
633
|
-
// #1165: caller
|
|
619
|
+
// #1165/#1168: caller file-flag paths stay as given. Obsolete copy fields
|
|
620
|
+
// (taskPath/packetPath) are not rewritten — stock volumes keep their bytes.
|
|
634
621
|
(admitted as { principal: DurablePrincipal }).principal = principal;
|
|
635
622
|
|
|
636
623
|
// current.json projects host.original from this run directory. Ownership is
|
|
@@ -876,7 +863,8 @@ function assignPublicSeatOption(
|
|
|
876
863
|
fields.authorityRefs.push(requireAuthorityRef(value));
|
|
877
864
|
return;
|
|
878
865
|
case "prerequisites":
|
|
879
|
-
|
|
866
|
+
// #1168: same opaque file-flag rule as --attach.
|
|
867
|
+
fields.prerequisitesPath = requireProvidedOptionValue(taken.def.canonical, value);
|
|
880
868
|
return;
|
|
881
869
|
case "pr":
|
|
882
870
|
fields.prNumber = parsePositivePrOption(value);
|
|
@@ -1324,16 +1312,13 @@ export async function admitPublicRole(
|
|
|
1324
1312
|
if (!record.phases.some((item) => item === phase)) {
|
|
1325
1313
|
throw new CliUsageError("coder phase must be plan or apply");
|
|
1326
1314
|
}
|
|
1315
|
+
// #1168: dispatch text is the first message only — no task.md copy.
|
|
1327
1316
|
return admitStandardMaterialInvocation("coder", {
|
|
1328
1317
|
...shared,
|
|
1329
1318
|
instruction,
|
|
1330
1319
|
attachmentPaths,
|
|
1331
1320
|
...project,
|
|
1332
|
-
placedFields: async (
|
|
1333
|
-
const taskPath = join(placed.runDirectory, "task.md");
|
|
1334
|
-
await writeFile(taskPath, instruction, "utf8");
|
|
1335
|
-
return { phase, taskPath };
|
|
1336
|
-
},
|
|
1321
|
+
placedFields: async () => ({ phase }),
|
|
1337
1322
|
});
|
|
1338
1323
|
}
|
|
1339
1324
|
case "worker-packet": {
|
|
@@ -1344,53 +1329,18 @@ export async function admitPublicRole(
|
|
|
1344
1329
|
if (!record.phases.some((item) => item === phase)) {
|
|
1345
1330
|
throw new CliUsageError("fixer phase must be plan or apply");
|
|
1346
1331
|
}
|
|
1347
|
-
|
|
1348
|
-
let prerequisitesSource: string | undefined;
|
|
1349
|
-
if (parsed.prerequisitesPath !== undefined) {
|
|
1350
|
-
const absolutePrereq = isAbsolute(parsed.prerequisitesPath)
|
|
1351
|
-
? parsed.prerequisitesPath
|
|
1352
|
-
: resolve(parsed.prerequisitesPath);
|
|
1353
|
-
try {
|
|
1354
|
-
prerequisitesSource = await readFile(absolutePrereq, "utf8");
|
|
1355
|
-
} catch (error) {
|
|
1356
|
-
throw new CliUsageError(
|
|
1357
|
-
`fixer prerequisites path is unreadable: ${parsed.prerequisitesPath}`,
|
|
1358
|
-
{ cause: error },
|
|
1359
|
-
);
|
|
1360
|
-
}
|
|
1361
|
-
try {
|
|
1362
|
-
prerequisites = parseFixerPrerequisites(prerequisitesSource);
|
|
1363
|
-
} catch (error) {
|
|
1364
|
-
if (error instanceof FixerPacketValidationError) {
|
|
1365
|
-
throw new CliUsageError(error.message, { cause: error });
|
|
1366
|
-
}
|
|
1367
|
-
throw error;
|
|
1368
|
-
}
|
|
1369
|
-
}
|
|
1332
|
+
// #1168: dispatch once as first message; --prerequisites path as-is.
|
|
1370
1333
|
return admitStandardMaterialInvocation("fixer", {
|
|
1371
1334
|
...shared,
|
|
1372
1335
|
instruction,
|
|
1373
1336
|
attachmentPaths,
|
|
1374
1337
|
...project,
|
|
1375
|
-
placedFields: async (
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
`${JSON.stringify(prerequisites, null, 2)}\n`,
|
|
1382
|
-
"utf8",
|
|
1383
|
-
);
|
|
1384
|
-
}
|
|
1385
|
-
const packetPath = join(placed.runDirectory, "fix-packet.md");
|
|
1386
|
-
await writeFile(packetPath, instruction, "utf8");
|
|
1387
|
-
return {
|
|
1388
|
-
phase,
|
|
1389
|
-
packetPath,
|
|
1390
|
-
prerequisites,
|
|
1391
|
-
...(prerequisitesPath === undefined ? {} : { prerequisitesPath }),
|
|
1392
|
-
};
|
|
1393
|
-
},
|
|
1338
|
+
placedFields: async () => ({
|
|
1339
|
+
phase,
|
|
1340
|
+
...(parsed.prerequisitesPath === undefined
|
|
1341
|
+
? {}
|
|
1342
|
+
: { prerequisitesPath: parsed.prerequisitesPath }),
|
|
1343
|
+
}),
|
|
1394
1344
|
});
|
|
1395
1345
|
}
|
|
1396
1346
|
case "collect-target": {
|
|
@@ -1579,13 +1529,12 @@ export async function admitPublicRole(
|
|
|
1579
1529
|
placedFields: async (placed) => {
|
|
1580
1530
|
const targetLabel = derived.targetObjectId === "" ? "(none observed)" : derived.targetObjectId;
|
|
1581
1531
|
const sourceLabel = derived.sourceObjectId === "" ? "(none observed)" : derived.sourceObjectId;
|
|
1532
|
+
// #1168: git facts stay; do not encode dispatch text as task/authority copies.
|
|
1582
1533
|
const mergerInput = validateMergerInput({
|
|
1583
1534
|
attemptId: placed.runId,
|
|
1584
1535
|
targetObjectId: derived.targetObjectId,
|
|
1585
1536
|
sourceObjectId: derived.sourceObjectId,
|
|
1586
1537
|
materials: {
|
|
1587
|
-
task: mergerMaterialFromUtf8(instruction),
|
|
1588
|
-
authority: mergerMaterialFromUtf8(instruction),
|
|
1589
1538
|
targetIntent: mergerMaterialFromUtf8(
|
|
1590
1539
|
`Investigate primary sources for target parent ${targetLabel}. Do not invent intent.`,
|
|
1591
1540
|
),
|
|
@@ -1767,7 +1716,7 @@ async function persistPlacedAdmission(
|
|
|
1767
1716
|
* before materializeCountersignInvocation writes the page.
|
|
1768
1717
|
* Seats whose extra facts are known before placement pass them as admittedFields.
|
|
1769
1718
|
* Seats whose extra facts depend on the placed run pass placedFields
|
|
1770
|
-
* (
|
|
1719
|
+
* (merger writes merger-input.json with git facts; coder/fixer dispatch is first-message only, #1168).
|
|
1771
1720
|
*/
|
|
1772
1721
|
async function admitStandardMaterialInvocation<
|
|
1773
1722
|
R extends PackagedRole,
|
|
@@ -1849,9 +1798,10 @@ export type AdmitAuditorInvocationOptions = AdmitInspectorInvocationOptions;
|
|
|
1849
1798
|
type InstructionTransportSource = {
|
|
1850
1799
|
readonly role?: string;
|
|
1851
1800
|
readonly instruction: string;
|
|
1852
|
-
readonly instructionEmpty
|
|
1801
|
+
readonly instructionEmpty?: boolean;
|
|
1853
1802
|
readonly attachments: readonly { readonly path: string }[];
|
|
1854
1803
|
readonly requestManifestPath?: string;
|
|
1804
|
+
readonly prerequisitesPath?: string;
|
|
1855
1805
|
readonly baseRevision?: string;
|
|
1856
1806
|
readonly lens?: ReviewerLens;
|
|
1857
1807
|
readonly authorityRefs?: readonly string[];
|
|
@@ -1913,14 +1863,17 @@ export function buildInstructionTransportPrompt(
|
|
|
1913
1863
|
}
|
|
1914
1864
|
return lines.join("\n");
|
|
1915
1865
|
}
|
|
1916
|
-
// #1165 J3: assemble from the admitted instruction bytes themselves.
|
|
1866
|
+
// #1165 J3 / #1168: assemble from the admitted instruction bytes themselves.
|
|
1917
1867
|
const lines: string[] = [admitted.instruction];
|
|
1918
|
-
// #1164/#1165: each caller path keeps its file-flag provenance.
|
|
1868
|
+
// #1164/#1165/#1168: each caller path keeps its file-flag provenance.
|
|
1919
1869
|
const flaggedPaths: string[] = [
|
|
1920
1870
|
...admitted.attachments.map((attachment) => `--attach ${attachment.path}`),
|
|
1921
1871
|
...(admitted.requestManifestPath === undefined
|
|
1922
1872
|
? []
|
|
1923
1873
|
: [`--request-manifest ${admitted.requestManifestPath}`]),
|
|
1874
|
+
...(admitted.prerequisitesPath === undefined
|
|
1875
|
+
? []
|
|
1876
|
+
: [`--prerequisites ${admitted.prerequisitesPath}`]),
|
|
1924
1877
|
];
|
|
1925
1878
|
if (flaggedPaths.length > 0) {
|
|
1926
1879
|
lines.push("");
|
|
@@ -2022,7 +1975,7 @@ export type AdmitFixerInvocationOptions = {
|
|
|
2022
1975
|
phase: FixerPhase;
|
|
2023
1976
|
instruction: string;
|
|
2024
1977
|
attachmentPaths: readonly string[];
|
|
2025
|
-
/** Optional caller path
|
|
1978
|
+
/** Optional caller --prerequisites path as-is (#1168). */
|
|
2026
1979
|
prerequisitesPath?: string;
|
|
2027
1980
|
project?: string;
|
|
2028
1981
|
createRunId?: () => string;
|
|
@@ -2198,7 +2151,7 @@ export function buildReviewerSkillArgProjection(
|
|
|
2198
2151
|
].join(" ");
|
|
2199
2152
|
}
|
|
2200
2153
|
|
|
2201
|
-
function mergerMaterialFromUtf8(text: string): MergerInput["materials"]["
|
|
2154
|
+
function mergerMaterialFromUtf8(text: string): MergerInput["materials"]["targetIntent"] {
|
|
2202
2155
|
const bytes = Buffer.from(text, "utf8");
|
|
2203
2156
|
return Object.freeze({
|
|
2204
2157
|
bytesBase64: bytes.toString("base64"),
|
|
@@ -463,8 +463,8 @@ const FIXER_OPTIONS = [
|
|
|
463
463
|
repeatable: false,
|
|
464
464
|
form: "option",
|
|
465
465
|
description: {
|
|
466
|
-
en: "
|
|
467
|
-
zh: "
|
|
466
|
+
en: "Caller prerequisites path passed as-is to the role. Package does not read, copy, or validate; use an absolute path when cwd differs from --project.",
|
|
467
|
+
zh: "调用方前置条件文件路径原样递给衙门。包不读、不复制、不校验;调用方当前目录与 --project 不同时请给绝对路径。",
|
|
468
468
|
},
|
|
469
469
|
},
|
|
470
470
|
] as const satisfies readonly PublicOptionDefinition[];
|
|
@@ -132,11 +132,11 @@ function projectRelocatedTurnIdentity(
|
|
|
132
132
|
mutableRequest.principal = admitted.principal;
|
|
133
133
|
const activation = mutableRequest.activation;
|
|
134
134
|
if (isRecord(activation)) {
|
|
135
|
-
for (const field of ["
|
|
135
|
+
for (const field of ["inputPath"] as const) {
|
|
136
136
|
const record = activation as Record<string, unknown>;
|
|
137
137
|
if (field in record) record[field] = rewrite(record[field]);
|
|
138
138
|
}
|
|
139
|
-
// #1165:
|
|
139
|
+
// #1165/#1168: caller file-flag paths are not activation fields to rewrite.
|
|
140
140
|
}
|
|
141
141
|
if (result.terminal !== undefined) {
|
|
142
142
|
for (const artifact of result.terminal.artifacts) {
|
|
@@ -20,7 +20,6 @@ import { findRoleRunDirectory, listBookRunDirectories, parseRunLeaf, sessionFile
|
|
|
20
20
|
import { isSafePositiveTicketNumber } from "../run-ticket-number.ts";
|
|
21
21
|
import { CliUsageError } from "./cli-errors.ts";
|
|
22
22
|
import type { FixerPhase } from "../package-contracts/fixer-output.ts";
|
|
23
|
-
import type { FixerPrerequisite } from "../package-contracts/fixer-packet.ts";
|
|
24
23
|
import { parseCollectorRepository } from "../collector-config.ts";
|
|
25
24
|
import type { DoctorCaseIdentity } from "../doctor-contracts.ts";
|
|
26
25
|
import type { NotarySourceRunLocator } from "../notary-contracts.ts";
|
|
@@ -992,10 +991,7 @@ type LoadedAdmittedRequestFields = {
|
|
|
992
991
|
readonly instructionEmpty: boolean;
|
|
993
992
|
readonly attachments: FrozenAttachment[];
|
|
994
993
|
readonly phase?: CoderPhase | FixerPhase;
|
|
995
|
-
readonly taskPath?: string;
|
|
996
|
-
readonly packetPath?: string;
|
|
997
994
|
readonly prerequisitesPath?: string;
|
|
998
|
-
readonly prerequisites?: readonly FixerPrerequisite[];
|
|
999
995
|
readonly baseRevision?: string;
|
|
1000
996
|
readonly lens?: ReviewerLens;
|
|
1001
997
|
readonly authorityRefs?: readonly string[];
|
|
@@ -1081,10 +1077,7 @@ async function loadResumableRunRecord(
|
|
|
1081
1077
|
let instructionEmpty = true;
|
|
1082
1078
|
let attachments: FrozenAttachment[] = [];
|
|
1083
1079
|
let phase: CoderPhase | FixerPhase | undefined;
|
|
1084
|
-
let taskPath: string | undefined;
|
|
1085
|
-
let packetPath: string | undefined;
|
|
1086
1080
|
let prerequisitesPath: string | undefined;
|
|
1087
|
-
let prerequisites: readonly FixerPrerequisite[] | undefined;
|
|
1088
1081
|
let baseRevision: string | undefined;
|
|
1089
1082
|
let lens: ReviewerLens | undefined;
|
|
1090
1083
|
let authorityRefs: readonly string[] | undefined;
|
|
@@ -1128,21 +1121,10 @@ async function loadResumableRunRecord(
|
|
|
1128
1121
|
if (record.phase === "plan" || record.phase === "apply") {
|
|
1129
1122
|
phase = record.phase;
|
|
1130
1123
|
}
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
}
|
|
1134
|
-
if (typeof record.packetPath === "string" && record.packetPath.trim() !== "") {
|
|
1135
|
-
packetPath = record.packetPath;
|
|
1136
|
-
}
|
|
1137
|
-
if (
|
|
1138
|
-
typeof record.prerequisitesPath === "string" &&
|
|
1139
|
-
record.prerequisitesPath.trim() !== ""
|
|
1140
|
-
) {
|
|
1124
|
+
// #1168: opaque caller path on resume — do not trim-filter provided values.
|
|
1125
|
+
if (typeof record.prerequisitesPath === "string") {
|
|
1141
1126
|
prerequisitesPath = record.prerequisitesPath;
|
|
1142
1127
|
}
|
|
1143
|
-
if (Array.isArray(record.prerequisites)) {
|
|
1144
|
-
prerequisites = record.prerequisites as FixerPrerequisite[];
|
|
1145
|
-
}
|
|
1146
1128
|
if (
|
|
1147
1129
|
typeof record.baseRevision === "string" &&
|
|
1148
1130
|
record.baseRevision.trim() !== ""
|
|
@@ -1319,10 +1301,7 @@ async function loadResumableRunRecord(
|
|
|
1319
1301
|
instructionEmpty,
|
|
1320
1302
|
attachments,
|
|
1321
1303
|
...(phase === undefined ? {} : { phase }),
|
|
1322
|
-
...(taskPath === undefined ? {} : { taskPath }),
|
|
1323
|
-
...(packetPath === undefined ? {} : { packetPath }),
|
|
1324
1304
|
...(prerequisitesPath === undefined ? {} : { prerequisitesPath }),
|
|
1325
|
-
...(prerequisites === undefined ? {} : { prerequisites }),
|
|
1326
1305
|
...(baseRevision === undefined ? {} : { baseRevision }),
|
|
1327
1306
|
...(lens === undefined ? {} : { lens }),
|
|
1328
1307
|
...(authorityRefs === undefined ? {} : { authorityRefs }),
|
|
@@ -1453,12 +1432,6 @@ function admitResumedRole(loaded: {
|
|
|
1453
1432
|
}
|
|
1454
1433
|
case "worker-task": {
|
|
1455
1434
|
const phase = resumedWorkerPhase(fields.phase ?? loaded.run.phase, record.phases, role, runId);
|
|
1456
|
-
const taskPath = fields.taskPath;
|
|
1457
|
-
if (taskPath === undefined) {
|
|
1458
|
-
throw new CliUsageError(
|
|
1459
|
-
`role run admitted coder task path is missing: ${runId}`,
|
|
1460
|
-
);
|
|
1461
|
-
}
|
|
1462
1435
|
if (fields.instruction.trim() === "") {
|
|
1463
1436
|
throw new CliUsageError(
|
|
1464
1437
|
`role run admitted coder task is blank: ${runId}`,
|
|
@@ -1469,34 +1442,24 @@ function admitResumedRole(loaded: {
|
|
|
1469
1442
|
phase,
|
|
1470
1443
|
...base,
|
|
1471
1444
|
instructionEmpty: false,
|
|
1472
|
-
taskPath,
|
|
1473
1445
|
};
|
|
1474
1446
|
return admitted;
|
|
1475
1447
|
}
|
|
1476
1448
|
case "worker-packet": {
|
|
1477
1449
|
const phase = resumedWorkerPhase(fields.phase ?? loaded.run.phase, record.phases, role, runId);
|
|
1478
|
-
const packetPath = fields.packetPath;
|
|
1479
|
-
if (packetPath === undefined) {
|
|
1480
|
-
throw new CliUsageError(
|
|
1481
|
-
`role run admitted fixer packet path is missing: ${runId}`,
|
|
1482
|
-
);
|
|
1483
|
-
}
|
|
1484
1450
|
if (fields.instruction.trim() === "") {
|
|
1485
1451
|
throw new CliUsageError(
|
|
1486
1452
|
`role run admitted fixer instruction is blank: ${runId}`,
|
|
1487
1453
|
);
|
|
1488
1454
|
}
|
|
1489
|
-
const prerequisites = fields.prerequisites ?? Object.freeze([]);
|
|
1490
1455
|
const admitted: AdmittedFixerInvocation = {
|
|
1491
1456
|
role: "fixer",
|
|
1492
1457
|
phase,
|
|
1493
1458
|
...base,
|
|
1494
1459
|
instructionEmpty: false,
|
|
1495
|
-
packetPath,
|
|
1496
1460
|
...(fields.prerequisitesPath === undefined
|
|
1497
1461
|
? {}
|
|
1498
1462
|
: { prerequisitesPath: fields.prerequisitesPath }),
|
|
1499
|
-
prerequisites,
|
|
1500
1463
|
};
|
|
1501
1464
|
return admitted;
|
|
1502
1465
|
}
|
|
@@ -23,10 +23,9 @@ const ADMITTED_PAGE_FIELDS = [
|
|
|
23
23
|
"admittedRequestPath", // pre-#1161 pages only
|
|
24
24
|
"sessionDirectory",
|
|
25
25
|
"sessionFile",
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// #1165: requestManifestPath is a caller path — never rewrite.
|
|
26
|
+
// #1165/#1168: caller file-flag paths (requestManifestPath, prerequisitesPath)
|
|
27
|
+
// stay as given. Obsolete copy fields (taskPath/packetPath) are not rewritten —
|
|
28
|
+
// stock volumes keep their bytes; live relocate no longer maintains them.
|
|
30
29
|
"mergerInputPath",
|
|
31
30
|
"sourceRunPath",
|
|
32
31
|
] as const;
|