# AI Reports

## Publish AI report results

> Store AI analysis results from a Hatchet workflow. Called by the workflow after running \`sfp project:report\`.\
> \
> \*\*Append-only:\*\* Each publish creates a new row (timestamp in key). No upserts.\
> \
> \*\*Retention:\*\* Keeps last 10 reports per scope/scopeName combination.

```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":{"PublishAIReportDto":{"type":"object","properties":{"repositoryIdentifier":{"type":"string","description":"Repository identifier (e.g., flxbl-io/sf-core)"},"scope":{"type":"string","description":"Analysis scope","enum":["repository","domain","package"]},"scopeName":{"type":"string","description":"Name of the domain or package analyzed. Use \"repository\" for repository scope."},"commitSha":{"type":"string","description":"Git commit SHA at the time of analysis"},"analyzedAt":{"type":"string","description":"ISO 8601 timestamp of when analysis was performed"},"status":{"type":"string","description":"Analysis status","enum":["completed","failed"]},"markdownReport":{"type":"string","description":"Markdown report content"},"provider":{"type":"string","description":"AI provider used (e.g., anthropic, openai)"},"model":{"type":"string","description":"AI model used (e.g., claude-sonnet-4-5-20250929)"},"executionTimeMs":{"type":"number","description":"Total execution time in milliseconds"},"taskExecutionId":{"type":"string","description":"Task execution ID from the Hatchet workflow"}},"required":["repositoryIdentifier","scope","scopeName","commitSha","analyzedAt","status","markdownReport"]}}},"paths":{"/sfp/api/ai-reports/results":{"post":{"operationId":"AIReportsController_publishResults","summary":"Publish AI report results","description":"Store AI analysis results from a Hatchet workflow. Called by the workflow after running `sfp project:report`.\n\n**Append-only:** Each publish creates a new row (timestamp in key). No upserts.\n\n**Retention:** Keeps last 10 reports per scope/scopeName combination.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishAIReportDto"}}}},"responses":{"201":{"description":"Report stored successfully"},"400":{"description":"Invalid request body"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Requires role: application"}},"tags":["AI Reports"]}}}}
```

## List AI report summaries

> Retrieve the latest AI report summary per scope/scopeName for a repository.\
> Returns metadata only — no markdown content. Use GET /ai-reports/latest for full report.

```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/ai-reports":{"get":{"operationId":"AIReportsController_getSummaries","summary":"List AI report summaries","description":"Retrieve the latest AI report summary per scope/scopeName for a repository.\nReturns metadata only — no markdown content. Use GET /ai-reports/latest for full report.","parameters":[{"name":"repositoryIdentifier","required":true,"in":"query","description":"Repository identifier (e.g., flxbl-io/sf-core)","schema":{"type":"string"}}],"responses":{"200":{"description":"Latest report summary per scope/scopeName"},"400":{"description":"Missing repositoryIdentifier"},"403":{"description":"Forbidden - Requires role: member, owner, application"}},"tags":["AI Reports"]}}}}
```

## Get AI report status

> Check the current status of AI analysis for a specific scope/scopeName.\
> Returns one of: \`never\_ran\`, \`generating\`, \`completed\`, or \`failed\`.\
> Use this to show real-time status in the UI without triggering a refresh.

```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/ai-reports/status":{"get":{"operationId":"AIReportsController_getStatus","summary":"Get AI report status","description":"Check the current status of AI analysis for a specific scope/scopeName.\nReturns one of: `never_ran`, `generating`, `completed`, or `failed`.\nUse this to show real-time status in the UI without triggering a refresh.","parameters":[{"name":"repositoryIdentifier","required":true,"in":"query","schema":{"type":"string"}},{"name":"scope","required":true,"in":"query","schema":{"type":"string"}},{"name":"scopeName","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Current AI report status"},"400":{"description":"Missing required query parameters"},"403":{"description":"Forbidden - Requires role: member, owner, application"}},"tags":["AI Reports"]}}}}
```

## Get latest full AI report

> Retrieve the latest full AI report (including markdown) for a specific scope/scopeName.

```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/ai-reports/latest":{"get":{"operationId":"AIReportsController_getLatest","summary":"Get latest full AI report","description":"Retrieve the latest full AI report (including markdown) for a specific scope/scopeName.","parameters":[{"name":"repositoryIdentifier","required":true,"in":"query","description":"Repository identifier","schema":{"type":"string"}},{"name":"scope","required":true,"in":"query","description":"Analysis scope (repository, domain, or package)","schema":{"type":"string"}},{"name":"scopeName","required":true,"in":"query","description":"Scope name (e.g., domain name, package name, or \"repository\")","schema":{"type":"string"}}],"responses":{"200":{"description":"Full AI report with markdown"},"400":{"description":"Missing required query parameters"},"403":{"description":"Forbidden - Requires role: member, owner, application"}},"tags":["AI Reports"]}}}}
```

## Get AI report history

> Retrieve historical report metadata (no markdown) for a specific scope/scopeName.\
> Useful for showing a timeline of past analyses.

```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/ai-reports/history":{"get":{"operationId":"AIReportsController_getHistory","summary":"Get AI report history","description":"Retrieve historical report metadata (no markdown) for a specific scope/scopeName.\nUseful for showing a timeline of past analyses.","parameters":[{"name":"repositoryIdentifier","required":true,"in":"query","description":"Repository identifier","schema":{"type":"string"}},{"name":"scope","required":true,"in":"query","description":"Analysis scope","schema":{"type":"string"}},{"name":"scopeName","required":true,"in":"query","description":"Scope name","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","description":"Maximum results to return (default: 10, max: 100)","schema":{"type":"number"}}],"responses":{"200":{"description":"Historical report metadata"},"400":{"description":"Missing required query parameters"},"403":{"description":"Forbidden - Requires role: member, owner, application"}},"tags":["AI Reports"]}}}}
```

## Trigger AI report refresh

> Trigger a new AI analysis via Hatchet workflow. Returns a task execution ID for tracking.\
> \
> \*\*Cost-aware:\*\* AI tokens are expensive. Reports are only generated on explicit user request — no auto-trigger.

```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/ai-reports/refresh":{"post":{"operationId":"AIReportsController_triggerRefresh","summary":"Trigger AI report refresh","description":"Trigger a new AI analysis via Hatchet workflow. Returns a task execution ID for tracking.\n\n**Cost-aware:** AI tokens are expensive. Reports are only generated on explicit user request — no auto-trigger.","parameters":[{"name":"repositoryIdentifier","required":true,"in":"query","description":"Repository identifier","schema":{"type":"string"}},{"name":"scope","required":true,"in":"query","description":"Analysis scope","schema":{"type":"string"}},{"name":"scopeName","required":true,"in":"query","description":"Scope name","schema":{"type":"string"}},{"name":"model","required":false,"in":"query","description":"AI model to use","schema":{}},{"name":"provider","required":false,"in":"query","description":"AI provider to use","schema":{}},{"name":"force","required":false,"in":"query","description":"Force re-analysis even if a completed report exists for the current commit (default: false)","schema":{"type":"boolean"}}],"responses":{"202":{"description":"Refresh triggered or skipped if report already exists for HEAD commit"},"400":{"description":"Missing required query parameters"},"403":{"description":"Forbidden - Requires role: member, owner"},"409":{"description":"An AI report generation is already in progress for this scope"}},"tags":["AI Reports"]}}}}
```
