From ec7c5a0181601a96a168d353bb775ceba82cae81 Mon Sep 17 00:00:00 2001 From: Daniil Koryto Date: Wed, 29 Apr 2026 17:18:02 +0300 Subject: [PATCH] fix: stop pre-blocking newer kilo versions --- AGENTS.md | 12 ++- CHANGELOG.md | 2 + README.md | 18 ++-- docs/README.md | 3 +- docs/gonkagate-x-kilo.md | 174 ++++++++++++++++++++++++++++++ docs/how-it-works.md | 16 +-- docs/readme-header-style.md | 2 +- docs/release-readiness.md | 15 ++- docs/troubleshooting.md | 8 +- docs/user-guide.md | 8 +- src/cli/parse.ts | 2 +- src/constants/contract.ts | 7 +- src/install/contracts.ts | 2 +- src/install/kilo.ts | 31 +++--- src/install/verification-notes.ts | 2 +- test/install/kilo.test.ts | 77 +++++++++++-- test/package-contract.test.ts | 4 + test/readme-contract.test.ts | 2 +- 18 files changed, 320 insertions(+), 65 deletions(-) create mode 100644 docs/gonkagate-x-kilo.md diff --git a/AGENTS.md b/AGENTS.md index 4354667..e850830 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -30,13 +30,14 @@ Current honest state: selection, while staying explicit that Kilo can recreate that cache later - the XDG-isolated oracle now mirrors user-level global Kilo config into the sandbox XDG config tree so project-scope verification matches the local - resolver on supported `@kilocode/cli@7.2.0` installs, and that temporary - sandbox now stages outside the repository with cleanup after verification + resolver on `@kilocode/cli >=7.2.0` installs, and that temporary sandbox now + stages outside the repository with cleanup after verification - the stock public build now ships `moonshotai/Kimi-K2.6` as the recommended validated curated default, with installer-managed `limit.output = 8192` for Kilo `7.2.0` compatibility -- exact support remains pinned to `@kilocode/cli@7.2.0`; later `7.2.x` - versions are not implied +- Kilo detection now accepts `@kilocode/cli >=7.2.0` without pre-blocking + future Kilo releases, while the audited compatibility baseline remains + `@kilocode/cli@7.2.0` - native Windows production support is not yet claimed because the native oracle-safety proof gate is still open - repository-side release automation is now checked in through @@ -84,7 +85,8 @@ These are repo-contract decisions, not casual refactors: - future `/v1/responses` support must be a migration, not a present claim - primary command: `kilo` - fallback alias: `kilocode` -- exact investigated Kilo compatibility profile: `@kilocode/cli@7.2.0` +- minimum accepted Kilo compatibility floor: `@kilocode/cli >=7.2.0` +- audited Kilo compatibility baseline: `@kilocode/cli@7.2.0` - Kilo runtime env vars: `KILO_CONFIG`, `KILO_CONFIG_DIR`, `KILO_CONFIG_CONTENT` - durable global target: `~/.config/kilo/kilo.jsonc` diff --git a/CHANGELOG.md b/CHANGELOG.md index f5ee52c..9994ded 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Accepted Kilo versions at or above `@kilocode/cli >=7.2.0` instead of + pre-blocking future Kilo releases with the previous `7.2.0`-only gate. - Promoted `moonshotai/Kimi-K2.6` to the recommended validated curated default, with installer-managed `limit.output = 8192` for Kilo `7.2.0` compatibility. diff --git a/README.md b/README.md index 354ab8f..f06e858 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ npx @gonkagate/kilo-setup ![Package](https://img.shields.io/badge/package-%40gonkagate%2Fkilo--setup-6E63FF?style=flat-square) ![Node](https://img.shields.io/badge/node-%3E%3D22.14.0-4DA2FF?style=flat-square) -![Kilo](https://img.shields.io/badge/kilo-7.2.0-35D6FF?style=flat-square) +![Kilo](https://img.shields.io/badge/kilo-%3E%3D7.2.0-35D6FF?style=flat-square) ![License](https://img.shields.io/badge/license-Apache--2.0-2A2A2A?style=flat-square) [![Website](https://img.shields.io/badge/Website-gonkagate.com-111827?style=flat-square)](https://gonkagate.com/en) @@ -52,7 +52,7 @@ What it does for you: What it does not do: - it does not install Kilo itself -- it does not claim support beyond exact `@kilocode/cli@7.2.0` +- it does not install or pin Kilo versions for you - it does not claim GonkaGate `responses` support today - it does not claim native Windows production support yet @@ -63,7 +63,7 @@ You need: - Node `>=22.14.0` - local `kilo` installed and available on `PATH`, or the fallback `kilocode` command -- local Kilo matching the exact investigated profile: `@kilocode/cli@7.2.0` +- local Kilo matching the minimum accepted floor: `@kilocode/cli >=7.2.0` - a GonkaGate API key in the usual `gp-...` format from the [dashboard](https://gonkagate.com/en/register) @@ -74,7 +74,7 @@ Current public baseline: - current transport target: `chat/completions` - curated default: `moonshotai/Kimi-K2.6` -- installer-managed `limit.output = 8192` for exact `@kilocode/cli@7.2.0` +- installer-managed `limit.output = 8192` for Kilo compatibility - no native Windows production claim yet ## Shortest Start Path @@ -90,7 +90,7 @@ npx @gonkagate/kilo-setup The installer will: 1. detect `kilo`, or fall back to `kilocode` -2. verify exact `@kilocode/cli@7.2.0` +2. verify local Kilo is at least `@kilocode/cli >=7.2.0` 3. show the curated model choice 4. choose the recommended scope automatically: - inside a git repository: `project` @@ -197,14 +197,16 @@ Scope rules: This repository intentionally stays narrow today: -- exact investigated compatibility profile: `@kilocode/cli@7.2.0` +- minimum accepted Kilo floor: `@kilocode/cli >=7.2.0` - current transport target: `chat/completions` - current curated default: `moonshotai/Kimi-K2.6` - real-path Kilo verification is not the production default - native Windows production support is not claimed yet -- later Kilo patch releases, unvalidated extra models, and new flows are not - implied just because this package exists +- future Kilo releases are not pre-blocked by version, but observed + compatibility breaks still need fixes +- unvalidated extra models and new flows are not implied just because this + package exists The shipped runtime treats effective Kilo config as the real success gate. It uses the local resolver as the durable verifier and keeps the XDG-isolated diff --git a/docs/README.md b/docs/README.md index d2279cd..7d3b194 100644 --- a/docs/README.md +++ b/docs/README.md @@ -24,4 +24,5 @@ Current contract documents: This repository ships the Kilo installer runtime with a validated curated Kimi K2.6 default, installer-managed `limit.output = 8192` for Kilo compatibility, -and support claims that stay pinned to exact `@kilocode/cli@7.2.0`. +and a minimum accepted Kilo floor of `@kilocode/cli >=7.2.0` without a preset +upper version bound. diff --git a/docs/gonkagate-x-kilo.md b/docs/gonkagate-x-kilo.md new file mode 100644 index 0000000..a859b0b --- /dev/null +++ b/docs/gonkagate-x-kilo.md @@ -0,0 +1,174 @@ +# GonkaGate x Kilo + +Hi everyone, + +We put together a small setup utility for Kilo: + +```bash +npx @gonkagate/kilo-setup +``` + +The goal is simple. If you already use `kilo` and already have a GonkaGate +API key, setup should take a minute or two. It should not turn into "open +three docs tabs, figure out where Kilo wants provider config, then hope you +didn't leave a secret in the repo by accident." + +That is what `@gonkagate/kilo-setup` is for. + +> Short version: this is a small CLI that wires local `kilo` to GonkaGate, +> keeps the secret out of repo-local config, and verifies the resolved result +> before sending you back to plain `kilo`. + +## Why we made it + +Manual provider setup is manageable once. It gets old fast after that. + +The annoying part is not the API itself. The annoying part is everything around +it: where the secret should live, which config layer should own what, whether +project config is safe to commit, and whether Kilo is actually using the +config you just wrote instead of something else from the current shell. + +We wanted a short path that does the boring work correctly and stays honest +about its limits. + +## The short version + +### Interactive + +```bash +npx @gonkagate/kilo-setup +``` + +### Non-interactive + +With `GONKAGATE_API_KEY`: + +```bash +GONKAGATE_API_KEY="$GONKAGATE_API_KEY" npx @gonkagate/kilo-setup --scope project --yes +``` + +With stdin: + +```bash +printf '%s' "$GONKAGATE_API_KEY" | npx @gonkagate/kilo-setup --api-key-stdin --scope project --yes +``` + +With project-scope cache cleanup: + +```bash +printf '%s' "$GONKAGATE_API_KEY" | npx @gonkagate/kilo-setup --api-key-stdin --scope project --clear-kilo-model-cache --yes +``` + +### After setup + +Go back to plain `kilo`. + +```bash +kilo +``` + +## What the installer actually does + +At a high level, it does four things: + +1. Figures out the local Kilo situation. +2. Writes the minimum safe config. +3. Keeps the secret in user scope, not in the repository. +4. Verifies the resolved result instead of trusting file writes. + +More concretely: + +- it detects `kilo`, or falls back to `kilocode` +- it accepts Kilo versions at or above `@kilocode/cli >=7.2.0` without a + preset upper bound +- it accepts the API key through a hidden prompt, `GONKAGATE_API_KEY`, or + `--api-key-stdin` +- it rejects plain `--api-key` +- it stores the managed secret at `~/.gonkagate/kilo/api-key` +- it writes the user-level `provider.gonkagate` definition and canonical + `{file:~/.gonkagate/kilo/api-key}` binding +- it chooses the recommended scope automatically +- inside a git repo, that usually means `project` +- outside a repo, that usually means `user` +- on reruns, it only asks about scope when the previous installer-managed scope + no longer matches the new recommendation +- in `project` scope, it writes only activation settings into + `.kilo/kilo.jsonc` +- it creates rollback backups before replacing installer-managed files +- it preserves unrelated Kilo config where it can +- it verifies the durable plain-`kilo` result with the local resolver +- if the current shell is still affected by `KILO_CONFIG`, + `KILO_CONFIG_DIR`, or `KILO_CONFIG_CONTENT`, it reports that separately +- for project installs, it can also clear Kilo's current global UI-model cache + +That last part matters more than it sounds. A config write is easy. A correct +resolved config is the part that actually counts. + +## A couple of details that mattered to us + +`project` scope is intentionally narrow. The repository gets activation only. +The provider definition and secret binding stay in user config. That keeps +`.kilo/kilo.jsonc` commit-safe by default and avoids the usual "why is there a +secret-related path in git" problem. + +We also did not want a setup command that happily prints or spreads the secret +around. The installer does not write to `auth.json`, does not generate `.env` +files, and does not touch shell profiles. + +The other important part is verification. The runtime treats effective Kilo +config as the real success gate. If the durable install is fine but the current +shell is still overridden by runtime-only Kilo env vars, the tool says so +instead of pretending everything is clean. + +## Current model and transport + +Right now the public default is deliberately small: + +- package: `@gonkagate/kilo-setup` +- provider id: `gonkagate` +- base URL: `https://api.gonkagate.com/v1` +- transport: `chat/completions` +- minimum Kilo floor: `@kilocode/cli >=7.2.0` +- recommended validated model: `moonshotai/Kimi-K2.6` +- managed limits: `limit.context = 262144`, `limit.output = 8192` + +We are treating model support as a curated list, not as a vague "it probably +works" promise. + +## What we are not claiming + +The current boundaries are deliberate: + +- no upper Kilo version pin by default +- no `/v1/responses` support today +- no plain `--api-key` +- no `.env` generation +- no shell profile edits +- no direct writes to `auth.json` +- no production-ready native Windows claim yet +- no claim that project config alone is enough on a brand-new machine +- no claim that live real-path `kilo debug config` against user paths is the + production default verifier + +If `/v1/responses` support shows up later, that should be a real migration, not +something implied by marketing copy. + +## Links + +### Project + +- [Repository](https://github.com/GonkaGate/kilo-setup) +- [npm package](https://www.npmjs.com/package/@gonkagate/kilo-setup) +- [Issues and feedback](https://github.com/GonkaGate/kilo-setup/issues) +- [Changelog](https://github.com/GonkaGate/kilo-setup/blob/main/CHANGELOG.md) +- [GonkaGate website](https://gonkagate.com/en) +- [Get a GonkaGate API key](https://gonkagate.com/en/register) +- [GonkaGate docs](https://gonkagate.com/en/docs) + +### Docs + +- [README](https://github.com/GonkaGate/kilo-setup/blob/main/README.md) +- [User guide](https://github.com/GonkaGate/kilo-setup/blob/main/docs/user-guide.md) +- [How it works](https://github.com/GonkaGate/kilo-setup/blob/main/docs/how-it-works.md) +- [Security notes](https://github.com/GonkaGate/kilo-setup/blob/main/docs/security.md) +- [Troubleshooting](https://github.com/GonkaGate/kilo-setup/blob/main/docs/troubleshooting.md) diff --git a/docs/how-it-works.md b/docs/how-it-works.md index 2373f6c..5732f45 100644 --- a/docs/how-it-works.md +++ b/docs/how-it-works.md @@ -16,7 +16,7 @@ The runtime is implemented and shipped. Today the repository ships: - the public CLI runtime -- Kilo detection for exact `@kilocode/cli@7.2.0` +- Kilo detection for `@kilocode/cli >=7.2.0` without a preset upper bound - safe secret intake, managed secret persistence, managed Kilo config parse/merge/write, rollback, install-state persistence, and redacted result rendering @@ -26,8 +26,9 @@ Today the repository ships: Current public limit: -- the published contract stays intentionally narrow to exact - `@kilocode/cli@7.2.0`, `chat/completions`, and non-Windows production claims +- the published contract keeps a minimum Kilo floor of + `@kilocode/cli >=7.2.0`, `chat/completions`, and non-Windows production + claims - the curated default is `moonshotai/Kimi-K2.6` with `limit.context = 262144` and `limit.output = 8192` @@ -37,7 +38,7 @@ Current public limit: ## Install Flow 1. Check that `kilo` is available, or fall back to `kilocode`. -2. Verify the exact supported compatibility profile: `@kilocode/cli@7.2.0`. +2. Verify the minimum accepted Kilo floor: `@kilocode/cli >=7.2.0`. 3. Resolve the curated model choice and scope. 4. Use the recommended scope automatically in the default interactive flow: - `project` inside a git repository @@ -113,9 +114,10 @@ That means: The repository must stay explicit about what is not yet claimed: -- no support claim beyond exact `@kilocode/cli@7.2.0` +- no Kilo version pin beyond the minimum accepted `@kilocode/cli >=7.2.0` - no GonkaGate `responses` transport claim - no production-ready native Windows claim before the native oracle-safety proof exists -- no implication that later `7.2.x` Kilo builds, broader model catalogs, or - native Windows are already proven just because the current default is public +- no implication that every future Kilo behavior, broader model catalog, or + native Windows path is already proven just because the current default is + public diff --git a/docs/readme-header-style.md b/docs/readme-header-style.md index 71fa5b9..58ecf90 100644 --- a/docs/readme-header-style.md +++ b/docs/readme-header-style.md @@ -177,7 +177,7 @@ npx @gonkagate/kilo-setup ![Package](https://img.shields.io/badge/package-%40gonkagate%2Fkilo--setup-6E63FF?style=flat-square) ![Node](https://img.shields.io/badge/node-%3E%3D22.14.0-4DA2FF?style=flat-square) -![Kilo](https://img.shields.io/badge/kilo-7.2.0-35D6FF?style=flat-square) +![Kilo](https://img.shields.io/badge/kilo-%3E%3D7.2.0-35D6FF?style=flat-square) ![License](https://img.shields.io/badge/license-Apache--2.0-2A2A2A?style=flat-square) [![Website](https://img.shields.io/badge/Website-gonkagate.com-111827?style=flat-square)](https://gonkagate.com/en) diff --git a/docs/release-readiness.md b/docs/release-readiness.md index 08f999e..6fa1160 100644 --- a/docs/release-readiness.md +++ b/docs/release-readiness.md @@ -15,7 +15,7 @@ docs, and tests for these facts: - public entrypoint: `npx @gonkagate/kilo-setup` - binary names: `kilo-setup` and `gonkagate-kilo` - Kilo command contract: `kilo` first, `kilocode` as fallback -- exact compatibility claim: `@kilocode/cli@7.2.0` +- minimum Kilo compatibility floor: `@kilocode/cli >=7.2.0` - current GonkaGate transport claim: `chat/completions` - curated public default: `moonshotai/Kimi-K2.6` @@ -40,16 +40,20 @@ Moonshot metadata checked on 2026-04-29: - the package writes `limit.output = 8192` as the installer-managed Kilo compatibility clamp because Kilo `7.2.0` requires a numeric output limit in custom model config +- npm registry metadata checked on 2026-04-29 showed `@kilocode/cli` patch + releases in the `7.2.x` line, including `7.2.14`, with both `kilo` and + `kilocode` binaries still exposed by the wrapper package +- future Kilo releases are not pre-blocked by version; observed compatibility + breaks should be handled as bugs with targeted fixes ## Explicitly Not Shipped Yet The repository must continue to avoid these claims: -- no support claim for Kilo versions beyond exact `7.2.0` - no claim that GonkaGate `responses` transport works today - no claim that real-path Kilo verification is the production default - no claim that native Windows production support is proven -- no claim that later Kilo patch releases or additional GonkaGate models are +- no claim that every future Kilo behavior or additional GonkaGate model is proven just because the current curated default is shipped ## Remaining Follow-Up Items @@ -64,5 +68,6 @@ repository-only pass: `@gonkagate/kilo-setup` Those items do not change the current package contract: the publishable surface -remains the exact Kilo baseline, the validated Kimi curated default, and the -current non-Windows verification policy documented above. +remains the minimum Kilo `7.2.0` floor without an upper version bound, the +validated Kimi curated default, and the current non-Windows verification policy +documented above. diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index a578e9d..7dc9184 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -23,13 +23,15 @@ Common reasons: - `kilo` and `kilocode` are both missing from `PATH` - `kilo --version` output could not be parsed safely -- local Kilo is present, but it is not exact `@kilocode/cli@7.2.0` +- local Kilo is present, but it is older than `@kilocode/cli >=7.2.0` - a higher-precedence Kilo layer such as `KILO_CONFIG`, `KILO_CONFIG_DIR`, or `KILO_CONFIG_CONTENT` overrides the intended result - provider allow/deny settings still disable `gonkagate` -The repository intentionally does not treat `7.2.5` as patch-compatible with -`7.2.0` by implication. +The repository does not pre-block future Kilo releases by version. If a newer +Kilo release changes config behavior in a way that breaks setup, treat that as +a compatibility bug to investigate and fix rather than as a version gate to add +by default. ## Why Does Project Scope Still Need Setup On Each Machine? diff --git a/docs/user-guide.md b/docs/user-guide.md index a72d513..fb64b50 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -21,7 +21,7 @@ to hand-edit Kilo config or store secrets in the repository. Today the public package is intentionally narrow: -- exact Kilo compatibility target: `@kilocode/cli@7.2.0` +- minimum Kilo compatibility floor: `@kilocode/cli >=7.2.0` - current transport target: `chat/completions` - current curated default: `moonshotai/Kimi-K2.6` @@ -34,7 +34,7 @@ Make sure these conditions are true: 1. You have local `kilo` installed, or the fallback `kilocode` command is available. -2. The local Kilo version matches exact `@kilocode/cli@7.2.0`. +2. The local Kilo version is at least `@kilocode/cli >=7.2.0`. 3. You already have a GonkaGate API key from the [dashboard](https://gonkagate.com/en/register). 4. You are ready to provide that key through one of the supported safe inputs: @@ -55,7 +55,7 @@ npx @gonkagate/kilo-setup The installer will then: 1. Detect `kilo`, or fall back to `kilocode`. -2. Check the exact supported Kilo profile. +2. Check the minimum supported Kilo floor. 3. Offer the curated GonkaGate model choice. 4. Choose the recommended scope automatically: - inside a git repository: `project` @@ -242,7 +242,7 @@ printf '%s' "$GONKAGATE_API_KEY" | npx @gonkagate/kilo-setup --api-key-stdin --s The most common reasons are: - `kilo` and `kilocode` are both missing from `PATH` -- installed Kilo is not exact `@kilocode/cli@7.2.0` +- installed Kilo is older than `@kilocode/cli >=7.2.0` - `KILO_CONFIG`, `KILO_CONFIG_DIR`, or `KILO_CONFIG_CONTENT` overrides are changing the effective result - local provider allow/deny settings still block `gonkagate` diff --git a/src/cli/parse.ts b/src/cli/parse.ts index bfd754e..289fc46 100644 --- a/src/cli/parse.ts +++ b/src/cli/parse.ts @@ -110,7 +110,7 @@ Examples: printf '%s' "$${GONKAGATE_SECRET_ENV_VAR}" | ${CONTRACT_METADATA.publicEntrypoint} --api-key-stdin --scope project --yes --json Runtime status: - The installer runtime is shipped for Kilo and currently defaults to the validated Kimi K2.6 profile for exact @kilocode/cli@7.2.0 installs. + The installer runtime is shipped for Kilo and currently defaults to the validated Kimi K2.6 profile for @kilocode/cli >=7.2.0 installs. Kilo contract anchors: - Primary command: ${KILO_PRIMARY_COMMAND} diff --git a/src/constants/contract.ts b/src/constants/contract.ts index 15964c7..6b2bdd1 100644 --- a/src/constants/contract.ts +++ b/src/constants/contract.ts @@ -5,12 +5,13 @@ export const CONTRACT_METADATA = { packageName: "@gonkagate/kilo-setup", publicEntrypoint: "npx @gonkagate/kilo-setup", publicState: - "Installer runtime is shipped with a validated curated Kimi K2.6 default for exact @kilocode/cli@7.2.0 installs, with installer-managed limit.output = 8192 for compatibility.", + "Installer runtime is shipped with a validated curated Kimi K2.6 default for @kilocode/cli >=7.2.0 installs, with installer-managed limit.output = 8192 for compatibility.", secondaryBinName: "gonkagate-kilo", upstreamKilo: { - checkedAt: "2026-04-14", + checkedAt: "2026-04-29", investigatedVersion: "7.2.0", - minimumVersion: "proof-gate-pending", + minimumVersion: "7.2.0", packageName: "@kilocode/cli", + supportedVersionRange: ">=7.2.0", }, } as const; diff --git a/src/install/contracts.ts b/src/install/contracts.ts index 0566ae1..e9d643f 100644 --- a/src/install/contracts.ts +++ b/src/install/contracts.ts @@ -31,7 +31,7 @@ export type InstallFlowErrorCode = | "kilo_version_unsupported"; export type KiloCommandName = "kilo" | "kilocode"; -export type KiloCompatibilityProfileId = "kilo_cli_7_2_0"; +export type KiloCompatibilityProfileId = "kilo_cli_7_2_plus"; export interface InstallFlowContext { configTargets: { diff --git a/src/install/kilo.ts b/src/install/kilo.ts index 625dde3..38da7cf 100644 --- a/src/install/kilo.ts +++ b/src/install/kilo.ts @@ -1,4 +1,4 @@ -import { valid } from "semver"; +import { satisfies as satisfiesSemver, valid } from "semver"; import type { BlockedKiloSummary, InstallFlowErrorCode, @@ -9,7 +9,9 @@ import type { InstallDependencies } from "./deps.js"; export const KILO_PACKAGE_NAME = "@kilocode/cli"; export const KILO_INVESTIGATED_VERSION = "7.2.0"; -export const KILO_MINIMUM_VERSION_STATUS = "proof-gate-pending"; +export const KILO_SUPPORTED_VERSION_RANGE = ">=7.2.0"; +export const KILO_SUPPORTED_VERSION_LABEL = `${KILO_PACKAGE_NAME} ${KILO_SUPPORTED_VERSION_RANGE}`; +export const KILO_MINIMUM_VERSION_STATUS = "minimum-floor-supported"; export const KILO_PRIMARY_COMMAND = "kilo"; export const KILO_FALLBACK_COMMAND = "kilocode"; export const KILO_CONFIG_ENV_VAR = "KILO_CONFIG"; @@ -22,9 +24,10 @@ export const KILO_PREFERRED_PROJECT_CONFIG = ".kilo/kilo.jsonc"; export const KILO_MANAGED_STATE_DIRECTORY = "~/.gonkagate/kilo"; export const KILO_DEBUG_CONFIG_COMMAND = "kilo debug config"; export const KILO_DEBUG_CONFIG_PURE_SUPPORTED = false; -export const KILO_COMPATIBILITY_PROFILE_7_2_0 = Object.freeze({ - id: "kilo_cli_7_2_0", - supportedVersion: KILO_INVESTIGATED_VERSION, +export const KILO_COMPATIBILITY_PROFILE_7_2_PLUS = Object.freeze({ + id: "kilo_cli_7_2_plus", + investigatedVersion: KILO_INVESTIGATED_VERSION, + supportedVersionRange: KILO_SUPPORTED_VERSION_RANGE, } as const); export const KILO_LEGACY_CONFIG_FILES = Object.freeze([ @@ -51,7 +54,8 @@ export const KILO_PROJECT_DIRECTORY_NAMES = Object.freeze([ export interface KiloCompatibilityProfile { id: string; - supportedVersion: string; + investigatedVersion: string; + supportedVersionRange: string; } export interface KiloDetectionBlocked { @@ -73,7 +77,7 @@ export type KiloDetectionResult = KiloDetectionBlocked | SupportedKiloDetection; const KILO_VERSION_PATTERN = /\b(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)\b/u; const DEFAULT_KILO_COMPATIBILITY_PROFILES = Object.freeze([ - KILO_COMPATIBILITY_PROFILE_7_2_0, + KILO_COMPATIBILITY_PROFILE_7_2_PLUS, ] as const satisfies readonly KiloCompatibilityProfile[]); export function parseKiloVersion(output: string): string | null { @@ -90,8 +94,10 @@ export function resolveSupportedKiloProfile( installedVersion: string, profiles: readonly KiloCompatibilityProfile[] = DEFAULT_KILO_COMPATIBILITY_PROFILES, ): KiloCompatibilityProfile | undefined { - return profiles.find( - (profile) => profile.supportedVersion === installedVersion, + return profiles.find((profile) => + satisfiesSemver(installedVersion, profile.supportedVersionRange, { + includePrerelease: true, + }), ); } @@ -104,8 +110,7 @@ export async function detectInstalledKilo( if (resolvedCommand === undefined) { return { errorCode: "kilo_not_found", - message: - "Kilo CLI was not found on PATH. Install @kilocode/cli@7.2.0 and rerun npx @gonkagate/kilo-setup.", + message: `Kilo CLI was not found on PATH. Install ${KILO_SUPPORTED_VERSION_LABEL} and rerun npx @gonkagate/kilo-setup.`, ok: false, }; } @@ -207,7 +212,7 @@ function createBlockedVersionResult( command, installedVersion, }, - message: `${commandPrefix} ${command} ${installedVersion ?? "unknown"}, but only exact @kilocode/cli@7.2.0 is supported right now.`, + message: `${commandPrefix} ${command} ${installedVersion ?? "unknown"}, but supported Kilo versions are ${KILO_SUPPORTED_VERSION_LABEL}.`, ok: false, }; } @@ -223,7 +228,7 @@ function createBlockedVersionResult( command, installedVersion, }, - message: `Could not determine the installed Kilo version from \`${command} --version\`${fallbackNote}.${signalNote} Install exact @kilocode/cli@7.2.0 or repair the local Kilo CLI and rerun npx @gonkagate/kilo-setup.`, + message: `Could not determine the installed Kilo version from \`${command} --version\`${fallbackNote}.${signalNote} Install ${KILO_SUPPORTED_VERSION_LABEL} or repair the local Kilo CLI and rerun npx @gonkagate/kilo-setup.`, ok: false, }; } diff --git a/src/install/verification-notes.ts b/src/install/verification-notes.ts index ab6c7c8..318ac2c 100644 --- a/src/install/verification-notes.ts +++ b/src/install/verification-notes.ts @@ -10,7 +10,7 @@ export const KILO_VERIFICATION_NOTES = Object.freeze([ `${KILO_DEBUG_CONFIG_COMMAND} --pure is not documented in the investigated Kilo baseline.`, `${KILO_CONFIG_ENV_VAR} and ${KILO_CONFIG_CONTENT_ENV_VAR} are Kilo override layers, not durable installer targets.`, "The curated Kimi K2.6 default writes limit.output = 8192 because Kilo 7.2.0 requires a numeric output limit in custom model config.", - "Support claims remain pinned to exact @kilocode/cli@7.2.0 even though the public default is now enabled.", + "The installer accepts @kilocode/cli >=7.2.0 without pre-blocking future Kilo releases; the audited compatibility baseline remains 7.2.0.", ] as const); export const KILO_VERIFICATION_PLACEHOLDER = { diff --git a/test/install/kilo.test.ts b/test/install/kilo.test.ts index 62b4bb1..7a69e40 100644 --- a/test/install/kilo.test.ts +++ b/test/install/kilo.test.ts @@ -9,15 +9,21 @@ import { createTestInstallDependencies } from "./test-deps.js"; test("parseKiloVersion extracts semver from kilo --version output", () => { assert.equal(parseKiloVersion("kilo 7.2.0"), "7.2.0"); - assert.equal(parseKiloVersion("kilocode version 7.2.5"), "7.2.5"); + assert.equal(parseKiloVersion("kilocode version 7.2.14"), "7.2.14"); assert.equal(parseKiloVersion("version unknown"), null); }); -test("resolveSupportedKiloProfile matches the exact 7.2.0 compatibility profile", () => { +test("resolveSupportedKiloProfile accepts versions at or above the 7.2.0 floor", () => { const profile = resolveSupportedKiloProfile("7.2.0"); - assert.equal(profile?.id, "kilo_cli_7_2_0"); - assert.equal(resolveSupportedKiloProfile("7.2.5"), undefined); + assert.equal(profile?.id, "kilo_cli_7_2_plus"); + assert.equal(resolveSupportedKiloProfile("7.2.14")?.id, "kilo_cli_7_2_plus"); + assert.equal(resolveSupportedKiloProfile("7.5.0")?.id, "kilo_cli_7_2_plus"); + assert.equal( + resolveSupportedKiloProfile("7.2.1-rc.202604092126")?.id, + "kilo_cli_7_2_plus", + ); + assert.equal(resolveSupportedKiloProfile("7.1.23"), undefined); }); test("detectInstalledKilo accepts kilo 7.2.0", async () => { @@ -40,7 +46,55 @@ test("detectInstalledKilo accepts kilo 7.2.0", async () => { if (detection.ok) { assert.equal(detection.kilo.command, "kilo"); assert.equal(detection.kilo.installedVersion, "7.2.0"); - assert.equal(detection.kilo.profileId, "kilo_cli_7_2_0"); + assert.equal(detection.kilo.profileId, "kilo_cli_7_2_plus"); + } +}); + +test("detectInstalledKilo accepts later 7.2.x patch versions", async () => { + const detection = await detectInstalledKilo( + createTestInstallDependencies({ + "kilo --version": { + kind: "result", + result: { + exitCode: 0, + signal: null, + stderr: "", + stdout: "kilo 7.2.14", + }, + }, + }), + ); + + assert.equal(detection.ok, true); + + if (detection.ok) { + assert.equal(detection.kilo.command, "kilo"); + assert.equal(detection.kilo.installedVersion, "7.2.14"); + assert.equal(detection.kilo.profileId, "kilo_cli_7_2_plus"); + } +}); + +test("detectInstalledKilo accepts newer Kilo versions without a preset upper bound", async () => { + const detection = await detectInstalledKilo( + createTestInstallDependencies({ + "kilo --version": { + kind: "result", + result: { + exitCode: 0, + signal: null, + stderr: "", + stdout: "kilo 7.5.0", + }, + }, + }), + ); + + assert.equal(detection.ok, true); + + if (detection.ok) { + assert.equal(detection.kilo.command, "kilo"); + assert.equal(detection.kilo.installedVersion, "7.5.0"); + assert.equal(detection.kilo.profileId, "kilo_cli_7_2_plus"); } }); @@ -53,7 +107,7 @@ test("detectInstalledKilo falls back to kilocode when kilo is missing", async () exitCode: 0, signal: null, stderr: "", - stdout: "kilocode 7.2.0", + stdout: "kilocode 7.2.14", }, }, }), @@ -63,7 +117,7 @@ test("detectInstalledKilo falls back to kilocode when kilo is missing", async () if (detection.ok) { assert.equal(detection.kilo.command, "kilocode"); - assert.equal(detection.kilo.installedVersion, "7.2.0"); + assert.equal(detection.kilo.installedVersion, "7.2.14"); } }); @@ -76,11 +130,11 @@ test("detectInstalledKilo blocks when kilo and kilocode are both missing", async if (!detection.ok) { assert.equal(detection.errorCode, "kilo_not_found"); - assert.match(detection.message, /Install @kilocode\/cli@7\.2\.0/i); + assert.match(detection.message, /Install @kilocode\/cli >=7\.2\.0/i); } }); -test("detectInstalledKilo blocks unsupported versions like 7.2.5", async () => { +test("detectInstalledKilo blocks versions below the 7.2.0 floor", async () => { const detection = await detectInstalledKilo( createTestInstallDependencies({ "kilo --version": { @@ -89,7 +143,7 @@ test("detectInstalledKilo blocks unsupported versions like 7.2.5", async () => { exitCode: 0, signal: null, stderr: "", - stdout: "kilo 7.2.5", + stdout: "kilo 7.1.23", }, }, }), @@ -100,7 +154,8 @@ test("detectInstalledKilo blocks unsupported versions like 7.2.5", async () => { if (!detection.ok) { assert.equal(detection.errorCode, "kilo_version_unsupported"); assert.equal(detection.kilo?.command, "kilo"); - assert.equal(detection.kilo?.installedVersion, "7.2.5"); + assert.equal(detection.kilo?.installedVersion, "7.1.23"); + assert.match(detection.message, /@kilocode\/cli >=7\.2\.0/i); } }); diff --git a/test/package-contract.test.ts b/test/package-contract.test.ts index b3b5a29..d46c18f 100644 --- a/test/package-contract.test.ts +++ b/test/package-contract.test.ts @@ -23,6 +23,8 @@ import { KILO_PREFERRED_GLOBAL_CONFIG, KILO_PREFERRED_PROJECT_CONFIG, KILO_PRIMARY_COMMAND, + KILO_SUPPORTED_VERSION_LABEL, + KILO_SUPPORTED_VERSION_RANGE, } from "../src/install/kilo.js"; import { readText } from "./contract-helpers.js"; @@ -97,6 +99,8 @@ test("prettier ignore matches the release-please changelog workflow", () => { test("constants use Kilo-specific defaults and leave OpenCode env vars out", () => { assert.equal(KILO_PRIMARY_COMMAND, "kilo"); assert.equal(KILO_FALLBACK_COMMAND, "kilocode"); + assert.equal(KILO_SUPPORTED_VERSION_RANGE, ">=7.2.0"); + assert.equal(KILO_SUPPORTED_VERSION_LABEL, "@kilocode/cli >=7.2.0"); assert.equal(KILO_CONFIG_ENV_VAR, "KILO_CONFIG"); assert.equal(KILO_CONFIG_DIR_ENV_VAR, "KILO_CONFIG_DIR"); assert.equal(KILO_CONFIG_CONTENT_ENV_VAR, "KILO_CONFIG_CONTENT"); diff --git a/test/readme-contract.test.ts b/test/readme-contract.test.ts index 2ef36c5..c93ac20 100644 --- a/test/readme-contract.test.ts +++ b/test/readme-contract.test.ts @@ -22,7 +22,7 @@ test("README stays usable as the first-stop GitHub and npm landing page", () => assert.match(readme, /~\/\.config\/kilo\/kilo\.jsonc/); assert.match(readme, /\.kilo\/kilo\.jsonc/); assert.match(readme, /~\/\.gonkagate\/kilo\/api-key/); - assert.match(readme, /@kilocode\/cli@7\.2\.0/); + assert.match(readme, /@kilocode\/cli >=7\.2\.0/); assert.match(readme, /chat\/completions/); assert.match(readme, /moonshotai\/Kimi-K2\.6/); assert.match(readme, /no native Windows production claim yet/i);