🤖 refactor: pass the WorkspaceService archive gate to workflow admissions instead of a process-global guard - #4562
Conversation
…ns instead of a process-global guard
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
@codex review |
|
Codex Review: Didn't find any major issues. Breezy! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
Summary
Removes the process-wide workflow archive guard. Workflow start/resume/retry admissions now ask the owning
WorkspaceServicedirectly (getWorkflowArchiveRefusal), passed in throughWorkflowServiceContextand a requiredWorkflowServiceconstructor option. With nothing registered at module scope, aWorkspaceServicebuilt in one test file can no longer decide admissions in another. The three per-file guard resets, including #4530's, are deleted.Background
Every
WorkspaceServiceconstructor calledsetWorkflowArchiveAdmissionGuard(...)with a closure over its own config and never cleared it. After #4475 split the WorkspaceService tests, a split file sharing a unit shard withWorkflowService.context.test.tsleft a guard over a partial config double behind, and 9 context tests failed. #4530 reset the guard in that one file;evaluateScreening.test.tsandWorkflowService.test.tscarried the same reset. The leak itself stayed open.A compare-and-clear release on dispose would not have closed it: about 170 test fixtures build a
WorkspaceServicewithout disposing it, so the last guard would still outlive its file.Implementation
workflowArchiveAdmission.ts:admissionGuardandsetWorkflowArchiveAdmissionGuardare gone.acquireWorkflowArchiveAdmission(guard, workspaceId)takes aWorkflowArchiveAdmissionGuard.WorkspaceService: the constructor closure became the publicgetWorkflowArchiveRefusal(workspaceId), with the same body. The class declaresimplements WorkflowArchiveAdmissionGuard.WorkflowService: new requiredarchiveAdmissionoption, so tsgo finds every construction site. It is wired at all three production sites:resolveWorkflowContextpassescontext.workspaceService.cli/workflow.tspasses the CLI's ownservices.workspaceService, which is the instance whose guard was installed before.TurnRequestBuilderget a newworkflowArchiveAdmissionbinding. It is set indi/layers/core.tsnext to the other WorkspaceService bindings, and the builder asserts it whentaskServiceis bound.startWorkflowRun/resumeWorkflowRun/retryWorkflowRunFromCheckpointpasscontext.workspaceService.Tests:
WorkflowService.test.tsinjects its gate instead of setting and resetting a global.WorkspaceServicerefuses archived and archiving workspaces, and admits active, unarchived and unknown ones. The logic previously had no owner-side coverage.startWorkflowRunrefuses through the context's WorkspaceService before creating a run. Replacing both the top-level and the class-level gate with an admit-all stub makes it fail.Validation
bun test workspaceService.archive workspaceService.bashAndFiles workflows/WorkflowService.context workflows/evaluateScreening workflows/WorkflowService.bun test src/node/services/workflows: 347 pass.bun test src/node/services/{workspaceService,taskService,turnRequestBuilder}* src/node/services/serviceContainer.test.ts: 1701 pass.src/node/services/{agentSession*,tools}andsrc/node/orpcalso pass.src/clipasses aftermake build-main. One run under host load 66 timed out "CLI run closes the AppFiberScope first…" at 5 s;workflow.test.tsthen passed 3 of 3 runs on its own.make static-checkpasses.Risks
Low. Admission semantics are unchanged in production, which has one WorkspaceService per process; the refusal is now looked up explicitly instead of through a module variable. A future
WorkflowServiceconstruction must supply the gate, and the type system enforces that.Generated with
xum• Model:anthropic:claude-opus-5-5• Thinking:high