feat: sync shared skills contract and graph-first discipline

This commit is contained in:
“BeeRad”
2026-04-17 20:58:21 +10:00
parent 5f4d1f61c2
commit 7e663abfb0
64 changed files with 1924 additions and 1902 deletions
-1
View File
@@ -15,7 +15,6 @@ export interface DatabaseEvent {
| 'AGENT_UPDATED'
| 'AGENT_DELEGATION_CREATED'
| 'AGENT_DELEGATION_UPDATED'
| 'GUIDE_UPDATED'
| 'SKILL_UPDATED'
| 'QUICK_ADD_COMPLETED'
| 'QUICK_ADD_FAILED'
-13
View File
@@ -1,13 +0,0 @@
export {
listSkills as listGuides,
readSkill as readGuide,
writeSkill as writeGuide,
deleteSkill as deleteGuide,
getUserSkillCount as getUserGuideCount,
getSkillStats as getGuideStats,
} from '@/services/skills/skillService';
export type {
SkillMeta as GuideMeta,
Skill as Guide,
} from '@/services/skills/skillService';
+26 -63
View File
@@ -2,16 +2,9 @@ import fs from 'fs';
import path from 'path';
import os from 'os';
import matter from 'gray-matter';
import type { Skill, SkillMeta } from '@/types/skills';
export interface SkillMeta {
name: string;
description: string;
immutable: boolean;
}
export interface Skill extends SkillMeta {
content: string;
}
export type { Skill, SkillMeta } from '@/types/skills';
const SKILLS_DIR = path.join(
os.homedir(),
@@ -29,18 +22,6 @@ const BUNDLED_SKILLS_DIR = path.join(
);
const SEED_MIGRATION_FLAG = path.join(SKILLS_DIR, '.seed-migrated-2026-03-07-skills-overhaul');
const SEEDED_SKILL_IDS = new Set([
'db-operations',
'create-skill',
'audit',
'traverse',
'onboarding',
'persona',
'calibration',
'connect',
'node-context-enrichment',
]);
const DEPRECATED_SKILL_IDS = new Set([
'start-here',
'schema',
@@ -58,6 +39,13 @@ const DEPRECATED_SKILL_IDS = new Set([
'research',
'survey',
'traverse-graph',
'audit',
'calibration',
'connect',
'db-operations',
'node-context-enrichment',
'persona',
'traverse',
]);
function ensureSkillsDir(): void {
@@ -85,6 +73,16 @@ function listMarkdownFiles(dir: string): string[] {
return fs.readdirSync(dir).filter((f) => f.endsWith('.md'));
}
function getBundledSkillFiles(): Map<string, string> {
const bundledById = new Map<string, string>();
for (const file of listMarkdownFiles(BUNDLED_SKILLS_DIR)) {
bundledById.set(normalizeSkillId(file), path.join(BUNDLED_SKILLS_DIR, file));
}
return bundledById;
}
function migrateLegacyGuides(): void {
const guideFiles = listMarkdownFiles(LEGACY_GUIDES_DIR);
for (const file of guideFiles) {
@@ -96,17 +94,9 @@ function migrateLegacyGuides(): void {
}
function seedSkills(): void {
const bundledFiles = listMarkdownFiles(BUNDLED_SKILLS_DIR);
const bundledById = new Map<string, string>();
for (const file of bundledFiles) {
bundledById.set(normalizeSkillId(file), path.join(BUNDLED_SKILLS_DIR, file));
}
for (const skillId of SEEDED_SKILL_IDS) {
const source = bundledById.get(skillId);
if (!source) continue;
const bundledById = getBundledSkillFiles();
for (const [skillId, source] of bundledById.entries()) {
const dest = path.join(SKILLS_DIR, `${skillId}.md`);
if (!fs.existsSync(dest)) {
fs.copyFileSync(source, dest);
@@ -119,15 +109,9 @@ function migrateSeededBaseline(): void {
return;
}
const bundledFiles = listMarkdownFiles(BUNDLED_SKILLS_DIR);
const bundledById = new Map<string, string>();
for (const file of bundledFiles) {
bundledById.set(normalizeSkillId(file), path.join(BUNDLED_SKILLS_DIR, file));
}
const bundledById = getBundledSkillFiles();
for (const skillId of SEEDED_SKILL_IDS) {
const source = bundledById.get(skillId);
if (!source) continue;
for (const [skillId, source] of bundledById.entries()) {
const dest = path.join(SKILLS_DIR, `${skillId}.md`);
fs.copyFileSync(source, dest);
}
@@ -148,7 +132,6 @@ function pruneDeprecatedSkills(): void {
function resolveSkillFilename(name: string): string | null {
const files = listMarkdownFiles(SKILLS_DIR);
const normalizedInput = normalizeSkillId(name);
const directCandidates = [
`${name}.md`,
`${name.toLowerCase()}.md`,
@@ -210,7 +193,9 @@ export function readSkill(name: string): Skill | null {
init();
const filename = resolveSkillFilename(name);
if (!filename) return null;
if (!filename) {
return null;
}
const filepath = path.join(SKILLS_DIR, filename);
const raw = fs.readFileSync(filepath, 'utf-8');
@@ -261,25 +246,3 @@ export function getSkillStats(): { userSkills: number; maxUserSkills: number; sy
systemSkills: 0,
};
}
// Compatibility aliases for legacy guide-first code paths.
export type GuideMeta = SkillMeta;
export type Guide = Skill;
export const listGuides = listSkills;
export const readGuide = readSkill;
export const writeGuide = writeSkill;
export const deleteGuide = deleteSkill;
export function getUserGuideCount(): number {
return getUserSkillCount();
}
export function getGuideStats(): { userGuides: number; maxUserGuides: number; systemGuides: number } {
const stats = getSkillStats();
return {
userGuides: stats.userSkills,
maxUserGuides: stats.maxUserSkills,
systemGuides: stats.systemSkills,
};
}