commits on main
← newer commits2026-10-02
b446d40f Aly Raffauf fix(daemon): keep startup on the clock
fix(daemon): keep startup on the clock
Share the caller deadline across discovery, startup, replacement, and shutdown.
ecc84659 Aly Raffauf test(skills): exercise linked skills and reloads
test(skills): exercise linked skills and reloads
Give external links, resource paths, and changed selections a spin through the real daemon.
c202a655 Aly Raffauf feat(skills): welcome symlinked installations
feat(skills): welcome symlinked installations
Follow external links, keep installed resource paths, and reload when selected targets change.
b63af2d8 Aly Raffauf test(skills): retire symlink escape expectations
test(skills): retire symlink escape expectations
Ordinary package links deserve a warmer welcome.
25785a55 Aly Raffauf docs(catalog): explain discovery and stale saves
docs(catalog): explain discovery and stale saves
Describe fresh catalog rows, inherited choices, and revision checks. Keep prepared context and discovery clearly separate.
0c99a3f9 Aly Raffauf feat(tui): show the daemon capability catalog
feat(tui): show the daemon capability catalog
Keep source rows distinct and refresh stale choices without replaying saves. Drop the spare workspace and draft state.
0a8145a3 Aly Raffauf feat(catalog): let the daemon own discovery
feat(catalog): let the daemon own discovery
Show every skill and instruction candidate, and guard saves with fresh revisions. Share preference resolution and bounded file fingerprints.
040a4aba Aly Raffauf docs(storage): explain maintenance ownership
docs(storage): explain maintenance ownership
Document how cleanup and daemon startup share the home lock.
6d7a42b6 Aly Raffauf test(storage): prove cleanup owns storage
test(storage): prove cleanup owns storage
Cover startup races, interrupted work, safe retention, and lock release.
633ff2d4 Aly Raffauf fix(storage): give cleanup the daemon lock
fix(storage): give cleanup the daemon lock
Hold ownership through deletion and vacuum, and stop the helper when its CLI goes away.
99a1a483 Aly Raffauf docs(services): spell out access and upload rules
docs(services): spell out access and upload rules
Document service policies, body limits, and known-length uploads.
e2ae9ad9 Aly Raffauf test(ingress): cover refusals and keepalive bodies
test(ingress): cover refusals and keepalive bodies
Check withheld bodies, framing limits, and connection reuse through the real daemon. Prove refused requests leave no work behind.
c51e2fa8 Aly Raffauf fix(daemon): authenticate early and bound request bodies
fix(daemon): authenticate early and bound request bodies
Give each service an explicit policy and read known-length bodies once at ingress. Keep anonymous proxy access and signed webhooks working.
e04c19de Aly Raffauf test(client): prove mutation failures never replay effects
test(client): prove mutation failures never replay effects
Exercise broken replies after admission. Keep each effect single and the UI honest.
aaf313e7 Aly Raffauf fix(client): validate mutation results before updating state
fix(client): validate mutation results before updating state
Keep confirmed changes and require complete mutation responses. Drop legacy extension fallbacks.
17daba3a Aly Raffauf fix(daemon): validate submissions before worker lookup
fix(daemon): validate submissions before worker lookup
Reject malformed submissions before waking a worker. Return complete UI preference responses.
6e75bf9e nekomimi.pet readme: add a terminal screenshot
readme: add a terminal screenshot
05fddc73 nekomimi.pet python tool: make timeout_ms optional and keep code when it is unusable
python tool: make timeout_ms optional and keep code when it is unusable
2026-10-01
21cf1ffb nekomimi.pet refactor(extensions): let extensions delete their own rows with a session
refactor(extensions): let extensions delete their own rows with a session
A CleanPlugin registers what an extension deletes when a session is deleted. Every installed extension's runs inside the delete's transaction, enabled or not, so the daemon no longer names tables it does not own. Rolling, notes, snapcompact, lcm, work and schedule move their cleanup to their own extensions. Cell rows stay in the daemon: they feed the image reference count released in the same transaction. The delete test now also covers a strategy that was switched off and a work item assigned to a session.
7870e7e9 nekomimi.pet fix(daemon): clear snapcompact and lcm rows when a session is deleted
fix(daemon): clear snapcompact and lcm rows when a session is deleted
Deleting a session that had used lcm failed with a foreign key error and removed nothing, because lcm's rows reference the session without a cascade. Snapcompact archives were never removed at all. Both are now cleared, with lcm's edges first. A new e2e reads the schema and checks that no table keyed by session keeps rows after a delete, so a table added later is caught too.
7f1ee85f nekomimi.pet feat(notes): let the model keep its own notes across every compaction
feat(notes): let the model keep its own notes across every compaction
A notes layer sits over whichever strategy is active. At each compaction it asks the model to rewrite its notes from the previous ones and the history just evicted, tells it the budget (2000 tokens by default), and puts the result as plain text ahead of every later request. A failed rewrite keeps the old notes and never fails the turn. The summarizer now takes its instructions per request and reads assistant turns as text and calls rather than raw provider JSON, skipping encrypted reasoning. Strategies trigger at 80% by default, since the notes are not counted in their estimates.
0a29dfa3 nekomimi.pet fix(compaction): keep stale capability notes and reasoning blobs out of evicted history
fix(compaction): keep stale capability notes and reasoning blobs out of evicted history
A compaction rebuilds the system prompt, so capabilities-changed notes in evicted history only repeat a catalog that no longer applies. Snapcompact also dumped Responses items it could not decode as raw JSON, so encrypted reasoning filled its frames. It now renders Responses messages and calls like chat-completions ones and skips reasoning items.
48f27cc7 Aly Raffauf chore(client): remove retry docs and benchmark harness
chore(client): remove retry docs and benchmark harness
Delete the added Markdown files and benchmark tests, and remove the dangling documentation link.
a41500ac Aly Raffauf test(perf): measure daemon request recovery costs
test(perf): measure daemon request recovery costs
Complexity is unchanged: O(1) policy work and O(n) payload processing. Against 23e4018, median healthy reads add 1.95 us, auth recovery drops from 348 to 240 us, and lost-ack handling drops from 362 to 181 us with one execution instead of two.
ecc9b385 Aly Raffauf test(client): exercise acknowledgement loss through real workflows
test(client): exercise acknowledgement loss through real workflows
Cut responses after real daemon admission and verify one durable effect through session, command, message, and sign-in workflows. Cover cancellation and preserve the active session when results are uncertain.
180f5974 Aly Raffauf fix(client): stop replaying uncertain daemon mutations
fix(client): stop replaying uncertain daemon mutations
Retry safe reads and proven authentication refusals; preserve pending messages when acknowledgements disappear. Remove implicit request helpers and test stream and caller recovery boundaries.
048e32d4 Aly Raffauf feat(daemon): mark pre-admission authentication refusals
feat(daemon): mark pre-admission authentication refusals
Mark bearer refusals before dispatch so clients can recover without replaying an admitted mutation.
668f912f nekomimi.pet docs(cli): explain sessions read and send in --help; accept short ids for --session
docs(cli): explain sessions read and send in --help; accept short ids for --session
The help now says what <session> accepts, what [turns] is, that send does not wait, and that read ends with [running] while work continues. The help named --prompt --session as the way to send and wait, but that path took only full IDs, so it resolves a prefix like the other commands.
49b0e96b nekomimi.pet feat(cli): add sessions read and sessions send for other agents
feat(cli): add sessions read and sessions send for other agents
`albedo sessions read <session> [turns]` prints the newest turns of a session's committed transcript (text or --json) and says whether it is still running. `albedo sessions send` is the same command as `albedo send`.
a747ece6 nekomimi.pet fix(cli): let send and stop take a shortened session ID
fix(cli): let send and stop take a shortened session ID
`albedo sessions` prints 8-character IDs, and only open and resume expanded them. send and stop passed the text to the daemon, which answered session not found. All three now share one prefix match.
79f5763a nekomimi.pet docs(agents): add commit and push guidance for a shared checkout
docs(agents): add commit and push guidance for a shared checkout
4024f006 nekomimi.pet feat(python): let a text result answer .content and .text
feat(python): let a text result answer .content and .text
Models kept calling (await files.read(...)).content, 18 failures across sessions. Text is still the string itself; the two names return it.
f1fd75fc nekomimi.pet feat(skills): add built-in design-preflight skill and an agents.md rule
feat(skills): add built-in design-preflight skill and an agents.md rule
The costliest mistakes were placement and side effects that tests never look at (extension-owned migrations put in the daemon, cached activity read stale, a prompt swap that busts the cache). The skill is a short pre-edit checklist; agents.md now says to read a subsystem's robot-docs page and name its owner before editing.
2e50b4bd nekomimi.pet fix(python): explain .content and .text on a text result
fix(python): explain .content and .text on a text result
files.read and friends return the text itself, already awaitable. Models kept calling (await files.read(...)).content and got a bare AttributeError (15 times across sessions); the error now says the result is the text.
146237e0 nekomimi.pet feat(kernel): restore helpers from source, cap saved state, expire idle sessions' state
feat(kernel): restore helpers from source, cap saved state, expire idle sessions' state
The kernel saved its namespace with dill when installed, else pickle, and its Python has no dill, so functions, classes and imports were lost on every restart. It now records the source of top-level imports, functions and classes (including from a cell that fails after defining them) and re-runs it on restore, re-registering it so the next save keeps it. Saved state is capped at 64 MiB (8 MiB a variable; 256 KiB of definitions) instead of 256 MiB. The restore note names what was re-run from source, what was not, and the largest saved variables. A state file is deleted when its session has been idle past ALBEDO_STATE_EXPIRY_SECONDS (default 14 days), judged from fresh store activity, never for a live kernel or running turn; unknown files older than a day go at startup. Covered by e2e tests through the real daemon.
024a9d77 nekomimi.pet feat(skills): ship orchestrating-agents and complexity-review built in
feat(skills): ship orchestrating-agents and complexity-review built in
Both are general, with no albedo internals, so they work for people who have only the daemon and TUI. orchestrating-agents now also covers model choice, shared contracts, verifying claims against the source, and staying in scope toward the user. The repo-local copy is removed because a project skill would shadow the built-in one.
6940da60 Aly Raffauf test(files): cover decoded windows and resume hints
test(files): cover decoded windows and resume hints
Exercise UTF-8 boundaries, exact totals, budgets, and giant-line diagnostics through the real daemon. Keep checks tied to behavior and useful resume data.
ea79aef3 Aly Raffauf perf(files): reduce read memory from O(file) to O(chunk + max_chars)
perf(files): reduce read memory from O(file) to O(chunk + max_chars)
128 MiB benchmarks cut peak Python RSS from 284-530 MiB to ~28 MiB, with >99.8% lower traced peaks. Small reads slowed at most 7.54% and ASCII full scans 10-28%, while Unicode and giant-line reads sped up.
23e40188 Aly Raffauf test(tui): remove older-daemon compatibility coverage
test(tui): remove older-daemon compatibility coverage
Keep scope behavior tests and drop the legacy-daemon fallback assertion.
e444c485 Aly Raffauf perf(context): render snapshots outside the session actor
perf(context): render snapshots outside the session actor
Move O(n) text rendering to the caller; total read complexity stays unchanged and snapshot copying scales with descriptor size. Renderer-only baseline: first pages took 1.44 ms at 1 MiB and 17.11 ms at 16 MiB; this change frees the actor rather than speeding up rendering.
96f08f0d nekomimi.pet feat(skills): add built-in research skill
feat(skills): add built-in research skill
General investigation skill (libraries, other projects' implementations, approaches): frame the decision, pin what you read, test what you claim, report in a fixed block. A new e2e asserts every shipped skill is cataloged.
d480d22b nekomimi.pet feat(files): let files.paths take a list of paths and globs
feat(files): let files.paths take a list of paths and globs
files.find already did; files.paths raised a TypeError on a list. Both now share the target and glob helpers.
09d3e185 nekomimi.pet docs(skills): steer customize-albedo toward the portable .agents locations
docs(skills): steer customize-albedo toward the portable .agents locations
eb5983de nekomimi.pet docs(skills): document SYSTEM.md and APPEND_SYSTEM.md in customize-albedo
docs(skills): document SYSTEM.md and APPEND_SYSTEM.md in customize-albedo
b6a1bcf9 nekomimi.pet docs(skills): make customize-albedo about authoring, not albedo internals
docs(skills): make customize-albedo about authoring, not albedo internals
The skill ships to people with only the daemon and TUI, so it now covers where a skill lives, what goes in SKILL.md, instruction files, and the /mcp and /extensions screens, without pointing at the source tree.
28aec150 nekomimi.pet chore(tui): remove unused sessionPrefs.archived
chore(tui): remove unused sessionPrefs.archived
57037d26 nekomimi.pet feat(tui): fold long user messages behind a click to expand
feat(tui): fold long user messages behind a click to expand
A settled message of yours past 12 rows shows its first 10 and a fold row. Clicking it renders only that block again and splices it into the settled rows, keeping the clicked row in place.
46d15279 nekomimi.pet feat(skills): ship built-in skills from priv/skills
feat(skills): ship built-in skills from priv/skills
Built-in skills rank below workspace and user skills and yield to a same-named one without a duplicate diagnostic. The first one, customize-albedo, covers skills, instruction files, MCP servers, and extensions.
9940771a Aly Raffauf fix(tui): clear streamed arguments on every detach path
fix(tui): clear streamed arguments on every detach path
Reset arguments and the cursor after cancellation, including requests still waiting for headers and subscriptions between reconnects. Keep unfinished previews across transient failures, and cover fresh subscriptions with regression tests.
9f5da824 Aly Raffauf perf(daemon): assemble tool arguments in amortized O(n)
perf(daemon): assemble tool arguments in amortized O(n)
Use append-only buffers to change assembly from O(n²) to amortized O(n), with immutable snapshots and unchanged limits. With 32-byte deltas, allocations fall from 1.10 GB to 1.19 MB at 256 KiB and from 17.31 GB to 5.24 MB at 1 MiB.