clud-bug 0.6.34 → 0.7.0-rc.11
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/README.md +20 -0
- package/bin/clud-bug.js +10 -1353
- package/data/canonical-v1.json +37 -0
- package/dist/cli/agents-md.d.ts +16 -0
- package/dist/cli/agents-md.d.ts.map +1 -0
- package/dist/cli/agents-md.js +226 -0
- package/dist/cli/agents-md.js.map +1 -0
- package/dist/cli/audit.d.ts +13 -0
- package/dist/cli/audit.d.ts.map +1 -0
- package/dist/cli/audit.js +90 -0
- package/dist/cli/audit.js.map +1 -0
- package/dist/cli/branch-protection.d.ts +57 -0
- package/dist/cli/branch-protection.d.ts.map +1 -0
- package/dist/cli/branch-protection.js +118 -0
- package/dist/cli/branch-protection.js.map +1 -0
- package/dist/cli/configure-github.d.ts +58 -0
- package/dist/cli/configure-github.d.ts.map +1 -0
- package/dist/cli/configure-github.js +242 -0
- package/dist/cli/configure-github.js.map +1 -0
- package/dist/cli/edit-workflow.d.ts +18 -0
- package/dist/cli/edit-workflow.d.ts.map +1 -0
- package/dist/cli/edit-workflow.js +43 -0
- package/dist/cli/edit-workflow.js.map +1 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +19 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/main.d.ts +3 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +2067 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/skill-usage.d.ts +109 -0
- package/dist/cli/skill-usage.d.ts.map +1 -0
- package/dist/cli/skill-usage.js +380 -0
- package/dist/cli/skill-usage.js.map +1 -0
- package/dist/cli/skills.d.ts +56 -0
- package/dist/cli/skills.d.ts.map +1 -0
- package/dist/cli/skills.js +292 -0
- package/dist/cli/skills.js.map +1 -0
- package/dist/cli/update.d.ts +29 -0
- package/dist/cli/update.d.ts.map +1 -0
- package/dist/cli/update.js +205 -0
- package/dist/cli/update.js.map +1 -0
- package/dist/cli/usage.d.ts +142 -0
- package/dist/cli/usage.d.ts.map +1 -0
- package/dist/cli/usage.js +348 -0
- package/dist/cli/usage.js.map +1 -0
- package/dist/core/audit.d.ts +8 -0
- package/dist/core/audit.d.ts.map +1 -0
- package/dist/core/audit.js +47 -0
- package/dist/core/audit.js.map +1 -0
- package/dist/core/auto-resolve.d.ts +235 -0
- package/dist/core/auto-resolve.d.ts.map +1 -0
- package/dist/core/auto-resolve.js +293 -0
- package/dist/core/auto-resolve.js.map +1 -0
- package/dist/core/configure-github.d.ts +179 -0
- package/dist/core/configure-github.d.ts.map +1 -0
- package/dist/core/configure-github.js +289 -0
- package/dist/core/configure-github.js.map +1 -0
- package/dist/core/detect.d.ts +77 -0
- package/dist/core/detect.d.ts.map +1 -0
- package/dist/core/detect.js +262 -0
- package/dist/core/detect.js.map +1 -0
- package/dist/core/diff-findings.d.ts +96 -0
- package/dist/core/diff-findings.d.ts.map +1 -0
- package/dist/core/diff-findings.js +261 -0
- package/dist/core/diff-findings.js.map +1 -0
- package/dist/core/formal-review.d.ts +79 -0
- package/dist/core/formal-review.d.ts.map +1 -0
- package/dist/core/formal-review.js +71 -0
- package/dist/core/formal-review.js.map +1 -0
- package/dist/core/index.d.ts +17 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +66 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/inline-threads.d.ts +160 -0
- package/dist/core/inline-threads.d.ts.map +1 -0
- package/dist/core/inline-threads.js +369 -0
- package/dist/core/inline-threads.js.map +1 -0
- package/dist/core/prompt-builder.d.ts +164 -0
- package/dist/core/prompt-builder.d.ts.map +1 -0
- package/dist/core/prompt-builder.js +419 -0
- package/dist/core/prompt-builder.js.map +1 -0
- package/dist/core/prompts.d.ts +9 -0
- package/dist/core/prompts.d.ts.map +1 -0
- package/dist/core/prompts.js +401 -0
- package/dist/core/prompts.js.map +1 -0
- package/dist/core/render-review.d.ts +6 -0
- package/dist/core/render-review.d.ts.map +1 -0
- package/dist/core/render-review.js +219 -0
- package/dist/core/render-review.js.map +1 -0
- package/dist/core/render.d.ts +13 -0
- package/dist/core/render.d.ts.map +1 -0
- package/dist/core/render.js +62 -0
- package/dist/core/render.js.map +1 -0
- package/dist/core/resolve-verifier.d.ts +46 -0
- package/dist/core/resolve-verifier.d.ts.map +1 -0
- package/dist/core/resolve-verifier.js +187 -0
- package/dist/core/resolve-verifier.js.map +1 -0
- package/dist/core/review-schema-zod.d.ts +240 -0
- package/dist/core/review-schema-zod.d.ts.map +1 -0
- package/dist/core/review-schema-zod.js +218 -0
- package/dist/core/review-schema-zod.js.map +1 -0
- package/dist/core/review-schema.d.ts +42 -0
- package/dist/core/review-schema.d.ts.map +1 -0
- package/dist/core/review-schema.js +156 -0
- package/dist/core/review-schema.js.map +1 -0
- package/dist/core/review-writeback.d.ts +193 -0
- package/dist/core/review-writeback.d.ts.map +1 -0
- package/dist/core/review-writeback.js +364 -0
- package/dist/core/review-writeback.js.map +1 -0
- package/dist/core/skills.d.ts +147 -0
- package/dist/core/skills.d.ts.map +1 -0
- package/dist/core/skills.js +726 -0
- package/dist/core/skills.js.map +1 -0
- package/dist/core/version.d.ts +2 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/core/version.js +4 -0
- package/dist/core/version.js.map +1 -0
- package/package.json +37 -5
- package/{lib/agents-md.js → src/cli/agents-md.ts} +25 -14
- package/{lib/audit.js → src/cli/audit.ts} +37 -44
- package/{lib/branch-protection.js → src/cli/branch-protection.ts} +75 -11
- package/src/cli/configure-github.ts +329 -0
- package/{lib/edit-workflow.js → src/cli/edit-workflow.ts} +32 -11
- package/src/cli/index.ts +107 -0
- package/src/cli/main.ts +2204 -0
- package/{lib/skill-usage.js → src/cli/skill-usage.ts} +168 -94
- package/src/cli/skills.ts +386 -0
- package/{lib/update.js → src/cli/update.ts} +87 -27
- package/{lib/usage.js → src/cli/usage.ts} +167 -76
- package/src/core/audit.ts +53 -0
- package/src/core/auto-resolve.ts +488 -0
- package/src/core/configure-github.ts +497 -0
- package/{lib/detect.js → src/core/detect.ts} +100 -47
- package/src/core/diff-findings.ts +323 -0
- package/src/core/formal-review.ts +168 -0
- package/src/core/index.ts +250 -0
- package/src/core/inline-threads.ts +471 -0
- package/src/core/prompt-builder.ts +561 -0
- package/{lib/prompts.js → src/core/prompts.ts} +16 -2
- package/{lib/render-review.js → src/core/render-review.ts} +57 -25
- package/{lib/render.js → src/core/render.ts} +37 -17
- package/src/core/resolve-verifier.ts +228 -0
- package/src/core/review-schema-zod.ts +262 -0
- package/{lib/review-schema.js → src/core/review-schema.ts} +68 -5
- package/src/core/review-writeback.ts +565 -0
- package/{lib/skills.js → src/core/skills.ts} +456 -342
- package/src/core/version.ts +3 -0
- package/templates/clud-bug-review.md.tmpl +115 -0
- package/templates/workflow-py.yml.tmpl +80 -3
- package/templates/workflow-ts.yml.tmpl +80 -3
- package/templates/workflow.yml.tmpl +175 -8
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
// src/cli/skill-usage.ts — Component 1+2 of the pragmatic SkDD pivot.
|
|
2
|
+
//
|
|
3
|
+
// Pure functions for deterministic skill-usage tracking. Per the
|
|
4
|
+
// strategic pivot (2026-05-30): replace Zak Elfassi's speculative
|
|
5
|
+
// recursive-meta-skill direction with concrete usage data + human-gated
|
|
6
|
+
// approval. This module is the data layer.
|
|
7
|
+
//
|
|
8
|
+
// Three responsibilities:
|
|
9
|
+
//
|
|
10
|
+
// 1. computeSkillUsageDelta(reviewJson)
|
|
11
|
+
// Given the structured-output JSON from one clud-bug review,
|
|
12
|
+
// return the per-skill delta for that one review.
|
|
13
|
+
//
|
|
14
|
+
// 2. mergeSkillUsage(existing, delta, timestamp)
|
|
15
|
+
// Merge a delta into the persistent usage block (the `usage`
|
|
16
|
+
// field in `.claude/skills/.clud-bug.json`).
|
|
17
|
+
//
|
|
18
|
+
// 3. assessSkillHealth(usage, now)
|
|
19
|
+
// Apply the deterministic thresholds + return a row per skill
|
|
20
|
+
// that `clud-bug usage --health` renders as a table.
|
|
21
|
+
//
|
|
22
|
+
// All three are pure. Side effects (file I/O) live in bin/clud-bug.js
|
|
23
|
+
// and the workflow post-step (v0.6.29).
|
|
24
|
+
//
|
|
25
|
+
// Thresholds — concrete numbers per design (2026-05-30):
|
|
26
|
+
//
|
|
27
|
+
// - archive-candidate: citations == 0 across last 90 days of loads
|
|
28
|
+
// - stale: last cited > 60 days ago
|
|
29
|
+
// - healthy: >= 3 citations in any rolling 90-day window
|
|
30
|
+
// - new: loads < 5 (still bedding in; don't judge yet)
|
|
31
|
+
//
|
|
32
|
+
// No automation acts on this output. It's a READ-ONLY dashboard.
|
|
33
|
+
// Humans read; humans decide; humans act.
|
|
34
|
+
import { spawn } from 'node:child_process';
|
|
35
|
+
/**
|
|
36
|
+
* Compute per-skill usage delta from a single review's structured JSON.
|
|
37
|
+
*
|
|
38
|
+
* Rules:
|
|
39
|
+
* - loads = 1 for every skill in per_skill_scan (the skill was in
|
|
40
|
+
* context for this review).
|
|
41
|
+
* - citations = 1 if the skill slug appears in ANY finding bucket
|
|
42
|
+
* (critical / minor / dedicated). Multiple findings from the same
|
|
43
|
+
* skill on one review = 1 citation, not N. Citations count REVIEWS
|
|
44
|
+
* that cited the skill, not findings within a review.
|
|
45
|
+
*
|
|
46
|
+
* Returns {} on missing / malformed input (defensive — never throws).
|
|
47
|
+
*/
|
|
48
|
+
export function computeSkillUsageDelta(reviewJson) {
|
|
49
|
+
if (!reviewJson || typeof reviewJson !== 'object')
|
|
50
|
+
return {};
|
|
51
|
+
const review = reviewJson;
|
|
52
|
+
const delta = {};
|
|
53
|
+
// Loads — one per skill that scanned.
|
|
54
|
+
for (const entry of review.per_skill_scan || []) {
|
|
55
|
+
if (!entry || typeof entry.skill !== 'string')
|
|
56
|
+
continue;
|
|
57
|
+
const slug = entry.skill;
|
|
58
|
+
if (!delta[slug])
|
|
59
|
+
delta[slug] = { loads: 0, citations: 0 };
|
|
60
|
+
delta[slug].loads = 1;
|
|
61
|
+
}
|
|
62
|
+
// Citations — collect unique skill slugs across all finding buckets.
|
|
63
|
+
const cited = new Set();
|
|
64
|
+
const collect = (findings) => {
|
|
65
|
+
for (const f of findings || []) {
|
|
66
|
+
if (f && typeof f.skill === 'string')
|
|
67
|
+
cited.add(f.skill);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
collect(review.critical_findings);
|
|
71
|
+
collect(review.minor_findings);
|
|
72
|
+
collect(review.preexisting_findings);
|
|
73
|
+
for (const section of review.dedicated_sections || []) {
|
|
74
|
+
collect(section?.findings);
|
|
75
|
+
}
|
|
76
|
+
for (const slug of cited) {
|
|
77
|
+
if (!delta[slug])
|
|
78
|
+
delta[slug] = { loads: 0, citations: 0 };
|
|
79
|
+
delta[slug].citations = 1;
|
|
80
|
+
}
|
|
81
|
+
return delta;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Merge a per-review delta into a persistent usage block.
|
|
85
|
+
*
|
|
86
|
+
* Semantics:
|
|
87
|
+
* - existing.loads + delta.loads → new.loads (accumulates forever)
|
|
88
|
+
* - existing.citations + delta.citations → new.citations
|
|
89
|
+
* - last_cited updates only when delta.citations > 0 (i.e., cited
|
|
90
|
+
* in THIS review). Stays at the prior value otherwise.
|
|
91
|
+
* - New skills (not in existing) get initialized fresh.
|
|
92
|
+
*/
|
|
93
|
+
export function mergeSkillUsage(existing, delta, timestamp) {
|
|
94
|
+
const safeExisting = (existing && typeof existing === 'object') ? existing : {};
|
|
95
|
+
const result = {};
|
|
96
|
+
// Copy all existing skills first (preserve skills NOT in this delta).
|
|
97
|
+
for (const [slug, entry] of Object.entries(safeExisting)) {
|
|
98
|
+
if (entry && typeof entry === 'object') {
|
|
99
|
+
const e = entry;
|
|
100
|
+
result[slug] = {
|
|
101
|
+
loads: Number(e.loads) || 0,
|
|
102
|
+
citations: Number(e.citations) || 0,
|
|
103
|
+
last_cited: typeof e.last_cited === 'string' ? e.last_cited : null,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Merge delta.
|
|
108
|
+
for (const [slug, d] of Object.entries(delta || {})) {
|
|
109
|
+
let row = result[slug];
|
|
110
|
+
if (!row) {
|
|
111
|
+
row = { loads: 0, citations: 0, last_cited: null };
|
|
112
|
+
result[slug] = row;
|
|
113
|
+
}
|
|
114
|
+
row.loads += Number(d.loads) || 0;
|
|
115
|
+
row.citations += Number(d.citations) || 0;
|
|
116
|
+
if ((Number(d.citations) || 0) > 0 && timestamp) {
|
|
117
|
+
row.last_cited = timestamp;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Apply deterministic skill-health thresholds to a usage block.
|
|
124
|
+
*
|
|
125
|
+
* Status values:
|
|
126
|
+
* - "archive-candidate": citations == 0 AND loads >= 5
|
|
127
|
+
* → loaded enough to judge, never cited → propose for removal
|
|
128
|
+
* - "stale": last_cited > 60 days ago (even with citations history)
|
|
129
|
+
* → was useful, hasn't fired recently
|
|
130
|
+
* - "new": loads < 5
|
|
131
|
+
* → still bedding in; don't judge yet
|
|
132
|
+
* - "healthy": cited within 60 days
|
|
133
|
+
* → still earning its place
|
|
134
|
+
*
|
|
135
|
+
* Sorted by status priority (archive > stale > new > healthy), then
|
|
136
|
+
* by loads desc within each group. Highest-noise skills surface first.
|
|
137
|
+
*/
|
|
138
|
+
export function assessSkillHealth(usage, now) {
|
|
139
|
+
const safeUsage = (usage && typeof usage === 'object') ? usage : {};
|
|
140
|
+
const safeNow = (now instanceof Date) ? now : new Date();
|
|
141
|
+
const sixtyDaysAgoMs = safeNow.getTime() - (60 * 24 * 60 * 60 * 1000);
|
|
142
|
+
const rows = [];
|
|
143
|
+
for (const [slug, entry] of Object.entries(safeUsage)) {
|
|
144
|
+
if (!entry || typeof entry !== 'object')
|
|
145
|
+
continue;
|
|
146
|
+
const e = entry;
|
|
147
|
+
const loads = Number(e.loads) || 0;
|
|
148
|
+
const citations = Number(e.citations) || 0;
|
|
149
|
+
const last_cited = typeof e.last_cited === 'string' ? e.last_cited : null;
|
|
150
|
+
let status;
|
|
151
|
+
let days_since_cited = null;
|
|
152
|
+
if (loads < 5) {
|
|
153
|
+
status = 'new';
|
|
154
|
+
}
|
|
155
|
+
else if (citations === 0) {
|
|
156
|
+
status = 'archive-candidate';
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
// Has citations. Check recency.
|
|
160
|
+
const lastCitedMs = last_cited ? Date.parse(last_cited) : null;
|
|
161
|
+
if (lastCitedMs && lastCitedMs >= sixtyDaysAgoMs) {
|
|
162
|
+
status = 'healthy';
|
|
163
|
+
days_since_cited = Math.floor((safeNow.getTime() - lastCitedMs) / (24 * 60 * 60 * 1000));
|
|
164
|
+
}
|
|
165
|
+
else if (lastCitedMs) {
|
|
166
|
+
status = 'stale';
|
|
167
|
+
days_since_cited = Math.floor((safeNow.getTime() - lastCitedMs) / (24 * 60 * 60 * 1000));
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
// Has citations count but no timestamp (legacy / corrupted) — treat as stale.
|
|
171
|
+
status = 'stale';
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
rows.push({ slug, status, loads, citations, last_cited, days_since_cited });
|
|
175
|
+
}
|
|
176
|
+
// Sort: archive-candidates first, then stale, then new, then healthy.
|
|
177
|
+
// Within each group, by loads descending (loudest first).
|
|
178
|
+
const statusOrder = {
|
|
179
|
+
'archive-candidate': 0,
|
|
180
|
+
'stale': 1,
|
|
181
|
+
'new': 2,
|
|
182
|
+
'healthy': 3,
|
|
183
|
+
};
|
|
184
|
+
rows.sort((a, b) => {
|
|
185
|
+
const da = statusOrder[a.status] ?? 99;
|
|
186
|
+
const db = statusOrder[b.status] ?? 99;
|
|
187
|
+
if (da !== db)
|
|
188
|
+
return da - db;
|
|
189
|
+
return b.loads - a.loads;
|
|
190
|
+
});
|
|
191
|
+
return rows;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Render the health dashboard as a 3-column table for the CLI.
|
|
195
|
+
*/
|
|
196
|
+
export function formatHealthDashboard(rows) {
|
|
197
|
+
if (!rows || rows.length === 0) {
|
|
198
|
+
return ('Skill health: no usage data yet.\n\n' +
|
|
199
|
+
'Skill-usage artifacts will start accumulating from your next\n' +
|
|
200
|
+
'clud-bug-review run on a substantive PR (workflow-only PRs auto-skip\n' +
|
|
201
|
+
'review via 0.0.W² and produce no artifact). Run this command again\n' +
|
|
202
|
+
'with `--repo owner/name` once a few reviews have completed.');
|
|
203
|
+
}
|
|
204
|
+
const STATUS_GLYPH = {
|
|
205
|
+
'archive-candidate': '🟥 archive?',
|
|
206
|
+
'stale': '🟨 stale',
|
|
207
|
+
'new': '🟦 new',
|
|
208
|
+
'healthy': '🟩 healthy',
|
|
209
|
+
};
|
|
210
|
+
const lines = [];
|
|
211
|
+
lines.push('Skill health (deterministic — read-only; no automation acts on this)');
|
|
212
|
+
lines.push('');
|
|
213
|
+
lines.push(' STATUS SLUG LOADS CITES LAST CITED');
|
|
214
|
+
lines.push(' ---------------- -------------------------------- ----- ----- --------------');
|
|
215
|
+
for (const r of rows) {
|
|
216
|
+
const status = STATUS_GLYPH[r.status] || r.status;
|
|
217
|
+
const slug = r.slug.length > 32 ? r.slug.slice(0, 29) + '...' : r.slug;
|
|
218
|
+
const ago = r.days_since_cited != null ? `${r.days_since_cited}d ago` : '(never)';
|
|
219
|
+
lines.push(` ${status.padEnd(16)} ${slug.padEnd(32)} ${String(r.loads).padStart(5)} ` +
|
|
220
|
+
`${String(r.citations).padStart(5)} ${ago}`);
|
|
221
|
+
}
|
|
222
|
+
lines.push('');
|
|
223
|
+
lines.push('Thresholds:');
|
|
224
|
+
lines.push(' archive-candidate = citations==0 + loads>=5');
|
|
225
|
+
lines.push(' stale = last cited >60 days ago');
|
|
226
|
+
lines.push(' new = loads<5 (still bedding in)');
|
|
227
|
+
lines.push(' healthy = cited within 60 days');
|
|
228
|
+
return lines.join('\n');
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Default `gh` runner — spawns the local gh CLI. Tests inject a mock.
|
|
232
|
+
*
|
|
233
|
+
* The runner has two methods:
|
|
234
|
+
* - json(args): returns parsed JSON stdout, or null on error.
|
|
235
|
+
* - run(args): returns {code, stdout, stderr}. For commands that
|
|
236
|
+
* download files etc. — no JSON parsing.
|
|
237
|
+
*/
|
|
238
|
+
async function defaultGhJson(args) {
|
|
239
|
+
return new Promise((resolve) => {
|
|
240
|
+
const child = spawn('gh', args, { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
241
|
+
let stdout = '';
|
|
242
|
+
child.stdout.on('data', (d) => { stdout += d; });
|
|
243
|
+
child.on('error', () => resolve(null));
|
|
244
|
+
child.on('close', (code) => {
|
|
245
|
+
if (code !== 0)
|
|
246
|
+
return resolve(null);
|
|
247
|
+
try {
|
|
248
|
+
resolve(JSON.parse(stdout));
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
resolve(null);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
async function defaultGhRun(args) {
|
|
257
|
+
return new Promise((resolve) => {
|
|
258
|
+
const child = spawn('gh', args, { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
259
|
+
let stdout = '';
|
|
260
|
+
let stderr = '';
|
|
261
|
+
child.stdout.on('data', (d) => { stdout += d; });
|
|
262
|
+
child.stderr.on('data', (d) => { stderr += d; });
|
|
263
|
+
child.on('error', () => resolve({ code: 1, stdout: '', stderr: 'gh not on PATH' }));
|
|
264
|
+
child.on('close', (code) => resolve({ code, stdout, stderr }));
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
export const DEFAULT_GH_RUNNER = {
|
|
268
|
+
json: defaultGhJson,
|
|
269
|
+
run: defaultGhRun,
|
|
270
|
+
};
|
|
271
|
+
/**
|
|
272
|
+
* Fetch all per-PR skill-usage artifacts from a repo. Each artifact is
|
|
273
|
+
* downloaded to a temp dir, its `.clud-bug.json` is parsed, and the
|
|
274
|
+
* usage block is returned.
|
|
275
|
+
*/
|
|
276
|
+
export async function fetchUsageArtifacts({ owner, repo, since = null, ghRunner = DEFAULT_GH_RUNNER }) {
|
|
277
|
+
if (!owner || !repo) {
|
|
278
|
+
throw new Error('fetchUsageArtifacts: owner + repo are required');
|
|
279
|
+
}
|
|
280
|
+
// List artifacts in one call. We deliberately do NOT use `--paginate`:
|
|
281
|
+
// `gh api --paginate --jq <expr>` applies the jq filter to EACH page
|
|
282
|
+
// independently and concatenates the outputs with newlines, which
|
|
283
|
+
// produces `[...]\n[...]` — invalid as a single JSON document.
|
|
284
|
+
// `JSON.parse` returns null and the dashboard silently shows nothing
|
|
285
|
+
// for repos with >30 artifacts (default page size). Caught by
|
|
286
|
+
// clud-bug-review on PR #127.
|
|
287
|
+
//
|
|
288
|
+
// `?per_page=100` covers up to 100 artifacts in one call. The 90-day
|
|
289
|
+
// artifact retention means most repos won't hit that ceiling (>100
|
|
290
|
+
// PR reviews in 90 days = >1/day sustained). If a future repo
|
|
291
|
+
// saturates this, paginate manually in v0.6.31+ (per_page=100 +
|
|
292
|
+
// explicit `?page=N` loop, parse each response as JSON, concatenate).
|
|
293
|
+
const list = await ghRunner.json([
|
|
294
|
+
'api',
|
|
295
|
+
`repos/${owner}/${repo}/actions/artifacts?per_page=100`,
|
|
296
|
+
'--jq',
|
|
297
|
+
'[.artifacts[] | select(.name | startswith("clud-bug-skill-usage-pr-")) | select(.expired == false) | {id, name, workflow_run_id: .workflow_run.id, created_at}]',
|
|
298
|
+
]);
|
|
299
|
+
// `--jq '[...]'` wraps the stream into a single array. If the runner
|
|
300
|
+
// returns null (404, no auth, etc.), bail to empty list.
|
|
301
|
+
if (!Array.isArray(list))
|
|
302
|
+
return [];
|
|
303
|
+
const items = list;
|
|
304
|
+
const filtered = since
|
|
305
|
+
? items.filter((a) => new Date(a.created_at) >= since)
|
|
306
|
+
: items;
|
|
307
|
+
const fs = await import('node:fs/promises');
|
|
308
|
+
const path = await import('node:path');
|
|
309
|
+
const os = await import('node:os');
|
|
310
|
+
const results = [];
|
|
311
|
+
for (const art of filtered) {
|
|
312
|
+
const prMatch = art.name.match(/^clud-bug-skill-usage-pr-(\d+)$/);
|
|
313
|
+
if (!prMatch)
|
|
314
|
+
continue;
|
|
315
|
+
// prMatch[1] is `string | undefined` under noUncheckedIndexedAccess; the
|
|
316
|
+
// regex guarantees the capture exists when match succeeds.
|
|
317
|
+
const prNumber = Number(prMatch[1]);
|
|
318
|
+
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'clud-bug-art-'));
|
|
319
|
+
try {
|
|
320
|
+
const dl = await ghRunner.run([
|
|
321
|
+
'run', 'download', String(art.workflow_run_id),
|
|
322
|
+
'-R', `${owner}/${repo}`,
|
|
323
|
+
'-n', art.name,
|
|
324
|
+
'-D', tmpDir,
|
|
325
|
+
]);
|
|
326
|
+
if (dl.code !== 0)
|
|
327
|
+
continue;
|
|
328
|
+
// The workflow uploaded `.clud-bug.json` (single file under the
|
|
329
|
+
// path key). `gh run download -D <dir>` writes it to the dest as
|
|
330
|
+
// `<dir>/.clud-bug.json` (preserves the source path).
|
|
331
|
+
const jsonPath = path.join(tmpDir, '.clud-bug.json');
|
|
332
|
+
let parsed;
|
|
333
|
+
try {
|
|
334
|
+
const raw = await fs.readFile(jsonPath, 'utf-8');
|
|
335
|
+
parsed = JSON.parse(raw);
|
|
336
|
+
}
|
|
337
|
+
catch {
|
|
338
|
+
continue; // artifact corrupted or layout unexpected
|
|
339
|
+
}
|
|
340
|
+
const parsedObj = (parsed && typeof parsed === 'object')
|
|
341
|
+
? parsed
|
|
342
|
+
: {};
|
|
343
|
+
const usage = (parsedObj.usage && typeof parsedObj.usage === 'object')
|
|
344
|
+
? parsedObj.usage
|
|
345
|
+
: {};
|
|
346
|
+
results.push({
|
|
347
|
+
prNumber,
|
|
348
|
+
artifactId: art.id,
|
|
349
|
+
usage,
|
|
350
|
+
fetchedAt: art.created_at,
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
finally {
|
|
354
|
+
await fs.rm(tmpDir, { recursive: true, force: true });
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return results;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Reduce an array of per-PR artifact records into a single accumulated
|
|
361
|
+
* usage block by left-folding `mergeSkillUsage` over them, ordered by
|
|
362
|
+
* `fetchedAt` ascending so the last_cited timestamp is deterministic.
|
|
363
|
+
*
|
|
364
|
+
* Because `mergeSkillUsage` is commutative for loads + citations counts
|
|
365
|
+
* AND keeps the LATEST timestamp it sees as last_cited (we sort
|
|
366
|
+
* ascending so newest wins on the final pass), out-of-order input
|
|
367
|
+
* produces an identical result.
|
|
368
|
+
*/
|
|
369
|
+
export function aggregateUsageStream(artifacts) {
|
|
370
|
+
if (!Array.isArray(artifacts) || artifacts.length === 0)
|
|
371
|
+
return {};
|
|
372
|
+
const sorted = [...artifacts].sort((a, b) => new Date(a.fetchedAt).getTime() - new Date(b.fetchedAt).getTime());
|
|
373
|
+
return sorted.reduce(
|
|
374
|
+
// mergeSkillUsage expects SkillDeltaMap-shape for the delta arg; usage
|
|
375
|
+
// here is SkillUsageMap (loads/citations counts match — only last_cited
|
|
376
|
+
// is extra, which mergeSkillUsage ignores from the delta side). The
|
|
377
|
+
// type assertion is safe and matches the JS prior behavior exactly.
|
|
378
|
+
(acc, art) => mergeSkillUsage(acc, (art.usage || {}), art.fetchedAt), {});
|
|
379
|
+
}
|
|
380
|
+
//# sourceMappingURL=skill-usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-usage.js","sourceRoot":"","sources":["../../src/cli/skill-usage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { SkillsClient, type RankableSkill, type SkillDescriptor } from '../core/skills.js';
|
|
2
|
+
export declare const MANIFEST_FILE = ".clud-bug.json";
|
|
3
|
+
export declare const MANIFEST_VERSION = 1;
|
|
4
|
+
export declare function sanitizeSlug(name: string): string;
|
|
5
|
+
export declare function entryKey(entry: ManifestEntry): string;
|
|
6
|
+
export interface BaselineSkill {
|
|
7
|
+
source: string;
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
installs: number;
|
|
11
|
+
kind: string;
|
|
12
|
+
content: string;
|
|
13
|
+
_source?: 'agent-skills' | 'bundled';
|
|
14
|
+
}
|
|
15
|
+
export interface LoadBaselineOptions {
|
|
16
|
+
fetch?: typeof globalThis.fetch | undefined;
|
|
17
|
+
cacheDir?: string | null | undefined;
|
|
18
|
+
}
|
|
19
|
+
export declare function loadBaseline(baselineDir: string, opts?: LoadBaselineOptions): Promise<BaselineSkill[]>;
|
|
20
|
+
export type WritableSkill = RankableSkill;
|
|
21
|
+
export interface ManifestEntry {
|
|
22
|
+
slug: string;
|
|
23
|
+
name: string;
|
|
24
|
+
source: string;
|
|
25
|
+
kind: string;
|
|
26
|
+
description: string;
|
|
27
|
+
}
|
|
28
|
+
export interface Manifest {
|
|
29
|
+
version: number;
|
|
30
|
+
installed: ManifestEntry[];
|
|
31
|
+
[key: string]: unknown;
|
|
32
|
+
}
|
|
33
|
+
export declare function writeSkills(targetDir: string, skills: WritableSkill[], client: SkillsClient): Promise<ManifestEntry[]>;
|
|
34
|
+
export declare function writeSkill(targetDir: string, skill: WritableSkill, client: SkillsClient): Promise<ManifestEntry>;
|
|
35
|
+
export declare function readManifest(targetDir: string): Promise<Manifest>;
|
|
36
|
+
export declare function writeManifest(targetDir: string, manifest: Manifest): Promise<void>;
|
|
37
|
+
export declare function mergeManifest(existing: Manifest, newEntries: ManifestEntry[]): Manifest;
|
|
38
|
+
export declare function removeSkill(targetDir: string, slug: string): Promise<ManifestEntry>;
|
|
39
|
+
export interface InstalledGroups {
|
|
40
|
+
baseline: ManifestEntry[];
|
|
41
|
+
remote: ManifestEntry[];
|
|
42
|
+
custom: Array<{
|
|
43
|
+
slug: string;
|
|
44
|
+
kind: 'custom';
|
|
45
|
+
description: string;
|
|
46
|
+
}>;
|
|
47
|
+
}
|
|
48
|
+
export declare function listInstalled(targetDir: string): Promise<InstalledGroups>;
|
|
49
|
+
export interface ManifestDiff {
|
|
50
|
+
add: RankableSkill[];
|
|
51
|
+
remove: ManifestEntry[];
|
|
52
|
+
unchanged: RankableSkill[];
|
|
53
|
+
}
|
|
54
|
+
export declare function diffManifest(manifest: Manifest, recommended: RankableSkill[]): ManifestDiff;
|
|
55
|
+
export type { SkillDescriptor };
|
|
56
|
+
//# sourceMappingURL=skills.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/cli/skills.ts"],"names":[],"mappings":"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"}
|