Repository navigation
feat(autopilot): the ticket flow is a graph in the Workflow app that Autopilot runs - #285
Merged
Merged
Conversation
…tenant storage TicketFlowDefinition (ordered step nodes + pass/fail edges) with the safety invariants, workspaces.ticket_flows (append-only versions, RLS) and the ticket flow snapshot on sessions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018WAdQ7Rm24xss5QDSvXtJB
…flow Both engines follow the flow a ticket started with; the planner skips steps the flow leaves out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018WAdQ7Rm24xss5QDSvXtJB
Graph + table of the ticket flow with inline validation, save, revert and the live step; members read-only. Board › Autopilot summarises the flow and links to it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018WAdQ7Rm24xss5QDSvXtJB
… versioning, tenants, planner Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018WAdQ7Rm24xss5QDSvXtJB
…low and reverts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018WAdQ7Rm24xss5QDSvXtJB
…ed as true/false Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018WAdQ7Rm24xss5QDSvXtJB
…onomy levels Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018WAdQ7Rm24xss5QDSvXtJB
Comment on lines
+366
to
+372
| foreach (var e in definition.Edges) | ||
| { | ||
| if (!byId.ContainsKey(e.From) || !byId.ContainsKey(e.To)) | ||
| { | ||
| problems.Add(new(null, $"An edge points at a step that doesn't exist ({e.From} → {e.To}).")); | ||
| } | ||
| } |
Comment on lines
+64
to
+71
| foreach (var step in new[] { "review", "test" }) | ||
| { | ||
| if (await Card(win, step).GetAttributeAsync("class") is { } css && css.Contains("run-skipped", StringComparison.Ordinal)) | ||
| { | ||
| await SetRunsAsync(win, step, on: true); | ||
| changed = true; | ||
| } | ||
| } |
Comment on lines
+232
to
+236
| foreach (var kind in System.Enum.GetValues<TicketStepKind>()) | ||
| { | ||
| var info = TicketStepKinds.Of(kind); | ||
| info.Roles.ShouldAllBe(r => AgentRoles.Find(r) != null); | ||
| } |
… says so Review of #285: AppendAsync retries the unique (TenantId, Version) collision three times and then let the DbUpdateException escape into the admin's circuit. The fourth collision now raises TicketFlowSaveConflictException, which TicketFlowService turns into a plain problem: "Someone else saved the ticket flow at the same moment. Reload it and try again." Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018WAdQ7Rm24xss5QDSvXtJB
1 of 2 tasks
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.
Change description
Ticket flow. Autopilot now runs, for every ticket, a graph that the owner sees and edits in the Workflow app. Before this, the flow was hard-coded twice: once in the
TicketWorkflowMAF edges and once in theAutopilotPlannerrules. ADR-0014 records the decision.Model (
Modules.Pipeline/Agents/TicketFlowDefinition.cs):TicketFlowDefinitionholds ordered step nodes (Code,Checks,Review,Test,Merge) and conditional edges (Pass→ next step,Fail→ back to Code).AgentRoleskey:IssueWork,ReviewerorAcceptance.TicketStepKindsis the extension point. A new kind (the Design/screenshot gate is next) is one enum value, one registry entry and one executor.Defaultreproduces today's flow exactly.Safety invariants (
TicketFlowValidator, plain-language reasons): the flow starts at Code and ends at Merge, and Checks always runs before Merge (it can't be turned off or filtered). Every ticket, whatever its labels, passes Review or Test; every combination of the filter labels is checked. The only cycle allowed is a fail edge back to Code. Every step must be reachable, steps stay in their natural order, there is one step per kind, and each step's role must be one that can run it.TicketFlowPlan.SafetyProblemre-checks the per-ticket plan before a MAF graph is built.AutopilotPlanner.WithinCapsstays the outer guard.Storage: a new
workspaces.ticket_flowstable in the Workspaces module, the module that owns board and Autopilot state.ticketflow.changed.Workspaces/AddTicketFlowsandSessions/AddTicketFlowVersion. The in-memory store keeps the standalone Web editable.Engines:
TicketWorkflow.Build(steps, plan, …)builds the MAFWorkflowBuildergraph from the ticket's resolved plan, replacing the hard-coded edges.sessions.TicketFlowVersion. Running tickets keep that version, including the step-by-step path after a restart. New tickets use the current version.AutopilotPlannerreadsPlanTask.Flow: there is no review move when Review is off for the ticket, and no test move when Test is off.FixRoundsagainstAutopilot:MaxFixRounds. There is no second counter.Workflow › Ticket flow is a new tab in the Workflow app. Admins can:
TicketWorkflowRunner.Members see the same view read-only. Everything is keyboard accessible (
role=switch,aria-pressedand named buttons) and uses tokens only. Nothing animates at rest: only the spinner of a running step moves, and it stops underprefers-reduced-motionor when Animations is off.Board › Autopilot summarises each project's flow in one line ("Code → Checks → Review → Test → Merge") and has a Ticket flow button that opens the view on that project.
Docs: README (Autopilot section),
docs/CONFIG.md(new "Workflow › Ticket flow" section),docs/plans/autonomy-levels.md(item 3d), and ADR-0014.Claude Design push is pending: the new Ticket flow screen and its
tf-*styles still need/design-sync(DesignSyncwrite_files). This non-interactive session had no design-system auth.Type of change
Related issues
Follows #270 (one ticket = one MAF workflow), #278 (one agent registry) and #279 (Settings › Autopilot + fix rounds).
Test plan
tests/AgentOs.Tests):TicketFlowDefinitionTests: every invariant, a JSON round trip, label resolution, and the default being today's flow.TicketWorkflowTests: all existing tests stay green. New ones cover a custom flow with Review skipped fortype:chore, a flow with Test off fortype:docs(review send-back still counted), an unsafe plan never being built, and the plan/version snapshot.TicketFlowServiceTests: run on both the in-memory and EF stores. They cover versioning and revert, invalid saves refused with nothing stored, members refused, the board's own flow winning, two tenants isolated, a task keeping its version, and a stored invalid flow being refused at run time.AutopilotPlannerTests: Review skipped → straight to testing; Test skipped → merge after review, with the right reason;WithinCapsstill caps flow moves; labels are resolved per task.TicketFlowStylesheetTests: no idle animation, tokens only, no phantom classes.ASPIRE010from the AppHost's Aspire SDK, which this PR doesn't touch. The fulldotnet test --solution AgentOs.slnx -c Releaserun passed 1756, skipped 80, failed 0.TicketFlowTests,RUN_AGENTOS_E2E): renders the 5 steps and the table, shows that Checks can't be turned off, saves Review off as a new version, refuses Review+Test off with the reason ("Turn on Review or Test…"), discards, then reverts. It leaves zero residue. The whole standalone E2E suite is green (35 passed, 20 gated).postgres:18.3container, Web booted against it):workspaces.ticket_flowshas RLS enabled and forced, with its policy;RowLevelSecurityRealDbTests, now includingticket_flows, is green;agentos_rls, tenanttenant-bsees 0 rows and the owning tenant sees 4.Checklist
dotnet buildpasses locally in Release modedotnet testpasses (with coverage if available)Notes / not done
/design-sync) is pending.🤖 Generated with Claude Code
https://claude.ai/code/session_018WAdQ7Rm24xss5QDSvXtJB