@promptci/core 0.0.1 → 0.1.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 (205) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +29 -30
  3. package/dist/agent-practices.d.ts +2 -0
  4. package/dist/agent-practices.d.ts.map +1 -1
  5. package/dist/agent-practices.js +91 -51
  6. package/dist/agent-practices.js.map +1 -1
  7. package/dist/ai-config.d.ts +139 -0
  8. package/dist/ai-config.d.ts.map +1 -0
  9. package/dist/ai-config.js +523 -0
  10. package/dist/ai-config.js.map +1 -0
  11. package/dist/baseline.d.ts +17 -1
  12. package/dist/baseline.d.ts.map +1 -1
  13. package/dist/baseline.js +5 -1
  14. package/dist/baseline.js.map +1 -1
  15. package/dist/buried-critical.d.ts +17 -0
  16. package/dist/buried-critical.d.ts.map +1 -0
  17. package/dist/buried-critical.js +112 -0
  18. package/dist/buried-critical.js.map +1 -0
  19. package/dist/canonical-owner.d.ts.map +1 -1
  20. package/dist/canonical-owner.js +18 -8
  21. package/dist/canonical-owner.js.map +1 -1
  22. package/dist/command-validity.d.ts.map +1 -1
  23. package/dist/command-validity.js +53 -74
  24. package/dist/command-validity.js.map +1 -1
  25. package/dist/conflicts.d.ts.map +1 -1
  26. package/dist/conflicts.js +1 -42
  27. package/dist/conflicts.js.map +1 -1
  28. package/dist/context-analysis.d.ts.map +1 -1
  29. package/dist/context-analysis.js +13 -2
  30. package/dist/context-analysis.js.map +1 -1
  31. package/dist/context-bloat.d.ts +19 -0
  32. package/dist/context-bloat.d.ts.map +1 -1
  33. package/dist/context-bloat.js +82 -9
  34. package/dist/context-bloat.js.map +1 -1
  35. package/dist/context-optimizer.d.ts.map +1 -1
  36. package/dist/context-optimizer.js +15 -54
  37. package/dist/context-optimizer.js.map +1 -1
  38. package/dist/copilot-instructions-detector.d.ts +24 -0
  39. package/dist/copilot-instructions-detector.d.ts.map +1 -0
  40. package/dist/copilot-instructions-detector.js +145 -0
  41. package/dist/copilot-instructions-detector.js.map +1 -0
  42. package/dist/cursor-rules-detector.d.ts +17 -0
  43. package/dist/cursor-rules-detector.d.ts.map +1 -0
  44. package/dist/cursor-rules-detector.js +110 -0
  45. package/dist/cursor-rules-detector.js.map +1 -0
  46. package/dist/custom-rules.d.ts +52 -0
  47. package/dist/custom-rules.d.ts.map +1 -0
  48. package/dist/custom-rules.js +298 -0
  49. package/dist/custom-rules.js.map +1 -0
  50. package/dist/dead-references.js +11 -9
  51. package/dist/dead-references.js.map +1 -1
  52. package/dist/detectors.d.ts +1 -3
  53. package/dist/detectors.d.ts.map +1 -1
  54. package/dist/detectors.js +46 -53
  55. package/dist/detectors.js.map +1 -1
  56. package/dist/duplicates.d.ts.map +1 -1
  57. package/dist/duplicates.js +10 -5
  58. package/dist/duplicates.js.map +1 -1
  59. package/dist/evidence.d.ts +28 -0
  60. package/dist/evidence.d.ts.map +1 -0
  61. package/dist/evidence.js +38 -0
  62. package/dist/evidence.js.map +1 -0
  63. package/dist/fix-engine.d.ts +11 -0
  64. package/dist/fix-engine.d.ts.map +1 -1
  65. package/dist/fix-engine.js +88 -71
  66. package/dist/fix-engine.js.map +1 -1
  67. package/dist/frameworks/python.d.ts.map +1 -1
  68. package/dist/frameworks/python.js +5 -2
  69. package/dist/frameworks/python.js.map +1 -1
  70. package/dist/health-score.d.ts.map +1 -1
  71. package/dist/health-score.js +1 -0
  72. package/dist/health-score.js.map +1 -1
  73. package/dist/hooks-settings-detector.d.ts +17 -0
  74. package/dist/hooks-settings-detector.d.ts.map +1 -0
  75. package/dist/hooks-settings-detector.js +228 -0
  76. package/dist/hooks-settings-detector.js.map +1 -0
  77. package/dist/index.d.ts +22 -7
  78. package/dist/index.d.ts.map +1 -1
  79. package/dist/index.js +18 -6
  80. package/dist/index.js.map +1 -1
  81. package/dist/manifest-consistency.d.ts +6 -0
  82. package/dist/manifest-consistency.d.ts.map +1 -1
  83. package/dist/manifest-consistency.js +26 -5
  84. package/dist/manifest-consistency.js.map +1 -1
  85. package/dist/markdown-fences.d.ts +112 -0
  86. package/dist/markdown-fences.d.ts.map +1 -0
  87. package/dist/markdown-fences.js +174 -0
  88. package/dist/markdown-fences.js.map +1 -0
  89. package/dist/mcp-config-detector.d.ts +20 -0
  90. package/dist/mcp-config-detector.d.ts.map +1 -0
  91. package/dist/mcp-config-detector.js +237 -0
  92. package/dist/mcp-config-detector.js.map +1 -0
  93. package/dist/missing-context.d.ts.map +1 -1
  94. package/dist/missing-context.js +2 -52
  95. package/dist/missing-context.js.map +1 -1
  96. package/dist/model-budgets.d.ts +69 -0
  97. package/dist/model-budgets.d.ts.map +1 -0
  98. package/dist/model-budgets.js +110 -0
  99. package/dist/model-budgets.js.map +1 -0
  100. package/dist/negative-instructions.d.ts +26 -0
  101. package/dist/negative-instructions.d.ts.map +1 -0
  102. package/dist/negative-instructions.js +174 -0
  103. package/dist/negative-instructions.js.map +1 -0
  104. package/dist/path-containment.d.ts +12 -0
  105. package/dist/path-containment.d.ts.map +1 -0
  106. package/dist/path-containment.js +53 -0
  107. package/dist/path-containment.js.map +1 -0
  108. package/dist/project-type.d.ts +12 -2
  109. package/dist/project-type.d.ts.map +1 -1
  110. package/dist/project-type.js +25 -12
  111. package/dist/project-type.js.map +1 -1
  112. package/dist/prompt-cache.d.ts.map +1 -1
  113. package/dist/prompt-cache.js +26 -19
  114. package/dist/prompt-cache.js.map +1 -1
  115. package/dist/promptci-gitignore.d.ts +34 -0
  116. package/dist/promptci-gitignore.d.ts.map +1 -0
  117. package/dist/promptci-gitignore.js +42 -0
  118. package/dist/promptci-gitignore.js.map +1 -0
  119. package/dist/repo-context.d.ts +27 -0
  120. package/dist/repo-context.d.ts.map +1 -1
  121. package/dist/repo-context.js +42 -11
  122. package/dist/repo-context.js.map +1 -1
  123. package/dist/report.d.ts +1 -0
  124. package/dist/report.d.ts.map +1 -1
  125. package/dist/report.js +132 -61
  126. package/dist/report.js.map +1 -1
  127. package/dist/scan.d.ts.map +1 -1
  128. package/dist/scan.js +7 -3
  129. package/dist/scan.js.map +1 -1
  130. package/dist/scanner.d.ts +13 -1
  131. package/dist/scanner.d.ts.map +1 -1
  132. package/dist/scanner.js +49 -37
  133. package/dist/scanner.js.map +1 -1
  134. package/dist/security-pack.d.ts +20 -0
  135. package/dist/security-pack.d.ts.map +1 -1
  136. package/dist/security-pack.js +27 -10
  137. package/dist/security-pack.js.map +1 -1
  138. package/dist/skills-detector.d.ts +19 -0
  139. package/dist/skills-detector.d.ts.map +1 -0
  140. package/dist/skills-detector.js +203 -0
  141. package/dist/skills-detector.js.map +1 -0
  142. package/dist/stale-instructions.d.ts +4 -1
  143. package/dist/stale-instructions.d.ts.map +1 -1
  144. package/dist/stale-instructions.js +51 -54
  145. package/dist/stale-instructions.js.map +1 -1
  146. package/dist/subagents-detector.d.ts +19 -0
  147. package/dist/subagents-detector.d.ts.map +1 -0
  148. package/dist/subagents-detector.js +155 -0
  149. package/dist/subagents-detector.js.map +1 -0
  150. package/dist/suppression.d.ts.map +1 -1
  151. package/dist/suppression.js +11 -45
  152. package/dist/suppression.js.map +1 -1
  153. package/dist/types.d.ts +28 -3
  154. package/dist/types.d.ts.map +1 -1
  155. package/dist/types.js +25 -1
  156. package/dist/types.js.map +1 -1
  157. package/dist/vague-guidance.d.ts +15 -2
  158. package/dist/vague-guidance.d.ts.map +1 -1
  159. package/dist/vague-guidance.js +42 -40
  160. package/dist/vague-guidance.js.map +1 -1
  161. package/dist/windsurf-detector.d.ts +22 -0
  162. package/dist/windsurf-detector.d.ts.map +1 -0
  163. package/dist/windsurf-detector.js +87 -0
  164. package/dist/windsurf-detector.js.map +1 -0
  165. package/dist/within-section-dedup.d.ts +16 -0
  166. package/dist/within-section-dedup.d.ts.map +1 -0
  167. package/dist/within-section-dedup.js +153 -0
  168. package/dist/within-section-dedup.js.map +1 -0
  169. package/package.json +11 -8
  170. package/dist/cheap-model-routing.d.ts +0 -4
  171. package/dist/cheap-model-routing.d.ts.map +0 -1
  172. package/dist/cheap-model-routing.js +0 -43
  173. package/dist/cheap-model-routing.js.map +0 -1
  174. package/dist/cli-output-filter.d.ts +0 -16
  175. package/dist/cli-output-filter.d.ts.map +0 -1
  176. package/dist/cli-output-filter.js +0 -88
  177. package/dist/cli-output-filter.js.map +0 -1
  178. package/dist/context-cost.d.ts +0 -4
  179. package/dist/context-cost.d.ts.map +0 -1
  180. package/dist/context-cost.js +0 -70
  181. package/dist/context-cost.js.map +0 -1
  182. package/dist/context-recommender.d.ts +0 -3
  183. package/dist/context-recommender.d.ts.map +0 -1
  184. package/dist/context-recommender.js +0 -329
  185. package/dist/context-recommender.js.map +0 -1
  186. package/dist/llm.d.ts +0 -6
  187. package/dist/llm.d.ts.map +0 -1
  188. package/dist/llm.js +0 -67
  189. package/dist/llm.js.map +0 -1
  190. package/dist/mcp-detector.d.ts +0 -4
  191. package/dist/mcp-detector.d.ts.map +0 -1
  192. package/dist/mcp-detector.js +0 -131
  193. package/dist/mcp-detector.js.map +0 -1
  194. package/dist/native-tool-preference.d.ts +0 -20
  195. package/dist/native-tool-preference.d.ts.map +0 -1
  196. package/dist/native-tool-preference.js +0 -94
  197. package/dist/native-tool-preference.js.map +0 -1
  198. package/dist/output-verbosity.d.ts +0 -3
  199. package/dist/output-verbosity.d.ts.map +0 -1
  200. package/dist/output-verbosity.js +0 -83
  201. package/dist/output-verbosity.js.map +0 -1
  202. package/dist/product-boundary.d.ts +0 -11
  203. package/dist/product-boundary.d.ts.map +0 -1
  204. package/dist/product-boundary.js +0 -301
  205. package/dist/product-boundary.js.map +0 -1
