Repository navigation
Conversation
This was referenced Nov 7, 2026
MaxGhenis
force-pushed
the
manifest-pyyaml
branch
from
November 9, 2026 22:38
d7e187d to
cc0a9f7
Compare
MaxGhenis
marked this pull request as ready for review
November 11, 2026 05:51
- build_manifest.py exits 1, writing nothing, when it can't import PyYAML, instead of falling back to a subset parser that turned numbers into strings and dropped nested fields (which broke the Analyses page). It also stops, naming the file, on frontmatter that isn't a YAML mapping. The subset parser and the regex category fallback are gone. - The dashboard's manifest hooks run the builder through uv. manifest:safe keeps the committed manifest when the build can't run. - --check builds the manifest without writing it and exits 1 when the copy on disk differs anywhere but generated_at. A new CI job runs it on Linux under Python 3.11 and 3.14. - IDF comes from decimal's correctly rounded ln rather than math.log, which rounds as each platform's C library does; shared_terms break ties by term. - Overlap pairs stay in artifact order, so a one-skill edit rewrites only the scores it moves (#106's edit: 242 changed lines instead of 1,084). The drawer and the Duplicates view sort pairs by score themselves. - Tests: a builder without PyYAML, frontmatter types and errors, --check, overlap order, guards against the built-in sum() and math.log, and a Hypothesis property that overlaps ignore artifact and word order. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…anifest Python 3.15 has shipped (CPython is at 3.15.2), so the manifest job's newer entry moves from 3.14 to 3.15. The job's comment called its pair the oldest and newest Python the repo supports, which 3.14 no longer is. The test job already runs 3.15.2. On macOS, the committed manifest matches a fresh build under every Python from 3.11 to 3.15. --check printed a traceback when the file on disk held JSON that wasn't an object. It now says so and exits 1, and a test covers that case and invalid JSON. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#108 edited skills/policyengine-data/SKILL.md without rebuilding the manifest, so main's copy lacked that edit. Rebuilding adds the edited artifact, one new overlap pair and the 113 scores the edit moves, and updates repo_coverage. Built from the same corpus, main's builder and this branch's give the same 326 pairs and the same scores. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tmatter
Review r3 found that every read used the locale's encoding. Under a
Latin-9 locale on Python 3.11, the build stopped on frontmatter that is
fine ("unacceptable character #x0080"); on Windows before 3.15 it would
misread the same text. Every read now goes through read_utf8, and the
manifest is written as UTF-8 with "\n" line endings.
- test_builder_never_uses_the_locale_encoding runs the build and --check
with EncodingWarning as an error, so any read or write that leaves the
encoding out fails it on every Python version.
- test_bad_frontmatter_makes_the_script_exit_1_and_write_nothing pins the
exit status that CI's --check and the predev hook rely on.
- The CI manifest job installs dependencies in its own step, and its error
no longer calls every failure a stale manifest.
- The IDF comment counts (n, df) pairs, not ratios, and says how the
decimal result becomes a float.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#92 edited the SKILL.md of three skills (policyengine, policyengine-tools, policyengine-uk), a reference file of a fourth, the reform-comparator agent and all eight bundles without rebuilding the manifest, so main's committed manifest no longer matched its sources. On main's corpus, main's builder and this branch's give the same 324 pairs and scores; only overlap order and 7 shared_terms lists differ. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
force-pushed
the
manifest-pyyaml
branch
from
November 11, 2026 05:54
f895efe to
54d0e28
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.
Closes the gaps #105 left in
scripts/build_manifest.pyand the dashboard's build hooks: its follow-up items 1 to 3, plus the diff-size problem #106 hit. Draft until CI passes on Linux and an independent review agrees.1. A missing PyYAML stops the build
main()prints how to run the script through uv and exits 1 before it writes anything.parse_frontmatterraises the same message for direct callers.parse_yaml_subset). Every frontmatter block in the repo's skills, agents, commands and analyses parses as a YAML mapping, so nothing needs it, and its output broke the Analyses page. The regex scan formetadata.categoryinload_skillsexisted only for that path, and no skill used it, so it went too.FrontmatterErrorthat names the file. Before, it dropped silently to the subset parser.read_utf8) and writes the manifest as UTF-8 with\nline endings. Before, every read used the locale's encoding: under a Latin-9 locale (LC_ALL=en_US.ISO8859-15) on Python 3.11, this PR before the review fixes stopped onskills/policyengine/SKILL.mdwith "unacceptable character #x0080", and main's builder exits 0 after corrupting 5 of the 6 analyses (numbers turn into strings in 4, and all 5 lose their country) and finding 323 overlaps instead of 326 (on main at a8d02cf). Python 3.15 runs in UTF-8 mode by default, so it wasn't affected. Both versions now match the committed manifest under that locale.dashboard/package.json,manifestrunsuv run python scripts/build_manifest.py.manifest:saferuns the same command and keeps the committed manifest when the build can't run.Before this PR,
/usr/bin/python3 scripts/build_manifest.py(macOS's Python 3.9.6, no PyYAML) exited 0. It wrote"child_poverty_pct_change": "-34.8"and"country": nullinto every analysis. Now:I ran the package.json scripts through bun, which runs the same script strings:
manifest, uv on PATHmanifest, no uv on PATHuv: command not found, exit 127, manifest untouchedmanifest:safe, no uv on PATHmanifest:safein a copy ofdashboard/alone/usr/bin/python32. CI checks that the manifest is fresh
--checkbuilds the manifest without writing it and compares it with the file on disk, withgenerated_atblanked in both. On a mismatch it prints the sections that differ, the first 200 diff lines and the command that fixes it, then exits 1. When the file on disk isn't valid JSON, or holds JSON that isn't an object, it says so instead of raising a traceback.manifestjob in.github/workflows/test.ymlruns--checkonubuntu-latestunder Python 3.11 and 3.15, the oldest and newest Python the repo supports. The existingtestjob already runs the suite under 3.15. The job installs dependencies in its own step, so a failed install shows as that step failing rather than as a stale manifest, and its error annotation says the log gives the reason.compute_overlapsnow takes IDF from thedecimalmodule's correctly roundedln, notmath.log, which rounds however the platform's C library does. On macOS,math.logmisses the correctly rounded value ofln((n + 1) / (df + 1))for 44 of the 79,799 pairs with 2 ≤ n < 400 and 1 ≤ df ≤ n. So a manifest built on a Mac could fail the Linux check whenever the artifact count hit one of those ratios. None of them occurs at today's 80 artifacts, so no score changes.manifestjobs report that the manifest I built on macOS matches a fresh build: under CPython 3.11.18 and 3.15.2 at the head, and under 3.11.18 and 3.14.10 at the first push. In a fresh clone, editing one skill without rebuilding makes the same command exit 1 and listartifacts, overlapsas the sections that differ.--checkmatches under Python 3.11.15, 3.12.14, 3.13.13, 3.14.7 and 3.15.2, and under 3.11.15 and 3.15.2 withLC_ALL=en_US.ISO8859-15.shared_termsnow break exact ties by term, so their order never depends on where a word first appears in a text. On main's current corpus (d34fd48) that reorders 7 of the 324 lists; in 3 of them a different term makes the 8-term cut.3. A test guards fsum
test_overlaps_never_use_builtin_sumswaps the built-insum(), asbuild_manifestsees it, for one that returns 1% more for floats, then checks thatcompute_overlapsreturns the same pairs. A manifest comparison would catch a return tosum()only on Python 3.11, wheresum([0.1] * 10)gives0.9999999999999999(3.12 on gives1.0). This test fails on every version.test_overlaps_never_use_the_c_librarys_logdoes the same formath.log.Mutation check: each of these edits to the builder makes its test fail:
sum()for the normsum()for the scoremath.logfor IDF--checkthat ignores contentRemoving only
main()'s PyYAML check changes nothing a user sees, sinceparse_frontmatterstill raises the same message, so that test still passes.test_check_fails_cleanly_on_a_malformed_manifestfails against this PR's first push, whose--checkraisedAttributeErroron a manifest holding[].Two tests came from the review:
test_builder_never_uses_the_locale_encodingruns the build and--checkwith-X warn_default_encoding -W error::EncodingWarning, so a read or write that leaves the encoding out fails it under every Python version, 3.15 included. It fails ifread_utf8drops its encoding, if one input goes back toread_text(), or if the write drops its encoding.test_bad_frontmatter_makes_the_script_exit_1_and_write_nothingfails ifmain()returns 0 after aFrontmatterError. CI's--checkand the dashboard'spredevhook rely on that exit status.4. Overlap diffs shrink
compute_overlapsno longer sorts pairs by score. They follow artifact order: bya, then byb.dashboard/src/data.tsexportsoverlapsByScore, a stable sort by score, andDrawer.tsx(first 8) andDuplicates.tsx(first 50) read it. A stable sort keeps tied scores in artifact order, the order the old manifest gave them, so both views list the same pairs in the same order as before. The shared terms they print change for 4 pairs, because of the term tie-break in section 2: the Drawer's first 5 for program-reviewer and backdate-program, and the Duplicates page's first 6 for that pair and for dashboard-planner and dashboard-scaffold, prior-scores-finder and prior-scores, and prior-analysis and prior-scores. I checked:policyengineskill's drawer: the same 8 pairs in the same order, three of them tied at 23%, checked in the browser at the first push.bundles_rawandrepo_coverage. Built from main's current corpus, main's builder and this branch's give the same 324 pairs and the same scores, and differ only inoverlaps: their order and 7shared_termslists. The manifest diff has 3,908 insertions and 3,929 deletions, nearly all from reorderingoverlapsonce.5. Left out: the 6,000-character cap in
infer_target_repos47 of the 80 artifacts have bodies longer than 6,000 characters. Dropping the cap adds 67 artifact-to-repo links across 26 artifacts (66 before #108). It would also make a separate bug worse: aliases match as substrings. "SSI" matches inside "missing" in 17 artifacts (policyengine-us), "PIP" inside "pipeline" in 11 (policyengine-uk), and "GIS" inside "registry" or "legislative" in others (policyengine-canada). Word-boundary aliases on their own remove 64 links. Both changes move
repo_coverageenough to need their own review, so they belong in a follow-up: #109 takes them up.Invariants
generated_at, whatever the hash seed (tests), the Python version from 3.11 to 3.15 (macOS runs of each; CI checks 3.11 and 3.15 on Linux), the platform between macOS and Linux (CI on Linux against the manifest I built on macOS), or the locale (the EncodingWarning test, and macOS runs under Latin-9).--checknever writes.overlapslists each pair once,abeforeb, in artifact order.shared_termsdepend only on the words in the corpus, not on the order of artifacts or of words within a text (Hypothesis property test).sum()or the C library'slogrounds.Tests
uv run pytest --ignore=tests/test_skill_examples.py: 224 passed (Python 3.14.7, macOS). CI'stestjob runs the same suite under CPython 3.15.2 on Linux.tests/test_build_manifest.py: 21 passed under Python 3.11.15 too.bun run build(tsc -b && vite build) passes.Other PRs that touch the manifest
Rebase onto main and regenerate with
uv run python scripts/build_manifest.pyrather than hand-merging; this PR did that on top of #108 and again on top of #92. The open PRs #94, #95, #100, #109 to #112 and #116 all change files that feed the manifest, so once this lands, the newmanifestcheck will fail each of them until it does the same.axiom: n/a: tooling (dashboard manifest builder, hooks and CI), no policy change.
🤖 Generated with Claude Code