@akagilnc/pi-workflow-roles 0.1.4444 → 0.1.4503

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 (50) 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 +512 -288
  5. package/dist/auditor-soul.js +8 -1
  6. package/dist/headless-host/description.js +3 -3
  7. package/dist/headless-host/production-host.js +519 -257
  8. package/dist/host-descriptions.js +3 -18
  9. package/dist/method-host-plugin/.claude-plugin/plugin.json +5 -0
  10. package/dist/method-host-plugin/skills/ak-cross-m-review/CONTEXT.md +48 -0
  11. package/dist/method-host-plugin/skills/ak-cross-m-review/LICENSE +21 -0
  12. package/dist/method-host-plugin/skills/ak-cross-m-review/SKILL.md +170 -0
  13. package/dist/method-host-plugin/skills/ak-cross-m-review/prompts/cmr-completeness.md +118 -0
  14. package/dist/method-host-plugin/skills/ak-cross-m-review/prompts/cmr-reviewer.md +128 -0
  15. package/dist/method-host-plugin/skills/ak-cross-m-review/provenance.json +41 -0
  16. package/dist/method-host-plugin/skills/diagnosing-bugs/SKILL.md +134 -0
  17. package/dist/method-host-plugin/skills/diagnosing-bugs/agents/openai.yaml +3 -0
  18. package/dist/method-host-plugin/skills/diagnosing-bugs/provenance.json +31 -0
  19. package/dist/method-host-plugin/skills/diagnosing-bugs/scripts/hitl-loop.template.sh +41 -0
  20. package/dist/method-host-plugin/skills/resolving-merge-conflicts/SKILL.md +14 -0
  21. package/dist/method-host-plugin/skills/resolving-merge-conflicts/agents/openai.yaml +3 -0
  22. package/dist/method-host-plugin/skills/resolving-merge-conflicts/provenance.json +26 -0
  23. package/dist/method-host-plugin/skills/tdd/SKILL.md +38 -0
  24. package/dist/method-host-plugin/skills/tdd/agents/openai.yaml +3 -0
  25. package/dist/method-host-plugin/skills/tdd/mocking.md +59 -0
  26. package/dist/method-host-plugin/skills/tdd/provenance.json +36 -0
  27. package/dist/method-host-plugin/skills/tdd/tests.md +77 -0
  28. package/dist/public-cli/countersign-run.js +214 -155
  29. package/dist/public-cli/diarist-run.js +4 -1
  30. package/dist/public-cli/invocation.js +129 -21
  31. package/dist/public-cli/main.js +386 -202
  32. package/dist/session-opening-materials.js +17 -5
  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/headless-host/description.ts +4 -3
  41. package/src/headless-host/role-turn-host.ts +27 -4
  42. package/src/host-descriptions.ts +3 -23
  43. package/src/host-native-method.ts +67 -0
  44. package/src/public-cli/countersign-run.ts +326 -218
  45. package/src/public-cli/diarist-run.ts +4 -0
  46. package/src/public-cli/invocation.ts +205 -23
  47. package/src/role-envelope.ts +17 -47
  48. package/src/role-runtime-dependencies.ts +17 -2
  49. package/src/role-runtime.ts +12 -7
  50. package/src/session-opening-materials.ts +27 -11
@@ -4,7 +4,8 @@
4
4
  */
5
5
  import { execFileSync } from "node:child_process";
6
6
  import { existsSync } from "node:fs";
7
- import { lstat, readFile, realpath, rename, writeFile, } from "node:fs/promises";
7
+ import { lstat, mkdtemp, readFile, realpath, rename, rm, writeFile, } from "node:fs/promises";
8
+ import { tmpdir } from "node:os";
8
9
  import { basename, dirname, isAbsolute, join, resolve, sep } from "node:path";
9
10
  import { activationBookDirectory, ensureRealDirectoryTree, homeFromRunDirectory, pathContainedIn, resolveActivationLedgerHome, } from "../activation-ledger-topology.js";
10
11
  import { resolveBookKeyFromGit } from "../activation-ledger-git.js";
@@ -36,7 +37,8 @@ export function issueAdmissionPlacement(authority, request) {
36
37
  runId: request.runId,
37
38
  role: request.role,
38
39
  });
