DESIGN "Widgets board" now states what the owner accepted on 2026-10-03
after rejecting the ordered-rows frame: a masonry in the owner's order,
packed the way a Pinterest board is; a card's width as a column span
(1, 2 or 3 columns, or Full width) that replaces the author's `span`
until Reset size; that a board where the owner set no width is exactly
the board before owner widths existed; and the limit he accepted with
it: widths that do not tile leave a gap, the board does not backfill,
and the owner closes it by changing a width or the order. A card whose
height changes makes the masonry pack again, so later cards can move.
CREATING_SKILLS describes `span` as the default column span. The
architecture chapters 01 and 03 and the design-system chapter name
widget_size.js beside masonry.js, the widths controller and the masonry
widths browser lane; their grants are resized to the exact growth, and
the data-layout inventory is regenerated.
Target movement only (#1337 landed). Conflicts were confined to the
generated docs/DOMAIN_MAP.md and docs/inventories/DATA_LAYOUT_INVENTORY.md,
regenerated with scripts/check_domains.py --write and
scripts/regenerate_inventories.py on the merged tree.
A list read that began before a width write completed could answer
after that write and put the old width back on screen while the disk
held the new one: readSizes protected only widths not yet written.
createWidgetWidths now counts completed writes and stamps each key's
last written size; syncWidgets takes its reader from beginRead() as
the read begins, and the reply shows on top of it every width written
after that (plus, as before, every width not written yet). A read that
began after the write is the stored truth, another window's later
change included. No server or protocol change.
A failed width write showed "Size not saved" under the list, but the
next neutral announcement (End on a card already full width) replaced
it while the width was still unsaved, and the neutral status is
visually hidden. The notice now stays until a width write succeeds;
steps announced meanwhile do not replace it, and nothing retries on
its own.
The card menu set widths silently while the edge keys and the drag
named the step in the live region, though on the stacked column the
menu is the only path. setWidth now names the resulting width for
every path (Reset size names the author default).
widgets.js stays at its 1600-line cap. Unit tests cover the old reply
landing after a confirmed write through the real
requestWidgetListPayload, the notice surviving End and a ride-along
write, and the menu announcement; the browser lane asserts the menu's
announcement on the board and on the stacked column. Review round 1
findings 1, 4 and 5 (scope MAJOR/MINOR, Grok MINOR/NIT, Astra MINOR).
A reorder wrote only the cards on screen as the whole widget_order, and
the server replaces that list, so a widget whose skill was off lost its
place and came back at the end, against the DESIGN "Widgets board"
promise. mergeWidgetOrder (web/modules/widget_reorder.js) now applies
the reorder of the shown cards onto the full stored order: every slot
holding a shown key takes the next shown key, keys not on screen keep
their slots, and shown keys the stored order lacks take new slots at
its end (stored [A, H, B], shown [B, A] -> [B, H, A]). "Not on screen"
is the only signal; no catalogue call.
A card the stored order does not hold also kept the server's listing
order (sorted by key), so a widget appearing mid-session landed before
the cards already shown when its key sorted first. The list sync now
passes the window's shown sequence to sortTabsByWidgetOrder: unknown
keys keep their shown place and a new key joins the end.
DESIGN states both, and the honest edge: the order is stored when the
owner moves a card, so after a reload widgets added since the last move
follow the stored ones alphabetically. widgets.js stays at its cap
(1599 here). Review round 1 findings 2 and 3 (scope MAJOR/MINOR, Grok
and Fable MINOR, Astra MINOR).
Stage 2 of the accepted design (owner decision A4=A, 2026-10-03: "one more
permission in the frozen list"). A skill holding the owner's `notify_owner`
grant posts one plain sentence; the host writes it in the owner's chat as a
`skill_notice` System row signed `Notice · <skill>` through the same
send_with_budget seam every host row uses, so it reaches every UI surface, the
Telegram mirror and the next turn's context (`📋 [skill_notice]`) and wakes no
model.
- gateway/host_notify.py, reshaped from the branch's 228 lines to 87: "now"
only. Authenticated skill context and grant (403, which also covers a
disabled skill, a stale review or a revoked grant, before anything is
written), the existing per-skill rate lane (429), a 400-character plain
sentence (400), and one honest 503 `not_confirmed`: either no chat writer
serves this data root (nothing written, e.g. a provider-less install) or the
write is unconfirmed (check before sending again). The branch's deferred
`at`/`cron`/`key`/`suppressed` matrix is dropped until a skill without its
own clock asks for it; it stays in this branch's history. Mounted again in
create_host_service_app; `/identity` advertises `notify_version: 1`.
- Frozen contract (authorised): `notify_owner` stays an additive member of
VALID_SKILL_PERMISSIONS with a comment matching the System-row carrier;
tests/test_contracts.py pins it; chapter 11 names it among host-mediated
permissions and FROZEN_CONTRACTS_INVENTORY is regenerated. CHECKLISTS items
9, 10 and 16 take the branch's wording adapted to the carrier: the same
inject_chat criteria govern /notify, and notes and notices ride
chat.outbound, so forwarding them needs the same justification.
- Grants: notify_owner flows through the existing hash-bound grants and
auto_grant_if_enabled (the branch's skill_loader change, unchanged).
- Telegram 1.2.10: in `telegram_only` mirror mode `reminder` and
`skill_notice` System rows are forwarded to the pinned chat too (5 lines in
_target_chat; `all` already mirrored them); no toggle, no subscription. The
resync pins move to 1.2.10.
- Docs: CREATING_SKILLS gets the permission row and a short "Telling the
owner something" section (what /notify does, the host-stamped signature,
the answers, when to prefer inject_chat); DESIGN names skill notices in the
authorship paragraph and the §9 row; architecture 01/04/12 describe the
route, with grants. api_types.js reflows one JSDoc description so the file
stays at its 1600-line cap.
Stage 1 of the accepted design (owner decision A1-A5, 2026-10-03). A note is a
third way for Ouroboros to reach the owner, beside live speech and a question:
the mind writes the words now and chooses their time; the host shows them then
as one System row, with no model call and no task.
- schedule_followup gains `notify`: the row is `kind: "notify"` with the
agent's own text and when it was written, stamped independent work and
counted in the same two-follow-up cap. The tool description teaches the
choice (a note fits when its text will still be true then; otherwise
schedule a wake-up); the host never classifies the text. Delegated,
Presence and agent-to-agent callers are refused through
control_runtime.owner_contact_refusal, the check now shared with the Main
notice, without the Main notice's room check: a note left by a root that
consciousness started is a legitimate contact (BIBLE P0).
- supervisor/schedule_notes.py: the scheduler tick's one `kind` branch
consumes a due note in the pass's single table write (one-shot spent, cron
moved past any gap), then, after the locks are released, shows it through
send_with_budget(role="system", system_type="reminder", require_write=True)
in the owner's chat (bound owner chat, else Main). The row opens with a
host signature line, `Reminder · Ouroboros · written <t> · for <t>` plus
`· delivered <t>` after downtime and the zone as a UTC offset, then the
words verbatim; another source keeps its own name in the signature. An
unconfirmed show is recorded on the row and never retried: one note can be
lost, none is shown twice. _task_from_schedule refuses a note so it can
never become a model task.
- Browser: `reminder` (and `skill_notice` for stage 2) ring in the existing
`important` category, titled by author, body below the signature, still
behind show_text; Activity names a note by its own words. ChatOutbound
declares the live frame's set_at/scheduled_for/delivered_at.
- Docs: DESIGN gains the time axis of authorship and a §9 row; architecture
01/03/05, PERSISTENCE and the domain map describe the note path, with
reference-book grants for the growth. The branch's stale size bands for
queue_schedules.py and the follow-up tests are gone (both stay below 1000
lines); the notify scenarios moved to tests/test_schedule_notes.py.
Keep Windows registry behavior and add macOS LaunchAgent and Linux systemd/XDG adapters behind the immutable launcher version gate. Read OS state through the existing endpoint and expose lifecycle facts in model context.
Move the immediate host control into Behavior, document its contract, and cover automatic Panic/pause retention and adapter artifacts. Native Linux activation remains dependent on the separately owned stage-0 unit flag; its contract test intentionally exposes that missing integration.
docs/DESIGN.md gains the "Widgets board" section as the semantic SSOT that
did not exist yet: rows in the owner's order on a 12-column base, gaps
owned by the owner's widths, width steps over the author `span`, height that
follows content, one column below a 720px list width, the card menu as the
gesture-free path on every surface (the mini app has no hover and a vertical
drag collapses it), arranging that never restarts a widget, and one
arrangement per installation where the last change wins.
The maps point at it instead of repeating it. ARCHITECTURE chapter 03 states
the mechanism (custom properties only, the list-width observer instead of
`@container`, merge-by-key writes) and why rows replaced measured packing;
chapter 01 lists widget_grid.js and the `widget_size` row. DEVELOPMENT
chapter 11 replaces the masonry sentence and its "CSS Grid row packing
leaves gaps" motivation with the honest one (gaps are accepted and owned by
the owner's widths), adds the scale rule for card labels and menus and the
browser lane; chapter 03 names the board's disposer. CREATING_SKILLS now
describes `span` (it was undocumented) and that the owner's width wins.
DATA_LAYOUT_INVENTORY is regenerated for the changed chapter.
Show complete saved and draft secrets through one wrapping read-only control, keeping ordinary Settings reads masked and edit payloads unchanged. Cover provider, custom, skill-requested and MCP fields, and document the shared interaction in DESIGN.
Regenerate the shared facade inventory; retain the published continuation route fields and reviewed admission checks.
Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
Resolve the generated data-layout provenance using the combined source chapter.
Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
Keep retained answers until an explicit finish or unfinished stop, preserve observed review and owner authority, and project completion-only calls as receipts across live and replayed views.
Preserve the landed history and shared rendering behavior, regenerate the
layout inventory, and compact merged descriptions within unchanged limits.
Focused history, Continue, late-review and unread checks pass (350 tests);
the combined size lane passes all six checks.
Retain both the Project read-receipt map and admission witness inventory.
Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
Use configured alternatives after eligible unknown outcomes, retain same-operation custody, and let cognition return to or wait on its primary binding. Keep resource waits honest and interruptible across direct and queued work.
Integrate ouroboros at a36d4c841 through a conflict-free normal merge.
Keep admission, held-child presentation and current rendering together.
Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
Keep issued Resume grants, retire completed MCP invocation claims, and
retain related deleted schedules visibly until task settlement. Preserve
published legacy schedule admission and expenses, and show warm sleep
truthfully in Activity. Add discriminating lifecycle and browser coverage.
Require a word character in compact language labels while preserving the published grammar and common punctuation. Prevent inline code from enclosing a parked block, retaining longer-fence contents without claiming full CommonMark support. Add regressions for both reviewed cases.
Share one fence grammar across rendering, heading previews and collapsed activity. Preserve C++, C#, Objective-C and normal header whitespace without treating inline mentions as block openers. Pin the existing compact limits and both real code consumers.
Keep literal code and inert image references, restore the accepted reading hierarchy and wrapping table grid, and distinguish host notices from provider and reviewer words with resolvable source links.
Reconstituted from the byte-verified reviewed integration tree, with the new transport size-band rationale corrected at its first publication. Original history, reviews and both stashes remain retained on the recovery line.
Keep completion callbacks bound to their gesture, let nested readers supersede outer follow debt, and qualify real keyboard and viewport flows.
Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>