Commit Graph
18 Commits
Author SHA1 Message Date
bmottin 740c3d8c3e Merge chore/gitleaks-allowlist-runtime-state into develop 2026-09-15 22:04:36 -04:00
bmottin e59e26890e chore(gitleaks): allowlist Claude Code daemon roster + per-session keys
`make scan-secrets` flagged 4 generic-api-key hits in ~/.claude, all written
by Claude Code itself: roster.json's rendezvousSock/ptySock unix-socket paths
and sessionId UUID (long, high-entropy, not credentials), and two per-worker
session keys (0600). Same class as the ide/*.lock entry above — machine-local,
ephemeral, and unreachable from a commit: link.sh exposes exactly seven repo
symlinks under ~/.claude and neither daemon/ nor sessions/ is among them, so
`git ls-files` can never see them.

Left unfixed they would redden every sweep, which is the failure mode the
.env entry already argues against — a permanently red scan stops being read.

Scoped to the two exact filenames rather than the directories, and verified:
fake secrets planted beside them in the same dirs are still caught, and the
repo's own history stays clean (745 commits, no leaks).
2026-09-15 22:01:50 -04:00
bmottin 98a8322010 Merge chore/correct-blk022-flaky-baseline into develop 2026-09-15 21:47:19 -04:00
bmottin 91ea02d990 chore(memory): correct BLK-022 — gitflow-test.sh is flaky, the before/after was noise
I recorded "92/14 on pristine develop vs 93/13 after — nothing worsened, one
case better". Three consecutive runs on one unchanged tree give 90/16, 92/14,
92/14: the suite is non-deterministic and both figures were single samples of
that spread. The port is indistinguishable from the noise; claiming an
improvement was false precision.

Surfaced because the post-merge run reported 90/16 and looked like a
regression. It was not — but the only reason the question could be settled
was re-running, which is exactly what the original claim had skipped.
2026-09-15 21:45:47 -04:00
bmottin 2e94538698 Merge chore/macos-port-capitalize into develop 2026-09-15 21:43:09 -04:00
bmottin 0909f38742 Merge chore/graphify-0.9.16 into develop 2026-09-15 21:43:09 -04:00
bmottin 24066d761c Merge chore/sweep-bdr019-makefile into develop 2026-09-15 21:43:08 -04:00
bmottin 1663b09bc5 Merge bugfix/macos-installer into develop 2026-09-15 21:43:07 -04:00
bmottin 09727c7f8a Merge bugfix/macos-gnu-coreutils into develop 2026-09-15 21:43:07 -04:00
bmottin 785e7922c5 Merge bugfix/macos-bash32-portability into develop 2026-09-15 21:43:06 -04:00
bmottin 1da870bd67 Merge bugfix/url-guard-ssrf-bash32 into develop 2026-09-15 21:42:56 -04:00
bmottin d8e516e976 chore(graphify): sync skill marker to 0.9.16
`graphify install` regenerated the skill files against the installed 0.9.16
CLI; only `.graphify_version` moved — SKILL.md and both references are
byte-identical to what 0.9.15 already shipped, so this clears the CLI's
"skill is from graphify 0.9.15, package is 0.9.16" warning with no content
change to review.

CLAUDE.md was clobbered by the installer (it appends its own `# graphify`
section) and restored from a pre-run snapshot, per BDR-028.
2026-09-15 21:40:07 -04:00
bmottin 66012a97a7 chore(memory): BLK-021/022, LRN-150/151, BDR-088, EVAL-029 — macOS port
Capitalizes the macOS port and the gstack Chromium deadlock, plus an
append-only correction to BLK-008 / LRN-038: their "ubuntu24.04 fallback
build" cause is refuted — macOS arm64 has a native Playwright 1.58.2 build,
no fallback, and the same hang reproduces. The real variable was the Node
version, and that wrong record misdirected this investigation for an hour.

EVAL-029 records two process failures worth keeping: the first fix
recommendation (pin node@22) was reversed only because the user asked
whether the browser was current — staleness had gone unpriced; and the grep
sweep returned empty twice while defects were present, once to `set -e`,
once to a pattern that could not match `${1,,}`.

Index rows added for all four registries. Pre-existing index drift
(BLK-018..020, LRN-144..149) left alone — backfilling means summarising
entries someone else wrote.
2026-09-15 21:39:22 -04:00
bmottin b2ec97889f chore(make): drop disable-model-invocation from the new-skill template
BDR-019 stripped the key from all 27 skills because `true` blocks model AND
orchestrator routing — silently breaking the routing CLAUDE.md describes —
while `false` was a no-op noise line. The scaffold kept injecting `true`, so
every skill created with `make new-skill` would have shipped unroutable.

doctor.sh already covers the other half upstream: its check was inverted to
warn on REINTRODUCTION rather than on absence, which is what surfaced this —
a new skill from the template would now trip that very guard.
2026-09-13 17:21:30 -04:00
bmottin 28211a78ea fix(install): unblock the installer on macOS — BSD sed, and a deadline on Chromium
Two independent failures, both of which stopped `make plugin` outright here.

GNU `sed -i` takes no suffix argument; BSD sed requires one and reads the
script as that suffix, so all three calls errored — and under `set -euo
pipefail` that aborts the installer. They go through a temp file now, written
back with `cat >` so the profile keeps its mode and owner.

While rewriting them: the orphan-comment cleanup `{N; /^\n$/d;}` could never
match on ANY platform — after N the pattern space starts with '#', so the
^\n$ anchor pair never applied. It was a silent no-op, now awk, and tested on
/bin/bash 3.2: both obsolete entries and their stranded headers go, the live
entry and the user's own lines stay, idempotent on re-run.

The second failure was worse because it was invisible: gstack's ./setup runs
`bunx playwright install chromium` unbounded, and Playwright 1.58.2 deadlocks
on Node 26 mid-extraction — both processes idle at 39/333 files, no error, no
progress, forever. That silently cut the 2026-09-13 run at step 2 of 10.
Chromium is now installed here instead, under a 900s deadline; on timeout the
installer bumps gstack's Playwright (its package.json declares "^1.x", so a
minor bump is in range) and retries once, then warns rather than aborts —
gstack is OFF by default and only its browser depends on this.

`timeout` is not in a stock macOS, so the deadline is pure bash. Proven by a
forced hang: rc 124 in 6s, no orphaned oopDownloadBrowserMain, stderr clean.
2026-09-13 17:21:23 -04:00
bmottin a4565c80c3 fix(portability): stop assuming GNU coreutils flags on macOS
BSD userland rejects or silently ignores several GNU spellings the repo used:

- `timeout` is not in a stock macOS at all (Homebrew installs it, and also as
  `gtimeout`). Without it every gates.sh check exited 127 and was recorded
  NOT-MET whatever the check actually did — a systematic false negative.
  The binary is now resolved once, with a pure-bash deadline behind it so the
  124 contract still holds where neither binary exists. GATES_TIMEOUT_BIN is
  overridable with `-` not `:-`, so an empty value forces that fallback: the
  suite passes 64/64 both ways, timeout cases included.
- `touch -d '10 days ago'` is GNU-only; perl's utime is the one spelling both
  platforms ship.
- BSD `wc -l` pads its count with leading spaces, so string compares failed as
  got[      48] want[48].
- `sed -i` needs a suffix argument on BSD AND does not expand \n in the
  replacement, so the release-candidate CHANGELOG edit silently did nothing
  and the assertion failed for the wrong reason. Rewritten in awk; the RC_TAG=0
  mode still REDs on the absent tag, so the test keeps its teeth.
- `/bin/grep` does not exist on macOS (grep lives in /usr/bin), and `stat -c`
  is GNU-only.

fast-libs 11/11, seo-data 221/221, release-candidate 5 GREEN / 0 RED.
2026-09-13 17:21:09 -04:00
bmottin f3919b6ace fix(portability): replace bash 4 builtins absent from macOS bash 3.2
macOS ships bash 3.2 as /bin/bash, which `#!/usr/bin/env bash` resolves to
when no newer bash is on PATH. Two builtins the repo relies on do not exist
there, and both failed SILENTLY:

- `mapfile` in the three surgical-commit helpers left every array empty, so
  the scope guards passed on nothing (fail-OPEN) and the commits degraded to
  "nothing pending — no-op" while reporting success. deploy-commit.test.sh
  went 4/16; memory and doc commits simply never happened.
- `declare -A` in the session-start hook errored on every session and left
  each plugin cost at 0, so the passive-budget warning could never fire.

`_read_lines_into` is the portable equivalent of `mapfile`, space-safe and
resetting its target first — expanding a never-assigned array trips `set -u`
on bash < 4.4, which is how the empty arrays surfaced as "unbound variable".
Plugin costs move to a `case`.

source-scope.sh's header prescribed `mapfile` to its callers; it now shows
the read loop, and its own test plus run-reconcile.sh stop using the builtin.

deploy-commit 16/16, source-scope 34/34, run-reconcile 25 GREEN / 0 RED,
session-start stderr empty.
2026-09-13 17:20:57 -04:00
bmottin 5efc506197 fix(url-guard): restore the SSRF guard on bash 3.2
`${1,,}` is bash 4.0+. macOS ships bash 3.2 as /bin/bash, where it raises
"bad substitution"; the subshell then exited 1 — read as "not local" — so
`url-guard.sh host` returned rc 0 for localhost, 127.x, 10.x, 192.168.x,
172.16-31.x, 169.254.169.254 and metadata.google.internal. The guard failed
OPEN on every Mac, and url-guard.test.sh recorded it as 13 "got[0] want[2]".

`shopt -s nocasematch` (bash 3.1+) keeps both the ASCII-only folding that
LC_ALL=C gives and the no-fork property the lowercase expansion had.

Verified on /bin/bash 3.2: the ten local/private/metadata targets now return
rc 2 (case-folded variants included), legitimate hosts still rc 0.
2026-09-13 17:20:43 -04:00