mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-04 02:32:07 +01:00
fix(server): recover lost human feedback delivery
Replay feedback lost before process launch, reconcile stranded review feedback, and project durable delivery state onto source comments. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
623f7aa555
commit
a6c28fa414
16 files changed
+3762
-33
No files matched your search
@@ -376,6 +376,7 @@ export const ISSUE_SURFACE_VISIBILITIES = ["default", "plugin_operation"] as con
|
||||
export type IssueSurfaceVisibility = (typeof ISSUE_SURFACE_VISIBILITIES)[number];
|
||||
|
||||
export const ISSUE_RECOVERY_ACTION_KINDS = [
|
||||
"feedback_delivery",
|
||||
"missing_disposition",
|
||||
"stranded_assigned_issue",
|
||||
"workspace_validation",
|
||||
@@ -401,6 +402,23 @@ export const ISSUE_RECOVERY_ACTION_OWNER_TYPES = [
|
||||
] as const;
|
||||
export type IssueRecoveryActionOwnerType = (typeof ISSUE_RECOVERY_ACTION_OWNER_TYPES)[number];
|
||||
|
||||
/**
|
||||
* Delivery state of one human feedback comment, as projected onto that comment
|
||||
* for operator surfaces. This is deliberately *not* a task status: the task
|
||||
* keeps its own workflow status while a delivery attempt is in flight.
|
||||
*
|
||||
* - `retrying` — automatic replay is still in flight; no operator action.
|
||||
* - `exhausted_needs_attention` — automatic replay gave up; a human must act.
|
||||
* - `recovered_after_attention` — delivery succeeded after it had needed
|
||||
* attention, so the resolution stays visible in thread history.
|
||||
*/
|
||||
export const ISSUE_FEEDBACK_DELIVERY_STATES = [
|
||||
"retrying",
|
||||
"exhausted_needs_attention",
|
||||
"recovered_after_attention",
|
||||
] as const;
|
||||
export type IssueFeedbackDeliveryState = (typeof ISSUE_FEEDBACK_DELIVERY_STATES)[number];
|
||||
|
||||
export const ISSUE_RECOVERY_ACTION_OUTCOMES = [
|
||||
"restored",
|
||||
"handed_back",
|
||||
|
||||
@@ -299,6 +299,7 @@ export {
|
||||
ONBOARDING_FIRST_TASK_ORIGIN_KIND,
|
||||
ISSUE_WATCHDOG_DISCOVERY_KINDS,
|
||||
ISSUE_SURFACE_VISIBILITIES,
|
||||
ISSUE_FEEDBACK_DELIVERY_STATES,
|
||||
ISSUE_RECOVERY_ACTION_KINDS,
|
||||
ISSUE_RECOVERY_ACTION_STATUSES,
|
||||
ISSUE_RECOVERY_ACTION_OWNER_TYPES,
|
||||
@@ -492,6 +493,7 @@ export {
|
||||
type IssueOriginKind,
|
||||
type IssueWatchdogDiscoveryKind,
|
||||
type IssueSurfaceVisibility,
|
||||
type IssueFeedbackDeliveryState,
|
||||
type IssueRecoveryActionKind,
|
||||
type IssueRecoveryActionStatus,
|
||||
type IssueRecoveryActionOwnerType,
|
||||
@@ -1008,6 +1010,8 @@ export type {
|
||||
IssueExecutionStagePrincipal,
|
||||
IssueExecutionDecision,
|
||||
IssueComment,
|
||||
IssueCommentFeedbackDelivery,
|
||||
IssueFeedbackDeliveryRetryResponse,
|
||||
IssueCommentDerivedAuthorSource,
|
||||
IssueCommentMetadata,
|
||||
IssueCommentMetadataSection,
|
||||
|
||||
@@ -649,6 +649,8 @@ export type {
|
||||
IssueReviewRequest,
|
||||
IssueExecutionDecision,
|
||||
IssueComment,
|
||||
IssueCommentFeedbackDelivery,
|
||||
IssueFeedbackDeliveryRetryResponse,
|
||||
IssueCommentDerivedAuthorSource,
|
||||
IssueCommentMetadata,
|
||||
IssueCommentMetadataSection,
|
||||
|
||||
@@ -14,6 +14,7 @@ import type {
|
||||
IssueReferenceSourceKind,
|
||||
IssueExecutionStageType,
|
||||
IssueExecutionStateStatus,
|
||||
IssueFeedbackDeliveryState,
|
||||
IssueHarnessKind,
|
||||
IssueOriginKind,
|
||||
IssuePriority,
|
||||
@@ -941,6 +942,54 @@ export type IssueCommentDerivedAuthorSource =
|
||||
| "run_id"
|
||||
| "run_log_comment_post";
|
||||
|
||||
/**
|
||||
* Delivery state projected onto a single human feedback comment.
|
||||
*
|
||||
* Every field here is safe to render to any operator who can already read the
|
||||
* comment: raw adapter errors, stack traces, request bodies, credentials, and
|
||||
* filesystem paths are mapped to a short `safeFailureReason` code server-side
|
||||
* and never passed through verbatim.
|
||||
*/
|
||||
export interface IssueCommentFeedbackDelivery {
|
||||
state: IssueFeedbackDeliveryState;
|
||||
/** The human comment this delivery obligation belongs to. */
|
||||
sourceCommentId: string;
|
||||
/** Completed automatic replay generations, or `null` when unknown. */
|
||||
attempt: number | null;
|
||||
/** Automatic replay budget, or `null` when unknown. */
|
||||
maxAttempts: number | null;
|
||||
nextAttemptAt: string | null;
|
||||
lastAttemptAt: string | null;
|
||||
deliveredAt: string | null;
|
||||
/**
|
||||
* Run the operator may open for context. Omitted (`null`) when no run exists
|
||||
* or the viewer is not authorized to read it — never rendered as a disabled
|
||||
* mystery action.
|
||||
*/
|
||||
targetRunId: string | null;
|
||||
/** True when the viewer may ask for one more explicit delivery attempt. */
|
||||
canRetry: boolean;
|
||||
/**
|
||||
* True when a replay is already queued for this obligation. Keeps the
|
||||
* "Retrying…" affordance durable across reloads instead of living only in
|
||||
* button-local component state.
|
||||
*/
|
||||
retryInFlight: boolean;
|
||||
/** Short operator-safe reason code, never a raw adapter error. */
|
||||
safeFailureReason: string | null;
|
||||
/**
|
||||
* How many human comments share this one delivery obligation (a batched wake
|
||||
* can cover several). Used for the thread rollup copy.
|
||||
*/
|
||||
batchedCommentCount: number;
|
||||
}
|
||||
|
||||
export interface IssueFeedbackDeliveryRetryResponse {
|
||||
outcome: "queued" | "already_queued" | "not_exhausted" | "no_invokable_assignee";
|
||||
message: string;
|
||||
feedbackDelivery: IssueCommentFeedbackDelivery | null;
|
||||
}
|
||||
|
||||
export interface IssueComment {
|
||||
id: string;
|
||||
companyId: string;
|
||||
@@ -964,6 +1013,12 @@ export interface IssueComment {
|
||||
deletedByRunId?: string | null;
|
||||
sourceTrust?: SourceTrustMetadata | null;
|
||||
followUpRequested?: boolean;
|
||||
/**
|
||||
* Present only while this human comment's delivery is retrying, exhausted, or
|
||||
* freshly recovered. Absent for the overwhelming majority of comments, which
|
||||
* were delivered on the first attempt.
|
||||
*/
|
||||
feedbackDelivery?: IssueCommentFeedbackDelivery | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user