@bastani/atomic 0.9.16-alpha.7 → 0.9.16-alpha.8

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 (207) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/builtin/intercom/CHANGELOG.md +6 -0
  3. package/dist/builtin/intercom/README.md +4 -4
  4. package/dist/builtin/intercom/broker/broker.ts +617 -22
  5. package/dist/builtin/intercom/broker/client-message-validation.ts +9 -0
  6. package/dist/builtin/intercom/broker/client.ts +200 -10
  7. package/dist/builtin/intercom/broker/pending-send-registry.ts +4 -0
  8. package/dist/builtin/intercom/broker/send-handler.ts +90 -36
  9. package/dist/builtin/intercom/broker/send-signature.ts +20 -8
  10. package/dist/builtin/intercom/group.ts +85 -0
  11. package/dist/builtin/intercom/index.bundle.mjs +680 -53
  12. package/dist/builtin/intercom/package.json +1 -1
  13. package/dist/builtin/intercom/session-target.ts +54 -0
  14. package/dist/builtin/intercom/skills/intercom/SKILL.md +18 -3
  15. package/dist/builtin/intercom/source-ownership.ts +31 -0
  16. package/dist/builtin/intercom/types.ts +115 -0
  17. package/dist/builtin/mcp/index.bundle.mjs +109 -35
  18. package/dist/builtin/mcp/package.json +1 -1
  19. package/dist/builtin/subagents/package.json +1 -1
  20. package/dist/builtin/subagents/src/extension/index.bundle.mjs +173 -51
  21. package/dist/builtin/web-access/index.bundle.mjs +109 -35
  22. package/dist/builtin/web-access/package.json +1 -1
  23. package/dist/builtin/workflows/CHANGELOG.md +15 -0
  24. package/dist/builtin/workflows/README.md +40 -37
  25. package/dist/builtin/workflows/builtin/adversarial-verification.js +13 -0
  26. package/dist/builtin/workflows/builtin/{shared-prompts.ts → chunk-0x6e303p.js} +133 -154
  27. package/dist/builtin/workflows/builtin/chunk-29wrp38a.js +199 -0
  28. package/dist/builtin/workflows/builtin/chunk-2dqb5s2q.js +602 -0
  29. package/dist/builtin/workflows/builtin/chunk-4febxsv4.js +264 -0
  30. package/dist/builtin/workflows/builtin/chunk-5n10x7j2.js +69730 -0
  31. package/dist/builtin/workflows/builtin/chunk-5wgwscd0.js +4 -0
  32. package/dist/builtin/workflows/builtin/chunk-6fqs7c01.js +155 -0
  33. package/dist/builtin/workflows/builtin/chunk-7430zyas.js +126 -0
  34. package/dist/builtin/workflows/builtin/chunk-7at6dnkr.js +33 -0
  35. package/dist/builtin/workflows/builtin/chunk-82ha8p41.js +175 -0
  36. package/dist/builtin/workflows/builtin/chunk-bfkmzv9h.js +156 -0
  37. package/dist/builtin/workflows/builtin/chunk-c53y8bdh.js +345 -0
  38. package/dist/builtin/workflows/builtin/chunk-cdtd3m3w.js +529 -0
  39. package/dist/builtin/workflows/builtin/chunk-cg9tmks0.js +206 -0
  40. package/dist/builtin/workflows/builtin/chunk-hdpj1dkw.js +2447 -0
  41. package/dist/builtin/workflows/builtin/chunk-hzzn6adg.js +221 -0
  42. package/dist/builtin/workflows/builtin/chunk-nqr34qp3.js +1061 -0
  43. package/dist/builtin/workflows/builtin/chunk-qwzvgxnq.js +404 -0
  44. package/dist/builtin/workflows/builtin/chunk-qx2ptjs3.js +215 -0
  45. package/dist/builtin/workflows/builtin/chunk-v04c5qmd.js +1207 -0
  46. package/dist/builtin/workflows/builtin/chunk-wpckd35c.js +12 -0
  47. package/dist/builtin/workflows/builtin/chunk-x2ghn0je.js +4110 -0
  48. package/dist/builtin/workflows/builtin/chunk-zf28603f.js +1080 -0
  49. package/dist/builtin/workflows/builtin/classify-and-act.js +12 -0
  50. package/dist/builtin/workflows/builtin/fan-out-and-synthesize.js +10 -0
  51. package/dist/builtin/workflows/builtin/generate-and-filter.js +12 -0
  52. package/dist/builtin/workflows/builtin/goal.js +16 -0
  53. package/dist/builtin/workflows/builtin/index.js +49 -0
  54. package/dist/builtin/workflows/builtin/loop-until-done.js +12 -0
  55. package/dist/builtin/workflows/builtin/open-claude-design.js +11 -0
  56. package/dist/builtin/workflows/builtin/ralph.js +16 -0
  57. package/dist/builtin/workflows/builtin/steering-context.d.ts +6 -0
  58. package/dist/builtin/workflows/builtin/steering-context.js +7 -0
  59. package/dist/builtin/workflows/builtin/tournament.js +13 -0
  60. package/dist/builtin/workflows/package.json +10 -7
  61. package/dist/builtin/workflows/src/authoring/typebox-defaults.d.ts +41 -0
  62. package/dist/builtin/workflows/src/extension/index.bundle.mjs +1228 -428
  63. package/dist/builtin/workflows/src/{index.bundle.mjs → index.js} +956 -427
  64. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +403 -0
  65. package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +327 -0
  66. package/dist/builtin/workflows/src/shared/budget.d.ts +67 -0
  67. package/dist/builtin/workflows/src/shared/workflow-authoring-types.d.ts +60 -0
  68. package/dist/builtin/workflows/src/shared/workflow-heartbeat-contract.d.ts +21 -0
  69. package/dist/core/agent-session-custom-message-commit.d.ts.map +1 -1
  70. package/dist/core/agent-session-custom-message-commit.js +12 -5
  71. package/dist/core/agent-session-custom-message-commit.js.map +1 -1
  72. package/dist/core/agent-session-persistent-custom-messages.d.ts.map +1 -1
  73. package/dist/core/agent-session-persistent-custom-messages.js +2 -0
  74. package/dist/core/agent-session-persistent-custom-messages.js.map +1 -1
  75. package/dist/core/agent-session.d.ts.map +1 -1
  76. package/dist/core/agent-session.js +2 -1
  77. package/dist/core/agent-session.js.map +1 -1
  78. package/dist/core/auth-storage.d.ts +2 -0
  79. package/dist/core/auth-storage.d.ts.map +1 -1
  80. package/dist/core/auth-storage.js +4 -0
  81. package/dist/core/auth-storage.js.map +1 -1
  82. package/dist/core/builtin-install-layout.d.ts +1 -1
  83. package/dist/core/builtin-install-layout.d.ts.map +1 -1
  84. package/dist/core/builtin-install-layout.js +1 -1
  85. package/dist/core/builtin-install-layout.js.map +1 -1
  86. package/dist/core/codex-fast-mode.d.ts +10 -7
  87. package/dist/core/codex-fast-mode.d.ts.map +1 -1
  88. package/dist/core/codex-fast-mode.js +31 -13
  89. package/dist/core/codex-fast-mode.js.map +1 -1
  90. package/dist/core/extensions/context-types.d.ts +35 -0
  91. package/dist/core/extensions/context-types.d.ts.map +1 -1
  92. package/dist/core/extensions/context-types.js.map +1 -1
  93. package/dist/core/extensions/index.d.ts +1 -1
  94. package/dist/core/extensions/index.d.ts.map +1 -1
  95. package/dist/core/extensions/index.js.map +1 -1
  96. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  97. package/dist/core/extensions/loader-virtual-modules.js +6 -1
  98. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  99. package/dist/core/model-runtime.d.ts +2 -0
  100. package/dist/core/model-runtime.d.ts.map +1 -1
  101. package/dist/core/model-runtime.js +4 -0
  102. package/dist/core/model-runtime.js.map +1 -1
  103. package/dist/core/runtime-credentials.d.ts +1 -0
  104. package/dist/core/runtime-credentials.d.ts.map +1 -1
  105. package/dist/core/runtime-credentials.js +8 -0
  106. package/dist/core/runtime-credentials.js.map +1 -1
  107. package/dist/core/sdk.d.ts.map +1 -1
  108. package/dist/core/sdk.js +5 -5
  109. package/dist/core/sdk.js.map +1 -1
  110. package/dist/core/session-manager-storage.d.ts +2 -0
  111. package/dist/core/session-manager-storage.d.ts.map +1 -1
  112. package/dist/core/session-manager-storage.js +4 -2
  113. package/dist/core/session-manager-storage.js.map +1 -1
  114. package/dist/core/slash-commands.js +1 -1
  115. package/dist/core/slash-commands.js.map +1 -1
  116. package/dist/core/workflow-stage-admission.d.ts +6 -1
  117. package/dist/core/workflow-stage-admission.d.ts.map +1 -1
  118. package/dist/core/workflow-stage-admission.js +8 -9
  119. package/dist/core/workflow-stage-admission.js.map +1 -1
  120. package/dist/index.d.ts +0 -1
  121. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  122. package/dist/modes/interactive/components/footer.js +1 -1
  123. package/dist/modes/interactive/components/footer.js.map +1 -1
  124. package/dist/modes/interactive/interactive-autocomplete.js +1 -1
  125. package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  126. package/dist/modes/interactive/interactive-startup.js +1 -1
  127. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  128. package/dist/modes/interactive-engine/isolated-runtime.d.ts +4 -0
  129. package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
  130. package/dist/modes/interactive-engine/isolated-runtime.js +69 -10
  131. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
  132. package/dist/modes/rpc/rpc-client-api.d.ts +18 -2
  133. package/dist/modes/rpc/rpc-client-api.d.ts.map +1 -1
  134. package/dist/modes/rpc/rpc-client-api.js +33 -5
  135. package/dist/modes/rpc/rpc-client-api.js.map +1 -1
  136. package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
  137. package/dist/modes/rpc/rpc-command-handler.js +8 -4
  138. package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
  139. package/dist/modes/rpc/rpc-types.d.ts +13 -0
  140. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  141. package/dist/modes/rpc/rpc-types.js.map +1 -1
  142. package/docs/intercom.md +15 -6
  143. package/docs/packages.md +2 -2
  144. package/docs/providers.md +8 -3
  145. package/docs/quickstart.md +2 -2
  146. package/docs/rpc.md +21 -4
  147. package/docs/settings.md +6 -4
  148. package/docs/subagents.md +1 -1
  149. package/docs/usage.md +1 -1
  150. package/docs/workflows.md +108 -239
  151. package/npm-shrinkwrap.json +32 -32
  152. package/package.json +9 -13
  153. package/dist/builtin/workflows/ambient.d.ts +0 -61
  154. package/dist/builtin/workflows/builtin/adversarial-verification-prompts.ts +0 -26
  155. package/dist/builtin/workflows/builtin/adversarial-verification-runner.ts +0 -391
  156. package/dist/builtin/workflows/builtin/adversarial-verification.ts +0 -34
  157. package/dist/builtin/workflows/builtin/classify-and-act-prompts.ts +0 -14
  158. package/dist/builtin/workflows/builtin/classify-and-act-runner.ts +0 -108
  159. package/dist/builtin/workflows/builtin/classify-and-act.ts +0 -40
  160. package/dist/builtin/workflows/builtin/fan-out-and-synthesize-prompts.ts +0 -14
  161. package/dist/builtin/workflows/builtin/fan-out-and-synthesize-runner.ts +0 -96
  162. package/dist/builtin/workflows/builtin/fan-out-and-synthesize.ts +0 -37
  163. package/dist/builtin/workflows/builtin/generate-and-filter-prompts.ts +0 -41
  164. package/dist/builtin/workflows/builtin/generate-and-filter-runner.ts +0 -90
  165. package/dist/builtin/workflows/builtin/generate-and-filter.ts +0 -31
  166. package/dist/builtin/workflows/builtin/goal-artifacts.ts +0 -64
  167. package/dist/builtin/workflows/builtin/goal-convergence.ts +0 -87
  168. package/dist/builtin/workflows/builtin/goal-ledger.ts +0 -139
  169. package/dist/builtin/workflows/builtin/goal-models.ts +0 -72
  170. package/dist/builtin/workflows/builtin/goal-orchestrator-prompts.ts +0 -94
  171. package/dist/builtin/workflows/builtin/goal-prompts.ts +0 -217
  172. package/dist/builtin/workflows/builtin/goal-reducer.ts +0 -176
  173. package/dist/builtin/workflows/builtin/goal-reports.ts +0 -76
  174. package/dist/builtin/workflows/builtin/goal-reverify.ts +0 -305
  175. package/dist/builtin/workflows/builtin/goal-review.ts +0 -139
  176. package/dist/builtin/workflows/builtin/goal-runner.ts +0 -504
  177. package/dist/builtin/workflows/builtin/goal-schemas.ts +0 -89
  178. package/dist/builtin/workflows/builtin/goal-types.ts +0 -164
  179. package/dist/builtin/workflows/builtin/goal.ts +0 -78
  180. package/dist/builtin/workflows/builtin/index.ts +0 -16
  181. package/dist/builtin/workflows/builtin/loop-until-done-prompts.ts +0 -87
  182. package/dist/builtin/workflows/builtin/loop-until-done-runner.ts +0 -282
  183. package/dist/builtin/workflows/builtin/loop-until-done.ts +0 -51
  184. package/dist/builtin/workflows/builtin/open-claude-design-live-protocol.ts +0 -305
  185. package/dist/builtin/workflows/builtin/open-claude-design-phases.ts +0 -337
  186. package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +0 -347
  187. package/dist/builtin/workflows/builtin/open-claude-design-setup.ts +0 -313
  188. package/dist/builtin/workflows/builtin/open-claude-design-utils.ts +0 -311
  189. package/dist/builtin/workflows/builtin/open-claude-design.ts +0 -57
  190. package/dist/builtin/workflows/builtin/pattern-artifact-root.ts +0 -28
  191. package/dist/builtin/workflows/builtin/progress-scoring.ts +0 -230
  192. package/dist/builtin/workflows/builtin/ralph-core.ts +0 -449
  193. package/dist/builtin/workflows/builtin/ralph-forked-prompts.ts +0 -100
  194. package/dist/builtin/workflows/builtin/ralph-models.ts +0 -183
  195. package/dist/builtin/workflows/builtin/ralph-review-gate.ts +0 -103
  196. package/dist/builtin/workflows/builtin/ralph-reviewer-prompt.ts +0 -104
  197. package/dist/builtin/workflows/builtin/ralph-runner.ts +0 -459
  198. package/dist/builtin/workflows/builtin/ralph.ts +0 -82
  199. package/dist/builtin/workflows/builtin/review-convergence.ts +0 -229
  200. package/dist/builtin/workflows/builtin/selection-math.ts +0 -156
  201. package/dist/builtin/workflows/builtin/steering-context.ts +0 -51
  202. package/dist/builtin/workflows/builtin/tournament-prompts.ts +0 -70
  203. package/dist/builtin/workflows/builtin/tournament-runner.ts +0 -400
  204. package/dist/builtin/workflows/builtin/tournament.ts +0 -73
  205. package/dist/builtin/workflows/builtin/verification-criteria.ts +0 -330
  206. package/dist/builtin/workflows/builtin/verification-prompts.ts +0 -206
  207. package/dist/builtin/workflows/builtin/verification-usage.ts +0 -44
@@ -1,391 +0,0 @@
1
- import { readFile, writeFile } from "node:fs/promises";
2
- import { join } from "node:path";
3
- import { Type } from "typebox";
4
- import type { WorkflowRunContext, WorkflowSerializableValue, WorkflowTaskResult } from "../src/shared/types.js";
5
- import {
6
- renderConsolidatorPrompt,
7
- renderRepairPrompt,
8
- renderWorkerPrompt,
9
- } from "./adversarial-verification-prompts.js";
10
- import {
11
- build_scoring_prompt,
12
- scoring_prompt_reads,
13
- warm_first_fan_out,
14
- type ScoringCandidate,
15
- type SharedHead,
16
- } from "./verification-prompts.js";
17
- import { stableArtifactRoot } from "./pattern-artifact-root.js";
18
- import { fold_usage } from "./verification-usage.js";
19
- import {
20
- decide_verification,
21
- normalize_criteria,
22
- parse_rubric,
23
- VERIFICATION_SCALE,
24
- type Criterion,
25
- type Criteria,
26
- type CriterionScore,
27
- type VerificationDecision,
28
- } from "./verification-criteria.js";
29
-
30
- export const DEFAULT_CRITERIA = {
31
- task_fit: "The candidate satisfies the literal task.",
32
- evidence: "Important claims cite observable evidence, and file findings cite file:line where applicable.",
33
- completeness: "Relevant validation is executed and reported with commands run and observed output, and no blocking correctness, safety, or completeness gap remains.",
34
- };
35
-
36
- // V2 deliberately requires every fanned-out cell to return a schema-valid score
37
- // after its bounded re-ask wave. A missing score is loudly Indeterminate rather
38
- // than silently narrowing the mean, and quorum is not caller-configurable.
39
- const QUORUM_FRACTION = 1;
40
-
41
- const criterionScoreSchema = Type.Object({
42
- criterion_id: Type.String(),
43
- score: VERIFICATION_SCALE.schema,
44
- evidence: Type.Array(Type.String()),
45
- findings: Type.Array(Type.Object({
46
- finding: Type.String(),
47
- severity: Type.Union([Type.Literal("veto"), Type.Literal("blocking"), Type.Literal("note")]),
48
- }, { additionalProperties: false })),
49
- }, { additionalProperties: false });
50
- const consolidatorSchema = Type.Object({
51
- repair_guidance: Type.String(),
52
- remaining_work: Type.Array(Type.String()),
53
- }, { additionalProperties: false });
54
-
55
- type CriterionScoreReport = {
56
- readonly criterion_id: string;
57
- readonly score: number;
58
- readonly evidence: readonly string[];
59
- readonly findings: readonly {
60
- readonly finding: string;
61
- readonly severity: "veto" | "blocking" | "note";
62
- }[];
63
- };
64
- type ConsolidatedReport = {
65
- readonly repair_guidance: string;
66
- readonly remaining_work: readonly string[];
67
- };
68
- type Inputs = {
69
- readonly task: string;
70
- readonly verifier_count: number;
71
- readonly max_repairs: number;
72
- readonly criteria?: string | Record<string, string>;
73
- readonly accept_mean?: number;
74
- readonly reask_limit?: number;
75
- };
76
- export type AdversarialVerificationResult = {
77
- readonly approved: boolean;
78
- readonly mean_score: number;
79
- readonly score_table_path: string;
80
- readonly repairs_completed: number;
81
- readonly candidate_path: string;
82
- readonly review_report_path: string;
83
- readonly remaining_work: string[];
84
- };
85
-
86
- type VerificationCell = {
87
- readonly criterion: Criterion;
88
- readonly verifierIndex: number;
89
- readonly name: string;
90
- readonly artifactPath: string;
91
- };
92
- type ValidResult = {
93
- readonly cell: VerificationCell;
94
- readonly report: CriterionScoreReport;
95
- readonly artifactPath: string;
96
- };
97
- type InvalidArtifact = {
98
- readonly invalid: true;
99
- readonly stage: string;
100
- };
101
-
102
- function isRecord(value: WorkflowSerializableValue): value is Record<string, WorkflowSerializableValue> {
103
- return typeof value === "object" && value !== null && !Array.isArray(value);
104
- }
105
-
106
- function hasOnlyKeys(value: Record<string, WorkflowSerializableValue>, keys: readonly string[]): boolean {
107
- const actual = Object.keys(value);
108
- return actual.length === keys.length && keys.every((key) => key in value);
109
- }
110
-
111
- function isStringArray(value: WorkflowSerializableValue | undefined): value is string[] {
112
- return Array.isArray(value) && value.every((entry) => typeof entry === "string");
113
- }
114
-
115
- function isStringRecord(value: WorkflowSerializableValue): value is Record<string, string> {
116
- return isRecord(value) && Object.values(value).every((entry) => typeof entry === "string");
117
- }
118
-
119
- function isCriterionFinding(value: WorkflowSerializableValue): boolean {
120
- return isRecord(value)
121
- && hasOnlyKeys(value, ["finding", "severity"])
122
- && typeof value.finding === "string"
123
- && (value.severity === "veto" || value.severity === "blocking" || value.severity === "note");
124
- }
125
-
126
- function isCriterionScore(value: WorkflowSerializableValue | undefined, criterionId: string): value is CriterionScoreReport {
127
- return value !== undefined
128
- && isRecord(value)
129
- && hasOnlyKeys(value, ["criterion_id", "score", "evidence", "findings"])
130
- && value.criterion_id === criterionId
131
- && typeof value.score === "number"
132
- && Number.isInteger(value.score)
133
- && value.score >= VERIFICATION_SCALE.min
134
- && value.score <= VERIFICATION_SCALE.max
135
- && isStringArray(value.evidence)
136
- && Array.isArray(value.findings)
137
- && value.findings.every(isCriterionFinding);
138
- }
139
-
140
- function isConsolidatedReport(value: WorkflowSerializableValue | undefined): value is ConsolidatedReport {
141
- return value !== undefined
142
- && isRecord(value)
143
- && hasOnlyKeys(value, ["repair_guidance", "remaining_work"])
144
- && typeof value.repair_guidance === "string"
145
- && isStringArray(value.remaining_work);
146
- }
147
-
148
- function structured<T extends WorkflowSerializableValue>(
149
- value: WorkflowSerializableValue | undefined,
150
- guard: (candidate: WorkflowSerializableValue | undefined) => candidate is T,
151
- ): T | undefined {
152
- return guard(value) ? value : undefined;
153
- }
154
-
155
- function resolveCriteria(value: WorkflowSerializableValue | undefined): Criteria {
156
- if (value === undefined) {
157
- return { groundTruthNote: "", criteria: normalize_criteria(DEFAULT_CRITERIA) };
158
- }
159
- if (typeof value === "string") return parse_rubric(value);
160
- if (isStringRecord(value)) return { groundTruthNote: "", criteria: normalize_criteria(value) };
161
- throw new TypeError("criteria must be a criteria.md string or a record of criterion descriptions");
162
- }
163
-
164
- function renderCriteriaMarkdown(criteria: Criteria): string {
165
- const lines = ["# Verification criteria"];
166
- if (criteria.groundTruthNote.length > 0) lines.push("## Ground Truth Note", criteria.groundTruthNote);
167
- lines.push("## Criteria");
168
- for (const item of criteria.criteria) {
169
- lines.push(`### ${item.name} {#${item.id}}`, item.description);
170
- }
171
- return `${lines.join("\n\n")}\n`;
172
- }
173
-
174
- function meanScore(scores: readonly CriterionScoreReport[]): number {
175
- if (scores.length === 0) return 0;
176
- return scores.reduce((total, score) => total + score.score, 0) / scores.length;
177
- }
178
-
179
- function toCriterionScore(report: CriterionScoreReport): CriterionScore {
180
- return {
181
- criterionId: report.criterion_id,
182
- score: report.score,
183
- evidence: report.evidence,
184
- findings: report.findings,
185
- };
186
- }
187
-
188
- function findingText(decision: Extract<VerificationDecision, { kind: "repair" }>): string[] {
189
- return decision.findings.map((finding) => finding.finding);
190
- }
191
-
192
- function quorumEvidence(missing: number, invalidCount: number, expectedCount: number, reaskLimit: number): string {
193
- return `Quorum failure: ${missing} of ${expectedCount} criterion scores remain missing after ${reaskLimit} re-ask wave(s); ${invalidCount} report attempts were invalid or missing.`;
194
- }
195
-
196
- function stageName(cell: VerificationCell, reaskWave: number): string {
197
- return reaskWave === 0 ? cell.name : `${cell.name}-reask-${reaskWave}`;
198
- }
199
-
200
- function verifierOutputFormat(criterionId: string): string {
201
- return `Call structured_output with criterion_id (set to ${criterionId}), score (1–20), evidence (string array), and findings containing finding and severity (veto, blocking, or note).`;
202
- }
203
-
204
- function scoreStep(
205
- cell: VerificationCell,
206
- reaskWave: number,
207
- head: SharedHead,
208
- criteriaPath: string,
209
- ) {
210
- const promptHead: SharedHead = {
211
- ...head,
212
- outputFormat: verifierOutputFormat(cell.criterion.id),
213
- };
214
- return {
215
- name: stageName(cell, reaskWave),
216
- prompt: build_scoring_prompt(promptHead, cell.criterion),
217
- context: "fresh" as const,
218
- reads: [criteriaPath, ...scoring_prompt_reads(promptHead)],
219
- schema: criterionScoreSchema,
220
- };
221
- }
222
-
223
- async function writeInvalid(path: string, stage: string): Promise<void> {
224
- const marker: InvalidArtifact = { invalid: true, stage };
225
- await writeFile(path, `${JSON.stringify(marker, null, 2)}\n`);
226
- }
227
-
228
- export async function runAdversarialVerification(ctx: WorkflowRunContext<Inputs>): Promise<AdversarialVerificationResult> {
229
- const root = await stableArtifactRoot(ctx, "adversarial-verification");
230
- const criteriaPath = join(root, "criteria.md");
231
- const candidatePath = join(root, "candidate.md");
232
- const resolvedCriteria = resolveCriteria(ctx.inputs.criteria);
233
- await writeFile(criteriaPath, renderCriteriaMarkdown(resolvedCriteria));
234
- await ctx.task("worker", { prompt: renderWorkerPrompt(ctx.inputs.task), context: "fresh", output: candidatePath, outputMode: "file-only" });
235
-
236
- const verifierCount = ctx.inputs.verifier_count ?? 3;
237
- const maxRepairs = ctx.inputs.max_repairs ?? 2;
238
- const acceptMean = ctx.inputs.accept_mean ?? 14;
239
- const reaskLimit = Math.max(0, Math.floor(ctx.inputs.reask_limit ?? 1));
240
- const expectedCount = resolvedCriteria.criteria.length * verifierCount;
241
- let repairsCompleted = 0;
242
- let consecutiveIndeterminate = 0;
243
- let finalDecision: VerificationDecision;
244
- let finalMean = 0;
245
- let scoreTablePath: string;
246
- let reviewReportPath: string;
247
- let remainingWork: string[] = [];
248
-
249
- for (let round = 0; ; round += 1) {
250
- const candidateBody = await readFile(candidatePath, "utf8");
251
- const scoringHead: SharedHead = {
252
- task: ctx.inputs.task,
253
- groundTruthNote: resolvedCriteria.groundTruthNote,
254
- candidates: [{ path: candidatePath, body: candidateBody } satisfies ScoringCandidate],
255
- scaleAnchors: VERIFICATION_SCALE.anchors,
256
- };
257
- const cells: VerificationCell[] = [];
258
- for (const criterion of resolvedCriteria.criteria) {
259
- for (let index = 0; index < verifierCount; index += 1) {
260
- const name = `verifier-${round}-${criterion.id}-${index + 1}`;
261
- cells.push({
262
- criterion,
263
- verifierIndex: index + 1,
264
- name,
265
- artifactPath: join(root, `verification-${round}-${criterion.id}-${index + 1}.json`),
266
- });
267
- }
268
- }
269
-
270
- const runWave = async (
271
- pending: readonly VerificationCell[],
272
- reaskWave: number,
273
- ): Promise<{ readonly valid: readonly ValidResult[]; readonly invalid: readonly VerificationCell[]; readonly results: readonly WorkflowTaskResult[] }> => {
274
- if (pending.length === 0) return { valid: [], invalid: [], results: [] };
275
- const reports = await warm_first_fan_out(
276
- ctx,
277
- pending.map((cell) => scoreStep(cell, reaskWave, scoringHead, criteriaPath)),
278
- () => scoringHead,
279
- { concurrency: Math.min(pending.length, 4), failFast: false },
280
- );
281
- const byName = new Map<string, (typeof reports)[number]>();
282
- for (const report of reports) {
283
- const name = report.name ?? report.stageName;
284
- if (name !== undefined) byName.set(name, report);
285
- }
286
- const valid: ValidResult[] = [];
287
- const invalid: VerificationCell[] = [];
288
- for (const cell of pending) {
289
- const report = byName.get(stageName(cell, reaskWave));
290
- const artifactPath = reaskWave === 0
291
- ? cell.artifactPath
292
- : cell.artifactPath.replace(/\.json$/, `-reask-${reaskWave}.json`);
293
- if (isCriterionScore(report?.structured, cell.criterion.id)) {
294
- await writeFile(artifactPath, `${JSON.stringify(report.structured, null, 2)}\n`);
295
- valid.push({ cell, report: report.structured, artifactPath });
296
- } else {
297
- await writeInvalid(artifactPath, stageName(cell, reaskWave));
298
- invalid.push(cell);
299
- }
300
- }
301
- return { valid, invalid, results: reports };
302
- };
303
-
304
- const roundResults: WorkflowTaskResult[] = [];
305
- let pending = [...cells];
306
- const validResults: ValidResult[] = [];
307
- let invalidCount = 0;
308
- for (let reaskWave = 0; reaskWave <= reaskLimit; reaskWave += 1) {
309
- const wave = await runWave(pending, reaskWave);
310
- roundResults.push(...wave.results);
311
- validResults.push(...wave.valid);
312
- invalidCount += wave.invalid.length;
313
- pending = [...wave.invalid];
314
- if (pending.length === 0) break;
315
- }
316
-
317
- const validReportsByCell = new Map(validResults.map((item) => [item.cell.name, item.report]));
318
- const scoreReports = cells.flatMap((cell) => {
319
- const report = validReportsByCell.get(cell.name);
320
- return report === undefined ? [] : [report];
321
- });
322
- const scores = scoreReports.map(toCriterionScore);
323
- const roundResult = { scores, invalidCount, expectedCount };
324
- const decision = decide_verification(roundResult, { acceptMean, quorumFraction: QUORUM_FRACTION });
325
- finalDecision = decision;
326
- finalMean = meanScore(scoreReports);
327
- scoreTablePath = join(root, `verification-summary-${round}.json`);
328
- reviewReportPath = join(root, `review-${round}.json`);
329
- const summary = {
330
- scores: scoreReports,
331
- mean: finalMean,
332
- invalidCount,
333
- decision,
334
- usage: fold_usage(roundResults),
335
- };
336
-
337
- if (decision.kind === "accept") {
338
- remainingWork = [];
339
- await writeFile(scoreTablePath, `${JSON.stringify(summary, null, 2)}\n`);
340
- await writeFile(reviewReportPath, `${JSON.stringify({ decision, remaining_work: [] }, null, 2)}\n`);
341
- break;
342
- }
343
-
344
- if (decision.kind === "indeterminate") {
345
- consecutiveIndeterminate += 1;
346
- remainingWork = [quorumEvidence(decision.missing, invalidCount, expectedCount, reaskLimit)];
347
- await writeFile(scoreTablePath, `${JSON.stringify(summary, null, 2)}\n`);
348
- await writeFile(reviewReportPath, `${JSON.stringify({ decision, evidence: remainingWork, remaining_work: remainingWork }, null, 2)}\n`);
349
- if (consecutiveIndeterminate >= 2) break;
350
- continue;
351
- }
352
-
353
- consecutiveIndeterminate = 0;
354
- const confirmedFindings = findingText(decision);
355
- const scorePaths = validResults.map((item) => item.artifactPath);
356
- const consolidated = await ctx.task(`consolidate-findings-${round}`, {
357
- prompt: renderConsolidatorPrompt(ctx.inputs.task, candidatePath, scorePaths, repairsCompleted, maxRepairs),
358
- context: "fresh",
359
- reads: [candidatePath, criteriaPath, ...scorePaths],
360
- schema: consolidatorSchema,
361
- });
362
- const fallbackRemaining = confirmedFindings.length > 0
363
- ? confirmedFindings
364
- : [`Mean score ${decision.mean} is below the acceptance threshold ${acceptMean}.`];
365
- const consolidatedReport: ConsolidatedReport = structured(consolidated.structured, isConsolidatedReport)
366
- ?? { repair_guidance: "Confirmed verifier findings require repair.", remaining_work: fallbackRemaining };
367
- remainingWork = fallbackRemaining;
368
- await writeFile(scoreTablePath, `${JSON.stringify(summary, null, 2)}\n`);
369
- await writeFile(reviewReportPath, `${JSON.stringify({ ...consolidatedReport, remaining_work: remainingWork }, null, 2)}\n`);
370
-
371
- if (repairsCompleted >= maxRepairs) break;
372
- repairsCompleted += 1;
373
- await ctx.task(`repair-${repairsCompleted}`, {
374
- prompt: renderRepairPrompt(ctx.inputs.task, candidatePath, reviewReportPath),
375
- context: "fresh",
376
- reads: [candidatePath, reviewReportPath],
377
- output: candidatePath,
378
- outputMode: "file-only",
379
- });
380
- }
381
-
382
- return {
383
- approved: finalDecision.kind === "accept",
384
- mean_score: finalMean,
385
- score_table_path: scoreTablePath,
386
- repairs_completed: repairsCompleted,
387
- candidate_path: candidatePath,
388
- review_report_path: reviewReportPath,
389
- remaining_work: finalDecision.kind === "accept" ? [] : remainingWork,
390
- };
391
- }
@@ -1,34 +0,0 @@
1
- import { Type } from "typebox";
2
- import { workflow } from "../src/authoring/workflow.js";
3
- import { withSteeringPropagationContext } from "./steering-context.js";
4
- import { DEFAULT_CRITERIA, runAdversarialVerification } from "./adversarial-verification-runner.js";
5
-
6
- export default workflow({
7
- name: "adversarial-verification",
8
- description: "Produce a candidate, score independent per-criterion verifier reports, and apply a deterministic mean-and-veto gate with bounded repairs.",
9
- // The 15-minute default, stated rather than inherited: this is a per-workflow
10
- // product decision, so a future change to the global default must not silently
11
- // re-cadence a long autonomous run.
12
- heartbeatIntervalMinutes: 15,
13
- inputs: {
14
- task: Type.String({ description: "Task whose candidate result must be independently verified." }),
15
- verifier_count: Type.Integer({ minimum: 1, maximum: 5, default: 3, description: "Number of independent verifiers for each criterion per round." }),
16
- max_repairs: Type.Integer({ minimum: 0, maximum: 5, default: 2, description: "Maximum candidate repair rounds before rejection." }),
17
- criteria: Type.Union([
18
- Type.String(),
19
- Type.Record(Type.String(), Type.String()),
20
- ], { default: DEFAULT_CRITERIA, description: "Criteria record of name-to-description entries, or criteria.md markdown." }),
21
- accept_mean: Type.Number({ default: 14, description: "Mean score required for acceptance on the 1–20 verification scale." }),
22
- reask_limit: Type.Integer({ minimum: 0, default: 1, description: "Maximum bounded re-ask waves for invalid criterion reports." }),
23
- },
24
- outputs: {
25
- approved: Type.Boolean({ description: "Whether the deterministic mean-and-veto gate accepted the candidate." }),
26
- mean_score: Type.Number({ description: "Mean score of the final round's schema-valid criterion reports." }),
27
- score_table_path: Type.String({ description: "Path to the final round per-criterion score summary." }),
28
- repairs_completed: Type.Integer({ description: "Number of repair rounds performed." }),
29
- candidate_path: Type.String({ description: "Path to the final candidate artifact." }),
30
- review_report_path: Type.String({ description: "Path to the final consolidated findings or quorum report." }),
31
- remaining_work: Type.Array(Type.String(), { description: "Unresolved findings or quorum evidence when not approved." }),
32
- },
33
- run: async (ctx) => await runAdversarialVerification(withSteeringPropagationContext(ctx)),
34
- });
@@ -1,14 +0,0 @@
1
- const GROUNDED_REPORTING = "Before reporting progress, audit each claim against a tool result from this session. Report only work you can point to evidence for; say so explicitly when something is unverified.";
2
- const READABLE_REPORT = "Lead with the outcome. Keep facts, decisions, caveats, and next steps; drop background and repetition. Use complete, readable sentences rather than compressed fragments.";
3
-
4
- export function classifierPrompt(prompt: string, categories: readonly string[]): string {
5
- return `<categories>\n${categories.map((category) => `- ${category}`).join("\n")}\n</categories>\n\n<role>\nYou route a task to exactly one declared action category.\n</role>\n\n<success_criteria>\nThe selected category is copied verbatim and supported by the task's concrete wording.\n</success_criteria>\n\n<decision_rules>\nChoose exactly one listed category. Use low confidence when the task is ambiguous or spans categories. Stop after making that single classification.\n</decision_rules>\n\n<output_format>\nReturn only the structured result requested by the schema: category, confidence, and a concise evidence-based rationale in complete sentences.\n</output_format>\n\n<objective>\nClassify this task: ${prompt}\n</objective>`;
6
- }
7
-
8
- export function actionPrompt(input: {
9
- readonly prompt: string;
10
- readonly category: string;
11
- readonly classificationPath: string;
12
- }): string {
13
- return `<evidence>\nRead the classification artifact at ${input.classificationPath}. Use only relevant evidence available to this stage; do not assume access to classifier conversation context.\n</evidence>\n\n<role>\nYou are the isolated action agent for category "${input.category}".\n</role>\n\n<success_criteria>\nComplete the requested action for this category, distinguish verified facts from assumptions, and report concrete evidence, validation, and remaining risks.\n</success_criteria>\n\n<stop_rules>\nStop when the category-specific action is complete or a remaining blocker is stated with its missing evidence.\n</stop_rules>\n\n<output_format>\nMarkdown with Outcome, Evidence, Validation, and Remaining risks headings. ${READABLE_REPORT}\n${GROUNDED_REPORTING}\n</output_format>\n\n<objective>\n${input.prompt}\n</objective>`;
14
- }
@@ -1,108 +0,0 @@
1
- import { writeFile } from "node:fs/promises";
2
- import { join } from "node:path";
3
- import { Type } from "typebox";
4
- import type { WorkflowRunContext, WorkflowSerializableValue } from "../src/shared/types.js";
5
- import { actionPrompt, classifierPrompt } from "./classify-and-act-prompts.js";
6
- import { stableArtifactRoot } from "./pattern-artifact-root.js";
7
-
8
- export const classificationSchema = Type.Object({
9
- category: Type.String({ description: "One category copied verbatim from the supplied list." }),
10
- confidence: Type.Number({ minimum: 0, maximum: 1 }),
11
- rationale: Type.String(),
12
- }, { additionalProperties: false });
13
-
14
- type Inputs = {
15
- readonly prompt: string;
16
- readonly categories: readonly string[];
17
- readonly confidence_threshold: number;
18
- } & Record<string, WorkflowSerializableValue>;
19
-
20
- export type ClassifyAndActResult = {
21
- readonly result: string;
22
- readonly category: string;
23
- readonly confidence: number;
24
- readonly action: string;
25
- readonly classification_path: string;
26
- readonly action_path: string;
27
- readonly artifact_dir: string;
28
- };
29
-
30
- function safeName(value: string): string {
31
- const normalized = value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
32
- return normalized || "fallback";
33
- }
34
- function actionTools(category: string): readonly string[] {
35
- const normalized = category.toLowerCase();
36
- if (normalized.includes("implement") || normalized.includes("fix") || normalized.includes("code")) {
37
- return ["read", "edit", "write", "bash"];
38
- }
39
- if (normalized.includes("research")) return ["read", "web_search", "fetch_content"];
40
- return ["read"];
41
- }
42
-
43
- /**
44
- * Resolve a low-confidence or unlisted classification. Interactive runs ask the
45
- * user; headless/non-interactive runs (where ctx.ui rejects) deterministically
46
- * fall back to the exact proposed category when it is listed, else the first
47
- * configured category, so the workflow still produces its declared outputs.
48
- */
49
- async function resolveFallbackCategory(
50
- ctx: WorkflowRunContext<Inputs>,
51
- exactCategory: string | undefined,
52
- ): Promise<{ category: string; fallbackMode: "interactive_select" | "deterministic" }> {
53
- try {
54
- const category = await ctx.ui.select("Classification is uncertain. Choose the action category.", ctx.inputs.categories);
55
- return { category, fallbackMode: "interactive_select" };
56
- } catch {
57
- return { category: exactCategory ?? ctx.inputs.categories[0]!, fallbackMode: "deterministic" };
58
- }
59
- }
60
-
61
- export async function runClassifyAndAct(ctx: WorkflowRunContext<Inputs>): Promise<ClassifyAndActResult> {
62
- const artifactDir = await stableArtifactRoot(ctx, "classify-and-act");
63
- const classified = await ctx.task("classifier", {
64
- prompt: classifierPrompt(ctx.inputs.prompt, ctx.inputs.categories),
65
- schema: classificationSchema,
66
- context: "fresh",
67
- tools: [],
68
- });
69
- const value = classified.structured;
70
- const proposedCategory = typeof value === "object" && value !== null && "category" in value
71
- ? String(value.category) : "";
72
- const confidenceValue = typeof value === "object" && value !== null && "confidence" in value
73
- ? value.confidence : 0;
74
- const confidence = typeof confidenceValue === "number" && Number.isFinite(confidenceValue)
75
- ? Math.max(0, Math.min(1, confidenceValue)) : 0;
76
- const rationale = typeof value === "object" && value !== null && "rationale" in value
77
- ? String(value.rationale) : "Classifier did not provide a usable structured rationale.";
78
- const exactCategory = ctx.inputs.categories.find((category) => category === proposedCategory);
79
- const needsFallback = exactCategory === undefined || confidence < ctx.inputs.confidence_threshold;
80
- const fallback = needsFallback ? await resolveFallbackCategory(ctx, exactCategory) : undefined;
81
- const category = fallback?.category ?? exactCategory!;
82
-
83
- const classificationPath = join(artifactDir, "classification.json");
84
- await writeFile(classificationPath, JSON.stringify({
85
- proposed_category: proposedCategory,
86
- selected_category: category,
87
- confidence,
88
- threshold: ctx.inputs.confidence_threshold,
89
- rationale,
90
- fallback_used: needsFallback,
91
- fallback_mode: fallback?.fallbackMode ?? "none",
92
- }, null, 2));
93
-
94
- const actionPath = join(artifactDir, `action-${safeName(category)}.md`);
95
- const action = await ctx.task(`action-${safeName(category)}`, {
96
- tools: actionTools(category),
97
- prompt: actionPrompt({ prompt: ctx.inputs.prompt, category, classificationPath }),
98
- context: "fresh",
99
- reads: [classificationPath],
100
- output: actionPath,
101
- outputMode: "file-only",
102
- });
103
- // `file-only` already returns a compact artifact reference. Reading the file
104
- // back here would defeat that and push the whole report into the caller's
105
- // context; `action_path` is returned for callers that want the contents.
106
- const result = action.text;
107
- return { result, category, confidence, action: action.stageName, classification_path: classificationPath, action_path: actionPath, artifact_dir: artifactDir };
108
- }
@@ -1,40 +0,0 @@
1
- import { Type } from "typebox";
2
- import { workflow } from "../src/authoring/workflow.js";
3
- import { withSteeringPropagationContext } from "./steering-context.js";
4
- import { runClassifyAndAct } from "./classify-and-act-runner.js";
5
-
6
- export const DEFAULT_ACTION_CATEGORIES = ["analysis", "implementation", "research"] as const;
7
-
8
- export default workflow({
9
- name: "classify-and-act",
10
- description: "Classify a task with structured confidence, route deterministically to an isolated category action, and ask for human selection when confidence is low.",
11
- // The 15-minute default, stated rather than inherited: this is a per-workflow
12
- // product decision, so a future change to the global default must not silently
13
- // re-cadence a long autonomous run.
14
- heartbeatIntervalMinutes: 15,
15
- inputs: {
16
- prompt: Type.String({ description: "Task to classify and execute." }),
17
- categories: Type.Array(Type.String({ minLength: 1 }), {
18
- minItems: 1,
19
- maxItems: 8,
20
- default: [...DEFAULT_ACTION_CATEGORIES],
21
- description: "Ordered action categories available to the classifier and fallback chooser.",
22
- }),
23
- confidence_threshold: Type.Number({
24
- minimum: 0.5,
25
- maximum: 0.99,
26
- default: 0.75,
27
- description: "Minimum structured confidence required to route without human selection.",
28
- }),
29
- },
30
- outputs: {
31
- result: Type.String({ description: "Compact reference to the category-specific action report artifact; read `action_path` for the full report." }),
32
- category: Type.String({ description: "Selected category, including any human fallback selection." }),
33
- confidence: Type.Number({ minimum: 0, maximum: 1, description: "Classifier confidence before fallback." }),
34
- action: Type.String({ description: "Executed category-specific action stage name." }),
35
- classification_path: Type.String({ description: "Structured classification artifact path." }),
36
- action_path: Type.String({ description: "Category action report artifact path." }),
37
- artifact_dir: Type.String({ description: "Per-run artifact directory." }),
38
- },
39
- run: async (ctx) => await runClassifyAndAct(withSteeringPropagationContext(ctx)),
40
- });
@@ -1,14 +0,0 @@
1
- const GROUNDED_REPORTING = "Before reporting progress, audit each claim against a tool result from this session. Report only work you can point to evidence for; say so explicitly when something is unverified.";
2
- const READABLE_REPORT = "Lead with the outcome. Keep facts, decisions, caveats, and next steps; drop background and repetition. Use complete, readable sentences rather than compressed fragments.";
3
-
4
- export function partitionPrompt(prompt: string, maxBranches: number): string {
5
- return `<role>\nYou partition work into independent evidence-producing branches.\n</role>\n\n<success_criteria>\nThe plan has between 1 and ${maxBranches} non-overlapping partitions whose labels and objectives are self-contained.\n</success_criteria>\n\n<decision_rules>\nSplit by files, sources, claims, candidates, or work items that can be evaluated independently. Avoid duplicate scope and identify boundaries explicitly. Stop when every required part of the task belongs to one partition.\n</decision_rules>\n\n<output_format>\nReturn only the structured result requested by the schema, with concise labels and self-contained objectives.\n</output_format>\n\n<objective>\nPartition this task: ${prompt}\n</objective>`;
6
- }
7
-
8
- export function branchPrompt(input: { readonly prompt: string; readonly label: string; readonly objective: string }): string {
9
- return `<overall_task>\n${input.prompt}\n</overall_task>\n\n<role>\nYou own one independent branch of a larger task. Your artifact lets a synthesizer audit this branch without its conversation context.\n</role>\n\n<success_criteria>\nCite concrete files, sources, commands, or other observable evidence, distinguish findings from uncertainty, and produce a standalone artifact.\n</success_criteria>\n\n<stop_rules>\nStop when the branch objective is supported or when unresolved uncertainty and the evidence needed to resolve it are explicit.\n</stop_rules>\n\n<output_format>\nMarkdown with Scope, Findings, Evidence, Conflicts or uncertainty, and Recommendations headings. ${READABLE_REPORT}\n${GROUNDED_REPORTING}\n</output_format>\n\n<branch>\nInvestigate only ${input.label}: ${input.objective}\n</branch>`;
10
- }
11
-
12
- export function synthesisPrompt(prompt: string, manifestPath: string): string {
13
- return `<artifact_contract>\nRead ${manifestPath} first, then read every branch artifact listed there. Do not omit a completed branch and do not assume access to branch conversations.\n</artifact_contract>\n\n<role>\nYou synthesize independent branch artifacts at a strict barrier. The final reader needs conclusions traceable to branch evidence rather than majority vote.\n</role>\n\n<success_criteria>\nDeduplicate overlapping findings, explicitly resolve or preserve conflicting claims, retain material uncertainty, and cite branch labels and artifact paths for important conclusions.\n</success_criteria>\n\n<stop_rules>\nStop after every completed branch is accounted for and each material conflict is resolved or preserved as uncertainty.\n</stop_rules>\n\n<output_format>\nMarkdown with Executive synthesis, Consolidated findings, Conflicts and resolutions, Evidence index, and Remaining uncertainty headings. ${READABLE_REPORT}\n${GROUNDED_REPORTING}\n</output_format>\n\n<objective>\nProduce the final answer for: ${prompt}\n</objective>`;
14
- }