@yasserkhanorg/impact-gate 2.1.1 → 2.1.2

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.
@@ -10,7 +10,7 @@ const LEGACY_TO_CATEGORY = {
10
10
  'ux-issue': 'ux',
11
11
  };
12
12
  const CANONICAL_CATEGORIES = new Set([
13
- 'visual', 'functional', 'ux', 'content', 'performance', 'console', 'accessibility',
13
+ 'visual', 'functional', 'ux', 'content', 'performance', 'console', 'accessibility', 'links',
14
14
  ]);
15
15
  /**
16
16
  * Normalize any FindingType (legacy or canonical) to a canonical FindingCategory.
@@ -46,6 +46,11 @@ export const SEVERITY_DEFINITIONS = {
46
46
  // Category definitions
47
47
  // ---------------------------------------------------------------------------
48
48
  export const CATEGORY_DEFINITIONS = {
49
+ links: {
50
+ label: 'Links',
51
+ description: 'Broken links (404), wrong destinations, dead anchors, external links that fail.',
52
+ examples: ['404 on nav link', 'Link goes to wrong page', 'Anchor target missing', 'External link returns 500'],
53
+ },
49
54
  visual: {
50
55
  label: 'Visual/UI',
51
56
  description: 'Layout breaks, broken images, z-index issues, font/color inconsistencies, animation glitches, alignment issues, dark mode problems.',
@@ -49,7 +49,8 @@ Pick dimensions that matter for THIS flow. Example: for "channel settings" → p
49
49
  ## Finding Categories
50
50
  When reporting findings, use the most specific category:
51
51
  - **visual** — Layout breaks, broken images, z-index issues, alignment, animation glitches, dark mode problems
52
- - **functional** — Broken links, dead buttons, form validation failures, incorrect redirects, race conditions, state not persisting
52
+ - **links** — Broken links (404), wrong destinations, dead anchors, external links that fail
53
+ - **functional** — Dead buttons, form validation failures, incorrect redirects, race conditions, state not persisting
53
54
  - **ux** — Confusing navigation, missing loading indicators, slow interactions (>500ms), unclear error messages, no confirmation before destructive actions
54
55
  - **content** — Typos, grammar errors, placeholder/lorem ipsum left in, truncated text, wrong labels
55
56
  - **performance** — Slow page loads (>3s), janky scrolling, layout shifts (CLS), excessive network requests
@@ -99,7 +99,7 @@ export const TOOL_DEFINITIONS = [
99
99
  input_schema: {
100
100
  type: 'object',
101
101
  properties: {
102
- type: { type: 'string', enum: ['visual', 'functional', 'ux', 'content', 'performance', 'console', 'accessibility', 'bug', 'visual-regression', 'ux-issue', 'gap'] },
102
+ type: { type: 'string', enum: ['visual', 'functional', 'ux', 'content', 'performance', 'console', 'accessibility', 'links', 'bug', 'visual-regression', 'ux-issue', 'gap'] },
103
103
  severity: { type: 'string', enum: ['critical', 'high', 'medium', 'low', 'info'] },
104
104
  summary: { type: 'string', description: 'What you found' },
105
105
  repro_steps: {
@@ -217,7 +217,7 @@ export function executeTool(ctx, name, input) {
217
217
  }
218
218
  case 'report_finding': {
219
219
  const VALID_TYPES = new Set([
220
- 'visual', 'functional', 'ux', 'content', 'performance', 'console', 'accessibility',
220
+ 'visual', 'functional', 'ux', 'content', 'performance', 'console', 'accessibility', 'links',
221
221
  'bug', 'visual-regression', 'ux-issue', 'gap',
222
222
  ]);
223
223
  const VALID_SEVERITIES = new Set(['critical', 'high', 'medium', 'low', 'info']);
@@ -91,6 +91,7 @@ export async function runFixLoop(config, findings, browser, projectRoot) {
91
91
  baseUrl: config.baseUrl,
92
92
  screenshotDir,
93
93
  screenshotCounter: 100, // Start at 100 to avoid collisions with Phase 2 screenshots
94
+ qaCommitHashes: new Set(),
94
95
  };
95
96
  for (const finding of fixable) {
96
97
  if (wtf.shouldStop()) {
@@ -111,7 +112,10 @@ export async function runFixLoop(config, findings, browser, projectRoot) {
111
112
  costUSD += result.costUSD;
112
113
  wtf.recordAttempt(result.fix.status, result.fix.filesChanged?.length || 0);
113
114
  }
114
- const healthScoreAfter = computeHealthScore(findings);
115
+ // Exclude verified fixes from the post-fix score so it reflects actual remaining issues
116
+ const verifiedIds = new Set(fixes.filter((f) => f.status === 'verified').map((f) => f.findingId));
117
+ const remainingFindings = findings.filter((f) => !verifiedIds.has(f.id));
118
+ const healthScoreAfter = computeHealthScore(remainingFindings);
115
119
  return {
116
120
  fixes,
117
121
  fixesAttempted: fixes.filter((f) => f.status !== 'skipped').length,
@@ -134,6 +138,7 @@ async function fixSingleFinding(client, model, config, finding, toolCtx) {
134
138
  let filesChanged = [];
135
139
  let beforeScreenshot;
136
140
  let afterScreenshot;
141
+ let verifiedFixed = false;
137
142
  let status = 'skipped';
138
143
  // Take "before" screenshot
139
144
  try {
@@ -176,9 +181,10 @@ async function fixSingleFinding(client, model, config, finding, toolCtx) {
176
181
  // If no tool use, the agent is done
177
182
  const toolUseBlocks = assistantContent.filter((b) => b.type === 'tool_use');
178
183
  if (toolUseBlocks.length === 0) {
179
- // Determine status from what happened
184
+ // Determine status: 'verified' requires both a commit and explicit confirmation
185
+ // from verify_in_browser that the bug is gone. A screenshot alone is not proof.
180
186
  if (commitHash) {
181
- status = afterScreenshot ? 'verified' : 'best-effort';
187
+ status = verifiedFixed ? 'verified' : 'best-effort';
182
188
  }
183
189
  break;
184
190
  }
@@ -194,8 +200,13 @@ async function fixSingleFinding(client, model, config, finding, toolCtx) {
194
200
  if (result.filesChanged) {
195
201
  filesChanged = [...filesChanged, ...result.filesChanged];
196
202
  }
197
- if (result.screenshotPath && block.name === 'verify_in_browser') {
198
- afterScreenshot = result.screenshotPath;
203
+ if (block.name === 'verify_in_browser') {
204
+ if (result.screenshotPath) {
205
+ afterScreenshot = result.screenshotPath;
206
+ }
207
+ if (result.verifiedFixed === true) {
208
+ verifiedFixed = true;
209
+ }
199
210
  }
200
211
  if (block.name === 'git_revert') {
201
212
  status = 'reverted';
@@ -82,14 +82,15 @@ export const FIX_TOOL_DEFINITIONS = [
82
82
  },
83
83
  {
84
84
  name: 'verify_in_browser',
85
- description: 'Navigate to a URL and take a screenshot to verify a fix. Returns the screenshot path and any console errors.',
85
+ description: 'Navigate to a URL, take a screenshot, and report whether the fix resolved the issue. You MUST set fixed=true only if the original bug is no longer present. Set fixed=false if the bug still reproduces or if you cannot confirm.',
86
86
  input_schema: {
87
87
  type: 'object',
88
88
  properties: {
89
89
  url: { type: 'string', description: 'URL to navigate to for verification' },
90
90
  label: { type: 'string', description: 'Label for the screenshot (e.g. "after-fix-001")' },
91
+ fixed: { type: 'boolean', description: 'true if the original bug is gone, false if it still reproduces or uncertain' },
91
92
  },
92
- required: ['url', 'label'],
93
+ required: ['url', 'label', 'fixed'],
93
94
  },
94
95
  },
95
96
  ];
@@ -216,6 +217,7 @@ export function executeFixTool(ctx, name, input) {
216
217
  execFileSync('git', ['add', ...files], { cwd: ctx.projectRoot, encoding: 'utf-8' });
217
218
  execFileSync('git', ['commit', '-m', message], { cwd: ctx.projectRoot, encoding: 'utf-8' });
218
219
  const hash = execFileSync('git', ['rev-parse', '--short', 'HEAD'], { cwd: ctx.projectRoot, encoding: 'utf-8' }).trim();
220
+ ctx.qaCommitHashes.add(hash);
219
221
  return { output: `Committed: ${hash} — ${message}`, commitHash: hash, filesChanged: files };
220
222
  }
221
223
  catch (err) {
@@ -224,10 +226,16 @@ export function executeFixTool(ctx, name, input) {
224
226
  }
225
227
  }
226
228
  case 'git_revert': {
229
+ // Safety: only revert commits created by the fix loop
230
+ const currentHead = execFileSync('git', ['rev-parse', '--short', 'HEAD'], { cwd: ctx.projectRoot, encoding: 'utf-8' }).trim();
231
+ if (!ctx.qaCommitHashes.has(currentHead)) {
232
+ return { output: `Blocked: HEAD (${currentHead}) was not created by the fix loop. Refusing to revert a user commit.` };
233
+ }
227
234
  try {
228
235
  execFileSync('git', ['revert', '--no-edit', 'HEAD'], { cwd: ctx.projectRoot, encoding: 'utf-8' });
229
- const hash = execFileSync('git', ['rev-parse', '--short', 'HEAD'], { cwd: ctx.projectRoot, encoding: 'utf-8' }).trim();
230
- return { output: `Reverted HEAD. New HEAD: ${hash}`, commitHash: hash };
236
+ ctx.qaCommitHashes.delete(currentHead);
237
+ const newHash = execFileSync('git', ['rev-parse', '--short', 'HEAD'], { cwd: ctx.projectRoot, encoding: 'utf-8' }).trim();
238
+ return { output: `Reverted ${currentHead}. New HEAD: ${newHash}`, commitHash: newHash };
231
239
  }
232
240
  catch (err) {
233
241
  const error = err;
@@ -254,7 +262,9 @@ export function executeFixTool(ctx, name, input) {
254
262
  catch {
255
263
  // Not available
256
264
  }
257
- return { output: `Screenshot saved: ${screenshotPath}${consoleErrors}`, screenshotPath };
265
+ const fixed = input.fixed === true;
266
+ const verdict = fixed ? 'Bug appears resolved.' : 'Bug still reproduces or unconfirmed.';
267
+ return { output: `Screenshot saved: ${screenshotPath}. ${verdict}${consoleErrors}`, screenshotPath, verifiedFixed: fixed };
258
268
  }
259
269
  default:
260
270
  return { output: `Unknown fix tool: ${name}` };
@@ -55,18 +55,25 @@ export function loadBaseline(outputDir) {
55
55
  /**
56
56
  * Compare current findings against a saved baseline.
57
57
  */
58
+ /**
59
+ * Build a fingerprint for a finding that includes flow, type, and summary
60
+ * to avoid collapsing distinct issues with the same generic summary.
61
+ */
62
+ function issueFingerprint(issue) {
63
+ return `${issue.flow}|${issue.type}|${issue.summary}`.toLowerCase();
64
+ }
58
65
  export function compareBaselines(currentScore, currentFindings, baseline) {
59
- const baselineIssueIds = new Set(baseline.issues.map((i) => i.summary.toLowerCase()));
60
- const currentIssueIds = new Set(currentFindings
66
+ const baselineFingerprints = new Set(baseline.issues.map((i) => issueFingerprint(i)));
67
+ const currentFingerprints = new Set(currentFindings
61
68
  .filter((f) => f.type !== 'verified-ok')
62
- .map((f) => f.summary.toLowerCase()));
69
+ .map((f) => issueFingerprint(f)));
63
70
  // Issues in baseline but not in current = fixed
64
71
  const fixedIssues = baseline.issues
65
- .filter((i) => !currentIssueIds.has(i.summary.toLowerCase()))
72
+ .filter((i) => !currentFingerprints.has(issueFingerprint(i)))
66
73
  .map((i) => `${i.id}: ${i.summary}`);
67
74
  // Issues in current but not in baseline = new
68
75
  const newIssues = currentFindings
69
- .filter((f) => f.type !== 'verified-ok' && !baselineIssueIds.has(f.summary.toLowerCase()))
76
+ .filter((f) => f.type !== 'verified-ok' && !baselineFingerprints.has(issueFingerprint(f)))
70
77
  .map((f) => `${f.id}: ${f.summary}`);
71
78
  // Category deltas
72
79
  const categoryDeltas = {};
@@ -1 +1 @@
1
- {"version":3,"file":"finding_taxonomy.d.ts","sourceRoot":"","sources":["../../src/qa-agent/finding_taxonomy.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,OAAO,EAAE,mBAAmB,EAAC,MAAM,YAAY,CAAC;AAiBrH;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAKjE;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,WAAW,GAAG,mBAAmB,CAK/E;AAMD,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAMhE,CAAC;AAMF,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,eAAe,EAAE;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAC,CAoClH,CAAC;AAYF;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAKlE"}
1
+ {"version":3,"file":"finding_taxonomy.d.ts","sourceRoot":"","sources":["../../src/qa-agent/finding_taxonomy.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,OAAO,EAAE,mBAAmB,EAAC,MAAM,YAAY,CAAC;AAiBrH;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAKjE;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,WAAW,GAAG,mBAAmB,CAK/E;AAMD,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAMhE,CAAC;AAMF,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,eAAe,EAAE;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAC,CAyClH,CAAC;AAYF;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAKlE"}
@@ -16,7 +16,7 @@ const LEGACY_TO_CATEGORY = {
16
16
  'ux-issue': 'ux',
17
17
  };
18
18
  const CANONICAL_CATEGORIES = new Set([
19
- 'visual', 'functional', 'ux', 'content', 'performance', 'console', 'accessibility',
19
+ 'visual', 'functional', 'ux', 'content', 'performance', 'console', 'accessibility', 'links',
20
20
  ]);
21
21
  /**
22
22
  * Normalize any FindingType (legacy or canonical) to a canonical FindingCategory.
@@ -52,6 +52,11 @@ exports.SEVERITY_DEFINITIONS = {
52
52
  // Category definitions
53
53
  // ---------------------------------------------------------------------------
54
54
  exports.CATEGORY_DEFINITIONS = {
55
+ links: {
56
+ label: 'Links',
57
+ description: 'Broken links (404), wrong destinations, dead anchors, external links that fail.',
58
+ examples: ['404 on nav link', 'Link goes to wrong page', 'Anchor target missing', 'External link returns 500'],
59
+ },
55
60
  visual: {
56
61
  label: 'Visual/UI',
57
62
  description: 'Layout breaks, broken images, z-index issues, font/color inconsistencies, animation glitches, alignment issues, dark mode problems.',
@@ -1 +1 @@
1
- {"version":3,"file":"agent_loop.d.ts","sourceRoot":"","sources":["../../../src/qa-agent/phase2/agent_loop.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAA2C,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAC,MAAM,aAAa,CAAC;AAuJ9G,wBAAsB,YAAY,CAC9B,MAAM,EAAE,QAAQ,EAChB,KAAK,EAAE,UAAU,EAAE,GACpB,OAAO,CAAC,YAAY,CAAC,CAyOvB"}
1
+ {"version":3,"file":"agent_loop.d.ts","sourceRoot":"","sources":["../../../src/qa-agent/phase2/agent_loop.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAA2C,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAC,MAAM,aAAa,CAAC;AAwJ9G,wBAAsB,YAAY,CAC9B,MAAM,EAAE,QAAQ,EAChB,KAAK,EAAE,UAAU,EAAE,GACpB,OAAO,CAAC,YAAY,CAAC,CAyOvB"}
@@ -55,7 +55,8 @@ Pick dimensions that matter for THIS flow. Example: for "channel settings" → p
55
55
  ## Finding Categories
56
56
  When reporting findings, use the most specific category:
57
57
  - **visual** — Layout breaks, broken images, z-index issues, alignment, animation glitches, dark mode problems
58
- - **functional** — Broken links, dead buttons, form validation failures, incorrect redirects, race conditions, state not persisting
58
+ - **links** — Broken links (404), wrong destinations, dead anchors, external links that fail
59
+ - **functional** — Dead buttons, form validation failures, incorrect redirects, race conditions, state not persisting
59
60
  - **ux** — Confusing navigation, missing loading indicators, slow interactions (>500ms), unclear error messages, no confirmation before destructive actions
60
61
  - **content** — Typos, grammar errors, placeholder/lorem ipsum left in, truncated text, wrong labels
61
62
  - **performance** — Slow page loads (>3s), janky scrolling, layout shifts (CLS), excessive network requests
@@ -103,7 +103,7 @@ exports.TOOL_DEFINITIONS = [
103
103
  input_schema: {
104
104
  type: 'object',
105
105
  properties: {
106
- type: { type: 'string', enum: ['visual', 'functional', 'ux', 'content', 'performance', 'console', 'accessibility', 'bug', 'visual-regression', 'ux-issue', 'gap'] },
106
+ type: { type: 'string', enum: ['visual', 'functional', 'ux', 'content', 'performance', 'console', 'accessibility', 'links', 'bug', 'visual-regression', 'ux-issue', 'gap'] },
107
107
  severity: { type: 'string', enum: ['critical', 'high', 'medium', 'low', 'info'] },
108
108
  summary: { type: 'string', description: 'What you found' },
109
109
  repro_steps: {
@@ -221,7 +221,7 @@ function executeTool(ctx, name, input) {
221
221
  }
222
222
  case 'report_finding': {
223
223
  const VALID_TYPES = new Set([
224
- 'visual', 'functional', 'ux', 'content', 'performance', 'console', 'accessibility',
224
+ 'visual', 'functional', 'ux', 'content', 'performance', 'console', 'accessibility', 'links',
225
225
  'bug', 'visual-regression', 'ux-issue', 'gap',
226
226
  ]);
227
227
  const VALID_SEVERITIES = new Set(['critical', 'high', 'medium', 'low', 'info']);
@@ -1 +1 @@
1
- {"version":3,"file":"fix_loop.d.ts","sourceRoot":"","sources":["../../../src/qa-agent/phase25/fix_loop.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,OAAO,EAAqC,aAAa,EAAE,QAAQ,EAAC,MAAM,aAAa,CAAC;AACrG,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,4BAA4B,CAAC;AAuD7D,wBAAsB,UAAU,CAC5B,MAAM,EAAE,QAAQ,EAChB,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,MAAM,GACpB,OAAO,CAAC,aAAa,CAAC,CAwFxB"}
1
+ {"version":3,"file":"fix_loop.d.ts","sourceRoot":"","sources":["../../../src/qa-agent/phase25/fix_loop.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,OAAO,EAAqC,aAAa,EAAE,QAAQ,EAAC,MAAM,aAAa,CAAC;AACrG,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,4BAA4B,CAAC;AAuD7D,wBAAsB,UAAU,CAC5B,MAAM,EAAE,QAAQ,EAChB,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,MAAM,GACpB,OAAO,CAAC,aAAa,CAAC,CA4FxB"}
@@ -97,6 +97,7 @@ async function runFixLoop(config, findings, browser, projectRoot) {
97
97
  baseUrl: config.baseUrl,
98
98
  screenshotDir,
99
99
  screenshotCounter: 100, // Start at 100 to avoid collisions with Phase 2 screenshots
100
+ qaCommitHashes: new Set(),
100
101
  };
101
102
  for (const finding of fixable) {
102
103
  if (wtf.shouldStop()) {
@@ -117,7 +118,10 @@ async function runFixLoop(config, findings, browser, projectRoot) {
117
118
  costUSD += result.costUSD;
118
119
  wtf.recordAttempt(result.fix.status, result.fix.filesChanged?.length || 0);
119
120
  }
120
- const healthScoreAfter = (0, health_score_js_1.computeHealthScore)(findings);
121
+ // Exclude verified fixes from the post-fix score so it reflects actual remaining issues
122
+ const verifiedIds = new Set(fixes.filter((f) => f.status === 'verified').map((f) => f.findingId));
123
+ const remainingFindings = findings.filter((f) => !verifiedIds.has(f.id));
124
+ const healthScoreAfter = (0, health_score_js_1.computeHealthScore)(remainingFindings);
121
125
  return {
122
126
  fixes,
123
127
  fixesAttempted: fixes.filter((f) => f.status !== 'skipped').length,
@@ -140,6 +144,7 @@ async function fixSingleFinding(client, model, config, finding, toolCtx) {
140
144
  let filesChanged = [];
141
145
  let beforeScreenshot;
142
146
  let afterScreenshot;
147
+ let verifiedFixed = false;
143
148
  let status = 'skipped';
144
149
  // Take "before" screenshot
145
150
  try {
@@ -182,9 +187,10 @@ async function fixSingleFinding(client, model, config, finding, toolCtx) {
182
187
  // If no tool use, the agent is done
183
188
  const toolUseBlocks = assistantContent.filter((b) => b.type === 'tool_use');
184
189
  if (toolUseBlocks.length === 0) {
185
- // Determine status from what happened
190
+ // Determine status: 'verified' requires both a commit and explicit confirmation
191
+ // from verify_in_browser that the bug is gone. A screenshot alone is not proof.
186
192
  if (commitHash) {
187
- status = afterScreenshot ? 'verified' : 'best-effort';
193
+ status = verifiedFixed ? 'verified' : 'best-effort';
188
194
  }
189
195
  break;
190
196
  }
@@ -200,8 +206,13 @@ async function fixSingleFinding(client, model, config, finding, toolCtx) {
200
206
  if (result.filesChanged) {
201
207
  filesChanged = [...filesChanged, ...result.filesChanged];
202
208
  }
203
- if (result.screenshotPath && block.name === 'verify_in_browser') {
204
- afterScreenshot = result.screenshotPath;
209
+ if (block.name === 'verify_in_browser') {
210
+ if (result.screenshotPath) {
211
+ afterScreenshot = result.screenshotPath;
212
+ }
213
+ if (result.verifiedFixed === true) {
214
+ verifiedFixed = true;
215
+ }
205
216
  }
206
217
  if (block.name === 'git_revert') {
207
218
  status = 'reverted';
@@ -7,12 +7,16 @@ export interface FixToolContext {
7
7
  baseUrl: string;
8
8
  screenshotDir: string;
9
9
  screenshotCounter: number;
10
+ /** Commit hashes created by the fix loop. Only these can be reverted. */
11
+ qaCommitHashes: Set<string>;
10
12
  }
11
13
  export interface FixToolResult {
12
14
  output: string;
13
15
  filesChanged?: string[];
14
16
  commitHash?: string;
15
17
  screenshotPath?: string;
18
+ /** Explicit verification signal from verify_in_browser */
19
+ verifiedFixed?: boolean;
16
20
  }
17
21
  export declare function executeFixTool(ctx: FixToolContext, name: string, input: Record<string, unknown>): FixToolResult;
18
22
  //# sourceMappingURL=fix_tools.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fix_tools.d.ts","sourceRoot":"","sources":["../../../src/qa-agent/phase25/fix_tools.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAE/C,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,4BAA4B,CAAC;AAM7D,eAAO,MAAM,oBAAoB,EAAE,SAAS,CAAC,IAAI,EAsFhD,CAAC;AAMF,MAAM,WAAW,cAAc;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AA2CD,wBAAgB,cAAc,CAC1B,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,aAAa,CA2If"}
1
+ {"version":3,"file":"fix_tools.d.ts","sourceRoot":"","sources":["../../../src/qa-agent/phase25/fix_tools.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAE/C,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,4BAA4B,CAAC;AAM7D,eAAO,MAAM,oBAAoB,EAAE,SAAS,CAAC,IAAI,EAuFhD,CAAC;AAMF,MAAM,WAAW,cAAc;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,yEAAyE;IACzE,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AA2CD,wBAAgB,cAAc,CAC1B,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,aAAa,CAoJf"}
@@ -86,14 +86,15 @@ exports.FIX_TOOL_DEFINITIONS = [
86
86
  },
87
87
  {
88
88
  name: 'verify_in_browser',
89
- description: 'Navigate to a URL and take a screenshot to verify a fix. Returns the screenshot path and any console errors.',
89
+ description: 'Navigate to a URL, take a screenshot, and report whether the fix resolved the issue. You MUST set fixed=true only if the original bug is no longer present. Set fixed=false if the bug still reproduces or if you cannot confirm.',
90
90
  input_schema: {
91
91
  type: 'object',
92
92
  properties: {
93
93
  url: { type: 'string', description: 'URL to navigate to for verification' },
94
94
  label: { type: 'string', description: 'Label for the screenshot (e.g. "after-fix-001")' },
95
+ fixed: { type: 'boolean', description: 'true if the original bug is gone, false if it still reproduces or uncertain' },
95
96
  },
96
- required: ['url', 'label'],
97
+ required: ['url', 'label', 'fixed'],
97
98
  },
98
99
  },
99
100
  ];
@@ -220,6 +221,7 @@ function executeFixTool(ctx, name, input) {
220
221
  (0, child_process_1.execFileSync)('git', ['add', ...files], { cwd: ctx.projectRoot, encoding: 'utf-8' });
221
222
  (0, child_process_1.execFileSync)('git', ['commit', '-m', message], { cwd: ctx.projectRoot, encoding: 'utf-8' });
222
223
  const hash = (0, child_process_1.execFileSync)('git', ['rev-parse', '--short', 'HEAD'], { cwd: ctx.projectRoot, encoding: 'utf-8' }).trim();
224
+ ctx.qaCommitHashes.add(hash);
223
225
  return { output: `Committed: ${hash} — ${message}`, commitHash: hash, filesChanged: files };
224
226
  }
225
227
  catch (err) {
@@ -228,10 +230,16 @@ function executeFixTool(ctx, name, input) {
228
230
  }
229
231
  }
230
232
  case 'git_revert': {
233
+ // Safety: only revert commits created by the fix loop
234
+ const currentHead = (0, child_process_1.execFileSync)('git', ['rev-parse', '--short', 'HEAD'], { cwd: ctx.projectRoot, encoding: 'utf-8' }).trim();
235
+ if (!ctx.qaCommitHashes.has(currentHead)) {
236
+ return { output: `Blocked: HEAD (${currentHead}) was not created by the fix loop. Refusing to revert a user commit.` };
237
+ }
231
238
  try {
232
239
  (0, child_process_1.execFileSync)('git', ['revert', '--no-edit', 'HEAD'], { cwd: ctx.projectRoot, encoding: 'utf-8' });
233
- const hash = (0, child_process_1.execFileSync)('git', ['rev-parse', '--short', 'HEAD'], { cwd: ctx.projectRoot, encoding: 'utf-8' }).trim();
234
- return { output: `Reverted HEAD. New HEAD: ${hash}`, commitHash: hash };
240
+ ctx.qaCommitHashes.delete(currentHead);
241
+ const newHash = (0, child_process_1.execFileSync)('git', ['rev-parse', '--short', 'HEAD'], { cwd: ctx.projectRoot, encoding: 'utf-8' }).trim();
242
+ return { output: `Reverted ${currentHead}. New HEAD: ${newHash}`, commitHash: newHash };
235
243
  }
236
244
  catch (err) {
237
245
  const error = err;
@@ -258,7 +266,9 @@ function executeFixTool(ctx, name, input) {
258
266
  catch {
259
267
  // Not available
260
268
  }
261
- return { output: `Screenshot saved: ${screenshotPath}${consoleErrors}`, screenshotPath };
269
+ const fixed = input.fixed === true;
270
+ const verdict = fixed ? 'Bug appears resolved.' : 'Bug still reproduces or unconfirmed.';
271
+ return { output: `Screenshot saved: ${screenshotPath}. ${verdict}${consoleErrors}`, screenshotPath, verifiedFixed: fixed };
262
272
  }
263
273
  default:
264
274
  return { output: `Unknown fix tool: ${name}` };
@@ -7,8 +7,5 @@ export declare function saveBaseline(outputDir: string, healthScore: HealthScore
7
7
  * Load a previously saved baseline. Returns null if no baseline exists.
8
8
  */
9
9
  export declare function loadBaseline(outputDir: string): RegressionBaseline | null;
10
- /**
11
- * Compare current findings against a saved baseline.
12
- */
13
10
  export declare function compareBaselines(currentScore: HealthScore, currentFindings: Finding[], baseline: RegressionBaseline): RegressionComparison;
14
11
  //# sourceMappingURL=baseline.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"baseline.d.ts","sourceRoot":"","sources":["../../../src/qa-agent/regression/baseline.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,oBAAoB,EAAsB,MAAM,aAAa,CAAC;AAKrH;;GAEG;AACH,wBAAgB,YAAY,CACxB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,OAAO,EAAE,EACnB,GAAG,EAAE,MAAM,GACZ,IAAI,CA2BN;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAazE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC5B,YAAY,EAAE,WAAW,EACzB,eAAe,EAAE,OAAO,EAAE,EAC1B,QAAQ,EAAE,kBAAkB,GAC7B,oBAAoB,CAqCtB"}
1
+ {"version":3,"file":"baseline.d.ts","sourceRoot":"","sources":["../../../src/qa-agent/regression/baseline.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,oBAAoB,EAAsB,MAAM,aAAa,CAAC;AAKrH;;GAEG;AACH,wBAAgB,YAAY,CACxB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,OAAO,EAAE,EACnB,GAAG,EAAE,MAAM,GACZ,IAAI,CA2BN;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAazE;AAaD,wBAAgB,gBAAgB,CAC5B,YAAY,EAAE,WAAW,EACzB,eAAe,EAAE,OAAO,EAAE,EAC1B,QAAQ,EAAE,kBAAkB,GAC7B,oBAAoB,CAqCtB"}
@@ -60,18 +60,25 @@ function loadBaseline(outputDir) {
60
60
  /**
61
61
  * Compare current findings against a saved baseline.
62
62
  */
63
+ /**
64
+ * Build a fingerprint for a finding that includes flow, type, and summary
65
+ * to avoid collapsing distinct issues with the same generic summary.
66
+ */
67
+ function issueFingerprint(issue) {
68
+ return `${issue.flow}|${issue.type}|${issue.summary}`.toLowerCase();
69
+ }
63
70
  function compareBaselines(currentScore, currentFindings, baseline) {
64
- const baselineIssueIds = new Set(baseline.issues.map((i) => i.summary.toLowerCase()));
65
- const currentIssueIds = new Set(currentFindings
71
+ const baselineFingerprints = new Set(baseline.issues.map((i) => issueFingerprint(i)));
72
+ const currentFingerprints = new Set(currentFindings
66
73
  .filter((f) => f.type !== 'verified-ok')
67
- .map((f) => f.summary.toLowerCase()));
74
+ .map((f) => issueFingerprint(f)));
68
75
  // Issues in baseline but not in current = fixed
69
76
  const fixedIssues = baseline.issues
70
- .filter((i) => !currentIssueIds.has(i.summary.toLowerCase()))
77
+ .filter((i) => !currentFingerprints.has(issueFingerprint(i)))
71
78
  .map((i) => `${i.id}: ${i.summary}`);
72
79
  // Issues in current but not in baseline = new
73
80
  const newIssues = currentFindings
74
- .filter((f) => f.type !== 'verified-ok' && !baselineIssueIds.has(f.summary.toLowerCase()))
81
+ .filter((f) => f.type !== 'verified-ok' && !baselineFingerprints.has(issueFingerprint(f)))
75
82
  .map((f) => `${f.id}: ${f.summary}`);
76
83
  // Category deltas
77
84
  const categoryDeltas = {};
@@ -31,7 +31,7 @@ export interface BrowserAction {
31
31
  timestamp: number;
32
32
  }
33
33
  /** Canonical finding categories (v1.1) */
34
- export type FindingCategory = 'visual' | 'functional' | 'ux' | 'content' | 'performance' | 'console' | 'accessibility';
34
+ export type FindingCategory = 'visual' | 'functional' | 'ux' | 'content' | 'performance' | 'console' | 'accessibility' | 'links';
35
35
  /** Legacy finding types kept for backward compatibility */
36
36
  export type LegacyFindingType = 'bug' | 'visual-regression' | 'ux-issue' | 'gap' | 'verified-ok';
37
37
  /** Accepts both canonical categories and legacy type names */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/qa-agent/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/qa-agent/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yasserkhanorg/impact-gate",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "description": "Diff-aware E2E impact analysis and coverage gating for Playwright/Cypress teams. Optional AI features can suggest, generate, and heal tests once your project has a route-families.json manifest.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/esm/index.js",