Files
command-center/agent/managed-skills/locale-c-multibyte-awk-silent-loss/SKILL.md
T
Frank 8af40c402b chore(agent): commit the machine tier and the doctrine text the checkout was already running
Landing blocker for #61 and #63: the deployment checkout is 12 commits behind and
`merge --ff-only` refuses while tracked paths are dirty. Discard is not available here
(workspace policy: no `checkout`/`stash` on shared state), so the dirt is committed.

- `agent/APPEND_SYSTEM.md`: the point-of-use / one-work-log / PR-link doctrine, already
  byte-identical to `origin/main` (`cmp` against the trunk blob: no difference). No new
  prose — the commit exists so the trunk merge can proceed.
- `agent/config.yml` and `agent/managed-skills/**`: the machine-live tier the heartbeat
  owns (AGENTS.md § Live-sync tiers).

`ALLOW_SECRETS=1` was used, deliberately and after auditing the staged diff by hand: the
only credential-shaped strings in it are two copies of `AKIA0000000000000EXAMPLE` — the
inert all-zero AWS example id — and they appear inside the two skill pages that teach
that exact placeholder shape. This checkout is still running the pre-#61 hook; the merged
gate (value-scoped placeholder filter, `71601f7`) exempts this value, so the refusal
dies with this landing. No `--no-verify` was used: the gate ran and its verdict is
recorded here.

Refs #61
2026-10-21 01:44:51 -07:00

3.1 KiB

name, description
name description
locale-c-multibyte-awk-silent-loss Debug generated output that silently loses data under LC_ALL=C — a regex quantifier on a multibyte character in awk/grep, plus the locale-dependent red test it produces.

LC_ALL=C kills multibyte regex quantifiers — silently

Symptom: a generator emits a complete, exit-0, missing-a-third-of-the-page artifact in cron / systemd user units / agent shells, and the same command looks perfect in the user's terminal. Companion symptom: a repo test is red for the agent and green for the operator.

Probe (do these in order, they are 5 seconds apart)

echo "LANG=[$LANG] LC_ALL=[$LC_ALL]"   # LC_ALL overrides LANG — en_US.UTF-8 + LC_ALL=C is byte-wise
locale -a | grep -iE 'utf-?8' | head    # which UTF-8 locale actually exists on this box

Then test the suspect pattern alone, under both locales, with the literal character:

printf '%s\n' '    // ─── Applications ───' | awk '/─+ / { print "QUANT MATCHED" }'
printf '%s\n' '    // ─── Applications ───' | awk '/─/    { print "LITERAL MATCHED" }'
printf '%s\n' '    // ─── Applications ───' | LC_ALL=C.utf8 awk '/─+ / { print "QUANT MATCHED under UTF-8" }'

Literal matches everywhere; the quantifier matches only under a UTF-8 locale. That asymmetry IS the bug: gawk under LC_ALL=C matches bytes, so ─+ means "the last byte of U+2500, repeated" — a byte sequence that never occurs. mawk/busybox/Go regexp have the same class of failure (quantifier or bracket class spanning a multibyte char).

Fix

Match and strip the multibyte literal with no quantifier:

/^[[:space:]]*\/\/[[:space:]]*─/ {          # literal gate
  s = $0; sub(/^[[:space:]]*\/\/[[:space:]]*/, "", s); sub(/[[:space:]]+$/, "", s)
  if (s ~ /─ .*─/) { gsub(/─/, "", s); gsub(/[[:space:]]+/, " ", s); sub(/^ /, "", s); ... }
  next
}

Never pin LC_ALL=en_US.UTF-8 to "fix" it — that locale often does not exist (a CachyOS box here shipped only C.utf8), so the script then breaks on another machine. Make the matcher byte-safe instead.

Pin it with a test

run env LC_ALL=C "$GEN" "$IN" + assert the lost content is present. The operator's UTF-8 terminal can never catch this class of bug, so the explicit C-locale run is the only durable guard.

Suite-verification law (how this got missed)

NEVER judge bats tests/ from tail output — a failure at test 28 is invisible in a 25-line window ending at test 109. Always:

out=$(bats tests/ 2>&1); echo "$out" | grep -cE '^ok'; echo "$out" | grep -E '^not ok' || echo GREEN

Run it under LC_ALL=C too: that is the environment every automated caller inherits. Same rule for | grep -c on a multi-line JSON field — count what you claim to have counted.

  • bats-assertion-trust — vacuously-passing assertions (green that proves nothing). This skill is the mirror case: correct assertions that are only red in one locale.
  • gitea-pr-api-cycle — unrelated; landed here only because the PR work is where this surfaced.