package/dist/types.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  /** Core data types for PromptCI */
2
- export type FileType = 'claude' | 'agents' | 'cursor' | 'copilot' | 'readme' | 'docs' | 'prompt' | 'unknown';
2
+ export type FileType = 'claude' | 'agents' | 'cursor' | 'windsurf' | 'copilot' | 'readme' | 'docs' | 'prompt' | 'skill' | 'agent' | 'unknown';
3
+ export declare function isOnDemandFileType(fileType: FileType): boolean;
3
4
  export type IssueSeverity = 'info' | 'warning' | 'high' | 'critical';
4
- export type IssueCategory = 'duplicate' | 'conflict' | 'context_bloat' | 'missing_context' | 'stale_instruction' | 'vague_guidance' | 'structure' | 'command_validity' | 'agent_practices' | 'security';
5
+ export type IssueCategory = 'duplicate' | 'conflict' | 'context_bloat' | 'missing_context' | 'stale_instruction' | 'vague_guidance' | 'structure' | 'command_validity' | 'agent_practices' | 'ai_config' | 'security' | 'custom';
5
6
  export type InstructionSection = {
6
7
  id: string;
7
8
  filePath: string;
@@ -34,7 +35,15 @@ export type PromptCiIssue = {
34
35
  }>;
35
36
  evidence: string[];
36
37
  recommendation: string;
38
+ /** Advisory, human-readable "here's how to fix it" text. Not machine-applied. */
37
39
  fixRecipe?: string;
40
+ /**
41
+ * True only when `applyFixRecipe` implements a mechanical, reversible edit for
42
+ * this issue and it is safe to auto-apply. Gates `promptci fix` (see
43
+ * `isRepairable`). Detectors set this deliberately per recipe — it is never
44
+ * inferred from the presence of `fixRecipe`, which is usually advisory prose.
45
+ */
46
+ autoApplySafe?: boolean;
38
47
  confidence: number;
39
48
  tags?: string[];
40
49
  impact?: 'high' | 'medium' | 'low';
@@ -44,7 +53,8 @@ export type TopFix = {
44
53
  reason: string;
45
54
  suggestedAction: string;
46
55
  };
47
- export type ProjectType = 'auto' | 'typescript' | 'nextjs' | 'unity' | 'dotnet' | 'python' | 'go' | 'rust' | 'unknown';
56
+ export declare const PROJECT_TYPES: readonly ["auto", "typescript", "nextjs", "unity", "dotnet", "python", "go", "rust", "unknown"];
57
+ export type ProjectType = (typeof PROJECT_TYPES)[number];
48
58
  export type ScanTrend = {
49
59
  previousScanDate?: string;
50
60
  scoreDelta: number;
@@ -83,6 +93,8 @@ export type ScanMetrics = {
83
93
  path: string;
84
94
  estimatedTokens: number;
85
95
  }>;
96
+ onDemandFileCount?: number;
97
+ estimatedOnDemandTokens?: number;
86
98
  };
87
99
  /**
88
100
  * R1: report.json intentionally omits InstructionFile's `content` and
@@ -124,5 +136,18 @@ export type ScanInput = {
124
136
  baseline?: Baseline;
125
137
  contextBudget?: number;
126
138
  fileContextBudget?: number;
139
+ /**
140
+ * FEAT-012: a target-model preset name (e.g. `claude-opus-5`) that scales the
141
+ * context-bloat thresholds to that model's context window. An explicit
142
+ * `contextBudget`/`fileContextBudget` always overrides the preset. Surfaced
143
+ * as the `targetModel` config key and `--target-model` flag.
144
+ */
145
+ targetModel?: string;
146
+ /**
147
+ * FEAT-004: force every vague-guidance finding to this severity, overriding
148
+ * the detector's high-signal/soft tiering. Surfaced as the
149
+ * `vagueGuidanceSeverity` config key.
150
+ */
151
+ vagueGuidanceSeverity?: 'info' | 'warning';
127
152
  };
