Skip to content

feat(tasks): start a task from Home and email the reporter its PR - #7159

Merged
viktormarinho merged 3 commits into
mainfrom
t3code/agent-steering-task-workflow
Sep 11, 2026
Merged

viktormarinho merged 3 commits into
mainfrom
t3code/agent-steering-task-workflow

Conversation

@viktormarinho

@viktormarinho viktormarinho commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Reporting something shouldn't mean visiting the board, moving the card to To-do, and clicking Run. Home's search box becomes the chat composer with a Task toggle (on by default): describe the problem, press Start task, and you land in the new chat watching an intake agent find the repository, file the card assigned to the Super Agent — which already queues execution — and hand back the link. When the agent side of the review ends and the card lands In Review, the reporter gets one email linking every PR.

Behind the default-off org flag home_task_intake_enabled. Cmd+K search and ordinary chat are unchanged; the existing /task guide still only saves a task.

Home task composer

Mobile, Task mode off, and the PR-ready email Home task composer on mobile

Toggling Task off gives an ordinary chat — the submit button reverts to the send arrow and the hand-off hint disappears:

Task mode off

The PR-ready email, rendered from buildPrReadyEmail with synthetic data (subject: DECO-144 is ready for your review):

PR-ready email

Included fixes (the flow doesn't work without them)

  • enqueueThreadRun couldn't enqueue from a built-in tool. Those run inside the agent loop's own DBOS step, where DBOS.startWorkflow throws Invalid call to a 'workflow' function from within a 'step'. It now detects that and writes the queue entry with DBOSClient instead. Pre-existing and not specific to this feature: any agent asked to delegate a task hit the same failure, swallowed by reactToSuperAgentDelegation's best-effort catch.
  • The hand-off landed with the chat closed. sidepanel is a retained search param, so pressing Start task from a Home whose chat panel was collapsed navigated to the new thread with the report invisible behind "Show chat". It now forces sidepanel=true&mainpanel=false. There's an e2e assertion for it that fails without the fix.
  • A card that names a repo now binds THAT repo before dispatch (pickSoleTaskRepo(choices, preferredRepo)), so a multi-repo org doesn't spend a turn re-picking what the card already decided. An unknown or ambiguous name narrows to nothing and falls back to today's mid-run TASK_ADD_REPO pick.

No migration

The email is sent at the handoff (parkReviewedCardForHuman, the single "it is your turn" transition) rather than written as a notifications row. A new row type would have cost a CHECK-constraint change plus re-verification at send time, for an inbox entry the card already provides. That transition is already a no-op unless the card is mid-cycle In Progress, so one email per review cycle falls out of it — no dedup key.

Deliberately not in this PR

  • No submission-id dedup. If the intake agent calls TASK_BOARD_ITEM_CREATE twice, you get two cards. The guide tells it to check TASK_BOARD_ITEM_LIST first, which is a prompt, not a gate. A duplicate card is visible and deletable; a unique index is a migration. Revisit if it actually happens.
  • No custom receipt UI or inline retry in the chat — the generic tool-call part renders the create, and the card is on the board either way.
  • Orgs with both automated reviewers disabled still never reach In Review, so they get no email. That's a pre-existing hole in enqueueEnabledReviewers (reviewers default ON), worth its own fix.

Validation

  • Workspace type checks pass; lint passes (14 pre-existing warnings, 0 errors); knip clean; formatted.
  • 8,709 unit tests pass, including new ones for the email copy/escaping and the repo-pinning filter.
  • Both e2e tests in packages/e2e/tests/home-task-intake.spec.ts pass against real Postgres — the toggle and draft persistence, and that submitting sends the report plus the start-task guide in one /messages payload and lands with the chat open.
  • Driven by hand in the local app end to end: Task mode submits, the thread opens with the /start-task guide and the report, and the run dispatches.
  • The guide was probed against a real model (openai/gpt-4o-mini via OpenRouter), replaying the shipped START_TASK_PROMPT verbatim against the real tool surface. It picks the repo from the list output, short-circuits on a duplicate without creating, and asks rather than inventing when the org has no repos. Two prompt bugs came out of that and are fixed: an instruction the server already overrides (status), and a demand for a "task link" the tools never return, which made the model invent URLs.
  • Still not exercised: the full hosted run, and outbound email. The Decopilot agent loop executes inside the agent sandbox, which is a Kubernetes provider (@kubernetes/client-node), so it cannot start on a laptop with no cluster — the DBOS enqueue fix is reasoned from the SDK's own guard and type-checked, not watched. No SMTP provider in dev either.

Known limitation

When several repositories could plausibly match and the report names none, the model picks one instead of asking, and the repo-pinning above then binds that guess. Tightening the prompt to force a question regressed it badly — the model started skipping TASK_BOARD_ITEM_LIST entirely and inventing repository names — so the weaker wording is deliberate. The card is visible on the board with an editable repo, and orgs with one repo (the common case) are unaffected.

Replaces the first draft of this branch, which had grown to 52 files and a migration.

Home's search box becomes the chat composer with a Task toggle, on by
default. Describe the problem, press Start task, and an intake agent finds
the repository, files the card assigned to the Super Agent — which already
queues execution — and hands back the link. No board visit, no move to
To-do, no Run click. When the agent side of the review ends and the card
lands In Review, the reporter gets one email with a link to every PR.

Behind the default-off org flag `home_task_intake_enabled`.

Two fixes the flow needs:

- `enqueueThreadRun` could not enqueue from a built-in tool, because those
  run inside the agent loop's own DBOS step and DBOS rejects
  `startWorkflow` there. It now detects that and writes the queue entry
  with `DBOSClient` instead. Pre-existing: any agent asked to delegate a
  task hit the same swallowed failure.
- A card that names a repo now binds THAT repo before dispatch, so a
  multi-repo org doesn't spend a turn re-picking what the card decided.

No migration. The email is sent at the handoff rather than written as a
notification row, which would have cost a CHECK-constraint change plus
re-verification at send time for an inbox entry the card already provides.
@viktormarinho
viktormarinho force-pushed the t3code/agent-steering-task-workflow branch from 9761be8 to c54cb23 Compare September 11, 2026 19:45
@viktormarinho viktormarinho changed the title feat(tasks): report from Home, start an agent, get the PR by email feat(tasks): start a task from Home and email the reporter its PR Sep 11, 2026
`sidepanel` is retained across navigation, so pressing Start task from a
Home whose chat panel was collapsed landed on the new thread with the
report invisible behind "Show chat". The hand-off now forces the chat
open and the main panel closed — the run is the only thing worth looking
at at that moment. Covered by an e2e assertion that fails without it.
TASK_BOARD_ITEM_LIST already returns `repos` — the org's imported
repositories, from the same `repositories.listByOrg` read, and its own
description calls them "the valid values for a task's repo". The guide
already called that tool to check for duplicates, so exposing a second
tool to answer the same question bought nothing and cost a round trip.

Probed against a real model with the shipped prompt verbatim: the repo
is picked correctly from the list output, a duplicate still short-circuits
before create, and the sequence is now LIST -> CREATE instead of
REPOSITORY_LIST -> LIST -> CREATE.
@viktormarinho
viktormarinho merged commit 3cd25be into main Sep 11, 2026
28 of 33 checks passed
@viktormarinho
viktormarinho deleted the t3code/agent-steering-task-workflow branch September 11, 2026 20:33
decocms Bot pushed a commit that referenced this pull request Sep 11, 2026
PR: #7159 feat(tasks): start a task from Home and email the reporter its PR
Bump type: minor

- decocms (apps/api/package.json): 4.354.0 -> 4.355.0
- @decocms/native (apps/native/package.json): 4.354.0 -> 4.355.0
- @decocms/e2e (packages/e2e/package.json): 1.71.0 -> 1.72.0
- @decocms/shared (packages/shared/package.json): 0.95.0 -> 0.96.0

Deploy-Scope: both
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.

1 participant