@kuznai/inception-engine 0.15.0 → 0.17.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 CHANGED
@@ -50,7 +50,9 @@ Managed skills overwrite their previous version. If a target exists but was not
50
50
  | Config patch (JSON merge) | All agents via manifest and CLI | All agents |
51
51
  | 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 |
52
52
  | Global/Repo Rules Files | All agents (antigravity uses repo-local `.agents/rules/`); github-copilot reads CLAUDE.md natively (deploy via claude-code) | All agents |
53
- | `init` manifest generation | Scans `SKILL.md` directories (`skills`), `.md` files with Claude-first agent mapping (`agentRules`), and `mcp-servers.json` (`mcpServers`); emits hints for `files/` and `configs/` directories | N/A |
53
+ | Permissions / Approval Config | claude-code (`~/.claude/settings.json`), codex (`~/.codex/config.toml`); other agents are warned and skipped | claude-code, codex |
54
+ | 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 |
55
+ | `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 |
54
56
 
55
57
  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.
56
58
 
@@ -98,6 +100,25 @@ Create an `inception.json` file at the root of your skills directory:
98
100
  "path": "rules/CLAUDE.md",
99
101
  "agents": ["claude-code"]
100
102
  }
103
+ ],
104
+ "permissions": [
105
+ {
106
+ "name": "safety-defaults",
107
+ "agents": ["claude-code"],
108
+ "config": {
109
+ "permissions": {
110
+ "allow": ["Read", "Glob"],
111
+ "deny": ["Bash(rm:*)"]
112
+ }
113
+ }
114
+ }
115
+ ],
116
+ "agentDefinitions": [
117
+ {
118
+ "name": "code-reviewer",
119
+ "path": "agents/code-reviewer.md",
120
+ "agents": ["claude-code", "opencode", "github-copilot"]
121
+ }
101
122
  ]
102
123
  }
103
124
  ```
@@ -145,6 +166,64 @@ Each **agentRules** entry deploys a Markdown instruction file to an agent's supp
145
166
 
146
167
  Instruction rule deployment is supported for all agents. For most agents, this targets a single global rules file (e.g., `~/.claude/CLAUDE.md` for `claude-code`, `~/.codex/AGENTS.md` for `codex`, `~/.gemini/GEMINI.md` for `gemini-cli`, and `~/.config/opencode/AGENTS.md` for `opencode`). For `antigravity`, inception-engine deploys to repo-local instruction surfaces at `{repo}/.agents/rules/{name}.md`. For `github-copilot`, no separate deployment is needed because Copilot reads `CLAUDE.md` natively — target it via the `claude-code` agentRules entry and it reaches Copilot automatically. Revert removes the deployed rules file.
147
168
 
