ccsniff 1.1.15 → 1.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cli.js +32 -4
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -380,6 +380,26 @@ if (opts['git-discipline']) {
|
|
|
380
380
|
if (opts['search-discipline']) {
|
|
381
381
|
const includeSubagents = opts['include-subagents'];
|
|
382
382
|
const BASH_SEARCH = /(^|[|&;]|\s)(rg|grep|find|ag|ack|fd|fgrep|egrep)\s/;
|
|
383
|
+
// A search-tool token inside a quoted string (echo/printf/node -e payloads) is text, not a shell
|
|
384
|
+
// invocation; blank quoted bodies before matching, like git-discipline strips commit-message bodies.
|
|
385
|
+
const stripQuoted = (s) => s.replace(/"(?:\\.|[^"\\])*"/g, '""').replace(/'(?:\\.|[^'\\])*'/g, "''");
|
|
386
|
+
// codesearch indexes ONLY the conversation's own cwd (the gm repo). A search whose target is a
|
|
387
|
+
// sibling repo outside cwd has NO codesearch index to route through, so the agent is forced to
|
|
388
|
+
// native search and flagging it is a false positive. Exempt a line that targets an absolute path
|
|
389
|
+
// or cd's into a directory that is not under the conversation cwd.
|
|
390
|
+
const normPath = (p) => String(p || '').replace(/\\/g, '/').replace(/\/+$/, '').toLowerCase();
|
|
391
|
+
const targetsOutsideCwd = (line, cwd) => {
|
|
392
|
+
const cwdN = normPath(cwd);
|
|
393
|
+
if (!cwdN) return false;
|
|
394
|
+
const stripped = stripQuoted(line);
|
|
395
|
+
// explicit `cd <dir>` to a path outside cwd
|
|
396
|
+
const cdM = stripped.match(/(?:^|[|&;]\s*)cd\s+([^\s|&;]+)/i);
|
|
397
|
+
if (cdM) { const d = normPath(cdM[1]); if (d.startsWith('/') || /^[a-z]:/.test(d)) { if (!d.startsWith(cwdN)) return true; } }
|
|
398
|
+
// absolute path argument to the search tool that is outside cwd
|
|
399
|
+
const absArgs = stripped.match(/(?:^|\s)((?:[a-z]:)?\/[^\s|&;"']+)/gi) || [];
|
|
400
|
+
for (const a of absArgs) { const d = normPath(a.trim()); if ((d.startsWith('/') || /^[a-z]:/.test(d)) && !d.startsWith(cwdN)) return true; }
|
|
401
|
+
return false;
|
|
402
|
+
};
|
|
383
403
|
const violations = [];
|
|
384
404
|
for (const ev of all) {
|
|
385
405
|
if (!filter(ev)) continue;
|
|
@@ -390,8 +410,14 @@ if (opts['search-discipline']) {
|
|
|
390
410
|
const ts = ev.timestamp, sid = ev.conversation?.id || '';
|
|
391
411
|
let kind = null, detail = '';
|
|
392
412
|
if (name === 'Grep' || name === 'Glob') {
|
|
393
|
-
|
|
394
|
-
|
|
413
|
+
// A Grep/Glob whose path points outside the cwd targets a sibling repo with no codesearch
|
|
414
|
+
// index — exempt it, same as a cross-repo bash search.
|
|
415
|
+
const gp = ev.block?.input?.path;
|
|
416
|
+
if (gp && targetsOutsideCwd(gp, ev.conversation?.cwd)) { /* cross-repo, exempt */ }
|
|
417
|
+
else {
|
|
418
|
+
kind = `native-search-${name.toLowerCase()}`;
|
|
419
|
+
detail = (ev.block?.input?.pattern || ev.block?.input?.query || '').slice(0, 120);
|
|
420
|
+
}
|
|
395
421
|
} else if (name === 'Task' || name === 'Agent') {
|
|
396
422
|
const sub = (ev.block?.input?.subagent_type || ev.block?.input?.description || '').toLowerCase();
|
|
397
423
|
if (/explore|search|general-purpose/.test(sub)) {
|
|
@@ -404,9 +430,11 @@ if (opts['search-discipline']) {
|
|
|
404
430
|
// not searching the codebase tree — codesearch has no equivalent for that and it is not the
|
|
405
431
|
// bypass the rule targets. Flag only a search tool that STARTS a pipeline segment (reads the
|
|
406
432
|
// tree directly), never one immediately downstream of a pipe.
|
|
407
|
-
const isTreeSearchLine = (line) => BASH_SEARCH.test(line.split('|')[0]);
|
|
433
|
+
const isTreeSearchLine = (line) => BASH_SEARCH.test(stripQuoted(line).split('|')[0]);
|
|
408
434
|
const hitLine = cmd.split('\n').find(isTreeSearchLine);
|
|
409
|
-
|
|
435
|
+
// Exempt a tree-search line that targets a sibling repo outside cwd (no codesearch index exists
|
|
436
|
+
// for it). Each command may `cd` first, so evaluate the cd context on the same line.
|
|
437
|
+
if (hitLine && !targetsOutsideCwd(hitLine, ev.conversation?.cwd)) {
|
|
410
438
|
kind = 'native-search-bash';
|
|
411
439
|
detail = (hitLine.split('|')[0]).trim().slice(0, 120);
|
|
412
440
|
}
|