specrails-core 4.12.0 → 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 (76) hide show
  1. package/README.md +49 -78
  2. package/bin/specrails-core.mjs +18 -98
  3. package/bin/tui-installer.mjs +22 -105
  4. package/commands/doctor.md +1 -1
  5. package/dist/installer/cli.js +12 -2
  6. package/dist/installer/cli.js.map +1 -1
  7. package/dist/installer/commands/doctor.js +3 -5
  8. package/dist/installer/commands/doctor.js.map +1 -1
  9. package/dist/installer/commands/init.js +23 -19
  10. package/dist/installer/commands/init.js.map +1 -1
  11. package/dist/installer/commands/update.js +17 -16
  12. package/dist/installer/commands/update.js.map +1 -1
  13. package/dist/installer/commands/v5-migration.js +119 -0
  14. package/dist/installer/commands/v5-migration.js.map +1 -0
  15. package/dist/installer/phases/install-config.js +3 -6
  16. package/dist/installer/phases/install-config.js.map +1 -1
  17. package/dist/installer/phases/manifest.js +2 -6
  18. package/dist/installer/phases/manifest.js.map +1 -1
  19. package/dist/installer/phases/prereqs.js +0 -1
  20. package/dist/installer/phases/prereqs.js.map +1 -1
  21. package/dist/installer/phases/scaffold.js +38 -148
  22. package/dist/installer/phases/scaffold.js.map +1 -1
  23. package/package.json +1 -1
  24. package/schemas/profile.v1.json +1 -1
  25. package/templates/agents/sr-architect.md +30 -0
  26. package/templates/agents/sr-developer.md +21 -8
  27. package/templates/agents/sr-reviewer.md +44 -31
  28. package/templates/codex-skills/batch-implement/SKILL.md +9 -32
  29. package/templates/codex-skills/implement/SKILL.md +61 -143
  30. package/templates/codex-skills/rails/sr-architect/SKILL.md +38 -20
  31. package/templates/codex-skills/rails/sr-developer/SKILL.md +29 -10
  32. package/templates/codex-skills/rails/sr-reviewer/SKILL.md +21 -10
  33. package/templates/commands/specrails/doctor.md +1 -1
  34. package/templates/commands/specrails/implement.md +117 -288
  35. package/templates/commands/specrails/memory-inspect.md +6 -4
  36. package/templates/commands/specrails/propose-spec.md +1 -1
  37. package/templates/commands/specrails/refactor-recommender.md +8 -51
  38. package/templates/commands/specrails/retry.md +12 -48
  39. package/templates/commands/specrails/telemetry.md +1 -1
  40. package/templates/gemini-commands/implement.toml +9 -0
  41. package/templates/profiles/default.json +5 -18
  42. package/commands/enrich.md +0 -1456
  43. package/templates/agents/sr-backend-developer.md +0 -91
  44. package/templates/agents/sr-backend-reviewer.md +0 -152
  45. package/templates/agents/sr-doc-sync.md +0 -247
  46. package/templates/agents/sr-frontend-developer.md +0 -85
  47. package/templates/agents/sr-frontend-reviewer.md +0 -145
  48. package/templates/agents/sr-merge-resolver.md +0 -195
  49. package/templates/agents/sr-performance-reviewer.md +0 -186
  50. package/templates/agents/sr-product-analyst.md +0 -36
  51. package/templates/agents/sr-product-manager.md +0 -148
  52. package/templates/agents/sr-security-reviewer.md +0 -191
  53. package/templates/agents/sr-test-writer.md +0 -176
  54. package/templates/codex-skills/enrich/SKILL.md +0 -191
  55. package/templates/codex-skills/merge-resolve/SKILL.md +0 -88
  56. package/templates/codex-skills/rails/sr-backend-developer/SKILL.md +0 -93
  57. package/templates/codex-skills/rails/sr-backend-reviewer/SKILL.md +0 -120
  58. package/templates/codex-skills/rails/sr-doc-sync/SKILL.md +0 -124
  59. package/templates/codex-skills/rails/sr-frontend-developer/SKILL.md +0 -106
  60. package/templates/codex-skills/rails/sr-frontend-reviewer/SKILL.md +0 -111
  61. package/templates/codex-skills/rails/sr-merge-resolver/SKILL.md +0 -156
  62. package/templates/codex-skills/rails/sr-performance-reviewer/SKILL.md +0 -109
  63. package/templates/codex-skills/rails/sr-product-analyst/SKILL.md +0 -85
  64. package/templates/codex-skills/rails/sr-product-manager/SKILL.md +0 -131
  65. package/templates/codex-skills/rails/sr-security-reviewer/SKILL.md +0 -121
  66. package/templates/codex-skills/rails/sr-test-writer/SKILL.md +0 -115
  67. package/templates/commands/specrails/auto-propose-backlog-specs.md +0 -312
  68. package/templates/commands/specrails/enrich.md +0 -1456
  69. package/templates/commands/specrails/get-backlog-specs.md +0 -226
  70. package/templates/commands/specrails/merge-resolve.md +0 -172
  71. package/templates/commands/specrails/reconfig.md +0 -80
  72. package/templates/commands/specrails/vpc-drift.md +0 -405
  73. package/templates/commands/test.md +0 -58
  74. package/templates/personas/persona.md +0 -43
  75. package/templates/personas/the-maintainer.md +0 -98
  76. package/templates/settings/perf-thresholds.yml +0 -25
