claudex-setup 1.16.0 → 1.16.2

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.
@@ -1,159 +1,226 @@
1
- # Launch Posts — Ready to Publish
1
+ # Launch Posts — Proof-Backed Distribution Assets
2
+
3
+ **Status:** Complete — every asset below is anchored in measured proof, a canonical artifact, or a verified runtime surface
4
+ **Date:** 2026-04-03
5
+
6
+ ## Shared Proof Anchors
7
+
8
+ Use these links as the canonical sources behind public claims:
9
+
10
+ - Proof artifact index: https://github.com/DnaFin/claudex/blob/main/research/proof-artifacts/README.md
11
+ - CLAUDEX self-dogfood trace: https://github.com/DnaFin/claudex/blob/main/research/proof-artifacts/claudex-self-dogfood-proof-trace-2026-04-03.md
12
+ - VTCLE case study: https://github.com/DnaFin/claudex/blob/main/research/case-study-vtcle-2026-04-03.md
13
+ - Social case study: https://github.com/DnaFin/claudex/blob/main/research/case-study-social-2026-04-03.md
14
+ - Polymiro case study: https://github.com/DnaFin/claudex/blob/main/research/case-study-polymiro-2026-04-03.md
15
+ - Public proof metrics source: https://github.com/DnaFin/claudex/blob/main/research/claudex-proof-metrics-source-2026-04-03.md
16
+
17
+ Measured-result boundary to preserve:
18
+
19
+ - before/after scores were measured with `claudex-setup@1.10.3` on `2026-04-03`
20
+ - current npm latest is `1.16.1`
21
+ - current product surface is `85 checks`
2
22
 
3
23
  ## Post 1: Reddit r/ClaudeAI
4
24
 
5
- **Title:** I built a tool that audits your project for Claude Code optimizationscores you 0-100
25
+ **Title:** I built a CLI that audits your Claude Code setup85 checks, measured on 4 real repos
6
26
 
7
27
  **Body:**
8
- After cataloging 1,107 Claude Code entries and verifying 948 of them with evidence, I built a CLI that checks if your project is actually set up to get the most out of Claude Code. It runs 84 checks across CLAUDE.md, hooks, commands, agents, diagrams, and more.
28
+ I built a zero-dependency CLI that audits how well a repo is set up for Claude Code.
9
29
 
10
- I tested it on 4 real repos. A FastAPI marketing engine went from 46 to 64. A React Native social app went from 40 to 48. A Polymiro project jumped from 35 to 48. The CLAUDEX catalog repo itself: 62 to 90.
30
+ It checks `85` things across `CLAUDE.md`, hooks, commands, agents, skills, MCP config, permissions, diagrams, and verification loops.
11
31
 
12
- ```
32
+ Measured on `2026-04-03` with `claudex-setup@1.10.3`:
33
+ - CLAUDEX: `62 -> 90`
34
+ - VTCLE: `46 -> 64`
35
+ - Social: `40 -> 48`
36
+ - Polymiro: `35 -> 48`
37
+
38
+ ```bash
13
39
  npx claudex-setup
14
40
  ```
15
41
 
16
- Then `npx claudex-setup setup` auto-creates everything that's missing, tailored to your stack (React, Python, TypeScript, etc).
42
+ It starts trust-first:
43
+ - audit first
44
+ - plan / suggest-only before writes
45
+ - apply only what you approve
46
+ - rollback artifacts for every applied batch
17
47
 
18
- Zero dependencies. No API keys. Runs entirely local.
48
+ Zero dependencies. No API keys. Runs local.
19
49
 
20
50
  GitHub: https://github.com/DnaFin/claudex-setup
21
51
 
22
- Would love feedback!
52
+ Proof and case studies:
53
+ - https://github.com/DnaFin/claudex/blob/main/research/proof-artifacts/README.md
54
+ - https://github.com/DnaFin/claudex/blob/main/research/case-study-vtcle-2026-04-03.md
55
+ - https://github.com/DnaFin/claudex/blob/main/research/case-study-social-2026-04-03.md
56
+ - https://github.com/DnaFin/claudex/blob/main/research/case-study-polymiro-2026-04-03.md
57
+
58
+ Would love feedback on what checks or rollout surfaces are still missing.
59
+
60
+ **Evidence anchor:** proof artifact index + 3 external case studies + current proof source
23
61
 
24
62
  ---
25
63
 
26
64
  ## Post 2: Reddit r/ChatGPTCoding
27
65
 
28
- **Title:** Your Claude Code project is probably running at 10% efficiency. Here's how to check.
66
+ **Title:** Most Claude Code repos are missing the safety layer, not the model
29
67
 
30
68
  **Body:**
31
- I spent weeks cataloging every Claude Code feature, technique, and best practice — 1,107 total, 948 verified with real evidence.
32
-
33
- Turns out most projects are missing basic stuff that makes a huge difference:
34
- - No CLAUDE.md (Claude doesn't know your project conventions)
35
- - No hooks (no auto-lint, no auto-test)
36
- - No custom commands (repeating the same prompts manually)
37
- - No Mermaid diagrams (wasting 73% more tokens on prose descriptions)
38
-
39
- I tested 4 real repos with 84 checks. Before optimization: scores ranged from 35 to 62. After: 48 to 90. A VTCLE FastAPI project jumped from 46→64 just from adding missing hooks and commands.
40
-
41
- ```
69
+ The interesting problem with Claude Code is not "can it write code?".
70
+ It's "is the repo actually set up so Claude can work safely and predictably?".
71
+
72
+ I built `claudex-setup` to audit that surface:
73
+ - `85` checks
74
+ - zero dependencies
75
+ - local-only by default
76
+ - trust-first flow: audit -> plan -> apply -> rollback
77
+
78
+ Measured on 4 real repos:
79
+ - FastAPI repo: `46 -> 64`
80
+ - React Native repo: `40 -> 48`
81
+ - Python/Docker repo: `35 -> 48`
82
+ - research engine repo: `62 -> 90`
83
+
84
+ ```bash
42
85
  npx claudex-setup
43
86
  ```
44
87
 
45
- Scores your project 0-100, tells you exactly what to fix, and can auto-apply everything.
88
+ The most common misses were not exotic:
89
+ - no deny rules
90
+ - no secrets protection
91
+ - no mermaid architecture
92
+ - no hooks registered in settings
93
+
94
+ Proof:
95
+ https://github.com/DnaFin/claudex/blob/main/research/proof-artifacts/README.md
46
96
 
47
- Free, open source, zero dependencies: https://github.com/DnaFin/claudex-setup
97
+ **Evidence anchor:** measured before/after traces + common gap summary from public proof set
48
98
 
49
99
  ---
50
100
 
51
101
  ## Post 3: Dev.to Article
52
102
 
53
- **Title:** 1,107 Claude Code Entries: What I Learned Building the Most Comprehensive Catalog
103
+ **Title:** What 4 Real Repos Taught Me About Claude Code Readiness
54
104
 
55
105
  **Body (excerpt):**
56
- I set out to catalog every single Claude Code capability, technique, and best practice. After repeated research cycles, I have 1,107 entries — 948 verified with real evidence. I packaged this into an 84-check CLI audit and tested it on 4 real projects scores before optimization ranged from 35 to 62, and after: 48 to 90.
106
+ I tested `claudex-setup` on 4 real repos and the pattern was clear:
57
107
 
58
- Here are the top 10 things most developers are missing:
108
+ - the best teams still miss permission deny rules
109
+ - mature repos often have hooks in files but not actually registered
110
+ - non-standard settings formats are a real adoption trap
111
+ - shared `settings.json` matters more than personal local overrides
59
112
 
60
- 1. **CLAUDE.md** Claude reads this at the start of every session. Without it, Claude doesn't know your build commands, code style, or project rules.
113
+ Measured on `2026-04-03` with `claudex-setup@1.10.3`:
114
+ - CLAUDEX: `62 -> 90`
115
+ - VTCLE: `46 -> 64`
116
+ - Social: `40 -> 48`
117
+ - Polymiro: `35 -> 48`
61
118
 
62
- 2. **Mermaid diagrams** A Mermaid architecture diagram saves 73% tokens compared to describing your project in prose.
119
+ The product today is strongest as:
63
120
 
64
- 3. **Hooks** Auto-lint after every edit. Auto-test before every commit. Hooks fire 100% of the time, CLAUDE.md rules fire ~80%.
121
+ `audit -> plan -> safe apply -> governance -> benchmark`
65
122
 
66
- 4. **Custom commands** `/test`, `/deploy`, `/review` package your repeated workflows.
123
+ Not a code generator. Not an MCP installer. A trust layer for Claude Code repos.
67
124
 
68
- 5. **Verification loops** — Tell Claude how to verify its own work. Include test commands in CLAUDE.md.
125
+ Proof packet:
126
+ https://github.com/DnaFin/claudex/blob/main/research/proof-artifacts/README.md
69
127
 
70
- 6. **Path-specific rules** Different conventions for frontend vs backend files.
71
-
72
- 7. **XML tags** — `<constraints>`, `<validation>` in CLAUDE.md = unambiguous instructions.
73
-
74
- 8. **Custom agents** — Security reviewer, test writer — specialized subagents for focused tasks.
75
-
76
- 9. **Skills** — Domain-specific workflows that load on demand, not every session.
77
-
78
- 10. **MCP servers** — Connect Claude to your database, ticket system, Slack.
79
-
80
- I packaged this into a CLI that checks your project:
81
- ```
82
- npx claudex-setup
83
- ```
84
-
85
- Full catalog: https://github.com/DnaFin/claudex-setup
128
+ **Evidence anchor:** proof artifact index + case-study docs + current proof source
86
129
 
87
130
  ---
88
131
 
89
132
  ## Post 4: Twitter/X Thread
90
133
 
91
134
  **Tweet 1:**
92
- I cataloged 1,107 Claude Code entries and verified 948 of them with evidence.
93
-
94
- Most projects use less than 5% of what Claude Code can do.
135
+ I built a zero-dependency CLI that audits Claude Code readiness across `85` checks.
95
136
 
96
- Tested on 4 real repos — a React Native app scored 40, a FastAPI engine scored 46. After auto-setup: 48 and 64. Here's the free 84-check audit:
137
+ Measured on 4 real repos:
138
+ - `62 -> 90`
139
+ - `46 -> 64`
140
+ - `40 -> 48`
141
+ - `35 -> 48`
97
142
 
98
- npx claudex-setup
143
+ `npx claudex-setup`
99
144
 
100
- Thread 🧵👇
145
+ Proof: github.com/DnaFin/claudex/blob/main/research/proof-artifacts/README.md
101
146
 
102
147
  **Tweet 2:**
103
- The #1 thing you're probably missing: CLAUDE.md
104
-
105
- It's a file Claude reads at the start of every session. Without it, Claude doesn't know your:
106
- - Build commands
107
- - Code style
108
- - Testing framework
109
- - Project architecture
148
+ The most common misses were boring and important:
149
+ - no deny rules
150
+ - no secrets protection
151
+ - no mermaid diagram
152
+ - no hooks registered in settings
110
153
 
111
- Takes 2 minutes to create. Impact: massive.
154
+ It is much more "trust layer" than "AI magic".
112
155
 
113
156
  **Tweet 3:**
114
- #2: Mermaid diagrams in CLAUDE.md
115
-
116
- A few hundred tokens of Mermaid syntax conveys what takes thousands of tokens in prose.
117
-
118
- 73% token savings = faster responses, lower cost, better context.
157
+ What it does well today:
158
+ - audit first
159
+ - suggest / plan before writes
160
+ - apply selectively
161
+ - emit rollback artifacts
162
+ - benchmark on isolated copy
119
163
 
120
164
  **Tweet 4:**
121
- #3: Hooks > CLAUDE.md rules
122
-
123
- CLAUDE.md instructions = ~80% compliance
124
- Hooks = 100% enforcement
165
+ Best result so far:
166
+ - CLAUDEX self-dogfood: `62 -> 90`
125
167
 