169
+ Each **permissions** entry deploys execution and safety-oriented configuration to an agent's permission or approval surface:
170
+
171
+ - **name** - Unique identifier (same format as skill names)
172
+ - **agents** - Array of agent IDs to deploy this entry to
173
+ - **config** - Permission config payload; shape is validated per agent (see below)
174
+
175
+ Permission deployment is currently supported for `claude-code` and `codex`. Other agents emit a warning and are skipped.
176
+
177
+ For `claude-code`, the config is merged into `~/.claude/settings.json`. Only the `permissions` key is accepted:
178
+
179
+ ```json
180
+ {
181
+ "name": "safety-defaults",
182
+ "agents": ["claude-code"],
183
+ "config": {
184
+ "permissions": {
185
+ "allow": ["Read", "Glob", "Bash(git:*)"],
186
+ "deny": ["Bash(rm:*)"]
187
+ }
188
+ }
189
+ }
190
+ ```
191
+
192
+ Both `allow` and `deny` are optional string arrays. Tool patterns follow Claude Code's permission glob syntax (e.g., `Bash(git:*)` to allow all git commands).
193
+
194
+ For `codex`, the config is merged into `~/.codex/config.toml`. Only the `approval_policy` key is accepted:
195
+
196
+ ```json
197
+ {
198
+ "name": "codex-approval",
199
+ "agents": ["codex"],
200
+ "config": {
201
+ "approval_policy": "suggest"
202
+ }
203
+ }
204
+ ```
205
+
206
+ Valid `approval_policy` values are `"auto"`, `"manual"`, `"suggest"`, and `"on-failure"`.
207
+
208
+ Revert restores the previous config values using the undo patch recorded at deploy time.
209
+
210
+ Each **agentDefinitions** entry deploys a Markdown agent-definition file to the repo-local agent-definitions directory of each targeted agent:
211
+
212
+ - **name** - Unique identifier (same format as skill names); used as the definition filename
213
+ - **path** - Relative path to the source Markdown file within the repo; must be a `.md` or `.markdown` file
214
+ - **agents** - Array of agent IDs to deploy this definition to
215
+
216
+ Agent-definition deployment is supported for `claude-code`, `gemini-cli`, `antigravity`, `opencode`, and `github-copilot`. For `codex`, inception-engine emits a warning and skips the entry — use `agentRules` to deploy persona instructions to Codex instead.
217
+
218
+ All targets are repo-local (they land inside the repository being deployed, not the user's home directory):
219
+ - **claude-code**: `{repo}/.claude/agents/{name}.md`
220
+ - **gemini-cli**: `{repo}/.gemini/agents/{name}.md`
221
+ - **antigravity**: `{repo}/.agents/rules/{name}.md`
222
+ - **opencode**: `{repo}/.opencode/agents/{name}.md`
223
+ - **github-copilot**: `{repo}/.github/agents/{name}.agent.md` (note the `.agent.md` suffix)
224
+
225
+ Revert removes the deployed agent-definition file.
226
+
148
227
  ## Creating Skills
149
228
 
150
229
  Each skill is a directory containing at minimum a `SKILL.md` file with YAML frontmatter:
@@ -175,12 +254,15 @@ Current `init` behavior:
175
254
  - Supports `--dry-run` so you can inspect the generated manifest before writing it
176
255
  - Discovers agent-rules Markdown files in the root and conventional subdirectories (`rules/`, `instructions/`, `.github/`, `.agents/rules/`), 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
177
256
  - Reads `mcp-servers.json` from the repo root (if present) and generates `mcpServers` entries; invalid entries are warned and skipped
178
- - Emits guidance when a `files/` or `configs/` directory is detected at the repo root
257
+ - Reads `files-manifest.json` from the repo root (if present) and generates `files` entries; invalid entries are warned and skipped
258
+ - Reads `configs-manifest.json` from the repo root (if present) and generates `configs` entries; invalid entries are warned and skipped
259
+ - Reads `agent-definitions-manifest.json` from the repo root (if present) and generates `agentDefinitions` entries; if absent, auto-discovers agent-definition Markdown files from `.claude/agents/`, `.gemini/agents/`, `.agents/rules/`, `.opencode/agents/`, and `.github/agents/`; invalid entries are warned and skipped
260
+ - Emits guidance to create a sidecar manifest when a `files/` or `configs/` directory is detected but the corresponding sidecar file is absent
179
261
 
180
262
  Current `init` limitations:
181
263
 
182
264
  - It does not reconcile generated manifest entries against `SKILL.md` frontmatter values
183
- - `files` and `configs` entries cannot be inferred automatically since deployment targets are system-specific; add them manually after `init`
265
+ - `files` and `configs` target paths are deployment-system-specific and cannot be inferred; they must be provided explicitly in `files-manifest.json` and `configs-manifest.json`
184
266
 
185
267
  ### Repo Conventions Recognized by `init`
186
268
 
@@ -196,6 +278,48 @@ Place a `mcp-servers.json` file at the repo root to have `init` populate the `mc
196
278
  ]
197
279
  ```
198
280
 
281
+ Place a `files-manifest.json` file at the repo root to have `init` populate the `files` section automatically. The file must be a JSON array of file entries using the same schema as the `files` field in `inception.json`:
282
+
283
+ ```json
284
+ [
285
+ {
286
+ "name": "my-settings",
287
+ "path": "files/settings.json",
288
+ "target": "{home}/.claude/settings.json",
289
+ "agents": ["claude-code"]
290
+ }
291
+ ]
292
+ ```
293
+
294
+ Place a `configs-manifest.json` file at the repo root to have `init` populate the `configs` section automatically. The file must be a JSON array of config entries using the same schema as the `configs` field in `inception.json`:
295
+
296
+ ```json
297
+ [
298
+ {
299
+ "name": "enable-feature",
300
+ "target": "{home}/.claude/settings.json",
301
+ "patch": { "someFeature": true },
302
+ "agents": ["claude-code"]
303
+ }
304
+ ]
305
+ ```
306
+
307
+ Invalid entries are warned and skipped; the rest are written into the generated manifest verbatim.
308
+
309
+ Place an `agent-definitions-manifest.json` file at the repo root to have `init` populate the `agentDefinitions` section automatically. The file must be a JSON array of agent-definition entries using the same schema as the `agentDefinitions` field in `inception.json`:
310
+
311
+ ```json
312
+ [
313
+ {
314
+ "name": "code-reviewer",
315
+ "path": "agents/code-reviewer.md",
316
+ "agents": ["claude-code", "opencode", "github-copilot"]
317
+ }
318
+ ]
319
+ ```
320
+
321
+ If no `agent-definitions-manifest.json` is present, `init` auto-discovers agent-definition Markdown files from five conventional subdirectories: `.claude/agents/`, `.gemini/agents/`, `.agents/rules/`, `.opencode/agents/`, and `.github/agents/`. Each discovered file is mapped to the owning agent(s). GitHub Copilot files named `{name}.agent.md` have the `.agent` infix stripped to derive the manifest name (e.g., `foo.agent.md` → name `foo`).
322
+
199
323
  Invalid entries are warned and skipped; the rest are written into the generated manifest verbatim.
200
324
 
201
325
  ## CLI Reference
@@ -17,6 +17,8 @@ export const AGENT_REGISTRY = [
17
17
  detectBinary: "documented",
18
18
  mcpConfig: "documented",
19
19
  agentRules: "documented",
20
+ permissions: "documented",
21
+ agentDefinitions: "documented",
20
22
  },
21
23
  mcpSupport: {
22
24
  status: "supported",
@@ -34,6 +36,22 @@ export const AGENT_REGISTRY = [
34
36
  windows: ["{home}", ".claude", "CLAUDE.md"],
35
37
  },
36
38
  },
39
+ permissionsSupport: {
40
+ status: "supported",
41
+ schemaLabel: "JSON permissions config",
42
+ path: {
43
+ posix: ["{home}", ".claude", "settings.json"],
44
+ windows: ["{home}", ".claude", "settings.json"],
45
+ },
46
+ },
47
+ agentDefinitionsSupport: {
48
+ status: "supported",
49
+ schemaLabel: "repo-local agent definition Markdown file",
50
+ path: {
51
+ posix: ["{repo}", ".claude", "agents", "{name}.md"],
52
+ windows: ["{repo}", ".claude", "agents", "{name}.md"],
53
+ },
54
+ },
37
55
  },
