Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 10 additions & 15 deletions packages/server/src/routes/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2449,27 +2449,22 @@ export function registerApiRoutes(
return apiError(c, 500, 'Failed to look up workflow run');
}

if (!run?.working_path) {
if (!run) {
return apiError(c, 404, 'Workflow run not found');
}

// Derive owner/repo from working_path (must be under ~/.archon/workspaces/owner/repo/...)
const normalizedWorkspacesPath = normalize(getArchonWorkspacesPath());
const normalizedWorkingPath = normalize(run.working_path);
if (!normalizedWorkingPath.startsWith(normalizedWorkspacesPath + sep)) {
getLog().error(
{ runId, workingPath: run.working_path },
'artifacts.working_path_outside_workspaces'
);
return apiError(c, 404, 'Artifact not available: working path not in workspaces');
// Derive owner/repo from codebase name (format: "owner/repo")
const codebase = run.codebase_id ? await codebaseDb.getCodebase(run.codebase_id) : null;
if (!codebase?.name) {
getLog().error({ runId, codebaseId: run.codebase_id }, 'artifacts.codebase_lookup_failed');
return apiError(c, 404, 'Artifact not available: codebase not found');
}
const relative = normalizedWorkingPath.substring(normalizedWorkspacesPath.length + 1);
const parts = relative.split(sep).filter(p => p.length > 0);
if (parts.length < 2) {
getLog().error({ runId, workingPath: run.working_path }, 'artifacts.owner_repo_parse_failed');
const nameParts = codebase.name.split('/');
if (nameParts.length < 2) {
getLog().error({ runId, codebaseName: codebase.name }, 'artifacts.owner_repo_parse_failed');
return apiError(c, 404, 'Artifact not available: could not determine owner/repo');
}
const [owner, repo] = parts;
const [owner, repo] = nameParts;
Comment on lines +2456 to +2467
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if any workflow runs exist with null codebase_id
ast-grep --pattern 'codebase_id UUID REFERENCES'

# Search for any existing fallback logic or migration plans
rg -n 'codebase_id' --type sql -C3

Repository: coleam00/Archon

Length of output: 12355


🏁 Script executed:

# Get the artifact endpoint context in api.ts
cd packages/server/src/routes && sed -n '2430,2480p' api.ts

Repository: coleam00/Archon

Length of output: 2014


🏁 Script executed:

# Search for any working_path usage and previous artifact retrieval logic
rg -n 'working_path' packages/server/src/routes/api.ts -B2 -A2

Repository: coleam00/Archon

Length of output: 824


🏁 Script executed:

# Search for any codebase_id related fallback or migration logic
rg -n 'codebase_id' packages/server/src/routes/api.ts -B2 -A2

Repository: coleam00/Archon

Length of output: 462


🏁 Script executed:

# Find getRunArtifactsPath definition
rg -n 'getRunArtifactsPath' packages/server/src -B2 -A5

Repository: coleam00/Archon

Length of output: 1254


🏁 Script executed:

# Look for any constants or configuration that shows artifact storage structure
rg -n 'artifacts' packages/server/src/routes/api.ts | head -20

Repository: coleam00/Archon

Length of output: 793


🏁 Script executed:

# Check if working_path is even stored in workflow_runs table
rg -n 'working_path' migrations/ -B2 -A2

Repository: coleam00/Archon

Length of output: 1672


🏁 Script executed:

# Find the `@archon/paths` module (likely in packages/paths or similar)
find packages -name "paths*" -type d

Repository: coleam00/Archon

Length of output: 73


🏁 Script executed:

# Look for getRunArtifactsPath implementation
rg -n 'getRunArtifactsPath' --type ts -B2 -A8

Repository: coleam00/Archon

Length of output: 9863


🏁 Script executed:

# Check if there's any fallback logic or migration strategy for null codebase_id
rg -n 'codebase_id.*null\|null.*codebase_id' packages/server/src --type ts -C3

Repository: coleam00/Archon

Length of output: 41


🏁 Script executed:

# Check git history of the artifact endpoint - see if it's recent
cd packages/server/src/routes && git log --oneline -20 -- api.ts | head -10

Repository: coleam00/Archon

Length of output: 112


🏁 Script executed:

# Look for any migration or data population scripts for codebase_id
find . -name "*migrat*" -type f -path "*/scripts/*" -o -name "*backfill*" -type f 2>/dev/null | head -10

Repository: coleam00/Archon

Length of output: 41


🏁 Script executed:

# Check if there are any TODOs or FIXMEs related to this issue
rg -n 'TODO|FIXME' packages/server/src/routes/api.ts | grep -i 'artifact\|codebase'

Repository: coleam00/Archon

Length of output: 41


Add fallback artifact path when codebase_id is unavailable.

The artifact endpoint returns 404 if codebase_id is null or the codebase lookup fails. However, the schema allows codebase_id to be nullable (migration 008: ON DELETE SET NULL), which affects:

  • Older workflow runs with codebase_id = null
  • Runs whose associated codebase was deleted

Artifacts are otherwise accessible via the worktree path (as seen in packages/workflows/src/executor.ts lines 198 and packages/cli/src/commands/continue.ts lines 220–222, which both provide fallbacks). The endpoint should use a similar fallback: if codebase_id is null and the run has a working_path, construct the artifact directory as join(run.working_path, '.archon', 'artifacts', 'runs', runId) before returning 404.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/server/src/routes/api.ts` around lines 2455 - 2466, The handler
currently bails with apiError when codebase lookup fails or codebase.name
doesn't contain owner/repo; instead, if run.working_path exists (i.e.,
codebase_id is null or codebase deleted) construct the artifact directory as
join(run.working_path, '.archon', 'artifacts', 'runs', runId) and use that as
the artifact path rather than returning 404; otherwise keep the existing
getLog().error and return apiError. Update the logic around
codebaseDb.getCodebase / nameParts / [owner, repo] to branch: prefer owner/repo
when available, else fallback to the run.working_path-based artifact directory
(use run, run.working_path, runId, getLog(), and apiError symbols to locate and
modify the code).


const artifactDir = getRunArtifactsPath(owner, repo, runId);
const filePath = join(artifactDir, filename);
Expand Down
Loading
Loading