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.
- package/README.md +3 -0
- package/bin/specrails-core.mjs +5 -0
- package/dist/agent-runtime/capabilities.d.ts +27 -0
- package/dist/agent-runtime/capabilities.js +73 -0
- package/dist/agent-runtime/capabilities.js.map +1 -0
- package/dist/agent-runtime/cli-executor.d.ts +43 -0
- package/dist/agent-runtime/cli-executor.js +405 -0
- package/dist/agent-runtime/cli-executor.js.map +1 -0
- package/dist/agent-runtime/cli-process.d.ts +32 -0
- package/dist/agent-runtime/cli-process.js +159 -0
- package/dist/agent-runtime/cli-process.js.map +1 -0
- package/dist/agent-runtime/cli.d.ts +39 -0
- package/dist/agent-runtime/cli.js +216 -0
- package/dist/agent-runtime/cli.js.map +1 -0
- package/dist/agent-runtime/codex-schema.d.ts +4 -0
- package/dist/agent-runtime/codex-schema.js +31 -0
- package/dist/agent-runtime/codex-schema.js.map +1 -0
- package/dist/agent-runtime/config.d.ts +11 -0
- package/dist/agent-runtime/config.js +263 -0
- package/dist/agent-runtime/config.js.map +1 -0
- package/dist/agent-runtime/core-host.d.ts +41 -0
- package/dist/agent-runtime/core-host.js +132 -0
- package/dist/agent-runtime/core-host.js.map +1 -0
- package/dist/agent-runtime/durable-store.d.ts +22 -0
- package/dist/agent-runtime/durable-store.js +205 -0
- package/dist/agent-runtime/durable-store.js.map +1 -0
- package/dist/agent-runtime/efficiency-summary.d.ts +67 -0
- package/dist/agent-runtime/efficiency-summary.js +52 -0
- package/dist/agent-runtime/efficiency-summary.js.map +1 -0
- package/dist/agent-runtime/efficiency-types.d.ts +60 -0
- package/dist/agent-runtime/efficiency-types.js +8 -0
- package/dist/agent-runtime/efficiency-types.js.map +1 -0
- package/dist/agent-runtime/efficiency.d.ts +5 -0
- package/dist/agent-runtime/efficiency.js +35 -0
- package/dist/agent-runtime/efficiency.js.map +1 -0
- package/dist/agent-runtime/evaluation-corpus.d.ts +13 -0
- package/dist/agent-runtime/evaluation-corpus.js +8 -0
- package/dist/agent-runtime/evaluation-corpus.js.map +1 -0
- package/dist/agent-runtime/evaluation.d.ts +43 -0
- package/dist/agent-runtime/evaluation.js +171 -0
- package/dist/agent-runtime/evaluation.js.map +1 -0
- package/dist/agent-runtime/executor-types.d.ts +125 -0
- package/dist/agent-runtime/executor-types.js +29 -0
- package/dist/agent-runtime/executor-types.js.map +1 -0
- package/dist/agent-runtime/executors.d.ts +23 -0
- package/dist/agent-runtime/executors.js +48 -0
- package/dist/agent-runtime/executors.js.map +1 -0
- package/dist/agent-runtime/gemini-policy.d.ts +8 -0
- package/dist/agent-runtime/gemini-policy.js +36 -0
- package/dist/agent-runtime/gemini-policy.js.map +1 -0
- package/dist/agent-runtime/graph/artifacts.d.ts +26 -0
- package/dist/agent-runtime/graph/artifacts.js +205 -0
- package/dist/agent-runtime/graph/artifacts.js.map +1 -0
- package/dist/agent-runtime/graph/nodes.d.ts +39 -0
- package/dist/agent-runtime/graph/nodes.js +321 -0
- package/dist/agent-runtime/graph/nodes.js.map +1 -0
- package/dist/agent-runtime/graph/review-policy.d.ts +18 -0
- package/dist/agent-runtime/graph/review-policy.js +32 -0
- package/dist/agent-runtime/graph/review-policy.js.map +1 -0
- package/dist/agent-runtime/graph/roles.d.ts +47 -0
- package/dist/agent-runtime/graph/roles.js +190 -0
- package/dist/agent-runtime/graph/roles.js.map +1 -0
- package/dist/agent-runtime/graph/state.d.ts +83 -0
- package/dist/agent-runtime/graph/state.js +23 -0
- package/dist/agent-runtime/graph/state.js.map +1 -0
- package/dist/agent-runtime/graph-checkpointer.d.ts +61 -0
- package/dist/agent-runtime/graph-checkpointer.js +137 -0
- package/dist/agent-runtime/graph-checkpointer.js.map +1 -0
- package/dist/agent-runtime/index.d.ts +20 -0
- package/dist/agent-runtime/index.js +21 -0
- package/dist/agent-runtime/index.js.map +1 -0
- package/dist/agent-runtime/kimi-acp.d.ts +11 -0
- package/dist/agent-runtime/kimi-acp.js +190 -0
- package/dist/agent-runtime/kimi-acp.js.map +1 -0
- package/dist/agent-runtime/openai-executor.d.ts +26 -0
- package/dist/agent-runtime/openai-executor.js +192 -0
- package/dist/agent-runtime/openai-executor.js.map +1 -0
- package/dist/agent-runtime/openspec-tool-server.d.ts +1 -0
- package/dist/agent-runtime/openspec-tool-server.js +37 -0
- package/dist/agent-runtime/openspec-tool-server.js.map +1 -0
- package/dist/agent-runtime/openspec.d.ts +123 -0
- package/dist/agent-runtime/openspec.js +263 -0
- package/dist/agent-runtime/openspec.js.map +1 -0
- package/dist/agent-runtime/prompts.d.ts +44 -0
- package/dist/agent-runtime/prompts.js +310 -0
- package/dist/agent-runtime/prompts.js.map +1 -0
- package/dist/agent-runtime/provider-diagnostic.d.ts +2 -0
- package/dist/agent-runtime/provider-diagnostic.js +25 -0
- package/dist/agent-runtime/provider-diagnostic.js.map +1 -0
- package/dist/agent-runtime/repository-context.d.ts +25 -0
- package/dist/agent-runtime/repository-context.js +100 -0
- package/dist/agent-runtime/repository-context.js.map +1 -0
- package/dist/agent-runtime/review-context.d.ts +14 -0
- package/dist/agent-runtime/review-context.js +41 -0
- package/dist/agent-runtime/review-context.js.map +1 -0
- package/dist/agent-runtime/role-routing.d.ts +10 -0
- package/dist/agent-runtime/role-routing.js +29 -0
- package/dist/agent-runtime/role-routing.js.map +1 -0
- package/dist/agent-runtime/role-state.d.ts +19 -0
- package/dist/agent-runtime/role-state.js +24 -0
- package/dist/agent-runtime/role-state.js.map +1 -0
- package/dist/agent-runtime/runtime-identity.d.ts +11 -0
- package/dist/agent-runtime/runtime-identity.js +33 -0
- package/dist/agent-runtime/runtime-identity.js.map +1 -0
- package/dist/agent-runtime/tool-event.d.ts +3 -0
- package/dist/agent-runtime/tool-event.js +24 -0
- package/dist/agent-runtime/tool-event.js.map +1 -0
- package/dist/agent-runtime/verification-plan.d.ts +55 -0
- package/dist/agent-runtime/verification-plan.js +206 -0
- package/dist/agent-runtime/verification-plan.js.map +1 -0
- package/dist/agent-runtime/workflow-types.d.ts +226 -0
- package/dist/agent-runtime/workflow-types.js +2 -0
- package/dist/agent-runtime/workflow-types.js.map +1 -0
- package/dist/agent-runtime/workflow.d.ts +17 -0
- package/dist/agent-runtime/workflow.js +636 -0
- package/dist/agent-runtime/workflow.js.map +1 -0
- package/dist/agent-runtime/workspace-tools.d.ts +29 -0
- package/dist/agent-runtime/workspace-tools.js +282 -0
- package/dist/agent-runtime/workspace-tools.js.map +1 -0
- package/dist/installer/cli.d.ts +35 -0
- package/dist/installer/cli.js +3 -0
- package/dist/installer/cli.js.map +1 -1
- package/dist/installer/commands/doctor.d.ts +27 -0
- package/dist/installer/commands/framework.d.ts +85 -0
- package/dist/installer/commands/init.d.ts +147 -0
- package/dist/installer/commands/update.d.ts +56 -0
- package/dist/installer/commands/v5-migration.d.ts +32 -0
- package/dist/installer/phases/framework-lifecycle.d.ts +53 -0
- package/dist/installer/phases/install-config.d.ts +64 -0
- package/dist/installer/phases/manifest.d.ts +45 -0
- package/dist/installer/phases/prereqs.d.ts +51 -0
- package/dist/installer/phases/provider-detect.d.ts +89 -0
- package/dist/installer/phases/scaffold.d.ts +211 -0
- package/dist/installer/phases/scaffold.js +39 -109
- package/dist/installer/phases/scaffold.js.map +1 -1
- package/dist/installer/runtime/kimi.d.ts +84 -0
- package/dist/installer/runtime/pipeline-state.d.ts +351 -0
- package/dist/installer/runtime/pipeline-state.js +514 -41
- package/dist/installer/runtime/pipeline-state.js.map +1 -1
- package/dist/installer/util/errors.d.ts +46 -0
- package/dist/installer/util/exec.d.ts +41 -0
- package/dist/installer/util/fs.d.ts +153 -0
- package/dist/installer/util/git.d.ts +44 -0
- package/dist/installer/util/install-transaction.d.ts +29 -0
- package/dist/installer/util/logger.d.ts +31 -0
- package/dist/installer/util/paths.d.ts +34 -0
- package/dist/installer/util/prompts.d.ts +23 -0
- package/dist/installer/util/registry.d.ts +174 -0
- package/dist/installer/util/template.d.ts +23 -0
- package/docs/README.md +1 -0
- package/docs/agent-runtime-efficiency.md +65 -0
- package/docs/agent-runtime.md +339 -0
- package/integration-contract.json +80 -7
- package/package.json +20 -2
- package/schemas/agent-runtime.schema.json +77 -0
- package/schemas/fixtures/runtime-efficiency-summary.v1.json +790 -0
- package/templates/codex-skills/batch-implement/SKILL.md +33 -58
- package/templates/codex-skills/implement/SKILL.md +21 -124
- package/templates/codex-skills/retry/SKILL.md +8 -34
- package/templates/commands/specrails/batch-implement.md +21 -16
- package/templates/commands/specrails/implement.md +17 -276
- package/templates/commands/specrails/retry.md +6 -34
- package/templates/gemini-commands/batch-implement.toml +34 -28
- package/templates/gemini-commands/implement.toml +34 -55
- 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 —
|
|
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
|
-
(
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
'
|
|
2321
|
-
'
|
|
2322
|
-
'
|
|
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
|
-
'##
|
|
2255
|
+
'## Repository context',
|
|
2325
2256
|
'',
|
|
2326
|
-
'- Read
|
|
2327
|
-
'
|
|
2328
|
-
'-
|
|
2329
|
-
'
|
|
2330
|
-
'
|
|
2331
|
-
'-
|
|
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
|
'',
|