feat: headless control plane — spec and milestone 1 foundations - #131
Merged
Conversation
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
force-pushed
the
c/contextcake-plan-review-90e92b
branch
from
August 11, 2026 18:54
2fbeefb to
6467388
Compare
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
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>
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
Commits the approved spec + design for the headless control plane (
contextcakeas 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 typedaccount status"disabled" state.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 underELECTRON_RUN_AS_NODE) satisfies the root floor..contextcake/profiles/<profile-id>/(newsidecar-state.mjs). Stores take an explicitprofileId; the service passes its default-profile view, the MCP server its runtime selection. Unscoped legacy files migrate toprofiles/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.packages/core/src/control/: typedControlError(stable code + the HTTP status the service adapter answers with), source add/patch/remove validation + probes + clone lifecycle, and settings view/patch.service.mjshandlers 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
sidecar-state.test.mjscovers migration, crash-resume, both-layouts refusal, profile isolation, and id validationNotes
contextcake+context-cake) is a John-side milestone-0 action and is not part of this PR.🤖 Generated with Claude Code