@akagilnc/pi-workflow-roles 0.1.3771 → 0.1.3783

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.
@@ -8756,24 +8756,35 @@ var init_invocation = __esm({
8756
8756
  var host_descriptions_exports = {};
8757
8757
  __export(host_descriptions_exports, {
8758
8758
  DEFAULT_ROLE_TURN_HOST: () => DEFAULT_ROLE_TURN_HOST,
8759
+ HEADLESS_HOST_DESCRIPTIONS: () => HEADLESS_HOST_DESCRIPTIONS,
8759
8760
  HOST_DESCRIPTIONS: () => HOST_DESCRIPTIONS,
8760
8761
  assertRegisteredHostName: () => assertRegisteredHostName,
8762
+ lookupHeadlessHostDescription: () => lookupHeadlessHostDescription,
8761
8763
  lookupHostDescription: () => lookupHostDescription,
8764
+ lookupHostFamily: () => lookupHostFamily,
8762
8765
  packagedExternalHostNames: () => packagedExternalHostNames
8763
8766
  });
8764
8767
  function lookupHostDescription(host) {
8765
8768
  return Object.hasOwn(HOST_DESCRIPTIONS, host) ? HOST_DESCRIPTIONS[host] : void 0;
8766
8769
  }
8770
+ function lookupHeadlessHostDescription(host) {
8771
+ return Object.hasOwn(HEADLESS_HOST_DESCRIPTIONS, host) ? HEADLESS_HOST_DESCRIPTIONS[host] : void 0;
8772
+ }
8773
+ function lookupHostFamily(host) {
8774
+ if (lookupHostDescription(host) !== void 0) return "acp";
8775
+ if (lookupHeadlessHostDescription(host) !== void 0) return "headless";
8776
+ return void 0;
8777
+ }
8767
8778
  function packagedExternalHostNames() {
8768
- return Object.keys(HOST_DESCRIPTIONS);
8779
+ return [...Object.keys(HOST_DESCRIPTIONS), ...Object.keys(HEADLESS_HOST_DESCRIPTIONS)];
8769
8780
  }
8770
8781
  function assertRegisteredHostName(host) {
8771
- if (host === DEFAULT_ROLE_TURN_HOST || lookupHostDescription(host) !== void 0) {
8782
+ if (host === DEFAULT_ROLE_TURN_HOST || lookupHostFamily(host) !== void 0) {
8772
8783
  return host;
8773
8784
  }
8774
8785
  throw new Error(`unregistered host: ${host}`);
8775
8786
  }
8776
- var PRIVATE_COMPAT_ENV, DEFAULT_ROLE_TURN_HOST, HOST_DESCRIPTIONS;
8787
+ var PRIVATE_COMPAT_ENV, DEFAULT_ROLE_TURN_HOST, HOST_DESCRIPTIONS, HEADLESS_HOST_DESCRIPTIONS;
8777
8788
  var init_host_descriptions = __esm({
8778
8789
  "src/host-descriptions.ts"() {
8779
8790
  "use strict";
@@ -8825,14 +8836,37 @@ var init_host_descriptions = __esm({
8825
8836
  })
8826
8837
  })
8827
8838
  });
8839
+ HEADLESS_HOST_DESCRIPTIONS = Object.freeze({
8840
+ "claude": Object.freeze({
8841
+ binaryFromHome: Object.freeze([".local", "bin", "claude"]),
8842
+ sessionBindingFile: "claude-headless-session.json",
8843
+ fixedArgs: Object.freeze([
8844
+ // One result envelope (not stream-json): typed receipt only; no event-stream copy.
8845
+ "--output-format",
8846
+ "json",
8847
+ "--permission-mode",
8848
+ "bypassPermissions",
8849
+ // Empty sources: no user/project/local operator surface (envelope owns materials).
8850
+ "--setting-sources",
8851
+ "",
8852
+ // With adapter-supplied --mcp-config only (AK relay); drops operator + claude.ai MCP.
8853
+ "--strict-mcp-config"
8854
+ ]),
8855
+ promptFlag: "-p",
8856
+ modelFlag: "--model",
8857
+ effortFlag: "--effort",
8858
+ // File path keeps large role envelopes off ARG_MAX.
8859
+ systemPromptFlag: "--system-prompt-file",
8860
+ jsonSchemaFlag: "--json-schema",
8861
+ mcpConfigFlag: "--mcp-config",
8862
+ sessionIdFlag: "--session-id",
8863
+ resumeFlag: "--resume"
8864
+ })
8865
+ });
8828
8866
  }
8829
8867
  });
8830
8868
 
8831
8869
  // src/public-cli/load-production-acp-host.ts
8832
- var load_production_acp_host_exports = {};
8833
- __export(load_production_acp_host_exports, {
8834
- loadProductionAcpHostFactory: () => loadProductionAcpHostFactory
8835
- });
8836
8870
  import { existsSync as existsSync5 } from "node:fs";
8837
8871
  import { join as join14 } from "node:path";
8838
8872
  import { pathToFileURL } from "node:url";
@@ -8856,6 +8890,54 @@ var init_load_production_acp_host = __esm({
8856
8890
  }
8857
8891
  });
8858
8892
 
8893
+ // src/public-cli/load-production-headless-host.ts
8894
+ import { existsSync as existsSync6 } from "node:fs";
8895
+ import { join as join15 } from "node:path";
8896
+ import { pathToFileURL as pathToFileURL2 } from "node:url";
8897
+ async function loadProductionHeadlessHostFactory(packageRoot, host) {
8898
+ const description = lookupHeadlessHostDescription(host);
8899
+ if (description === void 0) {
8900
+ throw new Error(`unregistered headless host: ${host}`);
8901
+ }
8902
+ const built = join15(packageRoot, "dist/headless-host/production-host.js");
8903
+ const source = join15(packageRoot, "src/headless-host/production-host.ts");
8904
+ const target = existsSync6(built) ? built : source;
8905
+ const href = pathToFileURL2(target).href;
8906
+ const mod = await import(href);
8907
+ const create = mod.createProductionHeadlessRoleTurnHost;
8908
+ return (options) => create({ ...options, description });
8909
+ }
8910
+ var init_load_production_headless_host = __esm({
8911
+ "src/public-cli/load-production-headless-host.ts"() {
8912
+ "use strict";
8913
+ init_host_descriptions();
8914
+ }
8915
+ });
8916
+
8917
+ // src/public-cli/load-production-external-host.ts
8918
+ var load_production_external_host_exports = {};
8919
+ __export(load_production_external_host_exports, {
8920
+ loadProductionExternalHostFactory: () => loadProductionExternalHostFactory
8921
+ });
8922
+ async function loadProductionExternalHostFactory(packageRoot, host) {
8923
+ const family = lookupHostFamily(host);
8924
+ if (family === "acp") {
8925
+ return loadProductionAcpHostFactory(packageRoot, host);
8926
+ }
8927
+ if (family === "headless") {
8928
+ return loadProductionHeadlessHostFactory(packageRoot, host);
8929
+ }
8930
+ throw new Error(`unregistered host: ${host}`);
8931
+ }
8932
+ var init_load_production_external_host = __esm({
8933
+ "src/public-cli/load-production-external-host.ts"() {
8934
+ "use strict";
8935
+ init_host_descriptions();
8936
+ init_load_production_acp_host();
8937
+ init_load_production_headless_host();
8938
+ }
8939
+ });
8940
+
8859
8941
  // src/public-cli/host-providers.ts
8860
8942
  var host_providers_exports = {};
8861
8943
  __export(host_providers_exports, {
@@ -8870,15 +8952,15 @@ __export(host_providers_exports, {
8870
8952
  renderHostProvidersTable: () => renderHostProvidersTable
8871
8953
  });
8872
8954
  import { readFileSync as readFileSync2 } from "node:fs";
8873
- import { join as join15 } from "node:path";
8955
+ import { join as join16 } from "node:path";
8874
8956
  function hostProvidersPath(home) {
8875
8957
  if (typeof home !== "string" || home.trim() === "") {
8876
8958
  throw new Error("home must be explicitly provided");
8877
8959
  }
8878
- return join15(home, ".ak-roles", "host-providers.json");
8960
+ return join16(home, ".ak-roles", "host-providers.json");
8879
8961
  }
8880
8962
  function hermesProviderModelsCachePath(home) {
8881
- return join15(home, ".hermes", "provider_models_cache.json");
8963
+ return join16(home, ".hermes", "provider_models_cache.json");
8882
8964
  }
8883
8965
  function parseHostProvidersTable(value) {
8884
8966
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
@@ -9445,7 +9527,7 @@ __export(config_exports, {
9445
9527
  validatePublicCliConfigAxes: () => validatePublicCliConfigAxes
9446
9528
  });
9447
9529
  import { mkdir as mkdir2, readFile as readFile10, writeFile as writeFile5 } from "node:fs/promises";
9448
- import { dirname as dirname8, join as join16 } from "node:path";
9530
+ import { dirname as dirname8, join as join17 } from "node:path";
9449
9531
  function isGateOfficerSeat(value) {
9450
9532
  return GATE_OFFICER_SEATS.includes(value);
9451
9533
  }
@@ -9453,7 +9535,7 @@ function publicCliConfigPath(home) {
9453
9535
  if (typeof home !== "string" || home.trim() === "") {
9454
9536
  throw new Error("home must be explicitly provided");
9455
9537
  }
9456
- return join16(home, ".ak-roles", "public-cli.json");
9538
+ return join17(home, ".ak-roles", "public-cli.json");
9457
9539
  }
9458
9540
  async function loadPublicCliConfig(home) {
9459
9541
  const path = publicCliConfigPath(home);
@@ -9862,7 +9944,7 @@ function credentialProvidersFromAuthData(data) {
9862
9944
  }
9863
9945
  async function loadCredentialProviders(agentDir) {
9864
9946
  try {
9865
- const raw = await readFile10(join16(agentDir, "auth.json"), "utf8");
9947
+ const raw = await readFile10(join17(agentDir, "auth.json"), "utf8");
9866
9948
  return credentialProvidersFromAuthData(JSON.parse(raw));
9867
9949
  } catch (error) {
9868
9950
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -10004,7 +10086,7 @@ var init_ticket_provenance_contracts = __esm({
10004
10086
  // src/ticket-provenance.ts
10005
10087
  import { createHash as createHash5 } from "node:crypto";
10006
10088
  import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "node:fs";
10007
- import { join as join17 } from "node:path";
10089
+ import { join as join18 } from "node:path";
10008
10090
  function ticketProvenanceSubject(ticketNumber) {
10009
10091
  if (!Number.isSafeInteger(ticketNumber) || ticketNumber < 1) {
10010
10092
  throw new Error(`ticket-provenance subject requires a positive ticket number, got ${String(ticketNumber)}`);
@@ -10062,7 +10144,7 @@ function resolveTicketProvenanceVolume(ticketNumber, cwd, home) {
10062
10144
  return {
10063
10145
  recordFile: path.recordFile,
10064
10146
  volumeDir: path.sessionDir,
10065
- humanViewFile: join17(path.sessionDir, TICKET_PROVENANCE_HUMAN_VIEW)
10147
+ humanViewFile: join18(path.sessionDir, TICKET_PROVENANCE_HUMAN_VIEW)
10066
10148
  };
10067
10149
  }
10068
10150
  async function readTicketProvenance(ticketNumber, cwd, home) {
@@ -10206,7 +10288,7 @@ var init_case_dossier_delivery = __esm({
10206
10288
 
10207
10289
  // src/host-transition-prior-native.ts
10208
10290
  import { access as access2, readdir as readdir3 } from "node:fs/promises";
10209
- import { dirname as dirname9, join as join18 } from "node:path";
10291
+ import { dirname as dirname9, join as join19 } from "node:path";
10210
10292
  function isEnoent2(error) {
10211
10293
  return typeof error === "object" && error !== null && error.code === "ENOENT";
10212
10294
  }
@@ -10231,7 +10313,7 @@ async function listSitianRecordPaths(sessionParent) {
10231
10313
  const recordPaths = [];
10232
10314
  for (const entry of entries) {
10233
10315
  if (!entry.isDirectory()) continue;
10234
- const recordFile = join18(sessionRoot, entry.name, "records.jsonl");
10316
+ const recordFile = join19(sessionRoot, entry.name, "records.jsonl");
10235
10317
  try {
10236
10318
  await access2(recordFile);
10237
10319
  recordPaths.push(recordFile);
@@ -10298,7 +10380,7 @@ var init_public_run_credentials = __esm({
10298
10380
  });
10299
10381
 
10300
10382
  // src/run-terminal-artifacts.ts
10301
- import { basename as basename6, dirname as dirname10, join as join19 } from "node:path";
10383
+ import { basename as basename6, dirname as dirname10, join as join20 } from "node:path";
10302
10384
  function runIdFromRunDirectory(runDirectory) {
10303
10385
  const name = basename6(runDirectory);
10304
10386
  const at = name.lastIndexOf("@");
@@ -10702,7 +10784,7 @@ var init_ledger_session_read = __esm({
10702
10784
 
10703
10785
  // src/analyst-gate-cycles-read.ts
10704
10786
  import { readdir as readdir4 } from "node:fs/promises";
10705
- import { join as join20 } from "node:path";
10787
+ import { join as join21 } from "node:path";
10706
10788
  function isRecord13(value) {
10707
10789
  return typeof value === "object" && value !== null && !Array.isArray(value);
10708
10790
  }
@@ -10964,7 +11046,7 @@ async function readAnalystGateCyclesFromAuditorRoles(auditorRolesDirectory, opti
10964
11046
  throw error;
10965
11047
  }
10966
11048
  for (const name of names) {
10967
- const path = join20(directory, name);
11049
+ const path = join21(directory, name);
10968
11050
  const fromPointer = name.endsWith(".pointer.json");
10969
11051
  const sessionPath = fromPointer ? await resolveOfficerSessionFromPointerFile(path) : path;
10970
11052
  if (sessionPath === void 0) continue;
@@ -11006,14 +11088,14 @@ var init_analyst_gate_cycles_read = __esm({
11006
11088
  });
11007
11089
 
11008
11090
  // src/session-opening-materials.ts
11009
- import { existsSync as existsSync6 } from "node:fs";
11091
+ import { existsSync as existsSync7 } from "node:fs";
11010
11092
  import { readFile as readFile12 } from "node:fs/promises";
11011
- import { dirname as dirname11, join as join21 } from "node:path";
11012
- import { fileURLToPath, pathToFileURL as pathToFileURL2 } from "node:url";
11093
+ import { dirname as dirname11, join as join22 } from "node:path";
11094
+ import { fileURLToPath, pathToFileURL as pathToFileURL3 } from "node:url";
11013
11095
  function resolvePackageRootDir(moduleUrl = import.meta.url) {
11014
11096
  let dir = dirname11(fileURLToPath(moduleUrl));
11015
11097
  for (let i = 0; i < 8; i += 1) {
11016
- if (existsSync6(join21(dir, "package.json")) && existsSync6(join21(dir, "souls"))) {
11098
+ if (existsSync7(join22(dir, "package.json")) && existsSync7(join22(dir, "souls"))) {
11017
11099
  return dir;
11018
11100
  }
11019
11101
  const parent = dirname11(dir);
@@ -11043,7 +11125,7 @@ var init_session_opening_materials = __esm({
11043
11125
  "src/session-opening-materials.ts"() {
11044
11126
  "use strict";
11045
11127
  init_packaged_role_registry();
11046
- packageRootUrl = pathToFileURL2(resolvePackageRootDir() + "/").href;
11128
+ packageRootUrl = pathToFileURL3(resolvePackageRootDir() + "/").href;
11047
11129
  MAIN_ROLE_SESSION_MATERIALS = {
11048
11130
  ...Object.fromEntries(
11049
11131
  PUBLIC_ROLE_RECORDS.map((record4) => [record4.role, record4.sessionMaterials])
@@ -11885,12 +11967,12 @@ var init_reviewer_dispatch = __esm({
11885
11967
  // src/public-cli/reviewer-dispatch-rejection.ts
11886
11968
  import { writeFileSync as writeFileSync4 } from "node:fs";
11887
11969
  import { readFile as readFile13, unlink as unlink3 } from "node:fs/promises";
11888
- import { join as join22 } from "node:path";
11970
+ import { join as join23 } from "node:path";
11889
11971
  function isReviewerPreflightViolation(value) {
11890
11972
  return typeof value === "string" && REVIEWER_PREFLIGHT_VIOLATIONS.includes(value);
11891
11973
  }
11892
11974
  function reviewerDispatchRejectionPath(runDirectory) {
11893
- return join22(runDirectory, REVIEWER_DISPATCH_REJECTION_FILE);
11975
+ return join23(runDirectory, REVIEWER_DISPATCH_REJECTION_FILE);
11894
11976
  }
11895
11977
  function recordReviewerDispatchRejectionSync(runDirectory, rejection) {
11896
11978
  writeFileSync4(
@@ -13312,7 +13394,7 @@ var init_collector_ledger = __esm({
13312
13394
  // src/package-resources/method-skill.ts
13313
13395
  import { createHash as createHash7 } from "node:crypto";
13314
13396
  import { readFile as readFile14, realpath as realpath7 } from "node:fs/promises";
13315
- import { join as join23 } from "node:path";
13397
+ import { join as join24 } from "node:path";
13316
13398
  function gitBlobOid(bytes) {
13317
13399
  const body = typeof bytes === "string" ? Buffer.from(bytes, "utf8") : Buffer.from(bytes);
13318
13400
  const header = Buffer.from(`blob ${body.byteLength}\0`, "utf8");
@@ -13329,10 +13411,10 @@ function packagedMethodSkillRelativeDirectory(name) {
13329
13411
  return `${METHOD_SKILL_RELATIVE_ROOT}/${name}`;
13330
13412
  }
13331
13413
  function resolvePackagedMethodSkillRoot(packageRoot, name) {
13332
- return join23(packageRoot, packagedMethodSkillRelativeDirectory(name));
13414
+ return join24(packageRoot, packagedMethodSkillRelativeDirectory(name));
13333
13415
  }
13334
13416
  function resolvePackagedMethodSkillPath(packageRoot, name) {
13335
- return join23(resolvePackagedMethodSkillRoot(packageRoot, name), "SKILL.md");
13417
+ return join24(resolvePackagedMethodSkillRoot(packageRoot, name), "SKILL.md");
13336
13418
  }
13337
13419
  function isRecord14(value) {
13338
13420
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -13426,8 +13508,8 @@ function parseProvenance(raw, expectedName) {
13426
13508
  }
13427
13509
  async function loadPackagedMethodSkillMaterial(packageRoot, name) {
13428
13510
  const rootDirectory = resolvePackagedMethodSkillRoot(packageRoot, name);
13429
- const skillPathConfigured = join23(rootDirectory, "SKILL.md");
13430
- const provenancePath = join23(rootDirectory, "provenance.json");
13511
+ const skillPathConfigured = join24(rootDirectory, "SKILL.md");
13512
+ const provenancePath = join24(rootDirectory, "provenance.json");
13431
13513
  let provenanceRaw;
13432
13514
  try {
13433
13515
  provenanceRaw = await readFile14(provenancePath, "utf8");
@@ -13444,7 +13526,7 @@ async function loadPackagedMethodSkillMaterial(packageRoot, name) {
13444
13526
  }
13445
13527
  const provenance = parseProvenance(provenanceJson, name);
13446
13528
  for (const [rel, expected] of Object.entries(provenance.files)) {
13447
- const absolute = join23(rootDirectory, rel);
13529
+ const absolute = join24(rootDirectory, rel);
13448
13530
  let bytes;
13449
13531
  try {
13450
13532
  bytes = await readFile14(absolute);
@@ -13960,7 +14042,7 @@ var init_terminal = __esm({
13960
14042
  // src/public-cli/settlement.ts
13961
14043
  import { randomUUID as randomUUID3 } from "node:crypto";
13962
14044
  import { appendFile as appendFile2, readFile as readFile15, readdir as readdir5, writeFile as writeFile6 } from "node:fs/promises";
13963
- import { dirname as dirname12, join as join24 } from "node:path";
14045
+ import { dirname as dirname12, join as join25 } from "node:path";
13964
14046
  function sealedLedgerHome(admitted) {
13965
14047
  return homeFromRunDirectory(admitted.runDirectory);
13966
14048
  }
@@ -14375,7 +14457,7 @@ async function readSessionProviderStop(sessionFile) {
14375
14457
  }
14376
14458
  }
14377
14459
  async function readBoundEvidenceChildKnownFailure(sessionFile) {
14378
- const childDirectory = join24(dirname12(sessionFile), "evidence-children");
14460
+ const childDirectory = join25(dirname12(sessionFile), "evidence-children");
14379
14461
  let names;
14380
14462
  try {
14381
14463
  names = await readdir5(childDirectory);
@@ -14386,7 +14468,7 @@ async function readBoundEvidenceChildKnownFailure(sessionFile) {
14386
14468
  for (const file of names.filter((name) => name.endsWith(".jsonl")).sort().reverse()) {
14387
14469
  let entries;
14388
14470
  try {
14389
- entries = await readBoundSessionEntries(join24(childDirectory, file));
14471
+ entries = await readBoundSessionEntries(join25(childDirectory, file));
14390
14472
  } catch (error) {
14391
14473
  throw sessionReadFailure(error, "failed to read discovered evidence-child session");
14392
14474
  }
@@ -14440,7 +14522,7 @@ async function loadBoundAuditorVolumes(sessionFile) {
14440
14522
  latestParentUserIndex = i;
14441
14523
  break;
14442
14524
  }
14443
- const childDirectories = [join24(dirname12(sessionFile), "auditor-roles")];
14525
+ const childDirectories = [join25(dirname12(sessionFile), "auditor-roles")];
14444
14526
  const valid = [];
14445
14527
  let sawAnyDirectory = false;
14446
14528
  for (const childDirectory of childDirectories) {
@@ -14455,7 +14537,7 @@ async function loadBoundAuditorVolumes(sessionFile) {
14455
14537
  for (const file of names.filter((name) => name.endsWith(".jsonl")).sort().reverse()) {
14456
14538
  let entries;
14457
14539
  try {
14458
- entries = await readBoundSessionEntries(join24(childDirectory, file));
14540
+ entries = await readBoundSessionEntries(join25(childDirectory, file));
14459
14541
  } catch (error) {
14460
14542
  throw sessionReadFailure(error, "failed to read discovered auditor session");
14461
14543
  }
@@ -14971,8 +15053,8 @@ function projectTerminalGateFact(rounds) {
14971
15053
  };
14972
15054
  }
14973
15055
  async function extractGateFactFromSessionDirectory(sessionDirectory, options = {}) {
14974
- const directories = [join24(sessionDirectory, "auditor-roles")];
14975
- const parentSessionFile = options.parentSessionFile ?? join24(sessionDirectory, "session.jsonl");
15056
+ const directories = [join25(sessionDirectory, "auditor-roles")];
15057
+ const parentSessionFile = options.parentSessionFile ?? join25(sessionDirectory, "session.jsonl");
14976
15058
  const rounds = await readAnalystGateCyclesFromAuditorRoles(directories, {
14977
15059
  parentSessionFile
14978
15060
  });
@@ -15070,8 +15152,8 @@ async function extractNavigatorFactFromAdmittedSession(sessionFile) {
15070
15152
  async function publishJudgeArtifacts(admitted, roleOutcome, coordinates) {
15071
15153
  await appendRunAttemptHistory({ role: admitted.role, runId: admitted.runId, sessionFile: coordinates.sessionFile }, roleOutcome);
15072
15154
  const artifactsDir = await ensureRunArtifactsDir(admitted.runDirectory);
15073
- const reportPath = join24(artifactsDir, "report.json");
15074
- const evidencePath = join24(artifactsDir, "evidence.json");
15155
+ const reportPath = join25(artifactsDir, "report.json");
15156
+ const evidencePath = join25(artifactsDir, "evidence.json");
15075
15157
  await writeFile6(
15076
15158
  reportPath,
15077
15159
  `${JSON.stringify(
@@ -15161,8 +15243,8 @@ async function trySettleJudgeTerminalResult(admitted, authority) {
15161
15243
  async function publishDoctorArtifacts(admitted, roleOutcome, coordinates, options = {}) {
15162
15244
  await appendRunAttemptHistory({ role: admitted.role, runId: admitted.runId, sessionFile: coordinates.sessionFile }, roleOutcome);
15163
15245
  const artifactsDir = await ensureRunArtifactsDir(admitted.runDirectory);
15164
- const reportPath = join24(artifactsDir, "report.json");
15165
- const evidencePath = join24(artifactsDir, "evidence.json");
15246
+ const reportPath = join25(artifactsDir, "report.json");
15247
+ const evidencePath = join25(artifactsDir, "evidence.json");
15166
15248
  await writeFile6(
15167
15249
  reportPath,
15168
15250
  `${JSON.stringify(
@@ -15395,7 +15477,7 @@ function uniqueFailureFallbackDirs(runDirectory, baseDir) {
15395
15477
  return dirs;
15396
15478
  }
15397
15479
  async function resolveFailureArtifactsBase(runDirectory) {
15398
- const artifactsDir = join24(runDirectory, "artifacts");
15480
+ const artifactsDir = join25(runDirectory, "artifacts");
15399
15481
  try {
15400
15482
  await ensureRunArtifactsDir(runDirectory);
15401
15483
  return { baseDir: artifactsDir };
@@ -15411,7 +15493,7 @@ async function writeFailureJsonRetainingCause(preferredCandidates, uniqueFallbac
15411
15493
  const candidates = [
15412
15494
  ...preferredCandidates,
15413
15495
  // One unique name per fallback dir — collisions on fixed names cannot exhaust this.
15414
- ...uniqueFallbackDirs.map((dir) => join24(dir, `${stem}.${randomUUID3()}.json`))
15496
+ ...uniqueFallbackDirs.map((dir) => join25(dir, `${stem}.${randomUUID3()}.json`))
15415
15497
  ];
15416
15498
  for (let i = 0; i < candidates.length; i += 1) {
15417
15499
  const path = candidates[i];
@@ -15456,26 +15538,26 @@ async function publishFailureArtifacts(admitted, failure2, authority) {
15456
15538
  } catch (error) {
15457
15539
  priorIssues.push(publicationAttemptFromError(sessionFile, error));
15458
15540
  }
15459
- const underArtifacts = baseDir === join24(admitted.runDirectory, "artifacts");
15541
+ const underArtifacts = baseDir === join25(admitted.runDirectory, "artifacts");
15460
15542
  const uniqueFallbackDirs = uniqueFailureFallbackDirs(
15461
15543
  admitted.runDirectory,
15462
15544
  baseDir
15463
15545
  );
15464
15546
  const errorCandidates = underArtifacts ? [
15465
- join24(baseDir, "error.json"),
15466
- join24(baseDir, "error.settlement.json"),
15467
- join24(admitted.runDirectory, "error.settlement.json")
15547
+ join25(baseDir, "error.json"),
15548
+ join25(baseDir, "error.settlement.json"),
15549
+ join25(admitted.runDirectory, "error.settlement.json")
15468
15550
  ] : [
15469
- join24(baseDir, "error.settlement.json"),
15470
- join24(baseDir, "error.json")
15551
+ join25(baseDir, "error.settlement.json"),
15552
+ join25(baseDir, "error.json")
15471
15553
  ];
15472
15554
  const evidenceCandidates = underArtifacts ? [
15473
- join24(baseDir, "evidence.json"),
15474
- join24(baseDir, "evidence.settlement.json"),
15475
- join24(admitted.runDirectory, "evidence.settlement.json")
15555
+ join25(baseDir, "evidence.json"),
15556
+ join25(baseDir, "evidence.settlement.json"),
15557
+ join25(admitted.runDirectory, "evidence.settlement.json")
15476
15558
  ] : [
15477
- join24(baseDir, "evidence.settlement.json"),
15478
- join24(baseDir, "evidence.json")
15559
+ join25(baseDir, "evidence.settlement.json"),
15560
+ join25(baseDir, "evidence.json")
15479
15561
  ];
15480
15562
  const errorPayloadBase = {
15481
15563
  kind: "error",
@@ -15765,7 +15847,7 @@ var init_settlement = __esm({
15765
15847
  import { constants as fsConstants } from "node:fs";
15766
15848
  import { randomUUID as randomUUID4 } from "node:crypto";
15767
15849
  import { lstat as lstat5, mkdir as mkdir4, open as open2 } from "node:fs/promises";
15768
- import { join as join25 } from "node:path";
15850
+ import { join as join26 } from "node:path";
15769
15851
  function presentTerminal(terminal, io) {
15770
15852
  if (terminal.roleOutcome.kind === "failure" || terminal.roleOutcome.kind === "no_receipt") {
15771
15853
  presentFailureTerminal(terminal, io);
@@ -15784,7 +15866,7 @@ async function finalizeExceptionRunBestEffort(runDirectory, io) {
15784
15866
  }
15785
15867
  }
15786
15868
  function runArtifactsDirectory(runDirectory) {
15787
- return join25(runDirectory, "artifacts");
15869
+ return join26(runDirectory, "artifacts");
15788
15870
  }
15789
15871
  async function ensureRealArtifactsDirectory(runDirectory) {
15790
15872
  const runStat = await lstat5(runDirectory);
@@ -15867,7 +15949,7 @@ function jsonSafeReplacer() {
15867
15949
  }
15868
15950
  async function retainDispatchError(admitted, principalAuthority, sessionAppender, attempt, error) {
15869
15951
  const artifactsDir = await ensureRealArtifactsDirectory(admitted.runDirectory);
15870
- const filePath = join25(
15952
+ const filePath = join26(
15871
15953
  artifactsDir,
15872
15954
  `dispatch-error-attempt-${attempt}-${randomUUID4()}.json`
15873
15955
  );
@@ -16116,7 +16198,7 @@ var init_auto_resume = __esm({
16116
16198
  // src/public-cli/post-admission.ts
16117
16199
  import { randomUUID as randomUUID5 } from "node:crypto";
16118
16200
  import { readFile as readFile16, writeFile as writeFile7 } from "node:fs/promises";
16119
- import { isAbsolute as isAbsolute7, join as join26, resolve as resolve11 } from "node:path";
16201
+ import { isAbsolute as isAbsolute7, join as join27, resolve as resolve11 } from "node:path";
16120
16202
  function appendContinuationSection(continuation, section) {
16121
16203
  const prompt = `${continuation.prompt}
16122
16204
 
@@ -16125,7 +16207,7 @@ ${section}`;
16125
16207
  }
16126
16208
  async function readInvocationHost(runDirectory) {
16127
16209
  try {
16128
- const raw = JSON.parse(await readFile16(join26(runDirectory, "invocation.json"), "utf8"));
16210
+ const raw = JSON.parse(await readFile16(join27(runDirectory, "invocation.json"), "utf8"));
16129
16211
  return typeof raw.host === "string" && raw.host.trim() !== "" ? raw.host : void 0;
16130
16212
  } catch (error) {
16131
16213
  if (error.code === "ENOENT") return void 0;
@@ -16279,7 +16361,7 @@ async function dispatchPostAdmissionTurn(input) {
16279
16361
  }
16280
16362
  try {
16281
16363
  await writeFile7(
16282
- join26(admitted.runDirectory, "stderr.log"),
16364
+ join27(admitted.runDirectory, "stderr.log"),
16283
16365
  result.stderr,
16284
16366
  "utf8"
16285
16367
  );
@@ -16388,7 +16470,7 @@ function resumeTurnRequestProjectionOptions(admitted, request, env, summonsPrepa
16388
16470
  }
16389
16471
  function isAlreadyFrozenSummonsAttachment(runDirectory, attachmentPath) {
16390
16472
  const absolute = isAbsolute7(attachmentPath) ? attachmentPath : resolve11(attachmentPath);
16391
- return pathContainedIn(join26(runDirectory, "attachments"), absolute);
16473
+ return pathContainedIn(join27(runDirectory, "attachments"), absolute);
16392
16474
  }
16393
16475
  async function prepareSummonsResumeMaterials(runDirectory, summons) {
16394
16476
  if (summons === void 0) return void 0;
@@ -17573,8 +17655,8 @@ __export(public_role_summons_exports, {
17573
17655
  summonGateOfficer: () => summonGateOfficer,
17574
17656
  summonPublicRole: () => summonPublicRole
17575
17657
  });
17576
- import { existsSync as existsSync7 } from "node:fs";
17577
- import { join as join27 } from "node:path";
17658
+ import { existsSync as existsSync8 } from "node:fs";
17659
+ import { join as join28 } from "node:path";
17578
17660
  function createCapturingIo() {
17579
17661
  const chunks = [];
17580
17662
  return {
@@ -17597,7 +17679,7 @@ function parentDir(path) {
17597
17679
  function walkPackageRoot(start) {
17598
17680
  let dir = start;
17599
17681
  for (let i = 0; i < 12; i += 1) {
17600
- if (existsSync7(join27(dir, "package.json")) && existsSync7(join27(dir, "souls"))) {
17682
+ if (existsSync8(join28(dir, "package.json")) && existsSync8(join28(dir, "souls"))) {
17601
17683
  return dir;
17602
17684
  }
17603
17685
  const parent = parentDir(dir);
@@ -17673,9 +17755,9 @@ async function createSummonEnv(options) {
17673
17755
  const hostName = options.seat.host ?? "pi";
17674
17756
  let roleTurnHost = piHost;
17675
17757
  if (hostName !== "pi") {
17676
- const { lookupHostDescription: lookupHostDescription2 } = await Promise.resolve().then(() => (init_host_descriptions(), host_descriptions_exports));
17677
- const { loadProductionAcpHostFactory: loadProductionAcpHostFactory2 } = await Promise.resolve().then(() => (init_load_production_acp_host(), load_production_acp_host_exports));
17678
- if (lookupHostDescription2(hostName) === void 0) {
17758
+ const { lookupHostFamily: lookupHostFamily2 } = await Promise.resolve().then(() => (init_host_descriptions(), host_descriptions_exports));
17759
+ const { loadProductionExternalHostFactory: loadProductionExternalHostFactory2 } = await Promise.resolve().then(() => (init_load_production_external_host(), load_production_external_host_exports));
17760
+ if (lookupHostFamily2(hostName) === void 0) {
17679
17761
  throw new Error(
17680
17762
  `public role summons host unregistered: host=${hostName} seat=${options.role}`
17681
17763
  );
@@ -17683,7 +17765,7 @@ async function createSummonEnv(options) {
17683
17765
  let hostPromise;
17684
17766
  roleTurnHost = {
17685
17767
  executeTurn: async (request) => {
17686
- hostPromise ??= loadProductionAcpHostFactory2(options.packageRoot, hostName).then(
17768
+ hostPromise ??= loadProductionExternalHostFactory2(options.packageRoot, hostName).then(
17687
17769
  (create) => create({
17688
17770
  packageRoot: options.packageRoot,
17689
17771
  principalAuthority
@@ -17717,7 +17799,7 @@ async function createSummonEnv(options) {
17717
17799
  async function summonPublicRole(options) {
17718
17800
  const packageRoot = resolveSummonsPackageRoot(options.packageRoot);
17719
17801
  const home = await resolveSummonHome(options);
17720
- const agentDir = options.agentDir ?? process.env.PI_CODING_AGENT_DIR ?? join27(home, ".pi", "agent");
17802
+ const agentDir = options.agentDir ?? process.env.PI_CODING_AGENT_DIR ?? join28(home, ".pi", "agent");
17721
17803
  const {
17722
17804
  loadCredentialProviders: loadCredentialProviders2,
17723
17805
  loadPublicCliConfig: loadPublicCliConfig2,
@@ -17725,7 +17807,8 @@ async function summonPublicRole(options) {
17725
17807
  } = await Promise.resolve().then(() => (init_config(), config_exports));
17726
17808
  const credentials = options.credentials ?? await loadCredentialProviders2(agentDir);
17727
17809
  const config = await loadPublicCliConfig2(home);
17728
- const seat = resolveEffectiveSeat2(config, options.role, credentials);
17810
+ const invocation = options.host === void 0 ? void 0 : { host: options.host };
17811
+ const seat = resolveEffectiveSeat2(config, options.role, credentials, invocation);
17729
17812
  const env = {
17730
17813
  ...await createSummonEnv({
17731
17814
  role: options.role,
@@ -17837,6 +17920,38 @@ async function summonPublicRole(options) {
17837
17920
  ...stderr === void 0 || stderr === "" ? {} : { stderr }
17838
17921
  };
17839
17922
  }
17923
+ async function parentInvocationHost(sourceRunDirectory) {
17924
+ const { readFile: readFile21 } = await import("node:fs/promises");
17925
+ const path = join28(sourceRunDirectory, "invocation.json");
17926
+ let text;
17927
+ try {
17928
+ text = await readFile21(path, "utf8");
17929
+ } catch (error) {
17930
+ const code = error instanceof Error && "code" in error ? error.code : void 0;
17931
+ throw new Error(
17932
+ `parent invocation.json required for gate source run at ${path}: ${code ?? (error instanceof Error ? error.message : String(error))}`,
17933
+ { cause: error }
17934
+ );
17935
+ }
17936
+ let raw;
17937
+ try {
17938
+ raw = JSON.parse(text);
17939
+ } catch (error) {
17940
+ throw new Error(
17941
+ `parent invocation.json unreadable at ${path}: ${error instanceof Error ? error.message : String(error)}`,
17942
+ { cause: error }
17943
+ );
17944
+ }
17945
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
17946
+ throw new Error(`parent invocation.json has non-object shape at ${path}`);
17947
+ }
17948
+ const host = raw.host;
17949
+ if (host === void 0) return void 0;
17950
+ if (typeof host !== "string" || host.trim() === "") {
17951
+ throw new Error(`parent invocation.json host must be a non-empty string at ${path}`);
17952
+ }
17953
+ return host;
17954
+ }
17840
17955
  async function summonGateOfficer(options) {
17841
17956
  let home = options.home;
17842
17957
  if (home === void 0) {
@@ -17850,6 +17965,7 @@ async function summonGateOfficer(options) {
17850
17965
  submission: options.submission
17851
17966
  });
17852
17967
  }
17968
+ const parentHost = await parentInvocationHost(options.sourceRunDirectory);
17853
17969
  const common = {
17854
17970
  cwd: options.cwd,
17855
17971
  ...home === void 0 ? {} : { home },
@@ -17858,6 +17974,7 @@ async function summonGateOfficer(options) {
17858
17974
  ...options.signal === void 0 ? {} : { signal: options.signal },
17859
17975
  ...options.reask === void 0 ? {} : { reviewReask: options.reask },
17860
17976
  ...gateReviewInstruction === void 0 ? {} : { gateReviewInstruction },
17977
+ ...parentHost === void 0 ? {} : { host: parentHost },
17861
17978
  ...options.roleTurnHost === void 0 ? {} : { roleTurnHost: options.roleTurnHost },
17862
17979
  ...options.createRunId === void 0 ? {} : { createRunId: options.createRunId }
17863
17980
  };
@@ -18023,7 +18140,7 @@ var init_compliance_transport = __esm({
18023
18140
  });
18024
18141
 
18025
18142
  // src/dossier-resolution.ts
18026
- import { existsSync as existsSync8, statSync as statSync2 } from "node:fs";
18143
+ import { existsSync as existsSync9, statSync as statSync2 } from "node:fs";
18027
18144
  import { resolve as resolve12 } from "node:path";
18028
18145
  function resolveAuditDossier(env = process.env) {
18029
18146
  const raw = env[AUDIT_RUN_DIR_ENV];
@@ -18032,7 +18149,7 @@ function resolveAuditDossier(env = process.env) {
18032
18149
  }
18033
18150
  const runDirectory = resolve12(raw);
18034
18151
  try {
18035
- if (!existsSync8(runDirectory) || !statSync2(runDirectory).isDirectory()) {
18152
+ if (!existsSync9(runDirectory) || !statSync2(runDirectory).isDirectory()) {
18036
18153
  return { status: "incomplete", observation: { kind: "missing-dossier" } };
18037
18154
  }
18038
18155
  } catch {
@@ -18282,11 +18399,11 @@ var init_navigator_session_contracts = __esm({
18282
18399
 
18283
18400
  // src/archivist-record-topology.ts
18284
18401
  import { createHash as createHash8 } from "node:crypto";
18285
- import { join as join28 } from "node:path";
18402
+ import { join as join29 } from "node:path";
18286
18403
  function subjectKeyedRecordDirectory(input) {
18287
18404
  const ledgerHome = input.parentSessionFile !== void 0 && input.parentSessionFile.length > 0 ? resolveActivationLedgerHomeForPath(input.parentSessionFile) : resolveActivationLedgerHome(input.home);
18288
18405
  const digest = createHash8("sha256").update(input.subject).digest("hex").slice(0, 32);
18289
- return join28(
18406
+ return join29(
18290
18407
  activationBookDirectory(ledgerHome, resolveBookKeyFromGit(input.cwd)),
18291
18408
  input.kind,
18292
18409
  digest
@@ -18310,11 +18427,11 @@ __export(archivist_record_entry_exports, {
18310
18427
  createRecordSessionOpen: () => createRecordSessionOpen,
18311
18428
  subjectKeyedRecordDirectory: () => subjectKeyedRecordDirectory
18312
18429
  });
18313
- import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync3, realpathSync as realpathSync2, writeFileSync as writeFileSync5 } from "node:fs";
18314
- import { dirname as dirname13, resolve as resolve13, join as join29 } from "node:path";
18430
+ import { existsSync as existsSync10, mkdirSync as mkdirSync4, readFileSync as readFileSync3, realpathSync as realpathSync2, writeFileSync as writeFileSync5 } from "node:fs";
18431
+ import { dirname as dirname13, resolve as resolve13, join as join30 } from "node:path";
18315
18432
  import { SessionManager } from "@earendil-works/pi-coding-agent";
18316
18433
  function readCurrentSession(sessionDir) {
18317
- const ledger = join29(sessionDir, CURRENT_SESSION_LEDGER);
18434
+ const ledger = join30(sessionDir, CURRENT_SESSION_LEDGER);
18318
18435
  try {
18319
18436
  const value = JSON.parse(readFileSync3(ledger, "utf8"));
18320
18437
  if (typeof value !== "object" || value === null || typeof value.sessionFile !== "string" || value.sessionFile.length === 0) {
@@ -18329,7 +18446,7 @@ function readCurrentSession(sessionDir) {
18329
18446
  }
18330
18447
  }
18331
18448
  function writeCurrentSession(sessionDir, sessionFile) {
18332
- const ledger = join29(sessionDir, CURRENT_SESSION_LEDGER);
18449
+ const ledger = join30(sessionDir, CURRENT_SESSION_LEDGER);
18333
18450
  try {
18334
18451
  writeFileSync5(ledger, `${JSON.stringify({ sessionFile })}
18335
18452
  `, { flag: "wx" });
@@ -18390,10 +18507,10 @@ function createRecordSessionOpen(options) {
18390
18507
  return { session: SessionManager.inMemory(cwd), resumed: false };
18391
18508
  } else {
18392
18509
  const parentResolved = resolve13(parentFile);
18393
- sessionDir = physicallyContainedIn(ledgerHome, parentResolved) ? join29(dirname13(parentResolved), options.kind) : join29(activationBookDirectory(ledgerHome, resolveBookKeyFromGit(cwd)), options.kind);
18510
+ sessionDir = physicallyContainedIn(ledgerHome, parentResolved) ? join30(dirname13(parentResolved), options.kind) : join30(activationBookDirectory(ledgerHome, resolveBookKeyFromGit(cwd)), options.kind);
18394
18511
  parentSession = parentFile;
18395
18512
  }
18396
- const nestAlreadyExists = existsSync9(sessionDir);
18513
+ const nestAlreadyExists = existsSync10(sessionDir);
18397
18514
  ensureRealDirectoryTree(ledgerHome, sessionDir);
18398
18515
  const mayResumeSameNest = options.subject !== void 0 || options.kind === WORKER_SUBMISSION_GATE_KIND;
18399
18516
  if (mayResumeSameNest && nestAlreadyExists) {
@@ -18411,7 +18528,7 @@ function createRecordSessionOpen(options) {
18411
18528
  );
18412
18529
  if (session.isPersisted()) {
18413
18530
  const file = session.getSessionFile();
18414
- if (file !== void 0 && !existsSync9(file)) {
18531
+ if (file !== void 0 && !existsSync10(file)) {
18415
18532
  const header = session.getHeader();
18416
18533
  if (header !== null && header.type === "session") {
18417
18534
  writeFileSync5(file, `${JSON.stringify(header)}
@@ -18429,7 +18546,7 @@ function createRecordSession(options) {
18429
18546
  return createRecordSessionOpen(options).session;
18430
18547
  }
18431
18548
  function bookDirectOfficerRunPointer(options) {
18432
- const nest = join29(dirname13(options.parentSessionFile), "auditor-roles");
18549
+ const nest = join30(dirname13(options.parentSessionFile), "auditor-roles");
18433
18550
  mkdirSync4(nest, { recursive: true });
18434
18551
  const pointer = {
18435
18552
  version: 1,
@@ -18439,7 +18556,7 @@ function bookDirectOfficerRunPointer(options) {
18439
18556
  ...options.runDirectory !== void 0 && options.runDirectory.trim() !== "" ? { runDirectory: options.runDirectory } : {}
18440
18557
  };
18441
18558
  writeFileSync5(
18442
- join29(nest, `${options.officer}.pointer.json`),
18559
+ join30(nest, `${options.officer}.pointer.json`),
18443
18560
  `${JSON.stringify(pointer)}
18444
18561
  `,
18445
18562
  "utf8"
@@ -21600,7 +21717,7 @@ var init_reviewer_role = __esm({
21600
21717
 
21601
21718
  // src/worker-submission-gates.ts
21602
21719
  import { execFileSync as execFileSync4 } from "node:child_process";
21603
- import { existsSync as existsSync10, lstatSync as lstatSync3, readdirSync as readdirSync2, readFileSync as readFileSync4, rmdirSync, rmSync } from "node:fs";
21720
+ import { existsSync as existsSync11, lstatSync as lstatSync3, readdirSync as readdirSync2, readFileSync as readFileSync4, rmdirSync, rmSync } from "node:fs";
21604
21721
  import { resolve as resolve18 } from "node:path";
21605
21722
  function git2(cwd, args) {
21606
21723
  return execFileSync4("git", args, {
@@ -21621,7 +21738,7 @@ function statusOf(error) {
21621
21738
  return typeof error === "object" && error !== null && "status" in error ? error.status : void 0;
21622
21739
  }
21623
21740
  function tryGetAll(file, key) {
21624
- if (!existsSync10(file)) return [];
21741
+ if (!existsSync11(file)) return [];
21625
21742
  try {
21626
21743
  const out = gitFile(file, ["--get-all", key]);
21627
21744
  return out.length === 0 ? [] : out.split("\n");
@@ -21631,7 +21748,7 @@ function tryGetAll(file, key) {
21631
21748
  }
21632
21749
  }
21633
21750
  function ownedHook(path) {
21634
- if (!existsSync10(path)) return false;
21751
+ if (!existsSync11(path)) return false;
21635
21752
  return readFileSync4(path, "utf8").includes(HOOK_MARKER);
21636
21753
  }
21637
21754
  function escapeGitConfigValueRegex(value) {
@@ -21658,11 +21775,11 @@ function rmOwnedDir(dir) {
21658
21775
  const hookPath = resolve18(dir, HOOK_FILE);
21659
21776
  if (!ownedHook(hookPath)) return;
21660
21777
  rmSync(hookPath, { force: true });
21661
- if (existsSync10(dir) && readdirSync2(dir).length === 0) rmdirSync(dir);
21778
+ if (existsSync11(dir) && readdirSync2(dir).length === 0) rmdirSync(dir);
21662
21779
  }
21663
21780
  function linkedGitDirs(commonDir) {
21664
21781
  const root = resolve18(commonDir, "worktrees");
21665
- if (!existsSync10(root)) return [];
21782
+ if (!existsSync11(root)) return [];
21666
21783
  return readdirSync2(root).map((name) => resolve18(root, name)).filter((dir) => lstatSync3(dir).isDirectory());
21667
21784
  }
21668
21785
  function uninstallPackageWorkerHooks(cwd) {
@@ -22351,7 +22468,7 @@ var init_activation_reconciliation = __esm({
22351
22468
 
22352
22469
  // src/role-runtime.ts
22353
22470
  import { readFileSync as readFileSync5, writeSync as writeSync4 } from "node:fs";
22354
- import { join as join31 } from "node:path";
22471
+ import { join as join32 } from "node:path";
22355
22472
  import { Value as Value5 } from "typebox/value";
22356
22473
  function decodeReviewerAdmittedInputs(getFlag) {
22357
22474
  let reviewScopeKeys;
@@ -22723,7 +22840,7 @@ function readDiaristRunCoordinates() {
22723
22840
  if (typeof runDirectory !== "string" || runDirectory.trim() === "") {
22724
22841
  throw new Error("diarist accept requires AK_ROLE_RUN_DIR");
22725
22842
  }
22726
- const admittedPath = join31(runDirectory, "admitted-request.json");
22843
+ const admittedPath = join32(runDirectory, "admitted-request.json");
22727
22844
  const admitted = JSON.parse(readFileSync5(admittedPath, "utf8"));
22728
22845
  if (typeof admitted.projectRoot !== "string" || admitted.projectRoot.trim() === "") {
22729
22846
  throw new Error(`diarist admitted-request missing projectRoot (${admittedPath})`);
@@ -24084,7 +24201,7 @@ __export(in_process_session_exports, {
24084
24201
  });
24085
24202
  import { mkdtemp as mkdtemp2, rm as rm2 } from "node:fs/promises";
24086
24203
  import { tmpdir as tmpdir2 } from "node:os";
24087
- import { join as join32 } from "node:path";
24204
+ import { join as join33 } from "node:path";
24088
24205
  import {
24089
24206
  createAgentSession,
24090
24207
  DefaultResourceLoader,
@@ -24207,7 +24324,7 @@ async function openPiInProcessSession(options) {
24207
24324
  let scratchDir;
24208
24325
  let resolvedAgentDir = options.agentDir;
24209
24326
  if (resolvedAgentDir === void 0) {
24210
- scratchDir = await mkdtemp2(join32(options.credentialScratchParent ?? tmpdir2(), "ak-institutional-"));
24327
+ scratchDir = await mkdtemp2(join33(options.credentialScratchParent ?? tmpdir2(), "ak-institutional-"));
24211
24328
  resolvedAgentDir = scratchDir;
24212
24329
  }
24213
24330
  try {
@@ -24903,7 +25020,7 @@ var init_reviewer_child_executor = __esm({
24903
25020
  import { spawn as spawn4 } from "node:child_process";
24904
25021
  import { mkdtemp as mkdtemp3, rm as rm3 } from "node:fs/promises";
24905
25022
  import { tmpdir as tmpdir3 } from "node:os";
24906
- import { join as join33 } from "node:path";
25023
+ import { join as join34 } from "node:path";
24907
25024
  async function runCommand(command, args, options = {}) {
24908
25025
  return await new Promise((resolve20, reject) => {
24909
25026
  const child = spawn4(command, args, { ...options.cwd === void 0 ? {} : { cwd: options.cwd }, stdio: ["ignore", "pipe", "pipe"], signal: options.signal });
@@ -24952,8 +25069,8 @@ async function prepareSnapshot(accepted, signal, dependencies) {
24952
25069
  if (!sameReviewerPinnedTarget({ repositoryRoot: accepted.repositoryRoot, objectFormat, targetHead }, accepted)) throw new Error("Accepted Reviewer target identity no longer matches the repository");
24953
25070
  await git3(accepted.repositoryRoot, ["cat-file", "-e", `${targetHead}^{commit}`], signal);
24954
25071
  dependencies.fault?.("mirror.before-create");
24955
- mirrorRoot = await mkdtemp3(join33(tmpdir3(), "ak-reviewer-snapshot-"));
24956
- const mirrorPath = join33(mirrorRoot, "repository.git");
25072
+ mirrorRoot = await mkdtemp3(join34(tmpdir3(), "ak-reviewer-snapshot-"));
25073
+ const mirrorPath = join34(mirrorRoot, "repository.git");
24957
25074
  dependencies.fault?.("mirror.create");
24958
25075
  await runCommand("git", ["init", "--bare", `--object-format=${accepted.objectFormat}`, mirrorPath], signal === void 0 ? {} : { signal });
24959
25076
  await git3(mirrorPath, ["fetch", "--no-tags", accepted.repositoryRoot, targetHead], signal);
@@ -24970,7 +25087,7 @@ async function prepareClone(snapshot, signal, dependencies) {
24970
25087
  const target = { repositoryRoot: snapshot.repositoryRoot, objectFormat: snapshot.objectFormat, targetHead: snapshot.targetHead, refs: { ...snapshot.refs } };
24971
25088
  try {
24972
25089
  dependencies.fault?.("workspace.before-create");
24973
- workspace = await mkdtemp3(join33(tmpdir3(), "ak-reviewer-leg-"));
25090
+ workspace = await mkdtemp3(join34(tmpdir3(), "ak-reviewer-leg-"));
24974
25091
  dependencies.fault?.("workspace.init");
24975
25092
  await git3(workspace, ["init", `--object-format=${snapshot.objectFormat}`, "--initial-branch=ak-reviewer-unborn"], signal);
24976
25093
  dependencies.fault?.("workspace.fetch");
@@ -25385,9 +25502,9 @@ init_auditor_soul();
25385
25502
  init_session_opening_materials();
25386
25503
 
25387
25504
  // src/acp-host/description.ts
25388
- import { join as join34 } from "node:path";
25505
+ import { join as join35 } from "node:path";
25389
25506
  function resolveAcpBinary(description, operatorHome) {
25390
- return join34(operatorHome, ...description.binaryFromHome);
25507
+ return join35(operatorHome, ...description.binaryFromHome);
25391
25508
  }
25392
25509
  function acpStdioArgs(description, model, seat) {
25393
25510
  const { prefix, suffix, modelFlag, thinkingFlag } = description.argv;
@@ -25413,7 +25530,7 @@ init_role_runtime();
25413
25530
  import { randomUUID as randomUUID6 } from "node:crypto";
25414
25531
  import { mkdir as mkdir5, readFile as readFile18, writeFile as writeFile8 } from "node:fs/promises";
25415
25532
  import { createServer } from "node:net";
25416
- import { basename as basename7, dirname as dirname17, join as join35 } from "node:path";
25533
+ import { basename as basename7, dirname as dirname17, join as join36 } from "node:path";
25417
25534
  import { fileURLToPath as fileURLToPath2 } from "node:url";
25418
25535
 
25419
25536
  // src/acp-host/role-turn-host.ts
@@ -25768,8 +25885,23 @@ function createComposedAcpRoleTurnHost(config) {
25768
25885
  })
25769
25886
  });
25770
25887
  }
25888
+ function terminatingToolJsonSchema(parameters) {
25889
+ const cloned = JSON.parse(JSON.stringify(parameters));
25890
+ return Object.freeze({
25891
+ ...cloned,
25892
+ $schema: "http://json-schema.org/draft-07/schema#"
25893
+ });
25894
+ }
25771
25895
  async function prepareAcpRoleEnvelope(options) {
25772
25896
  const { request } = options;
25897
+ if (options.socketPath === "") {
25898
+ throw new Error("prepareAcpRoleEnvelope requires socketPath");
25899
+ }
25900
+ const listTerminatingToolOnMcp = options.listTerminatingToolOnMcp !== false;
25901
+ const earlyTerminatingTool = packagedRoleOutputTool(request.activation.role);
25902
+ if (earlyTerminatingTool === void 0) {
25903
+ throw new Error(`role has no terminating tool: ${request.activation.role}`);
25904
+ }
25773
25905
  const flags = projectAcpActivationFlags(request);
25774
25906
  const tools = /* @__PURE__ */ new Map();
25775
25907
  const handlers = /* @__PURE__ */ new Map();
@@ -25789,7 +25921,7 @@ async function prepareAcpRoleEnvelope(options) {
25789
25921
  const raw = await readFile18(method.path, "utf8");
25790
25922
  methodSkills.set(name, { path: method.path, body: stripSkillFrontmatter(raw).trim() });
25791
25923
  }
25792
- let sessionFile = options.sessionFile ?? join35(request.runDirectory, "session", "session.jsonl");
25924
+ let sessionFile = options.sessionFile ?? join36(request.runDirectory, "session", "session.jsonl");
25793
25925
  await mkdir5(dirname17(sessionFile), { recursive: true });
25794
25926
  if (request.continuation.kind !== "resume") {
25795
25927
  try {
@@ -25992,6 +26124,68 @@ async function prepareAcpRoleEnvelope(options) {
25992
26124
  await emit("tool_execution_end", { toolCallId, toolName, isError: projected.isError });
25993
26125
  return projected;
25994
26126
  }
26127
+ async function invokeAkTool(name, args) {
26128
+ const tool = tools.get(name);
26129
+ if (tool === void 0) throw new Error(`Unknown AK tool: ${name}`);
26130
+ const toolCallId = randomUUID6();
26131
+ calls.push({ toolCallId, toolName: name });
26132
+ sessionEntries.push({
26133
+ type: "message",
26134
+ message: {
26135
+ role: "assistant",
26136
+ content: [{
26137
+ type: "toolCall",
26138
+ id: toolCallId,
26139
+ name,
26140
+ arguments: args ?? {}
26141
+ }]
26142
+ }
26143
+ });
26144
+ try {
26145
+ await emit("tool_execution_start", { toolCallId, toolName: name });
26146
+ const blocked = (await emit("tool_call", { toolCallId, toolName: name, input: args ?? {} })).some((value) => typeof value === "object" && value !== null && "block" in value && value.block === true);
26147
+ if (blocked) {
26148
+ return { content: [{ type: "text", text: `AK tool blocked: ${name}` }], isError: true, blocked: true };
26149
+ }
26150
+ } catch (error) {
26151
+ const declared = declareRoundInfrastructureFailure(error);
26152
+ try {
26153
+ const projected = await projectToolResult(toolCallId, name, {
26154
+ content: declared.content,
26155
+ details: declared.details,
26156
+ isError: true
26157
+ });
26158
+ return { content: projected.content, isError: true };
26159
+ } catch {
26160
+ return { content: declared.content, isError: true };
26161
+ }
26162
+ }
26163
+ try {
26164
+ const result = await tool.execute(toolCallId, args ?? {}, void 0, void 0, context);
26165
+ const projected = await projectToolResult(toolCallId, name, {
26166
+ content: result.content,
26167
+ details: result.details,
26168
+ isError: false
26169
+ });
26170
+ return { content: projected.content, isError: projected.isError };
26171
+ } catch (error) {
26172
+ let content;
26173
+ let details;
26174
+ if (isCorrectableExecuteError(error)) {
26175
+ const projected2 = projectCorrectableExecuteRejection(error);
26176
+ content = [{ type: "text", text: projected2.diagnostic }];
26177
+ details = projected2.details;
26178
+ } else {
26179
+ ({ content, details } = declareRoundInfrastructureFailure(error));
26180
+ }
26181
+ const projected = await projectToolResult(toolCallId, name, {
26182
+ content,
26183
+ details,
26184
+ isError: true
26185
+ });
26186
+ return { content: projected.content, isError: projected.isError };
26187
+ }
26188
+ }
25995
26189
  function reply(socket, id, result, error) {
25996
26190
  const rpcError = error instanceof Error ? { code: "ak-relay-failure", name: error.name, message: error.message } : { code: "ak-relay-failure", name: "RelayFailure", message: String(error) };
25997
26191
  socket.write(`${JSON.stringify({ id, ...error === void 0 ? { result } : { error: rpcError } })}
@@ -26020,8 +26214,9 @@ async function prepareAcpRoleEnvelope(options) {
26020
26214
  }
26021
26215
  try {
26022
26216
  if (rpc.method === "tools/list") {
26023
- reply(socket, rpc.id, { tools: [...tools.values()].map((tool2) => {
26024
- return { name: tool2.name, description: tool2.description, inputSchema: tool2.parameters };
26217
+ const listed = [...tools.values()].filter((tool) => listTerminatingToolOnMcp || tool.name !== earlyTerminatingTool);
26218
+ reply(socket, rpc.id, { tools: listed.map((tool) => {
26219
+ return { name: tool.name, description: tool.description, inputSchema: tool.parameters };
26025
26220
  }) });
26026
26221
  return;
26027
26222
  }
@@ -26029,74 +26224,15 @@ async function prepareAcpRoleEnvelope(options) {
26029
26224
  const params = rpc.params;
26030
26225
  const name = params?.name;
26031
26226
  if (typeof name !== "string") throw new Error("MCP tool name is missing");
26032
- const tool = tools.get(name);
26033
- if (tool === void 0) throw new Error(`Unknown AK tool: ${name}`);
26034
- const toolCallId = randomUUID6();
26035
- calls.push({ toolCallId, toolName: name });
26036
- {
26037
- const message = {
26038
- role: "assistant",
26039
- content: [{
26040
- type: "toolCall",
26041
- id: toolCallId,
26042
- name,
26043
- arguments: params?.arguments ?? {}
26044
- }]
26045
- };
26046
- sessionEntries.push({ type: "message", message });
26227
+ if (!listTerminatingToolOnMcp && name === earlyTerminatingTool) {
26228
+ throw new Error(`terminating tool ${name} is schema-channel only on this host`);
26047
26229
  }
26048
- try {
26049
- await emit("tool_execution_start", { toolCallId, toolName: name });
26050
- const blocked = (await emit("tool_call", { toolCallId, toolName: name, input: params?.arguments ?? {} })).some((value) => typeof value === "object" && value !== null && "block" in value && value.block === true);
26051
- if (blocked) {
26052
- reply(socket, rpc.id, void 0, new Error(`AK tool blocked: ${name}`));
26053
- return;
26054
- }
26055
- } catch (error) {
26056
- const declared = declareRoundInfrastructureFailure(error);
26057
- try {
26058
- const projected = await projectToolResult(toolCallId, name, {
26059
- content: declared.content,
26060
- details: declared.details,
26061
- isError: true
26062
- });
26063
- reply(socket, rpc.id, {
26064
- content: projected.content,
26065
- isError: true
26066
- });
26067
- } catch {
26068
- reply(socket, rpc.id, {
26069
- content: declared.content,
26070
- isError: true
26071
- });
26072
- }
26230
+ const outcome = await invokeAkTool(name, params?.arguments ?? {});
26231
+ if (outcome.blocked === true) {
26232
+ reply(socket, rpc.id, void 0, new Error(outcome.content.map((p) => p.type === "text" ? p.text : "").join("")));
26073
26233
  return;
26074
26234
  }
26075
- try {
26076
- const result = await tool.execute(toolCallId, params?.arguments ?? {}, void 0, void 0, context);
26077
- const projected = await projectToolResult(toolCallId, name, {
26078
- content: result.content,
26079
- details: result.details,
26080
- isError: false
26081
- });
26082
- reply(socket, rpc.id, { content: projected.content, ...projected.isError ? { isError: true } : {} });
26083
- } catch (error) {
26084
- let content;
26085
- let details;
26086
- if (isCorrectableExecuteError(error)) {
26087
- const projected2 = projectCorrectableExecuteRejection(error);
26088
- content = [{ type: "text", text: projected2.diagnostic }];
26089
- details = projected2.details;
26090
- } else {
26091
- ({ content, details } = declareRoundInfrastructureFailure(error));
26092
- }
26093
- const projected = await projectToolResult(toolCallId, name, {
26094
- content,
26095
- details,
26096
- isError: true
26097
- });
26098
- reply(socket, rpc.id, { content: projected.content, ...projected.isError ? { isError: true } : {} });
26099
- }
26235
+ reply(socket, rpc.id, { content: outcome.content, ...outcome.isError ? { isError: true } : {} });
26100
26236
  } catch (error) {
26101
26237
  reply(socket, rpc.id, void 0, error);
26102
26238
  }
@@ -26104,8 +26240,8 @@ async function prepareAcpRoleEnvelope(options) {
26104
26240
  }
26105
26241
  });
26106
26242
  }
26107
- await listen(server, options.socketPath);
26108
26243
  const relay = fileURLToPath2(new URL("./mcp-relay.mjs", import.meta.url));
26244
+ await listen(server, options.socketPath);
26109
26245
  let disposed = false;
26110
26246
  let priorAkRoleRunDir;
26111
26247
  let priorAkRoleCourtAttempt;
@@ -26148,6 +26284,11 @@ async function prepareAcpRoleEnvelope(options) {
26148
26284
  });
26149
26285
  }
26150
26286
  };
26287
+ const terminatingToolName = earlyTerminatingTool;
26288
+ async function ingestStructuredOutput(params) {
26289
+ if (calls.some((call) => call.toolName === terminatingToolName)) return;
26290
+ await invokeAkTool(terminatingToolName, params ?? {});
26291
+ }
26151
26292
  const closeRound = async () => {
26152
26293
  if (calls.length > 0) {
26153
26294
  const roundCalls = [...calls];
@@ -26214,6 +26355,11 @@ async function prepareAcpRoleEnvelope(options) {
26214
26355
  if (request.courtAttemptId === void 0) delete process.env.AK_ROLE_COURT_ATTEMPT;
26215
26356
  else process.env.AK_ROLE_COURT_ATTEMPT = request.courtAttemptId;
26216
26357
  runDirInjected = true;
26358
+ const terminating = tools.get(terminatingToolName);
26359
+ if (terminating === void 0) {
26360
+ throw new Error(`terminating tool not registered after activation: ${terminatingToolName}`);
26361
+ }
26362
+ const jsonSchema = terminatingToolJsonSchema(terminating.parameters);
26217
26363
  return {
26218
26364
  mcpServers: [{
26219
26365
  name: `ak-${request.activation.role}`,
@@ -26228,7 +26374,10 @@ async function prepareAcpRoleEnvelope(options) {
26228
26374
  prompt,
26229
26375
  abortSignal: hostAbort.signal,
26230
26376
  closeRound,
26231
- dispose
26377
+ dispose,
26378
+ jsonSchema,
26379
+ terminatingToolName,
26380
+ ingestStructuredOutput
26232
26381
  };
26233
26382
  } catch (error) {
26234
26383
  try {
@@ -26247,12 +26396,12 @@ async function prepareAcpRoleEnvelope(options) {
26247
26396
  // src/acp-host/seat-profile-soul.ts
26248
26397
  import { constants as constants3 } from "node:fs";
26249
26398
  import { access as access4, copyFile, lstat as lstat6, mkdir as mkdir6, readlink, symlink, unlink as unlink4 } from "node:fs/promises";
26250
- import { dirname as dirname18, join as join36, relative as relative3, resolve as resolve19 } from "node:path";
26399
+ import { dirname as dirname18, join as join37, relative as relative3, resolve as resolve19 } from "node:path";
26251
26400
  function seatProfileName(spec, role) {
26252
26401
  return `${spec.namePrefix}${role}`;
26253
26402
  }
26254
26403
  function packageRoleSoulPath(packageRoot, role) {
26255
- return join36(packageRoot, "souls", `${role}.md`);
26404
+ return join37(packageRoot, "souls", `${role}.md`);
26256
26405
  }
26257
26406
  async function pathExists(path) {
26258
26407
  try {
@@ -26269,16 +26418,16 @@ async function ensureSeatProfileSoul(options) {
26269
26418
  if (!await pathExists(soulTarget)) {
26270
26419
  throw new Error(`packaged role soul missing: ${soulTarget}`);
26271
26420
  }
26272
- const profilesRoot = join36(operatorHome, ...spec.profilesRootFromHome);
26273
- const profileDir = join36(profilesRoot, profileName);
26421
+ const profilesRoot = join37(operatorHome, ...spec.profilesRootFromHome);
26422
+ const profileDir = join37(profilesRoot, profileName);
26274
26423
  const hostRoot = dirname18(profilesRoot);
26275
- const soulPath = join36(profileDir, spec.soulFileName);
26424
+ const soulPath = join37(profileDir, spec.soulFileName);
26276
26425
  if (!await pathExists(profileDir)) {
26277
26426
  await mkdir6(profileDir, { recursive: true });
26278
26427
  for (const name of ["auth.json", ".env", "config.yaml"]) {
26279
- const source = join36(hostRoot, name);
26428
+ const source = join37(hostRoot, name);
26280
26429
  if (!await pathExists(source)) continue;
26281
- await copyFile(source, join36(profileDir, name));
26430
+ await copyFile(source, join37(profileDir, name));
26282
26431
  }
26283
26432
  } else {
26284
26433
  await mkdir6(profileDir, { recursive: true });
@@ -26305,9 +26454,9 @@ async function ensureSeatProfileSoul(options) {
26305
26454
 
26306
26455
  // src/acp-host/session-identity.ts
26307
26456
  import { mkdir as mkdir7, readFile as readFile19, rename, writeFile as writeFile9 } from "node:fs/promises";
26308
- import { dirname as dirname19, join as join37 } from "node:path";
26457
+ import { dirname as dirname19, join as join38 } from "node:path";
26309
26458
  function createAcpSessionIdentityAuthority(authority, sessionBindingFile) {
26310
- const bindingPath = (principal) => join37(authority.decode(principal).sessionDirectory, sessionBindingFile);
26459
+ const bindingPath = (principal) => join38(authority.decode(principal).sessionDirectory, sessionBindingFile);
26311
26460
  return {
26312
26461
  resolveSessionFile(principal) {
26313
26462
  return authority.decode(principal).sessionFile;