@kuznai/inception-engine 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -13
- package/dist/config/agents.js +127 -5
- package/dist/core/adapters/agent-definitions.d.ts +2 -2
- package/dist/core/adapters/agent-definitions.js +6 -5
- package/dist/core/adapters/frontmatter.d.ts +17 -5
- package/dist/core/adapters/frontmatter.js +36 -57
- package/dist/core/adapters/index.d.ts +1 -1
- package/dist/core/adapters/index.js +4 -4
- package/dist/core/adapters/mcp.d.ts +2 -2
- package/dist/core/adapters/mcp.js +4 -4
- package/dist/core/adapters/rules.d.ts +2 -2
- package/dist/core/adapters/rules.js +99 -28
- package/dist/core/deploy.d.ts +1 -1
- package/dist/core/deploy.js +206 -54
- package/dist/core/init.js +129 -49
- package/dist/core/ownership.d.ts +2 -2
- package/dist/core/preflight.d.ts +2 -2
- package/dist/core/preflight.js +142 -2
- package/dist/core/resolve.d.ts +1 -1
- package/dist/core/resolve.js +7 -4
- package/dist/core/revert.js +9 -7
- package/dist/core/runtime-paths.d.ts +2 -1
- package/dist/core/runtime-paths.js +30 -23
- package/dist/core/validation.d.ts +10 -1
- package/dist/core/validation.js +73 -35
- package/dist/formatters.d.ts +5 -0
- package/dist/formatters.js +58 -0
- package/dist/index.js +8 -24
- package/dist/logger.js +22 -21
- package/dist/schemas/manifest.d.ts +10 -0
- package/dist/schemas/manifest.js +10 -3
- package/dist/schemas/registry.d.ts +38 -0
- package/dist/schemas/registry.js +7 -0
- package/dist/types.d.ts +48 -0
- package/package.json +2 -2
package/dist/core/validation.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { lstat, readFile, realpath, stat } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { AGENT_REGISTRY_BY_ID } from "../config/agents.js";
|
|
3
4
|
import { UserError } from "../errors.js";
|
|
5
|
+
import { parseFrontmatterDocument } from "./adapters/frontmatter.js";
|
|
4
6
|
export function sourceAccessError(err, sourcePath) {
|
|
5
7
|
const code = err.code;
|
|
6
8
|
if (code === "ENOENT")
|
|
@@ -147,23 +149,6 @@ export function validateAgentRuleMarkdownPath(manifestPath, agentId) {
|
|
|
147
149
|
throw new UserError("DEPLOY_FAILED", `agentRules entry "${manifestPath}" for agent "${agentId}" must point to a Markdown source file`);
|
|
148
150
|
}
|
|
149
151
|
}
|
|
150
|
-
function trimMatchingQuotes(value) {
|
|
151
|
-
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
152
|
-
(value.startsWith("'") && value.endsWith("'"))) {
|
|
153
|
-
return value.slice(1, -1).trim();
|
|
154
|
-
}
|
|
155
|
-
return value;
|
|
156
|
-
}
|
|
157
|
-
function parseSimpleFrontmatterValue(field, rawValue, manifestPath) {
|
|
158
|
-
const value = trimMatchingQuotes(rawValue.trim());
|
|
159
|
-
if (value.length === 0) {
|
|
160
|
-
throw new UserError("DEPLOY_FAILED", `Skill "${manifestPath}" SKILL.md frontmatter field "${field}" must be a non-empty string`);
|
|
161
|
-
}
|
|
162
|
-
if (rawValue.trim() === "|" || rawValue.trim() === ">") {
|
|
163
|
-
throw new UserError("DEPLOY_FAILED", `Skill "${manifestPath}" SKILL.md frontmatter field "${field}" must be a single-line string`);
|
|
164
|
-
}
|
|
165
|
-
return value;
|
|
166
|
-
}
|
|
167
152
|
export async function validateSkillDefinitionFile(sourcePath, manifestPath) {
|
|
168
153
|
await validateSourceFile(sourcePath, `${manifestPath}/SKILL.md`);
|
|
169
154
|
let raw;
|
|
@@ -181,27 +166,80 @@ export async function validateSkillDefinitionFile(sourcePath, manifestPath) {
|
|
|
181
166
|
if (closingIndex === -1) {
|
|
182
167
|
throw new UserError("DEPLOY_FAILED", `Skill "${manifestPath}" SKILL.md is missing the closing --- frontmatter delimiter`);
|
|
183
168
|
}
|
|
184
|
-
let
|
|
185
|
-
let
|
|
186
|
-
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
169
|
+
let attributes;
|
|
170
|
+
let body;
|
|
171
|
+
try {
|
|
172
|
+
const parsed = parseFrontmatterDocument(raw);
|
|
173
|
+
attributes = parsed.attributes;
|
|
174
|
+
body = parsed.body;
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
throw new UserError("DEPLOY_FAILED", `Skill "${manifestPath}" SKILL.md has malformed YAML frontmatter: ${err instanceof Error ? err.message : String(err)}`);
|
|
178
|
+
}
|
|
179
|
+
const validateField = (field) => {
|
|
180
|
+
const value = attributes[field];
|
|
181
|
+
if (value === undefined || value === null) {
|
|
182
|
+
throw new UserError("DEPLOY_FAILED", `Skill "${manifestPath}" SKILL.md frontmatter must include a non-empty "${field}" field`);
|
|
183
|
+
}
|
|
184
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
185
|
+
throw new UserError("DEPLOY_FAILED", `Skill "${manifestPath}" SKILL.md frontmatter field "${field}" must be a non-empty string`);
|
|
186
|
+
}
|
|
187
|
+
if (value.includes("\n") || value.includes("\r")) {
|
|
188
|
+
throw new UserError("DEPLOY_FAILED", `Skill "${manifestPath}" SKILL.md frontmatter field "${field}" must be a single-line string`);
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
validateField("name");
|
|
192
|
+
validateField("description");
|
|
193
|
+
return { attributes, body };
|
|
194
|
+
}
|
|
195
|
+
function validateGithubCopilotRequirements(attributes, manifestPath) {
|
|
196
|
+
const hasTools = Object.hasOwn(attributes, "tools");
|
|
197
|
+
const hasInstructions = Object.hasOwn(attributes, "instructions");
|
|
198
|
+
if (!(hasTools || hasInstructions)) {
|
|
199
|
+
throw new UserError("DEPLOY_FAILED", `Instruction file "${manifestPath}" for agent "github-copilot" must define "tools" or "instructions" in frontmatter`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function validateAntigravityRequirements(attributes, manifestPath) {
|
|
203
|
+
const mcpServers = attributes["mcp-servers"] ?? attributes.mcpServers;
|
|
204
|
+
if (mcpServers === undefined)
|
|
205
|
+
return;
|
|
206
|
+
if (typeof mcpServers !== "object" ||
|
|
207
|
+
mcpServers === null ||
|
|
208
|
+
Array.isArray(mcpServers)) {
|
|
209
|
+
throw new UserError("DEPLOY_FAILED", `Instruction file "${manifestPath}" for agent "antigravity" must define "mcp-servers" as an object`);
|
|
210
|
+
}
|
|
211
|
+
for (const [name, config] of Object.entries(mcpServers)) {
|
|
212
|
+
if (typeof config !== "object" ||
|
|
213
|
+
config === null ||
|
|
214
|
+
Array.isArray(config)) {
|
|
215
|
+
throw new UserError("DEPLOY_FAILED", `Instruction file "${manifestPath}" for agent "antigravity" has malformed MCP server config for "${name}"`);
|
|
196
216
|
}
|
|
197
|
-
|
|
198
|
-
|
|
217
|
+
validateMcpServerConfigShape(config, name, "antigravity");
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Validates that an instruction file (agentRules or agentDefinitions) meets
|
|
222
|
+
* the structural requirements of the target agent.
|
|
223
|
+
*/
|
|
224
|
+
export async function validateInstructionFileRequirements(sourcePath, manifestPath, agentId) {
|
|
225
|
+
const requiresFrontmatter = AGENT_REGISTRY_BY_ID[agentId]?.instructionFrontmatterRequired === true;
|
|
226
|
+
if (!requiresFrontmatter)
|
|
227
|
+
return;
|
|
228
|
+
let attributes;
|
|
229
|
+
try {
|
|
230
|
+
const result = await validateSkillDefinitionFile(sourcePath, manifestPath);
|
|
231
|
+
attributes = result.attributes;
|
|
232
|
+
}
|
|
233
|
+
catch (err) {
|
|
234
|
+
if (err instanceof UserError) {
|
|
235
|
+
throw new UserError("DEPLOY_FAILED", `Instruction file "${manifestPath}" for agent "${agentId}" failed structural validation: ${err.message}`);
|
|
199
236
|
}
|
|
237
|
+
throw err;
|
|
200
238
|
}
|
|
201
|
-
if (
|
|
202
|
-
|
|
239
|
+
if (agentId === "github-copilot") {
|
|
240
|
+
validateGithubCopilotRequirements(attributes, manifestPath);
|
|
203
241
|
}
|
|
204
|
-
if (
|
|
205
|
-
|
|
242
|
+
else if (agentId === "antigravity") {
|
|
243
|
+
validateAntigravityRequirements(attributes, manifestPath);
|
|
206
244
|
}
|
|
207
245
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { styleText } from "node:util";
|
|
2
|
+
/**
|
|
3
|
+
* Groups and formats the dry-run plan by agent.
|
|
4
|
+
*/
|
|
5
|
+
export function formatDryRunPlan(planned) {
|
|
6
|
+
if (planned.length === 0)
|
|
7
|
+
return "";
|
|
8
|
+
const groups = new Map();
|
|
9
|
+
for (const change of planned) {
|
|
10
|
+
const list = groups.get(change.agent) ?? [];
|
|
11
|
+
list.push(change);
|
|
12
|
+
groups.set(change.agent, list);
|
|
13
|
+
}
|
|
14
|
+
const sortedAgents = Array.from(groups.keys()).sort();
|
|
15
|
+
const output = [];
|
|
16
|
+
for (const agent of sortedAgents) {
|
|
17
|
+
output.push(styleText(["bold", "yellow"], agent));
|
|
18
|
+
const changes = groups.get(agent);
|
|
19
|
+
if (!changes)
|
|
20
|
+
continue;
|
|
21
|
+
for (const change of changes) {
|
|
22
|
+
output.push(formatPlannedChange(change));
|
|
23
|
+
}
|
|
24
|
+
output.push("");
|
|
25
|
+
}
|
|
26
|
+
return output.join("\n");
|
|
27
|
+
}
|
|
28
|
+
function formatPlannedChange(change) {
|
|
29
|
+
const icon = styleText("cyan", "○");
|
|
30
|
+
const kind = styleText("dim", `[${change.kind}]`);
|
|
31
|
+
const lines = [
|
|
32
|
+
` ${icon} ${kind} ${change.verb} ${styleText("bold", change.skill)}`,
|
|
33
|
+
];
|
|
34
|
+
if (change.source !== undefined) {
|
|
35
|
+
lines.push(` source: ${styleText("dim", change.source)}`);
|
|
36
|
+
}
|
|
37
|
+
lines.push(` target: ${styleText("dim", change.target)}`);
|
|
38
|
+
const detail = formatChangeDetail(change);
|
|
39
|
+
if (detail) {
|
|
40
|
+
lines.push(` ${detail}`);
|
|
41
|
+
}
|
|
42
|
+
return lines.join("\n");
|
|
43
|
+
}
|
|
44
|
+
function formatChangeDetail(change) {
|
|
45
|
+
if (change.verb === "patch-config" && change.patch !== undefined) {
|
|
46
|
+
return `patch: ${styleText("dim", JSON.stringify(change.patch))}`;
|
|
47
|
+
}
|
|
48
|
+
if (change.verb === "unapply-patch" && change.patch !== undefined) {
|
|
49
|
+
return `undo: ${styleText("dim", JSON.stringify(change.patch))}`;
|
|
50
|
+
}
|
|
51
|
+
if (change.verb === "patch-toml" && change.patch !== undefined) {
|
|
52
|
+
return `patch: ${styleText("dim", JSON.stringify(change.patch))}`;
|
|
53
|
+
}
|
|
54
|
+
if (change.verb === "emit-frontmatter" && change.frontmatter !== undefined) {
|
|
55
|
+
return `frontmatter: ${styleText("dim", JSON.stringify(change.frontmatter))}`;
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ import { runPreflight } from "./core/preflight.js";
|
|
|
10
10
|
import { resolveHome } from "./core/resolve.js";
|
|
11
11
|
import { executeRevert, planRevert, planRevertAll } from "./core/revert.js";
|
|
12
12
|
import { UserError } from "./errors.js";
|
|
13
|
+
import { formatDryRunPlan } from "./formatters.js";
|
|
13
14
|
import { dryRunPrefix, logger } from "./logger.js";
|
|
14
15
|
import { AgentListSchema } from "./schemas/manifest.js";
|
|
15
16
|
const USAGE = `
|
|
@@ -26,7 +27,7 @@ Commands:
|
|
|
26
27
|
init <directory> Scan a directory for skill folders and generate inception.json
|
|
27
28
|
|
|
28
29
|
Options:
|
|
29
|
-
--
|
|
30
|
+
--plan Show what would be done without doing it
|
|
30
31
|
--agents <list> Comma-separated list of agent IDs to target
|
|
31
32
|
--force (init only) Overwrite an existing inception.json
|
|
32
33
|
--verbose Show detailed output
|
|
@@ -55,7 +56,7 @@ function parseCLI(argv) {
|
|
|
55
56
|
args,
|
|
56
57
|
allowPositionals: true,
|
|
57
58
|
options: {
|
|
58
|
-
|
|
59
|
+
plan: { type: "boolean", default: false },
|
|
59
60
|
verbose: { type: "boolean", default: false },
|
|
60
61
|
debug: { type: "boolean", default: false },
|
|
61
62
|
help: { type: "boolean", default: false },
|
|
@@ -107,7 +108,7 @@ function parseCLI(argv) {
|
|
|
107
108
|
return {
|
|
108
109
|
command,
|
|
109
110
|
directory: path.resolve(rawDir),
|
|
110
|
-
dryRun: values["dry-run"],
|
|
111
|
+
dryRun: (values.plan || values["dry-run"]),
|
|
111
112
|
agents,
|
|
112
113
|
verbose: values.verbose,
|
|
113
114
|
debug: values.debug,
|
|
@@ -136,21 +137,6 @@ async function main() {
|
|
|
136
137
|
}
|
|
137
138
|
return runRevert(options, manifest, home);
|
|
138
139
|
}
|
|
139
|
-
function renderDryRunPlan(planned) {
|
|
140
|
-
for (const change of planned) {
|
|
141
|
-
logger.plan(`[${change.agent}] ${change.verb} ${change.skill}`);
|
|
142
|
-
if (change.source !== undefined) {
|
|
143
|
-
logger.detail(`source: ${change.source}`);
|
|
144
|
-
}
|
|
145
|
-
logger.detail(`target: ${change.target}`);
|
|
146
|
-
if (change.verb === "patch-config" && change.patch !== undefined) {
|
|
147
|
-
logger.detail(`patch: ${JSON.stringify(change.patch)}`);
|
|
148
|
-
}
|
|
149
|
-
else if (change.verb === "unapply-patch" && change.patch !== undefined) {
|
|
150
|
-
logger.detail(`undo: ${JSON.stringify(change.patch)}`);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
140
|
async function runDeploy(options, manifest, home) {
|
|
155
141
|
let detectedAgents;
|
|
156
142
|
if (options.agents) {
|
|
@@ -187,9 +173,8 @@ async function runDeploy(options, manifest, home) {
|
|
|
187
173
|
const { succeeded, failed, planned } = await executeDeploy(actions, options.dryRun, options.verbose, home);
|
|
188
174
|
if (options.dryRun) {
|
|
189
175
|
logger.info("");
|
|
190
|
-
|
|
191
|
-
logger.info(
|
|
192
|
-
logger.info(`${planned.length} action(s) would be applied (dry-run)`);
|
|
176
|
+
logger.info(formatDryRunPlan(planned));
|
|
177
|
+
logger.info(`${planned.length} action(s) would be applied (plan)`);
|
|
193
178
|
return 0;
|
|
194
179
|
}
|
|
195
180
|
logger.info("");
|
|
@@ -212,9 +197,8 @@ async function runRevert(options, manifest, home) {
|
|
|
212
197
|
const { succeeded, skipped, failed, planned } = await executeRevert(actions, options.dryRun, options.verbose, home);
|
|
213
198
|
if (options.dryRun) {
|
|
214
199
|
logger.info("");
|
|
215
|
-
|
|
216
|
-
logger.info(
|
|
217
|
-
logger.info(`${planned.length} action(s) would be removed (dry-run)`);
|
|
200
|
+
logger.info(formatDryRunPlan(planned));
|
|
201
|
+
logger.info(`${planned.length} action(s) would be removed (plan)`);
|
|
218
202
|
return 0;
|
|
219
203
|
}
|
|
220
204
|
logger.info("");
|
package/dist/logger.js
CHANGED
|
@@ -1,36 +1,37 @@
|
|
|
1
1
|
import process from "node:process";
|
|
2
|
-
|
|
3
|
-
red: "\x1b[31m",
|
|
4
|
-
green: "\x1b[32m",
|
|
5
|
-
yellow: "\x1b[33m",
|
|
6
|
-
cyan: "\x1b[36m",
|
|
7
|
-
reset: "\x1b[0m",
|
|
8
|
-
};
|
|
2
|
+
import { styleText } from "node:util";
|
|
9
3
|
export function createLogger() {
|
|
10
4
|
let silent = false;
|
|
11
|
-
const tty = Boolean(process.stdout.isTTY);
|
|
12
|
-
const errTTY = Boolean(process.stderr.isTTY);
|
|
13
|
-
const c = (col, text, onTTY) => onTTY ? `${C[col]}${text}${C.reset}` : text;
|
|
14
5
|
return {
|
|
15
6
|
fail(label, msg) {
|
|
16
|
-
if (!silent)
|
|
17
|
-
|
|
7
|
+
if (!silent) {
|
|
8
|
+
const icon = styleText("red", "✗");
|
|
9
|
+
process.stderr.write(` ${icon} ${label}: ${msg}\n`);
|
|
10
|
+
}
|
|
18
11
|
},
|
|
19
12
|
ok(label) {
|
|
20
|
-
if (!silent)
|
|
21
|
-
|
|
13
|
+
if (!silent) {
|
|
14
|
+
const icon = styleText("green", "✓");
|
|
15
|
+
process.stdout.write(` ${icon} ${label}\n`);
|
|
16
|
+
}
|
|
22
17
|
},
|
|
23
18
|
skip(label, note) {
|
|
24
|
-
if (!silent)
|
|
25
|
-
|
|
19
|
+
if (!silent) {
|
|
20
|
+
const icon = styleText("yellow", "-");
|
|
21
|
+
process.stdout.write(` ${icon} ${label} ${note}\n`);
|
|
22
|
+
}
|
|
26
23
|
},
|
|
27
24
|
plan(label) {
|
|
28
|
-
if (!silent)
|
|
29
|
-
|
|
25
|
+
if (!silent) {
|
|
26
|
+
const icon = styleText("cyan", "○");
|
|
27
|
+
process.stdout.write(` ${icon} ${label}\n`);
|
|
28
|
+
}
|
|
30
29
|
},
|
|
31
30
|
warn(label, msg) {
|
|
32
|
-
if (!silent)
|
|
33
|
-
|
|
31
|
+
if (!silent) {
|
|
32
|
+
const icon = styleText("yellow", "!");
|
|
33
|
+
process.stdout.write(` ${icon} ${label}: ${msg}\n`);
|
|
34
|
+
}
|
|
34
35
|
},
|
|
35
36
|
info(msg) {
|
|
36
37
|
if (!silent)
|
|
@@ -57,5 +58,5 @@ export const logger = createLogger();
|
|
|
57
58
|
export function dryRunPrefix(dryRun) {
|
|
58
59
|
if (!dryRun)
|
|
59
60
|
return "";
|
|
60
|
-
return
|
|
61
|
+
return styleText("cyan", "[plan] ");
|
|
61
62
|
}
|
|
@@ -71,6 +71,11 @@ export declare const AgentRuleEntrySchema: z.ZodObject<{
|
|
|
71
71
|
"github-copilot": "github-copilot";
|
|
72
72
|
}>>>, z.ZodTransform<("claude-code" | "codex" | "gemini-cli" | "antigravity" | "opencode" | "github-copilot")[], ("claude-code" | "codex" | "gemini-cli" | "antigravity" | "opencode" | "github-copilot")[]>>;
|
|
73
73
|
path: z.ZodString;
|
|
74
|
+
scope: z.ZodDefault<z.ZodEnum<{
|
|
75
|
+
global: "global";
|
|
76
|
+
repo: "repo";
|
|
77
|
+
workspace: "workspace";
|
|
78
|
+
}>>;
|
|
74
79
|
}, z.core.$strip>;
|
|
75
80
|
export declare const PermissionsEntrySchema: z.ZodObject<{
|
|
76
81
|
name: z.ZodString;
|
|
@@ -158,6 +163,11 @@ export declare const ManifestSchema: z.ZodObject<{
|
|
|
158
163
|
"github-copilot": "github-copilot";
|
|
159
164
|
}>>>, z.ZodTransform<("claude-code" | "codex" | "gemini-cli" | "antigravity" | "opencode" | "github-copilot")[], ("claude-code" | "codex" | "gemini-cli" | "antigravity" | "opencode" | "github-copilot")[]>>;
|
|
160
165
|
path: z.ZodString;
|
|
166
|
+
scope: z.ZodDefault<z.ZodEnum<{
|
|
167
|
+
global: "global";
|
|
168
|
+
repo: "repo";
|
|
169
|
+
workspace: "workspace";
|
|
170
|
+
}>>;
|
|
161
171
|
}, z.core.$strip>>>;
|
|
162
172
|
permissions: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
163
173
|
name: z.ZodString;
|
package/dist/schemas/manifest.js
CHANGED
|
@@ -15,7 +15,7 @@ const SAFE_NAME_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
|
|
|
15
15
|
// is valid, while "{home}/../.ssh/config" is rejected.
|
|
16
16
|
// {repo} resolves to the manifest directory at deploy time, enabling repo-local
|
|
17
17
|
// targets (e.g. Antigravity's .agents/rules/ surface).
|
|
18
|
-
const TARGET_TEMPLATE_RE = /^\{(home|appdata|xdg_config|repo)\}(?:[\\/].*)?$/;
|
|
18
|
+
const TARGET_TEMPLATE_RE = /^\{(home|appdata|xdg_config|repo|workspace)\}(?:[\\/].*)?$/;
|
|
19
19
|
// Standalone schema used for type derivation and single-ID validation (e.g. index.ts).
|
|
20
20
|
export const AgentIdSchema = z.enum(AGENT_IDS);
|
|
21
21
|
// Used inside SkillEntrySchema.agents so that enum failures embed the received
|
|
@@ -88,7 +88,14 @@ export const AgentRuleEntrySchema = z.object({
|
|
|
88
88
|
name: nameField,
|
|
89
89
|
agents: agentsField,
|
|
90
90
|
// Relative path to the rules/instruction file within the source bundle.
|
|
91
|
+
// Must be a .md or .markdown file. Structural requirements (e.g. YAML
|
|
92
|
+
// frontmatter) are validated per agent requirements by the adapter.
|
|
91
93
|
path: sourcePathField,
|
|
94
|
+
// Deployment scope: "global" targets the agent's home-directory instruction
|
|
95
|
+
// file (default), "repo" targets the project-root instruction file within the
|
|
96
|
+
// deployed repository (e.g. {repo}/CLAUDE.md for claude-code), and "workspace"
|
|
97
|
+
// targets the agent's workspace-local instruction surface.
|
|
98
|
+
scope: z.enum(["global", "repo", "workspace"]).default("global"),
|
|
92
99
|
});
|
|
93
100
|
export const PermissionsEntrySchema = z.object({
|
|
94
101
|
name: nameField,
|
|
@@ -102,8 +109,8 @@ export const AgentDefinitionEntrySchema = z.object({
|
|
|
102
109
|
name: nameField,
|
|
103
110
|
agents: agentsField,
|
|
104
111
|
// Relative path to the agent definition Markdown file within the source bundle.
|
|
105
|
-
// Must be a .md or .markdown file
|
|
106
|
-
//
|
|
112
|
+
// Must be a .md or .markdown file. Structural requirements (e.g. YAML
|
|
113
|
+
// frontmatter) are validated per agent requirements by the adapter.
|
|
107
114
|
path: sourcePathField,
|
|
108
115
|
});
|
|
109
116
|
export const ManifestSchema = z.object({
|
|
@@ -46,6 +46,19 @@ declare const ConfigPatchRegistryEntrySchema: z.ZodObject<{
|
|
|
46
46
|
}>;
|
|
47
47
|
deployed: z.ZodString;
|
|
48
48
|
}, z.core.$strip>;
|
|
49
|
+
declare const FrontmatterEmitRegistryEntrySchema: z.ZodObject<{
|
|
50
|
+
kind: z.ZodLiteral<"frontmatter-emit">;
|
|
51
|
+
skill: z.ZodString;
|
|
52
|
+
agent: z.ZodEnum<{
|
|
53
|
+
"claude-code": "claude-code";
|
|
54
|
+
codex: "codex";
|
|
55
|
+
"gemini-cli": "gemini-cli";
|
|
56
|
+
antigravity: "antigravity";
|
|
57
|
+
opencode: "opencode";
|
|
58
|
+
"github-copilot": "github-copilot";
|
|
59
|
+
}>;
|
|
60
|
+
deployed: z.ZodString;
|
|
61
|
+
}, z.core.$strip>;
|
|
49
62
|
export declare const RegistryEntrySchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
50
63
|
kind: z.ZodLiteral<"skill-dir">;
|
|
51
64
|
source: z.ZodString;
|
|
@@ -90,6 +103,18 @@ export declare const RegistryEntrySchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
90
103
|
"github-copilot": "github-copilot";
|
|
91
104
|
}>;
|
|
92
105
|
deployed: z.ZodString;
|
|
106
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
107
|
+
kind: z.ZodLiteral<"frontmatter-emit">;
|
|
108
|
+
skill: z.ZodString;
|
|
109
|
+
agent: z.ZodEnum<{
|
|
110
|
+
"claude-code": "claude-code";
|
|
111
|
+
codex: "codex";
|
|
112
|
+
"gemini-cli": "gemini-cli";
|
|
113
|
+
antigravity: "antigravity";
|
|
114
|
+
opencode: "opencode";
|
|
115
|
+
"github-copilot": "github-copilot";
|
|
116
|
+
}>;
|
|
117
|
+
deployed: z.ZodString;
|
|
93
118
|
}, z.core.$strip>], "kind">;
|
|
94
119
|
export declare const RegistrySchema: z.ZodObject<{
|
|
95
120
|
version: z.ZodLiteral<1>;
|
|
@@ -137,11 +162,24 @@ export declare const RegistrySchema: z.ZodObject<{
|
|
|
137
162
|
"github-copilot": "github-copilot";
|
|
138
163
|
}>;
|
|
139
164
|
deployed: z.ZodString;
|
|
165
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
166
|
+
kind: z.ZodLiteral<"frontmatter-emit">;
|
|
167
|
+
skill: z.ZodString;
|
|
168
|
+
agent: z.ZodEnum<{
|
|
169
|
+
"claude-code": "claude-code";
|
|
170
|
+
codex: "codex";
|
|
171
|
+
"gemini-cli": "gemini-cli";
|
|
172
|
+
antigravity: "antigravity";
|
|
173
|
+
opencode: "opencode";
|
|
174
|
+
"github-copilot": "github-copilot";
|
|
175
|
+
}>;
|
|
176
|
+
deployed: z.ZodString;
|
|
140
177
|
}, z.core.$strip>], "kind">>;
|
|
141
178
|
}, z.core.$strip>;
|
|
142
179
|
export type SkillDirRegistryEntry = z.infer<typeof SkillDirRegistryEntrySchema>;
|
|
143
180
|
export type FileWriteRegistryEntry = z.infer<typeof FileWriteRegistryEntrySchema>;
|
|
144
181
|
export type ConfigPatchRegistryEntry = z.infer<typeof ConfigPatchRegistryEntrySchema>;
|
|
182
|
+
export type FrontmatterEmitRegistryEntry = z.infer<typeof FrontmatterEmitRegistryEntrySchema>;
|
|
145
183
|
export type RegistryEntry = z.infer<typeof RegistryEntrySchema>;
|
|
146
184
|
export type Registry = z.infer<typeof RegistrySchema>;
|
|
147
185
|
export {};
|
package/dist/schemas/registry.js
CHANGED
|
@@ -23,10 +23,17 @@ const ConfigPatchRegistryEntrySchema = z.object({
|
|
|
23
23
|
agent: AgentIdSchema,
|
|
24
24
|
deployed: z.string(),
|
|
25
25
|
});
|
|
26
|
+
const FrontmatterEmitRegistryEntrySchema = z.object({
|
|
27
|
+
kind: z.literal("frontmatter-emit"),
|
|
28
|
+
skill: z.string(),
|
|
29
|
+
agent: AgentIdSchema,
|
|
30
|
+
deployed: z.string(),
|
|
31
|
+
});
|
|
26
32
|
export const RegistryEntrySchema = z.discriminatedUnion("kind", [
|
|
27
33
|
SkillDirRegistryEntrySchema,
|
|
28
34
|
FileWriteRegistryEntrySchema,
|
|
29
35
|
ConfigPatchRegistryEntrySchema,
|
|
36
|
+
FrontmatterEmitRegistryEntrySchema,
|
|
30
37
|
]);
|
|
31
38
|
export const RegistrySchema = z.object({
|
|
32
39
|
version: z.literal(1),
|
package/dist/types.d.ts
CHANGED
|
@@ -7,6 +7,33 @@ export interface AgentPaths {
|
|
|
7
7
|
export type Confidence = "documented" | "implementation-only" | "provisional";
|
|
8
8
|
export interface SupportedAgentSurface {
|
|
9
9
|
status: "supported";
|
|
10
|
+
/**
|
|
11
|
+
* Declares how this agent relates to the surface:
|
|
12
|
+
* - "agent-specific" (default when absent): the agent owns this surface
|
|
13
|
+
* independently and deploy emits a normal action.
|
|
14
|
+
* - "native": the agent reads this surface autonomously without any deploy
|
|
15
|
+
* action from inception-engine; no action is emitted.
|
|
16
|
+
* - "shared-via": this agent rides another agent's deployment. When the
|
|
17
|
+
* primary agent (`via`) is also in the target list, deploy skips this
|
|
18
|
+
* agent's action (the primary writes the shared file). When the primary
|
|
19
|
+
* is absent, a guidance warning is emitted instead.
|
|
20
|
+
*/
|
|
21
|
+
surfaceKind?: {
|
|
22
|
+
kind: "agent-specific";
|
|
23
|
+
} | {
|
|
24
|
+
kind: "native";
|
|
25
|
+
} | {
|
|
26
|
+
kind: "shared-via";
|
|
27
|
+
via: AgentId;
|
|
28
|
+
/**
|
|
29
|
+
* When true, this agent cannot deploy to the surface independently —
|
|
30
|
+
* the primary agent (`via`) must also be in the target list. If the
|
|
31
|
+
* primary is absent, a guidance warning is emitted and no action is
|
|
32
|
+
* generated. When false or absent, the agent can deploy to the surface
|
|
33
|
+
* on its own if the primary is not present.
|
|
34
|
+
*/
|
|
35
|
+
requiresPrimary?: boolean;
|
|
36
|
+
};
|
|
10
37
|
path: AgentPaths;
|
|
11
38
|
schemaLabel: string;
|
|
12
39
|
mcpPatchKey?: string;
|
|
@@ -50,14 +77,35 @@ export interface AgentConfig {
|
|
|
50
77
|
* (e.g. GitHub Copilot reads `.claude/skills/` directly).
|
|
51
78
|
*/
|
|
52
79
|
skills?: AgentPaths;
|
|
80
|
+
/**
|
|
81
|
+
* When `skills` is absent, this field explains why. Currently only
|
|
82
|
+
* "shared-via" is used — the agent reads skills from the `via` agent's
|
|
83
|
+
* deployment path natively and needs no separate skills deploy action.
|
|
84
|
+
*/
|
|
85
|
+
skillsSurfaceKind?: {
|
|
86
|
+
kind: "shared-via";
|
|
87
|
+
via: AgentId;
|
|
88
|
+
};
|
|
53
89
|
detectPaths: AgentPaths;
|
|
54
90
|
detectBinary: string | null;
|
|
55
91
|
provenance: AgentProvenance;
|
|
56
92
|
mcpSupport?: AgentSurfaceSupport;
|
|
57
93
|
agentRulesSupport?: AgentSurfaceSupport;
|
|
94
|
+
agentRulesRepoSupport?: AgentSurfaceSupport;
|
|
95
|
+
agentRulesWorkspaceSupport?: AgentSurfaceSupport;
|
|
58
96
|
permissionsSupport?: AgentSurfaceSupport;
|
|
59
97
|
agentDefinitionsSupport?: AgentSurfaceSupport;
|
|
60
98
|
policyNote?: string;
|
|
99
|
+
/**
|
|
100
|
+
* When true, instruction files deployed to this agent must include valid
|
|
101
|
+
* YAML frontmatter. Drives validateInstructionFileRequirements without
|
|
102
|
+
* hardcoded agent-ID checks.
|
|
103
|
+
*/
|
|
104
|
+
instructionFrontmatterRequired?: boolean;
|
|
105
|
+
/**
|
|
106
|
+
* When true, preflight runs enterprise-policy detection for this agent.
|
|
107
|
+
*/
|
|
108
|
+
enterprisePolicyDetection?: boolean;
|
|
61
109
|
}
|
|
62
110
|
export interface PlanWarning {
|
|
63
111
|
kind: "confidence" | "collision" | "ambiguity";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kuznai/inception-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.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",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"test:posix": "node --test --test-isolation=none test/unit/*.test.ts test/os/cross-platform/*.test.ts test/os/posix/*.test.ts"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"front-matter": "^4.0.2",
|
|
51
50
|
"smol-toml": "^1.6.1",
|
|
51
|
+
"yaml": "^2.8.3",
|
|
52
52
|
"zod": "^4.0.0"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|