KQ-2068 · RUN/JOURNAL
Run Journal
An agent's run written up as it goes, as a journal of short paragraphs with their times in the margin. The newest line is written by a pen nib that rides the end of the text: after each chunk arrives its target is measured from a marker at the end of the words and it moves there on springs.flick along the line and springs.glide when the text wraps, leaning with its speed, while the words it has just written arrive in the accent and dry to ink. Only the newest entries stay written out; as one ages past condenseAfter it condenses on springs.glide into its one-line summary, its measured height closing as the summary fades in, and it opens again on a press or Enter. Up and Down move between entries, Home and End jump, links stay ordinary links, and paused, failed and finished runs each have their own designed state.
Waylight migration agent
Run 18 · orders → ledger schema · 14:02, 15 min
Up and Down move between entries. Enter opens or folds an older entry.
writing entry 4 of 9 · 1 condensed
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/run-journal
Props
- entries
- RunJournalEntry[]
- default defaultRunJournalEntries (9)
- The journal, oldest first: { id, at, text, summary, kind? }. The newest entry is the one being written; [[artifact-id]] or [[artifact-id|words]] in the text becomes a link.
- artifacts
- RunJournalArtifact[]
- default defaultRunJournalArtifacts (5)
- What the prose can link to: { id, label, href, kind? }, listed again in the footer.
- state
- "writing" | "paused" | "failed" | "finished"
- default "writing"
- Where the run stands: the nib writes, lifts away, stops beside a danger mark, or signs off with a closing rule.
- agent
- string
- default "Waylight migration agent"
- Who is writing; the region's accessible name.
- run
- string
- default "Run 18 · orders → ledger schema"
- What the run is, under the agent's name.
- pausedReason
- string
- default "Waiting for approval of the cut-over plan."
- Shown and announced while paused.
- error
- string
- default "Stopped: the orders table stayed locked for 30 seconds."
- Shown and announced when the run has failed.
- now
- number
- default the newest entry's time
- The moment the journal is read, in ms; the header counts the run's length to it.
- utcOffset
- number
- default 0
- Minutes added to UTC before a time is printed.
- condenseAfter
- number
- default 3
- How many of the newest entries stay written out; older ones condense to their summary line.
- expanded / defaultExpanded
- string[]
- default — / []
- Ids of aged entries opened by hand.
- onExpandEntry
- (id: string, open: boolean) => void
- default —
- A condensed entry was opened, or an opened one folded again.
- onOpenArtifact
- (artifact: RunJournalArtifact, event: React.MouseEvent<HTMLAnchorElement>) => void
- default —
- A link to an artifact was followed, in the prose or the footer. It stays an ordinary link unless you prevent the event.
- onStop
- () => void
- default —
- Stop was pressed while writing or paused.
- onResume
- () => void
- default —
- Resume was pressed while paused.
- nibStyle
- "nib" | "pencil" | "caret"
- default "nib"
- What writes the newest line: a fountain-pen nib, a pencil tip, or a heavy caret.
- accent
- string
- default "var(--accent-bright)"
- Wet ink, the nib, decision marks, links and the writing pill — any CSS colour.
- height
- number
- default 520
- The journal's height in px; the entries scroll inside it and stay pinned to the newest line while you are there.
- status
- "ready" | "loading" | "error"
- default "ready"
- Whether the journal has loaded; loading draws placeholder lines, error offers Try again.
- onReload
- () => void
- default —
- Try again was pressed after the journal failed to load.
- className
- string
- default —
- Classes for the outer region.
| Prop | Type | Default | Description |
|---|---|---|---|
| entries | RunJournalEntry[] | defaultRunJournalEntries (9) | The journal, oldest first: { id, at, text, summary, kind? }. The newest entry is the one being written; [[artifact-id]] or [[artifact-id|words]] in the text becomes a link. |
| artifacts | RunJournalArtifact[] | defaultRunJournalArtifacts (5) | What the prose can link to: { id, label, href, kind? }, listed again in the footer. |
| state | "writing" | "paused" | "failed" | "finished" | "writing" | Where the run stands: the nib writes, lifts away, stops beside a danger mark, or signs off with a closing rule. |
| agent | string | "Waylight migration agent" | Who is writing; the region's accessible name. |
| run | string | "Run 18 · orders → ledger schema" | What the run is, under the agent's name. |
| pausedReason | string | "Waiting for approval of the cut-over plan." | Shown and announced while paused. |
| error | string | "Stopped: the orders table stayed locked for 30 seconds." | Shown and announced when the run has failed. |
| now | number | the newest entry's time | The moment the journal is read, in ms; the header counts the run's length to it. |
| utcOffset | number | 0 | Minutes added to UTC before a time is printed. |
| condenseAfter | number | 3 | How many of the newest entries stay written out; older ones condense to their summary line. |
| expanded / defaultExpanded | string[] | — / [] | Ids of aged entries opened by hand. |
| onExpandEntry | (id: string, open: boolean) => void | — | A condensed entry was opened, or an opened one folded again. |
| onOpenArtifact | (artifact: RunJournalArtifact, event: React.MouseEvent<HTMLAnchorElement>) => void | — | A link to an artifact was followed, in the prose or the footer. It stays an ordinary link unless you prevent the event. |
| onStop | () => void | — | Stop was pressed while writing or paused. |
| onResume | () => void | — | Resume was pressed while paused. |
| nibStyle | "nib" | "pencil" | "caret" | "nib" | What writes the newest line: a fountain-pen nib, a pencil tip, or a heavy caret. |
| accent | string | "var(--accent-bright)" | Wet ink, the nib, decision marks, links and the writing pill — any CSS colour. |
| height | number | 520 | The journal's height in px; the entries scroll inside it and stay pinned to the newest line while you are there. |
| status | "ready" | "loading" | "error" | "ready" | Whether the journal has loaded; loading draws placeholder lines, error offers Try again. |
| onReload | () => void | — | Try again was pressed after the journal failed to load. |
| className | string | — | Classes for the outer region. |