Commit Graph
100 Commits
Author SHA1 Message Date
kyleandClaude Opus 5.5 7b95937c88 brokerd: the ledger raises a session's state by the stricter label
M5a task 21. The work is Ornith's, from the stopped run; the design
model checked it against the task file and committed it after finding
that the gate's failure came from its own reference worktree's stale
test binaries in the shared target/ (fixed with cargo clean; 944 tests).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 20:20:48 -07:00
kyleandClaude Opus 5.5 f389a9a43a M5a plan: tasks 21 and 22, from the device check
21: the ledger raises a session's state by the stricter of the grant's
label and the result's own, so a clean session that recalls a
memory-tainted note becomes untrusted and cannot write it into
memory.md (found on straylight, 2026-09-25). 22: the answers to a note
name notes.md, and for an untrusted add the file that was not changed.
The new given tests are ledger_label.rs and new versions of memoryd's
edit.rs and serve.rs; the old copies are kept as -task06 and -task10. On
a scratch tree at the end of task 20: the named tests fail and then pass,
5 and 4 mutations are caught, and the gate passes with 944 tests.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 17:55:41 -07:00
kyleandClaude Opus 5.5 f025c811c0 decisions: open, a reason in invalid-arguments refusals (M5b)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 17:44:36 -07:00
kyleandClaude Opus 5.5 0e5b1d2820 M5a spec: the session's state follows a result's own label; plainer note answers
Found on the device (2026-09-25): the ledger raised a session's state by
the grant's label, so a clean session that recalled a memory-tainted note
stayed trusted and could add it to memory.md. The spec's "as today" was
wrong; section 8 now says the state is raised by the stricter of the
grant's label and the result's, and the recall section says the session
becomes untrusted. The note answers (section 3) name notes.md and, for an
untrusted add, the file that was not changed: the model read the old ones
as success. Tasks 21 and 22.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 17:44:35 -07:00
kyleandClaude Opus 5.5 a3c800cf91 P22: crossbar's answer, and what M8 starts from
Crossbar (main, 4c64158) cannot serve Boxmaker as deployed; agents
connect straight to a host's llama-server until crossbar adds a default
route, per-route stickiness, side calls outside its limiter and
llama-server's error shape. Queued-looks-idle stays open.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 17:19:05 -07:00
kyle 34dbbb27be memoryd: a staged write's id counts every write staged that day 2026-09-25 16:41:44 -07:00
kyle 81107bc5c6 proto, memoryd: no line of an entry may start with §, and headers are exact
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-25 16:41:44 -07:00
kyle 3640d32de0 memoryd, proto, brokerd, bxctl: repeated error lines written once
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-25 16:41:44 -07:00
kyle b98f373ead memoryd: the day and the month of a time with get, never a slice
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-25 16:41:44 -07:00
kyleandClaude Opus 5.5 1adce5c9df brokerd tests: a slow fake podman no longer fails the time-limit tests
The fake wrote each argument with its own printf. On a loaded machine
(titan, serving Ornith while the gate runs) the 300 ms limit fired while
`run` was still recording, and the `kill` call's lines landed inside
`run`'s: `a_tool_past_its_time_limit_is_killed_removed_and_failed`
failed about one run in five. The fake now writes each call to a file of
its own and appends it with one `cat` (bash's printf writes line by
line), and the two time-limit tests check the calls other than `run`,
which may be killed before it records itself. Test-only; 20 of 20 runs
pass, and both tests pass with a forced one-second start.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 16:41:44 -07:00
kyleandClaude Opus 5.5 7d5c5a8d85 gate: pass on macOS: tests use /tmp, gatewayd finds its uid without /proc
M5a task 16. The work is Ornith's, from the stopped run; the design
model checked it against the task file and committed it once the
memoryd lint that stopped the gate was fixed (44bdcbd).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 16:41:44 -07:00
kyleandClaude Opus 5.5 d47fb32483 memoryd: a match guard, not an if in the arm (clippy 1.95)
Clippy 1.95's collapsible_match flags the nested `if` in the
`LogRecord::User` arm of `index_record`, and the workspace pins
rust-version 1.95, so `make gate` failed on titan. An empty user message
now falls to the `_ => {}` arm, which indexes nothing, as before.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 16:41:44 -07:00
kyle e763ad715e log: M5a/16-macos-gate stopped on a pre-existing memoryd clippy failure
The three task changes (.cargo/config.toml, copied toolkit shell test, and the three read_checked edits in gatewayd/secrets.rs) are done and all gatewayd/toolkit/brokerd tests pass. make gate does not reach them: it fails to compile memoryd on clippy collapsible_match at crates/memoryd/src/index.rs:224, which fails identically on the original committed code and is outside this task's scope. Per AGENTS.md point 4, committed only this log row.
2026-09-25 16:41:44 -07:00
kyleandClaude Opus 5.5 1dca52118d M5a plan: run tasks 16 to 20 on titan's own Ornith
Titan serves ornith-1.5-35b-a3b itself, so OpenCode there uses
titan/ornith-1.5-35b-a3b. The harness's device checks still use straylight.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 16:41:44 -07:00
kyle c55cffe884 Ignore the opencode directory. 2026-09-25 16:41:44 -07:00
kyleandClaude Opus 5.5 64190c3701 M5a plan: task 16, the gate passes on macOS; the review's tasks become 17 to 20
The work moved to titan (macOS), where the gate failed for reasons older
than M5a: sockets under macOS's long TMPDIR pass its 104-byte limit,
gatewayd reads /proc/self for its uid, and /tmp is /private/tmp. Task 16
sets TMPDIR=/tmp for every process Cargo runs (.cargo/config.toml [env]),
has gatewayd take its uid from the owner of a pipe it makes (no dependency,
no unsafe), and hands over a toolkit shell.rs that compares resolved paths.
On a scratch tree the gate passes on titan and on talos with 936 tests, and
a wrong uid fails 7 gatewayd tests. Tasks 16 to 19 are renumbered 17 to 20.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 16:41:44 -07:00
kyleandClaude Opus 5.5 0a7a95d709 M5a plan: task 19, a staged write never reuses an id
review::submit counted only the writes still waiting, so a write staged
after an accepted one got that one's id and was lost: never listed, never
acceptable. It now counts every Waiting line of the day. On a scratch tree
with task 16's line applied, both new tests fail and then pass, the old code
and a count of every line are both caught, and the gate passes (938 there;
941 after task 18).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 16:41:44 -07:00
kyle a32f94aead run-plan: OPENCODE_MODEL, not BOXMAKER_MODEL, names the model
It matches OPENCODE_FLAGS, and no longer clashes with BOXMAKER_MODEL, which
the device tests send to llama-server as the model name.
2026-09-25 16:41:44 -07:00
kyleandClaude Opus 5.5 46b2927d0a M5a plan: task 18, a note cannot forge a notes.md header
entry_problem refuses any line that starts with the separator, and a noted
header with an unknown last part is not a header. The new given tests are
forgery.rs and new versions of memory_args.rs and notes.rs; the old copies
are kept as -task02 and -task06. On a scratch tree at the end of task 17,
the three tests named in the task fail and then pass, four mutations of the
fix are caught, and the gate passes with 939 tests.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 16:41:44 -07:00
kyleandClaude Opus 5.5 53873c82bf M5a spec: no line of an entry or a note may start with §
The M5a review found that a note's text could hold a line shaped like a
notes.md header. Read back, the line started an entry of its own: an
untrusted session could plant a 'moved from memory.md' header, and recall
showed what followed it as identity, not untrusted. Entries and notes now
refuse any line that starts with the separator, and a header must match one
of its three forms exactly.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 16:41:44 -07:00
kyleandClaude Opus 5.5 d707be072d M5a plan: tasks 16 and 17, the review's nits
Task 16: memoryd takes the day and the month of a time with str::get, never a
slice. Task 17: repeated error lines in memoryd, proto, brokerd and bxctl
written once. Neither changes behaviour. Both were applied to a scratch tree
from 5f82260: the gate passes with 936 tests, and four mutations of the new
helpers are caught by the existing tests. The README runs with OPENCODE_MODEL.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 16:41:44 -07:00
kyleandClaude Opus 5.5 fb65206a6c Implementer log: the Model column filled in as Ornith-1.5-35B-A3B
Every row from M2a to M5a that read ? or Ornith, from the reviews' own
records of who ran each milestone. The DEBUG-HANDOFF row stays ? : no record
says which model it was.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 16:41:44 -07:00
kyleandClaude Opus 5.5 fb0aa2e576 Research: chat-template tags in text the model reads; tips I15 and T33; an open decision
M5a task 04 stopped twice on the chat-template tags the check refuses.
The first time, the model read them in a file and took them for its own
template. The second time, it spelled them out in its own reasoning.

Measured on straylight: the think and tool-call tags are one token
whatever the tokenizer's flag. Inside any chat message, the turn
markers become control tokens, so a tool result can forge a system
turn.

Adds the rule to AGENTS.md, and proposes neutralizing the tags in
loopd as an open decision.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 16:41:44 -07:00
kyleandClaude Opus 5.5 6f093fcd8e M5a task 15: the starter soul and device checks with memoryd, finished
The session did the task and stopped on make verify-device. The cause
was not the server: run-plan.sh and the device tests both read
BOXMAKER_MODEL, and the run's value (OpenCode's provider-prefixed id)
reached llama-server as the model name. With it unset, verify-device
passes 6 of 6. The copied files are identical to the plan's, and the
gate prints gate: ok, 936 tests.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 16:41:44 -07:00
kyle 9f57cfc381 M5a: the starter soul.md, and the device checks with memoryd running
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-25 16:41:44 -07:00
kyle 0a1c206d50 bxctl: reindex, and memory log, undo, pending, accept, reject
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-25 16:41:44 -07:00
kyle 15ee4b8e3d loopd: the memory block from memoryd, recall and memory as core tools
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-25 16:41:44 -07:00
kyle e167fc871b brokerd: memory calls to memoryd with the session's state; labels only stricter
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-25 16:41:44 -07:00
kyle fcfd590687 brokerd: recall and memory, decided under built-in grants
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-25 16:41:44 -07:00
kyle 0c8d136c6b memoryd: serve, three sockets and one lock over the files and the index
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-25 16:41:44 -07:00
kyle 49af057c81 memoryd: recall, with source tags and the recall log
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-25 16:41:44 -07:00
kyle f329d23bd9 memoryd: the FTS5 index over session logs and notes, with labels
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-25 16:41:44 -07:00
kyle b1c9d590c8 memoryd: the edit journal, undo of the latest edit, and review
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-25 16:41:44 -07:00
kyle b51b320706 memoryd: notes.md, and the five memory actions with routing by trust
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-25 16:41:44 -07:00
kyle f5981338b4 memoryd: the memory files, and the block a new session starts with
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-25 16:41:44 -07:00
kyle ad5ce5c6e7 memoryd: entries, and the check on every memory write
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-25 16:41:44 -07:00
kyleandClaude Opus 5.5 178484a981 M5a plan, task 04: check.rs given complete; later tests use no tags
Task 04's second session stopped too. It checked its code against the
markup test cases in its reasoning, and the tag it spelled out ended
its reasoning. Building tags from pieces keeps them out of files, not
out of the model's thoughts.

