An ENR feasibility evaluation — where the Workflow harness helps, where it fights the pipeline's constraints, and what to build instead.
No to refactoring the per-word generation pipeline (Pass 0–3, enrich.ts, the daemon) into a Workflow. It fights every load-bearing constraint the pipeline was built around.
Yes to a net-new Workflow-driven QA / hallucination-audit layer that runs after enrichment. That is where reasoning fan-out earns its keep — and building it also fixes the known-broken promotion gate that is blocking enriched → production today.
Don't rewrite the engine. Bolt the Workflow onto the part that actually needs reasoning fan-out.
enriched → production promotion right now.jadi=Capricorn, ini=rice, bangun=wergeld — all Kaikki-only, zero living usage) are the textbook target for a fan-out of independent verifiers. One-off corpus job.The Workflow harness is a deterministic JS script whose agent() primitive spawns Claude subagents (Opus / Sonnet / Haiku) with tools. Its headline powers: parallel() / pipeline() for concurrent subagents, real control flow (loops, conditionals, budget loops), and per-run resume via a journal.
Two facts that drive every collision below:
agent() spawns Claude, not a generic LLM. To drive Gemini from inside a Workflow, an agent would have to shell out to existing code — adding a Claude reasoning layer (cost + nondeterminism) around what is already a deterministic shell command.GEMINI_RATE_LIMIT_MS / SEA_LION_RATE_LIMIT_MS — a global rate-gap timer enforced between every LLM call. The cohort runner is a for loop with execSync per word and sleep(7000) between words. Promise.all appears only for DB grounding reads (enrich.ts:1248), never for LLM calls.
claude CLI subprocess only in two narrow conditional spots: Pass 1.2 conflict arbiter and Pass 3 low-aid retry. Claude is the exception, not the engine.
t_enrich_queue — atomic claim (FOR UPDATE SKIP LOCKED), attempt budgets, heartbeat, stale-row recovery, and two-stage version stamping (v3.6-transient → v3.6) for crash-resume. A Workflow would have to re-implement all of this — net new surface area replacing something that already works.
feedback_api_rate_limits: never run parallel Gemini workers — hit the spending cap 2026-04-01. The limit is per-API-account, not per-process. Fanning out 16 subagents each calling gemini-2.5-flash = 16× the request rate against one bucket = instant spend-cap hit. The pipeline's serial rate-gap timer is exactly the mechanism a fan-out would remove.agent() spawns Claude, not GeminiBash('npx tsx enrich.ts …') — a thin shell around the daemon's job with added Claude cost and nondeterminism. Strictly worse than execSync.agent() → enrich.ts over a cohort is structurally shell loops over enrich scripts — banned by feedback_use_queue_not_loops. And routing Claude reasoning into the generation path makes enrichment Claude-dependent, which deserves an explicit channel-decision record against feedback_anthropic_sdk_requires_frank_approval.pipeline() over a word-list with per-item failure isolation and a budget-stop is a cleaner expression than the current execSync + sleep loop. But every Gemini-bound stage must run at concurrency 1 — the fan-out benefit evaporates — and the daemon provides cross-session durability (atomic claim, heartbeat, stale-row recovery) that the Workflow lacks. A throwaway Workflow for a one-off bounded cohort where durability doesn't matter is defensible but low value.pedagogy-review.ts is broken today — it reads tables that no longer exist (dropped t080/t090) and writes to a dropped table (t075_sense_qa) — so no word can be programmatically promoted enriched → production. Reviewing an enriched sense for quality and hallucinations is reasoning + judgment = Claude-shaped. Naturally parallel across senses (each is independent). Runs on the Claude rate bucket — separate from Gemini generation, so fan-out is safe and cheap. Workflow adversarial-verify and completeness-critic patterns are the right shape: fan out N skeptic reviewers per sense, flag hallucinations, gate promotion. Three wins in one build: (1) uses the Workflow where it is strong, (2) fixes a known-broken piece, (3) unblocks the production promotion path.jadi=Capricorn, ini=rice, bangun=wergeld — all Kaikki-only, zero living usage) are the textbook target for a fan-out of independent web-checking verifiers. This is a one-off corpus batch, not a recurring generation step — fold it into the same Workflow harness as Option B./doc plan for the QA-as-Workflow layer — not a rewrite of enrich.ts.@anthropic-ai/sdk in pipeline code, so feedback_anthropic_sdk_requires_frank_approval is not strictly triggered. But making enrichment QA Claude-dependent is a channel decision worth recording explicitly in the plan frontmatter.enrich.ts:809–813 (rateGapMs), run-enrich-cohort.ts:143–204 (for-loop + sleep(7000) + failure isolation), enrich.ts:1248 (Promise.all only for DB grounding reads, never LLM calls).feedback_api_rate_limits + SessionStart hook. Incident not re-verified against billing logs this session.agent() spawns Claude subagents (not arbitrary LLMs); concurrency cap ≈ min(16, cores−2)validity_score population not queried this session./doc plan for the QA-as-Workflow layert_enrich_queue are not touched by this work@anthropic-ai/sdk in pipeline code, so the hard gate does not trigger. But this is a meaningful change in the enrichment stack's dependency profile — the plan frontmatter should capture it explicitly so it's auditable.
jadi=Capricorn, ini=rice, bangun=wergeld are all Kaikki-only with zero living usage — the classic Kaikki over-inclusion pattern. PLAN-139 scoped the fix. If the QA layer is green-lit, this one-off batch folds in cleanly as a second pass in the same Workflow.