Skip to content

Preserve large transcript records and add targeted capture recovery - #1138

Merged
alexeyzimarev merged 6 commits into
mainfrom
fix/large-transcript-capture
Sep 24, 2026
Merged

alexeyzimarev merged 6 commits into
mainfrom
fix/large-transcript-capture

Conversation

@alexeyzimarev

Copy link
Copy Markdown
Member

AI-3115 — no matching GitHub issue was found.

What & why

Large transcript records lose file-write evidence at the 64K cutoff. Preserve structured JSON within bounded redaction budgets, emit explicit capture-loss markers, and add kcap import --session <id> --repair-capture [--dry-run] for targeted recovery.

Where to look

Deploy server capture/repair support before releasing this CLI. Recovery checks capability before reading local transcripts and preserves source coordinates, cursors, and identical batch retries; unsupported gaps remain explicit.

Verification

  • Full CLI unit executable: 4,655 passed, 19 gated live-vendor skips, zero failures.
  • Capture recovery subset: 36 passed, covering source mutation, authorization refusal, escaped request sizes, retry identity, and partial exits.
  • dotnet publish src/Capacitor.Cli/Capacitor.Cli.csproj -c Release -p:UseSharedCompilation=false -m:1 -nr:false: osx-arm64 NativeAOT succeeded with zero warnings; published binary passed help and synthetic HTTP recovery smoke checks.

@nortonandreev

Copy link
Copy Markdown
Contributor

Have pushed a fix for the failing pipeline here: #1142

@alexeyzimarev
alexeyzimarev marked this pull request as ready for review September 24, 2026 12:09
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-24T12:15:21.772984Z 00ada5a Draft marked ready
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Preserve large transcripts and add targeted capture recovery

🐞 Bug fix ✨ Enhancement 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Preserve large redacted transcript records and mark bounded capture failures explicitly.
• Add capability-gated Claude and Codex recovery with dry-run and gap reporting.
• Split live, import, backfill, and spool uploads within transport limits.
Diagram

sequenceDiagram
    actor U as User
    participant CLI as kcap CLI
    participant API as Recovery API
    participant FS as Local Transcripts
    participant RED as Bounded Redactor
    participant BAT as Batch Client
    participant CAP as Session Capture
    U->>CLI: Request repair
    CLI->>API: Check capability
    API-->>CLI: Confirm ownership
    CLI->>FS: Discover and scan
    FS-->>CLI: Source records
    CLI->>RED: Redact each record
    RED-->>CLI: Safe JSON or marker
    CLI->>BAT: Queue coordinates
    BAT->>API: Prepare and upload
    API->>CAP: Validate and restore
    CAP-->>CLI: Status and gaps
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Extend normal reimport
  • ➕ Reuses the existing import command and transport.
  • ➕ Avoids introducing a dedicated recovery lifecycle.
  • ➖ Cannot preserve repair-specific staging, gap accounting, or durable job status cleanly.
  • ➖ Risks moving ordinary import cursors and conflating recovery with session creation.
  • ➖ Provides weaker ownership and source-coordinate guarantees.
2. Automatically repair during import
  • ➕ Requires no separate user workflow.
  • ➕ Could recover records whenever local transcripts are rediscovered.
  • ➖ May read sensitive local transcripts before server capability and ownership are confirmed.
  • ➖ Introduces unexpected durable writes during routine imports.
  • ➖ Makes residual gaps and partial completion less visible to users.

Recommendation: Keep the targeted, capability-gated recovery protocol. A separate command makes authorization, dry-run semantics, source immutability, bounded staging, idempotent retries, and residual-gap exit codes explicit; normal reimport or automatic repair would blur these guarantees.

Files changed (54) +1551 / -423

Enhancement (19) +380 / -0
RedactionLossReason.csClassify bounded redaction failures +3/-0

Classify bounded redaction failures

• Defines protocol-level reasons for input, malformed data, regex timeout, processing budget, and output-limit failures.

src/Capacitor.Cli/Capture/RedactionLossReason.cs

RedactionOutcome.csReturn structured redaction outcomes +4/-0

Return structured redaction outcomes

• Adds a result model carrying the safe line, optional loss reason, and original UTF-16 and UTF-8 sizes.

src/Capacitor.Cli/Capture/RedactionOutcome.cs

CaptureRepairArgs.csValidate targeted repair arguments +22/-0

