@planu/cli 0.72.0 → 0.74.0

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 (267) hide show
  1. package/README.md +1 -1
  2. package/dist/config/license-plans.json +9 -2
  3. package/dist/config/tool-groups.json +5 -1
  4. package/dist/engine/actuals/git-analyzer.js +1 -1
  5. package/dist/engine/actuals/git-analyzer.js.map +1 -1
  6. package/dist/engine/agent-prompt-generator.d.ts +12 -0
  7. package/dist/engine/agent-prompt-generator.d.ts.map +1 -0
  8. package/dist/engine/agent-prompt-generator.js +171 -0
  9. package/dist/engine/agent-prompt-generator.js.map +1 -0
  10. package/dist/engine/ai-tool-detector/index.d.ts +6 -0
  11. package/dist/engine/ai-tool-detector/index.d.ts.map +1 -0
  12. package/dist/engine/ai-tool-detector/index.js +95 -0
  13. package/dist/engine/ai-tool-detector/index.js.map +1 -0
  14. package/dist/engine/ci-generator/planu-steps.d.ts.map +1 -1
  15. package/dist/engine/ci-generator/planu-steps.js +10 -11
  16. package/dist/engine/ci-generator/planu-steps.js.map +1 -1
  17. package/dist/engine/convention-scanner/codebase-scanner.d.ts +7 -0
  18. package/dist/engine/convention-scanner/codebase-scanner.d.ts.map +1 -0
  19. package/dist/engine/convention-scanner/codebase-scanner.js +258 -0
  20. package/dist/engine/convention-scanner/codebase-scanner.js.map +1 -0
  21. package/dist/engine/convention-scanner/convention-parser.d.ts +7 -0
  22. package/dist/engine/convention-scanner/convention-parser.d.ts.map +1 -0
  23. package/dist/engine/convention-scanner/convention-parser.js +195 -0
  24. package/dist/engine/convention-scanner/convention-parser.js.map +1 -0
  25. package/dist/engine/convention-scanner/index.d.ts +3 -0
  26. package/dist/engine/convention-scanner/index.d.ts.map +1 -0
  27. package/dist/engine/convention-scanner/index.js +5 -0
  28. package/dist/engine/convention-scanner/index.js.map +1 -0
  29. package/dist/engine/convention-sync.d.ts +9 -0
  30. package/dist/engine/convention-sync.d.ts.map +1 -0
  31. package/dist/engine/convention-sync.js +156 -0
  32. package/dist/engine/convention-sync.js.map +1 -0
  33. package/dist/engine/doc-generator/portal/portal-regenerator.d.ts +2 -1
  34. package/dist/engine/doc-generator/portal/portal-regenerator.d.ts.map +1 -1
  35. package/dist/engine/doc-generator/portal/portal-regenerator.js +23 -15
  36. package/dist/engine/doc-generator/portal/portal-regenerator.js.map +1 -1
  37. package/dist/engine/feedback/triage.d.ts +16 -0
  38. package/dist/engine/feedback/triage.d.ts.map +1 -0
  39. package/dist/engine/feedback/triage.js +165 -0
  40. package/dist/engine/feedback/triage.js.map +1 -0
  41. package/dist/engine/hooks-reconciler.d.ts +7 -0
  42. package/dist/engine/hooks-reconciler.d.ts.map +1 -0
  43. package/dist/engine/hooks-reconciler.js +214 -0
  44. package/dist/engine/hooks-reconciler.js.map +1 -0
  45. package/dist/engine/platform-registry.d.ts +17 -0
  46. package/dist/engine/platform-registry.d.ts.map +1 -0
  47. package/dist/engine/platform-registry.js +78 -0
  48. package/dist/engine/platform-registry.js.map +1 -0
  49. package/dist/engine/project-health-checker.d.ts +4 -2
  50. package/dist/engine/project-health-checker.d.ts.map +1 -1
  51. package/dist/engine/project-health-checker.js +96 -7
  52. package/dist/engine/project-health-checker.js.map +1 -1
  53. package/dist/engine/rules-generator/index.d.ts +14 -0
  54. package/dist/engine/rules-generator/index.d.ts.map +1 -0
  55. package/dist/engine/rules-generator/index.js +313 -0
  56. package/dist/engine/rules-generator/index.js.map +1 -0
  57. package/dist/engine/rules-reconciler.d.ts +13 -0
  58. package/dist/engine/rules-reconciler.d.ts.map +1 -0
  59. package/dist/engine/rules-reconciler.js +193 -0
  60. package/dist/engine/rules-reconciler.js.map +1 -0
  61. package/dist/engine/skill-generator/detect.d.ts +1 -0
  62. package/dist/engine/skill-generator/detect.d.ts.map +1 -1
  63. package/dist/engine/skill-generator/detect.js +13 -5
  64. package/dist/engine/skill-generator/detect.js.map +1 -1
  65. package/dist/engine/skills/skills-fetcher.d.ts +4 -0
  66. package/dist/engine/skills/skills-fetcher.d.ts.map +1 -0
  67. package/dist/engine/skills/skills-fetcher.js +102 -0
  68. package/dist/engine/skills/skills-fetcher.js.map +1 -0
  69. package/dist/engine/skills-reconciler.d.ts +15 -0
  70. package/dist/engine/skills-reconciler.d.ts.map +1 -0
  71. package/dist/engine/skills-reconciler.js +98 -0
  72. package/dist/engine/skills-reconciler.js.map +1 -0
  73. package/dist/engine/spec-template-cleaner.d.ts +12 -0
  74. package/dist/engine/spec-template-cleaner.d.ts.map +1 -0
  75. package/dist/engine/spec-template-cleaner.js +119 -0
  76. package/dist/engine/spec-template-cleaner.js.map +1 -0
  77. package/dist/engine/validator/analyzer.d.ts +4 -2
  78. package/dist/engine/validator/analyzer.d.ts.map +1 -1
  79. package/dist/engine/validator/analyzer.js +5 -2
  80. package/dist/engine/validator/analyzer.js.map +1 -1
  81. package/dist/engine/validator/deep-code-checker.d.ts +4 -2
  82. package/dist/engine/validator/deep-code-checker.d.ts.map +1 -1
  83. package/dist/engine/validator/deep-code-checker.js +44 -1
  84. package/dist/engine/validator/deep-code-checker.js.map +1 -1
  85. package/dist/engine/validator/extractors.d.ts +8 -1
  86. package/dist/engine/validator/extractors.d.ts.map +1 -1
  87. package/dist/engine/validator/extractors.js +33 -0
  88. package/dist/engine/validator/extractors.js.map +1 -1
  89. package/dist/engine/validator.d.ts.map +1 -1
  90. package/dist/engine/validator.js +13 -2
  91. package/dist/engine/validator.js.map +1 -1
  92. package/dist/engine/workers/schema.d.ts +58 -0
  93. package/dist/engine/workers/schema.d.ts.map +1 -0
  94. package/dist/engine/workers/schema.js +41 -0
  95. package/dist/engine/workers/schema.js.map +1 -0
  96. package/dist/engine/workers/worker-engine.js +1 -1
  97. package/dist/engine/workers/worker-engine.js.map +1 -1
  98. package/dist/index.js +10 -0
  99. package/dist/index.js.map +1 -1
  100. package/dist/storage/convention-baseline.d.ts +20 -0
  101. package/dist/storage/convention-baseline.d.ts.map +1 -0
  102. package/dist/storage/convention-baseline.js +57 -0
  103. package/dist/storage/convention-baseline.js.map +1 -0
  104. package/dist/storage/feedback-remote.d.ts +8 -0
  105. package/dist/storage/feedback-remote.d.ts.map +1 -0
  106. package/dist/storage/feedback-remote.js +27 -0
  107. package/dist/storage/feedback-remote.js.map +1 -0
  108. package/dist/storage/feedback-store.d.ts +27 -0
  109. package/dist/storage/feedback-store.d.ts.map +1 -0
  110. package/dist/storage/feedback-store.js +272 -0
  111. package/dist/storage/feedback-store.js.map +1 -0
  112. package/dist/storage/index.d.ts +1 -0
  113. package/dist/storage/index.d.ts.map +1 -1
  114. package/dist/storage/index.js +1 -0
  115. package/dist/storage/index.js.map +1 -1
  116. package/dist/tools/convention-sync.d.ts +8 -0
  117. package/dist/tools/convention-sync.d.ts.map +1 -0
  118. package/dist/tools/convention-sync.js +77 -0
  119. package/dist/tools/convention-sync.js.map +1 -0
  120. package/dist/tools/create-spec/post-creation.js +1 -1
  121. package/dist/tools/create-spec/post-creation.js.map +1 -1
  122. package/dist/tools/create-spec-hu/ac-adapters/convention-adapter.d.ts +9 -0
  123. package/dist/tools/create-spec-hu/ac-adapters/convention-adapter.d.ts.map +1 -0
  124. package/dist/tools/create-spec-hu/ac-adapters/convention-adapter.js +68 -0
  125. package/dist/tools/create-spec-hu/ac-adapters/convention-adapter.js.map +1 -0
  126. package/dist/tools/create-spec-hu/ac-adapters/custom-template-adapter.d.ts +14 -0
  127. package/dist/tools/create-spec-hu/ac-adapters/custom-template-adapter.d.ts.map +1 -0
  128. package/dist/tools/create-spec-hu/ac-adapters/custom-template-adapter.js +60 -0
  129. package/dist/tools/create-spec-hu/ac-adapters/custom-template-adapter.js.map +1 -0
  130. package/dist/tools/create-spec-hu/ac-adapters/index.d.ts +4 -0
  131. package/dist/tools/create-spec-hu/ac-adapters/index.d.ts.map +1 -1
  132. package/dist/tools/create-spec-hu/ac-adapters/index.js +9 -1
  133. package/dist/tools/create-spec-hu/ac-adapters/index.js.map +1 -1
  134. package/dist/tools/create-spec-hu/serverless-hu-adapter.d.ts +8 -0
  135. package/dist/tools/create-spec-hu/serverless-hu-adapter.d.ts.map +1 -0
  136. package/dist/tools/create-spec-hu/serverless-hu-adapter.js +46 -0
  137. package/dist/tools/create-spec-hu/serverless-hu-adapter.js.map +1 -0
  138. package/dist/tools/create-spec-hu.d.ts.map +1 -1
  139. package/dist/tools/create-spec-hu.js +4 -0
  140. package/dist/tools/create-spec-hu.js.map +1 -1
  141. package/dist/tools/create-spec.d.ts.map +1 -1
  142. package/dist/tools/create-spec.js +3 -2
  143. package/dist/tools/create-spec.js.map +1 -1
  144. package/dist/tools/delete-decision.d.ts.map +1 -1
  145. package/dist/tools/delete-decision.js +2 -0
  146. package/dist/tools/delete-decision.js.map +1 -1
  147. package/dist/tools/delete-project.d.ts.map +1 -1
  148. package/dist/tools/delete-project.js +11 -14
  149. package/dist/tools/delete-project.js.map +1 -1
  150. package/dist/tools/delete-spec.d.ts.map +1 -1
  151. package/dist/tools/delete-spec.js +11 -9
  152. package/dist/tools/delete-spec.js.map +1 -1
  153. package/dist/tools/estimate.d.ts.map +1 -1
  154. package/dist/tools/estimate.js +6 -5
  155. package/dist/tools/estimate.js.map +1 -1
  156. package/dist/tools/export-session.d.ts.map +1 -1
  157. package/dist/tools/export-session.js +13 -10
  158. package/dist/tools/export-session.js.map +1 -1
  159. package/dist/tools/feedback-handler.d.ts +5 -0
  160. package/dist/tools/feedback-handler.d.ts.map +1 -0
  161. package/dist/tools/feedback-handler.js +106 -0
  162. package/dist/tools/feedback-handler.js.map +1 -0
  163. package/dist/tools/generate-teammate-prompt.d.ts +8 -0
  164. package/dist/tools/generate-teammate-prompt.d.ts.map +1 -1
  165. package/dist/tools/generate-teammate-prompt.js +33 -0
  166. package/dist/tools/generate-teammate-prompt.js.map +1 -1
  167. package/dist/tools/init-project/handler.d.ts.map +1 -1
  168. package/dist/tools/init-project/handler.js +42 -7
  169. package/dist/tools/init-project/handler.js.map +1 -1
  170. package/dist/tools/init-project/helpers.d.ts.map +1 -1
  171. package/dist/tools/init-project/helpers.js +1 -2
  172. package/dist/tools/init-project/helpers.js.map +1 -1
  173. package/dist/tools/init-project/result-builder.d.ts.map +1 -1
  174. package/dist/tools/init-project/result-builder.js +12 -1
  175. package/dist/tools/init-project/result-builder.js.map +1 -1
  176. package/dist/tools/log-decision.d.ts.map +1 -1
  177. package/dist/tools/log-decision.js +15 -4
  178. package/dist/tools/log-decision.js.map +1 -1
  179. package/dist/tools/manage-trash.d.ts.map +1 -1
  180. package/dist/tools/manage-trash.js +13 -27
  181. package/dist/tools/manage-trash.js.map +1 -1
  182. package/dist/tools/reconcile-hooks.d.ts +7 -0
  183. package/dist/tools/reconcile-hooks.d.ts.map +1 -0
  184. package/dist/tools/reconcile-hooks.js +78 -0
  185. package/dist/tools/reconcile-hooks.js.map +1 -0
  186. package/dist/tools/reconcile-rules.d.ts +7 -0
  187. package/dist/tools/reconcile-rules.d.ts.map +1 -0
  188. package/dist/tools/reconcile-rules.js +86 -0
  189. package/dist/tools/reconcile-rules.js.map +1 -0
  190. package/dist/tools/reconcile-skills.d.ts +8 -0
  191. package/dist/tools/reconcile-skills.d.ts.map +1 -0
  192. package/dist/tools/reconcile-skills.js +70 -0
  193. package/dist/tools/reconcile-skills.js.map +1 -0
  194. package/dist/tools/register-feedback-tools.d.ts +3 -0
  195. package/dist/tools/register-feedback-tools.d.ts.map +1 -0
  196. package/dist/tools/register-feedback-tools.js +65 -0
  197. package/dist/tools/register-feedback-tools.js.map +1 -0
  198. package/dist/tools/register-spec-tools/core-spec-tools.d.ts.map +1 -1
  199. package/dist/tools/register-spec-tools/core-spec-tools.js +10 -4
  200. package/dist/tools/register-spec-tools/core-spec-tools.js.map +1 -1
  201. package/dist/tools/register-team-tools.d.ts.map +1 -1
  202. package/dist/tools/register-team-tools.js +35 -8
  203. package/dist/tools/register-team-tools.js.map +1 -1
  204. package/dist/tools/safe-handler.d.ts.map +1 -1
  205. package/dist/tools/safe-handler.js +20 -2
  206. package/dist/tools/safe-handler.js.map +1 -1
  207. package/dist/tools/schemas/index.d.ts +1 -0
  208. package/dist/tools/schemas/index.d.ts.map +1 -1
  209. package/dist/tools/schemas/index.js +1 -0
  210. package/dist/tools/schemas/index.js.map +1 -1
  211. package/dist/tools/schemas/reconcile-skills-schemas.d.ts +7 -0
  212. package/dist/tools/schemas/reconcile-skills-schemas.d.ts.map +1 -0
  213. package/dist/tools/schemas/reconcile-skills-schemas.js +18 -0
  214. package/dist/tools/schemas/reconcile-skills-schemas.js.map +1 -0
  215. package/dist/tools/schemas/workers-schema.d.ts +1 -56
  216. package/dist/tools/schemas/workers-schema.d.ts.map +1 -1
  217. package/dist/tools/schemas/workers-schema.js +6 -42
  218. package/dist/tools/schemas/workers-schema.js.map +1 -1
  219. package/dist/tools/skill-registry/search.d.ts.map +1 -1
  220. package/dist/tools/skill-registry/search.js +29 -3
  221. package/dist/tools/skill-registry/search.js.map +1 -1
  222. package/dist/tools/suggest-tooling/skills-fetcher.d.ts +1 -3
  223. package/dist/tools/suggest-tooling/skills-fetcher.d.ts.map +1 -1
  224. package/dist/tools/suggest-tooling/skills-fetcher.js +3 -101
  225. package/dist/tools/suggest-tooling/skills-fetcher.js.map +1 -1
  226. package/dist/tools/token-recording.d.ts +16 -0
  227. package/dist/tools/token-recording.d.ts.map +1 -0
  228. package/dist/tools/token-recording.js +47 -0
  229. package/dist/tools/token-recording.js.map +1 -0
  230. package/dist/tools/update-status-actions.d.ts.map +1 -1
  231. package/dist/tools/update-status-actions.js +1 -2
  232. package/dist/tools/update-status-actions.js.map +1 -1
  233. package/dist/tools/update-status-convention-gate.d.ts +12 -0
  234. package/dist/tools/update-status-convention-gate.d.ts.map +1 -0
  235. package/dist/tools/update-status-convention-gate.js +159 -0
  236. package/dist/tools/update-status-convention-gate.js.map +1 -0
  237. package/dist/tools/update-status-reconcile.d.ts +7 -0
  238. package/dist/tools/update-status-reconcile.d.ts.map +1 -0
  239. package/dist/tools/update-status-reconcile.js +47 -0
  240. package/dist/tools/update-status-reconcile.js.map +1 -0
  241. package/dist/tools/update-status.d.ts.map +1 -1
  242. package/dist/tools/update-status.js +113 -67
  243. package/dist/tools/update-status.js.map +1 -1
  244. package/dist/tools/validate.d.ts.map +1 -1
  245. package/dist/tools/validate.js +93 -3
  246. package/dist/tools/validate.js.map +1 -1
  247. package/dist/types/ai-tool-rules.d.ts +42 -0
  248. package/dist/types/ai-tool-rules.d.ts.map +1 -0
  249. package/dist/types/ai-tool-rules.js +3 -0
  250. package/dist/types/ai-tool-rules.js.map +1 -0
  251. package/dist/types/conventions.d.ts +155 -0
  252. package/dist/types/conventions.d.ts.map +1 -0
  253. package/dist/types/conventions.js +3 -0
  254. package/dist/types/conventions.js.map +1 -0
  255. package/dist/types/feedback.d.ts +76 -0
  256. package/dist/types/feedback.d.ts.map +1 -0
  257. package/dist/types/feedback.js +3 -0
  258. package/dist/types/feedback.js.map +1 -0
  259. package/dist/types/index.d.ts +3 -0
  260. package/dist/types/index.d.ts.map +1 -1
  261. package/dist/types/index.js +1 -0
  262. package/dist/types/index.js.map +1 -1
  263. package/dist/types/project/planu-config.d.ts +4 -0
  264. package/dist/types/project/planu-config.d.ts.map +1 -1
  265. package/package.json +1 -1
  266. package/src/config/license-plans.json +9 -2
  267. package/src/config/tool-groups.json +5 -1
