thurview 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +185 -0
  3. package/bin/thurview.js +8 -0
  4. package/dist/cli.js +1101 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/diff.js +65 -0
  7. package/dist/diff.js.map +1 -0
  8. package/dist/document/compile.js +418 -0
  9. package/dist/document/compile.js.map +1 -0
  10. package/dist/document/parse.js +139 -0
  11. package/dist/document/parse.js.map +1 -0
  12. package/dist/document/schema.js +129 -0
  13. package/dist/document/schema.js.map +1 -0
  14. package/dist/flags.js +66 -0
  15. package/dist/flags.js.map +1 -0
  16. package/dist/git.js +206 -0
  17. package/dist/git.js.map +1 -0
  18. package/dist/highlight-theme.js +93 -0
  19. package/dist/highlight-theme.js.map +1 -0
  20. package/dist/highlight.js +163 -0
  21. package/dist/highlight.js.map +1 -0
  22. package/dist/main.js +3 -0
  23. package/dist/main.js.map +1 -0
  24. package/dist/server/server.js +387 -0
  25. package/dist/server/server.js.map +1 -0
  26. package/dist/store.js +100 -0
  27. package/dist/store.js.map +1 -0
  28. package/dist/symbols.js +192 -0
  29. package/dist/symbols.js.map +1 -0
  30. package/dist/theme.js +301 -0
  31. package/dist/theme.js.map +1 -0
  32. package/dist/threads.js +87 -0
  33. package/dist/threads.js.map +1 -0
  34. package/dist/ui/app.css +1415 -0
  35. package/dist/ui/app.js +2303 -0
  36. package/dist/ui/app.js.map +7 -0
  37. package/dist/ui/assets/fonts/inter-400.woff2 +0 -0
  38. package/dist/ui/assets/fonts/jetbrains-mono-400.woff2 +0 -0
  39. package/dist/ui/assets/fonts/press-start-2p-400.woff2 +0 -0
  40. package/dist/ui/assets/inter-400.woff2 +0 -0
  41. package/dist/ui/assets/jetbrains-mono-400.woff2 +0 -0
  42. package/dist/ui/assets/press-start-2p-400.woff2 +0 -0
  43. package/dist/ui/index.html +13 -0
  44. package/dist/version.js +6 -0
  45. package/dist/version.js.map +1 -0
  46. package/package.json +70 -0
  47. package/skills/thurview/SKILL.md +219 -0
  48. package/skills/thurview/references/components.md +120 -0
  49. package/skills/thurview/references/document-authoring.md +107 -0
  50. package/skills/thurview/references/lifecycle.md +88 -0
  51. package/skills/thurview/references/software-map.md +42 -0
  52. package/skills/thurview/references/theme.md +90 -0