Validate targeted repair arguments

• Requires exactly one explicit session and rejects normal import filters or actions that are unsafe or ambiguous in repair mode.

src/Capacitor.Cli/Commands/Capture/CaptureRepairArgs.cs

CaptureRepairClient.csImplement the capture recovery protocol client +119/-0

Implement the capture recovery protocol client

• Adds capability, prepare, batch upload, completion, and status calls with encoded-size limits, stable retry bodies, ordinals, and sanitized server errors.

src/Capacitor.Cli/Commands/Capture/CaptureRepairClient.cs

CaptureRepairCommand.csOrchestrate targeted transcript recovery +84/-0

Orchestrate targeted transcript recovery

• Discovers one ended Claude or Codex session, snapshots root and child sources, uploads redacted coordinates, completes recovery, polls durable status, and maps gaps to exit codes.

src/Capacitor.Cli/Commands/Capture/CaptureRepairCommand.cs

CaptureRepairFileSnapshot.csDetect transcript mutation during repair +14/-0

Detect transcript mutation during repair

• Captures source length and modification time and refuses recovery when a transcript disappears or changes during scanning.

src/Capacitor.Cli/Commands/Capture/CaptureRepairFileSnapshot.cs

CaptureRepairSourceReader.csStream redacted recovery coordinates +32/-0

Stream redacted recovery coordinates

• Reads strict UTF-8 JSONL records with source numbers and original lengths while repeatedly verifying the file remains unchanged.

src/Capacitor.Cli/Commands/Capture/CaptureRepairSourceReader.cs

CaptureRepairCapabilitiesResponse.csModel recovery protocol capabilities +5/-0

Model recovery protocol capabilities

• Defines the server response used to verify the supported recovery protocol version.

src/Capacitor.Cli/Commands/Capture/Wire/CaptureRepairCapabilitiesResponse.cs

CaptureRepairError.csModel recovery refusal codes +5/-0

Model recovery refusal codes

• Defines the bounded protocol error token returned by recovery endpoints.

src/Capacitor.Cli/Commands/Capture/Wire/CaptureRepairError.cs

CaptureRepairGap.csModel unresolved capture gaps +8/-0

Model unresolved capture gaps

• Represents remaining gap codes with source coordinates and optional tool-call identity.

src/Capacitor.Cli/Commands/Capture/Wire/CaptureRepairGap.cs

CaptureRepairLineRequest.csModel coordinate-preserving repair lines +8/-0

Model coordinate-preserving repair lines

• Defines each uploaded redacted record with its source line number and original UTF-16 length.

src/Capacitor.Cli/Commands/Capture/Wire/CaptureRepairLineRequest.cs

CaptureRepairResponse.csModel repair status and accounting +16/-0

Model repair status and accounting

• Captures operation phase, matched, candidate and restored counts, remaining gaps, and accounting freshness.

src/Capacitor.Cli/Commands/Capture/Wire/CaptureRepairResponse.cs

CaptureRepairSourceEndRequest.csDeclare recovery source boundaries +8/-0

Declare recovery source boundaries

• Defines each source's final batch ordinal and final line number for completion validation.

src/Capacitor.Cli/Commands/Capture/Wire/CaptureRepairSourceEndRequest.cs

CaptureRepairSourceRequest.csIdentify recovery transcript streams +8/-0

Identify recovery transcript streams

• Models the session, optional child agent, and vendor identity for each repair source.

src/Capacitor.Cli/Commands/Capture/Wire/CaptureRepairSourceRequest.cs

CompleteCaptureRepairRequest.csModel recovery completion requests +7/-0

Model recovery completion requests

• Collects validated source boundaries submitted when staging is complete.

src/Capacitor.Cli/Commands/Capture/Wire/CompleteCaptureRepairRequest.cs

PrepareCaptureRepairRequest.csModel recovery preparation requests +8/-0

Model recovery preparation requests

• Carries the eligible source list and dry-run mode into server-side staging.

src/Capacitor.Cli/Commands/Capture/Wire/PrepareCaptureRepairRequest.cs

PrepareCaptureRepairResponse.csModel prepared repair operations +7/-0

Model prepared repair operations

• Returns the durable repair identifier and initial operation phase.

src/Capacitor.Cli/Commands/Capture/Wire/PrepareCaptureRepairResponse.cs

