Repository navigation
scripts/repo_shape.py: a plain decimal with a nonzero digit that is too small for a 64-bit float, 0. and four hundred 0s and a 1, is yaml-unparsable by its line with the large end's remedy, where _scalar read it as 0.0 and check and execute went on with a number the file does not hold (#1260) - #1309
brettheap wants to merge 3 commits into
Conversation
…oo small for a 64-bit float, `0.` and four hundred `0`s and a `1`, is `yaml-unparsable` by its line with the large end's remedy, where `_scalar` read it as `0.0` and `check` and `execute` went on with a number the file does not hold (#1260) `_scalar` read a plain decimal with `float()` and refused only the result that is infinite (#1212, PR #1249). A decimal that holds a nonzero digit and whose float is zero changes kind the same way at the small end, from nonzero to zero, so it now raises the same `YamlError` with `_UNMADE_NUMBER_REMEDY`, in words that say it would be zero where the large end's say it would be infinite: `a plain decimal of 402 digits is too small to read as a number: a 64-bit float cannot hold it, so it would be zero`. `load_yaml` names the line, and `check` and `execute` print the refusal and exit 2 with no traceback, in a `commit:`, a key outside `pins:` and a `follow_ups:` item. The test of a nonzero digit asks each digit its value, because the pattern takes the digits of every script and `float()` reads each as its value. `0.0`, `-0.0`, a decimal of only zeros and a subnormal such as 5e-324 (326 characters) are numbers still. `adopt-project.py` needs no change: the refused value never reaches `_read_as`. Rows are in tests/test_plan_number_limits.py, 27 of them. Lane 3's ruling is #1260 issuecomment-6767326422. Stacked on #1249 (for #1212) at 3e5d1fd. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Reviewer's GuideImplementationAdd a shared plain-decimal parser that refuses floats rounded to zero when the spelling contains a nonzero digit, while preserving zero-only decimals and subnormals; route
TestsCover underflow refusals and line-specific remediation across YAML shapes and plan commands, along with valid zero, subnormal, and rounding-boundary controls.
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
RV1309: review of #1309 at Independent review (RV1309, lane openRepoShape-4, 2026-11-10). Reviewed Verdict. The behaviour is right: no MUST. Every probe agrees with the ruling, in every shape, with either sign, in every script's digits, and the words and the remedy are the large end's. One SHOULD, in the rows file only: two natural rewrites of the new nonzero-digit test pass all 62 rows. A row or two fixes it (below). FindingsSHOULD-1. The rows pin only half of the nonzero-digit test, the script half: two rewrites of it that break the ruling pass all 62 rows.
No NIT. Checks1. Correctness of the test in
2. The words: PASS. Each is followed by the same 3. Mirrored everywhere: PASS. 4. Rows: PASS on counts and on what each asserts; the coverage gap is SHOULD-1.
5. Mutants: FAIL (two of mine survive, SHOULD-1). Each is run against the whole rows file in a worktree of its own, restored with
(a), (c), (d) and (j) match the body's table. My (j) differs from the writer's 6. Existing rows and the gate: PASS. At the head, in the environment above:
7. Scope and pinned copies: PASS. The diff is 8. The PR body: PASS. Leaving the bot's appended summary aside, as the brief says:
9. Merge-trees: PASS.
Lane: openreposhape-4 (openRepoShape-4) |
…t is refused too, at the default digit limit (#1260) RV1309's review of #1309 found that in every refused decimal the rows use, the nonzero digit is the last character, so two rewrites of the check in `_scalar` passed all 62 rows: one that tests only the last digit, which reads `0.`, 400 `0`s and `10` as `0.0`, and one that makes one `int()` of all the digits, which raises an uncaught `ValueError` past 4300 digits. Two rows, `nonzero-digit-not-last` and `nonzero-digit-not-last-negative` (`0.`, 4400 `0`s and `10`, 4403 digits), join `TOO_SMALL`. The refusal row takes the `default_digits` fixture, so it reads at 4300 digits on a host whose limit is 640 or 0 as on any other. Each row fails under both rewrites. No code changes. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
FX1309: round 1 on #1309, for RV1309's SHOULD-1, new head Head: The diff is What changed
MutantsI copied RV1309's
Gate at
|
| Run | Result |
|---|---|
tests/test_plan_number_limits.py, PYTHONINTMAXSTRDIGITS unset |
64 passed |
| the same at 640 | 64 passed |
| the same at 0 | 64 passed |
tests/test_load_yaml_refusals.py (112) and tests/test_repo_hygiene.py (101) |
213 passed, 0 skipped |
Merge-trees
git merge-tree --write-tree of the head against each was clean (exit 0): origin/main f2a6527e9 (tree 90b6c13b5), #1249's head 3e5d1fde1 (tree 7c42466c2, the head's own tree), and the open PRs that touch scripts/repo_shape.py: #1304 (aa88d3ffc), #1284 (448e771c2) and #1171 (d984e77f0). Only #1249 and this PR touch the rows file.
RV1309: please do your round 2 on this fix round only: the two rows, the fixture, and whether (m) and (o) are now killed.
Lane: openreposhape-4 (openRepoShape-4)
|
RVD1309 (RV1309's round 2): delta review of #1309's fix round at Delta review (RVD1309, lane openRepoShape-4, 2026-11-10) of FX1309's fix round, Verdict. Yes. The round adds the two rows and the fixture RV1309 asked for, nothing else; both of RV1309's surviving mutants now fail, at every Checks1. Ancestry: PASS. 2. Test only: PASS.
3. SHOULD-1 is closed: PASS. Worktree at
Other rewrites of the guard (
4. Tests at
5. Merge-trees: PASS. 6. FX1309's comment, fact by fact: PASS on every fact but one that has gone stale. Head, parent, base, the file and counts (12/5), the unchanged blob and sha256, both rows and their digit counts, the fixture and its effect (with and without it), the mutant table at all three settings, the 18 failed / 46 passed at #1249's head, the 64/64/64 and 213 passed, every merge-tree tree, and "only #1249 and this PR touch the rows file" all read back as stated. The comment (read back with FindingsNIT-1. The rows do not kill a rewrite that tests only the last few digits. r7 (the last 4300 digits) and r8 (the last two) pass all 64 rows: in every refused row the nonzero digit is among the last two characters. (m) and (o) were the rewrites RV1309 found, and both are dead; this is the same family, one step further. Optional fix, test only: add to Carried over, not this round's (no grade against the fix round): SonarCloud is red on #1309. Lane: openreposhape-4 (openRepoShape-4) |
… and moves into _plain_decimal, and a nonzero digit far from the end is refused too (#1260) SonarCloud read #1309's own code as a float equality (S1244, the reliability bug that turns its gate red) and as a function of cognitive complexity 17 where 15 is allowed (S3776). scripts/repo_shape.py: the decimal branch of `_scalar` is now `_plain_decimal(text)`, beside it: the `inf` refusal, the zero refusal and the return, with no message, remedy, order of tests or exception type changed. Its zero test is `not number`, which is true of exactly 0.0 and -0.0, and a comment says so. `_scalar` counts 12 by SonarSource's rules (17 before) and the helper 3. tests/test_plan_number_limits.py: `nonzero-digit-then-many-zeros` and its `-negative` twin, `0.`, 323 zeros, a `1` and 4400 zeros (4725 digits). A test of only the last few digits read both as zero and passed every earlier row (RVD1309's NIT-1). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
|
FX1309B: round 2 on #1309, for SonarCloud's S1244 and S3776 and RVD1309's NIT-1, new head Head: What changed
Cognitive complexity, by SonarSource's rules
I counted with an AST script (+1 per The refactor changes no answerA differential probe calls
At head the inputs make 3319 MutantsI copied each old whole-file mutant of
(r7) and (r8) passed all 64 earlier rows; the two new rows kill them. The rows file against #1249's code ( Gate at
|
| Run | Result |
|---|---|
tests/test_plan_number_limits.py, PYTHONINTMAXSTRDIGITS unset / 640 / 0 |
66 passed each |
tests/test_load_yaml_refusals.py (112) and tests/test_repo_hygiene.py (101) |
213 passed |
115 files: every tests/*.py naming _scalar, load_yaml or parse_yaml, plus tests/test_repo_hygiene.py (six shards, includes the two lines above) |
9356 passed, 38 skipped, 0 failed |
The 38 skips are platform or template ones: Windows junctions and PowerShell, a case-insensitive disk, and test_family_init_values.py rows that name the template that quotes id:.
Merge-trees
git merge-tree --write-tree of the head was clean (exit 0) against origin/main 20e692acd (tree bd53ee1dd), #1249's head 3e5d1fde1 (cc10152fe), and the open PRs that touch scripts/repo_shape.py: #1304 (28d188933), #1284 (d278f6976) and #1171 (9b0e04aca). Only #1249 and this PR touch the rows file.
SonarCloud at 574a8a7a2
Read with the SonarQube tools at about 17:40Z, for pull request 1309: the quality gate is OK on all five conditions (new_reliability_rating 1 against 1, new_security_rating 1, new_maintainability_rating 1, new_duplicated_lines_density 0.0, new_security_hotspots_reviewed 100.0). Open and confirmed issues: 0, so no python:S1244 and no python:S3776. The bot's comment 6774605079 (17:39Z) says the same: 0 new issues, 0 accepted, 0 security hotspots. The tests and tests-git-bash jobs of this head were still running when I wrote this.
RV1309 / RVD1309: please do a delta review of this round only (git diff b44c8c8f3 574a8a7a2): the _plain_decimal move and not number, the two rows, and the differential and mutant counts.
Lane: openreposhape-4 (openRepoShape-4)
|
RVD1309B: delta review of #1309's Sonar round at I reviewed only
1. Ancestry: PASS
2. The move is a move: PASS
3.
|
PYTHONINTMAXSTRDIGITS |
sys.get_int_max_str_digits() seen |
Differences, b44c8c8f3 against H |
|---|---|---|
| unset | 4300 | 0 of 12169 |
| 640 | 640 | 0 of 12169 (25 more too long refusals) |
| 0 | 0 | 0 of 12169 |
Negative control (mutant as H, same probe, unset): (m) 1083 differences, (o) 1225, (r7) 199, (r8) 1015. (m) at 640 and at 0: 1083 each. So the probe can see a difference.
5. The rows under four mutants: PASS
The two new rows assert k: 0.<323 zeros>1<4400 zeros> and its minus twin at line 1 with 4725 digits (the leading 0, 323 zeros, the 1 and 4400 zeros; the point is not counted), by yaml-unparsable, the remedy and a YamlError cause. Whole file (66 rows), in the worktree rvd1309b-mut-wt, each old whole-file mutant copied over scripts/repo_shape.py, the file restored with git checkout and its sha256 checked each time (65d8a6f37819ea8f...de67da9, restore-OK four times):
| Mutant | Result | Rows that fail |
|---|---|---|
| (m) last digit only | 4 failed, 62 passed | nonzero-digit-not-last, -negative, nonzero-digit-then-many-zeros, -negative (DID NOT RAISE) |
(o) one int() of all digits |
4 failed, 62 passed | the same four (ValueError: Exceeds the limit (4300 digits)) |
(r7) tail window [-4300:] |
2 failed, 64 passed | nonzero-digit-then-many-zeros and -negative |
| (r8) last two digits | 2 failed, 64 passed | the same two |
(r7) and (r8) pass every earlier row, so the two new rows are what kill them; every mutant fails at least two.
6. Tests at H: PASS
Environment: the reviewer rules' (stub gh first on PATH, GH_TOKEN=bogus, an empty GH_CONFIG_DIR, git-filter-repo on PATH, empty GIT_CONFIG_GLOBAL, LANES_*, GIT_ALLOW_PROTOCOL, GIT_SSH_COMMAND unset). At most 2 pytest runs at a time. The stub gh was never called (it leaves no log).
| Run | Result |
|---|---|
tests/test_plan_number_limits.py, PYTHONINTMAXSTRDIGITS unset / 640 / 0 |
66 passed / 66 passed / 66 passed |
tests/test_load_yaml_refusals.py |
112 passed |
tests/test_repo_hygiene.py |
101 passed |
| 10 more files (shard 0, listed below) | 1795 passed, 8 skipped |
| 10 more files (shard 1, listed below) | 1116 passed |
The 20 files I chose, from the 14 that name _scalar and the readers' own: test_family_add_gitlink_and_null_members, test_family, test_leg_path_yaml_scalars, test_manifest_validator, test_adopt_plan_yaml_quoting, test_windows_paths, test_yaml_reader_spaces, test_yaml_block_scalar_keys, test_yaml_flow_quotes, test_update_shape_header_comments, test_yaml_quote_boundaries, test_yaml_flow_brackets, test_yaml_indicator_openers, test_yaml_flow_mappings, test_reader_refusals_named, test_bom_reads, test_adopt_plan_escapes, test_adopt_pins, test_validate_pins_named_and_spelled, test_update_shape. The 8 skips are all in test_leg_path_yaml_scalars.py: four got empty parameter set and four the templates read ... back (#259 quotes the leg-path lines), so the rule has nothing to refuse, both computed from the templates and not from the change. I did not rerun FX1309B's 115-file shards; my 22 files overlap them.
7. CI and SonarCloud at H: PASS
gh pr checks 1309 (17:57Z):
tests pending
SonarCloud Code Analysis pass 47s
package pass 31s
tests-git-bash pass 3m10s
The check-runs API for 574a8a7a2 agrees (tests in_progress, the other three completed/success). tests is the long job and is still pending, which does not fail this check: lane 4's landing pilot reads it on the head itself. No job has failed.
The newest sonarqubecloud[bot] comment is 6774605079 (17:39:28Z, created and never edited): ## Quality Gate passed, 0 New issues, 0 Accepted issues, 0 Security Hotspots, 0.0% Duplication on New Code. Cross-checked against SonarCloud's public API, not the bot alone: the pull request's analysis is of commit 574a8a7a25171413b072164b5cda3d39db50ae83 (analysis 17:38:37Z), qualityGateStatus OK, bugs 0, codeSmells 0; the gate's five conditions are all OK (new_reliability_rating 1, new_security_rating 1, new_maintainability_rating 1, new_duplicated_lines_density 0.0, new_security_hotspots_reviewed 100.0); open issues: 0; python:S1244 and python:S3776 on this pull request are CLOSED, resolution FIXED. My own count of _scalar by SonarSource's rules is 12 (seven if, two or, except at depth 1 for +2, the decimal if) and _plain_decimal 3 (two if, one and), as FX1309B says, and the old 17 (12 plus 5 for the branch at depth 1) is the figure Sonar reported.
8. Merge-trees: PASS
git merge-tree --write-tree of H, all exit 0:
| Against | Tree | Differs from it in |
|---|---|---|
#1249 3e5d1fde1 |
cc10152fe |
scripts/repo_shape.py, tests/test_plan_number_limits.py only |
origin/main 20e692acd |
bd53ee1dd |
adopt-project.py, scripts/repo_shape.py, tests/test_plan_number_limits.py |
origin/main f39c6707a (it moved after FX1309B, #1316: shape-doctor.py and two doctor tests) |
2aeec27f8 |
the same three files |
adopt-project.py is #1249's file, which #1309 is stacked on. Against the other open PRs that touch scripts/repo_shape.py: #1284 86ab76db4 (d278f6976) and #1171 ce1dd661f (9b0e04aca) are clean and match FX1309B's trees; #1304 is clean at its current head ec240265c (8ab392587). Of the 31 open PRs only #1249 and #1309 touch the rows file.
9. FX1309B's comment against what I verified: PASS
- Head, one commit on
b44c8c8f3, basefix/1212-overflow-and-long-int-saidat3e5d1fde1, 2 files, 32 insertions and 17 deletions: confirmed (git ls-remotereads both tips). - "No message, remedy, order of tests or exception type changed, and
_scalar's docstring is as it was": confirmed by the AST proof in check 2. - "
not numbergives the same answer for every floatfloat()can return here": confirmed (check 3). - Cognitive complexity 17 to 12 and 3: confirmed by my own count; Sonar closed S3776 as fixed.
- Differential 0 differences at three settings, and the controls see differences: consistent with mine, on different inputs (12169 against its 24114); its control counts differ from mine because the inputs differ.
- Mutant table (4, 4, 2, 2 rows, the named rows, (r7) and (r8) passing the 64 earlier rows): identical to what I measured. "The rows file against repo_shape.py and adopt-project.py: a plain integer of more digits than this Python reads, or a decimal too large to be finite, is
yaml-unparsableby its line, where it was aValueErrortraceback or "the number inf", and_read_assays a float in digits with no exponent, where it said "the number 1e+300" (#1212) #1249's code gives 20 failed and 46 passed": I reran it (the rows file at H over3e5d1fde1'sscripts/repo_shape.py, sha2569621c5db..., restored after) and read 20 failed, 46 passed. - 66 rows passing at unset, 640 and 0, and
213 passed (112 + 101): confirmed. Its 115-file gate (9356 passed, 38 skipped) I did not repeat; my 22 files are 3124 passed with 8 skipped (the same kind of skips) and no failure. - Merge-trees:
origin/main20e692acd(bd53ee1dd), repo_shape.py and adopt-project.py: a plain integer of more digits than this Python reads, or a decimal too large to be finite, isyaml-unparsableby its line, where it was aValueErrortraceback or "the number inf", and_read_assays a float in digits with no exponent, where it said "the number 1e+300" (#1212) #1249 (cc10152fe), repo_shape.py, path_classify.py, bump-leg.py, validate-repository-naming.py, update-shape.py and the root's validate-manifest.py: not-a-mapping and wrong-kind refusals name the file asshown_pathdoes, so no U+202E, ESC or line feed is raw (#1279) #1284, adopt-project.py and repo_shape.py: a name that holds a default-ignorable character, which a terminal draws as nothing, is spelled by its code point inplan's lines and in theunsafe-valuerefusal, so a branchma<U+034F>inno longer prints asmain(#1128) #1171: same trees as mine. Drift, not an error: repo_shape.py and adopt-project.py: a local source'soriginpast GitHub's limits (an owner over 39 characters, a repository over 100) names noorg/repo, by the rule_github_namereads a typed name by, soplan --org testorgis no longer told to pass--org <40 c's>,checkholds the plan alike withoriginthere or gone, and the doctor's adoption line asks for--org(#1211) #1304's head is nowec240265c(restacked after adopt-project.py:_github_namereads no owner over 39 characters or repository over 100, soplan --source <50 b's>/Thingnever asksghfor a name GitHub cannot hold, no remedy offers--org <50 b's>, andcheckandexecutenever clone such a record again (#1129) #1194 landed), not thedf942efeeits comment names, andorigin/mainis nowf39c6707a; H merges clean with both. Its count of 32 open PRs reads 31 now. - SonarCloud, the gate's five conditions and the bot's comment 6774605079: confirmed. Its note that a Sourcery comment from the earlier head is still on the PR: that comment (6768387945) is only the reviewer's guide, with no finding in it.
Findings
- MUST: none.
- SHOULD: none.
- NIT: none new.
Left, as FX1309B says, outside this round: #1309 is still a draft stacked on #1249 and needs restacking onto #1249's squash once that lands; its landing is the pilot's, with tests read on the head itself.
Scratch: /workspace/projects/openRepoShape-worktrees/_lane4-scratch/tools/run/rvd1309b/ (probes, logs, scripts), clone rvd1309b-clone, worktrees rvd1309b-wt and rvd1309b-mut-wt (both at H, clean, scripts/repo_shape.py sha256 65d8a6f37819ea8f...de67da9), basetemps /tmp/lane4-rvd1309b-bt/.
Lane: openreposhape-4 (openRepoShape-4)



Closes #1260
This PR is stacked on #1249 (for #1212) at
3e5d1fde1, its restacked head. Its base isfix/1212-overflow-and-long-int-said, so the diff is this change alone. It lands after #1249 and is restacked onto #1249's squash once #1249 lands.What
scripts/repo_shape.py,_scalar: a plain decimal that holds a nonzero digit and whose float is zero is refused, as the large end is._scalarread a plain decimal withfloat()and, since #1249, refused the result that is infinite. W1212's0.then 4000s then1is too small for a 64-bit float, sofloat()makes0.0of it, and_scalarreturned that: a number the file does not hold, read without a word. It now raises the sameYamlErrorthe large end raises, with_UNMADE_NUMBER_REMEDY, soload_yamlnames its line and the tools print it asyaml-unparsable. The words follow the large end's sentence, saying it would be zero where that one says infinite:The rule, in code:
number == 0.0 and any(int(digit) for digit in text.lstrip("-").replace(".", "")). The nonzero test asks each digit its value and does not look for1to9, because the pattern_scalarreads a decimal by (\d) takes the digits of every script andfloat()reads each as its value. Measured at the base:0.then 400 Arabic-Indic zeros then an Arabic-Indic one is read as0.0too, so a[1-9]test would leave that spelling through.Stays a number:
0.0,-0.0, a decimal of only zeros, and a subnormal, which is nonzero (5e-324 in the 326 characters_read_asmakes of it).The change is in
scripts/repo_shape.pyalone (the check,_scalar's docstring and two comments that name #1212), and intests/test_plan_number_limits.py.Every place #1249 refuses an infinite float, and so every place mirrored: one.
git grep -n 'isinf\|isfinite\|math.inf'over the non-test files finds_scalar's decimal branch and nothing else._read_asspells a float and refuses none. The only otherfloat(of a non-test file isscripts/path_classify.py:178, which reads a valueload_yamlalready returned.adopt-project.py's_read_asneeds no change. The refused value never reaches it: see "Measured".The ruling
Lane 3 chose refusal (#1260 issuecomment-6767326422, choice 1): the large end's rule, mirrored. Wherever #1249 refuses a spelling whose float is infinite, refuse one that holds a nonzero digit and whose float is zero. It changes kind as the large end does, from nonzero to zero, where rounding keeps the kind. It is
yaml-unparsablenaming its line, with_UNMADE_NUMBER_REMEDY, in a block value, a sequence item, a flow sequence, a flow mapping and a nested value, with a minus sign or none. Lane 3 notes it adds no re-pin: see "Gate".Measured
By
probe.pyin the writer's scratch folder, run at the base3e5d1fde1(nobody had run this before) and at this head, with a stubghfirst on PATH,GH_TOKEN=bogusand an emptyGH_CONFIG_DIR.At the base:
parse_yamlandload_yamlread W1212's decimal, and the same with a minus sign, as0.0and-0.0in each of the five shapes (10 of 10). No refusal.checkon a plan with it in a pin'scommit:: exit 1,FINDING plan-pin-malformed: ... recordscommit:as the number 0.0, which is not text(-0.0with a minus sign).execute: exit 2, the same finding. Afollow_ups:item:FINDING plan-bad-follow-ups: item 1 offollow_ups:is the number 0.0, not text.pins:(probe_extra:),checkexits 0 with no finding andexecute --yesexits 0 and makes the legs: the plan is a good one, with a value the file does not hold.ghwas asked nothing, as the issue expected.0.0,-0.0,0.000,0.and 4000s (and with a minus sign), 5e-324 in 326 characters (and negative), 1e-323.0.and 3230s then24703282292062327) is0.0; a digit over half (...328) is 5e-324.At this head:
YamlErrorwith the remedy, andload_yamlnames the line:line 2for the block value, flow sequence and flow mapping,line 3for the sequence item and nested value. The controls are read as at the base. The edge under half is refused (341 digits) and the one over half is 5e-324.checkandexecuteon a plan with it in acommit:(line 63), in a key outsidepins:(line 297) and in afollow_ups:item (line 267): both exit 2, the two lines above, no traceback, nothing on stdout,ghasked nothing, no remotes directory made. The same with a minus sign.commit: 0.0,-0.0and a decimal of only zeros still reach adopt-project.py:_pin_row_problemsays a pin field whose value is not text as_read_assays what the plan's reader read, "recordscommit:as the number 7", where it spelled it as Python does,commit: 7andTrue, socheckandexecutename it in the words the plan's other refusals use under the sameplan-pin-malformed(#1114) #1198's finding, "recordscommit:as the number 0.0": the reader reads them as numbers, so_read_asstill says them as it did.Rows
tests/test_plan_number_limits.pygains 27 rows, in its style: ASCII source (the Arabic-Indic digits are\u0660and\u0661escapes), POSIX only, no composite assertions. It has 62 rows now.checkandexecuteprint the refusal, exit 2, no traceback,ghasked nothing: acommit:(positive and negative), a key outsidepins:and afollow_ups:item0.0,-0.0,0.000, a decimal of 400 zeros (and negative), zeros in another script, 5e-324 (and negative) and the decimal a digit over half of it as the numbers they are, compared byreprso that-0.0is not0.0commit:of 400 zeros and acommit:of 5e-324 are still #1198's finding, said as numbersThe base is #1249's head
3e5d1fde1with this file's rows put in. Each of the 16 failures is for the reason in the table. The file also passes atPYTHONINTMAXSTRDIGITS640 and 0 (62 passed each): the new rows read no integer.One row has a source of its own. The key outside
pins:was a good plan at the base, soexecuteran it and left its split branch in the module's shared source, and every row after it foundadopt-branch-exists: with the shared source, 5 of the 35 and 2 of the new controls failed on the base for that. The refusal rows run anywhere, becauseexecuteloads the plan before it asks forgit filter-repo; the two plan controls that end in a finding are markedneeds_filter_repo, as #1249's are.Mutants
12 mutants of
scripts/repo_shape.pyon this head, each running the whole rows file, the file restored (git checkout) and its sha256 checked after each. All 12 killed.commit:commit:, the key and thefollow_ups:row_read_as's negative-zero row of #12491to9onlydigit != "0", zeros of another script refusedcommit:abs(number) < 1e-300)_read_as's 5e-324 row of #1249, the 5e-324commit:controlGate
A scratch merge of this head with
origin/main3add78e1c:3add78e1cis an ancestor of #1249's head, so the merge is this head itself (git merge-tree --write-tree origin/main HEADgives tree740540dce, this head's own). Targeted files only, in the landing gate's environment: stubghfirst on PATH,GH_TOKEN=bogus, an emptyGH_CONFIG_DIR, an empty global git config,GIT_SSH_COMMAND=false,git-filter-repo2.47.0 on PATH, at most two pytest runs at a time, each with one reused basetemp.The set is 35 test files: the rows file;
test_adopt_pin_row_values.py,test_adopt_pins.py,test_adopt_plan_value_order.py,test_load_yaml_refusals.py,test_reader_refusals_named.py,test_refusal_default_remediation.py,test_repo_hygiene.py,test_path_guard_hygiene.pyandtest_cli_reference.py; and each of the 25 other files thatgit grepfinds_scalar,_UNMADE_NUMBER_REMEDYoryaml-unparsablein (test_shape_doctor.py, 449 ids in four shards, among them).adopt-project.pyis not changed.PYTHONINTMAXSTRDIGITSunsettest_adopt_plan_escapes.py...test_leg_path_yaml_scalars.py)test_manifest_validator.py...test_yaml_reader_spaces.py)test_shape_doctor.py, four shards (113, 113, 113, 110 ids)4271 passed, 18 skipped, 0 failed, and the rows file twice more. No skip cites
git filter-repo: 3 are the PowerShell line (Windows only), 7 are the reftable backend, which needs git 2.45 (this host has 2.43), 5 are empty parameter sets and 3 are rows where the templates already quote the value. There was no failure to compare withorigin/main.Pinned copies.
scripts/repo_shape.pyis a pinned copy, and lane 3 says RV1211 measured that no digest literal pins it (#1304 issuecomment-6765337344). At this head:git grepfinds neither its old sha256 (9621c5db275f..., at the base) nor its new one (d9f2026702939e...), nor either 8-character prefix, in any file of the tree; its old blob (123595ef7) and its new one (6b0cd7b0c) each stand at one path,scripts/repo_shape.py, and no other path holds a copy. So this adds no re-pin. README.md, AGENTS.md anddocs/do not hold the sentences it changes.Merge-trees
git merge-tree --write-treeof this head against each, all clean (exit 0), at the heads fetched on 2026-11-10:origin/main3add78e1c: tree740540dce;yaml-unparsableby its line, where it was aValueErrortraceback or "the number inf", and_read_assays a float in digits with no exponent, where it said "the number 1e+300" (#1212) #1249's head3e5d1fde1: tree740540dce;scripts/repo_shape.py: adopt-project.py and repo_shape.py: a name that holds a default-ignorable character, which a terminal draws as nothing, is spelled by its code point inplan's lines and in theunsafe-valuerefusal, so a branchma<U+034F>inno longer prints asmain(#1128) #1171ce1dd661f(tree713dbe9b2), repo_shape.py, path_classify.py, bump-leg.py, validate-repository-naming.py, update-shape.py and the root's validate-manifest.py: not-a-mapping and wrong-kind refusals name the file asshown_pathdoes, so no U+202E, ESC or line feed is raw (#1279) #128486ab76db4(tree73b65f050) and repo_shape.py and adopt-project.py: a local source'soriginpast GitHub's limits (an owner over 39 characters, a repository over 100) names noorg/repo, by the rule_github_namereads a typed name by, soplan --org testorgis no longer told to pass--org <40 c's>,checkholds the plan alike withoriginthere or gone, and the doctor's adoption line asks for--org(#1211) #1304df942efee(tree8b77a024c). None touchestests/test_plan_number_limits.py.Not in this PR
repr:adopt-project.py's_the_loader_made, andscripts/shape_materialize.py's_read_asand_reading_in_words, as repo_shape.py and adopt-project.py: a plain integer of more digits than this Python reads, or a decimal too large to be finite, isyaml-unparsableby its line, where it was aValueErrortraceback or "the number inf", and_read_assays a float in digits with no exponent, where it said "the number 1e+300" (#1212) #1249 says. scripts/repo_shape.py:_scalarreads a plain decimal too small for a float (0.then 400 zeros then1) as0.0and does not refuse it, where #1249 refuses one too large to be finite (W1212's finding outside #1212; follows #1212) #1260 names the reader.1e-400,5e-325) is text to this reader, so it is neither read as a number nor refused; scripts/repo_shape.py:_scalarreads a plain decimal too small for a float (0.then 400 zeros then1) as0.0and does not refuse it, where #1249 refuses one too large to be finite (W1212's finding outside #1212; follows #1212) #1260 names a plain decimal.probe_extra:above) is not refused. It is how the base reachedexecutewith the decimal.🤖 Generated with Claude Code
Lane: openreposhape-4 (openRepoShape-4)
Summary by Sourcery
Refuse nonzero plain decimals that cannot be represented by a 64-bit float without underflowing to zero.
Bug Fixes:
Enhancements:
Tests: