@ironbee-ai/cli 0.3.0 → 0.4.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.
- package/CHANGELOG.md +19 -8
- package/README.md +163 -3
- package/dist/analysis/code-changes.d.ts +22 -0
- package/dist/analysis/code-changes.d.ts.map +1 -0
- package/dist/analysis/code-changes.js +141 -0
- package/dist/analysis/code-changes.js.map +1 -0
- package/dist/analysis/cross-session.d.ts +34 -0
- package/dist/analysis/cross-session.d.ts.map +1 -0
- package/dist/analysis/cross-session.js +230 -0
- package/dist/analysis/cross-session.js.map +1 -0
- package/dist/analysis/fix-effectiveness.d.ts +16 -0
- package/dist/analysis/fix-effectiveness.d.ts.map +1 -0
- package/dist/analysis/fix-effectiveness.js +99 -0
- package/dist/analysis/fix-effectiveness.js.map +1 -0
- package/dist/analysis/scoring.d.ts +15 -0
- package/dist/analysis/scoring.d.ts.map +1 -0
- package/dist/analysis/scoring.js +57 -0
- package/dist/analysis/scoring.js.map +1 -0
- package/dist/analysis/time-analysis.d.ts +22 -0
- package/dist/analysis/time-analysis.d.ts.map +1 -0
- package/dist/analysis/time-analysis.js +174 -0
- package/dist/analysis/time-analysis.js.map +1 -0
- package/dist/analysis/verdict-details.d.ts +23 -0
- package/dist/analysis/verdict-details.d.ts.map +1 -0
- package/dist/analysis/verdict-details.js +59 -0
- package/dist/analysis/verdict-details.js.map +1 -0
- package/dist/analysis/verification-quality.d.ts +19 -0
- package/dist/analysis/verification-quality.d.ts.map +1 -0
- package/dist/analysis/verification-quality.js +182 -0
- package/dist/analysis/verification-quality.js.map +1 -0
- package/dist/clients/base.d.ts +2 -0
- package/dist/clients/base.d.ts.map +1 -1
- package/dist/clients/claude/commands/ironbee-analyze.md +42 -0
- package/dist/clients/claude/commands/ironbee-verify.md +127 -0
- package/dist/clients/claude/hooks/clear-verdict.js +1 -1
- package/dist/clients/claude/hooks/clear-verdict.js.map +1 -1
- package/dist/clients/claude/hooks/require-verification.d.ts +15 -0
- package/dist/clients/claude/hooks/require-verification.d.ts.map +1 -0
- package/dist/clients/claude/hooks/require-verification.js +63 -0
- package/dist/clients/claude/hooks/require-verification.js.map +1 -0
- package/dist/clients/claude/hooks/session-start.d.ts.map +1 -1
- package/dist/clients/claude/hooks/session-start.js +7 -0
- package/dist/clients/claude/hooks/session-start.js.map +1 -1
- package/dist/clients/claude/hooks/track-action.d.ts +1 -1
- package/dist/clients/claude/hooks/track-action.d.ts.map +1 -1
- package/dist/clients/claude/hooks/track-action.js +58 -13
- package/dist/clients/claude/hooks/track-action.js.map +1 -1
- package/dist/clients/claude/hooks/verify-gate.js +1 -1
- package/dist/clients/claude/hooks/verify-gate.js.map +1 -1
- package/dist/clients/claude/index.d.ts +2 -0
- package/dist/clients/claude/index.d.ts.map +1 -1
- package/dist/clients/claude/index.js +51 -19
- package/dist/clients/claude/index.js.map +1 -1
- package/dist/clients/claude/rule.md +10 -7
- package/dist/clients/claude/skill.md +13 -8
- package/dist/clients/claude/skills/ironbee-analyze.md +39 -0
- package/dist/clients/cursor/commands/ironbee-analyze/SKILL.md +48 -0
- package/dist/clients/cursor/commands/ironbee-verify/SKILL.md +133 -0
- package/dist/clients/cursor/hooks/clear-verdict.js +1 -1
- package/dist/clients/cursor/hooks/clear-verdict.js.map +1 -1
- package/dist/clients/cursor/hooks/require-verification.d.ts +15 -0
- package/dist/clients/cursor/hooks/require-verification.d.ts.map +1 -0
- package/dist/clients/cursor/hooks/require-verification.js +65 -0
- package/dist/clients/cursor/hooks/require-verification.js.map +1 -0
- package/dist/clients/cursor/hooks/session-start.d.ts.map +1 -1
- package/dist/clients/cursor/hooks/session-start.js +3 -0
- package/dist/clients/cursor/hooks/session-start.js.map +1 -1
- package/dist/clients/cursor/hooks/track-action.d.ts.map +1 -1
- package/dist/clients/cursor/hooks/track-action.js +62 -12
- package/dist/clients/cursor/hooks/track-action.js.map +1 -1
- package/dist/clients/cursor/hooks/verify-gate.js +1 -1
- package/dist/clients/cursor/hooks/verify-gate.js.map +1 -1
- package/dist/clients/cursor/index.d.ts +2 -0
- package/dist/clients/cursor/index.d.ts.map +1 -1
- package/dist/clients/cursor/index.js +41 -16
- package/dist/clients/cursor/index.js.map +1 -1
- package/dist/clients/cursor/rule.md +10 -7
- package/dist/clients/cursor/skill.md +13 -8
- package/dist/commands/analyze.d.ts +3 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +298 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/hook.d.ts.map +1 -1
- package/dist/commands/hook.js +79 -0
- package/dist/commands/hook.js.map +1 -1
- package/dist/hooks/core/actions.d.ts +19 -0
- package/dist/hooks/core/actions.d.ts.map +1 -1
- package/dist/hooks/core/actions.js +5 -0
- package/dist/hooks/core/actions.js.map +1 -1
- package/dist/hooks/core/clear-verdict.d.ts +1 -1
- package/dist/hooks/core/clear-verdict.d.ts.map +1 -1
- package/dist/hooks/core/clear-verdict.js +13 -9
- package/dist/hooks/core/clear-verdict.js.map +1 -1
- package/dist/hooks/core/session-state.d.ts +47 -0
- package/dist/hooks/core/session-state.d.ts.map +1 -0
- package/dist/hooks/core/session-state.js +192 -0
- package/dist/hooks/core/session-state.js.map +1 -0
- package/dist/hooks/core/submit-verdict.d.ts +1 -0
- package/dist/hooks/core/submit-verdict.d.ts.map +1 -1
- package/dist/hooks/core/submit-verdict.js +35 -27
- package/dist/hooks/core/submit-verdict.js.map +1 -1
- package/dist/hooks/core/verification-lifecycle.d.ts +30 -0
- package/dist/hooks/core/verification-lifecycle.d.ts.map +1 -0
- package/dist/hooks/core/verification-lifecycle.js +75 -0
- package/dist/hooks/core/verification-lifecycle.js.map +1 -0
- package/dist/hooks/core/verify-gate.d.ts +1 -1
- package/dist/hooks/core/verify-gate.d.ts.map +1 -1
- package/dist/hooks/core/verify-gate.js +13 -20
- package/dist/hooks/core/verify-gate.js.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/config.d.ts +18 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +59 -0
- package/dist/lib/config.js.map +1 -1
- package/package.json +4 -3
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ironbee-verify
|
|
3
|
+
description: "Trigger browser verification of code changes. Args: (default), full, visual, functional"
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# IronBee Verify
|
|
8
|
+
|
|
9
|
+
Verify the current code changes in the browser.
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
- `/ironbee-verify` — **default** — focus on what changed, visual + functional checks on affected areas
|
|
13
|
+
- `/ironbee-verify full` — **full scope** — entire application, all checklists, edge cases, responsive, accessibility deep dive
|
|
14
|
+
- `/ironbee-verify visual` — **visual only** — contrast, layout, spacing, fonts, images, theming
|
|
15
|
+
- `/ironbee-verify functional` — **functional only** — clicks, forms, navigation, data flow, error handling
|
|
16
|
+
|
|
17
|
+
If no argument is given, use **default** mode.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Steps (all modes)
|
|
22
|
+
|
|
23
|
+
1. **Start verification**: Run `echo '{"session_id":"<your-session-id>"}' | ironbee hook verification-start` via terminal
|
|
24
|
+
2. **Build and start** the application if not already running
|
|
25
|
+
3. **For EVERY page you visit**, repeat this cycle:
|
|
26
|
+
a. **Navigate** using browser-devtools MCP tools
|
|
27
|
+
b. **Take a FULL PAGE screenshot** with `fullPage: true`
|
|
28
|
+
c. **Take an ARIA snapshot** to capture the page structure
|
|
29
|
+
d. **STOP and visually analyze the screenshot** — switch your focus entirely to finding visual problems. Look at this screenshot as if your ONLY job is to find visual defects:
|
|
30
|
+
**WARNING: ARIA reports DOM content, not what the user actually sees.** Do NOT assume the page looks correct just because ARIA shows the right content. Only the screenshot tells you what the user actually sees.
|
|
31
|
+
- Text readability — is it readable against its background? Look for text that blends in or poor contrast
|
|
32
|
+
- Layout — overlapping elements, unexpected gaps, overflow, content cut off
|
|
33
|
+
- Spacing — consistent padding/margin? Too cramped or too far apart?
|
|
34
|
+
- Colors — intentional and consistent? Any jarring mismatches?
|
|
35
|
+
- Typography — right sizes? Clipped or truncated text?
|
|
36
|
+
- Images/icons — loaded? Right size and aspect ratio?
|
|
37
|
+
- States — empty, loading, disabled, error states rendered properly?
|
|
38
|
+
Report your visual findings before continuing.
|
|
39
|
+
e. **Read the ARIA snapshot** — verify headings, labels, landmarks, and structure
|
|
40
|
+
f. If anything looks wrong → note it as an issue
|
|
41
|
+
4. **Functionally test** — run the checklist for your mode (see below). After each significant interaction, take another screenshot and repeat the visual analysis.
|
|
42
|
+
5. **Check console** for errors
|
|
43
|
+
6. **Stop** the dev server when verification is complete
|
|
44
|
+
7. **Submit your verdict** via terminal:
|
|
45
|
+
- Pass: `echo '{"session_id":"...","status":"pass","pages_tested":[...],"checks":[...],"console_errors":0,"network_failures":0}' | ironbee hook submit-verdict`
|
|
46
|
+
- Fail: `echo '{"session_id":"...","status":"fail","pages_tested":[...],"checks":[...],"console_errors":N,"network_failures":N,"issues":["describe what failed"]}' | ironbee hook submit-verdict`
|
|
47
|
+
8. **If failed** → collect ALL issues first (finish testing all affected pages), submit one fail verdict with all issues, then fix everything, rebuild, and re-verify. Do not fix one issue at a time — batch fixes to avoid repeated build/restart cycles.
|
|
48
|
+
9. If pass after a previous fail, include `"fixes"` in the verdict describing what was fixed
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Default Mode
|
|
53
|
+
|
|
54
|
+
Focus on the code you changed — not the entire application.
|
|
55
|
+
|
|
56
|
+
### 1. Study the changes
|
|
57
|
+
1. Run `git diff --name-only` and `git diff --name-only HEAD~1`
|
|
58
|
+
2. **Ignore `.ironbee/`, `.claude/`, `.cursor/`** — tool config, not application code
|
|
59
|
+
3. **Read the full diff** (`git diff` and/or `git diff HEAD~1`) — understand every change: what was added, removed, modified. Note specific values (colors, sizes, conditions, logic, API endpoints, component props).
|
|
60
|
+
4. Before opening the browser, you should be able to answer: what exactly changed, what should look or behave differently, and what could go wrong?
|
|
61
|
+
|
|
62
|
+
### 2. Verify in the browser
|
|
63
|
+
- **Cross-reference the diff against what you see.** For each change in the diff, verify it is correctly reflected in the browser. If the diff changes a color → check that color. If it changes a calculation → verify the result. If it adds a component → confirm it renders.
|
|
64
|
+
- **Test the flow end-to-end** — navigate, click, fill forms, submit, verify the outcome
|
|
65
|
+
- **Check one edge case** — empty input, invalid data, or double-click
|
|
66
|
+
- **Console** — any new errors or warnings?
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Full Mode (`/ironbee-verify full`)
|
|
71
|
+
|
|
72
|
+
Comprehensive verification of the **entire application**. Do NOT run `git diff` or scope to recent changes. Test every page, every flow, every visual detail. Any issue is a failure, regardless of when it was introduced.
|
|
73
|
+
|
|
74
|
+
### Visual Checklist
|
|
75
|
+
In addition to the per-page visual analysis in step 3d:
|
|
76
|
+
- **Responsiveness** — does the layout adapt if viewport changes? No horizontal scrolling on standard widths
|
|
77
|
+
- **Borders & separators** — visible and consistent? Not too faint or missing
|
|
78
|
+
- **Scroll behavior** — does the page scroll smoothly? No content hidden behind sticky headers/footers?
|
|
79
|
+
|
|
80
|
+
### Functional Checklist
|
|
81
|
+
- **Navigation** — do links and buttons navigate to the correct pages?
|
|
82
|
+
- **Forms** — fill inputs with real data, select options, submit. Do validation messages appear correctly?
|
|
83
|
+
- **Buttons & interactions** — do click handlers fire? Do toggles, dropdowns, and modals work?
|
|
84
|
+
- **Data flow** — does submitted data appear where expected?
|
|
85
|
+
- **Error handling** — what happens with invalid input? Does the UI handle errors gracefully?
|
|
86
|
+
- **Authentication** — if applicable, do protected routes redirect correctly?
|
|
87
|
+
- **API calls** — do network requests succeed? Check for failed requests in console/network
|
|
88
|
+
- **State persistence** — does state survive page refresh where expected?
|
|
89
|
+
- **Edge cases** — empty inputs, very long text, special characters, rapid clicks
|
|
90
|
+
|
|
91
|
+
### Accessibility (deep dive)
|
|
92
|
+
- Are headings hierarchical? Do form inputs have labels? Are landmarks present?
|
|
93
|
+
- Check for missing alt text on images
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Visual Mode (`/ironbee-verify visual`)
|
|
98
|
+
|
|
99
|
+
Focus exclusively on visual quality. Run the per-page visual analysis from step 3d on every page, plus:
|
|
100
|
+
- **Responsiveness** — viewport changes, no horizontal scrolling
|
|
101
|
+
- **Borders & separators** — visible and consistent?
|
|
102
|
+
- **Scroll behavior** — smooth scrolling, no hidden content
|
|
103
|
+
|
|
104
|
+
Take screenshots of **multiple states** if applicable (hover, active, disabled, empty, populated).
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Functional Mode (`/ironbee-verify functional`)
|
|
109
|
+
|
|
110
|
+
Focus exclusively on behavior. Use the same functional checklist as Full Mode above.
|
|
111
|
+
|
|
112
|
+
Test the **complete user flow**, not just the single step you changed.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## When to FAIL
|
|
117
|
+
|
|
118
|
+
If you observe ANY problem — wrong data, unexpected errors, visual defects, broken interactions, console errors, data inconsistency between pages — you MUST submit a **fail** verdict.
|
|
119
|
+
|
|
120
|
+
**Do NOT rationalize away problems.** If something looks wrong or behaves unexpectedly, it IS wrong. In **full** mode, there is no such thing as "pre-existing" — if it's broken, fail it.
|
|
121
|
+
|
|
122
|
+
**After a fail verdict, you MUST fix the issues and re-verify.** Do not just report and stop.
|
|
123
|
+
|
|
124
|
+
## Verdict Quality
|
|
125
|
+
|
|
126
|
+
Your `checks` array must list **specific observations**, not generic statements:
|
|
127
|
+
- GOOD: `["login form renders with email and password fields", "submitted valid credentials, redirected to /dashboard", "console clean — 0 errors"]`
|
|
128
|
+
- BAD: `["it works", "looks good", "feature implemented"]`
|
|
129
|
+
|
|
130
|
+
## Important
|
|
131
|
+
- ALWAYS submit a verdict after every verification attempt — both pass AND fail
|
|
132
|
+
- Do NOT edit code before submitting a fail verdict
|
|
133
|
+
- **Noticing a bug and submitting pass is the #1 violation** — if you see it, fail it
|
|
@@ -50,7 +50,7 @@ function run(projectDir) {
|
|
|
50
50
|
(0, actions_1.appendAction)(`${projectDir}/.ironbee/sessions/${sessionId}/actions.jsonl`, fileEditEntry);
|
|
51
51
|
(0, clear_verdict_1.runClearVerdict)({
|
|
52
52
|
verdictFile: `${projectDir}/.ironbee/sessions/${sessionId}/verdict.json`,
|
|
53
|
-
|
|
53
|
+
sessionDir: `${projectDir}/.ironbee/sessions/${sessionId}`,
|
|
54
54
|
});
|
|
55
55
|
process.exit(0);
|
|
56
56
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clear-verdict.js","sourceRoot":"","sources":["../../../../src/clients/cursor/hooks/clear-verdict.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;AAeH,kBA4CC;AAzDD,qEAAoE;AACpE,yDAA2E;AAC3E,gDAAsF;AACtF,gDAAyD;AACzD,8CAA+C;AAS/C,SAAgB,GAAG,CAAC,UAAkB;IAClC,IAAI,KAA+B,CAAC;IACpC,IAAI,CAAC;QACD,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAS,GAAE,CAA6B,CAAC;IAChE,CAAC;IAAC,OAAO,CAAU,EAAE,CAAC;QAClB,eAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,EAAE,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,SAAS,GAAW,KAAK,CAAC,eAAe,IAAI,SAAS,CAAC;IAC7D,IAAA,mBAAU,EAAC,GAAG,UAAU,sBAAsB,SAAS,cAAc,CAAC,CAAC;IAEvE,MAAM,WAAW,GAAuB,KAAK,CAAC,SAAS,CAAC;IAExD,4DAA4D;IAC5D,IAAI,WAAW,IAAI,WAAW,CAAC,QAAQ,CAAC,oBAAoB,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QACpG,eAAM,CAAC,KAAK,CAAC,wDAAwD,WAAW,EAAE,CAAC,CAAC;QACpF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,6CAA6C;IAC7C,IAAI,WAAW,EAAE,CAAC;QACd,MAAM,MAAM,GAAkB,IAAA,mBAAU,EAAC,UAAU,CAAC,CAAC;QACrD,IAAI,CAAC,IAAA,6BAAoB,EAAC,WAAW,EAAE,MAAM,CAAC,EAAE,CAAC;YAC7C,eAAM,CAAC,KAAK,CAAC,+DAA+D,WAAW,GAAG,CAAC,CAAC;YAC5F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;IACL,CAAC;IAED,oCAAoC;IACpC,MAAM,aAAa,GAAmB;QAClC,IAAI,EAAE,WAAW;QACjB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,SAAS,EAAE,WAAW;QACtB,SAAS,EAAE,WAAW;KACzB,CAAC;IACF,IAAA,sBAAY,EAAC,GAAG,UAAU,sBAAsB,SAAS,gBAAgB,EAAE,aAAa,CAAC,CAAC;IAE1F,IAAA,+BAAe,EAAC;QACZ,WAAW,EAAE,GAAG,UAAU,sBAAsB,SAAS,eAAe;QACxE,
|
|
1
|
+
{"version":3,"file":"clear-verdict.js","sourceRoot":"","sources":["../../../../src/clients/cursor/hooks/clear-verdict.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;AAeH,kBA4CC;AAzDD,qEAAoE;AACpE,yDAA2E;AAC3E,gDAAsF;AACtF,gDAAyD;AACzD,8CAA+C;AAS/C,SAAgB,GAAG,CAAC,UAAkB;IAClC,IAAI,KAA+B,CAAC;IACpC,IAAI,CAAC;QACD,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAS,GAAE,CAA6B,CAAC;IAChE,CAAC;IAAC,OAAO,CAAU,EAAE,CAAC;QAClB,eAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,EAAE,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,SAAS,GAAW,KAAK,CAAC,eAAe,IAAI,SAAS,CAAC;IAC7D,IAAA,mBAAU,EAAC,GAAG,UAAU,sBAAsB,SAAS,cAAc,CAAC,CAAC;IAEvE,MAAM,WAAW,GAAuB,KAAK,CAAC,SAAS,CAAC;IAExD,4DAA4D;IAC5D,IAAI,WAAW,IAAI,WAAW,CAAC,QAAQ,CAAC,oBAAoB,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QACpG,eAAM,CAAC,KAAK,CAAC,wDAAwD,WAAW,EAAE,CAAC,CAAC;QACpF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,6CAA6C;IAC7C,IAAI,WAAW,EAAE,CAAC;QACd,MAAM,MAAM,GAAkB,IAAA,mBAAU,EAAC,UAAU,CAAC,CAAC;QACrD,IAAI,CAAC,IAAA,6BAAoB,EAAC,WAAW,EAAE,MAAM,CAAC,EAAE,CAAC;YAC7C,eAAM,CAAC,KAAK,CAAC,+DAA+D,WAAW,GAAG,CAAC,CAAC;YAC5F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;IACL,CAAC;IAED,oCAAoC;IACpC,MAAM,aAAa,GAAmB;QAClC,IAAI,EAAE,WAAW;QACjB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,SAAS,EAAE,WAAW;QACtB,SAAS,EAAE,WAAW;KACzB,CAAC;IACF,IAAA,sBAAY,EAAC,GAAG,UAAU,sBAAsB,SAAS,gBAAgB,EAAE,aAAa,CAAC,CAAC;IAE1F,IAAA,+BAAe,EAAC;QACZ,WAAW,EAAE,GAAG,UAAU,sBAAsB,SAAS,eAAe;QACxE,UAAU,EAAE,GAAG,UAAU,sBAAsB,SAAS,EAAE;KAC7D,CAAC,CAAC;IAEH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor — require-verification hook adapter
|
|
3
|
+
*
|
|
4
|
+
* preToolUse hook for MCP:bdt_.* — blocks browser tool usage
|
|
5
|
+
* if no active verification cycle. Forces agent to call
|
|
6
|
+
* `ironbee hook verification-start` before using browser tools.
|
|
7
|
+
*
|
|
8
|
+
* When allowed, injects `_metadata` into tool input with sessionId and traceId
|
|
9
|
+
* so the MCP server knows the active session/trace context.
|
|
10
|
+
*
|
|
11
|
+
* Returns { permission: "deny" } + exit 2 to block.
|
|
12
|
+
* Returns { permission: "allow", updated_input: {...} } to allow with _metadata.
|
|
13
|
+
*/
|
|
14
|
+
export declare function run(projectDir: string): void;
|
|
15
|
+
//# sourceMappingURL=require-verification.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-verification.d.ts","sourceRoot":"","sources":["../../../../src/clients/cursor/hooks/require-verification.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAoBH,wBAAgB,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAgD5C"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Cursor — require-verification hook adapter
|
|
4
|
+
*
|
|
5
|
+
* preToolUse hook for MCP:bdt_.* — blocks browser tool usage
|
|
6
|
+
* if no active verification cycle. Forces agent to call
|
|
7
|
+
* `ironbee hook verification-start` before using browser tools.
|
|
8
|
+
*
|
|
9
|
+
* When allowed, injects `_metadata` into tool input with sessionId and traceId
|
|
10
|
+
* so the MCP server knows the active session/trace context.
|
|
11
|
+
*
|
|
12
|
+
* Returns { permission: "deny" } + exit 2 to block.
|
|
13
|
+
* Returns { permission: "allow", updated_input: {...} } to allow with _metadata.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.run = run;
|
|
17
|
+
const session_state_1 = require("../../../hooks/core/session-state");
|
|
18
|
+
const logger_1 = require("../../../lib/logger");
|
|
19
|
+
const stdin_1 = require("../../../lib/stdin");
|
|
20
|
+
function run(projectDir) {
|
|
21
|
+
let input;
|
|
22
|
+
try {
|
|
23
|
+
input = JSON.parse((0, stdin_1.readStdin)());
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
logger_1.logger.debug(`failed to parse stdin: ${e}`);
|
|
27
|
+
const output = { permission: "allow" };
|
|
28
|
+
process.stdout.write(JSON.stringify(output));
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
const sessionId = input.conversation_id ?? "default";
|
|
32
|
+
const sessionDir = `${projectDir}/.ironbee/sessions/${sessionId}`;
|
|
33
|
+
(0, logger_1.setLogFile)(`${sessionDir}/session.log`);
|
|
34
|
+
const verificationId = (0, session_state_1.getActiveVerificationId)(sessionDir);
|
|
35
|
+
if (!verificationId) {
|
|
36
|
+
const output = {
|
|
37
|
+
permission: "deny",
|
|
38
|
+
agent_message: `BLOCKED: You must start a verification cycle before using browser-devtools tools.
|
|
39
|
+
|
|
40
|
+
Start verification first:
|
|
41
|
+
echo '{"session_id":"${sessionId}"}' | ironbee hook verification-start
|
|
42
|
+
|
|
43
|
+
Then use browser tools to verify your changes.`,
|
|
44
|
+
};
|
|
45
|
+
process.stdout.write(JSON.stringify(output));
|
|
46
|
+
process.exit(2);
|
|
47
|
+
}
|
|
48
|
+
const traceId = (0, session_state_1.getActiveTraceId)(sessionDir);
|
|
49
|
+
// inject _metadata into tool input so MCP server knows session/trace context
|
|
50
|
+
const traceState = `ironbee=sid:${sessionId};vid:${verificationId}`;
|
|
51
|
+
const updatedInput = { ...(input.tool_input ?? {}) };
|
|
52
|
+
updatedInput._metadata = {
|
|
53
|
+
sessionId,
|
|
54
|
+
verificationId,
|
|
55
|
+
traceId,
|
|
56
|
+
traceState,
|
|
57
|
+
};
|
|
58
|
+
const output = {
|
|
59
|
+
permission: "allow",
|
|
60
|
+
updated_input: updatedInput,
|
|
61
|
+
};
|
|
62
|
+
process.stdout.write(JSON.stringify(output));
|
|
63
|
+
process.exit(0);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=require-verification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-verification.js","sourceRoot":"","sources":["../../../../src/clients/cursor/hooks/require-verification.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;AAoBH,kBAgDC;AAlED,qEAA8F;AAC9F,gDAAyD;AACzD,8CAA+C;AAgB/C,SAAgB,GAAG,CAAC,UAAkB;IAClC,IAAI,KAA4B,CAAC;IACjC,IAAI,CAAC;QACD,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAS,GAAE,CAA0B,CAAC;IAC7D,CAAC;IAAC,OAAO,CAAU,EAAE,CAAC;QAClB,eAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,EAAE,CAAC,CAAC;QAC5C,MAAM,MAAM,GAA2B,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;QAC/D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,SAAS,GAAW,KAAK,CAAC,eAAe,IAAI,SAAS,CAAC;IAC7D,MAAM,UAAU,GAAW,GAAG,UAAU,sBAAsB,SAAS,EAAE,CAAC;IAC1E,IAAA,mBAAU,EAAC,GAAG,UAAU,cAAc,CAAC,CAAC;IAExC,MAAM,cAAc,GAAuB,IAAA,uCAAuB,EAAC,UAAU,CAAC,CAAC;IAC/E,IAAI,CAAC,cAAc,EAAE,CAAC;QAClB,MAAM,MAAM,GAA2B;YACnC,UAAU,EAAE,MAAM;YAClB,aAAa,EAAE;;;yBAGF,SAAS;;+CAEa;SACtC,CAAC;QACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,OAAO,GAAuB,IAAA,gCAAgB,EAAC,UAAU,CAAC,CAAC;IAEjE,6EAA6E;IAC7E,MAAM,UAAU,GAAW,eAAe,SAAS,QAAQ,cAAc,EAAE,CAAC;IAC5E,MAAM,YAAY,GAA4B,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC,EAAE,CAAC;IAC9E,YAAY,CAAC,SAAS,GAAG;QACrB,SAAS;QACT,cAAc;QACd,OAAO;QACP,UAAU;KACb,CAAC;IAEF,MAAM,MAAM,GAA2B;QACnC,UAAU,EAAE,OAAO;QACnB,aAAa,EAAE,YAAY;KAC9B,CAAC;IACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-start.d.ts","sourceRoot":"","sources":["../../../../src/clients/cursor/hooks/session-start.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"session-start.d.ts","sourceRoot":"","sources":["../../../../src/clients/cursor/hooks/session-start.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAkBH,wBAAsB,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoE3D"}
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.run = run;
|
|
11
11
|
const actions_1 = require("../../../hooks/core/actions");
|
|
12
|
+
const session_state_1 = require("../../../hooks/core/session-state");
|
|
12
13
|
const logger_1 = require("../../../lib/logger");
|
|
13
14
|
const stdin_1 = require("../../../lib/stdin");
|
|
14
15
|
const telemetry_1 = require("../../../lib/telemetry");
|
|
@@ -31,7 +32,9 @@ async function run(projectDir) {
|
|
|
31
32
|
session_id: sessionId,
|
|
32
33
|
source: "cursor",
|
|
33
34
|
};
|
|
35
|
+
const sessionDir = `${projectDir}/.ironbee/sessions/${sessionId}`;
|
|
34
36
|
(0, actions_1.appendAction)(actionsFile, entry);
|
|
37
|
+
(0, session_state_1.reconcileSessionState)(sessionDir, actionsFile, actions_1.appendAction);
|
|
35
38
|
await (0, telemetry_1.trackSessionStart)("cursor", sessionId);
|
|
36
39
|
logger_1.logger.debug(`session-start: ${sessionId}`);
|
|
37
40
|
const verdictPass = JSON.stringify({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-start.js","sourceRoot":"","sources":["../../../../src/clients/cursor/hooks/session-start.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;
|
|
1
|
+
{"version":3,"file":"session-start.js","sourceRoot":"","sources":["../../../../src/clients/cursor/hooks/session-start.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAkBH,kBAoEC;AApFD,yDAA+E;AAC/E,qEAA0E;AAC1E,gDAAyD;AACzD,8CAA+C;AAC/C,sDAA2D;AAYpD,KAAK,UAAU,GAAG,CAAC,UAAkB;IACxC,IAAI,KAA8B,CAAC;IACnC,IAAI,CAAC;QACD,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAS,GAAE,CAA4B,CAAC;IAC/D,CAAC;IAAC,OAAO,CAAU,EAAE,CAAC;QAClB,eAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,EAAE,CAAC,CAAC;QAC5C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,SAAS,GAAW,KAAK,CAAC,eAAe,IAAI,SAAS,CAAC;IAC7D,MAAM,WAAW,GAAW,GAAG,UAAU,sBAAsB,SAAS,gBAAgB,CAAC;IACzF,IAAA,mBAAU,EAAC,GAAG,UAAU,sBAAsB,SAAS,cAAc,CAAC,CAAC;IAEvE,MAAM,KAAK,GAAuB;QAC9B,IAAI,EAAE,eAAe;QACrB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,UAAU,EAAE,SAAS;QACrB,MAAM,EAAE,QAAQ;KACnB,CAAC;IAEF,MAAM,UAAU,GAAW,GAAG,UAAU,sBAAsB,SAAS,EAAE,CAAC;IAC1E,IAAA,sBAAY,EAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IACjC,IAAA,qCAAqB,EAAC,UAAU,EAAE,WAAW,EAAE,sBAAY,CAAC,CAAC;IAC7D,MAAM,IAAA,6BAAiB,EAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC7C,eAAM,CAAC,KAAK,CAAC,kBAAkB,SAAS,EAAE,CAAC,CAAC;IAE5C,MAAM,WAAW,GAAW,IAAI,CAAC,SAAS,CAAC;QACvC,UAAU,EAAE,SAAS;QACrB,MAAM,EAAE,MAAM;QACd,YAAY,EAAE,CAAC,qCAAqC,CAAC;QACrD,MAAM,EAAE,CAAC,2BAA2B,EAAE,0BAA0B,CAAC;QACjE,cAAc,EAAE,CAAC;QACjB,gBAAgB,EAAE,CAAC;KACtB,CAAC,CAAC;IACH,MAAM,WAAW,GAAW,IAAI,CAAC,SAAS,CAAC;QACvC,UAAU,EAAE,SAAS;QACrB,MAAM,EAAE,MAAM;QACd,YAAY,EAAE,CAAC,qCAAqC,CAAC;QACrD,MAAM,EAAE,CAAC,cAAc,EAAE,4BAA4B,CAAC;QACtD,cAAc,EAAE,CAAC;QACjB,gBAAgB,EAAE,CAAC;QACnB,MAAM,EAAE,CAAC,iCAAiC,EAAE,sBAAsB,CAAC;KACtE,CAAC,CAAC;IAEH,MAAM,OAAO,GAAW;cACd,SAAS;;;;;;;;UAQb,WAAW;;;UAGX,WAAW;;;;2FAIsE,CAAC;IAExF,MAAM,MAAM,GAA6B;QACrC,kBAAkB,EAAE,OAAO;KAC9B,CAAC;IACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track-action.d.ts","sourceRoot":"","sources":["../../../../src/clients/cursor/hooks/track-action.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;
|
|
1
|
+
{"version":3,"file":"track-action.d.ts","sourceRoot":"","sources":["../../../../src/clients/cursor/hooks/track-action.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAmGH,wBAAgB,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAuD5C"}
|
|
@@ -18,10 +18,11 @@ exports.run = run;
|
|
|
18
18
|
const actions_1 = require("../../../hooks/core/actions");
|
|
19
19
|
const logger_1 = require("../../../lib/logger");
|
|
20
20
|
const stdin_1 = require("../../../lib/stdin");
|
|
21
|
-
const
|
|
21
|
+
const CALL_TOOL_NAME_PATTERN = /callTool\(\s*['"]([^'"]+)['"]/g;
|
|
22
22
|
const MCP_PREFIX = "mcp__browser-devtools__";
|
|
23
23
|
const CURSOR_MCP_PREFIX = "MCP:";
|
|
24
|
-
const
|
|
24
|
+
const TOOL_NAME_PREFIX = "bdt_";
|
|
25
|
+
const EXECUTE_TOOL = `${MCP_PREFIX}${TOOL_NAME_PREFIX}execute`;
|
|
25
26
|
/** Convert Cursor's MCP:<name> format to mcp__browser-devtools__<name>. */
|
|
26
27
|
function normalizeMcpToolName(cursorName) {
|
|
27
28
|
if (cursorName.startsWith(CURSOR_MCP_PREFIX)) {
|
|
@@ -35,17 +36,58 @@ function normalizeMcpToolName(cursorName) {
|
|
|
35
36
|
function toFullName(shortName) {
|
|
36
37
|
return shortName.startsWith(MCP_PREFIX) ? shortName : `${MCP_PREFIX}${shortName}`;
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
+
/** Extract balanced braces starting at position after opening brace. */
|
|
40
|
+
function extractBalancedBraces(str, startIndex) {
|
|
41
|
+
if (str[startIndex] !== "{") {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
let depth = 0;
|
|
45
|
+
for (let i = startIndex; i < str.length; i++) {
|
|
46
|
+
if (str[i] === "{") {
|
|
47
|
+
depth++;
|
|
48
|
+
}
|
|
49
|
+
else if (str[i] === "}") {
|
|
50
|
+
depth--;
|
|
51
|
+
if (depth === 0) {
|
|
52
|
+
return str.slice(startIndex, i + 1);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
function extractNestedToolCalls(toolInput) {
|
|
39
59
|
const inputStr = typeof toolInput === "string"
|
|
40
60
|
? toolInput
|
|
41
61
|
: JSON.stringify(toolInput ?? "");
|
|
42
|
-
const
|
|
43
|
-
|
|
62
|
+
const results = [];
|
|
63
|
+
const seen = new Set();
|
|
64
|
+
let match = CALL_TOOL_NAME_PATTERN.exec(inputStr);
|
|
44
65
|
while (match !== null) {
|
|
45
|
-
|
|
46
|
-
|
|
66
|
+
const toolName = toFullName(match[1]);
|
|
67
|
+
if (!seen.has(toolName)) {
|
|
68
|
+
seen.add(toolName);
|
|
69
|
+
let args = undefined;
|
|
70
|
+
const afterName = match.index + match[0].length;
|
|
71
|
+
const rest = inputStr.slice(afterName).trimStart();
|
|
72
|
+
if (rest.startsWith(",")) {
|
|
73
|
+
const afterComma = rest.slice(1).trimStart();
|
|
74
|
+
if (afterComma.startsWith("{")) {
|
|
75
|
+
const braceStr = extractBalancedBraces(afterComma, 0);
|
|
76
|
+
if (braceStr) {
|
|
77
|
+
try {
|
|
78
|
+
args = JSON.parse(braceStr);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
args = braceStr;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
results.push({ name: toolName, args });
|
|
87
|
+
}
|
|
88
|
+
match = CALL_TOOL_NAME_PATTERN.exec(inputStr);
|
|
47
89
|
}
|
|
48
|
-
return
|
|
90
|
+
return results;
|
|
49
91
|
}
|
|
50
92
|
function run(projectDir) {
|
|
51
93
|
let input;
|
|
@@ -61,6 +103,13 @@ function run(projectDir) {
|
|
|
61
103
|
const actionsFile = `${projectDir}/.ironbee/sessions/${sessionId}/actions.jsonl`;
|
|
62
104
|
(0, logger_1.setLogFile)(`${projectDir}/.ironbee/sessions/${sessionId}/session.log`);
|
|
63
105
|
const rawToolName = input.tool_name ?? "unknown";
|
|
106
|
+
// skip non-bdt tools (only track browser-devtools tools with bdt_ prefix)
|
|
107
|
+
const bareToolName = rawToolName.startsWith(CURSOR_MCP_PREFIX) ? rawToolName.slice(CURSOR_MCP_PREFIX.length) : rawToolName;
|
|
108
|
+
if (!bareToolName.startsWith(TOOL_NAME_PREFIX)) {
|
|
109
|
+
logger_1.logger.debug(`skipping track-action: not a bdt_ tool (${rawToolName})`);
|
|
110
|
+
process.stdout.write(JSON.stringify({}));
|
|
111
|
+
process.exit(0);
|
|
112
|
+
}
|
|
64
113
|
const toolName = normalizeMcpToolName(rawToolName);
|
|
65
114
|
const timestamp = new Date().toISOString();
|
|
66
115
|
// record the direct tool call
|
|
@@ -75,15 +124,16 @@ function run(projectDir) {
|
|
|
75
124
|
logger_1.logger.debug(`track-action: ${rawToolName} → ${toolName}`);
|
|
76
125
|
// for execute tool, extract and record nested callTool() invocations
|
|
77
126
|
if (toolName === EXECUTE_TOOL) {
|
|
78
|
-
const nested =
|
|
79
|
-
for (const
|
|
127
|
+
const nested = extractNestedToolCalls(input.tool_input);
|
|
128
|
+
for (const call of nested) {
|
|
80
129
|
const nestedEntry = {
|
|
81
130
|
type: "tool_call",
|
|
82
131
|
timestamp,
|
|
83
|
-
tool_name: name,
|
|
132
|
+
tool_name: call.name,
|
|
133
|
+
tool_input: call.args,
|
|
84
134
|
};
|
|
85
135
|
(0, actions_1.appendAction)(actionsFile, nestedEntry);
|
|
86
|
-
logger_1.logger.debug(`track-action (nested): ${name}`);
|
|
136
|
+
logger_1.logger.debug(`track-action (nested): ${call.name}`);
|
|
87
137
|
}
|
|
88
138
|
}
|
|
89
139
|
process.stdout.write(JSON.stringify({}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track-action.js","sourceRoot":"","sources":["../../../../src/clients/cursor/hooks/track-action.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;
|
|
1
|
+
{"version":3,"file":"track-action.js","sourceRoot":"","sources":["../../../../src/clients/cursor/hooks/track-action.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,9 +31,9 @@ async function run(projectDir) {
|
|
|
31
31
|
const config = (0, config_1.loadConfig)(projectDir);
|
|
32
32
|
const result = await (0, verify_gate_1.runVerifyGate)({
|
|
33
33
|
sessionId,
|
|
34
|
+
sessionDir: `${projectDir}/.ironbee/sessions/${sessionId}`,
|
|
34
35
|
actionsFile: `${projectDir}/.ironbee/sessions/${sessionId}/actions.jsonl`,
|
|
35
36
|
verdictFile: `${projectDir}/.ironbee/sessions/${sessionId}/verdict.json`,
|
|
36
|
-
retryFile: `${projectDir}/.ironbee/sessions/${sessionId}/retries`,
|
|
37
37
|
maxRetries: (0, config_1.getMaxRetries)(config),
|
|
38
38
|
});
|
|
39
39
|
const output = {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify-gate.js","sourceRoot":"","sources":["../../../../src/clients/cursor/hooks/verify-gate.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAmBH,kBAkCC;AAnDD,iEAAkF;AAClF,gDAA+E;AAC/E,gDAAyD;AACzD,8CAA+C;AAcxC,KAAK,UAAU,GAAG,CAAC,UAAkB;IACxC,IAAI,KAA0B,CAAC;IAC/B,IAAI,CAAC;QACD,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAS,GAAE,CAAwB,CAAC;IAC3D,CAAC;IAAC,OAAO,CAAU,EAAE,CAAC;QAClB,eAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,EAAE,CAAC,CAAC;QAC5C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,SAAS,GAAW,KAAK,CAAC,eAAe,IAAI,SAAS,CAAC;IAC7D,IAAA,mBAAU,EAAC,GAAG,UAAU,sBAAsB,SAAS,cAAc,CAAC,CAAC;IAEvE,MAAM,MAAM,GAAkB,IAAA,mBAAU,EAAC,UAAU,CAAC,CAAC;IAErD,MAAM,MAAM,GAAqB,MAAM,IAAA,2BAAa,EAAC;QACjD,SAAS;QACT,
|
|
1
|
+
{"version":3,"file":"verify-gate.js","sourceRoot":"","sources":["../../../../src/clients/cursor/hooks/verify-gate.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAmBH,kBAkCC;AAnDD,iEAAkF;AAClF,gDAA+E;AAC/E,gDAAyD;AACzD,8CAA+C;AAcxC,KAAK,UAAU,GAAG,CAAC,UAAkB;IACxC,IAAI,KAA0B,CAAC;IAC/B,IAAI,CAAC;QACD,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAS,GAAE,CAAwB,CAAC;IAC3D,CAAC;IAAC,OAAO,CAAU,EAAE,CAAC;QAClB,eAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,EAAE,CAAC,CAAC;QAC5C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,SAAS,GAAW,KAAK,CAAC,eAAe,IAAI,SAAS,CAAC;IAC7D,IAAA,mBAAU,EAAC,GAAG,UAAU,sBAAsB,SAAS,cAAc,CAAC,CAAC;IAEvE,MAAM,MAAM,GAAkB,IAAA,mBAAU,EAAC,UAAU,CAAC,CAAC;IAErD,MAAM,MAAM,GAAqB,MAAM,IAAA,2BAAa,EAAC;QACjD,SAAS;QACT,UAAU,EAAE,GAAG,UAAU,sBAAsB,SAAS,EAAE;QAC1D,WAAW,EAAE,GAAG,UAAU,sBAAsB,SAAS,gBAAgB;QACzE,WAAW,EAAE,GAAG,UAAU,sBAAsB,SAAS,eAAe;QACxE,UAAU,EAAE,IAAA,sBAAa,EAAC,MAAM,CAAC;KACpC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAyB,EAAE,CAAC;IAExC,uEAAuE;IACvE,0EAA0E;IAC1E,qEAAqE;IACrE,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QAC9C,MAAM,CAAC,gBAAgB,GAAG,MAAM,CAAC,OAAO,CAAC;IAC7C,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC"}
|
|
@@ -5,11 +5,13 @@ export declare class CursorClient implements IClient {
|
|
|
5
5
|
resolveProjectDir(): string;
|
|
6
6
|
install(projectDir: string): void;
|
|
7
7
|
uninstall(projectDir: string): void;
|
|
8
|
+
private cleanupArtifacts;
|
|
8
9
|
runVerifyGate(projectDir: string): void;
|
|
9
10
|
runClearVerdict(projectDir: string): void;
|
|
10
11
|
runTrackAction(projectDir: string): void;
|
|
11
12
|
runSessionStart(projectDir: string): void;
|
|
12
13
|
runRequireVerdict(projectDir: string): void;
|
|
14
|
+
runRequireVerification(projectDir: string): void;
|
|
13
15
|
private isIronBeeHook;
|
|
14
16
|
private mergeHooksConfig;
|
|
15
17
|
private removeIronBeeHooks;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/clients/cursor/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/clients/cursor/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AA2ClC,qBAAa,YAAa,YAAW,OAAO;IACxC,SAAgB,IAAI,EAAE,MAAM,CAAY;IAEjC,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAInC,iBAAiB,IAAI,MAAM;IAI3B,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAiDjC,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAO1C,OAAO,CAAC,gBAAgB;IAsBjB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAIvC,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAIzC,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAIxC,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAIzC,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAI3C,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAIvD,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,gBAAgB;IA4ExB,OAAO,CAAC,kBAAkB;IAuB1B,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,cAAc;CAoBzB"}
|
|
@@ -10,8 +10,9 @@ const clear_verdict_1 = require("./hooks/clear-verdict");
|
|
|
10
10
|
const track_action_1 = require("./hooks/track-action");
|
|
11
11
|
const session_start_1 = require("./hooks/session-start");
|
|
12
12
|
const require_verdict_1 = require("./hooks/require-verdict");
|
|
13
|
+
const require_verification_1 = require("./hooks/require-verification");
|
|
14
|
+
const config_1 = require("../../lib/config");
|
|
13
15
|
const MCP_SERVER_NAME = "browser-devtools";
|
|
14
|
-
const MCP_SERVER_PACKAGE = "browser-devtools-mcp";
|
|
15
16
|
const IRONBEE_HOOK_MARKER = "ironbee";
|
|
16
17
|
// Color for [cursor] label — gray
|
|
17
18
|
function cursorColor(text) {
|
|
@@ -28,6 +29,8 @@ class CursorClient {
|
|
|
28
29
|
return process.env.CURSOR_PROJECT_DIR ?? process.env.IRONBEE_PROJECT_DIR ?? process.cwd();
|
|
29
30
|
}
|
|
30
31
|
install(projectDir) {
|
|
32
|
+
// Clean up old artifacts first (safe for re-install / upgrade)
|
|
33
|
+
this.cleanupArtifacts(projectDir);
|
|
31
34
|
const cursorDir = (0, path_1.join)(projectDir, ".cursor");
|
|
32
35
|
const rulesDir = (0, path_1.join)(cursorDir, "rules");
|
|
33
36
|
const skillsDir = (0, path_1.join)(cursorDir, "skills");
|
|
@@ -41,11 +44,22 @@ class CursorClient {
|
|
|
41
44
|
const rulePath = (0, path_1.join)(rulesDir, "ironbee-verification.mdc");
|
|
42
45
|
const ruleContent = (0, fs_1.readFileSync)((0, path_1.join)(__dirname, "rule.md"), "utf-8");
|
|
43
46
|
(0, fs_1.writeFileSync)(rulePath, ruleContent);
|
|
47
|
+
const analyzeSkillDir = (0, path_1.join)(skillsDir, "ironbee-analyze");
|
|
48
|
+
(0, fs_1.mkdirSync)(analyzeSkillDir, { recursive: true });
|
|
49
|
+
const analyzeSkillPath = (0, path_1.join)(analyzeSkillDir, "SKILL.md");
|
|
50
|
+
const analyzeContent = (0, fs_1.readFileSync)((0, path_1.join)(__dirname, "commands", "ironbee-analyze", "SKILL.md"), "utf-8");
|
|
51
|
+
(0, fs_1.writeFileSync)(analyzeSkillPath, analyzeContent);
|
|
52
|
+
const verifySkillDir = (0, path_1.join)(skillsDir, "ironbee-verify");
|
|
53
|
+
(0, fs_1.mkdirSync)(verifySkillDir, { recursive: true });
|
|
54
|
+
const verifySkillPath = (0, path_1.join)(verifySkillDir, "SKILL.md");
|
|
55
|
+
const verifyContent = (0, fs_1.readFileSync)((0, path_1.join)(__dirname, "commands", "ironbee-verify", "SKILL.md"), "utf-8");
|
|
56
|
+
(0, fs_1.writeFileSync)(verifySkillPath, verifyContent);
|
|
44
57
|
const mcpPath = (0, path_1.join)(cursorDir, "mcp.json");
|
|
45
|
-
this.writeMcpConfig(mcpPath);
|
|
58
|
+
this.writeMcpConfig(mcpPath, projectDir);
|
|
46
59
|
console.log(` ${output_1.pc.dim("→")} ${cursorColor("[cursor]")} hooks ${output_1.pc.dim("→")} ${output_1.pc.dim(hooksPath)}`);
|
|
47
60
|
console.log(` ${output_1.pc.dim("→")} ${cursorColor("[cursor]")} skill ${output_1.pc.dim("→")} ${output_1.pc.dim(skillPath)}`);
|
|
48
61
|
console.log(` ${output_1.pc.dim("→")} ${cursorColor("[cursor]")} rule ${output_1.pc.dim("→")} ${output_1.pc.dim(rulePath)}`);
|
|
62
|
+
console.log(` ${output_1.pc.dim("→")} ${cursorColor("[cursor]")} command ${output_1.pc.dim("→")} ${output_1.pc.dim(analyzeSkillPath)}`);
|
|
49
63
|
console.log(` ${output_1.pc.dim("→")} ${cursorColor("[cursor]")} mcp ${output_1.pc.dim("→")} ${output_1.pc.dim(mcpPath)}`);
|
|
50
64
|
console.log();
|
|
51
65
|
console.log(` ${output_1.pc.yellow("⚠")} ${output_1.pc.yellow("Cursor requires manual steps:")}`);
|
|
@@ -54,21 +68,28 @@ class CursorClient {
|
|
|
54
68
|
console.log(` ${output_1.pc.yellow("3.")} If the server shows as enabled but tools are unavailable, toggle it off and on`);
|
|
55
69
|
}
|
|
56
70
|
uninstall(projectDir) {
|
|
71
|
+
this.cleanupArtifacts(projectDir);
|
|
72
|
+
console.log(` ${output_1.pc.dim("→")} ${cursorColor("[cursor]")} removed hooks, skill, rule, command, and MCP`);
|
|
73
|
+
console.log();
|
|
74
|
+
console.log(` ${output_1.pc.yellow("⚠")} Restart Cursor to apply changes`);
|
|
75
|
+
}
|
|
76
|
+
cleanupArtifacts(projectDir) {
|
|
57
77
|
const cursorDir = (0, path_1.join)(projectDir, ".cursor");
|
|
58
|
-
// remove skill and
|
|
78
|
+
// remove skill, rule, and command files
|
|
59
79
|
const skillPath = (0, path_1.join)(cursorDir, "skills", "ironbee-verification.md");
|
|
60
80
|
const rulePath = (0, path_1.join)(cursorDir, "rules", "ironbee-verification.mdc");
|
|
81
|
+
const analyzeSkillPath = (0, path_1.join)(cursorDir, "skills", "ironbee-analyze", "SKILL.md");
|
|
82
|
+
const verifySkillPath = (0, path_1.join)(cursorDir, "skills", "ironbee-verify", "SKILL.md");
|
|
61
83
|
this.removeFile(skillPath);
|
|
62
84
|
this.removeFile(rulePath);
|
|
85
|
+
this.removeFile(analyzeSkillPath);
|
|
86
|
+
this.removeFile(verifySkillPath);
|
|
63
87
|
// remove ironbee hooks from hooks.json
|
|
64
88
|
const hooksPath = (0, path_1.join)(cursorDir, "hooks.json");
|
|
65
89
|
this.removeIronBeeHooks(hooksPath);
|
|
66
90
|
// remove browser-devtools from mcp.json
|
|
67
91
|
const mcpPath = (0, path_1.join)(cursorDir, "mcp.json");
|
|
68
92
|
this.removeMcpServer(mcpPath);
|
|
69
|
-
console.log(` ${output_1.pc.dim("→")} ${cursorColor("[cursor]")} removed hooks, skill, rule, and MCP`);
|
|
70
|
-
console.log();
|
|
71
|
-
console.log(` ${output_1.pc.yellow("⚠")} Restart Cursor to apply changes`);
|
|
72
93
|
}
|
|
73
94
|
runVerifyGate(projectDir) {
|
|
74
95
|
(0, verify_gate_1.run)(projectDir);
|
|
@@ -85,6 +106,9 @@ class CursorClient {
|
|
|
85
106
|
runRequireVerdict(projectDir) {
|
|
86
107
|
(0, require_verdict_1.run)(projectDir);
|
|
87
108
|
}
|
|
109
|
+
runRequireVerification(projectDir) {
|
|
110
|
+
(0, require_verification_1.run)(projectDir);
|
|
111
|
+
}
|
|
88
112
|
isIronBeeHook(entry) {
|
|
89
113
|
return entry.command.includes(IRONBEE_HOOK_MARKER);
|
|
90
114
|
}
|
|
@@ -113,10 +137,16 @@ class CursorClient {
|
|
|
113
137
|
config.hooks.sessionStart.push({
|
|
114
138
|
command: `ironbee hook session-start --client cursor`,
|
|
115
139
|
});
|
|
116
|
-
// ── preToolUse — block
|
|
140
|
+
// ── preToolUse — block browser tools if no active verification ──
|
|
117
141
|
if (!config.hooks.preToolUse) {
|
|
118
142
|
config.hooks.preToolUse = [];
|
|
119
143
|
}
|
|
144
|
+
config.hooks.preToolUse.push({
|
|
145
|
+
command: `ironbee hook require-verification --client cursor`,
|
|
146
|
+
matcher: "MCP:bdt_.*",
|
|
147
|
+
failClosed: true,
|
|
148
|
+
});
|
|
149
|
+
// ── preToolUse — block edits if browser tools used without verdict ──
|
|
120
150
|
config.hooks.preToolUse.push({
|
|
121
151
|
command: `ironbee hook require-verdict --client cursor`,
|
|
122
152
|
matcher: "Write",
|
|
@@ -135,7 +165,7 @@ class CursorClient {
|
|
|
135
165
|
}
|
|
136
166
|
config.hooks.postToolUse.push({
|
|
137
167
|
command: `ironbee hook track-action --client cursor`,
|
|
138
|
-
matcher: "MCP
|
|
168
|
+
matcher: "MCP:bdt_.*",
|
|
139
169
|
});
|
|
140
170
|
// ── stop — verify-gate, forces re-verification via followup_message ──
|
|
141
171
|
if (!config.hooks.stop) {
|
|
@@ -185,7 +215,7 @@ class CursorClient {
|
|
|
185
215
|
(0, fs_1.unlinkSync)(filePath);
|
|
186
216
|
}
|
|
187
217
|
}
|
|
188
|
-
writeMcpConfig(mcpPath) {
|
|
218
|
+
writeMcpConfig(mcpPath, projectDir) {
|
|
189
219
|
let config = { mcpServers: {} };
|
|
190
220
|
if ((0, fs_1.existsSync)(mcpPath)) {
|
|
191
221
|
try {
|
|
@@ -199,13 +229,8 @@ class CursorClient {
|
|
|
199
229
|
config = { mcpServers: {} };
|
|
200
230
|
}
|
|
201
231
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
args: ["-y", MCP_SERVER_PACKAGE],
|
|
205
|
-
env: {
|
|
206
|
-
BROWSER_DEVTOOLS_INSTALL_CHROMIUM: "true",
|
|
207
|
-
},
|
|
208
|
-
};
|
|
232
|
+
const mcpEntry = (0, config_1.getMcpServerEntry)(projectDir);
|
|
233
|
+
config.mcpServers[MCP_SERVER_NAME] = mcpEntry;
|
|
209
234
|
(0, fs_1.writeFileSync)(mcpPath, JSON.stringify(config, null, 2));
|
|
210
235
|
}
|
|
211
236
|
}
|