#!/usr/bin/env bash # Regenerate the contents block at the top of `docs/port/DECISIONS.md`. # # tools/port/index-decisions # rewrite the index # tools/port/index-decisions --check # fail if it is out of date # # 🔴 WHY THIS EXISTS. The record reached 6 500 lines and 111 sections with no # index, and on 2026-08-30 I spent an iteration empirically re-deriving a result # it already contained -- under two headings that name the screens in question -- # then reported the question as unexplained to the Decoder. An unnavigable record # is not a record that is hard to read; it is one that does not get read. # # ⚠️ `--check` exists because a stale index is worse than none: it would answer # "is this already decided?" with a confident no. `check-all` runs it. set -euo pipefail cd "${PROJECT_DIR:-/work}" DOC=docs/port/DECISIONS.md BEG='' END='' body=$(python3 - "$DOC" <<'PY' import re, sys lines = open(sys.argv[1]).read().split('\n') out = [] for l in lines: if l.startswith('## '): title = l[3:].strip() # A GitHub anchor: lowercased, punctuation dropped, spaces to hyphens. anchor = re.sub(r'[^\w\s-]', '', title.lower()).strip().replace(' ', '-') # NO LINE NUMBERS. They would make the index a fixpoint problem -- writing # it shifts every line below it -- and, worse, every appended section # would silently invalidate all of them. An anchor survives both. out.append(f"* [{title}](#{anchor})") print('\n'.join(out)) PY ) new=$(printf '%s\n\n%d sections. Search this before re-deriving anything.\n\n%s\n\n%s\n' \ "$BEG" "$(grep -c '^## ' "$DOC")" "$body" "$END") cur=$(awk -v b="$BEG" -v e="$END" 'index($0,b){f=1} f{print} index($0,e){f=0}' "$DOC") if [ "${1:-}" = --check ]; then if [ "$cur" = "$new" ]; then echo " index-decisions ok"; exit 0 else echo " index-decisions 🔴 the index is out of date -- run tools/port/index-decisions"; exit 1; fi fi python3 - "$DOC" "$BEG" "$END" "$new" <<'PY' import sys doc, beg, end, new = sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4] s = open(doc).read() if beg in s: i, j = s.index(beg), s.index(end) + len(end) s = s[:i] + new.rstrip('\n') + s[j:] else: # First run: place it after the H1 and its opening paragraph. k = s.index('\n## ') s = s[:k] + '\n\n' + new.rstrip('\n') + s[k:] open(doc, 'w').write(s) print("index written") PY