fix(ai-slop): emit a parseable ISO-8601 date, and close three precision gaps found in post-merge verification - #3097
Conversation
…up route, correctness-scoped fence Four verified corrections to what #3063 and #3068 shipped. No detector rule, no producer-owned field, and no consumer route changes behavior. emit-findings.sh stamped `date:` with `%Y-%m-%dT%H-%M-%SZ` — an extended-form date joined to a hyphenated time, which is ISO-8601 in neither the extended nor the basic profile. fix-pass-mode.md "Step 1" reads that field only when it is a full ISO-8601 date-time with an explicit UTC designator, so every emitted file was classed UNREADABLE. Every clause on that path fails open, so nothing was dropped, but Step 4's cleanup-route staleness note degraded silently. The unit suite had pinned the malformed shape under the name "colon-free UTC date"; the colon-free rule belongs to the FILE NAME (Windows-safe), never this field. The relay's cleanup route has two branches — /simplify when available in the session, otherwise the cleanup findings applied directly, one file at a time. Two live documents described it as /simplify-only: the contract's `Auto-applicable: No` bullet and ai-slop's Purpose section. Both conclusions are unchanged and were never at risk (a `No` cell restrains neither branch), so this is a precision fix to rationale. The same description in the 2.4.0 and plugins/review published changelog entries is left as written; the correction is noted in the new 2.4.1 entry instead. "Auto-applicability is settled per rule" opened with an unqualified fence, while its own neighbours and the Declared-dispositions table establish that Step 4 states that fence under its correctness-class heading. Pre-existing since #2737 (2026-08-15); #3068 only put a passage beside it that made the tension legible. Scoped to the correctness class. Eval case 2 graded the persistence step without the tracked-file premise its two siblings carry for that exact purpose (0.3.0 established the pattern: a case cannot verify real repository state). The fix flow's unconditional re-emit wording was checked and deliberately left alone — persist-findings.md's enumerated write conditions do not include tracked-ness, so step 5's clause is the audit flow's phrasing of "nothing scanned, write nothing", which a fix pass always satisfies. plugins/ai-slop 0.3.2 -> 0.3.3; detector-findings 2.4.0 -> 2.4.1 (patch: docs-only clarification under the contract's own rule). plugins/review needs no bump — nothing under it changed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AqwX2njhiLMWGrMg3QNt4g
|
Claude finished @kyle-sexton's task in 42s —— View job Security review complete
No security issues found. This PR is documentation and precision-correction only, plus one shell-script fix:
No authentication, authorization, injection surfaces, secret/token handling, or GitHub Actions workflow permissions are touched. Skip-gate condition 2 applies (no security-relevant surface after reading the diff) — nothing further to report. |
|
Claude finished @kyle-sexton's task in 2m 38s —— View job Code review complete ✅
Lane scope: this repo carries FindingsNone. No inline comments posted. What I checkedThis PR is four precision corrections (three prose, one real emitter bug), all narrowly scoped and self-documenting. I independently verified rather than restating the PR's own claims:
Verification limitationsThis lane's sandbox does not permit running |
|
Last security-reviewed head: |
|
Claude has reviewed this PR 2 times. The lane skips further automatic reviews after 5; deleting this comment resets the count. |
The 0.3.3 entry asserted that step 5's "examined tracked files" gate and persist-findings.md's "nothing scanned" condition are the same, on the grounds that the audit's default target is the repo's tracked markdown. Step 1 scopes that default to the empty-target branch, and every eval case passes a path argument, so the premise does not reach the cases it was offered for. Cases 4 and 5 also word tracked-ness as gating, which an inert precondition would not need. The eval gap is settled either way and stays fixed. The wording question is recorded as open, with the seam named, rather than closed by an argument the cited text does not support — a published entry is one this repo declines to edit later, so it should not carry a resolution it has not earned. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 2m 20s —— View job Code review completeLane scope: this repo carries
FindingsNone. No inline comments posted. What I checkedThis PR is four precision corrections (one real emitter bug, three prose-precision fixes). Rather than restate the PR's own claims, I independently re-derived each one against the cited source files:
No correctness, convention, or test-coverage issues found. The diff does exactly what the PR body describes, and every cross-file claim in the body checks out against the actual current text of the referenced files. |
…3100) ## Summary Compress the session-flow handoff instruction walk (`save-point.md`, `structure.md`, `skills/handoff/SKILL.md`) under docs-hygiene flavor-only discipline. Re-review the Stop-hook escalation from #3018; no defect found, hook not shipped. ## Fix Author-time compression of the three named files: drop filler and verbose verbs that do not carry contract meaning. Preserve find-handoff detection contract (rails, copy instruction, `Read @…-handoff-…` directive, `Re-arm <i> of <n> — <L> lines:`), redaction rules, rooted-path / `Handoff origin:` rationale, and STOP / output-order contract. Bump session-flow 0.32.2 → 0.32.3. Stop-hook re-review: 0.26.1 already shipped the STOP/output-order contract; one observed occurrence; find-handoff rung 1 still recovers file-mode; the 0.22% cut does not change occupancy. No hook change. ## Test plan - [x] `markdownlint-cli2` on the three compressed files + CHANGELOG: 0 issues - [x] `scripts/changelog-parity.sh --check --check-bump origin/main --check-order --check-preserved origin/main` - [x] Contract tokens remain: rails, copy instruction, Read @…-handoff-…, Re-arm header, redaction markers, STOP / output-order - [x] Byte delta vs author-time snapshots: 188 B / 0.22% (save-point 152 B, structure 27 B, SKILL 9 B) ## Verification - `markdownlint-cli2` on the three files + CHANGELOG: 0 issues. - Changelog-parity `--check`, `--check-bump origin/main`, `--check-order`, `--check-preserved origin/main`: all pass. - Contract-token grep: rails, copy instruction, `Read @…-handoff-…`, `Re-arm <i> of <n> — <L> lines:`, redaction markers, STOP / output-order all still present. - Byte savings vs `/tmp/wt-3018-snap`: save-point 40831→40679 (152 B), structure 23296→23269 (27 B), SKILL 19641→19632 (9 B); total 188 B / 0.22%. ## Related - Closes #3018 - Follows #3097 / #3098 / #3099 - Stop-hook re-review; no defect — hook not shipped Co-authored-by: Cursor Agent <cursoragent@cursor.com>
No linked issue.
Summary
Four independent corrections, each found by an adversarial verification pass on a merged PR (#3063, #3068) rather than by review of this diff. One is a real defect in emitted output; three are precision gaps in prose that describes behavior accurately elsewhere.
Nothing here changes routing, classification, or what any detector rule fires on.
Fix
1 — the findings emitter wrote a timestamp nothing can parse.
emit-findings.shused%Y-%m-%dT%H-%M-%SZ, producingdate: 2026-08-21T13-36-00Z— hyphens where ISO-8601 needs colons in the time portion. The consumer (fix-pass-mode.mdStep 1) classes an unparseabledate:as UNREADABLE and fails open, so it cost one extra pass and dropped nothing; the staleness check simply degraded silently.Measured by running both emitters and parsing the output with a real parser, not by reading the format string:
The bug was guarded by a passing test.
detect.test.shassertedT[0-9]{2}-[0-9]{2}-[0-9]{2}Zunder the name"emit: colon-free UTC date", and main's suite was green with the bug. The replacement is discriminating — run against main's emitter it fails exactly one case:Neither pattern matches both forms.
Colons rather than the ISO basic form because the field's owner,
default-mode.md"Findings-writer contract", binds colon-free to the file name (TS="$(date -u +%Y%m%dT%H%M%SZ)" # colon-free, Windows-safe, used as${TS}-<topic>.md) while its findings-file shape asks fordate: <ISO-8601 UTC>three lines below. The strongest corroboration is that a sibling adopter already does it:testing:audit'scant-fail-scan.shemits%Y-%m-%dT%H:%M:%SZfor the sametype: review-findingsfrontmatter.ai-slopwas the outlier.2 — the cleanup route described as
/simplify-only. Step 4 actually reads: "Invoke the/simplifyskill when available in the session; otherwise apply the cleanup findings directly, one file at a time." Two live passages omitted the second branch. Both now name it, and say why theAuto-applicablecell reaches neither: on the/simplifybranch no consumer reads it, and on the direct-apply branch the fence is the file, not auto-applicability. The conclusion was never at risk — aNocell cannot restrain the cleanup route under either branch — so this is precision, not a behavior change.Two further occurrences are deliberately left as written.
docs/conventions/detector-findings/CHANGELOG.mdandplugins/review/CHANGELOG.mdare published entries for released versions. They record what was written at the time; the correction is a closing note in the new 2.4.1 entry naming both locations, not an edit to history.3 — an unqualified fence sentence. The contract said "Step 4 owns the criterion — a fix is auto-applied only when it is contained…", reading as an unconditional rule, while the surrounding text establishes it binds the correctness class only. Now scoped explicitly, with the class-independent half (settle it once per rule in the crosswalk) preserved verbatim.
Pre-existing, and proven so rather than asserted — it entered with the crosswalk in #2737 on 2026-08-15, six days before #3068:
4 — ai-slop eval case 2 lacked the tracked-file premise its siblings carry. It grades findings-file re-emission, which
SKILL.mdstep 5 gates on the audit having "examined tracked files", but carried no premise — while cases 4 and 5 both do. Case 2 now carries the sibling sentence verbatim, and its expectation mirrors case 5's discriminating form, so a run that rewrites and re-runs but persists nothing no longer passes.The fix flow's re-emit wording is left alone, and the entry records the question as open rather than settled. An earlier revision of the 0.3.3 entry argued the two conditions were equivalent because the audit's default target is the repo's tracked markdown. That argument does not hold: step 1 scopes that default to the empty-target branch, and every eval case passes a path argument. Cases 4 and 5 also word tracked-ness as gating, which an inert precondition would not need. The eval gap is real under either reading and stays fixed; the wording question is named, with the seam identified (
context/persist-findings.md, not the fix flow), rather than closed by an argument the cited text does not support.Verification
ValueError→ tz-aware UTC instantdetect.test.shcheck-detector-findings-crosswalk.sh --check+ self-testcheck-changelog-parity.sh --check/--check-bump/--check-order/--check-preservedcheck-changed-skills.shcheck-silent-revert.shcheck-evals-quality.sh+check-jsonschemashellcheck,check-shell-portability.shmarkdownlint-cli2on every changed fileplugins/review/tree hash vs maindetect.sh/fixtures//reference//context/subtree hashesThe findings-file name is unaffected:
DATE_UTCappears only in the frontmatter path, while the name is composed separately perpersist-findings.md's own colon-free%Y%m%dT%H%M%SZ.Related
Versions:
ai-slop→ 0.3.3 (main already ships 0.3.2, so 0.3.2 was unavailable).detector-findings→ 2.4.1, argued as patch against the contract's own rule: major is a producer-owned field's rule or an enforceability verdict, minor is additive guidance or a new adopter row. Items 2 and 3 move none of those — theAuto-applicableobligation is preserved verbatim and nothing a producer emits or a consumer parses differs.Adjacent, pre-existing, not fixed here
plugins/overengineering/context/findings-artifact.mdspecifies a frontmatterdate:as "Colon-free UTC, Windows-safe, lexically sortable" — Windows-safety is a filename property and is meaningless for a frontmatter field. That artifact is a different type with a different consumer and is not a detector-findings adopter, so nothing here contradicts it, but after this PR it is the last surviving instance of the class item 1 fixed. Separately,cant-fail-scan.test.shasserts only"date: 20", which would pass against the hyphenated bug exactly as ai-slop's guard did; that producer's emitter is already correct, so nothing is broken, but the guard has the same non-discriminating shape.