Repository navigation
Document what stops Lean indexing - #234
Conversation
Since #95, Lean indexing fails closed, but the documentation never said which entries stop it. An unreadable .lean file, a folder that cannot be listed or searched, an unreadable manifest.json in any subfolder, or a .lean symbolic link or special file stops the whole index, including in folders unrelated to Lean (C7, C2, NEW-MANIFEST-UNREADABLE). The .lean suffix and the manifest.json name are matched in any letter case. For render the implicit Lean root is the blueprint's parent, so this reaches folders next to the blueprint, and there is no CLI exclusion. The docs also claimed more than the capture does (C6, B-F1). Docstrings and the CLI README described a capture as one immutable or stable generation, but only the root descriptor is retained: descendants are reopened by name and rechecked by (dev, ino, file type) and their full name list, so coordinated moves across folders between those checks are not detected. The CLI README now lists the stopping entries, the letter-case rule, the remedy (permissions, or moving the entry out of the root or into a skipped folder) and the retention model, and the work impact paragraph no longer claims a retained generation. snapshot_project_sources names the stopping entries. These docstrings no longer call a capture one generation: the _tree_snapshot module docstring, TreeSnapshotError, _TreeChanged, BoundDirectoryTree.capture and bind_directory_tree in _tree_snapshot.py; IndexedSourceSnapshot, BoundProjectSources and bind_project_source_snapshot in lean.py; _captured_source_lines in audit.py; and project_modules in impact.py. Docstrings about the retained root directory itself are accurate and stay. No behavior changes.
Descriptor capture rechecks each descended folder by identity and full name list, so one file moved between two folders three times, timed to the walk, yields an accepted snapshot that no single state had (B-F1). The documentation now discloses this; nothing in the suite exercised it, so a change that closed the gap or widened it would go unnoticed. The test moves Zed/Y.lean to Proj/X.lean just before Zed is first listed, back before final verification, and to Proj/X.lean again just before Zed is relisted for verification, after Proj was verified. The listing hook wraps os.scandir and os.listdir and matches Zed by fstat identity, and every move happens only in the first capture attempt. It is xfail(strict=True) and only its own pytest.fail, reached after all three moves happened and the snapshot lacked the file, counts as the expected failure. If the moves never start, a plain assertion fails. If capture keeps the file or rejects the first attempt partway, the strict XPASS says the pin and the disclosure should go. The fix-round version moved the file after Proj was listed; main's end-of-scan relist rejects that timing and the pin would XPASS, so move 1 now happens at Zed's first listing.
The branch also rewrote what a capture guarantees: a README paragraph and the _tree_snapshot module docstring describing root-only retention and the cross-folder gap, generation wording in seven docstrings and the work impact paragraph, and a strict xfail pinning the three-move mixture. fix/lean-capture-unrelated-churn (#257) changes that guarantee and replaces the same README paragraph and module docstring with its own text, so the two branches conflicted and a reviewer had to read the guarantee twice. The guarantee belongs with the change that redefines it, so this branch drops all of it, including the pin, and keeps only what stays true either way: what stops Lean indexing and how to clear it. The snapshot_project_sources docstring copy of that list goes too; the README is its one home.
Since #165, render passes a publication.json marker to Lean indexing: a folder holding a complete publication manifest is skipped, and an unreadable publication.json below the root stops render's indexing like an unreadable manifest.json does. The stop list predated #165 and named neither, so a render user with an unreadable site manifest had no documented cause or remedy. Name both, and state the letter-case rule once at the end instead of per entry, so the exact-suffix change in #232 narrows one clause. The sentence promising root-relative error paths is dropped; it is not part of what stops indexing, and #237 changes which path errors name.
The stop list sat right after the descriptor paragraph, where #257 inserts its capture-guarantee paragraph, so the two branches conflicted on adjacent insertions. One paragraph later it stays in the Validation section and no open PR edits the lines around it.
The stop-list paragraph said the `.lean` suffix matches in any letter case. That holds on main, but #232 makes the suffix match exactly, so whichever of the two landed second would have left the README wrong. Drop the suffix from the sentence; the file and folder names it lists still match in any letter case except `build`, on main and with #232.
Review at 359f9f2Verdict: Needs one fix before merge. The PR adds one paragraph to the README's Validation section (+18/-0, docs only). It says Lean indexing is all-or-nothing, lists what stops it, and says how to clear a stop. Since #95, an unreadable folder anywhere under the Lean root fails Fixes before merge
Optional
Landing
Decision for the maintainer
This was a static review: no tests were run locally. CI at this head: all 9 checks pass. Posted by PR swarm: PR Swarm Lead |
|
Merge readiness: needs one small fix (reviewed at 359f9f2)
Merge order: any time after the fix. It merges cleanly with current main (abae767) and with every open sibling, including #257, which edits a different README paragraph. It is a draft, so it needs to be marked ready before merging. |
The closing sentence of the Lean stop list said file and folder names match in any letter case except build. Read next to the .lean entries the paragraph lists, it claimed A.LEAN is indexed. Since #232 the walk compares the .lean suffix exactly, so the sentence misled. Name the names that fold (the skipped folder names, manifest.json, publication.json and .git), keep build as the lowercase-only exception, and state that the .lean suffix must match exactly.
|
Update: fix pushed, now ready to merge (32057cf)
Follow-ups for whichever lands second: #270 removes |
#237 sends every by-name lookup through _lookup, which blames the folder, and every refused open, read or readlink through _access_denied. The ten _tree_snapshot.py hunks keep this branch's vanish handlers and named changes and call #237's helpers inside them. _PermissionDenied is not an OSError, so the handlers pass it through. The symbolic link branch is split: a refused readlink goes through _access_denied and the confirming lookup through _lookup. _read_file keeps this branch's keyword-only relative=. Final verification's verify_child_directory and the recorded names in verify_selected_directory use the same helpers, so anything the scan recorded is blamed by #237's rule. Refusals in the selected-mode relist and in _require_no_inputs stay changes and are never accepted; the retry's scan names the folder if the refusal lasts. test_folder_refused_to_a_selected_recheck_is_not_accepted[lookup] now expects "permission denied: site" instead of the pathless message. #268 removed expected_children, so this branch's selected-mode guard in capture_directory_descriptor (an undefined name after the merge) and test_selected_capture_refuses_expected_children go. #269 removed tolerated_links. The lean.py hunks keep this branch's lines without it; the include filter still skips .#*.lean lock links. #234 added a README stop list. This branch's capture paragraph moves after it, refers to "a folder the walk skips" instead of repeating the marker list, and says non-.lean files may change instead of "ignored unless they are .lean files", which contradicted the skipped lock links.
facebookresearch#234 documented the folders the Lean walk skips and listed lake-packages. facebookresearch#270 removed that name from _IGNORED_DIRECTORIES, so a folder named lake-packages is now indexed and moving an entry there no longer clears a stop. Remove the name from the list so the README matches lean.py and nothing in the repository names lake-packages.
Summary
autoform_cli/README.md: what stops indexing, that the stops apply in every folder under the Lean root, which folderrenderuses as the Lean root by default, which folders the walk skips, that there is no command-line exclusion, and which names match in any letter case (the skipped folder names,manifest.json,publication.json,.git; notbuild, and not the.leansuffix, which is exact since Count only the exact .lean suffix as Lean source #232).Behavior changes
None. One README paragraph (+20 lines).
Tests
No test changes. Each claim was checked by a throwaway probe that builds a Lean root and calls
snapshot_project_sources, on main ae2db51 and on #257's head, with the same results. The letter-case sentence was checked againstautoform_cli/lean.pyand_tree_snapshot.pyon main abae767.Overlap with open PRs
The branch merges cleanly with main abae767. The paragraph sits after the permalink paragraph, away from #257's insertion point after the descriptor paragraph. If #235 lands after this, it should qualify the "
renderwithout--lean-root" sentence for hosts without descriptor capture.Validation
tests/test_search.pyandtests/test_skill_examples.py(the tests that read this README): 90 passed on Python 3.13 at 32057cf.ruff check autoform_cli servers tests: clean.