Skip to content

Add codemod-campaign loop (cross-PR migration campaign)#12

Merged
DCCA merged 1 commit into
mainfrom
claude/openspec-skills-import-4xj0qo
Jun 23, 2026
Merged

Add codemod-campaign loop (cross-PR migration campaign)#12
DCCA merged 1 commit into
mainfrom
claude/openspec-skills-import-4xj0qo

Conversation

@DCCA

@DCCA DCCA commented Jun 23, 2026

Copy link
Copy Markdown
Owner

Summary

Ships the flagship complex loop — rank #1 from research deep-dive #3 — the codemod-campaign: a staged, throttled, ledger-tracked codemod campaign across the codebase, built on loopy's long-horizon primitives (durable StateStore + human Gate).

advanceCampaign(...) (called repeatedly, e.g. on a schedule) advances at most one batch per run:

  • ledger in StateStore tracks migrated files, open batches, counts, pilot approval;
  • reconciles against real PR state each run (merged → migrated, closed → files back to the pool);
  • throttles at maxOpenPrs; pilot batch is human-gated (no PRs until approved);
  • a failed batch (red tests) opens no PR; completes when nothing remains and no batches are open.

Idempotent and resumable. Injected boundaries (codemod, targets, test runner, prs) make it fully unit-tested with fakes + a memory store.

OpenSpec

Shipped via proposal → apply → archive; source of truth: openspec/specs/codemod-campaign.md.

Validation

  • typecheck / lint — clean
  • npm test166 tests (+5: full lifecycle — pilot gate → batches → throttle → reconcile/merge → completion → failure)
  • npm run build — clean

Programmatic for now (like the experiment orchestrator); a GitHub-backed CampaignPrs adapter and a loopy campaign CLI verb are noted follow-ups. Next from the ranking: prompt-eval-gate, model-upgrade-migration.

🤖 Generated with Claude Code

https://claude.ai/code/session_012CrMioorha3QtPUgWbtDbR


Generated by Claude Code

The flagship complex loop (rank #1 from research deep-dive #3): a staged,
throttled, ledger-tracked codemod campaign on the long-horizon primitives.

- loops/codemod-campaign/: advanceCampaign() drives a deterministic codemod
  across the codebase in batches of PRs. The campaign ledger lives in the
  durable StateStore; the pilot batch is human-gated; open PRs are throttled
  by maxOpenPrs; each run reconciles the ledger against real PR state
  (merged -> migrated, closed -> returned to pool) and advances at most one
  batch. Idempotent and resumable.
- Injected boundaries: codemod, targets, test runner, and a CampaignPrs
  (open + state) client, so it's fully unit-tested with fakes + a memory store.

Shipped via the OpenSpec cycle (openspec/specs/codemod-campaign.md).
Validated: typecheck, lint, 166 tests (+5), clean build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012CrMioorha3QtPUgWbtDbR

@DCCA DCCA left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review

CI green (build ~23s); locally typecheck, lint, 166 tests, build all pass.

Strengths

  • Best showcase of the long-horizon primitives together. The campaign ledger lives in the durable StateStore, the pilot batch is a real Gate, and advanceCampaign is idempotent + resumable — exactly the cross-PR campaign pattern the deep dive ranked #1.
  • Correct staged-rollout invariants, each covered by a test: no PR until the pilot is approved (gate); throttle at maxOpenPrs; reconcile against real PR state every run (merged → migrated, closed → files back to the pool); files migrate only on merge; a red batch opens no PR and is recorded; completion only when nothing remains and no batches are open. This directly answers the anti-patterns from the research (runaway, stale state, partial-rollout corruption, gate bypass).
  • Pure helpers (remainingTargets/selectBatch/reconcile/renderBurndown) are separately unit-tested; the whole engine is fakeable (codemod/targets/runner/prs + memory store) with no real network.

Notes (non-blocking, scoped)

  • Programmatic for now — CampaignPrs is injected; a GitHub-backed adapter (open + state) and a loopy campaign CLI verb are the noted follow-ups (consistent with the experiment orchestrator).
  • targets() returns files still matching the predicate, so campaignTotal is derived (migrated + in-flight + remaining); fine for burndown.

Recommend merge.


Generated by Claude Code

@DCCA
DCCA merged commit f835589 into main Jun 23, 2026
1 check passed
DCCA pushed a commit that referenced this pull request Jun 23, 2026
Adds loops/codemod-campaign/: advanceCampaign() drives a deterministic codemod across the codebase in throttled batches of PRs, tracked in a durable StateStore ledger, reconciled against real PR state each run (merged→migrated, closed→pool), with a human-gated pilot batch; idempotent + resumable, advancing one batch per run. Injected boundaries (codemod, targets, runner, prs) — fully unit-tested with fakes. The flagship complex loop (rank #1). Shipped via the OpenSpec cycle. Validated: typecheck, lint, 166 tests, clean build; CI green.
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.

2 participants