126
- Auto-lint after edits. Block commits without tests. Prevent force-push.
168
+ Best external proof:
169
+ - VTCLE: `46 -> 64`
127
170
 
128
- Hooks are deterministic. Instructions are advisory.
171
+ Case studies:
172
+ - github.com/DnaFin/claudex/blob/main/research/case-study-vtcle-2026-04-03.md
173
+ - github.com/DnaFin/claudex/blob/main/research/case-study-social-2026-04-03.md
174
+ - github.com/DnaFin/claudex/blob/main/research/case-study-polymiro-2026-04-03.md
129
175
 
130
176
  **Tweet 5:**
131
- Want to check your project in 10 seconds?
177
+ Measured results were captured on `claudex-setup@1.10.3` on `2026-04-03`.
178
+ Current npm latest is `1.16.1`, so exact scores can move slightly, but the proof packet is explicit about that boundary.
132
179
 
133
- npx claudex-setup
134
-
135
- Scores 0-100. Shows what's missing. Auto-fixes with `setup`.
136
-
137
- Free. Open source. Zero dependencies.
138
-
139
- https://github.com/DnaFin/claudex-setup
180
+ **Evidence anchor:** proof artifact index + per-repo traces
140
181
 
141
182
  ---
142
183
 
143
184
  ## Post 5: Hacker News (Show HN)
144
185
 
145
- **Title:** Show HN: claudex-setup Audit any project for Claude Code optimization (1,107 entries)
186
+ **Title:** Show HN: claudex-setup audit Claude Code readiness with 85 checks
146
187
 
147
188
  **Body:**
148
- I built a CLI tool that scores your project against Claude Code best practices.
149
-
150
- After researching 1,107 entries (948 verified with evidence), I tested 4 real repos with 84 checks. Scores before optimization: 35–62. After auto-setup: 48–90. The biggest jump was a research catalog repo going from 62 to 90.
151
-
152
- npx claudex-setup → audit (84 checks, 0-100 score)
153
- npx claudex-setup setup → auto-fix
154
-
155
- Detects your stack (React, Python, TS, Rust, Go, etc) and tailors recommendations.
156
-
157
- Zero dependencies, no API keys, runs locally.
158
-
159
- https://github.com/DnaFin/claudex-setup
189
+ I built a CLI that audits how well a repo is set up for Claude Code.
190
+
191
+ This is not a code-quality linter and not an MCP installer.
192
+ It focuses on Claude workflow quality:
193
+ - `CLAUDE.md`
194
+ - hooks
195
+ - commands
196
+ - agents
197
+ - skills
198
+ - MCP config
199
+ - permissions / deny rules
200
+ - diagrams
201
+ - verification loops
202
+
203
+ Core workflow:
204
+ - `npx claudex-setup`
205
+ - `npx claudex-setup suggest-only`
206
+ - `npx claudex-setup plan`
207
+ - `npx claudex-setup apply`
208
+ - `npx claudex-setup benchmark`
209
+
210
+ Measured on 4 real repos on `2026-04-03` with `claudex-setup@1.10.3`:
211
+ - CLAUDEX: `62 -> 90`
212
+ - VTCLE: `46 -> 64`
213
+ - Social: `40 -> 48`
214
+ - Polymiro: `35 -> 48`
215
+
216
+ Trust decisions that mattered:
217
+ - zero dependencies
218
+ - audit before write
219
+ - rollback artifacts
220
+ - cross-platform Node hooks
221
+ - explicit proof packets instead of vague claims
222
+
223
+ Proof packet:
224
+ https://github.com/DnaFin/claudex/blob/main/research/proof-artifacts/README.md
225
+
226
+ **Evidence anchor:** proof artifact index + current npm proof source
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "claudex-setup",
3
- "version": "1.16.0",
4
- "description": "Score your repo's Claude Code setup against 84 checks. See gaps, apply fixes selectively with rollback, govern hooks and permissions, and benchmark impact — without breaking existing config.",
3
+ "version": "1.16.2",
4
+ "description": "Score your repo's Claude Code setup against 85 checks. See gaps, apply fixes selectively with rollback, govern hooks and permissions, and benchmark impact — without breaking existing config.",
5
5
  "main": "src/index.js",
6
6
  "bin": {
7
7
  "claudex-setup": "bin/cli.js"
package/src/activity.js CHANGED
@@ -21,10 +21,12 @@ function ensureArtifactDirs(dir) {
21
21
  const activityDir = path.join(root, 'activity');
22
22
  const rollbackDir = path.join(root, 'rollbacks');
23
23
  const snapshotDir = path.join(root, 'snapshots');
24
+ const outcomesDir = path.join(root, 'outcomes');
24
25
  fs.mkdirSync(activityDir, { recursive: true });
25
26
  fs.mkdirSync(rollbackDir, { recursive: true });
26
27
  fs.mkdirSync(snapshotDir, { recursive: true });
27
- return { root, activityDir, rollbackDir, snapshotDir };
28
+ fs.mkdirSync(outcomesDir, { recursive: true });
29
+ return { root, activityDir, rollbackDir, snapshotDir, outcomesDir };
28
30
  }
29
31
 
30
32
  function writeJson(filePath, payload) {
@@ -322,6 +324,192 @@ function exportTrendReport(dir) {
322
324
  return lines.join('\n');
323
325
  }
324
326
 
327
+ function readOutcomeIndex(dir) {
328
+ const indexPath = path.join(dir, '.claude', 'claudex-setup', 'outcomes', 'index.json');
329
+ if (!fs.existsSync(indexPath)) return [];
330
+ try {
331
+ const entries = JSON.parse(fs.readFileSync(indexPath, 'utf8'));
332
+ return Array.isArray(entries) ? entries : [];
333
+ } catch {
334
+ return [];
335
+ }
336
+ }
337
+
338
+ function updateOutcomeIndex(outcomesDir, record) {
339
+ const indexPath = path.join(outcomesDir, 'index.json');
340
+ let entries = [];
341
+
342
+ if (fs.existsSync(indexPath)) {
343
+ try {
344
+ entries = JSON.parse(fs.readFileSync(indexPath, 'utf8'));
345
+ if (!Array.isArray(entries)) entries = [];
346
+ } catch {
347
+ entries = [];
348
+ }
349
+ }
350
+
351
+ entries.push(record);
352
+ const MAX_INDEX_ENTRIES = 500;
353
+ if (entries.length > MAX_INDEX_ENTRIES) {
354
+ entries = entries.slice(entries.length - MAX_INDEX_ENTRIES);
355
+ }
356
+ fs.writeFileSync(indexPath, JSON.stringify(entries, null, 2), 'utf8');
357
+ }
358
+
359
+ function normalizeOutcomeStatus(value) {
360
+ const normalized = `${value || ''}`.trim().toLowerCase();
361
+ if (!['accepted', 'rejected', 'deferred'].includes(normalized)) {
362
+ throw new Error('feedback status must be one of: accepted, rejected, deferred');
363
+ }
364
+ return normalized;
365
+ }
366
+
367
+ function normalizeOutcomeEffect(value) {
368
+ const normalized = `${value || ''}`.trim().toLowerCase();
369
+ if (!['positive', 'neutral', 'negative'].includes(normalized)) {
370
+ throw new Error('feedback effect must be one of: positive, neutral, negative');
371
+ }
372
+ return normalized;
373
+ }
374
+
375
+ function recordRecommendationOutcome(dir, payload) {
376
+ const key = `${payload.key || ''}`.trim();
377
+ if (!key) {
378
+ throw new Error('feedback requires a recommendation key');
379
+ }
380
+
381
+ const status = normalizeOutcomeStatus(payload.status);
382
+ const effect = normalizeOutcomeEffect(payload.effect || 'neutral');
383
+ const scoreDelta = Number.isFinite(payload.scoreDelta) ? payload.scoreDelta : (
384
+ payload.scoreDelta === null || payload.scoreDelta === undefined || payload.scoreDelta === ''
385
+ ? null
386
+ : Number(payload.scoreDelta)
387
+ );
388
+
389
+ if (scoreDelta !== null && !Number.isFinite(scoreDelta)) {
390
+ throw new Error('feedback scoreDelta must be a number when provided');
391
+ }
392
+
393
+ const id = timestampId();
394
+ const { outcomesDir } = ensureArtifactDirs(dir);
395
+ const filePath = path.join(outcomesDir, `${id}.json`);
396
+ const record = {
397
+ id,
398
+ createdAt: new Date().toISOString(),
399
+ key,
400
+ status,
401
+ effect,
402
+ source: `${payload.source || 'manual-cli'}`.trim() || 'manual-cli',
403
+ notes: `${payload.notes || ''}`.trim(),
404
+ scoreDelta,
405
+ };
406
+
407
+ writeJson(filePath, record);
408
+ updateOutcomeIndex(outcomesDir, {
409
+ ...record,
410
+ relativePath: path.relative(dir, filePath),
411
+ });
412
+
413
+ return {
414
+ id,
415
+ filePath,
416
+ relativePath: path.relative(dir, filePath),
417
+ record,
418
+ };
419
+ }
420
+
421
+ function summarizeOutcomeEntries(entries = []) {
422
+ const byKey = {};
423
+
424
+ for (const entry of entries) {
425
+ if (!entry || !entry.key) continue;
426
+ const bucket = byKey[entry.key] || {
427
+ key: entry.key,
428
+ total: 0,
429
+ accepted: 0,
430
+ rejected: 0,
431
+ deferred: 0,
432
+ positive: 0,
433
+ neutral: 0,
434
+ negative: 0,
435
+ scoreDeltaTotal: 0,
436
+ scoreDeltaCount: 0,
437
+ latestAt: null,
438
+ };
439
+
440
+ bucket.total += 1;
441
+ if (bucket[entry.status] !== undefined) bucket[entry.status] += 1;
442
+ if (bucket[entry.effect] !== undefined) bucket[entry.effect] += 1;
443
+ if (Number.isFinite(entry.scoreDelta)) {
444
+ bucket.scoreDeltaTotal += entry.scoreDelta;
445
+ bucket.scoreDeltaCount += 1;
446
+ }
447
+ if (!bucket.latestAt || new Date(entry.createdAt) > new Date(bucket.latestAt)) {
448
+ bucket.latestAt = entry.createdAt;
449
+ }
450
+
451
+ byKey[entry.key] = bucket;
452
+ }
453
+
454
+ for (const bucket of Object.values(byKey)) {
455
+ bucket.avgScoreDelta = bucket.scoreDeltaCount > 0
456
+ ? Number((bucket.scoreDeltaTotal / bucket.scoreDeltaCount).toFixed(2))
457
+ : null;
458
+ bucket.evidenceClass = bucket.total > 0 ? 'measured' : 'estimated';
459
+ }
460
+
461
+ return {
462
+ totalEntries: entries.length,
463
+ byKey,
464
+ keys: Object.keys(byKey).sort(),
465
+ };
466
+ }
467
+
468
+ function getRecommendationOutcomeSummary(dir) {
469
+ return summarizeOutcomeEntries(readOutcomeIndex(dir));
470
+ }
471
+
472
+ function getRecommendationAdjustment(summaryByKey, key) {
473
+ const bucket = summaryByKey && summaryByKey[key];
474
+ if (!bucket) return 0;
475
+
476
+ let adjustment = 0;
477
+ adjustment += bucket.accepted * 2;
478
+ adjustment += bucket.positive * 3;
479
+ adjustment -= bucket.rejected * 3;
480
+ adjustment -= bucket.negative * 4;
481
+
482
+ if (Number.isFinite(bucket.avgScoreDelta)) {
483
+ if (bucket.avgScoreDelta > 0) adjustment += Math.min(4, Math.round(bucket.avgScoreDelta / 4));
484
+ if (bucket.avgScoreDelta < 0) adjustment -= Math.min(4, Math.round(Math.abs(bucket.avgScoreDelta) / 4));
485
+ }
486
+
487
+ if (adjustment > 8) return 8;
488
+ if (adjustment < -8) return -8;
489
+ return adjustment;
490
+ }
491
+
492
+ function formatRecommendationOutcomeSummary(dir) {
493
+ const summary = getRecommendationOutcomeSummary(dir);
494
+ if (summary.totalEntries === 0) {
495
+ return 'No recommendation outcomes recorded yet. Use `npx claudex-setup feedback --key permissionDeny --status accepted --effect positive` after a real run.';
496
+ }
497
+
498
+ const lines = [
499
+ 'Recommendation outcome summary:',
500
+ '',
501
+ ];
502
+
503
+ for (const key of summary.keys) {
504
+ const bucket = summary.byKey[key];
505
+ const avg = Number.isFinite(bucket.avgScoreDelta) ? ` | avg score delta ${bucket.avgScoreDelta >= 0 ? '+' : ''}${bucket.avgScoreDelta}` : '';
506
+ const adjustment = getRecommendationAdjustment(summary.byKey, key);
507
+ lines.push(` ${key}: total ${bucket.total} | accepted ${bucket.accepted} | rejected ${bucket.rejected} | deferred ${bucket.deferred} | positive ${bucket.positive} | negative ${bucket.negative}${avg} | ranking ${adjustment >= 0 ? '+' : ''}${adjustment}`);
508
+ }
509
+
510
+ return lines.join('\n');
511
+ }
512
+
325
513
  module.exports = {
326
514
  ensureArtifactDirs,
327
515
  writeActivityArtifact,
@@ -332,4 +520,10 @@ module.exports = {
332
520
  compareLatest,
333
521
  formatHistory,
334
522
  exportTrendReport,
523
+ readOutcomeIndex,
524
+ recordRecommendationOutcome,
525
+ summarizeOutcomeEntries,
526
+ getRecommendationOutcomeSummary,
527
+ getRecommendationAdjustment,
528
+ formatRecommendationOutcomeSummary,
335
529
  };
package/src/analyze.js CHANGED
@@ -244,12 +244,15 @@ function toGaps(results) {
244
244
  }
245
245
 
246
246
  function toRecommendations(auditResult) {
247
- const failed = auditResult.results
248
- .filter(r => r.passed === false)
249
- .sort((a, b) => {
250
- const order = { critical: 3, high: 2, medium: 1, low: 0 };
251
- return (order[b.impact] || 0) - (order[a.impact] || 0);
252
- });
247
+ const failed = auditResult.results.filter(r => r.passed === false);
248
+ const topActionOrder = new Map((auditResult.topNextActions || []).map((item, index) => [item.key, index]));
249
+ failed.sort((a, b) => {
250
+ const rankedA = topActionOrder.has(a.key) ? topActionOrder.get(a.key) : Number.MAX_SAFE_INTEGER;
251
+ const rankedB = topActionOrder.has(b.key) ? topActionOrder.get(b.key) : Number.MAX_SAFE_INTEGER;
252
+ if (rankedA !== rankedB) return rankedA - rankedB;
253
+ const order = { critical: 3, high: 2, medium: 1, low: 0 };
254
+ return (order[b.impact] || 0) - (order[a.impact] || 0);
255
+ });
253
256
 
254
257
  return failed.slice(0, 10).map((r, index) => ({
255
258
  priority: index + 1,
@@ -259,6 +262,8 @@ function toRecommendations(auditResult) {
259
262
  module: moduleFromCategory(r.category),
260
263
  risk: riskFromImpact(r.impact),
261
264
  why: r.fix,
265
+ evidenceClass: (auditResult.topNextActions || []).find(item => item.key === r.key)?.evidenceClass || 'estimated',
266
+ rankingAdjustment: (auditResult.topNextActions || []).find(item => item.key === r.key)?.rankingAdjustment || 0,
262
267
  }));
263
268
  }
264
269