@jstn-sdk/ma 0.1.4 → 0.1.5

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 (112) hide show
  1. package/.codex/config.toml +2 -0
  2. package/.codex/hooks.json +1 -1
  3. package/.codex/prompts/enforcement.md +3 -3
  4. package/.codex/prompts/onboarding.md +14 -29
  5. package/README.md +129 -472
  6. package/bin/ma.js +103 -54
  7. package/docs/README.md +1 -2
  8. package/docs/getting-started.md +37 -402
  9. package/docs/mcp-setup.md +134 -3
  10. package/docs/onboarding.md +11 -41
  11. package/docs/qa/release-readiness-0.1.5.md +77 -0
  12. package/docs/release-spec.md +103 -81
  13. package/docs/skills-publishing.md +54 -187
  14. package/docs/skills.md +141 -78
  15. package/mcp/collections.json +1 -1
  16. package/mcp/fallback.json +1 -1
  17. package/mcp/servers.json +1 -1
  18. package/package.json +14 -17
  19. package/plugins/meta-architect/.app.json +1 -1
  20. package/plugins/meta-architect/.mcp.json +1 -1
  21. package/plugins/meta-architect/README.md +10 -23
  22. package/plugins/meta-architect/skills/meta-architect/SKILL.md +23 -17
  23. package/plugins/meta-architect/skills/meta-architect-arch/SKILL.md +24 -0
  24. package/plugins/meta-architect/skills/meta-architect-build/SKILL.md +25 -0
  25. package/plugins/meta-architect/skills/meta-architect-flow/SKILL.md +23 -0
  26. package/plugins/meta-architect/skills/meta-architect-sage/SKILL.md +23 -0
  27. package/plugins/meta-architect/skills/meta-architect-vet/SKILL.md +23 -0
  28. package/plugins/meta-architect/skills/meta-architect-vibe/SKILL.md +24 -0
  29. package/prompts/architect.md +216 -0
  30. package/prompts/builder.md +10 -0
  31. package/prompts/flow.md +9 -0
  32. package/prompts/release-manager.md +10 -0
  33. package/prompts/sage.md +10 -0
  34. package/prompts/security-reviewer.md +10 -0
  35. package/prompts/verifier.md +10 -0
  36. package/prompts/vibe.md +10 -0
  37. package/scripts/doctor.js +0 -8
  38. package/scripts/skills-install.js +36 -4
  39. package/scripts/skills-manifest.js +1 -1
  40. package/scripts/skills-validate.js +40 -78
  41. package/skills/index.json +22 -22
  42. package/skills/meta-architect/SKILL.md +23 -17
  43. package/skills/meta-architect/agents/openai.yaml +3 -3
  44. package/skills/meta-architect/references/core-release-rules.md +2 -2
  45. package/skills/meta-architect-arch/SKILL.md +24 -0
  46. package/skills/meta-architect-arch/agents/openai.yaml +4 -0
  47. package/skills/meta-architect-build/SKILL.md +25 -0
  48. package/skills/meta-architect-build/agents/openai.yaml +4 -0
  49. package/skills/meta-architect-flow/SKILL.md +23 -0
  50. package/skills/meta-architect-flow/agents/openai.yaml +4 -0
  51. package/skills/meta-architect-sage/SKILL.md +23 -0
  52. package/skills/meta-architect-sage/agents/openai.yaml +4 -0
  53. package/skills/meta-architect-vet/SKILL.md +23 -0
  54. package/skills/meta-architect-vet/agents/openai.yaml +4 -0
  55. package/skills/meta-architect-vibe/SKILL.md +24 -0
  56. package/skills/meta-architect-vibe/agents/openai.yaml +4 -0
  57. package/sprint/00-idea.md +1 -1
  58. package/sprint/01-architecture.md +1 -1
  59. package/sprint/02-oss-evidence.md +1 -1
  60. package/sprint/03-logic.md +1 -1
  61. package/sprint/04-security.md +2 -2
  62. package/sprint/05-dx-ux.md +1 -1
  63. package/src/decision-log.js +4 -4
  64. package/src/doctor.js +30 -0
  65. package/src/launcher.js +17 -21
  66. package/src/mcp-live-client.js +1 -1
  67. package/src/paths.js +32 -8
  68. package/src/release-state.js +3 -3
  69. package/src/setup.js +375 -0
  70. package/src/skills.js +166 -309
  71. package/templates/AGENTS.md +6 -6
  72. package/templates/model-instructions/core.md +1 -1
  73. package/.agents/plugins/marketplace.json +0 -20
  74. package/docs/assets/meta-architect-logo.png +0 -0
  75. package/docs/assets/meta-architect-logo.svg +0 -8
  76. package/docs/installed-sdk.md +0 -60
  77. package/docs/qa/release-readiness-0.1.4.md +0 -79
  78. package/plugins/meta-architect/.codex-plugin/plugin.json +0 -23
  79. package/plugins/meta-architect/skills/arch/SKILL.md +0 -27
  80. package/plugins/meta-architect/skills/arch/agents/openai.yaml +0 -4
  81. package/plugins/meta-architect/skills/build/SKILL.md +0 -24
  82. package/plugins/meta-architect/skills/build/agents/openai.yaml +0 -4
  83. package/plugins/meta-architect/skills/flow/SKILL.md +0 -24
  84. package/plugins/meta-architect/skills/flow/agents/openai.yaml +0 -4
  85. package/plugins/meta-architect/skills/meta-architect/agents/openai.yaml +0 -4
  86. package/plugins/meta-architect/skills/meta-architect/references/core-release-rules.md +0 -13
  87. package/plugins/meta-architect/skills/sage/SKILL.md +0 -24
  88. package/plugins/meta-architect/skills/sage/agents/openai.yaml +0 -4
  89. package/plugins/meta-architect/skills/vet/SKILL.md +0 -25
  90. package/plugins/meta-architect/skills/vet/agents/openai.yaml +0 -4
  91. package/plugins/meta-architect/skills/vibe/SKILL.md +0 -24
  92. package/plugins/meta-architect/skills/vibe/agents/openai.yaml +0 -4
  93. package/scripts/plugin-sync.js +0 -92
  94. package/scripts/postinstall.js +0 -23
  95. package/scripts/release-metadata.js +0 -94
  96. package/scripts/release-sync.js +0 -359
  97. package/scripts/release-verify.js +0 -153
  98. package/scripts/setup-npmrc.js +0 -39
  99. package/skills/arch/SKILL.md +0 -27
  100. package/skills/arch/agents/openai.yaml +0 -4
  101. package/skills/build/SKILL.md +0 -24
  102. package/skills/build/agents/openai.yaml +0 -4
  103. package/skills/flow/SKILL.md +0 -24
  104. package/skills/flow/agents/openai.yaml +0 -4
  105. package/skills/sage/SKILL.md +0 -24
  106. package/skills/sage/agents/openai.yaml +0 -4
  107. package/skills/vet/SKILL.md +0 -25
  108. package/skills/vet/agents/openai.yaml +0 -4
  109. package/skills/vibe/SKILL.md +0 -24
  110. package/skills/vibe/agents/openai.yaml +0 -4
  111. package/src/runtime-artifacts.js +0 -363
  112. package/src/skill-installer.js +0 -198
