@nerviq/cli 1.18.0 → 1.20.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.
- package/LICENSE +23 -23
- package/README.md +2 -2
- package/bin/cli.js +131 -130
- package/package.json +2 -1
- package/src/activity.js +1039 -1039
- package/src/adoption-advisor.js +299 -299
- package/src/aider/config-parser.js +166 -166
- package/src/aider/context.js +158 -158
- package/src/aider/deep-review.js +316 -316
- package/src/aider/domain-packs.js +303 -303
- package/src/aider/freshness.js +93 -93
- package/src/aider/governance.js +253 -253
- package/src/aider/interactive.js +334 -334
- package/src/aider/mcp-packs.js +329 -329
- package/src/aider/patch.js +214 -214
- package/src/aider/plans.js +186 -186
- package/src/aider/premium.js +360 -360
- package/src/aider/setup.js +404 -404
- package/src/aider/techniques.js +16 -16
- package/src/analyze.js +951 -951
- package/src/anti-patterns.js +485 -485
- package/src/audit/instruction-files.js +180 -180
- package/src/audit/recommendations.js +577 -577
- package/src/auto-suggest.js +154 -154
- package/src/badge.js +13 -13
- package/src/behavioral-drift.js +801 -801
- package/src/benchmark.js +67 -67
- package/src/catalog.js +103 -103
- package/src/certification.js +128 -128
- package/src/codex/config-parser.js +183 -183
- package/src/codex/context.js +223 -223
- package/src/codex/deep-review.js +493 -493
- package/src/codex/domain-packs.js +394 -394
- package/src/codex/freshness.js +84 -84
- package/src/codex/governance.js +192 -192
- package/src/codex/interactive.js +618 -618
- package/src/codex/mcp-packs.js +914 -914
- package/src/codex/patch.js +209 -209
- package/src/codex/plans.js +251 -251
- package/src/codex/premium.js +614 -614
- package/src/codex/setup.js +591 -591
- package/src/context.js +320 -320
- package/src/continuous-ops.js +681 -681
- package/src/copilot/activity.js +309 -309
- package/src/copilot/deep-review.js +346 -346
- package/src/copilot/domain-packs.js +372 -372
- package/src/copilot/freshness.js +57 -57
- package/src/copilot/governance.js +222 -222
- package/src/copilot/interactive.js +406 -406
- package/src/copilot/mcp-packs.js +826 -826
- package/src/copilot/plans.js +253 -253
- package/src/copilot/premium.js +451 -451
- package/src/copilot/setup.js +488 -488
- package/src/cost-tracking.js +61 -61
- package/src/cursor/activity.js +301 -301
- package/src/cursor/config-parser.js +265 -265
- package/src/cursor/context.js +256 -256
- package/src/cursor/deep-review.js +334 -334
- package/src/cursor/domain-packs.js +368 -368
- package/src/cursor/freshness.js +65 -65
- package/src/cursor/governance.js +229 -229
- package/src/cursor/interactive.js +391 -391
- package/src/cursor/mcp-packs.js +828 -828
- package/src/cursor/plans.js +254 -254
- package/src/cursor/premium.js +469 -469
- package/src/cursor/setup.js +488 -488
- package/src/dashboard.js +493 -493
- package/src/deep-review.js +428 -428
- package/src/deprecation.js +98 -98
- package/src/diff-only.js +280 -280
- package/src/doctor.js +119 -119
- package/src/domain-pack-expansion.js +1033 -1033
- package/src/domain-packs.js +387 -387
- package/src/feedback.js +178 -178
- package/src/fix-engine.js +783 -783
- package/src/fix-prompts.js +122 -122
- package/src/formatters/sarif.js +115 -115
- package/src/freshness.js +74 -74
- package/src/gemini/config-parser.js +275 -275
- package/src/gemini/context.js +290 -221
- package/src/gemini/deep-review.js +559 -559
- package/src/gemini/domain-packs.js +393 -393
- package/src/gemini/freshness.js +66 -66
- package/src/gemini/governance.js +201 -201
- package/src/gemini/interactive.js +860 -860
- package/src/gemini/mcp-packs.js +915 -915
- package/src/gemini/plans.js +269 -269
- package/src/gemini/premium.js +760 -760
- package/src/gemini/setup.js +692 -692
- package/src/gemini/techniques.js +105 -33
- package/src/governance.js +72 -72
- package/src/harmony/add.js +68 -68
- package/src/harmony/advisor.js +333 -333
- package/src/harmony/canon.js +565 -565
- package/src/harmony/cli.js +591 -591
- package/src/harmony/drift.js +401 -401
- package/src/harmony/governance.js +313 -313
- package/src/harmony/memory.js +239 -239
- package/src/harmony/sync.js +475 -475
- package/src/harmony/watch.js +370 -370
- package/src/hook-validation.js +342 -342
- package/src/index.js +271 -271
- package/src/init.js +184 -184
- package/src/instruction-surfaces.js +185 -185
- package/src/integrations.js +144 -144
- package/src/interactive.js +118 -118
- package/src/locales/en.json +1 -1
- package/src/locales/es.json +1 -1
- package/src/mcp-packs.js +830 -830
- package/src/mcp-server.js +726 -726
- package/src/mcp-validation.js +337 -337
- package/src/nerviq-sync.json +7 -7
- package/src/opencode/config-parser.js +109 -109
- package/src/opencode/context.js +247 -247
- package/src/opencode/deep-review.js +313 -313
- package/src/opencode/domain-packs.js +262 -262
- package/src/opencode/freshness.js +66 -66
- package/src/opencode/governance.js +159 -159
- package/src/opencode/interactive.js +392 -392
- package/src/opencode/mcp-packs.js +705 -705
- package/src/opencode/patch.js +184 -184
- package/src/opencode/plans.js +231 -231
- package/src/opencode/premium.js +413 -413
- package/src/opencode/setup.js +449 -449
- package/src/opencode/techniques.js +27 -27
- package/src/operating-profile.js +574 -574
- package/src/org.js +152 -152
- package/src/permission-rules.js +218 -218
- package/src/plans.js +839 -839
- package/src/platform-change-manifest.js +86 -86
- package/src/plugins.js +110 -110
- package/src/policy-layers.js +210 -210
- package/src/profiles.js +124 -124
- package/src/prompt-injection.js +74 -74
- package/src/public-api.js +173 -173
- package/src/recommendation-rules.js +84 -84
- package/src/repo-archetype.js +386 -386
- package/src/secret-patterns.js +39 -39
- package/src/server.js +527 -527
- package/src/setup/analysis.js +607 -607
- package/src/setup/runtime.js +172 -172
- package/src/setup.js +677 -677
- package/src/shared/capabilities.js +194 -194
- package/src/source-urls.js +132 -132
- package/src/stack-checks.js +565 -565
- package/src/supplemental-checks.js +13 -13
- package/src/synergy/adaptive.js +261 -261
- package/src/synergy/compensation.js +137 -137
- package/src/synergy/evidence.js +193 -193
- package/src/synergy/learning.js +199 -199
- package/src/synergy/patterns.js +227 -227
- package/src/synergy/ranking.js +83 -83
- package/src/synergy/report.js +165 -165
- package/src/synergy/routing.js +146 -146
- package/src/techniques/api.js +407 -407
- package/src/techniques/automation.js +316 -316
- package/src/techniques/compliance.js +257 -257
- package/src/techniques/hygiene.js +294 -294
- package/src/techniques/instructions.js +243 -243
- package/src/techniques/observability.js +226 -226
- package/src/techniques/optimization.js +142 -142
- package/src/techniques/quality.js +318 -318
- package/src/techniques/security.js +237 -237
- package/src/techniques/shared.js +443 -443
- package/src/techniques/stacks.js +2294 -2294
- package/src/techniques/tools.js +106 -106
- package/src/techniques/workflow.js +413 -413
- package/src/techniques.js +81 -81
- package/src/terminology.js +73 -73
- package/src/token-estimate.js +35 -35
- package/src/usage-patterns.js +99 -99
- package/src/verification-metadata.js +145 -145
- package/src/watch.js +247 -247
- package/src/windsurf/activity.js +302 -302
- package/src/windsurf/config-parser.js +267 -267
- package/src/windsurf/context.js +249 -249
- package/src/windsurf/deep-review.js +337 -337
- package/src/windsurf/domain-packs.js +370 -370
- package/src/windsurf/freshness.js +36 -36
- package/src/windsurf/governance.js +231 -231
- package/src/windsurf/interactive.js +388 -388
- package/src/windsurf/mcp-packs.js +792 -792
- package/src/windsurf/plans.js +247 -247
- package/src/windsurf/premium.js +468 -468
- package/src/windsurf/setup.js +471 -471
- package/src/windsurf/techniques.js +17 -17
- package/src/workspace.js +375 -375
package/src/auto-suggest.js
CHANGED
|
@@ -1,154 +1,154 @@
|
|
|
1
|
-
const { loadPatterns } = require('./usage-patterns');
|
|
2
|
-
const { readSnapshotIndex } = require('./activity');
|
|
3
|
-
|
|
4
|
-
const MIN_EVENTS = 2;
|
|
5
|
-
const SUPPRESS_THRESHOLD = 3;
|
|
6
|
-
const RECENT_AUDITS = 10;
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Analyze usage patterns and audit history to suggest rules.
|
|
10
|
-
*/
|
|
11
|
-
function analyzeSuggestions(dir) {
|
|
12
|
-
const patterns = loadPatterns(dir);
|
|
13
|
-
const snapshots = readSnapshotIndex(dir);
|
|
14
|
-
|
|
15
|
-
const keys = Object.keys(patterns);
|
|
16
|
-
const totalEvents = keys.reduce((sum, k) => {
|
|
17
|
-
const e = patterns[k];
|
|
18
|
-
return sum + e.accepted + e.rejected + e.skipped;
|
|
19
|
-
}, 0);
|
|
20
|
-
|
|
21
|
-
// Checks always accepted -> suggest as required
|
|
22
|
-
const suggestedRules = keys
|
|
23
|
-
.filter(k => {
|
|
24
|
-
const e = patterns[k];
|
|
25
|
-
return e.accepted >= MIN_EVENTS && e.rejected === 0;
|
|
26
|
-
})
|
|
27
|
-
.map(k => ({ key: k, accepted: patterns[k].accepted, total: patterns[k].accepted }));
|
|
28
|
-
|
|
29
|
-
// Checks always rejected -> suggest suppressing
|
|
30
|
-
const suggestedSuppressions = keys
|
|
31
|
-
.filter(k => {
|
|
32
|
-
const e = patterns[k];
|
|
33
|
-
return e.rejected >= SUPPRESS_THRESHOLD && e.accepted === 0;
|
|
34
|
-
})
|
|
35
|
-
.map(k => ({ key: k, rejected: patterns[k].rejected, total: patterns[k].rejected }));
|
|
36
|
-
|
|
37
|
-
// From audit snapshots: checks that repeatedly appear in topActionKeys (failing)
|
|
38
|
-
const auditSnapshots = snapshots
|
|
39
|
-
.filter(s => s.snapshotKind === 'audit' && s.summary && Array.isArray(s.summary.topActionKeys))
|
|
40
|
-
.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
|
|
41
|
-
.slice(0, RECENT_AUDITS);
|
|
42
|
-
|
|
43
|
-
const failCounts = {};
|
|
44
|
-
for (const snap of auditSnapshots) {
|
|
45
|
-
for (const key of snap.summary.topActionKeys) {
|
|
46
|
-
failCounts[key] = (failCounts[key] || 0) + 1;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const suggestedPriorities = Object.entries(failCounts)
|
|
51
|
-
.filter(([, count]) => count >= 2)
|
|
52
|
-
.sort((a, b) => b[1] - a[1])
|
|
53
|
-
.map(([key, count]) => ({ key, failCount: count, auditCount: auditSnapshots.length }));
|
|
54
|
-
|
|
55
|
-
const hasSuggestions = suggestedRules.length > 0 || suggestedSuppressions.length > 0 || suggestedPriorities.length > 0;
|
|
56
|
-
let bootstrap = { ready: true, state: 'ready', message: null, steps: [] };
|
|
57
|
-
|
|
58
|
-
if (totalEvents === 0 && auditSnapshots.length === 0) {
|
|
59
|
-
bootstrap = {
|
|
60
|
-
ready: false,
|
|
61
|
-
state: 'empty',
|
|
62
|
-
message: 'No local usage or snapshot history exists yet.',
|
|
63
|
-
steps: [
|
|
64
|
-
'Run `nerviq audit --snapshot` to save the baseline.',
|
|
65
|
-
'Use `nerviq fix`, `nerviq fix --all-critical`, or `nerviq feedback` to record recommendation outcomes.',
|
|
66
|
-
'Run `nerviq audit --snapshot` again after a meaningful repo change.',
|
|
67
|
-
'Re-run `nerviq suggest-rules`.',
|
|
68
|
-
],
|
|
69
|
-
};
|
|
70
|
-
} else if (!hasSuggestions && totalEvents === 0 && auditSnapshots.length > 0) {
|
|
71
|
-
bootstrap = {
|
|
72
|
-
ready: false,
|
|
73
|
-
state: 'snapshots-only',
|
|
74
|
-
message: `${auditSnapshots.length} audit snapshot(s) exist, but no recommendation outcomes have been recorded yet.`,
|
|
75
|
-
steps: [
|
|
76
|
-
'Run `nerviq fix` or `nerviq feedback` so Nerviq can learn which recommendations you accept or reject.',
|
|
77
|
-
'Re-run `nerviq suggest-rules` after another fix cycle.',
|
|
78
|
-
],
|
|
79
|
-
};
|
|
80
|
-
} else if (!hasSuggestions && totalEvents > 0 && auditSnapshots.length === 0) {
|
|
81
|
-
bootstrap = {
|
|
82
|
-
ready: false,
|
|
83
|
-
state: 'patterns-only',
|
|
84
|
-
message: `${totalEvents} usage event(s) exist, but no audit snapshots have been saved yet.`,
|
|
85
|
-
steps: [
|
|
86
|
-
'Run `nerviq audit --snapshot` to save the baseline.',
|
|
87
|
-
'Run it again after changes so repeated failures can be prioritized.',
|
|
88
|
-
'Re-run `nerviq suggest-rules`.',
|
|
89
|
-
],
|
|
90
|
-
};
|
|
91
|
-
} else if (!hasSuggestions) {
|
|
92
|
-
bootstrap = {
|
|
93
|
-
ready: false,
|
|
94
|
-
state: 'warming-up',
|
|
95
|
-
message: `Nerviq has some local history (${totalEvents} pattern events, ${auditSnapshots.length} audit snapshots), but not enough repeated signals yet.`,
|
|
96
|
-
steps: [
|
|
97
|
-
'Keep saving snapshots with `nerviq audit --snapshot`.',
|
|
98
|
-
'Keep recording outcomes with `nerviq fix` or `nerviq feedback`.',
|
|
99
|
-
'Re-run `nerviq suggest-rules` after another change cycle.',
|
|
100
|
-
],
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return { totalEvents, auditCount: auditSnapshots.length, suggestedRules, suggestedSuppressions, suggestedPriorities, bootstrap };
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Format suggestions for CLI output.
|
|
109
|
-
*/
|
|
110
|
-
function formatSuggestions(suggestions) {
|
|
111
|
-
const { totalEvents, auditCount, suggestedRules, suggestedSuppressions, suggestedPriorities, bootstrap } = suggestions;
|
|
112
|
-
|
|
113
|
-
const sources = [];
|
|
114
|
-
if (totalEvents > 0) sources.push(`${totalEvents} pattern events`);
|
|
115
|
-
if (auditCount > 0) sources.push(`${auditCount} audit snapshots`);
|
|
116
|
-
const lines = [
|
|
117
|
-
sources.length > 0
|
|
118
|
-
? ` Auto-Suggested Rules (based on ${sources.join(', ')}):`
|
|
119
|
-
: ' Auto-Suggested Rules:',
|
|
120
|
-
];
|
|
121
|
-
|
|
122
|
-
if (suggestedRules.length > 0) {
|
|
123
|
-
lines.push('', ' Suggested as required (always accepted):');
|
|
124
|
-
for (const r of suggestedRules) {
|
|
125
|
-
lines.push(` + ${r.key.padEnd(20)} — accepted ${r.accepted}/${r.total} times, consider making mandatory`);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (suggestedSuppressions.length > 0) {
|
|
130
|
-
lines.push('', ' Suggested to suppress (always rejected):');
|
|
131
|
-
for (const s of suggestedSuppressions) {
|
|
132
|
-
lines.push(` - ${s.key.padEnd(20)} — rejected ${s.rejected}/${s.total} times, may not fit your workflow`);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (suggestedPriorities.length > 0) {
|
|
137
|
-
lines.push('', ' Priority focus (failing repeatedly):');
|
|
138
|
-
for (const p of suggestedPriorities) {
|
|
139
|
-
lines.push(` ! ${p.key.padEnd(20)} — failed in ${p.failCount}/${p.auditCount} recent audits`);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (suggestedRules.length === 0 && suggestedSuppressions.length === 0 && suggestedPriorities.length === 0 && bootstrap && !bootstrap.ready) {
|
|
144
|
-
lines.push('', ` ${bootstrap.message}`);
|
|
145
|
-
lines.push(' Bootstrap it with:');
|
|
146
|
-
for (let i = 0; i < bootstrap.steps.length; i++) {
|
|
147
|
-
lines.push(` ${i + 1}. ${bootstrap.steps[i]}`);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return lines.join('\n');
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
module.exports = { analyzeSuggestions, formatSuggestions };
|
|
1
|
+
const { loadPatterns } = require('./usage-patterns');
|
|
2
|
+
const { readSnapshotIndex } = require('./activity');
|
|
3
|
+
|
|
4
|
+
const MIN_EVENTS = 2;
|
|
5
|
+
const SUPPRESS_THRESHOLD = 3;
|
|
6
|
+
const RECENT_AUDITS = 10;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Analyze usage patterns and audit history to suggest rules.
|
|
10
|
+
*/
|
|
11
|
+
function analyzeSuggestions(dir) {
|
|
12
|
+
const patterns = loadPatterns(dir);
|
|
13
|
+
const snapshots = readSnapshotIndex(dir);
|
|
14
|
+
|
|
15
|
+
const keys = Object.keys(patterns);
|
|
16
|
+
const totalEvents = keys.reduce((sum, k) => {
|
|
17
|
+
const e = patterns[k];
|
|
18
|
+
return sum + e.accepted + e.rejected + e.skipped;
|
|
19
|
+
}, 0);
|
|
20
|
+
|
|
21
|
+
// Checks always accepted -> suggest as required
|
|
22
|
+
const suggestedRules = keys
|
|
23
|
+
.filter(k => {
|
|
24
|
+
const e = patterns[k];
|
|
25
|
+
return e.accepted >= MIN_EVENTS && e.rejected === 0;
|
|
26
|
+
})
|
|
27
|
+
.map(k => ({ key: k, accepted: patterns[k].accepted, total: patterns[k].accepted }));
|
|
28
|
+
|
|
29
|
+
// Checks always rejected -> suggest suppressing
|
|
30
|
+
const suggestedSuppressions = keys
|
|
31
|
+
.filter(k => {
|
|
32
|
+
const e = patterns[k];
|
|
33
|
+
return e.rejected >= SUPPRESS_THRESHOLD && e.accepted === 0;
|
|
34
|
+
})
|
|
35
|
+
.map(k => ({ key: k, rejected: patterns[k].rejected, total: patterns[k].rejected }));
|
|
36
|
+
|
|
37
|
+
// From audit snapshots: checks that repeatedly appear in topActionKeys (failing)
|
|
38
|
+
const auditSnapshots = snapshots
|
|
39
|
+
.filter(s => s.snapshotKind === 'audit' && s.summary && Array.isArray(s.summary.topActionKeys))
|
|
40
|
+
.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
|
|
41
|
+
.slice(0, RECENT_AUDITS);
|
|
42
|
+
|
|
43
|
+
const failCounts = {};
|
|
44
|
+
for (const snap of auditSnapshots) {
|
|
45
|
+
for (const key of snap.summary.topActionKeys) {
|
|
46
|
+
failCounts[key] = (failCounts[key] || 0) + 1;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const suggestedPriorities = Object.entries(failCounts)
|
|
51
|
+
.filter(([, count]) => count >= 2)
|
|
52
|
+
.sort((a, b) => b[1] - a[1])
|
|
53
|
+
.map(([key, count]) => ({ key, failCount: count, auditCount: auditSnapshots.length }));
|
|
54
|
+
|
|
55
|
+
const hasSuggestions = suggestedRules.length > 0 || suggestedSuppressions.length > 0 || suggestedPriorities.length > 0;
|
|
56
|
+
let bootstrap = { ready: true, state: 'ready', message: null, steps: [] };
|
|
57
|
+
|
|
58
|
+
if (totalEvents === 0 && auditSnapshots.length === 0) {
|
|
59
|
+
bootstrap = {
|
|
60
|
+
ready: false,
|
|
61
|
+
state: 'empty',
|
|
62
|
+
message: 'No local usage or snapshot history exists yet.',
|
|
63
|
+
steps: [
|
|
64
|
+
'Run `nerviq audit --snapshot` to save the baseline.',
|
|
65
|
+
'Use `nerviq fix`, `nerviq fix --all-critical`, or `nerviq feedback` to record recommendation outcomes.',
|
|
66
|
+
'Run `nerviq audit --snapshot` again after a meaningful repo change.',
|
|
67
|
+
'Re-run `nerviq suggest-rules`.',
|
|
68
|
+
],
|
|
69
|
+
};
|
|
70
|
+
} else if (!hasSuggestions && totalEvents === 0 && auditSnapshots.length > 0) {
|
|
71
|
+
bootstrap = {
|
|
72
|
+
ready: false,
|
|
73
|
+
state: 'snapshots-only',
|
|
74
|
+
message: `${auditSnapshots.length} audit snapshot(s) exist, but no recommendation outcomes have been recorded yet.`,
|
|
75
|
+
steps: [
|
|
76
|
+
'Run `nerviq fix` or `nerviq feedback` so Nerviq can learn which recommendations you accept or reject.',
|
|
77
|
+
'Re-run `nerviq suggest-rules` after another fix cycle.',
|
|
78
|
+
],
|
|
79
|
+
};
|
|
80
|
+
} else if (!hasSuggestions && totalEvents > 0 && auditSnapshots.length === 0) {
|
|
81
|
+
bootstrap = {
|
|
82
|
+
ready: false,
|
|
83
|
+
state: 'patterns-only',
|
|
84
|
+
message: `${totalEvents} usage event(s) exist, but no audit snapshots have been saved yet.`,
|
|
85
|
+
steps: [
|
|
86
|
+
'Run `nerviq audit --snapshot` to save the baseline.',
|
|
87
|
+
'Run it again after changes so repeated failures can be prioritized.',
|
|
88
|
+
'Re-run `nerviq suggest-rules`.',
|
|
89
|
+
],
|
|
90
|
+
};
|
|
91
|
+
} else if (!hasSuggestions) {
|
|
92
|
+
bootstrap = {
|
|
93
|
+
ready: false,
|
|
94
|
+
state: 'warming-up',
|
|
95
|
+
message: `Nerviq has some local history (${totalEvents} pattern events, ${auditSnapshots.length} audit snapshots), but not enough repeated signals yet.`,
|
|
96
|
+
steps: [
|
|
97
|
+
'Keep saving snapshots with `nerviq audit --snapshot`.',
|
|
98
|
+
'Keep recording outcomes with `nerviq fix` or `nerviq feedback`.',
|
|
99
|
+
'Re-run `nerviq suggest-rules` after another change cycle.',
|
|
100
|
+
],
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return { totalEvents, auditCount: auditSnapshots.length, suggestedRules, suggestedSuppressions, suggestedPriorities, bootstrap };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Format suggestions for CLI output.
|
|
109
|
+
*/
|
|
110
|
+
function formatSuggestions(suggestions) {
|
|
111
|
+
const { totalEvents, auditCount, suggestedRules, suggestedSuppressions, suggestedPriorities, bootstrap } = suggestions;
|
|
112
|
+
|
|
113
|
+
const sources = [];
|
|
114
|
+
if (totalEvents > 0) sources.push(`${totalEvents} pattern events`);
|
|
115
|
+
if (auditCount > 0) sources.push(`${auditCount} audit snapshots`);
|
|
116
|
+
const lines = [
|
|
117
|
+
sources.length > 0
|
|
118
|
+
? ` Auto-Suggested Rules (based on ${sources.join(', ')}):`
|
|
119
|
+
: ' Auto-Suggested Rules:',
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
if (suggestedRules.length > 0) {
|
|
123
|
+
lines.push('', ' Suggested as required (always accepted):');
|
|
124
|
+
for (const r of suggestedRules) {
|
|
125
|
+
lines.push(` + ${r.key.padEnd(20)} — accepted ${r.accepted}/${r.total} times, consider making mandatory`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (suggestedSuppressions.length > 0) {
|
|
130
|
+
lines.push('', ' Suggested to suppress (always rejected):');
|
|
131
|
+
for (const s of suggestedSuppressions) {
|
|
132
|
+
lines.push(` - ${s.key.padEnd(20)} — rejected ${s.rejected}/${s.total} times, may not fit your workflow`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (suggestedPriorities.length > 0) {
|
|
137
|
+
lines.push('', ' Priority focus (failing repeatedly):');
|
|
138
|
+
for (const p of suggestedPriorities) {
|
|
139
|
+
lines.push(` ! ${p.key.padEnd(20)} — failed in ${p.failCount}/${p.auditCount} recent audits`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (suggestedRules.length === 0 && suggestedSuppressions.length === 0 && suggestedPriorities.length === 0 && bootstrap && !bootstrap.ready) {
|
|
144
|
+
lines.push('', ` ${bootstrap.message}`);
|
|
145
|
+
lines.push(' Bootstrap it with:');
|
|
146
|
+
for (let i = 0; i < bootstrap.steps.length; i++) {
|
|
147
|
+
lines.push(` ${i + 1}. ${bootstrap.steps[i]}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return lines.join('\n');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
module.exports = { analyzeSuggestions, formatSuggestions };
|
package/src/badge.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
function getBadgeUrl(score) {
|
|
2
|
-
const color = score >= 80 ? 'brightgreen' : score >= 60 ? 'yellow' : score >= 40 ? 'orange' : 'red';
|
|
3
|
-
const label = encodeURIComponent('Claude Code Ready');
|
|
4
|
-
const message = encodeURIComponent(`${score}/100`);
|
|
5
|
-
return `https://img.shields.io/badge/${label}-${message}-${color}`;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function getBadgeMarkdown(score) {
|
|
9
|
-
const url = getBadgeUrl(score);
|
|
10
|
-
return `[](https://github.com/nerviq/nerviq)`;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
module.exports = { getBadgeUrl, getBadgeMarkdown };
|
|
1
|
+
function getBadgeUrl(score) {
|
|
2
|
+
const color = score >= 80 ? 'brightgreen' : score >= 60 ? 'yellow' : score >= 40 ? 'orange' : 'red';
|
|
3
|
+
const label = encodeURIComponent('Claude Code Ready');
|
|
4
|
+
const message = encodeURIComponent(`${score}/100`);
|
|
5
|
+
return `https://img.shields.io/badge/${label}-${message}-${color}`;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function getBadgeMarkdown(score) {
|
|
9
|
+
const url = getBadgeUrl(score);
|
|
10
|
+
return `[](https://github.com/nerviq/nerviq)`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
module.exports = { getBadgeUrl, getBadgeMarkdown };
|