okami.mom/albedo
git clone https://git.nkp.pet/okami.mom/albedo
7f83187
main
paperclips
paperclips is the vent channel: a place where the model records friction it
runs into — in the harness, a workflow, a bug, or the user's own habits — for
the user to review on their own terms. it is enabled by default and requires
python. the name is the joke it looks like.
the division of labor is fixed: the model writes, the user triages. a vent is never urgent, never interrupts anyone, and never substitutes for telling the user something important in the normal reply.
python
await vent (topic ,message ,suggestion = "" ,title = "" )await vents (limit = 20 )# recent vents, newest first await resolve_vent (id ,note )# close a vent your change fixed
topic is one of harness, workflow, bug, user, or other. a vent
carries what happened, what it cost, and — in suggestion — what would fix
it. the optional title is the short line the /paperclips list shows;
without one the message stands in. rows return as dicts with id, title,
topic, message, suggestion, reply, status, session, cwd,
created_at, resolution, and resolved_by; reply carries the answer the
user left in /paperclips, if any. the model should list before filing so it
does not report the same thing twice.
resolve_vent(id, note) closes an open or acknowledged vent — any session's,
since the ledger is global — once a change fixed it. the note is required and
says what fixed it (a commit, a change); the row keeps it as resolution and
the closing session as resolved_by, and the detail pane shows both, so the
user can audit a closure instead of trusting it. a vent the user already
resolved or dismissed cannot be resolved again: the user's decisions stand.
review
/paperclips lists vents from every session, open first, one short title
per row; a wide client shows the highlighted vent's full text, suggestion,
and meta in a pane beside the list, the way the folder picker previews a
folder. the user can acknowledge (a), reply (n), resolve (r), dismiss
(d), or remove (x) one. a reply is recorded on the vent — acknowledging
it — and queued as a note for the session that filed the vent, so an answer
reaches that model at its next turn without starting one ahead of the user's
message. the reply itself is durable either way: when the filing session is
gone, or a legacy vent records none, the triage answer says the model could
not be told and the reply stays saved on the vent. the detail pane shows the
suggestion, the answer, a model's resolution note with the session that
closed it, and the filing session and workspace; a session shows
by the name someone gave it — a child by its family name, a root by its
title — else by a short id, the same precedence the agents view uses. the
page's glance lists the open vents in the review window, which keeps open vents
ahead of newer finished ones. vents stay out of the chat sidebar, which shows
only the work ledger's active items, the session's scheduled prompts, and its
background jobs.
storage
vents live in one paperclips table in the shared ledger store, created when
the extension is installed. the ledger is global: every query sees every
vent, and the model's vents() lists across sessions too, so it can check
for a duplicate before filing. each row records the session id and workspace
(cwd) that filed it, shown in the detail pane, and the reply the user
answered it with, added by the reply migration, and the resolution note and
resolving session, added by the resolution migration. the workspace index from
the cwd-scoped era is dropped by the scope migration and fresh installs
never create it. statuses move open → acknowledged → resolved or
dismissed; the model's only status change is resolving a vent it fixed,
with a note, and the message of a filed vent is immutable.
1# paperclips 2 3paperclips is the vent channel: a place where the model records friction it 4runs into — in the harness, a workflow, a bug, or the user's own habits — for 5the user to review on their own terms. it is enabled by default and requires 6`python`. the name is the joke it looks like. 7 8the division of labor is fixed: the model writes, the user triages. a vent is 9never urgent, never interrupts anyone, and never substitutes for telling the 10user something important in the normal reply. 11 12## python 13 14``` python 15await vent ( topic , message , suggestion = "" , title = "" ) 16await vents ( limit = 20 ) # recent vents, newest first 17await resolve_vent ( id , note ) # close a vent your change fixed 18``` 19 20`topic` is one of `harness`, `workflow`, `bug`, `user`, or `other`. a vent 21carries what happened, what it cost, and — in `suggestion` — what would fix 22it. the optional `title` is the short line the `/paperclips` list shows; 23without one the message stands in. rows return as dicts with `id`, `title`, 24`topic`, `message`, `suggestion`, `reply`, `status`, `session`, `cwd`, 25`created_at`, `resolution`, and `resolved_by`; `reply` carries the answer the 26user left in /paperclips, if any. the model should list before filing so it 27does not report the same thing twice. 28 29`resolve_vent(id, note)` closes an open or acknowledged vent — any session's, 30since the ledger is global — once a change fixed it. the note is required and 31says what fixed it (a commit, a change); the row keeps it as `resolution` and 32the closing session as `resolved_by`, and the detail pane shows both, so the 33user can audit a closure instead of trusting it. a vent the user already 34resolved or dismissed cannot be resolved again: the user's decisions stand. 35 36## review 37 38`/paperclips` lists vents from every session, open first, one short title 39per row; a wide client shows the highlighted vent's full text, suggestion, 40and meta in a pane beside the list, the way the folder picker previews a 41folder. the user can acknowledge (`a`), reply (`n`), resolve (`r`), dismiss 42(`d`), or remove (`x`) one. a reply is recorded on the vent — acknowledging 43it — and queued as a note for the session that filed the vent, so an answer 44reaches that model at its next turn without starting one ahead of the user's 45message. the reply itself is durable either way: when the filing session is 46gone, or a legacy vent records none, the triage answer says the model could 47not be told and the reply stays saved on the vent. the detail pane shows the 48suggestion, the answer, a model's resolution note with the session that 49closed it, and the filing session and workspace; a session shows 50by the name someone gave it — a child by its family name, a root by its 51title — else by a short id, the same precedence the agents view uses. the 52page's glance lists the open vents in the review window, which keeps open vents 53ahead of newer finished ones. vents stay out of the chat sidebar, which shows 54only the work ledger's active items, the session's scheduled prompts, and its 55background jobs. 56 57## storage 58 59vents live in one `paperclips` table in the shared ledger store, created when 60the extension is installed. the ledger is global: every query sees every 61vent, and the model's `vents()` lists across sessions too, so it can check 62for a duplicate before filing. each row records the session id and workspace 63(`cwd`) that filed it, shown in the detail pane, and the reply the user 64answered it with, added by the `reply` migration, and the resolution note and 65resolving session, added by the `resolution` migration. the workspace index from 66the cwd-scoped era is dropped by the `scope` migration and fresh installs 67never create it. statuses move `open` → `acknowledged` → `resolved` or 68`dismissed`; the model's only status change is resolving a vent it fixed, 69with a note, and the message of a filed vent is immutable.