specrails-core 5.2.3 → 5.4.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 (165) hide show
  1. package/README.md +3 -0
  2. package/bin/specrails-core.mjs +5 -0
  3. package/dist/agent-runtime/capabilities.d.ts +27 -0
  4. package/dist/agent-runtime/capabilities.js +73 -0
  5. package/dist/agent-runtime/capabilities.js.map +1 -0
  6. package/dist/agent-runtime/cli-executor.d.ts +43 -0
  7. package/dist/agent-runtime/cli-executor.js +405 -0
  8. package/dist/agent-runtime/cli-executor.js.map +1 -0
  9. package/dist/agent-runtime/cli-process.d.ts +32 -0
  10. package/dist/agent-runtime/cli-process.js +159 -0
  11. package/dist/agent-runtime/cli-process.js.map +1 -0
  12. package/dist/agent-runtime/cli.d.ts +39 -0
  13. package/dist/agent-runtime/cli.js +216 -0
  14. package/dist/agent-runtime/cli.js.map +1 -0
  15. package/dist/agent-runtime/codex-schema.d.ts +4 -0
  16. package/dist/agent-runtime/codex-schema.js +31 -0
  17. package/dist/agent-runtime/codex-schema.js.map +1 -0
  18. package/dist/agent-runtime/config.d.ts +11 -0
  19. package/dist/agent-runtime/config.js +263 -0
  20. package/dist/agent-runtime/config.js.map +1 -0
  21. package/dist/agent-runtime/core-host.d.ts +41 -0
  22. package/dist/agent-runtime/core-host.js +132 -0
  23. package/dist/agent-runtime/core-host.js.map +1 -0
  24. package/dist/agent-runtime/durable-store.d.ts +22 -0
  25. package/dist/agent-runtime/durable-store.js +205 -0
  26. package/dist/agent-runtime/durable-store.js.map +1 -0
  27. package/dist/agent-runtime/efficiency-summary.d.ts +67 -0
  28. package/dist/agent-runtime/efficiency-summary.js +52 -0
  29. package/dist/agent-runtime/efficiency-summary.js.map +1 -0
  30. package/dist/agent-runtime/efficiency-types.d.ts +60 -0
  31. package/dist/agent-runtime/efficiency-types.js +8 -0
  32. package/dist/agent-runtime/efficiency-types.js.map +1 -0
  33. package/dist/agent-runtime/efficiency.d.ts +5 -0
  34. package/dist/agent-runtime/efficiency.js +35 -0
  35. package/dist/agent-runtime/efficiency.js.map +1 -0
  36. package/dist/agent-runtime/evaluation-corpus.d.ts +13 -0
  37. package/dist/agent-runtime/evaluation-corpus.js +8 -0
  38. package/dist/agent-runtime/evaluation-corpus.js.map +1 -0
  39. package/dist/agent-runtime/evaluation.d.ts +43 -0
  40. package/dist/agent-runtime/evaluation.js +171 -0
  41. package/dist/agent-runtime/evaluation.js.map +1 -0
  42. package/dist/agent-runtime/executor-types.d.ts +125 -0
  43. package/dist/agent-runtime/executor-types.js +29 -0
  44. package/dist/agent-runtime/executor-types.js.map +1 -0
  45. package/dist/agent-runtime/executors.d.ts +23 -0
  46. package/dist/agent-runtime/executors.js +48 -0
  47. package/dist/agent-runtime/executors.js.map +1 -0
  48. package/dist/agent-runtime/gemini-policy.d.ts +8 -0
  49. package/dist/agent-runtime/gemini-policy.js +36 -0
  50. package/dist/agent-runtime/gemini-policy.js.map +1 -0
  51. package/dist/agent-runtime/graph/artifacts.d.ts +26 -0
  52. package/dist/agent-runtime/graph/artifacts.js +205 -0
  53. package/dist/agent-runtime/graph/artifacts.js.map +1 -0
  54. package/dist/agent-runtime/graph/nodes.d.ts +39 -0
  55. package/dist/agent-runtime/graph/nodes.js +321 -0
  56. package/dist/agent-runtime/graph/nodes.js.map +1 -0
  57. package/dist/agent-runtime/graph/review-policy.d.ts +18 -0
  58. package/dist/agent-runtime/graph/review-policy.js +32 -0
  59. package/dist/agent-runtime/graph/review-policy.js.map +1 -0
  60. package/dist/agent-runtime/graph/roles.d.ts +47 -0
  61. package/dist/agent-runtime/graph/roles.js +190 -0
  62. package/dist/agent-runtime/graph/roles.js.map +1 -0
  63. package/dist/agent-runtime/graph/state.d.ts +83 -0
  64. package/dist/agent-runtime/graph/state.js +23 -0
  65. package/dist/agent-runtime/graph/state.js.map +1 -0
  66. package/dist/agent-runtime/graph-checkpointer.d.ts +61 -0
  67. package/dist/agent-runtime/graph-checkpointer.js +137 -0
  68. package/dist/agent-runtime/graph-checkpointer.js.map +1 -0
  69. package/dist/agent-runtime/index.d.ts +20 -0
  70. package/dist/agent-runtime/index.js +21 -0
  71. package/dist/agent-runtime/index.js.map +1 -0
  72. package/dist/agent-runtime/kimi-acp.d.ts +11 -0
  73. package/dist/agent-runtime/kimi-acp.js +190 -0
  74. package/dist/agent-runtime/kimi-acp.js.map +1 -0
  75. package/dist/agent-runtime/openai-executor.d.ts +26 -0
  76. package/dist/agent-runtime/openai-executor.js +192 -0
  77. package/dist/agent-runtime/openai-executor.js.map +1 -0
  78. package/dist/agent-runtime/openspec-tool-server.d.ts +1 -0
  79. package/dist/agent-runtime/openspec-tool-server.js +37 -0
  80. package/dist/agent-runtime/openspec-tool-server.js.map +1 -0
  81. package/dist/agent-runtime/openspec.d.ts +123 -0
  82. package/dist/agent-runtime/openspec.js +263 -0
  83. package/dist/agent-runtime/openspec.js.map +1 -0
  84. package/dist/agent-runtime/prompts.d.ts +44 -0
  85. package/dist/agent-runtime/prompts.js +310 -0
  86. package/dist/agent-runtime/prompts.js.map +1 -0
  87. package/dist/agent-runtime/provider-diagnostic.d.ts +2 -0
  88. package/dist/agent-runtime/provider-diagnostic.js +25 -0
  89. package/dist/agent-runtime/provider-diagnostic.js.map +1 -0
  90. package/dist/agent-runtime/repository-context.d.ts +25 -0
  91. package/dist/agent-runtime/repository-context.js +100 -0
  92. package/dist/agent-runtime/repository-context.js.map +1 -0
  93. package/dist/agent-runtime/review-context.d.ts +14 -0
  94. package/dist/agent-runtime/review-context.js +41 -0
  95. package/dist/agent-runtime/review-context.js.map +1 -0
  96. package/dist/agent-runtime/role-routing.d.ts +10 -0
  97. package/dist/agent-runtime/role-routing.js +29 -0
  98. package/dist/agent-runtime/role-routing.js.map +1 -0
  99. package/dist/agent-runtime/role-state.d.ts +19 -0
  100. package/dist/agent-runtime/role-state.js +24 -0
  101. package/dist/agent-runtime/role-state.js.map +1 -0
  102. package/dist/agent-runtime/runtime-identity.d.ts +11 -0
  103. package/dist/agent-runtime/runtime-identity.js +33 -0
  104. package/dist/agent-runtime/runtime-identity.js.map +1 -0
  105. package/dist/agent-runtime/tool-event.d.ts +3 -0
  106. package/dist/agent-runtime/tool-event.js +24 -0
  107. package/dist/agent-runtime/tool-event.js.map +1 -0
  108. package/dist/agent-runtime/verification-plan.d.ts +55 -0
  109. package/dist/agent-runtime/verification-plan.js +206 -0
  110. package/dist/agent-runtime/verification-plan.js.map +1 -0
  111. package/dist/agent-runtime/workflow-types.d.ts +226 -0
  112. package/dist/agent-runtime/workflow-types.js +2 -0
  113. package/dist/agent-runtime/workflow-types.js.map +1 -0
  114. package/dist/agent-runtime/workflow.d.ts +17 -0
  115. package/dist/agent-runtime/workflow.js +636 -0
  116. package/dist/agent-runtime/workflow.js.map +1 -0
  117. package/dist/agent-runtime/workspace-tools.d.ts +29 -0
  118. package/dist/agent-runtime/workspace-tools.js +282 -0
  119. package/dist/agent-runtime/workspace-tools.js.map +1 -0
  120. package/dist/installer/cli.d.ts +35 -0
  121. package/dist/installer/cli.js +3 -0
  122. package/dist/installer/cli.js.map +1 -1
  123. package/dist/installer/commands/doctor.d.ts +27 -0
  124. package/dist/installer/commands/framework.d.ts +85 -0
  125. package/dist/installer/commands/init.d.ts +147 -0
  126. package/dist/installer/commands/update.d.ts +56 -0
  127. package/dist/installer/commands/v5-migration.d.ts +32 -0
  128. package/dist/installer/phases/framework-lifecycle.d.ts +53 -0
  129. package/dist/installer/phases/install-config.d.ts +64 -0
  130. package/dist/installer/phases/manifest.d.ts +45 -0
  131. package/dist/installer/phases/prereqs.d.ts +51 -0
  132. package/dist/installer/phases/provider-detect.d.ts +89 -0
  133. package/dist/installer/phases/scaffold.d.ts +211 -0
  134. package/dist/installer/phases/scaffold.js +39 -109
  135. package/dist/installer/phases/scaffold.js.map +1 -1
  136. package/dist/installer/runtime/kimi.d.ts +84 -0
  137. package/dist/installer/runtime/pipeline-state.d.ts +351 -0
  138. package/dist/installer/runtime/pipeline-state.js +514 -41
  139. package/dist/installer/runtime/pipeline-state.js.map +1 -1
  140. package/dist/installer/util/errors.d.ts +46 -0
  141. package/dist/installer/util/exec.d.ts +41 -0
  142. package/dist/installer/util/fs.d.ts +153 -0
  143. package/dist/installer/util/git.d.ts +44 -0
  144. package/dist/installer/util/install-transaction.d.ts +29 -0
  145. package/dist/installer/util/logger.d.ts +31 -0
  146. package/dist/installer/util/paths.d.ts +34 -0
  147. package/dist/installer/util/prompts.d.ts +23 -0
  148. package/dist/installer/util/registry.d.ts +174 -0
  149. package/dist/installer/util/template.d.ts +23 -0
  150. package/docs/README.md +1 -0
  151. package/docs/agent-runtime-efficiency.md +65 -0
  152. package/docs/agent-runtime.md +339 -0
  153. package/integration-contract.json +80 -7
  154. package/package.json +20 -2
  155. package/schemas/agent-runtime.schema.json +77 -0
  156. package/schemas/fixtures/runtime-efficiency-summary.v1.json +790 -0
  157. package/templates/codex-skills/batch-implement/SKILL.md +33 -58
  158. package/templates/codex-skills/implement/SKILL.md +21 -124
  159. package/templates/codex-skills/retry/SKILL.md +8 -34
  160. package/templates/commands/specrails/batch-implement.md +21 -16
  161. package/templates/commands/specrails/implement.md +17 -276
  162. package/templates/commands/specrails/retry.md +6 -34
  163. package/templates/gemini-commands/batch-implement.toml +34 -28
  164. package/templates/gemini-commands/implement.toml +34 -55
  165. package/templates/gemini-commands/retry.toml +10 -16
@@ -0,0 +1,211 @@
1
+ import type { Provider } from './provider-detect.js';
2
+ /**
3
+ * The three baseline agents — the COMPLETE set of agents the installer
4
+ * ships. The implement pipeline depends on all three. Any additional agent
5
+ * comes from a user-authored profile (`custom-*`), never the installer.
6
+ *
7
+ * Mirrors the `allOf` baseline in schemas/profile.v1.json — update
8
+ * both files together if this set ever changes.
9
+ */
10
+ export declare const CORE_AGENTS: Set<string>;
11
+ /**
12
+ * Rewrite every literal `Skill("opsx:<id>"[, …])` call in a Claude-authored agent
13
+ * body into the Gemini `activate_skill(name="…")` form. Positional skill input
14
+ * (e.g. `"<specName>"`) is dropped because `activate_skill` takes only `name` and
15
+ * the surrounding persona prose already carries the context. Unknown ids are left
16
+ * untouched (better a visible stale ref than a silent `name="undefined"`). This
17
+ * runs ONLY on the gemini render path; Claude/Codex keep the `Skill(...)` form.
18
+ */
19
+ export declare function translateOpsxSkillCallsForGemini(body: string): string;
20
+ /**
21
+ * Port shared Claude-authored prose to Kimi's directory-skill contract.
22
+ *
23
+ * Kimi's TUI/ACP clients intercept `/skill:*`, but a materialized workflow is
24
+ * already running inside a Session and must activate nested workflows through
25
+ * Kimi's built-in `Skill` tool (`{ skill, args }`). Emitting slash text here
26
+ * would silently become ordinary model text under `kimi -p`. Interactive slash
27
+ * examples therefore belong only in AGENTS/docs, never generated skill bodies.
28
+ * This is render-only; canonical Claude/Codex/Gemini templates stay unchanged.
29
+ */
30
+ export declare function translateClaudeTextForKimi(body: string): string;
31
+ export declare function geminiAgentLimitMetadata(env?: NodeJS.ProcessEnv): string[];
32
+ /**
33
+ * Phase 2 + Phase 3 of the retired install.sh:
34
+ * - Detect prior installation state (.claude/.codex/openspec already present).
35
+ * - Create the directory skeleton.
36
+ * - Copy templates into `.specrails/setup-templates/` (the internal
37
+ * staging dir that placement copies from and `update` diffs against).
38
+ * - Ensure `.gitignore` excludes the runtime artefacts.
39
+ *
40
+ * Placement (`placeArtefacts`) then copies the staged templates directly into
41
+ * the user's live `.claude/agents/` and `.claude/commands/specrails/` dirs so
42
+ * the installer finishes in one pass — no follow-up wizard required.
43
+ */
44
+ export interface ScaffoldInput {
45
+ /** Absolute path to the specrails-core package (installed via npx). */
46
+ scriptDir: string;
47
+ /**
48
+ * Absolute path to the relocated artifact root — where every Specrails-managed
49
+ * artifact (.specrails/.claude/.codex/.gemini/.kimi-code and instruction/settings files)
50
+ * is written. Under relocate-always this is the `$HOME` workspace, NOT the repo.
51
+ */
52
+ artifactRoot: string;
53
+ /**
54
+ * Absolute path to the user's repo root — the ONLY thing that stays in-repo is
55
+ * `openspec/**` (installed by init.ts) and git/worktree ops. Used solely by
56
+ * `detectExistingSetup`'s openspec probe and the gitignore no-op guard.
57
+ */
58
+ codeRoot: string;
59
+ /** Resolved provider from prereqs. */
60
+ provider: Provider;
61
+ /** Derived directory name (`.claude` or `.codex`). */
62
+ providerDir: string;
63
+ /** Optional explicit allow-list used by config-driven installs. */
64
+ selectedAgents?: string[];
65
+ /**
66
+ * When false, the static-placement helpers do NOT create the per-workspace
67
+ * mutable seeds (agent-memory dirs, gemini headless acknowledgments). Used by
68
+ * `installFramework` so the SHARED framework copy stays purely provider-static
69
+ * — the project layer is seeded separately by `assembleProjectWorkspace`.
70
+ * Defaults to true (legacy in-place behaviour for `scaffoldInstallation`).
71
+ */
72
+ seedProjectDirs?: boolean;
73
+ /**
74
+ * When true, place EVERY agent template (the full superset) regardless of
75
+ * `selectedAgents`. Used by `installFramework` so
76
+ * the SHARED framework store is a superset that ANY project's selection can
77
+ * link from — per-project agent filtering then happens at the workspace LINK
78
+ * step (`linkAgentFiles`), not at materialization. Defaults to false (legacy
79
+ * selection-honouring placement for in-place `scaffoldInstallation`).
80
+ */
81
+ materializeAllAgents?: boolean;
82
+ }
83
+ export interface ScaffoldResult {
84
+ existingSetup: boolean;
85
+ createdDirs: string[];
86
+ copiedFiles: number;
87
+ }
88
+ /**
89
+ * Returns true iff any of the provider directories already contains
90
+ * content. The desktop-app-driven path skips the "merge existing?" prompt and
91
+ * assumes `--yes`; the CLI dispatcher (bin/specrails-core.cjs) should
92
+ * have prompted before entering this phase.
93
+ */
94
+ export declare function detectExistingSetup(input: Pick<ScaffoldInput, 'artifactRoot' | 'codeRoot' | 'providerDir'>): boolean;
95
+ /**
96
+ * Entry point. Creates directories, copies templates, updates
97
+ * .gitignore. Returns a summary for logging / tests.
98
+ */
99
+ export declare function scaffoldInstallation(input: ScaffoldInput): ScaffoldResult;
100
+ export interface InstallFrameworkInput {
101
+ /** Absolute path to the specrails-core package (templates/ + commands/). */
102
+ scriptDir: string;
103
+ /** Root of the versioned framework store, e.g. `<home>/.specrails/framework`. */
104
+ frameworkDir: string;
105
+ /** Provider whose static subtree is being materialized. */
106
+ provider: Provider;
107
+ /** Derived provider dir (`.claude`/`.codex`/`.gemini`/`.kimi-code`). */
108
+ providerDir: string;
109
+ /** Framework version (the `<version>/` segment). */
110
+ version: string;
111
+ /** Optional explicit agent allow-list (kept for parity with scaffold). */
112
+ selectedAgents?: string[];
113
+ }
114
+ export interface InstallFrameworkResult {
115
+ /** `<frameworkDir>/<version>/<providerDir>` — root of the static subtree. */
116
+ providerFrameworkDir: string;
117
+ /** `<frameworkDir>/<version>` — the version root (also holds setup-templates/). */
118
+ versionDir: string;
119
+ /** True when a fresh materialization happened; false when the idempotent skip fired. */
120
+ materialized: boolean;
121
+ }
122
+ /** Path to the per-version, per-provider materialization marker (manifest hash). */
123
+ export declare function frameworkStampPath(versionDir: string, providerDir: string): string;
124
+ /**
125
+ * Validate one provider in a materialized version without needing the source
126
+ * package. Used by the final swap gate: the stamp identity and current output
127
+ * hash must still agree immediately before `current` moves.
128
+ */
129
+ export declare function frameworkMaterializationProblem(versionDir: string, version: string, provider: Provider, providerDir: string): string | null;
130
+ /**
131
+ * Materialize the provider-INVARIANT framework subtree ONCE into
132
+ * `<frameworkDir>/<version>/<providerDir>/` (+ `<version>/setup-templates/`).
133
+ * Idempotent: when the providerDir already exists with a matching stamp it is a
134
+ * no-op (the second workspace assemble re-uses the same copy). Writes NO
135
+ * per-workspace state (no agent-memory, no acks, no project-named instruction
136
+ * files) — those are seeded by `assembleProjectWorkspace`.
137
+ */
138
+ export declare function installFramework(input: InstallFrameworkInput): InstallFrameworkResult;
139
+ /**
140
+ * Atomically point `<frameworkDir>/current` at `<version>` so every workspace's
141
+ * provider links resolve through `current/...` and an update is a single swap.
142
+ */
143
+ export declare function ensureCurrentSymlink(frameworkDir: string, version: string): void;
144
+ export interface AssembleProjectWorkspaceInput {
145
+ /** The per-project workspace artifact root (= resolveArtifacts artifactRoot). */
146
+ workspace: string;
147
+ /** Root of the versioned framework store (the parent of `current/`). */
148
+ frameworkDir: string;
149
+ /** Provider whose subtrees are linked into the workspace. */
150
+ provider: Provider;
151
+ /** Derived provider dir (`.claude`/`.codex`/`.gemini`/`.kimi-code`). */
152
+ providerDir: string;
153
+ /** Framework version (used for the manifest record). */
154
+ version: string;
155
+ /** The user's real repo (drives PROJECT_NAME + gemini ack keying). */
156
+ codeRoot: string;
157
+ /** specrails-core package dir (for the manifest hash sources). */
158
+ scriptDir: string;
159
+ /**
160
+ * Optional agent allow-list. Drives BOTH which framework agents are LINKED
161
+ * into the workspace (`linkAgentFiles`) AND which agent-memory dirs are seeded.
162
+ * Undefined = the CORE trio only (the lean default). The SHARED framework store
163
+ * is always the full superset; this is where per-project filtering happens.
164
+ */
165
+ selectedAgents?: string[];
166
+ /**
167
+ * When true, the static provider subtrees (`agents`/`commands`/`skills`/`rules`)
168
+ * and the settings file are COPIED as real files from the framework store into
169
+ * the workspace instead of SYMLINKED. Used by the in-repo standalone install
170
+ * (`init`/`update` with `artifactRoot === codeRoot`) so the repo gets real,
171
+ * committable files — a symlink into `$HOME/.specrails/framework` would be
172
+ * invisible to a standalone user's `claude`/`codex`/`gemini`/`kimi` running in the
173
+ * repo. The PROJECT layer (agent-memory, manifest, instruction files) is real
174
+ * either way. Defaults to false (relocated workspaces symlink — the desktop /
175
+ * `--relocate` path).
176
+ */
177
+ copyStatics?: boolean;
178
+ }
179
+ export interface AssembleProjectWorkspaceResult {
180
+ /** Per-linked-subtree mechanism, for diagnostics (copy-fallback loses O(1) swap). */
181
+ links: Record<string, 'symlink' | 'junction' | 'copy'>;
182
+ /** Agent ids whose memory dirs were seeded as real writable dirs. */
183
+ seededMemoryAgents: string[];
184
+ }
185
+ /**
186
+ * Assemble a project workspace with NO network and NO re-materialization: (a)
187
+ * SYMLINK the static providerDir subtrees from `<frameworkDir>/current/
188
+ * <providerDir>/` into `<workspace>/<providerDir>/`, then (b) seed the PROJECT
189
+ * layer as real writable files (agent-memory dirs, the manifest, project-named
190
+ * instruction/settings files, gemini headless acks re-hashed against the LINKED
191
+ * files). `agent-memory/` is NEVER linked.
192
+ */
193
+ export declare function assembleProjectWorkspace(input: AssembleProjectWorkspaceInput): AssembleProjectWorkspaceResult;
194
+ /**
195
+ * Pre-acknowledge the generated gemini subagents so they load in HEADLESS
196
+ * (`gemini -p`) runs. gemini 0.46+ DISCOVERS `.gemini/agents/*.md` but only
197
+ * ENABLES a project's custom agents after the interactive "New Agents Discovered
198
+ * → Acknowledge and Enable" prompt — which never fires headless, so
199
+ * `invoke_agent sr-architect` returns "Subagent not found" and the implement
200
+ * orchestrator silently falls back to a generic agent (the specialised personas
201
+ * never run, the pipeline degrades). The acknowledgment is a user-global file
202
+ * `~/.gemini/acknowledgments/agents.json` shaped
203
+ * `{ [projectRoot]: { [agentName]: <sha256-hex of the agent .md file> } }`
204
+ * (hash algorithm verified empirically against gemini 0.47 = sha256 of the full
205
+ * file). Writing it at install time makes the freshly-generated agents trusted
206
+ * with no prompt, for both `gemini` CLI and the desktop's headless spawns. The
207
+ * file is MERGED — other projects' and other agents' entries are preserved.
208
+ * Best-effort: any failure is swallowed by the caller (agents still work once
209
+ * acknowledged interactively).
210
+ */
211
+ export declare function writeGeminiAgentAcknowledgments(repoRoot: string, agentIds: string[], agentsBaseDir?: string): void;
@@ -2,6 +2,7 @@ import { createHash, randomUUID } from 'node:crypto';
2
2
  import { constants, cpSync, mkdtempSync, renameSync, rmSync } from 'node:fs';
