@kuznai/inception-engine 0.22.0 → 0.24.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 +50 -9
- package/dist/src/config/agents.js +39 -0
- package/dist/src/core/adapters/execution-config.d.ts +14 -0
- package/dist/src/core/adapters/execution-config.js +60 -0
- package/dist/src/core/adapters/index.d.ts +4 -3
- package/dist/src/core/adapters/index.js +7 -5
- package/dist/src/core/adapters/rules.js +50 -19
- package/dist/src/core/capabilities.d.ts +1 -1
- package/dist/src/core/capabilities.js +18 -2
- package/dist/src/core/deploy.js +66 -2
- package/dist/src/core/init.js +69 -13
- package/dist/src/core/ownership.d.ts +1 -0
- package/dist/src/core/ownership.js +34 -4
- package/dist/src/core/preflight.js +28 -0
- package/dist/src/core/revert.js +86 -18
- package/dist/src/core/validation.d.ts +1 -1
- package/dist/src/core/validation.js +56 -3
- package/dist/src/schemas/manifest.d.ts +31 -0
- package/dist/src/schemas/manifest.js +39 -3
- package/dist/src/types.d.ts +6 -2
- package/dist/test/helpers/path.d.ts +2 -2
- package/dist/test/helpers/path.js +3 -3
- package/dist/test/os/posix/deploy.test.js +395 -0
- package/dist/test/os/posix/revert.test.js +188 -0
- package/dist/test/os/windows/deploy.test.d.ts +1 -0
- package/dist/test/os/windows/deploy.test.js +238 -0
- package/dist/test/unit/adapters.test.js +402 -2
- package/dist/test/unit/capabilities.test.js +44 -1
- package/dist/test/unit/cli.test.js +162 -0
- package/dist/test/unit/deploy.test.js +88 -647
- package/dist/test/unit/formatters.test.d.ts +1 -0
- package/dist/test/unit/formatters.test.js +74 -0
- package/dist/test/unit/init-fixture.test.js +85 -1
- package/dist/test/unit/manifest.test.js +72 -0
- package/dist/test/unit/ownership.test.js +61 -4
- package/dist/test/unit/preflight.test.js +145 -0
- package/dist/test/unit/resolve.test.js +67 -1
- package/dist/test/unit/revert.test.js +81 -182
- package/package.json +1 -1
- package/dist/test/os/windows/agentRules-integration.test.js +0 -245
- package/dist/test/os/windows/revert-integration.test.js +0 -72
- /package/dist/test/os/{windows/agentRules-integration.test.d.ts → posix/deploy.test.d.ts} +0 -0
- /package/dist/test/os/{windows/revert-integration.test.d.ts → posix/revert.test.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -51,9 +51,10 @@ 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 (`scope: "global"` → `~/.claude.json`; `scope: "repo"` → `{repo}/.claude/mcp.json`; `scope: "workspace"` → `{workspace}/.claude/mcp.json`), gemini-cli, codex, antigravity (`scope: "global"` → `~/.gemini/antigravity/mcp_config.json`; `scope: "repo"` → `{repo}/.agents/rules/{name}.md`), opencode; github-copilot with `scope: "repo"` deploys to `{repo}/.vscode/mcp.json` and `scope: "workspace"` deploys to `{workspace}/.vscode/mcp.json`; github-copilot with `scope: "global"` (default) is unsupported and warns | claude-code, gemini-cli, codex, antigravity, opencode, github-copilot |
|
|
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
|
|
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` (shared-via) and also supports native `scope: "copilot-repo"` (`{repo}/.github/copilot-instructions.md`) and `scope: "copilot-scoped"` (`{repo}/.github/instructions/{name}.instructions.md`) | All supported agents |
|
|
55
55
|
| Permissions / Approval Config | claude-code (`~/.claude/settings.json`), codex (`~/.codex/config.toml`), opencode (`~/.config/opencode/opencode.json` on POSIX, `%APPDATA%\\opencode\\opencode.json` on Windows); other agents are warned and skipped | claude-code, codex, opencode |
|
|
56
56
|
| Execution Hooks | claude-code (`~/.claude/settings.json`), github-copilot (`planned`); other agents are warned and skipped | claude-code |
|
|
57
|
+
| Execution / Safety Config | gemini-cli (`~/.gemini/settings.json`); other agents are warned and skipped | gemini-cli |
|
|
57
58
|
| Agent Definitions | claude-code (`{repo}/.claude/agents/{name}.md`), gemini-cli (`{repo}/.gemini/agents/{name}.md` or `.toml`, plus `scope: "global"` to `~/.gemini/agents/{name}.md` or `.toml`), antigravity (`{repo}/.agents/rules/{name}.md`), opencode (`{repo}/.opencode/agents/{name}.md`, plus `scope: "global"` to the user config dir), github-copilot (`{repo}/.github/copilot/agents/{name}.md`, with migration from legacy `.github/agents/{name}.agent.md`); codex is warned and skipped | All supported agents |
|
|
58
59
|
| `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`); shared surfaces default to the primary deploy target instead of shared riders; emits hints for `files/` and `configs/` directories | N/A |
|
|
59
60
|
| Instruction preflight analysis | Emits capability warnings for implementation-only, planned, unsupported, and shared-through surfaces used by the manifest; 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; emits a `config-authority` warning when Gemini CLI's `settings.json` contains an `instructionFilename` override that differs from the deploy target | N/A |
|
|
@@ -143,14 +144,35 @@ Create an `inception.json` file at the root of your skills directory:
|
|
|
143
144
|
"agents": ["claude-code"],
|
|
144
145
|
"config": {
|
|
145
146
|
"hooks": {
|
|
146
|
-
"
|
|
147
|
+
"PreToolUse": [
|
|
148
|
+
{
|
|
149
|
+
"matcher": "Bash",
|
|
150
|
+
"hooks": [{ "type": "command", "command": "scripts/check-env.sh" }]
|
|
151
|
+
}
|
|
152
|
+
],
|
|
153
|
+
"Stop": [
|
|
154
|
+
{
|
|
155
|
+
"hooks": [{ "type": "command", "command": "scripts/notify.sh" }]
|
|
156
|
+
}
|
|
157
|
+
]
|
|
147
158
|
}
|
|
148
159
|
}
|
|
149
160
|
}
|
|
161
|
+
],
|
|
162
|
+
"executionConfigs": [
|
|
163
|
+
{
|
|
164
|
+
"name": "gemini-safety",
|
|
165
|
+
"agents": ["gemini-cli"],
|
|
166
|
+
"config": {
|
|
167
|
+
"safeMode": true
|
|
168
|
+
}
|
|
169
|
+
}
|
|
150
170
|
]
|
|
151
171
|
}
|
|
152
172
|
```
|
|
153
173
|
|
|
174
|
+
`files` and `configs` are intentionally narrower than the raw target-template syntax might suggest. Arbitrary project-local targets under `{repo}` and `{workspace}` are allowed, but user-profile targets under `{home}`, `{appdata}`, and `{xdg_config}` must resolve to documented agent-owned global surfaces such as `~/.claude/settings.json` or `~/.codex/AGENTS.md`. Manifests cannot target inception-engine's own `~/.inception-engine/` state directory.
|
|
175
|
+
|
|
154
176
|
Each **skill** entry has:
|
|
155
177
|
|
|
156
178
|
- **name** - Unique identifier using letters, digits, dots, underscores, or hyphens; must not start with a dot
|
|
@@ -202,10 +224,12 @@ Each **agentRules** entry deploys a Markdown instruction file to an agent's supp
|
|
|
202
224
|
- **name** - Unique identifier (same format as skill names)
|
|
203
225
|
- **path** - Relative path to the source Markdown file within the repo; supported rules adapters require a `.md` or `.markdown` source path
|
|
204
226
|
- **agents** - Array of agent IDs to deploy this file to
|
|
205
|
-
- **scope** - `"global"` (default), `"repo"`, or `"
|
|
227
|
+
- **scope** - `"global"` (default), `"repo"`, `"workspace"`, `"copilot-repo"`, or `"copilot-scoped"`. Controls which instruction surface is targeted:
|
|
206
228
|
- `"global"` — deploys to the agent's home-directory instruction file when that surface is supported (e.g., `~/.claude/CLAUDE.md` for `claude-code`)
|
|
207
229
|
- `"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`)
|
|
208
230
|
- `"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
|
|
231
|
+
- `"copilot-repo"` — deploys to GitHub Copilot's native repo-level instruction file at `{repo}/.github/copilot-instructions.md` (`github-copilot` only; other agents are warned and skipped)
|
|
232
|
+
- `"copilot-scoped"` — deploys to `{repo}/.github/instructions/{name}.instructions.md` where `{name}` is the manifest entry name (`github-copilot` only; other agents are warned and skipped)
|
|
209
233
|
|
|
210
234
|
Instruction rule deployment is supported for implemented global, repo, and workspace surfaces. The target path depends on the agent and the `scope`:
|
|
211
235
|
|
|
@@ -218,7 +242,13 @@ Instruction rule deployment is supported for implemented global, repo, and works
|
|
|
218
242
|
| `opencode` | `~/.config/opencode/AGENTS.md` | `{repo}/AGENTS.md` | unsupported; warns and skips |
|
|
219
243
|
| `github-copilot` | unsupported / Claude-first | deploy via `claude-code` | unsupported; deploy via `claude-code` with `scope: "workspace"` |
|
|
220
244
|
|
|
221
|
-
|
|
245
|
+
GitHub Copilot also exposes two native instruction surfaces via dedicated scope values:
|
|
246
|
+
|
|
247
|
+
| Agent | `scope: "copilot-repo"` | `scope: "copilot-scoped"` |
|
|
248
|
+
|---|---|---|
|
|
249
|
+
| `github-copilot` | `{repo}/.github/copilot-instructions.md` | `{repo}/.github/instructions/{name}.instructions.md` |
|
|
250
|
+
|
|
251
|
+
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`, the Claude-first path (targeting via `claude-code` agentRules) remains the recommended approach for shared rules; the `copilot-repo` and `copilot-scoped` scopes are for Copilot-specific instructions that should not be shared with other agents. When both are present, preflight emits a precedence warning. Revert removes the deployed rules file.
|
|
222
252
|
|
|
223
253
|
Each **permissions** entry deploys execution and safety-oriented configuration to an agent's permission or approval surface:
|
|
224
254
|
|
|
@@ -269,7 +299,7 @@ Each **hooks** entry deploys lifecycle-binding configurations to an agent's exec
|
|
|
269
299
|
|
|
270
300
|
Hook deployment is currently supported for `claude-code`. For `github-copilot`, it is marked as `planned`. Other agents emit a warning and are skipped.
|
|
271
301
|
|
|
272
|
-
For `claude-code`, the config is merged into `~/.claude/settings.json`. Only the `hooks` key is accepted:
|
|
302
|
+
For `claude-code`, the config is merged into `~/.claude/settings.json`. Only the `hooks` key is accepted. Event names follow Claude Code's settings.json hooks surface (e.g. `PreToolUse`, `PostToolUse`, `Notification`, `Stop`, `SubagentStop`). Each event maps to an array of hook matchers; each matcher has an optional `matcher` string and a required `hooks` array of `{ type: "command", command: string }` objects:
|
|
273
303
|
|
|
274
304
|
```json
|
|
275
305
|
{
|
|
@@ -277,8 +307,17 @@ For `claude-code`, the config is merged into `~/.claude/settings.json`. Only the
|
|
|
277
307
|
"agents": ["claude-code"],
|
|
278
308
|
"config": {
|
|
279
309
|
"hooks": {
|
|
280
|
-
"
|
|
281
|
-
|
|
310
|
+
"PreToolUse": [
|
|
311
|
+
{
|
|
312
|
+
"matcher": "Bash",
|
|
313
|
+
"hooks": [{ "type": "command", "command": "scripts/check-env.sh" }]
|
|
314
|
+
}
|
|
315
|
+
],
|
|
316
|
+
"Stop": [
|
|
317
|
+
{
|
|
318
|
+
"hooks": [{ "type": "command", "command": "scripts/notify.sh" }]
|
|
319
|
+
}
|
|
320
|
+
]
|
|
282
321
|
}
|
|
283
322
|
}
|
|
284
323
|
}
|
|
@@ -341,7 +380,7 @@ Current `init` behavior:
|
|
|
341
380
|
- Applies either the `--agents` list or all currently known agent IDs
|
|
342
381
|
- Refuses to overwrite an existing `inception.json` unless `--force` is provided
|
|
343
382
|
- Supports `--plan` so you can inspect the generated manifest before writing it
|
|
344
|
-
- 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 unsupported agents plus shared-surface riders that should default to their primary deploy target
|
|
383
|
+
- 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` found outside `.github/` maps to `claude-code` (Copilot reads `CLAUDE.md` natively), `.github/copilot-instructions.md` maps to `github-copilot` with `scope: "copilot-repo"`, and `*.instructions.md` files in `.github/instructions/` map to `github-copilot` with `scope: "copilot-scoped"`; the fallback for unrecognized files excludes unsupported agents plus shared-surface riders that should default to their primary deploy target
|
|
345
384
|
- Reads `mcp-servers.json` from the repo root (if present) and generates `mcpServers` entries; invalid entries are warned and skipped
|
|
346
385
|
- Reads `files-manifest.json` from the repo root (if present) and generates `files` entries; invalid entries are warned and skipped
|
|
347
386
|
- Reads `configs-manifest.json` from the repo root (if present) and generates `configs` entries; invalid entries are warned and skipped
|
|
@@ -505,9 +544,11 @@ inception-engine maintains a centralized deployment registry at `~/.inception-en
|
|
|
505
544
|
|
|
506
545
|
- **Strong binding**: Each registry entry binds a specific target path to its skill, agent, and action kind. For `skill-dir` and `file-write`, ownership checks also require the recorded `source` to match before an existing target is treated as managed. For `config-patch` and `frontmatter-emit`, overwrite protection is keyed by target path, kind, skill, and agent; the stored `patch` and `undoPatch` are used for patch-level revert bookkeeping rather than deploy-time identity checks.
|
|
507
546
|
|
|
547
|
+
- **Reserved state**: Manifest-driven deploy and revert actions are not allowed to touch `~/.inception-engine/`, and the registry loader refuses symlinked registry files or directories.
|
|
548
|
+
|
|
508
549
|
- **Atomic redeploy**: When overwriting an existing managed `skill-dir` target, the engine renames the old target to a backup, creates the new deployment, and only removes the backup on success. If the new deployment fails, the backup is restored. `file-write` and `config-patch` deployments write directly to the target without this backup/rollback model.
|
|
509
550
|
|
|
510
|
-
- **Cross-platform**: The registry uses the same resolved home directory as the rest of the tool, including sudo scenarios on POSIX and elevated PowerShell on Windows.
|
|
551
|
+
- **Cross-platform**: The registry uses the same resolved home directory as the rest of the tool, including sudo scenarios on POSIX and elevated PowerShell on Windows. On POSIX, inception-engine keeps the state directory at `0700` and the registry file at `0600`.
|
|
511
552
|
|
|
512
553
|
## Running with Privilege Escalation
|
|
513
554
|
|
|
@@ -185,6 +185,7 @@ export const AGENT_REGISTRY = [
|
|
|
185
185
|
agentRules: "documented",
|
|
186
186
|
hooks: "provisional",
|
|
187
187
|
agentDefinitions: "documented",
|
|
188
|
+
executionConfig: "provisional",
|
|
188
189
|
},
|
|
189
190
|
mcpSupport: {
|
|
190
191
|
status: "supported",
|
|
@@ -256,6 +257,14 @@ export const AGENT_REGISTRY = [
|
|
|
256
257
|
windows: ["{repo}", ".gemini", "agents", "{name}.toml"],
|
|
257
258
|
},
|
|
258
259
|
},
|
|
260
|
+
executionConfigSupport: {
|
|
261
|
+
status: "supported",
|
|
262
|
+
schemaLabel: "Settings execution config",
|
|
263
|
+
path: {
|
|
264
|
+
posix: ["{home}", ".gemini", "settings.json"],
|
|
265
|
+
windows: ["{home}", ".gemini", "settings.json"],
|
|
266
|
+
},
|
|
267
|
+
},
|
|
259
268
|
agentRulesWorkspaceSupport: {
|
|
260
269
|
status: "supported",
|
|
261
270
|
schemaLabel: "workspace-local GEMINI.md",
|
|
@@ -443,6 +452,7 @@ export const AGENT_REGISTRY = [
|
|
|
443
452
|
provenance: {
|
|
444
453
|
detectPaths: "documented",
|
|
445
454
|
detectBinary: "documented",
|
|
455
|
+
agentRules: "documented",
|
|
446
456
|
agentDefinitions: "documented",
|
|
447
457
|
mcpConfig: "documented",
|
|
448
458
|
hooks: "provisional",
|
|
@@ -514,6 +524,35 @@ export const AGENT_REGISTRY = [
|
|
|
514
524
|
windows: ["{workspace}", "CLAUDE.md"],
|
|
515
525
|
},
|
|
516
526
|
},
|
|
527
|
+
// GitHub Copilot native repo-level instruction file. Not shared via
|
|
528
|
+
// CLAUDE.md; this is Copilot's own .github/copilot-instructions.md surface
|
|
529
|
+
// deployed directly without the shared-via deduplication path.
|
|
530
|
+
agentRulesCopilotRepoSupport: {
|
|
531
|
+
status: "supported",
|
|
532
|
+
surfaceKind: { kind: "agent-specific" },
|
|
533
|
+
schemaLabel: "repo-local .github/copilot-instructions.md",
|
|
534
|
+
path: {
|
|
535
|
+
posix: ["{repo}", ".github", "copilot-instructions.md"],
|
|
536
|
+
windows: ["{repo}", ".github", "copilot-instructions.md"],
|
|
537
|
+
},
|
|
538
|
+
},
|
|
539
|
+
// GitHub Copilot scoped instruction files. Each entry deploys to
|
|
540
|
+
// .github/instructions/{name}.instructions.md where {name} comes from
|
|
541
|
+
// the manifest entry name field.
|
|
542
|
+
agentRulesCopilotScopedSupport: {
|
|
543
|
+
status: "supported",
|
|
544
|
+
surfaceKind: { kind: "agent-specific" },
|
|
545
|
+
schemaLabel: "scoped .github/instructions/{name}.instructions.md",
|
|
546
|
+
path: {
|
|
547
|
+
posix: ["{repo}", ".github", "instructions", "{name}.instructions.md"],
|
|
548
|
+
windows: [
|
|
549
|
+
"{repo}",
|
|
550
|
+
".github",
|
|
551
|
+
"instructions",
|
|
552
|
+
"{name}.instructions.md",
|
|
553
|
+
],
|
|
554
|
+
},
|
|
555
|
+
},
|
|
517
556
|
mcpDevcontainerSupport: {
|
|
518
557
|
status: "supported",
|
|
519
558
|
schemaLabel: "devcontainer.json MCP surface",
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ExecutionConfigEntry } from "../../schemas/manifest.ts";
|
|
2
|
+
import type { AgentId, ConfigPatchDeployAction, ConfigPatchRevertAction, PlanWarning } from "../../types.ts";
|
|
3
|
+
export interface ExecutionConfigAdapterResult {
|
|
4
|
+
actions: ConfigPatchDeployAction[];
|
|
5
|
+
warnings: PlanWarning[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Compiles deploy actions for executionConfigs manifest entries.
|
|
9
|
+
*
|
|
10
|
+
* Execution configuration settings (like Gemini CLI's safeMode) are patched
|
|
11
|
+
* directly into the agent's primary settings file using config-patch actions.
|
|
12
|
+
*/
|
|
13
|
+
export declare function compileExecutionConfigActions(entry: ExecutionConfigEntry, detectedAgents: AgentId[], home: string): ExecutionConfigAdapterResult;
|
|
14
|
+
export declare function compileExecutionConfigReverts(entry: ExecutionConfigEntry, agentFilter: AgentId[] | null, home: string): ConfigPatchRevertAction[];
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { AGENT_REGISTRY_BY_ID } from "../../config/agents.js";
|
|
3
|
+
import { getPlatformKey, resolvePlaceholders } from "../resolve.js";
|
|
4
|
+
/**
|
|
5
|
+
* Compiles deploy actions for executionConfigs manifest entries.
|
|
6
|
+
*
|
|
7
|
+
* Execution configuration settings (like Gemini CLI's safeMode) are patched
|
|
8
|
+
* directly into the agent's primary settings file using config-patch actions.
|
|
9
|
+
*/
|
|
10
|
+
export function compileExecutionConfigActions(entry, detectedAgents, home) {
|
|
11
|
+
const actions = [];
|
|
12
|
+
const warnings = [];
|
|
13
|
+
const platform = getPlatformKey();
|
|
14
|
+
for (const agentId of entry.agents) {
|
|
15
|
+
if (!detectedAgents.includes(agentId))
|
|
16
|
+
continue;
|
|
17
|
+
const agent = AGENT_REGISTRY_BY_ID[agentId];
|
|
18
|
+
if (!agent?.executionConfigSupport ||
|
|
19
|
+
agent.executionConfigSupport.status !== "supported") {
|
|
20
|
+
warnings.push({
|
|
21
|
+
kind: "confidence",
|
|
22
|
+
message: `Agent "${agentId}" does not support modeled execution configuration surfaces — skipping "${entry.name}"`,
|
|
23
|
+
});
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const rawTarget = resolvePlaceholders(agent.executionConfigSupport.path[platform], entry.name, home);
|
|
27
|
+
const target = path.resolve(rawTarget);
|
|
28
|
+
actions.push({
|
|
29
|
+
kind: "config-patch",
|
|
30
|
+
skill: entry.name,
|
|
31
|
+
agent: agentId,
|
|
32
|
+
target,
|
|
33
|
+
patch: entry.config,
|
|
34
|
+
confidence: "provisional",
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return { actions, warnings };
|
|
38
|
+
}
|
|
39
|
+
export function compileExecutionConfigReverts(entry, agentFilter, home) {
|
|
40
|
+
const actions = [];
|
|
41
|
+
const platform = getPlatformKey();
|
|
42
|
+
for (const agentId of entry.agents) {
|
|
43
|
+
if (agentFilter && !agentFilter.includes(agentId))
|
|
44
|
+
continue;
|
|
45
|
+
const agent = AGENT_REGISTRY_BY_ID[agentId];
|
|
46
|
+
if (!agent?.executionConfigSupport ||
|
|
47
|
+
agent.executionConfigSupport.status !== "supported") {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const rawTarget = resolvePlaceholders(agent.executionConfigSupport.path[platform], entry.name, home);
|
|
51
|
+
const target = path.resolve(rawTarget);
|
|
52
|
+
actions.push({
|
|
53
|
+
kind: "config-patch",
|
|
54
|
+
skill: entry.name,
|
|
55
|
+
agent: agentId,
|
|
56
|
+
target,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return actions;
|
|
60
|
+
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import type { AgentDefinitionEntry, AgentRuleEntry, HookEntry, McpServerEntry, PermissionsEntry } from "../../schemas/manifest.ts";
|
|
1
|
+
import type { AgentDefinitionEntry, AgentRuleEntry, ExecutionConfigEntry, HookEntry, McpServerEntry, PermissionsEntry } from "../../schemas/manifest.ts";
|
|
2
2
|
import type { AgentId, ConfigPatchDeployAction, FileWriteDeployAction, FrontmatterEmitDeployAction, PlanWarning, TomlPatchDeployAction } from "../../types.ts";
|
|
3
3
|
import { compileAgentDefinitionReverts } from "./agent-definitions.ts";
|
|
4
|
+
import { compileExecutionConfigReverts } from "./execution-config.ts";
|
|
4
5
|
import { compileHookReverts } from "./hooks.ts";
|
|
5
6
|
import { compileMcpServerReverts } from "./mcp.ts";
|
|
6
7
|
import { compilePermissionsReverts } from "./permissions.ts";
|
|
7
8
|
import { compileAgentRuleReverts } from "./rules.ts";
|
|
8
|
-
export { compileAgentDefinitionReverts, compileAgentRuleReverts, compileHookReverts, compileMcpServerReverts, compilePermissionsReverts, };
|
|
9
|
+
export { compileAgentDefinitionReverts, compileAgentRuleReverts, compileExecutionConfigReverts, compileHookReverts, compileMcpServerReverts, compilePermissionsReverts, };
|
|
9
10
|
export type AdapterAction = ConfigPatchDeployAction | FileWriteDeployAction | TomlPatchDeployAction | FrontmatterEmitDeployAction;
|
|
10
11
|
export interface AdapterResult {
|
|
11
12
|
actions: AdapterAction[];
|
|
12
13
|
warnings: PlanWarning[];
|
|
13
14
|
}
|
|
14
|
-
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, hooks?: HookEntry[]): Promise<AdapterResult>;
|
|
15
|
+
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, hooks?: HookEntry[], executionConfigs?: ExecutionConfigEntry[]): Promise<AdapterResult>;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { compileAgentDefinitionActions, compileAgentDefinitionReverts, } from "./agent-definitions.js";
|
|
2
|
+
import { compileExecutionConfigActions, compileExecutionConfigReverts, } from "./execution-config.js";
|
|
2
3
|
import { compileHookActions, compileHookReverts } from "./hooks.js";
|
|
3
4
|
import { compileMcpServerActions, compileMcpServerReverts } from "./mcp.js";
|
|
4
5
|
import { compilePermissionsActions, compilePermissionsReverts, } from "./permissions.js";
|
|
5
6
|
import { compileAgentRuleActions, compileAgentRuleReverts } from "./rules.js";
|
|
6
|
-
export { compileAgentDefinitionReverts, compileAgentRuleReverts, compileHookReverts, compileMcpServerReverts, compilePermissionsReverts, };
|
|
7
|
+
export { compileAgentDefinitionReverts, compileAgentRuleReverts, compileExecutionConfigReverts, compileHookReverts, compileMcpServerReverts, compilePermissionsReverts, };
|
|
7
8
|
async function compileAll(entries, fn) {
|
|
8
9
|
const results = await Promise.all(entries.map(fn));
|
|
9
10
|
return {
|
|
@@ -11,17 +12,18 @@ async function compileAll(entries, fn) {
|
|
|
11
12
|
warnings: results.flatMap((r) => r.warnings),
|
|
12
13
|
};
|
|
13
14
|
}
|
|
14
|
-
export async function compileAdapterActions(mcpServers, agentRules, permissions, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo, agentDefinitions, workspace, hooks = []) {
|
|
15
|
+
export async function compileAdapterActions(mcpServers, agentRules, permissions, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo, agentDefinitions, workspace, hooks = [], executionConfigs = []) {
|
|
15
16
|
const actions = [];
|
|
16
17
|
const warnings = [];
|
|
17
|
-
const [mcp, rules, perms, defs, hookResults] = await Promise.all([
|
|
18
|
+
const [mcp, rules, perms, defs, hookResults, execResults] = await Promise.all([
|
|
18
19
|
compileAll(mcpServers, (entry) => compileMcpServerActions(entry, detectedAgents, home, repo, workspace)),
|
|
19
20
|
compileAll(agentRules, (entry) => compileAgentRuleActions(entry, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo, workspace)),
|
|
20
21
|
compileAll(permissions, (entry) => compilePermissionsActions(entry, detectedAgents, home)),
|
|
21
22
|
compileAll(agentDefinitions ?? [], (entry) => compileAgentDefinitionActions(entry, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo, workspace)),
|
|
22
23
|
compileAll(hooks, (entry) => compileHookActions(entry, detectedAgents, home)),
|
|
24
|
+
compileAll(executionConfigs, (entry) => compileExecutionConfigActions(entry, detectedAgents, home)),
|
|
23
25
|
]);
|
|
24
|
-
actions.push(...mcp.actions, ...rules.actions, ...perms.actions, ...defs.actions, ...hookResults.actions);
|
|
25
|
-
warnings.push(...mcp.warnings, ...rules.warnings, ...perms.warnings, ...defs.warnings, ...hookResults.warnings);
|
|
26
|
+
actions.push(...mcp.actions, ...rules.actions, ...perms.actions, ...defs.actions, ...hookResults.actions, ...execResults.actions);
|
|
27
|
+
warnings.push(...mcp.warnings, ...rules.warnings, ...perms.warnings, ...defs.warnings, ...hookResults.warnings, ...execResults.warnings);
|
|
26
28
|
return { actions, warnings };
|
|
27
29
|
}
|
|
@@ -2,6 +2,37 @@ import path from "node:path";
|
|
|
2
2
|
import { planCapabilityForDeploy, resolveCapabilitySurface, } from "../capabilities.js";
|
|
3
3
|
import { getPlatformKey, resolvePlaceholders } from "../resolve.js";
|
|
4
4
|
import { validateAgentRuleMarkdownPath, validateInstructionFileRequirements, validateSourceFile, validateSourcePath, } from "../validation.js";
|
|
5
|
+
function requiresRepoPath(scope) {
|
|
6
|
+
return (scope === "repo" || scope === "copilot-repo" || scope === "copilot-scoped");
|
|
7
|
+
}
|
|
8
|
+
function deduplicateTargets(supportedTargets, scope) {
|
|
9
|
+
const seenTargetPaths = new Set();
|
|
10
|
+
const dedupedTargets = [];
|
|
11
|
+
for (const t of supportedTargets) {
|
|
12
|
+
const surface = resolveCapabilitySurface(t.agentId, "agentRules", scope);
|
|
13
|
+
if (surface.surfaceKind === "shared-via" &&
|
|
14
|
+
surface.sharedVia &&
|
|
15
|
+
supportedTargets.some((o) => o.agentId === surface.sharedVia && o.target === t.target)) {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (!seenTargetPaths.has(t.target)) {
|
|
19
|
+
seenTargetPaths.add(t.target);
|
|
20
|
+
dedupedTargets.push(t);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return dedupedTargets;
|
|
24
|
+
}
|
|
25
|
+
function injectTargetDir(pathSegments, targetDir) {
|
|
26
|
+
if (!targetDir)
|
|
27
|
+
return pathSegments;
|
|
28
|
+
const placeholderIndex = pathSegments.findIndex((seg) => seg === "{repo}" || seg === "{workspace}");
|
|
29
|
+
if (placeholderIndex === -1)
|
|
30
|
+
return pathSegments;
|
|
31
|
+
const dirSegments = targetDir.split(/[\\/]+/).filter(Boolean);
|
|
32
|
+
const result = [...pathSegments];
|
|
33
|
+
result.splice(placeholderIndex + 1, 0, ...dirSegments);
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
5
36
|
function resolveAgentTarget(agentId, entry, home, repo, platform, workspace, allTargetAgentIds) {
|
|
6
37
|
const plan = planCapabilityForDeploy({
|
|
7
38
|
agentId,
|
|
@@ -28,10 +59,17 @@ function resolveAgentTarget(agentId, entry, home, repo, platform, workspace, all
|
|
|
28
59
|
message: `agentRules: scope "workspace" requires a workspace or repository path but none was resolved — skipping "${entry.name}" for agent "${agentId}"`,
|
|
29
60
|
};
|
|
30
61
|
}
|
|
62
|
+
if ((entry.scope === "copilot-repo" || entry.scope === "copilot-scoped") &&
|
|
63
|
+
!repo) {
|
|
64
|
+
return {
|
|
65
|
+
kind: "confidence",
|
|
66
|
+
message: `agentRules: scope "${entry.scope}" requires a repository path but none was resolved — skipping "${entry.name}" for agent "${agentId}"`,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
31
69
|
return {
|
|
32
70
|
agentId,
|
|
33
71
|
confidence: plan.confidence,
|
|
34
|
-
target: resolvePlaceholders(support?.path[platform] ?? [], entry.name, home, repo, workspace),
|
|
72
|
+
target: resolvePlaceholders(injectTargetDir(support?.path[platform] ?? [], entry.targetDir), entry.name, home, repo, workspace),
|
|
35
73
|
};
|
|
36
74
|
}
|
|
37
75
|
export async function compileAgentRuleActions(entry, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo, workspace) {
|
|
@@ -61,29 +99,22 @@ export async function compileAgentRuleActions(entry, sourceDir, resolvedSourceDi
|
|
|
61
99
|
// Deduplicate: when a shared-via rider's primary is also in supportedTargets,
|
|
62
100
|
// skip the rider — the primary agent writes the shared surface. As a fallback,
|
|
63
101
|
// also dedup by resolved path so no target file is written twice.
|
|
64
|
-
const
|
|
65
|
-
const dedupedTargets = [];
|
|
66
|
-
for (const t of supportedTargets) {
|
|
67
|
-
const surface = resolveCapabilitySurface(t.agentId, "agentRules", entry.scope);
|
|
68
|
-
if (surface.surfaceKind === "shared-via" &&
|
|
69
|
-
surface.sharedVia &&
|
|
70
|
-
supportedTargets.some((o) => o.agentId === surface.sharedVia && o.target === t.target)) {
|
|
71
|
-
// Primary agent is present and writes the same target — skip rider.
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
if (!seenTargetPaths.has(t.target)) {
|
|
75
|
-
seenTargetPaths.add(t.target);
|
|
76
|
-
dedupedTargets.push(t);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
102
|
+
const dedupedTargets = deduplicateTargets(supportedTargets, entry.scope);
|
|
79
103
|
// Validate the shared source file only when at least one target uses the
|
|
80
104
|
// current rules adapter surface.
|
|
81
105
|
const source = path.resolve(sourceDir, entry.path);
|
|
82
106
|
await validateSourcePath(source, entry.path, resolvedSourceDir, realRoot);
|
|
83
107
|
await validateSourceFile(source, entry.path);
|
|
108
|
+
// Native Copilot instruction files (.github/copilot-instructions.md and
|
|
109
|
+
// .github/instructions/*.instructions.md) are plain markdown and do not
|
|
110
|
+
// require agent-definition-style frontmatter (tools/instructions keys).
|
|
111
|
+
// Skip the instructionFrontmatterRequired check for these scopes.
|
|
112
|
+
const skipFrontmatterValidation = entry.scope === "copilot-repo" || entry.scope === "copilot-scoped";
|
|
84
113
|
for (const target of dedupedTargets) {
|
|
85
114
|
validateAgentRuleMarkdownPath(entry.path, target.agentId);
|
|
86
|
-
|
|
115
|
+
if (!skipFrontmatterValidation) {
|
|
116
|
+
await validateInstructionFileRequirements(source, entry.path, target.agentId);
|
|
117
|
+
}
|
|
87
118
|
actions.push({
|
|
88
119
|
kind: "file-write",
|
|
89
120
|
skill: entry.name,
|
|
@@ -107,11 +138,11 @@ export function compileAgentRuleReverts(entry, agentFilter, home, repo, workspac
|
|
|
107
138
|
if (surface.supportStatus !== "supported" || !support) {
|
|
108
139
|
continue;
|
|
109
140
|
}
|
|
110
|
-
if (entry.scope
|
|
141
|
+
if (requiresRepoPath(entry.scope) && !repo)
|
|
111
142
|
continue;
|
|
112
143
|
if (entry.scope === "workspace" && !workspace && !repo)
|
|
113
144
|
continue;
|
|
114
|
-
const target = resolvePlaceholders(support.path[platform], entry.name, home, repo, workspace);
|
|
145
|
+
const target = resolvePlaceholders(injectTargetDir(support.path[platform], entry.targetDir), entry.name, home, repo, workspace);
|
|
115
146
|
if (seenRevertTargets.has(target))
|
|
116
147
|
continue;
|
|
117
148
|
seenRevertTargets.add(target);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AgentId, AgentSurfaceSupport, CapabilityKind, Confidence, PlanWarning, SupportedAgentSurface } from "../types.ts";
|
|
2
|
-
type CapabilityScope = "global" | "repo" | "workspace" | "devcontainer";
|
|
2
|
+
type CapabilityScope = "global" | "repo" | "workspace" | "devcontainer" | "copilot-repo" | "copilot-scoped";
|
|
3
3
|
export interface ResolvedCapabilitySurface {
|
|
4
4
|
agentId: AgentId;
|
|
5
5
|
capability: CapabilityKind;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { AGENT_REGISTRY_BY_ID } from "../config/agents.js";
|
|
2
2
|
function resolveAgentRulesSupport(agentId, scope) {
|
|
3
3
|
const agent = AGENT_REGISTRY_BY_ID[agentId];
|
|
4
|
+
if (scope === "copilot-repo") {
|
|
5
|
+
return agent?.agentRulesCopilotRepoSupport;
|
|
6
|
+
}
|
|
7
|
+
if (scope === "copilot-scoped") {
|
|
8
|
+
return agent?.agentRulesCopilotScopedSupport;
|
|
9
|
+
}
|
|
4
10
|
if (scope === "repo") {
|
|
5
11
|
return agent?.agentRulesRepoSupport ?? agent?.agentRulesSupport;
|
|
6
12
|
}
|
|
@@ -52,6 +58,8 @@ function capabilityLabel(capability) {
|
|
|
52
58
|
return "agentDefinitions";
|
|
53
59
|
case "hooks":
|
|
54
60
|
return "hooks";
|
|
61
|
+
case "executionConfigs":
|
|
62
|
+
return "executionConfigs";
|
|
55
63
|
}
|
|
56
64
|
}
|
|
57
65
|
function capabilitySurfaceLabel(capability) {
|
|
@@ -68,6 +76,8 @@ function capabilitySurfaceLabel(capability) {
|
|
|
68
76
|
return "agent-definitions";
|
|
69
77
|
case "hooks":
|
|
70
78
|
return "hooks";
|
|
79
|
+
case "executionConfigs":
|
|
80
|
+
return "execution-config";
|
|
71
81
|
}
|
|
72
82
|
}
|
|
73
83
|
function resolveSkillsCapability(agentId) {
|
|
@@ -125,9 +135,15 @@ function getSurfaceRecordAndConfidence(agentId, capability, scope) {
|
|
|
125
135
|
confidence: agent.provenance.agentDefinitions,
|
|
126
136
|
};
|
|
127
137
|
}
|
|
138
|
+
if (capability === "hooks") {
|
|
139
|
+
return {
|
|
140
|
+
supportRecord: agent.hooksSupport,
|
|
141
|
+
confidence: agent.provenance.hooks,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
128
144
|
return {
|
|
129
|
-
supportRecord: agent.
|
|
130
|
-
confidence: agent.provenance.
|
|
145
|
+
supportRecord: agent.executionConfigSupport,
|
|
146
|
+
confidence: agent.provenance.executionConfig,
|
|
131
147
|
};
|
|
132
148
|
}
|
|
133
149
|
function resolveUnsupportedSurface(agentId, capability, supportRecord, confidence) {
|
package/dist/src/core/deploy.js
CHANGED
|
@@ -9,7 +9,7 @@ import { compileAdapterActions } from "./adapters/index.js";
|
|
|
9
9
|
import { applyTomlMcpPatch } from "./adapters/toml.js";
|
|
10
10
|
import { planCapabilityForDeploy } from "./capabilities.js";
|
|
11
11
|
import { applyMergePatch, computeUndoPatch, isPlainObject, } from "./merge-patch.js";
|
|
12
|
-
import { lookupDeployment, registerDeployment, verifyDeployment, } from "./ownership.js";
|
|
12
|
+
import { lookupDeployment, registryDirPath, registerDeployment, verifyDeployment, } from "./ownership.js";
|
|
13
13
|
import { getDeployMethod, resolveAgentSkillPath } from "./resolve.js";
|
|
14
14
|
import { resolveTargetTemplate } from "./runtime-paths.js";
|
|
15
15
|
import { sourceAccessError, validateSkillDefinitionFile, validateSourceFile, validateSourcePath, } from "./validation.js";
|
|
@@ -153,6 +153,62 @@ function detectAmbiguities(detectedAgents, manifest) {
|
|
|
153
153
|
}
|
|
154
154
|
return warnings;
|
|
155
155
|
}
|
|
156
|
+
function normalizeTemplatePath(template) {
|
|
157
|
+
return template.replaceAll("\\", "/");
|
|
158
|
+
}
|
|
159
|
+
function isRepoScopedTemplate(template) {
|
|
160
|
+
return template.startsWith("{repo}") || template.startsWith("{workspace}");
|
|
161
|
+
}
|
|
162
|
+
function normalizePathForComparison(candidate) {
|
|
163
|
+
const normalized = path.normalize(candidate);
|
|
164
|
+
return process.platform === "win32" ? normalized.toLowerCase() : normalized;
|
|
165
|
+
}
|
|
166
|
+
function isSameOrDescendantPath(candidate, root) {
|
|
167
|
+
const normalizedCandidate = normalizePathForComparison(candidate);
|
|
168
|
+
const normalizedRoot = normalizePathForComparison(root);
|
|
169
|
+
return (normalizedCandidate === normalizedRoot ||
|
|
170
|
+
normalizedCandidate.startsWith(normalizedRoot + path.sep));
|
|
171
|
+
}
|
|
172
|
+
function collectApprovedGlobalSurfaceTemplates(agentId) {
|
|
173
|
+
const agent = AGENT_REGISTRY_BY_ID[agentId];
|
|
174
|
+
if (!agent)
|
|
175
|
+
return new Set();
|
|
176
|
+
const supports = [
|
|
177
|
+
agent.mcpSupport,
|
|
178
|
+
agent.agentRulesSupport,
|
|
179
|
+
agent.permissionsSupport,
|
|
180
|
+
agent.hooksSupport,
|
|
181
|
+
agent.executionConfigSupport,
|
|
182
|
+
];
|
|
183
|
+
const approved = new Set();
|
|
184
|
+
for (const support of supports) {
|
|
185
|
+
if (!support || support.status !== "supported")
|
|
186
|
+
continue;
|
|
187
|
+
approved.add(normalizeTemplatePath(support.path.posix.join("/")));
|
|
188
|
+
approved.add(normalizeTemplatePath(support.path.windows.join("/")));
|
|
189
|
+
}
|
|
190
|
+
return approved;
|
|
191
|
+
}
|
|
192
|
+
function assertApprovedManagedTargetTemplate(template, targetAgents, kind) {
|
|
193
|
+
if (isRepoScopedTemplate(template))
|
|
194
|
+
return;
|
|
195
|
+
const normalizedTemplate = normalizeTemplatePath(template);
|
|
196
|
+
for (const agentId of targetAgents) {
|
|
197
|
+
const approvedTemplates = collectApprovedGlobalSurfaceTemplates(agentId);
|
|
198
|
+
if (approvedTemplates.has(normalizedTemplate)) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
throw new UserError("DEPLOY_FAILED", `${kind} target "${template}" is not an approved managed surface. ` +
|
|
203
|
+
`Use {repo}/... or {workspace}/... for arbitrary project-local paths, ` +
|
|
204
|
+
`or target a documented agent-owned global config surface.`);
|
|
205
|
+
}
|
|
206
|
+
function assertTargetOutsideReservedEngineState(targetPath, home) {
|
|
207
|
+
const reservedDir = registryDirPath(home);
|
|
208
|
+
if (isSameOrDescendantPath(targetPath, reservedDir)) {
|
|
209
|
+
throw new UserError("DEPLOY_FAILED", `Target "${targetPath}" is inside inception-engine state directory "${reservedDir}" and cannot be managed by manifests`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
156
212
|
function checkAntigravityPathCollisions(manifest) {
|
|
157
213
|
const warnings = [];
|
|
158
214
|
const defNames = new Set((manifest.agentDefinitions ?? [])
|
|
@@ -223,6 +279,7 @@ async function planFileWriteActions(manifest, sourceDir, resolvedSourceDir, real
|
|
|
223
279
|
const targetAgents = fileEntry.agents.filter((agentId) => detectedAgents.includes(agentId));
|
|
224
280
|
if (targetAgents.length === 0)
|
|
225
281
|
return;
|
|
282
|
+
assertApprovedManagedTargetTemplate(fileEntry.target, targetAgents, "files");
|
|
226
283
|
const source = path.resolve(sourceDir, fileEntry.path);
|
|
227
284
|
await validateSourcePath(source, fileEntry.path, resolvedSourceDir, realRoot);
|
|
228
285
|
await validateSourceFile(source, fileEntry.path);
|
|
@@ -245,6 +302,10 @@ async function planFileWriteActions(manifest, sourceDir, resolvedSourceDir, real
|
|
|
245
302
|
function planConfigPatchActions(manifest, detectedAgents, home, repo, workspace) {
|
|
246
303
|
const actions = [];
|
|
247
304
|
for (const configEntry of manifest.configs ?? []) {
|
|
305
|
+
const targetAgents = configEntry.agents.filter((agentId) => detectedAgents.includes(agentId));
|
|
306
|
+
if (targetAgents.length === 0)
|
|
307
|
+
continue;
|
|
308
|
+
assertApprovedManagedTargetTemplate(configEntry.target, targetAgents, "configs");
|
|
248
309
|
for (const agentId of configEntry.agents) {
|
|
249
310
|
if (!detectedAgents.includes(agentId))
|
|
250
311
|
continue;
|
|
@@ -280,7 +341,7 @@ export async function planDeploy(manifest, sourceDir, detectedAgents, home, repo
|
|
|
280
341
|
...(await planFileWriteActions(manifest, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repoDir, workspace)),
|
|
281
342
|
...planConfigPatchActions(manifest, detectedAgents, home, repoDir, workspace),
|
|
282
343
|
];
|
|
283
|
-
const adapterResult = await compileAdapterActions(manifest.mcpServers, manifest.agentRules, manifest.permissions ?? [], sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repoDir, manifest.agentDefinitions ?? [], workspace, manifest.hooks ?? []);
|
|
344
|
+
const adapterResult = await compileAdapterActions(manifest.mcpServers, manifest.agentRules, manifest.permissions ?? [], sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repoDir, manifest.agentDefinitions ?? [], workspace, manifest.hooks ?? [], manifest.executionConfigs ?? []);
|
|
284
345
|
actions.push(...adapterResult.actions);
|
|
285
346
|
const warnings = [
|
|
286
347
|
...skillPlan.warnings,
|
|
@@ -289,6 +350,9 @@ export async function planDeploy(manifest, sourceDir, detectedAgents, home, repo
|
|
|
289
350
|
...detectCollisions(actions),
|
|
290
351
|
...adapterResult.warnings,
|
|
291
352
|
];
|
|
353
|
+
for (const action of actions) {
|
|
354
|
+
assertTargetOutsideReservedEngineState(action.target, home);
|
|
355
|
+
}
|
|
292
356
|
return { actions, warnings };
|
|
293
357
|
}
|
|
294
358
|
export async function executeDeploy(actions, dryRun, verbose, home, deps = {}) {
|