docs: hand off — what shipped, what is verified, and what is blocked
Seven commits this pass, all deployed. The handoff leads with the thing that will otherwise waste the next session's first hour: `glm-5.3` hit a hard z.ai quota on 2026-08-29 (code 1310, resets 09-04), it is the DEFAULT validator on both stacks, and the `ZAI_API_KEY` fingerprints are identical — so every mission declaring a `done_when` fails its evaluation on local and production alike, with its artifacts fully delivered and correct. That failure is not a bug to fix. `evaluator.rs:480` refuses to fall back to the agent's own provider because a same-family verdict would claim an independence it does not have. It is also NOT the malformed-prompt 429 we hit before: this one carries a code and a reset date. Records the validation run honestly rather than as a clean sweep. Three of four things confirmed live — `always_inject` delivering a body beside an index entry in one prompt, retrieval still firing through the door, the corrected gate installed and quiet against 23 body-free Bash calls, attribution 34/34. The fourth did not happen: those agents never delegated, so the subagent field is written and null, and the path that motivated it has still never been watched populating `mission_events`. A task that invites delegation does not force it; the next attempt should instruct it outright. Also carried forward: local test state that production does not share (`workspace-repo-commit-protocol.always_inject = true`, set by hand), the three fork items sitting behind one runtime image rebuild with tank offline, and two silent-discard defects found by sweep and left unfixed — `container_tool_hooks:: install`'s outcome is recorded nowhere, which makes "did this mission run gated?" unanswerable once the container is reaped. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01WZb5A2kfVfjpdwSochkuHz
This commit is contained in:
co-authored by
Claude Opus 5
parent
f26de3ba76
commit
daf8d12157
+113
-280
@@ -1,315 +1,148 @@
|
|||||||
# Where this left off — 2026-08-21 (second pass)
|
# Where this left off — 2026-08-29
|
||||||
|
|
||||||
Read `CAPABILITY-REVIEW.md` for the system picture,
|
Read `MISSION-EGRESS.md` for what a mission container can reach,
|
||||||
`TOOL-CALL-ARCHITECTURE.md` for how mission tools actually work, and
|
`UPSTREAM-SCAN.md` for the fork-vs-upstream position, and
|
||||||
`SKILL-USE-BASELINE.md` for the measurement — which now scores behaviour rather
|
`SKILL-USE-BASELINE.md` for the delivery measurement.
|
||||||
than the agent's own account of it.
|
|
||||||
|
|
||||||
## State of the tree
|
## Read this first — the judge is down until 2026-09-04
|
||||||
|
|
||||||
Local suite green: **108 test binaries, 815 tests** (`cargo test --workspace`).
|
|
||||||
**Pushed** — 22 commits, CI green on gw-04, deployed.
|
|
||||||
|
|
||||||
Eight measurement missions ran on the local stack
|
|
||||||
(`scripts/skill-use-run.sh`); all are held 90 days and re-scorable with
|
|
||||||
`--score <id>`.
|
|
||||||
|
|
||||||
## The premise of the last handoff's item 1 was wrong
|
|
||||||
|
|
||||||
It said the container-tier gate and tap were "proven locally and unproven in
|
|
||||||
prod", and told you to watch for the first production mission.
|
|
||||||
|
|
||||||
**Production has never run a mission.**
|
|
||||||
|
|
||||||
```
|
```
|
||||||
gw-04$ select count(*) from missions; -> 0
|
429 Too Many Requests
|
||||||
gw-04$ select count(*) from mission_events; -> 0
|
[1310][Weekly/Monthly Limit Exhausted. Your limit will reset at 2026-09-04 10:01:33]
|
||||||
```
|
```
|
||||||
|
|
||||||
Prod is armed correctly — server restarted with
|
`glm-5.3` is the default validator on **both** stacks — neither sets
|
||||||
`CLAWMATES_RUNTIME_IMAGE=clawmates-runtime:hooks`, image present. There is
|
`validator_model`, and the `ZAI_API_KEY` fingerprints are identical
|
||||||
simply nothing to watch. Prod auth is Clerk, so a mission cannot be launched
|
(`sha256[0:12] = 616fb5076696`). So **every mission that declares a `done_when`
|
||||||
from a terminal; someone has to click. Generalise the lesson: before debugging
|
will fail its evaluation on local AND production until the quota resets.**
|
||||||
why a deployed thing shows no evidence, check whether anything ran.
|
|
||||||
|
|
||||||
### A leaked mission container nothing can reap
|
The code is behaving correctly and this is worth understanding before "fixing"
|
||||||
|
it. `evaluator.rs:480` deliberately refuses to fall back to the agent's own
|
||||||
|
provider, because a verdict produced by the same family the agent ran on would
|
||||||
|
claim an independence it does not have. The phase stays unmet, says why, and the
|
||||||
|
sweep retries. Three retries, three identical 429s, then `failed`.
|
||||||
|
|
||||||
`cm-runtime-mission-019ff5b157ce77028f308ebd3dc92748` has been `Up` since
|
Unlike the subscription-OAuth 429 (which was a malformed system prompt), this one is REAL: it carries
|
||||||
**2026-08-12** on `clawmates-runtime:sync`, with no `missions` row behind it.
|
code 1310 and a reset date. Do not go looking for a malformed prompt.
|
||||||
|
|
||||||
`mission_runtime`'s terminal sweeper selects `FROM missions WHERE status IN
|
Options, with the trade stated:
|
||||||
(…)`, and `teardown_container(mission_id)` is only ever called with an id from
|
|
||||||
that query. Nothing enumerates Docker for `cm-runtime-mission-*` containers with
|
|
||||||
no matching row, so a container whose row is gone is invisible to every reaper.
|
|
||||||
Same shape as the earlier agent-container reap drift, different table.
|
|
||||||
|
|
||||||
**It was not idle.** Its checkout held **ten commits on a branch that had never
|
1. Top up the z.ai quota — restores the judge we actually measured.
|
||||||
been pushed** — +3451/-30 across 30 files, eighteen INT items on `clawhdf5`
|
2. Wait until 2026-09-04 — nothing else breaks; `done_when` phases just can't pass.
|
||||||
including AES-256-GCM, Ed25519 signing and HNSW batch insert. The remote had
|
3. Switch to kimi — available now, and our own eval found it produces FALSE
|
||||||
eight other `clawmates/*` branches and not this one.
|
POSITIVES including passing deleted tests. Worse than no judge. Not advised.
|
||||||
|
4. The Anthropic subscription judge — works, but same family as the agent, so
|
||||||
Handled: bundled and verified, branch pushed to git.redclaw.dev, confirmed on
|
the verdict loses the independence the design exists for.
|
||||||
the remote at the tip (`87039e9`), container removed. 57G → 59G free. The
|
|
||||||
bundle is kept at `/opt/clawmates/rescued/rescue-019ff5b1.bundle`.
|
|
||||||
|
|
||||||
`mission_runtime::sweep_orphans` now closes the gap, and **that container is
|
|
||||||
why it refuses to reap a checkout holding commits no remote has.** A reaper
|
|
||||||
that deleted on sight would have destroyed all of it silently, as its designed
|
|
||||||
behaviour. Every unanswerable case — docker will not date it, git will not
|
|
||||||
answer, the clock skewed — resolves to *do not reap*.
|
|
||||||
|
|
||||||
## What shipped this pass
|
## What shipped this pass
|
||||||
|
|
||||||
### The tool tap kept the name and discarded the argument
|
Seven commits on `main`, all deployed to gw-04 (server recreated
|
||||||
|
2026-08-29T02:07:48). Suite at the end: **108 binaries, 842 Rust tests, 92
|
||||||
|
frontend tests, tsc clean.**
|
||||||
|
|
||||||
The container tier's first measured mission recorded `Bash × 6` and not one of
|
### The gate's exfiltration rule matched a spelling production never writes
|
||||||
them said what it ran. `vm_tool_tap::parse` read `tool_input` to pull the path
|
|
||||||
out of it and dropped the rest, so every behavioural question about a phase was
|
|
||||||
unanswerable from a record that looked complete.
|
|
||||||
|
|
||||||
`Observed.input` now keeps it, bounded: file bodies become a byte count, other
|
`5a2ed8f`. One rule stood between an agent and sending the checkout off the
|
||||||
long strings truncate with a marker. **Host-side only, no image rebuild** — the
|
machine, anchored to a segment STARTING with `curl -X POST`. The tap held the
|
||||||
arguments were always in the tap file. `tool.call` also gained `detail.path`
|
answer: 166 curl invocations across two production missions, every one a GET,
|
||||||
(the World's SSE reads it and had been getting null on every container-tier
|
and every one beginning `curl -s`. The `-s` pushes the needle off position zero.
|
||||||
call) and `file.touch` gained `detail.abs`.
|
`curl -s -X POST … -d @secret`, `-d @file`, `-F`, `-T`, `--upload-file`,
|
||||||
|
`wget --post-file` — all allowed.
|
||||||
|
|
||||||
### Skill-Use is scored from actions
|
`Match::Carries` matches a segment that starts with the command and contains the
|
||||||
|
needle anywhere; `CarriesExact` exists for flags whose CASE is their meaning
|
||||||
|
(curl `-F` uploads, `-f` fails quietly, as in the ordinary `curl -fsSL`).
|
||||||
|
Segments are lowercased individually, not up front. All 158 recorded production
|
||||||
|
commands replay through the new script with **0 false positives**.
|
||||||
|
|
||||||
`skill_use::Evidence` carries `tool.call` rows alongside the narrative, and
|
### A subagent's tool calls are no longer credited to its parent
|
||||||
every check prefers them. `workspace-repo-commit-protocol`'s boundary was a
|
|
||||||
substring search for `/workspace/repo` in prose — an agent that wrote to the
|
|
||||||
wrong root **without narrating it scored a clean pass**. Two verdicts changed
|
|
||||||
for honesty: silence is `NotObservable` rather than `Pass`, and a test that ran
|
|
||||||
after the first write is undecidable rather than a failure.
|
|
||||||
|
|
||||||
**Trigger is still `NotObservable`, and half of its old reason is now wrong.**
|
`fe5c7d2`. Measured against the real claude binary, not reasoned about:
|
||||||
"`claude_cli` cannot surface a tool call" is false. What still holds is that we
|
|
||||||
**inline** skill bodies, so there is no retrieval to observe. The blocker moved
|
|
||||||
from the transport to the delivery model, and the door (§3) closes it with no
|
|
||||||
scorer change at all.
|
|
||||||
|
|
||||||
### Research phases are staffed by a research team
|
1. Subagent tool calls DO fire both hooks. `PreToolUse` blocked a subagent's
|
||||||
|
denied curl. **`Agent` is not a gate bypass.**
|
||||||
|
2. They carry the PARENT's `session_id` — which is why `attribute_sessions`
|
||||||
|
keeps working; a subagent never adds a session.
|
||||||
|
3. Only `agent_type`/`agent_id` tell them apart, and `parse()` read past both.
|
||||||
|
|
||||||
`research_only` — repo-less, one research phase — defaulted to `rust_sdlc`, so
|
The tap appends the raw payload, so those fields were always on disk. Host-side
|
||||||
it was staffed with a planner, coder, tester, reviewer and committer, four of
|
fix only, no image rebuild.
|
||||||
whom had nothing to do. New `topic_research` team, plus `default_phase_teams`
|
|
||||||
so a recipe can staff each phase *purpose* separately. Measured: 5 roles → 3,
|
|
||||||
14 skill deliveries → 4, 50KB of prompt → 24KB, and **1 of 9 delivered skills
|
|
||||||
applicable → 4 of 4**.
|
|
||||||
|
|
||||||
The scores barely moved, and that is the honest reading: what changed is that
|
### The rest
|
||||||
`not_applicable` now means "no machine-checkable consequence" rather than "this
|
|
||||||
skill had nothing to do with this phase".
|
|
||||||
|
|
||||||
Three existing research templates were also wrong in ways nothing checked.
|
- `bd7fd46` — a mission that cannot attach to `clawmates_edge` now FAILS to
|
||||||
`papers_research` bound **`arxiv-daily`** — a skill whose content is "do not
|
launch. `clawmates_core` is `internal: true` with no default route, so a
|
||||||
search arXiv yourself" — to the DOMAIN SCOUT, the role whose job is searching.
|
discarded attach error meant a mission running with zero egress while
|
||||||
Its PAPER READER was told to "fetch the PDF, extract text"; the runtime image
|
reporting success. **Behaviour change: it can now stop a mission starting.**
|
||||||
has no pdftotext, no mutool and no pypdf, so every paper would have hit the
|
- `2f1a870` — `skills.always_inject` (migration 0083). Delivery and scoring
|
||||||
`[read: abstract only]` fallback, which reads exactly like the fallback working.
|
both, because they are different mistakes.
|
||||||
`insight_research` cross-referenced "our repos'" history when a mission binds
|
- `f26de3b` — `agent.last_run`, the metric band's historical half.
|
||||||
one. `codebase_research` wrote to a vault that is not mounted.
|
- `fde1341`, `563b074` — the egress measurement and the upstream scan.
|
||||||
|
|
||||||
### The wrong repo path was in the team templates too
|
## Verified live, and one honest negative
|
||||||
|
|
||||||
The `/workspace/repo` guard was written against `skills/` only. The same path
|
A validation mission ran locally on the `index` arm
|
||||||
was in four team templates — including `rust_sdlc`, default for five of six
|
(`01a04f74-564b-7cd3-9b55-9d8f29d3e2f4`):
|
||||||
recipes, whose coder was told "your working directory is /workspace/repo". The
|
|
||||||
guards now walk one corpus: skills, team templates and recipes together.
|
|
||||||
|
|
||||||
### Two more skills contradicted the platform
|
|
||||||
|
|
||||||
Both found by reading the source of truth before writing a check against it —
|
|
||||||
which is the only reason they were found.
|
|
||||||
|
|
||||||
- `decompose-int-items` taught `PLAN_COMPLETE: INT-01..05`. Ids are strictly
|
|
||||||
`INT-<digits>`, so the range form is rejected and the plan pass records
|
|
||||||
nothing while every item stays open.
|
|
||||||
- `workspace-repo-commit-protocol` claimed the task-card parser advances mission
|
|
||||||
state on the INT id in your commit subject. **Nothing in the platform reads
|
|
||||||
commit messages** — `apply_for_run` reads `run_events`, the turn output.
|
|
||||||
|
|
||||||
`no_skill_shows_a_marker_the_parser_would_reject` guards the class, running the
|
|
||||||
real parser over every marker in every skill's fenced blocks.
|
|
||||||
|
|
||||||
### Trigger is measured, and the door is what made it possible
|
|
||||||
|
|
||||||
`skill_use` scores Trigger from `ReadMcpResourceTool` calls, parsed through
|
|
||||||
`mcp_skills::parse_uri` — the function that wrote the URI. Run 8, one mission,
|
|
||||||
one clean A/B:
|
|
||||||
|
|
||||||
| skill | delivered by | Trigger |
|
|
||||||
|---|---|---|
|
|
||||||
| `workspace-repo-commit-protocol` | retrieval | **pass** |
|
|
||||||
| `web-search-triage` | inlined | not observable |
|
|
||||||
| `structured-paper-summary` | inlined | not observable |
|
|
||||||
| `scientific-writing-conventions` | inlined | not observable |
|
|
||||||
|
|
||||||
Careful with what that proves: the retrieval was *instructed* by the task. It
|
|
||||||
demonstrates the instrument, not a spontaneous relevance judgement.
|
|
||||||
|
|
||||||
### Red-first is observable, and it needed neither ordering nor the diff
|
|
||||||
|
|
||||||
The previous version of this list said the TDD check needed the repository
|
|
||||||
diff. That was wrong, and `tdd-red-green-refactor` says why: *"Commit the
|
|
||||||
RED-to-GREEN pair as one commit."* The failing test and its fix land together
|
|
||||||
by instruction, so the diff and the commit history are as blind as tool
|
|
||||||
ordering already was.
|
|
||||||
|
|
||||||
The witness is what each run PRINTED, and the tap was discarding it. Claude
|
|
||||||
Code's `PostToolUse` payload carries `tool_response` (stdout/stderr/
|
|
||||||
interrupted) — verified against the binary. `bounded_response` keeps the END of
|
|
||||||
that output, the opposite of `bounded_input`, because a command's meaning is
|
|
||||||
its verdict and `cargo test` prints it last.
|
|
||||||
|
|
||||||
failing run then a passing one → Pass
|
|
||||||
every run failed → Fail
|
|
||||||
every run passed → NotObservable, because a test that never
|
|
||||||
failed is equally what a correct
|
|
||||||
implementation written first looks like
|
|
||||||
|
|
||||||
## The four days after that pass went into infrastructure
|
|
||||||
|
|
||||||
No product commits landed between 2026-08-21 and 2026-08-25. What did happen,
|
|
||||||
re-verified live on the 25th:
|
|
||||||
|
|
||||||
- `PasswordAuthentication no` is effective on gw-01/gw-02/gw-04 (checked with
|
|
||||||
`sudo sshd -T`, not by reading a config a drop-in can override), and
|
|
||||||
`fail2ban` is active on all three — **95 / 74 / 77 total bans**, so it is
|
|
||||||
catching real traffic. `ignoreip` must keep `100.64.0.0/10`: every operator
|
|
||||||
and every fleet node reaches these hosts from CGNAT space.
|
|
||||||
- gw-02's three Postgres containers were published on `0.0.0.0` and are now
|
|
||||||
bound to `127.0.0.1` (5434 mindbridge, 5435 clawbridge, 5437 smartclaw).
|
|
||||||
- Roughly 93G reclaimed; the largest single piece was a source-level leak of one
|
|
||||||
test database per test, fixed in `b58f034`.
|
|
||||||
|
|
||||||
Two failure shapes worth keeping:
|
|
||||||
|
|
||||||
- Recreating a DB container leaves the owning app holding **dead pool
|
|
||||||
connections**. The port binding reads perfect and the app still returns its
|
|
||||||
baseline status code, so a shallow check calls it done while every pool is
|
|
||||||
stale. Restart the owning unit and assert on the established-connection count.
|
|
||||||
- A `grep` for the service name matched `smartclaw-email` before `smartclaw`,
|
|
||||||
so the wrong unit was restarted. Only the connection count being `0` caught it.
|
|
||||||
|
|
||||||
**Open, and not safe to assume otherwise:** gw-02 has *no host firewall* —
|
|
||||||
`INPUT` policy `ACCEPT`, `DOCKER-USER` empty. Ports 18789/3000/3010/8082 are
|
|
||||||
bound `0.0.0.0` by native processes (a compose edit will not move them), and the
|
|
||||||
only thing keeping them off the internet is an upstream cloud firewall the host
|
|
||||||
cannot see. gw-05 and web-01 have no fail2ban and `sudo` there needs a password.
|
|
||||||
|
|
||||||
## Next, in order
|
|
||||||
|
|
||||||
1. ~~**Watch the first production mission.**~~ **Done — 2026-08-25.** Two were
|
|
||||||
launched from the UI (`ClawHDF5`, `JEPA Research`); `ClawHDF5` completed and
|
|
||||||
every mechanism from the previous two passes fired correctly the first time.
|
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
|---|---|
|
|---|---|
|
||||||
| skills door | installed — `api_origin()` derived the host from the server's own container id, first run outside where it was tested |
|
| `always_inject` | **CONFIRMED** — same prompt, same arm: `workspace-repo-commit-protocol` inlined as a full body, `scientific-writing-conventions` offered as a uri |
|
||||||
| staffing | `Topic Research`, 3 roles, 4 deliveries (not `rust_sdlc`'s 5/14) |
|
| retrieval still works | **CONFIRMED** — `ReadMcpResourceTool(uri="skill:global/web-search-triage")`; the flag did not collapse the arm |
|
||||||
| tap drain | **92** tool calls |
|
| the corrected gate | **CONFIRMED installed** — new rules present in the live container, node present, no inert marker, 0 denials against 23 body-free `Bash` calls |
|
||||||
| attribution | **92 of 92**, across a phase with TWO passes and six turns |
|
| attribution | 34/34, third perfect run |
|
||||||
| boundary | all 8 `Write`/`Edit` paths under `/mission/repo` |
|
| `subagent` column | written, all null — **correct**, no subagents spawned |
|
||||||
| delivery arm | `inline`, 0 retrievals — correct, prod leaves the env unset |
|
| **subagent path** | **STILL UNEXERCISED.** These agents did not delegate. The mechanism is proven against the real binary and unit-tested; it has never been watched populating `mission_events`. |
|
||||||
| judge | pass 0 `met=false` *"zero URLs — `grep -c http` returns 0"*; pass 1 `met=true` *"57 http references"* |
|
|
||||||
|
|
||||||
Two traps it surfaced. **The drain waits for the PHASE, not the pass** —
|
To close it: run one mission whose task EXPLICITLY instructs delegation. That is
|
||||||
a phase on its second pass reports `tool.call = 0` and looks broken while
|
what forces the path; a task that merely invites it does not.
|
||||||
being correct. And **an unfiltered diagnostic query is a time bomb**: a
|
|
||||||
`select ... from mission_events` with no `WHERE mission_id` was fine while
|
|
||||||
prod held one mission and silently wrong the moment a second launched. The
|
|
||||||
real drain is `WHERE phase_id = $1`; the sloppiness was in the diagnostic.
|
|
||||||
|
|
||||||
Unexplained and worth a look: one agent called the **`Agent` tool 4 times**.
|
## Open, in the order I would take them
|
||||||
Mission agents are spawning subagents, which nothing in our design accounts
|
|
||||||
for.
|
|
||||||
|
|
||||||
2. ~~**Measure Trigger properly.**~~ **Done — 2026-08-25.** `skill_delivery`
|
1. **The judge quota.** Everything with a `done_when` is blocked until it is
|
||||||
ships both arms; `index` sends name + `when_to_use` + a uri and the agent
|
resolved. See the top of this file.
|
||||||
fetches bodies through the door. Runs 9/10 in `SKILL-USE-BASELINE.md` are the
|
2. **Watch the subagent field populate.** One mission, task explicitly
|
||||||
A/B: identical task, one server process, and **the first retrieval this
|
instructing `Agent` use.
|
||||||
project has seen that the task did not ask for**. Each agent fetched the
|
3. **Confirm the last-run cards in the prod UI.** They read HISTORICAL data, so
|
||||||
skill bound to its own role and neither fetched another's. No Compliance
|
unlike everything else this pass they should work right now against the two
|
||||||
regression appeared — 34% fewer tokens, both arms judged met, deliverables
|
2026-08-25 missions. If blank, suspect the roster join: `agent_last_run`
|
||||||
slightly larger. n=1 per arm, so that is a signal and not a rate.
|
reaches agents via `team_members → mission_teams → missions`, so an agent no
|
||||||
|
longer on the mission's team will not resolve.
|
||||||
|
4. **Three fork items, all behind one runtime image rebuild.** Branch
|
||||||
|
`port/config-write-lock` on the zeroclaw fork carries upstream `841f28c7f1`
|
||||||
|
(cherry-picked CLEANLY despite being 331 behind; `handle_prop_put` — the
|
||||||
|
endpoint ClawMates writes through — now takes the lock). Not merged, not
|
||||||
|
deployed. Still to take: credential-fragment redaction (`eadaee0b62`) and
|
||||||
|
`/api/pair` lockout hardening (`47adb9863e`). Tank is offline, so the rebuild
|
||||||
|
has to happen on gw-04 and push to the web-01 registry.
|
||||||
|
5. **Mission egress remediation** — written up in `MISSION-EGRESS.md`,
|
||||||
|
deliberately NOT applied on the operator's call. A mission container reaches
|
||||||
|
the entire tailnet and host SSH.
|
||||||
|
6. **The 331-commit upstream merge.** 18 overlapping files; `claude_cli.rs`
|
||||||
|
cannot conflict (zero upstream files).
|
||||||
|
7. **Two silent-discard defects found by sweep, not yet fixed.**
|
||||||
|
`container_tool_hooks::install`'s outcome is discarded at both call sites and
|
||||||
|
recorded nowhere, so "did this mission run gated?" is unanswerable once the
|
||||||
|
container is reaped — and `PreToolUse` is now a security control, not just
|
||||||
|
telemetry. `vm_tool_gate::INERT_FILE` has no reader anywhere (low severity:
|
||||||
|
node v22 is in the image, so it cannot currently trigger).
|
||||||
|
|
||||||
What is left here is volume: run more pairs before believing any number, and
|
## State you should know about
|
||||||
decide whether `index` becomes the default. It is currently opt-in per
|
|
||||||
mission (`config.skill_delivery`) or per deployment
|
|
||||||
(`CLAWMATES_SKILL_DELIVERY`).
|
|
||||||
|
|
||||||
3. **Fold the microVM tier onto `container_tool_hooks`.** Two mechanisms for
|
- **Local DB has test state**: `workspace-repo-commit-protocol.always_inject =
|
||||||
one job is how they drift — the argument-discarding bug lived in the shared
|
true`, set by hand for the validation run. **Production has none set** —
|
||||||
parser precisely because nobody looked at it from the container side. The
|
`always_inject` is deployed, defaulting off, changing nothing until someone
|
||||||
microVM path also still passes no turn agents, so its tool calls stay
|
marks a skill.
|
||||||
unattributed. Blocked: the fleet has been offline for over a week.
|
- **No production mission since 2026-08-25.** Everything above is deployed and,
|
||||||
|
apart from the last-run cards, unexercised in prod.
|
||||||
4. ~~**Pull upstream's egress policy**~~ — **mis-scoped; see
|
- **Fleet offline 17 days** — `architect`, `morpheus`, `tank`; `nodes` table is
|
||||||
`MISSION-EGRESS.md` (2026-08-27).** `0db7d999a` guards ZeroClaw's own Rust
|
empty. microVM tier stays blocked.
|
||||||
HTTP paths (`link_enricher`, `domain_guard`, `plugins/egress`). `claude_cli`
|
- **`target/` is a symlink to `/Volumes/NVMeRAID`.** If it detaches mid-run,
|
||||||
spawns the claude binary as a subprocess, so a mission agent's `curl` never
|
cargo dies with SIGKILL and then `Not a directory`. It is the drive, not a
|
||||||
touches that stack. Pulling it hardens the CHAT tier and leaves mission
|
flaky test.
|
||||||
egress untouched — worth doing on its own merits, not as this fix.
|
|
||||||
|
|
||||||
What was measured instead: a mission container reaches the **entire tailnet**
|
|
||||||
and **SSH on its own host** (`clawmates_edge` supplies a default route; the
|
|
||||||
host runs tailscale; NAT does the rest). Postgres is reachable but
|
|
||||||
password-protected, and no DB credentials are forwarded. Remediation is
|
|
||||||
written down and **deliberately not applied** — operator's call was measure
|
|
||||||
and report.
|
|
||||||
|
|
||||||
5. **A narrow credential for the rest of the door.** `SCOPE_SKILLS_READ` covers
|
|
||||||
`/mcp/skills`. The `/mcp` door proper (`mcp_door.rs`) still authenticates
|
|
||||||
with a full session, and it is the one that can `delegate`. Nothing hands it
|
|
||||||
a token today; anything that does should not hand it a person's.
|
|
||||||
|
|
||||||
## Open decisions that are yours
|
|
||||||
|
|
||||||
- **Self-authoring scope.** Agents apply their own `skill_candidate` items with
|
|
||||||
no human click (`CLAWMATES_SKILL_SELF_AUTHORING=0` restores the gate).
|
|
||||||
`identity_refinement` and `brain_consolidation` still wait for a human,
|
|
||||||
because they change what an agent IS rather than adding a procedure it can
|
|
||||||
consult.
|
|
||||||
|
|
||||||
## Deliberately not done
|
## Deliberately not done
|
||||||
|
|
||||||
- **The mission executor swap.** Blockers are structural: `cm-runtime`'s `files`
|
- The mission executor swap — blockers are structural (see prior handoffs).
|
||||||
tool rejects absolute paths by construction, `shell` runs in a per-agent
|
- A tap for the direct-session tier — dormant, `CLAWMATES_MISSION_EXECUTOR`
|
||||||
sandbox with no mission mount, `ToolContext` carries no path or VM handle, and
|
unset in production.
|
||||||
approvals key on `(session_id, message_id)`.
|
- `cm-brain` offline tests — 6 of 9 need live `clawbrainhub.com`.
|
||||||
- **A tap for the direct-session tier.** Dormant —
|
|
||||||
`CLAWMATES_MISSION_EXECUTOR` is unset in production, so it never runs.
|
|
||||||
- **`cm-brain` offline tests** — 6 of 9 need live `clawbrainhub.com`.
|
|
||||||
- **Graph memory / `clawhdf5-agent`** — in the workspace manifest, used by no
|
|
||||||
crate.
|
|
||||||
|
|
||||||
## Operational facts that cost time to learn
|
|
||||||
|
|
||||||
- The Gitea **actions-log API returns 403** for the token in
|
|
||||||
`deploy/compose/.env`. A token with the `actions` scope remains the
|
|
||||||
highest-value thing to obtain.
|
|
||||||
- **gw-04 uses legacy `docker-compose`**, not the v2 plugin.
|
|
||||||
- **Do not build images by hand on gw-04 while CI may run** — same 150G volume,
|
|
||||||
and the frontend image build is what loses.
|
|
||||||
- The server reaches Docker through a **socket proxy** (`DOCKER_HOST`). Use
|
|
||||||
`container_exec::connect()`, never `connect_with_local_defaults()`.
|
|
||||||
- Prod auth is **Clerk**; the bootstrap password in `deploy/compose/.env` works
|
|
||||||
only against the local stack.
|
|
||||||
- Rebuilding the local server image is a **full Rust compile inside Docker**
|
|
||||||
(~8 min); the layer cache does not preserve `target/`. Budget for it before
|
|
||||||
any measurement that needs new server code.
|
|
||||||
- macOS has no `timeout(1)`.
|
|
||||||
|
|
||||||
## The recurring shape, now seven times over
|
|
||||||
|
|
||||||
**A claim in a comment or a doc, believed and never checked.** Every significant
|
|
||||||
finding this pass came from reading the source of truth — the parser, the
|
|
||||||
recipe, the production table — rather than the text describing it. The two new
|
|
||||||
skill contradictions were found *while writing checks against those skills*,
|
|
||||||
which is the cheapest place to catch them and the reason to always read first.
|
|
||||||
|
|
||||||
The corollary the measurement itself demonstrated: **its own first verdict was
|
|
||||||
wrong**, and scoring a research phase as a TDD failure would have buried the
|
|
||||||
real finding (item 1). A check that reports a system defect as an agent defect
|
|
||||||
is worse than no check.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user