39
- ensureRoleRunPlacement(ledgerHome, placement);
40
+ if (request.materialize !== false)
41
+ ensureRoleRunPlacement(ledgerHome, placement);
40
42
  return {
41
43
  principal: authority.seal(placement),
42
44
  ...placement,
@@ -172,6 +174,27 @@ export async function bindAdmittedTicketNumber(admitted, ticketNumber) {
172
174
  await bindTicketNumberOnRunDirectory(admitted.runDirectory, ticketNumber);
173
175
  admitted.ticketNumber = ticketNumber;
174
176
  }
177
+ /** Persist each direct caller observed while a retained run is resumed. */
178
+ export async function recordAdmittedCorrelation(admitted, correlationId) {
179
+ const current = JSON.parse(await readFile(admitted.admittedRequestPath, "utf8"));
180
+ const prior = [
181
+ ...(Array.isArray(current.correlationIds)
182
+ ? current.correlationIds.filter((value) => typeof value === "string" && value.trim() !== "")
183
+ : []),
184
+ ...(typeof current.correlationId === "string" && current.correlationId.trim() !== ""
185
+ ? [current.correlationId]
186
+ : []),
187
+ ];
188
+ const correlationIds = [...new Set([...prior, correlationId])];
189
+ await writeFile(admitted.admittedRequestPath, `${JSON.stringify({ ...current, correlationId, correlationIds }, null, 2)}\n`, "utf8");
190
+ await mergeInvocationIdentityPage(admitted.runDirectory, {
191
+ correlationId,
192
+ correlationIds,
193
+ });
194
+ const mutable = admitted;
195
+ mutable.correlationId = correlationId;
196
+ mutable.correlationIds = correlationIds;
197
+ }
175
198
  /**
176
199
  * #871: persist the typed co-review set as a countersign run fact (admitted-request +
177
200
  * invocation.json). Whole-set replace — never union with a prior set. Main ticket
@@ -584,7 +607,7 @@ export function parseFixerArgv(args) {
584
607
  ...(project === undefined ? {} : { project }),
585
608
  };
586
609
  }
587
- async function freezeRegularFileAttachment(sourcePath, destinationDir, index) {
610
+ async function readRegularFileAttachment(sourcePath) {
588
611
  const absolute = isAbsolute(sourcePath) ? sourcePath : resolve(sourcePath);
589
612
  let st;
590
613
  try {
@@ -596,18 +619,66 @@ async function freezeRegularFileAttachment(sourcePath, destinationDir, index) {
596
619
  if (!st.isFile() || st.isSymbolicLink()) {
597
620
  throw new CliUsageError(`attachment must be a regular file (not a directory or symlink): ${sourcePath}`);
598
621
  }
599
- const bytes = await readFile(absolute);
600
- const name = `${String(index).padStart(2, "0")}-${basename(absolute)}`;
601
- const frozenPath = join(destinationDir, name);
622
+ try {
623
+ return { absolute, bytes: await readFile(absolute) };
624
+ }
625
+ catch (error) {
626
+ throw new CliUsageError(`attachment is not a readable regular file: ${sourcePath}`, { cause: error });
627
+ }
628
+ }
629
+ /**
630
+ * Snapshot deferred inputs sequentially before identity side effects. The staging
631
+ * files keep aggregate attachment bytes off heap until their final run is known.
632
+ */
633
+ async function removePreparedAttachmentDirectory(stagingDirectory) {
634
+ await rm(stagingDirectory, { recursive: true, force: true });
635
+ }
636
+ /** Own the complete deferred-snapshot lifetime without masking either failure. */
637
+ export async function withPreparedAttachments(attachmentPaths, use) {
638
+ if (attachmentPaths.length === 0)
639
+ return await use([]);
640
+ const stagingDirectory = await mkdtemp(join(tmpdir(), "ak-role-attachments-"));
641
+ const prepared = [];
642
+ let result;
643
+ try {
644
+ for (let index = 0; index < attachmentPaths.length; index += 1) {
645
+ const { absolute, bytes } = await readRegularFileAttachment(attachmentPaths[index]);
646
+ const snapshotPath = join(stagingDirectory, String(index).padStart(6, "0"));
647
+ await writeFile(snapshotPath, bytes);
648
+ prepared.push({ absolute, snapshotPath });
649
+ }
650
+ result = await use(prepared);
651
+ }
652
+ catch (primary) {
653
+ try {
654
+ await removePreparedAttachmentDirectory(stagingDirectory);
655
+ }
656
+ catch (cleanup) {
657
+ throw new AggregateError([primary, cleanup], "attachment snapshot operation failed and cleanup also failed", { cause: primary });
658
+ }
659
+ throw primary;
660
+ }
661
+ await removePreparedAttachmentDirectory(stagingDirectory);
662
+ return result;
663
+ }
664
+ async function freezeAttachmentBytes(provenancePath, bytes, destinationDir, index) {
665
+ const frozenPath = join(destinationDir, `${String(index).padStart(2, "0")}-${basename(provenancePath)}`);
602
666
  await writeFile(frozenPath, bytes);
603
667
  return {
604
- attachment: {
605
- provenancePath: absolute,
606
- frozenPath,
607
- byteLength: bytes.byteLength,
608
- sha256: sha256Hex(bytes),
609
- mediaKind: "regular-file",
610
- },
668
+ provenancePath,
669
+ frozenPath,
670
+ byteLength: bytes.byteLength,
671
+ sha256: sha256Hex(bytes),
672
+ mediaKind: "regular-file",
673
+ };
674
+ }
675
+ async function freezePreparedAttachment(prepared, destinationDir, index) {
676
+ return freezeAttachmentBytes(prepared.absolute, await readFile(prepared.snapshotPath), destinationDir, index);
677
+ }
678
+ async function freezeRegularFileAttachment(sourcePath, destinationDir, index) {
679
+ const { absolute, bytes } = await readRegularFileAttachment(sourcePath);
680
+ return {
681
+ attachment: await freezeAttachmentBytes(absolute, bytes, destinationDir, index),
611
682
  body: bytes,
612
683
  };
613
684
  }
@@ -633,6 +704,21 @@ export async function freezeAttachmentsIntoRun(attachmentPaths, runDirectory, su
633
704
  ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
634
705
  return freezeAttachments(attachmentPaths, attachmentsDirectory);
635
706
  }
707
+ /** Freeze prepared bytes and metadata through one path for birth or retained runs. */
708
+ export async function freezePreparedAttachmentsIntoRun(prepared, runDirectory, summonsKey) {
709
+ if (prepared.length === 0)
710
+ return [];
711
+ const ledgerHome = resolveActivationLedgerHome(homeFromRunDirectory(runDirectory));
712
+ const attachmentsDirectory = summonsKey === undefined
713
+ ? join(runDirectory, "attachments")
714
+ : join(runDirectory, "attachments", summonsKey);
715
+ ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
716
+ const attachments = [];
717
+ for (let index = 0; index < prepared.length; index += 1) {
718
+ attachments.push(await freezePreparedAttachment(prepared[index], attachmentsDirectory, index));
719
+ }
720
+ return attachments;
721
+ }
636
722
  function ticketAdmissionFields(ticketNumber) {
637
723
  if (ticketNumber === undefined)
638
724
  return {};
@@ -776,8 +862,8 @@ export function buildInspectorTransportPrompt(admitted, engineMaterial) {
776
862
  return buildInstructionTransportPrompt(admitted, engineMaterial);
777
863
  }
778
864
  /**
779
- * Atomically admit a Countersign Role run: freeze Attachments, persist the
780
- * request, write the invocation ledger (#572 / ADR 0074).
865
+ * Admit a Countersign run immediately, or reserve its coordinates for deferred
866
+ * materialization after identity lookup (#572 / ADR 0074 / #863).
781
867
  */
782
868
  export async function admitCountersignInvocation(options) {
783
869
  // Same shared freeze/coordinate body as judge but role: "countersign" so
@@ -793,8 +879,11 @@ export async function admitCountersignInvocation(options) {
793
879
  role: "countersign",
794
880
  subject: { unbound: true },
795
881
  home: options.home,
882
+ materialize: options.deferPersistence !== true,
796
883
  });
797
- const attachments = await freezeAttachments(options.attachmentPaths, attachmentsDirectory);
884
+ const attachments = options.deferPersistence === true
885
+ ? []
886
+ : await freezeAttachments(options.attachmentPaths, attachmentsDirectory);
798
887
  // Ticket binding is LLM-only post-admission (#635); admission stays unbound.
799
888
  const instruction = options.instruction;
800
889
  const instructionEmpty = instruction.trim() === "";
@@ -817,11 +906,13 @@ export async function admitCountersignInvocation(options) {
817
906
  })),
818
907
  };
819
908
  const admittedRequestPath = join(runDirectory, "admitted-request.json");
820
- await writeAdmittedRequestPersistence(admittedRequestPath, admitted, {
821
- sessionDirectory,
822
- sessionFile,
823
- });
824
- await writeRoleInvocationLedger({ ...admitted, sessionDirectory, sessionFile }, admitted.role, options.model);
909
+ if (options.deferPersistence !== true) {
910
+ await writeAdmittedRequestPersistence(admittedRequestPath, admitted, {
911
+ sessionDirectory,
912
+ sessionFile,
913
+ });
914
+ await writeRoleInvocationLedger({ ...admitted, sessionDirectory, sessionFile }, admitted.role, options.model);
915
+ }
825
916
  return {
826
917
  role: "countersign",
827
918
  runId,
@@ -836,6 +927,23 @@ export async function admitCountersignInvocation(options) {
836
927
  ...(options.correlationId === undefined ? {} : { correlationId: options.correlationId }),
837
928
  };
838
929
  }
930
+ /** Persist a deferred Countersign admission after same-ticket lookup found no retained run. */
931
+ export async function materializeCountersignInvocation(admitted, options) {
932
+ const placement = issueAdmissionPlacement(options.principalAuthority, {
933
+ cwd: admitted.projectRoot,
934
+ runId: admitted.runId,
935
+ role: "countersign",
936
+ subject: { unbound: true },
937
+ home: options.home,
938
+ });
939
+ const attachments = await freezePreparedAttachmentsIntoRun(options.preparedAttachments, admitted.runDirectory);
940
+ admitted.attachments = attachments;
941
+ await writeAdmittedRequestPersistence(admitted.admittedRequestPath, admitted, {
942
+ sessionDirectory: placement.sessionDirectory,
943
+ sessionFile: placement.sessionFile,
944
+ });
945
+ await writeRoleInvocationLedger({ ...admitted, sessionDirectory: placement.sessionDirectory, sessionFile: placement.sessionFile }, admitted.role, options.model);
946
+ }
839
947
  /** Build the Pi prompt transport for an admitted Countersign request. */
840
948
  export function buildCountersignTransportPrompt(admitted, engineMaterial) {
841
949
  return buildInstructionTransportPrompt(admitted, engineMaterial);