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
32 changes: 30 additions & 2 deletions .github/workflows/issue-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,36 @@ jobs:
exit 0
fi

FOUND=$(echo "$PR_TITLE
$PR_BODY" | grep -oiE '(Closes?|Fixes?|Resolves?|Refs?|Updates?)\s*#[0-9]+' || true)
# A REFERENCE INSIDE A FENCE OR A QUOTE IS NOT A REFERENCE.
#
# The body is markdown. A pull request that shows `Closes #12` inside a
# fenced code block -- quoting someone else's commit, pasting a template
# -- satisfied this gate without referencing anything, and so did a line
# beginning with `>`, which is the body quoting a different pull request.
# Verified before the change: both forms passed.
#
# This repository already carries the same lesson about its own skill
# file, where a parser counted headings quoted inside code blocks.
# A quotation is not a claim.
#
# The TITLE is not markdown and is matched as written.
BODY_PROSE=$(printf '%s\n' "${PR_BODY:-}" | awk '
/^[[:space:]]*```/ { fence = !fence; next }
fence { next }
/^[[:space:]]*>/ { next }
{ print }
')

# `#0` IS NOT AN ISSUE. `#[0-9]+` matched it, and `gh issue view 0`
# answers "Could not resolve to an issue or pull request". A number that
# cannot name an issue is not traceability. The cheapest honest guard is
# to refuse a leading zero rather than to ask the API: a network call
# inside a REQUIRED context turns a GitHub hiccup into a merge block for
# the whole repository.
#
# Whether a reference names an issue that EXISTS is a heavier question,
# recorded rather than answered here.
FOUND=$(printf '%s\n%s\n' "$PR_TITLE" "$BODY_PROSE" | grep -oiE '(Closes?|Fixes?|Resolves?|Refs?|Updates?)\s*#[1-9][0-9]*' || true)

if [ -n "$FOUND" ]; then
echo "✅ Issue gate passed: $FOUND"
Expand Down
22 changes: 22 additions & 0 deletions docs/now/2026-09-06-four-required-context-defects-closed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# NOW -- Four required-context defects closed, the fifth priced (2026-09-06)

## Four required-context defects closed (Refs #3388)

- `Closes #0` passed `check-linked-issue`, and `gh issue view 0` answers "Could not
resolve to an issue". The number must not be zero now.
- A reference inside a fenced code block or a `>` quote counted as traceability. Fences
and quoted lines are stripped from the body first; the title is not markdown and is
matched as written. This repository already carries the same lesson about its own skill
file, where a parser counted headings quoted inside code blocks.
- `check` missed a rename: `--diff-filter=A` reports an R entry, so a docs/now path
whose content newly lands by rename never reached the shape reader. `--no-renames`.
- `validate` decoded with `errors="replace"`, turning invalid bytes into U+FFFD and
parsing the repaired text. Measured first: **0 of 2086** tracked files are non-UTF-8, so
the strictness costs nothing today and closes the hole anyway.
- Six controls on the issue-gate logic, including the one that matters: a real reference
AFTER a fence is still found, so the stripping does not swallow what follows it.
- The fifth is left: bare `Infinity` is accepted by CPython and refused by
`node -e JSON.parse`. Exactly one tracked file carries it -- my first count said 20,
and 19 of those have it inside strings. The file is GENERATED and READ by two tools, so
the encoding is a conformance-data decision; shipping the stricter parse without it
would leave a REQUIRED context red and block every merge.
24 changes: 23 additions & 1 deletion tools/check_json_parses.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,29 @@ def scan(root=ROOT):
empty.append(rel)
continue
try:
json.loads(raw.decode("utf-8", "replace"))
# STRICT on both axes, because a lenient reader here is a gate that
# passes what its consumers refuse.
#
# `errors="replace"` turned any invalid byte into U+FFFD and then
# parsed the repaired text, so a file no strict reader accepts came
# back clean. Measured before the change: 0 of 2086 tracked files are
# non-UTF-8, so this costs nothing today and closes the hole anyway.
#
# NOT DONE HERE, and the reason is the point: `parse_constant` would
# also refuse bare `Infinity`, which CPython accepts and documents as
# "an extension to the JSON specification" while RFC 8259 has no such
# literal. `node -e JSON.parse(...)` rejects it, so this gate passes
# what another consumer refuses -- a real defect, confirmed.
#
# It is not fixed here because the blast radius is one tracked file,
# `conformance/vectors/gf16_conformance_v0.json`, whose six values are
# genuine IEEE754 infinities. That file is GENERATED by
# conformance/vectors/gen_all_formats.py and READ by
# tools/wp18_selftest_gate.py, so an encoding both sides agree on is a
# decision about conformance data, not about this reader. Shipping the
# stricter parse without it would leave a REQUIRED context red and
# block every merge in the repository.
json.loads(raw.decode("utf-8"))
except Exception as e:
bad.append((rel, str(e)[:90]))
return empty, bad
Expand Down
7 changes: 6 additions & 1 deletion tools/check_now_entry_shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,12 @@ def added_now_entries(base, head):
# `.md`, so the entry left the population SILENTLY and the gate reported that the
# change adds none. Measured on a real Cyrillic filename.
r = subprocess.run(
["git", "diff", "-z", "--name-only", "--diff-filter=A", f"{base}...{head}",
# `--no-renames`, because rename detection decides this gate's population.
# git reports a rename as a single R entry, so `--diff-filter=A` misses it
# and a docs/now/ path whose content newly lands by rename never reaches
# the shape reader. With the flag git reports D(old) + A(new) and the new
# path is judged like any other.
["git", "diff", "-z", "--name-only", "--no-renames", "--diff-filter=A", f"{base}...{head}",
"--", "docs/now/"],
capture_output=True,
text=True,
Expand Down
Loading