@kuznai/inception-engine 0.19.0 → 0.20.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 +48 -22
- package/dist/{config → src/config}/agents.js +87 -14
- package/dist/{core → src/core}/adapters/agent-definitions.d.ts +0 -12
- package/dist/src/core/adapters/agent-definitions.js +162 -0
- package/dist/{core → src/core}/adapters/frontmatter.d.ts +10 -0
- package/dist/{core → src/core}/adapters/frontmatter.js +23 -6
- package/dist/{core → src/core}/adapters/mcp.js +17 -20
- package/dist/{core → src/core}/adapters/permissions.js +16 -20
- package/dist/{core → src/core}/adapters/rules.js +26 -50
- package/dist/src/core/capabilities.d.ts +47 -0
- package/dist/src/core/capabilities.js +280 -0
- package/dist/{core → src/core}/deploy.js +70 -41
- package/dist/{core → src/core}/init.js +18 -24
- package/dist/src/core/merge-patch.d.ts +4 -0
- package/dist/src/core/merge-patch.js +46 -0
- package/dist/{core → src/core}/ownership.js +13 -0
- package/dist/{core → src/core}/preflight.js +141 -29
- package/dist/{core → src/core}/revert.js +86 -26
- package/dist/{core → src/core}/validation.js +20 -0
- package/dist/{schemas → src/schemas}/manifest.d.ts +20 -0
- package/dist/{schemas → src/schemas}/manifest.js +11 -0
- package/dist/{schemas → src/schemas}/registry.d.ts +36 -0
- package/dist/{schemas → src/schemas}/registry.js +12 -4
- package/dist/{types.d.ts → src/types.d.ts} +13 -0
- package/dist/test/helpers/fs.d.ts +2 -0
- package/dist/test/helpers/fs.js +17 -0
- package/dist/test/helpers/path.d.ts +10 -0
- package/dist/test/helpers/path.js +15 -0
- package/dist/test/helpers/skill-dir-scenarios.d.ts +7 -0
- package/dist/test/helpers/skill-dir-scenarios.js +206 -0
- package/dist/test/helpers/skill-dir.d.ts +7 -0
- package/dist/test/helpers/skill-dir.js +46 -0
- package/dist/test/os/cross-platform/cross-platform.test.d.ts +1 -0
- package/dist/test/os/cross-platform/cross-platform.test.js +328 -0
- package/dist/test/os/posix/skill-dir.test.d.ts +1 -0
- package/dist/test/os/posix/skill-dir.test.js +19 -0
- package/dist/test/os/windows/revert-integration.test.d.ts +1 -0
- package/dist/test/os/windows/revert-integration.test.js +72 -0
- package/dist/test/os/windows/skill-dir.test.d.ts +1 -0
- package/dist/test/os/windows/skill-dir.test.js +19 -0
- package/dist/test/unit/adapters.test.d.ts +1 -0
- package/dist/test/unit/adapters.test.js +947 -0
- package/dist/test/unit/capabilities.test.d.ts +1 -0
- package/dist/test/unit/capabilities.test.js +71 -0
- package/dist/test/unit/cli.test.d.ts +1 -0
- package/dist/test/unit/cli.test.js +834 -0
- package/dist/test/unit/deploy.test.d.ts +1 -0
- package/dist/test/unit/deploy.test.js +2481 -0
- package/dist/test/unit/detect.test.d.ts +1 -0
- package/dist/test/unit/detect.test.js +192 -0
- package/dist/test/unit/enterprise.test.d.ts +1 -0
- package/dist/test/unit/enterprise.test.js +106 -0
- package/dist/test/unit/frontmatter.test.d.ts +1 -0
- package/dist/test/unit/frontmatter.test.js +102 -0
- package/dist/test/unit/gemini-north-star.test.d.ts +1 -0
- package/dist/test/unit/gemini-north-star.test.js +243 -0
- package/dist/test/unit/manifest.test.d.ts +1 -0
- package/dist/test/unit/manifest.test.js +737 -0
- package/dist/test/unit/migration-golden.test.d.ts +1 -0
- package/dist/test/unit/migration-golden.test.js +197 -0
- package/dist/test/unit/ownership.test.d.ts +1 -0
- package/dist/test/unit/ownership.test.js +587 -0
- package/dist/test/unit/preflight.test.d.ts +1 -0
- package/dist/test/unit/preflight.test.js +501 -0
- package/dist/test/unit/resolve.test.d.ts +1 -0
- package/dist/test/unit/resolve.test.js +119 -0
- package/dist/test/unit/revert.test.d.ts +1 -0
- package/dist/test/unit/revert.test.js +1004 -0
- package/dist/test/unit/toml.test.d.ts +1 -0
- package/dist/test/unit/toml.test.js +55 -0
- package/package.json +1 -1
- package/dist/core/adapters/agent-definitions.js +0 -91
- /package/dist/{config → src/config}/agents.d.ts +0 -0
- /package/dist/{config → src/config}/manifest.d.ts +0 -0
- /package/dist/{config → src/config}/manifest.js +0 -0
- /package/dist/{core → src/core}/adapters/index.d.ts +0 -0
- /package/dist/{core → src/core}/adapters/index.js +0 -0
- /package/dist/{core → src/core}/adapters/mcp.d.ts +0 -0
- /package/dist/{core → src/core}/adapters/permissions.d.ts +0 -0
- /package/dist/{core → src/core}/adapters/rules.d.ts +0 -0
- /package/dist/{core → src/core}/adapters/toml.d.ts +0 -0
- /package/dist/{core → src/core}/adapters/toml.js +0 -0
- /package/dist/{core → src/core}/deploy.d.ts +0 -0
- /package/dist/{core → src/core}/detect.d.ts +0 -0
- /package/dist/{core → src/core}/detect.js +0 -0
- /package/dist/{core → src/core}/init.d.ts +0 -0
- /package/dist/{core → src/core}/ownership.d.ts +0 -0
- /package/dist/{core → src/core}/preflight.d.ts +0 -0
- /package/dist/{core → src/core}/resolve.d.ts +0 -0
- /package/dist/{core → src/core}/resolve.js +0 -0
- /package/dist/{core → src/core}/revert.d.ts +0 -0
- /package/dist/{core → src/core}/runtime-paths.d.ts +0 -0
- /package/dist/{core → src/core}/runtime-paths.js +0 -0
- /package/dist/{core → src/core}/validation.d.ts +0 -0
- /package/dist/{errors.d.ts → src/errors.d.ts} +0 -0
- /package/dist/{errors.js → src/errors.js} +0 -0
- /package/dist/{formatters.d.ts → src/formatters.d.ts} +0 -0
- /package/dist/{formatters.js → src/formatters.js} +0 -0
- /package/dist/{index.d.ts → src/index.d.ts} +0 -0
- /package/dist/{index.js → src/index.js} +0 -0
- /package/dist/{logger.d.ts → src/logger.d.ts} +0 -0
- /package/dist/{logger.js → src/logger.js} +0 -0
- /package/dist/{schemas → src/schemas}/errors.d.ts +0 -0
- /package/dist/{schemas → src/schemas}/errors.js +0 -0
- /package/dist/{types.js → src/types.js} +0 -0
|
@@ -3,6 +3,7 @@ import { AGENT_REGISTRY_BY_ID } from "../config/agents.js";
|
|
|
3
3
|
import { logger } from "../logger.js";
|
|
4
4
|
import { compileAgentDefinitionReverts, compileAgentRuleReverts, compileMcpServerReverts, compilePermissionsReverts, } from "./adapters/index.js";
|
|
5
5
|
import { revertTomlMcpPatch } from "./adapters/toml.js";
|
|
6
|
+
import { applyUndoPatch } from "./merge-patch.js";
|
|
6
7
|
import { lookupDeployment, unregisterDeployment, } from "./ownership.js";
|
|
7
8
|
import { resolveAgentSkillPath } from "./resolve.js";
|
|
8
9
|
import { resolveTargetTemplate } from "./runtime-paths.js";
|
|
@@ -112,24 +113,6 @@ async function readJsonConfig(filePath) {
|
|
|
112
113
|
}
|
|
113
114
|
return parsed;
|
|
114
115
|
}
|
|
115
|
-
function isPlainObject(v) {
|
|
116
|
-
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
117
|
-
}
|
|
118
|
-
function applyUndoPatch(current, undoPatch) {
|
|
119
|
-
const restored = { ...current };
|
|
120
|
-
for (const [key, originalValue] of Object.entries(undoPatch)) {
|
|
121
|
-
if (originalValue === null) {
|
|
122
|
-
delete restored[key];
|
|
123
|
-
}
|
|
124
|
-
else if (isPlainObject(originalValue) && isPlainObject(restored[key])) {
|
|
125
|
-
restored[key] = applyUndoPatch(restored[key], originalValue);
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
restored[key] = originalValue;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return restored;
|
|
132
|
-
}
|
|
133
116
|
function lstatOutcome(err) {
|
|
134
117
|
if (err.code === "ENOENT") {
|
|
135
118
|
return { outcome: "skip" };
|
|
@@ -157,14 +140,7 @@ export async function executeRevert(actions, dryRun, verbose, home, deps = {}) {
|
|
|
157
140
|
result = await revertTomlPatch(action, dryRun, verbose, home, planned, deps);
|
|
158
141
|
break;
|
|
159
142
|
case "frontmatter-emit":
|
|
160
|
-
|
|
161
|
-
// deletes the file, same as a file-write revert.
|
|
162
|
-
result = await revertFileWrite({
|
|
163
|
-
kind: "file-write",
|
|
164
|
-
skill: action.skill,
|
|
165
|
-
agent: action.agent,
|
|
166
|
-
target: action.target,
|
|
167
|
-
}, dryRun, verbose, home, planned, deps);
|
|
143
|
+
result = await revertFrontmatterEmit(action, dryRun, verbose, home, planned, deps);
|
|
168
144
|
break;
|
|
169
145
|
default: {
|
|
170
146
|
throw new Error(`Unhandled revert action kind: ${action.kind}`);
|
|
@@ -179,6 +155,90 @@ export async function executeRevert(actions, dryRun, verbose, home, deps = {}) {
|
|
|
179
155
|
planned,
|
|
180
156
|
};
|
|
181
157
|
}
|
|
158
|
+
function isManagedFrontmatterEntry(entry, action) {
|
|
159
|
+
return (entry !== null &&
|
|
160
|
+
entry.kind === "frontmatter-emit" &&
|
|
161
|
+
entry.skill === action.skill &&
|
|
162
|
+
entry.agent === action.agent);
|
|
163
|
+
}
|
|
164
|
+
async function loadManagedFrontmatterEntry(action, home, deps) {
|
|
165
|
+
const entry = await lookupDeployment(home, action.target, deps.registry);
|
|
166
|
+
return isManagedFrontmatterEntry(entry, action) ? entry : null;
|
|
167
|
+
}
|
|
168
|
+
function planFrontmatterRevert(action, frontmatterEntry, planned) {
|
|
169
|
+
planned.push({
|
|
170
|
+
verb: "unapply-patch",
|
|
171
|
+
kind: "frontmatter-emit",
|
|
172
|
+
skill: action.skill,
|
|
173
|
+
agent: action.agent,
|
|
174
|
+
target: action.target,
|
|
175
|
+
patch: frontmatterEntry.undoPatch,
|
|
176
|
+
});
|
|
177
|
+
return { outcome: "ok" };
|
|
178
|
+
}
|
|
179
|
+
async function applyFrontmatterRevert(action, frontmatterEntry) {
|
|
180
|
+
const frontmatterAdapter = await import("./adapters/frontmatter.js");
|
|
181
|
+
const current = await frontmatterAdapter.readFrontmatterDocumentFile(action.target);
|
|
182
|
+
const restoredFrontmatter = applyUndoPatch(current.attributes, frontmatterEntry.undoPatch ?? {});
|
|
183
|
+
const shouldDeleteFile = frontmatterEntry.created === true &&
|
|
184
|
+
!frontmatterEntry.hadFrontmatter &&
|
|
185
|
+
Object.keys(restoredFrontmatter).length === 0 &&
|
|
186
|
+
current.body.trim() === "";
|
|
187
|
+
if (shouldDeleteFile) {
|
|
188
|
+
await unlink(action.target);
|
|
189
|
+
return { shouldDeleteFile };
|
|
190
|
+
}
|
|
191
|
+
const restoredContent = frontmatterAdapter.buildMarkdownDocument(restoredFrontmatter, current.body, { hasFrontmatter: frontmatterEntry.hadFrontmatter ?? false });
|
|
192
|
+
await writeFile(action.target, restoredContent, "utf-8");
|
|
193
|
+
return { shouldDeleteFile };
|
|
194
|
+
}
|
|
195
|
+
async function revertFrontmatterEmit(action, dryRun, verbose, home, planned, deps) {
|
|
196
|
+
const label = `${action.skill} -> ${action.agent}`;
|
|
197
|
+
try {
|
|
198
|
+
await lstat(action.target);
|
|
199
|
+
}
|
|
200
|
+
catch (err) {
|
|
201
|
+
const result = lstatOutcome(err);
|
|
202
|
+
if (result.outcome === "skip") {
|
|
203
|
+
logger.skip(label, "(not found, skipping)");
|
|
204
|
+
return result;
|
|
205
|
+
}
|
|
206
|
+
logger.fail(label, result.error);
|
|
207
|
+
return result;
|
|
208
|
+
}
|
|
209
|
+
const frontmatterEntry = await loadManagedFrontmatterEntry(action, home, deps);
|
|
210
|
+
if (!frontmatterEntry) {
|
|
211
|
+
logger.warn(label, `skipping: ${action.target} is not in the deployment registry — not managed by inception-engine`);
|
|
212
|
+
return { outcome: "skip" };
|
|
213
|
+
}
|
|
214
|
+
if (!frontmatterEntry.undoPatch) {
|
|
215
|
+
return revertFileWrite({
|
|
216
|
+
kind: "file-write",
|
|
217
|
+
skill: action.skill,
|
|
218
|
+
agent: action.agent,
|
|
219
|
+
target: action.target,
|
|
220
|
+
}, dryRun, verbose, home, planned, deps);
|
|
221
|
+
}
|
|
222
|
+
if (dryRun) {
|
|
223
|
+
return planFrontmatterRevert(action, frontmatterEntry, planned);
|
|
224
|
+
}
|
|
225
|
+
try {
|
|
226
|
+
const { shouldDeleteFile } = await applyFrontmatterRevert(action, frontmatterEntry);
|
|
227
|
+
await unregisterDeployment(home, action.target, deps.registry);
|
|
228
|
+
logger.ok(label);
|
|
229
|
+
if (verbose) {
|
|
230
|
+
logger.detail(shouldDeleteFile
|
|
231
|
+
? `removed: ${action.target}`
|
|
232
|
+
: `unapplied frontmatter patch from: ${action.target}`);
|
|
233
|
+
}
|
|
234
|
+
return { outcome: "ok" };
|
|
235
|
+
}
|
|
236
|
+
catch (err) {
|
|
237
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
238
|
+
logger.fail(label, msg);
|
|
239
|
+
return { outcome: "fail", error: msg };
|
|
240
|
+
}
|
|
241
|
+
}
|
|
182
242
|
async function executeRevertAction(action, dryRun, verbose, home, planned, deps) {
|
|
183
243
|
const label = `${action.skill} -> ${action.agent}`;
|
|
184
244
|
try {
|
|
@@ -135,6 +135,23 @@ function validateCodexPermissions(config, entryName) {
|
|
|
135
135
|
throw new UserError("DEPLOY_FAILED", `permissions entry "${entryName}" for agent "codex" must define "approval_policy" as one of: ${CODEX_APPROVAL_POLICY_VALUES.join(", ")}`);
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
|
+
function validateOpenCodePermissions(config, entryName) {
|
|
139
|
+
rejectUnknownKeys(config, ["permissions"], entryName, "opencode");
|
|
140
|
+
const perms = config.permissions;
|
|
141
|
+
if (perms === undefined)
|
|
142
|
+
return;
|
|
143
|
+
if (typeof perms !== "object" || perms === null || Array.isArray(perms)) {
|
|
144
|
+
throw new UserError("DEPLOY_FAILED", `permissions entry "${entryName}" for agent "opencode" must define "permissions" as an object`);
|
|
145
|
+
}
|
|
146
|
+
const permsObj = perms;
|
|
147
|
+
for (const key of ["allow", "ask", "deny"]) {
|
|
148
|
+
const val = permsObj[key];
|
|
149
|
+
if (val !== undefined &&
|
|
150
|
+
(!Array.isArray(val) || val.some((item) => typeof item !== "string"))) {
|
|
151
|
+
throw new UserError("DEPLOY_FAILED", `permissions entry "${entryName}" for agent "opencode" must define "permissions.${key}" as an array of strings when present`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
138
155
|
export function validatePermissionsConfigShape(config, entryName, agentId) {
|
|
139
156
|
if (agentId === "claude-code") {
|
|
140
157
|
validateClaudeCodePermissions(config, entryName);
|
|
@@ -142,6 +159,9 @@ export function validatePermissionsConfigShape(config, entryName, agentId) {
|
|
|
142
159
|
else if (agentId === "codex") {
|
|
143
160
|
validateCodexPermissions(config, entryName);
|
|
144
161
|
}
|
|
162
|
+
else if (agentId === "opencode") {
|
|
163
|
+
validateOpenCodePermissions(config, entryName);
|
|
164
|
+
}
|
|
145
165
|
}
|
|
146
166
|
export function validateAgentRuleMarkdownPath(manifestPath, agentId) {
|
|
147
167
|
const extension = path.extname(manifestPath).toLowerCase();
|
|
@@ -59,6 +59,11 @@ export declare const McpServerEntrySchema: z.ZodObject<{
|
|
|
59
59
|
"github-copilot": "github-copilot";
|
|
60
60
|
}>>>, z.ZodTransform<("claude-code" | "codex" | "gemini-cli" | "antigravity" | "opencode" | "github-copilot")[], ("claude-code" | "codex" | "gemini-cli" | "antigravity" | "opencode" | "github-copilot")[]>>;
|
|
61
61
|
config: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
62
|
+
scope: z.ZodDefault<z.ZodEnum<{
|
|
63
|
+
global: "global";
|
|
64
|
+
repo: "repo";
|
|
65
|
+
workspace: "workspace";
|
|
66
|
+
}>>;
|
|
62
67
|
}, z.core.$strip>;
|
|
63
68
|
export declare const AgentRuleEntrySchema: z.ZodObject<{
|
|
64
69
|
name: z.ZodString;
|
|
@@ -100,6 +105,11 @@ export declare const AgentDefinitionEntrySchema: z.ZodObject<{
|
|
|
100
105
|
"github-copilot": "github-copilot";
|
|
101
106
|
}>>>, z.ZodTransform<("claude-code" | "codex" | "gemini-cli" | "antigravity" | "opencode" | "github-copilot")[], ("claude-code" | "codex" | "gemini-cli" | "antigravity" | "opencode" | "github-copilot")[]>>;
|
|
102
107
|
path: z.ZodString;
|
|
108
|
+
scope: z.ZodDefault<z.ZodEnum<{
|
|
109
|
+
global: "global";
|
|
110
|
+
repo: "repo";
|
|
111
|
+
workspace: "workspace";
|
|
112
|
+
}>>;
|
|
103
113
|
}, z.core.$strip>;
|
|
104
114
|
export declare const ManifestSchema: z.ZodObject<{
|
|
105
115
|
skills: z.ZodArray<z.ZodObject<{
|
|
@@ -151,6 +161,11 @@ export declare const ManifestSchema: z.ZodObject<{
|
|
|
151
161
|
"github-copilot": "github-copilot";
|
|
152
162
|
}>>>, z.ZodTransform<("claude-code" | "codex" | "gemini-cli" | "antigravity" | "opencode" | "github-copilot")[], ("claude-code" | "codex" | "gemini-cli" | "antigravity" | "opencode" | "github-copilot")[]>>;
|
|
153
163
|
config: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
164
|
+
scope: z.ZodDefault<z.ZodEnum<{
|
|
165
|
+
global: "global";
|
|
166
|
+
repo: "repo";
|
|
167
|
+
workspace: "workspace";
|
|
168
|
+
}>>;
|
|
154
169
|
}, z.core.$strip>>>;
|
|
155
170
|
agentRules: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
156
171
|
name: z.ZodString;
|
|
@@ -192,6 +207,11 @@ export declare const ManifestSchema: z.ZodObject<{
|
|
|
192
207
|
"github-copilot": "github-copilot";
|
|
193
208
|
}>>>, z.ZodTransform<("claude-code" | "codex" | "gemini-cli" | "antigravity" | "opencode" | "github-copilot")[], ("claude-code" | "codex" | "gemini-cli" | "antigravity" | "opencode" | "github-copilot")[]>>;
|
|
194
209
|
path: z.ZodString;
|
|
210
|
+
scope: z.ZodDefault<z.ZodEnum<{
|
|
211
|
+
global: "global";
|
|
212
|
+
repo: "repo";
|
|
213
|
+
workspace: "workspace";
|
|
214
|
+
}>>;
|
|
195
215
|
}, z.core.$strip>>>;
|
|
196
216
|
}, z.core.$strip>;
|
|
197
217
|
export type SkillEntry = z.infer<typeof SkillEntrySchema>;
|
|
@@ -83,6 +83,12 @@ export const McpServerEntrySchema = z.object({
|
|
|
83
83
|
// Raw server descriptor passed verbatim to each agent adapter.
|
|
84
84
|
// Adapters are responsible for validating the shape they need.
|
|
85
85
|
config: z.record(z.string(), z.unknown()),
|
|
86
|
+
// Deployment scope: "global" (default) targets the agent's user-level MCP
|
|
87
|
+
// config file. "repo" and "workspace" target repo- or workspace-relative
|
|
88
|
+
// config files for agents that support them (e.g. GitHub Copilot's
|
|
89
|
+
// .vscode/mcp.json). For agents without scope-specific surfaces the
|
|
90
|
+
// adapter falls back to the global surface or emits a warning.
|
|
91
|
+
scope: z.enum(["global", "repo", "workspace"]).default("global"),
|
|
86
92
|
});
|
|
87
93
|
export const AgentRuleEntrySchema = z.object({
|
|
88
94
|
name: nameField,
|
|
@@ -103,6 +109,7 @@ export const PermissionsEntrySchema = z.object({
|
|
|
103
109
|
// Raw permission config payload validated per agent by the permissions adapter.
|
|
104
110
|
// For claude-code: { permissions: { allow?: string[], deny?: string[] } }
|
|
105
111
|
// For codex: { approval_policy?: "auto" | "manual" | "suggest" | "on-failure" }
|
|
112
|
+
// For opencode: { permissions: { allow?: string[], ask?: string[], deny?: string[] } }
|
|
106
113
|
config: z.record(z.string(), z.unknown()),
|
|
107
114
|
});
|
|
108
115
|
export const AgentDefinitionEntrySchema = z.object({
|
|
@@ -112,6 +119,10 @@ export const AgentDefinitionEntrySchema = z.object({
|
|
|
112
119
|
// Must be a .md or .markdown file. Structural requirements (e.g. YAML
|
|
113
120
|
// frontmatter) are validated per agent requirements by the adapter.
|
|
114
121
|
path: sourcePathField,
|
|
122
|
+
// Deployment scope: "global" targets the agent's home-directory definition
|
|
123
|
+
// directory (if supported), "repo" targets the project-root definition directory
|
|
124
|
+
// within the deployed repository (default).
|
|
125
|
+
scope: z.enum(["global", "repo", "workspace"]).default("repo"),
|
|
115
126
|
});
|
|
116
127
|
export const ManifestSchema = z.object({
|
|
117
128
|
skills: z.array(SkillEntrySchema).superRefine((skills, ctx) => {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
declare const SkillDirRegistryEntrySchema: z.ZodObject<{
|
|
3
|
+
surfaceId: z.ZodOptional<z.ZodString>;
|
|
4
|
+
migratedFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
3
5
|
kind: z.ZodLiteral<"skill-dir">;
|
|
4
6
|
source: z.ZodString;
|
|
5
7
|
skill: z.ZodString;
|
|
@@ -18,6 +20,8 @@ declare const SkillDirRegistryEntrySchema: z.ZodObject<{
|
|
|
18
20
|
deployed: z.ZodString;
|
|
19
21
|
}, z.core.$strip>;
|
|
20
22
|
declare const FileWriteRegistryEntrySchema: z.ZodObject<{
|
|
23
|
+
surfaceId: z.ZodOptional<z.ZodString>;
|
|
24
|
+
migratedFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
21
25
|
kind: z.ZodLiteral<"file-write">;
|
|
22
26
|
source: z.ZodString;
|
|
23
27
|
skill: z.ZodString;
|
|
@@ -32,6 +36,8 @@ declare const FileWriteRegistryEntrySchema: z.ZodObject<{
|
|
|
32
36
|
deployed: z.ZodString;
|
|
33
37
|
}, z.core.$strip>;
|
|
34
38
|
declare const ConfigPatchRegistryEntrySchema: z.ZodObject<{
|
|
39
|
+
surfaceId: z.ZodOptional<z.ZodString>;
|
|
40
|
+
migratedFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
35
41
|
kind: z.ZodLiteral<"config-patch">;
|
|
36
42
|
patch: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
37
43
|
undoPatch: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
@@ -47,7 +53,13 @@ declare const ConfigPatchRegistryEntrySchema: z.ZodObject<{
|
|
|
47
53
|
deployed: z.ZodString;
|
|
48
54
|
}, z.core.$strip>;
|
|
49
55
|
declare const FrontmatterEmitRegistryEntrySchema: z.ZodObject<{
|
|
56
|
+
surfaceId: z.ZodOptional<z.ZodString>;
|
|
57
|
+
migratedFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
50
58
|
kind: z.ZodLiteral<"frontmatter-emit">;
|
|
59
|
+
patch: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
60
|
+
undoPatch: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
61
|
+
created: z.ZodOptional<z.ZodBoolean>;
|
|
62
|
+
hadFrontmatter: z.ZodOptional<z.ZodBoolean>;
|
|
51
63
|
skill: z.ZodString;
|
|
52
64
|
agent: z.ZodEnum<{
|
|
53
65
|
"claude-code": "claude-code";
|
|
@@ -60,6 +72,8 @@ declare const FrontmatterEmitRegistryEntrySchema: z.ZodObject<{
|
|
|
60
72
|
deployed: z.ZodString;
|
|
61
73
|
}, z.core.$strip>;
|
|
62
74
|
export declare const RegistryEntrySchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
75
|
+
surfaceId: z.ZodOptional<z.ZodString>;
|
|
76
|
+
migratedFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
63
77
|
kind: z.ZodLiteral<"skill-dir">;
|
|
64
78
|
source: z.ZodString;
|
|
65
79
|
skill: z.ZodString;
|
|
@@ -77,6 +91,8 @@ export declare const RegistryEntrySchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
77
91
|
}>>;
|
|
78
92
|
deployed: z.ZodString;
|
|
79
93
|
}, z.core.$strip>, z.ZodObject<{
|
|
94
|
+
surfaceId: z.ZodOptional<z.ZodString>;
|
|
95
|
+
migratedFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
80
96
|
kind: z.ZodLiteral<"file-write">;
|
|
81
97
|
source: z.ZodString;
|
|
82
98
|
skill: z.ZodString;
|
|
@@ -90,6 +106,8 @@ export declare const RegistryEntrySchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
90
106
|
}>;
|
|
91
107
|
deployed: z.ZodString;
|
|
92
108
|
}, z.core.$strip>, z.ZodObject<{
|
|
109
|
+
surfaceId: z.ZodOptional<z.ZodString>;
|
|
110
|
+
migratedFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
93
111
|
kind: z.ZodLiteral<"config-patch">;
|
|
94
112
|
patch: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
95
113
|
undoPatch: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
@@ -104,7 +122,13 @@ export declare const RegistryEntrySchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
104
122
|
}>;
|
|
105
123
|
deployed: z.ZodString;
|
|
106
124
|
}, z.core.$strip>, z.ZodObject<{
|
|
125
|
+
surfaceId: z.ZodOptional<z.ZodString>;
|
|
126
|
+
migratedFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
107
127
|
kind: z.ZodLiteral<"frontmatter-emit">;
|
|
128
|
+
patch: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
129
|
+
undoPatch: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
130
|
+
created: z.ZodOptional<z.ZodBoolean>;
|
|
131
|
+
hadFrontmatter: z.ZodOptional<z.ZodBoolean>;
|
|
108
132
|
skill: z.ZodString;
|
|
109
133
|
agent: z.ZodEnum<{
|
|
110
134
|
"claude-code": "claude-code";
|
|
@@ -119,6 +143,8 @@ export declare const RegistryEntrySchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
119
143
|
export declare const RegistrySchema: z.ZodObject<{
|
|
120
144
|
version: z.ZodLiteral<1>;
|
|
121
145
|
deployments: z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
146
|
+
surfaceId: z.ZodOptional<z.ZodString>;
|
|
147
|
+
migratedFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
122
148
|
kind: z.ZodLiteral<"skill-dir">;
|
|
123
149
|
source: z.ZodString;
|
|
124
150
|
skill: z.ZodString;
|
|
@@ -136,6 +162,8 @@ export declare const RegistrySchema: z.ZodObject<{
|
|
|
136
162
|
}>>;
|
|
137
163
|
deployed: z.ZodString;
|
|
138
164
|
}, z.core.$strip>, z.ZodObject<{
|
|
165
|
+
surfaceId: z.ZodOptional<z.ZodString>;
|
|
166
|
+
migratedFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
139
167
|
kind: z.ZodLiteral<"file-write">;
|
|
140
168
|
source: z.ZodString;
|
|
141
169
|
skill: z.ZodString;
|
|
@@ -149,6 +177,8 @@ export declare const RegistrySchema: z.ZodObject<{
|
|
|
149
177
|
}>;
|
|
150
178
|
deployed: z.ZodString;
|
|
151
179
|
}, z.core.$strip>, z.ZodObject<{
|
|
180
|
+
surfaceId: z.ZodOptional<z.ZodString>;
|
|
181
|
+
migratedFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
152
182
|
kind: z.ZodLiteral<"config-patch">;
|
|
153
183
|
patch: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
154
184
|
undoPatch: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
@@ -163,7 +193,13 @@ export declare const RegistrySchema: z.ZodObject<{
|
|
|
163
193
|
}>;
|
|
164
194
|
deployed: z.ZodString;
|
|
165
195
|
}, z.core.$strip>, z.ZodObject<{
|
|
196
|
+
surfaceId: z.ZodOptional<z.ZodString>;
|
|
197
|
+
migratedFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
166
198
|
kind: z.ZodLiteral<"frontmatter-emit">;
|
|
199
|
+
patch: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
200
|
+
undoPatch: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
201
|
+
created: z.ZodOptional<z.ZodBoolean>;
|
|
202
|
+
hadFrontmatter: z.ZodOptional<z.ZodBoolean>;
|
|
167
203
|
skill: z.ZodString;
|
|
168
204
|
agent: z.ZodEnum<{
|
|
169
205
|
"claude-code": "claude-code";
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { AgentIdSchema } from "./manifest.js";
|
|
3
|
-
const
|
|
3
|
+
const RegistryOwnershipMetadataSchema = z.object({
|
|
4
|
+
surfaceId: z.string().optional(),
|
|
5
|
+
migratedFrom: z.array(z.string()).optional(),
|
|
6
|
+
});
|
|
7
|
+
const SkillDirRegistryEntrySchema = RegistryOwnershipMetadataSchema.extend({
|
|
4
8
|
kind: z.literal("skill-dir"),
|
|
5
9
|
source: z.string(),
|
|
6
10
|
skill: z.string(),
|
|
@@ -8,14 +12,14 @@ const SkillDirRegistryEntrySchema = z.object({
|
|
|
8
12
|
method: z.enum(["symlink", "copy"]).optional(),
|
|
9
13
|
deployed: z.string(),
|
|
10
14
|
});
|
|
11
|
-
const FileWriteRegistryEntrySchema =
|
|
15
|
+
const FileWriteRegistryEntrySchema = RegistryOwnershipMetadataSchema.extend({
|
|
12
16
|
kind: z.literal("file-write"),
|
|
13
17
|
source: z.string(),
|
|
14
18
|
skill: z.string(),
|
|
15
19
|
agent: AgentIdSchema,
|
|
16
20
|
deployed: z.string(),
|
|
17
21
|
});
|
|
18
|
-
const ConfigPatchRegistryEntrySchema =
|
|
22
|
+
const ConfigPatchRegistryEntrySchema = RegistryOwnershipMetadataSchema.extend({
|
|
19
23
|
kind: z.literal("config-patch"),
|
|
20
24
|
patch: z.record(z.string(), z.unknown()),
|
|
21
25
|
undoPatch: z.record(z.string(), z.unknown()),
|
|
@@ -23,8 +27,12 @@ const ConfigPatchRegistryEntrySchema = z.object({
|
|
|
23
27
|
agent: AgentIdSchema,
|
|
24
28
|
deployed: z.string(),
|
|
25
29
|
});
|
|
26
|
-
const FrontmatterEmitRegistryEntrySchema =
|
|
30
|
+
const FrontmatterEmitRegistryEntrySchema = RegistryOwnershipMetadataSchema.extend({
|
|
27
31
|
kind: z.literal("frontmatter-emit"),
|
|
32
|
+
patch: z.record(z.string(), z.unknown()).optional(),
|
|
33
|
+
undoPatch: z.record(z.string(), z.unknown()).optional(),
|
|
34
|
+
created: z.boolean().optional(),
|
|
35
|
+
hadFrontmatter: z.boolean().optional(),
|
|
28
36
|
skill: z.string(),
|
|
29
37
|
agent: AgentIdSchema,
|
|
30
38
|
deployed: z.string(),
|
|
@@ -5,6 +5,7 @@ export interface AgentPaths {
|
|
|
5
5
|
windows: string[];
|
|
6
6
|
}
|
|
7
7
|
export type Confidence = "documented" | "implementation-only" | "provisional";
|
|
8
|
+
export type CapabilityKind = "skills" | "mcpServers" | "agentRules" | "permissions" | "agentDefinitions";
|
|
8
9
|
export interface SupportedAgentSurface {
|
|
9
10
|
status: "supported";
|
|
10
11
|
/**
|
|
@@ -90,12 +91,23 @@ export interface AgentConfig {
|
|
|
90
91
|
detectBinary: string | null;
|
|
91
92
|
provenance: AgentProvenance;
|
|
92
93
|
mcpSupport?: AgentSurfaceSupport;
|
|
94
|
+
mcpRepoSupport?: AgentSurfaceSupport;
|
|
95
|
+
mcpWorkspaceSupport?: AgentSurfaceSupport;
|
|
93
96
|
agentRulesSupport?: AgentSurfaceSupport;
|
|
94
97
|
agentRulesRepoSupport?: AgentSurfaceSupport;
|
|
95
98
|
agentRulesWorkspaceSupport?: AgentSurfaceSupport;
|
|
96
99
|
permissionsSupport?: AgentSurfaceSupport;
|
|
97
100
|
agentDefinitionsSupport?: AgentSurfaceSupport;
|
|
101
|
+
agentDefinitionsRepoSupport?: AgentSurfaceSupport;
|
|
102
|
+
agentDefinitionsWorkspaceSupport?: AgentSurfaceSupport;
|
|
103
|
+
agentDefinitionsTomlSupport?: AgentSurfaceSupport;
|
|
104
|
+
agentDefinitionsTomlRepoSupport?: AgentSurfaceSupport;
|
|
98
105
|
policyNote?: string;
|
|
106
|
+
/**
|
|
107
|
+
* A list of documented surfaces that are currently not safe to support directly.
|
|
108
|
+
* Preflight will emit warnings for these if the agent is targeted.
|
|
109
|
+
*/
|
|
110
|
+
unsupportedSurfaces?: AgentSurfaceSupport[];
|
|
99
111
|
/**
|
|
100
112
|
* When true, instruction files deployed to this agent must include valid
|
|
101
113
|
* YAML frontmatter. Drives validateInstructionFileRequirements without
|
|
@@ -127,6 +139,7 @@ export interface FileWriteDeployAction {
|
|
|
127
139
|
source: string;
|
|
128
140
|
target: string;
|
|
129
141
|
confidence?: Confidence;
|
|
142
|
+
migratedFrom?: string[];
|
|
130
143
|
}
|
|
131
144
|
export interface ConfigPatchDeployAction {
|
|
132
145
|
kind: "config-patch";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { access, mkdir } from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
export async function exists(p) {
|
|
5
|
+
try {
|
|
6
|
+
await access(p);
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export async function makeTmpDir(prefix = "ie-test-dir") {
|
|
14
|
+
const dir = path.join(os.tmpdir(), `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
15
|
+
await mkdir(dir, { recursive: true });
|
|
16
|
+
return dir;
|
|
17
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize path separators to forward slashes for cross-platform path assertions.
|
|
3
|
+
* Use this instead of hard-coding POSIX separators in expected strings.
|
|
4
|
+
*/
|
|
5
|
+
export declare function normalizeSlashes(value: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Assert that a path ends with the given POSIX-style suffix, normalizing separators.
|
|
8
|
+
* Use instead of: assert.ok(normalizeSlashes(p).endsWith("some/suffix"))
|
|
9
|
+
*/
|
|
10
|
+
export declare function assertPathEndsWith(actual: string, suffix: string, msg?: string): void;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
/**
|
|
3
|
+
* Normalize path separators to forward slashes for cross-platform path assertions.
|
|
4
|
+
* Use this instead of hard-coding POSIX separators in expected strings.
|
|
5
|
+
*/
|
|
6
|
+
export function normalizeSlashes(value) {
|
|
7
|
+
return value.replaceAll("\\", "/");
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Assert that a path ends with the given POSIX-style suffix, normalizing separators.
|
|
11
|
+
* Use instead of: assert.ok(normalizeSlashes(p).endsWith("some/suffix"))
|
|
12
|
+
*/
|
|
13
|
+
export function assertPathEndsWith(actual, suffix, msg) {
|
|
14
|
+
assert.ok(normalizeSlashes(actual).endsWith(suffix), msg ?? `Expected path "${actual}" to end with "${suffix}"`);
|
|
15
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
interface SkillDirScenarioOptions {
|
|
2
|
+
method: "symlink" | "copy";
|
|
3
|
+
assertManagedTarget(target: string, source: string, expectedSkillMd: string): Promise<void>;
|
|
4
|
+
}
|
|
5
|
+
export declare function registerSharedSkillDirDeployScenarios(options: SkillDirScenarioOptions): void;
|
|
6
|
+
export declare function registerSharedSkillDirRevertScenarios(options: SkillDirScenarioOptions): void;
|
|
7
|
+
export {};
|