Skip to content

docs(adr): add ADR 0086 for conversation surface participation - #6083

Merged
ifireball merged 9 commits into
fullsend-ai:mainfrom
ifireball:cursor/726ecc8c
Aug 20, 2026
Merged

docs(adr): add ADR 0086 for conversation surface participation#6083
ifireball merged 9 commits into
fullsend-ai:mainfrom
ifireball:cursor/726ecc8c

Conversation

@ifireball

Copy link
Copy Markdown
Member

Summary

  • Adds ADR 0086: portable Conversation surface via conversation.Client (parallel to tracker.Client), so agents can participate in GitHub Discussions and later other chat systems without growing forge.Client.
  • Extends NormalizedEvent v1 with entity.kind: conversation and required state.conversation.category (1:M category→conversation; M:M labels on conversations only; messages inherit parent context).
  • Updates docs/architecture.md and cross-links ADR 0076.

Test plan

  • make lint on staged ADR/docs changes
  • Review domain model (category vs labels) and conversation.Client seam against internal/tracker
  • Confirm ADR number 0086 does not collide with in-flight ADR PRs at merge time

Made with Cursor

Record the decision to introduce conversation.Client (parallel to
tracker.Client) so custom agents can participate in GitHub Discussions
and other chat systems without extending forge.Client, and extend
NormalizedEvent with conversation category metadata.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@ifireball
ifireball requested a review from a team as a code owner August 11, 2026 11:30
@ifireball ifireball self-assigned this Aug 11, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 11, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 11:31 AM UTC · Ended 11:44 AM UTC

Commit: f0fb298 · View workflow run →

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

docs: ADR 0086 for conversation surfaces + NormalizedEvent v1 conversation kind

📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Add ADR 0086 defining a portable conversation surface via conversation.Client.
• Extend NormalizedEvent v1 to model conversations with required category metadata.
• Update architecture docs and add a Discussion event fixture/example for CEL routing.
Diagram

graph TD
  A["Input drivers"] --> B(("NormalizedEvent v1")) --> C["Dispatch + CEL"] --> D["conversation.Client"] --> E{{"Conversation system\n(e.g. GitHub Discussions)"}}
  C --> F["forge.Client"]
  C --> G["tracker.Client"]
  subgraph Legend
    direction LR
    _svc["Service/component"] ~~~ _data(("Spec / event")) ~~~ _ext{{"External system"}}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Special-case GitHub Discussions in workflows
  • ➕ Fastest path for GitHub-only support
  • ➕ Avoids introducing a new domain client interface initially
  • ➖ Hard-codes GitHub semantics into dispatch/workflows
  • ➖ Duplicates auth/writeback logic and conflicts with existing interface-splitting direction
2. Extend forge.Client with conversation/message APIs
  • ➕ Single client interface for all GitHub surfaces
  • ➖ Expands forge scope beyond git-hosting and undermines the forge/tracker split
  • ➖ Makes non-forge chat backends (Slack/Discord/Matrix) awkward or impossible to model cleanly
3. Always-on external chat bot
  • ➕ Lower latency and simpler real-time interaction model
  • ➖ Bypasses unidirectional control flow, mint/OIDC identity, and harness registration guarantees
  • ➖ Creates a parallel execution path with different security and policy enforcement

Recommendation: Proceed with the chosen conversation.Client seam. It keeps forge.Client narrowly scoped, matches the established tracker.Client split, and cleanly models category (1:M) vs labels (M:M) for conversations while keeping message events inheriting parent context.

Files changed (6) +267 / -6

Documentation (6) +267 / -6
0076-slash-command-entity-context-separation.mdCross-link ADR 0076 to conversation surface decision (ADR 0086) +3/-0

Cross-link ADR 0076 to conversation surface decision (ADR 0086)

• Adds a forward reference noting that entity-context rules are extended for conversation surfaces in ADR 0086.

docs/ADRs/0076-slash-command-entity-context-separation.md

