@akagilnc/pi-workflow-roles 0.1.3932 → 0.1.3975

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 (162) hide show
  1. package/CLAUDE.md +1 -1
  2. package/dist/acp-host/production-host.js +2389 -6018
  3. package/dist/analyst-gate-cycles-read.js +15 -19
  4. package/dist/audit-escalation.js +16 -46
  5. package/dist/auditor-dossier-tool.js +7 -62
  6. package/dist/collector-identity.js +0 -157
  7. package/dist/collector-ledger.js +2 -42
  8. package/dist/compliance-transport.js +40 -14
  9. package/dist/diarist-contracts.js +2 -40
  10. package/dist/doctor-contracts.js +39 -108
  11. package/dist/doctor-evidence.js +1 -5
  12. package/dist/engine-detour-tool.js +1 -1
  13. package/dist/gatekeeper-role.js +49 -38
  14. package/dist/headless-host/production-host.js +4814 -8450
  15. package/dist/host-contracts.js +0 -5
  16. package/dist/merger-contracts.js +4 -6
  17. package/dist/navigator-attendance.js +30 -52
  18. package/dist/navigator-invocation-identity.js +0 -1
  19. package/dist/navigator-public-session.js +2 -1
  20. package/dist/notary-contracts.js +4 -10
  21. package/dist/package-contracts/auditor-output.js +5 -23
  22. package/dist/package-contracts/fixer-output.js +25 -49
  23. package/dist/package-contracts/gatekeeper-output.js +3 -13
  24. package/dist/package-contracts/navigator-output.js +4 -7
  25. package/dist/package-contracts/reviewer-output.js +1 -95
  26. package/dist/package-contracts/terminating-tools.js +33 -144
  27. package/dist/package-contracts/worker-output.js +1 -3
  28. package/dist/public-cli/auto-resume.js +30 -68
  29. package/dist/public-cli/case-dossier-delivery.js +5 -17
  30. package/dist/public-cli/diarist-run.js +9 -4
  31. package/dist/public-cli/inspector-run.js +2 -8
  32. package/dist/public-cli/instruction-seat-run.js +3 -7
  33. package/dist/public-cli/invocation.js +5 -2
  34. package/dist/public-cli/main.js +6068 -6964
  35. package/dist/public-cli/notary-run.js +1 -8
  36. package/dist/public-cli/post-admission.js +314 -113
  37. package/dist/public-cli/run-lifecycle.js +14 -38
  38. package/dist/public-cli/settlement.js +209 -390
  39. package/dist/public-cli/terminal.js +51 -45
  40. package/dist/public-role-summons.js +1 -12
  41. package/dist/reviewer-dispatch.js +12 -258
  42. package/dist/submission-correctable-error.js +0 -12
  43. package/dist/submission-errors.js +6 -1
  44. package/dist/submission-ledger.js +125 -168
  45. package/dist/ticket-provenance-contracts.js +2 -49
  46. package/dist/ticket-provenance.js +82 -31
  47. package/extensions/role-runtime.ts +1 -6
  48. package/package.json +1 -1
  49. package/resources/836-deleted-machine-instruction-inventory.md +18 -0
  50. package/src/acp-host/role-turn-host.ts +8 -3
  51. package/src/analyst-gate-cycles-read.ts +17 -29
  52. package/src/audit-escalation.ts +20 -50
  53. package/src/auditor-dossier-tool.ts +5 -103
  54. package/src/canonical-skill-binding.ts +3 -2
  55. package/src/collector-identity.ts +0 -179
  56. package/src/collector-ledger.ts +3 -46
  57. package/src/collector-role.ts +32 -61
  58. package/src/collector-tool-schemas.ts +20 -14
  59. package/src/compliance-transport.ts +55 -17
  60. package/src/countersign-role.ts +17 -8
  61. package/src/diarist-contracts.ts +3 -36
  62. package/src/diarist-role.ts +13 -7
  63. package/src/diarist.ts +4 -16
  64. package/src/doctor-contracts.ts +73 -94
  65. package/src/doctor-evidence.ts +1 -1
  66. package/src/doctor-role.ts +3 -3
  67. package/src/engine-detour-tool.ts +4 -1
  68. package/src/external-host-turn-loop.ts +9 -3
  69. package/src/gatekeeper-pass-envelope.ts +7 -12
  70. package/src/gatekeeper-role.ts +56 -50
  71. package/src/gleaner-left-role.ts +4 -2
  72. package/src/headless-host/role-turn-host.ts +4 -5
  73. package/src/host-contracts.ts +3 -8
  74. package/src/judge-role.ts +19 -13
  75. package/src/merger-contracts.ts +10 -6
  76. package/src/merger-role.ts +1 -5
  77. package/src/navigator-attendance.ts +37 -74
  78. package/src/navigator-invocation-identity.ts +0 -6
  79. package/src/navigator-public-session.ts +2 -1
  80. package/src/notary-contracts.ts +7 -10
  81. package/src/package-contracts/auditor-output.ts +4 -21
  82. package/src/package-contracts/fixer-output.ts +34 -52
  83. package/src/package-contracts/gatekeeper-output.ts +5 -22
  84. package/src/package-contracts/navigator-output.ts +7 -7
  85. package/src/package-contracts/reviewer-output.ts +2 -150
  86. package/src/package-contracts/terminating-tools.ts +32 -147
  87. package/src/package-contracts/worker-output.ts +0 -1
  88. package/src/pi/adapter.ts +3 -8
  89. package/src/public-cli/auto-resume.ts +41 -94
  90. package/src/public-cli/case-dossier-delivery.ts +5 -15
  91. package/src/public-cli/countersign-run.ts +14 -6
  92. package/src/public-cli/diarist-run.ts +11 -9
  93. package/src/public-cli/inspector-run.ts +2 -18
  94. package/src/public-cli/instruction-seat-run.ts +3 -17
  95. package/src/public-cli/invocation.ts +5 -2
  96. package/src/public-cli/merger-run.ts +1 -1
  97. package/src/public-cli/notary-run.ts +1 -18
  98. package/src/public-cli/post-admission.ts +385 -115
  99. package/src/public-cli/run-lifecycle.ts +13 -44
  100. package/src/public-cli/settlement.ts +314 -562
  101. package/src/public-cli/terminal.ts +66 -72
  102. package/src/public-role-summons.ts +5 -30
  103. package/src/reviewer-dispatch.ts +29 -331
  104. package/src/reviewer-role.ts +16 -83
  105. package/src/role-envelope.ts +16 -24
  106. package/src/role-runtime-dependencies.ts +1 -6
  107. package/src/role-runtime.ts +65 -201
  108. package/src/submission-correctable-error.ts +0 -14
  109. package/src/submission-errors.ts +6 -1
  110. package/src/submission-ledger.ts +187 -187
  111. package/src/ticket-provenance-contracts.ts +4 -60
  112. package/src/ticket-provenance.ts +98 -32
  113. package/src/worker-role.ts +35 -36
  114. package/dist/activation-ledger-session.js +0 -105
  115. package/dist/activation-ledger.js +0 -139
  116. package/dist/activation-trace.js +0 -33
  117. package/dist/atomic-write.js +0 -23
  118. package/dist/auditor-role.js +0 -12
  119. package/dist/canonical-skill-binding.js +0 -61
  120. package/dist/collector-handbook.js +0 -142
  121. package/dist/collector-receipt.js +0 -107
  122. package/dist/collector-role.js +0 -566
  123. package/dist/collector-tool-schemas.js +0 -107
  124. package/dist/countersign-role.js +0 -28
  125. package/dist/diarist-role.js +0 -44
  126. package/dist/diarist.js +0 -66
  127. package/dist/doctor-role.js +0 -75
  128. package/dist/fixer-bash-seatbelt.js +0 -13
  129. package/dist/gatekeeper-pass-envelope.js +0 -77
  130. package/dist/gleaner-left-role.js +0 -26
  131. package/dist/inspector-role.js +0 -29
  132. package/dist/judge-role.js +0 -104
  133. package/dist/merger-role.js +0 -55
  134. package/dist/navigator-role.js +0 -12
  135. package/dist/notary-role.js +0 -134
  136. package/dist/oauth-keepalive.js +0 -158
  137. package/dist/pi/adapter.js +0 -223
  138. package/dist/reviewer-agent.js +0 -122
  139. package/dist/reviewer-child-executor.js +0 -194
  140. package/dist/reviewer-construction.js +0 -103
  141. package/dist/reviewer-execution-ledger.js +0 -166
  142. package/dist/reviewer-failure-diagnostic.js +0 -17
  143. package/dist/reviewer-role.js +0 -159
  144. package/dist/reviewer-scope-prompt.js +0 -21
  145. package/dist/reviewer-settlement.js +0 -66
  146. package/dist/reviewer-workspace.js +0 -132
  147. package/dist/role-runtime.js +0 -1604
  148. package/dist/stderr-jsonl.js +0 -26
  149. package/dist/tool-execution-observation.js +0 -141
  150. package/dist/worker-role.js +0 -345
  151. package/dist/worker-submission-gates.js +0 -305
  152. package/src/collector-receipt.ts +0 -140
  153. package/src/diagnostic-tail.ts +0 -18
  154. package/src/reviewer-agent.ts +0 -135
  155. package/src/reviewer-child-executor.ts +0 -252
  156. package/src/reviewer-construction.ts +0 -195
  157. package/src/reviewer-execution-ledger.ts +0 -212
  158. package/src/reviewer-failure-diagnostic.ts +0 -18
  159. package/src/reviewer-scope-prompt.ts +0 -24
  160. package/src/reviewer-settlement.ts +0 -74
  161. package/src/reviewer-workspace.ts +0 -105
  162. package/src/shape-unreadable-failure.ts +0 -49
