thurview 0.19.0 → 0.21.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.
Files changed (44) hide show
  1. package/README.md +3 -5
  2. package/dist/cli.js +149 -42
  3. package/dist/cli.js.map +1 -1
  4. package/dist/diff.js +3 -3
  5. package/dist/diff.js.map +1 -1
  6. package/dist/document/compile.js +1 -1
  7. package/dist/document/compile.js.map +1 -1
  8. package/dist/export.js +10 -25
  9. package/dist/export.js.map +1 -1
  10. package/dist/forge/github.js +41 -0
  11. package/dist/forge/github.js.map +1 -1
  12. package/dist/forge/gitlab.js +84 -23
  13. package/dist/forge/gitlab.js.map +1 -1
  14. package/dist/forge/types.js +4 -0
  15. package/dist/forge/types.js.map +1 -1
  16. package/dist/git.js +0 -9
  17. package/dist/git.js.map +1 -1
  18. package/dist/highlight-theme.js +37 -14
  19. package/dist/highlight-theme.js.map +1 -1
  20. package/dist/highlight.js +3 -15
  21. package/dist/highlight.js.map +1 -1
  22. package/dist/pr-review/categories.js +51 -0
  23. package/dist/pr-review/categories.js.map +1 -0
  24. package/dist/pr-review/follow.js +208 -0
  25. package/dist/pr-review/follow.js.map +1 -0
  26. package/dist/pr-review/format.js +227 -0
  27. package/dist/pr-review/format.js.map +1 -0
  28. package/dist/server/server.js +32 -47
  29. package/dist/server/server.js.map +1 -1
  30. package/dist/ui/app.css +65 -30
  31. package/dist/ui/app.js +15 -16
  32. package/dist/ui/app.js.map +2 -2
  33. package/dist/ui/index.html +21 -0
  34. package/package.json +1 -1
  35. package/skills/thurview/SKILL.md +10 -20
  36. package/skills/thurview/references/document-authoring.md +1 -2
  37. package/skills/thurview/references/lifecycle.md +0 -1
  38. package/skills/thurview-design/SKILL.md +4 -7
  39. package/skills/thurview-explain/SKILL.md +6 -7
  40. package/skills/thurview-pr-review/SKILL.md +181 -0
  41. package/skills/thurview-pr-review/references/forges.md +47 -0
  42. package/dist/theme.js +0 -290
  43. package/dist/theme.js.map +0 -1
  44. package/skills/thurview/references/theme.md +0 -89
@@ -4,6 +4,27 @@
4
4
  <meta charset="utf-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1" />
6
6
  <title>thurview</title>
7
+ <script>
8
+ // Before first paint, so the page never flashes the other palette: the
9
+ // reader's pick from the menu wins, and "system" follows the OS, live.
10
+ (() => {
11
+ const os = matchMedia("(prefers-color-scheme: dark)");
12
+ // `chosen` is the menu's pick, so it applies even where storage is blocked
13
+ const apply = (chosen) => {
14
+ let pick = typeof chosen === "string" ? chosen : "system";
15
+ if (typeof chosen !== "string")
16
+ try {
17
+ pick = localStorage.getItem("thurview.theme") || "system";
18
+ } catch {}
19
+ const root = document.documentElement;
20
+ root.dataset.themePick = pick;
21
+ root.dataset.theme = pick === "system" ? (os.matches ? "dark" : "light") : pick;
22
+ };
23
+ os.addEventListener("change", () => apply(document.documentElement.dataset.themePick));
24
+ window.thurviewTheme = apply;
25
+ apply();
26
+ })();
27
+ </script>
7
28
  <link rel="stylesheet" href="/app.css" />
8
29
  </head>
9
30
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thurview",
3
- "version": "0.19.0",
3
+ "version": "0.21.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",
@@ -85,8 +85,7 @@ Read [Document authoring](references/document-authoring.md) before you write.
85
85
  Read [Components](references/components.md) before you edit `data.yaml` or add
86
86
  a fenced component. Read [Lifecycle](references/lifecycle.md) for statuses,
87
87
  storage and thread rules. Read [Software map](references/software-map.md)
88
- before you author `map.yaml`. Read [Theme](references/theme.md) before you
89
- write `theme.yaml`.
88
+ before you author `map.yaml`.
90
89
 
91
90
  ## Workflow
92
91
 
@@ -110,7 +109,7 @@ head), when you need to choose between several.
110
109
 
111
110
  Record from the output: `review.id` (the short id, accepted everywhere),
112
111
  `review.dir`, `review.base`, `review.head`, `files.document`, `files.data`,
113
- `files.map`, `files.theme`, `change` (files, additions, deletions) and
112
+ `files.map`, `change` (files, additions, deletions) and
114
113
  `guidance`.
115
114
 
116
115
  Resolve refs before passing them. Pass commit ids or plain ref names; do not
@@ -237,14 +236,7 @@ not, and publishes as "not assessed". See
237
236
  [Document authoring](references/document-authoring.md) and
238
237
  [Components](references/components.md).
239
238
 
240
- ### 6. Theme the review after the project
241
-
242
- Read [Theme](references/theme.md). Decide the look in its order: what the
243
- user asked for, then the reviewed project's own design system read from its
244
- files at head, then the default skin. Write `theme.yaml` in the review
245
- directory when steps 1 or 2 yield tokens; leave it empty otherwise.
246
-
247
- ### 7. Publish
239
+ ### 6. Publish
248
240
 
249
241
  ```sh
250
242
  thurview publish --review <id>
@@ -252,7 +244,7 @@ thurview publish --review <id>
252
244
 
253
245
  Read every row of `diagnostics`. Fix each `error` and publish again. A
254
246
  `warning` does not block. `publish` refuses (code `THREADS_OPEN`) when a
255
- submitted comment thread is still open (see step 10). On success `published`
247
+ submitted comment thread is still open (see step 9). On success `published`
256
248
  carries `rev` and `url`; the status becomes `awaiting-review`.
257
249
 
258
250
  Then open it for the reader, unless step 2 already did:
@@ -261,7 +253,7 @@ Then open it for the reader, unless step 2 already did:
261
253
  thurview open --review <id> # prints url; --view files|commits|map
262
254
  ```
263
255
 
264
- ### 8. Hand over
256
+ ### 7. Hand over
265
257
 
266
258
  Tell the user, in a few lines and nothing more:
267
259
 
@@ -271,8 +263,6 @@ Tell the user, in a few lines and nothing more:
271
263
  - the interface delta `verdict`, in its own words
272
264
  - the `security` verdict, in one clause: what the change crosses, or that it
273
265
  crosses nothing
274
- - which theme source you used: the user's request, the project's design
275
- system (name the files), or the default skin
276
266
  - when the review has no map, why not, in one clause
277
267
  - that you are now waiting for their questions and their decision, and that
278
268
  a question asked after you stop waiting is queued rather than lost - the
@@ -280,7 +270,7 @@ Tell the user, in a few lines and nothing more:
280
270
 
281
271
  The page explains its own controls; do not describe them.
282
272
 
283
- ### 9. Wait for the reader
273
+ ### 8. Wait for the reader
284
274
 
285
275
  ```sh
286
276
  thurview wait --review <id> --timeout <seconds>
@@ -307,14 +297,14 @@ worktree.
307
297
  not change the document for a question. Wait again.
308
298
  - `awaiting-agent-updates`: the reader submitted with "Request changes".
309
299
  `threads` lists what to address and `wait.decision` the summary. Go to
310
- step 10.
300
+ step 9.
311
301
  - `accepted`: approved. Report and stop.
312
302
  - `closed`: the reader ended the review without approving it. Report and stop.
313
303
  - `review-dismissed` or `review-deleted`: stop.
314
304
  - `timeout`: nothing happened. Wait again, or tell the user the reader has not
315
305
  responded and stop.
316
306
 
317
- ### 10. Address requested changes
307
+ ### 9. Address requested changes
318
308
 
319
309
  For each thread in `thurview threads list --review <id> --open`:
320
310
 
@@ -327,8 +317,8 @@ For each thread in `thurview threads list --review <id> --open`:
327
317
  - `thurview threads resolve <threadId> --review <id>` once the requested
328
318
  change is present. Do not resolve a thread you did not address.
329
319
 
330
- Then publish again (step 7), tell the user what changed since the previous
331
- revision in a line or two, and wait again (step 9). A republish requires zero
320
+ Then publish again (step 6), tell the user what changed since the previous
321
+ revision in a line or two, and wait again (step 8). A republish requires zero
332
322
  open submitted comment threads; questions do not block.
333
323
 
334
324
  ## Sharing a copy that needs no server
@@ -148,7 +148,6 @@ sequence diagram beats one with four.
148
148
 
149
149
  ## Files you edit
150
150
 
151
- Only `review.md`, `data.yaml`, `map.yaml` and `theme.yaml` in the review
152
- directory. Never
151
+ Only `review.md`, `data.yaml` and `map.yaml` in the review directory. Never
153
152
  edit `review.json`, `threads.json` or `revisions/`. Threads change only
154
153
  through `thurview threads`.
@@ -139,7 +139,6 @@ ${THURVIEW_HOME:-~/.thurview}/
139
139
  ├── review.md you edit
140
140
  ├── data.yaml you edit
141
141
  ├── map.yaml you edit
142
- ├── theme.yaml you edit (project look; empty = default skin)
143
142
  ├── review.json binding, pins, status, presented revision
144
143
  ├── threads.json threads and decisions (use the CLI)
145
144
  └── revisions/<n>/ sealed copies plus compiled document.json, map.json
@@ -75,11 +75,11 @@ Read the guidance files that exist, in this order; the second wins on conflict.
75
75
  `thurview design` lists the ones it found under `guidance`.
76
76
 
77
77
  The `thurview` skill ships the references this one shares — components,
78
- software map, theme, lifecycle. `thurview skill` prints the path of every
78
+ software map, lifecycle. `thurview skill` prints the path of every
79
79
  bundled SKILL.md; the references sit beside each one. Read **Components**
80
80
  before you edit `data.yaml`, **Software map** before you author `map.yaml`,
81
- **Theme** before you write `theme.yaml`, and **Lifecycle** for statuses,
82
- storage and thread rules — they are identical for all three kinds.
81
+ and **Lifecycle** for statuses, storage and thread rules — they are identical
82
+ for all three kinds.
83
83
 
84
84
  ## Workflow
85
85
 
@@ -213,10 +213,7 @@ The Map tab is where a design shows structure. Put the structure it
213
213
  A design that changes one part in place does not raise the question: leave
214
214
  `nodes: []` and say so in the handover.
215
215
 
216
- ### 6. Theme, then publish
217
-
218
- Write `theme.yaml` per the `thurview` skill's Theme reference, or leave it
219
- empty for the default skin. Then:
216
+ ### 6. Publish
220
217
 
221
218
  ```sh
222
219
  thurview publish --review <id>
@@ -62,12 +62,12 @@ Read the guidance files that exist, in this order; the second wins on conflict.
62
62
  `thurview explain` lists the ones it found under `guidance`.
63
63
 
64
64
  The `thurview` skill ships the references this one shares - document authoring,
65
- components, software map, searching the code, theme, lifecycle. `thurview skill` prints the path of
65
+ components, software map, searching the code, lifecycle. `thurview skill` prints the path of
66
66
  every bundled SKILL.md; the references sit beside each one. Read **Document
67
67
  authoring** before you write `review.md`, **Components** before you edit
68
68
  `data.yaml`, **Software map** before you author `map.yaml`, **Searching the
69
- code** before you look for callers, tests or importers, **Theme** before you
70
- write `theme.yaml`, and **Lifecycle** for statuses, storage and thread rules -
69
+ code** before you look for callers, tests or importers, and **Lifecycle** for
70
+ statuses, storage and thread rules -
71
71
  they are identical for all three kinds.
72
72
 
73
73
  Run the CLI as `thurview`; `npx -y thurview` runs the published package with
@@ -212,14 +212,13 @@ the code" - not a finding.
212
212
  `interfaces` in `data.yaml` is an error. So is `security`, which is what a
213
213
  change carries input across and an explainer has no change. So is
214
214
  `graph: base` on an anchor - there is one commit.
215
- 5. `theme.yaml` as usual - see **Theme**.
216
- 6. `thurview publish --review <id>`. Read `coverage` and `notExamined`. If the
215
+ 5. `thurview publish --review <id>`. Read `coverage` and `notExamined`. If the
217
216
  split is not the one you meant, anchor, place or search more and publish
