@stupify/cli 0.0.3 → 0.0.4

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 (59) hide show
  1. package/README.md +26 -31
  2. package/dist/analysis.d.ts +11 -9
  3. package/dist/analysis.js +30 -173
  4. package/dist/checks.d.ts +1 -0
  5. package/dist/checks.js +89 -2
  6. package/dist/command.js +55 -91
  7. package/dist/constants.d.ts +1 -1
  8. package/dist/constants.js +1 -1
  9. package/dist/counter-scout.js +70 -8
  10. package/dist/doctor.d.ts +4 -0
  11. package/dist/doctor.js +131 -0
  12. package/dist/git.d.ts +4 -1
  13. package/dist/git.js +34 -0
  14. package/dist/hooks.d.ts +3 -0
  15. package/dist/hooks.js +117 -0
  16. package/dist/model.d.ts +1 -15
  17. package/dist/model.js +37 -21
  18. package/dist/prompts.d.ts +8 -5
  19. package/dist/prompts.js +58 -168
  20. package/dist/render.d.ts +2 -2
  21. package/dist/render.js +70 -78
  22. package/dist/repomix-provider.d.ts +10 -2
  23. package/dist/repomix-provider.js +62 -11
  24. package/dist/search-bench.d.ts +1 -0
  25. package/dist/search-bench.js +675 -0
  26. package/dist/search-profile.d.ts +6 -0
  27. package/dist/search-profile.js +73 -0
  28. package/dist/sem-provider.d.ts +2 -2
  29. package/dist/sem-provider.js +33 -7
  30. package/dist/stupify.d.ts +2 -0
  31. package/dist/stupify.js +183 -333
  32. package/dist/types.d.ts +193 -109
  33. package/package.json +1 -1
  34. package/src/analysis.ts +48 -268
  35. package/src/checks.ts +91 -2
  36. package/src/command.ts +62 -107
  37. package/src/constants.ts +1 -1
  38. package/src/counter-scout.ts +63 -7
  39. package/src/doctor.ts +140 -0
  40. package/src/git.ts +35 -1
  41. package/src/hooks.ts +134 -0
  42. package/src/model.ts +39 -26
  43. package/src/prompts.ts +66 -202
  44. package/src/render.ts +68 -79
  45. package/src/repomix-provider.ts +66 -10
  46. package/src/search-bench.ts +783 -0
  47. package/src/search-profile.ts +89 -0
  48. package/src/sem-provider.ts +36 -9
  49. package/src/stupify.ts +213 -526
  50. package/src/types.ts +195 -119
  51. package/dist/batcher.d.ts +0 -3
  52. package/dist/batcher.js +0 -142
  53. package/dist/candidate-context.d.ts +0 -2
  54. package/dist/candidate-context.js +0 -40
  55. package/dist/experiment.d.ts +0 -1
  56. package/dist/experiment.js +0 -225
  57. package/src/batcher.ts +0 -198
  58. package/src/candidate-context.ts +0 -43
  59. package/src/experiment.ts +0 -317
package/dist/types.d.ts CHANGED
@@ -6,49 +6,64 @@ export type SourceId = Brand<string, "SourceId">;
6
6
  export type CheckId = Brand<string, "CheckId">;
7
7
  export declare function sourceId(value: string): SourceId;
8
8
  export declare function checkId(value: string): CheckId;
9
- export type Engine = "raw-diff" | "sem";
10
- export type ScoutMode = "llm" | "counter";
11
- export type AuditContextMode = "none" | "repomix";
12
- export type AuditPromptName = "strict" | "high_bar";
13
- type AnalyzeOptions = Readonly<{
9
+ export type SearchMode = "warn" | "off";
10
+ export type HookAction = "install" | "uninstall" | "status";
11
+ export type SearchSource = "since" | "stdin" | "commit" | "commits" | "staged";
12
+ type SearchOptions = Readonly<{
14
13
  checkIds: readonly string[] | null;
15
14
  json: boolean;
16
15
  model: ModelId;
17
- engine: Engine;
18
- scout: ScoutMode;
19
- auditContext: AuditContextMode;
20
- auditPrompt: AuditPromptName;
21
16
  debugSem: boolean;
22
- debugTargets: boolean;
23
17
  maxCandidates: number;
24
- auditBatchSize: number;
25
- maxAuditInputTokens: number;
26
- auditConcurrency: number;
18
+ maxSearchInputTokens: number;
19
+ searchProfilePath: string | null;
20
+ includeCounterReasonInPrompt: boolean;
27
21
  }>;
28
22
  export type Command = Readonly<{
29
23
  kind: "help";
30
24
  }> | Readonly<{
31
- kind: "experiment";
25
+ kind: "hook";
26
+ action: HookAction;
27
+ }> | Readonly<{
28
+ kind: "doctor";
29
+ }> | Readonly<{
30
+ kind: "bench-search";
32
31
  configPath: string;
33
32
  }> | (Readonly<{
34
33
  kind: "since";
35
34
  since: string;
36
- }> & AnalyzeOptions) | (Readonly<{
35
+ mode: "search";
36
+ source: "since";
37
+ }> & SearchOptions) | (Readonly<{
37
38
  kind: "stdin";
38
- }> & AnalyzeOptions) | (Readonly<{
39
+ mode: "search";
40
+ source: "stdin";
41
+ }> & SearchOptions) | (Readonly<{
39
42
  kind: "commit";
40
43
  commit: string;
41
- }> & AnalyzeOptions) | (Readonly<{
44
+ mode: "search";
45
+ source: "commit";
46
+ }> & SearchOptions) | (Readonly<{
42
47
  kind: "commits";
43
48
  count: number;
44
- }> & AnalyzeOptions);
45
- type ControlCommand = Readonly<{
49
+ mode: "search";
50
+ source: "commits";
51
+ }> & SearchOptions) | (Readonly<{
52
+ kind: "staged";
53
+ mode: "search";
54
+ source: "staged";
55
+ }> & SearchOptions);
56
+ export type SearchCommand = Exclude<Command, Readonly<{
46
57
  kind: "help";
47
58
  }> | Readonly<{
48
- kind: "experiment";
59
+ kind: "hook";
60
+ action: HookAction;
61
+ }> | Readonly<{
62
+ kind: "doctor";
63
+ }> | Readonly<{
64
+ kind: "bench-search";
49
65
  configPath: string;
50
- }>;
51
- export type AnalyzeCommand = Exclude<Command, ControlCommand>;
66
+ }>>;
52
67
  export type StupifyCheck = Readonly<{
53
68
  id: CheckId;
54
69
  name: string;
@@ -56,41 +71,26 @@ export type StupifyCheck = Readonly<{
56
71
  lookFor: readonly string[];
57
72
  ignoreWhen: readonly string[];
58
73
  enabledByDefault?: boolean;
74
+ hookMode?: SearchMode;
75
+ searchPrompt?: string;
76
+ searchExamples?: Readonly<{
77
+ match: readonly string[];
78
+ nonMatch: readonly string[];
79
+ }>;
59
80
  examples?: Readonly<{
60
81
  match?: readonly string[];
61
82
  noMatch?: readonly string[];
62
83
  }>;
63
84
  }>;
64
- export type FindingCandidate = Readonly<{
65
- checkId: string;
66
- why: string;
67
- proof: string;
68
- }>;
69
- export type Finding = Readonly<{
70
- sourceId: SourceId;
71
- checkId: CheckId;
72
- why: string;
73
- proof: string;
74
- }>;
75
- export type FindingsResult = Readonly<{
76
- findings: readonly Finding[];
77
- summary?: string;
78
- }>;
79
- export type AuditReviewStats = Readonly<{
80
- totalTargets: number;
81
- finding: number;
82
- clean: number;
83
- uncertain: number;
84
- invalid: number;
85
- }>;
86
- export type AuditReviewResult = FindingsResult & Readonly<{
87
- stats: AuditReviewStats;
88
- }>;
89
85
  export type NetDiffStats = Readonly<{
90
86
  filesChanged: number;
91
87
  additions: number;
92
88
  deletions: number;
93
89
  }>;
90
+ export type StagedDiff = Readonly<{
91
+ text: string;
92
+ stats: NetDiffStats;
93
+ }>;
94
94
  export type NetDiff = Readonly<{
95
95
  id: SourceId;
96
96
  label: string;
@@ -106,24 +106,6 @@ export type SourceRange = Readonly<{
106
106
  target: string;
107
107
  stats: NetDiffStats;
108
108
  }>;
109
- export type DiffHunk = Readonly<{
110
- pointer: string;
111
- batchId: string;
112
- fileId: string;
113
- hunkId: string;
114
- filePath: string;
115
- lineCount: number;
116
- text: string;
117
- }>;
118
- export type DiffBatch = Readonly<{
119
- id: string;
120
- hunks: readonly DiffHunk[];
121
- text: string;
122
- }>;
123
- export type CandidateContext = Readonly<{
124
- pointer: string;
125
- text: string;
126
- }>;
127
109
  export type SemChange = Readonly<{
128
110
  entityId: string;
129
111
  entityName: string;
@@ -170,67 +152,169 @@ export type SemContext = Readonly<{
170
152
  filePath?: string;
171
153
  text: string;
172
154
  }>;
173
- export type DebugTarget = Readonly<{
174
- targetId: string;
175
- checkId: CheckId;
176
- entityId: string;
177
- entityKind?: string;
178
- changeKind?: string;
179
- scoutReason?: string;
180
- sourceLabel?: string;
181
- }>;
182
155
  export type SemContextPack = Readonly<{
183
156
  provider: "repomix";
184
157
  filePaths: readonly string[];
185
158
  totalCharacters: number;
186
159
  totalTokens: number;
187
160
  text: string;
161
+ config: RepomixSearchConfig;
188
162
  }>;
189
- export type AnalysisRun = Readonly<{
190
- engine: Engine;
191
- auditContext: AuditContextMode;
192
- auditPrompt: AuditPromptName;
193
- mode: AnalyzeCommand["kind"];
194
- modelId: ModelId;
195
- checkIds: readonly CheckId[];
196
- sourceId: SourceId;
197
- label: string;
198
- stats: NetDiffStats;
199
- batchesScanned: number;
200
- candidateCount: number;
201
- targetsByCheck?: Readonly<Record<string, number>>;
202
- entitiesScanned: number;
203
- auditedCandidateCount: number;
204
- scoutModelCalls: number;
205
- auditModelCalls: number;
206
- timingsMs: Readonly<{
207
- diff: number;
208
- modelLoad: number;
209
- search: number;
210
- audit: number;
211
- total: number;
163
+ export type RepomixSearchConfig = Readonly<{
164
+ compress: boolean;
165
+ showLineNumbers: boolean;
166
+ removeEmptyLines: boolean;
167
+ maxFileSizeBytes: number;
168
+ maxTotalSizeBytes: number;
169
+ ignorePatterns: readonly string[];
170
+ }>;
171
+ export type SearchProfileRepomixConfig = Readonly<{
172
+ compress?: boolean;
173
+ showLineNumbers?: boolean;
174
+ removeEmptyLines?: boolean;
175
+ maxFileBytes?: number;
176
+ maxTotalBytes?: number;
177
+ ignorePatterns?: readonly string[];
178
+ }>;
179
+ export type SearchProfilePattern = Readonly<{
180
+ enabled?: boolean;
181
+ searchPrompt?: string;
182
+ matchExamples?: readonly string[];
183
+ nonMatchExamples?: readonly string[];
184
+ }>;
185
+ export type SearchProfile = Readonly<{
186
+ id: string;
187
+ context?: "repomix" | "sem";
188
+ maxCandidates?: number;
189
+ maxSearchInputTokens?: number;
190
+ includeCounterReasonInPrompt?: boolean;
191
+ repomix?: SearchProfileRepomixConfig;
192
+ patterns?: Readonly<Record<string, SearchProfilePattern>>;
193
+ }>;
194
+ export type SearchMatch = Readonly<{
195
+ targetId: string;
196
+ patternId: CheckId;
197
+ reason: string;
198
+ proof: string;
199
+ }>;
200
+ export type SearchRunJson = Readonly<{
201
+ schemaVersion: "search.v1";
202
+ mode: "search";
203
+ source: SearchSource;
204
+ model: Readonly<{
205
+ id: ModelId;
212
206
  }>;
213
- warnings: readonly string[];
214
- auditStats?: AuditReviewStats;
215
- debugTargets?: readonly DebugTarget[];
216
- traceEvents?: readonly TraceEvent[];
207
+ patterns: readonly CheckId[];
208
+ stats: Readonly<{
209
+ elapsedMs: number;
210
+ modelCalls: number;
211
+ inputTokens?: number;
212
+ inputTokenCap?: number;
213
+ skipped?: boolean;
214
+ skipReason?: "input_too_large" | "no_candidates";
215
+ filesChanged?: number;
216
+ entitiesScanned?: number;
217
+ candidates?: number;
218
+ repomixFiles?: number;
219
+ repomixTokens?: number;
220
+ repomixConfig?: RepomixSearchConfig;
221
+ searchTargets?: number;
222
+ profileId?: string;
223
+ targetsByPattern?: Readonly<Record<string, number>>;
224
+ targetsPreview?: readonly SearchTargetPreview[];
225
+ }>;
226
+ matches: readonly SearchMatch[];
217
227
  }>;
218
- export type TraceEvent = Readonly<{
228
+ export type SearchTargetPreview = Readonly<{
229
+ targetId: string;
230
+ patternId: CheckId;
231
+ entityKind?: string;
232
+ sourceKind?: string;
233
+ }>;
234
+ export type SearchBenchConfig = Readonly<{
219
235
  name: string;
220
- ms: number;
221
- count?: number;
222
- detail?: string;
236
+ profiles: readonly string[];
237
+ fixtures: string;
238
+ realSmokeRuns?: readonly SearchBenchSmokeRun[];
239
+ realCommitReplay?: readonly SearchBenchCommitReplay[];
223
240
  }>;
224
- export type AnalysisReport = Readonly<{
225
- run: AnalysisRun;
226
- result: FindingsResult;
241
+ export type SearchBenchSmokeRun = Readonly<{
242
+ id: string;
243
+ cwd?: string;
244
+ args: readonly string[];
245
+ }>;
246
+ export type SearchBenchCommitReplay = Readonly<{
247
+ id: string;
248
+ repoEnv?: string;
249
+ cwd?: string;
250
+ limit: number;
251
+ since?: string;
252
+ nonMerge?: boolean;
253
+ profiles: readonly string[];
254
+ }>;
255
+ export type SearchFixture = Readonly<{
256
+ id: string;
257
+ description: string;
258
+ stagedPatch: string;
259
+ checks: readonly string[];
260
+ expected: readonly SearchFixtureExpectation[];
261
+ }>;
262
+ export type SearchFixtureExpectation = Readonly<{
263
+ patternId: string;
264
+ shouldMatch: boolean;
265
+ }>;
266
+ export type SearchBenchRun = Readonly<{
267
+ profileId: string;
268
+ fixtureId?: string;
269
+ smokeId?: string;
270
+ elapsedMs: number;
271
+ modelCalls: number;
272
+ patterns: readonly CheckId[];
273
+ targets: number;
274
+ targetsByPattern: Readonly<Record<string, number>>;
275
+ inputTokens: number;
276
+ repomixPackedTokens?: number;
277
+ skipped: boolean;
278
+ skipReason?: string;
279
+ matches: readonly SearchMatch[];
280
+ expected?: readonly SearchFixtureExpectation[];
281
+ score?: number;
282
+ targetsPreview: readonly SearchTargetPreview[];
283
+ matchesUsingCounterReasonAsProof: number;
284
+ error?: string;
285
+ }>;
286
+ export type SearchBenchReplayRun = Readonly<{
287
+ profileId: string;
288
+ replayId: string;
289
+ commitId: string;
290
+ outcome: SearchReplayOutcome;
291
+ changedFiles: number;
292
+ addedLines: number;
293
+ deletedLines: number;
294
+ elapsedMs: number;
295
+ skipped: boolean;
296
+ skipReason?: string;
297
+ targets: number;
298
+ inputTokens: number;
299
+ repomixPackedTokens?: number;
300
+ modelCalls: number;
301
+ matches: readonly SearchMatch[];
302
+ matchesByPattern: Readonly<Record<string, number>>;
303
+ error?: string;
227
304
  }>;
305
+ export type SearchReplayOutcome = "no_candidates" | "ran_no_matches" | "ran_with_matches" | "skipped_input_too_large" | "error";
228
306
  export type ModelId = "gemma-4-e2b" | "gemma-4-e4b" | "gemma-4-26b-a4b" | "qwen3-4b-magicquant" | "qwen2.5-coder-1.5b" | "qwen2.5-coder-7b" | "qwen2.5-coder-32b";
229
307
  export type ModelConfig = Readonly<{
230
308
  id: ModelId;
231
309
  name: string;
232
- size: string;
233
310
  file: string;
234
311
  url: string;
312
+ size: string;
313
+ }>;
314
+ export type TraceEvent = Readonly<{
315
+ name: string;
316
+ ms: number;
317
+ count?: number;
318
+ detail?: string;
235
319
  }>;
236
320
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stupify/cli",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "Local-only diagnostic CLI for checking whether AI is making you dumber.",
5
5
  "private": false,
6
6
  "type": "module",