@akagilnc/pi-workflow-roles 0.1.5406 → 0.1.5475

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 (93) hide show
  1. package/CLAUDE.md +1 -1
  2. package/README.md +42 -55
  3. package/README.zh-CN.md +59 -73
  4. package/THIRD_PARTY_NOTICES.md +4 -7
  5. package/dist/acp-host/production-host.js +8261 -9073
  6. package/dist/collector-tool-schemas.js +1 -1
  7. package/dist/compliance-transport.js +2 -5
  8. package/dist/engine-detour-usage.js +3 -30
  9. package/dist/gatekeeper-role.js +4 -18
  10. package/dist/headless-host/description.js +0 -209
  11. package/dist/headless-host/production-host.js +6973 -8035
  12. package/dist/host-contracts.js +8 -0
  13. package/dist/migrate-book-topology.js +30 -27
  14. package/dist/packaged-role-registry.js +1 -9
  15. package/dist/pi/role-turn-host.js +37 -19
  16. package/dist/public-cli/auto-resume.js +29 -66
  17. package/dist/public-cli/countersign-run.js +4 -18
  18. package/dist/public-cli/instruction-seat-run.js +59 -76
  19. package/dist/public-cli/main.js +9844 -10720
  20. package/dist/public-cli/option-definitions.js +1 -1
  21. package/dist/public-cli/post-admission.js +204 -285
  22. package/dist/public-cli/process-cancel.js +8 -0
  23. package/dist/public-cli/run-lifecycle.js +24 -94
  24. package/dist/public-cli/settlement.js +614 -1524
  25. package/dist/public-cli/terminal.js +23 -53
  26. package/dist/public-role-summons.js +3 -8
  27. package/dist/receipt-delivery-policy.js +11 -12
  28. package/dist/run-terminal-artifacts.js +19 -14
  29. package/dist/serialize-thrown-value.js +7 -1
  30. package/dist/submission-ledger.js +21 -89
  31. package/package.json +1 -1
  32. package/packets/fixer-repair.md +3 -1
  33. package/packets/judge-apply.md +7 -16
  34. package/packets/judge-authority.md +7 -17
  35. package/packets/judge-plan.md +7 -18
  36. package/packets/judge-review.md +8 -22
  37. package/packets/judge-submission.md +4 -7
  38. package/resources/collector-bot-handbook.md +2 -2
  39. package/resources/diarist-collect.md +2 -2
  40. package/resources/engine-dispatch.md +2 -2
  41. package/resources/navigator-route-playbook.md +1 -1
  42. package/resources/secretariat-ticket-identity.md +1 -1
  43. package/scripts/build-package.mjs +0 -2
  44. package/souls/coder-output-guide.md +3 -3
  45. package/souls/coder.md +2 -3
  46. package/souls/doctor-auditor.md +0 -3
  47. package/souls/fixer-auditor.md +0 -2
  48. package/souls/fixer-output-guide.md +3 -3
  49. package/souls/fixer.md +2 -2
  50. package/souls/gate-output-guide.md +1 -1
  51. package/souls/quality-law.md +2 -0
  52. package/src/acp-host/role-turn-host.ts +168 -75
  53. package/src/collector-tool-schemas.ts +1 -1
  54. package/src/compliance-transport.ts +3 -6
  55. package/src/engine-detour-usage.ts +3 -33
  56. package/src/external-host-turn-loop.ts +81 -36
  57. package/src/gatekeeper-role.ts +5 -20
  58. package/src/headless-host/description.ts +4 -214
  59. package/src/headless-host/production-host.ts +2 -1
  60. package/src/headless-host/role-turn-host.ts +153 -186
  61. package/src/host-contracts.ts +13 -10
  62. package/src/navigator-public-session.ts +1 -1
  63. package/src/navigator-session-contracts.ts +1 -1
  64. package/src/package-contracts/gatekeeper-output.ts +1 -1
  65. package/src/package-contracts/navigator-output.ts +1 -1
  66. package/src/package-contracts/terminating-infrastructure.ts +1 -1
  67. package/src/packaged-role-registry.ts +2 -10
  68. package/src/pi/adapter.ts +0 -3
  69. package/src/pi/role-turn-host.ts +42 -28
  70. package/src/prepared-role-turn.ts +2 -0
  71. package/src/public-cli/auto-resume.ts +27 -66
  72. package/src/public-cli/countersign-run.ts +4 -22
  73. package/src/public-cli/instruction-seat-run.ts +79 -80
  74. package/src/public-cli/option-definitions.ts +1 -1
  75. package/src/public-cli/post-admission.ts +264 -340
  76. package/src/public-cli/process-cancel.ts +9 -0
  77. package/src/public-cli/run-lifecycle.ts +25 -126
  78. package/src/public-cli/settlement.ts +792 -1912
  79. package/src/public-cli/terminal.ts +29 -69
  80. package/src/public-role-summons.ts +3 -8
  81. package/src/receipt-delivery-policy.ts +11 -12
  82. package/src/role-envelope.ts +16 -9
  83. package/src/role-runtime.ts +14 -81
  84. package/src/run-terminal-artifacts.ts +21 -17
  85. package/src/serialize-thrown-value.ts +7 -1
  86. package/src/submission-ledger.ts +30 -116
  87. package/dist/audit-escalation.js +0 -7
  88. package/dist/pi/known-failure.js +0 -51
  89. package/dist/typed-provider-http.js +0 -57
  90. package/dist/upstream-error-testimony.js +0 -19
  91. package/src/pi/known-failure.ts +0 -76
  92. package/src/typed-provider-http.ts +0 -89
  93. package/src/upstream-error-testimony.ts +0 -45
