specrails-core 4.11.3 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/README.md +96 -89
  2. package/bin/specrails-core.mjs +282 -39
  3. package/bin/tui-installer.mjs +117 -149
  4. package/commands/doctor.md +1 -1
  5. package/dist/installer/cli.js +13 -3
  6. package/dist/installer/cli.js.map +1 -1
  7. package/dist/installer/commands/doctor.js +487 -27
  8. package/dist/installer/commands/doctor.js.map +1 -1
  9. package/dist/installer/commands/framework.js +49 -7
  10. package/dist/installer/commands/framework.js.map +1 -1
  11. package/dist/installer/commands/init.js +443 -41
  12. package/dist/installer/commands/init.js.map +1 -1
  13. package/dist/installer/commands/update.js +51 -23
  14. package/dist/installer/commands/update.js.map +1 -1
  15. package/dist/installer/commands/v5-migration.js +119 -0
  16. package/dist/installer/commands/v5-migration.js.map +1 -0
  17. package/dist/installer/phases/framework-lifecycle.js +125 -0
  18. package/dist/installer/phases/framework-lifecycle.js.map +1 -0
  19. package/dist/installer/phases/install-config.js +160 -11
  20. package/dist/installer/phases/install-config.js.map +1 -1
  21. package/dist/installer/phases/manifest.js +29 -8
  22. package/dist/installer/phases/manifest.js.map +1 -1
  23. package/dist/installer/phases/prereqs.js +57 -3
  24. package/dist/installer/phases/prereqs.js.map +1 -1
  25. package/dist/installer/phases/provider-detect.js +116 -6
  26. package/dist/installer/phases/provider-detect.js.map +1 -1
  27. package/dist/installer/phases/scaffold.js +1217 -117
  28. package/dist/installer/phases/scaffold.js.map +1 -1
  29. package/dist/installer/runtime/kimi.js +255 -0
  30. package/dist/installer/runtime/kimi.js.map +1 -0
  31. package/dist/installer/util/paths.js +12 -0
  32. package/dist/installer/util/paths.js.map +1 -1
  33. package/dist/installer/util/registry.js +234 -14
  34. package/dist/installer/util/registry.js.map +1 -1
  35. package/docs/README.md +1 -0
  36. package/docs/deployment.md +6 -7
  37. package/docs/getting-started.md +11 -7
  38. package/docs/installation.md +34 -16
  39. package/docs/plugin-architecture.md +11 -8
  40. package/docs/updating.md +21 -3
  41. package/docs/user-docs/cli-reference.md +43 -22
  42. package/docs/user-docs/codex-vs-claude-code.md +11 -9
  43. package/docs/user-docs/faq.md +1 -1
  44. package/docs/user-docs/getting-started-codex.md +5 -8
  45. package/docs/user-docs/getting-started-kimi.md +423 -0
  46. package/docs/user-docs/installation.md +49 -14
  47. package/docs/user-docs/quick-start.md +11 -8
  48. package/docs/windows.md +29 -4
  49. package/integration-contract.json +85 -13
  50. package/package.json +9 -5
  51. package/schemas/profile.v1.json +68 -6
  52. package/templates/agents/sr-architect.md +30 -0
  53. package/templates/agents/sr-developer.md +21 -8
  54. package/templates/agents/sr-reviewer.md +44 -31
  55. package/templates/codex-skills/batch-implement/SKILL.md +9 -32
  56. package/templates/codex-skills/implement/SKILL.md +61 -143
  57. package/templates/codex-skills/rails/sr-architect/SKILL.md +38 -20
  58. package/templates/codex-skills/rails/sr-developer/SKILL.md +29 -10
  59. package/templates/codex-skills/rails/sr-reviewer/SKILL.md +21 -10
  60. package/templates/commands/specrails/doctor.md +1 -1
  61. package/templates/commands/specrails/implement.md +117 -288
  62. package/templates/commands/specrails/memory-inspect.md +6 -4
  63. package/templates/commands/specrails/propose-spec.md +1 -1
  64. package/templates/commands/specrails/refactor-recommender.md +8 -51
  65. package/templates/commands/specrails/retry.md +12 -48
  66. package/templates/commands/specrails/telemetry.md +1 -1
  67. package/templates/gemini-commands/implement.toml +9 -0
  68. package/templates/kimi/specrails/run-skill.mjs +3005 -0
  69. package/templates/kimi/specrails/vendor/js-yaml/LICENSE +21 -0
  70. package/templates/kimi/specrails/vendor/js-yaml/NOTICE.md +16 -0
  71. package/templates/kimi/specrails/vendor/js-yaml/js-yaml.mjs +3856 -0
  72. package/templates/profiles/default.json +5 -18
  73. package/templates/profiles/kimi-default.json +15 -0
  74. package/commands/enrich.md +0 -1456
  75. package/templates/agents/sr-backend-developer.md +0 -91
  76. package/templates/agents/sr-backend-reviewer.md +0 -152
  77. package/templates/agents/sr-doc-sync.md +0 -247
  78. package/templates/agents/sr-frontend-developer.md +0 -85
  79. package/templates/agents/sr-frontend-reviewer.md +0 -145
  80. package/templates/agents/sr-merge-resolver.md +0 -195
  81. package/templates/agents/sr-performance-reviewer.md +0 -186
  82. package/templates/agents/sr-product-analyst.md +0 -36
  83. package/templates/agents/sr-product-manager.md +0 -148
  84. package/templates/agents/sr-security-reviewer.md +0 -191
  85. package/templates/agents/sr-test-writer.md +0 -176
  86. package/templates/codex-skills/enrich/SKILL.md +0 -191
  87. package/templates/codex-skills/merge-resolve/SKILL.md +0 -88
  88. package/templates/codex-skills/rails/sr-backend-developer/SKILL.md +0 -93
  89. package/templates/codex-skills/rails/sr-backend-reviewer/SKILL.md +0 -120
  90. package/templates/codex-skills/rails/sr-doc-sync/SKILL.md +0 -124
  91. package/templates/codex-skills/rails/sr-frontend-developer/SKILL.md +0 -106
  92. package/templates/codex-skills/rails/sr-frontend-reviewer/SKILL.md +0 -111
  93. package/templates/codex-skills/rails/sr-merge-resolver/SKILL.md +0 -156
  94. package/templates/codex-skills/rails/sr-performance-reviewer/SKILL.md +0 -109
  95. package/templates/codex-skills/rails/sr-product-analyst/SKILL.md +0 -85
  96. package/templates/codex-skills/rails/sr-product-manager/SKILL.md +0 -131
  97. package/templates/codex-skills/rails/sr-security-reviewer/SKILL.md +0 -121
  98. package/templates/codex-skills/rails/sr-test-writer/SKILL.md +0 -115
  99. package/templates/commands/specrails/auto-propose-backlog-specs.md +0 -312
  100. package/templates/commands/specrails/enrich.md +0 -1456
  101. package/templates/commands/specrails/get-backlog-specs.md +0 -226
  102. package/templates/commands/specrails/merge-resolve.md +0 -172
  103. package/templates/commands/specrails/reconfig.md +0 -80
  104. package/templates/commands/specrails/vpc-drift.md +0 -405
  105. package/templates/commands/test.md +0 -58
  106. package/templates/personas/persona.md +0 -43
  107. package/templates/personas/the-maintainer.md +0 -98
  108. package/templates/settings/perf-thresholds.yml +0 -25
