Skip to content

fix(pm): H44's timestamp leg accepts an ISO instant whose hour follows a T — the ruled minute spelling no longer reads as untimestamped - #18326

Merged
claude[bot] merged 1 commit into
mainfrom
claude/issue-18323-h44-timestamp-regex
Sep 15, 2026
Merged

claude[bot] merged 1 commit into
mainfrom
claude/issue-18323-h44-timestamp-regex

Conversation

@claude

@claude claude Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Fixes #18323

H44_READING_TIMESTAMP is the leg that decides a paragraph already carries its 取数时刻. It anchored the hour with a bare word boundary, which needs a NON-word character in front of it — and the T of an ISO instant is a word character. So the leg read false on the very spelling the 2026-09-02 ruling gives, and H44 reported readings that DO carry their time as untimestamped: a false positive on the row's own subject. A seconds stamp passed only by accident, the boundary holding before its mm:ssZ tail, so the match began at the MINUTES.

// before
/\b\d{2}:\d{2}(?::\d{2})?Z\b/
// after — the left anchor is a word boundary OR a lookbehind for the ISO T
/(?:\b|(?<=T))\d{2}:\d{2}(?::\d{2})?Z\b/

Reverse verification — probes on the module's own export

A file:// import of the script (a pure export; the module runs nothing on import and makes no request), against the unpatched file at a46cd8c4 and against this branch:

probe before after
2026-09-15T14:51Z — the live R+236 marker's fire stamp false true
2026-03T00:21Z — the spelling the ruling itself gives false true
2026-09-15T14:51:42Z true true
14:51Z — a bare clock true true
19:38 — a bare clock with no zone false false
12314:51Z — a clock inside a longer digit run false false

The seconds probe is the one that shows the difference between the fix and the accident it replaces: '2026-09-15T14:51:42Z'.match(...)[0] was 51:42Z before and is 14:51:42Z now — the match starts at the HOUR, and that is pinned as a case rather than the bare true that held either way.

The one design choice, on the four axes

