Commit graph

82 commits

Author SHA1 Message Date
Randall Stillwell
3810cd9dab feat(worker): harness registry dispatch — wire WorkerExecutor for remote-ag-ui
Replaces the hardcoded createMinimalSession in handle-job.ts with a registry
lookup via getExecutor(harnessConfig). The 'minimal' harness still wraps
createMinimalSession; 'remote-ag-ui' POSTs the task payload to a remote agent
endpoint (OpenHands / Open Code / etc.) and polls for completion.

Worker-side completion of Brief 3 (harness-registry-adapter). Pairs with the
already-built AG-UI inbound route at /api/ag-ui/[workspace] and the
harness_providers / role_harness_routes tables.
2026-09-03 23:27:25 -05:00
Randall Stillwell
2ed38fa1f2 chore(convoy): polish-dag-tiers-cost → merged (approved, all follow-ons closed) 2026-08-25 20:33:37 -05:00
Randall Stillwell
e3af2c33e6 feat(polish): cost caps + DAG + tiers + preflight + checks panel
- Cost caps: budget_caps table, MTD spend ledger, tRPC budgets router, orchestrator pause on cap
- DAG viz: convoy-dag.tsx SVG for brief dependencies in Mission Control
- Automation tiers: manual|assist|auto per convoy, orchestrator respects manual
- Preflight: connected-repos preflight endpoint
- Checks panel: forge checks stub in detail panel
- Budget caps schema + tRPC router + Settings UI stub

Convoy: .convoys/polish-dag-tiers-cost

Co-authored-by: orchestrator
2026-08-25 20:33:10 -05:00
Randall Stillwell
9ad114b2f5 chore(convoy): owner-cockpit-v02 → merged (approved, Epic 8/11/12 + doc-writer) 2026-08-25 18:55:50 -05:00
Randall Stillwell
02b1ae610a chore(convoy): owner-cockpit-v02 → in-progress (implementers complete, awaiting review) 2026-08-25 17:49:54 -05:00
Randall Stillwell
6f139d6af2 feat(owner-cockpit): forge webhooks + artifacts + copilot (Epic 8/11/12)
- Forge webhook POST /api/webhooks/forge HMAC sha256 verify, marker echodo-convoy → pr_review→merged as automation
- Completion artifacts table 0017, deterministic summary template, gallery /artifacts
- Ops copilot tRPC copilot + context tools (fleet, convoy, backlog) + panel + Draft Task → backlog.createTask
- Doc-writer SOPs: webhook rotation, copilot prompt, published flow examples
- Allow pr_review→merged as automation for webhook

Convoy: .convoys/owner-cockpit-v02

Co-authored-by: orchestrator
2026-08-25 17:49:38 -05:00
Randall Stillwell
6e17936b7f chore(convoy): worker-closeout-docwriter → merged (approved, Epic 7 closeout) 2026-08-25 17:13:52 -05:00
Randall Stillwell
86155455a7 feat(worker): close Epic 7 — draft PR + operator notes + doc-writer
- Draft PR via forge (apps/worker/src/git/pr.ts) push branch + createPullRequest draft with echodo-convoy marker, expose prUrl in Mission Control (convoy-service, convoys router, detail panel)
- Operator notes mid-build: convoy_operator_messages (0016), tRPC post/list, worker poll between tool rounds (queued) and before generateText (direct), detail panel thread for in_progress
- Doc-writer: harness doc-writer examples (docs/examples/research-pipeline.md), SOP template (docs/templates/doc-sop.md), role-doc-writer wiring

Convoy: .convoys/worker-closeout-docwriter

Co-authored-by: orchestrator
2026-08-25 16:56:02 -05:00
Randall Stillwell
1c27c88b14 chore(convoy): second-brain-os-v01 → merged (reviewed, lint/type-check/build pass) 2026-08-25 16:22:02 -05:00
Randall Stillwell
38d91d4749 merge feat/second-brain-os-v01 → main (second brain OS v0.1) 2026-08-25 16:21:55 -05:00
Randall Stillwell
6ccb060bea feat(second-brain): open self-hosted Obsidian for crews — harness-agnostic v0.1
- MCP create-backlog-item for natural language Plan/Epic/Task authoring
- Worker non-code: optional worktree + per-harness allowlist + doc_review→published
- Harness registry: harness_providers/role_harness_routes, WorkerAdapter (minimal|crewai|langgraph|remote-ag-ui), AG-UI POST /api/ag-ui, Settings → Harnesses with Test
- Plans tree: backlog.listTree + createPlan/Epic/Task + Start→Convoy, web CRUD without CLI
- Fleet: /fleet rollup across workspaces + SSE /api/fleet/events

Decision: docs/decisions/2026-08-25-second-brain-os-pivot.md
Convoy: .convoys/second-brain-os-v01

Co-authored-by: orchestrator
2026-08-25 16:20:53 -05:00
Randall Stillwell
d1b2b9695e docs(plans): expand automation foundation for owner cockpit vision
Add epics 10–12 (plans UI, completion artifacts, ops copilot), worker
draft-PR and live E2E verify tasks, and phase A–E execution order after
A1 gap review.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-12 14:11:20 -05:00
Randall Stillwell
35def387ae docs(plans): add Autensa benchmark tasks to automation foundation roadmap
Map reliability, operator UX, and spend-control follow-ons onto epics 1–9
so worker, webhooks, and fleet work have bead-scale task briefs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-03 10:48:36 -05:00
Randall Stillwell
2f6adf4382 feat(web): Submatter marketing redesign with Signal Editorial system
Introduce public /landing and /pricing pages for the SBMTR brand with
bento features, convoy product demo, motion reveals, and scoped marketing
tokens. Unauthenticated visitors route to the landing page.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-10 22:50:05 -05:00
Randall Stillwell
b513b3b04f fix(docker): serialize Coolify builds and harden web/worker image inputs
Avoid Coolify OOM crashes by documenting and scripting sequential service builds, and make Docker builds resilient to local-only .env symlinks and missing .cursor agent paths.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-08 01:00:21 -05:00
Randall Stillwell
e8074dc5fc fix(docker): unblock orchestrator and worker Coolify builds
Disable inherited incremental compilation for tsup DTS in orchestrator and worker, and align Dockerfile entrypoints with dist/index.js output.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 23:33:31 -05:00
Randall Stillwell
3e33cab2d6 fix(mcp): keep yaml external in tsup bundle for Docker ESM runtime
Inlining yaml into the MCP ESM bundle caused dynamic require("process") crashes in production. Externalize yaml for mcp-server, orchestrator, and worker builds.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 22:53:44 -05:00
varutasu
8e1ab90fb1
feat(worker): minimal agent runtime for orchestrator jobs (Epic 7) (#11)
* feat(worker): minimal agent runtime for orchestrator jobs (Epic 7)

Adds apps/worker to consume Redis dispatch jobs, run a tool loop with model registry resolution, and record claim/complete + convoy role_complete events.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(deploy): add orchestrator and worker to Coolify compose

Fix CI pnpm setup conflict and ship Docker targets for the automation stack alongside web/collab/mcp.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 15:31:34 -05:00
varutasu
5bade93b07
feat(orchestrator): convoy driver tick loop (Epic 6)
feat(orchestrator): convoy driver tick loop (Epic 6)
2026-07-07 15:16:57 -05:00
Randall Stillwell
8b01c1b8dd feat(orchestrator): convoy driver tick loop and Redis job queue (Epic 6)
Adds apps/orchestrator with planOrchestratorAction in shared, dry-run mode,
Redis role_dispatch enqueue, gate pauses, and stall detection logging.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 15:16:34 -05:00
varutasu
5025ac5266
feat(mission-control): convoy kanban, gate inbox, co-pilot (Epic 5)
feat(mission-control): convoy kanban, gate inbox, co-pilot (Epic 5)
2026-07-07 15:16:13 -05:00
Randall Stillwell
ea70716fc6 feat(mission-control): convoy kanban, gate inbox, and co-pilot (Epic 5)
Adds mission control UI with human gate actions via tRPC, kanban columns from
the shared lifecycle enum, and gate co-pilot using resolveModel('gate-copilot').

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 15:01:03 -05:00
varutasu
4bb553c15f
feat(convoys): convoy lifecycle MCP (Epic 4)
feat(convoys): convoy lifecycle MCP (Epic 4)
2026-07-07 14:51:30 -05:00
Randall Stillwell
9405da8a45 feat(convoys): convoy lifecycle MCP and state machine (Epic 4)
Adds server-enforced convoy transitions with gate actor guards, convoy_events
logging, and six MCP tools (create, brief, transition, log, query, reconcile).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 14:51:19 -05:00
varutasu
2a9be5d4e1
feat(convoys): pipeline convoy scaffolding (Epic 2)
feat(convoys): pipeline convoy scaffolding (Epic 2)
2026-07-07 14:48:27 -05:00
Randall Stillwell
ce4e5b7c29 chore: merge main into feat/pipeline-convoy-scaffolding
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 14:48:16 -05:00
varutasu
0604d66008
feat(automation): connected repos (Epic 3)
feat(automation): connected repos (Epic 3)
2026-07-07 14:47:56 -05:00
Randall Stillwell
30c4e533e8 feat(automation): connected repos — paste remote URL and forge adapters (Epic 3)
Workspace admins connect git remotes via settings UI; forge type is inferred
from the URL, API tokens stay env-var references, and test connection fetches
default branch for orchestrator/worker consumers.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 14:45:40 -05:00
Randall Stillwell
76dacff58d feat(convoys): add pipeline convoy scaffolding (Epic 2)
Installs .convoys/README.md, log-convoy-event.sh, convoy-planning Cursor rule,
and gitignored metrics JSONL. Documents Echodo dogfood kickoff and adds a
shipped convoy record for Epic 1 model provider registry.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 14:17:18 -05:00
varutasu
2d309e8a75
feat(automation): model provider registry (Epic 1)
feat(automation): model provider registry (Epic 1)
2026-07-07 14:17:11 -05:00
Randall Stillwell
863d2d9d44 fix(web): stop exporting formatDuration from runs settings page
Next.js App Router rejects non-page exports from page modules; duration
formatting stays a local helper.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 14:11:04 -05:00
Randall Stillwell
a6898617b5 fix(shared): drop .js extensions in model-routing imports for Next.js
Webpack resolves workspace packages without Node ESM .js suffixes; extensionless
paths match the rest of packages/shared and fix middleware build failures.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 14:09:40 -05:00
Randall Stillwell
dfe73b3647 feat(automation): complete model provider registry epic (tasks 3–6)
Adds ai.models tRPC router with provider CRUD, role routes, testProvider, and
resolveForRole; Vercel AI SDK client factory in packages/ai; Settings pages
for providers and role routing; agent_runs model metadata columns with MCP
complete_task fields and runs UI column.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 14:07:47 -05:00
Randall Stillwell
f04122fd04 feat(database): add model_providers and role_model_routes tables
Adds workspace-scoped provider registry schema, relations, migration 0010,
and seedDefaultRoleRoutes() for pipeline defaults when aliases exist.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 14:00:48 -05:00
Randall Stillwell
fde698f439 chore(plans): mark shared-schemas-resolve-model task done
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 13:56:41 -05:00
Randall Stillwell
cda4958b17 feat(shared): add model routing schemas and resolveModel()
Implements Epic 1 task 1 per docs/adr-model-routing.md: zod schemas for
providers and role routes, pipeline default aliases, legacy Cursor slug map,
and a pure resolveModel() with brief → convoy → workspace → default order.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 13:56:36 -05:00
Randall Stillwell
e256380671 plan(automation): add mission-control foundation backlog and model-routing ADR
Documents the automation foundation plan (nine epics, Epic 1 taskified) and
the accepted model-provider registry contract. Updates .env.example for backlog
import workspace id and local/cloud AI provider env guidance.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 13:55:03 -05:00
varutasu
491d196384
fix(docker): reorder build stages so web-build comes after its --from= sources (#2)
Coolify's builder fails the build at parse time with:
  "cannot copy from stage 'collab-build', it needs to be defined before
   current stage 'web-build'"

The previous commit introduced forward COPY --from references that work
on newer BuildKit DAG builders but not on the legacy Docker builder
Coolify uses. Move `collab-build` and `mcp-build` above `web-build` in
lexical order so the references resolve. Functionally identical — the
DAG ordering effect is the same — just expressed in a way the older
builder accepts.

Added a NOTE comment above the stages so the next person who tries to
"clean up" the file order doesn't reintroduce the same regression.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-05 21:13:39 -05:00
varutasu
3fb79f6f04
Merge pull request #1 from stwl-labs/hotfix/docker-build-ordering
fix(docker): serialize build stages so next build doesn't OOM on the 8 GB host
2026-06-05 21:04:32 -05:00
Randall Stillwell
d4e4f9dbf0 fix(docker): serialize build stages so next build doesn't OOM on the 8 GB host
Coolify deploys were failing with exit 255 (kernel OOM, no Docker error)
around the 73s mark of `next build`. Root cause: docker/Dockerfile's three
build stages (web-build, collab-build, mcp-build) all `FROM deps`, and
BuildKit was running them in parallel. The web-build alone wants ~3 GB
heap (capped at 5120 MB) and was racing tsup workers + buildkit + dockerd
on an 8 GB host until the kernel reaped it.

docker-compose.coolify.yml already had a comment claiming `depends_on:
[collab, mcp]` on `web` would serialize the builds. It doesn't —
`depends_on` only orders runtime startup, not `docker compose build`.

Fix: enforce ordering inside the Dockerfile DAG by COPYing one trivial
artifact from each lighter stage into web-build. BuildKit now waits for
collab-build and mcp-build to finish before starting the heavy Next.js
compile, which then gets the host effectively to itself. The copied
files land in /tmp and are never read by the runtime web image.

Also updated the compose comment to reflect the new (and accurate)
ordering mechanism.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-05 21:02:39 -05:00
Randall Stillwell
011d3eb710 fix(workspaces): wire top-header create-workspace button + clarify echodo db naming
The Create Workspace button in the top-header dropdown was still calling
`window.alert("Create workspace (placeholder)")` instead of opening the
real CreateWorkspaceDialog. Wires it to the same dialog the sidebar
workspace switcher uses.

Also clarifies in .env.example and AGENTS.md that the canonical Postgres
database name is `echodo` everywhere (local, Coolify, drizzle ledger,
docker-compose POSTGRES_DB). A stale `tasks` database on CT 102 from the
pre-rename era was the root cause of the 2026-06 Authentik "Configuration"
SSO outage: Coolify correctly pointed at `echodo` (which was empty), while
the only initialized schema lived in the relic `tasks` DB.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-05 16:33:41 -05:00
Randall Stillwell
8b981723b6 chore(plans): mark export-db-to-markdown-frontmatter done
Written by the exporter itself during the dogfood run — final dogfood
evidence that the two-way sync loop closes correctly. See run
0bace0aa-ef6e-4aca-a041-e7f2343ba854 in agent_runs for the trail.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 10:56:34 -05:00
Randall Stillwell
56b697b81c feat(markdown-backlog): close the sync loop with DB → frontmatter export
Until now the markdown importer was one-way (plans/*.md → DB). Any
agent-driven status flip via claim_task / complete_task would be
clobbered on the next importer sweep. This change closes the loop: the
DB now projects status, priority, agent_prompt, and updated_at back
into the file's frontmatter, preserving body bytes, key order, and
every other frontmatter key.

New: packages/database/src/markdown-backlog/export.ts
  - `rewriteFrontmatter()` — pure function, covered by 10 Vitest cases
    (round-trip identity, status flip, priority flip, agent_prompt
    null/block-scalar/single-line variants, body preservation,
    trailing-newline preservation, idempotent re-application).
  - `exportBacklogItemToMarkdown()` — DB-loading wrapper with atomic
    write (tmp + rename) and tenant fencing. Returns a structured
    result so callers can surface what happened in their response.

Wired into:
  - `claim_task` MCP tool — exports on the ready → in_progress flip.
  - `complete_task` MCP tool — exports on any finalStatus transition.
  - `backlog.updateWorkflowPrompt` tRPC mutation — exports on prompt
    edits made through the app UI.

Robust repo-root resolution (`apps/{mcp-server,web}/src/lib/repo-root.ts`,
plus a copy in `import-markdown-backlog.ts`): walk up from the source
file looking for `pnpm-workspace.yaml`, falling back to env var or cwd.
This fixes a class of bug where `pnpm --filter <pkg>` cd's into the
package directory and breaks naive cwd-based path resolution — the
importer was deleting all 44 rows during smoke testing before this fix
because it found zero files in `packages/database/plans/`.

`config/CursorSync.md`: documents the new two-way contract, the
DB-wins-on-allow-list conflict policy, and the
MARKDOWN_BACKLOG_REPO_ROOT=off escape hatch for production deployments
where `plans/` isn't checked out.

Smoke verified end-to-end against the homelab DB: claim flips file
status to in_progress, complete flips it back to ready, importer
round-trips with stable content_hash (true no-op), agent identity
preserved throughout.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 10:21:22 -05:00
Randall Stillwell
fc2235a346 feat(agent-runs): capture client + model identity on claim/complete
Adds level-B agent attribution: every MCP tool call can identify itself
with a `client` (e.g. cursor-ide, codex, echodo-orchestrator) and `model`
(e.g. claude-4.6-sonnet) string. Both optional, both stored in
agent_runs.metadata as JSONB so the schema doesn't move.

- claim_task: new optional `client` + `model` args. Written into the
  inserted agent_runs row's metadata, and mirrored into the audit log
  entry. On idempotent re-claim, incoming values are merged into
  existing metadata (existing keys override only when explicit), so a
  mid-session model switch updates attribution without losing earlier
  context.
- complete_task: same optional args, with merge-on-close semantics —
  late-bound values override the earlier claim's values so the run row
  reflects whichever model actually closed the session. Audit row also
  carries the merged identity.
- /settings/runs UI: stack the client/model under the actor name in the
  table so attribution is visible at a glance without adding a column.

Smoke-tested: claim with {cursor-ide, claude-4.6-sonnet} then complete
with only model={claude-4.6-sonnet-medium-thinking} yields final
metadata {client: cursor-ide, model: claude-4.6-sonnet-medium-thinking}
on both the run row and the task.completed audit entry.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 10:11:35 -05:00
Randall Stillwell
e99aa733c9 chore(agent-coordination): wire Cursor MCP + one-shot importer for dogfooding
Connect Echodo to itself: Cursor sessions can now call this repo's MCP
server (`claim_task`, `complete_task`) over stdio, and operators can
bootstrap the DB from `plans/` without leaving a long-running file
watcher in place.

- `.cursor/mcp.json`: register `echodo` MCP server. Spawns
  `pnpm -s --filter @tasks/mcp-server mcp`. The `mcp` script invokes tsx
  with `--env-file=../../.env` so DATABASE_URL is picked up at the
  per-session process boundary without leaking into committed config.
- `import:markdown-backlog`: new one-shot importer (sibling of the
  existing watch script). Until the DB → markdown export side lands
  (see follow-up task), running the watcher continuously would clobber
  agent-driven status flips on every sweep. The one-shot variant runs a
  single `syncMarkdownBacklogScan` pass and exits.
- File `Task-export-db-to-markdown-frontmatter.md` documenting the
  remaining direction of the sync loop.

Smoke-tested end-to-end against the homelab DB: full `claim_task` →
`complete_task` round-trip via real MCP stdio protocol, with agent_runs
+ audit_log rows landing as expected and the backlog item status
restored via `finalStatus`.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 08:57:21 -05:00
Randall Stillwell
b2aff2045b feat(mcp): claim_task tool + register claim/complete pair
Pairs with the parallel complete_task commit. claim_task opens an
agent_runs row, flips status to in_progress only when it's safe
(ready/draft → in_progress, never overwriting a deliberate
blocked/done/in_progress), and returns the resolved workflow prompt
+ source level. Idempotent re-claim by the same actor returns the
existing run with reused=true and refreshes notes only — started_at
is sacred. Different-actor re-claim errors with ALREADY_CLAIMED
naming the existing actor and run id.

Tenancy fence: if the backlog item exists but in a different workspace
than the resolved handle, we refuse with "doesn't belong to workspace"
rather than 404. Prevents cross-tenant existence fishing.

All three writes (run insert + status flip + audit insert) happen in
one db.transaction() so a partial claim is unreachable.

tools/index.ts now registers both claim_task and complete_task.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 22:23:05 -05:00
Randall Stillwell
93b6398c76 feat(mcp): complete_task tool — close agent_runs row + finalize status
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 22:21:26 -05:00
Randall Stillwell
72aa2a5f0c feat(backlog): workflow_prompt with task → epic → plan inheritance
Adds the data layer for per-item agent prompts. Markdown frontmatter
gets an `agent_prompt:` block scalar that survives the importer
round-trip (newlines preserved), and `resolveWorkflowPrompt()` walks
task → epic → plan → built-in default returning both the resolved
string and the source level. Walk is slug-based, not parent_id-based,
because the importer leaves parent_id briefly null mid-transaction.

tRPC `backlog.getWorkflowPrompt` returns ownOverride + effectivePrompt
so future UI can render the override box + preview without two
queries. `backlog.updateWorkflowPrompt` is owner/admin-gated (prompts
change downstream Cursor/Claude behavior) and audit-logged on every
write.

UI deferred — apps/web doesn't have a backlog-item detail panel yet;
the existing object-detail panel is for the objects table. Follow-up
filed at Task-workflow-prompt-task-detail-ui.md.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 22:18:18 -05:00
Randall Stillwell
f014686412 feat(runs): agent_runs table + tRPC router + settings UI
Read-side only — write paths land with claim_task / complete_task
in the next epic. Keyset pagination on started_at, three procedures
(listRecent, listForTask, summary), and a /settings/runs view that
mirrors the audit page's visual language.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 22:16:04 -05:00
Randall Stillwell
93565cd94c ops(db): reconcile CT 102 drift — stamp ledger, add missing 0002 tables
The `tasks` Postgres on CT 102 was bootstrapped years ago with
`drizzle-kit push`, which writes schema but skips the ledger. As of
today the ledger contained zero rows and the schema was missing
`markdown_backlog_items` + `cursor_sync_mappings` (migration 0002
ran on neither code path). Migration 0007's ALTER on
markdown_backlog_items had silently failed because of this; audit_log
was added manually.

The one-shot at docs/operations/2026-06-02-db-drift-reconcile.sql
created the two missing tables at the final post-0007 shape (skipping
0002's now-obsolete FK-to-objects intermediate state, which 0003
would have immediately rewritten anyway) and stamped all 8 migrations
with their sha256 + journal `when` so drizzle's
`lastDbMigration.created_at < migration.folderMillis` gate treats
them as already applied.

`pnpm db:migrate` is now a clean no-op against this DB. Future
migrations work normally.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 16:17:42 -05:00