mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
* feat(gateway): claim-scoped context briefing — heavy sections only on context-acquisition verbs
* feat(gateway): cap unbounded LLM-facing payloads — embedded diffs, notification bodies, handoff journal content, north star
* feat(mcp): role-scope the optimal server's tool groups; index management becomes dev/test-only
* feat(mcp): cap per-result content on kb/error/learning search, mentor sources, rag citations
* refactor(gateway): extract heavy-briefing sections + clip helper to keep xenon ranks
* feat(orchestrator): cross-tick cooldown for notification-triggered spawns
* feat(usage,orchestrator): scope spawn-waste to anthropic sessions; cap agent Bash output via settings env
* docs: claim-scoped briefing, payload caps, optimal role-scoping, notification-spawn cooldown
* test(mcp): type the mixed-item cap fixture explicitly
* fix(orchestrator): lazy-init the notification-spawn cooldown store
* fix(lifecycle): admin-override claim reconciliation + PM request_changes verb (S6 postmortem B3+B4)
B3 — admin_set_status now reconciles claim ownership when leaving BLOCKED:
review/queue targets clear claimed_by/claimed_at/active_claimant_id and
consume the pre-block snapshot (a stale escalation claim was stranding the
next claimant: give_me_work handed the task out while note() bounced
not_authorized — the live b8fe0494 wedge). The pending/in_progress restore
path also syncs active_claimant_id, and a REST PATCH unassign releases the
claim with it.
B4 — new PM verb request_changes: awaiting_pm_review -> needs_revision with
concrete issues. The PM previously had no reject at merge review (only
complete/escalate), so an AC/scope violation looped i_am_blocked->escalate
4x live. Full vertical: lifecycle transition + ActionSpec + IntentSpec,
TaskService.request_changes (routes like a QA fail — original dev for a
leaf, revision PM for assembled; issues appended to dev_notes), verb-runner
compose, choreographer verb (spec gate + non-empty issues + soup check +
a2a delivery of the reject reason), HTTP routes on both PM flows, MCP tool,
journal:decision tracing, PM prompts, regenerated lifecycle artifacts.
* fix(panel): stop scorecard fetches for fallback-roster placeholder ids
useAgents() serves the static AGENT_ROSTER (ids "1".."22") while agent
definitions load; the Scorecards tab fetched a member scorecard per row
immediately, firing 22 guaranteed-422 requests per refetch cycle. Through
the browser's per-origin connection limit those queued every metrics-page
query behind them (~10s of skeletons on every tab). Gate the fetch on a
real member id (agent UUID or the "ceo" alias).
* Upgraded uv.lock
* fix(sequencing): declared deps become real edges + full loop-breaker coverage + assembled-branch freshness (S6 postmortem B1/B2/B6 + breaker)
B1a — code delegations REQUIRE a collision surface: new TASK_AT_DELEGATE
completeness spec (conditional FieldRequirement, when=('task_type','code'))
enforced at the gateway delegate gate. A no-surface code sibling is
'parallel to everything' by analyzer design, which is how two devs ran the
CEO's explicitly-ordered work out of order (f3e1afc5: seq#1 started before
seq#0, zero dependency edges). PM prompts updated; REST/manual creation
(TASK_AT_CREATE) unchanged.
B1b — the CEO's declared 'Depends on' lists become real edges: DraftSurface
gains declared_depends_on; SequencingService.analyze unions declared edges
(validated: self/out-of-range rejected) with the derived collision rules,
cycle-checked by the existing toposort. confirm_live_batch/preview_batch
map each draft's depends_on through (string indices coerced); intake tool
doc + prompter role prompt instruct verbatim copying. The live S6 root got
1 of its 3 declared in-batch edges and started alongside still-running R3.
Breaker coverage — the progress-aware respawn circuit breaker
(_pm_respawn_should_gate: strike counting, status-advance reset,
tracing-gap budget, DB durability, one-shot CEO notification) was consulted
by only 3 spawn paths; the doc/QA/dev/PR-review/PR-gate/revision/board
paths spawned unguarded at fixed cadence (the 26-respawn fe-doc loop,
~$7.20). Now consulted at every task-keyed spawn site (14 total).
B2 — assembled-branch freshness: submit_up/submit_root auto-sync the
assembled branch when it has fallen behind its base (children are terminal
at submit time, so the rebase is safe; master is never written). A rebase
conflict is a hard reject naming the files instead of a blind re-review —
kills the needs_revision↔awaiting_pr_review ping-pong of re-submitting a
stale head. Leaf i_am_done already had the behind-base gate; claim-time
fetch-fresh cut already existed.
B6 — documenter revision-pass loop: the awaiting_documentation bail
rejections (i_am_blocked/unclaim) now name the actual exit (i_documented
re-affirm) and the documenter prompt gets an explicit revision-pass rule.
* fix(orchestration): assembly-integrity gate + dispatcher heartbeat (incidents #11, #1)
Assembly integrity — submit_up/submit_root refuse when a completed child's
commits are not patch-present in the assembled branch (git cherry —
rebase-safe; branch pruned after merge or any git error fails open). Live
incident #11: a completed revert subtask's merge was lost from the cell
branch and the review gate re-flagged the exact violation the revert fixed,
spawning another revision cycle.
Dispatcher heartbeat — a dispatcher.alive audit row every 5 minutes from
the dispatch loop. The 2026-07-01 outage was 4h25m of fleet-wide silence
with no way to distinguish 'loop dead' from 'no work'; the loop's stdout
died with the container while audit_log survives. CHANGELOG for tonight's
full sweep included.
* style: ruff format for the orchestration sweep
* refactor(gateway): fold the assembled-submit guards + trim complexity under the xenon gate
_assembled_submit_guards combines the #11 integrity check and B2 freshen for
submit_up/submit_root; lifecycle's invalid-source remediate and git's
per-child cherry probe extracted into helpers. Test harnesses built via
__new__ stub the respawn tracker (the breaker now runs on their paths).
---------
Co-authored-by: Renn F <rennf93@users.noreply.github.com>
775 lines
19 KiB
JSON
775 lines
19 KiB
JSON
{
|
|
"claim_rules": {
|
|
"auditor": [],
|
|
"cell_pm": [
|
|
"needs_revision",
|
|
"pending"
|
|
],
|
|
"ceo": [],
|
|
"developer": [
|
|
"needs_revision",
|
|
"pending"
|
|
],
|
|
"documenter": [
|
|
"awaiting_documentation",
|
|
"pending"
|
|
],
|
|
"head_marketing": [],
|
|
"main_pm": [
|
|
"needs_revision",
|
|
"pending"
|
|
],
|
|
"pr_reviewer": [
|
|
"awaiting_pr_review",
|
|
"pending"
|
|
],
|
|
"product_owner": [],
|
|
"qa": [
|
|
"awaiting_qa"
|
|
]
|
|
},
|
|
"intents": [
|
|
{
|
|
"allowed_roles": [
|
|
"documenter"
|
|
],
|
|
"composes": [],
|
|
"description": "Claim awaiting_documentation. Returns evidence inline.",
|
|
"name": "claim_doc_task",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"pr_reviewer"
|
|
],
|
|
"composes": [],
|
|
"description": "Claim an assembled-PR review task (awaiting_pr_review) WITHOUT transitioning it \u2014 mirrors QA's claim_review. The assembled diff and the parent task's acceptance criteria are returned inline.",
|
|
"name": "claim_gate_review",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"pr_reviewer"
|
|
],
|
|
"composes": [
|
|
"claim",
|
|
"start"
|
|
],
|
|
"description": "Claim an inbound external-PR review task and start work. pending -> claimed -> in_progress.",
|
|
"name": "claim_pr_review",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"qa"
|
|
],
|
|
"composes": [],
|
|
"description": "Claim a task in awaiting_qa for review. Returns evidence inline.",
|
|
"name": "claim_review",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"cell_pm",
|
|
"main_pm"
|
|
],
|
|
"composes": [
|
|
"complete"
|
|
],
|
|
"description": "Cell PM merges the PR (leaf into the cell branch, or the gated cell\u2192root PR into the root branch) + transitions to completed; Main PM escalates the root to the CEO (who merges root\u2192master). The merge runs BEFORE the complete transition: TaskService.complete asserts the PR is already merged, so the choreographer verb body (cell_pm_complete / main_pm_complete) owns the merge-first ordering \u2014 no trailing pr_merge side_effect is declared here.",
|
|
"name": "complete",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"cell_pm",
|
|
"main_pm"
|
|
],
|
|
"composes": [
|
|
"create_subtask"
|
|
],
|
|
"description": "Create a subtask under the current task. Validates the delegation chain (main_pm->cell_pm; cell_pm->its team's devs) and the assignee-vs-task_type rule (Cell PMs get planning-typed tasks; devs get code/research, UX devs also design). documentation is NOT delegatable \u2014 the lifecycle auto-creates the doc phase after the code subtask passes QA.",
|
|
"name": "delegate",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"head_marketing",
|
|
"main_pm",
|
|
"product_owner"
|
|
],
|
|
"composes": [
|
|
"escalate_to_ceo"
|
|
],
|
|
"description": "Escalate to CEO with reason. Transitions to awaiting_ceo_approval.",
|
|
"name": "escalate_to_ceo",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"cell_pm",
|
|
"main_pm"
|
|
],
|
|
"composes": [],
|
|
"description": "Escalate to your role's escalation_target.",
|
|
"name": "escalate_up",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"qa"
|
|
],
|
|
"composes": [
|
|
"qa_fail"
|
|
],
|
|
"description": "Fail QA with concrete issues. Transitions to needs_revision.",
|
|
"name": "fail_review",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"cell_pm",
|
|
"developer",
|
|
"documenter",
|
|
"main_pm",
|
|
"pr_reviewer",
|
|
"qa"
|
|
],
|
|
"composes": [],
|
|
"description": "Return your most-actionable task or signal idle.",
|
|
"name": "give_me_work",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"developer",
|
|
"documenter",
|
|
"qa"
|
|
],
|
|
"composes": [
|
|
"block"
|
|
],
|
|
"description": "Escalate to PM. Logs a struggle journal entry.",
|
|
"name": "i_am_blocked",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"developer"
|
|
],
|
|
"composes": [
|
|
"submit_verification",
|
|
"submit_qa"
|
|
],
|
|
"description": "Submit work for QA. Auto-runs in_progress->verifying then verifying->awaiting_qa. Strict - PR must be open (call open_pr first) and >=1 commit.",
|
|
"name": "i_am_done",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"auditor",
|
|
"cell_pm",
|
|
"developer",
|
|
"documenter",
|
|
"head_marketing",
|
|
"main_pm",
|
|
"pr_reviewer",
|
|
"product_owner",
|
|
"prompter",
|
|
"qa",
|
|
"secretary"
|
|
],
|
|
"composes": [],
|
|
"description": "Signal you have no active work. PMs auto-pause owned in_progress tasks.",
|
|
"name": "i_am_idle",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"documenter"
|
|
],
|
|
"composes": [
|
|
"docs_complete"
|
|
],
|
|
"description": "Signal docs complete. Transitions to awaiting_pm_review.",
|
|
"name": "i_documented",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"cell_pm",
|
|
"main_pm"
|
|
],
|
|
"composes": [
|
|
"claim",
|
|
"set_plan",
|
|
"start"
|
|
],
|
|
"description": "PM mirror of i_will_work_on for parent tasks. Claim, plan, transition to in_progress; from there delegate subtasks.",
|
|
"name": "i_will_plan",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"developer"
|
|
],
|
|
"composes": [
|
|
"claim",
|
|
"set_plan",
|
|
"start"
|
|
],
|
|
"description": "Claim a task, set the plan, and transition to in_progress. Atomic - preconditions checked before any state mutation.",
|
|
"name": "i_will_work_on",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"developer"
|
|
],
|
|
"composes": [],
|
|
"description": "Push the branch and open a PR. Atomic - preconditions (assignee, >=1 commit, no prior PR) checked BEFORE any git operation. After success, call i_am_done.",
|
|
"name": "open_pr",
|
|
"pre_side_effects": [],
|
|
"side_effects": [
|
|
"push_branch",
|
|
"create_pr"
|
|
]
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"qa"
|
|
],
|
|
"composes": [
|
|
"qa_pass"
|
|
],
|
|
"description": "Pass QA. Transitions awaiting_qa -> awaiting_documentation.",
|
|
"name": "pass_review",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"pr_reviewer"
|
|
],
|
|
"composes": [
|
|
"pr_review_done"
|
|
],
|
|
"description": "Post one complete change-request to the external PR and finish the review task. in_progress -> completed.",
|
|
"name": "post_pr_review",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"pr_reviewer"
|
|
],
|
|
"composes": [
|
|
"pr_fail"
|
|
],
|
|
"description": "Fail the assembled-PR review with concrete issues. Transitions awaiting_pr_review -> needs_revision, routed back like a QA fail.",
|
|
"name": "pr_fail",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"pr_reviewer"
|
|
],
|
|
"composes": [
|
|
"pr_pass"
|
|
],
|
|
"description": "Pass the assembled-PR review. Transitions awaiting_pr_review -> awaiting_pm_review so the PM can merge.",
|
|
"name": "pr_pass",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"cell_pm"
|
|
],
|
|
"composes": [],
|
|
"description": "Hand a claimed/in_progress task to another developer in your own cell. The branch is keyed to the task (not the agent), so it is preserved \u2014 the new developer continues the work-in-progress. No status change.",
|
|
"name": "reassign",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"cell_pm",
|
|
"main_pm"
|
|
],
|
|
"composes": [
|
|
"request_changes"
|
|
],
|
|
"description": "Reject the merge review with concrete issues. Transitions awaiting_pm_review -> needs_revision, routed back like a QA fail (original developer for a leaf, revision PM for an assembled task). Use this for an AC/scope violation caught at merge review \u2014 never i_am_blocked/escalate, which have no revision routing.",
|
|
"name": "request_changes",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"cell_pm",
|
|
"developer",
|
|
"documenter",
|
|
"main_pm",
|
|
"qa"
|
|
],
|
|
"composes": [
|
|
"resume"
|
|
],
|
|
"description": "Resume a paused task you own. paused -> in_progress.",
|
|
"name": "resume",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"main_pm"
|
|
],
|
|
"composes": [
|
|
"submit_for_review"
|
|
],
|
|
"description": "Main PM opens the root\u2192master PR and moves the root task to awaiting_pr_review for the main reviewer (the root analogue of the cell PM's submit_up). After pr_pass, call complete to escalate to the CEO. For branch-bearing roots (a Main-PM root-subtask assembles the cells' merged work); branchless coordination roots skip the gate and complete directly. The gate is branch-keyed, not task_type-keyed \u2014 a Main-PM root is planning-typed, never code.",
|
|
"name": "submit_root",
|
|
"pre_side_effects": [
|
|
"create_root_pr"
|
|
],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"cell_pm"
|
|
],
|
|
"composes": [
|
|
"submit_for_review"
|
|
],
|
|
"description": "Cell PM opens the cell\u2192root PR and moves the cell task into the PR-review gate (awaiting_pr_review). The cell reviewer reviews the assembled diff; after pr_pass the same Cell PM completes it.",
|
|
"name": "submit_up",
|
|
"pre_side_effects": [
|
|
"create_pr"
|
|
],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"developer"
|
|
],
|
|
"composes": [],
|
|
"description": "Rebase your task's branch onto its current base THROUGH the gate (raw git is denied). Use when your branch has fallen behind its base \u2014 e.g. a sibling task's PR merged into the parent branch while you worked. Fetches origin, rebases head onto base, and force-pushes (with-lease). No DB state change. On conflicts the rebase is aborted and the conflicted files are returned \u2014 resolve by hand, commit, then sync_branch again.",
|
|
"name": "sync_branch",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"auditor",
|
|
"cell_pm",
|
|
"head_marketing",
|
|
"main_pm",
|
|
"product_owner"
|
|
],
|
|
"composes": [],
|
|
"description": "List actionable tasks in your scope.",
|
|
"name": "triage",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"main_pm"
|
|
],
|
|
"composes": [],
|
|
"description": "List actionable tasks across all teams (Main PM only).",
|
|
"name": "triage_all",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"cell_pm",
|
|
"main_pm"
|
|
],
|
|
"composes": [
|
|
"unblock"
|
|
],
|
|
"description": "PM unblocks a blocked task; restores pre-block state.",
|
|
"name": "unblock",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
},
|
|
{
|
|
"allowed_roles": [
|
|
"cell_pm",
|
|
"developer",
|
|
"documenter",
|
|
"main_pm",
|
|
"pr_reviewer",
|
|
"qa"
|
|
],
|
|
"composes": [],
|
|
"description": "Voluntarily release a claim back to pending. The work-in-progress branch is preserved. A PR reviewer who claimed an external review (in_progress) or a gate review (awaiting_pr_review) and cannot finish releases the claim here rather than wedging the lane until the stale-claim reaper.",
|
|
"name": "unclaim",
|
|
"pre_side_effects": [],
|
|
"side_effects": []
|
|
}
|
|
],
|
|
"transitions": [
|
|
{
|
|
"action": "cancel",
|
|
"roles": [
|
|
"ceo"
|
|
],
|
|
"source": "awaiting_ceo_approval",
|
|
"target": "cancelled"
|
|
},
|
|
{
|
|
"action": "ceo_approve",
|
|
"roles": [
|
|
"ceo"
|
|
],
|
|
"source": "awaiting_ceo_approval",
|
|
"target": "completed"
|
|
},
|
|
{
|
|
"action": "ceo_reject",
|
|
"roles": [
|
|
"ceo"
|
|
],
|
|
"source": "awaiting_ceo_approval",
|
|
"target": "needs_revision"
|
|
},
|
|
{
|
|
"action": "ceo_reject_to_pool",
|
|
"roles": [
|
|
"ceo"
|
|
],
|
|
"source": "awaiting_ceo_approval",
|
|
"target": "pending"
|
|
},
|
|
{
|
|
"action": "docs_complete",
|
|
"roles": [
|
|
"documenter"
|
|
],
|
|
"source": "awaiting_documentation",
|
|
"target": "awaiting_pm_review"
|
|
},
|
|
{
|
|
"action": "cancel",
|
|
"roles": [
|
|
"cell_pm",
|
|
"ceo",
|
|
"main_pm"
|
|
],
|
|
"source": "awaiting_documentation",
|
|
"target": "cancelled"
|
|
},
|
|
{
|
|
"action": "claim",
|
|
"roles": [
|
|
"documenter"
|
|
],
|
|
"source": "awaiting_documentation",
|
|
"target": "claimed"
|
|
},
|
|
{
|
|
"action": "escalate_to_ceo",
|
|
"roles": [
|
|
"head_marketing",
|
|
"main_pm",
|
|
"product_owner"
|
|
],
|
|
"source": "awaiting_pm_review",
|
|
"target": "awaiting_ceo_approval"
|
|
},
|
|
{
|
|
"action": "cancel",
|
|
"roles": [
|
|
"cell_pm",
|
|
"ceo",
|
|
"main_pm"
|
|
],
|
|
"source": "awaiting_pm_review",
|
|
"target": "cancelled"
|
|
},
|
|
{
|
|
"action": "complete",
|
|
"roles": [
|
|
"cell_pm",
|
|
"main_pm"
|
|
],
|
|
"source": "awaiting_pm_review",
|
|
"target": "completed"
|
|
},
|
|
{
|
|
"action": "request_changes",
|
|
"roles": [
|
|
"cell_pm",
|
|
"main_pm"
|
|
],
|
|
"source": "awaiting_pm_review",
|
|
"target": "needs_revision"
|
|
},
|
|
{
|
|
"action": "pr_pass",
|
|
"roles": [
|
|
"pr_reviewer"
|
|
],
|
|
"source": "awaiting_pr_review",
|
|
"target": "awaiting_pm_review"
|
|
},
|
|
{
|
|
"action": "cancel",
|
|
"roles": [
|
|
"cell_pm",
|
|
"ceo",
|
|
"main_pm"
|
|
],
|
|
"source": "awaiting_pr_review",
|
|
"target": "cancelled"
|
|
},
|
|
{
|
|
"action": "claim",
|
|
"roles": [
|
|
"pr_reviewer"
|
|
],
|
|
"source": "awaiting_pr_review",
|
|
"target": "claimed"
|
|
},
|
|
{
|
|
"action": "pr_fail",
|
|
"roles": [
|
|
"pr_reviewer"
|
|
],
|
|
"source": "awaiting_pr_review",
|
|
"target": "needs_revision"
|
|
},
|
|
{
|
|
"action": "qa_pass",
|
|
"roles": [
|
|
"qa"
|
|
],
|
|
"source": "awaiting_qa",
|
|
"target": "awaiting_documentation"
|
|
},
|
|
{
|
|
"action": "cancel",
|
|
"roles": [
|
|
"cell_pm",
|
|
"ceo",
|
|
"main_pm"
|
|
],
|
|
"source": "awaiting_qa",
|
|
"target": "cancelled"
|
|
},
|
|
{
|
|
"action": "claim",
|
|
"roles": [
|
|
"qa"
|
|
],
|
|
"source": "awaiting_qa",
|
|
"target": "claimed"
|
|
},
|
|
{
|
|
"action": "qa_fail",
|
|
"roles": [
|
|
"qa"
|
|
],
|
|
"source": "awaiting_qa",
|
|
"target": "needs_revision"
|
|
},
|
|
{
|
|
"action": "cancel",
|
|
"roles": [
|
|
"cell_pm",
|
|
"ceo",
|
|
"main_pm"
|
|
],
|
|
"source": "backlog",
|
|
"target": "cancelled"
|
|
},
|
|
{
|
|
"action": "activate",
|
|
"roles": null,
|
|
"source": "backlog",
|
|
"target": "pending"
|
|
},
|
|
{
|
|
"action": "escalate_to_ceo",
|
|
"roles": [
|
|
"head_marketing",
|
|
"main_pm",
|
|
"product_owner"
|
|
],
|
|
"source": "blocked",
|
|
"target": "awaiting_ceo_approval"
|
|
},
|
|
{
|
|
"action": "cancel",
|
|
"roles": [
|
|
"cell_pm",
|
|
"ceo",
|
|
"main_pm"
|
|
],
|
|
"source": "blocked",
|
|
"target": "cancelled"
|
|
},
|
|
{
|
|
"action": "unblock",
|
|
"roles": null,
|
|
"source": "blocked",
|
|
"target": "in_progress"
|
|
},
|
|
{
|
|
"action": "unblock",
|
|
"roles": null,
|
|
"source": "blocked",
|
|
"target": "pending"
|
|
},
|
|
{
|
|
"action": "cancel",
|
|
"roles": [
|
|
"cell_pm",
|
|
"ceo",
|
|
"main_pm"
|
|
],
|
|
"source": "claimed",
|
|
"target": "cancelled"
|
|
},
|
|
{
|
|
"action": "start",
|
|
"roles": null,
|
|
"source": "claimed",
|
|
"target": "in_progress"
|
|
},
|
|
{
|
|
"action": "submit_pm_review",
|
|
"roles": null,
|
|
"source": "in_progress",
|
|
"target": "awaiting_pm_review"
|
|
},
|
|
{
|
|
"action": "submit_for_review",
|
|
"roles": null,
|
|
"source": "in_progress",
|
|
"target": "awaiting_pr_review"
|
|
},
|
|
{
|
|
"action": "block",
|
|
"roles": null,
|
|
"source": "in_progress",
|
|
"target": "blocked"
|
|
},
|
|
{
|
|
"action": "cancel",
|
|
"roles": [
|
|
"cell_pm",
|
|
"ceo",
|
|
"main_pm"
|
|
],
|
|
"source": "in_progress",
|
|
"target": "cancelled"
|
|
},
|
|
{
|
|
"action": "pr_review_done",
|
|
"roles": [
|
|
"pr_reviewer"
|
|
],
|
|
"source": "in_progress",
|
|
"target": "completed"
|
|
},
|
|
{
|
|
"action": "pause",
|
|
"roles": null,
|
|
"source": "in_progress",
|
|
"target": "paused"
|
|
},
|
|
{
|
|
"action": "submit_verification",
|
|
"roles": null,
|
|
"source": "in_progress",
|
|
"target": "verifying"
|
|
},
|
|
{
|
|
"action": "cancel",
|
|
"roles": [
|
|
"cell_pm",
|
|
"ceo",
|
|
"main_pm"
|
|
],
|
|
"source": "needs_revision",
|
|
"target": "cancelled"
|
|
},
|
|
{
|
|
"action": "claim",
|
|
"roles": null,
|
|
"source": "needs_revision",
|
|
"target": "claimed"
|
|
},
|
|
{
|
|
"action": "cancel",
|
|
"roles": [
|
|
"cell_pm",
|
|
"ceo",
|
|
"main_pm"
|
|
],
|
|
"source": "paused",
|
|
"target": "cancelled"
|
|
},
|
|
{
|
|
"action": "resume",
|
|
"roles": null,
|
|
"source": "paused",
|
|
"target": "in_progress"
|
|
},
|
|
{
|
|
"action": "cancel",
|
|
"roles": [
|
|
"cell_pm",
|
|
"ceo",
|
|
"main_pm"
|
|
],
|
|
"source": "pending",
|
|
"target": "cancelled"
|
|
},
|
|
{
|
|
"action": "claim",
|
|
"roles": null,
|
|
"source": "pending",
|
|
"target": "claimed"
|
|
},
|
|
{
|
|
"action": "submit_qa",
|
|
"roles": null,
|
|
"source": "verifying",
|
|
"target": "awaiting_qa"
|
|
},
|
|
{
|
|
"action": "cancel",
|
|
"roles": [
|
|
"cell_pm",
|
|
"ceo",
|
|
"main_pm"
|
|
],
|
|
"source": "verifying",
|
|
"target": "cancelled"
|
|
}
|
|
]
|
|
}
|