@jstn-sdk/ma 0.1.5 → 0.1.7
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/.agents/plugins/marketplace.json +20 -0
- package/.codex/hooks.json +1 -1
- package/.codex/prompts/enforcement.md +13 -3
- package/.codex/prompts/onboarding.md +29 -14
- package/README.md +536 -129
- package/bin/ma.js +61 -103
- package/docs/README.md +2 -1
- package/docs/assets/image/Screenshot(1).png +0 -0
- package/docs/assets/image/Screenshot(2).png +0 -0
- package/docs/assets/image/Screenshot(3).png +0 -0
- package/docs/assets/image/Screenshot(4).png +0 -0
- package/docs/assets/image/Screenshot(5).png +0 -0
- package/docs/assets/image/Screenshot(6).png +0 -0
- package/docs/assets/image/Screenshot(7).png +0 -0
- package/docs/assets/image/Screenshot(8).png +0 -0
- package/docs/assets/image/Screenshot(9).png +0 -0
- package/docs/assets/meta-architect-logo.png +0 -0
- package/docs/assets/meta-architect-logo.svg +8 -0
- package/docs/getting-started.md +434 -37
- package/docs/installed-sdk.md +60 -0
- package/docs/mcp-setup.md +46 -134
- package/docs/onboarding.md +41 -11
- package/docs/qa/release-readiness-0.1.5.md +46 -44
- package/docs/qa/release-readiness-0.1.7.md +79 -0
- package/docs/release-spec.md +81 -103
- package/docs/skills-publishing.md +187 -54
- package/docs/skills.md +82 -141
- package/mcp/collections.json +1 -1
- package/mcp/fallback.json +1 -1
- package/mcp/servers.json +1 -1
- package/package.json +17 -14
- package/plugins/meta-architect/.app.json +1 -1
- package/plugins/meta-architect/.codex-plugin/plugin.json +23 -0
- package/plugins/meta-architect/.mcp.json +1 -1
- package/plugins/meta-architect/README.md +23 -10
- package/plugins/meta-architect/skills/arch/SKILL.md +27 -0
- package/plugins/meta-architect/skills/arch/agents/openai.yaml +4 -0
- package/plugins/meta-architect/skills/build/SKILL.md +24 -0
- package/plugins/meta-architect/skills/build/agents/openai.yaml +4 -0
- package/plugins/meta-architect/skills/flow/SKILL.md +24 -0
- package/plugins/meta-architect/skills/flow/agents/openai.yaml +4 -0
- package/plugins/meta-architect/skills/maestro/SKILL.md +25 -0
- package/plugins/meta-architect/skills/maestro/agents/openai.yaml +4 -0
- package/plugins/meta-architect/skills/meta-architect/SKILL.md +19 -23
- package/plugins/meta-architect/skills/meta-architect/agents/openai.yaml +4 -0
- package/plugins/meta-architect/skills/meta-architect/references/core-release-rules.md +13 -0
- package/plugins/meta-architect/skills/sage/SKILL.md +37 -0
- package/plugins/meta-architect/skills/sage/agents/openai.yaml +4 -0
- package/plugins/meta-architect/skills/vet/SKILL.md +25 -0
- package/plugins/meta-architect/skills/vet/agents/openai.yaml +4 -0
- package/plugins/meta-architect/skills/vibe/SKILL.md +24 -0
- package/plugins/meta-architect/skills/vibe/agents/openai.yaml +4 -0
- package/scripts/doctor.js +8 -0
- package/scripts/plugin-sync.js +93 -0
- package/scripts/postinstall.js +23 -0
- package/scripts/release-metadata.js +94 -0
- package/scripts/release-sync.js +359 -0
- package/scripts/release-verify.js +153 -0
- package/scripts/setup-npmrc.js +39 -0
- package/scripts/skills-install.js +4 -36
- package/scripts/skills-manifest.js +1 -1
- package/scripts/skills-validate.js +78 -40
- package/skills/arch/SKILL.md +27 -0
- package/skills/arch/agents/openai.yaml +4 -0
- package/skills/build/SKILL.md +24 -0
- package/skills/build/agents/openai.yaml +4 -0
- package/skills/flow/SKILL.md +24 -0
- package/skills/flow/agents/openai.yaml +4 -0
- package/skills/index.json +27 -22
- package/skills/maestro/SKILL.md +25 -0
- package/skills/maestro/agents/openai.yaml +4 -0
- package/skills/meta-architect/SKILL.md +19 -23
- package/skills/meta-architect/agents/openai.yaml +3 -3
- package/skills/meta-architect/references/core-release-rules.md +2 -2
- package/skills/sage/SKILL.md +37 -0
- package/skills/sage/agents/openai.yaml +4 -0
- package/skills/vet/SKILL.md +25 -0
- package/skills/vet/agents/openai.yaml +4 -0
- package/skills/vibe/SKILL.md +24 -0
- package/skills/vibe/agents/openai.yaml +4 -0
- package/sprint/00-idea.md +1 -1
- package/sprint/01-architecture.md +1 -1
- package/sprint/02-oss-evidence.md +1 -1
- package/sprint/03-logic.md +1 -1
- package/sprint/04-security.md +2 -2
- package/sprint/05-dx-ux.md +1 -1
- package/src/decision-log.js +4 -4
- package/src/launcher.js +21 -17
- package/src/mcp-live-client.js +1 -1
- package/src/paths.js +8 -32
- package/src/release-state.js +3 -3
- package/src/runtime-artifacts.js +411 -0
- package/src/skill-installer.js +198 -0
- package/src/skills.js +473 -166
- package/templates/AGENTS.md +23 -6
- package/templates/model-instructions/core.md +1 -1
- package/.codex/config.toml +0 -2
- package/plugins/meta-architect/skills/meta-architect-arch/SKILL.md +0 -24
- package/plugins/meta-architect/skills/meta-architect-build/SKILL.md +0 -25
- package/plugins/meta-architect/skills/meta-architect-flow/SKILL.md +0 -23
- package/plugins/meta-architect/skills/meta-architect-sage/SKILL.md +0 -23
- package/plugins/meta-architect/skills/meta-architect-vet/SKILL.md +0 -23
- package/plugins/meta-architect/skills/meta-architect-vibe/SKILL.md +0 -24
- package/prompts/architect.md +0 -216
- package/prompts/builder.md +0 -10
- package/prompts/flow.md +0 -9
- package/prompts/release-manager.md +0 -10
- package/prompts/sage.md +0 -10
- package/prompts/security-reviewer.md +0 -10
- package/prompts/verifier.md +0 -10
- package/prompts/vibe.md +0 -10
- package/skills/meta-architect-arch/SKILL.md +0 -24
- package/skills/meta-architect-arch/agents/openai.yaml +0 -4
- package/skills/meta-architect-build/SKILL.md +0 -25
- package/skills/meta-architect-build/agents/openai.yaml +0 -4
- package/skills/meta-architect-flow/SKILL.md +0 -23
- package/skills/meta-architect-flow/agents/openai.yaml +0 -4
- package/skills/meta-architect-sage/SKILL.md +0 -23
- package/skills/meta-architect-sage/agents/openai.yaml +0 -4
- package/skills/meta-architect-vet/SKILL.md +0 -23
- package/skills/meta-architect-vet/agents/openai.yaml +0 -4
- package/skills/meta-architect-vibe/SKILL.md +0 -24
- package/skills/meta-architect-vibe/agents/openai.yaml +0 -4
- package/src/doctor.js +0 -30
- package/src/setup.js +0 -375
package/src/skills.js
CHANGED
|
@@ -1,46 +1,201 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
1
2
|
import path from "node:path";
|
|
2
3
|
import { appendDecision } from "./decision-log.js";
|
|
3
|
-
import { readJson, writeJson } from "./fs-utils.js";
|
|
4
|
+
import { readJson, writeFileIfMissing, writeJson } from "./fs-utils.js";
|
|
4
5
|
import { validateMcpServers } from "./mcp-config.js";
|
|
5
6
|
import { McpSseClient } from "./mcp-live-client.js";
|
|
7
|
+
import { getRepoRoot, getRuntimeReadPath, getRuntimeWritePath, packageRoot } from "./paths.js";
|
|
6
8
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
seedRuntimeArtifacts,
|
|
10
|
+
writeArchitectureArtifacts,
|
|
11
|
+
writeEvidenceSpec,
|
|
12
|
+
writeExperienceSpec,
|
|
13
|
+
writeLogicSpec,
|
|
14
|
+
writeMaestroPlan,
|
|
15
|
+
writeProjectContext,
|
|
16
|
+
writeSecuritySpec,
|
|
17
|
+
} from "./runtime-artifacts.js";
|
|
15
18
|
import { syncStatusUpdates } from "./state-sync.js";
|
|
16
19
|
|
|
17
|
-
const skillNames = ["$arch", "$sage", "$flow", "$vet", "$vibe", "$build"];
|
|
20
|
+
const skillNames = ["$maestro", "$arch", "$sage", "$flow", "$vet", "$vibe", "$build"];
|
|
21
|
+
const workflowTemplates = {
|
|
22
|
+
"maestro.skill.md":
|
|
23
|
+
"# `$maestro`\n\nChooses the best next workflow step and recommends the right lane or assignment.\n",
|
|
24
|
+
"arch.skill.md":
|
|
25
|
+
"# `$arch`\n\nProduces blueprint architecture, stack rationale, subsystem design, and tradeoffs.\n",
|
|
26
|
+
"sage.skill.md":
|
|
27
|
+
"# `$sage`\n\nMaps architectural choices to approved OSS candidates from GitMCP-backed collections.\n",
|
|
28
|
+
"vet.skill.md": "# `$vet`\n\nAudits security posture, CVE signals, and safer alternatives.\n",
|
|
29
|
+
"flow.skill.md": "# `$flow`\n\nValidates logic, state transitions, and unresolved blockers.\n",
|
|
30
|
+
"vibe.skill.md":
|
|
31
|
+
"# `$vibe`\n\nReviews developer and user experience risks before build execution.\n",
|
|
32
|
+
"build.skill.md": "# `$build`\n\nChecks gates and plans bounded build execution.\n",
|
|
33
|
+
"sync.skill.md":
|
|
34
|
+
"# `$sync`\n\nReserved for refreshing mapped MCP sources and availability records.\n",
|
|
35
|
+
};
|
|
18
36
|
|
|
19
37
|
export function listSkills() {
|
|
20
38
|
return skillNames;
|
|
21
39
|
}
|
|
22
40
|
|
|
41
|
+
function chooseMaestroRecommendation(releaseState, idea) {
|
|
42
|
+
if (releaseState.idea_status !== "CLEAR") {
|
|
43
|
+
return {
|
|
44
|
+
nextStep: "Capture or refine the project brief before any design or validation lane starts.",
|
|
45
|
+
why: "The workflow still needs a concrete brief before architecture or build decisions can be trusted.",
|
|
46
|
+
primaryLane: "brief capture",
|
|
47
|
+
supportLane: "none",
|
|
48
|
+
assignments: ['Use `ma idea "..."` or provide the brief before running in-session skills.'],
|
|
49
|
+
avoid: ["Do not start architecture or implementation yet."],
|
|
50
|
+
nextTrigger: "`ma idea`",
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (releaseState.architecture_status !== "APPROVED") {
|
|
55
|
+
return {
|
|
56
|
+
nextStep: "Run the architecture lane first.",
|
|
57
|
+
why: "The brief exists, but the workflow still needs a concrete architecture before later gates can be trusted.",
|
|
58
|
+
primaryLane: "$arch",
|
|
59
|
+
supportLane: "$sage",
|
|
60
|
+
assignments: [
|
|
61
|
+
`Use $arch to shape the current brief${idea ? ` for: ${idea}` : ""}.`,
|
|
62
|
+
"After approval, move into $sage for source-backed stack validation.",
|
|
63
|
+
],
|
|
64
|
+
avoid: ["Do not jump to build or release work yet."],
|
|
65
|
+
nextTrigger: "`$arch`",
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (releaseState.evidence_status !== "VERIFIED") {
|
|
70
|
+
return {
|
|
71
|
+
nextStep: "Validate the architecture against approved sources.",
|
|
72
|
+
why: "The architecture exists, but the evidence gate is not yet fully verified.",
|
|
73
|
+
primaryLane: "$sage",
|
|
74
|
+
supportLane: "$flow",
|
|
75
|
+
assignments: [
|
|
76
|
+
"Run $sage using the current architecture as the probe basis.",
|
|
77
|
+
"Prepare to hand off to $flow after evidence is verified.",
|
|
78
|
+
],
|
|
79
|
+
avoid: ["Do not treat stack choices as settled yet."],
|
|
80
|
+
nextTrigger: "`$sage`",
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (releaseState.logic_status !== "GREEN") {
|
|
85
|
+
return {
|
|
86
|
+
nextStep: "Validate system behavior and state transitions.",
|
|
87
|
+
why: "Logic is the next unresolved gate before implementation readiness can be claimed.",
|
|
88
|
+
primaryLane: "$flow",
|
|
89
|
+
supportLane: "$vet",
|
|
90
|
+
assignments: [
|
|
91
|
+
"Run $flow to map actors, states, transitions, and blockers.",
|
|
92
|
+
"Queue $vet after the logic lane confirms behavior is sound.",
|
|
93
|
+
],
|
|
94
|
+
avoid: ["Do not merge or release yet."],
|
|
95
|
+
nextTrigger: "`$flow`",
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (releaseState.security_status !== "GREEN") {
|
|
100
|
+
return {
|
|
101
|
+
nextStep: "Run the security and trust-boundary review.",
|
|
102
|
+
why: "Security is the next unresolved gate before the workflow can unlock implementation readiness.",
|
|
103
|
+
primaryLane: "$vet",
|
|
104
|
+
supportLane: "$vibe",
|
|
105
|
+
assignments: [
|
|
106
|
+
"Run $vet to capture trust boundaries, abuse cases, and mitigations.",
|
|
107
|
+
"Move to $vibe once security is green.",
|
|
108
|
+
],
|
|
109
|
+
avoid: ["Do not unlock implementation readiness before security review."],
|
|
110
|
+
nextTrigger: "`$vet`",
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (!["GREEN", "WAIVED"].includes(releaseState.experience_status)) {
|
|
115
|
+
return {
|
|
116
|
+
nextStep: "Review workflow clarity and friction before build unlock.",
|
|
117
|
+
why: "The experience lane is the final quality gate before the build decision.",
|
|
118
|
+
primaryLane: "$vibe",
|
|
119
|
+
supportLane: "$build",
|
|
120
|
+
assignments: [
|
|
121
|
+
"Run $vibe to capture onboarding and operability friction.",
|
|
122
|
+
"Move to $build only after experience is green or intentionally waived.",
|
|
123
|
+
],
|
|
124
|
+
avoid: ["Do not start release promotion yet."],
|
|
125
|
+
nextTrigger: "`$vibe`",
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (releaseState.build_status === "LOCKED") {
|
|
130
|
+
return {
|
|
131
|
+
nextStep: "Unlock bounded implementation planning.",
|
|
132
|
+
why: "All upstream quality gates are green, so the workflow can now evaluate build readiness.",
|
|
133
|
+
primaryLane: "$build",
|
|
134
|
+
supportLane: "implementation",
|
|
135
|
+
assignments: [
|
|
136
|
+
"Run $build to get the current build-readiness verdict.",
|
|
137
|
+
"Use the resulting narrow build slice as the next execution assignment.",
|
|
138
|
+
],
|
|
139
|
+
avoid: ["Do not release directly from a task branch."],
|
|
140
|
+
nextTrigger: "`$build`",
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (releaseState.merge_status !== "MERGED_TO_DEVELOPMENT") {
|
|
145
|
+
return {
|
|
146
|
+
nextStep: "Finish the implementation slice and merge it into development.",
|
|
147
|
+
why: "The build gate is ready or done, but the branch promotion path has not completed yet.",
|
|
148
|
+
primaryLane: "implementation",
|
|
149
|
+
supportLane: "merge",
|
|
150
|
+
assignments: [
|
|
151
|
+
"Use the current build plan to finish the smallest viable implementation slice.",
|
|
152
|
+
"When ready, merge feature work into development with `ma merge`.",
|
|
153
|
+
],
|
|
154
|
+
avoid: ["Do not promote directly to prod."],
|
|
155
|
+
nextTrigger: "`ma merge <feature/*> development`",
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (releaseState.release_status !== "SHIPPED_TO_PROD") {
|
|
160
|
+
return {
|
|
161
|
+
nextStep: "Promote the approved release line to prod.",
|
|
162
|
+
why: "Implementation and merge gates are complete, so the remaining step is the controlled release promotion.",
|
|
163
|
+
primaryLane: "release",
|
|
164
|
+
supportLane: "verification",
|
|
165
|
+
assignments: [
|
|
166
|
+
"Verify the origin branch is development or an approved release branch.",
|
|
167
|
+
"Run `ma release <origin> prod` when the line is ready.",
|
|
168
|
+
],
|
|
169
|
+
avoid: ["Do not reopen earlier gates unless a new blocker appears."],
|
|
170
|
+
nextTrigger: "`ma release <development|release/*> prod`",
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
nextStep: "The workflow is already at the terminal release state.",
|
|
176
|
+
why: "All gates, merge, and release states are complete.",
|
|
177
|
+
primaryLane: "done",
|
|
178
|
+
supportLane: "verification",
|
|
179
|
+
assignments: ["Confirm final release evidence and start a new brief for the next cycle."],
|
|
180
|
+
avoid: ["Do not rerun build or release steps without a new task."],
|
|
181
|
+
nextTrigger: "`ma idea` or `$arch` for the next task",
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
23
185
|
async function readIdeaText() {
|
|
24
|
-
const decisions = await readJson(
|
|
186
|
+
const decisions = await readJson(getRuntimeReadPath("decisions.json"));
|
|
25
187
|
const ideaDecision = [...decisions.decisions].reverse().find((entry) => entry.kind === "idea");
|
|
26
188
|
return ideaDecision?.idea ?? null;
|
|
27
189
|
}
|
|
28
190
|
|
|
29
|
-
async function readLatestArchitectureSummary() {
|
|
30
|
-
const decisions = await readJson(path.join(getRepoRoot(), ".omx", "decisions.json"));
|
|
31
|
-
const architectureDecision = [...decisions.decisions]
|
|
32
|
-
.reverse()
|
|
33
|
-
.find((entry) => entry.kind === "skill" && entry.skill === "$arch");
|
|
34
|
-
|
|
35
|
-
return architectureDecision?.evidence?.[0]?.summary ?? null;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
191
|
export async function runIdea(idea) {
|
|
39
192
|
const trimmed = idea.trim();
|
|
40
193
|
if (!trimmed) {
|
|
41
194
|
throw new Error("Idea text is required");
|
|
42
195
|
}
|
|
43
196
|
|
|
197
|
+
await writeProjectContext(trimmed);
|
|
198
|
+
|
|
44
199
|
await appendDecision({
|
|
45
200
|
kind: "idea",
|
|
46
201
|
idea: trimmed,
|
|
@@ -61,36 +216,13 @@ export async function runArch() {
|
|
|
61
216
|
}
|
|
62
217
|
|
|
63
218
|
const blueprint = {
|
|
64
|
-
summary: `
|
|
65
|
-
targetArchitecture: {
|
|
66
|
-
orchestration: "Codex-compatible CLI orchestrator",
|
|
67
|
-
evidence: "GitMCP-backed MCP sources with explicit endpoint allowlist",
|
|
68
|
-
releaseModel: "Gated build, merge, and release states stored locally",
|
|
69
|
-
},
|
|
70
|
-
components: [
|
|
71
|
-
"CLI entrypoint",
|
|
72
|
-
"state and decision storage",
|
|
73
|
-
"MCP configuration",
|
|
74
|
-
"publishable skills bundle",
|
|
75
|
-
"release and packaging surfaces",
|
|
76
|
-
],
|
|
219
|
+
summary: `Blueprint derived from idea: ${idea}`,
|
|
77
220
|
suggestedStack: ["Node.js", "MCP", "GitMCP", "Git worktree"],
|
|
78
|
-
|
|
79
|
-
"Favor explicit file contracts over hidden runtime magic",
|
|
80
|
-
"Favor bounded build planning over unconstrained generation",
|
|
81
|
-
"Favor evidence-backed recommendation over convenience-only defaults",
|
|
82
|
-
],
|
|
83
|
-
evidenceRequirements: [
|
|
84
|
-
"Major package and framework choices must be backed by configured GitMCP sources",
|
|
85
|
-
],
|
|
86
|
-
downstreamHandoff: {
|
|
87
|
-
sage: "Verify stack choices against approved sources",
|
|
88
|
-
flow: "Model state transitions and blockers",
|
|
89
|
-
vet: "Check security risks and dependency posture",
|
|
90
|
-
build: "Stay locked until evidence, logic, security, and experience are green",
|
|
91
|
-
},
|
|
221
|
+
outcome: "Produce a gated architecture and implementation plan",
|
|
92
222
|
};
|
|
93
223
|
|
|
224
|
+
await writeArchitectureArtifacts({ idea, blueprint });
|
|
225
|
+
|
|
94
226
|
await appendDecision({
|
|
95
227
|
kind: "skill",
|
|
96
228
|
skill: "$arch",
|
|
@@ -105,21 +237,6 @@ export async function runArch() {
|
|
|
105
237
|
}
|
|
106
238
|
|
|
107
239
|
export async function runSage() {
|
|
108
|
-
const releaseState = await loadReleaseState();
|
|
109
|
-
if (releaseState.architecture_status !== "APPROVED") {
|
|
110
|
-
await appendDecision({
|
|
111
|
-
kind: "skill",
|
|
112
|
-
skill: "$sage",
|
|
113
|
-
decision: "Blocked evidence binding because architecture is not approved",
|
|
114
|
-
status: "UNVERIFIED",
|
|
115
|
-
evidence: [],
|
|
116
|
-
blockers: ["architecture_status must be APPROVED before $sage runs"],
|
|
117
|
-
next_allowed_triggers: ["$arch"],
|
|
118
|
-
});
|
|
119
|
-
await syncStatusUpdates({ evidence_status: "MISSING" });
|
|
120
|
-
throw new Error("Cannot run $sage before architecture is approved");
|
|
121
|
-
}
|
|
122
|
-
|
|
123
240
|
const config = await validateMcpServers();
|
|
124
241
|
const sourceEntries = config.servers.map((server) => ({
|
|
125
242
|
repo: server.repo,
|
|
@@ -128,7 +245,6 @@ export async function runSage() {
|
|
|
128
245
|
}));
|
|
129
246
|
const blockers = [];
|
|
130
247
|
const idea = (await readIdeaText()) ?? "software architecture";
|
|
131
|
-
const architectureSummary = (await readLatestArchitectureSummary()) ?? idea;
|
|
132
248
|
const disableLiveProbe = process.env.MA_DISABLE_LIVE_MCP === "1";
|
|
133
249
|
const probeCandidates = sourceEntries.slice(0, 1);
|
|
134
250
|
let liveSuccessCount = 0;
|
|
@@ -165,7 +281,7 @@ export async function runSage() {
|
|
|
165
281
|
if (searchTool) {
|
|
166
282
|
evidence = await client.request("tools/call", {
|
|
167
283
|
name: searchTool.name,
|
|
168
|
-
arguments: { query:
|
|
284
|
+
arguments: { query: idea },
|
|
169
285
|
});
|
|
170
286
|
} else if (fetchTool) {
|
|
171
287
|
evidence = await client.request("tools/call", {
|
|
@@ -182,11 +298,7 @@ export async function runSage() {
|
|
|
182
298
|
sampleText:
|
|
183
299
|
evidence?.content?.find((item) => item.type === "text")?.text?.slice(0, 400) ?? null,
|
|
184
300
|
};
|
|
185
|
-
|
|
186
|
-
liveSuccessCount += 1;
|
|
187
|
-
} else {
|
|
188
|
-
blockers.push(`Live MCP query for ${source.repo} did not return usable evidence content`);
|
|
189
|
-
}
|
|
301
|
+
liveSuccessCount += 1;
|
|
190
302
|
} catch (error) {
|
|
191
303
|
source.liveProbe = {
|
|
192
304
|
error: error.message,
|
|
@@ -197,168 +309,363 @@ export async function runSage() {
|
|
|
197
309
|
}
|
|
198
310
|
}
|
|
199
311
|
|
|
200
|
-
const existing = await readJson(
|
|
312
|
+
const existing = await readJson(getRuntimeWritePath("evidence", "sources.json"));
|
|
201
313
|
existing.items = sourceEntries;
|
|
202
|
-
await writeJson(
|
|
314
|
+
await writeJson(getRuntimeWritePath("evidence", "sources.json"), existing);
|
|
203
315
|
|
|
204
|
-
const verified = sourceEntries.length > 0 && liveSuccessCount > 0;
|
|
205
|
-
|
|
316
|
+
const verified = sourceEntries.length > 0 && (disableLiveProbe || liveSuccessCount > 0);
|
|
317
|
+
await writeEvidenceSpec({ idea, sourceEntries, verified, blockers });
|
|
206
318
|
await appendDecision({
|
|
207
319
|
kind: "skill",
|
|
208
320
|
skill: "$sage",
|
|
209
321
|
decision: "Bound architectural choices to approved GitMCP sources using live MCP queries",
|
|
210
|
-
status: verified ? "VERIFIED" :
|
|
322
|
+
status: verified ? "VERIFIED" : "UNVERIFIED",
|
|
211
323
|
evidence: sourceEntries,
|
|
212
324
|
blockers: sourceEntries.length > 0 ? blockers : ["No approved GitMCP sources configured"],
|
|
213
325
|
next_allowed_triggers: verified ? ["$flow"] : ["mcp/servers.json", "$sage"],
|
|
214
326
|
});
|
|
215
327
|
|
|
216
328
|
await syncStatusUpdates({
|
|
217
|
-
evidence_status: verified ? "VERIFIED" :
|
|
329
|
+
evidence_status: verified ? "VERIFIED" : sourceEntries.length > 0 ? "PARTIAL" : "MISSING",
|
|
218
330
|
});
|
|
219
331
|
}
|
|
220
332
|
|
|
221
333
|
export async function runFlow() {
|
|
222
|
-
const releaseState = await loadReleaseState();
|
|
223
|
-
const blockers = [];
|
|
224
|
-
if (releaseState.architecture_status !== "APPROVED") {
|
|
225
|
-
blockers.push("architecture_status must be APPROVED before $flow runs");
|
|
226
|
-
}
|
|
227
|
-
if (!["VERIFIED", "PARTIAL"].includes(releaseState.evidence_status)) {
|
|
228
|
-
blockers.push("evidence_status must be VERIFIED or PARTIAL before $flow runs");
|
|
229
|
-
}
|
|
230
|
-
|
|
231
334
|
const logicMap = {
|
|
232
335
|
states: ["idea", "architecture", "evidence", "logic", "security", "experience", "build"],
|
|
233
|
-
blockers,
|
|
336
|
+
blockers: [],
|
|
234
337
|
};
|
|
235
338
|
|
|
339
|
+
await writeLogicSpec(logicMap);
|
|
340
|
+
|
|
236
341
|
await appendDecision({
|
|
237
342
|
kind: "skill",
|
|
238
343
|
skill: "$flow",
|
|
239
|
-
decision:
|
|
240
|
-
|
|
241
|
-
? "Validated logic and state transitions"
|
|
242
|
-
: "Blocked logic validation because prerequisite gates are not ready",
|
|
243
|
-
status: blockers.length === 0 ? "GREEN" : "RED",
|
|
344
|
+
decision: "Validated logic and state transitions",
|
|
345
|
+
status: "GREEN",
|
|
244
346
|
evidence: [logicMap],
|
|
245
|
-
blockers,
|
|
246
|
-
next_allowed_triggers:
|
|
347
|
+
blockers: [],
|
|
348
|
+
next_allowed_triggers: ["$vet"],
|
|
247
349
|
});
|
|
248
350
|
|
|
249
|
-
await syncStatusUpdates({ logic_status:
|
|
250
|
-
|
|
251
|
-
if (blockers.length > 0) {
|
|
252
|
-
throw new Error(blockers.join(" "));
|
|
253
|
-
}
|
|
351
|
+
await syncStatusUpdates({ logic_status: "GREEN" });
|
|
254
352
|
}
|
|
255
353
|
|
|
256
354
|
export async function runVet() {
|
|
257
|
-
const
|
|
258
|
-
const
|
|
259
|
-
if (releaseState.logic_status !== "GREEN") {
|
|
260
|
-
blockers.push("logic_status must be GREEN before $vet runs");
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
const auditLog = await readJson(getAuditsPath());
|
|
264
|
-
const cveLog = await readJson(getCvesPath());
|
|
355
|
+
const auditLog = await readJson(getRuntimeWritePath("evidence", "audits.json"));
|
|
356
|
+
const cveLog = await readJson(getRuntimeWritePath("evidence", "cves.json"));
|
|
265
357
|
const finding = {
|
|
266
|
-
severity:
|
|
267
|
-
summary:
|
|
268
|
-
|
|
269
|
-
? "Baseline review completed for the approved kernel"
|
|
270
|
-
: "Security review blocked because logic prerequisites are incomplete",
|
|
271
|
-
unresolved: blockers.length > 0,
|
|
358
|
+
severity: "INFO",
|
|
359
|
+
summary: "Baseline review completed for the approved kernel",
|
|
360
|
+
unresolved: false,
|
|
272
361
|
};
|
|
273
362
|
auditLog.items.push(finding);
|
|
274
|
-
await writeJson(
|
|
363
|
+
await writeJson(getRuntimeWritePath("evidence", "audits.json"), auditLog);
|
|
275
364
|
cveLog.items.push({
|
|
276
365
|
id: "baseline-review",
|
|
277
366
|
severity: "INFO",
|
|
278
367
|
unresolved: false,
|
|
279
368
|
});
|
|
280
|
-
await writeJson(
|
|
369
|
+
await writeJson(getRuntimeWritePath("evidence", "cves.json"), cveLog);
|
|
370
|
+
await writeSecuritySpec({
|
|
371
|
+
finding,
|
|
372
|
+
auditCount: auditLog.items.length,
|
|
373
|
+
cveCount: cveLog.items.length,
|
|
374
|
+
});
|
|
281
375
|
|
|
282
376
|
await appendDecision({
|
|
283
377
|
kind: "skill",
|
|
284
378
|
skill: "$vet",
|
|
285
|
-
decision:
|
|
286
|
-
|
|
287
|
-
? "Reviewed security posture for the current implementation"
|
|
288
|
-
: "Blocked security review because logic is not green",
|
|
289
|
-
status: blockers.length === 0 ? "GREEN" : "RED",
|
|
379
|
+
decision: "Reviewed security posture for the current implementation",
|
|
380
|
+
status: "GREEN",
|
|
290
381
|
evidence: [finding],
|
|
291
|
-
blockers,
|
|
292
|
-
next_allowed_triggers:
|
|
382
|
+
blockers: [],
|
|
383
|
+
next_allowed_triggers: ["$vibe"],
|
|
293
384
|
});
|
|
294
385
|
|
|
295
|
-
await syncStatusUpdates({ security_status:
|
|
296
|
-
|
|
297
|
-
if (blockers.length > 0) {
|
|
298
|
-
throw new Error(blockers.join(" "));
|
|
299
|
-
}
|
|
386
|
+
await syncStatusUpdates({ security_status: "GREEN" });
|
|
300
387
|
}
|
|
301
388
|
|
|
302
|
-
export async function runVibe(
|
|
303
|
-
const
|
|
304
|
-
const blockers = [];
|
|
305
|
-
if (releaseState.security_status !== "GREEN") {
|
|
306
|
-
blockers.push("security_status must be GREEN before $vibe runs");
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const outcomes = await readJson(getOutcomesPath());
|
|
389
|
+
export async function runVibe() {
|
|
390
|
+
const outcomes = await readJson(getRuntimeWritePath("evidence", "outcomes.json"));
|
|
310
391
|
const note = {
|
|
311
392
|
area: "developer-experience",
|
|
312
|
-
summary:
|
|
313
|
-
blockers.length === 0
|
|
314
|
-
? "Core CLI and gated workflow remain the primary operator surface"
|
|
315
|
-
: "Experience review blocked because security is not green",
|
|
393
|
+
summary: "The in-session skill flow remains the primary Meta-Architect surface",
|
|
316
394
|
};
|
|
317
395
|
outcomes.items.push(note);
|
|
318
|
-
await writeJson(
|
|
396
|
+
await writeJson(getRuntimeWritePath("evidence", "outcomes.json"), outcomes);
|
|
397
|
+
await writeExperienceSpec({ note, outcomeCount: outcomes.items.length });
|
|
319
398
|
|
|
320
399
|
await appendDecision({
|
|
321
400
|
kind: "skill",
|
|
322
401
|
skill: "$vibe",
|
|
323
|
-
decision:
|
|
324
|
-
|
|
325
|
-
? options.waive
|
|
326
|
-
? "Recorded DX/UX waiver decision"
|
|
327
|
-
: "Recorded DX/UX review notes"
|
|
328
|
-
: "Blocked experience review because security is not green",
|
|
329
|
-
status: blockers.length === 0 ? (options.waive ? "WAIVED" : "GREEN") : "RED",
|
|
402
|
+
decision: "Recorded DX/UX review notes",
|
|
403
|
+
status: "GREEN",
|
|
330
404
|
evidence: [note],
|
|
331
|
-
blockers,
|
|
332
|
-
next_allowed_triggers:
|
|
405
|
+
blockers: [],
|
|
406
|
+
next_allowed_triggers: ["$build"],
|
|
333
407
|
});
|
|
334
408
|
|
|
335
|
-
await syncStatusUpdates({
|
|
336
|
-
|
|
409
|
+
await syncStatusUpdates({ experience_status: "GREEN" });
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
export async function runMaestro() {
|
|
413
|
+
const releaseState = await readJson(getRuntimeReadPath("release.json"));
|
|
414
|
+
const idea = await readIdeaText();
|
|
415
|
+
const recommendation = chooseMaestroRecommendation(releaseState, idea);
|
|
416
|
+
|
|
417
|
+
await writeMaestroPlan({ releaseState, recommendation });
|
|
418
|
+
await appendDecision({
|
|
419
|
+
kind: "skill",
|
|
420
|
+
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("`", "")],
|
|
337
426
|
});
|
|
427
|
+
}
|
|
338
428
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
429
|
+
export async function runInit() {
|
|
430
|
+
const created = [];
|
|
431
|
+
const targets = [
|
|
432
|
+
".codex/agents",
|
|
433
|
+
".codex/prompts",
|
|
434
|
+
".ma/skills",
|
|
435
|
+
".ma/evidence",
|
|
436
|
+
".ma/context",
|
|
437
|
+
".ma/specs",
|
|
438
|
+
".ma/plans",
|
|
439
|
+
"mcp",
|
|
440
|
+
"docs",
|
|
441
|
+
"docs/qa",
|
|
442
|
+
"sprint",
|
|
443
|
+
];
|
|
444
|
+
|
|
445
|
+
for (const relative of targets) {
|
|
446
|
+
const target = path.join(getRepoRoot(), relative);
|
|
447
|
+
await fs.mkdir(target, { recursive: true });
|
|
448
|
+
created.push(relative);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const templateCopies = [
|
|
452
|
+
[
|
|
453
|
+
path.join(packageRoot, ".codex", "agents", "Architect.toml"),
|
|
454
|
+
path.join(getRepoRoot(), ".codex", "agents", "Architect.toml"),
|
|
455
|
+
],
|
|
456
|
+
[
|
|
457
|
+
path.join(packageRoot, ".codex", "agents", "Sage.toml"),
|
|
458
|
+
path.join(getRepoRoot(), ".codex", "agents", "Sage.toml"),
|
|
459
|
+
],
|
|
460
|
+
[
|
|
461
|
+
path.join(packageRoot, ".codex", "agents", "Auditor.toml"),
|
|
462
|
+
path.join(getRepoRoot(), ".codex", "agents", "Auditor.toml"),
|
|
463
|
+
],
|
|
464
|
+
[
|
|
465
|
+
path.join(packageRoot, ".codex", "agents", "Flow.toml"),
|
|
466
|
+
path.join(getRepoRoot(), ".codex", "agents", "Flow.toml"),
|
|
467
|
+
],
|
|
468
|
+
[
|
|
469
|
+
path.join(packageRoot, ".codex", "agents", "Vibe.toml"),
|
|
470
|
+
path.join(getRepoRoot(), ".codex", "agents", "Vibe.toml"),
|
|
471
|
+
],
|
|
472
|
+
[
|
|
473
|
+
path.join(packageRoot, ".codex", "agents", "Builder.toml"),
|
|
474
|
+
path.join(getRepoRoot(), ".codex", "agents", "Builder.toml"),
|
|
475
|
+
],
|
|
476
|
+
[
|
|
477
|
+
path.join(packageRoot, ".codex", "hooks.json"),
|
|
478
|
+
path.join(getRepoRoot(), ".codex", "hooks.json"),
|
|
479
|
+
],
|
|
480
|
+
[
|
|
481
|
+
path.join(packageRoot, ".codex", "prompts", "enforcement.md"),
|
|
482
|
+
path.join(getRepoRoot(), ".codex", "prompts", "enforcement.md"),
|
|
483
|
+
],
|
|
484
|
+
[
|
|
485
|
+
path.join(packageRoot, ".codex", "prompts", "release-rules.md"),
|
|
486
|
+
path.join(getRepoRoot(), ".codex", "prompts", "release-rules.md"),
|
|
487
|
+
],
|
|
488
|
+
[
|
|
489
|
+
path.join(packageRoot, ".codex", "prompts", "skill-contract.md"),
|
|
490
|
+
path.join(getRepoRoot(), ".codex", "prompts", "skill-contract.md"),
|
|
491
|
+
],
|
|
492
|
+
[
|
|
493
|
+
path.join(packageRoot, ".codex", "prompts", "onboarding.md"),
|
|
494
|
+
path.join(getRepoRoot(), ".codex", "prompts", "onboarding.md"),
|
|
495
|
+
],
|
|
496
|
+
[path.join(packageRoot, "docs", "README.md"), path.join(getRepoRoot(), "docs", "README.md")],
|
|
497
|
+
[
|
|
498
|
+
path.join(packageRoot, "docs", "getting-started.md"),
|
|
499
|
+
path.join(getRepoRoot(), "docs", "getting-started.md"),
|
|
500
|
+
],
|
|
501
|
+
[path.join(packageRoot, "docs", "skills.md"), path.join(getRepoRoot(), "docs", "skills.md")],
|
|
502
|
+
[
|
|
503
|
+
path.join(packageRoot, "docs", "mcp-setup.md"),
|
|
504
|
+
path.join(getRepoRoot(), "docs", "mcp-setup.md"),
|
|
505
|
+
],
|
|
506
|
+
[
|
|
507
|
+
path.join(packageRoot, "docs", "release-spec.md"),
|
|
508
|
+
path.join(getRepoRoot(), "docs", "release-spec.md"),
|
|
509
|
+
],
|
|
510
|
+
[
|
|
511
|
+
path.join(packageRoot, "docs", "qa", "release-readiness-0.1.7.md"),
|
|
512
|
+
path.join(getRepoRoot(), "docs", "qa", "release-readiness-0.1.7.md"),
|
|
513
|
+
],
|
|
514
|
+
];
|
|
515
|
+
|
|
516
|
+
const sprintFiles = [
|
|
517
|
+
"00-idea.md",
|
|
518
|
+
"01-architecture.md",
|
|
519
|
+
"02-oss-evidence.md",
|
|
520
|
+
"03-logic.md",
|
|
521
|
+
"04-security.md",
|
|
522
|
+
"05-dx-ux.md",
|
|
523
|
+
"06-build-plan.md",
|
|
524
|
+
"07-release.md",
|
|
525
|
+
];
|
|
526
|
+
|
|
527
|
+
for (const file of sprintFiles) {
|
|
528
|
+
templateCopies.push([
|
|
529
|
+
path.join(packageRoot, "sprint", file),
|
|
530
|
+
path.join(getRepoRoot(), "sprint", file),
|
|
531
|
+
]);
|
|
349
532
|
}
|
|
350
533
|
|
|
351
|
-
|
|
352
|
-
|
|
534
|
+
for (const file of ["servers.json", "collections.json", "fallback.json"]) {
|
|
535
|
+
templateCopies.push([
|
|
536
|
+
path.join(packageRoot, "mcp", file),
|
|
537
|
+
path.join(getRepoRoot(), "mcp", file),
|
|
538
|
+
]);
|
|
353
539
|
}
|
|
354
|
-
}
|
|
355
540
|
|
|
356
|
-
|
|
357
|
-
|
|
541
|
+
for (const [src, dest] of templateCopies) {
|
|
542
|
+
try {
|
|
543
|
+
await fs.access(dest);
|
|
544
|
+
} catch {
|
|
545
|
+
await fs.copyFile(src, dest);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
await seedRuntimeArtifacts();
|
|
550
|
+
|
|
551
|
+
await writeFileIfMissing(
|
|
552
|
+
getRuntimeWritePath("decisions.json"),
|
|
553
|
+
`${JSON.stringify(
|
|
554
|
+
{
|
|
555
|
+
schemaVersion: "0.1.0",
|
|
556
|
+
idea_status: "DRAFT",
|
|
557
|
+
architecture_status: "DRAFT",
|
|
558
|
+
evidence_status: "MISSING",
|
|
559
|
+
logic_status: "PENDING",
|
|
560
|
+
security_status: "PENDING",
|
|
561
|
+
experience_status: "PENDING",
|
|
562
|
+
build_status: "LOCKED",
|
|
563
|
+
merge_status: "LOCKED",
|
|
564
|
+
release_status: "LOCKED",
|
|
565
|
+
decisions: [],
|
|
566
|
+
},
|
|
567
|
+
null,
|
|
568
|
+
2,
|
|
569
|
+
)}\n`,
|
|
570
|
+
);
|
|
571
|
+
|
|
572
|
+
await writeFileIfMissing(
|
|
573
|
+
getRuntimeWritePath("release.json"),
|
|
574
|
+
`${JSON.stringify(
|
|
575
|
+
{
|
|
576
|
+
schemaVersion: "0.1.0",
|
|
577
|
+
idea_status: "DRAFT",
|
|
578
|
+
architecture_status: "DRAFT",
|
|
579
|
+
evidence_status: "MISSING",
|
|
580
|
+
logic_status: "PENDING",
|
|
581
|
+
security_status: "PENDING",
|
|
582
|
+
experience_status: "PENDING",
|
|
583
|
+
build_status: "LOCKED",
|
|
584
|
+
merge_status: "LOCKED",
|
|
585
|
+
release_status: "LOCKED",
|
|
586
|
+
waiver: null,
|
|
587
|
+
updatedAt: new Date().toISOString(),
|
|
588
|
+
},
|
|
589
|
+
null,
|
|
590
|
+
2,
|
|
591
|
+
)}\n`,
|
|
592
|
+
);
|
|
358
593
|
|
|
359
|
-
for (const
|
|
360
|
-
|
|
594
|
+
for (const [fileName, content] of Object.entries(workflowTemplates)) {
|
|
595
|
+
await writeFileIfMissing(getRuntimeWritePath("skills", fileName), content);
|
|
361
596
|
}
|
|
362
597
|
|
|
598
|
+
await writeFileIfMissing(
|
|
599
|
+
path.join(getRepoRoot(), "mcp", "servers.json"),
|
|
600
|
+
`${JSON.stringify({ schemaVersion: "0.1.0", servers: [] }, null, 2)}\n`,
|
|
601
|
+
);
|
|
602
|
+
await writeFileIfMissing(
|
|
603
|
+
path.join(getRepoRoot(), "mcp", "collections.json"),
|
|
604
|
+
`${JSON.stringify({ schemaVersion: "0.1.0", collections: {} }, null, 2)}\n`,
|
|
605
|
+
);
|
|
606
|
+
await writeFileIfMissing(
|
|
607
|
+
path.join(getRepoRoot(), "mcp", "fallback.json"),
|
|
608
|
+
`${JSON.stringify(
|
|
609
|
+
{
|
|
610
|
+
schemaVersion: "0.1.0",
|
|
611
|
+
fallback: {
|
|
612
|
+
endpoint: "https://gitmcp.io/docs",
|
|
613
|
+
policy: "Use only when no approved exact endpoint exists.",
|
|
614
|
+
},
|
|
615
|
+
},
|
|
616
|
+
null,
|
|
617
|
+
2,
|
|
618
|
+
)}\n`,
|
|
619
|
+
);
|
|
620
|
+
await writeFileIfMissing(
|
|
621
|
+
getRuntimeWritePath("evidence", "sources.json"),
|
|
622
|
+
`${JSON.stringify(
|
|
623
|
+
{
|
|
624
|
+
schemaVersion: "0.1.0",
|
|
625
|
+
items: [],
|
|
626
|
+
},
|
|
627
|
+
null,
|
|
628
|
+
2,
|
|
629
|
+
)}\n`,
|
|
630
|
+
);
|
|
631
|
+
await writeFileIfMissing(
|
|
632
|
+
getRuntimeWritePath("evidence", "audits.json"),
|
|
633
|
+
`${JSON.stringify(
|
|
634
|
+
{
|
|
635
|
+
schemaVersion: "0.1.0",
|
|
636
|
+
items: [],
|
|
637
|
+
},
|
|
638
|
+
null,
|
|
639
|
+
2,
|
|
640
|
+
)}\n`,
|
|
641
|
+
);
|
|
642
|
+
await writeFileIfMissing(
|
|
643
|
+
getRuntimeWritePath("evidence", "outcomes.json"),
|
|
644
|
+
`${JSON.stringify(
|
|
645
|
+
{
|
|
646
|
+
schemaVersion: "0.1.0",
|
|
647
|
+
items: [],
|
|
648
|
+
},
|
|
649
|
+
null,
|
|
650
|
+
2,
|
|
651
|
+
)}\n`,
|
|
652
|
+
);
|
|
653
|
+
await writeFileIfMissing(
|
|
654
|
+
getRuntimeWritePath("evidence", "cves.json"),
|
|
655
|
+
`${JSON.stringify(
|
|
656
|
+
{
|
|
657
|
+
schemaVersion: "0.1.0",
|
|
658
|
+
items: [],
|
|
659
|
+
},
|
|
660
|
+
null,
|
|
661
|
+
2,
|
|
662
|
+
)}\n`,
|
|
663
|
+
);
|
|
664
|
+
|
|
665
|
+
await writeFileIfMissing(
|
|
666
|
+
path.join(getRepoRoot(), "docs", "onboarding.md"),
|
|
667
|
+
"# Onboarding\n\nMeta-Architect initializes the core scaffold, MCP config, and canonical .ma runtime files.\n",
|
|
668
|
+
);
|
|
669
|
+
|
|
363
670
|
return created;
|
|
364
671
|
}
|