Files
boxmaker/docs/plans/M5a/17-memoryd-no-slicing.md
kyleandClaude Opus 5.5 64190c3701 M5a plan: task 16, the gate passes on macOS; the review's tasks become 17 to 20
The work moved to titan (macOS), where the gate failed for reasons older
than M5a: sockets under macOS's long TMPDIR pass its 104-byte limit,
gatewayd reads /proc/self for its uid, and /tmp is /private/tmp. Task 16
sets TMPDIR=/tmp for every process Cargo runs (.cargo/config.toml [env]),
has gatewayd take its uid from the owner of a pipe it makes (no dependency,
no unsafe), and hands over a toolkit shell.rs that compares resolved paths.
On a scratch tree the gate passes on titan and on talos with 936 tests, and
a wrong uid fails 7 gatewayd tests. Tasks 16 to 19 are renumbered 17 to 20.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 16:41:44 -07:00

110 lines
2.9 KiB
Markdown

# M5a task 17: `memoryd` takes the day and the month with `get`, not by slicing
**Branch:** `m5a` (run `git switch m5a`; `git status --short` must be empty, otherwise stop)
**Commit subject:** `memoryd: the day and the month of a time with get, never a slice`
## Goal
No behaviour change. Four files of `memoryd` cut the day (`2026-09-24`) or the month (`2026-09`)
out of `to_rfc3339()` with a slice such as `&rfc[..10]`. `AGENTS.md` forbids indexing that can go
out of range in library code. The time is always long enough, so none of these can panic today,
but two of them rely on that without a check. All five places become `str::get` with a fallback,
which cannot panic whatever the string is. Found in the M5a review (2026-09-24).
## Files
- Modify: `crates/memoryd/src/notes.rs`, `crates/memoryd/src/journal.rs`,
`crates/memoryd/src/review.rs`, `crates/memoryd/src/recall.rs`, `docs/implementer-log.md`
- No test changes: the existing tests cover every line changed.
## The edits, exactly
Nothing else in these files changes. Leave the comments above each line as they are.
**1. `crates/memoryd/src/notes.rs`**, in `minute`, the two lines
```rust
let head = if s.len() >= 16 { &s[..16] } else { &s };
format!("{head}Z")
```
become the one line
```rust
format!("{}Z", s.get(..16).unwrap_or(&s))
```
**2. `crates/memoryd/src/journal.rs`**, in `append`, the five lines
```rust
let day = if rfc.len() >= 10 {
&rfc[..10]
} else {
"0000-00-00"
};
```
become
```rust
let day = rfc.get(..10).unwrap_or("0000-00-00");
```
and, further down in the same function, the line
```rust
let month = &day[..7];
```
becomes
```rust
let month = day.get(..7).unwrap_or("0000-00");
```
Leave `&all[all.len().saturating_sub(count)..]` in `log` as it is: its start is never past the end.
**3. `crates/memoryd/src/review.rs`**, in `submit`, the line
```rust
let day = &rfc[..10];
```
becomes
```rust
let day = rfc.get(..10).unwrap_or("0000-00-00");
```
**4. `crates/memoryd/src/recall.rs`**, in `recall`, the line
```rust
let month = &rfc[..7];
```
becomes
```rust
let month = rfc.get(..7).unwrap_or("0000-00");
```
## Steps
- [ ] **1. Make the five edits.** Run `cargo fmt --all`.
- [ ] **2. Check none is left.** `grep -nE '\[\.\.[0-9]+\]' crates/memoryd/src/*.rs` prints
nothing.
- [ ] **3. Run the tests.** `cargo test -p memoryd`: every suite passes.
- [ ] **4. Run the gate.** `make gate`. Expected last line: `gate: ok`, with 936 tests, the same
as before this task.
- [ ] **5. Log and commit.** `git add crates/memoryd docs/implementer-log.md && git commit`
## Done when
- `make gate` prints `gate: ok`, and step 2's `grep` prints nothing.
## Stop and report if
- Any line quoted above is not in the file exactly as shown.
- Any test fails. This task changes no behaviour, so a failure means an edit is wrong; do not
change a test.