Sprint 11: config-as-code — portable campaign definitions, export/import, and the promocean CLI - #28
Merged
Merged
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s lifecycles and seed backfill
…ync verification script Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…sort
sortBySlug's compare called slug.localeCompare unconditionally, which throws
on a null slug. Since sortBySlug ran before the findings gate, a legacy
slug === null row — exactly the case the gate exists to catch — crashed the
sort into a generic 500 instead of the designed
{ error: 'unexported definitions missing slugs', findings: [...] } response.
Move the sort after the gate (every slug is a non-null string by then) and
make the compare null-safe as defense in depth.
…nes floor, prune ref guard, cli polish Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the Sprint 11 plan (
docs/superpowers/plans/2026-07-16-sprint-11-config-as-code.md) — campaign definitions become git-committable JSON, delivering the "config-as-code: JSON export/import of definitions + CLI (also the Strapi-exit migration path)" v1.x slice:GET /config-plane/projects/:id/exportemits theformatVersion: 1file exactly (slug-sorted for determinism, explicit nulls, slug cross-refs); any legacy row missing a slug fails loudly with EVERY offender namedPOST /config-plane/projects/:id/import— slug-matched upsert with field-level diffing (idempotent), opt-inprune,dryRunreturning the plan with zero writes; every write goes through the Document Service so all Sprint 8–10 lifecycle validations fire; mid-run rejection returns 422 with a plan RECOMPUTED from the database, never the intended one@promocean/cli(promocean export|import) — secret viaPROMOCEAN_CONFIG_SECRETenv only; exit code 2 on dry-run-found-changes makespromocean import --dry-runa zero-tooling CI drift checkdiffidentical); nine-scenario live import-verification script checked in (pnpm --filter cms verify:config-sync)Behavior notes for existing consumers
slug— existing dev volumes need a reseed (docker compose --profile stack down -v) or manual slug backfill; the export endpoint's loud failure names every offender.x-config-secrettrust model, operator-only. This is a posture change from the previously read-only plane.require()s the ESM-only@promocean/contracts(its first coupling to a workspace package); runtime images and CI are already Node 22.--prune, an import is rejected up front (400, before any write) if a kept offer references a placement/timed event the file omits — that target would be deleted, orphaning the offer. (Documented in both READMEs; a deliberate tightening of the spec's cross-ref rule.)@promocean/clion the runner before Playwright (the spec drives the real binary).Test plan
Review notes
Six tasks through the full gate cycle (three task fix waves: contracts null-coverage, cms verification-script gap, export gate-before-sort with differential live repro) plus the final whole-branch review — verdict ready to merge after fix wave
43c5ed1, which closed two Criticals the whole-branch read caught: the npm-installedpromoceanbin silently no-oping (isMain vs bin symlinks — now realpath-based with a symlink subprocess regression test) and the CI e2e job never building the CLI. Also tightenedconfigFileSchema(pointRules keys / registeredEventTypes / duplicate slugs) whileformatVersion: 1is still free to change. Task 6 additionally caught the cms Docker image missingcontracts/distand export nondeterminism. Follow-up issue filed alongside this PR: config-plane polish bundle.One v1.x roadmap item remains: the React Native SDK.
🤖 Generated with Claude Code