@jstn-sdk/ma 0.1.10 → 0.1.12

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 (133) hide show
  1. package/.agents/plugins/marketplace.json +0 -0
  2. package/README.md +136 -29
  3. package/bin/ma.js +23 -67
  4. package/docs/README.md +4 -1
  5. package/docs/assets/image/Screenshot(1).png +0 -0
  6. package/docs/assets/image/Screenshot(2).png +0 -0
  7. package/docs/assets/image/Screenshot(3).png +0 -0
  8. package/docs/assets/image/Screenshot(4).png +0 -0
  9. package/docs/assets/image/Screenshot(5).png +0 -0
  10. package/docs/assets/image/Screenshot(6).png +0 -0
  11. package/docs/assets/image/Screenshot(7).png +0 -0
  12. package/docs/assets/image/Screenshot(8).png +0 -0
  13. package/docs/assets/image/Screenshot(9).png +0 -0
  14. package/docs/assets/meta-architect-logo.png +0 -0
  15. package/docs/assets/meta-architect-logo.svg +0 -0
  16. package/docs/getting-started.md +74 -19
  17. package/docs/installed-sdk.md +23 -0
  18. package/docs/mcp-setup.md +30 -1
  19. package/docs/qa/{release-readiness-0.1.10.md → release-readiness-0.1.12.md} +29 -8
  20. package/docs/qa/release-readiness-0.1.5.md +0 -0
  21. package/docs/reference/native-engineering-patterns.md +35 -0
  22. package/docs/reference/native-security-playbooks.md +21 -0
  23. package/docs/reference/native-source-selection.md +21 -0
  24. package/docs/reference/native-style-and-deslop.md +20 -0
  25. package/docs/release-spec.md +21 -10
  26. package/docs/skills-publishing.md +25 -1
  27. package/docs/skills.md +24 -12
  28. package/mcp/local/code-intel.js +113 -0
  29. package/mcp/local/memory.js +46 -0
  30. package/mcp/local/playbooks.js +168 -0
  31. package/mcp/local/state.js +71 -0
  32. package/mcp/local/team-run.js +66 -0
  33. package/mcp/local/trace.js +60 -0
  34. package/mcp/local-capabilities.json +56 -0
  35. package/mcp/native-playbooks.json +117 -0
  36. package/mcp/servers.json +10 -0
  37. package/package.json +4 -1
  38. package/plugins/meta-architect/.app.json +1 -1
  39. package/plugins/meta-architect/.codex-plugin/plugin.json +4 -4
  40. package/plugins/meta-architect/.mcp.json +1 -1
  41. package/plugins/meta-architect/README.md +27 -1
  42. package/plugins/meta-architect/skills/align/SKILL.md +24 -0
  43. package/plugins/meta-architect/skills/align/agents/openai.yaml +4 -0
  44. package/plugins/meta-architect/skills/align/references/shared-language.md +24 -0
  45. package/plugins/meta-architect/skills/arch/SKILL.md +0 -0
  46. package/plugins/meta-architect/skills/arch/agents/openai.yaml +0 -0
  47. package/plugins/meta-architect/skills/build/SKILL.md +0 -0
  48. package/plugins/meta-architect/skills/build/agents/openai.yaml +0 -0
  49. package/plugins/meta-architect/skills/cleanup/SKILL.md +23 -0
  50. package/plugins/meta-architect/skills/cleanup/agents/openai.yaml +4 -0
  51. package/plugins/meta-architect/skills/cleanup/references/style-and-deslop.md +18 -0
  52. package/plugins/meta-architect/skills/diagnose/SKILL.md +24 -0
  53. package/plugins/meta-architect/skills/diagnose/agents/openai.yaml +4 -0
  54. package/plugins/meta-architect/skills/flow/SKILL.md +0 -0
  55. package/plugins/meta-architect/skills/flow/agents/openai.yaml +0 -0
  56. package/plugins/meta-architect/skills/maestro/SKILL.md +36 -3
  57. package/plugins/meta-architect/skills/maestro/agents/openai.yaml +2 -2
  58. package/plugins/meta-architect/skills/{meta-architect → maestro}/references/core-release-rules.md +0 -0
  59. package/plugins/meta-architect/skills/maestro/references/native-ingest-map.md +44 -0
  60. package/plugins/meta-architect/skills/sage/SKILL.md +3 -1
  61. package/plugins/meta-architect/skills/sage/agents/openai.yaml +0 -0
  62. package/plugins/meta-architect/skills/sage/references/source-selection.md +28 -0
  63. package/plugins/meta-architect/skills/tdd/SKILL.md +24 -0
  64. package/plugins/meta-architect/skills/tdd/agents/openai.yaml +4 -0
  65. package/plugins/meta-architect/skills/vet/SKILL.md +3 -1
  66. package/plugins/meta-architect/skills/vet/agents/openai.yaml +0 -0
  67. package/plugins/meta-architect/skills/vet/references/security-playbooks.md +23 -0
  68. package/plugins/meta-architect/skills/vibe/SKILL.md +0 -0
  69. package/plugins/meta-architect/skills/vibe/agents/openai.yaml +0 -0
  70. package/scripts/biome-staged.js +0 -0
  71. package/scripts/build-linux-packages.mjs +328 -0
  72. package/scripts/doctor.js +19 -0
  73. package/scripts/linux-package-lib.mjs +40 -0
  74. package/scripts/linux-package-smoke.mjs +103 -0
  75. package/scripts/plugin-sync.js +0 -0
  76. package/scripts/postinstall.js +0 -0
  77. package/scripts/release-metadata.js +0 -0
  78. package/scripts/release-sync.js +13 -6
  79. package/scripts/release-verify.js +0 -0
  80. package/scripts/setup-npmrc.js +0 -0
  81. package/skills/align/SKILL.md +24 -0
  82. package/skills/align/agents/openai.yaml +4 -0
  83. package/skills/align/references/shared-language.md +24 -0
  84. package/skills/arch/SKILL.md +0 -0
  85. package/skills/arch/agents/openai.yaml +0 -0
  86. package/skills/build/SKILL.md +0 -0
  87. package/skills/build/agents/openai.yaml +0 -0
  88. package/skills/cleanup/SKILL.md +23 -0
  89. package/skills/cleanup/agents/openai.yaml +4 -0
  90. package/skills/cleanup/references/style-and-deslop.md +18 -0
  91. package/skills/diagnose/SKILL.md +24 -0
  92. package/skills/diagnose/agents/openai.yaml +4 -0
  93. package/skills/flow/SKILL.md +0 -0
  94. package/skills/flow/agents/openai.yaml +0 -0
  95. package/skills/index.json +21 -6
  96. package/skills/maestro/SKILL.md +36 -3
  97. package/skills/maestro/agents/openai.yaml +2 -2
  98. package/skills/{meta-architect → maestro}/references/core-release-rules.md +0 -0
  99. package/skills/maestro/references/native-ingest-map.md +44 -0
  100. package/skills/sage/SKILL.md +3 -1
  101. package/skills/sage/agents/openai.yaml +0 -0
  102. package/skills/sage/references/source-selection.md +28 -0
  103. package/skills/tdd/SKILL.md +24 -0
  104. package/skills/tdd/agents/openai.yaml +4 -0
  105. package/skills/vet/SKILL.md +3 -1
  106. package/skills/vet/agents/openai.yaml +0 -0
  107. package/skills/vet/references/security-playbooks.md +23 -0
  108. package/skills/vibe/SKILL.md +0 -0
  109. package/skills/vibe/agents/openai.yaml +0 -0
  110. package/src/bootstrap.js +124 -24
  111. package/src/decision-log.js +12 -9
  112. package/src/launcher.js +0 -0
  113. package/src/mcp-config.js +130 -8
  114. package/src/mcp-live-client.js +1 -1
  115. package/src/paths.js +33 -1
  116. package/src/release-state.js +30 -1
  117. package/src/runtime/build-readiness.js +38 -0
  118. package/src/runtime/continuity-notes.js +79 -0
  119. package/src/runtime/guidance-stack.js +42 -0
  120. package/src/runtime/maestro-manager.js +586 -0
  121. package/src/runtime/orchestrator.js +158 -0
  122. package/src/runtime/runtime-state.js +382 -0
  123. package/src/runtime/signal-hooks.js +52 -0
  124. package/src/runtime/startup-path.js +14 -0
  125. package/src/runtime/workspaces.js +25 -0
  126. package/src/runtime-artifacts.js +190 -30
  127. package/src/skill-installer.js +53 -5
  128. package/src/skills.js +633 -49
  129. package/src/state-sync.js +51 -8
  130. package/plugins/meta-architect/skills/meta-architect/SKILL.md +0 -32
  131. package/plugins/meta-architect/skills/meta-architect/agents/openai.yaml +0 -4
  132. package/skills/meta-architect/SKILL.md +0 -32
  133. package/skills/meta-architect/agents/openai.yaml +0 -4
package/src/skills.js CHANGED
@@ -5,9 +5,25 @@ import { readJson, writeFileIfMissing, writeJson } from "./fs-utils.js";
5
5
  import { validateMcpServers } from "./mcp-config.js";
6
6
  import { McpSseClient } from "./mcp-live-client.js";
7
7
  import { getRepoRoot, getRuntimeReadPath, getRuntimeWritePath, packageRoot } from "./paths.js";
8
+ import { evaluateRuntimeBuildReadiness } from "./runtime/build-readiness.js";
9
+ import {
10
+ buildHelperFailureMatrix,
11
+ chooseMaestroManagerAction,
12
+ createManagerRun,
13
+ getActiveManagerRun,
14
+ loadManagerRunRegistry,
15
+ saveManagerRunRegistry,
16
+ } from "./runtime/maestro-manager.js";
17
+ import { submitTask } from "./runtime/orchestrator.js";
18
+ import {
19
+ assertLeaderAuthority,
20
+ createRuntimeSummary,
21
+ loadRuntimeSnapshot,
22
+ } from "./runtime/runtime-state.js";
8
23
  import {
9
24
  seedRuntimeArtifacts,
10
25
  writeArchitectureArtifacts,
26
+ writeBuildPlanArtifact,
11
27
  writeEvidenceSpec,
12
28
  writeExperienceSpec,
13
29
  writeLogicSpec,
@@ -18,9 +34,10 @@ import {
18
34
  import { syncStatusUpdates } from "./state-sync.js";
19
35
 
20
36
  const skillNames = ["$maestro", "$arch", "$sage", "$flow", "$vet", "$vibe", "$build"];
37
+ const maestroWorkflowSequence = ["$arch", "$sage", "$flow", "$vet", "$vibe", "$build"];
21
38
  const workflowTemplates = {
22
39
  "maestro.skill.md":
23
- "# `$maestro`\n\nChooses the best next workflow step and recommends the right lane or assignment.\n",
40
+ "# `$maestro`\n\nThe singular Meta-Architect umbrella workflow. Inspect runtime state, execute bounded helper or gated work when it is safe, persist the manager-run control plane, and return the exact next trigger.\n",
24
41
  "arch.skill.md":
25
42
  "# `$arch`\n\nProduces blueprint architecture, stack rationale, subsystem design, and tradeoffs.\n",
26
43
  "sage.skill.md":
@@ -30,6 +47,14 @@ const workflowTemplates = {
30
47
  "vibe.skill.md":
31
48
  "# `$vibe`\n\nReviews developer and user experience risks before build execution.\n",
32
49
  "build.skill.md": "# `$build`\n\nChecks gates and plans bounded build execution.\n",
50
+ "align.skill.md":
51
+ "# `$align`\n\nHelper skill for scope alignment, shared language, and docs clarity. Non-gating.\n",
52
+ "diagnose.skill.md":
53
+ "# `$diagnose`\n\nHelper skill for blocked-lane diagnosis and root-cause slicing. Non-gating.\n",
54
+ "tdd.skill.md":
55
+ "# `$tdd`\n\nHelper skill for regression-first or test-first preparation. Non-gating.\n",
56
+ "cleanup.skill.md":
57
+ "# `$cleanup`\n\nHelper skill for simplification, anti-slop cleanup, and final-pass polish. Non-gating.\n",
33
58
  "sync.skill.md":
34
59
  "# `$sync`\n\nReserved for refreshing mapped MCP sources and availability records.\n",
35
60
  };
@@ -38,7 +63,7 @@ export function listSkills() {
38
63
  return skillNames;
39
64
  }
40
65
 
41
- function chooseMaestroRecommendation(releaseState, idea) {
66
+ function chooseMaestroRecommendation(releaseState, idea, buildReadiness = null) {
42
67
  if (releaseState.idea_status !== "CLEAR") {
43
68
  return {
44
69
  nextStep: "Capture or refine the project brief before any design or validation lane starts.",
@@ -127,6 +152,21 @@ function chooseMaestroRecommendation(releaseState, idea) {
127
152
  }
128
153
 
129
154
  if (releaseState.build_status === "LOCKED") {
155
+ if (buildReadiness && buildReadiness.releaseBlockers.length === 0 && !buildReadiness.allowed) {
156
+ return {
157
+ nextStep: "Repair runtime artifacts before bounded build planning can unlock.",
158
+ why: "The release gates are green, but runtime artifacts or pending mailbox proposals are still blocking build readiness.",
159
+ primaryLane: "runtime repair",
160
+ supportLane: "$build",
161
+ assignments: [
162
+ "Repair the listed runtime blockers first.",
163
+ "Re-run $build only after runtime blockers are cleared.",
164
+ ],
165
+ avoid: ["Do not unlock bounded implementation planning while runtime blockers remain."],
166
+ nextTrigger: "`repair runtime artifacts`",
167
+ };
168
+ }
169
+
130
170
  return {
131
171
  nextStep: "Unlock bounded implementation planning.",
132
172
  why: "All upstream quality gates are green, so the workflow can now evaluate build readiness.",
@@ -188,7 +228,338 @@ async function readIdeaText() {
188
228
  return ideaDecision?.idea ?? null;
189
229
  }
190
230
 
231
+ async function readRuntimeSummary() {
232
+ const runtimeSnapshot = await loadRuntimeSnapshot();
233
+ return createRuntimeSummary(runtimeSnapshot);
234
+ }
235
+
236
+ function assertControlPlaneReady(runtimeSummary) {
237
+ const blockingInvalidArtifacts = runtimeSummary.invalidArtifacts.filter((artifact) =>
238
+ ["runtime.release", "runtime.decisions"].includes(artifact),
239
+ );
240
+ const blockingMissingArtifacts = runtimeSummary.missingArtifacts.filter(
241
+ (artifact) => artifact === "runtime.decisions" || artifact === "runtime.release",
242
+ );
243
+
244
+ const blockingArtifacts = [...blockingInvalidArtifacts, ...blockingMissingArtifacts];
245
+ if (blockingArtifacts.length > 0) {
246
+ throw new Error(`Invalid runtime artifacts: ${blockingArtifacts.join(", ")}`);
247
+ }
248
+ }
249
+
250
+ function getManagerDecisionStatus(managerRun) {
251
+ return managerRun.state.toUpperCase().replaceAll("-", "_");
252
+ }
253
+
254
+ function stripBackticks(value) {
255
+ return value.replaceAll("`", "");
256
+ }
257
+
258
+ export async function runBuildLane({ actor = null } = {}) {
259
+ const authority = await assertLeaderAuthority(actor);
260
+ const runtimeSnapshot = await loadRuntimeSnapshot();
261
+ const runtimeSummary = createRuntimeSummary(runtimeSnapshot);
262
+ const evaluation = evaluateRuntimeBuildReadiness(runtimeSnapshot.release, runtimeSummary);
263
+
264
+ if (evaluation.controlPlaneBlockers.length > 0) {
265
+ throw new Error(`Invalid runtime artifacts: ${evaluation.controlPlaneBlockers.join(", ")}`);
266
+ }
267
+
268
+ if (!evaluation.allowed) {
269
+ await writeBuildPlanArtifact({
270
+ allowed: false,
271
+ blockers: evaluation.blockers,
272
+ nextTriggers: evaluation.nextTriggers,
273
+ runtimeSummary,
274
+ });
275
+ await appendDecision({
276
+ actor: authority.leaderActor,
277
+ kind: "skill",
278
+ skill: "$build",
279
+ decision: "Build execution remains locked under the current runtime and release state.",
280
+ status: "BLOCKED",
281
+ evidence: [{ kind: "runtime-summary", value: runtimeSummary }],
282
+ blockers: evaluation.blockers,
283
+ next_allowed_triggers: evaluation.nextTriggers,
284
+ });
285
+ return {
286
+ status: "BLOCKED",
287
+ nextTrigger: evaluation.nextTriggers[0] ?? "$build",
288
+ blockers: evaluation.blockers,
289
+ };
290
+ }
291
+
292
+ const suggestedBranches = ["feature/implementation", "feature/verification"];
293
+ await writeBuildPlanArtifact({
294
+ allowed: true,
295
+ blockers: [],
296
+ nextTriggers: ["$build"],
297
+ suggestedBranches,
298
+ runtimeSummary,
299
+ });
300
+ await appendDecision({
301
+ actor: authority.leaderActor,
302
+ kind: "skill",
303
+ skill: "$build",
304
+ decision: "Build gate ready",
305
+ status: "READY",
306
+ evidence: [
307
+ { kind: "runtime-summary", value: runtimeSummary },
308
+ { kind: "branches", value: suggestedBranches },
309
+ ],
310
+ blockers: [],
311
+ next_allowed_triggers: ["$build"],
312
+ });
313
+ await syncStatusUpdates({ build_status: "READY" }, { actor: authority.leaderActor });
314
+ return {
315
+ status: "READY",
316
+ nextTrigger: "$build",
317
+ blockers: [],
318
+ suggestedBranches,
319
+ };
320
+ }
321
+
322
+ function getAutonomousGateRunners() {
323
+ return {
324
+ $arch: runArch,
325
+ $sage: runSage,
326
+ $flow: runFlow,
327
+ $vet: runVet,
328
+ $vibe: runVibe,
329
+ $build: runBuildLane,
330
+ };
331
+ }
332
+
333
+ function updateManagerRunTimestamps(managerRun, overrides = {}) {
334
+ const now = new Date().toISOString();
335
+ Object.assign(managerRun, overrides, { updatedAt: now });
336
+ if (["completed", "blocked", "failed", "cancelled"].includes(managerRun.state)) {
337
+ managerRun.completedAt ??= now;
338
+ }
339
+ }
340
+
341
+ function buildManagerDecisionEvidence(managerRun, recommendation) {
342
+ return [
343
+ {
344
+ runId: managerRun.id,
345
+ mode: managerRun.mode,
346
+ state: managerRun.state,
347
+ nextAction: managerRun.nextAction,
348
+ helperRuns: managerRun.helperRuns.map((helper) => ({
349
+ id: helper.id,
350
+ skill: helper.skill,
351
+ status: helper.status,
352
+ objective: helper.objective,
353
+ })),
354
+ dispatchPlan: {
355
+ helpers: managerRun.dispatchPlan.helpers.map((helper) => ({
356
+ skill: helper.skill,
357
+ objective: helper.objective,
358
+ })),
359
+ gated: managerRun.dispatchPlan.gated.map((gate) => ({
360
+ skill: gate.skill,
361
+ objective: gate.objective,
362
+ status: gate.status,
363
+ })),
364
+ team: managerRun.dispatchPlan.team
365
+ ? {
366
+ title: managerRun.dispatchPlan.team.title,
367
+ createdTaskIds: managerRun.dispatchPlan.team.createdTaskIds,
368
+ }
369
+ : null,
370
+ },
371
+ },
372
+ recommendation,
373
+ ];
374
+ }
375
+
376
+ function buildManagerDecisionBlockers(managerRun, runtimeSummary, buildReadiness) {
377
+ const blockers = [];
378
+ if (managerRun.state === "waiting-review" && managerRun.pendingReview.proposalPath) {
379
+ blockers.push(`Manager run is waiting for review at ${managerRun.pendingReview.proposalPath}.`);
380
+ }
381
+ if (managerRun.state === "blocked" && managerRun.retry.lastReason) {
382
+ blockers.push(managerRun.retry.lastReason);
383
+ }
384
+ if (
385
+ buildReadiness &&
386
+ !buildReadiness.allowed &&
387
+ buildReadiness.nextTriggers.includes("repair runtime artifacts")
388
+ ) {
389
+ blockers.push(...buildReadiness.runtimeBlockers);
390
+ }
391
+ if (runtimeSummary.pendingMailboxCount > 0) {
392
+ blockers.push("Pending mailbox proposals require leader review.");
393
+ }
394
+
395
+ return [...new Set(blockers)];
396
+ }
397
+
398
+ function executeManagerHelper(helper, { releaseState, runtimeSummary, recommendation }) {
399
+ if (helper.skill === "$align") {
400
+ return {
401
+ helperId: helper.id,
402
+ kind: "alignment",
403
+ workflowSequence: maestroWorkflowSequence,
404
+ currentBuildStatus: releaseState.build_status,
405
+ recommendedNextTrigger: recommendation.nextTrigger,
406
+ };
407
+ }
408
+
409
+ if (helper.skill === "$diagnose") {
410
+ return {
411
+ helperId: helper.id,
412
+ kind: "diagnostic",
413
+ pendingMailboxCount: runtimeSummary.pendingMailboxCount,
414
+ invalidArtifacts: runtimeSummary.invalidArtifacts,
415
+ missingArtifacts: runtimeSummary.missingArtifacts,
416
+ };
417
+ }
418
+
419
+ if (helper.skill === "$tdd") {
420
+ return {
421
+ helperId: helper.id,
422
+ kind: "test-first",
423
+ buildStatus: releaseState.build_status,
424
+ nextTrigger: recommendation.nextTrigger,
425
+ };
426
+ }
427
+
428
+ if (helper.skill === "$cleanup") {
429
+ return {
430
+ helperId: helper.id,
431
+ kind: "cleanup",
432
+ mergeStatus: releaseState.merge_status,
433
+ releaseStatus: releaseState.release_status,
434
+ };
435
+ }
436
+
437
+ return {
438
+ helperId: helper.id,
439
+ kind: "manager-helper",
440
+ objective: helper.objective,
441
+ };
442
+ }
443
+
444
+ async function executeManagerHelpers({
445
+ registry,
446
+ managerRun,
447
+ releaseState,
448
+ runtimeSummary,
449
+ recommendation,
450
+ helperFailureMatrix,
451
+ }) {
452
+ const startedAt = new Date().toISOString();
453
+ updateManagerRunTimestamps(managerRun, { state: "running" });
454
+ for (const helperRun of managerRun.helperRuns) {
455
+ helperRun.status = "running";
456
+ helperRun.startedAt = startedAt;
457
+ }
458
+ await saveManagerRunRegistry(registry);
459
+
460
+ const results = await Promise.allSettled(
461
+ managerRun.helperRuns.map(async (helperRun) => {
462
+ const evidence = executeManagerHelper(helperRun, {
463
+ releaseState,
464
+ runtimeSummary,
465
+ recommendation,
466
+ });
467
+ return { helperRun, evidence };
468
+ }),
469
+ );
470
+
471
+ const continuedHelpers = [];
472
+ let hadFailure = false;
473
+ for (const result of results) {
474
+ const helperRun =
475
+ result.status === "fulfilled"
476
+ ? result.value.helperRun
477
+ : managerRun.helperRuns[results.indexOf(result)];
478
+
479
+ if (result.status === "fulfilled") {
480
+ helperRun.status = "completed";
481
+ helperRun.evidence.push(result.value.evidence);
482
+ helperRun.completedAt = new Date().toISOString();
483
+ continuedHelpers.push(helperRun.skill);
484
+ continue;
485
+ }
486
+
487
+ hadFailure = true;
488
+ const policy = helperFailureMatrix.helper_failed_but_manager_can_fall_back_to_safe_summary;
489
+ helperRun.status = "failed";
490
+ helperRun.errorClass = "helper_failed_but_manager_can_fall_back_to_safe_summary";
491
+ helperRun.errorMessage = result.reason?.message ?? String(result.reason);
492
+ helperRun.completedAt = new Date().toISOString();
493
+ helperRun.evidence.push({
494
+ runId: managerRun.id,
495
+ helperId: helperRun.id,
496
+ skill: helperRun.skill,
497
+ objective: helperRun.objective,
498
+ degradedReason: helperRun.errorMessage,
499
+ safeNextTrigger: recommendation.nextTrigger,
500
+ siblingHelperPolicy: policy.siblingHelperPolicy,
501
+ continuedHelpers,
502
+ });
503
+ }
504
+
505
+ if (hadFailure) {
506
+ updateManagerRunTimestamps(managerRun, {
507
+ state: "completed",
508
+ retry: {
509
+ count: managerRun.retry.count + 1,
510
+ lastReason: "One or more helper runs degraded to recommendation-only behavior.",
511
+ },
512
+ });
513
+ await saveManagerRunRegistry(registry);
514
+ return false;
515
+ }
516
+
517
+ await saveManagerRunRegistry(registry);
518
+ return true;
519
+ }
520
+
521
+ async function executeManagerTeamDispatch(registry, managerRun) {
522
+ const teamPlan = managerRun.dispatchPlan.team;
523
+ if (!teamPlan) {
524
+ return;
525
+ }
526
+
527
+ const taskResult = await submitTask({
528
+ title: teamPlan.title,
529
+ owner: "leader",
530
+ metadata: {
531
+ classification: "durable-team-task",
532
+ managerOwner: "$maestro",
533
+ managerRunId: managerRun.id,
534
+ objective: teamPlan.objective,
535
+ verificationOwner: teamPlan.verificationOwner,
536
+ launchHints: teamPlan.launchHints,
537
+ staffing: teamPlan.staffing,
538
+ },
539
+ });
540
+
541
+ if (taskResult.proposed) {
542
+ updateManagerRunTimestamps(managerRun, {
543
+ state: "waiting-review",
544
+ pendingReview: {
545
+ proposalPath: taskResult.proposalPath,
546
+ mailboxOwner: "leader",
547
+ resumeTrigger: "Review the queued team task proposal, then rerun `$maestro`.",
548
+ },
549
+ });
550
+ await saveManagerRunRegistry(registry);
551
+ return;
552
+ }
553
+
554
+ teamPlan.createdTaskIds.push(taskResult.task.id);
555
+ updateManagerRunTimestamps(managerRun, { state: "running" });
556
+ await saveManagerRunRegistry(registry);
557
+ }
558
+
191
559
  export async function runIdea(idea) {
560
+ const runtimeSummary = await readRuntimeSummary();
561
+ assertControlPlaneReady(runtimeSummary);
562
+ await assertLeaderAuthority();
192
563
  const trimmed = idea.trim();
193
564
  if (!trimmed) {
194
565
  throw new Error("Idea text is required");
@@ -203,25 +574,28 @@ export async function runIdea(idea) {
203
574
  status: "CLEAR",
204
575
  evidence: [{ kind: "user-input", value: trimmed }],
205
576
  blockers: [],
206
- next_allowed_triggers: ["$arch"],
577
+ next_allowed_triggers: ["$maestro"],
207
578
  });
208
579
 
209
580
  await syncStatusUpdates({ idea_status: "CLEAR" });
210
581
  }
211
582
 
212
583
  export async function runArch() {
584
+ await assertLeaderAuthority();
585
+ const runtimeSummary = await readRuntimeSummary();
586
+ assertControlPlaneReady(runtimeSummary);
213
587
  const idea = await readIdeaText();
214
588
  if (!idea) {
215
589
  throw new Error("Cannot run $arch before ma idea captures a project brief");
216
590
  }
217
591
 
218
592
  const blueprint = {
219
- summary: `Blueprint derived from idea: ${idea}`,
220
- suggestedStack: ["Node.js", "MCP", "GitMCP", "Git worktree"],
221
- outcome: "Produce a gated architecture and implementation plan",
593
+ summary: `Blueprint derived from idea: ${idea}. Runtime shell currently exposes ${runtimeSummary.workerCount} workers, ${runtimeSummary.workspaceCount} workspaces, and ${runtimeSummary.guidanceSourceCount} guidance sources.`,
594
+ suggestedStack: ["Node.js", "MCP", "GitMCP", "Git worktree", "File-backed runtime state"],
595
+ outcome: "Produce a gated architecture and implementation plan backed by runtime state.",
222
596
  };
223
597
 
224
- await writeArchitectureArtifacts({ idea, blueprint });
598
+ await writeArchitectureArtifacts({ idea, blueprint, runtimeSummary });
225
599
 
226
600
  await appendDecision({
227
601
  kind: "skill",
@@ -237,7 +611,10 @@ export async function runArch() {
237
611
  }
238
612
 
239
613
  export async function runSage() {
614
+ await assertLeaderAuthority();
240
615
  const config = await validateMcpServers();
616
+ const runtimeSummary = await readRuntimeSummary();
617
+ assertControlPlaneReady(runtimeSummary);
241
618
  const sourceEntries = config.servers.map((server) => ({
242
619
  repo: server.repo,
243
620
  endpoint: server.endpoint,
@@ -246,7 +623,6 @@ export async function runSage() {
246
623
  const blockers = [];
247
624
  const idea = (await readIdeaText()) ?? "software architecture";
248
625
  const disableLiveProbe = process.env.MA_DISABLE_LIVE_MCP === "1";
249
- const probeCandidates = sourceEntries.slice(0, 1);
250
626
  let liveSuccessCount = 0;
251
627
 
252
628
  for (const source of sourceEntries) {
@@ -258,14 +634,6 @@ export async function runSage() {
258
634
  continue;
259
635
  }
260
636
 
261
- if (!probeCandidates.includes(source)) {
262
- source.liveProbe = {
263
- skipped: true,
264
- reason: "Not selected for the live probe set in this run",
265
- };
266
- continue;
267
- }
268
-
269
637
  const client = new McpSseClient(source.endpoint);
270
638
  try {
271
639
  const init = await client.connect();
@@ -313,13 +681,21 @@ export async function runSage() {
313
681
  existing.items = sourceEntries;
314
682
  await writeJson(getRuntimeWritePath("evidence", "sources.json"), existing);
315
683
 
316
- const verified = sourceEntries.length > 0 && (disableLiveProbe || liveSuccessCount > 0);
317
- await writeEvidenceSpec({ idea, sourceEntries, verified, blockers });
684
+ const verified =
685
+ sourceEntries.length > 0 && !disableLiveProbe && liveSuccessCount === sourceEntries.length;
686
+ if (sourceEntries.length > 0 && !verified && blockers.length === 0) {
687
+ blockers.push(
688
+ disableLiveProbe
689
+ ? "Live MCP verification was skipped, so evidence remains unverified."
690
+ : "No live MCP verification succeeded, so evidence remains unverified.",
691
+ );
692
+ }
693
+ await writeEvidenceSpec({ idea, sourceEntries, verified, blockers, runtimeSummary });
318
694
  await appendDecision({
319
695
  kind: "skill",
320
696
  skill: "$sage",
321
697
  decision: "Bound architectural choices to approved GitMCP sources using live MCP queries",
322
- status: verified ? "VERIFIED" : "UNVERIFIED",
698
+ status: verified ? "VERIFIED" : sourceEntries.length > 0 ? "PARTIAL" : "MISSING",
323
699
  evidence: sourceEntries,
324
700
  blockers: sourceEntries.length > 0 ? blockers : ["No approved GitMCP sources configured"],
325
701
  next_allowed_triggers: verified ? ["$flow"] : ["mcp/servers.json", "$sage"],
@@ -331,10 +707,37 @@ export async function runSage() {
331
707
  }
332
708
 
333
709
  export async function runFlow() {
710
+ await assertLeaderAuthority();
711
+ const runtimeSnapshot = await loadRuntimeSnapshot();
712
+ const runtimeSummary = createRuntimeSummary(runtimeSnapshot);
713
+ assertControlPlaneReady(runtimeSummary);
714
+ if (runtimeSnapshot.release.evidence_status !== "VERIFIED") {
715
+ throw new Error("Cannot run $flow before $sage reaches VERIFIED evidence_status");
716
+ }
717
+ const blockers = [];
718
+ if (runtimeSummary.missingArtifacts.length > 0) {
719
+ blockers.push(`Missing runtime artifacts: ${runtimeSummary.missingArtifacts.join(", ")}`);
720
+ }
721
+ if (runtimeSummary.invalidArtifacts.length > 0) {
722
+ blockers.push(`Invalid runtime artifacts: ${runtimeSummary.invalidArtifacts.join(", ")}`);
723
+ }
724
+ if (runtimeSummary.pendingMailboxCount > 0) {
725
+ blockers.push(
726
+ "Pending mailbox proposals require leader review before logic can be marked green.",
727
+ );
728
+ }
729
+ if (runtimeSummary.workerCount > 0 && runtimeSummary.workspaceCount === 0) {
730
+ blockers.push("Workers exist without registered workspaces.");
731
+ }
334
732
  const logicMap = {
733
+ actors: ["leader", "worker", "guidance_stack", "hook_dispatcher", "workspace_manager"],
335
734
  states: ["idea", "architecture", "evidence", "logic", "security", "experience", "build"],
336
- blockers: [],
735
+ runtimeSummary,
736
+ blockers,
737
+ nextTrigger: blockers.length === 0 ? "`$vet`" : "`$flow`",
337
738
  };
739
+ const status = blockers.length === 0 ? "GREEN" : "RED";
740
+ const nextAllowedTriggers = blockers.length === 0 ? ["$vet"] : ["$flow"];
338
741
 
339
742
  await writeLogicSpec(logicMap);
340
743
 
@@ -342,87 +745,253 @@ export async function runFlow() {
342
745
  kind: "skill",
343
746
  skill: "$flow",
344
747
  decision: "Validated logic and state transitions",
345
- status: "GREEN",
748
+ status,
346
749
  evidence: [logicMap],
347
- blockers: [],
348
- next_allowed_triggers: ["$vet"],
750
+ blockers,
751
+ next_allowed_triggers: nextAllowedTriggers,
349
752
  });
350
753
 
351
- await syncStatusUpdates({ logic_status: "GREEN" });
754
+ await syncStatusUpdates({ logic_status: status });
352
755
  }
353
756
 
354
757
  export async function runVet() {
758
+ await assertLeaderAuthority();
759
+ const runtimeSummary = await readRuntimeSummary();
760
+ assertControlPlaneReady(runtimeSummary);
355
761
  const auditLog = await readJson(getRuntimeWritePath("evidence", "audits.json"));
356
762
  const cveLog = await readJson(getRuntimeWritePath("evidence", "cves.json"));
763
+ const reviewApproved =
764
+ auditLog.items.some((item) => item.source === "review" || item.approved === true) ||
765
+ cveLog.items.some((item) => item.source === "review" || item.approved === true);
357
766
  const finding = {
358
767
  severity: "INFO",
359
- summary: "Baseline review completed for the approved kernel",
360
- unresolved: false,
768
+ source: "placeholder",
769
+ summary: `Placeholder security review recorded; explicit security approval is still required after reviewing ${runtimeSummary.compatibilityHookCount} compatibility hooks and ${runtimeSummary.runtimeHookCount} runtime events.`,
770
+ unresolved: true,
361
771
  };
362
772
  auditLog.items.push(finding);
363
773
  await writeJson(getRuntimeWritePath("evidence", "audits.json"), auditLog);
364
774
  cveLog.items.push({
365
775
  id: "baseline-review",
776
+ source: "placeholder",
366
777
  severity: "INFO",
367
- unresolved: false,
778
+ unresolved: true,
368
779
  });
369
780
  await writeJson(getRuntimeWritePath("evidence", "cves.json"), cveLog);
370
781
  await writeSecuritySpec({
371
782
  finding,
372
783
  auditCount: auditLog.items.length,
373
784
  cveCount: cveLog.items.length,
785
+ runtimeSummary,
786
+ nextTrigger: reviewApproved ? "`$vibe`" : "`$vet`",
374
787
  });
788
+ const status = reviewApproved ? "GREEN" : "PENDING";
789
+ const blockers = reviewApproved
790
+ ? []
791
+ : ["Security review evidence has not been explicitly approved yet."];
792
+ const nextAllowedTriggers = reviewApproved ? ["$vibe"] : ["$vet"];
375
793
 
376
794
  await appendDecision({
377
795
  kind: "skill",
378
796
  skill: "$vet",
379
797
  decision: "Reviewed security posture for the current implementation",
380
- status: "GREEN",
798
+ status,
381
799
  evidence: [finding],
382
- blockers: [],
383
- next_allowed_triggers: ["$vibe"],
800
+ blockers,
801
+ next_allowed_triggers: nextAllowedTriggers,
384
802
  });
385
803
 
386
- await syncStatusUpdates({ security_status: "GREEN" });
804
+ await syncStatusUpdates({ security_status: status });
387
805
  }
388
806
 
389
807
  export async function runVibe() {
808
+ await assertLeaderAuthority();
809
+ const runtimeSummary = await readRuntimeSummary();
810
+ assertControlPlaneReady(runtimeSummary);
390
811
  const outcomes = await readJson(getRuntimeWritePath("evidence", "outcomes.json"));
812
+ const reviewApproved = outcomes.items.some(
813
+ (item) => item.source === "review" || item.approved === true,
814
+ );
391
815
  const note = {
392
816
  area: "developer-experience",
393
- summary: "The in-session skill flow remains the primary Meta-Architect surface",
817
+ source: "placeholder",
818
+ summary: `Placeholder DX/UX review recorded; explicit workflow approval is still required while the runtime tracks ${runtimeSummary.taskCount} tasks and ${runtimeSummary.workspaceCount} workspaces.`,
394
819
  };
395
820
  outcomes.items.push(note);
396
821
  await writeJson(getRuntimeWritePath("evidence", "outcomes.json"), outcomes);
397
- await writeExperienceSpec({ note, outcomeCount: outcomes.items.length });
822
+ const status = reviewApproved ? "GREEN" : "PENDING";
823
+ const blockers = reviewApproved
824
+ ? []
825
+ : ["DX/UX review evidence has not been explicitly approved yet."];
826
+ const nextAllowedTriggers = reviewApproved ? ["$build"] : ["$vibe"];
827
+ await writeExperienceSpec({
828
+ note,
829
+ outcomeCount: outcomes.items.length,
830
+ runtimeSummary,
831
+ nextTrigger: reviewApproved ? "`$build`" : "`$vibe`",
832
+ });
398
833
 
399
834
  await appendDecision({
400
835
  kind: "skill",
401
836
  skill: "$vibe",
402
837
  decision: "Recorded DX/UX review notes",
403
- status: "GREEN",
838
+ status,
404
839
  evidence: [note],
405
- blockers: [],
406
- next_allowed_triggers: ["$build"],
840
+ blockers,
841
+ next_allowed_triggers: nextAllowedTriggers,
407
842
  });
408
843
 
409
- await syncStatusUpdates({ experience_status: "GREEN" });
844
+ await syncStatusUpdates({ experience_status: status });
410
845
  }
411
846
 
412
847
  export async function runMaestro() {
413
- const releaseState = await readJson(getRuntimeReadPath("release.json"));
414
- const idea = await readIdeaText();
415
- const recommendation = chooseMaestroRecommendation(releaseState, idea);
848
+ await assertLeaderAuthority();
849
+ let runtimeSnapshot = await loadRuntimeSnapshot();
850
+ let releaseState = runtimeSnapshot.release;
851
+ let runtimeSummary = createRuntimeSummary(runtimeSnapshot);
852
+ assertControlPlaneReady(runtimeSummary);
853
+ let idea = await readIdeaText();
854
+ let buildReadiness = evaluateRuntimeBuildReadiness(releaseState, runtimeSummary);
855
+ let recommendation = chooseMaestroRecommendation(releaseState, idea, buildReadiness);
856
+ const helperFailureMatrix = buildHelperFailureMatrix();
857
+ const registry = await loadManagerRunRegistry();
858
+ const activeRun = getActiveManagerRun(registry);
859
+ const managerAction = chooseMaestroManagerAction({
860
+ releaseState,
861
+ runtimeSummary,
862
+ buildReadiness,
863
+ recommendation,
864
+ activeRun,
865
+ });
866
+
867
+ if (activeRun?.state === "waiting-review" && managerAction.nextAction === "recommend") {
868
+ await writeMaestroPlan({
869
+ releaseState,
870
+ recommendation,
871
+ runtimeSummary,
872
+ workflowSequence: maestroWorkflowSequence,
873
+ managerRun: activeRun,
874
+ });
875
+ await appendDecision({
876
+ kind: "skill",
877
+ skill: "$maestro",
878
+ decision: "Held the manager in waiting-review until the pending proposal is resolved",
879
+ status: "WAITING_REVIEW",
880
+ evidence: buildManagerDecisionEvidence(activeRun, recommendation),
881
+ blockers: buildManagerDecisionBlockers(activeRun, runtimeSummary, buildReadiness),
882
+ next_allowed_triggers: [stripBackticks(recommendation.nextTrigger)],
883
+ });
884
+ return;
885
+ }
886
+
887
+ const managerRun = createManagerRun({
888
+ parentRunId: activeRun?.id ?? null,
889
+ triggeredBy: "$maestro",
890
+ mode: managerAction.mode,
891
+ nextAction: managerAction.nextAction,
892
+ dispatchPlan: managerAction.dispatchPlan,
893
+ pendingReview: managerAction.pendingReview ?? null,
894
+ });
895
+ registry.runs.push(managerRun);
896
+ updateManagerRunTimestamps(managerRun);
897
+ await saveManagerRunRegistry(registry);
898
+
899
+ try {
900
+ updateManagerRunTimestamps(managerRun, { state: "dispatching" });
901
+ await saveManagerRunRegistry(registry);
902
+
903
+ if (managerRun.helperRuns.length > 0) {
904
+ const helpersCompleted = await executeManagerHelpers({
905
+ registry,
906
+ managerRun,
907
+ releaseState,
908
+ runtimeSummary,
909
+ recommendation,
910
+ helperFailureMatrix,
911
+ });
912
+ if (!helpersCompleted) {
913
+ runtimeSnapshot = await loadRuntimeSnapshot();
914
+ releaseState = runtimeSnapshot.release;
915
+ runtimeSummary = createRuntimeSummary(runtimeSnapshot);
916
+ buildReadiness = evaluateRuntimeBuildReadiness(releaseState, runtimeSummary);
917
+ recommendation = chooseMaestroRecommendation(releaseState, idea, buildReadiness);
918
+ }
919
+ }
920
+
921
+ if (managerRun.state !== "completed" && managerRun.nextAction === "dispatch-gated") {
922
+ const gateRunners = getAutonomousGateRunners();
923
+ for (const gate of managerRun.dispatchPlan.gated) {
924
+ const runner = gateRunners[gate.skill];
925
+ if (!runner) {
926
+ gate.status = "recommended";
927
+ continue;
928
+ }
929
+
930
+ gate.status = "running";
931
+ updateManagerRunTimestamps(managerRun, { state: "running" });
932
+ await saveManagerRunRegistry(registry);
933
+ await runner();
934
+ gate.status = "completed";
935
+ await saveManagerRunRegistry(registry);
936
+ }
937
+ }
938
+
939
+ if (managerRun.state !== "completed" && managerRun.nextAction === "dispatch-team") {
940
+ await executeManagerTeamDispatch(registry, managerRun);
941
+ }
942
+ } catch (error) {
943
+ updateManagerRunTimestamps(managerRun, {
944
+ state: "failed",
945
+ retry: {
946
+ count: managerRun.retry.count + 1,
947
+ lastReason: error.message,
948
+ },
949
+ });
950
+ await saveManagerRunRegistry(registry);
951
+ throw error;
952
+ }
416
953
 
417
- await writeMaestroPlan({ releaseState, recommendation });
954
+ runtimeSnapshot = await loadRuntimeSnapshot();
955
+ releaseState = runtimeSnapshot.release;
956
+ runtimeSummary = createRuntimeSummary(runtimeSnapshot);
957
+ assertControlPlaneReady(runtimeSummary);
958
+ idea = await readIdeaText();
959
+ buildReadiness = evaluateRuntimeBuildReadiness(releaseState, runtimeSummary);
960
+ recommendation = chooseMaestroRecommendation(releaseState, idea, buildReadiness);
961
+
962
+ if (managerRun.state === "dispatching" || managerRun.state === "running") {
963
+ updateManagerRunTimestamps(managerRun, { state: "completed" });
964
+ await saveManagerRunRegistry(registry);
965
+ }
966
+
967
+ if (
968
+ buildReadiness.nextTriggers.includes("$build") ||
969
+ buildReadiness.nextTriggers.includes("repair runtime artifacts")
970
+ ) {
971
+ await writeBuildPlanArtifact({
972
+ allowed: buildReadiness.allowed,
973
+ blockers: buildReadiness.blockers,
974
+ nextTriggers: buildReadiness.nextTriggers,
975
+ runtimeSummary,
976
+ });
977
+ }
978
+
979
+ await writeMaestroPlan({
980
+ releaseState,
981
+ recommendation,
982
+ runtimeSummary,
983
+ workflowSequence: maestroWorkflowSequence,
984
+ managerRun,
985
+ });
418
986
  await appendDecision({
419
987
  kind: "skill",
420
988
  skill: "$maestro",
421
- decision: "Recommended the next workflow step and assignment lane",
422
- status: "ADVISORY",
423
- evidence: [recommendation],
424
- blockers: [],
425
- next_allowed_triggers: [recommendation.nextTrigger.replaceAll("`", "")],
989
+ decision:
990
+ "Executed the autonomous Meta-Architect manager run and persisted the control-plane record",
991
+ status: getManagerDecisionStatus(managerRun),
992
+ evidence: buildManagerDecisionEvidence(managerRun, recommendation),
993
+ blockers: buildManagerDecisionBlockers(managerRun, runtimeSummary, buildReadiness),
994
+ next_allowed_triggers: [stripBackticks(recommendation.nextTrigger)],
426
995
  });
427
996
  }
428
997
 
@@ -433,6 +1002,12 @@ export async function runInit() {
433
1002
  ".codex/prompts",
434
1003
  ".ma/skills",
435
1004
  ".ma/evidence",
1005
+ ".ma/guidance",
1006
+ ".ma/memory",
1007
+ ".ma/hooks",
1008
+ ".ma/tasks",
1009
+ ".ma/workspaces",
1010
+ ".ma/state",
436
1011
  ".ma/context",
437
1012
  ".ma/specs",
438
1013
  ".ma/plans",
@@ -508,8 +1083,8 @@ export async function runInit() {
508
1083
  path.join(getRepoRoot(), "docs", "release-spec.md"),
509
1084
  ],
510
1085
  [
511
- path.join(packageRoot, "docs", "qa", "release-readiness-0.1.10.md"),
512
- path.join(getRepoRoot(), "docs", "qa", "release-readiness-0.1.10.md"),
1086
+ path.join(packageRoot, "docs", "qa", "release-readiness-0.1.12.md"),
1087
+ path.join(getRepoRoot(), "docs", "qa", "release-readiness-0.1.12.md"),
513
1088
  ],
514
1089
  ];
515
1090
 
@@ -531,7 +1106,12 @@ export async function runInit() {
531
1106
  ]);
532
1107
  }
533
1108
 
534
- for (const file of ["servers.json", "collections.json", "fallback.json"]) {
1109
+ for (const file of [
1110
+ "servers.json",
1111
+ "collections.json",
1112
+ "fallback.json",
1113
+ "local-capabilities.json",
1114
+ ]) {
535
1115
  templateCopies.push([
536
1116
  path.join(packageRoot, "mcp", file),
537
1117
  path.join(getRepoRoot(), "mcp", file),
@@ -599,6 +1179,10 @@ export async function runInit() {
599
1179
  path.join(getRepoRoot(), "mcp", "servers.json"),
600
1180
  `${JSON.stringify({ schemaVersion: "0.1.0", servers: [] }, null, 2)}\n`,
601
1181
  );
1182
+ await writeFileIfMissing(
1183
+ path.join(getRepoRoot(), "mcp", "local-capabilities.json"),
1184
+ `${JSON.stringify({ schemaVersion: "0.1.0", capabilities: [] }, null, 2)}\n`,
1185
+ );
602
1186
  await writeFileIfMissing(
603
1187
  path.join(getRepoRoot(), "mcp", "collections.json"),
604
1188
  `${JSON.stringify({ schemaVersion: "0.1.0", collections: {} }, null, 2)}\n`,