@jstn-sdk/ma 0.1.13 → 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.
Files changed (259) hide show
  1. package/.agents/plugins/marketplace.json +0 -0
  2. package/.codex/agents/Architect.toml +1 -0
  3. package/.codex/agents/Auditor.toml +1 -0
  4. package/.codex/agents/Builder.toml +1 -0
  5. package/.codex/agents/Flow.toml +1 -0
  6. package/.codex/agents/Sage.toml +1 -0
  7. package/.codex/agents/Vibe.toml +1 -0
  8. package/.codex/hooks.json +12 -2
  9. package/.codex/prompts/enforcement.md +0 -0
  10. package/.codex/prompts/onboarding.md +6 -1
  11. package/.codex/prompts/release-rules.md +0 -0
  12. package/.codex/prompts/skill-contract.md +0 -0
  13. package/COVERAGE.md +9 -9
  14. package/DEMO.md +15 -6
  15. package/LICENSE +0 -0
  16. package/README.md +127 -784
  17. package/bin/ma.js +591 -105
  18. package/data/clone-data.ledger.json +0 -0
  19. package/data/clone-data.proof.json +0 -0
  20. package/data/clone-data.rvf +0 -0
  21. package/docs/README.md +8 -2
  22. package/docs/assets/banner.png +0 -0
  23. package/docs/autonomous-tasks.md +46 -0
  24. package/docs/codex-integration.md +16 -0
  25. package/docs/getting-started.md +32 -8
  26. package/docs/installed-sdk.md +0 -0
  27. package/docs/mcp-setup.md +30 -1
  28. package/docs/qa/{release-issue-gates-0.1.13.json → release-issue-gates-0.14.1.json} +77 -77
  29. package/docs/qa/release-readiness-0.1.5.md +0 -0
  30. package/docs/qa/{release-readiness-0.1.13.md → release-readiness-0.14.1.md} +12 -12
  31. package/docs/quality.md +24 -0
  32. package/docs/reference/native-engineering-patterns.md +0 -0
  33. package/docs/reference/native-security-playbooks.md +0 -0
  34. package/docs/reference/native-source-selection.md +0 -0
  35. package/docs/reference/native-style-and-deslop.md +0 -0
  36. package/docs/release-spec.md +27 -14
  37. package/docs/skills.md +1 -1
  38. package/docs/vendor-plugin-publishing.md +49 -0
  39. package/index.js +73 -0
  40. package/mcp/collections.json +0 -0
  41. package/mcp/fallback.json +0 -0
  42. package/mcp/local/code-intel.js +185 -41
  43. package/mcp/local/context.js +180 -0
  44. package/mcp/local/memory.js +17 -6
  45. package/mcp/local/playbooks.js +0 -0
  46. package/mcp/local/quality.js +39 -0
  47. package/mcp/local/state.js +7 -3
  48. package/mcp/local/team-run.js +8 -3
  49. package/mcp/local/trace.js +0 -0
  50. package/mcp/local-capabilities.json +9 -0
  51. package/mcp/native-playbooks.json +0 -0
  52. package/mcp/servers.json +0 -0
  53. package/package.json +37 -6
  54. package/plugins/meta-architect/.app.json +1 -1
  55. package/plugins/meta-architect/.claude-plugin/plugin.json +12 -0
  56. package/plugins/meta-architect/.codex-plugin/plugin.json +1 -1
  57. package/plugins/meta-architect/.mcp.json +1 -1
  58. package/plugins/meta-architect/README.md +14 -2
  59. package/plugins/meta-architect/obsidian/main.js +137 -4
  60. package/plugins/meta-architect/obsidian/manifest.json +1 -1
  61. package/plugins/meta-architect/obsidian/styles.css +0 -0
  62. package/plugins/meta-architect/skills/align/SKILL.md +0 -0
  63. package/plugins/meta-architect/skills/align/agents/openai.yaml +0 -0
  64. package/plugins/meta-architect/skills/align/references/shared-language.md +0 -0
  65. package/plugins/meta-architect/skills/arch/SKILL.md +0 -0
  66. package/plugins/meta-architect/skills/arch/agents/openai.yaml +0 -0
  67. package/plugins/meta-architect/skills/build/SKILL.md +0 -0
  68. package/plugins/meta-architect/skills/build/agents/openai.yaml +0 -0
  69. package/plugins/meta-architect/skills/cleanup/SKILL.md +0 -0
  70. package/plugins/meta-architect/skills/cleanup/agents/openai.yaml +0 -0
  71. package/plugins/meta-architect/skills/cleanup/references/style-and-deslop.md +0 -0
  72. package/plugins/meta-architect/skills/diagnose/SKILL.md +0 -0
  73. package/plugins/meta-architect/skills/diagnose/agents/openai.yaml +0 -0
  74. package/plugins/meta-architect/skills/flow/SKILL.md +0 -0
  75. package/plugins/meta-architect/skills/flow/agents/openai.yaml +0 -0
  76. package/plugins/meta-architect/skills/maestro/SKILL.md +17 -1
  77. package/plugins/meta-architect/skills/maestro/agents/openai.yaml +0 -0
  78. package/plugins/meta-architect/skills/maestro/references/core-release-rules.md +2 -2
  79. package/plugins/meta-architect/skills/maestro/references/native-ingest-map.md +0 -0
  80. package/plugins/meta-architect/skills/sage/SKILL.md +0 -0
  81. package/plugins/meta-architect/skills/sage/agents/openai.yaml +0 -0
  82. package/plugins/meta-architect/skills/sage/references/source-selection.md +0 -0
  83. package/plugins/meta-architect/skills/tdd/SKILL.md +0 -0
  84. package/plugins/meta-architect/skills/tdd/agents/openai.yaml +0 -0
  85. package/plugins/meta-architect/skills/vet/SKILL.md +0 -0
  86. package/plugins/meta-architect/skills/vet/agents/openai.yaml +0 -0
  87. package/plugins/meta-architect/skills/vet/references/security-playbooks.md +0 -0
  88. package/plugins/meta-architect/skills/vibe/SKILL.md +0 -0
  89. package/plugins/meta-architect/skills/vibe/agents/openai.yaml +0 -0
  90. package/schemas/autonomous-task-queue.schema.json +58 -0
  91. package/schemas/handoff-packet.schema.json +36 -0
  92. package/schemas/setup-receipt.schema.json +28 -0
  93. package/schemas/skill-frontmatter.schema.json +20 -0
  94. package/schemas/support-bundle.schema.json +37 -0
  95. package/schemas/task-contract.schema.json +31 -0
  96. package/scripts/active-autonomy-hook.mjs +141 -11
  97. package/scripts/biome-staged.js +0 -0
  98. package/scripts/build-linux-packages.mjs +7 -3
  99. package/scripts/cleanup-test-fixtures.sh +55 -0
  100. package/scripts/context-hydration-hook.mjs +89 -0
  101. package/scripts/demo-smoke.js +285 -0
  102. package/scripts/doctor.js +10 -8
  103. package/scripts/install.sh +33 -4
  104. package/scripts/install.sh.sha256 +1 -0
  105. package/scripts/linux-package-lib.mjs +0 -0
  106. package/scripts/linux-package-smoke.mjs +2 -2
  107. package/scripts/package-size-check.mjs +26 -0
  108. package/scripts/plugin-build.js +314 -0
  109. package/scripts/plugin-publish.js +77 -0
  110. package/scripts/plugin-sync.js +83 -17
  111. package/scripts/prepack.js +9 -0
  112. package/scripts/ralph/prompt.md +0 -0
  113. package/scripts/release-metadata.js +0 -0
  114. package/scripts/release-sync.js +83 -7
  115. package/scripts/release-verify.js +131 -7
  116. package/scripts/setup-npmrc.js +48 -23
  117. package/scripts/skills-install.js +9 -2
  118. package/scripts/skills-manifest.js +2 -21
  119. package/scripts/skills-pack.js +2 -2
  120. package/scripts/skills-validate.js +5 -55
  121. package/skills/align/SKILL.md +0 -0
  122. package/skills/align/agents/openai.yaml +0 -0
  123. package/skills/align/references/shared-language.md +0 -0
  124. package/skills/arch/SKILL.md +0 -0
  125. package/skills/arch/agents/openai.yaml +0 -0
  126. package/skills/build/SKILL.md +0 -0
  127. package/skills/build/agents/openai.yaml +0 -0
  128. package/skills/cleanup/SKILL.md +0 -0
  129. package/skills/cleanup/agents/openai.yaml +0 -0
  130. package/skills/cleanup/references/style-and-deslop.md +0 -0
  131. package/skills/diagnose/SKILL.md +0 -0
  132. package/skills/diagnose/agents/openai.yaml +0 -0
  133. package/skills/flow/SKILL.md +0 -0
  134. package/skills/flow/agents/openai.yaml +0 -0
  135. package/skills/index.json +0 -0
  136. package/skills/maestro/SKILL.md +17 -1
  137. package/skills/maestro/agents/openai.yaml +0 -0
  138. package/skills/maestro/references/core-release-rules.md +2 -2
  139. package/skills/maestro/references/native-ingest-map.md +0 -0
  140. package/skills/sage/SKILL.md +0 -0
  141. package/skills/sage/agents/openai.yaml +0 -0
  142. package/skills/sage/references/source-selection.md +0 -0
  143. package/skills/tdd/SKILL.md +0 -0
  144. package/skills/tdd/agents/openai.yaml +0 -0
  145. package/skills/vet/SKILL.md +0 -0
  146. package/skills/vet/agents/openai.yaml +0 -0
  147. package/skills/vet/references/security-playbooks.md +0 -0
  148. package/skills/vibe/SKILL.md +0 -0
  149. package/skills/vibe/agents/openai.yaml +0 -0
  150. package/sprint/00-idea.md +0 -0
  151. package/sprint/01-architecture.md +0 -0
  152. package/sprint/02-oss-evidence.md +0 -0
  153. package/sprint/03-logic.md +0 -0
  154. package/sprint/04-security.md +0 -0
  155. package/sprint/05-dx-ux.md +0 -0
  156. package/sprint/06-build-plan.md +0 -0
  157. package/sprint/07-release.md +2 -2
  158. package/src/agents.js +281 -0
  159. package/src/bootstrap.js +272 -65
  160. package/src/build-gate.js +0 -0
  161. package/src/codex-app-server.js +291 -0
  162. package/src/decision-log.js +0 -0
  163. package/src/fs-utils.js +175 -4
  164. package/src/launcher.js +26 -23
  165. package/src/mcp-config.js +9 -1
  166. package/src/mcp-live-client.js +141 -8
  167. package/src/paths.js +6 -1
  168. package/src/policy.js +2 -2
  169. package/src/prelaunch.js +223 -0
  170. package/src/process-utils.js +62 -0
  171. package/src/quality/ai-quality-orchestrator.js +328 -0
  172. package/src/release-issue-gates.js +62 -0
  173. package/src/release-operations.js +72 -0
  174. package/src/release-state.js +0 -0
  175. package/src/runtime/active-autonomy-core.js +0 -0
  176. package/src/runtime/agent-compat.js +31 -0
  177. package/src/runtime/alignment-sentinel.js +0 -0
  178. package/src/runtime/architect-review.js +249 -11
  179. package/src/runtime/autonomous-tasks.js +585 -0
  180. package/src/runtime/build-readiness.js +0 -0
  181. package/src/runtime/code-graph-rehearse.js +0 -0
  182. package/src/runtime/codeburn-core.js +118 -0
  183. package/src/runtime/context-authority.js +40 -0
  184. package/src/runtime/context-economy-core.js +40 -0
  185. package/src/runtime/continuity-graph.js +201 -0
  186. package/src/runtime/continuity-notes.js +71 -26
  187. package/src/runtime/core-source-ingest.js +2 -2
  188. package/src/runtime/detached-provider.js +90 -13
  189. package/src/runtime/doctor-report.js +18 -0
  190. package/src/runtime/environment-awareness-core.js +0 -0
  191. package/src/runtime/exposure-catalog.js +0 -0
  192. package/src/runtime/graphify-core.js +167 -0
  193. package/src/runtime/guidance-stack.js +9 -2
  194. package/src/runtime/handoff-packets.js +92 -0
  195. package/src/runtime/headroom-core.js +104 -0
  196. package/src/runtime/helper-orchestration-core.js +0 -0
  197. package/src/runtime/hook-profiles.js +20 -0
  198. package/src/runtime/learning-loop-core.js +110 -4
  199. package/src/runtime/live-agent-verification.js +122 -0
  200. package/src/runtime/maestro-events.js +0 -0
  201. package/src/runtime/maestro-manager.js +0 -0
  202. package/src/runtime/maestro-output.js +58 -0
  203. package/src/runtime/maestro-state.js +0 -0
  204. package/src/runtime/managed-markdown.js +29 -0
  205. package/src/runtime/mcp-authority.js +147 -0
  206. package/src/runtime/mcp-policy.js +0 -0
  207. package/src/runtime/obsidian-integration-core.js +255 -17
  208. package/src/runtime/obsidian-plugin-bridge.js +344 -38
  209. package/src/runtime/orchestrator.js +0 -0
  210. package/src/runtime/pi-maestro-core.js +89 -0
  211. package/src/runtime/preferences.js +79 -0
  212. package/src/runtime/project-context.js +636 -0
  213. package/src/runtime/prompt-strategy-core.js +0 -0
  214. package/src/runtime/quorum-review.js +0 -0
  215. package/src/runtime/ralph-execution-core.js +0 -0
  216. package/src/runtime/redaction-gateway.js +218 -19
  217. package/src/runtime/runtime-state.js +94 -2
  218. package/src/runtime/schema-migrations.js +162 -0
  219. package/src/runtime/semantic-recording-core.js +0 -0
  220. package/src/runtime/signal-hooks.js +13 -0
  221. package/src/runtime/skills-registry-export.js +96 -8
  222. package/src/runtime/startup-path.js +0 -0
  223. package/src/runtime/task-contracts.js +83 -0
  224. package/src/runtime/universal-plugin-broker-core.js +373 -50
  225. package/src/runtime/workspace-intelligence-runtime.js +0 -0
  226. package/src/runtime/workspace-virtualizer.js +0 -0
  227. package/src/runtime/workspaces.js +0 -0
  228. package/src/runtime-artifacts.js +0 -0
  229. package/src/setup-lifecycle.js +359 -0
  230. package/src/skill-frontmatter.js +78 -0
  231. package/src/skill-installer.js +226 -71
  232. package/src/skills.js +309 -31
  233. package/src/state-sync.js +0 -0
  234. package/src/test-fixtures.js +543 -0
  235. package/src/tui/grid.js +67 -0
  236. package/src/tui/status-grid.js +23 -0
  237. package/support-bundle.json +114 -0
  238. package/templates/AGENTS.md +6 -2
  239. package/templates/catalog-manifest.json +0 -0
  240. package/templates/model-instructions/core.md +0 -0
  241. package/templates/model-instructions/release.md +0 -0
  242. package/templates/model-instructions/security.md +0 -0
  243. package/templates/quality/ai-quality-rules.yml +37 -0
  244. package/docs/assets/image/Screenshot(1).png +0 -0
  245. package/docs/assets/image/Screenshot(2).png +0 -0
  246. package/docs/assets/image/Screenshot(3).png +0 -0
  247. package/docs/assets/image/Screenshot(4).png +0 -0
  248. package/docs/assets/image/Screenshot(5).png +0 -0
  249. package/docs/assets/image/Screenshot(6).png +0 -0
  250. package/docs/assets/image/Screenshot(7).png +0 -0
  251. package/docs/assets/image/Screenshot(8).png +0 -0
  252. package/docs/assets/image/Screenshot(9).png +0 -0
  253. package/docs/assets/meta-architect-logo.png +0 -0
  254. package/docs/assets/meta-architect-logo.svg +0 -8
  255. package/docs/onboarding.md +0 -81
  256. package/docs/prompt-guidance-contract.md +0 -17
  257. package/docs/prompt-guidance-fragments/active-autonomy-core.md +0 -7
  258. package/docs/skills-publishing.md +0 -255
  259. package/scripts/postinstall.js +0 -23
@@ -1,8 +1,20 @@
1
1
  #!/usr/bin/env sh
2
2
  set -eu
3
3
 
4
- MA_PACKAGE="${MA_PACKAGE:-@jstn-sdk/ma@latest}"
4
+ MA_PACKAGE="${MA_PACKAGE:-@jstn-sdk/ma@0.14.1}"
5
5
  CODEX_PACKAGE="${CODEX_PACKAGE:-@openai/codex@latest}"
6
+ NO_SETUP=0
7
+ NO_SKILLS=0
8
+ DRY_RUN=0
9
+
10
+ for arg in "$@"; do
11
+ case "$arg" in
12
+ --no-setup) NO_SETUP=1 ;;
13
+ --no-skills) NO_SKILLS=1 ;;
14
+ --dry-run) DRY_RUN=1 ;;
15
+ *) echo "meta-architect install: unknown option: $arg" >&2; exit 2 ;;
16
+ esac
17
+ done
6
18
 
7
19
  need_cmd() {
8
20
  command -v "$1" >/dev/null 2>&1 || {
@@ -14,14 +26,31 @@ need_cmd() {
14
26
  need_cmd npm
15
27
  need_cmd node
16
28
 
17
- echo "meta-architect install: installing Codex + Meta-Architect"
29
+ echo "meta-architect install: plan"
30
+ echo " install: $CODEX_PACKAGE $MA_PACKAGE"
31
+ echo " setup: $([ "$NO_SETUP" -eq 1 ] && echo disabled || echo enabled)"
32
+ echo " skills: $([ "$NO_SKILLS" -eq 1 ] && echo disabled || echo enabled)"
33
+ echo " undo: npm uninstall -g $MA_PACKAGE $CODEX_PACKAGE"
34
+
35
+ if [ "$DRY_RUN" -eq 1 ]; then
36
+ echo "meta-architect install: dry-run complete"
37
+ exit 0
38
+ fi
39
+
40
+ if [ "$NO_SKILLS" -eq 1 ]; then export MA_SKIP_SKILLS=1; fi
18
41
  npm i -g "$CODEX_PACKAGE" "$MA_PACKAGE"
42
+ echo "meta-architect install: versions"
43
+ node --version
44
+ npm --version
45
+ command -v codex >/dev/null 2>&1 && codex --version || echo "codex: unavailable"
19
46
 
20
- if command -v ma >/dev/null 2>&1; then
47
+ if command -v ma >/dev/null 2>&1 && [ "$NO_SETUP" -eq 0 ]; then
21
48
  echo "meta-architect install: seeding local MA runtime"
22
- ma setup >/dev/null
49
+ ma setup
23
50
  echo "meta-architect install: ready"
24
51
  echo "start: ma --madmax --high"
52
+ elif [ "$NO_SETUP" -eq 1 ]; then
53
+ echo "meta-architect install: setup disabled by --no-setup"
25
54
  else
26
55
  echo "meta-architect install: ma command not found after npm install" >&2
27
56
  exit 1
@@ -0,0 +1 @@
1
+ 3ffac1b709bceb6343181fef3402fa3bed6a9d9067299a2938489a4d3458ad41 scripts/install.sh
File without changes
@@ -3,9 +3,9 @@
3
3
  import assert from "node:assert/strict";
4
4
  import { spawnSync } from "node:child_process";
5
5
  import fs from "node:fs/promises";
6
- import os from "node:os";
7
6
  import path from "node:path";
8
7
  import process from "node:process";
8
+ import { createTestNamespace } from "../src/test-fixtures.js";
9
9
  import {
10
10
  getDebArtifactPath,
11
11
  getPacmanArtifactPath,
@@ -61,7 +61,7 @@ async function main() {
61
61
  throw new Error("Native Linux package smoke validation is supported only on Linux hosts");
62
62
  }
63
63
 
64
- const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "meta-architect-linux-smoke-"));
64
+ const tempRoot = createTestNamespace("meta-architect-linux-smoke");
65
65
  const debExtractRoot = path.join(tempRoot, "deb");
66
66
  const pacmanExtractRoot = path.join(tempRoot, "pacman");
67
67
  const rpmExtractRoot = path.join(tempRoot, "rpm");
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { spawnSync } from "node:child_process";
4
+
5
+ const budget = Number(process.env.MA_PACKAGE_SIZE_BUDGET ?? 5 * 1024 * 1024);
6
+ const result = spawnSync("npm", ["pack", "--dry-run", "--json", "--ignore-scripts"], {
7
+ encoding: "utf8",
8
+ });
9
+ if (result.status !== 0) throw new Error(result.stderr || "npm pack inspection failed");
10
+ const pack = JSON.parse(result.stdout)[0];
11
+ const excludedMedia = pack.files.filter((file) => /docs\/assets\//.test(file.path));
12
+ if (excludedMedia.length > 0)
13
+ throw new Error(
14
+ `Heavy demo media included: ${excludedMedia.map((file) => file.path).join(", ")}`,
15
+ );
16
+ const unexpectedExecutables = pack.files.filter(
17
+ (file) =>
18
+ file.mode === 493 && !file.path.startsWith("bin/") && !/^scripts\/[^/]+\.sh$/.test(file.path),
19
+ );
20
+ if (unexpectedExecutables.length > 0) {
21
+ throw new Error(
22
+ `Unexpected executable package files: ${unexpectedExecutables.map((file) => file.path).join(", ")}`,
23
+ );
24
+ }
25
+ console.log(`package size: ${pack.size} bytes (budget ${budget})`);
26
+ if (pack.size > budget) throw new Error(`Package exceeds ${budget} byte budget`);
@@ -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
+ });
@@ -3,6 +3,7 @@
3
3
  import fs from "node:fs/promises";
4
4
  import path from "node:path";
5
5
  import process from "node:process";
6
+ import { fileURLToPath } from "node:url";
6
7
 
7
8
  const repoRoot = process.cwd();
8
9
  const skillsRoot = path.join(repoRoot, "skills");
@@ -30,10 +31,23 @@ async function copyDir(src, dest) {
30
31
  }
31
32
  }
32
33
 
34
+ async function linkOrCopyDir(src, dest) {
35
+ if (process.env.MA_PLUGIN_SYNC_MODE !== "copy") {
36
+ try {
37
+ await fs.symlink(path.relative(path.dirname(dest), src), dest, "dir");
38
+ return "symlink";
39
+ } catch {
40
+ // Restricted worktrees and Windows may reject directory links.
41
+ }
42
+ }
43
+ await copyDir(src, dest);
44
+ return "copy";
45
+ }
46
+
33
47
  async function listSkillDirs(root) {
34
- const entries = await fs.readdir(root, { withFileTypes: true }).catch(() => []);
48
+ const entries = await fs.readdir(root, { withFileTypes: true });
35
49
  return entries
36
- .filter((entry) => entry.isDirectory())
50
+ .filter((entry) => entry.isDirectory() || entry.isSymbolicLink())
37
51
  .map((entry) => entry.name)
38
52
  .sort();
39
53
  }
@@ -53,24 +67,74 @@ async function syncPluginSkills() {
53
67
  const src = path.join(skillsRoot, name);
54
68
  const dest = path.join(pluginSkillsRoot, name);
55
69
  await fs.rm(dest, { recursive: true, force: true });
56
- await copyDir(src, dest);
70
+ await linkOrCopyDir(src, dest);
57
71
  }
58
72
 
59
73
  return skillDirs;
60
74
  }
61
75
 
62
- async function verifyPluginSkills() {
63
- const skillDirs = await listSkillDirs(skillsRoot);
64
- const pluginDirs = await listSkillDirs(pluginSkillsRoot);
65
- if (skillDirs.length !== pluginDirs.length) {
66
- throw new Error("Plugin skill mirror drift: directory count mismatch");
76
+ async function listFiles(root, current = root, files = []) {
77
+ const entries = await fs.readdir(current, { withFileTypes: true });
78
+ for (const entry of entries) {
79
+ const absolutePath = path.join(current, entry.name);
80
+ if (entry.isDirectory() || entry.isSymbolicLink()) {
81
+ await listFiles(root, absolutePath, files);
82
+ } else if (entry.isFile()) {
83
+ files.push(path.relative(root, absolutePath));
84
+ }
85
+ }
86
+ return files.sort();
87
+ }
88
+
89
+ export async function verifyPluginSkills(sourceRoot = skillsRoot, mirrorRoot = pluginSkillsRoot) {
90
+ await fs.access(sourceRoot);
91
+ await fs.access(mirrorRoot);
92
+ const sourceSkillDirs = await listSkillDirs(sourceRoot);
93
+ const mirrorSkillDirs = await listSkillDirs(mirrorRoot);
94
+ const filesForSkillDirs = async (root, skillDirs) => {
95
+ const files = [];
96
+ for (const skillDir of skillDirs) {
97
+ for (const relativePath of await listFiles(path.join(root, skillDir))) {
98
+ files.push(path.join(skillDir, relativePath));
99
+ }
100
+ }
101
+ return files.sort();
102
+ };
103
+ const sourceFiles = await filesForSkillDirs(sourceRoot, sourceSkillDirs);
104
+ const mirrorFiles = await filesForSkillDirs(mirrorRoot, mirrorSkillDirs);
105
+ if (JSON.stringify(sourceFiles) !== JSON.stringify(mirrorFiles)) {
106
+ throw new Error("Plugin skill mirror drift: file set mismatch");
67
107
  }
68
108
 
69
- for (let index = 0; index < skillDirs.length; index += 1) {
70
- if (skillDirs[index] !== pluginDirs[index]) {
71
- throw new Error(
72
- `Plugin skill mirror drift: expected ${skillDirs[index]}, found ${pluginDirs[index]}`,
73
- );
109
+ for (const relativePath of sourceFiles) {
110
+ const sourcePath = path.join(sourceRoot, relativePath);
111
+ const mirrorPath = path.join(mirrorRoot, relativePath);
112
+ const [source, mirror, sourceStat, mirrorStat] = await Promise.all([
113
+ fs.readFile(sourcePath),
114
+ fs.readFile(mirrorPath),
115
+ fs.stat(sourcePath),
116
+ fs.stat(mirrorPath),
117
+ ]);
118
+ if (!source.equals(mirror)) {
119
+ throw new Error(`Plugin skill mirror drift: content mismatch at ${relativePath}`);
120
+ }
121
+ if ((sourceStat.mode & 0o777) !== (mirrorStat.mode & 0o777)) {
122
+ throw new Error(`Plugin skill mirror drift: mode mismatch at ${relativePath}`);
123
+ }
124
+ }
125
+ for (const skillDir of sourceSkillDirs) {
126
+ const mirrorPath = path.join(mirrorRoot, skillDir);
127
+ const mirrorStat = await fs.lstat(mirrorPath);
128
+ if (mirrorStat.isSymbolicLink()) {
129
+ const [sourceRealPath, mirrorRealPath] = await Promise.all([
130
+ fs.realpath(path.join(sourceRoot, skillDir)),
131
+ fs.realpath(mirrorPath),
132
+ ]);
133
+ if (sourceRealPath !== mirrorRealPath) {
134
+ throw new Error(`Plugin skill mirror drift: invalid symlink target at ${skillDir}`);
135
+ }
136
+ } else if (!mirrorStat.isDirectory()) {
137
+ throw new Error(`Plugin skill mirror drift: invalid mirror entry at ${skillDir}`);
74
138
  }
75
139
  }
76
140
  }
@@ -87,7 +151,9 @@ async function main() {
87
151
  console.log(pluginSkillsRoot);
88
152
  }
89
153
 
90
- main().catch((error) => {
91
- console.error(error.message);
92
- process.exitCode = 1;
93
- });
154
+ if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
155
+ main().catch((error) => {
156
+ console.error(error.message);
157
+ process.exitCode = 1;
158
+ });
159
+ }
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execFileSync } from "node:child_process";
4
+ import process from "node:process";
5
+
6
+ execFileSync(process.execPath, ["./scripts/plugin-sync.js"], {
7
+ stdio: "inherit",
8
+ env: { ...process.env, MA_PLUGIN_SYNC_MODE: "copy" },
9
+ });
File without changes
File without changes