3
3
  import os from 'node:os';
4
4
  import path from 'node:path';
5
+ import { pathToFileURL } from 'node:url';
5
6
  import { atomicSymlinkSwap, copyDir, copyFile, isDir, isSymlink, listDir, mkdirp, pathExists, readBytes, readTextFile, removePath, symlinkOrCopy, writeFileLf, } from '../util/fs.js';
6
7
  import { info, ok, warn } from '../util/logger.js';
7
8
  import { buildManifest, writeManifestFiles } from './manifest.js';
@@ -152,7 +153,7 @@ const SKILL_FROM_COMMAND = {
152
153
  },
153
154
  'sr-batch-implement': {
154
155
  command: 'batch-implement',
155
- description: 'sr:batch-implement — Batch implementation orchestrator. Accepts multiple feature references, computes dependency-aware execution waves, invokes sr:implement per wave.',
156
+ description: 'sr:batch-implement — Run multiple frozen specs as one programmatic agent workflow.',
156
157
  },
157
158
  'sr-compat-check': {
158
159
  command: 'compat-check',
@@ -322,21 +323,6 @@ export function scaffoldInstallation(input) {
322
323
  const skillsSubdir = input.provider === 'gemini' ? 'agents' : 'skills';
323
324
  info(`Placed ${skills.placed} ${skillsLabel}(s) into ${input.providerDir}/${skillsSubdir}/`);
324
325
  }
325
- const pipelineContract = providerPipelineContract(input.scriptDir);
326
- if (input.provider === 'codex') {
327
- for (const name of ['implement', 'batch-implement', 'retry']) {
328
- prependSkillContract(path.join(input.artifactRoot, '.codex', 'skills', name, 'SKILL.md'), pipelineContract);
329
- }
330
- }
331
- else if (input.provider === 'gemini') {
332
- for (const name of ['implement', 'batch-implement', 'retry']) {
333
- const file = path.join(input.artifactRoot, '.gemini', 'commands', 'specrails', `${name}.toml`);
334
- if (pipelineContract && pathExists(file)) {
335
- const source = readTextFile(file);
336
- writeFileLf(file, source.replace("prompt = '''\n", "prompt = '''\n" + pipelineContract));
337
- }
338
- }
339
- }
340
326
  // --- Codex provider settings + AGENTS.md initial content ---
341
327
  if (input.provider === 'codex') {
342
328
  const written = applyCodexSettings(input);
@@ -1373,17 +1359,15 @@ function writeKimiWorkflowSkill(args) {
1373
1359
  '',
1374
1360
  ].join('\n');
1375
1361
  writeFileLf(args.dest, frontmatter +
1376
- (pathExists(path.join(path.dirname(args.src), '..', '..', 'runtime', 'provider-pipeline.md'))
1377
- ? readTextFile(path.join(path.dirname(args.src), '..', '..', 'runtime', 'provider-pipeline.md')) + '\n' : '') +
1378
- KIMI_NESTED_SKILL_CONTRACT +
1379
- KIMI_ROLE_EXECUTION_CONTRACT +
1380
- KIMI_RUNTIME_CONTEXT_CONTRACT +
1381
- rendered);
1362
+ (['implement', 'batch-implement', 'retry'].includes(args.commandName) ? rendered :
1363
+ (pathExists(path.join(path.dirname(args.src), '..', '..', 'runtime', 'provider-pipeline.md'))
1364
+ ? readTextFile(path.join(path.dirname(args.src), '..', '..', 'runtime', 'provider-pipeline.md')) + '\n' : '') +
1365
+ KIMI_NESTED_SKILL_CONTRACT +
1366
+ KIMI_ROLE_EXECUTION_CONTRACT +
1367
+ KIMI_RUNTIME_CONTEXT_CONTRACT +
1368
+ rendered));
1382
1369
  }
