Skip to content

Commit 2b0cc38

Browse files
docs: align skills and architecture with ADR 41 dispatch
Update architecture.md and agent skills for synchronous workflow_call: finding-agent-runs and retro-analysis trace runs on the enrolled-repo shim (not separate .fullsend dispatch runs). Restore code-implementation API contract checklist dropped during rebase. Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Barak Korren <bkorren@redhat.com>
1 parent 1e0dea8 commit 2b0cc38

3 files changed

Lines changed: 53 additions & 78 deletions

File tree

docs/architecture.md

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,11 @@ Infrastructure platform choice and configuration are specified in the adopting o
3939

4040
- Forge abstraction: all forge operations go through the `forge.Client` interface, keeping the rest of the codebase forge-agnostic ([ADR 0005](ADRs/0005-forge-abstraction-layer.md)).
4141
- Installation model: ordered layer stack (install forward, uninstall reverse, analyze for status reporting) with idempotent operations. Current stack: config-repo → workflows → secrets → inference → dispatch → enrollment ([ADR 0006](ADRs/0006-ordered-layer-model.md)).
42-
- Cross-repo dispatch: enrolled repos call `.fullsend` via `workflow_call`; a dispatch workflow mints OIDC tokens exchanged at a central token mint (GCP Cloud Function) for scoped GitHub App installation tokens per agent role. App PEM secrets are stored in Secret Manager, not the config repo ([ADR 0008](ADRs/0008-workflow-dispatch-for-cross-repo-dispatch.md)).
42+
- Cross-repo dispatch: enrolled repos call `.fullsend` via `workflow_call`; dispatch routes events to upstream reusable workflows via synchronous `workflow_call` jobs. Each reusable workflow mints OIDC tokens exchanged at a central token mint (GCP Cloud Function) for scoped GitHub App installation tokens per agent role. App PEM secrets are stored in Secret Manager, not the config repo ([ADR 0008](ADRs/0008-workflow-dispatch-for-cross-repo-dispatch.md), [ADR 0041](ADRs/0041-synchronous-workflow-call-event-dispatch.md)).
4343
- Shim workflow security: `pull_request_target` prevents PR authors from modifying the shim workflow. No long-lived secrets flow through the shim — OIDC tokens are issued by the GitHub runtime and scoped to the workflow run ([ADR 0009](ADRs/0009-pull-request-target-in-shim-workflows.md)).
4444
- Repo maintenance: a workflow in `.fullsend` (`.github/workflows/repo-maintenance.yml`) reconciles enrollment shims in target repos when `config.yaml` changes or on manual dispatch. The CLI's `EnrollmentLayer.Install()` dispatches this workflow via `workflow_dispatch` and monitors it for completion, then reports any enrollment PRs created in target repos.
4545
- Installer scaffold: the `WorkflowsLayer` deploys content from an embedded scaffold (`internal/scaffold/`), keeping deployable files as real files under version control rather than Go string constants.
46-
- Reusable workflows: agent workflows in `.fullsend` are thin callers (~40-70 lines) that delegate infrastructure logic to upstream reusable workflows (`fullsend-ai/fullsend/.github/workflows/reusable-*.yml`) via `workflow_call`. Infrastructure patches ship once upstream and propagate to all orgs without re-install ([ADR 0031](ADRs/0031-reusable-workflows-for-action-installed-distribution.md)).
47-
- Event-driven stage dispatch: eliminate `workflow_dispatch` + `gh workflow run` fan-out from `dispatch.yml` in favor of synchronous `workflow_call` so the dispatched run stays linked to the caller ([ADR 0041](ADRs/0041-synchronous-workflow-call-event-dispatch.md)).
46+
- Reusable workflows: `dispatch.yml` in `.fullsend` calls upstream reusable workflows (`fullsend-ai/fullsend/.github/workflows/reusable-*.yml`) directly via `workflow_call` jobs (no per-stage thin callers). Infrastructure patches ship once upstream and propagate to all orgs without re-install ([ADR 0031](ADRs/0031-reusable-workflows-for-action-installed-distribution.md), [ADR 0041](ADRs/0041-synchronous-workflow-call-event-dispatch.md)).
4847

4948
**Open questions:**
5049

@@ -131,10 +130,6 @@ The mechanism that assigns work to agents and prevents conflicts. Responsible fo
131130

132131
The existing design principle is that [the repo is the coordinator](problems/agent-architecture.md#interaction-model-the-repo-as-coordinator) — branch protection, CODEOWNERS, status checks, and GitHub events provide coordination without a central orchestrator. The agent dispatch and coordination layer may be nothing more than the glue that connects GitHub webhooks to agent infrastructure. Or it may need to be more.
133132

134-
**Decided:**
135-
136-
- Event-driven stage dispatch runs synchronously via `workflow_call` to preserve run correlation in the GitHub Actions UI (see [ADR 0041](ADRs/0041-synchronous-workflow-call-event-dispatch.md)).
137-
138133
**Open questions:**
139134

140135
- Is GitHub's event system sufficient, or do we need additional coordination logic (e.g. to prevent two code agents from picking up the same issue)?
@@ -180,7 +175,6 @@ Observability is a cross-cutting concern that touches every other component. Eac
180175
**Decided:**
181176

182177
- JSONL reasoning trace exposure: raw JSONL conversation transcripts are extracted from sandboxes and stored with owner-scoped access. Credential scanning acts as an invariant check on [ADR 0017](ADRs/0017-credential-isolation-for-sandboxed-agents.md)'s isolation model. Agents handling data from protected sources beyond the target repo can opt in to JSONL suppression via configuration ([ADR 0021](ADRs/0021-jsonl-reasoning-trace-exposure.md)).
183-
- Event-driven stage dispatch remains traceable end-to-end in the GitHub Actions UI by using synchronous `workflow_call` dispatch (see [ADR 0041](ADRs/0041-synchronous-workflow-call-event-dispatch.md)).
184178

185179
**Open questions:**
186180

@@ -518,14 +512,13 @@ GitHub event ──► SHIM WORKFLOW (fullsend.yml in enrolled repo)
518512
╔═══════════════════════════════════════════════════════════════╗
519513
║ DISPATCH WORKFLOW (.fullsend repo, dispatch.yml) ║
520514
║ ║
521-
║ Mints OIDC token → Cloud Function (token mint) → scoped ║
522-
║ GitHub App installation token per agent role. ║
523-
║ Dispatches per-role agent workflows (code.yml, triage.yml). ║
515+
║ Routes to stage; synchronous workflow_call to upstream ║
516+
║ reusable-{stage}.yml (or prioritize.yml in .fullsend). ║
524517
╚═══════════════════════════════════════════════════════════════╝
525518
526519
527520
╔═══════════════════════════════════════════════════════════════╗
528-
║ AGENT WORKFLOW (.fullsend repo, e.g. code.yml)
521+
║ AGENT WORKFLOW (fullsend-ai/fullsend reusable-*.yml) ║
529522
║ ║
530523
║ Validates source repo is enrolled in config.yaml. ║
531524
║ Uses scoped GitHub App tokens: ║
@@ -607,7 +600,7 @@ GitHub event ──► SHIM WORKFLOW (fullsend.yml in enrolled repo)
607600

608601
| Abstract layer | MVP technology | ADR |
609602
|---|---|---|
610-
| Dispatcher | Shim workflow (`fullsend.yml`) in enrolled repo → `workflow_call` to `.fullsend/dispatch.yml`OIDC mint → per-role agent workflows (thin callers → upstream reusable workflows) | [ADR 0008](ADRs/0008-workflow-dispatch-for-cross-repo-dispatch.md), [ADR 0031](ADRs/0031-reusable-workflows-for-action-installed-distribution.md) |
603+
| Dispatcher | Shim workflow (`fullsend.yml`) in enrolled repo → `workflow_call` to `.fullsend/dispatch.yml`synchronous `workflow_call` to upstream reusable workflows | [ADR 0008](ADRs/0008-workflow-dispatch-for-cross-repo-dispatch.md), [ADR 0031](ADRs/0031-reusable-workflows-for-action-installed-distribution.md), [ADR 0041](ADRs/0041-synchronous-workflow-call-event-dispatch.md) |
611604
| Agent runner | GitHub Actions job → `fullsend run` CLI (via `fullsend-ai/fullsend@v0` composite action) | |
612605
| Harness store | YAML files in `.fullsend/harness/` (e.g. `code.yaml`, `triage.yaml`) | |
613606
| Sandbox | OpenShell with per-agent L7 network policies (endpoint + binary restrictions) | |

internal/scaffold/fullsend-repo/skills/finding-agent-runs/SKILL.md

Lines changed: 24 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ Given an issue or PR, find the fullsend agent workflow runs using `gh` CLI.
1313
## Setup
1414

1515
```bash
16-
ORG=$(echo "${REPO_FULL_NAME:-$(gh repo view --json owner -q .owner.login)}" | cut -d/ -f1)
17-
DISPATCH_REPO="${ORG}/.fullsend"
16+
SOURCE_REPO="${REPO_FULL_NAME:-$(gh repo view --json nameWithOwner -q .nameWithOwner)}"
17+
ORG=$(echo "${SOURCE_REPO}" | cut -d/ -f1)
18+
CONFIG_REPO="${ORG}/.fullsend"
1819
```
1920

20-
The shim workflow (`fullsend.yaml`) runs in the source repo on `main`. It
21-
dispatches to `${DISPATCH_REPO}` which runs the agent workflows
22-
(`triage.yml`, `code.yml`, `review.yml`, `retro.yml`).
21+
Per-org installs use synchronous `workflow_call`: the enrolled-repo shim
22+
(`fullsend.yaml`) calls `${CONFIG_REPO}` `dispatch.yml`, which runs agent
23+
stages as jobs in the **same** Actions run on `SOURCE_REPO`. There are no
24+
separate `dispatch.yml` runs in `.fullsend` to look up.
2325

2426
## Issue → Agent Runs
2527

@@ -28,15 +30,15 @@ dispatches to `${DISPATCH_REPO}` which runs the agent workflows
2830
Triage dispatches from `issue_comment` events (the `/fs-triage` command):
2931

3032
```bash
31-
gh run list --workflow=fullsend.yaml \
33+
gh run list --repo "${SOURCE_REPO}" --workflow=fullsend.yaml \
3234
--json databaseId,status,conclusion,event,createdAt \
3335
-q '.[] | select(.event == "issue_comment")'
3436
```
3537

36-
Match by timestamp against the `/fs-triage` comment (`gh issue view <N> --json comments`), then confirm `dispatch-triage` succeeded:
38+
Match by timestamp against the `/fs-triage` comment (`gh issue view <N> --json comments`), then confirm the **Triage** stage job succeeded:
3739

3840
```bash
39-
gh run view <RUN_ID> --json jobs \
41+
gh run view <RUN_ID> --repo "${SOURCE_REPO}" --json jobs \
4042
-q '.jobs[] | "\(.name) \(.status)/\(.conclusion)"'
4143
```
4244

@@ -45,47 +47,35 @@ gh run view <RUN_ID> --json jobs \
4547
Code dispatches from `issues` events when `ready-to-code` is applied:
4648

4749
```bash
48-
gh run list --workflow=fullsend.yaml \
50+
gh run list --repo "${SOURCE_REPO}" --workflow=fullsend.yaml \
4951
--json databaseId,status,conclusion,event,createdAt \
5052
-q '.[] | select(.event == "issues")'
5153
```
5254

53-
Confirm `dispatch-code completed/success` in the jobs list.
54-
55-
### Find the actual agent run
56-
57-
Match by timestamp in the dispatch repo (runs start within seconds):
58-
59-
```bash
60-
gh run list --repo "${DISPATCH_REPO}" --workflow=triage.yml --limit 5 \
61-
--json databaseId,status,conclusion,createdAt
62-
63-
gh run list --repo "${DISPATCH_REPO}" --workflow=code.yml --limit 5 \
64-
--json databaseId,status,conclusion,createdAt
65-
```
55+
Confirm the **Code** job completed successfully in that run's job list.
6656

6757
## PR → Agent Runs
6858

6959
### Code agent run
7060

7161
The PR branch follows `agent/{issue}-{slug}`. Extract the issue number and
72-
use the issue recipe above to find the code dispatch.
62+
use the issue recipe above to find the code dispatch run on `SOURCE_REPO`.
7363

7464
### Review dispatch
7565

7666
Review dispatches from `pull_request_target` events. Match by `headBranch`:
7767

7868
```bash
79-
gh run list --workflow=fullsend.yaml \
69+
gh run list --repo "${SOURCE_REPO}" --workflow=fullsend.yaml \
8070
--json databaseId,status,conclusion,event,headBranch,createdAt \
8171
-q '.[] | select(.event == "pull_request_target")'
8272
```
8373

84-
Confirm `dispatch-review completed/success`, then find the run:
74+
Confirm the **Review** job completed successfully:
8575

8676
```bash
87-
gh run list --repo "${DISPATCH_REPO}" --workflow=review.yml --limit 5 \
88-
--json databaseId,status,conclusion,createdAt
77+
gh run view <RUN_ID> --repo "${SOURCE_REPO}" --json jobs \
78+
-q '.jobs[] | "\(.name) \(.status)/\(.conclusion)"'
8979
```
9080

9181
### Retro dispatch
@@ -94,29 +84,26 @@ Retro dispatches from `pull_request_target` (on PR close) and from
9484
`issue_comment` events (the `/fs-retro` command):
9585

9686
```bash
97-
gh run list --workflow=fullsend.yaml \
87+
gh run list --repo "${SOURCE_REPO}" --workflow=fullsend.yaml \
9888
--json databaseId,status,conclusion,event,createdAt \
9989
-q '.[] | select(.event == "pull_request_target" or .event == "issue_comment")'
10090
```
10191

102-
Find the actual retro agent run:
103-
104-
```bash
105-
gh run list --repo "${DISPATCH_REPO}" --workflow=retro.yml --limit 5 \
106-
--json databaseId,status,conclusion,createdAt
107-
```
92+
Confirm the **Retro** job completed successfully in the same run.
10893

10994
## Reference
11095

11196
### Logs and artifacts
11297

98+
Use the shim run ID on `SOURCE_REPO` (not `${CONFIG_REPO}`):
99+
113100
```bash
114101
# Search logs for errors
115-
gh run view <RUN_ID> --repo "${DISPATCH_REPO}" --log 2>&1 \
102+
gh run view <RUN_ID> --repo "${SOURCE_REPO}" --log 2>&1 \
116103
| grep -i "error\|fail\|exit code"
117104

118-
# Download session artifact
119-
gh run download <RUN_ID> --repo "${DISPATCH_REPO}"
105+
# Download session artifact (uploaded by the stage job in this run)
106+
gh run download <RUN_ID> --repo "${SOURCE_REPO}"
120107
```
121108

122109
### Common failure signatures

internal/scaffold/fullsend-repo/skills/retro-analysis/SKILL.md

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,67 +15,62 @@ Given the originating PR or issue, reconstruct what agents ran and in what order
1515
### Setup
1616

1717
```bash
18-
ORG=$(echo "$REPO_FULL_NAME" | cut -d/ -f1)
19-
DISPATCH_REPO="${ORG}/.fullsend"
18+
SOURCE_REPO="${REPO_FULL_NAME:-$(gh repo view --json nameWithOwner -q .nameWithOwner)}"
19+
ORG=$(echo "${SOURCE_REPO}" | cut -d/ -f1)
20+
CONFIG_REPO="${ORG}/.fullsend"
2021
```
2122

23+
Per-org installs run shim → `dispatch.yml` → stage jobs synchronously in one
24+
Actions run on `SOURCE_REPO`. Stage names in the job list include **Route**,
25+
**Triage**, **Code**, **Review**, **Fix**, **Retro**, and **Prioritize**.
26+
2227
### From an issue
2328

24-
1. Find triage dispatches (triggered by `/fs-triage` command or `needs-info` label responses):
29+
1. Find shim runs on the source repo (triage/code triggered by issue events or `/fs-triage`):
2530

2631
```bash
27-
gh run list --repo "$REPO_FULL_NAME" --workflow=fullsend.yaml \
32+
gh run list --repo "$SOURCE_REPO" --workflow=fullsend.yaml \
2833
--json databaseId,status,conclusion,event,createdAt \
2934
-q '.[] | select(.event == "issue_comment" or .event == "issues")'
3035
```
3136

32-
2. Find the corresponding agent runs in the dispatch repo:
33-
34-
```bash
35-
gh run list --repo "$DISPATCH_REPO" --workflow=triage.yml --limit 10 \
36-
--json databaseId,status,conclusion,createdAt
37-
```
38-
39-
3. If the issue reached `ready-to-code`, find code dispatches:
37+
2. Inspect stage jobs inside that run (not separate runs in `.fullsend`):
4038

4139
```bash
42-
gh run list --repo "$DISPATCH_REPO" --workflow=code.yml --limit 10 \
43-
--json databaseId,status,conclusion,createdAt
40+
gh run view <RUN_ID> --repo "$SOURCE_REPO" --json jobs \
41+
-q '.jobs[] | "\(.name) \(.status)/\(.conclusion) \(.startedAt)"'
4442
```
4543

4644
### From a PR
4745

48-
1. The PR branch follows `agent/{issue}-{slug}`. Extract the issue number to trace the full history.
46+
1. The PR branch follows `agent/{issue}-{slug}`. Extract the issue number to trace the full history on `SOURCE_REPO`.
4947

50-
2. Find review dispatches:
48+
2. Find shim runs for review/fix/retro (match by `headBranch` or timestamp):
5149

5250
```bash
53-
gh run list --repo "$DISPATCH_REPO" --workflow=review.yml --limit 10 \
54-
--json databaseId,status,conclusion,createdAt
55-
```
56-
57-
3. Find fix dispatches (if review requested changes):
58-
59-
```bash
60-
gh run list --repo "$DISPATCH_REPO" --workflow=fix.yml --limit 10 \
61-
--json databaseId,status,conclusion,createdAt
51+
gh run list --repo "$SOURCE_REPO" --workflow=fullsend.yaml \
52+
--json databaseId,status,conclusion,event,headBranch,createdAt \
53+
-q '.[] | select(.event == "pull_request_target" or .event == "issue_comment")'
6254
```
6355

6456
### Reading agent logs and artifacts
6557

6658
```bash
6759
# View job outcomes
68-
gh run view <RUN_ID> --repo "$DISPATCH_REPO" --json jobs \
60+
gh run view <RUN_ID> --repo "$SOURCE_REPO" --json jobs \
6961
-q '.jobs[] | "\(.name) \(.status)/\(.conclusion)"'
7062

7163
# Search logs for errors
72-
gh run view <RUN_ID> --repo "$DISPATCH_REPO" --log 2>&1 \
64+
gh run view <RUN_ID> --repo "$SOURCE_REPO" --log 2>&1 \
7365
| grep -i "error\|fail\|exit code"
7466

7567
# Download session artifacts (JSONL traces)
76-
gh run download <RUN_ID> --repo "$DISPATCH_REPO"
68+
gh run download <RUN_ID> --repo "$SOURCE_REPO"
7769
```
7870

71+
Use `${CONFIG_REPO}` only when reading harness/agent definitions under
72+
`.fullsend` (files), not for workflow run IDs.
73+
7974
## Exploration strategy
8075

8176
You have a large amount of context to cover. Use subagents to avoid overflowing your main context window.

0 commit comments

Comments
 (0)