Skip to content

Fix direct QA reporting + configurable retention + orphan recording tracking#6951

Merged
Jasonnnz merged 1 commit into
feature/qa-video-automationfrom
swarm/qa-video-auto/task-20
Feb 23, 2026
Merged

Fix direct QA reporting + configurable retention + orphan recording tracking#6951
Jasonnnz merged 1 commit into
feature/qa-video-automationfrom
swarm/qa-video-auto/task-20

Conversation

@Jasonnnz
Copy link
Copy Markdown
Contributor

@Jasonnnz Jasonnnz commented Feb 23, 2026

Summary

Test plan

  • Submit a task via the macOS task input while a chat thread is active -- verify conversationId is sent in task_submit
  • Verify QA recordings from direct task_submit get attached to the originating chat thread
  • Verify retentionDays flows from daemon config through task_routed to the client's finalizeQARecording
  • Change qaRecording.defaultRetentionDays in config and verify the client uses the updated value
  • Verify orphan recordings (no reportToSessionId) still get tracked as file-backed attachments for cleanup
  • Verify escalated sessions continue to work with reportToSessionId set to sourceSessionId

🤖 Generated with Claude Code


Open with Devin

P1 #3: Add conversationId to TaskSubmit so direct CU QA sessions can set
reportToSessionId. Client passes active thread ID. Daemon routes it to CU
session metadata, enabling attachment creation on finalize.

P1 #4: Add retentionDays to TaskRouted from daemon config. Client reads it
instead of hardcoding 7 days.

Also: create file-backed attachment for recordings without reportToSessionId
so cleanup can track orphan files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Jasonnnz Jasonnnz self-assigned this Feb 23, 2026
@Jasonnnz Jasonnnz merged commit d08f2c8 into feature/qa-video-automation Feb 23, 2026
@Jasonnnz Jasonnnz deleted the swarm/qa-video-auto/task-20 branch February 23, 2026 17:27
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

View 5 additional findings in Devin Review.

Open in Devin Review

