@akagilnc/pi-workflow-roles 0.1.4980 → 0.1.4992

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/acp-host/production-host.js +438 -456
  2. package/dist/analyst-gate-cycles-read.js +16 -11
  3. package/dist/analyst-metric-families/gate-cycles.js +2 -2
  4. package/dist/audit-escalation.js +4 -4
  5. package/dist/compliance-transport.js +2 -2
  6. package/dist/countersign-contracts.js +6 -5
  7. package/dist/doctor-evidence.js +2 -1
  8. package/dist/gatekeeper-role.js +20 -41
  9. package/dist/headless-host/production-host.js +438 -456
  10. package/dist/inspector-contracts.js +3 -2
  11. package/dist/migrate-book-topology.js +59 -54
  12. package/dist/navigator-invocation-identity.js +6 -4
  13. package/dist/notary-contracts.js +3 -19
  14. package/dist/package-contracts/auditor-output.js +4 -19
  15. package/dist/package-contracts/judge-output.js +6 -5
  16. package/dist/package-contracts/terminating-tools.js +9 -3
  17. package/dist/packaged-role-registry.js +10 -12
  18. package/dist/public-cli/countersign-run.js +1 -1
  19. package/dist/public-cli/main.js +90 -86
  20. package/dist/public-cli/option-definitions.js +2 -2
  21. package/dist/public-cli/settlement.js +11 -11
  22. package/dist/review-submission.js +20 -0
  23. package/dist/submission-errors.js +2 -2
  24. package/dist/submission-ledger.js +14 -2
  25. package/package.json +1 -1
  26. package/souls/doctor-auditor.md +1 -1
  27. package/souls/fixer-auditor.md +4 -4
  28. package/souls/gate-output-guide.md +2 -2
  29. package/souls/inspector.md +1 -1
  30. package/souls/judge-auditor.md +2 -2
  31. package/souls/notary.md +1 -1
  32. package/souls/quality-law.md +1 -1
  33. package/souls/secretariat.md +4 -5
  34. package/src/analyst-gate-cycles-read.ts +17 -9
  35. package/src/analyst-metric-families/gate-cycles.ts +2 -2
  36. package/src/audit-escalation.ts +8 -8
  37. package/src/auditor-role.ts +1 -1
  38. package/src/compliance-transport.ts +7 -7
  39. package/src/countersign-contracts.ts +10 -8
  40. package/src/countersign-role.ts +6 -35
  41. package/src/doctor-evidence.ts +2 -1
  42. package/src/doctor-role.ts +1 -2
  43. package/src/gatekeeper-role.ts +30 -55
  44. package/src/host-contracts.ts +4 -3
  45. package/src/inspector-contracts.ts +7 -6
  46. package/src/inspector-role.ts +3 -20
  47. package/src/judge-role.ts +29 -49
  48. package/src/navigator-invocation-identity.ts +16 -4
  49. package/src/notary-contracts.ts +8 -26
  50. package/src/notary-role.ts +1 -1
  51. package/src/package-contracts/auditor-output.ts +6 -27
  52. package/src/package-contracts/judge-output.ts +10 -8
  53. package/src/package-contracts/terminating-tools.ts +9 -3
  54. package/src/packaged-role-registry.ts +12 -13
  55. package/src/pi/adapter.ts +6 -5
  56. package/src/public-cli/countersign-run.ts +1 -1
  57. package/src/public-cli/option-definitions.ts +2 -2
  58. package/src/public-cli/settlement.ts +13 -14
  59. package/src/review-submission.ts +29 -0
  60. package/src/role-envelope.ts +17 -9
  61. package/src/role-runtime.ts +32 -15
  62. package/src/submission-errors.ts +6 -6
  63. package/src/{gatekeeper-pass-envelope.ts → submission-gate.ts} +29 -16
  64. package/src/submission-ledger.ts +13 -3
  65. package/src/ticket-trajectory.ts +9 -4
  66. package/src/worker-role.ts +16 -2
@@ -81,7 +81,7 @@ function optionalDispatchReason(raw) {
81
81
  return raw;
82
82
  }
83
83
  function isGateTerminatingToolName(toolName) {
84
- return DISPATCH_TOOLS.has(toolName) || OFFICER_TOOL_TO_FACE[toolName] !== undefined;
84
+ return toolName === "ak_submission_output" || DISPATCH_TOOLS.has(toolName) || OFFICER_TOOL_TO_FACE[toolName] !== undefined;
85
85
  }
86
86
  /**
87
87
  * toolCallIds whose paired toolResult is an accepted receipt (`isError === false`).
@@ -176,7 +176,7 @@ function extractAllAcceptedGateToolCalls(rows) {
176
176
  }
177
177
  return out;
178
178
  }
179
- function projectAcceptedGateCall(filePath, rows, call) {
179
+ function projectAcceptedGateCall(filePath, rows, call, pointerOfficer) {
180
180
  // Continuous memory volumes carry many summons; span only this binding's interval.
181
181
  const span = requireAcceptedGateSpan(intervalRowsForGateCall(rows, call.rowIndex), filePath);
182
182
  const status = readAcceptedGateStatus(call.args);
@@ -208,7 +208,9 @@ function projectAcceptedGateCall(filePath, rows, call) {
208
208
  ...bindingFields,
209
209
  };
210
210
  }
211
- const officer = OFFICER_TOOL_TO_FACE[call.toolName];
211
+ const officer = call.toolName === "ak_submission_output"
212
+ ? pointerOfficer
213
+ : OFFICER_TOOL_TO_FACE[call.toolName];
212
214
  if (officer === undefined) {
213
215
  // isGateTerminatingToolName already screened; keep loud if tables drift.
214
216
  throw new Error(`accepted gate receipt has unknown officer tool ${call.toolName} in ${filePath}`);
@@ -225,7 +227,7 @@ function projectAcceptedGateCall(filePath, rows, call) {
225
227
  ...bindingFields,
226
228
  };
227
229
  }
228
- async function classifyAuditorVolume(filePath) {
230
+ async function classifyAuditorVolume(filePath, pointerOfficer) {
229
231
  // Canonical JSONL errors propagate — failure honesty (never wash to fewer rounds).
230
232
  const rows = await readLedgerSessionJsonl(filePath);
231
233
  const accepted = extractAllAcceptedGateToolCalls(rows);
@@ -234,7 +236,9 @@ async function classifyAuditorVolume(filePath) {
234
236
  return [];
235
237
  const volumes = [];
236
238
  for (const call of accepted) {
237
- const projected = projectAcceptedGateCall(filePath, rows, call);
239
+ const projected = call.toolName === "ak_submission_output" && pointerOfficer === undefined
240
+ ? undefined // Shared tool alone carries no officer identity; a typed pointer does.
241
+ : projectAcceptedGateCall(filePath, rows, call, pointerOfficer);
238
242
  if (projected !== undefined)
239
243
  volumes.push(projected);
240
244
  }
@@ -330,7 +334,9 @@ async function resolveOfficerSessionFromPointerFile(pointerPath) {
330
334
  if (typeof sessionFile !== "string" || sessionFile.trim() === "") {
331
335
  throw new Error(`direct officer run pointer missing sessionFile in ${pointerPath}`);
332
336
  }
333
- return sessionFile;
337
+ const officer = raw.officer === "inspector" || raw.officer === "notary"
338
+ ? raw.officer : undefined;
339
+ return { sessionFile, ...(officer === undefined ? {} : { officer }) };
334
340
  }
335
341
  /**
336
342
  * Read and pair gate-cycle rounds from one or more auditor-roles directories.
@@ -368,17 +374,16 @@ export async function readAnalystGateCyclesFromAuditorRoles(auditorRolesDirector
368
374
  for (const name of names) {
369
375
  const path = join(directory, name);
370
376
  const fromPointer = name.endsWith(".pointer.json");
371
- const sessionPath = fromPointer
377
+ const pointer = fromPointer
372
378
  ? await resolveOfficerSessionFromPointerFile(path)
373
- : path;
374
- if (sessionPath === undefined)
375
- continue;
379
+ : undefined;
380
+ const sessionPath = pointer?.sessionFile ?? path;
376
381
  if (fromPointer) {
377
382
  if (classifiedOfficerSessions.has(sessionPath))
378
383
  continue;
379
384
  classifiedOfficerSessions.add(sessionPath);
380
385
  }
381
- const classified = await classifyAuditorVolume(sessionPath);
386
+ const classified = await classifyAuditorVolume(sessionPath, pointer?.officer);
382
387
  for (const volume of classified) {
383
388
  if (options.parentSessionFile !== undefined &&
384
389
  volume.parentSessionFile !== undefined &&
@@ -31,9 +31,9 @@ function emptyAccum() {
31
31
  function absorbRound(accum, round) {
32
32
  accum.rounds += 1;
33
33
  accum.wallSum += round.officerWallMs;
34
- if (round.status === "bounce")
34
+ if (round.status === "bounce" || round.status === "continue")
35
35
  accum.bounceCount += 1;
36
- if (round.status === "pass")
36
+ if (round.status === "pass" || round.status === "converged")
37
37
  accum.passCount += 1;
38
38
  }
39
39
  function finishOfficer(officer, accum) {
@@ -89,8 +89,8 @@ export function isAuditEscalationResult(value) {
89
89
  */
