@gr8ful/spf 0.1.0

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 (153) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +321 -0
  3. package/assets/defaults/spf.config.yaml +141 -0
  4. package/assets/prompts/builder/system.md +13 -0
  5. package/assets/prompts/builder/user.md +34 -0
  6. package/assets/prompts/documenter/system.md +17 -0
  7. package/assets/prompts/documenter/user.md +48 -0
  8. package/assets/prompts/planner/system.md +21 -0
  9. package/assets/prompts/planner/user.md +45 -0
  10. package/assets/prompts/reviewer/system.md +16 -0
  11. package/assets/prompts/reviewer/user.md +44 -0
  12. package/assets/prompts/scout/system.md +20 -0
  13. package/assets/prompts/scout/user.md +34 -0
  14. package/assets/skill/SKILL.md +80 -0
  15. package/assets/skill/cookbooks/authoring_chains.md +193 -0
  16. package/assets/skill/cookbooks/how_to_prompt_for_the_eng.md +109 -0
  17. package/assets/skill/cookbooks/roster.md +197 -0
  18. package/assets/skill/cookbooks/run_adw.md +92 -0
  19. package/assets/skill/cookbooks/spf_overview.md +111 -0
  20. package/assets/skill/references/config.md +188 -0
  21. package/assets/skill/references/handoff.md +162 -0
  22. package/assets/skill/references/observability.md +184 -0
  23. package/dist/chains/adw_build.d.ts +12 -0
  24. package/dist/chains/adw_build.js +27 -0
  25. package/dist/chains/adw_build_review.d.ts +21 -0
  26. package/dist/chains/adw_build_review.js +55 -0
  27. package/dist/chains/adw_build_test.d.ts +21 -0
  28. package/dist/chains/adw_build_test.js +67 -0
  29. package/dist/chains/adw_document.d.ts +23 -0
  30. package/dist/chains/adw_document.js +59 -0
  31. package/dist/chains/adw_plan.d.ts +12 -0
  32. package/dist/chains/adw_plan.js +27 -0
  33. package/dist/chains/adw_plan_build.d.ts +12 -0
  34. package/dist/chains/adw_plan_build.js +30 -0
  35. package/dist/chains/adw_plan_build_test.d.ts +16 -0
  36. package/dist/chains/adw_plan_build_test.js +65 -0
  37. package/dist/chains/adw_plan_build_test_quality.d.ts +18 -0
  38. package/dist/chains/adw_plan_build_test_quality.js +66 -0
  39. package/dist/chains/adw_prompt.d.ts +12 -0
  40. package/dist/chains/adw_prompt.js +25 -0
  41. package/dist/chains/adw_quality.d.ts +12 -0
  42. package/dist/chains/adw_quality.js +32 -0
  43. package/dist/chains/adw_scout.d.ts +12 -0
  44. package/dist/chains/adw_scout.js +27 -0
  45. package/dist/chains/adw_simple_sdlc.d.ts +43 -0
  46. package/dist/chains/adw_simple_sdlc.js +147 -0
  47. package/dist/chains/context.d.ts +19 -0
  48. package/dist/chains/context.js +1 -0
  49. package/dist/chains/index.d.ts +19 -0
  50. package/dist/chains/index.js +116 -0
  51. package/dist/cli/bin.d.ts +15 -0
  52. package/dist/cli/bin.js +24 -0
  53. package/dist/cli/commands/abort.d.ts +1 -0
  54. package/dist/cli/commands/abort.js +42 -0
  55. package/dist/cli/commands/doctor.d.ts +1 -0
  56. package/dist/cli/commands/doctor.js +165 -0
  57. package/dist/cli/commands/eject.d.ts +1 -0
  58. package/dist/cli/commands/eject.js +55 -0
  59. package/dist/cli/commands/events.d.ts +1 -0
  60. package/dist/cli/commands/events.js +49 -0
  61. package/dist/cli/commands/init.d.ts +1 -0
  62. package/dist/cli/commands/init.js +62 -0
  63. package/dist/cli/commands/install-skill.d.ts +1 -0
  64. package/dist/cli/commands/install-skill.js +122 -0
  65. package/dist/cli/commands/list.d.ts +1 -0
  66. package/dist/cli/commands/list.js +13 -0
  67. package/dist/cli/commands/migrate.d.ts +1 -0
  68. package/dist/cli/commands/migrate.js +167 -0
  69. package/dist/cli/commands/phases.d.ts +1 -0
  70. package/dist/cli/commands/phases.js +25 -0
  71. package/dist/cli/commands/run.d.ts +3 -0
  72. package/dist/cli/commands/run.js +27 -0
  73. package/dist/cli/commands/sessions.d.ts +1 -0
  74. package/dist/cli/commands/sessions.js +20 -0
  75. package/dist/cli/commands/trace.d.ts +8 -0
  76. package/dist/cli/commands/trace.js +10 -0
  77. package/dist/cli/commands/ui.d.ts +1 -0
  78. package/dist/cli/commands/ui.js +35 -0
  79. package/dist/cli/commands/version.d.ts +1 -0
  80. package/dist/cli/commands/version.js +8 -0
  81. package/dist/cli/commands/watch.d.ts +8 -0
  82. package/dist/cli/commands/watch.js +210 -0
  83. package/dist/cli/gitignore.d.ts +1 -0
  84. package/dist/cli/gitignore.js +14 -0
  85. package/dist/cli/index.d.ts +1 -0
  86. package/dist/cli/index.js +156 -0
  87. package/dist/core/agent_cc.d.ts +75 -0
  88. package/dist/core/agent_cc.js +322 -0
  89. package/dist/core/agent_flue.d.ts +66 -0
  90. package/dist/core/agent_flue.js +321 -0
  91. package/dist/core/agents.d.ts +64 -0
  92. package/dist/core/agents.js +456 -0
  93. package/dist/core/changes.d.ts +35 -0
  94. package/dist/core/changes.js +98 -0
  95. package/dist/core/console.d.ts +36 -0
  96. package/dist/core/console.js +156 -0
  97. package/dist/core/data_types.d.ts +562 -0
  98. package/dist/core/data_types.js +382 -0
  99. package/dist/core/gates.d.ts +33 -0
  100. package/dist/core/gates.js +144 -0
  101. package/dist/core/git_helper.d.ts +59 -0
  102. package/dist/core/git_helper.js +115 -0
  103. package/dist/core/issues/github_provider.d.ts +52 -0
  104. package/dist/core/issues/github_provider.js +211 -0
  105. package/dist/core/issues/provider.d.ts +90 -0
  106. package/dist/core/issues/provider.js +14 -0
  107. package/dist/core/paths.d.ts +78 -0
  108. package/dist/core/paths.js +108 -0
  109. package/dist/core/permissions.d.ts +78 -0
  110. package/dist/core/permissions.js +187 -0
  111. package/dist/core/prompts.d.ts +4 -0
  112. package/dist/core/prompts.js +17 -0
  113. package/dist/core/quality.d.ts +65 -0
  114. package/dist/core/quality.js +194 -0
  115. package/dist/core/runner.d.ts +72 -0
  116. package/dist/core/runner.js +168 -0
  117. package/dist/core/session.d.ts +16 -0
  118. package/dist/core/session.js +60 -0
  119. package/dist/core/sqlite.d.ts +55 -0
  120. package/dist/core/sqlite.js +106 -0
  121. package/dist/core/tracer.d.ts +56 -0
  122. package/dist/core/tracer.js +246 -0
  123. package/dist/core/utils.d.ts +40 -0
  124. package/dist/core/utils.js +108 -0
  125. package/dist/core/watch.d.ts +44 -0
  126. package/dist/core/watch.js +194 -0
  127. package/dist/test/agent_cc.test.d.ts +1 -0
  128. package/dist/test/agent_cc.test.js +95 -0
  129. package/dist/test/agent_flue.test.d.ts +1 -0
  130. package/dist/test/agent_flue.test.js +83 -0
  131. package/dist/test/data_types.test.d.ts +10 -0
  132. package/dist/test/data_types.test.js +49 -0
  133. package/dist/test/ui_server.test.d.ts +1 -0
  134. package/dist/test/ui_server.test.js +119 -0
  135. package/dist/test/watch.test.d.ts +1 -0
  136. package/dist/test/watch.test.js +227 -0
  137. package/dist/ui/server/app.d.ts +3 -0
  138. package/dist/ui/server/app.js +98 -0
  139. package/dist/ui/server/db.d.ts +82 -0
  140. package/dist/ui/server/db.js +333 -0
  141. package/dist/ui/server/serve.d.ts +13 -0
  142. package/dist/ui/server/serve.js +80 -0
  143. package/dist/ui/server/static.d.ts +5 -0
  144. package/dist/ui/server/static.js +55 -0
  145. package/dist/ui/shared/types.d.ts +263 -0
  146. package/dist/ui/shared/types.js +8 -0
  147. package/package.json +52 -0
  148. package/web/assets/index-C7nF068F.css +1 -0
  149. package/web/assets/index-mzSArcnQ.js +11 -0
  150. package/web/assets/play-latin-400-normal-GKW-4YV7.woff2 +0 -0
  151. package/web/assets/play-latin-700-normal-DyPlLDbb.woff2 +0 -0
  152. package/web/index.html +14 -0
  153. package/web/logo.svg +6 -0