218
217
  again.
219
- 7. `thurview open --review <id>`, then `thurview wait --review <id>`. The loop,
218
+ 6. `thurview open --review <id>`, then `thurview wait --review <id>`. The loop,
220
219
  the statuses and the thread rules are identical to a review; see
221
220
  **Lifecycle**.
222
- 8. To share it beyond the browser, `thurview export --review <id> --out <path>`
221
+ 7. To share it beyond the browser, `thurview export --review <id> --out <path>`
223
222
  writes a static, read-only copy - see the `thurview` skill's **Sharing a
224
223
  copy that needs no server**.
225
224
 
@@ -0,0 +1,181 @@
1
+ ---
2
+ name: thurview-pr-review
3
+ description: Review a pull or merge request on the forge itself and follow it until it merges - one short summary with a confidence score that is edited in place, one resolvable inline thread per finding in a fixed set of categories, threads resolved as their findings are fixed, and only what each push changed re-reviewed. Use when the user asks to review a PR or MR and post the review on it, to watch or follow a PR until it lands, for a Greptile-style or bot-style review, or invokes /thurview-pr-review. Not for a review the reader opens in the browser, which is the thurview skill, nor for fixing what a review finds, which is thurview-fix.
4
+ user-invocable: true
5
+ argument-hint: "<PR or MR number or URL> [--once] [--stop]"
6
+ ---
7
+
8
+ # thurview-pr-review
9
+
10
+ Review a change request where its author already is, and keep the review true
11
+ until the change request is merged or closed. The forge holds all the state:
12
+ one summary note with a hidden marker, one thread per finding with a hidden
13
+ marker. Nothing is kept on this machine, so the loop can die and resume
14
+ anywhere.
15
+
16
+ ```mermaid
17
+ flowchart LR
18
+ W[wait] -->|push| R[review only what moved]
19
+ R --> S[sync: new threads, resolve fixed, edit summary]
20
+ S --> W
21
+ W -->|merged, closed, stopped| E[summary says so; stop]
22
+ W -->|none| W
23
+ ```
24
+
25
+ Run the CLI as `thurview`, or `npx -y thurview` when it is not on PATH. It
26
+ prints TOON, and exit code 2 is a usage error. If it answers `unknown flag` or
27
+ `unknown command` for something below, run `thurview update` and retry once.
28
+
29
+ ## Request
30
+
31
+ $ARGUMENTS
32
+
33
+ `--once` posts one pass and stops there. `--stop` runs
34
+ `thurview pr-review stop --change <ref>` and nothing else.
35
+
36
+ ## Never
37
+
38
+ - Never approve, merge, close or push to the change request. The verdict is
39
+ the summary's confidence. The command has no verb for any of those, and you
40
+ do not reach around it with `gh` or `glab`.
41
+ - Never post a second summary. `sync` edits the one it finds.
42
+ - Never post a finding you are not sure of. Leave it out and say in a risk
43
+ bullet that something was not confirmed.
44
+ - Never post what you would not sign. Follow the user's own rules for text
45
+ posted in their name when they keep any - a sign-off line goes in `signoff`.
46
+
47
+ ## 1. Where the review stands
48
+
49
+ ```sh
50
+ thurview pr-review status --change <ref>
51
+ ```
52
+
53
+ It prints the change request's head and base, the head the last pass reviewed
54
+ (`review.reviewedHead`), every open finding with its `id`, and the categories
55
+ and confidence scale below. A stopped review stays stopped: do not sync it.
56
+
57
+ ## 2. Review only what moved
58
+
59
+ - No summary yet: review `git diff <base> <head>`, the whole change.
60
+ - A summary at an older head: review `git diff <reviewedHead> <head>`. When
61
+ `git merge-base --is-ancestor <reviewedHead> <head>` fails, the branch was
62
+ rewritten: review the whole change again.
63
+
64
+ Fetch the head first (`gh pr checkout <n>` or `glab mr checkout <n>`, or
65
+ `git fetch origin <fetchRef>`), and search at the pinned commits with the
66
+ recipes in the `thurview` skill's Searching the code reference
67
+ (`thurview skill` prints its path). The evidence rules are `thurview-fix`'s:
68
+ a problem just as present at the base is not this change's finding, and a
69
+ finding that rests on "no callers" says which search found none.
70
+
71
+ Then decide each open finding against the new head: **fixed**, or **still
72
+ valid** (do nothing - its thread stays open and is not posted again).
73
+
74
+ ## 3. Findings
75
+
76
+ One point per finding, on a line the diff touches - the forge refuses any
77
+ other line. Prefer one real defect over many nits.
78
+
79
+ | Category | Definition |
80
+ | ----------------- | ------------------------------------------------------------------------------ |
81
+ | `bug` | The code does the wrong thing for an input it accepts. |
82
+ | `security` | An attacker gains access, data or execution they should not have. |
83
+ | `performance` | Time, memory or calls grow worse than the change needs. |
84
+ | `reliability` | A failure, retry, timeout or race is handled wrongly or not at all. |
85
+ | `compatibility` | A public API, schema, config, flag or data format breaks its callers. |
86
+ | `maintainability` | The next change here is harder: duplication, dead code, a misleading name. |
87
+ | `tests` | A behaviour the change adds or alters is not tested, or a test proves nothing. |
88
+ | `docs` | A comment, README or doc now says something the code does not do. |
89
+
90
+ Severity is `blocking` (must be fixed before merge), `non-blocking` (worth
91
+ fixing) or `nit` (taste, and the comment says `nit:`).
92
+
93
+ Confidence that the change is safe to merge:
94
+
95
+ | Score | Meaning |
96
+ | ----- | ----------------------------------------------------------- |
97
+ | 5 | Safe to merge; nothing open beyond nits. |
98
+ | 4 | Safe to merge; non-blocking findings are worth a look. |
99
+ | 3 | Unsure: a risk is named that the review could not rule out. |
100
+ | 2 | Not yet: a blocking finding is open. |
101
+ | 1 | Do not merge: it breaks something that works today. |
102
+
103
+ An open blocking finding caps confidence at 2; `sync` refuses more.
104
+
105
+ ## 4. Sync
106
+
107
+ Write `pass.json` for this head. `findings` holds only what is new; `fixed`
108
+ holds the ids of open findings this push fixed:
109
+
110
+ ```json
111
+ {
112
+ "head": "<the full sha you reviewed>",
113
+ "confidence": 2,
114
+ "reason": "Safe once the retry loop stops on a 4xx.",
115
+ "risk": ["Every upload goes through the changed retry path.", "No test covers a 4xx."],
116
+ "change": "Retries a failed upload three times with exponential backoff.",
117
+ "reviewUrl": "https://reviews.example.com/pr-7/",
118
+ "signoff": "<the user's sign-off line, when they keep one>",
119
+ "findings": [
120
+ {
121
+ "category": "bug",
122
+ "severity": "blocking",
123
+ "path": "src/upload.ts",
124
+ "line": 42,
125
+ "startLine": 40,
126
+ "title": "The retry loop never stops on a 4xx.",
127
+ "body": "Return the response on any status below 500.",
128
+ "suggestion": "if (res.status < 500) return res;"
129
+ }
130
+ ],
131
+ "fixed": ["3f2a9c1b07"]
132
+ }
133
+ ```
134
+
135
+ - `head` is the commit you reviewed. `sync` refuses the pass when the change
136
+ request moved on since: review what the new push added, then sync again.
137
+ - `reason`, `change`, `signoff` and each `risk` bullet are one line each;
138
+ `sync` refuses a line break in any of them. `reason` is one sentence;
139
+ `risk` is one to five bullets naming what could break, the blast radius, and
140
+ anything touching security, data, infra or a public API; `change` is two or
141
+ three sentences.
142
+ - The summary is capped at 120 words, the counts table aside. `sync` refuses
143
+ more: cut to what the author acts on.
144
+ - A finding's `title` is the claim in one line, `body` the fix. Title, body
145
+ and sign-off together fit five lines. `suggestion` replaces the lines from
146
+ `startLine` to `line` and is optional.
147
+ - `reviewUrl` links the full rendered review. When the user has a publish
148
+ target - `thurview export --out <folder>` into a Pages folder or a static
149
+ host they serve - publish there and pass its URL. With none, leave it out.
150
+
151
+ ```sh
152
+ thurview pr-review sync --change <ref> --file pass.json --dry-run
153
+ thurview pr-review sync --change <ref> --file pass.json
154
+ ```
155
+
156
+ The dry run prints the summary as it will read. A finding already open is
157
+ reported under `duplicates` and not posted twice.
158
+
159
+ ## 5. Follow
160
+
161
+ ```sh
162
+ thurview pr-review wait --change <ref> # --interval 120 --timeout 540 by default
163
+ ```
164
+
165
+ It blocks until there is something to do and prints one `event`:
166
+
167
+ | Event | Do |
168
+ | ----------------------------- | -------------------------------------------- |
169
+ | `push` | back to step 2, with `since` as the old head |
170
+ | `none` | run `wait` again |
171
+ | `merged`, `closed`, `stopped` | stop: the summary already says so |
172
+
173
+ With `--once`, stop after the first sync.
174
+
175
+ A reader stops the loop with the `thurview:stop` label or a comment that
176
+ starts `/thurview stop`; you stop it with `thurview pr-review stop`. A stopped
177
+ review resumes with `thurview pr-review start --change <ref>` once the label
178
+ is gone. Report what you posted and the summary's link when the loop ends.
179
+
180
+ How GitHub and GitLab differ, and what each supports, is in
181
+ [Forges](references/forges.md).
@@ -0,0 +1,47 @@
1
+ # Forges
2
+
3
+ `thurview pr-review` drives the same seam as `thurview forge`: `gh api` for
4
+ GitHub and `glab api` for GitLab, a self-hosted host owned by whichever CLI is
5
+ authenticated for it. The seam has no merge, close or push, so neither does
6
+ this command.
7
+
8
+ ## What each forge does
9
+
10
+ | Step | GitHub | GitLab |
11
+ | ----------------- | ------------------------------------------ | --------------------------------------------------- |
12
+ | The summary | one issue comment, `PATCH`ed in place | one merge request note, `PUT` in place |
13
+ | A finding | one review comment, a resolvable thread | one diff discussion, a resolvable thread |
14
+ | A line range | anchored as the range | anchored at its last line |
15
+ | A suggestion | ` ```suggestion ` over the range | ` ```suggestion:-N+0 ` reaching back over the range |
16
+ | Resolving a fixed | a reply, then `resolveReviewThread` | a reply, then `PUT .../discussions/<id>` resolved |
17
+ | The stop label | `thurview:stop` among the pull's labels | `thurview:stop` among the merge request's labels |
18
+ | The stop command | an issue comment starting `/thurview stop` | a top-level note starting `/thurview stop` |
19
+ | Merged or closed | `merged`, or `state: closed` | `state: merged` or `closed` |
20
+
21
+ ## Where the state lives
22
+
23
+ The summary carries
24
+ `<!-- thurview-pr-review {"head":"<sha>","state":"active","seen":"<note id>"} -->`
25
+ and each finding's first comment
26
+ `<!-- thurview-finding {"id":"<id>","category":"bug","severity":"blocking"} -->`.
27
+ `state` is `active`, `stopped`, `merged` or `closed`. `seen` is the newest
28
+ note already read, so a `/thurview stop` posted before a `start` stops nothing.
29
+ Only a summary posted by the account the CLI is logged in as counts, so a
30
+ pasted marker changes nothing. A finding's id is the `id` given in the pass, or a hash of its category, path
31
+ and title, which is how the same finding found on the next push is recognised.
32
+
33
+ ## Gaps
34
+
35
+ - No forge approve. A forge approve can arm an auto-merge, and the verdict
36
+ lives in the summary; `thurview forge submit` is the command for one.
37
+ - GitHub reads the newest 100 review threads (`reviewThreads(last:100)`), the
38
+ same limit `thurview forge prior` has; GitLab reads every page.
39
+ - Every call asks the forge who it is (`gh api user`, `glab api user`) to
40
+ tell its own markers from pasted ones, so it needs a token that can read its
41
+ own user; a GitHub App installation token cannot.
42
+ - A finding must sit on a line the diff touches. A finding on an untouched
43
+ caller goes in a risk bullet.
44
+ - GitLab reports no per-thread staleness, and its adapter is driven by stub
45
+ tests but has not been run against a live instance.
46
+ - The full-review link is whatever URL the pass names; this command publishes
47
+ nothing itself.