@kuznai/inception-engine 0.19.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -22
- package/dist/{config → src/config}/agents.js +113 -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/src/core/adapters/index.js +25 -0
- 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 +82 -54
- package/dist/{core → src/core}/detect.js +2 -7
- package/dist/{core → src/core}/init.js +20 -25
- 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/src/core/preflight.js +296 -0
- package/dist/{core → src/core}/revert.js +86 -26
- package/dist/{core → src/core}/validation.js +31 -0
- package/dist/{errors.d.ts → src/errors.d.ts} +3 -1
- package/dist/{errors.js → src/errors.js} +2 -2
- 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} +15 -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/agentRules-integration.test.d.ts +1 -0
- package/dist/test/os/windows/agentRules-integration.test.js +245 -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 +1017 -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/init-fixture.test.d.ts +1 -0
- package/dist/test/unit/init-fixture.test.js +153 -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 +521 -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/core/adapters/index.js +0 -30
- package/dist/core/preflight.js +0 -168
- /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/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}/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/{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
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { cp, readFile, rm } from "node:fs/promises";
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { describe, it } from "node:test";
|
|
6
|
+
import { makeTmpDir } from "../helpers/fs.js";
|
|
7
|
+
import { assertPathEndsWith, normalizeSlashes } from "../helpers/path.js";
|
|
8
|
+
const PROJECT_ROOT = path.resolve(import.meta.dirname, "..", "..");
|
|
9
|
+
const FIXTURE_DIR = path.join(PROJECT_ROOT, "test", "fixtures", "readme-sample");
|
|
10
|
+
function run(args, env) {
|
|
11
|
+
return new Promise((resolve) => {
|
|
12
|
+
const child = spawn(process.execPath, [path.join(PROJECT_ROOT, "src", "index.ts"), ...args], {
|
|
13
|
+
cwd: PROJECT_ROOT,
|
|
14
|
+
env: { ...process.env, ...env },
|
|
15
|
+
});
|
|
16
|
+
let stdout = "";
|
|
17
|
+
let stderr = "";
|
|
18
|
+
child.stdout.on("data", (d) => {
|
|
19
|
+
stdout += d.toString();
|
|
20
|
+
});
|
|
21
|
+
child.stderr.on("data", (d) => {
|
|
22
|
+
stderr += d.toString();
|
|
23
|
+
});
|
|
24
|
+
child.on("close", (code) => {
|
|
25
|
+
resolve({ stdout, stderr, code: code ?? 1 });
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Extract the JSON manifest object from `init --plan` stdout.
|
|
31
|
+
* The output format is:
|
|
32
|
+
* [plan] Would write /path/inception.json with N skill(s), ...:
|
|
33
|
+
* <blank line>
|
|
34
|
+
* { ...json... }
|
|
35
|
+
* The [plan] prefix may include ANSI escape codes; the first `{` is
|
|
36
|
+
* reliably the start of the JSON object.
|
|
37
|
+
*/
|
|
38
|
+
function extractPlanJson(stdout) {
|
|
39
|
+
const jsonStart = stdout.indexOf("{");
|
|
40
|
+
assert.ok(jsonStart !== -1, `Could not find JSON object in --plan stdout:\n${stdout}`);
|
|
41
|
+
return JSON.parse(stdout.slice(jsonStart));
|
|
42
|
+
}
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
// Block 1: init --plan against the real limbo/ tree (read-only)
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
describe("init --plan against real limbo/ tree", () => {
|
|
47
|
+
it("emits the 4 limbo skills with all 5 agents and empty other sections", async () => {
|
|
48
|
+
const limboDir = path.join(PROJECT_ROOT, "limbo");
|
|
49
|
+
const { stdout, code } = await run(["init", limboDir, "--plan"]);
|
|
50
|
+
assert.equal(code, 0, `init --plan exited non-zero.\nstdout: ${stdout}`);
|
|
51
|
+
assert.ok(stdout.includes("[plan]"), `missing [plan] prefix:\n${stdout}`);
|
|
52
|
+
const manifest = extractPlanJson(stdout);
|
|
53
|
+
// Exactly 4 skills
|
|
54
|
+
assert.equal(manifest.skills.length, 4, `expected 4 skills, got ${manifest.skills.length}: ${JSON.stringify(manifest.skills.map((s) => s.name))}`);
|
|
55
|
+
// Names sorted alphabetically (sort before comparing - filesystem order not guaranteed)
|
|
56
|
+
const names = manifest.skills.map((s) => s.name).sort();
|
|
57
|
+
assert.deepEqual(names, [
|
|
58
|
+
"inception",
|
|
59
|
+
"interstellar",
|
|
60
|
+
"tenet",
|
|
61
|
+
"the-prestige",
|
|
62
|
+
]);
|
|
63
|
+
// Each skill has exactly the 5 portability agents (github-copilot excluded)
|
|
64
|
+
const expectedAgents = [
|
|
65
|
+
"antigravity",
|
|
66
|
+
"claude-code",
|
|
67
|
+
"codex",
|
|
68
|
+
"gemini-cli",
|
|
69
|
+
"opencode",
|
|
70
|
+
];
|
|
71
|
+
for (const skill of manifest.skills) {
|
|
72
|
+
assert.deepEqual(skill.agents.slice().sort(), expectedAgents, `skill "${skill.name}" agents mismatch: ${JSON.stringify(skill.agents)}`);
|
|
73
|
+
assertPathEndsWith(skill.path, `skills/${skill.name}`, `skill "${skill.name}" path should end with skills/${skill.name}`);
|
|
74
|
+
}
|
|
75
|
+
// All other sections are empty arrays
|
|
76
|
+
assert.deepEqual(manifest.mcpServers, [], "mcpServers should be []");
|
|
77
|
+
assert.deepEqual(manifest.agentRules, [], "agentRules should be []");
|
|
78
|
+
assert.deepEqual(manifest.agentDefinitions, [], "agentDefinitions should be []");
|
|
79
|
+
assert.deepEqual(manifest.files, [], "files should be []");
|
|
80
|
+
assert.deepEqual(manifest.configs, [], "configs should be []");
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
// Block 2: init against README-shaped fixture (copied to temp dir)
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
describe("init against readme-sample fixture", () => {
|
|
87
|
+
it("generates a manifest covering all README-documented init discovery paths", async () => {
|
|
88
|
+
const tmpDir = await makeTmpDir("ie-fixture-readme");
|
|
89
|
+
try {
|
|
90
|
+
// Copy the static fixture tree (including .claude/ hidden dir) into tmpDir
|
|
91
|
+
await cp(FIXTURE_DIR, tmpDir, { recursive: true });
|
|
92
|
+
const { stdout, code } = await run(["init", tmpDir]);
|
|
93
|
+
assert.equal(code, 0, `init exited non-zero.\nstdout: ${stdout}`);
|
|
94
|
+
const manifest = JSON.parse(await readFile(path.join(tmpDir, "inception.json"), "utf-8"));
|
|
95
|
+
// --- skills: 2 entries, github-copilot excluded per portability rules ---
|
|
96
|
+
assert.equal(manifest.skills.length, 2, `expected 2 skills, got ${manifest.skills.length}: ${JSON.stringify(manifest.skills.map((s) => s.name))}`);
|
|
97
|
+
const skillNames = manifest.skills.map((s) => s.name).sort();
|
|
98
|
+
assert.deepEqual(skillNames, ["my-skill", "other-skill"]);
|
|
99
|
+
const expectedSkillAgents = [
|
|
100
|
+
"antigravity",
|
|
101
|
+
"claude-code",
|
|
102
|
+
"codex",
|
|
103
|
+
"gemini-cli",
|
|
104
|
+
"opencode",
|
|
105
|
+
];
|
|
106
|
+
for (const skill of manifest.skills) {
|
|
107
|
+
assert.deepEqual(skill.agents.slice().sort(), expectedSkillAgents, `skill "${skill.name}" should have all 5 agents (not github-copilot): ${JSON.stringify(skill.agents)}`);
|
|
108
|
+
assertPathEndsWith(skill.path, `skills/${skill.name}`, `skill "${skill.name}" path should end with skills/${skill.name}`);
|
|
109
|
+
}
|
|
110
|
+
// --- agentRules: 3 entries for CLAUDE.md, AGENTS.md, GEMINI.md ---
|
|
111
|
+
assert.equal(manifest.agentRules.length, 3, `expected 3 agentRules, got ${manifest.agentRules.length}: ${JSON.stringify(manifest.agentRules.map((r) => r.name))}`);
|
|
112
|
+
const claudeRule = manifest.agentRules.find((r) => normalizeSlashes(r.path).endsWith("CLAUDE.md"));
|
|
113
|
+
assert.ok(claudeRule, "should have an agentRules entry for CLAUDE.md");
|
|
114
|
+
assert.deepEqual(claudeRule?.agents.slice().sort(), ["claude-code"], `CLAUDE.md agents: ${JSON.stringify(claudeRule?.agents)}`);
|
|
115
|
+
assert.equal(claudeRule?.scope, "global");
|
|
116
|
+
const agentsRule = manifest.agentRules.find((r) => normalizeSlashes(r.path).endsWith("AGENTS.md"));
|
|
117
|
+
assert.ok(agentsRule, "should have an agentRules entry for AGENTS.md");
|
|
118
|
+
assert.deepEqual(agentsRule?.agents.slice().sort(), ["codex", "opencode"], `AGENTS.md agents: ${JSON.stringify(agentsRule?.agents)}`);
|
|
119
|
+
assert.equal(agentsRule?.scope, "global");
|
|
120
|
+
const geminiRule = manifest.agentRules.find((r) => normalizeSlashes(r.path).endsWith("GEMINI.md"));
|
|
121
|
+
assert.ok(geminiRule, "should have an agentRules entry for GEMINI.md");
|
|
122
|
+
assert.deepEqual(geminiRule?.agents.slice().sort(), ["gemini-cli"],
|
|
123
|
+
// antigravity is shared-via gemini-cli and excluded from init defaults
|
|
124
|
+
`GEMINI.md agents should be [gemini-cli] only: ${JSON.stringify(geminiRule?.agents)}`);
|
|
125
|
+
assert.equal(geminiRule?.scope, "global");
|
|
126
|
+
// --- mcpServers: 1 entry round-tripped from mcp-servers.json sidecar ---
|
|
127
|
+
assert.equal(manifest.mcpServers.length, 1, `expected 1 mcpServer, got ${manifest.mcpServers.length}`);
|
|
128
|
+
const mcp = manifest.mcpServers[0];
|
|
129
|
+
assert.equal(mcp.name, "my-mcp-server");
|
|
130
|
+
assert.deepEqual(mcp.agents.slice().sort(), [
|
|
131
|
+
"claude-code",
|
|
132
|
+
"codex",
|
|
133
|
+
"gemini-cli",
|
|
134
|
+
"opencode",
|
|
135
|
+
]);
|
|
136
|
+
assert.equal(mcp.config.command, "npx");
|
|
137
|
+
assert.deepEqual(mcp.config.args, ["-y", "@example/mcp-server"]);
|
|
138
|
+
// --- agentDefinitions: 1 entry from .claude/agents/ -> claude-code ---
|
|
139
|
+
assert.equal(manifest.agentDefinitions.length, 1, `expected 1 agentDefinition, got ${manifest.agentDefinitions.length}`);
|
|
140
|
+
const def = manifest.agentDefinitions[0];
|
|
141
|
+
assert.equal(def.name, "code-reviewer");
|
|
142
|
+
assert.deepEqual(def.agents, ["claude-code"]);
|
|
143
|
+
assert.equal(def.scope, "repo");
|
|
144
|
+
assertPathEndsWith(def.path, ".claude/agents/code-reviewer.md", "code-reviewer path should end with .claude/agents/code-reviewer.md");
|
|
145
|
+
// --- files and configs stay empty (no sidecar manifests for them) ---
|
|
146
|
+
assert.deepEqual(manifest.files, [], "files should be []");
|
|
147
|
+
assert.deepEqual(manifest.configs, [], "configs should be []");
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
await rm(tmpDir, { recursive: true });
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|