Both Agents Dream — Implementation Plan

Build plan for the spec. AutoDream 4-phase consolidation + a Karpathy wiki for the advisor and the market agent, grounded in Flue + Cloudflare. · 2026-06-26

For agentic workers: execute task-by-task with superpowers:subagent-driven-development — fresh subagent per task, review between. Steps are ☐ checkboxes. Every code step shows real code; every test step shows the command + expected result. Pin model opus on every implementer and reviewer (per Pete's standing rule). The plan covers all six spec phases (A–F) in one document; ship and review phase by phase.

Goal: Give both HomeZero agents a nightly four-phase dream that maintains a private, backlinked wiki of what each is learning — the advisor about a buyer's search, the market about a place fed by many signal-gated sources — with everything public rendered as a projection of a wiki page.

Architecture: Extract the generic memory machinery into a shared src/brain/ module both agents import (separate tables in separate DOs — shared code, never shared data). Each agent's wiki lives in its DO's native SQLite files table, reached via Flue's SandboxApi (native read/write/edit/grep). The dream reads the day from Flue's durable event stream (readEvents) and rewrites pages + reweights yearnings. The market additionally ingests in two tiers — broad cheap stubs vs deep per-property enrichment gated on attention.

Tech stack: Flue beta.5 (@flue/runtime)Cloudflare Durable Objects + DO SQLitevalibotvitest + node:sqliteConvex (projections)

Global Constraints

Every task's requirements implicitly include these. Exact values, copied from the spec + repo.

Sessions are read via Flue's durable event stream — EventStreamStore.readEvents(path, {offset, limit}), path agents/<type>/<id>. NEVER read the internal flue_session_entries table (the drift that bricked v6 DOs).
Memory is the native filesystem — the DO's files table via the SandboxApi (native read/write/edit/grep/glob). No external store. The wiki = wiki/index.md + wiki/<slug>.md pages.
Native SQL handle is Sql (src/sqlh.ts): synchronous sql.exec(query, ...binds).toArray(), VARIADIC binds. Tests inject fakeSqlStorage() (test/helpers/fakeSqlStorage.ts, node:sqlite).
Shared code, separate dreams. src/brain/ holds only generic mechanism; each agent keeps its own seeds + body prose. No agent ever reads another's tables.
Deep ingest is signal-gated. Tier-2 (county/Maps/water/property-news) fires ONLY for a home with attention (zeroed; extend to view/save). Never deep-ingest the whole market. A per-pass budget caps Tier-2 calls.
Convex projection shapes are unchanged. listings.verdict/valueFactors/deepDive, boardCards, market_reports, learningPanels.read. The wiki is additive; publishers render from it.
Tests + deploy. Run npx vitest run in flue/ (single file: npx vitest run test/<path>); the suite is green today (233/233) — keep it green. Deploy: npx flue build --target cloudflare → npx wrangler deploy -c dist/homezero_flue/wrangler.json.
Copy + data rules. Brand "HomeZero" (one word). Real data only on public surfaces; no individual people's names. The www app is a modified Next.js — out of scope here (all work is in flue/, a Worker).
Phases
  1. A · Shared src/brain/ + index→pages + session-read + validate advisor dream (Tasks 1–9)
  2. B · The advisor's search wiki (Tasks 10–11)
  3. C · Market brain + yearnings + skills + journaling (Tasks 12–15)
  4. D · The market place wiki — two-tier ingest + day-one connectors (Tasks 16–21)
  5. E · The dream beats — 4-phase + lint + hygiene (Tasks 22–25)
  6. F · End-to-end validation (Tasks 26–27)
Phase A · Shared brain, index→pages, session-read, validate advisor dream

Extract the generic memory machinery out of src/advisor/ into src/brain/ with zero advisor behavior change (pure refactor, tests stay green), then add the new wiki + session-read primitives, migrate the advisor to index→pages, and validate its dream runs live.

Task 1 · Extract src/brain/files.ts (files-table helpers)

Create src/brain/files.ts
Modify src/advisor/brainStore.ts (re-export from new module)
Test test/brain/files.test.ts
Produces: writeFileRow/readFileRow/listFilePaths/deleteFileRow/fileExists/searchFiles/saveFiles/loadFiles(sql, …) — identical signatures to today's brainStore.ts versions.

Task 2 · Extract src/brain/yearnings.ts (generic yearning CRUD)

Create src/brain/yearnings.ts
Modify src/advisor/brainStore.ts (re-export; keep advisor-specific UNIVERSAL_CORE_YEARNINGS + seedYearnings)
Test test/brain/yearnings.test.ts
Produces: Yearning, UpsertYearning, upsertYearning, listYearnings, reweightYearning, and new generic seedCoreYearnings(sql, core: ReadonlyArray<{key;prompt}>, now?). Consumes: nothing new.

Task 3 · Extract src/brain/schema.ts (ensureBrainSchema)

Create src/brain/schema.ts
Modify src/advisor/brainStore.ts, src/agents/advisor.ts (import path only)
Produces: ensureBrainSchema(sql) creating files, yearnings, skill_metrics, skill_params, sessions (verbatim DDL from brainStore.ts:49–90).

Task 4 · Extract src/brain/sandbox.ts (makeBrainSandboxApi) + brainTools.ts

Create src/brain/sandbox.ts, src/brain/brainTools.ts
Modify src/advisor/advisorFs.ts, src/advisor/tools.ts (delegate)
Test test/brain/sandbox.test.ts
Produces: makeBrainSandboxApi(sql): SandboxApi (today's makeAdvisorSandboxApi body, verbatim — it's already generic); makeBrainTools(getClient, agentId): ToolDefinition[] returning [brain_read, brain_write] from tools.ts:277–342. (T8 widens this to makeBrainTools(getClient, agentType, agentId) and adds recall_session; this task lands the 2-arg form and updates the advisor call site, T8 migrates both.)

Task 5 · New src/brain/wiki.ts — wiki primitives over the files table

Create src/brain/wiki.ts
Test test/brain/wiki.test.ts
Consumes: writeFileRow/readFileRow/listFilePaths (Task 1). Produces: writeWikiPage(sql, {slug,title,body,links}), readWikiPage(sql, slug), listWikiSlugs(sql), addBacklink(sql, slug, linkTo), rebuildIndex(sql): Promise<string>; consts WIKI_PREFIX='wiki', WIKI_INDEX='wiki/index.md'.

Task 6 · New src/brain/session.ts — read the durable event stream

Create src/brain/session.ts
Test test/brain/session.test.ts
Produces: sessionStreamPath(agentType, id): string = `agents/${agentType}/${id}`; readSessionEvents(sql, agentType, id, opts?): Promise<unknown[]> via Flue's EventStreamStore.readEvents.
Verification step first (multi-component grounding): confirm the exact constructor/export for the SQLite event-stream store and that reading agents/<type>/<id> over the DO's own ctx.storage.sql returns the recorded conversation. The d.mts shows SqliteEventStreamStore(sql) with readEvents(path,{offset,limit}) → {events?,nextOffset,closed}; verify it's reachable from @flue/runtime (or its subpath) and pin the import before coding against it. The public signature below is fixed; only the construction line is finalized at this step.

Task 7 · New src/brain/contract.ts — the 4-phase DREAM prose

Create src/brain/contract.ts
Test test/brain/contract.test.ts
Produces: DREAM_CONTRACT: string — the shared four-phase instruction (orient · gather signal via the session stream · consolidate the wiki + reconcile yearnings · prune&index = lint). Each agent's prompt embeds it, then appends body-specific lines.

Task 8 · Advisor adopts index→pages + the 4-phase dream

Modify src/advisor/prompts.ts (DREAM PASS → embed DREAM_CONTRACT), src/advisor/skills/memory/SKILL.md (index→pages discipline)
Modify src/agents/advisor.ts (add recall_session tool wired to readSessionEvents)
Test test/advisor/dream.test.ts (still green), test/agent.test.ts (tool list += recall_session)
Consumes: DREAM_CONTRACT (T7), readSessionEvents (T6), rebuildIndex/writeWikiPage (T5). Produces: advisor dream that reads the session stream, rewrites wiki/ pages + wiki/index.md, reconciles yearnings, writes project_read.

Task 9 · Validate the advisor dream live

Ops trigger on a live advisor; no code change unless the run reveals a gap
Consumes: the deployed worker. Produces: evidence the 6→4-phase dream executes end-to-end (the gap the spec flags: only the dispatch is tested today).
Phase B · The advisor's search wiki

Task 10 · Working beats ingest wiki pages

Modify src/advisor/prompts.ts (TEND/SCOUT/ZERO-WAKE passes)
Modify src/advisor/skills/memory/SKILL.md
Consumes: wiki primitives (T5) via the native edit tool. Produces: tend/scout/react author or update wiki/<area|theme|home>.md pages with backlinks, instead of appending to a single journal.

Task 11 · Projections render from wiki pages

Modify src/advisor/prompts.ts (author_home_card + project_read guidance)
Consumes: wiki pages. Produces: the card body and project_read summary are drawn from the home's wiki page + the index — same Convex shapes (board:authorHomeCard, board:setRead), now grounded in the wiki.
Phase C · Market brain + yearnings + skills + journaling

Task 12 · Market DO gains the brain tables

Modify src/agents/market.ts (onStart → ensureBrainSchema(this.ctx.storage.sql))
Test test/market/brain-schema.test.ts
Consumes: ensureBrainSchema (T3). Produces: the market DO's SQLite now also has files + yearnings (alongside listings/parcels/...), co-resident in one DO.

Task 13 · Market core yearnings, seeded at provisioning

Create src/market/yearnings.ts (MARKET_CORE_YEARNINGS)
Modify src/agents/market.ts (seed in onStart, idempotent)
Test test/market/yearnings.test.ts
Consumes: seedCoreYearnings (T2). Produces: the 6 place-yearnings (price-drivers, moving-areas, seasonality, honest-vs-over, supply-trajectory, whats-changing) at confidence 0.2, idempotent across boots.

Task 14 · Market agent gets the sandbox, brain tools, and skills

Create src/market/marketFs.ts (thin wrapper over makeBrainSandboxApi)
Modify src/agents/market.ts (add sandbox, makeBrainTools, skills)
Create src/market/skills/memory/SKILL.md, src/market/skills/brain/SKILL.md
Test test/market/agent-shape.test.ts
Consumes: makeBrainSandboxApi (T4), makeBrainTools (T4), wiki tools. Produces: the market agent now has the native file tools over its files table, brain_read/brain_write/recall_session, and memory+brain skills.

Task 15 · Working beats drop a wiki/journal line

Modify src/market/prompts.ts (sweep/drain/metrics each end by noting what they saw)
Produces: something for the dream to consolidate — each working pass appends a dated, slug-tagged note (to a wiki/log.md or the relevant page) of what changed.
Phase D · Market place wiki — two-tier ingest + day-one connectors

Task 16 · The connector seam — ingestSource(kind, tier, payload)

Create src/market/ingest/source.ts (registry + dispatcher)
Test test/market/ingest-source.test.ts
Produces: type Tier = 1 | 2; interface Connector { kind: string; tier: Tier; fetch(ref): Promise<Record<string,unknown>>; weave(sql, slug, data): Promise<void> }; registerConnector(c); ingestSource(sql, kind, ref): Promise<void> (looks up the connector, fetches, weaves into the wiki page ref.slug).

Task 17 · Tier 1 — sweep stubs a wiki page per listing

Modify src/market/prompts.ts (sweep), src/market/tools.ts (a stub_wiki helper or extend store_listings)
Test test/market/tier1-stub.test.ts
Consumes: writeWikiPage (T5). Produces: after a sweep, every for-sale listing has a thin wiki/<slug>.md stub (raw Zillow facts, not yet woven) — cheap, broad.

Task 18 · Tier 2 — signal-gated deep ingest on drain

Create src/market/ingest/deep.ts (deepIngest(sql, zpid, opts))
Modify src/market/prompts.ts (drain), src/market/tools.ts (a deep_ingest tool the drain calls)
Test test/market/tier2-gate.test.ts
Consumes: ingestSource (T16), the day-one connectors (T19–21). Produces: deepIngest runs the Tier-2 connectors for ONE property and weaves its page; a per-pass budget caps calls. The gate: only invoked for a zeroed listing (drain), never broadly.

Task 19 · Day-one connector — county records (EagleWeb)

Create src/market/ingest/connectors/county.ts
Test test/market/connectors/county.test.ts
Produces: a Tier-2 Connector (kind:'county') whose fetch({zpid,slug}) resolves the parcel + pulls sale history/assessed/zoning (direct Worker fetch to Delta EagleWeb), weave appends a "County record" section + backlinks comparable sales.
Live endpoint pinned at impl: the connector contract is complete; the EagleWeb base URL + response parse is confirmed against the live source during this task (a const ENDPOINT + a parse fn), reusing the egress path proven for parcels. The test mocks fetch — no network in CI.

Task 20 · Day-one connectors — Google Maps + Colorado water (CDSS)

Create src/market/ingest/connectors/maps.ts, .../water.ts
Test test/market/connectors/maps.test.ts, .../water.test.ts
Produces: two Tier-2 connectors. maps (kind:'maps'): drive-times + nearby (Places API, MAPS secret) → page "Proximity" section. water (kind:'water'): CDSS REST decree/priority/irrigation → page "Water rights" section + reweight owned-water-relevant notes.

Task 21 · Day-one connectors — local news + civic minutes

Create src/market/ingest/connectors/news.ts (Tier-1 market-wide + Tier-2 property mentions), .../civic.ts (Tier-1)
Test test/market/connectors/news.test.ts, .../civic.test.ts
Produces: news ingests local-paper items into a market-wide wiki/news.md theme page (Tier 1) and links property/street mentions onto listing pages (Tier 2); civic ingests council/county agenda items into wiki/whats-changing.md.
Phase E · The dream beats — 4-phase + lint + hygiene

Task 22 · Market dream() beat + schedule

Modify src/agents/market.ts (onStart schedule + dream() method)
Test test/market/dream-beat.test.ts
Consumes: the dispatch pattern (mirror advisor.dream()). Produces: dream() → dispatch({agent:'market', id, input:{kind:'dream'}}); onStart schedules 0 12 * * * under the arm-once guard.

Task 23 · Hygiene SQL — prune stale + resolved-pending

Create src/market/hygiene.ts (pruneStaleListings, clearResolvedPending)
Test test/market/hygiene.test.ts
Produces: pruneStaleListings(sql, now): Promise<number> deletes homeStatus != 'FOR_SALE' AND last_seen_at < now-30d; clearResolvedPending(sql): Promise<number> deletes pending_resolution rows with a matching parcel_listings link. Both return the deleted count.

Task 24 · Market DREAM PASS prompt (4-phase + lint + hygiene)

Modify src/market/prompts.ts (add a kind:"dream" block embedding DREAM_CONTRACT)
Modify src/market/tools.ts (expose a prune_brain tool wrapping T23)
Test test/market/agent-shape.test.ts (instructions contain "dream")
Consumes: DREAM_CONTRACT (T7), hygiene (T23). Produces: the market dream — orient/gather (read the session stream)/consolidate the place wiki + reconcile place-yearnings/prune&index, then call prune_brain (the hygiene) and sign with a tally line.

Task 25 · Confirm advisor/market dream parity

Test test/brain/contract.test.ts (both prompts embed DREAM_CONTRACT)
Produces: a guard test asserting both ADVISOR_INSTRUCTIONS and MARKET_INSTRUCTIONS contain DREAM_CONTRACT — so the shared four phases can't silently drift apart.
Phase F · End-to-end validation

Task 26 · Deploy + market dream E2E

Ops deploy; trigger; inspect via DO read stub

Task 27 · Both-agents validation checklist (spec §10)

Self-review (run before execution)

CheckResult
Spec coverage§2 memory→Tasks 1–8; §4 four phases→T7,8,24; §5 two wikis→T8,10,13,17; §6 ingest+gate→T16–21; §7 reconcile/projections→T11,17,18; §8 shared module→T1–5; §9 build phases→all; §10 validation→T26,27. No uncovered section.
Type consistencySql, SandboxApi, Connector/Tier, WikiPage, seedCoreYearnings, readSessionEvents, deepIngest used identically across tasks. makeBrainTools(getClient, agentType, agentId) arity fixed at T8 and reused at T14.
Known-at-impl flaggedT6 (event-stream construction) and the connector endpoints (T19–21) are the only externally-verified bits — each carries a verification step + an offline mocked-fetch test. No logic placeholders.

Implementation plan · 2026-06-26 · pairs with the spec. Grounded in: flue/src/advisor/{brainStore,tools,advisorFs,prompts}.ts, flue/src/market/{store,tools,prompts,publish,ingest,stub}.ts, flue/src/agents/{advisor,market}.ts, convex/{listings,board,validators}.ts, @flue/runtime event-stream + sandbox APIs, and the test/ patterns (agent.test.ts, advisor/dream.test.ts, staff/marketTools.test.ts). Execute with subagent-driven-development, model opus.