You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Discovery no longer reads a file a project reaches outside its own tree
A class-B file that a project reaches outside the project, the project's own memory store and its ancestor governance is now sized by stat only and never read. Nothing is removed from the plugin and no command or config key changes. The installed plugin moved: scripts/lib/class-b.mjs and scripts/lib/caliper.mjs with their plugin/ twins, and the version in plugin.json (git diff --stat 49eb079 HEAD -- plugin/scripts/lib/ lists the two libraries before the bump: 94 insertions, 8 deletions).
Security
A file the project's class-B governance reaches OUTSIDE the project, the project's own memory store and its ancestor governance is no longer read (CWK2-029 (b), the read half). The cases: a @~/... import such as @~/.aws/credentials, a @../ escape, a @~/.claude/... file other than the project's own memory store (such as .credentials.json or settings.json), a file inside an ancestor folder that is not that folder's CLAUDE.md (a @../sibling/file), an import held by a clone's own top CLAUDE.md when the session root is a nested folder of the clone (such as a package folder holding its own CLAUDE.md), a project CLAUDE.md that is a link to a file elsewhere, and a memory-store file whose real path leaves through a link or junction. Before, such a file was listed as the project's own governance (scope project), and its content was read for further @ imports and for the certain-fat count. Now discoverClassB (the OUTSIDE branch in add()) puts it in inherited with scope outside and statOnly, takes its bytes from stat, never follows its imports, never puts it in entries (so the conductor, the wizard and every wash target never see it), and names it in one flag, outside the project, its own memory store and its ancestor governance (<kind>): <path> — sized by stat only, never read, never washed (a path only, never content; the path reads ~/... under your home folder). measureEntries in caliper.mjs never reads a statOnly entry, whatever the read budget or scanEverything says, not even a memory index for its line count. For a file the project itself reaches, location decides; the imports of an ancestor CLAUDE.md keep the ancestor's wider reach. What a user sees: a project whose CLAUDE.md imports ~/notes.md now shows a smaller footprint, because the import closure behind that file is no longer measured, and one new flag. Scope: the user's own global ~/.claude chain keeps its reach; an ancestor CLAUDE.md above the project's repository top (the nearest folder at or above the project root that holds a .git entry, read by lstat and never followed) and its own @import closure (inside its folder, ~/.claude or another ancestor folder) stay in the inherited tier and are read as before; the project's own memory store is admitted only while its real path stays inside ~/.claude (a store linked or junctioned out is outside); a file the project itself names inside ~/.claude (other than its own memory store) or inside an ancestor folder (other than that folder's CLAUDE.md) is OUTSIDE. A CLAUDE.md between the session folder and that top is the clone's own: it is read, and its imports follow the project's rule, so a file it imports from elsewhere in the clone, outside the session folder, is outside (an undercount, the safe direction). Named residual, not closed: with no .git entry up to the home folder, the walk starts above the session folder as before; the same holds where the nearest .git is a file git wrote for a submodule, so a session opened inside a submodule of a cloned superproject gives that superproject's CLAUDE.md the ancestor reach. The home folder itself never counts as an ancestor folder. Named residual, not closed: a project file HARD-LINKED to a file in your home folder is not seen by this rule, because its real path is its own project path, so its content is still read; the write half stays safe (in the witness for the hard-link case, after a write the project entry is a single-link file and the home file is unchanged). — test: scripts/lib/class-b.test.mjs, CWK2-029 (b): a plain project CLAUDE.md @import of a HOME file outside ~/.claude is OUTSIDE: never read, never scope project, sized by stat, flagged, CWK2-029 (b): a memory store that is a directory JUNCTION to a HOME folder outside ~/.claude puts nothing in entries and reads nothing (skips visibly where a junction cannot be made), CWK2-029 (b): a project CLAUDE.md that is a SYMLINK to a HOME file is OUTSIDE, never read (skips visibly where a file symlink cannot be made), CWK2-029 (b) control: an ANCESTOR governance file and its own-folder @import stay the inherited tier and ARE read; a ~/.claude import from an ANCESTOR's closure is not OUTSIDE, CWK2-029 (b): an ANCESTOR CLAUDE.md that is a SYMLINK out of its folder is not ancestor governance: its target is OUTSIDE (skips visibly where a file symlink cannot be made), INSPECT 99 L99-1: a project @import of a file in ~/.claude that is not the project's own memory store is OUTSIDE: never read, never scope project, flagged, INSPECT 99 L99-3: a file the PROJECT reaches inside an ancestor folder is OUTSIDE unless it is the ancestor CLAUDE.md itself; the ancestor's own @import closure stays read, RE-INSPECT 102 R102-1: a clone's own top CLAUDE.md above a nested session root keeps the room rule: its ~/.claude/.credentials.json import is OUTSIDE, never read, RE-INSPECT 102 R102-1 pin: the house shape, a room with its own .git under an ancestor folder with its own .git and a CLAUDE.md importing @AGENTS.md, keeps the ancestor closure read, RE-INSPECT 102 R102-1 residual (named, not closed): with no .git up to HOME, a CLAUDE.md above a nested session root is still an ancestor and its ~/.claude import is read and RE-INSPECT 102 R102-1: the .git entry that marks the repository top is read by lstat, never followed: a dangling .git link still marks the top (skips visibly where a dangling junction cannot be made). On the box that wrote this, the plain-import test, the junction test (its gauge assertion too: the memory index is not read for its lines), the control, the two INSPECT 99 tests and the four RE-INSPECT 102 tests (the dangling-junction leg included, because a dangling junction can be made there) run; the two file-symlink tests skip (a file symlink needs a privilege that account lacks) and have not been observed anywhere yet: they belong to the POSIX CI legs.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Discovery no longer reads a file a project reaches outside its own tree
A class-B file that a project reaches outside the project, the project's own memory store and its ancestor governance is now sized by stat only and never read. Nothing is removed from the plugin and no command or config key changes. The installed plugin moved:
scripts/lib/class-b.mjsandscripts/lib/caliper.mjswith theirplugin/twins, and the version inplugin.json(git diff --stat 49eb079 HEAD -- plugin/scripts/lib/lists the two libraries before the bump: 94 insertions, 8 deletions).Security
@~/...import such as@~/.aws/credentials, a@../escape, a@~/.claude/...file other than the project's own memory store (such as.credentials.jsonorsettings.json), a file inside an ancestor folder that is not that folder'sCLAUDE.md(a@../sibling/file), an import held by a clone's own topCLAUDE.mdwhen the session root is a nested folder of the clone (such as a package folder holding its ownCLAUDE.md), a projectCLAUDE.mdthat is a link to a file elsewhere, and a memory-store file whose real path leaves through a link or junction. Before, such a file was listed as the project's own governance (scopeproject), and its content was read for further@imports and for the certain-fat count. NowdiscoverClassB(the OUTSIDE branch inadd()) puts it ininheritedwith scopeoutsideandstatOnly, takes its bytes fromstat, never follows its imports, never puts it inentries(so the conductor, the wizard and every wash target never see it), and names it in one flag,outside the project, its own memory store and its ancestor governance (<kind>): <path> — sized by stat only, never read, never washed(a path only, never content; the path reads~/...under your home folder).measureEntriesincaliper.mjsnever reads astatOnlyentry, whatever the read budget orscanEverythingsays, not even a memory index for its line count. For a file the project itself reaches, location decides; the imports of an ancestorCLAUDE.mdkeep the ancestor's wider reach. What a user sees: a project whoseCLAUDE.mdimports~/notes.mdnow shows a smaller footprint, because the import closure behind that file is no longer measured, and one new flag. Scope: the user's own global~/.claudechain keeps its reach; an ancestorCLAUDE.mdabove the project's repository top (the nearest folder at or above the project root that holds a.gitentry, read bylstatand never followed) and its own@importclosure (inside its folder,~/.claudeor another ancestor folder) stay in the inherited tier and are read as before; the project's own memory store is admitted only while its real path stays inside~/.claude(a store linked or junctioned out is outside); a file the project itself names inside~/.claude(other than its own memory store) or inside an ancestor folder (other than that folder'sCLAUDE.md) is OUTSIDE. ACLAUDE.mdbetween the session folder and that top is the clone's own: it is read, and its imports follow the project's rule, so a file it imports from elsewhere in the clone, outside the session folder, is outside (an undercount, the safe direction). Named residual, not closed: with no.gitentry up to the home folder, the walk starts above the session folder as before; the same holds where the nearest.gitis a file git wrote for a submodule, so a session opened inside a submodule of a cloned superproject gives that superproject'sCLAUDE.mdthe ancestor reach. The home folder itself never counts as an ancestor folder. Named residual, not closed: a project file HARD-LINKED to a file in your home folder is not seen by this rule, because its real path is its own project path, so its content is still read; the write half stays safe (in the witness for the hard-link case, after a write the project entry is a single-link file and the home file is unchanged). — test:scripts/lib/class-b.test.mjs,CWK2-029 (b): a plain project CLAUDE.md @import of a HOME file outside ~/.claude is OUTSIDE: never read, never scope project, sized by stat, flagged,CWK2-029 (b): a memory store that is a directory JUNCTION to a HOME folder outside ~/.claude puts nothing in entries and reads nothing (skips visibly where a junction cannot be made),CWK2-029 (b): a project CLAUDE.md that is a SYMLINK to a HOME file is OUTSIDE, never read (skips visibly where a file symlink cannot be made),CWK2-029 (b) control: an ANCESTOR governance file and its own-folder @import stay the inherited tier and ARE read; a ~/.claude import from an ANCESTOR's closure is not OUTSIDE,CWK2-029 (b): an ANCESTOR CLAUDE.md that is a SYMLINK out of its folder is not ancestor governance: its target is OUTSIDE (skips visibly where a file symlink cannot be made),INSPECT 99 L99-1: a project @import of a file in ~/.claude that is not the project's own memory store is OUTSIDE: never read, never scope project, flagged,INSPECT 99 L99-3: a file the PROJECT reaches inside an ancestor folder is OUTSIDE unless it is the ancestor CLAUDE.md itself; the ancestor's own @import closure stays read,RE-INSPECT 102 R102-1: a clone's own top CLAUDE.md above a nested session root keeps the room rule: its ~/.claude/.credentials.json import is OUTSIDE, never read,RE-INSPECT 102 R102-1 pin: the house shape, a room with its own .git under an ancestor folder with its own .git and a CLAUDE.md importing @AGENTS.md, keeps the ancestor closure read,RE-INSPECT 102 R102-1 residual (named, not closed): with no .git up to HOME, a CLAUDE.md above a nested session root is still an ancestor and its ~/.claude import is readandRE-INSPECT 102 R102-1: the .git entry that marks the repository top is read by lstat, never followed: a dangling .git link still marks the top (skips visibly where a dangling junction cannot be made). On the box that wrote this, the plain-import test, the junction test (its gauge assertion too: the memory index is not read for its lines), the control, the two INSPECT 99 tests and the four RE-INSPECT 102 tests (the dangling-junction leg included, because a dangling junction can be made there) run; the two file-symlink tests skip (a file symlink needs a privilege that account lacks) and have not been observed anywhere yet: they belong to the POSIX CI legs.Release page · CoalWash
All reactions