Feat/issue 271 search metadata - #272
Open
Liu233w wants to merge 8 commits into
Open
Conversation
Every page sent a <title> and nothing else, so a search engine built its own snippet out of the first text it found. On the home page that is the terminal banner ($ pip install ojhunt), which tells a reader nothing about the project. A shared link showed no preview either. base.html.jinja now carries a meta description, a canonical link, and the Open Graph tags. Each page declares its summary in a meta_description block; the home and About pages inherit the default, which summarises the project as a whole. Descriptions stay at 160 characters or shorter, where the snippet is cut. The easter-egg routes answer 200 on 40+ scanner paths (/admin, /.env, /wp-login.php). Those pages and the 404 page now send noindex and no canonical URL, so they stay out of the index. Page routes render through the new render_page() helper, which supplies the absolute base URL and the canonical URL from the request — the same request.base_url pattern robots.txt and sitemap.xml already use. Resolves #271
The format hook runs `ruff check --fix` after every Python edit, so an import added before its first use is deleted before the next edit runs. It happened twice in one session and surfaced both times as a NameError far from the cause. The page-metadata work also produced a doc section that restated what the code already said. Sharpen the routing rule that should have stopped it: prefer a test that discovers what it checks over a written rule, and keep prose for the intent a test cannot express.
Contributor
|
Tick the box to add this pull request to the merge queue (same as
|
The routing table in docs/development.md told an agent where to look, but nothing made it look at the moment it mattered. Two conventions were missed in one session: comments were written above asserts instead of inside them, and a fact already covered by docs/dev/python.md was duplicated into hooks.md. Conventions tied to editing a kind of file move to .claude/rules/*.md with paths: frontmatter, so they enter context when a matching file is opened rather than waiting to be looked up. Six rules cover Python, tests, e2e, the web layer, docs and hooks. Three kinds of knowledge stay in docs/dev/, because no file pattern can trigger them: a new crawler starts as a file that does not exist yet, ops work touches no repo file, and questions like "does this warrant an ADR" precede any file. The routing table now carries only those. The update-env skill records the split and the compaction caveat. format-lint-python.sh gains one check: a comment directly above an assert in a test. It reads the edit payload rather than the file, so the cases already in the suite do not fire on every unrelated edit.
A comment above an assert is invisible when that assert fails; a message prints. .claude/rules/python.md already says so, but 45 sites across 27 files predate the rule, which makes it read as optional to anyone skimming the suite. Most were one of two boilerplate lines repeated across the crawler tests. Those became messages that state the invariant rather than restating the call — "solved_list must hold one entry per solved problem" instead of "Check that solved_list has the correct length". The rest carried real reasoning and moved into the message verbatim. This clears the way for a lint rule to enforce the convention repo-wide.
The comment-above-assert check was an awk program inside format-lint-python.sh. Being line-based it could not tell code from a string literal, so it flagged the example snippets inside the very test file that documents the rule. It also read the edit payload rather than the file, purely to route around violations that already existed in the suite. Rules now live in lint/rules/. ./doit.sh lint runs them over the repo and the hook runs the same files over the one file that changed, so the two cannot disagree. This rule is Python, not ast-grep YAML, because it needs source position. A trailing comment and an own-line comment are the same shape in the parse tree, and the YAML version reported one violation three different ways depending on what came after it: the line below when another assert followed, nothing at all when a non-assert followed or the body ended, and a false positive when the trailing comment belonged to an assignment. sgconfig.yml and lint/rule-tests/ stay for rules that are purely structural, where YAML reads better than code. tests/lint/ pins which line each case is blamed on, including the cases that must stay silent. rules_are_tested_test.py discovers rules from the directory and fails when one ships without tests, so this is not a convention to remember. ./doit.sh lint-rules joins full-check. The parser-based rule found four trailing comments the line-based one missed; those are folded into their assert messages.
Liu233w
force-pushed
the
feat/issue-271-search-metadata
branch
from
August 14, 2026 10:02
da940e8 to
c774d53
Compare
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.
No description provided.