Repository navigation
Discover project profiles instead of enumerating client brands - #11
Merged
Merged
Conversation
CI broke because merge 29d4382 combined a branch that deleted .codex/config.toml with a main that had grown a host-profile model still referencing it. Doctor read a file that no longer existed and reported a warning, failing the profile test. The deeper cause was that "client-neutral" had no testable definition, so two contributors implemented incompatible versions 27 minutes apart and the merge silently kept the wrong half of each. Define the boundary as: a client brand may appear as data (a discovered profile's file name, prose in docs) but never as control flow. Doctor now discovers .mcp.json and any dot-directory config.toml or mcp.json, then checks only the launch contract, so onboarding a client needs no code change. --host codex/claude collapse into --host profiles. Add tests/client-neutrality.test.ts to enforce zero brand tokens in src/, synthv/, scripts/, and .github/, and restore .codex/config.toml, which the READMEs, quickstarts, and host docs still reference. Skip locally modified profiles in the doctor test. Emptying these files to stop a stale build from auto-launching once made this test look like a real regression (docs/issue-8-fix-and-verification-2026-08-11.zh-CN.md); CI checks out clean, so it stays strict there.
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.
Why CI was red
Merge
29d4382combined a branch that deleted.codex/config.tomlwith amainthat had independently grown a host-profile model still referencing it. Doctor
kept reading a file that no longer existed:
The file was gone, but every reference to it came back from
main—README.md:261,README_CN.md:239,docs/hosts/codex.md:10,docs/quickstart.md:69,docs/quickstart_cn.md:67, andscripts/doctor.mjs:433.The deeper cause
client-neutralhad no testable definition. Two contributors implemented it27 minutes apart on the same day, in incompatible ways:
ede9e89(18:01) — strict: ship no client config at all588c03f(18:28) — permissive: ship project profiles, add--host codex|claudeBoth wrote their reading into
AGENTS.mdas prose. Prose does not fail in CI, sothe merge silently kept the deletion from one and the references from the other.
The rule this PR introduces
A client brand may appear as data — a discovered profile's file name, prose in
docs/telling a user how to register the server. It must never appear ascontrol flow.
That judgement also settles the original dispute: shipping
.codex/config.tomlwasnever the violation; the
--host codexbranch in Doctor was. The strict branchdeleted the innocent file and left the real coupling in place — and dropped
.codex/config.tomlwhile keeping.mcp.json, an asymmetry with no principlebehind it. Discovery removes it: both are just profiles.
Changes
scripts/doctor.mjs— discovers.mcp.jsonand any<dot-dir>/config.tomlor
<dot-dir>/mcp.json, validates only the launch contract(
synthv-agent-bridgestarted asnode dist/src/cli.js).--host core|codex|claude|all→--host core|profiles|all.tests/client-neutrality.test.ts(new) — fails if a brand token appears insrc/,synthv/,scripts/, or.github/..codex/config.toml— restored; still referenced by both READMEs, bothquickstarts, and
docs/hosts/codex.md.AGENTS.md— the prose replaced with the rule above.--host codex|claude|all→--host profiles.Verification
Onboarding a new client with zero code changes, and catching a bad one:
The guard test goes red when coupling is introduced (verified by injecting
if (process.env.HOST === "codex")intoscripts/clean.mjs):Full suite:
One deliberate exception
tests/client-neutrality.test.tsitself contains nine brand names — the denylistit matches against. A test that checks for brands has to know their names. It is
data, not control flow, and lives outside the four enforced directories.
cursoris deliberately not on that list: it collides withpageCursor,cursorToken, and the parsing cursors throughoutscore-import.ts, where thefalse-positive rate would drown the signal. Noted in the test.
Known gap
The negative path (a misconfigured profile →
warning) is verified by hand abovebut has no regression test; that needs a profile-root override so a test can point
at a fixture. Not included here to keep the change scoped.