@kuznai/inception-engine 0.11.1 → 0.12.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
@@ -128,17 +128,17 @@ Each **mcpServer** entry registers an MCP server into the agent's config file by
128
128
 
129
129
  - **name** - Unique identifier (same format as skill names); used as the server's key in the config
130
130
  - **agents** - Array of agent IDs to register this server with
131
- - **config** - Raw server descriptor object (e.g. `{ "command": "...", "args": [...] }` for stdio transport). The exact shape is passed through verbatim; agent adapters handle agent-specific requirements.
131
+ - **config** - Raw server descriptor object. For the currently supported JSON-backed adapters, inception-engine requires at least one non-empty `command` or `url` field, validates `args` as an array of strings when present, and validates `env` as a string-to-string object when present. Additional keys are passed through verbatim.
132
132
 
133
- MCP server registration is currently supported for `claude-code` (`~/.claude.json`) and `gemini-cli` (`~/.gemini/settings.json`). Other agents emit a warning and are skipped. Revert removes the registered server entry from the config file.
133
+ MCP server registration is currently supported for `claude-code` (`~/.claude.json`) and `gemini-cli` (`~/.gemini/settings.json`). Other agents emit a schema-aware warning and are skipped when their support would require a non-JSON adapter, such as Codex `config.toml`, Antigravity frontmatter in repo-scoped rules files, OpenCode `opencode.json`, or GitHub Copilot repo-scoped MCP surfaces. Revert removes the registered server entry from the config file.
134
134
 
135
135
  Each **agentRules** entry deploys a Markdown instruction file to an agent's supported global rules file location:
136
136
 
137
137
  - **name** - Unique identifier (same format as skill names)
138
- - **path** - Relative path to the source Markdown file within the repo
138
+ - **path** - Relative path to the source Markdown file within the repo; supported global rules adapters require a `.md` or `.markdown` source path
139
139
  - **agents** - Array of agent IDs to deploy this file to
140
140
 
141
- Global rules-file deployment is currently supported for `claude-code` (`~/.claude/CLAUDE.md`), `codex` (`~/.codex/AGENTS.md`), `gemini-cli` (`~/.gemini/GEMINI.md`), and `opencode` (`~/.config/opencode/AGENTS.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. Other agents emit a warning and are skipped because their instruction surfaces are different, repo-scoped, or not yet implemented. Revert removes the deployed rules file.
141
+ Global rules-file deployment is currently supported for `claude-code` (`~/.claude/CLAUDE.md`), `codex` (`~/.codex/AGENTS.md`), `gemini-cli` (`~/.gemini/GEMINI.md`), and `opencode` (`~/.config/opencode/AGENTS.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. Other agents emit schema-aware warnings and are skipped when their instruction surfaces are repo-scoped, frontmatter-driven, or otherwise not implemented as a single global Markdown file. Revert removes the deployed rules file.
142
142
 
143
143
  ## Creating Skills
144
144
 
@@ -155,7 +155,7 @@ description: What this skill does and when to use it
155
155
  Instructions for the AI agent...
156
156
  ```
157
157
 
158
- The `name` and `description` fields in the frontmatter are used by most agents. The description determines when the agent activates the skill. inception-engine does not currently validate the frontmatter missing or malformed fields may cause the skill to be ignored or misbehave at the agent level.
158
+ The `name` and `description` fields in the frontmatter are used by most agents. The description determines when the agent activates the skill. inception-engine now validates this minimum contract during deploy: `SKILL.md` must start with YAML frontmatter and include non-empty single-line `name` and `description` fields. It still does not attempt full YAML/schema validation beyond that targeted check.
159
159
 
160
160
  ## `init` Command
161
161
 
@@ -171,7 +171,7 @@ Current `init` behavior:
171
171
 
172
172
  Current `init` limitations:
173
173
 
174
- - It does not read or validate YAML frontmatter inside `SKILL.md`
174
+ - It does not reconcile generated manifest entries against `SKILL.md` frontmatter values
175
175
  - It does not infer `files`, `configs`, `mcpServers`, or `agentRules`
176
176
  - It does not reconcile generated output with the longer-term Claude-first portability direction
177
177
 
@@ -18,13 +18,21 @@ export const AGENT_REGISTRY = [
18
18
  mcpConfig: "documented",
19
19
  agentRules: "documented",
20
20
  },
21
- mcpConfigPath: {
22
- posix: ["{home}", ".claude.json"],
23
- windows: ["{home}", ".claude.json"],
24
- },
25
- agentRulesPath: {
26
- posix: ["{home}", ".claude", "CLAUDE.md"],
27
- windows: ["{home}", ".claude", "CLAUDE.md"],
21
+ mcpSupport: {
22
+ status: "supported",
23
+ schemaLabel: "JSON mcpServers config",
24
+ path: {
25
+ posix: ["{home}", ".claude.json"],
26
+ windows: ["{home}", ".claude.json"],
27
+ },
28
+ },
29
+ agentRulesSupport: {
30
+ status: "supported",
31
+ schemaLabel: "global Markdown rules file",
32
+ path: {
33
+ posix: ["{home}", ".claude", "CLAUDE.md"],
34
+ windows: ["{home}", ".claude", "CLAUDE.md"],
35
+ },
28
36
  },
29
37
  },
30
38
  {
@@ -45,10 +53,18 @@ export const AGENT_REGISTRY = [
45
53
  detectBinary: "documented",
46
54
  agentRules: "documented",
47
55
  },
48
- // mcpConfigPath omitted: Codex uses TOML config, not JSON — not supported by config-patch
49
- agentRulesPath: {
50
- posix: ["{home}", ".codex", "AGENTS.md"],
51
- windows: ["{home}", ".codex", "AGENTS.md"],
56
+ mcpSupport: {
57
+ status: "unsupported",
58
+ schemaLabel: "config.toml MCP schema",
59
+ reason: "Codex stores MCP servers in config.toml, so JSON merge-patch deployment is not sufficient yet",
60
+ },
61
+ agentRulesSupport: {
62
+ status: "supported",
63
+ schemaLabel: "global Markdown rules file",
64
+ path: {
65
+ posix: ["{home}", ".codex", "AGENTS.md"],
66
+ windows: ["{home}", ".codex", "AGENTS.md"],
67
+ },
52
68
  },
53
69
  },
54
70
  {
@@ -70,13 +86,21 @@ export const AGENT_REGISTRY = [
70
86
  mcpConfig: "documented",
71
87
  agentRules: "documented",
72
88
  },
73
- mcpConfigPath: {
74
- posix: ["{home}", ".gemini", "settings.json"],
75
- windows: ["{home}", ".gemini", "settings.json"],
76
- },
77
- agentRulesPath: {
78
- posix: ["{home}", ".gemini", "GEMINI.md"],
79
- windows: ["{home}", ".gemini", "GEMINI.md"],
89
+ mcpSupport: {
90
+ status: "supported",
91
+ schemaLabel: "JSON mcpServers config",
92
+ path: {
93
+ posix: ["{home}", ".gemini", "settings.json"],
94
+ windows: ["{home}", ".gemini", "settings.json"],
95
+ },
96
+ },
97
+ agentRulesSupport: {
98
+ status: "supported",
99
+ schemaLabel: "global Markdown rules file",
100
+ path: {
101
+ posix: ["{home}", ".gemini", "GEMINI.md"],
102
+ windows: ["{home}", ".gemini", "GEMINI.md"],
103
+ },
80
104
  },
81
105
  },
82
106
  {
@@ -96,7 +120,16 @@ export const AGENT_REGISTRY = [
96
120
  detectPaths: "implementation-only",
97
121
  detectBinary: "provisional",
98
122
  },
99
- // mcpConfigPath and agentRulesPath omitted: paths not documented strongly enough for this release
123
+ mcpSupport: {
124
+ status: "unsupported",
125
+ schemaLabel: "frontmatter-driven MCP rules",
126
+ reason: "Antigravity MCP support depends on frontmatter inside repo-scoped .agents/rules files, which this release does not translate or validate yet",
127
+ },
128
+ agentRulesSupport: {
129
+ status: "unsupported",
130
+ schemaLabel: "repo-scoped rules files",
131
+ reason: "Antigravity instructions live in repo-scoped .agents/rules files rather than one global Markdown target",
132
+ },
100
133
  },
101
134
  {
102
135
  id: "opencode",
@@ -116,10 +149,18 @@ export const AGENT_REGISTRY = [
116
149
  detectBinary: "documented",
117
150
  agentRules: "documented",
118
151
  },
119
- // mcpConfigPath omitted: OpenCode uses opencode.json (TOML-adjacent format), not plain JSON
120
- agentRulesPath: {
121
- posix: ["{xdg_config}", "opencode", "AGENTS.md"],
122
- windows: ["{appdata}", "opencode", "AGENTS.md"],
152
+ mcpSupport: {
153
+ status: "unsupported",
154
+ schemaLabel: "opencode.json MCP schema",
155
+ reason: "OpenCode keeps MCP config in opencode.json under its own shape, so plain JSON merge-patch support is not implemented here",
156
+ },
157
+ agentRulesSupport: {
158
+ status: "supported",
159
+ schemaLabel: "global Markdown rules file",
160
+ path: {
161
+ posix: ["{xdg_config}", "opencode", "AGENTS.md"],
162
+ windows: ["{appdata}", "opencode", "AGENTS.md"],
163
+ },
123
164
  },
124
165
  },
125
166
  {
@@ -139,10 +180,16 @@ export const AGENT_REGISTRY = [
139
180
  detectPaths: "documented",
140
181
  detectBinary: "documented",
141
182
  },
142
- // agentRulesPath omitted: Copilot reads CLAUDE.md natively (Claude-first portability rule).
143
- // Deploy via the "claude-code" agentRules entry — it reaches Copilot automatically.
144
- // mcpConfigPath omitted: Copilot MCP config surface is not implemented here yet.
145
- claudeNativeInstruction: true,
183
+ mcpSupport: {
184
+ status: "unsupported",
185
+ schemaLabel: "repo-scoped MCP surfaces",
186
+ reason: "GitHub Copilot MCP support depends on repo-scoped files such as devcontainer or agent-frontmatter mappings, which are not translated here",
187
+ },
188
+ agentRulesSupport: {
189
+ status: "unsupported",
190
+ schemaLabel: "Claude-native shared instructions",
191
+ reason: 'GitHub Copilot reads CLAUDE.md natively, so deploy via the "claude-code" agentRules target instead of a separate rules surface',
192
+ },
146
193
  policyNote: "Organization policies may override locally deployed skills. Verify with your GitHub org admin if deployed skills are not active.",
147
194
  },
148
195
  ];
@@ -1,6 +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 { validateMcpServerConfigShape } from "../validation.js";
4
5
  export function compileMcpServerActions(entry, detectedAgents, home) {
5
6
  const actions = [];
6
7
  const warnings = [];
@@ -9,14 +10,16 @@ export function compileMcpServerActions(entry, detectedAgents, home) {
9
10
  if (!detectedAgents.includes(agentId))
10
11
  continue;
11
12
  const agent = AGENT_REGISTRY_BY_ID[agentId];
12
- if (!agent?.mcpConfigPath) {
13
+ const support = agent?.mcpSupport;
14
+ if (!support || support.status === "unsupported") {
13
15
  warnings.push({
14
16
  kind: "confidence",
15
- message: `mcpServers: agent "${agentId}" does not have a documented MCP config path — skipping "${entry.name}"`,
17
+ message: `mcpServers: agent "${agentId}" uses ${support?.schemaLabel ?? "an unsupported MCP schema"} and ${support?.reason ?? "does not expose a supported MCP adapter"} — skipping "${entry.name}"`,
16
18
  });
17
19
  continue;
18
20
  }
19
- const target = resolvePlaceholders(agent.mcpConfigPath[platform], "", home);
21
+ validateMcpServerConfigShape(entry.config, entry.name, agentId);
22
+ const target = resolvePlaceholders(support.path[platform], "", home);
20
23
  // Ensure no stray empty segments collapse the path unexpectedly
21
24
  const resolvedTarget = path.resolve(target);
22
25
  actions.push({
@@ -37,9 +40,10 @@ export function compileMcpServerReverts(entry, agentFilter, home) {
37
40
  if (agentFilter && !agentFilter.includes(agentId))
38
41
  continue;
39
42
  const agent = AGENT_REGISTRY_BY_ID[agentId];
40
- if (!agent?.mcpConfigPath)
43
+ const support = agent?.mcpSupport;
44
+ if (!support || support.status === "unsupported")
41
45
  continue;
42
- const target = path.resolve(resolvePlaceholders(agent.mcpConfigPath[platform], "", home));
46
+ const target = path.resolve(resolvePlaceholders(support.path[platform], "", home));
43
47
  actions.push({
44
48
  kind: "config-patch",
45
49
  skill: entry.name,
@@ -1,43 +1,49 @@
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 { validateSourceFile, validateSourcePath } from "../validation.js";
4
+ import { validateAgentRuleMarkdownPath, validateSourceFile, validateSourcePath, } from "../validation.js";
5
5
  export async function compileAgentRuleActions(entry, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home) {
6
6
  const actions = [];
7
7
  const warnings = [];
8
8
  const platform = getPlatformKey();
9
9
  const targetAgents = entry.agents.filter((agentId) => detectedAgents.includes(agentId));
10
+ const supportedTargets = [];
10
11
  if (targetAgents.length === 0) {
11
12
  return { actions, warnings };
12
13
  }
13
- // Validate the source file once (before iterating agents) since it is shared.
14
- const source = path.resolve(sourceDir, entry.path);
15
- await validateSourcePath(source, entry.path, resolvedSourceDir, realRoot);
16
- await validateSourceFile(source, entry.path);
17
14
  for (const agentId of targetAgents) {
18
15
  const agent = AGENT_REGISTRY_BY_ID[agentId];
19
- if (agent?.claudeNativeInstruction) {
20
- warnings.push({
21
- kind: "confidence",
22
- message: `agentRules: agent "${agentId}" reads CLAUDE.md natively — deploy via "claude-code" target to reach Copilot automatically; no separate deployment needed`,
23
- });
24
- continue;
25
- }
26
- if (!agent?.agentRulesPath) {
16
+ const support = agent?.agentRulesSupport;
17
+ if (!support || support.status === "unsupported") {
27
18
  warnings.push({
28
19
  kind: "confidence",
29
- message: `agentRules: agent "${agentId}" does not have a documented rules file path — skipping "${entry.name}"`,
20
+ message: `agentRules: agent "${agentId}" uses ${support?.schemaLabel ?? "an unsupported instruction schema"} and ${support?.reason ?? "does not expose a supported rules adapter"} — skipping "${entry.name}"`,
30
21
  });
31
22
  continue;
32
23
  }
33
- const target = resolvePlaceholders(agent.agentRulesPath[platform], "", home);
24
+ supportedTargets.push({
25
+ agentId,
26
+ confidence: agent.provenance.agentRules ?? "provisional",
27
+ target: resolvePlaceholders(support.path[platform], "", home),
28
+ });
29
+ }
30
+ if (supportedTargets.length === 0) {
31
+ return { actions, warnings };
32
+ }
33
+ // Validate the shared source file only when at least one target uses the
34
+ // current global-Markdown adapter surface.
35
+ const source = path.resolve(sourceDir, entry.path);
36
+ await validateSourcePath(source, entry.path, resolvedSourceDir, realRoot);
37
+ await validateSourceFile(source, entry.path);
38
+ for (const target of supportedTargets) {
39
+ validateAgentRuleMarkdownPath(entry.path, target.agentId);
34
40
  actions.push({
35
41
  kind: "file-write",
36
42
  skill: entry.name,
37
- agent: agentId,
43
+ agent: target.agentId,
38
44
  source,
39
- target,
40
- confidence: agent.provenance.agentRules ?? "provisional",
45
+ target: target.target,
46
+ confidence: target.confidence,
41
47
  });
42
48
  }
43
49
  return { actions, warnings };
@@ -49,9 +55,10 @@ export function compileAgentRuleReverts(entry, agentFilter, home) {
49
55
  if (agentFilter && !agentFilter.includes(agentId))
50
56
  continue;
51
57
  const agent = AGENT_REGISTRY_BY_ID[agentId];
52
- if (!agent?.agentRulesPath)
58
+ const support = agent?.agentRulesSupport;
59
+ if (!support || support.status === "unsupported")
53
60
  continue;
54
- const target = resolvePlaceholders(agent.agentRulesPath[platform], "", home);
61
+ const target = resolvePlaceholders(support.path[platform], "", home);
55
62
  actions.push({
56
63
  kind: "file-write",
57
64
  skill: entry.name,
@@ -8,7 +8,7 @@ import { compileAdapterActions } from "./adapters/index.js";
8
8
  import { lookupDeployment, registerDeployment, verifyDeployment, } from "./ownership.js";
9
9
  import { getDeployMethod, resolveAgentSkillPath } from "./resolve.js";
10
10
  import { resolveTargetTemplate } from "./runtime-paths.js";
11
- import { sourceAccessError, validateSourceFile, validateSourcePath, } from "./validation.js";
11
+ import { sourceAccessError, validateSkillDefinitionFile, validateSourceFile, validateSourcePath, } from "./validation.js";
12
12
  function isPlainObject(v) {
13
13
  return typeof v === "object" && v !== null && !Array.isArray(v);
14
14
  }
@@ -505,6 +505,7 @@ async function validateSkillContract(source, skillPath) {
505
505
  }
506
506
  throw new UserError("DEPLOY_FAILED", `Skill "${skillPath}" source is missing SKILL.md: ${source}`);
507
507
  }
508
+ await validateSkillDefinitionFile(path.join(source, "SKILL.md"), skillPath);
508
509
  }
509
510
  async function assertTargetAbsent(targetPath) {
510
511
  try {
@@ -1,3 +1,6 @@
1
1
  export declare function sourceAccessError(err: unknown, sourcePath: string): string;
2
2
  export declare function validateSourcePath(source: string, skillPath: string, resolvedSourceDir: string, realRoot: string): Promise<void>;
3
3
  export declare function validateSourceFile(sourcePath: string, manifestPath: string): Promise<void>;
4
+ export declare function validateMcpServerConfigShape(config: Record<string, unknown>, entryName: string, agentId: string): void;
5
+ export declare function validateAgentRuleMarkdownPath(manifestPath: string, agentId: string): void;
6
+ export declare function validateSkillDefinitionFile(sourcePath: string, manifestPath: string): Promise<void>;
@@ -1,4 +1,4 @@
1
- import { lstat, realpath, stat } from "node:fs/promises";
1
+ import { lstat, readFile, realpath, stat } from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { UserError } from "../errors.js";
4
4
  export function sourceAccessError(err, sourcePath) {
@@ -64,3 +64,99 @@ export async function validateSourceFile(sourcePath, manifestPath) {
64
64
  throw new UserError("DEPLOY_FAILED", `Source is not a file: ${manifestPath}`);
65
65
  }
66
66
  }
67
+ function isRecordOfStrings(value) {
68
+ return (typeof value === "object" &&
69
+ value !== null &&
70
+ !Array.isArray(value) &&
71
+ Object.values(value).every((entry) => typeof entry === "string"));
72
+ }
73
+ function validateNonEmptyStringField(value, field, entryName, agentId) {
74
+ if (typeof value !== "string" || value.trim().length === 0) {
75
+ throw new UserError("DEPLOY_FAILED", `mcpServers entry "${entryName}" for agent "${agentId}" must define "${field}" as a non-empty string`);
76
+ }
77
+ }
78
+ export function validateMcpServerConfigShape(config, entryName, agentId) {
79
+ const hasCommand = Object.hasOwn(config, "command");
80
+ const hasUrl = Object.hasOwn(config, "url");
81
+ if (!(hasCommand || hasUrl)) {
82
+ throw new UserError("DEPLOY_FAILED", `mcpServers entry "${entryName}" for agent "${agentId}" must define either a non-empty "command" or "url"`);
83
+ }
84
+ if (hasCommand) {
85
+ validateNonEmptyStringField(config.command, "command", entryName, agentId);
86
+ }
87
+ if (hasUrl) {
88
+ validateNonEmptyStringField(config.url, "url", entryName, agentId);
89
+ }
90
+ if (Object.hasOwn(config, "args") &&
91
+ (!Array.isArray(config.args) ||
92
+ config.args.some((arg) => typeof arg !== "string"))) {
93
+ throw new UserError("DEPLOY_FAILED", `mcpServers entry "${entryName}" for agent "${agentId}" must define "args" as an array of strings when present`);
94
+ }
95
+ if (Object.hasOwn(config, "env") && !isRecordOfStrings(config.env)) {
96
+ throw new UserError("DEPLOY_FAILED", `mcpServers entry "${entryName}" for agent "${agentId}" must define "env" as an object of string values when present`);
97
+ }
98
+ }
99
+ export function validateAgentRuleMarkdownPath(manifestPath, agentId) {
100
+ const extension = path.extname(manifestPath).toLowerCase();
101
+ if (extension !== ".md" && extension !== ".markdown") {
102
+ throw new UserError("DEPLOY_FAILED", `agentRules entry "${manifestPath}" for agent "${agentId}" must point to a Markdown source file`);
103
+ }
104
+ }
105
+ function trimMatchingQuotes(value) {
106
+ if ((value.startsWith('"') && value.endsWith('"')) ||
107
+ (value.startsWith("'") && value.endsWith("'"))) {
108
+ return value.slice(1, -1).trim();
109
+ }
110
+ return value;
111
+ }
112
+ function parseSimpleFrontmatterValue(field, rawValue, manifestPath) {
113
+ const value = trimMatchingQuotes(rawValue.trim());
114
+ if (value.length === 0) {
115
+ throw new UserError("DEPLOY_FAILED", `Skill "${manifestPath}" SKILL.md frontmatter field "${field}" must be a non-empty string`);
116
+ }
117
+ if (rawValue.trim() === "|" || rawValue.trim() === ">") {
118
+ throw new UserError("DEPLOY_FAILED", `Skill "${manifestPath}" SKILL.md frontmatter field "${field}" must be a single-line string`);
119
+ }
120
+ return value;
121
+ }
122
+ export async function validateSkillDefinitionFile(sourcePath, manifestPath) {
123
+ await validateSourceFile(sourcePath, `${manifestPath}/SKILL.md`);
124
+ let raw;
125
+ try {
126
+ raw = await readFile(sourcePath, "utf-8");
127
+ }
128
+ catch (err) {
129
+ throw new UserError("DEPLOY_FAILED", sourceAccessError(err, `${manifestPath}/SKILL.md`));
130
+ }
131
+ const lines = raw.split(/\r?\n/);
132
+ if (lines[0]?.trim() !== "---") {
133
+ throw new UserError("DEPLOY_FAILED", `Skill "${manifestPath}" SKILL.md must start with YAML frontmatter delimited by ---`);
134
+ }
135
+ const closingIndex = lines.findIndex((line, index) => index > 0 && line.trim() === "---");
136
+ if (closingIndex === -1) {
137
+ throw new UserError("DEPLOY_FAILED", `Skill "${manifestPath}" SKILL.md is missing the closing --- frontmatter delimiter`);
138
+ }
139
+ let name = null;
140
+ let description = null;
141
+ for (const line of lines.slice(1, closingIndex)) {
142
+ const trimmed = line.trim();
143
+ if (trimmed.length === 0 || trimmed.startsWith("#"))
144
+ continue;
145
+ const match = /^([A-Za-z0-9_-]+)\s*:\s*(.*)$/.exec(line);
146
+ if (!match)
147
+ continue;
148
+ const [, key, rawValue] = match;
149
+ if (key === "name") {
150
+ name = parseSimpleFrontmatterValue("name", rawValue, manifestPath);
151
+ }
152
+ else if (key === "description") {
153
+ description = parseSimpleFrontmatterValue("description", rawValue, manifestPath);
154
+ }
155
+ }
156
+ if (name === null) {
157
+ throw new UserError("DEPLOY_FAILED", `Skill "${manifestPath}" SKILL.md frontmatter must include a non-empty "name" field`);
158
+ }
159
+ if (description === null) {
160
+ throw new UserError("DEPLOY_FAILED", `Skill "${manifestPath}" SKILL.md frontmatter must include a non-empty "description" field`);
161
+ }
162
+ }
package/dist/types.d.ts CHANGED
@@ -5,6 +5,17 @@ export interface AgentPaths {
5
5
  windows: string[];
6
6
  }
7
7
  export type Confidence = "documented" | "implementation-only" | "provisional";
8
+ export interface SupportedAgentSurface {
9
+ status: "supported";
10
+ path: AgentPaths;
11
+ schemaLabel: string;
12
+ }
13
+ export interface UnsupportedAgentSurface {
14
+ status: "unsupported";
15
+ schemaLabel: string;
16
+ reason: string;
17
+ }
18
+ export type AgentSurfaceSupport = SupportedAgentSurface | UnsupportedAgentSurface;
8
19
  export interface AgentProvenance {
9
20
  skills: Confidence;
10
21
  detectPaths: Confidence;
@@ -19,9 +30,8 @@ export interface AgentConfig {
19
30
  detectPaths: AgentPaths;
20
31
  detectBinary: string | null;
21
32
  provenance: AgentProvenance;
22
- mcpConfigPath?: AgentPaths;
23
- agentRulesPath?: AgentPaths;
24
- claudeNativeInstruction?: true;
33
+ mcpSupport?: AgentSurfaceSupport;
34
+ agentRulesSupport?: AgentSurfaceSupport;
25
35
  policyNote?: string;
26
36
  }
27
37
  export interface PlanWarning {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kuznai/inception-engine",
3
- "version": "0.11.1",
3
+ "version": "0.12.0",
4
4
  "description": "Deploy AI agent skills from a git repo to user home directories",
5
5
  "license": "MIT",
6
6
  "author": "Damian Piątkowski",