Skip to content

feat: headless control plane — spec and milestone 1 foundations - #131

Merged
siracusa5 merged 6 commits into
mainfrom
c/contextcake-plan-review-90e92b
Aug 11, 2026
Merged

feat: headless control plane — spec and milestone 1 foundations#131
siracusa5 merged 6 commits into
mainfrom
c/contextcake-plan-review-90e92b

Conversation

@siracusa5

Copy link
Copy Markdown
Collaborator

Summary

Commits the approved spec + design for the headless control plane (contextcake as the full local administration surface; UI optional) and delivers milestone 1 of its sequence: the Node 22 floor, profile-scoped sidecar state with a one-time migration, and the first slice of the shared control-operations layer the CLI and HTTP service will both adapt.

Changes

  • specs/contextcake-control-plane/ — Design-First spec (~45 EARS criteria across 14 groups) + design doc. §8 records the accepted decisions: staged publication (Wave A first, absent families absent), Windows demoted to a parallel gated milestone (v1 = macOS + Linux), keychain custody inversion with a shared delete path, engines ≥22, Homebrew in the same wave as npm, and a typed account status "disabled" state.
  • Node floor — root engines >=18>=22; CI's engine job now runs a 22/24 matrix; a new desktop test asserts the Electron-bundled Node (which runs the identical CLI under ELECTRON_RUN_AS_NODE) satisfies the root floor.
  • Profile-scoped sidecar state — rules, priorities, resolution history, and the transaction journal move to .contextcake/profiles/<profile-id>/ (new sidecar-state.mjs). Stores take an explicit profileId; the service passes its default-profile view, the MCP server its runtime selection. Unscoped legacy files migrate to profiles/default/ on first access — idempotent, crash-resumable, and refusing (never guessing) when a file exists in both layouts. The team-shared rules file inside a live layer root is deliberately untouched.
  • Control operations (first slice) — new packages/core/src/control/: typed ControlError (stable code + the HTTP status the service adapter answers with), source add/patch/remove validation + probes + clone lifecycle, and settings view/patch. service.mjs handlers become parsing shims over the same operations; git credentials flow in as an injected capability rather than being read from service state. Responses stay byte-identical.

Test Plan

  • Local tests pass — full root suite green (including the retrieval eval) plus 105/105 desktop tests
  • CI checks pass (first run of the new 22/24 engine matrix)
  • New suite sidecar-state.test.mjs covers migration, crash-resume, both-layouts refusal, profile isolation, and id validation

Notes

  • Merging this PR is the natural approval act for the spec's §8 decisions.
  • Milestone 2 (Wave A CLI: foundation/profiles/sources/settings/query/diagnostics over these operations) follows on a separate branch.
  • npm name reservation (contextcake + context-cake) is a John-side milestone-0 action and is not part of this PR.

🤖 Generated with Claude Code

@siracusa5 siracusa5 added the enhancement New feature or request label Aug 11, 2026
siracusa5 and others added 5 commits August 11, 2026 14:54
Design-First spec for building `contextcake` into the full local control
plane (CLI-first administration, JSON envelopes, staged npm publication,
credential registry, MCP child-env hardening). Derived from the reviewed
plan; §8 records the accepted decisions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: John Siracusa <siracusa5@users.noreply.github.com>
Homebrew ships in the same wave as npm; `account status` reports a typed
"disabled" state in accounts-disabled builds. Accepted 2026-08-11.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: John Siracusa <siracusa5@users.noreply.github.com>
Engines >=22 per control-plane spec §5.13; CI's engine job now runs a
22/24 matrix, and a desktop test asserts the Electron-bundled Node (which
runs the identical CLI under ELECTRON_RUN_AS_NODE) satisfies the floor.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: John Siracusa <siracusa5@users.noreply.github.com>
Rules, priorities, resolution history, and the transaction journal move
from `.contextcake/` to `.contextcake/profiles/<profile-id>/`
(control-plane spec §5.3). Stores take an explicit profileId; the service
passes its default-profile view, the MCP server its runtime selection.
Unscoped legacy files migrate to profiles/default on first access —
idempotent, crash-resumable, and refusing (never guessing) when a file
exists in both layouts. The team-shared rules file inside a live layer
root is deliberately untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: John Siracusa <siracusa5@users.noreply.github.com>
…vice

First slice of the control-operations layer (control-plane design §1-2):
packages/core/src/control/ now owns source add/patch/remove validation,
probes, clone lifecycle, and settings view/patch, with typed ControlError
(stable code + the HTTP status the service adapter answers with). The
HTTP handlers become parsing shims over the same operations the CLI will
call; git credentials flow in as an injected capability, never read from
service state. Full root suite green, byte-identical responses.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: John Siracusa <siracusa5@users.noreply.github.com>
@siracusa5
siracusa5 force-pushed the c/contextcake-plan-review-90e92b branch from 2fbeefb to 6467388 Compare August 11, 2026 18:54
Spec: align the §5.3 migration criterion with the shipped design
(migrate, then recover — equivalent because journal targets are absolute),
make the --timeout and redaction criteria testable, add the missing
`account status` criterion, fix the stale engines/status claims, and name
the real site install pages. Drift: Node 18 → 22 in README and site
install pages; profile-scoped `.contextcake/profiles/<id>/` paths in the
discrepancy reference, console README, and conflict-resolution design;
CLAUDE.md key-files rows for control/ and sidecar-state.mjs. Also drop
the now-dead readManifest() from service.mjs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: John Siracusa <siracusa5@users.noreply.github.com>
@siracusa5
siracusa5 merged commit 5728ec5 into main Aug 11, 2026
9 checks passed
@siracusa5
siracusa5 deleted the c/contextcake-plan-review-90e92b branch August 11, 2026 19:11
siracusa5 added a commit that referenced this pull request Aug 11, 2026
main moved ahead by four PRs while this branch was open. Three of them
interacted with it directly:

#131 added packages/core/tests/sidecar-state.test.mjs to the test chain. The
only conflict was package.json's "test" script — this branch replaced the
chain with scripts/test.mjs, so a mechanical "keep ours" would have silently
dropped that suite from the gate. It is registered now, and the runner grew
assertEverySuiteRegistered(): on a full run it walks packages/core/tests and
scripts/tests and refuses to start if a test file exists that no suite names.
The old chain had the same failure mode and no way to notice it.

#132 removed two stray NUL bytes from service.mjs and main.mjs — the actual
cause of the grep blindness this branch had documented in CONTRIBUTING as a
locale problem. That diagnosis was wrong: a NUL byte makes grep treat a file
as binary regardless of LANG, and both files now grep cleanly with LANG
unset. The section is corrected to name the real cause, and scripts/test.mjs
gained assertNoNulBytes() so a reintroduced NUL fails the gate instead of
quietly hiding a file from every search. #132 fixed the instances; nothing
stopped the next one.

#130/#129 touched console and desktop only and merged clean.

Also aligns packages/core/package.json's node floor with the root's new >=22.

Verified after the merge: npm test 33/33; console typecheck + 453 tests;
desktop 106 tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: John Siracusa <siracusa5@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant