Record project stack facts after creation, with detection as evidence - #699
Merged
Merged
Conversation
…#648) The priority policy already raised work from a project's `framework` or `cms` fact, but nothing could write one after `project new`: a stack had to be typed in by hand, and `tech-detect` never reached `project.json`. `project-facts` closes that link. Supplied facts are operator decisions and always win; `--detect` runs one `tech-detect` pass over the project's own target and records what it saw as evidence under its own provenance, so the record says which is which. A detection never overwrites an operator-entered fact. It reads robots.txt first and fetches at most twice, through the same guarded single-page tools the standalone commands use, and it runs only where it was asked for -- `project-prepare` does not run it. A failed, disallowed or ambiguous detection leaves the fact absent with its reason instead of guessing.
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Advances #648 (child C: priorities raised by what the site is actually built on, detected by
tech-detectand recorded inproject.json). The epic stays open.The gap
seohead/projects/priorities.pyalready raises work from a project'sframeworkorcmsfact, but nothing could write a fact afterproject new:grep -rn tech_detect seohead/projects/returned nothing, andprepare_projectran crawl/sitemap/competitors/plan only. A stack had to be typed in by hand at creation.What this adds
project-facts/seo_project_facts, registered through the shared handler in both interfaces:seohead project facts --directory ./example-project --input '{"facts":[...]}' --apply seohead project facts --directory ./example-project --detect --applydetected_valuewith the actionkept_operatorand leaves the record alone. Which is which is carried by the fields the schema already had — a detected fact'sprovenancestarts withdetected by tech-detectand names the marker that matched and the URL it was seen on, andobserved_atis that observation's time. A supplied fact claiming that provenance is refused.--detectis the only thing that makes a request, and never implicit. It readsrobots.txtfirst and fetches the project's own target once — two requests at most, through the same guarded single-page toolstech-detectandrobots-checkuse, so it inherits their pinning transport. A disallowed path is not fetched; rules that could not be read are a refusal, not permission.project-preparestill runs no detection.detectionblock always names astate(run/partial/not_run/unavailable) and a reason. A failed fetch, a disallowed target, a category with no matching signature, and a category where two candidates matched each leave the fact absent with its own reason. Nothing is guessed.--applywritesproject.jsonthrough the existing locked, backed-up atomic document writer. Recording a fact does not reorder work by itself —project-priorities --applystill does that, explicitly.Detection covers the
cmsandframeworkfacts the packaged policy consults; the fact name is thetech-detectcategory name, so there is no translation table to drift.site_typeand anything else remain operator-entered.The core stays free of
cliandservers: the detection tools are injected, the same wayprepare_projecttakes them.Tests
tests/test_project_facts.py(14) andtests/test_project_facts_interfaces.py(4). Every detection is injected; no test makes a request. Positive, failure, unavailable and partial paths are covered: unreadable robots, disallowed target, failed detection, no signature, ambiguous candidates, a generator version label that is not a second candidate, and forged detection provenance. Onorigin/mainthe new files fail —ModuleNotFoundError: seohead.projects.factson collection, and 4 failed in the interface module.Gates
ruff check .,ruff format --check .— clean.pytest tests/test_registration.py tests/test_docs_drift.py tests/test_doc_counts.py -q— passed.pytest -q— 4543 passed, 2 skipped in 6:49.Docs:
docs/PROJECTS.mdgets a "Recording stack facts" section;docs/TOOLS.md,docs/INPUTS.mdanddocs/TOOL_REFERENCE.mdare updated (the last two regenerated), with the command counts inPROVENANCE.md,docs/COMPARISON.md,docs/SKILLS.md,docs/USAGE.mdanddocs/scenarios/README.mdmoved to 93/98.changelog.d/648.mdadded.