Effect-ification: Instance deleted, 0 ALS fallbacks, 81 TUI tests#21
Merged
Effect-ification: Instance deleted, 0 ALS fallbacks, 81 TUI tests#21
Conversation
added 30 commits
March 18, 2026 15:00
…e Instance.* from tool layer (B2) Tool.Context and Tool.InitContext now carry directory/worktree/projectID/containsPath fields. All 17 tool execute() handlers read from ctx instead of Instance singleton. Construction sites in prompt.ts and registry.ts populate the new fields. 12 test files updated with mock context. New service-layers.ts and tui-service.ts support the Effect layer infrastructure. ~20 Instance.* occurrences removed from tool layer. 1423 tests pass, 0 failures.
…ading (B3) Add optional `directory` parameter to internal state() functions in env, bus, command, provider, plugin, mcp, pty, and agent modules. Each state() now accepts explicit directory with ALS fallback (directory ?? Instance.directory). - scripts.ts: fully Instance-free, uses ctx.directory from tool context - bus: publish/subscribe/once/subscribeAll gain optional directory param - env: get/set/all/remove gain optional directory param - command: get/list gain optional directory param, worktree captured at init - agent: worktree captured at init time instead of lazy ALS read - plugin: state/initPlugins/trigger/list/init gain optional directory param - mcp: state/create gain directory param, threaded through initialization - pty: state() parameterized (bind sites deferred to B4) - EnvService/BusService layers: read from InstanceContext instead of Instance 7 direct Instance reads removed, 17 expected remnants (fallbacks, worktree, bind). 1423 tests pass, 0 failures.
…(B4) Replace all 5 Instance.bind() call sites with plain closures that capture directory from the surrounding scope (InstanceContext or local variable). Callbacks now pass directory explicitly to Bus.publish/subscribe. - file/watcher.ts: capture directory from InstanceContext, pass to Bus.publish - project/vcs.ts: capture directory, pass to Bus.subscribe and Bus.publish - format/index.ts: capture directory, pass to Bus.subscribe - pty/index.ts: capture directory in create(), pass to Bus.publish and remove() - file/index.ts: replace Instance.containsPath with local containsPath using instance.directory and instance.project.worktree from InstanceContext Instance import removed from watcher.ts, vcs.ts, format/index.ts, file/index.ts. 1423 tests pass, 0 failures.
…s (B5) Change Formatter.Info.enabled() signature to accept (directory, worktree) parameters. All 25 formatter enabled() functions updated. Callers in FormatService.layer pass instance.directory and instance.project.worktree from InstanceContext. Instance import removed from formatter.ts. 8 Instance.* occurrences eliminated. 1423 tests pass, 0 failures.
Add directory/worktree parameters to LSPServer.Info.root() and spawn() interfaces. All 37 server definitions updated. NearestRoot helper takes directory param instead of reading Instance.directory. - server.ts: Instance import removed, all 11 Instance refs eliminated - index.ts: state() parameterized, getClients/hasClients capture directory/worktree from Instance (ALS fallback for now) - client.ts: create() takes directory param, Instance import removed 16 Instance occurrences eliminated across 3 files. 1423 tests pass, 0 failures.
…atus, compaction, llm (B7) Add optional directory/worktree/project parameters to session module leaf helpers with ALS fallback: - system.ts: environment() takes optional ctx with directory/worktree/project - instruction.ts: state(), systemPaths(), resolve(), resolveRelative() parameterized InstructionService.layer reads from InstanceContext - status.ts: state() parameterized, SessionStatusService reads InstanceContext - compaction.ts: process() takes optional directory/worktree - llm.ts: StreamInput gains projectID field, header uses it with ALS fallback prompt.ts and index.ts construction sites deferred to B10. 14 Instance.* occurrences parameterized with ALS fallback. 1423 tests pass, 0 failures.
Worktree module: capture Instance.worktree/project at function entry in makeWorktreeInfo, createFromInfo, remove, reset. Internal candidate() takes explicit worktree param. 21 → 9 Instance refs (all ALS fallbacks or Instance.provide for B10). Config module: state() parameterized, initConfig() captures directory/worktree at entry. TUI config: state() parameterized, initTuiConfig() captures at entry. migrate-tui-config: opencodeFiles() takes optional directory/worktree. ~25 direct Instance reads replaced with captured values or ALS fallbacks. 1423 tests pass, 0 failures.
STATUS.md: added Effect-ification progress table (B1-B8 done), list of Instance-free and ALS-fallback modules PLAN.md: updated status line, added B2-B10 to completed/next table WHAT_WE_DID.md: added Phase 7 section with B1-B8 commit table DO_NEXT.md: replaced stale backport items with B9-B10 checklist
…on/tool APIs (B9) Session: createNext, plan, list accept optional directory/project/worktree params with ALS fallback. Removed dead Instance.project ref in remove(). Server routes: capture Instance values at handler entry. CLI commands: capture Instance values inside provide callbacks. tool/registry: parameterize state() with optional directory. project/bootstrap: capture directory and projectID at entry. debug/agent: add missing context fields (directory, worktree, projectID).
…nce ALS (B10a-b) service-layers.ts: all 10 layer constructors use yield* InstanceContext instead of Instance.directory. runtime.ts: runPromiseInstance accepts optional directory param. instances.ts: lookup uses side-map with Instance.current fallback; Instances.get accepts optional context shape.
… (B10c) Prompt functions (loop, resolveTools, createUserMessage, shell) capture Instance values at entry and use locals throughout. resolveTools accepts optional directory/worktree/projectID params with ALS fallback. Deep tool context construction sites use captured locals instead of Instance directly. Also adds pre-existing-failures policy to AGENTS.md.
Separate context propagation (ALS) from bootstrap/lifecycle concerns. InstanceALS provides directory, worktree, project, current, containsPath, run, and bind — no cache, no bootstrap, no disposal. Instance delegates all ALS reads to InstanceALS internally. Zero behavioral change.
Pass explicit directory to Bus.publish calls inside Database.effect closures where Session.Info.directory is in scope. Eliminates ~13 ALS fallbacks in session CRUD operations (touch, create, share, setTitle, setArchived, setPermission, setRevert, clearRevert, setSummary, remove).
Add optional directory param to SessionStatus.set/get/list so callers with captured directory can bypass ALS. Thread _dir through Bus.publish and SessionStatus.set calls in prompt.ts loop and createUserMessage. Pass input.directory to Bus.publish in compaction.ts.
Extract boot/cache/dispose/disposeAll/reload logic from Instance into InstanceLifecycle. Instance.provide becomes a thin wrapper calling InstanceLifecycle.boot + InstanceALS.run. Zero behavioral change.
…ecycle (B10f-2) Replace Instance.provide with InstanceLifecycle.boot + InstanceALS.run across all entry points: CLI commands (agent, mcp, github, pr, models, providers), TUI (worker, attach, thread), server (server.ts, routes), control-plane workspace server, worktree, config, and cli/bootstrap. Replace Instance.dispose with InstanceLifecycle.dispose(directory), Instance.disposeAll with InstanceLifecycle.disposeAll(), and Instance.reload with InstanceLifecycle.reload. Instance module now has zero callers for lifecycle operations.
Replace all Instance.directory/worktree/project/current/containsPath reads with InstanceALS equivalents across 40 files. Zero imports of Instance remain — the module is now unused and ready for deletion.
Instance module is now a thin shim delegating to InstanceALS + InstanceLifecycle. Zero src/ code imports Instance — only test fixtures use it. The three concerns are fully decoupled: - InstanceALS: context propagation (ALS reads) - InstanceLifecycle: boot/dispose/reload (cache + lifecycle) - InstanceContext: Effect service layer bridge Fix duplicate InstanceALS import in worktree/index.ts.
…ce.ts
Move Instance compatibility shim from src/project/instance.ts to
test/fixture/instance-shim.ts. Update all 58 test file imports.
Delete the src/ copy — zero src/ code references Instance now.
The shim delegates to InstanceALS (context) + InstanceLifecycle
(boot/dispose/reload) and is kept only because 58 test files use
Instance.provide({ directory, init?, fn }) which would be a
fragile mechanical rewrite to inline.
Remove ?? InstanceALS.directory fallbacks from 15 leaf module state() functions. Callers now pass directory explicitly. Also makes runPromiseInstance() directory param required and updates all 10 call sites in src/ to pass InstanceALS.directory.
…te-tui-config) Make directory required in Command.get/list, MCP local transport, SessionStatus.get/list/set, and MigrateInput. Update all callers. 36 fallbacks remain (session core, worktree, env, bus, plugin, pty, bash).
New test infrastructure: - test/cli/tui/helpers.tsx: reusable mock factories for all TUI contexts (theme, dialog, sync, sdk, local, route, keybind, kv, toast) Dialog tests (5 files, 15 tests): - dialog-agent, dialog-model, dialog-theme-list, dialog-session-list, dialog-skill — each with 3 test cases Standalone component tests (3 files, 9 tests): - logo, spinner, tips — verify render output Total: 81 TUI tests across 13 files (was 56 across 5).
Launches frankencode in a tmux session, sends keystrokes, captures terminal frames, and asserts on visible content. Flows tested: home splash, command palette, agent cycling, message submission + LLM response, cost dialog. Usage: bun test/cli/tui/tmux-tui-test.ts [--flow <name>]
PLAN.md: mark Effect-ification complete, note 36 deferred fallbacks STATUS.md: accurate counts (1447 tests, 123 files, 36 fallbacks, 150 entry-point reads, 0 TS errors, 27 commits on branch) DO_NEXT.md: itemized remaining fallbacks by module with caller counts BUGS.md: add manual TUI testing results (2026-03-20, all pass)
Make directory/worktree/projectID/ctx required in: - session/system.ts (3): environment() ctx parameter - session/instruction.ts (5): resolveRelative, state, systemPaths, resolve - session/compaction.ts (2): process() directory/worktree - session/llm.ts (1): stream() projectID - session/index.ts (4): createNext, plan, list project param - session/prompt.ts (5): resolvePromptParts, cancel, resolveTools 16 fallbacks remain (worktree, pty, bash, env, bus, plugin).
added 3 commits
March 20, 2026 10:50
- worktree/index.ts: make ctx required in makeWorktreeInfo, createFromInfo - pty/index.ts: make directory required in remove() - tool/bash.ts: guard initCtx.directory, remove InstanceALS import 10 fallbacks remain (env: 4, plugin: 4, bus: 2).
env/index.ts (4): make directory required in get/all/set/remove plugin/index.ts (4): make directory required in trigger/list/init bus/index.ts (2): make directory required in publish/subscribe Updated 25 Env callers, 31 Plugin callers, 78 Bus callers across 29 src/ files and 9 test files. Total: 59 of 59 ALS fallback patterns eliminated.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Complete Effect-ification of the Instance module — 33 commits across 181 files.
src/project/instance.ts— zero src/ imports. Test-only shim attest/fixture/instance-shim.ts?? InstanceALS.xfallback patterns — every module now receivesdirectory/worktree/projectIDexplicitlyInstance decoupling (B1-B10g)
Instance split into three modules:
InstanceALS— AsyncLocalStorage context propagation (directory, worktree, project)InstanceLifecycle— boot/dispose/reload with cachingInstanceContext— Effect layer bridgeALS fallback elimination (59/59)
TUI tests
test/cli/tui/helpers.tsx— reusable mock factories for all TUI contextstest/cli/tui/tmux-tui-test.ts— tmux-based integration harness (5 flows)Manual testing (2026-03-20)
All TUI flows verified: home screen, command palette, agent cycling, message submission, cost dialog.
Test plan
bun test— 1447 pass, 0 fail, 8 skippednpx tsc --noEmit— 0 errorsgrep '?? InstanceALS' src/— 0 matchesgrep 'project/instance"' src/— 0 matches