@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
@@ -0,0 +1,148 @@
1
+ /*
2
+ * Core purpose
3
+ * Shared low-level primitives for the OpenPrd canvas subsystem: session key
4
+ * hashing, string/JSON normalization helpers, and the file-backed ops ledger
5
+ * (read/append/update operations in ops.json).
6
+ *
7
+ * Positioning
8
+ * Imported by canvas-workspace.js, canvas-binding.js, and
9
+ * canvas-codex-relay.js. Keep this module dependency-light (no HTTP, no
10
+ * process spawning) so every canvas module can safely depend on it.
11
+ */
12
+ import crypto from 'node:crypto';
13
+ import { readJson, writeJson } from './fs-utils.js';
14
+ import { timestamp } from './time.js';
15
+
16
+ const SESSION_KEY_MAX = 84;
17
+ const HANDOFF_TEXT_MAX = 24000;
18
+ const CANVAS_SURFACE_BACKGROUND = '#ffffff';
19
+ const LEGACY_CANVAS_BACKGROUNDS = new Set(['#fbfaf7', '#fffdf9', '#f8f6f1']);
20
+
21
+ function isPlainObject(value) {
22
+ return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
23
+ }
24
+
25
+ function shortHash(value) {
26
+ return crypto.createHash('sha256').update(String(value ?? '')).digest('hex').slice(0, 10);
27
+ }
28
+
29
+ function sanitizeSessionSegment(value, fallback = 'workspace') {
30
+ const normalized = String(value ?? '')
31
+ .trim()
32
+ .replace(/[/\\:]+/g, '-')
33
+ .replace(/[^a-zA-Z0-9._-]+/g, '-')
34
+ .replace(/^-+|-+$/g, '')
35
+ .slice(0, SESSION_KEY_MAX);
36
+ return normalized || fallback;
37
+ }
38
+
39
+ function buildSessionKey(kind, id) {
40
+ const safeKind = sanitizeSessionSegment(kind, 'session');
41
+ const safeId = sanitizeSessionSegment(id, 'workspace');
42
+ return `${safeKind}-${safeId}-${shortHash(`${kind}:${id}`)}`;
43
+ }
44
+
45
+ function firstPresent(...values) {
46
+ for (const value of values) {
47
+ if (typeof value === 'string' && value.trim()) {
48
+ return value.trim();
49
+ }
50
+ }
51
+ return null;
52
+ }
53
+
54
+ function normalizeBindingTitle(...values) {
55
+ const title = firstPresent(...values);
56
+ if (!title) {
57
+ return null;
58
+ }
59
+ return title.length > 160 ? `${title.slice(0, 157)}...` : title;
60
+ }
61
+
62
+ async function readOps(paths) {
63
+ const ops = await readJson(paths.opsFile).catch(() => null);
64
+ if (!ops || !Array.isArray(ops.ops)) {
65
+ return { type: 'openprd.canvas.ops.v1', nextSeq: 0, ops: [] };
66
+ }
67
+ return ops;
68
+ }
69
+
70
+ async function appendOperation(paths, operation) {
71
+ const ops = await readOps(paths);
72
+ const seq = Number(ops.nextSeq ?? ops.ops.length) + 1;
73
+ const nextOperation = {
74
+ id: operation.id ?? `op-${seq}-${shortHash(JSON.stringify(operation))}`,
75
+ seq,
76
+ createdAt: timestamp(),
77
+ ...operation,
78
+ };
79
+ const nextOps = {
80
+ ...ops,
81
+ nextSeq: seq,
82
+ ops: [...ops.ops, nextOperation],
83
+ };
84
+ await writeJson(paths.opsFile, nextOps);
85
+ return nextOperation;
86
+ }
87
+
88
+ async function updateOperation(paths, operationId, patch) {
89
+ const ops = await readOps(paths);
90
+ let updatedOperation = null;
91
+ const nextOperations = ops.ops.map((op) => {
92
+ if (op.id !== operationId) {
93
+ return op;
94
+ }
95
+ updatedOperation = {
96
+ ...op,
97
+ ...patch,
98
+ updatedAt: timestamp(),
99
+ };
100
+ return updatedOperation;
101
+ });
102
+ if (!updatedOperation) {
103
+ const error = new Error(`Canvas operation not found: ${operationId}`);
104
+ error.statusCode = 404;
105
+ throw error;
106
+ }
107
+ await writeJson(paths.opsFile, {
108
+ ...ops,
109
+ ops: nextOperations,
110
+ });
111
+ return updatedOperation;
112
+ }
113
+
114
+ function trimString(value, maxLength = HANDOFF_TEXT_MAX) {
115
+ const text = String(value ?? '');
116
+ return text.length > maxLength ? `${text.slice(0, maxLength)}\n...[truncated]` : text;
117
+ }
118
+
119
+ function parsePositiveInteger(value, fallback = 0) {
120
+ const parsed = Number(value);
121
+ return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : fallback;
122
+ }
123
+
124
+ function normalizeStringArray(value) {
125
+ if (!Array.isArray(value)) {
126
+ return [];
127
+ }
128
+ return value.map((item) => String(item)).filter(Boolean);
129
+ }
130
+
131
+ export {
132
+ HANDOFF_TEXT_MAX,
133
+ SESSION_KEY_MAX,
134
+ CANVAS_SURFACE_BACKGROUND,
135
+ LEGACY_CANVAS_BACKGROUNDS,
136
+ appendOperation,
137
+ buildSessionKey,
138
+ firstPresent,
139
+ isPlainObject,
140
+ normalizeBindingTitle,
141
+ normalizeStringArray,
142
+ parsePositiveInteger,
143
+ readOps,
144
+ sanitizeSessionSegment,
145
+ shortHash,
146
+ trimString,
147
+ updateOperation,
148
+ };