@@ -0,0 +1,272 @@
1
+ // storage/feedback-store.ts — Feedback Hub persistence (SPEC-188)
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
+ import { join, dirname } from 'node:path';
4
+ import { withFileLock } from './file-mutex.js';
5
+ import { sendFeedbackRemote } from './feedback-remote.js';
6
+ // ---------------------------------------------------------------------------
7
+ // Path helpers
8
+ // ---------------------------------------------------------------------------
9
+ function getFeedbackPath(dataDir) {
10
+ return join(dataDir, 'global', 'feedback', 'feedback-ledger.json');
11
+ }
12
+ function ensureDir(dirPath) {
13
+ if (!existsSync(dirPath)) {
14
+ mkdirSync(dirPath, { recursive: true });
15
+ }
16
+ }
17
+ // ---------------------------------------------------------------------------
18
+ // Low-level I/O
19
+ // ---------------------------------------------------------------------------
20
+ function readLedger(filePath) {
21
+ if (!existsSync(filePath)) {
22
+ return [];
23
+ }
24
+ try {
25
+ const raw = readFileSync(filePath, 'utf-8');
26
+ const parsed = JSON.parse(raw);
27
+ if (!Array.isArray(parsed)) {
28
+ return [];
29
+ }
30
+ return parsed;
31
+ }
32
+ catch {
33
+ return [];
34
+ }
35
+ }
36
+ function writeLedger(filePath, entries) {
37
+ ensureDir(dirname(filePath));
38
+ writeFileSync(filePath, JSON.stringify(entries, null, 2), 'utf-8');
39
+ }
40
+ // ---------------------------------------------------------------------------
41
+ // ID generation
42
+ // ---------------------------------------------------------------------------
43
+ function generateId(entries) {
44
+ if (entries.length === 0) {
45
+ return 'FB-001';
46
+ }
47
+ const nums = entries
48
+ .map((e) => {
49
+ const m = /^FB-(\d+)$/.exec(e.id);
50
+ return m?.[1] !== undefined ? parseInt(m[1], 10) : 0;
51
+ })
52
+ .filter((n) => n > 0);
53
+ const maxNum = nums.length > 0 ? Math.max(...nums) : 0;
54
+ return `FB-${String(maxNum + 1).padStart(3, '0')}`;
55
+ }
56
+ // ---------------------------------------------------------------------------
57
+ // Version helper
58
+ // ---------------------------------------------------------------------------
59
+ function readPlanuVersion(dataDir) {
60
+ // Walk up from dataDir to find package.json
61
+ const projectRoot = dirname(dataDir.endsWith('/data') ? dataDir : dataDir);
62
+ const candidates = [
63
+ join(dataDir, '..', 'package.json'),
64
+ join(dataDir, '../../package.json'),
65
+ join(process.cwd(), 'package.json'),
66
+ ];
67
+ for (const candidate of candidates) {
68
+ if (existsSync(candidate)) {
69
+ try {
70
+ const raw = readFileSync(candidate, 'utf-8');
71
+ const pkg = JSON.parse(raw);
72
+ if (typeof pkg.version === 'string') {
73
+ return pkg.version;
74
+ }
75
+ }
76
+ catch {
77
+ // continue
78
+ }
79
+ }
80
+ }
81
+ void projectRoot;
82
+ return 'unknown';
83
+ }
84
+ // ---------------------------------------------------------------------------
85
+ // Similarity helper (word overlap)
86
+ // ---------------------------------------------------------------------------
87
+ const STOP_WORDS = new Set([
88
+ 'the',
89
+ 'a',
90
+ 'an',
91
+ 'is',
92
+ 'are',
93
+ 'was',
94
+ 'were',
95
+ 'it',
96
+ 'its',
97
+ 'in',
98
+ 'on',
99
+ 'at',
100
+ 'to',
101
+ 'for',
102
+ 'of',
103
+ 'and',
104
+ 'or',
105
+ 'but',
106
+ 'not',
107
+ 'with',
108
+ 'this',
109
+ 'that',
110
+ 'i',
111
+ 'we',
112
+ 'my',
113
+ 'our',
114
+ ]);
115
+ function tokenize(text) {
116
+ return new Set(text
117
+ .toLowerCase()
118
+ .replace(/[^a-z0-9\s]/g, ' ')
119
+ .split(/\s+/)
120
+ .filter((w) => w.length > 1 && !STOP_WORDS.has(w)));
121
+ }
122
+ function jaccardScore(a, b) {
123
+ if (a.size === 0 && b.size === 0) {
124
+ return 1;
125
+ }
126
+ const intersection = [...a].filter((w) => b.has(w)).length;
127
+ const union = new Set([...a, ...b]).size;
128
+ return union === 0 ? 0 : intersection / union;
129
+ }
130
+ // ---------------------------------------------------------------------------
131
+ // Public API
132
+ // ---------------------------------------------------------------------------
133
+ /**
134
+ * Submit a new feedback entry. Auto-generates ID, timestamp, and version.
135
+ */
136
+ export async function submitFeedback(dataDir, entry) {
137
+ const filePath = getFeedbackPath(dataDir);
138
+ const version = readPlanuVersion(dataDir);
139
+ return withFileLock(filePath, () => {
140
+ const entries = readLedger(filePath);
141
+ const id = generateId(entries);
142
+ const newEntry = {
143
+ ...entry,
144
+ id,
145
+ createdAt: new Date().toISOString(),
146
+ planuVersion: version,
147
+ };
148
+ entries.push(newEntry);
149
+ writeLedger(filePath, entries);
150
+ void sendFeedbackRemote({
151
+ type: newEntry.type,
152
+ title: newEntry.title,
153
+ description: newEntry.description,
154
+ planuVersion: newEntry.planuVersion,
155
+ stack: newEntry.context?.stack,
156
+ tags: newEntry.tags,
157
+ });
158
+ return Promise.resolve(newEntry);
159
+ });
160
+ }
161
+ /**
162
+ * Load and filter feedback entries.
163
+ */
164
+ export function getFeedback(dataDir, filter) {
165
+ const filePath = getFeedbackPath(dataDir);
166
+ let entries = readLedger(filePath);
167
+ if (filter?.type !== undefined) {
168
+ entries = entries.filter((e) => e.type === filter.type);
169
+ }
170
+ if (filter?.status !== undefined) {
171
+ entries = entries.filter((e) => e.status === filter.status);
172
+ }
173
+ if (filter?.specId !== undefined) {
174
+ entries = entries.filter((e) => e.specId === filter.specId);
175
+ }
176
+ return entries;
177
+ }
178
+ /**
179
+ * Update an existing feedback entry by ID.
180
+ */
181
+ export async function updateFeedback(dataDir, id, update) {
182
+ const filePath = getFeedbackPath(dataDir);
183
+ return withFileLock(filePath, () => {
184
+ const entries = readLedger(filePath);
185
+ const idx = entries.findIndex((e) => e.id === id);
186
+ if (idx === -1) {
187
+ return Promise.resolve(null);
188
+ }
189
+ const existing = entries[idx];
190
+ if (existing === undefined) {
191
+ return Promise.resolve(null);
192
+ }
193
+ const merged = { ...existing, ...update, id };
194
+ entries[idx] = merged;
195
+ writeLedger(filePath, entries);
196
+ return Promise.resolve(merged);
197
+ });
198
+ }
199
+ /**
200
+ * Mark feedback as resolved, optionally linking spec and PR.
201
+ */
202
+ export async function resolveFeedback(dataDir, id, specId, prUrl, notes) {
203
+ return updateFeedback(dataDir, id, {
204
+ status: 'resolved',
205
+ resolvedAt: new Date().toISOString(),
206
+ ...(specId !== undefined ? { specId } : {}),
207
+ ...(prUrl !== undefined ? { prUrl } : {}),
208
+ ...(notes !== undefined ? { resolvedNotes: notes } : {}),
209
+ });
210
+ }
211
+ /**
212
+ * Compute summary statistics across all feedback.
213
+ */
214
+ export function getSummary(dataDir) {
215
+ const entries = readLedger(getFeedbackPath(dataDir));
216
+ const byType = {
217
+ bug: 0,
218
+ feature: 0,
219
+ suggestion: 0,
220
+ dx: 0,
221
+ };
222
+ const byStatus = {
223
+ pending: 0,
224
+ triaged: 0,
225
+ spec_created: 0,
226
+ implementing: 0,
227
+ resolved: 0,
228
+ dismissed: 0,
229
+ };
230
+ let totalResolutionMs = 0;
231
+ let resolvedCount = 0;
232
+ for (const e of entries) {
233
+ byType[e.type] = byType[e.type] + 1;
234
+ byStatus[e.status] = byStatus[e.status] + 1;
235
+ if (e.status === 'resolved' && e.resolvedAt) {
236
+ const created = new Date(e.createdAt).getTime();
237
+ const resolved = new Date(e.resolvedAt).getTime();
238
+ if (!isNaN(created) && !isNaN(resolved)) {
239
+ totalResolutionMs += resolved - created;
240
+ resolvedCount++;
241
+ }
242
+ }
243
+ }
244
+ const avgResolutionDays = resolvedCount > 0 ? totalResolutionMs / resolvedCount / (1000 * 60 * 60 * 24) : 0;
245
+ const topRequests = [...entries]
246
+ .filter((e) => (e.votes ?? 0) > 0)
247
+ .sort((a, b) => (b.votes ?? 0) - (a.votes ?? 0))
248
+ .slice(0, 5)
249
+ .map((e) => ({ title: e.title, votes: e.votes ?? 0, id: e.id }));
250
+ return {
251
+ total: entries.length,
252
+ byType,
253
+ byStatus,
254
+ pending: byStatus.pending,
255
+ resolved: byStatus.resolved,
256
+ avgResolutionDays,
257
+ topRequests,
258
+ };
259
+ }
260
+ /**
261
+ * Find feedback entries with title similar to the given string.
262
+ * Uses Jaccard word overlap. Threshold defaults to 0.3.
263
+ */
264
+ export function findSimilar(dataDir, title, threshold = 0.3) {
265
+ const entries = readLedger(getFeedbackPath(dataDir));
266
+ const queryTokens = tokenize(title);
267
+ return entries.filter((e) => {
268
+ const entryTokens = tokenize(e.title);
269
+ return jaccardScore(queryTokens, entryTokens) >= threshold;
270
+ });
271
+ }
272
+ //# sourceMappingURL=feedback-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feedback-store.js","sourceRoot":"","sources":["../../src/storage/feedback-store.ts"],"names":[],"mappings":"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"}
@@ -16,4 +16,5 @@ export * as errorTelemetryStore from './error-telemetry-store.js';
16
16
  export * as specObservabilityStore from './spec-observability-store.js';
