Skip to content

Commit b11626a

Browse files
T-GroCopilot
andcommitted
Add cross-workflow mermaid arrows, move Handover Map to top, fix 4 fact gaps
Reviewer cycle 4 surfaced a structural insight (Gemini): mermaid stateDiagram-v2 direction LR does NOT auto-draw edges across nested state{} composites. The 'grouping = visible cross-dependencies' promise from cycle 3 was unfulfilled — the workflows sat side-by- side as disconnected boxes. Doc: - Draw explicit cross-workflow arrows where the handover endpoints are both in the same diagram group: * Group A2: LPM_DispatchFlakeFix -> LFF_Validate (sync dispatch- workflow) * Group A3: RA_T2_CreatePR -> RPS_ListPRs (async via label AI-Issue-Regression-PR, picked up in RPS's next scheduled run) - Move Handover Map from the bottom (after all diagrams) to immediately AFTER Overview, BEFORE the first group diagram. Reader now sees cross-workflow signals BEFORE the diagrams that contain them. Three reviewers flagged the prior placement. - Fix add_to_project Overview trigger row: clarify pull_request_target fires but all jobs are gated off (GPT flagged the overview/diagram contradiction). - Add 'messages safe-output' glossary entry; table row max set to n/a (Sonnet flagged undefined). - Resolve AI-Auto-Resolve-* 'external' ambiguity: humans (manual, opt-in) per labelops-pr-maintenance.md description. - Add 'Affects-* family' glossary entry with all 7 area names. Generator: - Rule 48 added: cross-workflow arrows are MANDATORY when the workflows are in the same Mermaid block. stateDiagram-v2 does not auto-draw cross-composite edges; must declare explicitly. Sync dispatch and async-via-label both modeled as labeled --> with cross-workflow tag in the edge label. - Rule 49 added: Handover Map placement MUST be after Overview and before first group diagram. Bottom placement hides the dependency map from the reader who needs it most. Metrics: 560 -> 566 lines (+6, within +20 budget); 78 -> 78 pipe rows (unchanged); 0 long edges; 6/6 mermaid blocks render. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent bcc39f2 commit b11626a

2 files changed

Lines changed: 31 additions & 17 deletions

File tree

.github/docs/state-machine.md

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
- **`has_conflicts`** (labelops-pr-maintenance) — PR has merge conflicts.
2424
- **`ci_blocked`** (labelops-pr-maintenance) — CI hasn't started yet (queued or blocked by other workflows).
2525
- **`12h stuck guard`** (labelops-pr-maintenance) — Skip the PR if LabelOps already committed within the last 12 hours AND checks are still red. Prevents retry storms.
26+
- **`messages` safe-output** — gh-aw runtime mechanism for posting lifecycle status updates (run-started, run-success, run-failure) and a per-run footer to a user-visible target (issue/PR comment). Templates support placeholders like `{workflow_name}`, `{run_url}`, `{event_type}`. Not rate-limited via `max:` — it's a per-run signaling channel, not a content output.
2627
- **milestone 29 / `2026-05-12` cutoff** — Repo-specific operational constants: milestone 29 is applied by `add_to_project.yml` (internal milestone number; title unconfirmed from source); the `2026-05-12` cutoff in `labelops-pr-security-scan` is the date the scanner went live — PRs opened before that date are skipped to avoid re-scanning historical PRs.
28+
- **`⚠️ Affects-*` family** (labelops-pr-security-scan) — agent-applied warning labels indicating which repository area a PR touches: `Build-Infra`, `Compiler-Output`, `Bootstrap`, `Restore`, `Design-Time`, `Test-Tooling`, `Agent-Config`. Drive reviewer attention to PRs touching sensitive code paths.
2729

2830
## Legend
2931

@@ -49,7 +51,7 @@
4951
| `labelops-pr-security-scan.md` | schedule 1h, dispatch | none | `noop`, `add-labels`, `add-comment` |
5052
| `regression-pr-shepherd.md` | schedule 4h, dispatch | none | `noop`, `add-comment`, `push-to-pull-request-branch`, `remove-labels` |
5153
| `repo-assist.md` | schedule 12h, dispatch, slash_command `/repo-assist`, reaction `eyes` | none | `noop`, `messages`, `add-comment`, `create-pull-request`, `push-to-pull-request-branch`, `create-issue`, `update-issue`, `add-labels`, `remove-labels` |
52-
| `add_to_project.yml` | issues (opened, transferred), pull_request_target (opened, main) || add label `Needs-Triage`, set milestone 29 |
54+
| `add_to_project.yml` | issues (opened, transferred); pull_request_target (opened, main — gated off) || add label `Needs-Triage`, set milestone 29 |
5355
| `backport.yml` | issue_comment (created), schedule (cron `0 13 * * *`) || delegates to `dotnet/arcade` backport-base.yml |
5456
| `branch-merge.yml` | push (main, release/\*) || delegates to `dotnet/arcade` inter-branch-merge-base.yml |
5557
| `check_release_notes.yml` | pull_request_target (opened/sync/reopened/labeled/unlabeled; main, release/\*) || create or update PR comment |
@@ -60,6 +62,22 @@
6062

6163
---
6264

65+
## Handover Map
66+
67+
> **Cross-workflow signals at a glance.** Workflows talk to each other via labels, dispatch, indirect handoffs, and state-store branches. This map shows every cross-workflow signal documented below.
68+
69+
| Source Workflow | Signal | Target | Mechanism | Notes |
70+
|---|---|---|---|---|
71+
| `labelops-pr-maintenance.md` | Proven flake (flaky-test-detector ≥3 distinct unrelated PRs; test not introduced by current PR) | `labelops-flake-fix.md` | `dispatch-workflow: workflows: [labelops-flake-fix]` | Passes inputs; max 3/run |
72+
| `aw-auto-update.md` | CHANGED_FILES non-empty after `gh aw upgrade + compile` | Copilot Coding Agent (CCA) | `create-agent-session` (base: main, max: 1) | CCA writes `.lock.yml` files using `COPILOT_GITHUB_TOKEN` |
73+
| `agentic-state-machine.md` | State-machine doc changed | PR reviewer (human) | `create-pull-request` (labels: automation, NO_RELEASE_NOTES; allowed-files: .github/docs/**) | Writes `.github/docs/state-machine.md` |
74+
| `repo-assist.md` | Regression test PR created (Task 2) | `regression-pr-shepherd.md` | Indirect via label `AI-Issue-Regression-PR` on PR | Shepherd picks up in subsequent scheduled run |
75+
| `commands.yml` | `/run <cmd>` approved PR comment | PR branch | `git push origin HEAD:branch` (direct write) | Requires commenter admin/write access |
76+
| `backport.yml` | `/backport to <branch>` PR comment | `dotnet/arcade` backport-base.yml | `uses: dotnet/arcade/.github/workflows/backport-base.yml@main` | Reusable workflow; schedule trigger only cleans old runs |
77+
| `branch-merge.yml` | Push to `release/*` or `main` | `dotnet/arcade` inter-branch-merge-base.yml | `uses: dotnet/arcade/.github/workflows/inter-branch-merge-base.yml@main` | Config: `.config/service-branch-merge.json` |
78+
79+
---
80+
6381
## Group A1 — Agentic Infrastructure
6482

6583
```mermaid
@@ -235,6 +253,7 @@ stateDiagram-v2
235253
LPSS_MorePRs --> LPSS_WriteMemory : ⚙️ no
236254
LPSS_WriteMemory --> [*] : ⚙️ save state.json to safety/scanned-PRs branch
237255
}
256+
LPM_DispatchFlakeFix --> LFF_Validate : 🤖 dispatch-workflow (cross-workflow, passes inputs)
238257
```
239258

240259
### Safe-outputs configuration
@@ -330,6 +349,7 @@ stateDiagram-v2
330349
RA_TaskFinal --> RA_WriteMemory : ⚙️ Task FINAL: update Monthly Activity Summary issue (update-issue)
331350
RA_WriteMemory --> [*] : 🤖 write state.json to memory/repo-assist branch, messages safe-output
332351
}
352+
RA_T2_CreatePR --> RPS_ListPRs : 🤖 async via label AI-Issue-Regression-PR (picked up in next RPS run)
333353
```
334354

335355
> **`repo-assist` Task 2 — Step A skip conditions** (any of these → no PR):
@@ -349,7 +369,7 @@ stateDiagram-v2
349369
| `regression-pr-shepherd.md` | `add-comment` | 5 | hide-older-comments |
350370
| `regression-pr-shepherd.md` | `push-to-pull-request-branch` | 10 | title `Add regression test: `; labels `AI-Issue-Regression-PR`; allowed-files `tests/**`, `vsintegration/tests/**`; protected-files fallback-to-issue |
351371
| `regression-pr-shepherd.md` | `remove-labels` | 5 | allowed `AI-thinks-issue-fixed` |
352-
| `repo-assist.md` | `messages` | | footer, run-started, run-success, run-failure |
372+
| `repo-assist.md` | `messages` | n/a | lifecycle signaling — see Glossary |
353373
| `repo-assist.md` | `add-comment` | 10 | hide-older-comments |
354374
| `repo-assist.md` | `create-pull-request` | 10 | title `Add regression test: `; labels `NO_RELEASE_NOTES, AI-Issue-Regression-PR`; reviewers abonie, T-Gro; auto-merge; allowed-files `tests/**`, `vsintegration/tests/**` |
355375
| `repo-assist.md` | `push-to-pull-request-branch` | 4 | title `[Repo Assist] `; protected-files fallback-to-issue |
@@ -538,23 +558,9 @@ All labels in one place — who adds, removes, or reads each. **Cross-workflow f
538558
| `⚠️ Suspicious-Prompting`, `⚠️ Scope-Review-Needed` | agent-add | LPSS ||| review-trigger flags |
539559
| `AI-thinks-issue-fixed` | agent-add + agent-remove | RA | RPS, RA || **bidirectional** — RA proposes, RPS/RA retract |
540560
| `AI-thinks-windows-only` | agent-add + agent-remove | RA | RA || RA self-corrects in Task 3 |
541-
| `AI-Auto-Resolve-CI`, `AI-Auto-Resolve-Conflicts` | filter (read-only) | — (external) || LPM (`gh pr list --search label:...`) | **selection signal into LPM** |
561+
| `AI-Auto-Resolve-CI`, `AI-Auto-Resolve-Conflicts` | filter (read-only) | humans (manual, opt-in) || LPM (`gh pr list --search label:...`) | **selection signal into LPM** |
542562
| `Needs-Triage` | imperative | ATP (`apply-label` job, github-script) ||| classic workflow, not gh-aw |
543563

544564
---
545565

546-
## Handover Map
547-
548-
| Source Workflow | Signal | Target | Mechanism | Notes |
549-
|---|---|---|---|---|
550-
| `labelops-pr-maintenance.md` | Proven flake (flaky-test-detector ≥3 distinct unrelated PRs; test not introduced by current PR) | `labelops-flake-fix.md` | `dispatch-workflow: workflows: [labelops-flake-fix]` | Passes inputs; max 3/run |
551-
| `aw-auto-update.md` | CHANGED_FILES non-empty after `gh aw upgrade + compile` | Copilot Coding Agent (CCA) | `create-agent-session` (base: main, max: 1) | CCA writes `.lock.yml` files using `COPILOT_GITHUB_TOKEN` |
552-
| `agentic-state-machine.md` | State-machine doc changed | PR reviewer (human) | `create-pull-request` (labels: automation, NO_RELEASE_NOTES; allowed-files: .github/docs/**) | Writes `.github/docs/state-machine.md` |
553-
| `repo-assist.md` | Regression test PR created (Task 2) | `regression-pr-shepherd.md` | Indirect via label `AI-Issue-Regression-PR` on PR | Shepherd picks up in subsequent scheduled run |
554-
| `commands.yml` | `/run <cmd>` approved PR comment | PR branch | `git push origin HEAD:branch` (direct write) | Requires commenter admin/write access |
555-
| `backport.yml` | `/backport to <branch>` PR comment | `dotnet/arcade` backport-base.yml | `uses: dotnet/arcade/.github/workflows/backport-base.yml@main` | Reusable workflow; schedule trigger only cleans old runs |
556-
| `branch-merge.yml` | Push to `release/*` or `main` | `dotnet/arcade` inter-branch-merge-base.yml | `uses: dotnet/arcade/.github/workflows/inter-branch-merge-base.yml@main` | Config: `.config/service-branch-merge.json` |
557-
558-
---
559-
560566
<!-- generator-version: d4fe5640de7eb85c source-shas: d4fe5640,da8c5e34,7dca5b8f,59ba52fc,7dd4063d,18a65fe1,3775b51d,98d92f32,5e9a1344,ec5fa486,359def31,49b2989b,36b2b857,acf12bdf,b5c04ea8 sources: agentic-state-machine.md:d4fe5640,aw-auto-update.md:da8c5e34,labelops-flake-fix.md:7dca5b8f,labelops-pr-maintenance.md:59ba52fc,labelops-pr-security-scan.md:7dd4063d,regression-pr-shepherd.md:18a65fe1,repo-assist.md:3775b51d,add_to_project.yml:98d92f32,backport.yml:5e9a1344,branch-merge.yml:ec5fa486,check_release_notes.yml:359def31,commands.yml:49b2989b,copilot-setup-steps.yml:36b2b857,repository_lockdown_check.yml:acf12bdf,skill-validation.yml:b5c04ea8 -->

.github/workflows/agentic-state-machine.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,14 @@ You are a workflow-automation documentor. You read all workflow files in `.githu
314314
315315
47. **Mermaid grouping — workflows with cross-dependencies STAY in the same block.** Reviewers may complain that multi-workflow Mermaid blocks are "too dense" and propose one-workflow-per-block. **Resist this for any group whose workflows have cross-workflow signals** — shared labels (producer/consumer), shared state-store branches, dispatch-workflow handovers, indirect-via-label handoffs. Splitting these into separate diagrams hides the dependency graph: the reader sees independent islands and has to reconstruct the cross-edges by mental cross-reference with the Labels table and Handover Map. Keep them grouped so the visual proximity itself communicates "these interact." Acceptable to split groups whose workflows are truly independent (e.g., Group D — `branch-merge` / `skill-validation` / `copilot-setup-steps` share nothing). Per-workflow splits that erase visible cross-edges = MAJOR.
316316
317+
48. **Cross-workflow arrows are MANDATORY when grouped.** Rule 47 keeps cross-dependent workflows in the same Mermaid block. Rule 48 makes those cross-dependencies *visually* explicit: `stateDiagram-v2 direction LR` does NOT auto-draw edges across nested `state X { ... }` composites — it just renders side-by-side boxes. The reader sees no connection unless you declare it. For every cross-workflow handover documented in the Handover Map between workflows in the same diagram group, draw an EXPLICIT mermaid edge between the relevant inner states. Examples:
318+
- **Sync dispatch** (workflow A dispatches workflow B in the same run): `LPM_DispatchFlakeFix --> LFF_Validate : 🤖 dispatch-workflow (cross-workflow, passes inputs)`
319+
- **Async via label** (workflow A produces a label; workflow B picks it up in its next scheduled run): `RA_T2_CreatePR --> RPS_ListPRs : 🤖 async via label AI-Issue-Regression-PR (picked up in next RPS run)`
320+
- **State-store handover** (workflow A writes to a memory branch read by workflow B in same run): same shape; label the transition with the branch name.
321+
These declarations go in the outer `stateDiagram-v2` scope, AFTER both composites close (`}`) but BEFORE the diagram's closing ```` ``` ````. `stateDiagram-v2` supports bare state-name references across composites IF the inner state names are unique (prefix convention like `LPM_*`, `LFF_*` enforces this). Missing cross-edge for a documented handover whose endpoints are both in the same group = MAJOR — defeats the entire purpose of the grouping.
322+
323+
49. **Handover Map placement at TOP, not bottom.** Position the Handover Map immediately AFTER the Overview table and BEFORE the first group diagram. The map answers "how do these workflows interact?" — the reader needs that context BEFORE wading into individual control-flow diagrams. Burying the map at the bottom (the original "summary tables follow" pattern) forces the reader to discover cross-dependencies bottom-up: parse 6 diagrams in isolation, hit the map last, then mentally retrofit the connections. Three independent reviewers confirmed this. Handover Map placed AFTER any group diagram = MAJOR.
324+
317325
318326
</rules>
319327

0 commit comments

Comments
 (0)