clud-bug 0.7.0-rc.11 → 0.7.0-rc.13
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/dist/cli/hooks.d.ts +40 -0
- package/dist/cli/hooks.d.ts.map +1 -0
- package/dist/cli/hooks.js +105 -0
- package/dist/cli/hooks.js.map +1 -0
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +61 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/review-prompt.d.ts +28 -0
- package/dist/cli/review-prompt.d.ts.map +1 -0
- package/dist/cli/review-prompt.js +169 -0
- package/dist/cli/review-prompt.js.map +1 -0
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +22 -0
- package/dist/cli/update.js.map +1 -1
- package/dist/core/budget-plan.d.ts +125 -0
- package/dist/core/budget-plan.d.ts.map +1 -0
- package/dist/core/budget-plan.js +211 -0
- package/dist/core/budget-plan.js.map +1 -0
- package/dist/core/index.d.ts +5 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +14 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/multi-pass-aggregate.d.ts +131 -0
- package/dist/core/multi-pass-aggregate.d.ts.map +1 -0
- package/dist/core/multi-pass-aggregate.js +427 -0
- package/dist/core/multi-pass-aggregate.js.map +1 -0
- package/dist/core/plan-review.d.ts +57 -0
- package/dist/core/plan-review.d.ts.map +1 -0
- package/dist/core/plan-review.js +77 -0
- package/dist/core/plan-review.js.map +1 -0
- package/dist/core/review-plan.d.ts +219 -0
- package/dist/core/review-plan.d.ts.map +1 -0
- package/dist/core/review-plan.js +274 -0
- package/dist/core/review-plan.js.map +1 -0
- package/dist/core/review-writeback.d.ts +20 -0
- package/dist/core/review-writeback.d.ts.map +1 -1
- package/dist/core/review-writeback.js +16 -0
- package/dist/core/review-writeback.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/package.json +1 -1
- package/src/cli/hooks.ts +122 -0
- package/src/cli/main.ts +56 -0
- package/src/cli/review-prompt.ts +206 -0
- package/src/cli/update.ts +22 -0
- package/src/core/budget-plan.ts +324 -0
- package/src/core/index.ts +64 -0
- package/src/core/multi-pass-aggregate.ts +545 -0
- package/src/core/plan-review.ts +136 -0
- package/src/core/review-plan.ts +485 -0
- package/src/core/review-writeback.ts +38 -0
- package/src/core/version.ts +1 -1
- package/templates/workflow-py.yml.tmpl +1 -1
- package/templates/workflow-ts.yml.tmpl +1 -1
- package/templates/workflow.yml.tmpl +1 -1
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** Stable marker embedded in our hook's prompt so re-runs replace it in place. */
|
|
2
|
+
export declare const CLUD_BUG_HOOK_MARKER = "clud-bug-local-review";
|
|
3
|
+
/**
|
|
4
|
+
* Build the `prompt` of the Claude Code `type: agent` commit-review hook,
|
|
5
|
+
* pinned to the clud-bug VERSION that scaffolded it. Pinning matters: a bare
|
|
6
|
+
* `npx clud-bug` resolves to the `latest` dist-tag, which can predate the
|
|
7
|
+
* `review-prompt` verb (e.g. while v0.7 is prerelease on `next`); `@${version}`
|
|
8
|
+
* guarantees the verb exists. `clud-bug update` refreshes the pin in place.
|
|
9
|
+
*
|
|
10
|
+
* Rather than baking a static recipe (which would drift from the repo's
|
|
11
|
+
* skills/config), it tells the subagent to run `clud-bug review-prompt` — the
|
|
12
|
+
* engine-driven verb that emits a recipe tailored to THIS repo's resolved plan
|
|
13
|
+
* — and follow it. The recipe is generated fresh at commit time, always current.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildCommitReviewPrompt(version: string): string;
|
|
16
|
+
/** One Claude Code hook entry: a tool matcher plus its hook list. */
|
|
17
|
+
export interface HookMatcherEntry {
|
|
18
|
+
matcher?: string;
|
|
19
|
+
hooks: Array<Record<string, unknown>>;
|
|
20
|
+
}
|
|
21
|
+
/** Minimal shape of the `.claude/settings.json` we read + merge into. */
|
|
22
|
+
export interface ClaudeSettings {
|
|
23
|
+
hooks?: Record<string, HookMatcherEntry[]>;
|
|
24
|
+
[key: string]: unknown;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Builds the PostToolUse entry that spawns the commit-review subagent: a native
|
|
28
|
+
* `type: agent` hook that is backgrounded (`async`), surfaces findings
|
|
29
|
+
* (`asyncRewake`), and fires only on `git commit` (`if`).
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildLocalReviewHook(recipe: string): HookMatcherEntry;
|
|
32
|
+
/**
|
|
33
|
+
* Merges the clud-bug commit-review hook into an existing `.claude/settings.json`
|
|
34
|
+
* object. **Idempotent** (replaces any prior clud-bug entry rather than
|
|
35
|
+
* duplicating) and **non-clobbering** (preserves every other top-level key,
|
|
36
|
+
* every other event, and every other hook). Tolerates a missing/malformed
|
|
37
|
+
* `existing` value.
|
|
38
|
+
*/
|
|
39
|
+
export declare function mergeLocalReviewHook(existing: unknown, recipe: string): ClaudeSettings;
|
|
40
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/cli/hooks.ts"],"names":[],"mappings":"AAcA,kFAAkF;AAClF,eAAO,MAAM,oBAAoB,0BAA0B,CAAC;AAE5D;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAkB/D;AAED,qEAAqE;AACrE,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvC;AAED,yEAAyE;AACzE,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAC3C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAcrE;AAUD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,cAAc,CAwBtF"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// Wave 6b — Claude Code `type: agent` commit-review hook scaffolding.
|
|
2
|
+
//
|
|
3
|
+
// `clud-bug init --with-hooks` writes a native Claude Code hook that, on every
|
|
4
|
+
// `git commit` the agent makes, spawns a clud-bug review SUBAGENT in the same
|
|
5
|
+
// session — so it runs on the session's subscription (no API key), in the
|
|
6
|
+
// background (the commit never blocks), and surfaces findings back to the agent.
|
|
7
|
+
//
|
|
8
|
+
// The model (see the Wave 6b plan): clud-bug supplies the *recipe* (the
|
|
9
|
+
// agent-hook `prompt`); Claude Code runs it as a subagent. This is the dynamic,
|
|
10
|
+
// always-on counterpart to the `/clud-bug-review` slash command.
|
|
11
|
+
//
|
|
12
|
+
// `type: agent` hooks are documented as experimental; the same outcome is
|
|
13
|
+
// reachable via a `type: command` hook + `additionalContext` if the API shifts.
|
|
14
|
+
/** Stable marker embedded in our hook's prompt so re-runs replace it in place. */
|
|
15
|
+
export const CLUD_BUG_HOOK_MARKER = 'clud-bug-local-review';
|
|
16
|
+
/**
|
|
17
|
+
* Build the `prompt` of the Claude Code `type: agent` commit-review hook,
|
|
18
|
+
* pinned to the clud-bug VERSION that scaffolded it. Pinning matters: a bare
|
|
19
|
+
* `npx clud-bug` resolves to the `latest` dist-tag, which can predate the
|
|
20
|
+
* `review-prompt` verb (e.g. while v0.7 is prerelease on `next`); `@${version}`
|
|
21
|
+
* guarantees the verb exists. `clud-bug update` refreshes the pin in place.
|
|
22
|
+
*
|
|
23
|
+
* Rather than baking a static recipe (which would drift from the repo's
|
|
24
|
+
* skills/config), it tells the subagent to run `clud-bug review-prompt` — the
|
|
25
|
+
* engine-driven verb that emits a recipe tailored to THIS repo's resolved plan
|
|
26
|
+
* — and follow it. The recipe is generated fresh at commit time, always current.
|
|
27
|
+
*/
|
|
28
|
+
export function buildCommitReviewPrompt(version) {
|
|
29
|
+
return `<!-- ${CLUD_BUG_HOOK_MARKER} v1 -->
|
|
30
|
+
You are clud-bug's local commit review, running as a background subagent on this
|
|
31
|
+
session's own subscription (no extra auth — you have git, gh, and file access).
|
|
32
|
+
|
|
33
|
+
Step 1 — get your review recipe from clud-bug's engine:
|
|
34
|
+
|
|
35
|
+
npx clud-bug@${version} review-prompt --trigger commit
|
|
36
|
+
|
|
37
|
+
That prints a structured review recipe tailored to THIS repo's skills + config (a
|
|
38
|
+
fast single pass for a commit). If that command isn't available, run the repo's
|
|
39
|
+
installed clud-bug CLI's \`review-prompt --trigger commit\` instead.
|
|
40
|
+
|
|
41
|
+
Step 2 — follow that recipe exactly: review the commit that was just made against
|
|
42
|
+
the skills it names, and surface any findings back into the session so they can be
|
|
43
|
+
fixed. A clean commit needs only a one-line note.
|
|
44
|
+
|
|
45
|
+
Keep it tight — this is the commit-time safety net; the deeper review runs at PR time.`;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Builds the PostToolUse entry that spawns the commit-review subagent: a native
|
|
49
|
+
* `type: agent` hook that is backgrounded (`async`), surfaces findings
|
|
50
|
+
* (`asyncRewake`), and fires only on `git commit` (`if`).
|
|
51
|
+
*/
|
|
52
|
+
export function buildLocalReviewHook(recipe) {
|
|
53
|
+
return {
|
|
54
|
+
matcher: 'Bash',
|
|
55
|
+
hooks: [
|
|
56
|
+
{
|
|
57
|
+
type: 'agent',
|
|
58
|
+
if: 'Bash(git commit *)',
|
|
59
|
+
async: true,
|
|
60
|
+
asyncRewake: true,
|
|
61
|
+
timeout: 180,
|
|
62
|
+
prompt: recipe,
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function isOurHook(h) {
|
|
68
|
+
return typeof h?.['prompt'] === 'string' && h['prompt'].includes(CLUD_BUG_HOOK_MARKER);
|
|
69
|
+
}
|
|
70
|
+
function isCludBugReviewEntry(entry) {
|
|
71
|
+
return !!entry && Array.isArray(entry.hooks) && entry.hooks.some(isOurHook);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Merges the clud-bug commit-review hook into an existing `.claude/settings.json`
|
|
75
|
+
* object. **Idempotent** (replaces any prior clud-bug entry rather than
|
|
76
|
+
* duplicating) and **non-clobbering** (preserves every other top-level key,
|
|
77
|
+
* every other event, and every other hook). Tolerates a missing/malformed
|
|
78
|
+
* `existing` value.
|
|
79
|
+
*/
|
|
80
|
+
export function mergeLocalReviewHook(existing, recipe) {
|
|
81
|
+
const base = existing && typeof existing === 'object' ? { ...existing } : {};
|
|
82
|
+
const hooks = { ...(base.hooks ?? {}) };
|
|
83
|
+
const priorPost = Array.isArray(hooks.PostToolUse) ? hooks.PostToolUse : [];
|
|
84
|
+
// Preserve every non-clud-bug hook — including any the user co-located INSIDE
|
|
85
|
+
// our own matcher entry: drop only the hook(s) carrying our marker, never the
|
|
86
|
+
// whole entry.
|
|
87
|
+
const ours = buildLocalReviewHook(recipe);
|
|
88
|
+
const otherEntries = [];
|
|
89
|
+
const coLocatedUserHooks = [];
|
|
90
|
+
for (const entry of priorPost) {
|
|
91
|
+
if (isCludBugReviewEntry(entry)) {
|
|
92
|
+
for (const h of entry.hooks)
|
|
93
|
+
if (!isOurHook(h))
|
|
94
|
+
coLocatedUserHooks.push(h);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
otherEntries.push(entry);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const ourEntry = coLocatedUserHooks.length > 0 ? { ...ours, hooks: [...coLocatedUserHooks, ...ours.hooks] } : ours;
|
|
101
|
+
hooks.PostToolUse = [...otherEntries, ourEntry];
|
|
102
|
+
base.hooks = hooks;
|
|
103
|
+
return base;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/cli/hooks.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,EAAE;AACF,+EAA+E;AAC/E,8EAA8E;AAC9E,0EAA0E;AAC1E,iFAAiF;AACjF,EAAE;AACF,wEAAwE;AACxE,gFAAgF;AAChF,iEAAiE;AACjE,EAAE;AACF,0EAA0E;AAC1E,gFAAgF;AAEhF,kFAAkF;AAClF,MAAM,CAAC,MAAM,oBAAoB,GAAG,uBAAuB,CAAC;AAE5D;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAAe;IACrD,OAAO,QAAQ,oBAAoB;;;;;;mBAMlB,OAAO;;;;;;;;;;uFAU6D,CAAC;AACxF,CAAC;AAcD;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAc;IACjD,OAAO;QACL,OAAO,EAAE,MAAM;QACf,KAAK,EAAE;YACL;gBACE,IAAI,EAAE,OAAO;gBACb,EAAE,EAAE,oBAAoB;gBACxB,KAAK,EAAE,IAAI;gBACX,WAAW,EAAE,IAAI;gBACjB,OAAO,EAAE,GAAG;gBACZ,MAAM,EAAE,MAAM;aACf;SACF;KACF,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,CAAsC;IACvD,OAAO,OAAO,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,QAAQ,IAAK,CAAC,CAAC,QAAQ,CAAY,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;AACrG,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAmC;IAC/D,OAAO,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAiB,EAAE,MAAc;IACpE,MAAM,IAAI,GACR,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAI,QAA2B,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACtF,MAAM,KAAK,GAAuC,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;IAC5E,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IAE5E,8EAA8E;IAC9E,8EAA8E;IAC9E,eAAe;IACf,MAAM,IAAI,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAuB,EAAE,CAAC;IAC5C,MAAM,kBAAkB,GAAmC,EAAE,CAAC;IAC9D,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;QAC9B,IAAI,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,KAAK;gBAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;oBAAE,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC7E,CAAC;aAAM,CAAC;YACN,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,MAAM,QAAQ,GACZ,kBAAkB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,CAAC,GAAG,kBAAkB,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACpG,KAAK,CAAC,WAAW,GAAG,CAAC,GAAG,YAAY,EAAE,QAAQ,CAAC,CAAC;IAChD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACnB,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/cli/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"AAmPA,iBAAe,IAAI,kBA6BlB;AAm8DD,OAAO,EAAE,IAAI,EAAE,CAAC"}
|
package/dist/cli/main.js
CHANGED
|
@@ -26,6 +26,7 @@ import { writeSkills, writeSkill, loadBaseline, readManifest, writeManifest, rem
|
|
|
26
26
|
import { computeAuditFileSet } from './audit.js';
|
|
27
27
|
import { renderAuditHeader } from '../core/audit.js';
|
|
28
28
|
import { runUpdate } from './update.js';
|
|
29
|
+
import { runReviewPrompt } from './review-prompt.js';
|
|
29
30
|
import { getPendingWorkflowEdits, makeBranchName, git as gitCmd } from './edit-workflow.js';
|
|
30
31
|
import { applyToRepo as applyAgentDocs } from './agents-md.js';
|
|
31
32
|
import { detectRepo, detectDefaultBranch, getProtectionState, enableConversationResolution } from './branch-protection.js';
|
|
@@ -59,6 +60,7 @@ function parseArgs(argv) {
|
|
|
59
60
|
// .claude/commands/clud-bug-review.md so `/clud-bug-review` works in a
|
|
60
61
|
// Claude Code session (reviews the current PR with the session's tokens).
|
|
61
62
|
withLocalReview: false,
|
|
63
|
+
withHooks: false,
|
|
62
64
|
// v0.7.0-rc.4: `clud-bug configure-github` flags.
|
|
63
65
|
// --dry-run prints the diff but skips PATCH; --branch overrides "main".
|
|
64
66
|
dryRun: false,
|
|
@@ -106,10 +108,16 @@ function parseArgs(argv) {
|
|
|
106
108
|
args.withSkdd = true;
|
|
107
109
|
else if (a === '--with-local-review')
|
|
108
110
|
args.withLocalReview = true;
|
|
111
|
+
else if (a === '--with-hooks')
|
|
112
|
+
args.withHooks = true;
|
|
109
113
|
else if (a === '--dry-run')
|
|
110
114
|
args.dryRun = true;
|
|
111
115
|
else if (a === '--branch')
|
|
112
116
|
args.branch = argv[++i];
|
|
117
|
+
else if (a === '--trigger')
|
|
118
|
+
args.trigger = argv[++i];
|
|
119
|
+
else if (a === '--diff-size')
|
|
120
|
+
args.diffSizeBytes = Number(argv[++i]);
|
|
113
121
|
else
|
|
114
122
|
args._.push(a);
|
|
115
123
|
}
|
|
@@ -200,6 +208,11 @@ Commands:
|
|
|
200
208
|
Required env vars: GH_TOKEN, ANTHROPIC_API_KEY,
|
|
201
209
|
REPO ("owner/name"), PR_NUMBER. Output: JSON
|
|
202
210
|
\`{actions, verifierCallCount, shouldRequestChanges}\`.
|
|
211
|
+
review-prompt Emit the local-review recipe — the structured prompt a
|
|
212
|
+
Claude Code agent/hook runs to review the current diff on
|
|
213
|
+
the session's own subscription. Plans via the shared
|
|
214
|
+
engine: --trigger commit (default) → a fast single pass;
|
|
215
|
+
push/pr → the full multi-pass plan. Prints to stdout.
|
|
203
216
|
|
|
204
217
|
Options:
|
|
205
218
|
--offline Skip skills.sh; pin only the bundled baseline specimens.
|
|
@@ -209,6 +222,11 @@ Options:
|
|
|
209
222
|
\`/clud-bug-review\` works in a Claude Code session —
|
|
210
223
|
reviews the current branch's PR using that session's
|
|
211
224
|
own tokens (no hosted App, no extra auth).
|
|
225
|
+
--with-hooks (init) Also scaffold a native Claude Code \`type: agent\`
|
|
226
|
+
commit-review hook into .claude/settings.json — on every
|
|
227
|
+
\`git commit\` the agent makes, a backgrounded clud-bug
|
|
228
|
+
review subagent runs on the session's subscription.
|
|
229
|
+
Implies --with-local-review. Off by default.
|
|
212
230
|
--quiet,-q Token-frugal mode for agent invocations. Suppresses
|
|
213
231
|
progress chatter; emits exactly one final
|
|
214
232
|
\`ok <key-value>\` summary line per command. Errors
|
|
@@ -221,6 +239,7 @@ Options:
|
|
|
221
239
|
--dry-run Print the canonical-v1 diff without PATCH-ing
|
|
222
240
|
(configure-github only).
|
|
223
241
|
--branch <name> Target branch for configure-github (default: main).
|
|
242
|
+
--trigger <ctx> review-prompt context: commit (default) | push | pr.
|
|
224
243
|
--repo <owner/name> Restrict \`usage\` to a single repo. Default: all repos
|
|
225
244
|
with clud-bug-review.yml in the gh user's auth scope.
|
|
226
245
|
--pr <N> Restrict \`usage\` to a single PR.
|
|
@@ -268,6 +287,7 @@ async function main() {
|
|
|
268
287
|
case 'select-review-event': return runSelectReviewEvent(args);
|
|
269
288
|
case 'post-inline-threads': return runPostInlineThreads(args);
|
|
270
289
|
case 'resolve-threads': return runResolveThreads(args);
|
|
290
|
+
case 'review-prompt': return runReviewPrompt(args);
|
|
271
291
|
default:
|
|
272
292
|
process.stderr.write(`Unknown command: ${cmd || '(none)'}\n\n${HELP}`);
|
|
273
293
|
process.exit(2);
|
|
@@ -1147,6 +1167,11 @@ async function runInit(args) {
|
|
|
1147
1167
|
// Claude Code session — the agent reviews the current branch's open PR using
|
|
1148
1168
|
// THAT session's own tokens (Max or API), no hosted App or new auth required.
|
|
1149
1169
|
// `.claude/` is already in the --commit add-list below, so it's staged too.
|
|
1170
|
+
// `--with-hooks` implies `--with-local-review` — the auto hook and the manual
|
|
1171
|
+
// `/clud-bug-review` command are complementary (the hook auto-runs the engine
|
|
1172
|
+
// recipe on each commit; the command runs it on demand against the PR).
|
|
1173
|
+
if (args.withHooks)
|
|
1174
|
+
args.withLocalReview = true;
|
|
1150
1175
|
if (args.withLocalReview) {
|
|
1151
1176
|
const commandPath = join(cwd, '.claude', 'commands', 'clud-bug-review.md');
|
|
1152
1177
|
await mkdir(dirname(commandPath), { recursive: true });
|
|
@@ -1154,6 +1179,42 @@ async function runInit(args) {
|
|
|
1154
1179
|
await writeFile(commandPath, commandContent);
|
|
1155
1180
|
log(` wrote ${rel(cwd, commandPath)}`);
|
|
1156
1181
|
}
|
|
1182
|
+
// v0.7.0 (Wave 6b): optional native commit-review hook. Merges a Claude Code
|
|
1183
|
+
// `type: agent` PostToolUse hook into `.claude/settings.json` (preserving any
|
|
1184
|
+
// existing settings + hooks) that, on every `git commit` the agent makes,
|
|
1185
|
+
// spawns a clud-bug review subagent on the session's subscription, in the
|
|
1186
|
+
// background — the hook's prompt runs `clud-bug review-prompt` and follows it.
|
|
1187
|
+
if (args.withHooks) {
|
|
1188
|
+
const { mergeLocalReviewHook, buildCommitReviewPrompt } = await import('./hooks.js');
|
|
1189
|
+
const hookPrompt = buildCommitReviewPrompt(await readPkgVersion());
|
|
1190
|
+
const settingsPath = join(cwd, '.claude', 'settings.json');
|
|
1191
|
+
await mkdir(dirname(settingsPath), { recursive: true });
|
|
1192
|
+
// Read-then-parse so we can tell "no file yet" (fresh merge) from "file
|
|
1193
|
+
// exists but is invalid JSON" (leave it ALONE — never clobber user content).
|
|
1194
|
+
let raw;
|
|
1195
|
+
try {
|
|
1196
|
+
raw = await readFile(settingsPath, 'utf8');
|
|
1197
|
+
}
|
|
1198
|
+
catch {
|
|
1199
|
+
raw = undefined; // no settings.json yet → fresh
|
|
1200
|
+
}
|
|
1201
|
+
let existing;
|
|
1202
|
+
let proceed = true;
|
|
1203
|
+
if (raw !== undefined) {
|
|
1204
|
+
try {
|
|
1205
|
+
existing = JSON.parse(raw);
|
|
1206
|
+
}
|
|
1207
|
+
catch {
|
|
1208
|
+
proceed = false;
|
|
1209
|
+
log(` skipped ${rel(cwd, settingsPath)} (existing file is not valid JSON; left untouched)`);
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
if (proceed) {
|
|
1213
|
+
const merged = mergeLocalReviewHook(existing, hookPrompt);
|
|
1214
|
+
await writeFile(settingsPath, JSON.stringify(merged, null, 2) + '\n');
|
|
1215
|
+
log(` wrote ${rel(cwd, settingsPath)} (commit-review hook)`);
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1157
1218
|
// Stamp the manifest. Sets strictMode: true ONLY on fresh installs —
|
|
1158
1219
|
// a manifest that's never been touched by clud-bug init/update has no
|
|
1159
1220
|
// lastUpdate field. Existing v0.3.x advisory installs (where strictMode
|