agents-relay 2.0.10 → 2.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/README.md +15 -15
  2. package/dist/dashboard-html.js +1 -1
  3. package/dist/dashboard.js +1 -1
  4. package/dist/workflow/authoritative-unblock-v2.js +1 -1
  5. package/dist/workflow/blocker-resolution-v2.js +1 -1
  6. package/dist/workflow/definitions-v2.js +1 -1
  7. package/dist/workflow/planner-orchestration-v2.js +1 -1
  8. package/dist/workflow/planner-trigger-v2.js +1 -1
  9. package/dist/workflow/review-v2.js +1 -1
  10. package/dist/workflow/schedule-cycle-v2.js +1 -1
  11. package/dist/workflow/scheduled-run-v2.js +1 -1
  12. package/dist/workflow/task-related-action-v2.js +1 -1
  13. package/dist/workflow/troubleshooter-v2.js +1 -1
  14. package/package.json +1 -1
  15. package/workflow/job-lifecycle.mmd +66 -16
  16. package/workflow/task-lifecycle.mmd +201 -52
  17. package/dist/workflow/definitions.js +0 -37
  18. package/workflow/job-lifecycle-v2.mmd +0 -70
  19. package/workflow/task-lifecycle-v2.mmd +0 -201
  20. /package/workflow/{authoritative-unblock-v2.mmd → authoritative-unblock.mmd} +0 -0
  21. /package/workflow/{blocker-resolution-v2.mmd → blocker-resolution.mmd} +0 -0
  22. /package/workflow/{planner-orchestration-v2.mmd → planner-orchestration.mmd} +0 -0
  23. /package/workflow/{planner-trigger-v2.mmd → planner-trigger.mmd} +0 -0
  24. /package/workflow/{review-lifecycle-v2.mmd → review-lifecycle.mmd} +0 -0
  25. /package/workflow/{schedule-cycle-v2.mmd → schedule-cycle.mmd} +0 -0
  26. /package/workflow/{scheduled-run-v2.mmd → scheduled-run.mmd} +0 -0
  27. /package/workflow/{task-related-action-v2.mmd → task-related-action.mmd} +0 -0
  28. /package/workflow/{troubleshooter-v2.mmd → troubleshooter.mmd} +0 -0
package/README.md CHANGED
@@ -28,19 +28,19 @@ RelayStore owns local operational execution facts; GitHub remains the human-read
28
28
 
29
29
  | Area | Canonical graph |
30
30
  | --- | --- |
31
- | Job lifecycle | [`workflow/job-lifecycle-v2.mmd`](workflow/job-lifecycle-v2.mmd) |
32
- | Task lifecycle | [`workflow/task-lifecycle-v2.mmd`](workflow/task-lifecycle-v2.mmd) |
33
- | Review lifecycle | [`workflow/review-lifecycle-v2.mmd`](workflow/review-lifecycle-v2.mmd) |
34
- | Planner trigger | [`workflow/planner-trigger-v2.mmd`](workflow/planner-trigger-v2.mmd) |
35
- | Planner orchestration | [`workflow/planner-orchestration-v2.mmd`](workflow/planner-orchestration-v2.mmd) |
36
- | Blocker resolution | [`workflow/blocker-resolution-v2.mmd`](workflow/blocker-resolution-v2.mmd) |
37
- | Authoritative unblock | [`workflow/authoritative-unblock-v2.mmd`](workflow/authoritative-unblock-v2.mmd) |
38
- | Scheduled run | [`workflow/scheduled-run-v2.mmd`](workflow/scheduled-run-v2.mmd) |
39
- | Schedule cycle | [`workflow/schedule-cycle-v2.mmd`](workflow/schedule-cycle-v2.mmd) |
40
- | Troubleshooter | [`workflow/troubleshooter-v2.mmd`](workflow/troubleshooter-v2.mmd) |
41
- | Related-task action policy | [`workflow/task-related-action-v2.mmd`](workflow/task-related-action-v2.mmd) |
42
-
43
- Legacy [`workflow/job-lifecycle.mmd`](workflow/job-lifecycle.mmd) and [`workflow/task-lifecycle.mmd`](workflow/task-lifecycle.mmd) are compatibility/parity fixtures only. See [`docs/workflow-engine.md`](docs/workflow-engine.md) and [`docs/architecture-v2.md`](docs/architecture-v2.md).
31
+ | Job lifecycle | [`workflow/job-lifecycle.mmd`](workflow/job-lifecycle.mmd) |
32
+ | Task lifecycle | [`workflow/task-lifecycle.mmd`](workflow/task-lifecycle.mmd) |
33
+ | Review lifecycle | [`workflow/review-lifecycle.mmd`](workflow/review-lifecycle.mmd) |
34
+ | Planner trigger | [`workflow/planner-trigger.mmd`](workflow/planner-trigger.mmd) |
35
+ | Planner orchestration | [`workflow/planner-orchestration.mmd`](workflow/planner-orchestration.mmd) |
36
+ | Blocker resolution | [`workflow/blocker-resolution.mmd`](workflow/blocker-resolution.mmd) |
37
+ | Authoritative unblock | [`workflow/authoritative-unblock.mmd`](workflow/authoritative-unblock.mmd) |
38
+ | Scheduled run | [`workflow/scheduled-run.mmd`](workflow/scheduled-run.mmd) |
39
+ | Schedule cycle | [`workflow/schedule-cycle.mmd`](workflow/schedule-cycle.mmd) |
40
+ | Troubleshooter | [`workflow/troubleshooter.mmd`](workflow/troubleshooter.mmd) |
41
+ | Related-task action policy | [`workflow/task-related-action.mmd`](workflow/task-related-action.mmd) |
42
+
43
+ These paths always represent the current canonical graphs. Historical graph definitions are available through Git history, tags, and commits rather than parallel versioned files in `workflow/`. See [`docs/workflow-engine.md`](docs/workflow-engine.md) for the executable profile and runtime boundary.
44
44
 
45
45
  ## Quick start
46
46
 
@@ -88,9 +88,9 @@ npx agents-relay task update --repo OWNER/REPO --pr 12 --id job-1 --task-id chil
88
88
 
89
89
  Jobs separate durable lifecycle from derived runtime status. Durable lifecycle is `DRAFT | ACTIVE | COMPLETED | CANCELLED`: a newly created unscheduled Job is DRAFT, creating executable work activates it, and scheduled Jobs are ACTIVE because the scheduler is allowed to advance them. Runtime status (`IDLE`, `WAITING`, `QUEUED`, `RUNNING`, `BLOCKED`, `FAILED`, `REVIEWING`, `MERGE_PENDING`, `MERGED`, or `CANCELLED`) is computed from Tasks, Review, PR, and schedule facts and is never persisted as lifecycle truth.
90
90
 
91
- Lifecycle transition authority lives in the directly renderable V2 flowchart sources linked in [Workflow graph navigation](#workflow-graph-navigation). The legacy `stateDiagram-v2` files remain compatibility fixtures only; see [`docs/workflow-engine.md`](docs/workflow-engine.md) for the executable Mermaid profile and runtime boundary.
91
+ Lifecycle transition authority lives in the directly renderable canonical flowchart sources linked in [Workflow graph navigation](#workflow-graph-navigation). Git history owns prior graph versions; the working tree contains only the current graph set.
92
92
 
93
- The canonical Mermaid Graph Engine is the authoritative durable workflow decision path. Job/Task lifecycle transitions plus Review, Planner, Blocker/Unblock, Schedule, and Troubleshooter orchestration branches are defined by the v2 workflow graphs and executed through the shared graph runtime. TypeScript supplies facts and primitive action/effect implementations; it must not duplicate those workflow branches as a second procedural state machine.
93
+ The canonical Mermaid Graph Engine is the authoritative durable workflow decision path. Job/Task lifecycle transitions plus Review, Planner, Blocker/Unblock, Schedule, and Troubleshooter orchestration branches are defined by the canonical workflow graphs and executed through the shared graph runtime. TypeScript supplies facts and primitive action/effect implementations; it must not duplicate those workflow branches as a second procedural state machine.
94
94
 
95
95
  Job objectives and Task inputs are Markdown. Prefer `--objective-file` / `--input-file` (use `-` for stdin) for durable long-form context; inline `--objective` / `--input` remain for short/simple text and are mutually exclusive with the file variants. When a diagram materially clarifies the work, put Mermaid first and then Markdown detail. A newly created Job must capture enough context to finish independently of the originating chat. Its PR body contains exactly one hidden `agents-relay:job:v1` metadata marker followed by the objective Markdown; there is no separate Job comment duplicating the objective. Objective and Job metadata updates rewrite that same PR body. Legacy Job-comment markers remain readable and are migrated into the PR body on the next Job save.
96
96
 
@@ -186,9 +186,9 @@ export const dashboardHtml = `<!doctype html>
186
186
  <nav role="tablist" aria-label="Console views">
187
187
  <button id="jobs-tab" type="button" role="tab" aria-selected="true" aria-controls="jobs-view">Jobs</button>
188
188
  <button id="usage-tab" type="button" role="tab" aria-selected="false" aria-controls="usage-view">Usage</button>
189
- <button id="graphs-tab" type="button" role="tab" aria-selected="false" aria-controls="graphs-view">Graphs</button>
190
189
  <button id="rules-tab" type="button" role="tab" aria-selected="false" aria-controls="rules-view">Router Rules</button>
191
190
  <button id="shortcuts-tab" type="button" role="tab" aria-selected="false" aria-controls="shortcuts-view">Shortcuts</button>
191
+ <button id="graphs-tab" type="button" role="tab" aria-selected="false" aria-controls="graphs-view">Graphs</button>
192
192
  </nav>
193
193
  </header>
194
194
  <main>
package/dist/dashboard.js CHANGED
@@ -16,7 +16,7 @@ export async function dashboardWorkflowGraphs() {
16
16
  const names = (await readdir(WORKFLOW_DIR)).filter(name => name.endsWith('.mmd')).sort();
17
17
  return Promise.all(names.map(async (name) => ({
18
18
  id: name.replace(/\.mmd$/, ''),
19
- name: name.replace(/\.mmd$/, '').split('-').map(part => part === 'v2' ? 'V2' : part.charAt(0).toUpperCase() + part.slice(1)).join(' '),
19
+ name: name.replace(/\.mmd$/, '').split('-').map(part => part.charAt(0).toUpperCase() + part.slice(1)).join(' '),
20
20
  path: `workflow/${name}`,
21
21
  source: await readFile(join(WORKFLOW_DIR, name), 'utf8'),
22
22
  })));
@@ -1,7 +1,7 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { GraphRuntime } from './graph-v2.js';
3
3
  import { dispatchWorkflowGraph, dispatchWorkflowGraphSync } from './dispatcher.js';
4
- const source = readFileSync(new URL('../../workflow/authoritative-unblock-v2.mmd', import.meta.url), 'utf8');
4
+ const source = readFileSync(new URL('../../workflow/authoritative-unblock.mmd', import.meta.url), 'utf8');
5
5
  const boolGuard = (name) => (facts) => facts.durableFacts[name] === true;
6
6
  export const authoritativeUnblockV2 = new GraphRuntime(source, {
7
7
  states: new Set(['blocked', 'autonomous_replan', 'fixed_retry']),
@@ -1,7 +1,7 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { GraphRuntime } from './graph-v2.js';
3
3
  import { dispatchWorkflowGraph, dispatchWorkflowGraphSync } from './dispatcher.js';
4
- const source = readFileSync(new URL('../../workflow/blocker-resolution-v2.mmd', import.meta.url), 'utf8');
4
+ const source = readFileSync(new URL('../../workflow/blocker-resolution.mmd', import.meta.url), 'utf8');
5
5
  const boolGuard = (name) => (facts) => facts.durableFacts[name] === true;
6
6
  export const blockerResolutionV2 = new GraphRuntime(source, {
7
7
  states: new Set([
@@ -11,7 +11,7 @@ function actionRegistry() {
11
11
  return Object.fromEntries([...WORKFLOW_MUTATION_NAMES, ...WORKFLOW_EFFECT_NAMES].map(id => [id, { id }]));
12
12
  }
13
13
  function load(name, states, guards) {
14
- const url = new URL(`../../workflow/${name}-v2.mmd`, import.meta.url);
14
+ const url = new URL(`../../workflow/${name}.mmd`, import.meta.url);
15
15
  return new GraphRuntime(readFileSync(url, 'utf8'), {
16
16
  states: new Set(states),
17
17
  guards,
@@ -2,7 +2,7 @@ import { readFileSync } from 'node:fs';
2
2
  import { GraphRuntime } from './graph-v2.js';
3
3
  import { dispatchWorkflowGraph, dispatchWorkflowGraphSync } from './dispatcher.js';
4
4
  import { isEffectivelyBlocked } from '../unblock.js';
5
- const source = readFileSync(new URL('../../workflow/planner-orchestration-v2.mmd', import.meta.url), 'utf8');
5
+ const source = readFileSync(new URL('../../workflow/planner-orchestration.mmd', import.meta.url), 'utf8');
6
6
  const boolGuard = (name) => (facts) => facts.durableFacts[name] === true;
7
7
  export const plannerOrchestrationV2 = new GraphRuntime(source, {
8
8
  states: new Set([
@@ -1,7 +1,7 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { GraphRuntime } from './graph-v2.js';
3
3
  import { dispatchWorkflowGraphSync } from './dispatcher.js';
4
- const source = readFileSync(new URL('../../workflow/planner-trigger-v2.mmd', import.meta.url), 'utf8');
4
+ const source = readFileSync(new URL('../../workflow/planner-trigger.mmd', import.meta.url), 'utf8');
5
5
  const boolGuard = (name) => (facts) => facts.durableFacts[name] === true;
6
6
  export const plannerTriggerV2 = new GraphRuntime(source, {
7
7
  states: new Set(['idle', 'check_unblock', 'check_schedule', 'check_initial', 'manual', 'unblock', 'schedule', 'initial', 'continuation']),
@@ -1,7 +1,7 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { GraphRuntime } from './graph-v2.js';
3
3
  import { dispatchWorkflowGraph, dispatchWorkflowGraphSync } from './dispatcher.js';
4
- const source = readFileSync(new URL('../../workflow/review-lifecycle-v2.mmd', import.meta.url), 'utf8');
4
+ const source = readFileSync(new URL('../../workflow/review-lifecycle.mmd', import.meta.url), 'utf8');
5
5
  const boolGuard = (name) => (facts) => facts.durableFacts[name] === true;
6
6
  export const reviewLifecycleV2 = new GraphRuntime(source, {
7
7
  states: new Set(['NONE', 'PENDING', 'STARTED', 'APPROVED', 'CHANGES_REQUIRED', 'BLOCKED', 'STALE']),
@@ -1,7 +1,7 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { GraphRuntime } from './graph-v2.js';
3
3
  import { dispatchWorkflowGraphSync } from './dispatcher.js';
4
- const source = readFileSync(new URL('../../workflow/schedule-cycle-v2.mmd', import.meta.url), 'utf8');
4
+ const source = readFileSync(new URL('../../workflow/schedule-cycle.mmd', import.meta.url), 'utf8');
5
5
  const boolGuard = (name) => (facts) => facts.durableFacts[name] === true;
6
6
  export const scheduleCycleV2 = new GraphRuntime(source, {
7
7
  states: new Set(['idle', 'check_satisfied', 'waiting', 'finished']),
@@ -1,7 +1,7 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { GraphRuntime } from './graph-v2.js';
3
3
  import { dispatchWorkflowGraph, dispatchWorkflowGraphSync } from './dispatcher.js';
4
- const source = readFileSync(new URL('../../workflow/scheduled-run-v2.mmd', import.meta.url), 'utf8');
4
+ const source = readFileSync(new URL('../../workflow/scheduled-run.mmd', import.meta.url), 'utf8');
5
5
  const boolGuard = (name) => (facts) => facts.durableFacts[name] === true;
6
6
  export const scheduledRunV2 = new GraphRuntime(source, {
7
7
  states: new Set([
@@ -2,7 +2,7 @@ import { readFileSync } from 'node:fs';
2
2
  import { decideTaskLifecycle } from './lifecycle.js';
3
3
  import { GraphRuntime } from './graph-v2.js';
4
4
  import { dispatchWorkflowGraphSync } from './dispatcher.js';
5
- const source = readFileSync(new URL('../../workflow/task-related-action-v2.mmd', import.meta.url), 'utf8');
5
+ const source = readFileSync(new URL('../../workflow/task-related-action.mmd', import.meta.url), 'utf8');
6
6
  const boolGuard = (name) => (facts) => facts.durableFacts[name] === true;
7
7
  export const taskRelatedActionV2 = new GraphRuntime(source, {
8
8
  states: new Set(['evaluate', 'check_other', 'check_recovery', 'skip', 'selected']),
@@ -1,7 +1,7 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { GraphRuntime } from './graph-v2.js';
3
3
  import { dispatchWorkflowGraphSync } from './dispatcher.js';
4
- const source = readFileSync(new URL('../../workflow/troubleshooter-v2.mmd', import.meta.url), 'utf8');
4
+ const source = readFileSync(new URL('../../workflow/troubleshooter.mmd', import.meta.url), 'utf8');
5
5
  const boolGuard = (name) => (facts) => facts.durableFacts[name] === true;
6
6
  export const troubleshooterV2 = new GraphRuntime(source, {
7
7
  states: new Set(['idle', 'check_ordinary', 'check_run', 'check_needs', 'check_id', 'check_barrier', 'skip', 'create']),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agents-relay",
3
- "version": "2.0.10",
3
+ "version": "2.0.11",
4
4
  "description": "Durable async agent jobs coordinated through GitHub pull requests",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,20 +1,70 @@
1
- stateDiagram-v2
2
- [*] --> DRAFT
1
+ flowchart LR
2
+ %% relay: initial draft
3
+ draft["state: DRAFT"]
4
+ active["state: ACTIVE"]
5
+ completed["state: COMPLETED"]
6
+ cancelled["state: CANCELLED"]
7
+ notMergedDraft["guard: notMerged"]
8
+ notMergedActive["guard: notMerged"]
9
+ autoMergeReview["guard: autoMerge"]
10
+ autoMergeImplementation["guard: autoMerge"]
11
+ prOpenReconcile["guard: prOpen"]
12
+ reviewDisabledReconcile["guard: reviewDisabled"]
13
+ implementationCompleteReconcile["guard: implementationComplete"]
14
+ autoMergeReconcile["guard: autoMerge"]
15
+ headAvailableReconcile["guard: headAvailable"]
16
+ mergeCapableReconcile["guard: mergeCapable"]
17
+ mergeReconcile["action: effect.mergePullRequest"]
18
+ cancelDraftMerge["action: effect.cancelActiveTasks"]
19
+ cancelDraftClose["action: effect.cancelActiveTasks"]
20
+ mergeReview["action: effect.mergePullRequest"]
21
+ mergeImplementation["action: effect.mergePullRequest"]
22
+ cancelActiveMerge["action: effect.cancelActiveTasks"]
23
+ cancelActiveClose["action: effect.cancelActiveTasks"]
24
+ cancelCancelledMerge["action: effect.cancelActiveTasks"]
3
25
 
4
- DRAFT --> ACTIVE: activate
5
- DRAFT --> COMPLETED: pr.merged / effect.cancelActiveTasks
6
- DRAFT --> CANCELLED: cancel / effect.cancelActiveTasks
7
- DRAFT --> CANCELLED: pr.closed [notMerged] / effect.cancelActiveTasks
26
+ draft -->|on: activate| active
27
+ draft -->|on: pr.merged| cancelDraftMerge
28
+ cancelDraftMerge --> completed
29
+ draft -->|on: cancel| cancelDraft
30
+ cancelDraft["action: effect.cancelActiveTasks"]
31
+ cancelDraft --> cancelled
32
+ draft -->|on: pr.closed| notMergedDraft
33
+ notMergedDraft -->|true| cancelDraftClose
34
+ cancelDraftClose --> cancelled
8
35
 
9
- ACTIVE --> ACTIVE: review.approved [autoMerge] / effect.mergePullRequest
10
- ACTIVE --> ACTIVE: implementation.completed [autoMerge] / effect.mergePullRequest
11
- ACTIVE --> ACTIVE: effect.mergePullRequest.failed
12
- ACTIVE --> COMPLETED: pr.merged / effect.cancelActiveTasks
13
- ACTIVE --> CANCELLED: cancel / effect.cancelActiveTasks
14
- ACTIVE --> CANCELLED: pr.closed [notMerged] / effect.cancelActiveTasks
36
+ active -->|on: reconcile| prOpenReconcile
37
+ prOpenReconcile -->|true| reviewDisabledReconcile
38
+ prOpenReconcile -->|false| active
39
+ reviewDisabledReconcile -->|true| implementationCompleteReconcile
40
+ reviewDisabledReconcile -->|false| active
41
+ implementationCompleteReconcile -->|true| autoMergeReconcile
42
+ implementationCompleteReconcile -->|false| active
43
+ autoMergeReconcile -->|true| headAvailableReconcile
44
+ autoMergeReconcile -->|false| active
45
+ headAvailableReconcile -->|true| mergeCapableReconcile
46
+ headAvailableReconcile -->|false| active
47
+ mergeCapableReconcile -->|true| mergeReconcile
48
+ mergeCapableReconcile -->|false| active
49
+ mergeReconcile --> active
15
50
 
16
- CANCELLED --> COMPLETED: pr.merged / effect.cancelActiveTasks
17
- CANCELLED --> CANCELLED: effect.cancelActiveTasks.failed
18
- COMPLETED --> COMPLETED: effect.cancelActiveTasks.failed
51
+ active -->|on: review.approved| autoMergeReview
52
+ autoMergeReview -->|true| mergeReview
53
+ mergeReview --> active
54
+ active -->|on: implementation.completed| autoMergeImplementation
55
+ autoMergeImplementation -->|true| mergeImplementation
56
+ mergeImplementation --> active
57
+ active -->|on: effect.mergePullRequest.failed| active
58
+ active -->|on: pr.merged| cancelActiveMerge
59
+ cancelActiveMerge --> completed
60
+ active -->|on: cancel| cancelActive
61
+ cancelActive["action: effect.cancelActiveTasks"]
62
+ cancelActive --> cancelled
63
+ active -->|on: pr.closed| notMergedActive
64
+ notMergedActive -->|true| cancelActiveClose
65
+ cancelActiveClose --> cancelled
19
66
 
20
- COMPLETED --> [*]
67
+ cancelled -->|on: pr.merged| cancelCancelledMerge
68
+ cancelCancelledMerge --> completed
69
+ cancelled -->|on: effect.cancelActiveTasks.failed| cancelled
70
+ completed -->|on: effect.cancelActiveTasks.failed| completed
@@ -1,52 +1,201 @@
1
- stateDiagram-v2
2
- [*] --> DRAFT
3
-
4
- DRAFT --> QUEUED: release / mutation.clearError,mutation.clearFailureReason
5
- DRAFT --> QUEUED: queue [dependenciesSatisfied] / mutation.clearError,mutation.clearFailureReason
6
- DRAFT --> QUEUED: reconcile [dependenciesSatisfied] / mutation.clearError,mutation.clearFailureReason
7
- DRAFT --> BLOCKED: block
8
- DRAFT --> CANCELLED: cancel
9
-
10
- QUEUED --> DRAFT: hold
11
- QUEUED --> DRAFT: reconcile [dependenciesUnsatisfied]
12
- QUEUED --> QUEUED: reconcile [runnable] / mutation.clearError,mutation.clearFailureReason
13
- QUEUED --> QUEUED: dispatch [dispatchable] / effect.launchTask
14
- QUEUED --> RUNNING: task.started / mutation.clearError,mutation.clearFailureReason
15
- QUEUED --> RUNNING: review.started / mutation.clearError,mutation.clearFailureReason
16
- QUEUED --> SUCCEEDED: review.approved / mutation.clearError,mutation.clearFailureReason
17
- QUEUED --> SUCCEEDED: review.changes_required / mutation.clearError,mutation.clearFailureReason
18
- QUEUED --> BLOCKED: review.blocked
19
- QUEUED --> BLOCKED: block
20
- QUEUED --> FAILED: fail
21
- QUEUED --> FAILED: effect.launchTask.failed
22
- QUEUED --> FAILED: watchdog.failed
23
- QUEUED --> FAILED: worker.delivery_failed
24
- QUEUED --> FAILED: worker.start_ack_failed
25
- QUEUED --> CANCELLED: cancel
26
-
27
- RUNNING --> BLOCKED: task.blocked
28
- RUNNING --> SUCCEEDED: review.approved / mutation.clearError,mutation.clearFailureReason
29
- RUNNING --> SUCCEEDED: review.changes_required / mutation.clearError,mutation.clearFailureReason
30
- RUNNING --> BLOCKED: review.blocked
31
- RUNNING --> SUCCEEDED: task.completed / mutation.clearError,mutation.clearFailureReason
32
- RUNNING --> FAILED: task.failed
33
- RUNNING --> FAILED: watchdog.failed
34
- RUNNING --> CANCELLED: task.cancelled
35
- RUNNING --> CANCELLED: cancel
36
-
37
- BLOCKED --> UNBLOCKED: task.unblocked
38
- BLOCKED --> CANCELLED: cancel
39
-
40
- UNBLOCKED --> QUEUED: retry / mutation.clearError,mutation.clearFailureReason
41
-
42
- FAILED --> QUEUED: queue [dependenciesSatisfied] / mutation.clearError,mutation.clearFailureReason
43
- FAILED --> QUEUED: retry / mutation.clearError,mutation.clearFailureReason
44
- FAILED --> RUNNING: task.started [recoverableExecution] / mutation.clearError,mutation.clearFailureReason
45
- FAILED --> SUCCEEDED: task.completed [recoverableExecution] / mutation.clearError,mutation.clearFailureReason
46
- FAILED --> BLOCKED: task.blocked [recoverableExecution]
47
- FAILED --> FAILED: task.failed [recoverableExecution]
48
- FAILED --> CANCELLED: task.cancelled [recoverableExecution]
49
- FAILED --> CANCELLED: cancel
50
-
51
- SUCCEEDED --> [*]
52
- CANCELLED --> [*]
1
+ flowchart LR
2
+ %% relay: initial draft
3
+ draft["state: DRAFT"]
4
+ queued["state: QUEUED"]
5
+ running["state: RUNNING"]
6
+ blocked["state: BLOCKED"]
7
+ unblocked["state: UNBLOCKED"]
8
+ succeeded["state: SUCCEEDED"]
9
+ failed["state: FAILED"]
10
+ cancelled["state: CANCELLED"]
11
+
12
+ depSat["guard: dependenciesSatisfied"]
13
+ depUnsat["guard: dependenciesUnsatisfied"]
14
+ runnable["guard: runnable"]
15
+ dispatchable["guard: dispatchable"]
16
+ recoverStart["guard: recoverableExecution"]
17
+ recoverComplete["guard: recoverableExecution"]
18
+ recoverBlocked["guard: recoverableExecution"]
19
+ recoverFailed["guard: recoverableExecution"]
20
+ recoverCancelled["guard: recoverableExecution"]
21
+
22
+ retryAvailableRunning["guard: retryAvailable"]
23
+ plannerRetryAvailable["guard: retryAvailable"]
24
+ plannerUnavailableMark["action: mutation.markPlannerUnavailable"]
25
+ orphanRetryAvailable["guard: retryAvailable"]
26
+ orphanRetryClearError["action: mutation.clearError"]
27
+ orphanRetryClearLease["action: mutation.clearLease"]
28
+ orphanRetryClearExecution["action: mutation.clearExecution"]
29
+ orphanFailMark["action: mutation.markStartupOrphanedExhausted"]
30
+ orphanFailClearLease["action: mutation.clearLease"]
31
+ orphanFailClearExecution["action: mutation.clearExecution"]
32
+ plannerRetryClearError["action: mutation.clearError"]
33
+ plannerRetryClearLease["action: mutation.clearLease"]
34
+ plannerRetryClearExecution["action: mutation.clearExecution"]
35
+ plannerFailClearLease["action: mutation.clearLease"]
36
+ plannerFailClearExecution["action: mutation.clearExecution"]
37
+ retryAvailableQueued["guard: retryAvailable"]
38
+ leaseRetryRunningClearError["action: mutation.clearError"]
39
+ leaseRetryRunningClearLease["action: mutation.clearLease"]
40
+ leaseRetryRunningClearExecution["action: mutation.clearExecution"]
41
+ leaseFailRunningMark["action: mutation.markLeaseExpired"]
42
+ leaseFailRunningClearLease["action: mutation.clearLease"]
43
+ leaseFailRunningClearExecution["action: mutation.clearExecution"]
44
+ leaseRetryQueuedClearError["action: mutation.clearError"]
45
+ leaseRetryQueuedClearLease["action: mutation.clearLease"]
46
+ leaseRetryQueuedClearExecution["action: mutation.clearExecution"]
47
+ leaseFailQueuedMark["action: mutation.markLeaseExpired"]
48
+ leaseFailQueuedClearLease["action: mutation.clearLease"]
49
+ leaseFailQueuedClearExecution["action: mutation.clearExecution"]
50
+
51
+ releaseClearError["action: mutation.clearError"]
52
+ releaseClearReason["action: mutation.clearFailureReason"]
53
+ reconcileDraftClearError["action: mutation.clearError"]
54
+ reconcileDraftClearReason["action: mutation.clearFailureReason"]
55
+ reconcileQueuedClearError["action: mutation.clearError"]
56
+ reconcileQueuedClearReason["action: mutation.clearFailureReason"]
57
+ dispatchLaunch["action: effect.launchTask"]
58
+ startClearError["action: mutation.clearError"]
59
+ startClearReason["action: mutation.clearFailureReason"]
60
+ reviewStartClearError["action: mutation.clearError"]
61
+ reviewStartClearReason["action: mutation.clearFailureReason"]
62
+ reviewApproveQueuedClearError["action: mutation.clearError"]
63
+ reviewApproveQueuedClearReason["action: mutation.clearFailureReason"]
64
+ reviewChangesQueuedClearError["action: mutation.clearError"]
65
+ reviewChangesQueuedClearReason["action: mutation.clearFailureReason"]
66
+ reviewApproveRunningClearError["action: mutation.clearError"]
67
+ reviewApproveRunningClearReason["action: mutation.clearFailureReason"]
68
+ reviewChangesRunningClearError["action: mutation.clearError"]
69
+ reviewChangesRunningClearReason["action: mutation.clearFailureReason"]
70
+ completeClearError["action: mutation.clearError"]
71
+ completeClearReason["action: mutation.clearFailureReason"]
72
+ unblockRetryClearError["action: mutation.clearError"]
73
+ unblockRetryClearReason["action: mutation.clearFailureReason"]
74
+ failedRetryClearError["action: mutation.clearError"]
75
+ failedRetryClearReason["action: mutation.clearFailureReason"]
76
+ recoverStartClearError["action: mutation.clearError"]
77
+ recoverStartClearReason["action: mutation.clearFailureReason"]
78
+ recoverCompleteClearError["action: mutation.clearError"]
79
+ recoverCompleteClearReason["action: mutation.clearFailureReason"]
80
+
81
+ draft -->|on: release| releaseClearError
82
+ releaseClearError --> releaseClearReason
83
+ releaseClearReason --> queued
84
+ draft -->|on: queue| depSat
85
+ draft -->|on: reconcile| depSat
86
+ depSat -->|true| reconcileDraftClearError
87
+ reconcileDraftClearError --> reconcileDraftClearReason
88
+ reconcileDraftClearReason --> queued
89
+ draft -->|on: block| blocked
90
+ draft -->|on: cancel| cancelled
91
+
92
+ queued -->|on: hold| draft
93
+ queued -->|on: reconcile| depUnsat
94
+ depUnsat -->|true| draft
95
+ queued -->|on: reconcile| runnable
96
+ runnable -->|true| reconcileQueuedClearError
97
+ reconcileQueuedClearError --> reconcileQueuedClearReason
98
+ reconcileQueuedClearReason --> queued
99
+ queued -->|on: dispatch| dispatchable
100
+ dispatchable -->|true| dispatchLaunch
101
+ dispatchLaunch --> queued
102
+ queued -->|on: task.started| startClearError
103
+ startClearError --> startClearReason
104
+ startClearReason --> running
105
+ queued -->|on: review.started| reviewStartClearError
106
+ reviewStartClearError --> reviewStartClearReason
107
+ reviewStartClearReason --> running
108
+ queued -->|on: review.approved| reviewApproveQueuedClearError
109
+ reviewApproveQueuedClearError --> reviewApproveQueuedClearReason
110
+ reviewApproveQueuedClearReason --> succeeded
111
+ queued -->|on: review.changes_required| reviewChangesQueuedClearError
112
+ reviewChangesQueuedClearError --> reviewChangesQueuedClearReason
113
+ reviewChangesQueuedClearReason --> succeeded
114
+ queued -->|on: review.blocked| blocked
115
+ queued -->|on: block| blocked
116
+ queued -->|on: fail| failed
117
+ queued -->|on: effect.launchTask.failed| failed
118
+ queued -->|on: watchdog.failed| failed
119
+ queued -->|on: worker.delivery_failed| failed
120
+ queued -->|on: worker.start_ack_failed| failed
121
+ queued -->|on: planner.unavailable| plannerUnavailableMark
122
+ plannerUnavailableMark --> failed
123
+ queued -->|on: lease.expired| retryAvailableQueued
124
+ retryAvailableQueued -->|true| leaseRetryQueuedClearError
125
+ leaseRetryQueuedClearError --> leaseRetryQueuedClearLease
126
+ leaseRetryQueuedClearLease --> leaseRetryQueuedClearExecution
127
+ leaseRetryQueuedClearExecution --> queued
128
+ retryAvailableQueued -->|false| leaseFailQueuedMark
129
+ leaseFailQueuedMark --> leaseFailQueuedClearLease
130
+ leaseFailQueuedClearLease --> leaseFailQueuedClearExecution
131
+ leaseFailQueuedClearExecution --> failed
132
+ queued -->|on: cancel| cancelled
133
+
134
+ running -->|on: task.blocked| blocked
135
+ running -->|on: review.approved| reviewApproveRunningClearError
136
+ reviewApproveRunningClearError --> reviewApproveRunningClearReason
137
+ reviewApproveRunningClearReason --> succeeded
138
+ running -->|on: review.changes_required| reviewChangesRunningClearError
139
+ reviewChangesRunningClearError --> reviewChangesRunningClearReason
140
+ reviewChangesRunningClearReason --> succeeded
141
+ running -->|on: review.blocked| blocked
142
+ running -->|on: task.completed| completeClearError
143
+ completeClearError --> completeClearReason
144
+ completeClearReason --> succeeded
145
+ running -->|on: task.failed| failed
146
+ running -->|on: watchdog.failed| failed
147
+ running -->|on: planner.failed| plannerRetryAvailable
148
+ running -->|on: execution.orphaned| orphanRetryAvailable
149
+ orphanRetryAvailable -->|true| orphanRetryClearError
150
+ orphanRetryClearError --> orphanRetryClearLease
151
+ orphanRetryClearLease --> orphanRetryClearExecution
152
+ orphanRetryClearExecution --> queued
153
+ orphanRetryAvailable -->|false| orphanFailMark
154
+ orphanFailMark --> orphanFailClearLease
155
+ orphanFailClearLease --> orphanFailClearExecution
156
+ orphanFailClearExecution --> failed
157
+ plannerRetryAvailable -->|true| plannerRetryClearError
158
+ plannerRetryClearError --> plannerRetryClearLease
159
+ plannerRetryClearLease --> plannerRetryClearExecution
160
+ plannerRetryClearExecution --> queued
161
+ plannerRetryAvailable -->|false| plannerFailClearLease
162
+ plannerFailClearLease --> plannerFailClearExecution
163
+ plannerFailClearExecution --> failed
164
+ running -->|on: lease.expired| retryAvailableRunning
165
+ retryAvailableRunning -->|true| leaseRetryRunningClearError
166
+ leaseRetryRunningClearError --> leaseRetryRunningClearLease
167
+ leaseRetryRunningClearLease --> leaseRetryRunningClearExecution
168
+ leaseRetryRunningClearExecution --> queued
169
+ retryAvailableRunning -->|false| leaseFailRunningMark
170
+ leaseFailRunningMark --> leaseFailRunningClearLease
171
+ leaseFailRunningClearLease --> leaseFailRunningClearExecution
172
+ leaseFailRunningClearExecution --> failed
173
+ running -->|on: task.cancelled| cancelled
174
+ running -->|on: cancel| cancelled
175
+
176
+ blocked -->|on: task.unblocked| unblocked
177
+ blocked -->|on: cancel| cancelled
178
+
179
+ unblocked -->|on: retry| unblockRetryClearError
180
+ unblockRetryClearError --> unblockRetryClearReason
181
+ unblockRetryClearReason --> queued
182
+
183
+ failed -->|on: queue| depSat
184
+ failed -->|on: retry| failedRetryClearError
185
+ failedRetryClearError --> failedRetryClearReason
186
+ failedRetryClearReason --> queued
187
+ failed -->|on: task.started| recoverStart
188
+ recoverStart -->|true| recoverStartClearError
189
+ recoverStartClearError --> recoverStartClearReason
190
+ recoverStartClearReason --> running
191
+ failed -->|on: task.completed| recoverComplete
192
+ recoverComplete -->|true| recoverCompleteClearError
193
+ recoverCompleteClearError --> recoverCompleteClearReason
194
+ recoverCompleteClearReason --> succeeded
195
+ failed -->|on: task.blocked| recoverBlocked
196
+ recoverBlocked -->|true| blocked
197
+ failed -->|on: task.failed| recoverFailed
198
+ recoverFailed -->|true| failed
199
+ failed -->|on: task.cancelled| recoverCancelled
200
+ recoverCancelled -->|true| cancelled
201
+ failed -->|on: cancel| cancelled
@@ -1,37 +0,0 @@
1
- import { readFileSync } from 'node:fs';
2
- import { parseExecutableMermaid, WorkflowEngine } from './mermaid.js';
3
- import { WORKFLOW_EFFECT_NAMES, WORKFLOW_EVENT_NAMES, WORKFLOW_FACT_NAMES, WORKFLOW_MUTATION_NAMES, classifyWorkflowActions } from './contracts.js';
4
- function declarativeActions() {
5
- return Object.fromEntries([...WORKFLOW_MUTATION_NAMES, ...WORKFLOW_EFFECT_NAMES].map(name => [name, { declarative: true }]));
6
- }
7
- export function validateCanonicalWorkflowGraph(graph) {
8
- const canonicalEvents = new Set(WORKFLOW_EVENT_NAMES);
9
- const canonicalFacts = new Set(WORKFLOW_FACT_NAMES);
10
- for (const transition of graph.transitions) {
11
- if (!canonicalEvents.has(transition.event)) {
12
- throw new Error(`Unknown canonical workflow event ${transition.event} referenced at line ${transition.line}`);
13
- }
14
- if (transition.guard && !canonicalFacts.has(transition.guard)) {
15
- throw new Error(`Unknown canonical workflow fact ${transition.guard} referenced at line ${transition.line}`);
16
- }
17
- classifyWorkflowActions(transition.actions);
18
- }
19
- }
20
- function load(name, guards = {}) {
21
- const url = new URL(`../../workflow/${name}.mmd`, import.meta.url);
22
- const graph = parseExecutableMermaid(readFileSync(url, 'utf8'));
23
- validateCanonicalWorkflowGraph(graph);
24
- return new WorkflowEngine(graph, guards, declarativeActions());
25
- }
26
- const booleanGuard = (name) => context => context[name] === true;
27
- export const jobLifecycleWorkflow = load('job-lifecycle', {
28
- notMerged: booleanGuard('notMerged'),
29
- autoMerge: booleanGuard('autoMerge'),
30
- });
31
- export const taskLifecycleWorkflow = load('task-lifecycle', {
32
- dependenciesSatisfied: booleanGuard('dependenciesSatisfied'),
33
- dependenciesUnsatisfied: booleanGuard('dependenciesUnsatisfied'),
34
- runnable: booleanGuard('runnable'),
35
- dispatchable: booleanGuard('dispatchable'),
36
- recoverableExecution: booleanGuard('recoverableExecution'),
37
- });
@@ -1,70 +0,0 @@
1
- flowchart LR
2
- %% relay: initial draft
3
- draft["state: DRAFT"]
4
- active["state: ACTIVE"]
5
- completed["state: COMPLETED"]
6
- cancelled["state: CANCELLED"]
7
- notMergedDraft["guard: notMerged"]
8
- notMergedActive["guard: notMerged"]
9
- autoMergeReview["guard: autoMerge"]
10
- autoMergeImplementation["guard: autoMerge"]
11
- prOpenReconcile["guard: prOpen"]
12
- reviewDisabledReconcile["guard: reviewDisabled"]
13
- implementationCompleteReconcile["guard: implementationComplete"]
14
- autoMergeReconcile["guard: autoMerge"]
15
- headAvailableReconcile["guard: headAvailable"]
16
- mergeCapableReconcile["guard: mergeCapable"]
17
- mergeReconcile["action: effect.mergePullRequest"]
18
- cancelDraftMerge["action: effect.cancelActiveTasks"]
19
- cancelDraftClose["action: effect.cancelActiveTasks"]
20
- mergeReview["action: effect.mergePullRequest"]
21
- mergeImplementation["action: effect.mergePullRequest"]
22
- cancelActiveMerge["action: effect.cancelActiveTasks"]
23
- cancelActiveClose["action: effect.cancelActiveTasks"]
24
- cancelCancelledMerge["action: effect.cancelActiveTasks"]
25
-
26
- draft -->|on: activate| active
27
- draft -->|on: pr.merged| cancelDraftMerge
28
- cancelDraftMerge --> completed
29
- draft -->|on: cancel| cancelDraft
30
- cancelDraft["action: effect.cancelActiveTasks"]
31
- cancelDraft --> cancelled
32
- draft -->|on: pr.closed| notMergedDraft
33
- notMergedDraft -->|true| cancelDraftClose
34
- cancelDraftClose --> cancelled
35
-
36
- active -->|on: reconcile| prOpenReconcile
37
- prOpenReconcile -->|true| reviewDisabledReconcile
38
- prOpenReconcile -->|false| active
39
- reviewDisabledReconcile -->|true| implementationCompleteReconcile
40
- reviewDisabledReconcile -->|false| active
41
- implementationCompleteReconcile -->|true| autoMergeReconcile
42
- implementationCompleteReconcile -->|false| active
43
- autoMergeReconcile -->|true| headAvailableReconcile
44
- autoMergeReconcile -->|false| active
45
- headAvailableReconcile -->|true| mergeCapableReconcile
46
- headAvailableReconcile -->|false| active
47
- mergeCapableReconcile -->|true| mergeReconcile
48
- mergeCapableReconcile -->|false| active
49
- mergeReconcile --> active
50
-
51
- active -->|on: review.approved| autoMergeReview
52
- autoMergeReview -->|true| mergeReview
53
- mergeReview --> active
54
- active -->|on: implementation.completed| autoMergeImplementation
55
- autoMergeImplementation -->|true| mergeImplementation
56
- mergeImplementation --> active
57
- active -->|on: effect.mergePullRequest.failed| active
58
- active -->|on: pr.merged| cancelActiveMerge
59
- cancelActiveMerge --> completed
60
- active -->|on: cancel| cancelActive
61
- cancelActive["action: effect.cancelActiveTasks"]
62
- cancelActive --> cancelled
63
- active -->|on: pr.closed| notMergedActive
64
- notMergedActive -->|true| cancelActiveClose
65
- cancelActiveClose --> cancelled
66
-
67
- cancelled -->|on: pr.merged| cancelCancelledMerge
68
- cancelCancelledMerge --> completed
69
- cancelled -->|on: effect.cancelActiveTasks.failed| cancelled
70
- completed -->|on: effect.cancelActiveTasks.failed| completed
@@ -1,201 +0,0 @@
1
- flowchart LR
2
- %% relay: initial draft
3
- draft["state: DRAFT"]
4
- queued["state: QUEUED"]
5
- running["state: RUNNING"]
6
- blocked["state: BLOCKED"]
7
- unblocked["state: UNBLOCKED"]
8
- succeeded["state: SUCCEEDED"]
9
- failed["state: FAILED"]
10
- cancelled["state: CANCELLED"]
11
-
12
- depSat["guard: dependenciesSatisfied"]
13
- depUnsat["guard: dependenciesUnsatisfied"]
14
- runnable["guard: runnable"]
15
- dispatchable["guard: dispatchable"]
16
- recoverStart["guard: recoverableExecution"]
17
- recoverComplete["guard: recoverableExecution"]
18
- recoverBlocked["guard: recoverableExecution"]
19
- recoverFailed["guard: recoverableExecution"]
20
- recoverCancelled["guard: recoverableExecution"]
21
-
22
- retryAvailableRunning["guard: retryAvailable"]
23
- plannerRetryAvailable["guard: retryAvailable"]
24
- plannerUnavailableMark["action: mutation.markPlannerUnavailable"]
25
- orphanRetryAvailable["guard: retryAvailable"]
26
- orphanRetryClearError["action: mutation.clearError"]
27
- orphanRetryClearLease["action: mutation.clearLease"]
28
- orphanRetryClearExecution["action: mutation.clearExecution"]
29
- orphanFailMark["action: mutation.markStartupOrphanedExhausted"]
30
- orphanFailClearLease["action: mutation.clearLease"]
31
- orphanFailClearExecution["action: mutation.clearExecution"]
32
- plannerRetryClearError["action: mutation.clearError"]
33
- plannerRetryClearLease["action: mutation.clearLease"]
34
- plannerRetryClearExecution["action: mutation.clearExecution"]
35
- plannerFailClearLease["action: mutation.clearLease"]
36
- plannerFailClearExecution["action: mutation.clearExecution"]
37
- retryAvailableQueued["guard: retryAvailable"]
38
- leaseRetryRunningClearError["action: mutation.clearError"]
39
- leaseRetryRunningClearLease["action: mutation.clearLease"]
40
- leaseRetryRunningClearExecution["action: mutation.clearExecution"]
41
- leaseFailRunningMark["action: mutation.markLeaseExpired"]
42
- leaseFailRunningClearLease["action: mutation.clearLease"]
43
- leaseFailRunningClearExecution["action: mutation.clearExecution"]
44
- leaseRetryQueuedClearError["action: mutation.clearError"]
45
- leaseRetryQueuedClearLease["action: mutation.clearLease"]
46
- leaseRetryQueuedClearExecution["action: mutation.clearExecution"]
47
- leaseFailQueuedMark["action: mutation.markLeaseExpired"]
48
- leaseFailQueuedClearLease["action: mutation.clearLease"]
49
- leaseFailQueuedClearExecution["action: mutation.clearExecution"]
50
-
51
- releaseClearError["action: mutation.clearError"]
52
- releaseClearReason["action: mutation.clearFailureReason"]
53
- reconcileDraftClearError["action: mutation.clearError"]
54
- reconcileDraftClearReason["action: mutation.clearFailureReason"]
55
- reconcileQueuedClearError["action: mutation.clearError"]
56
- reconcileQueuedClearReason["action: mutation.clearFailureReason"]
57
- dispatchLaunch["action: effect.launchTask"]
58
- startClearError["action: mutation.clearError"]
59
- startClearReason["action: mutation.clearFailureReason"]
60
- reviewStartClearError["action: mutation.clearError"]
61
- reviewStartClearReason["action: mutation.clearFailureReason"]
62
- reviewApproveQueuedClearError["action: mutation.clearError"]
63
- reviewApproveQueuedClearReason["action: mutation.clearFailureReason"]
64
- reviewChangesQueuedClearError["action: mutation.clearError"]
65
- reviewChangesQueuedClearReason["action: mutation.clearFailureReason"]
66
- reviewApproveRunningClearError["action: mutation.clearError"]
67
- reviewApproveRunningClearReason["action: mutation.clearFailureReason"]
68
- reviewChangesRunningClearError["action: mutation.clearError"]
69
- reviewChangesRunningClearReason["action: mutation.clearFailureReason"]
70
- completeClearError["action: mutation.clearError"]
71
- completeClearReason["action: mutation.clearFailureReason"]
72
- unblockRetryClearError["action: mutation.clearError"]
73
- unblockRetryClearReason["action: mutation.clearFailureReason"]
74
- failedRetryClearError["action: mutation.clearError"]
75
- failedRetryClearReason["action: mutation.clearFailureReason"]
76
- recoverStartClearError["action: mutation.clearError"]
77
- recoverStartClearReason["action: mutation.clearFailureReason"]
78
- recoverCompleteClearError["action: mutation.clearError"]
79
- recoverCompleteClearReason["action: mutation.clearFailureReason"]
80
-
81
- draft -->|on: release| releaseClearError
82
- releaseClearError --> releaseClearReason
83
- releaseClearReason --> queued
84
- draft -->|on: queue| depSat
85
- draft -->|on: reconcile| depSat
86
- depSat -->|true| reconcileDraftClearError
87
- reconcileDraftClearError --> reconcileDraftClearReason
88
- reconcileDraftClearReason --> queued
89
- draft -->|on: block| blocked
90
- draft -->|on: cancel| cancelled
91
-
92
- queued -->|on: hold| draft
93
- queued -->|on: reconcile| depUnsat
94
- depUnsat -->|true| draft
95
- queued -->|on: reconcile| runnable
96
- runnable -->|true| reconcileQueuedClearError
97
- reconcileQueuedClearError --> reconcileQueuedClearReason
98
- reconcileQueuedClearReason --> queued
99
- queued -->|on: dispatch| dispatchable
100
- dispatchable -->|true| dispatchLaunch
101
- dispatchLaunch --> queued
102
- queued -->|on: task.started| startClearError
103
- startClearError --> startClearReason
104
- startClearReason --> running
105
- queued -->|on: review.started| reviewStartClearError
106
- reviewStartClearError --> reviewStartClearReason
107
- reviewStartClearReason --> running
108
- queued -->|on: review.approved| reviewApproveQueuedClearError
109
- reviewApproveQueuedClearError --> reviewApproveQueuedClearReason
110
- reviewApproveQueuedClearReason --> succeeded
111
- queued -->|on: review.changes_required| reviewChangesQueuedClearError
112
- reviewChangesQueuedClearError --> reviewChangesQueuedClearReason
113
- reviewChangesQueuedClearReason --> succeeded
114
- queued -->|on: review.blocked| blocked
115
- queued -->|on: block| blocked
116
- queued -->|on: fail| failed
117
- queued -->|on: effect.launchTask.failed| failed
118
- queued -->|on: watchdog.failed| failed
119
- queued -->|on: worker.delivery_failed| failed
120
- queued -->|on: worker.start_ack_failed| failed
121
- queued -->|on: planner.unavailable| plannerUnavailableMark
122
- plannerUnavailableMark --> failed
123
- queued -->|on: lease.expired| retryAvailableQueued
124
- retryAvailableQueued -->|true| leaseRetryQueuedClearError
125
- leaseRetryQueuedClearError --> leaseRetryQueuedClearLease
126
- leaseRetryQueuedClearLease --> leaseRetryQueuedClearExecution
127
- leaseRetryQueuedClearExecution --> queued
128
- retryAvailableQueued -->|false| leaseFailQueuedMark
129
- leaseFailQueuedMark --> leaseFailQueuedClearLease
130
- leaseFailQueuedClearLease --> leaseFailQueuedClearExecution
131
- leaseFailQueuedClearExecution --> failed
132
- queued -->|on: cancel| cancelled
133
-
134
- running -->|on: task.blocked| blocked
135
- running -->|on: review.approved| reviewApproveRunningClearError
136
- reviewApproveRunningClearError --> reviewApproveRunningClearReason
137
- reviewApproveRunningClearReason --> succeeded
138
- running -->|on: review.changes_required| reviewChangesRunningClearError
139
- reviewChangesRunningClearError --> reviewChangesRunningClearReason
140
- reviewChangesRunningClearReason --> succeeded
141
- running -->|on: review.blocked| blocked
142
- running -->|on: task.completed| completeClearError
143
- completeClearError --> completeClearReason
144
- completeClearReason --> succeeded
145
- running -->|on: task.failed| failed
146
- running -->|on: watchdog.failed| failed
147
- running -->|on: planner.failed| plannerRetryAvailable
148
- running -->|on: execution.orphaned| orphanRetryAvailable
149
- orphanRetryAvailable -->|true| orphanRetryClearError
150
- orphanRetryClearError --> orphanRetryClearLease
151
- orphanRetryClearLease --> orphanRetryClearExecution
152
- orphanRetryClearExecution --> queued
153
- orphanRetryAvailable -->|false| orphanFailMark
154
- orphanFailMark --> orphanFailClearLease
155
- orphanFailClearLease --> orphanFailClearExecution
156
- orphanFailClearExecution --> failed
157
- plannerRetryAvailable -->|true| plannerRetryClearError
158
- plannerRetryClearError --> plannerRetryClearLease
159
- plannerRetryClearLease --> plannerRetryClearExecution
160
- plannerRetryClearExecution --> queued
161
- plannerRetryAvailable -->|false| plannerFailClearLease
162
- plannerFailClearLease --> plannerFailClearExecution
163
- plannerFailClearExecution --> failed
164
- running -->|on: lease.expired| retryAvailableRunning
165
- retryAvailableRunning -->|true| leaseRetryRunningClearError
166
- leaseRetryRunningClearError --> leaseRetryRunningClearLease
167
- leaseRetryRunningClearLease --> leaseRetryRunningClearExecution
168
- leaseRetryRunningClearExecution --> queued
169
- retryAvailableRunning -->|false| leaseFailRunningMark
170
- leaseFailRunningMark --> leaseFailRunningClearLease
171
- leaseFailRunningClearLease --> leaseFailRunningClearExecution
172
- leaseFailRunningClearExecution --> failed
173
- running -->|on: task.cancelled| cancelled
174
- running -->|on: cancel| cancelled
175
-
176
- blocked -->|on: task.unblocked| unblocked
177
- blocked -->|on: cancel| cancelled
178
-
179
- unblocked -->|on: retry| unblockRetryClearError
180
- unblockRetryClearError --> unblockRetryClearReason
181
- unblockRetryClearReason --> queued
182
-
183
- failed -->|on: queue| depSat
184
- failed -->|on: retry| failedRetryClearError
185
- failedRetryClearError --> failedRetryClearReason
186
- failedRetryClearReason --> queued
187
- failed -->|on: task.started| recoverStart
188
- recoverStart -->|true| recoverStartClearError
189
- recoverStartClearError --> recoverStartClearReason
190
- recoverStartClearReason --> running
191
- failed -->|on: task.completed| recoverComplete
192
- recoverComplete -->|true| recoverCompleteClearError
193
- recoverCompleteClearError --> recoverCompleteClearReason
194
- recoverCompleteClearReason --> succeeded
195
- failed -->|on: task.blocked| recoverBlocked
196
- recoverBlocked -->|true| blocked
197
- failed -->|on: task.failed| recoverFailed
198
- recoverFailed -->|true| failed
199
- failed -->|on: task.cancelled| recoverCancelled
200
- recoverCancelled -->|true| cancelled
201
- failed -->|on: cancel| cancelled