Skip to content

docs(configuration): the retry-cap row still promised a zero that the loader refuses (BACKLOG #1217, half 1) - #591

Merged
wshallwshall merged 2 commits into
mainfrom
claude/builder-2-1217-retry-doc
Aug 25, 2026
Merged

docs(configuration): the retry-cap row still promised a zero that the loader refuses (BACKLOG #1217, half 1)#591
wshallwshall merged 2 commits into
mainfrom
claude/builder-2-1217-retry-doc

Conversation

@wshallwshall

Copy link
Copy Markdown
Collaborator

The retry-cap catalog row in docs/CONFIGURATION.md still asserted "0 or a negative value is accepted and dead-letters on the first failure" -- false since PR #383 floored the setting at ge=1. A catalog row describing a configuration the loader refuses is worse than silence: an operator writes it, startup fails, and the document that sent them there still reads authoritative. docs/BACKLOG.md untouched. Item #1217 stays OPEN -- this is half 1 only, not a closure.

Driven, not read off the field: 0 and -1 rejected; 1, 100, and None load; key omitted loads 100; RetryPolicy(max_attempts=0) (the code-level type, unrelated to the operator setting) still legal.

Why models.py was deliberately left alone, since it looks like an omission: the floor applies to the operator-facing setting only. Adding ge=1 to models.py would look like the symmetric completion of the same tightening and would instead delete a used mechanism -- RetryPolicy(max_attempts=0) is the deliberate permanent-no-retry idiom, and four test modules depend on it. settings.py already anticipates this exact mistake in its own comment; the new test makes that comment executable rather than advisory.

The prose test is negative on purpose -- it asserts the false claim cannot come back, not that the new sentence matches word for word. An exact-sentence assertion reds on any rewording, which just trains the next author to edit the test instead of the doc.

Red-first: restoring the old sentence verbatim reds exactly the catalog test (1 of 15 in that selection), anchor asserted unique and file hash asserted changed before scoring, then restored byte-identical.

Half 2 deliberately not in this branch. Whether retry-forever needs a TOML or env spelling is a product question -- the item's own text says choosing the spelling IS the item. Measured rather than assumed: 0, -1, "", "none", "null", "forever", "inf" all rejected; key omitted gives 100; Python None gives None. So retry-forever is reachable in code-first configuration and nowhere else, since TOML has no null literal. Routed to the Dispatcher for a ruling separately.

Verification, explicitly scoped: test_retry_cap_default.py + test_delivery_settings.py + test_settings.py, 149 passed. ruff/ruff format clean. Full suite not run.

… loader refuses (BACKLOG #1217, half 1)

PR #383 floored the operator-facing `retry_max_attempts` at `ge=1`. The catalog row in
docs/CONFIGURATION.md was not moved with it and still asserted:

    `0` or a negative value is accepted and dead-letters on the first failure

That has been false since #383. A catalog row describing a configuration the loader REFUSES
is worse than silence: an operator writes it, the start fails, and the document that sent
them there still reads as authoritative.

DRIVEN, NOT READ OFF THE FIELD DECLARATION:

    retry_max_attempts = 0     REJECTED        = -1        REJECTED
                       = 1     LOADS -> 1      = 100       LOADS -> 100
                       = None  LOADS -> None   key omitted LOADS -> 100
    RetryPolicy(max_attempts=0)  STILL LEGAL

The row now says what the loader does, and keeps naming the internal idiom the floor
deliberately does NOT touch.

THAT LAST CLAUSE IS THE POINT OF THE WHOLE ITEM AND IT IS EASY TO DELETE BY ACCIDENT. The
obvious "remaining half" -- adding `ge=1` to `models.py` -- looks like the symmetrical
completion of the same tightening and would instead DELETE A USED MECHANISM:
`RetryPolicy(max_attempts=0)` is the deliberate idiom for a permanent, no-retry failure and
FOUR test modules depend on it (test_batch_completion, test_postgres_store, test_resend,
test_sqlserver_store). settings.py anticipates the mistake in its own comment; the new
`test_the_internal_no_retry_idiom_is_untouched_by_the_operator_facing_floor` makes that
executable rather than advisory.

THE PROSE TEST IS NEGATIVE ON PURPOSE. It asserts the false CLAIM cannot come back, not that
the new sentence matches word for word. An exact-sentence assertion reds on any rewording,
which trains the next author to edit the test instead of the doc.

RED-FIRST: restoring the old sentence verbatim reds
`test_the_configuration_catalog_does_not_still_promise_the_pre_floor_behaviour`, 1 of 15 in
that selection, with the anchor asserted unique and the file hash asserted changed before
scoring, then restored byte-identical.

HALF 2 IS NOT IN THIS COMMIT AND IS NOT MINE TO DECIDE. Whether the retry-forever posture
needs a TOML or env spelling is a product question -- the row says choosing the spelling IS
the item. Measured here rather than quoted, every plausible spelling driven through the real
model:

    0, -1, "", "none", "null", "forever", "inf"   ALL REJECTED
    key omitted -> 100
    python None -> None                            <- code-first ONLY

So retry-forever is reachable in code-first configuration and nowhere else, because TOML has
no null literal. The row recommends a string spelling coerced by a field validator; adopting
one changes the accepted-configuration set, so it is routed for a ruling rather than settled
in a build.

Verification, with scope: tests/test_retry_cap_default.py, tests/test_delivery_settings.py and
tests/test_settings.py, on .venv/Scripts/python.exe (CPython 3.14.6 non-freethreaded, seven CI
extras). ruff 0.15.22 (== the constraints.lock pin) check and format --check clean. NOT the
full suite.

No test was removed or weakened. The ledger row is not mine to author and is not in this
commit; #1217 stays OPEN on half 2.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@wshallwshall
wshallwshall enabled auto-merge (squash) August 25, 2026 18:47
@wshallwshall
wshallwshall merged commit 2275604 into main Aug 25, 2026
39 of 40 checks passed
@wshallwshall
wshallwshall deleted the claude/builder-2-1217-retry-doc branch August 25, 2026 20:33
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.

1 participant