docs(#2665): the guard's own comments still described one kimi home, not two

Same drift as the CONTEXT.md seams, one layer over: #2755 took
NON_REGISTRY_CONFIG_HOME_DESCRIPTORS from one entry to two, and five comments
across three files were left describing the one-entry world — "two live write
surfaces", "today's only entry", "today's single entry", and a <kimi>/config.toml
bullet naming only Kimi CLI's KIMI_SHARE_DIR.

The sharpest one was a wrong pointer rather than a stale count: run-tests.cjs
cited "scripts/lib/live-config-guard.cjs" for why the scope is narrow. That path
does not exist, and it names the one directory this module is deliberately NOT
in — the installer copies scripts/lib/ to users wholesale while uninstall removes
only an allowlist, which is the whole reason the guard lives one level up. A
reader following that pointer would have concluded the opposite of the decision.

Comments only; no behaviour change. lint:ci rc=0, tests/live-config-guard.test.cjs
24/24, tests/run-tests-harness.test.cjs 138/138.
This commit is contained in:
0xdhx
2026-08-05 07:10:09 -05:00
parent 664bab3b48
commit 12cfd27f53
3 changed files with 21 additions and 15 deletions

View File

@@ -142,22 +142,26 @@ function resolveLiveConfigRoots(deps = {}) {
* `root x GSD_OWNED_ENTRIES`.
*
* #2665 round 3: resolveLiveConfigRoots enumerates getGlobalConfigDir per registry
* runtime plus grok. Two live write surfaces are invisible to that shape, so a leak
* on either passed through this guard — the PR's own safety net — silently:
* runtime plus grok. A live write surface that is not a config ROOT is invisible to
* that shape, so a leak on one passed through this guard — the PR's own safety net —
* silently. There are THREE today ($GSD_HOME/.gsd, plus one config.toml per entry in
* NON_REGISTRY_CONFIG_HOME_DESCRIPTORS, which #2755 took from one entry to two):
*
* $GSD_HOME/.gsd — GSD's user-owned store (consent.json, defaults.json, capability
* overlays). Watched WHOLESALE: unlike ~/.claude this root is
* exclusively ours, so the shared-root false-positive trap in
* SCOPE above does not apply and an ownership filter would only
* narrow the guard for nothing.
* <kimi>/config.toml — the file GSD writes its native [[hooks]] block into
* (resolveKimiHooksTomlDir, KIMI_SHARE_DIR). The INVERSE case:
* ~/.kimi belongs to Kimi CLI, so only the one file GSD writes is
* <non-registry home>/config.toml — the file GSD writes its native [[hooks]] block
* into, one per NON_REGISTRY_CONFIG_HOME_DESCRIPTORS entry: Kimi
* CLI's ~/.kimi (KIMI_SHARE_DIR) and, since #2755, Kimi Code's
* ~/.kimi-code (KIMI_CODE_HOME). The INVERSE case: those roots
* belong to their products, so only the one file GSD writes is
* watched, never the root. This is the KNOWN GAP above accepted
* deliberately in one direction — GSD demonstrably writes this
* file (bin/install.js calls resolveKimiHooksTomlDir at two sites),
* so a concurrent Kimi CLI write is the only false positive, and
* Kimi is not running during the suite.
* deliberately in one direction — GSD demonstrably writes these
* files (bin/install.js resolves the hooks-toml dir at two sites),
* so a concurrent write by those products is the only false
* positive, and neither runs during the suite.
*
* @returns {string[]} absolute paths; empty if the built lib is absent.
*/
@@ -175,7 +179,7 @@ function resolveExtraWatchTargets(deps = {}) {
} = require(path.join(libDir, 'runtime-homes.cjs'));
// ITERATE the descriptor array rather than naming one resolver. Calling
// resolveKimiHooksTomlDir directly would cover today's only entry and
// resolveKimiHooksTomlDir directly would cover one of today's two entries and
// silently miss tomorrow's — the same partial-enumeration defect that put
// KIMI_SHARE_DIR outside the scrub set in the first place, reintroduced one
// layer over. TEST_ENV_BASE derives its keys from this array; deriving the

View File

@@ -975,15 +975,17 @@ function main() {
// #2665: snapshot GSD's install footprint in every LIVE runtime config dir
// before a single test runs. The suite must not write there; the check after
// the chunk loop is what makes a violation loud instead of silent. See
// scripts/lib/live-config-guard.cjs for why the scope is narrow.
// scripts/live-config-guard.cjs for why the scope is narrow (it is deliberately
// NOT under scripts/lib/, which the installer copies to users wholesale).
const liveConfigGuardEnabled = process.env.GSD_SKIP_LIVE_CONFIG_GUARD !== '1';
let liveConfigRoots = [];
let liveConfigExtras = [];
let liveConfigBefore = null;
if (liveConfigGuardEnabled) {
liveConfigRoots = resolveLiveConfigRoots();
// #2665 round 3: $GSD_HOME/.gsd and kimi's native config.toml are live write
// surfaces that are not runtime config ROOTS, so they are invisible to the
// #2665 round 3: $GSD_HOME/.gsd, and one native config.toml per non-registry
// config-home descriptor (Kimi CLI's and, since #2755, Kimi Code's), are live
// write surfaces that are not runtime config ROOTS, so they are invisible to the
// line above. Watched independently — and note the OR: the extras alone are
// reason enough to snapshot, so an unbuilt tree that yields zero roots no
// longer silently disables the whole guard.

View File

@@ -172,7 +172,7 @@ describe('#2665: live-config hermeticity guard', () => {
});
});
// ── Round 3: the two write surfaces that are not runtime config ROOTS ────────
// ── Round 3: the write surfaces that are not runtime config ROOTS ───────────
describe('#2665: guard watches non-root write surfaces', () => {
test('resolveExtraWatchTargets covers $GSD_HOME/.gsd and kimi config.toml', () => {
const home = tmpRoot();
@@ -207,7 +207,7 @@ describe('#2665: guard watches non-root write surfaces', () => {
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
// named resolver instead would cover one of today's two entries 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) {