UploadCaptureRepairBatchRequest.csModel ordered recovery batches +9/-0

Model ordered recovery batches

• Defines a source-scoped batch ordinal and its coordinate-preserving redacted lines.

src/Capacitor.Cli/Commands/Capture/Wire/UploadCaptureRepairBatchRequest.cs

Program.csRoute import repair mode +13/-0

Route import repair mode

• Parses repair and dry-run usage, validates incompatible arguments, and dispatches targeted recovery before normal import scope resolution.

src/Capacitor.Cli/Program.cs

Bug fix (13) +355 / -372
BoundedJsonBufferWriter.csBound JSON serialization output +37/-0

Bound JSON serialization output

• Adds a pooled buffer writer that rejects reservations or advances beyond a fixed byte budget and clears rented memory on disposal.

src/Capacitor.Cli/Capture/BoundedJsonBufferWriter.cs

CaptureLossMarker.csDefine versioned capture-loss markers +18/-0

Define versioned capture-loss markers

• Introduces the safe marker uploaded when redaction cannot retain a record, including normalized reasons and input size metadata.

src/Capacitor.Cli/Capture/CaptureLossMarker.cs

RedactionBudget.csEnforce a per-record redaction deadline +10/-0

Enforce a per-record redaction deadline

• Tracks one shared one-second processing budget across all work performed for a transcript record.

src/Capacitor.Cli/Capture/RedactionBudget.cs

RedactionBudgetExceededException.csSignal exhausted redaction budgets +3/-0

Signal exhausted redaction budgets

• Adds an internal exception used to convert processing-budget exhaustion into explicit capture loss.

src/Capacitor.Cli/Capture/RedactionBudgetExceededException.cs

RedactionOutputLimitException.csSignal bounded writer overflow +3/-0

Signal bounded writer overflow

• Adds an internal exception for JSON output that exceeds the configured record limit.

src/Capacitor.Cli/Capture/RedactionOutputLimitException.cs

TranscriptCapture.csCentralize safe transcript encoding +30/-0

Centralize safe transcript encoding

• Wraps redaction outcomes, replaces lost records with versioned markers, and aggregates loss reporting across line collections.

src/Capacitor.Cli/Capture/TranscriptCapture.cs

CaptureLineLost.csReport explicit transcript capture loss +9/-0

Report explicit transcript capture loss

• Adds an import warning that identifies the affected session stream, source line, loss reason, and queued marker.

src/Capacitor.Cli/Commands/CaptureLineLost.cs

SessionImporter.csRetain source positions for uncapturable records +14/-24

Retain source positions for uncapturable records

• Routes imported records through bounded capture, uploads loss markers instead of skipping oversized lines, and reports their source coordinates.

src/Capacitor.Cli/Commands/SessionImporter.cs

TranscriptBatchBuffer.csSplit transcript envelopes by transport limits +25/-0

Split transcript envelopes by transport limits

• Adds UTF-8 byte- and line-aware splitting that preserves source coordinates and carries repository metadata only on the first chunk.

src/Capacitor.Cli/Commands/TranscriptBatchBuffer.cs

WatchCommand.csApply bounded capture across live and spooled delivery +33/-67

Apply bounded capture across live and spooled delivery

• Uses safe records or loss markers for live and shutdown capture, splits oversized batches, preserves Cursor acknowledgement semantics, and keeps raw lines for local tool tracking.

src/Capacitor.Cli/Commands/WatchCommand.cs

CursorTranscriptBackfill.csBound Cursor backfill uploads +17/-63

Bound Cursor backfill uploads

• Applies shared transcript encoding and splits backfill requests while rechecking quarantine, attachment barriers, and execution budgets between chunks.

src/Capacitor.Cli/Harness/Cursor/CursorTranscriptBackfill.cs

SecretRedactor.csRedact structured records up to 4 MiB safely +141/-203

Redact structured records up to 4 MiB safely

• Replaces the legacy 64K cutoff with bounded structural JSON redaction, shared time and regex limits, pooled buffers, explicit outcomes, and safe handling of malformed or expanding output.

src/Capacitor.Cli/SecretRedactor.cs

WatcherManager.csBound inline transcript drains +15/-15

Bound inline transcript drains

• Encodes inline records through the shared capture path, reports losses, and posts size-bounded chunks with per-chunk failure handling.

src/Capacitor.Cli/WatcherManager.cs

