prizmkit 1.1.112 → 1.1.114

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.
Files changed (48) hide show
  1. package/bundled/VERSION.json +3 -3
  2. package/bundled/adapters/codex/skill-adapter.js +4 -0
  3. package/bundled/dev-pipeline/SCHEMA_ANALYSIS.md +10 -10
  4. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +1 -0
  5. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +7 -0
  6. package/bundled/dev-pipeline/scripts/utils.py +8 -3
  7. package/bundled/dev-pipeline/templates/bootstrap-tier1.md +7 -1
  8. package/bundled/dev-pipeline/templates/bootstrap-tier2.md +7 -1
  9. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +7 -1
  10. package/bundled/dev-pipeline/templates/sections/bugfix-phase-commit-report.md +1 -1
  11. package/bundled/dev-pipeline/templates/sections/phase-browser-verification-auto.md +7 -1
  12. package/bundled/dev-pipeline/templates/sections/phase-browser-verification-opencli.md +7 -1
  13. package/bundled/dev-pipeline/templates/sections/phase-browser-verification.md +7 -1
  14. package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +87 -21
  15. package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +14 -0
  16. package/bundled/dev-pipeline/tests/test_python_runner_parity.py +42 -0
  17. package/bundled/dev-pipeline/tests/test_runtime_helper.py +23 -0
  18. package/bundled/skills/_metadata.json +1 -1
  19. package/bundled/skills/app-planner/SKILL.md +18 -2
  20. package/bundled/skills/app-planner/references/generated-plan-review.md +67 -0
  21. package/bundled/skills/bug-planner/SKILL.md +19 -24
  22. package/bundled/skills/bug-planner/references/generated-plan-review.md +63 -0
  23. package/bundled/skills/bug-planner/scripts/validate-bug-list.py +43 -3
  24. package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +6 -6
  25. package/bundled/skills/feature-pipeline-launcher/SKILL.md +7 -16
  26. package/bundled/skills/feature-planner/SKILL.md +17 -22
  27. package/bundled/skills/feature-planner/references/generated-plan-review.md +63 -0
  28. package/bundled/skills/feature-workflow/SKILL.md +8 -7
  29. package/bundled/skills/prizmkit-code-review/references/reviewer-agent-prompt.md +2 -2
  30. package/bundled/skills/prizmkit-deploy/references/database-setup.md +12 -3
  31. package/bundled/skills/prizmkit-init/SKILL.md +2 -2
  32. package/bundled/skills/prizmkit-prizm-docs/references/op-init.md +12 -14
  33. package/bundled/skills/prizmkit-test/SKILL.md +1 -1
  34. package/bundled/skills/prizmkit-test/references/boundary-coverage-protocol.md +1 -1
  35. package/bundled/skills/prizmkit-test/references/examples.md +2 -2
  36. package/bundled/skills/refactor-pipeline-launcher/SKILL.md +3 -2
  37. package/bundled/skills/refactor-planner/SKILL.md +20 -26
  38. package/bundled/skills/refactor-planner/references/fast-path.md +2 -2
  39. package/bundled/skills/refactor-planner/references/generated-plan-review.md +63 -0
  40. package/bundled/skills/refactor-workflow/SKILL.md +6 -5
  41. package/package.json +1 -1
  42. package/src/clean.js +60 -7
  43. package/src/config.js +61 -20
  44. package/src/gitignore-template.js +6 -3
  45. package/src/manifest.js +6 -2
  46. package/src/platforms.js +14 -0
  47. package/src/scaffold.js +198 -34
  48. package/src/upgrade.js +5 -2
package/src/scaffold.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  } from './metadata.js';
28
28
  import { generateGitignore } from './gitignore-template.js';
29
29
  import { buildManifest, writeManifest } from './manifest.js';
30
- import { defaultCliForPlatform, expandPlatforms, isKnownPlatform, platformLabel, projectMemoryFile, resolvePayloadPlatforms } from './platforms.js';
30
+ import { defaultCliForPlatform, expandPlatforms, isKnownPlatform, platformLabel, privateProjectMemoryFile, privateProjectMemoryFiles, projectMemoryFile, resolvePayloadPlatforms } from './platforms.js';
31
31
  import { normalizeRuntime, runtimeLabel } from './runtimes.js';
32
32
  import { applyAiCliLaunchToConfig, resolveAiCliLaunchSelection } from './ai-cli-launch.js';
33
33
 
