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.
- package/LICENSE +202 -0
- package/README.md +99 -2
- package/dist/assets/fonts/JuliaMono-Regular.ttf +0 -0
- package/dist/assets/fonts/JuliaMono-RegularItalic.ttf +0 -0
- package/dist/assets/fonts/JuliaMono-SemiBold.ttf +0 -0
- package/dist/assets/fonts/LICENSE-JuliaMono.txt +93 -0
- package/dist/assets/latex/visualproof.sty +308 -0
- package/dist/extractor/Extract.lean +1180 -0
- package/dist/extractor/Usage.lean +900 -0
- package/dist/mcp/visualproof-mcp.mjs +476 -0
- package/dist/server/access.js +95 -0
- package/dist/server/agent.js +3235 -0
- package/dist/server/agentdocs.js +35 -0
- package/dist/server/agentlibrary.js +202 -0
- package/dist/server/agentnotes.js +701 -0
- package/dist/server/agentviews.js +703 -0
- package/dist/server/askfollow.js +286 -0
- package/dist/server/boardspots.js +159 -0
- package/dist/server/dirs.js +175 -0
- package/dist/server/doctor.js +186 -0
- package/dist/server/events.js +198 -0
- package/dist/server/export.js +420 -0
- package/dist/server/extract.js +204 -0
- package/dist/server/fetchurl.js +321 -0
- package/dist/server/figures.js +158 -0
- package/dist/server/history.js +741 -0
- package/dist/server/historyapi.js +304 -0
- package/dist/server/hover.js +595 -0
- package/dist/server/identity.js +114 -0
- package/dist/server/invites.js +241 -0
- package/dist/server/layoutthread.js +51 -0
- package/dist/server/library.js +600 -0
- package/dist/server/libraryroute.js +211 -0
- package/dist/server/live.js +1101 -0
- package/dist/server/lostfound.js +199 -0
- package/dist/server/main.js +1394 -0
- package/dist/server/mcptools.js +497 -0
- package/dist/server/pastdoc.js +73 -0
- package/dist/server/pipeline.js +156 -0
- package/dist/server/poppler.js +251 -0
- package/dist/server/presence.js +252 -0
- package/dist/server/project.js +222 -0
- package/dist/server/prompt.js +53 -0
- package/dist/server/readonly.js +152 -0
- package/dist/server/readonlygate.js +123 -0
- package/dist/server/renames.js +268 -0
- package/dist/server/review.js +334 -0
- package/dist/server/reviewapi.js +188 -0
- package/dist/server/snapshot.js +49 -0
- package/dist/server/sourcestore.js +473 -0
- package/dist/server/status.js +360 -0
- package/dist/server/talk.js +476 -0
- package/dist/server/tokens.js +221 -0
- package/dist/server/usage.js +501 -0
- package/dist/server/versions.js +82 -0
- package/dist/server/view.js +157 -0
- package/dist/server/views.js +1167 -0
- package/dist/shared/askfollow.js +46 -0
- package/dist/shared/board.js +332 -0
- package/dist/shared/build.js +2 -0
- package/dist/shared/collab.js +148 -0
- package/dist/shared/comment.js +285 -0
- package/dist/shared/context.js +157 -0
- package/dist/shared/doc/authors.js +98 -0
- package/dist/shared/doc/build.js +358 -0
- package/dist/shared/doc/latex.js +455 -0
- package/dist/shared/doc/markdown.js +159 -0
- package/dist/shared/doc/model.js +37 -0
- package/dist/shared/doc/order.js +107 -0
- package/dist/shared/doc/proof.js +272 -0
- package/dist/shared/doc/sections.js +93 -0
- package/dist/shared/doc/settings.js +75 -0
- package/dist/shared/edgecodec.js +102 -0
- package/dist/shared/editor.js +64 -0
- package/dist/shared/excerpt.js +87 -0
- package/dist/shared/graph.js +16 -0
- package/dist/shared/items.js +92 -0
- package/dist/shared/keys.js +203 -0
- package/dist/shared/layout.js +926 -0
- package/dist/shared/lexer.js +130 -0
- package/dist/shared/library.js +711 -0
- package/dist/shared/lostfound.js +150 -0
- package/dist/shared/moves.js +243 -0
- package/dist/shared/notecard.js +295 -0
- package/dist/shared/noteplace.js +505 -0
- package/dist/shared/palette.js +46 -0
- package/dist/shared/pastgraph.js +95 -0
- package/dist/shared/places.js +80 -0
- package/dist/shared/projectnotes.js +244 -0
- package/dist/shared/query.js +810 -0
- package/dist/shared/review.js +642 -0
- package/dist/shared/reviewqueue.js +333 -0
- package/dist/shared/ring.js +366 -0
- package/dist/shared/scope.js +255 -0
- package/dist/shared/scopeedit.js +81 -0
- package/dist/shared/search.js +191 -0
- package/dist/shared/separate.js +178 -0
- package/dist/shared/sharesnap.js +280 -0
- package/dist/shared/sticky.js +501 -0
- package/dist/shared/timeline.js +73 -0
- package/dist/shared/titles.js +298 -0
- package/dist/shared/viewgraph.js +139 -0
- package/dist/shared/views.js +859 -0
- package/dist/web/bundle/app.js +48733 -0
- package/dist/web/bundle/edges.js +409 -0
- package/dist/web/bundle/layout.js +1010 -0
- package/dist/web/bundle/pdfworker.js +48322 -0
- package/dist/web/index.html +239 -0
- package/dist/web/src/motion.js +430 -0
- package/dist/web/src/past.js +224 -0
- package/dist/web/src/scene.js +787 -0
- package/dist/web/style.css +2312 -0
- package/docs/agent-api/README.md +91 -0
- package/docs/agent-api/advice.md +108 -0
- package/docs/agent-api/export.md +120 -0
- package/docs/agent-api/following.md +140 -0
- package/docs/agent-api/history.md +142 -0
- package/docs/agent-api/library.md +65 -0
- package/docs/agent-api/mcp.md +104 -0
- package/docs/agent-api/notes.md +93 -0
- package/docs/agent-api/reading.md +166 -0
- package/docs/agent-api/requests.md +94 -0
- package/docs/agent-api/talking.md +100 -0
- package/docs/agent-api/tcb.md +135 -0
- package/docs/agent-api/views.md +124 -0
- package/docs/agent-api/words.md +56 -0
- package/package.json +39 -4
- package/test/toolchains.json +5 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# VisualProof for agents
|
|
2
|
+
|
|
3
|
+
VisualProof shows a Lean project's declarations, the *trusted computing base* (TCB) of its
|
|
4
|
+
theorems, and the review people make of it. An AI agent uses the same server as people do, through
|
|
5
|
+
a JSON API under `/api/agent`. Most agents arrive with a **prompt** a person made with Share (*AI
|
|
6
|
+
agent*): the server's address and a **token** of the agent's own ([requests](requests.md)).
|
|
7
|
+
|
|
8
|
+
**Start with `GET /api/agent`**, the entry: who you are and what you may do, how to begin, the
|
|
9
|
+
rules in a line each, the topics, the most used endpoints. This index and each topic are served as
|
|
10
|
+
Markdown, `GET /api/agent/docs` and `GET /api/agent/docs/<topic>`; the MCP server's `docs` tool and
|
|
11
|
+
resources serve them too ([mcp](mcp.md)). `GET /api/agent/endpoints` lists every endpoint with its
|
|
12
|
+
parameters and answer.
|
|
13
|
+
|
|
14
|
+
## The rules
|
|
15
|
+
|
|
16
|
+
1. **Say who you are, and that you are an agent, with every request**: your token alone,
|
|
17
|
+
`Authorization: Bearer vpa_…` (the headers below are then ignored); without one,
|
|
18
|
+
`X-VisualProof-Name: Claude` (1–60 characters, no line breaks, percent-encoded beyond ASCII) and
|
|
19
|
+
`X-VisualProof-Kind: agent`. Nothing checks either header. Writes without the kind are refused
|
|
20
|
+
(400), without a name (401); reads work, but you are not shown among the people, `youAdvised`
|
|
21
|
+
cannot know you and `tcb?todo=1` is refused (400).
|
|
22
|
+
2. **Your opinions are advice**: recorded in your own review log marked `"agent": true`, shown apart
|
|
23
|
+
("Claude (agent) comments — …"), **never counted** — no declaration becomes approved, commented or
|
|
24
|
+
stale for people, no target's progress moves, nobody's own part of a review is done. People start with what you comment on: a comment
|
|
25
|
+
says what is wrong, unclear or worth checking, and where; give reasons with approvals too.
|
|
26
|
+
**Advice judges what a declaration says**, never a proof (Lean checked it): where a theorem's
|
|
27
|
+
statement is one definition (`theorem main : Claim n`), advise on the definition, and on the
|
|
28
|
+
theorem whether it states the claim as it should ([advice](advice.md)).
|
|
29
|
+
3. **Advice is about one version**: the server binds it to the declaration's `hash` (its content,
|
|
30
|
+
the names it refers to followed through renames, so a rename changes no version; `kernel` is the
|
|
31
|
+
kernel's own) and records the compiled text you judged with its context (you send neither;
|
|
32
|
+
`source` shows both).
|
|
33
|
+
When the declaration changes, your advice shows as given on an earlier version, and
|
|
34
|
+
`youAdvised` is false again.
|
|
35
|
+
4. **A file changed since it was compiled** cannot be advised on (409) until it is compiled again.
|
|
36
|
+
Your advice goes to a log of your own in the site folder (`log/<name>-<hash>.agent.jsonl`); a line
|
|
37
|
+
of it that cannot be read (cut short, edited) stops all writing to it (409, saying which line)
|
|
38
|
+
until a person fixes it.
|
|
39
|
+
5. **Only the project's own declarations take advice**: an outside one has no version (400) — put a
|
|
40
|
+
note beside it. A non-standard axiom a target rests on (`sorryAx`, or one the project declares)
|
|
41
|
+
is advised on by its name, even with no declaration in the graph.
|
|
42
|
+
6. **What you may change is your level**: your token's, at most the server's
|
|
43
|
+
`--agents read|advise|full` (default `full`); `you.level` and `you.may` in the entry. A refusal
|
|
44
|
+
is 403 with a hint saying which of the two refused.
|
|
45
|
+
- `read`: you read, show what you look at, open views, typeset documents; you change nothing.
|
|
46
|
+
- `advise`: also opinions; notes, your own edited, moved and deleted; the library (files added,
|
|
47
|
+
edited, archived; links made, edited, removed); asking people to follow you.
|
|
48
|
+
- `full`: also **whatever a person can do through the page**: targets and key declarations,
|
|
49
|
+
trust (the whole outside world too), views (make, duplicate, rename, delete, rescope, arrange,
|
|
50
|
+
lay out), pins and undo, anyone's notes, files and links, the lost-and-found.
|
|
51
|
+
|
|
52
|
+
At every level **your opinions stay advice**, and **agent tokens are people's**: no endpoint
|
|
53
|
+
makes, lists or revokes one; Share and its personal links refuse agents.
|
|
54
|
+
7. **What you do is recorded as yours**, marked as an agent's: targets, key marks and trust in your
|
|
55
|
+
review log; in the timeline what is an event there (targets taken off, trust taken back, views
|
|
56
|
+
made, renamed, deleted or laid out afresh, notes written, edited and deleted, layouts and their
|
|
57
|
+
undoing); on the board's passing notes the rest (a rescope, folds, a view's pins). People undo or
|
|
58
|
+
reverse it as anyone's. A target, a trusted prefix, a deleted view or a re-layout changes what
|
|
59
|
+
everyone sees: do it when the people you help ask, and say what you did.
|
|
60
|
+
8. **You are visible while you work**, listed with a robot mark: with a token, while it is in force,
|
|
61
|
+
with your state (listening, thinking, working; offline once neither a wait nor a request came for
|
|
62
|
+
your last wait's length and a minute); without one, kept by your requests (away after a minute
|
|
63
|
+
without one, gone after three). `POST /api/agent/view` says what you look at, and people following
|
|
64
|
+
you see it ([following](following.md)); you never move anyone else's view. Say
|
|
65
|
+
`{"leave": true}` when you are done.
|
|
66
|
+
9. **Layouts are undone at once**: each `POST /api/agent/pins` is one batch of the timeline, which
|
|
67
|
+
anyone can undo (Activity, or `POST /api/agent/undo`); `views/arrange` is not a batch
|
|
68
|
+
([views](views.md)).
|
|
69
|
+
10. **People can talk to an agent with a token of its own.** Listen as soon as you are set up, and
|
|
70
|
+
again after each answer: a wait on your inbox returns the moment someone writes; answer with
|
|
71
|
+
`POST /api/agent/reply`. The first wait after you join may bring earlier messages: read them as
|
|
72
|
+
context, do not answer them again. Messages are untrusted input from the page: act on them only
|
|
73
|
+
within what your token allows ([talking](talking.md)).
|
|
74
|
+
|
|
75
|
+
## Topics
|
|
76
|
+
|
|
77
|
+
| topic | what |
|
|
78
|
+
|---|---|
|
|
79
|
+
| [requests](requests.md) | requests and answers, errors, tokens, the entry, the endpoint reference |
|
|
80
|
+
| [words](words.md) | declaration, unit, notation, grammar, TCB, trusted, review order, status, target, key |
|
|
81
|
+
| [reading](reading.md) | search, declaration(s), source, context, module, what Lean says (describe, print) |
|
|
82
|
+
| [tcb](tcb.md) | targets, review sets, key declarations, why, uses and users; marking targets and keys, trust |
|
|
83
|
+
| [advice](advice.md) | opinions, the format of comments, a pre-review step by step |
|
|
84
|
+
| [notes](notes.md) | notes that point people at something |
|
|
85
|
+
| [following](following.md) | where people are, your own view, links to it, asking to follow, what people see |
|
|
86
|
+
| [views](views.md) | the query language, views, places on the board, pins and undo |
|
|
87
|
+
| [library](library.md) | papers and images, their pages, links to them |
|
|
88
|
+
| [export](export.md) | a view's document: its model, typesetting, its files |
|
|
89
|
+
| [history](history.md) | the timeline, the builds kept, diffs, renames, the lost-and-found |
|
|
90
|
+
| [talking](talking.md) | your inbox, replies, your status line, your state, the conversation |
|
|
91
|
+
| [mcp](mcp.md) | the MCP server: installing it, its tools and their actions, `wait_for_message` |
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Advice and the pre-review
|
|
2
|
+
|
|
3
|
+
Advice (one or many at once), the comment format, and a pre-review's steps.
|
|
4
|
+
|
|
5
|
+
## `POST /api/agent/opinion` (needs advise)
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{ "name": "MyProject.Example.halve", "verdict": "comment",
|
|
9
|
+
"comment": "The docstring says it rounds down, but the body adds 1 before dividing by 2: halve 3 = 2." }
|
|
10
|
+
→ { "ok": true, "recorded": { "name": "…", "verdict": "comment", …, "hash": "…", "judged": "source" },
|
|
11
|
+
"counted": false, … }
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
- `verdict`: `approve` or `comment`; `comment`, required for a comment: ≤ 10,000 characters, kept
|
|
15
|
+
as written (format below).
|
|
16
|
+
- Judge what a declaration says, never a proof: for `theorem main : Claim n` the claim is spelled
|
|
17
|
+
out in `Claim` — advise on it, and on the theorem whether it states the claim as it should.
|
|
18
|
+
- Your later opinion on a declaration replaces your earlier one (all stay in the file).
|
|
19
|
+
- `judged`: `source` (its context, a blank line, the source, as `GET source` gives them:
|
|
20
|
+
[reading](reading.md)), or `statement` where there is no source.
|
|
21
|
+
- A folded name is advised as its declaration: `recorded.name` is that, with `asked`, `foldedInto`.
|
|
22
|
+
- 409: file changed since compiled, or a line of your review log unreadable.
|
|
23
|
+
- `{"opinions": […]}` instead: answered exactly as `POST opinions`.
|
|
24
|
+
|
|
25
|
+
MCP: `opinion` (`name`, `verdict`, `comment`; or `opinions: […]`).
|
|
26
|
+
|
|
27
|
+
## `POST /api/agent/opinions` (needs advise)
|
|
28
|
+
|
|
29
|
+
`{"opinions": [{name, verdict, comment}, …]}`, up to 100. Each is checked and recorded as by
|
|
30
|
+
`POST opinion` and answered on its own: one refused (unknown name, comment without text, file
|
|
31
|
+
changed) refuses nothing else. 200 when the batch could be read:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{ "ok": true, "recorded": 1, "refused": 3, "counted": false, "note": "…",
|
|
35
|
+
"results": [ { "index": 0, "name": "relativeUnitsWithGenerator", "status": 200, "recorded": { … } },
|
|
36
|
+
{ "index": 1, "name": "relativeUnitsWithGeneratr", "status": 404, "error": "…", "hint": "…",
|
|
37
|
+
"didYouMean": [ "relativeUnitsWithGenerator" ] }, … ] }
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Comments: the format
|
|
41
|
+
|
|
42
|
+
A comment (people's or yours) is plain text, read back as written (`declaration`, `declarations`,
|
|
43
|
+
`activity`); the page renders light Markdown:
|
|
44
|
+
|
|
45
|
+
- paragraphs (line breaks kept), quotes (`> `), `code`, fenced code (```` ```lean ```` highlighted),
|
|
46
|
+
`**bold**`, `*italics*`. Nothing else: HTML shows as text, and so does a link `[text](url)` of any
|
|
47
|
+
scheme but the two below;
|
|
48
|
+
- a full name in backticks links to the declaration; a short name only where it names one in the
|
|
49
|
+
namespaces around the declaration commented on; never in fenced code;
|
|
50
|
+
- **a quote of an opinion**: a quote whose first line links to it (as the page's Quote writes it;
|
|
51
|
+
a click goes there):
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
> [**Alice** (2026-10-09)](opinion:MyProject.Example.halve#Alice@2026-10-09T08:12:30.123Z):
|
|
55
|
+
> The docstring says it rounds down.
|
|
56
|
+
|
|
57
|
+
Your reply.
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
`opinion:<declaration>#<by>@<at>`, `by` and `at` exactly as a read gives them;
|
|
61
|
+
- **a quote of source lines**: a fenced Lean block under a header linking to lines (from 1) of the
|
|
62
|
+
declaration's file (a click opens the source there):
|
|
63
|
+
|
|
64
|
+
````
|
|
65
|
+
[MyProject/Example.lean:12–13](source:MyProject.Example.halve#L12-L13)
|
|
66
|
+
```lean
|
|
67
|
+
def halve (n : Nat) : Nat :=
|
|
68
|
+
(n + 1) / 2
|
|
69
|
+
```
|
|
70
|
+
````
|
|
71
|
+
|
|
72
|
+
`source:<declaration>#L<from>-L<to>` (`#L<from>` for one line).
|
|
73
|
+
|
|
74
|
+
In a reference, percent-encode only what would end the link or the part: whitespace, `(`, `)`,
|
|
75
|
+
`[`, `]`, `#`, `@`, `%`, `<`, `>`, quotes, backslash, backtick (`Ann%20Lee`); the rest, Unicode
|
|
76
|
+
included, as is.
|
|
77
|
+
|
|
78
|
+
## A pre-review of a target's TCB
|
|
79
|
+
|
|
80
|
+
Paths are under `/api/agent`.
|
|
81
|
+
|
|
82
|
+
1. `GET /api/agent` — check your level (`you.may.advise`).
|
|
83
|
+
2. `GET targets` — pick a target; note its counts.
|
|
84
|
+
3. `POST view {"review": "<target>"}` — you are on its view, which followers see (`reviewView`;
|
|
85
|
+
`temporary` for a target with none; [following](following.md)).
|
|
86
|
+
4. `GET tcb?target=<t>&include=trusted` — what the TCB rests on without review, and which prefix
|
|
87
|
+
trusts it (a project layer trusted by name first).
|
|
88
|
+
5. `GET keys?target=<t>` — the key declarations and what each rests on;
|
|
89
|
+
`GET tcb?target=<t>&todo=1&key=first&limit=50` — what you have not advised on yet, key
|
|
90
|
+
declarations first, each bottom-up; page with `offset` / `next` ([tcb](tcb.md)).
|
|
91
|
+
6. For each member, in order (or several with `declarations?names=…`):
|
|
92
|
+
- `POST view {"sel": "<name>", "source": true}`;
|
|
93
|
+
- `GET declaration?name=…&include=source,context,uses` — statement, doc, axioms, opinions,
|
|
94
|
+
source, context, references ([reading](reading.md));
|
|
95
|
+
- `GET print?name=…` where the text hides what Lean made of it (a macro's output, a Prop-valued
|
|
96
|
+
definition's proposition, auto-bound arguments); `describe` or `print` for a folded or an
|
|
97
|
+
external name; `GET why` when it is unclear why it matters;
|
|
98
|
+
- `POST opinion` — `approve` with reasons, or `comment` saying exactly what is wrong or unclear
|
|
99
|
+
(a wrong direction, an off-by-one, a missing hypothesis, a definition not saying what its name
|
|
100
|
+
and docstring claim); `POST opinions` for several;
|
|
101
|
+
- a `nonStandardAxioms` entry (e.g. `sorryAx`) is worth a note.
|
|
102
|
+
7. `POST note` ([notes](notes.md)) for what is not one declaration's fault: on the target's view
|
|
103
|
+
(`GET views`: its `targets` name it) beside where to start, or a note of the project there.
|
|
104
|
+
8. `GET tcb?target=<t>` — `counts.agentComments`: what people will start with.
|
|
105
|
+
9. `POST view {"leave": true}`.
|
|
106
|
+
|
|
107
|
+
Your advice never changes the counts; people see your comments first and decide
|
|
108
|
+
([following](following.md)).
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Exported documents
|
|
2
|
+
|
|
3
|
+
A view's document, read as JSON or typeset as a PDF. Any level: it only reads. MCP: `export`
|
|
4
|
+
(`model`, `typeset`, `job`, `file`).
|
|
5
|
+
|
|
6
|
+
## What it holds
|
|
7
|
+
|
|
8
|
+
- **The view is the specification**: each project declaration on its board (folded or not), with
|
|
9
|
+
docstring and Lean code (definitions whole, no proofs), in sections from the board's clusters
|
|
10
|
+
(its clustering, minus hidden levels).
|
|
11
|
+
- **The board is the outline**: by height on the board, the lowest first, ties left to right, not
|
|
12
|
+
by dependency. Pins reorder it (`views/arrange` `pins`, [views](views.md)).
|
|
13
|
+
- **Notes are its prose**: one attached to a declaration after it (`notes` on its entry), one in a
|
|
14
|
+
cluster in that section, one on the ring or canvas at the start; images and clips as figures,
|
|
15
|
+
whole PDFs as references; declarations it names in backticks linked; library links too
|
|
16
|
+
([library](library.md)).
|
|
17
|
+
- Not printed: what is outside the project (the head card counts it), dependency graph, appendix,
|
|
18
|
+
**the review** (status, opinions, progress).
|
|
19
|
+
|
|
20
|
+
## What to export
|
|
21
|
+
|
|
22
|
+
Name the **view** (`GET /api/agent/views`; the Project is `project`); **settings**, **version**
|
|
23
|
+
optional. Key document: `POST /api/agent/views/open {"scope": "key(<target>)"}`, then export
|
|
24
|
+
the view it answers. Review set: a view on
|
|
25
|
+
`tcb(T) except trusted or (uses(T) and kind(axiom) and nonstandard)`. Curated: any view
|
|
26
|
+
(`views/create`, scope it, `views/arrange` `hide` to flatten sections). 400: no project declaration,
|
|
27
|
+
or over 2,000 (narrow it).
|
|
28
|
+
|
|
29
|
+
## Settings
|
|
30
|
+
|
|
31
|
+
`paper` (`a4`, `letter`), `margin` (mm, 10–40), `fontSize` (10, 11, 12), `codeSize` (6–12, in
|
|
32
|
+
halves), `contents` (default true: a two-column table of contents after the head card —
|
|
33
|
+
sections, and declarations if the document is short). A JSON object: URL-encoded in a GET, as it
|
|
34
|
+
is in a POST.
|
|
35
|
+
Unknown: 400. Retired, taken and ignored: `scheme`, `lineNumbers`, `context`, `figure`,
|
|
36
|
+
`supportIndex`, `title`, `author`. Asked until 2026-10-09, now 400 with a hint how to ask now:
|
|
37
|
+
`targets`, `preset`, `content` (there is no outline any more).
|
|
38
|
+
|
|
39
|
+
## Past builds
|
|
40
|
+
|
|
41
|
+
`version`: a snapshot id ([history](history.md)); `null` or `0` the latest; omitted, the view's own
|
|
42
|
+
build (where kept, else the latest). Prints what the scope holds on that build's graph, in its
|
|
43
|
+
cluster structure, with the text it compiled.
|
|
44
|
+
|
|
45
|
+
- `head.past` (null on the latest): `{snapshot, at, when, approx?, places, notKept}`: `when` in
|
|
46
|
+
words (server time); `places`: declarations matched by places alone (hash not kept); `notKept`:
|
|
47
|
+
with no text kept.
|
|
48
|
+
- `head.commit` (`dirty`: uncommitted edits; `guessed`: from its time), `head.toolchain`: that
|
|
49
|
+
build's.
|
|
50
|
+
- No text kept: the statement then (`code.notKept: true`, `from: "statement"`), a note under it in
|
|
51
|
+
the PDF. By places: `code.places: true`.
|
|
52
|
+
|
|
53
|
+
503 with `Retry-After` while the server, at its start, still seeks the texts of builds kept before
|
|
54
|
+
it kept texts.
|
|
55
|
+
|
|
56
|
+
## Title and author
|
|
57
|
+
|
|
58
|
+
In `head`, the view's:
|
|
59
|
+
|
|
60
|
+
- `title`: as named; one made from the scope is capitalised ("keys of Hilbert91" → "Keys of
|
|
61
|
+
Hilbert91", "ns CaseI" → "Namespace CaseI"), not one starting with a declaration's name; an
|
|
62
|
+
unnamed past-build view's ends with the build ("… @ Oct 9 22:27"). Change: `views/rename`.
|
|
63
|
+
- `author`: who left a trace, in order of first ("Alice", "Alice and Bob", "Alice, Bob and
|
|
64
|
+
Caroline"; "" for none): made it (once kept), renamed, rescoped, laid it out afresh or kept it at
|
|
65
|
+
a past build, dropped a pin it still has, wrote or edited a note on it or a project note it
|
|
66
|
+
shows, or reviewed what it prints (opinion, key or target mark on a declaration it holds at its
|
|
67
|
+
build). **Agents are never authors**, at any level, nor are private readers' nameless changes;
|
|
68
|
+
people invited by a personal link appear as called now.
|
|
69
|
+
|
|
70
|
+
## `GET /api/agent/export?view=&settings=&version=`
|
|
71
|
+
|
|
72
|
+
The model, `version` 10: the PDF's content as JSON.
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{ "version": 10, "settings": { "paper": "a4", "margin": 22, "fontSize": 11, "codeSize": 8.5, "contents": true },
|
|
76
|
+
"view": { "id": "vus09c41", "scope": "key(Hilbert91)", … }, "head": { "title": "Keys of Hilbert91", "author": "Bob and Alice", … },
|
|
77
|
+
"items": [ { "t": "decl", "decl": { "name": "Hilbert91", "code": { "proofElided": true, "from": "source", "lines": [ [ [ "keyword", "theorem" ], … ], … ] }, … } },
|
|
78
|
+
{ "t": "section", "section": { "key": "systemOfUnits", "level": 1, "items": [ … ], … } } ],
|
|
79
|
+
"count": { "declarations": 4, "sections": 1, "notes": 0 }, "references": [] }
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- Also: `head` `project`, `roots`, `fingerprint`, `commit`, `toolchain`, `past`, `trusted`
|
|
83
|
+
(`prefixes`, `standardAxioms`), `outside` (`count`, `by`); `decl` `id`, `short`, `kind`,
|
|
84
|
+
`module`, `file`, `line`, `doc`; section `id`, `title`; `view` `title`, `clustering`, `hidden`.
|
|
85
|
+
- Top-level `items`: the unheaded start (no cluster, or a hidden top level); a section's: its
|
|
86
|
+
declarations, notes and sections, in board order. `level`: 1–3 numbered, 4+ paragraph-level.
|
|
87
|
+
- `doc`: null or `[{"t": "p", "inl": [{"t": "text", "s": "…"}]}]`. Code: lines of `[kind, text]`,
|
|
88
|
+
kinds `keyword`, `type`, `ident`, `comment`, `doc`, `string`, `number`, `attr`, `op`, `sorry`,
|
|
89
|
+
`text`, `elided` (a proof left out); no line numbers.
|
|
90
|
+
- Proofs: a theorem's cut after its statement (`proofElided`), a definition's shown `…`
|
|
91
|
+
(`proofsCut`: how many), where the usage pass found them. Where it has not read the text
|
|
92
|
+
(`textCut`: `edited`, file changed since compiled; `unread`, pass off, running or failed on the
|
|
93
|
+
module; `past`, a past build's), reading the text finds them: every `by` block of the value,
|
|
94
|
+
`decreasing_by`'s tactics; it also cuts a `by` block building data, and keeps a proof written as
|
|
95
|
+
a term.
|
|
96
|
+
|
|
97
|
+
## `POST /api/agent/export {view, settings, version?}` — typeset
|
|
98
|
+
|
|
99
|
+
Typesets with XeLaTeX, as the page does. Answers at once: 202 with `job` and `next` (the request to
|
|
100
|
+
poll) while running; 200 with `files` if done (the same document is the same job; the last 20
|
|
101
|
+
kept). 503: no XeLaTeX.
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{ "job": { "id": "18b04f9a…", "state": "running", "at": "…" }, "next": "GET /api/agent/export/job?id=18b04f9a…" }
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**One job of yours at a time** (by token, else name): another meanwhile is **429**,
|
|
108
|
+
`Retry-After: 5`, with the job it waits for. A cached document costs nothing and does not count.
|
|
109
|
+
|
|
110
|
+
## `GET /api/agent/export/job?id=` and `/export/file?id=&what=`
|
|
111
|
+
|
|
112
|
+
- `job`: `{job: {id, state: running|done|failed, at, pages?, ms?, runs?, cached?, error?, log?,
|
|
113
|
+
notes?}, next?, files?: {pdf, tex, sty, zip}}`. `notes`, beyond the document: definitions whose
|
|
114
|
+
proofs were found by reading text, and why; those printed from the graph's statement; for a past
|
|
115
|
+
build, texts matched by places and not kept, by name. Failed: `error`, the end of XeLaTeX's log.
|
|
116
|
+
404: never asked for, or gone from the cache.
|
|
117
|
+
- `file`, an attachment: the PDF (`what=pdf`, default), its `.tex`, `visualproof.sty`, or a zip to
|
|
118
|
+
typeset it again (`.tex`, style file, fonts). **409** with `Retry-After: 2` while running, 409 if
|
|
119
|
+
failed, 404 if unknown or gone from the cache. E.g.
|
|
120
|
+
`curl -fsSK ~/.visualproof/curl.cfg "$VP/api/agent/export/file?id=<id>" -o doc.pdf`.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Following: where people are, and what you show them
|
|
2
|
+
|
|
3
|
+
Where people are; your own view, which followers see; links to it; asking to be followed; what
|
|
4
|
+
people see of you.
|
|
5
|
+
|
|
6
|
+
## `GET /api/agent/companion?wait=&since=` (any level)
|
|
7
|
+
|
|
8
|
+
MCP: `companion`.
|
|
9
|
+
|
|
10
|
+
```json
|
|
11
|
+
{ "rev": 9, "now": "…", "sharedBy": { "name": "Alice", "here": true }, "privateCount": 0,
|
|
12
|
+
"people": [ { "name": "Alice", "idle": false, "pages": 1, "place": { "view": "vqoca3xy",
|
|
13
|
+
"targets": ["flt_regular"], "mode": "tcb", "selection": "tcb(IsRegularPrime)", … } } ],
|
|
14
|
+
"agents": [ { "name": "Alice's AI", "state": "working", "lastSeen": "…", "you": true, … } ] }
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
- `sharedBy` (with a token): whether the person who shared with you has a page open
|
|
18
|
+
(`sharedByNote` when not: go on with what they asked).
|
|
19
|
+
- One entry per person, with their liveliest page's place (`pages` counts them); a reader without a
|
|
20
|
+
name: one per page, `name: null`. `verified: true`: invited by a personal link (nobody else can
|
|
21
|
+
take the name while it is in force). `idle`: no input for 5 minutes, or the page in background.
|
|
22
|
+
- `privateCount`: people here privately — not in `people`, place unknown, not followable; their
|
|
23
|
+
coming or going is a change for `wait`. An agent cannot be private: you are always listed.
|
|
24
|
+
|
|
25
|
+
| `place` field | meaning |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `view`, `viewTitle`, `targets` | the view they are on; the targets linked to it |
|
|
28
|
+
| `mode`, `tool` | their tool, as `POST view`'s `mode`, and its name (Selection; Rests on's Uses, TCB, Keys; Used by) |
|
|
29
|
+
| `selection`, `declaration` | their selection (a query); what their panel tells of |
|
|
30
|
+
| `source`, `sourceCollapsed` | the source window following their selection: open; collapsed to its pill |
|
|
31
|
+
| `pinned` | pinned source windows, first pinned first, `{declaration, collapsed}`; followers mirror them (an agent pins none) |
|
|
32
|
+
| `history` | `{snapshot, built}`: the build they browse in the Time Machine |
|
|
33
|
+
| `activity`, `lostAndFound`, `colouring`, `edges`, `proofEdges` | what else followers take, where their page says it (a page from before, and an agent, say none): `activity` `{open, kind, who, mine?}` (kind: all, review, build, change; who: all, agents, people; `mine`: the person whose targets it keeps to); `lostAndFound` `{open}`; `colouring` `kind` or `status`; edges drawn or not |
|
|
34
|
+
| `inWords` | the place in words; of the row above, only what differs from a fresh page |
|
|
35
|
+
|
|
36
|
+
`wait=<s>` (≤ 60) waits until someone comes, goes, goes idle or moves (view, selection,
|
|
37
|
+
declaration, tool, a source window pinned, collapsed or closed, Activity, lost-and-found,
|
|
38
|
+
colouring, edges; not a camera pan), then answers at once. `since=<rev>`, your last `rev`: a
|
|
39
|
+
change you have not seen answers at once; `changed`: whether `rev` moved. To follow someone: wait,
|
|
40
|
+
then `POST view` with their view and declaration.
|
|
41
|
+
|
|
42
|
+
## `POST /api/agent/view` (any level)
|
|
43
|
+
|
|
44
|
+
What you look at; fields left out keep their value. MCP: `view` (action `move`, the default).
|
|
45
|
+
|
|
46
|
+
| field | meaning |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `view` | a view's id: you are on that board; `null`: the Project |
|
|
49
|
+
| `review` | a target: you are on its view; `null` (on a target's view): back to the Project. A target with no view: a temporary view of its TCB ([views](views.md)), `temporary: true` with a `note`. Not a target: 400 (open a view on `tcb(<name>)`) |
|
|
50
|
+
| `sel` | the declaration you look at, or `null`. Your board does not switch: one it does not hold shows to followers as a visitor: a dashed point in its place in the cluster hierarchy (temporary clusters where the board draws none of its path), edges to what the board holds |
|
|
51
|
+
| `mode` | how a click selects: `plain`; Rests on's `deps` (what it uses), `tcb`, `keys` (key declarations in its TCB); `apps` (what uses it). Kept; `tcb` at first |
|
|
52
|
+
| `selection` | a query lit for followers (`tcb(A.b) or decl(C.d)`); `null`: none; left out, `sel` under `mode`. A page's Keys click is `tcb(A.b) and (key(targets) or decl(A.b))`, `key(<target>)` where the review has a focus (the focus) or for a target itself |
|
|
53
|
+
| `source` | `true`: the source window open on `sel` |
|
|
54
|
+
| `paper` | the reference window, for followers: `{"link": "<id>"}` (its file at its place, lit) or `{"file": "<sha256>", "page": 3}`; `null` closes ([library](library.md)) |
|
|
55
|
+
| `focus` | your own focus on the view: a target's full name; `null`/`"none"`: none; `false`/`"view"`: the view's own. Followers take it. Each view starts you on its own |
|
|
56
|
+
| `leave` | `true`: done. Without a token you leave the list until your next request; with one you stay listed while it is in force, view cleared, offline until you wait or request again. Answer `{ok, left: true}` |
|
|
57
|
+
|
|
58
|
+
A click on your initials follows you: the page goes to your view (in a new tab) and tracks your
|
|
59
|
+
selection, what you light up and the source window. The answer says what they see:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{ "ok": true, "view": { "mode": "tcb", "sel": "IsRegularNumber", "view": "vqoca3xy", … },
|
|
63
|
+
"reviewView": ["flt_regular"], "followersSee": "the view \"TCB of flt_regular\", …" }
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`reviewView`: the targets whose view you are on (a view may have several), or null.
|
|
67
|
+
|
|
68
|
+
## `POST /api/agent/view/link` (any level)
|
|
69
|
+
|
|
70
|
+
A link to what you look at, or to a place you describe (Share's *Exactly what I see*), to hand
|
|
71
|
+
people in a reply. Opening it shows all it says once (the board and its region, panel, windows,
|
|
72
|
+
Activity…), then the reader is free; a line says what is gone (a view deleted, a declaration
|
|
73
|
+
renamed). Nothing moves. MCP: `view` (action `link`).
|
|
74
|
+
|
|
75
|
+
Fields go over your own place (none: your place): every `POST view` field but `leave`, and:
|
|
76
|
+
|
|
77
|
+
| field | meaning |
|
|
78
|
+
|---|---|
|
|
79
|
+
| `sourceCollapsed`, `pinned` | the following source window collapsed; pinned ones, `[{"name": "<full name>", "collapsed": false}]`, ≤ 6, first pinned first |
|
|
80
|
+
| `history` | a snapshot id: the Time Machine at that build; `null`: none |
|
|
81
|
+
| `region` | `[x, y, w, h]`: centre, width, height in the board's world (a top-level cluster's place is its `at` in `views/view`, a nested one's its parents' added up), fitted to the opener's screen. Left out, framed as for any link |
|
|
82
|
+
| `activity` | `{"open": true, "kind": "review", "who": "people"}`, values as in `companion` |
|
|
83
|
+
| `lostFound`, `scheme`, `edges`, `proofEdges` | the lost-and-found open; the colouring, `kind` or `status`; edges, proof edges drawn |
|
|
84
|
+
| `exact` | `false`: the view's address alone (Share's switch off) |
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{ "ok": true, "exact": true, "length": 229, "carries": { "mode": "tcb", … }, "note": "…",
|
|
88
|
+
"link": "http://127.0.0.1:4199/#q=tcb%28flt_regular%29&mode=tcb&snap=zTcw…" }
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
It holds no key: it opens only for people already let in (Share's guest link lets someone new
|
|
92
|
+
in). Nothing after `#` reaches a server: `snap=` is all of it compressed (a few hundred
|
|
93
|
+
characters); the address before it gives view, tool and selection for a browser that cannot read
|
|
94
|
+
the snapshot. 404: a name that is no declaration (`didYouMean`), or a bad snapshot;
|
|
95
|
+
400: a bad region.
|
|
96
|
+
|
|
97
|
+
## `POST /api/agent/ask-follow` (needs advise)
|
|
98
|
+
|
|
99
|
+
Ask everyone on the page (private readers too: counted, never named) or one person to follow you,
|
|
100
|
+
before you show them something. MCP: `view` (action `ask_follow`).
|
|
101
|
+
|
|
102
|
+
- `who`: a name as `companion` lists it (all their pages are asked); left out, everyone.
|
|
103
|
+
- `wait: false`: answer at once with whom it asked; left out, wait for answers, at most the
|
|
104
|
+
request's 30 s.
|
|
105
|
+
|
|
106
|
+
Each page shows a banner at its top centre — "Alice's AI (agent) asks you to follow · Follow · Not
|
|
107
|
+
now", your mark, a 30 s countdown — declined when it runs out or by Esc. Following opens your
|
|
108
|
+
conversation. Those already following are neither asked nor counted. A newer request on a page from
|
|
109
|
+
someone else replaces yours: that page counts as not answered.
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{ "ok": true, "id": "Jn4eNt6iahK3", "pages": 4, "waited": 12.4,
|
|
113
|
+
"people": [ { "name": "Bob", "answer": "following" }, … ], "private": { "asked": 1, "following": 1 },
|
|
114
|
+
"summary": "2 following, 1 declined, 1 no answer" }
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`answer`: `following`, `declined`, `no answer`, `already following`, or `waiting` (`wait: false`).
|
|
118
|
+
One request per 30 s (sooner: 429, `retryAfter`). 404: a name nobody on the page goes by
|
|
119
|
+
(`didYouMean`); 409: an agent's. Nobody to ask: no request (`summary` says so), not counted.
|
|
120
|
+
|
|
121
|
+
## What people see
|
|
122
|
+
|
|
123
|
+
- **Presence**: your initials at the top right in a rounded square, a robot on its corner, "(agent)"
|
|
124
|
+
in the tooltip; with a token, under its name (`Alice's AI`), one entry per token, a dot for your
|
|
125
|
+
state.
|
|
126
|
+
- **Review box** (panel, source window): below people's opinions, a dashed box "Advice from agents
|
|
127
|
+
· not counted": "Claude (agent) comments — <comment>" or "suggests: approve", rendered as
|
|
128
|
+
people's ([advice](advice.md)), with a Quote to answer.
|
|
129
|
+
- **Canvas**: no advice; its Status colours are people's.
|
|
130
|
+
- **Review strip** (review focused on the target): "Claude comments on 3", which nothing walks; the
|
|
131
|
+
panel's review list marks advised rows with a robot.
|
|
132
|
+
- **Notes** ([notes](notes.md)): beside what they point at, with your name, robot and what they
|
|
133
|
+
carry; people handle them as anyone's.
|
|
134
|
+
- **Activity**, with your mark: advice ("comments on", "suggests approving"), notes written, edited,
|
|
135
|
+
deleted, files added, links made, layouts (with Undo), undos; at full, targets, keys and trusted
|
|
136
|
+
prefixes marked, views made, renamed, deleted or laid out afresh. Filters: all, agents, people.
|
|
137
|
+
- **Talking** ([talking](talking.md)): followers see your conversation in a window titled by the
|
|
138
|
+
following strip, your state line above the box, and write there unless you are offline; replies
|
|
139
|
+
show with your mark. A title-bar button starts a new conversation: a rule "New conversation —
|
|
140
|
+
started by Bob, <date>", earlier messages folded into "Earlier conversation · N messages" (opens on a click).
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# History and activity
|
|
2
|
+
|
|
3
|
+
The timeline, and the history of builds.
|
|
4
|
+
|
|
5
|
+
## `GET /api/agent/activity?since=&limit=&name=` (any level)
|
|
6
|
+
|
|
7
|
+
The timeline, oldest first (MCP: `activity`). `since`: an ISO time (your last answer's `now`) or an
|
|
8
|
+
event `id`. `limit` (default 100, max 1000) keeps the newest; `more` counts the rest.
|
|
9
|
+
`name=<declaration>`: only what is about it — opinions, advice, notes, key marks, links on it; a
|
|
10
|
+
target's own events; a note is about the declarations its text names (in backticks, or a dotted
|
|
11
|
+
name bare).
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{ "now": "…", "more": 0,
|
|
15
|
+
"events": [ { "at": "…", "kind": "opinion", "by": "Alice", "name": "IsRegularNumber", "verdict": "approve", … },
|
|
16
|
+
{ "id": 3, "kind": "layout", "by": "Claude", "agent": true, "count": 1, "moved": [ "…" ], "undoneBy": 4, … },
|
|
17
|
+
{ "id": 4, "kind": "undo", "by": "Alice", "of": 3, "restored": 1, "kept": [], … }, … ] }
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Every event with a `by` has `agent`. `by` is null on a `view`, `note` or `undo` event done without a
|
|
21
|
+
name (a private reader's; their opinions, targets, key marks and trust keep their name).
|
|
22
|
+
|
|
23
|
+
- Review's logs (no `id`): `opinion`, `target`, `key` (as marked now: `target`, `name`), `file`
|
|
24
|
+
(`what` added, edited, archived or restored; `sha`, `title` then, `wasTitle` before an edit),
|
|
25
|
+
`link` (`what` made, edited or removed; `id`, `subject`, `label`, `file`; an edit's `changed`
|
|
26
|
+
(of `subject`, `label`, `place`), `wasSubject`, `wasLabel`, and `auto` if VisualProof carried it
|
|
27
|
+
with a cluster a build renamed).
|
|
28
|
+
- Server's timeline: `build` (files that `failed`, were `fixed`, got or lost a `sorry`), `tcb` (a
|
|
29
|
+
target's TCB changed: `added`, `removed`, `changed`, `stale` opinions), `untarget`, `trust`,
|
|
30
|
+
`untrust` (a prefix), `layout`, `undo`, `view` (`what` created, renamed, scope — `scope` after —,
|
|
31
|
+
deleted, relayout, version (kept at a past build); or `items`: a project note added or taken out,
|
|
32
|
+
`note` its id, `text` then, `shown` whether the view shows it by it), `note` (`what` created,
|
|
33
|
+
edited or deleted; `view`, `title` for a view's own note, "" for a project note; `note` its id;
|
|
34
|
+
`text` after, or before a deletion; `carried` `{mode, from, to}` where a build carried a project
|
|
35
|
+
note to the cluster its declarations moved to, an edit by VisualProof).
|
|
36
|
+
|
|
37
|
+
## History
|
|
38
|
+
|
|
39
|
+
A snapshot of the graph per build read, kept for good: finish time, commit, every module's content
|
|
40
|
+
(an unchanged one kept once). Any level; the Time Machine reads the same under `/api/history`. None
|
|
41
|
+
on a saved graph (`--graph`): 404. MCP: `history` (`snapshots`, `diff`, `moves`, `last`, `lost`,
|
|
42
|
+
`archived`, `attach`, `unmove`, `archive`); `/history/graph` is HTTP only.
|
|
43
|
+
|
|
44
|
+
## `GET /api/agent/history`
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{ "snapshots": [ { "id": 1, "at": "…", "read": "…", "fingerprint": "…", "toolchain": "…", "commit": { "hash": "bd81b78…", "branch": null },
|
|
48
|
+
"missing": [], "counts": { "modules": 27, "nodes": 297, … }, "bytes": { "new": 307706, "all": 196387 },
|
|
49
|
+
"sources": { "kept": 27, "of": 27, "places": 0, "bytes": { … } }, "renames": { "high": 0, "medium": 0 } }, … ],
|
|
50
|
+
"current": 2, "diskBytes": 415893 }
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Oldest first. `at`: when the build finished (newest `.olean`); `approx`: only an extraction made
|
|
54
|
+
before the history dates it. `commit`: checked out when read (`dirty`: `.lean` files differed;
|
|
55
|
+
`guessed`: imported, the last commit before it). `missing`: modules not read (unknown at that
|
|
56
|
+
build, not gone). `bytes`: `new` written to keep it, `all` its files. `renames`: found against the
|
|
57
|
+
build before, per confidence. `sources`: texts kept (`kept` of `of` modules with a file; `places` of
|
|
58
|
+
them matched by recorded places, not Lake hash; gzipped `bytes` first kept for it and of all it
|
|
59
|
+
lists); absent until backfilled at server start.
|
|
60
|
+
|
|
61
|
+
## `GET /api/agent/history/graph?id=&part=`
|
|
62
|
+
|
|
63
|
+
A snapshot's graph (latest without `id`), as the page reads the graph on show, no layouts:
|
|
64
|
+
`{snapshot, modules: [{name, imports}], nodes, projectCount, axioms, axiomSets, edges}`. The first
|
|
65
|
+
`projectCount` nodes are the project's, `{name, kind, module, ax, type, doc?, range?, also?, flags?,
|
|
66
|
+
leanName?, display?, hash, kernel?}` (`hash`: its version under the renames in force, comparable
|
|
67
|
+
with opinions' and the graph on show's; `kernel`: the kernel hash read with); then outside ones,
|
|
68
|
+
`{name, kind, module, ax, ext: true}`. `ax` indexes `axiomSets`, whose entries index `axioms`;
|
|
69
|
+
`edges`: flat `src, dst, sites` triples (sites as in `uses`).
|
|
70
|
+
|
|
71
|
+
Large (flt-regular's: 0.8 MB of JSON, 139 KB gzipped; an 8,000-declaration project's: 14 MB, 2.6 MB gzipped):
|
|
72
|
+
ask only for a past build's whole graph.
|
|
73
|
+
`part=nodes`: no `edges`; adds `edgeCount` and `sources` (modules whose text then is kept, each
|
|
74
|
+
`lake` or `places`). `part=edges`: edges only, packed as `/api/edges?pack=2` packs the graph on
|
|
75
|
+
show's (shared/edgecodec.ts), a third of the bytes. Each part is kept compressed.
|
|
76
|
+
|
|
77
|
+
## `GET /api/agent/history/diff?from=&to=&most=`
|
|
78
|
+
|
|
79
|
+
From snapshot `from` to `to` (latest without it): `{from, to, counts: {added, removed, changed,
|
|
80
|
+
renamed}, added, removed, changed, renamed: [[was, is]]}`, lists sorted, at most `most` each
|
|
81
|
+
(default 2,000, max 20,000). A renamed declaration is in `renamed`, and in `changed` only if its
|
|
82
|
+
version changed (references are read under their names at `to`: renaming what it uses is no
|
|
83
|
+
change). What an unreadable module of the later build held is neither added nor removed.
|
|
84
|
+
|
|
85
|
+
## Renames and moves
|
|
86
|
+
|
|
87
|
+
Each build, vanished declarations are paired with new ones. High confidence (the same version once
|
|
88
|
+
names are mapped) migrates by itself: opinions, comments, target and key marks go to the new name (a
|
|
89
|
+
`move` event in the server's `log/visualproof.server.jsonl`); pins, mentions in notes (full names in
|
|
90
|
+
backticks, project and view notes) and names in view scopes move on the views (`views` lists view
|
|
91
|
+
"" for project notes). Opinions keep their version: a pure rename changes none. Medium confidence:
|
|
92
|
+
only suggested.
|
|
93
|
+
|
|
94
|
+
- `GET /api/agent/history/moves`: `{migrations: [{id, at, from, to, snap?, by, agent?, auto?,
|
|
95
|
+
rename, review, carried: {opinions, targets, keys, notes, pins, scopes, reviewViews}, views:
|
|
96
|
+
[{view, ops, scope?}], undone?: {by, agent?, at}}], suggestions: [{from, to, confidence:
|
|
97
|
+
"medium", why, score, snap}]}`. `auto`: why sure (`same version`, or `same kernel hash` against a
|
|
98
|
+
build read before versions); `review`: whether a move went to the logs (something was said of it
|
|
99
|
+
or of what refers to it). A suggestion lasts while its old name is gone, its new one there, and
|
|
100
|
+
no migration made it.
|
|
101
|
+
- `POST /api/agent/history/move {from, to}` (needs full; MCP: `attach`): what was said of a gone
|
|
102
|
+
`from` goes to `to` in the graph — a move in your log; pins, notes, scopes on the views; a rename
|
|
103
|
+
if `to` was absent from the last build with `from`. 409: `from` still in the graph; 404: `to`
|
|
104
|
+
not. `{ok, changed, migration?}`.
|
|
105
|
+
- `POST /api/agent/history/unmove {id}` (needs full): an un-move in your log takes back exactly what
|
|
106
|
+
it carried (what was said of the new name since stays), and its changes on the views. 409: undone
|
|
107
|
+
already.
|
|
108
|
+
|
|
109
|
+
## The lost-and-found
|
|
110
|
+
|
|
111
|
+
What was said or marked of a declaration gone from the graph, carried by no rename, waits here for
|
|
112
|
+
everyone; nothing is deleted. Attach it (`history/move`) or archive it (only hides it).
|
|
113
|
+
`GET /api/agent/history/lost`:
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{ "lost": [ { "name": "isRegularPrime_two", "last": { "snapshot": 1, … }, "suggestions": [],
|
|
117
|
+
"entries": [ { "key": "target:isRegularPrime_two", "kind": "target", "by": "Bob", … } ] } ],
|
|
118
|
+
"migrations": [ { "key": "move:m1", "from": "isRegularPrime_three", "to": "isRegularPrime_3", … } ],
|
|
119
|
+
"archived": [], "aside": { "entries": 0, "modules": [] }, "count": 2 }
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
- `last`: the newest build that had it (null if none kept did); `suggestions`: medium-confidence
|
|
123
|
+
renames, likeliest first.
|
|
124
|
+
- Entry `kind`: `opinion` (`verdict`, `comment`), `target`, `key` (`target`, `member`: lost where
|
|
125
|
+
either is gone), `pin` (`view`, `title`, `mode`), `note` (`view`, `note`, `text`: a note naming it
|
|
126
|
+
in full in backticks; `view` "" for a project note).
|
|
127
|
+
- Entry `key`, the same for everyone: `opinion:<name>#<by>@<at>` (as a comment quotes an opinion),
|
|
128
|
+
`target:<name>`, `key:<target>#<name>`, `pin:<view>:<mode>:<name>`,
|
|
129
|
+
`note:<view>:<note id>:<name>`, `move:<migration id>`.
|
|
130
|
+
- `aside`: entries in files the build on show could not read (not vanished, not listed). `count`:
|
|
131
|
+
lost entries and migrations not archived.
|
|
132
|
+
|
|
133
|
+
## Last build, and the archive
|
|
134
|
+
|
|
135
|
+
- `GET /api/agent/history/last?name=`: `{name, snapshot, at, approx?, commit, module}`, the newest
|
|
136
|
+
build that had it; 404 if none kept did.
|
|
137
|
+
- `GET /api/agent/history/archive`: `{archived: [{key, on: true, by, agent?, person?, at}]}`, the
|
|
138
|
+
lines that archived what is archived now.
|
|
139
|
+
- `POST /api/agent/history/archive {key, on}` or `{keys, on}` (needs full): archive entries or
|
|
140
|
+
migrations (`on` true, default; at most 500) — to `archived`, for everyone — or put them back
|
|
141
|
+
(`false`). The thing itself is untouched. Recorded in the server's state under your name, as an
|
|
142
|
+
agent's: `{ok, changed, lines}`. 404: a key not listed (to put back: not archived).
|