@juzser/blacksmith 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 (172) hide show
  1. package/.claude/agents/auditor.md +146 -0
  2. package/.claude/agents/coder.md +164 -0
  3. package/.claude/agents/grader.md +110 -0
  4. package/.claude/agents/merger.md +107 -0
  5. package/.claude/agents/planner.md +92 -0
  6. package/.claude/agents/researcher.md +105 -0
  7. package/.claude/agents/reviewer.md +171 -0
  8. package/.claude/agents/scribe.md +72 -0
  9. package/.claude/agents/security-reviewer.md +130 -0
  10. package/.claude/agents/spec-reviewer.md +215 -0
  11. package/.claude/agents/tester.md +121 -0
  12. package/.claude/agents/uiux.md +126 -0
  13. package/.claude/agents/verifier.md +103 -0
  14. package/.claude/agents/wave-runner.md +74 -0
  15. package/LICENSE +21 -0
  16. package/README.md +389 -0
  17. package/factory/orchestrator/dist/actors.js +46 -0
  18. package/factory/orchestrator/dist/agents-registry.js +308 -0
  19. package/factory/orchestrator/dist/args.js +84 -0
  20. package/factory/orchestrator/dist/artifacts.js +111 -0
  21. package/factory/orchestrator/dist/attribution.js +160 -0
  22. package/factory/orchestrator/dist/audit.js +812 -0
  23. package/factory/orchestrator/dist/autonomy.js +151 -0
  24. package/factory/orchestrator/dist/budgetAlarm.js +366 -0
  25. package/factory/orchestrator/dist/budgets.js +196 -0
  26. package/factory/orchestrator/dist/claims.js +633 -0
  27. package/factory/orchestrator/dist/cli.js +3185 -0
  28. package/factory/orchestrator/dist/commit.js +152 -0
  29. package/factory/orchestrator/dist/coverage.js +188 -0
  30. package/factory/orchestrator/dist/crossFinding.js +479 -0
  31. package/factory/orchestrator/dist/crosscheck.js +396 -0
  32. package/factory/orchestrator/dist/daemon.js +707 -0
  33. package/factory/orchestrator/dist/db/projector.js +1317 -0
  34. package/factory/orchestrator/dist/db/queries.js +1714 -0
  35. package/factory/orchestrator/dist/db/schema.js +305 -0
  36. package/factory/orchestrator/dist/delegation.js +400 -0
  37. package/factory/orchestrator/dist/diffstat.js +164 -0
  38. package/factory/orchestrator/dist/dispatchAudit.js +275 -0
  39. package/factory/orchestrator/dist/dotenv.js +72 -0
  40. package/factory/orchestrator/dist/effort.js +202 -0
  41. package/factory/orchestrator/dist/epic.js +1018 -0
  42. package/factory/orchestrator/dist/epicWidth.js +238 -0
  43. package/factory/orchestrator/dist/errorIssues.js +249 -0
  44. package/factory/orchestrator/dist/errors.js +11 -0
  45. package/factory/orchestrator/dist/escalation.js +500 -0
  46. package/factory/orchestrator/dist/events.js +1015 -0
  47. package/factory/orchestrator/dist/findingAge.js +91 -0
  48. package/factory/orchestrator/dist/findingContext.js +103 -0
  49. package/factory/orchestrator/dist/findings.js +1156 -0
  50. package/factory/orchestrator/dist/gate.js +911 -0
  51. package/factory/orchestrator/dist/gh.js +146 -0
  52. package/factory/orchestrator/dist/git.js +87 -0
  53. package/factory/orchestrator/dist/goalCheck.js +380 -0
  54. package/factory/orchestrator/dist/graph.js +61 -0
  55. package/factory/orchestrator/dist/hookDecision.js +106 -0
  56. package/factory/orchestrator/dist/immutability.js +171 -0
  57. package/factory/orchestrator/dist/impact.js +280 -0
  58. package/factory/orchestrator/dist/integration.js +141 -0
  59. package/factory/orchestrator/dist/judgePreflight.js +155 -0
  60. package/factory/orchestrator/dist/judges.js +310 -0
  61. package/factory/orchestrator/dist/lessonAudit.js +399 -0
  62. package/factory/orchestrator/dist/lessons.js +1329 -0
  63. package/factory/orchestrator/dist/mcp.js +555 -0
  64. package/factory/orchestrator/dist/paths.js +82 -0
  65. package/factory/orchestrator/dist/plan.js +502 -0
  66. package/factory/orchestrator/dist/planQuorum.js +421 -0
  67. package/factory/orchestrator/dist/policy.js +1308 -0
  68. package/factory/orchestrator/dist/policyHook.js +28 -0
  69. package/factory/orchestrator/dist/preconditions.js +47 -0
  70. package/factory/orchestrator/dist/projects.js +134 -0
  71. package/factory/orchestrator/dist/prompts.js +57 -0
  72. package/factory/orchestrator/dist/provenance.js +201 -0
  73. package/factory/orchestrator/dist/providers/api-transport.js +117 -0
  74. package/factory/orchestrator/dist/providers/cli-transport.js +208 -0
  75. package/factory/orchestrator/dist/providers/index.js +54 -0
  76. package/factory/orchestrator/dist/providers/schema-validate.js +152 -0
  77. package/factory/orchestrator/dist/providers/types.js +49 -0
  78. package/factory/orchestrator/dist/queue.js +263 -0
  79. package/factory/orchestrator/dist/quorum.js +347 -0
  80. package/factory/orchestrator/dist/quorumEscalations.js +132 -0
  81. package/factory/orchestrator/dist/results.js +65 -0
  82. package/factory/orchestrator/dist/roadmap.js +437 -0
  83. package/factory/orchestrator/dist/runtime.js +86 -0
  84. package/factory/orchestrator/dist/sameMistakeKpi.js +243 -0
  85. package/factory/orchestrator/dist/sandbox.js +165 -0
  86. package/factory/orchestrator/dist/scaffold.js +373 -0
  87. package/factory/orchestrator/dist/scheduler.js +408 -0
  88. package/factory/orchestrator/dist/schemas.js +195 -0
  89. package/factory/orchestrator/dist/security.js +222 -0
  90. package/factory/orchestrator/dist/severity.js +293 -0
  91. package/factory/orchestrator/dist/spec.js +376 -0
  92. package/factory/orchestrator/dist/specChange.js +497 -0
  93. package/factory/orchestrator/dist/stack.js +324 -0
  94. package/factory/orchestrator/dist/symbols.js +966 -0
  95. package/factory/orchestrator/dist/taskEvents.js +399 -0
  96. package/factory/orchestrator/dist/taskId.js +126 -0
  97. package/factory/orchestrator/dist/taxonomy.js +113 -0
  98. package/factory/orchestrator/dist/testSelect.js +129 -0
  99. package/factory/orchestrator/dist/testerAudit.js +264 -0
  100. package/factory/orchestrator/dist/testgate.js +171 -0
  101. package/factory/orchestrator/dist/usage.js +874 -0
  102. package/factory/orchestrator/dist/waivers.js +228 -0
  103. package/factory/orchestrator/dist/waveBudget.js +223 -0
  104. package/factory/orchestrator/dist/waveConcurrency.js +250 -0
  105. package/factory/orchestrator/dist/waveNext.js +210 -0
  106. package/factory/orchestrator/dist/waveSchedule.js +146 -0
  107. package/factory/orchestrator/dist/worktree.js +207 -0
  108. package/factory/orchestrator/drizzle/0000_broken_rockslide.sql +183 -0
  109. package/factory/orchestrator/drizzle/0001_luxuriant_zaladane.sql +1 -0
  110. package/factory/orchestrator/drizzle/0002_yellow_wild_pack.sql +8 -0
  111. package/factory/orchestrator/drizzle/0003_damp_riptide.sql +12 -0
  112. package/factory/orchestrator/drizzle/0004_broad_lady_vermin.sql +1 -0
  113. package/factory/orchestrator/drizzle/0005_romantic_jocasta.sql +2 -0
  114. package/factory/orchestrator/drizzle/0006_bent_madelyne_pryor.sql +16 -0
  115. package/factory/orchestrator/drizzle/0007_overjoyed_goliath.sql +1 -0
  116. package/factory/orchestrator/drizzle/0008_smart_iron_patriot.sql +2 -0
  117. package/factory/orchestrator/drizzle/0009_agents_epic_id.sql +2 -0
  118. package/factory/orchestrator/drizzle/0010_milestone_kind.sql +1 -0
  119. package/factory/orchestrator/drizzle/meta/_journal.json +83 -0
  120. package/factory/policies/budgets.yml +262 -0
  121. package/factory/policies/crosscheck.yml +308 -0
  122. package/factory/policies/delegation.yml +44 -0
  123. package/factory/policies/effort.yml +142 -0
  124. package/factory/policies/guardrails.yml +306 -0
  125. package/factory/policies/lessons.md +239 -0
  126. package/factory/policies/scheduler.yml +90 -0
  127. package/factory/policies/sensitive-paths.yml +148 -0
  128. package/factory/policies/severity.yml +83 -0
  129. package/factory/policies/stack.yml +60 -0
  130. package/factory/policies/taxonomy.yml +340 -0
  131. package/factory/policies/worktree.yml +95 -0
  132. package/factory/scaffold/base/.github/workflows/ci.yml +34 -0
  133. package/factory/scaffold/base/.gitignore.tmpl +11 -0
  134. package/factory/scaffold/base/AGENTS.md +33 -0
  135. package/factory/scaffold/base/README.md +25 -0
  136. package/factory/scaffold/base/biome.json.tmpl +30 -0
  137. package/factory/scaffold/base/package.json +25 -0
  138. package/factory/scaffold/base/pnpm-workspace.yaml.tmpl +16 -0
  139. package/factory/scaffold/base/src/index.ts +4 -0
  140. package/factory/scaffold/base/test/index.test.ts +8 -0
  141. package/factory/scaffold/base/tsconfig.json +20 -0
  142. package/factory/scaffold/base/tsconfig.test.json +9 -0
  143. package/factory/scaffold/base/vitest.config.ts +29 -0
  144. package/factory/scaffold/mcp/mcp.manifest.json +22 -0
  145. package/factory/scaffold/mcp/package.fragment.json +9 -0
  146. package/factory/scaffold/mcp/src/mcp/README.md +63 -0
  147. package/factory/scaffold/mcp/src/mcp/guard.ts +110 -0
  148. package/factory/scaffold/mcp/src/mcp/redact.ts +69 -0
  149. package/factory/scaffold/mcp/src/mcp/server.ts +55 -0
  150. package/factory/scaffold/mcp/src/mcp/tools/health.ts +60 -0
  151. package/factory/scaffold/mcp/test/mcp/guard.test.ts +108 -0
  152. package/factory/scaffold/mcp/test/mcp/redact.test.ts +61 -0
  153. package/factory/scaffold/mcp/test/mcp/surface.test.ts +100 -0
  154. package/factory/scaffold/ui/index.html +12 -0
  155. package/factory/scaffold/ui/package.fragment.json +13 -0
  156. package/factory/scaffold/ui/src/App.vue +10 -0
  157. package/factory/scaffold/ui/src/main.ts +5 -0
  158. package/factory/scaffold/ui/src/shims.d.ts +11 -0
  159. package/factory/scaffold/ui/vite.config.ts +20 -0
  160. package/factory/scaffold/ui-tailwind/package.fragment.json +6 -0
  161. package/factory/scaffold/ui-tailwind/vite.config.ts +26 -0
  162. package/factory/specs/schema/event.schema.json +82 -0
  163. package/factory/specs/schema/finding-evidence.schema.json +45 -0
  164. package/factory/specs/schema/finding.schema.json +115 -0
  165. package/factory/specs/schema/grader-verdict.schema.json +50 -0
  166. package/factory/specs/schema/judge-verdict.schema.json +19 -0
  167. package/factory/specs/schema/lesson.schema.json +85 -0
  168. package/factory/specs/schema/mcp-manifest.schema.json +230 -0
  169. package/factory/specs/schema/result.schema.json +81 -0
  170. package/factory/specs/schema/spec-change-request.schema.json +46 -0
  171. package/factory/specs/schema/task-spec.schema.json +134 -0
  172. package/package.json +98 -0
@@ -0,0 +1,207 @@
1
+ import path from 'node:path';
2
+ import { SmithError } from './errors.js';
3
+ import { runGit as git } from './git.js';
4
+ export class WorktreeError extends SmithError {
5
+ }
6
+ /** The task-id segment reserved for an epic's integration branch (smith/<epic>/integration) —
7
+ * never a real task. Exported for db/projector.ts's foldTasks() guard and epic.ts's
8
+ * runEpicVerdict(), both of which need to recognise `<epic>/integration` as non-task. */
9
+ export const RESERVED_TASK_ID = 'integration';
10
+ function localBranchExists(projectDir, branch) {
11
+ try {
12
+ git(projectDir, ['show-ref', '--verify', '--quiet', `refs/heads/${branch}`]);
13
+ return true;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ /**
20
+ * Best-effort default-branch detection: origin/HEAD symbolic ref first (the
21
+ * normal case after a clone), then whatever branch is currently checked out,
22
+ * then the conventional main/master names.
23
+ */
24
+ function detectDefaultBranch(projectDir) {
25
+ try {
26
+ const ref = git(projectDir, ['symbolic-ref', 'refs/remotes/origin/HEAD']);
27
+ const name = ref.replace(/^refs\/remotes\/origin\//, '');
28
+ if (name && name !== ref)
29
+ return name;
30
+ }
31
+ catch {
32
+ // no origin/HEAD — fall through
33
+ }
34
+ try {
35
+ const current = git(projectDir, ['branch', '--show-current']);
36
+ if (current)
37
+ return current;
38
+ }
39
+ catch {
40
+ // detached or no commits yet — fall through
41
+ }
42
+ for (const candidate of ['main', 'master']) {
43
+ if (localBranchExists(projectDir, candidate))
44
+ return candidate;
45
+ }
46
+ throw new WorktreeError('worktree.default-branch-not-found', `Could not detect a default branch in ${projectDir}.`, { projectDir });
47
+ }
48
+ /**
49
+ * A task id without its own epic prefix: `epic-7/task-142` under epic-7 is
50
+ * `task-142`, and the same string under a *different* epic is left alone —
51
+ * the leading segment belongs to the id then, not to this epic.
52
+ *
53
+ * D-177: the branch name applied this strip and the directory did not, so one
54
+ * task id addressed one branch but two directories, and which one you got
55
+ * depended on how the operator happened to spell the id. Every shipped spec
56
+ * writes the qualified form; `listStale` derives the id it prints from the
57
+ * branch, so it always prints the bare form — and `worktree rm`, the verb the
58
+ * operator guide pairs it with, computed a path that did not exist for any
59
+ * worktree created from the qualified spelling. Four envkit worktrees sat on
60
+ * disk unreachable by the only verb meant to remove them.
61
+ *
62
+ * Deliberately not taskId.ts's single-argument `bareTaskId`, which drops the
63
+ * first segment whether or not it matches: a task id whose leading segment is
64
+ * some *other* epic keeps it, here and in the branch alike.
65
+ */
66
+ function bareTaskId(epic, taskId) {
67
+ return taskId.startsWith(`${epic}/`) ? taskId.slice(epic.length + 1) : taskId;
68
+ }
69
+ /**
70
+ * Where a task's worktree lives: `<parent>/.wt/<project>/<bare-task-id>`, a
71
+ * SIBLING of the project rather than a child of it. Takes the epic for the
72
+ * same reason `taskBranchName` does — so both spellings of one id land in one
73
+ * place (D-177).
74
+ *
75
+ * D-42/P9-26: this used to be `path.join(projectDir, 'wt', taskId)`, and the
76
+ * cost was an epic whose six per-task lint gates were all green while
77
+ * `pnpm lint` at the integration root exited 1 without reading a source file.
78
+ * Every worktree is a full checkout carrying the project's own `biome.json`,
79
+ * so a tool that walks down from the project root found seven root configs
80
+ * and refused to run. From inside a worktree the siblings are not
81
+ * descendants, so no task gate could ever see the condition. Placing them
82
+ * outside the root kills the class outright: no root-walking tool can reach
83
+ * a path it would have to climb *up* to find, whatever tool comes next.
84
+ *
85
+ * D-40: absolute, always. `git worktree add` resolves a relative path against
86
+ * the git cwd — which is `projectDir` — so a relative `projectDir` used to
87
+ * put the checkout at `<root>/envkit/<root>/envkit/wt/<task>` while
88
+ * the returned path claimed otherwise. Resolving up front means the string
89
+ * this module returns is the string on disk.
90
+ */
91
+ export function taskWorktreeDir(projectDir, epic, taskId) {
92
+ const project = path.resolve(projectDir);
93
+ return path.join(path.dirname(project), '.wt', path.basename(project), bareTaskId(epic, taskId));
94
+ }
95
+ /** `smith/<epic>/integration` — the one branch an epic assembles onto. Exported for
96
+ * integration.ts, which runs the check suite against it (D-42/P9-26). */
97
+ export function integrationBranchName(epic) {
98
+ return `smith/${epic}/integration`;
99
+ }
100
+ /**
101
+ * `smith/<epic>/<bare-task-id>` — the branch convention, defined once.
102
+ *
103
+ * D-23/P9-12: exported because three places need to agree on it — this module
104
+ * (which creates the branch), taskEvents.ts's `task-added` (which declares it
105
+ * so the board can link to it before any worktree exists), and
106
+ * db/projector.ts's fallback for events logged before that payload field.
107
+ * Three hand-written copies of one string convention is one copy too many.
108
+ *
109
+ * A task_id already embeds its epic ("epic-7/task-142", findings.ts's
110
+ * convention) so strip that prefix before rejoining — concatenating epic +
111
+ * full task_id double-embeds it (smith/epic-7/epic-7/task-142). The CLI hands
112
+ * this whatever the operator typed, so both shapes really do arrive.
113
+ */
114
+ export function taskBranchName(epic, taskId) {
115
+ return `smith/${epic}/${bareTaskId(epic, taskId)}`;
116
+ }
117
+ function ensureIntegrationBranch(projectDir, epic) {
118
+ const branch = integrationBranchName(epic);
119
+ if (!localBranchExists(projectDir, branch)) {
120
+ const defaultBranch = detectDefaultBranch(projectDir);
121
+ git(projectDir, ['branch', branch, defaultBranch]);
122
+ }
123
+ return branch;
124
+ }
125
+ /**
126
+ * Create a task worktree at `<projects root>/.wt/<project>/<task-id>` — a
127
+ * sibling of whatever directory the project was handed as, never a path of
128
+ * this module's own choosing, so a project outside this clone keeps its
129
+ * worktrees outside it too (see taskWorktreeDir)
130
+ * on branch smith/<epic>/<task-id>, cut from the CURRENT head of
131
+ * smith/<epic>/integration (creating the integration branch from the default
132
+ * branch first if it doesn't exist yet).
133
+ */
134
+ export function createTaskWorktree(projectDir, epic, taskId) {
135
+ if (taskId === RESERVED_TASK_ID) {
136
+ throw new WorktreeError('worktree.reserved-task-id', `Task id "${RESERVED_TASK_ID}" is reserved for the integration branch itself.`, { taskId });
137
+ }
138
+ const integrationBranch = ensureIntegrationBranch(projectDir, epic);
139
+ const branch = taskBranchName(epic, taskId);
140
+ const worktreeDir = taskWorktreeDir(projectDir, epic, taskId);
141
+ git(projectDir, ['worktree', 'add', '-b', branch, worktreeDir, integrationBranch]);
142
+ return { worktreeDir, branch, epic, taskId };
143
+ }
144
+ /** Remove a task's worktree and its local branch after it has merged. */
145
+ export function removeTaskWorktree(projectDir, epic, taskId) {
146
+ const worktreeDir = taskWorktreeDir(projectDir, epic, taskId);
147
+ const branch = taskBranchName(epic, taskId);
148
+ try {
149
+ git(projectDir, ['worktree', 'remove', worktreeDir]);
150
+ }
151
+ catch (err) {
152
+ throw new WorktreeError('worktree.remove-failed', `Failed to remove worktree at ${worktreeDir}: ${err instanceof Error ? err.message : String(err)}`, { worktreeDir });
153
+ }
154
+ try {
155
+ git(projectDir, ['branch', '-d', branch]);
156
+ }
157
+ catch (err) {
158
+ throw new WorktreeError('worktree.branch-delete-failed', `Failed to delete branch ${branch} (not fully merged?): ${err instanceof Error ? err.message : String(err)}`, { branch });
159
+ }
160
+ }
161
+ function parseWorktreePorcelain(output) {
162
+ const entries = [];
163
+ let current = null;
164
+ for (const line of output.split('\n')) {
165
+ if (line.startsWith('worktree ')) {
166
+ if (current?.worktree)
167
+ entries.push({ worktree: current.worktree, branch: current.branch ?? null });
168
+ current = { worktree: line.slice('worktree '.length), branch: null };
169
+ }
170
+ else if (line.startsWith('branch ') && current) {
171
+ current.branch = line.slice('branch '.length).replace(/^refs\/heads\//, '');
172
+ }
173
+ else if (line === '' && current?.worktree) {
174
+ entries.push({ worktree: current.worktree, branch: current.branch ?? null });
175
+ current = null;
176
+ }
177
+ }
178
+ if (current?.worktree)
179
+ entries.push({ worktree: current.worktree, branch: current.branch ?? null });
180
+ return entries;
181
+ }
182
+ /**
183
+ * List task worktrees whose branch is fully merged into smith/<epic>/integration.
184
+ * Reports only — never deletes.
185
+ */
186
+ export function listStale(projectDir, epic) {
187
+ const integrationBranch = integrationBranchName(epic);
188
+ const prefix = `smith/${epic}/`;
189
+ const porcelain = git(projectDir, ['worktree', 'list', '--porcelain']);
190
+ const entries = parseWorktreePorcelain(porcelain);
191
+ const stale = [];
192
+ for (const entry of entries) {
193
+ if (!entry.branch?.startsWith(prefix))
194
+ continue;
195
+ const taskId = entry.branch.slice(prefix.length);
196
+ if (taskId === RESERVED_TASK_ID)
197
+ continue;
198
+ try {
199
+ git(projectDir, ['merge-base', '--is-ancestor', entry.branch, integrationBranch]);
200
+ stale.push({ worktreeDir: entry.worktree, branch: entry.branch, taskId });
201
+ }
202
+ catch {
203
+ // not an ancestor -> not merged yet, not stale
204
+ }
205
+ }
206
+ return stale;
207
+ }
@@ -0,0 +1,183 @@
1
+ CREATE TABLE `agents` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `session_id` text NOT NULL,
4
+ `task_id` text,
5
+ `agent_id` text,
6
+ `agent_role` text NOT NULL,
7
+ `provider` text NOT NULL,
8
+ `model_tier` text NOT NULL,
9
+ `dispatched_at` text NOT NULL,
10
+ `terminal_event_id` text,
11
+ `terminal_at` text,
12
+ `terminal_type` text,
13
+ `status` text NOT NULL
14
+ );
15
+ --> statement-breakpoint
16
+ CREATE INDEX `agents_session_idx` ON `agents` (`session_id`);--> statement-breakpoint
17
+ CREATE INDEX `agents_status_idx` ON `agents` (`status`);--> statement-breakpoint
18
+ CREATE INDEX `agents_role_idx` ON `agents` (`agent_role`);--> statement-breakpoint
19
+ CREATE TABLE `artifacts` (
20
+ `id` text PRIMARY KEY NOT NULL,
21
+ `session_id` text NOT NULL,
22
+ `task_id` text NOT NULL,
23
+ `event_id` text NOT NULL,
24
+ `ts` text NOT NULL,
25
+ `type` text NOT NULL,
26
+ `path` text NOT NULL,
27
+ `description` text
28
+ );
29
+ --> statement-breakpoint
30
+ CREATE INDEX `artifacts_session_idx` ON `artifacts` (`session_id`);--> statement-breakpoint
31
+ CREATE INDEX `artifacts_task_idx` ON `artifacts` (`task_id`);--> statement-breakpoint
32
+ CREATE TABLE `dispatches` (
33
+ `event_id` text PRIMARY KEY NOT NULL,
34
+ `session_id` text NOT NULL,
35
+ `ts` text NOT NULL,
36
+ `task_id` text,
37
+ `agent_id` text,
38
+ `agent_role` text NOT NULL,
39
+ `provider` text NOT NULL,
40
+ `model_tier` text NOT NULL,
41
+ `spec_ref` text,
42
+ `reason` text,
43
+ `parent_prompt_id` text,
44
+ `causal_parent` text
45
+ );
46
+ --> statement-breakpoint
47
+ CREATE INDEX `dispatches_session_idx` ON `dispatches` (`session_id`);--> statement-breakpoint
48
+ CREATE INDEX `dispatches_task_idx` ON `dispatches` (`task_id`);--> statement-breakpoint
49
+ CREATE INDEX `dispatches_role_idx` ON `dispatches` (`agent_role`);--> statement-breakpoint
50
+ CREATE INDEX `dispatches_provider_idx` ON `dispatches` (`provider`);--> statement-breakpoint
51
+ CREATE INDEX `dispatches_model_tier_idx` ON `dispatches` (`model_tier`);--> statement-breakpoint
52
+ CREATE TABLE `edges` (
53
+ `event_id` text PRIMARY KEY NOT NULL,
54
+ `session_id` text NOT NULL,
55
+ `ts` text NOT NULL,
56
+ `task_id` text NOT NULL,
57
+ `depends_on` text NOT NULL,
58
+ `edge_type` text NOT NULL,
59
+ `edge_provenance` text NOT NULL
60
+ );
61
+ --> statement-breakpoint
62
+ CREATE INDEX `edges_session_idx` ON `edges` (`session_id`);--> statement-breakpoint
63
+ CREATE INDEX `edges_task_idx` ON `edges` (`task_id`);--> statement-breakpoint
64
+ CREATE TABLE `errors` (
65
+ `event_id` text PRIMARY KEY NOT NULL,
66
+ `session_id` text NOT NULL,
67
+ `ts` text NOT NULL,
68
+ `task_ref` text,
69
+ `agent_id` text,
70
+ `error_group` text NOT NULL,
71
+ `error_class` text NOT NULL,
72
+ `severity` text NOT NULL,
73
+ `detail` text
74
+ );
75
+ --> statement-breakpoint
76
+ CREATE INDEX `errors_session_idx` ON `errors` (`session_id`);--> statement-breakpoint
77
+ CREATE INDEX `errors_group_idx` ON `errors` (`error_group`);--> statement-breakpoint
78
+ CREATE INDEX `errors_severity_idx` ON `errors` (`severity`);--> statement-breakpoint
79
+ CREATE INDEX `errors_ts_idx` ON `errors` (`ts`);--> statement-breakpoint
80
+ CREATE TABLE `events_raw` (
81
+ `event_id` text PRIMARY KEY NOT NULL,
82
+ `session_id` text NOT NULL,
83
+ `ts` text NOT NULL,
84
+ `event_type` text NOT NULL,
85
+ `task_id` text,
86
+ `agent_id` text,
87
+ `plan_version` integer NOT NULL,
88
+ `causal_parent` text,
89
+ `payload` text NOT NULL
90
+ );
91
+ --> statement-breakpoint
92
+ CREATE INDEX `events_raw_session_idx` ON `events_raw` (`session_id`);--> statement-breakpoint
93
+ CREATE INDEX `events_raw_task_idx` ON `events_raw` (`task_id`);--> statement-breakpoint
94
+ CREATE INDEX `events_raw_type_idx` ON `events_raw` (`event_type`);--> statement-breakpoint
95
+ CREATE INDEX `events_raw_ts_idx` ON `events_raw` (`ts`);--> statement-breakpoint
96
+ CREATE TABLE `findings` (
97
+ `finding_id` text PRIMARY KEY NOT NULL,
98
+ `session_id` text NOT NULL,
99
+ `task_id` text NOT NULL,
100
+ `epic_id` text,
101
+ `fingerprint` text NOT NULL,
102
+ `finding_category` text NOT NULL,
103
+ `severity` text NOT NULL,
104
+ `finding_status` text NOT NULL,
105
+ `summary` text NOT NULL,
106
+ `found_by` text NOT NULL,
107
+ `found_by_provider` text,
108
+ `verified_by` text,
109
+ `verified_by_provider` text,
110
+ `same_mistake_of_lesson_id` text,
111
+ `waiver_id` text,
112
+ `raised_at` text NOT NULL,
113
+ `updated_at` text NOT NULL
114
+ );
115
+ --> statement-breakpoint
116
+ CREATE INDEX `findings_session_idx` ON `findings` (`session_id`);--> statement-breakpoint
117
+ CREATE INDEX `findings_task_idx` ON `findings` (`task_id`);--> statement-breakpoint
118
+ CREATE INDEX `findings_status_idx` ON `findings` (`finding_status`);--> statement-breakpoint
119
+ CREATE INDEX `findings_severity_idx` ON `findings` (`severity`);--> statement-breakpoint
120
+ CREATE INDEX `findings_fingerprint_idx` ON `findings` (`fingerprint`);--> statement-breakpoint
121
+ CREATE TABLE `lessons` (
122
+ `lesson_id` text PRIMARY KEY NOT NULL,
123
+ `session_id` text NOT NULL,
124
+ `lesson_type` text NOT NULL,
125
+ `lesson_level` text NOT NULL,
126
+ `lesson_status` text NOT NULL,
127
+ `lesson_scope` text NOT NULL,
128
+ `statement` text NOT NULL,
129
+ `valid_from` text NOT NULL,
130
+ `superseded_by` text,
131
+ `invalidated_by_event_id` text,
132
+ `provenance_event_ids` text,
133
+ `evidence` text,
134
+ `times_prevented` integer DEFAULT 0 NOT NULL
135
+ );
136
+ --> statement-breakpoint
137
+ CREATE INDEX `lessons_session_idx` ON `lessons` (`session_id`);--> statement-breakpoint
138
+ CREATE INDEX `lessons_status_idx` ON `lessons` (`lesson_status`);--> statement-breakpoint
139
+ CREATE TABLE `prompts` (
140
+ `event_id` text PRIMARY KEY NOT NULL,
141
+ `session_id` text NOT NULL,
142
+ `ts` text NOT NULL,
143
+ `prompt` text NOT NULL,
144
+ `causal_parent` text
145
+ );
146
+ --> statement-breakpoint
147
+ CREATE INDEX `prompts_session_idx` ON `prompts` (`session_id`);--> statement-breakpoint
148
+ CREATE TABLE `sessions` (
149
+ `session_id` text PRIMARY KEY NOT NULL,
150
+ `started_at` text NOT NULL,
151
+ `last_event_at` text NOT NULL,
152
+ `event_count` integer NOT NULL
153
+ );
154
+ --> statement-breakpoint
155
+ CREATE TABLE `tasks` (
156
+ `task_id` text PRIMARY KEY NOT NULL,
157
+ `session_id` text NOT NULL,
158
+ `epic_id` text,
159
+ `case_tag` text,
160
+ `origin` text,
161
+ `task_status` text NOT NULL,
162
+ `plan_version` integer,
163
+ `objective` text,
164
+ `claims` text,
165
+ `branch` text,
166
+ `created_at` text NOT NULL,
167
+ `updated_at` text NOT NULL
168
+ );
169
+ --> statement-breakpoint
170
+ CREATE INDEX `tasks_session_idx` ON `tasks` (`session_id`);--> statement-breakpoint
171
+ CREATE INDEX `tasks_epic_idx` ON `tasks` (`epic_id`);--> statement-breakpoint
172
+ CREATE INDEX `tasks_status_idx` ON `tasks` (`task_status`);--> statement-breakpoint
173
+ CREATE TABLE `waivers` (
174
+ `event_id` text PRIMARY KEY NOT NULL,
175
+ `session_id` text NOT NULL,
176
+ `ts` text NOT NULL,
177
+ `fingerprint` text NOT NULL,
178
+ `decision` text NOT NULL,
179
+ `operator_note` text
180
+ );
181
+ --> statement-breakpoint
182
+ CREATE INDEX `waivers_session_idx` ON `waivers` (`session_id`);--> statement-breakpoint
183
+ CREATE INDEX `waivers_fingerprint_idx` ON `waivers` (`fingerprint`);
@@ -0,0 +1 @@
1
+ ALTER TABLE `tasks` ADD `budget_tokens` integer;
@@ -0,0 +1,8 @@
1
+ CREATE TABLE `milestones` (
2
+ `milestone_id` text PRIMARY KEY NOT NULL,
3
+ `name` text NOT NULL,
4
+ `status` text NOT NULL,
5
+ `sequence` integer NOT NULL,
6
+ `goal` text,
7
+ `epic_ids` text NOT NULL
8
+ );
@@ -0,0 +1,12 @@
1
+ ALTER TABLE `dispatches` ADD `project` text;--> statement-breakpoint
2
+ CREATE INDEX `dispatches_project_idx` ON `dispatches` (`project`);--> statement-breakpoint
3
+ ALTER TABLE `errors` ADD `project` text;--> statement-breakpoint
4
+ CREATE INDEX `errors_project_idx` ON `errors` (`project`);--> statement-breakpoint
5
+ ALTER TABLE `events_raw` ADD `project` text;--> statement-breakpoint
6
+ CREATE INDEX `events_raw_project_idx` ON `events_raw` (`project`);--> statement-breakpoint
7
+ ALTER TABLE `findings` ADD `project` text;--> statement-breakpoint
8
+ CREATE INDEX `findings_project_idx` ON `findings` (`project`);--> statement-breakpoint
9
+ ALTER TABLE `milestones` ADD `project` text DEFAULT 'black-smith' NOT NULL;--> statement-breakpoint
10
+ CREATE INDEX `milestones_project_idx` ON `milestones` (`project`);--> statement-breakpoint
11
+ ALTER TABLE `tasks` ADD `project` text;--> statement-breakpoint
12
+ CREATE INDEX `tasks_project_idx` ON `tasks` (`project`);
@@ -0,0 +1 @@
1
+ ALTER TABLE `events_raw` ADD `actor` text;
@@ -0,0 +1,2 @@
1
+ ALTER TABLE `lessons` ADD `finding_category` text;--> statement-breakpoint
2
+ ALTER TABLE `lessons` ADD `claim_path` text;
@@ -0,0 +1,16 @@
1
+ CREATE TABLE `epics` (
2
+ `epic_id` text PRIMARY KEY NOT NULL,
3
+ `session_id` text NOT NULL,
4
+ `epic_status` text NOT NULL,
5
+ `closed_by` text NOT NULL,
6
+ `machine_verdict` text,
7
+ `machine_reason` text,
8
+ `override_rationale` text,
9
+ `blockers` text,
10
+ `closed_at` text NOT NULL,
11
+ `event_id` text NOT NULL,
12
+ `project` text
13
+ );
14
+ --> statement-breakpoint
15
+ CREATE INDEX `epics_session_idx` ON `epics` (`session_id`);--> statement-breakpoint
16
+ CREATE INDEX `epics_project_idx` ON `epics` (`project`);
@@ -0,0 +1 @@
1
+ ALTER TABLE `agents` ADD `round` integer DEFAULT 1 NOT NULL;
@@ -0,0 +1,2 @@
1
+ ALTER TABLE `lessons` ADD `agent_role` text;--> statement-breakpoint
2
+ ALTER TABLE `lessons` ADD `case_type` text;
@@ -0,0 +1,2 @@
1
+ ALTER TABLE `agents` ADD `epic_id` text;--> statement-breakpoint
2
+ CREATE INDEX `agents_epic_idx` ON `agents` (`epic_id`);
@@ -0,0 +1 @@
1
+ ALTER TABLE `milestones` ADD `kind` text DEFAULT 'factory' NOT NULL;
@@ -0,0 +1,83 @@
1
+ {
2
+ "version": "7",
3
+ "dialect": "sqlite",
4
+ "entries": [
5
+ {
6
+ "idx": 0,
7
+ "version": "6",
8
+ "when": 1785818885974,
9
+ "tag": "0000_broken_rockslide",
10
+ "breakpoints": true
11
+ },
12
+ {
13
+ "idx": 1,
14
+ "version": "6",
15
+ "when": 1785819387767,
16
+ "tag": "0001_luxuriant_zaladane",
17
+ "breakpoints": true
18
+ },
19
+ {
20
+ "idx": 2,
21
+ "version": "6",
22
+ "when": 1785823535112,
23
+ "tag": "0002_yellow_wild_pack",
24
+ "breakpoints": true
25
+ },
26
+ {
27
+ "idx": 3,
28
+ "version": "6",
29
+ "when": 1785831313729,
30
+ "tag": "0003_damp_riptide",
31
+ "breakpoints": true
32
+ },
33
+ {
34
+ "idx": 4,
35
+ "version": "6",
36
+ "when": 1785831788547,
37
+ "tag": "0004_broad_lady_vermin",
38
+ "breakpoints": true
39
+ },
40
+ {
41
+ "idx": 5,
42
+ "version": "6",
43
+ "when": 1785851922349,
44
+ "tag": "0005_romantic_jocasta",
45
+ "breakpoints": true
46
+ },
47
+ {
48
+ "idx": 6,
49
+ "version": "6",
50
+ "when": 1786081446525,
51
+ "tag": "0006_bent_madelyne_pryor",
52
+ "breakpoints": true
53
+ },
54
+ {
55
+ "idx": 7,
56
+ "version": "6",
57
+ "when": 1786132918663,
58
+ "tag": "0007_overjoyed_goliath",
59
+ "breakpoints": true
60
+ },
61
+ {
62
+ "idx": 8,
63
+ "version": "6",
64
+ "when": 1786939800891,
65
+ "tag": "0008_smart_iron_patriot",
66
+ "breakpoints": true
67
+ },
68
+ {
69
+ "idx": 9,
70
+ "version": "6",
71
+ "when": 1787382509200,
72
+ "tag": "0009_agents_epic_id",
73
+ "breakpoints": true
74
+ },
75
+ {
76
+ "idx": 10,
77
+ "version": "6",
78
+ "when": 1788429177107,
79
+ "tag": "0010_milestone_kind",
80
+ "breakpoints": true
81
+ }
82
+ ]
83
+ }