Ship the example project skeleton with an initialized checklist (#648) - #697
Merged
Merged
Conversation
`seohead project status --directory examples/project-skeleton` answered `not_initialized`: the one project in this repository a reader can run the documented command against reported a state instead of a coverage figure, and nothing under tests/ or docs/ named that directory at all. Checklist initialization stays separate from project creation, as documented. The example is fixed the other way: `project checklist-init` was run against the skeleton and its `coverage.json` is now committed, with one definition per catalogue item, every item `not_run` and no execution record, because nothing has been run against its synthetic site. Initialization stamps each definition with the wall clock, which is the only machine-specific value the generated file carried. Those 250 `observed_at` values are normalized to the project's own `created_at` (`2026-09-09T00:00:00Z`), the only observation time this example can honestly state, so the committed file is byte-stable across regenerations and carries no generating machine's clock. There are no absolute paths and no fabricated results. `scripts/generate_project_skeleton_coverage.py` performs that regeneration in one command, following the repository's other generated-artifact scripts: it initializes a throwaway copy so a `--check` run never writes into the shipped project, then normalizes and renders. `tests/test_project_skeleton_coverage.py` holds the shipped file to the live catalogue. It fails if the file disappears, if its item IDs drift from the catalogue, if any shipped item claims a result, if a definition time is not the project's creation time, if the bytes differ from a fresh generation, or if `project-status` stops reporting counts for it. The ID-drift and staleness messages name the regeneration command, matching the other generated-artifact gates. The documented status command now points at the skeleton by path, so `tests/test_docs_commands_execute.py` executes it against the shipped project; that gate no longer creates a synthetic project when the documented directory already exists under `examples/`.
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.
The gap
Epic #648's definition of done says
project statuson theexamples/skeleton prints a coverage figure matching a hand count. It did not:The one project in this repository a reader can run the documented command against answered with a state instead of a number. The epic also asked that the skeleton be executable and walkable by the doc gates, and
grep -rn "project-skeleton" tests/ docs/ scripts/returned nothing — no test and no document named that directory.Separate initialization is deliberate and documented (
docs/PROJECTS.md), soproject newis unchanged. The example is fixed the other way: it now ships already initialized.What changed
examples/project-skeleton/coverage.jsonis committed: 250 definitions, one per catalogue item, every onenot_runwith an emptyrecordslist. Nothing has been run against the synthetic site, so nothing claims a result.observed_atvalues are normalized to the project's owncreated_at(2026-09-09T00:00:00Z) — the only observation time this example can honestly state — so the committed file is byte-stable and carries no generating machine's clock. No absolute paths, no fabricated results.scripts/generate_project_skeleton_coverage.pyregenerates that file in one command, following the repository's otherscripts/generate_*.pyartifacts. It initializes a throwaway copy, so--checknever writes into the shipped project and a stale committed file is compared against a first initialization rather than a reconciliation of itself.tests/test_project_skeleton_coverage.pyis the gate: it fails if the file disappears, if item IDs drift from the live catalogue, if any shipped item claims a result, if a definition time is not the project's creation time, if the bytes differ from a fresh generation, or ifproject-statusstops reporting counts. The drift and staleness messages namepython scripts/generate_project_skeleton_coverage.py, matching the other generated-artifact gates.docs/PROJECTS.mddescribes the skeleton as already initialized and names it by path, in a runnable fence — sotests/test_docs_commands_execute.pynow executesproject statusagainst the shipped project. That gate no longer creates a synthetic project when the documented directory already exists underexamples/.examples/README.mdgains a section for the skeleton;changelog.d/648.mdrecords the change.Validation
Hand count of the live catalogue:
seohead project-status --directory examples/project-skeletonafter the change:The printed figure matches the hand count.
The gate was proven to fail without the fix, three ways, each restored afterwards:
state == "initialized"asserting againstnot_initialized— the exact pre-change behaviour.AssertionError: examples/project-skeleton/coverage.json has drifted from the packaged catalogue: regenerate it with 'python scripts/generate_project_skeleton_coverage.py'succeededrecord injected into one item:test_no_shipped_item_claims_a_resultfails withLeft contains one more item: {'reason': 'fabricated', 'status': 'succeeded'}.Restored, the file matches a fresh generation byte for byte and all 6 pass.
Gate output:
Note on the full run: on the uncommitted working tree, ten documented
crawl-sitelines failed withnative scan provenance requires a clean source checkout. That is the build-provenance gate reacting to a dirty tree, not to this change; the run above, after committing, is clean.