@@ -6,10 +6,9 @@ import { atomicSymlinkSwap, copyDir, copyFile, isDir, isSymlink, listDir, mkdirp
6
6
  import { info, ok, warn } from '../util/logger.js';
7
7
  import { buildManifest, writeManifestFiles } from './manifest.js';
8
8
  /**
9
- * The three baseline agents that every specrails install requires.
10
- * These are the only agents guaranteed to be present the implement
11
- * pipeline depends on all three. sr-merge-resolver and every other
12
- * agent are optional add-ons selected at install time.
9
+ * The three baseline agents the COMPLETE set of agents the installer
10
+ * ships. The implement pipeline depends on all three. Any additional agent
11
+ * comes from a user-authored profile (`custom-*`), never the installer.
13
12
  *
14
13
  * Mirrors the `allOf` baseline in schemas/profile.v1.json — update
15
14
  * both files together if this set ever changes.
@@ -19,11 +18,6 @@ export const CORE_AGENTS = new Set([
19
18
  'sr-developer',
20
19
  'sr-reviewer',
21
20
  ]);
22
- /**
23
- * Agents excluded from the quick tier because they require a full
24
- * /specrails:enrich persona pass to function correctly.
25
- */
26
- const QUICK_EXCLUDED_AGENTS = new Set(['sr-product-manager', 'sr-product-analyst']);
27
21
  /**
28
22
  * Gemini built-in tool ids granted to every `.gemini/agents/sr-*.md` subagent.
29
23
  * (Validated headless in the desktop spike — read/write/shell/glob/grep.) Because
@@ -141,14 +135,6 @@ const GEMINI_DEFAULT_MODEL = 'gemini-3.5-flash';
141
135
  // one with `max_turns: 40` → not found, one without → loads). The 30-turn default
142
136
  // cap is instead absorbed by the implement.toml MAX_TURNS → re-delegate/resume
143
137
  // contract. Re-introduce only if a future gemini build is reconfirmed to accept it.
144
- /**
145
- * Skills excluded from the quick tier because they depend on
146
- * VPC-only agents (sr-product-manager, sr-product-analyst).
147
- */
148
- const QUICK_EXCLUDED_SKILLS = new Set([
149
- 'sr-auto-propose-backlog-specs',
150
- 'sr-get-backlog-specs',
151
- ]);
152
138
  /**
153
139
  * Claude top-level `sr-*` skills, GENERATED at install time from their
154
140
  * canonical slash-command body under `templates/commands/specrails/<command>.md`.
@@ -178,26 +164,7 @@ const SKILL_FROM_COMMAND = {
178
164
  command: 'why',
179
165
  description: 'sr:why — Search explanation records written by specrails agents during the OpenSpec implementation pipeline.',
180
166
  },
181
- 'sr-get-backlog-specs': {
182
- command: 'get-backlog-specs',
183
- description: 'sr:get-backlog-specs — View product-driven backlog from GitHub Issues and propose top 3 for implementation.',
184
- },
185
- 'sr-auto-propose-backlog-specs': {
186
- command: 'auto-propose-backlog-specs',
187
- description: 'sr:auto-propose-backlog-specs — Generate new feature ideas through product discovery, create GitHub Issues.',
188
- },
189
167
  };
190
- /**
191
- * Command → required agent dependency map. A command is excluded
192
- * from the quick tier when its required agent was excluded (i.e.
193
- * VPC-dependent) or when the feature flag (Agent Teams) is off.
194
- */
195
- const COMMAND_AGENT_DEPENDENCIES = [
196
- { command: 'auto-propose-backlog-specs', requires: ['sr-product-manager'] },
197
- { command: 'vpc-drift', requires: ['sr-product-manager', 'sr-product-analyst'] },
198
- { command: 'get-backlog-specs', requires: ['sr-product-analyst'] },
199
- { command: 'merge-resolve', requires: ['sr-merge-resolver'] },
200
- ];
201
168
  /**
202
169
  * Agents that write "explanation" memory records. When any of them
203
170
  * ships we also need a shared `.claude/agent-memory/explanations/`
@@ -267,7 +234,6 @@ export function scaffoldInstallation(input) {
267
234
  // Codex skills live under <providerDir>/skills/ (e.g. .codex/skills/).
268
235
  // The pre-§18 code wrote to `.agents/skills/` which codex doesn't read;
269
236
  // that was a placeholder name from the gated state.
270
- mk(path.join(input.artifactRoot, input.providerDir, 'skills', 'enrich'));
271
237
  mk(path.join(input.artifactRoot, input.providerDir, 'skills', 'doctor'));
272
238
  mk(path.join(input.artifactRoot, input.providerDir, 'skills', 'rails'));
273
239
  }
@@ -291,7 +257,6 @@ export function scaffoldInstallation(input) {
291
257
  mk(path.join(setupTemplates, 'commands'));
292
258
  mk(path.join(setupTemplates, 'skills'));
293
259
  mk(path.join(setupTemplates, 'rules'));
294
- mk(path.join(setupTemplates, 'personas'));
295
260
  mk(path.join(setupTemplates, 'claude-md'));
296
261
  mk(path.join(setupTemplates, 'settings'));
297
262
  // --- .gitignore hygiene ---
@@ -327,19 +292,18 @@ export function scaffoldInstallation(input) {
327
292
  else {
328
293
  warn(`templates/ not found at ${templatesSrc} — skipping template copy`);
329
294
  }
330
- // --- Write bundled commands (enrich.md + doctor.md) ---
295
+ // --- Write bundled commands (doctor.md) ---
331
296
  copyBundledCommands({ ...input, copiedIncrement: (n) => (copiedFiles += n) });
332
297
  pruneLegacyArtifacts(input);
333
298
  if (input.provider === 'kimi') {
334
299
  copiedFiles += placeKimiSkillRunner(input);
335
300
  }
336
- // --- Quick tier: direct-placement short-circuit ---
337
- if (input.tier === 'quick') {
338
- const placed = placeQuickTierArtefacts({ ...input });
301
+ // --- Direct placement (the only path) ---
302
+ {
303
+ const placed = placeArtefacts({ ...input });
339
304
  copiedFiles += placed.agents + placed.commands + placed.rules;
340
- const skippedNote = placed.skippedAgents > 0 ? ` (skipped ${placed.skippedAgents} VPC-dependent)` : '';
341
- info(`Quick tier: placed ${placed.agents} agent(s) + ${placed.commands} command(s) + ` +
342
- `${placed.rules} rule file(s) directly into ${input.providerDir}/${skippedNote}`);
305
+ info(`Placed ${placed.agents} agent(s) + ${placed.commands} command(s) + ` +
306
+ `${placed.rules} rule file(s) directly into ${input.providerDir}/`);
343
307
  }
344
308
  // --- Skills placement (both tiers, both providers) ---
345
309
  // Claude: top-level `sr-*` skills are generated from their canonical
@@ -349,10 +313,9 @@ export function scaffoldInstallation(input) {
349
313
  {
350
314
  const skills = placeSkills(input);
351
315
  copiedFiles += skills.filesCopied;
352
- const skillSkipNote = skills.skipped > 0 ? ` (skipped ${skills.skipped} VPC-dependent)` : '';
353
316
  const skillsLabel = input.provider === 'gemini' ? 'agent' : 'skill';
354
317
  const skillsSubdir = input.provider === 'gemini' ? 'agents' : 'skills';
355
- info(`Placed ${skills.placed} ${skillsLabel}(s) into ${input.providerDir}/${skillsSubdir}/${skillSkipNote}`);
318
+ info(`Placed ${skills.placed} ${skillsLabel}(s) into ${input.providerDir}/${skillsSubdir}/`);
356
319
  }
357
320
  // --- Codex provider settings + AGENTS.md initial content ---
358
321
  if (input.provider === 'codex') {
@@ -376,20 +339,6 @@ export function scaffoldInstallation(input) {
376
339
  info(`Kimi provider: wrote ${written} setting file(s) (.kimi-code/AGENTS.md, mcp.json)`);
377
340
  }
378
341
  }
379
- // --- Full-tier hint: enrich is required to generate VPC artefacts ---
380
- if (input.tier === 'full') {
381
- const cliName = input.provider === 'codex'
382
- ? 'Codex CLI'
383
- : input.provider === 'gemini'
384
- ? 'Gemini CLI'
385
- : input.provider === 'kimi'
386
- ? 'Kimi CLI'
387
- : 'Claude Code';
388
- const enrichCommand = input.provider === 'kimi' ? '/skill:specrails-enrich' : '/specrails:enrich';
389
- info(`Full tier staged. Run \`${enrichCommand}\` in ${cliName} to generate ` +
390
- 'VPC personas and adapt agents (including sr-product-manager and ' +
391
- 'sr-product-analyst) to this codebase.');
392
- }
393
342
  ok(`Created ${createdDirs.length} directories, copied ${copiedFiles} files`);
394
343
  return {
395
344
  existingSetup: detectExistingSetup({
@@ -553,7 +502,6 @@ export function installFramework(input) {
553
502
  codeRoot: versionDir,
554
503
  provider: input.provider,
555
504
  providerDir: input.providerDir,
556
- tier: 'quick',
557
505
  selectedAgents: undefined,
558
506
  materializeAllAgents: true,
559
507
  seedProjectDirs: false,
@@ -697,7 +645,7 @@ function seedProjectLayer(input, currentProviderDir) {
697
645
  if (!name.endsWith('.md'))
698
646
  continue;
699
647
  const id = name.slice(0, -3);
700
- if (selected.has(id) && !QUICK_EXCLUDED_AGENTS.has(id))
648
+ if (selected.has(id))
701
649
  placedAgentIds.push(id);
702
650
  }
703
651
  }
@@ -743,7 +691,6 @@ function seedProjectLayer(input, currentProviderDir) {
743
691
  const id = path.basename(roleDir);
744
692
  if (/^sr-[a-z0-9-]+$/.test(id) &&
745
693
  selected.has(id) &&
746
- !QUICK_EXCLUDED_AGENTS.has(id) &&
747
694
  pathExists(path.join(roleDir, 'SKILL.md'))) {
748
695
  placedAgentIds.push(id);
749
696
  }
@@ -799,10 +746,10 @@ function seedKimiMcpFile(mcpPath) {
799
746
  * every SELECTED framework-owned agent at the shared read-only copy.
800
747
  *
801
748
  * `selectedIds` is the per-project agent allow-list (already unioned with the
802
- * CORE trio by the caller). Only framework agents whose id is in it AND not in
803
- * `QUICK_EXCLUDED_AGENTS` are linked — the shared framework store is the full
804
- * superset, so this is where per-project filtering lands. `undefined` ⇒ link
805
- * every framework agent (used by the legacy callers / parity tests).
749
+ * CORE trio by the caller). Only framework agents whose id is in it are linked
750
+ * the shared framework store is the full superset, so this is where per-project
751
+ * filtering lands. `undefined` ⇒ link every framework agent (used by the legacy
752
+ * callers / parity tests).
806
753
  *
807
754
  * When `preferCopy` is true each agent is COPIED as a real file rather than
808
755
  * symlinked (the in-repo standalone install — so a standalone user's CLI finds
@@ -826,7 +773,7 @@ function linkAgentFiles(frameworkAgentsDir, workspaceAgentsDir, selectedIds, pre
826
773
  continue;
827
774
  frameworkProvided.add(name);
828
775
  const id = name.slice(0, -3);
829
- if (selectedIds && (!selectedIds.has(id) || QUICK_EXCLUDED_AGENTS.has(id)))
776
+ if (selectedIds && !selectedIds.has(id))
830
777
  continue;
831
778
  linkedNames.add(name);
832
779
  const m = symlinkOrCopy(src, path.join(workspaceAgentsDir, name), preferCopy);
@@ -886,8 +833,7 @@ function linkKimiSkillDirectories(frameworkSkillsDir, workspaceSkillsDir, select
886
833
  // it, but never expose nested roles if a caller supplies one directly.
887
834
  continue;
888
835
  }
889
- if (/^sr-[a-z0-9-]+$/.test(name) &&
890
- (!selectedRoleIds.has(name) || QUICK_EXCLUDED_AGENTS.has(name))) {
836
+ if (/^sr-[a-z0-9-]+$/.test(name) && !selectedRoleIds.has(name)) {
891
837
  continue;
892
838
  }
893
839
  linkedFrameworkNames.add(name);
@@ -1008,9 +954,8 @@ function copyBundledCommands(input) {
1008
954
  const destDir = path.join(input.artifactRoot, input.providerDir, 'skills', skillName);
1009
955
  // A codex-native override (written for spawn_agent semantics + the
1010
956
  // correct `.codex/skills/rails/` layout) wins over the claude port.
1011
- // This is the ONLY codex command-placement pass in full tier, so
1012
- // without the override check full-tier codex users get the claude
1013
- // body — e.g. enrich's obsolete `.codex/agents/*.toml` model.
957
+ // This is the ONLY codex command-placement pass, so without the override
958
+ // check codex users get the claude body with no codex-native semantics.
1014
959
  const overrideSkill = path.join(codexOverrides, skillName, 'SKILL.md');
1015
960
  if (pathExists(overrideSkill)) {
1016
961
  copyDir(path.join(codexOverrides, skillName), destDir);
@@ -1385,7 +1330,7 @@ function adaptKimiWorkflowBody(commandName, body) {
1385
1330
  }
1386
1331
  if (commandName !== 'implement')
1387
1332
  return body;
1388
- let adapted = replaceMarkdownSection(body, '##### Apply per-agent model overrides (profile mode only)', '##### Legacy mode — preserve current behavior', [
1333
+ let adapted = replaceMarkdownSection(body, '##### Apply per-agent model overrides (only when a profile declares them)', '##### Agent roles', [
1389
1334
  '##### Resolve per-role model overrides (profile mode only)',
1390
1335
  '',
1391
1336
  'Keep each `AGENT_MODEL[id]` value exactly as declared in the profile.',
@@ -1399,24 +1344,6 @@ function adaptKimiWorkflowBody(commandName, body) {
1399
1344
  '`kimi-code/` prefix at the CLI boundary. Never map Claude aliases.',
1400
1345
  '',
1401
1346
  ].join('\n'));
1402
- adapted = replaceMarkdownSection(adapted, '##### Legacy mode — preserve current behavior', '##### Agent roles (both modes)', [
1403
- '##### Legacy mode — preserve current behavior',
1404
- '',
1405
- 'If no profile is active, discover role directories without mutating them:',
1406
- '',
1407
- '```bash',
1408
- 'AVAILABLE_AGENTS="$(find -L .kimi-code/skills -mindepth 2 -maxdepth 2 \\',
1409
- ' -type f -name SKILL.md -print 2>/dev/null | sed \'s|.*/skills/||;s|/SKILL.md$||\' \\',
1410
- ' | grep -E \'^(sr|custom)-\' | sort)"',
1411
- 'PROFILE_MODE="legacy"',
1412
- 'PROFILE_NAME=""',
1413
- '```',
1414
- '',
1415
- 'Per-role model overrides are empty in legacy mode. External role',
1416
- 'processes use the explicit Kimi default (`k3`, launched as',
1417
- '`kimi-code/k3`).',
1418
- '',
1419
- ].join('\n'));
1420
1347
  adapted = replaceMarkdownSection(adapted, '#### Merge Algorithm', '**Step 4: Record outcomes**', [
1421
1348
  '#### Kimi role-wave merge algorithm',
1422
1349
  '',
@@ -1910,7 +1837,6 @@ function placeGeminiAgents(input) {
1910
1837
  const placeholders = {
1911
1838
  PROJECT_NAME: path.basename(input.codeRoot),
1912
1839
  SECURITY_EXEMPTIONS_PATH: '.gemini/security-exemptions.yaml',
1913
- PERSONA_DIR: '.gemini/agents/personas/',
1914
1840
  };
1915
1841
  const placedIds = [];
1916
1842
  for (const src of listDir(agentsSrc)) {
@@ -1922,10 +1848,6 @@ function placeGeminiAgents(input) {
1922
1848
  // filtering happens at the workspace LINK step (linkAgentFiles).
1923
1849
  if (!input.materializeAllAgents && !selectedAgents.has(agentId))
1924
1850
  continue;
1925
- if (!input.materializeAllAgents && QUICK_EXCLUDED_AGENTS.has(agentId)) {
1926
- result.skipped++;
1927
- continue;
1928
- }
1929
1851
  writeGeminiAgentFromTemplate({
1930
1852
  artifactRoot: input.artifactRoot,
1931
1853
  src,
@@ -2202,20 +2124,19 @@ function pruneLegacyArtifacts(input) {
2202
2124
  }
2203
2125
  }
2204
2126
  /**
2205
- * Quick-tier placement: copy agents / commands / rules from the
2127
+ * Direct placement: copy agents / commands / rules from the
2206
2128
  * .specrails/setup-templates/ staging directory into the live
2207
- * provider directory, substituting template placeholders and
2208
- * excluding agents + commands whose dependencies are not present.
2129
+ * provider directory, substituting template placeholders. This is the
2130
+ * only placement path there are no install tiers.
2209
2131
  *
2210
2132
  * Source is setup-templates/ (not scriptDir/templates/) so the pipeline
2211
2133
  * is: scriptDir/templates/ → setup-templates/ (earlier scaffold step)
2212
- * → <providerDir>/ (this function). The intermediate hop mirrors the
2213
- * retired bash installer and lets downstream consumers (specrails-desktop's
2214
- * deployTemplates, /specrails:enrich, update flow) read from a single
2215
- * canonical staging dir.
2134
+ * → <providerDir>/ (this function). The intermediate hop lets downstream
2135
+ * consumers (specrails-desktop's deployTemplates, update flow) read from a
2136
+ * single canonical staging dir.
2216
2137
  */
2217
- function placeQuickTierArtefacts(input) {
2218
- // Codex projects: the quick-tier `agents/` + `rules/` placement is
2138
+ function placeArtefacts(input) {
2139
+ // Codex projects: the `agents/` + `rules/` placement is
2219
2140
  // skipped (handled by `placeSkills` rail-skills + `applyCodexSettings`).
2220
2141
  // The slash-command catalogue under `setup-templates/commands/specrails/`
2221
2142
  // IS ported, but to `.codex/skills/<name>/SKILL.md` instead of
@@ -2322,18 +2243,16 @@ function placeQuickTierArtefacts(input) {
2322
2243
  const placeholders = {
2323
2244
  PROJECT_NAME: projectName,
2324
2245
  SECURITY_EXEMPTIONS_PATH: `${input.providerDir}/security-exemptions.yaml`,
2325
- PERSONA_DIR: `${input.providerDir}/agents/personas/`,
2326
2246
  };
2327
2247
  // --- Agents ---
2328
2248
  const agentsSrc = path.join(setupTemplates, 'agents');
2329
2249
  const agentsDest = path.join(providerDirAbs, 'agents');
2330
2250
  let agentsPlaced = 0;
2331
- let agentsSkipped = 0;
2332
- const installedAgentNames = new Set();
2333
- // When no agent selection is provided (fresh init with no install-config),
2334
- // default to placing only the three core agents. This keeps the default
2335
- // install lean optional agents (sr-merge-resolver, layer specialists,
2336
- // product agents) are explicitly opt-in via the TUI or install-config.
2251
+ const agentsSkipped = 0;
2252
+ // The only shipped agents are the three core agents. A profile-driven
2253
+ // install may pass a selection; anything outside CORE_AGENTS has no template
2254
+ // to place, so the intersection is always the core trio (extension happens
2255
+ // via user-owned custom-*.md agents, never through the installer).
2337
2256
  const selectedAgents = input.selectedAgents
2338
2257
  ? new Set([...input.selectedAgents, ...CORE_AGENTS])
2339
2258
  : new Set([...CORE_AGENTS]);
@@ -2349,10 +2268,6 @@ function placeQuickTierArtefacts(input) {
2349
2268
  // filtering happens at the workspace LINK step, not here.
2350
2269
  if (!input.materializeAllAgents && selectedAgents && !selectedAgents.has(agentId))
2351
2270
  continue;
2352
- if (!input.materializeAllAgents && QUICK_EXCLUDED_AGENTS.has(agentId)) {
2353
- agentsSkipped++;
2354
- continue;
2355
- }
2356
2271
  const dest = path.join(agentsDest, name);
2357
2272
  const rendered = renderPlaceholders(readTextFile(src), {
2358
2273
  ...placeholders,
@@ -2360,7 +2275,6 @@ function placeQuickTierArtefacts(input) {
2360
2275
  });
2361
2276
  writeFileLf(dest, rendered);
2362
2277
  agentsPlaced++;
2363
- installedAgentNames.add(agentId);
2364
2278
  // Per-agent memory directory. Created even when empty so the first run of
2365
2279
  // the agent doesn't error on ENOENT. Skipped when materializing the SHARED
2366
2280
  // framework (`seedProjectDirs === false`): agent-memory is per-workspace
@@ -2375,13 +2289,6 @@ function placeQuickTierArtefacts(input) {
2375
2289
  }
2376
2290
  }
2377
2291
  // --- Commands ---
2378
- // Skip commands whose required agents were excluded.
2379
- const excludedCommands = new Set();
2380
- for (const dep of COMMAND_AGENT_DEPENDENCIES) {
2381
- const hasAllRequired = dep.requires.every((a) => installedAgentNames.has(a));
2382
- if (!hasAllRequired)
2383
- excludedCommands.add(dep.command);
2384
- }
2385
2292
  const commandsSrc = path.join(setupTemplates, 'commands', 'specrails');
2386
2293
  const commandsDest = path.join(providerDirAbs, 'commands', 'specrails');
2387
2294
  let commandsPlaced = 0;
@@ -2391,9 +2298,6 @@ function placeQuickTierArtefacts(input) {
2391
2298
  const name = path.basename(src);
2392
2299
  if (!name.endsWith('.md'))
2393
2300
  continue;
2394
- const cmdId = name.slice(0, -3);
2395
- if (excludedCommands.has(cmdId))
2396
- continue;
2397
2301
  const dest = path.join(commandsDest, name);
2398
2302
  const rendered = renderPlaceholders(readTextFile(src), {
2399
2303
  ...placeholders,
@@ -2445,7 +2349,7 @@ function applyCodexSettings(input) {
2445
2349
  written++;
2446
2350
  }
2447
2351
  // AGENTS.md — top-level instructions file the codex CLI loads on startup.
2448
- // Written with a sentinel block so update + enrich passes can refresh the
2352
+ // Written with a sentinel block so update passes can refresh the
2449
2353
  // managed content while preserving anything the user added outside it.
2450
2354
  const agentsMdPath = path.join(input.artifactRoot, 'AGENTS.md');
2451
2355
  const agentsMdContent = renderInitialAgentsMd(input.codeRoot);
@@ -2513,7 +2417,7 @@ function upsertAgentsMdManagedBlock(existing, managedBlock) {
2513
2417
  // CLAUDE: the top-level `sr-*` skills (sr-implement, sr-why, …) are GENERATED
2514
2418
  // from their canonical slash-command body (`templates/commands/specrails/
2515
2419
  // <command>.md`) — the command is the single source of truth, so the skill can
2516
- // never drift from it. Quick tier excludes VPC-dependent ones.
2420
+ // never drift from it.
2517
2421
  //
2518
2422
  // CODEX: top-level skills are NOT placed — every one has a command counterpart
2519
2423
  // that the command path ports to `.codex/skills/<name>/` (with codex-native
@@ -2529,10 +2433,6 @@ function placeSkills(input) {
2529
2433
  const commandsSrc = path.join(input.artifactRoot, '.specrails', 'setup-templates', 'commands', 'specrails');
2530
2434
  const skillEntries = Object.entries(SKILL_FROM_COMMAND);
2531
2435
  for (const [skillName, spec] of skillEntries) {
2532
- if (input.tier === 'quick' && QUICK_EXCLUDED_SKILLS.has(skillName)) {
2533
- result.skipped++;
2534
- continue;
2535
- }
2536
2436
  const src = path.join(commandsSrc, `${spec.command}.md`);
2537
2437
  if (!pathExists(src))
2538
2438
  continue;
@@ -2555,8 +2455,7 @@ function placeSkills(input) {
2555
2455
  // copies were vestigial — unused on Claude, always overridden on codex,
2556
2456
  // and shipped with unsubstituted placeholders — and were removed).
2557
2457
  //
2558
- // Only the three CORE_AGENTS are placed by default; sr-merge-resolver and
2559
- // every layer specialist are placed only when selectedAgents includes them.
2458
+ // Only the three CORE_AGENTS ship, so only their rail skills exist to place.
2560
2459
  const codexRailsOverridesDir = input.provider === 'codex'
2561
2460
  ? path.join(input.scriptDir, 'templates', 'codex-skills', 'rails')
2562
2461
  : null;
@@ -2612,10 +2511,6 @@ function placeSkills(input) {
2612
2511
  const roleId = name.slice(0, -3);
2613
2512
  if (!input.materializeAllAgents && !selectedAgents.has(roleId))
2614
2513
  continue;
2615
- if (!input.materializeAllAgents && QUICK_EXCLUDED_AGENTS.has(roleId)) {
2616
- result.skipped++;
2617
- continue;
2618
- }
2619
2514
  writeKimiRoleSkill({
2620
2515
  src,
2621
2516
  dest: path.join(destBase, roleId, 'SKILL.md'),
@@ -2630,14 +2525,9 @@ function placeSkills(input) {
2630
2525
  }
2631
2526
  }
2632
2527
  }
2528
+ // v5 ships only the core trio; every bundled command's role dependencies
2529
+ // are always satisfied, so no command exclusion set is needed.
2633
2530
  const excludedCommands = new Set();
2634
- if (!input.materializeAllAgents) {
2635
- for (const dep of COMMAND_AGENT_DEPENDENCIES) {
2636
- if (!dep.requires.every((role) => placedRoleIds.has(role))) {
2637
- excludedCommands.add(dep.command);
2638
- }
2639
- }
2640
- }
2641
2531
  if (isDir(commandsSrc)) {
2642
2532
  for (const src of listDir(commandsSrc)) {
2643
2533
  const name = path.basename(src);