1383
1370
  function adaptKimiWorkflowBody(commandName, body) {
1384
- if (commandName === 'batch-implement') {
1385
- return adaptKimiBatchImplement(body);
1386
- }
1387
1371
  if (commandName === 'auto-propose-backlog-specs') {
1388
1372
  return adaptKimiAutoPropose(body);
1389
1373
  }
@@ -1396,30 +1380,7 @@ function adaptKimiWorkflowBody(commandName, body) {
1396
1380
  if (commandName === 'telemetry') {
1397
1381
  return renderKimiTelemetryWorkflow();
1398
1382
  }
1399
- if (commandName === 'retry') {
1400
- return adaptKimiRetry(body);
1401
- }
1402
- if (commandName !== 'implement')
1403
- return body;
1404
- return body.replace('##### Invocation configuration', [
1405
- '##### Kimi invocation configuration',
1406
- '',
1407
- 'Keep the parsed `AGENT_MODEL` map as structured orchestration data.',
1408
- 'Resolve each role model from its exact profile value and put it in the',
1409
- 'role-wave JSON `model` field; absent values use `k3`. Shell variables',
1410
- 'from earlier tools are not persistent. Never rewrite role frontmatter',
1411
- 'or translate a Claude model alias into a Kimi model.',
1412
- '',
1413
- 'Every implementation role uses `workspace:"current"` and the same',
1414
- 'aggregate execution context. Serialize writers within supplied roots;',
1415
- 'no per-ticket full pipeline, nested worktree, copied-file merge or',
1416
- 'replacement run. The runner preserves shared backlog and frozen specs',
1417
- 'even though each role has a private execution cwd.',
1418
- '',
1419
- ].join('\n'));
1420
- }
1421
- function adaptKimiBatchImplement(body) {
1422
- return body.replace('Delegate to implement once with all frozen specs and selected roots.', 'Activate `Skill(skill="specrails-implement", args="<all original arguments>")` once in this orchestrator with all frozen specs and selected roots. Do not launch a role wave of full implementations or one implementation per ticket.');
1383
+ return body;
1423
1384
  }
1424
1385
  function adaptKimiAutoPropose(body) {
1425
1386
  return body
@@ -1437,21 +1398,6 @@ function adaptKimiAutoPropose(body) {
1437
1398
  .replaceAll('The Explore agent receives this prompt:', 'The sr-product-analyst role receives this prompt:')
1438
1399
  .replaceAll('After the Explore agent completes:', 'After the sr-product-analyst role completes:');
1439
1400
  }
1440
- function adaptKimiRetry(body) {
1441
- return body + [
1442
- '',
1443
- '## Kimi direct-role continuation',
1444
- '',
1445
- 'Use the existing runtime status and exact absolute context. Invoke only',
1446
- 'the required sr-* or profile role through a foreground role wave, using',
1447
- '`workspace:"current"`; do not activate a nested specrails-implement.',
1448
- 'Pass the complete bounded handoff explicitly, including every frozen',
1449
- 'criterion, selected roots, current phase and next action. Native session',
1450
- 'memory is not a substitute. Preserve valid completed phases and source',
1451
- 'work when a later reviewer or archive step is blocked.',
1452
- '',
1453
- ].join('\n');
1454
- }
1455
1401
  function renderKimiEnrichWorkflow() {
1456
1402
  return [
1457
1403
  '# Enrich SpecRails for Kimi Code',
@@ -1937,6 +1883,8 @@ function renderInitialKimiAgentsMd(repoRoot) {
1937
1883
  '`.kimi-code/specrails/run-skill.mjs`. Role skills live at',
1938
1884
  '`.kimi-code/skills/<sr-*|custom-*>/SKILL.md` and are launched by workflows in',
1939
1885
  'separate helper-managed `kimi -p --output-format stream-json` processes.',
1886
+ 'Inside a programmatic runtime role, follow the supplied OpenSpec tools and',
1887
+ 'frozen scope instead; never start a nested implementation workflow.',
1940
1888
  '',
1941
1889
  '## Conventions',
1942
1890
  '',
@@ -1956,40 +1904,7 @@ function renderInitialKimiAgentsMd(repoRoot) {
1956
1904
  ].join('\n');
1957
1905
  }
1958
1906
  function renderInitialGeminiMd(repoRoot) {
1959
- const projectName = path.basename(repoRoot);
1960
- return [
1961
- AGENTS_MD_START,
1962
- '',
1963
- `# ${projectName} — agent instructions`,
1964
- '',
1965
- 'This project uses the **specrails** agent workflow under `.gemini/`.',
1966
- 'See `.gemini/commands/specrails/` for the slash commands and `.gemini/agents/`',
1967
- 'for the `sr-*` subagents available to gemini sessions in this repository.',
1968
- '',
1969
- '## Conventions',
1970
- '',
1971
- '- Read specs from `.specrails/local-tickets.json` when implementing',
1972
- ' numbered tickets (`#42`, `#71` etc.).',
1973
- '- Prefer the `/specrails:*` commands (implement, batch-implement, …) over',
1974
- ' ad-hoc edits when one covers the task.',
1975
- '- Agent execution is enabled via `.gemini/settings.json`',
1976
- ' (`experimental.enableAgents: true`).',
1977
- '',
1978
- AGENTS_MD_END,
1979
- '',
1980
- ].join('\n');
1981
- }
1982
- function providerPipelineContract(scriptDir) {
1983
- const source = path.join(scriptDir, 'templates', 'runtime', 'provider-pipeline.md');
1984
- return pathExists(source) ? readTextFile(source) + '\n\n' : '';
1985
- }
1986
- function prependSkillContract(file, contract) {
1987
- if (!contract || !pathExists(file))
1988
- return;
1989
- const source = readTextFile(file);
1990
- const end = source.startsWith('---\n') ? source.indexOf('\n---\n', 4) : -1;
1991
- const index = end < 0 ? 0 : end + 5;
1992
- writeFileLf(file, source.slice(0, index) + '\n' + contract + source.slice(index));
1907
+ return renderInitialAgentsMd(repoRoot).replace(AGENTS_MD_END, 'Read provider rules from `.gemini/`.\n\n' + AGENTS_MD_END);
1993
1908
  }
1994
1909
  function assertPipelineRuntimeSource(scriptDir) {
1995
1910
  const contractFile = path.join(scriptDir, 'integration-contract.json');
@@ -2009,6 +1924,22 @@ function placePipelineRuntime(input) {
2009
1924
  copyFile(source, path.join(dest, 'pipeline-state.mjs'));
2010
1925
  writeFileLf(path.join(dest, 'pipeline.mjs'), "import { runPipelineCli } from './pipeline-state.mjs'\n" +
2011
1926
  "process.exitCode = await runPipelineCli(process.argv.slice(2))\n");
1927
+ const runtime = path.join(input.scriptDir, 'dist', 'agent-runtime', 'cli.js');
1928
+ if (pathExists(runtime)) {
1929
+ writeFileLf(path.join(dest, 'agent-runtime.mjs'), `import { runRuntimeCommand } from ${JSON.stringify(pathToFileURL(runtime).href)}\n` +
1930
+ `import { parseArgs } from ${JSON.stringify(pathToFileURL(path.join(input.scriptDir, 'dist', 'installer', 'cli.js')).href)}\n` +
1931
+ "const { subcommand, flags, positionals } = parseArgs(process.argv.slice(2))\n" +
1932
+ "try { process.exitCode = await runRuntimeCommand(flags, [subcommand, ...positionals].filter(Boolean)) } catch (error) { console.error(error.message); process.exitCode = 1 }\n");
1933
+ const configPath = path.join(input.artifactRoot, '.specrails', 'agent-runtime.json');
1934
+ if (!pathExists(configPath)) {
1935
+ const provider = input.provider;
1936
+ writeFileLf(configPath, JSON.stringify({ schemaVersion: 1, enabled: true,
1937
+ providers: [{ id: provider, kind: 'cli', cli: provider }],
1938
+ agents: Object.fromEntries(['architect', 'developer', 'reviewer'].map(role => [role, { provider, maxTurns: 100 }])), verification: [],
1939
+ }, null, 2) + '\n');
1940
+ }
1941
+ return 3;
1942
+ }
2012
1943
  return 2;
2013
1944
  }
2014
1945
  function pruneLegacyArtifacts(input) {
@@ -2317,19 +2248,18 @@ function renderInitialAgentsMd(repoRoot) {
2317
2248
  '',
2318
2249
  `# ${projectName} — agent instructions`,
2319
2250
  '',
2320
- 'This project uses the **specrails** agent workflow under `.codex/`.',
2321
- 'See `.codex/skills/` for the catalog of agent skills available to codex',
2322
- 'sessions in this repository.',
2251
+ 'Implementation is coordinated by the Specrails programmatic agent runtime.',
2252
+ 'Use the frozen scope and official OpenSpec workflow supplied for your role.',
2253
+ 'Do not start another implement or batch-implement workflow inside a role.',
2323
2254
  '',
2324
- '## Conventions',
2255
+ '## Repository context',
2325
2256
  '',
2326
- '- Read specs from `.specrails/local-tickets.json` when implementing',
2327
- ' numbered tickets (`#42`, `#71` etc.).',
2328
- '- Prefer the skills in `.codex/skills/sr-*` over ad-hoc edits when a',
2329
- ' skill covers the task (implement, batch-implement, refactor-recommender,',
2330
- ' compat-check, why, ...).',
2331
- '- Honour the sandbox policy declared in `.codex/config.toml`',
2332
- ' (`sandbox_mode` + `approval_policy` top-level keys).',
2257
+ '- Read project README, CONTRIBUTING and relevant nested instructions.',
2258
+ '- Use package manifests and checked-in build wrappers for actual commands.',
2259
+ '- Read API contracts before changing consumers or generated code.',
2260
+ '- Keep edits within the admitted repositories; report permission blockers',
2261
+ ' with the affected repository and path instead of repeating the attempt.',
2262
+ '- Report incomplete tasks and their concrete reasons in the role result.',
2333
2263
  '',
2334
2264
  AGENTS_MD_END,
2335
2265
  '',