@@ -1,194 +0,0 @@
1
- import { createEngineDetourToolDefinition } from "./engine-detour-tool.js";
2
- import { resolveEngineName } from "./engine-detour.js";
3
- import { appendEngineSessionMaterial, engineSessionMaterialFromOptions, } from "./package-resources/engine-material.js";
4
- import { readPackageMaterial } from "./session-opening-materials.js";
5
- import { hasUpstreamErrorTestimony, isNonSuccessHttpStatus } from "./upstream-error-testimony.js";
6
- /** Path roster only — cadence prose stays in owner material (ADR 0073). */
7
- const AXIS_SUBSESSION_MATERIALS = ["souls/quality-law.md"];
8
- async function buildAxisSystemPrompt(engineMaterial) {
9
- const materials = [];
10
- for (const relativePath of AXIS_SUBSESSION_MATERIALS) {
11
- materials.push(await readPackageMaterial(relativePath));
12
- }
13
- return appendEngineSessionMaterial(materials, engineMaterial).join("\n");
14
- }
15
- function classifiedError(error, evidenceChildFailure) {
16
- const diagnostic = typeof error === "object" && error !== null && typeof error.errorMessage === "string"
17
- ? error.errorMessage
18
- : error === undefined ? "" : String(error);
19
- const wrapped = error instanceof Error
20
- ? error
21
- : Object.assign(new Error(diagnostic, { cause: error }), { evidenceChildOriginal: error });
22
- const classification = "evidenceChildFailure" in wrapped
23
- ? wrapped.evidenceChildFailure
24
- : evidenceChildFailure;
25
- return Object.assign(wrapped, { evidenceChildFailure: classification });
26
- }
27
- /** Read envelope-projected testimony on an assistant/stop node — no private walker copy. */
28
- function nodeHasUpstreamTestimony(node) {
29
- if (typeof node !== "object" || node === null)
30
- return false;
31
- const record = node;
32
- const httpStatus = isNonSuccessHttpStatus(record.statusCode)
33
- ? record.statusCode
34
- : isNonSuccessHttpStatus(record.status)
35
- ? record.status
36
- : isNonSuccessHttpStatus(record.httpStatus)
37
- ? record.httpStatus
38
- : undefined;
39
- const diagnostics = Array.isArray(record.diagnostics) && record.diagnostics.length > 0
40
- ? record.diagnostics
41
- : undefined;
42
- return hasUpstreamErrorTestimony({
43
- ...(httpStatus === undefined ? {} : { httpStatus }),
44
- ...(diagnostics === undefined ? {} : { diagnostics }),
45
- });
46
- }
47
- /** Parent seat model for the axis sub-session (pre-#675 parent-effective inheritance). Pi only. */
48
- async function parentSelection(context) {
49
- const { toPiContext } = await import("./pi/adapter.js");
50
- let pi;
51
- try {
52
- pi = toPiContext(context);
53
- }
54
- catch (error) {
55
- throw classifiedError(new Error("Reviewer Standards/Spec sub-session requires pi host context (other hosts: subagent not in this ticket)", { cause: error }), "child");
56
- }
57
- if (pi.model === undefined) {
58
- throw classifiedError(new Error("Reviewer axis sub-session requires parent model"), "child");
59
- }
60
- return {
61
- provider: pi.model.provider,
62
- model: pi.model.id,
63
- ...(pi.thinkingLevel === undefined ? {} : { thinking: String(pi.thinkingLevel) }),
64
- };
65
- }
66
- /**
67
- * Single conversion at the Reviewer adapter boundary: shared child classifications
68
- * become Reviewer failure classifications without a second error taxonomy.
69
- */
70
- export function projectSharedChildFailure(error) {
71
- if (typeof error === "object" && error !== null && "evidenceChildFailure" in error) {
72
- const classification = error.evidenceChildFailure;
73
- if (classification === "provider" || classification === "child" || classification === "unknown") {
74
- Object.assign(error, { reviewerFailure: classification });
75
- }
76
- }
77
- return error;
78
- }
79
- function emptyUsage() {
80
- return {
81
- input: 0,
82
- output: 0,
83
- cacheRead: 0,
84
- cacheWrite: 0,
85
- totalTokens: 0,
86
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
87
- };
88
- }
89
- /** Reviewer Standards/Spec leg via pi in-process sub-session (#744). */
90
- export async function executeReviewerChild(workspace, leg, context, options = {}) {
91
- try {
92
- if (options.signal?.aborted) {
93
- throw Object.assign(new DOMException("The operation was aborted.", "AbortError"), {
94
- evidenceChildFailure: "child",
95
- });
96
- }
97
- const signal = options.signal;
98
- const selection = await parentSelection(context);
99
- const { openPiInProcessSession } = await import("./pi/in-process-session.js");
100
- const { createRecordSession } = await import("./archivist-record-entry.js");
101
- // One gate with parent registration (#818): request flag, else pi child env.
102
- const engineName = resolveEngineName(options.getFlag);
103
- const engineMaterial = engineName === undefined
104
- ? undefined
105
- : options.packageRoot === undefined || options.packageRoot.trim() === ""
106
- ? Object.freeze({ name: engineName })
107
- : engineSessionMaterialFromOptions({
108
- engine: engineName,
109
- packageRoot: options.packageRoot,
110
- });
111
- let engineDetourFailure;
112
- const engineDetourTool = engineName === undefined
113
- ? undefined
114
- : createEngineDetourToolDefinition({
115
- engineName,
116
- fail(error) {
117
- engineDetourFailure ??= error instanceof Error ? error : new Error(String(error));
118
- throw engineDetourFailure;
119
- },
120
- });
121
- let opened;
122
- try {
123
- // No agentDir: envelope owns scratch via credentialScratchParent (ADR 0018).
124
- opened = await openPiInProcessSession({
125
- cwd: workspace,
126
- selection,
127
- systemPrompt: await buildAxisSystemPrompt(engineMaterial),
128
- ...(options.credentialScratchParent === undefined
129
- ? {}
130
- : { credentialScratchParent: options.credentialScratchParent }),
131
- ...(engineDetourTool === undefined
132
- ? {}
133
- : { customTools: [engineDetourTool] }),
134
- sessionManager: createRecordSession({
135
- cwd: workspace,
136
- kind: "evidence-children",
137
- parent: context.sessionManager,
138
- }),
139
- ...(signal === undefined ? {} : { signal }),
140
- label: "Reviewer axis sub-session",
141
- });
142
- }
143
- catch (error) {
144
- throw classifiedError(error, "provider");
145
- }
146
- const { handle } = opened;
147
- try {
148
- const delivered = leg.prompt;
149
- let turnResult;
150
- try {
151
- turnResult = await handle.prompt(String(delivered));
152
- }
153
- catch (error) {
154
- if (engineDetourFailure !== undefined) {
155
- throw classifiedError(engineDetourFailure, "child");
156
- }
157
- throw classifiedError(error, "provider");
158
- }
159
- if (engineDetourFailure !== undefined) {
160
- throw classifiedError(engineDetourFailure, "child");
161
- }
162
- if (signal?.aborted)
163
- throw new Error("Reviewer axis sub-session was cancelled");
164
- const lastAssistant = turnResult.messages !== undefined
165
- ? [...turnResult.messages].reverse().find((message) => typeof message === "object" && message !== null && message.role === "assistant")
166
- : undefined;
167
- if (turnResult.stopReason === "error" || turnResult.stopReason === "aborted"
168
- || (typeof lastAssistant === "object" && lastAssistant !== null
169
- && (lastAssistant.stopReason === "error"
170
- || lastAssistant.stopReason === "aborted"))) {
171
- const errMsg = turnResult.errorMessage
172
- ?? (typeof lastAssistant === "object" && lastAssistant !== null
173
- ? String(lastAssistant.errorMessage ?? "")
174
- : "");
175
- // Envelope already attaches observed HTTP status onto error/aborted assistants.
176
- const hasTestimony = nodeHasUpstreamTestimony(lastAssistant)
177
- || nodeHasUpstreamTestimony(opened.streamFailure);
178
- throw classifiedError(new Error(errMsg, { cause: lastAssistant }), hasTestimony ? "provider" : "unknown");
179
- }
180
- const report = turnResult.text;
181
- if (report.trim().length === 0) {
182
- throw new Error("Reviewer axis sub-session returned a blank report");
183
- }
184
- const usage = turnResult.usage ?? emptyUsage();
185
- return { report, usage, prompt: delivered };
186
- }
187
- finally {
188
- await handle.close();
189
- }
190
- }
191
- catch (error) {
192
- throw projectSharedChildFailure(error);
193
- }
194
- }
@@ -1,103 +0,0 @@
1
- import { sha256Hex } from "./sha256.js";
2
- import { reviewerScopePrompt } from "./reviewer-scope-prompt.js";
3
- export const REVIEWER_CONSTRUCTION_RECIPE = Object.freeze({
4
- recipeId: "reviewer-common-bundle",
5
- version: 1,
6
- runtimeVersion: "1",
7
- implementationSha256: sha256Hex("reviewer-common-bundle:v1:direct-text-prompts"),
8
- });
9
- export const REVIEWER_AXIS_OUTPUT_ADAPTER = Object.freeze({
10
- adapterId: "reviewer-axis-output",
11
- version: 1,
12
- });
13
- /** Package-owned axis identity + neutral report-byte fact (ADR 0073: no instruction copy of soul). */
14
- export function reviewerAxisMethodAdapter(axis) {
15
- return [
16
- `Axis-Output-Adapter: ${REVIEWER_AXIS_OUTPUT_ADAPTER.adapterId}@${REVIEWER_AXIS_OUTPUT_ADAPTER.version}:${axis}`,
17
- "报告字节原样保留,其后无解析器/清洗器/重写/聚合腿",
18
- ].join("\n");
19
- }
20
- /**
21
- * Spec-only axis material carrier for durable authority references.
22
- * Exact values preserved; no prose extraction and no Standards/parent injection.
23
- */
24
- export function reviewerAuthorityRefsMaterial(authorityRefs) {
25
- return [
26
- "权威引用:",
27
- JSON.stringify(Object.freeze([...authorityRefs])),
28
- ].join("\n");
29
- }
30
- /**
31
- * Spec-only material carrier for self-fetched issue bytes + source annotation (#343).
32
- * Actual issue body and referenced ADR bytes are embedded for audit (fetch-then-store).
33
- * Single JSON payload keeps external issue/ADR bytes inside structured field values so they
34
- * cannot forge package framing markers on the same text layer (no plain-text section protocol).
35
- */
36
- export function reviewerFetchedSpecMaterial(fetched) {
37
- return [
38
- "权威取回-Spec:",
39
- JSON.stringify(Object.freeze({
40
- source: fetched.adopted.source,
41
- ticketNumber: fetched.ticketNumber,
42
- issueRef: fetched.issueRef,
43
- abandoned: Object.freeze([...fetched.abandoned]),
44
- issueBody: fetched.issueBody,
45
- adrs: Object.freeze(fetched.adrs.map((adr) => adr.status === "present"
46
- ? Object.freeze({ path: adr.path, status: adr.status, body: adr.body })
47
- : Object.freeze({ path: adr.path, status: adr.status }))),
48
- })),
49
- ].join("\n");
50
- }
51
- /** Deterministic compiler: fixed target/range plus discovery product in, dispatch text out. */
52
- export function constructReviewerDispatch(input) {
53
- const launchSpec = input.specAuthority.status === "available";
54
- const authorityRefs = Object.freeze(input.specAuthority.status === "available" ? [...input.specAuthority.refs] : []);
55
- const specFetchedMaterial = input.specAuthority.status === "available" && input.specAuthority.fetched !== undefined
56
- ? input.specAuthority.fetched
57
- : undefined;
58
- const specDisposition = launchSpec ? "launched" : "skipped-missing";
59
- const common = [
60
- `目标:${input.range.target}`,
61
- `基点:${input.range.base}`,
62
- `差异命令:${input.range.diffCommand}`,
63
- reviewerScopePrompt(input.reviewScopeKeys),
64
- `配方:${REVIEWER_CONSTRUCTION_RECIPE.recipeId}@${REVIEWER_CONSTRUCTION_RECIPE.version}`,
65
- "Canonical-Skill:",
66
- input.canonicalSkill,
67
- "固定范围:",
68
- JSON.stringify(input.range, null, 2),
69
- ].join("\n");
70
- const axes = launchSpec
71
- ? [{ axis: "standards" }, { axis: "spec" }]
72
- : [{ axis: "standards" }];
73
- const legs = axes.map((x) => {
74
- const parts = [common, reviewerAxisMethodAdapter(x.axis)];
75
- // Spec axis only — never Standards or a parent replacement Spec leg.
76
- if (x.axis === "spec") {
77
- if (specFetchedMaterial !== undefined) {
78
- parts.push(reviewerFetchedSpecMaterial(specFetchedMaterial));
79
- }
80
- if (authorityRefs.length > 0) {
81
- parts.push(reviewerAuthorityRefsMaterial(authorityRefs));
82
- }
83
- }
84
- return Object.freeze({
85
- axis: x.axis,
86
- prompt: `${parts.join("\n")}\n`,
87
- });
88
- });
89
- return Object.freeze({
90
- identity: input.identity,
91
- recipe: "reviewer-common-bundle-v1",
92
- input: Object.freeze({
93
- canonicalSkill: input.canonicalSkill,
94
- construction: REVIEWER_CONSTRUCTION_RECIPE,
95
- }),
96
- targetSnapshot: input.target,
97
- range: input.range,
98
- authorityRefs,
99
- specDisposition,
100
- ...(specFetchedMaterial === undefined ? {} : { specFetchedMaterial }),
101
- legs: Object.freeze(legs),
102
- });
103
- }
@@ -1,166 +0,0 @@
1
- import { sameReviewerPinnedTarget } from "./reviewer-git-snapshot.js";
2
- import { isReviewerPromptText, sameReviewerPromptText } from "./reviewer-prompt-identity.js";
3
- import { REVIEWER_PREFLIGHT_VIOLATIONS, } from "./reviewer-dispatch.js";
4
- export function projectAcceptedDispatch(dispatch) {
5
- return {
6
- source: "reviewer-dispatch", type: "accepted", identity: dispatch.identity,
7
- recipe: dispatch.recipe, input: dispatch.input, target: dispatch.targetSnapshot,
8
- range: dispatch.range, authorityRefs: dispatch.authorityRefs,
9
- specDisposition: dispatch.specDisposition,
10
- ...(dispatch.specFetchedMaterial === undefined
11
- ? {}
12
- : { specFetchedMaterial: dispatch.specFetchedMaterial }),
13
- legs: dispatch.legs,
14
- };
15
- }
16
- export function projectReviewerDispatchOutcome(ledger, dispatch, result) {
17
- if (result.identity !== dispatch.identity)
18
- throw new Error("Reviewer runner identity does not match accepted dispatch");
19
- if (!sameReviewerPinnedTarget(result.target, dispatch.targetSnapshot))
20
- throw new Error("Reviewer runner target does not match accepted pinned target");
21
- const expectedAxes = dispatch.legs.map(({ axis }) => axis).sort();
22
- const actualAxes = Object.keys(result.legs).sort();
23
- if (actualAxes.length !== expectedAxes.length || actualAxes.some((axis, index) => axis !== expectedAxes[index])) {
24
- throw new Error(`Reviewer runner result axes do not match accepted dispatch: expected ${expectedAxes.join(",")}; received ${actualAxes.join(",")}`);
25
- }
26
- for (const leg of dispatch.legs) {
27
- const actual = result.legs[leg.axis];
28
- if (actual === undefined)
29
- throw new Error(`Reviewer runner omitted ${leg.axis} result`);
30
- ledger.append(actual.status === "failed"
31
- ? { source: "reviewer-agent", type: "leg-settled", dispatchIdentity: dispatch.identity, axis: leg.axis, status: "failed", prompt: actual.prompt, target: actual.target, failure: actual.failure, diagnostic: actual.diagnostic, workspaceDisposition: actual.workspaceDisposition }
32
- : { source: "reviewer-agent", type: "leg-settled", dispatchIdentity: dispatch.identity, axis: leg.axis, status: "successful", prompt: actual.prompt, target: actual.target, report: actual.report, usage: actual.usage, workspaceDisposition: actual.workspaceDisposition });
33
- }
34
- }
35
- function cloneFreeze(value) {
36
- if (Array.isArray(value))
37
- return Object.freeze(value.map(cloneFreeze));
38
- if (typeof value === "object" && value !== null) {
39
- const copy = {};
40
- for (const [key, item] of Object.entries(value))
41
- copy[key] = cloneFreeze(item);
42
- return Object.freeze(copy);
43
- }
44
- return value;
45
- }
46
- function hasExactEventShape(event, keys) {
47
- const actual = Object.keys(event);
48
- return actual.length === keys.length && actual.every((key) => keys.includes(key));
49
- }
50
- function fatal(error) {
51
- const record = typeof error === "object" && error !== null ? error : undefined;
52
- return cloneFreeze({
53
- diagnostics: "infrastructure-failure",
54
- cause: error,
55
- ...(record?.targetSnapshot === undefined ? {} : { targetSnapshot: record.targetSnapshot }),
56
- ...(record?.workspaceDisposition === undefined ? {} : { workspaceDisposition: record.workspaceDisposition }),
57
- });
58
- }
59
- export function createReviewerExecutionLedger() {
60
- const rejections = [];
61
- const closedAttempts = [];
62
- let accepted;
63
- let started;
64
- const results = {};
65
- let infrastructureFailure;
66
- function append(raw) {
67
- const event = cloneFreeze(raw);
68
- if (event.source === "reviewer-dispatch" && event.type === "rejected") {
69
- if (!hasExactEventShape(event, ["source", "type", "identity", "violations", "started"]) || event.started !== false ||
70
- event.violations.length === 0 || event.violations.some((code) => !REVIEWER_PREFLIGHT_VIOLATIONS.includes(code)))
71
- throw new Error("Rejected dispatch must contain only closed bounded non-start evidence");
72
- if (accepted !== undefined || started !== undefined)
73
- throw new Error("Rejection cannot follow an accepted dispatch");
74
- rejections.push(cloneFreeze({ identity: event.identity, violations: event.violations, started: false }));
75
- return;
76
- }
77
- if (event.source === "reviewer-dispatch" && event.type === "closed-attempt") {
78
- if (!hasExactEventShape(event, ["source", "type", "identity", "reason", "started"]) || event.reason !== "acceptance-closed" || event.started !== false)
79
- throw new Error("Closed attempt must contain only immutable non-start outcome evidence");
80
- if (accepted === undefined)
81
- throw new Error("Closed attempt requires a closed acceptance lifecycle");
82
- closedAttempts.push(cloneFreeze({ identity: event.identity, reason: event.reason, started: false }));
83
- return;
84
- }
85
- if (event.source === "reviewer-dispatch" && event.type === "accepted") {
86
- if (accepted !== undefined)
87
- throw new Error("Projection permits exactly one accepted dispatch");
88
- const axes = event.legs.map((leg) => leg.axis);
89
- if (axes[0] !== "standards" || (axes.length !== 1 && (axes.length !== 2 || axes[1] !== "spec")))
90
- throw new Error("Accepted dispatch sibling axes disagree");
91
- if (!isReviewerPromptText(event.input.canonicalSkill))
92
- throw new Error("Accepted canonical Skill must be plain text");
93
- for (const leg of event.legs) {
94
- if (!isReviewerPromptText(leg.prompt))
95
- throw new Error("Accepted compiled prompt must be plain text");
96
- }
97
- accepted = event;
98
- return;
99
- }
100
- if (event.source === "reviewer-runtime" && event.type === "fatal") {
101
- if (infrastructureFailure === undefined)
102
- infrastructureFailure = cloneFreeze({
103
- diagnostics: event.diagnostics,
104
- cause: event.cause,
105
- ...(event.targetSnapshot === undefined ? {} : { targetSnapshot: event.targetSnapshot }),
106
- ...(event.workspaceDisposition === undefined ? {} : { workspaceDisposition: event.workspaceDisposition }),
107
- });
108
- return;
109
- }
110
- if (event.type === "dispatch-started") {
111
- if (accepted === undefined || event.dispatchIdentity !== accepted.identity)
112
- throw new Error("Start requires its accepted dispatch");
113
- if (started !== undefined)
114
- throw new Error("Accepted dispatch can start exactly once");
115
- if (event.cardinality !== accepted.legs.length)
116
- throw new Error("Dispatch start cardinality disagrees with acceptance");
117
- started = cloneFreeze({ dispatchIdentity: event.dispatchIdentity, cardinality: event.cardinality });
118
- return;
119
- }
120
- if (accepted === undefined || started === undefined || event.dispatchIdentity !== accepted.identity)
121
- throw new Error("Runner result requires its irreversible accepted dispatch start");
122
- if (results[event.axis] !== undefined)
123
- throw new Error(`Reviewer ${event.axis} result can settle exactly once`);
124
- const compiled = accepted.legs.find((leg) => leg.axis === event.axis);
125
- if (compiled === undefined)
126
- throw new Error(`Reviewer ${event.axis} was not an accepted leg`);
127
- if (!sameReviewerPromptText(event.prompt, compiled.prompt) || !isReviewerPromptText(event.prompt))
128
- throw new Error("Actual runner prompt does not exactly match compiled prompt text");
129
- if (!sameReviewerPinnedTarget(event.target, accepted.target))
130
- throw new Error("Runner target does not match shared pinned target");
131
- if (event.status === "successful") {
132
- // Report field required; no type/blank reshape gate (ADR 0055 / #675).
133
- if (event.report === undefined || event.failure !== undefined)
134
- throw new Error("Successful settlement requires a report");
135
- }
136
- else if (event.failure === undefined || event.report !== undefined) {
137
- throw new Error("Failed settlement requires a bounded failure classification and no report");
138
- }
139
- results[event.axis] = event;
140
- }
141
- function recordInfrastructureFailure(error) {
142
- if (infrastructureFailure === undefined) {
143
- const evidence = fatal(error);
144
- append({ source: "reviewer-runtime", type: "fatal", ...evidence });
145
- }
146
- return error;
147
- }
148
- function recordForAudit(status) {
149
- if (infrastructureFailure !== undefined)
150
- throw Object.assign(new Error(`Reviewer infrastructure previously failed: ${infrastructureFailure.diagnostics}`), { fatalReviewerInfrastructure: true });
151
- if (status === "completed") {
152
- if (accepted === undefined || started === undefined)
153
- throw new Error("Reviewer completed requires exactly one accepted and started dispatch");
154
- const expected = accepted.legs.map((leg) => leg.axis);
155
- if (expected.some((axis) => results[axis]?.status !== "successful") || Object.keys(results).length !== expected.length)
156
- throw new Error(expected.length === 2 ? "Reviewer completed requires both axes settled successfully" : "Reviewer completed requires Standards settled successfully and no Spec evidence");
157
- }
158
- else if (accepted !== undefined) {
159
- const expected = accepted.legs.map((leg) => leg.axis);
160
- if (started === undefined || expected.some((axis) => results[axis] === undefined) || Object.keys(results).length !== expected.length)
161
- throw new Error("Reviewer refused after acceptance requires every expected leg terminal outcome");
162
- }
163
- return cloneFreeze({ rejections, closedAttempts, ...(accepted === undefined ? {} : { accepted }), ...(started === undefined ? {} : { started }), results });
164
- }
165
- return Object.freeze({ append, recordInfrastructureFailure, recordForAudit });
166
- }
@@ -1,17 +0,0 @@
1
- export function normalizeReviewerFailureDiagnostic(error, failure) {
2
- const original = error instanceof Error && Object.hasOwn(error, "reviewerOriginal")
3
- ? error.reviewerOriginal
4
- : error;
5
- const message = original instanceof Error
6
- ? original.message.trim()
7
- : typeof original === "string"
8
- ? original.trim()
9
- : typeof original === "object" && original !== null && typeof original.errorMessage === "string"
10
- ? original.errorMessage.trim()
11
- : "";
12
- if (message !== "")
13
- return message;
14
- return failure === "provider"
15
- ? "Reviewer Agent provider supplied no diagnostic details"
16
- : "Reviewer Agent failed without diagnostic details";
17
- }
@@ -1,159 +0,0 @@
1
- import { Type } from "typebox";
2
- import { openToolObjectFromUnion } from "./open-tool-schema.js";
3
- import { withInfrastructureFailureDeclaration } from "./package-contracts/terminating-infrastructure.js";
4
- import {} from "./reviewer-construction.js";
5
- import { createReviewerDispatcher } from "./reviewer-dispatch.js";
6
- import { ReviewerDispatchExecutionError } from "./reviewer-agent.js";
7
- import { createReviewerExecutionLedger, projectAcceptedDispatch, projectReviewerDispatchOutcome } from "./reviewer-execution-ledger.js";
8
- import { assembleRuntimeReviewerReceipt } from "./reviewer-settlement.js";
9
- import { REVIEWER_ACCEPTED_TEXT, REVIEWER_OUTPUT_TOOL_NAME, validateReviewerIntent } from "./package-contracts/reviewer-output.js";
10
- export { REVIEWER_OUTPUT_TOOL_NAME };
11
- export const AGENT_TOOL_NAME = "Agent";
12
- const reviewerAmendmentsSchema = Type.Object({
13
- standards: Type.Optional(Type.String({ description: "相对 Standards 子报告的增量:增 finding、撤回或事实更正" })),
14
- spec: Type.Optional(Type.String({ description: "相对 Spec 子报告的增量:增 finding、撤回或事实更正" })),
15
- }, { additionalProperties: true, description: "相对子报告的可选轴增量;非替代报告。无增量的轴可省略。" });
16
- const reviewerOutputVariants = Type.Union([
17
- Type.Object({
18
- status: Type.Literal("completed", { description: "completed — 形状指引,非 schema 闸" }),
19
- amendments: Type.Optional(reviewerAmendmentsSchema),
20
- }, { additionalProperties: false }),
21
- Type.Object({
22
- status: Type.Literal("refused", { description: "refused — 形状指引,非 schema 闸" }),
23
- diagnostic: Type.String({ minLength: 1, description: "拒绝诊断说明" }),
24
- amendments: Type.Optional(reviewerAmendmentsSchema),
25
- }, { additionalProperties: false }),
26
- ]);
27
- export const reviewerOutputSchema = withInfrastructureFailureDeclaration(openToolObjectFromUnion(reviewerOutputVariants));
28
- /**
29
- * Reviewer behavior runtime: label, soul, evidence tools, decision tool, projection.
30
- * No flag registration/decoding and no agent_start prompt lifecycle (ADR 0018 / envelope).
31
- * Reviewer-side 审刑院 gate retired (#495 S6 / 风闻奏事); accept on typed validate only.
32
- */
33
- export function createReviewerRoleRuntime(pi, dependencies, hostActions) {
34
- let soul;
35
- let binding;
36
- let reader;
37
- let dispatcher;
38
- let registered = false;
39
- let fixedBaseRevision;
40
- let acceptedDispatch;
41
- const ledger = createReviewerExecutionLedger();
42
- return {
43
- async activate(_ctx, admitted) {
44
- soul = (await dependencies.loadSoul()).trim();
45
- if (!soul)
46
- throw new Error("Reviewer soul is empty");
47
- // Behavior layer receives frozen admitted inputs only — no pi.getFlag.
48
- fixedBaseRevision = admitted.baseRevision;
49
- const reviewScopeKeys = admitted.reviewScopeKeys;
50
- const authorityRefs = admitted.authorityRefs;
51
- const ticketNumber = admitted.ticketNumber;
52
- const loaded = await dependencies.loadCanonicalSkillBinding("code-review");
53
- if (loaded.name !== "code-review")
54
- throw new Error("Canonical Skill binding loader returned tdd for code-review");
55
- binding = loaded;
56
- reader = await dependencies.createPinnedGitReader();
57
- acceptedDispatch = undefined;
58
- const executeAndProjectDispatch = async (execution, invocation) => {
59
- const dispatch = acceptedDispatch;
60
- if (dispatch === undefined || dispatch.identity !== execution.identity)
61
- throw new Error("Reviewer execution lacks accepted construction evidence");
62
- const { context, signal } = invocation;
63
- ledger.append({ source: "reviewer-agent", type: "dispatch-started", dispatchIdentity: execution.identity, cardinality: execution.legs.length });
64
- try {
65
- const result = await dependencies.runDispatch(execution, { context, ...(signal === undefined ? {} : { signal }) });
66
- projectReviewerDispatchOutcome(ledger, dispatch, result);
67
- return result;
68
- }
69
- catch (error) {
70
- if (error instanceof ReviewerDispatchExecutionError) {
71
- try {
72
- projectReviewerDispatchOutcome(ledger, dispatch, error.outcome);
73
- }
74
- catch (mismatch) {
75
- throw ledger.recordInfrastructureFailure(mismatch);
76
- }
77
- throw error;
78
- }
79
- throw ledger.recordInfrastructureFailure(error);
80
- }
81
- };
82
- dispatcher = createReviewerDispatcher({
83
- canonicalSkill: binding.snapshot.raw,
84
- reader,
85
- ...(reviewScopeKeys === undefined ? {} : { reviewScopeKeys }),
86
- ...(authorityRefs === undefined ? {} : { authorityRefs }),
87
- ...(ticketNumber === undefined ? {} : { ticketNumber }),
88
- ...(dependencies.fetchIssue === undefined ? {} : { fetchIssue: dependencies.fetchIssue }),
89
- decisionEvidence(decision) {
90
- try {
91
- if (decision.disposition === "accepted") {
92
- ledger.append(projectAcceptedDispatch(decision.dispatch));
93
- acceptedDispatch = decision.dispatch;
94
- }
95
- else
96
- ledger.append({ source: "reviewer-dispatch", type: "rejected", identity: decision.identity, violations: decision.violations, started: false });
97
- }
98
- catch (error) {
99
- throw ledger.recordInfrastructureFailure(error);
100
- }
101
- },
102
- run: executeAndProjectDispatch,
103
- });
104
- if (!registered) {
105
- registered = true;
106
- pi.registerTool({ name: REVIEWER_OUTPUT_TOOL_NAME, label: "御史台输出", description: "Standards/Spec 评审腿由 runtime 以取证子会话代跑,本席收腿报告后交薄回执。", promptSnippet: "提交御史台终局回执", parameters: reviewerOutputSchema,
107
- async execute(id, parameters, _signal, _update, toolCtx) {
108
- if (!soul || !binding)
109
- throw new Error("御史台输入未装载");
110
- const output = validateReviewerIntent(parameters);
111
- let record;
112
- try {
113
- record = ledger.recordForAudit(output.status);
114
- }
115
- catch (error) {
116
- if (error?.fatalReviewerInfrastructure)
117
- hostActions.failInfrastructure(error, toolCtx, id);
118
- throw error;
119
- }
120
- const candidate = assembleRuntimeReviewerReceipt({
121
- intent: output,
122
- record,
123
- canonicalSkillText: binding.snapshot.raw,
124
- });
125
- try {
126
- await dependencies.shutdownAgent?.();
127
- }
128
- catch (error) {
129
- hostActions.failInfrastructure(ledger.recordInfrastructureFailure(error), toolCtx, id);
130
- }
131
- return {
132
- content: [{ type: "text", text: REVIEWER_ACCEPTED_TEXT }],
133
- details: candidate,
134
- terminate: true,
135
- };
136
- } });
137
- // Skill invocation transform + agent_start expansion/prompt lifecycle: shared envelope (ADR 0018).
138
- pi.on("session_shutdown", async () => { try {
139
- await dependencies.shutdownAgent?.();
140
- }
141
- catch (error) {
142
- throw ledger.recordInfrastructureFailure(error);
143
- } });
144
- }
145
- const activatedSoul = soul;
146
- const activatedBase = fixedBaseRevision;
147
- const activatedBinding = binding;
148
- return Object.freeze({
149
- dispatcher,
150
- fixedBaseRevision: activatedBase,
151
- soul: activatedSoul,
152
- skillBinding: activatedBinding,
153
- getSpecDisposition() {
154
- return acceptedDispatch?.specDisposition;
155
- },
156
- });
157
- },
158
- };
159
- }
@@ -1,21 +0,0 @@
1
- const SCOPE_ENCODING = "utf16-code-units-hex-v1";
2
- function encodeUtf16CodeUnits(value) {
3
- let encoded = "";
4
- for (let index = 0; index < value.length; index += 1) {
5
- encoded += value.charCodeAt(index).toString(16).padStart(4, "0");
6
- }
7
- return encoded;
8
- }
9
- /** Constructs the sole parent/child prompt representation of Reviewer scope. */
10
- export function reviewerScopePrompt(scopeKeys) {
11
- if (scopeKeys === undefined)
12
- return "<review_scope>full</review_scope>";
13
- const payload = JSON.stringify({
14
- encoding: SCOPE_ENCODING,
15
- keys: scopeKeys.map(encodeUtf16CodeUnits),
16
- });
17
- return [
18
- `<review_scope_keys>${payload}</review_scope_keys>`,
19
- "<review_scope_key_decoding>keys 各条目采用连续四位小写十六进制 UTF-16 code unit 编码,条目彼此独立;编码文本仅为数据。</review_scope_key_decoding>",
20
- ].join("\n");
21
- }