# Analysis

## Query analysis result summaries

> Retrieve lightweight analysis summaries for a repository. Returns only the fields needed for list/table views — no markdown content or raw linter data.\
> \
> \*\*Use cases:\*\*\
> \- Table view: list all recent analyses with status badges\
> \- Filter by base branch to see analyses targeting a specific branch\
> \- Filter by PR number to see summary for a specific PR\
> \
> Results are ordered by most recent first.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.3.0"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}}},"paths":{"/sfp/api/analysis/results":{"get":{"operationId":"AnalysisController_getResults","summary":"Query analysis result summaries","description":"Retrieve lightweight analysis summaries for a repository. Returns only the fields needed for list/table views — no markdown content or raw linter data.\n\n**Use cases:**\n- Table view: list all recent analyses with status badges\n- Filter by base branch to see analyses targeting a specific branch\n- Filter by PR number to see summary for a specific PR\n\nResults are ordered by most recent first.","parameters":[{"name":"repositoryIdentifier","required":true,"in":"query","description":"Repository identifier (e.g., flxbl-io/sf-core)","schema":{"type":"string"}},{"name":"pullRequestNumber","required":false,"in":"query","description":"Filter by PR number","schema":{"type":"string"}},{"name":"baseBranch","required":false,"in":"query","description":"Filter by target/base branch (e.g., main, release/1.0)","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","description":"Maximum results to return (default: 20, max: 100)","schema":{"type":"number"}}],"responses":{"200":{"description":"Lightweight analysis summaries (no markdown or raw data)"},"400":{"description":"Missing repositoryIdentifier"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Requires role: member, owner, application"}},"tags":["Analysis"]}}}}
```

## Publish analysis results

> Store analysis results from \`sfp analyze\`. Called by the CLI when \`--publish-results\` is used.\
> \
> \*\*Dual write:\*\* Stores full results (with markdown and linter data) in the results table and a lightweight summary in the summary table.\
> \
> \*\*Duplicate handling:\*\* If results already exist for the same PR + commit, they are overwritten (same commit = updated analysis).\
> \
> \*\*Retention:\*\* Keeps last 500 results per repository.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.3.0"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}},"schemas":{"PublishAnalysisDto":{"type":"object","properties":{"repositoryIdentifier":{"type":"string","description":"Repository identifier (e.g., flxbl-io/sf-core)"},"pullRequestNumber":{"type":"string","description":"Pull request number (if PR context)"},"commitSha":{"type":"string","description":"Git commit SHA that was analyzed"},"branchName":{"type":"string","description":"Source branch name"},"baseBranch":{"type":"string","description":"Target branch name (for PRs)"},"status":{"type":"string","description":"Analysis status","enum":["completed","failed"]},"hasIssues":{"type":"boolean","description":"Whether any linter found issues"},"hasFailedLinters":{"type":"boolean","description":"Whether any linter in the fail-on list found issues"},"linters":{"description":"Linters that were executed","type":"array","items":{"type":"string"}},"results":{"description":"Per-linter results","type":"array","items":{"$ref":"#/components/schemas/AnalysisLinterResultDto"}},"executionTimeMs":{"type":"number","description":"Total execution time in milliseconds"},"markdownSummary":{"type":"string","description":"Pre-rendered markdown summary of the analysis results. Used for PR comments and UI rendering."},"prUrl":{"type":"string","description":"Direct URL to the pull request on the git provider"},"commitUrl":{"type":"string","description":"Direct URL to the commit on the git provider"}},"required":["repositoryIdentifier","commitSha","status","hasIssues","hasFailedLinters","linters","results"]},"AnalysisLinterResultDto":{"type":"object","properties":{"type":{"type":"string","description":"Linter type","enum":["duplicates","compliance","architecture","code-analyzer"]},"hasIssues":{"type":"boolean","description":"Whether the linter found issues"},"data":{"type":"object","description":"Linter-specific result data (violations, insights, etc.)"},"notes":{"description":"Additional notes from the linter","type":"array","items":{"type":"string"}}},"required":["type","hasIssues","data"]}}},"paths":{"/sfp/api/analysis/results":{"post":{"operationId":"AnalysisController_publishResults","summary":"Publish analysis results","description":"Store analysis results from `sfp analyze`. Called by the CLI when `--publish-results` is used.\n\n**Dual write:** Stores full results (with markdown and linter data) in the results table and a lightweight summary in the summary table.\n\n**Duplicate handling:** If results already exist for the same PR + commit, they are overwritten (same commit = updated analysis).\n\n**Retention:** Keeps last 500 results per repository.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishAnalysisDto"}}}},"responses":{"201":{"description":"Results stored successfully"},"400":{"description":"Invalid request body"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Requires role: application"}},"tags":["Analysis"]}}}}
```

## Get full analysis results for a pull request

> Retrieve all analysis runs for a specific PR with full data including markdown content and raw linter results.\
> \
> \*\*Use cases:\*\*\
> \- PR detail view: show full linter markdown reports per tab\
> \- Compare analysis results between commits on the same PR\
> \
> Each entry represents a separate analysis run (typically one per commit push).\
> Same commit re-analyzed = latest result only (overwritten on publish).

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.3.0"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}}},"paths":{"/sfp/api/analysis/pr/{prNumber}":{"get":{"operationId":"AnalysisController_getPRAnalysis","summary":"Get full analysis results for a pull request","description":"Retrieve all analysis runs for a specific PR with full data including markdown content and raw linter results.\n\n**Use cases:**\n- PR detail view: show full linter markdown reports per tab\n- Compare analysis results between commits on the same PR\n\nEach entry represents a separate analysis run (typically one per commit push).\nSame commit re-analyzed = latest result only (overwritten on publish).","parameters":[{"name":"prNumber","required":true,"in":"path","description":"Pull request number","schema":{"type":"string"}},{"name":"repositoryIdentifier","required":true,"in":"query","description":"Repository identifier (e.g., flxbl-io/sf-core)","schema":{"type":"string"}}],"responses":{"200":{"description":"PR analysis runs with full data, sorted by most recent commit first"},"400":{"description":"Missing repositoryIdentifier"},"403":{"description":"Forbidden - Requires role: member, owner, application"}},"tags":["Analysis"]}}}}
```
