The rename
Publishing a migration is unusual for a product site and right for this one: the repository is public, the old name is everywhere in it, and a reader hits the mismatch within a minute. Headline: architecturally done, textually about 40% done.
~71.5% of the new codebase is not browser code. Playwright is 1 of 16 registered specs and 16.8% of spec code. Including the legacy CLI package — 71,182 lines of AWS, IAM, credentials, sentinel and TUI code, all generic — the browser-specific share of the whole 217k-line repository falls to about 14%.
The 30 April 2026 naming brief said it first, and better:
“The project is called ‘SP’ (SGraph Playwright), which is wrong: Playwright is just one of many components now.”
“The overall product is sometimes called ‘ephemeral EC2,’ which is too narrow: it is bigger than EC2.”
“Now is the right time to fix this. We are in the middle of a refactoring. The code, the CLI, the API, and the UI can all be renamed together.”
That was four months ago.
⚠ The guard that has been hiding it
tests/ci/test_no_legacy_imports.py exists to stop the new tree importing from the legacy one. Its regex:
r'from\s+sgraph_ai_service_playwright[^_]|import\s+sgraph_ai_service_playwright[^_]'
[^_] requires a non-underscore after the package stem. The real package is sgraph_ai_service_playwright__cli — double underscore. Verified by running both patterns over the tree:
GUARD regex : 0 files -> test PASSES (vacuously) REAL imports : 69 files, 228 import lines FIXED regex : 69 files -> test FAILS, as intended
The 228 break down as __cli.aws 126, __cli.credentials 71, __cli.tui 23, plus a handful in osx, observability, firefox, neko and sentinel. And the dependency runs both ways — the legacy package imports sg_compute 72 times. The guard's own docstring says “BV2.7 broke the cycle.” The cycle is not broken.
There is a second tell in the same file. Its allowlist exempts a path called …/Local__Docker__SGraph_AI__Service__Playwright.py — a class named after the old service, living inside the new tree. The rename has not reached the class names.
Deleting four characters turns this test red. It is fix F1, and it should happen before anyone claims the tree is clean.
The nine acceptance criteria, scored
From the 30 April brief, verified against the tree.
| # | Criterion | Evidence | |
|---|---|---|---|
| 1 | No “SP” / “SGraph Playwright” references remain | no | sp and sp-cli are live pyproject.toml entry points; the legacy CLI package is 71,182 lines |
| 2 | CLI uses sg-compute node/pod/stack | partial | The binary exists, but only sg nodes is wired in. Cli__Compute — the taxonomy-correct aggregator — exists and is not an entry point, reachable only through a script |
| 3 | API uses /nodes /pods /stacks /specs | done | All four route classes exist and are mounted |
| 4 | Frontend nav shows Nodes/Specs/Stacks/Settings | done | Compute · Nodes · Stacks · Specs · Settings · API |
| 5 | Specs stored as JSON with a spec.json | better | Deliberate deviation, and better than asked for: typed manifest.py with a schema class. The mechanism → |
| 6 | “Stack” reserved for multi-node only | no | Every per-spec CLI help string still says “Ephemeral X EC2 stacks” for a single instance — 13 occurrences in one file |
| 7 | ≥ 6 specs defined | done | 16 registered |
| 8 | Folder structure matches the taxonomy | partial | sg_compute/{core,cli,control_plane,platforms} and sg_compute_specs/ match; the frontend directory does not |
| 9 | Old naming gone from user-facing surfaces | no | service_name='sg-playwright', SG_PLAYWRIGHT__*, the image names, the PyPI name |
Score: 3 done, 2 partial, 4 not done — plus one deliberate improvement over spec.
Criterion 6 is the cheapest and most visible win. The brief was explicit: “Reserve ‘stack’ for this. Do not use it for single nodes.” Thirteen help strings in one file violate it — and, per the ledger, there is no multi-node orchestration for the word to describe anyway.
Where the names are, counted
| Name | Files containing it |
|---|---|
sgraph_ai_service_playwright | 5,140 |
sg-playwright | 5,008 |
sg_compute | 3,013 |
SG/Compute | 815 |
sg-compute | 557 |
| the old repository name | 114 |
| the old PyPI name | 14 |
Runtime self-identification is still Playwright: Capability__Detector sets service_name = 'sg-playwright'. Environment variables are 21 distinct SG_PLAYWRIGHT__* against 2 SG_COMPUTE__*.
What a rename would actually break
| Surface | Current | Breaks? |
|---|---|---|
| Repository name | the old name | 114 files reference it |
| PyPI package | the old name | yes — a published name. Needs a new package plus a deprecation shim |
| Docker images | diniscruz/sg-playwright, -vnc, sg-host-control | yes — 124 + 19 references including CI, user-data and compose. Running nodes pull by name |
| Legacy package directory | the old package | 228 imports across 69 files |
| Frontend directory | the old name | Static mount paths, and a packaging guard |
| Environment variables | SG_PLAYWRIGHT__* (21) | yes — baked into the env file on every running node. A rename orphans live infrastructure |
| Runtime identity | service_name = 'sg-playwright' | Consumers key off /health/info |
| CLI aliases | sp, sp-cli | Documented as “legacy, kept for backward compat” |
| DNS zone | the live per-node zone (128 refs) | § the domain collision |
One thing is already broken. bake-ami.yml invokes a binary called sg-play sixteen times, and sg-play is defined nowhere. That entire workflow is dead — which also means the AMI bake pipeline cited as a maturity signal is not runnable as written.
The sequencing — because a big-bang rename orphans live nodes
Fix the guard first
Four characters. The legacy dependency becomes visible and measurable, and every step after this one can be checked rather than believed.
Fix sg-play
One line. A dead workflow hiding a whole pipeline.
Add aliases before removing names
Publish the new PyPI package and Docker tags alongside the old. Make service_name configurable. Accept both environment-variable prefixes, with the old one warning.
Break the cycle
228 imports, mostly aws, credentials and tui. This is the real work, and it is what blocks a clean package boundary.
Rename the repository — last
When nothing points at the old name that is not aliased.
⚠ The domain collision
The site you are reading is sg-compute.sgit.ai. sg-compute.sgraph.ai is a live Route 53 zone, used for per-node DNS as <stack-name>.sg-compute.<zone>, and it appears 128 times in the platform's code and tests, including in code defaults and test assertions.
Same label, different TLD. That is workable, and it is also the kind of thing that produces a support question every week forever. The two options were: claim the distinction explicitly, or move the node DNS and touch 128 references and every running node.
The decision is the first one, and it is stated rather than left to be discovered. sgit.ai is documentation; sgraph.ai is running infrastructure. Where it could still bite, and what would change the answer →
Three good ideas from the naming brief, currently unused
- The recursion. “The Ephemeral Compute control plane should be able to run inside Ephemeral Compute… This is recursion, but it is also practical.” The most quotable unbuilt idea in the corpus →
- The simulated marketplace. “This is the simulated AWS Marketplace: a catalogue of pre-configured, ready-to-launch environments.” Sixteen specs with typed manifests, stability ratings and boot times is exactly that catalogue →
- It is bigger than EC2. Still true, and still not reflected in a
Platformabstraction with one implementation. Q3.