@jstn-sdk/ma 0.1.7 → 0.1.9
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.
- package/README.md +26 -5
- package/bin/ma.js +15 -0
- package/docs/README.md +1 -1
- package/docs/getting-started.md +12 -1
- package/docs/qa/{release-readiness-0.1.7.md → release-readiness-0.1.9.md} +8 -8
- package/docs/release-spec.md +6 -6
- package/package.json +1 -1
- package/plugins/meta-architect/.app.json +1 -1
- package/plugins/meta-architect/.codex-plugin/plugin.json +1 -1
- package/plugins/meta-architect/.mcp.json +1 -1
- package/plugins/meta-architect/README.md +1 -1
- package/src/bootstrap.js +342 -0
- package/src/launcher.js +2 -0
- package/src/mcp-live-client.js +1 -1
- package/src/skills.js +2 -2
package/README.md
CHANGED
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
</div>
|
|
19
19
|
|
|
20
20
|
> [!IMPORTANT]
|
|
21
|
-
> Meta-Architect `v0.1.
|
|
21
|
+
> Meta-Architect `v0.1.9` is a production-grade skills line.
|
|
22
22
|
> It is not a lightweight demo branch.
|
|
23
|
-
> From `v0.1.
|
|
23
|
+
> From `v0.1.9` onward, the package is expected to ship with stable skill contracts, deterministic packaging, explicit release gates, and honest install and publish surfaces.
|
|
24
24
|
|
|
25
25
|
## Overview
|
|
26
26
|
|
|
@@ -57,7 +57,7 @@ It adds:
|
|
|
57
57
|
</tr>
|
|
58
58
|
<tr>
|
|
59
59
|
<td><strong>Release line</strong></td>
|
|
60
|
-
<td><code>v0.1.
|
|
60
|
+
<td><code>v0.1.9</code></td>
|
|
61
61
|
</tr>
|
|
62
62
|
<tr>
|
|
63
63
|
<td><strong>License</strong></td>
|
|
@@ -230,7 +230,7 @@ Required output:
|
|
|
230
230
|
5. Data model and storage choices
|
|
231
231
|
6. Auth/security considerations
|
|
232
232
|
7. DX/UX considerations
|
|
233
|
-
8. Delivery plan for v0.1.
|
|
233
|
+
8. Delivery plan for v0.1.9
|
|
234
234
|
9. Risks and trade-offs
|
|
235
235
|
10. Decision log
|
|
236
236
|
11. Exact next trigger to run after this
|
|
@@ -256,10 +256,18 @@ See [example/usage-workflow.md](./example/usage-workflow.md) for the full prompt
|
|
|
256
256
|
If you are working from a repository directly and need scaffolded local support files, use:
|
|
257
257
|
|
|
258
258
|
```bash
|
|
259
|
+
ma bootstrap
|
|
260
|
+
ma bootstrap --init-mcp
|
|
261
|
+
ma doctor
|
|
259
262
|
ma setup
|
|
260
263
|
ma
|
|
261
264
|
```
|
|
262
265
|
|
|
266
|
+
Recommended lazy-user path:
|
|
267
|
+
- run `ma bootstrap` first to repair packaged assets, scaffold local runtime files, and verify the environment
|
|
268
|
+
- add `--init-mcp` if you want starter GitMCP source files written into the local `mcp/` folder when it is empty or invalid
|
|
269
|
+
- use `ma doctor` later when you want a check-only readiness report without changing files
|
|
270
|
+
|
|
263
271
|
Expected output for `ma setup`:
|
|
264
272
|
|
|
265
273
|
```text
|
|
@@ -408,10 +416,23 @@ What `ma setup` and `ma init` do:
|
|
|
408
416
|
- they prepare `.ma/` runtime files such as context, specs, plans, evidence, and runbook files
|
|
409
417
|
- they do not run the skill workflow by themselves
|
|
410
418
|
|
|
419
|
+
What `ma bootstrap` does:
|
|
420
|
+
- checks whether `codex` is callable
|
|
421
|
+
- repairs installed skills and support-bundle assets when possible
|
|
422
|
+
- runs local scaffold setup
|
|
423
|
+
- can seed starter MCP files with `--init-mcp` when the local MCP config is empty or invalid
|
|
424
|
+
- reports `READY`, `READY_WITH_WARNINGS`, or `BLOCKED`
|
|
425
|
+
|
|
426
|
+
What `ma doctor` does:
|
|
427
|
+
- runs the same environment checks without changing files
|
|
428
|
+
- prints the current readiness state and exact next step
|
|
429
|
+
|
|
411
430
|
What to use when:
|
|
412
431
|
- use Codex and run the skills in-session
|
|
413
432
|
- use `$maestro` when you want Meta-Architect to choose the best next step for you
|
|
414
433
|
- use `$arch -> $sage -> $flow -> $vet -> $vibe -> $build` inside the Codex session
|
|
434
|
+
- use `ma bootstrap` when you want the lazy-user setup path
|
|
435
|
+
- use `ma doctor` when you want a check-only environment report
|
|
415
436
|
- use `ma setup` or `ma init` only when you want local scaffolding or scripted helper automation from the terminal
|
|
416
437
|
- use `ma sdk-path` when you need the exact installed support-bundle path for packaged prompts, MCP files, sprint files, scripts, plugin metadata, or templates
|
|
417
438
|
|
|
@@ -587,7 +608,7 @@ Release automation:
|
|
|
587
608
|
| [Plugin README](./plugins/meta-architect/README.md) | plugin distribution surface |
|
|
588
609
|
| [Collaborative Whiteboard Mission](./missions/collaborative-whiteboard/mission.md) | concrete scenario walkthrough |
|
|
589
610
|
| [Release Spec](./docs/release-spec.md) | release and gate policy |
|
|
590
|
-
| [Release Readiness](./docs/qa/release-readiness-0.1.
|
|
611
|
+
| [Release Readiness](./docs/qa/release-readiness-0.1.9.md) | QA evidence for the `v0.1.9` line |
|
|
591
612
|
|
|
592
613
|
## Release Hygiene
|
|
593
614
|
|
package/bin/ma.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
import { runBootstrap, runDoctor } from "../src/bootstrap.js";
|
|
3
4
|
import {
|
|
4
5
|
evaluateBuildGate,
|
|
5
6
|
formatBuildBlockers,
|
|
@@ -36,6 +37,8 @@ import { syncStatusUpdates } from "../src/state-sync.js";
|
|
|
36
37
|
function printUsage() {
|
|
37
38
|
console.error("Secondary helper commands:");
|
|
38
39
|
console.error(" ma");
|
|
40
|
+
console.error(" ma bootstrap [--init-mcp]");
|
|
41
|
+
console.error(" ma doctor");
|
|
39
42
|
console.error(" ma setup");
|
|
40
43
|
console.error(" ma init");
|
|
41
44
|
console.error(' ma idea "..."');
|
|
@@ -220,6 +223,18 @@ async function main() {
|
|
|
220
223
|
return;
|
|
221
224
|
}
|
|
222
225
|
|
|
226
|
+
if (command === "bootstrap") {
|
|
227
|
+
const outcome = await runBootstrap({ initMcp: rest.includes("--init-mcp") });
|
|
228
|
+
process.exitCode = outcome.result === "BLOCKED" ? 1 : 0;
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (command === "doctor") {
|
|
233
|
+
const outcome = await runDoctor();
|
|
234
|
+
process.exitCode = outcome.result === "BLOCKED" ? 1 : 0;
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
223
238
|
if (command === "init") {
|
|
224
239
|
const created = await runInit();
|
|
225
240
|
console.log("meta-architect init");
|
package/docs/README.md
CHANGED
package/docs/getting-started.md
CHANGED
|
@@ -74,7 +74,7 @@ Required output:
|
|
|
74
74
|
5. Data model and storage choices
|
|
75
75
|
6. Auth/security considerations
|
|
76
76
|
7. DX/UX considerations
|
|
77
|
-
8. Delivery plan for v0.1.
|
|
77
|
+
8. Delivery plan for v0.1.9
|
|
78
78
|
9. Risks and trade-offs
|
|
79
79
|
10. Decision log
|
|
80
80
|
11. Exact next trigger to run after this
|
|
@@ -181,6 +181,17 @@ Easy rule:
|
|
|
181
181
|
- they prepare context, specs, plans, evidence, and runbook files
|
|
182
182
|
- they do not automatically run the skill workflow
|
|
183
183
|
|
|
184
|
+
`ma bootstrap` is the lazy-user path:
|
|
185
|
+
- it checks whether `codex` is callable
|
|
186
|
+
- it repairs installed skills and support-bundle assets when possible
|
|
187
|
+
- it runs local scaffold setup
|
|
188
|
+
- it can seed starter MCP files with `--init-mcp` when the local MCP config is empty or invalid
|
|
189
|
+
- it reports `READY`, `READY_WITH_WARNINGS`, or `BLOCKED`
|
|
190
|
+
|
|
191
|
+
`ma doctor` is the check-only path:
|
|
192
|
+
- it runs the same environment checks without changing files
|
|
193
|
+
- it prints the current readiness state and exact next step
|
|
194
|
+
|
|
184
195
|
`ma sdk-path` prints the installed packaged support-bundle root for relevant files such as prompts, MCP files, sprint files, scripts, plugin metadata, and templates.
|
|
185
196
|
|
|
186
197
|
## 5. Configure MCP / GitMCP
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
# Release Readiness 0.1.
|
|
1
|
+
# Release Readiness 0.1.9
|
|
2
2
|
|
|
3
3
|
## Production bar
|
|
4
4
|
|
|
5
|
-
`v0.1.
|
|
5
|
+
`v0.1.9` is treated as production only when:
|
|
6
6
|
- the package installs cleanly from the canonical public install command
|
|
7
7
|
- the Codex-hosted runtime path works end to end
|
|
8
8
|
- the helper flow remains valid for scripted verification
|
|
9
|
-
- release docs, package metadata, and workflows all agree on `0.1.
|
|
9
|
+
- release docs, package metadata, and workflows all agree on `0.1.9`
|
|
10
10
|
|
|
11
11
|
Target release state:
|
|
12
|
-
- npm package: `@jstn-sdk/ma@0.1.
|
|
12
|
+
- npm package: `@jstn-sdk/ma@0.1.9`
|
|
13
13
|
- npm registry state: pending publish
|
|
14
|
-
- publishability note: `0.1.
|
|
15
|
-
- git tag: `v0.1.
|
|
16
|
-
- GitHub release: pending publish for `v0.1.
|
|
14
|
+
- publishability note: `0.1.8` is already published, so `0.1.9` is the next publishable package line
|
|
15
|
+
- git tag: `v0.1.9`
|
|
16
|
+
- GitHub release: pending publish for `v0.1.9`
|
|
17
17
|
|
|
18
18
|
## Production checklist
|
|
19
19
|
|
|
20
20
|
- skills-first product identity: PASS
|
|
21
21
|
- package/plugin identity aligned to `@jstn-sdk/ma`: PASS
|
|
22
|
-
- version/tag alignment `0.1.
|
|
22
|
+
- version/tag alignment `0.1.9` / `v0.1.9`: PASS
|
|
23
23
|
- install/uninstall docs aligned: PASS
|
|
24
24
|
- onboarding is concise and sequential: PASS
|
|
25
25
|
- helper command documented as secondary: PASS
|
package/docs/release-spec.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
# v0.1.
|
|
1
|
+
# v0.1.9 Requirements & Rules
|
|
2
2
|
|
|
3
3
|
## Production definition
|
|
4
4
|
|
|
5
|
-
Meta-Architect `v0.1.
|
|
5
|
+
Meta-Architect `v0.1.9` is production only when:
|
|
6
6
|
1. the package/install surface works
|
|
7
7
|
2. the in-session skill workflow from `$arch` through `$build` works
|
|
8
8
|
3. the release evidence matches the actual package and git tag
|
|
9
9
|
|
|
10
|
-
## What `v0.1.
|
|
10
|
+
## What `v0.1.9` must have
|
|
11
11
|
|
|
12
12
|
### 1. Canonical package/runtime path
|
|
13
13
|
|
|
@@ -49,11 +49,11 @@ Canonical state files:
|
|
|
49
49
|
|
|
50
50
|
### 4. Required release evidence
|
|
51
51
|
|
|
52
|
-
- `package.json` version `0.1.
|
|
53
|
-
- git tag `v0.1.
|
|
52
|
+
- `package.json` version `0.1.9`
|
|
53
|
+
- git tag `v0.1.9`
|
|
54
54
|
- `RELEASE.md`
|
|
55
55
|
- `CHANGELOG.md`
|
|
56
|
-
- `docs/qa/release-readiness-0.1.
|
|
56
|
+
- `docs/qa/release-readiness-0.1.9.md`
|
|
57
57
|
- green `npm run release:check`
|
|
58
58
|
|
|
59
59
|
### 5. Dist-tag discipline
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "meta-architect",
|
|
3
3
|
"displayName": "Meta-Architect",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.9",
|
|
5
5
|
"description": "Programmatic architecture and verified engineering skills for Codex-native workflows.",
|
|
6
6
|
"entry": "./README.md",
|
|
7
7
|
"skillsDir": "./skills"
|
|
@@ -105,7 +105,7 @@ When consuming the plugin:
|
|
|
105
105
|
The plugin version should track the release scope of the core repo.
|
|
106
106
|
|
|
107
107
|
For this repository:
|
|
108
|
-
- plugin scope is aligned to Meta-Architect `v0.1.
|
|
108
|
+
- plugin scope is aligned to Meta-Architect `v0.1.9`
|
|
109
109
|
- any breaking contract change should be versioned intentionally
|
|
110
110
|
|
|
111
111
|
The plugin is one distribution surface of the same product, not a separate product line.
|
package/src/bootstrap.js
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { loadMcpServers } from "./mcp-config.js";
|
|
6
|
+
import { getRepoRoot, getRuntimeWritePath, packageRoot } from "./paths.js";
|
|
7
|
+
import {
|
|
8
|
+
areSkillsInstalled,
|
|
9
|
+
ensureSkillsInstalled,
|
|
10
|
+
ensureSupportBundleInstalled,
|
|
11
|
+
getSkillInstallRoot,
|
|
12
|
+
getSupportBundleRoot,
|
|
13
|
+
isSupportBundleInstalled,
|
|
14
|
+
} from "./skill-installer.js";
|
|
15
|
+
import { runInit } from "./skills.js";
|
|
16
|
+
|
|
17
|
+
function makeStatus(kind, label, detail = "") {
|
|
18
|
+
return { kind, label, detail };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function resolveCodexCommand() {
|
|
22
|
+
return process.env.MA_CODEX_BIN ?? "codex";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function runCommand(command, args) {
|
|
26
|
+
const isNodeScript = [".js", ".mjs", ".cjs"].includes(path.extname(command));
|
|
27
|
+
const finalCommand = isNodeScript ? process.execPath : command;
|
|
28
|
+
const finalArgs = isNodeScript ? [command, ...args] : args;
|
|
29
|
+
return spawnSync(finalCommand, finalArgs, { encoding: "utf8" });
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function inspectCodex() {
|
|
33
|
+
const command = resolveCodexCommand();
|
|
34
|
+
const result = runCommand(command, ["--version"]);
|
|
35
|
+
if (result.error || result.status !== 0) {
|
|
36
|
+
const detail = result.error?.message ?? result.stderr.trim() ?? result.stdout.trim();
|
|
37
|
+
return {
|
|
38
|
+
ok: false,
|
|
39
|
+
command,
|
|
40
|
+
detail: detail || "Codex command failed",
|
|
41
|
+
version: "",
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
ok: true,
|
|
47
|
+
command,
|
|
48
|
+
detail: "",
|
|
49
|
+
version: result.stdout.trim(),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function listCodexPaths() {
|
|
54
|
+
const result = spawnSync("which", ["-a", "codex"], { encoding: "utf8" });
|
|
55
|
+
if (result.error || result.status !== 0) {
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return result.stdout
|
|
60
|
+
.split("\n")
|
|
61
|
+
.map((line) => line.trim())
|
|
62
|
+
.filter(Boolean);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function isWindowsPathInWsl(value) {
|
|
66
|
+
return value.startsWith("/mnt/") && value.includes("/AppData/Roaming/npm/");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function writeCodexWrapper() {
|
|
70
|
+
const wrapperDir = path.join(os.homedir(), ".local", "bin");
|
|
71
|
+
const wrapperPath = path.join(wrapperDir, "codex");
|
|
72
|
+
const content = `#!/usr/bin/env bash
|
|
73
|
+
set -euo pipefail
|
|
74
|
+
|
|
75
|
+
if command -v node >/dev/null 2>&1; then
|
|
76
|
+
NODE_BIN="$(command -v node)"
|
|
77
|
+
NODE_DIR="$(dirname "$NODE_BIN")"
|
|
78
|
+
if [ -x "$NODE_DIR/codex" ] && [ "$NODE_DIR/codex" != "$0" ]; then
|
|
79
|
+
exec "$NODE_DIR/codex" "$@"
|
|
80
|
+
fi
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
while IFS= read -r candidate; do
|
|
84
|
+
[ -n "$candidate" ] || continue
|
|
85
|
+
if [ "$candidate" = "$0" ]; then
|
|
86
|
+
continue
|
|
87
|
+
fi
|
|
88
|
+
case "$candidate" in
|
|
89
|
+
/mnt/*) continue ;;
|
|
90
|
+
esac
|
|
91
|
+
exec "$candidate" "$@"
|
|
92
|
+
done < <(which -a codex 2>/dev/null || true)
|
|
93
|
+
|
|
94
|
+
echo "Unable to locate a Linux Codex binary. Reinstall with: npm install -g @openai/codex@latest" >&2
|
|
95
|
+
exit 1
|
|
96
|
+
`;
|
|
97
|
+
|
|
98
|
+
await fs.mkdir(wrapperDir, { recursive: true });
|
|
99
|
+
await fs.writeFile(wrapperPath, content, { mode: 0o755 });
|
|
100
|
+
await fs.chmod(wrapperPath, 0o755);
|
|
101
|
+
const pathEntries = (process.env.PATH ?? "").split(path.delimiter).filter(Boolean);
|
|
102
|
+
if (!pathEntries.includes(wrapperDir)) {
|
|
103
|
+
process.env.PATH = [wrapperDir, ...pathEntries].join(path.delimiter);
|
|
104
|
+
}
|
|
105
|
+
return wrapperPath;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async function inspectCodexResolution({ fix }) {
|
|
109
|
+
if (process.platform !== "linux") {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const paths = listCodexPaths();
|
|
114
|
+
if (paths.length === 0) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const first = paths[0];
|
|
119
|
+
const linuxAlternative = paths.find((candidate) => !isWindowsPathInWsl(candidate));
|
|
120
|
+
if (!isWindowsPathInWsl(first) || !linuxAlternative) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (!fix) {
|
|
125
|
+
return makeStatus(
|
|
126
|
+
"WARN",
|
|
127
|
+
"codex path points at a Windows npm install inside WSL",
|
|
128
|
+
`Preferred path is ${first}; Linux alternative exists at ${linuxAlternative}`,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const wrapperPath = await writeCodexWrapper();
|
|
133
|
+
return makeStatus(
|
|
134
|
+
"FIXED",
|
|
135
|
+
"codex path will prefer a Linux wrapper inside WSL",
|
|
136
|
+
`Installed wrapper at ${wrapperPath}`,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async function inspectLocalScaffold() {
|
|
141
|
+
const requiredFiles = [
|
|
142
|
+
getRuntimeWritePath("decisions.json"),
|
|
143
|
+
getRuntimeWritePath("release.json"),
|
|
144
|
+
path.join(getRepoRoot(), "mcp", "servers.json"),
|
|
145
|
+
];
|
|
146
|
+
|
|
147
|
+
for (const file of requiredFiles) {
|
|
148
|
+
try {
|
|
149
|
+
await fs.access(file);
|
|
150
|
+
} catch {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function seedStarterMcpConfig() {
|
|
159
|
+
const files = ["servers.json", "collections.json", "fallback.json"];
|
|
160
|
+
for (const file of files) {
|
|
161
|
+
await fs.copyFile(path.join(packageRoot, "mcp", file), path.join(getRepoRoot(), "mcp", file));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async function inspectMcpState({ fix, initMcp }) {
|
|
166
|
+
try {
|
|
167
|
+
const servers = await loadMcpServers();
|
|
168
|
+
if (servers.servers.length === 0) {
|
|
169
|
+
if (fix && initMcp) {
|
|
170
|
+
await seedStarterMcpConfig();
|
|
171
|
+
const seededServers = await loadMcpServers();
|
|
172
|
+
return makeStatus(
|
|
173
|
+
"FIXED",
|
|
174
|
+
"starter MCP sources were seeded into mcp/servers.json",
|
|
175
|
+
`${seededServers.servers.length} configured source(s)`,
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return makeStatus(
|
|
180
|
+
"WARN",
|
|
181
|
+
"mcp/servers.json exists but contains no approved repo-backed sources",
|
|
182
|
+
initMcp
|
|
183
|
+
? "Run `ma bootstrap --init-mcp` to seed starter sources, or add exact upstream GitMCP repo endpoints manually."
|
|
184
|
+
: "Add exact upstream GitMCP repo endpoints before claiming VERIFIED evidence.",
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return makeStatus(
|
|
189
|
+
"OK",
|
|
190
|
+
"mcp/servers.json has approved starter sources",
|
|
191
|
+
`${servers.servers.length} configured source(s)`,
|
|
192
|
+
);
|
|
193
|
+
} catch (error) {
|
|
194
|
+
if (fix && initMcp) {
|
|
195
|
+
await seedStarterMcpConfig();
|
|
196
|
+
const seededServers = await loadMcpServers();
|
|
197
|
+
return makeStatus(
|
|
198
|
+
"FIXED",
|
|
199
|
+
"starter MCP sources replaced an invalid MCP configuration",
|
|
200
|
+
`${seededServers.servers.length} configured source(s)`,
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return makeStatus("WARN", "mcp/servers.json is not ready for evidence binding", error.message);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
async function runEnvironmentFlow({ fix, initMcp }) {
|
|
209
|
+
const statuses = [];
|
|
210
|
+
|
|
211
|
+
const codexResolution = await inspectCodexResolution({ fix });
|
|
212
|
+
if (codexResolution) {
|
|
213
|
+
statuses.push(codexResolution);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const codex = inspectCodex();
|
|
217
|
+
if (codex.ok) {
|
|
218
|
+
statuses.push(makeStatus("OK", "codex command is available", codex.version));
|
|
219
|
+
} else {
|
|
220
|
+
statuses.push(
|
|
221
|
+
makeStatus(
|
|
222
|
+
"BLOCKED",
|
|
223
|
+
"codex command is not usable",
|
|
224
|
+
"Install or repair Codex with: npm install -g @openai/codex@latest",
|
|
225
|
+
),
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const skillInstallRoot = getSkillInstallRoot();
|
|
230
|
+
if (fix) {
|
|
231
|
+
const result = await ensureSkillsInstalled();
|
|
232
|
+
statuses.push(
|
|
233
|
+
makeStatus(
|
|
234
|
+
result.installed.length > 0 ? "FIXED" : "OK",
|
|
235
|
+
"Codex skills are installed",
|
|
236
|
+
skillInstallRoot,
|
|
237
|
+
),
|
|
238
|
+
);
|
|
239
|
+
} else {
|
|
240
|
+
statuses.push(
|
|
241
|
+
makeStatus(
|
|
242
|
+
(await areSkillsInstalled()) ? "OK" : "WARN",
|
|
243
|
+
"Codex skills install state",
|
|
244
|
+
skillInstallRoot,
|
|
245
|
+
),
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const supportBundleRoot = getSupportBundleRoot();
|
|
250
|
+
if (fix) {
|
|
251
|
+
const result = await ensureSupportBundleInstalled();
|
|
252
|
+
statuses.push(
|
|
253
|
+
makeStatus(
|
|
254
|
+
result.installed.length > 0 ? "FIXED" : "OK",
|
|
255
|
+
"support bundle is installed",
|
|
256
|
+
supportBundleRoot,
|
|
257
|
+
),
|
|
258
|
+
);
|
|
259
|
+
} else {
|
|
260
|
+
statuses.push(
|
|
261
|
+
makeStatus(
|
|
262
|
+
(await isSupportBundleInstalled()) ? "OK" : "WARN",
|
|
263
|
+
"support bundle install state",
|
|
264
|
+
supportBundleRoot,
|
|
265
|
+
),
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (fix) {
|
|
270
|
+
await runInit();
|
|
271
|
+
statuses.push(
|
|
272
|
+
makeStatus(
|
|
273
|
+
"FIXED",
|
|
274
|
+
"local Meta-Architect scaffold is ready",
|
|
275
|
+
path.join(getRepoRoot(), ".ma"),
|
|
276
|
+
),
|
|
277
|
+
);
|
|
278
|
+
} else {
|
|
279
|
+
statuses.push(
|
|
280
|
+
makeStatus(
|
|
281
|
+
(await inspectLocalScaffold()) ? "OK" : "WARN",
|
|
282
|
+
"local Meta-Architect scaffold state",
|
|
283
|
+
path.join(getRepoRoot(), ".ma"),
|
|
284
|
+
),
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
statuses.push(await inspectMcpState({ fix, initMcp }));
|
|
289
|
+
return statuses;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function summarizeStatuses(statuses) {
|
|
293
|
+
const hasBlocked = statuses.some((status) => status.kind === "BLOCKED");
|
|
294
|
+
const hasWarn = statuses.some((status) => status.kind === "WARN");
|
|
295
|
+
if (hasBlocked) {
|
|
296
|
+
return "BLOCKED";
|
|
297
|
+
}
|
|
298
|
+
if (hasWarn) {
|
|
299
|
+
return "READY_WITH_WARNINGS";
|
|
300
|
+
}
|
|
301
|
+
return "READY";
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function printStatuses(title, statuses) {
|
|
305
|
+
console.log(title);
|
|
306
|
+
console.log("=".repeat(title.length));
|
|
307
|
+
for (const status of statuses) {
|
|
308
|
+
const label = status.kind.padEnd(7, " ");
|
|
309
|
+
if (status.detail) {
|
|
310
|
+
console.log(`${label} ${status.label}: ${status.detail}`);
|
|
311
|
+
} else {
|
|
312
|
+
console.log(`${label} ${status.label}`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
const result = summarizeStatuses(statuses);
|
|
316
|
+
console.log();
|
|
317
|
+
console.log(`Result: ${result}`);
|
|
318
|
+
if (result === "BLOCKED") {
|
|
319
|
+
console.log("Next: install or repair blocked prerequisites, then rerun `ma bootstrap`.");
|
|
320
|
+
} else if (result === "READY_WITH_WARNINGS") {
|
|
321
|
+
console.log("Next: review warnings, then start Codex or run `ma run '$maestro'`.");
|
|
322
|
+
} else {
|
|
323
|
+
console.log("Next: start Codex or run `ma run '$maestro'`.");
|
|
324
|
+
}
|
|
325
|
+
return result;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export async function runDoctor() {
|
|
329
|
+
const statuses = await runEnvironmentFlow({ fix: false, initMcp: false });
|
|
330
|
+
return {
|
|
331
|
+
statuses,
|
|
332
|
+
result: printStatuses("Meta-Architect Doctor", statuses),
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export async function runBootstrap({ initMcp = false } = {}) {
|
|
337
|
+
const statuses = await runEnvironmentFlow({ fix: true, initMcp });
|
|
338
|
+
return {
|
|
339
|
+
statuses,
|
|
340
|
+
result: printStatuses("Meta-Architect Bootstrap", statuses),
|
|
341
|
+
};
|
|
342
|
+
}
|
package/src/launcher.js
CHANGED
package/src/mcp-live-client.js
CHANGED
package/src/skills.js
CHANGED
|
@@ -508,8 +508,8 @@ export async function runInit() {
|
|
|
508
508
|
path.join(getRepoRoot(), "docs", "release-spec.md"),
|
|
509
509
|
],
|
|
510
510
|
[
|
|
511
|
-
path.join(packageRoot, "docs", "qa", "release-readiness-0.1.
|
|
512
|
-
path.join(getRepoRoot(), "docs", "qa", "release-readiness-0.1.
|
|
511
|
+
path.join(packageRoot, "docs", "qa", "release-readiness-0.1.9.md"),
|
|
512
|
+
path.join(getRepoRoot(), "docs", "qa", "release-readiness-0.1.9.md"),
|
|
513
513
|
],
|
|
514
514
|
];
|
|
515
515
|
|