Repository navigation
Count only an absolute managed-mcp.json path as a managed MCP config - #967
Merged
seathatflowsinourveins merged 1 commit intoOct 10, 2026
Conversation
On POSIX the Windows path C:\Program Files\ClaudeCode\managed-mcp.json is a relative filename, so a file of that literal name in the working directory made skill_doctor_argv drop --strict-mcp-config while the client saw no managed config and would load user and project MCP servers. The command center's micro of #925 at 46cc5dd found it and the co-op's GPT reads of #925 at 46cc5dd and 715229c reproduced it (a readable file of that name holding malformed JSON, the default helper omitting the flag); the native client's My() picks the directory of the actual platform. A candidate now counts only when it is absolute and already normalised under the host's own path rules, with no platform branch and without resolving a relative candidate against the working directory; the comment no longer claims another system's path cannot exist on this one. Tests: one plants both the Windows-named file and a plain managed-mcp.json in the working directory and expects every fence to stay (it fails on the head of #925 and passes here); the comment test holds the new wording. ManagedMcpDefaultLocations, added by #925, is narrowed as that PR declared: a documented string is a location only where it is an absolute path on the host (counts_here), so the Windows cases run on nt hosts and on POSIX the Windows string is asserted inert in every state; the sensitivity test and the run test use the host's own locations. Sixteen in-memory mutations (research record, p3-mutations-20261010): the P3 revert, prepending the working directory and basename matching are caught, and ignoring or misspelling the Windows location are equivalent mutants on POSIX, caught on nt only. The Windows decision's ledger-refusal locator follows the added lines (2423-2429 to 2432-2438, counted by newline). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
seathatflowsinourveins
deleted the
claude/cc-native-practice-managed-path-abs-20261010
branch
October 10, 2026 15:17
5 tasks done
seathatflowsinourveins
added a commit
that referenced
this pull request
Oct 11, 2026
…ot a managed config The co-op's GPT read of #967 at 3de3dda (ACK, one non-blocking P3): the normalisation equality in _readable_system_file (os.path.abspath(name) == name) could be removed with every test green, because the relative-name test is already rejected by isabs and the default-location matrix only passes normalised strings. ManagedMcpDefaultLocations.test_an_absolute_path_that_is_not_normalised_is_not_a_managed_config uses real files (no fake host, so it runs on every platform): an existing child directory and the same managed-mcp.json reached through a dot-dot, a dot and a doubled-separator spelling. Each exists through the filesystem and each keeps the complete fenced argv, by parameter and by the default route; pathlib drops the dot and doubled-separator segments itself, so only the dot-dot spelling is also asserted as a Path. The normalised spelling of the same file drops only --strict-mcp-config, alone and next to a rejected candidate. Mutations (research record, pr925/p3-mutations-20261010): removing only the normalisation equality fails the new test (4 cases, none elsewhere), reverting the P3 fix still fails the relative-name test and now the new one; removing only isabs stays green because abspath(name) == name already implies an absolute name (an equivalent mutant, so isabs remains for readability). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
seathatflowsinourveins
added a commit
that referenced
this pull request
Oct 11, 2026
The command center's note on landing #967: the most useful P3 is a CI-run test that patches the module's os with ntpath, so the Windows side of the check is covered under Python 3.12, the CI interpreter. os.path is posixpath on a POSIX host, so until now the Windows clauses of _readable_system_file were argued from ntpath's functions and never executed. ManagedMcpDefaultLocations.test_the_windows_path_rules_count_the_windows_string_and_not_the_posix_ones replaces the module's os, for the test only, with a namespace whose isabs and abspath are ntpath's and whose file checks answer yes, so the path rule alone decides: the Windows documented string drops --strict-mcp-config, the macOS and Linux strings do not (under 3.12 ntpath.isabs accepts a leading separator and only the equality rejects them; from 3.13 isabs rejects them first), and a dot-dot, dot, forward-slash and doubled-separator spelling of the Windows string, a relative name and a drive-relative name each keep every fence. One accepted candidate among rejected ones decides the form, by parameter and by the default route. Source-level mutants of _readable_system_file, run in the module's own globals so the mutated body sees the swapped os (research record, pr925/p3-source-mutations-*): removing only the normalisation equality fails the new test on 3.12 and 3.13 (the four non-normalised Windows spellings, plus the macOS and Linux strings on 3.12) and the POSIX-side test added in the previous commit; removing only isabs fails it through the drive-relative name, because ntpath's pure-Python abspath on a POSIX host leaves "C:managed-mcp.json" equal to itself (the Windows abspath resolves it, so there isabs is belt and braces); reverting to the presence-only check of #925 fails the POSIX and Windows tests. The harness of the earlier mutation tables replaced the whole function and would not see a swapped os, so these supersede it for this test. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
seathatflowsinourveins
added a commit
that referenced
this pull request
Oct 11, 2026
…s under ntpath (#973) * Test that an absolute but non-normalised managed-config spelling is not a managed config The co-op's GPT read of #967 at 3de3dda (ACK, one non-blocking P3): the normalisation equality in _readable_system_file (os.path.abspath(name) == name) could be removed with every test green, because the relative-name test is already rejected by isabs and the default-location matrix only passes normalised strings. ManagedMcpDefaultLocations.test_an_absolute_path_that_is_not_normalised_is_not_a_managed_config uses real files (no fake host, so it runs on every platform): an existing child directory and the same managed-mcp.json reached through a dot-dot, a dot and a doubled-separator spelling. Each exists through the filesystem and each keeps the complete fenced argv, by parameter and by the default route; pathlib drops the dot and doubled-separator segments itself, so only the dot-dot spelling is also asserted as a Path. The normalised spelling of the same file drops only --strict-mcp-config, alone and next to a rejected candidate. Mutations (research record, pr925/p3-mutations-20261010): removing only the normalisation equality fails the new test (4 cases, none elsewhere), reverting the P3 fix still fails the relative-name test and now the new one; removing only isabs stays green because abspath(name) == name already implies an absolute name (an equivalent mutant, so isabs remains for readability). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Cover the managed-config path rule under ntpath on every host The command center's note on landing #967: the most useful P3 is a CI-run test that patches the module's os with ntpath, so the Windows side of the check is covered under Python 3.12, the CI interpreter. os.path is posixpath on a POSIX host, so until now the Windows clauses of _readable_system_file were argued from ntpath's functions and never executed. ManagedMcpDefaultLocations.test_the_windows_path_rules_count_the_windows_string_and_not_the_posix_ones replaces the module's os, for the test only, with a namespace whose isabs and abspath are ntpath's and whose file checks answer yes, so the path rule alone decides: the Windows documented string drops --strict-mcp-config, the macOS and Linux strings do not (under 3.12 ntpath.isabs accepts a leading separator and only the equality rejects them; from 3.13 isabs rejects them first), and a dot-dot, dot, forward-slash and doubled-separator spelling of the Windows string, a relative name and a drive-relative name each keep every fence. One accepted candidate among rejected ones decides the form, by parameter and by the default route. Source-level mutants of _readable_system_file, run in the module's own globals so the mutated body sees the swapped os (research record, pr925/p3-source-mutations-*): removing only the normalisation equality fails the new test on 3.12 and 3.13 (the four non-normalised Windows spellings, plus the macOS and Linux strings on 3.12) and the POSIX-side test added in the previous commit; removing only isabs fails it through the drive-relative name, because ntpath's pure-Python abspath on a POSIX host leaves "C:managed-mcp.json" equal to itself (the Windows abspath resolves it, so there isabs is belt and braces); reverting to the presence-only check of #925 fails the POSIX and Windows tests. The harness of the earlier mutation tables replaced the whole function and would not see a swapped os, so these supersede it for this test. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.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.
Scope
skill_doctor_argvintools/skill-usage/skill_usage.pynow counts a managed-config candidate only when it is absolute and already normalised under the host's own path rules, so on POSIX a readable file literally namedC:\Program Files\ClaudeCode\managed-mcp.jsonin the working directory no longer drops--strict-mcp-configwhile the client sees no managed config (the P3 of the co-op's GPT reads of Fence the headless /skill-doctor run #925 at46cc5dd1and715229c7, found first by the command center's micro of46cc5dd1).tests.test_skill_usage.ManagedMcpDefaultLocations, added by Fence the headless /skill-doctor run #925, is narrowed as Fence the headless /skill-doctor run #925 declared: a documented string is a location only where it is an absolute path, so the Windows cases run onnthosts and the Windows string is asserted inert on POSIX.e1c88ff3d7edc71052d6fb4eed8422438b06efaf(main with Fence the headless /skill-doctor run #925 landed, 2026-10-10T14:03:40Z); one commit,3de3dda86d6dbd5abeb4b5d7187f46892440b9c6, replayed onto it from the follow-up prepared on Fence the headless /skill-doctor run #925's head715229c72(no conflict).lane:foundationtools/skill-usage/skill_usage.py(_readable_system_file, the check inskill_doctor_argv, the comment),tests/test_skill_usage.py(the planted-file regression, the comment assertions, the narrowedManagedMcpDefaultLocations),docs/decisions/2026-10-04-pwsh7-windows-guidance.md(one shifted line locator, now 2432-2438),manifests/evidence.json(re-registration of the three).Follows #925: the agreed follow-up for its deferred P3. Nothing here changes a setting, a hook or a host.
SOTA sources
46cc5dd1(finding 2, verdict sha256da3470f5…) and at715229c7(finding 1, verdict sha2562cf30652…): in a POSIX temporary directory a readable file with the Windows path as its literal name, holding malformed JSON, made the default helper omit--strict-mcp-config, withPath(...).is_absolute()false. The command center's micro of46cc5dd1found it first.24972e3bc859fab2b46ed4c1e51f7d6130f06d3bd550811a114640de3370d0de, read 2026-10-10):My()at byte 209080002 returns/Library/Application Support/ClaudeCodeon macOS,C:\Program Files\ClaudeCodeon Windows and/etc/claude-codeotherwise, so each documented string is a location only on its own platform; the reader and refusal at bytes 217796118 and 217799919 are cited in Fence the headless /skill-doctor run #925.posixpaththe two POSIX strings are absolute and unchanged byabspathand the Windows string is neither; underntpaththe Windows string is absolute and unchanged, and the POSIX strings are not (3.13) or are changed byabspath(3.12, whereisabsaccepts a leading separator). The check is therefore absolute andabspath(name) == name. Run withntpathon this POSIX host, not on a Windows host.Evidence-class table
managed-mcp.json, in the working directory keep every fence; the same test fails on main's codelocal_integrationtests.test_skill_usage.RunSkillDoctor.test_a_relative_file_named_like_a_managed_path_is_not_a_managed_config. This head'sRunSkillDoctorandManagedMcpDefaultLocationsclasses run against main'sskill_usage.py(e1c88ff3) fail 4: that test, the comment test and the two Windows cases of the narrowed matrix; at this head 0 failsource_reviewtest_the_managed_mcp_comment_and_guide_cite_the_client_and_the_docsholds both (it fails on main's comment)ntthe reverse (ntpath rules on 3.12.3 and 3.13.16, not run on Windows)local_integration(POSIX host),source_review(nt)ManagedMcpDefaultLocations.test_a_documented_string_counts_only_where_it_is_an_absolute_path; the other cases usecounts_hereand the host's own locationsRunSkillDoctor1, 1 and 3 tests; the narrowed class 2 cases, 0 and 10), as are each POSIX location ignored or misspelled, all detection off,anytoall, no readability check, no regular-file check, the strict flag never or always dropped and a bypassed default route. Not caught, by construction: ignoring or misspelling the Windows location, which are equivalent mutants on POSIX because the string never counts there; they fail only on annthostlocal_integration(mutation harness; nothing on disk changes)mutations_p3.py, table retained in the lane's research record (pr925/p3-mutations-20261010.txt)tools/skill-usage/skill_usage.py, counted by newlinesource_reviewtests.test_skill_usagetest_the_windows_decision_cites_the_ledger_refusal_lines, which fails on the earlier locatorDeclared test contract change
Two main test methods, both from #925, fail against this head by design, because their Windows present cases expect the strict flag dropped for the Windows string on POSIX, the behaviour this PR corrects:
tests.test_skill_usage.ManagedMcpDefaultLocations.test_each_documented_location_decides_the_form_alone(the Windowsparsedandunparsablecases) andtest_dropping_a_locations_detection_fails_its_cases(thestill_seen='Windows'cases when macOS or Linux is dropped). Main'stests/test_skill_usage.pyrun against this head: 215 run, 4 failing cases in exactly those two methods, 19 skipped. At this head the module has 217 tests and passes.Local commands run
The local full-suite shards in a CI-like environment are noisy on this host (four of eight red at the CI-green #925 head on tests no change touches: user-site packages in
tests.test_token_e2e_grader, interrupt tests intests.test_new_wsl_mcp_conformance_lifecycleandtests.test_adoption_version_probes, the launchd matrix intests.test_adoption_launchd, the zizmor push-gate test and the credential-race worktree precondition; shard 4 did not report), so the commands above are the targeted lists and CI's eight shards are the full-suite measurement.Decision record
No new record: this corrects the #925 check and follows the
2026-10-04-pwsh7-windows-guidancerecord's locator, which moved with the added lines.Host evidence
Not applicable: no file under
evidence/hosts/changes.Checklist
permissions: {}and grant each job only what it needs. (none changed)🤖 Generated with Claude Code