Skip to content

Generate deployment address books#100

Merged
punk6529 merged 4 commits into
mainfrom
codex/address-book-generator
Jun 11, 2026
Merged

Generate deployment address books#100
punk6529 merged 4 commits into
mainfrom
codex/address-book-generator

Conversation

@punk6529

@punk6529 punk6529 commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add a stdlib-only deployment address-book generator/checker that projects committed manifests into compact integrator-facing JSON
  • commit the local Anvil address book under deployments/address-books/ with manifest checksum, ABI checksum source, contract addresses, ABI/runtime bytecode hashes, sources, artifacts, and verification status
  • validate schema, exact release contract set, nonzero 20-byte addresses, duplicate deployed addresses, hash mismatches, missing metadata, and strict source_dirty typing
  • wire address-book tests and drift checks into make check, Linux/Windows wrappers, and GitHub Actions
  • document how address books differ from full deployment manifests and update the roadmap/run-state trace

Closes #99

Validation

  • python scripts\test_address_books.py
  • python scripts\generate_address_books.py --check
  • python -m py_compile scripts\generate_release_artifacts.py scripts\test_release_artifacts.py scripts\check_abi_compatibility.py scripts\test_abi_compatibility.py scripts\generate_deployment_manifest.py scripts\test_deployment_manifest.py scripts\generate_address_books.py scripts\test_address_books.py
  • bash -n scripts/check.sh
  • PowerShell parser validation for scripts\check.ps1
  • per-file JSON parsing for the generated address book, deployment manifest, and ABI checksums
  • make check
  • powershell -ExecutionPolicy Bypass -File scripts\check.ps1
  • git diff --check reported only the known scripts/check.ps1 line-ending warning

Summary by CodeRabbit

  • New Features

    • Deterministic deployment address books with a generator and strict check mode; sample compact address-book artifact added.
  • Documentation

    • Docs and READMEs updated to describe address-book schema, generation, validation behavior, and release workflow inclusion.
  • Tests

    • New unit tests for generation, drift detection, and many validation failure cases.
  • Chores

    • CI, Makefile, and local check scripts updated to run address-book generation and verification as part of routine checks.

@claude claude 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.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Please review the address-book generator with special attention to:

  • whether the address-book schema is useful as a compact projection of deployment manifests,
  • whether invalid/duplicate address and contract-set validation are sufficient,
  • whether drift checks are wired without duplicating unrelated manifest/release checks,
  • whether docs clearly distinguish address books from full deployment manifests.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 37372b71-832e-4f9e-a694-b0ed5cc03460

📥 Commits

Reviewing files that changed from the base of the PR and between f626303 and ef5f5e6.

📒 Files selected for processing (4)
  • ops/AUTONOMOUS_RUN.md
  • ops/ROADMAP.md
  • scripts/generate_address_books.py
  • scripts/test_address_books.py
✅ Files skipped from review due to trivial changes (1)
  • ops/ROADMAP.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • ops/AUTONOMOUS_RUN.md
  • scripts/generate_address_books.py

📝 Walkthrough

Walkthrough

Adds a deterministic address-book generator CLI with schema, tests, CI/Makefile/check-script integration, a sample generated address-book, and documentation/ops updates; includes a check-mode that byte-compares regenerated outputs and fails on drift, invalid addresses, or missing release metadata.

Changes

Address Book Generation

