Summary
The Supermodel public API now exposes a dedicated dead code analysis endpoint at POST /v1/analysis/dead-code (operationId: generateDeadCodeAnalysis). This action should be refactored from performing local graph analysis to being a thin consumer of that endpoint.
Currently, the action:
- Zips the repo
- Calls
generateSupermodelGraph to get the full Supermodel IR (nodes + relationships)
- Locally filters Function nodes, checks for callers via
calls relationships
- Applies heuristic entry-point/export/test filtering in
dead-code.ts
- Formats results into a PR comment
After this refactor, the action should:
- Zip the repo (unchanged)
- Call
generateDeadCodeAnalysis — the API handles all analysis server-side
- Map the API response directly to PR comment / action outputs
- No local graph processing needed
Why
- The API endpoint is smarter — it combines parse graph + call graph, detects transitive dead code, does symbol-level import analysis, and provides confidence levels + reasons
- Removes ~200 lines of local analysis logic that the API now handles better
- The API detects entry points server-side (exports, route handlers, main functions) — no need for local heuristics
- Response includes
confidence (high/medium/low) and reason fields for richer reporting
- Detects more than just functions: classes, methods, interfaces, types, variables, constants
Current Architecture (to be replaced)
src/index.ts
- Entry point for the GitHub Action
- Creates zip via
git archive
- Generates idempotency key from commit hash + UUID
- Calls
api.generateSupermodelGraph() via @supermodeltools/sdk
- Passes raw graph nodes/relationships to
findDeadCode()
- Posts PR comment, sets action outputs
- Comprehensive error handling with status-code-specific messages
src/dead-code.ts
findDeadCode(nodes, relationships, ignorePatterns) — the core local analysis:
- Filters for
Function label nodes
- Builds set of called function IDs from
calls relationships
- Skips: ignored files, entry point files, entry point function names, exported functions
formatPrComment(deadCode) — markdown table formatter
- Helper functions:
isEntryPointFile, isEntryPointFunction, shouldIgnoreFile
- Constants:
DEFAULT_EXCLUDE_PATTERNS, ENTRY_POINT_PATTERNS, ENTRY_POINT_FUNCTION_NAMES
action.yml
- Inputs:
supermodel-api-key, github-token, comment-on-pr, fail-on-dead-code, ignore-patterns
- Outputs:
dead-code-count, dead-code-json
- Runs on node20, main:
dist/index.js
Tests
src/__tests__/dead-code.test.ts — unit tests for all local analysis functions
src/__tests__/integration.test.ts — end-to-end test calling actual API (skipped without key)
Dependencies
@supermodeltools/sdk@^0.4.1 — needs upgrade for new endpoint
@actions/core, @actions/exec, @actions/github — standard GH Action libs
minimatch@^9.0.0 — for glob pattern matching (may no longer be needed)
New API Endpoint Details
POST /v1/analysis/dead-code
Header: Idempotency-Key, X-Api-Key
Body: multipart/form-data with `file` (zip archive)
Response Schema (DeadCodeAnalysisResponse)
{
metadata: {
totalDeclarations: number;
deadCodeCandidates: number;
aliveCode: number;
analysisMethod: string; // e.g. "parse_graph + call_graph"
rootFilesCount?: number;
transitiveDeadCount?: number;
symbolLevelDeadCount?: number;
analysisStartTime?: string;
analysisEndTime?: string;
};
deadCodeCandidates: Array<{
file: string;
name: string;
line: number;
type: 'function' | 'class' | 'method' | 'interface' | 'type' | 'variable' | 'constant';
confidence: 'high' | 'medium' | 'low';
reason: string;
}>;
aliveCode: Array<{
file: string;
name: string;
line: number;
type: string;
callerCount: number;
}>;
entryPoints: Array<{
file: string;
name: string;
line: number;
type: string;
reason: string;
}>;
}
Async envelope: Returns 202 with { status: "processing", jobId, retryAfter } while processing, then 200 with { status: "completed", jobId, result: DeadCodeAnalysisResponse } when done. The SDK handles polling automatically.
Implementation Plan
1. Update SDK dependency
2. Refactor src/index.ts
- Replace
api.generateSupermodelGraph() → api.generateDeadCodeAnalysis()
- Remove graph node/relationship processing
- Map
response.result.deadCodeCandidates directly to output format
- Update idempotency key prefix from
deadcode to analysis:deadcode
- Expose richer metadata in action outputs (confidence, reason, type, metadata stats)
3. Simplify src/dead-code.ts
- Remove
findDeadCode() — no longer needed
- Remove all entry point detection helpers — API handles this
- Remove
DEFAULT_EXCLUDE_PATTERNS, ENTRY_POINT_PATTERNS, ENTRY_POINT_FUNCTION_NAMES
- Keep
formatPrComment() but update to use new response fields:
- Add
Type and Confidence columns to the table
- Include
reason in expandable details
- Add metadata summary (totalDeclarations, analysis method, etc.)
ignore-patterns input can remain for client-side post-filtering (filter by file path)
minimatch dependency can stay if we keep ignore-patterns, otherwise remove
4. Update action.yml
- Consider adding new outputs:
metadata-json, alive-code-count, entry-points-json
- Existing outputs (
dead-code-count, dead-code-json) should map cleanly
5. Rewrite tests
- Unit tests: rewrite to test new response mapping and comment formatting
- Integration test: update to call
generateDeadCodeAnalysis instead of generateCallGraph
6. Update README
- Update "What it does" section to reflect API-driven analysis
- Note new capabilities (confidence levels, types beyond functions, transitive detection)
7. Version bump for GH Actions marketplace
- Bump
package.json version
- Rebuild
dist/index.js via npm run build
- Create new release / update
v1 tag
Related
Summary
The Supermodel public API now exposes a dedicated dead code analysis endpoint at
POST /v1/analysis/dead-code(operationId:generateDeadCodeAnalysis). This action should be refactored from performing local graph analysis to being a thin consumer of that endpoint.Currently, the action:
generateSupermodelGraphto get the full Supermodel IR (nodes + relationships)callsrelationshipsdead-code.tsAfter this refactor, the action should:
generateDeadCodeAnalysis— the API handles all analysis server-sideWhy
confidence(high/medium/low) andreasonfields for richer reportingCurrent Architecture (to be replaced)
src/index.tsgit archiveapi.generateSupermodelGraph()via@supermodeltools/sdkfindDeadCode()src/dead-code.tsfindDeadCode(nodes, relationships, ignorePatterns)— the core local analysis:Functionlabel nodescallsrelationshipsformatPrComment(deadCode)— markdown table formatterisEntryPointFile,isEntryPointFunction,shouldIgnoreFileDEFAULT_EXCLUDE_PATTERNS,ENTRY_POINT_PATTERNS,ENTRY_POINT_FUNCTION_NAMESaction.ymlsupermodel-api-key,github-token,comment-on-pr,fail-on-dead-code,ignore-patternsdead-code-count,dead-code-jsondist/index.jsTests
src/__tests__/dead-code.test.ts— unit tests for all local analysis functionssrc/__tests__/integration.test.ts— end-to-end test calling actual API (skipped without key)Dependencies
@supermodeltools/sdk@^0.4.1— needs upgrade for new endpoint@actions/core,@actions/exec,@actions/github— standard GH Action libsminimatch@^9.0.0— for glob pattern matching (may no longer be needed)New API Endpoint Details
Response Schema (
DeadCodeAnalysisResponse)Async envelope: Returns
202with{ status: "processing", jobId, retryAfter }while processing, then200with{ status: "completed", jobId, result: DeadCodeAnalysisResponse }when done. The SDK handles polling automatically.Implementation Plan
1. Update SDK dependency
@supermodeltools/sdkto version that includesgenerateDeadCodeAnalysismethodv0.6.0#6 (breaking changes in v0.6.0)2. Refactor
src/index.tsapi.generateSupermodelGraph()→api.generateDeadCodeAnalysis()response.result.deadCodeCandidatesdirectly to output formatdeadcodetoanalysis:deadcode3. Simplify
src/dead-code.tsfindDeadCode()— no longer neededDEFAULT_EXCLUDE_PATTERNS,ENTRY_POINT_PATTERNS,ENTRY_POINT_FUNCTION_NAMESformatPrComment()but update to use new response fields:TypeandConfidencecolumns to the tablereasonin expandable detailsignore-patternsinput can remain for client-side post-filtering (filter by file path)minimatchdependency can stay if we keepignore-patterns, otherwise remove4. Update
action.ymlmetadata-json,alive-code-count,entry-points-jsondead-code-count,dead-code-json) should map cleanly5. Rewrite tests
generateDeadCodeAnalysisinstead ofgenerateCallGraph6. Update README
7. Version bump for GH Actions marketplace
package.jsonversiondist/index.jsvianpm run buildv1tagRelated
v0.6.0#6 — Breaking change to Supermodel api/sdk coming in v0.6.0generateDeadCodeAnalysisoperation