feat(fleet): native Mosaic backlog on @mosaicstack/db (atomic claim + TTL)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful

Add Mosaic's own backlog-of-record on the existing Postgres storage layer,
replacing the former Hermes adapter (no Hermes dependency) and the earlier
sqlite idea (no sqlite, no new client).

- packages/db: `backlog` table (drizzle) + enum + migration 0011; BacklogService
  taking a Db handle so it runs on both createDb (server PG) and createPgliteDb
  (embedded). Atomic claim via SELECT ... FOR UPDATE SKIP LOCKED inside one tx,
  TTL claims + reclaim of expired, deps DAG gate, idempotency-key dedup, stats.
- packages/mosaic: `mosaic fleet backlog <sub> --json` (create/list/claim/
  reclaim/link/stats/block/complete). Embedded PGlite default at
  <mosaicHome>/fleet/backlog; full Postgres via DATABASE_URL — same code.
  Migrations run on first use.
- install.sh: preserve fleet/backlog across `mosaic update`.
- docs/fleet/backlog-conventions.md: schema, phase convention, atomic-claim +
  TTL semantics, PGlite-default/Postgres-by-config, Mosaic-native (no Hermes).
- Tests (in-memory PGlite, real PG semantics): create/list, exactly-one-winner
  concurrency (and N-card no-double-claim), deps gate, reclaim of expired, stats.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Jarvis
2026-06-24 09:27:33 -05:00
parent eb795bab18
commit 791d6b7c51
14 changed files with 4809 additions and 5 deletions

View File

@@ -0,0 +1,22 @@
CREATE TYPE "public"."backlog_status" AS ENUM('ready', 'claimed', 'blocked', 'done');--> statement-breakpoint
CREATE TABLE "backlog" (
"id" text PRIMARY KEY NOT NULL,
"title" text NOT NULL,
"body" text,
"phase" text,
"priority" integer DEFAULT 0 NOT NULL,
"status" "backlog_status" DEFAULT 'ready' NOT NULL,
"depends_on" jsonb DEFAULT '[]'::jsonb NOT NULL,
"claim_owner" text,
"claim_ttl_seconds" integer,
"claimed_at" timestamp with time zone,
"attempts" integer DEFAULT 0 NOT NULL,
"idempotency_key" text,
"acceptance" jsonb,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE INDEX "backlog_status_priority_idx" ON "backlog" USING btree ("status","priority");--> statement-breakpoint
CREATE INDEX "backlog_status_claimed_at_idx" ON "backlog" USING btree ("status","claimed_at");--> statement-breakpoint
CREATE UNIQUE INDEX "backlog_idempotency_key_idx" ON "backlog" USING btree ("idempotency_key");

File diff suppressed because it is too large Load Diff

View File

@@ -78,6 +78,13 @@
"when": 1745366400000,
"tag": "0010_federation_enrollment_tokens",
"breakpoints": true
},
{
"idx": 11,
"version": "7",
"when": 1782310438919,
"tag": "0011_bitter_gateway",
"breakpoints": true
}
]
}
}