38
56
  {
39
57
  id: "codex",
@@ -52,6 +70,7 @@ export const AGENT_REGISTRY = [
52
70
  detectPaths: "documented",
53
71
  detectBinary: "documented",
54
72
  agentRules: "documented",
73
+ permissions: "documented",
55
74
  },
56
75
  mcpSupport: {
57
76
  status: "supported",
@@ -69,6 +88,19 @@ export const AGENT_REGISTRY = [
69
88
  windows: ["{home}", ".codex", "AGENTS.md"],
70
89
  },
71
90
  },
91
+ permissionsSupport: {
92
+ status: "supported",
93
+ schemaLabel: "TOML approval policy config",
94
+ path: {
95
+ posix: ["{home}", ".codex", "config.toml"],
96
+ windows: ["{home}", ".codex", "config.toml"],
97
+ },
98
+ },
99
+ agentDefinitionsSupport: {
100
+ status: "unsupported",
101
+ schemaLabel: "dedicated agent definition directory",
102
+ 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",
103
+ },
72
104
  },
73
105
  {
74
106
  id: "gemini-cli",
@@ -88,6 +120,7 @@ export const AGENT_REGISTRY = [
88
120
  detectBinary: "documented",
89
121
  mcpConfig: "documented",
90
122
  agentRules: "documented",
123
+ agentDefinitions: "implementation-only",
91
124
  },
92
125
  mcpSupport: {
93
126
  status: "supported",
@@ -105,6 +138,19 @@ export const AGENT_REGISTRY = [
105
138
  windows: ["{home}", ".gemini", "GEMINI.md"],
106
139
  },
107
140
  },
141
+ permissionsSupport: {
142
+ status: "unsupported",
143
+ schemaLabel: "global permissions surface",
144
+ reason: "Gemini CLI does not expose a documented global per-user permission or approval config surface",
145
+ },
146
+ agentDefinitionsSupport: {
147
+ status: "supported",
148
+ schemaLabel: "repo-local agent definition Markdown file",
149
+ path: {
150
+ posix: ["{repo}", ".gemini", "agents", "{name}.md"],
151
+ windows: ["{repo}", ".gemini", "agents", "{name}.md"],
152
+ },
153
+ },
108
154
  },