90
90
  export async function disposeComplianceDecision(decision, handlers, deliveredOutput) {
91
91
  switch (decision.status) {
92
- case "pass":
93
- return await handlers.pass(decision.usage);
92
+ case "converged":
93
+ return await handlers.converged(decision.usage);
94
94
  case "no-receipt":
95
95
  // The parent candidate remains accepted, but its parallel audit leg is a
96
96
  // public typed fact and must not be collapsed into an ordinary pass.
@@ -104,8 +104,8 @@ export async function disposeComplianceDecision(decision, handlers, deliveredOut
104
104
  throw new Error("Compliance received projection handler is unavailable");
105
105
  }
106
106
  return await handlers.received(decision, decision.usage === undefined ? {} : { usage: decision.usage });
107
- case "bounce":
108
- return await handlers.bounce(decision.violations);
107
+ case "continue":
108
+ return await handlers.continue(decision.violations);
109
109
  case "escalate":
110
110
  return await handlers.escalate(projectAuditEscalation(decision, deliveredOutput));
111
111
  case "transport_failure":
@@ -21,8 +21,8 @@ function tryReadComplianceCandidate(arguments_, usage) {
21
21
  }
22
22
  const args = arguments_;
23
23
  const status = args.status;
24
- if (status === "pass") return { status, receipt: arguments_, ...usage === void 0 ? {} : { usage } };
25
- if (status === "bounce") return { status, violations: readListField(args.violations), receipt: arguments_, ...usage === void 0 ? {} : { usage } };
24
+ if (status === "converged") return { status, receipt: arguments_, ...usage === void 0 ? {} : { usage } };
25
+ if (status === "continue") return { status, violations: readListField(args.violations), receipt: arguments_, ...usage === void 0 ? {} : { usage } };
26
26
  if (status === "escalate") {
27
27
  return {
28
28
  status,
@@ -1,18 +1,19 @@
1
- const COUNTERSIGN_OUTPUT_TOOL_NAME = "ak_countersign_output";
1
+ import { REVIEW_SUBMISSION_OUTPUT_TOOL_NAME } from "./review-submission.js";
2
+ const COUNTERSIGN_OUTPUT_TOOL_NAME = REVIEW_SUBMISSION_OUTPUT_TOOL_NAME;
2
3
  function validateRecordedCountersignOutput(verdict) {
3
4
  if (verdict === null || typeof verdict !== "object" || Array.isArray(verdict)) {
4
5
  throw new Error("Countersign verdict has no execution discriminator");
5
6
  }
6
- let countersignStatus;
7
+ let status;
7
8
  try {
8
- countersignStatus = verdict.countersignStatus;
9
+ status = verdict.status;
9
10
  } catch {
10
11
  throw new Error("Countersign verdict has no execution discriminator");
11
12
  }
12
- if (typeof countersignStatus !== "string") {
13
+ if (typeof status !== "string") {
13
14
  throw new Error("Countersign verdict has no execution discriminator");
14
15
  }
15
- if (["converged", "continue", "escalate"].includes(countersignStatus)) {
16
+ if (["converged", "continue", "escalate"].includes(status)) {
16
17
  return verdict;
17
18
  }
18
19
  throw new Error("Countersign verdict has no execution discriminator");
@@ -59,6 +59,8 @@ function deriveSession(content, id) {
59
59
  let accepted, observedCommit, turns = 0, calls = 0, tokens = 0;
60
60
  const statuses = [], commits = [];
61
61
  for (const row of rows) {
62
+ if (row.type === "custom" && row.customType === "ak-role-submission-closure" && record(row.data) && row.data.isError === false && typeof row.data.toolName === "string" && isTerminatingToolName(row.data.toolName))
63
+ accepted = row;
62
64
  const message = record(row.message) ? row.message : undefined;
63
65
  if (message?.role === "assistant") {
64
66
  for (const part of Array.isArray(message.content) ? message.content : [])
@@ -81,7 +83,6 @@ function deriveSession(content, id) {
81
83
  continue;
82
84
  throw error;
83
85
  }
84
- accepted = row;
85
86
  const facts = acceptedFacts(message.toolName, details);
86
87
  if (facts.commit && facts.commit !== observedCommit) {
87
88
  commits.push({ source: id, commit: facts.commit });
@@ -1,11 +1,12 @@
1
1
  import { auditorRunDirectory } from "./auditor-dossier-tool.js";
2
- import { packagedGateDecision, packagedGateStageLabel } from "./packaged-role-registry.js";
2
+ import { packagedGateStageLabel } from "./packaged-role-registry.js";
3
3
  import { GatekeeperDecisionError } from "./submission-errors.js";
4
4
  import { INSPECTOR_OUTPUT_TOOL_NAME } from "./inspector-contracts.js";
5
+ import { REVIEW_SUBMISSION_OUTPUT_TOOL_NAME } from "./review-submission.js";
5
6
  import { GATEKEEPER_OUTPUT_TOOL_NAME, gatekeeperDecisionSchema, gatekeeperOutputSchema, } from "./package-contracts/gatekeeper-output.js";
6
7
  import { runIdFromRunDirectory } from "./run-terminal-artifacts.js";
7
8
  export const INSPECTOR_OUTPUT_TOOL = INSPECTOR_OUTPUT_TOOL_NAME;
8
- export const NOTARY_OUTPUT_TOOL = "ak_notary_output";
9
+ export const NOTARY_OUTPUT_TOOL = REVIEW_SUBMISSION_OUTPUT_TOOL_NAME;
9
10
  function gateSeatLabel(stage) {
10
11
  return packagedGateStageLabel(stage) ?? stage;
11
12
  }
@@ -67,17 +68,17 @@ function readRecord(value) {
67
68
  }
68
69
  /**
69
70
  * Read only the conclusion field for queueing (#753).
70
- * pass | bounce | escalate → queue signal + raw receipt.
71
+ * converged | continue | escalate → queue signal + raw receipt.
71
72
  * Anything else accepted → needs_reask (resume speaker), never unreadable/parent-stand.
72
73
  * `fallbackStatus` is the terminal outcome.status when the receipt body has no status key
73
74
  * (keeps missing-args sentinel intact as the receipt).
74
75
  */
75
- /** Map 给事中 countersignStatus onto the shared gate queue words (#969). */
76
- function gateStatusFromCountersign(status) {
76
+ /** Map the shared review verdict onto the gate queue words (#1028). */
77
+ function reviewQueueStatus(status) {
77
78
  if (status === "converged")
78
- return "pass";
79
+ return "converged";
79
80
  if (status === "continue")
80
- return "bounce";
81
+ return "continue";
81
82
  if (status === "escalate")
82
83
  return "escalate";
83
84
  return undefined;
@@ -85,31 +86,14 @@ function gateStatusFromCountersign(status) {
85
86
  function projectOfficerDecision(officer, decision, fallbackStatus) {
86
87
  const receipt = retainedReceipt(decision);
87
88
  const record = readRecord(decision);
88
- // 给事中: only countersignStatus, strict three-word map; never generic status,
89
- // never unmapped raw word, never fallbackStatus (#969 / ADR 0040/0055).
90
- if (packagedGateDecision(officer) === "countersign-status") {
91
- const countersignStatus = record !== undefined && typeof record.countersignStatus === "string"
92
- ? record.countersignStatus
93
- : undefined;
94
- const status = typeof countersignStatus === "string"
95
- ? gateStatusFromCountersign(countersignStatus)
96
- : undefined;
97
- if (status === "pass") {
98
- return { status: "pass", officer, receipt };
99
- }
100
- if (status === "bounce" || status === "escalate") {
101
- return { status, officer, receipt };
102
- }
103
- return { status: "needs_reask", officer, receipt };
104
- }
105
- // inspector / notary / auditor: shared gate words on generic status.
106
89
  const status = (record !== undefined && typeof record.status === "string" ? record.status : undefined)
107
90
  ?? fallbackStatus;
108
- if (status === "pass") {
109
- return { status: "pass", officer, receipt };
91
+ const queueStatus = typeof status === "string" ? reviewQueueStatus(status) : undefined;
92
+ if (queueStatus === "converged") {
93
+ return { status: "converged", officer, receipt };
110
94
  }
111
- if (status === "bounce" || status === "escalate") {
112
- return { status, officer, receipt };
95
+ if (queueStatus === "continue" || queueStatus === "escalate") {
96
+ return { status: queueStatus, officer, receipt };
113
97
  }
114
98
  return { status: "needs_reask", officer, receipt };
115
99
  }
@@ -161,8 +145,8 @@ export function officerRunIdFromSummoned(summoned) {
161
145
  return undefined;
162
146
  }
163
147
  function withOfficerRunId(result, summoned) {
164
- if (result.status !== "pass"
165
- && result.status !== "bounce"
148
+ if (result.status !== "converged"
149
+ && result.status !== "continue"
166
150
  && result.status !== "escalate"
167
151
  && result.status !== "needs_reask") {
168
152
  return result;
@@ -233,23 +217,18 @@ function projectOfficerTerminal(officer, summoned) {
233
217
  }, summoned);
234
218
  }
235
219
  /**
236
- * Plain-language re-ask when the officer conclusion is not pass|bounce|escalate.
220
+ * Plain-language re-ask when the officer conclusion is not converged|continue|escalate.
237
221
  * Not a packaged engine handbook line (#755 exception for 读不出三态).
238
- * inspector / notary / auditor keep shared gate words; 给事中 uses own three-state
239
- * field and words so reask does not invite non-contract values (#969 / ADR 0055).
222
+ * Every review officer uses the same `status` field and three queue words (#1028).
240
223
  */
241
- export const OFFICER_CONCLUSION_REASK = "上次交卷的结论不是 pass、bounce、escalate 三态之一。请重新输出,结论字段写明其一;打回或上呈的话就是给对方看的原文。";
242
- /** 给事中 re-ask: countersignStatus converged|continue|escalate only (#969). */
243
- export const COUNTERSIGN_CONCLUSION_REASK = "上次交卷的 countersignStatus 不是 converged、continue、escalate 三态之一。请重新输出,countersignStatus 写明其一;封驳或上呈的话就是给对方看的原文。";
224
+ export const OFFICER_CONCLUSION_REASK = "上次交卷的 status 不是 converged、continue、escalate 三态之一。请重新输出,status 写明其一;continue 或 escalate 的话就是给对方看的原文。";
244
225
  /** Pick the re-ask line for the officer under review. */
245
226
  export function officerConclusionReask(officer) {
246
- return packagedGateDecision(officer) === "countersign-status"
247
- ? COUNTERSIGN_CONCLUSION_REASK
248
- : OFFICER_CONCLUSION_REASK;
227
+ return OFFICER_CONCLUSION_REASK;
249
228
  }
250
229
  /**
251
230
  * Summon (via injected seam) + project. Default summonGateOfficer drive lives
252
- * on the shared envelope (`gatekeeper-pass-envelope.ts`, ADR 0018 / #675) —
231
+ * on the shared envelope (`submission-gate.ts`, ADR 0018 / #675) —
253
232
  * role module keeps projection only.
254
233
  */
255
234
  export async function projectGatekeeperRun(options) {