clud-bug 0.6.34 → 0.7.0-rc.1

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 (95) hide show
  1. package/bin/clud-bug.js +10 -1353
  2. package/dist/cli/agents-md.d.ts +16 -0
  3. package/dist/cli/agents-md.d.ts.map +1 -0
  4. package/dist/cli/agents-md.js +226 -0
  5. package/dist/cli/agents-md.js.map +1 -0
  6. package/dist/cli/audit.d.ts +13 -0
  7. package/dist/cli/audit.d.ts.map +1 -0
  8. package/dist/cli/audit.js +90 -0
  9. package/dist/cli/audit.js.map +1 -0
  10. package/dist/cli/branch-protection.d.ts +57 -0
  11. package/dist/cli/branch-protection.d.ts.map +1 -0
  12. package/dist/cli/branch-protection.js +118 -0
  13. package/dist/cli/branch-protection.js.map +1 -0
  14. package/dist/cli/edit-workflow.d.ts +18 -0
  15. package/dist/cli/edit-workflow.d.ts.map +1 -0
  16. package/dist/cli/edit-workflow.js +43 -0
  17. package/dist/cli/edit-workflow.js.map +1 -0
  18. package/dist/cli/index.d.ts +8 -0
  19. package/dist/cli/index.d.ts.map +1 -0
  20. package/dist/cli/index.js +18 -0
  21. package/dist/cli/index.js.map +1 -0
  22. package/dist/cli/main.d.ts +3 -0
  23. package/dist/cli/main.d.ts.map +1 -0
  24. package/dist/cli/main.js +1336 -0
  25. package/dist/cli/main.js.map +1 -0
  26. package/dist/cli/skill-usage.d.ts +109 -0
  27. package/dist/cli/skill-usage.d.ts.map +1 -0
  28. package/dist/cli/skill-usage.js +380 -0
  29. package/dist/cli/skill-usage.js.map +1 -0
  30. package/dist/cli/skills.d.ts +56 -0
  31. package/dist/cli/skills.d.ts.map +1 -0
  32. package/dist/cli/skills.js +292 -0
  33. package/dist/cli/skills.js.map +1 -0
  34. package/dist/cli/update.d.ts +29 -0
  35. package/dist/cli/update.d.ts.map +1 -0
  36. package/dist/cli/update.js +186 -0
  37. package/dist/cli/update.js.map +1 -0
  38. package/dist/cli/usage.d.ts +142 -0
  39. package/dist/cli/usage.d.ts.map +1 -0
  40. package/dist/cli/usage.js +348 -0
  41. package/dist/cli/usage.js.map +1 -0
  42. package/dist/core/audit.d.ts +8 -0
  43. package/dist/core/audit.d.ts.map +1 -0
  44. package/dist/core/audit.js +47 -0
  45. package/dist/core/audit.js.map +1 -0
  46. package/dist/core/detect.d.ts +77 -0
  47. package/dist/core/detect.d.ts.map +1 -0
  48. package/dist/core/detect.js +262 -0
  49. package/dist/core/detect.js.map +1 -0
  50. package/dist/core/index.d.ts +8 -0
  51. package/dist/core/index.d.ts.map +1 -0
  52. package/dist/core/index.js +14 -0
  53. package/dist/core/index.js.map +1 -0
  54. package/dist/core/prompts.d.ts +9 -0
  55. package/dist/core/prompts.d.ts.map +1 -0
  56. package/dist/core/prompts.js +401 -0
  57. package/dist/core/prompts.js.map +1 -0
  58. package/dist/core/render-review.d.ts +6 -0
  59. package/dist/core/render-review.d.ts.map +1 -0
  60. package/dist/core/render-review.js +219 -0
  61. package/dist/core/render-review.js.map +1 -0
  62. package/dist/core/render.d.ts +13 -0
  63. package/dist/core/render.d.ts.map +1 -0
  64. package/dist/core/render.js +80 -0
  65. package/dist/core/render.js.map +1 -0
  66. package/dist/core/review-schema.d.ts +42 -0
  67. package/dist/core/review-schema.d.ts.map +1 -0
  68. package/dist/core/review-schema.js +156 -0
  69. package/dist/core/review-schema.js.map +1 -0
  70. package/dist/core/skills.d.ts +80 -0
  71. package/dist/core/skills.d.ts.map +1 -0
  72. package/dist/core/skills.js +510 -0
  73. package/dist/core/skills.js.map +1 -0
  74. package/package.json +27 -4
  75. package/{lib/agents-md.js → src/cli/agents-md.ts} +25 -14
  76. package/{lib/audit.js → src/cli/audit.ts} +37 -44
  77. package/{lib/branch-protection.js → src/cli/branch-protection.ts} +75 -11
  78. package/{lib/edit-workflow.js → src/cli/edit-workflow.ts} +32 -11
  79. package/src/cli/index.ts +101 -0
  80. package/src/cli/main.ts +1376 -0
  81. package/{lib/skill-usage.js → src/cli/skill-usage.ts} +168 -94
  82. package/src/cli/skills.ts +386 -0
  83. package/{lib/update.js → src/cli/update.ts} +68 -27
  84. package/{lib/usage.js → src/cli/usage.ts} +167 -76
  85. package/src/core/audit.ts +53 -0
  86. package/{lib/detect.js → src/core/detect.ts} +100 -47
  87. package/src/core/index.ts +70 -0
  88. package/{lib/prompts.js → src/core/prompts.ts} +16 -2
  89. package/{lib/render-review.js → src/core/render-review.ts} +57 -25
  90. package/{lib/render.js → src/core/render.ts} +36 -10
  91. package/{lib/review-schema.js → src/core/review-schema.ts} +68 -5
  92. package/{lib/skills.js → src/core/skills.ts} +172 -343
  93. package/templates/workflow-py.yml.tmpl +2 -2
  94. package/templates/workflow-ts.yml.tmpl +2 -2
  95. package/templates/workflow.yml.tmpl +17 -8