Layer / File(s) Summary
Generator core implementation and validation
scripts/generate_address_books.py
generate_address_books.py validates deployment manifests, loads ABI/bytecode hashes from release artifacts, normalizes and deduplicates addresses, enforces contract-set consistency, and generates deterministic JSON address books with a --check mode that diffs regenerated output.
Test coverage and validation
scripts/test_address_books.py
Unittests dynamically import the generator, create deterministic fixtures, assert expected fields and hashes, exercise drift detection (exit 0 vs 1), and assert failures for duplicate/malformed addresses, missing metadata, invalid types/enums, bad hash formats, and missing release entries.
CI and build workflow integration
.github/workflows/ci.yml, Makefile, scripts/check.sh, scripts/check.ps1
Adds address-books/address-books-check Make targets, wires address-books-check into make check, adds CI step running tests and --check with logs, and updates shell/PowerShell check scripts to run the new checks.
Schema and sample artifact
deployments/schema/address-book.schema.json, deployments/address-books/anvil-6529stream-v0.1.0-001.json
JSON Schema defines address-book shape and constraints; sample address-book JSON demonstrates generated fields, provenance, network/git context, contract entries, hashes, and verification status.
Documentation and ops traceability
README.md, docs/*.md, deployments/README.md, ops/*.md
Documents address-book purpose, generation commands, check-mode semantics, release-artifact integration, and updates ops traceability/ROADMAP to record the feature and checklist step.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • 6529-Collections/6529Stream#92: Modifies the same make check/CI integration points and the check workflow, overlapping integration surface with address-book checking.

Poem

🐰 I hopped through manifests, tidy and neat,
Pulled hashes and addresses, matched each beat,
Wrote compact books with provenance bright,
CI checks them, byte-for-byte by night,
A rabbit’s hop makes release paths light.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Generate deployment address books' is clear, concise, and accurately reflects the main objective of the changeset—implementing address-book generation functionality.
Linked Issues check ✅ Passed The PR successfully implements all coding requirements from issue #99: address-book generation from manifests [#99], deterministic JSON with manifest checksums/ABI hashes/addresses [#99], validation for addresses/duplicates/contracts [#99], focused unit tests [#99], wiring into make/check scripts/CI [#99], and documentation updates [#99].
Out of Scope Changes check ✅ Passed All changes are in-scope: address-book generator/tests, schemas, check-script wiring, documentation, and ops traceability. No out-of-scope work like RPC verification, live network discovery, or unrelated refactoring is present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/address-book-generator

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

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

The branch head is now stable after the run-state follow-up commit. Please review the current head 20fc73421e0c4c8085a8873adcab1872cd12e49e with the same focus areas:

  • compact address-book schema usefulness,
  • invalid/duplicate address and contract-set validation,
  • drift-check wiring,
  • documentation clarity versus full deployment manifests.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get the list of files changed in the PR
gh pr view 100 --repo 6529-Collections/6529Stream --json files --jq '.files[].path'

Length of output: 493


🏁 Script executed:

#!/bin/bash
# Read the main generator script
cat scripts/generate_address_books.py 2>/dev/null || echo "FILE NOT FOUND"

Length of output: 13100


🏁 Script executed:

#!/bin/bash
# Read the test script
cat scripts/test_address_books.py 2>/dev/null || echo "FILE NOT FOUND"

Length of output: 8549


🏁 Script executed:

#!/bin/bash
# Read any committed address book files
find deployments/address-books -type f 2>/dev/null | head -20
cat deployments/address-books/*.json 2>/dev/null | head -200 || echo "No JSON files found"

Length of output: 5370


🏁 Script executed:

#!/bin/bash
# Read check.sh and check.ps1 for drift wiring
cat scripts/check.sh 2>/dev/null || echo "FILE NOT FOUND"
echo "---"
cat scripts/check.ps1 2>/dev/null || echo "FILE NOT FOUND"

Length of output: 2986


🏁 Script executed:

#!/bin/bash
# Read docs / README changes
cat README.md 2>/dev/null | head -300
echo "---"
find docs -type f 2>/dev/null | xargs ls -la 2>/dev/null
find . -name "ROADMAP*" -o -name "roadmap*" 2>/dev/null | xargs cat 2>/dev/null | head -200

Length of output: 12809


🏁 Script executed:

#!/bin/bash
# Read the GitHub Actions workflow files
find .github/workflows -type f | xargs ls -la 2>/dev/null
cat .github/workflows/*.yml 2>/dev/null || cat .github/workflows/*.yaml 2>/dev/null

Length of output: 4970


🏁 Script executed:

#!/bin/bash
# Get full diff of the PR
gh pr diff 100 --repo 6529-Collections/6529Stream 2>/dev/null | head -2000

Length of output: 65754



@punk6529 — reviewed against your four focus areas. Overall the generator is solid and the wiring is clean. A few findings below:


Address-book schema (usefulness as compact projection)

The schema retains exactly the right surface: network identity, release metadata, source traceability (manifest path + SHA256, ABI checksums path, event topic catalog), per-contract addresses with source/artifact paths, ABI and runtime bytecode hashes, and verification status. The deliberate omissions (constructor arguments, admin ceremony, verification commands) are well-chosen for the integrator/indexer audience.

Minor — address case is not normalized (EIP-55). normalize_address validates format and rejects the zero address, but stores the address with its original casing. Duplicate detection is correctly case-insensitive, but two manifests that spell the same address with different casing would produce different address-book JSON. For a purely local Anvil rehearsal this doesn't matter today, but production manifests may have mixed-case checksummed addresses.

# In normalize_address, consider canonicalising before storing:
return address  # currently: original casing
# could be: address.lower()  (or EIP-55 checksum via eth_utils if dep is ever added)

Minor — no address-book JSON schema file. deployments/schema/deployment-manifest.schema.json exists for manifests; there is no deployments/schema/address-book.schema.json. Not blocking, but worth noting for schema parity.


Invalid/duplicate address and contract-set validation (sufficiency)

The coverage is thorough for the pre-audit stage:

  • ✅ 20-byte hex regex + zero-address rejection
  • ✅ Case-insensitive duplicate detection across all contracts in one deployment
  • ✅ Exact bidirectional contract-set match (missing + unknown both reported)
  • ✅ Per-contract ABI and bytecode hash cross-check against the release artifact baseline
  • ✅ Strict source_dirty boolean type (no string coercion)
  • ✅ All required fields validated with typed require_* helpers

Two small gaps worth considering as the project approaches production:

verification_status accepts any non-empty string. A typo like "verifed" passes silently. An allowlist enum ("verified", "not_applicable", "pending", …) would catch this at generation time.

Hash field format is not validated beyond non-empty string. Passing "notahash" as abi_hash would pass require_string and then fail the equality check against the baseline — which does catch it. But a sha256: prefix check would provide an earlier, more informative error for fields that originate outside the manifest generator (e.g. hand-edited manifests).


Drift checks wired without duplicating unrelated checks

check.sh, check.ps1, and the CI workflow are clean — each script runs the manifest checks and address-book checks once, in dependency order, with no duplication.

The Makefile has a double-execution path. The check target lists both deployment-manifest-check directly and address-books-check (which depends on deployment-manifest-check). Because all targets are .PHONY, Make does not memoize them, so deployment-manifest-check runs twice:

# Current:
check: build test size release-artifacts-check abi-compatibility-check \
       deployment-manifest-check address-books-check deploy-rehearsal
#                                 ↑ runs once here
address-books-check: deployment-manifest-check
#                    ↑ and again here when check invokes address-books-check

Dropping deployment-manifest-check from check's direct prerequisites resolves it without changing anything observable — address-books-check already guarantees it runs first:

check: build test size release-artifacts-check abi-compatibility-check \
       address-books-check deploy-rehearsal

This is a correctness-neutral redundancy today, but adds unnecessary latency and will confuse future contributors reading make check output with duplicate step headers.


Docs distinguishing address books from full deployment manifests

The distinction is consistent and well-propagated across deployments/README.md, docs/deployment.md, docs/tooling.md, docs/status.md, ops/ROADMAP.md, and README.md. Every updated location explicitly names what address books omit (constructor arguments, admin ceremony details, verification commands) and what they retain. The docs/status.md change from "address books" (planned) to "production address books" (remaining) is appropriately precise.

One small addition that would reinforce the docs: a sentence in deployments/README.md or deployments/address-books/ noting that address-book files are generated outputs and should not be manually edited — the same expectation already implicit in the drift-check mechanism but not stated in prose anywhere.


Summary table

Area Finding Severity
Schema Address case not EIP-55 normalized; output case matches input Minor
Schema No address-book.schema.json alongside manifest schema Minor
Validation verification_status unconstrained (any non-empty string) Minor
Validation Hash field prefix (sha256:) not validated Minor
Drift wiring deployment-manifest-check runs twice under make check Low
Docs No explicit "do not manually edit" note for address-book files Minor

The core generation logic, validation suite, and drift-check integration are sound. The double-execution in the Makefile is the one item I'd address before merging; everything else can reasonably be deferred to a follow-up.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# List the overall structure of new files in this PR
git diff --name-only HEAD~5 HEAD 2>/dev/null || git diff --name-only origin/main HEAD 2>/dev/null || git log --oneline -10

echo "=== Tree of scripts/ and deployments/ ==="
tree scripts/ deployments/ 2>/dev/null || (find scripts/ deployments/ -type f | sort)

Length of output: 1951


🏁 Script executed:

#!/bin/bash
echo "=== generate_address_books.py ==="
cat scripts/generate_address_books.py

echo ""
echo "=== test_address_books.py ==="
cat scripts/test_address_books.py

Length of output: 21615


🏁 Script executed:

#!/bin/bash
echo "=== check.sh ==="
cat scripts/check.sh

echo ""
echo "=== check.ps1 ==="
cat scripts/check.ps1

echo ""
echo "=== GitHub Actions workflows ==="
find .github/ -type f | sort
cat .github/workflows/*.yml 2>/dev/null || find .github -name "*.yml" -exec cat {} \;

Length of output: 7988


🏁 Script executed:

#!/bin/bash
echo "=== Address books directory ==="
find deployments/address-books/ -type f | sort
cat deployments/address-books/*.json 2>/dev/null | head -200

echo ""
echo "=== Deployment manifests directory ==="
find deployments/ -name "*.json" | sort | head -20

Length of output: 5718


🏁 Script executed:

#!/bin/bash
echo "=== README or docs ==="
cat README.md 2>/dev/null | head -300
find . -name "*.md" | grep -v node_modules | sort
cat docs/*.md 2>/dev/null || true

echo ""
echo "=== Makefile ==="
cat Makefile 2>/dev/null || true

Length of output: 58322



@punk6529 Here is the focused review of the current head across your four areas.


1. Address-book schema — compact projection usefulness

The schema is well-designed as an integrator-facing projection. The right fields are included (network, chain, release versions, lifecycle state, source manifest checksum, per-contract address/source/artifact path/ABI hash/runtime bytecode hash/verification status) and the right fields are deliberately excluded (constructor args, admin ceremony, deployer, Safe, pause guardians, RPC endpoints, Foundry build settings). The source block makes traceability explicit without embedding the full manifest.

One naming nuance worth noting: source.deployment_manifest_sha256 is populated from manifest.release_artifacts.manifest_sha256 — which is the deployment manifest's own self-checksum (computed during manifest generation). The name is accurate but could momentarily be confused with a checksum of the release artifact manifest. The generator comment and docs/deployment.md explanation make this clear on closer reading, but a short inline comment in build_address_book near the assignment would prevent future confusion:

# This is the deployment manifest's own SHA-256, stored inside it during generation.
source_manifest_checksum = require_string(
    release_artifacts.get("manifest_sha256"),
    "manifest.release_artifacts.manifest_sha256",
)

2. Address and contract-set validation

Strengths:

  • ADDRESS_RE correctly enforces 20-byte hex format.
  • Zero-address rejection is explicit.
  • Duplicate detection uses .lower() for comparison, preventing case-sensitivity bypass.
  • Contract-set validation is symmetric — it catches both manifest-omitting-release-contracts and manifest-referencing-unknown-contracts.
  • Both ABI and runtime bytecode hashes are cross-checked against the release artifact baseline; neither alone is sufficient.
  • require_bool for source_dirty correctly rejects the string "false" — the test for this is good to have explicitly.

Gaps:

a) Missing test for the "unknown contracts" branch:
validate_contract_set has two error branches but only one is exercised. test_generator_rejects_missing_release_contract deletes Beta from the manifest (triggering "omits release contracts"), but there is no test that adds an extra contract to the manifest that isn't in the release artifacts (the "references unknown contracts" branch). Adding this test would give full branch coverage:

def test_generator_rejects_unknown_contract(self) -> None:
    with tempfile.TemporaryDirectory() as temp_dir:
        root = Path(temp_dir)
        release_dir = release_artifacts(root)
        manifest_path = deployment_manifest(root)
        manifest = generator.load_json(manifest_path)
        manifest["contracts"]["Gamma"] = {
            "address": "0x0000000000000000000000000000000000000003",
            "abi_hash": "sha256:" + ("c" * 64),
            "bytecode_hash": "sha256:" + ("3" * 64),
            "verification_status": "not_applicable",
        }
        write_json(manifest_path, manifest)

        with self.assertRaisesRegex(generator.AddressBookError, "unknown contracts"):
            generator.build_address_book(manifest_path, release_dir, root)

b) Missing test for the missing-output-dir branch in check_address_books:
check_address_books returns 1 with an error if output_dir doesn't exist. This is not covered by the existing tests.

c) lifecycle_state and verification_status are not validated against an allowlist:
Both are passed through with require_string() only. A manifest with lifecycle_state: "hacked" or verification_status: "unknown_value" would be silently projected into the address book. Given the schema version is v1 and the field values are protocol-defined, constraining them now costs little:

VALID_LIFECYCLE_STATES = {"Rehearsed", "Broadcast", "Verified", "Deprecated"}
VALID_VERIFICATION_STATUSES = {"not_applicable", "pending", "verified", "failed"}

d) Minor: chain_id and commit format not validated:
require_int permits chain_id: 0 or negative values; require_string accepts any non-empty string for commit. A chain_id > 0 guard and a 40-char hex pattern for commit would be cheap additions.


3. Drift-check wiring

The wiring is clean and does not duplicate unrelated checks:

Surface Test step Check step
check.sh test_address_books.py generate_address_books.py --check
check.ps1 same same
Makefile address-books-check test_address_books.py generate_address_books.py --check
CI "Address books" step test_address_books.py generate_address_books.py --check

The address-books-check Makefile target correctly depends on deployment-manifest-check (not release-artifacts-check), which matches the actual dependency — address books read from committed abi-checksums.json, not from a freshly built artifact. The CI step is isolated from the release-artifact and ABI compatibility steps. filecmp.cmp(..., shallow=False) ensures byte-level comparison, not just mtime/size.

One scalability note: DEFAULT_MANIFESTS is a static list. As more networks or deployment versions are added under deployments/examples/, maintainers will need to update the default list or always pass --manifest flags — neither generate nor --check auto-discovers new manifests from the directory. The check mode won't catch a missing address book for a newly added manifest unless the developer runs with the explicit --manifest flag. Auto-discovery from the directory (with the default list as a fallback) would make this more robust at scale, but this is a forward-looking concern for the current single-manifest state.


4. Documentation clarity — address books vs full deployment manifests

The distinction is clearly drawn and consistently stated across:

  • docs/deployment.md: explicit paragraph on what address books contain and explicitly exclude ("without parsing constructor arguments or admin ceremony details")
  • docs/tooling.md: repeats the distinction in the release-artifacts workflow section
  • README.md: the "address-book step" description in the Quickstart correctly scopes it to "compact generated address books"
  • docs/status.md: scripts/test_address_books.py and scripts/generate_address_books.py --check are described accurately

The deployments/README.md was listed as changed — that file would be the natural canonical home for the schema field-by-field table distinguishing the two formats, if one doesn't already exist there.


Summary

Area Status Notes
Schema design ✅ Clean Field selection is the right integrator projection
Address validation ✅ Strong Format, zero address, case-insensitive duplicate
Contract-set validation ✅ Symmetric Both directions caught
Hash cross-checks ✅ Both hashes ABI + runtime both validated
Missing test: unknown-contracts branch ⚠️ Gap Add test_generator_rejects_unknown_contract
Missing test: missing output_dir ⚠️ Gap Minor but branch is untested
lifecycle_state / verification_status allowlists ⚠️ Weak Enum-like fields accepted without constraint
Drift wiring ✅ No duplication Dependency chain correct
Documentation ✅ Clear Consistent across all docs surfaces

@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

🤖 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/generate_address_books.py`:
- Around line 62-65: The require_int validator incorrectly accepts booleans
because bool is a subclass of int; update require_int (used for fields like
chain_id) to reject bools explicitly by checking that the value is an int but
not a bool (or by requiring type(value) is int) and raise AddressBookError if
the value is a boolean or non-int so only real integers pass validation.
🪄 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

Run ID: 19b37cfa-862d-4081-b058-678e426033b8

📥 Commits

Reviewing files that changed from the base of the PR and between 5646761 and 20fc734.

📒 Files selected for processing (14)
  • .github/workflows/ci.yml
  • Makefile
  • README.md
  • deployments/README.md
  • deployments/address-books/anvil-6529stream-v0.1.0-001.json
  • docs/deployment.md
  • docs/status.md
  • docs/tooling.md
  • ops/AUTONOMOUS_RUN.md
  • ops/ROADMAP.md
  • scripts/check.ps1
  • scripts/check.sh
  • scripts/generate_address_books.py
  • scripts/test_address_books.py

Comment thread scripts/generate_address_books.py

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

I addressed the findings from comment 4679312734 in f626303:

  • removed duplicate deployment-manifest-check execution from make check,
  • added deployments/schema/address-book.schema.json,
  • added a generated-output/no-manual-edits note for address books,
  • normalized generated addresses to lowercase,
  • constrained verification_status to the deployment-manifest enum,
  • validated sha256: hash formats,
  • expanded address-book tests to cover mixed-case normalization, invalid verification status, and invalid hash format.

Validation rerun: focused address-book tests/checks, Python compile, shell/PowerShell syntax, JSON parsing, make check, Windows scripts\check.ps1, and whitespace check.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== Makefile check target ==="
grep -A 10 '^check:' Makefile
echo ""
echo "=== address-book.schema.json ==="
cat deployments/schema/address-book.schema.json 2>/dev/null || echo "NOT FOUND"
echo ""
echo "=== no-manual-edits note in address-books README/header ==="
find deployments/address-books -type f | sort
grep -r "manual" deployments/address-books/ 2>/dev/null || echo "No manual-edit note found in address-books dir"
grep -r "generated" deployments/address-books/ 2>/dev/null | head -10
grep -r "manual\|do not edit\|generated output" deployments/README.md 2>/dev/null | head -10
echo ""
echo "=== normalize_address in generate_address_books.py ==="
grep -A 15 "def normalize_address" scripts/generate_address_books.py
echo ""
echo "=== verification_status constraint ==="
grep -A 20 "verification_status\|VALID_VERIF\|allowlist\|enum" scripts/generate_address_books.py | head -50
echo ""
echo "=== sha256 hash validation ==="
grep -A 10 "sha256\|HASH_RE\|hash.*format\|validate.*hash" scripts/generate_address_books.py | head -50
echo ""
echo "=== test file additions ==="
grep -A 5 "def test_generator" scripts/test_address_books.py

Length of output: 11643


🏁 Script executed:

#!/bin/bash
echo "=== lifecycle_state handling in generator ==="
grep -n "lifecycle_state\|LIFECYCLE\|require_enum" scripts/generate_address_books.py

echo ""
echo "=== mixed-case normalization test ==="
grep -A 20 "test_generator.*mixed\|mixed.*case\|normalize.*address\|lower" scripts/test_address_books.py | head -40

echo ""
echo "=== unknown contracts test ==="
grep -n "unknown\|rejects_unknown" scripts/test_address_books.py

echo ""
echo "=== schema address pattern check (lowercase only vs mixed) ==="
grep -n "pattern\|address" deployments/schema/address-book.schema.json | head -20

echo ""
echo "=== ADDRESS_RE regex in generator ==="
grep -n "ADDRESS_RE" scripts/generate_address_books.py

Length of output: 1738



@punk6529 — all six items from comment 4679312734 are confirmed in the code:

Finding Fix Status
Duplicate deployment-manifest-check in make check Dropped from direct deps; only via address-books-check
Missing address-book.schema.json Added at deployments/schema/address-book.schema.json with sha256/$defs, lowercase-only address pattern, lifecycle/verification enums, chain_id minimum, commit hex pattern
No "do not manually edit" note Present in deployments/README.md
Address case not normalized normalize_address returns address.lower(); schema address def uses ^0x[0-9a-f]{40}$
verification_status unconstrained require_enum() + VERIFICATION_STATUSES frozenset; test test_generator_rejects_invalid_verification_status added
Hash format not validated require_sha256() + SHA256_RE; test test_generator_rejects_invalid_hash_format added

Two small items from the second review comment remain open if you want to close them, or they can be deferred:

  1. lifecycle_state uses require_string not require_enum in the generator (line 251–252). The JSON Schema constrains it, but the Python runtime will silently pass any non-empty string through without raising AddressBookError. Adding require_enum(manifest.get("lifecycle_state"), "manifest.lifecycle_state", LIFECYCLE_STATES) (parallel to the verification_status fix) would make runtime and schema consistent.

  2. validate_contract_set "references unknown contracts" branch is untested. Only the "omits release contracts" branch has a test. A counterpart test (add an extra contract to the manifest that isn't in release artifacts, assert the "unknown contracts" error) would give full branch coverage.

Neither is blocking — the schema catches (1) at any schema-validating consumer and (2) the branch is exercised in production use. Happy to track either as a follow-up issue if useful.

@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.

🧹 Nitpick comments (1)
deployments/schema/address-book.schema.json (1)

52-61: 💤 Low value

Consider adding lifecycle_state enum validation in the generator.

The schema correctly defines the lifecycle_state enum, but the generator (snippet 3, line 251) only validates that it's a non-empty string without checking against allowed values. For consistency with the verification_status enum validation added in the follow-up commit, consider adding lifecycle_state enum validation in the generator.

Enhancement: Add enum constant and validation

In scripts/generate_address_books.py, define the lifecycle state choices and use require_enum instead of require_string:

LIFECYCLE_STATES = frozenset({
    "Planned",
    "Rehearsed", 
    "Active",
    "Deprecated",
    "EmergencySuperseded",
    "Retired",
    "Cancelled",
})

# In build_address_book:
"lifecycle_state": require_enum(
    manifest.get("lifecycle_state"),
    "manifest.lifecycle_state",
    LIFECYCLE_STATES,
),
🤖 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 `@deployments/schema/address-book.schema.json` around lines 52 - 61, The
generator currently uses require_string for lifecycle_state in
build_address_book which only checks non-empty strings; add a LIFECYCLE_STATES
constant (frozen set of the seven allowed values) in
scripts/generate_address_books.py and replace the require_string call for
manifest.get("lifecycle_state") with
require_enum(manifest.get("lifecycle_state"), "manifest.lifecycle_state",
LIFECYCLE_STATES) so lifecycle_state is validated against the schema's enum;
keep the symbol names LIFECYCLE_STATES, build_address_book, require_enum, and
manifest.get("lifecycle_state") to locate the change.
🤖 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.

Nitpick comments:
In `@deployments/schema/address-book.schema.json`:
- Around line 52-61: The generator currently uses require_string for
lifecycle_state in build_address_book which only checks non-empty strings; add a
LIFECYCLE_STATES constant (frozen set of the seven allowed values) in
scripts/generate_address_books.py and replace the require_string call for
manifest.get("lifecycle_state") with
require_enum(manifest.get("lifecycle_state"), "manifest.lifecycle_state",
LIFECYCLE_STATES) so lifecycle_state is validated against the schema's enum;
keep the symbol names LIFECYCLE_STATES, build_address_book, require_enum, and
manifest.get("lifecycle_state") to locate the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d859cc97-fc69-47cb-b814-c6ce2f6046d5

📥 Commits

Reviewing files that changed from the base of the PR and between 20fc734 and f626303.

📒 Files selected for processing (9)
  • Makefile
  • deployments/README.md
  • deployments/schema/address-book.schema.json
  • docs/deployment.md
  • docs/tooling.md
  • ops/AUTONOMOUS_RUN.md
  • ops/ROADMAP.md
  • scripts/generate_address_books.py
  • scripts/test_address_books.py
✅ Files skipped from review due to trivial changes (3)
  • docs/tooling.md
  • docs/deployment.md
  • ops/ROADMAP.md
🚧 Files skipped from review as they are similar to previous changes (5)
  • deployments/README.md
  • Makefile
  • ops/AUTONOMOUS_RUN.md
  • scripts/generate_address_books.py
  • scripts/test_address_books.py

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Final re-check please. I addressed the inline require_int finding in ef5f5e6 and resolved the thread:

  • require_int rejects booleans,
  • chain_id must be positive,
  • git.commit must be a 40-character hash,
  • lifecycle_state is constrained to the deployment schema enum,
  • tests now cover 14 address-book cases, including missing output directory and unknown contracts.

Validation rerun: address-book tests/check, full Python compile, shell/PowerShell syntax, JSON parsing, make check, Windows scripts\check.ps1, and whitespace check.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== require_int boolean rejection ==="
grep -A 15 "def require_int" scripts/generate_address_books.py

echo ""
echo "=== chain_id positive constraint ==="
grep -n "chain_id" scripts/generate_address_books.py | head -20

echo ""
echo "=== git.commit 40-char hex validation ==="
grep -n "commit\|COMMIT_RE\|40" scripts/generate_address_books.py | head -20

echo ""
echo "=== lifecycle_state require_enum usage ==="
grep -n "lifecycle_state\|LIFECYCLE" scripts/generate_address_books.py | head -20

echo ""
echo "=== LIFECYCLE_STATES constant ==="
grep -A 5 "LIFECYCLE_STATES\s*=" scripts/generate_address_books.py

echo ""
echo "=== test count and new test methods ==="
grep -n "def test_" scripts/test_address_books.py

echo ""
echo "=== unknown contracts test ==="
grep -A 20 "test_generator_rejects_unknown_contract\|unknown_contract" scripts/test_address_books.py | head -30

echo ""
echo "=== missing output dir test ==="
grep -A 20 "missing_output\|output_dir\|nonexistent\|no_output" scripts/test_address_books.py | head -30

Length of output: 6326



@punk6529 — final re-check complete. All remaining open items from the previous review round are confirmed addressed in ef5f5e6:

Item Implementation Test
require_int rejects booleans isinstance(value, bool) guard in require_int test_generator_rejects_boolean_chain_id
chain_id must be positive New require_positive_int helper; used at manifest.network.chain_id test_generator_rejects_nonpositive_chain_id
git.commit 40-char hex GIT_COMMIT_RE = r"^[0-9a-fA-F]{40}$"; require_git_commit() used at line 290 test_generator_rejects_invalid_git_commit
lifecycle_state enum LIFECYCLE_STATES frozenset (Planned, Rehearsed, Active, Deprecated); require_enum() at line 277 test_generator_rejects_invalid_lifecycle_state
Unknown-contracts branch test_generator_rejects_unknown_contract — adds Gamma to manifest, asserts "unknown contracts" error
Missing output-dir branch test_check_mode_rejects_missing_output_directory

14 test methods confirmed. The validation surface is now complete end-to-end: boolean/int type safety, positive chain_id, 40-char hex commit, lifecycle and verification enums, sha256-prefix hash format, 20-byte non-zero addresses, case-insensitive duplicate detection, symmetric contract-set validation, and ABI + runtime bytecode hash cross-checks. Drift wiring is clean with no duplicate Make executions. Documentation is consistent across all surfaces.

No remaining open findings. The implementation is ready to merge.

[approve]

Copy link
Copy Markdown
Contributor Author

Merge decision for autonomous run:

  • GitHub Actions CI run 27339627582 completed successfully on head ef5f5e6e1c5841f2fd3a63281b2c1e065808812f.
  • CodeRabbit final re-check comment 4679472288 states there are no remaining open findings and the implementation is ready to merge.
  • The only CodeRabbit inline review thread was resolved after ef5f5e6.
  • The aggregate CodeRabbit commit status remains pending with no target URL, matching prior stale-pending bot behavior in this repo.
  • Claude was intentionally not requested per current user instruction.

Proceeding to merge rather than stall on the stale aggregate status.

@punk6529 punk6529 merged commit ad6deea into main Jun 11, 2026
2 checks passed
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.

[P1-RELEASE-003] Generate deployment address books

1 participant