feat: preview workflow moves before execution (#3677)
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
---
|
||||
created: 2026-09-14
|
||||
status: implemented
|
||||
requirements:
|
||||
- REQ-TASKS-WORKFLOW-MOVE-PREVIEW-001
|
||||
- REQ-TASKS-WORKFLOW-MOVE-PREVIEW-002
|
||||
system_design:
|
||||
- ../../specs/tasks/system-design/workflow-move-preview.md
|
||||
legacy_specs: []
|
||||
---
|
||||
|
||||
# Implementation Plan: Workflow Move Preview
|
||||
|
||||
## Overview
|
||||
|
||||
Add compact task-specific recipient and model feedback before a step move.
|
||||
Deliver a read-only shared backend decision first, then integrate the desktop
|
||||
popover and phone drawer with end-to-end move verification. The backend boundary
|
||||
needs isolated side-effect and routing-parity proof before any UI depends on it.
|
||||
|
||||
Confirmed user choices: two summary lines, current/other/new conversation,
|
||||
unchanged or before/after model, additional settings count, optional details.
|
||||
The preview includes conditional Codex model changes without profile changes.
|
||||
|
||||
## Scope
|
||||
|
||||
### In scope
|
||||
|
||||
- Task stepper and compact step disclosure, including task preview use sites.
|
||||
- Read-only move prediction using runtime overrides and entry options.
|
||||
- Conditional set, keep, restore-original and no-match behavior.
|
||||
- Loading, retry, uncertainty, accessibility, five locales, and phone composition.
|
||||
|
||||
### Out of scope
|
||||
|
||||
- Changes to session routing policy, profile defaults, provider acceptance,
|
||||
native subagents, workflow editing, or mandatory move confirmation.
|
||||
- Board drag, bulk moves, and unrelated move menus.
|
||||
- Production instance mutation or live provider probes during development.
|
||||
|
||||
## Technical approach
|
||||
|
||||
Follow the [design](../../specs/tasks/system-design/workflow-move-preview.md).
|
||||
Extract shared read-only decisions from orchestrator workflow routing and
|
||||
conditional configuration. Add the proposed task move-preview endpoint and
|
||||
DTO, then a domain API client/hook and shared renderer. Keep execution-time
|
||||
atomic checks and existing move semantics authoritative.
|
||||
|
||||
Nearest shipped mobile surface: `workflow-step-disclosure.tsx`.
|
||||
Curated baseline: MobilePickerSheet and the mobile UI language's temporary
|
||||
choice drawer. Use its fixed header, internal scroll, safe-area clearance,
|
||||
focus return, and shared state logic.
|
||||
|
||||
No schema or persistent preview cache. The design carries the endpoint contract;
|
||||
no separate architecture decision is needed for an advisory projection of the
|
||||
existing lifecycle. Public documentation changes belong to implementation.
|
||||
|
||||
## ASCII UI preview
|
||||
|
||||
Structural requirements: exactly two centered collapsed summary rows below actions and capabilities;
|
||||
an icon-only info button expands details below the summary; Options and existing capability/progress
|
||||
content stay available. Spacing and abbreviated data below are illustrative.
|
||||
All drawn strings become localized copy or model/session data.
|
||||
|
||||
### UI-01: Desktop step hover or keyboard disclosure
|
||||
|
||||
AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.1 through .5 and -002.1, .4.
|
||||
|
||||
```text
|
||||
+--------------------------------+
|
||||
| -> Move here |
|
||||
| Options |
|
||||
| [step capabilities] |
|
||||
|--------------------------------|
|
||||
| Reuse current session |
|
||||
| Astra -> Luna +2 (i) |
|
||||
+--------------------------------+
|
||||
|
||||
Expanded details appear beneath the footer.
|
||||
Other outcomes: New session; Reuse: Implementation; No session starts.
|
||||
Unchanged model: Astra (override retained), or Luna without an override.
|
||||
```
|
||||
|
||||
The footer layout was revised after implementation with user approval. The
|
||||
next-step options form above chat uses the same footer below its Move action.
|
||||
|
||||
`+2` means reasoning and context reset here, excluding the already displayed
|
||||
model change. A model-only change has no count. Details disclose uncertainty,
|
||||
skipped rules, full labels, profile, and source retirement as applicable.
|
||||
|
||||
### UI-02: Phone step drawer
|
||||
|
||||
Entry: tap the existing current-step disclosure. The drawer keeps its fixed
|
||||
header and one scroll body. AC-TASKS-WORKFLOW-MOVE-PREVIEW-002.2, .4.
|
||||
|
||||
```text
|
||||
+--------------------------------+
|
||||
| Move to x | fixed header
|
||||
|--------------------------------|
|
||||
| Analysis (current) |
|
||||
|--------------------------------|
|
||||
| Implement |
|
||||
| [Options] [Move here] |
|
||||
| Reuse current session |
|
||||
| Astra -> Luna +1 (i) |
|
||||
|--------------------------------|
|
||||
| Review |
|
||||
| [Options] [Move here] |
|
||||
| Reuse: Analysis |
|
||||
| Astra (i) |
|
||||
|________________________________| safe-area clearance
|
||||
```
|
||||
|
||||
Details expand in the same scroll body, immediately after the summary. All touch
|
||||
actions have at least 44px hit areas. No stacked overlays or horizontal scrolling.
|
||||
Same projection and move draft serve desktop and phone.
|
||||
|
||||
### UI-03: Loading, error, unknown
|
||||
|
||||
AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.5, .7 and -002.3.
|
||||
|
||||
```text
|
||||
+-------------------------+ +-------------------------+
|
||||
| Move here | | Move here |
|
||||
| Options | | Options |
|
||||
|-------------------------| |-------------------------|
|
||||
| Checking session... | | Preview unavailable |
|
||||
| | | Retry |
|
||||
+-------------------------+ +-------------------------+
|
||||
|
||||
+-------------------------+
|
||||
| Move here |
|
||||
| Options |
|
||||
|-------------------------|
|
||||
| New session |
|
||||
| Model not known (i) |
|
||||
+-------------------------+
|
||||
```
|
||||
|
||||
Loading, error, or unknown alone does not disable Move here. Existing permission,
|
||||
pending-move, and task gates still apply. Phone rows use these same statuses.
|
||||
|
||||
## Tests
|
||||
|
||||
| Criteria | Planned evidence |
|
||||
| --- | --- |
|
||||
| 001.1, 001.2 | workflow_move_preview_test.go: PreviewMatchesMove, SameProfileOverride, ExplicitTargets, TerminalCandidates, NewSessionDefaults |
|
||||
| 001.3, 001.4, 001.5 | workflow_move_preview_test.go: ConditionalSetKeepRestore, OriginalEligibility, AmbiguousRules, UnknownCapabilities, DeduplicatedChanges |
|
||||
| 001.6 | workflow_move_preview_test.go: NoSideEffects; workflow_move_preview_http_test.go: AuthorizationAndRedaction |
|
||||
| 001.7, 002.3 | use-workflow-move-preview.test.ts: LateResponse, DraftChanges, ReopenReconnect, Retry; deferred-move backend fixture |
|
||||
| 002.1, 002.2, 002.4 | workflow-move-preview.test.tsx and workflow-stepper.test.tsx: summary/details, keyboard, counts, localization; phone E2E |
|
||||
|
||||
## E2E tests
|
||||
|
||||
New `tests/workflow/workflow-move-preview.spec.ts` (chromium) covers a retained
|
||||
session model override during an in-place move, reuse of another named session,
|
||||
and creation of a fresh profiled session. Each scenario inspects the preview,
|
||||
executes the move, and checks the resulting session identity or model against
|
||||
isolated fixture API state. Unit and integration tests cover conditional
|
||||
settings, reset and skipped states, no-session launch gates, authorization,
|
||||
fresh-launch configuration projection, and stale-response handling.
|
||||
|
||||
New `tests/workflow/mobile-workflow-move-preview.spec.ts` (mobile-chrome) covers
|
||||
the coarse-pointer touch drawer, inline details, 44px controls, focus return on
|
||||
dismissal, and no horizontal overflow. The scenario uses the repository's
|
||||
tablet context because the full phone task route uses `SessionMobileLayout` and
|
||||
does not render the desktop task stepper. Existing step-targeting and move-option
|
||||
suites provide the adjacent mobile regression evidence. No production DB or task
|
||||
is used.
|
||||
|
||||
## Work orders
|
||||
|
||||
- [x] [Task 01: Read-only move decisions and API](task-01-move-decision-api.md)
|
||||
- [x] [Task 02: Compact preview and move verification](task-02-compact-preview.md)
|
||||
|
||||
Order: 01 -> 02. Both are sequential. No delegation is authorized by this plan.
|
||||
|
||||
## Verification results
|
||||
|
||||
Design checks passed on 2026-09-14:
|
||||
|
||||
- `python3 scripts/list-docs.py validate`: 267 decisions and 911 specifications validated.
|
||||
- `python3 scripts/lint-spec-files.py --all`: all specification files passed.
|
||||
- `python3 scripts/lint-spec-files.test.py`: 36 tests passed.
|
||||
- Relative-link, acceptance-reference, and whitespace checks passed for all five files.
|
||||
- `git diff --check` passed; scoped git status confirmed all five new artifacts.
|
||||
|
||||
Implementation is complete and both work orders are complete.
|
||||
|
||||
- Backend package tests and the targeted race suite passed.
|
||||
- Frontend focused tests passed with 44 tests across five files. Typecheck,
|
||||
full lint, localization checks, and the new-code localization ratchet passed.
|
||||
- `make -C apps/backend build` and `pnpm run build:e2e` passed.
|
||||
- Desktop workflow E2E passed all 12 tests. Mobile workflow E2E passed all 5
|
||||
tests after the final drawer exit-state assertion was stabilized.
|
||||
- Specification, public-doc, and diff checks passed.
|
||||
|
||||
The mobile browser scenario uses the existing coarse-pointer tablet context to
|
||||
exercise `CompactWorkflowStepDisclosure`. The full Pixel 5 task route uses the
|
||||
separate `SessionMobileLayout` and does not render the desktop task stepper.
|
||||
This is a test-surface detail; the shared touch drawer remains the production
|
||||
mobile disclosure used by the task preview and tablet task surfaces.
|
||||
|
||||
### Review remediation addendum
|
||||
|
||||
The implementation evidence was extended after code-only review. Backend preview
|
||||
recipient selection now uses the same no-session launch predicate as execution,
|
||||
including the no-auto-start and skip-without-instructions gates. The preview
|
||||
returns `no_session` without a recipient when the task remains idle, and keeps
|
||||
the task-level profile fallback when an allowed fresh launch can occur.
|
||||
|
||||
The preview endpoint authorizes the task before reading task state. Existing
|
||||
source sessions retain current-session routing when no destination profile is
|
||||
configured, while profile changes can predict a fresh target session even when
|
||||
the destination does not auto-start a prompt. Fresh launches project applicable
|
||||
session settings, and context reset and mode changes report skipped states when
|
||||
execution cannot apply them. Busy reusable targets report deferred dispatch,
|
||||
and no-session dispatch has its own localized detail label.
|
||||
|
||||
Open previews now invalidate from live store revisions and connection changes,
|
||||
including session model and fallback updates, clear stale success while
|
||||
refreshing, and retain late-response guards. Every movable disclosure row can
|
||||
receive a preview through a two-request queue. Typed diagnostics and Kandev-owned
|
||||
fields and values render through the active locale; provider option labels remain
|
||||
bounded display data.
|
||||
|
||||
Additional remediation checks passed on 2026-09-15:
|
||||
|
||||
- `go test ./internal/workflow/move ./internal/orchestrator`.
|
||||
- `make lint` from `apps/backend`.
|
||||
- Focused Vitest: 3 files, 13 tests passed.
|
||||
- `pnpm run typecheck`, `pnpm run lint`, `pnpm run i18n:check`, and
|
||||
`pnpm run i18n:ratchet` from `apps/web`.
|
||||
|
||||
Final post-remediation verification passed on 2026-09-15:
|
||||
|
||||
- Focused Vitest passed all 50 tests across six affected files.
|
||||
- `make build` from `apps/backend` and `pnpm run build:e2e` from `apps/web`.
|
||||
- The focused desktop move-preview spec passed 2 tests, and the focused mobile
|
||||
move-preview spec passed 1 test.
|
||||
- `go test -race ./internal/orchestrator ./internal/task/handlers -run 'Preview|WorkflowStepSession|WorkflowSessionConfig|WorkflowSessionTarget|SameProfile'`.
|
||||
- `go test -race ./internal/orchestrator -count=1`, including the completed-task
|
||||
follow-up admission path.
|
||||
- `go test ./internal/orchestrator -run '^TestCompletedTaskFollowUpAdmissionIsConversationalOnly$' -count=100 -failfast`.
|
||||
- Specification, public-doc, formatting, and localization checks passed after
|
||||
trimming unrelated generated catalog churn.
|
||||
|
||||
### Approved footer revision (2026-09-15)
|
||||
|
||||
- Centered the preview below step actions and capabilities, with an info icon.
|
||||
- Added the same live-draft footer to chat and passthrough next-step options.
|
||||
- Passed 79 focused unit/component tests, typecheck, and changed-file lint.
|
||||
- Passed two desktop and two touch browser scenarios covering footer placement,
|
||||
next-step submission, inline details, and 44px touch targets.
|
||||
- Updated the requirements, design, work order, and public workflow guide.
|
||||
|
||||
## Risks
|
||||
|
||||
- Selection helpers can write provenance or warnings; preview must isolate pure decisions.
|
||||
- Live provider rejection and deferred moves cannot be guaranteed by a hover snapshot.
|
||||
- Runtime configuration can differ from mutable profile rows.
|
||||
- Read-only snapshots and WS updates race; stale-generation tests are required.
|
||||
- Long translations can crowd the compact surface; full details stay accessible.
|
||||
@@ -0,0 +1,141 @@
|
||||
---
|
||||
id: "01-move-decision-api"
|
||||
title: "Read-only move decisions and API"
|
||||
status: completed
|
||||
wave: 1
|
||||
depends_on: []
|
||||
plan: "plan.md"
|
||||
requirements:
|
||||
- REQ-TASKS-WORKFLOW-MOVE-PREVIEW-001
|
||||
- REQ-TASKS-WORKFLOW-MOVE-PREVIEW-002
|
||||
acceptance_criteria:
|
||||
- AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.1
|
||||
- AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.2
|
||||
- AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.3
|
||||
- AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.4
|
||||
- AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.5
|
||||
- AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.6
|
||||
- AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.7
|
||||
system_design:
|
||||
- ../../specs/tasks/system-design/workflow-move-preview.md
|
||||
---
|
||||
|
||||
# Task 01: Read-only move decisions and API
|
||||
|
||||
## Summary
|
||||
|
||||
Provide a task-specific preview of recipient and expected configuration without
|
||||
executing routing or ACP operations. Reuse decisions in execution paths so the
|
||||
endpoint and actual moves remain consistent.
|
||||
|
||||
## In scope
|
||||
|
||||
Shared recipient decision extraction, effective configuration and conditional
|
||||
rule projection, normalized one-shot reset/dispatch effects, DTO, authorized
|
||||
HTTP endpoint, dependency wiring, and focused backend regression fixtures.
|
||||
|
||||
## Out of scope
|
||||
|
||||
Rendered UI, schema migrations, changed lifecycle policy, provider probes,
|
||||
and caching or reserving preview selections.
|
||||
|
||||
## Acceptance
|
||||
|
||||
1. Real fixture moves match their previews for same/other/new session cases,
|
||||
explicit targets, overrides, and conditional settings; terminal exclusion holds.
|
||||
2. Repeated previews leave session/task metadata, bindings, messages, and runtime
|
||||
invocation counters unchanged. Authorization and safe DTO filtering hold.
|
||||
3. Unknown/skipped/planned configuration is explicit; existing atomic route,
|
||||
retry, deferred-move, and best-effort provider semantics remain intact.
|
||||
|
||||
## Verification
|
||||
|
||||
Run from repository root. Add named test files before running these commands;
|
||||
use TDD to demonstrate the missing preview behavior first.
|
||||
|
||||
```bash
|
||||
(cd apps/backend && go test ./internal/orchestrator ./internal/task/handlers ./internal/task/service ./internal/workflow/...)
|
||||
(cd apps/backend && go test -race ./internal/orchestrator ./internal/task/handlers -run 'Preview|WorkflowStepSession|WorkflowSessionConfig|WorkflowSessionTarget|SameProfile')
|
||||
python3 scripts/list-docs.py validate
|
||||
python3 scripts/lint-spec-files.py --all
|
||||
git diff --check
|
||||
```
|
||||
|
||||
## Files likely touched
|
||||
|
||||
- `apps/backend/internal/orchestrator/workflow_move_preview.go`,
|
||||
`workflow_move_preview_settings.go`, and `_test.go` (new).
|
||||
- `apps/backend/internal/orchestrator/event_handlers_workflow.go`.
|
||||
- `apps/backend/internal/orchestrator/workflow_session_target.go`.
|
||||
- `apps/backend/internal/orchestrator/workflow_session_config.go`.
|
||||
- `apps/backend/internal/task/handlers/workflow_move_preview_http.go` and `_test.go` (new).
|
||||
- `apps/backend/internal/task/handlers/task_handlers.go`, `task_http_handlers.go`.
|
||||
- `apps/backend/internal/task/dto/` and existing backendapp dependency wiring.
|
||||
|
||||
## Dependencies
|
||||
|
||||
None. Read both paired specifications and current lifecycle/conditional-settings
|
||||
contracts. Existing same-profile policy and session-target tests are exemplars.
|
||||
|
||||
## Risks
|
||||
|
||||
A helper named resolve can mutate state. Review every reachable call; extract
|
||||
pure inputs/outputs and keep warning publication in execution only.
|
||||
|
||||
## Parallelism
|
||||
|
||||
`sequential`
|
||||
|
||||
## Inputs
|
||||
|
||||
[Design](../../specs/tasks/system-design/workflow-move-preview.md), especially
|
||||
Resolution, API, and Freshness and failures. [Plan test matrix](plan.md#tests).
|
||||
|
||||
## Results
|
||||
|
||||
Implemented the read-only workflow move decision layer and the authorized
|
||||
`POST /api/v1/tasks/:id/move-preview` endpoint. Recipient selection shares the
|
||||
pure reusable-session selector with execution, preserves explicit targets and
|
||||
terminal-session exclusion, projects runtime configuration and conditional
|
||||
rules without writes, and reports unknown or deferred outcomes explicitly.
|
||||
|
||||
Verification passed:
|
||||
|
||||
- `cd apps/backend && go test ./internal/orchestrator ./internal/task/handlers ./internal/task/service ./internal/workflow/...`
|
||||
- `cd apps/backend && go test -race ./internal/orchestrator ./internal/task/handlers -run 'Preview|WorkflowStepSession|WorkflowSessionConfig|WorkflowSessionTarget|SameProfile'`
|
||||
- `python3 scripts/list-docs.py validate`
|
||||
- `python3 scripts/lint-spec-files.py --all`
|
||||
- `git diff --check`
|
||||
|
||||
## Review remediation results
|
||||
|
||||
The preview now shares `workflowmove.ShouldAutoStartAgent` with the actual
|
||||
no-session launch handler. A destination without `auto_start_agent`, or a
|
||||
`skip_step_prompt` move without instructions, returns `no_session` with no
|
||||
recipient. A permitted sessionless launch still resolves the task-level agent
|
||||
profile when the destination has no step profile. Provider option labels are
|
||||
bounded display labels, while Kandev-owned setting fields keep stable keys for
|
||||
localization. The endpoint authorizes the task before repository access, keeps
|
||||
current-session routing when only the task profile fallback exists, predicts
|
||||
profile switches from an existing source session, and projects applicable
|
||||
configure-session rules for a fresh launch. Busy reusable targets report
|
||||
deferred dispatch, while fresh context and passthrough mode changes report
|
||||
skipped applicability.
|
||||
|
||||
Regression coverage compares both idle launch gates with the actual move path,
|
||||
checks task-profile fallback for an allowed launch, and verifies the setting
|
||||
label DTO shape, task authorization ordering, typed configuration notices, and
|
||||
busy-target dispatch.
|
||||
|
||||
Remediation verification passed on 2026-09-15:
|
||||
|
||||
- `cd apps/backend && go test ./internal/workflow/move ./internal/orchestrator`
|
||||
- `cd apps/backend && make lint`
|
||||
|
||||
Final post-remediation verification also passed for the targeted backend race
|
||||
suite and the managed backend build:
|
||||
|
||||
- `cd apps/backend && go test -race ./internal/orchestrator ./internal/task/handlers -run 'Preview|WorkflowStepSession|WorkflowSessionConfig|WorkflowSessionTarget|SameProfile'`
|
||||
- `cd apps/backend && go test -race ./internal/orchestrator -count=1`
|
||||
- `cd apps/backend && go test ./internal/orchestrator -run '^TestCompletedTaskFollowUpAdmissionIsConversationalOnly$' -count=100 -failfast`
|
||||
- `cd apps/backend && make build`
|
||||
@@ -0,0 +1,194 @@
|
||||
---
|
||||
id: "02-compact-preview"
|
||||
title: "Compact preview and move verification"
|
||||
status: completed
|
||||
wave: 2
|
||||
depends_on:
|
||||
- "01-move-decision-api"
|
||||
plan: "plan.md"
|
||||
requirements:
|
||||
- REQ-TASKS-WORKFLOW-MOVE-PREVIEW-001
|
||||
- REQ-TASKS-WORKFLOW-MOVE-PREVIEW-002
|
||||
acceptance_criteria:
|
||||
- AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.1
|
||||
- AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.2
|
||||
- AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.3
|
||||
- AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.4
|
||||
- AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.5
|
||||
- AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.6
|
||||
- AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.7
|
||||
- AC-TASKS-WORKFLOW-MOVE-PREVIEW-002.1
|
||||
- AC-TASKS-WORKFLOW-MOVE-PREVIEW-002.2
|
||||
- AC-TASKS-WORKFLOW-MOVE-PREVIEW-002.3
|
||||
- AC-TASKS-WORKFLOW-MOVE-PREVIEW-002.4
|
||||
system_design:
|
||||
- ../../specs/tasks/system-design/workflow-move-preview.md
|
||||
---
|
||||
|
||||
# Task 02: Compact preview and move verification
|
||||
|
||||
## Summary
|
||||
|
||||
Render the shared prediction in the step hover and mobile drawer. Verify the
|
||||
visible prediction against actual moves using isolated backend fixtures.
|
||||
|
||||
## In scope
|
||||
|
||||
Domain client/hook, scoped invalidation, late-response guards, two-line renderer,
|
||||
inline details, same draft for preview/move, all locales, focused component and
|
||||
browser coverage, and public workflow guidance.
|
||||
|
||||
## Out of scope
|
||||
|
||||
Workflow editing, new routing rules, board drag/bulk-move previews, mandatory
|
||||
confirmation, or direct provider probing.
|
||||
|
||||
## Acceptance
|
||||
|
||||
1. UI-01 and UI-03 remain compact, keyboard accessible, localized, and accurate
|
||||
through overrides, model changes, option changes, unknowns, and transport races.
|
||||
2. UI-02 exposes equivalent predictions and inline details with 44px touch actions,
|
||||
one scroll owner, focus return, and viewport containment.
|
||||
3. Browser tests verify preview versus actual recipient/model, including new and
|
||||
reused sessions. Documentation explains predictions and execution-time checks.
|
||||
|
||||
## ASCII UI preview
|
||||
|
||||
UI-01 desktop and UI-02 phone excerpts; see [full previews](plan.md#ascii-ui-preview)
|
||||
for UI-03 loading/error, all variants, structural notes, and criterion mappings.
|
||||
|
||||
```text
|
||||
Desktop Phone drawer
|
||||
+---------------------------+ +------------------------------+
|
||||
| Move here | | Move to x |
|
||||
| Options | |------------------------------|
|
||||
| [step capabilities] | | Implement |
|
||||
|---------------------------| | [Options] [Move here] |
|
||||
| Reuse current session | |------------------------------|
|
||||
| Astra -> Luna +1 (i) | | Reuse current session |
|
||||
+---------------------------+ | Astra -> Luna +1 (i) |
|
||||
+------------------------------+
|
||||
```
|
||||
|
||||
The approved footer also appears below the Move action in the next-step
|
||||
options popover and drawer above chat. It uses that action's destination and draft.
|
||||
|
||||
Collapsed summaries stay two centered lines. Details expand inline; phone rows share
|
||||
one internal scroll region. The +1 denotes a non-model setting change here.
|
||||
AC-TASKS-WORKFLOW-MOVE-PREVIEW-002.1 through .4 apply.
|
||||
|
||||
## Verification
|
||||
|
||||
Commands run from repository root. Bootstrap this worktree before the first
|
||||
pnpm check. Managed E2E commands build fresh artifacts and run sequentially.
|
||||
The new test files below are implementation outputs, not existing tests.
|
||||
|
||||
```bash
|
||||
(cd apps && pnpm install --frozen-lockfile)
|
||||
(cd apps/web && pnpm test hooks/domains/kanban/use-workflow-move-preview.test.ts components/task/workflow-move-preview.test.tsx components/task/workflow-stepper.test.tsx)
|
||||
(cd apps/web && pnpm run typecheck && pnpm run lint && pnpm run i18n:check && pnpm run i18n:ratchet)
|
||||
(cd apps/web && pnpm e2e:run tests/workflow/workflow-move-preview.spec.ts tests/workflow/workflow-session-targeting.spec.ts tests/workflow/workflow-step-move-overrides.spec.ts -- --project=chromium)
|
||||
(cd apps/web && pnpm e2e:run tests/workflow/mobile-workflow-move-preview.spec.ts tests/workflow/mobile-workflow-session-targeting.spec.ts tests/workflow/mobile-workflow-step-move-overrides.spec.ts -- --project=mobile-chrome)
|
||||
python3 scripts/list-docs.py validate
|
||||
python3 scripts/lint-spec-files.test.py
|
||||
python3 scripts/lint-spec-files.py --all
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Inspect rendered desktop and phone screenshots from these tests against UI-01
|
||||
through UI-03. Record actual commands/results and any deviation. Add any other
|
||||
changed unit suite to the targeted command before completion.
|
||||
|
||||
## Files likely touched
|
||||
|
||||
- `apps/web/lib/api/domains/kanban-api.ts`.
|
||||
- `apps/web/hooks/domains/kanban/use-workflow-move-preview.ts`, its tests, and
|
||||
`use-workflow-move-preview-revision.ts` (new).
|
||||
- `apps/web/components/task/workflow-move-preview.tsx` and `.test.tsx` (new).
|
||||
- `apps/web/components/task/workflow-stepper.tsx` and `.test.tsx`.
|
||||
- `apps/web/components/task/workflow-step-disclosure.tsx` and disclosure actions.
|
||||
- `apps/web/src/locales/` for en, pt-pt, zh-cn, zh-hk, zh-tw; generate Traditional Chinese with i18n:zh-hant.
|
||||
- `apps/web/e2e/tests/workflow/workflow-move-preview.spec.ts` and `mobile-workflow-move-preview.spec.ts` (new).
|
||||
- `docs/public/tasks-and-workflows.md` and paired feature documents/work-order results.
|
||||
|
||||
## Dependencies
|
||||
|
||||
Task 01 and its typed response. Reuse existing stepper, move options, session
|
||||
targeting, and mobile drawer tests; do not simulate all routing in frontend mocks.
|
||||
|
||||
## Risks
|
||||
|
||||
Disclosure remounts, pinned viewed tabs, WS updates, and draft changes can race.
|
||||
Preserve move-pending ownership and never render a response from another scope.
|
||||
|
||||
## Parallelism
|
||||
|
||||
`sequential`
|
||||
|
||||
## Inputs
|
||||
|
||||
[Design](../../specs/tasks/system-design/workflow-move-preview.md): Presentation,
|
||||
Mobile, Freshness and failures. Use mobile-parity, TDD, E2E, and docs-maintainer
|
||||
skills during implementation. No implementation delegation is authorized.
|
||||
|
||||
## Results
|
||||
|
||||
Implemented the shared preview client, debounced request hook, compact renderer,
|
||||
desktop disclosure integration, and coarse-pointer drawer integration. The same
|
||||
normalized options draft feeds the preview and the eventual move. All five web
|
||||
locales include the new copy, and public workflow guidance describes the
|
||||
advisory prediction and execution-time recheck.
|
||||
|
||||
Verification passed:
|
||||
|
||||
- `(cd apps && pnpm install --frozen-lockfile)`
|
||||
- Focused Vitest: 5 files, 44 tests passed.
|
||||
- `pnpm run typecheck`, `pnpm run lint`, `pnpm run i18n:check`, and `pnpm run i18n:ratchet`.
|
||||
- `make -C apps/backend build` and `pnpm run build:e2e`.
|
||||
- Desktop workflow E2E: 12 tests passed, including recipient reuse, fresh
|
||||
sessions, retained model overrides, targeting, and move options.
|
||||
- Mobile workflow E2E: 5 tests passed, including the preview drawer, session
|
||||
targeting, and move-option regressions. The preview scenario uses the
|
||||
repository's coarse-pointer tablet context because the Pixel 5 full-page task
|
||||
route intentionally uses `SessionMobileLayout`, which has no desktop task
|
||||
stepper. The exercised `CompactWorkflowStepDisclosure` branch is the shared
|
||||
touch drawer used by the task preview and tablet task surfaces.
|
||||
- `python3 scripts/list-docs.py validate`
|
||||
- `python3 scripts/lint-spec-files.test.py`
|
||||
- `python3 scripts/lint-spec-files.py --all`
|
||||
- `node --test scripts/validate-public-docs.test.mjs`
|
||||
- `node scripts/validate-public-docs.mjs`
|
||||
- `git diff --check`
|
||||
|
||||
The managed build reports existing Darwin signing, deprecated Vite chunk
|
||||
configuration, and large-chunk warnings; all build and browser commands exit
|
||||
successfully.
|
||||
|
||||
## Review remediation results
|
||||
|
||||
The request hook now receives a store-derived revision containing relevant task,
|
||||
source and destination step, session, workflow, profile, workspace, and
|
||||
connection state, including per-session model and fallback data. It clears a
|
||||
successful result before refetching on live updates and retains cancellation
|
||||
and generation guards. Drawer rows all enqueue their previews; the shared queue
|
||||
limits active requests to two and allows later rows to resolve after earlier
|
||||
requests finish.
|
||||
|
||||
The renderer maps known notice, field, and built-in value codes to localized
|
||||
copy, including a dedicated no-session dispatch state, while retaining a
|
||||
generic fallback for unknown diagnostics and safe data labels for provider
|
||||
options. A non-English DTO-shape test covers missing snapshot, ambiguous rule,
|
||||
and inapplicable-session notices.
|
||||
|
||||
Remediation verification passed on 2026-09-15:
|
||||
|
||||
- Focused Vitest: 3 files, 13 tests passed.
|
||||
- `cd apps/web && pnpm run typecheck && pnpm run lint && pnpm run i18n:check && pnpm run i18n:ratchet`
|
||||
|
||||
Final post-remediation verification passed on 2026-09-15:
|
||||
|
||||
- Focused Vitest: 6 files, 50 tests passed.
|
||||
- `pnpm run build:e2e`, `pnpm run typecheck`, `pnpm run lint`,
|
||||
`pnpm run i18n:check`, and `pnpm run i18n:ratchet`.
|
||||
- Desktop workflow move-preview E2E: 2 tests passed.
|
||||
- Mobile workflow move-preview E2E: 1 test passed.
|
||||
@@ -48,6 +48,20 @@ Workflow position and runtime state are different. Moving a card changes its wor
|
||||
|
||||
During a move and while the destination agent is preparing or starting, the destination marker shows a spinner in the existing marker space. Open the existing step disclosure to see the lifecycle status and agent profile. On touch devices, these details appear in the existing **Move to** Drawer. A destination without auto-start settles after the move and remains available for a later agent start.
|
||||
|
||||
Before an allowed move, the step disclosure can show a compact preview of the
|
||||
recipient and effective model. It identifies whether the move reuses the
|
||||
current session, reuses another named session, creates a new session, or leaves
|
||||
the task idle without a recipient when the destination has no launch turn. The
|
||||
second line shows the current model or an expected model change and counts
|
||||
additional settings changes. Use the info button for the session, profile, model,
|
||||
context reset, source-session disposition, and prompt dispatch information.
|
||||
The preview sits in a centered footer below the move controls. The next-step
|
||||
button above chat shows the same footer in its options popover or touch drawer.
|
||||
Changing the options refreshes that preview.
|
||||
The preview is advisory. **Move here** checks routing, permissions, WIP, and
|
||||
current session state again when the move runs. A preview can therefore change
|
||||
while a turn is running or while another session becomes available.
|
||||
|
||||
## Move a task with one-time entry options
|
||||
|
||||
The normal **Move here** and next-step actions use the destination step's saved workflow defaults. When one transition needs an exception, open **Move with options** from the workflow stepper, Chat status bar, or passthrough toolbar. The options apply only to that entry and never rewrite the workflow step.
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
---
|
||||
status: draft
|
||||
system: tasks
|
||||
created: 2026-09-14
|
||||
owners:
|
||||
- kandev
|
||||
---
|
||||
|
||||
# Workflow Move Preview Requirements
|
||||
|
||||
## Overview
|
||||
|
||||
Before moving a task, users can see which conversation will receive the step
|
||||
and which model and settings it is expected to use. The tasks system owns this
|
||||
capability because it owns workflow recipient selection and step entry behavior.
|
||||
|
||||
A profile identity and a running model are different facts. A session launched
|
||||
with a Luna profile can retain a later Astra model selection when reused.
|
||||
|
||||
## Terminology
|
||||
|
||||
- **Current session:** The conversation selected by the move's routing context,
|
||||
not necessarily a separately viewed or pinned chat tab.
|
||||
- **Expected configuration:** The selected session's effective settings after
|
||||
applicable entry rules, subject to provider acceptance and execution-time state.
|
||||
- **Preview:** A read-only prediction; it does not reserve a session or execute a move.
|
||||
|
||||
## Requirements
|
||||
|
||||
### REQ-TASKS-WORKFLOW-MOVE-PREVIEW-001: Session and settings prediction
|
||||
|
||||
**Intent:** Expose conversation continuity and model changes before a move.
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- **AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.1:** Opening a movable step disclosure
|
||||
shall show current-session reuse, other-session reuse with its name, new
|
||||
session creation, or an idle task with no recipient according to task-specific
|
||||
routing. Explicit initial and earlier-step targets, same-profile policies,
|
||||
terminal candidates, and the destination's no-session launch gates shall
|
||||
follow the existing routing contract.
|
||||
- **AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.2:** An unchanged session shall show its
|
||||
effective model. Reuse of a Luna-profile session running Astra shall show
|
||||
Astra and disclose the retained override. A new session shall show its
|
||||
expected launch model without copying the source session's overrides.
|
||||
- **AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.3:** Applicable conditional settings shall
|
||||
produce a before/after model summary without implying a new conversation.
|
||||
Set shall retain unnamed fields; keep and no-match shall retain current
|
||||
values; restore-original shall use the original effective snapshot. Rules
|
||||
inapplicable to a different session or passthrough shall not predict application.
|
||||
- **AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.4:** Additional effective setting changes
|
||||
shall appear as a count with accessible details showing field names and
|
||||
before/after values. Context reset and source-session retirement shall be
|
||||
disclosed. Identical values shall not count as changes. Model changes shall
|
||||
not be counted again among additional changes.
|
||||
- **AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.5:** Missing original snapshots, ambiguous
|
||||
rules, unavailable capability data, and provider-dependent outcomes shall
|
||||
be identified with distinct reason states such as unavailable or skipped,
|
||||
rather than one generic message. Unknown values shall not be presented as
|
||||
confirmed models. Best-effort application remains best-effort.
|
||||
- **AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.6:** Opening or refreshing the preview
|
||||
shall not create sessions, start agents, change settings, write conversation
|
||||
warnings, or trigger transitions. Existing authorization shall prevent
|
||||
disclosure of another workspace's sessions or sensitive configuration.
|
||||
- **AC-TASKS-WORKFLOW-MOVE-PREVIEW-001.7:** Changing the task, destination, move
|
||||
options, known routing/configuration state, or the connection state shall
|
||||
invalidate the preview. Late responses shall not overwrite a newer selection.
|
||||
Actual moves shall retain execution-time validation, including deferred moves.
|
||||
|
||||
### REQ-TASKS-WORKFLOW-MOVE-PREVIEW-002: Compact accessible disclosure
|
||||
|
||||
**Intent:** Provide useful feedback within the existing step move surface.
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- **AC-TASKS-WORKFLOW-MOVE-PREVIEW-002.1:** The collapsed desktop preview shall
|
||||
use two centered summary lines below actions and capabilities: session outcome,
|
||||
then model/settings with an icon-only details button.
|
||||
Details shall remain opt-in. Long labels shall truncate with full accessible
|
||||
text. Existing Options and capability/progress content shall remain usable.
|
||||
The next-step options popover and touch drawer shall show the same footer
|
||||
below their Move action, using the destination and draft of that action.
|
||||
- **AC-TASKS-WORKFLOW-MOVE-PREVIEW-002.2:** Hover, keyboard focus, and activation
|
||||
shall expose desktop feedback. Phones and coarse pointers shall expose the
|
||||
same information and details in the step drawer, without requiring hover.
|
||||
Touch actions shall measure at least 44 CSS pixels; content shall remain
|
||||
within the viewport with one internal vertical scroll owner and focus return.
|
||||
- **AC-TASKS-WORKFLOW-MOVE-PREVIEW-002.3:** Loading shall show Checking session.
|
||||
Failure shall show Preview unavailable with Retry. Preview loading or failure
|
||||
alone shall not disable an otherwise allowed move. Known move restrictions
|
||||
shall continue to use the existing move gates. No stale prediction shall look current.
|
||||
- **AC-TASKS-WORKFLOW-MOVE-PREVIEW-002.4:** All labels, details, statuses, and
|
||||
accessible names shall support the five shipped locales, including field,
|
||||
value, and diagnostic reason codes returned by the preview API. Model and
|
||||
session names remain product data. The interface shall distinguish planned
|
||||
settings from completed changes without adding a confirmation dialog.
|
||||
|
||||
## Existing contracts
|
||||
|
||||
- [Session lifecycle](workflow-profile-session-lifecycle.md)
|
||||
- [Conditional settings](workflow-session-settings.md)
|
||||
- [Design](../system-design/workflow-move-preview.md)
|
||||
- [Implementation plan](../../../plans/workflow-move-preview/plan.md)
|
||||
|
||||
## Out of scope
|
||||
|
||||
Changing workflow defaults, editing profiles from the preview, automatically
|
||||
repairing model overrides, routing native subagents, and adding mandatory
|
||||
confirmation. This package targets the task stepper and its compact disclosure,
|
||||
and the next-step control above chat, not every board drag, bulk move, or move menu.
|
||||
@@ -0,0 +1,213 @@
|
||||
---
|
||||
status: draft
|
||||
system: tasks
|
||||
requirements:
|
||||
- REQ-TASKS-WORKFLOW-MOVE-PREVIEW-001
|
||||
- REQ-TASKS-WORKFLOW-MOVE-PREVIEW-002
|
||||
---
|
||||
|
||||
# Workflow Move Preview System Design
|
||||
|
||||
## Purpose and boundaries
|
||||
|
||||
Add an advisory projection of the existing move decision. Preserve the routing
|
||||
and best-effort conditional-setting contracts. The tasks system owns the
|
||||
projection; the agent runtime owns actual provider acceptance.
|
||||
|
||||
[Requirements](../requirements/workflow-move-preview.md) define the outcome.
|
||||
[Lifecycle design](workflow-profile-session-lifecycle.md) defines recipients.
|
||||
[Conditional settings](../requirements/workflow-session-settings.md) defines
|
||||
set, keep, restore-original, original-session eligibility, and partial failure.
|
||||
|
||||
## Requirement mapping
|
||||
|
||||
| Requirement | Sections |
|
||||
| --- | --- |
|
||||
| REQ-TASKS-WORKFLOW-MOVE-PREVIEW-001 | Resolution, API, Freshness and failures |
|
||||
| REQ-TASKS-WORKFLOW-MOVE-PREVIEW-002 | Presentation, Mobile, Verification |
|
||||
|
||||
## Resolution
|
||||
|
||||
Introduce a read-only decision layer in `internal/orchestrator/workflow_move_preview.go`.
|
||||
Extract shared selection decisions from `prepareWorkflowStepSession`,
|
||||
`shouldKeepCurrentWorkflowStepSession`, and `workflow_session_target.go`.
|
||||
The existing execution paths consume those decisions but retain their atomic
|
||||
selection, route-ledger, retry, credential, and terminal-session checks.
|
||||
Do not call mutating prepare/ensure helpers to implement preview.
|
||||
|
||||
Resolve the same authoritative move source as `httpMoveTask`; do not use the
|
||||
browser's viewed session as routing authority. Read the destination, source,
|
||||
sessions, explicit target bindings, profile configuration, and available runtime
|
||||
configuration. Apply destination start policy and source end policy. No profile
|
||||
override still follows existing workflow-default resolution. Reuse may select
|
||||
a matching other session or create one if no eligible candidate exists and the
|
||||
destination can actually launch a session for this move. When the destination
|
||||
has no auto-start action, or when `skip_step_prompt` removes the only launch
|
||||
turn because it has no instructions, report an idle `no_session` outcome
|
||||
instead of claiming that a session will be created. The shared
|
||||
`workflowmove.ShouldAutoStartAgent` predicate keeps this projection aligned
|
||||
with the no-session execution path.
|
||||
|
||||
Preserve terminal-session exclusion, explicit target identity, deterministic
|
||||
candidate ordering, and same-profile/new behavior. A zero-session task is
|
||||
reported through the existing launch decision; if that decision cannot be
|
||||
resolved without provisioning, return unknown rather than ensuring a session.
|
||||
Dynamic profile selection without a concrete recipient reports its profile and
|
||||
an unknown model; preview never probes or launches a provider to choose one.
|
||||
|
||||
For an existing recipient, use the runtime's effective configuration projection
|
||||
and durable overrides with their existing precedence. Profile defaults alone
|
||||
cannot describe a reused conversation. For new recipients, resolve launch
|
||||
configuration without carrying overrides from the outgoing session.
|
||||
|
||||
Factor pure rule selection and configuration projection out of
|
||||
`workflow_session_config.go`. Reuse `selectConfigureSessionRule`,
|
||||
`sessionConfigurationTargetForRule`, and existing option normalization.
|
||||
`resolveWorkflowSessionConfigTarget` currently emits conversation warnings;
|
||||
preview must instead collect structured diagnostic codes without calling that
|
||||
side-effecting path. Share decisions, not warning publication.
|
||||
|
||||
Evaluate original-session eligibility, canonical family matching and ambiguity,
|
||||
keep/no-match, set's named fields, and restore's immutable original snapshot.
|
||||
Report skipped rules accurately. Preserve restrictions on model/mode options.
|
||||
Use available model-aware capability snapshots only. Provider acceptance remains
|
||||
uncertain until application; do not synthesize capabilities or restore defaults.
|
||||
|
||||
Project applicable context-reset entry actions and the normalized one-shot reset
|
||||
option using execution order. Include whether the configured prompt will run,
|
||||
is suppressed, or waits for turn end/queue admission in expanded details.
|
||||
Do not duplicate reset effects or treat instruction text as a configuration change.
|
||||
|
||||
## API
|
||||
|
||||
Proposed read-only POST `/api/v1/tasks/:id/move-preview` accepts the destination
|
||||
`workflow_id`, `workflow_step_id`, and the existing `entry_options` shape.
|
||||
It shares request validation and task/workspace authorization with the move
|
||||
handler. It accepts no client-selected source session. POST carries the draft
|
||||
without putting instructions in a URL. Neither instructions nor raw request
|
||||
bodies are logged or echoed. Return `Cache-Control: no-store`.
|
||||
|
||||
Wire the handler through `task_handlers.go`, a narrow orchestrator preview
|
||||
interface, and existing dependency construction. New DTO fields:
|
||||
|
||||
- `task_id`, `workflow_step_id`, `source_session_id`, `evaluated_at`.
|
||||
- `outcome`: `reuse_current`, `reuse_other`, `create_new`, `no_session`, or
|
||||
`unknown`.
|
||||
- `recipient`: nullable session ID/name, profile ID/name, agent family.
|
||||
- `model`: before/after IDs and labels, known/unknown flags, and source
|
||||
(`runtime`, `override`, `profile`, `step_rule`, `original`).
|
||||
- `changes`: normalized field key, safe label, before/after value, and
|
||||
`planned`/`unchanged`/`skipped`/`unknown` applicability.
|
||||
- `context_reset`, `source_disposition`: keep/park/complete/unknown,
|
||||
`dispatch`: prompt/no_prompt/deferred/unknown.
|
||||
- `notices`: closed reason codes with safe parameters, including retained
|
||||
model override, missing snapshot, unsupported option, and stale capability.
|
||||
|
||||
Only selectable, non-sensitive model configuration enters this DTO. Never expose
|
||||
credentials, environment, raw session metadata, prompts, or provider errors.
|
||||
Unauthorized and missing tasks use existing API errors. Uncertain routing uses
|
||||
an unknown projection; a `no_session` projection has no recipient, and no
|
||||
fabricated session ID is returned for a new session.
|
||||
This response is additive; no migration or durable preview ledger is needed.
|
||||
|
||||
## Freshness and failures
|
||||
|
||||
`use-workflow-move-preview.ts` under `hooks/domains/kanban/` owns requests through
|
||||
`lib/api/domains/kanban-api.ts`. Fetch only while an applicable disclosure is open.
|
||||
Use the existing hover delay. Every disclosed movable drawer row may enqueue a
|
||||
request, while a shared queue keeps at most two requests in flight and cancels
|
||||
rows that close or unmount. Do not request previews for every step across every
|
||||
mounted task.
|
||||
Deduplicate pending requests by task, destination, normalized options, and a local
|
||||
invalidation generation. Abort on close/context change and reject late generations.
|
||||
|
||||
Invalidate on task placement/primary-session changes, relevant session runtime
|
||||
updates, profile updates, workflow-step updates, reconnect, and draft changes.
|
||||
Clear on close and fetch fresh on reopen. Debounce draft edits; typing instruction
|
||||
text need not refresh unless its presence changes prompt dispatch semantics.
|
||||
|
||||
Keep two-line loading/error states compact. Retry is explicit and does not move
|
||||
the task. Preview failure does not introduce a new move barrier. Show predictions
|
||||
as planned, not guaranteed; details explain that execution rechecks current state.
|
||||
Deferred moves show that settings are checked again at turn end. The actual move
|
||||
continues through existing execution paths and handles provider partial failures.
|
||||
No preview token is required to move and no confirmation flow is added.
|
||||
|
||||
## Presentation
|
||||
|
||||
Add `workflow-move-preview.tsx` as a shared projection renderer with no fetches.
|
||||
`StepMoveControls` in `workflow-stepper.tsx` owns the draft and passes the same
|
||||
normalized entry options to preview and move. Thread task/workflow identity down
|
||||
from the stepper. Integrate the renderer in `workflow-step-disclosure.tsx` rows.
|
||||
|
||||
Collapsed layout is two centered lines below actions and capabilities. Line one distinguishes current,
|
||||
other named, new conversations, and an idle task with no recipient. Line two shows an unchanged effective model
|
||||
or a before/after arrow, followed by an optional additional-change count.
|
||||
A retained model/profile mismatch uses the compact override label from UI-01.
|
||||
|
||||
Count actual non-model field changes plus one context-reset effect. Do not count
|
||||
source retirement as a setting change. Deduplicate model and config-option model
|
||||
representations. If only reasoning changes, show the unchanged model with +1.
|
||||
Use the generic New session label for a permitted fresh launch. Use a separate
|
||||
localized no-session label when the move leaves the task idle. Show the model on
|
||||
line two for a fresh launch when known; profile name belongs in details when it
|
||||
differs from the model label.
|
||||
|
||||
The API returns stable field, value, and diagnostic reason codes for Kandev-owned
|
||||
settings. The renderer localizes those codes in the active locale and displays
|
||||
provider-defined labels only when they are safe display data. Model and session
|
||||
names remain data.
|
||||
|
||||
Center both footer lines and use an icon-only info button with a localized
|
||||
accessible name. A separator divides actions from the muted footer.
|
||||
|
||||
The chat and passthrough next-step controls pass the destination directly from
|
||||
`usePlanActions` through `WorkflowMoveProceedButton` to the options form. The
|
||||
form previews its current draft below the Move action, on desktop and touch.
|
||||
Mount the preview only while the options surface is open. Use the existing
|
||||
revision, debounce, cancellation, and concurrency logic.
|
||||
|
||||
Use a keyboard/touch-operable details toggle with `aria-expanded`, not a nested
|
||||
hover-only tooltip. Details list full session/profile identity, planned changes,
|
||||
source retirement, dispatch, and applicable notices. Arrow summaries mean planned
|
||||
changes; accessible text and expanded details explain this. Keep Options, existing
|
||||
capability icons, progress, move errors, and move pending ownership intact.
|
||||
Unknowns take priority over misleading before/after arrows. Status changes use
|
||||
one localized status region without repeatedly announcing unchanged predictions.
|
||||
|
||||
## Mobile
|
||||
|
||||
Reuse `CompactWorkflowStepDisclosure` and its `useTouchDrawer` branch, including
|
||||
its `max-h-[80dvh]` surface and fixed header. The curated MobilePickerSheet pattern
|
||||
supplies a discoverable header entry, inset drawer, focus return, and safe areas.
|
||||
This is a short temporary step choice, so it belongs in the existing drawer.
|
||||
|
||||
Each visible step row gains the same two-line summary. Details expand inline
|
||||
inside the drawer's single scroll body; avoid nested popovers or drawers.
|
||||
Move here, Options, Retry, and details have at least 44px touch hit areas.
|
||||
Desktop keeps compact 24px action density. Long names truncate in the summary
|
||||
and wrap in details. Verify 320px, the default mobile viewport, and breakpoint
|
||||
neighbors 767/768px with the applicable pointer mode. No document horizontal
|
||||
scroll or separate persisted mobile selection is introduced.
|
||||
|
||||
## Verification
|
||||
|
||||
Backend fixtures compare preview selection/configuration with actual move
|
||||
outcomes on isolated tasks. Assert preview does not change rows, metadata,
|
||||
route bindings, messages, or runtime call counters. Cover the historical
|
||||
Luna-profile/Astra override scenario plus conditional settings, the two
|
||||
no-session launch gates, task-profile fallback, and deferred moves. Frontend
|
||||
tests cover live store/reconnect invalidation, queued rows beyond the first two,
|
||||
and localized field/value/diagnostic rendering.
|
||||
Browser tests inspect the preview, perform the move, then verify recipient and
|
||||
model through fixture API state. See the [plan](../../../plans/workflow-move-preview/plan.md).
|
||||
|
||||
## Related decisions
|
||||
|
||||
- [Profile session lifecycle](../../../decisions/2026-08-31-workflow-profile-session-switch-policy.md)
|
||||
- [Original configuration](../../../decisions/2026-08-01-workflow-session-original-configuration.md)
|
||||
|
||||
This projection preserves those decisions. Shared read-only resolution avoids
|
||||
frontend routing duplication; an independent frontend approximation would drift
|
||||
on explicit bindings and runtime overrides. A new ADR is unnecessary for this
|
||||
additive feature because these boundaries and rationale fit the paired design.
|
||||
Reference in New Issue
Block a user