specrails-core 5.5.1 → 6.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 (276) hide show
  1. package/README.md +27 -145
  2. package/bin/specrails-core.mjs +12 -554
  3. package/dist/agent-runtime/capabilities.js +0 -1
  4. package/dist/agent-runtime/cli-executor.d.ts +1 -1
  5. package/dist/agent-runtime/cli-executor.js +4 -3
  6. package/dist/agent-runtime/cli-process.js +0 -1
  7. package/dist/agent-runtime/cli.d.ts +8 -0
  8. package/dist/agent-runtime/cli.js +31 -5
  9. package/dist/agent-runtime/codex-schema.js +0 -1
  10. package/dist/agent-runtime/compact/architect.d.ts +3 -272
  11. package/dist/agent-runtime/compact/architect.js +8 -9
  12. package/dist/agent-runtime/compact/chat-client.d.ts +3 -3
  13. package/dist/agent-runtime/compact/chat-client.js +1 -2
  14. package/dist/agent-runtime/compact/developer.d.ts +3 -70
  15. package/dist/agent-runtime/compact/developer.js +13 -14
  16. package/dist/agent-runtime/compact/environment.d.ts +4 -5
  17. package/dist/agent-runtime/compact/environment.js +1 -2
  18. package/dist/agent-runtime/compact/exit-code-honesty.d.ts +2 -1
  19. package/dist/agent-runtime/compact/exit-code-honesty.js +0 -1
  20. package/dist/agent-runtime/compact/guarded-loop.d.ts +2 -18
  21. package/dist/agent-runtime/compact/guarded-loop.js +7 -8
  22. package/dist/agent-runtime/compact/prompt-inputs.d.ts +0 -2
  23. package/dist/agent-runtime/compact/prompt-inputs.js +1 -2
  24. package/dist/agent-runtime/compact/reviewer.d.ts +0 -13
  25. package/dist/agent-runtime/compact/reviewer.js +5 -6
  26. package/dist/agent-runtime/compact/step.d.ts +0 -1
  27. package/dist/agent-runtime/compact/step.js +1 -2
  28. package/dist/agent-runtime/compact/test-reachability.js +0 -1
  29. package/dist/agent-runtime/config.js +0 -1
  30. package/dist/agent-runtime/core-host.d.ts +1 -1
  31. package/dist/agent-runtime/core-host.js +5 -3
  32. package/dist/agent-runtime/durable-store.d.ts +0 -1
  33. package/dist/agent-runtime/durable-store.js +1 -2
  34. package/dist/agent-runtime/efficiency-summary.d.ts +2 -2
  35. package/dist/agent-runtime/efficiency-summary.js +1 -2
  36. package/dist/agent-runtime/efficiency-types.js +0 -1
  37. package/dist/agent-runtime/efficiency.js +0 -1
  38. package/dist/agent-runtime/evaluation-corpus.js +0 -1
  39. package/dist/agent-runtime/evaluation.d.ts +2 -1
  40. package/dist/agent-runtime/evaluation.js +1 -2
  41. package/dist/agent-runtime/executor-types.d.ts +1 -1
  42. package/dist/agent-runtime/executor-types.js +0 -1
  43. package/dist/agent-runtime/executors.js +0 -1
  44. package/dist/agent-runtime/gemini-policy.js +0 -1
  45. package/dist/agent-runtime/graph/artifacts.d.ts +1 -1
  46. package/dist/agent-runtime/graph/artifacts.js +11 -5
  47. package/dist/agent-runtime/graph/nodes.d.ts +1 -1
  48. package/dist/agent-runtime/graph/nodes.js +1 -2
  49. package/dist/agent-runtime/graph/review-policy.js +0 -1
  50. package/dist/agent-runtime/graph/roles.d.ts +2 -5
  51. package/dist/agent-runtime/graph/roles.js +2 -8
  52. package/dist/agent-runtime/graph/state.d.ts +1 -1
  53. package/dist/agent-runtime/graph/state.js +0 -1
  54. package/dist/agent-runtime/graph-checkpointer.d.ts +2 -1
  55. package/dist/agent-runtime/graph-checkpointer.js +0 -1
  56. package/dist/agent-runtime/guardrails.d.ts +3 -3
  57. package/dist/agent-runtime/guardrails.js +1 -2
  58. package/dist/agent-runtime/index.d.ts +2 -1
  59. package/dist/agent-runtime/index.js +2 -2
  60. package/dist/agent-runtime/kimi-acp.js +1 -2
  61. package/dist/agent-runtime/kimi-model.d.ts +6 -0
  62. package/dist/agent-runtime/kimi-model.js +12 -0
  63. package/dist/agent-runtime/openai-executor.d.ts +0 -9
  64. package/dist/agent-runtime/openai-executor.js +6 -7
  65. package/dist/agent-runtime/openspec-tool-server.js +1 -2
  66. package/dist/agent-runtime/openspec.d.ts +0 -2
  67. package/dist/agent-runtime/openspec.js +3 -7
  68. package/dist/agent-runtime/prompts.d.ts +4 -3
  69. package/dist/agent-runtime/prompts.js +0 -1
  70. package/dist/agent-runtime/provider-diagnostic.js +1 -2
  71. package/dist/agent-runtime/recovery.d.ts +46 -0
  72. package/dist/agent-runtime/recovery.js +169 -0
  73. package/dist/agent-runtime/repository-context.d.ts +1 -1
  74. package/dist/agent-runtime/repository-context.js +0 -1
  75. package/dist/agent-runtime/review-context.d.ts +1 -1
  76. package/dist/agent-runtime/review-context.js +0 -1
  77. package/dist/agent-runtime/role-routing.js +0 -1
  78. package/dist/agent-runtime/role-state.js +0 -1
  79. package/dist/agent-runtime/runtime-identity.js +1 -2
  80. package/dist/agent-runtime/tool-event.js +0 -1
  81. package/dist/agent-runtime/verification-plan.d.ts +5 -4
  82. package/dist/agent-runtime/verification-plan.js +1 -2
  83. package/dist/agent-runtime/workflow-types.js +0 -1
  84. package/dist/agent-runtime/workflow.js +0 -1
  85. package/dist/agent-runtime/workspace-tools.d.ts +2 -2
  86. package/dist/agent-runtime/workspace-tools.js +1 -2
  87. package/dist/installer/cli.d.ts +3 -32
  88. package/dist/installer/cli.js +26 -101
  89. package/dist/installer/commands/framework.d.ts +4 -3
  90. package/dist/installer/commands/framework.js +0 -1
  91. package/dist/installer/commands/init.d.ts +4 -25
  92. package/dist/installer/commands/init.js +5 -8
  93. package/dist/installer/phases/framework-lifecycle.d.ts +3 -17
  94. package/dist/installer/phases/framework-lifecycle.js +2 -3
  95. package/dist/installer/phases/install-config.d.ts +7 -8
  96. package/dist/installer/phases/install-config.js +2 -7
  97. package/dist/installer/phases/manifest.d.ts +6 -7
  98. package/dist/installer/phases/manifest.js +2 -7
  99. package/dist/installer/phases/prereqs.d.ts +6 -7
  100. package/dist/installer/phases/prereqs.js +4 -6
  101. package/dist/installer/phases/provider-detect.d.ts +6 -7
  102. package/dist/installer/phases/provider-detect.js +2 -4
  103. package/dist/installer/phases/scaffold.d.ts +9 -10
  104. package/dist/installer/phases/scaffold.js +82 -805
  105. package/dist/installer/util/errors.js +0 -1
  106. package/dist/installer/util/exec.d.ts +3 -2
  107. package/dist/installer/util/exec.js +0 -1
  108. package/dist/installer/util/fs.d.ts +0 -10
  109. package/dist/installer/util/fs.js +1 -2
  110. package/dist/installer/util/git.js +0 -1
  111. package/dist/installer/util/install-transaction.d.ts +2 -2
  112. package/dist/installer/util/install-transaction.js +1 -2
  113. package/dist/installer/util/logger.d.ts +1 -3
  114. package/dist/installer/util/logger.js +0 -1
  115. package/dist/installer/util/paths.js +0 -1
  116. package/dist/installer/util/registry.d.ts +4 -8
  117. package/dist/installer/util/registry.js +2 -3
  118. package/dist/{installer/runtime → pipeline}/pipeline-state.js +0 -3
  119. package/dist/shared/args.d.ts +18 -0
  120. package/dist/shared/args.js +53 -0
  121. package/integration-contract.json +10 -46
  122. package/package.json +3 -10
  123. package/templates/agents/sr-architect.md +15 -310
  124. package/templates/agents/sr-developer.md +15 -269
  125. package/templates/agents/sr-reviewer.md +13 -367
  126. package/templates/codex-skills/rails/sr-architect/SKILL.md +14 -308
  127. package/templates/codex-skills/rails/sr-developer/SKILL.md +14 -201
  128. package/templates/codex-skills/rails/sr-reviewer/SKILL.md +15 -289
  129. package/templates/kimi/specrails/run-skill.mjs +91 -2173
  130. package/bin/tui-installer.mjs +0 -430
  131. package/commands/doctor.md +0 -62
  132. package/dist/agent-runtime/capabilities.js.map +0 -1
  133. package/dist/agent-runtime/cli-executor.js.map +0 -1
  134. package/dist/agent-runtime/cli-process.js.map +0 -1
  135. package/dist/agent-runtime/cli.js.map +0 -1
  136. package/dist/agent-runtime/codex-schema.js.map +0 -1
  137. package/dist/agent-runtime/compact/architect.js.map +0 -1
  138. package/dist/agent-runtime/compact/chat-client.js.map +0 -1
  139. package/dist/agent-runtime/compact/developer.js.map +0 -1
  140. package/dist/agent-runtime/compact/environment.js.map +0 -1
  141. package/dist/agent-runtime/compact/exit-code-honesty.js.map +0 -1
  142. package/dist/agent-runtime/compact/guarded-loop.js.map +0 -1
  143. package/dist/agent-runtime/compact/prompt-inputs.js.map +0 -1
  144. package/dist/agent-runtime/compact/reviewer.js.map +0 -1
  145. package/dist/agent-runtime/compact/step.js.map +0 -1
  146. package/dist/agent-runtime/compact/test-reachability.js.map +0 -1
  147. package/dist/agent-runtime/config.js.map +0 -1
  148. package/dist/agent-runtime/core-host.js.map +0 -1
  149. package/dist/agent-runtime/durable-store.js.map +0 -1
  150. package/dist/agent-runtime/efficiency-summary.js.map +0 -1
  151. package/dist/agent-runtime/efficiency-types.js.map +0 -1
  152. package/dist/agent-runtime/efficiency.js.map +0 -1
  153. package/dist/agent-runtime/evaluation-corpus.js.map +0 -1
  154. package/dist/agent-runtime/evaluation.js.map +0 -1
  155. package/dist/agent-runtime/executor-types.js.map +0 -1
  156. package/dist/agent-runtime/executors.js.map +0 -1
  157. package/dist/agent-runtime/gemini-policy.js.map +0 -1
  158. package/dist/agent-runtime/graph/artifacts.js.map +0 -1
  159. package/dist/agent-runtime/graph/nodes.js.map +0 -1
  160. package/dist/agent-runtime/graph/review-policy.js.map +0 -1
  161. package/dist/agent-runtime/graph/roles.js.map +0 -1
  162. package/dist/agent-runtime/graph/state.js.map +0 -1
  163. package/dist/agent-runtime/graph-checkpointer.js.map +0 -1
  164. package/dist/agent-runtime/guardrails.js.map +0 -1
  165. package/dist/agent-runtime/index.js.map +0 -1
  166. package/dist/agent-runtime/kimi-acp.js.map +0 -1
  167. package/dist/agent-runtime/openai-executor.js.map +0 -1
  168. package/dist/agent-runtime/openspec-tool-server.js.map +0 -1
  169. package/dist/agent-runtime/openspec.js.map +0 -1
  170. package/dist/agent-runtime/prompts.js.map +0 -1
  171. package/dist/agent-runtime/provider-diagnostic.js.map +0 -1
  172. package/dist/agent-runtime/repository-context.js.map +0 -1
  173. package/dist/agent-runtime/review-context.js.map +0 -1
  174. package/dist/agent-runtime/role-routing.js.map +0 -1
  175. package/dist/agent-runtime/role-state.js.map +0 -1
  176. package/dist/agent-runtime/runtime-identity.js.map +0 -1
  177. package/dist/agent-runtime/tool-event.js.map +0 -1
  178. package/dist/agent-runtime/verification-plan.js.map +0 -1
  179. package/dist/agent-runtime/workflow-types.js.map +0 -1
  180. package/dist/agent-runtime/workflow.js.map +0 -1
  181. package/dist/agent-runtime/workspace-tools.js.map +0 -1
  182. package/dist/installer/cli.js.map +0 -1
  183. package/dist/installer/commands/doctor.d.ts +0 -27
  184. package/dist/installer/commands/doctor.js +0 -615
  185. package/dist/installer/commands/doctor.js.map +0 -1
  186. package/dist/installer/commands/framework.js.map +0 -1
  187. package/dist/installer/commands/init.js.map +0 -1
  188. package/dist/installer/commands/update.d.ts +0 -56
  189. package/dist/installer/commands/update.js +0 -257
  190. package/dist/installer/commands/update.js.map +0 -1
  191. package/dist/installer/commands/v5-migration.d.ts +0 -32
  192. package/dist/installer/commands/v5-migration.js +0 -133
  193. package/dist/installer/commands/v5-migration.js.map +0 -1
  194. package/dist/installer/phases/framework-lifecycle.js.map +0 -1
  195. package/dist/installer/phases/install-config.js.map +0 -1
  196. package/dist/installer/phases/manifest.js.map +0 -1
  197. package/dist/installer/phases/prereqs.js.map +0 -1
  198. package/dist/installer/phases/provider-detect.js.map +0 -1
  199. package/dist/installer/phases/scaffold.js.map +0 -1
  200. package/dist/installer/runtime/kimi.d.ts +0 -84
  201. package/dist/installer/runtime/kimi.js +0 -255
  202. package/dist/installer/runtime/kimi.js.map +0 -1
  203. package/dist/installer/runtime/pipeline-state.js.map +0 -1
  204. package/dist/installer/util/errors.js.map +0 -1
  205. package/dist/installer/util/exec.js.map +0 -1
  206. package/dist/installer/util/fs.js.map +0 -1
  207. package/dist/installer/util/git.js.map +0 -1
  208. package/dist/installer/util/install-transaction.js.map +0 -1
  209. package/dist/installer/util/logger.js.map +0 -1
  210. package/dist/installer/util/paths.js.map +0 -1
  211. package/dist/installer/util/prompts.d.ts +0 -23
  212. package/dist/installer/util/prompts.js +0 -49
  213. package/dist/installer/util/prompts.js.map +0 -1
  214. package/dist/installer/util/registry.js.map +0 -1
  215. package/dist/installer/util/template.d.ts +0 -23
  216. package/dist/installer/util/template.js +0 -60
  217. package/dist/installer/util/template.js.map +0 -1
  218. package/docs/README.md +0 -40
  219. package/docs/agent-runtime-efficiency.md +0 -65
  220. package/docs/agent-runtime.md +0 -347
  221. package/docs/agents.md +0 -315
  222. package/docs/changelog.md +0 -168
  223. package/docs/ci-cd.md +0 -60
  224. package/docs/concepts.md +0 -183
  225. package/docs/customization.md +0 -363
  226. package/docs/deployment.md +0 -234
  227. package/docs/getting-started.md +0 -122
  228. package/docs/installation.md +0 -395
  229. package/docs/local-tickets.md +0 -191
  230. package/docs/migration-guide.md +0 -140
  231. package/docs/playbook-oss-maintainer.md +0 -112
  232. package/docs/playbook-parallel-dev.md +0 -124
  233. package/docs/playbook-product-discovery.md +0 -115
  234. package/docs/plugin-architecture.md +0 -144
  235. package/docs/research/codex-compatibility-analysis.md +0 -365
  236. package/docs/research/mcp-feasibility-analysis.md +0 -382
  237. package/docs/testing/test-matrix-codex.md +0 -130
  238. package/docs/updating.md +0 -89
  239. package/docs/user-docs/cli-reference.md +0 -428
  240. package/docs/user-docs/codex-vs-claude-code.md +0 -23
  241. package/docs/user-docs/core-updates.md +0 -70
  242. package/docs/user-docs/faq.md +0 -146
  243. package/docs/user-docs/getting-started-codex.md +0 -194
  244. package/docs/user-docs/getting-started-kimi.md +0 -423
  245. package/docs/user-docs/installation.md +0 -237
  246. package/docs/user-docs/provider-pipelines.md +0 -96
  247. package/docs/user-docs/quick-start.md +0 -161
  248. package/docs/windows.md +0 -78
  249. package/docs/workflows.md +0 -463
  250. package/schemas/profile.v1.json +0 -207
  251. package/templates/claude-md/CLAUDE-quickstart.md +0 -54
  252. package/templates/claude-md/root.md +0 -50
  253. package/templates/codex-skills/batch-implement/SKILL.md +0 -38
  254. package/templates/codex-skills/implement/SKILL.md +0 -38
  255. package/templates/codex-skills/retry/SKILL.md +0 -16
  256. package/templates/commands/specrails/compat-check.md +0 -271
  257. package/templates/commands/specrails/doctor.md +0 -62
  258. package/templates/commands/specrails/explore-spec.md +0 -173
  259. package/templates/commands/specrails/health-check.md +0 -527
  260. package/templates/commands/specrails/memory-inspect.md +0 -261
  261. package/templates/commands/specrails/opsx-diff.md +0 -419
  262. package/templates/commands/specrails/propose-spec.md +0 -102
  263. package/templates/commands/specrails/refactor-recommender.md +0 -169
  264. package/templates/commands/specrails/telemetry.md +0 -552
  265. package/templates/commands/specrails/why.md +0 -96
  266. package/templates/gemini-commands/batch-implement.toml +0 -37
  267. package/templates/gemini-commands/implement.toml +0 -37
  268. package/templates/gemini-commands/retry.toml +0 -15
  269. package/templates/profiles/default.json +0 -14
  270. package/templates/profiles/kimi-default.json +0 -15
  271. package/templates/rules/layer.md +0 -8
  272. package/templates/runtime/provider-pipeline.md +0 -113
  273. package/templates/security/security-exemptions.yaml +0 -20
  274. package/templates/settings/confidence-config.json +0 -17
  275. package/templates/settings/settings.json +0 -15
  276. /package/dist/{installer/runtime → pipeline}/pipeline-state.d.ts +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/installer/cli.ts"],"names":[],"mappings":"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"}
