mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-03-30 13:43:26 +08:00
feat: define skill placement and provenance policy (#748)
This commit is contained in:
@@ -47,6 +47,7 @@ The project is organized into several core components:
|
|||||||
- Cross-platform: Windows, macOS, Linux support via Node.js scripts
|
- Cross-platform: Windows, macOS, Linux support via Node.js scripts
|
||||||
- Agent format: Markdown with YAML frontmatter (name, description, tools, model)
|
- Agent format: Markdown with YAML frontmatter (name, description, tools, model)
|
||||||
- Skill format: Markdown with clear sections for when to use, how it works, examples
|
- Skill format: Markdown with clear sections for when to use, how it works, examples
|
||||||
|
- Skill placement: Curated in skills/; generated/imported under ~/.claude/skills/. See docs/SKILL-PLACEMENT-POLICY.md
|
||||||
- Hook format: JSON with matcher conditions and command/notification hooks
|
- Hook format: JSON with matcher conditions and command/notification hooks
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|||||||
104
docs/SKILL-PLACEMENT-POLICY.md
Normal file
104
docs/SKILL-PLACEMENT-POLICY.md
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
# Skill Placement and Provenance Policy
|
||||||
|
|
||||||
|
This document defines where generated, imported, and curated skills belong, how they are identified, and what gets shipped.
|
||||||
|
|
||||||
|
## Skill Types and Placement
|
||||||
|
|
||||||
|
| Type | Root Path | Shipped | Provenance |
|
||||||
|
|------|-----------|---------|------------|
|
||||||
|
| Curated | `skills/` (repo) | Yes | Not required |
|
||||||
|
| Learned | `~/.claude/skills/learned/` | No | Required |
|
||||||
|
| Imported | `~/.claude/skills/imported/` | No | Required |
|
||||||
|
| Evolved | `~/.claude/homunculus/evolved/skills/` (global) or `projects/<hash>/evolved/skills/` (per-project) | No | Inherits from instinct source |
|
||||||
|
|
||||||
|
Curated skills live in the repo under `skills/`. Install manifests reference only curated paths. Generated and imported skills live under the user home directory and are never shipped.
|
||||||
|
|
||||||
|
## Curated Skills
|
||||||
|
|
||||||
|
Location: `skills/<skill-name>/` with `SKILL.md` at root.
|
||||||
|
|
||||||
|
- Included in `manifests/install-modules.json` paths.
|
||||||
|
- Validated by `scripts/ci/validate-skills.js`.
|
||||||
|
- No provenance file. Use `origin` in SKILL.md frontmatter (ECC, community) for attribution.
|
||||||
|
|
||||||
|
## Learned Skills
|
||||||
|
|
||||||
|
Location: `~/.claude/skills/learned/<skill-name>/`.
|
||||||
|
|
||||||
|
Created by continuous-learning (evaluate-session hook, /learn command). Default path is configurable via `skills/continuous-learning/config.json` → `learned_skills_path`.
|
||||||
|
|
||||||
|
- Not in repo. Not shipped.
|
||||||
|
- Must have `.provenance.json` sibling to `SKILL.md`.
|
||||||
|
- Loaded at runtime when directory exists.
|
||||||
|
|
||||||
|
## Imported Skills
|
||||||
|
|
||||||
|
Location: `~/.claude/skills/imported/<skill-name>/`.
|
||||||
|
|
||||||
|
User-installed skills from external sources (URL, file copy, etc.). No automated importer exists yet; placement is by convention.
|
||||||
|
|
||||||
|
- Not in repo. Not shipped.
|
||||||
|
- Must have `.provenance.json` sibling to `SKILL.md`.
|
||||||
|
|
||||||
|
## Evolved Skills (Continuous Learning v2)
|
||||||
|
|
||||||
|
Location: `~/.claude/homunculus/evolved/skills/` (global) or `~/.claude/homunculus/projects/<hash>/evolved/skills/` (per-project).
|
||||||
|
|
||||||
|
Generated by instinct-cli evolve from clustered instincts. Separate system from learned/imported.
|
||||||
|
|
||||||
|
- Not in repo. Not shipped.
|
||||||
|
- Provenance inherited from source instincts; no separate `.provenance.json` required.
|
||||||
|
|
||||||
|
## Provenance Metadata
|
||||||
|
|
||||||
|
Required for learned and imported skills. File: `.provenance.json` in the skill directory.
|
||||||
|
|
||||||
|
Required fields:
|
||||||
|
|
||||||
|
| Field | Type | Description |
|
||||||
|
|-------|------|-------------|
|
||||||
|
| source | string | Origin (URL, path, or identifier) |
|
||||||
|
| created_at | string | ISO 8601 timestamp |
|
||||||
|
| confidence | number | 0–1 |
|
||||||
|
| author | string | Who or what produced the skill |
|
||||||
|
|
||||||
|
Schema: `schemas/provenance.schema.json`. Validation: `scripts/lib/skill-evolution/provenance.js` → `validateProvenance`.
|
||||||
|
|
||||||
|
## Validator Behavior
|
||||||
|
|
||||||
|
### validate-skills.js
|
||||||
|
|
||||||
|
Scope: Curated skills only (`skills/` in repo).
|
||||||
|
|
||||||
|
- If `skills/` does not exist: exit 0 (nothing to validate).
|
||||||
|
- For each subdirectory: must contain `SKILL.md`, non-empty.
|
||||||
|
- Does not touch learned/imported/evolved roots.
|
||||||
|
|
||||||
|
### validate-install-manifests.js
|
||||||
|
|
||||||
|
Scope: Curated paths only. All `paths` in modules must exist in the repo.
|
||||||
|
|
||||||
|
- Generated/imported roots are out of scope. No manifest references them.
|
||||||
|
- Missing path → error. No optional-path handling.
|
||||||
|
|
||||||
|
### Scripts That Use Generated Roots
|
||||||
|
|
||||||
|
`scripts/skills-health.js`, `scripts/lib/skill-evolution/health.js`, session hooks: they probe `~/.claude/skills/learned` and `~/.claude/skills/imported`. Missing directories are treated as empty; no errors.
|
||||||
|
|
||||||
|
## Publishable vs Local-Only
|
||||||
|
|
||||||
|
| Publishable | Local-Only |
|
||||||
|
|-------------|------------|
|
||||||
|
| `skills/*` (curated) | `~/.claude/skills/learned/*` |
|
||||||
|
| | `~/.claude/skills/imported/*` |
|
||||||
|
| | `~/.claude/homunculus/**/evolved/**` |
|
||||||
|
|
||||||
|
Only curated skills appear in install manifests and get copied during install.
|
||||||
|
|
||||||
|
## Implementation Roadmap
|
||||||
|
|
||||||
|
1. Policy document and provenance schema (this change).
|
||||||
|
2. Add provenance validation to learned-skill write paths (evaluate-session, /learn output) so new learned skills always get `.provenance.json`.
|
||||||
|
3. Update instinct-cli evolve to write optional provenance when generating evolved skills.
|
||||||
|
4. Add `scripts/validate-provenance.js` to CI for any repo paths that must not contain learned/imported content (if needed).
|
||||||
|
5. Document learned/imported roots in CONTRIBUTING.md or user docs so contributors know not to commit them.
|
||||||
31
schemas/provenance.schema.json
Normal file
31
schemas/provenance.schema.json
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"title": "Skill Provenance",
|
||||||
|
"description": "Provenance metadata for learned and imported skills. Required in ~/.claude/skills/learned/* and ~/.claude/skills/imported/*",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"source": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
"description": "Origin (URL, path, or identifier)"
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time",
|
||||||
|
"description": "ISO 8601 timestamp"
|
||||||
|
},
|
||||||
|
"confidence": {
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 1,
|
||||||
|
"description": "Confidence score 0-1"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
"description": "Who or what produced the skill"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["source", "created_at", "confidence", "author"],
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
@@ -99,13 +99,14 @@ function validateCommands() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check skill directory references (e.g., "skills/tdd-workflow/")
|
// Check skill directory references (e.g., "skills/tdd-workflow/")
|
||||||
|
// learned and imported are reserved roots (~/.claude/skills/); no local dir expected
|
||||||
|
const reservedSkillRoots = new Set(['learned', 'imported']);
|
||||||
const skillRefs = contentNoCodeBlocks.matchAll(/skills\/([a-z][-a-z0-9]*)\//g);
|
const skillRefs = contentNoCodeBlocks.matchAll(/skills\/([a-z][-a-z0-9]*)\//g);
|
||||||
for (const match of skillRefs) {
|
for (const match of skillRefs) {
|
||||||
const refName = match[1];
|
const refName = match[1];
|
||||||
if (!validSkills.has(refName)) {
|
if (reservedSkillRoots.has(refName) || validSkills.has(refName)) continue;
|
||||||
console.warn(`WARN: ${file} - references skill directory skills/${refName}/ (not found locally)`);
|
console.warn(`WARN: ${file} - references skill directory skills/${refName}/ (not found locally)`);
|
||||||
warnCount++;
|
warnCount++;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check agent name references in workflow diagrams (e.g., "planner -> tdd-guide")
|
// Check agent name references in workflow diagrams (e.g., "planner -> tdd-guide")
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
/**
|
/**
|
||||||
* Validate selective-install manifests and profile/module relationships.
|
* Validate selective-install manifests and profile/module relationships.
|
||||||
|
* Module paths are curated repo paths only. Generated/imported skill roots
|
||||||
|
* (~/.claude/skills/learned, etc.) are never in manifests.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
@@ -109,6 +111,7 @@ function validateInstallManifests() {
|
|||||||
const normalizedPath = normalizeRelativePath(relativePath);
|
const normalizedPath = normalizeRelativePath(relativePath);
|
||||||
const absolutePath = path.join(REPO_ROOT, normalizedPath);
|
const absolutePath = path.join(REPO_ROOT, normalizedPath);
|
||||||
|
|
||||||
|
// All module paths must exist; no optional/generated paths in manifests
|
||||||
if (!fs.existsSync(absolutePath)) {
|
if (!fs.existsSync(absolutePath)) {
|
||||||
console.error(
|
console.error(
|
||||||
`ERROR: Module ${module.id} references missing path: ${normalizedPath}`
|
`ERROR: Module ${module.id} references missing path: ${normalizedPath}`
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
/**
|
/**
|
||||||
* Validate skill directories have SKILL.md with required structure
|
* Validate curated skill directories (skills/ in repo).
|
||||||
|
* Scope: curated only. Learned/imported/evolved roots are out of scope.
|
||||||
|
* If skills/ does not exist, exit 0 (no curated skills to validate).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
@@ -10,7 +12,7 @@ const SKILLS_DIR = path.join(__dirname, '../../skills');
|
|||||||
|
|
||||||
function validateSkills() {
|
function validateSkills() {
|
||||||
if (!fs.existsSync(SKILLS_DIR)) {
|
if (!fs.existsSync(SKILLS_DIR)) {
|
||||||
console.log('No skills directory found, skipping validation');
|
console.log('No curated skills directory (skills/), skipping');
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user