@@ -1,25 +0,0 @@
1
- ---
2
- name: vet
3
- description: "Use when the user wants a security and trust-boundary review of the current design before implementation or release."
4
- ---
5
-
6
- # Vet
7
-
8
- Use this skill inside Codex to review security posture before the build lane.
9
-
10
- ## Output
11
-
12
- Produce:
13
- - trust boundaries
14
- - authn/authz expectations
15
- - sensitive data paths
16
- - abuse cases and likely failure modes
17
- - concrete mitigations
18
- - release blockers vs acceptable risks
19
- - exact next trigger, usually `$vibe`
20
-
21
- ## Rules
22
-
23
- - Prioritize material risks over exhaustive but low-value checklists.
24
- - Call out missing assumptions that affect security posture.
25
- - Distinguish between must-fix blockers and documented accepted risk.
@@ -1,4 +0,0 @@
1
- interface:
2
- display_name: "$vet"
3
- short_description: "Security and trust-boundary review"
4
- default_prompt: "Use $vet to review trust boundaries, security risks, abuse cases, and safer alternatives in the current design."
@@ -1,24 +0,0 @@
1
- ---
2
- name: vibe
3
- description: "Use when the user wants a DX and UX review of the planned workflow before implementation proceeds."
4
- ---
5
-
6
- # Vibe
7
-
8
- Use this skill inside Codex to review whether the system will feel coherent for both operators and end users.
9
-
10
- ## Output
11
-
12
- Produce:
13
- - developer workflow risks
14
- - user workflow risks
15
- - complexity hotspots
16
- - onboarding or operability friction
17
- - simplifications that improve clarity
18
- - exact next trigger, usually `$build`
19
-
20
- ## Rules
21
-
22
- - Focus on concrete friction, not aesthetics-only feedback.
23
- - Prefer fewer surfaces, fewer steps, and clearer operator outcomes.
24
- - Preserve the architecture and security constraints established earlier in the flow.
@@ -1,4 +0,0 @@
1
- interface:
2
- display_name: "$vibe"
3
- short_description: "DX and UX review before implementation"
4
- default_prompt: "Use $vibe to review developer and user experience risks before the build lane proceeds."
@@ -1,363 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
3
- import { ensureDir, writeFileIfMissing } from "./fs-utils.js";
4
- import { getRuntimeWritePath } from "./paths.js";
5
-
6
- const runtimeDirs = ["context", "specs", "plans"];
7
-
8
- function renderProjectContext({ idea = null }) {
9
- return [
10
- "# Project Context",
11
- "",
12
- `Updated: ${new Date().toISOString()}`,
13
- "",
14
- "## Current Brief",
15
- "",
16
- idea ?? 'No project brief captured yet. Run `ma idea "..."` first.',
17
- "",
18
- "## Source Of Truth",
19
- "",
20
- "- `.ma/decisions.json` tracks gate and decision history",
21
- "- `.ma/release.json` tracks release-state fields",
22
- "- `.ma/runbook.md` defines the local helper workflow",
23
- "",
24
- "## Next Recommended Trigger",
25
- "",
26
- idea ? "`$arch`" : "`ma idea`",
27
- "",
28
- ].join("\n");
29
- }
30
-
31
- function renderArchitectureSpec({ idea, blueprint }) {
32
- return [
33
- "# Architecture Spec",
34
- "",
35
- `Updated: ${new Date().toISOString()}`,
36
- "",
37
- "## Problem Statement",
38
- "",
39
- idea,
40
- "",
41
- "## Blueprint Summary",
42
- "",
43
- blueprint.summary,
44
- "",
45
- "## Suggested Stack",
46
- "",
47
- ...blueprint.suggestedStack.map((item) => `- ${item}`),
48
- "",
49
- "## Intended Outcome",
50
- "",
51
- blueprint.outcome,
52
- "",
53
- "## Next Recommended Trigger",
54
- "",
55
- "`$sage`",
56
- "",
57
- ].join("\n");
58
- }
59
-
60
- function renderEvidenceSpec({ idea, sourceEntries, verified, blockers }) {
61
- const status = verified ? "VERIFIED" : sourceEntries.length > 0 ? "PARTIAL" : "MISSING";
62
- const lines = [
63
- "# Evidence Spec",
64
- "",
65
- `Updated: ${new Date().toISOString()}`,
66
- "",
67
- "## Probe Basis",
68
- "",
69
- idea,
70
- "",
71
- "## Evidence Status",
72
- "",
73
- status,
74
- "",
75
- "## Sources",
76
- "",
77
- ];
78
-
79
- if (sourceEntries.length === 0) {
80
- lines.push("No approved GitMCP sources configured.", "");
81
- } else {
82
- for (const source of sourceEntries) {
83
- lines.push(`- ${source.repo} (${source.category})`);
84
- lines.push(` - endpoint: ${source.endpoint}`);
85
- if (source.liveProbe?.sampleText) {
86
- lines.push(` - live probe: ${source.liveProbe.sampleText}`);
87
- } else if (source.liveProbe?.reason) {
88
- lines.push(` - live probe: ${source.liveProbe.reason}`);
89
- } else if (source.liveProbe?.error) {
90
- lines.push(` - live probe error: ${source.liveProbe.error}`);
91
- }
92
- }
93
- lines.push("");
94
- }
95
-
96
- lines.push("## Blockers", "");
97
- if (blockers.length === 0) {
98
- lines.push("None.", "");
99
- } else {
100
- lines.push(...blockers.map((blocker) => `- ${blocker}`), "");
101
- }
102
-
103
- lines.push("## Next Recommended Trigger", "", verified ? "`$flow`" : "`$sage`", "");
104
- return lines.join("\n");
105
- }
106
-
107
- function renderLogicSpec(logicMap) {
108
- return [
109
- "# Logic Spec",
110
- "",
111
- `Updated: ${new Date().toISOString()}`,
112
- "",
113
- "## States",
114
- "",
115
- ...logicMap.states.map((state) => `- ${state}`),
116
- "",
117
- "## Blockers",
118
- "",
119
- ...(logicMap.blockers.length === 0 ? ["None."] : logicMap.blockers.map((item) => `- ${item}`)),
120
- "",
121
- "## Next Recommended Trigger",
122
- "",
123
- "`$vet`",
124
- "",
125
- ].join("\n");
126
- }
127
-
128
- function renderSecuritySpec({ finding, auditCount, cveCount }) {
129
- return [
130
- "# Security Spec",
131
- "",
132
- `Updated: ${new Date().toISOString()}`,
133
- "",
134
- "## Latest Finding",
135
- "",
136
- `- severity: ${finding.severity}`,
137
- `- summary: ${finding.summary}`,
138
- `- unresolved: ${finding.unresolved}`,
139
- "",
140
- "## Evidence Files",
141
- "",
142
- `- audits logged: ${auditCount}`,
143
- `- cve entries logged: ${cveCount}`,
144
- "",
145
- "## Next Recommended Trigger",
146
- "",
147
- "`$vibe`",
148
- "",
149
- ].join("\n");
150
- }
151
-
152
- function renderExperienceSpec({ note, outcomeCount }) {
153
- return [
154
- "# Experience Spec",
155
- "",
156
- `Updated: ${new Date().toISOString()}`,
157
- "",
158
- "## Latest Outcome",
159
- "",
160
- `- area: ${note.area}`,
161
- `- summary: ${note.summary}`,
162
- "",
163
- "## Evidence Files",
164
- "",
165
- `- outcomes logged: ${outcomeCount}`,
166
- "",
167
- "## Next Recommended Trigger",
168
- "",
169
- "`$build`",
170
- "",
171
- ].join("\n");
172
- }
173
-
174
- function renderImplementationPlan({ idea, blueprint }) {
175
- return [
176
- "# Implementation Plan",
177
- "",
178
- `Updated: ${new Date().toISOString()}`,
179
- "",
180
- "## Goal",
181
- "",
182
- idea,
183
- "",
184
- "## Planned Phases",
185
- "",
186
- "- Capture the approved architecture baseline",
187
- "- Validate evidence through approved GitMCP sources",
188
- "- Validate logic and state transitions",
189
- "- Review security and experience gates",
190
- "- Unlock bounded build execution",
191
- "",
192
- "## Architecture Anchor",
193
- "",
194
- blueprint.summary,
195
- "",
196
- ].join("\n");
197
- }
198
-
199
- function renderBuildPlan({ allowed, blockers, nextTriggers, suggestedBranches = [] }) {
200
- const lines = [
201
- "# Build Plan",
202
- "",
203
- `Updated: ${new Date().toISOString()}`,
204
- "",
205
- "## Gate State",
206
- "",
207
- allowed ? "READY" : "LOCKED",
208
- "",
209
- "## Blockers",
210
- "",
211
- ];
212
-
213
- if (blockers.length === 0) {
214
- lines.push("None.", "");
215
- } else {
216
- lines.push(...blockers.map((blocker) => `- ${blocker}`), "");
217
- }
218
-
219
- lines.push("## Next Allowed Triggers", "");
220
- lines.push(
221
- ...(nextTriggers.length === 0 ? ["- $build"] : nextTriggers.map((item) => `- ${item}`)),
222
- "",
223
- );
224
-
225
- if (suggestedBranches.length > 0) {
226
- lines.push(
227
- "## Suggested Branches",
228
- "",
229
- ...suggestedBranches.map((branch) => `- ${branch}`),
230
- "",
231
- );
232
- }
233
-
234
- return lines.join("\n");
235
- }
236
-
237
- function renderRunbook() {
238
- return [
239
- "# Meta-Architect Runbook",
240
- "",
241
- "## Purpose",
242
- "",
243
- "This runbook defines the local helper-path workflow that supports the primary in-session skill flow.",
244
- "",
245
- "## Canonical Sequence",
246
- "",
247
- "1. `ma setup`",
248
- '2. `ma idea "..."`',
249
- "3. `ma run '$arch'`",
250
- "4. `ma run '$sage'`",
251
- "5. `ma run '$flow'`",
252
- "6. `ma run '$vet'`",
253
- "7. `ma run '$vibe'`",
254
- "8. `ma status`",
255
- "9. `ma run '$build'`",
256
- "",
257
- "## Runtime Artifacts",
258
- "",
259
- "- `.ma/context/project.md`",
260
- "- `.ma/specs/architecture.md`",
261
- "- `.ma/specs/evidence.md`",
262
- "- `.ma/specs/logic.md`",
263
- "- `.ma/specs/security.md`",
264
- "- `.ma/specs/experience.md`",
265
- "- `.ma/plans/implementation.md`",
266
- "- `.ma/plans/build.md`",
267
- "- `.ma/decisions.json`",
268
- "- `.ma/release.json`",
269
- "",
270
- "## Guardrails",
271
- "",
272
- "- Do not edit gate status files manually.",
273
- "- Treat GitHub release state and npm registry state as separate facts.",
274
- "- Do not claim a publish channel succeeded without evidence from that channel.",
275
- "",
276
- ].join("\n");
277
- }
278
-
279
- async function writeArtifact(relativePath, content) {
280
- const target = getRuntimeWritePath(...relativePath.split("/"));
281
- await ensureDir(path.dirname(target));
282
- await fs.writeFile(target, `${content.trimEnd()}\n`);
283
- }
284
-
285
- export async function seedRuntimeArtifacts() {
286
- for (const dir of runtimeDirs) {
287
- await ensureDir(getRuntimeWritePath(dir));
288
- }
289
-
290
- await writeFileIfMissing(
291
- getRuntimeWritePath("context", "project.md"),
292
- `${renderProjectContext({})}\n`,
293
- );
294
- await writeFileIfMissing(
295
- getRuntimeWritePath("specs", "architecture.md"),
296
- "# Architecture Spec\n\nNo architecture captured yet.\n",
297
- );
298
- await writeFileIfMissing(
299
- getRuntimeWritePath("specs", "evidence.md"),
300
- "# Evidence Spec\n\nNo evidence captured yet.\n",
301
- );
302
- await writeFileIfMissing(
303
- getRuntimeWritePath("specs", "logic.md"),
304
- "# Logic Spec\n\nNo logic review captured yet.\n",
305
- );
306
- await writeFileIfMissing(
307
- getRuntimeWritePath("specs", "security.md"),
308
- "# Security Spec\n\nNo security review captured yet.\n",
309
- );
310
- await writeFileIfMissing(
311
- getRuntimeWritePath("specs", "experience.md"),
312
- "# Experience Spec\n\nNo experience review captured yet.\n",
313
- );
314
- await writeFileIfMissing(
315
- getRuntimeWritePath("plans", "implementation.md"),
316
- "# Implementation Plan\n\nNo implementation plan captured yet.\n",
317
- );
318
- await writeFileIfMissing(
319
- getRuntimeWritePath("plans", "build.md"),
320
- "# Build Plan\n\nBuild is still locked.\n",
321
- );
322
- await writeFileIfMissing(getRuntimeWritePath("runbook.md"), `${renderRunbook()}\n`);
323
- }
324
-
325
- export async function writeProjectContext(idea) {
326
- await writeArtifact("context/project.md", renderProjectContext({ idea }));
327
- }
328
-
329
- export async function writeArchitectureArtifacts({ idea, blueprint }) {
330
- await writeArtifact("specs/architecture.md", renderArchitectureSpec({ idea, blueprint }));
331
- await writeArtifact("plans/implementation.md", renderImplementationPlan({ idea, blueprint }));
332
- }
333
-
334
- export async function writeEvidenceSpec({ idea, sourceEntries, verified, blockers }) {
335
- await writeArtifact(
336
- "specs/evidence.md",
337
- renderEvidenceSpec({ idea, sourceEntries, verified, blockers }),
338
- );
339
- }
340
-
341
- export async function writeLogicSpec(logicMap) {
342
- await writeArtifact("specs/logic.md", renderLogicSpec(logicMap));
343
- }
344
-
345
- export async function writeSecuritySpec({ finding, auditCount, cveCount }) {
346
- await writeArtifact("specs/security.md", renderSecuritySpec({ finding, auditCount, cveCount }));
347
- }
348
-
349
- export async function writeExperienceSpec({ note, outcomeCount }) {
350
- await writeArtifact("specs/experience.md", renderExperienceSpec({ note, outcomeCount }));
351
- }
352
-
353
- export async function writeBuildPlanArtifact({
354
- allowed,
355
- blockers,
356
- nextTriggers,
357
- suggestedBranches = [],
358
- }) {
359
- await writeArtifact(
360
- "plans/build.md",
361
- renderBuildPlan({ allowed, blockers, nextTriggers, suggestedBranches }),
362
- );
363
- }
@@ -1,198 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import os from "node:os";
3
- import path from "node:path";
4
- import { packageRoot } from "./paths.js";
5
-
6
- function resolveCodexHome() {
7
- return process.env.CODEX_HOME ?? path.join(os.homedir(), ".codex");
8
- }
9
-
10
- function resolveSkillInstallRoot() {
11
- return path.join(resolveCodexHome(), "skills");
12
- }
13
-
14
- function resolveSupportBundleRoot() {
15
- return path.join(resolveCodexHome(), "meta-architect-sdk");
16
- }
17
-
18
- async function copyDir(src, dest) {
19
- await fs.mkdir(dest, { recursive: true });
20
- const entries = await fs.readdir(src, { withFileTypes: true });
21
- for (const entry of entries) {
22
- const srcPath = path.join(src, entry.name);
23
- const destPath = path.join(dest, entry.name);
24
- if (entry.isDirectory()) {
25
- await copyDir(srcPath, destPath);
26
- } else {
27
- await fs.copyFile(srcPath, destPath);
28
- }
29
- }
30
- }
31
-
32
- export function getSkillInstallRoot() {
33
- return resolveSkillInstallRoot();
34
- }
35
-
36
- export function getSupportBundleRoot() {
37
- return resolveSupportBundleRoot();
38
- }
39
-
40
- export async function loadSkillManifest() {
41
- const manifestPath = path.join(packageRoot, "skills", "index.json");
42
- const manifest = JSON.parse(await fs.readFile(manifestPath, "utf8"));
43
- return manifest.skills ?? [];
44
- }
45
-
46
- export async function installSkills({ targetRoot = getSkillInstallRoot() } = {}) {
47
- const skills = await loadSkillManifest();
48
- await fs.mkdir(targetRoot, { recursive: true });
49
-
50
- const installed = [];
51
- for (const skill of skills) {
52
- const src = path.join(packageRoot, skill.path);
53
- const dest = path.join(targetRoot, path.basename(skill.path));
54
- await fs.rm(dest, { recursive: true, force: true });
55
- await copyDir(src, dest);
56
- installed.push({ name: skill.name, dest });
57
- }
58
-
59
- return { targetRoot, installed };
60
- }
61
-
62
- async function copyPath(src, dest) {
63
- const stat = await fs.stat(src);
64
- if (stat.isDirectory()) {
65
- await fs.rm(dest, { recursive: true, force: true });
66
- await copyDir(src, dest);
67
- return "directory";
68
- }
69
-
70
- await fs.mkdir(path.dirname(dest), { recursive: true });
71
- await fs.copyFile(src, dest);
72
- return "file";
73
- }
74
-
75
- export async function installSupportBundle({ targetRoot = getSupportBundleRoot() } = {}) {
76
- const assets = [
77
- {
78
- name: "mcp",
79
- src: path.join(packageRoot, "mcp"),
80
- dest: path.join(targetRoot, "mcp"),
81
- },
82
- {
83
- name: "sprint",
84
- src: path.join(packageRoot, "sprint"),
85
- dest: path.join(targetRoot, "sprint"),
86
- },
87
- {
88
- name: "prompts",
89
- src: path.join(packageRoot, ".codex", "prompts"),
90
- dest: path.join(targetRoot, "prompts"),
91
- },
92
- {
93
- name: "scripts",
94
- src: path.join(packageRoot, "scripts"),
95
- dest: path.join(targetRoot, "scripts"),
96
- },
97
- {
98
- name: "plugin",
99
- src: path.join(packageRoot, "plugins", "meta-architect"),
100
- dest: path.join(targetRoot, "plugins", "meta-architect"),
101
- },
102
- {
103
- name: "templates",
104
- src: path.join(packageRoot, "templates"),
105
- dest: path.join(targetRoot, "templates"),
106
- },
107
- {
108
- name: "docs-readme",
109
- src: path.join(packageRoot, "docs", "README.md"),
110
- dest: path.join(targetRoot, "docs", "README.md"),
111
- },
112
- ];
113
-
114
- await fs.mkdir(targetRoot, { recursive: true });
115
- const installed = [];
116
- for (const asset of assets) {
117
- await copyPath(asset.src, asset.dest);
118
- installed.push({ name: asset.name, dest: asset.dest });
119
- }
120
-
121
- const pkg = JSON.parse(await fs.readFile(path.join(packageRoot, "package.json"), "utf8"));
122
- const manifest = {
123
- packageName: pkg.name,
124
- packageVersion: pkg.version,
125
- installedAt: new Date().toISOString(),
126
- root: targetRoot,
127
- assets: installed,
128
- };
129
- await fs.writeFile(
130
- path.join(targetRoot, "asset-manifest.json"),
131
- `${JSON.stringify(manifest, null, 2)}\n`,
132
- );
133
-
134
- return { targetRoot, installed };
135
- }
136
-
137
- export async function areSkillsInstalled({ targetRoot = getSkillInstallRoot() } = {}) {
138
- const skills = await loadSkillManifest();
139
-
140
- for (const skill of skills) {
141
- const skillDir = path.join(targetRoot, path.basename(skill.path));
142
- try {
143
- await fs.access(path.join(skillDir, "SKILL.md"));
144
- } catch {
145
- return false;
146
- }
147
- }
148
-
149
- return true;
150
- }
151
-
152
- export async function isSupportBundleInstalled({ targetRoot = getSupportBundleRoot() } = {}) {
153
- const requiredFiles = [
154
- path.join(targetRoot, "asset-manifest.json"),
155
- path.join(targetRoot, "mcp", "servers.json"),
156
- path.join(targetRoot, "sprint", "07-release.md"),
157
- path.join(targetRoot, "prompts", "onboarding.md"),
158
- path.join(targetRoot, "scripts", "skills-install.js"),
159
- path.join(targetRoot, "plugins", "meta-architect", ".codex-plugin", "plugin.json"),
160
- path.join(targetRoot, "templates", "AGENTS.md"),
161
- ];
162
-
163
- for (const file of requiredFiles) {
164
- try {
165
- await fs.access(file);
166
- } catch {
167
- return false;
168
- }
169
- }
170
-
171
- return true;
172
- }
173
-
174
- export async function ensureSkillsInstalled({ targetRoot = getSkillInstallRoot() } = {}) {
175
- if (process.env.MA_SKIP_AUTO_INSTALL === "1") {
176
- return { targetRoot, installed: [], skipped: true };
177
- }
178
-
179
- if (await areSkillsInstalled({ targetRoot })) {
180
- return { targetRoot, installed: [], skipped: false };
181
- }
182
-
183
- const result = await installSkills({ targetRoot });
184
- return { ...result, skipped: false };
185
- }
186
-
187
- export async function ensureSupportBundleInstalled({ targetRoot = getSupportBundleRoot() } = {}) {
188
- if (process.env.MA_SKIP_AUTO_INSTALL === "1") {
189
- return { targetRoot, installed: [], skipped: true };
190
- }
191
-
192
- if (await isSupportBundleInstalled({ targetRoot })) {
193
- return { targetRoot, installed: [], skipped: false };
194
- }
195
-
196
- const result = await installSupportBundle({ targetRoot });
197
- return { ...result, skipped: false };
198
- }