@@ -1,27 +0,0 @@
1
- /**
2
- * Every canonical SpecRails command is materialized as a direct-child Kimi
3
- * skill. Discover the list from the packaged source of truth so doctor cannot
4
- * silently fall behind when the command catalog grows.
5
- */
6
- export declare const KIMI_MANAGED_WORKFLOW_SKILLS: string[];
7
- /**
8
- * `npx specrails-core doctor` — health check for a specrails install.
9
- * Ports bin/doctor.sh to Node with identical exit semantics:
10
- * - exit 0 when every check passes
11
- * - exit 1 when any check fails
12
- * Appends a single line to ~/.specrails/doctor.log after every run.
13
- */
14
- export interface DoctorFlags {
15
- 'root-dir'?: string | boolean;
16
- provider?: string | boolean;
17
- }
18
- export interface DoctorResult {
19
- passed: number;
20
- failed: number;
21
- results: Array<{
22
- kind: 'pass' | 'fail';
23
- message: string;
24
- fix?: string;
25
- }>;
26
- }
27
- export declare function runDoctor(flags?: DoctorFlags): Promise<DoctorResult>;
@@ -1,615 +0,0 @@
1
- import { appendFileSync, readFileSync } from 'node:fs';
2
- import { homedir } from 'node:os';
3
- import path from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
- import { info, ok, fail as logFail, rawOut } from '../util/logger.js';
6
- import { commandExists, runCommand } from '../util/exec.js';
7
- import { isDir, isFile, listDir, mkdirp, readTextFile, } from '../util/fs.js';
8
- import { isGitRepo } from '../util/git.js';
9
- import { buildManifest } from '../phases/manifest.js';
10
- import { assertClaudeAuthenticated, assertKimiAuthenticated, isSupportedKimiVersion, kimiVersion, MIN_KIMI_VERSION, } from '../phases/provider-detect.js';
11
- import { derivedPaths } from '../phases/provider-detect.js';
12
- import { ProviderError } from '../util/errors.js';
13
- import { resolveArtifacts } from '../util/registry.js';
14
- import { KIMI_REQUIRED_OPENSPEC_SKILLS } from './init.js';
15
- const CORE_PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..');
16
- /**
17
- * Every canonical SpecRails command is materialized as a direct-child Kimi
18
- * skill. Discover the list from the packaged source of truth so doctor cannot
19
- * silently fall behind when the command catalog grows.
20
- */
21
- export const KIMI_MANAGED_WORKFLOW_SKILLS = listDir(path.join(CORE_PACKAGE_ROOT, 'templates', 'commands', 'specrails'))
22
- .filter((entry) => isFile(entry) &&
23
- path.extname(entry) === '.md' &&
24
- path.basename(entry) !== 'setup.md')
25
- .map((entry) => `specrails-${path.basename(entry, '.md')}`)
26
- .sort();
27
- const SHA256_DIGEST = /^sha256:[0-9a-f]{64}$/;
28
- export async function runDoctor(flags = {}) {
29
- const projectRoot = path.resolve(typeof flags['root-dir'] === 'string' ? flags['root-dir'] : process.cwd());
30
- // Relocate-always: Specrails artifacts (provider dir, agent files, instructions
31
- // file) live under `artifactRoot`. Git stays in the repo (codeRoot). Readers
32
- // pass allocate:false → falls back to the in-repo legacy layout when there is
33
- // no registry entry (so a never-installed / legacy repo still reports cleanly).
34
- const { artifactRoot, codeRoot } = resolveArtifacts(projectRoot, {
35
- allocate: false,
36
- home: process.env.SPECRAILS_REGISTRY_HOME,
37
- });
38
- rawOut('\nspecrails doctor\n\n');
39
- const results = [];
40
- const addPass = (message) => {
41
- results.push({ kind: 'pass', message });
42
- };
43
- const addFail = (message, fix) => {
44
- results.push({ kind: 'fail', message, fix });
45
- };
46
- const provider = resolveDoctorProvider(artifactRoot, flags.provider);
47
- const { providerDir, instructionsFile } = derivedPaths(provider);
48
- // Check 1: selected provider CLI.
49
- const cli = provider === 'claude' ? 'claude' : provider;
50
- const cliLabel = provider === 'claude'
51
- ? 'Claude Code'
52
- : provider === 'kimi'
53
- ? 'Kimi Code'
54
- : provider === 'gemini'
55
- ? 'Gemini'
56
- : 'Codex';
57
- const cliFound = await commandExists(cli);
58
- if (cliFound) {
59
- const path_ = await resolveCommandPath(cli);
60
- addPass(`${cliLabel} CLI: found${path_ ? ` (${path_})` : ''}`);
61
- }
62
- else {
63
- const installFix = provider === 'kimi'
64
- ? 'Install Kimi Code: https://www.kimi.com/code/docs/en/kimi-code-cli/guides/getting-started.html'
65
- : provider === 'claude'
66
- ? 'Install Claude Code: https://claude.ai/download'
67
- : `Install the ${cliLabel} CLI and retry`;
68
- addFail(`${cliLabel} CLI: not found`, installFix);
69
- }
70
- // Check 2: provider version/authentication when a bounded probe exists.
71
- if (cliFound && provider === 'claude') {
72
- try {
73
- await assertClaudeAuthenticated({ skipPrereqs: false });
74
- addPass('Claude: authenticated');
75
- }
76
- catch {
77
- addFail('Claude: not authenticated', 'Option 1: claude config set api_key <your-key> | Option 2: claude auth login');
78
- }
79
- }
80
- else if (cliFound && provider === 'kimi') {
81
- const version = await kimiVersion();
82
- if (isSupportedKimiVersion(version)) {
83
- addPass(`Kimi Code version: ${version}`);
84
- }
85
- else {
86
- addFail(`Kimi Code version: unsupported (${version})`, `Upgrade Kimi Code to ${MIN_KIMI_VERSION} or newer`);
87
- }
88
- try {
89
- const auth = await assertKimiAuthenticated({ skipPrereqs: false });
90
- if (auth === 'authenticated') {
91
- addPass('Kimi: authentication evidence found');
92
- }
93
- else {
94
- // There is no non-billable readiness probe in 0.27. Unknown is healthy:
95
- // doctor must not spend quota merely to prove login.
96
- addPass('Kimi: authentication readiness unknown (non-billing check)');
97
- }
98
- }
99
- catch {
100
- addFail('Kimi: not authenticated', 'Run: kimi login');
101
- }
102
- }
103
- // Check 3: provider-native role artifacts.
104
- const agentsDir = provider === 'kimi'
105
- ? path.join(artifactRoot, providerDir, 'skills')
106
- : provider === 'codex'
107
- ? path.join(artifactRoot, providerDir, 'skills', 'rails')
108
- : path.join(artifactRoot, providerDir, 'agents');
109
- if (isDir(agentsDir)) {
110
- const agentFiles = findInstalledAgentFiles(agentsDir, provider);
111
- if (agentFiles.length >= 1) {
112
- const names = agentFiles
113
- .map((f) => provider === 'kimi' || provider === 'codex'
114
- ? path.basename(path.dirname(f))
115
- : path.basename(f, path.extname(f)))
116
- .join(', ');
117
- const relativeRoleDir = provider === 'kimi'
118
- ? `${providerDir}/skills`
119
- : provider === 'codex'
120
- ? `${providerDir}/skills/rails`
121
- : `${providerDir}/agents`;
122
- const label = provider === 'kimi' ? 'Role skills' : 'Agent files';
123
- addPass(`${label}: ${agentFiles.length} agent(s) found in ${relativeRoleDir} (${names})`);
124
- }
125
- else {
126
- addFail(`${provider === 'kimi' ? 'Role skills' : 'Agent files'}: ` +
127
- `${path.relative(artifactRoot, agentsDir)} exists but no generated role artifacts were found`, 'Run specrails-core init to set up agents');
128
- }
129
- }
130
- else {
131
- addFail(`${provider === 'kimi' ? 'Role skills' : 'Agent files'}: ` +
132
- `${path.relative(artifactRoot, agentsDir)} directory not found`, 'Run specrails-core init to set up agents');
133
- }
134
- // Check 4: provider instructions file present
135
- if (isFile(path.join(artifactRoot, instructionsFile))) {
136
- addPass(`${instructionsFile}: present`);
137
- }
138
- else {
139
- addFail(`${instructionsFile}: missing`, 'Run npx specrails-core update to regenerate.');
140
- }
141
- if (provider === 'kimi') {
142
- checkKimiArtifacts({ artifactRoot, codeRoot, addPass, addFail });
143
- }
144
- // Check 5: Git initialized (in the repo — codeRoot, not the artifact root).
145
- // `git rev-parse` supports normal repositories, linked worktrees (`.git` is a
146
- // file there), subdirectories and repository layouts that do not expose a
147
- // literal `.git/` directory.
148
- if (await isGitRepo(codeRoot)) {
149
- addPass('Git: initialized');
150
- }
151
- else {
152
- addFail('Git: not a git repository', 'Initialize with: git init');
153
- }
154
- // Check 6: npm present
155
- if (await commandExists('npm')) {
156
- try {
157
- const { stdout } = await runCommand('npm', ['--version'], { inherit: false });
158
- addPass(`npm: found (v${stdout.trim()})`);
159
- }
160
- catch {
161
- addPass('npm: found');
162
- }
163
- }
164
- else {
165
- addFail('npm: not found', 'Install npm: https://docs.npmjs.com/downloading-and-installing-node-js-and-npm');
166
- }
167
- // Render results in order.
168
- for (const r of results) {
169
- if (r.kind === 'pass')
170
- ok(r.message);
171
- else
172
- logFail(`${r.message}\n Fix: ${r.fix ?? ''}`);
173
- }
174
- const passed = results.filter((r) => r.kind === 'pass').length;
175
- const failed = results.length - passed;
176
- rawOut('\n');
177
- if (failed === 0) {
178
- info(`All ${passed + failed} checks passed. Run ${provider === 'kimi'
179
- ? '/skill:specrails-implement'
180
- : '/specrails:implement'} to get started.`);
181
- }
182
- else {
183
- rawOut(`${failed} check(s) failed.\n`);
184
- }
185
- rawOut('\n');
186
- appendDoctorLog(passed, failed);
187
- return { passed, failed, results };
188
- }
189
- async function resolveCommandPath(cmd) {
190
- const probe = process.platform === 'win32' ? 'where' : 'which';
191
- try {
192
- const { stdout } = await runCommand(probe, [cmd], { inherit: false });
193
- const first = stdout.trim().split(/\r?\n/)[0];
194
- return first && first.length > 0 ? first : null;
195
- }
196
- catch {
197
- return null;
198
- }
199
- }
200
- function resolveDoctorProvider(projectRoot, explicit) {
201
- if (explicit === 'claude' ||
202
- explicit === 'codex' ||
203
- explicit === 'gemini' ||
204
- explicit === 'kimi') {
205
- return explicit;
206
- }
207
- if (explicit !== undefined) {
208
- throw new ProviderError(`--provider value must be 'claude', 'codex', 'gemini', or 'kimi', got: ${String(explicit)}`);
209
- }
210
- const manifestPath = path.join(projectRoot, '.specrails', 'specrails-manifest.json');
211
- if (isFile(manifestPath)) {
212
- try {
213
- const manifest = JSON.parse(readTextFile(manifestPath));
214
- if (isProvider(manifest.primary_provider))
215
- return manifest.primary_provider;
216
- if (Array.isArray(manifest.providers)) {
217
- const recorded = manifest.providers.filter(isProvider);
218
- if (recorded.length === 1)
219
- return recorded[0];
220
- }
221
- }
222
- catch {
223
- // The manifest itself is diagnosed later. Preserve legacy directory
224
- // fallback here so doctor still reports every actionable problem.
225
- }
226
- }
227
- // Preserve the established multi-tree fallback: Gemini and Codex predate
228
- // Claude-first resolution. Kimi slots ahead of Claude without changing
229
- // existing Gemini/Codex behavior.
230
- if (isDir(path.join(projectRoot, '.gemini')))
231
- return 'gemini';
232
- if (isDir(path.join(projectRoot, '.codex')))
233
- return 'codex';
234
- if (isDir(path.join(projectRoot, '.kimi-code')))
235
- return 'kimi';
236
- if (isDir(path.join(projectRoot, '.claude')))
237
- return 'claude';
238
- return 'claude';
239
- }
240
- function isProvider(value) {
241
- return (value === 'claude' ||
242
- value === 'codex' ||
243
- value === 'gemini' ||
244
- value === 'kimi');
245
- }
246
- function findInstalledAgentFiles(root, provider) {
247
- if (!isDir(root))
248
- return [];
249
- if (provider === 'kimi') {
250
- return listDir(root)
251
- .filter((entry) => {
252
- const id = path.basename(entry);
253
- return (isDir(entry) &&
254
- /^(?:sr|custom)-[a-z0-9-]+$/.test(id) &&
255
- isFile(path.join(entry, 'SKILL.md')));
256
- })
257
- .map((entry) => path.join(entry, 'SKILL.md'))
258
- .sort();
259
- }
260
- if (provider === 'codex') {
261
- return listDir(root)
262
- .filter((entry) => isDir(entry) && isFile(path.join(entry, 'SKILL.md')))
263
- .map((entry) => path.join(entry, 'SKILL.md'))
264
- .sort();
265
- }
266
- const matcher = /^(custom-|sr-).+\.md$/;
267
- return listDir(root)
268
- .filter((entry) => isFile(entry) && matcher.test(path.basename(entry)))
269
- .sort();
270
- }
271
- function isRecord(value) {
272
- return typeof value === 'object' && value !== null && !Array.isArray(value);
273
- }
274
- function validateStringRecord(value, field) {
275
- if (!isRecord(value))
276
- return [`${field} must be an object of string values`];
277
- return Object.entries(value)
278
- .filter(([, item]) => typeof item !== 'string')
279
- .map(([key]) => `${field}.${key} must be a string`);
280
- }
281
- function validateStringArray(value, field) {
282
- if (!Array.isArray(value) || value.some((item) => typeof item !== 'string')) {
283
- return [`${field} must be an array of strings`];
284
- }
285
- return [];
286
- }
287
- function validateKimiMcpServer(name, value) {
288
- const field = `mcpServers.${name}`;
289
- if (!isRecord(value))
290
- return [`${field} must be an object`];
291
- const errors = [];
292
- let transport = value.transport;
293
- if (transport === undefined) {
294
- if (typeof value.command === 'string')
295
- transport = 'stdio';
296
- else if (typeof value.url === 'string')
297
- transport = 'http';
298
- }
299
- if (transport !== 'stdio' && transport !== 'http' && transport !== 'sse') {
300
- return [`${field} must declare a command, a URL, or a supported transport`];
301
- }
302
- if (transport === 'stdio') {
303
- if (typeof value.command !== 'string' || value.command.length === 0) {
304
- errors.push(`${field}.command must be a non-empty string`);
305
- }
306
- if (value.args !== undefined) {
307
- errors.push(...validateStringArray(value.args, `${field}.args`));
308
- }
309
- if (value.env !== undefined) {
310
- errors.push(...validateStringRecord(value.env, `${field}.env`));
311
- }
312
- if (value.cwd !== undefined && typeof value.cwd !== 'string') {
313
- errors.push(`${field}.cwd must be a string`);
314
- }
315
- if (value.executor !== undefined &&
316
- value.executor !== 'local' &&
317
- value.executor !== 'kaos') {
318
- errors.push(`${field}.executor must be "local" or "kaos"`);
319
- }
320
- }
321
- else {
322
- if (typeof value.url !== 'string') {
323
- errors.push(`${field}.url must be a valid URL`);
324
- }
325
- else {
326
- try {
327
- new URL(value.url);
328
- }
329
- catch {
330
- errors.push(`${field}.url must be a valid URL`);
331
- }
332
- }
333
- if (value.headers !== undefined) {
334
- errors.push(...validateStringRecord(value.headers, `${field}.headers`));
335
- }
336
- if (value.auth !== undefined && value.auth !== 'oauth') {
337
- errors.push(`${field}.auth must be "oauth"`);
338
- }
339
- if (value.bearerTokenEnvVar !== undefined &&
340
- (typeof value.bearerTokenEnvVar !== 'string' ||
341
- value.bearerTokenEnvVar.length === 0)) {
342
- errors.push(`${field}.bearerTokenEnvVar must be a non-empty string`);
343
- }
344
- }
345
- if (value.enabled !== undefined && typeof value.enabled !== 'boolean') {
346
- errors.push(`${field}.enabled must be a boolean`);
347
- }
348
- for (const timeoutField of ['startupTimeoutMs', 'toolTimeoutMs']) {
349
- const timeout = value[timeoutField];
350
- if (timeout !== undefined &&
351
- (typeof timeout !== 'number' ||
352
- !Number.isInteger(timeout) ||
353
- timeout < 1)) {
354
- errors.push(`${field}.${timeoutField} must be a positive integer`);
355
- }
356
- }
357
- for (const toolsField of ['enabledTools', 'disabledTools']) {
358
- if (value[toolsField] !== undefined) {
359
- errors.push(...validateStringArray(value[toolsField], `${field}.${toolsField}`));
360
- }
361
- }
362
- return errors;
363
- }
364
- function inspectKimiMcpConfig(filePath) {
365
- let parsed;
366
- try {
367
- parsed = JSON.parse(readTextFile(filePath));
368
- }
369
- catch {
370
- return { errors: ['file is not valid JSON'], serverCount: 0 };
371
- }
372
- if (!isRecord(parsed)) {
373
- return { errors: ['root must be a JSON object'], serverCount: 0 };
374
- }
375
- // Kimi defaults a missing mcpServers field to an empty object, so `{}` is a
376
- // valid upstream config. When present, every entry must match Kimi 0.27's
377
- // stdio/HTTP/SSE schema.
378
- const serversValue = parsed.mcpServers ?? {};
379
- if (!isRecord(serversValue)) {
380
- return {
381
- errors: ['mcpServers must be an object keyed by server name'],
382
- serverCount: 0,
383
- };
384
- }
385
- const errors = Object.entries(serversValue).flatMap(([name, value]) => validateKimiMcpServer(name, value));
386
- return { errors, serverCount: Object.keys(serversValue).length };
387
- }
388
- function summarizePaths(paths) {
389
- const shown = paths.slice(0, 3).join(', ');
390
- return paths.length <= 3 ? shown : `${shown} (+${paths.length - 3} more)`;
391
- }
392
- function readCorePackageVersion() {
393
- try {
394
- const parsed = JSON.parse(readTextFile(path.join(CORE_PACKAGE_ROOT, 'package.json')));
395
- return typeof parsed.version === 'string' && parsed.version.trim().length > 0
396
- ? parsed.version.trim()
397
- : null;
398
- }
399
- catch {
400
- return null;
401
- }
402
- }
403
- function inspectKimiManifest(artifactRoot, manifestPath) {
404
- let parsed;
405
- try {
406
- parsed = JSON.parse(readTextFile(manifestPath));
407
- }
408
- catch {
409
- return { errors: ['file is not valid JSON'], version: null, artifactCount: 0 };
410
- }
411
- if (!isRecord(parsed)) {
412
- return {
413
- errors: ['root must be a JSON object'],
414
- version: null,
415
- artifactCount: 0,
416
- };
417
- }
418
- const errors = [];
419
- const version = typeof parsed.version === 'string' && parsed.version.trim().length > 0
420
- ? parsed.version.trim()
421
- : null;
422
- if (!version)
423
- errors.push('version must be a non-empty string');
424
- const currentVersion = readCorePackageVersion();
425
- if (!currentVersion) {
426
- errors.push('running Core package version could not be read');
427
- }
428
- else if (version && version !== currentVersion) {
429
- errors.push(`version ${version} does not match running Core ${currentVersion}`);
430
- }
431
- const markerPath = path.join(artifactRoot, '.specrails', 'specrails-version');
432
- if (!isFile(markerPath)) {
433
- errors.push('specrails-version marker is missing');
434
- }
435
- else if (version && readTextFile(markerPath).trim() !== version) {
436
- errors.push('specrails-version marker does not match manifest version');
437
- }
438
- if (typeof parsed.installed_at !== 'string' ||
439
- !Number.isFinite(Date.parse(parsed.installed_at))) {
440
- errors.push('installed_at must be a valid timestamp');
441
- }
442
- const providers = Array.isArray(parsed.providers)
443
- ? parsed.providers.filter(isProvider)
444
- : [];
445
- if (!Array.isArray(parsed.providers) ||
446
- providers.length !== parsed.providers.length ||
447
- providers.length === 0) {
448
- errors.push('providers must be a non-empty array of supported providers');
449
- }
450
- else {
451
- if (new Set(providers).size !== providers.length) {
452
- errors.push('providers must not contain duplicates');
453
- }
454
- if (!providers.includes('kimi')) {
455
- errors.push('providers does not record kimi');
456
- }
457
- }
458
- if (!isProvider(parsed.primary_provider)) {
459
- errors.push('primary_provider must be a supported provider');
460
- }
461
- else if (!providers.includes(parsed.primary_provider)) {
462
- errors.push('primary_provider must also appear in providers');
463
- }
464
- if (!isRecord(parsed.artifacts) || Object.keys(parsed.artifacts).length === 0) {
465
- errors.push('artifacts must be a non-empty checksum object');
466
- return { errors, version, artifactCount: 0 };
467
- }
468
- const actualArtifacts = parsed.artifacts;
469
- const malformedDigests = Object.entries(actualArtifacts)
470
- .filter(([, digest]) => typeof digest !== 'string' || !SHA256_DIGEST.test(digest))
471
- .map(([artifact]) => artifact);
472
- if (malformedDigests.length > 0) {
473
- errors.push(`artifacts contains invalid sha256 digests: ${summarizePaths(malformedDigests)}`);
474
- }
475
- try {
476
- const expectedArtifacts = buildManifest({
477
- scriptDir: CORE_PACKAGE_ROOT,
478
- repoRoot: artifactRoot,
479
- version: currentVersion ?? version ?? 'unknown',
480
- installedAt: '1970-01-01T00:00:00Z',
481
- }).artifacts;
482
- const actualKeys = Object.keys(actualArtifacts);
483
- const expectedKeys = Object.keys(expectedArtifacts);
484
- const missing = expectedKeys.filter((key) => !(key in actualArtifacts));
485
- const unexpected = actualKeys.filter((key) => !(key in expectedArtifacts));
486
- const changed = expectedKeys.filter((key) => key in actualArtifacts && actualArtifacts[key] !== expectedArtifacts[key]);
487
- if (missing.length > 0) {
488
- errors.push(`artifacts is missing: ${summarizePaths(missing)}`);
489
- }
490
- if (unexpected.length > 0) {
491
- errors.push(`artifacts has unknown entries: ${summarizePaths(unexpected)}`);
492
- }
493
- if (changed.length > 0) {
494
- errors.push(`artifacts checksum mismatch: ${summarizePaths(changed)}`);
495
- }
496
- }
497
- catch {
498
- errors.push('packaged Core artifact checksums could not be computed');
499
- }
500
- return {
501
- errors,
502
- version,
503
- artifactCount: Object.keys(actualArtifacts).length,
504
- };
505
- }
506
- function checkKimiArtifacts(args) {
507
- const skillRoot = path.join(args.artifactRoot, '.kimi-code', 'skills');
508
- const legacyRoleRoot = path.join(skillRoot, 'rails');
509
- const staleNestedRoles = listDir(legacyRoleRoot).filter((entry) => isDir(entry));
510
- if (staleNestedRoles.length > 0) {
511
- args.addFail(`Kimi role skills: stale nested skills/rails layout contains ` +
512
- staleNestedRoles.map((entry) => path.basename(entry)).join(', '), 'Run: npx specrails-core update --provider kimi; resolve any reported custom-role conflict manually');
513
- }
514
- else {
515
- args.addPass('Kimi role layout: all roles are direct children of .kimi-code/skills');
516
- }
517
- const runnerRoot = path.join(args.artifactRoot, '.kimi-code', 'specrails');
518
- const requiredRunnerFiles = [
519
- 'run-skill.mjs',
520
- path.join('vendor', 'js-yaml', 'js-yaml.mjs'),
521
- path.join('vendor', 'js-yaml', 'LICENSE'),
522
- path.join('vendor', 'js-yaml', 'NOTICE.md'),
523
- ];
524
- const missingRunnerFiles = requiredRunnerFiles.filter((relative) => !isFile(path.join(runnerRoot, relative)));
525
- const mismatchedRunnerFiles = missingRunnerFiles.length === 0
526
- ? requiredRunnerFiles.filter((relative) => {
527
- const installed = path.join(runnerRoot, relative);
528
- const packaged = path.join(CORE_PACKAGE_ROOT, 'templates', 'kimi', 'specrails', relative);
529
- try {
530
- return !readFileSync(installed).equals(readFileSync(packaged));
531
- }
532
- catch {
533
- return true;
534
- }
535
- })
536
- : [];
537
- if (missingRunnerFiles.length === 0 &&
538
- mismatchedRunnerFiles.length === 0) {
539
- args.addPass('Kimi headless skill runner: complete managed bundle integrity verified outside the skill scanner');
540
- }
541
- else if (missingRunnerFiles.length > 0) {
542
- args.addFail(`Kimi headless skill runner: missing ${missingRunnerFiles.join(', ')} ` +
543
- 'under .kimi-code/specrails', 'Run: npx specrails-core update --provider kimi');
544
- }
545
- else {
546
- args.addFail(`Kimi headless skill runner: managed content mismatch in ` +
547
- mismatchedRunnerFiles.join(', '), 'Run: npx specrails-core update --provider kimi');
548
- }
549
- const missingSpecrails = KIMI_MANAGED_WORKFLOW_SKILLS.filter((name) => !isFile(path.join(skillRoot, name, 'SKILL.md')));
550
- if (KIMI_MANAGED_WORKFLOW_SKILLS.length === 0) {
551
- args.addFail('Kimi workflow skills: packaged managed catalog is unavailable', 'Reinstall specrails-core, then run: npx specrails-core update --provider kimi');
552
- }
553
- else if (missingSpecrails.length === 0) {
554
- args.addPass(`Kimi workflow skills: all ${KIMI_MANAGED_WORKFLOW_SKILLS.length} managed workflows present`);
555
- }
556
- else {
557
- args.addFail(`Kimi workflow skills: missing ${missingSpecrails.join(', ')}`, 'Run: npx specrails-core update --provider kimi');
558
- }
559
- const missingOpenSpec = KIMI_REQUIRED_OPENSPEC_SKILLS.filter((name) => !isFile(path.join(skillRoot, name, 'SKILL.md')));
560
- if (missingOpenSpec.length === 0) {
561
- args.addPass(`Kimi OpenSpec skills: all ${KIMI_REQUIRED_OPENSPEC_SKILLS.length} present`);
562
- }
563
- else {
564
- args.addFail(`Kimi OpenSpec skills: missing ${missingOpenSpec.join(', ')}`, 'Run: npx specrails-core update --provider kimi');
565
- }
566
- const legacyRoot = path.join(args.codeRoot, '.kimi', 'skills');
567
- const staleLegacy = listDir(legacyRoot).filter((entry) => isDir(entry) && path.basename(entry).startsWith('openspec-'));
568
- if (staleLegacy.length > 0) {
569
- args.addFail(`Kimi OpenSpec skills: stale generated .kimi/skills output found`, 'Run: npx specrails-core update --provider kimi');
570
- }
571
- else {
572
- args.addPass('Kimi OpenSpec layout: no stale .kimi/skills output');
573
- }
574
- const mcpPath = path.join(args.artifactRoot, '.kimi-code', 'mcp.json');
575
- if (isFile(mcpPath)) {
576
- const mcp = inspectKimiMcpConfig(mcpPath);
577
- if (mcp.errors.length === 0) {
578
- args.addPass(`.kimi-code/mcp.json: valid (${mcp.serverCount} server(s))`);
579
- }
580
- else {
581
- args.addFail(`.kimi-code/mcp.json: invalid (${mcp.errors.join('; ')})`, 'Fix the JSON using `kimi` → `/mcp-config`, or restore a valid config and retry');
582
- }
583
- }
584
- else {
585
- args.addFail('.kimi-code/mcp.json: missing', 'Run: npx specrails-core update --provider kimi');
586
- }
587
- const manifestPath = path.join(args.artifactRoot, '.specrails', 'specrails-manifest.json');
588
- if (isFile(manifestPath)) {
589
- const manifest = inspectKimiManifest(args.artifactRoot, manifestPath);
590
- if (manifest.errors.length === 0) {
591
- args.addPass(`SpecRails manifest: valid for Core ${manifest.version} ` +
592
- `(${manifest.artifactCount} packaged source checksums verified; records kimi)`);
593
- }
594
- else {
595
- args.addFail(`SpecRails manifest: invalid (${manifest.errors.join('; ')})`, 'Run: npx specrails-core update --provider kimi');
596
- }
597
- }
598
- else {
599
- args.addFail('SpecRails manifest: missing', 'Run: npx specrails-core update --provider kimi');
600
- }
601
- }
602
- function appendDoctorLog(passed, failed) {
603
- try {
604
- const logDir = path.join(homedir(), '.specrails');
605
- mkdirp(logDir);
606
- const logFile = path.join(logDir, 'doctor.log');
607
- const stamp = new Date().toISOString().replace(/\.\d{3}Z$/, 'Z');
608
- const total = passed + failed;
609
- appendFileSync(logFile, `${stamp} checks=${total} passed=${passed} failed=${failed}\n`);
610
- }
611
- catch {
612
- // Best-effort logging — never fail doctor because we can't write the log.
613
- }
614
- }
615
- //# sourceMappingURL=doctor.js.map