@openprd/cli 0.1.11 → 0.1.19

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 (147) hide show
  1. package/.openprd/changes/adaptive-project-framing/.openprd.yaml +2 -0
  2. package/.openprd/changes/adaptive-project-framing/design.md +47 -0
  3. package/.openprd/changes/adaptive-project-framing/proposal.md +35 -0
  4. package/.openprd/changes/adaptive-project-framing/specs/agent-requirements/spec.md +16 -0
  5. package/.openprd/changes/adaptive-project-framing/task-events.jsonl +20 -0
  6. package/.openprd/changes/adaptive-project-framing/tasks.md +340 -0
  7. package/.openprd/changes/docs-anti-pollution-and-design-direction-review/.openprd.yaml +2 -0
  8. package/.openprd/changes/docs-anti-pollution-and-design-direction-review/design.md +34 -0
  9. package/.openprd/changes/docs-anti-pollution-and-design-direction-review/proposal.md +23 -0
  10. package/.openprd/changes/docs-anti-pollution-and-design-direction-review/specs/agent-requirements/spec.md +16 -0
  11. package/.openprd/changes/docs-anti-pollution-and-design-direction-review/task-events.jsonl +14 -0
  12. package/.openprd/changes/docs-anti-pollution-and-design-direction-review/tasks.md +238 -0
  13. package/.openprd/changes/loop-isolated-worktree-commit/.openprd.yaml +2 -0
  14. package/.openprd/changes/loop-isolated-worktree-commit/design.md +53 -0
  15. package/.openprd/changes/loop-isolated-worktree-commit/proposal.md +38 -0
  16. package/.openprd/changes/loop-isolated-worktree-commit/specs/agent-requirements/spec.md +16 -0
  17. package/.openprd/changes/loop-isolated-worktree-commit/task-events.jsonl +22 -0
  18. package/.openprd/changes/loop-isolated-worktree-commit/tasks.md +357 -0
  19. package/.openprd/changes/openprd/.openprd.yaml +2 -0
  20. package/.openprd/changes/openprd/design.md +46 -0
  21. package/.openprd/changes/openprd/proposal.md +36 -0
  22. package/.openprd/changes/openprd/specs/agent-requirements/spec.md +16 -0
  23. package/.openprd/changes/openprd/task-events.jsonl +23 -0
  24. package/.openprd/changes/openprd/tasks.md +242 -0
  25. package/.openprd/changes/openprd-generated-change/.openprd.yaml +2 -0
  26. package/.openprd/changes/openprd-generated-change/design.md +50 -0
  27. package/.openprd/changes/openprd-generated-change/proposal.md +37 -0
  28. package/.openprd/changes/openprd-generated-change/specs/agent-requirements/spec.md +16 -0
  29. package/.openprd/changes/openprd-generated-change/task-events.jsonl +21 -0
  30. package/.openprd/changes/openprd-generated-change/tasks.md +357 -0
  31. package/.openprd/changes/pm-human-in-the-loop/.openprd.yaml +2 -0
  32. package/.openprd/changes/pm-human-in-the-loop/design.md +38 -0
  33. package/.openprd/changes/pm-human-in-the-loop/proposal.md +29 -0
  34. package/.openprd/changes/pm-human-in-the-loop/specs/agent-requirements/spec.md +16 -0
  35. package/.openprd/changes/pm-human-in-the-loop/task-events.jsonl +18 -0
  36. package/.openprd/changes/pm-human-in-the-loop/tasks.md +306 -0
  37. package/.openprd/changes/test-strategy-router/.openprd.yaml +2 -0
  38. package/.openprd/changes/test-strategy-router/design.md +65 -0
  39. package/.openprd/changes/test-strategy-router/proposal.md +45 -0
  40. package/.openprd/changes/test-strategy-router/specs/agent-requirements/spec.md +16 -0
  41. package/.openprd/changes/test-strategy-router/task-events.jsonl +1 -0
  42. package/.openprd/changes/test-strategy-router/tasks.md +132 -0
  43. package/.openprd/changes/verify-boundaries-and-historical-refresh/.openprd.yaml +2 -0
  44. package/.openprd/changes/verify-boundaries-and-historical-refresh/design.md +28 -0
  45. package/.openprd/changes/verify-boundaries-and-historical-refresh/proposal.md +23 -0
  46. package/.openprd/changes/verify-boundaries-and-historical-refresh/specs/agent-requirements/spec.md +16 -0
  47. package/.openprd/changes/verify-boundaries-and-historical-refresh/task-events.jsonl +11 -0
  48. package/.openprd/changes/verify-boundaries-and-historical-refresh/tasks.md +66 -0
  49. package/.openprd/changes/vibe-coding-dev-check/.openprd.yaml +2 -0
  50. package/.openprd/changes/vibe-coding-dev-check/design.md +37 -0
  51. package/.openprd/changes/vibe-coding-dev-check/proposal.md +28 -0
  52. package/.openprd/changes/vibe-coding-dev-check/specs/agent-requirements/spec.md +16 -0
  53. package/.openprd/changes/vibe-coding-dev-check/task-events.jsonl +18 -0
  54. package/.openprd/changes/vibe-coding-dev-check/tasks.md +306 -0
  55. package/.openprd/design/README.md +11 -6
  56. package/.openprd/design/README_EN.md +4 -1
  57. package/.openprd/design/active/asset-spec.md +6 -0
  58. package/.openprd/design/active/direction-plan.md +5 -5
  59. package/.openprd/design/active/selected-direction.md +2 -0
  60. package/.openprd/design/anti-slop.md +26 -1
  61. package/.openprd/design/assets/surface-presets.md +6 -0
  62. package/.openprd/design/checklists/ui-quality-gate.md +7 -0
  63. package/.openprd/design/lenses/frontend-lenses.md +28 -0
  64. package/.openprd/design/recipes/content-experience.md +8 -1
  65. package/.openprd/design/recipes/operational-tool.md +7 -0
  66. package/.openprd/design/recipes/product-launch.md +8 -1
  67. package/.openprd/design/templates/README.md +6 -3
  68. package/.openprd/design/templates/README_EN.md +6 -3
  69. package/.openprd/design/templates/ops-dashboard.html +8 -1
  70. package/.openprd/design/templates/product-launch.html +2 -1
  71. package/.openprd/design/themes/theme-catalog.json +23 -5
  72. package/.openprd/engagements/active/prd.md +137 -112
  73. package/.openprd/standards/config.json +7 -1
  74. package/AGENTS.md +13 -3
  75. package/README.md +127 -14
  76. package/README_EN.md +156 -13
  77. package/package.json +1 -1
  78. package/scripts/dev-check-wrapup-copy.mjs +46 -21
  79. package/skills/openprd-diagram-review/SKILL.md +27 -2
  80. package/skills/openprd-diagram-review/references/explanation-svg-patterns.md +131 -0
  81. package/skills/openprd-discovery-loop/SKILL.md +2 -2
  82. package/skills/openprd-frontend-design/SKILL.md +44 -20
  83. package/skills/openprd-frontend-design/references/design-asset-contract.md +6 -0
  84. package/skills/openprd-frontend-design/references/direction-engine.md +29 -4
  85. package/skills/openprd-harness/SKILL.md +22 -16
  86. package/skills/openprd-quality/SKILL.md +10 -8
  87. package/skills/openprd-requirement-intake/SKILL.md +2 -0
  88. package/skills/openprd-router/SKILL.md +2 -1
  89. package/skills/openprd-shared/SKILL.md +26 -16
  90. package/skills/openprd-standards/SKILL.md +4 -2
  91. package/src/agent-canonical-content.js +810 -0
  92. package/src/agent-integration.js +258 -777
  93. package/src/canvas-app-client-app.js +838 -0
  94. package/src/canvas-app-client-helpers.js +1138 -0
  95. package/src/canvas-app-styles.js +898 -0
  96. package/src/canvas-app.html.js +135 -0
  97. package/src/canvas-binding.js +414 -0
  98. package/src/canvas-codex-relay.js +430 -0
  99. package/src/canvas-i18n.js +282 -0
  100. package/src/canvas-scene.js +377 -0
  101. package/src/canvas-session-store.js +148 -0
  102. package/src/canvas-workspace.js +1264 -0
  103. package/src/cli/args.js +72 -4
  104. package/src/cli/basic-print.js +3 -0
  105. package/src/cli/canvas-print.js +106 -0
  106. package/src/cli/doctor-print.js +20 -0
  107. package/src/cli/print.js +2 -0
  108. package/src/cli/quality-commands.js +222 -0
  109. package/src/cli/quality-print.js +28 -2
  110. package/src/cli/run-print.js +5 -0
  111. package/src/cli/workflow-print.js +3 -0
  112. package/src/codex-app-server-relay.js +251 -0
  113. package/src/codex-hook-runner-template.mjs +978 -58
  114. package/src/design-starter-support.js +2 -2
  115. package/src/design-starter.js +39 -3
  116. package/src/dev-standards.js +125 -10
  117. package/src/diagram-core.js +6 -20
  118. package/src/discovery.js +2 -8
  119. package/src/docs-compact.js +125 -0
  120. package/src/execution-strategy.js +1 -1
  121. package/src/fleet.js +9 -3
  122. package/src/guide.js +227 -0
  123. package/src/html-artifacts.js +428 -7
  124. package/src/knowledge.js +45 -11
  125. package/src/language-policy.js +63 -3
  126. package/src/learning-review.js +1 -1
  127. package/src/loop.js +1 -1
  128. package/src/openprd.js +68 -131
  129. package/src/openspec/change-validate.js +2 -2
  130. package/src/openspec/constants.js +6 -7
  131. package/src/openspec/execute.js +2 -2
  132. package/src/openspec/generate.js +318 -102
  133. package/src/openspec/migration.js +168 -0
  134. package/src/openspec/paths.js +1 -22
  135. package/src/prd-core.js +1 -1
  136. package/src/quality-visual-review.js +257 -14
  137. package/src/quality.js +46 -8
  138. package/src/review-presentation.js +60 -0
  139. package/src/run-harness.js +41 -3
  140. package/src/session-evidence.js +363 -0
  141. package/src/standards.js +64 -0
  142. package/src/test-strategy.js +7 -4
  143. package/src/visual-compare-centering.js +622 -0
  144. package/src/visual-compare-core.js +1123 -0
  145. package/src/visual-compare.js +620 -698
  146. package/src/workspace-core.js +94 -4
  147. package/src/workspace-workflow.js +46 -1
