refactor(#2665): derive the guard's non-root targets from the descriptor array too

Follow-up to 38c9395d, found while fact-checking the round-3 response rather
than by a test.

That commit made TEST_ENV_BASE derive its keys from
NON_REGISTRY_CONFIG_HOME_DESCRIPTORS, but had the guard call
resolveKimiHooksTomlDir directly. Both halves covered kimi, so nothing was
broken — but only one of them would pick up a SECOND descriptor. That is the
same partial-enumeration defect that put KIMI_SHARE_DIR outside the scrub set,
reintroduced one layer over, in the very commit that closed it.

resolveExtraWatchTargets now iterates the array and resolves each descriptor
through resolveConfigHomeFromDescriptor, so the scrub set and the guard derive
from one source and cannot drift apart.

Verified: a synthetic second descriptor is picked up automatically (it was not
before); kimi's target is unchanged on both the default (~/.kimi/config.toml)
and KIMI_SHARE_DIR override paths.

The new test asserts one target per descriptor plus the store root. The COUNT
is the load-bearing half — every per-descriptor assertion passes vacuously
today with a single entry, so only the count fails when the array grows and the
guard does not follow.

NAMED RESIDUAL, documented at NON_REGISTRY_OWNED_FILE: this assumes every
non-registry descriptor is written the same way (config.toml). A descriptor
whose owned file differs needs a per-descriptor mapping. It fails toward
under-watching rather than false positives, so it is called out rather than
left to be discovered.
This commit is contained in:
0xdhx
2026-08-01 03:14:21 -05:00
parent fb02fa5722
commit 706bd2ab4e
2 changed files with 67 additions and 6 deletions

View File

@@ -196,6 +196,39 @@ describe('#2665: guard watches non-root write surfaces', () => {
}
});
test('extra targets are DERIVED from the descriptor array, not a named resolver', () => {
const {
NON_REGISTRY_CONFIG_HOME_DESCRIPTORS,
resolveConfigHomeFromDescriptor,
} = require('../gsd-core/bin/lib/runtime-homes.cjs');
const home = tmpRoot();
try {
const env = { GSD_HOME: home };
const targets = resolveExtraWatchTargets({ env, os: { homedir: () => home } });
// Every descriptor in the array must contribute a target. Calling one
// named resolver instead would cover today's single entry and silently
// miss tomorrow's — the same partial-enumeration defect that put
// KIMI_SHARE_DIR outside the scrub set, one layer over.
for (const d of NON_REGISTRY_CONFIG_HOME_DESCRIPTORS) {
const dir = resolveConfigHomeFromDescriptor(d, { env, home });
assert.ok(
targets.includes(path.resolve(path.join(dir, 'config.toml'))),
`descriptor ${JSON.stringify(d.env)} contributed no watch target`,
);
}
// The count is what actually catches a regression to a hardcoded call:
// it fails the moment the array grows and the guard does not follow.
assert.strictEqual(
targets.length,
1 + NON_REGISTRY_CONFIG_HOME_DESCRIPTORS.length,
'expected the GSD store root plus exactly one target per descriptor',
);
} finally {
cleanup(home);
}
});
test('GSD_HOME falls back to homedir when unset', () => {
const home = tmpRoot();
try {