Skip to content

Define catalogue contract and deterministic validation - #17

Merged
senyo888 merged 3 commits into
mainfrom
bella/catalogue-contract
Jul 15, 2026
Merged

senyo888 merged 3 commits into
mainfrom
bella/catalogue-contract

Conversation

@senyo888

@senyo888 senyo888 commented Jul 14, 2026 •

Copy link
Copy Markdown
Owner

Summary

Scope

  • Upgrade catalog.json to schema v2 with immutable catalogue numbers, publication state, and canonical presentation metadata for all 7 published pets.
  • Add deterministic validation for package, README, site, installer, checksum, preview-token, membership, and stable-numbering consistency.
  • Add the catalog-contract pull-request workflow and catalogue contract documentation.
  • Normalize repeated README, website-card, installer, issue-template, PR-template, and contributor-facing facts.
  • Address review feedback by correcting the README heading hierarchy and documenting all validator definitions.

Reason

Catalogue truth was repeated manually across package metadata, README surfaces, site cards, and installers without a complete deterministic contract. The change keeps the static architecture and manual website workflow while preventing silent drift.

Files affected

  • catalog.json
  • scripts/validate_catalog.py
  • .github/workflows/validate.yml
  • docs/CATALOG_CONTRACT.md
  • Root and per-pet READMEs
  • site/index.html and all 7 installer pages
  • CONTRIBUTING.md
  • Submission issue and pull-request templates

Change type

  • New pet package
  • Existing pet update
  • Maintainer-initiated website sync
  • Documentation or validation only

Pet details

  • Pet name: N/A — collection-wide contract
  • Pet ID: N/A
  • Catalogue number: N/A — preserves 001–007
  • Update subtype: N/A
  • Related issue: N/A
  • Attribution: Existing repository attribution; no asset changes

Package checklist

  • One pet is included in this pull request — N/A; this is collection-wide and changes no package
  • pets/<pet-id>/pet.json matches the lowercase directory ID
  • The pet README uses the canonical Package property list and order
  • catalog.json contains the assigned number and canonical presentation fields
  • The v2 atlas is 1536 × 2288, transparent, and uses the 8 × 11 layout
  • Preview and QA evidence were produced from the submitted atlas — N/A; assets are unchanged
  • Root README count, preview, name, order, summary, installer, and checksum surfaces agree
  • Every preview cache token matches the exact referenced preview file
  • Website card and installer identity, number, role, summary, traits, alt text, and links agree
  • Website content work was explicitly initiated and approved by a maintainer
  • The atlas SHA-256 matches the catalogue and validation summary
  • Decoded codex:// parameters match the canonical package metadata and raw spritesheet URL
  • Standard animation rows, directions, and continuity were reviewed — unchanged and outside this contract-only slice

Validation performed

  • JSON files parse successfully
  • python3 scripts/validate_catalog.py passes
  • Preview rendering completed successfully — not run; preview bytes are unchanged
  • Local website links and installer route were checked
  • Desktop and 390 px mobile layouts were checked
  • Keyboard order, focus visibility, reduced motion, and console output were checked
  • git diff --check passes

Results:

  • python3 scripts/validate_catalog.py --base-ref origin/main: passed
  • Catalogue result: 7 published pets, 61 local site references, and 76 local Markdown references passed
  • Validator docstrings: 22/22 definitions, 100% coverage
  • README heading progression: MD001 passed
  • Python syntax and 110-column check: passed
  • JSON parsing: 15 catalogue/package/QA files passed
  • YAML parsing: issue template and validation workflow passed
  • Negative regression checks: duplicate numbers, malformed installer links, and renumbering rejected
  • Privacy scan: 80 public candidate files, 0 matches
  • Credential/private-path pattern scan: 0 matches
  • Not performed: browser visual/accessibility review and real desktop-app codex:// activation

Impact

Runtime impact

No pet runtime package changes. No pet.json, spritesheet, preview, QA image, checksum, or installer-parameter changes. Home Assistant entity semantics and deterministic control lanes are unaffected.

UI impact

No redesign, CSS, layout, or image changes. Public copy and alt text are normalized, and stable data-pet-id hooks are added. Generated dashboards are unaffected. UI truth-consistency risk is reduced by deterministic cross-surface validation.

Migration impact

catalog.json changes from schema version 1 to 2. External consumers hard-coded to v1 must support v2. No installed-pet migration, cache clear, application restart, or system restart is required.

Rollback safety

Revert the PR commits. Runtime packages and binary assets are untouched, so rollback restores schema v1 and the prior public surfaces without data cleanup.

  • Deterministic lane-ordering risk: none.
  • Catalogue-ordering risk: reduced through immutable-number enforcement.
  • UI truth-consistency risk: reduced through exact catalogue-to-README/site/installer checks.
  • Hidden behavioral drift: none identified; runtime behavior is unchanged.

Rights

  • For every submitted asset, I am the creator or have authority to contribute it under CC BY 4.0 — N/A; no assets changed
  • I agree that accepted artwork and documentation may be published under CC BY 4.0 with the attribution provided above — N/A; existing repository terms are unchanged

Summary by CodeRabbit

  • New Features

    • Expanded the catalogue data with catalogue numbers, publication status, roles/summaries, traits, and enhanced preview text.
    • Added stable pet identifiers to catalogue cards and installer pages for consistent targeting.
  • Documentation

    • Added a catalogue contract and updated contribution/PR templates to enforce synchronized README, website, installer, and preview/cache-token updates.
  • Bug Fixes

    • Strengthened validation via a new pull-request workflow and a multi-stage validator to catch contract, schema, link, preview, and identity inconsistencies.
  • Chores

    • Refined preview image alt text and improved README/install copy for clarity.

@coderabbitai

coderabbitai Bot commented Jul 14, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@senyo888, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 55 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d356edb9-0c78-43e0-bcd4-d92e8e7028b7

📥 Commits

Reviewing files that changed from the base of the PR and between 4d77e65 and 4a7dd12.

📒 Files selected for processing (1)
  • scripts/validate_catalog.py
📝 Walkthrough

Walkthrough

The PR introduces catalogue schema version 2, formalizes catalogue and contribution contracts, expands validation across package and public surfaces, adds pull-request enforcement, and synchronizes README, package, catalogue, and website metadata.

Changes

Catalogue contract and synchronized surfaces

Layer / File(s) Summary
Contract, schema, and contribution workflow
.github/ISSUE_TEMPLATE/*, .github/pull_request_template.md, catalog.json, docs/CATALOG_CONTRACT.md, CONTRIBUTING.md
Catalogue metadata, immutable numbering, presentation fields, contribution requirements, and pull-request validation checklists were expanded.
Catalogue validation and PR enforcement
scripts/validate_catalog.py, .github/workflows/validate.yml
Validation now accumulates errors across catalogue, package, README, website, installer, reference, deep-link, and stable-identity checks; pull requests run validation against the base commit.
Root and package README updates
README.md, pets/*/README.md
README catalogue tables, descriptions, preview alt text, cache tokens, installation guidance, and contract references were updated.
Website card and installer identity
site/index.html, site/install/*/index.html
Pet cards and installer pages now expose stable data-pet-id attributes, with selected theme and installer copy updates.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PullRequest
  participant ValidateWorkflow
  participant validate_catalog.py
  participant CatalogueSurfaces
  PullRequest->>ValidateWorkflow: open or update pull request
  ValidateWorkflow->>validate_catalog.py: run with base commit
  validate_catalog.py->>CatalogueSurfaces: validate catalogue, packages, README, site, and links
  validate_catalog.py-->>ValidateWorkflow: return accumulated validation result
  ValidateWorkflow-->>PullRequest: publish check status
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: defining the catalogue contract and adding deterministic validation.
Description check ✅ Passed The description follows the template sections and provides the needed scope, checks, impact, and rights details with reasonable completeness.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bella/catalogue-contract

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@senyo888
senyo888 marked this pull request as ready for review July 14, 2026 20:33

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
scripts/validate_catalog.py (2)

508-508: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

zip() without strict=.

Safe today only because the preceding actual_ids != expected_ids check (line 504-506) already guarantees cards and pets are equal length before this loop runs. Adding strict=True would make that invariant explicit and guard against future refactors that remove the early return.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/validate_catalog.py` at line 508, Add strict=True to the zip call in
the validation loop over cards and pets, making the required equal-length
invariant explicit while preserving the existing iteration behavior.

Source: Linters/SAST tools


379-482: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Hardcoded example pet ID couples the validator to one specific catalogue entry.

Line 467-468 checks for the literal string "PET_ID=aetherwing # choose an ID from the table above". This ties the validator (and README.md) to "aetherwing" specifically rather than deriving the example from the current catalogue (e.g. typed_pets[0]["id"]). Not a live bug — a rename/retirement of that pet would just surface a clear validation error — but it's a hidden coupling not called out in the "Change requirements"/"Change matrix" tables.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/validate_catalog.py` around lines 379 - 482, Update
validate_root_readme to derive the manual-install example ID from the canonical
pets collection instead of hardcoding “aetherwing”. Build the expected guidance
using the first catalogue entry’s id, while preserving the existing validation
error and guidance format.
CONTRIBUTING.md (1)

44-60: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Clarify maintainer-authorization requirement before, not after, the site-file edit list.

Step 3 lists site/assets/..., site/install/<pet-id>/index.html, and site/index.html as files to update in this same PR, and only afterward (lines 55-59) states website content is maintainer-initiated work requiring explicit authorization before it's edited. A contributor following the numbered list top-to-bottom could start editing site/ before reaching that caveat, contradicting the "Approval gates" in docs/CATALOG_CONTRACT.md ("Maintainer initiation is required before website content work").

✏️ Suggested reordering
 3. Update every public catalogue surface in the same pull request:
 
+   Website content remains maintainer-initiated manual work: get explicit
+   maintainer authorization before editing `site/` files below.
+
    ```text
    pets/<pet-id>/
    site/assets/<pet-id>-preview.gif
    site/install/<pet-id>/index.html
    catalog.json
    README.md
    site/index.html
    ```
 
    The root README update is mandatory for both new pets and existing-pet upgrades.
-   Website content remains maintainer-initiated manual work: a maintainer must explicitly
-   authorize the website portion before it is edited or approved. The Pages workflow
+   The Pages workflow
    deploys approved `site/` files after merge; it does not create or autonomously update
    catalogue content.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CONTRIBUTING.md` around lines 44 - 60, Reorder the maintainer-authorization
requirement in the Step 3 guidance so it appears before the list of site/ files,
clearly requiring explicit authorization before contributors edit or approve any
website content. Keep the existing catalogue file list, README requirement, and
Pages workflow clarification unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@README.md`:
- Line 23: Change the pet-links heading in the README from level-three to
level-two by replacing the leading ### with ##, preserving all linked entries
and their order.

---

Nitpick comments:
In `@CONTRIBUTING.md`:
- Around line 44-60: Reorder the maintainer-authorization requirement in the
Step 3 guidance so it appears before the list of site/ files, clearly requiring
explicit authorization before contributors edit or approve any website content.
Keep the existing catalogue file list, README requirement, and Pages workflow
clarification unchanged.

In `@scripts/validate_catalog.py`:
- Line 508: Add strict=True to the zip call in the validation loop over cards
and pets, making the required equal-length invariant explicit while preserving
the existing iteration behavior.
- Around line 379-482: Update validate_root_readme to derive the manual-install
example ID from the canonical pets collection instead of hardcoding
“aetherwing”. Build the expected guidance using the first catalogue entry’s id,
while preserving the existing validation error and guidance format.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 010978af-dbcb-44d7-bba6-4fda4fa5d7a9

📥 Commits

Reviewing files that changed from the base of the PR and between 66e2e73 and 321c909.

📒 Files selected for processing (23)
  • .github/ISSUE_TEMPLATE/add-your-pet.yml
  • .github/pull_request_template.md
  • .github/workflows/validate.yml
  • CONTRIBUTING.md
  • README.md
  • catalog.json
  • docs/CATALOG_CONTRACT.md
  • pets/aetherbite/README.md
  • pets/aethercore/README.md
  • pets/aethermite/README.md
  • pets/aetherwing/README.md
  • pets/bella/README.md
  • pets/calian/README.md
  • pets/scarlet/README.md
  • scripts/validate_catalog.py
  • site/index.html
  • site/install/aetherbite/index.html
  • site/install/aethercore/index.html
  • site/install/aethermite/index.html
  • site/install/aetherwing/index.html
  • site/install/bella/index.html
  • site/install/calian/index.html
  • site/install/scarlet/index.html

Comment thread README.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/validate_catalog.py (1)

551-554: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Strictly verify that the contribution card follows all published pet cards.

Currently, last_card_position searches for any </article> before the contribution card, not necessarily the last pet card in the document. If the contribution card is incorrectly placed between two pet cards, this check will falsely pass.

Compare its position against the last pet card to guarantee it appears at the very end of the list.

🐛 Proposed fix
-    contribution_position = text.find('class="contribution-card"')
-    last_card_position = text.rfind('</article>', 0, contribution_position)
-    if contribution_position < 0 or last_card_position < 0:
+    contribution_position = text.find('class="contribution-card"')
+    last_pet_card = text.rfind('class="pet-card')
+    if contribution_position < 0 or contribution_position < last_pet_card:
         add_error(errors, "contribution card must follow all published pet cards")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/validate_catalog.py` around lines 551 - 554, Update the
contribution-card validation around contribution_position to locate the last
published pet card specifically, rather than any preceding </article>. Compare
contribution_position against that final pet-card position and add the existing
error when the contribution card is missing or appears before the last published
pet card, ensuring it must follow all published pet cards.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/validate_catalog.py`:
- Line 273: Update the deep-link regex in the catalog validation logic to
exclude single quotes, closing brackets, and closing parentheses alongside the
existing whitespace, double-quote, and HTML-boundary exclusions. Preserve
matching of valid codex://pets/install query URLs while preventing trailing
Markdown or HTML delimiters from being captured.

---

Outside diff comments:
In `@scripts/validate_catalog.py`:
- Around line 551-554: Update the contribution-card validation around
contribution_position to locate the last published pet card specifically, rather
than any preceding </article>. Compare contribution_position against that final
pet-card position and add the existing error when the contribution card is
missing or appears before the last published pet card, ensuring it must follow
all published pet cards.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 496fe339-f9b3-4b61-9b6e-135b03531a08

📥 Commits

Reviewing files that changed from the base of the PR and between 321c909 and 4d77e65.

📒 Files selected for processing (2)
  • README.md
  • scripts/validate_catalog.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • README.md

Comment thread scripts/validate_catalog.py Outdated
@senyo888
senyo888 merged commit 9c83abf into main Jul 15, 2026
2 checks passed
@senyo888
senyo888 deleted the bella/catalogue-contract branch July 15, 2026 16:35
@coderabbitai coderabbitai Bot mentioned this pull request Jul 15, 2026
26 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant