Skip to content

Delivery issue409 - #411

Merged
LeXwDeX merged 4 commits into
devfrom
feat/409-issue409
Aug 21, 2026
Merged

Delivery issue409#411
LeXwDeX merged 4 commits into
devfrom
feat/409-issue409

Conversation

@LeXwDeX

@LeXwDeX LeXwDeX commented Aug 21, 2026

Copy link
Copy Markdown
Owner

Closes #409

Why

opencode run "/memory" (and run --command memory) hung forever with zero output, while the same command via serve POST /session/:id/command returned instantly. Early-return command dispatches (/memory, /trust, /goal non-kick at packages/opencode/src/session/prompt.ts) write a user message + text parts and return WITHOUT entering the session runner. The run CLI exits its event loop only on the session.status {type:"idle"} event (run.ts), which only the runner's onIdle publishes — so these commands never emitted it. Secondary: run mode prints text parts only when time.end is set; the early-return response parts carried no time, so output would have been empty even without the hang.

What changed

  • packages/opencode/src/session/prompt.ts: new commandTurn helper runs the early-return writes as a micro-turn via SessionRunState.startIfIdle — idle sessions get the real busy→idle transition (idle event fires, run mode exits); busy sessions keep today's inline semantics (no queueing, no duplicate idle), preserving the /goal busy guards.
  • /memory, /trust, and /goal//subgoal non-kick branches now wrap their message/part writes in commandTurn; response parts carry time: { start, end } so run-mode consumers print them.
  • Goal kick dispatch stays OUTSIDE the turn (its busy guards read the live session status, which a busy marker would corrupt); the kick path then enters loop() as before.

Evidence

  • TDD regression suite packages/opencode/test/cli/run/early-return-command.test.ts (4 arms: run "/memory", run --command memory, run --command trust status, run "/goal"): RED before fix (30s spawn-timeout kill, exit ≠ 0), GREEN after (all exit 0, non-empty stdout, ~1.3s each).
  • Adjacent suites green: headless-init.test.ts (fix: headless init does not stamp project time_initialized so memory stays inert #404, 4/4), goal.test.ts + workspace-trust.test.ts + dag-goal-wake-retrigger.test.ts (50/50), prompt.test.ts + httpapi-memory-wiring.test.ts (78 pass), bun run test:dag-core gate passed.
  • CI at PR head all green: Typecheck, Unit Tests (linux), E2E Tests (linux + windows), SpecGit Acceptance.
  • bun typecheck (packages/opencode) and repo bun run lint ratchet clean (4837 ≤ 4850).

Checklist

  • Why, What changed, and Evidence are filled in.
  • specgit finish exits 0.

Early-return command dispatches (/memory, /trust, /goal non-kick) wrote
their parts and returned without ever entering the session runner, so the
busy→idle status transition never fired and the run CLI — which exits its
event loop only on the idle event — hung forever (#409). The response
parts also lacked time.end, which run mode requires before printing text.

Run the early-return writes as a micro-turn via SessionRunState.startIfIdle
(idle sessions get the busy→idle transition; busy sessions keep today's
inline semantics so the /goal busy guards still read true status), and
stamp time {start,end} on the response parts. Goal kick dispatch stays
outside the turn: its guards read the live session status.

Regression: test/cli/run/early-return-command.test.ts (4 arms, all exit 0
with non-empty output).
@LeXwDeX
LeXwDeX marked this pull request as ready for review August 21, 2026 01:08
@LeXwDeX
LeXwDeX changed the base branch from main to dev August 21, 2026 08:23
@LeXwDeX
LeXwDeX merged commit 49ee9b9 into dev Aug 21, 2026
8 checks passed
@LeXwDeX
LeXwDeX deleted the feat/409-issue409 branch August 21, 2026 08:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: run mode hangs forever on early-return commands like memory and trust

1 participant