Catalog, roadmap, and CI-gated status tracking for ledger properties (#1225) - #1226
Catalog, roadmap, and CI-gated status tracking for ledger properties (#1225)#1226williamdemeo wants to merge 7 commits into
Conversation
c2c871d to
bcee109
Compare
bcee109 to
7942b71
Compare
There was a problem hiding this comment.
Pull request overview
Introduces a repo-managed catalog + generated roadmap for tracking formal ledger properties across Conway and Dijkstra, with property status derived from Agda source and enforced via a CI drift gate to prevent roadmap/issue drift from proofs.
Changes:
- Adds a YAML property catalog and an ADR describing the tracking model and workflow.
- Adds Python tooling to (a) derive property status from Agda and regenerate the roadmap, and (b) sync/render GitHub issues for coordination.
- Adds a CI workflow to run the no-network “roadmap is current” check, publishes the roadmap via mkdocs, and adds README badges.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
scripts/python/scan_properties.py |
Derives status from Agda/filesystem and regenerates canonical + mkdocs roadmap; --check gates drift. |
scripts/python/README.md |
Documents the property-tracking scripts and intended workflows. |
scripts/python/gh_project_render.py |
Renders a GitHub-issues coordination view for catalog-referenced issues. |
scripts/python/gh_project_populate.py |
Seeds GitHub issues/labels from the catalog and writes created issue numbers back. |
README.md |
Adds CI/nightly/properties-check workflow badges. |
docs/notes/properties.yaml |
Adds the version-controlled property catalog (no status field; status derived). |
docs/notes/ledger-properties-roadmap.md |
Adds the generated, human-facing roadmap dashboard. |
docs/notes/0001-ledger-property-tracking.md |
Adds ADR describing rationale, conventions, and reconciliation/workflow. |
build-tools/static/mkdocs/mkdocs.yml |
Publishes the roadmap page in mkdocs navigation. |
build-tools/static/mkdocs/docs/ledger-properties-roadmap.md |
Adds the mkdocs-site copy of the generated roadmap (intended byte-identical). |
.github/workflows/properties-check.yml |
Adds CI drift gate running scan_properties.py --check on relevant changes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
534803f to
9926708
Compare
|
Rebase refresh (2026-08-05). Force-pushed
Generated by Claude Code |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.
Suppressed comments (1)
scripts/python/scan_properties.py:227
validate_catalog()records missing/duplicate ids as errors, butmain()still unconditionally callsevaluate(p)and indexesp["id"]. If the catalog ever contains an entry withoutid(orpropertiesis missing), the script will crash with a traceback instead of reporting the catalog error and exiting cleanly with code 1 (breaking the intended CI gate UX).
results = {}
for p in cat["properties"]:
status, path, probs = evaluate(p)
results[p["id"]] = {"status": status, "path": path}
problems.extend(probs)
|
Copilot's 2026-08-06 re-review came back clean (no new comments). Its one suppressed note — |
ce4c57c to
cd861ec
Compare
cd861ec to
110e06b
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Suppressed comments (6)
.github/workflows/properties-check.yml:19
- The path filter does not include this workflow file itself. A future PR that only changes or breaks
properties-check.ymlwill not run the gate it modifies. Include.github/workflows/properties-check.ymlin the filtered paths.
- 'scripts/python/scan_properties.py'
scripts/python/gh_project_populate.py:229
--erais documented as limiting the run to one era, but label setup still uses every catalog era with--force. Thus--era dijkstraalso creates or updatesera:conway. Filter this loop consistently with the umbrella and property loops.
for era in meta["eras"]:
ensure_label(gh, f"era:{era}", LABEL_COLORS["era"], f"{era} era")
scripts/python/gh_project_populate.py:257
- Existing tracked issues are skipped before any label reconciliation. Because
status:*is applied only when creating an issue, a later Agda transition such asstated→provedleaves the GitHub label—and any label-backed coordination view—permanently stale after rerunning this script. Reconcile derived labels on existing issues while preserving unrelated labels, or avoid publishing status labels.
if p.get("issues"):
continue # already tracked
scripts/python/gh_project_populate.py:264
- Issue numbers are only held in memory until the entire creation loop finishes. If a later
create_issueraises, earlier issues already exist remotely but none of their numbers are written back, so rerunning creates duplicates. Persist each successful write-back atomically before the next creation, or save accumulated updates on failure.
if num:
created += 1
text = set_issue_numbers(text, p["id"], [num])
scripts/python/README.md:47
- Issue #1225's acceptance criteria require the catalog↔issues sync to be run once, including labels and initial issues, but this PR's notes state that population remains unapplied and the Dijkstra catalog entries still have no issues. Since the PR says it implements #1225, either complete that initial seeding before merge or explicitly leave/update the issue scope rather than presenting this criterion as complete.
Creates the per-era umbrella tracking issues, the `property` / `era:*` /
`status:*` / `sts:*` labels, and one issue per catalog entry that has no issue
yet; best-effort links them as sub-issues of the umbrella; then writes the new
issue numbers back into `properties.yaml` (comment-preserving, targeted edits).
scripts/python/scan_properties.py:120
- Only
id,era, andstsare validated, and even the list item is assumed to be a mapping. Consequentlyproperties: [null]crashes here, while an entry missingtitleor using a non-stringmodulepasses validation and crashes later in evaluation/rendering instead of producing the documented catalog error. Validate each item and all downstream-required field types before evaluation.
for p in cat.get("properties", []):
pid = p.get("id")
|
Triage of the six suppressed notes in Copilot's 2026-08-07 review (the visible roadmap-drift comment was already fixed and resolved): Fixed — all five code notes were legit
Addressed by scoping, not code |
293fe39 to
8611193
Compare
8611193 to
b98b11c
Compare
build-tools/properties.yaml is the single hand-curated inventory of ledger properties across the Conway and Dijkstra eras: identity, era, STS, Agda module, key defs, and tracking issues. It deliberately declares NO status — status is derived from the Agda by the scanner (next commit), so the bookkeeping cannot silently drift from the code. docs/adr/0001-ledger-property-tracking.md records the design: a three-layer model (Agda = truth for "proved", catalog = identity, GitHub issues = coordination), the derived-status vocabulary (idea/planned/stated/proved), property-module conventions, the workflow, and the initial reconciliation plan for #45's sub-issues. Part of #1225. AI-assisted: Claude Fable 5 (Anthropic)
build-tools/scripts/scan_properties.py derives each catalog entry's status from the Agda on disk (no module -> idea; module file absent -> planned; "coming soon" marker -> stated; otherwise -> proved) and regenerates the dashboard, build-tools/static/mkdocs/docs/ledger-properties-dashboard.md — a single generated file living in the mkdocs site tree. --check regenerates and fails on a stale dashboard or an invalid catalog (per-entry shape validation with clean error reports, exit 1); it is the no-network drift gate that CI runs. The Agda --safe typecheck in the main CI is what makes 'proved' mean proved. Part of #1225. AI-assisted: Claude Fable 5 (Anthropic)
catalog -> GitHub: build-tools/scripts/gh_project_populate.py seeds labels, per-era umbrella issues, and one issue per untracked catalog entry, writing new numbers back into the catalog immediately after each creation (an interrupted run loses nothing, so a rerun cannot file duplicates). For already-tracked issues it reconciles the derived status:* label — add current, drop stale, preserve everything else; issues shared by entries with differing derived statuses are skipped with a note. GitHub -> repo: build-tools/scripts/gh_project_render.py renders live open/closed/assignee state for every tracked issue into build-tools/static/mkdocs/docs/ledger-properties-issues.md, logging one ✅/❌ line per issue as it fetches. Formal status stays with the scanner; this view is coordination only. The initial seeding created the Conway trackers #1228–#1241 under umbrella #45 and the Dijkstra umbrella #1227; the ~15 Dijkstra port issues are deferred until the ports start. build-tools/scripts/README.md documents all three scripts. Part of #1225. AI-assisted: Claude Fable 5 (Anthropic)
The generated dashboard becomes the site's "Properties Dashboard" page, with its nav tab between Dijkstra and Appendix; the README gains CI and properties-check badges so the drift gate's status is visible at a glance. Part of #1225. AI-assisted: Claude Fable 5 (Anthropic)
Module names in the dashboard tables now link to the module's generated page on the site (the dashboard lives in the same directory); issue numbers link to the GitHub issues. A planned module is not on the branch, so it has no page — it stays plain text rather than a dangling link that would fail the strict mkdocs build. Verified every proved/stated catalog module is in the site's import closure (aggregators re-export them all), so every emitted link resolves. AI-assisted: Claude Fable 5 (Anthropic)
The Conway module listing predated the EventuallyRefunded (#414) and LastVoteApplied (#417, GOV + LEDGER) modules — their pages were built (they are in the site's import closure via the Properties aggregators) but unreachable from the sidebar. Also fix the GenMinspend label typo. Interface.TypeClasses and Ledger.Dijkstra.Specification.Computational are literate modules with no generated page (not in the import closure of Ledger.lagda.md), so they stay out of the nav. AI-assisted: Claude Fable 5 (Anthropic)
b98b11c to
0414afb
Compare
Description
A version-controlled tracking system for ledger properties across the Conway and Dijkstra eras (the machinery for #1225; the one-time issue-seeding run is deliberately deferred — see notes for reviewers).
The idea in one line:
and CI fails whenever the committed bookkeeping disagrees with the code.
How the pieces fit
build-tools/properties.yaml: the human-curated catalog.build-tools/scripts/scan_properties.py: resolves each entry's module againstsrc/.This script classifies each entry as one of the following (and regenerates
ledger-properties-dashboard):idea;planned;coming soonmarker →stated;proved(the Agda--safetypecheck in main CI is what makesprovedmean proved).build-tools/static/mkdocs/docs/ledger-properties-dashboard.md: the generated dashboard (per-era summary + status tables).Generated directly in the mkdocs site tree and published as the Properties Dashboard page (a single copy — there is no separate canonical/site pair).
.github/workflows/properties-check.yml: the no-network CI gate.scan_properties.py --checkfails if the catalog is invalid or the committed dashboard is stale.gh_project_populate.py/gh_project_render.py: optional GitHub-sync scripts (run locally withgh).Seed issues/labels from the catalog, and render
build-tools/static/mkdocs/docs/ledger-properties-issues.md, the live open/closed/assignee coordination view. Coordination only---never a source of status truth.Design and rationale live in the ADR,
docs/adr/0001-ledger-property-tracking.md; the scripts are documented inbuild-tools/scripts/README.md.Try it out!
Status is derived, not declared: watch the gate catch a "lie" (from
nix develop):python3 build-tools/scripts/scan_properties.py --check # OK: bookkeeping agrees with the Agda# regenerate the dashboard python3 build-tools/scripts/scan_properties.py# undo the experiment git checkout -- src build-toolsSee the dashboard on the docs site (top-level Properties Dashboard tab, next to Home):
or incrementally, reusing an existing
_build:nix develop→fls-shake mkdocs→ servedist/mkdocs.With an authenticated
gh, the issue side:# refresh the issues view from live GitHub; git diff shows drift python3 build-tools/scripts/gh_project_render.py# preview catalog→GitHub seeding (leave unapplied; see notes) python3 build-tools/scripts/gh_project_populate.py --dry-runContents
Docs / tooling / CI only:
src/is byte-identical tomaster. The catalog, the ADR, the generated dashboard and issues view (both live in the mkdocs site tree), the three scripts + their README, the CI workflow, the mkdocs nav entry, and README badges.Current state: Conway 12 proved / 7 stated / 2 idea; Dijkstra 15 port ideas.
Notes for reviewers
Issues under #45 were already reconciled while building this:
gh_project_populate.pyis deliberately left un-applied; its label scheme (era:conway,status:*,sts:*) differs from the repo's existing labels (era: conway), and applying would also file the 15 Dijkstra port issues.Follow-up: reconcile the conventions before the first real run; the port issues get filed as ports start.
The optional read-only GitHub Projects v2 board is documented in the ADR for us to do later as follow-up improvements.
Part of #1225.
Checklist
CHANGELOG.md(n/a — docs/tooling/CI only)src/is byte-identical tomaster)