M5c-2 plan: task 01, workspace names up to memoryd's 512

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-28 16:59:35 -07:00
co-authored by Claude Opus 5.5
parent 2adcb734a5
commit cdd0a40207
2 changed files with 18 additions and 13 deletions
+13 -8
View File
@@ -21,7 +21,7 @@ tool), task 07 (`memoryd` answers it).
- **`question`**: required; 1 to 2,000 characters, counted as characters (`chars().count()`),
never bytes; a question of only spaces or newlines is empty.
- **`workspaces`**: optional; at most two names, none empty, none repeated, each 1 to 100
- **`workspaces`**: optional; at most two names, none empty, none repeated, each 1 to 512
characters of ASCII letters, digits, `_` and `-`. Missing, or `[]`, means the one workspace
`own`, the agent's own trusted one. Whether a name is one this agent's `[honcho]` configuration
has is **not** checked here: `memoryd` checks that in task 07.
@@ -66,10 +66,13 @@ This is the complete list.
earlier name is the same). A call with several faults is shown the first one.
- **Names are compared as written**: `fleet` and `Fleet` are two names (a Honcho name is
case-sensitive).
- **Why 100 characters.** `bxcore` has no rule for Honcho's names (`memoryd`'s config has its own,
which `bxcore` cannot use: `bxcore` depends on no other crate). The model names a workspace by
a short word (`own`, `untrusted`, `fleet`) or an agent's name; 100 characters is plenty and
keeps the name short enough to repeat in a refusal.
- **Why 512 characters.** The model names a workspace by a short word (`own`, `untrusted`,
`fleet`) or by another agent's name from `[[honcho.read]]`. `memoryd`'s config accepts an
agent's name of 1 to 512 characters of the same set (`honcho::config::MAX_NAME` and `is_name`
in `crates/memoryd/src/honcho/config.rs`), so the limit here is the same: every agent that
config allows can be asked. `bxcore` cannot use `memoryd`'s constant, because `bxcore` depends
on no other crate; do not add such a dependency. `brokerd` cuts a refusal it shows the model to
300 characters, so a long repeated name in a refusal is harmless.
- **Characters and bytes in a name.** A name's form allows ASCII only, so its length in bytes
(`len()`) is its length in characters; a name with any other character fails the form check
whatever its length.
@@ -143,8 +146,10 @@ pub const SEPARATOR: &str = "§";
pub const MAX_QUESTION: usize = 2_000;
/// The most workspaces one `ask_memory` may name: both are asked at once, inside `brokerd`'s wait.
pub const MAX_WORKSPACES: usize = 2;
/// The most characters of a workspace name in `ask_memory`.
pub const MAX_WORKSPACE_NAME: usize = 100;
/// The most characters of a workspace name in `ask_memory`. It matches `memoryd`'s rule for
/// Honcho's names (`honcho::config::MAX_NAME`), so every agent `[[honcho.read]]` allows can be
/// asked.
pub const MAX_WORKSPACE_NAME: usize = 512;
/// The workspace `ask_memory` asks when it names none: the agent's own trusted one.
pub const OWN_WORKSPACE: &str = "own";
```
@@ -345,7 +350,7 @@ Each of these changes to the finished code makes at least one given test fail (2
caught): the question checked without `trim`; its length in bytes; its limit moved by one
either way; the limit on names moved by one, or dropped; the repeat check dropped, comparing a
name with itself, or ignoring case; the empty-name sentence skipped; `.` allowed in a name, `-`
refused, non-ASCII letters allowed; the 100-character limit moved by one, or dropped; `asked`
refused, non-ASCII letters allowed; the 512-character limit moved by one, or dropped; `asked`
empty for no names, or out of order; unknown keys accepted; `workspaces` required; the empty list
left out when written; the names checked before their number; the tool's name; any sentence's
words.
@@ -26,7 +26,7 @@ fn the_name_and_the_limits() {
assert_eq!(ASK_MEMORY, "ask_memory");
assert_eq!(MAX_QUESTION, 2_000);
assert_eq!(MAX_WORKSPACES, 2);
assert_eq!(MAX_WORKSPACE_NAME, 100);
assert_eq!(MAX_WORKSPACE_NAME, 512);
assert_eq!(OWN_WORKSPACE, "own");
}
@@ -129,8 +129,8 @@ fn at_most_two_workspaces_each_named_once() {
/// Only the form is checked here; whether a name is one of `[honcho]`'s workspaces is `memoryd`'s
/// check.
#[test]
fn a_workspace_name_has_1_to_100_letters_digits_underscores_or_hyphens() {
let form = "a workspace name has 1 to 100 letters, digits, _ or -; use own, untrusted, fleet or \
fn a_workspace_name_has_1_to_512_letters_digits_underscores_or_hyphens() {
let form = "a workspace name has 1 to 512 letters, digits, _ or -; use own, untrusted, fleet or \
another agent's name";
for good in [
"own",
@@ -138,7 +138,7 @@ fn a_workspace_name_has_1_to_100_letters_digits_underscores_or_hyphens() {
"Boxmaker_1-trusted",
"x",
"-_-",
&"a".repeat(100),
&"a".repeat(512),
] {
assert_eq!(ask("q", &[good]).check(), Ok(()), "{good}");
}
@@ -152,7 +152,7 @@ fn a_workspace_name_has_1_to_100_letters_digits_underscores_or_hyphens() {
"é",
"own\n",
"a:b",
&"a".repeat(101),
&"a".repeat(513),
] {
assert_eq!(refused(&ask("q", &[bad])), form, "{bad:?}");
assert_eq!(refused(&ask("q", &["own", bad])), form, "second: {bad:?}");