@kuznai/inception-engine 0.18.0 → 0.19.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 +27 -24
- package/dist/config/agents.js +87 -10
- package/dist/core/adapters/agent-definitions.d.ts +2 -2
- package/dist/core/adapters/agent-definitions.js +6 -5
- package/dist/core/adapters/index.d.ts +1 -1
- package/dist/core/adapters/index.js +4 -4
- package/dist/core/adapters/mcp.d.ts +2 -2
- package/dist/core/adapters/mcp.js +4 -4
- package/dist/core/adapters/rules.d.ts +2 -2
- package/dist/core/adapters/rules.js +61 -14
- package/dist/core/deploy.d.ts +1 -1
- package/dist/core/deploy.js +206 -54
- package/dist/core/init.js +127 -47
- package/dist/core/ownership.d.ts +2 -2
- package/dist/core/preflight.d.ts +1 -1
- package/dist/core/preflight.js +95 -25
- package/dist/core/resolve.d.ts +1 -1
- package/dist/core/resolve.js +7 -4
- package/dist/core/revert.js +9 -7
- package/dist/core/runtime-paths.d.ts +2 -1
- package/dist/core/runtime-paths.js +30 -23
- package/dist/core/validation.d.ts +10 -1
- package/dist/core/validation.js +55 -0
- package/dist/formatters.d.ts +5 -0
- package/dist/formatters.js +58 -0
- package/dist/index.js +8 -24
- package/dist/logger.js +22 -21
- package/dist/schemas/manifest.d.ts +2 -0
- package/dist/schemas/manifest.js +8 -5
- package/dist/schemas/registry.d.ts +38 -0
- package/dist/schemas/registry.js +7 -0
- package/dist/types.d.ts +47 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ inception-engine reads a manifest file (`inception.json`) from the target direct
|
|
|
27
27
|
|
|
28
28
|
Managed skills overwrite their previous version. If a target exists but was not created by inception-engine, deployment refuses to replace it. On POSIX systems, symlinks mean updates to the source repo are reflected immediately.
|
|
29
29
|
|
|
30
|
-
Before executing, the deploy command runs preflight analysis on instruction files: it warns when the same agent will have
|
|
30
|
+
Before executing, the deploy command runs preflight analysis on instruction files: it validates that `agentRules` and `agentDefinitions` for targets requiring specific structure (like `github-copilot` and `antigravity`) include valid YAML frontmatter with `name` and `description` fields. For `github-copilot`, it further ensures either `tools` or `instructions` are defined; for `antigravity`, it validates the shape of any `mcp-servers` or `mcpServers` defined in the frontmatter. It also warns when the same agent will have multiple `agentRules` scopes active simultaneously, when the same source file is deployed to multiple scopes (duplicate-content risk), when `agentRules` or `agentDefinitions` source files exceed 50 KB (context-budget risk), and when GitHub Copilot appears to be running under enterprise-managed policy that may override local configuration. Warnings are printed but do not block deployment; structural validation failures block deployment for the affected targets.
|
|
31
31
|
|
|
32
32
|
## Agent Compatibility Matrix
|
|
33
33
|
|
|
@@ -51,11 +51,11 @@ Before executing, the deploy command runs preflight analysis on instruction file
|
|
|
51
51
|
| File write | All agents via manifest and CLI | All agents |
|
|
52
52
|
| Config patch (JSON merge) | All agents via manifest and CLI | All agents |
|
|
53
53
|
| MCP Servers | claude-code, gemini-cli, codex, antigravity, opencode; github-copilot repo-scoped surfaces are warned and skipped | claude-code, gemini-cli, codex, antigravity, opencode |
|
|
54
|
-
| Global/Repo Rules Files |
|
|
54
|
+
| Global/Repo/Workspace Rules Files | `scope: "global"` and `scope: "repo"` are supported on the implemented agent surfaces; `scope: "workspace"` is supported for `claude-code`, `codex`, and `gemini-cli`; `github-copilot` reads Claude-native rules via `claude-code` and has no separate rules deployment target | All supported agents |
|
|
55
55
|
| Permissions / Approval Config | claude-code (`~/.claude/settings.json`), codex (`~/.codex/config.toml`); other agents are warned and skipped | claude-code, codex |
|
|
56
56
|
| Agent Definitions | claude-code (`{repo}/.claude/agents/{name}.md`), gemini-cli (`{repo}/.gemini/agents/{name}.md`), antigravity (`{repo}/.agents/rules/{name}.md`), opencode (`{repo}/.opencode/agents/{name}.md`), github-copilot (`{repo}/.github/agents/{name}.agent.md`); codex is warned and skipped | All supported agents |
|
|
57
57
|
| `init` manifest generation | Scans `SKILL.md` directories (`skills`), `.md` files with Claude-first agent mapping (`agentRules`), `mcp-servers.json` (`mcpServers`), and agent-definition Markdown files (`agentDefinitions`); emits hints for `files/` and `configs/` directories | N/A |
|
|
58
|
-
| Instruction preflight analysis | Emits `precedence` warnings when an agent has
|
|
58
|
+
| Instruction preflight analysis | Emits `precedence` warnings when an agent has multiple `agentRules` scopes active simultaneously or the same source file is deployed to multiple scopes; emits `budget` warnings when `agentRules` or `agentDefinitions` source files exceed 50 KB; emits GitHub Copilot enterprise-policy warnings when local configuration may be overridden | N/A |
|
|
59
59
|
|
|
60
60
|
Features that depend on agent-specific config surfaces are intentionally conservative: if a target path or schema is not implemented with enough confidence, inception-engine warns and skips it rather than guessing.
|
|
61
61
|
|
|
@@ -173,22 +173,23 @@ Each **agentRules** entry deploys a Markdown instruction file to an agent's supp
|
|
|
173
173
|
- **name** - Unique identifier (same format as skill names)
|
|
174
174
|
- **path** - Relative path to the source Markdown file within the repo; supported rules adapters require a `.md` or `.markdown` source path
|
|
175
175
|
- **agents** - Array of agent IDs to deploy this file to
|
|
176
|
-
- **scope** - `"global"` (default) or `"
|
|
177
|
-
- `"global"` — deploys to the agent's home-directory instruction file (e.g., `~/.claude/CLAUDE.md` for `claude-code`)
|
|
178
|
-
- `"repo"` — deploys to the project-root instruction file inside the deployed repository (e.g., `{repo}/CLAUDE.md` for `claude-code`)
|
|
176
|
+
- **scope** - `"global"` (default), `"repo"`, or `"workspace"`. Controls which instruction surface is targeted:
|
|
177
|
+
- `"global"` — deploys to the agent's home-directory instruction file when that surface is supported (e.g., `~/.claude/CLAUDE.md` for `claude-code`)
|
|
178
|
+
- `"repo"` — deploys to the project-root instruction file inside the deployed repository when that surface is supported (e.g., `{repo}/CLAUDE.md` for `claude-code`)
|
|
179
|
+
- `"workspace"` — deploys to the workspace-root instruction file when an agent exposes one (e.g., `{workspace}/CLAUDE.md` for `claude-code`); when unsupported, deployment is skipped with a warning
|
|
179
180
|
|
|
180
|
-
Instruction rule deployment is supported for
|
|
181
|
+
Instruction rule deployment is supported for implemented global, repo, and workspace surfaces. The target path depends on the agent and the `scope`:
|
|
181
182
|
|
|
182
|
-
| Agent | `scope: "global"` | `scope: "repo"` |
|
|
183
|
-
|
|
184
|
-
| `claude-code` | `~/.claude/CLAUDE.md` | `{repo}/CLAUDE.md` |
|
|
185
|
-
| `codex` | `~/.codex/AGENTS.md` | `{repo}/AGENTS.md` |
|
|
186
|
-
| `gemini-cli` | `~/.gemini/GEMINI.md` | `{repo}/GEMINI.md` |
|
|
187
|
-
| `antigravity` |
|
|
188
|
-
| `opencode` | `~/.config/opencode/AGENTS.md` | `{repo}/AGENTS.md` |
|
|
189
|
-
| `github-copilot` | unsupported
|
|
183
|
+
| Agent | `scope: "global"` | `scope: "repo"` | `scope: "workspace"` |
|
|
184
|
+
|---|---|---|---|
|
|
185
|
+
| `claude-code` | `~/.claude/CLAUDE.md` | `{repo}/CLAUDE.md` | `{workspace}/CLAUDE.md` |
|
|
186
|
+
| `codex` | `~/.codex/AGENTS.md` | `{repo}/AGENTS.md` | `{workspace}/AGENTS.md` |
|
|
187
|
+
| `gemini-cli` | `~/.gemini/GEMINI.md` | `{repo}/GEMINI.md` | `{workspace}/GEMINI.md` |
|
|
188
|
+
| `antigravity` | `~/.gemini/GEMINI.md` | `{repo}/GEMINI.md` | unsupported; warns and skips |
|
|
189
|
+
| `opencode` | `~/.config/opencode/AGENTS.md` | `{repo}/AGENTS.md` | unsupported; warns and skips |
|
|
190
|
+
| `github-copilot` | unsupported / Claude-first | deploy via `claude-code` | unsupported; deploy via `claude-code` with `scope: "workspace"` |
|
|
190
191
|
|
|
191
|
-
For `antigravity`,
|
|
192
|
+
For `antigravity`, `agentRules` now targets the shared GEMINI.md surface (`~/.gemini/GEMINI.md` for `global`, `{repo}/GEMINI.md` for `repo`) — the same paths used by `gemini-cli`. When both agents appear in the same entry, deduplication ensures only one write action is emitted. `workspace` scope is not supported and is skipped with a warning. For `github-copilot`, no separate deployment is needed — target it via the `claude-code` agentRules entry and it reaches Copilot automatically. Revert removes the deployed rules file.
|
|
192
193
|
|
|
193
194
|
Each **permissions** entry deploys execution and safety-oriented configuration to an agent's permission or approval surface:
|
|
194
195
|
|
|
@@ -275,8 +276,8 @@ Current `init` behavior:
|
|
|
275
276
|
- Uses the directory name as the manifest skill name
|
|
276
277
|
- Applies either the `--agents` list or all currently known agent IDs
|
|
277
278
|
- Refuses to overwrite an existing `inception.json` unless `--force` is provided
|
|
278
|
-
- Supports `--
|
|
279
|
-
- Discovers agent-rules Markdown files in the root and conventional subdirectories (`rules/`, `instructions/`, `.github
|
|
279
|
+
- Supports `--plan` so you can inspect the generated manifest before writing it
|
|
280
|
+
- Discovers agent-rules Markdown files in the root and conventional subdirectories (`rules/`, `instructions/`, `.github/`), mapping them to agents using Claude-first portability conventions: `copilot-instructions.md` maps to `claude-code` (Copilot reads `CLAUDE.md` natively), and the fallback for unrecognized files excludes agents whose agentRules surface is unsupported
|
|
280
281
|
- Reads `mcp-servers.json` from the repo root (if present) and generates `mcpServers` entries; invalid entries are warned and skipped
|
|
281
282
|
- Reads `files-manifest.json` from the repo root (if present) and generates `files` entries; invalid entries are warned and skipped
|
|
282
283
|
- Reads `configs-manifest.json` from the repo root (if present) and generates `configs` entries; invalid entries are warned and skipped
|
|
@@ -366,13 +367,15 @@ inception-engine init <directory> [options]
|
|
|
366
367
|
|
|
367
368
|
| Option | Description |
|
|
368
369
|
|---|---|
|
|
369
|
-
| `--
|
|
370
|
+
| `--plan` | Show what would be done without making changes |
|
|
370
371
|
| `--agents <list>` | Comma-separated list of agent IDs to target (overrides deploy detection; restricts revert) |
|
|
371
372
|
| `--force` | `init` only; overwrite an existing `inception.json` |
|
|
372
373
|
| `--verbose` | Show detailed output including file paths |
|
|
373
374
|
| `--debug` | Show full error stack traces |
|
|
374
375
|
| `--help` | Show help message |
|
|
375
376
|
|
|
377
|
+
With `--plan`, deploy and revert print a grouped action preview by agent. Each planned change includes the source path when applicable, the resolved target path, and action-specific details such as JSON/TOML patch payloads or emitted frontmatter content.
|
|
378
|
+
|
|
376
379
|
### Examples
|
|
377
380
|
|
|
378
381
|
```bash
|
|
@@ -380,7 +383,7 @@ inception-engine init <directory> [options]
|
|
|
380
383
|
npx @kuznai/inception-engine ./my-skills-repo
|
|
381
384
|
|
|
382
385
|
# Preview what would be deployed
|
|
383
|
-
npx @kuznai/inception-engine ./my-skills-repo --
|
|
386
|
+
npx @kuznai/inception-engine ./my-skills-repo --plan
|
|
384
387
|
|
|
385
388
|
# Deploy only to Claude Code and Codex
|
|
386
389
|
npx @kuznai/inception-engine ./my-skills-repo --agents claude-code,codex
|
|
@@ -389,13 +392,13 @@ npx @kuznai/inception-engine ./my-skills-repo --agents claude-code,codex
|
|
|
389
392
|
npx @kuznai/inception-engine revert ./my-skills-repo
|
|
390
393
|
|
|
391
394
|
# Preview what would be removed
|
|
392
|
-
npx @kuznai/inception-engine revert ./my-skills-repo --
|
|
395
|
+
npx @kuznai/inception-engine revert ./my-skills-repo --plan
|
|
393
396
|
|
|
394
397
|
# Generate a starter manifest from discovered skill folders
|
|
395
398
|
npx @kuznai/inception-engine init ./my-skills-repo
|
|
396
399
|
|
|
397
400
|
# Preview the generated manifest without writing it
|
|
398
|
-
npx @kuznai/inception-engine init ./my-skills-repo --
|
|
401
|
+
npx @kuznai/inception-engine init ./my-skills-repo --plan
|
|
399
402
|
```
|
|
400
403
|
|
|
401
404
|
## Sample Skills
|
|
@@ -405,8 +408,8 @@ The `limbo/` directory contains exceptional sample skills for testing purposes o
|
|
|
405
408
|
Try them out:
|
|
406
409
|
|
|
407
410
|
```bash
|
|
408
|
-
npx @kuznai/inception-engine init limbo --
|
|
409
|
-
npx @kuznai/inception-engine limbo --
|
|
411
|
+
npx @kuznai/inception-engine init limbo --plan
|
|
412
|
+
npx @kuznai/inception-engine limbo --plan
|
|
410
413
|
```
|
|
411
414
|
|
|
412
415
|
## Agent Detection
|
package/dist/config/agents.js
CHANGED
|
@@ -60,6 +60,14 @@ export const AGENT_REGISTRY = [
|
|
|
60
60
|
windows: ["{repo}", ".claude", "agents", "{name}.md"],
|
|
61
61
|
},
|
|
62
62
|
},
|
|
63
|
+
agentRulesWorkspaceSupport: {
|
|
64
|
+
status: "supported",
|
|
65
|
+
schemaLabel: "workspace-local CLAUDE.md",
|
|
66
|
+
path: {
|
|
67
|
+
posix: ["{workspace}", "CLAUDE.md"],
|
|
68
|
+
windows: ["{workspace}", "CLAUDE.md"],
|
|
69
|
+
},
|
|
70
|
+
},
|
|
63
71
|
},
|
|
64
72
|
{
|
|
65
73
|
id: "codex",
|
|
@@ -117,6 +125,14 @@ export const AGENT_REGISTRY = [
|
|
|
117
125
|
schemaLabel: "dedicated agent definition directory",
|
|
118
126
|
reason: "OpenAI Codex does not expose a documented dedicated per-agent definition directory surface separate from AGENTS.md and config.toml — use agentRules to deploy persona instructions instead",
|
|
119
127
|
},
|
|
128
|
+
agentRulesWorkspaceSupport: {
|
|
129
|
+
status: "supported",
|
|
130
|
+
schemaLabel: "workspace-local AGENTS.md",
|
|
131
|
+
path: {
|
|
132
|
+
posix: ["{workspace}", "AGENTS.md"],
|
|
133
|
+
windows: ["{workspace}", "AGENTS.md"],
|
|
134
|
+
},
|
|
135
|
+
},
|
|
120
136
|
},
|
|
121
137
|
{
|
|
122
138
|
id: "gemini-cli",
|
|
@@ -175,6 +191,14 @@ export const AGENT_REGISTRY = [
|
|
|
175
191
|
windows: ["{repo}", ".gemini", "agents", "{name}.md"],
|
|
176
192
|
},
|
|
177
193
|
},
|
|
194
|
+
agentRulesWorkspaceSupport: {
|
|
195
|
+
status: "supported",
|
|
196
|
+
schemaLabel: "workspace-local GEMINI.md",
|
|
197
|
+
path: {
|
|
198
|
+
posix: ["{workspace}", "GEMINI.md"],
|
|
199
|
+
windows: ["{workspace}", "GEMINI.md"],
|
|
200
|
+
},
|
|
201
|
+
},
|
|
178
202
|
},
|
|
179
203
|
{
|
|
180
204
|
id: "antigravity",
|
|
@@ -203,20 +227,25 @@ export const AGENT_REGISTRY = [
|
|
|
203
227
|
windows: ["{repo}", ".agents", "rules", "{name}.md"],
|
|
204
228
|
},
|
|
205
229
|
},
|
|
230
|
+
// Antigravity shares its instruction surfaces with gemini-cli (both target
|
|
231
|
+
// the same GEMINI.md paths). surfaceKind: shared-via drives deduplication
|
|
232
|
+
// when both agents appear in the same agentRules entry.
|
|
206
233
|
agentRulesSupport: {
|
|
207
234
|
status: "supported",
|
|
208
|
-
|
|
235
|
+
surfaceKind: { kind: "shared-via", via: "gemini-cli" },
|
|
236
|
+
schemaLabel: "global Gemini blueprint instructions file",
|
|
209
237
|
path: {
|
|
210
|
-
posix: ["{
|
|
211
|
-
windows: ["{
|
|
238
|
+
posix: ["{home}", ".gemini", "GEMINI.md"],
|
|
239
|
+
windows: ["{home}", ".gemini", "GEMINI.md"],
|
|
212
240
|
},
|
|
213
241
|
},
|
|
214
242
|
agentRulesRepoSupport: {
|
|
215
243
|
status: "supported",
|
|
216
|
-
|
|
244
|
+
surfaceKind: { kind: "shared-via", via: "gemini-cli" },
|
|
245
|
+
schemaLabel: "repo-local GEMINI.md",
|
|
217
246
|
path: {
|
|
218
|
-
posix: ["{repo}", ".
|
|
219
|
-
windows: ["{repo}", ".
|
|
247
|
+
posix: ["{repo}", "GEMINI.md"],
|
|
248
|
+
windows: ["{repo}", "GEMINI.md"],
|
|
220
249
|
},
|
|
221
250
|
},
|
|
222
251
|
permissionsSupport: {
|
|
@@ -232,6 +261,12 @@ export const AGENT_REGISTRY = [
|
|
|
232
261
|
windows: ["{repo}", ".agents", "rules", "{name}.md"],
|
|
233
262
|
},
|
|
234
263
|
},
|
|
264
|
+
agentRulesWorkspaceSupport: {
|
|
265
|
+
status: "unsupported",
|
|
266
|
+
schemaLabel: "workspace-local instruction surface",
|
|
267
|
+
reason: "Antigravity is natively repo-local and does not expose a separate workspace-local instruction surface",
|
|
268
|
+
},
|
|
269
|
+
instructionFrontmatterRequired: true,
|
|
235
270
|
},
|
|
236
271
|
{
|
|
237
272
|
id: "opencode",
|
|
@@ -290,6 +325,11 @@ export const AGENT_REGISTRY = [
|
|
|
290
325
|
windows: ["{repo}", ".opencode", "agents", "{name}.md"],
|
|
291
326
|
},
|
|
292
327
|
},
|
|
328
|
+
agentRulesWorkspaceSupport: {
|
|
329
|
+
status: "unsupported",
|
|
330
|
+
schemaLabel: "workspace-local AGENTS.md",
|
|
331
|
+
reason: "OpenCode does not expose a documented workspace-local instruction surface distinct from repo-local AGENTS.md",
|
|
332
|
+
},
|
|
293
333
|
},
|
|
294
334
|
{
|
|
295
335
|
id: "github-copilot",
|
|
@@ -298,6 +338,7 @@ export const AGENT_REGISTRY = [
|
|
|
298
338
|
// from `.claude/skills/` (the same path used by claude-code). Deploying
|
|
299
339
|
// via the `claude-code` skills target automatically covers Copilot — no
|
|
300
340
|
// separate `~/.copilot/skills/` path is needed or maintained.
|
|
341
|
+
skillsSurfaceKind: { kind: "shared-via", via: "claude-code" },
|
|
301
342
|
detectPaths: {
|
|
302
343
|
posix: ["{home}", ".copilot"],
|
|
303
344
|
windows: ["{home}", ".copilot"],
|
|
@@ -314,15 +355,49 @@ export const AGENT_REGISTRY = [
|
|
|
314
355
|
plannedSurface: "devcontainer (.devcontainer/devcontainer.json) and agent-frontmatter (.github/agents/*.agent.md)",
|
|
315
356
|
reason: "GitHub Copilot MCP support will be implemented via repo-scoped devcontainer features and agent-frontmatter mappings — surfaces that are genuinely Copilot-specific and not covered by other agent targets",
|
|
316
357
|
},
|
|
358
|
+
// GitHub Copilot reads Claude-native instruction files (CLAUDE.md) without
|
|
359
|
+
// a separate deploy action. These surfaces are marked shared-via claude-code
|
|
360
|
+
// with requiresPrimary: true so deploy skips emitting a separate action
|
|
361
|
+
// when claude-code is also targeted, and emits a guidance warning when it
|
|
362
|
+
// is not (copilot cannot write to these surfaces independently).
|
|
317
363
|
agentRulesSupport: {
|
|
318
|
-
status: "
|
|
364
|
+
status: "supported",
|
|
365
|
+
surfaceKind: {
|
|
366
|
+
kind: "shared-via",
|
|
367
|
+
via: "claude-code",
|
|
368
|
+
requiresPrimary: true,
|
|
369
|
+
},
|
|
319
370
|
schemaLabel: "Claude-native shared instructions",
|
|
320
|
-
|
|
371
|
+
path: {
|
|
372
|
+
posix: ["{home}", ".claude", "CLAUDE.md"],
|
|
373
|
+
windows: ["{home}", ".claude", "CLAUDE.md"],
|
|
374
|
+
},
|
|
321
375
|
},
|
|
322
376
|
agentRulesRepoSupport: {
|
|
323
|
-
status: "
|
|
377
|
+
status: "supported",
|
|
378
|
+
surfaceKind: {
|
|
379
|
+
kind: "shared-via",
|
|
380
|
+
via: "claude-code",
|
|
381
|
+
requiresPrimary: true,
|
|
382
|
+
},
|
|
324
383
|
schemaLabel: "repo-local CLAUDE.md",
|
|
325
|
-
|
|
384
|
+
path: {
|
|
385
|
+
posix: ["{repo}", "CLAUDE.md"],
|
|
386
|
+
windows: ["{repo}", "CLAUDE.md"],
|
|
387
|
+
},
|
|
388
|
+
},
|
|
389
|
+
agentRulesWorkspaceSupport: {
|
|
390
|
+
status: "supported",
|
|
391
|
+
surfaceKind: {
|
|
392
|
+
kind: "shared-via",
|
|
393
|
+
via: "claude-code",
|
|
394
|
+
requiresPrimary: true,
|
|
395
|
+
},
|
|
396
|
+
schemaLabel: "workspace-local CLAUDE.md",
|
|
397
|
+
path: {
|
|
398
|
+
posix: ["{workspace}", "CLAUDE.md"],
|
|
399
|
+
windows: ["{workspace}", "CLAUDE.md"],
|
|
400
|
+
},
|
|
326
401
|
},
|
|
327
402
|
permissionsSupport: {
|
|
328
403
|
status: "unsupported",
|
|
@@ -338,6 +413,8 @@ export const AGENT_REGISTRY = [
|
|
|
338
413
|
},
|
|
339
414
|
},
|
|
340
415
|
policyNote: "Organization policies may override locally deployed configuration. Verify with your GitHub org admin if deployed skills or rules are not active.",
|
|
416
|
+
instructionFrontmatterRequired: true,
|
|
417
|
+
enterprisePolicyDetection: true,
|
|
341
418
|
},
|
|
342
419
|
];
|
|
343
420
|
export const AGENT_REGISTRY_BY_ID = Object.fromEntries(AGENT_REGISTRY.map((a) => [a.id, a]));
|
|
@@ -16,5 +16,5 @@ export interface AgentDefinitionsAdapterResult {
|
|
|
16
16
|
* Target paths use the `{repo}` placeholder so definitions land in the
|
|
17
17
|
* repository being deployed, not the user's home directory.
|
|
18
18
|
*/
|
|
19
|
-
export declare function compileAgentDefinitionActions(entry: AgentDefinitionEntry, sourceDir: string, resolvedSourceDir: string, realRoot: string, detectedAgents: AgentId[], home: string, repo?: string): Promise<AgentDefinitionsAdapterResult>;
|
|
20
|
-
export declare function compileAgentDefinitionReverts(entry: AgentDefinitionEntry, agentFilter: AgentId[] | null, home: string, repo?: string): FileWriteRevertAction[];
|
|
19
|
+
export declare function compileAgentDefinitionActions(entry: AgentDefinitionEntry, sourceDir: string, resolvedSourceDir: string, realRoot: string, detectedAgents: AgentId[], home: string, repo?: string, workspace?: string): Promise<AgentDefinitionsAdapterResult>;
|
|
20
|
+
export declare function compileAgentDefinitionReverts(entry: AgentDefinitionEntry, agentFilter: AgentId[] | null, home: string, repo?: string, workspace?: string): FileWriteRevertAction[];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { AGENT_REGISTRY_BY_ID } from "../../config/agents.js";
|
|
3
3
|
import { getPlatformKey, resolvePlaceholders } from "../resolve.js";
|
|
4
|
-
import { validateAgentRuleMarkdownPath, validateSourceFile, validateSourcePath, } from "../validation.js";
|
|
4
|
+
import { validateAgentRuleMarkdownPath, validateInstructionFileRequirements, validateSourceFile, validateSourcePath, } from "../validation.js";
|
|
5
5
|
/**
|
|
6
6
|
* Compiles deploy actions for agentDefinitions manifest entries.
|
|
7
7
|
*
|
|
@@ -14,7 +14,7 @@ import { validateAgentRuleMarkdownPath, validateSourceFile, validateSourcePath,
|
|
|
14
14
|
* Target paths use the `{repo}` placeholder so definitions land in the
|
|
15
15
|
* repository being deployed, not the user's home directory.
|
|
16
16
|
*/
|
|
17
|
-
export async function compileAgentDefinitionActions(entry, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo) {
|
|
17
|
+
export async function compileAgentDefinitionActions(entry, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo, workspace) {
|
|
18
18
|
const actions = [];
|
|
19
19
|
const warnings = [];
|
|
20
20
|
const platform = getPlatformKey();
|
|
@@ -43,7 +43,7 @@ export async function compileAgentDefinitionActions(entry, sourceDir, resolvedSo
|
|
|
43
43
|
supportedTargets.push({
|
|
44
44
|
agentId,
|
|
45
45
|
confidence: agent.provenance.agentDefinitions ?? "provisional",
|
|
46
|
-
target: resolvePlaceholders(support.path[platform], entry.name, home, repo),
|
|
46
|
+
target: resolvePlaceholders(support.path[platform], entry.name, home, repo, workspace),
|
|
47
47
|
});
|
|
48
48
|
}
|
|
49
49
|
if (supportedTargets.length === 0) {
|
|
@@ -55,6 +55,7 @@ export async function compileAgentDefinitionActions(entry, sourceDir, resolvedSo
|
|
|
55
55
|
await validateSourceFile(source, entry.path);
|
|
56
56
|
for (const target of supportedTargets) {
|
|
57
57
|
validateAgentRuleMarkdownPath(entry.path, target.agentId);
|
|
58
|
+
await validateInstructionFileRequirements(source, entry.path, target.agentId);
|
|
58
59
|
actions.push({
|
|
59
60
|
kind: "file-write",
|
|
60
61
|
skill: entry.name,
|
|
@@ -66,7 +67,7 @@ export async function compileAgentDefinitionActions(entry, sourceDir, resolvedSo
|
|
|
66
67
|
}
|
|
67
68
|
return { actions, warnings };
|
|
68
69
|
}
|
|
69
|
-
export function compileAgentDefinitionReverts(entry, agentFilter, home, repo) {
|
|
70
|
+
export function compileAgentDefinitionReverts(entry, agentFilter, home, repo, workspace) {
|
|
70
71
|
const actions = [];
|
|
71
72
|
const platform = getPlatformKey();
|
|
72
73
|
for (const agentId of entry.agents) {
|
|
@@ -78,7 +79,7 @@ export function compileAgentDefinitionReverts(entry, agentFilter, home, repo) {
|
|
|
78
79
|
support.status === "unsupported" ||
|
|
79
80
|
support.status === "planned")
|
|
80
81
|
continue;
|
|
81
|
-
const target = resolvePlaceholders(support.path[platform], entry.name, home, repo);
|
|
82
|
+
const target = resolvePlaceholders(support.path[platform], entry.name, home, repo, workspace);
|
|
82
83
|
actions.push({
|
|
83
84
|
kind: "file-write",
|
|
84
85
|
skill: entry.name,
|
|
@@ -10,4 +10,4 @@ export interface AdapterResult {
|
|
|
10
10
|
actions: AdapterAction[];
|
|
11
11
|
warnings: PlanWarning[];
|
|
12
12
|
}
|
|
13
|
-
export declare function compileAdapterActions(mcpServers: McpServerEntry[], agentRules: AgentRuleEntry[], permissions: PermissionsEntry[], sourceDir: string, resolvedSourceDir: string, realRoot: string, detectedAgents: AgentId[], home: string, repo?: string, agentDefinitions?: AgentDefinitionEntry[]): Promise<AdapterResult>;
|
|
13
|
+
export declare function compileAdapterActions(mcpServers: McpServerEntry[], agentRules: AgentRuleEntry[], permissions: PermissionsEntry[], sourceDir: string, resolvedSourceDir: string, realRoot: string, detectedAgents: AgentId[], home: string, repo?: string, agentDefinitions?: AgentDefinitionEntry[], workspace?: string): Promise<AdapterResult>;
|
|
@@ -3,16 +3,16 @@ import { compileMcpServerActions, compileMcpServerReverts } from "./mcp.js";
|
|
|
3
3
|
import { compilePermissionsActions, compilePermissionsReverts, } from "./permissions.js";
|
|
4
4
|
import { compileAgentRuleActions, compileAgentRuleReverts } from "./rules.js";
|
|
5
5
|
export { compileAgentDefinitionReverts, compileAgentRuleReverts, compileMcpServerReverts, compilePermissionsReverts, };
|
|
6
|
-
export async function compileAdapterActions(mcpServers, agentRules, permissions, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo, agentDefinitions) {
|
|
6
|
+
export async function compileAdapterActions(mcpServers, agentRules, permissions, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo, agentDefinitions, workspace) {
|
|
7
7
|
const actions = [];
|
|
8
8
|
const warnings = [];
|
|
9
9
|
for (const entry of mcpServers) {
|
|
10
|
-
const r = compileMcpServerActions(entry, detectedAgents, home, repo);
|
|
10
|
+
const r = compileMcpServerActions(entry, detectedAgents, home, repo, workspace);
|
|
11
11
|
actions.push(...r.actions);
|
|
12
12
|
warnings.push(...r.warnings);
|
|
13
13
|
}
|
|
14
14
|
for (const entry of agentRules) {
|
|
15
|
-
const r = await compileAgentRuleActions(entry, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo);
|
|
15
|
+
const r = await compileAgentRuleActions(entry, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo, workspace);
|
|
16
16
|
actions.push(...r.actions);
|
|
17
17
|
warnings.push(...r.warnings);
|
|
18
18
|
}
|
|
@@ -22,7 +22,7 @@ export async function compileAdapterActions(mcpServers, agentRules, permissions,
|
|
|
22
22
|
warnings.push(...r.warnings);
|
|
23
23
|
}
|
|
24
24
|
for (const entry of agentDefinitions ?? []) {
|
|
25
|
-
const r = await compileAgentDefinitionActions(entry, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo);
|
|
25
|
+
const r = await compileAgentDefinitionActions(entry, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo, workspace);
|
|
26
26
|
actions.push(...r.actions);
|
|
27
27
|
warnings.push(...r.warnings);
|
|
28
28
|
}
|
|
@@ -4,5 +4,5 @@ export interface McpAdapterResult {
|
|
|
4
4
|
actions: Array<ConfigPatchDeployAction | TomlPatchDeployAction | FrontmatterEmitDeployAction>;
|
|
5
5
|
warnings: PlanWarning[];
|
|
6
6
|
}
|
|
7
|
-
export declare function compileMcpServerActions(entry: McpServerEntry, detectedAgents: AgentId[], home: string, repo?: string): McpAdapterResult;
|
|
8
|
-
export declare function compileMcpServerReverts(entry: McpServerEntry, agentFilter: AgentId[] | null, home: string, repo?: string): Array<ConfigPatchRevertAction | TomlPatchRevertAction | FrontmatterEmitRevertAction>;
|
|
7
|
+
export declare function compileMcpServerActions(entry: McpServerEntry, detectedAgents: AgentId[], home: string, repo?: string, workspace?: string): McpAdapterResult;
|
|
8
|
+
export declare function compileMcpServerReverts(entry: McpServerEntry, agentFilter: AgentId[] | null, home: string, repo?: string, workspace?: string): Array<ConfigPatchRevertAction | TomlPatchRevertAction | FrontmatterEmitRevertAction>;
|
|
@@ -46,7 +46,7 @@ function buildMcpDeployAction(entry, agentId, resolvedTarget, confidence, mcpPat
|
|
|
46
46
|
confidence,
|
|
47
47
|
};
|
|
48
48
|
}
|
|
49
|
-
export function compileMcpServerActions(entry, detectedAgents, home, repo) {
|
|
49
|
+
export function compileMcpServerActions(entry, detectedAgents, home, repo, workspace) {
|
|
50
50
|
const actions = [];
|
|
51
51
|
const warnings = [];
|
|
52
52
|
const platform = getPlatformKey();
|
|
@@ -70,7 +70,7 @@ export function compileMcpServerActions(entry, detectedAgents, home, repo) {
|
|
|
70
70
|
continue;
|
|
71
71
|
}
|
|
72
72
|
validateMcpServerConfigShape(entry.config, entry.name, agentId);
|
|
73
|
-
const rawTarget = resolvePlaceholders(support.path[platform], entry.name, home, repo);
|
|
73
|
+
const rawTarget = resolvePlaceholders(support.path[platform], entry.name, home, repo, workspace);
|
|
74
74
|
const resolvedTarget = path.resolve(rawTarget);
|
|
75
75
|
const confidence = agent.provenance.mcpConfig ?? "provisional";
|
|
76
76
|
const mcpPatchKey = support.mcpPatchKey ?? "mcpServers";
|
|
@@ -78,7 +78,7 @@ export function compileMcpServerActions(entry, detectedAgents, home, repo) {
|
|
|
78
78
|
}
|
|
79
79
|
return { actions, warnings };
|
|
80
80
|
}
|
|
81
|
-
export function compileMcpServerReverts(entry, agentFilter, home, repo) {
|
|
81
|
+
export function compileMcpServerReverts(entry, agentFilter, home, repo, workspace) {
|
|
82
82
|
const actions = [];
|
|
83
83
|
const platform = getPlatformKey();
|
|
84
84
|
for (const agentId of entry.agents) {
|
|
@@ -90,7 +90,7 @@ export function compileMcpServerReverts(entry, agentFilter, home, repo) {
|
|
|
90
90
|
support.status === "unsupported" ||
|
|
91
91
|
support.status === "planned")
|
|
92
92
|
continue;
|
|
93
|
-
const rawTarget = resolvePlaceholders(support.path[platform], entry.name, home, repo);
|
|
93
|
+
const rawTarget = resolvePlaceholders(support.path[platform], entry.name, home, repo, workspace);
|
|
94
94
|
const target = path.resolve(rawTarget);
|
|
95
95
|
if (isMarkdownTarget(target)) {
|
|
96
96
|
actions.push({
|
|
@@ -4,5 +4,5 @@ export interface RulesAdapterResult {
|
|
|
4
4
|
actions: FileWriteDeployAction[];
|
|
5
5
|
warnings: PlanWarning[];
|
|
6
6
|
}
|
|
7
|
-
export declare function compileAgentRuleActions(entry: AgentRuleEntry, sourceDir: string, resolvedSourceDir: string, realRoot: string, detectedAgents: AgentId[], home: string, repo?: string): Promise<RulesAdapterResult>;
|
|
8
|
-
export declare function compileAgentRuleReverts(entry: AgentRuleEntry, agentFilter: AgentId[] | null, home: string, repo?: string): FileWriteRevertAction[];
|
|
7
|
+
export declare function compileAgentRuleActions(entry: AgentRuleEntry, sourceDir: string, resolvedSourceDir: string, realRoot: string, detectedAgents: AgentId[], home: string, repo?: string, workspace?: string): Promise<RulesAdapterResult>;
|
|
8
|
+
export declare function compileAgentRuleReverts(entry: AgentRuleEntry, agentFilter: AgentId[] | null, home: string, repo?: string, workspace?: string): FileWriteRevertAction[];
|
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { AGENT_REGISTRY_BY_ID } from "../../config/agents.js";
|
|
3
3
|
import { getPlatformKey, resolvePlaceholders } from "../resolve.js";
|
|
4
|
-
import { validateAgentRuleMarkdownPath, validateSourceFile, validateSourcePath, } from "../validation.js";
|
|
4
|
+
import { validateAgentRuleMarkdownPath, validateInstructionFileRequirements, validateSourceFile, validateSourcePath, } from "../validation.js";
|
|
5
5
|
function resolveRulesSupport(agentId, scope) {
|
|
6
6
|
const agent = AGENT_REGISTRY_BY_ID[agentId];
|
|
7
7
|
if (scope === "repo") {
|
|
8
8
|
return agent?.agentRulesRepoSupport ?? agent?.agentRulesSupport;
|
|
9
9
|
}
|
|
10
|
+
if (scope === "workspace") {
|
|
11
|
+
return (agent?.agentRulesWorkspaceSupport ??
|
|
12
|
+
agent?.agentRulesRepoSupport ??
|
|
13
|
+
agent?.agentRulesSupport);
|
|
14
|
+
}
|
|
10
15
|
return agent?.agentRulesSupport;
|
|
11
16
|
}
|
|
12
|
-
function resolveAgentTarget(agentId, entry, home, repo, platform) {
|
|
17
|
+
function resolveAgentTarget(agentId, entry, home, repo, platform, workspace, allTargetAgentIds) {
|
|
13
18
|
const support = resolveRulesSupport(agentId, entry.scope);
|
|
14
19
|
if (!support || support.status === "unsupported") {
|
|
15
20
|
return {
|
|
16
21
|
kind: "confidence",
|
|
17
|
-
message: `agentRules: agent "${agentId}" uses ${support?.schemaLabel ?? "an unsupported instruction schema"} and ${support?.status === "unsupported" ? support.reason : "does not expose a supported rules adapter"} — skipping "${entry.name}"`,
|
|
22
|
+
message: `agentRules: agent "${agentId}" uses ${support?.schemaLabel ?? "an unsupported instruction schema"} (unsupported) and ${support?.status === "unsupported" ? support.reason : "does not expose a supported rules adapter"} — skipping "${entry.name}"`,
|
|
18
23
|
};
|
|
19
24
|
}
|
|
20
25
|
if (support.status === "planned") {
|
|
@@ -23,20 +28,37 @@ function resolveAgentTarget(agentId, entry, home, repo, platform) {
|
|
|
23
28
|
message: `agentRules: agent "${agentId}" rules support is planned via ${support.plannedSurface} — skipping "${entry.name}" until that surface is implemented`,
|
|
24
29
|
};
|
|
25
30
|
}
|
|
31
|
+
// shared-via: when requiresPrimary is set and the primary agent is absent
|
|
32
|
+
// from the target list, emit a guidance warning instead of deploying.
|
|
33
|
+
if (support.surfaceKind?.kind === "shared-via" &&
|
|
34
|
+
support.surfaceKind.requiresPrimary &&
|
|
35
|
+
allTargetAgentIds &&
|
|
36
|
+
!allTargetAgentIds.includes(support.surfaceKind.via)) {
|
|
37
|
+
return {
|
|
38
|
+
kind: "confidence",
|
|
39
|
+
message: `agentRules: agent "${agentId}" reads this surface via "${support.surfaceKind.via}" — add "${support.surfaceKind.via}" to the entry's agents list to deploy to this surface, or deploy via the "${support.surfaceKind.via}" agentRules target instead`,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
26
42
|
if (entry.scope === "repo" && !repo) {
|
|
27
43
|
return {
|
|
28
44
|
kind: "confidence",
|
|
29
45
|
message: `agentRules: scope "repo" requires a repository path but none was resolved — skipping "${entry.name}" for agent "${agentId}"`,
|
|
30
46
|
};
|
|
31
47
|
}
|
|
48
|
+
if (entry.scope === "workspace" && !workspace && !repo) {
|
|
49
|
+
return {
|
|
50
|
+
kind: "confidence",
|
|
51
|
+
message: `agentRules: scope "workspace" requires a workspace or repository path but none was resolved — skipping "${entry.name}" for agent "${agentId}"`,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
32
54
|
const agent = AGENT_REGISTRY_BY_ID[agentId];
|
|
33
55
|
return {
|
|
34
56
|
agentId,
|
|
35
57
|
confidence: agent?.provenance.agentRules ?? "provisional",
|
|
36
|
-
target: resolvePlaceholders(support.path[platform], entry.name, home, repo),
|
|
58
|
+
target: resolvePlaceholders(support.path[platform], entry.name, home, repo, workspace),
|
|
37
59
|
};
|
|
38
60
|
}
|
|
39
|
-
export async function compileAgentRuleActions(entry, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo) {
|
|
61
|
+
export async function compileAgentRuleActions(entry, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo, workspace) {
|
|
40
62
|
const actions = [];
|
|
41
63
|
const warnings = [];
|
|
42
64
|
const platform = getPlatformKey();
|
|
@@ -46,7 +68,7 @@ export async function compileAgentRuleActions(entry, sourceDir, resolvedSourceDi
|
|
|
46
68
|
return { actions, warnings };
|
|
47
69
|
}
|
|
48
70
|
for (const agentId of targetAgents) {
|
|
49
|
-
const result = resolveAgentTarget(agentId, entry, home, repo, platform);
|
|
71
|
+
const result = resolveAgentTarget(agentId, entry, home, repo, platform, workspace, targetAgents);
|
|
50
72
|
if ("kind" in result) {
|
|
51
73
|
warnings.push(result);
|
|
52
74
|
}
|
|
@@ -57,13 +79,34 @@ export async function compileAgentRuleActions(entry, sourceDir, resolvedSourceDi
|
|
|
57
79
|
if (supportedTargets.length === 0) {
|
|
58
80
|
return { actions, warnings };
|
|
59
81
|
}
|
|
82
|
+
// Deduplicate: when a shared-via rider's primary is also in supportedTargets,
|
|
83
|
+
// skip the rider — the primary agent writes the shared surface. As a fallback,
|
|
84
|
+
// also dedup by resolved path so no target file is written twice.
|
|
85
|
+
const seenTargetPaths = new Set();
|
|
86
|
+
const dedupedTargets = [];
|
|
87
|
+
for (const t of supportedTargets) {
|
|
88
|
+
const sup = resolveRulesSupport(t.agentId, entry.scope);
|
|
89
|
+
if (sup?.status === "supported" &&
|
|
90
|
+
sup.surfaceKind?.kind === "shared-via" &&
|
|
91
|
+
supportedTargets.some((o) => o.agentId ===
|
|
92
|
+
sup.surfaceKind.via &&
|
|
93
|
+
o.target === t.target)) {
|
|
94
|
+
// Primary agent is present and writes the same target — skip rider.
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (!seenTargetPaths.has(t.target)) {
|
|
98
|
+
seenTargetPaths.add(t.target);
|
|
99
|
+
dedupedTargets.push(t);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
60
102
|
// Validate the shared source file only when at least one target uses the
|
|
61
103
|
// current rules adapter surface.
|
|
62
104
|
const source = path.resolve(sourceDir, entry.path);
|
|
63
105
|
await validateSourcePath(source, entry.path, resolvedSourceDir, realRoot);
|
|
64
106
|
await validateSourceFile(source, entry.path);
|
|
65
|
-
for (const target of
|
|
107
|
+
for (const target of dedupedTargets) {
|
|
66
108
|
validateAgentRuleMarkdownPath(entry.path, target.agentId);
|
|
109
|
+
await validateInstructionFileRequirements(source, entry.path, target.agentId);
|
|
67
110
|
actions.push({
|
|
68
111
|
kind: "file-write",
|
|
69
112
|
skill: entry.name,
|
|
@@ -75,23 +118,27 @@ export async function compileAgentRuleActions(entry, sourceDir, resolvedSourceDi
|
|
|
75
118
|
}
|
|
76
119
|
return { actions, warnings };
|
|
77
120
|
}
|
|
78
|
-
export function compileAgentRuleReverts(entry, agentFilter, home, repo) {
|
|
121
|
+
export function compileAgentRuleReverts(entry, agentFilter, home, repo, workspace) {
|
|
79
122
|
const actions = [];
|
|
80
123
|
const platform = getPlatformKey();
|
|
124
|
+
const seenRevertTargets = new Set();
|
|
81
125
|
for (const agentId of entry.agents) {
|
|
82
126
|
if (agentFilter && !agentFilter.includes(agentId))
|
|
83
127
|
continue;
|
|
84
|
-
const
|
|
85
|
-
const support = entry.scope === "repo"
|
|
86
|
-
? (agent?.agentRulesRepoSupport ?? agent?.agentRulesSupport)
|
|
87
|
-
: agent?.agentRulesSupport;
|
|
128
|
+
const support = resolveRulesSupport(agentId, entry.scope);
|
|
88
129
|
if (!support ||
|
|
89
130
|
support.status === "unsupported" ||
|
|
90
|
-
support.status === "planned")
|
|
131
|
+
support.status === "planned") {
|
|
91
132
|
continue;
|
|
133
|
+
}
|
|
92
134
|
if (entry.scope === "repo" && !repo)
|
|
93
135
|
continue;
|
|
94
|
-
|
|
136
|
+
if (entry.scope === "workspace" && !workspace && !repo)
|
|
137
|
+
continue;
|
|
138
|
+
const target = resolvePlaceholders(support.path[platform], entry.name, home, repo, workspace);
|
|
139
|
+
if (seenRevertTargets.has(target))
|
|
140
|
+
continue;
|
|
141
|
+
seenRevertTargets.add(target);
|
|
95
142
|
actions.push({
|
|
96
143
|
kind: "file-write",
|
|
97
144
|
skill: entry.name,
|
package/dist/core/deploy.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AgentId, DeployAction, Manifest, PlannedChange, PlanWarning, SkillDirDeployAction } from "../types.ts";
|
|
2
2
|
import { type RegistryPersistence } from "./ownership.ts";
|
|
3
|
-
export declare function planDeploy(manifest: Manifest, sourceDir: string, detectedAgents: AgentId[], home: string): Promise<{
|
|
3
|
+
export declare function planDeploy(manifest: Manifest, sourceDir: string, detectedAgents: AgentId[], home: string, repo?: string, workspace?: string): Promise<{
|
|
4
4
|
actions: DeployAction[];
|
|
5
5
|
warnings: PlanWarning[];
|
|
6
6
|
}>;
|