Repository navigation
Conversation
- 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>
infer_target_repos matched aliases as case-insensitive substrings, so "SSI" in "missing", "PIP" in "pipeline" and "GIS" in "registry" tagged the country models. It matched a repo name inside a longer token, so policyengine-app-v2 tagged policyengine-app and the skill name policyengine-model-development tagged policyengine-model. And it read only the first 6,000 characters of a body. Now a repo name, its import name or an alias counts only where it stands as a whole token, and at each position the longest term wins. A term in capitals (PIP, CRM) counts only in capitals; every other term counts in any case, as GitHub resolves repo names. The matcher reads the whole body. The web-app aliases point at policyengine-app-v2, api.policyengine.org points at policyengine-api, and "frontend" no longer counts. The registry owner rule treats the country-models category as country-model work, so two agents that lost false links keep their owner. target_repos links: 267 -> 221 (+61 / -107) across 69 artifacts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
force-pushed
the
manifest-pyyaml
branch
from
November 9, 2026 22:38
d7e187d to
cc0a9f7
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.
Fixes how
scripts/build_manifest.pydecides which PolicyEngine repos each skill, agent and command targets: the follow-up that #107's section 5 left out.infer_target_reposfills each artifact'starget_reposindashboard/src/data/manifest.json, andrepo_coverageand some registry owners follow from it. It matched aliases as case-insensitive substrings, matched a repo name inside a longer token, and read only the first 6,000 characters of a body. This PR removes 107 of its 267 artifact-to-repo links and adds 61.This PR stacks on #107 (
manifest-pyyaml). When #107 merges, I rebase onto main, regenerate the manifest and point this PR at main. It stays a draft until then and until an independent review agrees.1. The rule
RepoMatcherreads an artifact's name, description, whole body and category from left to right. At each position it takes the longest term that stands there as a whole token, records that term's repo, and carries on after it. The terms are each repo name in the inventory, its import name (policyengine_us) and the aliases inREPO_ALIASES.REPO_ALIASESorder, each once. The old function used the same order.The old function ran one regex per repo and one substring test per alias. The new one runs
str.findper term and checks the characters on either side, so it never builds a regex from repo names. A full build takes about 2 seconds here.2. Decisions
Case. An acronym in lowercase is usually code or another word:
uv pip install,foo.cpp, OBBBA's 2030 "snap-back", actcfilter tag. So a term written in capitals (PIP, SNAP, CRM) counts only in capitals. I measured the alternative on today's 80 artifacts: counting the capitals aliases in any case adds 7 links. Four of them come frompipand tag policyengine-uk, one comes from theri-ctc-calculator-backendservice name and tags policyengine-us, and two are arguable (the parameter filegov/irs/credits/ctc.yamlin reference-validator's example table, and thectc/eitcfilter tags in/prior-analysis). Model variables and parameter paths such astax_unit.eitcandgov.usda.snapappear only in artifacts that name policyengine-us anyway, so capitals-only drops none of those links.Every other term, repo names included, counts in any case. GitHub resolves repo names in any case (
gh api repos/policyengine/aca-calcreturnsPolicyEngine/ACA-Calc), prose capitalizes them, and trigger lists write phrases in lowercase ("universal credit"). The old function matched repo names only as written; ignoring case adds 3 links, all real: "a new PolicyEngine-US state benefit" inencode-policy-v2, andaca-calcin/create-dashboardand/new-tool.The cap. Gone. A cap at any position breaks "adding text never removes a repo", because text added near the top pushes a later mention past it. 47 of the 80 artifacts have bodies longer than 6,000 characters, and reading them whole adds 36 links. 33 are plain mentions of the repo, such as policyengine-household-api in the cloud-costs skill's table of past incidents. The other 3 come from the limits in section 6.
The alias table.
policyengine.organdapp-v2now point at policyengine-app-v2, not the legacy policyengine-app. The policyengine-app skill describes app-v2 as "the site served at policyengine.org".api.policyengine.orgnow points at policyengine-api. Before, the substringpolicyengine.orginside it tagged the legacy web app.Registry owners.
owner_for_artifactnow treats thecountry-modelscategory as country-model work. Two agents in that category,model-workerandreview-worker, owed their only country-model link to a false match, so without this change they would move to the generic owner.3. What changes
Only
target_repos,registry_ownerand the per-repo counts inrepo_coveragechange. Links between artifacts and repos, by repo kind:69 of the 80 artifacts gain or lose a link. A 70th, pr-pusher, keeps its repos in a new order: its policyengine-us link now comes from the repo's name, not an alias, so it sorts with the named repos. Why each link went:
policyengine-model-development(18); policyengine-app inpolicyengine-app-v2/...(7); atlas inpolicyengine-atlas-pbif-grant.md; poverty-dashboard inchild-poverty-dashboardapi.policyengine.org/calculatepip", "non-uv pip installs"state-legislative-trackerin microsim-runnerapi.policyengine.orgnow names policyengine-apiapi.policyengine.org" in microsim-runner'policyengine_uk' : 'policyengine_us'in dashboard-integratoraca-calcBy repo:
/prior-analysisand/prior-scoresmove from "Country model engineering" to "PolicyEngine". Their only country-model links came from "pipeline", "registry", "not-possible" and thectc/eitcfilter tags.The Catalog's repo filter and chips, the drawer's "Target repos" list and the Workflows page's repo chips read
target_repos. The drawer, the Catalog and the Cleanup page showregistry_owner. No page readsrepo_coverageyet.4. Invariants
These hold for every input, and the tests check each one:
.git,'s) always counts (Hypothesis).reference_targets, a plain character-by-character scan of the same rule. The tests check this for the real table, and for random small tables whose terms overlap, nest, repeat and start one another (Hypothesis, two differential tests).ValueError.REPO_ALIASESorder.5. Tests
tests/test_target_repos.py: 64 tests, 8 of them Hypothesis properties, in under 30 seconds. Most examples come from this repo's own skills, agents and commands, with at least one for each kind of false positive in section 3.uv run pytest --ignore=tests/test_skill_examples.py: 286 passed under Python 3.15.2 and under 3.11.15 (macOS).uv run python scripts/build_manifest.py --checkpasses under Python 3.11 and 3.15.6. Limits this PR leaves
calibration-diagnosticsagent tags the calibration-diagnostics repo.policyengine.org/us/research/...URL tags policyengine-app-v2, which serves the posts, even when the artifact only reads them.v2.api.policyengine.org, the API v2 alpha, has no alias.Other PRs that touch the manifest
Rebase onto main and regenerate with
uv run python scripts/build_manifest.pyrather than hand-merging the manifest.axiom: n/a: tooling (dashboard manifest builder), no policy change.
🤖 Generated with Claude Code