@dzhechkov/keysarium 1.5.32 → 1.5.34
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/.dz-manifest.json +66 -42
- package/package.json +1 -1
- package/sbom.json +101 -41
- package/src/commands/doctor.js +71 -111
- package/src/commands/init.js +1 -1
- package/src/commands/list.js +1 -1
- package/src/commands/remove.js +1 -1
- package/src/commands/update.js +1 -1
- package/src/utils.js +99 -11
- package/templates/.claude/skills/edu-site-generator/SKILL.md +2 -2
- package/templates/.claude/skills/explore/SKILL.md +1 -1
- package/templates/.claude/skills/feature-adr/SKILL.md +1 -1
- package/templates/.claude/skills/frontend-design/SKILL.md +1 -1
- package/templates/.claude/skills/goap-research-ed25519/SKILL.md +141 -11
- package/templates/.claude/skills/goap-research-ed25519/scripts/check_report_evidence.py +363 -0
- package/templates/.claude/skills/goap-research-ed25519/scripts/ed25519_verifier.py +297 -4
- package/templates/.claude/skills/goap-research-ed25519/scripts/evidence_fetch.py +277 -0
- package/templates/.claude/skills/goap-research-ed25519/scripts/fixture_legacy_v1_fact.json +21 -0
- package/templates/.claude/skills/goap-research-ed25519/scripts/learning_bridge.py +462 -0
- package/templates/.claude/skills/goap-research-ed25519/scripts/source_tiers.py +170 -0
- package/templates/.claude/skills/goap-research-ed25519/scripts/test_evidence_provenance.py +784 -0
- package/templates/.claude/skills/presentation-storyteller/SKILL.md +1 -1
- package/templates/.claude/skills/problem-solver-enhanced/SKILL.md +1 -1
- package/templates/.claude/skills/reverse-engineering-unicorn/SKILL.md +1 -1
- package/templates/docs/continuous-learning-guide.md +4 -4
- package/templates/docs/feature-adr/01-architecture.md +1 -1
- package/templates/docs/feature-adr/03-deployment-guide.md +2 -2
- package/templates/docs/improvement-directions.md +1 -1
- package/templates/docs/keysarium/01-deployment-guide.md +16 -16
- package/templates/docs/keysarium/02-admin-guide.md +1 -1
- package/templates/docs/keysarium/04-infrastructure-requirements.md +6 -6
- package/templates/docs/keysarium-core/03-deployment-guide.md +5 -5
- package/templates/docs/keysarium-core/04-admin-guide.md +6 -6
- package/templates/lib/platform-templates/opencode.md +1 -1
- package/templates/lib/worker-templates/brain-export.md +1 -1
package/src/commands/doctor.js
CHANGED
|
@@ -5,7 +5,7 @@ const path = require('path');
|
|
|
5
5
|
const {
|
|
6
6
|
green, red, yellow, cyan, bold, dim,
|
|
7
7
|
info, success, warn, error: logError,
|
|
8
|
-
fileExists, readJSON, readManifest,
|
|
8
|
+
fileExists, readJSON, readManifest, getTemplateFileNames,
|
|
9
9
|
MANIFEST_FILE,
|
|
10
10
|
} = require('../utils');
|
|
11
11
|
|
|
@@ -60,7 +60,7 @@ function checkFilesExist(manifest, targetDir) {
|
|
|
60
60
|
return {
|
|
61
61
|
passed: false,
|
|
62
62
|
detail: `${missing.length} file(s) missing: ${missing.slice(0, 5).join(', ')}${missing.length > 5 ? '...' : ''}`,
|
|
63
|
-
fix: `Run ${cyan('@dzhechkov/keysarium update')} to restore missing files.`,
|
|
63
|
+
fix: `Run ${cyan('npx @dzhechkov/keysarium update')} to restore missing files.`,
|
|
64
64
|
};
|
|
65
65
|
});
|
|
66
66
|
}
|
|
@@ -76,7 +76,7 @@ function checkClaudeMd(targetDir) {
|
|
|
76
76
|
return {
|
|
77
77
|
passed: false,
|
|
78
78
|
detail: 'CLAUDE.md not found',
|
|
79
|
-
fix: `Run ${cyan('@dzhechkov/keysarium update')} or ${cyan('@dzhechkov/keysarium init --force')} to restore.`,
|
|
79
|
+
fix: `Run ${cyan('npx @dzhechkov/keysarium update')} or ${cyan('npx @dzhechkov/keysarium init --force')} to restore.`,
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
82
|
|
|
@@ -117,7 +117,7 @@ function checkSkillsComplete(targetDir) {
|
|
|
117
117
|
return {
|
|
118
118
|
passed: false,
|
|
119
119
|
detail: '.claude/skills/ directory not found',
|
|
120
|
-
fix: `Run ${cyan('@dzhechkov/keysarium update')} to restore skills.`,
|
|
120
|
+
fix: `Run ${cyan('npx @dzhechkov/keysarium update')} to restore skills.`,
|
|
121
121
|
};
|
|
122
122
|
}
|
|
123
123
|
|
|
@@ -165,141 +165,100 @@ function checkSkillsComplete(targetDir) {
|
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
/**
|
|
168
|
-
*
|
|
168
|
+
* Shared body for the "every shipped <thing>.md is installed" checks.
|
|
169
|
+
*
|
|
170
|
+
* The expected list is DERIVED from the package's own templates/ tree, never hardcoded —
|
|
171
|
+
* a command or rule added to templates/ is named-checked on the next run with no edit here.
|
|
172
|
+
* (Regression this guards: the lists used to be frozen at a legacy 11-command / 7-rule
|
|
173
|
+
* subset, so `doctor` reported "All 11 command files present" on a 19-command install and
|
|
174
|
+
* newer files like feature-adr.md / dream.md / reward-learning.md were never named.)
|
|
169
175
|
*/
|
|
170
|
-
function
|
|
171
|
-
|
|
172
|
-
const commandsDir = path.join(targetDir, '.claude', 'commands');
|
|
173
|
-
const expectedCommands = [
|
|
174
|
-
'casarium.md',
|
|
175
|
-
'new-research.md',
|
|
176
|
-
'parallel-research.md',
|
|
177
|
-
'discovery.md',
|
|
178
|
-
'explore-case.md',
|
|
179
|
-
'research.md',
|
|
180
|
-
'cjm-prototype.md',
|
|
181
|
-
'solve.md',
|
|
182
|
-
'architecture-phase.md',
|
|
183
|
-
'presentation.md',
|
|
184
|
-
'harvest.md',
|
|
185
|
-
];
|
|
186
|
-
|
|
187
|
-
if (!fileExists(commandsDir)) {
|
|
188
|
-
return {
|
|
189
|
-
passed: false,
|
|
190
|
-
detail: '.claude/commands/ directory not found',
|
|
191
|
-
fix: `Run ${cyan('@dzhechkov/keysarium update')} to restore commands.`,
|
|
192
|
-
};
|
|
193
|
-
}
|
|
176
|
+
function checkComponentFilesPresent(targetDir, opts) {
|
|
177
|
+
const { checkName, componentKey, dirParts, noun } = opts;
|
|
194
178
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
}
|
|
179
|
+
return check(checkName, () => {
|
|
180
|
+
const dir = path.join(targetDir, ...dirParts);
|
|
181
|
+
const relDir = dirParts.join('/') + '/';
|
|
182
|
+
const expected = getTemplateFileNames(componentKey);
|
|
201
183
|
|
|
202
|
-
if (
|
|
184
|
+
if (expected.length === 0) {
|
|
203
185
|
return {
|
|
204
|
-
passed:
|
|
205
|
-
detail: `
|
|
186
|
+
passed: false,
|
|
187
|
+
detail: `Cannot read the shipped ${noun} list from the package templates/ tree`,
|
|
188
|
+
fix: 'Reinstall the package: the templates/ directory is missing or unreadable.',
|
|
206
189
|
};
|
|
207
190
|
}
|
|
208
191
|
|
|
209
|
-
|
|
210
|
-
passed: false,
|
|
211
|
-
detail: `Missing ${missing.length} command(s): ${missing.join(', ')}`,
|
|
212
|
-
fix: `Run ${cyan('@dzhechkov/keysarium update')} to restore missing commands.`,
|
|
213
|
-
};
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Check 5: All 7 rule .md files are present.
|
|
219
|
-
*/
|
|
220
|
-
function checkRulesPresent(targetDir) {
|
|
221
|
-
return check('Rules present', () => {
|
|
222
|
-
const rulesDir = path.join(targetDir, '.claude', 'rules');
|
|
223
|
-
const expectedRules = [
|
|
224
|
-
'agent-swarm.md',
|
|
225
|
-
'anti-patterns.md',
|
|
226
|
-
'checkpoint-protocol.md',
|
|
227
|
-
'domain-specific.md',
|
|
228
|
-
'file-conventions.md',
|
|
229
|
-
'modular-reuse.md',
|
|
230
|
-
'research-quality.md',
|
|
231
|
-
];
|
|
232
|
-
|
|
233
|
-
if (!fileExists(rulesDir)) {
|
|
192
|
+
if (!fileExists(dir)) {
|
|
234
193
|
return {
|
|
235
194
|
passed: false,
|
|
236
|
-
detail:
|
|
237
|
-
fix: `Run ${cyan('@dzhechkov/keysarium update')} to restore
|
|
195
|
+
detail: `${relDir} directory not found`,
|
|
196
|
+
fix: `Run ${cyan('npx @dzhechkov/keysarium update')} to restore ${noun}s.`,
|
|
238
197
|
};
|
|
239
198
|
}
|
|
240
199
|
|
|
241
|
-
const missing =
|
|
242
|
-
for (const rule of expectedRules) {
|
|
243
|
-
if (!fileExists(path.join(rulesDir, rule))) {
|
|
244
|
-
missing.push(rule);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
200
|
+
const missing = expected.filter((name) => !fileExists(path.join(dir, name)));
|
|
247
201
|
|
|
248
202
|
if (missing.length === 0) {
|
|
249
203
|
return {
|
|
250
204
|
passed: true,
|
|
251
|
-
detail: `All ${
|
|
205
|
+
detail: `All ${expected.length} ${noun} files present`,
|
|
252
206
|
};
|
|
253
207
|
}
|
|
254
208
|
|
|
255
209
|
return {
|
|
256
210
|
passed: false,
|
|
257
|
-
detail: `Missing ${missing.length}
|
|
258
|
-
fix: `Run ${cyan('@dzhechkov/keysarium update')} to restore missing
|
|
211
|
+
detail: `Missing ${missing.length}/${expected.length} ${noun}(s): ${missing.slice(0, 5).join(', ')}${missing.length > 5 ? '...' : ''}`,
|
|
212
|
+
fix: `Run ${cyan('npx @dzhechkov/keysarium update')} to restore missing ${noun}s.`,
|
|
259
213
|
};
|
|
260
214
|
});
|
|
261
215
|
}
|
|
262
216
|
|
|
263
217
|
/**
|
|
264
|
-
* Check
|
|
218
|
+
* Check 4: every shipped command .md file is present.
|
|
265
219
|
*/
|
|
266
|
-
function
|
|
267
|
-
return
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
fix: `Run ${cyan('@dzhechkov/keysarium update')} to restore agents.`,
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
let entries;
|
|
279
|
-
try {
|
|
280
|
-
entries = fs.readdirSync(agentsDir);
|
|
281
|
-
} catch {
|
|
282
|
-
return {
|
|
283
|
-
passed: false,
|
|
284
|
-
detail: 'Cannot read .claude/agents/ directory',
|
|
285
|
-
fix: 'Check directory permissions.',
|
|
286
|
-
};
|
|
287
|
-
}
|
|
220
|
+
function checkCommandsPresent(targetDir) {
|
|
221
|
+
return checkComponentFilesPresent(targetDir, {
|
|
222
|
+
checkName: 'Commands present',
|
|
223
|
+
componentKey: 'commands',
|
|
224
|
+
dirParts: ['.claude', 'commands'],
|
|
225
|
+
noun: 'command',
|
|
226
|
+
});
|
|
227
|
+
}
|
|
288
228
|
|
|
289
|
-
|
|
229
|
+
/**
|
|
230
|
+
* Check 5: every shipped rule .md file is present.
|
|
231
|
+
*/
|
|
232
|
+
function checkRulesPresent(targetDir) {
|
|
233
|
+
return checkComponentFilesPresent(targetDir, {
|
|
234
|
+
checkName: 'Rules present',
|
|
235
|
+
componentKey: 'rules',
|
|
236
|
+
dirParts: ['.claude', 'rules'],
|
|
237
|
+
noun: 'rule',
|
|
238
|
+
});
|
|
239
|
+
}
|
|
290
240
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
241
|
+
/**
|
|
242
|
+
* Check 5b: every shipped governance shard is present.
|
|
243
|
+
*/
|
|
244
|
+
function checkShardsPresent(targetDir) {
|
|
245
|
+
return checkComponentFilesPresent(targetDir, {
|
|
246
|
+
checkName: 'Shards present',
|
|
247
|
+
componentKey: 'shards',
|
|
248
|
+
dirParts: ['.claude', 'shards'],
|
|
249
|
+
noun: 'shard',
|
|
250
|
+
});
|
|
251
|
+
}
|
|
297
252
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
253
|
+
/**
|
|
254
|
+
* Check 6: every shipped agent template .md file is present.
|
|
255
|
+
*/
|
|
256
|
+
function checkAgentsPresent(targetDir) {
|
|
257
|
+
return checkComponentFilesPresent(targetDir, {
|
|
258
|
+
checkName: 'Agents present',
|
|
259
|
+
componentKey: 'agents',
|
|
260
|
+
dirParts: ['.claude', 'agents'],
|
|
261
|
+
noun: 'agent',
|
|
303
262
|
});
|
|
304
263
|
}
|
|
305
264
|
|
|
@@ -314,7 +273,7 @@ function checkSettingsValid(targetDir) {
|
|
|
314
273
|
return {
|
|
315
274
|
passed: false,
|
|
316
275
|
detail: '.claude/settings.json not found',
|
|
317
|
-
fix: `Run ${cyan('@dzhechkov/keysarium update')} to restore settings.`,
|
|
276
|
+
fix: `Run ${cyan('npx @dzhechkov/keysarium update')} to restore settings.`,
|
|
318
277
|
};
|
|
319
278
|
}
|
|
320
279
|
|
|
@@ -390,7 +349,7 @@ async function run(options) {
|
|
|
390
349
|
// ── a) Check manifest exists ───────────────────────────────────────────
|
|
391
350
|
if (!fileExists(manifestPath)) {
|
|
392
351
|
logError('Keysarium is not installed in this directory.');
|
|
393
|
-
info(`Run ${cyan('@dzhechkov/keysarium init')} to install.`);
|
|
352
|
+
info(`Run ${cyan('npx @dzhechkov/keysarium init')} to install.`);
|
|
394
353
|
process.exit(1);
|
|
395
354
|
}
|
|
396
355
|
|
|
@@ -411,6 +370,7 @@ async function run(options) {
|
|
|
411
370
|
checkSkillsComplete(targetDir),
|
|
412
371
|
checkCommandsPresent(targetDir),
|
|
413
372
|
checkRulesPresent(targetDir),
|
|
373
|
+
checkShardsPresent(targetDir),
|
|
414
374
|
checkAgentsPresent(targetDir),
|
|
415
375
|
checkSettingsValid(targetDir),
|
|
416
376
|
checkResearchDir(targetDir),
|
package/src/commands/init.js
CHANGED
|
@@ -90,7 +90,7 @@ async function run(options) {
|
|
|
90
90
|
if (fileExists(manifestPath)) {
|
|
91
91
|
if (!force) {
|
|
92
92
|
warn('Keysarium is already installed in this directory.');
|
|
93
|
-
info(`Run ${cyan('@dzhechkov/keysarium update')} to update, or use ${yellow('--force')} to overwrite.`);
|
|
93
|
+
info(`Run ${cyan('npx @dzhechkov/keysarium update')} to update, or use ${yellow('--force')} to overwrite.`);
|
|
94
94
|
process.exit(1);
|
|
95
95
|
}
|
|
96
96
|
warn('Existing installation found — overwriting (--force).');
|
package/src/commands/list.js
CHANGED
|
@@ -65,7 +65,7 @@ async function run(options) {
|
|
|
65
65
|
// ── a) Read manifest ───────────────────────────────────────────────────
|
|
66
66
|
if (!fileExists(manifestPath)) {
|
|
67
67
|
warn('Keysarium is not installed in this directory.');
|
|
68
|
-
info(`Run ${cyan('@dzhechkov/keysarium init')} to install.`);
|
|
68
|
+
info(`Run ${cyan('npx @dzhechkov/keysarium init')} to install.`);
|
|
69
69
|
process.exit(1);
|
|
70
70
|
}
|
|
71
71
|
|
package/src/commands/remove.js
CHANGED
|
@@ -187,7 +187,7 @@ async function run(options) {
|
|
|
187
187
|
console.log(` ${dim('-')} ${skippedCount} file(s) already missing (skipped)`);
|
|
188
188
|
}
|
|
189
189
|
console.log('');
|
|
190
|
-
info(`To reinstall, run: ${cyan('@dzhechkov/keysarium init')}`);
|
|
190
|
+
info(`To reinstall, run: ${cyan('npx @dzhechkov/keysarium init')}`);
|
|
191
191
|
console.log('');
|
|
192
192
|
|
|
193
193
|
process.exit(0);
|
package/src/commands/update.js
CHANGED
|
@@ -30,7 +30,7 @@ async function run(options) {
|
|
|
30
30
|
// ── a) Read existing manifest ───────────────────────────────────────────
|
|
31
31
|
if (!fileExists(manifestPath)) {
|
|
32
32
|
logError('Keysarium is not installed in this directory.');
|
|
33
|
-
info(`Run ${cyan('@dzhechkov/keysarium init')} to install.`);
|
|
33
|
+
info(`Run ${cyan('npx @dzhechkov/keysarium init')} to install.`);
|
|
34
34
|
process.exit(1);
|
|
35
35
|
}
|
|
36
36
|
|
package/src/utils.js
CHANGED
|
@@ -250,19 +250,105 @@ function getTemplatesDir() {
|
|
|
250
250
|
// Component definitions
|
|
251
251
|
// ===========================================================================
|
|
252
252
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
253
|
+
/**
|
|
254
|
+
* Count the units a component contributes, by inspecting the real templates/ tree.
|
|
255
|
+
*
|
|
256
|
+
* `countMode` decides what a "unit" is:
|
|
257
|
+
* 'dirs' — immediate subdirectories (one skill pack = one directory)
|
|
258
|
+
* 'files' — every file, recursively (lib/, docs/ ship nested files)
|
|
259
|
+
* 'md' — immediate *.md files (one command / rule / shard / agent = one file)
|
|
260
|
+
*
|
|
261
|
+
* Returns null when the count cannot be determined (missing dir, unreadable),
|
|
262
|
+
* so callers can degrade to a bare label instead of printing a wrong number.
|
|
263
|
+
*/
|
|
264
|
+
function countTemplateUnits(comp) {
|
|
265
|
+
if (comp.isFile) return null;
|
|
266
|
+
|
|
267
|
+
const srcPath = path.join(getTemplatesDir(), comp.src);
|
|
268
|
+
|
|
269
|
+
try {
|
|
270
|
+
if (!fs.statSync(srcPath).isDirectory()) return null;
|
|
271
|
+
} catch {
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
try {
|
|
276
|
+
if (comp.countMode === 'files') {
|
|
277
|
+
return getRelativePaths(srcPath).length;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const entries = fs.readdirSync(srcPath, { withFileTypes: true });
|
|
281
|
+
|
|
282
|
+
if (comp.countMode === 'dirs') {
|
|
283
|
+
return entries.filter((e) => e.isDirectory()).length;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// default: 'md'
|
|
287
|
+
return entries.filter((e) => e.isFile() && e.name.endsWith('.md')).length;
|
|
288
|
+
} catch {
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Component definitions.
|
|
295
|
+
*
|
|
296
|
+
* IMPORTANT: `label` is a COMPUTED getter — the parenthetical count is read from the
|
|
297
|
+
* shipped templates/ tree at access time, never hardcoded. Adding a command / rule /
|
|
298
|
+
* skill to templates/ changes what `init`, `init --dry-run` and `list` print, with no
|
|
299
|
+
* source edit. (Regression this guards: the labels used to be frozen strings reading
|
|
300
|
+
* "8 skill packs / 13 slash commands / 10 rules / 7 shards / 4 modules" long after the
|
|
301
|
+
* tree had grown past all five numbers.)
|
|
302
|
+
*/
|
|
303
|
+
const COMPONENT_SPECS = {
|
|
304
|
+
skills: { src: '.claude/skills', name: 'Skills', unit: 'skill packs', countMode: 'dirs', group: 'core' },
|
|
305
|
+
commands: { src: '.claude/commands', name: 'Commands', unit: 'slash commands', countMode: 'md', group: 'core' },
|
|
306
|
+
rules: { src: '.claude/rules', name: 'Rules', unit: 'auto-loaded rules', countMode: 'md', group: 'core' },
|
|
307
|
+
shards: { src: '.claude/shards', name: 'Shards', unit: 'context shards', countMode: 'md', group: 'core' },
|
|
308
|
+
agents: { src: '.claude/agents', name: 'Agent templates', unit: 'swarm configs', countMode: 'md', group: 'core' },
|
|
309
|
+
hooks: { src: '.claude/settings.json', name: 'Hooks configuration', group: 'core', isFile: true },
|
|
310
|
+
lib: { src: 'lib', name: 'Library modules', unit: 'modules', countMode: 'files', group: 'extended' },
|
|
311
|
+
docs: { src: 'docs', name: 'Documentation', unit: 'guides', countMode: 'files', group: 'docs' },
|
|
312
|
+
claude_md: { src: 'CLAUDE.md', name: 'Master instructions', group: 'core', isFile: true },
|
|
313
|
+
harvest: { src: 'TOOLKIT_HARVEST.md', name: 'Knowledge harvest tracker', group: 'core', isFile: true },
|
|
264
314
|
};
|
|
265
315
|
|
|
316
|
+
/**
|
|
317
|
+
* The shipped `*.md` filenames for a directory component, read from templates/.
|
|
318
|
+
*
|
|
319
|
+
* This is the single source of truth for "what SHOULD be installed" — `doctor` derives its
|
|
320
|
+
* named checks from it, so a new command/rule/shard is named-checked the moment it lands in
|
|
321
|
+
* templates/, with no second list to keep in sync. Returns [] when templates/ is unreadable.
|
|
322
|
+
*/
|
|
323
|
+
function getTemplateFileNames(componentKey) {
|
|
324
|
+
const comp = COMPONENT_SPECS[componentKey];
|
|
325
|
+
if (!comp || comp.isFile) return [];
|
|
326
|
+
|
|
327
|
+
try {
|
|
328
|
+
return fs
|
|
329
|
+
.readdirSync(path.join(getTemplatesDir(), comp.src), { withFileTypes: true })
|
|
330
|
+
.filter((e) => e.isFile() && e.name.endsWith('.md'))
|
|
331
|
+
.map((e) => e.name)
|
|
332
|
+
.sort();
|
|
333
|
+
} catch {
|
|
334
|
+
return [];
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const COMPONENTS = {};
|
|
339
|
+
for (const [key, spec] of Object.entries(COMPONENT_SPECS)) {
|
|
340
|
+
const comp = Object.assign({}, spec);
|
|
341
|
+
Object.defineProperty(comp, 'label', {
|
|
342
|
+
enumerable: true,
|
|
343
|
+
get() {
|
|
344
|
+
const n = countTemplateUnits(this);
|
|
345
|
+
if (n === null || !this.unit) return this.name;
|
|
346
|
+
return `${this.name} (${n} ${this.unit})`;
|
|
347
|
+
},
|
|
348
|
+
});
|
|
349
|
+
COMPONENTS[key] = comp;
|
|
350
|
+
}
|
|
351
|
+
|
|
266
352
|
// ===========================================================================
|
|
267
353
|
// Exports
|
|
268
354
|
// ===========================================================================
|
|
@@ -306,4 +392,6 @@ module.exports = {
|
|
|
306
392
|
|
|
307
393
|
// Components
|
|
308
394
|
COMPONENTS,
|
|
395
|
+
countTemplateUnits,
|
|
396
|
+
getTemplateFileNames,
|
|
309
397
|
};
|
|
@@ -10,7 +10,7 @@ trust_tier: 1
|
|
|
10
10
|
|
|
11
11
|
# edu-site-generator — Gamified Educational Site Generator
|
|
12
12
|
|
|
13
|
-
<!-- Trust Tier: 1 — Structured | Path to Tier 2: run a BTO evaluation (
|
|
13
|
+
<!-- Trust Tier: 1 — Structured | Path to Tier 2: run a BTO evaluation (see the skills-bto package) -->
|
|
14
14
|
|
|
15
15
|
> Generate a complete gamified educational SPA from documentation/content, optimized for GitHub Pages deployment.
|
|
16
16
|
|
|
@@ -21,7 +21,7 @@ Trigger on:
|
|
|
21
21
|
- "create learning site [topic]"
|
|
22
22
|
- "build educational app [topic]"
|
|
23
23
|
- "gamified site from documentation"
|
|
24
|
-
- `/edu-site [topic or docs path]`
|
|
24
|
+
- `/edu-site-generator [topic or docs path]`
|
|
25
25
|
|
|
26
26
|
## Overview
|
|
27
27
|
|
|
@@ -10,7 +10,7 @@ description: >
|
|
|
10
10
|
provide solutions until task is fully explored.
|
|
11
11
|
trust_tier: 1
|
|
12
12
|
trust_tier_label: "Structured"
|
|
13
|
-
trust_tier_path: "Run a BTO evaluation
|
|
13
|
+
trust_tier_path: "Run a BTO evaluation (see the skills-bto package) to promote to Tier 2"
|
|
14
14
|
---
|
|
15
15
|
|
|
16
16
|
# Explore: Adaptive Task Clarification
|
|
@@ -11,7 +11,7 @@ description: >
|
|
|
11
11
|
"implement feature", "/feature-adr".
|
|
12
12
|
trust_tier: 0
|
|
13
13
|
trust_tier_label: "Advisory"
|
|
14
|
-
trust_tier_path: "Run a BTO evaluation
|
|
14
|
+
trust_tier_path: "Run a BTO evaluation (see the skills-bto package) to promote to Tier 1"
|
|
15
15
|
agentic_qe_version: "7.5.1"
|
|
16
16
|
agentic_qe_source: "https://github.com/proffesor-for-testing/agentic-qe"
|
|
17
17
|
agentic_qe_skills_core: 9
|
|
@@ -4,7 +4,7 @@ description: Create distinctive, production-grade frontend interfaces with high
|
|
|
4
4
|
license: Complete terms in LICENSE.txt
|
|
5
5
|
trust_tier: 0
|
|
6
6
|
trust_tier_label: "Advisory"
|
|
7
|
-
trust_tier_path: "Add references/ directory and run a BTO evaluation
|
|
7
|
+
trust_tier_path: "Add references/ directory and run a BTO evaluation (see the skills-bto package) to promote to Tier 1"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
This skill guides creation of distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.
|