@@ -0,0 +1,562 @@
1
+ /**
2
+ * Concrete data types for the SPF ADW system.
3
+ *
4
+ * RULE (four-param rule): any function that takes more than 4 parameters takes
5
+ * ONE of these objects instead. AgentCall and PhaseParams are the pattern.
6
+ *
7
+ * Every agent call declares a concrete output type — an envelope built with
8
+ * envelopeType() — that its final JSON response is parsed against. No untyped
9
+ * handoffs. Validation is Valibot's job here (zod's/Python's pydantic
10
+ * equivalent) — chosen because Flue's own structured-output wiring is built
11
+ * on Valibot, so an envelope type doubles as the tool schema handed to it
12
+ * with no second definition.
13
+ */
14
+ import * as v from "valibot";
15
+ export type PhaseKind = "engineer" | "agent" | "code";
16
+ export type PhaseStatus = "queued" | "running" | "success" | "fail";
17
+ /** Everything run.phase() needs. Passed as one object, never loose params. */
18
+ declare const PhaseParamsShape: v.ObjectSchema<{
19
+ readonly name: v.StringSchema<undefined>;
20
+ readonly kind: v.PicklistSchema<["engineer", "agent", "code"], undefined>;
21
+ readonly owner: v.StringSchema<undefined>;
22
+ readonly description: v.StringSchema<undefined>;
23
+ readonly retries: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>]>, 0>;
24
+ }, undefined>;
25
+ /**
26
+ * A phase name identifies; a description explains. Both are required.
27
+ *
28
+ * The description is the only sentence the trace, the console, and the
29
+ * phase block in the UI ever show about intent — everything else is ids,
30
+ * statuses, and timings. `commit_plan: "Commit the plan"` tells a reader
31
+ * nothing they could not already see, so an echo is rejected the same way
32
+ * a blank one is. This is a construction-time error on purpose: it fires
33
+ * before the phase opens, not after a run is already in the trace.
34
+ */
35
+ export declare const PhaseParamsSchema: v.SchemaWithPipe<readonly [v.ObjectSchema<{
36
+ readonly name: v.StringSchema<undefined>;
37
+ readonly kind: v.PicklistSchema<["engineer", "agent", "code"], undefined>;
38
+ readonly owner: v.StringSchema<undefined>;
39
+ readonly description: v.StringSchema<undefined>;
40
+ readonly retries: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>]>, 0>;
41
+ }, undefined>, v.RawTransformAction<{
42
+ name: string;
43
+ kind: "agent" | "code" | "engineer";
44
+ owner: string;
45
+ description: string;
46
+ retries: number;
47
+ }, {
48
+ name: string;
49
+ kind: "agent" | "code" | "engineer";
50
+ owner: string;
51
+ retries: number;
52
+ description: string;
53
+ }>]>;
54
+ export type PhaseParams = v.InferOutput<typeof PhaseParamsSchema>;
55
+ export declare function makePhaseParams(input: v.InferInput<typeof PhaseParamsShape>): PhaseParams;
56
+ /** The persisted phase record — PhaseParams plus lifecycle. */
57
+ export interface Phase {
58
+ phase_id: string;
59
+ adw_id: string;
60
+ seq: number;
61
+ params: PhaseParams;
62
+ status: PhaseStatus;
63
+ attempt: number;
64
+ error?: string | null;
65
+ started_at?: string | null;
66
+ ended_at?: string | null;
67
+ }
68
+ export declare const EnvelopeBaseSchema: v.ObjectSchema<{
69
+ status: v.PicklistSchema<["success", "fail"], undefined>;
70
+ summary: v.OptionalSchema<v.StringSchema<undefined>, "">;
71
+ artifacts: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, () => never[]>;
72
+ notes_for_next_agent: v.OptionalSchema<v.StringSchema<undefined>, "">;
73
+ }, undefined>;
74
+ export type EnvelopeBase = v.InferOutput<typeof EnvelopeBaseSchema>;
75
+ export interface EnvelopeType<T> {
76
+ name: string;
77
+ schema: v.GenericSchema<Record<string, unknown>, T>;
78
+ fields: string[];
79
+ }
80
+ export declare const GenericOutput: EnvelopeType<{
81
+ status: "fail" | "success";
82
+ summary: string;
83
+ artifacts: string[];
84
+ notes_for_next_agent: string;
85
+ }>;
86
+ export type GenericOutputT = v.InferOutput<typeof GenericOutput.schema>;
87
+ export declare const PlanOutput: EnvelopeType<{
88
+ status: "fail" | "success";
89
+ summary: string;
90
+ artifacts: string[];
91
+ notes_for_next_agent: string;
92
+ commit_message: string;
93
+ }>;
94
+ export type PlanOutputT = v.InferOutput<typeof PlanOutput.schema>;
95
+ export declare const BuildOutput: EnvelopeType<{
96
+ status: "fail" | "success";
97
+ summary: string;
98
+ artifacts: string[];
99
+ notes_for_next_agent: string;
100
+ changed_files: string[];
101
+ commit_message: string;
102
+ }>;
103
+ export type BuildOutputT = v.InferOutput<typeof BuildOutput.schema>;
104
+ export declare const ScoutFindingSchema: v.ObjectSchema<{
105
+ readonly file: v.StringSchema<undefined>;
106
+ readonly note: v.OptionalSchema<v.StringSchema<undefined>, "">;
107
+ }, undefined>;
108
+ export type ScoutFinding = v.InferOutput<typeof ScoutFindingSchema>;
109
+ export declare const ScoutOutput: EnvelopeType<{
110
+ status: "fail" | "success";
111
+ summary: string;
112
+ artifacts: string[];
113
+ notes_for_next_agent: string;
114
+ findings: {
115
+ file: string;
116
+ note: string;
117
+ }[];
118
+ }>;
119
+ export type ScoutOutputT = v.InferOutput<typeof ScoutOutput.schema>;
120
+ /** One thing the request (or plan) asked for, and whether it is there. */
121
+ export declare const ReviewFindingSchema: v.ObjectSchema<{
122
+ readonly requirement: v.StringSchema<undefined>;
123
+ readonly met: v.BooleanSchema<undefined>;
124
+ readonly evidence: v.OptionalSchema<v.StringSchema<undefined>, "">;
125
+ }, undefined>;
126
+ export type ReviewFinding = v.InferOutput<typeof ReviewFindingSchema>;
127
+ /** Confirmation that what was built is what was asked for — not a test run. */
128
+ export declare const ReviewOutput: EnvelopeType<{
129
+ status: "fail" | "success";
130
+ summary: string;
131
+ artifacts: string[];
132
+ notes_for_next_agent: string;
133
+ approved: boolean;
134
+ findings: {
135
+ requirement: string;
136
+ met: boolean;
137
+ evidence: string;
138
+ }[];
139
+ blocking: string[];
140
+ }>;
141
+ export type ReviewOutputT = v.InferOutput<typeof ReviewOutput.schema>;
142
+ /** Where the write-up of a completed change landed. */
143
+ export declare const DocumentOutput: EnvelopeType<{
144
+ status: "fail" | "success";
145
+ summary: string;
146
+ artifacts: string[];
147
+ notes_for_next_agent: string;
148
+ document_path: string;
149
+ documented_files: string[];
150
+ commit_message: string;
151
+ }>;
152
+ export type DocumentOutputT = v.InferOutput<typeof DocumentOutput.schema>;
153
+ export declare const QualityAreaSchema: v.PicklistSchema<["frontend", "backend"], undefined>;
154
+ export type QualityArea = v.InferOutput<typeof QualityAreaSchema>;
155
+ export declare const QualityOperationSchema: v.PicklistSchema<["lint", "typecheck", "build"], undefined>;
156
+ export type QualityOperation = v.InferOutput<typeof QualityOperationSchema>;
157
+ /** One deterministic quality command, as configured in spf.config.yaml's `quality.checks`. */
158
+ export declare const QualityCheckSpecSchema: v.ObjectSchema<{
159
+ readonly name: v.StringSchema<undefined>;
160
+ readonly area: v.OptionalSchema<v.PicklistSchema<["frontend", "backend"], undefined>, "backend">;
161
+ readonly operation: v.PicklistSchema<["lint", "typecheck", "build"], undefined>;
162
+ readonly argv: v.SchemaWithPipe<readonly [v.ArraySchema<v.StringSchema<undefined>, undefined>, v.MinLengthAction<string[], 1, "argv must name at least the binary to run">]>;
163
+ readonly timeout_seconds: v.OptionalSchema<v.NumberSchema<undefined>, 120>;
164
+ }, undefined>;
165
+ export type QualityCheckSpec = v.InferOutput<typeof QualityCheckSpecSchema>;
166
+ /**
167
+ * `quality.checks` names the deterministic commands; `quality.suites` groups
168
+ * them into what a chain actually runs (`test`, `all`, ...). An unconfigured
169
+ * suite is a hard error at validate() time — see agents.validate() — not a
170
+ * silent placeholder that reports green. There is deliberately no packaged
171
+ * default suite: "no quality commands configured yet" must fail loudly on
172
+ * the first quality-gated chain, not quietly pass one.
173
+ */
174
+ export declare const QualityConfigSchema: v.ObjectSchema<{
175
+ readonly checks: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
176
+ readonly name: v.StringSchema<undefined>;
177
+ readonly area: v.OptionalSchema<v.PicklistSchema<["frontend", "backend"], undefined>, "backend">;
178
+ readonly operation: v.PicklistSchema<["lint", "typecheck", "build"], undefined>;
179
+ readonly argv: v.SchemaWithPipe<readonly [v.ArraySchema<v.StringSchema<undefined>, undefined>, v.MinLengthAction<string[], 1, "argv must name at least the binary to run">]>;
180
+ readonly timeout_seconds: v.OptionalSchema<v.NumberSchema<undefined>, 120>;
181
+ }, undefined>, undefined>, () => never[]>;
182
+ readonly suites: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>, () => {}>;
183
+ }, undefined>;
184
+ export type QualityConfig = v.InferOutput<typeof QualityConfigSchema>;
185
+ /** Captured evidence from one quality command. */
186
+ export interface QualityCheckResult {
187
+ name: string;
188
+ area: QualityArea;
189
+ operation: QualityOperation;
190
+ command: string;
191
+ returncode: number;
192
+ passed: boolean;
193
+ duration_seconds: number;
194
+ output_artifact: string;
195
+ output_tail: string;
196
+ }
197
+ /** Aggregate result from a quality block: every check it ran, and the verdict. */
198
+ export interface QualityResult {
199
+ passed: boolean;
200
+ checks: QualityCheckResult[];
201
+ failures: string[];
202
+ artifacts: string[];
203
+ }
204
+ /** Everything changes.capture() needs. One object, never loose params. */
205
+ export interface ChangeCapture {
206
+ base: string;
207
+ max_diff_lines: number;
208
+ include_untracked: boolean;
209
+ }
210
+ export declare function makeChangeCapture(input: Partial<ChangeCapture> & {
211
+ base?: string;
212
+ }): ChangeCapture;
213
+ /**
214
+ * The commit a change is measured from, and why that one.
215
+ *
216
+ * `reason` is the line the trace shows. A diff is only as trustworthy as the
217
+ * thing it was taken against, so the ADW records that choice instead of
218
+ * leaving the reader to infer it.
219
+ */
220
+ export declare class BaseRef {
221
+ ref: string;
222
+ commit: string;
223
+ reason: string;
224
+ constructor(ref: string, commit: string, reason?: string);
225
+ /** Display form — a named ref as itself, a pinned raw sha shortened. */
226
+ get label(): string;
227
+ }
228
+ /** What changed since the base commit — pure git facts, no judgement. */
229
+ export declare class ChangeSet {
230
+ base: BaseRef;
231
+ files: string[];
232
+ untracked: string[];
233
+ insertions: number;
234
+ deletions: number;
235
+ stat: string;
236
+ diff_path: string;
237
+ truncated: boolean;
238
+ constructor(base: BaseRef, files?: string[], untracked?: string[], insertions?: number, deletions?: number, stat?: string, diff_path?: string, // the full diff, written into context_handoff/
239
+ truncated?: boolean);
240
+ get empty(): boolean;
241
+ }
242
+ /**
243
+ * A ChangeSet shaped as an envelope so an agent can be handed it directly.
244
+ *
245
+ * Same adapter idea as VerifyOutput: code computes the diff, the documenter
246
+ * consumes it through the one door every agent handoff uses.
247
+ */
248
+ export declare const ChangesOutput: EnvelopeType<{
249
+ status: "fail" | "success";
250
+ summary: string;
251
+ artifacts: string[];
252
+ notes_for_next_agent: string;
253
+ base: string;
254
+ changed_files: string[];
255
+ insertions: number;
256
+ deletions: number;
257
+ stat: string;
258
+ diff_path: string;
259
+ }>;
260
+ export type ChangesOutputT = v.InferOutput<typeof ChangesOutput.schema>;
261
+ /**
262
+ * A deterministic result, shaped as an envelope so an agent can consume it.
263
+ *
264
+ * Agents hand each other typed envelopes; code blocks return QualityResult.
265
+ * This is the adapter, so a failing lint or test run flows back into the
266
+ * builder through exactly the same door a tester agent's report used to —
267
+ * the ADW script is the only thing that knows the difference.
268
+ */
269
+ export declare const VerifyOutput: EnvelopeType<{
270
+ status: "fail" | "success";
271
+ summary: string;
272
+ artifacts: string[];
273
+ notes_for_next_agent: string;
274
+ passed: boolean;
275
+ failures: string[];
276
+ }>;
277
+ export type VerifyOutputT = v.InferOutput<typeof VerifyOutput.schema>;
278
+ /**
279
+ * One thing a gate looked at, and what it found.
280
+ *
281
+ * `note` is the evidence — "exists, 2.1KB", "exit 0", "not in the diff". On a
282
+ * failed check it doubles as the reason, so it is what the agent is told.
283
+ */
284
+ export interface GateCheck {
285
+ item: string;
286
+ ok: boolean;
287
+ note: string;
288
+ }
289
+ /**
290
+ * What every gate returns: the checks it ran. Violations are derived.
291
+ *
292
+ * Authoring stays a one-liner per item — `report.check(...)` appends and
293
+ * returns self, so a gate is a loop and a return.
294
+ */
295
+ export declare class GateReport {
296
+ checks: GateCheck[];
297
+ check(item: string, ok: boolean, note?: string): GateReport;
298
+ get violations(): string[];
299
+ get passed(): boolean;
300
+ }
301
+ /** The minimal shape a gate needs from a run — avoids a circular import with runner.ts. */
302
+ export interface RunContext {
303
+ repo_root: string;
304
+ }
305
+ export type GateFn = (envelope: EnvelopeBase, run: RunContext) => GateReport | string[];
306
+ /** One agent invocation: prompt in, typed envelope out, gates verified. */
307
+ export interface AgentCall<T extends EnvelopeBase = EnvelopeBase> {
308
+ output_type: EnvelopeType<T>;
309
+ prompt: string;
310
+ previous?: EnvelopeBase | null;
311
+ gates?: GateFn[];
312
+ }
313
+ export declare function makeAgentCall<T extends EnvelopeBase>(input: {
314
+ output_type: EnvelopeType<T>;
315
+ prompt: string;
316
+ previous?: EnvelopeBase | null;
317
+ gates?: GateFn[];
318
+ }): AgentCall<T>;
319
+ export declare const PromptEngineeringSchema: v.ObjectSchema<{
320
+ readonly system: v.StringSchema<undefined>;
321
+ readonly user: v.StringSchema<undefined>;
322
+ }, undefined>;
323
+ export type PromptEngineering = v.InferOutput<typeof PromptEngineeringSchema>;
324
+ export declare const ThinkingLevelSchema: v.PicklistSchema<["off", "minimal", "low", "medium", "high", "xhigh", "max"], undefined>;
325
+ export type ThinkingLevel = v.InferOutput<typeof ThinkingLevelSchema>;
326
+ export declare const AgentConfigSchema: v.ObjectSchema<{
327
+ readonly name: v.StringSchema<undefined>;
328
+ readonly coding_agent: v.OptionalSchema<v.PicklistSchema<["flue", "claude_code"], undefined>, "flue">;
329
+ readonly model: v.OptionalSchema<v.StringSchema<undefined>, "google/gemini-3.6-flash">;
330
+ readonly thinking: v.OptionalSchema<v.PicklistSchema<["off", "minimal", "low", "medium", "high", "xhigh", "max"], undefined>, "medium">;
331
+ readonly color: v.OptionalSchema<v.StringSchema<undefined>, "">;
332
+ readonly purpose: v.OptionalSchema<v.StringSchema<undefined>, "">;
333
+ readonly prompt_engineering: v.ObjectSchema<{
334
+ readonly system: v.StringSchema<undefined>;
335
+ readonly user: v.StringSchema<undefined>;
336
+ }, undefined>;
337
+ readonly harness_engineering: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, () => never[]>;
338
+ readonly tools: v.OptionalSchema<v.NullableSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>, undefined>;
339
+ readonly writes: v.OptionalSchema<v.NullableSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>, undefined>;
340
+ }, undefined>;
341
+ export type AgentConfig = v.InferOutput<typeof AgentConfigSchema>;
342
+ export declare const ConfigDefaultsSchema: v.ObjectSchema<{
343
+ readonly coding_agent: v.OptionalSchema<v.PicklistSchema<["flue", "claude_code"], undefined>, "flue">;
344
+ readonly model: v.OptionalSchema<v.StringSchema<undefined>, "google/gemini-3.6-flash">;
345
+ readonly thinking: v.OptionalSchema<v.PicklistSchema<["off", "minimal", "low", "medium", "high", "xhigh", "max"], undefined>, "medium">;
346
+ readonly color: v.OptionalSchema<v.StringSchema<undefined>, "">;
347
+ readonly harness_engineering: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, () => never[]>;
348
+ readonly tools: v.OptionalSchema<v.NullableSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>, undefined>;
349
+ readonly protected_files: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, () => string[]>;
350
+ readonly data_dir: v.OptionalSchema<v.StringSchema<undefined>, ".spf/data">;
351
+ }, undefined>;
352
+ export type ConfigDefaults = v.InferOutput<typeof ConfigDefaultsSchema>;
353
+ export declare const ObservabilityConfigSchema: v.ObjectSchema<{
354
+ readonly db: v.OptionalSchema<v.StringSchema<undefined>, ".spf/data/spf.db">;
355
+ readonly poll_ms: v.OptionalSchema<v.NumberSchema<undefined>, 500>;
356
+ }, undefined>;
357
+ export type ObservabilityConfig = v.InferOutput<typeof ObservabilityConfigSchema>;
358
+ /**
359
+ * `spf watch`'s configuration. `provider` is a small enum today (just
360
+ * `"github"`) by design — adding Jira/Linear later is a new provider
361
+ * module (`core/issues/*_provider.ts`) implementing `IssueProvider` plus
362
+ * one more enum entry here, not a rewrite of the poll loop.
363
+ *
364
+ * `repo` has no sensible default and is validated as required at `spf
365
+ * watch` startup, not here — an empty string parses fine (this schema has
366
+ * no opinion on whether watch is even configured), matching the same
367
+ * "fails loudly before anything spawns, not eagerly at parse time" pattern
368
+ * `quality:` already uses.
369
+ */
370
+ export declare const WatchProviderSchema: v.PicklistSchema<["github"], undefined>;
371
+ export type WatchProvider = v.InferOutput<typeof WatchProviderSchema>;
372
+ export declare const WatchConfigSchema: v.ObjectSchema<{
373
+ readonly provider: v.OptionalSchema<v.PicklistSchema<["github"], undefined>, "github">;
374
+ readonly repo: v.OptionalSchema<v.StringSchema<undefined>, "">;
375
+ readonly label_prefix: v.OptionalSchema<v.StringSchema<undefined>, "spf">;
376
+ readonly chain: v.OptionalSchema<v.StringSchema<undefined>, "plan-build-test">;
377
+ readonly base_branch: v.OptionalSchema<v.StringSchema<undefined>, "main">;
378
+ readonly poll_ms: v.OptionalSchema<v.NumberSchema<undefined>, 60000>;
379
+ readonly concurrency: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, 2>;
380
+ }, undefined>;
381
+ export type WatchConfig = v.InferOutput<typeof WatchConfigSchema>;
382
+ export declare const SFConfigSchema: v.ObjectSchema<{
383
+ readonly defaults: v.OptionalSchema<v.ObjectSchema<{
384
+ readonly coding_agent: v.OptionalSchema<v.PicklistSchema<["flue", "claude_code"], undefined>, "flue">;
385
+ readonly model: v.OptionalSchema<v.StringSchema<undefined>, "google/gemini-3.6-flash">;
386
+ readonly thinking: v.OptionalSchema<v.PicklistSchema<["off", "minimal", "low", "medium", "high", "xhigh", "max"], undefined>, "medium">;
387
+ readonly color: v.OptionalSchema<v.StringSchema<undefined>, "">;
388
+ readonly harness_engineering: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, () => never[]>;
389
+ readonly tools: v.OptionalSchema<v.NullableSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>, undefined>;
390
+ readonly protected_files: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, () => string[]>;
391
+ readonly data_dir: v.OptionalSchema<v.StringSchema<undefined>, ".spf/data">;
392
+ }, undefined>, () => {
393
+ coding_agent: "claude_code" | "flue";
394
+ model: string;
395
+ thinking: "high" | "low" | "max" | "medium" | "minimal" | "off" | "xhigh";
396
+ color: string;
397
+ harness_engineering: string[];
398
+ tools?: string[] | null | undefined;
399
+ protected_files: string[];
400
+ data_dir: string;
401
+ }>;
402
+ readonly observability: v.OptionalSchema<v.ObjectSchema<{
403
+ readonly db: v.OptionalSchema<v.StringSchema<undefined>, ".spf/data/spf.db">;
404
+ readonly poll_ms: v.OptionalSchema<v.NumberSchema<undefined>, 500>;
405
+ }, undefined>, () => {
406
+ db: string;
407
+ poll_ms: number;
408
+ }>;
409
+ readonly agents: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
410
+ readonly name: v.StringSchema<undefined>;
411
+ readonly coding_agent: v.OptionalSchema<v.PicklistSchema<["flue", "claude_code"], undefined>, "flue">;
412
+ readonly model: v.OptionalSchema<v.StringSchema<undefined>, "google/gemini-3.6-flash">;
413
+ readonly thinking: v.OptionalSchema<v.PicklistSchema<["off", "minimal", "low", "medium", "high", "xhigh", "max"], undefined>, "medium">;
414
+ readonly color: v.OptionalSchema<v.StringSchema<undefined>, "">;
415
+ readonly purpose: v.OptionalSchema<v.StringSchema<undefined>, "">;
416
+ readonly prompt_engineering: v.ObjectSchema<{
417
+ readonly system: v.StringSchema<undefined>;
418
+ readonly user: v.StringSchema<undefined>;
419
+ }, undefined>;
420
+ readonly harness_engineering: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, () => never[]>;
421
+ readonly tools: v.OptionalSchema<v.NullableSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>, undefined>;
422
+ readonly writes: v.OptionalSchema<v.NullableSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>, undefined>;
423
+ }, undefined>, undefined>, () => never[]>;
424
+ readonly quality: v.OptionalSchema<v.ObjectSchema<{
425
+ readonly checks: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
426
+ readonly name: v.StringSchema<undefined>;
427
+ readonly area: v.OptionalSchema<v.PicklistSchema<["frontend", "backend"], undefined>, "backend">;
428
+ readonly operation: v.PicklistSchema<["lint", "typecheck", "build"], undefined>;
429
+ readonly argv: v.SchemaWithPipe<readonly [v.ArraySchema<v.StringSchema<undefined>, undefined>, v.MinLengthAction<string[], 1, "argv must name at least the binary to run">]>;
430
+ readonly timeout_seconds: v.OptionalSchema<v.NumberSchema<undefined>, 120>;
431
+ }, undefined>, undefined>, () => never[]>;
432
+ readonly suites: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>, () => {}>;
433
+ }, undefined>, () => {
434
+ checks: {
435
+ name: string;
436
+ area: "backend" | "frontend";
437
+ operation: "build" | "lint" | "typecheck";
438
+ argv: string[];
439
+ timeout_seconds: number;
440
+ }[];
441
+ suites: {
442
+ [x: string]: string[];
443
+ };
444
+ }>;
445
+ readonly watch: v.OptionalSchema<v.ObjectSchema<{
446
+ readonly provider: v.OptionalSchema<v.PicklistSchema<["github"], undefined>, "github">;
447
+ readonly repo: v.OptionalSchema<v.StringSchema<undefined>, "">;
448
+ readonly label_prefix: v.OptionalSchema<v.StringSchema<undefined>, "spf">;
449
+ readonly chain: v.OptionalSchema<v.StringSchema<undefined>, "plan-build-test">;
450
+ readonly base_branch: v.OptionalSchema<v.StringSchema<undefined>, "main">;
451
+ readonly poll_ms: v.OptionalSchema<v.NumberSchema<undefined>, 60000>;
452
+ readonly concurrency: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, 2>;
453
+ }, undefined>, () => {
454
+ provider: "github";
455
+ repo: string;
456
+ label_prefix: string;
457
+ chain: string;
458
+ base_branch: string;
459
+ poll_ms: number;
460
+ concurrency: number;
461
+ }>;
462
+ }, undefined>;
463
+ export type SFConfig = v.InferOutput<typeof SFConfigSchema>;
464
+ /** One traced event, always logged against adw_id + phase. */
465
+ export interface EventRecord {
466
+ adw_id: string;
467
+ phase_id: string;
468
+ type: string;
469
+ name: string;
470
+ payload: Record<string, unknown>;
471
+ parent_id: string;
472
+ tokens?: number | null;
473
+ started_at?: string | null;
474
+ ended_at?: string | null;
475
+ }
476
+ export declare function makeEventRecord(input: Partial<EventRecord> & {
477
+ adw_id: string;
478
+ type: string;
479
+ }): EventRecord;
480
+ /**
481
+ * Everything one coding-agent dispatch+read turn needs, whichever backend
482
+ * (`coding_agent:` in config) actually runs it — Flue today, others later.
483
+ * Each backend module (`agent_flue.ts`, ...) is free to ignore fields it has
484
+ * no use for (a subprocess-based backend has no use for `flue_db_path`) and
485
+ * to interpret `model` in its own vocabulary (Flue: `provider/model-id`;
486
+ * others may take a bare alias) — `agents.validate()` already branches its
487
+ * model-shape check on `coding_agent` for exactly this reason.
488
+ *
489
+ * No `session_dir`/`raw_output_path` (Flue's own persistence is the durable
490
+ * record for Flue; a subprocess backend owns its own equivalent) and no
491
+ * `extensions` (harness_engineering has no analogue on any current backend —
492
+ * see agents.validate()). `output_schema`/`output_type_name` is the one
493
+ * contract every backend must honor somehow — Flue via an injected
494
+ * `sf_report` tool, a CLI-shaped backend via its own structured-output flag —
495
+ * so a Valibot envelope type becomes that backend's schema-validated output
496
+ * with no second definition anywhere.
497
+ */
498
+ export interface AgentRequest {
499
+ prompt: string;
500
+ system_prompt: string;
501
+ model: string;
502
+ thinking: ThinkingLevel;
503
+ session_id: string;
504
+ resume: boolean;
505
+ tools?: string[] | null;
506
+ output_schema: v.GenericSchema<Record<string, unknown>, unknown>;
507
+ output_type_name: string;
508
+ cwd: string;
509
+ flue_db_path: string;
510
+ }
511
+ /**
512
+ * Tokens and the dollars they cost, per component, summed over a call.
513
+ *
514
+ * Mirrors pi's `usage` shape one-for-one so the numbers reconcile with what
515
+ * pi itself reports: `input` EXCLUDES cache reads, which bill at their own
516
+ * (cheaper) rate — add them to learn the size of the prompt that was sent.
517
+ */
518
+ export declare class UsageBreakdown {
519
+ input_tokens: number;
520
+ output_tokens: number;
521
+ cache_read_tokens: number;
522
+ cache_write_tokens: number;
523
+ reasoning_tokens: number;
524
+ total_tokens: number;
525
+ input_cost: number;
526
+ output_cost: number;
527
+ cache_read_cost: number;
528
+ cache_write_cost: number;
529
+ total_cost: number;
530
+ /**
531
+ * Fold in one pi `message_end` usage object.
532
+ *
533
+ * `totalTokens` is passed in rather than re-derived: the caller already
534
+ * computes it pi's way (totalTokens, else the sum of the parts).
535
+ */
536
+ add_turn(usage: Record<string, any>, totalTokens: number): void;
537
+ /** Add another call's usage — a phase that retries spends more than once. */
538
+ merge(other: UsageBreakdown): void;
539
+ toJSON(): Record<string, number>;
540
+ }
541
+ export interface AgentResult {
542
+ text: string;
543
+ /**
544
+ * The validated structured output, however this backend produced it —
545
+ * Flue's injected `sf_report` tool call, or another backend's own
546
+ * schema-validated result field. Present whenever the backend captured
547
+ * one, regardless of whether it also produced JSON in `text`. `null`
548
+ * means it never validated, so the caller falls back to extracting JSON
549
+ * from `text` directly.
550
+ */
551
+ report: unknown | null;
552
+ session_id: string;
553
+ tokens: number;
554
+ cost: number;
555
+ usage: UsageBreakdown;
556
+ context_tokens: number;
557
+ context_window: number;
558
+ }
559
+ export declare function makeAgentResult(input: Partial<AgentResult> & {
560
+ session_id: string;
561
+ }): AgentResult;
562
+ export {};