@@ -3,7 +3,7 @@ import { openToolObject } from "./open-tool-schema.js";
3
3
  import { withTerminatingOutputDeclarations } from "./package-contracts/terminating-infrastructure.js";
4
4
  /**
5
5
  * #1088: LLM gathers evidence via host CLI and submits the receipt.
6
- * Field declarations guide the model — host must not pure-shape-reject (第 0 条 / ADR 0057).
6
+ * Field declarations guide the model — host must not pure-shape-reject (仓内 CLAUDE.md 开篇 / ADR 0057).
7
7
  * Presence of `groups` remains the Collector terminal discriminator for settlement/analyst.
8
8
  */
9
9
  export const collectorOutputBaseSchema = openToolObject(Type.Object({
@@ -1,7 +1,7 @@
1
1
  import { auditorRunDirectory } from "./auditor-dossier-tool.js";
2
2
  import { officerConclusionReask } from "./gatekeeper-role.js";
3
3
  import { receivedDiscriminator } from "./submission-errors.js";
4
- import { coalesceSubmissionRows } from "./public-cli/terminal.js";
4
+ import { currentReplyRows } from "./public-cli/terminal.js";
5
5
  import { readableGateItem } from "./readable-gate-item.js";
6
6
  import { deliveryLimitFromConfig } from "./receipt-delivery-policy.js";
7
7
  import { isRecord } from "./unknown-value.js";
@@ -78,10 +78,7 @@ async function projectAuditorTerminal(summoned) {
78
78
  };
79
79
  }
80
80
  if (outcome.kind === "accepted") {
81
- const rows = coalesceSubmissionRows(
82
- outcome.payloads,
83
- summoned.terminal?.submissions
84
- );
81
+ const rows = currentReplyRows(summoned.terminal);
85
82
  if (rows.length === 0) {
86
83
  return readComplianceCandidate({}, usage);
87
84
  }
@@ -27,8 +27,8 @@ export const ENGINE_DETOUR_CALL_KIND = "engine-detour-call";
27
27
  export const ENGINE_DETOUR_TOOL_USAGE_FACT_KEY = "engineDetourToolUsage";
28
28
  /**
29
29
  * Run-relative sitian volume path for one detour call.
30
- * Openable once the run directory is known (resume.command / top-level runId);
31
- * contains no runId bytes itself (#108 + #537 AC8).
30
+ * Openable once the run directory is known from the terminal's run id.
31
+ * Contains no runId bytes itself (#108 + #537).
32
32
  */
33
33
  export const ENGINE_DETOUR_CALL_RECORD_FILE_RELATIVE = `session/${ENGINE_DETOUR_CALL_KIND}/records.jsonl`;
34
34
  /** stdout UTF-8 byte length (ticket-frozen metric; empty stdout is real 0). */
@@ -167,7 +167,7 @@ export async function readEngineDetourToolUsage(input) {
167
167
  }
168
168
  const pointer = {
169
169
  identity: record.identity,
170
- recordFile,
170
+ recordFile: ENGINE_DETOUR_CALL_RECORD_FILE_RELATIVE,
171
171
  kind: record.kind,
172
172
  level: record.level,
173
173
  };
@@ -180,33 +180,6 @@ export async function readEngineDetourToolUsage(input) {
180
180
  const calls = Array.from(callsByToolCallId.values());
181
181
  return { callCount: calls.length, calls };
182
182
  }
183
- /**
184
- * Project usage onto the public Terminal face.
185
- * Non-resumable: keep absolute recordFile (runId already public via top-level runId).
186
- * Resumable: keep an openable run-relative recordFile and identity with no runId
187
- * bytes (#108 single disclosure + #537 AC8 reopen).
188
- */
189
- export function projectEngineDetourToolUsageForPublicTerminal(usage, options) {
190
- if (options.discloseRecordFile)
191
- return usage;
192
- return {
193
- callCount: usage.callCount,
194
- calls: usage.calls.map((call) => ({
195
- toolCallId: call.toolCallId,
196
- durationMs: call.durationMs,
197
- ...(call.code === undefined ? {} : { code: call.code }),
198
- ...(call.stdoutByteLength === undefined
199
- ? {}
200
- : { stdoutByteLength: call.stdoutByteLength }),
201
- recordPointer: {
202
- identity: call.recordPointer.identity,
203
- kind: call.recordPointer.kind,
204
- level: call.recordPointer.level,
205
- recordFile: ENGINE_DETOUR_CALL_RECORD_FILE_RELATIVE,
206
- },
207
- })),
208
- };
209
- }
210
183
  /** One shared invocation.json reader (ENOENT → undefined; other errors propagate). */
211
184
  function readInvocationRecord(runDirectory) {
212
185
  try {
@@ -5,8 +5,10 @@ import { INSPECTOR_OUTPUT_TOOL_NAME } from "./inspector-contracts.js";
5
5
  import { REVIEW_QUEUE_STATUSES, REVIEW_SUBMISSION_OUTPUT_TOOL_NAME } from "./review-submission.js";
6
6
  import { GATEKEEPER_OUTPUT_TOOL_NAME } from "./package-contracts/gatekeeper-output.js";
7
7
  import { roleSubmissionDeclaration } from "./role-submission-declarations.js";
8
+ import { currentReplyRows } from "./public-cli/terminal.js";
8
9
  import { runIdFromRunDirectory } from "./run-terminal-artifacts.js";
9
10
  import { isRecord } from "./unknown-value.js";
11
+ import { serializeThrownValue } from "./serialize-thrown-value.js";
10
12
  export const INSPECTOR_OUTPUT_TOOL = INSPECTOR_OUTPUT_TOOL_NAME;
11
13
  export const NOTARY_OUTPUT_TOOL = REVIEW_SUBMISSION_OUTPUT_TOOL_NAME;
12
14
  function gateSeatLabel(stage) {
@@ -31,11 +33,6 @@ export { GatekeeperDecisionError } from "./submission-errors.js";
31
33
  * the shared contract module (with infrastructure-failure declaration).
32
34
  */
33
35
  export const GATEKEEPER_TOOL_SPEC = roleSubmissionDeclaration("gatekeeper");
34
- function failureReason(error) {
35
- if (error instanceof AggregateError)
36
- return error.errors.map(failureReason).join("; ");
37
- return error instanceof Error ? `${error.name}: ${error.message}` : String(error);
38
- }
39
36
  /** Original decision bytes — no sentinel replacement (#836). */
40
37
  function retainedReceipt(decision) {
41
38
  return decision;
@@ -72,17 +69,6 @@ function projectOfficerDecision(officer, decision, fallbackStatus) {
72
69
  * identity. Never guess from undivided submissions — sole row included — history
73
70
  * stays on terminal.submissions (#836 presentation).
74
71
  */
75
- function thisCourtOfficerPayloads(terminal) {
76
- const outcome = terminal?.roleOutcome;
77
- // This-court identity only from accepted/audit_escalation settlement payloads
78
- // (#879). Failure history is not this-court (#953) — it rides submissions.
79
- if (outcome !== undefined && (outcome.kind === "accepted" || outcome.kind === "audit_escalation")) {
80
- if (outcome.payloads !== undefined && outcome.payloads.length > 0)
81
- return outcome.payloads;
82
- }
83
- // No sole-row identity guess: undivided submissions are not this-court (#879).
84
- return [];
85
- }
86
72
  /**
87
73
  * Failure/transport channel surfaces recorded history beside the failure
88
74
  * (#836 A.3) via the historical carrier only (#953 — not failure.payloads).
@@ -130,7 +116,7 @@ function withOfficerRunId(result, summoned) {
130
116
  function projectOfficerTerminal(officer, summoned) {
131
117
  const terminal = summoned.terminal;
132
118
  const outcome = terminal?.roleOutcome;
133
- const thisCourt = thisCourtOfficerPayloads(terminal);
119
+ const thisCourt = currentReplyRows(terminal);
134
120
  if (outcome === undefined) {
135
121
  const detail = summoned.stderr ?? "";
136
122
  const failurePayloads = officerFailurePayloads(terminal);
@@ -221,7 +207,7 @@ export async function projectGatekeeperRun(options) {
221
207
  catch (error) {
222
208
  return {
223
209
  officer,
224
- result: { status: "transport_failure", stage: officer, reason: failureReason(error) },
210
+ result: { status: "transport_failure", stage: officer, reason: serializeThrownValue(error) },
225
211
  };
226
212
  }
227
213
  return {
@@ -54,215 +54,6 @@ function codexTomlStringTable(entries) {
54
54
  const parts = Object.entries(entries).map(([key, value]) => `${key}=${codexTomlString(value)}`);
55
55
  return `{${parts.join(",")}}`;
56
56
  }
57
- /**
58
- * Free-form JSON leaf for Type.Unknown under Codex strict transport.
59
- * Strict rejects bare untyped nodes and root-level additionalProperties:true;
60
- * a $defs anyOf of JSON values (with nested additionalProperties as $ref)
61
- * is accepted and keeps array/object receipts expressible.
62
- * Package code still does not validate or reject the receipt against schema.
63
- */
64
- const CODEX_JSON_VALUE_DEF = "codexJsonValue";
65
- const CODEX_JSON_VALUE_REF = `#/$defs/${CODEX_JSON_VALUE_DEF}`;
66
- const CODEX_JSON_VALUE_SCHEMA = Object.freeze({
67
- anyOf: Object.freeze([
68
- Object.freeze({ type: "string" }),
69
- Object.freeze({ type: "number" }),
70
- Object.freeze({ type: "boolean" }),
71
- Object.freeze({ type: "null" }),
72
- Object.freeze({ type: "array", items: Object.freeze({ $ref: CODEX_JSON_VALUE_REF }) }),
73
- Object.freeze({
74
- type: "object",
75
- properties: Object.freeze({}),
76
- required: Object.freeze([]),
77
- additionalProperties: Object.freeze({ $ref: CODEX_JSON_VALUE_REF }),
78
- }),
79
- ]),
80
- });
81
- /**
82
- * Derive a Codex/OpenAI-strict transport schema from the package open schema.
83
- * Legal open schema is untouched; this is a host-only transmission projection
84
- * (#646 / 0057 法意 / 0054 strict): every object closes, every property is
85
- * required, and only originally-optional fields become a null union (official
86
- * guidance: emulate optional via type|null). Originally-required fields stay
87
- * non-nullable. Nested open-tool anyOf wrappers are flattened so every branch
88
- * carries `type`. Type.Unknown / description-only leaves become a free JSON
89
- * $ref. Package code still does not validate or reject the receipt.
90
- */
91
- export function closeJsonSchemaForCodex(schema) {
92
- const closed = closeSchemaNode(schema);
93
- const existingDefs = isRecord(closed.$defs)
94
- ? closed.$defs
95
- : {};
96
- return {
97
- ...closed,
98
- $defs: {
99
- ...existingDefs,
100
- [CODEX_JSON_VALUE_DEF]: CODEX_JSON_VALUE_SCHEMA,
101
- },
102
- };
103
- }
104
- /** Pure null leaf only — composite type|null is stripped in-leaf, not dropped whole. */
105
- function isPureNullTypeSchema(value) {
106
- if (!isRecord(value))
107
- return false;
108
- if (value.type === "null")
109
- return true;
110
- if (Array.isArray(value.type) && value.type.length > 0 && value.type.every((t) => t === "null")) {
111
- return true;
112
- }
113
- return false;
114
- }
115
- /**
116
- * Within a leaf, remove null members from type arrays.
117
- * Required edges keep the non-null type(s); optional edges re-add null once.
118
- */
119
- function stripNullFromLeafType(leaf) {
120
- if (!isRecord(leaf) || !Array.isArray(leaf.type))
121
- return leaf;
122
- const nonNull = leaf.type.filter((t) => t !== "null");
123
- if (nonNull.length === leaf.type.length)
124
- return leaf;
125
- if (nonNull.length === 0)
126
- return { ...leaf, type: "null" };
127
- if (nonNull.length === 1)
128
- return { ...leaf, type: nonNull[0] };
129
- return { ...leaf, type: nonNull };
130
- }
131
- /**
132
- * Flatten nested anyOf wrappers into concrete leaf schemas.
133
- * Open-tool unions often wrap leaves in description-only anyOf shells that
134
- * lack `type`; strict structured output rejects those intermediate nodes.
135
- */
136
- function flattenUnionLeaves(schema) {
137
- if (!isRecord(schema))
138
- return [schema];
139
- if (Array.isArray(schema.anyOf)) {
140
- return schema.anyOf.flatMap(flattenUnionLeaves);
141
- }
142
- return [schema];
143
- }
144
- /** Drop pure-null leaves after in-leaf null stripping; optional edges re-add null once. */
145
- function nonNullLeaves(schema) {
146
- return flattenUnionLeaves(schema)
147
- .map(stripNullFromLeafType)
148
- .filter((leaf) => !isPureNullTypeSchema(leaf));
149
- }
150
- /**
151
- * Property edge under strict transport.
152
- * Required → closed non-null leaf(s). Optional → closed leaf(s) + null.
153
- */
154
- function closePropertySchema(schema, optional) {
155
- const description = isRecord(schema) && typeof schema.description === "string"
156
- ? { description: schema.description }
157
- : {};
158
- const leaves = nonNullLeaves(schema).map(closeSchemaNode);
159
- if (leaves.length === 0)
160
- return { type: "null", ...description };
161
- if (!optional) {
162
- const closed = leaves.length === 1 ? leaves[0] : { anyOf: leaves };
163
- // Codex strict does not allow sibling keys on $ref; put property guidance
164
- // on an enclosing schema instead of losing it or weakening the free-JSON ref.
165
- if (isRecord(closed) && typeof closed.$ref === "string") {
166
- return { anyOf: [closed], ...description };
167
- }
168
- return isRecord(closed) ? { ...closed, ...description } : closed;
169
- }
170
- return { anyOf: [...leaves, { type: "null" }], ...description };
171
- }
172
- /**
173
- * Strict generators require every schema node to declare `type` (or a $ref).
174
- * Type.Unknown / description-only leaves → free JSON $ref (not string): array
175
- * and object receipts stay expressible under --output-schema.
176
- */
177
- function ensureTypedLeaf(schema) {
178
- if (schema.type !== undefined)
179
- return schema;
180
- if (typeof schema.$ref === "string")
181
- return schema;
182
- if (isRecord(schema.properties) || schema.additionalProperties !== undefined) {
183
- return { ...schema, type: "object" };
184
- }
185
- if (schema.items !== undefined) {
186
- return { ...schema, type: "array" };
187
- }
188
- if (schema.const !== undefined) {
189
- const value = schema.const;
190
- if (value === null)
191
- return { ...schema, type: "null" };
192
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
193
- return { ...schema, type: typeof value };
194
- }
195
- }
196
- if (Array.isArray(schema.enum) && schema.enum.length > 0) {
197
- const sample = schema.enum.find((item) => item !== null);
198
- if (typeof sample === "string" || typeof sample === "number" || typeof sample === "boolean") {
199
- return { ...schema, type: typeof sample };
200
- }
201
- }
202
- // Free JSON via $defs. $ref must stand alone (strict rejects sibling keys).
203
- return { $ref: CODEX_JSON_VALUE_REF };
204
- }
205
- function originalRequiredNames(node) {
206
- if (!Array.isArray(node.required))
207
- return new Set();
208
- return new Set(node.required.filter((item) => typeof item === "string"));
209
- }
210
- function closeSchemaNode(node) {
211
- if (!isRecord(node))
212
- return node;
213
- // Already a ref (free-JSON leaf or pre-existing) — do not retype.
214
- if (typeof node.$ref === "string")
215
- return node;
216
- // Union node: flatten then close each concrete leaf (do not keep untyped shells).
217
- if (Array.isArray(node.anyOf)) {
218
- const leaves = nonNullLeaves(node).map(closeSchemaNode);
219
- if (leaves.length === 0)
220
- return { type: "null" };
221
- if (leaves.length === 1)
222
- return leaves[0];
223
- return { anyOf: leaves };
224
- }
225
- let out = { ...node };
226
- if (node.items !== undefined) {
227
- out.items = closeSchemaNode(node.items);
228
- }
229
- if (isRecord(node.$defs)) {
230
- out.$defs = Object.fromEntries(Object.entries(node.$defs).map(([key, value]) => [key, closeSchemaNode(value)]));
231
- }
232
- const hasProperties = isRecord(node.properties);
233
- const isObjectType = node.type === "object"
234
- || (Array.isArray(node.type) && node.type.includes("object"))
235
- || hasProperties
236
- || node.additionalProperties !== undefined;
237
- if (hasProperties) {
238
- const props = node.properties;
239
- const wasRequired = originalRequiredNames(node);
240
- const closedProps = {};
241
- const required = [];
242
- for (const [name, propSchema] of Object.entries(props)) {
243
- required.push(name);
244
- closedProps[name] = closePropertySchema(propSchema, !wasRequired.has(name));
245
- }
246
- out.properties = closedProps;
247
- out.required = required;
248
- out.additionalProperties = false;
249
- if (out.type === undefined)
250
- out.type = "object";
251
- // Object nodes must not also carry residual anyOf from the open copy.
252
- delete out.anyOf;
253
- }
254
- else if (isObjectType) {
255
- out.additionalProperties = false;
256
- if (!Array.isArray(out.required))
257
- out.required = [];
258
- if (out.type === undefined)
259
- out.type = "object";
260
- }
261
- else {
262
- out = ensureTypedLeaf(out);
263
- }
264
- return out;
265
- }
266
57
  /**
267
58
  * Project shared-envelope MCP rows into `codex -c mcp_servers.<name>.*` argv pairs.
268
59
  * Dot-path + TOML values per official config-advanced; spawn argv (no shell).