marketplace/bundles/plan-marshall/skills/workflow-integration-sonar/SKILL.md
SonarQube/SonarCloud issue workflow - fetch issues, triage, and fix or suppress based on context
npx skillsauth add cuioss/plan-marshall workflow-integration-sonarInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Sonar provider for the findings-pipeline sonar-issue producer. Fetches gate-blocking issues from SonarQube/SonarCloud, applies the pre-filter (sonar-rules.json), and writes one finding per surviving issue via manage-findings add. Consumer dispatch lives in phase-6-finalize/workflow/sonar-roundtrip.md.
Architectural context: This SKILL.md owns the producer-side CLI surface. For the producer→store→consumer→gate flow that connects this producer to the unified store, the per-domain
ext-triageconsumer dispatch, and the invariant gate, seeref-workflow-architecture/standards/findings-pipeline.md.
Execution mode: Fetch Sonar issues, triage each for fix or suppress, implement changes, verify build.
Prohibited actions:
Constraints:
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| project | string | yes | — | SonarQube project key |
| pr | string | no | auto-detect | Pull request ID |
| severities | string | no | all | Filter by severity (comma-separated: BLOCKER,CRITICAL,MAJOR,MINOR,INFO) |
| types | string | no | all | Filter by type (comma-separated: BUG,CODE_SMELL,VULNERABILITY) |
manage-providers for workflow-integration-sonartriage_helpers from ref-toon-format at runtime (see ref-workflow-architecture → "Shared Infrastructure")workflow-integration-sonar (Sonar issue workflow)
├─> sonar_rest.py (issue fetching, status changes via REST API)
├─> _credentials_core.get_authenticated_client() (credential loading)
└─> triage_helpers (ref-toon-format) — shared triage, error handling
# Producer-side: fetch + pre-filter + store one sonar-issue finding per surviving issue
python3 .plan/execute-script.py plan-marshall:workflow-integration-sonar:sonar fetch-and-store \
--plan-id EXAMPLE-PLAN --project com.example:project --pr 123 --severities BLOCKER,CRITICAL
# LLM consumer reads stored findings via manage-findings
python3 .plan/execute-script.py plan-marshall:manage-findings:manage-findings list --plan-id EXAMPLE-PLAN --type sonar-issue
Purpose: Stage gate-blocking Sonar issues into the per-type finding store, then let the LLM consumer drive fix-vs-suppress decisions from the stored findings.
Producer-side flow: sonar.py fetch-and-store is the only callable surface. It fetches issues via the REST client, applies the sonar-rules.json pre-filter (drops issues already documented as suppressable via NOSONAR / test-acceptable rules), and writes one sonar-issue finding per surviving issue via manage-findings add. Severity is derived from the Sonar severity (BLOCKER/CRITICAL/MAJOR → error, MINOR → warning, INFO → info), the rule key is captured in the finding's rule field, and the project key is captured in module.
Steps:
Fetch & Store:
python3 .plan/execute-script.py plan-marshall:workflow-integration-sonar:sonar fetch-and-store \
--plan-id {plan_id} --project {project_key} [--pr {pr_number}] [--severities BLOCKER,CRITICAL] [--types BUG,VULNERABILITY]
Output reports count_fetched, count_skipped_suppressable, count_stored, and producer_mismatch_hash_id (set when count_stored ≠ count_fetched − count_skipped_suppressable; the mismatch is also persisted as a Q-Gate finding under phase 5-execute with title prefix (producer-mismatch)).
Query Stored Findings:
python3 .plan/execute-script.py plan-marshall:manage-findings:manage-findings list --plan-id {plan_id} --type sonar-issue
Process — the LLM reads each finding's detail (which carries key, rule, sonar_severity, sonar_type, project, pull_request, component, file, line, and the full message) and decides fix-vs-suppress per finding. After acting on each finding, call manage-findings resolve --hash-id {hash} --resolution fixed|suppressed|accepted.
For ad-hoc inspection or non-finding-store integrations, sonar_rest.py search remains available as the raw REST surface. Producer-side flows MUST use sonar.py fetch-and-store.
Input:
Steps:
Determine Context (optional — get PR number if not provided)
python3 .plan/execute-script.py plan-marshall:tools-integration-ci:ci pr view
Fetch Issues via REST
python3 .plan/execute-script.py plan-marshall:workflow-integration-sonar:sonar_rest search \
--project {project_key} \
[--pr {pr_number}] \
[--severities BLOCKER,CRITICAL] \
[--types BUG,VULNERABILITY]
Parse the Response
The script outputs structured TOON directly.
Output:
project_key: ...
pull_request_id: ...
issues[N]{key,type,severity,file,line,rule,message}:
- key: ...
type: BUG|CODE_SMELL|VULNERABILITY
severity: BLOCKER|CRITICAL|MAJOR|MINOR|INFO
file: ...
line: N
rule: java:S1234
message: ...
statistics:
total_issues_fetched: N
by_severity: {}
by_type: {}
Purpose: Process stored Sonar findings and resolve them.
Input: sonar-issue findings already populated in the per-type store via Workflow 1.
Steps:
Query Findings:
python3 .plan/execute-script.py plan-marshall:manage-findings:manage-findings list --plan-id {plan_id} --type sonar-issue
LLM Decides Per Finding
The LLM reads each finding's detail (key, rule, sonar_severity, sonar_type, project, file, line, message) and decides fix-vs-suppress. There is no script-side classification call.
Execute Actions
For fix:
For suppress:
// NOSONAR rule - reason)Mark Findings Resolved:
python3 .plan/execute-script.py plan-marshall:manage-findings:manage-findings resolve \
--plan-id {plan_id} --hash-id {hash} --resolution fixed|suppressed|accepted
Mark Issues Resolved on Sonar (Optional):
python3 .plan/execute-script.py plan-marshall:workflow-integration-sonar:sonar_rest transition \
--issue-key {issue_key} --transition accept
Script: plan-marshall:workflow-integration-sonar:sonar → sonar.py (producer-side fetch + pre-filter + finding store)
Script: plan-marshall:workflow-integration-sonar:sonar_rest → sonar_rest.py (raw REST API client)
Purpose: Producer-side flow — fetch gate-blocking issues via the REST client, apply the pre-filter, and persist one sonar-issue finding per surviving issue.
Usage:
python3 .plan/execute-script.py plan-marshall:workflow-integration-sonar:sonar fetch-and-store \
--plan-id {plan_id} --project {project_key} [--pr {pr}] [--severities ...] [--types ...]
Output: TOON with counters (count_fetched, count_skipped_suppressable, count_stored), the list of stored finding hash_ids, and producer_mismatch_hash_id when applicable.
standards/sonar-rules.json is now a pre-filter only for the producer-side fetch-and-store flow. Suppressable rules (rules already documented as suppressable, test-acceptable rules) are dropped before findings are written; severity/type boost mappings derive the finding severity field. Final fix-vs-suppress classification of stored findings belongs to the LLM consumer reading the finding detail.
Key principles:
suppressable_rules (with documented justification)test_acceptable_rules are acceptable in test filesSupported languages: Java, JavaScript, TypeScript, Python. Unrecognized rules fall back to the Sonar issue message for triage guidance.
For triage override guidance, see ref-workflow-architecture → "Triage Override Guidance".
Generated by sonar.py:get_suppression_string() based on file extension and rule prefix:
Java: // NOSONAR java:S1234 - reason for suppression
JavaScript/TypeScript: // NOSONAR javascript:S1234 - reason for suppression
Python: # NOSONAR python:S1234 - reason for suppression
| Failure | Action | |---------|--------| | REST API failure | Report error with HTTP status. Verify credentials configured and project key is correct. | | REST API returns empty | No issues found — report success with zero counts. | | triage failure (invalid JSON) | Log warning, skip the issue, continue processing remaining. | | Fix implementation failure | Report which file/line failed. Do not suppress as fallback — ask the caller. | | REST status change failure | Log warning, continue — marking resolved is best-effort. | | Build verification failure after fixes | Report failing tests/compilation. Do not commit broken fixes. |
| Standard | When to Load |
|----------|-------------|
| standards/sonar-rules.json | Adding/updating classification rules, always-fix types, suppressable rules, fix suggestions, or suppression_syntax templates |
The canonical argparse surface for the two entry-point scripts this skill registers: sonar.py (sonar notation) and sonar_rest.py (sonar_rest notation). The plugin-doctor analyzer (_analyze_manage_invocation.py) reads this section as source-of-truth for the manage-invocation-invalid and missing-canonical-block rules. Consuming docs xref this section by name instead of restating the command inline. See pm-plugin-development:plugin-script-architecture cross-skill-integration.md § "Script invocation in documentation".
python3 .plan/execute-script.py plan-marshall:workflow-integration-sonar:sonar fetch-and-store \
--plan-id PLAN_ID --project PROJECT [--pr PR] [--severities SEVERITIES] [--types TYPES]
python3 .plan/execute-script.py plan-marshall:workflow-integration-sonar:sonar_rest search \
--project PROJECT [--pr PR] [--severities SEVERITIES] [--types TYPES]
python3 .plan/execute-script.py plan-marshall:workflow-integration-sonar:sonar_rest transition \
--issue-key ISSUE_KEY --transition {accept,falsepositive,wontfix}
python3 .plan/execute-script.py plan-marshall:workflow-integration-sonar:sonar_rest metrics \
--project PROJECT --component COMPONENT [--metrics METRICS]
See ref-workflow-architecture → "Workflow Skill Orchestration" for the full dependency graph and shared infrastructure documentation. Called by: plan-marshall:workflow-pr-doctor (Sonar issue handling).
testing
A test skill for README generation
testing
A test skill with existing references
tools
Skill without references directory
development
Test skill with table-format references