@@ -0,0 +1,219 @@
1
+ ---
2
+ name: thurview
3
+ description: Author and publish a thurview review - a guided, evidence-anchored explanation of a branch, pull request or commit range that the reader opens in the browser, annotates, asks questions about, and approves or sends back. Use when the user asks to review a branch or PR, to explain or walk through a change, "review my branch against main", to explain how a codebase or subsystem works, or invokes /thurview. Not for a pass/fail bug hunt.
4
+ user-invocable: true
5
+ argument-hint: "[<pr-number|pr-url> | --base <ref> --head <ref> | <architecture topic>]"
6
+ ---
7
+
8
+ # thurview
9
+
10
+ The agent studies the change and writes a short document in which every claim
11
+ about code is anchored to an exact file and line range at a pinned commit.
12
+ thurview validates those anchors, seals a revision, and serves it in the
13
+ browser with live code peeks, diffs, diagrams and a map. The reader asks
14
+ questions, leaves anchored comments, and approves or requests changes. The
15
+ agent answers, updates, republishes.
16
+
17
+ ```mermaid
18
+ flowchart LR
19
+ A[scaffold: pin base and head] --> B[author review.md, data.yaml, map.yaml]
20
+ B --> C[publish: validate and seal revision]
21
+ C --> D[open: reader reviews in the browser]
22
+ D -->|question| E[threads reply]
23
+ E --> D
24
+ D -->|request changes| B
25
+ D -->|approve| F[done]
26
+ ```
27
+
28
+ Run the CLI as `thurview`. When it is not on PATH, `npx -y thurview` runs
29
+ the published package with the same commands; substitute it everywhere below.
30
+
31
+ Every command prints TOON on stdout: the result, then `help[]` with the next
32
+ commands. Errors are structured on stdout too (`error`, `code`, `help`); exit
33
+ code 1 is a failure, 2 a usage error such as an unknown flag. Progress goes to
34
+ stderr; do not scrape it. `thurview` alone shows the reviews of the current
35
+ directory; `thurview <command> --help` shows flags and examples.
36
+
37
+ ## Request
38
+
39
+ $ARGUMENTS
40
+
41
+ Empty: the current branch against its up-to-date trunk. A PR number or URL:
42
+ that pull request. `--base`/`--head`: that range. Anything else: an
43
+ architecture review of that topic in the current repository.
44
+
45
+ ## Before authoring
46
+
47
+ Read the guidance files that exist, in this order. The second wins on
48
+ conflict.
49
+
50
+ 1. `~/.thurview/THURVIEW.md` (or `$THURVIEW_HOME/THURVIEW.md`), user guidance.
51
+ 2. `THURVIEW.md` at the repository root, repository guidance.
52
+
53
+ `thurview scaffold` lists the ones it found under `guidance`.
54
+
55
+ Read [Document authoring](references/document-authoring.md) before you write.
56
+ Read [Components](references/components.md) before you edit `data.yaml` or add
57
+ a fenced component. Read [Lifecycle](references/lifecycle.md) for statuses,
58
+ storage and thread rules. Read [Software map](references/software-map.md)
59
+ before you author `map.yaml`. Read [Theme](references/theme.md) before you
60
+ write `theme.yaml`.
61
+
62
+ ## Workflow
63
+
64
+ ### 1. Resolve the review
65
+
66
+ Run `thurview info` in the source worktree. It lists reviews bound to that
67
+ worktree with `inSync` (HEAD equals the pinned head). Reuse a review that
68
+ matches the requested change. Otherwise run `thurview scaffold` with the
69
+ matching flags:
70
+
71
+ ```sh
72
+ thurview scaffold # current branch vs trunk fork point
73
+ thurview scaffold --pr 123 # pull request (needs gh)
74
+ thurview scaffold --base <ref> --head <ref>
75
+ thurview scaffold --new # another review for the same binding
76
+ thurview scaffold --update --review <id> # re-pin after the branch moved
77
+ ```
78
+
79
+ Record from the scaffold output: `review.id` (short id accepted everywhere),
80
+ `review.dir`, `review.base`, `review.head`, `files.document`, `files.data`,
81
+ `files.map`, `files.theme`, `change` (files, additions, deletions) and
82
+ `guidance`.
83
+
84
+ Resolve refs before passing them. Pass commit ids or plain ref names; do not
85
+ pass `<rev>^` inside a jj workspace.
86
+
87
+ ### 2. Show small changes at once
88
+
89
+ When `change.additions + change.deletions` is under 300, publish first and
90
+ land the reader on the diff, then write the document:
91
+
92
+ ```sh
93
+ thurview publish --review <id> --view files --open
94
+ ```
95
+
96
+ The scaffolded stub validates as long as `README.md` exists at head; if it
97
+ does not, point the `entry` anchor at any file that does. Larger changes skip
98
+ this step.
99
+
100
+ ### 3. Study the change
101
+
102
+ Read the whole diff once (`git diff <base> <head>`). Then read each changed
103
+ symbol's callers and callees at head. Trace the main flow through storage,
104
+ network and configuration boundaries. Compare the stated intent (commit
105
+ messages, PR description, the user's own words) with what the code does. The
106
+ gap is the most valuable finding.
107
+
108
+ Read every range you anchor from the pinned commit, not the working tree:
109
+ `git show <head>:<path>` or `git show <base>:<path>`.
110
+
111
+ ### 4. Author the document
112
+
113
+ Edit `review.md` and `data.yaml` in the review directory following
114
+ [Document authoring](references/document-authoring.md). Keep it short.
115
+ Default to anchor links for evidence; use an inline peek only when the reader
116
+ must see the code to follow the main claim.
117
+
118
+ ### 5. Theme the review after the project
119
+
120
+ Read [Theme](references/theme.md). Decide the look in its order: what the
121
+ user asked for, then the reviewed project's own design system read from its
122
+ files at head, then the default skin. Write `theme.yaml` in the review
123
+ directory when steps 1 or 2 yield tokens; leave it empty otherwise. Say
124
+ which source you used when you hand over the review.
125
+
126
+ ### 6. Author the map
127
+
128
+ Dispatch one sub-agent to write `map.yaml` per
129
+ [Software map](references/software-map.md) while you write the document, with
130
+ this prompt filled in:
131
+
132
+ ```text
133
+ Use the thurview skill's software-map reference (`thurview skill` prints the
134
+ SKILL.md path; the reference is in references/software-map.md beside it).
135
+
136
+ Review directory: <dir>
137
+ Source worktree: <worktree>
138
+ Base commit: <base>
139
+ Head commit: <head>
140
+
141
+ Author <dir>/map.yaml: the head structure under nodes/edges and the base
142
+ structure under base. Do not edit review.md or data.yaml. Do not publish.
143
+ Return when `thurview publish --review <id>` reports no map.yaml errors, or
144
+ report the errors you could not fix.
145
+ ```
146
+
147
+ Without a sub-agent facility, write the map yourself after the document, or
148
+ leave `nodes: []` and say the map is not published.
149
+
150
+ ### 7. Publish
151
+
152
+ ```sh
153
+ thurview publish --review <id>
154
+ ```
155
+
156
+ Read every row of `diagnostics`. Fix each `error` and publish again. A
157
+ `warning` does not block. `publish` refuses (code `THREADS_OPEN`) when a
158
+ submitted comment thread is still open (see step 9). On success `published`
159
+ carries `rev` and `url`; the status becomes `awaiting-review`.
160
+
161
+ Then open it for the reader:
162
+
163
+ ```sh
164
+ thurview open --review <id> # prints url; --view files|commits|map
165
+ ```
166
+
167
+ Give the user the `url` from the output.
168
+
169
+ ### 8. Wait for the reader
170
+
171
+ ```sh
172
+ thurview wait --review <id>
173
+ ```
174
+
175
+ It blocks until the reader needs you and prints `wait.reason` with the
176
+ threads that need you:
177
+
178
+ - `question`: an "Ask now" thread. Answer each thread in `threads` with
179
+ `thurview threads reply <threadId> --review <id> --body "<answer>"`. Do
180
+ not change the document for a question. Wait again.
181
+ - `awaiting-agent-updates`: the reader submitted with "Request changes".
182
+ `threads` lists what to address and `wait.decision` the summary. Go to
183
+ step 9.
184
+ - `accepted`: approved. Report and stop.
185
+ - `review-dismissed` or `review-deleted`: stop.
186
+ - error `TIMEOUT` (exit code 1, after `--timeout` seconds, default 3600):
187
+ wait again, or report that the reader has not responded.
188
+
189
+ ### 9. Address requested changes
190
+
191
+ For each thread in `thurview threads list --review <id> --open`:
192
+
193
+ - A document problem: fix `review.md` or `data.yaml`.
194
+ - A code change request: change the branch under the normal rules (failing
195
+ test first), then `thurview scaffold --update --review <id>` to re-pin, and
196
+ re-read every anchored range that moved.
197
+ - Answer in the thread with `threads reply` when the reader asked something
198
+ or when it is not obvious what you changed.
199
+ - `thurview threads resolve <threadId> --review <id>` once the requested
200
+ change is present. Do not resolve a thread you did not address.
201
+
202
+ Then publish again (step 7), and wait again (step 8). A republish requires
203
+ zero open submitted comment threads; questions do not block.
204
+
205
+ ## Architecture reviews
206
+
207
+ Pin the same commit as base and head: `thurview scaffold --base HEAD --head
208
+ HEAD`. Choose sections that describe the system (data flows, state, storage,
209
+ module boundaries) and skip diff-specific ones. Scope to one subsystem. All
210
+ other steps are the same; the Files tab shows any file at head on request.
211
+
212
+ ## Completion criteria
213
+
214
+ Report completion only when all of these hold:
215
+
216
+ - The reader has the URL of a published revision.
217
+ - Every `error` diagnostic is resolved.
218
+ - The map is published, or you said why it is not.
219
+ - The review is waiting on the reader, accepted, dismissed or deleted.
@@ -0,0 +1,120 @@
1
+ # Components
2
+
3
+ `data.yaml` holds typed inputs. `review.md` references them by id. Validation
4
+ is strict: an unknown key fails `publish`.
5
+
6
+ ## data.yaml
7
+
8
+ ```yaml
9
+ actors:
10
+ agent: { label: Agent }
11
+ server: { label: Server, map: system.server } # map: optional node id
12
+
13
+ anchors:
14
+ spawn:
15
+ title: PTY spawn site # required
16
+ detail: Cold-path fallback branch # optional, shown with the peek
17
+ map: system.server # optional node id
18
+ peek: # required for links, peeks and diagrams
19
+ file: src/pty.ts # path at the pinned commit
20
+ from: 214 # 1-based, inclusive
21
+ to: 223 # >= from
22
+ graph: head # head (default) or base
23
+
24
+ stores:
25
+ reviewDb:
26
+ kind: relational # relational (tables) or document (documents)
27
+ label: review.db
28
+ tables:
29
+ threads:
30
+ label: threads # optional
31
+ key: id # optional
32
+ schema:
33
+ id: { type: text, pk: true }
34
+ body: { type: text }
35
+ ```
36
+
37
+ An anchor without `peek` can label a map node but cannot open code.
38
+
39
+ ## Anchor link
40
+
41
+ ```markdown
42
+ [the spawn site](anchor:spawn)
43
+ ```
44
+
45
+ Opens the range in the side peek. The anchor needs a `peek`.
46
+
47
+ ## peek
48
+
49
+ ````markdown
50
+ ```peek
51
+ spawn
52
+ ```
53
+ ````
54
+
55
+ Renders the range inline with title, path and detail.
56
+
57
+ ## sequence
58
+
59
+ ````markdown
60
+ ```sequence
61
+ label: Open a trace quote
62
+ messages:
63
+ - { from: agent, to: server, label: "startLogin(cols, rows)", anchor: spawn }
64
+ - { from: server, to: server, label: "spawnPty(dims)", code: "spawnPty(dims)" }
65
+ - { from: server, to: { label: CLI }, label: ready, anchor: ready }
66
+ ```
67
+ ````
68
+
69
+ `from` and `to` are actor ids or an inline `{ label }`. Each message needs an
70
+ `anchor` (peekable) or `code` (a string, or `{ language, text }`). Clicking a
71
+ message opens its anchor.
72
+
73
+ ## callstack
74
+
75
+ ````markdown
76
+ ```callstack
77
+ title: Warm allocation
78
+ base: [reconcile, auth, enqueueWork]
79
+ head:
80
+ - reconcile
81
+ - enqueueWork
82
+ - { calls: [enqueueWork, processItem], reason: dispatched via the work queue }
83
+ ```
84
+ ````
85
+
86
+ Rules:
87
+
88
+ 1. List order is the stack; each frame calls the one below it.
89
+ 2. One anchor per frame, at the call site or the function head.
90
+ 3. The diff is positional over anchor identity. A frame kept in both stacks
91
+ is one head-graph anchor listed in both lists; it renders as context.
92
+ 4. A frame only in `base` is a removed call; its anchor must use
93
+ `graph: base`. Frames in `head` must use head anchors.
94
+ 5. `{ calls: [parent, child], reason }` marks a hop that is hard to follow
95
+ (queue, callback, RPC). It renders the child with a dashed `≈`.
96
+ 6. One component is one linear stack. Use two for two flows.
97
+ 7. `publish` checks each `-` frame against deleted lines and each `+` frame
98
+ against added lines in the pinned diff. Listing a frame on one side only
99
+ for contrast is rejected.
100
+
101
+ ## database
102
+
103
+ ````markdown
104
+ ```database
105
+ title: Thread storage
106
+ stores: [reviewDb]
107
+ usecases:
108
+ - id: resolve
109
+ label: Resolve a thread
110
+ summary: optional one-liner
111
+ ops:
112
+ - { op: read, store: reviewDb.threads, actor: agent, label: load open threads, anchor: loadThreads }
113
+ - { op: write, store: reviewDb.threads.body, actor: agent, label: mark resolved, anchor: markResolved }
114
+ ```
115
+ ````
116
+
117
+ `store` is `storeId.collection` or `storeId.collection.field`. A read flows
118
+ store to actor; a write flows actor to store; `op` sets the direction. Every
119
+ store used must be listed in `stores`. Every `actor` must exist in
120
+ `data.yaml`. Add this component only when a storage view materially helps.
@@ -0,0 +1,107 @@
1
+ # Document authoring
2
+
3
+ ## Reader contract
4
+
5
+ The reader sees the original request and your document. Not your reasoning,
6
+ not the implementation session, not the names you used while working.
7
+ Jargon coined during implementation is noise to them.
8
+
9
+ The H1 is the review's title in the browser and on the home page. Make it
10
+ short and specific to the change ("Publish pipeline: single mount"), never
11
+ generic.
12
+
13
+ Write short. Decide what to leave out before deciding what to put in. Every
14
+ sentence costs the reader attention; spend it on what they cannot get from the
15
+ diff: intent, the shape of the change, risk, what was left out and why.
16
+
17
+ Write in plain, direct sentences. One idea per sentence. No praise of the
18
+ change ("robust", "comprehensive"). Describe it.
19
+
20
+ ## Structure
21
+
22
+ Open with a landing section between the H1 and the first H2:
23
+
24
+ ```markdown
25
+ # Audit every login
26
+
27
+ **Summary**
28
+
29
+ - login() now records every attempt before checking the user
30
+ - failed attempts are logged too, which the old code skipped
31
+ - one new module, no interface change
32
+
33
+ **Why**
34
+
35
+ Support could not tell whether a locked-out user had tried at all. The
36
+ request was "log every attempt, not only successes".
37
+ ```
38
+
39
+ Then fewer than five further sections when practical. Pick those that fit:
40
+
41
+ - requirements
42
+ - design
43
+ - interface change
44
+ - lifecycle or data flow
45
+ - state or storage
46
+ - testing evidence
47
+ - decision log
48
+
49
+ Add implementation detail only where it lets the reader check an important
50
+ claim. In the decision log, keep the user's requirements in the user's words
51
+ and add the implementation decisions that shaped the result.
52
+
53
+ Do not invent user-impact risks. When risk depends on usage you do not know,
54
+ say so or ask.
55
+
56
+ Collapse optional detail with `{collapsed}` at the end of an H2:
57
+
58
+ ```markdown
59
+ ## Edge cases {collapsed}
60
+ ```
61
+
62
+ Progressive disclosure: every `##` heading is a section the reader can fold.
63
+
64
+ ## Evidence
65
+
66
+ Every claim about code carries an anchor. An anchor is a named source range
67
+ at the pinned base or head commit, defined in `data.yaml`. Link prose to it
68
+ with an anchor link; the browser opens the range beside the document:
69
+
70
+ ```markdown
71
+ The [spawn site](anchor:spawn) falls back to 120x30.
72
+ ```
73
+
74
+ Show code inline only when the reader must see it to follow the main claim:
75
+
76
+ ````markdown
77
+ ```peek
78
+ spawn
79
+ ```
80
+ ````
81
+
82
+ Use the smallest range that proves the claim. Read the range from the pinned
83
+ commit before you anchor it. `publish` rejects an anchor whose file or lines
84
+ do not exist at that commit, and an anchor link to an anchor with no `peek`.
85
+
86
+ A claim you cannot anchor is a question, not a fact. Write it as one.
87
+
88
+ ## Diagrams
89
+
90
+ Use the fenced components for behaviour that prose explains badly:
91
+
92
+ - `sequence` for temporal behaviour across actors
93
+ - `callstack` for call-flow differences between base and head
94
+ - `database` for persisted-state structure and the operations on it
95
+
96
+ Each message, frame and operation carries an anchor, so the reader can open
97
+ the code behind every arrow. See [Components](components.md).
98
+
99
+ Add a diagram only when it materially helps. A document with one good
100
+ sequence diagram beats one with four.
101
+
102
+ ## Files you edit
103
+
104
+ Only `review.md`, `data.yaml`, `map.yaml` and `theme.yaml` in the review
105
+ directory. Never
106
+ edit `review.json`, `threads.json` or `revisions/`. Threads change only
107
+ through `thurview threads`.
@@ -0,0 +1,88 @@
1
+ # Lifecycle and storage
2
+
3
+ ## Binding and pins
4
+
5
+ A review binds to one unit of change: a branch, a pull request, or an
6
+ explicit range. Scaffold resolves and records exact base and head commit
7
+ ids. Everything is read from those commits, so moving the checkout changes
8
+ nothing the reader sees.
9
+
10
+ Choose the base deliberately:
11
+
12
+ - bare scaffold: the trunk fork point (`merge-base` with `origin/HEAD`)
13
+ - one commit: `--base <head>~1 --head <head>`
14
+ - a stack: the branch directly below it
15
+
16
+ `thurview scaffold --update --review <id>` re-pins from the binding: a branch
17
+ follows its local tip, a PR asks GitHub. Publication never moves pins; it
18
+ warns when the branch moved past them.
19
+
20
+ ## Statuses
21
+
22
+ | Status | Owner and next action |
23
+ | ------------------------ | -------------------------------------------------------- |
24
+ | `draft` | Agent authors and publishes. |
25
+ | `awaiting-review` | Reader reads, asks, comments, decides. |
26
+ | `awaiting-agent-updates` | Agent addresses threads, resolves them, republishes. |
27
+ | `accepted` | Terminal. Cannot be republished. |
28
+ | `rejected` | Terminal. |
29
+
30
+ "Ask now" does not change the status. "Submit review" with "Request changes"
31
+ sets `awaiting-agent-updates`; with "Approve" sets `accepted`.
32
+
33
+ Dismissal is separate: the reader removes the review from the active list and
34
+ `wait` returns `review-dismissed`. A new publication restores it.
35
+
36
+ ## Threads
37
+
38
+ Two kinds, chosen by the reader when creating one:
39
+
40
+ - `ask` mode (a question): delivered at once. `wait` returns `question`.
41
+ Answer with `threads reply`. It stays open until the reader resolves it;
42
+ open questions never block a republish.
43
+ - `review` mode (a comment): held as pending until the reader submits. Then
44
+ `wait` returns `awaiting-agent-updates` with the submitted threads.
45
+
46
+ Targets: a document block (with an optional quoted selection), a file line
47
+ on the base or head side, a map node, or the whole review.
48
+
49
+ `publish` after the first revision requires zero open submitted comment
50
+ threads. Resolve a thread only when its requested change is present. Do not
51
+ rewrite or merge threads.
52
+
53
+ ```sh
54
+ thurview threads list --review <id> [--open]
55
+ thurview threads get <threadId> --review <id>
56
+ thurview threads reply <threadId> --review <id> --body "<text>"
57
+ thurview threads resolve <threadId> --review <id>
58
+ ```
59
+
60
+ ## Storage
61
+
62
+ ```text
63
+ ${THURVIEW_HOME:-~/.thurview}/
64
+ ├── THURVIEW.md user guidance (optional)
65
+ ├── server.json running server, if any
66
+ └── reviews/<id>/
67
+ ├── review.md you edit
68
+ ├── data.yaml you edit
69
+ ├── map.yaml you edit
70
+ ├── theme.yaml you edit (project look; empty = default skin)
71
+ ├── review.json binding, pins, status, presented revision
72
+ ├── threads.json threads and decisions (use the CLI)
73
+ └── revisions/<n>/ sealed copies plus compiled document.json, map.json
74
+ ```
75
+
76
+ A failed publish leaves the last sealed revision in place. The reader can
77
+ switch between revisions in the browser.
78
+
79
+ ## wait
80
+
81
+ `thurview wait --review <id> [--timeout <s>]` polls the review and returns
82
+ `wait.reason` in `question`, `awaiting-agent-updates`, `accepted`,
83
+ `rejected`, `review-dismissed`, `review-deleted`, with the threads that need
84
+ you. After the timeout it fails with code `TIMEOUT` (exit 1). A question
85
+ already answered by the agent is not reported again.
86
+
87
+ `thurview threads get <id>` truncates bodies over 1500 characters; pass
88
+ `--full` when the hint says so.
@@ -0,0 +1,42 @@
1
+ # Software map
2
+
3
+ `map.yaml` describes the repository structure at head, and optionally at
4
+ base, as nested nodes. The Map tab lets the reader drill from systems to code
5
+ and shows what the change added, removed or touched.
6
+
7
+ ```yaml
8
+ nodes:
9
+ - { id: app, kind: system, label: Review app, description: Local server and UI }
10
+ - { id: app.cli, kind: container, label: CLI, files: ["src/cli.ts"] }
11
+ - { id: app.server, kind: container, label: Server, files: ["src/server/**"] }
12
+ - { id: app.server.threads, kind: component, label: Threads, files: ["src/threads.ts"], anchor: createThread }
13
+ - { id: reader, kind: person, label: Reader }
14
+ edges:
15
+ - { from: reader, to: app.server, label: reviews in the browser }
16
+ - { from: app.cli, to: app.server, label: publishes revisions }
17
+ base: # optional: structure at the base commit
18
+ nodes: [...]
19
+ edges: [...]
20
+ ```
21
+
22
+ Rules:
23
+
24
+ - `id` is a dot path. Every parent must exist as a node (`app` before
25
+ `app.cli`). Identity is the id; keep ids stable between base and head.
26
+ - `kind`: `person`, `system`, `container`, `component`, `code`.
27
+ - `files`: globs relative to the repository root (`*`, `**`, `?`). They link
28
+ the node to changed files in the Files tab. A glob matching nothing at the
29
+ pinned commit is a warning.
30
+ - `anchor`: an anchor id from `data.yaml` that opens representative code.
31
+ - Edges reference node ids. Labels are short verbs.
32
+
33
+ Model the important people, systems, containers, components and code
34
+ elements. Do not model incidental implementation detail. For a large
35
+ repository, keep the top level small and put detail one level down.
36
+
37
+ Work base first, then apply only the structural changes of the diff to get
38
+ head. Without `base`, nodes touched by the diff show as changed and nothing
39
+ shows as added or removed.
40
+
41
+ `thurview publish` validates the map with the document; map errors block
42
+ publication like document errors. An empty `nodes: []` means no map.
@@ -0,0 +1,90 @@
1
+ # Theme
2
+
3
+ A review looks like the project it reviews. `theme.yaml` in the review
4
+ directory carries the tokens; `publish` validates it and seals it with the
5
+ revision. An empty or absent file gives the default skin.
6
+
7
+ ## Decide the look, in this order
8
+
9
+ Move to the next step only when the current one yields nothing.
10
+
11
+ 1. The user asked for a specific look or named a design system: use that.
12
+ 2. Inspect the reviewed project at the head commit and match its own design
13
+ system: a Tailwind or theme config, CSS custom properties or design
14
+ tokens, a component library theme, brand assets, an existing styled page
15
+ or website directory, font files it ships. Read the real values; do not
16
+ guess. Record what you read in `source`.
17
+ 3. Nothing found: keep the default skin. Do not invent a palette.
18
+
19
+ State which of the three you used when you hand over the review.
20
+
21
+ ## theme.yaml
22
+
23
+ ```yaml
24
+ name: acme-web # shown in the review menu
25
+ source: tailwind.config.ts, src/styles/tokens.css
26
+ mode: light # dark (default) or light
27
+
28
+ colors: # any CSS color; every key optional
29
+ bg: "#ffffff" # page
30
+ bg2: "#f6f7f9" # panels, bars
31
+ bg3: "#eef0f3" # hover
32
+ code: "#f8fafc" # code surfaces
33
+ fg: "#111827" # text
34
+ fg2: "#4b5563" # secondary text
35
+ muted: "#9ca3af"
36
+ line: "#e5e7eb" # borders
37
+ accent: "#2563eb" # headings, primary actions, status
38
+ link: "#2563eb" # links and anchor links
39
+ ok: "#16a34a"
40
+ warn: "#d97706"
41
+ del: "#dc2626"
42
+ add: "rgb(22 163 74 / .12)" # added-line background
43
+ remove: "rgb(220 38 38 / .12)" # deleted-line background
44
+ select: "rgb(217 119 6 / .18)" # highlighted-line background
45
+
46
+ fonts:
47
+ display: "Inter, sans-serif" # brand, buttons, document headings
48
+ body: "Inter, sans-serif"
49
+ mono: "'JetBrains Mono', monospace"
50
+ stylesheets: # external font css, loaded by the page
51
+ - https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap
52
+ files: # font files the project ships, read at head
53
+ - { family: Acme Sans, path: web/public/fonts/acme-sans.woff2, weight: "400 700" }
54
+
55
+ shape:
56
+ radius: 8px # 0 in the default skin
57
+ bevel: false # pixel bevels on panels and buttons
58
+ glow: false # neon text glow on headings and tabs
59
+ scanlines: false # CRT overlay
60
+ headingTransform: none # uppercase in the default skin
61
+
62
+ code: # syntax palette; any key optional
63
+ keyword: "#7c3aed"
64
+ string: "#15803d"
65
+ function: "#b45309"
66
+ type: "#b45309"
67
+ variable: "#0369a1"
68
+ number: "#b45309"
69
+ comment: "#9ca3af"
70
+ punctuation: "#6b7280"
71
+ operator: "#374151"
72
+ tag: "#be185d"
73
+ fg: "#111827"
74
+
75
+ css: | # optional extra rules, appended last
76
+ .doc h1 { letter-spacing: 0; }
77
+ ```
78
+
79
+ Rules:
80
+
81
+ - Keep contrast readable: body text against `bg`, code against `code`.
82
+ - A light project gets `mode: light` and light backgrounds; the default skin
83
+ is dark and its bevels, glow and scanlines are off by default only when you
84
+ set them so.
85
+ - `fonts.files` paths must exist at the pinned head commit; `publish`
86
+ rejects a missing one. Font stylesheets are fetched by the reader's
87
+ browser.
88
+ - Map the project's semantic roles, not its whole palette: primary to
89
+ `accent` and `link`, success/warning/danger to `ok`/`warn`/`del`.
90
+ - Unknown keys fail validation.