Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Sections dated before 2026-09-19 predate the cycle and stay as they are. Named m

## Unreleased

- fix(wire-company-brain): **re-wiring a company brain works on macOS, and a rewrite that fails no longer reports "Updated"**: the block was handed to awk as `-v blk=…`, which BSD awk (macOS) refuses when the value holds a newline, so every re-run (a moved brain, a changed block) left the files untouched while printing `Updated: … rewritten in place`; the block now goes through the environment (`ENVIRON["BLK"]`), and a failed rewrite or append prints `FAILED: …`, leaves the file alone and is not counted. Pinned by `tests/wave2/test-company-brain.sh` T2c (a stub awk with BSD's `-v` rule; 4 of its 5 checks fail on 2ba8158) — reported in #598 from a field-run project, macOS 26 / BSD awk 20200816
- fix(doctor, sync-project, speed-setup): **doctor says when the speed fixes never reached a project**: `bin/exec.sh`, `bin/_common.sh` or `bin/lint-gate.sh` without the 2026-10-29 speed code (marker per file) gives a Machine health warning "speed fixes not active", and the Recommended fix leads with the exact `sync-project.sh --upgrade-bin ...` command (exec.sh always with its `_common.sh`; each copy backed up) before any other advice, because every other number measures the old scripts; `sync-project.sh` names the speed fixes on a hand-edited exec.sh / _common.sh that has the exit-code fix but not the speed work; `skills/speed-setup.md` has Claude show each local edit in one line and ask before replacing. Field: an English colleague's ExpenseTracker analysis after the toolkit update still showed a full mxbuild on every change (45.5 min, 57% of all exec time) with 15 drifted scripts in bin/; reproduced here with the real pre-#587 exec.sh / _common.sh / lint-gate.sh — doctor names all three, sync names exec.sh and refreshes the two unedited ones — Maurits (mauritscgvisser)
- fix(doctor, speed-setup): **doctor no longer says "None needed" next to a verdict of "5x slower"**: when process starts are fast but one bench step is 5x+ the reference and 2 s+ slower, the Recommended fix names that step (slow git status: `git config core.untrackedCache true` / `core.fsmonitor true`, no admin rights); a project inside a OneDrive / Dropbox / Google Drive / iCloud folder gets a Machine health warning and "move the project to a local folder" as the fix; low-memory advice now offers "restart the computer" before `--cleanup`; the bench's git step runs one untimed warm-up so a stale index after a copy or clone no longer reads as slow (field, ab-581/gk: 18.3 s cold, 31 ms warm); `skills/speed-setup.md` tells Claude never to say deno, mxbuild or helper process to a user. Field run: ab-581/gk on Linux, bench 14.7 s vs 10.9 s, "None needed" correctly; a project under a OneDrive path, move advice shown — Maurits (mauritscgvisser)
- fix(gate-check, gate-cache): **the closeout verdict cache also keys on file CONTENT, so an overwrite that keeps an old mtime (`cp -p`, `rsync -t`, `tar x`, `unzip`, `touch -d`) can no longer replay a stale verdict**: a signed triage.md copied over a FAIL one still printed the cached Stage 0 FAIL (PR #589 review); the cache now stores one `find | sort | xargs cksum | cksum` signature of the project files (skipping .git, node_modules, .mxtk, mprcontents, deployment, *.mpr, files over 1 MB) and any difference, or a signature that cannot be computed, re-evaluates; new `tests/wave2/test-gate-cache.sh` (hit, edit/delete/waiver miss, cp -p miss, TTL 0, 'not evaluated' line); `MXTK_GATE_CACHE_TRACE=1` prints `gate-cache: hit|miss` on --closeout. Field run: ab-581/base copy (197 MB, 633 hashed files) - signature 28 ms, cache hit 1464 -> 1498 ms vs 2567-2786 ms full evaluation - PR #589 reviewer, OlafFede (#583) — OlafFede (#583)
Expand Down
22 changes: 16 additions & 6 deletions bin/wire-company-brain.sh
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,24 @@ while IFS= read -r CL; do
tmp="$(mktemp)"
if grep -q "$BEGIN" "$CL"; then
grep -q "$END" "$CL" || { echo "$(basename "$CL") has a BEGIN marker but no END — fix by hand" >&2; rm -f "$tmp"; continue; }
awk -v b="$BEGIN" -v e="$END" -v blk="$block" '
index($0,b)==1 { print blk; skip=1; next }
# The block goes in through the environment, not -v: BSD awk (macOS) refuses a newline in a
# -v value, so every re-run failed there while still printing "Updated" (#598).
if BLK="$block" awk -v b="$BEGIN" -v e="$END" '
index($0,b)==1 { print ENVIRON["BLK"]; skip=1; next }
index($0,e)==1 { skip=0; next }
!skip { print }' "$CL" > "$tmp" && mv "$tmp" "$CL"
echo "Updated: ${CL#$PROJECT/} — company brain block rewritten in place."
!skip { print }' "$CL" > "$tmp" && mv "$tmp" "$CL"; then
echo "Updated: ${CL#$PROJECT/} — company brain block rewritten in place."
else
echo "FAILED: ${CL#$PROJECT/} — company brain block not rewritten; file left unchanged." >&2
rm -f "$tmp"; continue
fi
else
{ cat "$CL"; printf '\n%s\n' "$block"; } > "$tmp" && mv "$tmp" "$CL"
echo "Updated: ${CL#$PROJECT/} — company brain block appended."
if { cat "$CL"; printf '\n%s\n' "$block"; } > "$tmp" && mv "$tmp" "$CL"; then
echo "Updated: ${CL#$PROJECT/} — company brain block appended."
else
echo "FAILED: ${CL#$PROJECT/} — company brain block not appended; file left unchanged." >&2
rm -f "$tmp"; continue
fi
fi
rm -f "$tmp"
written=$((written+1))
Expand Down
35 changes: 35 additions & 0 deletions tests/wave2/test-company-brain.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
# block each, and a surface the project does not have is not created. Added 2026-09-20
# after an eval session read AGENTS.md/CLAUDE.md/PROJECT.md, never opened CLAUDE.local.md,
# and so never saw the company brain at all (retrieval 2/3 → 3/3 once this was fixed).
# T2c a re-point under BSD-awk rules (no newline in -v, as macOS awk) still rewrites in place,
# and a rewrite that fails prints FAILED, not Updated, leaves the file alone and is not
# counted (#598)
# T3 wire refuses an unshaped folder; wire on a project without CLAUDE.local.md refuses
# T4 check-no-private-citations: positive control (planted pointer) exits 1, clean tree exits 0,
# the toolkit's own templates/company-brain/ path is not a hit
Expand Down Expand Up @@ -62,6 +65,38 @@ r=$(grep -c "^$P " "$B/projects.tsv"); [ "$r" -eq 1 ] && ok "re-wire: still regi
B2="$WORK/acme-brain-2"; "$INIT" "$B2" >/dev/null 2>&1; "$BIN/wire-company-brain.sh" "$P" "$B2" >/dev/null 2>&1
grep -qF "$B2/ROUTING.md" "$CL" && ! grep -qF "$B/ROUTING.md" "$CL" && ok "re-point rewrites in place" || bad "re-point left the old path"

echo "== T2c: re-point under BSD-awk rules; a failed rewrite never says Updated (#598) =="
# macOS awk (one-true-awk 20200816) refuses a newline in a -v value ("newline in string"); gawk
# and mawk accept it, so the re-point above passes on Linux whatever the script does. This stub
# enforces the BSD rule and otherwise hands over to the real awk.
REAL_AWK="$(command -v awk)"; SB="$WORK/bsd-awk"; mkdir -p "$SB"
cat > "$SB/awk" <<STUB
#!/usr/bin/env bash
prev=""
for a in "\$@"; do
if [ "\$prev" = "-v" ]; then case "\$a" in *\$'\n'*) echo "awk: newline in string" >&2; exit 2;; esac; fi
prev="\$a"
done
exec "$REAL_AWK" "\$@"
STUB
chmod +x "$SB/awk"
B3="$WORK/acme-brain-3"; "$INIT" "$B3" >/dev/null 2>&1
out=$(PATH="$SB:$PATH" "$BIN/wire-company-brain.sh" "$P" "$B3" 2>&1)
grep -qF "$B3/ROUTING.md" "$CL" && ! grep -qF "$B2/ROUTING.md" "$CL" \
&& ok "re-point under BSD-awk rules rewrites in place" || bad "re-point under BSD-awk rules left the old path: $out"
# A rewrite that fails must not report success, and must leave the file and the count alone.
cat > "$SB/awk" <<'STUB'
#!/usr/bin/env bash
echo "awk: simulated failure" >&2; exit 2
STUB
chmod +x "$SB/awk"
before=$(cksum < "$CL")
out=$(PATH="$SB:$PATH" "$BIN/wire-company-brain.sh" "$P" "$B" 2>&1)
echo "$out" | grep -q "^Updated: CLAUDE.local.md" && bad "failed rewrite still printed Updated: $out" || ok "failed rewrite does not print Updated"
echo "$out" | grep -q "^FAILED: CLAUDE.local.md" && ok "failed rewrite is reported as FAILED" || bad "no FAILED line: $out"
[ "$(cksum < "$CL")" = "$before" ] && ok "failed rewrite leaves the file unchanged" || bad "file changed after a failed rewrite"
echo "$out" | grep -q "written to 0 instruction surface" && ok "failed surface is not counted" || bad "count wrong: $(echo "$out" | grep 'written to')"

echo "== T2b: the pointer reaches every instruction surface that exists =="
M="$WORK/multi"; mkdir -p "$M"
"$BIN/init-project.sh" "$M" --ignore-sources >/dev/null 2>&1
Expand Down
Loading