@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/launcher.js CHANGED
File without changes
package/src/mcp-config.js CHANGED
@@ -1,7 +1,26 @@
1
1
  import fs from "node:fs/promises";
2
- import { getMcpServersPath } from "./paths.js";
2
+ import path from "node:path";
3
+ import { pathToFileURL } from "node:url";
4
+ import { getBundledMcpPath, getMcpLocalCapabilitiesPath, getMcpServersPath } from "./paths.js";
3
5
 
4
6
  const gitMcpRepoPattern = /^https:\/\/gitmcp\.io\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
7
+ const localCapabilityNames = ["_state", "memory", "trace", "team_run", "code_intel", "playbooks"];
8
+ const localCapabilityNameSet = new Set(localCapabilityNames);
9
+
10
+ function validateObjectWithArray(parsed, arrayField, label) {
11
+ if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed[arrayField])) {
12
+ throw new Error(`${label} must be an object with a ${arrayField} array`);
13
+ }
14
+
15
+ return parsed;
16
+ }
17
+
18
+ function normalizeGitMcpDescriptor(server) {
19
+ return {
20
+ ...server,
21
+ kind: server.kind ?? "gitmcp-evidence",
22
+ };
23
+ }
5
24
 
6
25
  export function isValidGitMcpEndpoint(url) {
7
26
  return gitMcpRepoPattern.test(url);
@@ -9,18 +28,25 @@ export function isValidGitMcpEndpoint(url) {
9
28
 
10
29
  export async function loadMcpServers() {
11
30
  const raw = await fs.readFile(getMcpServersPath(), "utf8");
12
- const parsed = JSON.parse(raw);
13
-
14
- if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.servers)) {
15
- throw new Error("mcp/servers.json must be an object with a servers array");
16
- }
17
-
18
- return parsed;
31
+ const parsed = validateObjectWithArray(JSON.parse(raw), "servers", "mcp/servers.json");
32
+ return {
33
+ ...parsed,
34
+ servers: parsed.servers.map(normalizeGitMcpDescriptor),
35
+ };
19
36
  }
20
37
 
21
38
  export async function validateMcpServers() {
22
39
  const parsed = await loadMcpServers();
23
40
  for (const server of parsed.servers) {
41
+ if (server.kind !== "gitmcp-evidence") {
42
+ throw new Error(`Invalid GitMCP descriptor kind: ${server.kind ?? "(missing)"}`);
43
+ }
44
+ if (typeof server.category !== "string" || server.category.trim() === "") {
45
+ throw new Error("GitMCP descriptors require a category");
46
+ }
47
+ if (typeof server.repo !== "string" || server.repo.trim() === "") {
48
+ throw new Error("GitMCP descriptors require a repo");
49
+ }
24
50
  if (!isValidGitMcpEndpoint(server.endpoint)) {
25
51
  throw new Error(`Invalid GitMCP endpoint: ${server.endpoint}`);
26
52
  }
@@ -28,3 +54,99 @@ export async function validateMcpServers() {
28
54
 
29
55
  return parsed;
30
56
  }
57
+
58
+ export async function loadLocalCapabilities() {
59
+ const raw = await fs.readFile(getMcpLocalCapabilitiesPath(), "utf8");
60
+ return validateObjectWithArray(JSON.parse(raw), "capabilities", "mcp/local-capabilities.json");
61
+ }
62
+
63
+ export function getSupportedLocalCapabilities() {
64
+ return [...localCapabilityNames];
65
+ }
66
+
67
+ export async function validateLocalCapabilities() {
68
+ const parsed = await loadLocalCapabilities();
69
+ const seen = new Set();
70
+
71
+ for (const descriptor of parsed.capabilities) {
72
+ if (descriptor.kind !== "local-capability") {
73
+ throw new Error(`Invalid local capability kind: ${descriptor.kind ?? "(missing)"}`);
74
+ }
75
+ if (!localCapabilityNameSet.has(descriptor.capability)) {
76
+ throw new Error(`Unsupported local capability: ${descriptor.capability}`);
77
+ }
78
+ if (seen.has(descriptor.capability)) {
79
+ throw new Error(`Duplicate local capability: ${descriptor.capability}`);
80
+ }
81
+ if (descriptor.transport !== "inproc") {
82
+ throw new Error(
83
+ `Local capability ${descriptor.capability} must use inproc transport, received ${descriptor.transport}`,
84
+ );
85
+ }
86
+ if (typeof descriptor.module !== "string" || descriptor.module.trim() === "") {
87
+ throw new Error(`Local capability ${descriptor.capability} requires a module`);
88
+ }
89
+ if (typeof descriptor.readinessCheck !== "string" || descriptor.readinessCheck.trim() === "") {
90
+ throw new Error(`Local capability ${descriptor.capability} requires a readinessCheck`);
91
+ }
92
+ if (descriptor.seededByBootstrap !== true) {
93
+ throw new Error(
94
+ `Local capability ${descriptor.capability} must declare seededByBootstrap: true`,
95
+ );
96
+ }
97
+ seen.add(descriptor.capability);
98
+ }
99
+
100
+ for (const capability of localCapabilityNames) {
101
+ if (!seen.has(capability)) {
102
+ throw new Error(`Missing local capability descriptor: ${capability}`);
103
+ }
104
+ }
105
+
106
+ return parsed;
107
+ }
108
+
109
+ export function resolveLocalCapabilityModulePath(descriptor) {
110
+ if (path.isAbsolute(descriptor.module)) {
111
+ throw new Error(`Local capability ${descriptor.capability} cannot use an absolute module path`);
112
+ }
113
+
114
+ const bundledLocalRoot = path.resolve(getBundledMcpPath("local"));
115
+ const resolvedModulePath = path.resolve(getBundledMcpPath(descriptor.module));
116
+ if (!resolvedModulePath.startsWith(`${bundledLocalRoot}${path.sep}`)) {
117
+ throw new Error(
118
+ `Local capability ${descriptor.capability} must resolve inside bundled mcp/local`,
119
+ );
120
+ }
121
+
122
+ return resolvedModulePath;
123
+ }
124
+
125
+ export async function loadLocalCapabilityModule(descriptor) {
126
+ const modulePath = resolveLocalCapabilityModulePath(descriptor);
127
+ return import(pathToFileURL(modulePath).href);
128
+ }
129
+
130
+ export async function runLocalCapabilityReadinessChecks() {
131
+ const parsed = await validateLocalCapabilities();
132
+ const results = [];
133
+
134
+ for (const descriptor of parsed.capabilities) {
135
+ const moduleExports = await loadLocalCapabilityModule(descriptor);
136
+ const readinessCheck = moduleExports[descriptor.readinessCheck];
137
+ if (typeof readinessCheck !== "function") {
138
+ throw new Error(
139
+ `Local capability ${descriptor.capability} is missing readiness export ${descriptor.readinessCheck}`,
140
+ );
141
+ }
142
+
143
+ const outcome = await readinessCheck();
144
+ results.push({
145
+ capability: descriptor.capability,
146
+ ready: outcome?.ready !== false,
147
+ detail: outcome?.detail ?? "",
148
+ });
149
+ }
150
+
151
+ return results;
152
+ }
@@ -38,7 +38,7 @@ export class McpSseClient {
38
38
  capabilities: {},
39
39
  clientInfo: {
40
40
  name: "meta-architect",
41
- version: "0.1.10",
41
+ version: "0.1.12-dev",
42
42
  },
43
43
  });
44
44
 
package/src/paths.js CHANGED
@@ -13,6 +13,14 @@ export function getRuntimeRoot() {
13
13
  return path.join(getRepoRoot(), ".ma");
14
14
  }
15
15
 
16
+ export function getRuntimeSubsystemPath(subsystem, ...parts) {
17
+ return path.join(getRuntimeRoot(), subsystem, ...parts);
18
+ }
19
+
20
+ export function getRuntimeStatePath(...parts) {
21
+ return getRuntimeSubsystemPath("state", ...parts);
22
+ }
23
+
16
24
  export function getRuntimeWritePath(...parts) {
17
25
  return path.join(getRuntimeRoot(), ...parts);
18
26
  }
@@ -21,6 +29,30 @@ export function getRuntimeReadPath(...parts) {
21
29
  return path.join(getRuntimeRoot(), ...parts);
22
30
  }
23
31
 
32
+ export function getMcpRootPath() {
33
+ return path.join(getRepoRoot(), "mcp");
34
+ }
35
+
36
+ export function getBundledMcpPath(...parts) {
37
+ return path.join(packageRoot, "mcp", ...parts);
38
+ }
39
+
24
40
  export function getMcpServersPath() {
25
- return path.join(getRepoRoot(), "mcp", "servers.json");
41
+ return path.join(getMcpRootPath(), "servers.json");
42
+ }
43
+
44
+ export function getMcpLocalCapabilitiesPath() {
45
+ return path.join(getMcpRootPath(), "local-capabilities.json");
46
+ }
47
+
48
+ export function getBundledNativePlaybooksPath() {
49
+ return getBundledMcpPath("native-playbooks.json");
50
+ }
51
+
52
+ export function getBundledDocsPath(...parts) {
53
+ return path.join(packageRoot, "docs", ...parts);
54
+ }
55
+
56
+ export function getBundledSkillsPath(...parts) {
57
+ return path.join(packageRoot, "skills", ...parts);
26
58
  }
@@ -2,7 +2,7 @@ import fs from "node:fs/promises";
2
2
  import { writeJson } from "./fs-utils.js";
3
3
  import { getRuntimeReadPath, getRuntimeWritePath } from "./paths.js";
4
4
 
5
- const allowedStatuses = {
5
+ export const allowedStatuses = {
6
6
  idea_status: ["DRAFT", "CLEAR", "BLOCKED"],
7
7
  architecture_status: ["DRAFT", "REVIEWED", "APPROVED"],
8
8
  evidence_status: ["MISSING", "PARTIAL", "VERIFIED"],
@@ -27,6 +27,23 @@ function validateWaiver(state) {
27
27
  }
28
28
  }
29
29
 
30
+ export function createDefaultReleaseState() {
31
+ return {
32
+ schemaVersion: "0.1.0",
33
+ idea_status: "DRAFT",
34
+ architecture_status: "DRAFT",
35
+ evidence_status: "MISSING",
36
+ logic_status: "PENDING",
37
+ security_status: "PENDING",
38
+ experience_status: "PENDING",
39
+ build_status: "LOCKED",
40
+ merge_status: "LOCKED",
41
+ release_status: "LOCKED",
42
+ waiver: null,
43
+ updatedAt: null,
44
+ };
45
+ }
46
+
30
47
  export function validateReleaseState(state) {
31
48
  if (!state || typeof state !== "object" || Array.isArray(state)) {
32
49
  throw new Error("Release state must be an object");
@@ -48,6 +65,18 @@ export async function loadReleaseState() {
48
65
  return validateReleaseState(parsed);
49
66
  }
50
67
 
68
+ export async function loadReleaseStateOrDefault() {
69
+ try {
70
+ return await loadReleaseState();
71
+ } catch (error) {
72
+ if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
73
+ return createDefaultReleaseState();
74
+ }
75
+
76
+ throw error;
77
+ }
78
+ }
79
+
51
80
  export async function saveReleaseState(state) {
52
81
  validateReleaseState(state);
53
82
  const next = {
@@ -0,0 +1,38 @@
1
+ import {
2
+ evaluateBuildGate,
3
+ formatBuildBlockers,
4
+ formatNextAllowedTriggers,
5
+ } from "../build-gate.js";
6
+
7
+ export function evaluateRuntimeBuildReadiness(releaseState, runtimeSummary) {
8
+ const releaseEvaluation = evaluateBuildGate(releaseState);
9
+ const controlPlaneBlockers = [
10
+ ...runtimeSummary.invalidArtifacts.filter((artifact) =>
11
+ ["runtime.release", "runtime.decisions"].includes(artifact),
12
+ ),
13
+ ...runtimeSummary.missingArtifacts.filter(
14
+ (artifact) => artifact === "runtime.release" || artifact === "runtime.decisions",
15
+ ),
16
+ ];
17
+ const runtimeBlockers = [
18
+ ...runtimeSummary.invalidArtifacts.map((artifact) => `runtime artifact ${artifact} is invalid`),
19
+ ...runtimeSummary.missingArtifacts.map((artifact) => `runtime artifact ${artifact} is missing`),
20
+ ...(runtimeSummary.pendingMailboxCount > 0
21
+ ? ["pending mailbox proposals require leader review"]
22
+ : []),
23
+ ];
24
+ const releaseBlockers = formatBuildBlockers(releaseEvaluation);
25
+ const nextTriggers =
26
+ releaseEvaluation.allowed && runtimeBlockers.length > 0
27
+ ? ["repair runtime artifacts"]
28
+ : formatNextAllowedTriggers(releaseEvaluation);
29
+
30
+ return {
31
+ allowed: releaseEvaluation.allowed && runtimeBlockers.length === 0,
32
+ controlPlaneBlockers,
33
+ runtimeBlockers,
34
+ releaseBlockers,
35
+ blockers: [...releaseBlockers, ...runtimeBlockers],
36
+ nextTriggers,
37
+ };
38
+ }
@@ -0,0 +1,79 @@
1
+ import fs from "node:fs/promises";
2
+ import { ensureDir, readJson, writeFileIfMissing, writeJson } from "../fs-utils.js";
3
+ import { getRuntimeSubsystemPath } from "../paths.js";
4
+ import { guardLeaderMutation } from "./runtime-state.js";
5
+
6
+ export function getContinuityRoot() {
7
+ return getRuntimeSubsystemPath("memory");
8
+ }
9
+
10
+ export function getContinuityNotesPath() {
11
+ return getRuntimeSubsystemPath("memory", "notes.md");
12
+ }
13
+
14
+ export function getContinuityIndexPath() {
15
+ return getRuntimeSubsystemPath("memory", "index.json");
16
+ }
17
+
18
+ export async function seedContinuityArtifacts() {
19
+ await ensureDir(getContinuityRoot());
20
+ await writeFileIfMissing(
21
+ getContinuityNotesPath(),
22
+ "# Continuity Notes\n\nNo continuity notes captured yet.\n",
23
+ );
24
+ await writeFileIfMissing(
25
+ getContinuityIndexPath(),
26
+ `${JSON.stringify(
27
+ {
28
+ schemaVersion: "0.1.0",
29
+ sessionCount: 0,
30
+ lastUpdatedAt: null,
31
+ },
32
+ null,
33
+ 2,
34
+ )}\n`,
35
+ );
36
+ }
37
+
38
+ export async function loadContinuityNotes() {
39
+ return fs.readFile(getContinuityNotesPath(), "utf8");
40
+ }
41
+
42
+ export async function loadContinuityIndex() {
43
+ return readJson(getContinuityIndexPath());
44
+ }
45
+
46
+ export async function storeContinuityNote(content, options = {}) {
47
+ const guard = await guardLeaderMutation({
48
+ actor: options.actor,
49
+ kind: "memory-note-write",
50
+ payload: { content },
51
+ });
52
+ if (!guard.allowed) {
53
+ return { proposed: true, proposalPath: guard.proposalPath };
54
+ }
55
+
56
+ const note = content.trim();
57
+ if (!note) {
58
+ throw new Error("memory.store_note requires non-empty content");
59
+ }
60
+
61
+ const [existingNotes, existingIndex] = await Promise.all([
62
+ loadContinuityNotes(),
63
+ loadContinuityIndex(),
64
+ ]);
65
+ const timestamp = new Date().toISOString();
66
+ const nextNotes = `${existingNotes.trimEnd()}\n\n## ${timestamp}\n\n${note}\n`;
67
+ const nextIndex = {
68
+ ...existingIndex,
69
+ sessionCount: existingIndex.sessionCount + 1,
70
+ lastUpdatedAt: timestamp,
71
+ };
72
+
73
+ await Promise.all([
74
+ fs.writeFile(getContinuityNotesPath(), nextNotes),
75
+ writeJson(getContinuityIndexPath(), nextIndex),
76
+ ]);
77
+
78
+ return { proposed: false, proposalPath: null, index: nextIndex };
79
+ }
@@ -0,0 +1,42 @@
1
+ import { ensureDir, writeFileIfMissing } from "../fs-utils.js";
2
+ import { getRuntimeSubsystemPath } from "../paths.js";
3
+
4
+ export function getGuidanceRoot() {
5
+ return getRuntimeSubsystemPath("guidance");
6
+ }
7
+
8
+ export function getMergedGuidancePath() {
9
+ return getRuntimeSubsystemPath("guidance", "merged.json");
10
+ }
11
+
12
+ export function getGuidanceIncludeGraphPath() {
13
+ return getRuntimeSubsystemPath("guidance", "include-graph.json");
14
+ }
15
+
16
+ export async function seedGuidanceStackArtifacts() {
17
+ await ensureDir(getGuidanceRoot());
18
+ await writeFileIfMissing(
19
+ getMergedGuidancePath(),
20
+ `${JSON.stringify(
21
+ {
22
+ schemaVersion: "0.1.0",
23
+ sources: [],
24
+ content: "",
25
+ },
26
+ null,
27
+ 2,
28
+ )}\n`,
29
+ );
30
+ await writeFileIfMissing(
31
+ getGuidanceIncludeGraphPath(),
32
+ `${JSON.stringify(
33
+ {
34
+ schemaVersion: "0.1.0",
35
+ roots: [],
36
+ edges: [],
37
+ },
38
+ null,
39
+ 2,
40
+ )}\n`,
41
+ );
42
+ }