17
17
  export * as federationStore from './federation-store.js';
18
18
  export * as rbacStore from './rbac-store.js';
19
+ export * as conventionBaselineStore from './convention-baseline.js';
19
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,QAAQ,EACR,SAAS,EACT,cAAc,EACd,aAAa,GACd,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,SAAS,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,cAAc,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,aAAa,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,iBAAiB,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,oBAAoB,MAAM,6BAA6B,CAAC;AACpE,OAAO,KAAK,YAAY,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,mBAAmB,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,sBAAsB,MAAM,+BAA+B,CAAC;AACxE,OAAO,KAAK,eAAe,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,SAAS,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,QAAQ,EACR,SAAS,EACT,cAAc,EACd,aAAa,GACd,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,SAAS,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,cAAc,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,aAAa,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,iBAAiB,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,oBAAoB,MAAM,6BAA6B,CAAC;AACpE,OAAO,KAAK,YAAY,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,mBAAmB,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,sBAAsB,MAAM,+BAA+B,CAAC;AACxE,OAAO,KAAK,eAAe,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,SAAS,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,uBAAuB,MAAM,0BAA0B,CAAC"}
@@ -17,4 +17,5 @@ export * as errorTelemetryStore from './error-telemetry-store.js';
17
17
  export * as specObservabilityStore from './spec-observability-store.js';
18
18
  export * as federationStore from './federation-store.js';
19
19
  export * as rbacStore from './rbac-store.js';
20
+ export * as conventionBaselineStore from './convention-baseline.js';
20
21
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,OAAO,EACL,eAAe,EACf,QAAQ,EACR,SAAS,EACT,cAAc,EACd,aAAa,GACd,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,SAAS,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,cAAc,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,aAAa,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,iBAAiB,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,oBAAoB,MAAM,6BAA6B,CAAC;AACpE,OAAO,KAAK,YAAY,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,mBAAmB,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,sBAAsB,MAAM,+BAA+B,CAAC;AACxE,OAAO,KAAK,eAAe,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,SAAS,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,OAAO,EACL,eAAe,EACf,QAAQ,EACR,SAAS,EACT,cAAc,EACd,aAAa,GACd,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,SAAS,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,cAAc,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,aAAa,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,iBAAiB,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,oBAAoB,MAAM,6BAA6B,CAAC;AACpE,OAAO,KAAK,YAAY,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,mBAAmB,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,sBAAsB,MAAM,+BAA+B,CAAC;AACxE,OAAO,KAAK,eAAe,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,SAAS,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,uBAAuB,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { ToolResult } from '../types/index.js';
3
+ export declare function handleConfigHealth(args: {
4
+ projectId: string;
5
+ projectPath: string;
6
+ }): Promise<ToolResult>;
7
+ export declare function registerConfigHealthTool(server: McpServer): void;
8
+ //# sourceMappingURL=convention-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convention-sync.d.ts","sourceRoot":"","sources":["../../src/tools/convention-sync.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAwEpD,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,UAAU,CAAC,CAMtB;AAMD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAehE"}
@@ -0,0 +1,77 @@
1
+ // tools/convention-sync.ts — MCP tool: config_health
2
+ // Shows overall sync percentage between project conventions and their enforcement.
3
+ // READ-ONLY: never modifies files.
4
+ import { z } from 'zod';
5
+ import { calculateConventionSync } from '../engine/convention-sync.js';
6
+ import { getKnowledge } from '../storage/knowledge-store.js';
7
+ import { safeTracked } from './safe-handler.js';
8
+ // ---------------------------------------------------------------------------
9
+ // Zod schema
10
+ // ---------------------------------------------------------------------------
11
+ const configHealthSchema = {
12
+ projectId: z
13
+ .string()
14
+ .max(64)
15
+ .describe('Project identifier (hash) used to load project knowledge for skills analysis'),
16
+ projectPath: z.string().max(4096).describe('Absolute path to the project root to analyse'),
17
+ };
18
+ // ---------------------------------------------------------------------------
19
+ // Formatter
20
+ // ---------------------------------------------------------------------------
21
+ function scoreBar(score) {
22
+ const filled = Math.round(score / 10);
23
+ return '[' + '█'.repeat(filled) + '░'.repeat(10 - filled) + ']';
24
+ }
25
+ function formatReport(report) {
26
+ const { overallScore, rulesHealth, skillsHealth, hooksHealth, conventionHealth } = report;
27
+ const lines = [];
28
+ lines.push('# Convention Sync Health Report');
29
+ lines.push('');
30
+ lines.push(`## Overall Score: ${overallScore}/100 ${scoreBar(overallScore)}`);
31
+ lines.push('');
32
+ lines.push(`**${report.summary}**`);
33
+ lines.push('');
34
+ lines.push('## Dimension Breakdown');
35
+ lines.push('');
36
+ lines.push(`| Dimension | Score | Bar |`);
37
+ lines.push(`|-----------------|-------|----------------------------|`);
38
+ lines.push(`| Rules files | ${String(rulesHealth).padStart(3)}/100 | ${scoreBar(rulesHealth)} |`);
39
+ lines.push(`| Skills | ${String(skillsHealth).padStart(3)}/100 | ${scoreBar(skillsHealth)} |`);
40
+ lines.push(`| Git hooks | ${String(hooksHealth).padStart(3)}/100 | ${scoreBar(hooksHealth)} |`);
41
+ lines.push(`| Conventions | ${String(conventionHealth).padStart(3)}/100 | ${scoreBar(conventionHealth)} |`);
42
+ lines.push('');
43
+ if (report.recommendations.length > 0) {
44
+ lines.push('## Recommendations');
45
+ lines.push('');
46
+ for (const rec of report.recommendations) {
47
+ lines.push(`- ${rec}`);
48
+ }
49
+ lines.push('');
50
+ }
51
+ return lines.join('\n');
52
+ }
53
+ // ---------------------------------------------------------------------------
54
+ // Handler
55
+ // ---------------------------------------------------------------------------
56
+ export async function handleConfigHealth(args) {
57
+ const knowledge = await getKnowledge(args.projectId);
58
+ const report = await calculateConventionSync(args.projectPath, knowledge);
59
+ const text = formatReport(report);
60
+ const isError = report.overallScore === 0;
61
+ return { content: [{ type: 'text', text }], isError };
62
+ }
63
+ // ---------------------------------------------------------------------------
64
+ // Registration
65
+ // ---------------------------------------------------------------------------
66
+ export function registerConfigHealthTool(server) {
67
+ server.registerTool('config_health', {
68
+ description: "Calculate the overall sync percentage between the project's conventions and its enforcement mechanisms (rules files, skills, git hooks, convention violations). Returns a 0–100 weighted score with per-dimension breakdown and prioritised recommendations. READ-ONLY — never modifies files.",
69
+ inputSchema: configHealthSchema,
70
+ annotations: {
71
+ readOnlyHint: true,
72
+ destructiveHint: false,
73
+ title: 'Config Health',
74
+ },
75
+ }, safeTracked('config_health', async (args) => handleConfigHealth(args)));
76
+ }
77
+ //# sourceMappingURL=convention-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convention-sync.js","sourceRoot":"","sources":["../../src/tools/convention-sync.ts"],"names":[],"mappings":"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"}
@@ -126,7 +126,7 @@ export async function generatePostCreationSuggestions(projectPath, description,
126
126
  // Item 4: Suggest committing progress with conventional commits
127
127
  suggestions.push({
128
128
  tool: 'manage_git',
129
- reason: 'After implementing, save your progress frequently with conventional commits referencing the spec ID.',
129
+ reason: 'Save progress with git after implementing: `git commit -m "feat(SPEC-XXX): implementation checkpoint"` include the spec ID for traceability',
130
130
  });
131
131
  return suggestions;
132
132
  }