128
153
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAMnC,MAAM,MAAM,QAAQ,GAChB,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,SAAS,GACT,QAAQ,GACR,MAAM,GACN,QAAQ,GACR,OAAO,GACP,OAAO,GACP,SAAS,CAAC;AAUd,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAE9D;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;AAErE,MAAM,MAAM,aAAa,GACrB,WAAW,GACX,UAAU,GACV,eAAe,GACf,iBAAiB,GACjB,mBAAmB,GACnB,gBAAgB,GAChB,WAAW,GACX,kBAAkB,GAClB,iBAAiB,GACjB,WAAW,GACX,UAAU,GAEV,QAAQ,CAAC;AAEb,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,aAAa,CAAC;IACxB,QAAQ,EAAE,aAAa,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7E,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAMF,eAAO,MAAM,aAAa,iGAUhB,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,MAAM,MAAM,SAAS,GAAG;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,aAAa,EAAE,KAAK,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,YAAY,EAAE,eAAe,EAAE,CAAC;IAChC,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC;IAC5B,eAAe,CAAC,EAAE,aAAa,EAAE,CAAC;IAClC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,aAAa,EAAE,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,0BAA0B,EAAE,MAAM,CAAC;IACnC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,uBAAuB,EAAE,KAAK,CAAC;QAC7B,IAAI,EAAE,MAAM,CAAC;QACb,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC,CAAC;IAGH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,GAAG,WAAW,GAAG,iBAAiB,CAAC,CAAC;AAE5H,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,GAAG;IAC9D,YAAY,EAAE,kBAAkB,EAAE,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC;AAEvC,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5C,CAAC"}
package/dist/types.js CHANGED
@@ -1,3 +1,27 @@
1
1
  /** Core data types for PromptCI */
