Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/reusable-dispatch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,9 @@ jobs:
STAGE="triage"
fi
elif [[ "${EVENT_ACTION}" == "labeled" ]]; then
if [[ "${TRIGGERING_LABEL}" == "ready-to-code" ]]; then
if [[ "${TRIGGERING_LABEL}" == "ready-for-triage" ]]; then
STAGE="triage"
elif [[ "${TRIGGERING_LABEL}" == "ready-to-code" ]]; then
STAGE="code"
elif [[ "${TRIGGERING_LABEL}" == "ready-for-review" ]]; then
if [[ "${ISSUE_IS_PR}" == "true" ]]; then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,10 @@ inference compute on them automatically.

Agent-to-agent handoffs use label-based triggers, not slash commands.
When one agent completes a stage, its post-script applies a label
(e.g., `ready-to-code`, `ready-for-review`) which triggers the next
stage via the `issues.labeled` dispatch path. Label application requires
write access — an implicit authorization gate — so no explicit
`is_authorized` check is needed on that path.
(e.g., `ready-for-triage`, `ready-to-code`, `ready-for-review`) which
triggers the next stage via the `issues.labeled` dispatch path. Label
application requires write access — an implicit authorization gate — so
no explicit `is_authorized` check is needed on that path.

The `COMMENT_USER_TYPE != "Bot"` check in the slash command guard means
bot accounts cannot invoke slash commands at all (the condition
Expand Down
4 changes: 3 additions & 1 deletion docs/agents/retro.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ The retro agent also runs automatically when a PR is closed (merged or not).

## Control labels

The retro agent does not apply or consume control labels.
| Label | Meaning |
|-------|---------|
| `ready-for-triage` | Applied by the post-script to proposal issues so they enter the [triage](triage.md) pipeline automatically. |

## Configuration and extension

Expand Down
8 changes: 5 additions & 3 deletions docs/agents/triage.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ The `/fs-triage` command does not accept arguments — it re-evaluates the issue
using current content, comments, and any prior triage analysis.

Triage also runs automatically when a new issue is opened or edited by a
repository owner, member, or collaborator, and when someone comments on an
issue labeled `needs-info` (to re-evaluate after the reporter provides
clarification).
repository owner, member, or collaborator, when the `ready-for-triage`
label is applied to an issue (used by the [retro agent](retro.md) to
route proposal issues into the triage pipeline), and when someone
comments on an issue labeled `needs-info` (to re-evaluate after the
reporter provides clarification).

## Control labels

Expand Down
2 changes: 1 addition & 1 deletion docs/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ See [architecture.md](architecture.md) and [agent-architecture.md](problems/agen

### Label State Machine

The set of valid label transitions on issues and PRs that encode workflow state. Labels like `ready-to-code` drive agent dispatch; others such as `ready-for-merge` and `requires-manual-review` encode review outcomes. In per-repo installs, `ready-for-review` on a PR also triggers review; applying it to a standalone issue does not. Per-org installs still accept legacy issue-side review triggers pending a follow-up. The label state machine guard validates that transitions are legal and enforces mutual exclusion — for example, starting a triage run clears downstream labels so stale state does not carry forward.
The set of valid label transitions on issues and PRs that encode workflow state. Labels like `ready-for-triage`, `ready-to-code`, and `ready-for-review` drive agent dispatch; others such as `ready-for-merge` and `requires-manual-review` encode review outcomes. In per-repo installs, `ready-for-review` on a PR also triggers review; applying it to a standalone issue does not. Per-org installs still accept legacy issue-side review triggers pending a follow-up. The label state machine guard validates that transitions are legal and enforces mutual exclusion — for example, starting a triage run clears downstream labels so stale state does not carry forward.
See [ADR 0002](ADRs/0002-initial-fullsend-design.md) building block 3.

## M
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
# lint-workflow-size: max-lines=470
# lint-workflow-size: max-lines=475
# Dispatcher workflow that routes events to agent workflows based on stage.
# Routing logic determines the stage from event context — the shim only
# forwards the raw event. Adding a new stage requires only a case branch
Expand Down Expand Up @@ -185,7 +185,9 @@ jobs:
STAGE="triage"
fi
elif [[ "${EVENT_ACTION}" == "labeled" ]]; then
if [[ "${TRIGGERING_LABEL}" == "ready-to-code" ]]; then
if [[ "${TRIGGERING_LABEL}" == "ready-for-triage" ]]; then
STAGE="triage"
elif [[ "${TRIGGERING_LABEL}" == "ready-to-code" ]]; then
STAGE="code"
elif [[ "${TRIGGERING_LABEL}" == "ready-for-review" ]]; then
if [[ "${ISSUE_HAS_PR}" == "true" ]]; then
Expand Down
11 changes: 11 additions & 0 deletions internal/scaffold/fullsend-repo/scripts/post-code.sh
Original file line number Diff line number Diff line change
Expand Up @@ -456,3 +456,14 @@ rm -f "${PR_CREATE_STDERR}"

echo "PR created: ${PR_URL}"
echo "pr_url=${PR_URL}" >> "${GITHUB_OUTPUT:-/dev/null}"

# Apply ready-for-review label so the review agent is dispatched via the
# issues.labeled path. The pull_request_target.opened event requires the PR
# author to pass is_event_actor_authorized, which fails for bot accounts
# (GitHub App bots have no collaborator role). The label-based path has no
# explicit auth gate — label application itself requires write access.
PR_NUMBER_FROM_URL="${PR_URL##*/}"
gh issue edit "${PR_NUMBER_FROM_URL}" \
--repo "${REPO_FULL_NAME}" \
--add-label "ready-for-review" 2>/dev/null || \
echo "::warning::Failed to apply ready-for-review label to PR #${PR_NUMBER_FROM_URL}"
5 changes: 5 additions & 0 deletions internal/scaffold/fullsend-repo/scripts/post-retro-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,11 @@ run_test "happy-path-issue-created" \
"${FIXTURE_ONE_PROPOSAL}" \
"gh issue create"

# Verify that the happy-path applied the ready-for-triage label.
run_test "happy-path-triage-label" \
"${FIXTURE_ONE_PROPOSAL}" \
"ready-for-triage"

# Happy path: no proposals, comment posted successfully.
run_test "happy-path-no-proposals" \
"${FIXTURE_NO_PROPOSALS}" \
Expand Down
3 changes: 2 additions & 1 deletion internal/scaffold/fullsend-repo/scripts/post-retro.sh
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ for i in $(seq 0 $((PROPOSAL_COUNT - 1))); do
if ! ISSUE_URL=$(gh issue create \
--repo "${TARGET_REPO}" \
--title "${TITLE}" \
--body "${BODY}" 2>&1); then
--body "${BODY}" \
--label "ready-for-triage" 2>&1); then
echo "ERROR: failed to create issue in ${TARGET_REPO} (gh issue create --repo ${TARGET_REPO}): ${ISSUE_URL}" >&2
exit 1
fi
Expand Down
1 change: 1 addition & 0 deletions internal/scaffold/scaffold_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ func TestDispatchWorkflowContent(t *testing.T) {
assert.Contains(t, s, "/fs-fix")
assert.Contains(t, s, "/fs-retro")
assert.Contains(t, s, "/fs-prioritize")
assert.Contains(t, s, "ready-for-triage")
assert.Contains(t, s, "ready-to-code")
assert.Contains(t, s, "ready-for-review")
assert.Contains(t, s, "TRIGGERING_LABEL")
Expand Down
Loading