@@ -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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"}
@@ -0,0 +1,292 @@
1
+ // CLI skill helpers — install/update commands that touch the filesystem.
2
+ //
3
+ // Split from lib/skills.js during the v0.7.0 TS migration. Pure helpers
4
+ // (SkillsClient, rankAndCap, partition/extract/select functions) live in
5
+ // src/core/skills.ts so the App can consume them without dragging
6
+ // node:fs into a serverless bundle.
7
+ //
8
+ // `_internal` debug-export removed: `sanitizeSlug`, `entryKey`,
9
+ // `MANIFEST_FILE` (the CLI-side pieces previously hidden under
10
+ // `_internal.X`) are now first-class named exports of this module.
11
+ import { mkdir, writeFile, readdir, readFile, rm, stat } from 'node:fs/promises';
12
+ import { join } from 'node:path';
13
+ import { homedir } from 'node:os';
14
+ import { createHash } from 'node:crypto';
15
+ export const MANIFEST_FILE = '.clud-bug.json';
16
+ export const MANIFEST_VERSION = 1;
17
+ // Canonical home for clud-bug's baseline skills.
18
+ // PINNED TO A COMMIT SHA, NOT `main`. This re-couples the trust boundary
19
+ // to clud-bug releases: a compromised commit on agent-skills@main cannot
20
+ // silently land in users' Claude review skills mid-cycle. To roll new
21
+ // skill content, bump BASELINE_SKILLS_REF below in the same clud-bug PR
22
+ // that ships the corresponding bundled fallback update.
23
+ // See thrillmade/agent-skills — skills.sh `skills/<name>/SKILL.md` layout.
24
+ const BASELINE_SKILLS_REF = '436963ed37cbd9c6a9b7a07e907d5a0a432fab59';
25
+ const AGENT_SKILLS_BASE = process.env['CLUD_BUG_AGENT_SKILLS_BASE'] ??
26
+ `https://raw.githubusercontent.com/thrillmade/agent-skills/${BASELINE_SKILLS_REF}/skills`;
27
+ const SKILL_FETCH_TIMEOUT_MS = 5000;
28
+ const SKILL_CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24h
29
+ export function sanitizeSlug(name) {
30
+ return name.toLowerCase().replace(/[^a-z0-9-]+/g, '-').replace(/^-+|-+$/g, '');
31
+ }
32
+ export function entryKey(entry) {
33
+ // Baseline skills have no source; key by slug. Remote skills key by source/name.
34
+ return entry.kind === 'baseline'
35
+ ? `baseline:${entry.slug}`
36
+ : `${entry.source}/${entry.name || entry.slug}`;
37
+ }
38
+ // Loads the baseline skills, preferring the pinned thrillmade/agent-skills
39
+ // commit and falling back to the bundled npm-package copy on any fetch failure.
40
+ // Returns the same shape as before, plus a `_source` of either 'agent-skills'
41
+ // or 'bundled' so the CLI can report which path was used.
42
+ //
43
+ // Options:
44
+ // - fetch — injectable for tests (defaults to globalThis.fetch)
45
+ // - cacheDir — where to cache fetched SKILL.md files (defaults to
46
+ // ~/.cache/clud-bug/skills/, skipped if null)
47
+ export async function loadBaseline(baselineDir, opts = {}) {
48
+ const fetchImpl = opts.fetch ?? globalThis.fetch;
49
+ const cacheDir = opts.cacheDir === null ? null : (opts.cacheDir ?? join(homedir(), '.cache', 'clud-bug', 'skills'));
50
+ // First, enumerate the bundled baseline skills (source of truth for which
51
+ // names exist). Then fetch each in parallel — sequential awaits would
52
+ // stack timeouts (3 baselines × 5s = 15s before fallback when offline).
53
+ const bundled = await readBundled(baselineDir);
54
+ const remotes = await Promise.all(bundled.map((s) => tryFetchSkill(s.name, fetchImpl, cacheDir)));
55
+ return bundled.map((skill, i) => {
56
+ const remote = remotes[i];
57
+ return remote
58
+ ? { ...skill, content: remote, _source: 'agent-skills' }
59
+ : { ...skill, _source: 'bundled' };
60
+ });
61
+ }
62
+ // Reads the bundled baseline from the npm-package directory.
63
+ async function readBundled(baselineDir) {
64
+ const skills = [];
65
+ let entries;
66
+ try {
67
+ entries = await readdir(baselineDir, { withFileTypes: true });
68
+ }
69
+ catch {
70
+ return skills;
71
+ }
72
+ for (const entry of entries) {
73
+ if (!entry.isFile() || !entry.name.endsWith('.md'))
74
+ continue;
75
+ const content = await readFile(join(baselineDir, entry.name), 'utf8');
76
+ skills.push({
77
+ source: 'clud-bug-baseline',
78
+ name: entry.name.replace(/\.md$/, ''),
79
+ description: '(baseline)',
80
+ installs: 0,
81
+ kind: 'baseline',
82
+ content,
83
+ });
84
+ }
85
+ return skills;
86
+ }
87
+ // Try to read from cache, then fall back to network. Returns the SKILL.md
88
+ // content string on success, null on any failure (caller falls back to bundled).
89
+ async function tryFetchSkill(name, fetchImpl, cacheDir) {
90
+ // Cache lookup first.
91
+ if (cacheDir) {
92
+ const cached = await readFromCache(cacheDir, name);
93
+ if (cached !== null)
94
+ return cached;
95
+ }
96
+ // Network fetch with timeout covering BOTH the connection AND the body
97
+ // read (clearTimeout in finally guarantees the timer doesn't keep the
98
+ // event loop alive for up to 5s past a failed CLI run).
99
+ const url = `${AGENT_SKILLS_BASE}/${encodeURIComponent(name)}/SKILL.md`;
100
+ const ctrl = new AbortController();
101
+ const timer = setTimeout(() => ctrl.abort(), SKILL_FETCH_TIMEOUT_MS);
102
+ try {
103
+ const res = await fetchImpl(url, { signal: ctrl.signal });
104
+ if (!res.ok)
105
+ return null;
106
+ const content = await res.text();
107
+ if (!content || !content.trim())
108
+ return null;
109
+ if (cacheDir)
110
+ await writeToCache(cacheDir, name, content);
111
+ return content;
112
+ }
113
+ catch {
114
+ return null;
115
+ }
116
+ finally {
117
+ clearTimeout(timer);
118
+ }
119
+ }
120
+ async function readFromCache(cacheDir, name) {
121
+ const path = cachePath(cacheDir, name);
122
+ try {
123
+ const st = await stat(path);
124
+ if (Date.now() - st.mtimeMs > SKILL_CACHE_TTL_MS)
125
+ return null;
126
+ return await readFile(path, 'utf8');
127
+ }
128
+ catch {
129
+ return null;
130
+ }
131
+ }
132
+ async function writeToCache(cacheDir, name, content) {
133
+ try {
134
+ await mkdir(cacheDir, { recursive: true });
135
+ await writeFile(cachePath(cacheDir, name), content);
136
+ }
137
+ catch {
138
+ // Cache write failures are non-fatal — we already have the content.
139
+ }
140
+ }
141
+ function cachePath(cacheDir, name) {
142
+ // Include AGENT_SKILLS_BASE in the hash so different upstream URLs (e.g.
143
+ // a fork via CLUD_BUG_AGENT_SKILLS_BASE, or a different pinned SHA after
144
+ // a clud-bug release) get different cache entries. Otherwise switching
145
+ // bases would silently return the previously-cached content from a
146
+ // different upstream — cross-base cache poisoning.
147
+ const hash = createHash('sha256')
148
+ .update(`${AGENT_SKILLS_BASE}\n${name}`)
149
+ .digest('hex')
150
+ .slice(0, 16);
151
+ return join(cacheDir, `${hash}.md`);
152
+ }
153
+ export async function writeSkills(targetDir, skills, client) {
154
+ await mkdir(targetDir, { recursive: true });
155
+ const written = [];
156
+ for (const skill of skills) {
157
+ const entry = await writeSkill(targetDir, skill, client);
158
+ written.push(entry);
159
+ }
160
+ await writeManifest(targetDir, mergeManifest(await readManifest(targetDir), written));
161
+ return written;
162
+ }
163
+ export async function writeSkill(targetDir, skill, client) {
164
+ await mkdir(targetDir, { recursive: true });
165
+ const slug = sanitizeSlug(skill.name);
166
+ const skillDir = join(targetDir, slug);
167
+ await mkdir(skillDir, { recursive: true });
168
+ const content = skill.content ?? (await client.getContent(skill.source, skill.name));
169
+ await writeFile(join(skillDir, 'SKILL.md'), content);
170
+ return {
171
+ slug,
172
+ name: skill.name,
173
+ source: skill.source,
174
+ kind: skill.kind || 'remote',
175
+ description: skill.description || '',
176
+ };
177
+ }
178
+ export async function readManifest(targetDir) {
179
+ try {
180
+ const text = await readFile(join(targetDir, MANIFEST_FILE), 'utf8');
181
+ const data = JSON.parse(text);
182
+ return {
183
+ ...data,
184
+ version: data.version || MANIFEST_VERSION,
185
+ installed: Array.isArray(data.installed) ? data.installed : [],
186
+ };
187
+ }
188
+ catch {
189
+ return { version: MANIFEST_VERSION, installed: [] };
190
+ }
191
+ }
192
+ export async function writeManifest(targetDir, manifest) {
193
+ await mkdir(targetDir, { recursive: true });
194
+ // Preserve any additional fields callers want to stamp (e.g. lastUpdate,
195
+ // lastUpdateVersion, pinVersion). Only `version` and `installed` are normalized.
196
+ const out = {
197
+ ...manifest,
198
+ version: manifest.version || MANIFEST_VERSION,
199
+ installed: manifest.installed || [],
200
+ };
201
+ await writeFile(join(targetDir, MANIFEST_FILE), JSON.stringify(out, null, 2) + '\n');
202
+ }
203
+ export function mergeManifest(existing, newEntries) {
204
+ const byKey = new Map();
205
+ for (const entry of existing.installed || []) {
206
+ byKey.set(entryKey(entry), entry);
207
+ }
208
+ for (const entry of newEntries) {
209
+ byKey.set(entryKey(entry), entry);
210
+ }
211
+ // Spread `existing` so caller-set fields (pinVersion, lastUpdate,
212
+ // lastUpdateVersion, etc.) survive merges performed by writeSkills /
213
+ // refresh / add. Only `installed` is rebuilt; everything else carries.
214
+ return { ...existing, version: MANIFEST_VERSION, installed: [...byKey.values()] };
215
+ }
216
+ export async function removeSkill(targetDir, slug) {
217
+ const manifest = await readManifest(targetDir);
218
+ const entry = manifest.installed.find((e) => e.slug === slug);
219
+ if (!entry) {
220
+ throw new Error(`'${slug}' is not in the clud-bug manifest. If it's a custom skill, delete it manually with: rm -rf .claude/skills/${slug}`);
221
+ }
222
+ await rm(join(targetDir, slug), { recursive: true, force: true });
223
+ manifest.installed = manifest.installed.filter((e) => e.slug !== slug);
224
+ await writeManifest(targetDir, manifest);
225
+ return entry;
226
+ }
227
+ export async function listInstalled(targetDir) {
228
+ const manifest = await readManifest(targetDir);
229
+ const managedSlugs = new Set(manifest.installed.map((e) => e.slug));
230
+ const groups = { baseline: [], remote: [], custom: [] };
231
+ for (const entry of manifest.installed) {
232
+ if (entry.kind === 'baseline') {
233
+ groups.baseline.push(entry);
234
+ }
235
+ else {
236
+ groups.remote.push(entry);
237
+ }
238
+ }
239
+ let entries;
240
+ try {
241
+ entries = await readdir(targetDir, { withFileTypes: true });
242
+ }
243
+ catch {
244
+ return groups;
245
+ }
246
+ for (const entry of entries) {
247
+ if (!entry.isDirectory())
248
+ continue;
249
+ if (managedSlugs.has(entry.name))
250
+ continue;
251
+ const skillFile = join(targetDir, entry.name, 'SKILL.md');
252
+ let description = '';
253
+ try {
254
+ const text = await readFile(skillFile, 'utf8');
255
+ const m = text.match(/^description:\s*(.+)$/m);
256
+ description = m?.[1]?.trim() || '';
257
+ }
258
+ catch {
259
+ continue; // not a skill dir
260
+ }
261
+ groups.custom.push({ slug: entry.name, kind: 'custom', description });
262
+ }
263
+ return groups;
264
+ }
265
+ // Diff a current manifest against a freshly-recommended skill set.
266
+ // Returns { add: [], remove: [], unchanged: [] }. Custom skills are never affected.
267
+ export function diffManifest(manifest, recommended) {
268
+ const recByKey = new Map(recommended.map((s) => [
269
+ s.kind === 'baseline' ? `baseline:${sanitizeSlug(s.name)}` : `${s.source}/${s.name}`,
270
+ s,
271
+ ]));
272
+ const installedByKey = new Map(manifest.installed.map((e) => [entryKey(e), e]));
273
+ const add = [];
274
+ const remove = [];
275
+ const unchanged = [];
276
+ for (const [key, skill] of recByKey) {
277
+ if (installedByKey.has(key)) {
278
+ unchanged.push(skill);
279
+ }
280
+ else {
281
+ add.push(skill);
282
+ }
283
+ }
284
+ for (const [key, entry] of installedByKey) {
285
+ if (entry.kind === 'baseline')
286
+ continue; // baseline always stays
287
+ if (!recByKey.has(key))
288
+ remove.push(entry);
289
+ }
290
+ return { add, remove, unchanged };
291
+ }
292
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/cli/skills.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { type LoadBaselineOptions } from './skills.js';
2
+ export interface RunUpdateOptions {
3
+ cwd: string;
4
+ templatesDir: string;
5
+ baselineDir: string;
6
+ ourVersion: string;
7
+ refreshRemote?: boolean | undefined;
8
+ loadBaselineOpts?: LoadBaselineOptions | undefined;
9
+ }
10
+ export interface UpdateChangeRecord {
11
+ path: string;
12
+ label: string;
13
+ from?: string | undefined;
14
+ to?: string | undefined;
15
+ }
16
+ export interface UpdateSkippedRecord {
17
+ path: string;
18
+ label: string;
19
+ reason: string;
20
+ }
21
+ export interface RunUpdateResult {
22
+ changed: UpdateChangeRecord[];
23
+ unchanged: UpdateChangeRecord[];
24
+ skipped?: UpdateSkippedRecord[];
25
+ ourVersion?: string;
26
+ missing?: 'init';
27
+ }
28
+ export declare function runUpdate(opts: RunUpdateOptions): Promise<RunUpdateResult>;
29
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/cli/update.ts"],"names":[],"mappings":"AAKA,OAAO,EAA6C,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAiBlG,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAEpC,gBAAgB,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;CACpD;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAChC,OAAO,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAGD,wBAAsB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAiGhF"}
@@ -0,0 +1,186 @@
1
+ import { readFile, writeFile, mkdir, stat, rm } from 'node:fs/promises';
2
+ import { join, dirname } from 'node:path';
3
+ import { renderFile, pickTemplate, templateLanguage } from '../core/render.js';
4
+ import { reviewPrompt } from '../core/prompts.js';
5
+ import { detect, buildDescriptionLine } from '../core/detect.js';
6
+ import { loadBaseline, readManifest, writeManifest } from './skills.js';
7
+ import { applyToRepo as applyAgentDocs } from './agents-md.js';
8
+ // Returns { changed, unchanged, skipped, ourVersion }.
9
+ export async function runUpdate(opts) {
10
+ const { cwd, templatesDir, baselineDir, ourVersion, refreshRemote = false, loadBaselineOpts } = opts;
11
+ if (!cwd || !templatesDir || !baselineDir || !ourVersion) {
12
+ throw new Error('runUpdate requires cwd, templatesDir, baselineDir, ourVersion');
13
+ }
14
+ const skillsDir = join(cwd, '.claude', 'skills');
15
+ const manifest = await readManifest(skillsDir);
16
+ if (manifest.installed.length === 0 && !(await pathExists(join(cwd, '.github/workflows/clud-bug-review.yml')))) {
17
+ return { changed: [], unchanged: [], missing: 'init' };
18
+ }
19
+ const changed = [];
20
+ const unchanged = [];
21
+ const skipped = [];
22
+ // 1. Re-render review workflow with the latest template.
23
+ const signals = await detect(cwd);
24
+ const tmplName = pickTemplate(signals.languages);
25
+ // REVIEW_SCHEMA + CCA_VERSION + CLUD_BUG_VERSION come from render.js DEFAULTS.
26
+ const newReview = await renderFile(join(templatesDir, tmplName), {
27
+ REVIEW_PROMPT: reviewPrompt({
28
+ projectDescription: buildDescriptionLine(signals),
29
+ language: templateLanguage(tmplName),
30
+ }),
31
+ });
32
+ await maybeRefreshVersioned(join(cwd, '.github/workflows/clud-bug-review.yml'), newReview, changed, unchanged, skipped, 'review workflow');
33
+ // 2. Re-render audit workflow if it's installed (init from v0.3+ ships it).
34
+ // Routed through renderFile (was raw readFile pre-v0.5.11) so
35
+ // {{CCA_VERSION}} substitution lands in audit alongside review.
36
+ const auditPath = join(cwd, '.github/workflows/clud-bug-audit.yml');
37
+ if (await pathExists(auditPath)) {
38
+ const newAudit = await renderFile(join(templatesDir, 'audit.yml.tmpl'), {});
39
+ await maybeRefreshVersioned(auditPath, newAudit, changed, unchanged, skipped, 'audit workflow');
40
+ }
41
+ // 2b. Re-render self-update workflow if installed (init from v0.4+ ships it).
42
+ // Routed through renderFile for parity — no CCA ref in self-update today
43
+ // but future tokens should propagate uniformly without another refactor.
44
+ const selfUpdatePath = join(cwd, '.github/workflows/clud-bug-self-update.yml');
45
+ if (await pathExists(selfUpdatePath)) {
46
+ const newSelfUpdate = await renderFile(join(templatesDir, 'self-update.yml.tmpl'), {});
47
+ await maybeRefreshVersioned(selfUpdatePath, newSelfUpdate, changed, unchanged, skipped, 'self-update workflow');
48
+ }
49
+ // 3. Refresh baseline skills (always controlled by clud-bug).
50
+ // Slugs listed in manifest.excludedBaselines are skipped AND their
51
+ // existing .claude/skills/<slug>/ dir is removed if present, so a repo
52
+ // that opts out of a baseline doesn't end up regenerating it on every
53
+ // update (the original symptom this field exists to fix).
54
+ const excludedRaw = manifest['excludedBaselines'];
55
+ const excluded = new Set(Array.isArray(excludedRaw) ? excludedRaw : []);
56
+ const baseline = await loadBaseline(baselineDir, loadBaselineOpts);
57
+ for (const skill of baseline) {
58
+ const slug = sanitize(skill.name);
59
+ if (excluded.has(skill.name) || excluded.has(slug)) {
60
+ const skillDir = join(skillsDir, slug);
61
+ if (await pathExists(skillDir)) {
62
+ await rm(skillDir, { recursive: true, force: true });
63
+ changed.push({ path: skillDir, label: `excluded baseline ${skill.name}: removed` });
64
+ }
65
+ continue;
66
+ }
67
+ const skillPath = join(skillsDir, slug, 'SKILL.md');
68
+ await maybeWrite(skillPath, skill.content, changed, unchanged, `baseline ${skill.name}`);
69
+ }
70
+ // 4. Optionally refresh remote skills (off by default).
71
+ // Custom skills are never touched.
72
+ // (Remote refresh is intentionally minimal here — `clud-bug refresh`
73
+ // already covers add/remove diffs against skills.sh.)
74
+ if (refreshRemote) {
75
+ // Placeholder for parity with the flag; full logic remains in
76
+ // `clud-bug refresh`. We just emit an advisory.
77
+ }
78
+ // 5. Refresh the AGENTS.md / CLAUDE.md clud-bug block. The block embeds
79
+ // the version + strict-mode state, so an update with a new version
80
+ // rewrites it. Files that don't already exist (other than AGENTS.md)
81
+ // are left alone, so this never silently creates instruction stubs.
82
+ // `=== true` mirrors the workflow's gate predicate at
83
+ // templates/workflow*.yml.tmpl. A v0.3 advisory manifest (strictMode
84
+ // undefined, lastUpdate set) renders "off" — matching the gate, not the
85
+ // default-on behavior of fresh v0.4+ installs.
86
+ const agentDocs = await applyAgentDocs(cwd, {
87
+ version: ourVersion,
88
+ strictMode: manifest['strictMode'] === true,
89
+ });
90
+ for (const p of agentDocs.created)
91
+ changed.push({ path: join(cwd, p), label: `agent docs: created ${p}` });
92
+ for (const p of agentDocs.touched)
93
+ changed.push({ path: join(cwd, p), label: `agent docs: ${p}` });
94
+ // 6. Stamp the manifest with the version that ran the update.
95
+ manifest['lastUpdate'] = new Date().toISOString();
96
+ manifest['lastUpdateVersion'] = ourVersion;
97
+ await writeManifest(skillsDir, manifest);
98
+ return { changed, unchanged, skipped, ourVersion };
99
+ }
100
+ async function maybeWrite(path, contents, changed, unchanged, label) {
101
+ const prior = await readSafe(path);
102
+ if (prior === contents) {
103
+ unchanged.push({ path, label });
104
+ return;
105
+ }
106
+ await mkdir(dirname(path), { recursive: true });
107
+ await writeFile(path, contents);
108
+ changed.push({ path, label });
109
+ }
110
+ // Refresh a versioned template (one that carries `# clud-bug-template-version:`
111
+ // on line 1). If the installed file lacks that marker, treat it as
112
+ // user-customized and leave it alone — recovery path is delete + `clud-bug init`.
113
+ // Mirrors logmind v0.2.1's refresh-mode contract.
114
+ async function maybeRefreshVersioned(path, contents, changed, unchanged, skipped, label) {
115
+ const tmplVersion = extractTemplateVersion(contents);
116
+ if (!tmplVersion) {
117
+ // Defensive: every versioned template is supposed to carry a marker.
118
+ // Falling back to byte-compare write here would silently mass-overwrite
119
+ // every installed file (including marker-bearing ones) the moment a
120
+ // future template regressed — the inverse of the protection contract
121
+ // this function exists to enforce. Throw so the regression surfaces
122
+ // in CI instead.
123
+ throw new Error(`Template for ${label} has no # clud-bug-template-version marker — refusing to refresh (templates must declare a marker so refresh-mode can reason about ownership).`);
124
+ }
125
+ const prior = await readSafe(path);
126
+ if (prior === null) {
127
+ // First time writing here; nothing to preserve.
128
+ await mkdir(dirname(path), { recursive: true });
129
+ await writeFile(path, contents);
130
+ changed.push({ path, label });
131
+ return;
132
+ }
133
+ const priorVersion = extractTemplateVersion(prior);
134
+ if (priorVersion === null) {
135
+ // Markerless installed file = customized. Preserve and warn.
136
+ skipped.push({
137
+ path,
138
+ label,
139
+ reason: 'markerless (user-customized); delete the file + run `clud-bug init` to refresh',
140
+ });
141
+ return;
142
+ }
143
+ if (prior === contents) {
144
+ unchanged.push({ path, label });
145
+ return;
146
+ }
147
+ // Marker present (current or stale) AND content drifted: refresh.
148
+ await mkdir(dirname(path), { recursive: true });
149
+ await writeFile(path, contents);
150
+ changed.push({ path, label, from: priorVersion, to: tmplVersion });
151
+ }
152
+ // Extract the template-version marker. Templates put it on line 1, but
153
+ // scan the first 5 lines so a leading blank or stray header doesn't hide it.
154
+ // Anchoring near the top means a stray `# clud-bug-template-version:` lower
155
+ // in the file (in a comment inside a heredoc, say) can't be mistaken for the
156
+ // authoritative marker. Returns null if not present.
157
+ function extractTemplateVersion(text) {
158
+ if (!text)
159
+ return null;
160
+ const head = text.split('\n', 5).join('\n');
161
+ const m = head.match(/^# clud-bug-template-version:\s*(\S+)/m);
162
+ // m[1] is `string | undefined` under noUncheckedIndexedAccess; coalesce
163
+ // to null to keep the return type tight.
164
+ return m ? (m[1] ?? null) : null;
165
+ }
166
+ async function readSafe(path) {
167
+ try {
168
+ return await readFile(path, 'utf8');
169
+ }
170
+ catch {
171
+ return null;
172
+ }
173
+ }
174
+ async function pathExists(path) {
175
+ try {
176
+ await stat(path);
177
+ return true;
178
+ }
179
+ catch {
180
+ return false;
181
+ }
182
+ }
183
+ function sanitize(name) {
184
+ return name.toLowerCase().replace(/[^a-z0-9-]+/g, '-').replace(/^-+|-+$/g, '');
185
+ }
186
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/cli/update.ts"],"names":[],"mappings":"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"}