@jstn-sdk/ma 0.14.0 → 0.14.1
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/COVERAGE.md +9 -9
- package/DEMO.md +4 -4
- package/README.md +80 -70
- package/bin/ma.js +6 -8
- package/docs/README.md +2 -2
- package/docs/assets/banner.png +0 -0
- package/docs/getting-started.md +9 -9
- package/docs/qa/{release-issue-gates-0.14.0.json → release-issue-gates-0.14.1.json} +77 -77
- package/docs/qa/{release-readiness-0.14.0.md → release-readiness-0.14.1.md} +12 -12
- package/docs/release-spec.md +12 -12
- package/docs/vendor-plugin-publishing.md +49 -0
- package/mcp/local/code-intel.js +9 -3
- package/package.json +12 -3
- package/plugins/meta-architect/.app.json +1 -1
- package/plugins/meta-architect/.claude-plugin/plugin.json +12 -0
- package/plugins/meta-architect/.codex-plugin/plugin.json +1 -1
- package/plugins/meta-architect/.mcp.json +1 -1
- package/plugins/meta-architect/README.md +13 -1
- package/plugins/meta-architect/obsidian/manifest.json +1 -1
- package/plugins/meta-architect/skills/maestro/SKILL.md +17 -1
- package/plugins/meta-architect/skills/maestro/references/core-release-rules.md +2 -2
- package/schemas/autonomous-task-queue.schema.json +2 -0
- package/scripts/install.sh +1 -1
- package/scripts/install.sh.sha256 +1 -1
- package/scripts/plugin-build.js +314 -0
- package/scripts/plugin-publish.js +77 -0
- package/scripts/release-sync.js +11 -0
- package/scripts/release-verify.js +35 -4
- package/skills/maestro/SKILL.md +17 -1
- package/skills/maestro/references/core-release-rules.md +2 -2
- package/sprint/07-release.md +2 -2
- package/src/agents.js +4 -2
- package/src/bootstrap.js +20 -2
- package/src/codex-app-server.js +4 -4
- package/src/launcher.js +2 -2
- package/src/mcp-live-client.js +2 -2
- package/src/prelaunch.js +34 -0
- package/src/process-utils.js +62 -0
- package/src/quality/ai-quality-orchestrator.js +2 -2
- package/src/release-operations.js +14 -4
- package/src/runtime/architect-review.js +2 -2
- package/src/runtime/autonomous-tasks.js +220 -43
- package/src/runtime/codeburn-core.js +9 -3
- package/src/runtime/core-source-ingest.js +2 -2
- package/src/runtime/detached-provider.js +17 -8
- package/src/runtime/live-agent-verification.js +2 -2
- package/src/runtime/project-context.js +2 -2
- package/src/runtime/skills-registry-export.js +7 -3
- package/src/skills.js +12 -12
- package/src/test-fixtures.js +4 -4
- package/support-bundle.json +1 -1
- package/scripts/postinstall.js +0 -30
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "meta-architect",
|
|
3
|
+
"description": "Meta-Architect gated workflow skills for Claude Code.",
|
|
4
|
+
"version": "0.14.1",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "JustineDevs",
|
|
7
|
+
"url": "https://github.com/JustineDevs"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/JustineDevs/meta-architect",
|
|
10
|
+
"repository": "https://github.com/JustineDevs/meta-architect.git",
|
|
11
|
+
"license": "MIT"
|
|
12
|
+
}
|
|
@@ -48,6 +48,17 @@ Use the core repo when you want to develop Meta-Architect itself. Use the plugin
|
|
|
48
48
|
|
|
49
49
|
The plugin-facing bundle should be consumed alongside the repository’s documented packaging/install flow.
|
|
50
50
|
|
|
51
|
+
### Claude Code marketplace
|
|
52
|
+
|
|
53
|
+
This repository is the hosted marketplace. In Claude Code, add it and install the existing plugin:
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
/plugin marketplace add JustineDevs/meta-architect
|
|
57
|
+
/plugin install meta-architect@meta-architect
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The same plugin can be tested locally with `claude --plugin-dir ./plugins/meta-architect`.
|
|
61
|
+
|
|
51
62
|
Recommended CLI install for macOS, Linux, WSL, and Git-Bash:
|
|
52
63
|
|
|
53
64
|
```bash
|
|
@@ -138,7 +149,7 @@ When consuming the plugin:
|
|
|
138
149
|
The plugin version should track the release scope of the core repo.
|
|
139
150
|
|
|
140
151
|
For this repository:
|
|
141
|
-
- plugin scope is aligned to Meta-Architect `v0.14.
|
|
152
|
+
- plugin scope is aligned to Meta-Architect `v0.14.1`
|
|
142
153
|
- any breaking contract change should be versioned intentionally
|
|
143
154
|
|
|
144
155
|
The plugin is one distribution surface of the same product, not a separate product line.
|
|
@@ -151,4 +162,5 @@ The plugin is one distribution surface of the same product, not a separate produ
|
|
|
151
162
|
- [docs/mcp-setup.md](../../docs/mcp-setup.md)
|
|
152
163
|
- [.app.json](./.app.json)
|
|
153
164
|
- [.codex-plugin/plugin.json](./.codex-plugin/plugin.json)
|
|
165
|
+
- [.claude-plugin/plugin.json](./.claude-plugin/plugin.json)
|
|
154
166
|
- [.mcp.json](./.mcp.json)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "meta-architect",
|
|
3
3
|
"name": "Meta-Architect",
|
|
4
|
-
"version": "0.14.
|
|
4
|
+
"version": "0.14.1",
|
|
5
5
|
"minAppVersion": "1.5.0",
|
|
6
6
|
"description": "Connects active Obsidian notes, selections, graph metadata, canvases, attachments, and request queues to Meta-Architect vault context.",
|
|
7
7
|
"author": "JustineDevs",
|
|
@@ -7,7 +7,7 @@ description: "Use when the user wants the singular Meta-Architect in-session aut
|
|
|
7
7
|
|
|
8
8
|
## Overview
|
|
9
9
|
|
|
10
|
-
Use this skill inside Codex as the singular Meta-Architect umbrella surface and
|
|
10
|
+
Use this skill inside Codex as the singular Meta-Architect umbrella surface and persistent autonomous manager. It accepts one task or a durable batch, inspects workflow state, chooses the smallest safe next step, manages the fixed gated design-and-review sequence, and keeps resuming eligible work until each task is completed, blocked, cancelled, or failed. It never invents a second umbrella command. There is no separate shipped `$meta-architect` skill.
|
|
11
11
|
|
|
12
12
|
## Workflow
|
|
13
13
|
|
|
@@ -30,6 +30,19 @@ Use this skill inside Codex as the singular Meta-Architect umbrella surface and
|
|
|
30
30
|
- `$build`
|
|
31
31
|
5. End with a clear result shape: decision, evidence, blockers, the lane assignment if any, and the exact next trigger.
|
|
32
32
|
|
|
33
|
+
## Autonomous task loop
|
|
34
|
+
|
|
35
|
+
For a task or batch, keep the manager loop active across turns:
|
|
36
|
+
|
|
37
|
+
1. Normalize the request into the durable `.ma` task contract before dispatch.
|
|
38
|
+
2. Discover the selected host, available skills, and required lane syntax without taking ownership of user-installed assets.
|
|
39
|
+
3. Dispatch independent tasks with bounded concurrency and preserve dependency order for dependent tasks.
|
|
40
|
+
4. Inspect, implement, test, review, repair, and verify. Route a failure back to its owning lane with the failure evidence attached.
|
|
41
|
+
5. Persist checkpoints, receipts, and the next trigger after every transition so an interrupted process can resume safely.
|
|
42
|
+
6. Continue unaffected batch tasks when one task is blocked, then return a batch summary with terminal states and unresolved blockers.
|
|
43
|
+
|
|
44
|
+
Routine local work continues without asking for another prompt. Stop only for credentials, destructive actions, production or external mutations, explicit approval gates, unsafe commands, unavailable required providers, or missing verification evidence.
|
|
45
|
+
|
|
33
46
|
## Output
|
|
34
47
|
|
|
35
48
|
Produce:
|
|
@@ -43,6 +56,9 @@ Produce:
|
|
|
43
56
|
## Rules
|
|
44
57
|
|
|
45
58
|
- Prefer the smallest next step that moves the workflow forward safely.
|
|
59
|
+
- Continue eligible work until the current task or batch reaches a terminal state; do not stop after a single successful lane.
|
|
60
|
+
- Treat persisted `.ma` state as the source for resume, deduplication, dependency ordering, cancellation, and bounded retries.
|
|
61
|
+
- Keep autonomous execution bounded by task dependencies, concurrency limits, deadlines, retry limits, and explicit safety gates.
|
|
46
62
|
- Respect current gate state before recommending implementation or release work.
|
|
47
63
|
- Be explicit when more evidence, planning, or validation is still needed.
|
|
48
64
|
- Treat the in-session skill flow as primary. Use `ma ...` terminal helpers only when repo-local setup, inspection, or scripted state automation is explicitly the better support path.
|
|
@@ -8,6 +8,6 @@
|
|
|
8
8
|
- `logic_status = GREEN`
|
|
9
9
|
- `security_status = GREEN`
|
|
10
10
|
- `experience_status = GREEN` or `WAIVED`
|
|
11
|
-
- Feature work merges into `
|
|
12
|
-
- Release promotion is allowed only from `
|
|
11
|
+
- Feature work merges into `dev`, never directly into `main`.
|
|
12
|
+
- Release promotion is allowed only from `dev` or approved `release/*`.
|
|
13
13
|
- Use the helper command path only when repo-local state automation is explicitly needed; otherwise stay inside Codex and carry the gate decisions in the session.
|
|
@@ -46,6 +46,8 @@
|
|
|
46
46
|
"completedAt": { "type": ["string", "null"], "format": "date-time" },
|
|
47
47
|
"error": { "type": ["string", "null"] },
|
|
48
48
|
"blocker": { "type": ["string", "null"] },
|
|
49
|
+
"runnerPid": { "type": ["integer", "null"], "minimum": 1 },
|
|
50
|
+
"runnerId": { "type": ["string", "null"], "minLength": 1 },
|
|
49
51
|
"evidence": { "type": "array", "items": {} },
|
|
50
52
|
"selectedCapabilities": { "type": "array", "items": { "type": "object" } },
|
|
51
53
|
"invocation": { "type": ["string", "null"] }
|
package/scripts/install.sh
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
3ffac1b709bceb6343181fef3402fa3bed6a9d9067299a2938489a4d3458ad41 scripts/install.sh
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import process from "node:process";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
|
|
8
|
+
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
9
|
+
const skillsRoot = path.join(repoRoot, "skills");
|
|
10
|
+
const sourcePluginRoot = path.join(repoRoot, "plugins", "meta-architect");
|
|
11
|
+
const packageJson = JSON.parse(await fs.readFile(path.join(repoRoot, "package.json"), "utf8"));
|
|
12
|
+
|
|
13
|
+
const TARGETS = {
|
|
14
|
+
codex: {
|
|
15
|
+
support: "native",
|
|
16
|
+
description: "Codex plugin bundle with native skills, app metadata, and MCP metadata.",
|
|
17
|
+
install:
|
|
18
|
+
"Copy this directory to a Codex plugin location or load it with the host plugin loader.",
|
|
19
|
+
publish: "Publish the generated directory through the Codex plugin distribution flow.",
|
|
20
|
+
},
|
|
21
|
+
"claude-code": {
|
|
22
|
+
support: "native",
|
|
23
|
+
description: "Claude Code marketplace repository containing a native plugin source.",
|
|
24
|
+
install:
|
|
25
|
+
"/plugin marketplace add <owner>/<marketplace-repository> then /plugin install meta-architect@<marketplace>",
|
|
26
|
+
publish: "Commit this directory to a Git repository, then add it as a Claude Code marketplace.",
|
|
27
|
+
},
|
|
28
|
+
cursor: {
|
|
29
|
+
support: "native",
|
|
30
|
+
description: "Cursor marketplace repository containing native skills and rules.",
|
|
31
|
+
install: "Install the generated marketplace repository through Cursor's plugin flow.",
|
|
32
|
+
publish:
|
|
33
|
+
"Commit this directory to a Git repository and submit or distribute it as a Cursor marketplace.",
|
|
34
|
+
},
|
|
35
|
+
antigravity: {
|
|
36
|
+
support: "native",
|
|
37
|
+
description: "Antigravity plugin directory with native rules and skills.",
|
|
38
|
+
install:
|
|
39
|
+
"Copy this directory into .agents/plugins/ in the workspace or the host plugin directory.",
|
|
40
|
+
publish: "Distribute the generated plugin directory through the Antigravity plugin flow.",
|
|
41
|
+
},
|
|
42
|
+
"gemini-cli": {
|
|
43
|
+
support: "native",
|
|
44
|
+
description: "Gemini CLI extension with a context file and Agent Skills.",
|
|
45
|
+
install: "gemini extensions install <github-url-or-local-path>",
|
|
46
|
+
publish: "Push this directory to GitHub, then install it with gemini extensions install.",
|
|
47
|
+
},
|
|
48
|
+
opencode: {
|
|
49
|
+
support: "native",
|
|
50
|
+
description: "OpenCode project package using its native .opencode/skills surface.",
|
|
51
|
+
install: "Copy .opencode/skills into the OpenCode project.",
|
|
52
|
+
publish: "Distribute this directory through Git or the OpenCode package mechanism.",
|
|
53
|
+
},
|
|
54
|
+
pi: {
|
|
55
|
+
support: "native",
|
|
56
|
+
description: "Pi package surface distributed by the @jstn-sdk/ma package.",
|
|
57
|
+
install:
|
|
58
|
+
"pi install npm:@jstn-sdk/ma@<version> or pi install git:github.com/JustineDevs/meta-architect@v<version>",
|
|
59
|
+
publish: "Publish @jstn-sdk/ma once; no separate Pi package is created.",
|
|
60
|
+
},
|
|
61
|
+
openclaw: {
|
|
62
|
+
support: "portable",
|
|
63
|
+
description:
|
|
64
|
+
"OpenClaw-compatible skills bundle. No runtime plugin is invented for a skills-only source.",
|
|
65
|
+
install: "Copy skills/ into the OpenClaw workspace and load the generated AGENTS.md context.",
|
|
66
|
+
publish:
|
|
67
|
+
"Publish the bundle through the OpenClaw skills or ClawHub flow after adding a real runtime entrypoint.",
|
|
68
|
+
},
|
|
69
|
+
cline: {
|
|
70
|
+
support: "native",
|
|
71
|
+
description: "Cline project rules and native skills bundle.",
|
|
72
|
+
install: "Copy .clinerules and .cline/skills into the Cline project.",
|
|
73
|
+
publish: "Distribute the generated project bundle through Git or the Cline host flow.",
|
|
74
|
+
},
|
|
75
|
+
continue: {
|
|
76
|
+
support: "portable",
|
|
77
|
+
description: "Continue-compatible rules bundle with the portable Agent Skills baseline.",
|
|
78
|
+
install: "Copy .continue/rules and skills into the Continue project.",
|
|
79
|
+
publish: "Distribute the generated bundle through Git or the Continue configuration flow.",
|
|
80
|
+
},
|
|
81
|
+
goose: {
|
|
82
|
+
support: "portable",
|
|
83
|
+
description: "Goose-compatible portable context and skills bundle.",
|
|
84
|
+
install: "Copy AGENTS.md and skills/ into the Goose workspace.",
|
|
85
|
+
publish: "Distribute the generated bundle through Git or the Goose extension flow.",
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const supportedPluginTargets = Object.freeze(Object.keys(TARGETS));
|
|
90
|
+
|
|
91
|
+
function parseArgs(argv) {
|
|
92
|
+
const targets = [];
|
|
93
|
+
let output = path.join(repoRoot, "dist", "vendor-plugins");
|
|
94
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
95
|
+
const arg = argv[index];
|
|
96
|
+
if (arg === "--target" || arg === "--targets") {
|
|
97
|
+
targets.push(...(argv[index + 1] ?? "").split(",").filter(Boolean));
|
|
98
|
+
index += 1;
|
|
99
|
+
} else if (arg === "--output") {
|
|
100
|
+
output = path.resolve(argv[index + 1] ?? output);
|
|
101
|
+
index += 1;
|
|
102
|
+
} else if (arg === "--help" || arg === "-h") {
|
|
103
|
+
console.log("Usage: npm run plugin:build -- --targets all [--output DIR]");
|
|
104
|
+
process.exit(0);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const selected = targets.length === 0 || targets.includes("all") ? Object.keys(TARGETS) : targets;
|
|
108
|
+
for (const target of selected) {
|
|
109
|
+
if (!Object.hasOwn(TARGETS, target)) throw new Error(`Unknown plugin target: ${target}`);
|
|
110
|
+
}
|
|
111
|
+
return { output, targets: [...new Set(selected)] };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async function copyTree(source, destination) {
|
|
115
|
+
const stat = await fs.lstat(source);
|
|
116
|
+
if (stat.isSymbolicLink()) return copyTree(await fs.realpath(source), destination);
|
|
117
|
+
if (stat.isDirectory()) {
|
|
118
|
+
await fs.mkdir(destination, { recursive: true });
|
|
119
|
+
for (const entry of await fs.readdir(source)) {
|
|
120
|
+
await copyTree(path.join(source, entry), path.join(destination, entry));
|
|
121
|
+
}
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
await fs.mkdir(path.dirname(destination), { recursive: true });
|
|
125
|
+
await fs.copyFile(source, destination);
|
|
126
|
+
await fs.chmod(destination, stat.mode & 0o777);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async function writeJson(filePath, value) {
|
|
130
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
131
|
+
await fs.writeFile(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function writeText(filePath, content) {
|
|
135
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
136
|
+
await fs.writeFile(filePath, content.endsWith("\n") ? content : `${content}\n`, "utf8");
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async function copySkills(destination) {
|
|
140
|
+
await copyTree(skillsRoot, destination);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function baselineInstructions(target) {
|
|
144
|
+
return `# Meta-Architect (${target})\n\nUse the bundled Meta-Architect lanes as the canonical workflow contract:\n\n\`$arch\` -> \`$sage\` -> \`$flow\` -> \`$vet\` -> \`$vibe\` -> \`$build\`\n\nRun each lane through this host's native skill or rule loader. Do not claim a gate passed without fresh evidence.\n`;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function cursorRule() {
|
|
148
|
+
return `---\ndescription: Meta-Architect gated workflow\nglobs:\n - "**/*"\nalwaysApply: false\n---\n\nUse the Meta-Architect skills in this plugin in order: $arch, $sage, $flow, $vet, $vibe, then $build. Keep build and release work blocked until the earlier lanes have fresh evidence.\n`;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async function buildCodex(output) {
|
|
152
|
+
await copyTree(path.join(sourcePluginRoot, ".codex-plugin"), path.join(output, ".codex-plugin"));
|
|
153
|
+
await copySkills(path.join(output, "skills"));
|
|
154
|
+
for (const file of [".app.json", ".mcp.json", "README.md"]) {
|
|
155
|
+
await copyTree(path.join(sourcePluginRoot, file), path.join(output, file));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async function buildClaude(output) {
|
|
160
|
+
const plugin = path.join(output, "plugins", "meta-architect");
|
|
161
|
+
await writeJson(path.join(output, ".claude-plugin", "marketplace.json"), {
|
|
162
|
+
name: "meta-architect",
|
|
163
|
+
owner: { name: "JustineDevs", url: "https://github.com/JustineDevs" },
|
|
164
|
+
metadata: { description: "Meta-Architect gated workflow plugin", version: packageJson.version },
|
|
165
|
+
plugins: [
|
|
166
|
+
{
|
|
167
|
+
name: "meta-architect",
|
|
168
|
+
source: "./plugins/meta-architect",
|
|
169
|
+
description: TARGETS["claude-code"].description,
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
});
|
|
173
|
+
await writeJson(path.join(plugin, ".claude-plugin", "plugin.json"), {
|
|
174
|
+
name: "meta-architect",
|
|
175
|
+
description: "Meta-Architect gated workflow skills for Claude Code.",
|
|
176
|
+
version: packageJson.version,
|
|
177
|
+
author: { name: "JustineDevs", url: "https://github.com/JustineDevs" },
|
|
178
|
+
license: "MIT",
|
|
179
|
+
});
|
|
180
|
+
await copySkills(path.join(plugin, "skills"));
|
|
181
|
+
await writeText(path.join(plugin, "AGENTS.md"), baselineInstructions("Claude Code"));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async function buildCursor(output) {
|
|
185
|
+
const plugin = path.join(output, "plugins", "meta-architect");
|
|
186
|
+
await writeJson(path.join(output, ".cursor-plugin", "marketplace.json"), {
|
|
187
|
+
name: "meta-architect",
|
|
188
|
+
owner: { name: "JustineDevs", email: "justinedevs@jstn.site" },
|
|
189
|
+
metadata: { description: "Meta-Architect gated workflow plugin", version: packageJson.version },
|
|
190
|
+
plugins: [
|
|
191
|
+
{
|
|
192
|
+
name: "meta-architect",
|
|
193
|
+
source: "./plugins/meta-architect",
|
|
194
|
+
description: TARGETS.cursor.description,
|
|
195
|
+
},
|
|
196
|
+
],
|
|
197
|
+
});
|
|
198
|
+
await writeJson(path.join(plugin, ".cursor-plugin", "plugin.json"), {
|
|
199
|
+
name: "meta-architect",
|
|
200
|
+
displayName: "Meta-Architect",
|
|
201
|
+
version: packageJson.version,
|
|
202
|
+
description: "Gated workflow skills for Cursor.",
|
|
203
|
+
author: { name: "JustineDevs", email: "justinedevs@jstn.site" },
|
|
204
|
+
license: "MIT",
|
|
205
|
+
keywords: ["cursor", "plugin", "skills", "workflow"],
|
|
206
|
+
});
|
|
207
|
+
await copySkills(path.join(plugin, "skills"));
|
|
208
|
+
await writeText(path.join(plugin, "rules", "meta-architect.mdc"), cursorRule());
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
async function buildAntigravity(output) {
|
|
212
|
+
await writeJson(path.join(output, "plugin.json"), {
|
|
213
|
+
name: "meta-architect",
|
|
214
|
+
version: packageJson.version,
|
|
215
|
+
});
|
|
216
|
+
await copySkills(path.join(output, "skills"));
|
|
217
|
+
await writeText(
|
|
218
|
+
path.join(output, "rules", "meta-architect.md"),
|
|
219
|
+
baselineInstructions("Antigravity"),
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async function buildGemini(output) {
|
|
224
|
+
await writeJson(path.join(output, "gemini-extension.json"), {
|
|
225
|
+
name: "meta-architect",
|
|
226
|
+
version: packageJson.version,
|
|
227
|
+
description: "Meta-Architect gated workflow skills for Gemini CLI.",
|
|
228
|
+
contextFileName: "GEMINI.md",
|
|
229
|
+
});
|
|
230
|
+
await writeText(path.join(output, "GEMINI.md"), baselineInstructions("Gemini CLI"));
|
|
231
|
+
await copySkills(path.join(output, "skills"));
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
async function buildOpenCode(output) {
|
|
235
|
+
await copySkills(path.join(output, ".opencode", "skills"));
|
|
236
|
+
await writeText(path.join(output, "AGENTS.md"), baselineInstructions("OpenCode"));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async function buildPi(output) {
|
|
240
|
+
await copySkills(path.join(output, "skills"));
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
async function buildOpenClaw(output) {
|
|
244
|
+
await copySkills(path.join(output, "skills"));
|
|
245
|
+
await writeText(path.join(output, "AGENTS.md"), baselineInstructions("OpenClaw"));
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
async function buildCline(output) {
|
|
249
|
+
await writeText(path.join(output, ".clinerules"), baselineInstructions("Cline"));
|
|
250
|
+
await copySkills(path.join(output, ".cline", "skills"));
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
async function buildContinue(output) {
|
|
254
|
+
await copySkills(path.join(output, "skills"));
|
|
255
|
+
await writeText(
|
|
256
|
+
path.join(output, ".continue", "rules", "meta-architect.md"),
|
|
257
|
+
baselineInstructions("Continue"),
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
async function buildGoose(output) {
|
|
262
|
+
await copySkills(path.join(output, "skills"));
|
|
263
|
+
await writeText(path.join(output, "AGENTS.md"), baselineInstructions("Goose"));
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const builders = {
|
|
267
|
+
codex: buildCodex,
|
|
268
|
+
"claude-code": buildClaude,
|
|
269
|
+
cursor: buildCursor,
|
|
270
|
+
antigravity: buildAntigravity,
|
|
271
|
+
"gemini-cli": buildGemini,
|
|
272
|
+
opencode: buildOpenCode,
|
|
273
|
+
pi: buildPi,
|
|
274
|
+
openclaw: buildOpenClaw,
|
|
275
|
+
cline: buildCline,
|
|
276
|
+
continue: buildContinue,
|
|
277
|
+
goose: buildGoose,
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
async function buildTarget(target, root) {
|
|
281
|
+
const output = path.join(root, target);
|
|
282
|
+
await fs.rm(output, { recursive: true, force: true });
|
|
283
|
+
await builders[target](output);
|
|
284
|
+
await writeJson(path.join(output, "BUILD-MANIFEST.json"), {
|
|
285
|
+
schemaVersion: "1.0",
|
|
286
|
+
name: "meta-architect",
|
|
287
|
+
version: packageJson.version,
|
|
288
|
+
target,
|
|
289
|
+
support: TARGETS[target].support,
|
|
290
|
+
source: "skills/",
|
|
291
|
+
description: TARGETS[target].description,
|
|
292
|
+
install: TARGETS[target].install,
|
|
293
|
+
publish: TARGETS[target].publish,
|
|
294
|
+
});
|
|
295
|
+
return output;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export async function buildPlugins({ output, targets }) {
|
|
299
|
+
await fs.mkdir(output, { recursive: true });
|
|
300
|
+
return Promise.all(targets.map((target) => buildTarget(target, output)));
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
async function main() {
|
|
304
|
+
const args = parseArgs(process.argv.slice(2));
|
|
305
|
+
const outputs = await buildPlugins(args);
|
|
306
|
+
console.log(outputs.join("\n"));
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
310
|
+
main().catch((error) => {
|
|
311
|
+
console.error(error.message);
|
|
312
|
+
process.exitCode = 1;
|
|
313
|
+
});
|
|
314
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { execFileSync } from "node:child_process";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import process from "node:process";
|
|
6
|
+
import { buildPlugins, supportedPluginTargets } from "./plugin-build.js";
|
|
7
|
+
|
|
8
|
+
const repoRoot = process.cwd();
|
|
9
|
+
const output = path.join(repoRoot, "dist", "vendor-plugins");
|
|
10
|
+
const publishers = {};
|
|
11
|
+
|
|
12
|
+
function parseArgs(argv) {
|
|
13
|
+
const targets = [];
|
|
14
|
+
let execute = false;
|
|
15
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
16
|
+
const arg = argv[index];
|
|
17
|
+
if (arg === "--target" || arg === "--targets") {
|
|
18
|
+
targets.push(...(argv[index + 1] ?? "").split(",").filter(Boolean));
|
|
19
|
+
index += 1;
|
|
20
|
+
} else if (arg === "--execute") {
|
|
21
|
+
execute = true;
|
|
22
|
+
} else if (arg === "--help" || arg === "-h") {
|
|
23
|
+
console.log("Usage: npm run plugin:publish -- --target pi [--execute]");
|
|
24
|
+
process.exit(0);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (targets.length !== 1) throw new Error("plugin:publish requires exactly one --target");
|
|
28
|
+
if (targets[0] === "all")
|
|
29
|
+
throw new Error("Publishing all hosts at once is unsafe; publish one target at a time");
|
|
30
|
+
if (!supportedPluginTargets.includes(targets[0]))
|
|
31
|
+
throw new Error(`Unknown plugin target: ${targets[0]}`);
|
|
32
|
+
return { target: targets[0], execute };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function main() {
|
|
36
|
+
const { target, execute } = parseArgs(process.argv.slice(2));
|
|
37
|
+
const [targetRoot] = await buildPlugins({ output, targets: [target] });
|
|
38
|
+
const publisher = publishers[target];
|
|
39
|
+
if (!publisher) {
|
|
40
|
+
console.log(
|
|
41
|
+
JSON.stringify(
|
|
42
|
+
{
|
|
43
|
+
target,
|
|
44
|
+
status: "prepared",
|
|
45
|
+
path: targetRoot,
|
|
46
|
+
next: "Commit the generated directory to the host marketplace or repository required by this host.",
|
|
47
|
+
},
|
|
48
|
+
null,
|
|
49
|
+
2,
|
|
50
|
+
),
|
|
51
|
+
);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!execute) {
|
|
56
|
+
console.log(
|
|
57
|
+
JSON.stringify(
|
|
58
|
+
{
|
|
59
|
+
target,
|
|
60
|
+
status: "dry-run",
|
|
61
|
+
path: targetRoot,
|
|
62
|
+
command: [publisher.command, ...publisher.args].join(" "),
|
|
63
|
+
},
|
|
64
|
+
null,
|
|
65
|
+
2,
|
|
66
|
+
),
|
|
67
|
+
);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
execFileSync(publisher.command, publisher.args, { cwd: targetRoot, stdio: "inherit" });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
main().catch((error) => {
|
|
75
|
+
console.error(error.message);
|
|
76
|
+
process.exitCode = 1;
|
|
77
|
+
});
|
package/scripts/release-sync.js
CHANGED
|
@@ -226,6 +226,7 @@ function syncPluginVersions(nextVersion) {
|
|
|
226
226
|
for (const file of [
|
|
227
227
|
path.join("plugins", "meta-architect", ".app.json"),
|
|
228
228
|
path.join("plugins", "meta-architect", ".mcp.json"),
|
|
229
|
+
path.join("plugins", "meta-architect", "obsidian", "manifest.json"),
|
|
229
230
|
]) {
|
|
230
231
|
const value = readJson(file);
|
|
231
232
|
value.version = nextVersion;
|
|
@@ -236,6 +237,16 @@ function syncPluginVersions(nextVersion) {
|
|
|
236
237
|
const pluginManifest = readJson(pluginManifestFile);
|
|
237
238
|
pluginManifest.version = nextVersion;
|
|
238
239
|
writePluginManifestJson(pluginManifestFile, pluginManifest);
|
|
240
|
+
|
|
241
|
+
const claudePluginFile = path.join("plugins", "meta-architect", ".claude-plugin", "plugin.json");
|
|
242
|
+
const claudePlugin = readJson(claudePluginFile);
|
|
243
|
+
claudePlugin.version = nextVersion;
|
|
244
|
+
writeJson(claudePluginFile, claudePlugin);
|
|
245
|
+
|
|
246
|
+
const claudeMarketplaceFile = path.join(".claude-plugin", "marketplace.json");
|
|
247
|
+
const claudeMarketplace = readJson(claudeMarketplaceFile);
|
|
248
|
+
claudeMarketplace.metadata.version = nextVersion;
|
|
249
|
+
writeJson(claudeMarketplaceFile, claudeMarketplace);
|
|
239
250
|
}
|
|
240
251
|
|
|
241
252
|
function syncCurrentReleaseFiles(oldVersion, nextVersion) {
|
|
@@ -48,11 +48,22 @@ function latestCdnInstall() {
|
|
|
48
48
|
function verifyInstallBlock(file) {
|
|
49
49
|
const content = readText(file);
|
|
50
50
|
const cdnInstall = latestCdnInstall();
|
|
51
|
-
|
|
51
|
+
const htmlCdnInstall = cdnInstall.replaceAll("&&", "&&");
|
|
52
|
+
const normalizedContent = content.replaceAll("\\|", "|");
|
|
53
|
+
const splitCdnInstall = [
|
|
54
|
+
"curl -fsSLo install.sh https://cdn.jsdelivr.net/gh/JustineDevs/meta-architect@latest/scripts/install.sh",
|
|
55
|
+
"curl -fsSLo install.sh.sha256 https://cdn.jsdelivr.net/gh/JustineDevs/meta-architect@latest/scripts/install.sh.sha256",
|
|
56
|
+
"sed 's#scripts/install.sh#install.sh#' install.sh.sha256 | sha256sum -c -",
|
|
57
|
+
"sh install.sh",
|
|
58
|
+
].every((command) => normalizedContent.includes(command));
|
|
59
|
+
if (!content.includes(CANONICAL_INSTALL) && !content.includes(cdnInstall) && !splitCdnInstall) {
|
|
52
60
|
return;
|
|
53
61
|
}
|
|
54
62
|
|
|
55
|
-
assert(
|
|
63
|
+
assert(
|
|
64
|
+
content.includes(cdnInstall) || content.includes(htmlCdnInstall) || splitCdnInstall,
|
|
65
|
+
`${file}: missing jsDelivr POSIX installer command`,
|
|
66
|
+
);
|
|
56
67
|
assert(content.includes(CANONICAL_INSTALL), `${file}: missing canonical npm install command`);
|
|
57
68
|
assert(content.includes(CANONICAL_LAUNCH), `${file}: missing canonical launch command`);
|
|
58
69
|
assert(content.includes(UNINSTALL_MA), `${file}: missing uninstall Meta-Architect command`);
|
|
@@ -156,7 +167,7 @@ function verifyCoverageDoc({ version, gitTag }) {
|
|
|
156
167
|
function verifyReadmeReleaseSurface({ gitTag }) {
|
|
157
168
|
const content = readText("README.md");
|
|
158
169
|
const demoImage = `<img src="https://raw.githubusercontent.com/JustineDevs/meta-architect/${gitTag}/docs/assets/DEMO_VIDEO.gif" alt="Meta-Architect demo video" width="800">`;
|
|
159
|
-
const
|
|
170
|
+
const bannerImage = `<img src="./docs/assets/banner.png" alt="Meta-Architect: quality gates and evidence verification for AI coding agents" width="1000">`;
|
|
160
171
|
assert(content.includes("> [!NOTE]"), "README.md: missing product-positioning note admonition");
|
|
161
172
|
assert(
|
|
162
173
|
content.includes(
|
|
@@ -185,7 +196,11 @@ function verifyReadmeReleaseSurface({ gitTag }) {
|
|
|
185
196
|
),
|
|
186
197
|
"README.md: missing GitHub release badge",
|
|
187
198
|
);
|
|
188
|
-
assert(
|
|
199
|
+
assert(
|
|
200
|
+
fs.existsSync(path.join("docs", "assets", "banner.png")),
|
|
201
|
+
"docs/assets/banner.png: missing",
|
|
202
|
+
);
|
|
203
|
+
assert(content.includes(bannerImage), "README.md: banner image missing");
|
|
189
204
|
assert(
|
|
190
205
|
!content.includes("raw.githubusercontent.com/JustineDevs/meta-architect/main/"),
|
|
191
206
|
"README.md: stable docs must not reference mutable main",
|
|
@@ -356,12 +371,28 @@ function main() {
|
|
|
356
371
|
const pluginManifest = readJson(
|
|
357
372
|
path.join("plugins", "meta-architect", ".codex-plugin", "plugin.json"),
|
|
358
373
|
);
|
|
374
|
+
const claudeMarketplace = readJson(path.join(".claude-plugin", "marketplace.json"));
|
|
375
|
+
const claudePlugin = readJson(
|
|
376
|
+
path.join("plugins", "meta-architect", ".claude-plugin", "plugin.json"),
|
|
377
|
+
);
|
|
359
378
|
assert(pluginApp.version === version, "plugins/meta-architect/.app.json: version drift");
|
|
360
379
|
assert(pluginMcp.version === version, "plugins/meta-architect/.mcp.json: version drift");
|
|
361
380
|
assert(
|
|
362
381
|
pluginManifest.version === version,
|
|
363
382
|
"plugins/meta-architect/.codex-plugin/plugin.json: version drift",
|
|
364
383
|
);
|
|
384
|
+
assert(
|
|
385
|
+
claudeMarketplace.metadata?.version === version,
|
|
386
|
+
".claude-plugin/marketplace.json: version drift",
|
|
387
|
+
);
|
|
388
|
+
assert(
|
|
389
|
+
claudeMarketplace.plugins?.some((plugin) => plugin.source === "./plugins/meta-architect"),
|
|
390
|
+
".claude-plugin/marketplace.json: missing Meta-Architect plugin source",
|
|
391
|
+
);
|
|
392
|
+
assert(
|
|
393
|
+
claudePlugin.version === version,
|
|
394
|
+
"plugins/meta-architect/.claude-plugin/plugin.json: version drift",
|
|
395
|
+
);
|
|
365
396
|
|
|
366
397
|
for (const file of [
|
|
367
398
|
"README.md",
|