397777089e
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
41 lines
1.4 KiB
JavaScript
41 lines
1.4 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Glob F8 post-execution filter (router-gate v4 Stream C, spec §5.2 F8 closure).
|
|
*
|
|
* Pure: the consumer hook expands the glob (glob.sync) and passes the already-
|
|
* matched path array here. We strip paths that live under a /restricted/ segment
|
|
* (e.g. subagent-block files the controller must not read) or whose inode is in
|
|
* the protectedInodes Set (injected). No `glob` npm dependency in this module.
|
|
*/
|
|
|
|
const RUNTIME_RE = /[~/\\]\.claude[/\\]runtime[/\\]/;
|
|
const DOUBLE_STAR_RE = /\*\*/;
|
|
|
|
/**
|
|
* True when an incoming Glob pattern targets ~/.claude/runtime with a ** wildcard
|
|
* and therefore must be post-filtered.
|
|
* @param {string} pattern
|
|
*/
|
|
export function globNeedsFilter(pattern) {
|
|
if (typeof pattern !== 'string') return false;
|
|
return RUNTIME_RE.test(pattern) && DOUBLE_STAR_RE.test(pattern);
|
|
}
|
|
|
|
/**
|
|
* Filter an already-expanded glob match list.
|
|
* @param {string[]} matches
|
|
* @param {{isProtectedInode?: (path: string) => boolean}} [deps]
|
|
* @returns {string[]}
|
|
*/
|
|
export function filterRestrictedMatches(matches, deps = {}) {
|
|
if (!Array.isArray(matches)) return [];
|
|
const isProtectedInode = typeof deps.isProtectedInode === 'function' ? deps.isProtectedInode : () => false;
|
|
return matches.filter((m) => {
|
|
if (typeof m !== 'string') return false;
|
|
const norm = m.replace(/\\/g, '/');
|
|
if (norm.includes('/restricted/')) return false;
|
|
if (isProtectedInode(m)) return false;
|
|
return true;
|
|
});
|
|
}
|