The choice is between naming the left anchor (start / whitespace / punctuation, which the word boundary already spells, plus the ISO T) and dropping the left boundary altogether. This PR names it, and looks behind rather than consuming, so a match is still exactly the stamp.

  • 实际业务需求 — measured, not supposed: the only predecessor that occurs on this board is the ISO T, in the R+236 round-open marker (fire 2026-09-15T14:51Z) and in the ruling's own 2026-03T00:21Z. No artefact was measured writing a stamp behind any other letter. Dropping the boundary would serve a case nobody has: 12314:51Z is a digit run that happens to contain a clock, never a reading's time.
  • 项目长远合理性 — the boundary is doing real work and the defect was its SCOPE, not its presence; keeping it and naming the one exception is the contract-shaped repair, where dropping it would be a workaround that trades one class of wrong answer for another. The row's banner already claimed that a paragraph carrying HH:MM[:SS]Z is clean — this makes the regex true to a statement the file has been making all along, rather than rewriting the statement down to the implementation.
  • 防 AI 写代码犯错 — a report-only patrol that fires on a well-formed artefact teaches the seat writing it that the ruled spelling is wrong, and the cheapest way to silence a false row is to write a MORE precise stamp than the ruling asks for (which is exactly what this file's own marker case had been reduced to doing). Removing the false positive removes that pressure. Looking behind rather than consuming keeps the match equal to the stamp, so a future reader that echoes it gets no stray designator. Admitting any letter — the lenient direction — would make the leg quieter in ways nobody declared; the three negatives are pinned as cases so the widening cannot creep.
  • 创业阶段不扩散 — exactly one predecessor is admitted, and only in the uppercase the ruling spells. RFC 3339's lowercase t is legal and absent from this corpus; it is pinned as NOT admitted, so taking it later is a measurement rather than a guess.

Self-test

node scripts/pm/check-half-states.mjs --self-test: 4235 → 4243 cases pass, exit 0. Eight cases added, one rewritten:

  • the two ISO spellings that read false (2026-09-15T14:51Z, and the ruling's own 2026-03T00:21Z);
  • where the seconds stamp's match STARTS;
  • three declared negatives — the digit run, any other letter, and the lowercase t;
  • an ISO instant with no zone (2026-09-15T14:51) still reads false, exactly as a bare clock does;
  • the H44 marker case re-pinned to MINUTES, with the SECONDS spelling of the same reading kept beside it so neither can regress alone. The comment above it said this file spelled that stamp to seconds because a minute stamp could not clean a paragraph — a statement that is now false, so it is rewritten (not deleted) to say the limit is gone.

Firing control (ablation): with the one regex line reverted and every case kept, the self-test goes red on exactly four cases by name — the two ISO spellings, the match-start pin, and the marker case, which reports {shape: 'a round-open marker', kind: 'tree', fragment: '827cacbf'} where null is wanted. That row IS the false positive this PR removes. Restoring reproduced the committed blob hash exactly, and git diff HEAD and git status --porcelain are both empty.

Scope

scripts/pm/check-half-states.mjs only, and inside it only the constant at the H44 grammar, its doc comment, and its self-test cases. H44's population, its seat gate, its marker shapes (h44RoundOpenShapes / h44IsRoundOpenMarker), the fragment grammar and every other H row are untouched. :9791 is the constant's only consumer (grep count: one declaration, one consumer, the self-test cases) and it calls .test, so nothing reads the match text today.

The two sibling cards dispatched on this same file — #18324 and #18325 — work at other regions (h44NeedsSeatComments, the seatMarkers capture, latestSeatMarker) and also add self-test cases at the tail; whichever lands second merges main and re-runs the self-test. PR #18322 is the predecessor that landed the marker spelling this card's measurement came from.

Acceptance notes

  • PROTOCOL_STAMP_RE (H56's stamp shape) carries the same \b opener and is NOT affected: its boundary sits in front of the four-digit YEAR, where a non-word character really does precede it. Checked, not assumed.
  • Noted, not filed: the leg validates the SHAPE of a clock and not its ranges, so 1234-56:78Z reads as a stamp. It read that way before this change and still does; the direction is toward MORE paragraphs clean, so it can only make the row quieter, and no artefact on the board writes it.

skip-changeset: nothing published moves. The diff is one file under scripts/pm/**, which no package's files[] ships.

Generated by Claude Code


Generated by Claude Code

…s a T

`H44_READING_TIMESTAMP` anchored the hour with a bare word boundary, which
needs a NON-word character in front of it. The `T` of an ISO instant is a word
character, so `2026-09-15T14:51Z` read false — and so did `2026-03T00:21Z`, the
spelling the 2026-09-02 ruling itself gives. A reading that DID carry its
取数时刻 in the ruled minute form was reported as untimestamped: a false
positive on the row's own subject. A seconds stamp passed only by accident, the
boundary holding before its `mm:ssZ` tail so the match began at the minutes.

The left anchor now names one further predecessor — the ISO `T`, looked BEHIND
rather than consumed, so a match is still exactly the stamp. Nothing else is
admitted: the boundary is kept (a clock inside a longer digit run is still not
a stamp), no other letter opens one, and only the uppercase `T` the ruling
spells. Strictly more paragraphs read clean, so the row can only get quieter.

Self-test 4235 -> 4243 cases: the two ISO spellings that read false, a pin on
where the seconds match STARTS (the fix, not the accident), three declared
negatives, and the H44 marker case re-pinned to MINUTES with the seconds
spelling kept beside it — the comment saying that limit existed is rewritten,
because the limit is gone.

Claude-Session: https://claude.ai/code/session_01HZfg2AwVX191qCizp88gQr
Co-authored-by: Claude <noreply@anthropic.com>
@claude

claude Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 87fa4c8932fe02ea96707612900f245fe05e4cdd

Reviewing seat: domain:skills, in-seat review at the contract-review tier — get_session read at 2026-09-15T07:15Z: configured_model = session_context.model = last_served_model, the constant's tier, no fallback notice this round. Card #18323, claim 5685351787, report 5685737302 (posted through the tool; read back clean); Clause-②: no on the claim; default-tier build, seat review at tier.

① Derived judgments

  • Accept set / public surface: none moves — scripts/pm/check-half-states.mjs (+50/−6, the only file) against base a46cd8c4; nothing published; skip-changeset read back (size/s + skip-changeset). Non-governed ⇒ in-seat landing.
  • The change, read whole on a detached worktree of the head: ONE regex line — H44_READING_TIMESTAMP's left anchor becomes an alternation of the word boundary and a non-consuming look-behind for the uppercase ISO T (:9666), with a 26-line comment stating the defect, the one admitted predecessor and the three declared negatives; eight cases added (the ISO minute form, the ruling's own spelling 2026-03T00:21Z, the match now STARTING at the hour, a digit run, any other letter, the lowercase t, a zone-less ISO instant, the seconds spelling of the marker) and the marker case re-pinned to the ruled MINUTE spelling with its comment rewritten rather than deleted. The seat's probes on both trees agree with the report byte for byte: main reads false / false / true[51:42Z] / true / false / false, the head true[14:51Z] / true[00:21Z] / true[14:51:42Z] / true / false / false, lowercase t and x14:51Z false on both. Self-test 4235 / main → 4243 / head; ESLint 0/0; check-self-test-wired OK; --pair 18326 0; the battery on the seat's worktree — see the provenance for its exit.
  • Gates 41 / 41 / 0 / 0 by --ran on the head; the battery 483 s, 1730 pass (dev). Reverse verification: the ablation reverted the one regex line with every case kept — 4 of 4243 red by name (the three new grammar cases and the re-pinned marker case, which IS the false positive the card is about), restored blob 5bcfa9e7 = HEAD, git diff HEAD empty. The look-behind's own hazard (a regex fragment mangled by the write APIs) was handled as instructed: the literal is named by line, never pasted.

② Semver level

Not applicable — nothing published moves; skip-changeset measured.

③ Boundary flags

open_questions: none. One seat premise refuted, owned here: 「adjust the floor to the measured count」 — this file carries NO case-count floor (the two cases.length sites are the verdict printer), so there was nothing to adjust; the dev measured it instead of inventing one. Five deviations answered: the design spelled twice before commit (a consuming T branch failed the match-start case; the look-behind landed) — accepted, the transcript carries both; no floor — accepted; ESLint run repo-wide, not narrowed — accepted; the PR body carries two footers (the platform appended its block on a rule-less footer — register :347, not a defect, not re-sent) — accepted; measure-self-test-floor.mjs read once and found refusing on main — accepted. Out of scope: one card FILED by the seat, #18329 (the census refusal; not this lane's by SUBJECT, left bare for triage); noted, not filed: range-less clock shapes (1234-56:78Z) read as stamps — quieter only; the double-footer reading is already register :347 / :409, so no card. Landing: in-seat once every check on this head is green — ready through the CCR route, auto-merge SQUASH, the enqueue event and the queue ref read, provenance below. #18324 / #18325 (same file, other regions) fold next; whichever PR lands second merges origin/main and re-runs the self-test before its ACCEPT.

Implemented-by: claude/issue-18323-h44-timestamp-regex
Reviewed-by: session_01HZfg2AwVX191qCizp88gQr

VERDICT: PASS


Generated by Claude Code

@claude

claude Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

Landing provenance — skills seat, session session_01HZfg2AwVX191qCizp88gQr, 2026-09-15T18:37Z. Non-governed landing (scripts/pm/check-half-states.mjs only): review of record 5685923189 PASS on head 87fa4c8932fe02ea96707612900f245fe05e4cdd, ACCEPT 5685923716 on #18323; every check on that head read green at 2026-09-15T18:35Z (26 success / 11 skipped / running none / failed none); the seat's own battery on a detached worktree of the head: 1730 cases pass, 462 s, exit 0. The seat flipped the PR ready through POST …/pulls/18326/ccr/ready_for_review and armed auto-merge SQUASH through PUT …/pulls/18326/ccr/auto_merge (echo {"enabled":true,"merge_method":"squash"} — the echo is not the reading); the ready_for_review event reads 2026-09-15T18:35Z and the added_to_merge_queue event one second later, both by claude[bot]; the queue ref refs/heads/gh-readonly-queue/main/pr-18326-a46cd8c4… read 1 twenty seconds after the enqueue (a lone entry, chained on a46cd8c4). Landing is confirmed by the three readings (merged_at + git log origin/main carrying (#18326) single-parent + the queue ref gone) at the next wake; then #18323's residue is stripped and the landing record posted. #18324 / #18325 (same file, other regions) fold behind PR #18322's landing and this one; the fold's dev merges origin/main before its ACCEPT.


Generated by Claude Code

Merged via the queue into main with commit de9c319 Sep 15, 2026
39 checks passed
@claude
claude Bot deleted the claude/issue-18323-h44-timestamp-regex branch September 15, 2026 18:56
os-zhuang pushed a commit that referenced this pull request Sep 15, 2026
Takes in PR #18326 (the H44_READING_TIMESTAMP region and its cases), which
landed on main while this branch was in flight. Different regions of the same
file; no conflict.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HZfg2AwVX191qCizp88gQr
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

1 participant