@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
@@ -1559,10 +1559,10 @@ __export(session_assistant_usage_exports, {
1559
1559
  });
1560
1560
  import { join as join5 } from "node:path";
1561
1561
  async function readAssistantUsageFromSessionFile(sessionFile) {
1562
- const { readFile: readFile24 } = await import("node:fs/promises");
1562
+ const { readFile: readFile23 } = await import("node:fs/promises");
1563
1563
  let text;
1564
1564
  try {
1565
- text = await readFile24(sessionFile, "utf8");
1565
+ text = await readFile23(sessionFile, "utf8");
1566
1566
  } catch (error) {
1567
1567
  if (error?.code === "ENOENT") return void 0;
1568
1568
  throw error;
@@ -2669,21 +2669,6 @@ function projectTicketProvenanceSessions(value) {
2669
2669
  }
2670
2670
  return sessions;
2671
2671
  }
2672
- function projectTicketProvenanceAmendments(value) {
2673
- if (!Array.isArray(value)) return [];
2674
- const out = [];
2675
- for (const raw of value) {
2676
- if (!isRecord2(raw)) continue;
2677
- const s = nonNegativeInteger(raw.s);
2678
- const line2 = positiveInteger(raw.line);
2679
- const speaker = projectSpeaker(raw.speaker);
2680
- const text = raw.text;
2681
- if (s === void 0 || line2 === void 0 || speaker === void 0) continue;
2682
- if (typeof text !== "string") continue;
2683
- out.push({ s, line: line2, speaker, text });
2684
- }
2685
- return out;
2686
- }
2687
2672
  function projectTicketProvenanceHeader(value) {
2688
2673
  if (!isRecord2(value)) return void 0;
2689
2674
  const ticket = positiveInteger(value.ticket);
@@ -2708,12 +2693,14 @@ function projectTicketProvenanceLine(value) {
2708
2693
  const s = nonNegativeInteger(value.s);
2709
2694
  if (speaker === void 0 || s === void 0) return void 0;
2710
2695
  if (typeof value.text !== "string") return void 0;
2711
- const line2 = positiveInteger(value.line);
2696
+ const sourcePosition = nonNegativeInteger(value.sourcePosition);
2697
+ const sourceIdentity = typeof value.sourceIdentity === "string" && value.sourceIdentity !== "" ? value.sourceIdentity : void 0;
2712
2698
  const id = typeof value.id === "string" && value.id !== "" ? value.id : void 0;
2713
2699
  return {
2714
2700
  speaker,
2715
2701
  s,
2716
- ...line2 === void 0 ? {} : { line: line2 },
2702
+ ...sourcePosition === void 0 ? {} : { sourcePosition },
2703
+ ...sourceIdentity === void 0 ? {} : { sourceIdentity },
2717
2704
  ...id === void 0 ? {} : { id },
2718
2705
  text: value.text
2719
2706
  };
@@ -2805,11 +2792,6 @@ function projectDiaristSessions(value) {
2805
2792
  if (raw === void 0) return [];
2806
2793
  return projectTicketProvenanceSessions(raw);
2807
2794
  }
2808
- function projectDiaristAmendments(value) {
2809
- const raw = value?.amendments;
2810
- if (raw === void 0) return [];
2811
- return projectTicketProvenanceAmendments(raw);
2812
- }
2813
2795
  var DIARIST_OUTPUT_TOOL_NAME, DIARIST_ACCEPTED_TEXT;
2814
2796
  var init_diarist_contracts = __esm({
2815
2797
  "src/diarist-contracts.ts"() {
@@ -3819,13 +3801,10 @@ function assertRegisteredHostName(host) {
3819
3801
  }
3820
3802
  throw new Error(`unregistered host: ${host}`);
3821
3803
  }
3822
- var PRIVATE_COMPAT_ENV, DEFAULT_ROLE_TURN_HOST, HOST_DESCRIPTIONS, HEADLESS_HOST_DESCRIPTIONS;
3804
+ var DEFAULT_ROLE_TURN_HOST, HOST_DESCRIPTIONS, HEADLESS_HOST_DESCRIPTIONS;
3823
3805
  var init_host_descriptions = __esm({
3824
3806
  "src/host-descriptions.ts"() {
3825
3807
  "use strict";
3826
- PRIVATE_COMPAT_ENV = Object.fromEntries(
3827
- ["CLAUDE", "CURSOR", "CODEX"].flatMap((vendor) => ["SKILLS", "RULES", "AGENTS", "MCPS", "HOOKS", "SESSIONS"].map((kind) => [`GROK_${vendor}_${kind}_ENABLED`, "false"]))
3828
- );
3829
3808
  DEFAULT_ROLE_TURN_HOST = "pi";
3830
3809
  HOST_DESCRIPTIONS = Object.freeze({
3831
3810
  /** Operator home `~/.grok`, native session/load resume, `agent [--model X] stdio`. */
@@ -3838,12 +3817,7 @@ var init_host_descriptions = __esm({
3838
3817
  }),
3839
3818
  modelPassing: "argv",
3840
3819
  boundResume: "session/load",
3841
- sessionBindingFile: "grok-acp-session.json",
3842
- childEnv: Object.freeze({
3843
- ...PRIVATE_COMPAT_ENV,
3844
- GROK_MEMORY: "0",
3845
- GROK_SUBAGENTS: "0"
3846
- })
3820
+ sessionBindingFile: "grok-acp-session.json"
3847
3821
  }),
3848
3822
  /**
3849
3823
  * Operator home `~/.hermes`, native session/load resume, `acp` subcommand.
@@ -3862,7 +3836,6 @@ var init_host_descriptions = __esm({
3862
3836
  modelPassing: "set_model",
3863
3837
  boundResume: "session/load",
3864
3838
  sessionBindingFile: "hermes-acp-session.json",
3865
- childEnv: Object.freeze({}),
3866
3839
  seatProfileSoul: Object.freeze({
3867
3840
  flag: "-p",
3868
3841
  namePrefix: "ak-",
@@ -3883,12 +3856,7 @@ var init_host_descriptions = __esm({
3883
3856
  // Intermediate assistant/tool/system events require verbose with stream-json.
3884
3857
  "--verbose",
3885
3858
  "--permission-mode",
3886
- "bypassPermissions",
3887
- // Empty sources: no user/project/local operator surface (envelope owns materials).
3888
- "--setting-sources",
3889
- "",
3890
- // With adapter-supplied --mcp-config only (AK relay); drops operator + claude.ai MCP.
3891
- "--strict-mcp-config"
3859
+ "bypassPermissions"
3892
3860
  ]),
3893
3861
  promptFlag: "-p",
3894
3862
  modelFlag: "--model",
@@ -10783,10 +10751,10 @@ function pairGateRounds(volumes) {
10783
10751
  return rounds.sort((a, b) => a.officerStartedAt.localeCompare(b.officerStartedAt)).map((round, index) => ({ ...round, roundIndex: index + 1 }));
10784
10752
  }
10785
10753
  async function resolveOfficerSessionFromPointerFile(pointerPath) {
10786
- const { readFile: readFile24 } = await import("node:fs/promises");
10754
+ const { readFile: readFile23 } = await import("node:fs/promises");
10787
10755
  let raw;
10788
10756
  try {
10789
- raw = JSON.parse(await readFile24(pointerPath, "utf8"));
10757
+ raw = JSON.parse(await readFile23(pointerPath, "utf8"));
10790
10758
  } catch (error) {
10791
10759
  throw new Error(
10792
10760
  `direct officer run pointer unreadable in ${pointerPath}: ${error instanceof Error ? error.message : String(error)}`,
@@ -11387,16 +11355,27 @@ async function readPackageMaterial(relativePath) {
11387
11355
  }
11388
11356
  async function joinPackageMaterials(relativePaths) {
11389
11357
  const chunks = [];
11390
- for (const relativePath of relativePaths) {
11391
- chunks.push(await readPackageMaterial(relativePath));
11392
- }
11358
+ for (const relativePath of relativePaths) chunks.push(await readPackageMaterial(relativePath));
11393
11359
  return chunks.join("\n\n");
11394
11360
  }
11361
+ function roleSoulPath(role, materials) {
11362
+ const suffix = `/souls/${role}.md`;
11363
+ const path = materials.find((candidate) => `/${candidate}`.endsWith(suffix));
11364
+ if (path === void 0) throw new Error(`session materials omit the ${role} Soul`);
11365
+ return path;
11366
+ }
11367
+ async function loadSeparatedSessionPart(role, materials, part) {
11368
+ const soul = roleSoulPath(role, materials);
11369
+ return part === "soul" ? readPackageMaterial(soul) : joinPackageMaterials(materials.filter((path) => path !== soul));
11370
+ }
11395
11371
  function loadMainRoleSessionMaterials(role) {
11396
- return joinPackageMaterials(MAIN_ROLE_SESSION_MATERIALS[role]);
11372
+ return loadSeparatedSessionPart(role, MAIN_ROLE_SESSION_MATERIALS[role], "soul");
11373
+ }
11374
+ function loadMainRoleReferenceMaterials(role) {
11375
+ return loadSeparatedSessionPart(role, MAIN_ROLE_SESSION_MATERIALS[role], "references");
11397
11376
  }
11398
11377
  function loadGatekeeperSessionMaterials(role) {
11399
- return joinPackageMaterials(GATEKEEPER_SESSION_MATERIALS[role]);
11378
+ return loadSeparatedSessionPart(role, GATEKEEPER_SESSION_MATERIALS[role], "soul");
11400
11379
  }
11401
11380
  var packageRootUrl, MAIN_ROLE_SESSION_MATERIALS, GATEKEEPER_SESSION_MATERIALS;
11402
11381
  var init_session_opening_materials = __esm({
@@ -11426,6 +11405,8 @@ __export(auditor_soul_exports, {
11426
11405
  AUDITOR_SESSION_MATERIALS: () => AUDITOR_SESSION_MATERIALS,
11427
11406
  AUDITOR_SOUL_ROLES: () => AUDITOR_SOUL_ROLES,
11428
11407
  isAuditorSoulRole: () => isAuditorSoulRole,
11408
+ loadAuditorReferenceMaterials: () => loadAuditorReferenceMaterials,
11409
+ loadAuditorReferenceMaterialsFromSubjectInput: () => loadAuditorReferenceMaterialsFromSubjectInput,
11429
11410
  loadAuditorSoul: () => loadAuditorSoul,
11430
11411
  loadAuditorSoulFromSubjectInput: () => loadAuditorSoulFromSubjectInput,
11431
11412
  resolveAuditorSubject: () => resolveAuditorSubject
@@ -11452,11 +11433,18 @@ async function loadAuditorSoul(role) {
11452
11433
  if (soul.trim().length === 0) {
11453
11434
  throw new Error(`The ${role} auditor Soul is blank`);
11454
11435
  }
11455
- return joinPackageMaterials(materials);
11436
+ return soul;
11437
+ }
11438
+ function loadAuditorReferenceMaterials(role) {
11439
+ const soulPath = auditorSoulRelativePath(role);
11440
+ return joinPackageMaterials(AUDITOR_SESSION_MATERIALS[role].filter((path) => path !== soulPath));
11456
11441
  }
11457
11442
  async function loadAuditorSoulFromSubjectInput(raw) {
11458
11443
  return loadAuditorSoul(resolveAuditorSubject(raw));
11459
11444
  }
11445
+ function loadAuditorReferenceMaterialsFromSubjectInput(raw) {
11446
+ return loadAuditorReferenceMaterials(resolveAuditorSubject(raw));
11447
+ }
11460
11448
  var AUDITOR_SOUL_ROLES, AK_ROLE_AUDITOR_SUBJECT_ENV, AK_ROLE_AUDITOR_SOURCE_RUN_ENV, AUDITOR_SESSION_MATERIALS;
11461
11449
  var init_auditor_soul = __esm({
11462
11450
  "src/auditor-soul.ts"() {
@@ -16418,6 +16406,20 @@ function resolveTicketProvenanceVolume(ticketNumber, cwd, home) {
16418
16406
  );
16419
16407
  return { recordFile: path.recordFile, volumeDir: path.sessionDir };
16420
16408
  }
16409
+ function projectTicketProvenanceRaw(value) {
16410
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
16411
+ const raw = value;
16412
+ if (typeof raw.raw !== "string" || !Number.isInteger(raw.s) || raw.s < 0 || !Number.isInteger(raw.sourcePosition) || raw.sourcePosition < 0) {
16413
+ return void 0;
16414
+ }
16415
+ const sourceIdentity = typeof raw.sourceIdentity === "string" && raw.sourceIdentity !== "" ? raw.sourceIdentity : void 0;
16416
+ return {
16417
+ raw: raw.raw,
16418
+ s: raw.s,
16419
+ sourcePosition: raw.sourcePosition,
16420
+ ...sourceIdentity === void 0 ? {} : { sourceIdentity }
16421
+ };
16422
+ }
16421
16423
  function projectTicketProvenanceCommit(value) {
16422
16424
  if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
16423
16425
  const record4 = value;
@@ -16432,9 +16434,18 @@ function projectTicketProvenanceCommit(value) {
16432
16434
  if (sessions === void 0 || !Array.isArray(body.lines)) return void 0;
16433
16435
  const lines = [];
16434
16436
  for (const raw of body.lines) {
16437
+ if (typeof raw === "string") {
16438
+ lines.push(raw);
16439
+ continue;
16440
+ }
16435
16441
  const line2 = projectTicketProvenanceLine(raw);
16436
- if (line2 === void 0) return void 0;
16437
- lines.push(line2);
16442
+ if (line2 !== void 0) {
16443
+ lines.push(line2);
16444
+ continue;
16445
+ }
16446
+ const preserved = projectTicketProvenanceRaw(raw);
16447
+ if (preserved === void 0) return void 0;
16448
+ lines.push(preserved);
16438
16449
  }
16439
16450
  return { timestamp: record4.timestamp, sessions, lines };
16440
16451
  }
@@ -16445,7 +16456,14 @@ async function readTicketProvenance(ticketNumber, cwd, home) {
16445
16456
  text = await readFile18(recordFile, "utf8");
16446
16457
  } catch (error) {
16447
16458
  if (error.code === "ENOENT") {
16448
- return { header: void 0, lines: [], unprojectedRaw: [], recordFile };
16459
+ return {
16460
+ header: void 0,
16461
+ lines: [],
16462
+ unprojectedRaw: [],
16463
+ recordFile,
16464
+ sourceIdentities: /* @__PURE__ */ new Map(),
16465
+ legacySourcePositions: /* @__PURE__ */ new Map()
16466
+ };
16449
16467
  }
16450
16468
  throw error;
16451
16469
  }
@@ -16453,6 +16471,31 @@ async function readTicketProvenance(ticketNumber, cwd, home) {
16453
16471
  let header;
16454
16472
  const lines = [];
16455
16473
  const unprojectedRaw = [];
16474
+ const sourceIdentities = /* @__PURE__ */ new Map();
16475
+ const legacySourcePositions = /* @__PURE__ */ new Map();
16476
+ const rememberIdentity = (s, identity) => {
16477
+ const seen = sourceIdentities.get(s) ?? /* @__PURE__ */ new Set();
16478
+ const fresh = !seen.has(identity);
16479
+ seen.add(identity);
16480
+ sourceIdentities.set(s, seen);
16481
+ return fresh;
16482
+ };
16483
+ const rememberLegacyPosition = (s, position) => {
16484
+ const seen = legacySourcePositions.get(s) ?? /* @__PURE__ */ new Set();
16485
+ seen.add(position);
16486
+ legacySourcePositions.set(s, seen);
16487
+ };
16488
+ const remapCoverage = (coverage, priorIndexes) => {
16489
+ const normalized = /* @__PURE__ */ new Map();
16490
+ for (const [s, values] of coverage) {
16491
+ const target = priorIndexes[s] ?? s;
16492
+ const union = normalized.get(target) ?? /* @__PURE__ */ new Set();
16493
+ for (const value of values) union.add(value);
16494
+ normalized.set(target, union);
16495
+ }
16496
+ coverage.clear();
16497
+ for (const [s, values] of normalized) coverage.set(s, values);
16498
+ };
16456
16499
  let sawFirst = false;
16457
16500
  for (let index = 0; index < physical.length; index += 1) {
16458
16501
  const raw = physical[index];
@@ -16477,10 +16520,30 @@ async function readTicketProvenance(ticketNumber, cwd, home) {
16477
16520
  const commit = projectTicketProvenanceCommit(parsed);
16478
16521
  if (commit !== void 0) {
16479
16522
  const merged = mergeSessionBounds(header?.sessions, commit.sessions);
16480
- const remapped = commit.lines.map((entry) => ({
16481
- ...entry,
16482
- s: merged.incomingIndexes[entry.s] ?? entry.s
16483
- }));
16523
+ remapCoverage(sourceIdentities, merged.priorIndexes);
16524
+ remapCoverage(legacySourcePositions, merged.priorIndexes);
16525
+ const remapped = [];
16526
+ for (const entry of commit.lines) {
16527
+ if (typeof entry === "string") {
16528
+ unprojectedRaw.push(entry);
16529
+ continue;
16530
+ }
16531
+ const s = merged.incomingIndexes[entry.s] ?? merged.priorIndexes[entry.s] ?? entry.s;
16532
+ if ("raw" in entry) {
16533
+ if (entry.sourceIdentity !== void 0) {
16534
+ if (rememberIdentity(s, entry.sourceIdentity)) unprojectedRaw.push(entry.raw);
16535
+ } else {
16536
+ rememberLegacyPosition(s, entry.sourcePosition);
16537
+ unprojectedRaw.push(entry.raw);
16538
+ }
16539
+ continue;
16540
+ }
16541
+ remapped.push({ ...entry, s });
16542
+ if (entry.id === void 0) {
16543
+ if (entry.sourceIdentity !== void 0) rememberIdentity(s, entry.sourceIdentity);
16544
+ else if (entry.sourcePosition !== void 0) rememberLegacyPosition(s, entry.sourcePosition);
16545
+ }
16546
+ }
16484
16547
  const now = commit.timestamp;
16485
16548
  header = {
16486
16549
  repo: header?.repo ?? resolveBookKeyFromGit(cwd),
@@ -16498,7 +16561,19 @@ async function readTicketProvenance(ticketNumber, cwd, home) {
16498
16561
  }
16499
16562
  unprojectedRaw.push(raw);
16500
16563
  }
16501
- return { header, lines, unprojectedRaw, recordFile };
16564
+ for (const line2 of lines) {
16565
+ if (line2.id !== void 0) continue;
16566
+ if (line2.sourceIdentity !== void 0) rememberIdentity(line2.s, line2.sourceIdentity);
16567
+ else if (line2.sourcePosition !== void 0) rememberLegacyPosition(line2.s, line2.sourcePosition);
16568
+ }
16569
+ return {
16570
+ header,
16571
+ lines,
16572
+ unprojectedRaw,
16573
+ recordFile,
16574
+ sourceIdentities,
16575
+ legacySourcePositions
16576
+ };
16502
16577
  }
16503
16578
  function resolveBoundIndex(bound, sessionLines) {
16504
16579
  if (typeof bound.id === "string" && bound.id !== "") {
@@ -16517,8 +16592,8 @@ function resolveBoundIndex(bound, sessionLines) {
16517
16592
  }
16518
16593
  return void 0;
16519
16594
  }
16520
- function amendmentKey(s, line2) {
16521
- return `${s}:${line2}`;
16595
+ function dialogueIdentity(s, id) {
16596
+ return `${s}\0${id}`;
16522
16597
  }
16523
16598
  function rangeDeclarationKey(range) {
16524
16599
  return JSON.stringify({
@@ -16569,7 +16644,8 @@ function undeclaredSessionRanges(prior, merged) {
16569
16644
  const out = [];
16570
16645
  for (let s = 0; s < merged.length; s += 1) {
16571
16646
  const session = merged[s];
16572
- const declared = priorKeys.get(physicalPathIdentity(session.path)) ?? /* @__PURE__ */ new Set();
16647
+ const identity = physicalPathIdentity(session.path);
16648
+ const declared = priorKeys.get(identity) ?? /* @__PURE__ */ new Set();
16573
16649
  const fresh = session.ranges.filter(
16574
16650
  (range) => !declared.has(rangeDeclarationKey(range))
16575
16651
  );
@@ -16587,36 +16663,61 @@ function undeclaredSessionRanges(prior, merged) {
16587
16663
  }
16588
16664
  return out;
16589
16665
  }
16590
- function compareLinePosition(left, right) {
16591
- if (left.s !== right.s) return left.s - right.s;
16592
- const leftLine = left.line ?? Number.MAX_SAFE_INTEGER;
16593
- const rightLine = right.line ?? Number.MAX_SAFE_INTEGER;
16594
- return leftLine - rightLine;
16595
- }
16596
16666
  function mergeFreshIntoCarried(carried, fresh) {
16597
- const seenIds = /* @__PURE__ */ new Set();
16598
- const seenPositions = /* @__PURE__ */ new Set();
16599
- const out = [];
16600
- for (const line2 of carried) {
16601
- if (line2.id !== void 0) seenIds.add(line2.id);
16602
- if (line2.line !== void 0)
16603
- seenPositions.add(amendmentKey(line2.s, line2.line));
16604
- out.push(line2);
16605
- }
16606
- for (const line2 of fresh) {
16607
- if (line2.id !== void 0) {
16608
- if (seenIds.has(line2.id)) continue;
16609
- seenIds.add(line2.id);
16667
+ const seenSources = /* @__PURE__ */ new Map();
16668
+ const bySession = /* @__PURE__ */ new Map();
16669
+ const absorb = (lines) => {
16670
+ for (const line2 of lines) {
16671
+ const sourceIdentity = line2.id === void 0 ? line2.sourceIdentity : `id\0${line2.id}`;
16672
+ const identity = sourceIdentity === void 0 ? void 0 : `${line2.s}\0${sourceIdentity}`;
16673
+ const seen = identity === void 0 ? void 0 : seenSources.get(identity);
16674
+ if (seen !== void 0) {
16675
+ if (line2.sourcePosition !== void 0) {
16676
+ Object.assign(seen, { sourcePosition: line2.sourcePosition });
16677
+ }
16678
+ continue;
16679
+ }
16680
+ const bucket = bySession.get(line2.s) ?? [];
16681
+ bucket.push({ ...line2 });
16682
+ if (identity !== void 0) seenSources.set(identity, bucket.at(-1));
16683
+ bySession.set(line2.s, bucket);
16684
+ }
16685
+ };
16686
+ absorb(carried);
16687
+ absorb(fresh);
16688
+ return [...bySession.entries()].sort(([left], [right]) => left - right).flatMap(([, lines]) => lines.map((line2, archiveIndex) => ({ line: line2, archiveIndex })).sort((left, right) => {
16689
+ const leftPosition = left.line.sourcePosition;
16690
+ const rightPosition = right.line.sourcePosition;
16691
+ if (leftPosition === void 0 && rightPosition === void 0) {
16692
+ return left.archiveIndex - right.archiveIndex;
16693
+ }
16694
+ if (leftPosition === void 0) return 1;
16695
+ if (rightPosition === void 0) return -1;
16696
+ return leftPosition - rightPosition || left.archiveIndex - right.archiveIndex;
16697
+ }).map(({ line: line2 }) => line2));
16698
+ }
16699
+ function stableSourceFacts(sessionLines) {
16700
+ const positionByIdentity = /* @__PURE__ */ new Map();
16701
+ const facts = [];
16702
+ let precedingId = "<start>";
16703
+ let idlessOffset = 0;
16704
+ for (const entry of sessionLines) {
16705
+ const id = entry.row === void 0 ? void 0 : nativeEventId(entry.row);
16706
+ if (id !== void 0) {
16707
+ precedingId = id;
16708
+ idlessOffset = 0;
16709
+ } else {
16710
+ idlessOffset += 1;
16610
16711
  }
16611
- if (line2.line !== void 0) {
16612
- const position = amendmentKey(line2.s, line2.line);
16613
- if (seenPositions.has(position)) continue;
16614
- seenPositions.add(position);
16712
+ const identity = id === void 0 ? `after\0${precedingId}\0${idlessOffset}` : `id\0${id}`;
16713
+ let position = positionByIdentity.get(identity);
16714
+ if (position === void 0) {
16715
+ position = positionByIdentity.size;
16716
+ positionByIdentity.set(identity, position);
16615
16717
  }
16616
- out.push(line2);
16718
+ facts.push({ position, identity });
16617
16719
  }
16618
- out.sort(compareLinePosition);
16619
- return out;
16720
+ return facts;
16620
16721
  }
16621
16722
  function normalizeResolvedRanges(ranges, sessionLines, sessionPath) {
16622
16723
  const resolved = [];
@@ -16668,9 +16769,14 @@ async function projectSessionRanges(input) {
16668
16769
  }
16669
16770
  const rows = sessionLines.map((entry) => entry.row);
16670
16771
  const dialogue = adaptSessionDialogue(rows);
16772
+ const sourceFacts = stableSourceFacts(sessionLines);
16773
+ const sourcePositionByIdentity = /* @__PURE__ */ new Map();
16774
+ for (const fact of sourceFacts) {
16775
+ sourcePositionByIdentity.set(fact.identity, fact.position);
16776
+ }
16671
16777
  const seenIds = input.seenIds;
16672
16778
  const lines = [];
16673
- const unparsable = [];
16779
+ const raw = [];
16674
16780
  const ranges = normalizeResolvedRanges(
16675
16781
  input.session.ranges,
16676
16782
  sessionLines,
@@ -16678,38 +16784,30 @@ async function projectSessionRanges(input) {
16678
16784
  );
16679
16785
  for (const range of ranges) {
16680
16786
  for (let index = range.fromIndex; index <= range.toIndex; index += 1) {
16787
+ const { position: sourcePosition, identity: sourceIdentity } = sourceFacts[index];
16788
+ if (input.coveredSourceIdentities.has(sourceIdentity) || input.legacyCoveredSourcePositions.has(sourcePosition)) continue;
16681
16789
  const entry = sessionLines[index];
16682
16790
  if (entry.row === void 0) {
16683
- const key = amendmentKey(input.s, entry.line);
16684
- const amendment = input.amendmentsByKey.get(key);
16685
- if (amendment !== void 0) {
16686
- lines.push({
16687
- speaker: amendment.speaker,
16688
- s: input.s,
16689
- line: entry.line,
16690
- text: amendment.text
16691
- });
16692
- } else {
16693
- unparsable.push({ s: input.s, line: entry.line, raw: entry.raw });
16694
- }
16791
+ raw.push({ raw: entry.raw, s: input.s, sourcePosition, sourceIdentity });
16695
16792
  continue;
16696
16793
  }
16697
16794
  for (const event of dialogue[index] ?? []) {
16698
16795
  if (event.id !== void 0) {
16699
- if (seenIds.has(event.id)) continue;
16700
- seenIds.add(event.id);
16796
+ const identity = dialogueIdentity(input.s, event.id);
16797
+ if (seenIds.has(identity)) continue;
16798
+ seenIds.add(identity);
16701
16799
  }
16702
16800
  lines.push({
16703
16801
  speaker: event.speaker,
16704
16802
  s: input.s,
16705
- line: entry.line,
16706
- ...event.id === void 0 ? {} : { id: event.id },
16803
+ sourcePosition,
16804
+ ...event.id === void 0 ? { sourceIdentity } : { id: event.id },
16707
16805
  text: event.text
16708
16806
  });
16709
16807
  }
16710
16808
  }
16711
16809
  }
16712
- return { lines, unparsable };
16810
+ return { lines, raw, sourcePositionByIdentity };
16713
16811
  }
16714
16812
  async function reprojectTicketProvenance(input) {
16715
16813
  const prior = await readTicketProvenance(input.ticketNumber, input.cwd, input.home);
@@ -16724,8 +16822,7 @@ async function reprojectTicketProvenance(input) {
16724
16822
  updatedAt: now2,
16725
16823
  sessions: []
16726
16824
  },
16727
- lines: prior.lines,
16728
- unparsable: []
16825
+ lines: prior.lines
16729
16826
  };
16730
16827
  }
16731
16828
  const merged = mergeSessionBounds(prior.header?.sessions, input.sessions);
@@ -16741,34 +16838,34 @@ async function reprojectTicketProvenance(input) {
16741
16838
  updatedAt: now2,
16742
16839
  sessions: merged.sessions
16743
16840
  },
16744
- lines: prior.lines,
16745
- unparsable: []
16841
+ lines: prior.lines
16746
16842
  };
16747
16843
  }
16748
- const amendmentsByKey = /* @__PURE__ */ new Map();
16749
- for (const amendment of input.amendments ?? []) {
16750
- const cumulativeIndex = merged.incomingIndexes[amendment.s];
16751
- if (cumulativeIndex === void 0) continue;
16752
- amendmentsByKey.set(amendmentKey(cumulativeIndex, amendment.line), {
16753
- ...amendment,
16754
- s: cumulativeIndex
16755
- });
16756
- }
16757
16844
  const seenIds = new Set(
16758
- prior.lines.flatMap((line2) => line2.id === void 0 ? [] : [line2.id])
16845
+ prior.lines.flatMap(
16846
+ (line2) => line2.id === void 0 ? [] : [dialogueIdentity(line2.s, line2.id)]
16847
+ )
16759
16848
  );
16760
16849
  const fresh = [];
16761
- const unparsable = [];
16850
+ const raw = [];
16762
16851
  for (const delta of deltas) {
16763
16852
  const projected = await projectSessionRanges({
16764
16853
  s: delta.s,
16765
16854
  session: delta.session,
16766
- amendmentsByKey,
16767
16855
  seenIds,
16856
+ coveredSourceIdentities: prior.sourceIdentities.get(delta.s) ?? /* @__PURE__ */ new Set(),
16857
+ legacyCoveredSourcePositions: prior.legacySourcePositions.get(delta.s) ?? /* @__PURE__ */ new Set(),
16768
16858
  ...input.home === void 0 ? {} : { home: input.home }
16769
16859
  });
16860
+ fresh.push(...prior.lines.flatMap((line2) => {
16861
+ if (line2.s !== delta.s) return [];
16862
+ const sourceIdentity = line2.id === void 0 ? line2.sourceIdentity : `id\0${line2.id}`;
16863
+ if (sourceIdentity === void 0) return [];
16864
+ const sourcePosition = projected.sourcePositionByIdentity.get(sourceIdentity);
16865
+ return sourcePosition === void 0 ? [] : [{ ...line2, sourcePosition }];
16866
+ }));
16770
16867
  fresh.push(...projected.lines);
16771
- unparsable.push(...projected.unparsable);
16868
+ raw.push(...projected.raw);
16772
16869
  }
16773
16870
  const lines = mergeFreshIntoCarried(prior.lines, fresh);
16774
16871
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -16779,9 +16876,6 @@ async function reprojectTicketProvenance(input) {
16779
16876
  updatedAt: now,
16780
16877
  sessions: merged.sessions
16781
16878
  };
16782
- if (unparsable.length > 0) {
16783
- return { recordFile: prior.recordFile, header, lines, unparsable };
16784
- }
16785
16879
  const identityMaterial = JSON.stringify({
16786
16880
  ticket: input.ticketNumber,
16787
16881
  deltas: deltas.map(({ s, session }) => ({
@@ -16789,7 +16883,7 @@ async function reprojectTicketProvenance(input) {
16789
16883
  path: physicalPathIdentity(session.path),
16790
16884
  ranges: session.ranges
16791
16885
  })),
16792
- lines: fresh
16886
+ lines: [...fresh, ...raw]
16793
16887
  });
16794
16888
  const identity = `ticket-provenance:${createHash7("sha256").update(identityMaterial).digest("hex")}`;
16795
16889
  const pointer = appendSitianRecord({
@@ -16798,15 +16892,14 @@ async function reprojectTicketProvenance(input) {
16798
16892
  payload: {
16799
16893
  type: "ticket-provenance-append",
16800
16894
  sessions: merged.sessions,
16801
- lines: fresh
16895
+ lines: [...fresh, ...raw]
16802
16896
  }
16803
16897
  });
16804
16898
  const folded = await readTicketProvenance(input.ticketNumber, input.cwd, input.home);
16805
16899
  return {
16806
16900
  recordFile: pointer.recordFile,
16807
16901
  header: folded.header ?? header,
16808
- lines: folded.lines,
16809
- unparsable: []
16902
+ lines: folded.lines
16810
16903
  };
16811
16904
  }
16812
16905
  var TicketProvenanceInputError;
@@ -23489,33 +23582,6 @@ var diaristOutputSchema = withTerminatingOutputDeclarations(
23489
23582
  description: "\u672C\u7968\u5BF9\u8BDD\u8FB9\u754C\uFF1B\u7A7A\u5217\u8868\uFF1D\u672C\u8F6E\u65E0\u5BF9\u8BDD\u53EF\u5212\u3002\u7AEF\u70B9\u65E0\u6CD5\u6307\u540D\u65F6\u8D70 reask\uFF0C\u4E0D\u4E2D\u6B62\u3002"
23490
23583
  }
23491
23584
  )
23492
- ),
23493
- amendments: Type21.Optional(
23494
- Type21.Array(
23495
- Type21.Object(
23496
- {
23497
- s: Type21.Optional(
23498
- Type21.Unknown({ description: "\u5377\u4E0B\u6807\uFF08sessions \u4F4D\u7F6E\uFF09" })
23499
- ),
23500
- line: Type21.Optional(
23501
- Type21.Unknown({ description: "\u6E90\u5377 1-based \u884C\u53F7" })
23502
- ),
23503
- speaker: Type21.Optional(
23504
- Type21.String({ description: "owner | runner" })
23505
- ),
23506
- text: Type21.Optional(
23507
- Type21.String({ description: "\u8865\u5199\u6B63\u6587\uFF08\u539F\u8BDD\uFF09" })
23508
- )
23509
- },
23510
- {
23511
- additionalProperties: true,
23512
- description: "\u4E00\u6761\u574F\u884C\u8865\u5199\uFF1B\u7F3A\u5B57\u6BB5\u7684\u6210\u5458\u673A\u68B0\u8DF3\u8FC7"
23513
- }
23514
- ),
23515
- {
23516
- description: "\u53EF\u9009\uFF1B\u673A\u68B0\u89E3\u6790\u4E0D\u4E86\u7684\u884C\u4EA4\u6B64\u8865\u5199\u3002\u7F3A\u672C\u5B57\u6BB5\uFF1D\u65E0\u8865\u5199\uFF0C\u4E0D\u62D2\u6536\u3002"
23517
- }
23518
- )
23519
23585
  )
23520
23586
  })
23521
23587
  )
@@ -23523,8 +23589,8 @@ var diaristOutputSchema = withTerminatingOutputDeclarations(
23523
23589
  var DIARIST_TOOL_SPEC = {
23524
23590
  name: DIARIST_OUTPUT_TOOL_NAME,
23525
23591
  label: "\u8D77\u5C45\u90CE\u8F93\u51FA",
23526
- description: "\u8D77\u5C45\u90CE\u4EA4\u672C\u7968\u5BF9\u8BDD\u8FB9\u754C\uFF08sessions\uFF09\u4E0E\u53EF\u9009\u574F\u884C\u8865\u5199\uFF08amendments\uFF09\uFF1B\u8BA4\u4E0D\u51FA\u672C\u5EAD\u5BF9\u8C61\u5219 escalate\u3002",
23527
- promptSnippet: "\u8D77\u5C45\u90CE\u4EA4\u8FB9\u754C\u4E0E\u53EF\u9009\u8865\u5199",
23592
+ description: "\u8D77\u5C45\u90CE\u4EA4\u672C\u7968\u5BF9\u8BDD\u8FB9\u754C\uFF08sessions\uFF09\uFF1B\u8BA4\u4E0D\u51FA\u672C\u5EAD\u5BF9\u8C61\u5219 escalate\u3002",
23593
+ promptSnippet: "\u8D77\u5C45\u90CE\u4EA4\u8FB9\u754C",
23528
23594
  parameters: diaristOutputSchema
23529
23595
  };
23530
23596
 
@@ -23652,14 +23718,12 @@ async function commitDiaristProjection(input) {
23652
23718
  ticketNumber: input.ticketNumber,
23653
23719
  cwd: input.cwd,
23654
23720
  ...input.home === void 0 ? {} : { home: input.home },
23655
- sessions: input.sessions,
23656
- ...input.amendments === void 0 ? {} : { amendments: input.amendments }
23721
+ sessions: input.sessions
23657
23722
  });
23658
23723
  return {
23659
23724
  ticketNumber: input.ticketNumber,
23660
23725
  volumeRecordFile: result.recordFile,
23661
- lineCount: result.lines.length,
23662
- unparsable: result.unparsable
23726
+ lineCount: result.lines.length
23663
23727
  };
23664
23728
  }
23665
23729
 
@@ -24998,17 +25062,6 @@ function readDiaristRunCoordinates(ctx) {
24998
25062
  };
24999
25063
  }
25000
25064
  var DIARIST_BOUNDS_REASK = "\u8FB9\u754C\u65E0\u6CD5\u4F7F\u7528\u3002\u8BF7\u91CD\u4EA4 sessions\uFF1A\u6BCF\u5377 path + ranges\uFF0C\u6BCF\u7AEF\u4EE5\u539F\u751F id \u6216\u672C\u8F6E\u884C\u53F7\u4E8C\u9009\u4E00\u6307\u540D\u3002";
25001
- function diaristUnparsableReask(rows) {
25002
- const payload = rows.map((row) => ({
25003
- s: row.s,
25004
- line: row.line,
25005
- raw: row.raw
25006
- }));
25007
- return [
25008
- "\u4E0B\u5217\u6E90\u884C\u672A\u80FD\u5F55\u5165\uFF0C\u8BF7\u7ECF amendments \u8865\u5199\uFF08\u6BCF\u6761 s + line + speaker + text\uFF09\uFF1B\u5176\u4F59\u8FB9\u754C\u53EF\u4FDD\u6301\u4E0D\u53D8\u3002",
25009
- JSON.stringify(payload)
25010
- ].join("\n");
25011
- }
25012
25065
  function createDiaristRoleRuntime(roleHost, dependencies) {
25013
25066
  return createFiledOfficerRuntime(
25014
25067
  roleHost,
@@ -25030,15 +25083,13 @@ function createDiaristRoleRuntime(roleHost, dependencies) {
25030
25083
  if (sessions === void 0) {
25031
25084
  throw new ParentQueueReaskError(DIARIST_BOUNDS_REASK);
25032
25085
  }
25033
- const amendments = projectDiaristAmendments(parameters);
25034
25086
  let facts;
25035
25087
  try {
25036
25088
  facts = await commitDiaristProjection({
25037
25089
  ticketNumber,
25038
25090
  cwd: coords.projectRoot,
25039
25091
  home: coords.home,
25040
- sessions,
25041
- amendments
25092
+ sessions
25042
25093
  });
25043
25094
  } catch (error) {
25044
25095
  if (error instanceof ParentQueueReaskError) throw error;
@@ -25050,9 +25101,6 @@ ${error.message}`
25050
25101
  }
25051
25102
  throw error;
25052
25103
  }
25053
- if (facts.unparsable.length > 0) {
25054
- throw new ParentQueueReaskError(diaristUnparsableReask(facts.unparsable));
25055
- }
25056
25104
  }
25057
25105
  return parameters;
25058
25106
  }
@@ -25224,6 +25272,7 @@ function createRoleRuntimeExtension(dependencies) {
25224
25272
  });
25225
25273
  let admitted = false;
25226
25274
  let selectedRole;
25275
+ let roleReferenceMaterials = "";
25227
25276
  let activeReviewerParent;
25228
25277
  let reviewerOriginalRequest;
25229
25278
  let reviewerExpansionCaptured = false;
@@ -25317,10 +25366,10 @@ function createRoleRuntimeExtension(dependencies) {
25317
25366
  activeReviewerParent.skillBinding.name,
25318
25367
  text
25319
25368
  ) ?? text;
25320
- return text === event.text ? { action: "continue" } : { action: "transform", text };
25321
25369
  }
25322
- return text === event.text ? { action: "continue" } : { action: "transform", text };
25370
+ return { action: "continue" };
25323
25371
  });
25372
+ roleHost.on("before_agent_start", () => roleReferenceMaterials === "" ? void 0 : { readingMaterial: { kind: "role-reference-materials", content: roleReferenceMaterials } });
25324
25373
  roleHost.on("before_agent_start", async (event, ctx) => {
25325
25374
  const role = roleHost.getFlag(ROLE_FLAG.name);
25326
25375
  const prompt = event.prompt;
@@ -25886,6 +25935,7 @@ function createRoleRuntimeExtension(dependencies) {
25886
25935
  }
25887
25936
  admitted = false;
25888
25937
  selectedRole = void 0;
25938
+ roleReferenceMaterials = "";
25889
25939
  activeReviewerParent = void 0;
25890
25940
  reviewerOriginalRequest = void 0;
25891
25941
  reviewerExpansionCaptured = false;
@@ -26020,6 +26070,7 @@ function createRoleRuntimeExtension(dependencies) {
26020
26070
  }
26021
26071
  }
26022
26072
  await executeActivationStage(entry.role, activationStage(entry.role, runtime), { clock, writeTrace });
26073
+ roleReferenceMaterials = await dependencies.loadRoleReferenceMaterials?.(entry.role) ?? "";
26023
26074
  if (!engineDetourRegistered) {
26024
26075
  engineDetourRegistered = registerEngineDetourTool(roleHost, hostActions);
26025
26076
  }
@@ -26059,11 +26110,15 @@ var navigatorRoutePlaybookPath = fileURLToPath2(
26059
26110
  var collectorHandbookSeedPath = fileURLToPath2(
26060
26111
  new URL("../resources/collector-bot-handbook.md", import.meta.url)
26061
26112
  );
26113
+ function loadPackagedRoleReferenceMaterials(role) {
26114
+ return role === "auditor" ? loadAuditorReferenceMaterialsFromSubjectInput() : loadMainRoleReferenceMaterials(role);
26115
+ }
26062
26116
  function createRoleRuntimeDependencies(packageRoot) {
26063
26117
  const doctorAuditor = createPiDoctorAuditor();
26064
26118
  const navigatorSessionFactory = createNativeNavigatorSessionFactory();
26065
26119
  return {
26066
26120
  packageRoot,
26121
+ loadRoleReferenceMaterials: loadPackagedRoleReferenceMaterials,
26067
26122
  loadJudgeSoul: () => loadMainRoleSessionMaterials("judge"),
26068
26123
  loadFixerSoul: () => loadMainRoleSessionMaterials("fixer"),
26069
26124
  loadFixPacket: (path) => readFile22(path, "utf8"),
@@ -26124,9 +26179,9 @@ function createRoleRuntimeDependencies(packageRoot) {
26124
26179
  // src/role-envelope.ts
26125
26180
  init_engine_detour();
26126
26181
  import { randomUUID as randomUUID8 } from "node:crypto";
26127
- import { mkdir as mkdir5, readFile as readFile23, writeFile as writeFile12 } from "node:fs/promises";
26182
+ import { mkdir as mkdir6, writeFile as writeFile12 } from "node:fs/promises";
26128
26183
  import { createServer } from "node:net";
26129
- import { basename as basename9, dirname as dirname23, join as join40 } from "node:path";
26184
+ import { dirname as dirname24, join as join41 } from "node:path";
26130
26185
  import { fileURLToPath as fileURLToPath3 } from "node:url";
26131
26186
 
26132
26187
  // src/gatekeeper-pass-envelope.ts
@@ -26211,25 +26266,68 @@ async function requireGatekeeperPass(options) {
26211
26266
  }
26212
26267
  }
26213
26268
 
26269
+ // src/host-native-method.ts
26270
+ import { lstat as lstat7, mkdir as mkdir5, readlink, realpath as realpath7, symlink } from "node:fs/promises";
26271
+ import { basename as basename9, dirname as dirname23, join as join40 } from "node:path";
26272
+ var HOST_METHOD_PLUGIN_NAME = "ak-methods";
26273
+ var packagedMethodsDir = (root) => join40(root, "resources", "methods");
26274
+ var packagedMethodPluginDir = (root) => join40(root, "dist", "method-host-plugin");
26275
+ function hostMethodSkills(methods) {
26276
+ return Object.freeze(methods.flatMap((method) => {
26277
+ if (method.kind !== "skill") return [];
26278
+ const name = basename9(dirname23(method.path));
26279
+ return name ? [Object.freeze({ name })] : [];
26280
+ }));
26281
+ }
26282
+ var alreadyPrefixed = (prompt, token) => {
26283
+ const text = prompt.trimStart();
26284
+ return text === token || text.startsWith(`${token} `) || text.startsWith(`${token}
26285
+ `);
26286
+ };
26287
+ function prefixMethodInvocation(token, prompt) {
26288
+ if (alreadyPrefixed(prompt, token)) return prompt;
26289
+ return prompt ? `${token} ${prompt}` : token;
26290
+ }
26291
+ function applyClaudeSkillInvocation(methods, prompt) {
26292
+ const skills = hostMethodSkills(methods);
26293
+ if (skills.length !== 1) return prompt;
26294
+ return prefixMethodInvocation(`/${HOST_METHOD_PLUGIN_NAME}:${skills[0].name}`, prompt);
26295
+ }
26296
+ function applyCodexSkillInvocation(methods, prompt) {
26297
+ return hostMethodSkills(methods).reduceRight(
26298
+ (invocation, skill) => prefixMethodInvocation(`$${skill.name}`, invocation),
26299
+ prompt
26300
+ );
26301
+ }
26302
+ async function installWorkspaceMethodSkills(cwd, packageRoot) {
26303
+ const target = await realpath7(packagedMethodsDir(packageRoot));
26304
+ const link = join40(cwd, ".agents", "skills");
26305
+ try {
26306
+ const stat2 = await lstat7(link);
26307
+ if (!stat2.isSymbolicLink() || await realpath7(link) !== target) {
26308
+ const detail = stat2.isSymbolicLink() ? `symlink to ${await readlink(link)}` : "non-symlink entry";
26309
+ throw new Error(`workspace method catalog conflict at ${link}: ${detail}`);
26310
+ }
26311
+ return;
26312
+ } catch (error) {
26313
+ if (error.code !== "ENOENT") throw error;
26314
+ }
26315
+ await mkdir5(dirname23(link), { recursive: true });
26316
+ try {
26317
+ await symlink(target, link);
26318
+ } catch (error) {
26319
+ if (error.code !== "EEXIST") throw error;
26320
+ if (await realpath7(link).catch(() => "") !== target) {
26321
+ throw new Error(`workspace method catalog conflict at ${link}`);
26322
+ }
26323
+ }
26324
+ }
26325
+
26214
26326
  // src/role-envelope.ts
26215
26327
  init_packaged_role_registry();
26216
- init_method_skill();
26217
26328
  init_role_activation_flags();
26218
26329
  init_submission_correctable_error();
26219
26330
  init_navigator_invocation_identity();
26220
- function buildSkillExpansion(methodSkills, prompt) {
26221
- if (methodSkills.size !== 1) return void 0;
26222
- const entry = methodSkills.entries().next().value;
26223
- if (entry === void 0) return void 0;
26224
- const [name, method] = entry;
26225
- return Object.freeze({
26226
- name,
26227
- location: method.path,
26228
- content: method.body,
26229
- // Non-pi typed chain keeps original task bytes (ticket #822 r3); no consumer trim.
26230
- userMessage: prompt
26231
- });
26232
- }
26233
26331
  async function listen(server, path) {
26234
26332
  await new Promise((resolve21, reject) => {
26235
26333
  server.once("error", reject);
@@ -26264,21 +26362,14 @@ async function prepareRoleEnvelope(options) {
26264
26362
  const calls = [];
26265
26363
  const customEntries = [];
26266
26364
  const sessionEntries = [];
26267
- const methodSkills = /* @__PURE__ */ new Map();
26268
26365
  let preferredTools = [];
26269
26366
  let rejection;
26270
26367
  let infrastructureRoundFailure;
26271
26368
  const hostAbort = new AbortController();
26272
26369
  const runId = request.runDirectory.split("/").filter(Boolean).at(-1) ?? randomUUID8();
26273
- await mkdir5(request.runDirectory, { recursive: true });
26274
- for (const method of request.methods) {
26275
- if (method.kind !== "skill") continue;
26276
- const name = basename9(dirname23(method.path));
26277
- const raw = await readFile23(method.path, "utf8");
26278
- methodSkills.set(name, { path: method.path, body: stripSkillFrontmatter(raw).trim() });
26279
- }
26280
- let sessionFile = options.sessionFile ?? join40(request.runDirectory, "session", "session.jsonl");
26281
- await mkdir5(dirname23(sessionFile), { recursive: true });
26370
+ await mkdir6(request.runDirectory, { recursive: true });
26371
+ let sessionFile = options.sessionFile ?? join41(request.runDirectory, "session", "session.jsonl");
26372
+ await mkdir6(dirname24(sessionFile), { recursive: true });
26282
26373
  if (request.continuation.kind !== "resume") {
26283
26374
  try {
26284
26375
  await writeFile12(
@@ -26309,7 +26400,7 @@ async function prepareRoleEnvelope(options) {
26309
26400
  getLeafEntry: () => sessionEntries.at(-1),
26310
26401
  getLeafId: () => runId,
26311
26402
  getEntries: () => sessionEntries,
26312
- getSessionDir: () => dirname23(sessionFile),
26403
+ getSessionDir: () => dirname24(sessionFile),
26313
26404
  getSessionFile: () => sessionFile,
26314
26405
  getHeader: () => ({ type: "session", id: runId }),
26315
26406
  setSessionFile(path) {
@@ -26344,8 +26435,9 @@ async function prepareRoleEnvelope(options) {
26344
26435
  deliverSubmissionRejection(_value) {
26345
26436
  },
26346
26437
  capabilities: {
26347
- skillExpansion(prompt) {
26348
- return buildSkillExpansion(methodSkills, prompt);
26438
+ // #922: native loaders own expansion; package does not pre-read bodies (ADR 0032).
26439
+ skillExpansion() {
26440
+ return void 0;
26349
26441
  }
26350
26442
  },
26351
26443
  registerFlag(name, definition) {
@@ -26684,10 +26776,9 @@ async function prepareRoleEnvelope(options) {
26684
26776
  message: { role: "user", content: prompt }
26685
26777
  });
26686
26778
  }
26687
- const methodPrompt = (await Promise.all(request.methods.map(({ path }) => readFile23(path, "utf8")))).join("\n\n");
26688
26779
  const promptResults = await emit("before_agent_start", {
26689
26780
  prompt,
26690
- systemPrompt: methodPrompt,
26781
+ systemPrompt: "",
26691
26782
  systemPromptOptions: {}
26692
26783
  });
26693
26784
  const systemPromptParts = promptResults.flatMap((value) => {
@@ -26695,7 +26786,7 @@ async function prepareRoleEnvelope(options) {
26695
26786
  if (!("systemPrompt" in value) || typeof value.systemPrompt !== "string") return [];
26696
26787
  return [value.systemPrompt];
26697
26788
  });
26698
- const systemPromptBody = systemPromptParts.length > 0 ? systemPromptParts.join("\n\n") : methodPrompt;
26789
+ const systemPromptBody = systemPromptParts.join("\n\n");
26699
26790
  const readingMaterials = [];
26700
26791
  for (const value of promptResults) {
26701
26792
  if (typeof value !== "object" || value === null) continue;
@@ -26708,6 +26799,13 @@ async function prepareRoleEnvelope(options) {
26708
26799
  throw new Error(`terminating tool not registered after activation: ${terminatingToolName}`);
26709
26800
  }
26710
26801
  const jsonSchema = terminatingToolJsonSchema(terminating.parameters);
26802
+ if (request.host === "codex" && hostMethodSkills(request.methods).length > 0) {
26803
+ const packageRoot = options.dependencies.packageRoot;
26804
+ if (typeof packageRoot !== "string" || packageRoot === "") {
26805
+ throw new Error("codex project Skill catalog requires packageRoot");
26806
+ }
26807
+ await installWorkspaceMethodSkills(request.cwd, packageRoot);
26808
+ }
26711
26809
  return {
26712
26810
  mcpServers: [{
26713
26811
  name: `ak-${request.activation.role}`,
@@ -26745,7 +26843,7 @@ async function prepareRoleEnvelope(options) {
26745
26843
  init_session_identity();
26746
26844
 
26747
26845
  // src/headless-host/description.ts
26748
- import { join as join41 } from "node:path";
26846
+ import { join as join42 } from "node:path";
26749
26847
  function isClaudePrintDescription(description) {
26750
26848
  return description.protocol === "claude-print";
26751
26849
  }
@@ -26753,7 +26851,7 @@ function isCodexExecDescription(description) {
26753
26851
  return description.protocol === "codex-exec";
26754
26852
  }
26755
26853
  function resolveHeadlessBinary(description, operatorHome) {
26756
- return join41(operatorHome, ...description.binaryFromHome);
26854
+ return join42(operatorHome, ...description.binaryFromHome);
26757
26855
  }
26758
26856
  function headlessTurnArgs(options) {
26759
26857
  const { description } = options;
@@ -26765,6 +26863,7 @@ function headlessTurnArgs(options) {
26765
26863
  description.jsonSchemaFlag,
26766
26864
  JSON.stringify(options.jsonSchema)
26767
26865
  ];
26866
+ if (options.pluginDir) args.push("--plugin-dir", options.pluginDir);
26768
26867
  if (options.mcpConfigPath !== void 0 && options.mcpConfigPath !== "") {
26769
26868
  args.push(description.mcpConfigFlag, options.mcpConfigPath);
26770
26869
  }
@@ -26961,7 +27060,6 @@ function codexTurnArgs(options) {
26961
27060
  args.push("resume", options.session.id);
26962
27061
  }
26963
27062
  args.push("--json");
26964
- args.push("--ignore-user-config", "--ignore-rules");
26965
27063
  const roots = (options.writableRoots ?? []).filter((root) => root !== "");
26966
27064
  if (roots.length > 0) {
26967
27065
  args.push(
@@ -27009,7 +27107,7 @@ import { spawn as spawn4, spawnSync } from "node:child_process";
27009
27107
  import { randomUUID as randomUUID9 } from "node:crypto";
27010
27108
  import { existsSync as existsSync13 } from "node:fs";
27011
27109
  import { writeFile as writeFile13 } from "node:fs/promises";
27012
- import { dirname as dirname24, isAbsolute as isAbsolute11, join as join42, resolve as resolve20 } from "node:path";
27110
+ import { dirname as dirname25, isAbsolute as isAbsolute11, join as join43, resolve as resolve20 } from "node:path";
27013
27111
 
27014
27112
  // src/external-host-turn-loop.ts
27015
27113
  init_host_contracts();
@@ -27228,8 +27326,8 @@ function formatCodexFailurePayload(payload) {
27228
27326
  function cwdIsGitWorkTree(cwd) {
27229
27327
  let dir = cwd;
27230
27328
  for (; ; ) {
27231
- if (existsSync13(join42(dir, ".git"))) return true;
27232
- const parent = dirname24(dir);
27329
+ if (existsSync13(join43(dir, ".git"))) return true;
27330
+ const parent = dirname25(dir);
27233
27331
  if (parent === dir) return false;
27234
27332
  dir = parent;
27235
27333
  }
@@ -27418,7 +27516,8 @@ function buildTurnArgs(options) {
27418
27516
  mcpConfigPath: options.mcpConfigPath,
27419
27517
  ...options.model === void 0 ? {} : { model: options.model },
27420
27518
  ...options.effort === void 0 ? {} : { effort: options.effort },
27421
- session: { kind: options.sessionKind, id: options.sessionId }
27519
+ session: { kind: options.sessionKind, id: options.sessionId },
27520
+ ...options.pluginDir === void 0 ? {} : { pluginDir: options.pluginDir }
27422
27521
  });
27423
27522
  }
27424
27523
  function createHeadlessRoleTurnHost(config) {
@@ -27435,23 +27534,36 @@ function createHeadlessRoleTurnHost(config) {
27435
27534
  await config.sessionIdentity.bind(request.principal, sessionId);
27436
27535
  }
27437
27536
  const env = { ...process.env, ...config.env ?? {} };
27438
- const systemPromptPath = join42(request.runDirectory, "headless-system-prompt.txt");
27537
+ const systemPromptPath = join43(request.runDirectory, "headless-system-prompt.txt");
27439
27538
  await writeFile13(systemPromptPath, systemPrompt, "utf8");
27440
27539
  let mcpConfigPath;
27441
27540
  let outputSchemaPath;
27541
+ let pluginDir;
27542
+ let applyMethodPrompt = codex ? (prompt) => applyCodexSkillInvocation(request.methods, prompt) : (prompt) => prompt;
27442
27543
  if (codex) {
27443
- outputSchemaPath = join42(request.runDirectory, "headless-output-schema.json");
27444
- const closed = closeJsonSchemaForCodex(prepared.jsonSchema);
27445
- await writeFile13(outputSchemaPath, `${JSON.stringify(closed, null, 2)}
27446
- `, "utf8");
27544
+ outputSchemaPath = join43(request.runDirectory, "headless-output-schema.json");
27545
+ await writeFile13(
27546
+ outputSchemaPath,
27547
+ `${JSON.stringify(closeJsonSchemaForCodex(prepared.jsonSchema), null, 2)}
27548
+ `,
27549
+ "utf8"
27550
+ );
27447
27551
  } else {
27448
- mcpConfigPath = join42(request.runDirectory, "headless-mcp-config.json");
27552
+ mcpConfigPath = join43(request.runDirectory, "headless-mcp-config.json");
27449
27553
  await writeFile13(
27450
27554
  mcpConfigPath,
27451
27555
  `${JSON.stringify(headlessMcpConfigDocument(prepared.mcpServers), null, 2)}
27452
27556
  `,
27453
27557
  "utf8"
27454
27558
  );
27559
+ if (hostMethodSkills(request.methods).length > 0) {
27560
+ const packageRoot = env.AK_PACKAGE_ROOT ?? process.env.AK_PACKAGE_ROOT;
27561
+ if (typeof packageRoot !== "string" || packageRoot === "") {
27562
+ throw new Error("claude method plugin-dir requires AK_PACKAGE_ROOT");
27563
+ }
27564
+ pluginDir = packagedMethodPluginDir(packageRoot);
27565
+ applyMethodPrompt = (prompt) => applyClaudeSkillInvocation(request.methods, prompt);
27566
+ }
27455
27567
  }
27456
27568
  const sessionParent = config.sessionIdentity.resolveSessionFile(request.principal);
27457
27569
  outcome = await driveExternalRoleTurnRounds(prepared, request, {
@@ -27476,7 +27588,8 @@ function createHeadlessRoleTurnHost(config) {
27476
27588
  sessionId,
27477
27589
  sessionKind,
27478
27590
  cwd: request.cwd,
27479
- ...gitCommonDir === void 0 ? {} : { writableRoots: [gitCommonDir] }
27591
+ ...gitCommonDir === void 0 ? {} : { writableRoots: [gitCommonDir] },
27592
+ ...pluginDir === void 0 ? {} : { pluginDir }
27480
27593
  });
27481
27594
  } catch (error) {
27482
27595
  const message = error instanceof Error ? error.message : String(error);
@@ -27493,7 +27606,7 @@ function createHeadlessRoleTurnHost(config) {
27493
27606
  args,
27494
27607
  cwd: request.cwd,
27495
27608
  env,
27496
- stdin: prompt,
27609
+ stdin: applyMethodPrompt(prompt),
27497
27610
  ...abortSignal === void 0 ? {} : { signal: abortSignal },
27498
27611
  ...request.timeoutMs === void 0 ? {} : { timeoutMs: request.timeoutMs },
27499
27612
  onStdoutLine(line2) {