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/README.md +38 -18
- package/dist/cli.js +273 -16
- package/dist/cli.js.map +1 -1
- package/dist/coverage.js +208 -0
- package/dist/coverage.js.map +1 -0
- package/dist/document/compile.js +25 -10
- package/dist/document/compile.js.map +1 -1
- package/dist/graph.js +25 -4
- package/dist/graph.js.map +1 -1
- package/dist/server/server.js +4 -2
- package/dist/server/server.js.map +1 -1
- package/dist/store.js +4 -0
- package/dist/store.js.map +1 -1
- package/dist/ui/app.css +282 -5
- package/dist/ui/app.js +718 -190
- package/dist/ui/app.js.map +4 -4
- package/package.json +1 -1
- package/skills/thurview/SKILL.md +43 -15
- package/skills/thurview/references/code-explainer.md +166 -0
- package/skills/thurview/references/software-map.md +71 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thurview",
|
|
3
|
-
"version": "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",
|
package/skills/thurview/SKILL.md
CHANGED
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: thurview
|
|
3
|
-
description: Author and publish a thurview
|
|
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> | <
|
|
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
|
|
45
|
-
that pull request. `--base`/`--head`: that range.
|
|
46
|
-
|
|
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.
|
|
168
|
+
### 4. Decide on the map, then start it
|
|
154
169
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
the
|
|
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
|
-
##
|
|
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
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
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.
|
|
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
|