Skip to content

docs(adr): harness CEL dispatch and NormalizedEvent v1 - #2650

Merged
ifireball merged 10 commits into
fullsend-ai:mainfrom
ifireball:cursor/a3557196
Jun 30, 2026
Merged

ifireball merged 10 commits into
fullsend-ai:mainfrom
ifireball:cursor/a3557196

Conversation

@ifireball

Copy link
Copy Markdown
Member

Summary

  • Add ADR 0054 proposing forge-portable agent triggering via CEL trigger expressions on harness files and a fullsend dispatch command with input/output drivers.
  • Define the v1 NormalizedEvent normative schema, examples, and execution-ref projection rules so today's fullsend run inputs can be generated without changing the CLI contract.
  • Update docs/architecture.md and cross-reference ADR 0026.

Test plan

  • make lint passes (ADR frontmatter, markdown links, JSON schema)
  • Review ADR 0054 decision and consequences
  • Review NormalizedEvent v1 schema against current dispatch event_payload shape
  • Confirm execution-ref projection table covers all agent workflows (triage, code, review, fix, retro, prioritize)

Made with Cursor

Record ADR 0054 for forge-portable agent triggering via harness CEL
expressions and fullsend dispatch drivers, with a normative event schema
sufficient to project today's execution ref without changing fullsend run.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

github-actions Bot commented Jun 25, 2026 •

Copy link
Copy Markdown

Site preview

Preview: https://781d3ce2-site.fullsend-ai.workers.dev

Commit: 07e0bcb06c4bd0f6a714a97131f96ef488bcb78b

@ifireball ifireball self-assigned this Jun 25, 2026
@ifireball
ifireball requested a review from ggallen June 25, 2026 10:37
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 25, 2026 •

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 10:38 AM UTC · Ended 10:42 AM UTC
Commit: ff8ec85 · View workflow run →

@ifireball
ifireball marked this pull request as ready for review June 25, 2026 10:42
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Document ADR 0054: harness CEL dispatch + NormalizedEvent v1 spec
📝 Documentation 🕐 40+ Minutes

Grey Divider

Description

• Add ADR 0054 defining harness-scoped CEL trigger routing and fullsend dispatch drivers.
• Specify NormalizedEvent v1 schema, examples, and execution-ref projection for backward
 compatibility.
• Update architecture/ADR cross-references to reflect the new dispatch direction.
Diagram

graph TD
  ID["Input driver"] --> NE["NormalizedEvent"] --> CEL["CEL trigger eval"] --> MH["Matched harnesses"] --> ER["Execution ref projection"] --> OD["Output driver"]
  HS[/"Harness YAML (trigger)"/] --> CEL
  SC[/"NormalizedEvent v1 schema"/] --> NE
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Keep routing in workflow bash (status quo)
  • ➕ No migration work; behavior already proven in CI workflows
  • ➕ No new CEL evaluation surface area
  • ➖ Forge-coupled and duplicated routing logic across install modes
  • ➖ Harder to test and co-locate with harness intent
  • ➖ Requires more allow-listed workflow surface for new agents
2. Central routing table (single config.yaml)
  • ➕ Single place to audit routing/guards
  • ➕ Avoids embedding logic in CI workflow bash
  • ➖ Rules drift away from harness definitions; poor locality for org/custom agents
  • ➖ Still requires careful operational/security updates when routing expands
3. Harness-scoped CEL triggers + dispatch drivers (chosen)
  • ➕ Co-locates “when to run” with the harness; improves portability across forges
  • ➕ Enables generic runner workflows to be allow-listed once
  • ➕ Testable routing by replaying NormalizedEvent fixtures outside CI
  • ➖ Requires a normalized event contract and CEL tooling/linting discipline
  • ➖ Adds adapter/driver complexity and multi-match fan-out considerations

Recommendation: Proceed with the chosen Option C as documented: it best matches the stated goals (forge portability, harness-local authoring, and reduced allow-list friction). Review focus should be on whether NormalizedEvent v1 is sufficient to project today’s execution-ref inputs across all workflows without accidental GitHub-only leakage.

Files changed (9) +730 / -1

Documentation (9) +730 / -1
0026-stage-based-dispatch-for-agent-workflow-decoupling.mdClarify ADR 0026 supersession by harness CEL triggers (ADR 0054) +1/-1

Clarify ADR 0026 supersession by harness CEL triggers (ADR 0054)

• Updates ADR 0026 status text to explicitly note that '# fullsend-stage:' markers are superseded by harness CEL triggers as described in ADR 0054.

docs/ADRs/0026-stage-based-dispatch-for-agent-workflow-decoupling.md

0054-harness-cel-dispatch.mdAdd ADR 0054 for CEL-triggered harness dispatch + driver-based I/O +214/-0

Add ADR 0054 for CEL-triggered harness dispatch + driver-based I/O

• Introduces an accepted ADR proposing CEL 'trigger' expressions on harness YAML, a 'fullsend dispatch' subcommand, and pluggable input/output drivers. Documents the motivation (portability and allow-list security), the dispatch pipeline, and GitHub Actions integration direction.

docs/ADRs/0054-harness-cel-dispatch.md

architecture.mdDocument harness triggers and dispatch routing direction +8/-0

Document harness triggers and dispatch routing direction

• Adds architecture notes stating that harnesses may include CEL 'trigger' expressions evaluated against a forge-neutral NormalizedEvent. Records the decision to move routing from workflow bash to 'fullsend dispatch' per ADR 0054.

docs/architecture.md

README.mdDefine NormalizedEvent v1 contract and execution-ref projection rules +81/-0

Define NormalizedEvent v1 contract and execution-ref projection rules

• Adds the v1 normative README describing schema location, CEL context, adapter expectations, and versioning. Specifies how 'fullsend dispatch' projects NormalizedEvent into the existing execution-ref fields expected by 'fullsend run' and current workflows.

docs/normative/normalized-event/v1/README.md

fs-fix-comment.jsonAdd NormalizedEvent example for /fs-fix slash command on PR-linked issue +44/-0

Add NormalizedEvent example for /fs-fix slash command on PR-linked issue

• Provides a fixture covering a comment-based fix trigger on a work item that links to a change proposal, including populated change_proposal state for projection.

docs/normative/normalized-event/v1/examples/fs-fix-comment.json

issue-opened.jsonAdd NormalizedEvent example for issue opened transition +25/-0

Add NormalizedEvent example for issue opened transition

• Provides a minimal fixture for a work-item open event with actor and label snapshot.

docs/normative/normalized-event/v1/examples/issue-opened.json

ready-to-code-labeled.jsonAdd NormalizedEvent example for ready-to-code label addition +29/-0

Add NormalizedEvent example for ready-to-code label addition

• Adds a fixture representing a label_changed transition used by triage-to-code routing triggers.

docs/normative/normalized-event/v1/examples/ready-to-code-labeled.json

review-changes-requested.jsonAdd NormalizedEvent example for review submitted (changes requested) +39/-0

Add NormalizedEvent example for review submitted (changes requested)

• Adds a fixture for a change_proposal review_submitted transition, including reviewer identity and change_proposal execution context.

docs/normative/normalized-event/v1/examples/review-changes-requested.json

normalized-event.schema.jsonAdd v1 JSON Schema for NormalizedEvent +289/-0

Add v1 JSON Schema for NormalizedEvent

• Introduces the normative JSON Schema defining required top-level fields (repo/entity/transition/actor/state/source), strict additionalProperties controls, and conditional requirements for label/comment/review transitions. Encodes constraints needed to support dispatch routing and execution-ref projection while staying forge-neutral in structure.

docs/normative/normalized-event/v1/normalized-event.schema.json

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 25, 2026 •

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 10:45 AM UTC · Completed 10:58 AM UTC
Commit: 823a331 · View workflow run →

@qodo-code-review

qodo-code-review Bot commented Jun 25, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (1)

Context used
✅ Compliance rules (platform): 51 rules

Grey Divider


Action required

1. ADR 0054 exceeds 100 lines ✓ Resolved 📜 Skill insight ⚙ Maintainability
Description
ADR 0054’s content exceeds the 100-line maximum (excluding frontmatter), indicating the ADR is too
long for the required format. This makes the decision record harder to audit and maintain.
Code

docs/ADRs/0054-harness-cel-dispatch.md[214]

+  scope ([ADR 0018](0018-scripted-pipeline-for-multi-agent-orchestration.md)).
Relevance

⭐⭐ Medium

No historical evidence found enforcing 100-line ADR length limit; team reviews ADR substance
case-by-case.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The checklist requires ADR content (excluding frontmatter) to be <=100 lines. ADR 0054 extends to at
least line 214 in the committed file, exceeding the limit.

docs/ADRs/0054-harness-cel-dispatch.md[14-214]
Skill: writing-adrs

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`docs/ADRs/0054-harness-cel-dispatch.md` is longer than the allowed 100 lines of content (excluding frontmatter).

## Issue Context
Move detailed material (examples, projection tables, long workflow snippets) into linked docs (e.g., the normative spec README, architecture.md, or problem docs), and keep the ADR as a concise point-in-time decision record.

## Fix Focus Areas
- docs/ADRs/0054-harness-cel-dispatch.md[14-214]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. ADR 0054 Context 4 paragraphs ✓ Resolved 📜 Skill insight ⚙ Maintainability
Description
The ADR 0054 ## Context section contains more than 3 paragraphs. This violates the requirement
that Context be 1–3 short paragraphs.
Code

docs/ADRs/0054-harness-cel-dispatch.md[R22-54]

+## Context
+
+The primary motivation is to make **custom agents easy to author and portable
+across forges**. Today, adding a custom agent means editing shared dispatch
+bash in GitHub Actions workflows, adding a new per-stage workflow file, and
+re-implementing the same routing rules for each install mode. That workflow is
+GitHub-specific, not co-located with the harness, and does not travel to GitLab
+or other forges ([gitlab-implementation.md](../problems/gitlab-implementation.md#event-mapping)).
+
+A secondary motivation is **security allow-listing**. Workloads that call the
+token mint or inference APIs must run from workflows explicitly trusted by those
+layers. The mint validates `job_workflow_ref` against `.fullsend`, the upstream
+fullsend repo, or registered per-repo repos, and against an allowed workflow
+file list ([ADR 0029](0029-central-token-mint-secretless-fullsend.md)). Inference
+access via GCP Workload Identity Federation uses the same class of binding. Each new custom agent workflow file
+therefore requires operational changes in two security surfaces — friction that
+discourages experimentation and org-specific agents.
+
+Agent triggering today lives in bash embedded in GitHub Actions workflows
+(`reusable-dispatch.yml`, `internal/scaffold/.../dispatch.yml`). The router
+reads `github.event_*` fields, applies ACL and label guards, selects a
+**stage** string, and fans out to stage workflows via static `workflow_call`
+jobs or `# fullsend-stage:` scanning ([ADR 0026](0026-stage-based-dispatch-for-agent-workflow-decoupling.md),
+[ADR 0041](0041-synchronous-workflow-call-event-dispatch.md)).
+[ADR 0045](0045-forge-portable-harness-schema.md) moved execution identity into
+harness files but left **when** an agent runs in workflow bash.
+
+Colocating CEL `trigger` rules on harness files and driving dispatch through
+`fullsend dispatch` lets orgs add agents by dropping harness YAML (with triggers)
+into layered config — without new allow-listed workflow files per agent. A
+single generic runner workflow can be trusted once; routing nuance (slash
+commands, label snapshots, actor ACLs, fork gates, review-bot fix loops) lives
+in portable harness expressions evaluated against a forge-neutral event struct.
Relevance

⭐⭐ Medium

No historical evidence found enforcing Context paragraph-count limits in ADRs.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The Context section spans four distinct paragraphs separated by blank lines (primary motivation;
secondary motivation; current triggering approach; proposed direction), exceeding the 1–3 paragraph
limit.

docs/ADRs/0054-harness-cel-dispatch.md[22-55]
Skill: writing-adrs

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
ADR 0054 `## Context` exceeds the allowed 1–3 short paragraphs.

## Issue Context
Condense the Context to at most 3 short paragraphs and rely on links to problem docs/other ADRs for supporting detail.

## Fix Focus Areas
- docs/ADRs/0054-harness-cel-dispatch.md[22-55]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. GitHub-only URL constraint ✓ Resolved 🐞 Bug ≡ Correctness
Description
NormalizedEvent is described as forge-neutral, but the schema requires entity.url and
entity.linked_change_proposal.url to match https://github.com/..., which will fail validation
for GitLab/manual inputs and undermines cross-forge portability.
Code

docs/normative/normalized-event/v1/normalized-event.schema.json[R47-66]

+        "url": {
+          "type": "string",
+          "format": "uri",
+          "pattern": "^https://github\\.com/[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+/(issues|pull)/[0-9]+$",
+          "description": "Canonical entity URL. GitLab and other forges use their native URL form until a forge-neutral URI scheme is defined."
+        },
+        "linked_change_proposal": {
+          "type": "object",
+          "additionalProperties": false,
+          "required": ["id", "url"],
+          "properties": {
+            "id": {
+              "type": "integer",
+              "minimum": 1
+            },
+            "url": {
+              "type": "string",
+              "format": "uri",
+              "pattern": "^https://github\\.com/[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+/pull/[0-9]+$"
+            }
Relevance

⭐⭐ Medium

No prior decisions found on making forge-neutral schemas accept non-GitHub URLs; portability intent
exists but unclear enforcement.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
ADR 0054 and the NormalizedEvent README frame the model as forge-neutral and explicitly call out
GitLab portability, but the schema hard-codes GitHub URL regexes while also permitting
source.system to be gitlab, making non-GitHub events impossible to validate.

docs/ADRs/0054-harness-cel-dispatch.md[24-55]
docs/normative/normalized-event/v1/normalized-event.schema.json[47-66]
docs/normative/normalized-event/v1/normalized-event.schema.json[268-276]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The `NormalizedEvent` v1 JSON Schema currently enforces GitHub-only URL patterns for `entity.url` and `entity.linked_change_proposal.url`, despite the spec/ADR explicitly targeting cross-forge portability.

### Issue Context
- ADR 0054 positions dispatch as forge-portable.
- The schema itself allows `source.system = gitlab`, but the URL fields cannot validate for GitLab-native URLs.

### Fix Focus Areas
- docs/normative/normalized-event/v1/normalized-event.schema.json[47-66]
- docs/normative/normalized-event/v1/normalized-event.schema.json[268-276]

### Suggested fix
Update the schema so URL validation is conditional:
- If `source.system == "github"`, keep GitHub-specific URL patterns.
- Otherwise, allow any valid URI (`format: "uri"`) without a `github.com`-specific `pattern` (or introduce a forge-neutral URI scheme and validate against that).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
4. ADR 0054 Consequences 7 bullets ✓ Resolved 📜 Skill insight ⚙ Maintainability
Description
The ADR 0054 ## Consequences section contains 7 bullet points, exceeding the required 3–5
one-sentence bullets. This makes consequences harder to scan and compare across ADRs.
Code

docs/ADRs/0054-harness-cel-dispatch.md[R198-214]

+## Consequences
+
+- Custom agents become **drop-in harness files** with `trigger` expressions;
+  no per-agent workflow files or dispatch bash edits required.
+- Mint and inference allow-lists can trust a **small set of generic runner
+  workflows** instead of every agent-specific workflow file.
+- Trigger rules live beside the harness they activate; routing is
+  unit-testable by feeding `NormalizedEvent` fixtures to CEL without GitHub
+  Actions.
+- Forge portability improves: only input drivers map native events to
+  `NormalizedEvent`; harness CEL is shared.
+- `# fullsend-stage:` workflow markers and duplicated bash routers can be
+  deleted once migration completes.
+- CEL in harness files requires contributor documentation, linting, and eval
+  fixtures ([testing-agents.md](../problems/testing-agents.md)).
+- Multi-match fan-out is explicit; sequential stage chaining remains out of
+  scope ([ADR 0018](0018-scripted-pipeline-for-multi-agent-orchestration.md)).
Relevance

⭐⭐ Medium

No historical evidence found enforcing Consequences bullet-count limits in ADRs.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The checklist requires 3–5 one-sentence bullets in Consequences; ADR 0054 includes 7 bullets in this
section.

docs/ADRs/0054-harness-cel-dispatch.md[198-214]
Skill: writing-adrs

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
ADR 0054 `## Consequences` has 7 bullets; the required format is 3–5 one-sentence bullet points.

## Issue Context
Combine or move lower-priority consequences into linked docs (architecture.md, implementation notes, or problem docs) and keep only the key 3–5 consequences in the ADR.

## Fix Focus Areas
- docs/ADRs/0054-harness-cel-dispatch.md[198-214]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

5. Work_item accepts pull URL 🐞 Bug ≡ Correctness
Description
The schema permits entity.kind == "work_item" to use a /pull/ URL ((issues|pull)), and the
README projects event_payload.issue.html_url directly from entity.url; this can produce an
issue.html_url that fails existing workflow validation which requires an /issues/ URL.
Code

docs/normative/normalized-event/v1/normalized-event.schema.json[R35-52]

+      "required": ["kind", "id", "url"],
+      "properties": {
+        "kind": {
+          "type": "string",
+          "enum": ["work_item", "change_proposal"],
+          "description": "Forge-neutral entity kind (issue vs PR/MR)."
+        },
+        "id": {
+          "type": "integer",
+          "minimum": 1,
+          "description": "Entity number within repo."
+        },
+        "url": {
+          "type": "string",
+          "format": "uri",
+          "pattern": "^https://github\\.com/[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+/(issues|pull)/[0-9]+$",
+          "description": "Canonical entity URL. GitLab and other forges use their native URL form until a forge-neutral URI scheme is defined."
+        },
Relevance

⭐⭐⭐ High

Team previously accepted strict /issues/ URL validation in pre-code.sh; likely to align
schema/projection to avoid failures.

PR-#286

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The spec allows work_item URLs to be /pull/, but the execution-ref projection uses entity.url
as event_payload.issue.html_url, which is then passed into scripts/pre-code.sh where a strict
/issues/ regex is enforced, causing the pipeline to error on such spec-valid inputs.

docs/normative/normalized-event/v1/normalized-event.schema.json[35-52]
docs/normative/normalized-event/v1/README.md[40-46]
.github/workflows/reusable-code.yml[132-139]
internal/scaffold/fullsend-repo/scripts/pre-code.sh[17-30]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`entity.url` validation does not correlate with `entity.kind`, allowing `work_item` to have a PR URL. The README’s execution-ref projection maps `event_payload.issue.html_url` from `entity.url`, and downstream code workflows validate that value as a GitHub issue URL.

### Issue Context
Downstream code dispatch uses `event_payload.issue.html_url` to populate `GITHUB_ISSUE_URL`, and `scripts/pre-code.sh` rejects anything not matching `/issues/<n>`.

### Fix Focus Areas
- docs/normative/normalized-event/v1/normalized-event.schema.json[35-52]
- docs/normative/normalized-event/v1/README.md[40-46]

### Suggested fix
Add conditional schema rules (preferably gated under `source.system == "github"` if you also address non-GitHub URLs):
- If `entity.kind == "work_item"`, require `entity.url` to match `.../issues/<n>`.
- If `entity.kind == "change_proposal"`, require `entity.url` to match `.../pull/<n>`.
This prevents producing an execution ref that fails existing pipeline validation.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

6. ADR 0026 status annotated 📜 Skill insight ⚙ Maintainability
Description
The ## Status value includes extra annotation text instead of being exactly Accepted,
Deprecated, or Superseded, and it no longer matches the frontmatter status. This breaks the
ADR status vocabulary and creates inconsistency between frontmatter and body.
Code

docs/ADRs/0026-stage-based-dispatch-for-agent-workflow-decoupling.md[18]

+Accepted (Option C superseded by [ADR 0041](0041-synchronous-workflow-call-event-dispatch.md) for the event-driven dispatch path; `# fullsend-stage:` markers superseded by harness CEL triggers in [ADR 0054](0054-harness-cel-dispatch.md))
Relevance

⭐ Low

Similar “bare ADR Status only” suggestion was rejected; team tolerates annotated Status lines in
body.

PR-#716

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The ADR template requires the body Status value to be exactly one of the accepted status values and
to match the YAML frontmatter. In ADR 0026, the frontmatter is status: Accepted while the body
Status line is Accepted (...), violating both the allowed status vocabulary and the
frontmatter/body match requirement.

Rule 1062061: Restrict ADR status to accepted values
docs/ADRs/0026-stage-based-dispatch-for-agent-workflow-decoupling.md[1-4]
docs/ADRs/0026-stage-based-dispatch-for-agent-workflow-decoupling.md[16-19]
Skill: writing-adrs

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`docs/ADRs/0026-stage-based-dispatch-for-agent-workflow-decoupling.md` has `status: Accepted` in YAML frontmatter, but the body `## Status` content is `Accepted (...)` with additional text. The compliance rules require the status value to be exactly one of `Accepted`, `Deprecated`, or `Superseded`, and the frontmatter status must match the body.

## Issue Context
Keep any supersedence/annotation text as a separate note under the Status section (or elsewhere), but not inside the status value itself.

## Fix Focus Areas
- docs/ADRs/0026-stage-based-dispatch-for-agent-workflow-decoupling.md[16-19]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread docs/ADRs/0054-harness-cel-dispatch.md Resolved
Comment thread docs/ADRs/0054-harness-cel-dispatch.md Resolved
Comment thread docs/ADRs/0054-harness-cel-dispatch.md Resolved
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 25, 2026 •

Copy link
Copy Markdown

Review

Findings

Medium

  • [missing-authorization] PR-level — This PR adds ADR 0061 (a new dispatch mechanism) and the NormalizedEvent v1 normative schema with no linked issue. This is a substantial architectural addition (new ADR, new normative schema, 7 example fixtures, cross-references to multiple existing ADRs). While ADR proposals may precede implementation issues and this is docs-only, non-trivial changes benefit from explicit authorization to establish scope.
    Remediation: Link this PR to an authorizing issue that captures the problem statement and approval for introducing CEL-based dispatch.

  • [scope-coherence] docs/ADRs/0061-harness-cel-dispatch.md — ADR 0061 describes NormalizedEvent with "forge-neutral field names" while the README explicitly limits v1 normative scope to "GitHub Actions only." Both documents individually explain this (forge-neutral naming for future extension, GitHub-only normative scope for v1), but the framing could be clearer. Readers encountering the ADR's forge-neutrality language may expect multi-forge coverage that v1 does not provide.
    Remediation: Consider reframing as "GitHub-first with forge-neutral field naming for future extension" to set clearer expectations in the ADR's Decision section.

Low

  • [edge-case] docs/normative/normalized-event/v1/README.md:349 — The CEL trigger example for /fs-fix accesses event.state.change_proposal.is_fork without guarding against state.change_proposal being absent. In CEL, accessing a field on a missing object causes a runtime error rather than returning false. A has() guard would make the example more robust and set a safer pattern for harness authors.
    Remediation: Use has(event.state.change_proposal) && !event.state.change_proposal.is_fork.

  • [missing-documentation-update] docs/guides/user/building-custom-agents.md — The custom agent guide documents only workflow_dispatch-based triggering. Once CEL triggers are implemented per ADR 0061, this guide should be updated to cover the new mechanism.
    Remediation: Track as follow-up work to update the guide when CEL dispatch is implemented.

  • [potentially-stale-references] docs/problems/gitlab-implementation.md — References to # fullsend-stage: markers which ADR 0061 explicitly deprecates. The markers appear in multiple code examples. While this is a problem/design document (not a user guide), a deprecation note would help readers.
    Remediation: Add a note in the stage markers section indicating they are superseded by harness CEL triggers per ADR 0061.

  • [missing-cross-reference] docs/ADRs/0061-harness-cel-dispatch.md — The connection between CEL dispatch and mint allow-listing (ADR 0029) is present but spread across Context and Consequences sections. A more explicit explanation of how workflow allow-listing works would strengthen the motivation.
    Remediation: Add 2-3 sentences in the Context section clarifying the allow-list maintenance burden that CEL dispatch reduces.

Previous run

Review

Findings

Critical

  • [adr-number-collision] docs/ADRs/0055-harness-cel-dispatch.md — ADR 0055 already exists on main as 0055-unified-env-var-delivery.md. This creates a number collision that violates ADR uniqueness conventions and will cause ambiguity. The highest current ADR on main is 0058 (agent-registration.md), so the new ADR should be numbered 0059.
    Remediation: Renumber the ADR to 0059 (or the next available number). Update all internal cross-references: ADR 0026 status annotation, ADR 0041 status annotation, docs/architecture.md entries, and the NormalizedEvent v1 README references to ADR 0055.

Medium

  • [internal-inconsistency] docs/normative/normalized-event/v1/examples/ready-to-code-labeled.json — The ready-to-code-labeled.json fixture assigns actor.role: "none" to fullsend-ai-triage[bot], and review-changes-requested.json assigns actor.role: "none" to fullsend-ai-review[bot]. The README's "Actor role mapping (GitHub)" section explicitly states: "For GitHub App bots, use the installation's effective permission on the repository (typically write), not none." These fixtures contradict the normative adapter guidance and will produce incorrect test expectations for adapter implementations.
    Remediation: Update bot actor roles in both fixtures from "none" to "write" (or the effective installation permission) to match the README's documented mapping rule.
Previous run (2)

Review

Findings

Medium

  • [internal-inconsistency] docs/normative/normalized-event/v1/examples/ready-to-code-labeled.json — The ready-to-code-labeled.json fixture assigns actor.role: "none" to fullsend-ai-triage[bot], and review-changes-requested.json assigns actor.role: "none" to fullsend-ai-review[bot]. The README's "Actor role mapping (GitHub)" section explicitly states: "For GitHub App bots, use the installation's effective permission on the repository (typically write), not none." These fixtures contradict the normative adapter guidance and will produce incorrect test expectations for adapter implementations.
    Remediation: Update bot actor roles in both fixtures from "none" to "write" (or the effective installation permission) to match the README's documented mapping rule.
Previous run (3)

Review

Findings

Medium

  • [architectural-coherence] docs/ADRs/0055-harness-cel-dispatch.md — ADR 0055 claims to partially supersede ADR 0041 (synchronous workflow_call event dispatch). Both ADRs and the updated ADR 0041 status annotation explain the relationship — static stage routing is superseded while synchronous execution is preserved via dynamic matrix jobs. However, this is a substantive mechanism change (static workflow_call jobs → dynamic matrix jobs) that warrants human verification: confirm that the dynamic matrix approach genuinely preserves the run-correlation and observability properties that motivated ADR 0041's synchronous execution model.
    Remediation: Verify during review that dynamic matrix jobs provide equivalent run correlation in the GitHub Actions UI to the static workflow_call approach. If they do not, the "preserves synchronous execution" claim needs qualification.
Previous run

Looks good to me

Previous run (4)

Review

Findings

Critical

  • [adr-number-collision] docs/ADRs/0054-harness-cel-dispatch.md — ADR 0054 already exists on main as 0054-require-authorization-on-all-agent-dispatch-paths.md. This creates a number collision that violates ADR versioning conventions and will cause ambiguity. The new ADR must be renumbered to the next available number.
    Remediation: Run the /renumber-adr skill or manually renumber the ADR. All internal cross-references (ADR 0026 status line, architecture.md entries, normative spec README) must be updated to match the new number.

Medium

  • [missing-authorization] PR-level — This is a non-trivial change (~730 lines added: new ADR, normative schema, architecture updates) with no linked issue. While ADR proposals are a standard pattern, linking an issue establishes authorized scope for review.

  • [schema-url-pattern-restrictive] docs/normative/normalized-event/v1/normalized-event.schema.json:30 — The entity.url field has a pattern constraint hardcoded to GitHub URLs only (^https://github\\.com/...). This contradicts the stated design goal of a forge-neutral event struct — GitLab or self-hosted forge URLs would fail schema validation. The same issue affects linked_change_proposal.url. Either remove the GitHub-specific pattern (relying on format: uri), or document explicitly that v1 is intentionally GitHub-only with a note that future versions will broaden the pattern.

  • [ambiguous-entity-mapping] docs/normative/normalized-event/v1/README.md:56 — The execution-ref projection mixes fields from linked_change_proposal (for number/html_url) and state.change_proposal (for head/base). No schema constraint enforces that these refer to the same change proposal. If their id fields differ, the projected payload would combine metadata from two different PRs. Add a schema constraint enforcing consistency, or document which object takes precedence when they conflict.

  • [architectural-alignment] docs/ADRs/0054-harness-cel-dispatch.md — ADR 0041 eliminated dynamic agent discovery (# fullsend-stage: scanning) in favor of static workflow_call jobs. CEL-based trigger evaluation reintroduces dynamic discovery in a new form. The ADR should explicitly state whether it supersedes ADR 0041's static dispatch model, and clarify the relationship to ADR 0018's prohibition on LLM-based orchestration (which is distinct from CEL-based routing but operates in the same dispatch layer).


Labels: PR adds new ADR and normative schema for dispatch/harness infrastructure

Previous run (5)

Review

Findings

Medium

  • [architectural-coherence] docs/ADRs/0055-harness-cel-dispatch.md — ADR 0055 claims to partially supersede ADR 0041 (synchronous workflow_call event dispatch). Both ADRs and the updated ADR 0041 status annotation explain the relationship — static stage routing is superseded while synchronous execution is preserved via dynamic matrix jobs. However, this is a substantive mechanism change (static workflow_call jobs → dynamic matrix jobs) that warrants human verification: confirm that the dynamic matrix approach genuinely preserves the run-correlation and observability properties that motivated ADR 0041's synchronous execution model.
    Remediation: Verify during review that dynamic matrix jobs provide equivalent run correlation in the GitHub Actions UI to the static workflow_call approach. If they do not, the "preserves synchronous execution" claim needs qualification.
Previous run (6)

Looks good to me

Previous run (7)

Review

Findings

Critical

  • [adr-number-collision] docs/ADRs/0054-harness-cel-dispatch.md — ADR 0054 already exists on main as 0054-require-authorization-on-all-agent-dispatch-paths.md. This creates a number collision that violates ADR versioning conventions and will cause ambiguity. The new ADR must be renumbered to the next available number.
    Remediation: Run the /renumber-adr skill or manually renumber the ADR. All internal cross-references (ADR 0026 status line, architecture.md entries, normative spec README) must be updated to match the new number.

Medium

  • [missing-authorization] PR-level — This is a non-trivial change (~730 lines added: new ADR, normative schema, architecture updates) with no linked issue. While ADR proposals are a standard pattern, linking an issue establishes authorized scope for review.

  • [schema-url-pattern-restrictive] docs/normative/normalized-event/v1/normalized-event.schema.json:30 — The entity.url field has a pattern constraint hardcoded to GitHub URLs only (^https://github\\.com/...). This contradicts the stated design goal of a forge-neutral event struct — GitLab or self-hosted forge URLs would fail schema validation. The same issue affects linked_change_proposal.url. Either remove the GitHub-specific pattern (relying on format: uri), or document explicitly that v1 is intentionally GitHub-only with a note that future versions will broaden the pattern.

  • [ambiguous-entity-mapping] docs/normative/normalized-event/v1/README.md:56 — The execution-ref projection mixes fields from linked_change_proposal (for number/html_url) and state.change_proposal (for head/base). No schema constraint enforces that these refer to the same change proposal. If their id fields differ, the projected payload would combine metadata from two different PRs. Add a schema constraint enforcing consistency, or document which object takes precedence when they conflict.

  • [architectural-alignment] docs/ADRs/0054-harness-cel-dispatch.md — ADR 0041 eliminated dynamic agent discovery (# fullsend-stage: scanning) in favor of static workflow_call jobs. CEL-based trigger evaluation reintroduces dynamic discovery in a new form. The ADR should explicitly state whether it supersedes ADR 0041's static dispatch model, and clarify the relationship to ADR 0018's prohibition on LLM-based orchestration (which is distinct from CEL-based routing but operates in the same dispatch layer).


Labels: PR adds new ADR and normative schema for dispatch/harness infrastructure

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the review comment for full details.

@fullsend-ai-review fullsend-ai-review Bot added component/dispatch Workflow dispatch and triggers component/harness Agent harness, config, and skills loading component/docs User-facing documentation labels Jun 25, 2026
ifireball and others added 2 commits June 25, 2026 16:34
Signed-off-by: Barak Korren <bkorren@redhat.com>
Merge main, rename ADR 0054→0055 to avoid collision, condense ADR to
format limits, use forge-neutral URL validation, and document change-
proposal identity rules for execution-ref projection.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 25, 2026 •

Copy link
Copy Markdown

🤖 Review · ❌ Terminated · Started 1:39 PM UTC · Ended 1:57 PM UTC
Commit: 2d8adb7 · View workflow run →

@ifireball

Copy link
Copy Markdown
Member Author

Addressed review feedback in 5317cf0:

  • ADR number collision: Renumbered to ADR 0055 (main already has ADR 0054 for dispatch authorization).
  • ADR format: Condensed to ≤100 content lines, 3 Context paragraphs, 5 Consequences bullets; moved examples/projection detail to normative spec.
  • Forge-neutral URLs: Removed GitHub-only URL patterns from normalized-event.schema.json; URLs use format: uri for any forge.
  • Change-proposal identity: Documented MUST rules linking entity, linked_change_proposal, and state.change_proposal.id in normative README + schema descriptions.

CI is green; awaiting human review approval.

@codecov

codecov Bot commented Jun 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@fullsend-ai-review fullsend-ai-review Bot added the ready-for-merge All reviewers approved — ready to merge label Jun 25, 2026
@fullsend-ai-review

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 1:39 PM UTC · Completed 1:57 PM UTC
Commit: 5317cf0 · View workflow run →

ifireball and others added 3 commits June 30, 2026 11:06
Signed-off-by: Barak Korren <bkorren@redhat.com>
Merge upstream/main (0055 taken by unified-env-var-delivery). Cross-ref
agent registration for harness enumeration in fullsend dispatch pipeline.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Use code-point wording in comment.body schema description; set bot
actor.role to write in triage and review examples.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 30, 2026 •

Copy link
Copy Markdown

🤖 Review · ❌ Terminated · Started 8:14 AM UTC · Ended 8:39 AM UTC
Commit: 104508d · View workflow run →

@rh-hemartin

Copy link
Copy Markdown
Member

Could add an example for cron? I'm worried about the implementation itself, as the can't be executing every minute and check, we would need to generate a workflow specifically from the cron instructions?

@fullsend-ai-review fullsend-ai-review Bot added the requires-manual-review Review requires human judgment label Jun 30, 2026
@fullsend-ai-review

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 8:14 AM UTC · Completed 8:38 AM UTC
Commit: c0c1e68 · View workflow run →

@ifireball

Copy link
Copy Markdown
Member Author

@rh-hemartin

Could add an example for cron? I'm worried about the implementation itself, as the can't be executing every minute and check, we would need to generate a workflow specifically from the cron instructions?

This takes a bit more thinking so I don't want to scope it in here, but there are basically two kinds of cron:

  • Cron that is actually monitoring events in another system - that is what the poll ADR is for (docs(adr): add polling-based work discovery ADR #2409)
  • Cron that really want to do something at arbitrary time points - we can implement this by:
    • Adding time data to the NormalizedEvent structure
    • Adding a workflow that runs in a tight cron schedule
    • Triggering workflows where the CEL expression matches the time data

There are some subtleties WRT how to detect and manage skipped runs when the underlying systems cannot trigger our workflow frequently enough, so that requires a bit more thinking, and I don't want to delay this on that.

BTW - since this does not negate using normal workflows to trigger arbitrary harness files, we could still use those from Cron while we work on getting it into the CEL expression space.

Signed-off-by: Barak Korren <bkorren@redhat.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 30, 2026 •

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 1:10 PM UTC · Completed 1:22 PM UTC
Commit: 07e0bcb · View workflow run →

@ifireball
ifireball added this pull request to the merge queue Jun 30, 2026
Merged via the queue into fullsend-ai:main with commit 8354284 Jun 30, 2026
13 checks passed
@ifireball
ifireball deleted the cursor/a3557196 branch June 30, 2026 13:17
@fullsend-ai-retro

fullsend-ai-retro Bot commented Jun 30, 2026 •

Copy link
Copy Markdown

🤖 Retro · ❌ Terminated · Started 1:21 PM UTC · Ended 1:30 PM UTC
Commit: 104508d · View workflow run →

@fullsend-ai-review

Copy link
Copy Markdown

Review skipped — this PR is already merged.

The /fs-review command only reviews open pull requests.

Posted by fullsend post-review check

@fullsend-ai-retro

Copy link
Copy Markdown

🤖 Finished Retro · ❌ Failure · Started 1:21 PM UTC · Completed 1:30 PM UTC
Commit: 07e0bcb · View workflow run →

This branch was successfully deployed

1 active deployment
site-preview — 07e0bcb0 Deployed Jun 30, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/dispatch Workflow dispatch and triggers component/docs User-facing documentation component/harness Agent harness, config, and skills loading requires-manual-review Review requires human judgment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants