Skip to content

fix(harvest-learnings): a bug-log heading the toolkit log carries is not drafted again when it has ~ * or ` - #594

Open
saingge wants to merge 1 commit into
MendixMau:masterfrom
saingge:fix/harvest-known-heading
Open

saingge wants to merge 1 commit into
MendixMau:masterfrom
saingge:fix/harvest-known-heading

Conversation

@saingge

@saingge saingge commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Branch fix/harvest-known-heading, one commit (3b4dc2e) on origin/master 95e1b30. Lane 3 (direct). It was first seen while testing #553 (draft every ## section of a bug log), which is merged; this is a separate change to the same section of the script and does not depend on anything open.

What changed and why

bin/harvest-learnings.sh section 1 skips a project's bug-log heading when its first 30 characters after the BUG-nn: tag already appear in the toolkit's bug-logs/mxcli-bugs.md ("known"). It strips ~, * and the backtick from the project heading before it cuts those 30 characters, then searches the toolkit log as written. The toolkit log has those characters in its headings (186 of its 223 ## headings), so the stripped slice is not a substring of the heading it came from, and the entry was drafted again. Example: a project heading BUG-01: `alter entity drop attribute` causes … is sliced to alter entity drop attribute ca, which is not in the log's BUG-01: `alter entity drop attribute` causes ….

Two changes, both in section 1:

  1. The toolkit log is stripped the same way (tr -d '~*\'` into a temp file) before the search. This is the cause.
  2. The search takes -e. Once the log is stripped, a slice can start with -- (BUG-26 and BUG-54 begin with a backtick and then --mcp), which grep read as an option and answered "not found". Found by running the first change alone over every heading.

Impact

Row Answer
Process none. No step or gate added or removed.
Dependencies bin/harvest-learnings.sh and its own fixture only. CHANGELOG.md gets one line. No shared file, no new tool, no new artifact read.
Context cost none: no routed or always-loaded file touched. render-routing.sh --check: baseline 65444 words on origin/master and on this branch.
Behaviour n/a: scripts only.
Runtime n/a. One tr over the toolkit log (about 7,200 lines) and one temp file, removed with the existing rm -f.

Field evidence

A project whose bug log holds copies of all 223 headings of the toolkit log, run with --to a scratch directory (nothing written to the project or the toolkit):

  • origin/master (95e1b30): 103 headings drafted again.
  • with only the strip change: 2 drafted (BUG-26, BUG-54), from the -- cause above.
  • with both changes: 0.

A second run on a project with a copy of BUG-01, BUG-02 and BUG-03 and one new heading: master drafts all four, this branch drafts the new one. It was first seen when T5 of #553 drafted BUG-01 again on its first run. No project text is used here, only the toolkit's own headings.

Checklist

  • No client data anywhere in the diff (LEAKGUARD_ALLOW_NO_DENYLIST=1 LEAKGUARD_BASE=origin/master bin/check-no-client-data.sh: no new capitalised words, no client data detected; the fixture takes its headings from the clone's own bug-logs/mxcli-bugs.md and adds one synthetic heading, BUG-900).
  • Size: 2 counted files, 50 lines changed (script 10, test 40). Within the cap.
  • Test tier: T1. One fixture section (T6) in tests/wave2/test-harvest-learnings.sh, plus the field run above.
  • Golden input: T6 reads the toolkit's real headings (three with `~*`` in the first 30 characters and the first one that starts with a backtick and a dash) from the isolated clone, so the fixture follows the log.
  • [n/a] Both layouts.
  • Both platforms: macOS only (bash 3.2 with BSD tr and grep). tr -d and grep -qiF -e are POSIX; not run under Git Bash.
  • CHANGELOG.md line under ## Unreleased, credited.
  • [n/a] New skill; new bug entries.

Verification

Run on this branch (3b4dc2e), macOS arm64, 2026-10-29.

# the fixed script
bash tests/wave2/test-harvest-learnings.sh bin/harvest-learnings.sh
  ok   exit 0
  ok   4 known headings (with ~ * ` in them, or a dash left first) not drafted; the new one is
  PASS=22 FAIL=0

# origin/master's bin/harvest-learnings.sh (95e1b30) with this branch's fixture
  FAIL expected only BUG-900 drafted; got:
  FAIL-detail: ## [candidate ...] BUG-01 ... BUG-02 ... BUG-03 ... BUG-26 ... BUG-900
  PASS=21 FAIL=1
  • T6 is the only failure on master's script, and the 21 other checks (T1 to T5) pass on both.
  • bin/check-scripts.sh 125/125 shell and 25/25 Node parse; bin/check-pr-discipline.sh origin/master clean; bin/render-routing.sh --check in sync; bin/mdl-rules.sh --check in sync; bin/check-portability.sh clean; bin/check-no-private-citations.sh clean; bin/check-no-client-data.sh (with LEAKGUARD_BASE=origin/master) no new capitalised words, no client data detected; bash tests/run-tests.sh passed=33 failed=0.
  • bash tests/wave2/run-all.sh was not run: test-harvest-learnings.sh is the only fixture that runs the changed script, and it passes 22/0 above.

…not drafted again when it has ~ * or `

Section 1 strips ~ * ` from a project heading, takes the first 30 characters after a BUG-nnn
tag and searches bug-logs/mxcli-bugs.md for them. The log was searched as written, so the
stripped text was never a substring of a toolkit heading that has those characters
(BUG-01 starts with a backtick pair), and the heading was drafted again. The log is now
stripped the same way before the search. The search also takes -e: stripping leaves BUG-26
and BUG-54 starting with "--", which grep read as an option.

A project whose bug log held copies of all 223 headings in the toolkit log drafted 103 of
them at 95e1b30 and 0 now. Fixture: tests/wave2/test-harvest-learnings.sh T6, with four headings
taken from the log itself; it fails on 95e1b30.
@MendixMau

Copy link
Copy Markdown
Owner

Triage (outside PR, code not run): FIX track. Verdict: MERGE-AFTER-FIX. The only fix needed is a rebase: CHANGELOG.md conflicts with master 60e369b, just at the insertion point under ## Unreleased.

  • Injection / malicious code: none found. Every added line read. No hidden or bidi characters, no network calls or credential reads, no workflow or hook changes. The temp file is created with mktemp and removed by the existing rm -f.
  • Value: real. Known ledger entries get drafted again because the project heading is stripped of ~*\`` but the ledger is searched unstripped (bin/harvest-learnings.sh:92on base). The-efix for slices that start with--` is correct and needed once the ledger is stripped.
  • Regression risk: low. harvest-learnings.sh is a wrap-up tool, not a gate. If $TOOLKIT_BUGLOG is missing, tr writes an empty file and every heading is drafted. Master behaves the same way today, so nothing gets worse.
  • Repo rules:
    • Field-proof is cited: 103 headings drafted on master, 0 after the fix.
    • T6 fails on master's script and reads its headings from the real ledger, not hand-written input.
    • The CHANGELOG line is credited.
    • Baseline words are unchanged.
    • Git Bash was not run, but tr -d and grep -F -e are POSIX, so the risk is acceptable.
  • Note: this still needs the independent merge review per CLAUDE.md. This triage is not that review.

Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants