prizmkit 1.0.0 → 1.0.1
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/bundled/VERSION.json +5 -0
- package/bundled/adapters/claude/agent-adapter.js +108 -0
- package/bundled/adapters/claude/command-adapter.js +104 -0
- package/bundled/adapters/claude/paths.js +35 -0
- package/bundled/adapters/claude/rules-adapter.js +77 -0
- package/bundled/adapters/claude/settings-adapter.js +73 -0
- package/bundled/adapters/claude/team-adapter.js +183 -0
- package/bundled/adapters/codebuddy/agent-adapter.js +43 -0
- package/bundled/adapters/codebuddy/paths.js +29 -0
- package/bundled/adapters/codebuddy/settings-adapter.js +47 -0
- package/bundled/adapters/codebuddy/skill-adapter.js +68 -0
- package/bundled/adapters/codebuddy/team-adapter.js +46 -0
- package/bundled/adapters/shared/frontmatter.js +77 -0
- package/bundled/agents/prizm-dev-team-coordinator.md +142 -0
- package/bundled/agents/prizm-dev-team-dev.md +99 -0
- package/bundled/agents/prizm-dev-team-pm.md +114 -0
- package/bundled/agents/prizm-dev-team-reviewer.md +119 -0
- package/bundled/dev-pipeline/README.md +482 -0
- package/bundled/dev-pipeline/assets/feature-list-example.json +147 -0
- package/bundled/dev-pipeline/assets/prizm-dev-team-integration.md +138 -0
- package/bundled/dev-pipeline/launch-bugfix-daemon.sh +425 -0
- package/bundled/dev-pipeline/launch-daemon.sh +549 -0
- package/bundled/dev-pipeline/reset-feature.sh +209 -0
- package/bundled/dev-pipeline/retry-bug.sh +344 -0
- package/bundled/dev-pipeline/retry-feature.sh +338 -0
- package/bundled/dev-pipeline/run-bugfix.sh +638 -0
- package/bundled/dev-pipeline/run.sh +845 -0
- package/bundled/dev-pipeline/scripts/check-session-status.py +158 -0
- package/bundled/dev-pipeline/scripts/detect-stuck.py +385 -0
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +598 -0
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +402 -0
- package/bundled/dev-pipeline/scripts/init-bugfix-pipeline.py +294 -0
- package/bundled/dev-pipeline/scripts/init-dev-team.py +134 -0
- package/bundled/dev-pipeline/scripts/init-pipeline.py +335 -0
- package/bundled/dev-pipeline/scripts/update-bug-status.py +748 -0
- package/bundled/dev-pipeline/scripts/update-feature-status.py +1076 -0
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +262 -0
- package/bundled/dev-pipeline/templates/bug-fix-list-schema.json +159 -0
- package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +291 -0
- package/bundled/dev-pipeline/templates/feature-list-schema.json +112 -0
- package/bundled/dev-pipeline/templates/session-status-schema.json +77 -0
- package/bundled/skills/_metadata.json +267 -0
- package/bundled/skills/app-planner/SKILL.md +580 -0
- package/bundled/skills/app-planner/assets/planning-guide.md +313 -0
- package/bundled/skills/app-planner/scripts/validate-and-generate.py +758 -0
- package/bundled/skills/bug-planner/SKILL.md +235 -0
- package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +252 -0
- package/bundled/skills/dev-pipeline-launcher/SKILL.md +223 -0
- package/bundled/skills/prizm-kit/SKILL.md +151 -0
- package/bundled/skills/prizm-kit/assets/claude-md-template.md +38 -0
- package/bundled/skills/prizm-kit/assets/codebuddy-md-template.md +35 -0
- package/bundled/skills/prizm-kit/assets/hooks/prizm-commit-hook.json +15 -0
- package/bundled/skills/prizmkit-adr-manager/SKILL.md +68 -0
- package/bundled/skills/prizmkit-adr-manager/assets/adr-template.md +26 -0
- package/bundled/skills/prizmkit-analyze/SKILL.md +194 -0
- package/bundled/skills/prizmkit-api-doc-generator/SKILL.md +56 -0
- package/bundled/skills/prizmkit-bug-fix-workflow/SKILL.md +351 -0
- package/bundled/skills/prizmkit-bug-reproducer/SKILL.md +62 -0
- package/bundled/skills/prizmkit-ci-cd-generator/SKILL.md +54 -0
- package/bundled/skills/prizmkit-clarify/SKILL.md +52 -0
- package/bundled/skills/prizmkit-code-review/SKILL.md +70 -0
- package/bundled/skills/prizmkit-committer/SKILL.md +117 -0
- package/bundled/skills/prizmkit-db-migration/SKILL.md +65 -0
- package/bundled/skills/prizmkit-dependency-health/SKILL.md +123 -0
- package/bundled/skills/prizmkit-deployment-strategy/SKILL.md +58 -0
- package/bundled/skills/prizmkit-error-triage/SKILL.md +55 -0
- package/bundled/skills/prizmkit-implement/SKILL.md +47 -0
- package/bundled/skills/prizmkit-init/SKILL.md +156 -0
- package/bundled/skills/prizmkit-log-analyzer/SKILL.md +55 -0
- package/bundled/skills/prizmkit-monitoring-setup/SKILL.md +75 -0
- package/bundled/skills/prizmkit-onboarding-generator/SKILL.md +70 -0
- package/bundled/skills/prizmkit-perf-profiler/SKILL.md +55 -0
- package/bundled/skills/prizmkit-plan/SKILL.md +54 -0
- package/bundled/skills/prizmkit-plan/assets/plan-template.md +37 -0
- package/bundled/skills/prizmkit-prizm-docs/SKILL.md +140 -0
- package/bundled/skills/prizmkit-prizm-docs/assets/PRIZM-SPEC.md +943 -0
- package/bundled/skills/prizmkit-retrospective/SKILL.md +79 -0
- package/bundled/skills/prizmkit-security-audit/SKILL.md +130 -0
- package/bundled/skills/prizmkit-specify/SKILL.md +52 -0
- package/bundled/skills/prizmkit-specify/assets/spec-template.md +37 -0
- package/bundled/skills/prizmkit-summarize/SKILL.md +51 -0
- package/bundled/skills/prizmkit-summarize/assets/registry-template.md +18 -0
- package/bundled/skills/prizmkit-tasks/SKILL.md +50 -0
- package/bundled/skills/prizmkit-tasks/assets/tasks-template.md +21 -0
- package/bundled/skills/prizmkit-tech-debt-tracker/SKILL.md +139 -0
- package/bundled/team/prizm-dev-team.json +47 -0
- package/bundled/templates/claude-md-template.md +38 -0
- package/bundled/templates/codebuddy-md-template.md +35 -0
- package/package.json +2 -1
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code Agent Adapter
|
|
3
|
+
* Converts core/ agent definitions to .claude/agents/ format.
|
|
4
|
+
*
|
|
5
|
+
* Key differences from CodeBuddy agents:
|
|
6
|
+
* - tools: comma-separated string -> YAML array
|
|
7
|
+
* - model: "inherit" -> explicit model name
|
|
8
|
+
* - skills: field removed (skills become /slash-commands in body)
|
|
9
|
+
* - TaskCreate/Get/Update/List -> Task (single tool)
|
|
10
|
+
* - SendMessage -> SendMessage (native Agent Teams communication)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { parseFrontmatter, buildMarkdown } from '../shared/frontmatter.js';
|
|
14
|
+
import { mkdirSync } from 'node:fs';
|
|
15
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
16
|
+
import path from 'path';
|
|
17
|
+
|
|
18
|
+
// Tool name mapping from CodeBuddy to Claude Code
|
|
19
|
+
// Claude Code 原生 Agent Teams 支持 SendMessage 工具进行 teammate 间通信
|
|
20
|
+
const TOOL_MAPPING = {
|
|
21
|
+
'TaskCreate': 'Task',
|
|
22
|
+
'TaskGet': 'Task',
|
|
23
|
+
'TaskUpdate': 'Task',
|
|
24
|
+
'TaskList': 'Task',
|
|
25
|
+
'SendMessage': 'SendMessage',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Default model for Claude Code agents
|
|
29
|
+
const DEFAULT_MODEL = 'claude-sonnet-4-20250514';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Convert a core agent definition to Claude Code format.
|
|
33
|
+
* @param {string} agentContent - Content of the core agent .md
|
|
34
|
+
* @param {Object} options - { model?: string }
|
|
35
|
+
* @returns {string} - Claude Code formatted agent .md content
|
|
36
|
+
*/
|
|
37
|
+
export function convertAgent(agentContent, options = {}) {
|
|
38
|
+
const { frontmatter, body } = parseFrontmatter(agentContent);
|
|
39
|
+
|
|
40
|
+
// Convert tools: comma-separated string -> deduplicated array
|
|
41
|
+
let tools = [];
|
|
42
|
+
if (frontmatter.tools) {
|
|
43
|
+
const rawTools = frontmatter.tools.split(',').map(t => t.trim());
|
|
44
|
+
const mapped = rawTools.map(t => {
|
|
45
|
+
if (TOOL_MAPPING.hasOwnProperty(t)) {
|
|
46
|
+
return TOOL_MAPPING[t];
|
|
47
|
+
}
|
|
48
|
+
return t;
|
|
49
|
+
}).filter(Boolean);
|
|
50
|
+
tools = [...new Set(mapped)];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Convert skills references in body to slash commands
|
|
54
|
+
let convertedBody = body;
|
|
55
|
+
if (frontmatter.skills) {
|
|
56
|
+
const skillsList = frontmatter.skills.split(',').map(s => s.trim());
|
|
57
|
+
|
|
58
|
+
// Add a section about available slash commands
|
|
59
|
+
const commandList = skillsList.map(s => `- \`/${s}\``).join('\n');
|
|
60
|
+
const commandSection = `\n\n### 可用命令 (Available Slash Commands)\n\n以下 PrizmKit 命令可通过 slash command 调用:\n${commandList}\n`;
|
|
61
|
+
|
|
62
|
+
// Insert before the first ### section or at the end of body
|
|
63
|
+
const firstH3 = convertedBody.indexOf('\n### ');
|
|
64
|
+
if (firstH3 > 0) {
|
|
65
|
+
convertedBody = convertedBody.slice(0, firstH3) + commandSection + convertedBody.slice(firstH3);
|
|
66
|
+
} else {
|
|
67
|
+
convertedBody += commandSection;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Replace "invoke ... skill" with slash command syntax
|
|
72
|
+
convertedBody = convertedBody.replace(
|
|
73
|
+
/invoke\s+(?:the\s+)?[`"]?(\w[\w-]*)[`"]?\s+skill/gi,
|
|
74
|
+
'run `/$1` command'
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// Replace prizmkit.xxx shorthand with /prizmkit-xxx
|
|
78
|
+
convertedBody = convertedBody.replace(
|
|
79
|
+
/prizmkit\.(\w+)/g,
|
|
80
|
+
(match, sub) => `/prizmkit-${sub.replace(/_/g, '-')}`
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// Build Claude Code frontmatter
|
|
84
|
+
const claudeFrontmatter = {
|
|
85
|
+
name: frontmatter.name,
|
|
86
|
+
description: frontmatter.description,
|
|
87
|
+
tools: tools,
|
|
88
|
+
model: options.model || DEFAULT_MODEL,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
return buildMarkdown(claudeFrontmatter, convertedBody);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Install an agent definition to the target project's .claude/agents/.
|
|
96
|
+
* @param {string} corePath - Path to core/agents/<name>.md
|
|
97
|
+
* @param {string} targetRoot - Target project root
|
|
98
|
+
* @param {Object} options - { model?: string }
|
|
99
|
+
*/
|
|
100
|
+
export async function installAgent(corePath, targetRoot, options = {}) {
|
|
101
|
+
const filename = path.basename(corePath);
|
|
102
|
+
const targetDir = path.join(targetRoot, '.claude', 'agents');
|
|
103
|
+
mkdirSync(targetDir, { recursive: true });
|
|
104
|
+
|
|
105
|
+
const content = await readFile(corePath, 'utf8');
|
|
106
|
+
const converted = convertAgent(content, options);
|
|
107
|
+
await writeFile(path.join(targetDir, filename), converted);
|
|
108
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code Command Adapter
|
|
3
|
+
* Converts core/ skill content to .claude/commands/ format.
|
|
4
|
+
*
|
|
5
|
+
* Key differences from CodeBuddy SKILL.md:
|
|
6
|
+
* - Claude Code commands omit the `name` field (filename is the name)
|
|
7
|
+
* - Only `description` in frontmatter
|
|
8
|
+
* - `${SKILL_DIR}` references rewritten to relative paths
|
|
9
|
+
* - Skills with assets/scripts use directory structure
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { parseFrontmatter, buildMarkdown } from '../shared/frontmatter.js';
|
|
13
|
+
import { COMMANDS_DIR } from './paths.js';
|
|
14
|
+
import { existsSync, mkdirSync, cpSync } from 'node:fs';
|
|
15
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
16
|
+
import path from 'path';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Convert a core SKILL.md to Claude Code command.md format.
|
|
20
|
+
* @param {string} skillContent - Content of the core SKILL.md
|
|
21
|
+
* @param {string} skillName - Skill directory name
|
|
22
|
+
* @returns {string} - Claude Code formatted command.md content
|
|
23
|
+
*/
|
|
24
|
+
export function convertSkillToCommand(skillContent, skillName) {
|
|
25
|
+
const { frontmatter, body } = parseFrontmatter(skillContent);
|
|
26
|
+
|
|
27
|
+
// Claude Code command frontmatter only uses description
|
|
28
|
+
const claudeFrontmatter = {
|
|
29
|
+
description: frontmatter.description || `PrizmKit ${skillName} command`,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// Rewrite ${SKILL_DIR} references to use relative path from .claude/commands/<name>/
|
|
33
|
+
let convertedBody = body;
|
|
34
|
+
|
|
35
|
+
// Replace ${SKILL_DIR} with a Claude Code compatible path
|
|
36
|
+
// In Claude Code, commands in a directory can reference sibling files
|
|
37
|
+
// Use project-root-relative paths as fallback
|
|
38
|
+
convertedBody = convertedBody.replace(
|
|
39
|
+
/\$\{SKILL_DIR\}/g,
|
|
40
|
+
`.claude/commands/${skillName}`
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
// Replace "invoke the X skill" or "prizmkit.X" patterns with /X slash command
|
|
44
|
+
convertedBody = convertedBody.replace(
|
|
45
|
+
/invoke\s+(?:the\s+)?[`"]?(\w[\w-]*)[`"]?\s+skill/gi,
|
|
46
|
+
'run the `/$1` command'
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
// Replace prizmkit.xxx with /prizmkit-xxx for Claude Code
|
|
50
|
+
convertedBody = convertedBody.replace(
|
|
51
|
+
/prizmkit\.(\w+)/g,
|
|
52
|
+
(match, sub) => {
|
|
53
|
+
// Map common shorthand: prizmkit.init -> /prizmkit-init
|
|
54
|
+
const commandName = `prizmkit-${sub.replace(/_/g, '-')}`;
|
|
55
|
+
return `\`/${commandName}\``;
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
return buildMarkdown(claudeFrontmatter, convertedBody);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Install a skill as a Claude Code command in the target project.
|
|
64
|
+
* @param {string} corePath - Path to core/skills/<skill-name>/
|
|
65
|
+
* @param {string} targetRoot - Target project root
|
|
66
|
+
*/
|
|
67
|
+
export async function installCommand(corePath, targetRoot) {
|
|
68
|
+
const skillName = path.basename(corePath);
|
|
69
|
+
const hasAssets = existsSync(path.join(corePath, 'assets'));
|
|
70
|
+
const hasScripts = existsSync(path.join(corePath, 'scripts'));
|
|
71
|
+
|
|
72
|
+
if (hasAssets || hasScripts) {
|
|
73
|
+
// Use directory structure for commands with resources
|
|
74
|
+
const targetDir = path.join(targetRoot, COMMANDS_DIR, skillName);
|
|
75
|
+
mkdirSync(targetDir, { recursive: true });
|
|
76
|
+
|
|
77
|
+
// Convert and write command.md
|
|
78
|
+
const skillMdPath = path.join(corePath, 'SKILL.md');
|
|
79
|
+
if (existsSync(skillMdPath)) {
|
|
80
|
+
const content = await readFile(skillMdPath, 'utf8');
|
|
81
|
+
const converted = convertSkillToCommand(content, skillName);
|
|
82
|
+
await writeFile(path.join(targetDir, `${skillName}.md`), converted);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Copy assets and scripts
|
|
86
|
+
for (const subdir of ['scripts', 'assets']) {
|
|
87
|
+
const srcSubdir = path.join(corePath, subdir);
|
|
88
|
+
if (existsSync(srcSubdir)) {
|
|
89
|
+
cpSync(srcSubdir, path.join(targetDir, subdir), { recursive: true });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
// Single file command
|
|
94
|
+
const targetDir = path.join(targetRoot, COMMANDS_DIR);
|
|
95
|
+
mkdirSync(targetDir, { recursive: true });
|
|
96
|
+
|
|
97
|
+
const skillMdPath = path.join(corePath, 'SKILL.md');
|
|
98
|
+
if (existsSync(skillMdPath)) {
|
|
99
|
+
const content = await readFile(skillMdPath, 'utf8');
|
|
100
|
+
const converted = convertSkillToCommand(content, skillName);
|
|
101
|
+
await writeFile(path.join(targetDir, `${skillName}.md`), converted);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code platform path constants and conventions.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export const PLATFORM_ID = 'claude';
|
|
6
|
+
export const CLI_COMMAND = 'claude';
|
|
7
|
+
|
|
8
|
+
// Project-level paths (relative to project root)
|
|
9
|
+
export const COMMANDS_DIR = '.claude/commands';
|
|
10
|
+
export const AGENTS_DIR = '.claude/agents';
|
|
11
|
+
export const SETTINGS_FILE = '.claude/settings.json';
|
|
12
|
+
export const RULES_DIR = '.claude/rules';
|
|
13
|
+
export const PROJECT_MEMORY_FILE = 'CLAUDE.md';
|
|
14
|
+
export const MCP_CONFIG_FILE = '.mcp.json';
|
|
15
|
+
|
|
16
|
+
// Global paths (relative to home directory)
|
|
17
|
+
export const GLOBAL_CONFIG_DIR = '.claude';
|
|
18
|
+
export const GLOBAL_AGENTS_DIR = '.claude/agents';
|
|
19
|
+
|
|
20
|
+
// Command file conventions (equivalent to skills)
|
|
21
|
+
// Note: Actual command files are named <skill-name>.md (e.g. prizmkit-specify.md)
|
|
22
|
+
// Directory-based commands with assets also use <skill-name>.md inside the directory.
|
|
23
|
+
export const COMMAND_DEFINITION_FILE = '<skill-name>.md';
|
|
24
|
+
export const COMMAND_DIR_VAR = '${COMMAND_DIR}'; // May not be natively supported
|
|
25
|
+
|
|
26
|
+
// Agent definition format
|
|
27
|
+
export const AGENT_FILE_EXT = '.md';
|
|
28
|
+
|
|
29
|
+
// CLI flags
|
|
30
|
+
export const CLI_FLAGS = {
|
|
31
|
+
nonInteractive: '-p',
|
|
32
|
+
autoAccept: '--yes',
|
|
33
|
+
verbose: '--verbose',
|
|
34
|
+
print: '--print',
|
|
35
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code Rules Adapter
|
|
3
|
+
* Generates .claude/rules/ files for PrizmKit-enabled projects.
|
|
4
|
+
* Rules provide modular, path-scoped instructions for Claude Code.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { mkdirSync } from 'node:fs';
|
|
8
|
+
import { writeFile } from 'node:fs/promises';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
|
|
11
|
+
const RULES = [
|
|
12
|
+
{
|
|
13
|
+
filename: 'prizm-documentation.md',
|
|
14
|
+
content: `---
|
|
15
|
+
description: "PrizmKit documentation rules"
|
|
16
|
+
globs:
|
|
17
|
+
- "**/*.ts"
|
|
18
|
+
- "**/*.tsx"
|
|
19
|
+
- "**/*.js"
|
|
20
|
+
- "**/*.jsx"
|
|
21
|
+
- "**/*.py"
|
|
22
|
+
- "**/*.go"
|
|
23
|
+
- "**/*.rs"
|
|
24
|
+
- "**/*.java"
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
When modifying source files in this project:
|
|
28
|
+
1. Check if \`.prizm-docs/root.prizm\` exists
|
|
29
|
+
2. If it does, read it before making changes to understand project structure
|
|
30
|
+
3. After making changes, update affected \`.prizm-docs/\` files
|
|
31
|
+
4. Follow the Prizm doc format (KEY: value, not prose)
|
|
32
|
+
5. Size limits: L0 = 4KB, L1 = 3KB, L2 = 5KB
|
|
33
|
+
`,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
filename: 'prizm-commit-workflow.md',
|
|
37
|
+
content: `---
|
|
38
|
+
description: "PrizmKit commit workflow rules"
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
Before any git commit in this project:
|
|
42
|
+
1. Update \`.prizm-docs/\` for affected modules
|
|
43
|
+
2. Use Conventional Commits format: type(scope): description
|
|
44
|
+
3. Bug fixes use \`fix()\` prefix, not \`feat()\`
|
|
45
|
+
4. Do NOT create REGISTRY.md entries for bug fixes
|
|
46
|
+
5. Use \`/prizmkit-committer\` command for the complete commit workflow
|
|
47
|
+
`,
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
filename: 'prizm-progressive-loading.md',
|
|
51
|
+
content: `---
|
|
52
|
+
description: "PrizmKit progressive context loading protocol"
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
This project uses PrizmKit's progressive loading protocol:
|
|
56
|
+
- ON SESSION START: Read \`.prizm-docs/root.prizm\` (L0 — project map)
|
|
57
|
+
- ON TASK: Read L1 (\`.prizm-docs/<module>.prizm\`) for relevant modules
|
|
58
|
+
- ON FILE EDIT: Read L2 (\`.prizm-docs/<module>/<submodule>.prizm\`) before modifying
|
|
59
|
+
- NEVER load all .prizm docs at once
|
|
60
|
+
- Arrow notation (->) in .prizm files indicates load pointers
|
|
61
|
+
- DECISIONS and CHANGELOG in .prizm files are append-only
|
|
62
|
+
`,
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Install PrizmKit rules to the target project's .claude/rules/ directory.
|
|
68
|
+
* @param {string} targetRoot - Target project root
|
|
69
|
+
*/
|
|
70
|
+
export async function installRules(targetRoot) {
|
|
71
|
+
const rulesDir = path.join(targetRoot, '.claude', 'rules');
|
|
72
|
+
mkdirSync(rulesDir, { recursive: true });
|
|
73
|
+
|
|
74
|
+
for (const rule of RULES) {
|
|
75
|
+
await writeFile(path.join(rulesDir, rule.filename), rule.content);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code Settings Adapter
|
|
3
|
+
* Generates .claude/settings.json with PrizmKit hooks and permissions.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
7
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generate Claude Code settings.json for a PrizmKit-enabled project.
|
|
12
|
+
* @param {string} targetRoot - Target project root
|
|
13
|
+
* @param {Object} options - { hooks: boolean, pipeline: boolean }
|
|
14
|
+
*/
|
|
15
|
+
export async function generateSettings(targetRoot, options = {}) {
|
|
16
|
+
const settingsPath = path.join(targetRoot, '.claude', 'settings.json');
|
|
17
|
+
mkdirSync(path.dirname(settingsPath), { recursive: true });
|
|
18
|
+
|
|
19
|
+
let existing = {};
|
|
20
|
+
if (existsSync(settingsPath)) {
|
|
21
|
+
try {
|
|
22
|
+
existing = JSON.parse(await readFile(settingsPath, 'utf8'));
|
|
23
|
+
} catch {
|
|
24
|
+
existing = {};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Permissions for pipeline and PrizmKit operations
|
|
29
|
+
if (!existing.permissions) existing.permissions = {};
|
|
30
|
+
if (!existing.permissions.allow) existing.permissions.allow = [];
|
|
31
|
+
|
|
32
|
+
const prizmkitPermissions = [
|
|
33
|
+
'Bash(python3 *)',
|
|
34
|
+
'Bash(git *)',
|
|
35
|
+
'Bash(jq *)',
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
if (options.pipeline) {
|
|
39
|
+
prizmkitPermissions.push(
|
|
40
|
+
'Bash(./dev-pipeline/*)',
|
|
41
|
+
'Bash(python3 dev-pipeline/*)',
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Merge without duplicates
|
|
46
|
+
for (const perm of prizmkitPermissions) {
|
|
47
|
+
if (!existing.permissions.allow.includes(perm)) {
|
|
48
|
+
existing.permissions.allow.push(perm);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Hooks for PrizmKit commit workflow
|
|
53
|
+
if (options.hooks !== false) {
|
|
54
|
+
if (!existing.hooks) existing.hooks = {};
|
|
55
|
+
|
|
56
|
+
// SessionStart hook: remind about .prizm-docs
|
|
57
|
+
if (!existing.hooks.SessionStart) {
|
|
58
|
+
existing.hooks.SessionStart = [
|
|
59
|
+
{
|
|
60
|
+
matcher: 'startup',
|
|
61
|
+
hooks: [
|
|
62
|
+
{
|
|
63
|
+
type: 'command',
|
|
64
|
+
command: 'test -f .prizm-docs/root.prizm && echo "PrizmKit: .prizm-docs found. Read root.prizm for project context." || echo "PrizmKit: No .prizm-docs found. Run /prizmkit-init to bootstrap."',
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
await writeFile(settingsPath, JSON.stringify(existing, null, 2));
|
|
73
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code Team Adapter
|
|
3
|
+
*
|
|
4
|
+
* 支持 Claude Code 原生 Agent Teams 系统。
|
|
5
|
+
* 通过环境变量 CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 启用原生团队模式。
|
|
6
|
+
*
|
|
7
|
+
* 两种模式:
|
|
8
|
+
* 1. 原生 Agent Teams 模式 (推荐): 使用 SendMessage 实现 teammate 间多向通信
|
|
9
|
+
* 2. Subagent 模式 (兜底): 通过 Task 工具由 Coordinator 单向编排
|
|
10
|
+
*
|
|
11
|
+
* 原生 Agent Teams 的核心机制:
|
|
12
|
+
* - 每个 agent 作为 teammate 持续运行
|
|
13
|
+
* - 通过 SendMessage 工具实现点对点、广播通信
|
|
14
|
+
* - 共享任务目录 ~/.claude/tasks/{team-name}/
|
|
15
|
+
* - 支持 shutdown 消息终止 teammate
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { mkdirSync, existsSync } from 'node:fs';
|
|
19
|
+
import { writeFile, readFile } from 'node:fs/promises';
|
|
20
|
+
import path from 'path';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 检测是否启用了原生 Agent Teams 模式
|
|
24
|
+
* @returns {boolean}
|
|
25
|
+
*/
|
|
26
|
+
export function isNativeTeamsEnabled() {
|
|
27
|
+
return process.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS === '1';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 生成原生 Agent Teams 配置
|
|
32
|
+
* 当 CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 时使用此模式
|
|
33
|
+
*
|
|
34
|
+
* @param {Object} teamDef - 平台无关的团队定义 (core/team/*.json)
|
|
35
|
+
* @param {string} targetRoot - 目标项目根目录
|
|
36
|
+
*/
|
|
37
|
+
async function installNativeTeam(teamDef, targetRoot) {
|
|
38
|
+
const claudeDir = path.join(targetRoot, '.claude');
|
|
39
|
+
mkdirSync(claudeDir, { recursive: true });
|
|
40
|
+
|
|
41
|
+
// 构建原生 Agent Teams 配置
|
|
42
|
+
const teamConfig = {
|
|
43
|
+
name: teamDef.name,
|
|
44
|
+
description: teamDef.description,
|
|
45
|
+
platform: 'claude',
|
|
46
|
+
orchestrationMode: 'native-agent-teams',
|
|
47
|
+
envVar: 'CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1',
|
|
48
|
+
teammates: teamDef.members.map(m => ({
|
|
49
|
+
name: m.name,
|
|
50
|
+
role: m.role,
|
|
51
|
+
agentFile: `.claude/agents/${m.agentDefinition}.md`,
|
|
52
|
+
prompt: m.prompt || '',
|
|
53
|
+
subscriptions: m.subscriptions || [],
|
|
54
|
+
})),
|
|
55
|
+
communication: {
|
|
56
|
+
protocol: 'SendMessage',
|
|
57
|
+
modes: ['point-to-point', 'broadcast', 'shutdown'],
|
|
58
|
+
messageTypes: [
|
|
59
|
+
'STATUS_UPDATE',
|
|
60
|
+
'COMPLETION_SIGNAL',
|
|
61
|
+
'ISSUE_REPORT',
|
|
62
|
+
'ESCALATION',
|
|
63
|
+
'HEARTBEAT_CHECK',
|
|
64
|
+
'TASK_ASSIGNMENT',
|
|
65
|
+
],
|
|
66
|
+
routing: 'mesh',
|
|
67
|
+
note: 'Teammates 之间可直接通信 (SendMessage),关键消息同时通知 Coordinator。',
|
|
68
|
+
},
|
|
69
|
+
sharedTaskDir: `~/.claude/tasks/${teamDef.name}/`,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
await writeFile(
|
|
73
|
+
path.join(claudeDir, 'team-info.json'),
|
|
74
|
+
JSON.stringify(teamConfig, null, 2)
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// 生成 Agent Teams 使用说明
|
|
78
|
+
const teamGuide = `# ${teamDef.name} — Agent Teams 配置
|
|
79
|
+
|
|
80
|
+
## 启用方式
|
|
81
|
+
|
|
82
|
+
\`\`\`bash
|
|
83
|
+
export CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
|
|
84
|
+
\`\`\`
|
|
85
|
+
|
|
86
|
+
## 团队成员
|
|
87
|
+
|
|
88
|
+
| 名称 | 角色 | Agent 文件 |
|
|
89
|
+
|------|------|-----------|
|
|
90
|
+
${teamDef.members.map(m => `| ${m.name} | ${m.role} | \`.claude/agents/${m.agentDefinition}.md\` |`).join('\n')}
|
|
91
|
+
|
|
92
|
+
## 通信机制
|
|
93
|
+
|
|
94
|
+
原生 Agent Teams 使用 **SendMessage** 工具实现 teammate 间通信:
|
|
95
|
+
|
|
96
|
+
- **点对点**: \`SendMessage(to: "pm", message: "...")\`
|
|
97
|
+
- **广播**: \`SendMessage(to: "*", message: "...")\`
|
|
98
|
+
- **终止**: \`SendMessage(to: "dev", type: "shutdown")\`
|
|
99
|
+
|
|
100
|
+
## 消息类型
|
|
101
|
+
|
|
102
|
+
- \`STATUS_UPDATE\` — Agent 汇报状态变化
|
|
103
|
+
- \`COMPLETION_SIGNAL\` — Agent 完成任务通知
|
|
104
|
+
- \`ISSUE_REPORT\` — Agent 报告问题
|
|
105
|
+
- \`ESCALATION\` — Agent 请求升级处理
|
|
106
|
+
- \`HEARTBEAT_CHECK\` — 检查 Agent 存活
|
|
107
|
+
- \`TASK_ASSIGNMENT\` — 任务分配指令
|
|
108
|
+
|
|
109
|
+
## 与 Subagent 模式的区别
|
|
110
|
+
|
|
111
|
+
| 维度 | Subagent 模式 | 原生 Agent Teams |
|
|
112
|
+
|------|---------------|-----------------|
|
|
113
|
+
| 通信方式 | Coordinator 通过 Task 单向 spawn | SendMessage 多向通信 |
|
|
114
|
+
| Agent 生命周期 | 完成即消亡 | 持续运行 |
|
|
115
|
+
| 协作模式 | 星型 (Coordinator 中心) | 网状 (任意 teammate 间) |
|
|
116
|
+
| 共享状态 | 无 | ~/.claude/tasks/${teamDef.name}/ |
|
|
117
|
+
`;
|
|
118
|
+
|
|
119
|
+
await writeFile(
|
|
120
|
+
path.join(claudeDir, 'team-guide.md'),
|
|
121
|
+
teamGuide
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* 生成 Subagent 模式配置 (兜底)
|
|
127
|
+
* 当未启用 Agent Teams 时使用此模式
|
|
128
|
+
*
|
|
129
|
+
* @param {Object} teamDef - 平台无关的团队定义
|
|
130
|
+
* @param {string} targetRoot - 目标项目根目录
|
|
131
|
+
*/
|
|
132
|
+
async function installSubagentTeam(teamDef, targetRoot) {
|
|
133
|
+
const claudeDir = path.join(targetRoot, '.claude');
|
|
134
|
+
mkdirSync(claudeDir, { recursive: true });
|
|
135
|
+
|
|
136
|
+
const teamInfo = {
|
|
137
|
+
name: teamDef.name,
|
|
138
|
+
description: teamDef.description,
|
|
139
|
+
platform: 'claude',
|
|
140
|
+
orchestrationMode: 'subagent',
|
|
141
|
+
note: 'Subagent 兜底模式。如需启用原生 Agent Teams,设置 CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 后重新安装。',
|
|
142
|
+
agents: teamDef.members
|
|
143
|
+
.filter(m => m.role !== 'lead')
|
|
144
|
+
.map(m => ({
|
|
145
|
+
name: m.name,
|
|
146
|
+
role: m.role,
|
|
147
|
+
agentFile: `.claude/agents/${m.agentDefinition}.md`,
|
|
148
|
+
prompt: m.prompt,
|
|
149
|
+
})),
|
|
150
|
+
upgrade: {
|
|
151
|
+
envVar: 'CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS',
|
|
152
|
+
command: 'npx prizmkit init # 重新安装以启用原生 Agent Teams',
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
await writeFile(
|
|
157
|
+
path.join(claudeDir, 'team-info.json'),
|
|
158
|
+
JSON.stringify(teamInfo, null, 2)
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* 安装团队配置到目标项目。
|
|
164
|
+
* 自动检测环境变量决定使用原生 Agent Teams 或 Subagent 模式。
|
|
165
|
+
*
|
|
166
|
+
* @param {Object} teamDef - 平台无关的团队定义
|
|
167
|
+
* @param {string} targetRoot - 目标项目根目录
|
|
168
|
+
* @returns {Promise<{ mode: string }>} - 安装的模式
|
|
169
|
+
*/
|
|
170
|
+
export async function installTeam(teamDef, targetRoot) {
|
|
171
|
+
const nativeMode = isNativeTeamsEnabled();
|
|
172
|
+
|
|
173
|
+
if (nativeMode) {
|
|
174
|
+
console.log(' ✓ Agent Teams 模式: 原生 (CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1)');
|
|
175
|
+
await installNativeTeam(teamDef, targetRoot);
|
|
176
|
+
return { mode: 'native-agent-teams' };
|
|
177
|
+
} else {
|
|
178
|
+
console.log(' ✓ Agent Teams 模式: Subagent (兜底模式)');
|
|
179
|
+
console.log(' 提示: 设置 CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 可启用原生 Agent Teams');
|
|
180
|
+
await installSubagentTeam(teamDef, targetRoot);
|
|
181
|
+
return { mode: 'subagent' };
|
|
182
|
+
}
|
|
183
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeBuddy Agent Adapter
|
|
3
|
+
* Converts core/ agent definitions to .codebuddy/agents/ format.
|
|
4
|
+
* For CodeBuddy, this is mostly pass-through as the core format matches.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { parseFrontmatter, buildMarkdown } from '../shared/frontmatter.js';
|
|
8
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
9
|
+
import { readFile, writeFile, symlink } from 'node:fs/promises';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Convert a core agent definition to CodeBuddy format.
|
|
14
|
+
* @param {string} agentContent - Content of the core agent .md
|
|
15
|
+
* @returns {string} - CodeBuddy-formatted agent .md content
|
|
16
|
+
*/
|
|
17
|
+
export function convertAgent(agentContent) {
|
|
18
|
+
// CodeBuddy format is already the native core format
|
|
19
|
+
return agentContent;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Install an agent definition to the target project.
|
|
24
|
+
* @param {string} corePath - Path to core/agents/<name>.md
|
|
25
|
+
* @param {string} targetRoot - Target project root
|
|
26
|
+
* @param {Object} options - { useSymlinks: boolean }
|
|
27
|
+
*/
|
|
28
|
+
export async function installAgent(corePath, targetRoot, options = {}) {
|
|
29
|
+
const filename = path.basename(corePath);
|
|
30
|
+
const targetDir = path.join(targetRoot, '.codebuddy', 'agents');
|
|
31
|
+
mkdirSync(targetDir, { recursive: true });
|
|
32
|
+
|
|
33
|
+
if (options.useSymlinks) {
|
|
34
|
+
const targetPath = path.join(targetDir, filename);
|
|
35
|
+
if (!existsSync(targetPath)) {
|
|
36
|
+
await symlink(corePath, targetPath);
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
const content = await readFile(corePath, 'utf8');
|
|
40
|
+
const converted = convertAgent(content);
|
|
41
|
+
await writeFile(path.join(targetDir, filename), converted);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeBuddy platform path constants and conventions.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export const PLATFORM_ID = 'codebuddy';
|
|
6
|
+
export const CLI_COMMAND = 'cbc';
|
|
7
|
+
|
|
8
|
+
// Project-level paths (relative to project root)
|
|
9
|
+
export const SKILLS_DIR = '.codebuddy/skills';
|
|
10
|
+
export const AGENTS_DIR = '.codebuddy/agents';
|
|
11
|
+
export const SETTINGS_FILE = '.codebuddy/settings.json';
|
|
12
|
+
export const PROJECT_MEMORY_FILE = 'CODEBUDDY.md';
|
|
13
|
+
|
|
14
|
+
// Global paths (relative to home directory)
|
|
15
|
+
export const GLOBAL_TEAMS_DIR = '.codebuddy/teams';
|
|
16
|
+
export const GLOBAL_CONFIG_DIR = '.codebuddy';
|
|
17
|
+
|
|
18
|
+
// Skill file conventions
|
|
19
|
+
export const SKILL_DEFINITION_FILE = 'SKILL.md';
|
|
20
|
+
export const SKILL_DIR_VAR = '${SKILL_DIR}';
|
|
21
|
+
|
|
22
|
+
// Agent definition format
|
|
23
|
+
export const AGENT_FILE_EXT = '.md';
|
|
24
|
+
|
|
25
|
+
// CLI flags
|
|
26
|
+
export const CLI_FLAGS = {
|
|
27
|
+
nonInteractive: '--print -y',
|
|
28
|
+
verbose: '--verbose',
|
|
29
|
+
};
|