@@ -869,20 +869,175 @@ export async function installPrizmkitScripts(projectRoot, dryRun, runtime = 'pyt
869
869
  const PRIZMKIT_MARKER_START = '<!-- PRIZMKIT:START';
870
870
  const PRIZMKIT_MARKER_END = '<!-- PRIZMKIT:END -->';
871
871
 
872
+ function extendManagedBlockEnd(content, endIdx) {
873
+ if (content.slice(endIdx, endIdx + 2) === '\r\n') return endIdx + 2;
874
+ if (content[endIdx] === '\n' || content[endIdx] === '\r') return endIdx + 1;
875
+ return endIdx;
876
+ }
877
+
878
+ function markerPositions(content, marker) {
879
+ const positions = [];
880
+ let cursor = 0;
881
+ while (cursor < content.length) {
882
+ const idx = content.indexOf(marker, cursor);
883
+ if (idx === -1) break;
884
+ positions.push(idx);
885
+ cursor = idx + marker.length;
886
+ }
887
+ return positions;
888
+ }
889
+
890
+ function positionInBlocks(position, blocks) {
891
+ return blocks.some(block => position >= block.start && position < block.end);
892
+ }
893
+
894
+ export function analyzeManagedProjectMemoryBlocks(content) {
895
+ const blocks = [];
896
+ const warnings = new Set();
897
+ let cursor = 0;
898
+
899
+ while (cursor < content.length) {
900
+ const startIdx = content.indexOf(PRIZMKIT_MARKER_START, cursor);
901
+ if (startIdx === -1) break;
902
+
903
+ const nextStartIdx = content.indexOf(PRIZMKIT_MARKER_START, startIdx + PRIZMKIT_MARKER_START.length);
904
+ const endMarkerIdx = content.indexOf(PRIZMKIT_MARKER_END, startIdx + PRIZMKIT_MARKER_START.length);
905
+
906
+ if (endMarkerIdx === -1) {
907
+ warnings.add('PRIZMKIT:START without PRIZMKIT:END');
908
+ cursor = startIdx + PRIZMKIT_MARKER_START.length;
909
+ continue;
910
+ }
911
+
912
+ if (nextStartIdx !== -1 && nextStartIdx < endMarkerIdx) {
913
+ warnings.add('nested PRIZMKIT:START before PRIZMKIT:END');
914
+ cursor = endMarkerIdx + PRIZMKIT_MARKER_END.length;
915
+ continue;
916
+ }
917
+
918
+ const rawEnd = endMarkerIdx + PRIZMKIT_MARKER_END.length;
919
+ const blockEnd = extendManagedBlockEnd(content, rawEnd);
920
+ blocks.push({
921
+ start: startIdx,
922
+ end: blockEnd,
923
+ text: content.slice(startIdx, blockEnd),
924
+ });
925
+ cursor = blockEnd;
926
+ }
927
+
928
+ for (const endIdx of markerPositions(content, PRIZMKIT_MARKER_END)) {
929
+ if (!positionInBlocks(endIdx, blocks)) {
930
+ warnings.add('PRIZMKIT:END without matching PRIZMKIT:START');
931
+ }
932
+ }
933
+
934
+ return { blocks, warnings: [...warnings] };
935
+ }
936
+
937
+ export function removeManagedProjectMemoryBlocks(content) {
938
+ const analysis = analyzeManagedProjectMemoryBlocks(content);
939
+ if (!analysis.blocks.length) {
940
+ return { content, removedBlocks: [], warnings: analysis.warnings };
941
+ }
942
+
943
+ let cursor = 0;
944
+ let nextContent = '';
945
+ for (const block of analysis.blocks) {
946
+ nextContent += content.slice(cursor, block.start);
947
+ cursor = block.end;
948
+ }
949
+ nextContent += content.slice(cursor);
950
+
951
+ return {
952
+ content: nextContent.replace(/\n{3,}/g, '\n\n'),
953
+ removedBlocks: analysis.blocks.map(block => block.text),
954
+ warnings: analysis.warnings,
955
+ };
956
+ }
957
+
958
+ export function normalizeMainProjectMemoryContent(content, privateFile) {
959
+ const removal = removeManagedProjectMemoryBlocks(content);
960
+ const importPointer = privateFile ? `@./${privateFile}` : null;
961
+ const nextContent = removal.content
962
+ .split(/\r?\n/)
963
+ .filter(line => !importPointer || line.trim() !== importPointer)
964
+ .join('\n')
965
+ .replace(/\n{3,}/g, '\n\n')
966
+ .trimEnd();
967
+
968
+ return {
969
+ content: nextContent,
970
+ removedBlocks: removal.removedBlocks,
971
+ warnings: removal.warnings,
972
+ };
973
+ }
974
+
975
+ function mergeManagedProjectMemoryBlock(existing, templateContent) {
976
+ const analysis = analyzeManagedProjectMemoryBlocks(existing);
977
+
978
+ if (analysis.blocks.length) {
979
+ let cursor = 0;
980
+ let merged = '';
981
+ let inserted = false;
982
+ for (const block of analysis.blocks) {
983
+ merged += existing.slice(cursor, block.start);
984
+ if (!inserted) {
985
+ merged += `${templateContent}\n`;
986
+ inserted = true;
987
+ }
988
+ cursor = block.end;
989
+ }
990
+ merged += existing.slice(cursor);
991
+ logManagedProjectMemoryWarnings('private memory', analysis.warnings);
992
+ return merged.replace(/\n{3,}/g, '\n\n').trimEnd() + '\n';
993
+ }
994
+
995
+ const trimmed = existing.trimEnd();
996
+ if (analysis.warnings.length) {
997
+ logManagedProjectMemoryWarnings('private memory', analysis.warnings);
998
+ if (trimmed.includes(templateContent)) return `${trimmed}\n`;
999
+ }
1000
+ if (!trimmed) return `${templateContent}\n`;
1001
+
1002
+ return `${trimmed}\n\n${templateContent}\n`;
1003
+ }
1004
+
1005
+ function ensureSingleImportPointer(existing, importPointer) {
1006
+ const cleaned = removeManagedProjectMemoryBlocks(existing);
1007
+ const lines = cleaned.content.split(/\r?\n/).filter(line => line.trim() !== importPointer);
1008
+ const base = lines.join('\n').replace(/\n{3,}/g, '\n\n').trimEnd();
1009
+ const content = base ? `${base}\n\n${importPointer}\n` : `${importPointer}\n`;
1010
+ return {
1011
+ content,
1012
+ removedBlocks: cleaned.removedBlocks,
1013
+ warnings: cleaned.warnings,
1014
+ };
1015
+ }
1016
+
1017
+ function logManagedProjectMemoryWarnings(memoryFile, warnings) {
1018
+ for (const warning of warnings) {
1019
+ console.log(chalk.yellow(` ⚠ ${memoryFile}: ${warning}; preserving unmatched marker content`));
1020
+ }
1021
+ }
1022
+
872
1023
  /**
873
- * Merge PrizmKit template content into a project memory file.
874
- * - File missing → create with template content
875
- * - File exists with markers → replace content between markers
876
- * - File exists without markers → append template content
1024
+ * Install PrizmKit framework memory as a private imported file.
1025
+ * - Private file missing → create with managed template content
1026
+ * - Private file exists with markers → replace content between markers
1027
+ * - Private file exists without markers → append managed template content
1028
+ * - Main memory file stays user-owned and contains exactly one import pointer
877
1029
  */
878
1030
  export async function installProjectMemory(platform, projectRoot, dryRun) {
879
1031
  const templatesDir = getTemplatesDir();
880
1032
  const templateName = 'project-memory-template.md';
881
- const targetName = projectMemoryFile(platform);
882
- if (!targetName) return;
883
- const targetPath = path.join(projectRoot, targetName);
1033
+ const mainName = projectMemoryFile(platform);
1034
+ const privateName = privateProjectMemoryFile(platform);
1035
+ if (!mainName || !privateName) return;
1036
+
1037
+ const mainPath = path.join(projectRoot, mainName);
1038
+ const privatePath = path.join(projectRoot, privateName);
1039
+ const importPointer = `@./${privateName}`;
884
1040
 
885
- // Template lives in core/templates/ (bundled as templates/).
886
1041
  const templateCandidates = [
887
1042
  path.join(templatesDir, templateName),
888
1043
  ];
@@ -908,34 +1063,37 @@ Codex discovers repository skills from \`.agents/skills/\`. When a user or promp
908
1063
  }
909
1064
 
910
1065
  if (dryRun) {
911
- console.log(chalk.gray(` [dry-run] ${targetName}`));
1066
+ console.log(chalk.gray(` [dry-run] ${privateName}`));
1067
+ console.log(chalk.gray(` [dry-run] ${mainName} import ${importPointer}`));
912
1068
  return;
913
1069
  }
914
1070
 
915
- if (!await fs.pathExists(targetPath)) {
916
- // File doesn't exist — create with template content
917
- await fs.writeFile(targetPath, templateContent + '\n', 'utf-8');
918
- console.log(chalk.green(` ✓ ${targetName} (created)`));
919
- return;
1071
+ if (!await fs.pathExists(privatePath)) {
1072
+ await fs.writeFile(privatePath, `${templateContent}\n`, 'utf-8');
1073
+ console.log(chalk.green(` ✓ ${privateName} (created PrizmKit section)`));
1074
+ } else {
1075
+ const existingPrivate = await fs.readFile(privatePath, 'utf-8');
1076
+ const mergedPrivate = mergeManagedProjectMemoryBlock(existingPrivate, templateContent);
1077
+ if (mergedPrivate !== existingPrivate) {
1078
+ await fs.writeFile(privatePath, mergedPrivate, 'utf-8');
1079
+ console.log(chalk.green(` ✓ ${privateName} (updated PrizmKit section)`));
1080
+ } else {
1081
+ console.log(chalk.green(` ✓ ${privateName} (up-to-date)`));
1082
+ }
920
1083
  }
921
1084
 
922
- // File exists merge via markers
923
- const existing = await fs.readFile(targetPath, 'utf-8');
924
- const startIdx = existing.indexOf(PRIZMKIT_MARKER_START);
925
- const endIdx = existing.indexOf(PRIZMKIT_MARKER_END);
926
-
927
- if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
928
- // Replace content between markers (inclusive)
929
- const before = existing.substring(0, startIdx);
930
- const after = existing.substring(endIdx + PRIZMKIT_MARKER_END.length);
931
- const merged = before + templateContent + after;
932
- await fs.writeFile(targetPath, merged, 'utf-8');
933
- console.log(chalk.green(` ✓ ${targetName} (updated PrizmKit section)`));
1085
+ const existingMain = await fs.pathExists(mainPath)
1086
+ ? await fs.readFile(mainPath, 'utf-8')
1087
+ : '';
1088
+ const mainMerge = ensureSingleImportPointer(existingMain, importPointer);
1089
+ logManagedProjectMemoryWarnings(mainName, mainMerge.warnings);
1090
+ const nextMain = mainMerge.content;
1091
+ if (nextMain !== existingMain) {
1092
+ await fs.writeFile(mainPath, nextMain, 'utf-8');
1093
+ const migrationSuffix = mainMerge.removedBlocks.length ? ' and migrated managed block' : '';
1094
+ console.log(chalk.green(` ✓ ${mainName} (imports ${privateName}${migrationSuffix})`));
934
1095
  } else {
935
- // No markers found — append template content
936
- const separator = existing.endsWith('\n') ? '\n' : '\n\n';
937
- await fs.writeFile(targetPath, existing + separator + templateContent + '\n', 'utf-8');
938
- console.log(chalk.green(` ✓ ${targetName} (appended PrizmKit section)`));
1096
+ console.log(chalk.green(` ✓ ${mainName} (import up-to-date)`));
939
1097
  }
940
1098
  }
941
1099
 
@@ -1166,9 +1324,12 @@ export async function installPipeline(projectRoot, dryRun, options = {}) {
1166
1324
  /**
1167
1325
  * 生成 .gitignore
1168
1326
  */
1169
- export async function installGitignore(projectRoot, options, dryRun) {
1327
+ export async function installGitignore(projectRoot, options = {}, dryRun) {
1170
1328
  const targetPath = path.join(projectRoot, '.gitignore');
1171
- const templateContent = generateGitignore({ pipeline: options.pipeline });
1329
+ const templateContent = generateGitignore({
1330
+ pipeline: options.pipeline,
1331
+ privateMemoryFiles: options.privateMemoryFiles || [],
1332
+ });
1172
1333
 
1173
1334
  if (dryRun) {
1174
1335
  console.log(chalk.gray(` [dry-run] .gitignore`));
@@ -1496,7 +1657,10 @@ export async function scaffold(config) {
1496
1657
 
1497
1658
  // 7. .gitignore
1498
1659
  console.log(chalk.blue(' 项目配置:'));
1499
- await installGitignore(projectRoot, { pipeline }, dryRun);
1660
+ await installGitignore(projectRoot, {
1661
+ pipeline,
1662
+ privateMemoryFiles: privateProjectMemoryFiles(payloadPlatforms),
1663
+ }, dryRun);
1500
1664
 
1501
1665
  // 8. 写入 .prizmkit/config.json(如果指定了 aiCli)
1502
1666
  if (resolvedAiCli) {
package/src/upgrade.js CHANGED
@@ -35,7 +35,7 @@ import {
35
35
  resolveSkillList,
36
36
  EXTRAS_REGISTRY,
37
37
  } from './scaffold.js';
38
- import { platformLabel, resolvePayloadPlatforms } from './platforms.js';
38
+ import { platformLabel, privateProjectMemoryFiles, resolvePayloadPlatforms } from './platforms.js';
39
39
  import { normalizeRuntime, runtimeLabel } from './runtimes.js';
40
40
 
41
41
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -432,7 +432,10 @@ export async function runUpgrade(directory, options = {}) {
432
432
 
433
433
  // .gitignore
434
434
  console.log(chalk.blue(' Gitignore:'));
435
- await installGitignore(projectRoot, { pipeline }, dryRun);
435
+ await installGitignore(projectRoot, {
436
+ pipeline,
437
+ privateMemoryFiles: privateProjectMemoryFiles(payloadPlatforms),
438
+ }, dryRun);
436
439
 
437
440
  // PrizmKit scripts
438
441
  console.log(chalk.blue(' PrizmKit Scripts:'));