@quo-systems/dock 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/NOTICE +6 -0
- package/README.md +27 -0
- package/beings/avatar.ts +84 -0
- package/beings/desk.ts +46 -0
- package/beings/index.ts +5 -0
- package/beings/quo-dock.md +698 -0
- package/beings/setup.ts +23 -0
- package/beings/side.ts +51 -0
- package/beings/user.ts +78 -0
- package/cli/client.ts +65 -0
- package/cli/daemon.ts +582 -0
- package/cli/quo.ts +126 -0
- package/dist/beings/avatar.d.ts +32 -0
- package/dist/beings/avatar.js +82 -0
- package/dist/beings/desk.d.ts +42 -0
- package/dist/beings/desk.js +43 -0
- package/dist/beings/index.d.ts +3 -0
- package/dist/beings/index.js +5 -0
- package/dist/beings/setup.d.ts +2 -0
- package/dist/beings/setup.js +16 -0
- package/dist/beings/side.d.ts +25 -0
- package/dist/beings/side.js +37 -0
- package/dist/beings/user.d.ts +108 -0
- package/dist/beings/user.js +74 -0
- package/dist/cli/client.d.ts +14 -0
- package/dist/cli/client.js +51 -0
- package/dist/cli/daemon.d.ts +57 -0
- package/dist/cli/daemon.js +581 -0
- package/dist/cli/quo.d.ts +2 -0
- package/dist/cli/quo.js +121 -0
- package/dist/harbor/browser.d.ts +13 -0
- package/dist/harbor/browser.js +50 -0
- package/dist/harbor/disk.d.ts +19 -0
- package/dist/harbor/disk.js +126 -0
- package/dist/harbor/edge/edge.d.ts +26 -0
- package/dist/harbor/edge/edge.js +123 -0
- package/dist/harbor/edge/exercise.d.ts +7 -0
- package/dist/harbor/edge/exercise.js +179 -0
- package/dist/harbor/edge/storage.d.ts +20 -0
- package/dist/harbor/edge/storage.js +81 -0
- package/dist/harbor/edge/worker.d.ts +14 -0
- package/dist/harbor/edge/worker.js +47 -0
- package/dist/harbor/files.d.ts +14 -0
- package/dist/harbor/files.js +83 -0
- package/dist/harbor/idb.d.ts +15 -0
- package/dist/harbor/idb.js +85 -0
- package/dist/human/dom.d.ts +2 -0
- package/dist/human/dom.js +15 -0
- package/dist/human/html.d.ts +32 -0
- package/dist/human/html.js +136 -0
- package/dist/human/screen.d.ts +11 -0
- package/dist/human/screen.js +66 -0
- package/dist/human/tab.d.ts +7 -0
- package/dist/human/tab.js +68 -0
- package/dist/mcp/agent.d.ts +10 -0
- package/dist/mcp/agent.js +78 -0
- package/dist/mcp/http.d.ts +27 -0
- package/dist/mcp/http.js +96 -0
- package/dist/mcp/oauth.d.ts +98 -0
- package/dist/mcp/oauth.js +241 -0
- package/dist/mcp/pilot.d.ts +6 -0
- package/dist/mcp/pilot.js +68 -0
- package/dist/mcp/runner.d.ts +45 -0
- package/dist/mcp/runner.js +94 -0
- package/dist/mcp/server.d.ts +9 -0
- package/dist/mcp/server.js +63 -0
- package/dist/mcp/web/exchange.d.ts +23 -0
- package/dist/mcp/web/exchange.js +136 -0
- package/harbor/browser.ts +63 -0
- package/harbor/disk.ts +120 -0
- package/harbor/edge/edge.ts +147 -0
- package/harbor/edge/exercise.ts +187 -0
- package/harbor/edge/platform.d.ts +28 -0
- package/harbor/edge/storage.ts +82 -0
- package/harbor/edge/worker.ts +47 -0
- package/harbor/edge/wrangler.toml +21 -0
- package/harbor/files.ts +89 -0
- package/harbor/idb.ts +90 -0
- package/harbor/quo-harbor.md +403 -0
- package/human/dom.ts +21 -0
- package/human/html.ts +164 -0
- package/human/quo-human.md +86 -0
- package/human/screen.ts +76 -0
- package/human/tab.ts +84 -0
- package/mcp/agent.ts +94 -0
- package/mcp/http.ts +96 -0
- package/mcp/oauth.ts +260 -0
- package/mcp/pilot.ts +73 -0
- package/mcp/quo-mcp.md +262 -0
- package/mcp/runner.ts +131 -0
- package/mcp/server.ts +67 -0
- package/mcp/web/exchange.ts +146 -0
- package/package.json +89 -0
|
@@ -0,0 +1,698 @@
|
|
|
1
|
+
# The dock
|
|
2
|
+
|
|
3
|
+
This is the trunk of the dock: what every estate on Quo needs and nobody writes
|
|
4
|
+
twice. `packages/quo/SPEC.md` is the truth of `packages/quo/src` and knows
|
|
5
|
+
nothing of this folder; the four documents under `packages/dock/` are the truth
|
|
6
|
+
of their folders in the same way, and where any of them disagrees with
|
|
7
|
+
`packages/quo/SPEC.md`, the spec wins and the document is rewritten. Nothing
|
|
8
|
+
here adds a word to harbor, ward or being.
|
|
9
|
+
|
|
10
|
+
Three layers, one repository, and the words for them:
|
|
11
|
+
|
|
12
|
+
| layer | folder | package | published |
|
|
13
|
+
| --------- | ----------------- | ------------------- | --------------- |
|
|
14
|
+
| Quo | `packages/quo/` | `@quo-systems/quo` | yes, Apache 2.0 |
|
|
15
|
+
| the dock | `packages/dock/` | `@quo-systems/dock` | yes, Apache 2.0 |
|
|
16
|
+
| an estate | `estates/*` | none | never |
|
|
17
|
+
|
|
18
|
+
**An estate is all of one owner's harbors.** The droplet, the edge and the
|
|
19
|
+
Mac under one root, with the desk, the user being and the avatars living
|
|
20
|
+
across them: that is one estate, and `estates/lab/` is its folder. A second
|
|
21
|
+
domain is a second estate. An adopter's company is an estate in their own
|
|
22
|
+
repository, and it looks exactly like ours. An estate folder is one folder
|
|
23
|
+
per harbor, each the quo directory that device runs minus what it mints,
|
|
24
|
+
its class bodies, its routes, its agents, its dial list, plus that device's
|
|
25
|
+
unit; a package file that depends on the dock and nothing else; secrets by
|
|
26
|
+
reference; and one document. Nothing else may be needed to run it, and the
|
|
27
|
+
proof is mechanical: an estate folder copied into an empty repository, with
|
|
28
|
+
one install of the dock, boots. If it does not, the missing piece belongs
|
|
29
|
+
in the dock.
|
|
30
|
+
|
|
31
|
+
**The dock is what a harbor is fitted with to receive people and models**:
|
|
32
|
+
the daemon and the `quo` command, the front desk, the user being and the
|
|
33
|
+
avatar, the harbors on real terrains, the model sides and the screen, the
|
|
34
|
+
credential exchange. It is general by two rules, under "Generality", and it
|
|
35
|
+
is published so an adopter installs it once and writes only their estate.
|
|
36
|
+
|
|
37
|
+
The four documents of the dock:
|
|
38
|
+
|
|
39
|
+
| document | owns |
|
|
40
|
+
| ---------------------- | ------------------------------------------------ |
|
|
41
|
+
| `beings/quo-dock.md` | this: the beings and rules every side shares |
|
|
42
|
+
| `human/quo-human.md` | the human side: a blueprint spoken as HTML |
|
|
43
|
+
| `mcp/quo-mcp.md` | the model side: a blueprint spoken as tools |
|
|
44
|
+
| `harbor/quo-harbor.md` | transports: harbor core, reach, store, directory |
|
|
45
|
+
|
|
46
|
+
Each names only its folder. The human document never says WebSocket or
|
|
47
|
+
OAuth; the model document never says form; the harbor document never says
|
|
48
|
+
being. Anything two sides need lives here.
|
|
49
|
+
|
|
50
|
+
## The picture
|
|
51
|
+
|
|
52
|
+
A device runs one harbor, and a harbor is nothing but the device's own
|
|
53
|
+
secrets, data and code offered to Quo. Every world on that device is a ward:
|
|
54
|
+
a seed, a partition and a body of code, with an origin the harbor
|
|
55
|
+
remembers. The device's own capabilities, GPS, camera, disk, calendar, are
|
|
56
|
+
beings in a ward that is the device owner's. Every person and every model
|
|
57
|
+
is an occupant, reaching a being through an avatar under a gate. Every SaaS
|
|
58
|
+
and every foreign API is an envoy, a being whose methods call out. Every
|
|
59
|
+
relation, to acme, to a model, to the phone's GPS, is the same relation: an
|
|
60
|
+
invitation, a knock, a standing, keys that rotate, the three words.
|
|
61
|
+
|
|
62
|
+
So the app on a desk and the app in a pocket are browsers of worlds: one
|
|
63
|
+
harbor, many wards, one per world, each in its own runtime, switching
|
|
64
|
+
between them a screen act and nothing more. A world opened there is born on
|
|
65
|
+
the device's seed with the world's code, and never has to be moved home,
|
|
66
|
+
because it was never anywhere else. The droplet is the world that never
|
|
67
|
+
sleeps. Identity is relation: a session is a standing, a token is an
|
|
68
|
+
invitation used once, login is a knock, logout is remove, and there is no
|
|
69
|
+
session store anywhere. Ownership is the device: one daemon holds the
|
|
70
|
+
harbor, the socket is the only owner door, occupants come in by routes.
|
|
71
|
+
|
|
72
|
+
## The one law
|
|
73
|
+
|
|
74
|
+
Nobody outside Quo is a being, and nobody outside Quo is a ward. A human at
|
|
75
|
+
a screen, a model at an MCP client, a model in an API loop, a SaaS behind an
|
|
76
|
+
API: every one of them is an **occupant**, reached through a being, named by
|
|
77
|
+
an id that being minted, seeing exactly what that being's gate shows it.
|
|
78
|
+
Everything under `packages/dock/` is that sentence applied to screens, models,
|
|
79
|
+
transports and devices.
|
|
80
|
+
|
|
81
|
+
Three roles exist, and they are held by where a thing runs, not by config:
|
|
82
|
+
|
|
83
|
+
| role | what it can do | who can hold it |
|
|
84
|
+
| --------- | ------------------------------------------- | --------------------------------------------------- |
|
|
85
|
+
| occupant | ask a being what her gate shows this asker | anyone, local or remote |
|
|
86
|
+
| owner | boot a being, invite for her, knock for her | the root, on the device; or a ward the root invited |
|
|
87
|
+
| developer | write a being class the harbor will hold | only a process on the device |
|
|
88
|
+
|
|
89
|
+
Whoever holds all three keeps them apart: the owner creates and places, and
|
|
90
|
+
never does the work. The work is done through an avatar under a gate, so
|
|
91
|
+
that every arrival is named and judged.
|
|
92
|
+
|
|
93
|
+
## Vocabulary
|
|
94
|
+
|
|
95
|
+
- **User being.** One being per human, running 24/7 on a dialable harbor.
|
|
96
|
+
Holds the human's standings: acme, calendar, bank, the house. Everything
|
|
97
|
+
anyone does for the human goes through her.
|
|
98
|
+
- **Avatar.** A being that is the voice of someone outside Quo. Her `answer`
|
|
99
|
+
turns to that someone over a **side**, and her methods let that someone
|
|
100
|
+
ask her one standing. The side is hers, not Quo's. A screen and a model
|
|
101
|
+
are two sides of one avatar class.
|
|
102
|
+
- **Front desk.** A being on the user's harbor that strangers and fresh
|
|
103
|
+
clients meet first. It holds a standing to every user being and can ask
|
|
104
|
+
one for a device invitation. It is the only being that is ever public, and
|
|
105
|
+
only for the first hello.
|
|
106
|
+
- **Envoy.** A being whose methods call a non-Quo thing and whose describe
|
|
107
|
+
is that thing's surface. A SaaS, an MCP server someone else runs, an
|
|
108
|
+
Arduino behind serial: each enters a world as a being like any other.
|
|
109
|
+
- **Gate.** The `for(occupant, asker)` decision on each ask of a being. What
|
|
110
|
+
she shows is what she can be asked. An occupant's entire permission model
|
|
111
|
+
is the gates of the beings it is an occupant of.
|
|
112
|
+
- **Client identity.** What a credential exchange establishes: this human at
|
|
113
|
+
this browser, this OAuth client for this human, this process on this
|
|
114
|
+
machine. One client identity is one avatar, for life.
|
|
115
|
+
- **Route.** A hostname a reverse proxy sends to one process: `web.`, `quo.`,
|
|
116
|
+
`mcp.`. Routes are deployment, never boundaries.
|
|
117
|
+
|
|
118
|
+
## Architecture
|
|
119
|
+
|
|
120
|
+
One droplet, one harbor, three routes. Every other placement is a subset.
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
acme.com, or razvan.com: the dialable part of an estate
|
|
124
|
+
reverse proxy
|
|
125
|
+
web. serves the bundle, runs the credential exchange, ends with an invitation
|
|
126
|
+
quo. the harbor's socket door: the rendezvous for every dialer
|
|
127
|
+
mcp. the model side over HTTP, a credential exchange in front
|
|
128
|
+
quo serve: one process, one harbor, the ask pointer
|
|
129
|
+
unix socket owner asks, local only, never behind the proxy
|
|
130
|
+
localhost ports the routes above
|
|
131
|
+
ward main front desk, one user being per human, envoys
|
|
132
|
+
ward avatars one avatar per client identity
|
|
133
|
+
ward estate optional: what the estate agent asks
|
|
134
|
+
|
|
135
|
+
mac
|
|
136
|
+
quo serve (laptop, dialer, holds a socket to quo.)
|
|
137
|
+
unix socket owner asks, local only
|
|
138
|
+
ward main the human's local beings
|
|
139
|
+
ward avatars avatars for local sides
|
|
140
|
+
a local agent
|
|
141
|
+
quo side -> an avatar over stdio occupant
|
|
142
|
+
quo pilot -> the ask pointer over the sock owner, here
|
|
143
|
+
quo pilot --via lab -> a standing at the droplet's ward, sealed owner, there
|
|
144
|
+
the editor -> being classes on disk developer
|
|
145
|
+
|
|
146
|
+
iphone, or a tab
|
|
147
|
+
harbor (dialer, holds a socket to quo., woken by push where there is one)
|
|
148
|
+
ward main the human's avatar for this device
|
|
149
|
+
the human at the screen occupant
|
|
150
|
+
|
|
151
|
+
droplet, unattended
|
|
152
|
+
an agent under cron -> the owner pilot owner: the estate
|
|
153
|
+
-> an avatar over stdio occupant: reports, chores
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Wards are split by trust, not by feature. Avatars live in their own ward so
|
|
157
|
+
that a class bug in an avatar takes down avatars, not the user beings. There
|
|
158
|
+
is no rule that says so; it is the cheapest isolation a harbor offers.
|
|
159
|
+
|
|
160
|
+
## The avatar
|
|
161
|
+
|
|
162
|
+
One avatar per client identity, not per session or per page load. Her
|
|
163
|
+
standing to the user being is minted once and persists in the partition; a
|
|
164
|
+
side opening and closing is a reconnect, and the keys carry on. Reconnect
|
|
165
|
+
never re-invites.
|
|
166
|
+
|
|
167
|
+
One class for every side. It has:
|
|
168
|
+
|
|
169
|
+
- `answer`: the user being asks her only to push, and she forwards the push
|
|
170
|
+
to her side as a notification if the side has one, and drops it if not.
|
|
171
|
+
She describes herself with one ask, `notify`, gated to the user being.
|
|
172
|
+
- methods that mirror what her side asked for: each call from the side
|
|
173
|
+
becomes `standings.user.ask(name, args)`, with the time the side leaves.
|
|
174
|
+
|
|
175
|
+
She never holds a second standing. Someone who should reach acme reaches the
|
|
176
|
+
user being, whose gate for that asker shows `acme.book`, and the user being
|
|
177
|
+
forwards on her own acme standing. Acme sees the human's id. The occupant
|
|
178
|
+
never sees acme's invitation, never holds a key at acme, and cannot keep a
|
|
179
|
+
relation when the human removes it.
|
|
180
|
+
|
|
181
|
+
## The side
|
|
182
|
+
|
|
183
|
+
The one interface every side implements, so that one avatar serves all:
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
side
|
|
187
|
+
describe(blueprint) the avatar's describe, spoken as this side speaks: a form, a tool list
|
|
188
|
+
call(name, args, time?) one ask in, from the side; the avatar forwards it
|
|
189
|
+
push(object) one notification out, to every side she has; dropped if there is none
|
|
190
|
+
three words object, error object, silence, and the ward's words, each rendered as the side renders it
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Sides in this repository: the human at a screen, an MCP server, a runner for
|
|
194
|
+
function-calling APIs, an event-driven agent. Each is one folder and one
|
|
195
|
+
suite; none of them knows another exists.
|
|
196
|
+
|
|
197
|
+
A side is those three things, and its lifetime is its own. Two lifetimes
|
|
198
|
+
exist, each with two users, so each earns its shape: a **connected** side
|
|
199
|
+
lives until closed, the screen and the MCP server; a **run** side lives by
|
|
200
|
+
turns, the runner and the agent, each turn from a trigger to the model's
|
|
201
|
+
last word. A push is the trigger of a turn, never a line smuggled into one:
|
|
202
|
+
a push that arrives while a turn is running waits in her cells and starts
|
|
203
|
+
the next turn when this one ends. Nothing is dropped and nothing is held;
|
|
204
|
+
the ask that carried the push was answered the moment it landed. Between
|
|
205
|
+
turns, the world reaches a model the way step 11 says, an ask that starts a
|
|
206
|
+
run and a callback when it ends.
|
|
207
|
+
|
|
208
|
+
One describe, many renderings. A screen is the user being's describe spoken
|
|
209
|
+
as forms; a tool list is the same describe spoken as tools. Nobody builds a
|
|
210
|
+
UI and then a tool layer: they build asks, both fall out, and neither side
|
|
211
|
+
can do a thing the other cannot, because the gate is one decision for
|
|
212
|
+
describe and for dispatch.
|
|
213
|
+
|
|
214
|
+
## Asks only
|
|
215
|
+
|
|
216
|
+
There is no listening in Quo, and none under `packages/dock/`. A being who wants
|
|
217
|
+
another's events invites her, the other takes the standing, and asks her
|
|
218
|
+
whenever something happens. An event is an ask in the other direction, and
|
|
219
|
+
it is the same act next door and across planets; only latency and
|
|
220
|
+
reachability change. It follows that two beings never share memory, not
|
|
221
|
+
even in one ward: a callback, a stream or a bus between them is a link that
|
|
222
|
+
breaks the day one of them moves, and Quo exists so that nothing breaks
|
|
223
|
+
when a being moves.
|
|
224
|
+
|
|
225
|
+
Two consequences every side obeys:
|
|
226
|
+
|
|
227
|
+
- **Pushing to a dialer is asking a dialer.** The server asks the tab, so
|
|
228
|
+
the tab's being must have invited the server's, and the tab's harbor must
|
|
229
|
+
hold a socket for the ask to arrive on.
|
|
230
|
+
- **Slow work acknowledges.** An ask waits thirty seconds by default and
|
|
231
|
+
five minutes at the ceiling, and a late reply is not read. Anything that
|
|
232
|
+
takes longer answers at once with an acknowledgement and asks back on its
|
|
233
|
+
own standing when it is done. A run never holds an ask open.
|
|
234
|
+
|
|
235
|
+
## The front desk
|
|
236
|
+
|
|
237
|
+
Public, for the first hello only, and everything after is behind an
|
|
238
|
+
invitation. Its asks:
|
|
239
|
+
|
|
240
|
+
```
|
|
241
|
+
hello() -> { asks it will answer, and how to get in }
|
|
242
|
+
device({ proof }) -> invitation | { error } proof is what a route produced
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
`proof` is the outcome of a credential exchange that already happened outside
|
|
246
|
+
Quo: a session cookie `web.` set, an OAuth grant `mcp.` verified, a signed
|
|
247
|
+
nonce from a local process. The front desk checks it with the verifier for
|
|
248
|
+
that proof kind, finds the user being, asks her `invite({ client })`, and
|
|
249
|
+
hands back what she minted. The front desk never mints an invitation itself:
|
|
250
|
+
only the user being invites into her own world, and she keeps the client
|
|
251
|
+
identity in the occupant's notes.
|
|
252
|
+
|
|
253
|
+
## The credential exchange
|
|
254
|
+
|
|
255
|
+
The only piece that looks like today's SaaS, and it is deliberately kept as
|
|
256
|
+
thin as one call. Every route ends the same way:
|
|
257
|
+
|
|
258
|
+
1. The route authenticates by its own means. Password, passkey, OAuth, a
|
|
259
|
+
bearer token from a client, a nonce from a local process.
|
|
260
|
+
2. The route asks the front desk `device({ proof })` and receives an
|
|
261
|
+
invitation.
|
|
262
|
+
3. The route hands the invitation to the avatar it is about to boot, or to
|
|
263
|
+
the one already booted for this client identity if it is a reconnect, in
|
|
264
|
+
which case nothing is handed and the existing standing is used.
|
|
265
|
+
4. The avatar knocks. The heir dies. From here there is no token anywhere.
|
|
266
|
+
|
|
267
|
+
The human decides one more thing at step 1, on the same page that names
|
|
268
|
+
the identity: whether this device may **wake** the human's other devices.
|
|
269
|
+
The word travels with the proof, the user being writes it as a note on the
|
|
270
|
+
occupant she mints, and her gate reads the note: `push` is shown to the
|
|
271
|
+
desk and to a device with that note, and to nobody else. A device that may
|
|
272
|
+
wake can hand an agent an event through the user being, and she sees who
|
|
273
|
+
did. The note is written when the occupant is minted; to change it, remove
|
|
274
|
+
the occupant and allow again, because reconnect mints nothing.
|
|
275
|
+
|
|
276
|
+
Tokens, cookies and grants exist for the length of step 1 and are never
|
|
277
|
+
stored on a Quo side. Revocation is `occupants.remove(id)` on the user being:
|
|
278
|
+
the client's next ask, under the key the door bound for its avatar, hears
|
|
279
|
+
`removed`, and the side speaks that in its own vocabulary: the MCP route
|
|
280
|
+
answers 401 at the next session and forgets the grant.
|
|
281
|
+
|
|
282
|
+
## The daemon and the CLI
|
|
283
|
+
|
|
284
|
+
One command, `quo`, under `packages/dock/cli/`. It imports the four library exports
|
|
285
|
+
and nothing else, holds no class body, and never speaks to a ward except
|
|
286
|
+
through the ask pointer or an avatar, the two doors everyone has.
|
|
287
|
+
|
|
288
|
+
```
|
|
289
|
+
quo init [--dir D] mint a seed, boot a harbor and one ward over a disk store, write both
|
|
290
|
+
quo serve [--dir D] [--dial URL] the daemon: harbor from disk, the unix socket, the routes' listeners, the agents, a socket held to URL
|
|
291
|
+
quo pilot [--dir D] [--via S] the owner pilot over stdio: boot, invite, knock, remove, census; as the root, or via a standing at another ward
|
|
292
|
+
quo side [--dir D] --as NAME an avatar over stdio for a local client; NAME is the client identity
|
|
293
|
+
quo run [--dir D] --as NAME --url URL --model NAME a human at a terminal talking to a model through an avatar; a line in, the final text out
|
|
294
|
+
quo census [--dir D] print the census once and exit
|
|
295
|
+
quo boot|invite|knock|remove the four owner asks from a shell, for scripts and for agents under cron; --via S sends them to another ward
|
|
296
|
+
quo reach <pk> <url> a hint for the harbor's directory: that world's ward lives at that quo. route
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**One process owns the harbor.** `quo serve` is the only process that ever
|
|
300
|
+
holds the seed, the partition and the ask pointer, on every device, the Mac
|
|
301
|
+
included. Two processes over one partition are two wards with one pk, and
|
|
302
|
+
they diverge silently. `init` is the one exception: it creates with no
|
|
303
|
+
daemon running, and exits.
|
|
304
|
+
|
|
305
|
+
**Everyone else connects to it locally.** `pilot` and the bare owner asks
|
|
306
|
+
are clients of a unix socket the daemon opens with permissions only the
|
|
307
|
+
device's user can read, and the daemon hands the ask pointer to that
|
|
308
|
+
socket. `side` is a client of a second local socket, for occupants: the
|
|
309
|
+
first line names a client identity, every line after is MCP, and the model
|
|
310
|
+
side runs in the daemon beside the avatar, so the process on the other end
|
|
311
|
+
is a pipe to stdio and knows nothing but newlines. Reaching that socket is
|
|
312
|
+
the proof for a local side: the daemon mints a nonce the desk honours
|
|
313
|
+
once, and a `local` proof arriving any other way is refused. `packages/quo/SPEC.md`
|
|
314
|
+
allows this: the harbor hands the ask to one holder by the device's own
|
|
315
|
+
rules, and file permissions are the device's rules. The ward stays
|
|
316
|
+
in-process with its harbor; only the pointer crosses, across a
|
|
317
|
+
boundary the harbor guards.
|
|
318
|
+
|
|
319
|
+
**Two kinds of door on one daemon, never mixed.** The unix socket is for
|
|
320
|
+
the owner and is never behind the proxy; there is no `cli.` route. The
|
|
321
|
+
listeners on localhost are for occupants and sit behind the proxy as the
|
|
322
|
+
routes. The socket is the root. Owning a droplet from elsewhere is a
|
|
323
|
+
standing: the root there invites an owner on the ward's own pk, the root
|
|
324
|
+
here knocks for the user being with it, and she takes the droplet's ward
|
|
325
|
+
under a name, `lab`. Owning is one of the human's standings, so she holds
|
|
326
|
+
it as she holds acme. From then on `quo pilot --via lab`, and the bare
|
|
327
|
+
owner asks with `--via lab`, are sealed asks at the droplet's door,
|
|
328
|
+
counted, rotated, removable: the daemon here asks on her standing
|
|
329
|
+
in-process, as it drives an avatar for a side, and saves. The answers are
|
|
330
|
+
the droplet's, as it answers an owner at its door. SSH is for the day the
|
|
331
|
+
root itself must act. No key is ever carried but an invitation, and an
|
|
332
|
+
owner at the door cannot mint another.
|
|
333
|
+
|
|
334
|
+
**The CLI stays thin.** Each subcommand picks a directory, builds the
|
|
335
|
+
store, reaches the daemon, and hands off to a being or a side that already
|
|
336
|
+
exists. Logic that appears in a subcommand was missing from a being or a
|
|
337
|
+
side, and moves there.
|
|
338
|
+
|
|
339
|
+
## Envoys: the non-Quo world coming in
|
|
340
|
+
|
|
341
|
+
Every API, SaaS, MCP server run by someone else, and every device that
|
|
342
|
+
speaks no Quo, enters a world as an envoy being:
|
|
343
|
+
|
|
344
|
+
- Her methods call the outside thing. Her describe is that thing's surface,
|
|
345
|
+
narrowed to what the human wants exposed.
|
|
346
|
+
- Her credential for the outside thing comes from the device's environment
|
|
347
|
+
through her class, never through her cells. Cells are values in the
|
|
348
|
+
partition, and the partition is the harbor's to persist; a secret written
|
|
349
|
+
there would be a secret the harbor has to lie about.
|
|
350
|
+
- She is an ordinary occupant of the user being, or the user being holds a
|
|
351
|
+
standing to her, by the same invitation dance as any relation.
|
|
352
|
+
|
|
353
|
+
## Scenes
|
|
354
|
+
|
|
355
|
+
The estate is proven by scenes, not features. Each one below uses nothing
|
|
356
|
+
but what is written above, and each names the one place a convention had
|
|
357
|
+
to be decided.
|
|
358
|
+
|
|
359
|
+
1. **A link on WhatsApp.** An acme employee's being minted an id for you
|
|
360
|
+
and got an invitation; the link is that value next to a reach hint. It
|
|
361
|
+
is single-use and unowned: whoever knocks first is bound, so links are
|
|
362
|
+
minted per person. The hint is a harbor convention.
|
|
363
|
+
2. **You have a world.** Your root does one owner knock: a being of yours,
|
|
364
|
+
existing or booted on the spot, knocks with the invitation, takes acme,
|
|
365
|
+
and puts its own invitation in the args so acme can push back. Two
|
|
366
|
+
invitations, two relations. You never open acme's page.
|
|
367
|
+
3. **You have no world.** The link opens a tab; the bundle boots a harbor,
|
|
368
|
+
a ward and an avatar on a seed minted into the browser's store; the
|
|
369
|
+
avatar knocks and takes acme; the tab's screen is her side. A world in a
|
|
370
|
+
rented room: yours, on your seed, booted by acme's code.
|
|
371
|
+
4. **Urgency now, home later.** Book in the tab. At home, the tab exports
|
|
372
|
+
seed and partition and deletes its copy in one gesture; your harbor
|
|
373
|
+
boots the same seed, the same pk, and acme's rendezvous rebinds it on the
|
|
374
|
+
next connect. Migration is three moves and nobody is told.
|
|
375
|
+
5. **A model books for you.** Claude is an occupant of your user being
|
|
376
|
+
through an avatar; your gate shows it `acme.book` and `calendar.free`;
|
|
377
|
+
your being forwards on her own standings. Acme sees your id and never
|
|
378
|
+
learns a model was involved. Remote Claude is an occupant and nothing
|
|
379
|
+
else; local Claude may also be the owner and the developer, kept apart.
|
|
380
|
+
6. **An agent woken by events.** Your user being asks the agent's avatar;
|
|
381
|
+
the avatar starts a run in its folder and acknowledges; the run asks back
|
|
382
|
+
with the result. One run at a time. What it may do is the gate; how it
|
|
383
|
+
behaves is its constitution.
|
|
384
|
+
7. **A phone in a tunnel.** The socket drops, the rendezvous forgets the
|
|
385
|
+
reach, asks to the phone are unreached, and nothing else moves. Seed,
|
|
386
|
+
partition and keys are on the phone. Reconnect rebinds the same pk under
|
|
387
|
+
the same keys and count. Signal is lost, identity never.
|
|
388
|
+
8. **A ward on another device, piloted from here.** The root there invites
|
|
389
|
+
an owner on the ward; your being knocks; every owner ask from now on is a
|
|
390
|
+
sealed ask on that standing, counted, rotated, removable. No key is ever
|
|
391
|
+
carried but an invitation, and an owner at the door cannot mint another.
|
|
392
|
+
|
|
393
|
+
## Generality
|
|
394
|
+
|
|
395
|
+
Six general pieces exist under `packages/dock/`, and everything concrete is an
|
|
396
|
+
implementation of one of them. An estate implements none of them: it holds
|
|
397
|
+
class bodies and placement, and reaches every piece through the dock.
|
|
398
|
+
|
|
399
|
+
| piece | one interface for | implementations |
|
|
400
|
+
| ------------ | ------------------------------------------ | ------------------------------------------------ |
|
|
401
|
+
| harbor core | partitions, directory, own doors, forward | one, on every terrain |
|
|
402
|
+
| reach | carrying bytes to a pk | request, socket |
|
|
403
|
+
| store | keeping partitions by seed | memory, disk, IndexedDB, edge storage |
|
|
404
|
+
| side | an avatar speaking to someone outside | screen, MCP server, runner, agent |
|
|
405
|
+
| proof | turning a credential into an invitation | one verifier, a daemon nonce, three kinds |
|
|
406
|
+
| envoy | a non-Quo surface as a being | none built: a name until its first user |
|
|
407
|
+
|
|
408
|
+
Two rules keep them general:
|
|
409
|
+
|
|
410
|
+
1. A piece exists only with two users. No interface is written for one
|
|
411
|
+
implementation; what one terrain alone needs stays inside that terrain.
|
|
412
|
+
2. Every interface has one suite, run against every implementation. A new
|
|
413
|
+
implementation is accepted when the shared suite passes untouched.
|
|
414
|
+
|
|
415
|
+
Harbor core, reach and store held across three terrains and moved into
|
|
416
|
+
`packages/quo/src` with `packages/quo/SPEC.md` in the same commit on 2026-09-04;
|
|
417
|
+
what stays here of them is each terrain's store, loader, lease and listener. The
|
|
418
|
+
other three are dock conventions and stay here.
|
|
419
|
+
|
|
420
|
+
## Invariants
|
|
421
|
+
|
|
422
|
+
1. An occupant holds one standing: its avatar's standing to the user being.
|
|
423
|
+
It never holds a standing at a third party.
|
|
424
|
+
2. An occupant sees keys, invitations, pks and partitions never. What
|
|
425
|
+
crosses a side is asks, args, answers and the three words.
|
|
426
|
+
3. The gate is the permission model. There is no second list.
|
|
427
|
+
4. Credentials live for one call and are never stored on a Quo side.
|
|
428
|
+
Revocation is remove.
|
|
429
|
+
5. The root is held by the device's own rule and no route of a world
|
|
430
|
+
exposes it: the ask pointer on a daemon's local socket, and on the edge,
|
|
431
|
+
where there is no local process, a platform secret. Every other owner is
|
|
432
|
+
an occupant of the ward, minted by the root alone.
|
|
433
|
+
6. The owner creates and places. The work goes through an avatar.
|
|
434
|
+
7. One avatar per client identity. Reconnect is not re-invite.
|
|
435
|
+
8. Silence is never retried by a side.
|
|
436
|
+
9. Envoys read secrets from the device, not from cells.
|
|
437
|
+
10. Nothing under `packages/dock/` imports a private path of `packages/quo/src`,
|
|
438
|
+
only the four package exports; nothing under `estates/` imports a path of
|
|
439
|
+
`packages/dock/` or of `packages/quo/src`, only the two packages by name.
|
|
440
|
+
11. Nothing here changes a harbor, a ward or a being.
|
|
441
|
+
12. An estate needs nothing the dock does not give it. Its folder, copied
|
|
442
|
+
into an empty repository with one install, boots.
|
|
443
|
+
|
|
444
|
+
## Where the dock stands
|
|
445
|
+
|
|
446
|
+
The one place under `packages/dock/` where a gap between these documents and the
|
|
447
|
+
folders is named. Each line is a debt to close, not a note to keep.
|
|
448
|
+
|
|
449
|
+
Two rules hold:
|
|
450
|
+
|
|
451
|
+
- **The ward and the being are asserted on the memory harbor, and every
|
|
452
|
+
harbor by the conformance suite.** The first keeps the network from
|
|
453
|
+
hiding a fault in the words: the memory harbor records its wire and
|
|
454
|
+
stands in for weather, so a door test that fails there fails at the door.
|
|
455
|
+
The second is how a harbor on any terrain is accepted, untouched, and not
|
|
456
|
+
before. Neither binds an adopter; they bind this bench.
|
|
457
|
+
- **One language, TypeScript, until 1.0.0.** A second kit is a second thing to
|
|
458
|
+
keep in step with every change, and the vectors under `packages/quo/vectors/`
|
|
459
|
+
are the hand that will be extended when the time comes.
|
|
460
|
+
|
|
461
|
+
The order of work, each step usable on its own and each proving a sentence
|
|
462
|
+
above or sending us back to fix it:
|
|
463
|
+
|
|
464
|
+
1. Done. `packages/dock/` scaffold: its own package linking the library, the
|
|
465
|
+
four exports only, `check:dock` in the root gate, the terrain test pointed at
|
|
466
|
+
`packages/dock/beings`. The disk harbor in `packages/dock/harbor/disk.ts`:
|
|
467
|
+
one folder per ward holding seed, partition and the class source, a ward
|
|
468
|
+
record, the lease, and a save after every call. The `quo` CLI: init, serve,
|
|
469
|
+
census, boot, invite, knock, over the daemon's unix socket. Pilot and side
|
|
470
|
+
landed at steps 4 and 5.
|
|
471
|
+
2. Done. The beings in `packages/dock/beings/`: `User`, `Desk`, `Avatar`, proven
|
|
472
|
+
on the memory harbor in `packages/dock/test/beings.test.ts`. A fake proof
|
|
473
|
+
becomes an invitation the user being minted, the avatar knocks and takes
|
|
474
|
+
her, and her tool list equals the user being's describe for her;
|
|
475
|
+
reconnect mints nothing; two clients see two tool lists; a push is a
|
|
476
|
+
reverse ask that reaches the side; remove is revocation. The ids that
|
|
477
|
+
carry the conventions: the desk is the occupant the root named `desk`
|
|
478
|
+
at the user being; the desk holds each user being as `user:<name>`; the
|
|
479
|
+
user being holds each device's way back as `to:<client>`; the avatar
|
|
480
|
+
holds the user being as `user` and is pushed to as `user:push`, two ids
|
|
481
|
+
because standings and occupants share one namespace.
|
|
482
|
+
3. Done. The side in `packages/dock/beings/side.ts`: a function of the avatar
|
|
483
|
+
that runs until closed, and `word`, which tells the three words and the
|
|
484
|
+
object apart before any side renders them. The MCP server in
|
|
485
|
+
`packages/dock/mcp/server.ts`, proven over the SDK's in-memory transport in
|
|
486
|
+
`packages/dock/test/mcp.test.ts`: tools/list is her describe spoken as tools,
|
|
487
|
+
tools/call is a named ask, an object is a result, an error object and
|
|
488
|
+
the two words are error results with the text the trunk gives them, a
|
|
489
|
+
push is a logging notification, and a session closing and opening
|
|
490
|
+
reuses the standing. The SDK is the dock's first dependency, under
|
|
491
|
+
`packages/dock/` alone.
|
|
492
|
+
4. Done. `quo side --as NAME` over stdio, proven in
|
|
493
|
+
`packages/dock/test/cli.test.ts` with the SDK's stdio client as a child
|
|
494
|
+
process: the daemon finds or boots
|
|
495
|
+
`avatar:NAME`, enters her with a nonce the desk honours once, and runs
|
|
496
|
+
the model side beside her; the tool list is the user being's describe
|
|
497
|
+
for that client; a second start is a reconnect and mints nothing; a
|
|
498
|
+
`local` proof from anywhere else is refused. `quo init` now does the
|
|
499
|
+
root's setup, the desk public and one user being named by `--user`, so
|
|
500
|
+
a fresh folder is a world. Claude Code and Claude Desktop on the Mac
|
|
501
|
+
need only `quo serve` running and `quo side --as claude` as the server
|
|
502
|
+
command: no droplet, no OAuth.
|
|
503
|
+
5. Done. `quo pilot` in `packages/dock/mcp/pilot.ts`, proven in
|
|
504
|
+
`packages/dock/test/cli.test.ts` with the SDK's stdio client as a child
|
|
505
|
+
process: the owner's asks as tools and no more, census, boot, invite,
|
|
506
|
+
knock and, since step 16, remove, each
|
|
507
|
+
one an owner ask on the daemon's root socket, logged to stderr with
|
|
508
|
+
what it made. It is the root and not an avatar: nothing is booted for
|
|
509
|
+
it and no occupant is minted for it. With no daemon it says so and
|
|
510
|
+
exits. Claude Code as the owner is `claude mcp add` with
|
|
511
|
+
`quo pilot` as the command.
|
|
512
|
+
6. Done. `quo serve --http PORT`: the HTTP door on loopback, `/health`
|
|
513
|
+
naming the wards, routes mounting by path so a hostname on the proxy is
|
|
514
|
+
a path on the daemon; proven in `packages/dock/test/cli.test.ts`. The systemd
|
|
515
|
+
unit and the Caddyfile are in `estates/lab/droplet/`. Disk store, the
|
|
516
|
+
lease and reboot from disk with relations intact were steps 1 and 4.
|
|
517
|
+
7. Done. OAuth on the `mcp.` route in `packages/dock/mcp/oauth.ts`, mounted by
|
|
518
|
+
the daemon when `<dir>/routes.json` names the two public origins, and
|
|
519
|
+
proven over real HTTP in `packages/dock/test/oauth.test.ts`: metadata,
|
|
520
|
+
protected-resource metadata, dynamic registration, PKCE with S256, the
|
|
521
|
+
code grant, refresh with rotation, opaque tokens mapping a bearer to a
|
|
522
|
+
client identity, revoke by identity, and expiry. The conventions pinned
|
|
523
|
+
here: a pending request and a code live ten minutes, an access token
|
|
524
|
+
one hour, a refresh token thirty days; a code is spent the first time
|
|
525
|
+
it is offered, right or wrong; the client identity is chosen at the
|
|
526
|
+
allow page, not taken from the client's registration, because a client
|
|
527
|
+
like claude.ai registers a fresh client id on every connect and the
|
|
528
|
+
avatar must outlive that. The store is `<dir>/oauth.json`, the route's
|
|
529
|
+
own, mode 0600, and holds no secret of Quo's.
|
|
530
|
+
8. Done. The exchange pages in `packages/dock/mcp/web/exchange.ts`, mounted on
|
|
531
|
+
the web route, proven over real HTTP in `packages/dock/test/web.test.ts`.
|
|
532
|
+
Login checks `QUO_OWNER_PASSWORD` in constant time and sets a signed
|
|
533
|
+
session cookie that lives ten minutes, the life of a request; with no
|
|
534
|
+
password set the exchange is closed. Allow names the client, where it
|
|
535
|
+
returns to, and the identity it will be, suggested from the client's
|
|
536
|
+
name and editable, one word and not the user or the desk. Allow admits
|
|
537
|
+
her through the one path every side uses: find or boot the avatar,
|
|
538
|
+
enter with a nonce the desk honours once under the `web` proof kind,
|
|
539
|
+
then complete the OAuth request with that identity. Deny sends the
|
|
540
|
+
client `access_denied`. Two pages, hand-written, rendering no blueprint.
|
|
541
|
+
9. Done. The MCP endpoint in `packages/dock/mcp/http.ts` at `/mcp` on the mcp
|
|
542
|
+
route: streamable HTTP, a bearer names the identity, the identity names
|
|
543
|
+
her avatar through the same admit path, the side from step 3 runs
|
|
544
|
+
beside her, one session per connection, a session belonging to the
|
|
545
|
+
identity that opened it. Proven in `packages/dock/test/http.test.ts` with the
|
|
546
|
+
SDK's streamable HTTP client over the whole exchange. MCP is complete:
|
|
547
|
+
every human-assisted case on every device, with nothing of Quo's
|
|
548
|
+
crossing a machine.
|
|
549
|
+
10. Done. The runner in `packages/dock/mcp/runner.ts`: the second side, an MCP
|
|
550
|
+
client written inline for a model that speaks function calling. Her
|
|
551
|
+
describe is a tools array, a tool call is a named ask, the three words
|
|
552
|
+
are tool messages, a line from the human or a push from the user being
|
|
553
|
+
starts a turn, and turns never overlap. Proven in
|
|
554
|
+
`packages/dock/test/runner.test.ts` over a scripted endpoint on loopback, and
|
|
555
|
+
live against Qwen3 Coder 30B in LM Studio on the Mac, which read her
|
|
556
|
+
describe, called `whoami` through the gate and answered with the id she
|
|
557
|
+
minted. What it taught: LM Studio refuses a parameters schema with no
|
|
558
|
+
`properties`, so the runner is where a describe is narrowed for an
|
|
559
|
+
endpoint, and nowhere else.
|
|
560
|
+
11. Done. The agent side in `packages/dock/mcp/agent.ts`: the world is the loop.
|
|
561
|
+
A push from the user being is acknowledged at once by her `notify`,
|
|
562
|
+
lands in her inbox, which is the queue in her cells, and the side runs
|
|
563
|
+
it, one event at a time in order, then asks the user being back with
|
|
564
|
+
`report({ event, result })`, the ask this step added to her, gated to
|
|
565
|
+
devices. A run is a function of the event or a process in the agent's
|
|
566
|
+
folder with the event as its last argument, which is what `claude -p`
|
|
567
|
+
is. Proven in `packages/dock/test/agent.test.ts` with a fake run and a fake
|
|
568
|
+
process: the ask is answered before the run ends, a throw reports an
|
|
569
|
+
error object, and events that came while no side was up run when one
|
|
570
|
+
comes up. What it decided: the queue lives in the partition and not in
|
|
571
|
+
the side, so a restart loses nothing but the one run in flight. On a
|
|
572
|
+
device, `<dir>/agents.json` names each agent's identity, command and
|
|
573
|
+
folder, and the daemon admits her on the local proof and runs her side
|
|
574
|
+
beside her avatar; proven in the same suite over a disk harbor.
|
|
575
|
+
12. The `quo.` route: Done. The reach interface with request and socket, since
|
|
576
|
+
the library move `packages/quo/src/harbor/reach.ts`, the disk harbor holds
|
|
577
|
+
the directory, and the daemon mounts `/quo` and dials with `--dial`. The
|
|
578
|
+
library's conformance suite passed untouched over two disk harbors on
|
|
579
|
+
loopback under both reaches, and the rendezvous carried a knock from a third
|
|
580
|
+
harbor to a dialer through its listener; `packages/dock/test/wire.test.ts`.
|
|
581
|
+
Live: a Mac daemon dialed `quo.lab.quo.systems`, an avatar there knocked at
|
|
582
|
+
the lab's user being across the internet, the lab knocked back over the held
|
|
583
|
+
socket and took `to:mac`, and a push from the lab landed in her inbox on the
|
|
584
|
+
Mac. What it taught: the proxy rewrites the route root with a trailing
|
|
585
|
+
slash, and a ward pk is 64 bytes on the wire;
|
|
586
|
+
`packages/dock/harbor/quo-harbor.md` has both.
|
|
587
|
+
13. The browser harbor: Done. Harbor core carved out of the disk harbor
|
|
588
|
+
into a core of its own, since the library move `packages/quo/src/harbor/core.ts`,
|
|
589
|
+
the store a piece with files and IndexedDB under it, the dialer its
|
|
590
|
+
own terrain-free piece, the socket reach on the standard surface.
|
|
591
|
+
`packages/dock/harbor/browser.ts` is the core in a tab: IndexedDB, a web lock
|
|
592
|
+
for the lease, one socket per world.
|
|
593
|
+
The library's conformance suite passed untouched inside a real
|
|
594
|
+
Chromium against two browser harbors in one tab through a daemon on
|
|
595
|
+
loopback, migration between two databases included;
|
|
596
|
+
`packages/dock/test/terrain/browser.test.ts`, behind `check:terrain`. And the
|
|
597
|
+
first screen, `packages/dock/human/tab.ts`, rudimentary on purpose: a page on
|
|
598
|
+
the web route that boots a harbor in the tab, takes the owner password
|
|
599
|
+
once under the `tab` proof kind, and renders her describe as buttons,
|
|
600
|
+
with pushes landing on the page; a reload asks nothing. What it taught:
|
|
601
|
+
a tab's store keeps values through JSON because the cells guard refuses
|
|
602
|
+
structured clone; a side in a tab saves after the exchange and after
|
|
603
|
+
every call, as the daemon does; and a dialed socket is the fallback
|
|
604
|
+
from the moment it is dialed, because a ward asks the instant it boots.
|
|
605
|
+
14. Owners at the door in the CLI: Done. The root socket takes `via`, a
|
|
606
|
+
standing the user being holds at another ward, and the daemon asks on
|
|
607
|
+
it in-process and saves; `quo pilot` and the bare owner asks take
|
|
608
|
+
`--via S`. Scene 8 on two daemons over a dialed socket in
|
|
609
|
+
`packages/dock/test/cli.test.ts`: the far root invites on its ward's pk, the
|
|
610
|
+
user being here knocks and takes `lab`, census and boot land there,
|
|
611
|
+
invite on the far pk is refused at the door, the standing survives a
|
|
612
|
+
restart, and the owner removed meets silence. What it taught: the
|
|
613
|
+
library had no owner ask that removes an owner, and the test reached
|
|
614
|
+
into the ward's cells; the word is `remove` now, decided in `packages/quo/SPEC.md`
|
|
615
|
+
at step 16.
|
|
616
|
+
15. The human side, minimal: Done. Three pieces under `packages/dock/human/`:
|
|
617
|
+
`html.ts`, pure, a schema as a form, a form back as typed arguments,
|
|
618
|
+
an answer as a view, the three words with faces; `screen.ts`, the side
|
|
619
|
+
over a surface that can only show a page and hand back a form,
|
|
620
|
+
re-asking her describe after every call so the page follows the
|
|
621
|
+
digest; `dom.ts`, the surface on an element. The tab keeps its harbor
|
|
622
|
+
and exchange and hands the avatar to the side. Proven on the memory
|
|
623
|
+
harbor with a fake surface in `packages/dock/test/human.test.ts`, and in
|
|
624
|
+
Chromium behind `check:terrain`. Minimal on purpose: design, a
|
|
625
|
+
switcher, the guest's page and the native app are left to the human
|
|
626
|
+
document's own sitting, and none of them blocks a world from having
|
|
627
|
+
a screen.
|
|
628
|
+
16. Removing: Done. `packages/quo/SPEC.md` gave the owner its fourth ask, `remove`,
|
|
629
|
+
the mirror of knock: a relation out of a being by id, occupant or
|
|
630
|
+
standing, and on the ward's own pk an owner, by the root alone. In
|
|
631
|
+
`packages/quo/src/ward/owner.ts` with its test; the pilot's fourth tool; `quo
|
|
632
|
+
remove` from the shell, the same word; the step 14 test asks it
|
|
633
|
+
instead of reaching into the cells. The lab's leftovers went with it,
|
|
634
|
+
recorded in `estates/lab/lab.md`.
|
|
635
|
+
17. What the lab wants: Done. A launchd agent beside the systemd unit in
|
|
636
|
+
`estates/lab/droplet/`, the daemon as the user forever with
|
|
637
|
+
`~/.quo/dial.json` naming the routes it holds a socket to, installed
|
|
638
|
+
on the operator's Mac against the lab. And `quo run`: the runner from
|
|
639
|
+
a terminal, the same pipe as `quo side` with a model named in the
|
|
640
|
+
hello, the daemon running the runner beside the avatar, a line in a
|
|
641
|
+
turn and the final text a line out, proven with a scripted endpoint
|
|
642
|
+
as a child process in `packages/dock/test/cli.test.ts`. The gate profile per
|
|
643
|
+
client identity the road lists is defined nowhere and was not built.
|
|
644
|
+
18. The edge terrain: Done. `packages/dock/harbor/edge/`, the core over a Durable
|
|
645
|
+
Object: its storage the store with the seed sealed under a platform
|
|
646
|
+
secret, the deployed worker the code, the object the lease; reached by
|
|
647
|
+
request, holding dialers' sockets, the root a route under a platform
|
|
648
|
+
secret. The conformance suite passed untouched inside the platform's
|
|
649
|
+
runtime, behind `check:terrain`; deployed to the lab's account and
|
|
650
|
+
piloted from the Mac over a standing, `--via edge`. The third terrain
|
|
651
|
+
the library move waited for; the `ws` question answered in the harbor
|
|
652
|
+
document. `estates/lab/lab.md` keeps the record, one slip included.
|
|
653
|
+
|
|
654
|
+
19. The split, in flight: the estate folder became the dock, the lab's own
|
|
655
|
+
things moved to `estates/lab/`, its units and its document, and
|
|
656
|
+
the dock's package took its name. Then the repository took the shape
|
|
657
|
+
that says what ships by where it lives: `packages/quo/` and
|
|
658
|
+
`packages/dock/` are the two published packages, `estates/` is private,
|
|
659
|
+
and the root is nobody's package, the workspaces and the gate. The lab
|
|
660
|
+
redeployed from the new paths and a copy of `estates/lab/` booting in
|
|
661
|
+
an empty repository are what close it.
|
|
662
|
+
20. The dock published: Done. `@quo-systems/dock` 0.1.0, the same shape
|
|
663
|
+
the library took, an emitted `dist/` with the `quo` command pointing
|
|
664
|
+
into it, the source and the four documents beside it, and
|
|
665
|
+
`packages/dock/test/package.test.ts` as the one suite that meets it as
|
|
666
|
+
an adopter: the library's tarball and this one installed into an empty
|
|
667
|
+
folder with nothing but Node, then `quo init`, a daemon, and
|
|
668
|
+
`quo census` answering with the desk and the user being. The library
|
|
669
|
+
went to 0.2.0 first, since the door's words moved the wire. What it
|
|
670
|
+
decided: the daemon bundles the tab from beside itself, emitted or
|
|
671
|
+
source, whichever is there, the one place the dock reads a file by
|
|
672
|
+
path at run time.
|
|
673
|
+
|
|
674
|
+
Steps 1 to 18 and 20 are in the tree and on the lab, and MCP is complete;
|
|
675
|
+
step 19 is in flight, and it is the one gap named today. `next.md` is where
|
|
676
|
+
the next sitting starts.
|
|
677
|
+
|
|
678
|
+
## Glossary
|
|
679
|
+
|
|
680
|
+
- **avatar**: a being that is someone's voice from outside Quo.
|
|
681
|
+
- **client identity**: what a credential exchange establishes; one avatar.
|
|
682
|
+
- **envoy**: a being whose methods call a non-Quo thing.
|
|
683
|
+
- **dock**: what every estate needs and nobody writes twice, `packages/dock/`,
|
|
684
|
+
published as `@quo-systems/dock`.
|
|
685
|
+
- **estate**: all of one owner's harbors, with what is theirs alone, one
|
|
686
|
+
folder under `estates/`, never published. Also the agent under cron that
|
|
687
|
+
holds the owner pilot for one.
|
|
688
|
+
- **front desk**: the being every fresh client meets; hands out invitations
|
|
689
|
+
minted by user beings.
|
|
690
|
+
- **gate**: `for(occupant, asker)`; the whole permission model.
|
|
691
|
+
- **owner pilot**: `quo pilot`, the four owner asks over stdio, reaching
|
|
692
|
+
the daemon's socket; with `--via`, a ward elsewhere through a standing.
|
|
693
|
+
- **daemon**: `quo serve`, the one process on a device that holds a harbor.
|
|
694
|
+
- **proof**: what a route produces after authenticating; the front desk
|
|
695
|
+
trades it for an invitation.
|
|
696
|
+
- **route**: a hostname a reverse proxy sends to one process.
|
|
697
|
+
- **side**: the interface an avatar speaks through to someone outside Quo.
|
|
698
|
+
- **user being**: one per human, 24/7, holding all of the human's standings.
|