@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.
- package/.openprd/changes/adaptive-project-framing/.openprd.yaml +2 -0
- package/.openprd/changes/adaptive-project-framing/design.md +47 -0
- package/.openprd/changes/adaptive-project-framing/proposal.md +35 -0
- package/.openprd/changes/adaptive-project-framing/specs/agent-requirements/spec.md +16 -0
- package/.openprd/changes/adaptive-project-framing/task-events.jsonl +20 -0
- package/.openprd/changes/adaptive-project-framing/tasks.md +340 -0
- package/.openprd/changes/docs-anti-pollution-and-design-direction-review/.openprd.yaml +2 -0
- package/.openprd/changes/docs-anti-pollution-and-design-direction-review/design.md +34 -0
- package/.openprd/changes/docs-anti-pollution-and-design-direction-review/proposal.md +23 -0
- package/.openprd/changes/docs-anti-pollution-and-design-direction-review/specs/agent-requirements/spec.md +16 -0
- package/.openprd/changes/docs-anti-pollution-and-design-direction-review/task-events.jsonl +14 -0
- package/.openprd/changes/docs-anti-pollution-and-design-direction-review/tasks.md +238 -0
- package/.openprd/changes/loop-isolated-worktree-commit/.openprd.yaml +2 -0
- package/.openprd/changes/loop-isolated-worktree-commit/design.md +53 -0
- package/.openprd/changes/loop-isolated-worktree-commit/proposal.md +38 -0
- package/.openprd/changes/loop-isolated-worktree-commit/specs/agent-requirements/spec.md +16 -0
- package/.openprd/changes/loop-isolated-worktree-commit/task-events.jsonl +22 -0
- package/.openprd/changes/loop-isolated-worktree-commit/tasks.md +357 -0
- package/.openprd/changes/openprd/.openprd.yaml +2 -0
- package/.openprd/changes/openprd/design.md +46 -0
- package/.openprd/changes/openprd/proposal.md +36 -0
- package/.openprd/changes/openprd/specs/agent-requirements/spec.md +16 -0
- package/.openprd/changes/openprd/task-events.jsonl +23 -0
- package/.openprd/changes/openprd/tasks.md +242 -0
- package/.openprd/changes/openprd-generated-change/.openprd.yaml +2 -0
- package/.openprd/changes/openprd-generated-change/design.md +50 -0
- package/.openprd/changes/openprd-generated-change/proposal.md +37 -0
- package/.openprd/changes/openprd-generated-change/specs/agent-requirements/spec.md +16 -0
- package/.openprd/changes/openprd-generated-change/task-events.jsonl +21 -0
- package/.openprd/changes/openprd-generated-change/tasks.md +357 -0
- package/.openprd/changes/pm-human-in-the-loop/.openprd.yaml +2 -0
- package/.openprd/changes/pm-human-in-the-loop/design.md +38 -0
- package/.openprd/changes/pm-human-in-the-loop/proposal.md +29 -0
- package/.openprd/changes/pm-human-in-the-loop/specs/agent-requirements/spec.md +16 -0
- package/.openprd/changes/pm-human-in-the-loop/task-events.jsonl +18 -0
- package/.openprd/changes/pm-human-in-the-loop/tasks.md +306 -0
- package/.openprd/changes/test-strategy-router/.openprd.yaml +2 -0
- package/.openprd/changes/test-strategy-router/design.md +65 -0
- package/.openprd/changes/test-strategy-router/proposal.md +45 -0
- package/.openprd/changes/test-strategy-router/specs/agent-requirements/spec.md +16 -0
- package/.openprd/changes/test-strategy-router/task-events.jsonl +1 -0
- package/.openprd/changes/test-strategy-router/tasks.md +132 -0
- package/.openprd/changes/verify-boundaries-and-historical-refresh/.openprd.yaml +2 -0
- package/.openprd/changes/verify-boundaries-and-historical-refresh/design.md +28 -0
- package/.openprd/changes/verify-boundaries-and-historical-refresh/proposal.md +23 -0
- package/.openprd/changes/verify-boundaries-and-historical-refresh/specs/agent-requirements/spec.md +16 -0
- package/.openprd/changes/verify-boundaries-and-historical-refresh/task-events.jsonl +11 -0
- package/.openprd/changes/verify-boundaries-and-historical-refresh/tasks.md +66 -0
- package/.openprd/changes/vibe-coding-dev-check/.openprd.yaml +2 -0
- package/.openprd/changes/vibe-coding-dev-check/design.md +37 -0
- package/.openprd/changes/vibe-coding-dev-check/proposal.md +28 -0
- package/.openprd/changes/vibe-coding-dev-check/specs/agent-requirements/spec.md +16 -0
- package/.openprd/changes/vibe-coding-dev-check/task-events.jsonl +18 -0
- package/.openprd/changes/vibe-coding-dev-check/tasks.md +306 -0
- package/.openprd/design/README.md +11 -6
- package/.openprd/design/README_EN.md +4 -1
- package/.openprd/design/active/asset-spec.md +6 -0
- package/.openprd/design/active/direction-plan.md +5 -5
- package/.openprd/design/active/selected-direction.md +2 -0
- package/.openprd/design/anti-slop.md +26 -1
- package/.openprd/design/assets/surface-presets.md +6 -0
- package/.openprd/design/checklists/ui-quality-gate.md +7 -0
- package/.openprd/design/lenses/frontend-lenses.md +28 -0
- package/.openprd/design/recipes/content-experience.md +8 -1
- package/.openprd/design/recipes/operational-tool.md +7 -0
- package/.openprd/design/recipes/product-launch.md +8 -1
- package/.openprd/design/templates/README.md +6 -3
- package/.openprd/design/templates/README_EN.md +6 -3
- package/.openprd/design/templates/ops-dashboard.html +8 -1
- package/.openprd/design/templates/product-launch.html +2 -1
- package/.openprd/design/themes/theme-catalog.json +23 -5
- package/.openprd/engagements/active/prd.md +137 -112
- package/.openprd/standards/config.json +7 -1
- package/AGENTS.md +13 -3
- package/README.md +127 -14
- package/README_EN.md +156 -13
- package/package.json +1 -1
- package/scripts/dev-check-wrapup-copy.mjs +46 -21
- package/skills/openprd-diagram-review/SKILL.md +27 -2
- package/skills/openprd-diagram-review/references/explanation-svg-patterns.md +131 -0
- package/skills/openprd-discovery-loop/SKILL.md +2 -2
- package/skills/openprd-frontend-design/SKILL.md +44 -20
- package/skills/openprd-frontend-design/references/design-asset-contract.md +6 -0
- package/skills/openprd-frontend-design/references/direction-engine.md +29 -4
- package/skills/openprd-harness/SKILL.md +22 -16
- package/skills/openprd-quality/SKILL.md +10 -8
- package/skills/openprd-requirement-intake/SKILL.md +2 -0
- package/skills/openprd-router/SKILL.md +2 -1
- package/skills/openprd-shared/SKILL.md +26 -16
- package/skills/openprd-standards/SKILL.md +4 -2
- package/src/agent-canonical-content.js +810 -0
- package/src/agent-integration.js +258 -777
- package/src/canvas-app-client-app.js +838 -0
- package/src/canvas-app-client-helpers.js +1138 -0
- package/src/canvas-app-styles.js +898 -0
- package/src/canvas-app.html.js +135 -0
- package/src/canvas-binding.js +414 -0
- package/src/canvas-codex-relay.js +430 -0
- package/src/canvas-i18n.js +282 -0
- package/src/canvas-scene.js +377 -0
- package/src/canvas-session-store.js +148 -0
- package/src/canvas-workspace.js +1264 -0
- package/src/cli/args.js +72 -4
- package/src/cli/basic-print.js +3 -0
- package/src/cli/canvas-print.js +106 -0
- package/src/cli/doctor-print.js +20 -0
- package/src/cli/print.js +2 -0
- package/src/cli/quality-commands.js +222 -0
- package/src/cli/quality-print.js +28 -2
- package/src/cli/run-print.js +5 -0
- package/src/cli/workflow-print.js +3 -0
- package/src/codex-app-server-relay.js +251 -0
- package/src/codex-hook-runner-template.mjs +978 -58
- package/src/design-starter-support.js +2 -2
- package/src/design-starter.js +39 -3
- package/src/dev-standards.js +125 -10
- package/src/diagram-core.js +6 -20
- package/src/discovery.js +2 -8
- package/src/docs-compact.js +125 -0
- package/src/execution-strategy.js +1 -1
- package/src/fleet.js +9 -3
- package/src/guide.js +227 -0
- package/src/html-artifacts.js +428 -7
- package/src/knowledge.js +45 -11
- package/src/language-policy.js +63 -3
- package/src/learning-review.js +1 -1
- package/src/loop.js +1 -1
- package/src/openprd.js +68 -131
- package/src/openspec/change-validate.js +2 -2
- package/src/openspec/constants.js +6 -7
- package/src/openspec/execute.js +2 -2
- package/src/openspec/generate.js +318 -102
- package/src/openspec/migration.js +168 -0
- package/src/openspec/paths.js +1 -22
- package/src/prd-core.js +1 -1
- package/src/quality-visual-review.js +257 -14
- package/src/quality.js +46 -8
- package/src/review-presentation.js +60 -0
- package/src/run-harness.js +41 -3
- package/src/session-evidence.js +363 -0
- package/src/standards.js +64 -0
- package/src/test-strategy.js +7 -4
- package/src/visual-compare-centering.js +622 -0
- package/src/visual-compare-core.js +1123 -0
- package/src/visual-compare.js +620 -698
- package/src/workspace-core.js +94 -4
- 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
|
};
|
package/src/test-strategy.js
CHANGED
|
@@ -145,13 +145,16 @@ export function inferTestStrategyForTask(task = {}) {
|
|
|
145
145
|
};
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
|
|
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
|
|
153
|
-
evidencePlan:
|
|
154
|
-
|
|
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
|
}
|