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
50 changes: 50 additions & 0 deletions .claude/jit-context/paths/00-manual/00-README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,53 @@ ever indexed or injected.
fragment itself says "not chased further" and "worth a look if a second issue shows the same
shape." One incident, no known trigger pattern in this repo's own paths/tools/vocabulary to
match on. Revisit if a second issue repeats the same `could-not-classify` shape.

- **jit-misses-generic-words-v-escape** (2026-10-06, `trap.d/424.jit-misses-generic-words-v-escape.md`).
Checked against HEAD (bda0282): already fixed. `scripts/jit-misses.sh` now compares the
generic-word list by exact `FILENAME` membership in `isgenericfile[]`, built from
`ENVIRON["GENERIC_ARG_FILES_ENV"]`, not from a `-v`-decoded path -- the same ENVIRON technique
#437 used for `JIT_BASE`/`tools_base`/`vocab_base`, landed in `e0f8d39` (#437/#438). The
remaining `-v logfile=`/`-v genname=` sites are cosmetic display text only, exactly as the
fragment itself flagged.

- **rebuild-tsv-v-escape** (2026-10-06, `trap.d/424.rebuild-tsv-v-escape.md`). Two defects, one
outcome each. The `GENERIC_WORDS_FILE`/`wf` site: already fixed, same commit (`e0f8d39`,
#437/#438) -- `scripts/rebuild-tsv.sh` now splits `ENVIRON["GENERIC_WORDS_FILES"]` rather than
reading a `-v`-decoded `wf`. The `layerdir`/`bytesof()` site (the vocabulary byte-count
report): still true -- `layerdir` still reaches `bytesof()` via `-v layerdir=...` at HEAD.
Filed Digital-Process-Tools/claude-jit-context#475.

- **wrong-worktree-edits** (2026-10-06, `trap.d/437.wrong-worktree-edits.md`). A lesson about
forgetting a per-call `cd <worktree> &&` prefix, not a code defect. Declined here rather than
promoted: the mitigation the fragment itself names -- the supertool write op's own
`[branch: ...]` receipt line -- already surfaces exactly this after the fact, on every write,
for free. A jit-context reminder would have to fire on every `edit`/`paste`/`batch` call in
the whole repository (no ERE can tell "has a same-call `cd` prefix" from "does not" without
lookbehind) to catch the rare miss, which is a worse trade than reading the receipt that is
already there. See the parallel `tools/00-manual/00-README.md` entry for the tools-dimension
side of this same decision.

- **awk-pipe-failure-masked-by-or-true** (2026-10-06, `trap.d/459.awk-pipe-failure-masked-by-or-true.md`).
Checked against HEAD (bda0282): still true. `tests/test-no-heredocs-459.sh`'s
`detect_heredoc_lines()` still pipes `awk ... | grep -nE -- "$HEREDOC_PATTERN" || true`, so an
`awk` crash and a genuinely clean file still render identically. Non-blocking, narrow, one
test's own shape. Filed Digital-Process-Tools/claude-jit-context#478.

- **release-check-crash-reads-as-pass** (2026-10-06, `trap.d/461.release-check-crash-reads-as-pass.md`).
Checked against HEAD (bda0282): still true in both `tests/test-release-branch-461.sh` and
`tests/test-release-branch-437.sh` -- a `check_release_tree.py` crash with no `FAIL ` line
still reads as a pass in both. CI is covered separately; this is a local-run-only gap. Filed
Digital-Process-Tools/claude-jit-context#476.

- **release-equivalence-builds-head-not-source-ref** (2026-10-06,
`trap.d/461.release-equivalence-builds-head-not-source-ref.md`). Checked against HEAD
(bda0282): still true. `tests/test-release-branch-461.sh` still builds `--ref HEAD` while
`.github/workflows/release-branch.yml` publishes `$SOURCE_REF`, so a `workflow_dispatch` run
against an older ref still checks the wrong tree's equivalence. Filed
Digital-Process-Tools/claude-jit-context#477.

- **privacy-page-claims-vs-code** (2026-10-06, `trap.d/466.privacy-page-claims-vs-code.md`).
Checked against HEAD (bda0282): already fixed. All four claims (F1 opt-in scope, F2 the
120-byte field, F3 `bytes-shown-*` aging, F4 `jit_worktree_mismatch_line`'s own read) are
stated correctly in `PRIVACY.md` as it reads now, landed in `1db1603` (#466/#468) and
`7046d0a` (#466/#470).
4 changes: 4 additions & 0 deletions .claude/jit-context/paths/00-manual/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ Hooks read `.claude/jit-context/<dimension>/<layer>/00-index.tsv` — never the

One awk trap, measured on both `awk version 20200816` and `GNU Awk 5.4.1` because the two disagree: **`split()` on a one-character separator also splits on newlines** — one-true-awk does, gawk does not. Any walk over alternate fields (the single-quote split that lifts paths out of `supertool` arguments) then reads its arguments from the wrong side of the separator on one platform and not the other. Bracket the separator — `"[\047]"` — and awk compiles a regex, which splits on that character alone everywhere.

**A dynamic regex needs a doubled escape byte to put one literal backslash inside a bracket expression; a `/literal/` regex does not.** Building a bracket class at runtime (`qclass = "[" q1 q2 q3 "]?"` with `q3` built from one escape byte) and handing it to `match()`/`gsub()` as a STRING treats that lone escape byte as an introducer for whatever follows it — here, the class's own closing bracket — so the bracket never closes and the whole ERE fails to compile: `nonterminated character class` and exit 2, refusing every call for the rest of the session (one `common-awk.sh` extension cost 205 of 343 tests this way, #432). Build `q3` from two escape bytes instead of one; the escape-consuming pass then collapses them back to a single literal one inside the class, confirmed on one-true-awk under `LC_ALL=C` — not yet checked against gawk with the same construct.

**`in` is an awk reserved word, and a parameter or array named `in` compiles silently on both engines — no syntax error, just garbage downstream.** `function f(lines, n, in, i)` shadows the keyword `for (key in array)` uses, and neither gawk nor one-true-awk complains at parse time; every caller of that function then breaks with no error pointing at the cause (#442: 374/374 passing tests went to 163/374 on this alone, and a rename with no other change restored all of them). Treat `in` — and anything else that reads as a legal identifier but is actually a keyword or builtin, such as `getline`, `print`, `printf` or `length` — as reserved in a parameter or local-array list, not only at statement position.

**Never match a regex against a single character.** `c ~ /[A-Z]/` inside a `for` over `substr(s, i, 1)` is a multibyte decode, and one character of a UTF-8 string is one *byte* to one-true-awk: a lone continuation byte raises `towc: multibyte conversion failure`, which aborts the whole `END` block — the hook prints nothing and still exits 0, so it reads as having had nothing to say. Measured: `détail de la facturation` matched no vocabulary entry under `awk version 20200816` and matched under gawk. Use `index("ABC…XYZ", c) > 0` instead; it is a byte search with no decode, and no byte of a multibyte sequence is ever an ASCII letter or digit, so the verdict is unchanged. Mind that `index(s, "")` returns 1 — an empty operand needs its own guard.

**The hook awks run under `LC_ALL=C`, and that is load-bearing.** The rule above is about one character; this is its whole-record neighbour. A `tolower()` or `gsub()` over a record that is not valid UTF-8 aborts one-true-awk's `END` block with `illegal byte sequence` — nothing on stdout, not even `{}`, the diagnostic in the session, exit 0 — and makes gawk print `Invalid multibyte data detected` (#68). A lone `0xE9` from a Latin-1 paste, or a sequence cut at a copy boundary, is enough; on the tool hook it defeated a `block` rule. Under `C` both engines read bytes and have nothing to decode. The cost is that `tolower()` no longer folds non-ASCII, which is why the Latin-1 table in `JIT_AWK_FOLD` carries **both** cases: a fold table that only lists lowercase forms is dead under `C`. Check any new normalisation against that table rather than assuming, and keep the pin on the `awk` invocation — `rebuild-tsv.sh` has the opposite contract and its own locale.
Expand Down
12 changes: 12 additions & 0 deletions .claude/jit-context/tools/00-manual/00-README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,15 @@ so nothing here is ever indexed or injected.
upstream as `Digital-Process-Tools/claude-oss#1042`. Until it lands, follow every
`--apply` with `CLAUDE_PROJECT_DIR="$PWD" bash scripts/rebuild-tsv.sh` and commit both
files.

- **wrong-worktree-edits** (2026-10-06, `trap.d/437.wrong-worktree-edits.md`). A `supertool
edit`/`paste`/`batch` call sent without its own `cd <worktree> &&` prefix landed in the main
clone instead of the worktree a task was meant to edit -- caught only by a later fixture run
behaving as if the old code were still there. Declined rather than promoted: there is no ERE
that can distinguish "this call already has a same-call `cd` prefix" from "it does not"
without lookbehind, which awk's dialect does not have (per `paths/00-manual/entries.md`), so
the only matchable rule here would fire on every `edit`/`paste`/`batch` call in the whole
repository, correctly-prefixed ones included -- noise on every legitimate call to catch a rare
miss. The op's own `[branch: ...]` receipt line already names which branch a write landed on,
checkable after the fact on exactly the calls that need it. See the parallel
`paths/00-manual/00-README.md` entry for the same decision.
30 changes: 0 additions & 30 deletions trap.d/424.jit-misses-generic-words-v-escape.md

This file was deleted.

31 changes: 0 additions & 31 deletions trap.d/424.rebuild-tsv-v-escape.md

This file was deleted.

30 changes: 0 additions & 30 deletions trap.d/432.dynamic-regex-bracket-backslash.md

This file was deleted.

21 changes: 0 additions & 21 deletions trap.d/437.wrong-worktree-edits.md

This file was deleted.

17 changes: 0 additions & 17 deletions trap.d/442.awk-in-is-reserved.md

This file was deleted.

24 changes: 0 additions & 24 deletions trap.d/459.awk-pipe-failure-masked-by-or-true.md

This file was deleted.

Loading
Loading