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:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user