0086-conversation-surface-for-agent-participation.mdAdd ADR 0086: portable conversation surface via conversation.Client +126/-0

Add ADR 0086: portable conversation surface via conversation.Client

• Introduces the decision to add 'conversation.Client' (parallel to 'tracker.Client') for GitHub Discussions and future chat systems. Defines a domain model separating conversation categories (1:M) from labels (M:M) and specifies NormalizedEvent v1 requirements for conversation events.

docs/ADRs/0086-conversation-surface-for-agent-participation.md

architecture.mdDocument conversation participation architecture and security considerations +13/-1

Document conversation participation architecture and security considerations

• Updates the architecture overview to include conversation surfaces as first-class dispatch inputs using 'entity.kind: conversation' and writeback through 'conversation.Client'. Adds identity/scope open questions and clarifies conversation context separation from code-mutating slash commands.

docs/architecture.md

README.mdDocument NormalizedEvent v1 conversation semantics and CEL example +19/-1

Document NormalizedEvent v1 conversation semantics and CEL example

• Adds guidance for 'entity.kind: conversation', including required 'state.conversation.category' and how labels apply at conversation-level only. Updates adapter requirements and includes an illustrative CEL trigger for a conversation-native agent.

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

discussion-fs-vouch-comment.jsonAdd example NormalizedEvent fixture for Discussion comment slash command +38/-0

Add example NormalizedEvent fixture for Discussion comment slash command

• Adds a concrete 'entity.kind: conversation' JSON example showing 'comment_added' transition, conversation labels, and required category metadata.

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

normalized-event.schema.jsonExtend NormalizedEvent v1 JSON Schema for conversation entity and category +68/-4

Extend NormalizedEvent v1 JSON Schema for conversation entity and category

• Adds 'conversation' to 'entity.kind', introduces 'state.conversation.category' with required 'name' and optional 'id/slug/format', and enforces presence of 'state.conversation' when 'entity.kind' is conversation. Clarifies that 'state.labels' are conversation-level labels (category is not a label).

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

@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown

Site preview

Preview: https://64c26e87-site.fullsend-ai.workers.dev

Commit: a65c62ed782b788789b05a6521e12f71d3470a84

@codecov

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@qodo-code-review

qodo-code-review Bot commented Aug 11, 2026

Copy link
Copy Markdown

Code Review by Qodo

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

Grey Divider


Action required

1. Planned adapters missing callout ✗ Dismissed 📜 Skill insight ≡ Correctness
Description
The normative README documents not-yet-implemented Discussion support as plain prose instead of the
required > **Planned:** callout with an issue link. This can mislead readers about current vs
planned behavior and violates the documentation standard.
Code

docs/normative/normalized-event/v1/README.md[R32-36]

+- `entity.kind: conversation` covers GitHub Discussions and future chat
+  systems ([ADR 0086](../../../ADRs/0086-conversation-surface-for-agent-participation.md)).
+  GitHub Discussion adapters are planned under `gha-event`; additional
+  `source.system` values (e.g. Slack) are non-breaking enum additions when
+  those drivers land.
Relevance

●●● Strong

Team enforces Planned callout plus tracking link for not-yet-implemented docs; will update README
accordingly.

PR-#3903

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 1062082 requires any mention of not-yet-implemented features to use a `>
**Planned:**` callout and include an issue link. The added README lines describe Discussions support
as "planned" in normal prose and do not include the required callout or an issue link.

docs/normative/normalized-event/v1/README.md[32-36]
Skill: writing-user-docs

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/normative/normalized-event/v1/README.md` mentions planned (not-yet-implemented) GitHub Discussions support as normal text. Compliance requires planned features to be documented using a `> **Planned:**` blockquote callout and to include a link to the tracking issue.

## Issue Context
The README currently states that GitHub Discussion adapters / Discussions support is "planned" without using the required callout format and without an issue link.

## Fix Focus Areas
- docs/normative/normalized-event/v1/README.md[32-36]
- docs/normative/normalized-event/v1/README.md[60-70]

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



Remediation recommended

2. CEL optional fields unguarded ✓ Resolved 🐞 Bug ≡ Correctness
Description
The new conversation CEL trigger example dereferences optional fields
(state.conversation.category.slug and transition.comment.command) without has(...) guards, so
valid events may cause CEL evaluation errors or evaluate unexpectedly. This makes the normative
example unsafe to copy/paste for discussion/comment routing when adapters omit optional fields or
when comments are not slash commands.
Code

docs/normative/normalized-event/v1/README.md[R185-188]

+event.entity.kind == "conversation"
+  && event.state.conversation.category.slug == "vouch-request"
+  && event.transition.kind == "comment_added"
+  && event.transition.comment.command == "/fs-vouch"
Relevance

●●● Strong

Normative NormalizedEvent docs changes are commonly accepted; adding has(...) guards makes CEL
example safe to copy/paste.

PR-#2650

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The README’s new CEL example compares category.slug and comment.command, but the schema
explicitly makes both fields optional, so valid events can omit them and still pass schema
validation; this is the same pitfall previously flagged for other CEL examples.

docs/normative/normalized-event/v1/README.md[184-189]
docs/normative/normalized-event/v1/normalized-event.schema.json[202-221]
docs/normative/normalized-event/v1/normalized-event.schema.json[322-349]
PR-#5532

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 newly added CEL example for conversation-native agents directly accesses optional fields (`event.state.conversation.category.slug` and `event.transition.comment.command`). Because these fields are optional in the NormalizedEvent v1 schema, valid events may omit them, causing CEL evaluation errors or non-portable triggers.

### Issue Context
- `transition.comment.command` is optional (only `transition.comment.body` is required).
- `state.conversation.category.slug` is optional (only `state.conversation.category.name` is required).

### Fix approach
Update the example trigger to guard optional fields with `has(...)`, and/or prefer `category.name` (required) for routing.

Example fix:
```cel
// Conversation-native agent on Discussion slash command (ADR 0086)
event.entity.kind == "conversation"
 && event.transition.kind == "comment_added"
 && has(event.transition.comment.command)
 && event.transition.comment.command == "/fs-vouch"
 && has(event.state.conversation.category.slug)
 && event.state.conversation.category.slug == "vouch-request"
```
(Alternatively, route on `event.state.conversation.category.name == "Vouch Request"` to avoid relying on optional `slug`.)

### Fix Focus Areas
- docs/normative/normalized-event/v1/README.md[184-189]

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



Informational

3. ADR 0086 exceeds 100 lines 📜 Skill insight ⚙ Maintainability
Description
ADR 0086 exceeds the 100-line maximum (excluding frontmatter), indicating the decision record is
likely too long and should be tightened or moved into linked docs. This increases review and
long-term maintenance burden for ADRs.
Code

docs/ADRs/0086-conversation-surface-for-agent-participation.md[R119-126]

+## Consequences
+
+- Harnesses route with CEL on both `state.conversation.category` and
+  `state.labels` (e.g. category selects the agent; labels refine).
+- Slack becomes input-driver + `conversation.Client` adapter work; channel maps
+  to category, thread maps to conversation.
+- Domain split: `forge.Client` / `tracker.Client` / `conversation.Client`.
+- Linking a conversation to a work item for `/fs-code` remains a follow-on.
Relevance

● Weak

Length-limit enforcement was previously rejected for ADRs; team allowed >100-line ADR content.

PR-#2582

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 1062092 requires ADR content (excluding frontmatter) to be ≤100 lines. ADR 0086 has
111 content lines (lines 16-126), exceeding the limit.

docs/ADRs/0086-conversation-surface-for-agent-participation.md[1-126]
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/0086-conversation-surface-for-agent-participation.md` exceeds the maximum allowed ADR length of 100 lines (excluding YAML frontmatter).

## Issue Context
The file is 126 lines total, with 15 lines of frontmatter, leaving 111 content lines—over the 100-line limit.

## Fix Focus Areas
- docs/ADRs/0086-conversation-surface-for-agent-participation.md[16-126]

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


Grey Divider

Context sources
✅ Compliance rules (platform): 54 rules

Grey Divider

Tip of the day
💡 Did you know, you can copy the agent prompt from any finding and feed it to your IDE agent

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread docs/normative/normalized-event/v1/README.md Outdated
Comment thread docs/normative/normalized-event/v1/README.md
@ifireball

Copy link
Copy Markdown
Member Author

Also declining the ADR line-count skill insight: the domain model table and conversation.Client / tracker.Client alignment are load-bearing for this decision; splitting would obscure the single decision. Happy to tighten in a follow-up if review still wants it after merge.

Require has() checks for optional comment.command and category.slug in
the NormalizedEvent conversation trigger example so copy-paste triggers
do not fail on valid events that omit those fields.

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

fullsend-ai-review Bot commented Aug 11, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 11:45 AM UTC · Completed 12:01 PM UTC

Commit: 62739d2 · View workflow run →

@fullsend-ai-review

fullsend-ai-review Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review

Findings

Medium

  • [schema-code-mismatch] docs/normative/normalized-event/v1/normalized-event.schema.json — The JSON schema's transition.kind enum does not include comment_edited or comment_deleted, yet the Go code defines TransitionCommentEdited and TransitionCommentDeleted and validates them. This PR deepens the pre-existing inconsistency: the new conversation-specific validation requires comment.id and comment.parent_id for comment_edited and comment_deleted transitions on conversations, but the schema's allOf block forbids the comment sub-object for any transition kind other than comment_added.
    Remediation: Add comment_edited and comment_deleted to the transition.kind enum. Update the transition allOf comment constraint to allow the comment sub-object for all three comment_* kinds.

Low

  • [consumer-completeness] internal/harnessdispatch/project.go:57buildEventPayload switches on event.Entity.Kind with cases for EntityWorkItem and EntityChangeProposal only. A conversation entity falls through silently, producing a payload with no entity identifier. Once a gha-event Discussion adapter lands, dispatched conversation agents would receive an EventPayload missing their entity context. The ADR marks the Discussion adapter as planned, so this is not yet reachable at runtime, but it is a latent gap.

  • [scope-intent-mismatch] — PR title uses docs(adr): prefix, signaling documentation-only change. However, the PR includes production Go code changes (internal/normevent/event.go), new tests (internal/normevent/event_test.go), and schema extensions (normalized-event.schema.json).

Previous run

Review

Findings

Medium

  • [scope-intent-mismatch] — PR title uses docs(adr): prefix, signaling documentation-only change. However, the PR includes production Go code changes (internal/normevent/event.go), new validation logic in Validate(), schema extensions (normalized-event.schema.json), new test (event_test.go), and a new example fixture. This is not documentation-only.
    Remediation: Change PR title prefix to match the actual scope, e.g. feat(normevent): add conversation entity kind support (ADR 0086).

Low

  • [consumer-completeness] internal/harnessdispatch/project.go:57buildEventPayload switches on event.Entity.Kind with cases for EntityWorkItem and EntityChangeProposal only. A conversation entity falls through silently, producing a payload with no entity identifier. Once a gha-event Discussion adapter lands, dispatched conversation agents would receive an EventPayload missing their entity context. The ADR marks the Discussion adapter as planned, so this is not yet reachable at runtime, but it is a latent gap.

Resolved since last review: The prior test-adequacy finding is now addressed — TestValidate_ConversationRules covers all three Validate() error paths (missing state.conversation, empty category.name, conversation forbidden on non-conversation entity).

Previous run (2)

Review

Findings

Medium

  • [scope-intent-mismatch] — PR title uses docs(adr): prefix, signaling documentation-only change. However, the PR includes production Go code changes (internal/normevent/event.go), new validation logic in Validate(), schema extensions (normalized-event.schema.json), new test (event_test.go), and a new example fixture. This is not documentation-only.
    Remediation: Change PR title prefix to match the actual scope, e.g. feat(normevent): add conversation entity kind support (ADR 0086).

Low

  • [consumer-completeness] internal/harnessdispatch/project.go:57buildEventPayload switches on event.Entity.Kind with cases for EntityWorkItem and EntityChangeProposal only. A conversation entity falls through silently, producing an empty payload. Once a gha-event Discussion adapter lands, dispatched conversation agents would receive an EventPayload with no entity identifier.
    Remediation: Add a case for EntityConversation or return an error for unhandled entity kinds.

  • [test-adequacy] internal/normevent/event_test.go:77 — The new TestParseJSON_ConversationExample test covers only the happy path. No tests for the three new Validate() error paths: (1) conversation entity without state.conversation, (2) conversation entity with empty category.name, (3) non-conversation entity with state.conversation present.


Labels: PR modifies Go production code and tests in internal/normevent/

Previous run (3)

Review

Findings

Medium

  • [stale-doc] docs/guides/user/cel-triggers-reference.md:51 — The CEL triggers reference documents event.entity.kind as having only two possible values (work_item, change_proposal). This PR extends the schema with a third value (conversation), making the reference incomplete. The NormalizedEvent fields table also omits the new event.state.conversation field, which is required when entity.kind is conversation.
    Remediation: Update the entity kind description to include conversation. Add event.state.conversation to the fields table alongside event.state.change_proposal.

  • [consumer-completeness] docs/normative/normalized-event/v1/examples/discussion-fs-vouch-comment.json — The new example fixture uses entity.kind: conversation and state.conversation, but TestParseJSON_Examples in internal/normevent/event_test.go iterates all .json files in the examples directory and calls ParseJSON through the Go normevent.Event struct. Since State lacks a Conversation field, Go silently discards state.conversation data. The test passes but validates a lossy representation.
    Remediation: Either update Go types before merging so the example round-trips faithfully, or exclude this fixture from the Go validation test with a TODO linking to the follow-up.

Low

  • [consumer-completeness] internal/harnessdispatch/project.go:57buildEventPayload switches on event.Entity.Kind with cases for EntityWorkItem and EntityChangeProposal only. A conversation entity kind would fall through silently. Expected for a schema-first PR; track as a follow-on implementation task.
  • [consumer-completeness] internal/normevent/event.go:119 — The Go State struct has no Conversation field and no EntityConversation constant. json.Unmarshal will silently drop state.conversation data and ToMap() will not include it in the CEL evaluation context. Follow-on task alongside the conversation adapter.
  • [naming-convention] docs/normative/normalized-event/v1/examples/discussion-fs-vouch-comment.json — Fixture is named discussion-fs-vouch-comment.json but the ADR introduces conversation as the forge-neutral entity kind. Existing gitlab-mr-* fixtures use backend-specific prefixes, so the current name is consistent with that precedent.
Previous run (4)

Review

Findings

Medium

  • [stale-doc] docs/guides/user/cel-triggers-reference.md — The CEL triggers reference documents event.entity.kind as having only two possible values (work_item, change_proposal). This PR extends the schema with a third value (conversation), making the reference incomplete. Users writing CEL triggers for conversation-native agents will not find the new value or event.state.conversation documented there.
    Remediation: Update the NormalizedEvent fields table to add conversation as a third entity kind value and add event.state.conversation to the fields table.

Low

  • [consumer-completeness] internal/harnessdispatch/project.go:57buildEventPayload switches on event.Entity.Kind with cases for EntityWorkItem and EntityChangeProposal only. A conversation entity kind would fall through silently. Expected for a schema-first PR; track as a follow-on implementation task.
  • [consumer-completeness] internal/normevent/event.go:119 — The Go State struct has no Conversation field. Until updated, json.Unmarshal will silently drop state.conversation data and the CEL context will not contain conversation metadata. Follow-on task alongside the conversation adapter.
  • [consumer-completeness] internal/normevent/event.go:24 — No EntityConversation Go constant exists for the new "conversation" entity kind. Follow-on task.
  • [edge-case] docs/normative/normalized-event/v1/examples/discussion-fs-vouch-comment.json:3 — The actor.is_entity_author schema description mentions only "work item or change proposal" — does not include conversation. Minor description staleness with no functional impact.
  • [internal-consistency] docs/ADRs/0086-conversation-surface-for-agent-participation.md:97 — Architecture seams item 3 states "entity-context rules keep code-mutating slash commands off conversations" but does not trace the enforcement path. ADR 0076 establishes CEL triggers as the target-state mechanism; a cross-reference would clarify.

Labels: PR modifies documentation files (ADRs, architecture docs, normative spec, and schema)

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added requires-manual-review Review requires human judgment component/docs User-facing documentation labels Aug 11, 2026
Comment thread docs/normative/normalized-event/v1/normalized-event.schema.json
Document that GitHub DiscussionCategory only exposes isAnswerable for
format derivation, drop implied announcement/poll API mapping, and
address low review nits on is_entity_author and ADR 0076 CEL enforcement.

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

fullsend-ai-review Bot commented Aug 11, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 6:13 PM UTC · Completed 6:32 PM UTC

Commit: a3167c2 · View workflow run →

Comment thread docs/normative/normalized-event/v1/normalized-event.schema.json
Comment thread docs/normative/normalized-event/v1/normalized-event.schema.json Outdated
Comment thread docs/normative/normalized-event/v1/normalized-event.schema.json
Comment thread docs/ADRs/0086-conversation-surface-for-agent-participation.md Outdated
Comment thread docs/normative/normalized-event/v1/README.md Outdated
Comment thread docs/architecture.md Outdated
Comment thread docs/normative/normalized-event/v1/normalized-event.schema.json Outdated
Resolve architecture.md conflict with upstream, forbid state.conversation
on non-conversation entities, clarify GitHub slug/format data sources,
update CEL trigger docs, and teach normevent.Event about conversation
state so example fixtures round-trip.

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

Copy link
Copy Markdown
Member Author

Also addressed the earlier review-agent medium findings in f2cbdda:

  • Updated docs/guides/user/cel-triggers-reference.md for conversation / state.conversation
  • Added normevent Conversation types + validation so discussion-fs-vouch-comment.json round-trips in TestParseJSON_Examples

@fullsend-ai-review

fullsend-ai-review Bot commented Aug 18, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 9:44 AM UTC · Ended 9:53 AM UTC

Commit: f2cbdda · View workflow run →

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

fullsend-ai-review Bot commented Aug 18, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 9:54 AM UTC · Completed 10:11 AM UTC

Commit: d6ff96e · View workflow run →

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added the go Pull requests that update go code label Aug 18, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 18, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 11:11 AM UTC · Ended 11:22 AM UTC

Commit: dc083a0 · View workflow run →

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

fullsend-ai-review Bot commented Aug 18, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 11:22 AM UTC · Completed 11:35 AM UTC

Commit: ccf2212 · View workflow run →

@waynesun09 waynesun09 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Approving at head ccf2212b. Design review below — nothing blocking; the non-blocking points are follow-on requirements to keep in view when the implementation PRs land.

What this ADR decides (and what it deliberately does not)

The chosen Option D — a narrow conversation.Client parallel to tracker.Client, entity.kind: conversation on NormalizedEvent v1, auth reused from ADR 0054, category ≠ label — is the right seam and consistent with the #5988 split. Note for readers coming from the "plan with an agent in a Discussion, then hand off to /fs-code" use case: this ADR establishes the participation surface only. The Discussion → work-item handoff is explicitly a follow-on (Consequences, last bullet; architecture.md open question). When it lands it goes through tracker.Client (issue create + cross-link) with an issues:write identity delta, not through conversation.Client. Worth keeping that sequencing honest in the implementation tracker.

Design scrutiny (non-blocking)

  1. Enforcement sequencing. The ADR relies on CEL trigger over entity.kind (ADR 0076 target state) to keep code-mutating commands off conversations. Today no harness in fullsend-ai/agents carries a trigger: expression, and internal/harnessdispatch/project.go (buildEventPayload, triggerSource) only knows work_item / change_proposal. So the Discussion adapter PR must ship together with (a) entity-kind guards on the coder/fix/review paths and (b) conversation payload projection — otherwise /fs-code typed in a Discussion would route to the coder with an empty entity payload. Suggest stating that ordering requirement in the implementation issue.
  2. Threading granularity. transition.comment carries no parent/thread id. GitHub Discussions have two-level replies, and the ADR maps a Slack thread to a conversation — so a GitHub reply-thread has no analogue and an agent cannot know which sub-thread to answer in. An optional transition.comment.parent_id (or thread id) later is an additive, non-breaking schema change; fine to defer, but it will be needed for any real multi-turn session.
  3. Identifier portability. entity.id is an integer and entity.key is Jira-shaped (^[A-Za-z][A-Za-z0-9_]+-\d+$). Slack/Discord/Matrix thread ids fit neither, so the portability claim has no identifier carrier yet for non-numeric backends. One-line note for the Slack follow-on.
  4. Identity delta. Confirmed no mint role grants discussions today (internal/mintcore/github.go role table), so the open question in architecture.md is accurate; a conversation-class role (or per-role discussions: write) is a prerequisite for any writeback.
  5. Multi-turn cost/concurrency. With Option B rejected, every message is a full dispatch; two quick replies on the same conversation produce two concurrent runs. Existing per-entity locking/cancel semantics (as for /fs-fix) should be stated as applying per conversation when the adapter lands.

Open bot findings at head — neither is major: the review-agent Medium about the docs(adr): title vs. production Go/schema changes is fair (consider feat(normevent): … before merge); the Low about buildEventPayload is the same latent gap as point 1.

ifireball and others added 3 commits August 19, 2026 23:35
Align ADR 0086 with Slack conversation/thread naming and GitHub
discussion_comment parent pointers. Require comment.id and
parent_id (parent_id == id on thread roots) instead of
state.conversation.thread.

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

fullsend-ai-review Bot commented Aug 19, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 9:08 PM UTC · Completed 9:26 PM UTC

Commit: a65c62e · View workflow run →

@ifireball
ifireball added this pull request to the merge queue Aug 20, 2026
Merged via the queue into fullsend-ai:main with commit aa785a9 Aug 20, 2026
14 checks passed
@ifireball
ifireball deleted the cursor/726ecc8c branch August 20, 2026 07:41
ralphbean added a commit that referenced this pull request Aug 21, 2026
After rebasing on main, Comment.ID changed from int to string per ADR 0086
(conversation support via #6083). Update all code paths:

- ghaevent.go: convert intField result to string with strconv.Itoa
- project.go: check Comment.ID != "" instead of != 0
- project_test.go, ghaevent_test.go: update test assertions to expect string
- cleanup_test.go: add ListIssueReactions stub to fakeRetryCleanupSCM

Assisted-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
ralphbean added a commit that referenced this pull request Aug 21, 2026
After rebasing on main, Comment.ID changed from int to string per ADR 0086
(conversation support via #6083). Update all code paths:

- ghaevent.go: convert intField result to string with strconv.Itoa
- project.go: check Comment.ID != "" instead of != 0
- project_test.go, ghaevent_test.go: update test assertions to expect string
- cleanup_test.go: add ListIssueReactions stub to fakeRetryCleanupSCM

Assisted-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/docs User-facing documentation go Pull requests that update go code requires-manual-review Review requires human judgment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants