visualproof 0.0.0-stage → 0.1.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 (128) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +99 -2
  3. package/dist/assets/fonts/JuliaMono-Regular.ttf +0 -0
  4. package/dist/assets/fonts/JuliaMono-RegularItalic.ttf +0 -0
  5. package/dist/assets/fonts/JuliaMono-SemiBold.ttf +0 -0
  6. package/dist/assets/fonts/LICENSE-JuliaMono.txt +93 -0
  7. package/dist/assets/latex/visualproof.sty +308 -0
  8. package/dist/extractor/Extract.lean +1180 -0
  9. package/dist/extractor/Usage.lean +900 -0
  10. package/dist/mcp/visualproof-mcp.mjs +476 -0
  11. package/dist/server/access.js +95 -0
  12. package/dist/server/agent.js +3235 -0
  13. package/dist/server/agentdocs.js +35 -0
  14. package/dist/server/agentlibrary.js +202 -0
  15. package/dist/server/agentnotes.js +701 -0
  16. package/dist/server/agentviews.js +703 -0
  17. package/dist/server/askfollow.js +286 -0
  18. package/dist/server/boardspots.js +159 -0
  19. package/dist/server/dirs.js +175 -0
  20. package/dist/server/doctor.js +186 -0
  21. package/dist/server/events.js +198 -0
  22. package/dist/server/export.js +420 -0
  23. package/dist/server/extract.js +204 -0
  24. package/dist/server/fetchurl.js +321 -0
  25. package/dist/server/figures.js +158 -0
  26. package/dist/server/history.js +741 -0
  27. package/dist/server/historyapi.js +304 -0
  28. package/dist/server/hover.js +595 -0
  29. package/dist/server/identity.js +114 -0
  30. package/dist/server/invites.js +241 -0
  31. package/dist/server/layoutthread.js +51 -0
  32. package/dist/server/library.js +600 -0
  33. package/dist/server/libraryroute.js +211 -0
  34. package/dist/server/live.js +1101 -0
  35. package/dist/server/lostfound.js +199 -0
  36. package/dist/server/main.js +1394 -0
  37. package/dist/server/mcptools.js +497 -0
  38. package/dist/server/pastdoc.js +73 -0
  39. package/dist/server/pipeline.js +156 -0
  40. package/dist/server/poppler.js +251 -0
  41. package/dist/server/presence.js +252 -0
  42. package/dist/server/project.js +222 -0
  43. package/dist/server/prompt.js +53 -0
  44. package/dist/server/readonly.js +152 -0
  45. package/dist/server/readonlygate.js +123 -0
  46. package/dist/server/renames.js +268 -0
  47. package/dist/server/review.js +334 -0
  48. package/dist/server/reviewapi.js +188 -0
  49. package/dist/server/snapshot.js +49 -0
  50. package/dist/server/sourcestore.js +473 -0
  51. package/dist/server/status.js +360 -0
  52. package/dist/server/talk.js +476 -0
  53. package/dist/server/tokens.js +221 -0
  54. package/dist/server/usage.js +501 -0
  55. package/dist/server/versions.js +82 -0
  56. package/dist/server/view.js +157 -0
  57. package/dist/server/views.js +1167 -0
  58. package/dist/shared/askfollow.js +46 -0
  59. package/dist/shared/board.js +332 -0
  60. package/dist/shared/build.js +2 -0
  61. package/dist/shared/collab.js +148 -0
  62. package/dist/shared/comment.js +285 -0
  63. package/dist/shared/context.js +157 -0
  64. package/dist/shared/doc/authors.js +98 -0
  65. package/dist/shared/doc/build.js +358 -0
  66. package/dist/shared/doc/latex.js +455 -0
  67. package/dist/shared/doc/markdown.js +159 -0
  68. package/dist/shared/doc/model.js +37 -0
  69. package/dist/shared/doc/order.js +107 -0
  70. package/dist/shared/doc/proof.js +272 -0
  71. package/dist/shared/doc/sections.js +93 -0
  72. package/dist/shared/doc/settings.js +75 -0
  73. package/dist/shared/edgecodec.js +102 -0
  74. package/dist/shared/editor.js +64 -0
  75. package/dist/shared/excerpt.js +87 -0
  76. package/dist/shared/graph.js +16 -0
  77. package/dist/shared/items.js +92 -0
  78. package/dist/shared/keys.js +203 -0
  79. package/dist/shared/layout.js +926 -0
  80. package/dist/shared/lexer.js +130 -0
  81. package/dist/shared/library.js +711 -0
  82. package/dist/shared/lostfound.js +150 -0
  83. package/dist/shared/moves.js +243 -0
  84. package/dist/shared/notecard.js +295 -0
  85. package/dist/shared/noteplace.js +505 -0
  86. package/dist/shared/palette.js +46 -0
  87. package/dist/shared/pastgraph.js +95 -0
  88. package/dist/shared/places.js +80 -0
  89. package/dist/shared/projectnotes.js +244 -0
  90. package/dist/shared/query.js +810 -0
  91. package/dist/shared/review.js +642 -0
  92. package/dist/shared/reviewqueue.js +333 -0
  93. package/dist/shared/ring.js +366 -0
  94. package/dist/shared/scope.js +255 -0
  95. package/dist/shared/scopeedit.js +81 -0
  96. package/dist/shared/search.js +191 -0
  97. package/dist/shared/separate.js +178 -0
  98. package/dist/shared/sharesnap.js +280 -0
  99. package/dist/shared/sticky.js +501 -0
  100. package/dist/shared/timeline.js +73 -0
  101. package/dist/shared/titles.js +298 -0
  102. package/dist/shared/viewgraph.js +139 -0
  103. package/dist/shared/views.js +859 -0
  104. package/dist/web/bundle/app.js +48733 -0
  105. package/dist/web/bundle/edges.js +409 -0
  106. package/dist/web/bundle/layout.js +1010 -0
  107. package/dist/web/bundle/pdfworker.js +48322 -0
  108. package/dist/web/index.html +239 -0
  109. package/dist/web/src/motion.js +430 -0
  110. package/dist/web/src/past.js +224 -0
  111. package/dist/web/src/scene.js +787 -0
  112. package/dist/web/style.css +2312 -0
  113. package/docs/agent-api/README.md +91 -0
  114. package/docs/agent-api/advice.md +108 -0
  115. package/docs/agent-api/export.md +120 -0
  116. package/docs/agent-api/following.md +140 -0
  117. package/docs/agent-api/history.md +142 -0
  118. package/docs/agent-api/library.md +65 -0
  119. package/docs/agent-api/mcp.md +104 -0
  120. package/docs/agent-api/notes.md +93 -0
  121. package/docs/agent-api/reading.md +166 -0
  122. package/docs/agent-api/requests.md +94 -0
  123. package/docs/agent-api/talking.md +100 -0
  124. package/docs/agent-api/tcb.md +135 -0
  125. package/docs/agent-api/views.md +124 -0
  126. package/docs/agent-api/words.md +56 -0
  127. package/package.json +39 -4
  128. package/test/toolchains.json +5 -0
@@ -0,0 +1,135 @@
1
+ # Targets and their TCB
2
+
3
+ Targets, the members of a target's TCB that need review, its key declarations, why something is in
4
+ a TCB, and references (`uses`, `users`): any level. Then marking targets and keys, and trust (needs
5
+ full). Terms: [Words](words.md). MCP: `review` (actions `targets`, `tcb`, `keys`, `why`); `refs`
6
+ (actions `uses`, `users`); `mark` (actions `target`, `key`); `trust`.
7
+
8
+ ## `GET /api/agent/targets`
9
+
10
+ ```json
11
+ {"targets": [{"name": "Hilbert91", "markedBy": "Bob", "at": "…", "inGraph": true,
12
+ "counts": {"needReview": 16, "approved": 1, "commented": 0, "stale": 0, "unreviewed": 15,
13
+ "advised": 2, "agentComments": 0, "advisedByYou": 2,
14
+ "key": {"total": 4, "approved": 1, "commented": 0, "stale": 0, "unreviewed": 3}}},
15
+ {"name": "FltRegular.caseI", "markedBy": "Alice's AI", "markedByAgent": true, …}, …]}
16
+ ```
17
+
18
+ `approved` … `unreviewed`: people's statuses, summing to `needReview`. `advised`, `agentComments`,
19
+ `advisedByYou`: agents' advice on present versions, counted apart. `key`: the second level of
20
+ progress, the target's key declarations (the target among them).
21
+
22
+ ## `GET /api/agent/tcb?target=&include=&todo=&key=&offset=&limit=`
23
+
24
+ The members of `target`'s TCB that need review, in review order; any declaration may be the target
25
+ (`isTarget`: whether it is marked). `limit` 1–500, default 50; `next`: the next `offset`, null at
26
+ the end.
27
+
28
+ | parameter | effect |
29
+ |---|---|
30
+ | `todo=1` | only members you have not advised on in their present version (to resume a pre-review); with `include=review` only; 400 if you do not say who you are |
31
+ | `key=first`, `key=only` | key declarations first, then the rest; or key declarations alone (the review list's ◆ Key); each in review order |
32
+ | `include` | `review` (default); `trusted`: the trusted members; `all`: those needing review, then the trusted, `position` counting within each |
33
+
34
+ ```json
35
+ {"target": "Hilbert91", "isTarget": true, "order": "review: …", "counts": {"needReview": 16, …},
36
+ "trustedNotCounted": 195, "axioms": [], "include": "review", "offset": 0, "limit": 50, "total": 16, "next": null,
37
+ "members": [{"position": 2, "name": "RelativeUnits", "kind": "def", "module": "…", "key": true,
38
+ "status": "approved", "advice": [], "youAdvised": false},
39
+ {"position": 7, …, "advice": [{"by": "Claude", "verdict": "approve"}], "youAdvised": true}, …]}
40
+ ```
41
+
42
+ - `position`: place in the whole review order (also with `todo`, `key`); `total`: what the filter
43
+ keeps. The target comes last. `counts.key` counts the `key: true` members by status.
44
+ - No "next to review", for people or agents: the review set is read as a list.
45
+ - `axioms`: every axiom beyond the three standard ones the target rests on, through statements,
46
+ bodies or proofs, as `#print axioms` finds them (`sorryAx` included); each
47
+ `{name, inGraph, status, usedIn}`, `usedIn` the declarations using it. They need review whatever
48
+ is trusted, come first, count in `needReview`; `why` answers `inTcb: false, inReview: true` and
49
+ `usedIn` for them.
50
+ - `include=trusted`: each member's `trustedBy`, the prefixes covering it (`"@external"`: the whole
51
+ outside world) or `"standard axiom"`; the project's own first, then by prefix, then by name.
52
+ `trusted` sums them: `{project, external, byPrefix: {"Init": 6, …}}`.
53
+
54
+ ## `GET /api/agent/keys?target=&members=`
55
+
56
+ A target's key declarations top-down: the target, then each a layer below every key declaration
57
+ resting on it (within a layer, later in review order first). Each with `doc`, `restsOn` (the key
58
+ declarations it rests on directly) and its `support` (members it reaches through non-key members)
59
+ by status; plus the key graph's `edges`. `members=0`: support counts only, no names.
60
+
61
+ ```json
62
+ {"target": "Hilbert91", "isTarget": true, "order": "top-down: …", "note": "…",
63
+ "counts": {"key": {"total": 4, "approved": 1, …}, "all": {"total": 16, …}, "offBoardAxioms": 0},
64
+ "keys": [{"name": "Hilbert91", "target": true, "status": "none", "doc": null, "restsOn": ["RelativeUnits", …], …},
65
+ {"name": "systemOfUnits.IsFundamental", "kind": "def", "markedBy": "Alice", "markedAt": "…", "restsOn": ["systemOfUnits"],
66
+ "support": {"total": 5, "unreviewed": 5, …, "members": ["CyclotomicIntegers", …]}, …}, …],
67
+ "edges": [["systemOfUnits.IsFundamental", "systemOfUnits"], …], "viaProof": []}
68
+ ```
69
+
70
+ `viaProof`: non-standard axioms the target rests on through proofs alone (no statement or body
71
+ reaches them), part of its support. `marksOutsideReview`, when any: marks on declarations the review
72
+ no longer holds (trusted since, or out of the TCB), kept, counted for nothing.
73
+
74
+ ## `GET /api/agent/why?target=&name=`
75
+
76
+ The shortest chain of statement and body references from the target to the declaration.
77
+
78
+ ```json
79
+ {"target": "Hilbert91", "name": "CyclotomicIntegers", "inTcb": true,
80
+ "chain": [{"name": "Hilbert91", "kind": "theorem", "module": "…"},
81
+ {"name": "relativeUnitsModule", "kind": "instance", …, "usedIn": "the statement of Hilbert91"},
82
+ {"name": "CyclotomicIntegers", …, "usedIn": "the statement of relativeUnitsModule"}],
83
+ "reviewPosition": {"position": 1, "of": 16}}
84
+ ```
85
+
86
+ `inTcb: false`, `chain` null: nothing in the statement, nor in the body of a definition it reaches,
87
+ refers to it.
88
+
89
+ ## `GET /api/agent/uses?name=&where=&offset=&limit=` and `GET /api/agent/users?…`
90
+
91
+ `uses`: what the declaration refers to by name; `users`: what refers to it. Each reference with
92
+ `where` it sits (in the declaration for `uses`, in the user for `users`): `statement`, `body`,
93
+ `proof`, or `grammar` (syntax that only declares grammar). Order: statement, body, then proof and
94
+ grammar; the project before the outside world; then name. `where=statement|body|proof|grammar`
95
+ filters; `counts` cover all (statement, body, proof; grammar only in `total`). `limit` 1–1000,
96
+ default 100; `next`: the next `offset`. A folded name counts as its owner; references to itself are
97
+ left out.
98
+
99
+ ```json
100
+ {"name": "flt_regular", "direction": "uses", "note": "…", "offset": 0, "limit": 4, "total": 65, "next": 4,
101
+ "counts": {"total": 65, "statement": 8, "body": 0, "proof": 65, "project": 3, "external": 62, "trusted": 62},
102
+ "refs": [{"name": "Fact", "kind": "class", "module": "Mathlib.Logic.Basic", "external": true,
103
+ "where": ["statement", "proof"], "trusted": true, "trustedBy": ["Mathlib"]}, …]}
104
+ ```
105
+
106
+ **Notation** in `uses`: units of `kind: notation` (with `display`). The macro or elaborator that ran
107
+ on the text is at `statement` or `body`; the syntax the text parses with (helper syntax a parent
108
+ notation consumes included) at `where: ["grammar"]`, `grammar: true`, outside the TCB. Notation used
109
+ only in proofs: `where: ["proof"]`, not in the TCB. `where=grammar` lists just the grammar. A
110
+ rule's `uses`: the syntax it interprets (grammar), the meta code it calls, the notation its
111
+ expansion emits.
112
+
113
+ ## Marking targets and keys, and trust (level full)
114
+
115
+ At level full you do what a person can through the page; below it, 403 saying which level refused.
116
+ Each is checked as the page's requests are and recorded under your name in your own review log,
117
+ `"agent": true`, with your mark in the timeline.
118
+
119
+ Names resolve as everywhere (`didYouMean`, folded names). `on` defaults to true. The answer says
120
+ whether anything `changed`; if so, `recorded` is the event written; if it was so already, nothing is
121
+ written.
122
+
123
+ | request | what |
124
+ |---|---|
125
+ | `POST /api/agent/target {name, on}` | mark a project declaration as a target (☆ Target) or take it off. Marking makes no view: `view` (its linked view) is `null` after marking; `next`: the request that puts you on its view, a temporary view of its TCB where it has none. Taken off, its view (if any) stays, unlinked; marked again, nothing relinks it |
126
+ | `POST /api/agent/key {target, name, on}` or `{target, names: […], on}` | mark or unmark key declarations of a target's review; `names` up to 100, each answered on its own (`results`, with `status`). 409 if `target` is not a target; the name must be in its review (`tcb?target=` lists it); the target is always key (400) |
127
+ | `POST /api/agent/trust {prefix, on}` | trust without review, or stop trusting (a default too): a module or namespace, a whole dotted component, or `@external` (everything outside the project). Answers `covers` (`{project, outside}`) and `trusted`, the list after |
128
+
129
+ ```json
130
+ {"ok": true, "changed": true,
131
+ "recorded": {"op": "target", "at": "…", "by": "Alice's AI", "name": "FltRegular.caseI", "on": true, "agent": true},
132
+ "view": null, "next": "POST /api/agent/view {\"review\": \"FltRegular.caseI\"} puts you on its view …"}
133
+ ```
134
+
135
+ Views, pins and undoing a layout: [Views](views.md).
@@ -0,0 +1,124 @@
1
+ # Views and the layout
2
+
3
+ Views, their targets and focus, queries, the endpoints, past builds, pins on the Project view.
4
+
5
+ ## Views
6
+
7
+ A view is a board everyone shares: its **scope** (a query) and arrangement (clustering, folds, pins,
8
+ hidden levels of its cluster tree); each person's camera and selection are their own. The
9
+ Project (`project`) holds everything; it cannot be deleted or renamed (400). A view on a query
10
+ nobody arranges or names is not kept: it lives while someone (a page, or you) is on it; pinning,
11
+ folding or naming keeps it.
12
+
13
+ - **A target has at most one view**, or none, opened by clicking it anywhere. Marking makes and
14
+ links none. `views/link` sets it to any view; the view left keeps scope and arrangement.
15
+ - **A view may have several targets** (`targets`, first linked first; a star by its title, which
16
+ stays as any view's, names them). Its focus starts as its first target; later links leave it.
17
+ - Taking a target off unlinks it alone; its view stays. A target's view is rescoped, renamed and
18
+ deleted as any kept view; deleted, its targets have no view, and nothing gives them one by itself
19
+ (not marking, a restart, a build or a rename).
20
+ - A click on a target with no view, or `view {review}` ([following](following.md)), gives it a
21
+ temporary view of its TCB (`tcb(<target>)`, at the latest build), focused on it and linked while
22
+ it lasts: kept (pinned, folded, named, rescoped, another target linked), it keeps the link; gone,
23
+ the target has none again. Making it is no timeline event; nothing else makes a target a view.
24
+ - Views named `review:<target>` (made by marking before) are ordinary views.
25
+
26
+ ## The review is a focus
27
+
28
+ A view has a focus target or none. With one, the page's review works there — the strip, its line
29
+ of progress, marking key (`k`), why a declaration is in the TCB — over the focus's whole review set,
30
+ whatever the board holds ([tcb](tcb.md)). `focus` (in every answer giving a view) is: as set (a
31
+ target's Key view, opened from its panel: that target; Zoom in: the focus of the view it came from;
32
+ by the first target linked; by anyone), else the first target linked, else the one target its
33
+ board holds, else `null`. Your own focus (`POST view {focus}`) changes nothing of the view.
34
+
35
+ ## The query language
36
+
37
+ `all`, `tcb(A, B)`, `uses(A)`, `usedBy(A)`, `decl(A, B)`, `key(T)` (the target and the declarations
38
+ marked key for it that its review still holds; `key(targets)`: every target's), `ns(P)`, `file(P)`,
39
+ `trusted`, `external`, `kind(theorem, def)`, `status(unreviewed|approved|commented|stale)`,
40
+ `advice(approve|comment)`, `sorry`, `nonstandard`; joined left to right by `and`, `or`, `except`;
41
+ parentheses group; a closure may take a query (`tcb(ns(P) except external)`); a name that needs it
42
+ is in JSON quotes. A target's review set: `tcb(T) except trusted or (uses(T) and kind(axiom) and
43
+ nonstandard)`. At most 20,000 characters, 32 levels of nesting, 1,000 parts, 2,000 names, 64
44
+ closures (`tcb`, `uses`, `usedBy`, each target of a `key(…)`); beyond, 400.
45
+
46
+ ## The endpoints
47
+
48
+ Under `/api/agent/`; changes are for everyone on the view. MCP: `views`, action the path's last
49
+ part (`list` for `GET views`, `read` for `views/view`).
50
+
51
+ | request | needs | what |
52
+ |---|---|---|
53
+ | `GET views` | — | per view `{id, title, description, name, scope, clustering, kept, targets?, focus, by, at, version?, on}`: `title` as shown (people's name, else short, "… @ Oct 9 22:27" at a past build), `description` the scope in full, `by` null for the nameless (a private reader), `on` who is on it, `version` the snapshot it is kept at. `unreadable`: kept views the server cannot read now, left untouched |
54
+ | `GET views/view?id=&mode=&members=` | — | scope; holdings `{project, outside}`; items `{add, remove}` (project notes added, taken out: `{id, text}`; `all: true` on the Project); folds; `hidden`; pins; clusters as laid out (`key, depth, count, r, parent, room, at, pinned`), in its own coordinates. `members=1`: its declarations (≤ 5,000) |
55
+ | `POST views/open {scope, version?, clustering?, focus?}` | — | the view on that query (the open one with the same scope and build, or a new unkept one); you are on it: `{view, holds, note}`. `version`: a snapshot id (`null`, `0`, left out: latest); `clustering`, `focus` (the target it is made from): a new one's |
56
+ | `POST views/create {name, scope?, clustering?, from?, version?}` | full | a kept, named view on a scope, or a copy of `from` (scope, clustering, pins, folds, items — on the Project, every note its scope would not give, as added — and build; with `scope`, that scope arranged as `from`); `version` keeps it at a build (the Time Machine's Save as new view), `null`/`0` latest |
57
+ | `POST views/scope {id, scope}` | full | change what it holds (those on it are told) |
58
+ | `POST views/items {id, add?, remove?}` | full | project notes (by id) added or taken out: on the add list only where the scope does not give it, the remove list only where it does. Not the Project (400; deleting is [`note/delete`](notes.md)); 404 for no project note. An Activity event, as a scope change: `{ok, changed, view, items: {add, remove}, notes: [{id, shown}]}` |
59
+ | `POST views/focus {id, focus}` | full | the view's own focus: a target's full name, or `null`/left out; personal focuses stay: `{ok, changed, view}` |
60
+ | `POST views/link {id, target}` | full | link a target (a view with targets takes another; an unkept one becomes kept); not the Project, nor a view at a past build (409): `{ok, changed, view, left?}`, `left` the view it leaves |
61
+ | `POST views/arrange {id, clustering?, hide?, show?, fold?, unfold?, pins?, version?}` | full | `version`: the build it is kept at (Keep this version in this view; `null`/`0`: latest again; never on the Project or a target's view; a timeline event); clustering; `hide`/`show` levels (`[keys]`: a hidden cluster's contents sit in its parent, a fold on it goes, the export's sections follow; nothing on the board moves, pins in what moves keep their place); `fold`/`unfold` (`[keys]`); `pins` `[{name or cluster, at: [x, y] or null}]` in the board's coordinates after hiding/showing (≤ 500; beyond the parent's room brought inside): `{ok, view, changed, hidden, placed, note?}` |
62
+ | `POST views/duplicate {id, name?}` | full | a kept copy (scope, clustering, pins, folds, items as for `create`), named `"<its title> (copy)"` (numbered while taken) unless named; you are on it: `{view, from}` |
63
+ | `POST views/rename {id, name}` | full | `null` removes a kept view's name: `{ok, changed, view}` |
64
+ | `POST views/delete {id}` | full | a kept view, with its pins, folds, layout; pages on it go to the Project. A target's view: `unlinked` names its targets; one timeline event: `{ok, deleted, title, scope, unlinked?, note}` |
65
+ | `POST views/relayout {id}` | full | ⚙ Board's Re-layout: every pin goes, not undoable; folds stay; on the Project the whole graph is laid out anew: `{ok, view, dropped, note}` |
66
+
67
+ ## Views at a past build
68
+
69
+ Its `version` is a snapshot ([history](history.md)): the pages show that build's graph (a clock on
70
+ its tab, changes since marked), arranged as any view, with that build's layout memory. Not reviewed
71
+ (the review is the latest build's); exported by its id as that build's document
72
+ ([export](export.md)); sources: `GET source?name=&snapshot=<version>`. These endpoints answer its
73
+ holdings, clusters and pins at the latest build; a layout they make never becomes its memory. The
74
+ companion shows who is in the Time Machine ([following](following.md)).
75
+
76
+ ## `GET /api/agent/place?name=|cluster=&mode=&near=&limit=` (any level)
77
+
78
+ `place`, `pins` and `undo` are about the **Project view** (other views: `views/view`,
79
+ `views/arrange`). MCP: `pins` (actions `place`, `pin`, `undo`).
80
+
81
+ Where a declaration or cluster is (`mode`: `namespace`, default, or `module`), and what else is in
82
+ its parent. Coordinates are in the **parent cluster's frame**, origin at its centre.
83
+ `r`: radius (5 for a declaration); `room`: how far from the centre its centre may go;
84
+ `parent.room`: the parent's usable radius (less its label's room), so a child of radius `r` goes up
85
+ to `parent.room − r`. The page keeps a drop inside. A cluster's key is its full path
86
+ (`systemOfUnits.IsFundamental`); a top-level one has `parent.cluster` and `room` null, in the
87
+ canvas's frame.
88
+
89
+ `pinned`: its pin (null: at `laidOut`); `pinnedBy`: `{name, agent, at}`, null if unknown (`name`
90
+ null: a private reader, or a page that gave none). An undo's restored pins count
91
+ as the undoer's. `siblings`: the rest of the parent (declarations, clusters), each with `r`, `at`
92
+ (pin or layout), pinned and by whom, nearest first to `nearestTo` (your `near=x,y`, else the thing
93
+ itself); `gap`: free space between the circles were the thing at `nearestTo` (below zero:
94
+ overlap). `limit` 0–2000, default 100; `more`: the rest.
95
+
96
+ ```json
97
+ { "kind": "node", "key": "systemOfUnits.index", "r": 5, "room": 34.2, …,
98
+ "parent": { "cluster": "systemOfUnits", "r": 53.1, "room": 39.2 }, "laidOut": [-15.1, 22.9],
99
+ "pinned": [-10.8, -32.4], "pinnedBy": { "name": "Claude", "agent": true, "at": "…" },
100
+ "siblings": { "total": 10, "pinned": 1, "nearestTo": [-20, 30], "more": 8,
101
+ "list": [ { "key": "…", "declKind": "theorem", "at": [-25.4, 22.9], "gap": -1.1, … }, … ] } }
102
+ ```
103
+
104
+ To avoid overlaps, ask with `near=` your spot and move until the first sibling's `gap` is positive:
105
+ on the page a pin pushes aside what is not pinned (a declaration, or a cluster with its contents),
106
+ and the later of two overlapping pins pushes the earlier, so an overlap moves things you did not
107
+ mean to, others' pins included.
108
+
109
+ ## `POST /api/agent/pins` (needs full)
110
+
111
+ ```json
112
+ { "mode": "namespace", "pins": [ { "name": "systemOfUnits.index", "at": [-15, -45] },
113
+ { "name": "systemOfUnits.isMaximal", "at": null } ] }
114
+ ```
115
+
116
+ `at` in the parent's frame (`place`); `null` lets go (back to the layout). ≤ 500 per request;
117
+ beyond the parent's `room`, brought inside as a drag is. Pins are shared, live on every page. The
118
+ request is **one batch** in the timeline ("Claude moved 3 declarations"), with each pin's previous
119
+ place. Answer `{ok, id, count, placed: [{key, at}, …]}`; `id` null when nothing changed.
120
+
121
+ ## `POST /api/agent/undo {id}` (needs full)
122
+
123
+ The batch's pins go back, except those moved since (`kept`): `{ok, id, restored, kept, note?}`; 409
124
+ already undone; 404 no such batch. People undo from Activity. `views/arrange` pins are no batch.
@@ -0,0 +1,56 @@
1
+ # Words
2
+
3
+ The terms the other topics use.
4
+
5
+ - **Declaration**: a Lean constant of the project (`kind`: def, theorem, structure, inductive,
6
+ class, instance, abbrev, opaque, axiom, notation, …) or outside it (`external: true`, no source).
7
+ - **Unit**: a declaration of the graph is a command as written; what Lean generates from it unnamed
8
+ in the text (what a project's declaring command writes beside the declaration it names, `@[simps]`
9
+ lemmas) is part of it, in `also`, its references, axioms and content hash included.
10
+ - **Folded names**: constructors, structure fields and projections, recursors, matchers, equation
11
+ lemmas, `also` names are not graph declarations; a reference to one is to its owner. Asked for,
12
+ an `also` name or a name one component below a declaration or `also` name
13
+ (`systemOfUnits.units`) is that declaration, unless a typo or two from a declaration beside it
14
+ (generated last parts like `mk`, `rec`, `eq_1` fold even then); the answer adds `asked`,
15
+ `foldedInto`, `foldedNote`. `describe` and `print` take the folded name.
16
+ - **Notation** (`kind: notation`): a project syntax extension command (`syntax`, `notation`,
17
+ `macro`, `macro_rules`, `elab`, `elab_rules`, `declare_syntax_cat`; `local`, `scoped` too) as one
18
+ unit, its parser and `_aux_` macro or elaborator folded in. Statement: the command's text;
19
+ `display`: the page's name (`notation · I · in UnitLemmas`); `leanName`: its Lean constant where
20
+ its name is not one. Names: rules `<kind>.macro_rules`, `<kind>.elab_rules` (`_2`, … for later
21
+ rules of the kind in the module; `.<Module>` if not in the syntax's module), a syntax its kind, a
22
+ category `<category>.syntax_cat`. `describe` and `print` of a unit ask about its constant
23
+ (`unit` in the answer).
24
+ - **Grammar** (`grammar: true`, flag `grammar`): a notation unit only declaring syntax (`syntax`,
25
+ `declare_syntax_cat`): in no TCB, no review; references to it are `where: grammar`, which a TCB
26
+ does not follow. A declaration depends on the macros and elaborators that actually ran on its
27
+ statement or body (of an overloaded kind's rules, that one; with no run in the info tree, the only
28
+ rule of a syntax its text parses): notation units with an implementation, declarations registered
29
+ `@[macro]`, `@[term_elab]`, `@[command_elab]`; and on the meta code they call (ordinary units,
30
+ flagged `meta`). Notation an expansion emits is a dependency of the rule emitting it. A rule
31
+ lists the syntax it `interprets`; a grammar unit, its `interpretedBy`. Unexpanders, delaborators:
32
+ in no TCB. Notation from outside the project is never recorded: no use listed, in no TCB.
33
+ - **`where`** a reference sits, one or several: `statement` (the type), `body` (a definition's
34
+ value), `proof` (a subterm whose type is a proposition).
35
+ - **TCB of T**: everything T's *statement* reaches through statement and body references, T
36
+ included; proof references never count. Includes the notation units interpreting their text
37
+ (never grammar) and the code they call. [Targets and their TCB](tcb.md).
38
+ - **Instances of classes whose instances are all equal** (`Decidable`, `DecidableEq`, `Fintype`,
39
+ `Unique`, …): in no TCB; such an instance argument is a `proof` reference. Instances of classes
40
+ carrying data (`Add`, `Monad`, `Inhabited`, …) stay.
41
+ - **Needs review**: a TCB member not *trusted*. Trusted: under a trusted prefix (by module, or by
42
+ name for the project's own; default `Batteries`, `Init`, `Lean`, `Mathlib`, `Std`), and the
43
+ standard axioms `propext`, `Classical.choice`, `Quot.sound`.
44
+ - **Review order**: bottom-up (what a declaration uses before it; mutual users together), then
45
+ what more targets rest on, then name. A review judges a declaration assuming what it uses means
46
+ what it says.
47
+ - **Status** (people's): `commented` if some reviewer's latest opinion on the present version is a
48
+ comment; else `approved` if one approves; else `stale` if it has opinions, none on the present
49
+ version; else `none`.
50
+ - **Target**: a theorem whose TCB is reviewed; marked by people, or agents at level full
51
+ (`markedByAgent`).
52
+ - **Key declaration**: a review member that matters for reading the target (central definitions,
53
+ the structures under them, the main theorem), marked per target as targets are; the target always
54
+ is one. A non-key member is **supported by** a key declaration reaching it by statement and body
55
+ references through non-key members; the **key graph** links key declarations reached so. People
56
+ review key declarations first.
package/package.json CHANGED
@@ -1,6 +1,41 @@
1
1
  {
2
2
  "name": "visualproof",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "See a Lean codebase's declaration graph and the TCB of its theorems.",
6
+ "license": "Apache-2.0",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/LucianoXu/VisualProof.git"
10
+ },
11
+ "bin": {
12
+ "visualproof": "dist/server/main.js"
13
+ },
14
+ "files": [
15
+ "dist/",
16
+ "docs/agent-api/",
17
+ "test/toolchains.json"
18
+ ],
19
+ "scripts": {
20
+ "build": "node scripts/build.mjs",
21
+ "prepack": "npm run build",
22
+ "serve": "node src/server/main.ts serve",
23
+ "typecheck": "tsc --noEmit -p .",
24
+ "test": "node --test --import ./test/setup.ts \"test/*.test.ts\"",
25
+ "test:toolchains": "node scripts/test-toolchains.mjs",
26
+ "golden:update": "VP_GOLDEN_UPDATE=1 node --test --import ./test/setup.ts test/compat.test.ts"
27
+ },
28
+ "engines": {
29
+ "node": "^22.18.0 || >=24.2.0"
30
+ },
31
+ "dependencies": {
32
+ "d3-hierarchy": "^3.1.2",
33
+ "pdfjs-dist": "6.3.289"
34
+ },
35
+ "devDependencies": {
36
+ "@types/d3-hierarchy": "^3.1.7",
37
+ "@types/node": "^24.0.0",
38
+ "esbuild": "^0.28.2",
39
+ "typescript": "^5.9.0"
40
+ }
41
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "policy": "The last six or so stable Lean releases, and whatever the showcase project needs (v4.28.0, for the sphere packing formalization); the newest patch of each minor release.",
3
+ "floor": "v4.28.0",
4
+ "toolchains": ["v4.28.0", "v4.29.1", "v4.30.0", "v4.31.0", "v4.32.2", "v4.33.1", "v4.34.1", "v4.35.0"]
5
+ }