Tests (17) +718 / -51
AdvancingRedactionTimeProvider.csProvide deterministic advancing redaction time +7/-0

Provide deterministic advancing redaction time

• Adds a test clock whose timestamp advances on every read to exercise shared processing budgets.

test/Capacitor.Cli.Tests.Unit/Capture/AdvancingRedactionTimeProvider.cs

BoundedJsonBufferWriterTests.csTest bounded JSON writer enforcement +18/-0

Test bounded JSON writer enforcement

• Verifies reservations and advances beyond the byte limit fail without corrupting already-written content.

test/Capacitor.Cli.Tests.Unit/Capture/BoundedJsonBufferWriterTests.cs

RedactionBudgetTests.csTest shared record processing budgets +25/-0

Test shared record processing budgets

• Confirms elapsed time accumulates across checks and across every value in one record.

test/Capacitor.Cli.Tests.Unit/Capture/RedactionBudgetTests.cs

TranscriptCaptureTests.csTest safe capture-loss markers +32/-0

Test safe capture-loss markers

• Verifies malformed large input becomes secret-safe versioned JSON and every loss reason maps to its protocol name.

test/Capacitor.Cli.Tests.Unit/Capture/TranscriptCaptureTests.cs

CaptureRepairArgsTests.csTest repair argument isolation +35/-0

Test repair argument isolation

• Covers rejected import flags, required session cardinality, and valid targeted preview combinations.

test/Capacitor.Cli.Tests.Unit/Commands/Capture/CaptureRepairArgsTests.cs

CaptureRepairClientTests.csTest recovery batching and retries +77/-0

Test recovery batching and retries

• Verifies lost acknowledgements resend identical bodies and ordinals, escaped wire bytes drive splitting, and oversized individual records are refused.

test/Capacitor.Cli.Tests.Unit/Commands/Capture/CaptureRepairClientTests.cs

CaptureRepairCommandTests.csTest end-to-end recovery orchestration +187/-0

Test end-to-end recovery orchestration

• Covers capability ordering, root and child coordinates, dry runs, residual gaps, server refusals, unfinished jobs, invalid UTF-8, and Codex descendant selection.

test/Capacitor.Cli.Tests.Unit/Commands/Capture/CaptureRepairCommandTests.cs

CaptureRepairSourceReaderTests.csTest safe recovery source scanning +62/-0

Test safe recovery source scanning

• Verifies coordinates, large Unicode redaction, loss markers, mutation detection, missing sources, cancellation, and strict UTF-8 handling.

test/Capacitor.Cli.Tests.Unit/Commands/Capture/CaptureRepairSourceReaderTests.cs

LostRepairAcknowledgmentHandler.csSimulate lost recovery acknowledgements +15/-0

Simulate lost recovery acknowledgements

• Adds a test handler that drops the first accepted batch response to exercise byte-identical retries.

test/Capacitor.Cli.Tests.Unit/Commands/Capture/LostRepairAcknowledgmentHandler.cs

RepairImportSource.csStub transcript discovery for repair tests +21/-0

Stub transcript discovery for repair tests

• Provides a controllable Claude or Codex import source and records whether local discovery was attempted.

test/Capacitor.Cli.Tests.Unit/Commands/Capture/RepairImportSource.cs

SessionImporterCaptureTests.csTest large-record import preservation +76/-0

Test large-record import preservation

• Confirms large tool results retain structure after redaction and oversized records become numbered loss markers across root and child uploads.

test/Capacitor.Cli.Tests.Unit/Commands/SessionImporterCaptureTests.cs

SessionImporterProgressTests.csUpdate importer loss reporting expectations +11/-10

Update importer loss reporting expectations

• Replaces skipped-line assertions with capture-loss warnings and verifies source numbering and progress counts include marker records.

test/Capacitor.Cli.Tests.Unit/Commands/SessionImporterProgressTests.cs

ShutdownTranscriptSpoolTests.csTest safe shutdown capture markers +22/-10

Test safe shutdown capture markers

• Verifies an uncapturable shutdown-tail record is spooled as a redacted loss marker at its original coordinate.

test/Capacitor.Cli.Tests.Unit/Commands/ShutdownTranscriptSpoolTests.cs

TranscriptBatchBufferTests.csTest coordinate-preserving batch splitting +23/-0

Test coordinate-preserving batch splitting

• Covers multibyte UTF-8 sizing, metadata preservation, source coordinates, and empty metadata envelopes.

test/Capacitor.Cli.Tests.Unit/Commands/TranscriptBatchBufferTests.cs

WatchCommandTests.csUpdate tool tracking loss thresholds +4/-14

Update tool tracking loss thresholds

• Moves oversized tool-result fixtures to the new 4 MiB boundary while retaining raw-line correlation behavior tests.

test/Capacitor.Cli.Tests.Unit/Commands/WatchCommandTests.cs

CursorTranscriptBackfillTests.csTest bounded Cursor backfill chunks +22/-0

Test bounded Cursor backfill chunks

• Confirms multiple large encoded records are posted in separate requests within the transcript byte budget.

test/Capacitor.Cli.Tests.Unit/Harness/Cursor/CursorTranscriptBackfillTests.cs

SecretRedactorTests.csExpand bounded redaction coverage +81/-17

Expand bounded redaction coverage

• Tests legacy-boundary preservation, 4 MiB input and output limits, Unicode expansion, excessive depth, secret removal, correlation retention, and processing safety.

test/Capacitor.Cli.Tests.Unit/SecretRedactorTests.cs

Documentation (2) +76 / -0
README.mdDocument bounded capture and targeted recovery +44/-0

Document bounded capture and targeted recovery

• Documents capture-loss markers, the 4 MiB redaction boundary, targeted Claude/Codex recovery, deployment ordering, operational limits, and exit codes.

README.md

help-import.txtAdd repair-capture CLI help +32/-0

Add repair-capture CLI help

• Describes the new repair and dry-run flags, rejected combinations, server prerequisites, batching limits, durable processing, and exit behavior.

src/Capacitor.Cli.Core/Resources/help-import.txt

Other (3) +22 / -0
CaptureJsonContext.csGenerate capture marker JSON metadata +7/-0

Generate capture marker JSON metadata

• Adds NativeAOT-compatible source-generated serialization metadata for capture-loss markers.

src/Capacitor.Cli/Capture/CaptureJsonContext.cs

CaptureRepairJsonContext.csGenerate recovery protocol JSON metadata +14/-0

Generate recovery protocol JSON metadata

• Registers recovery request and response models for source-generated, NativeAOT-compatible JSON handling.

src/Capacitor.Cli/Commands/Capture/Wire/CaptureRepairJsonContext.cs

CommandServices.csRegister the capture repair command +1/-0

Register the capture repair command

• Adds the targeted recovery orchestrator to dependency injection.

src/Capacitor.Cli/Commands/CommandServices.cs

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 00ada5a565

ℹ️ 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".

Comment thread src/Capacitor.Cli/Harness/Cursor/CursorTranscriptBackfill.cs Outdated
Comment thread src/Capacitor.Cli/Commands/Capture/CaptureRepairCommand.cs Outdated
@qodo-code-review

qodo-code-review Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (1) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Uppercase session IDs cannot be repaired ✓ Resolved 🐞 Bug ≡ Correctness
Description
CaptureRepairCommand.HandleAsync removes hyphens from sessionId but leaves its case unchanged
before using it for discovery, final candidate matching, and the recovery URL. Claude and Codex
discovery normalize GUID filters to lowercase dashless IDs, so an uppercase UUID accepted by
validation finds no local transcript and cannot recover that session.
Code

src/Capacitor.Cli/Commands/Capture/CaptureRepairCommand.cs[R17-18]

+            sessionId = sessionId.Replace("-", "", StringComparison.Ordinal);
+            if (string.IsNullOrWhiteSpace(sessionId) || sessionId.Length > 128 || sessionId.Any(c => !char.IsAsciiLetterOrDigit(c) && c != '_'))
Relevance

●●● Strong

Case normalization is a deterministic correctness fix, matching accepted precedent for
canonicalizing upstream identifiers.

PR-#1005

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The repair command accepts uppercase letters, strips only hyphens, and then uses ordinal matching.
Existing Claude and Codex discovery convert a GUID filter to its lowercase N form before
performing their own ordinal matches, which means the discovery succeeds internally but the repair
command's final comparison rejects the returned lowercase session ID.

src/Capacitor.Cli/Commands/Capture/CaptureRepairCommand.cs[17-27]
src/Capacitor.Cli/Commands/ImportCommand.cs[3002-3006]
src/Capacitor.Cli/Harness/Claude/ClaudeImportSource.cs[38-44]
src/Capacitor.Cli/Harness/Codex/CodexImportSource.cs[54-59]

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

Issue description
`kcap import --session <uppercase-guid> --repair-capture` passes validation but fails to locate the local Claude or Codex transcript because repair strips hyphens without canonicalizing GUID case. The normalized value is also used in the server URL and source requests, so normalize it once before all subsequent repair operations.

Fix Focus Areas
- src/Capacitor.Cli/Commands/Capture/CaptureRepairCommand.cs[17-18]

Recommended Fix
Replace the hyphen-only normalization with the same GUID normalization used by ordinary import (for example, `ImportCommand.NormalizeGuid(sessionId)`), while retaining the existing validation for non-GUID session IDs. Use that canonical value consistently for discovery filters, candidate comparison, URLs, and repair source requests.

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


2. Malformed records can upload unchanged ✓ Resolved 📘 Rule violation ≡ Correctness
Description
RedactLineWithOutcome catches JsonException, applies regex replacement to the complete
rawJsonlLine, and returns a successful outcome even when that fallback changes nothing. A
malformed record at or below the 64 KiB fallback limit with no recognized secret pattern therefore
passes through TranscriptCapture.Encode without a loss marker and reaches live capture, import,
spooling, and repair unchanged.
Code

src/Capacitor.Cli/SecretRedactor.cs[R35-40]

+                line = RedactJsonStringValues(rawJsonlLine, bytes, budget) ?? rawJsonlLine;
+            } catch (JsonException) {
+                if (rawJsonlLine.Length > MaxRedactableLineChars)
+                    return Lost(RedactionLossReason.MalformedInput);
+                line = RedactSecrets(rawJsonlLine, budget);
+            }
Relevance

●●● Strong

Accepted precedent explicitly rejects raw passthrough because malformed or oversized content can
leak secrets.

PR-#129

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2943475 prohibits applying secret replacement to a complete serialized input, while rule
2943490 requires failed or refused lines to emit a fixed placeholder rather than their original
content. The changed fallback applies RedactSecrets directly to rawJsonlLine, then reports no
loss when the unchanged result is returned; TranscriptCapture.Encode only substitutes a marker
when Loss is populated.

Rule 2943475: Redact secrets only on decoded JSON values, not on raw serialized lines
Rule 2943490: Redaction writer must never emit unredacted rejected lines
src/Capacitor.Cli/SecretRedactor.cs[35-43]
src/Capacitor.Cli/Capture/TranscriptCapture.cs[20-28]
src/Capacitor.Cli/Commands/Capture/CaptureRepairSourceReader.cs[20-25]

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

## Issue description
Malformed JSON is regex-redacted as a complete raw line and may be returned unchanged, allowing rejected content to reach capture outputs without a loss marker.

## Fix Focus Areas
- src/Capacitor.Cli/SecretRedactor.cs[35-43]
- src/Capacitor.Cli/Capture/TranscriptCapture.cs[20-28]
- src/Capacitor.Cli/Commands/Capture/CaptureRepairSourceReader.cs[20-25]

## Recommended Fix
When structured JSON parsing fails, return a `MalformedInput` loss outcome containing only a fixed safe placeholder rather than running regex replacement over the raw line. Keep value-level redaction exclusively inside the structured JSON rewrite path and add coverage for small malformed records containing both recognized and unrecognized text.

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


3. Two summaries duplicate nearby code ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The new summaries above BuildTranscriptSpoolBatch and spooled_tail_is_secret_redacted merely
restate the method names and immediately visible behavior. They add no constraint or rationale, so
later readers cannot distinguish behavior-critical documentation from redundant narration.
Code

src/Capacitor.Cli/Commands/WatchCommand.cs[2426]

+    /// <summary>Serialize a replayable transcript batch.</summary>
Relevance

●●● Strong

Recent repository precedent accepts shortening comments that merely restate visible behavior or
method names.

PR-#693
PR-#512
PR-#507

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2762993 requires comments to document non-obvious, behavior-critical constraints and
specifically rejects comments that duplicate signature information or visible code. Both cited
one-line summaries paraphrase the names of the declarations directly below them.

Rule 2762993: Restrict comments to documenting non-obvious, behavior‑critical constraints
src/Capacitor.Cli/Commands/WatchCommand.cs[2426-2427]
test/Capacitor.Cli.Tests.Unit/Commands/ShutdownTranscriptSpoolTests.cs[232-234]

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

## Issue description
Two newly shortened XML summaries duplicate their method names or assertions without documenting a non-obvious constraint, trade-off, or failure mode.

## Fix Focus Areas
- src/Capacitor.Cli/Commands/WatchCommand.cs[2426-2427]
- test/Capacitor.Cli.Tests.Unit/Commands/ShutdownTranscriptSpoolTests.cs[232-234]

## Recommended Fix
Remove the redundant summaries, or rewrite them only if there is a behavior-critical invariant that cannot be inferred from each method name and implementation.

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


View medium (1)
4. Changed transcripts can pass validation ✓ Resolved 🐞 Bug ☼ Reliability
Description
CaptureRepairFileSnapshot.AssertUnchanged compares only path, byte length, and last-write
timestamp rather than the content being uploaded. An in-place same-length rewrite with a preserved
or filesystem-rounded timestamp can therefore alter records during the scan without aborting
recovery, despite the command requiring an unchanged ended-session source.
Code

src/Capacitor.Cli/Commands/Capture/CaptureRepairFileSnapshot.cs[R10-12]

+    public void AssertUnchanged() {
+        var current = Take(Path);
+        if (current != this) throw new IOException("Transcript changed during recovery; retry after the session ends.");
Relevance

●● Moderate

The metadata-only snapshot risks missed same-size rewrites, but no close precedent establishes the
team’s decision.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The snapshot record contains only Path, Length, and LastWrite, and AssertUnchanged accepts
the file whenever those metadata values compare equal. The reader sends redacted lines incrementally
while relying on this metadata-only check before each line and at EOF, after which the command asks
the server to complete the repair.

src/Capacitor.Cli/Commands/Capture/CaptureRepairFileSnapshot.cs[3-12]
src/Capacitor.Cli/Commands/Capture/CaptureRepairSourceReader.cs[16-29]
src/Capacitor.Cli/Commands/Capture/CaptureRepairCommand.cs[49-58]

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

## Issue description
Capture recovery detects source changes only through file length and last-write time. Same-length content changes with an unchanged timestamp can evade the checks and allow recovery to validate data read from a changing transcript.

## Fix Focus Areas
- src/Capacitor.Cli/Commands/Capture/CaptureRepairFileSnapshot.cs[3-13]
- src/Capacitor.Cli/Commands/Capture/CaptureRepairSourceReader.cs[16-29]
- src/Capacitor.Cli/Commands/Capture/CaptureRepairCommand.cs[49-58]

## Recommended Fix
Bind each recovery source to a content digest or equivalent immutable snapshot. Compute the digest while reading, then verify it against a second stable read before requesting completion; reject the operation when file identity, length, timestamp, or digest differs.

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



Informational

5. Session end can strand transcript lines 🐞 Bug ≡ Correctness
Description
CursorTranscriptBackfill.RunAsync returns a successful-looking partial result when a quarantine or
attachment barrier appears between chunks, but its session-end callers ignore that result and
continue posting the terminal hook. When this happens after an earlier chunk was delivered, session
end clears the attachment queue and closes the stream while the remaining transcript lines stay
behind the server watermark.
Code

src/Capacitor.Cli/Harness/Cursor/CursorTranscriptBackfill.cs[R103-105]

+                if (budget() || markers.IsQuarantined(sessionId)
+                    || markers.BarrierPending(sessionId, time.GetUtcNow(), CursorMarkers.DefaultBarrierBound))
+                    return new Stats(posted, Failed: false);
Relevance

● Weak

Recent Cursor precedent rejected changing delivery behavior to abort after blocked or gap responses.

PR-#817

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The split loop explicitly exits between chunks when a barrier or quarantine appears, returning
Failed: false even though not all lines were posted. The top-level and child session-end paths
await this method without inspecting its Stats, then proceed to post session end; surrounding
comments state that session end clears the attachment FIFO needed by transcript normalization.

src/Capacitor.Cli/Harness/Cursor/CursorTranscriptBackfill.cs[100-112]
src/Capacitor.Cli/Commands/Harness/CursorHookCommand.cs[478-510]
src/Capacitor.Cli/Commands/Harness/CursorHookCommand.cs[762-785]

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

## Issue description
Cursor backfill can stop between split chunks because a quarantine or attachment barrier appears, yet session-end callers ignore the partial result and still submit the terminal hook. This can close the session and clear attachment state before the remaining transcript lines are delivered.

## Fix Focus Areas
- src/Capacitor.Cli/Harness/Cursor/CursorTranscriptBackfill.cs[100-114]
- src/Capacitor.Cli/Commands/Harness/CursorHookCommand.cs[487-510]
- src/Capacitor.Cli/Commands/Harness/CursorHookCommand.cs[762-785]

## Recommended Fix
Return an explicit incomplete or blocked status whenever chunk delivery stops before all lines are posted. In every pre-session-end caller, inspect that status and spool or defer the terminal hook instead of posting it until the transcript backfill completes.

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


6. New tests bypass temporary injection 📘 Rule violation ▣ Testability
Description
CaptureRepairCommandTests and four other changed test classes construct method-local TempDir
instances instead of declaring one public required property decorated with [TempDir]. Every
affected test manually owns temporary state, so TUnit cannot provide the checklist-mandated
centralized lifecycle for these classes.
Code

test/Capacitor.Cli.Tests.Unit/Commands/Capture/CaptureRepairCommandTests.cs[37]

+        using var tmp = new TempDir();
Relevance

● Weak

Recent test reviews rejected replacing local TempDir instances with injected properties, despite the
same stated rule.

PR-#976
PR-#972
PR-#1015

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2808173 explicitly forbids new TempDir() calls in test classes and requires a single injected
[TempDir] public required property. The cited additions introduce manually managed instances
across five changed test classes.

Rule 2808173: Use injected [TempDir] public required property in test classes instead of manual fields
test/Capacitor.Cli.Tests.Unit/Commands/Capture/CaptureRepairCommandTests.cs[37-37]
test/Capacitor.Cli.Tests.Unit/Commands/Capture/CaptureRepairSourceReaderTests.cs[11-11]
test/Capacitor.Cli.Tests.Unit/Commands/SessionImporterCaptureTests.cs[22-22]
test/Capacitor.Cli.Tests.Unit/Commands/ShutdownTranscriptSpoolTests.cs[14-14]
test/Capacitor.Cli.Tests.Unit/Harness/Cursor/CursorTranscriptBackfillTests.cs[11-11]

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

## Issue description
Five changed test classes manually construct `TempDir` instances even though test classes must receive temporary storage through a single framework-injected `[TempDir]` property.

## Fix Focus Areas
- test/Capacitor.Cli.Tests.Unit/Commands/Capture/CaptureRepairCommandTests.cs[11-13]
- test/Capacitor.Cli.Tests.Unit/Commands/Capture/CaptureRepairSourceReaderTests.cs[8-11]
- test/Capacitor.Cli.Tests.Unit/Commands/SessionImporterCaptureTests.cs[10-22]
- test/Capacitor.Cli.Tests.Unit/Commands/ShutdownTranscriptSpoolTests.cs[11-16]
- test/Capacitor.Cli.Tests.Unit/Harness/Cursor/CursorTranscriptBackfillTests.cs[8-13]

## Recommended Fix
Add one `[TempDir] public required TempDir Tmp { get; init; }` property to each affected test class, replace method-local `new TempDir()` declarations with that property, and remove manual disposal scopes for the injected directory.

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


Grey Divider

Context sources
✅ Compliance rules (platform): 64 rules
✅ Cross-repo context — repo relationships
  Explored: repo: kurrent-io/kcap-server (sha: 40b047c6)
  Explored: repo: kurrent-io/kcap-deployments (sha: dc4e85d2)
Review mode: 🧠 Deep: This is a broad, behavior-heavy change spanning redaction/security, live and shutdown capture paths, CLI parsing, recovery protocols, retries, file consistency, batching, and multiple vendor workflows, creating many independent opportunities for subtle defects.

Grey Divider

Tip of the day
💡 Did you know, you can choose which labels appear on a finding, and whether they show icons or text

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/Capacitor.Cli/SecretRedactor.cs
Comment thread src/Capacitor.Cli/Commands/WatchCommand.cs Outdated
Comment thread src/Capacitor.Cli/Commands/Capture/CaptureRepairFileSnapshot.cs Outdated
Comment thread src/Capacitor.Cli/Commands/Capture/CaptureRepairCommand.cs Outdated
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.

2 participants