Files
boxmaker/docs/plans/M6b/01-loopd-consult-registry.md
T
kyleandGrok 4.6 50e9cc2037 docs: M6b implementation plan
Six closed tasks for consult: registry, CONSULT_WAIT, [consult]/[secrets],
ToolName and grants, Decision body, loopback HTTP. Reference is the git bundle
~/boxmaker-refs/m6b-ref.bundle at 5fb05f0. Gate after task 06 is 1611.

Co-Authored-By: Grok 4.6 <noreply@x.ai>
2026-10-03 21:39:31 -07:00

7.2 KiB

M6b task 01: consult in the M5c registry, not core

Branch: m6b. Check it: git branch --show-current prints m6b and git status --short is empty; otherwise stop. Never switch branch. Commit subject: loopd: consult in the M5c registry, not core Log row: the Task cell is M6b/01-loopd-consult-registry.

First action. Run this before any Read of crate source. Do not ls crates/loopd/tests/. Do not Read tests/support/, turn.rs, session.rs, docs/implementer-log.md (except the first 12 lines at the log step). The signatures below are complete.

cp docs/plans/M6b/files/crates/loopd/tests/consult_registry.rs crates/loopd/tests/

Goal

consult is in Registry::m5c(), not core. find_tool finds it. A new session's epoch tools array stays clock, recall, memory, ask_memory, find_tool, call_tool (spec 4). loopd does not answer the call: dispatch already Ports every non-core name other than subagent to brokerd.

Every place that changes

Place What happens there
crates/loopd/src/consult.rs new: CONSULT, schema()
crates/loopd/src/lib.rs pub mod consult;
crates/loopd/src/tools.rs m5c() pushes the non-core entry after subagent
crates/loopd/tests/consult_registry.rs new, given
everything else no change: not dispatch, not broker_port.rs

Files

  • Copy, from docs/plans/M6b/files/ (the same path under it): the new test crates/loopd/tests/consult_registry.rs.
  • Create: crates/loopd/src/consult.rs (the module below).
  • Modify: crates/loopd/src/lib.rs, crates/loopd/src/tools.rs, docs/implementer-log.md.
  • Do not touch: any other file.

At the log-and-commit step, read only the first 12 lines of docs/implementer-log.md.

Facts you need

  • Not core. core_schemas() already filters e.core. A non-core Entry is found by find and by get, and is absent from Baseline.tools.
  • m5c() only. Do not add the entry to m2b, m3a, or m5a. loopd serve uses m5c.
  • push, after subagent. ask_memory stays at index 3. consult is last among the non-core names.
  • rustfmt mod order: consult after config / before cron as rustfmt decides.
  • Same-crate modules may import each other. This task's module imports nothing from turn or tools.
  • The items the edits use. This table is complete.
    Item Signature
    ToolSchema { name: String, description: String, parameters: serde_json::Value } in crate::llama
    Entry { schema: ToolSchema, core: bool }
    Registry::m5c m5c() -> Registry
    Registry::get get(&self, name: &str) -> Option<&Entry>
    Registry::find find(&self, query: &str) -> Vec<&ToolSchema>
    Registry::core_schemas core_schemas(&self) -> Vec<ToolSchema>

The edits, exactly

crates/loopd/src/consult.rs

Write this module. Do not add a wait constant, a parse, or a runtime (later tasks).

//! The `consult` tool: `brokerd` decides it and POSTs an allowlisted body (M6 spec, section 4).
//! It is not core; the parent finds it with `find_tool` and calls it through `call_tool`.

pub const CONSULT: &str = "consult";

pub fn schema() -> crate::llama::ToolSchema {
    crate::llama::ToolSchema {
        name: CONSULT.to_string(),
        description: "Ask a remote model a question. The session history is not sent. Needs a grant from the owner.".to_string(),
        parameters: serde_json::json!({
            "type": "object",
            "properties": {
                "question": {
                    "type": "string",
                    "description": "The question to send. Nothing else of the session is included."
                }
            },
            "required": ["question"]
        }),
    }
}

crates/loopd/src/lib.rs

L1. After pub mod config; add pub mod consult;. rustfmt decides the final order.

crates/loopd/src/tools.rs

R1. The lines (exactly once, inside m5c)

        entries.push(Entry {
            schema: crate::subagent::schema(),
            core: false,
        });
        Registry::new(entries)

become

        entries.push(Entry {
            schema: crate::subagent::schema(),
            core: false,
        });
        entries.push(Entry {
            schema: crate::consult::schema(),
            core: false,
        });
        Registry::new(entries)

Steps

  • 1. Copy the given test.

    cp docs/plans/M6b/files/crates/loopd/tests/consult_registry.rs crates/loopd/tests/
    
  • 2. See it fail. cargo build --tests --keep-going -p loopd, with a shell timeout of 600000 ms: test target consult_registry does not compile (E0432 unresolved loopd::consult). Every other target compiles.

  • 3. The edits. Write consult.rs, L1, R1. cargo check -p loopd prints no error and no warning. wc -l crates/loopd/src/consult.rs and wc -l crates/loopd/src/tools.rs each ≤ 500.

  • 4. The tests. cargo test -p loopd --test consult_registry --test subagent_registry --test ask_memory_tool --test tools --test baseline: every test passes, 2 in consult_registry.

  • 5. Check. git diff --stat lists exactly crates/loopd/src/consult.rs, crates/loopd/src/lib.rs, crates/loopd/src/tools.rs. git status --short also shows the new test as untracked.

  • 6. Run the gate. cargo fmt --all, then make gate, with a shell timeout of 600000 ms. Expected last line: gate: ok. That is done counting: 1592 (1590 before, plus the 2 of consult_registry.rs). After gate: ok, do not add up test result: lines and do not run cargo test --workspace.

  • 7. Log and commit. Add your row to docs/implementer-log.md; its Task cell is M6b/01-loopd-consult-registry. Read only the first 12 lines of that file; insert the row under the header. Stage with git add crates/loopd docs/implementer-log.md Cargo.lock, then commit as AGENTS.md says. Cargo.lock does not change in this task; the git add is harmless.

Done when

  • make gate prints gate: ok with 1592 tests.
  • git diff HEAD~1 --stat lists only crates/loopd/src/consult.rs, crates/loopd/src/lib.rs, crates/loopd/src/tools.rs, crates/loopd/tests/consult_registry.rs and docs/implementer-log.md.

Stop and report if

  • The branch check at the top fails.
  • A "before" block is not in its file exactly as shown, or is there more than once.
  • Step 2 shows a different result: the tests compile, or a different crate fails.
  • cargo check in step 3 prints an error or a warning. Quote it, and stop.
  • A test fails in step 4. Do not change the test: stop, and give the failing tests' names and their messages.
  • The fix seems to need a change anywhere else. It does not; stop and say why you think so.
  • A test outside consult_registry.rs fails in the gate: check once whether it fails without your change (git stash -u, run it, git stash pop), then stop and report both results.

What the given tests pin

consult is in m5c(), core is false, schema() matches the entry, find("consult") and find("remote") both hit it, subagent is still present, and a baseline assembled from m5c() still lists only the six core names in tools.