Skip to content

docs(plans): portable-core refactoring & rewrite plan (P0–P7) - #12

Open
DanielSoCra wants to merge 1 commit into
mainfrom
docs/portable-core-refactor-plan
Open

docs(plans): portable-core refactoring & rewrite plan (P0–P7)#12
DanielSoCra wants to merge 1 commit into
mainfrom
docs/portable-core-refactor-plan

Conversation

@DanielSoCra

Copy link
Copy Markdown
Owner

What this is

The complete end-to-end plan for re-layering Runforge from a hosted control plane into a portable governed core + optional infra shell — inspired by the comparison with disler/super-simple-software-factory (same philosophy: code owns the loop, agents are bounded phases; SSSF proves the portable/stampable form factor, Runforge proves governance).

Docs-only PR. One file: docs/plans/portable-core-refactor-plan.md. No code, no behavior change — this is the plan for the refactor, not the refactor.

The plan in one paragraph

8 phases (P0–P7), ~30 PRs: guardrails & golden-run characterization first (P0) → extract the governance brain into packages/core as pure moves (P1) → formalize ports with contract suites (P2) → build portable adapters: SQLite stores via PGlite + file decision inbox (P3) → lift processWorkRequest out of the daemon.ts closure into executeRun() with a real portable CLI (P4, the pivotal extraction) → package the core as a stampable skill (P5) → slim the daemon to a ≤400-line composition root + extract concierge/briefing-summarizer as a separate product (P6) → deprecation, public-release readiness, L1/L2 ratification of the layering invariant (P7).

End state litmus test: runforge run --issue 123 executes the full governed pipeline on a clean checkout with zero Postgres, zero daemon — and deployment #0 runs the same code with Postgres adapters.

Grounding (not assumptions)

The plan is based on direct source inspection of main:

  • control-plane/daemon.ts read in full — processWorkRequest trapped in the composition-root closure is the extraction target; implicit ports (ConfigReader, RunWriter, TrunkReader, PromotionPort) already exist.
  • Full package-level API inventory (Appendix A in the doc). Three findings that de-risk the program:
    1. The daemon has zero direct Postgres imports — storage swap is contained to three packages.
    2. PGlite is already in three packages' devDeps running gate tests — the portable-storage spike is mostly done.
    3. decision-index already ships port contracts with fakes (Notifier/SourceSink/ResumeDispatcher) — P2 formalizes proven seams rather than inventing them.

Non-negotiables encoded in the plan

  • No behavior change until the seam is proven (golden-run characterization gates every phase).
  • Every decision function gains a purity gate (extends the decideMerge-stays-pure pattern).
  • Deployment #0 keeps running off main at all times; the old run spine stays behind a flag until P7.
  • The refactor itself should run through Runforge lanes — it's the largest validation of the system it produces.

Review focus

  1. P6 PR 27 product gate: extract concierge + briefing-summarizer to a separate repo (recommended) vs. keep as infra-shell opt-ins — needs an Operator decision.
  2. Phase sequencing: P2 overlaps P1's tail, P4 is pivotal — sanity-check the dependency order.
  3. The §2 target tree: package names/boundaries (core, adapters-sqlite, adapters-github, adapters-postgres) before P1 starts moving files.

End-to-end plan to re-layer Runforge into a portable governed core
(packages/core: lanes, merge-decision, earn-in, budgets, FSM, agents,
worktrees), ports/adapters (SQLite + file decision inbox as the
portable impls, Postgres/GitHub as infra impls), and a thin daemon
composition root — with the core shippable as a stampable skill.

Grounded in direct source inspection: daemon.ts composition root,
session-runtime adapters, and a full package-level API inventory
(Appendix A). 8 phases, ~30 PRs, golden-run characterization first,
no behavior change until seams are proven.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant