[codex] Add structured issue-thread interactions (#4244)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies.
> - Operators supervise that work through issues, comments, approvals,
and the board UI.
> - Some agent proposals need structured board/user decisions, not
hidden markdown conventions or heavyweight governed approvals.
> - Issue-thread interactions already provide a natural thread-native
surface for proposed tasks and questions.
> - This pull request extends that surface with request confirmations,
richer interaction cards, and agent/plugin/MCP helpers.
> - The benefit is that plan approvals and yes/no decisions become
explicit, auditable, and resumable without losing the single-issue
workflow.
## What Changed
- Added persisted issue-thread interactions for suggested tasks,
structured questions, and request confirmations.
- Added board UI cards for interaction review, selection, question
answers, and accept/reject confirmation flows.
- Added MCP and plugin SDK helpers for creating interaction cards from
agents/plugins.
- Updated agent wake instructions, onboarding assets, Paperclip skill
docs, and public docs to prefer structured confirmations for
issue-scoped decisions.
- Rebased the branch onto `public-gh/master` and renumbered branch
migrations to `0063` and `0064`; the idempotency migration uses `ADD
COLUMN IF NOT EXISTS` for old branch users.
## Verification
- `git diff --check public-gh/master..HEAD`
- `pnpm exec vitest run packages/adapter-utils/src/server-utils.test.ts
packages/mcp-server/src/tools.test.ts
packages/shared/src/issue-thread-interactions.test.ts
ui/src/lib/issue-thread-interactions.test.ts
ui/src/lib/issue-chat-messages.test.ts
ui/src/components/IssueThreadInteractionCard.test.tsx
ui/src/components/IssueChatThread.test.tsx
server/src/__tests__/issue-thread-interaction-routes.test.ts
server/src/__tests__/issue-thread-interactions-service.test.ts
server/src/services/issue-thread-interactions.test.ts` -> 9 files / 79
tests passed
- `pnpm -r typecheck` -> passed, including `packages/db` migration
numbering check
## Risks
- Medium: this adds a new issue-thread interaction model across
db/shared/server/ui/plugin surfaces.
- Migration risk is reduced by placing this branch after current master
migrations (`0063`, `0064`) and making the idempotency column add
idempotent for users who applied the old branch numbering.
- UI interaction behavior is covered by component tests, but this PR
does not include browser screenshots.
> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.
## Model Used
- OpenAI Codex, GPT-5-class coding agent runtime. Exact model ID and
context window are not exposed in this Paperclip run; tool use and local
shell/code execution were enabled.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-21 20:15:11 -05:00
import type { LiveRunForIssue } from "../api/heartbeats" ;
import type {
IssueChatComment ,
IssueChatTranscriptEntry ,
} from "../lib/issue-chat-messages" ;
import type { IssueTimelineEvent } from "../lib/issue-timeline-events" ;
import type {
AskUserQuestionsInteraction ,
RequestConfirmationInteraction ,
SuggestTasksInteraction ,
} from "../lib/issue-thread-interactions" ;
export const issueThreadInteractionFixtureMeta = {
companyId : "company-storybook" ,
projectId : "project-board-ui" ,
issueId : "issue-thread-interactions" ,
currentUserId : "user-board" ,
} as const ;
function createComment ( overrides : Partial < IssueChatComment > ) : IssueChatComment {
const createdAt = overrides . createdAt ? ? new Date ( "2026-04-20T14:00:00.000Z" ) ;
return {
id : "comment-default" ,
companyId : issueThreadInteractionFixtureMeta.companyId ,
issueId : issueThreadInteractionFixtureMeta.issueId ,
Add recovery handoff system notices (#5289)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies.
> - Agent runs can end productively while the source issue still lacks a
durable final disposition.
> - That leaves the control plane unsure whether to resume, escalate, or
close the work.
> - Issue comments also need a presentation contract so system-authored
recovery notices can render as first-class thread messages without
overloading normal comments.
> - This pull request adds successful-run handoff recovery, comment
presentation metadata, and system notice rendering.
> - The benefit is stricter task liveness with clearer operator-facing
recovery state.
## What Changed
- Added successful-run handoff decisions, wake payloads, escalation
behavior, and recovery tests.
- Added issue comment presentation metadata with migration
`0078_white_darwin.sql` and shared/server/company portability support.
- Rendered recovery/system notices in issue chat with dedicated UI
components, fixtures, tests, and storybook/lab coverage.
- Included the current recovery model-profile hint patch so automatic
recovery follow-ups use the cheap profile.
## Verification
- `pnpm install --frozen-lockfile`
- `pnpm exec vitest run
server/src/services/recovery/successful-run-handoff.test.ts
ui/src/components/SystemNotice.test.tsx
ui/src/lib/system-notice-comment.test.ts
ui/src/components/IssueChatThreadSystemNotice.test.tsx`
## Risks
- Migration-bearing PR: merge this before any other branch that might
later add a migration.
- The branch touches both recovery services and issue-thread rendering,
so review should pay attention to recovery wake idempotency and comment
metadata compatibility.
## Model Used
- OpenAI GPT-5 Codex via Paperclip `codex_local` adapter, with
shell/git/GitHub CLI tool use.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-05-06 06:05:58 -05:00
authorType : overrides.authorAgentId ? "agent" : "user" ,
[codex] Add structured issue-thread interactions (#4244)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies.
> - Operators supervise that work through issues, comments, approvals,
and the board UI.
> - Some agent proposals need structured board/user decisions, not
hidden markdown conventions or heavyweight governed approvals.
> - Issue-thread interactions already provide a natural thread-native
surface for proposed tasks and questions.
> - This pull request extends that surface with request confirmations,
richer interaction cards, and agent/plugin/MCP helpers.
> - The benefit is that plan approvals and yes/no decisions become
explicit, auditable, and resumable without losing the single-issue
workflow.
## What Changed
- Added persisted issue-thread interactions for suggested tasks,
structured questions, and request confirmations.
- Added board UI cards for interaction review, selection, question
answers, and accept/reject confirmation flows.
- Added MCP and plugin SDK helpers for creating interaction cards from
agents/plugins.
- Updated agent wake instructions, onboarding assets, Paperclip skill
docs, and public docs to prefer structured confirmations for
issue-scoped decisions.
- Rebased the branch onto `public-gh/master` and renumbered branch
migrations to `0063` and `0064`; the idempotency migration uses `ADD
COLUMN IF NOT EXISTS` for old branch users.
## Verification
- `git diff --check public-gh/master..HEAD`
- `pnpm exec vitest run packages/adapter-utils/src/server-utils.test.ts
packages/mcp-server/src/tools.test.ts
packages/shared/src/issue-thread-interactions.test.ts
ui/src/lib/issue-thread-interactions.test.ts
ui/src/lib/issue-chat-messages.test.ts
ui/src/components/IssueThreadInteractionCard.test.tsx
ui/src/components/IssueChatThread.test.tsx
server/src/__tests__/issue-thread-interaction-routes.test.ts
server/src/__tests__/issue-thread-interactions-service.test.ts
server/src/services/issue-thread-interactions.test.ts` -> 9 files / 79
tests passed
- `pnpm -r typecheck` -> passed, including `packages/db` migration
numbering check
## Risks
- Medium: this adds a new issue-thread interaction model across
db/shared/server/ui/plugin surfaces.
- Migration risk is reduced by placing this branch after current master
migrations (`0063`, `0064`) and making the idempotency column add
idempotent for users who applied the old branch numbering.
- UI interaction behavior is covered by component tests, but this PR
does not include browser screenshots.
> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.
## Model Used
- OpenAI Codex, GPT-5-class coding agent runtime. Exact model ID and
context window are not exposed in this Paperclip run; tool use and local
shell/code execution were enabled.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-21 20:15:11 -05:00
authorAgentId : null ,
authorUserId : issueThreadInteractionFixtureMeta.currentUserId ,
body : "" ,
Add recovery handoff system notices (#5289)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies.
> - Agent runs can end productively while the source issue still lacks a
durable final disposition.
> - That leaves the control plane unsure whether to resume, escalate, or
close the work.
> - Issue comments also need a presentation contract so system-authored
recovery notices can render as first-class thread messages without
overloading normal comments.
> - This pull request adds successful-run handoff recovery, comment
presentation metadata, and system notice rendering.
> - The benefit is stricter task liveness with clearer operator-facing
recovery state.
## What Changed
- Added successful-run handoff decisions, wake payloads, escalation
behavior, and recovery tests.
- Added issue comment presentation metadata with migration
`0078_white_darwin.sql` and shared/server/company portability support.
- Rendered recovery/system notices in issue chat with dedicated UI
components, fixtures, tests, and storybook/lab coverage.
- Included the current recovery model-profile hint patch so automatic
recovery follow-ups use the cheap profile.
## Verification
- `pnpm install --frozen-lockfile`
- `pnpm exec vitest run
server/src/services/recovery/successful-run-handoff.test.ts
ui/src/components/SystemNotice.test.tsx
ui/src/lib/system-notice-comment.test.ts
ui/src/components/IssueChatThreadSystemNotice.test.tsx`
## Risks
- Migration-bearing PR: merge this before any other branch that might
later add a migration.
- The branch touches both recovery services and issue-thread rendering,
so review should pay attention to recovery wake idempotency and comment
metadata compatibility.
## Model Used
- OpenAI GPT-5 Codex via Paperclip `codex_local` adapter, with
shell/git/GitHub CLI tool use.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-05-06 06:05:58 -05:00
presentation : null ,
metadata : null ,
[codex] Add structured issue-thread interactions (#4244)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies.
> - Operators supervise that work through issues, comments, approvals,
and the board UI.
> - Some agent proposals need structured board/user decisions, not
hidden markdown conventions or heavyweight governed approvals.
> - Issue-thread interactions already provide a natural thread-native
surface for proposed tasks and questions.
> - This pull request extends that surface with request confirmations,
richer interaction cards, and agent/plugin/MCP helpers.
> - The benefit is that plan approvals and yes/no decisions become
explicit, auditable, and resumable without losing the single-issue
workflow.
## What Changed
- Added persisted issue-thread interactions for suggested tasks,
structured questions, and request confirmations.
- Added board UI cards for interaction review, selection, question
answers, and accept/reject confirmation flows.
- Added MCP and plugin SDK helpers for creating interaction cards from
agents/plugins.
- Updated agent wake instructions, onboarding assets, Paperclip skill
docs, and public docs to prefer structured confirmations for
issue-scoped decisions.
- Rebased the branch onto `public-gh/master` and renumbered branch
migrations to `0063` and `0064`; the idempotency migration uses `ADD
COLUMN IF NOT EXISTS` for old branch users.
## Verification
- `git diff --check public-gh/master..HEAD`
- `pnpm exec vitest run packages/adapter-utils/src/server-utils.test.ts
packages/mcp-server/src/tools.test.ts
packages/shared/src/issue-thread-interactions.test.ts
ui/src/lib/issue-thread-interactions.test.ts
ui/src/lib/issue-chat-messages.test.ts
ui/src/components/IssueThreadInteractionCard.test.tsx
ui/src/components/IssueChatThread.test.tsx
server/src/__tests__/issue-thread-interaction-routes.test.ts
server/src/__tests__/issue-thread-interactions-service.test.ts
server/src/services/issue-thread-interactions.test.ts` -> 9 files / 79
tests passed
- `pnpm -r typecheck` -> passed, including `packages/db` migration
numbering check
## Risks
- Medium: this adds a new issue-thread interaction model across
db/shared/server/ui/plugin surfaces.
- Migration risk is reduced by placing this branch after current master
migrations (`0063`, `0064`) and making the idempotency column add
idempotent for users who applied the old branch numbering.
- UI interaction behavior is covered by component tests, but this PR
does not include browser screenshots.
> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.
## Model Used
- OpenAI Codex, GPT-5-class coding agent runtime. Exact model ID and
context window are not exposed in this Paperclip run; tool use and local
shell/code execution were enabled.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-21 20:15:11 -05:00
createdAt ,
updatedAt : overrides.updatedAt ? ? createdAt ,
. . . overrides ,
} ;
}
function createSuggestTasksInteraction (
overrides : Partial < SuggestTasksInteraction > ,
) : SuggestTasksInteraction {
return {
id : "interaction-suggest-default" ,
companyId : issueThreadInteractionFixtureMeta.companyId ,
issueId : issueThreadInteractionFixtureMeta.issueId ,
kind : "suggest_tasks" ,
title : "Suggested issue tree for the first interaction pass" ,
summary :
"Draft task creation stays pending until a reviewer accepts it, so the thread can preview structure without mutating the task system." ,
status : "pending" ,
continuationPolicy : "wake_assignee" ,
createdByAgentId : "agent-codex" ,
createdByUserId : null ,
resolvedByAgentId : null ,
resolvedByUserId : null ,
createdAt : new Date ( "2026-04-20T14:11:00.000Z" ) ,
updatedAt : new Date ( "2026-04-20T14:11:00.000Z" ) ,
resolvedAt : null ,
payload : {
version : 1 ,
defaultParentId : "PAP-1709" ,
tasks : [
{
clientKey : "root-design" ,
title : "Prototype issue-thread interaction cards" ,
description :
"Build render-only cards that sit in the issue feed and show suggested tasks before anything is persisted." ,
priority : "high" ,
assigneeAgentId : "agent-codex" ,
billingCode : "ui-research" ,
labels : [ "UI" , "interaction" ] ,
} ,
{
clientKey : "child-stories" ,
parentClientKey : "root-design" ,
title : "Add Storybook coverage for acceptance and rejection states" ,
description :
"Cover pending, accepted, rejected, and collapsed-child previews in a fixture-backed story." ,
priority : "medium" ,
assigneeAgentId : "agent-qa" ,
labels : [ "Storybook" ] ,
} ,
{
clientKey : "child-mixed-thread" ,
parentClientKey : "root-design" ,
title : "Prototype the mixed thread feed" ,
description :
"Show comments, activity, live runs, and interaction cards in one chronological feed." ,
priority : "medium" ,
assigneeAgentId : "agent-codex" ,
labels : [ "Issue thread" ] ,
} ,
{
clientKey : "hidden-follow-up" ,
parentClientKey : "child-mixed-thread" ,
title : "Follow-up polish on spacing and answered summaries" ,
description :
"Collapse this under the visible task tree so the preview proves the hidden-descendant treatment." ,
priority : "low" ,
hiddenInPreview : true ,
} ,
] ,
} ,
result : null ,
. . . overrides ,
} ;
}
function createAskUserQuestionsInteraction (
overrides : Partial < AskUserQuestionsInteraction > ,
) : AskUserQuestionsInteraction {
return {
id : "interaction-questions-default" ,
companyId : issueThreadInteractionFixtureMeta.companyId ,
issueId : issueThreadInteractionFixtureMeta.issueId ,
kind : "ask_user_questions" ,
title : "Resolve open UX decisions before Phase 1" ,
summary :
"This form stays local until the operator submits it, so the assignee only wakes once after the whole answer set is ready." ,
status : "pending" ,
continuationPolicy : "wake_assignee" ,
createdByAgentId : "agent-codex" ,
createdByUserId : null ,
resolvedByAgentId : null ,
resolvedByUserId : null ,
createdAt : new Date ( "2026-04-20T14:18:00.000Z" ) ,
updatedAt : new Date ( "2026-04-20T14:18:00.000Z" ) ,
resolvedAt : null ,
payload : {
version : 1 ,
title : "Before I wire the persistence layer, which preview behavior do you want?" ,
submitLabel : "Send answers" ,
questions : [
{
id : "collapse-depth" ,
prompt : "How aggressive should the suggested-task preview collapse descendant work?" ,
helpText :
"We need enough context to review the tree without making the feed feel like a project plan." ,
selectionMode : "single" ,
required : true ,
options : [
{
id : "visible-root" ,
label : "Only collapse hidden descendants" ,
description : "Keep top-level and visible child tasks expanded." ,
} ,
{
id : "collapse-all" ,
label : "Collapse all descendants by default" ,
description : "Show only root tasks until the operator expands the tree." ,
} ,
] ,
} ,
{
id : "post-submit-summary" ,
prompt : "What should the answered-state card emphasize after submission?" ,
helpText : "Pick every summary treatment that would help future reviewers." ,
selectionMode : "multi" ,
required : true ,
options : [
{
id : "answers-inline" ,
label : "Inline answer pills" ,
description : "Keep the exact operator choices visible under each question." ,
} ,
{
id : "summary-note" ,
label : "Short markdown summary" ,
description : "Add a compact narrative summary at the bottom of the card." ,
} ,
{
id : "resolver-meta" ,
label : "Resolver metadata" ,
description : "Show who answered and when without opening the raw thread." ,
} ,
] ,
} ,
] ,
} ,
result : null ,
. . . overrides ,
} ;
}
function createRequestConfirmationInteraction (
overrides : Partial < RequestConfirmationInteraction > ,
) : RequestConfirmationInteraction {
return {
id : "interaction-confirmation-default" ,
companyId : issueThreadInteractionFixtureMeta.companyId ,
issueId : issueThreadInteractionFixtureMeta.issueId ,
kind : "request_confirmation" ,
title : "Approve the proposed plan" ,
summary :
"The assignee is waiting on a direct board decision before continuing from the plan document." ,
status : "pending" ,
continuationPolicy : "wake_assignee" ,
createdByAgentId : "agent-codex" ,
createdByUserId : null ,
resolvedByAgentId : null ,
resolvedByUserId : null ,
createdAt : new Date ( "2026-04-20T14:30:00.000Z" ) ,
updatedAt : new Date ( "2026-04-20T14:30:00.000Z" ) ,
resolvedAt : null ,
payload : {
version : 1 ,
prompt : "Approve the plan and let the assignee start implementation?" ,
acceptLabel : "Approve plan" ,
rejectLabel : "Request revisions" ,
rejectRequiresReason : true ,
rejectReasonLabel : "Describe the plan changes needed before approval" ,
detailsMarkdown :
"This confirmation watches the `plan` document revision so stale approvals are blocked if the plan changes." ,
supersedeOnUserComment : true ,
target : {
type : "issue_document" ,
issueId : issueThreadInteractionFixtureMeta.issueId ,
key : "plan" ,
revisionId : "11111111-1111-4111-8111-111111111111" ,
revisionNumber : 3 ,
} ,
} ,
result : null ,
. . . overrides ,
} ;
}
export const pendingSuggestedTasksInteraction = createSuggestTasksInteraction ( { } ) ;
export const acceptedSuggestedTasksInteraction = createSuggestTasksInteraction ( {
id : "interaction-suggest-accepted" ,
status : "accepted" ,
resolvedByUserId : issueThreadInteractionFixtureMeta.currentUserId ,
resolvedAt : new Date ( "2026-04-20T14:16:00.000Z" ) ,
updatedAt : new Date ( "2026-04-20T14:16:00.000Z" ) ,
result : {
version : 1 ,
createdTasks : [
{
clientKey : "root-design" ,
issueId : "issue-created-1" ,
identifier : "PAP-1713" ,
title : "Prototype issue-thread interaction cards" ,
} ,
{
clientKey : "child-stories" ,
issueId : "issue-created-2" ,
identifier : "PAP-1714" ,
title : "Add Storybook coverage for acceptance and rejection states" ,
parentIssueId : "issue-created-1" ,
parentIdentifier : "PAP-1713" ,
} ,
{
clientKey : "child-mixed-thread" ,
issueId : "issue-created-3" ,
identifier : "PAP-1715" ,
title : "Prototype the mixed thread feed" ,
parentIssueId : "issue-created-1" ,
parentIdentifier : "PAP-1713" ,
} ,
{
clientKey : "hidden-follow-up" ,
issueId : "issue-created-4" ,
identifier : "PAP-1716" ,
title : "Follow-up polish on spacing and answered summaries" ,
parentIssueId : "issue-created-3" ,
parentIdentifier : "PAP-1715" ,
} ,
] ,
} ,
} ) ;
export const rejectedSuggestedTasksInteraction = createSuggestTasksInteraction ( {
id : "interaction-suggest-rejected" ,
status : "rejected" ,
resolvedByUserId : issueThreadInteractionFixtureMeta.currentUserId ,
resolvedAt : new Date ( "2026-04-20T14:17:00.000Z" ) ,
updatedAt : new Date ( "2026-04-20T14:17:00.000Z" ) ,
result : {
version : 1 ,
rejectionReason :
"Keep the first pass tighter. The hidden follow-on work is useful, but the acceptance story should stay focused on one visible root and one visible child." ,
} ,
} ) ;
export const pendingAskUserQuestionsInteraction = createAskUserQuestionsInteraction ( { } ) ;
export const answeredAskUserQuestionsInteraction = createAskUserQuestionsInteraction ( {
id : "interaction-questions-answered" ,
status : "answered" ,
resolvedByUserId : issueThreadInteractionFixtureMeta.currentUserId ,
resolvedAt : new Date ( "2026-04-20T14:24:00.000Z" ) ,
updatedAt : new Date ( "2026-04-20T14:24:00.000Z" ) ,
result : {
version : 1 ,
answers : [
{
questionId : "collapse-depth" ,
optionIds : [ "visible-root" ] ,
} ,
{
questionId : "post-submit-summary" ,
optionIds : [ "answers-inline" , "summary-note" , "resolver-meta" ] ,
} ,
] ,
summaryMarkdown : [
"- Keep visible child tasks expanded when they are part of the main review path." ,
"- Preserve inline answer chips and resolver metadata in the answered state." ,
"- Add a short summary note so future reviewers understand the operator's intent without replaying the form." ,
] . join ( "\n" ) ,
} ,
} ) ;
export const pendingRequestConfirmationInteraction = createRequestConfirmationInteraction ( { } ) ;
export const genericPendingRequestConfirmationInteraction = createRequestConfirmationInteraction ( {
id : "interaction-confirmation-generic-pending" ,
title : "Confirm next step" ,
summary : "The assignee needs a lightweight yes or no before continuing." ,
continuationPolicy : "none" ,
payload : {
version : 1 ,
prompt : "Continue with the current approach?" ,
} ,
} ) ;
export const optionalDeclineRequestConfirmationInteraction = createRequestConfirmationInteraction ( {
id : "interaction-confirmation-optional-decline" ,
continuationPolicy : "none" ,
payload : {
version : 1 ,
prompt : "Use the smaller implementation path?" ,
acceptLabel : "Confirm" ,
rejectLabel : "Decline" ,
rejectRequiresReason : false ,
declineReasonPlaceholder : "Optional: tell the agent what you'd change." ,
} ,
} ) ;
export const disabledDeclineReasonRequestConfirmationInteraction = createRequestConfirmationInteraction ( {
id : "interaction-confirmation-no-decline-reason" ,
continuationPolicy : "none" ,
payload : {
version : 1 ,
prompt : "Close this low-risk follow-up as unnecessary?" ,
acceptLabel : "Close it" ,
rejectLabel : "Keep it" ,
allowDeclineReason : false ,
} ,
} ) ;
export const acceptedRequestConfirmationInteraction = createRequestConfirmationInteraction ( {
id : "interaction-confirmation-accepted" ,
status : "accepted" ,
resolvedByUserId : issueThreadInteractionFixtureMeta.currentUserId ,
resolvedAt : new Date ( "2026-04-20T14:34:00.000Z" ) ,
updatedAt : new Date ( "2026-04-20T14:34:00.000Z" ) ,
result : {
version : 1 ,
outcome : "accepted" ,
} ,
} ) ;
export const planApprovalAcceptedRequestConfirmationInteraction = createRequestConfirmationInteraction ( {
id : "interaction-confirmation-plan-accepted" ,
status : "accepted" ,
resolvedByUserId : issueThreadInteractionFixtureMeta.currentUserId ,
resolvedAt : new Date ( "2026-04-20T14:34:00.000Z" ) ,
updatedAt : new Date ( "2026-04-20T14:34:00.000Z" ) ,
payload : {
version : 1 ,
prompt : "Approve the plan and let the assignee start implementation?" ,
acceptLabel : "Approve plan" ,
rejectLabel : "Request changes" ,
rejectRequiresReason : true ,
declineReasonPlaceholder : "Optional: what would you like revised?" ,
target : {
type : "issue_document" ,
issueId : issueThreadInteractionFixtureMeta.issueId ,
key : "plan" ,
revisionId : "11111111-1111-4111-8111-111111111111" ,
revisionNumber : 4 ,
} ,
} ,
result : {
version : 1 ,
outcome : "accepted" ,
} ,
} ) ;
export const rejectedRequestConfirmationInteraction = createRequestConfirmationInteraction ( {
id : "interaction-confirmation-rejected" ,
status : "rejected" ,
resolvedByUserId : issueThreadInteractionFixtureMeta.currentUserId ,
resolvedAt : new Date ( "2026-04-20T14:36:00.000Z" ) ,
updatedAt : new Date ( "2026-04-20T14:36:00.000Z" ) ,
result : {
version : 1 ,
outcome : "rejected" ,
reason : "Split the migration and UI work into separate reviewable steps." ,
} ,
} ) ;
export const rejectedNoReasonRequestConfirmationInteraction = createRequestConfirmationInteraction ( {
id : "interaction-confirmation-rejected-no-reason" ,
status : "rejected" ,
resolvedByUserId : issueThreadInteractionFixtureMeta.currentUserId ,
resolvedAt : new Date ( "2026-04-20T14:37:00.000Z" ) ,
updatedAt : new Date ( "2026-04-20T14:37:00.000Z" ) ,
result : {
version : 1 ,
outcome : "rejected" ,
reason : null ,
} ,
} ) ;
export const commentExpiredRequestConfirmationInteraction = createRequestConfirmationInteraction ( {
id : "interaction-confirmation-expired-comment" ,
status : "expired" ,
resolvedByUserId : issueThreadInteractionFixtureMeta.currentUserId ,
resolvedAt : new Date ( "2026-04-20T14:38:00.000Z" ) ,
updatedAt : new Date ( "2026-04-20T14:38:00.000Z" ) ,
result : {
version : 1 ,
outcome : "superseded_by_comment" ,
commentId : "22222222-2222-4222-8222-222222222222" ,
} ,
} ) ;
export const staleTargetRequestConfirmationInteraction = createRequestConfirmationInteraction ( {
id : "interaction-confirmation-expired-target" ,
status : "expired" ,
resolvedByAgentId : "agent-codex" ,
resolvedAt : new Date ( "2026-04-20T14:40:00.000Z" ) ,
updatedAt : new Date ( "2026-04-20T14:40:00.000Z" ) ,
payload : {
version : 1 ,
prompt : "Approve the plan and let the assignee start implementation?" ,
acceptLabel : "Approve plan" ,
rejectLabel : "Request revisions" ,
rejectRequiresReason : true ,
target : {
type : "issue_document" ,
issueId : issueThreadInteractionFixtureMeta.issueId ,
key : "plan" ,
revisionId : "44444444-4444-4444-8444-444444444444" ,
revisionNumber : 4 ,
} ,
} ,
result : {
version : 1 ,
outcome : "stale_target" ,
staleTarget : {
type : "issue_document" ,
issueId : issueThreadInteractionFixtureMeta.issueId ,
key : "plan" ,
revisionId : "11111111-1111-4111-8111-111111111111" ,
revisionNumber : 3 ,
} ,
} ,
} ) ;
export const failedRequestConfirmationInteraction = createRequestConfirmationInteraction ( {
id : "interaction-confirmation-failed" ,
status : "failed" ,
updatedAt : new Date ( "2026-04-20T14:42:00.000Z" ) ,
} ) ;
export const issueThreadInteractionComments : IssueChatComment [ ] = [
createComment ( {
id : "comment-thread-board" ,
body : "Pressure-test first-class issue-thread interactions before we touch persistence. I want to see the cards in the real feed, not in a disconnected mock." ,
createdAt : new Date ( "2026-04-20T14:02:00.000Z" ) ,
updatedAt : new Date ( "2026-04-20T14:02:00.000Z" ) ,
} ) ,
createComment ( {
id : "comment-thread-agent" ,
authorAgentId : "agent-codex" ,
authorUserId : null ,
body : "I found the existing issue chat surface and I am adding prototype-only interaction records so the Storybook review can happen before persistence work." ,
createdAt : new Date ( "2026-04-20T14:09:00.000Z" ) ,
updatedAt : new Date ( "2026-04-20T14:09:00.000Z" ) ,
runId : "run-thread-interaction" ,
runAgentId : "agent-codex" ,
} ) ,
] ;
export const issueThreadInteractionEvents : IssueTimelineEvent [ ] = [
{
id : "event-thread-checkout" ,
createdAt : new Date ( "2026-04-20T14:01:00.000Z" ) ,
actorType : "user" ,
actorId : issueThreadInteractionFixtureMeta.currentUserId ,
statusChange : {
from : "todo" ,
to : "in_progress" ,
} ,
} ,
] ;
export const issueThreadInteractionLiveRuns : LiveRunForIssue [ ] = [
{
id : "run-thread-live" ,
status : "running" ,
invocationSource : "manual" ,
triggerDetail : null ,
startedAt : "2026-04-20T14:26:00.000Z" ,
finishedAt : null ,
createdAt : "2026-04-20T14:26:00.000Z" ,
agentId : "agent-codex" ,
agentName : "CodexCoder" ,
adapterType : "codex_local" ,
} ,
] ;
export const issueThreadInteractionTranscriptsByRunId = new Map <
string ,
readonly IssueChatTranscriptEntry [ ]
> ( [
[
"run-thread-live" ,
[
{
kind : "assistant" ,
ts : "2026-04-20T14:26:02.000Z" ,
text : "Wiring the prototype interaction cards into the same issue feed that already renders comments and live runs." ,
} ,
{
kind : "thinking" ,
ts : "2026-04-20T14:26:04.000Z" ,
text : "Need to keep the payload shapes local to the UI layer so Phase 0 stays non-persistent." ,
} ,
] ,
] ,
] ) ;
export const mixedIssueThreadInteractions = [
acceptedSuggestedTasksInteraction ,
pendingRequestConfirmationInteraction ,
pendingAskUserQuestionsInteraction ,
] ;