Commit graph Huginn/crates/mind-body/src
Author SHA1 Message Date
Meta Vens
122a968f30 closing rule: acts without a commit close Recorded, Fixed names the merge or squash commit, the reminder bounds Recorded; each flush names its own reason
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 10:27:54 +01:00
Meta Vens
e47eec7e85 brief-done-means-landed: one closing rule for the Self run, told once at start; briefs and flush point to it
A brief that asks for a change closes Fixed by a default-branch commit, not Recorded on an open PR; work waiting on someone else is superseded by her own follow-up. Replaces the three 'Recorded with your answer' sentences.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 10:04:02 +01:00
Meta Vens
48e81bdf80 persona: the work tail names her plans as well as her open follow-ups
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 20:55:13 +01:00
Meta Vens
d386da81bc persona: the work question names her plans and memories, says open pages, and drops the messages clause from no-message lines
WORK_QUESTION also sends her to huginn query over her own plans, frames what she
finds as candidates she weighs, names --cursor, and says every follow-up in her
campaigns is hers whoever filed it. The messages clause is ANSWER_MESSAGES, set
before the question on first lines that carry messages only. Stale prose about
bare later lines is corrected in the body map, MESSAGES_HEADER's comment and one
test name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 20:46:11 +01:00
Meta Vens
e1636761f9 persona: every line asks what she is building; chat is answered as part of that work
WORK_QUESTION ends every first line, with messages or without, and sends her to
her own mind (huginn campaigns, open, unreported) and to start_self_run. WAKE_ASK
is now only the once-a-day new-thing opener before it. WORK_TAIL ends every later
line (plain, refused, stale, notices, Self replies). WAKE_QUESTION and
TRAFFIC_QUESTION are deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 20:29:50 +01:00
Meta Vens
8e2eb46522 mind-body: the moved-brief test carries the campaign it imports under
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 19:23:45 +01:00
Meta Vens
73e3c05af6 mind-body: the moved-brief test imports into a root with no native write
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 19:22:56 +01:00
Meta Vens
7e2f893439 huginn import tests: the history has four receipts under the root; the brief test uses the testkit's own instance
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 19:18:36 +01:00
Meta Vens
56df1ca31f mind-body: briefs a moved campaign carries are not her Persona's briefs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 19:18:35 +01:00
Meta Vens
c76e37280d huginn-mind: a Moved resolution freezes its campaign's root and the receiver replays the history as an import naming its source
The giver: (Campaign, Moved) joins the matrix; a Moved to this mind refuses MoveToSelf and a withdrawn Moved MoveIsFinal; any staged document rooted at a moved campaign, derived ones included, refuses CampaignMoved; Docs::closing_resolution reads every other document under the root closed by the Moved, and the image fans status_changed out so an earlier as_of still reads in force. The oracle derives the same fallback independently.

The receiver: PipelineProvenance.imported_from (optional, absent from every other receipt and from the digest) names the source receipt and the externals the batch cites. An import derives nothing, refuses its own instance, a Moved outcome, and an external this mind holds; a listed external stands in for an absent referent. mind-body persona.rs gains one outcome_words arm for the new variant.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 17:47:43 +01:00
91279f6496 Merge pull request 'mind-body: a nightly memory consolidation run for one Mind (typed Slept cut line)' (#14) from hands/eureka-body-sleep-turn-one-mind into main 2026-11-08 14:03:34 +00:00
Meta Vens
6aa5e01292 mind-body: the newest slept night's closing decides the day, not an older one's
A test with two slept nights pins that covered_through reads each night's own closing (the citation of its run), which no earlier test distinguished from the oldest Slept closing in force.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-08 14:24:07 +01:00
Meta Vens
7c9ccb9499 mind-body: the Sleep run is the night's memory consolidation only
SLEEP_GUIDANCE opens on 'Tonight you consolidate your memory.' and drops the contemplation paragraph; the night line closes on what she did with her memory, in the guidance and the schema's description. The module doc names the run the night's consolidation (rulings sleep-day-coverage-ruled, contemplation-own-session). A test pins that the start line carries the consolidation opening and that neither the guidance nor the schema invites her to think, read or look into anything.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-08 14:12:06 +01:00
Meta Vens
2e98327ded eureka-pipeline, huginn-mind, mind-body: a night's cut line is its typed Slept closing
ResolutionOutcome::Slept { line, day_through } is how a Sleep run ends when the ledger took her reply; day_through is the last memory of her day she was shown. CitationRole::DayThrough (day_through) makes the memory an A7 referent and a cites/cited edge; admission refuses Slept on any subject but a Sleep run, a day_through that is not a memory admitted before the batch, and skips the in-force check for that role since the night may have consumed it. The outcome alias carries Slept. sleep.rs close admits the typed outcome and covered_through reads only the Slept closing in force and day_through's admission ordinal: SLEPT, THROUGH and the rationale parse are gone, and a hand closing or a withdrawn Slept covers nothing. outcome_words renders Slept as 'slept: <line>'. Published schemas and the envelope golden regenerated from the derivation.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-08 14:07:22 +01:00
Meta Vens
ee5a4f92bb mind-body: a failed night after a slept one leaves the slept night's cover standing 2026-11-08 12:54:03 +01:00
Meta Vens
2291e90355 mind-body: the once-per-window test frees her unit and moves the clock, so only last_sleep spends the window 2026-11-08 12:13:57 +01:00
Meta Vens
9a0dfdd0e1 mind-body: sleep day tests follow one-night-at-a-time admission and second-grained times 2026-11-08 12:08:05 +01:00
Meta Vens
9981c5b902 mind-body: read a closing's reason as its line 2026-11-08 12:04:16 +01:00
Meta Vens
e3be529b1e mind-body: a night's day is anchored on the newest night that slept; the heartbeat's night rules are pinned
The day began at the previous Sleep run whatever became of it, so the memories past DAY_MAX and a failed
night's whole day never met the disposition cover-the-day requires. A night now closes with where its day was
covered through (the ordinal of the last memory it was shown), and the next day is what was admitted after the
newest night that closed 'slept:'; the first night's day is the 24 hours before it opened. A consolidation is
made by a night, whatever room it keeps, so it is not the next day's memory.

Night::from_settings carries the both-or-neither start check out of the binary where a test reaches it.
Tests pin last_sleep with the unit gone, the window's minutes and its 23 and 59 bounds, and the half-set start.
2026-11-08 12:03:18 +01:00
Meta Vens
cebac9d426 mind-body: a Mind sleeps once a night, in her Persona slot, disposing of her day by typed operations
The spawn prelude leaves one_process for a shared start_session. sleep.rs is the one owner of a night: the night line (her day whole, open items, the tide), SleepReply and its schema, the decoder's ledger (every day memory exactly once, ids her memories in force, one conversation per consolidation, told back, third refusal ends it), admission of whole operations in batches that never split a consolidation, and the closing of the run with her line. The heartbeat opens one Sleep run per listed idle Mind per window (HEARTBEAT_SLEEP_UTC, HEARTBEAT_SLEEP_MINDS); a missed night is not made up and a failed one not retried.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-08 11:01:39 +01:00
Meta Vens
79edda37f6 eureka-pipeline, huginn-mind: a Sleep turn shares the Persona slot, a consolidation is a pair
RunTurn gains Sleep and RunSlot/RunTurn::slot (PersonaTurn and Sleep hold the Persona slot, a Self run the other); live_holder, launch holders and the unit template compare slots, not turns. MemoryOrigin gains Sleep { run }. Admission refuses an unpaired consolidation both ways (MindRefusal::UnpairedConsolidation): a memory that consolidates others without a Superseded resolution of each by it in the batch, and a memory Superseded by memories that do not name it. Published schemas regenerated.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-08 11:01:39 +01:00
32bc2367da chat_image: the bounded read is its own function, with a test that fails without the take bound
load() refuses an over-cap file on its length first, so the take(MAX_BYTES + 1) on the read was
reachable only by a file that grew after that check and no test could see it. read_bounded holds the
read; its test grows a file past the cap and requires the read to stop at MAX_BYTES + 1.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-08 08:13:35 +00:00
cd15cae22c persona tests: the whole-line golden carries the image trust sentence
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 20:55:37 +00:00
4aeaf2d6e7 persona: an image's content is data, never instruction, in the messages header
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 20:54:57 +00:00
e2c9638f27 mind-body: a delivered chat image reaches her session as an image block
ChatDelivery gains tuple index 11, `image: Option<ChatImage>` ([path, mime,
size, sha256], a reference into her per-room image store, never bytes); the
pending kind is gamecult.persona.chat_pending.v2, and v1 answers and records
still decode with no image. chat_image::load is the one place a reference
becomes bytes: exact `<hex sha256 of room id>/<sha256>[.ext]` path with no
traversal or symlink, regular file, 5 MiB declared and actual, declared size
and sha256, png/jpeg/gif/webp magic bytes matching the declared mime. The
persona line carries the image as a base64 image block after its text and an
`attachment role=organ` line saying attached or not shown and why. The
stream-json echo of a line with blocks still counts as our echo. The store is
MIND_PERSONA_IMAGE_STORE; unset, every image is not shown.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 20:52:30 +00:00
Meta Vens
77ce0465ea stream: the proxy-environment test is an integration target, so the lib carries no environment read
Moves the_stream_agent_ignores_the_proxy_environment to crates/mind-body/tests/stream_proxy.rs, as control.rs carries its env-touching tests. It asserts through the public surface: with a proxy in the child's environment the stream's agent reaches its endpoint directly and follows no redirect, and a plain ureq agent in the same environment takes the proxy. No behaviour change.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 09:37:17 +01:00
Meta Vens
98a3741d4b stream: the binary's argument reader carries the reasoned allow its siblings carry
mind-stream reads its own arguments like the other binaries, which each allow the crate's disallowed-methods lint with a reason; one range assertion written as contains. No behaviour change.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 08:11:16 +00:00
Meta Vens
b90d84cd50 release-reply-path: two fixtures reconciled after the merges
A DM's room is its room id under the reply cut (the steward cut's hand-built DM delivery carried the alias form); a request after a result opens a turn under the task cut, so the resume cut's bound test closes that turn with a result.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 08:09:24 +00:00
Meta Vens
c1f7d7d8d9 Merge hands/eureka-body-stream-thoughts (e2e0488) into eureka-body/release-reply-path
# Conflicts:
#	crates/mind-body/src/persona.rs
2026-11-07 08:03:05 +00:00
Meta Vens
d920e8b171 Merge hands/eureka-body-project-name-addresses-steward (25502a5) into eureka-body/release-reply-path
# Conflicts:
#	crates/mind-body/src/persona.rs
#	crates/mind-body/src/persona/tests.rs
2026-11-07 08:02:11 +00:00
Meta Vens
8616cc2752 Merge hands/eureka-body-self-session-resume (46800b8) into eureka-body/release-reply-path
# Conflicts:
#	crates/mind-body/src/self_run.rs
#	crates/mind-body/src/self_run/decide.rs
#	crates/mind-body/src/self_run/decide/tests.rs
#	crates/mind-body/tests/public_surface.txt
2026-11-07 07:57:32 +00:00
Meta Vens
c5a2c68cb8 self: silent-stop kinds cover every kind the CLI queues nothing for on our stop; capture fixtures killshell and deadline-race; tests kill hand mutants H2 and H5
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 07:44:59 +00:00
Meta Vens
7c0313b068 self: a stop of ours owes no turn only for a shell task (task_type local_bash, Bash or Monitor); every other or unread kind owes its turn when stopped
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 07:48:13 +01:00
Meta Vens
62ce2ba12d self: idleness reads the CLI's own background-task level and its notification-to-turn rule; at idle the oldest waiting conversation goes first
Cut: State.tasks, Event::TaskStarted, the tool_use_id keying of task lines and the notification replay, and TaskNotified's tasks.remove gate. running is a copy of the CLI's last background_tasks_changed, replaced whole; a notification owes a turn when the task was backgrounded and the session did not stop it with TaskStop (or KillShell, KillBash: the stream shows the alias as the model named it); Polled and Inbox carry other_first, so a served conversation's newer brief no longer outruns an older brief of another. Fixtures bg-fgto, bg-kill and bg-monitor pin the three falsified cases; the probe's fake API gains a generic tool step and a timed scenario.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 06:48:03 +01:00
Meta Vens
625c171781 probe: background-task captures with the real claude 2.1.312 (bg-fgto, bg-kill, bg-monitor)
A foreground task moved to the background at its timeout, a task stopped with TaskStop, and a persistent Monitor; scrubbed to /probe/work, the key is the fake one.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 06:41:38 +01:00
Meta Vens
d655b59ce8 self: a session serves one conversation at a time; another conversation's brief is written only at idle, and every result belongs to the conversation being served
decide owns idleness (no turn open, nothing outstanding, no backgrounded task running, no notification owed its turn) and the switch of
conversation; read_usage reads the task lines for liveness only; the CLI's replay of a task notification is no echo of ours. SelfInbox
serves one Conversation and attributes a result by the span, not by the order of the stream. Deleted: briefless_open, briefless_answers,
turn_conversation, turn_allows, may_tell, one_conversation_told, note_task, tasks, notified, the Persona pointer line and its plumbing.
ScheduleWakeup and CronCreate are denied to the Self session. Tests replay the real-order captures with briefs spliced in.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 05:31:38 +01:00
Meta Vens
970086f6a0 probe: background-task captures with the real claude 2.1.312 (bg-idle, bg-fold, bg-other, bg-race, bg-agent, bg-late)
The harness runs the CLI against the fake Messages API with a fake key and a throwaway config dir: bg and agent plan steps, a
Monitor step, --disallowedTools through DENY. Captured: an Agent call with run_in_background gives task_started
(is_backgrounded true, the call's tool_use_id) and a task_notification with the same id; a background Bash ending while no turn is open
makes the CLI begin its own turn (init, a request, no echo); ScheduleWakeup and CronCreate are absent from the init tools when denied;
a Monitor is a backgrounded task with the same two lines, so it needs no denial. Host paths scrubbed to /probe/work.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 05:14:03 +01:00
Meta Vens
e2e0488abb stream: LF again; the stale boundary docs name the label as the gap's origin
Restores LF on stream.rs, stream/tests.rs and bin/mind-stream.rs (5defa18 converted them). Renames the capped-repo test for the rule built; build_seed's since is the newest thought's label tick time; STREAM_MIN_GAP_S counts from the label, so a model run of M seconds leaves 900 - M s of quiet after admission. No behaviour change.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 04:44:48 +01:00
Meta Vens
3402cb839d self: a notification is pending by its task's id alone and a turn that took in its conversation's briefs takes it in; tests for the survivors
A notification with no tool_use_id registers nothing (the open-turn gate still holds it by its request). Tests: the notified conversation's brief joins its turn, a notification of another conversation stays pending through a brief turn, two conversations' notifications open a turn no brief may join, an idle non-request line opens no turn, a resolved claim is read by its own key, a claimed cut spec stays on the start line.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 03:46:44 +01:00
Meta Vens
8bdb84d94b self: a briefless turn is open from a request with nothing echoed until its result; the start message states the routing rules
A request with no line of ours echoed is a turn that took in no brief, notification or not; until its result only the conversation it continues, or the notification's task's, is written. Nothing told yet means no other conversation exists.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 03:20:23 +01:00
Meta Vens
08a80697d3 self_run tests: the fake claude scripts that loop end when their stdin closes
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 03:16:27 +01:00
Meta Vens
a1370cf424 persona: a reply that cannot be placed is a text-free pointer in the public session
A reply that answers no brief, or briefs of two conversations, was read by nothing and re-paged on every Persona read. It is now a route in the public conversation marked as a pointer: the line carries the reply id and a fixed note, never its text, and the Persona reads the reply by id. Heard, it is resolved like any reply.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 03:16:27 +01:00
Meta Vens
7182ff107b self: a notification's result is its task's turn's; a briefless turn holds other conversations; a resolved claim's conversation is read by key
The stream's task_started and task_notification events carry the tool_use_id of the call that started the task. The actuator records, per task, the briefs the starting turn was answering; a briefless result after a notification answers those (any notification it cannot place answers none). While a notification's turn is open, only the conversation it is attributed to may be written. A restart reads a resolved claim's conversation by key and opens the gate for it alone. The flush result is the note to the successor, in the journal: it is no reply. The start message states the rules.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 03:16:26 +01:00
Meta Vens
5defa18afa stream: soul pass s2 fixes (thinking window, capped per repo, no proxy env, identical lines, forge read at gap marks)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 02:01:02 +00:00
Meta Vens
46800b8f8a self_run resume: a request with no echo before it is bounded by the result before it (kills the result-line mutant)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 01:20:51 +00:00
Meta Vens
70de8cfec2 stream: soul pass s1 fixes (stale repo news, userinfo bypass, reads, prompt version, poll cost)
- Repo activity is news only for events after her newest thought, and the notice is stamped with the event time; a capped repo counts only beside such an event.
- OllamaStream::open parses the URL as the HTTP client does and refuses userinfo, a path or a query.
- A thought's reads cite what the capped context sections kept.
- Every thought records prompt_version: Ghostlight revision, word budget, guidance and the continuer frame (thought.v2, not yet deployed).
- tick decides due-ness from responsibilities and news before building the seed or reading the persona.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 01:14:34 +00:00
Eureka Hands
4bc00e36f9 self tests: the gate follows the conversation of a line written and unechoed when a result arrives
Kills the conversation_of mutants (== to !=, body to None) that the previous pass left.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 01:08:45 +00:00
Meta Vens
25502a5e74 persona tests: her own row is in the addressing once, whatever the table holds
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 01:56:06 +01:00
Meta Vens
57592e3f7f address, persona tests: no hang on a self-overlapping name; the hash order, the fallback's own row and the poll's table refresh are pinned
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 01:28:09 +01:00
Meta Vens
54a89b94bf self_run resume: the kept conversation lives in the unit second state directory, outside her working directory; a resumed start consumes its record before spawning; the warm window counts from the line before a request
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 00:23:39 +00:00