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
@@ -9,10 +9,11 @@
9
9
  * --yes - skip TUI, write defaults immediately
10
10
  */
11
11
 
12
- import { checkbox, select, Separator } from '@inquirer/prompts';
13
- import { writeFileSync, mkdirSync, existsSync } from 'node:fs';
12
+ import { select } from '@inquirer/prompts';
13
+ import { writeFileSync, mkdirSync, existsSync, readFileSync } from 'node:fs';
14
14
  import { execSync } from 'node:child_process';
15
15
  import { resolve } from 'node:path';
16
+ import { fileURLToPath } from 'node:url';
16
17
 
17
18
  // ─── Alternate screen buffer (fullscreen mode) ──────────────────────────────
18
19
 
@@ -31,51 +32,35 @@ function clearScreen() {
31
32
 
32
33
  // ─── Agent registry ───────────────────────────────────────────────────────────
33
34
 
35
+ // The three core agents are the complete shipped set. Extend an install with
36
+ // user-owned custom-* agents declared in a profile (.specrails/profiles/**) —
37
+ // the installer never ships or manages non-core agents.
34
38
  const AGENTS = [
35
- // Architecture
36
- { id: 'sr-architect', category: 'Architecture', description: 'Architecture design, change specs, implementation planning' },
37
- // Development
38
- { id: 'sr-developer', category: 'Development', description: 'Full-stack implementation across all layers' },
39
- { id: 'sr-frontend-developer', category: 'Development', description: 'Frontend implementation (React, Vue, Angular, etc.)' },
40
- { id: 'sr-backend-developer', category: 'Development', description: 'Backend specialization (APIs, databases, services)' },
41
- // Review
42
- { id: 'sr-reviewer', category: 'Review', description: 'General code review — the final quality gate' },
43
- { id: 'sr-frontend-reviewer', category: 'Review', description: 'Frontend review (UI, accessibility, performance)' },
44
- { id: 'sr-backend-reviewer', category: 'Review', description: 'Backend review (APIs, security, scalability)' },
45
- { id: 'sr-security-reviewer', category: 'Review', description: 'Security analysis — OWASP, vulnerabilities, hardening' },
46
- { id: 'sr-performance-reviewer', category: 'Review', description: 'Performance analysis — profiling, bottlenecks, optimization' },
47
- // Product
48
- { id: 'sr-product-manager', category: 'Product', description: 'Product discovery, VPC personas, backlog management' },
49
- { id: 'sr-product-analyst', category: 'Product', description: 'Backlog analysis, spec gap analysis, reporting' },
50
- // Utilities
51
- { id: 'sr-test-writer', category: 'Utilities', description: 'Comprehensive test generation (unit, integration, E2E)' },
52
- { id: 'sr-doc-sync', category: 'Utilities', description: 'Documentation sync — keeps docs aligned with code' },
53
- { id: 'sr-merge-resolver', category: 'Utilities', description: 'Merge conflict resolution with context awareness' },
39
+ { id: 'sr-architect', category: 'Architecture', description: 'Architecture design, change specs, implementation planning' },
40
+ { id: 'sr-developer', category: 'Development', description: 'Full-stack implementation across all layers' },
41
+ { id: 'sr-reviewer', category: 'Review', description: 'Code review — correctness, tests, security, performance' },
54
42
  ];
55
43
 
56
44
  const ALL_AGENT_IDS = AGENTS.map(a => a.id);
57
45
 
58
- // Core agents — the three that every install requires. The implement
59
- // pipeline depends on exactly these three. All other agents (including
60
- // sr-merge-resolver) are optional add-ons selected by the user.
46
+ // Core agents — the three the installer ships, which the implement pipeline
47
+ // depends on. They are the COMPLETE shipped set; any extra specialist comes
48
+ // from a user-authored profile (custom-*), never the installer.
61
49
  const CORE_AGENTS = new Set([
62
50
  'sr-architect',
63
51
  'sr-developer',
64
52
  'sr-reviewer',
65
53
  ]);
66
54
 
67
- // Only the three CORE agents are pre-selected. Optional agents (sr-merge-resolver,
68
- // product manager, test writer, layer specialists, reviewers, utilities) are
69
- // opt-in so the default install is as lean as possible. Users can add optional
70
- // agents via `/specrails:enrich` or by re-running init.
55
+ // The three core agents ARE the full set; the selection always equals them.
71
56
  const DEFAULT_SELECTED = new Set([
72
57
  ...CORE_AGENTS,
73
58
  ]);
74
59
 
75
- // ─── Model presets (Claude only — see PROVIDER_DEFAULT_MODEL) ────────────────────
76
- // Claude has real cost/quality tiers (sonnet/haiku/opus). Codex and gemini are
77
- // single-model in the scaffold (it hardcodes the per-agent model and ignores the
78
- // install-config preset), so these presets apply to Claude only.
60
+ // ─── Model presets ──────────────────────────────────────────────────────────────
61
+ // Claude exposes distinct Core-defined cost/quality tiers. Other providers use
62
+ // an explicit provider-native default for every named preset; preset names never
63
+ // imply that Claude aliases should be copied into another provider's config.
79
64
 
80
65
  const MODEL_PRESETS = {
81
66
  balanced: {
@@ -89,22 +74,30 @@ const MODEL_PRESETS = {
89
74
  overrides: {},
90
75
  },
91
76
  max: {
92
- label: 'Max quality — Opus for architect + PM, Sonnet for rest',
77
+ label: 'Max quality — Opus for the architect, Sonnet for the rest',
93
78
  defaults: 'sonnet',
94
- overrides: { 'sr-architect': 'opus', 'sr-product-manager': 'opus' },
79
+ overrides: { 'sr-architect': 'opus' },
95
80
  },
96
81
  };
97
82
 
98
- // Per-provider default agent model. For codex/gemini the scaffold hardcodes this
99
- // (the install-config model is advisory), so the TUI writes the provider's real
100
- // model instead of a Claude-flavoured preset. Keep in sync with scaffold.ts
101
- // (GEMINI_DEFAULT_MODEL / the codex config.toml model).
83
+ // Per-provider default agent model. Keep in sync with install-config.ts and the
84
+ // provider renderers.
102
85
  const PROVIDER_DEFAULT_MODEL = {
103
86
  claude: 'sonnet',
104
87
  codex: 'gpt-5.5-mini',
105
88
  gemini: 'gemini-3.5-flash',
89
+ kimi: 'k3',
106
90
  };
107
91
 
92
+ function resolveProviderModelPreset(provider, preset = 'balanced') {
93
+ if (provider === 'claude') return MODEL_PRESETS[preset];
94
+ return {
95
+ label: `${PROVIDER_DEFAULT_MODEL[provider]} for all agents`,
96
+ defaults: PROVIDER_DEFAULT_MODEL[provider],
97
+ overrides: {},
98
+ };
99
+ }
100
+
108
101
  // ─── Provider registry ─────────────────────────────────────────────────────────
109
102
  // Single source of truth for the AI CLIs the TUI can target. Add a provider here
110
103
  // and it flows through detection, the --provider flag, and the interactive picker.
@@ -112,8 +105,19 @@ const PROVIDERS = [
112
105
  { id: 'claude', label: 'Claude Code (recommended)', versionCmd: 'claude --version', installLabel: 'Claude Code', installUrl: 'https://claude.ai/download' },
113
106
  { id: 'codex', label: 'Codex (OpenAI)', versionCmd: 'codex --version', installLabel: 'Codex CLI', installUrl: 'https://developers.openai.com/codex' },
114
107
  { id: 'gemini', label: 'Gemini CLI (Google)', versionCmd: 'gemini --version', installLabel: 'Gemini CLI', installUrl: 'https://github.com/google-gemini/gemini-cli' },
108
+ { id: 'kimi', label: 'Kimi Code', versionCmd: 'kimi --version', installLabel: 'Kimi Code', installUrl: 'https://www.kimi.com/code/docs/en/' },
115
109
  ];
116
110
  const VALID_PROVIDER_IDS = new Set(PROVIDERS.map(p => p.id));
111
+ const providerProbeTimeoutOverride = Number.parseInt(
112
+ process.env.SPECRAILS_PROVIDER_PROBE_TIMEOUT_MS ?? '',
113
+ 10,
114
+ );
115
+ const PROVIDER_PROBE_TIMEOUT_MS =
116
+ Number.isFinite(providerProbeTimeoutOverride) &&
117
+ providerProbeTimeoutOverride >= 100 &&
118
+ providerProbeTimeoutOverride <= 30_000
119
+ ? providerProbeTimeoutOverride
120
+ : 3_000;
117
121
 
118
122
  // ─── Helpers ──────────────────────────────────────────────────────────────────
119
123
 
@@ -121,25 +125,46 @@ const VALID_PROVIDER_IDS = new Set(PROVIDERS.map(p => p.id));
121
125
  function detectInstalledProviders() {
122
126
  const installed = new Set();
123
127
  for (const p of PROVIDERS) {
124
- try { execSync(p.versionCmd, { stdio: 'ignore' }); installed.add(p.id); } catch { /* not installed */ }
128
+ try {
129
+ execSync(p.versionCmd, {
130
+ stdio: 'ignore',
131
+ timeout: PROVIDER_PROBE_TIMEOUT_MS,
132
+ });
133
+ installed.add(p.id);
134
+ } catch { /* absent, broken, or hung — do not block the installer */ }
125
135
  }
126
136
  return installed;
127
137
  }
128
138
 
129
- // Parse `--provider <id>` or `--provider=<id>` from process.argv. Returns a valid
130
- // provider id or null (unknown values warn-then-null so the TUI falls back to the
131
- // interactive picker).
132
- function parseProviderArg() {
133
- const args = process.argv.slice(2);
139
+ // Parse `--provider <id>` or `--provider=<id>` from process.argv. An explicit
140
+ // but invalid value is a configuration error, never an invitation to silently
141
+ // open a picker and install a different provider.
142
+ function parseProviderArg(args = process.argv.slice(2)) {
134
143
  for (let i = 0; i < args.length; i++) {
135
144
  const a = args[i];
136
- if (a === '--provider' && args[i + 1]) {
145
+ if (a === '--provider') {
146
+ if (!args[i + 1] || args[i + 1].startsWith('-')) {
147
+ throw new Error(
148
+ `--provider requires one of: ${[...VALID_PROVIDER_IDS].join(', ')}`,
149
+ );
150
+ }
137
151
  const v = args[i + 1].trim().toLowerCase();
138
- return VALID_PROVIDER_IDS.has(v) ? v : null;
152
+ if (!VALID_PROVIDER_IDS.has(v)) {
153
+ throw new Error(
154
+ `unsupported --provider '${args[i + 1]}' (expected: ${[...VALID_PROVIDER_IDS].join(', ')})`,
155
+ );
156
+ }
157
+ return v;
139
158
  }
140
159
  if (a.startsWith('--provider=')) {
141
160
  const v = a.slice('--provider='.length).trim().toLowerCase();
142
- return VALID_PROVIDER_IDS.has(v) ? v : null;
161
+ if (!VALID_PROVIDER_IDS.has(v)) {
162
+ throw new Error(
163
+ `unsupported --provider '${a.slice('--provider='.length)}' ` +
164
+ `(expected: ${[...VALID_PROVIDER_IDS].join(', ')})`,
165
+ );
166
+ }
167
+ return v;
143
168
  }
144
169
  }
145
170
  return null;
@@ -155,26 +180,6 @@ function detectGitRoot(dir) {
155
180
  }
156
181
  }
157
182
 
158
- function buildCheckboxChoices() {
159
- const choices = [];
160
- let currentCategory = null;
161
- for (const agent of AGENTS) {
162
- if (agent.category !== currentCategory) {
163
- if (currentCategory !== null) choices.push(new Separator(''));
164
- choices.push(new Separator(`── ${agent.category} ${'─'.repeat(Math.max(0, 46 - agent.category.length))}`));
165
- currentCategory = agent.category;
166
- }
167
- const isCore = CORE_AGENTS.has(agent.id);
168
- choices.push({
169
- value: agent.id,
170
- name: `${agent.id.padEnd(28)} ${agent.description}${isCore ? ' (core)' : ''}`,
171
- checked: DEFAULT_SELECTED.has(agent.id),
172
- disabled: isCore ? 'core — always installed' : false,
173
- });
174
- }
175
- return choices;
176
- }
177
-
178
183
  function writeInstallConfig(specrailsDir, cfg) {
179
184
  if (!existsSync(specrailsDir)) mkdirSync(specrailsDir, { recursive: true });
180
185
 
@@ -188,7 +193,6 @@ function writeInstallConfig(specrailsDir, cfg) {
188
193
  '# Re-run: npx specrails-core@latest init to regenerate',
189
194
  `version: 1`,
190
195
  `provider: ${cfg.provider}`,
191
- `tier: ${cfg.tier}`,
192
196
  `agents:`,
193
197
  ` selected: [${cfg.selectedAgents.join(', ')}]`,
194
198
  ` excluded: [${cfg.excludedAgents.join(', ')}]`,
@@ -205,23 +209,46 @@ function writeInstallConfig(specrailsDir, cfg) {
205
209
  function writeDefaultConfig(specrailsDir, provider) {
206
210
  const defaultSelected = [...DEFAULT_SELECTED];
207
211
  const defaultExcluded = ALL_AGENT_IDS.filter(id => !DEFAULT_SELECTED.has(id));
212
+ const modelSelection = resolveProviderModelPreset(provider);
208
213
  writeInstallConfig(specrailsDir, {
209
214
  provider,
210
- tier: 'full',
211
215
  selectedAgents: defaultSelected,
212
216
  excludedAgents: defaultExcluded,
213
217
  modelPreset: 'balanced',
214
- modelDefaults: PROVIDER_DEFAULT_MODEL[provider] ?? 'sonnet',
215
- modelOverrides: {},
218
+ modelDefaults: modelSelection.defaults,
219
+ modelOverrides: modelSelection.overrides,
216
220
  });
217
221
  }
218
222
 
223
+ function scaffoldDefaultProfile(specrailsDir, provider) {
224
+ try {
225
+ const scriptDir = fileURLToPath(new URL('..', import.meta.url));
226
+ const templateName = provider === 'kimi' ? 'kimi-default.json' : 'default.json';
227
+ const templatePath = resolve(scriptDir, 'templates/profiles', templateName);
228
+ const profilesDir = resolve(specrailsDir, 'profiles');
229
+ // Provider-bound defaults must coexist in a multi-provider project. Keep
230
+ // the historical filename for Claude and give Kimi its own stable fallback.
231
+ const targetName = provider === 'kimi' ? 'kimi-default.json' : 'project-default.json';
232
+ const targetPath = resolve(profilesDir, targetName);
233
+ if (existsSync(templatePath) && !existsSync(targetPath)) {
234
+ mkdirSync(profilesDir, { recursive: true });
235
+ writeFileSync(targetPath, readFileSync(templatePath));
236
+ console.log(` ✓ Profile scaffolded at .specrails/profiles/${targetName}`);
237
+ } else if (existsSync(targetPath)) {
238
+ console.log(` ↷ Profile already exists at .specrails/profiles/${targetName} — skipped`);
239
+ }
240
+ } catch (e) {
241
+ console.warn(` ⚠ Could not scaffold profile: ${e.message}`);
242
+ }
243
+ }
244
+
219
245
  // ─── Main ─────────────────────────────────────────────────────────────────────
220
246
 
221
247
  async function run() {
222
248
  const rawArgs = process.argv.slice(2);
223
249
  const autoYes = rawArgs.includes('--yes') || rawArgs.includes('-y');
224
250
  const withProfiles = rawArgs.includes('--with-profiles');
251
+ const argvProvider = parseProviderArg(rawArgs);
225
252
  // First positional arg (skipping flag values that follow `--provider`,
226
253
  // `--root-dir`, etc.) is the target directory.
227
254
  const FLAGS_WITH_VALUES = new Set(['--provider', '--root-dir', '--from-config']);
@@ -246,35 +273,12 @@ async function run() {
246
273
 
247
274
  const specrailsDir = resolve(rootDir, '.specrails');
248
275
 
249
- // Optional: scaffold .specrails/profiles/project-default.json from the shipped template.
250
- // Off by default to keep standalone installs zero-noise.
251
- if (withProfiles) {
252
- try {
253
- const { readFileSync, writeFileSync, existsSync, mkdirSync } = await import('node:fs');
254
- const { dirname } = await import('node:path');
255
- const scriptDir = new URL('..', import.meta.url).pathname;
256
- const templatePath = resolve(scriptDir, 'templates/profiles/default.json');
257
- const profilesDir = resolve(specrailsDir, 'profiles');
258
- const targetPath = resolve(profilesDir, 'project-default.json');
259
- if (existsSync(templatePath) && !existsSync(targetPath)) {
260
- mkdirSync(profilesDir, { recursive: true });
261
- writeFileSync(targetPath, readFileSync(templatePath));
262
- console.log(` ✓ Profile scaffolded at .specrails/profiles/project-default.json`);
263
- } else if (existsSync(targetPath)) {
264
- console.log(` ↷ Profile already exists at .specrails/profiles/project-default.json — skipped`);
265
- }
266
- } catch (e) {
267
- console.warn(` ⚠ Could not scaffold profile: ${e.message}`);
268
- }
269
- }
270
-
271
276
  // Auto-yes: write defaults and exit (no TUI needed)
272
277
  //
273
278
  // Honours an explicit --provider <id> argv flag when present; otherwise
274
279
  // picks claude → codex → first-detected. Errors only when none detected.
275
280
  if (autoYes) {
276
281
  const installed = detectInstalledProviders();
277
- const argvProvider = parseProviderArg();
278
282
  let provider;
279
283
  if (argvProvider) {
280
284
  if (!installed.has(argvProvider)) {
@@ -291,15 +295,16 @@ async function run() {
291
295
  provider = PROVIDERS.find(p => installed.has(p.id))?.id;
292
296
  if (!provider) {
293
297
  console.error('');
294
- console.error(' ⚠ No supported AI CLI detected on PATH (Claude Code, Codex, or Gemini CLI).');
298
+ console.error(' ⚠ No supported AI CLI detected on PATH (Claude Code, Codex, Gemini CLI, or Kimi Code).');
295
299
  for (const p of PROVIDERS) console.error(` Install ${p.installLabel}: ${p.installUrl}`);
296
300
  console.error('');
297
301
  process.exit(1);
298
302
  }
299
303
  }
304
+ if (withProfiles) scaffoldDefaultProfile(specrailsDir, provider);
300
305
  writeDefaultConfig(specrailsDir, provider);
301
306
  console.log(` ✓ Default config written to .specrails/install-config.yaml`);
302
- console.log(` ✓ Provider: ${provider}, Tier: full, Agents: ${DEFAULT_SELECTED.size}/${ALL_AGENT_IDS.length}, Preset: balanced\n`);
307
+ console.log(` ✓ Provider: ${provider}, Agents: ${DEFAULT_SELECTED.size}, Preset: balanced\n`);
303
308
  return;
304
309
  }
305
310
 
@@ -328,7 +333,6 @@ async function run() {
328
333
  // ── Step 1: Provider ────────────────────────────────────────────────────────
329
334
 
330
335
  const installed = detectInstalledProviders();
331
- const argvProvider = parseProviderArg();
332
336
  let provider;
333
337
 
334
338
  if (argvProvider) {
@@ -359,61 +363,30 @@ async function run() {
359
363
  });
360
364
  }
361
365
  }
366
+ if (withProfiles) scaffoldDefaultProfile(specrailsDir, provider);
362
367
 
363
- // ── Step 2: Installation tier ───────────────────────────────────────────────
368
+ // ── Agents: the three core agents are the full shipped set ──────────────────
364
369
 
365
370
  clearScreen();
366
371
  console.log(` Provider: ${provider}\n`);
372
+ console.log(' Installing the three core agents: sr-architect, sr-developer, sr-reviewer.');
373
+ console.log(' Add specialists later via a profile (.specrails/profiles/**) with custom-* agents.\n');
367
374
 
368
- const tier = await select({
369
- message: 'Installation tier:',
370
- default: 'quick',
371
- choices: [
372
- {
373
- value: 'quick',
374
- name: 'Quick — Ready to use immediately (recommended)',
375
- description: 'Agents installed with sensible defaults. No AI step required.',
376
- },
377
- {
378
- value: 'full',
379
- name: 'Full — AI-powered setup',
380
- description: 'After install, run /specrails:enrich to AI-customize all agents for your codebase',
381
- },
382
- ],
383
- });
384
-
385
- // ── Step 3: Agent selection ─────────────────────────────────────────────────
386
-
387
- clearScreen();
388
- console.log(` Provider: ${provider} | Tier: ${tier}\n`);
389
- console.log(' Select agents to install. Space = toggle, a = all/none, Enter = confirm.\n');
390
-
391
- // Use most of the terminal height for agent list (reserve 6 lines for header/footer)
392
- const termRows = process.stdout.rows || 24;
393
- const agentPageSize = Math.max(10, termRows - 6);
394
-
395
- const userSelected = await checkbox({
396
- message: 'Agents to install:',
397
- choices: buildCheckboxChoices(),
398
- pageSize: agentPageSize,
399
- // Core agents are installed unconditionally (disabled rows above), so an
400
- // empty optional selection is valid — means "only core, nothing extra".
401
- });
402
-
403
- // Core agents are always included regardless of checkbox state
404
- const selectedAgents = [...new Set([...CORE_AGENTS, ...userSelected])];
375
+ const selectedAgents = [...CORE_AGENTS];
405
376
  const excludedAgents = ALL_AGENT_IDS.filter(id => !selectedAgents.includes(id));
406
377
 
407
- // ── Step 4: Model preset ────────────────────────────────────────────────────
378
+ // ── Step 2: Model preset ────────────────────────────────────────────────────
408
379
 
409
380
  clearScreen();
410
- console.log(` Provider: ${provider} | Tier: ${tier} | Agents: ${selectedAgents.length}/${ALL_AGENT_IDS.length}\n`);
381
+ console.log(` Provider: ${provider} | Agents: ${selectedAgents.length}\n`);
411
382
 
412
- // Claude exposes real model tiers; codex/gemini are single-model in the scaffold,
413
- // so skip the (Claude-flavoured) preset picker for them and use the fixed model.
383
+ // Claude exposes real model tiers. Other providers retain the same config
384
+ // shape but resolve the preset through their provider-native catalog.
414
385
  let modelPreset = 'balanced';
415
- let modelDefaults = PROVIDER_DEFAULT_MODEL[provider] ?? 'sonnet';
416
- let modelOverrides = {};
386
+ let {
387
+ defaults: modelDefaults,
388
+ overrides: modelOverrides,
389
+ } = resolveProviderModelPreset(provider, modelPreset);
417
390
  if (provider === 'claude') {
418
391
  modelPreset = await select({
419
392
  message: 'Model configuration:',
@@ -424,7 +397,7 @@ async function run() {
424
397
  });
425
398
  ({ defaults: modelDefaults, overrides: modelOverrides } = MODEL_PRESETS[modelPreset]);
426
399
  } else {
427
- console.log(` → Model: ${modelDefaults} (${provider} uses one model for all agents)\n`);
400
+ console.log(` → Model: ${modelDefaults} (${provider} provider preset)\n`);
428
401
  }
429
402
 
430
403
  // ── Write config & exit fullscreen ──────────────────────────────────────────
@@ -433,7 +406,6 @@ async function run() {
433
406
 
434
407
  writeInstallConfig(specrailsDir, {
435
408
  provider,
436
- tier,
437
409
  selectedAgents,
438
410
  excludedAgents,
439
411
  modelPreset,
@@ -442,12 +414,8 @@ async function run() {
442
414
  });
443
415
 
444
416
  console.log(`\n ✓ Config written to .specrails/install-config.yaml`);
445
- console.log(` ✓ Provider: ${provider} | Tier: ${tier} | Agents: ${selectedAgents.length}/${ALL_AGENT_IDS.length} | Preset: ${modelPreset}`);
446
- if (tier === 'full') {
447
- console.log(`\n Next: run /specrails:enrich --from-config inside ${provider} to AI-customize your agents.\n`);
448
- } else {
449
- console.log(`\n Agents will be installed with template defaults.\n`);
450
- }
417
+ console.log(` ✓ Provider: ${provider} | Agents: ${selectedAgents.length} | Preset: ${modelPreset}`);
418
+ console.log(`\n Agents will be installed with template defaults — no follow-up step required.\n`);
451
419
  }
452
420
 
453
421
  run().catch(err => {
@@ -35,7 +35,7 @@ Each check is displayed as ✅ (pass) or ❌ (fail with fix instruction).
35
35
 
36
36
  On all checks passed:
37
37
  ```
38
- All 6 checks passed. Run /specrails:get-backlog-specs to get started.
38
+ All 6 checks passed. Run /specrails:implement to get started.
39
39
  ```
40
40
 
41
41
  On failure:
@@ -8,7 +8,7 @@
8
8
  * Phase 5 deletes the shell scripts, the `bin/` dispatcher collapses
9
9
  * to a single `import { main } from './dist/installer/cli.js'` call.
10
10
  */
11
- import { readFileSync } from 'node:fs';
11
+ import { readFileSync, realpathSync } from 'node:fs';
12
12
  import path from 'node:path';
13
13
  import { fileURLToPath, pathToFileURL } from 'node:url';
14
14
  import { runDoctor } from './commands/doctor.js';
@@ -73,7 +73,7 @@ export function parseArgs(argv) {
73
73
  function usageText() {
74
74
  return [
75
75
  '',
76
- 'specrails-core — AI agent workflow system',
76
+ 'specrails-core — Provider-independent AI agent workflow system',
77
77
  '',
78
78
  'Usage:',
79
79
  ' specrails-core <command> [options]',
@@ -185,13 +185,23 @@ export async function main(argv = process.argv.slice(2)) {
185
185
  *
186
186
  * Comparing `import.meta.url` against `process.argv[1]` keeps the guard inert on
187
187
  * import (so unit tests that `import { main }` never trigger a process.exit).
188
+ *
189
+ * SYMLINK CAVEAT: Node's ESM loader realpaths the entry module, so
190
+ * `import.meta.url` is the REAL path while `process.argv[1]` is the literal
191
+ * spawn argument. When the package lives behind a symlinked path (macOS
192
+ * `os.tmpdir()` = /var/folders → /private/var/folders — exactly where
193
+ * specrails-desktop's core-update channel stages the download), the raw
194
+ * comparison fails and main() silently never runs (child exits 0 having done
195
+ * nothing). Compare against the realpathed argv[1] too.
188
196
  */
189
197
  const isDirectRun = (() => {
190
198
  try {
191
199
  const entry = process.argv[1];
192
200
  if (!entry)
193
201
  return false;
194
- return import.meta.url === pathToFileURL(entry).href;
202
+ if (import.meta.url === pathToFileURL(entry).href)
203
+ return true;
204
+ return import.meta.url === pathToFileURL(realpathSync(entry)).href;
195
205
  }
196
206
  catch {
197
207
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/installer/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/installer/cli.ts"],"names":[],"mappings":"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"}