@@ -2,6 +2,53 @@ import path from 'node:path';
2
2
  import yaml from 'js-yaml';
3
3
  import { FilesystemError, InstallerError } from '../util/errors.js';
4
4
  import { pathExists, readTextFile, writeFileLf } from '../util/fs.js';
5
+ const PROVIDER_DEFAULT_MODELS = {
6
+ claude: 'sonnet',
7
+ codex: 'gpt-5.5-mini',
8
+ gemini: 'gemini-3.5-flash',
9
+ kimi: 'k3',
10
+ };
11
+ /**
12
+ * Agent ids become provider-native file/directory names. Keep them to the
13
+ * portable direct-child skill grammar so config cannot escape an install root
14
+ * or create names that Kimi's managed runner will later reject.
15
+ */
16
+ const SAFE_AGENT_ID = /^[a-z0-9][a-z0-9-]{0,63}$/;
17
+ /**
18
+ * Must remain byte-for-byte equivalent to the canonical Kimi runtime and the
19
+ * public integration contract. Config validation happens before any framework
20
+ * write so an unsafe model can never create an install that only fails later at
21
+ * process launch.
22
+ */
23
+ const SAFE_KIMI_MODEL_ID = /^[A-Za-z0-9][A-Za-z0-9._/:-]{0,127}$/;
24
+ /**
25
+ * Resolve a preset into provider-native identifiers. Kimi currently exposes no
26
+ * Core-defined cost/capability tier mapping, so every named preset resolves to
27
+ * its explicit `k3` default. User-supplied exact identifiers are handled later
28
+ * and are never interpreted as Claude aliases.
29
+ */
30
+ export function resolveProviderModelConfig(provider, preset = 'balanced') {
31
+ if (provider === 'claude') {
32
+ if (preset === 'budget') {
33
+ return { preset, defaults: { model: 'haiku' }, overrides: {} };
34
+ }
35
+ if (preset === 'max') {
36
+ return {
37
+ preset,
38
+ defaults: { model: 'sonnet' },
39
+ overrides: {
40
+ 'sr-architect': 'opus',
41
+ 'sr-product-manager': 'opus',
42
+ },
43
+ };
44
+ }
45
+ }
46
+ return {
47
+ preset,
48
+ defaults: { model: PROVIDER_DEFAULT_MODELS[provider] },
49
+ overrides: {},
50
+ };
51
+ }
5
52
  export class InvalidConfigError extends InstallerError {
6
53
  errors;
7
54
  constructor(errors) {
@@ -57,13 +104,18 @@ export function validateInstallConfig(raw) {
57
104
  if (doc.provider === undefined) {
58
105
  errors.push(`missing required 'provider' field`);
59
106
  }
60
- else if (doc.provider !== 'claude' && doc.provider !== 'codex' && doc.provider !== 'gemini') {
61
- errors.push(`unsupported provider '${String(doc.provider)}' (expected: claude, codex, or gemini)`);
62
- }
63
- if (doc.tier !== undefined && doc.tier !== 'full' && doc.tier !== 'quick') {
64
- errors.push(`unsupported tier '${String(doc.tier)}' (expected: full or quick)`);
107
+ else if (doc.provider !== 'claude' &&
108
+ doc.provider !== 'codex' &&
109
+ doc.provider !== 'gemini' &&
110
+ doc.provider !== 'kimi') {
111
+ errors.push(`unsupported provider '${String(doc.provider)}' (expected: claude, codex, gemini, or kimi)`);
65
112
  }
113
+ // NOTE: a legacy `tier` field (`full`/`quick`) may still be present in pre-v5
114
+ // configs. It is intentionally ignored (not rejected and not carried forward)
115
+ // — v5 has no install tiers.
66
116
  const agents = doc.agents;
117
+ let selectedAgents = [];
118
+ let excludedAgents;
67
119
  if (!agents || typeof agents !== 'object') {
68
120
  errors.push(`missing required 'agents' section with 'selected' list`);
69
121
  }
@@ -71,6 +123,23 @@ export function validateInstallConfig(raw) {
71
123
  if (!Array.isArray(agents.selected)) {
72
124
  errors.push(`'agents.selected' must be a list`);
73
125
  }
126
+ else {
127
+ selectedAgents = validateAgentIdList(agents.selected, 'agents.selected', errors);
128
+ }
129
+ if (agents.excluded !== undefined && !Array.isArray(agents.excluded)) {
130
+ errors.push(`'agents.excluded' must be a list`);
131
+ }
132
+ else if (Array.isArray(agents.excluded)) {
133
+ excludedAgents = validateAgentIdList(agents.excluded, 'agents.excluded', errors);
134
+ }
135
+ if (Array.isArray(agents.selected) && Array.isArray(agents.excluded)) {
136
+ const excluded = new Set(excludedAgents ?? []);
137
+ for (const agent of selectedAgents) {
138
+ if (excluded.has(agent)) {
139
+ errors.push(`'agents.selected' and 'agents.excluded' must not overlap: ${agent}`);
140
+ }
141
+ }
142
+ }
74
143
  if (agents.preset !== undefined &&
75
144
  agents.preset !== 'balanced' &&
76
145
  agents.preset !== 'budget' &&
@@ -78,27 +147,107 @@ export function validateInstallConfig(raw) {
78
147
  errors.push(`unsupported preset '${String(agents.preset)}' (expected: balanced, budget, or max)`);
79
148
  }
80
149
  }
150
+ const models = doc.models;
151
+ if (doc.models !== undefined && (!models || typeof models !== 'object')) {
152
+ errors.push(`'models' must be a mapping`);
153
+ }
154
+ const modelPreset = models?.preset;
155
+ if (modelPreset !== undefined &&
156
+ modelPreset !== 'balanced' &&
157
+ modelPreset !== 'budget' &&
158
+ modelPreset !== 'max') {
159
+ errors.push(`unsupported model preset '${String(modelPreset)}' (expected: balanced, budget, or max)`);
160
+ }
161
+ const provider = doc.provider;
162
+ const modelDefaults = models?.defaults;
163
+ if (models?.defaults !== undefined &&
164
+ (!modelDefaults || typeof modelDefaults !== 'object')) {
165
+ errors.push(`'models.defaults' must be a mapping`);
166
+ }
167
+ else if (modelDefaults?.model !== undefined &&
168
+ !isValidModelIdentifier(provider, modelDefaults.model)) {
169
+ errors.push(modelIdentifierError('models.defaults.model', provider));
170
+ }
171
+ const modelOverrides = models?.overrides;
172
+ if (modelOverrides !== undefined &&
173
+ (!modelOverrides || typeof modelOverrides !== 'object' || Array.isArray(modelOverrides))) {
174
+ errors.push(`'models.overrides' must be a mapping`);
175
+ }
176
+ else if (modelOverrides && typeof modelOverrides === 'object') {
177
+ for (const [agent, model] of Object.entries(modelOverrides)) {
178
+ if (!SAFE_AGENT_ID.test(agent)) {
179
+ errors.push(`'models.overrides' key '${agent}' must be a lowercase kebab-case agent id (1-64 characters)`);
180
+ }
181
+ if (!isValidModelIdentifier(provider, model)) {
182
+ errors.push(modelIdentifierError(`models.overrides.${agent}`, provider));
183
+ }
184
+ }
185
+ }
81
186
  if (errors.length > 0) {
82
187
  throw new InvalidConfigError(errors);
83
188
  }
84
- const selected = agents?.selected ?? [];
189
+ const preset = (modelPreset ?? agents?.preset ?? 'balanced');
190
+ const resolvedModels = resolveProviderModelConfig(provider, preset);
191
+ if (typeof modelDefaults?.model === 'string') {
192
+ resolvedModels.defaults.model = modelDefaults.model;
193
+ }
194
+ if (modelOverrides && typeof modelOverrides === 'object') {
195
+ resolvedModels.overrides = { ...modelOverrides };
196
+ }
85
197
  const result = {
86
198
  version: 1,
87
- provider: doc.provider,
199
+ provider,
88
200
  agents: {
89
- selected,
201
+ selected: selectedAgents,
90
202
  },
203
+ models: resolvedModels,
91
204
  };
92
205
  // NOTE: a legacy `agent_teams` field may still be present in older configs.
93
206
  // It is intentionally ignored (not rejected) for backward compatibility.
94
- if (doc.tier !== undefined) {
95
- result.tier = doc.tier;
96
- }
97
207
  if (agents?.preset !== undefined) {
98
208
  result.agents.preset = agents.preset;
99
209
  }
210
+ if (excludedAgents !== undefined) {
211
+ result.agents.excluded = excludedAgents;
212
+ }
100
213
  return result;
101
214
  }
215
+ function validateAgentIdList(value, field, errors) {
216
+ const valid = [];
217
+ const seen = new Set();
218
+ for (const [index, entry] of value.entries()) {
219
+ if (typeof entry !== 'string' || !SAFE_AGENT_ID.test(entry)) {
220
+ errors.push(`'${field}[${index}]' must be a lowercase kebab-case agent id (1-64 characters)`);
221
+ continue;
222
+ }
223
+ if (seen.has(entry)) {
224
+ errors.push(`'${field}' must not contain duplicate agent id '${entry}'`);
225
+ continue;
226
+ }
227
+ seen.add(entry);
228
+ valid.push(entry);
229
+ }
230
+ return valid;
231
+ }
232
+ function isValidModelIdentifier(provider, value) {
233
+ if (provider === 'kimi') {
234
+ return typeof value === 'string' && SAFE_KIMI_MODEL_ID.test(value);
235
+ }
236
+ return isExactModelIdentifier(value);
237
+ }
238
+ function modelIdentifierError(field, provider) {
239
+ if (provider === 'kimi') {
240
+ return (`'${field}' must be a safe Kimi model id: 1-128 characters matching ` +
241
+ `[A-Za-z0-9][A-Za-z0-9._/:-]*`);
242
+ }
243
+ return `'${field}' must be a nonblank provider model identifier`;
244
+ }
245
+ function isExactModelIdentifier(value) {
246
+ return (typeof value === 'string' &&
247
+ value.length > 0 &&
248
+ value.trim().length > 0 &&
249
+ value === value.trim());
250
+ }
102
251
  /**
103
252
  * Serialises an {@link InstallConfig} back to YAML and writes it with
104
253
  * LF line endings. Used by `npx specrails-core update --reset-config`
@@ -1 +1 @@
1
- {"version":3,"file":"install-config.js","sourceRoot":"","sources":["../../../src/installer/phases/install-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"install-config.js","sourceRoot":"","sources":["../../../src/installer/phases/install-config.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import { createHash } from 'node:crypto';
2
2
  import { readdirSync, statSync } from 'node:fs';
3
3
  import path from 'node:path';
4
4
  import { FilesystemError } from '../util/errors.js';
5
- import { readBytes, writeFileLf } from '../util/fs.js';
5
+ import { pathExists, readBytes, readTextFile, writeFileLf } from '../util/fs.js';
6
6
  /**
7
7
  * Computes a stable sha256 digest for a file, returned as `sha256:<hex>`.
8
8
  */
@@ -12,10 +12,8 @@ export function sha256Of(filePath) {
12
12
  return `sha256:${hash}`;
13
13
  }
14
14
  /**
15
- * Walks `templates/**` plus the two bundled command files and
16
- * produces a stable-sorted manifest. Replicates the output format of
17
- * the retired `generate_manifest` bash helper so the byte-diff CI
18
- * fixture passes without modification.
15
+ * Walks `templates/**` plus the bundled doctor command file and
16
+ * produces a stable-sorted manifest.
19
17
  *
20
18
  * Stable-sort rule: artifact keys are sorted ascending by POSIX path.
21
19
  */
@@ -27,15 +25,38 @@ export function buildManifest(input) {
27
25
  const rel = path.relative(input.scriptDir, absFile).split(path.sep).join('/');
28
26
  artifacts[rel] = sha256Of(absFile);
29
27
  });
30
- const enrichPath = path.join(input.scriptDir, 'commands', 'enrich.md');
31
28
  const doctorPath = path.join(input.scriptDir, 'commands', 'doctor.md');
32
- artifacts['commands/specrails/enrich.md'] = sha256Of(enrichPath);
33
29
  artifacts['commands/specrails/doctor.md'] = sha256Of(doctorPath);
34
- return {
30
+ const manifest = {
35
31
  version: input.version,
36
32
  installed_at,
37
33
  artifacts: sortKeys(artifacts),
38
34
  };
35
+ if (input.providers && input.providers.length > 0) {
36
+ const existing = readExistingProviderInventory(input.repoRoot);
37
+ manifest.providers = [...new Set([...existing.providers, ...input.providers])];
38
+ manifest.primary_provider =
39
+ existing.primaryProvider ?? input.primaryProvider ?? manifest.providers[0];
40
+ }
41
+ return manifest;
42
+ }
43
+ function readExistingProviderInventory(repoRoot) {
44
+ const manifestPath = path.join(repoRoot, '.specrails', 'specrails-manifest.json');
45
+ if (!pathExists(manifestPath))
46
+ return { providers: [] };
47
+ try {
48
+ const parsed = JSON.parse(readTextFile(manifestPath));
49
+ const providers = Array.isArray(parsed.providers)
50
+ ? parsed.providers.filter((provider) => typeof provider === 'string')
51
+ : [];
52
+ return {
53
+ providers,
54
+ primaryProvider: typeof parsed.primary_provider === 'string' ? parsed.primary_provider : undefined,
55
+ };
56
+ }
57
+ catch {
58
+ return { providers: [] };
59
+ }
39
60
  }
40
61
  /**
41
62
  * Writes the manifest JSON and the companion version file under
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../src/installer/phases/manifest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../src/installer/phases/manifest.ts"],"names":[],"mappings":"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"}
@@ -4,13 +4,41 @@ import { commandExists, runCommand } from '../util/exec.js';
4
4
  import { isDir, isFile, listDir } from '../util/fs.js';
5
5
  import { info, ok, warn } from '../util/logger.js';
6
6
  import { gitInstalled, initRepo, isGitRepo, repoRoot } from '../util/git.js';
7
- import { assertClaudeAuthenticated, claudeVersion, detectAvailability, resolveProvider, } from './provider-detect.js';
7
+ import { assertClaudeAuthenticated, assertKimiAuthenticated, claudeVersion, detectAvailability, isSupportedKimiVersion, kimiVersion, MIN_KIMI_VERSION, resolveProvider, } from './provider-detect.js';
8
+ /**
9
+ * OpenSpec 1.4.1, which the installer invokes during the default init/update
10
+ * flow, requires Node >=20.19.0. Keep this floor independent from Kimi's npm
11
+ * package requirement: SpecRails launches an externally installed Kimi CLI and
12
+ * does not require the Kimi npm distribution.
13
+ */
14
+ export const MIN_NODE_VERSION = '20.19.0';
15
+ export function isSupportedNodeVersion(version) {
16
+ const parsed = /^v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(version.trim());
17
+ if (!parsed)
18
+ return false;
19
+ const actual = parsed.slice(1, 4).map(Number);
20
+ const minimum = MIN_NODE_VERSION.split('.').map(Number);
21
+ for (let index = 0; index < minimum.length; index++) {
22
+ if (actual[index] > minimum[index])
23
+ return true;
24
+ if (actual[index] < minimum[index])
25
+ return false;
26
+ }
27
+ return true;
28
+ }
8
29
  /**
9
30
  * Orchestrates every prerequisite check that must pass before the
10
31
  * installer proceeds to Phase 3 (scaffolding). Emits ok/warn/info
11
32
  * lines matching the retired bash output.
12
33
  */
13
34
  export async function checkPrerequisites(options) {
35
+ const nodeVersion = process.versions.node;
36
+ if (!isSupportedNodeVersion(nodeVersion)) {
37
+ throw new PrerequisiteError(`Node.js ${nodeVersion} is unsupported. SpecRails requires Node.js ` +
38
+ `${MIN_NODE_VERSION} or newer because OpenSpec 1.4.1 uses that runtime floor. ` +
39
+ 'Install a supported Node.js release from https://nodejs.org/');
40
+ }
41
+ ok(`Node.js: ${nodeVersion}`);
14
42
  if (!(await gitInstalled())) {
15
43
  throw new PrerequisiteError('git is required but not on PATH. Install git: https://git-scm.com/');
16
44
  }
@@ -40,18 +68,45 @@ export async function checkPrerequisites(options) {
40
68
  ok(`Provider: claude (--provider flag)`);
41
69
  }
42
70
  }
71
+ if (provider === 'kimi') {
72
+ if (availability.kimi) {
73
+ const v = await kimiVersion();
74
+ if (!isSupportedKimiVersion(v) && !options.skipPrereqs) {
75
+ throw new PrerequisiteError(`Kimi Code ${v} is unsupported. Upgrade to ${MIN_KIMI_VERSION} or newer: ` +
76
+ 'https://www.kimi.com/code/docs/en/kimi-code-cli/guides/getting-started.html');
77
+ }
78
+ ok(`Kimi Code CLI: ${v}`);
79
+ }
80
+ else if (options.explicitProvider === 'kimi') {
81
+ if (!options.skipPrereqs) {
82
+ throw new PrerequisiteError('Kimi Code CLI is not installed. Install it from https://www.kimi.com/code/docs/en/ ' +
83
+ 'and retry, or run with SPECRAILS_SKIP_PREREQS=1 for fixture generation.');
84
+ }
85
+ ok('Provider: kimi (--provider flag)');
86
+ }
87
+ }
43
88
  // 1.3 Authentication for the selected provider.
44
89
  if (provider === 'claude') {
45
90
  await assertClaudeAuthenticated({ skipPrereqs: options.skipPrereqs });
46
91
  ok('Claude: authenticated');
47
92
  }
93
+ if (provider === 'kimi' && availability.kimi) {
94
+ const status = await assertKimiAuthenticated({ skipPrereqs: options.skipPrereqs });
95
+ if (status === 'authenticated') {
96
+ ok('Kimi: authentication evidence found');
97
+ }
98
+ else if (status === 'unknown') {
99
+ info('Kimi authentication could not be proven without a billable prompt; ' +
100
+ 'the first workflow will report 401/login errors. Run `kimi login` if needed.');
101
+ }
102
+ }
48
103
  // 1.4 npm — required for running the TUI and for the `update` command.
49
104
  if (!(await commandExists('npm'))) {
50
105
  if (options.skipPrereqs) {
51
106
  warn('npm not found (skipped — SPECRAILS_SKIP_PREREQS=1)');
52
107
  }
53
108
  else {
54
- throw new PrerequisiteError('npm is required but not on PATH. Install Node.js 20+ from https://nodejs.org/');
109
+ throw new PrerequisiteError(`npm is required but not on PATH. Install Node.js ${MIN_NODE_VERSION}+ from https://nodejs.org/`);
55
110
  }
56
111
  }
57
112
  else {
@@ -81,7 +136,6 @@ export async function checkPrerequisites(options) {
81
136
  if (ossSignals.isOss) {
82
137
  ok('OSS project detected (public repo + CI + CONTRIBUTING.md)');
83
138
  }
84
- // 1.8 JIRA CLI — silently skipped when missing (only relevant in enrich).
85
139
  return { availability, provider, ossSignals };
86
140
  }
87
141
  async function detectOssSignals(repoRoot, hasGh) {
@@ -1 +1 @@
1
- {"version":3,"file":"prereqs.js","sourceRoot":"","sources":["../../../src/installer/phases/prereqs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prereqs.js","sourceRoot":"","sources":["../../../src/installer/phases/prereqs.ts"],"names":[],"mappings":"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"}
@@ -3,17 +3,20 @@ import path from 'node:path';
3
3
  import { ProviderError } from '../util/errors.js';
4
4
  import { commandExists, runCommand } from '../util/exec.js';
5
5
  import { pathExists, readTextFile } from '../util/fs.js';
6
+ /** Oldest TypeScript Kimi Code CLI release covered by this integration. */
7
+ export const MIN_KIMI_VERSION = '0.27.0';
6
8
  /**
7
9
  * Detects which AI CLIs are on PATH. Runs `where` on Windows and
8
10
  * `which` on POSIX via the cross-platform commandExists helper.
9
11
  */
10
12
  export async function detectAvailability() {
11
- const [claude, codex, gemini] = await Promise.all([
13
+ const [claude, codex, gemini, kimi] = await Promise.all([
12
14
  commandExists('claude'),
13
15
  commandExists('codex'),
14
16
  commandExists('gemini'),
17
+ commandExists('kimi'),
15
18
  ]);
16
- return { claude, codex, gemini };
19
+ return { claude, codex, gemini, kimi };
17
20
  }
18
21
  /**
19
22
  * Returns the Claude CLI version string (stdout of `claude --version`)
@@ -28,13 +31,36 @@ export async function claudeVersion() {
28
31
  return 'unknown';
29
32
  }
30
33
  }
34
+ /** Returns the raw Kimi Code CLI version or `unknown` when it cannot be probed. */
35
+ export async function kimiVersion() {
36
+ try {
37
+ const { stdout, stderr } = await runCommand('kimi', ['--version'], {
38
+ inherit: false,
39
+ timeoutMs: 10_000,
40
+ });
41
+ return stdout.trim() || stderr.trim() || 'unknown';
42
+ }
43
+ catch {
44
+ return 'unknown';
45
+ }
46
+ }
47
+ /** Extracts a semver-like triple from version output such as `kimi-code 0.27.0`. */
48
+ export function parseCliVersion(raw) {
49
+ return /(?:^|[^\d])(\d+)\.(\d+)\.(\d+)(?:[^\d]|$)/.exec(raw)?.slice(1, 4).join('.') ?? null;
50
+ }
51
+ /** True when `raw` identifies a Kimi CLI at or above {@link MIN_KIMI_VERSION}. */
52
+ export function isSupportedKimiVersion(raw) {
53
+ const parsed = parseCliVersion(raw);
54
+ if (!parsed)
55
+ return false;
56
+ return compareVersionTriples(parsed, MIN_KIMI_VERSION) >= 0;
57
+ }
31
58
  /**
32
59
  * Resolves which provider the installer should use. Priority:
33
60
  * 1. Explicit `--provider claude` flag (already passed through args).
34
61
  * 2. Config file (read upstream in install-config.ts).
35
62
  * 3. Whichever CLI is installed.
36
63
  *
37
- * Codex-only installs error out — see design: Codex is "coming soon".
38
64
  * The caller may bypass prereq failures with `skipPrereqs: true`
39
65
  * (env `SPECRAILS_SKIP_PREREQS=1`).
40
66
  */
@@ -45,26 +71,33 @@ export async function resolveProvider(availability, options = {}) {
45
71
  return 'claude';
46
72
  if (options.explicit === 'gemini')
47
73
  return 'gemini';
74
+ if (options.explicit === 'kimi')
75
+ return 'kimi';
48
76
  // No multi-provider auto-pick beyond the historical Claude-first default: when
49
77
  // several CLIs are installed and no provider was requested, prefer Claude so
50
78
  // existing projects don't get re-bootstrapped onto a different provider. Users
51
- // pick codex/gemini via --provider or install-config.yaml.
79
+ // pick codex/gemini/kimi via --provider or install-config.yaml.
52
80
  if (availability.claude)
53
81
  return 'claude';
54
82
  if (availability.codex)
55
83
  return 'codex';
56
84
  if (availability.gemini)
57
85
  return 'gemini';
86
+ if (availability.kimi)
87
+ return 'kimi';
58
88
  if (options.skipPrereqs)
59
89
  return 'claude';
60
90
  throw new ProviderError('No AI CLI found. Install Claude Code (https://claude.ai/download), ' +
61
91
  'Codex CLI (https://developers.openai.com/codex), or ' +
62
- 'Gemini CLI (https://github.com/google-gemini/gemini-cli) before running specrails-core init.');
92
+ 'Gemini CLI (https://github.com/google-gemini/gemini-cli), or ' +
93
+ 'Kimi Code (https://www.kimi.com/code/docs/en/) before running specrails-core init.');
63
94
  }
64
95
  /**
65
96
  * Directory / filename conventions the provider dictates.
66
97
  * - Claude Code: .claude/ + CLAUDE.md
67
98
  * - Codex: .codex/ + AGENTS.md
99
+ * - Gemini CLI: .gemini/ + GEMINI.md
100
+ * - Kimi Code: .kimi-code/ + AGENTS.md
68
101
  */
69
102
  export function derivedPaths(provider) {
70
103
  if (provider === 'codex') {
@@ -73,7 +106,13 @@ export function derivedPaths(provider) {
73
106
  if (provider === 'gemini') {
74
107
  return { providerDir: '.gemini', instructionsFile: 'GEMINI.md' };
75
108
  }
76
- return { providerDir: '.claude', instructionsFile: 'CLAUDE.md' };
109
+ if (provider === 'kimi') {
110
+ return { providerDir: '.kimi-code', instructionsFile: '.kimi-code/AGENTS.md' };
111
+ }
112
+ if (provider === 'claude') {
113
+ return { providerDir: '.claude', instructionsFile: 'CLAUDE.md' };
114
+ }
115
+ throw new ProviderError(`Unsupported provider: ${String(provider)}`);
77
116
  }
78
117
  /**
79
118
  * Asserts that Claude Code is authenticated. Matches the three-path
@@ -96,6 +135,59 @@ export async function assertClaudeAuthenticated(options = {}) {
96
135
  ' Option 2 (OAuth): claude auth login',
97
136
  ].join('\n'));
98
137
  }
138
+ /**
139
+ * Bounded, non-billing Kimi authentication probe.
140
+ *
141
+ * Kimi 0.27 has no CLI command that proves managed OAuth readiness without
142
+ * starting a model request. We therefore recognise non-secret evidence (the
143
+ * managed credential file or a process-scoped model key), and honour explicit
144
+ * login failures emitted by `kimi doctor`. A successful `kimi doctor` only
145
+ * validates configuration, so it deliberately yields `unknown`.
146
+ */
147
+ export async function probeKimiAuthentication(options = {}) {
148
+ const env = options.env ?? process.env;
149
+ if (typeof env.KIMI_MODEL_API_KEY === 'string' &&
150
+ env.KIMI_MODEL_API_KEY.length > 0 &&
151
+ typeof env.KIMI_MODEL_NAME === 'string' &&
152
+ env.KIMI_MODEL_NAME.length > 0) {
153
+ return 'authenticated';
154
+ }
155
+ const kimiHome = options.kimiCodeHome ??
156
+ (typeof env.KIMI_CODE_HOME === 'string' && env.KIMI_CODE_HOME.length > 0
157
+ ? env.KIMI_CODE_HOME
158
+ : path.join(homedir(), '.kimi-code'));
159
+ if (pathExists(path.join(kimiHome, 'credentials', 'kimi-code.json'))) {
160
+ return 'authenticated';
161
+ }
162
+ try {
163
+ const { stdout, stderr } = await runCommand('kimi', ['doctor'], {
164
+ inherit: false,
165
+ timeoutMs: 10_000,
166
+ env,
167
+ });
168
+ return textReportsMissingKimiLogin(`${stdout}\n${stderr}`) ? 'unauthenticated' : 'unknown';
169
+ }
170
+ catch (error) {
171
+ const probe = error;
172
+ const text = `${probe.stdout ?? ''}\n${probe.stderr ?? ''}\n${probe.message ?? ''}`;
173
+ return textReportsMissingKimiLogin(text) ? 'unauthenticated' : 'unknown';
174
+ }
175
+ }
176
+ /**
177
+ * Rejects only a conclusive login failure. `unknown` is allowed because setup
178
+ * must not spend quota merely to prove authentication.
179
+ */
180
+ export async function assertKimiAuthenticated(options = {}) {
181
+ const status = await probeKimiAuthentication(options);
182
+ if (status !== 'unauthenticated' || options.skipPrereqs)
183
+ return status;
184
+ throw new ProviderError([
185
+ 'Kimi Code is installed but login is required.',
186
+ '',
187
+ ' Run: kimi login',
188
+ ' Then retry specrails-core init.',
189
+ ].join('\n'));
190
+ }
99
191
  async function hasClaudeApiKeyConfigured() {
100
192
  try {
101
193
  const { stdout } = await runCommand('claude', ['config', 'list'], { inherit: false });
@@ -117,4 +209,22 @@ async function hasClaudeOauthJson() {
117
209
  return false;
118
210
  }
119
211
  }
212
+ function textReportsMissingKimiLogin(raw) {
213
+ const text = raw.toLowerCase();
214
+ return (text.includes('login required') ||
215
+ text.includes('not logged in') ||
216
+ text.includes('not authenticated') ||
217
+ text.includes('please run kimi login') ||
218
+ text.includes('run `kimi login`'));
219
+ }
220
+ function compareVersionTriples(left, right) {
221
+ const a = left.split('.').map(Number);
222
+ const b = right.split('.').map(Number);
223
+ for (let i = 0; i < 3; i++) {
224
+ const diff = (a[i] ?? 0) - (b[i] ?? 0);
225
+ if (diff !== 0)
226
+ return diff;
227
+ }
228
+ return 0;
229
+ }
120
230
  //# sourceMappingURL=provider-detect.js.map