prizmkit 1.1.143 → 1.1.145
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 +3 -3
- package/bundled/adapters/pi/paths.js +9 -0
- package/bundled/adapters/pi/rules-adapter.js +13 -0
- package/bundled/adapters/pi/settings-adapter.js +23 -0
- package/bundled/adapters/pi/skill-adapter.js +18 -0
- package/bundled/dev-pipeline/prizmkit_runtime/config.py +15 -3
- package/bundled/dev-pipeline/prizmkit_runtime/gitops.py +3 -1
- package/bundled/dev-pipeline/prizmkit_runtime/platform_detection.py +10 -2
- package/bundled/dev-pipeline/prizmkit_runtime/runner_bookkeeping.py +1 -0
- package/bundled/dev-pipeline/prizmkit_runtime/runner_recovery.py +1 -0
- package/bundled/dev-pipeline/prizmkit_runtime/sessions.py +26 -2
- package/bundled/dev-pipeline/scripts/parse-stream-progress.py +83 -7
- package/bundled/dev-pipeline/tests/test_unified_cli.py +117 -0
- package/bundled/skills/_metadata.json +1 -1
- package/bundled/skills/prizmkit-code-review/SKILL.md +3 -3
- package/bundled/skills/prizmkit-code-review/references/independent-code-review.md +63 -58
- package/bundled/skills/prizmkit-code-review/references/review-report-template.md +8 -1
- package/bundled/skills/prizmkit-plan/SKILL.md +3 -3
- package/bundled/skills/prizmkit-plan/assets/plan-template.md +3 -0
- package/bundled/skills/prizmkit-plan/references/independent-plan-review.md +55 -52
- package/bundled/skills/prizmkit-test/SKILL.md +3 -3
- package/bundled/skills/prizmkit-test/references/independent-test-review.md +68 -69
- package/bundled/skills/prizmkit-test/references/test-report-template.md +5 -1
- package/package.json +1 -1
- package/src/ai-cli-launch.js +1 -1
- package/src/clean.js +13 -4
- package/src/config.js +32 -5
- package/src/detect-platform.js +11 -7
- package/src/index.js +5 -0
- package/src/platforms.js +6 -2
- package/src/prompts.js +12 -4
- package/src/scaffold.js +72 -20
- package/src/upgrade.js +12 -5
package/src/scaffold.js
CHANGED
|
@@ -96,6 +96,7 @@ async function removeEmptyDirectory(dirPath) {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
export async function removeRetiredAgentTeamArtifacts(platform, projectRoot, dryRun) {
|
|
99
|
+
if (platform === 'pi') return;
|
|
99
100
|
const agentDir = platform === 'claude'
|
|
100
101
|
? path.join(projectRoot, '.claude', 'agents')
|
|
101
102
|
: platform === 'codex'
|
|
@@ -231,12 +232,16 @@ export async function installSkills(platform, skills, projectRoot, dryRun, runti
|
|
|
231
232
|
// Load Claude command adapter for skill conversion
|
|
232
233
|
let convertSkillToCommand;
|
|
233
234
|
let convertSkillToCodex;
|
|
235
|
+
let convertSkillToPi;
|
|
234
236
|
if (platform === 'claude') {
|
|
235
237
|
const commandAdapter = await loadAdapter('claude', 'command-adapter.js');
|
|
236
238
|
convertSkillToCommand = commandAdapter.convertSkillToCommand;
|
|
237
239
|
} else if (platform === 'codex') {
|
|
238
240
|
const codexSkillAdapter = await loadAdapter('codex', 'skill-adapter.js');
|
|
239
241
|
convertSkillToCodex = codexSkillAdapter.convertSkill;
|
|
242
|
+
} else if (platform === 'pi') {
|
|
243
|
+
const piSkillAdapter = await loadAdapter('pi', 'skill-adapter.js');
|
|
244
|
+
convertSkillToPi = piSkillAdapter.convertSkill;
|
|
240
245
|
}
|
|
241
246
|
|
|
242
247
|
for (const skillName of skills) {
|
|
@@ -347,6 +352,25 @@ export async function installSkills(platform, skills, projectRoot, dryRun, runti
|
|
|
347
352
|
}
|
|
348
353
|
}
|
|
349
354
|
console.log(chalk.green(` ✓ .agents/skills/${skillName}/`));
|
|
355
|
+
} else if (platform === 'pi') {
|
|
356
|
+
const content = await fs.readFile(skillMdPath, 'utf8');
|
|
357
|
+
const converted = convertSkillToPi(content, skillName);
|
|
358
|
+
const targetDir = path.join(projectRoot, '.pi', 'skills', skillName);
|
|
359
|
+
|
|
360
|
+
if (dryRun) {
|
|
361
|
+
console.log(chalk.gray(` [dry-run] .pi/skills/${skillName}/`));
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
await fs.remove(targetDir);
|
|
366
|
+
await fs.ensureDir(targetDir);
|
|
367
|
+
await fs.writeFile(path.join(targetDir, 'SKILL.md'), converted);
|
|
368
|
+
for (const entry of await fs.readdir(corePath, { withFileTypes: true })) {
|
|
369
|
+
if (entry.isDirectory()) {
|
|
370
|
+
await fs.copy(path.join(corePath, entry.name), path.join(targetDir, entry.name));
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
console.log(chalk.green(` ✓ .pi/skills/${skillName}/`));
|
|
350
374
|
}
|
|
351
375
|
}
|
|
352
376
|
}
|
|
@@ -503,6 +527,18 @@ job_max_runtime_seconds = 3300
|
|
|
503
527
|
await installCodexRules(projectRoot, ruleFiles);
|
|
504
528
|
removeLegacyCodexRules(projectRoot, allRuleFileNames);
|
|
505
529
|
console.log(chalk.green(` ✓ .agents/rules/ (${ruleFiles.length} 条规则)`));
|
|
530
|
+
} else if (platform === 'pi') {
|
|
531
|
+
if (dryRun) {
|
|
532
|
+
console.log(chalk.gray(' [dry-run] .pi/settings.json'));
|
|
533
|
+
console.log(chalk.gray(` [dry-run] .pi/rules/ (${ruleFiles.length} 条规则)`));
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
const { generateSettings } = await loadAdapter('pi', 'settings-adapter.js');
|
|
537
|
+
const { installRules } = await loadAdapter('pi', 'rules-adapter.js');
|
|
538
|
+
await generateSettings(projectRoot);
|
|
539
|
+
await installRules(projectRoot, ruleFiles);
|
|
540
|
+
console.log(chalk.green(' ✓ .pi/settings.json'));
|
|
541
|
+
console.log(chalk.green(` ✓ .pi/rules/ (${ruleFiles.length} 条规则)`));
|
|
506
542
|
}
|
|
507
543
|
}
|
|
508
544
|
|
|
@@ -927,11 +963,11 @@ export async function installProjectMemory(platform, projectRoot, dryRun) {
|
|
|
927
963
|
const templateName = 'project-memory-template.md';
|
|
928
964
|
const mainName = projectMemoryFile(platform);
|
|
929
965
|
const privateName = privateProjectMemoryFile(platform);
|
|
930
|
-
if (!
|
|
966
|
+
if (!privateName) return;
|
|
931
967
|
|
|
932
|
-
const mainPath = path.join(projectRoot, mainName);
|
|
968
|
+
const mainPath = mainName ? path.join(projectRoot, mainName) : null;
|
|
933
969
|
const privatePath = path.join(projectRoot, privateName);
|
|
934
|
-
const importPointer = `@./${privateName}
|
|
970
|
+
const importPointer = mainName ? `@./${privateName}` : null;
|
|
935
971
|
|
|
936
972
|
const templateCandidates = [
|
|
937
973
|
path.join(templatesDir, templateName),
|
|
@@ -944,7 +980,18 @@ export async function installProjectMemory(platform, projectRoot, dryRun) {
|
|
|
944
980
|
}
|
|
945
981
|
|
|
946
982
|
let templateContent = (await fs.readFile(templatePath, 'utf-8')).trimEnd();
|
|
947
|
-
if (platform === '
|
|
983
|
+
if (platform === 'pi') {
|
|
984
|
+
templateContent = templateContent.replace(
|
|
985
|
+
'### Available Commands\nRun `/prizmkit` to see all available PrizmKit commands.',
|
|
986
|
+
`### Available PrizmKit Skills
|
|
987
|
+
Pi discovers project skills from \`.pi/skills/\`. Invoke them with \`/skill:<name>\` (for example \`/skill:prizmkit-plan\`).
|
|
988
|
+
|
|
989
|
+
- Start with \`/skill:prizmkit\` to see all available PrizmKit skills.
|
|
990
|
+
- Skill assets and references live inside each \`.pi/skills/<skill>/\` directory.
|
|
991
|
+
- PrizmKit behavioral rules live in \`.pi/rules/\`; read the relevant Markdown guidance before commit, documentation, or context-loading work.
|
|
992
|
+
`
|
|
993
|
+
);
|
|
994
|
+
} else if (platform === 'codex') {
|
|
948
995
|
templateContent = templateContent.replace(
|
|
949
996
|
'### Available Commands\nRun `/prizmkit` to see all available PrizmKit commands.',
|
|
950
997
|
`### Available PrizmKit Skills
|
|
@@ -959,10 +1006,11 @@ Codex discovers repository skills from \`.agents/skills/\`. When a user or promp
|
|
|
959
1006
|
|
|
960
1007
|
if (dryRun) {
|
|
961
1008
|
console.log(chalk.gray(` [dry-run] ${privateName}`));
|
|
962
|
-
console.log(chalk.gray(` [dry-run] ${mainName} import ${importPointer}`));
|
|
1009
|
+
if (mainName) console.log(chalk.gray(` [dry-run] ${mainName} import ${importPointer}`));
|
|
963
1010
|
return;
|
|
964
1011
|
}
|
|
965
1012
|
|
|
1013
|
+
await fs.ensureDir(path.dirname(privatePath));
|
|
966
1014
|
if (!await fs.pathExists(privatePath)) {
|
|
967
1015
|
await fs.writeFile(privatePath, `${templateContent}\n`, 'utf-8');
|
|
968
1016
|
console.log(chalk.green(` ✓ ${privateName} (created PrizmKit section)`));
|
|
@@ -977,18 +1025,20 @@ Codex discovers repository skills from \`.agents/skills/\`. When a user or promp
|
|
|
977
1025
|
}
|
|
978
1026
|
}
|
|
979
1027
|
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
1028
|
+
if (mainPath && importPointer) {
|
|
1029
|
+
const existingMain = await fs.pathExists(mainPath)
|
|
1030
|
+
? await fs.readFile(mainPath, 'utf-8')
|
|
1031
|
+
: '';
|
|
1032
|
+
const mainMerge = ensureSingleImportPointer(existingMain, importPointer);
|
|
1033
|
+
logManagedProjectMemoryWarnings(mainName, mainMerge.warnings);
|
|
1034
|
+
const nextMain = mainMerge.content;
|
|
1035
|
+
if (nextMain !== existingMain) {
|
|
1036
|
+
await fs.writeFile(mainPath, nextMain, 'utf-8');
|
|
1037
|
+
const migrationSuffix = mainMerge.removedBlocks.length ? ' and migrated managed block' : '';
|
|
1038
|
+
console.log(chalk.green(` ✓ ${mainName} (imports ${privateName}${migrationSuffix})`));
|
|
1039
|
+
} else {
|
|
1040
|
+
console.log(chalk.green(` ✓ ${mainName} (import up-to-date)`));
|
|
1041
|
+
}
|
|
992
1042
|
}
|
|
993
1043
|
}
|
|
994
1044
|
|
|
@@ -1477,7 +1527,7 @@ export const EXTRAS_REGISTRY = {
|
|
|
1477
1527
|
/**
|
|
1478
1528
|
* 执行纯净安装
|
|
1479
1529
|
* @param {Object} config
|
|
1480
|
-
* @param {string} config.platform - 'codebuddy' | 'claude' | 'codex' | 'all'
|
|
1530
|
+
* @param {string} config.platform - 'codebuddy' | 'claude' | 'codex' | 'pi' | 'all'
|
|
1481
1531
|
* @param {string} [config.runtime] - 'python' (legacy aliases accepted: 'unix' | 'windows')
|
|
1482
1532
|
* @param {string} config.skills - 'core' | 'minimal' | 'recommended:<type>'
|
|
1483
1533
|
* @param {boolean} config.pipeline - 是否安装 dev-pipeline
|
|
@@ -1499,7 +1549,7 @@ export async function scaffold(config) {
|
|
|
1499
1549
|
});
|
|
1500
1550
|
const resolvedAiCli = launchSelection.aiCli;
|
|
1501
1551
|
if (!isKnownPlatform(platform)) {
|
|
1502
|
-
throw new Error(`Unknown platform "${platform}". Expected codebuddy, claude, codex, or all.`);
|
|
1552
|
+
throw new Error(`Unknown platform "${platform}". Expected codebuddy, claude, codex, pi, or all.`);
|
|
1503
1553
|
}
|
|
1504
1554
|
const platforms = expandPlatforms(platform);
|
|
1505
1555
|
const payloadPlatforms = resolvePayloadPlatforms(platform, resolvedAiCli);
|
|
@@ -1679,7 +1729,9 @@ export async function scaffold(config) {
|
|
|
1679
1729
|
console.log(` 2. ${chalk.cyan(cli)} ${chalk.gray('# 启动 AI 对话')}`);
|
|
1680
1730
|
const initInstruction = mainPlatform === 'codex'
|
|
1681
1731
|
? '说 "运行 prizmkit-init"'
|
|
1682
|
-
:
|
|
1732
|
+
: mainPlatform === 'pi'
|
|
1733
|
+
? '输入 "/skill:prizmkit-init"'
|
|
1734
|
+
: '说 "/prizmkit-init"';
|
|
1683
1735
|
console.log(` 3. ${chalk.cyan(initInstruction)} ${chalk.gray('# 初始化项目上下文')}`);
|
|
1684
1736
|
|
|
1685
1737
|
if (pipeline) {
|
package/src/upgrade.js
CHANGED
|
@@ -73,14 +73,16 @@ export async function removeSkillFiles(platform, projectRoot, skillNames, dryRun
|
|
|
73
73
|
console.log(chalk.red(` ✗ removed .codebuddy/skills/${skillName}/`));
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
-
} else if (platform === 'codex') {
|
|
77
|
-
const skillDir =
|
|
76
|
+
} else if (platform === 'codex' || platform === 'pi') {
|
|
77
|
+
const skillDir = platform === 'pi'
|
|
78
|
+
? path.join(projectRoot, '.pi', 'skills', skillName)
|
|
79
|
+
: path.join(projectRoot, '.agents', 'skills', skillName);
|
|
78
80
|
if (await fs.pathExists(skillDir)) {
|
|
79
81
|
if (dryRun) {
|
|
80
|
-
console.log(chalk.gray(` [dry-run] remove .
|
|
82
|
+
console.log(chalk.gray(` [dry-run] remove ${path.relative(projectRoot, skillDir)}/`));
|
|
81
83
|
} else {
|
|
82
84
|
await fs.remove(skillDir);
|
|
83
|
-
console.log(chalk.red(` ✗ removed .
|
|
85
|
+
console.log(chalk.red(` ✗ removed ${path.relative(projectRoot, skillDir)}/`));
|
|
84
86
|
}
|
|
85
87
|
}
|
|
86
88
|
}
|
|
@@ -91,6 +93,7 @@ export async function removeSkillFiles(platform, projectRoot, skillNames, dryRun
|
|
|
91
93
|
* Remove agent files for a specific platform.
|
|
92
94
|
*/
|
|
93
95
|
export async function removeAgentFiles(platform, projectRoot, agentFileNames, dryRun) {
|
|
96
|
+
if (platform === 'pi') return;
|
|
94
97
|
for (const fileName of agentFileNames) {
|
|
95
98
|
const dir = platform === 'claude'
|
|
96
99
|
? path.join(projectRoot, '.claude', 'agents')
|
|
@@ -124,7 +127,9 @@ export async function removeRuleFiles(platform, projectRoot, ruleFileNames, dryR
|
|
|
124
127
|
? path.join(projectRoot, '.claude', 'rules')
|
|
125
128
|
: platform === 'codex'
|
|
126
129
|
? path.join(projectRoot, '.agents', 'rules')
|
|
127
|
-
:
|
|
130
|
+
: platform === 'pi'
|
|
131
|
+
? path.join(projectRoot, '.pi', 'rules')
|
|
132
|
+
: path.join(projectRoot, '.codebuddy', 'rules');
|
|
128
133
|
// Rules are stored as .md for claude, .mdc for codebuddy
|
|
129
134
|
const targetName = platform === 'codebuddy'
|
|
130
135
|
? baseName.replace(/\.md$/, '.mdc')
|
|
@@ -243,11 +248,13 @@ export async function runUpgrade(directory, options = {}) {
|
|
|
243
248
|
const hasClaude = await hasPlatformFiles(path.join(projectRoot, '.claude', 'commands'));
|
|
244
249
|
const hasCodeBuddy = await hasPlatformFiles(path.join(projectRoot, '.codebuddy', 'skills'));
|
|
245
250
|
const hasCodex = await hasPlatformFiles(path.join(projectRoot, '.agents', 'skills'));
|
|
251
|
+
const hasPi = await hasPlatformFiles(path.join(projectRoot, '.pi', 'skills'));
|
|
246
252
|
|
|
247
253
|
const detectedPlatforms = [
|
|
248
254
|
hasCodeBuddy && 'codebuddy',
|
|
249
255
|
hasClaude && 'claude',
|
|
250
256
|
hasCodex && 'codex',
|
|
257
|
+
hasPi && 'pi',
|
|
251
258
|
].filter(Boolean);
|
|
252
259
|
|
|
253
260
|
if (detectedPlatforms.length > 1) platform = 'all';
|