check.rs is now given whole, with the tags from pieces, and task 04
fills only entries.rs. The three later tests that used a tag only as
something the check refuses now use an instruction phrase or an
invisible character. They pass against the reference.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 16:41:44 -07:00
kyleandClaude Opus 5.5 8328e8f607 M5a plan, task 04: chat-template tags built from pieces
Task 04's session read the given test and the check.rs skeleton, both
holding the tags the check refuses, and Ornith took them for its own
template. It lost track of the file and made no change. The tags are
now built with concat! and format! in check.rs and in the four given
tests that held them, and the spec describes them in words. The
rewritten tests pass against the reference, are rustfmt-clean, and
still catch the case-folding mutation.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 16:41:44 -07:00
kyle b84b9af540 memoryd: the crate, memoryd.toml, and listening on a socket
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-25 16:41:44 -07:00
kyle 964bd99b12 proto: memory, the arguments of recall and memory and eight message kinds
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-25 16:41:35 -07:00
kyle 861ff7d06a brokerd: policy and ledger as modules, before the memory tools
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-25 16:41:35 -07:00
kyleandClaude Opus 5.5 41f8329afe nix: a flake that builds every binary, the tool image and a dev shell
Follows the owner's other projects (sift, tether): nixpkgs pinned to
nixos-26.05, x86_64-linux, the version from the commit. `packages.default`
builds all six binaries with rustPlatform (tests stay in `make gate`),
`packages.tools-image` is deploy/tools-image.nix, and `devShells.default`
has Rust 1.95.0, clippy, rustfmt, cargo-deny and make. No NixOS module
yet: that is M8 (P22).

Checked on straylight: `nix flake check` passes; `nix build` gives
brokerd, bxctl, gatewayd, inferproxy, loopd and toolkit, each printing
its usage; `nix build .#tools-image` and `nix develop` work.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 16:41:29 -07:00
kyleandClaude Opus 5.5 45f311ecfc Propose P22: a fleet of independent agents, deployed with Nix (M8)
Owner's direction, 2026-09-25: one agent per host, each with its own
identity, memory and credentials, sharing fleet memory through Honcho;
inference from a configured llama-server-compatible endpoint; a last
milestone that deploys to NixOS hosts and other Linux hosts. Not applied
to the brief yet.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 16:41:29 -07:00
kyleandClaude Opus 5.5 0062b2a895 CLAUDE.md: M5a is planned
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 15:33:20 -07:00
kyleandClaude Opus 5.5 de1032157b Plan M5a: local memory in 15 tasks
memoryd (files, the check, edits, journal, index, recall, serving),
the memory tools and built-in grants in brokerd, the memory block in
loopd, bxctl reindex and memory, and the device checks with memoryd.

Each task was built as a reference and gated. Each was replayed on its
own at its end state (854 to 936 tests) and mutation-checked. Each
skeleton compiles and fails its tests. Every todo comment was read
beside its signature.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 15:32:54 -07:00
kyleandClaude Opus 5.5 19fd74db6e M5a spec: details settled while building the reference
The memory socket in brokerd.toml is optional, and bxctl's flag is
--memory-socket. A note's header carries its class. Built-in grants are
kept apart from the owner's, and builtin- ids are reserved. The session
state is carried through Decision and RunSpec, labels through
run_labelled. loopd's assemble_with and MemorySource. Baseline
measured at 881 and 2,432 tokens.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 14:58:33 -07:00
kyleandClaude Opus 5.5 d80b0b3d8a gatewayd: serve_answers waits for every reply it reads
nobody_else_and_nothing_else_answers_it read five replies after
waiting only for the first, so it failed whenever the other four were
not posted yet. It failed once in a full `make gate` run, when many
test binaries ran at once. The helper now waits for as many posts as
the test reads.

The M4b plan's copy is left as it was handed over.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 14:56:58 -07:00
kyleandClaude Opus 5.5 5ffca7a577 M5a spec approved
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:53:02 -07:00
kyleandClaude Opus 5.5 c7f3895c3f Apply P21: identity and experience; memory writes without approval; built-in policy
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:53:02 -07:00
kyleandClaude Opus 5.5 775aa853ed M5a spec: recall hits carry a source tag: identity, memory or memory-tainted
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:51:46 -07:00
kyleandClaude Opus 5.5 0ce3bfc641 Research: prompt-injection defences for persisted memory; the M5a check refuses all default-ignorable code points
The research feeds M5b's sanitizer. One finding is a bug in the M5a
draft: category Cf misses variation selectors, the combining grapheme
joiner, and the Hangul and Braille fillers.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:51:06 -07:00
kyleandClaude Opus 5.5 64a5931354 P21 and the M5a spec: identity and experience; the archive becomes notes, and note is a memory action
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:49:28 -07:00
kyleandClaude Opus 5.5 20bb2ff6fc M5a: the check stays short and fixed; a sanitizer from injection research becomes M5b hardening
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:46:00 -07:00
kyleandClaude Opus 5.5 bb04467001 M5a spec: memory writes are not announced, only journalled; approval syntax noted in the open decision
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:43:55 -07:00
kyleandClaude Opus 5.5 29f9069a33 Propose P21 (memory writes without approval, as in Hermes); revise the M5a spec to match
Writes from sessions that have read untrusted content go to the
archive, labelled untrusted, and never reach the prompt. Every write is
checked, announced in its thread, journalled and can be undone.
Session-scoped approvals for other tools become an open decision.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:41:02 -07:00
kyleandClaude Opus 5.5 817fb9d47f M5a spec: built-in policy for recall and memory; tool calls indexed; output summaries in M5c
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:33:37 -07:00
kyleandClaude Opus 5.5 e86d203740 Draft the M5a spec (local memory); compaction moves to M5c
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:22:08 -07:00
kyleandClaude Opus 5.5 174bdc05b2 CLAUDE.md: memoryd and the M5 split
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:12:38 -07:00
kyleandClaude Opus 5.5 d1c106dd5c Apply P20: M5 splits into M5a (local memory), M5b (Honcho) and M5c (the scheduler)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:12:21 -07:00
kyleandClaude Opus 5.5 774807aa81 Apply P19: recall over the local index and Honcho; trust per workspace
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:12:11 -07:00
kyleandClaude Opus 5.5 9685289242 Apply P18: memoryd, the one owner of memory
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:11:48 -07:00
kyleandClaude Opus 5.5 428b87d31d Apply P17: memory is three files read once per epoch; the memory tool with consolidate
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:11:31 -07:00
kyleandClaude Opus 5.5 85d9519d22 M5 proposals: P19 names no workspace; trust is per workspace, set by the owner
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:07:40 -07:00
kyleandClaude Opus 5.5 71cfe7bb6c M5 proposals: a tiering job in M5c, recall-hit counts from M5a, hermes-fleet trusted; projects as an open decision
The owner's review of 2026-09-24.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:05:04 -07:00
kyleandClaude Opus 5.5 6d36c54ddd M5 proposals: consolidate moves memories to an archive; memoryd owns the memory files and the index
The owner's review of 2026-09-24. P17: the memory tool gains
consolidate, which moves entries out of memory.md into
memory/archive.md, and from M5b into Honcho, instead of losing them.
P18: memoryd owns memory/ and the SQLite index, so every memory tool
runs in one place.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:03:07 -07:00
kyleandClaude Opus 5.5 bb53729950 M5 direction: three memory files, Honcho through memoryd; propose P17 to P20
The owner's direction of 2026-09-24:

- Memory is three local files, as Hermes has them: a soul written by
  the owner, and memory and user files the agent edits.
- Honcho is the fleet's memory. Each Boxmaker writes only to its own
  workspace, and can read other workspaces at a trust level the owner
  sets.
- A new role, memoryd, does the syncing, because brokerd never holds
  conversation history and loopd has no network.
- M5 splits into M5a (files and local search), M5b (memoryd and
  Honcho) and M5c (the scheduler).

The brief is not changed until the owner approves P17 to P20.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 12:48:49 -07:00
kyleandClaude Opus 5.5 a1d5083bd5 CLAUDE.md: M4b is done and merged; branches land by rebase
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 12:31:12 -07:00
kyleandClaude Opus 5.5 ddb459a631 M4b: the redirect checked on the owner's server; finding 1 closed
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 12:29:02 -07:00
kyleandClaude Opus 5.5 bfbdccb99d M4b review of tasks 16 to 18; tip T32
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 12:22:24 -07:00
kyleandClaude Opus 5.5 a43d9979c8 gatewayd: serve_restart takes the two caught-up turns in either order
The two posts caught up at restart are two top-level posts, so two
sessions, and their turns run on their own threads. gatewayd starts
them in order, but which one reaches loopd first is up to the
scheduler. Under load the test failed about 1 run in 60; task 18's
session hit it once. mm_json.rs already checks the order of catch-up
(reversing the sort fails there), so this test now compares the two
turns as a set. It passed 100 of 100 runs under load.

The M4a plan's copy is left as it was handed over.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 12:22:10 -07:00
kyle e10d93c3e8 gatewayd: approvals asked by non-approvers in direct messages go to an approver
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-24 12:07:06 -07:00
kyle 989548419d gatewayd: the texts that say who asked for a redirected approval
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-24 11:51:43 -07:00
kyle bf89512832 brokerd: the refusal without a runner names the missing [runner] section
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-24 11:48:49 -07:00
kyleandClaude Opus 5.5 f6dd7f1741 M4b review, and follow-up tasks 16 to 18
The review of tasks 01 to 15 goes in the implementer log, with the
device check against the owner's Mattermost. Three follow-ups:

- 16: the refusal without a runner says why.
- 17: the texts that say who asked.
- 18: approvals from non-approvers in direct or group messages go to
  an approver.

Task 14's given serve_approvals.rs becomes serve_approvals.rs-task14,
since task 18 hands over a new version. Tip T31 is added.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 11:35:24 -07:00
kyleandClaude Opus 5.5 d2e814161f M4b spec: approvals from non-approvers in direct messages go to an approver, with who asked and what
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 11:09:59 -07:00
kyle edf9ba3515 gatewayd: approvals answered from Mattermost; typing paused; the notice
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-24 10:19:41 -07:00
kyleandClaude Opus 5.5 af7137dafe M4b task 15: fix task 14's dropped refusal reason, as a listed edit
Task 15's session found the defect in serve/approvals.rs, a file it did not list, and stopped.
The comment in task 14 used one name for two values; task 14's tests could not reach it. Lesson T30.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 08:46:33 -07:00
kyle c38e450f44 gatewayd: serve, posting approvals, marking them, and the listener
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-24 05:07:50 -07:00
kyle a33ff240c4 gatewayd: gateway, the gateway.sock listener and one thread per connection
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-24 04:59:02 -07:00
kyle 07e4e16270 gatewayd: state, the posts of open approvals, and the turn of a session
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-24 04:50:54 -07:00
kyle c5df86d13d gatewayd: approvals, the registry and the judging of commands
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-24 04:48:06 -07:00
kyle d9f8fa9331 gatewayd: approvals::text, the posts that show an approval
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-24 04:42:37 -07:00
kyle 18791ab389 gatewayd: mm, patch_post and username
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-24 04:36:45 -07:00
kyle 365e50081d gatewayd: strip a leading mention of this bot; recognise approval commands 2026-09-24 04:33:03 -07:00
kyle b45ca14c14 gatewayd: config, [approvals] users and socket
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-24 04:28:26 -07:00
kyle e0560ab996 brokerd: courier, carrying pending approvals to gatewayd and answers back
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-24 04:25:07 -07:00
kyle 412f80c470 brokerd: config, [gateway] socket for Mattermost approvals 2026-09-24 04:18:04 -07:00
kyle a00711e379 brokerd: answers carry the Mattermost post; Table::contains
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-24 04:15:11 -07:00
kyle a5c37d8756 bxctl: deny, another name for refuse
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-24 04:11:01 -07:00
kyle ebb78e816d proto: gateway, the four messages between brokerd and gatewayd
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-24 04:07:46 -07:00
kyle db3f9ed01b proto: escape, moved from bxctl so gatewayd shows the same thing
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-24 04:01:03 -07:00
kyleandClaude Opus 5.5 2d415fc1be Plan M4b: approvals over Mattermost in 15 tasks
Skeletons for new files only; existing files change by exact edits, so no task overwrites an
earlier one's work. Each task's tests were run against a reference built in order from master,
with the gate at each step and mutations checked; each skeleton compiles and fails its tests, and
every todo!() comment was read beside its signature. The reference is kept off this machine.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 03:34:21 -07:00
kyleandClaude Opus 5.5 b1f732a42a M4b spec: names and details settled while building the reference
approval_reply and GatewayOutcome (proto already has an ApprovalAnswer); the bot's edit permission
confirmed on the owner's server; a restart replaces a dead post's text; the reason escaped as
inline code; the part size bound; the reply for an approval too long to show.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 03:22:55 -07:00
kyleandClaude Opus 5.5 a8f7819da3 M4b spec approved
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 01:54:59 -07:00
kyleandClaude Opus 5.5 1c2695d21d Apply P16: approvals are !approve/!deny replies in the approval's thread; no reactions
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 01:54:50 -07:00
kyleandClaude Opus 5.5 3088dcc201 M4b spec: gatewayd strips a leading mention of its own bot; bare commands are the operator's care
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 01:53:54 -07:00
kyleandClaude Opus 5.5 00a9b576b2 Specify M4b (approvals over Mattermost); propose P16 on approval replies
The owner's decisions of 2026-09-24: commands only, no reactions; an approvers list that falls
back to allow.users; approvals in the asking thread; on a gatewayd restart, old posts are marked
dead and brokerd's courier posts pending approvals again.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 01:48:51 -07:00
kyleandClaude Opus 5.5 3322a56e69 CLAUDE.md: M4a is done and merged; M4b is next
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 01:37:17 -07:00
kyleandClaude Opus 5.5 2ee9310fc3 Merge M4a: gatewayd, conversations over Mattermost
Sixteen tasks by Ornith through the plan driver, the review's fixes, and task 16 for its one low
finding. Checked end to end against the owner's Mattermost.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 01:36:59 -07:00
kyleandClaude Opus 5.5 53560ca731 M4a task 16 review: accepted; the plan's copy of its test is now the formatted file
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 01:36:22 -07:00