@jstn-sdk/ma 0.1.13 → 0.14.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/.agents/plugins/marketplace.json +0 -0
- package/.codex/agents/Architect.toml +1 -0
- package/.codex/agents/Auditor.toml +1 -0
- package/.codex/agents/Builder.toml +1 -0
- package/.codex/agents/Flow.toml +1 -0
- package/.codex/agents/Sage.toml +1 -0
- package/.codex/agents/Vibe.toml +1 -0
- package/.codex/hooks.json +12 -2
- package/.codex/prompts/enforcement.md +0 -0
- package/.codex/prompts/onboarding.md +6 -1
- package/.codex/prompts/release-rules.md +0 -0
- package/.codex/prompts/skill-contract.md +0 -0
- package/COVERAGE.md +7 -7
- package/DEMO.md +15 -6
- package/LICENSE +0 -0
- package/README.md +126 -793
- package/bin/ma.js +585 -97
- package/data/clone-data.ledger.json +0 -0
- package/data/clone-data.proof.json +0 -0
- package/data/clone-data.rvf +0 -0
- package/docs/README.md +8 -2
- package/docs/autonomous-tasks.md +46 -0
- package/docs/codex-integration.md +16 -0
- package/docs/getting-started.md +28 -4
- package/docs/installed-sdk.md +0 -0
- package/docs/mcp-setup.md +30 -1
- package/docs/qa/{release-issue-gates-0.1.13.json → release-issue-gates-0.14.0.json} +77 -77
- package/docs/qa/release-readiness-0.1.5.md +0 -0
- package/docs/qa/{release-readiness-0.1.13.md → release-readiness-0.14.0.md} +12 -12
- package/docs/quality.md +24 -0
- package/docs/reference/native-engineering-patterns.md +0 -0
- package/docs/reference/native-security-playbooks.md +0 -0
- package/docs/reference/native-source-selection.md +0 -0
- package/docs/reference/native-style-and-deslop.md +0 -0
- package/docs/release-spec.md +27 -14
- package/docs/skills.md +1 -1
- package/index.js +73 -0
- package/mcp/collections.json +0 -0
- package/mcp/fallback.json +0 -0
- package/mcp/local/code-intel.js +179 -41
- package/mcp/local/context.js +180 -0
- package/mcp/local/memory.js +17 -6
- package/mcp/local/playbooks.js +0 -0
- package/mcp/local/quality.js +39 -0
- package/mcp/local/state.js +7 -3
- package/mcp/local/team-run.js +8 -3
- package/mcp/local/trace.js +0 -0
- package/mcp/local-capabilities.json +9 -0
- package/mcp/native-playbooks.json +0 -0
- package/mcp/servers.json +0 -0
- package/package.json +26 -4
- package/plugins/meta-architect/.app.json +1 -1
- package/plugins/meta-architect/.codex-plugin/plugin.json +1 -1
- package/plugins/meta-architect/.mcp.json +1 -1
- package/plugins/meta-architect/README.md +2 -2
- package/plugins/meta-architect/obsidian/main.js +137 -4
- package/plugins/meta-architect/obsidian/manifest.json +1 -1
- package/plugins/meta-architect/obsidian/styles.css +0 -0
- package/plugins/meta-architect/skills/align/SKILL.md +0 -0
- package/plugins/meta-architect/skills/align/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/align/references/shared-language.md +0 -0
- package/plugins/meta-architect/skills/arch/SKILL.md +0 -0
- package/plugins/meta-architect/skills/arch/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/build/SKILL.md +0 -0
- package/plugins/meta-architect/skills/build/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/cleanup/SKILL.md +0 -0
- package/plugins/meta-architect/skills/cleanup/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/cleanup/references/style-and-deslop.md +0 -0
- package/plugins/meta-architect/skills/diagnose/SKILL.md +0 -0
- package/plugins/meta-architect/skills/diagnose/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/flow/SKILL.md +0 -0
- package/plugins/meta-architect/skills/flow/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/maestro/SKILL.md +0 -0
- package/plugins/meta-architect/skills/maestro/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/maestro/references/core-release-rules.md +0 -0
- package/plugins/meta-architect/skills/maestro/references/native-ingest-map.md +0 -0
- package/plugins/meta-architect/skills/sage/SKILL.md +0 -0
- package/plugins/meta-architect/skills/sage/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/sage/references/source-selection.md +0 -0
- package/plugins/meta-architect/skills/tdd/SKILL.md +0 -0
- package/plugins/meta-architect/skills/tdd/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/vet/SKILL.md +0 -0
- package/plugins/meta-architect/skills/vet/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/vet/references/security-playbooks.md +0 -0
- package/plugins/meta-architect/skills/vibe/SKILL.md +0 -0
- package/plugins/meta-architect/skills/vibe/agents/openai.yaml +0 -0
- package/schemas/autonomous-task-queue.schema.json +56 -0
- package/schemas/handoff-packet.schema.json +36 -0
- package/schemas/setup-receipt.schema.json +28 -0
- package/schemas/skill-frontmatter.schema.json +20 -0
- package/schemas/support-bundle.schema.json +37 -0
- package/schemas/task-contract.schema.json +31 -0
- package/scripts/active-autonomy-hook.mjs +141 -11
- package/scripts/biome-staged.js +0 -0
- package/scripts/build-linux-packages.mjs +7 -3
- package/scripts/cleanup-test-fixtures.sh +55 -0
- package/scripts/context-hydration-hook.mjs +89 -0
- package/scripts/demo-smoke.js +285 -0
- package/scripts/doctor.js +10 -8
- package/scripts/install.sh +33 -4
- package/scripts/install.sh.sha256 +1 -0
- package/scripts/linux-package-lib.mjs +0 -0
- package/scripts/linux-package-smoke.mjs +2 -2
- package/scripts/package-size-check.mjs +26 -0
- package/scripts/plugin-sync.js +83 -17
- package/scripts/postinstall.js +17 -10
- package/scripts/prepack.js +9 -0
- package/scripts/ralph/prompt.md +0 -0
- package/scripts/release-metadata.js +0 -0
- package/scripts/release-sync.js +72 -7
- package/scripts/release-verify.js +100 -7
- package/scripts/setup-npmrc.js +48 -23
- package/scripts/skills-install.js +9 -2
- package/scripts/skills-manifest.js +2 -21
- package/scripts/skills-pack.js +2 -2
- package/scripts/skills-validate.js +5 -55
- package/skills/align/SKILL.md +0 -0
- package/skills/align/agents/openai.yaml +0 -0
- package/skills/align/references/shared-language.md +0 -0
- package/skills/arch/SKILL.md +0 -0
- package/skills/arch/agents/openai.yaml +0 -0
- package/skills/build/SKILL.md +0 -0
- package/skills/build/agents/openai.yaml +0 -0
- package/skills/cleanup/SKILL.md +0 -0
- package/skills/cleanup/agents/openai.yaml +0 -0
- package/skills/cleanup/references/style-and-deslop.md +0 -0
- package/skills/diagnose/SKILL.md +0 -0
- package/skills/diagnose/agents/openai.yaml +0 -0
- package/skills/flow/SKILL.md +0 -0
- package/skills/flow/agents/openai.yaml +0 -0
- package/skills/index.json +0 -0
- package/skills/maestro/SKILL.md +0 -0
- package/skills/maestro/agents/openai.yaml +0 -0
- package/skills/maestro/references/core-release-rules.md +0 -0
- package/skills/maestro/references/native-ingest-map.md +0 -0
- package/skills/sage/SKILL.md +0 -0
- package/skills/sage/agents/openai.yaml +0 -0
- package/skills/sage/references/source-selection.md +0 -0
- package/skills/tdd/SKILL.md +0 -0
- package/skills/tdd/agents/openai.yaml +0 -0
- package/skills/vet/SKILL.md +0 -0
- package/skills/vet/agents/openai.yaml +0 -0
- package/skills/vet/references/security-playbooks.md +0 -0
- package/skills/vibe/SKILL.md +0 -0
- package/skills/vibe/agents/openai.yaml +0 -0
- package/sprint/00-idea.md +0 -0
- package/sprint/01-architecture.md +0 -0
- package/sprint/02-oss-evidence.md +0 -0
- package/sprint/03-logic.md +0 -0
- package/sprint/04-security.md +0 -0
- package/sprint/05-dx-ux.md +0 -0
- package/sprint/06-build-plan.md +0 -0
- package/sprint/07-release.md +0 -0
- package/src/agents.js +279 -0
- package/src/bootstrap.js +252 -63
- package/src/build-gate.js +0 -0
- package/src/codex-app-server.js +291 -0
- package/src/decision-log.js +0 -0
- package/src/fs-utils.js +175 -4
- package/src/launcher.js +24 -21
- package/src/mcp-config.js +9 -1
- package/src/mcp-live-client.js +140 -7
- package/src/paths.js +6 -1
- package/src/policy.js +2 -2
- package/src/prelaunch.js +189 -0
- package/src/quality/ai-quality-orchestrator.js +328 -0
- package/src/release-issue-gates.js +62 -0
- package/src/release-operations.js +62 -0
- package/src/release-state.js +0 -0
- package/src/runtime/active-autonomy-core.js +0 -0
- package/src/runtime/agent-compat.js +31 -0
- package/src/runtime/alignment-sentinel.js +0 -0
- package/src/runtime/architect-review.js +248 -10
- package/src/runtime/autonomous-tasks.js +408 -0
- package/src/runtime/build-readiness.js +0 -0
- package/src/runtime/code-graph-rehearse.js +0 -0
- package/src/runtime/codeburn-core.js +112 -0
- package/src/runtime/context-authority.js +40 -0
- package/src/runtime/context-economy-core.js +40 -0
- package/src/runtime/continuity-graph.js +201 -0
- package/src/runtime/continuity-notes.js +71 -26
- package/src/runtime/core-source-ingest.js +0 -0
- package/src/runtime/detached-provider.js +82 -14
- package/src/runtime/doctor-report.js +18 -0
- package/src/runtime/environment-awareness-core.js +0 -0
- package/src/runtime/exposure-catalog.js +0 -0
- package/src/runtime/graphify-core.js +167 -0
- package/src/runtime/guidance-stack.js +9 -2
- package/src/runtime/handoff-packets.js +92 -0
- package/src/runtime/headroom-core.js +104 -0
- package/src/runtime/helper-orchestration-core.js +0 -0
- package/src/runtime/hook-profiles.js +20 -0
- package/src/runtime/learning-loop-core.js +110 -4
- package/src/runtime/live-agent-verification.js +122 -0
- package/src/runtime/maestro-events.js +0 -0
- package/src/runtime/maestro-manager.js +0 -0
- package/src/runtime/maestro-output.js +58 -0
- package/src/runtime/maestro-state.js +0 -0
- package/src/runtime/managed-markdown.js +29 -0
- package/src/runtime/mcp-authority.js +147 -0
- package/src/runtime/mcp-policy.js +0 -0
- package/src/runtime/obsidian-integration-core.js +255 -17
- package/src/runtime/obsidian-plugin-bridge.js +344 -38
- package/src/runtime/orchestrator.js +0 -0
- package/src/runtime/pi-maestro-core.js +89 -0
- package/src/runtime/preferences.js +79 -0
- package/src/runtime/project-context.js +636 -0
- package/src/runtime/prompt-strategy-core.js +0 -0
- package/src/runtime/quorum-review.js +0 -0
- package/src/runtime/ralph-execution-core.js +0 -0
- package/src/runtime/redaction-gateway.js +218 -19
- package/src/runtime/runtime-state.js +94 -2
- package/src/runtime/schema-migrations.js +162 -0
- package/src/runtime/semantic-recording-core.js +0 -0
- package/src/runtime/signal-hooks.js +13 -0
- package/src/runtime/skills-registry-export.js +92 -8
- package/src/runtime/startup-path.js +0 -0
- package/src/runtime/task-contracts.js +83 -0
- package/src/runtime/universal-plugin-broker-core.js +373 -50
- package/src/runtime/workspace-intelligence-runtime.js +0 -0
- package/src/runtime/workspace-virtualizer.js +0 -0
- package/src/runtime/workspaces.js +0 -0
- package/src/runtime-artifacts.js +0 -0
- package/src/setup-lifecycle.js +359 -0
- package/src/skill-frontmatter.js +78 -0
- package/src/skill-installer.js +226 -71
- package/src/skills.js +297 -19
- package/src/state-sync.js +0 -0
- package/src/test-fixtures.js +543 -0
- package/src/tui/grid.js +67 -0
- package/src/tui/status-grid.js +23 -0
- package/support-bundle.json +114 -0
- package/templates/AGENTS.md +6 -2
- package/templates/catalog-manifest.json +0 -0
- package/templates/model-instructions/core.md +0 -0
- package/templates/model-instructions/release.md +0 -0
- package/templates/model-instructions/security.md +0 -0
- package/templates/quality/ai-quality-rules.yml +37 -0
- package/docs/assets/image/Screenshot(1).png +0 -0
- package/docs/assets/image/Screenshot(2).png +0 -0
- package/docs/assets/image/Screenshot(3).png +0 -0
- package/docs/assets/image/Screenshot(4).png +0 -0
- package/docs/assets/image/Screenshot(5).png +0 -0
- package/docs/assets/image/Screenshot(6).png +0 -0
- package/docs/assets/image/Screenshot(7).png +0 -0
- package/docs/assets/image/Screenshot(8).png +0 -0
- package/docs/assets/image/Screenshot(9).png +0 -0
- package/docs/assets/meta-architect-logo.png +0 -0
- package/docs/assets/meta-architect-logo.svg +0 -8
- package/docs/onboarding.md +0 -81
- package/docs/prompt-guidance-contract.md +0 -17
- package/docs/prompt-guidance-fragments/active-autonomy-core.md +0 -7
- package/docs/skills-publishing.md +0 -255
package/src/skill-installer.js
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
1
2
|
import fs from "node:fs/promises";
|
|
2
3
|
import os from "node:os";
|
|
3
4
|
import path from "node:path";
|
|
5
|
+
import { getAgent } from "./agents.js";
|
|
4
6
|
import { getBundledDocsPath, packageRoot } from "./paths.js";
|
|
5
7
|
|
|
6
8
|
function resolveCodexHome() {
|
|
7
9
|
return process.env.CODEX_HOME ?? path.join(os.homedir(), ".codex");
|
|
8
10
|
}
|
|
9
11
|
|
|
10
|
-
function resolveSkillInstallRoot() {
|
|
12
|
+
function resolveSkillInstallRoot(agentType = "codex") {
|
|
13
|
+
const agent = getAgent(agentType);
|
|
14
|
+
if (agentType !== "codex" && agent.globalSkillsDir?.startsWith("~/")) {
|
|
15
|
+
return path.join(os.homedir(), agent.globalSkillsDir.slice(2));
|
|
16
|
+
}
|
|
11
17
|
return path.join(resolveCodexHome(), "skills");
|
|
12
18
|
}
|
|
13
19
|
|
|
@@ -15,14 +21,16 @@ function resolveSupportBundleRoot() {
|
|
|
15
21
|
return path.join(resolveCodexHome(), "meta-architect-sdk");
|
|
16
22
|
}
|
|
17
23
|
|
|
18
|
-
async function copyDir(src, dest) {
|
|
24
|
+
async function copyDir(src, dest, { omitIndex = false } = {}) {
|
|
19
25
|
await fs.mkdir(dest, { recursive: true });
|
|
20
26
|
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
21
27
|
for (const entry of entries) {
|
|
28
|
+
if (omitIndex && entry.name === "index.json") continue;
|
|
22
29
|
const srcPath = path.join(src, entry.name);
|
|
23
30
|
const destPath = path.join(dest, entry.name);
|
|
24
|
-
|
|
25
|
-
|
|
31
|
+
const sourceStat = entry.isSymbolicLink() ? await fs.stat(srcPath) : entry;
|
|
32
|
+
if (sourceStat.isDirectory()) {
|
|
33
|
+
await copyDir(srcPath, destPath, { omitIndex });
|
|
26
34
|
} else {
|
|
27
35
|
await fs.copyFile(srcPath, destPath);
|
|
28
36
|
}
|
|
@@ -38,8 +46,55 @@ async function pathExists(targetPath) {
|
|
|
38
46
|
}
|
|
39
47
|
}
|
|
40
48
|
|
|
41
|
-
|
|
42
|
-
|
|
49
|
+
async function listFiles(root, current = root, output = []) {
|
|
50
|
+
const entries = await fs.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
51
|
+
for (const entry of entries) {
|
|
52
|
+
if (entry.name === ".ma-install-receipt.json" || entry.name === ".ma-backups") continue;
|
|
53
|
+
const absolute = path.join(current, entry.name);
|
|
54
|
+
if (entry.isDirectory()) await listFiles(root, absolute, output);
|
|
55
|
+
else if (entry.isFile()) output.push(path.relative(root, absolute));
|
|
56
|
+
}
|
|
57
|
+
return output.sort();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function treeHash(root) {
|
|
61
|
+
const hash = crypto.createHash("sha256");
|
|
62
|
+
for (const relative of await listFiles(root)) {
|
|
63
|
+
hash.update(relative);
|
|
64
|
+
hash.update(await fs.readFile(path.join(root, relative)));
|
|
65
|
+
}
|
|
66
|
+
return hash.digest("hex");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export async function readInstallReceipt(root, kind = "skills") {
|
|
70
|
+
try {
|
|
71
|
+
return JSON.parse(await fs.readFile(installReceiptPath(root, kind), "utf8"));
|
|
72
|
+
} catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function installReceiptPath(root, kind = "skills") {
|
|
78
|
+
if (kind === "skills" && path.basename(root) === "skills") {
|
|
79
|
+
return path.join(path.dirname(root), ".ma", "codex-skills-install-receipt.json");
|
|
80
|
+
}
|
|
81
|
+
return path.join(root, ".ma-install-receipt.json");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function writeInstallReceipt(root, receipt, kind = "skills") {
|
|
85
|
+
const receiptPath = installReceiptPath(root, kind);
|
|
86
|
+
await fs.mkdir(path.dirname(receiptPath), { recursive: true });
|
|
87
|
+
await fs.writeFile(receiptPath, `${JSON.stringify(receipt, null, 2)}\n`, { mode: 0o600 });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function backupPath(root, source, label) {
|
|
91
|
+
const backupRoot = path.join(root, ".ma-backups", `${Date.now()}-${label}`);
|
|
92
|
+
await copyPath(source, backupRoot);
|
|
93
|
+
return backupRoot;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function getSkillInstallRoot(agentType = "codex") {
|
|
97
|
+
return resolveSkillInstallRoot(agentType);
|
|
43
98
|
}
|
|
44
99
|
|
|
45
100
|
export function getSupportBundleRoot() {
|
|
@@ -55,24 +110,59 @@ export async function loadSkillManifest() {
|
|
|
55
110
|
export async function installSkills({ targetRoot = getSkillInstallRoot() } = {}) {
|
|
56
111
|
const skills = await loadSkillManifest();
|
|
57
112
|
await fs.mkdir(targetRoot, { recursive: true });
|
|
113
|
+
const previous = await readInstallReceipt(targetRoot, "skills");
|
|
114
|
+
const managed = new Set(previous?.managedPaths ?? []);
|
|
58
115
|
|
|
59
116
|
const installed = [];
|
|
117
|
+
const conflicts = [];
|
|
118
|
+
const backups = [];
|
|
60
119
|
for (const skill of skills) {
|
|
61
120
|
const src = path.join(packageRoot, skill.path);
|
|
62
121
|
const dest = path.join(targetRoot, path.basename(skill.path));
|
|
63
|
-
await
|
|
64
|
-
|
|
65
|
-
|
|
122
|
+
if (await pathExists(dest)) {
|
|
123
|
+
if (!managed.has(path.basename(skill.path))) {
|
|
124
|
+
conflicts.push({ name: skill.name, dest, reason: "existing-unmanaged-path" });
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
backups.push({
|
|
128
|
+
name: skill.name,
|
|
129
|
+
path: await backupPath(targetRoot, dest, path.basename(skill.path)),
|
|
130
|
+
});
|
|
131
|
+
await fs.rm(dest, { recursive: true, force: true });
|
|
132
|
+
}
|
|
133
|
+
await copyDir(src, dest, {
|
|
134
|
+
omitIndex: dest.endsWith(path.join("plugins", "meta-architect", "skills")),
|
|
135
|
+
});
|
|
136
|
+
installed.push({ name: skill.name, dest, hash: await treeHash(dest) });
|
|
66
137
|
}
|
|
67
138
|
|
|
68
|
-
|
|
139
|
+
await writeInstallReceipt(
|
|
140
|
+
targetRoot,
|
|
141
|
+
{
|
|
142
|
+
schemaVersion: "1.0.0",
|
|
143
|
+
record_type: "codex_skill_install_receipt",
|
|
144
|
+
packageName: "@jstn-sdk/ma",
|
|
145
|
+
packageVersion: JSON.parse(await fs.readFile(path.join(packageRoot, "package.json"), "utf8"))
|
|
146
|
+
.version,
|
|
147
|
+
installedAt: new Date().toISOString(),
|
|
148
|
+
managedPaths: installed.map((entry) => path.basename(entry.dest)),
|
|
149
|
+
installed,
|
|
150
|
+
conflicts,
|
|
151
|
+
backups,
|
|
152
|
+
},
|
|
153
|
+
"skills",
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
return { targetRoot, installed, conflicts, backups };
|
|
69
157
|
}
|
|
70
158
|
|
|
71
159
|
async function copyPath(src, dest) {
|
|
72
160
|
const stat = await fs.stat(src);
|
|
73
161
|
if (stat.isDirectory()) {
|
|
74
162
|
await fs.rm(dest, { recursive: true, force: true });
|
|
75
|
-
await copyDir(src, dest
|
|
163
|
+
await copyDir(src, dest, {
|
|
164
|
+
omitIndex: dest.endsWith(path.join("plugins", "meta-architect", "skills")),
|
|
165
|
+
});
|
|
76
166
|
return "directory";
|
|
77
167
|
}
|
|
78
168
|
|
|
@@ -81,80 +171,143 @@ async function copyPath(src, dest) {
|
|
|
81
171
|
return "file";
|
|
82
172
|
}
|
|
83
173
|
|
|
84
|
-
export async function
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
{
|
|
107
|
-
|
|
108
|
-
src: path.join(packageRoot, "plugins", "meta-architect"),
|
|
109
|
-
dest: path.join(targetRoot, "plugins", "meta-architect"),
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
name: "templates",
|
|
113
|
-
src: path.join(packageRoot, "templates"),
|
|
114
|
-
dest: path.join(targetRoot, "templates"),
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
name: "docs-readme",
|
|
118
|
-
src: getBundledDocsPath("README.md"),
|
|
119
|
-
dest: path.join(targetRoot, "docs", "README.md"),
|
|
120
|
-
},
|
|
121
|
-
];
|
|
122
|
-
|
|
123
|
-
const optionalAssets = [
|
|
124
|
-
{
|
|
125
|
-
name: "docs-reference",
|
|
126
|
-
src: getBundledDocsPath("reference"),
|
|
127
|
-
dest: path.join(targetRoot, "docs", "reference"),
|
|
128
|
-
},
|
|
129
|
-
];
|
|
130
|
-
|
|
131
|
-
for (const asset of optionalAssets) {
|
|
132
|
-
if (await pathExists(asset.src)) {
|
|
133
|
-
assets.push(asset);
|
|
174
|
+
export async function loadSupportBundleManifest() {
|
|
175
|
+
const manifest = JSON.parse(
|
|
176
|
+
await fs.readFile(path.join(packageRoot, "support-bundle.json"), "utf8"),
|
|
177
|
+
);
|
|
178
|
+
if (
|
|
179
|
+
manifest.schemaVersion !== "1.0.0" ||
|
|
180
|
+
!/^\d+\.\d+\.\d+$/.test(manifest.bundleVersion) ||
|
|
181
|
+
manifest.compatibility?.managedBy !== "@jstn-sdk/ma" ||
|
|
182
|
+
typeof manifest.compatibility?.node !== "string"
|
|
183
|
+
) {
|
|
184
|
+
throw new Error("Invalid support bundle manifest version");
|
|
185
|
+
}
|
|
186
|
+
if (!Array.isArray(manifest.assets) || manifest.assets.length === 0) {
|
|
187
|
+
throw new Error("Support bundle manifest must define assets");
|
|
188
|
+
}
|
|
189
|
+
for (const asset of manifest.assets) {
|
|
190
|
+
if (
|
|
191
|
+
typeof asset.name !== "string" ||
|
|
192
|
+
typeof asset.source !== "string" ||
|
|
193
|
+
typeof asset.destination !== "string" ||
|
|
194
|
+
!["file", "directory"].includes(asset.type) ||
|
|
195
|
+
typeof asset.required !== "boolean"
|
|
196
|
+
) {
|
|
197
|
+
throw new Error(`Invalid support bundle asset: ${asset.name ?? "(unnamed)"}`);
|
|
134
198
|
}
|
|
135
199
|
}
|
|
200
|
+
return manifest;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export async function installSupportBundle({ targetRoot = getSupportBundleRoot() } = {}) {
|
|
204
|
+
const pkg = JSON.parse(await fs.readFile(path.join(packageRoot, "package.json"), "utf8"));
|
|
205
|
+
const bundle = await loadSupportBundleManifest();
|
|
206
|
+
if (bundle.bundleVersion !== pkg.version) {
|
|
207
|
+
throw new Error(
|
|
208
|
+
`Support bundle manifest ${bundle.bundleVersion} does not match package ${pkg.version}`,
|
|
209
|
+
);
|
|
210
|
+
}
|
|
136
211
|
|
|
137
212
|
await fs.mkdir(targetRoot, { recursive: true });
|
|
213
|
+
const previous = await readInstallReceipt(targetRoot, "support");
|
|
214
|
+
const managed = new Set(previous?.managedPaths ?? []);
|
|
138
215
|
const installed = [];
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
216
|
+
const conflicts = [];
|
|
217
|
+
const backups = [];
|
|
218
|
+
for (const asset of bundle.assets) {
|
|
219
|
+
const source =
|
|
220
|
+
asset.source === "docs/README.md"
|
|
221
|
+
? getBundledDocsPath("README.md")
|
|
222
|
+
: asset.source === "docs/reference"
|
|
223
|
+
? getBundledDocsPath("reference")
|
|
224
|
+
: path.join(packageRoot, asset.source);
|
|
225
|
+
if (!(await pathExists(source))) {
|
|
226
|
+
if (asset.required) throw new Error(`Missing required support bundle asset: ${asset.source}`);
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
const destination = path.join(targetRoot, asset.destination);
|
|
230
|
+
if (await pathExists(destination)) {
|
|
231
|
+
if (!managed.has(asset.destination)) {
|
|
232
|
+
conflicts.push({ name: asset.name, dest: destination, reason: "existing-unmanaged-path" });
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
backups.push({
|
|
236
|
+
name: asset.name,
|
|
237
|
+
path: await backupPath(targetRoot, destination, asset.name),
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
await copyPath(source, destination);
|
|
241
|
+
installed.push({
|
|
242
|
+
name: asset.name,
|
|
243
|
+
class: asset.class,
|
|
244
|
+
dest: destination,
|
|
245
|
+
relative: asset.destination,
|
|
246
|
+
});
|
|
142
247
|
}
|
|
143
248
|
|
|
144
|
-
const pkg = JSON.parse(await fs.readFile(path.join(packageRoot, "package.json"), "utf8"));
|
|
145
249
|
const manifest = {
|
|
250
|
+
schemaVersion: bundle.schemaVersion,
|
|
251
|
+
bundleVersion: bundle.bundleVersion,
|
|
146
252
|
packageName: pkg.name,
|
|
147
253
|
packageVersion: pkg.version,
|
|
148
254
|
installedAt: new Date().toISOString(),
|
|
149
255
|
root: targetRoot,
|
|
150
256
|
assets: installed,
|
|
257
|
+
conflicts,
|
|
258
|
+
backups,
|
|
151
259
|
};
|
|
152
260
|
await fs.writeFile(
|
|
153
261
|
path.join(targetRoot, "asset-manifest.json"),
|
|
154
262
|
`${JSON.stringify(manifest, null, 2)}\n`,
|
|
155
263
|
);
|
|
264
|
+
await writeInstallReceipt(
|
|
265
|
+
targetRoot,
|
|
266
|
+
{
|
|
267
|
+
...manifest,
|
|
268
|
+
record_type: "codex_support_bundle_install_receipt",
|
|
269
|
+
managedPaths: installed.map((asset) => asset.relative),
|
|
270
|
+
conflicts,
|
|
271
|
+
backups,
|
|
272
|
+
},
|
|
273
|
+
"support",
|
|
274
|
+
);
|
|
156
275
|
|
|
157
|
-
return { targetRoot, installed };
|
|
276
|
+
return { targetRoot, installed, conflicts, backups };
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export async function rollbackInstalledAssets({ targetRoot, kind = "skills" } = {}) {
|
|
280
|
+
const root = targetRoot ?? (kind === "skills" ? getSkillInstallRoot() : getSupportBundleRoot());
|
|
281
|
+
const receipt = await readInstallReceipt(root, kind);
|
|
282
|
+
if (!receipt) return { status: "nothing-to-rollback", removed: [], restored: [], skipped: [] };
|
|
283
|
+
const restored = [];
|
|
284
|
+
const removed = [];
|
|
285
|
+
const skipped = [];
|
|
286
|
+
for (const entry of receipt.installed ?? []) {
|
|
287
|
+
const relative = entry.relative ?? path.basename(entry.dest);
|
|
288
|
+
const dest = path.isAbsolute(entry.dest) ? entry.dest : path.join(root, relative);
|
|
289
|
+
if (!(await pathExists(dest))) continue;
|
|
290
|
+
if (entry.hash && (await treeHash(dest)) !== entry.hash) {
|
|
291
|
+
skipped.push({ path: dest, reason: "modified-after-install" });
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
await fs.rm(dest, { recursive: true, force: true });
|
|
295
|
+
removed.push(dest);
|
|
296
|
+
}
|
|
297
|
+
for (const backup of receipt.backups ?? []) {
|
|
298
|
+
if (!(await pathExists(backup.path))) continue;
|
|
299
|
+
const relative =
|
|
300
|
+
receipt.installed?.find((entry) => entry.name === backup.name)?.relative ?? backup.name;
|
|
301
|
+
const dest = path.join(root, relative);
|
|
302
|
+
await fs.rm(dest, { recursive: true, force: true });
|
|
303
|
+
await copyPath(backup.path, dest);
|
|
304
|
+
restored.push(dest);
|
|
305
|
+
}
|
|
306
|
+
if (kind === "support") {
|
|
307
|
+
await fs.rm(path.join(root, "asset-manifest.json"), { force: true });
|
|
308
|
+
}
|
|
309
|
+
if (skipped.length === 0) await fs.rm(installReceiptPath(root, kind), { force: true });
|
|
310
|
+
return { status: skipped.length ? "partial" : "rolled-back", removed, restored, skipped };
|
|
158
311
|
}
|
|
159
312
|
|
|
160
313
|
export async function areSkillsInstalled({ targetRoot = getSkillInstallRoot() } = {}) {
|
|
@@ -173,6 +326,8 @@ export async function areSkillsInstalled({ targetRoot = getSkillInstallRoot() }
|
|
|
173
326
|
}
|
|
174
327
|
|
|
175
328
|
export async function isSupportBundleInstalled({ targetRoot = getSupportBundleRoot() } = {}) {
|
|
329
|
+
const pkg = JSON.parse(await fs.readFile(path.join(packageRoot, "package.json"), "utf8"));
|
|
330
|
+
const bundle = await loadSupportBundleManifest();
|
|
176
331
|
const requiredFiles = [
|
|
177
332
|
path.join(targetRoot, "asset-manifest.json"),
|
|
178
333
|
path.join(targetRoot, "mcp", "servers.json"),
|
|
@@ -205,16 +360,16 @@ export async function isSupportBundleInstalled({ targetRoot = getSupportBundleRo
|
|
|
205
360
|
|
|
206
361
|
const manifestPath = path.join(targetRoot, "asset-manifest.json");
|
|
207
362
|
const manifest = JSON.parse(await fs.readFile(manifestPath, "utf8"));
|
|
363
|
+
if (manifest.schemaVersion !== "1.0.0" || manifest.bundleVersion !== pkg.version) {
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
208
366
|
const assetNames = new Set((manifest.assets ?? []).map((asset) => asset.name));
|
|
209
367
|
|
|
210
|
-
for (const
|
|
211
|
-
if (!assetNames.has(
|
|
368
|
+
for (const requiredAsset of bundle.assets.filter((asset) => asset.required)) {
|
|
369
|
+
if (!assetNames.has(requiredAsset.name)) {
|
|
212
370
|
return false;
|
|
213
371
|
}
|
|
214
372
|
}
|
|
215
|
-
if ((await pathExists(getBundledDocsPath("reference"))) && !assetNames.has("docs-reference")) {
|
|
216
|
-
return false;
|
|
217
|
-
}
|
|
218
373
|
|
|
219
374
|
return true;
|
|
220
375
|
}
|