Summary
All 7 fetch() calls in app.js have no AbortController. The pipelineState.isRunning guard only prevents UI re-entry — it cannot cancel in-flight HTTP requests. This creates race conditions where stale responses overwrite current pipeline state.
Risk Assessment
- Risk Level: High
- Likelihood: Medium — occurs when users re-trigger pipeline or use refinement during execution
- Impact: High — state corruption, wrong code displayed
- Timeline: As usage grows
Affected Code
fetch() calls without AbortController (lines 1008, 1050, 1108, 1187, 1299, 1362, 1417)
None of the 7 fetch calls use an AbortController signal.
runThinkingPipeline() (line 3723)
if (pipelineState.isRunning) return;
Only guards UI re-entry. Cannot cancel the 3 sequential API calls (Architect → Generator → Dissector) if the user navigates away or wants to restart.
runRefinement() (line 3627)
Does NOT check pipelineState.isRunning, so it can execute concurrently with runThinkingPipeline(), both writing to pipelineState.step2Result.
Race Condition Scenario
- User clicks "Run Pipeline" → starts Step 1 (Architect)
- User gets impatient after 15s, refreshes and clicks again
- Pipeline A's Step 2 response arrives, writes to
pipelineState.step2Result
- Pipeline B's Step 1 completes, overwrites
pipelineState.step1Result
- Pipeline B's Step 2 now uses Pipeline B's spec but Step 2 output from Pipeline A is briefly visible
Suggested Fix
let currentAbortController = null;
async function runThinkingPipeline() {
// Cancel any in-flight pipeline
if (currentAbortController) {
currentAbortController.abort();
}
currentAbortController = new AbortController();
const signal = currentAbortController.signal;
// Pass signal to all fetch calls
const response = await fetch(url, { method: "POST", headers, body, signal });
// Check after each step
if (signal.aborted) return;
// ... continue pipeline
}
Also add isRunning guard to runRefinement().
Summary
All 7
fetch()calls inapp.jshave noAbortController. ThepipelineState.isRunningguard only prevents UI re-entry — it cannot cancel in-flight HTTP requests. This creates race conditions where stale responses overwrite current pipeline state.Risk Assessment
Affected Code
fetch() calls without AbortController (lines 1008, 1050, 1108, 1187, 1299, 1362, 1417)
None of the 7 fetch calls use an AbortController signal.
runThinkingPipeline() (line 3723)
Only guards UI re-entry. Cannot cancel the 3 sequential API calls (Architect → Generator → Dissector) if the user navigates away or wants to restart.
runRefinement() (line 3627)
Does NOT check
pipelineState.isRunning, so it can execute concurrently withrunThinkingPipeline(), both writing topipelineState.step2Result.Race Condition Scenario
pipelineState.step2ResultpipelineState.step1ResultSuggested Fix
Also add
isRunningguard torunRefinement().