fix(watch): run the orchestrator with the watched project as cwd

PLAN § v8.1.3 punkt 5. watch-cron.mjs started the orchestrator with
cwd = pluginRoot, so every watched project was outside cwd, i.e. not the
caller's own working tree, and its .llm-security-ignore / policy.json
were dropped: the user saw findings they had already suppressed. The
orchestrator now runs with cwd = the target dir (its parent for a file);
a relative target.path still resolves against pluginRoot as before.

The scope test's entropy blob is now fixed instead of random: one run
with a random blob reported zero findings for both projects, probably a
blob starting with `/` (skipped as a path, 1 in 64). Red on 002c0ba with
the fixed blob, verified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-23 11:34:55 +02:00
commit 62e3cade60
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
2 changed files with 25 additions and 4 deletions

View file

@ -32,7 +32,14 @@ const ORCHESTRATOR = join(PLUGIN_ROOT, 'scanners', 'scan-orchestrator.mjs');
const LATEST = join(PLUGIN_ROOT, 'reports', 'watch', 'latest.json');
// Not a real credential — a known-positive blob for the entropy scanner only.
const HIGH_ENTROPY_BLOB = crypto.randomBytes(72).toString('base64');
// Fixed, not random: a random blob starts with `/` one time in 64, and the
// entropy scanner skips a string that starts with `/` as a path. One run of
// this test with a random blob reported zero findings for both projects; that
// cause is the probable one, not a proven one (the blob was not logged).
const HIGH_ENTROPY_BLOB = Buffer.concat([
crypto.createHash('sha512').update('watch-cron-scope-1').digest(),
crypto.createHash('sha512').update('watch-cron-scope-2').digest(),
]).subarray(0, 72).toString('base64');
function writeProject(dir, { withIgnore }) {
mkdirSync(dir, { recursive: true });