@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
@@ -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,10 +214,19 @@ 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"),
202
228
  path.join("plugins", "meta-architect", ".mcp.json"),
229
+ path.join("plugins", "meta-architect", "obsidian", "manifest.json"),
203
230
  ]) {
204
231
  const value = readJson(file);
205
232
  value.version = nextVersion;
@@ -210,14 +237,28 @@ function syncPluginVersions(nextVersion) {
210
237
  const pluginManifest = readJson(pluginManifestFile);
211
238
  pluginManifest.version = nextVersion;
212
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);
213
250
  }
214
251
 
215
252
  function syncCurrentReleaseFiles(oldVersion, nextVersion) {
216
253
  for (const file of [
217
254
  "README.md",
255
+ "DEMO.md",
256
+ "COVERAGE.md",
218
257
  "RELEASE.md",
219
258
  path.join("docs", "README.md"),
220
259
  path.join("docs", "getting-started.md"),
260
+ path.join("docs", "onboarding.md"),
261
+ path.join("docs", "skills.md"),
221
262
  path.join("docs", "release-spec.md"),
222
263
  path.join("plugins", "meta-architect", "README.md"),
223
264
  ]) {
@@ -228,16 +269,17 @@ function syncCurrentReleaseFiles(oldVersion, nextVersion) {
228
269
  const nextQa = path.join("docs", "qa", `release-readiness-${nextVersion}.md`);
229
270
  fs.renameSync(oldQa, nextQa);
230
271
  updateCurrentSurfaceFile(nextQa, oldVersion, nextVersion);
272
+
273
+ const oldIssueGates = path.join("docs", "qa", `release-issue-gates-${oldVersion}.json`);
274
+ const nextIssueGates = path.join("docs", "qa", `release-issue-gates-${nextVersion}.json`);
275
+ if (fs.existsSync(oldIssueGates)) {
276
+ fs.renameSync(oldIssueGates, nextIssueGates);
277
+ updateCurrentSurfaceFile(nextIssueGates, oldVersion, nextVersion);
278
+ }
231
279
  }
232
280
 
233
281
  function syncSupportingCode(oldVersion, nextVersion) {
234
282
  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
283
  {
242
284
  file: path.join("test", "package-install-smoke.test.js"),
243
285
  search: `jstn-sdk-ma-${oldVersion}.tgz`,
@@ -259,6 +301,9 @@ function syncSupportingCode(oldVersion, nextVersion) {
259
301
 
260
302
  const mcpLiveClientFile = path.join("src", "mcp-live-client.js");
261
303
  const mcpLiveClient = readText(mcpLiveClientFile);
304
+ if (/resolveMcpClientVersion\(packageMetadata\)/.test(mcpLiveClient)) {
305
+ return;
306
+ }
262
307
  if (!/version: "[0-9]+\.[0-9]+\.[0-9]+(?:-dev)?"/.test(mcpLiveClient)) {
263
308
  throw new Error("Expected to find mcp live client version declaration");
264
309
  }
@@ -271,6 +316,27 @@ function syncSupportingCode(oldVersion, nextVersion) {
271
316
  );
272
317
  }
273
318
 
319
+ function refreshCurrentReleaseFiles(oldVersion, currentVersion) {
320
+ for (const file of [
321
+ "README.md",
322
+ "DEMO.md",
323
+ "COVERAGE.md",
324
+ "RELEASE.md",
325
+ path.join("docs", "README.md"),
326
+ path.join("docs", "getting-started.md"),
327
+ path.join("docs", "onboarding.md"),
328
+ path.join("docs", "skills.md"),
329
+ path.join("docs", "release-spec.md"),
330
+ path.join("plugins", "meta-architect", "README.md"),
331
+ path.join("docs", "qa", `release-readiness-${currentVersion}.md`),
332
+ path.join("docs", "qa", `release-issue-gates-${currentVersion}.json`),
333
+ path.join("scripts", "install.sh"),
334
+ path.join("plugins", "meta-architect", "obsidian", "manifest.json"),
335
+ ]) {
336
+ if (fs.existsSync(file)) updateCurrentSurfaceFile(file, oldVersion, currentVersion);
337
+ }
338
+ }
339
+
274
340
  function rewriteReleaseState(nextVersion, previousVersion) {
275
341
  const releasePath = "RELEASE.md";
276
342
  const qaPath = path.join("docs", "qa", `release-readiness-${nextVersion}.md`);
@@ -319,6 +385,13 @@ function main() {
319
385
  const args = parseArgs(process.argv.slice(2));
320
386
  const pkg = readJson("package.json");
321
387
  const currentVersion = pkg.version;
388
+ if (args.refreshFrom) {
389
+ refreshCurrentReleaseFiles(args.refreshFrom, currentVersion);
390
+ console.log(
391
+ JSON.stringify({ updated: true, refreshed: true, version: currentVersion }, null, 2),
392
+ );
393
+ return;
394
+ }
322
395
  const changedFiles = getChangedFiles(args);
323
396
  const relevantChanges = args.force ? ["<forced>"] : changedFiles.filter(isWatchedPath);
324
397
 
@@ -342,12 +415,15 @@ function main() {
342
415
  }
343
416
 
344
417
  const bumpKind = args.bump || "patch";
345
- const nextVersion = bumpVersion(currentVersion, bumpKind);
418
+ const nextVersion = args.version || bumpVersion(currentVersion, bumpKind);
419
+ parseVersion(nextVersion);
346
420
 
347
421
  syncPackageVersion(nextVersion);
422
+ syncSupportBundleVersion(nextVersion);
348
423
  syncPluginVersions(nextVersion);
349
424
  prependChangelog(nextVersion);
350
425
  syncCurrentReleaseFiles(currentVersion, nextVersion);
426
+ syncReadmeReleaseSurface(nextVersion);
351
427
  syncSupportingCode(currentVersion, nextVersion);
352
428
  rewriteReleaseState(nextVersion, currentVersion);
353
429
 
@@ -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,29 @@ 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
+ const htmlCdnInstall = cdnInstall.replaceAll("&&", "&amp;&amp;");
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) {
47
60
  return;
48
61
  }
49
62
 
50
- assert(content.includes(CDN_INSTALL), `${file}: missing jsDelivr POSIX installer command`);
63
+ assert(
64
+ content.includes(cdnInstall) || content.includes(htmlCdnInstall) || splitCdnInstall,
65
+ `${file}: missing jsDelivr POSIX installer command`,
66
+ );
51
67
  assert(content.includes(CANONICAL_INSTALL), `${file}: missing canonical npm install command`);
52
68
  assert(content.includes(CANONICAL_LAUNCH), `${file}: missing canonical launch command`);
53
69
  assert(content.includes(UNINSTALL_MA), `${file}: missing uninstall Meta-Architect command`);
@@ -77,12 +93,29 @@ function verifyNpmIgnore() {
77
93
  }
78
94
  }
79
95
 
96
+ function verifyDistPolicy() {
97
+ const tracked = execFileSync("git", ["ls-files", "dist/"], { encoding: "utf8" }).trim();
98
+ assert(!tracked, `dist/: generated release artifacts must not be tracked:\n${tracked}`);
99
+ }
100
+
101
+ function verifyInstallerIntegrity() {
102
+ const installer = readText("scripts/install.sh");
103
+ const checksum = readText("scripts/install.sh.sha256").trim().split(/\s+/)[0];
104
+ const actual = crypto.createHash("sha256").update(installer).digest("hex");
105
+ assert(checksum === actual, "scripts/install.sh.sha256: checksum does not match installer");
106
+ assert(
107
+ !installer.includes("raw.githubusercontent.com") && !installer.includes("jsdelivr"),
108
+ "scripts/install.sh: must not fetch mutable installer sources at runtime",
109
+ );
110
+ }
111
+
80
112
  function verifyDemoDoc({ version, gitTag }) {
113
+ const cdnInstall = latestCdnInstall();
81
114
  assert(fs.existsSync("DEMO.md"), "DEMO.md: missing demo guide");
82
115
  const content = readText("DEMO.md");
83
116
  assert(content.includes(`Release line: \`${gitTag}\``), "DEMO.md: wrong release line");
84
117
  assert(content.includes("Package: `@jstn-sdk/ma`"), "DEMO.md: missing package name");
85
- assert(content.includes(CDN_INSTALL), "DEMO.md: missing jsDelivr installer");
118
+ assert(content.includes(cdnInstall), "DEMO.md: missing versioned installer");
86
119
  assert(content.includes(CANONICAL_INSTALL), "DEMO.md: missing canonical npm install");
87
120
  assert(content.includes(CANONICAL_LAUNCH), "DEMO.md: missing canonical launch");
88
121
  assert(content.includes(UNINSTALL_MA), "DEMO.md: missing MA uninstall command");
@@ -131,6 +164,77 @@ function verifyCoverageDoc({ version, gitTag }) {
131
164
  assert(!content.includes("v0.1.0 release bar"), "COVERAGE.md: stale release bar");
132
165
  }
133
166
 
167
+ function verifyReadmeReleaseSurface({ gitTag }) {
168
+ const content = readText("README.md");
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">`;
170
+ const bannerImage = `<img src="./docs/assets/banner.png" alt="Meta-Architect: quality gates and evidence verification for AI coding agents" width="1000">`;
171
+ assert(content.includes("> [!NOTE]"), "README.md: missing product-positioning note admonition");
172
+ assert(
173
+ content.includes(
174
+ "> Meta-Architect is a workflow layer for teams that want architecture, evidence, review, and release discipline before build execution.",
175
+ ),
176
+ "README.md: missing workflow-layer positioning note",
177
+ );
178
+ assert(
179
+ content.includes("> Meta-Architect does not replace your coding runtime."),
180
+ "README.md: missing runtime-wrapper boundary note",
181
+ );
182
+ assert(
183
+ content.includes(
184
+ "> It wraps that runtime with architecture, evidence, gate enforcement, and release-sensitive workflow control.",
185
+ ),
186
+ "README.md: missing runtime-wrapper behavior note",
187
+ );
188
+ assert(content.includes(demoImage), "README.md: missing requested 800px demo GIF");
189
+ assert(
190
+ content.includes("<summary><strong>🔌 All 33 plugins & features</strong></summary>"),
191
+ "README.md: missing all 33 plugins/features toggle",
192
+ );
193
+ assert(
194
+ content.includes(
195
+ "https://img.shields.io/github/v/release/JustineDevs/meta-architect?display_name=tag&sort=semver",
196
+ ),
197
+ "README.md: missing GitHub release badge",
198
+ );
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");
204
+ assert(
205
+ !content.includes("raw.githubusercontent.com/JustineDevs/meta-architect/main/"),
206
+ "README.md: stable docs must not reference mutable main",
207
+ );
208
+ }
209
+
210
+ function verifyRealDemoKit() {
211
+ const runbook = readText(path.join("docs", "demo", "REAL_DEMO_RUNBOOK.md"));
212
+ const story = readText(path.join("docs", "demo", "DEMO_STORY.md"));
213
+ const checklist = readText(path.join("docs", "demo", "PROSPECT_CHECKLIST.md"));
214
+ assert(fs.existsSync(path.join("scripts", "demo-smoke.js")), "scripts/demo-smoke.js: missing");
215
+ assert(
216
+ runbook.includes("npm run demo:smoke"),
217
+ "REAL_DEMO_RUNBOOK.md: missing demo smoke command",
218
+ );
219
+ assert(runbook.includes("$maestro"), "REAL_DEMO_RUNBOOK.md: missing maestro scenario");
220
+ assert(
221
+ runbook.includes("vault_context"),
222
+ "REAL_DEMO_RUNBOOK.md: missing Obsidian context boundary",
223
+ );
224
+ assert(story.includes("Northstar Logistics"), "DEMO_STORY.md: missing realistic buyer story");
225
+ assert(story.includes("npm run release:verify"), "DEMO_STORY.md: missing release proof close");
226
+ assert(
227
+ checklist.includes("Remove `Demo Account`, `Test Company`, `Sample Co`"),
228
+ "PROSPECT_CHECKLIST.md: missing no-test-branding check",
229
+ );
230
+ for (const forbidden of ["Demo Account", "Test Company", "Sample Co"]) {
231
+ assert(
232
+ !runbook.includes(forbidden) && !story.includes(forbidden),
233
+ `demo docs: forbidden visible demo branding ${forbidden}`,
234
+ );
235
+ }
236
+ }
237
+
134
238
  function verifyCanonicalSemanticSurfaces({ version, gitTag }) {
135
239
  const usageWorkflow = readText(path.join("example", "usage-workflow.md"));
136
240
  assert(
@@ -178,7 +282,7 @@ function verifyCanonicalSemanticSurfaces({ version, gitTag }) {
178
282
 
179
283
  const currentQa = readText(path.join("docs", "qa", `release-readiness-${version}.md`));
180
284
  assert(
181
- currentQa.includes("Harden Meta-Architect v0.1.13 semantic core"),
285
+ currentQa.includes(`Harden Meta-Architect ${gitTag} semantic core`),
182
286
  `docs/qa/release-readiness-${version}.md: missing realistic semantic smoke idea`,
183
287
  );
184
288
  assert(
@@ -217,8 +321,12 @@ function main() {
217
321
  assert(pkg.files?.includes("COVERAGE.md"), "package.json: files must include COVERAGE.md");
218
322
 
219
323
  verifyNpmIgnore();
324
+ verifyDistPolicy();
325
+ verifyInstallerIntegrity();
220
326
  verifyDemoDoc({ version, gitTag });
221
327
  verifyCoverageDoc({ version, gitTag });
328
+ verifyReadmeReleaseSurface({ gitTag });
329
+ verifyRealDemoKit();
222
330
  verifyCanonicalSemanticSurfaces({ version, gitTag });
223
331
 
224
332
  const changelog = readText("CHANGELOG.md");
@@ -263,12 +371,28 @@ function main() {
263
371
  const pluginManifest = readJson(
264
372
  path.join("plugins", "meta-architect", ".codex-plugin", "plugin.json"),
265
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
+ );
266
378
  assert(pluginApp.version === version, "plugins/meta-architect/.app.json: version drift");
267
379
  assert(pluginMcp.version === version, "plugins/meta-architect/.mcp.json: version drift");
268
380
  assert(
269
381
  pluginManifest.version === version,
270
382
  "plugins/meta-architect/.codex-plugin/plugin.json: version drift",
271
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
+ );
272
396
 
273
397
  for (const file of [
274
398
  "README.md",
@@ -279,7 +403,7 @@ function main() {
279
403
  path.join("docs", "skills.md"),
280
404
  path.join("plugins", "meta-architect", "README.md"),
281
405
  ]) {
282
- verifyInstallBlock(file);
406
+ verifyInstallBlock(file, gitTag);
283
407
  }
284
408
 
285
409
  const envTag =
@@ -1,39 +1,64 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import { randomUUID } from "node:crypto";
3
4
  import fs from "node:fs/promises";
5
+ import os from "node:os";
4
6
  import path from "node:path";
5
7
  import process from "node:process";
8
+ import { fileURLToPath } from "node:url";
6
9
 
7
- function normalizeRegistry(registryUrl) {
8
- return registryUrl.endsWith("/") ? registryUrl : `${registryUrl}/`;
10
+ export async function createTemporaryNpmConfig({
11
+ token,
12
+ registry = "https://registry.npmjs.org/",
13
+ scope = "",
14
+ tempRoot = process.env.RUNNER_TEMP || os.tmpdir(),
15
+ } = {}) {
16
+ if (!token) return null;
17
+ const normalizedRegistry = registry.endsWith("/") ? registry : `${registry}/`;
18
+ const host = new URL(normalizedRegistry).host;
19
+ const configPath = path.join(tempRoot, `meta-architect-npmrc-${randomUUID()}`);
20
+ const content = [
21
+ `registry=${normalizedRegistry}`,
22
+ ...(scope ? [`${scope}:registry=${normalizedRegistry}`] : []),
23
+ `//${host}/:_authToken=${token}`,
24
+ "",
25
+ ].join("\n");
26
+
27
+ await fs.writeFile(configPath, content, { encoding: "utf8", mode: 0o600 });
28
+ await fs.chmod(configPath, 0o600);
29
+ return configPath;
30
+ }
31
+
32
+ export async function cleanupTemporaryNpmConfig(configPath) {
33
+ if (!configPath) return false;
34
+ await fs.rm(configPath, { force: true });
35
+ return true;
9
36
  }
10
37
 
11
38
  async function main() {
12
39
  const token = process.env.NPM_TOKEN || process.env.NODE_AUTH_TOKEN;
13
40
  if (!token) {
14
- console.log("No npm token detected. Skipping .npmrc generation.");
41
+ console.log("No npm token detected. Skipping temporary npm auth config.");
15
42
  return;
16
43
  }
17
44
 
18
- const registry = normalizeRegistry(process.env.NPM_REGISTRY_URL || "https://registry.npmjs.org/");
19
- const scope = process.env.NPM_SCOPE || "";
20
- const host = new URL(registry).host;
21
- const npmrcPath = path.join(process.cwd(), ".npmrc");
22
-
23
- const content = [
24
- `registry=${registry}`,
25
- ...(scope ? [`${scope}:registry=${registry}`] : []),
26
- `//${host}/:_authToken=${token}`,
27
- "",
28
- ].join("\n");
29
-
30
- await fs.writeFile(npmrcPath, content, "utf8");
31
- console.log(
32
- `Wrote CI .npmrc for ${scope ? `scope ${scope}` : "the canonical unscoped package"}.`,
33
- );
45
+ const configPath = await createTemporaryNpmConfig({
46
+ token,
47
+ registry: process.env.NPM_REGISTRY_URL || "https://registry.npmjs.org/",
48
+ scope: process.env.NPM_SCOPE || "",
49
+ });
50
+ if (process.env.GITHUB_ENV) {
51
+ await fs.appendFile(process.env.GITHUB_ENV, `NPM_CONFIG_USERCONFIG=${configPath}\n`);
52
+ }
53
+ console.log("Created temporary npm auth config outside the workspace.");
54
+ if (!process.env.GITHUB_ENV) {
55
+ console.log(`Use NPM_CONFIG_USERCONFIG=${configPath} for the current command.`);
56
+ }
34
57
  }
35
58
 
36
- main().catch((error) => {
37
- console.error(error.message);
38
- process.exitCode = 1;
39
- });
59
+ if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
60
+ main().catch((error) => {
61
+ console.error(error.message);
62
+ process.exitCode = 1;
63
+ });
64
+ }
@@ -1,22 +1,29 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import process from "node:process";
4
- import { installSkills } from "../src/skill-installer.js";
4
+ import { installSkills, rollbackInstalledAssets } from "../src/skill-installer.js";
5
5
 
6
6
  function parseArgs(argv) {
7
- const args = { path: null };
7
+ const args = { path: null, rollback: false };
8
8
  for (let index = 0; index < argv.length; index += 1) {
9
9
  const token = argv[index];
10
10
  if (token === "--path") {
11
11
  args.path = argv[index + 1];
12
12
  index += 1;
13
13
  }
14
+ if (token === "--rollback") args.rollback = true;
14
15
  }
15
16
  return args;
16
17
  }
17
18
 
18
19
  async function main() {
19
20
  const args = parseArgs(process.argv.slice(2));
21
+ if (args.rollback) {
22
+ console.log(
23
+ JSON.stringify(await rollbackInstalledAssets({ targetRoot: args.path ?? undefined })),
24
+ );
25
+ return;
26
+ }
20
27
  const { installed } = await installSkills({ targetRoot: args.path ?? undefined });
21
28
  for (const skill of installed) {
22
29
  console.log(`installed ${skill.name} -> ${skill.dest}`);
@@ -3,31 +3,12 @@
3
3
  import fs from "node:fs/promises";
4
4
  import path from "node:path";
5
5
  import process from "node:process";
6
+ import { parseSkillFrontmatter, validateSkillFrontmatter } from "../src/skill-frontmatter.js";
6
7
 
7
8
  const repoRoot = process.cwd();
8
9
  const skillsRoot = path.join(repoRoot, "skills");
9
10
  const manifestPath = path.join(skillsRoot, "index.json");
10
11
 
11
- function parseFrontmatterNameAndDescription(content) {
12
- const match = content.match(/^---\n([\s\S]*?)\n---/);
13
- if (!match) {
14
- throw new Error("Missing SKILL.md frontmatter");
15
- }
16
-
17
- const lines = match[1].split("\n");
18
- let name = "";
19
- let description = "";
20
- for (const line of lines) {
21
- if (line.startsWith("name:")) {
22
- name = line.slice("name:".length).trim();
23
- }
24
- if (line.startsWith("description:")) {
25
- description = line.slice("description:".length).trim().replace(/^"|"$/g, "");
26
- }
27
- }
28
- return { name, description };
29
- }
30
-
31
12
  async function main() {
32
13
  const entries = await fs.readdir(skillsRoot, { withFileTypes: true });
33
14
  const skills = [];
@@ -39,7 +20,7 @@ async function main() {
39
20
 
40
21
  const skillPath = path.join(skillsRoot, entry.name, "SKILL.md");
41
22
  const content = await fs.readFile(skillPath, "utf8");
42
- const meta = parseFrontmatterNameAndDescription(content);
23
+ const meta = validateSkillFrontmatter(parseSkillFrontmatter(content), entry.name);
43
24
  skills.push({
44
25
  name: meta.name,
45
26
  path: `skills/${entry.name}`,
@@ -2,9 +2,9 @@
2
2
 
3
3
  import { spawnSync } from "node:child_process";
4
4
  import fs from "node:fs/promises";
5
- import os from "node:os";
6
5
  import path from "node:path";
7
6
  import process from "node:process";
7
+ import { createTestNamespace } from "../src/test-fixtures.js";
8
8
 
9
9
  const repoRoot = process.cwd();
10
10
  const distRoot = path.join(repoRoot, "dist");
@@ -28,7 +28,7 @@ async function copyDir(src, dest) {
28
28
  async function main() {
29
29
  await fs.mkdir(distRoot, { recursive: true });
30
30
  await fs.rm(bundlePath, { force: true });
31
- const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "meta-architect-skills-"));
31
+ const tempRoot = createTestNamespace("meta-architect-skills");
32
32
  const frozenSkillsRoot = path.join(tempRoot, "skills");
33
33
  await copyDir(skillsRoot, frozenSkillsRoot);
34
34
 
@@ -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 { parseSkillFrontmatter, validateSkillFrontmatter } from "../src/skill-frontmatter.js";
6
7
 
7
8
  const repoRoot = process.cwd();
8
9
  const skillsRoot = path.join(repoRoot, "skills");
@@ -12,42 +13,6 @@ function fail(message) {
12
13
  process.exitCode = 1;
13
14
  }
14
15
 
15
- function extractFrontmatter(content) {
16
- const match = content.match(/^---\n([\s\S]*?)\n---\n?/);
17
- if (!match) {
18
- return null;
19
- }
20
-
21
- const yaml = match[1];
22
- const result = {};
23
-
24
- for (const rawLine of yaml.split("\n")) {
25
- const line = rawLine.trim();
26
- if (!line || line.startsWith("#")) {
27
- continue;
28
- }
29
-
30
- const separator = line.indexOf(":");
31
- if (separator === -1) {
32
- continue;
33
- }
34
-
35
- const key = line.slice(0, separator).trim();
36
- let value = line.slice(separator + 1).trim();
37
-
38
- if (
39
- (value.startsWith('"') && value.endsWith('"')) ||
40
- (value.startsWith("'") && value.endsWith("'"))
41
- ) {
42
- value = value.slice(1, -1);
43
- }
44
-
45
- result[key] = value;
46
- }
47
-
48
- return result;
49
- }
50
-
51
16
  async function validateSkillDir(skillDir) {
52
17
  const skillName = path.basename(skillDir);
53
18
  const skillPath = path.join(skillDir, "SKILL.md");
@@ -58,25 +23,10 @@ async function validateSkillDir(skillDir) {
58
23
  throw new Error(`${skillName}: missing SKILL.md`);
59
24
  }
60
25
 
61
- const frontmatter = extractFrontmatter(skillContent);
62
- if (!frontmatter) {
63
- throw new Error(`${skillName}: SKILL.md missing frontmatter`);
64
- }
65
-
66
- if (!frontmatter.name) {
67
- throw new Error(`${skillName}: frontmatter missing name`);
68
- }
69
-
70
- if (frontmatter.name !== skillName) {
71
- throw new Error(`${skillName}: frontmatter name must match directory name`);
72
- }
73
-
74
- if (!/^[a-z0-9-]+$/.test(frontmatter.name)) {
75
- throw new Error(`${skillName}: frontmatter name must be lowercase kebab-case`);
76
- }
77
-
78
- if (!frontmatter.description || frontmatter.description.length < 10) {
79
- throw new Error(`${skillName}: frontmatter description is missing or too short`);
26
+ try {
27
+ validateSkillFrontmatter(parseSkillFrontmatter(skillContent), skillName);
28
+ } catch (error) {
29
+ throw new Error(`${skillName}: ${error.message}`);
80
30
  }
81
31
 
82
32
  const agentContent = await fs.readFile(agentPath, "utf8").catch(() => null);
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes