glue: honor the caller's original event when invoked via workflow_call (fix auto-trigger no-op) #2

Open
opened 2026-11-12 21:25:12 +00:00 by hermes_forgeron · 0 comments
Collaborator

Part of #1 (finding 1). This blocks day-to-day usage: every automatic trigger currently produces a no-op run.

Evidence (observed live, test_factory_ai)

  • Commenting on an agent-labeled issue fired a run (event issue_comment), but the job log shows:

    [agent 0.0s] not addressed to the agent (unhandled event workflow_call/created) — skipping

  • A manual dispatch with an explicit mode works, so the whole plan/build machinery is fine — only intent inference is broken on the reusable-workflow path.

Root cause

Project workflows delegate through uses: serious-devs/ai-factory/.forgejo/workflows/agent.yml@main. Inside the called workflow, GITHUB_EVENT_NAME is workflow_call, so readEvent() in glue/src/event.ts builds an EventInfo with name: 'workflow_call' and action: 'created' — the created value comes from the CALLER's payload, which proves GITHUB_EVENT_PATH still holds the original issue_comment / issues event. resolveIntent() has no workflow_call branch and falls through to run: false.

Proposed change

glue/src/event.ts — in readEvent(), when GITHUB_EVENT_NAME === 'workflow_call', keep parsing GITHUB_EVENT_PATH (the caller's event) and derive the effective event family from the payload shape instead of the env var:

  • payload has comment → treat as issue_comment (action from payload)
  • payload has issue + label → treat as issues / labeled
  • payload has issue → treat as issues (action from payload)
  • otherwise → keep workflow_call (falls through to the existing skip)

resolveIntent() should need no change: the existing issues labeled / issues opened / issue_comment branches then handle everything, including the self-trigger guard in main.ts (senderLogin comes from the caller payload's sender.login).

Add regression tests to glue/src/smoke.ts, which already builds GITHUB_EVENT_PATH fixtures and asserts on resolveIntent results:

  • caller payload = comment @agent plan on an unlabeled issue + env workflow_call → { mode: 'plan', run: true }
  • caller payload = plain comment on an agent-labeled issue + env workflow_call → { mode: 'plan', run: true }
  • caller payload = issues/labeled with label build + env workflow_call → { mode: 'build', run: true }
  • caller payload = issues/labeled with an irrelevant label + env workflow_call → run: false
  • env workflow_call with a payload without issue/comment (e.g. push) → run: false
  • explicit AGENT_MODE=build + env workflow_call → the explicit mode still wins

Deployment note

Glue changes only take effect after a new image tag is built and pushed and the agent-image default in .forgejo/workflows/agent.yml is updated (currently factory.serious-devs.io/serious-devs/ai-factory:20261013-1) — see docs/setup.md §3.

Acceptance criteria

  • npm run check passes and all the new smoke.ts cases above are present and green
  • e2e on serious-devs/test_factory_ai: on a scratch issue labeled agent, posting a plain comment triggers a run whose agent-1 job log shows trigger: ... (no not addressed to the agent skip) and the agent posts a plan reply — no manual dispatch
  • e2e: labeling a scratch issue build (automatic) runs the build without manual dispatch
  • e2e regression: a comment on a NON-agent-labeled issue still results in a skip, and comments authored by the bot are still self-trigger-guarded
  • Manual dispatch with an explicit mode still behaves exactly as today
Part of #1 (finding 1). This blocks day-to-day usage: every automatic trigger currently produces a no-op run. ## Evidence (observed live, test_factory_ai) - Commenting on an agent-labeled issue fired a run (event `issue_comment`), but the job log shows: `[agent 0.0s] not addressed to the agent (unhandled event workflow_call/created) — skipping` - A manual dispatch with an explicit `mode` works, so the whole plan/build machinery is fine — only intent inference is broken on the reusable-workflow path. ## Root cause Project workflows delegate through `uses: serious-devs/ai-factory/.forgejo/workflows/agent.yml@main`. Inside the called workflow, `GITHUB_EVENT_NAME` is `workflow_call`, so `readEvent()` in `glue/src/event.ts` builds an `EventInfo` with `name: 'workflow_call'` and `action: 'created'` — the `created` value comes from the CALLER's payload, which proves `GITHUB_EVENT_PATH` still holds the original `issue_comment` / `issues` event. `resolveIntent()` has no `workflow_call` branch and falls through to `run: false`. ## Proposed change `glue/src/event.ts` — in `readEvent()`, when `GITHUB_EVENT_NAME === 'workflow_call'`, keep parsing `GITHUB_EVENT_PATH` (the caller's event) and derive the effective event family from the payload shape instead of the env var: - payload has `comment` → treat as `issue_comment` (action from payload) - payload has `issue` + `label` → treat as `issues` / `labeled` - payload has `issue` → treat as `issues` (action from payload) - otherwise → keep `workflow_call` (falls through to the existing skip) `resolveIntent()` should need no change: the existing `issues labeled` / `issues opened` / `issue_comment` branches then handle everything, including the self-trigger guard in `main.ts` (`senderLogin` comes from the caller payload's `sender.login`). Add regression tests to `glue/src/smoke.ts`, which already builds `GITHUB_EVENT_PATH` fixtures and asserts on `resolveIntent` results: - caller payload = comment `@agent plan` on an unlabeled issue + env `workflow_call` → `{ mode: 'plan', run: true }` - caller payload = plain comment on an agent-labeled issue + env `workflow_call` → `{ mode: 'plan', run: true }` - caller payload = `issues`/`labeled` with label `build` + env `workflow_call` → `{ mode: 'build', run: true }` - caller payload = `issues`/`labeled` with an irrelevant label + env `workflow_call` → `run: false` - env `workflow_call` with a payload without `issue`/`comment` (e.g. push) → `run: false` - explicit `AGENT_MODE=build` + env `workflow_call` → the explicit mode still wins ## Deployment note Glue changes only take effect after a new image tag is built and pushed and the `agent-image` default in `.forgejo/workflows/agent.yml` is updated (currently `factory.serious-devs.io/serious-devs/ai-factory:20261013-1`) — see `docs/setup.md` §3. ## Acceptance criteria - [ ] `npm run check` passes and all the new smoke.ts cases above are present and green - [ ] e2e on `serious-devs/test_factory_ai`: on a scratch issue labeled `agent`, posting a plain comment triggers a run whose `agent-1` job log shows `trigger: ...` (no `not addressed to the agent` skip) and the agent posts a plan reply — no manual dispatch - [ ] e2e: labeling a scratch issue `build` (automatic) runs the build without manual dispatch - [ ] e2e regression: a comment on a NON-agent-labeled issue still results in a skip, and comments authored by the bot are still self-trigger-guarded - [ ] Manual dispatch with an explicit `mode` still behaves exactly as today
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
serious-devs/ai-factory#2
No description provided.