Context Boundary
- Repo/module:
talkincode/GameKit, AI proposal lifecycle in src/studio/store.tsx
- Version/commit:
main, 9eb811e7bc3db3193b57609425723c478e438d32
- Runtime: browser UI calling
/api/ai
- OS/browser: not recorded; this is a source-level reproduction
- Dependencies/config: no feature flag involved
Expectation vs. Reality
Expected: An AI proposal remains attached to the project and source version that produced it. If the user changes projects while the request is pending, accepting that stale proposal must not modify the new project.
Actual: ask captures the original current project for the request, but stores the resulting proposal in global state without a project ID. acceptProposal applies its files to whichever project is active when the user clicks Accept. A proposal for A's main.py can overwrite B's main.py.
Reproduction Path
- Open project A and start AI Tools → Generate code for
main.py.
- While
/api/ai is pending, switch to project B (a delayed or mocked response can make this deterministic).
- When the proposal appears, click Accept.
- Inspect B's
main.py.
Minimal reproduction: proposal = generate(A); activeProject = B; accept(proposal).
Blast Radius
- Affected users/paths: AI-generated code accepted after a project switch.
- Frequency: only when a request is still pending during navigation.
- Severity rationale: can overwrite code in a different project; recommend P1 for cross-project data integrity.
- Workaround: wait for the AI request to finish before switching projects, or reject any proposal returned after switching.
Evidence
- Request captures the original project and sets a global proposal: ask
- Acceptance writes into the currently active project: acceptProposal
Context Boundary
talkincode/GameKit, AI proposal lifecycle insrc/studio/store.tsxmain,9eb811e7bc3db3193b57609425723c478e438d32/api/aiExpectation vs. Reality
Expected: An AI proposal remains attached to the project and source version that produced it. If the user changes projects while the request is pending, accepting that stale proposal must not modify the new project.
Actual:
askcaptures the originalcurrentproject for the request, but stores the resulting proposal in global state without a project ID.acceptProposalapplies its files to whichever project is active when the user clicks Accept. A proposal for A'smain.pycan overwrite B'smain.py.Reproduction Path
main.py./api/aiis pending, switch to project B (a delayed or mocked response can make this deterministic).main.py.Minimal reproduction:
proposal = generate(A); activeProject = B; accept(proposal).Blast Radius
Evidence