Skip to content

epic #470 C13: core-decoupling ratchet reads 0, pinned permanently - #808

Merged
Weegy merged 20 commits into
mainfrom
feat/470-c13-residue
Aug 21, 2026
Merged

epic #470 C13: core-decoupling ratchet reads 0, pinned permanently#808
Weegy merged 20 commits into
mainfrom
feat/470-c13-residue

Conversation

@Weegy

@Weegy Weegy commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Epic #470 C13. Stacked on #807 (C12). Ratchet 0.

Core carries no Dev Platform reference at all — no code path, config key, i18n key, fixture string or comment. All 14 zones CLEAN, and the floor is now enforced as an absolute rather than as a baseline.

3,300  epic start
  214  after C10 (the tree deleted)
  209  after C12 (the publicPaths exemptions)
    0  this PR

Per-zone

Zone Was Now What was there
middleware/src 19 0 Comments. Some pointed at paths C10 deleted (devplatform/routes/devWebhooks.ts, src/devplatform/devJobTypes.ts) — stale links, now corrected
middleware/test 62 0 Fixture route prefixes, nav ids, channel types → a neutral example plugin; one test renamed and re-scoped (below)
middleware/packages 17 0 A tombstone comment in pluginContext.ts + one shared-pool comment; CHANGELOG.md allowlisted
middleware/migrations 69 0 Allowlisted — see below
middleware/env-example 1 0 Operator pointer now names the Hub (the actual install path) instead of the plugin's source repo
web-ui/app 19 0 Nav/route fixtures, plus a genuinely stale comment claiming the entry shows "while DEV_PLATFORM_ENABLED" — an env var C10 deleted
scripts 27 0 The ratchet was counting its own PATTERNS array
middleware/scripts, sidecars, package.json, web-ui/messages, web-ui/config, ci-workflows, compose 0 0 Already clean after C10 — the CI matrix, id-token: write and compose residue named in the C13 brief were handled there

The floor is absolute, not a baseline

A ratchet parked at zero still reads its floor out of a JSON file, and a JSON file is editable. One hand-edit and core could legally re-acquire a reference — the outcome the whole epic exists to prevent.

So EXTRACTION_COMPLETE in scripts/check-core-decoupling.mjs makes the check assert 0 outright and ignore the baseline for pass/fail. --update refuses to write a non-zero baseline. The CI job (core decoupling ratchet (#470), unchanged name, still required) additionally greps the report for TOTAL 0, so even a refactor that made the script exit 0 while still counting hits fails the job.

Mutation-checked — one probe comment added to src/services/ssrfGuard.ts:

$ node scripts/check-core-decoupling.mjs
Core re-acquired Dev Platform references: 1 found, 0 allowed.
  middleware/src: 1
exit 1

$ node scripts/check-core-decoupling.mjs --update
refusing to record a non-zero baseline: 1 reference(s) found.
exit 1

Reversing the extraction is now an architectural decision to argue in review — flip the constant, restore a baseline — not a number to edit.

What is allowlisted, and why it is not a dodge

Two entries, each anchored on an exact path so the exemption cannot widen. Both are historical record rather than coupling — a record you are allowed to edit is not a record.

Allowlisted Why it cannot be reworded
middleware/migrations/00{22..30}_* Every deployment that ran them has those filenames in its schema_migrations ledger, and C11's plugin-side migrator seeds its own ledger from exactly those donor rows. Rename one and the handoff stops matching on the installations that need it most. The DDL body names the real tables and columns living in those databases right now.
middleware/packages/plugin-api/CHANGELOG.md A published entry for a released version, written to be found: it spells out the removed exports so a consumer grepping their own source lands on the entry explaining where the type went. Rewording it breaks its one job and misreports what shipped.

The script also excludes itself. PATTERNS has to spell out the 21 identifiers it hunts for, so an unfiltered scan counted 27 hits against the detector and made the target 27 instead of 0. Self-exclusion is safe precisely because it is the detector — no runtime, ships in no image, and adding a pattern there can only make the check stricter. The narrower alternative (skipping the array by line range) breaks the moment the array moves.

services/githubAppJwt.ts stays in core and needed no allowlist — it is generic GitHub App auth and carries no matching identifier. Its comment now says explicitly that moving it into the plugin repo would recreate the reverse dependency across a repo boundary.

Zero counts identifiers, not the English name

Worth being explicit, because it is the difference between a sweep and a whitewash. The patterns are identifier-shaped (devPlatform, dev-runner, DEV_JOB, djr_, …). A comment may still say "the dev platform plugin", and several deliberately do. What cannot survive is an import, a route, a config key, an i18n key or a fixture string. Prose describes history; identifiers create coupling. Where the old comment pointed at a real code artifact that no longer exists, it was corrected rather than reworded.

One test re-scoped, not just renamed

manifestDevJobsLegacyKey.test.tsmanifestRetiredPermissionKey.test.ts. It pinned one historical permission key, but the guarantee it protects — unknown permission keys are ignored, not rejected — is key-agnostic. Pinned to one name it would go stale-but-green the next time a different capability is retired. It now exercises the shapes a retired key arrives in (bare true, a block of options, alongside live keys). Which names were retired stays in the changelog, which is a changelog's job.

A trap this sweep walked into

Renaming the nav fixture's de label left never leaks the per-locale label map to the browser asserting res.text.includes('Dev-Plattform') === false — a string that no longer existed anywhere, so the guard was permanently green. Repointed at the real de label (Beispiel-Plugin), which the sibling locale test proves is present in the de response. Flagging it because it is the exact failure mode a mass-rename invites.

Verification

Check Result
middleware full suite 6,948 tests — 6,936 pass, 0 fail, 12 skipped
web-ui vitest 717 tests, 85 files — all pass
middleware tsc --noEmit + eslint clean
middleware typecheck:test ratchet 371, no regressions (caught one error I introduced; fixed, not re-baselined)
web-ui typecheck, eslint clean (0 errors)
i18n:check OK — 3,560 keys, en + de
i18n:literals exit 0
check-core-decoupling.mjs TOTAL 0 / baseline 0, all 14 zones CLEAN
Zero-enforcement mutation check and --update both fail on one reintroduced reference

Nothing was left above zero.

Do not merge yet; stacked on #807.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Cross-family review (Forge)

Reviewed against code, not against the description. GPT-5.4 (reasoning=high) via codex exec — a different model family from the author, deliberately.

Verdict: MERGE after 04fc1053. The zero floor is real and the mutation evidence reproduces. One genuine hole was found in the allowlisting, plus two gaps; all three are fixed on this branch.

The enforcement itself reproduces

Re-ran the author's mutation independently (one // probe: devplatform in src/services/ssrfGuard.ts):

Layer Result
node scripts/check-core-decoupling.mjs exit 1, names the zone
--update exit 1, refuses a non-zero baseline
CI's grep -qE '^ TOTAL 0' exit 1

All three fail independently. EXTRACTION_COMPLETE is not decorative.

DEFECT (fixed) — the self-exclusion was a basename wildcard, not a path

'!**/check-core-decoupling.mjs' excludes every file of that name anywhere in a scanned zone, not just the detector. Proven:

$ printf '// devplatform devRunner dev_job\n' > middleware/src/__probe/check-core-decoupling.mjs
$ node scripts/check-core-decoupling.mjs
Core is free of Dev Platform references.
exit 0

Three real identifiers inside middleware/src, counted as zero. That is precisely the "reference hiding inside an allowlisted region" the floor exists to prevent, and it needed no edit to the script or the baseline — just a filename.

Anchored to the exact repo-relative path. The scripts zone still reports CLEAN (self-exclusion intact) and the probe now exits 1.

The mutation test is now committed rather than performedscripts/check-core-decoupling.test.mjs plants the probe and asserts the checker goes red. It builds its own pattern tokens at runtime (['dev','platform'].join('')) so the test file cannot trip the detector it tests. Mutation-checked in both directions: reverting the glob turns it red, restoring it turns it green.

GAP (fixed) — the regression test would never have run

scripts/ has no package.json, and no CI job globs *.test.mjs. A test file left there is green because nothing executes it — the same failure family this job's own timeout comment already names. Wired into the decoupling job as a step after the zero assertion.

GAP (fixed) — the rename stopped at identifiers, not at the name

PATTERNS is identifier-shaped, so Dev Platform and Dev-Plattform match nothing. Four fixtures still carried the plugin's display name while this PR states "what cannot survive is … a fixture string":

middleware/test/uiRouteCatalogNav.test.ts · middleware/test/toolPluginRuntimeRouteDisposal.test.ts · web-ui/app/_lib/__tests__/navParse.test.ts · web-ui/app/_lib/__tests__/navMerge.test.ts

Renamed to Example Plugin / Beispiel-Plugin together with their assertions, preserving the en / de / de-AT / fr fallback each test exercises. Invisible to the ratchet by construction, so this one only closes by reading.

The identifiers-not-prose argument is otherwise correct and was not disturbed — deliberate prose in the detector, .env.example, package.json _dependencyNote and chat/page.tsx is untouched. Adding the English name to PATTERNS would make the detector's own prose unfixable.

Mass-rename trap — swept, one more angle

Extracted every string literal the C13 diff removed-and-did-not-re-add, then grepped each against the tree at HEAD. Besides the Dev-Plattform leak the author already caught, no assertion compares against a string that no longer exists. The four fixtures above were self-consistent (fixture and assertion moved together), so they were a naming gap, not permanently-green tests.

No behaviour hidden in the sweep

Classified every changed line in all 11 non-test source files (pluginContext.ts, githubAppJwt.ts, manifestLoader.ts, awaitStore.ts, publicPaths.ts, ssrfGuard.ts, gateReevaluation.ts, adminEmbeddingProvider.ts, conductorWebhooksInbound.ts, 0007_webhooks.sql, .env.example) plus both web-ui files: comment-only, every one. The sole executable change in the whole residue sweep is the ratchet script itself. Claim (4) holds exactly.

Allowlist judgement

Migrations 0022–0030 and the plugin-api CHANGELOG are anchored on exact paths and are genuinely historical record — rewording either breaks the artifact's one job. Left as-is. Worth knowing about the residual shape: a new line added inside those two regions would be allowlisted too. The migrations are frozen released DDL (editing one is already a violation with its own consequences) and the CHANGELOG is append-only per release, so the exposure is narrow and visible in review — unlike the basename hole, which was invisible.

Gates (on the merged branch)

middleware 6,948 tests — 6,936 pass, 0 fail, 12 skipped · web-ui vitest 717 pass · typecheck:test ratchet 371, no regressions · middleware eslint clean · web-ui typecheck clean, eslint 0 errors · i18n:check OK — 3,560 keys, en + de · i18n:literals exit 0 · check-core-decoupling.mjs TOTAL 0 / baseline 0 · detector regression test 2/2 · ci.yml parses, decoupling job has 5 steps.

Note: C12's review fix (f7acf93f) is merged forward into this branch, so the Fixed changelog entry here covers the whole C12+C13 review.

Weegy added 17 commits August 20, 2026 20:21
…(C10)

Epic #470 C10 — the flip. The Dev Platform now lives in
byte5ai/omadia-dev-platform and installs via Hub/ZIP.

Removed:
- middleware/src/devplatform/ (62 files) — stores, worker, backends, LLM
  proxy, pipeline/gates, GitHub App, triggers, routers, wireDevPlatform
- middleware/test/devplatform/ (58 files)
- middleware/scripts/dev-transcript.ts

Adversarial eval (#498): the `brief_delimiter` Tier A probe ran the real
`composeBrief` out of src/devplatform/. A probe against a module core no
longer ships measures a library, not a deployed defense — so the probe, its
five corpus scenarios (direct-injection.jsonl, indirect-injection.jsonl) and
their baseline rows leave with it. This is a real coverage reduction and is
recorded as such in test/adversarial/README.md, with both ways to close it.
Deterministic corpus: 12 scenarios -> 7.
…y (C10)

Removed:
- middleware/packages/dev-runner-shim/ (23 files) — the in-container agent
  shim. Never built by `npm run build`, yet index.ts resolved its dist/ at
  runtime; the extraction removes that inconsistency with it.
- middleware/sidecars/dev-runner/ (2), dev-runner-daemon/ (30, dockerode),
  dev-dind/ (2)
- docker-compose.dev-platform.yaml

All four now live in byte5ai/omadia-dev-platform, which owns their GHCR
publishing, SBOM and signing pipeline.
index.ts (-238 lines):
- 15 devplatform imports + the now-dead DeviceFlowStore / ConductorRoleStore
- the GitHub-webhook block mounted before express.json
- the whole assembly block: assembleDevPlatform / mountDevPlatform, the
  GitHub-App routers, the three chat orchestrator tools, worker start +
  SIGTERM/SIGINT hooks, the uiRouteCatalog nav registration, the retention
  cron and the no-graphPool warning

Side effect worth calling out: the `/api/v1/dev-runner/llm/` carve-out sat
BEFORE the conductor inbound webhook router, so an express.json ran ahead of
that router's route-level express.raw() and short-circuited it (body-parser
marks the request `_body`). Deleting the carve-out restores the order the
surrounding comments already document: pluginRawBodyMount -> conductor raw
router -> global express.json.

config.ts (-305 lines): all 43 DEV_*/FLY_* dev-platform schema keys, the
`devPlatform` namespace, `buildDevPlatformConfig`, `csvList`, and the
CORE_DEV_PREFIXED_KEYS / DevPlatformEnvKey / isDevPlatformEnvKey machinery
that existed only to hold those keys out of the top level — `Config` is now
`ParsedConfig`. `devPlatformBootRefusals` goes too: the plugin owns both
interlocks (pluginConfig.ts, verified), so they became activation refusals
rather than vanishing. KEPT: devFlag() (two PUBLIC_MCP_* call sites),
DEV_ENDPOINTS_ENABLED, DEV_ENDPOINTS_LOOPBACK_ONLY, FLY_APP_NAME.

.env.example: the 15-key block replaced with a pointer to the plugin repo.

middleware/package.json: the §5 note — express/pg/zod stay as plugin
peerDependencies resolved through the host node_modules symlink.
… (C10)

- web-ui/app/admin/dev-platform/ (29 files) — the operator SPA. It ships from
  the plugin now as a compiled Vite bundle served through the C8 static host
  at /p/<pluginId>/ui/.
- web-ui/app/_components/devjobs/ (6 files) + app/_lib/useDevJobEvents.ts
- app/admin/page.tsx — the grid card. The generic `requiresNavFrom` mechanism
  stays; this was its only user.
- app/_lib/i18n-structural.test.ts — the GateInbox.tsx path entry.

H3 resolved by omission, as the plugin's ACCEPTANCE-RUN records. chat/page.tsx
no longer special-cases `tool.name === 'dev_job_start'`; a dev-job start from
the installed plugin now falls through to the generic long-running-task card
(`isTaskStartToolName` / TaskChatCard), which is the accepted degradation.

i18n: 299 leaf keys per locale removed (adminDevPlatform.* 288, chat.devJob.* 9,
admin.index.cards.devPlatform.* 2) = 598 across en+de, plus the four orphaned
`i18n-identical-allowlist.json` entries the validator flagged.
`npm run i18n:check` OK — 3560 keys; `i18n:literals` translate=0.
… (C10)

publish-images.yml:
- the `dev-runner` and `dev-runner-daemon` matrix entries
- the runner-image supply chain: cosign install, syft SPDX-JSON SBOM,
  keyless sign + attest (all guarded on `matrix.name == 'dev-runner'`)
- `id-token: write`, which existed solely for that keyless signing

auto-release.yml / release.yml: the matching caller-side `id-token: write`
grants, which a reusable workflow cannot self-grant and nothing else needs.
The `if: false` npm-provenance job in release.yml keeps its own grant.

byte5ai/omadia-dev-platform owns runner GHCR publishing, SBOM and signing
now. Per implementation.md §2.4 the cosign certificate identity binds to
repo + workflow + ref, so the new signer needs the transition
`--certificate-identity-regexp` landed before it publishes — that is P4's
job in the plugin repo, not core's.

The missing-Dockerfile guard stays: it also computes the version `stamp`
every remaining image consumes; only its dev-runner-daemon justification
comment is gone.

scripts/wave-{implement,verify}.workflow.mjs: the generic wave prompts baked
in "terminal transitions go through finalizeDevJob" — a dev-platform domain
rule in a domain-agnostic prompt, naming a function core no longer ships.
Genericised to "the subsystem's single finalizer"; the rule survives, the
implementor name does not. Same for the `docs/dev-platform/` example path.
`tsc` caught these, which is exactly why C10 has to be one PR.

Three LONG_RUNNING_* keys sat INTERLEAVED with the dev-platform keys in
config.ts, between DEV_PLATFORM_RUNNER_BASE_URL and DEV_PLATFORM_CLI_BIN, and
went out with the block:

  LONG_RUNNING_SUBAGENT_TOOLS   — W2-2 / issue #543, the generic
  LONG_RUNNING_TASK_STALE_MS      `<tool>_start/_status/_list` seam that any
  LONG_RUNNING_TASK_RETAIN_MS     slow tool opts into. Not dev-platform.

FLY_APP_NAME went too, despite CORE_DEV_PREFIXED_KEYS documenting in prose that
it "describes the host, not the feature, so it must survive the extraction".

All four are restored under an explicit heading that says why they are core, so
the next person reading config.ts does not have to re-derive it. Also drops the
`node:os` import, now unused (it backed the workspace-dir default), and rewords
the three comments this PR itself introduced that named the extracted subsystem
— C10 must not add coupling references while removing them.

Verified: middleware build + typecheck + adversarial/golden tsconfigs green;
6925 pass / 0 fail; typecheck:test ratchet 406 -> 371 (baseline lowered);
lint 0 problems. web-ui typecheck green, 717 pass / 0 fail, i18n 3560 keys OK.
…(C10)

Ratchet: **3,300 → 214**, updated consistently in all three places the README
says must agree — `decoupling-baseline.json`, the README "Baseline **214**"
line, and the `acceptance.md` guard row.

Nine of fourteen zones read CLEAN. Every survivor is scheduled, not stranded:

  migrations       69  C11 — 0022-0030 stay; core still applies them
  middleware/test  62  C13 — fixture strings + the legacy-key regression test
  scripts          27  C13 — the ratchet's own pattern list (needs a
                            self-exclusion before the total can reach 0)
  middleware/src   19  C12 — publicPaths (6); rest are comments
  web-ui/app       19  C13 — nav test fixtures, two comments
  packages         17  C13 — plugin-api CHANGELOG recording the removal
  env-example       1  the plugin repo URL, which cannot be reworded

Also: `test-typecheck-baseline.json` 406 → 371, and `package-lock.json`
regenerated (npm left `packages/dev-runner-shim` as an `extraneous: true`
stanza rather than dropping it; `npm ci` verified clean afterwards).

Docs:
- README gains a "C10 — the flip" status section: what left, what was kept and
  why, H3 resolved by omission, the adversarial coverage reduction, and the
  express.json ordering bug the deletion fixed. The H3 "decision before code"
  is struck through — it is answered now.
- plan.md §4.2 gains a C10 note (and flags that its `devJobStepEffect.ts` line
  went stale in the other direction: C5 deleted that port as dead code). P4 row
  marked shipped.
- docs/CHANGELOG.md: "Dev Platform moved to byte5ai/omadia-dev-platform
  (install via Hub/ZIP)" — written for operators, so it leads with how to get
  it back, states that no data is touched, and that in-flight jobs survive the
  upgrade because C12 has not run yet.
…sha_on_release matrix ref (C10 review)

Cross-family review of PR #804. Three defects, no scope change to the deletion itself.

1. `.github/workflows/publish-images.yml` referenced `matrix.sha_on_release`, which
   nothing defines any more: the only two matrix entries that set it (dev-runner,
   dev-runner-daemon) left with the Dev Platform. actionlint errors on this branch and
   is clean on main. Dropping the clause also restores the behaviour the adjacent
   comment already claims — sha tags on the edge build only.

2. `middleware/package.json` — the `_dependencyNote` added by this PR was indented four
   spaces and pushed `"dependencies"` to column 0. Valid JSON, but the rest of the file
   is 2-space and any tool that rewrites it would reflow the diff. Text unchanged.

3. Removing the LLM-proxy carve-out moved `createConductorWebhooksInboundRouter` from
   *after* the global `express.json` to *before* it. That is correct — and it silently
   fixes a live bug: on main the router HMAC'd `Buffer.alloc(0)`, because body-parser
   stamps `_body` and the route-level `express.raw()` then short-circuits, so every
   correctly-signed inbound webhook answered 401. Measured on a standalone probe:
   json-first yields rawLen 0, router-first yields the full 24 bytes.

   Nothing locked that order. `conductorWebhookInbound.test.ts` mounts the router alone
   on a bare app, which passes under BOTH orders — which is exactly how the broken
   ordering shipped green. Added two behavioural tests (same signed request, both mount
   orders: 202 vs 401) plus a source-order assertion in `778RouteMounts.wiring.test.ts`
   that fails loudly if either anchor goes missing rather than passing vacuously.

   All four assertions mutation-checked: reordering the mount fails the wiring test,
   renaming the anchor fails it for the anchor reason, and forcing/removing the parser
   in the harness kills exactly the intended behavioural tests.

Also corrects the C10 file count in the spec README (213 -> 217 measured deletions).
The adjacent "43 config keys" claim was verified correct and left alone. Ratchet stays
at 214 — the one comment that would have raised it was reworded, not excused.
Core stops exempting two URLs on a plugin's behalf. Since C4 the plugin
declares them itself in `permissions.public_paths`, and the operator consents
per prefix (`platform/publicPathGrants.ts`).

The deletion is the load-bearing half of that handover, not tidy-up.
`validateDeclaredPublicPath` REJECTS a declaration that collides with a live
static exemption — "is already a static core public path … remove the core
exemption first, or drop the declaration" — because two mechanisms claiming
one URL is ambiguous and only one of them terminates. So while these entries
existed the plugin's own grant could never validate. With them gone it does.

Guarded by a new suite that pins `STATIC_PUBLIC_PATHS` as a CLOSED set: every
entry must be accounted for by a named, justified core-owned exemption.
Restore either deleted entry and the suite goes red on the unaccounted entry,
which is what makes this commit cleanly revertible.

The suite deliberately does not name the two deleted paths. Hardcoding a
plugin's wire paths into core is a reference to that plugin whichever
direction it asserts in — the coupling this epic removes and the thing
`scripts/check-core-decoupling.mjs` counts — and it goes stale-but-green the
day the plugin renames them. The closed set is also the stronger guard: it
catches any unauthenticated surface being added, not just these two. The 401
follows as a corollary, since `requireAuth` runs on the `/api` mount before
routing, and is asserted end-to-end against the same chain `src/index.ts`
assembles.

Ratchet: 214 → 209. Nothing raised.
Core carries no Dev Platform reference at all: no code path, config key,
i18n key, fixture string or comment. All 14 zones CLEAN.

  214 -> 0    (3,300 at the epic's start, 214 after C10, 209 after C12)

WHAT MOVED

- middleware/src (14 -> 0), packages (17 -> 0), env-example (1 -> 0):
  comments and one operator-facing pointer. Where the reference was to a
  dead path (`devplatform/routes/devWebhooks.ts`, `src/devplatform/
  devJobTypes.ts`) it was a stale link and is now corrected; where it named
  the product it stays named, in prose.
- middleware/test (62 -> 0): fixture route prefixes, nav ids and channel
  types now use a neutral example plugin. `manifestDevJobsLegacyKey.test.ts`
  becomes `manifestRetiredPermissionKey.test.ts` and asserts the guarantee
  that actually exists — unknown permission keys are ignored, not rejected —
  which is key-agnostic, so pinning one historical key made it stale-but-
  green the next time a different capability is retired.
- web-ui/app (19 -> 0): the same, plus a genuinely stale comment claiming
  the nav entry appears "while DEV_PLATFORM_ENABLED" — an env var C10
  deleted.
- scripts (27 -> 0): the ratchet was counting its own `PATTERNS` array. It
  now excludes itself. A detector that counts its own definitions can never
  reach zero, and "zero except for the 27 that are the tool" is not a
  property anyone can check at a glance.

WHAT IS ALLOWLISTED, AND WHY IT IS NOT A DODGE

Two path-anchored entries, both historical record rather than coupling.
A record you are allowed to edit is not a record.

- `middleware/migrations/00{22..30}_*` — every deployment that ran them has
  those FILENAMES in its `schema_migrations` ledger, and C11's plugin-side
  migrator seeds from exactly those donor rows. Rename one and the handoff
  stops matching on the installations that need it most.
- `packages/plugin-api/CHANGELOG.md` — a published entry for a released
  version, written to be found by a consumer grepping for a removed type.

`services/githubAppJwt.ts` stays in core and needed no allowlist: it is
generic GitHub App auth and carries no matching identifier.

THE FLOOR IS NOW ABSOLUTE

A ratchet parked at zero still reads its floor out of a JSON file, and a
JSON file is editable. `EXTRACTION_COMPLETE` makes the script assert 0
outright and ignore the baseline for pass/fail; `--update` refuses to write
a non-zero baseline. The CI job additionally greps the report for `TOTAL 0`,
so a future refactor that made the script exit 0 while still counting hits
still fails. Bringing the Dev Platform back into core is an architectural
decision to argue in review, not a number to edit.

Zero counts IDENTIFIERS, not the English name: a comment may still say "the
dev platform plugin". Prose describes history; identifiers create coupling.
…oopback (C12 review)

The suite self-skips its five unauthenticated 401 assertions when a
sandbox refuses a loopback listener. Locally that is right — the closed-set
assertion still runs. In CI it is not: a runner that denied bind(127.0.0.1:0)
would delete the entire 401 half of the guard while the job stayed green,
which is the same permanently-green failure family the decoupling job's own
timeout comment warns about.

Keep the local skip, but throw with a named reason when CI is set.
…fixture rename (C13 review)

Three defects from cross-family review of the zero floor.

1. The self-exclusion was a BASENAME wildcard. `!**/check-core-decoupling.mjs`
   hides every file of that name anywhere in a scanned zone, not just the one
   detector. A probe at middleware/src/__probe/check-core-decoupling.mjs
   carrying three real identifiers scanned as "Core is free of Dev Platform
   references", exit 0. Anchored to the exact repo-relative path; the scripts
   zone still reports CLEAN, and the probe now trips the check.

2. The mutation test is now committed, not just performed. It plants that
   probe and asserts the checker goes red. Its own tokens are assembled at
   runtime so the test file cannot trip the detector it tests.

3. The C13 identifier rename left the plugin's HUMAN-READABLE label behind in
   four fixtures. PATTERNS are identifier-shaped, so `Dev Platform` and
   `Dev-Plattform` are invisible to the zero floor while the sweep claimed no
   fixture string survives. Renamed with their assertions, preserving the
   en/de/de-AT/fr fallback each test exercises. Deliberate prose mentions are
   untouched.

The regression test is wired into the decoupling job. scripts/ has no
package.json and no job globs *.test.mjs, so it would otherwise have been a
test nobody runs — green because nothing executed it.
@Weegy
Weegy changed the base branch from feat/470-c12-public-paths to main August 21, 2026 06:19
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.

1 participant