macca-method 2.1.1 → 2.1.3
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/macca-lock.json +1 -1
- package/.agents/skills/_shared/references/brainstorm-session.md +5 -5
- package/.agents/skills/_shared/references/invocation-policy.md +20 -20
- package/.agents/skills/_shared/references/output-ownership.md +11 -11
- package/.agents/skills/_shared/references/scope-rules.md +1 -1
- package/.agents/skills/_shared/references/skill-catalog.md +20 -20
- package/.agents/skills/_shared/scripts/validate-skills.py +37 -15
- package/.agents/skills/add-feature/SKILL.md +9 -3
- package/.agents/skills/antislop-copywriting/SKILL.md +372 -0
- package/.agents/skills/brainstorm-api/SKILL.md +28 -16
- package/.agents/skills/brainstorm-api/assets/api.template.md +35 -15
- package/.agents/skills/brainstorm-architecture/SKILL.md +35 -15
- package/.agents/skills/brainstorm-architecture/assets/architecture.template.md +44 -25
- package/.agents/skills/brainstorm-prd/SKILL.md +47 -17
- package/.agents/skills/brainstorm-prd/assets/PRD.template.md +47 -23
- package/.agents/skills/brainstorm-rules/SKILL.md +36 -19
- package/.agents/skills/brainstorm-rules/assets/rules.template.md +32 -18
- package/.agents/skills/brainstorm-schema/SKILL.md +18 -8
- package/.agents/skills/brainstorm-schema/assets/schema.template.md +25 -10
- package/.agents/skills/brainstorm-styleguide/SKILL.md +37 -19
- package/.agents/skills/brainstorm-styleguide/assets/StyleGuide.template.md +78 -60
- package/.agents/skills/brainstorm-task/SKILL.md +27 -14
- package/.agents/skills/brainstorm-task/assets/Task.template.md +29 -18
- package/.agents/skills/bug-fix/SKILL.md +25 -1
- package/.agents/skills/code-review/SKILL.md +7 -7
- package/.agents/skills/code-review/references/review-checklist.md +21 -10
- package/.agents/skills/developer/SKILL.md +8 -0
- package/.agents/skills/developer/references/execute-task.md +13 -7
- package/.agents/skills/help/SKILL.md +32 -20
- package/.agents/skills/meet/SKILL.md +9 -4
- package/.agents/skills/quick-dev/SKILL.md +27 -22
- package/.agents/skills/release-readiness/SKILL.md +17 -13
- package/.agents/skills/skill-creator/LICENSE.txt +202 -0
- package/.agents/skills/skill-creator/SKILL.md +485 -0
- package/.agents/skills/skill-creator/agents/analyzer.md +274 -0
- package/.agents/skills/skill-creator/agents/comparator.md +202 -0
- package/.agents/skills/skill-creator/agents/grader.md +223 -0
- package/.agents/skills/skill-creator/assets/eval_review.html +146 -0
- package/.agents/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/.agents/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/.agents/skills/skill-creator/references/schemas.md +441 -0
- package/.agents/skills/skill-creator/scripts/__init__.py +0 -0
- package/.agents/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/.agents/skills/skill-creator/scripts/generate_report.py +326 -0
- package/.agents/skills/skill-creator/scripts/improve_description.py +247 -0
- package/.agents/skills/skill-creator/scripts/package_skill.py +136 -0
- package/.agents/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/.agents/skills/skill-creator/scripts/run_eval.py +310 -0
- package/.agents/skills/skill-creator/scripts/run_loop.py +328 -0
- package/.agents/skills/skill-creator/scripts/utils.py +47 -0
- package/.agents/skills/spec-audit/SKILL.md +28 -1
- package/.agents/skills/spec-compliance/SKILL.md +31 -18
- package/.agents/skills/spec-init/SKILL.md +29 -17
- package/README.md +158 -122
- package/bin/macca-method.js +1425 -1081
- package/package.json +40 -40
- package/scripts/run-skill-validator.js +27 -9
- package/scripts/test-install.js +600 -357
- package/scripts/test-upgrade-legacy.js +119 -100
- package/scripts/validate-skill-behavior.js +175 -64
|
@@ -8,136 +8,155 @@ const path = require("node:path");
|
|
|
8
8
|
const { execFileSync } = require("node:child_process");
|
|
9
9
|
|
|
10
10
|
const rootDir = path.resolve(__dirname, "..");
|
|
11
|
-
const temporaryRoot = fs.mkdtempSync(
|
|
11
|
+
const temporaryRoot = fs.mkdtempSync(
|
|
12
|
+
path.join(resolveTempRoot(), "macca-legacy-upgrade-"),
|
|
13
|
+
);
|
|
12
14
|
const projectDir = path.join(temporaryRoot, "project");
|
|
13
15
|
const obsoleteMeetingName = Buffer.from("cmFwYXQ=", "base64").toString("utf8");
|
|
14
16
|
|
|
15
17
|
function commandName(base) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
if (process.platform !== "win32") {
|
|
19
|
+
return base;
|
|
20
|
+
}
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
return base === "npm" || base === "npx" ? `${base}.cmd` : base;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
function resolveTempRoot() {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
const tempRoot = os.tmpdir();
|
|
27
|
+
try {
|
|
28
|
+
return fs.realpathSync(tempRoot);
|
|
29
|
+
} catch {
|
|
30
|
+
return tempRoot;
|
|
31
|
+
}
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
function captureNpm(args, options = {}) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
const npmExecPath = process.env.npm_execpath;
|
|
36
|
+
if (npmExecPath && /\.c?js$/i.test(npmExecPath)) {
|
|
37
|
+
return capture(process.execPath, [npmExecPath, ...args], options);
|
|
38
|
+
}
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
return capture(commandName("npm"), args, options);
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
function runNpm(args, options = {}) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
const npmExecPath = process.env.npm_execpath;
|
|
45
|
+
if (npmExecPath && /\.c?js$/i.test(npmExecPath)) {
|
|
46
|
+
run(process.execPath, [npmExecPath, ...args], options);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
run(commandName("npm"), args, options);
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
function run(command, args, options = {}) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
return execFileSync(command, args, {
|
|
55
|
+
cwd: rootDir,
|
|
56
|
+
stdio: "inherit",
|
|
57
|
+
...options,
|
|
58
|
+
});
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
function capture(command, args, options = {}) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
return execFileSync(command, args, {
|
|
63
|
+
cwd: rootDir,
|
|
64
|
+
encoding: "utf8",
|
|
65
|
+
...options,
|
|
66
|
+
});
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
function assertExists(targetPath) {
|
|
68
|
-
|
|
70
|
+
if (!fs.existsSync(targetPath))
|
|
71
|
+
throw new Error(`Missing expected path: ${targetPath}`);
|
|
69
72
|
}
|
|
70
73
|
|
|
71
74
|
function assertMissing(targetPath) {
|
|
72
|
-
|
|
75
|
+
if (fs.existsSync(targetPath))
|
|
76
|
+
throw new Error(`Obsolete path was not removed: ${targetPath}`);
|
|
73
77
|
}
|
|
74
78
|
|
|
75
79
|
try {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
80
|
+
fs.mkdirSync(projectDir, { recursive: true });
|
|
81
|
+
|
|
82
|
+
const legacyPackOutput = captureNpm([
|
|
83
|
+
"pack",
|
|
84
|
+
"macca-method@1.1.0",
|
|
85
|
+
"--json",
|
|
86
|
+
"--pack-destination",
|
|
87
|
+
temporaryRoot,
|
|
88
|
+
]);
|
|
89
|
+
const legacyPackageList = JSON.parse(legacyPackOutput);
|
|
90
|
+
const legacyPackageSpec = path.join(
|
|
91
|
+
temporaryRoot,
|
|
92
|
+
legacyPackageList[0].filename,
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
runNpm([
|
|
96
|
+
"exec",
|
|
97
|
+
"--yes",
|
|
98
|
+
"--package",
|
|
99
|
+
legacyPackageSpec,
|
|
100
|
+
"--",
|
|
101
|
+
"macca-method",
|
|
102
|
+
"install",
|
|
103
|
+
"--yes",
|
|
104
|
+
"--tool",
|
|
105
|
+
"opencode",
|
|
106
|
+
"--directory",
|
|
107
|
+
projectDir,
|
|
108
|
+
"--name",
|
|
109
|
+
"Legacy User",
|
|
110
|
+
"--project",
|
|
111
|
+
"Legacy Project",
|
|
112
|
+
"--communication-language",
|
|
113
|
+
"English",
|
|
114
|
+
"--document-language",
|
|
115
|
+
"English",
|
|
116
|
+
]);
|
|
117
|
+
|
|
118
|
+
const legacyRoot = path.join(projectDir, ".opencode", "skill");
|
|
119
|
+
assertExists(path.join(legacyRoot, obsoleteMeetingName, "SKILL.md"));
|
|
120
|
+
|
|
121
|
+
const packOutput = captureNpm([
|
|
122
|
+
"pack",
|
|
123
|
+
"--json",
|
|
124
|
+
"--pack-destination",
|
|
125
|
+
temporaryRoot,
|
|
126
|
+
]);
|
|
127
|
+
const packageList = JSON.parse(packOutput);
|
|
128
|
+
const packageSpec = path.join(temporaryRoot, packageList[0].filename);
|
|
129
|
+
|
|
130
|
+
runNpm([
|
|
131
|
+
"exec",
|
|
132
|
+
"--yes",
|
|
133
|
+
"--package",
|
|
134
|
+
packageSpec,
|
|
135
|
+
"--",
|
|
136
|
+
"macca-method",
|
|
137
|
+
"upgrade",
|
|
138
|
+
"--directory",
|
|
139
|
+
projectDir,
|
|
140
|
+
]);
|
|
141
|
+
|
|
142
|
+
const currentRoot = path.join(projectDir, ".opencode", "skills");
|
|
143
|
+
assertExists(path.join(currentRoot, "meet", "SKILL.md"));
|
|
144
|
+
assertExists(path.join(currentRoot, "release-readiness", "SKILL.md"));
|
|
145
|
+
assertMissing(path.join(legacyRoot, obsoleteMeetingName));
|
|
146
|
+
|
|
147
|
+
const config = JSON.parse(
|
|
148
|
+
fs.readFileSync(
|
|
149
|
+
path.join(projectDir, ".agents", "developer-config.json"),
|
|
150
|
+
"utf8",
|
|
151
|
+
),
|
|
152
|
+
);
|
|
153
|
+
if (config.name !== "Legacy User" || config.project !== "Legacy Project") {
|
|
154
|
+
throw new Error("Legacy upgrade did not preserve developer config");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
process.stdout.write(
|
|
158
|
+
"OK: published 1.1.0 OpenCode installation upgraded safely\n",
|
|
159
|
+
);
|
|
141
160
|
} finally {
|
|
142
|
-
|
|
161
|
+
fs.rmSync(temporaryRoot, { recursive: true, force: true });
|
|
143
162
|
}
|
|
@@ -8,117 +8,228 @@ const path = require("node:path");
|
|
|
8
8
|
const root = path.resolve(__dirname, "..");
|
|
9
9
|
const skillsDir = path.join(root, ".agents", "skills");
|
|
10
10
|
const manifestPath = path.join(root, ".agents", "macca-managed-skills.txt");
|
|
11
|
-
const invocationPath = path.join(
|
|
11
|
+
const invocationPath = path.join(
|
|
12
|
+
skillsDir,
|
|
13
|
+
"_shared",
|
|
14
|
+
"references",
|
|
15
|
+
"invocation-policy.md",
|
|
16
|
+
);
|
|
12
17
|
const issues = [];
|
|
13
18
|
|
|
14
19
|
function read(relativePath) {
|
|
15
|
-
|
|
20
|
+
return fs.readFileSync(path.join(root, relativePath), "utf8");
|
|
16
21
|
}
|
|
17
22
|
|
|
18
23
|
function requireText(file, text, message) {
|
|
19
|
-
|
|
24
|
+
if (!file.includes(text)) issues.push(message);
|
|
20
25
|
}
|
|
21
26
|
|
|
22
|
-
const managed = fs
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
const managed = fs
|
|
28
|
+
.readFileSync(manifestPath, "utf8")
|
|
29
|
+
.split(/\r?\n/)
|
|
30
|
+
.map((line) => line.trim())
|
|
31
|
+
.filter(Boolean);
|
|
32
|
+
|
|
33
|
+
let externalSkills = new Set();
|
|
34
|
+
const lockPath = path.join(root, "skills-lock.json");
|
|
35
|
+
if (fs.existsSync(lockPath)) {
|
|
36
|
+
try {
|
|
37
|
+
const lock = JSON.parse(fs.readFileSync(lockPath, "utf8"));
|
|
38
|
+
if (lock && lock.skills) {
|
|
39
|
+
externalSkills = new Set(Object.keys(lock.skills));
|
|
40
|
+
}
|
|
41
|
+
} catch {}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const publicSkills = fs
|
|
45
|
+
.readdirSync(skillsDir, { withFileTypes: true })
|
|
46
|
+
.filter(
|
|
47
|
+
(entry) =>
|
|
48
|
+
entry.isDirectory() &&
|
|
49
|
+
entry.name !== "_shared" &&
|
|
50
|
+
!externalSkills.has(entry.name) &&
|
|
51
|
+
fs.existsSync(path.join(skillsDir, entry.name, "SKILL.md")),
|
|
52
|
+
)
|
|
53
|
+
.map((entry) => entry.name)
|
|
54
|
+
.sort();
|
|
27
55
|
const manifestSkills = managed.filter((name) => name !== "_shared").sort();
|
|
28
56
|
|
|
29
57
|
if (JSON.stringify(publicSkills) !== JSON.stringify(manifestSkills)) {
|
|
30
|
-
|
|
58
|
+
issues.push(
|
|
59
|
+
`manifest/folder mismatch: folders=${publicSkills.join(",")} manifest=${manifestSkills.join(",")}`,
|
|
60
|
+
);
|
|
31
61
|
}
|
|
32
62
|
|
|
33
63
|
const invocation = fs.readFileSync(invocationPath, "utf8");
|
|
34
64
|
for (const skill of publicSkills) {
|
|
35
|
-
|
|
65
|
+
if (!invocation.includes(`\`${skill}\``))
|
|
66
|
+
issues.push(`invocation policy missing ${skill}`);
|
|
36
67
|
}
|
|
37
68
|
|
|
38
69
|
const meet = read(".agents/skills/meet/SKILL.md");
|
|
39
|
-
requireText(
|
|
40
|
-
|
|
70
|
+
requireText(
|
|
71
|
+
meet,
|
|
72
|
+
"exactly one contribution block",
|
|
73
|
+
"meet must limit each selected persona to one contribution",
|
|
74
|
+
);
|
|
75
|
+
requireText(
|
|
76
|
+
meet,
|
|
77
|
+
"No persona gets a second response",
|
|
78
|
+
"meet must prohibit second persona turns",
|
|
79
|
+
);
|
|
41
80
|
|
|
42
81
|
const quick = read(".agents/skills/quick-dev/SKILL.md");
|
|
43
|
-
requireText(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
82
|
+
requireText(
|
|
83
|
+
quick,
|
|
84
|
+
"active report-first gate",
|
|
85
|
+
"quick-dev must not intercept active report-first approval",
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
for (const skill of [
|
|
89
|
+
"bug-fix",
|
|
90
|
+
"code-review",
|
|
91
|
+
"spec-compliance",
|
|
92
|
+
"spec-audit",
|
|
93
|
+
]) {
|
|
94
|
+
const body = read(`.agents/skills/${skill}/SKILL.md`);
|
|
95
|
+
requireText(
|
|
96
|
+
body,
|
|
97
|
+
"fix-mode.md",
|
|
98
|
+
`${skill} must load the canonical fix-mode contract`,
|
|
99
|
+
);
|
|
48
100
|
}
|
|
49
101
|
|
|
50
102
|
const bugFix = read(".agents/skills/bug-fix/SKILL.md");
|
|
51
|
-
requireText(
|
|
52
|
-
|
|
103
|
+
requireText(
|
|
104
|
+
bugFix,
|
|
105
|
+
"Always wait for explicit user approval before the first code change",
|
|
106
|
+
"bug-fix must require explicit approval before first code change",
|
|
107
|
+
);
|
|
108
|
+
requireText(
|
|
109
|
+
bugFix,
|
|
110
|
+
"Validate Regression Prevention",
|
|
111
|
+
"bug-fix must validate regression-prevention changes before recording the bug",
|
|
112
|
+
);
|
|
53
113
|
|
|
54
114
|
const release = read(".agents/skills/release-readiness/SKILL.md");
|
|
55
|
-
requireText(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
115
|
+
requireText(
|
|
116
|
+
release,
|
|
117
|
+
"report-only",
|
|
118
|
+
"release-readiness must remain report-only",
|
|
119
|
+
);
|
|
120
|
+
requireText(
|
|
121
|
+
release,
|
|
122
|
+
"Never deploys",
|
|
123
|
+
"release-readiness description must prohibit deployment",
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
const brainstormSession = read(
|
|
127
|
+
".agents/skills/_shared/references/brainstorm-session.md",
|
|
128
|
+
);
|
|
59
129
|
for (const depth of ["quick", "standard", "critical"]) {
|
|
60
|
-
|
|
130
|
+
requireText(
|
|
131
|
+
brainstormSession,
|
|
132
|
+
`\`${depth}\``,
|
|
133
|
+
`brainstorm session must define ${depth} discovery depth`,
|
|
134
|
+
);
|
|
61
135
|
}
|
|
62
|
-
requireText(
|
|
136
|
+
requireText(
|
|
137
|
+
brainstormSession,
|
|
138
|
+
"escalate the active depth to `critical`",
|
|
139
|
+
"brainstorm session must escalate saved depth when current evidence is critical",
|
|
140
|
+
);
|
|
63
141
|
|
|
64
142
|
const requiredAssets = [
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
143
|
+
["brainstorm-prd", "PRD.template.md"],
|
|
144
|
+
["brainstorm-architecture", "architecture.template.md"],
|
|
145
|
+
["brainstorm-schema", "schema.template.md"],
|
|
146
|
+
["brainstorm-api", "api.template.md"],
|
|
147
|
+
["brainstorm-styleguide", "StyleGuide.template.md"],
|
|
148
|
+
["brainstorm-rules", "rules.template.md"],
|
|
149
|
+
["brainstorm-task", "Task.template.md"],
|
|
72
150
|
];
|
|
73
151
|
for (const [skill, asset] of requiredAssets) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
152
|
+
const assetPath = path.join(skillsDir, skill, "assets", asset);
|
|
153
|
+
if (!fs.existsSync(assetPath))
|
|
154
|
+
issues.push(`${skill} missing deferred output asset ${asset}`);
|
|
155
|
+
const body = read(`.agents/skills/${skill}/SKILL.md`);
|
|
156
|
+
requireText(body, `assets/${asset}`, `${skill} must defer-load ${asset}`);
|
|
78
157
|
}
|
|
79
158
|
|
|
80
|
-
requireText(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
159
|
+
requireText(
|
|
160
|
+
read(".agents/skills/spec-init/SKILL.md"),
|
|
161
|
+
"## Missing Decisions",
|
|
162
|
+
"spec-init must record missing decisions",
|
|
163
|
+
);
|
|
164
|
+
requireText(
|
|
165
|
+
read(".agents/skills/brainstorm-task/SKILL.md"),
|
|
166
|
+
"Definition of Done",
|
|
167
|
+
"brainstorm-task must derive phase Definition of Done",
|
|
168
|
+
);
|
|
169
|
+
requireText(
|
|
170
|
+
read(".agents/skills/developer/SKILL.md"),
|
|
171
|
+
"references/execute-task.md",
|
|
172
|
+
"developer must use state-based task workflow",
|
|
173
|
+
);
|
|
174
|
+
requireText(
|
|
175
|
+
read(".agents/skills/spec-audit/SKILL.md"),
|
|
176
|
+
"skill-catalog.md",
|
|
177
|
+
"framework audit must use compact skill catalog first",
|
|
178
|
+
);
|
|
84
179
|
|
|
85
180
|
const apiAsset = read(".agents/skills/brainstorm-api/assets/api.template.md");
|
|
86
181
|
for (const marker of [
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
182
|
+
"## REST Section",
|
|
183
|
+
"## GraphQL Section",
|
|
184
|
+
"## RPC / tRPC Section",
|
|
185
|
+
"## Event-Driven Section",
|
|
186
|
+
"Retryable",
|
|
187
|
+
"Client Action",
|
|
93
188
|
]) {
|
|
94
|
-
|
|
189
|
+
requireText(apiAsset, marker, `api template missing ${marker}`);
|
|
95
190
|
}
|
|
96
191
|
|
|
97
|
-
const schemaAsset = read(
|
|
192
|
+
const schemaAsset = read(
|
|
193
|
+
".agents/skills/brainstorm-schema/assets/schema.template.md",
|
|
194
|
+
);
|
|
98
195
|
for (const marker of [
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
196
|
+
"## Relational Section",
|
|
197
|
+
"## Document Section",
|
|
198
|
+
"## Key-Value Section",
|
|
199
|
+
"## Graph Section",
|
|
200
|
+
"## Event Store Section",
|
|
104
201
|
]) {
|
|
105
|
-
|
|
202
|
+
requireText(schemaAsset, marker, `schema template missing ${marker}`);
|
|
106
203
|
}
|
|
107
204
|
|
|
108
|
-
const taskAsset = read(
|
|
109
|
-
|
|
110
|
-
|
|
205
|
+
const taskAsset = read(
|
|
206
|
+
".agents/skills/brainstorm-task/assets/Task.template.md",
|
|
207
|
+
);
|
|
208
|
+
requireText(
|
|
209
|
+
taskAsset,
|
|
210
|
+
"## Phase 2: [Phase Name]",
|
|
211
|
+
"task template missing a second phase example",
|
|
212
|
+
);
|
|
213
|
+
requireText(
|
|
214
|
+
taskAsset,
|
|
215
|
+
"Repeat the `Phase Definition of Done` block",
|
|
216
|
+
"task template must require Definition of Done for every phase",
|
|
217
|
+
);
|
|
111
218
|
|
|
112
219
|
for (const skill of publicSkills) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
220
|
+
const body = read(`.agents/skills/${skill}/SKILL.md`);
|
|
221
|
+
if (body.includes("../_shared/references/runtime-config.md")) {
|
|
222
|
+
issues.push(`${skill} still loads monolithic runtime-config.md`);
|
|
223
|
+
}
|
|
117
224
|
}
|
|
118
225
|
|
|
119
226
|
if (issues.length) {
|
|
120
|
-
|
|
121
|
-
|
|
227
|
+
process.stderr.write(
|
|
228
|
+
`Behavioral contract findings:\n${issues.map((issue) => `- ${issue}`).join("\n")}\n`,
|
|
229
|
+
);
|
|
230
|
+
process.exit(1);
|
|
122
231
|
}
|
|
123
232
|
|
|
124
|
-
process.stdout.write(
|
|
233
|
+
process.stdout.write(
|
|
234
|
+
`OK: ${publicSkills.length} skill behavioral contracts validated\n`,
|
|
235
|
+
);
|