@akagilnc/pi-workflow-roles 0.1.2525 → 0.1.2535

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.
@@ -14416,6 +14416,15 @@ var init_notary_contracts = __esm({
14416
14416
  }
14417
14417
  });
14418
14418
 
14419
+ // src/inspector-contracts.ts
14420
+ var INSPECTOR_OUTPUT_TOOL_NAME;
14421
+ var init_inspector_contracts = __esm({
14422
+ "src/inspector-contracts.ts"() {
14423
+ "use strict";
14424
+ INSPECTOR_OUTPUT_TOOL_NAME = "ak_inspector_output";
14425
+ }
14426
+ });
14427
+
14419
14428
  // src/packaged-role-registry.ts
14420
14429
  var PACKAGED_ROLE_REGISTRY;
14421
14430
  var init_packaged_role_registry = __esm({
@@ -14428,6 +14437,7 @@ var init_packaged_role_registry = __esm({
14428
14437
  init_doctor_contracts();
14429
14438
  init_merger_contracts();
14430
14439
  init_notary_contracts();
14440
+ init_inspector_contracts();
14431
14441
  PACKAGED_ROLE_REGISTRY = [
14432
14442
  { role: "judge", phases: [null], outputTool: JUDGE_OUTPUT_TOOL_NAME, inputFlag: void 0, phaseFlag: void 0, activationStage: "load-and-install" },
14433
14443
  { role: "fixer", phases: ["plan", "apply"], outputTool: FIXER_OUTPUT_TOOL_NAME, inputFlag: "ak-fix-packet", phaseFlag: "ak-fixer-phase", activationStage: "load-and-install" },
@@ -14437,7 +14447,8 @@ var init_packaged_role_registry = __esm({
14437
14447
  { role: "collector", phases: [null], outputTool: COLLECTOR_OUTPUT_TOOL, inputFlag: void 0, phaseFlag: void 0, activationStage: "load-and-install" },
14438
14448
  { role: "doctor", phases: [null], outputTool: DOCTOR_OUTPUT_TOOL_NAME, inputFlag: "ak-doctor-case", phaseFlag: void 0, activationStage: "load-and-install" },
14439
14449
  { role: "merger", phases: [null], outputTool: MERGER_OUTPUT_TOOL_NAME, inputFlag: "ak-merger-input", phaseFlag: void 0, activationStage: "prepare-git-and-install" },
14440
- { role: "notary", phases: [null], outputTool: NOTARY_OUTPUT_TOOL_NAME, inputFlag: "ak-notary-source-run", phaseFlag: void 0, activationStage: "load-and-install" }
14450
+ { role: "notary", phases: [null], outputTool: NOTARY_OUTPUT_TOOL_NAME, inputFlag: "ak-notary-source-run", phaseFlag: void 0, activationStage: "load-and-install" },
14451
+ { role: "inspector", phases: [null], outputTool: INSPECTOR_OUTPUT_TOOL_NAME, inputFlag: void 0, phaseFlag: void 0, activationStage: "load-and-install" }
14441
14452
  ];
14442
14453
  }
14443
14454
  });
@@ -14481,7 +14492,7 @@ function isPublicConfigurableSeat(value) {
14481
14492
  function isPublicCliSupportCommand(value) {
14482
14493
  return PUBLIC_CLI_SUPPORT_COMMANDS.includes(value);
14483
14494
  }
14484
- var INTERNAL_ROLE_ENTRYPOINT_RELATIVE, PUBLIC_CALLABLE_ROLES, AUTOMATIC_NAVIGATOR_SEAT, AUTOMATIC_GATEKEEPER_SEAT, AUTOMATIC_INSPECTOR_SEAT, AUTOMATIC_CONFIGURABLE_SEATS, PUBLIC_CONFIGURABLE_SEATS, PUBLIC_CLI_SUPPORT_COMMANDS, STARTUP_CANDIDATES, PUBLIC_DETERMINISTIC_COMMANDS;
14495
+ var INTERNAL_ROLE_ENTRYPOINT_RELATIVE, PUBLIC_CALLABLE_ROLES, AUTOMATIC_NAVIGATOR_SEAT, AUTOMATIC_GATEKEEPER_SEAT, AUTOMATIC_CONFIGURABLE_SEATS, PUBLIC_CONFIGURABLE_SEATS, PUBLIC_CLI_SUPPORT_COMMANDS, STARTUP_CANDIDATES, PUBLIC_DETERMINISTIC_COMMANDS;
14485
14496
  var init_registry2 = __esm({
14486
14497
  "src/public-cli/registry.ts"() {
14487
14498
  "use strict";
@@ -14492,10 +14503,8 @@ var init_registry2 = __esm({
14492
14503
  );
14493
14504
  AUTOMATIC_NAVIGATOR_SEAT = "navigator";
14494
14505
  AUTOMATIC_GATEKEEPER_SEAT = "gatekeeper";
14495
- AUTOMATIC_INSPECTOR_SEAT = "inspector";
14496
14506
  AUTOMATIC_CONFIGURABLE_SEATS = [
14497
14507
  AUTOMATIC_GATEKEEPER_SEAT,
14498
- AUTOMATIC_INSPECTOR_SEAT,
14499
14508
  AUTOMATIC_NAVIGATOR_SEAT
14500
14509
  ];
14501
14510
  PUBLIC_CONFIGURABLE_SEATS = [
@@ -14601,12 +14610,12 @@ function setPersistentSeatConfig(config, seat, selection) {
14601
14610
  function clearPersistentSeatConfig(config, seat) {
14602
14611
  const previous = config.seats[seat];
14603
14612
  if (previous === void 0) return config;
14604
- if (seat === "notary" && previous.engine !== void 0) {
14613
+ if ((seat === "notary" || seat === "inspector") && previous.engine !== void 0) {
14605
14614
  return {
14606
14615
  ...config,
14607
14616
  seats: {
14608
14617
  ...config.seats,
14609
- notary: { engine: previous.engine }
14618
+ [seat]: { engine: previous.engine }
14610
14619
  }
14611
14620
  };
14612
14621
  }
@@ -14767,7 +14776,7 @@ function parseSeatModelConfig(value, seat) {
14767
14776
  throw new Error(`config seat ${seat} engine must be a string`);
14768
14777
  }
14769
14778
  if (!hasProvider) {
14770
- if (seat === "notary" && typeof raw.engine === "string") {
14779
+ if ((seat === "notary" || seat === "inspector") && typeof raw.engine === "string") {
14771
14780
  if (raw.thinking !== void 0) {
14772
14781
  throw new Error(`config seat ${seat} thinking requires provider/model`);
14773
14782
  }
@@ -15413,7 +15422,8 @@ function validateAcceptedDetails(toolName, details) {
15413
15422
  [COLLECTOR_OUTPUT_TOOL]: [],
15414
15423
  [DOCTOR_OUTPUT_TOOL_NAME]: ["completed", "refused"],
15415
15424
  [MERGER_OUTPUT_TOOL_NAME]: ["completed", "escalate"],
15416
- [NOTARY_OUTPUT_TOOL_NAME]: ["pass", "bounce"]
15425
+ [NOTARY_OUTPUT_TOOL_NAME]: ["pass", "bounce"],
15426
+ [INSPECTOR_OUTPUT_TOOL_NAME]: ["pass", "bounce"]
15417
15427
  };
15418
15428
  const collectorDiscriminator = toolName === COLLECTOR_OUTPUT_TOOL && Array.isArray(candidate?.groups);
15419
15429
  const baseDiscriminator = discriminator;
@@ -15439,6 +15449,8 @@ function validateAcceptedDetails(toolName, details) {
15439
15449
  return validateMergerOutput(details);
15440
15450
  case NOTARY_OUTPUT_TOOL_NAME:
15441
15451
  return validateRecordedNotaryOutput(details);
15452
+ case INSPECTOR_OUTPUT_TOOL_NAME:
15453
+ return candidate;
15442
15454
  }
15443
15455
  } catch (error) {
15444
15456
  if (error instanceof Error && error.constructor === Error) throw new AcceptedDetailsContractError(error.message, { cause: error });
@@ -15452,6 +15464,7 @@ function acceptedFacts(toolName, details) {
15452
15464
  case REVIEWER_OUTPUT_TOOL_NAME:
15453
15465
  case DOCTOR_OUTPUT_TOOL_NAME:
15454
15466
  case NOTARY_OUTPUT_TOOL_NAME:
15467
+ case INSPECTOR_OUTPUT_TOOL_NAME:
15455
15468
  return { status: details.status };
15456
15469
  case JUDGE_OUTPUT_TOOL_NAME:
15457
15470
  return { status: details.judgeStatus };
@@ -15472,6 +15485,7 @@ var init_terminating_tools = __esm({
15472
15485
  init_judge_output();
15473
15486
  init_reviewer_output();
15474
15487
  init_audit_escalation();
15488
+ init_inspector_contracts();
15475
15489
  init_doctor_contracts();
15476
15490
  init_merger_contracts();
15477
15491
  init_notary_contracts();
@@ -15484,7 +15498,8 @@ var init_terminating_tools = __esm({
15484
15498
  COLLECTOR_OUTPUT_TOOL,
15485
15499
  DOCTOR_OUTPUT_TOOL_NAME,
15486
15500
  MERGER_OUTPUT_TOOL_NAME,
15487
- NOTARY_OUTPUT_TOOL_NAME
15501
+ NOTARY_OUTPUT_TOOL_NAME,
15502
+ INSPECTOR_OUTPUT_TOOL_NAME
15488
15503
  ];
15489
15504
  AcceptedDetailsContractError = class extends Error {
15490
15505
  constructor(message, options) {
@@ -15914,7 +15929,7 @@ async function readRoleRunState(runDirectory) {
15914
15929
  if (typeof record4.runId !== "string" || record4.runId.trim() === "") {
15915
15930
  return void 0;
15916
15931
  }
15917
- if (record4.role !== "judge" && record4.role !== "coder" && record4.role !== "fixer" && record4.role !== "collector" && record4.role !== "doctor" && record4.role !== "reviewer" && record4.role !== "merger" && record4.role !== "notary") {
15932
+ if (record4.role !== "judge" && record4.role !== "coder" && record4.role !== "fixer" && record4.role !== "collector" && record4.role !== "doctor" && record4.role !== "reviewer" && record4.role !== "merger" && record4.role !== "notary" && record4.role !== "inspector") {
15918
15933
  return void 0;
15919
15934
  }
15920
15935
  if (record4.state !== "admitted" && record4.state !== "running" && record4.state !== "resumable" && record4.state !== "terminal") {
@@ -16937,7 +16952,7 @@ function renderHumanOwnerOptionLines(owner, locale2 = "en") {
16937
16952
  }
16938
16953
  return lines;
16939
16954
  }
16940
- var ANALYST_REQUIRE_ANY_OF, ANALYST_DEFAULT_MODE, REJECTED_PUBLIC_SPELLINGS, GLOBAL_OPTIONS, SHARED_PROJECT_SEMANTICS, SHARED_ATTACH_SEMANTICS, JUDGE_OPTIONS, CODER_OPTIONS, FIXER_OPTIONS, REVIEWER_OPTIONS, COLLECTOR_OPTIONS, DOCTOR_OPTIONS, NOTARY_OPTIONS, MERGER_OPTIONS, ANALYST_OPTIONS, PUBLIC_OPTION_TABLE, PUBLIC_NAVIGATOR_HELP_NOTE, TOP_LEVEL_HELP, ROLE_COMMAND_HELP, SUPPORT_COMMAND_HELP, PUBLIC_COMMAND_HELP;
16955
+ var ANALYST_REQUIRE_ANY_OF, ANALYST_DEFAULT_MODE, REJECTED_PUBLIC_SPELLINGS, GLOBAL_OPTIONS, SHARED_PROJECT_SEMANTICS, SHARED_ATTACH_SEMANTICS, JUDGE_OPTIONS, INSPECTOR_OPTIONS, CODER_OPTIONS, FIXER_OPTIONS, REVIEWER_OPTIONS, COLLECTOR_OPTIONS, DOCTOR_OPTIONS, NOTARY_OPTIONS, MERGER_OPTIONS, ANALYST_OPTIONS, PUBLIC_OPTION_TABLE, PUBLIC_NAVIGATOR_HELP_NOTE, TOP_LEVEL_HELP, ROLE_COMMAND_HELP, SUPPORT_COMMAND_HELP, PUBLIC_COMMAND_HELP;
16941
16956
  var init_option_definitions = __esm({
16942
16957
  "src/public-cli/option-definitions.ts"() {
16943
16958
  "use strict";
@@ -17066,6 +17081,10 @@ var init_option_definitions = __esm({
17066
17081
  bindOwner("judge", SHARED_PROJECT_SEMANTICS),
17067
17082
  bindOwner("judge", SHARED_ATTACH_SEMANTICS)
17068
17083
  ];
17084
+ INSPECTOR_OPTIONS = [
17085
+ bindOwner("inspector", SHARED_PROJECT_SEMANTICS),
17086
+ bindOwner("inspector", SHARED_ATTACH_SEMANTICS)
17087
+ ];
17069
17088
  CODER_OPTIONS = [
17070
17089
  {
17071
17090
  id: "phase",
@@ -17406,6 +17425,7 @@ var init_option_definitions = __esm({
17406
17425
  doctor: DOCTOR_OPTIONS,
17407
17426
  merger: MERGER_OPTIONS,
17408
17427
  notary: NOTARY_OPTIONS,
17428
+ inspector: INSPECTOR_OPTIONS,
17409
17429
  analyst: ANALYST_OPTIONS
17410
17430
  };
17411
17431
  PUBLIC_NAVIGATOR_HELP_NOTE = "Navigator attends automatically on every run; configure with `ak-role config set navigator <provider/model[:thinking]>` (not a caller command).";
@@ -17490,6 +17510,12 @@ var init_option_definitions = __esm({
17490
17510
  "ak-role notary --source-run 01a034f1-75bf-71a6-bcf5-d1299145b1a5@judge"
17491
17511
  ]
17492
17512
  },
17513
+ inspector: {
17514
+ command: "inspector",
17515
+ summary: "Direct complexity and test-quality inspection.",
17516
+ usage: ["ak-role inspector [options] [instruction]"],
17517
+ examples: ['ak-role inspector --attach ./change.patch "Review this material."']
17518
+ },
17493
17519
  analyst: {
17494
17520
  command: "analyst",
17495
17521
  summary: "Deterministic analysis seat (issue / sweep / cohort).",
@@ -17689,13 +17715,12 @@ function requireAuthorityRef(value) {
17689
17715
  }
17690
17716
  return value;
17691
17717
  }
17692
- function parseJudgeArgv(args) {
17718
+ function parseStandardMaterialArgv(owner, args) {
17693
17719
  const attachmentPaths = [];
17694
17720
  let project;
17695
17721
  const positional = [];
17696
17722
  const tokens = [...args];
17697
- const definitions = roleOptions("judge");
17698
- const options = createTypedOptionConsumer(definitions);
17723
+ const options = createTypedOptionConsumer(roleOptions(owner));
17699
17724
  while (tokens.length > 0) {
17700
17725
  if (tokens[0] === "--") {
17701
17726
  tokens.shift();
@@ -17704,33 +17729,26 @@ function parseJudgeArgv(args) {
17704
17729
  }
17705
17730
  const taken = options.takeDashed(tokens);
17706
17731
  if (taken !== void 0) {
17707
- if (taken.def.id === "attach") {
17708
- attachmentPaths.push(requireOptionPath(taken.def.canonical, taken.value));
17709
- continue;
17710
- }
17711
- if (taken.def.id === "project") {
17712
- project = requireOptionPath(taken.def.canonical, taken.value);
17713
- continue;
17714
- }
17715
- throw new CliUsageError(`unknown judge option: ${taken.def.canonical}`);
17732
+ if (taken.def.id === "attach") attachmentPaths.push(requireOptionPath(taken.def.canonical, taken.value));
17733
+ else if (taken.def.id === "project") project = requireOptionPath(taken.def.canonical, taken.value);
17734
+ else throw new CliUsageError(`unknown ${owner} option: ${taken.def.canonical}`);
17735
+ continue;
17716
17736
  }
17717
17737
  const token = tokens.shift();
17718
- if (isRejectedPublicSpelling("judge", token)) {
17719
- throw new CliUsageError(
17720
- "judge does not accept a public burden selector; Judge infers its own burden"
17721
- );
17722
- }
17723
- if (token.startsWith("-") && token !== "-") {
17724
- throw new CliUsageError(`unknown judge option: ${token}`);
17738
+ if (owner === "judge" && isRejectedPublicSpelling("judge", token)) {
17739
+ throw new CliUsageError("judge does not accept a public burden selector; Judge infers its own burden");
17725
17740
  }
17741
+ if (token.startsWith("-") && token !== "-") throw new CliUsageError(`unknown ${owner} option: ${token}`);
17726
17742
  positional.push(token);
17727
17743
  }
17728
17744
  options.assertRequired();
17729
- return {
17730
- instruction: positional.join(" "),
17731
- attachmentPaths,
17732
- ...project === void 0 ? {} : { project }
17733
- };
17745
+ return { instruction: positional.join(" "), attachmentPaths, ...project === void 0 ? {} : { project } };
17746
+ }
17747
+ function parseJudgeArgv(args) {
17748
+ return parseStandardMaterialArgv("judge", args);
17749
+ }
17750
+ function parseInspectorArgv(args) {
17751
+ return parseStandardMaterialArgv("inspector", args);
17734
17752
  }
17735
17753
  function parseCoderArgv(args) {
17736
17754
  const attachmentPaths = [];
@@ -17870,25 +17888,19 @@ async function freezeAttachmentsWithTicketNumber(attachmentPaths, attachmentsDir
17870
17888
  function ticketAdmissionFields(ticketNumber) {
17871
17889
  return ticketNumber === void 0 ? {} : { ticketNumber };
17872
17890
  }
17873
- async function admitJudgeInvocation(options) {
17874
- if (options.project !== void 0) {
17875
- requireOptionPath("--project", options.project);
17876
- }
17891
+ async function admitStandardMaterialInvocation(role, options) {
17892
+ if (options.project !== void 0) requireOptionPath("--project", options.project);
17877
17893
  const projectRoot = resolve5(options.project ?? options.cwd);
17878
17894
  const runId = (options.createRunId ?? uuidv7)();
17879
- const { ledgerHome, bookKey, runDirectory, sessionDirectory, sessionFile } = roleRunSessionCoordinates({ cwd: projectRoot, runId, role: "judge", home: options.home });
17895
+ const { ledgerHome, bookKey, runDirectory, sessionDirectory, sessionFile } = roleRunSessionCoordinates({ cwd: projectRoot, runId, role, home: options.home });
17880
17896
  const attachmentsDirectory = join9(runDirectory, "attachments");
17881
17897
  ensureRealDirectoryTree(ledgerHome, sessionDirectory);
17882
17898
  ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
17883
- const { attachments, ticketNumber } = await freezeAttachmentsWithTicketNumber(
17884
- options.attachmentPaths,
17885
- attachmentsDirectory
17886
- );
17899
+ const { attachments, ticketNumber } = await freezeAttachmentsWithTicketNumber(options.attachmentPaths, attachmentsDirectory);
17887
17900
  const ticketFields = ticketAdmissionFields(ticketNumber);
17888
17901
  const instruction = options.instruction;
17889
- const instructionEmpty = instruction.trim() === "";
17890
17902
  const admitted = {
17891
- role: "judge",
17903
+ role,
17892
17904
  runId,
17893
17905
  bookKey,
17894
17906
  projectRoot,
@@ -17897,45 +17909,34 @@ async function admitJudgeInvocation(options) {
17897
17909
  sessionFile,
17898
17910
  ...ticketFields,
17899
17911
  instruction,
17900
- instructionEmpty,
17901
- attachments: attachments.map((a) => ({
17902
- provenancePath: a.provenancePath,
17903
- frozenPath: a.frozenPath,
17904
- byteLength: a.byteLength,
17905
- sha256: a.sha256,
17906
- mediaKind: a.mediaKind
17907
- }))
17912
+ instructionEmpty: instruction.trim() === "",
17913
+ attachments: attachments.map((attachment) => ({ ...attachment }))
17908
17914
  };
17909
17915
  const admittedRequestPath = join9(runDirectory, "admitted-request.json");
17910
17916
  await writeFile4(admittedRequestPath, `${JSON.stringify(admitted, null, 2)}
17911
17917
  `, "utf8");
17912
- await writeRoleInvocationLedger(admitted, admitted.role, options.model);
17913
- return {
17914
- role: "judge",
17915
- runId,
17916
- bookKey,
17917
- projectRoot,
17918
- instruction,
17919
- instructionEmpty,
17920
- attachments,
17921
- runDirectory,
17922
- sessionDirectory,
17923
- sessionFile,
17924
- admittedRequestPath,
17925
- ...ticketFields
17926
- };
17918
+ await writeRoleInvocationLedger(admitted, role, options.model);
17919
+ return { ...admitted, attachments, admittedRequestPath };
17927
17920
  }
17928
- function buildJudgeTransportPrompt(admitted, engineMaterial) {
17921
+ async function admitJudgeInvocation(options) {
17922
+ return admitStandardMaterialInvocation("judge", options);
17923
+ }
17924
+ async function admitInspectorInvocation(options) {
17925
+ return admitStandardMaterialInvocation("inspector", options);
17926
+ }
17927
+ function buildStandardMaterialTransportPrompt(admitted, engineMaterial) {
17929
17928
  const lines = [admitted.instructionEmpty ? "" : admitted.instruction];
17930
17929
  if (admitted.attachments.length > 0) {
17931
- lines.push("");
17932
- lines.push("\u5DF2\u53D7\u7406\u9644\u4EF6\uFF08\u51BB\u7ED3\u5FEB\u7167\u8DEF\u5F84\uFF09\uFF1A");
17933
- for (const attachment of admitted.attachments) {
17934
- lines.push(`- ${attachment.frozenPath}`);
17935
- }
17930
+ lines.push("", "\u5DF2\u53D7\u7406\u9644\u4EF6\uFF08\u51BB\u7ED3\u5FEB\u7167\u8DEF\u5F84\uFF09\uFF1A", ...admitted.attachments.map((attachment) => `- ${attachment.frozenPath}`));
17936
17931
  }
17937
17932
  return appendEngineSessionMaterial(lines, engineMaterial).join("\n");
17938
17933
  }
17934
+ function buildInspectorTransportPrompt(admitted, engineMaterial) {
17935
+ return buildStandardMaterialTransportPrompt(admitted, engineMaterial);
17936
+ }
17937
+ function buildJudgeTransportPrompt(admitted, engineMaterial) {
17938
+ return buildStandardMaterialTransportPrompt(admitted, engineMaterial);
17939
+ }
17939
17940
  async function ensureRunArtifactsDir(runDirectory) {
17940
17941
  const dir = join9(runDirectory, "artifacts");
17941
17942
  await mkdir2(dir, { recursive: true });
@@ -22665,6 +22666,60 @@ async function settleLawfulDoctorTerminalResult(admitted) {
22665
22666
  async function trySettleDoctorTerminalResult(admitted) {
22666
22667
  return settleLawfulDoctorTerminalResult(admitted);
22667
22668
  }
22669
+ function extractInspectorRoleOutcome(entries) {
22670
+ if (!isReceiptSettlementBindingClear(entries)) return void 0;
22671
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
22672
+ const message = entries[index]?.message;
22673
+ if (message?.role !== "toolResult" || message.toolName !== INSPECTOR_OUTPUT_TOOL_NAME) continue;
22674
+ if (!isAcceptedPackagedRoleTerminalResult(message)) continue;
22675
+ const details = message.details;
22676
+ if (typeof details !== "object" || details === null) continue;
22677
+ const status = Reflect.get(details, "status");
22678
+ if (status !== "pass" && status !== "bounce") continue;
22679
+ const findings = Reflect.get(details, "findings");
22680
+ return { kind: "accepted", role: "inspector", status, decisiveFacts: { findings } };
22681
+ }
22682
+ return void 0;
22683
+ }
22684
+ function findUnusableOutputReceipt(entries, toolName, isUsable, diagnostic) {
22685
+ let acceptedNonUsable;
22686
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
22687
+ const message = entries[index]?.message;
22688
+ if (message?.role !== "toolResult") continue;
22689
+ const residual = boundErroredToolCandidate(entries, index, message, toolName);
22690
+ if (residual !== void 0) {
22691
+ return { candidate: residual.candidate, diagnostic: residual.diagnostic };
22692
+ }
22693
+ if (acceptedNonUsable === void 0 && message.toolName === toolName && isAcceptedPackagedRoleTerminalResult(message) && !isUsable(message.details)) {
22694
+ acceptedNonUsable = message.details;
22695
+ }
22696
+ }
22697
+ return acceptedNonUsable === void 0 ? void 0 : { candidate: acceptedNonUsable, diagnostic };
22698
+ }
22699
+ async function trySettleInspectorTerminalResult(admitted) {
22700
+ const entries = await readLawfulSettlementEntries(admitted);
22701
+ if (entries === void 0) return void 0;
22702
+ const outcome = extractInspectorRoleOutcome(entries);
22703
+ if (outcome !== void 0) {
22704
+ return withOptionalGateProjection({
22705
+ roleOutcome: outcome,
22706
+ navigator: extractNavigatorFact(entries),
22707
+ artifacts: [],
22708
+ runId: admitted.runId
22709
+ }, admitted.sessionDirectory);
22710
+ }
22711
+ const unusable = findUnusableOutputReceipt(
22712
+ entries,
22713
+ INSPECTOR_OUTPUT_TOOL_NAME,
22714
+ (candidate) => isRecord8(candidate) && (candidate.status === "pass" || candidate.status === "bounce"),
22715
+ "\u7ED9\u4E8B\u4E2D\u56DE\u6267\u65E0\u663E\u5F0F pass/bounce"
22716
+ );
22717
+ return unusable === void 0 ? void 0 : settleFailureTerminalResult(admitted, {
22718
+ cause: "output",
22719
+ diagnostic: unusable.diagnostic,
22720
+ details: { candidate: unusable.candidate, acceptedReceipt: false }
22721
+ });
22722
+ }
22668
22723
  function extractNotaryRoleOutcome(entries) {
22669
22724
  if (!isReceiptSettlementBindingClear(entries)) return void 0;
22670
22725
  for (let i = entries.length - 1; i >= 0; i -= 1) {
@@ -22694,39 +22749,24 @@ async function settleLawfulNotaryTerminalResult(admitted) {
22694
22749
  if (entries === void 0) return void 0;
22695
22750
  const extracted = extractNotaryRoleOutcome(entries);
22696
22751
  if (extracted === void 0) {
22697
- let acceptedNonUsable;
22698
- for (let index = entries.length - 1; index >= 0; index -= 1) {
22699
- const message = entries[index]?.message;
22700
- if (message?.role !== "toolResult") continue;
22701
- const residual = boundErroredToolCandidate(
22702
- entries,
22703
- index,
22704
- message,
22705
- NOTARY_OUTPUT_TOOL_NAME
22706
- );
22707
- if (residual !== void 0) {
22708
- return settleFailureTerminalResult(admitted, {
22709
- cause: "output",
22710
- diagnostic: residual.diagnostic,
22711
- details: { candidate: residual.candidate, acceptedReceipt: false }
22712
- });
22713
- }
22714
- if (acceptedNonUsable === void 0 && message.toolName === NOTARY_OUTPUT_TOOL_NAME && isAcceptedPackagedRoleTerminalResult(message)) {
22752
+ const unusable = findUnusableOutputReceipt(
22753
+ entries,
22754
+ NOTARY_OUTPUT_TOOL_NAME,
22755
+ (candidate) => {
22715
22756
  try {
22716
- validateRecordedNotaryOutput(message.details);
22757
+ validateRecordedNotaryOutput(candidate);
22758
+ return true;
22717
22759
  } catch {
22718
- acceptedNonUsable = message.details;
22760
+ return false;
22719
22761
  }
22720
- }
22721
- }
22722
- if (acceptedNonUsable !== void 0) {
22723
- return settleFailureTerminalResult(admitted, {
22724
- cause: "output",
22725
- diagnostic: "\u7B26\u5B9D\u90CE\u56DE\u6267\u65E0\u663E\u5F0F pass/bounce",
22726
- details: { candidate: acceptedNonUsable, acceptedReceipt: false }
22727
- });
22728
- }
22729
- return void 0;
22762
+ },
22763
+ "\u7B26\u5B9D\u90CE\u56DE\u6267\u65E0\u663E\u5F0F pass/bounce"
22764
+ );
22765
+ return unusable === void 0 ? void 0 : settleFailureTerminalResult(admitted, {
22766
+ cause: "output",
22767
+ diagnostic: unusable.diagnostic,
22768
+ details: { candidate: unusable.candidate, acceptedReceipt: false }
22769
+ });
22730
22770
  }
22731
22771
  const navigator = extractNavigatorFact(entries);
22732
22772
  return withOptionalGateProjection(
@@ -23405,6 +23445,7 @@ var init_settlement = __esm({
23405
23445
  init_method_skill();
23406
23446
  init_navigator_invocation_identity();
23407
23447
  init_receipt_delivery_policy();
23448
+ init_inspector_contracts();
23408
23449
  init_invocation();
23409
23450
  init_terminal();
23410
23451
  CONCISE_DIAGNOSTIC_MAX_CHARS = 480;
@@ -25090,6 +25131,73 @@ var init_notary_run = __esm({
25090
25131
  }
25091
25132
  });
25092
25133
 
25134
+ // src/public-cli/inspector-run.ts
25135
+ function buildInspectorActivationExtraArgs(admitted, options = {}) {
25136
+ return [
25137
+ "--no-skills",
25138
+ "--no-prompt-templates",
25139
+ "--no-themes",
25140
+ "--no-context-files",
25141
+ "--session",
25142
+ admitted.sessionFile,
25143
+ "--session-dir",
25144
+ admitted.sessionDirectory,
25145
+ ...options.extraPiArgs ?? [],
25146
+ "--ak-role",
25147
+ "inspector",
25148
+ "--mode",
25149
+ "json",
25150
+ ...buildSeatModelCliArgs(options.model),
25151
+ buildInspectorTransportPrompt(admitted, engineSessionMaterialFromOptions(options))
25152
+ ];
25153
+ }
25154
+ async function runPublicInspector(argv, env, io, parse) {
25155
+ let admitted;
25156
+ try {
25157
+ const parsed = parse(argv);
25158
+ admitted = await admitInspectorInvocation({
25159
+ home: env.home,
25160
+ cwd: env.cwd,
25161
+ instruction: parsed.instruction,
25162
+ attachmentPaths: parsed.attachmentPaths,
25163
+ ...parsed.project === void 0 ? {} : { project: parsed.project },
25164
+ ...env.createRunId === void 0 ? {} : { createRunId: env.createRunId },
25165
+ ...env.model === void 0 ? {} : { model: env.model }
25166
+ });
25167
+ } catch (error) {
25168
+ if (error instanceof CliUsageError) {
25169
+ presentStructuralRejection(error, io);
25170
+ return { exitCode: 2 };
25171
+ }
25172
+ throw error;
25173
+ }
25174
+ const extraArgs = buildInspectorActivationExtraArgs(admitted, {
25175
+ packageRoot: env.packageRoot,
25176
+ ...env.model === void 0 ? {} : { model: env.model },
25177
+ ...env.engine === void 0 ? {} : { engine: env.engine },
25178
+ ...env.extraPiArgs === void 0 ? {} : { extraPiArgs: env.extraPiArgs }
25179
+ });
25180
+ return runAdmittedOneShotRole({
25181
+ admitted,
25182
+ env,
25183
+ io,
25184
+ extraArgs,
25185
+ adapters: { trySettle: trySettleInspectorTerminalResult, shouldPresentSettled: () => true },
25186
+ ...env.engine === void 0 ? {} : { effectiveEngine: env.engine }
25187
+ });
25188
+ }
25189
+ var init_inspector_run = __esm({
25190
+ "src/public-cli/inspector-run.ts"() {
25191
+ "use strict";
25192
+ init_engine_material();
25193
+ init_cli_errors();
25194
+ init_invocation();
25195
+ init_config2();
25196
+ init_one_shot_dispatch();
25197
+ init_settlement();
25198
+ }
25199
+ });
25200
+
25093
25201
  // src/public-cli/judge-run.ts
25094
25202
  import { writeFile as writeFile10 } from "node:fs/promises";
25095
25203
  import { join as join19 } from "node:path";
@@ -29329,6 +29437,26 @@ async function runAkRole(argv, env) {
29329
29437
  ...result2.terminal === void 0 ? {} : { terminal: result2.terminal }
29330
29438
  };
29331
29439
  }
29440
+ if (parsed.command === "inspector") {
29441
+ const agentDir = resolveAgentDir(env, home);
29442
+ const cwd = env.cwd ?? process.cwd();
29443
+ const config = await loadAndValidateConfig(home, env.packageRoot);
29444
+ const credentials = env.credentials ?? await loadCredentialProviders(agentDir);
29445
+ const seat = resolveEffectiveSeat(config, "inspector", credentials, invocationFromParsed(parsed));
29446
+ const result2 = await runPublicInspector(parsed.args, {
29447
+ home,
29448
+ agentDir,
29449
+ packageRoot: env.packageRoot,
29450
+ cwd,
29451
+ credentials,
29452
+ ...env.correlationId === void 0 ? {} : { correlationId: env.correlationId },
29453
+ ...env.piRunner === void 0 ? {} : { piRunner: env.piRunner },
29454
+ ...seat.selection === void 0 ? {} : { model: seat.selection },
29455
+ ...projectSeatEngine(seat),
29456
+ ...env.createRunId === void 0 ? {} : { createRunId: env.createRunId }
29457
+ }, io, PUBLIC_ROLE_ARGV.inspector.parse);
29458
+ return { exitCode: result2.exitCode, ...result2.terminal === void 0 ? {} : { terminal: result2.terminal } };
29459
+ }
29332
29460
  if (parsed.command === "merger") {
29333
29461
  const agentDir = resolveAgentDir(env, home);
29334
29462
  const cwd = env.cwd ?? process.cwd();
@@ -29405,6 +29533,7 @@ var init_cli = __esm({
29405
29533
  init_doctor_run();
29406
29534
  init_fixer_run();
29407
29535
  init_notary_run();
29536
+ init_inspector_run();
29408
29537
  init_judge_run();
29409
29538
  init_merger_run();
29410
29539
  init_reviewer_run();
@@ -29422,6 +29551,7 @@ var init_cli = __esm({
29422
29551
  doctor: { parse: parseDoctorArgv, options: optionsForOwner("doctor") },
29423
29552
  merger: { parse: parseMergerArgv, options: optionsForOwner("merger") },
29424
29553
  notary: { parse: parseNotaryArgv, options: optionsForOwner("notary") },
29554
+ inspector: { parse: parseInspectorArgv, options: optionsForOwner("inspector") },
29425
29555
  reviewer: { parse: parseReviewerArgv, options: optionsForOwner("reviewer") },
29426
29556
  /** Deterministic analysis seat (#336) — argv parse only; no LLM admission. */
29427
29557
  analyst: { parse: parseAnalystArgv, options: optionsForOwner("analyst") }
@@ -8,13 +8,11 @@ export const INTERNAL_ROLE_ENTRYPOINT_RELATIVE = "extensions/role-runtime.ts";
8
8
  export const PUBLIC_CALLABLE_ROLES = PACKAGED_ROLE_REGISTRY.map((entry) => entry.role);
9
9
  /** Automatic attendance seat — configurable, never a caller-selected command. */
10
10
  export const AUTOMATIC_NAVIGATOR_SEAT = "navigator";
11
- /** Automatic gate seats — configurable model only; never caller commands (#453). */
11
+ /** Automatic province seat — configurable model only; never a caller command. */
12
12
  export const AUTOMATIC_GATEKEEPER_SEAT = "gatekeeper";
13
- export const AUTOMATIC_INSPECTOR_SEAT = "inspector";
14
- /** All automatic configurable seats (no independent public activation command). */
13
+ /** Automatic-only configurable seats. Inspector remains automatic-capable via its callable seat. */
15
14
  export const AUTOMATIC_CONFIGURABLE_SEATS = [
16
15
  AUTOMATIC_GATEKEEPER_SEAT,
17
- AUTOMATIC_INSPECTOR_SEAT,
18
16
  AUTOMATIC_NAVIGATOR_SEAT,
19
17
  ];
20
18
  export const PUBLIC_CONFIGURABLE_SEATS = [
@@ -44,7 +44,7 @@ import {
44
44
  packagedRoleMetadata,
45
45
  } from "../src/packaged-role-registry.ts";
46
46
  import { createPiJudgeAuditor } from "../src/judge-auditor.ts";
47
- import { loadMainRoleSessionMaterials } from "../src/session-opening-materials.ts";
47
+ import { loadGatekeeperSessionMaterials, loadMainRoleSessionMaterials } from "../src/session-opening-materials.ts";
48
48
  const extensionPath = fileURLToPath(import.meta.url);
49
49
  const packageRoot = fileURLToPath(new URL("..", import.meta.url));
50
50
  const navigatorRoutePlaybookPath = fileURLToPath(new URL("../resources/navigator-route-playbook.md", import.meta.url));
@@ -265,6 +265,7 @@ export default function roleRuntime(pi: ExtensionAPI): void {
265
265
  loadDoctorCase,
266
266
  auditDoctorCompliance: createPiDoctorAuditor(),
267
267
  loadNotarySoul: () => loadMainRoleSessionMaterials("notary"),
268
+ loadInspectorSoul: () => loadGatekeeperSessionMaterials("inspector"),
268
269
  loadNotarySourceRun: loadNotarySourceRunLocator,
269
270
  loadNavigatorWorkContext: (options) => loadNavigatorWorkContext(pi, options),
270
271
  createNavigatorAttendance: (options) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akagilnc/pi-workflow-roles",
3
- "version": "0.1.2525",
3
+ "version": "0.1.2535",
4
4
  "description": "Soul-bound workflow roles for Pi",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -5,9 +5,10 @@ import { executeAuditorChild, type AuditorCompletion, type AuditorDecisionTool }
5
5
  import { openToolObject } from "./open-tool-schema.ts";
6
6
  import type { NoReceiptLifecycleFacts } from "./receipt-delivery-policy.ts";
7
7
  import { loadGatekeeperSessionMaterials } from "./session-opening-materials.ts";
8
+ import { INSPECTOR_OUTPUT_TOOL_NAME } from "./inspector-contracts.ts";
8
9
 
9
10
  export const GATEKEEPER_OUTPUT_TOOL = "ak_gatekeeper_output";
10
- export const INSPECTOR_OUTPUT_TOOL = "ak_inspector_output";
11
+ export const INSPECTOR_OUTPUT_TOOL = INSPECTOR_OUTPUT_TOOL_NAME;
11
12
  export const NOTARY_OUTPUT_TOOL = "ak_notary_output";
12
13
  const SUBJECT_TOOL = "ak_gatekeeper_subject";
13
14
 
@@ -0,0 +1 @@
1
+ export const INSPECTOR_OUTPUT_TOOL_NAME = "ak_inspector_output" as const;
@@ -0,0 +1,20 @@
1
+ import { Type } from "typebox";
2
+
3
+ import { INSPECTOR_OUTPUT_TOOL_NAME } from "./inspector-contracts.ts";
4
+ import { openToolObject } from "./open-tool-schema.ts";
5
+ import { withInfrastructureFailureDeclaration } from "./package-contracts/terminating-infrastructure.ts";
6
+
7
+ export { INSPECTOR_OUTPUT_TOOL_NAME as INSPECTOR_OUTPUT_TOOL };
8
+
9
+ export const inspectorOutputSchema = withInfrastructureFailureDeclaration(openToolObject(Type.Object({
10
+ status: Type.Unknown({ description: "pass | bounce — 取值形状指引,不作拒收依据" }),
11
+ findings: Type.Unknown({ description: "随交卷留存的问题记录" }),
12
+ })));
13
+
14
+ export function projectInspectorReceipt(parameters: unknown) {
15
+ return {
16
+ content: [{ type: "text" as const, text: "给事中回执已受理" }],
17
+ details: parameters,
18
+ terminate: true as const,
19
+ };
20
+ }