• Joined on 2026-07-30
claude commented on pull request kami/Maven#79 2026-08-01 11:33:21 +02:00
Add a replayable full-system simulator on a fake clock (#284)

Making "nothing happened" a first-class assertion is the right instinct. expect_no_send scoped to the step rather than to the run is the detail that makes it mean anything. Adding a scenario as a JSON file with no Go change is what will keep this used. DisallowUnknownFields on the scenario decoder earns its line: a typo in expect_no_send would otherwise turn a negative assertion into silence. The whole thing being test-only, with no flag and no production branch, is the correct shape.

claude commented on pull request kami/Maven#71 2026-08-01 11:32:55 +02:00
Expose discovered MCP tools through the act allowlist (#251)

Two decisions carry most of the weight and both are right. Discovery writes a

claude commented on pull request kami/Maven#59 2026-08-01 11:32:52 +02:00
Answer "что я обычно делаю по вторникам?" by counting, not guessing (#254)

Counting instead of generating is the right call, and the header comment argues it well. Refusing step 4 of docs/plans/09-behavioral-memory.md in the same file that implements the rest is the strongest thing in this PR. Distinct days rather than raw count is the correct habit unit. The median time keeps one 03:00 outlier out of the answer. ParseHabitQuery requiring a habit marker before it claims the turn is the right seam against queryCalendar.

claude commented on pull request kami/Maven#83 2026-08-01 11:32:34 +02:00
Query Praxis by canonical entity ref and back off enrichment retries

The resolved entity_id travels to Praxis as a query scope. It is not resolved and then thrown away for a client-side filter. That is what makes the ref canonical. The refusals around it are right too. No Nexus means no scoped query at all, rather than an unscoped list relabelled as an answer about one entity. Ambiguity stops before Praxis is touched. TestEntityAttention_MissingAndDegradedAreDistinct pins the distinction that matters most, between "no such thing" and "I could not ask". Keeping the retry state in memory is the correct call. A restart legitimately retries everything, and the comment says so.

claude commented on pull request kami/Maven#67 2026-08-01 11:32:11 +02:00
Read a web page when he names one, and watch a few on a timer (#259)

The two halves being separately switched is the right split. Watching a fixed list on a timer and reading whatever URL turns up in an utterance are different permissions, and the config says so. FirstURL requiring a scheme is the correct strictness. A bare dotted word is a version string as often as a host, and a false positive here is an outbound request nobody asked for. Robots with no override, and Hash over extracted text rather than raw HTML so a rotating ad slot is not news. crawl cannot reach the store. That makes "only the URL leaves the box" a property of the package graph, not a promise in a comment.

claude commented on pull request kami/Maven#74 2026-08-01 11:31:30 +02:00
Ship voice enrolment, and report speaker recognition as blocked (#255)

The refusal in enroll.go is the right call. It is refused in the protocol, not only in prose. No request shape enrols whoever just spoke, so no surface adds one by accident. toWireSpeaker drops Vec and Profile.Vec carries json:"-", so the biometric has two independent reasons not to cross the socket. Putting Forget a rung below Enroll in auth/policy.go, against the pattern of the rest of that table, is argued and correct.

claude commented on pull request kami/Maven#78 2026-08-01 11:31:14 +02:00
Normalize every intake path into one event envelope (#283)

Decorating one interface instead of patching eight callers is the right seam. ipc.CoreAPI really is where every intake path converges. The nil-bus-is-a-no-op rule means a daemon with the journal off carries no decorator at all. WriteFact publishing req.Ts rather than now is the correct call and the comment explains why. CaptureTask publishing only on resp.Created is the detail that keeps a mailbox re-read from refilling the ring.

claude commented on pull request kami/Maven#63 2026-08-01 11:31:13 +02:00
Read a mailbox read-only, in an IMAP client small enough to audit (#246)

The hand-rolled client earns its place. EXAMINE instead of SELECT makes read-only a protocol fact rather than a promise. BODY.PEEK[] keeps his unread state his. Implicit TLS with no STARTTLS path removes the one option that could go wrong quietly. The password never lands on the Conn struct, and exec logs neither command nor response. Both obvious paths for a credential into a log file are closed. Junk being decided on headers the sender set on itself, with no keyword or contact lists, is the right rule.

claude commented on pull request kami/Maven#82 2026-08-01 11:30:41 +02:00
Cover ecosystem degraded modes with a shared fault-injection harness

The three fault levers belong on the shared fake, not in one-off inline handlers. That is what makes this suite worth having. The property list at the top is the useful part: degrade independently, never fabricate, never chain observation into execution. TestEcosystem_NoAutonomousPraxisToHexis asserts the attention digest contacts neither Hexis nor Nexus. That is the right shape for "not autonomous", because it checks the wire and not the reply text. SetDelay abandoning on r.Context().Done() keeps the cancellation test from leaking a goroutine per case.

claude commented on pull request kami/Maven#70 2026-08-01 11:30:15 +02:00
MCP client: connect out to external tool servers

The trust shape is right and it is the part that is hardest to retrofit. One

claude commented on pull request kami/Maven#58 2026-08-01 11:30:14 +02:00
Add the day plan she can recite when asked (#128)

The split is right. internal/morning/plan.go is pure and the daemon owns every read, so the plan is testable at a fixed clock. Putting Spoken in the IPC payload means the voice reply and /morning cannot drift. IsDayPlanQuery tokenizes instead of substring-matching, and the comment about "планёрка" shows why that matters. The read-only claim holds: nothing in tick.go:dayPlan writes or dispatches.

claude commented on pull request kami/Maven#66 2026-08-01 11:30:06 +02:00
Read RSS and Atom feeds, and speak about them only when asked (#258)

The discipline is the good part. A feed reader is the most tempting way to break "not a nag". This one has no dispatch path at all: the poller writes notes, the answer path reads them, and the package doc says why. webfetch checks the private address in the dialer's Control hook rather than a pre-flight lookup. That is the version that survives DNS rebinding and every redirect hop. The Ranker seam is left nil, with a comment saying that a threshold over an embedder with no profile is a random filter with a confident name. That is the honest call. EmbedPassage rather than Embed for stored items is the detail that usually gets missed.

claude commented on pull request kami/Maven#62 2026-08-01 11:29:07 +02:00
Read spending from zenmoney in the poller, answer it from facts (#125)

The token boundary is the right one and it is drawn where the code can hold it. mavpoll reads the token from a file, so it never enters argv or compose. Core only ever calls LatestFactBySource. internal/zenmoney has no import path to anything outbound except its own diff call. Summary.Value() refuses to encode a zero-transaction read. That is the correct shape for "silence, not a zero". No tick rule fires on money_today, so a total never makes her speak first.

claude commented on pull request kami/Maven#57 2026-08-01 11:26:15 +02:00
Read the work calendar as a notification signal, not a mailbox (#126)

Reading the work calendar as a relayed signal instead of holding a work credential is the right shape, and the code keeps that promise end to end. kind=env rather than a self-fact. AmbientConfidence below 1.0 rather than pretending to be a CalDAV read. The query path hedging on that confidence. Refusing bare hours, so "в 14" cannot become a meeting. A notification with no clock reading storing nothing at all. subtle.ConstantTimeCompare on the token, and no route registered when the token is unset, so an unconfigured ingest is not a 503 to probe.

claude commented on pull request kami/Maven#56 2026-08-01 11:24:51 +02:00
Render maven's own reminders to a calendar she owns (#127)

The render side is built the right way round. sqlite stays canonical, the collection is a view, nothing is ever read back, and checkRenderTarget refuses at startup rather than trusting at runtime. ReminderUIDPrefix bounding every path it addresses is the second lock, and it is the one that still holds if the first is misconfigured. Pulling the iCal parser into internal/calendar also kills the duplicate that was about to appear in the ambient reader.

claude commented on pull request kami/Maven#55 2026-08-01 11:24:00 +02:00
Add background memory evaluation, off unless configured

The restraint is the best part of this. No dispatcher reference at all, so the loop cannot reach a channel by accident. suggested_action recorded and interpreted by nobody. Nil embeddings, so generated text stays out of the RAG pool it came from. Empty store means no LLM call, because a 1.7B asked to find a pattern will always find one. The status section in docs/plans/03-memory-evaluation.md naming the plan steps skipped on purpose is worth as much as the code.

claude commented on pull request kami/Maven#54 2026-08-01 11:23:10 +02:00
Announce tick-inferred routines, opt-in and rate-limited

The restraint is well built. Off unless configured. sev1, so the ordinary care gate suppresses it. One per tick, one per cooldown. The body is pattern.PhraseRoutine rather than model output. That last one matters most: an inferred routine cannot arrive worded as something she never observed.

claude commented on pull request kami/Maven#53 2026-08-01 11:22:36 +02:00
Move the quiet-toggle and pattern-extraction slices out of voice.go (#321)

The extraction is clean, and quiet_toggle.go is better than the code it moved. Tokenising instead of reaching for \b is the right call. The comment explaining why Go's \b cannot see Cyrillic word boundaries is the kind of note that stops a rewrite into a regexp next year.

claude commented on pull request kami/Maven#51 2026-08-01 11:21:28 +02:00
Gate POST /api/chat on the same step-up as /tools (#317)

The gate itself is right. The four tests cover the shape that matters: fail-closed under -require-stepup, denied on an unasserted session, passing on an asserted one, fail-open by default. The route table comment in main.go is the most useful thing in the diff. It makes the next route's gate a decision rather than an oversight.

claude commented on pull request kami/Maven#52 2026-08-01 11:21:28 +02:00
Add a locked-down maven.<domain> block to the nginx template (#354)

The block is right in substance. Same bind and same ACL as the siblings. client_max_body_size 32m for PCM uploads, proxy_read_timeout 300s for a slow iGPU turn. The header says plainly that this file is the auth. The compose warning about building from sibling working trees is worth more than it looks.