@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.
Files changed (253) 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 +7 -7
  14. package/DEMO.md +15 -6
  15. package/LICENSE +0 -0
  16. package/README.md +126 -793
  17. package/bin/ma.js +585 -97
  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/autonomous-tasks.md +46 -0
  23. package/docs/codex-integration.md +16 -0
  24. package/docs/getting-started.md +28 -4
  25. package/docs/installed-sdk.md +0 -0
  26. package/docs/mcp-setup.md +30 -1
  27. package/docs/qa/{release-issue-gates-0.1.13.json → release-issue-gates-0.14.0.json} +77 -77
  28. package/docs/qa/release-readiness-0.1.5.md +0 -0
  29. package/docs/qa/{release-readiness-0.1.13.md → release-readiness-0.14.0.md} +12 -12
  30. package/docs/quality.md +24 -0
  31. package/docs/reference/native-engineering-patterns.md +0 -0
  32. package/docs/reference/native-security-playbooks.md +0 -0
  33. package/docs/reference/native-source-selection.md +0 -0
  34. package/docs/reference/native-style-and-deslop.md +0 -0
  35. package/docs/release-spec.md +27 -14
  36. package/docs/skills.md +1 -1
  37. package/index.js +73 -0
  38. package/mcp/collections.json +0 -0
  39. package/mcp/fallback.json +0 -0
  40. package/mcp/local/code-intel.js +179 -41
  41. package/mcp/local/context.js +180 -0
  42. package/mcp/local/memory.js +17 -6
  43. package/mcp/local/playbooks.js +0 -0
  44. package/mcp/local/quality.js +39 -0
  45. package/mcp/local/state.js +7 -3
  46. package/mcp/local/team-run.js +8 -3
  47. package/mcp/local/trace.js +0 -0
  48. package/mcp/local-capabilities.json +9 -0
  49. package/mcp/native-playbooks.json +0 -0
  50. package/mcp/servers.json +0 -0
  51. package/package.json +26 -4
  52. package/plugins/meta-architect/.app.json +1 -1
  53. package/plugins/meta-architect/.codex-plugin/plugin.json +1 -1
  54. package/plugins/meta-architect/.mcp.json +1 -1
  55. package/plugins/meta-architect/README.md +2 -2
  56. package/plugins/meta-architect/obsidian/main.js +137 -4
  57. package/plugins/meta-architect/obsidian/manifest.json +1 -1
  58. package/plugins/meta-architect/obsidian/styles.css +0 -0
  59. package/plugins/meta-architect/skills/align/SKILL.md +0 -0
  60. package/plugins/meta-architect/skills/align/agents/openai.yaml +0 -0
  61. package/plugins/meta-architect/skills/align/references/shared-language.md +0 -0
  62. package/plugins/meta-architect/skills/arch/SKILL.md +0 -0
  63. package/plugins/meta-architect/skills/arch/agents/openai.yaml +0 -0
  64. package/plugins/meta-architect/skills/build/SKILL.md +0 -0
  65. package/plugins/meta-architect/skills/build/agents/openai.yaml +0 -0
  66. package/plugins/meta-architect/skills/cleanup/SKILL.md +0 -0
  67. package/plugins/meta-architect/skills/cleanup/agents/openai.yaml +0 -0
  68. package/plugins/meta-architect/skills/cleanup/references/style-and-deslop.md +0 -0
  69. package/plugins/meta-architect/skills/diagnose/SKILL.md +0 -0
  70. package/plugins/meta-architect/skills/diagnose/agents/openai.yaml +0 -0
  71. package/plugins/meta-architect/skills/flow/SKILL.md +0 -0
  72. package/plugins/meta-architect/skills/flow/agents/openai.yaml +0 -0
  73. package/plugins/meta-architect/skills/maestro/SKILL.md +0 -0
  74. package/plugins/meta-architect/skills/maestro/agents/openai.yaml +0 -0
  75. package/plugins/meta-architect/skills/maestro/references/core-release-rules.md +0 -0
  76. package/plugins/meta-architect/skills/maestro/references/native-ingest-map.md +0 -0
  77. package/plugins/meta-architect/skills/sage/SKILL.md +0 -0
  78. package/plugins/meta-architect/skills/sage/agents/openai.yaml +0 -0
  79. package/plugins/meta-architect/skills/sage/references/source-selection.md +0 -0
  80. package/plugins/meta-architect/skills/tdd/SKILL.md +0 -0
  81. package/plugins/meta-architect/skills/tdd/agents/openai.yaml +0 -0
  82. package/plugins/meta-architect/skills/vet/SKILL.md +0 -0
  83. package/plugins/meta-architect/skills/vet/agents/openai.yaml +0 -0
  84. package/plugins/meta-architect/skills/vet/references/security-playbooks.md +0 -0
  85. package/plugins/meta-architect/skills/vibe/SKILL.md +0 -0
  86. package/plugins/meta-architect/skills/vibe/agents/openai.yaml +0 -0
  87. package/schemas/autonomous-task-queue.schema.json +56 -0
  88. package/schemas/handoff-packet.schema.json +36 -0
  89. package/schemas/setup-receipt.schema.json +28 -0
  90. package/schemas/skill-frontmatter.schema.json +20 -0
  91. package/schemas/support-bundle.schema.json +37 -0
  92. package/schemas/task-contract.schema.json +31 -0
  93. package/scripts/active-autonomy-hook.mjs +141 -11
  94. package/scripts/biome-staged.js +0 -0
  95. package/scripts/build-linux-packages.mjs +7 -3
  96. package/scripts/cleanup-test-fixtures.sh +55 -0
  97. package/scripts/context-hydration-hook.mjs +89 -0
  98. package/scripts/demo-smoke.js +285 -0
  99. package/scripts/doctor.js +10 -8
  100. package/scripts/install.sh +33 -4
  101. package/scripts/install.sh.sha256 +1 -0
  102. package/scripts/linux-package-lib.mjs +0 -0
  103. package/scripts/linux-package-smoke.mjs +2 -2
  104. package/scripts/package-size-check.mjs +26 -0
  105. package/scripts/plugin-sync.js +83 -17
  106. package/scripts/postinstall.js +17 -10
  107. package/scripts/prepack.js +9 -0
  108. package/scripts/ralph/prompt.md +0 -0
  109. package/scripts/release-metadata.js +0 -0
  110. package/scripts/release-sync.js +72 -7
  111. package/scripts/release-verify.js +100 -7
  112. package/scripts/setup-npmrc.js +48 -23
  113. package/scripts/skills-install.js +9 -2
  114. package/scripts/skills-manifest.js +2 -21
  115. package/scripts/skills-pack.js +2 -2
  116. package/scripts/skills-validate.js +5 -55
  117. package/skills/align/SKILL.md +0 -0
  118. package/skills/align/agents/openai.yaml +0 -0
  119. package/skills/align/references/shared-language.md +0 -0
  120. package/skills/arch/SKILL.md +0 -0
  121. package/skills/arch/agents/openai.yaml +0 -0
  122. package/skills/build/SKILL.md +0 -0
  123. package/skills/build/agents/openai.yaml +0 -0
  124. package/skills/cleanup/SKILL.md +0 -0
  125. package/skills/cleanup/agents/openai.yaml +0 -0
  126. package/skills/cleanup/references/style-and-deslop.md +0 -0
  127. package/skills/diagnose/SKILL.md +0 -0
  128. package/skills/diagnose/agents/openai.yaml +0 -0
  129. package/skills/flow/SKILL.md +0 -0
  130. package/skills/flow/agents/openai.yaml +0 -0
  131. package/skills/index.json +0 -0
  132. package/skills/maestro/SKILL.md +0 -0
  133. package/skills/maestro/agents/openai.yaml +0 -0
  134. package/skills/maestro/references/core-release-rules.md +0 -0
  135. package/skills/maestro/references/native-ingest-map.md +0 -0
  136. package/skills/sage/SKILL.md +0 -0
  137. package/skills/sage/agents/openai.yaml +0 -0
  138. package/skills/sage/references/source-selection.md +0 -0
  139. package/skills/tdd/SKILL.md +0 -0
  140. package/skills/tdd/agents/openai.yaml +0 -0
  141. package/skills/vet/SKILL.md +0 -0
  142. package/skills/vet/agents/openai.yaml +0 -0
  143. package/skills/vet/references/security-playbooks.md +0 -0
  144. package/skills/vibe/SKILL.md +0 -0
  145. package/skills/vibe/agents/openai.yaml +0 -0
  146. package/sprint/00-idea.md +0 -0
  147. package/sprint/01-architecture.md +0 -0
  148. package/sprint/02-oss-evidence.md +0 -0
  149. package/sprint/03-logic.md +0 -0
  150. package/sprint/04-security.md +0 -0
  151. package/sprint/05-dx-ux.md +0 -0
  152. package/sprint/06-build-plan.md +0 -0
  153. package/sprint/07-release.md +0 -0
  154. package/src/agents.js +279 -0
  155. package/src/bootstrap.js +252 -63
  156. package/src/build-gate.js +0 -0
  157. package/src/codex-app-server.js +291 -0
  158. package/src/decision-log.js +0 -0
  159. package/src/fs-utils.js +175 -4
  160. package/src/launcher.js +24 -21
  161. package/src/mcp-config.js +9 -1
  162. package/src/mcp-live-client.js +140 -7
  163. package/src/paths.js +6 -1
  164. package/src/policy.js +2 -2
  165. package/src/prelaunch.js +189 -0
  166. package/src/quality/ai-quality-orchestrator.js +328 -0
  167. package/src/release-issue-gates.js +62 -0
  168. package/src/release-operations.js +62 -0
  169. package/src/release-state.js +0 -0
  170. package/src/runtime/active-autonomy-core.js +0 -0
  171. package/src/runtime/agent-compat.js +31 -0
  172. package/src/runtime/alignment-sentinel.js +0 -0
  173. package/src/runtime/architect-review.js +248 -10
  174. package/src/runtime/autonomous-tasks.js +408 -0
  175. package/src/runtime/build-readiness.js +0 -0
  176. package/src/runtime/code-graph-rehearse.js +0 -0
  177. package/src/runtime/codeburn-core.js +112 -0
  178. package/src/runtime/context-authority.js +40 -0
  179. package/src/runtime/context-economy-core.js +40 -0
  180. package/src/runtime/continuity-graph.js +201 -0
  181. package/src/runtime/continuity-notes.js +71 -26
  182. package/src/runtime/core-source-ingest.js +0 -0
  183. package/src/runtime/detached-provider.js +82 -14
  184. package/src/runtime/doctor-report.js +18 -0
  185. package/src/runtime/environment-awareness-core.js +0 -0
  186. package/src/runtime/exposure-catalog.js +0 -0
  187. package/src/runtime/graphify-core.js +167 -0
  188. package/src/runtime/guidance-stack.js +9 -2
  189. package/src/runtime/handoff-packets.js +92 -0
  190. package/src/runtime/headroom-core.js +104 -0
  191. package/src/runtime/helper-orchestration-core.js +0 -0
  192. package/src/runtime/hook-profiles.js +20 -0
  193. package/src/runtime/learning-loop-core.js +110 -4
  194. package/src/runtime/live-agent-verification.js +122 -0
  195. package/src/runtime/maestro-events.js +0 -0
  196. package/src/runtime/maestro-manager.js +0 -0
  197. package/src/runtime/maestro-output.js +58 -0
  198. package/src/runtime/maestro-state.js +0 -0
  199. package/src/runtime/managed-markdown.js +29 -0
  200. package/src/runtime/mcp-authority.js +147 -0
  201. package/src/runtime/mcp-policy.js +0 -0
  202. package/src/runtime/obsidian-integration-core.js +255 -17
  203. package/src/runtime/obsidian-plugin-bridge.js +344 -38
  204. package/src/runtime/orchestrator.js +0 -0
  205. package/src/runtime/pi-maestro-core.js +89 -0
  206. package/src/runtime/preferences.js +79 -0
  207. package/src/runtime/project-context.js +636 -0
  208. package/src/runtime/prompt-strategy-core.js +0 -0
  209. package/src/runtime/quorum-review.js +0 -0
  210. package/src/runtime/ralph-execution-core.js +0 -0
  211. package/src/runtime/redaction-gateway.js +218 -19
  212. package/src/runtime/runtime-state.js +94 -2
  213. package/src/runtime/schema-migrations.js +162 -0
  214. package/src/runtime/semantic-recording-core.js +0 -0
  215. package/src/runtime/signal-hooks.js +13 -0
  216. package/src/runtime/skills-registry-export.js +92 -8
  217. package/src/runtime/startup-path.js +0 -0
  218. package/src/runtime/task-contracts.js +83 -0
  219. package/src/runtime/universal-plugin-broker-core.js +373 -50
  220. package/src/runtime/workspace-intelligence-runtime.js +0 -0
  221. package/src/runtime/workspace-virtualizer.js +0 -0
  222. package/src/runtime/workspaces.js +0 -0
  223. package/src/runtime-artifacts.js +0 -0
  224. package/src/setup-lifecycle.js +359 -0
  225. package/src/skill-frontmatter.js +78 -0
  226. package/src/skill-installer.js +226 -71
  227. package/src/skills.js +297 -19
  228. package/src/state-sync.js +0 -0
  229. package/src/test-fixtures.js +543 -0
  230. package/src/tui/grid.js +67 -0
  231. package/src/tui/status-grid.js +23 -0
  232. package/support-bundle.json +114 -0
  233. package/templates/AGENTS.md +6 -2
  234. package/templates/catalog-manifest.json +0 -0
  235. package/templates/model-instructions/core.md +0 -0
  236. package/templates/model-instructions/release.md +0 -0
  237. package/templates/model-instructions/security.md +0 -0
  238. package/templates/quality/ai-quality-rules.yml +37 -0
  239. package/docs/assets/image/Screenshot(1).png +0 -0
  240. package/docs/assets/image/Screenshot(2).png +0 -0
  241. package/docs/assets/image/Screenshot(3).png +0 -0
  242. package/docs/assets/image/Screenshot(4).png +0 -0
  243. package/docs/assets/image/Screenshot(5).png +0 -0
  244. package/docs/assets/image/Screenshot(6).png +0 -0
  245. package/docs/assets/image/Screenshot(7).png +0 -0
  246. package/docs/assets/image/Screenshot(8).png +0 -0
  247. package/docs/assets/image/Screenshot(9).png +0 -0
  248. package/docs/assets/meta-architect-logo.png +0 -0
  249. package/docs/assets/meta-architect-logo.svg +0 -8
  250. package/docs/onboarding.md +0 -81
  251. package/docs/prompt-guidance-contract.md +0 -17
  252. package/docs/prompt-guidance-fragments/active-autonomy-core.md +0 -7
  253. package/docs/skills-publishing.md +0 -255
@@ -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.0}"
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
+ 0a18d94ded8872eae750cd2cc4a5b6ab05a6c48796def3634bc2414b3d48f7f7 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`);
@@ -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
+ }
@@ -1,20 +1,27 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import fs from "node:fs/promises";
3
4
  import process from "node:process";
4
- import { installSkills, installSupportBundle } from "../src/skill-installer.js";
5
5
 
6
6
  async function main() {
7
- if (process.env.MA_SKIP_AUTO_INSTALL === "1") {
8
- console.log("meta-architect: skipped Codex skill auto-install");
7
+ const dryRun = process.env.MA_POSTINSTALL_DRY_RUN === "1";
8
+ const skipSkills = process.env.MA_SKIP_SKILLS === "1";
9
+ const receiptPath = process.env.MA_POSTINSTALL_RECEIPT;
10
+ console.log(
11
+ `meta-architect: postinstall skills=${skipSkills ? "disabled" : "enabled"} dry-run=${dryRun ? "yes" : "no"}`,
12
+ );
13
+ if (dryRun || skipSkills || process.env.MA_SKIP_AUTO_INSTALL === "1") {
14
+ console.log("meta-architect: deferred host selection until first interactive launch");
9
15
  return;
10
16
  }
11
-
12
- const [
13
- { targetRoot: skillRoot, installed: skills },
14
- { targetRoot: bundleRoot, installed: assets },
15
- ] = await Promise.all([installSkills(), installSupportBundle()]);
16
- console.log(`meta-architect: installed ${skills.length} Codex skills into ${skillRoot}`);
17
- console.log(`meta-architect: installed ${assets.length} support assets into ${bundleRoot}`);
17
+ console.log("meta-architect: host selection deferred until first interactive launch");
18
+ if (receiptPath) {
19
+ await fs.writeFile(
20
+ receiptPath,
21
+ `${JSON.stringify({ schemaVersion: "0.1.0", deferred: true }, null, 2)}\n`,
22
+ );
23
+ console.log(`meta-architect: receipt ${receiptPath}`);
24
+ }
18
25
  }
19
26
 
20
27
  main().catch((error) => {
@@ -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
@@ -31,6 +31,8 @@ const WATCHED_FILES = new Set([
31
31
  function parseArgs(argv) {
32
32
  const args = {
33
33
  bump: "",
34
+ version: "",
35
+ refreshFrom: "",
34
36
  fromRef: "",
35
37
  toRef: "",
36
38
  githubOutput: "",
@@ -44,6 +46,16 @@ function parseArgs(argv) {
44
46
  index += 1;
45
47
  continue;
46
48
  }
49
+ if (token === "--version") {
50
+ args.version = argv[index + 1] ?? "";
51
+ index += 1;
52
+ continue;
53
+ }
54
+ if (token === "--refresh-from") {
55
+ args.refreshFrom = argv[index + 1] ?? "";
56
+ index += 1;
57
+ continue;
58
+ }
47
59
  if (token === "--from-ref") {
48
60
  args.fromRef = argv[index + 1] ?? "";
49
61
  index += 1;
@@ -184,6 +196,12 @@ function updateCurrentSurfaceFile(file, oldVersion, nextVersion) {
184
196
  writeText(file, content);
185
197
  }
186
198
 
199
+ function syncReadmeReleaseSurface(_nextVersion) {
200
+ const readmePath = "README.md";
201
+ // The README uses a dynamic GitHub release badge; no version replacement is needed.
202
+ writeText(readmePath, readText(readmePath));
203
+ }
204
+
187
205
  function syncPackageVersion(nextVersion) {
188
206
  const pkg = readJson("package.json");
189
207
  const lock = readJson("package-lock.json");
@@ -196,6 +214,14 @@ function syncPackageVersion(nextVersion) {
196
214
  writeJson("package-lock.json", lock);
197
215
  }
198
216
 
217
+ function syncSupportBundleVersion(nextVersion) {
218
+ const manifestPath = "support-bundle.json";
219
+ if (!fs.existsSync(manifestPath)) return;
220
+ const manifest = readJson(manifestPath);
221
+ manifest.bundleVersion = nextVersion;
222
+ writeJson(manifestPath, manifest);
223
+ }
224
+
199
225
  function syncPluginVersions(nextVersion) {
200
226
  for (const file of [
201
227
  path.join("plugins", "meta-architect", ".app.json"),
@@ -215,9 +241,13 @@ function syncPluginVersions(nextVersion) {
215
241
  function syncCurrentReleaseFiles(oldVersion, nextVersion) {
216
242
  for (const file of [
217
243
  "README.md",
244
+ "DEMO.md",
245
+ "COVERAGE.md",
218
246
  "RELEASE.md",
219
247
  path.join("docs", "README.md"),
220
248
  path.join("docs", "getting-started.md"),
249
+ path.join("docs", "onboarding.md"),
250
+ path.join("docs", "skills.md"),
221
251
  path.join("docs", "release-spec.md"),
222
252
  path.join("plugins", "meta-architect", "README.md"),
223
253
  ]) {
@@ -228,16 +258,17 @@ function syncCurrentReleaseFiles(oldVersion, nextVersion) {
228
258
  const nextQa = path.join("docs", "qa", `release-readiness-${nextVersion}.md`);
229
259
  fs.renameSync(oldQa, nextQa);
230
260
  updateCurrentSurfaceFile(nextQa, oldVersion, nextVersion);
261
+
262
+ const oldIssueGates = path.join("docs", "qa", `release-issue-gates-${oldVersion}.json`);
263
+ const nextIssueGates = path.join("docs", "qa", `release-issue-gates-${nextVersion}.json`);
264
+ if (fs.existsSync(oldIssueGates)) {
265
+ fs.renameSync(oldIssueGates, nextIssueGates);
266
+ updateCurrentSurfaceFile(nextIssueGates, oldVersion, nextVersion);
267
+ }
231
268
  }
232
269
 
233
270
  function syncSupportingCode(oldVersion, nextVersion) {
234
271
  const replacements = [
235
- {
236
- file: path.join("src", "skills.js"),
237
- search: `release-readiness-${oldVersion}.md`,
238
- replacement: `release-readiness-${nextVersion}.md`,
239
- label: "skills QA path",
240
- },
241
272
  {
242
273
  file: path.join("test", "package-install-smoke.test.js"),
243
274
  search: `jstn-sdk-ma-${oldVersion}.tgz`,
@@ -259,6 +290,9 @@ function syncSupportingCode(oldVersion, nextVersion) {
259
290
 
260
291
  const mcpLiveClientFile = path.join("src", "mcp-live-client.js");
261
292
  const mcpLiveClient = readText(mcpLiveClientFile);
293
+ if (/resolveMcpClientVersion\(packageMetadata\)/.test(mcpLiveClient)) {
294
+ return;
295
+ }
262
296
  if (!/version: "[0-9]+\.[0-9]+\.[0-9]+(?:-dev)?"/.test(mcpLiveClient)) {
263
297
  throw new Error("Expected to find mcp live client version declaration");
264
298
  }
@@ -271,6 +305,27 @@ function syncSupportingCode(oldVersion, nextVersion) {
271
305
  );
272
306
  }
273
307
 
308
+ function refreshCurrentReleaseFiles(oldVersion, currentVersion) {
309
+ for (const file of [
310
+ "README.md",
311
+ "DEMO.md",
312
+ "COVERAGE.md",
313
+ "RELEASE.md",
314
+ path.join("docs", "README.md"),
315
+ path.join("docs", "getting-started.md"),
316
+ path.join("docs", "onboarding.md"),
317
+ path.join("docs", "skills.md"),
318
+ path.join("docs", "release-spec.md"),
319
+ path.join("plugins", "meta-architect", "README.md"),
320
+ path.join("docs", "qa", `release-readiness-${currentVersion}.md`),
321
+ path.join("docs", "qa", `release-issue-gates-${currentVersion}.json`),
322
+ path.join("scripts", "install.sh"),
323
+ path.join("plugins", "meta-architect", "obsidian", "manifest.json"),
324
+ ]) {
325
+ if (fs.existsSync(file)) updateCurrentSurfaceFile(file, oldVersion, currentVersion);
326
+ }
327
+ }
328
+
274
329
  function rewriteReleaseState(nextVersion, previousVersion) {
275
330
  const releasePath = "RELEASE.md";
276
331
  const qaPath = path.join("docs", "qa", `release-readiness-${nextVersion}.md`);
@@ -319,6 +374,13 @@ function main() {
319
374
  const args = parseArgs(process.argv.slice(2));
320
375
  const pkg = readJson("package.json");
321
376
  const currentVersion = pkg.version;
377
+ if (args.refreshFrom) {
378
+ refreshCurrentReleaseFiles(args.refreshFrom, currentVersion);
379
+ console.log(
380
+ JSON.stringify({ updated: true, refreshed: true, version: currentVersion }, null, 2),
381
+ );
382
+ return;
383
+ }
322
384
  const changedFiles = getChangedFiles(args);
323
385
  const relevantChanges = args.force ? ["<forced>"] : changedFiles.filter(isWatchedPath);
324
386
 
@@ -342,12 +404,15 @@ function main() {
342
404
  }
343
405
 
344
406
  const bumpKind = args.bump || "patch";
345
- const nextVersion = bumpVersion(currentVersion, bumpKind);
407
+ const nextVersion = args.version || bumpVersion(currentVersion, bumpKind);
408
+ parseVersion(nextVersion);
346
409
 
347
410
  syncPackageVersion(nextVersion);
411
+ syncSupportBundleVersion(nextVersion);
348
412
  syncPluginVersions(nextVersion);
349
413
  prependChangelog(nextVersion);
350
414
  syncCurrentReleaseFiles(currentVersion, nextVersion);
415
+ syncReadmeReleaseSurface(nextVersion);
351
416
  syncSupportingCode(currentVersion, nextVersion);
352
417
  rewriteReleaseState(nextVersion, currentVersion);
353
418
 
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import { execFileSync } from "node:child_process";
4
+ import crypto from "node:crypto";
3
5
  import fs from "node:fs";
4
6
  import path from "node:path";
5
7
  import process from "node:process";
@@ -7,8 +9,6 @@ import { validateReleaseIssueGates } from "../src/release-issue-gates.js";
7
9
 
8
10
  const CANONICAL_PACKAGE = "@jstn-sdk/ma";
9
11
  const CANONICAL_INSTALL = "npm i -g @openai/codex@latest @jstn-sdk/ma@latest";
10
- const CDN_INSTALL =
11
- "curl -fsSL https://cdn.jsdelivr.net/gh/JustineDevs/meta-architect@main/scripts/install.sh | sh";
12
12
  const CANONICAL_LAUNCH = "ma --madmax --high";
13
13
  const UNINSTALL_MA = "npm uninstall -g @jstn-sdk/ma";
14
14
  const UNINSTALL_BOTH = "npm uninstall -g @jstn-sdk/ma @openai/codex";
@@ -41,13 +41,18 @@ function parseVersion(version) {
41
41
  return match.groups;
42
42
  }
43
43
 
44
+ function latestCdnInstall() {
45
+ return "curl -fsSLo install.sh https://cdn.jsdelivr.net/gh/JustineDevs/meta-architect@latest/scripts/install.sh && curl -fsSLo install.sh.sha256 https://cdn.jsdelivr.net/gh/JustineDevs/meta-architect@latest/scripts/install.sh.sha256 && sed 's#scripts/install.sh#install.sh#' install.sh.sha256 | sha256sum -c - && sh install.sh";
46
+ }
47
+
44
48
  function verifyInstallBlock(file) {
45
49
  const content = readText(file);
46
- if (!content.includes(CANONICAL_INSTALL) && !content.includes(CDN_INSTALL)) {
50
+ const cdnInstall = latestCdnInstall();
51
+ if (!content.includes(CANONICAL_INSTALL) && !content.includes(cdnInstall)) {
47
52
  return;
48
53
  }
49
54
 
50
- assert(content.includes(CDN_INSTALL), `${file}: missing jsDelivr POSIX installer command`);
55
+ assert(content.includes(cdnInstall), `${file}: missing jsDelivr POSIX installer command`);
51
56
  assert(content.includes(CANONICAL_INSTALL), `${file}: missing canonical npm install command`);
52
57
  assert(content.includes(CANONICAL_LAUNCH), `${file}: missing canonical launch command`);
53
58
  assert(content.includes(UNINSTALL_MA), `${file}: missing uninstall Meta-Architect command`);
@@ -77,12 +82,29 @@ function verifyNpmIgnore() {
77
82
  }
78
83
  }
79
84
 
85
+ function verifyDistPolicy() {
86
+ const tracked = execFileSync("git", ["ls-files", "dist/"], { encoding: "utf8" }).trim();
87
+ assert(!tracked, `dist/: generated release artifacts must not be tracked:\n${tracked}`);
88
+ }
89
+
90
+ function verifyInstallerIntegrity() {
91
+ const installer = readText("scripts/install.sh");
92
+ const checksum = readText("scripts/install.sh.sha256").trim().split(/\s+/)[0];
93
+ const actual = crypto.createHash("sha256").update(installer).digest("hex");
94
+ assert(checksum === actual, "scripts/install.sh.sha256: checksum does not match installer");
95
+ assert(
96
+ !installer.includes("raw.githubusercontent.com") && !installer.includes("jsdelivr"),
97
+ "scripts/install.sh: must not fetch mutable installer sources at runtime",
98
+ );
99
+ }
100
+
80
101
  function verifyDemoDoc({ version, gitTag }) {
102
+ const cdnInstall = latestCdnInstall();
81
103
  assert(fs.existsSync("DEMO.md"), "DEMO.md: missing demo guide");
82
104
  const content = readText("DEMO.md");
83
105
  assert(content.includes(`Release line: \`${gitTag}\``), "DEMO.md: wrong release line");
84
106
  assert(content.includes("Package: `@jstn-sdk/ma`"), "DEMO.md: missing package name");
85
- assert(content.includes(CDN_INSTALL), "DEMO.md: missing jsDelivr installer");
107
+ assert(content.includes(cdnInstall), "DEMO.md: missing versioned installer");
86
108
  assert(content.includes(CANONICAL_INSTALL), "DEMO.md: missing canonical npm install");
87
109
  assert(content.includes(CANONICAL_LAUNCH), "DEMO.md: missing canonical launch");
88
110
  assert(content.includes(UNINSTALL_MA), "DEMO.md: missing MA uninstall command");
@@ -131,6 +153,73 @@ function verifyCoverageDoc({ version, gitTag }) {
131
153
  assert(!content.includes("v0.1.0 release bar"), "COVERAGE.md: stale release bar");
132
154
  }
133
155
 
156
+ function verifyReadmeReleaseSurface({ gitTag }) {
157
+ const content = readText("README.md");
158
+ 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 logoImage = `<img src="https://raw.githubusercontent.com/JustineDevs/meta-architect/${gitTag}/docs/assets/meta-architect-logo.svg" alt="Meta-Architect: quality gates and evidence verification for AI coding agents" width="1024" height="240">`;
160
+ assert(content.includes("> [!NOTE]"), "README.md: missing product-positioning note admonition");
161
+ assert(
162
+ content.includes(
163
+ "> Meta-Architect is a workflow layer for teams that want architecture, evidence, review, and release discipline before build execution.",
164
+ ),
165
+ "README.md: missing workflow-layer positioning note",
166
+ );
167
+ assert(
168
+ content.includes("> Meta-Architect does not replace your coding runtime."),
169
+ "README.md: missing runtime-wrapper boundary note",
170
+ );
171
+ assert(
172
+ content.includes(
173
+ "> It wraps that runtime with architecture, evidence, gate enforcement, and release-sensitive workflow control.",
174
+ ),
175
+ "README.md: missing runtime-wrapper behavior note",
176
+ );
177
+ assert(content.includes(demoImage), "README.md: missing requested 800px demo GIF");
178
+ assert(
179
+ content.includes("<summary><strong>🔌 All 33 plugins & features</strong></summary>"),
180
+ "README.md: missing all 33 plugins/features toggle",
181
+ );
182
+ assert(
183
+ content.includes(
184
+ "https://img.shields.io/github/v/release/JustineDevs/meta-architect?display_name=tag&sort=semver",
185
+ ),
186
+ "README.md: missing GitHub release badge",
187
+ );
188
+ assert(content.includes(logoImage), "README.md: release-pinned logo missing");
189
+ assert(
190
+ !content.includes("raw.githubusercontent.com/JustineDevs/meta-architect/main/"),
191
+ "README.md: stable docs must not reference mutable main",
192
+ );
193
+ }
194
+
195
+ function verifyRealDemoKit() {
196
+ const runbook = readText(path.join("docs", "demo", "REAL_DEMO_RUNBOOK.md"));
197
+ const story = readText(path.join("docs", "demo", "DEMO_STORY.md"));
198
+ const checklist = readText(path.join("docs", "demo", "PROSPECT_CHECKLIST.md"));
199
+ assert(fs.existsSync(path.join("scripts", "demo-smoke.js")), "scripts/demo-smoke.js: missing");
200
+ assert(
201
+ runbook.includes("npm run demo:smoke"),
202
+ "REAL_DEMO_RUNBOOK.md: missing demo smoke command",
203
+ );
204
+ assert(runbook.includes("$maestro"), "REAL_DEMO_RUNBOOK.md: missing maestro scenario");
205
+ assert(
206
+ runbook.includes("vault_context"),
207
+ "REAL_DEMO_RUNBOOK.md: missing Obsidian context boundary",
208
+ );
209
+ assert(story.includes("Northstar Logistics"), "DEMO_STORY.md: missing realistic buyer story");
210
+ assert(story.includes("npm run release:verify"), "DEMO_STORY.md: missing release proof close");
211
+ assert(
212
+ checklist.includes("Remove `Demo Account`, `Test Company`, `Sample Co`"),
213
+ "PROSPECT_CHECKLIST.md: missing no-test-branding check",
214
+ );
215
+ for (const forbidden of ["Demo Account", "Test Company", "Sample Co"]) {
216
+ assert(
217
+ !runbook.includes(forbidden) && !story.includes(forbidden),
218
+ `demo docs: forbidden visible demo branding ${forbidden}`,
219
+ );
220
+ }
221
+ }
222
+
134
223
  function verifyCanonicalSemanticSurfaces({ version, gitTag }) {
135
224
  const usageWorkflow = readText(path.join("example", "usage-workflow.md"));
136
225
  assert(
@@ -178,7 +267,7 @@ function verifyCanonicalSemanticSurfaces({ version, gitTag }) {
178
267
 
179
268
  const currentQa = readText(path.join("docs", "qa", `release-readiness-${version}.md`));
180
269
  assert(
181
- currentQa.includes("Harden Meta-Architect v0.1.13 semantic core"),
270
+ currentQa.includes(`Harden Meta-Architect ${gitTag} semantic core`),
182
271
  `docs/qa/release-readiness-${version}.md: missing realistic semantic smoke idea`,
183
272
  );
184
273
  assert(
@@ -217,8 +306,12 @@ function main() {
217
306
  assert(pkg.files?.includes("COVERAGE.md"), "package.json: files must include COVERAGE.md");
218
307
 
219
308
  verifyNpmIgnore();
309
+ verifyDistPolicy();
310
+ verifyInstallerIntegrity();
220
311
  verifyDemoDoc({ version, gitTag });
221
312
  verifyCoverageDoc({ version, gitTag });
313
+ verifyReadmeReleaseSurface({ gitTag });
314
+ verifyRealDemoKit();
222
315
  verifyCanonicalSemanticSurfaces({ version, gitTag });
223
316
 
224
317
  const changelog = readText("CHANGELOG.md");
@@ -279,7 +372,7 @@ function main() {
279
372
  path.join("docs", "skills.md"),
280
373
  path.join("plugins", "meta-architect", "README.md"),
281
374
  ]) {
282
- verifyInstallBlock(file);
375
+ verifyInstallBlock(file, gitTag);
283
376
  }
284
377
 
285
378
  const envTag =