2
- export {};
2
+ /**
3
+ * On-demand file types are loaded by an agent only when a skill/subagent is
4
+ * invoked, not on every turn. They do not count toward always-loaded context
5
+ * cost and are owned by the ai_config detectors, so the generic prose detectors
6
+ * skip them.
7
+ */
8
+ const ON_DEMAND_FILE_TYPES = new Set(['skill', 'agent']);
9
+ export function isOnDemandFileType(fileType) {
10
+ return ON_DEMAND_FILE_TYPES.has(fileType);
11
+ }
12
+ // Single source of truth: consumers that need to *validate* a project type at
13
+ // runtime (the CLI's config loader, `promptci init`) import this array rather
14
+ // than keeping their own copy, which is how `python`/`go`/`rust` previously
15
+ // ended up writable by `init` but rejected by `loadConfig`.
16
+ export const PROJECT_TYPES = [
17
+ 'auto',
18
+ 'typescript',
19
+ 'nextjs',
20
+ 'unity',
21
+ 'dotnet',
22
+ 'python',
23
+ 'go',
24
+ 'rust',
25
+ 'unknown',
26
+ ];
3
27
  //# sourceMappingURL=types.js.map
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,mCAAmC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAmBnC;;;;;GAKG;AACH,MAAM,oBAAoB,GAA0B,IAAI,GAAG,CAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAE1F,MAAM,UAAU,kBAAkB,CAAC,QAAkB;IACnD,OAAO,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC5C,CAAC;AAqED,8EAA8E;AAC9E,8EAA8E;AAC9E,4EAA4E;AAC5E,4DAA4D;AAC5D,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,MAAM;IACN,YAAY;IACZ,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,IAAI;IACJ,MAAM;IACN,SAAS;CACD,CAAC"}
@@ -5,8 +5,21 @@
5
5
  * Emits at most one issue per section regardless of how many vague phrases
6
6
  * appear in it.
7
7
  *
8
- * Heuristic detector — confidence 0.8, severity "info".
8
+ * Heuristic detector. Findings are tiered (FEAT-004): high-signal platitudes
9
+ * ("write clean code", "best practices", "SOLID principles", …) are
10
+ * warning 0.80; soft style/UX/paradigm phrases are info 0.75. A team can force
11
+ * one severity for every finding via the `severityOverride` option (wired to
12
+ * the `vagueGuidanceSeverity` config key).
9
13
  */
10
14
  import type { InstructionFile, PromptCiIssue } from './types.js';
11
- export declare function detectVagueGuidance(files: InstructionFile[]): PromptCiIssue[];
15
+ export type VagueGuidanceOptions = {
16
+ /**
17
+ * FEAT-004: force every vague-guidance finding to this severity, overriding
18
+ * the per-section high-signal/soft tiering. Wired to the `vagueGuidanceSeverity`
19
+ * config key so teams can enforce a stricter (all-warning) or looser
20
+ * (all-info) posture. Confidence still reflects the matched tier.
21
+ */
22
+ severityOverride?: 'info' | 'warning';
23
+ };
24
+ export declare function detectVagueGuidance(files: InstructionFile[], options?: VagueGuidanceOptions): PromptCiIssue[];
12
25
  //# sourceMappingURL=vague-guidance.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"vague-guidance.d.ts","sourceRoot":"","sources":["../src/vague-guidance.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAsB,aAAa,EAAE,MAAM,YAAY,CAAC;AA8LrF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,aAAa,EAAE,CAsD7E"}
1
+ {"version":3,"file":"vague-guidance.d.ts","sourceRoot":"","sources":["../src/vague-guidance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAqC,aAAa,EAAE,MAAM,YAAY,CAAC;AAqLpG,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC,CAAC;AAEF,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,eAAe,EAAE,EACxB,OAAO,GAAE,oBAAyB,GACjC,aAAa,EAAE,CA8DjB"}
@@ -5,9 +5,14 @@
5
5
  * Emits at most one issue per section regardless of how many vague phrases
6
6
  * appear in it.
7
7
  *
8
- * Heuristic detector — confidence 0.8, severity "info".
8
+ * Heuristic detector. Findings are tiered (FEAT-004): high-signal platitudes
9
+ * ("write clean code", "best practices", "SOLID principles", …) are
10
+ * warning 0.80; soft style/UX/paradigm phrases are info 0.75. A team can force
11
+ * one severity for every finding via the `severityOverride` option (wired to
12
+ * the `vagueGuidanceSeverity` config key).
9
13
  */
10
14
  import * as crypto from 'node:crypto';
15
+ import { stripCodeBlocks } from './markdown-fences.js';
11
16
  const VAGUE_PHRASES = [
12
17
  'write clean code',
13
18
  'write clean', // catches "write clean Go code", "write clean Python code", etc.
@@ -105,6 +110,31 @@ function expandHyphenVariants(phrases) {
105
110
  return [...expanded];
106
111
  }
107
112
  const ALL_VAGUE_PHRASES = expandHyphenVariants(VAGUE_PHRASES);
113
+ /**
114
+ * FEAT-004: High-signal platitudes. These are the phrases that most reliably
115
+ * mark instruction rot — broad quality/effort exhortations that give an agent
116
+ * no constraint at all. A section containing any of them is emitted at
117
+ * `warning` (0.80); sections whose only matches are softer style/UX/paradigm
118
+ * phrases stay `info` (0.75). Listed in the post-hyphen-expansion form so the
119
+ * no-hyphen twins ("production ready" ↔ "production-ready") both qualify.
120
+ */
121
+ const HIGH_SIGNAL_PHRASES = new Set([
122
+ 'write clean code',
123
+ 'write clean',
124
+ 'use best practices',
125
+ 'best practices',
126
+ 'follow best practices',
127
+ 'make it production ready',
128
+ 'production ready',
129
+ 'production-ready',
130
+ 'production quality',
131
+ 'production-quality',
132
+ 'be careful',
133
+ 'solid principles',
134
+ 'follow solid',
135
+ 'clean architecture',
136
+ 'make it maintainable',
137
+ ]);
108
138
  function escapeRegExp(text) {
109
139
  return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
110
140
  }
@@ -115,41 +145,6 @@ function escapeRegExp(text) {
115
145
  * reused across every section/file.
116
146
  */
117
147
  const PHRASE_PATTERNS = new Map(ALL_VAGUE_PHRASES.map((phrase) => [phrase, new RegExp(`\\b${escapeRegExp(phrase)}\\b`)]));
118
- /**
119
- * V4: Strip fenced code blocks (``` and ~~~, matching either fence
120
- * character/length per CommonMark — see scanner.ts) and inline code spans
121
- * before matching. A fenced example that quotes a vague phrase is
122
- * documentation about the phrase, not real guidance directed at the agent.
123
- */
124
- function stripCodeBlocks(text) {
125
- const lines = text.split('\n');
126
- const kept = [];
127
- let inBlock = false;
128
- let fenceChar = null;
129
- let fenceLen = 0;
130
- for (const line of lines) {
131
- if (!inBlock) {
132
- const openMatch = /^ {0,3}([`~]{3,})/.exec(line);
133
- if (openMatch) {
134
- inBlock = true;
135
- fenceChar = openMatch[1][0] ?? null;
136
- fenceLen = openMatch[1].length;
137
- continue;
138
- }
139
- kept.push(line);
140
- }
141
- else {
142
- const closeMatch = /^ {0,3}([`~]{3,})\s*$/.exec(line);
143
- if (closeMatch && closeMatch[1][0] === fenceChar && closeMatch[1].length >= fenceLen) {
144
- inBlock = false;
145
- fenceChar = null;
146
- fenceLen = 0;
147
- }
148
- // else: still inside the fence — drop the line
149
- }
150
- }
151
- return kept.join('\n').replace(/`[^`\n]+`/g, '');
152
- }
153
148
  /**
154
149
  * V1: Find lines (or pairs of consecutive wrapped lines) containing `phraseRe`
155
150
  * within the per-line length budget. Hard-wrapped guidance like:
@@ -181,7 +176,7 @@ function issueId(section) {
181
176
  const hash = crypto.createHash('sha1').update(key).digest('hex').slice(0, 12);
182
177
  return `vague-${hash}`;
183
178
  }
184
- export function detectVagueGuidance(files) {
179
+ export function detectVagueGuidance(files, options = {}) {
185
180
  const issues = [];
186
181
  // One issue per section — collect all matching phrases and lines first
187
182
  const seen = new Set();
@@ -190,7 +185,7 @@ export function detectVagueGuidance(files) {
190
185
  const sectionKey = `${file.path}:${section.startLine}`;
191
186
  if (seen.has(sectionKey))
192
187
  continue;
193
- const scanText = stripCodeBlocks(section.text);
188
+ const scanText = stripCodeBlocks(section.text, { stripInlineCode: true });
194
189
  // V1: collapse newlines to spaces for this fast pre-filter only, so a
195
190
  // phrase hard-wrapped across two lines still passes the gate. The actual
196
191
  // evidence extraction below (findPhraseMatches) independently re-checks
@@ -214,9 +209,16 @@ export function detectVagueGuidance(files) {
214
209
  continue;
215
210
  seen.add(sectionKey);
216
211
  const phraseList = matchedPhrases.map((p) => `"${p}"`).join(', ');
212
+ // FEAT-004: tier by the strongest phrase in the section. Any high-signal
213
+ // platitude escalates the whole finding to warning; a config override,
214
+ // when set, wins over the derived tier (but not the tier-based confidence).
215
+ const isHighSignal = matchedPhrases.some((p) => HIGH_SIGNAL_PHRASES.has(p));
216
+ const tierSeverity = isHighSignal ? 'warning' : 'info';
217
+ const severity = options.severityOverride ?? tierSeverity;
218
+ const confidence = isHighSignal ? 0.8 : 0.75;
217
219
  issues.push({
218
220
  id: issueId(section),
219
- severity: 'info',
221
+ severity,
220
222
  category: 'vague_guidance',
221
223
  title: 'Vague guidance detected',
222
224
  summary: `This section contains guidance that may be too vague to be actionable: ${phraseList}.`,
@@ -226,7 +228,7 @@ export function detectVagueGuidance(files) {
226
228
  recommendation: 'Replace vague guidance with concrete constraints — specific commands, forbidden ' +
227
229
  'patterns, or measurable criteria. For example, replace "write clean code" with ' +
228
230
  '"functions must be ≤ 50 lines; no unused variables".',
229
- confidence: 0.8,
231
+ confidence,
230
232
  });
231
233
  }
232
234
  }
@@ -1 +1 @@
1
- {"version":3,"file":"vague-guidance.js","sourceRoot":"","sources":["../src/vague-guidance.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vague-guidance.js","sourceRoot":"","sources":["../src/vague-guidance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Windsurf Rules Detector (issue #67)
3
+ *
4
+ * `.windsurfrules` is Windsurf's legacy, always-on, workspace-wide rules file:
5
+ * every rule in it is fed to the model on every request for the whole
6
+ * workspace. Windsurf also supports scoped `.windsurf/rules/*.md` files with
7
+ * glob / manual / model-decision activation.
8
+ *
9
+ * This detector flags one thing the generic prose detectors miss: a workspace
10
+ * `.windsurfrules` that clearly carries language- or framework-specific rules,
11
+ * which are cheaper as glob-scoped rules that load only for matching files. It
12
+ * emits a single cautious `info` suggesting the author clarify intended scope.
13
+ *
14
+ * The Windsurf-specific size/truncation check for `.windsurfrules` lives in
15
+ * `context-bloat.ts`, alongside the other file-type-specific size thresholds.
16
+ *
17
+ * Deterministic and offline.
18
+ */
19
+ import type { RepoContext } from './repo-context.js';
20
+ import type { PromptCiIssue } from './types.js';
21
+ export declare function detectWindsurfRules(context: RepoContext): PromptCiIssue[];
22
+ //# sourceMappingURL=windsurf-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windsurf-detector.d.ts","sourceRoot":"","sources":["../src/windsurf-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAkChD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,WAAW,GAAG,aAAa,EAAE,CAwCzE"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Windsurf Rules Detector (issue #67)
3
+ *
4
+ * `.windsurfrules` is Windsurf's legacy, always-on, workspace-wide rules file:
5
+ * every rule in it is fed to the model on every request for the whole
6
+ * workspace. Windsurf also supports scoped `.windsurf/rules/*.md` files with
7
+ * glob / manual / model-decision activation.
8
+ *
9
+ * This detector flags one thing the generic prose detectors miss: a workspace
10
+ * `.windsurfrules` that clearly carries language- or framework-specific rules,
11
+ * which are cheaper as glob-scoped rules that load only for matching files. It
12
+ * emits a single cautious `info` suggesting the author clarify intended scope.
13
+ *
14
+ * The Windsurf-specific size/truncation check for `.windsurfrules` lives in
15
+ * `context-bloat.ts`, alongside the other file-type-specific size thresholds.
16
+ *
17
+ * Deterministic and offline.
18
+ */
19
+ import { shortHash } from './ai-config.js';
20
+ /**
21
+ * Language / framework signals that, when they appear as SECTION HEADINGS in an
22
+ * always-on workspace file, indicate rules scoped to only part of the codebase.
23
+ * Heading-only matching keeps this precise: a passing mention of "python" in
24
+ * prose does not count, but a `## Python` section does. Terms are chosen to be
25
+ * unambiguous in a heading (e.g. `golang`, not bare `go`).
26
+ */
27
+ const SCOPED_TOPICS = [
28
+ { label: 'TypeScript', re: /\btypescript\b/i },
29
+ { label: 'JavaScript', re: /\bjavascript\b/i },
30
+ { label: 'Python', re: /\bpython\b/i },
31
+ { label: 'Rust', re: /\brust\b/i },
32
+ { label: 'Go', re: /\bgolang\b/i },
33
+ { label: 'Ruby', re: /\bruby\b|\brails\b/i },
34
+ { label: 'Java', re: /\bjava\b(?!script)/i },
35
+ { label: 'Kotlin', re: /\bkotlin\b/i },
36
+ { label: 'Swift', re: /\bswift\b/i },
37
+ { label: 'C#', re: /\bc#|\bcsharp\b|\bdotnet\b|\.net\b/i },
38
+ { label: 'React', re: /\breact\b/i },
39
+ { label: 'Vue', re: /\bvue\b/i },
40
+ { label: 'Svelte', re: /\bsvelte\b/i },
41
+ { label: 'Django', re: /\bdjango\b/i },
42
+ ];
43
+ /**
44
+ * Two or more distinct scoped topics in headings is a strong, low-noise signal
45
+ * that an always-on file mixes rule sets that would be better glob-scoped. One
46
+ * topic is left alone — a single `## Python` section in a Python repo is normal.
47
+ */
48
+ const MIN_DISTINCT_TOPICS = 2;
49
+ export function detectWindsurfRules(context) {
50
+ const issues = [];
51
+ for (const file of context.files) {
52
+ if (file.fileType !== 'windsurf')
53
+ continue;
54
+ const topics = new Set();
55
+ for (const section of file.sections) {
56
+ const heading = section.heading;
57
+ if (!heading)
58
+ continue;
59
+ for (const topic of SCOPED_TOPICS) {
60
+ if (topic.re.test(heading))
61
+ topics.add(topic.label);
62
+ }
63
+ }
64
+ if (topics.size >= MIN_DISTINCT_TOPICS) {
65
+ const found = [...topics].sort();
66
+ issues.push({
67
+ id: `ai-config-windsurf-scope-${shortHash(file.path)}`,
68
+ severity: 'info',
69
+ category: 'ai_config',
70
+ title: '.windsurfrules mixes language-specific rules in a workspace-wide file',
71
+ summary: `This \`.windsurfrules\` has headings for multiple languages/frameworks ` +
72
+ `(${found.join(', ')}), but it applies to the whole workspace on every ` +
73
+ `request. Language- or framework-specific rules are cheaper as glob-scoped ` +
74
+ `rules that load only for matching files.`,
75
+ filePaths: [file.path],
76
+ locations: [{ filePath: file.path, startLine: 1 }],
77
+ evidence: [`Scoped topics found in headings: ${found.join(', ')}`],
78
+ recommendation: 'Clarify the intended scope: keep genuinely workspace-wide conventions in ' +
79
+ '`.windsurfrules`, and move language- or framework-specific rules into ' +
80
+ 'glob-scoped `.windsurf/rules/*.md` files, each with a glob trigger.',
81
+ confidence: 0.6,
82
+ });
83
+ }
84
+ }
85
+ return issues;
86
+ }
87
+ //# sourceMappingURL=windsurf-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windsurf-detector.js","sourceRoot":"","sources":["../src/windsurf-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,aAAa,GAAyC;IAC1D,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,EAAE,iBAAiB,EAAE;IAC9C,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,EAAE,iBAAiB,EAAE;IAC9C,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,aAAa,EAAE;IACtC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE;IAClC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,aAAa,EAAE;IAClC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,qBAAqB,EAAE;IAC5C,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,qBAAqB,EAAE;IAC5C,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,aAAa,EAAE;IACtC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE;IACpC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,qCAAqC,EAAE;IAC1D,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE;IACpC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,UAAU,EAAE;IAChC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,aAAa,EAAE;IACtC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,aAAa,EAAE;CACvC,CAAC;AAEF;;;;GAIG;AACH,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAE9B,MAAM,UAAU,mBAAmB,CAAC,OAAoB;IACtD,MAAM,MAAM,GAAoB,EAAE,CAAC;IAEnC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACjC,IAAI,IAAI,CAAC,QAAQ,KAAK,UAAU;YAAE,SAAS;QAE3C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;QACjC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;YAChC,IAAI,CAAC,OAAO;gBAAE,SAAS;YACvB,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;gBAClC,IAAI,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;oBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,IAAI,IAAI,mBAAmB,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;YACjC,MAAM,CAAC,IAAI,CAAC;gBACV,EAAE,EAAE,4BAA4B,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACtD,QAAQ,EAAE,MAAM;gBAChB,QAAQ,EAAE,WAAW;gBACrB,KAAK,EAAE,uEAAuE;gBAC9E,OAAO,EACL,yEAAyE;oBACzE,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,oDAAoD;oBACxE,4EAA4E;oBAC5E,0CAA0C;gBAC5C,SAAS,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;gBACtB,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;gBAClD,QAAQ,EAAE,CAAC,oCAAoC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClE,cAAc,EACZ,2EAA2E;oBAC3E,wEAAwE;oBACxE,qEAAqE;gBACvE,UAAU,EAAE,GAAG;aAChB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Within-section semantic dedup detector (FEAT-013).
3
+ *
4
+ * The cross-file `detectDuplicates` detector works at section granularity and
5
+ * misses a single section that restates the same point several ways. This
6
+ * detector looks *inside* a section: for sections with more than five
7
+ * paragraphs, it computes pairwise Jaccard similarity on the paragraphs and
8
+ * flags any pair that is ≥ 0.65 similar, naming the paragraph numbers.
9
+ *
10
+ * Info severity only — near-duplicate prose within one section is worth a
11
+ * gentle nudge, not a hard failure. Deterministic: no clock, network, or
12
+ * randomness.
13
+ */
14
+ import type { InstructionFile, PromptCiIssue } from './types.js';
15
+ export declare function detectWithinSectionDedup(files: InstructionFile[]): PromptCiIssue[];
16
+ //# sourceMappingURL=within-section-dedup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"within-section-dedup.d.ts","sourceRoot":"","sources":["../src/within-section-dedup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAsB,aAAa,EAAE,MAAM,YAAY,CAAC;AAkGrF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,aAAa,EAAE,CA2DlF"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Within-section semantic dedup detector (FEAT-013).
3
+ *
4
+ * The cross-file `detectDuplicates` detector works at section granularity and
5
+ * misses a single section that restates the same point several ways. This
6
+ * detector looks *inside* a section: for sections with more than five
7
+ * paragraphs, it computes pairwise Jaccard similarity on the paragraphs and
8
+ * flags any pair that is ≥ 0.65 similar, naming the paragraph numbers.
9
+ *
10
+ * Info severity only — near-duplicate prose within one section is worth a
11
+ * gentle nudge, not a hard failure. Deterministic: no clock, network, or
12
+ * randomness.
13
+ */
14
+ import * as crypto from 'node:crypto';
15
+ import { snippet } from './evidence.js';
16
+ /** Persistent, always-loaded instruction files this detector applies to. */
17
+ const TARGET_FILE_TYPES = new Set([
18
+ 'claude',
19
+ 'agents',
20
+ 'cursor',
21
+ 'windsurf',
22
+ 'copilot',
23
+ 'prompt',
24
+ ]);
25
+ const MIN_PARAGRAPHS = 6; // "> 5 paragraphs"
26
+ const PARAGRAPH_JACCARD_THRESHOLD = 0.65;
27
+ const MIN_PARAGRAPH_CHARS = 40; // normalised; shorter paragraphs are too noisy
28
+ const MIN_PARAGRAPH_TOKENS = 8;
29
+ /** Normalise paragraph text for comparison: lowercase, strip markdown, collapse ws. */
30
+ function normalize(text) {
31
+ return text
32
+ .toLowerCase()
33
+ .replace(/^#{1,6}\s+/gm, '')
34
+ .replace(/^[\s]*[-*+]\s+/gm, '')
35
+ .replace(/^[\s]*\d+[.)]\s+/gm, '')
36
+ .replace(/\s+/g, ' ')
37
+ .trim();
38
+ }
39
+ function tokenize(text) {
40
+ return new Set(text.match(/\b\w+\b/g) ?? []);
41
+ }
42
+ function jaccard(a, b) {
43
+ if (a.size === 0 || b.size === 0)
44
+ return 0;
45
+ let intersection = 0;
46
+ for (const t of a)
47
+ if (b.has(t))
48
+ intersection++;
49
+ return intersection / (a.size + b.size - intersection);
50
+ }
51
+ /**
52
+ * Split a section into paragraphs (blank-line separated), tracking each
53
+ * paragraph's 1-based number and its start line within the file. Code-fence
54
+ * paragraphs are skipped entirely — a repeated code block is the concern of the
55
+ * duplicate-section detector, not prose dedup.
56
+ */
57
+ function splitParagraphs(section) {
58
+ const lines = section.text.split('\n');
59
+ const paragraphs = [];
60
+ let current = [];
61
+ let currentStart = section.startLine;
62
+ let paragraphNumber = 0;
63
+ const flush = () => {
64
+ if (current.length === 0)
65
+ return;
66
+ paragraphNumber++;
67
+ const text = current.join('\n');
68
+ if (!text.includes('```') && !text.includes('~~~')) {
69
+ const norm = normalize(text);
70
+ const tokens = tokenize(norm);
71
+ if (norm.length >= MIN_PARAGRAPH_CHARS && tokens.size >= MIN_PARAGRAPH_TOKENS) {
72
+ paragraphs.push({ number: paragraphNumber, text, startLine: currentStart, tokens });
73
+ }
74
+ }
75
+ current = [];
76
+ };
77
+ for (let i = 0; i < lines.length; i++) {
78
+ const line = lines[i] ?? '';
79
+ if (line.trim() === '') {
80
+ flush();
81
+ }
82
+ else {
83
+ if (current.length === 0)
84
+ currentStart = section.startLine + i;
85
+ current.push(line);
86
+ }
87
+ }
88
+ flush();
89
+ return paragraphs;
90
+ }
91
+ function issueId(filePath, startLine) {
92
+ const hash = crypto
93
+ .createHash('sha1')
94
+ .update(`within-section-dup:${filePath}:${startLine}`)
95
+ .digest('hex')
96
+ .slice(0, 12);
97
+ return `within-section-dup-${hash}`;
98
+ }
99
+ export function detectWithinSectionDedup(files) {
100
+ const issues = [];
101
+ for (const file of files) {
102
+ if (!TARGET_FILE_TYPES.has(file.fileType))
103
+ continue;
104
+ for (const section of file.sections) {
105
+ const paragraphs = splitParagraphs(section);
106
+ // "> 5 paragraphs" is measured against the qualifying (comparable)
107
+ // paragraphs — trivial one-liners never counted toward the section total.
108
+ if (paragraphs.length < MIN_PARAGRAPHS)
109
+ continue;
110
+ // Find the single strongest similar pair (and how many pairs cross the bar).
111
+ let best = null;
112
+ let pairCount = 0;
113
+ for (let i = 0; i < paragraphs.length; i++) {
114
+ for (let j = i + 1; j < paragraphs.length; j++) {
115
+ const sim = jaccard(paragraphs[i].tokens, paragraphs[j].tokens);
116
+ if (sim >= PARAGRAPH_JACCARD_THRESHOLD) {
117
+ pairCount++;
118
+ if (!best || sim > best.sim)
119
+ best = { a: paragraphs[i], b: paragraphs[j], sim };
120
+ }
121
+ }
122
+ }
123
+ if (!best)
124
+ continue;
125
+ const heading = section.heading ?? '(untitled section)';
126
+ const pct = Math.round(best.sim * 100);
127
+ const morePairs = pairCount > 1 ? ` (${pairCount} similar pairs in total)` : '';
128
+ issues.push({
129
+ id: issueId(file.path, section.startLine),
130
+ severity: 'info',
131
+ category: 'duplicate',
132
+ title: `Possible repetition within section: ${heading}`,
133
+ summary: `Within "${heading}", paragraphs ${best.a.number} and ${best.b.number} are about ` +
134
+ `${pct}% similar${morePairs}. The section may be restating the same point several ` +
135
+ `ways — consider consolidating.`,
136
+ filePaths: [file.path],
137
+ locations: [
138
+ { filePath: file.path, startLine: best.a.startLine, endLine: best.a.startLine },
139
+ { filePath: file.path, startLine: best.b.startLine, endLine: best.b.startLine },
140
+ ],
141
+ evidence: [
142
+ `Paragraph ${best.a.number}: "${snippet(best.a.text, 120)}"`,
143
+ `Paragraph ${best.b.number}: "${snippet(best.b.text, 120)}"`,
144
+ ],
145
+ recommendation: 'Merge the near-duplicate paragraphs into one clear statement. If both are ' +
146
+ 'intentional (e.g. a summary and a detailed version), make the distinction explicit.',
147
+ confidence: 0.5,
148
+ });
149
+ }
150
+ }
151
+ return issues;
152
+ }
153
+ //# sourceMappingURL=within-section-dedup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"within-section-dedup.js","sourceRoot":"","sources":["../src/within-section-dedup.ts"],"names":[],"mappings":"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"}