Skip to content

fix(console): a running turn on an empty project never meets a Retry - #634

Merged
hevayo merged 1 commit into
wso2:mainfrom
hevayo:fix/629-retry-while-writing
Aug 26, 2026
Merged

fix(console): a running turn on an empty project never meets a Retry#634
hevayo merged 1 commit into
wso2:mainfrom
hevayo:fix/629-retry-while-writing

Conversation

@hevayo

@hevayo hevayo commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Fixes #629.

What

The spec rail attributes a running turn to a section by its flow token — and a turn with no token pulsed nothing. But the turn that carries a member's interview answers is plain prose, not a /<skill> command, and it is the very turn that writes the first requirements document. Unattributed, it left the spec workspace showing "Nothing written yet" plus a Retry that could fire /start against work in flight.

Two rules close it, one per surface:

  • railSections(): a flowless (or unrecognised-flow) turn on a project that holds nothing — no requirements, no design, no validation — claims Requirements by elimination: nothing downstream can be written before that document exists. The moment anything exists, the rail's honest silence resumes; known flows are attributed exactly as before, and guessing from emptiness stays retired.
  • SpecView: the empty state additionally requires no agent working at all, so the one flow the rail places elsewhere (/design typed into chat before any kickoff landed) cannot fall through to the Retry either — the pane shows a plain working spinner without naming a document it may not be writing.

SpecView inherits the first rule through requirementsActive (it reuses the rail's answer), so the common case — the answer turn, or any plain-chat first write — renders the existing "Agent is working on the requirements document" spinner with the Requirements section pulsing. The three copies of "does this project have requirements" in SpecView collapse into one shared predicate, and the rail's lexicon.md entry records the elimination exception.

Accepted sliver: for up to one status-poll interval after the answers are submitted, the console does not yet know a turn is running, so the Retry can flash briefly. A click there is backstopped: the seed is guarded and the panel drops it once the rehydrated thread shows the exchange in flight.

Proof of real execution

On the local stack (console rebuilt from this branch's tree), project office-parking-spot: kickoff /start → interview → Use recommended answers → the flowless answer turn. The workspace was sampled every second against the newest agent_turns row:

17:53:28 turn=running/<empty> ui=SPINNER
17:53:29 turn=running/<empty> ui=SPINNER
   … 30 consecutive samples, all SPINNER …
17:53:31 turn=running/<empty> ui=SPINNER

running/<empty> is exactly the shape from the issue's measurement. Zero samples showed Retry or "Nothing written yet" from the moment the status flipped to working through to the PRD landing in the workspace; the rail pulsed Requirements throughout, and the pane showed the working spinner.

Tests

  • railSections.test.ts: flowless + working + empty project → Requirements active; unknown org-skill flow → same; flowless with design-but-no-requirements → still silent (the elimination premise is strict); flowless once requirements exist → silent; empty project with nobody working → not-started.
  • SpecView.test.tsx: the flowless answer turn renders the spinner and no Retry; a /design run on an empty project renders a plain "Agent is working" and no Retry. The pre-existing pin that a design run never claims the requirements document still passes.
  • Spec feature suite: 25 files / 290 tests pass; tsc clean for the touched files (the src/features/marketplace/* errors on main are pre-existing and untouched); eslint clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MpXLxZ5x5PNYZrJ5Gmf5cG

The rail attributes a running turn to a section by its flow token, and a
turn with no token pulsed nothing — but the turn that carries a member's
interview answers is plain prose, and it is the very turn that writes the
first requirements document. Unattributed, it left the spec workspace
showing "Nothing written yet" plus a Retry that could fire /start against
work in flight (wso2#629).

Two rules close it, one per surface:

- railSections: a flowless turn on a project that holds NOTHING claims
  Requirements by elimination — nothing downstream can be written before
  that document exists. The moment anything exists the rail's honest
  silence resumes; known flows are attributed exactly as before.
- SpecView: the empty state additionally requires no agent working at
  all, so the one flow the rail places elsewhere (/design typed before
  any kickoff landed) cannot fall through to the Retry either — the pane
  shows a plain working spinner without naming a document it may not be
  writing.

The three copies of "does this project have requirements" in SpecView
collapse into one shared predicate, and the rail's lexicon entry records
the elimination exception.

Fixes wso2#629

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MpXLxZ5x5PNYZrJ5Gmf5cG
@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 310a140d-366a-43ac-91da-42bb3e1f021e

📥 Commits

Reviewing files that changed from the base of the PR and between 22a84cf and dd55576.

📒 Files selected for processing (5)
  • apps/console/design/lexicon.md
  • apps/console/src/features/spec/components/SpecView.test.tsx
  • apps/console/src/features/spec/components/SpecView.tsx
  • apps/console/src/features/spec/lib/railSections.test.ts
  • apps/console/src/features/spec/lib/railSections.ts

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Summary

  • Attribute flowless or unknown running turns to Requirements only when the project has no specification files.
  • Keep the working state visible and suppress the empty state and Retry action during agent work.
  • Reuse the requirementsActive predicate in SpecView.
  • Add rail and empty-state tests for flowless, unknown, design, and existing-content scenarios.
  • Document the fallback behavior in lexicon.md.

Walkthrough

The rail now uses the running flow token to select an active section. For flowless or unknown work, Requirements is active only when the project has no requirements, design, or validation content. SpecView uses the shared requirements-file check, shows a generic working state for unattributed work, and hides the empty state and Retry action while an agent is working. Tests cover empty and partially populated projects.

Sequence Diagram(s)

sequenceDiagram
  participant Agent
  participant RailSections
  participant SpecView
  Agent->>RailSections: report active flow and project content
  RailSections->>RailSections: select mapped section or empty-project Requirements fallback
  RailSections-->>SpecView: return section activity
  SpecView->>SpecView: evaluate active work and requirements files
  SpecView-->>Agent: show requirements or generic working state
Loading

Suggested reviewers: axewilledge

Merge Risk: ⚪ Minimal · up to dd555

The console now keeps the Requirements view in a working state while the first document is being written and prevents an unsafe Retry from appearing during active work. No actionable merge-blocking risk remains beyond normal checks.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the console fix for running turns on empty projects and the unintended Retry state. It is concise and directly related to the primary change.
Description check ✅ Passed The description directly explains the flowless-turn attribution problem, the empty-state and Retry fixes, the implementation approach, and the test coverage.
Linked Issues check ✅ Passed The changes satisfy issue #629. Flowless or unrecognized running turns claim Requirements only on completely empty projects, and SpecView suppresses the empty state and Retry while any agent work is a…
Out of Scope Changes check ✅ Passed The changes remain within issue #629. They update rail attribution, SpecView empty-state behavior, tests, and the related lexicon documentation. No unrelated code changes are identified.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 4 files. (1 skipped: 1 …
Full details: Linked Issues check

Explanation

The changes satisfy issue #629. Flowless or unrecognized running turns claim Requirements only on completely empty projects, and SpecView suppresses the empty state and Retry while any agent work is active. Existing flow attribution remains unchanged.

Full details: Docstring Coverage

Explanation

Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 4 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@hevayo
hevayo merged commit a15e140 into wso2:main Aug 26, 2026
4 checks passed
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.

Retry is offered while an agent is writing the requirements

3 participants