@@ -1 +1 @@
1
- {"version":3,"file":"post-creation.js","sourceRoot":"","sources":["../../../src/tools/create-spec/post-creation.ts"],"names":[],"mappings":"AAAA,wGAAwG;AACxG,kEAAkE;AAGlE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,SAAiB,EACjB,MAAc;IAEd,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACxD,+CAA+C;IAC/C,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;IACtD,CAAC;IACD,oBAAoB;IACpB,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,SAAiB,EACjB,MAAc,EACd,WAAmB;IAEnB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACtD,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACtC,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,OAAO,EAAE,CAAC,CAAC,KAAK,GAAG,GAAG,GAAG,WAAW;SACrC,CAAC,CAAC,CAAC;QACJ,MAAM,cAAc,GAAG,oBAAoB,CAAC,UAAU,CAAC,CAAC;QACxD,MAAM,qBAAqB,GAAG,cAAc,CAAC,MAAM,CACjD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,CAChD,CAAC;QACF,IAAI,qBAAqB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvC,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,QAAQ,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC;QAC/E,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC;YACxB,CAAC,CAAC,cAAc,QAAQ,CAAC,MAAM,sFAAsF;YACrH,CAAC,CAAC,aAAa,qBAAqB,CAAC,MAAM,8EAA8E,CAAC;IAC9H,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,mBAAmB,CAAC,SAAiB,EAAE,IAAU;IAC/D,sDAAsD;IACtD,KAAK,CAAC,KAAK,IAAmB,EAAE;QAC9B,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACjE,MAAM,EAAE,uBAAuB,EAAE,GAAG,MAAM,MAAM,CAAC,gCAAgC,CAAC,CAAC;QACnF,KAAK,iBAAiB,CACpB,SAAS,EACT,uBAAuB,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CACnE,CAAC;IACJ,CAAC,CAAC,EAAE,CAAC;AACP,CAAC;AAED,mEAAmE;AACnE,MAAM,mBAAmB,GAAa;IACpC,wCAAwC;IACxC,yDAAyD;IACzD,uDAAuD;IACvD,qDAAqD;IACrD,qCAAqC;IACrC,gCAAgC;IAChC,sDAAsD;IACtD,oEAAoE;IACpE,wDAAwD;IACxD,yDAAyD;IACzD,cAAc;CACf,CAAC;AAEF,8EAA8E;AAC9E,SAAS,sBAAsB,CAAC,WAAmB;IACjD,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,wCAAwC;AACxC,MAAM,oBAAoB,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,oBAAoB,EAAE,aAAa,CAAC,CAAC;AAElG,SAAS,qBAAqB,CAAC,SAAuC;IACpE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,KAAK,CAAC;IACf,CAAC;IACD,uEAAuE;IACvE,MAAM,QAAQ,GAAG,CAAC,SAAS,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAChF,uEAAuE;IACvE,MAAM,cAAc,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACxF,OAAO,oBAAoB,CAAC,IAAI,CAC9B,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CACzE,CAAC;AACJ,CAAC;AAED,oCAAoC;AACpC,MAAM,iBAAiB,GAA4C;IACjE,EAAE,OAAO,EAAE,0DAA0D,EAAE,QAAQ,EAAE,MAAM,EAAE;IACzF,EAAE,OAAO,EAAE,2CAA2C,EAAE,QAAQ,EAAE,MAAM,EAAE;IAC1E,EAAE,OAAO,EAAE,0CAA0C,EAAE,QAAQ,EAAE,UAAU,EAAE;IAC7E,EAAE,OAAO,EAAE,iDAAiD,EAAE,QAAQ,EAAE,eAAe,EAAE;CAC1F,CAAC;AAEF,kHAAkH;AAClH,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,WAAmB,EACnB,WAAmB,EACnB,SAA4B;IAE5B,MAAM,WAAW,GAA6B,EAAE,CAAC;IAEjD,kDAAkD;IAClD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,WAAW,CAAC,CAAC;QAC/C,IAAI,QAAQ,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC/B,WAAW,CAAC,IAAI,CAAC;gBACf,IAAI,EAAE,mBAAmB;gBACzB,MAAM,EACJ,oGAAoG;aACvG,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,mDAAmD;IACrD,CAAC;IAED,qFAAqF;IACrF,IAAI,sBAAsB,CAAC,WAAW,CAAC,EAAE,CAAC;QACxC,WAAW,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,iBAAiB;YACvB,MAAM,EACJ,8OAA8O;SACjP,CAAC,CAAC;IACL,CAAC;IAED,8EAA8E;IAC9E,IAAI,qBAAqB,CAAC,SAAS,CAAC,EAAE,CAAC;QACrC,WAAW,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,cAAc;YACpB,MAAM,EACJ,kMAAkM;SACrM,CAAC,CAAC;IACL,CAAC;IAED,oEAAoE;IACpE,KAAK,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,iBAAiB,EAAE,CAAC;QACtD,IAAI,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAC9B,WAAW,CAAC,IAAI,CAAC;gBACf,IAAI,EAAE,gBAAgB;gBACtB,MAAM,EAAE,wBAAwB,QAAQ,gCAAgC,QAAQ,YAAY;gBAC5F,gBAAgB,EAAE,QAAQ;aAC3B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,gEAAgE;IAChE,WAAW,CAAC,IAAI,CAAC;QACf,IAAI,EAAE,YAAY;QAClB,MAAM,EACJ,sGAAsG;KACzG,CAAC,CAAC;IAEH,OAAO,WAAW,CAAC;AACrB,CAAC"}
1
+ {"version":3,"file":"post-creation.js","sourceRoot":"","sources":["../../../src/tools/create-spec/post-creation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { ProjectKnowledge } from '../../../types/index.js';
2
+ /**
3
+ * Reads CLAUDE.md and .claude/rules/*.md conventions, then generates
4
+ * project-specific acceptance criteria that every spec should include.
5
+ *
6
+ * Returns `- [ ] ...` lines that enforce the project's own conventions.
7
+ */
8
+ export declare function generateConventionAcs(knowledge: ProjectKnowledge): string[];
9
+ //# sourceMappingURL=convention-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convention-adapter.d.ts","sourceRoot":"","sources":["../../../../src/tools/create-spec-hu/ac-adapters/convention-adapter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhE;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,gBAAgB,GAAG,MAAM,EAAE,CA0E3E"}
@@ -0,0 +1,68 @@
1
+ // tools/create-spec-hu/ac-adapters/convention-adapter.ts — SPEC-191
2
+ // Generates acceptance criteria from project conventions (CLAUDE.md + .claude/rules/)
3
+ import { parseConventions } from '../../../engine/convention-scanner/index.js';
4
+ /**
5
+ * Reads CLAUDE.md and .claude/rules/*.md conventions, then generates
6
+ * project-specific acceptance criteria that every spec should include.
7
+ *
8
+ * Returns `- [ ] ...` lines that enforce the project's own conventions.
9
+ */
10
+ export function generateConventionAcs(knowledge) {
11
+ const projectPath = knowledge.projectPath;
12
+ if (!projectPath) {
13
+ return [];
14
+ }
15
+ const rules = parseConventions(projectPath);
16
+ if (rules.length === 0) {
17
+ return [];
18
+ }
19
+ const acs = [];
20
+ // Group rules by category and generate one AC per category
21
+ const byCategory = new Map();
22
+ for (const rule of rules) {
23
+ const existing = byCategory.get(rule.category) ?? [];
24
+ existing.push(rule.description);
25
+ byCategory.set(rule.category, existing);
26
+ }
27
+ // Naming conventions
28
+ const naming = byCategory.get('naming');
29
+ if (naming) {
30
+ acs.push('- [ ] All new identifiers follow project naming conventions: ' +
31
+ naming.slice(0, 3).join('; '));
32
+ }
33
+ // i18n conventions
34
+ const i18n = byCategory.get('i18n');
35
+ if (i18n) {
36
+ acs.push('- [ ] No hardcoded user-facing strings — all text uses i18n/translation system');
37
+ }
38
+ // Architecture conventions
39
+ const arch = byCategory.get('architecture');
40
+ if (arch) {
41
+ acs.push('- [ ] Import patterns comply with project architecture rules: ' +
42
+ arch.slice(0, 2).join('; '));
43
+ }
44
+ // File limit conventions
45
+ const fileLimits = byCategory.get('file-limits');
46
+ if (fileLimits) {
47
+ acs.push('- [ ] File and function sizes within project limits: ' + fileLimits.slice(0, 2).join('; '));
48
+ }
49
+ // Code quality conventions
50
+ const codeQuality = byCategory.get('code-quality');
51
+ if (codeQuality) {
52
+ acs.push('- [ ] Code quality rules enforced: ' + codeQuality.slice(0, 3).join('; '));
53
+ }
54
+ // Testing conventions
55
+ const testing = byCategory.get('testing');
56
+ if (testing) {
57
+ acs.push('- [ ] Testing conventions followed: ' + testing.slice(0, 2).join('; '));
58
+ }
59
+ // Custom conventions
60
+ const custom = byCategory.get('custom');
61
+ if (custom) {
62
+ for (const desc of custom.slice(0, 3)) {
63
+ acs.push(`- [ ] ${desc}`);
64
+ }
65
+ }
66
+ return acs;
67
+ }
68
+ //# sourceMappingURL=convention-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convention-adapter.js","sourceRoot":"","sources":["../../../../src/tools/create-spec-hu/ac-adapters/convention-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { ProjectKnowledge } from '../../../types/index.js';
2
+ /**
3
+ * Reads `specTemplate` from the project's planu.json and converts each entry
4
+ * into a `- [ ] ...` acceptance criteria line.
5
+ *
6
+ * Supported keys inside `specTemplate`:
7
+ * - `acceptanceCriteria` — array of strings, one AC per item
8
+ * - `qualityGates` — array of strings, appended after acceptanceCriteria
9
+ *
10
+ * Returns an empty array when planu.json is absent, unreadable, or has no
11
+ * `specTemplate` section.
12
+ */
13
+ export declare function generateCustomTemplateAcs(knowledge: ProjectKnowledge): string[];
14
+ //# sourceMappingURL=custom-template-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-template-adapter.d.ts","sourceRoot":"","sources":["../../../../src/tools/create-spec-hu/ac-adapters/custom-template-adapter.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAmB,MAAM,yBAAyB,CAAC;AAkBjF;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,gBAAgB,GAAG,MAAM,EAAE,CAkC/E"}
@@ -0,0 +1,60 @@
1
+ // tools/create-spec-hu/ac-adapters/custom-template-adapter.ts
2
+ // Generates acceptance criteria from project-defined specTemplate in planu.json
3
+ import { readFileSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ function isStringArray(value) {
6
+ return Array.isArray(value) && value.every((item) => typeof item === 'string');
7
+ }
8
+ function readPlanuJsonConfig(projectPath) {
9
+ try {
10
+ const raw = JSON.parse(readFileSync(join(projectPath, 'planu.json'), 'utf-8'));
11
+ if (typeof raw !== 'object' || raw === null) {
12
+ return null;
13
+ }
14
+ return raw;
15
+ }
16
+ catch {
17
+ return null;
18
+ }
19
+ }
20
+ /**
21
+ * Reads `specTemplate` from the project's planu.json and converts each entry
22
+ * into a `- [ ] ...` acceptance criteria line.
23
+ *
24
+ * Supported keys inside `specTemplate`:
25
+ * - `acceptanceCriteria` — array of strings, one AC per item
26
+ * - `qualityGates` — array of strings, appended after acceptanceCriteria
27
+ *
28
+ * Returns an empty array when planu.json is absent, unreadable, or has no
29
+ * `specTemplate` section.
30
+ */
31
+ export function generateCustomTemplateAcs(knowledge) {
32
+ const projectPath = knowledge.projectPath;
33
+ if (!projectPath) {
34
+ return [];
35
+ }
36
+ const config = readPlanuJsonConfig(projectPath);
37
+ if (!config?.specTemplate) {
38
+ return [];
39
+ }
40
+ const { acceptanceCriteria, qualityGates } = config.specTemplate;
41
+ const acs = [];
42
+ if (isStringArray(acceptanceCriteria)) {
43
+ for (const criterion of acceptanceCriteria) {
44
+ const trimmed = criterion.trim();
45
+ if (trimmed) {
46
+ acs.push(`- [ ] ${trimmed}`);
47
+ }
48
+ }
49
+ }
50
+ if (isStringArray(qualityGates)) {
51
+ for (const gate of qualityGates) {
52
+ const trimmed = gate.trim();
53
+ if (trimmed) {
54
+ acs.push(`- [ ] ${trimmed}`);
55
+ }
56
+ }
57
+ }
58
+ return acs;
59
+ }
60
+ //# sourceMappingURL=custom-template-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-template-adapter.js","sourceRoot":"","sources":["../../../../src/tools/create-spec-hu/ac-adapters/custom-template-adapter.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,gFAAgF;AAEhF,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC;AACjF,CAAC;AAED,SAAS,mBAAmB,CAAC,WAAmB;IAC9C,IAAI,CAAC;QACH,MAAM,GAAG,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QACxF,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,GAAsB,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,yBAAyB,CAAC,SAA2B;IACnE,MAAM,WAAW,GAAG,SAAS,CAAC,WAAW,CAAC;IAC1C,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,MAAM,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAChD,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC;QAC1B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,EAAE,kBAAkB,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC;IAEjE,MAAM,GAAG,GAAa,EAAE,CAAC;IAEzB,IAAI,aAAa,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACtC,KAAK,MAAM,SAAS,IAAI,kBAAkB,EAAE,CAAC;YAC3C,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;YACjC,IAAI,OAAO,EAAE,CAAC;gBACZ,GAAG,CAAC,IAAI,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC;QAChC,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;YAChC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,OAAO,EAAE,CAAC;gBACZ,GAAG,CAAC,IAAI,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -3,8 +3,12 @@ export { generateArchitectureAcs } from './architecture-adapter.js';
3
3
  export { generateStackAcs } from './stack-adapter.js';
4
4
  export { generateDatabaseAcs } from './database-adapter.js';
5
5
  export { generateTestingAcs } from './testing-adapter.js';
6
+ export { generateConventionAcs } from './convention-adapter.js';
7
+ export { generateCustomTemplateAcs } from './custom-template-adapter.js';
6
8
  /**
7
9
  * Aggregates ACs from all specialized adapters, deduplicates, and returns the final list.
10
+ * SPEC-191: Now includes project-specific convention criteria from CLAUDE.md + .claude/rules/.
11
+ * Custom template ACs (from planu.json specTemplate) are prepended so they appear first.
8
12
  *
9
13
  * @param knowledge - Detected project knowledge (architecture, stack, DB, testing).
10
14
  * @param _specType - Spec type (reserved for future per-type filtering).
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/tools/create-spec-hu/ac-adapters/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAMhE,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAU/F"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/tools/create-spec-hu/ac-adapters/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAQhE,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAEzE;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAY/F"}