Skip to content

Ref writers for conversations and actors: namespaces, delegation, and closing the rest - #305

Open
nishu-builder wants to merge 1 commit into
claude/upbeat-cori-xk77fg-3-clifrom
claude/upbeat-cori-xk77fg-4-conversations
Open

nishu-builder wants to merge 1 commit into
claude/upbeat-cori-xk77fg-3-clifrom
claude/upbeat-cori-xk77fg-4-conversations

Conversation

@nishu-builder

@nishu-builder nishu-builder commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Moves conversations and actors into namespaces (design/ref-writers.md, "Conversations" and "Actors") and stops letting anything else through: a push outside refs/caos/w/<ns>/ is refused unless the ref is content-named or unguarded. Part 4 of 4, stacked on #304.

  • Conversations:
    • a head is refs/caos/w/<ns>/conversations/<hex id>/head, with <ns> fixed by the creator's key and the id, so a client finds its own without a lookup;
    • a subagent's head sits in its parent's namespace;
    • the sidebar moves to the writer's personal namespace;
    • across process boundaries a conversation is named by its address, <ns>/<id>: llm-step's --conversation, the X-Caos-Conversation header, and reader:@=… conversation=.
  • Actors: an actor's state branch moves to refs/caos/w/<ns>/actors/<name>. The caller puts writes=<ns> on the actor request, and std/actor's finish sends the run token that grants as a push option (caos-auth=run:<token>) on its raw receive-pack POST. The wrapper adds no writes to the inner's request. tests/actor and tests/actor-ref found a namespace with the test's token and hand writes=<ns> to what moves refs in it; tests/actor-ref also checks that an update without the token is refused.
  • Workers: llm-step asks to write its conversation's namespace and hands it to its subagents, relays and async tasks. llm-test-tool founds namespaces with its test's run token. std/caos-conversation-list reads heads and memberships from their namespaces and lists each conversation by its address.
  • caos-cli: writers takes a conversation as well as a namespace, conversation-ref <id|address> prints a head ref, and the TUI's /invite takes a public key.
  • Claude Code: cloud bootstrap takes --ref-writer-key, and drive conv finds a session's head in any namespace.
  • Suite: the client driving it signs as a fresh writer and hands --writes=* down to every test. Tests that pushed plain refs/heads/* now use a namespace or a content-named ref.
  • Docs follow (including std/actor/README.md, whose open question 5 this answers), and design/ref-writers.md is marked implemented.

Existing conversations under refs/caos/v3/ stay in the repository but are no longer listed; nothing moves them. The same goes for any actor state under refs/heads/actors/.

Verified here

  • cargo fmt --check, clippy -D warnings and cargo test pass, except launcher::checkout_import_completes_partial_history_and_keeps_local_edits, which fails the same way on main in this container.
  • llm-step, run-and-update-ref and llm-test-tool build and pass their tests.
  • Both lint scripts and nix build pass.
  • Against the built server and caos-cli, with two writers: a plain branch push is refused; one writer's conversation-ref finds the other's conversation by id; a push into it is refused until writers add <id>, and refused again after writers remove <address>.
  • std/actor, the actor tests and caos-conversation-list vet with the std/go prelude. Against a built server, a raw receive-pack update into a namespace reaches the hook with its push option: it is refused without one ("needs a caos-auth push option") and with an unknown token ("unknown run token"), both from a hand-built request and from std/actor's own setRef. The hook accepts the namespace commit the actor tests build.
  • caos-conversation-list's list(), run against a server seeded by caos-cli, lists conversations by address with their memberships.
  • tests/git-import/fixture.py passes every step up to a lost-reply fault-injection step that fails the same way on main in this container.

Not verified here

  • The caos-test suite, including every updated test and tests/actor/tests/actor-ref: caosd up can't fetch flake inputs from inside its containers in this sandbox.
  • An actor push that succeeds with a real run token: tokens are only minted when the server dispatches a job. The hook's handling of valid tokens is covered by Ref writers, server side: the pre-receive hook, run tokens, admission #303's tests.

Stack

  1. Propose ref writers: who may push a ref, and how jobs inherit it #298: design doc
  2. Ref writers, server side: the pre-receive hook, run tokens, admission #303: server
  3. Ref writers, client side: keys, namespaces and writers from caos-cli #304: caos-cli
  4. this PR: conversations and actors

🤖 Generated with Claude Code

https://claude.ai/code/session_01NzY2JJGk9nTMG6gu8dZXpc

… closing the rest

Conversations move into ref-writers namespaces (design/ref-writers.md), and
with them every ref the server lets through without a writer's proof: a push
outside a namespace is now refused unless the ref is content-named or
unguarded (refs/caos/dev).

- A conversation lives in refs/caos/w/<ns>/conversations/<hex id>/head, with
  <ns> fixed by its creator's key and its id; a subagent's head sits in its
  parent's namespace; the sidebar moves to a personal namespace. Across a
  process boundary a conversation is named by its address, <ns>/<id>
  (llm-step's --conversation, X-Caos-Conversation, reader:@= grants).
- llm-step asks to write its conversation's namespace and hands it to its
  subagents, relays and async tasks; llm-test-tool founds namespaces with the
  run token its test was granted.
- std/caos-conversation-list reads heads and memberships from their
  namespaces and lists each conversation by its address.
- An actor's state branch moves into a namespace,
  refs/caos/w/<ns>/actors/<name>: the caller puts writes=<ns> on the actor
  request, and std/actor's finish sends the run token that grants as a push
  option on its raw receive-pack POST. tests/actor and tests/actor-ref found a
  namespace with the test's token; actor-ref also shows a tokenless update is
  refused.
- caos-cli resolves a conversation's namespace (its own, or the one holding
  that id), `writers add` takes a conversation, `conversation-ref` prints a
  head ref, and the tui's /invite takes a public key. Cloud bootstrap takes
  --ref-writer-key.
- The suite signs as a fresh writer and hands --writes=* down to every test;
  tests that pushed plain branches use a namespace or a content-named ref.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzY2JJGk9nTMG6gu8dZXpc
@nishu-builder
nishu-builder force-pushed the claude/upbeat-cori-xk77fg-4-conversations branch from a9933c5 to edaa73c Compare October 6, 2026 02:18
@nishu-builder nishu-builder changed the title Ref writers for conversations: namespaces, delegation, and closing the rest Ref writers for conversations and actors: namespaces, delegation, and closing the rest Oct 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants