@akagilnc/pi-workflow-roles 0.1.4422 → 0.1.4489

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.
Files changed (53) hide show
  1. package/README.md +2 -0
  2. package/README.zh-CN.md +2 -0
  3. package/dist/acp-host/description.js +2 -3
  4. package/dist/acp-host/production-host.js +333 -258
  5. package/dist/auditor-soul.js +8 -1
  6. package/dist/diarist-contracts.js +2 -11
  7. package/dist/headless-host/description.js +3 -3
  8. package/dist/headless-host/production-host.js +340 -227
  9. package/dist/host-descriptions.js +3 -18
  10. package/dist/method-host-plugin/.claude-plugin/plugin.json +5 -0
  11. package/dist/method-host-plugin/skills/ak-cross-m-review/CONTEXT.md +48 -0
  12. package/dist/method-host-plugin/skills/ak-cross-m-review/LICENSE +21 -0
  13. package/dist/method-host-plugin/skills/ak-cross-m-review/SKILL.md +170 -0
  14. package/dist/method-host-plugin/skills/ak-cross-m-review/prompts/cmr-completeness.md +118 -0
  15. package/dist/method-host-plugin/skills/ak-cross-m-review/prompts/cmr-reviewer.md +128 -0
  16. package/dist/method-host-plugin/skills/ak-cross-m-review/provenance.json +41 -0
  17. package/dist/method-host-plugin/skills/diagnosing-bugs/SKILL.md +134 -0
  18. package/dist/method-host-plugin/skills/diagnosing-bugs/agents/openai.yaml +3 -0
  19. package/dist/method-host-plugin/skills/diagnosing-bugs/provenance.json +31 -0
  20. package/dist/method-host-plugin/skills/diagnosing-bugs/scripts/hitl-loop.template.sh +41 -0
  21. package/dist/method-host-plugin/skills/resolving-merge-conflicts/SKILL.md +14 -0
  22. package/dist/method-host-plugin/skills/resolving-merge-conflicts/agents/openai.yaml +3 -0
  23. package/dist/method-host-plugin/skills/resolving-merge-conflicts/provenance.json +26 -0
  24. package/dist/method-host-plugin/skills/tdd/SKILL.md +38 -0
  25. package/dist/method-host-plugin/skills/tdd/agents/openai.yaml +3 -0
  26. package/dist/method-host-plugin/skills/tdd/mocking.md +59 -0
  27. package/dist/method-host-plugin/skills/tdd/provenance.json +36 -0
  28. package/dist/method-host-plugin/skills/tdd/tests.md +77 -0
  29. package/dist/public-cli/main.js +14 -21
  30. package/dist/session-opening-materials.js +17 -5
  31. package/dist/ticket-provenance-contracts.js +6 -25
  32. package/dist/ticket-provenance.js +223 -90
  33. package/extensions/role-runtime.ts +16 -6
  34. package/package.json +1 -1
  35. package/resources/method-host-plugin/.claude-plugin/plugin.json +5 -0
  36. package/scripts/build-package.mjs +6 -1
  37. package/src/acp-host/description.ts +2 -4
  38. package/src/acp-host/production-host.ts +0 -1
  39. package/src/auditor-soul.ts +10 -1
  40. package/src/diarist-contracts.ts +1 -19
  41. package/src/diarist-role.ts +3 -31
  42. package/src/diarist.ts +5 -19
  43. package/src/headless-host/description.ts +4 -3
  44. package/src/headless-host/role-turn-host.ts +27 -4
  45. package/src/host-descriptions.ts +3 -23
  46. package/src/host-native-method.ts +67 -0
  47. package/src/ledger-session-read.ts +1 -2
  48. package/src/role-envelope.ts +17 -47
  49. package/src/role-runtime-dependencies.ts +17 -2
  50. package/src/role-runtime.ts +14 -31
  51. package/src/session-opening-materials.ts +27 -11
  52. package/src/ticket-provenance-contracts.ts +11 -38
  53. package/src/ticket-provenance.ts +228 -109
@@ -99,7 +99,6 @@ import {
99
99
  } from "./secretariat-contracts.ts";
100
100
  import {
101
101
  DIARIST_ACCEPTED_TEXT,
102
- projectDiaristAmendments,
103
102
  projectDiaristSessions,
104
103
  } from "./diarist-contracts.ts";
105
104
  import { commitDiaristProjection } from "./diarist.ts";
@@ -581,6 +580,8 @@ type NavigatorAttendanceDependency = Omit<NavigatorAttendance, "knownRoutePlaybo
581
580
  export type RoleRuntimeDependencies = {
582
581
  /** Package root for packaged engine-note resolution (#879). */
583
582
  packageRoot?: string;
583
+ /** Non-identity opening materials delivered in the ordinary role brief. */
584
+ loadRoleReferenceMaterials?(role: PackagedRole): Promise<string>;
584
585
  loadJudgeSoul(): Promise<string>;
585
586
  loadFixerSoul?(): Promise<string>;
586
587
  loadFixPacket?(path: string): Promise<string>;
@@ -961,26 +962,10 @@ function readDiaristRunCoordinates(ctx: HostContext): {
961
962
  const DIARIST_BOUNDS_REASK =
962
963
  "边界无法使用。请重交 sessions:每卷 path + ranges,每端以原生 id 或本轮行号二选一指名。" as const;
963
964
 
964
- /** Build reask text that hands unparsable source lines back for amendment. */
965
- function diaristUnparsableReask(
966
- rows: readonly { readonly s: number; readonly line: number; readonly raw: string }[],
967
- ): string {
968
- const payload = rows.map((row) => ({
969
- s: row.s,
970
- line: row.line,
971
- raw: row.raw,
972
- }));
973
- return [
974
- "下列源行未能录入,请经 amendments 补写(每条 s + line + speaker + text);其余边界可保持不变。",
975
- JSON.stringify(payload),
976
- ].join("\n");
977
- }
978
-
979
965
  /**
980
966
  * #708 / #779 / #901: 起居郎 public seat on the shared filed-officer envelope.
981
- * LLM judges ticket + dialogue bounds (+ optional amendments); mechanical layer
982
- * reprojects the unique records.jsonl. Unusable bounds and still-open unparsable
983
- * lines reask via ParentQueueReaskError (same mechanism as countersign). Machine
967
+ * LLM judges ticket + dialogue bounds; mechanical layer reprojects the unique
968
+ * records.jsonl. Unusable bounds reask via ParentQueueReaskError. Machine
984
969
  * facts never come from model self-report (锚定宪法).
985
970
  */
986
971
  export function createDiaristRoleRuntime(
@@ -1011,7 +996,6 @@ export function createDiaristRoleRuntime(
1011
996
  if (sessions === undefined) {
1012
997
  throw new ParentQueueReaskError(DIARIST_BOUNDS_REASK);
1013
998
  }
1014
- const amendments = projectDiaristAmendments(parameters);
1015
999
  let facts;
1016
1000
  try {
1017
1001
  facts = await commitDiaristProjection({
@@ -1019,7 +1003,6 @@ export function createDiaristRoleRuntime(
1019
1003
  cwd: coords.projectRoot,
1020
1004
  home: coords.home,
1021
1005
  sessions,
1022
- amendments,
1023
1006
  });
1024
1007
  } catch (error) {
1025
1008
  // Bound/session input failures → reask via typed identity (not message prefix).
@@ -1032,9 +1015,6 @@ export function createDiaristRoleRuntime(
1032
1015
  }
1033
1016
  throw error;
1034
1017
  }
1035
- if (facts.unparsable.length > 0) {
1036
- throw new ParentQueueReaskError(diaristUnparsableReask(facts.unparsable));
1037
- }
1038
1018
  }
1039
1019
  return parameters;
1040
1020
  },
@@ -1288,7 +1268,8 @@ export function createRoleRuntimeExtension(
1288
1268
  });
1289
1269
 
1290
1270
  let admitted = false;
1291
- let selectedRole: string | undefined;
1271
+ let selectedRole: PackagedRole | undefined;
1272
+ let roleReferenceMaterials = "";
1292
1273
  /** Live Reviewer parent activation for envelope agent_start prompt assembly. */
1293
1274
  let activeReviewerParent: ReviewerActivation | undefined;
1294
1275
  /** Envelope-owned Reviewer Skill expansion state (ADR 0018 — not a role-module facade). */
@@ -1401,14 +1382,14 @@ export function createRoleRuntimeExtension(
1401
1382
  activeReviewerParent.skillBinding.name,
1402
1383
  text,
1403
1384
  ) ?? text;
1404
- return text === event.text
1405
- ? { action: "continue" as const }
1406
- : { action: "transform" as const, text };
1407
1385
  }
1408
- return text === event.text
1409
- ? { action: "continue" as const }
1410
- : { action: "transform" as const, text };
1386
+ return { action: "continue" as const };
1411
1387
  });
1388
+ // Reference law/guides use the existing typed reading-material channel;
1389
+ // they are not rewritten into operator dialogue or the identity Soul.
1390
+ roleHost.on("before_agent_start", () => roleReferenceMaterials === ""
1391
+ ? undefined
1392
+ : { readingMaterial: { kind: "role-reference-materials", content: roleReferenceMaterials } });
1412
1393
  roleHost.on("before_agent_start", async (event, ctx) => {
1413
1394
  const role = roleHost.getFlag(ROLE_FLAG.name);
1414
1395
  const prompt = event.prompt;
@@ -2092,6 +2073,7 @@ export function createRoleRuntimeExtension(
2092
2073
  }
2093
2074
  admitted = false;
2094
2075
  selectedRole = undefined;
2076
+ roleReferenceMaterials = "";
2095
2077
  activeReviewerParent = undefined;
2096
2078
  reviewerOriginalRequest = undefined;
2097
2079
  reviewerExpansionCaptured = false;
@@ -2252,6 +2234,7 @@ export function createRoleRuntimeExtension(
2252
2234
  }
2253
2235
 
2254
2236
  await executeActivationStage(entry.role, activationStage(entry.role, runtime), { clock, writeTrace });
2237
+ roleReferenceMaterials = await dependencies.loadRoleReferenceMaterials?.(entry.role) ?? "";
2255
2238
  // #357 T2 / #378 / #380 / #391 / #818: any role+engine activation registers the package detour tool once.
2256
2239
  // Gate is resolveEngineName (RoleHost flag → env fallback) — no per-engine execute branch; no role-module spawn.
2257
2240
  if (!engineDetourRegistered) {
@@ -50,12 +50,28 @@ export async function joinPackageMaterials(
50
50
  relativePaths: readonly string[],
51
51
  ): Promise<string> {
52
52
  const chunks: string[] = [];
53
- for (const relativePath of relativePaths) {
54
- chunks.push(await readPackageMaterial(relativePath));
55
- }
53
+ for (const relativePath of relativePaths) chunks.push(await readPackageMaterial(relativePath));
56
54
  return chunks.join("\n\n");
57
55
  }
58
56
 
57
+ function roleSoulPath(role: string, materials: readonly string[]): string {
58
+ const suffix = `/souls/${role}.md`;
59
+ const path = materials.find((candidate) => `/${candidate}`.endsWith(suffix));
60
+ if (path === undefined) throw new Error(`session materials omit the ${role} Soul`);
61
+ return path;
62
+ }
63
+
64
+ async function loadSeparatedSessionPart(
65
+ role: string,
66
+ materials: readonly string[],
67
+ part: "soul" | "references",
68
+ ): Promise<string> {
69
+ const soul = roleSoulPath(role, materials);
70
+ return part === "soul"
71
+ ? readPackageMaterial(soul)
72
+ : joinPackageMaterials(materials.filter((path) => path !== soul));
73
+ }
74
+
59
75
  type PublicRoleMaterials = {
60
76
  readonly [Role in PackagedRole]: Extract<
61
77
  (typeof PUBLIC_ROLE_RECORDS)[number],
@@ -72,10 +88,12 @@ export const MAIN_ROLE_SESSION_MATERIALS = {
72
88
 
73
89
  export type MainRoleSession = keyof typeof MAIN_ROLE_SESSION_MATERIALS;
74
90
 
75
- export function loadMainRoleSessionMaterials(
76
- role: MainRoleSession,
77
- ): Promise<string> {
78
- return joinPackageMaterials(MAIN_ROLE_SESSION_MATERIALS[role]);
91
+ export function loadMainRoleSessionMaterials(role: MainRoleSession): Promise<string> {
92
+ return loadSeparatedSessionPart(role, MAIN_ROLE_SESSION_MATERIALS[role], "soul");
93
+ }
94
+
95
+ export function loadMainRoleReferenceMaterials(role: MainRoleSession): Promise<string> {
96
+ return loadSeparatedSessionPart(role, MAIN_ROLE_SESSION_MATERIALS[role], "references");
79
97
  }
80
98
 
81
99
  /** Gatekeeper province; notary reuses the public notary materials definition. */
@@ -88,8 +106,6 @@ export const GATEKEEPER_SESSION_MATERIALS = {
88
106
 
89
107
  export type GatekeeperSessionRole = keyof typeof GATEKEEPER_SESSION_MATERIALS;
90
108
 
91
- export function loadGatekeeperSessionMaterials(
92
- role: GatekeeperSessionRole,
93
- ): Promise<string> {
94
- return joinPackageMaterials(GATEKEEPER_SESSION_MATERIALS[role]);
109
+ export function loadGatekeeperSessionMaterials(role: GatekeeperSessionRole): Promise<string> {
110
+ return loadSeparatedSessionPart(role, GATEKEEPER_SESSION_MATERIALS[role], "soul");
95
111
  }
@@ -48,29 +48,20 @@ export type TicketProvenanceHeader = {
48
48
 
49
49
  /**
50
50
  * 一条对话(存于不可变投影提交;旧 snapshot 中也可为裸行)。
51
- * `id` 与 `line` 按源事实存在则记、不存在不编;两者皆无的少数条目
52
- * 靠录中前后有定位的条目锚定。
51
+ * `id` 按源事实存在则记、不存在不编;`s` 保留卷定位。
53
52
  */
54
53
  export type TicketProvenanceLine = {
55
54
  readonly speaker: TicketProvenanceSpeaker;
56
55
  /** 卷下标(册子头 `sessions` 的位置)。 */
57
56
  readonly s: number;
58
- readonly line?: number;
57
+ /** Logical source order for display. */
58
+ readonly sourcePosition?: number;
59
+ /** Replay-invariant structural identity used for id-less cumulative coverage. */
60
+ readonly sourceIdentity?: string;
59
61
  readonly id?: string;
60
62
  readonly text: string;
61
63
  };
62
64
 
63
- /**
64
- * 坏行补写:绑定源卷与行,带说话人与正文。
65
- * 编没编由符宝郎读录核旨,代码不判断(`unparsable-line-to-diarist`)。
66
- */
67
- export type TicketProvenanceAmendment = {
68
- readonly s: number;
69
- readonly line: number;
70
- readonly speaker: TicketProvenanceSpeaker;
71
- readonly text: string;
72
- };
73
-
74
65
  function isRecord(value: unknown): value is Record<string, unknown> {
75
66
  return typeof value === "object" && value !== null && !Array.isArray(value);
76
67
  }
@@ -136,28 +127,6 @@ export function projectTicketProvenanceSessions(
136
127
  return sessions;
137
128
  }
138
129
 
139
- /**
140
- * 投影补写集合。缺该字段=无补写(不拒收);成员形状不成立的整条跳过——
141
- * 它没有绑定位置,放不回去。
142
- */
143
- export function projectTicketProvenanceAmendments(
144
- value: unknown,
145
- ): readonly TicketProvenanceAmendment[] {
146
- if (!Array.isArray(value)) return [];
147
- const out: TicketProvenanceAmendment[] = [];
148
- for (const raw of value) {
149
- if (!isRecord(raw)) continue;
150
- const s = nonNegativeInteger(raw.s);
151
- const line = positiveInteger(raw.line);
152
- const speaker = projectSpeaker(raw.speaker);
153
- const text = raw.text;
154
- if (s === undefined || line === undefined || speaker === undefined) continue;
155
- if (typeof text !== "string") continue;
156
- out.push({ s, line, speaker, text });
157
- }
158
- return out;
159
- }
160
-
161
130
  /** 读回册子头(文件第一行)。形状不成立即 undefined——按无册处理,不猜。 */
162
131
  export function projectTicketProvenanceHeader(
163
132
  value: unknown,
@@ -190,12 +159,16 @@ export function projectTicketProvenanceLine(
190
159
  const s = nonNegativeInteger(value.s);
191
160
  if (speaker === undefined || s === undefined) return undefined;
192
161
  if (typeof value.text !== "string") return undefined;
193
- const line = positiveInteger(value.line);
162
+ const sourcePosition = nonNegativeInteger(value.sourcePosition);
163
+ const sourceIdentity = typeof value.sourceIdentity === "string" && value.sourceIdentity !== ""
164
+ ? value.sourceIdentity
165
+ : undefined;
194
166
  const id = typeof value.id === "string" && value.id !== "" ? value.id : undefined;
195
167
  return {
196
168
  speaker,
197
169
  s,
198
- ...(line === undefined ? {} : { line }),
170
+ ...(sourcePosition === undefined ? {} : { sourcePosition }),
171
+ ...(sourceIdentity === undefined ? {} : { sourceIdentity }),
199
172
  ...(id === undefined ? {} : { id }),
200
173
  text: value.text,
201
174
  };