# Tweet-stream transcript rendering

The X tweet stream becomes one `:KnowledgeDocument` whose body is a verbatim chronological transcript of every operator-authored tweet, reply, and quote-tweet. The classifier (`memory-classify`, document mode) splits this body into `:Section` children — threading and topic boundaries live as section boundaries inside the body, never as separate graph nodes.

The transcript is plain UTF-8 markdown, oldest tweet first, designed so the classifier reads sections as topic-bounded runs of related tweets.

## Separator and header

Each tweet entry starts with a separator line, then a header line, then a blank line, then the body, then a blank line:

```
---
@<handle> | <iso-8601 instant>

<tweet body verbatim>

```

- `<handle>` is the operator's `username` (the archive owner) for every entry — the tweet stream is operator-authored content only.
- `<iso-8601 instant>` is the parsed `created_at` rendered as `YYYY-MM-DDTHH:MM:SS+00:00`. Always UTC offset (the archive's `created_at` is UTC-fixed).
- `<tweet body verbatim>` is the `full_text` field verbatim — no entity expansion, no URL shortening, no truncation. Entity references (mentions, URLs) appear inline as they did in the original tweet.

## Reply context

When `in_reply_to_status_id_str` is set, the header gets a suffix:

```
---
@<handle> | <iso> | replying to @<in_reply_to_screen_name>

<tweet body verbatim>

```

The skill does not attempt to render the parent tweet body — operator replies that quote the parent verbatim do so naturally inside `full_text`.

## Quote-tweet context

When `quoted_status_id_str` is set, the quoted tweet's text is rendered inline beneath the operator's text, indented as a markdown blockquote prefixed by author and timestamp. The quoted tweet's body comes from the archive when present (`data/tweets.js` may contain quoted tweets the operator authored themselves) or from the entity-expansion URL when not.

```
---
@<handle> | <iso>

<operator's tweet body verbatim>

> @<quoted-author> | <quoted iso>: <quoted body>

```

When the quoted tweet text is not available in the archive (third-party quoted tweet), render:

```
> @<quoted-author>: <quoted-status-url>
```

## Deletion markers

Any tweet referenced in `data/tweet-headers.js` with no matching body in `data/tweets.js` is a deleted tweet. Render in the chronological slot:

```
---
@<handle> | <iso>

[deleted on <iso>]

```

Deletion bodies preserve chronological context for the classifier (a topic-bounded section may include a "deleted" marker between two surviving tweets without the section boundary being broken).

## Media references

Embedded media gets one inline reference per attachment, immediately after the tweet body and before the trailing blank line:

```
---
@<handle> | <iso>

<tweet body verbatim>

[media: photo — <sha256>-<filename>]
[media: video — <sha256>-<filename>]

```

The actual bytes are staged under `{accountDir}/archive/x/<importId>/media/`; the reference token names the file the classifier can read if needed. Binary-only media (video) is referenced but not ingested as a child KD. Document-shaped media (OCR-able images, archived PDFs) recurses through `document-ingest` to land a child KD, attached via `HAS_ENCLOSURE` from the tweet-stream KD.

## Ordering and stability

- Tweets sort by `created_at` ascending — chronological, oldest first.
- Two tweets with identical `created_at` sort by `id_str` ascending (X tweet IDs are time-ordered snowflakes; lexicographic order on the string form is equivalent to numeric order within a millisecond).
- Re-rendering the same archive bytes produces byte-identical output — the `attachmentId = sha256(transcript-bytes)` idempotency contract depends on this.

## Worked example

```
---
@joelsmalley | 2024-07-03T14:23:01+00:00

Just published a piece on retail flows. Curious what @adamlangley thinks.

---
@joelsmalley | 2024-07-03T14:31:22+00:00 | replying to @adamlangley

Fair pushback. The chart on page 4 covers exactly that case.

---
@joelsmalley | 2024-07-03T18:02:00+00:00

QT: this matches my intuition.

> @danmcleod | 2024-07-03T17:45:11+00:00: New data on the Q3 inflow pattern — see thread.

---
@joelsmalley | 2024-07-04T09:00:00+00:00

[deleted on 2024-07-04T09:00:00+00:00]

```

The classifier sees four chronological entries with stable boundaries — a retail-flows topic, a reply continuation, a QT response, then a deletion gap. Whether those become one section or several is the classifier's decision, not this plugin's.
