thurview 0.6.0 → 0.8.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thurview",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "Guided, evidence-anchored reviews of agent-written code. A coding agent authors the review; you read, ask, comment and decide in the browser.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,12 +1,24 @@
1
1
  ---
2
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.
3
+ description: Author and publish a thurview document - a guided, evidence-anchored explanation the reader opens in the browser, annotates, asks questions about, and approves or sends back. Two kinds: a review of a branch, pull request or commit range, and a code explainer of a whole codebase or one subsystem at a pinned commit. 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 where its design problems might be, or invokes /thurview. Not for a pass/fail bug hunt.
4
4
  user-invocable: true
5
- argument-hint: "[<pr-number|pr-url> | --base <ref> --head <ref> | <architecture topic>]"
5
+ argument-hint: "[<pr-number|pr-url> | --base <ref> --head <ref> | explain [<path>]]"
6
6
  ---
7
7
 
8
8
  # thurview
9
9
 
10
+ There are two kinds of document, and the first decision is which one the
11
+ request asks for.
12
+
13
+ - A **review** explains a CHANGE: a branch, a pull request, a commit range. It
14
+ has a diff, commits and an interface delta, and the reader approves it or
15
+ sends it back. Everything below describes it.
16
+ - A **code explainer** explains a CODEBASE, or one subsystem, at a single
17
+ pinned commit, so the reader can see the architecture well enough to spot
18
+ design problems themselves. It has no diff and nothing to approve, and it
19
+ states what it did not examine. Read
20
+ [Code explainer](references/code-explainer.md) and follow that instead.
21
+
10
22
  The agent studies the change and writes a short document in which every claim
11
23
  about code is anchored to an exact file and line range at a pinned commit.
12
24
  thurview validates those anchors, seals a revision, and serves it in the
@@ -41,9 +53,11 @@ directory; `thurview <command> --help` shows flags and examples.
41
53
 
42
54
  $ARGUMENTS
43
55
 
44
- Empty: the current branch against its up-to-date trunk. A PR number or URL:
45
- that pull request. `--base`/`--head`: that range. Anything else: an
46
- architecture review of that topic in the current repository.
56
+ Empty: a review of the current branch against its up-to-date trunk. A PR
57
+ number or URL: that pull request. `--base`/`--head`: that range. `explain`, or
58
+ a request to explain the codebase, a subsystem or its architecture rather than
59
+ a change: a code explainer, per
60
+ [Code explainer](references/code-explainer.md).
47
61
 
48
62
  ## Before authoring
49
63
 
@@ -60,7 +74,8 @@ Read [Components](references/components.md) before you edit `data.yaml` or add
60
74
  a fenced component. Read [Lifecycle](references/lifecycle.md) for statuses,
61
75
  storage and thread rules. Read [Software map](references/software-map.md)
62
76
  before you author `map.yaml`. Read [Theme](references/theme.md) before you
63
- write `theme.yaml`.
77
+ write `theme.yaml`. Read [Code explainer](references/code-explainer.md) when
78
+ the request is a codebase rather than a change.
64
79
 
65
80
  ## Workflow
66
81
 
@@ -150,11 +165,18 @@ reader who wanted them would have run those instead.
150
165
  Read every range you anchor from the pinned commit, not the working tree:
151
166
  `git show <head>:<path>` or `git show <base>:<path>`.
152
167
 
153
- ### 4. Start the map
168
+ ### 4. Decide on the map, then start it
154
169
 
155
- Dispatch one sub-agent to write `map.yaml` per
156
- [Software map](references/software-map.md) now, so it works while you write
157
- the document, with this prompt filled in:
170
+ The Map tab answers where the change landed in the system and what sits next
171
+ to it. A change that lands in one place does not raise that question: leave
172
+ `nodes: []`, say why in the handover, and go to step 5. A change that crosses a
173
+ boundary, adds or removes a part, or reaches code the diff does not show, does:
174
+ map it. [Software map](references/software-map.md) makes that call in full, and
175
+ a map that earns nothing is worse for the reader than none.
176
+
177
+ When it earns its place, dispatch one sub-agent to write `map.yaml` per that
178
+ reference now, so it works while you write the document, with this prompt
179
+ filled in:
158
180
 
159
181
  ```text
160
182
  Use the thurview skill's software-map reference (`thurview skill` prints the
@@ -226,6 +248,7 @@ Tell the user, in a few lines and nothing more:
226
248
  - the interface delta `verdict`, in its own words
227
249
  - which theme source you used: the user's request, the project's design
228
250
  system (name the files), or the default skin
251
+ - when the review has no map, why not, in one clause
229
252
  - that you are now waiting for their questions and their decision
230
253
 
231
254
  The page explains its own controls; do not describe them.
@@ -273,12 +296,17 @@ Then publish again (step 7), tell the user what changed since the previous
273
296
  revision in a line or two, and wait again (step 9). A republish requires zero
274
297
  open submitted comment threads; questions do not block.
275
298
 
276
- ## Architecture reviews
299
+ ## Explaining a codebase rather than a change
300
+
301
+ Do not pin the same commit as base and head to fake it. That leaves a review
302
+ whose Files, Commits and interface-delta surfaces all describe a change that
303
+ does not exist, which is a claim, not a gap.
277
304
 
278
- Pin the same commit as base and head: `thurview scaffold --base HEAD --head
279
- HEAD`. Choose sections that describe the system (data flows, state, storage,
280
- module boundaries) and skip diff-specific ones. Scope to one subsystem. All
281
- other steps are the same; the Files tab shows any file at head on request.
305
+ Run `thurview explain [<path>]` instead and follow
306
+ [Code explainer](references/code-explainer.md). It is the same loop - pin,
307
+ author, publish, wait, answer - over a document kind whose unit is a codebase:
308
+ no diff, no commits, no interface delta, and a Coverage tab stating what the
309
+ document reached and what it did not.
282
310
 
283
311
  ## Completion criteria
284
312
 
@@ -0,0 +1,166 @@
1
+ # Code explainer
2
+
3
+ A **review** explains a change. An **explainer** explains a codebase, or one
4
+ subsystem of it, at a single pinned commit, so the reader can see the
5
+ architecture well enough to spot design problems themselves.
6
+
7
+ Same engine, different unit. It shares anchors, peeks, the map, threads,
8
+ revisions and the publish → wait → answer loop. It has no diff, no commits and
9
+ no interface delta, because those are claims about a change and there is no
10
+ change. Where a review shows the interface delta, an explainer shows
11
+ **coverage**: what it examined at that commit, and what it did not.
12
+
13
+ | Tab | Review | Explainer |
14
+ | ------------- | ---------------------------------- | --------------------------------------------- |
15
+ | Review | the walkthrough, with the delta | **Explainer**: the document, with coverage |
16
+ | Files | split diff of the changed files | absent |
17
+ | Commits | base..head | absent |
18
+ | Map | parts, marked added/changed/removed | parts at the pinned commit |
19
+ | Coverage | absent | **what the document reached, and what it did not** |
20
+ | Threads | ask, comment, decide | same, and the decision reads *Done reading* / *Send it back* |
21
+
22
+ ## When to write one
23
+
24
+ Write an explainer when the request is about the code as it stands: "explain
25
+ this codebase", "how does the server work", "walk me through `src/graph`",
26
+ "I want to see the architecture". Write a review when the request is about a
27
+ change: a branch, a pull request, a range.
28
+
29
+ If the request is a change, do not reach for an explainer because the change is
30
+ large. A large change is still a change.
31
+
32
+ ## The document kind, in one command
33
+
34
+ ```sh
35
+ thurview explain # the whole repository at HEAD
36
+ thurview explain src/server # one subsystem
37
+ thurview explain --commit v1.2.0 # a released commit rather than HEAD
38
+ ```
39
+
40
+ The positional argument is a path or a glob; a bare path means that directory
41
+ and everything under it. It is the **scope**, and everything else obeys it:
42
+ `graph architecture` reports the clusters inside it, and coverage accounts for
43
+ every file inside it. A scope that matches no file at that commit is refused.
44
+
45
+ Record `explainer.id`, `explainer.dir`, `explainer.commit`, `explainer.scope`
46
+ and `scale.filesInScope` from the output. Everywhere else the id is passed as
47
+ `--review <id>`; that flag names a document, whichever kind it is.
48
+
49
+ ## Keeping it short without lying about it
50
+
51
+ A review is bounded by its diff. A codebase is not, and this is the hard part:
52
+ evidence-anchored prose over a whole repository either runs unreadably long or
53
+ quietly leaves most of the system out. Prose that leaves things out silently is
54
+ misleading about architecture, which is the one thing an explainer must not be.
55
+
56
+ So work in three layers, and let each carry what it is good at.
57
+
58
+ 1. **System — the map carries breadth.** Author `map.yaml` first, seeded from
59
+ `thurview graph architecture --review <id>`: communities become nodes, their
60
+ files become the node's `files` globs, and the edges between communities
61
+ become edges. Every part of the scope should appear here, including the parts
62
+ the prose will not reach. See [Software map](software-map.md) for the shape.
63
+ 2. **Subsystem — the prose carries depth.** Pick the parts that carry the most
64
+ structure and the most traffic, and explain those. Three to six sections.
65
+ Everything else stays on the map.
66
+ 3. **File and symbol — anchors carry the proof.** Every claim gets an anchor.
67
+ The reader opens code where they want it and nowhere else.
68
+
69
+ **Select by structure, not by taste, and say what you selected on.** The graph
70
+ gives you the basis: cluster size in files and symbols, the hub symbols of each
71
+ cluster (most referenced), and the reference counts on the edges between
72
+ clusters. Say in the document which parts you took and why they were the ones -
73
+ "the two clusters with the most traffic between them" is a reason a reader can
74
+ check. "The interesting bits" is not.
75
+
76
+ ## Coverage is derived, not claimed
77
+
78
+ `thurview publish` accounts for every file in scope at the pinned commit and
79
+ puts one of three states on it:
80
+
81
+ - **explained** - an anchor in the document points into the file.
82
+ - **placed** - a map node's `files` globs match it, and no anchor does. The
83
+ reader is told where it sits, not what it does.
84
+ - **not examined** - neither.
85
+
86
+ The counts go above the document and onto the Coverage tab, and `publish`
87
+ prints them with the files it did not examine. You cannot forget to state
88
+ coverage, and you cannot overstate it: to move a file out of *not examined* you
89
+ have to actually anchor it or actually place it on the map.
90
+
91
+ Two consequences worth planning for:
92
+
93
+ - **An explainer without a map counts everything the prose does not anchor as
94
+ not examined.** `publish` warns when there is no map. That is a true
95
+ statement, and usually not the one you want to make: author the map.
96
+ - **A broad glob is visible.** The Coverage tab lists each map node with the
97
+ globs it owns and how many files they match, so `**/*` on one node inflates
98
+ nothing quietly.
99
+
100
+ Coverage also states what the code graph could not read: files in languages it
101
+ does not parse (`thurview graph` covers TypeScript, JavaScript, Python, Go,
102
+ Rust and Java), and whether its file list was capped. Those files are absent
103
+ from the structure, not empty. If a large part of the scope is outside the
104
+ graph, say so in the document rather than letting the map imply the system is
105
+ smaller than it is.
106
+
107
+ ## Surface structure; do not grade it
108
+
109
+ thurview's thesis holds here: *it does not review the code for you; it helps
110
+ you understand it fast enough to review it yourself.* An explainer exists so
111
+ the reader can **detect** design problems. That is only consistent with the
112
+ thesis if you surface structure and leave the conclusion to them.
113
+
114
+ The test: **every fact in an explainer is a count, or a list of named things,
115
+ at the pinned commit, that the reader could re-derive with `thurview graph`.**
116
+
117
+ Observation - write these:
118
+
119
+ - "`src/server` is referenced from four other parts; it references one."
120
+ - "`Store` is defined in `src/db.ts` and `src/cache.ts`."
121
+ - "The API layer reaches the database layer in 14 places and the model layer in
122
+ 2; the model layer reaches the API layer in 6."
123
+ - "Nothing in the scope references `legacy/` at this commit."
124
+ - "No test file reaches this cluster." (a count of zero, stated as one)
125
+
126
+ Judgement - never write these:
127
+
128
+ - "This violates separation of concerns."
129
+ - "The god object here should be split."
130
+ - severities, scores, "issues found", "critical", "smell", a ranked list of
131
+ problems, or a recommendation section.
132
+
133
+ The difference is not tone. "A module with 14 inbound dependencies" is
134
+ something the reader acts on; "an over-coupled module" is a verdict they cannot
135
+ check. When you are unsure, write the count and stop. If a structure genuinely
136
+ worries you, the honest move is a question in the document - "the two stores
137
+ both define `Session`; whether that is one concept or two is not visible from
138
+ the code" - not a finding.
139
+
140
+ ## Workflow
141
+
142
+ 1. `thurview explain [<scope>]`. Note the id, the commit and the scope.
143
+ 2. `thurview graph architecture --review <id>`. This is the structure at the
144
+ pinned commit; do not re-derive it by reading directories.
145
+ `thurview graph callers <name>` and `tests-for <name>` answer the follow-ups.
146
+ `graph interfaces` and `graph impact` compare two commits and are refused.
147
+ 3. Author `map.yaml` from the architecture output, covering the whole scope.
148
+ Dispatch a sub-agent for it if you have one, exactly as a review does.
149
+ 4. Author `review.md` and `data.yaml` per [Document authoring](document-authoring.md),
150
+ minus the interface-delta section: an explainer has none, and declaring
151
+ `interfaces` in `data.yaml` is an error. So is `graph: base` on an anchor -
152
+ there is one commit.
153
+ 5. `theme.yaml` as usual - see [Theme](theme.md).
154
+ 6. `thurview publish --review <id>`. Read `coverage` and `notExamined`. If the
155
+ split is not the one you meant, anchor or place more and publish again.
156
+ 7. `thurview open --review <id>`, then `thurview wait --review <id>`. The loop,
157
+ the statuses and the thread rules are identical to a review; see
158
+ [Lifecycle](lifecycle.md).
159
+
160
+ ## Hand over
161
+
162
+ In a few lines: the url, the scope and the commit, the coverage line in its own
163
+ words (including how many files were not examined), which parts you chose to
164
+ explain and on what basis, and that you are waiting for their questions. Do not
165
+ list the design problems you think you saw. The document is built so the reader
166
+ finds them.
@@ -1,8 +1,66 @@
1
1
  # Software map
2
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.
3
+ ## What it is for
4
+
5
+ The Files tab already answers *which lines changed*. The map answers the one
6
+ question no other tab does: **where the change landed in the system, and what
7
+ sits next to it.** A reader opens it to find out which parts the diff touched,
8
+ what those parts connect to, and therefore what could break that the diff
9
+ never mentions — and where to start reading.
10
+
11
+ That makes the map a reviewing instrument, not a picture of the architecture.
12
+ The Map tab reads it that way: parts the change touched are drawn before the
13
+ parts it did not, a part carrying changed files says how many, links into a
14
+ changed part are marked as the seams where two sides can fall out of step, and
15
+ the reader is offered one part to start at. A node that answers none of *where
16
+ did the change land*, *what does it sit next to*, *where do I start* does not
17
+ sit there harmlessly — it makes the ones that do harder to find.
18
+
19
+ Write it, then read it as the reader: does it send someone to the part of the
20
+ change that needs attention faster than scrolling the diff would? If not,
21
+ either cut nodes until it does, or ship no map at all.
22
+
23
+ ## When to ship without a map
24
+
25
+ `nodes: []` is a real answer, not a gap. A map that adds nothing costs the
26
+ reader a tab they open, learn nothing from, and distrust on the next review.
27
+ An absent one costs nothing.
28
+
29
+ Ship without a map when:
30
+
31
+ - The change lands in one place and stays there. The Files tab already says
32
+ where it is; a map would only restate it with rounded corners.
33
+ - Every part you could name is a file the diff already lists. The map would be
34
+ the Files tab with fewer details.
35
+ - The repository has no structure worth naming at review scale — a handful of
36
+ modules with no boundary between them.
37
+
38
+ Author one when:
39
+
40
+ - The change crosses a boundary: one part now calls, stores or serves
41
+ something another part owns.
42
+ - It adds or removes a part, so the shape of the system is different after it.
43
+ - What the change touches is used by code the diff does not show, and the
44
+ reader has to know what that is before judging it.
45
+ - The review is an architecture review. There the map is the subject, not the
46
+ orientation for one.
47
+
48
+ When you skip it, say so in the handover, with the reason, in one line. Silence
49
+ reads as an oversight.
50
+
51
+ ## What to model
52
+
53
+ Model the people, systems, containers, components and code elements a reader
54
+ must hold in mind to judge **this** change. Do not model incidental
55
+ implementation detail, and do not aim for completeness: an exhaustive map and
56
+ no map cost the reader about the same. For a large repository, keep the top
57
+ level small and put detail one level down, so the first screen is a short list
58
+ of places the change could be.
59
+
60
+ ## Schema
61
+
62
+ `map.yaml` describes the repository structure at head, and optionally at base,
63
+ as nested nodes.
6
64
 
7
65
  ```yaml
8
66
  nodes:
@@ -25,17 +83,20 @@ Rules:
25
83
  `app.cli`). Identity is the id; keep ids stable between base and head.
26
84
  - `kind`: `person`, `system`, `container`, `component`, `code`.
27
85
  - `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.
86
+ the node to changed files in the Files tab, and they are what makes a node
87
+ say how much of the change it holds. A glob matching nothing at the pinned
88
+ commit is a warning.
89
+ - `anchor`: an anchor id from `data.yaml` that opens representative code. Give
90
+ one to every node the change touched; it is the shortest path from the map
91
+ to the code.
31
92
  - Edges reference node ids. Labels are short verbs.
32
93
 
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.
94
+ ## Base and head
36
95
 
37
96
  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
97
+ head. That is what lets the tab say *added*, *removed* and *changed* rather
98
+ than *touched*, and those three words are most of what a reader takes from the
99
+ map. Without `base`, nodes touched by the diff show as changed and nothing
39
100
  shows as added or removed.
40
101
 
41
102
  `thurview publish` validates the map with the document; map errors block