Skip to content

fix(quotes): follow quote chains past two levels (#85) - #86

Merged
wolfgang-aura merged 2 commits into
mainfrom
claude/intelligent-lehmann-cb18e5
Oct 18, 2026
Merged

wolfgang-aura merged 2 commits into
mainfrom
claude/intelligent-lehmann-cb18e5

Conversation

@wolfgang-aura

Copy link
Copy Markdown
Owner

Fixes #85.

Problem

A syndication payload carries one level of quoted_tweet, and that nested object has no id for the next hop. Capsule 5eb7a4bf… kept 3 of a 7-post quote chain (main + 6 quotes) and still said Status: COMPLETE.

Change

  • followQuoteChainsViaSyndication runs last in the syndication block, before inlineMedia, so deeper levels' media and avatars get inlined. For every leaf quote with a canonical permalink (top level, thread segments, blockquotes) it fetches the leaf by id through syndicationSuccessCache and appends its quoted_tweet as a nested quote. It stops when a post quotes nothing.
  • The leaf's own blocks are never replaced, only appended to, so DOM-only polls and cards survive.
  • Cap: CONFIG.quoteChainMaxDepth = 8 levels below the main post. The leaf at the cap is still fetched, so a chain that ends exactly there is not flagged. Cycles are caught against the ancestor path.
  • Past the cap, or on a non-404 failure, the pass leaves a quote-chain-note. It renders in the HTML and .llm.md, is counted in archiveStats/manifest (quoteChainsUnfollowed), the capture summary, the share-result warnings and the in-page receipt, and makes captureGaps say INCOMPLETE.
  • A 404 leaves a quote-tombstone with chainEnd, worded as "could not be followed", not "quoted post gone".
  • Neither is a strict-mode blocker. assessExportCompleteness is unchanged, so unattended captures don't become needs_owner.
  • Reply-context cards are not followed.
  • On screens up to 520px, nested quote cards render as a left rule instead of a full box. Before, each level cost 46px of width.

Checks

  • test/quote-chain.test.mjs (new, added to npm test). It failed before the fix with followQuoteChainsViaSyndication is not a function. It covers:
    • a 6-level chain fully nested, with the DOM-only poll kept
    • LLM labels 1 … 1.1.1.1.1.1 distinct after headings stop at ######
    • cap note + INCOMPLETE + strict verdict still clean
    • a chain ending exactly at the cap stays COMPLETE
    • 503 on a thread-segment leaf leaves a gap note; 404 leaves a tombstone and stays COMPLETE
    • cycle stops silently; reply context is not fetched
  • Walkers audited: inlineMedia/rescue task collection, collectMediaManifest, collectBundleMediaFiles, the share-model media rewrite, enrichVideoCandidates, assignArchiveMediaIds all recurse through quote without a depth limit. No change needed.
  • npm test, npm run lint and npm run format:check pass locally.
  • Seen in a screenshot (Brave, 375px, generated 6-level fixture): before the CSS change, the level-6 card was 117px wide with @Diros009 overflowing its border. After it, the card is 257px wide with no horizontal scroll. The cap note and "Incomplete capture" banner are visible on the capped fixture.
  • Desktop at 1280px: measured in the DOM only (cards unchanged, 640→502px over 4 levels). The screenshot timed out.

Not live-verified. That needs a re-export of https://x.com/hibtc37/status/2111240021563056451 with the rebuilt extension, expecting main + 6 quotes ending at @Diros009's 2101125814888931800.

🤖 Generated with Claude Code

A syndication payload carries one level of quoted_tweet, and the nested
object has no id for the next hop, so a chain like main -> A -> B -> C
stopped at B while the receipt said COMPLETE.

followQuoteChainsViaSyndication runs after all syndication enrichment and
before inlineMedia. It fetches every leaf quote by id (through the
per-export cache) and appends its quoted_tweet until a post quotes nothing.
The leaf's own blocks are never replaced, so DOM-only polls and cards stay.

- Cap: CONFIG.quoteChainMaxDepth, 8 levels below the main post. The leaf
  at the cap is still fetched, so only a chain that really continues gets
  a quote-chain-note ("not followed past <id>").
- A non-404 failure also leaves a quote-chain-note. Both count in the
  receipt, manifest and share warnings, so the receipt says INCOMPLETE.
- A 404 leaves a quote-tombstone (chainEnd). A cycle stops silently.
- Neither is a strict-mode blocker: a deeper hop is only discoverable by
  fetching, and a blocker would turn unattended captures into needs_owner.
- Reply-context cards are not followed.
- On screens up to 520px, nested cards become a left rule instead of a
  full box. At 375px a level-6 card was 117px wide with its handle
  overflowing; it is now 257px.

Fixes #85

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
)

repairExportBlockers rebuilds a quote the main pass could not fetch with
one nested level and stopped there, so a chain recovered by the repair
round (or the modal's Retry) shipped two levels deep and said COMPLETE.
Run followQuoteChainsViaSyndication after the rebuild and before the
media rescue, so the deeper cards' media is downloaded too.

Refs #85

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@wolfgang-aura

Copy link
Copy Markdown
Owner Author

Follow-up 9c3c94d: repairExportBlockers now runs followQuoteChainsViaSyndication after its quote rebuild and before the media rescue. Without it, a quote first recovered by the repair round, or by the modal's Retry, shipped two levels deep and said COMPLETE. Test case 6 covers it and failed before the fix.

Checked against real syndication (read-only Node script, no browser, nothing published): enrichFocusedPostViaSyndication + followQuoteChainsViaSyndication on hibtc37/status/2111240021563056451 gives the exact chain from the issue table. That is 6 quotes, ending at @Diros009 2101125814888931800, with 7 GETs, all 200.

Also seen in a screenshot at 375px: examples/sample-export.html with the phone CSS. The nested quote under an image card renders as a left rule, with no horizontal scroll.

@wolfgang-aura
wolfgang-aura merged commit 64aef88 into main Oct 18, 2026
1 check passed
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.

Quote chains deeper than two levels are truncated while the receipt says COMPLETE

1 participant