Skip to content

feat: pattern guards, reanalyze-and-wait, and overview noise tuning#13

Merged
alerizzo merged 3 commits into
mainfrom
feat/pattern-reanalyze-overview
Jun 3, 2026
Merged

feat: pattern guards, reanalyze-and-wait, and overview noise tuning#13
alerizzo merged 3 commits into
mainfrom
feat/pattern-reanalyze-overview

Conversation

@alerizzo
Copy link
Copy Markdown
Collaborator

@alerizzo alerizzo commented Jun 3, 2026

Summary

Bundles three CLI improvements that were developed together on the same working tree (three changesets included):

  • Pattern config-file & coding-standard awarenesspattern <tool> <id> now shows pattern info (same card as patterns, --output json supported). pattern/patterns skip listing and refuse updates when a tool uses a local config file; pattern refuses to modify coding-standard-enforced patterns. The issues --overview noise suggestions adapt per pattern: a runnable codacy pattern … --disable command when possible, otherwise a manual "update your config file / coding standard" step.
  • --reanalyze-and-wait (-w) — blocking reanalysis variant for repository and pull-request: triggers analysis, polls to completion (10s interval, 20min cap), then prints issue deltas by pattern/severity/category. New src/utils/reanalyze-wait.ts.
  • issues --overview polish — human-friendly False Positives labels and the noisy-pattern detection that seeds the suggestions above.

Shared printPatternCard/PATTERN_JSON_FIELDS moved into src/utils/formatting.ts so both pattern commands render identically.

Test plan

  • npm run check-types
  • npm test (371 tests)
  • npm run build
  • Spot-check codacy pattern <gh> <org> <repo> <tool> <id> (info), --disable on a config-file tool and on a standard-enforced pattern, and issues --overview on a repo with a config-file-driven noisy tool

🤖 Generated with Claude Code

Bundles three CLI improvements that were developed together:

- pattern config-file & coding-standard awareness: new `pattern <tool>
  <id>` info mode (same card as `patterns`); `pattern`/`patterns` skip
  listing and refuse updates when a tool uses a local config file;
  `pattern` refuses to modify coding-standard-enforced patterns; the
  `issues --overview` noise suggestions render a manual "update your
  config file / coding standard" step instead of a command when a
  pattern can't be disabled via the CLI.

- `--reanalyze-and-wait` (`-w`) blocking variant for `repository` and
  `pull-request`: triggers a reanalysis, polls to completion, and prints
  issue deltas by pattern/severity/category (new utils/reanalyze-wait.ts).

- `issues --overview` polish: human-friendly False Positives labels and
  the noisy-pattern detection that seeds the suggestions above.

Shared `printPatternCard`/`PATTERN_JSON_FIELDS` moved into
utils/formatting.ts so both pattern commands render identically.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 3, 2026 08:45
@codacy-production
Copy link
Copy Markdown

codacy-production Bot commented Jun 3, 2026

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 124 complexity · 27 duplication

Metric Results
Complexity 124
Duplication 27

View in Codacy

AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.

Run reviewer

TIP This summary will be updated as you push new changes.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces several enhancements to the Codacy Cloud CLI, including a blocking --reanalyze-and-wait (-w) option for the repository and pull-request commands, improved noise-reduction suggestions and human-friendly labels in issues --overview, and local configuration file and coding standard guards for pattern commands. The review feedback is highly constructive and should be addressed: first, optimize buildNoiseSuggestions by slicing the noisy patterns list to MAX_NOISE_SUGGESTIONS before initiating concurrent network requests; second, wrap the polling requests in pollForAnalysis in a try/catch block to make the CLI resilient to transient network errors during long-running analyses.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/commands/issues.ts
Comment on lines +292 to +340
async function buildNoiseSuggestions(
noisy: PatternsCount[],
globalTools: Tool[],
repoTools: AnalysisTool[],
ctx: { provider: string; organization: string; repository: string },
): Promise<NoiseSuggestion[]> {
const results = await Promise.all(
noisy.map(async (pattern): Promise<NoiseSuggestion | null> => {
const tool = resolvePatternTool(pattern.id, globalTools);
if (!tool) return null; // can't identify the tool — discard silently
// The `pattern` command matches the tool by name; hyphenate spaces per its convention.
const toolToken = tool.name.replace(/\s+/g, "-");
const repoTool = findRepoTool(repoTools, tool);

// A local configuration file overrides Codacy-side pattern config, so the
// pattern must be disabled in that file rather than via the CLI.
if (repoTool?.settings.usesConfigurationFile) {
return {
title: pattern.title,
total: pattern.total,
action: `Update your local ${tool.name} configuration file to disable the pattern`,
};
}

// A pattern enforced by a coding standard must be changed in the standard.
if (repoTool) {
const standards = await fetchPatternStandards(
ctx,
repoTool.uuid,
pattern.id,
);
if (standards.length > 0) {
return {
title: pattern.title,
total: pattern.total,
action: `Update ${standards.join(", ")} to disable the pattern`,
};
}
}

return {
title: pattern.title,
total: pattern.total,
command: `codacy pattern ${toolToken} ${pattern.id} --disable`,
};
}),
);
return results.filter((s): s is NoiseSuggestion => s !== null);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Efficiency Issue: Redundant Concurrent API Requests

Currently, buildNoiseSuggestions maps over all noisy patterns in noisy and triggers concurrent asynchronous calls to fetchPatternStandards (which makes network requests to listRepositoryToolPatterns) for every single one of them.

However, printNoiseSuggestions only displays up to MAX_NOISE_SUGGESTIONS (10) suggestions. If a repository has dozens of noisy patterns, this results in a large number of redundant network requests.

Recommendation

We can optimize this by:

  1. Synchronously resolving the tools first using globalTools.
  2. Filtering out patterns with unresolvable tools.
  3. Slicing the candidate list to MAX_NOISE_SUGGESTIONS before performing any asynchronous network calls. This avoids template literals with backticks in the suggestion to adhere to the strict formatting rules.
async function buildNoiseSuggestions(
  noisy: PatternsCount[],
  globalTools: Tool[],
  repoTools: AnalysisTool[],
  ctx: { provider: string; organization: string; repository: string },
): Promise<NoiseSuggestion[]> {
  // First, resolve tools synchronously and filter out patterns with unresolvable tools
  const patternsWithTools = noisy
    .map((pattern) => {
      const tool = resolvePatternTool(pattern.id, globalTools);
      return { pattern, tool };
    })
    .filter((item): item is { pattern: PatternsCount; tool: Tool } => item.tool !== undefined && item.tool !== null);

  // Since we only display up to MAX_NOISE_SUGGESTIONS, slice the list before making asynchronous API calls
  const candidates = patternsWithTools.slice(0, MAX_NOISE_SUGGESTIONS);

  const results = await Promise.all(
    candidates.map(async ({ pattern, tool }): Promise<NoiseSuggestion> => {
      const toolToken = tool.name.replace(/\s+/g, "-");
      const repoTool = findRepoTool(repoTools, tool);

      // A local configuration file overrides Codacy-side pattern config, so the
      // pattern must be disabled in that file rather than via the CLI.
      if (repoTool?.settings.usesConfigurationFile) {
        return {
          title: pattern.title,
          total: pattern.total,
          action: "Update your local " + tool.name + " configuration file to disable the pattern",
        };
      }

      // A pattern enforced by a coding standard must be changed in the standard.
      if (repoTool) {
        const standards = await fetchPatternStandards(
          ctx,
          repoTool.uuid,
          pattern.id,
        );
        if (standards.length > 0) {
          return {
            title: pattern.title,
            total: pattern.total,
            action: "Update " + standards.join(", ") + " to disable the pattern",
          };
        }
      }

      return {
        title: pattern.title,
        total: pattern.total,
        command: "codacy pattern " + toolToken + " " + pattern.id + " --disable",
      };
    }),
  );
  return results;
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call — done. buildNoiseSuggestions now resolves each pattern's owning tool synchronously, drops the unresolvable ones, and slices to MAX_NOISE_SUGGESTIONS before issuing any listRepositoryToolPatterns calls — so we never fetch coding-standard status for patterns we won't display. The "… (N more)" hint is preserved via the pre-slice resolvable count.

🤖 Generated by /pr-fixup command

Comment on lines +304 to +319
// Phase A — wait until the new analysis starts (or has already finished).
while (!inProgress(status) && !done(status)) {
if (timedOut()) return { status, timedOut: true };
await timers.sleep(pollMs);
status = await getStatus();
}

// Phase B — analysis is running; wait for it to finish.
if (!done(status)) {
spinner.text = "Analysis in progress. This may take a few minutes...";
while (!done(status)) {
if (timedOut()) return { status, timedOut: true };
await timers.sleep(pollMs);
status = await getStatus();
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Resilience: Handle Transient Network Errors During Polling

When polling for analysis completion (which can take up to 20 minutes), transient network glitches, rate limits, or temporary server issues are highly likely to occur.

Currently, if getStatus() throws an error during polling, the entire CLI process will crash immediately. Wrapping the polling calls inside the loops in a try/catch block will make the CLI resilient to transient network drops, allowing it to simply retry on the next tick.

  // Phase A — wait until the new analysis starts (or has already finished).
  while (!inProgress(status) && !done(status)) {
    if (timedOut()) return { status, timedOut: true };
    await timers.sleep(pollMs);
    try {
      status = await getStatus();
    } catch (err) {
      // Ignore transient network errors during polling and retry
    }
  }

  // Phase B — analysis is running; wait for it to finish.
  if (!done(status)) {
    spinner.text = "Analysis in progress. This may take a few minutes...";
    while (!done(status)) {
      if (timedOut()) return { status, timedOut: true };
      await timers.sleep(pollMs);
      try {
        status = await getStatus();
      } catch (err) {
        // Ignore transient network errors during polling and retry
      }
    }
  }

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Holding off on this one. Swallowing all errors during a 20-minute poll would also mask persistent failures (auth/permission/404), looping silently until the timeout, and it adds complexity to a file we're simultaneously simplifying for the complexity gate. The maxWaitMs cap already bounds the loop. A bounded consecutive-failure retry would be the right way to add resilience without hiding hard failures — noting it as a possible follow-up rather than applying the catch-all here.

🤖 Generated by /pr-fixup command

Copy link
Copy Markdown

@codacy-production codacy-production Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

The PR successfully implements the functional requirements for pattern guards, the reanalyze-and-wait polling mode, and noise reduction in the issues overview. However, Codacy results are currently not up to standards due to high complexity and new quality issues.

A critical blocker is the usage of an undefined function fetchAllTools in src/commands/issues.ts, which will cause a runtime failure. Additionally, src/utils/reanalyze-wait.ts is identified as a high-risk file: it possesses high cyclomatic complexity (70), is entirely uncovered by tests, and contains a logic issue regarding potential clock skew during analysis polling. These issues should be resolved before merging.

About this PR

  • The configuration file guard logic (checking if a tool uses a local configuration and blocking updates) is duplicated across src/commands/pattern.ts and src/commands/patterns.ts. This logic should be centralized in a shared utility to ensure consistent behavior.
1 comment outside of the diff
src/commands/patterns.ts

line 192 🔴 HIGH RISK
The .action handler for the patterns command is doing too much. Separation of the bulk-update flow from the list-rendering flow would make the command much easier to test and modify.

Try running the following prompt in your IDE agent:

Refactor the action handler for the patterns command in src/commands/patterns.ts. Separate the bulk update logic (handleBulkUpdate) and the pattern listing logic into distinct functions to improve maintainability and NLOC.

Test suggestions

  • Verify pattern info mode displays card/JSON correctly when no action flag is provided
  • Verify config-file guard prevents modification in both 'pattern' and 'patterns' commands
  • Verify coding-standard guard prevents modification of enforced patterns in the 'pattern' command
  • Verify 'issues --overview' correctly relabels False Positive buckets
  • Verify noise detection logic identifies patterns exceeding both the percentage share and frequency multiplier thresholds
  • Verify noise suggestions correctly toggle between runnable CLI commands and manual instructions based on modifiability
  • Verify the polling loop correctly uses the trigger time (t0) to avoid tracking stale analyses
  • Verify issue snapshot and diff logic correctly calculates signed net deltas across all dimensions (severity, category, pattern)
  • Automate unit test for clock skew scenarios in isAnalysisInProgress (high risk, 0 coverage)
  • Automate unit tests for renderReanalyzeReport with mock delta payloads (high risk, 0 coverage)
Prompt proposal for missing tests
Consider implementing these tests if applicable:
1. Automate unit test for clock skew scenarios in `isAnalysisInProgress` (high risk, 0 coverage)
2. Automate unit tests for `renderReanalyzeReport` with mock delta payloads (high risk, 0 coverage)

TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback

Comment thread src/utils/formatting.ts Outdated
* dim ⬛ when disabled. (`enabled` is OR'd with `enabledBy` to work around an
* API quirk where a standard-enforced pattern can report `enabled: false`.)
*/
export function printPatternCard(cp: ConfiguredPattern): void {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 HIGH RISK

The printPatternCard function is becoming a 'God function' for pattern rendering. Breaking it into smaller components (e.g., printPatternHeader, printPatternMetadata, and printPatternDocumentation) would improve readability and reduce the complexity score.

Try running the following prompt in your IDE agent:

Refactor the printPatternCard function in src/utils/formatting.ts to reduce its cyclomatic complexity. Extract the logic for rendering metadata, documentation (Why/How), and parameters into smaller, private helper functions.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — split into printPatternHeader, printPatternMeta, printPatternDocs, and printPatternParams. printPatternCard now just composes them, bringing cyclomatic complexity back under the limit.

🤖 Generated by /pr-fixup command

Comment thread src/commands/issues.ts
// tools tell us which ones are config-file-driven and let us check
// coding-standard enforcement per pattern.
const [globalTools, repoToolsResponse] = await Promise.all([
fetchAllTools(),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 HIGH RISK

fetchAllTools is not defined or imported. Try running the following prompt in your coding agent:

Implement a fetchAllTools helper in src/utils/formatting.ts that pages through ToolsService.listTools to return all global tools, then import it into src/commands/issues.ts.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

False positive. fetchAllTools is defined locally in this file (async function fetchAllTools() ~line 384) and is used both here and by buildFilterBody. The CI build-and-test job (which runs tsc + the test suite) passes on Node 20 and 22 — it would fail at compile time if the function were undefined.

🤖 Generated by /pr-fixup command

}

/** Print the human-readable delta report. */
export function renderReanalyzeReport(
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MEDIUM RISK

This function is exceeding complexity limits by handling all three dimensions of the reanalyze report (pattern, severity, category) in one block. Extracting each dimension's rendering logic into specialized functions would clarify the flow.

Try running the following prompt in your IDE agent:

Split renderReanalyzeReport in src/utils/reanalyze-wait.ts into smaller functions. Create renderPatternDeltas, renderSeverityDeltas, and renderCategoryDeltas helpers.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — extracted renderPatternDeltas, renderSeverityDeltas, and renderCategoryDeltas. renderReanalyzeReport now composes them and is under both the cyclomatic-complexity and line-count limits.

🤖 Generated by /pr-fixup command

* reanalysis (`startedAnalysis` more recent than t0) and hasn't finished yet
* (`startedAnalysis` more recent than `endedAnalysis`).
*/
export function isAnalysisInProgress(
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MEDIUM RISK

To account for potential clock skew between the client and server, subtract a safety margin from triggeredAt before using it for comparisons in isAnalysisInProgress and isAnalysisDone.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deferring this one. startedAnalysis/endedAnalysis are server-generated timestamps while triggeredAt is the client trigger time, so a skew margin would only matter in an edge case and trades deterministic detection for a magic constant. Flagging for discussion rather than adding it speculatively — happy to introduce a small margin if clock skew turns out to cause missed detections in practice.

🤖 Generated by /pr-fixup command

Comment thread src/commands/issues.ts Outdated
repository,
),
]);
suggestions = await buildNoiseSuggestions(
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚪ LOW RISK

Suggestion: Limit the number of patterns processed to avoid redundant API calls for patterns that won't be displayed.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — patterns are now capped to MAX_NOISE_SUGGESTIONS before any per-pattern API calls (resolved synchronously and sliced first), so there's no burst of redundant requests on repos with many noisy patterns.

🤖 Generated by /pr-fixup command

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR bundles several CLI UX and workflow improvements around pattern management, issue overview noise reduction, and a new blocking reanalysis mode that waits for completion and reports issue deltas.

Changes:

  • Add --reanalyze-and-wait (-w) to repository and pull-request, including polling + delta reporting (human + JSON).
  • Enhance pattern/patterns with shared rendering + JSON projection, plus guards for config-file-driven tools and coding-standard-enforced patterns.
  • Polish issues --overview by relabeling false-positive buckets and adding “noisy pattern” disable suggestions.

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/utils/reanalyze-wait.ts New shared polling/snapshot/delta/render utilities for --reanalyze-and-wait.
src/utils/reanalyze-wait.test.ts Unit tests for snapshots, diffing, polling behavior, rendering, and JSON output.
src/utils/formatting.ts Add formatDuration, isBeingAnalyzed, and centralize pattern card rendering + JSON field list.
src/utils/formatting.test.ts Tests for formatDuration and isBeingAnalyzed.
src/commands/repository.ts Add --reanalyze-and-wait flow for repositories using overview baseline + polling.
src/commands/repository.test.ts Tests for repository --reanalyze-and-wait behavior and JSON output.
src/commands/pull-request.ts Add --reanalyze-and-wait flow for PRs using PR-issue baselines + polling.
src/commands/pull-request.test.ts Tests for PR --reanalyze-and-wait behavior and JSON output.
src/commands/patterns.ts Reuse shared printPatternCard/PATTERN_JSON_FIELDS and add config-file tool guard.
src/commands/patterns.test.ts Coverage for configuration-file guard behavior in patterns.
src/commands/pattern.ts Add info mode, JSON output, config-file guard, and coding-standard enforcement guard.
src/commands/pattern.test.ts New tests for info mode + guards (config-file and standard-enforced patterns).
src/commands/issues.ts Relabel false-positive buckets and add noisy-pattern suggestions that adapt to tool/pattern constraints.
src/commands/issues.test.ts Tests for false-positive relabeling and noise-suggestion paths (command vs manual steps).
src/commands/AGENTS.md Document new modes/guards and shared utilities for agents/maintainers.
SPECS/README.md Update spec tracking entries for the new features.
SPECS/commands/tools-and-patterns.md Document pattern info mode and configuration-file/coding-standard guards.
SPECS/commands/issues.md Document false-positive relabeling + noisy-pattern suggestion logic and extra API calls.
SPECS/commands/analysis.md Document --reanalyze-and-wait behavior, polling rules, and outputs.
README.md Update command summaries to mention new behavior (pattern info mode, reanalyze-and-wait).
AGENTS.md Add repo-wide convention for polling via utils/reanalyze-wait.ts + timers.sleep.
.changeset/reanalyze-and-wait.md Changeset entry for --reanalyze-and-wait release note.
.changeset/pattern-config-file-awareness.md Changeset entry for pattern guards + info mode.
.changeset/issues-overview-noise.md Changeset entry for issues overview false-positive labels + noise suggestions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/commands/issues.ts
// Resolve disable suggestions for noisy patterns. The extra tools fetch
// only happens when there's something to suggest, and stays under the
// spinner so the user sees progress rather than a stall.
const noisy = detectNoisyPatterns(counts.patterns);
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — buildNoiseSuggestions now resolves owning tools synchronously, drops unresolvable patterns, and slices to MAX_NOISE_SUGGESTIONS before making any listRepositoryToolPatterns calls. No per-pattern network calls happen for patterns that won't be displayed.

🤖 Generated by /pr-fixup command

Comment thread src/utils/reanalyze-wait.ts Outdated
Comment on lines +181 to +185
.sort(
(a, b) =>
SEVERITY_ORDER.indexOf(a.severity!) -
SEVERITY_ORDER.indexOf(b.severity!),
);
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — fixed. Added a severityRank helper that maps unknown severities to the end of the canonical order (instead of indexOf returning -1 and sorting them first), and added a regression test (sorts unknown severities last instead of first).

🤖 Generated by /pr-fixup command

@alerizzo
Copy link
Copy Markdown
Collaborator Author

alerizzo commented Jun 3, 2026

Review feedback addressed

Thanks for the thorough reviews. Pushed a fixup commit:

Fixed (Codacy quality gate — the 8 new issues)

  • Complexity — split renderReanalyzeReport into renderPatternDeltas/renderSeverityDeltas/renderCategoryDeltas, printPatternCard into printPatternHeader/printPatternMeta/printPatternDocs/printPatternParams, extracted diffPatternMap/tallyPattern out of diffSnapshots/snapshotFromPrIssues. All now under the cyclomatic/length limits.
  • Security (Semgrep non-literal RegExp) — replaced the new RegExp(String.fromCharCode(27) + …) ANSI-strip in the tests with a literal /\x1b\[[0-9;]*m/g.
  • AGENTS.md doc lint — reworded the "Polling / waiting" bullet into shorter sentences with an escape hatch.

Fixed (review comments)

  • Redundant API calls in buildNoiseSuggestions (Gemini + Copilot + Codacy) — resolve owning tools synchronously, drop unresolvable patterns, and slice to MAX_NOISE_SUGGESTIONS before any listRepositoryToolPatterns calls. "… (N more)" hint preserved.
  • Unknown-severity sort (Copilot) — severityRank now sorts unknown severities last instead of first; added a regression test.
  • Config-file guard duplication (Codacy) — centralized the wording (configFileNotice, CONFIG_FILE_LOCKED_MESSAGE) in utils/formatting.ts so pattern/patterns stay consistent.

Dismissed

  • fetchAllTools "undefined" (Codacy, critical) — false positive: it's defined locally in issues.ts (~line 384). build-and-test passes on Node 20/22, which it couldn't if the symbol were missing.

Deferred / flagged for discussion

  • try/catch around polling (Gemini) — declined the catch-all: it would mask persistent auth/404 failures for up to 20 min and adds complexity. A bounded consecutive-failure retry would be the better follow-up.
  • Clock-skew margin in isAnalysisInProgress (Codacy) — these are server timestamps vs a client trigger time; deferring a speculative margin unless skew proves to cause missed detections.
  • patterns action handler complexity (Codacy, in the "potential false positives" bucket) — the bulk path is already extracted to handleBulkUpdate; the remaining handler is a linear guard→mode sequence, so further splitting would scatter the flow for little gain. Doesn't fail the gate.

npm run check-types, npm run build, and the full suite (372 tests) all pass locally.

🤖 Generated by /pr-fixup command

alerizzo and others added 2 commits June 3, 2026 10:15
- Reduce cyclomatic complexity flagged by Codacy: split
  renderReanalyzeReport, printPatternCard, and extract helpers from
  diffSnapshots/snapshotFromPrIssues — all under the limits now.
- Cap buildNoiseSuggestions to MAX_NOISE_SUGGESTIONS before any
  per-pattern API calls (Gemini/Copilot/Codacy efficiency note);
  preserve the "… (N more)" hint.
- Sort unknown severities last in diffSnapshots via severityRank
  instead of indexOf returning -1 (Copilot); add regression test.
- Replace non-literal RegExp in issues tests with a literal to clear
  the Semgrep finding.
- Centralize the config-file guard wording in utils/formatting.ts so
  pattern/patterns stay consistent (Codacy DRY note).
- Reword the AGENTS.md polling bullet to satisfy the doc linter.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Extract renderDeltaSections from renderReanalyzeReport and patternIcon
  from printPatternHeader so both drop under the cyclomatic-complexity
  medium limit (7).
- Split the AGENTS.md "Polling / waiting" bullet into short sub-bullets
  to satisfy the sentence-complexity doc lint.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 3, 2026 09:23
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 1 comment.

Comment on lines +303 to +304
const startedAt = now();
const timedOut = () => now() - startedAt > maxWaitMs;
@alerizzo alerizzo merged commit f039b39 into main Jun 3, 2026
5 checks passed
@alerizzo alerizzo deleted the feat/pattern-reanalyze-overview branch June 3, 2026 09:53
@github-actions github-actions Bot mentioned this pull request Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants