Skip to content

1.9.79: the re-click backfill counts only a click's own failures towards a step-over, from the first of them - #329

Open
tracking202 wants to merge 3 commits into
1.9.79from
claude/dazzling-archimedes-9ytvfu
Open

tracking202 wants to merge 3 commits into
1.9.79from
claude/dazzling-archimedes-9ytvfu

Conversation

@tracking202

@tracking202 tracking202 commented Oct 28, 2026 •

Copy link
Copy Markdown
Owner

The adversarial review of #282 (6 non-blocking findings) is addressed here for findings 1–4 and 6. The reports stay encrypted. Finding 5 waits on the owner's call and is not in this PR.

This branch also merges #328 (90715f4), the fix for the three request-value casts that left 1.9.79's own PHPStan job red. It becomes a no-op once #328 lands on 1.9.79.

What changes

1. Only a failure shown to be the click's counts towards stepping it over.

  • A step-over can't be undone: the click then counts at each of its visits for good.
  • Before, any failure the code could not name as a passing problem counted, including a type error and a wrapper that had dropped the errno.
  • Now a failure counts only when its chain carries one of two things, and no passing problem:
    • a server errno;
    • the repair's UnexpectedValueException for a value the click's rows hold.
  • Anything else stops the run at the click and counts towards nothing. The walk stays stopped there, the error log names the click, and GET /system/dataengine names it too.
  • Seven more MySQL errors now count as passing problems: 1158–1161 (network read or write), 1030 (storage engine), 1297 (temporary) and 1180 (during commit).

2. The hour starts at the first failure of the click's own.

  • failing_since used to start at the click's first failure of any kind.
  • So after two hours of lock waits, ten minutes of the click's own errors stepped it over. The docs said "10 runs over an hour".
  • failing_since is now the first run that failed with the click's own error, and it stays null while only passing problems stop the walk.
  • The API doc, OpenAPI spec, upgrade guide, changelog and progress note say so.

3. Tests for the paths the review named.

  • Measured: the cron job runs under MYSQLI_REPORT_STRICT alone, as connect.php sets it, and so do the existing tests. A failed statement reaches the classifier as Connection's [errno N] tag.
  • So the tag branch was already the one every case ran. The untested branch was the other one, a mysqli_sql_exception's code.
  • The passing-problem cases now run under both report modes and include the new errnos.
  • ReClickBackfillFailureTest holds the classifier on 14 exception chains no trigger can raise: wrapped, nested, untagged, a type error, a logic error.
  • A real lost connection makes the next statement on the dead handle throw out of run() before anything is counted. That is loud and counts nothing; this PR leaves it as it is.

4. The consent reader's parity with PHP is a committed test.

  • LandingConsentReaderTest runs landing.php's own reader and link decorator under node, on 45 spellings.
  • It holds each answer to PHP's parse_str() and RequestSignals::consentGiven(): absent, consent or refusal.
  • It also checks what a followed link carries: refused, the tracker reads 0; given, it reads no p202_consent.
  • When CI is set it fails rather than skips if node is missing.
  • CLAUDE.md Fix newline at end of index #11 said "36 spellings", from a scratch run nothing could repeat. It now names the test.

6. SchemaVersionIntegrationTest

  • It now checks its own reads instead of turning a failed one into "no rows".
  • It restores the mysqli report mode it found.
  • It adds two cases: no 202_version row, and no table. Neither claims an upgrade, and the sync worker's refusal names each.

CLAUDE.md #35 records both halves of finding 1 and 2's shape. Pattern #11 records finding 4's.

Testing

On this PR (90715f4): CI is green, including:

  • PHPStan;
  • integration on MySQL 8.0;
  • test, upgrade-equals-install and agent-evals;
  • lint.

The two review checks report "did not run". Since #275, every PR into 1.9.79 gets that answer, until 1.9.79 reaches master (see the comment below).

Locally on PHP 8.3.6 and MariaDB 10.11, full vendor/, on 1.9.79 at c6d5167, before #328 was merged in.

The ladder (verify.sh --changed):

  openapi    PASS
  patterns   PASS
  phpcs      PASS
  phpstan    FAIL  phpstan.neon.dist failed, phpstan-strict.neon passed
  syntax     PASS
  unit       PASS

Integration, each suite on its own fresh database:

  • ReClickBackfillIntegrationTest 21/21
  • SchemaVersionIntegrationTest 11/11
  • ReClickRollupUpgradeIntegrationTest 3/3
  • UpgradePendingAnswerServedIntegrationTest 11/11

Live: tests/live/reclick-backfill-cron.sh passed 12/12 through the real cron job (202-cronjobs/index.php) and GET /system/dataengine. It ran against a 1.9.79 instance served from this tree. In that run the refused click is stopped at, then stepped over once its own failures are an hour old.

Each fix was planted against, and a named test fails:

Plant Fails
a failure with no cause counts again 4 classifier cases
the hour runs from any failure all 10 passing-problem cases
the seven new errnos removed the classifier, and 4 integration cases
the mysqli_sql_exception branch removed 2 classifier cases, and every "raised" integration case
the chain walk stops at the first exception 3 classifier cases
landing reader by exact name the parity test
JavaScript's trim() the parity test
no cut at a NUL both parity tests
decorator deletes only the exact name the decorator test
decorator does nothing the decorator test
a missing row read as 1.0.2 its own case
a missing table read as 1.0.2 its own case

🤖 Generated with Claude Code

https://claude.ai/code/session_01U3VVstdYdz5zwv5MUbkDjT

1.9.79's PHPStan job has been red since the merges at 15:46Z. #308 extended
ForbidNumericCastOfRequestParamRule to the pages and baselined the casts
already there. Three PRs merged beside it each added a cast that its baseline
does not count, and each PR passed on its own:

- Personal settings (#283) cast the same-IP fallback after checking it is a
  key of its choices. It now stores 1 for '1' and 0 for '0', the two keys the
  check admits.
- Setup > Offline Conversions (#293) cast a feed id after a regex test. It now
  reads it with PostedId::read().
- Setup > Traffic Sources (#271) cast the edited account's id to read its
  stored postbacks. The page's own ownership check compares the raw value in
  SQL, where MySQL reads '12abc' as 12. So a save from
  ?edit_ppc_account_id=12abc changed account 12 (one of the account's own, not
  the one named) and held that account's postbacks. Measured on a live
  instance: the old page saved the tampered edit onto account 1. The id is now
  read exactly, and anything else is refused in the page's words before
  anything is read or written.

The baseline counts are unchanged: each file now holds only the casts they
counted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VRoS2SViuxaucFaKWsFnLr
…rds a step-over, from the first of them

The adversarial review of #282 (findings 1-4 and 6):

- A failure that names no cause (no errno, no value of the click's: a
  type error, a wrapper that dropped the errno) counted towards stepping
  the click over for good. It counts in none now, and 1158-1161, 1030,
  1297 and 1180 join the errors of the moment.
- The hour before a step-over ran from the click's first failure of any
  kind, so ten minutes of its own errors after two hours of lock waits
  stepped it over. failing_since is the first failure of its own now.
- The classifier is held on the chains no trigger raises, and the
  moment cases run under both mysqli report modes.
- LandingConsentReaderTest runs landing.php's consent reader and link
  decorator under node and holds them to parse_str() on 45 spellings;
  CLAUDE.md said 36, from a scratch run nothing could repeat.
- SchemaVersionIntegrationTest checks its own reads, restores the report
  mode, and covers a missing row and a missing table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U3VVstdYdz5zwv5MUbkDjT
Copilot AI balanced review requested due to automatic review settings October 28, 2026 16:23
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-28T16:24:01.224314Z
We couldn’t complete this review. Comment @codex review to try again.
0a0803b PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

tracking202 commented Oct 28, 2026 •

Copy link
Copy Markdown
Owner Author

Two kinds of red check on this PR, neither from its change.

PHPStan (custom rules): fix ported in 90715f4. 1.9.79 itself fails PHPStan with five errors (c6d5167, cold result cache). They come from three request-value casts that 1.9.79's own merges left in 202-account/account.php, tracking202/setup/offline_conversions.php and tracking202/setup/ppc_accounts.php. Each PR that added one passed on its own head; the stricter rule from #308 only met them after the merges.

#328 fixes all three. Its branch is merged into this one: a merge commit, nothing rewritten, and no change to its fix. With it, phpstan analyse -c phpstan.neon.dist reports 0 errors here. It becomes a no-op once #328 lands on 1.9.79.

claude-review and adversarial-review: "did not run". Since #275 merged, 1.9.79's two review workflows differ from master's. The Claude app gives its token only to a workflow identical to the default branch's copy, so every PR into 1.9.79 gets this answer until 1.9.79 reaches master. #275's description says so under "Merge order". The new steps make that failure loud instead of a silent CLEAN, as intended. A re-run would get the same answer, and nothing in this PR can change it.


Generated by Claude Code

…'s PHPStan job refuses

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U3VVstdYdz5zwv5MUbkDjT
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.

3 participants