Skip to content

fix: hard-fail missing infra templates and include source-contract template assets in upgrade plans#42

Merged
sbonoc merged 1 commit intomainfrom
codex/fix-issue-34-upgrade-bootstrap-templates
Apr 1, 2026
Merged

fix: hard-fail missing infra templates and include source-contract template assets in upgrade plans#42
sbonoc merged 1 commit intomainfrom
codex/fix-issue-34-upgrade-bootstrap-templates

Conversation

@sbonoc
Copy link
Copy Markdown
Owner

@sbonoc sbonoc commented Apr 1, 2026

Summary

This PR fixes the local bootstrap/upgrade drift described in issue #34.

Root causes addressed

  1. Bootstrap template failure was non-fatal in practice
  • ensure_file_from_template and ensure_file_from_rendered_template used command substitution directly.
  • Missing templates could fail in a subshell while the caller continued and created empty target files.
  1. Upgrade planning could miss newly introduced template assets
  • upgrade_consumer.py scoped candidate paths primarily from the target repo contract.
  • When a generated consumer contract lagged behind source, newly added template assets could be omitted from plan/apply.

Design

Bootstrap template handling

  • scripts/lib/blueprint/bootstrap_templates.sh
    • bootstrap_template_content now returns non-zero on missing templates.
    • Callers now explicitly check template resolution and log_fatal in parent shell.
    • Added empty-file repair behavior: if an existing template-backed target is zero bytes, rewrite it from template content and warn.

Upgrade planning scope

  • scripts/lib/blueprint/upgrade_consumer.py
    • Load source contract (when available) and merge source + target contract scopes for:
      • required_files
      • source_only_paths
      • consumer_seeded_paths
      • init_managed_paths
      • conditional_scaffold_paths
      • blueprint-managed roots
    • Union protected roots from both contracts for safety.
    • Result: lagging generated-consumer contracts still pick up newly introduced blueprint-managed template assets in upgrade plans.

Tests

  • Added tests/blueprint/test_bootstrap_templates.py
    • missing-template path now fails and does not create empty target file
    • existing zero-byte target is repaired from template content
  • Extended tests/blueprint/test_upgrade_consumer.py
    • verifies upgrade plan includes new template assets from source contract when target contract is lagging
  • Updated scripts/lib/quality/test_pyramid_contract.json to classify the new test file as unit.

Backward-Compatibility Notes

  • Additive vs behavior-changing
    • Additive: source+target contract scope merge for upgrade planning.
    • Behavior-changing (bug fix): missing bootstrap templates now stop execution instead of silently continuing.
  • Default behavior with features disabled
    • No feature toggles changed.
  • Impact on existing generated repos
    • Positive/safe: upgrade planning captures missing template assets more reliably.
    • Existing zero-byte template-backed files can now self-repair during bootstrap.
  • Upgrade/rebootstrap required?
    • No full rebootstrap required.
  • Migration steps for already-generated repos
    1. make blueprint-resync-consumer-seeds
    2. BLUEPRINT_RESYNC_APPLY_SAFE=true make blueprint-resync-consumer-seeds
    3. make blueprint-upgrade-consumer-preflight
    4. BLUEPRINT_UPGRADE_APPLY=true make blueprint-upgrade-consumer
    5. make blueprint-upgrade-consumer-validate
    6. make infra-validate

Validation Evidence

  • python3 -m unittest -q tests.blueprint.test_bootstrap_templates
  • python3 -m unittest -q tests.blueprint.test_upgrade_consumer
  • make quality-hooks-run

Fixes #34

@sbonoc
Copy link
Copy Markdown
Owner Author

sbonoc commented Apr 1, 2026

@copilot review

@sbonoc sbonoc merged commit 3d76c96 into main Apr 1, 2026
2 of 3 checks passed
@sbonoc sbonoc deleted the codex/fix-issue-34-upgrade-bootstrap-templates branch April 1, 2026 13:49
Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 1, 2026

@copilot review

Review complete. All 16 tests pass and quality hooks pass. Here's a summary of findings:

No blockers. The fix is correct and the two root causes are properly addressed.

Notable observations:

  1. render_bootstrap_template_content (line 40) — the inner content="$(bootstrap_template_content ...)" doesn't use the explicit if ! content=$(...) guard pattern (it relies on set -euo pipefail propagation instead). Works correctly, but slightly asymmetric with the caller functions. Not a bug.

  2. Trailing newlines stripped — bash command substitution strips trailing newlines from $(cat "$template_path"), so repaired/created files won't have a POSIX-compliant trailing newline. This is pre-existing behaviour (same as ensure_file_with_content path) and the test correctly expects it. Worth a follow-up if linting enforces trailing newlines on generated files.

  3. ensure_file_from_rendered_template coverage gap — missing-template and empty-file repair paths for the rendered variant aren't directly tested. The code is structurally identical to the tested ensure_file_from_template, so risk is low. A follow-up parametrised test would close the gap.

  4. source_only merge correctness — merging source contract's source_only paths into the upgrade classification is semantically correct: paths newly marked as source-only in a newer blueprint version will correctly be skipped in consumer upgrade plans.

  5. managed_dir_roots re-binding in main()_collect_candidate_paths returns a (potentially expanded) superset and rebinds the same variable name. Correct, but worth a comment if the signature is ever revisited.

Everything else looks clean. Commit: dd58df4.

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.

[bug]: local runtime bootstrap can fail when required infra templates are missing after consumer upgrade

2 participants