You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 1a440e7
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: docs/specs/dor-browser.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -200,7 +200,7 @@ Source of truth: `lib/src/components/wall/agent-browser-surface-controller.ts` (
200
200
201
201
-`launch` opens an http(s) `url` in a new GUI session, or for a named session navigates its browser when up in the mode asked for, else relaunches it headed or headless; it resolves when the browser is up, not the page. **Never stop a browser a named launch finds up in its mode**: a Tool re-announced (rationale).
202
202
-**Never start a browser from `attach` or `measure`**, except that `attach` relaunches a gone one at the page its caller names, answering `relaunched`.
203
-
-**Never expose arbitrary CLI arguments, JavaScript or CDP methods through the webview channel**: each operation is one fixed argv or client call, and `edit` runs fixed host-owned JS plus an OS clipboard write. The trusted `dor` process keeps native passthrough.
203
+
-**Never expose arbitrary CLI arguments, JavaScript or CDP methods through the webview channel**: each operation is one fixed argv or client call, and `edit` runs fixed host-owned JS plus an OS clipboard write. Tool reading-state operations follow `docs/specs/dor-tool.md` → Document navigation. The trusted `dor` process keeps native passthrough.
204
204
205
205
**Must answer a launch inside `BROWSER_REQUEST_TIMEOUT_MS`**, queueing included — the wait every transport gives any reply, past agent-browser's own 25 s action timeout, so the webview never re-asks while the host still works.
Copy file name to clipboardExpand all lines: docs/specs/dor-tool.md
+15-3Lines changed: 15 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -131,7 +131,7 @@ Source of truth: `useToolRunEnd` in `lib/src/components/wall/use-tool-run-end.ts
131
131
132
132
A reap stops an idle Tool's Session, shell included; rehydrate starts it again in the same Surface, which keeps its leaf, Tool metadata, scrollback, rename, and alert, and reads as an exited Session meanwhile.
133
133
134
-
**Must reap only a Tool whose running designated command declared itself safe to stop** with `dehydrate: true` in the run's latest `serve` ([OSC 367](#osc-367)): its args alone restart it, and a payload only adds fidelity. Clean or unreported state never qualifies (rationale). **Never reap a Tool** that reports unsaved changes, announced `persist: "never"`, is a marked preview slot or popped out, awaits approval, has an auxiliary helper, is a pending kill (`docs/specs/reopen.md`), or belongs to a closing or transferring Workspace (rationale).
134
+
**Must reap only a Tool whose running designated command declared itself safe to stop** with `dehydrate: true` in the run's latest `serve` ([OSC 367](#osc-367)): its args alone restart it, and a payload only adds fidelity. Clean or unreported state never qualifies (rationale). **Never reap a Tool** that reports unsaved changes, announced `persist: "never"`, is a marked preview slot or popped out, awaits approval or document navigation, has an auxiliary helper, is a pending kill (`docs/specs/reopen.md`), or belongs to a closing or transferring Workspace (rationale).
135
135
136
136
**Must reap only after 30 minutes continuously out of sight and without PTY output** — Doored, in an inactive Workspace, or in a hidden webview (rationale): never on the minimize or switch itself, and never for memory pressure. The stop:
137
137
@@ -233,6 +233,18 @@ Source of truth: `resolveOpenTool` in `lib/src/host/tool-open.ts`.
233
233
234
234
Source of truth: `runFilePicker` in `dor/src/commands/open-picker.ts`; `listOpenHandlers` in `lib/src/host/tool-open.ts`.
235
235
236
+
## Document navigation
237
+
238
+
-**Must resolve a Tool's document-link request through ordinary open dispatch and trust checks**, relative to the current canonical document's directory. The request chooses the current Surface or another Surface; it never requests a preview or a fresh instance. Existing matching Tools are focused through ordinary reuse without changing either Surface's history.
239
+
-**Must keep Back/Forward history on the navigating Surface**, covering every file/folder handler, including user Tools. Traversal reopens the recorded canonical target with its selected handler and lookup directory in that Surface even when another Surface shows the target; a new in-place visit after Back drops the forward branch. Pin a preview on a committed in-place file visit.
240
+
-**Must obtain Save / Discard / Cancel before replacing a dirty document**, using [Closing unsaved Tools](#closing-unsaved-tools). A same-document anchor or reuse of another Surface leaves the draft alone. Never cache drafts or undo state in history.
241
+
-**Must validate the destination before interrupting the current Tool**, and keep the current location/history on lookup failure or cancelled consent. Refuse overlapping navigation from one Surface and stale requests whose source run changed. When the interrupt or the new run fails, keep or restore the source's run, never typing over user input. Report navigation failures on the source, without opening the preview error viewer.
242
+
-**Must retain history through minimize, renderer changes, and live Workspace transfer, but never in durable saves**. Only the current document restarts after cold restore. Ending designation, Break, or closing discards history. Refuse Workspace transfer during navigation or pending reading-position restoration.
243
+
-**Must release pending reading-position restoration on timeout**, even when the destination never serves a page or never answers; renderer rebinding must not renew the deadline.
244
+
-**Must capture and restore Markdown reading position during history traversal**, including source/rich-text mode; an anchor visit selects rich text. Capture is best effort: a page that cannot answer still navigates. Reading-state replies are matched as save replies are, and never acknowledge a save or update dirty state. Automation renderers use a fixed host-owned read/apply operation with validated reading-state data, never page-supplied code.
245
+
246
+
Source of truth: `surface.tool` in `lib/src/components/wall/use-dor-control.ts`; `toolView` in `lib/src/components/wall/tool-navigation.ts`; `ToolPanel` in `lib/src/components/wall/ToolPanel.tsx`; `dor-tools-lib/src/protocol.ts`.
247
+
236
248
## Preview slot
237
249
238
250
**Must keep at most one preview slot per Workspace**: a Tool Surface whose params carry `toolPreview`, marked in its Pane header and Door (`docs/specs/layout.md` → Pane header) and tagged `[preview]` by `dor list`. Creating a slot pins every other marked Surface, a closing one included, so a refused close never leaves two. **Must resolve a preview through the user's ordered `open` list**, as `dor open` does, never through a faster built-in-only renderer (rationale). A Tool browsing files selects with `dor open --preview <file>` and activates with `dor open <file>`, or sends either as an OSC 367 `open` ([OSC 367](#osc-367)). Same Tool means same scope, name and run; a run a superseded retarget interrupted is not running.
@@ -342,9 +354,9 @@ Source of truth: `toolTakesOverCaller` in `lib/src/components/wall/tool-takeover
342
354
-**Must reconstruct announcements, state, and resets from raw replay without emitting replies or acting on an `open`**, preserving transferred announcements when since-mark replay has no command start. Ordinary terminal announcements stay inert.
343
355
-**Must read a `serve` carrying only `dehydrate` or `persist` as an announcement**, which selects no port. `dehydrate: true` and `persist: "never"` govern [Reaping](#reaping) alone; `persist: "respawn"` is the default, and neither changes cold restore.
344
356
- Reserved: **Must retain `name` as an inert parsed field**, serving the announced-name item under [Future](#future).
345
-
-**Must act on `open` only from live output of a Tool Session's launched run**, as `dor open` from that Session (`--preview` when `preview` is true), resolved from the Session's local CWD, else the target's directory. The path is absolute, with no control character; the Tool gets no answer.
357
+
-**Must act on `open` only from live output of a Tool Session's launched run**, using [Document navigation](#document-navigation) when a disposition is present, otherwise as `dor open` from that Session (`--preview` when `preview` is true), resolved from the Session's local CWD, else the target's directory. The path is absolute, with no control character; the Tool gets no answer.
346
358
-**Must drop every `open` at the PTY owner's parse outside the launched run**: from the first command start after a write the host marked `launch`, if the shell reports that write's line, to the next start, finish, or prompt. Any start ends the launch. Output never begins a run; a reported line only narrows, never vouches (rationale). **Must mark `launch` only command lines the host types to run**, never user input, `dor send`, or a remote Client's write.
347
-
-**Must show a failed `open` in the preview slot**: a preview whose lookup fails runs the built-in error viewer there instead (`docs/specs/dor-tools-builtin.md` → Error viewer), and a failed activate is sent again as a preview unless a newer `open` from that Session followed it.
359
+
-**Must show a failed legacy `open` without a disposition in the preview slot**: a preview whose lookup fails runs the built-in error viewer there instead (`docs/specs/dor-tools-builtin.md` → Error viewer), and a failed activate is sent again as a preview unless a newer `open` from that Session followed it.
348
360
-**Never assign an OSC 367 verb beyond `serve`, `state`, `open`, and `dehydrate`**; existing title/progress protocols keep those roles.
349
361
350
362
Source of truth: `dor-tools-lib/src/osc.ts`; `TerminalProtocolParser` in `lib/src/lib/terminal-protocol.ts`; `ToolLaunchLatch` in `lib/src/lib/tool-launch-latch.ts`; `applyLiveToolEvents` in `lib/src/lib/tool-events.ts`.
Copy file name to clipboardExpand all lines: docs/specs/dor-tools-builtin.md
+9Lines changed: 9 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -55,6 +55,15 @@ Source of truth: `saveText` / `StorePath` in `dor-tools-builtin/src/editor-route
55
55
56
56
Source of truth: `dor-tools-builtin/viewer/markdown.tsx`; `safeCreateDOM` in `dor-tools-builtin/viewer/markdown-safety.ts`; `editorRoutes` in `dor-tools-builtin/src/editor-routes.ts`; `dor-tools-builtin/src/markdown-images.ts`. Tests: `dor-tools-builtin/test/markdown-editor.test.mjs`.
57
57
58
+
### Relative links
59
+
60
+
-**Must follow a relative link on plain click**, and offer Open in another surface and Edit link on its context menu. Cmd/Ctrl-click chooses another Surface. Dispatch follows `docs/specs/dor-tool.md` → Document navigation. (rationale)
61
+
-**Must treat only a scheme-less relative reference as a document link**, resolved from the opened canonical file's directory with parent references allowed and its query ignored; HTTP(S)/mail links keep their existing handling.
62
+
-**Must send document opens to the Tool process**, which emits OSC 367 (`docs/specs/security-local.md` → Local-file viewer); **never navigate relative to the capability URL**. The page receives only sent/error, with host failures shown by the Surface.
63
+
-**Must resolve a fragment to the rendered heading whose case-folded, punctuation-stripped, duplicate-suffixed id it names**, never writing ids into saved Markdown. Same-document fragments scroll without reloading or prompting; a missing heading reports an error while retaining the document. Back/Forward reading-state semantics belong to `docs/specs/dor-tool.md` → Document navigation.
64
+
65
+
Source of truth: `dor-tools-builtin/viewer/markdown.tsx`; `markdownLink` in `dor-tools-builtin/src/markdown-links.ts`; `runFileViewer` in `dor-tools-builtin/src/file-viewer.ts`.
66
+
58
67
## Image editor
59
68
60
69
`builtin:file` edits PNG and JPEG, alone or over a [Markdown document](#markdown-editor).
Copy file name to clipboardExpand all lines: docs/specs/dor-tools-builtin.rationale.md
+5Lines changed: 5 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -39,3 +39,8 @@ Windows tests in 2026-10 (Node 22.22.3) showed an atomic Node rename failing wit
39
39
Microsoft documents ReplaceFile failures that have already moved the original or replacement file (1176/1177), as well as a native commit preceding a lost helper reply. Deleting the draft or backup after an unconfirmed replacement can therefore delete the only surviving bytes. Confirmed saves and failures before replacement still delete both.
40
40
41
41
The Windows draft inherits its directory's ACL, so a protected document in a more broadly readable directory exposes its unsaved draft to that directory's readers until replacement merges the document's ACL. An owner-only stage was tried and dropped (2026-10): creating it needed a PowerShell `Add-Type` P/Invoke to `CreateDirectoryW`, which compiled C# and spawned PowerShell a second time on every save, failed under Constrained Language Mode, and protected draft bytes only in that rare configuration.
42
+
43
+
44
+
## Relative links
45
+
46
+
Lexical 0.48 formats a bare Markdown filename such as `b.md` as `https://b.md` in the live anchor, while retaining the original URL in its node. The viewer preserves validated document references in that rendering step so ordinary clicks and the link dialog agree (innerdogfood, 2026-10).
Copy file name to clipboardExpand all lines: docs/specs/dor-tools-lib.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
# Dor Tools Library
2
2
3
3
> - See `docs/specs/glossary.md` for Session / Pane vocabulary.
4
-
> - Owns `dor-tools-lib`, the MIT package that Tools and their hosts share for the Tool integration protocol: its license and dependency boundary, entry points, and consumers. The wire rules it implements belong to `docs/specs/dor-tool.md` → OSC 367, Unsaved changes, and Closing unsaved Tools.
4
+
> - Owns `dor-tools-lib`, the MIT package that Tools and their hosts share for the Tool integration protocol: its license and dependency boundary, entry points, and consumers. The wire rules it implements belong to `docs/specs/dor-tool.md` → OSC 367, Unsaved changes, Closing unsaved Tools, and Document navigation.
5
5
6
6
## Package
7
7
@@ -13,7 +13,7 @@
13
13
|---|---|---|
14
14
|`osc`| an encoder per verb, throwing on a value the host would ignore; a reader for its own dehydrate payload | a parser per verb |
|`frame`| the save/reading-state channel client | — |
17
17
18
18
-**The host (`lib`) must reach the package through source aliases**, beside every `dor-tools-builtin/*` alias, since no host build compiles the package first.
19
19
-`dor-tools-builtin` speaks the protocol through it (`docs/specs/dor-tools-builtin.md` → Packaging).
**Must hold the slot's header while a switch holds its ghost** (`docs/specs/dor-tool.md` → Switching the slot): the ghost's face and Display glyph stay until the new view is ready. A terminal face's label keeps its name until the retarget, then shows the Tool's name (`docs/specs/dor-tool.md` → Naming); derivation resumes once ready. A serving Tool's name, read from its params, needs no hold (rationale).
31
31
32
-
**Never give a Tool navigation, an address, or a dev-server chip** (rationale).
32
+
**Must offer document Back/Forward on both Tool faces when the Surface has history**, in Terminal Context at narrow widths (`docs/specs/dor-tool.md` → Document navigation). **Never give a Tool an address or a dev-server chip** (rationale).
33
33
34
34
Every Pane header ends with the pane-action group: zoom/unzoom, minimize, kill.
Copy file name to clipboardExpand all lines: docs/specs/layout.rationale.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,7 @@
6
6
7
7
The keep is judged by the burst's first press, so a double-click inside a rename opened earlier still selects a word. A preview's label opens no rename because the double-click's first click would open the field under the second.
8
8
9
-
Tools carry no navigation, address, or dev-server chip (Ned, 2026-09-29): a Tool is named for what it is, and a page it serves is not somewhere to navigate from, so that chrome stays with plain browser Surfaces.
9
+
Tools remain named for what they are, without exposing a capability URL as an address. Document Back/Forward extends their file workflow; it is separate from a browser renderer's own URL history (2026-10).
10
10
11
11
A serving preview's header changed size on every switch while its name was the dev-server chip (standalone, 2026-09-29): the chip names a pane only once the Window's port scan resolves the page's loopback port (600 ms of debounce, then a scan at idle), which landed after the switch's hold had ended, so the address widened to the whole `localhost:<port>/<path>` and shrank back. A name from params changes once, with the retarget, so nothing needs holding.
0 commit comments