Comment on lines +337 to +351
if (msg.recording && !(meta?.reportToSessionId)) {
try {
createFileBackedAttachment({
filename: `qa-recording-${msg.sessionId}.mp4`,
mimeType: msg.recording.mimeType || 'video/mp4',
sizeBytes: msg.recording.sizeBytes,
filePath: msg.recording.localPath,
sha256: undefined,
expiresAt: msg.recording.expiresAt,
});
log.info({ sessionId: msg.sessionId }, 'Created orphan file-backed attachment for cleanup tracking (no reportToSessionId)');
} catch (err) {
log.error({ err, sessionId: msg.sessionId }, 'Failed to create file-backed attachment for orphan recording');
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Recording file untracked when reportToSessionId exists but conversation was deleted

When meta?.reportToSessionId is set but conversationStore.getConversation(reportSessionId) returns null (e.g., the user cleared sessions while the CU session was running), the recording file gets no file-backed attachment created.

Root Cause

The new orphan-tracking code at line 337 checks !(meta?.reportToSessionId), which is false when a reportToSessionId exists. But the normal attachment-creation path at line 256-287 only runs inside if (conversation) (line 243). When the conversation is missing, neither path creates an attachment:

  1. Line 243: if (conversation) is false → attachment creation at line 258 is skipped
  2. Line 327: else branch just logs a warning
  3. Line 337: !(meta?.reportToSessionId) is false → orphan tracking is skipped

Result: the recording file on disk is never registered in the attachment store, so the cleanup system cannot track or expire it.

Impact: Recording files accumulate on disk indefinitely for this edge case, causing a slow storage leak.

Suggested change
if (msg.recording && !(meta?.reportToSessionId)) {
try {
createFileBackedAttachment({
filename: `qa-recording-${msg.sessionId}.mp4`,
mimeType: msg.recording.mimeType || 'video/mp4',
sizeBytes: msg.recording.sizeBytes,
filePath: msg.recording.localPath,
sha256: undefined,
expiresAt: msg.recording.expiresAt,
});
log.info({ sessionId: msg.sessionId }, 'Created orphan file-backed attachment for cleanup tracking (no reportToSessionId)');
} catch (err) {
log.error({ err, sessionId: msg.sessionId }, 'Failed to create file-backed attachment for orphan recording');
}
}
// Create a file-backed attachment for recordings without a reporting session
// (or when the reporting conversation was deleted) so cleanup can track orphan files.
if (msg.recording && !(meta?.reportToSessionId && conversationStore.getConversation(meta.reportToSessionId))) {
try {
createFileBackedAttachment({
filename: `qa-recording-${msg.sessionId}.mp4`,
mimeType: msg.recording.mimeType || 'video/mp4',
sizeBytes: msg.recording.sizeBytes,
filePath: msg.recording.localPath,
sha256: undefined,
expiresAt: msg.recording.expiresAt,
});
log.info({ sessionId: msg.sessionId }, 'Created orphan file-backed attachment for cleanup tracking (no reportToSessionId)');
} catch (err) {
log.error({ err, sessionId: msg.sessionId }, 'Failed to create file-backed attachment for orphan recording');
}
}
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 416899300f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

reportToSessionId: routed.reportToSessionId,
qaMode: routed.qaMode ?? false
qaMode: routed.qaMode ?? false,
retentionDays: routed.retentionDays.flatMap { Int($0) } ?? 7
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Safely parse routed retentionDays before Int conversion

routed.retentionDays.flatMap { Int($0) } performs a trapping conversion, so a very large (or non-finite) retentionDays value from the daemon will crash the macOS client when a QA session is created; this is reachable because daemon config currently only requires qaRecording.defaultRetentionDays to be a positive integer, not bounded to Int range. Please use a non-trapping conversion with bounds checks/fallback (and apply the same guard to the identical conversion in the other session-construction path).

Useful? React with 👍 / 👎.

Jasonnnz added a commit that referenced this pull request Feb 23, 2026
…ays (#6951)

P1 #3: Add conversationId to TaskSubmit so direct CU QA sessions can set
reportToSessionId. Client passes active thread ID. Daemon routes it to CU
session metadata, enabling attachment creation on finalize.

P1 #4: Add retentionDays to TaskRouted from daemon config. Client reads it
instead of hardcoding 7 days.

Also: create file-backed attachment for recordings without reportToSessionId
so cleanup can track orphan files.

Co-authored-by: Vellum Assistant <assistant@vellum.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Jasonnnz added a commit that referenced this pull request Feb 23, 2026
…ays (#6951)

P1 #3: Add conversationId to TaskSubmit so direct CU QA sessions can set
reportToSessionId. Client passes active thread ID. Daemon routes it to CU
session metadata, enabling attachment creation on finalize.

P1 #4: Add retentionDays to TaskRouted from daemon config. Client reads it
instead of hardcoding 7 days.

Also: create file-backed attachment for recordings without reportToSessionId
so cleanup can track orphan files.

Co-authored-by: Vellum Assistant <assistant@vellum.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Jasonnnz added a commit that referenced this pull request Feb 23, 2026
…ays (#6951)

P1 #3: Add conversationId to TaskSubmit so direct CU QA sessions can set
reportToSessionId. Client passes active thread ID. Daemon routes it to CU
session metadata, enabling attachment creation on finalize.

P1 #4: Add retentionDays to TaskRouted from daemon config. Client reads it
instead of hardcoding 7 days.

Also: create file-backed attachment for recordings without reportToSessionId
so cleanup can track orphan files.

Co-authored-by: Vellum Assistant <assistant@vellum.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Jasonnnz added a commit that referenced this pull request Feb 23, 2026
…ays (#6951)

P1 #3: Add conversationId to TaskSubmit so direct CU QA sessions can set
reportToSessionId. Client passes active thread ID. Daemon routes it to CU
session metadata, enabling attachment creation on finalize.

P1 #4: Add retentionDays to TaskRouted from daemon config. Client reads it
instead of hardcoding 7 days.

Also: create file-backed attachment for recordings without reportToSessionId
so cleanup can track orphan files.

Co-authored-by: Vellum Assistant <assistant@vellum.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Jasonnnz added a commit that referenced this pull request Feb 23, 2026
…ays (#6951)

P1 #3: Add conversationId to TaskSubmit so direct CU QA sessions can set
reportToSessionId. Client passes active thread ID. Daemon routes it to CU
session metadata, enabling attachment creation on finalize.

P1 #4: Add retentionDays to TaskRouted from daemon config. Client reads it
instead of hardcoding 7 days.

Also: create file-backed attachment for recordings without reportToSessionId
so cleanup can track orphan files.

Co-authored-by: Vellum Assistant <assistant@vellum.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Jasonnnz added a commit that referenced this pull request Feb 23, 2026
…ays (#6951)

P1 #3: Add conversationId to TaskSubmit so direct CU QA sessions can set
reportToSessionId. Client passes active thread ID. Daemon routes it to CU
session metadata, enabling attachment creation on finalize.

P1 #4: Add retentionDays to TaskRouted from daemon config. Client reads it
instead of hardcoding 7 days.

Also: create file-backed attachment for recordings without reportToSessionId
so cleanup can track orphan files.

Co-authored-by: Vellum Assistant <assistant@vellum.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant