* test(#2755): failing-first coverage for per-runtime kimi hooks root Install/uninstall filesystem-shape rows over a sandbox HOME (no permission tricks) plus resolver unit rows. Covers both uninstall directions, which is where a fix applied only to the install call site would drift. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(#2755): resolve the kimi hooks-TOML root per runtime resolveKimiHooksTomlDir took no runtime argument and hardcoded ~/.kimi, but both kimi and kimi-code route through the single hooksSurface=kimi-hooks-toml branch. A --kimi-code install therefore wrote its [[hooks]] block, hook bundle and CommonJS marker into Kimi CLI's config file, and a --kimi-code uninstall stripped Kimi CLI's block. Adds a runtime selector to the resolver -- kimi keeps ~/.kimi + KIMI_SHARE_DIR, kimi-code gets ~/.kimi-code + KIMI_CODE_HOME, per Kimi Code's own upstream data-locations and hooks docs -- and passes the runtime at both the install and uninstall call sites. An omitted or unrecognized runtime still resolves ~/.kimi, so the exported no-arg contract is unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test(#2755): use centralized helpers and add a divergence guard Review findings, all fixed in-PR: - The new test block reimplemented runMinimalInstall, createTempDir and toPosixPath. Extends runMinimalInstall with optional root/extraEnv instead (back-compat: every existing caller passes neither) and uses the centralized helpers, per CONTRIBUTING's Use Centralized Test Helpers rule. - Adds a parity assertion between the capability registry and the resolver: a third runtime declaring hooksSurface kimi-hooks-toml would silently inherit ~/.kimi, re-creating this very defect. The guard fires the moment those two surfaces drift. - Adds an installer-level test proving KIMI_SHARE_DIR and KIMI_CODE_HOME do not interfere when both are set, which only the resolver unit covered before. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test(#2755): track the kimi-code hooks root in the emitted-artifact gates The remote runner caught a real ripple: moving kimi-code hooks to ~/.kimi-code made 31 emitted paths unattributable and 58 emitted hashes unexplained, because three parallel surfaces keyed on the literal .kimi path. - HOOK_CONFIG_RELATIVE_PATHS excluded only .kimi/config.toml, so kimi-code's config.toml became manifest-visible; it embeds a platform-varying node-runner command and must stay out for both products. - HOOKS_ROOTS, the package.json-marker branch and the synthesized-install-metadata pattern each named .kimi only. - tests/fixtures/install-tree/kimi-code.json still recorded the old paths; regenerated via gen:install-tree. Adds the per-PR drift acknowledgment for the 58 paths whose bytes are unchanged but whose destination moved - a ripple no source diff can show, since no hook script was edited. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(#2755): clear production-tree security advisories The remote runner's npm-integrity gate reported 2 high advisories in the production dependency tree. My diff touches neither package.json nor package-lock.json, so these come from the base -- but a red gate is not something to wave off as pre-existing, so it is fixed here rather than deferred. Lockfile-only, semver-in-range, via npm audit fix: fast-uri 3.1.4 -> 3.1.5 (host confusion via backslash authority introducer) ip-address 10.2.0 -> 10.4.0 (three SSRF / trust-boundary bypasses) hono 4.12.31 -> 4.13.0 (moderate; reverting it traded a high for a moderate, so the full remedy is taken) npm audit now reports 0 vulnerabilities at every severity, npm ci installs clean from the updated lockfile, and the build and the kimi behavior both re-verified afterwards. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore(#2755): backfill changeset pr numbers Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -55,6 +55,16 @@ export interface ResolveKimiOpts {
|
||||
existsSync?: (p: string) => boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for `resolveKimiHooksTomlDir`. Separate from `ResolveKimiOpts` so the
|
||||
* `runtime` selector is not implied to affect `resolveKimiGlobalDir`, which
|
||||
* resolves the generic Agent-Skills root and is runtime-independent.
|
||||
*/
|
||||
export interface ResolveKimiHooksTomlOpts extends ResolveKimiOpts {
|
||||
/** Runtime id — `kimi` (default) or `kimi-code`. See #2755. */
|
||||
runtime?: string;
|
||||
}
|
||||
|
||||
export interface ResolveConfigHomeOpts {
|
||||
env?: Record<string, string | undefined>;
|
||||
home?: string;
|
||||
@@ -370,28 +380,45 @@ export function resolveKimiGlobalDir(opts: ResolveKimiOpts = {}): string {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the directory holding Kimi CLI's OWN native config.toml (the file
|
||||
* Kimi itself reads for providers/models/hooks/etc — see
|
||||
* moonshotai.github.io/kimi-cli/en/configuration/data-locations.html and
|
||||
* .../reference/kimi-command.html). Default `~/.kimi`, overridden by
|
||||
* `KIMI_SHARE_DIR` per Kimi's own upstream env-var (NOT `KIMI_CONFIG_DIR`,
|
||||
* which is a GSD-installer write-location override for the unrelated generic
|
||||
* Agent-Skills root resolved by resolveKimiGlobalDir above).
|
||||
* Resolve the directory holding the Kimi product's OWN native config.toml —
|
||||
* the file that product itself reads for providers/models/hooks/etc, and the
|
||||
* one GSD writes its `[[hooks]]` block, hooks bundle and CommonJS marker into.
|
||||
*
|
||||
* This is deliberately a SEPARATE directory from GSD's kimi configHome
|
||||
* (~/.config/agents): Kimi's own docs confirm the Agent-Skills search path is
|
||||
* independent of KIMI_SHARE_DIR ("This variable does not affect Agent Skills
|
||||
* search paths, which are handled separately"). #2095 Upgrade 1 writes GSD's
|
||||
* native [[hooks]] entries into `<this dir>/config.toml`, never into the
|
||||
* skills configDir.
|
||||
* The two Kimi runtimes share `hooksSurface: "kimi-hooks-toml"` but are
|
||||
* different products with different roots, and this must be selected by
|
||||
* `runtime` (#2755). Before that fix this function was unparameterized and a
|
||||
* `--kimi-code` install wrote its hooks into Kimi CLI's `~/.kimi`, leaving Kimi
|
||||
* Code with none:
|
||||
*
|
||||
* kimi → `~/.kimi`, overridden by `KIMI_SHARE_DIR`
|
||||
* (moonshotai.github.io/kimi-cli/en/configuration/data-locations.html)
|
||||
* kimi-code → `~/.kimi-code`, overridden by `KIMI_CODE_HOME`
|
||||
* (moonshotai/kimi-code docs/en/configuration/data-locations.md;
|
||||
* its hooks doc places `[[hooks]]` in `~/.kimi-code/config.toml`)
|
||||
*
|
||||
* Each product's env var is scoped to that product: `KIMI_SHARE_DIR` is Kimi
|
||||
* CLI's own upstream variable and must NOT redirect kimi-code, nor vice versa.
|
||||
*
|
||||
* An unrecognised `runtime` (and an omitted one) falls back to `~/.kimi`, which
|
||||
* preserves the pre-#2755 behaviour for every existing caller that passes no
|
||||
* runtime — this function is exported, so that default is a contract.
|
||||
*
|
||||
* For BOTH runtimes this is deliberately a SEPARATE directory from the generic
|
||||
* Agent-Skills root resolved by `resolveKimiGlobalDir` (`~/.config/agents`):
|
||||
* both vendors' docs confirm the Agent-Skills search path is independent of the
|
||||
* data-root env var. GSD's native `[[hooks]]` entries go in
|
||||
* `<this dir>/config.toml`, never into the skills configDir.
|
||||
*/
|
||||
export function resolveKimiHooksTomlDir(opts: ResolveKimiOpts = {}): string {
|
||||
export function resolveKimiHooksTomlDir(opts: ResolveKimiHooksTomlOpts = {}): string {
|
||||
const env: Record<string, string | undefined> = opts.env ?? process.env;
|
||||
const home = opts.home ?? os.homedir();
|
||||
return resolveConfigHomeFromDescriptor(
|
||||
{ kind: 'dot-home', name: '.kimi', env: ['KIMI_SHARE_DIR'] },
|
||||
{ env, home },
|
||||
);
|
||||
// Explicit comparison rather than an object lookup keyed on `runtime`: the
|
||||
// value originates from argv, and an index would resolve inherited keys
|
||||
// (`constructor`, `__proto__`) to something that is not a descriptor.
|
||||
const descriptor: DotHomeDescriptor = opts.runtime === 'kimi-code'
|
||||
? { kind: 'dot-home', name: '.kimi-code', env: ['KIMI_CODE_HOME'] }
|
||||
: { kind: 'dot-home', name: '.kimi', env: ['KIMI_SHARE_DIR'] };
|
||||
return resolveConfigHomeFromDescriptor(descriptor, { env, home });
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user