@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
package/src/bootstrap.js CHANGED
@@ -1,16 +1,28 @@
1
- import { spawnSync } from "node:child_process";
2
1
  import fs from "node:fs/promises";
3
2
  import os from "node:os";
4
3
  import path from "node:path";
4
+ import { detectInstalled, getAgent } from "./agents.js";
5
5
  import { loadDecisionLog } from "./decision-log.js";
6
+ import { inspectRuntimeStateHealth } from "./fs-utils.js";
6
7
  import {
7
8
  runLocalCapabilityReadinessChecks,
8
9
  validateLocalCapabilities,
9
10
  validateMcpServers,
10
11
  } from "./mcp-config.js";
12
+ import { getMcpBridgeConfiguration, mcpClientVersion } from "./mcp-live-client.js";
11
13
  import { getMcpRootPath, getRepoRoot, getRuntimeWritePath, packageRoot } from "./paths.js";
14
+ import { safeSpawnSync } from "./process-utils.js";
15
+ import { resolveReleaseIssueGates } from "./release-issue-gates.js";
12
16
  import { loadReleaseState } from "./release-state.js";
17
+ import { validateAgentIntegrations } from "./runtime/agent-compat.js";
18
+ import { getArchitectReviewConfiguration } from "./runtime/architect-review.js";
19
+ import { printDoctorStatuses, summarizeDoctorStatuses } from "./runtime/doctor-report.js";
20
+ import { mcpWriteCapabilityStatus } from "./runtime/mcp-authority.js";
21
+ import { loadObsidianVaultConfig } from "./runtime/obsidian-integration-core.js";
22
+ import { inspectRedactionVault } from "./runtime/redaction-gateway.js";
13
23
  import { loadLeaderAuthority, loadRuntimeSnapshot } from "./runtime/runtime-state.js";
24
+ import { findOutdatedSchemas } from "./runtime/schema-migrations.js";
25
+ import { inspectSetupDrift } from "./setup-lifecycle.js";
14
26
  import {
15
27
  areSkillsInstalled,
16
28
  ensureSkillsInstalled,
@@ -18,49 +30,216 @@ import {
18
30
  getSkillInstallRoot,
19
31
  getSupportBundleRoot,
20
32
  isSupportBundleInstalled,
33
+ readInstallReceipt,
21
34
  } from "./skill-installer.js";
22
35
  import { runInit } from "./skills.js";
36
+ import { renderCheckGrid } from "./tui/status-grid.js";
23
37
 
24
38
  function makeStatus(kind, label, detail = "") {
25
39
  return { kind, label, detail };
26
40
  }
27
41
 
28
- function resolveCodexCommand() {
29
- return process.env.MA_CODEX_BIN ?? "codex";
42
+ function inspectMcpBridge() {
43
+ const template = process.env.MA_MCP_REMOTE_BRIDGE_CMD?.trim();
44
+ if (!template) return makeStatus("OK", "MCP remote bridge", "not configured");
45
+ const command = template.split(/\s+/, 1)[0].replace(/^['"]|['"]$/g, "");
46
+ const policy = getMcpBridgeConfiguration();
47
+ const allowed = policy.allowedCommands.some(
48
+ (entry) => entry === command || path.basename(entry) === path.basename(command),
49
+ );
50
+ return makeStatus(
51
+ allowed ? "OK" : "WARN",
52
+ "MCP remote bridge",
53
+ allowed
54
+ ? `${command} is explicitly allowlisted (${policy.source})`
55
+ : `${command} is not allowlisted; configure MA_MCP_REMOTE_BRIDGE_ALLOWLIST or mcp/bridge.json`,
56
+ );
30
57
  }
31
58
 
32
- function runCommand(command, args) {
33
- const isNodeScript = [".js", ".mjs", ".cjs"].includes(path.extname(command));
34
- const finalCommand = isNodeScript ? process.execPath : command;
35
- const finalArgs = isNodeScript ? [command, ...args] : args;
36
- return spawnSync(finalCommand, finalArgs, { encoding: "utf8" });
59
+ function inspectArchitectReview() {
60
+ const template = process.env.MA_ARCHITECT_REVIEW_CMD?.trim();
61
+ if (!template) return makeStatus("OK", "external architect review", "not configured");
62
+ const command = template.split(/\s+/, 1)[0].replace(/^['"]|['"]$/g, "");
63
+ const policy = getArchitectReviewConfiguration();
64
+ const allowed = policy.allowedCommands.some(
65
+ (entry) => entry === command || path.basename(entry) === path.basename(command),
66
+ );
67
+ return makeStatus(
68
+ allowed ? "OK" : "WARN",
69
+ "external architect review",
70
+ allowed
71
+ ? `${command} is explicitly allowlisted (${policy.source})`
72
+ : `${command} is not allowlisted; configure MA_ARCHITECT_REVIEW_ALLOWLIST or .ma/architect-review-policy.json`,
73
+ );
37
74
  }
38
75
 
39
- function inspectCodex() {
40
- const command = resolveCodexCommand();
41
- const result = runCommand(command, ["--version"]);
42
- const version = result.stdout.trim();
43
- if (result.status === 0) {
44
- return {
45
- ok: true,
46
- command,
47
- detail: result.error?.message ?? "",
48
- version,
76
+ export async function inspectWorkspaceNpmrc() {
77
+ const npmrcPath = path.join(getRepoRoot(), ".npmrc");
78
+ try {
79
+ const content = await fs.readFile(npmrcPath, "utf8");
80
+ const hasAuthMaterial = /(?:_authToken|_auth|_password|username)\s*=|token\s*=/i.test(content);
81
+ return makeStatus(
82
+ hasAuthMaterial ? "WARN" : "OK",
83
+ "workspace npm auth",
84
+ hasAuthMaterial
85
+ ? "token-bearing .npmrc detected; use NODE_AUTH_TOKEN or a temporary config outside the workspace"
86
+ : "no token-bearing .npmrc detected",
87
+ );
88
+ } catch (error) {
89
+ if (error?.code === "ENOENT")
90
+ return makeStatus("OK", "workspace npm auth", "no workspace .npmrc");
91
+ return makeStatus("WARN", "workspace npm auth", `unable to inspect .npmrc: ${error.message}`);
92
+ }
93
+ }
94
+
95
+ async function inspectPluginInjectionState() {
96
+ const root = path.join(os.homedir(), ".ma", "backups", "plugins");
97
+ try {
98
+ const plugins = await fs.readdir(root, { withFileTypes: true });
99
+ const receipts = [];
100
+ for (const plugin of plugins) {
101
+ if (!plugin.isDirectory()) continue;
102
+ const runs = await fs.readdir(path.join(root, plugin.name), { withFileTypes: true });
103
+ for (const run of runs.filter((entry) => entry.isDirectory())) {
104
+ const receiptPath = path.join(root, plugin.name, run.name, "receipt.json");
105
+ try {
106
+ receipts.push(JSON.parse(await fs.readFile(receiptPath, "utf8")));
107
+ } catch {
108
+ // Ignore incomplete backup directories.
109
+ }
110
+ }
111
+ }
112
+ const latest = receipts.sort((a, b) => `${b.backupRoot}`.localeCompare(`${a.backupRoot}`))[0];
113
+ const hosts = latest?.vendorInjection?.configured_hosts ?? [];
114
+ return makeStatus(
115
+ "OK",
116
+ "plugin MCP injection state",
117
+ hosts.length > 0 ? `configured hosts: ${hosts.join(", ")}` : "no recorded vendor mutations",
118
+ );
119
+ } catch {
120
+ return makeStatus("OK", "plugin MCP injection state", "no recorded vendor mutations");
121
+ }
122
+ }
123
+
124
+ async function inspectContextHealth() {
125
+ const contextPath = getRuntimeWritePath("context", "project-index.json");
126
+ const briefPath = getRuntimeWritePath("context", "agent-brief.md");
127
+ const hookPath = path.join(getRepoRoot(), ".codex", "hooks.json");
128
+ try {
129
+ const project = JSON.parse(await fs.readFile(contextPath, "utf8"));
130
+ const brief = await fs.readFile(briefPath, "utf8");
131
+ const hooks = JSON.parse(await fs.readFile(hookPath, "utf8"));
132
+ const hookText = JSON.stringify(hooks);
133
+ const hydrated =
134
+ hookText.includes("context-hydration-hook.mjs") ||
135
+ hookText.includes("ma hook context-hydration");
136
+ const hookFiles = [];
137
+ const collectHookCommands = (value) => {
138
+ if (Array.isArray(value)) return value.forEach(collectHookCommands);
139
+ if (!value || typeof value !== "object") return;
140
+ if (typeof value.command === "string") hookFiles.push(value.command);
141
+ Object.values(value).forEach(collectHookCommands);
49
142
  };
143
+ collectHookCommands(hooks);
144
+ const brokenHookCommands = [];
145
+ for (const command of hookFiles) {
146
+ const relative = command.match(/^node\s+([^\s]+)/)?.[1];
147
+ if (!relative) continue;
148
+ try {
149
+ await fs.access(path.resolve(getRepoRoot(), relative));
150
+ } catch {
151
+ brokenHookCommands.push(relative);
152
+ }
153
+ }
154
+ const freshness = project.freshness?.status ?? "unknown";
155
+ const outdated = await findOutdatedSchemas(getRepoRoot());
156
+ const runtimeFindings = await inspectRuntimeStateHealth(getRepoRoot());
157
+ const setupDrift = await inspectSetupDrift(getRepoRoot());
158
+ const mcpWriteStatus = mcpWriteCapabilityStatus();
159
+ return [
160
+ makeStatus(
161
+ setupDrift.length ? "WARN" : "OK",
162
+ "seeded artifact drift",
163
+ setupDrift.length
164
+ ? setupDrift.map((entry) => `${entry.status}: ${entry.path}`).join(", ")
165
+ : "no managed template drift",
166
+ ),
167
+ makeStatus(
168
+ runtimeFindings.length ? "WARN" : "OK",
169
+ "runtime state integrity",
170
+ runtimeFindings.length
171
+ ? runtimeFindings.map((finding) => `${finding.type}: ${finding.path}`).join(", ")
172
+ : "atomic writes and locks healthy",
173
+ ),
174
+ makeStatus(
175
+ freshness === "stale" ? "WARN" : "OK",
176
+ "project context freshness",
177
+ `${freshness}; ${project.quality?.confidence ?? "unknown"} confidence`,
178
+ ),
179
+ makeStatus(brief.trim() ? "OK" : "WARN", "agent context brief", briefPath),
180
+ makeStatus(
181
+ hydrated ? "OK" : "WARN",
182
+ "startup/prompt context hydration",
183
+ hydrated ? hookPath : "run `ma setup`",
184
+ ),
185
+ makeStatus(
186
+ brokenHookCommands.length ? "WARN" : "OK",
187
+ "hook command portability",
188
+ brokenHookCommands.length
189
+ ? `missing: ${brokenHookCommands.join(", ")}`
190
+ : "all local hook scripts are present",
191
+ ),
192
+ makeStatus(
193
+ "OK",
194
+ "Obsidian integration",
195
+ (await loadObsidianVaultConfig())?.vaultPath || process.env.MA_OBSIDIAN_VAULT
196
+ ? "configured"
197
+ : "not configured (explicitly disabled)",
198
+ ),
199
+ await inspectRedactionVault().then((vault) =>
200
+ makeStatus(
201
+ vault.status === "warning" ? "WARN" : "OK",
202
+ "redaction vault policy",
203
+ vault.issues.length > 0
204
+ ? vault.issues.join(", ")
205
+ : `${vault.policy.retentionDays}d retention, ${vault.policy.maxEntries} max entries`,
206
+ ),
207
+ ),
208
+ await inspectWorkspaceNpmrc(),
209
+ makeStatus("OK", "MCP context resources", "local read-only context capability available"),
210
+ makeStatus(
211
+ mcpWriteStatus.readOnly ? "WARN" : "OK",
212
+ "MCP write authority",
213
+ mcpWriteStatus.detail,
214
+ ),
215
+ makeStatus(
216
+ outdated.length ? "WARN" : "OK",
217
+ "runtime schema versions",
218
+ outdated.length ? `${outdated.length} outdated artifact(s); run ma migrate` : "current",
219
+ ),
220
+ ];
221
+ } catch (_error) {
222
+ return [
223
+ makeStatus(
224
+ "WARN",
225
+ "project context health",
226
+ "Run `ma setup` to generate bounded context artifacts",
227
+ ),
228
+ ];
50
229
  }
230
+ }
51
231
 
232
+ function inspectAgent(type = process.env.MA_AGENT || "codex") {
233
+ const result = detectInstalled(type);
52
234
  return {
53
- ok: false,
54
- command,
55
- detail:
56
- (result.error?.message ?? result.stderr.trim() ?? result.stdout.trim()) ||
57
- "Codex command failed",
58
- version: "",
235
+ ok: result.installed,
236
+ detail: result.error || `${getAgent(type).displayName} command failed`,
237
+ version: result.version,
59
238
  };
60
239
  }
61
240
 
62
241
  function listCodexPaths() {
63
- const result = spawnSync("which", ["-a", "codex"], { encoding: "utf8" });
242
+ const result = safeSpawnSync("which", ["-a", "codex"], { encoding: "utf8" });
64
243
  if (result.error || result.status !== 0) {
65
244
  return [];
66
245
  }
@@ -157,6 +336,7 @@ async function inspectLocalScaffold() {
157
336
  getRuntimeWritePath("context", "code-graph-rehearse.json"),
158
337
  getRuntimeWritePath("context", "core-source-ingest.json"),
159
338
  getRuntimeWritePath("context", "learning-loop-core.json"),
339
+ getRuntimeWritePath("context", "project-index.json"),
160
340
  getRuntimeWritePath("context", "obsidian-bridge.json"),
161
341
  getRuntimeWritePath("context", "obsidian-vault-index.json"),
162
342
  getRuntimeWritePath("context", "obsidian-vault-operations.json"),
@@ -177,7 +357,8 @@ async function inspectLocalScaffold() {
177
357
  getRuntimeWritePath("state", "manager-runs.json"),
178
358
  getRuntimeWritePath("state", "maestro-state.json"),
179
359
  getRuntimeWritePath("evidence", "semantic-receipts.json"),
180
- path.join(getRepoRoot(), "docs", "qa", "release-issue-gates-0.1.13.json"),
360
+ resolveReleaseIssueGates(getRepoRoot())?.path ??
361
+ path.join(getRepoRoot(), "docs", "qa", "release-issue-gates-missing.json"),
181
362
  path.join(getMcpRootPath(), "servers.json"),
182
363
  path.join(getMcpRootPath(), "local-capabilities.json"),
183
364
  ];
@@ -319,48 +500,59 @@ async function inspectLocalCapabilityState({ fix }) {
319
500
  }
320
501
 
321
502
  async function runEnvironmentFlow({ fix, initMcp }) {
322
- const statuses = [];
503
+ const statuses = [makeStatus("OK", "MCP client version", mcpClientVersion)];
504
+ statuses.push(inspectMcpBridge());
505
+ statuses.push(inspectArchitectReview());
323
506
 
324
- const codexResolution = await inspectCodexResolution({ fix });
507
+ const agentType = process.env.MA_AGENT?.trim() || "codex";
508
+ const agent = getAgent(agentType);
509
+ const codexResolution = agentType === "codex" ? await inspectCodexResolution({ fix }) : null;
325
510
  if (codexResolution) {
326
511
  statuses.push(codexResolution);
327
512
  }
328
513
 
329
- const codex = inspectCodex();
330
- if (codex.ok) {
331
- statuses.push(makeStatus("OK", "codex command is available", codex.version));
514
+ const installed = inspectAgent(agentType);
515
+ if (installed.ok) {
516
+ statuses.push(makeStatus("OK", `${agent.displayName} command is available`, installed.version));
332
517
  } else {
333
518
  statuses.push(
334
519
  makeStatus(
335
520
  "BLOCKED",
336
- "codex command is not usable",
337
- "Install or repair Codex with: npm install -g @openai/codex@latest",
521
+ `${agent.displayName} command is not usable`,
522
+ installed.detail || "Install or repair the selected agent command.",
338
523
  ),
339
524
  );
340
525
  }
341
526
 
342
- const skillInstallRoot = getSkillInstallRoot();
527
+ const skillInstallRoot = getSkillInstallRoot(agent.id);
343
528
  if (fix) {
344
529
  const result = await ensureSkillsInstalled();
345
530
  statuses.push(
346
531
  makeStatus(
347
532
  result.installed.length > 0 ? "FIXED" : "OK",
348
- "Codex skills are installed",
533
+ `${agent.displayName} skills are installed`,
349
534
  skillInstallRoot,
350
535
  ),
351
536
  );
352
537
  } else {
538
+ const receipt = await readInstallReceipt(skillInstallRoot, "skills");
353
539
  statuses.push(
354
540
  makeStatus(
355
541
  (await areSkillsInstalled()) ? "OK" : "WARN",
356
- "Codex skills install state",
357
- skillInstallRoot,
542
+ `${agent.displayName} skills install state`,
543
+ receipt
544
+ ? `${skillInstallRoot} (v${receipt.packageVersion}, receipt present)`
545
+ : `${skillInstallRoot} (receipt missing)`,
358
546
  ),
359
547
  );
360
548
  }
361
549
 
362
550
  const supportBundleRoot = getSupportBundleRoot();
363
- if (fix) {
551
+ if (agent.id !== "codex") {
552
+ statuses.push(
553
+ makeStatus("OK", "Codex support bundle", "not applicable to the selected agent surface"),
554
+ );
555
+ } else if (fix) {
364
556
  const result = await ensureSupportBundleInstalled();
365
557
  statuses.push(
366
558
  makeStatus(
@@ -370,11 +562,14 @@ async function runEnvironmentFlow({ fix, initMcp }) {
370
562
  ),
371
563
  );
372
564
  } else {
565
+ const receipt = await readInstallReceipt(supportBundleRoot, "support");
373
566
  statuses.push(
374
567
  makeStatus(
375
568
  (await isSupportBundleInstalled()) ? "OK" : "WARN",
376
569
  "support bundle install state",
377
- supportBundleRoot,
570
+ receipt
571
+ ? `${supportBundleRoot} (v${receipt.bundleVersion}, receipt present)`
572
+ : `${supportBundleRoot} (receipt missing)`,
378
573
  ),
379
574
  );
380
575
  }
@@ -403,35 +598,43 @@ async function runEnvironmentFlow({ fix, initMcp }) {
403
598
 
404
599
  statuses.push(await inspectGitMcpState({ fix, initMcp }));
405
600
  statuses.push(await inspectLocalCapabilityState({ fix }));
406
- return statuses;
407
- }
408
-
409
- function summarizeStatuses(statuses) {
410
- const hasBlocked = statuses.some((status) => status.kind === "BLOCKED");
411
- const hasWarn = statuses.some((status) => status.kind === "WARN");
412
- if (hasBlocked) {
413
- return "BLOCKED";
414
- }
415
- if (hasWarn) {
416
- return "READY_WITH_WARNINGS";
601
+ statuses.push(...(await inspectContextHealth()));
602
+ statuses.push(await inspectPluginInjectionState());
603
+ if (agent.id === "cursor") {
604
+ try {
605
+ const validation = await validateAgentIntegrations(getRepoRoot(), { targets: ["cursor"] });
606
+ const cursorResult = validation.results.cursor;
607
+ statuses.push(
608
+ makeStatus(
609
+ cursorResult?.status === "valid" ? "OK" : "WARN",
610
+ "Cursor native project rules",
611
+ cursorResult?.status === "valid"
612
+ ? ".cursor/rules/agents.mdc validated"
613
+ : cursorResult?.issues?.map((issue) => issue.message).join(", ") || "run `ma setup`",
614
+ ),
615
+ );
616
+ } catch (error) {
617
+ statuses.push(makeStatus("WARN", "Cursor native project rules", error.message));
618
+ }
417
619
  }
418
- return "READY";
620
+ return statuses;
419
621
  }
420
622
 
421
623
  function printStatuses(title, statuses) {
422
- console.log(title);
423
- console.log("=".repeat(title.length));
424
- for (const status of statuses) {
425
- const label = status.kind.padEnd(7, " ");
426
- if (status.detail) {
427
- console.log(`${label} ${status.label}: ${status.detail}`);
428
- } else {
429
- console.log(`${label} ${status.label}`);
430
- }
624
+ if (process.stdout.isTTY) {
625
+ const result = summarizeDoctorStatuses(statuses);
626
+ console.log(title);
627
+ console.log("=".repeat(title.length));
628
+ console.log(renderCheckGrid(statuses));
629
+ console.log(`\nResult: ${result}`);
630
+ console.log(
631
+ result === "BLOCKED"
632
+ ? "Next: install or repair blocked prerequisites, then rerun `ma bootstrap`."
633
+ : "Next: start Codex or run `ma run '$maestro'`.",
634
+ );
635
+ return result;
431
636
  }
432
- const result = summarizeStatuses(statuses);
433
- console.log();
434
- console.log(`Result: ${result}`);
637
+ const result = printDoctorStatuses(title, statuses);
435
638
  if (result === "BLOCKED") {
436
639
  console.log("Next: install or repair blocked prerequisites, then rerun `ma bootstrap`.");
437
640
  } else if (result === "READY_WITH_WARNINGS") {
@@ -442,16 +645,20 @@ function printStatuses(title, statuses) {
442
645
  return result;
443
646
  }
444
647
 
445
- export async function runDoctor() {
648
+ export async function runDoctor({ json = false } = {}) {
446
649
  const statuses = await runEnvironmentFlow({ fix: false, initMcp: false });
650
+ const result = summarizeDoctorStatuses(statuses);
651
+ if (json) return { schemaVersion: "0.1.0", scope: "environment", result, statuses };
447
652
  return {
448
653
  statuses,
449
654
  result: printStatuses("Meta-Architect Doctor", statuses),
450
655
  };
451
656
  }
452
657
 
453
- export async function runBootstrap({ initMcp = false } = {}) {
658
+ export async function runBootstrap({ initMcp = false, json = false } = {}) {
454
659
  const statuses = await runEnvironmentFlow({ fix: true, initMcp });
660
+ const result = summarizeDoctorStatuses(statuses);
661
+ if (json) return { schemaVersion: "0.1.0", scope: "bootstrap", result, statuses };
455
662
  return {
456
663
  statuses,
457
664
  result: printStatuses("Meta-Architect Bootstrap", statuses),
package/src/build-gate.js CHANGED
File without changes