@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.
@@ -45,8 +45,6 @@ export function createRoleRuntimeDependencies(packageRoot: string): RoleRuntimeD
45
45
  packageRoot,
46
46
  loadRoleReferenceMaterials: loadPackagedRoleReferenceMaterials,
47
47
  loadRoleSoul: loadRegisteredRoleSoul,
48
- loadFixPacket: (path) => readFile(path, "utf8"),
49
- loadCoderTask: (path) => readFile(path, "utf8"),
50
48
  loadDoctorCase,
51
49
  loadNotarySourceRun: loadNotarySourceRunLocator,
52
50
  loadMergerInput: async (path) => JSON.parse(await readFile(path, "utf8")),
@@ -346,8 +346,6 @@ export {
346
346
  } from "./worker-role.ts";
347
347
  export { fixerOutputSchema, validateFixerOutput } from "./package-contracts/fixer-output.ts";
348
348
  export type { FixerBlocker, FixerClassResult, FixerPhase, FixerTestEvidence } from "./package-contracts/fixer-output.ts";
349
- export { fixerPrerequisiteSchema, fixerPrerequisitesSchema, parseFixerPrerequisites, validateFixerPrerequisites } from "./package-contracts/fixer-packet.ts";
350
- export type { FixerInvocationInput, FixerPrerequisite } from "./package-contracts/fixer-packet.ts";
351
349
  export {
352
350
  AUDITOR_SOUL_ROLES,
353
351
  AK_ROLE_AUDITOR_SUBJECT_ENV,
@@ -460,8 +458,6 @@ export type RoleRuntimeDependencies = {
460
458
  loadRoleReferenceMaterials?(role: PackagedRole): Promise<string>;
461
459
  /** One soul loader. The role argument selects the registry record. */
462
460
  loadRoleSoul(role: PackagedRole): Promise<string>;
463
- loadFixPacket?(path: string): Promise<string>;
464
- loadCoderTask?(path: string): Promise<string>;
465
461
  loadNotarySourceRun?(path: string): Promise<import("./notary-contracts.ts").NotarySourceRunLocator>;
466
462
  loadDoctorCase?(path: string): Promise<import("./doctor-contracts.ts").DoctorCase>;
467
463
  loadMergerInput?(path: string): Promise<unknown>;
@@ -1459,12 +1455,6 @@ export function createRoleRuntimeExtension(
1459
1455
  roleHost,
1460
1456
  {
1461
1457
  loadSoul: () => requireRoleSoul("fixer"),
1462
- async loadPacket(path) {
1463
- if (dependencies.loadFixPacket === undefined) {
1464
- throw new Error("Fixer packet loader is not configured");
1465
- }
1466
- return dependencies.loadFixPacket(path);
1467
- },
1468
1458
  },
1469
1459
  hostActions,
1470
1460
  { unfinishedReasonBounceLimit: deliveryLimit },
@@ -1473,12 +1463,6 @@ export function createRoleRuntimeExtension(
1473
1463
  roleHost,
1474
1464
  {
1475
1465
  loadSoul: () => requireRoleSoul("coder"),
1476
- async loadTask(path) {
1477
- if (dependencies.loadCoderTask === undefined) {
1478
- throw new Error("Coder task loader is not configured");
1479
- }
1480
- return dependencies.loadCoderTask(path);
1481
- },
1482
1466
  },
1483
1467
  hostActions,
1484
1468
  { unfinishedReasonBounceLimit: deliveryLimit },
@@ -10,11 +10,6 @@ import {
10
10
  import { validateFixerOutput, type FixerPhase } from "./package-contracts/fixer-output.ts";
11
11
  import { registerFiledSubmissionTool } from "./filed-submission.ts";
12
12
  import { roleSubmissionDeclaration } from "./role-submission-declarations.ts";
13
- import {
14
- FixerPacketValidationError,
15
- parseFixerPrerequisites,
16
- type FixerInvocationInput,
17
- } from "./package-contracts/fixer-packet.ts";
18
13
  import {
19
14
  createWorkerSubmissionGate,
20
15
  WorkerCommitReminderError,
@@ -37,21 +32,8 @@ export {
37
32
  validateAcceptedWorkerDetails,
38
33
  } from "./package-contracts/worker-output.ts";
39
34
  export type { WorkerOutput, FixerOutput, CoderOutput };
35
+ /** #1168: phase only — dispatch text is the first message, not a packet flag. */
40
36
  export const FIXER_FLAG_DEFINITIONS = {
41
- packet: {
42
- name: "ak-fix-packet",
43
- definition: {
44
- description: "Path to opaque prose instructions for the Fixer",
45
- type: "string" as const,
46
- },
47
- },
48
- prerequisites: {
49
- name: "ak-fixer-prerequisites",
50
- definition: {
51
- description: "Optional path to a JSON array of typed Fixer prerequisites",
52
- type: "string" as const,
53
- },
54
- },
55
37
  phase: {
56
38
  name: "ak-fixer-phase",
57
39
  definition: {
@@ -73,12 +55,10 @@ export type WorkerRoleHostActions = HostGatekeeperActions;
73
55
 
74
56
  export type FixerRoleDependencies = {
75
57
  loadSoul(): Promise<string>;
76
- loadPacket(path: string): Promise<string>;
77
58
  };
78
59
 
79
60
  export type CoderRoleDependencies = {
80
61
  loadSoul(): Promise<string>;
81
- loadTask(path: string): Promise<string>;
82
62
  };
83
63
 
84
64
  export type WorkerRoleRuntime = {
@@ -178,9 +158,6 @@ export function createFixerRoleRuntime(
178
158
  options?: { readonly unfinishedReasonBounceLimit?: number },
179
159
  ): WorkerRoleRuntime {
180
160
  let soul: string | undefined;
181
- let packet: FixerInvocationInput | undefined;
182
- let packetPath: string | undefined;
183
- let prerequisitesPath: string | undefined;
184
161
  let phase: WorkerPhase | undefined;
185
162
  let lifecycleRegistered = false;
186
163
  // #1132: ADR 0050 缺理由催全次数. The in-process seam passes the value it
@@ -190,14 +167,6 @@ export function createFixerRoleRuntime(
190
167
  ?? deliveryLimitFromEnv(process.env),
191
168
  });
192
169
 
193
- pi.registerFlag(
194
- FIXER_FLAG_DEFINITIONS.packet.name,
195
- FIXER_FLAG_DEFINITIONS.packet.definition,
196
- );
197
- pi.registerFlag(
198
- FIXER_FLAG_DEFINITIONS.prerequisites.name,
199
- FIXER_FLAG_DEFINITIONS.prerequisites.definition,
200
- );
201
170
  pi.registerFlag(
202
171
  FIXER_FLAG_DEFINITIONS.phase.name,
203
172
  FIXER_FLAG_DEFINITIONS.phase.definition,
@@ -214,33 +183,12 @@ export function createFixerRoleRuntime(
214
183
  );
215
184
  }
216
185
  phase = selectedPhase;
217
- const resolvedPacketPath = pi.getFlag(FIXER_FLAG_DEFINITIONS.packet.name);
218
- if (typeof resolvedPacketPath !== "string" || resolvedPacketPath.trim().length === 0) {
219
- throw new Error("Fixer role requires --ak-fix-packet");
220
- }
221
- packetPath = resolvedPacketPath;
222
- const instructions = await dependencies.loadPacket(packetPath);
223
- if (instructions.trim().length === 0) {
224
- throw new FixerPacketValidationError(
225
- new Error("Fixer instructions must be nonblank"),
226
- );
227
- }
228
- const resolvedPrerequisitesPath = pi.getFlag(FIXER_FLAG_DEFINITIONS.prerequisites.name);
229
- if (resolvedPrerequisitesPath !== undefined && (typeof resolvedPrerequisitesPath !== "string" || resolvedPrerequisitesPath.trim().length === 0)) {
230
- throw new Error("Fixer --ak-fixer-prerequisites path must be nonblank when supplied");
231
- }
232
- prerequisitesPath =
233
- typeof resolvedPrerequisitesPath === "string" ? resolvedPrerequisitesPath : undefined;
234
- const prerequisites = prerequisitesPath !== undefined
235
- ? parseFixerPrerequisites(await dependencies.loadPacket(prerequisitesPath))
236
- : Object.freeze([]);
237
- packet = Object.freeze({ instructions, prerequisites });
238
186
 
239
187
  if (!lifecycleRegistered) {
240
188
  lifecycleRegistered = true;
241
189
  registerWorkerSubmission(pi, "fixer", {
242
- notReady: "修内司修理包与阶段未装载",
243
- ready: () => packet !== undefined && phase !== undefined,
190
+ notReady: "修内司阶段未装载",
191
+ ready: () => phase !== undefined,
244
192
  phase: () => phase,
245
193
  project: (parameters, current) => deepFreeze(validateFixerOutput(parameters, current)),
246
194
  submissionGate,
@@ -257,17 +205,12 @@ export function createFixerRoleRuntime(
257
205
  reason: fixerBashSeatbeltDenyReason(matched),
258
206
  };
259
207
  });
208
+ // #1168: soul + phase only; dispatch text is the first message.
260
209
  pi.on("before_agent_start", (event) => {
261
210
  if (soul === undefined) throw new Error("修内司职分未装载");
262
- if (packetPath === undefined) throw new Error("修内司修理包路径未装载");
263
- // Path delivery only — body is self-fetched; no inline duplicate of flag bytes (#632).
264
- const prerequisitesBlock =
265
- prerequisitesPath === undefined
266
- ? ""
267
- : `\n\n<fixer_prerequisites_path>\n${prerequisitesPath}\n</fixer_prerequisites_path>`;
268
211
  return {
269
212
  systemPrompt:
270
- `${event.systemPrompt}\n\n<fixer_soul>\n${soul}\n</fixer_soul>\n\n<fixer_phase>\n${phase ?? ""}\n</fixer_phase>\n\n<fix_packet_path>\n${packetPath}\n</fix_packet_path>${prerequisitesBlock}`,
213
+ `${event.systemPrompt}\n\n<fixer_soul>\n${soul}\n</fixer_soul>\n\n<fixer_phase>\n${phase ?? ""}\n</fixer_phase>`,
271
214
  };
272
215
  });
273
216
  }
@@ -285,7 +228,6 @@ export function createCoderRoleRuntime(
285
228
  options?: { readonly unfinishedReasonBounceLimit?: number },
286
229
  ): WorkerRoleRuntime {
287
230
  let soul: string | undefined;
288
- let task: string | undefined;
289
231
  let phase: WorkerPhase | undefined;
290
232
  let lifecycleRegistered = false;
291
233
  // #1132: same resolved ceiling as the fixer gate. Absent = Pi child env.
@@ -294,10 +236,6 @@ export function createCoderRoleRuntime(
294
236
  ?? deliveryLimitFromEnv(process.env),
295
237
  });
296
238
 
297
- pi.registerFlag("ak-coder-task", {
298
- description: "Markdown task assigned to the coder role",
299
- type: "string",
300
- });
301
239
  pi.registerFlag("ak-coder-phase", {
302
240
  description:
303
241
  "Coder phase: plan (inspect and propose an implementation plan; no edits or commits) or apply (execute the approved plan and verify the first implementation)",
@@ -305,7 +243,7 @@ export function createCoderRoleRuntime(
305
243
  });
306
244
 
307
245
  return {
308
- async activate(ctx) {
246
+ async activate() {
309
247
  soul = (await dependencies.loadSoul()).trim();
310
248
  if (soul.length === 0) throw new Error("Coder soul is empty");
311
249
  const selectedPhase = pi.getFlag("ak-coder-phase");
@@ -315,28 +253,23 @@ export function createCoderRoleRuntime(
315
253
  );
316
254
  }
317
255
  phase = selectedPhase;
318
- const taskPath = pi.getFlag("ak-coder-task");
319
- if (typeof taskPath !== "string" || taskPath.trim().length === 0) {
320
- throw new Error("Coder role requires --ak-coder-task");
321
- }
322
- task = (await dependencies.loadTask(taskPath)).trim();
323
- if (task.length === 0) throw new Error("Coder task is empty");
324
256
 
325
257
  if (!lifecycleRegistered) {
326
258
  lifecycleRegistered = true;
327
259
  registerWorkerSubmission(pi, "coder", {
328
- notReady: "将作监任务与阶段未装载",
329
- ready: () => task !== undefined && phase !== undefined,
260
+ notReady: "将作监阶段未装载",
261
+ ready: () => phase !== undefined,
330
262
  phase: () => phase,
331
263
  project: (parameters, current) => validateWorkerOutput(parameters, current, "Coder"),
332
264
  submissionGate,
333
265
  hostActions,
334
266
  });
335
- pi.on("before_agent_start", (event, ctx) => {
267
+ // #1168: soul + phase only; dispatch text is the first message.
268
+ pi.on("before_agent_start", (event) => {
336
269
  if (soul === undefined) throw new Error("将作监职分未装载");
337
270
  return {
338
271
  systemPrompt:
339
- `${event.systemPrompt}\n\n<coder_soul>\n${soul}\n</coder_soul>\n\n<coder_phase>\n${phase ?? ""}\n</coder_phase>\n\n<coder_task>\n${task ?? ""}\n</coder_task>`,
272
+ `${event.systemPrompt}\n\n<coder_soul>\n${soul}\n</coder_soul>\n\n<coder_phase>\n${phase ?? ""}\n</coder_phase>`,
340
273
  };
341
274
  });
342
275
  }
@@ -1,77 +0,0 @@
1
- import { Type } from "typebox";
2
- import { Value } from "typebox/value";
3
- import { isRecord } from "../unknown-value.js";
4
- const FIXER_PREREQUISITE_ID_PATTERN = "^[A-Za-z0-9][A-Za-z0-9._-]*$";
5
- const fixerPrerequisiteSchema = Type.Object({
6
- id: Type.String({ pattern: FIXER_PREREQUISITE_ID_PATTERN }),
7
- requirement: Type.String({ pattern: "\\S" })
8
- });
9
- const fixerPrerequisitesSchema = Type.Array(fixerPrerequisiteSchema);
10
- function causeMessage(cause) {
11
- if (cause instanceof Error) return cause.message;
12
- if (typeof cause === "string") return cause;
13
- try {
14
- return JSON.stringify(cause) ?? String(cause);
15
- } catch {
16
- return String(cause);
17
- }
18
- }
19
- class FixerPacketValidationError extends Error {
20
- code = "AK_INVALID_FIX_PACKET";
21
- constructor(cause) {
22
- const prefix = "Fixer prerequisites or instructions violate the invocation contract";
23
- super(
24
- cause === void 0 ? prefix : `${prefix}: ${causeMessage(cause)}`,
25
- cause === void 0 ? void 0 : { cause }
26
- );
27
- this.name = "FixerPacketValidationError";
28
- }
29
- }
30
- function fail(cause) {
31
- throw new FixerPacketValidationError(cause);
32
- }
33
- function parseFailure(value) {
34
- if (!Array.isArray(value)) fail(new Error("Fixer prerequisites must be a JSON array"));
35
- for (const entry of value) {
36
- if (!isRecord(entry)) {
37
- fail(new Error("Fixer prerequisite entry must be an object with id and requirement fields"));
38
- }
39
- if (typeof entry.id !== "string" || !new RegExp(FIXER_PREREQUISITE_ID_PATTERN).test(entry.id)) {
40
- fail(new Error(`Fixer prerequisite id violates pattern ${FIXER_PREREQUISITE_ID_PATTERN}`));
41
- }
42
- if (typeof entry.requirement !== "string" || !/\S/.test(entry.requirement)) {
43
- fail(new Error("Fixer prerequisite requirement must be nonblank"));
44
- }
45
- }
46
- fail(new Error("Fixer prerequisites violate the attachment schema"));
47
- }
48
- function validateFixerPrerequisites(value) {
49
- if (!Value.Check(fixerPrerequisitesSchema, value)) parseFailure(value);
50
- const entries = value;
51
- const ids = /* @__PURE__ */ new Set();
52
- const prerequisites = entries.map((entry) => {
53
- if (ids.has(entry.id)) {
54
- fail(new Error(`Fixer prerequisites contain duplicate id: ${entry.id}`));
55
- }
56
- ids.add(entry.id);
57
- return Object.freeze({ id: entry.id, requirement: entry.requirement });
58
- });
59
- return Object.freeze(prerequisites);
60
- }
61
- function parseFixerPrerequisites(source) {
62
- let decoded;
63
- try {
64
- decoded = JSON.parse(source);
65
- } catch (error) {
66
- fail(error);
67
- }
68
- return validateFixerPrerequisites(decoded);
69
- }
70
- export {
71
- FIXER_PREREQUISITE_ID_PATTERN,
72
- FixerPacketValidationError,
73
- fixerPrerequisiteSchema,
74
- fixerPrerequisitesSchema,
75
- parseFixerPrerequisites,
76
- validateFixerPrerequisites
77
- };
@@ -1,6 +0,0 @@
1
- [
2
- {
3
- "id": "owner.choice",
4
- "requirement": "The controlling owner decision required before this repair exists."
5
- }
6
- ]
@@ -1,91 +0,0 @@
1
- import { Type, type Static } from "typebox";
2
- import { Value } from "typebox/value";
3
-
4
- import { isRecord } from "../unknown-value.ts";
5
-
6
- export const FIXER_PREREQUISITE_ID_PATTERN = "^[A-Za-z0-9][A-Za-z0-9._-]*$";
7
-
8
- export const fixerPrerequisiteSchema = Type.Object({
9
- id: Type.String({ pattern: FIXER_PREREQUISITE_ID_PATTERN }),
10
- requirement: Type.String({ pattern: "\\S" }),
11
- });
12
-
13
- export const fixerPrerequisitesSchema = Type.Array(fixerPrerequisiteSchema);
14
- export type FixerPrerequisite = Readonly<Static<typeof fixerPrerequisiteSchema>>;
15
- export type FixerInvocationInput = Readonly<{
16
- instructions: string;
17
- prerequisites: readonly FixerPrerequisite[];
18
- }>;
19
-
20
- function causeMessage(cause: unknown): string {
21
- if (cause instanceof Error) return cause.message;
22
- if (typeof cause === "string") return cause;
23
- try {
24
- return JSON.stringify(cause) ?? String(cause);
25
- } catch {
26
- return String(cause);
27
- }
28
- }
29
-
30
- export class FixerPacketValidationError extends Error {
31
- readonly code = "AK_INVALID_FIX_PACKET";
32
-
33
- constructor(cause?: unknown) {
34
- const prefix = "Fixer prerequisites or instructions violate the invocation contract";
35
- super(
36
- cause === undefined ? prefix : `${prefix}: ${causeMessage(cause)}`,
37
- cause === undefined ? undefined : { cause },
38
- );
39
- this.name = "FixerPacketValidationError";
40
- }
41
- }
42
-
43
- function fail(cause: unknown): never {
44
- throw new FixerPacketValidationError(cause);
45
- }
46
-
47
- function parseFailure(value: unknown): never {
48
- if (!Array.isArray(value)) fail(new Error("Fixer prerequisites must be a JSON array"));
49
- for (const entry of value) {
50
- if (!isRecord(entry)) {
51
- fail(new Error("Fixer prerequisite entry must be an object with id and requirement fields"));
52
- }
53
- if (
54
- typeof (entry as Record<string, unknown>).id !== "string" ||
55
- !(new RegExp(FIXER_PREREQUISITE_ID_PATTERN)).test((entry as { id: string }).id)
56
- ) {
57
- fail(new Error(`Fixer prerequisite id violates pattern ${FIXER_PREREQUISITE_ID_PATTERN}`));
58
- }
59
- if (
60
- typeof (entry as Record<string, unknown>).requirement !== "string" ||
61
- !/\S/.test((entry as { requirement: string }).requirement)
62
- ) {
63
- fail(new Error("Fixer prerequisite requirement must be nonblank"));
64
- }
65
- }
66
- fail(new Error("Fixer prerequisites violate the attachment schema"));
67
- }
68
-
69
- export function validateFixerPrerequisites(value: unknown): readonly FixerPrerequisite[] {
70
- if (!Value.Check(fixerPrerequisitesSchema, value)) parseFailure(value);
71
- const entries = value as Static<typeof fixerPrerequisitesSchema>;
72
- const ids = new Set<string>();
73
- const prerequisites = entries.map((entry) => {
74
- if (ids.has(entry.id)) {
75
- fail(new Error(`Fixer prerequisites contain duplicate id: ${entry.id}`));
76
- }
77
- ids.add(entry.id);
78
- return Object.freeze({ id: entry.id, requirement: entry.requirement });
79
- });
80
- return Object.freeze(prerequisites);
81
- }
82
-
83
- export function parseFixerPrerequisites(source: string): readonly FixerPrerequisite[] {
84
- let decoded: unknown;
85
- try {
86
- decoded = JSON.parse(source);
87
- } catch (error) {
88
- fail(error);
89
- }
90
- return validateFixerPrerequisites(decoded);
91
- }