package/src/standards.js CHANGED
@@ -773,6 +773,42 @@ export async function initStandardsWorkspace(projectRoot, options = {}) {
773
773
  };
774
774
  }
775
775
 
776
+ export const DOC_MEGA_LINE_CHARS = 300;
777
+ export const DOC_AVG_LINE_CHARS = 200;
778
+ export const DOC_STALE_VERSION_THRESHOLD = 20;
779
+
780
+ export function analyzeDocQuality(relativePath, text) {
781
+ const lines = text.split('\n');
782
+ const contentLines = lines.filter((line) => line.trim().length > 0);
783
+ const megaLines = contentLines.filter((line) => line.length > DOC_MEGA_LINE_CHARS);
784
+ const totalChars = contentLines.reduce((sum, line) => sum + line.length, 0);
785
+ const avgLineChars = contentLines.length > 0 ? Math.round(totalChars / contentLines.length) : 0;
786
+ const maxLineChars = contentLines.reduce((max, line) => Math.max(max, line.length), 0);
787
+ return {
788
+ path: relativePath,
789
+ lines: lines.length,
790
+ contentLines: contentLines.length,
791
+ megaLines: megaLines.length,
792
+ avgLineChars,
793
+ maxLineChars,
794
+ bytes: Buffer.byteLength(text, 'utf8'),
795
+ };
796
+ }
797
+
798
+ export async function analyzeDocStaleness(projectRoot, docMtimeMs) {
799
+ const versionsDir = cjoin(projectRoot, '.openprd', 'state', 'versions');
800
+ const entries = await fs.readdir(versionsDir).catch(() => []);
801
+ const versionFiles = entries.filter((name) => /^v\d+\.json$/.test(name)).sort();
802
+ let versionsBehind = 0;
803
+ for (const name of versionFiles) {
804
+ const stat = await fs.stat(cjoin(versionsDir, name)).catch(() => null);
805
+ if (stat && stat.mtimeMs > docMtimeMs) {
806
+ versionsBehind += 1;
807
+ }
808
+ }
809
+ return { totalVersions: versionFiles.length, versionsBehind };
810
+ }
811
+
776
812
  export async function checkStandardsWorkspace(projectRoot, options = {}) {
777
813
  const errors = [];
778
814
  const warnings = [];
@@ -838,6 +874,7 @@ export async function checkStandardsWorkspace(projectRoot, options = {}) {
838
874
  ...externalReferenceIgnorePatterns(projectRoot, config ?? {}),
839
875
  ];
840
876
  const requiredDocs = [];
877
+ const docsQuality = [];
841
878
  const sourceFiles = await collectSourceFiles(projectRoot, projectRoot, [], ignorePatterns);
842
879
  const hasProjectSource = sourceFiles.length > 0;
843
880
  const openPrdToolProject = await isOpenPrdToolProject(projectRoot);
@@ -860,6 +897,28 @@ export async function checkStandardsWorkspace(projectRoot, options = {}) {
860
897
  if (hasProjectSource && !openPrdToolProject && options.docsContent !== false && DOC_PLACEHOLDER_PATTERNS.some((pattern) => pattern.test(text))) {
861
898
  errors.push(`${relativePath} 仍包含模板占位内容,必须更新为当前项目事实。`);
862
899
  }
900
+
901
+ if (options.docsQuality !== false) {
902
+ const quality = analyzeDocQuality(relativePath, text);
903
+ if (quality.megaLines > 0) {
904
+ warnings.push(`${relativePath} 存在 ${quality.megaLines} 行超过 ${DOC_MEGA_LINE_CHARS} 字符的巨行(最长 ${quality.maxLineChars} 字符),疑似 append-only 污染,建议运行 openprd docs-compact . 查看压缩建议。`);
905
+ }
906
+ if (quality.contentLines >= 10 && quality.avgLineChars > DOC_AVG_LINE_CHARS) {
907
+ warnings.push(`${relativePath} 平均行长 ${quality.avgLineChars} 字符(阈值 ${DOC_AVG_LINE_CHARS}),文档结构疑似退化为长段落堆叠,建议拆分为结构化小节。`);
908
+ }
909
+ if (doc.fileName === 'prd.md') {
910
+ const docStat = await fs.stat(docPath).catch(() => null);
911
+ if (docStat) {
912
+ const staleness = await analyzeDocStaleness(projectRoot, docStat.mtimeMs);
913
+ quality.versionsBehind = staleness.versionsBehind;
914
+ quality.totalVersions = staleness.totalVersions;
915
+ if (staleness.versionsBehind > DOC_STALE_VERSION_THRESHOLD) {
916
+ warnings.push(`${relativePath} 自上次更新后已产生 ${staleness.versionsBehind} 个 requirement 版本(阈值 ${DOC_STALE_VERSION_THRESHOLD}),基线 PRD 已陈旧,需要回填最新已确认需求。`);
917
+ }
918
+ }
919
+ }
920
+ docsQuality.push(quality);
921
+ }
863
922
  }
864
923
 
865
924
  const templateFiles = [];
@@ -901,6 +960,10 @@ export async function checkStandardsWorkspace(projectRoot, options = {}) {
901
960
 
902
961
  checks.push(`Standards docs root: ${STANDARD_DOCS_ROOT.replaceAll(path.sep, '/')}`);
903
962
  checks.push(`Required docs: ${requiredDocs.filter((doc) => doc.exists).length}/${STANDARD_DOCS.length}.`);
963
+ if (docsQuality.length > 0) {
964
+ const pollutedDocs = docsQuality.filter((doc) => doc.megaLines > 0).length;
965
+ checks.push(`Docs quality: ${docsQuality.length} docs analyzed, ${pollutedDocs} with mega-lines > ${DOC_MEGA_LINE_CHARS} chars.`);
966
+ }
904
967
  checks.push(`Manual templates: ${templateFiles.filter((file) => file.exists).length}/${STANDARD_TEMPLATE_FILES.length}.`);
905
968
  const lineConfig = config?.developmentStandards?.codeFileLines ?? DEFAULT_DEVELOPMENT_STANDARDS.codeFileLines;
906
969
  checks.push(`Development standards: code files ok <= ${lineConfig.okMax} lines, attention <= ${lineConfig.attentionMax} lines.`);
@@ -916,6 +979,7 @@ export async function checkStandardsWorkspace(projectRoot, options = {}) {
916
979
  warnings,
917
980
  checks,
918
981
  requiredDocs,
982
+ docsQuality,
919
983
  templateFiles,
920
984
  manualReport,
921
985
  };
@@ -145,13 +145,16 @@ export function inferTestStrategyForTask(task = {}) {
145
145
  };
146
146
  }
147
147
 
148
- if (includesAny(text, [/visual|视觉|截图|界面|页面|组件|样式|browser|playwright|cypress|e2e|端到端|用户主路径|主流程/])) {
148
+ const singleElementCentering = includesAny(text, [/centering-board|center-board|visual centroid|bbox center|canvas center|inside centered|internal centering|内部居中|视觉重心|主体外接框|外接框中心|画布中心|单元素|单个元素|偏心|不居中|没居中|图标内部|图片内部|素材内部|按钮图形|logo center|icon center/]);
149
+ if (includesAny(text, [/visual|视觉|截图|界面|页面|组件|样式|间距|留白|边距|宽度|高度|卡片|对齐|内容槽位|内部槽位|标题|副标题|标签|状态|价格|按钮|密度|圆角|颜色|字号|图标|按钮|padding|margin|spacing|gap|browser|playwright|cypress|e2e|端到端|用户主路径|主流程|内部居中|视觉重心|主体外接框|画布中心|偏心|不居中|没居中/])) {
149
150
  return {
150
151
  layers: ['integration', 'e2e'],
151
152
  size: 'large',
152
- scope: includesAny(text, [/visual|视觉|截图|样式/]) ? 'visual-flow' : 'user-flow',
153
- evidencePlan: '主流程自动化、截图或 visual-compare 证据 + 本任务 verify 命令',
154
- upgradeReason: '触达用户可见路径,需要端到端或视觉级证据',
153
+ scope: includesAny(text, [/visual|视觉|截图|样式|间距|留白|边距|宽度|高度|卡片|对齐|内容槽位|内部槽位|标题|副标题|标签|状态|价格|按钮|密度|圆角|颜色|字号|图标|按钮|padding|margin|spacing|gap|内部居中|视觉重心|主体外接框|画布中心|偏心|不居中|没居中/]) ? 'visual-flow' : 'user-flow',
154
+ evidencePlan: singleElementCentering
155
+ ? '主流程自动化、截图或 visual-compare 证据 + 本任务 verify 命令;单元素内部居中要补 centering-board,量测画布中心、主体外接框中心和视觉重心偏移'
156
+ : '主流程自动化、截图或 visual-compare 证据 + 本任务 verify 命令;轻量 UI 可视优化也需要 before/after、verification-board 或 alignment-board 证据,同构卡片/列表要覆盖内部内容槽位',
157
+ upgradeReason: '触达用户可见路径,需要端到端或视觉级证据;轻量 UI 可视优化不能只用构建或 dev-check 收口',
155
158
  inferred: true,
156
159
  };
157
160
  }