109
155
  {
110
156
  id: "antigravity",
@@ -122,6 +168,8 @@ export const AGENT_REGISTRY = [
122
168
  skills: "implementation-only",
123
169
  detectPaths: "implementation-only",
124
170
  detectBinary: "provisional",
171
+ agentRules: "documented",
172
+ agentDefinitions: "documented",
125
173
  },
126
174
  mcpSupport: {
127
175
  status: "supported",
@@ -139,6 +187,19 @@ export const AGENT_REGISTRY = [
139
187
  windows: ["{repo}", ".agents", "rules", "{name}.md"],
140
188
  },
141
189
  },
190
+ permissionsSupport: {
191
+ status: "unsupported",
192
+ schemaLabel: "global permissions surface",
193
+ reason: "Antigravity does not expose a documented global per-user permission or approval config surface",
194
+ },
195
+ agentDefinitionsSupport: {
196
+ status: "supported",
197
+ schemaLabel: "repo-local agent definition Markdown file",
198
+ path: {
199
+ posix: ["{repo}", ".agents", "rules", "{name}.md"],
200
+ windows: ["{repo}", ".agents", "rules", "{name}.md"],
201
+ },
202
+ },
142
203
  },
143
204
  {
144
205
  id: "opencode",
@@ -157,6 +218,7 @@ export const AGENT_REGISTRY = [
157
218
  detectPaths: "documented",
158
219
  detectBinary: "documented",
159
220
  agentRules: "documented",
221
+ agentDefinitions: "documented",
160
222
  },
161
223
  mcpSupport: {
162
224
  status: "supported",
@@ -175,35 +237,62 @@ export const AGENT_REGISTRY = [
175
237
  windows: ["{appdata}", "opencode", "AGENTS.md"],
176
238
  },
177
239
  },
240
+ permissionsSupport: {
241
+ status: "unsupported",
242
+ schemaLabel: "global permissions surface",
243
+ reason: "OpenCode does not expose a documented global per-user permission or approval config surface",
244
+ },
245
+ agentDefinitionsSupport: {
246
+ status: "supported",
247
+ schemaLabel: "repo-local agent definition Markdown file",
248
+ path: {
249
+ posix: ["{repo}", ".opencode", "agents", "{name}.md"],
250
+ windows: ["{repo}", ".opencode", "agents", "{name}.md"],
251
+ },
252
+ },
178
253
  },
179
254
  {
180
255
  id: "github-copilot",
181
256
  displayName: "GitHub Copilot",
182
- skills: {
183
- posix: ["{home}", ".copilot", "skills", "{name}"],
184
- windows: ["{home}", ".copilot", "skills", "{name}"],
185
- },
257
+ // No `skills` field: GitHub Copilot natively executes Claude-style skills
258
+ // from `.claude/skills/` (the same path used by claude-code). Deploying
259
+ // via the `claude-code` skills target automatically covers Copilot — no
260
+ // separate `~/.copilot/skills/` path is needed or maintained.
186
261
  detectPaths: {
187
262
  posix: ["{home}", ".copilot"],
188
263
  windows: ["{home}", ".copilot"],
189
264
  },
190
265
  detectBinary: "github-copilot",
191
266
  provenance: {
192
- skills: "documented",
193
267
  detectPaths: "documented",
194
268
  detectBinary: "documented",
269
+ agentDefinitions: "documented",
195
270
  },
196
271
  mcpSupport: {
197
- status: "unsupported",
272
+ status: "planned",
198
273
  schemaLabel: "repo-scoped MCP surfaces",
199
- reason: "GitHub Copilot MCP support depends on repo-scoped files such as devcontainer or agent-frontmatter mappings, which are not translated here",
274
+ plannedSurface: "devcontainer (.devcontainer/devcontainer.json) and agent-frontmatter (.github/agents/*.agent.md)",
275
+ 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",
200
276
  },
201
277
  agentRulesSupport: {
202
278
  status: "unsupported",
203
279
  schemaLabel: "Claude-native shared instructions",
204
280
  reason: 'GitHub Copilot reads CLAUDE.md natively, so deploy via the "claude-code" agentRules target instead of a separate rules surface',
205
281
  },
206
- policyNote: "Organization policies may override locally deployed skills. Verify with your GitHub org admin if deployed skills are not active.",
282
+ permissionsSupport: {
283
+ status: "unsupported",
284
+ schemaLabel: "global permissions surface",
285
+ reason: "GitHub Copilot permissions are managed via organization policy, not a deployable per-user config surface",
286
+ },
287
+ agentDefinitionsSupport: {
288
+ status: "supported",
289
+ schemaLabel: "repo-local agent definition Markdown file",
290
+ path: {
291
+ posix: ["{repo}", ".github", "agents", "{name}.agent.md"],
292
+ windows: ["{repo}", ".github", "agents", "{name}.agent.md"],
293
+ },
294
+ },
295
+ policyNote: "Organization policies may override locally deployed configuration. Verify with your GitHub org admin if deployed skills or rules are not active.",
207
296
  },
208
297
  ];
209
298
  export const AGENT_REGISTRY_BY_ID = Object.fromEntries(AGENT_REGISTRY.map((a) => [a.id, a]));
@@ -42,6 +42,8 @@ function validateManifest(data, filePath) {
42
42
  if (issuePath.length === 1 &&
43
43
  (issuePath[0] === "mcpServers" ||
44
44
  issuePath[0] === "agentRules" ||
45
+ issuePath[0] === "agentDefinitions" ||
46
+ issuePath[0] === "permissions" ||
45
47
  issuePath[0] === "files" ||
46
48
  issuePath[0] === "configs")) {
47
49
  throw new UserError("MANIFEST_INVALID", `${filePath}: "${issuePath[0]}" must be an array`);
@@ -0,0 +1,20 @@
1
+ import type { AgentDefinitionEntry } from "../../schemas/manifest.ts";
2
+ import type { AgentId, FileWriteDeployAction, FileWriteRevertAction, PlanWarning } from "../../types.ts";
3
+ export interface AgentDefinitionsAdapterResult {
4
+ actions: FileWriteDeployAction[];
5
+ warnings: PlanWarning[];
6
+ }
7
+ /**
8
+ * Compiles deploy actions for agentDefinitions manifest entries.
9
+ *
10
+ * Agent definition files are Markdown files (typically with YAML frontmatter)
11
+ * that define custom agents or subagents for a given platform. Unlike
12
+ * agentRules (which target a single shared global file per agent), each
13
+ * definition entry produces a separate file named after the entry in the
14
+ * agent's dedicated agent-definitions directory (repo-local).
15
+ *
16
+ * Target paths use the `{repo}` placeholder so definitions land in the
17
+ * repository being deployed, not the user's home directory.
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[];
@@ -0,0 +1,90 @@
1
+ import path from "node:path";
2
+ import { AGENT_REGISTRY_BY_ID } from "../../config/agents.js";
3
+ import { getPlatformKey, resolvePlaceholders } from "../resolve.js";
4
+ import { validateAgentRuleMarkdownPath, validateSourceFile, validateSourcePath, } from "../validation.js";
5
+ /**
6
+ * Compiles deploy actions for agentDefinitions manifest entries.
7
+ *
8
+ * Agent definition files are Markdown files (typically with YAML frontmatter)
9
+ * that define custom agents or subagents for a given platform. Unlike
10
+ * agentRules (which target a single shared global file per agent), each
11
+ * definition entry produces a separate file named after the entry in the
12
+ * agent's dedicated agent-definitions directory (repo-local).
13
+ *
14
+ * Target paths use the `{repo}` placeholder so definitions land in the
15
+ * repository being deployed, not the user's home directory.
16
+ */
17
+ export async function compileAgentDefinitionActions(entry, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo) {
18
+ const actions = [];
19
+ const warnings = [];
20
+ const platform = getPlatformKey();
21
+ const targetAgents = entry.agents.filter((agentId) => detectedAgents.includes(agentId));
22
+ const supportedTargets = [];
23
+ if (targetAgents.length === 0) {
24
+ return { actions, warnings };
25
+ }
26
+ for (const agentId of targetAgents) {
27
+ const agent = AGENT_REGISTRY_BY_ID[agentId];
28
+ const support = agent?.agentDefinitionsSupport;
29
+ if (!support || support.status === "unsupported") {
30
+ warnings.push({
31
+ kind: "confidence",
32
+ message: `agentDefinitions: agent "${agentId}" uses ${support?.schemaLabel ?? "an unsupported agent-definition schema"} and ${support?.status === "unsupported" ? support.reason : "does not expose a supported agent-definitions adapter"} — skipping "${entry.name}"`,
33
+ });
34
+ continue;
35
+ }
36
+ if (support.status === "planned") {
37
+ warnings.push({
38
+ kind: "confidence",
39
+ message: `agentDefinitions: agent "${agentId}" agent-definitions support is planned via ${support.plannedSurface} — skipping "${entry.name}" until that surface is implemented`,
40
+ });
41
+ continue;
42
+ }
43
+ supportedTargets.push({
44
+ agentId,
45
+ confidence: agent.provenance.agentDefinitions ?? "provisional",
46
+ target: resolvePlaceholders(support.path[platform], entry.name, home, repo),
47
+ });
48
+ }
49
+ if (supportedTargets.length === 0) {
50
+ return { actions, warnings };
51
+ }
52
+ // Validate the shared source file only when at least one target is active.
53
+ const source = path.resolve(sourceDir, entry.path);
54
+ await validateSourcePath(source, entry.path, resolvedSourceDir, realRoot);
55
+ await validateSourceFile(source, entry.path);
56
+ for (const target of supportedTargets) {
57
+ validateAgentRuleMarkdownPath(entry.path, target.agentId);
58
+ actions.push({
59
+ kind: "file-write",
60
+ skill: entry.name,
61
+ agent: target.agentId,
62
+ source,
63
+ target: target.target,
64
+ confidence: target.confidence,
65
+ });
66
+ }
67
+ return { actions, warnings };
68
+ }
69
+ export function compileAgentDefinitionReverts(entry, agentFilter, home, repo) {
70
+ const actions = [];
71
+ const platform = getPlatformKey();
72
+ for (const agentId of entry.agents) {
73
+ if (agentFilter && !agentFilter.includes(agentId))
74
+ continue;
75
+ const agent = AGENT_REGISTRY_BY_ID[agentId];
76
+ const support = agent?.agentDefinitionsSupport;
77
+ if (!support ||
78
+ support.status === "unsupported" ||
79
+ support.status === "planned")
80
+ continue;
81
+ const target = resolvePlaceholders(support.path[platform], entry.name, home, repo);
82
+ actions.push({
83
+ kind: "file-write",
84
+ skill: entry.name,
85
+ agent: agentId,
86
+ target,
87
+ });
88
+ }
89
+ return actions;
90
+ }
@@ -1,11 +1,13 @@
1
- import type { AgentRuleEntry, McpServerEntry } from "../../schemas/manifest.ts";
1
+ import type { AgentDefinitionEntry, AgentRuleEntry, McpServerEntry, PermissionsEntry } from "../../schemas/manifest.ts";
2
2
  import type { AgentId, ConfigPatchDeployAction, FileWriteDeployAction, FrontmatterEmitDeployAction, PlanWarning, TomlPatchDeployAction } from "../../types.ts";
3
+ import { compileAgentDefinitionReverts } from "./agent-definitions.ts";
3
4
  import { compileMcpServerReverts } from "./mcp.ts";
5
+ import { compilePermissionsReverts } from "./permissions.ts";
4
6
  import { compileAgentRuleReverts } from "./rules.ts";
5
- export { compileAgentRuleReverts, compileMcpServerReverts };
7
+ export { compileAgentDefinitionReverts, compileAgentRuleReverts, compileMcpServerReverts, compilePermissionsReverts, };
6
8
  export type AdapterAction = ConfigPatchDeployAction | FileWriteDeployAction | TomlPatchDeployAction | FrontmatterEmitDeployAction;
7
9
  export interface AdapterResult {
8
10
  actions: AdapterAction[];
9
11
  warnings: PlanWarning[];
10
12
  }
11
- export declare function compileAdapterActions(mcpServers: McpServerEntry[], agentRules: AgentRuleEntry[], sourceDir: string, resolvedSourceDir: string, realRoot: string, detectedAgents: AgentId[], home: string, repo?: string): 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[]): Promise<AdapterResult>;
@@ -1,7 +1,9 @@
1
+ import { compileAgentDefinitionActions, compileAgentDefinitionReverts, } from "./agent-definitions.js";
1
2
  import { compileMcpServerActions, compileMcpServerReverts } from "./mcp.js";
3
+ import { compilePermissionsActions, compilePermissionsReverts, } from "./permissions.js";
2
4
  import { compileAgentRuleActions, compileAgentRuleReverts } from "./rules.js";
3
- export { compileAgentRuleReverts, compileMcpServerReverts };
4
- export async function compileAdapterActions(mcpServers, agentRules, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo) {
5
+ export { compileAgentDefinitionReverts, compileAgentRuleReverts, compileMcpServerReverts, compilePermissionsReverts, };
6
+ export async function compileAdapterActions(mcpServers, agentRules, permissions, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo, agentDefinitions) {
5
7
  const actions = [];
6
8
  const warnings = [];
7
9
  for (const entry of mcpServers) {
@@ -14,5 +16,15 @@ export async function compileAdapterActions(mcpServers, agentRules, sourceDir, r
14
16
  actions.push(...r.actions);
15
17
  warnings.push(...r.warnings);
16
18
  }
19
+ for (const entry of permissions) {
20
+ const r = compilePermissionsActions(entry, detectedAgents, home);
21
+ actions.push(...r.actions);
22
+ warnings.push(...r.warnings);
23
+ }
24
+ for (const entry of agentDefinitions ?? []) {
25
+ const r = await compileAgentDefinitionActions(entry, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo);
26
+ actions.push(...r.actions);
27
+ warnings.push(...r.warnings);
28
+ }
17
29
  return { actions, warnings };
18
30
  }
@@ -62,6 +62,13 @@ export function compileMcpServerActions(entry, detectedAgents, home, repo) {
62
62
  });
63
63
  continue;
64
64
  }
65
+ if (support.status === "planned") {
66
+ warnings.push({
67
+ kind: "confidence",
68
+ message: `mcpServers: agent "${agentId}" MCP support is planned via ${support.plannedSurface} — skipping "${entry.name}" until that surface is implemented`,
69
+ });
70
+ continue;
71
+ }
65
72
  validateMcpServerConfigShape(entry.config, entry.name, agentId);
66
73
  const rawTarget = resolvePlaceholders(support.path[platform], entry.name, home, repo);
67
74
  const resolvedTarget = path.resolve(rawTarget);
@@ -79,7 +86,9 @@ export function compileMcpServerReverts(entry, agentFilter, home, repo) {
79
86
  continue;
80
87
  const agent = AGENT_REGISTRY_BY_ID[agentId];
81
88
  const support = agent?.mcpSupport;
82
- if (!support || support.status === "unsupported")
89
+ if (!support ||
90
+ support.status === "unsupported" ||
91
+ support.status === "planned")
83
92
  continue;
84
93
  const rawTarget = resolvePlaceholders(support.path[platform], entry.name, home, repo);
85
94
  const target = path.resolve(rawTarget);
@@ -0,0 +1,8 @@
1
+ import type { PermissionsEntry } from "../../schemas/manifest.ts";
2
+ import type { AgentId, ConfigPatchDeployAction, ConfigPatchRevertAction, PlanWarning, TomlPatchDeployAction, TomlPatchRevertAction } from "../../types.ts";
3
+ export interface PermissionsAdapterResult {
4
+ actions: Array<ConfigPatchDeployAction | TomlPatchDeployAction>;
5
+ warnings: PlanWarning[];
6
+ }
7
+ export declare function compilePermissionsActions(entry: PermissionsEntry, detectedAgents: AgentId[], home: string): PermissionsAdapterResult;
8
+ export declare function compilePermissionsReverts(entry: PermissionsEntry, agentFilter: AgentId[] | null, home: string): Array<ConfigPatchRevertAction | TomlPatchRevertAction>;
@@ -0,0 +1,90 @@
1
+ import path from "node:path";
2
+ import { AGENT_REGISTRY_BY_ID } from "../../config/agents.js";
3
+ import { getPlatformKey, resolvePlaceholders } from "../resolve.js";
4
+ import { validatePermissionsConfigShape } from "../validation.js";
5
+ function isTomlTarget(targetPath) {
6
+ return path.extname(targetPath).toLowerCase() === ".toml";
7
+ }
8
+ export function compilePermissionsActions(entry, detectedAgents, home) {
9
+ const actions = [];
10
+ const warnings = [];
11
+ const platform = getPlatformKey();
12
+ for (const agentId of entry.agents) {
13
+ if (!detectedAgents.includes(agentId))
14
+ continue;
15
+ const agent = AGENT_REGISTRY_BY_ID[agentId];
16
+ const support = agent?.permissionsSupport;
17
+ if (!support || support.status === "unsupported") {
18
+ warnings.push({
19
+ kind: "confidence",
20
+ message: `permissions: agent "${agentId}" ${support?.status === "unsupported" ? support.reason : "does not expose a supported permissions adapter"} — skipping "${entry.name}"`,
21
+ });
22
+ continue;
23
+ }
24
+ if (support.status === "planned") {
25
+ warnings.push({
26
+ kind: "confidence",
27
+ message: `permissions: agent "${agentId}" permissions support is planned via ${support.plannedSurface} — skipping "${entry.name}" until that surface is implemented`,
28
+ });
29
+ continue;
30
+ }
31
+ validatePermissionsConfigShape(entry.config, entry.name, agentId);
32
+ const rawTarget = resolvePlaceholders(support.path[platform], entry.name, home);
33
+ const resolvedTarget = path.resolve(rawTarget);
34
+ const confidence = agent.provenance.permissions ?? "provisional";
35
+ if (isTomlTarget(resolvedTarget)) {
36
+ actions.push({
37
+ kind: "toml-patch",
38
+ skill: entry.name,
39
+ agent: agentId,
40
+ target: resolvedTarget,
41
+ config: entry.config,
42
+ confidence,
43
+ });
44
+ }
45
+ else {
46
+ actions.push({
47
+ kind: "config-patch",
48
+ skill: entry.name,
49
+ agent: agentId,
50
+ target: resolvedTarget,
51
+ patch: entry.config,
52
+ confidence,
53
+ });
54
+ }
55
+ }
56
+ return { actions, warnings };
57
+ }
58
+ export function compilePermissionsReverts(entry, agentFilter, home) {
59
+ const actions = [];
60
+ const platform = getPlatformKey();
61
+ for (const agentId of entry.agents) {
62
+ if (agentFilter && !agentFilter.includes(agentId))
63
+ continue;
64
+ const agent = AGENT_REGISTRY_BY_ID[agentId];
65
+ const support = agent?.permissionsSupport;
66
+ if (!support ||
67
+ support.status === "unsupported" ||
68
+ support.status === "planned")
69
+ continue;
70
+ const rawTarget = resolvePlaceholders(support.path[platform], entry.name, home);
71
+ const target = path.resolve(rawTarget);
72
+ if (isTomlTarget(target)) {
73
+ actions.push({
74
+ kind: "toml-patch",
75
+ skill: entry.name,
76
+ agent: agentId,
77
+ target,
78
+ });
79
+ }
80
+ else {
81
+ actions.push({
82
+ kind: "config-patch",
83
+ skill: entry.name,
84
+ agent: agentId,
85
+ target,
86
+ });
87
+ }
88
+ }
89
+ return actions;
90
+ }