Refuse to run on config keys the builder cannot build

build_demo.py reads every key with cfg.get(), so a config describing objects it does
not implement was skipped in silence — it printed DONE over an empty database. That
is the same "reports success over an environment that isn't" failure the purge section
exists to prevent, one layer up, and it is how a vertical config (take-offs, progress
statements) would have failed.

Unknown top-level keys now list themselves and abort. DEMO_ALLOW_UNKNOWN_KEYS=1
overrides for a deliberate partial run. Keys starting with _ stay free for comments,
so the shipped example config passes clean.

SKILL.md now states outright that build_demo.py is a per-engagement template rather
than an engine, since that is what makes the failure mode surprising.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
glenn
2026-07-31 11:10:16 +02:00
co-authored by Claude Opus 5
parent 8ea297e8bf
commit 6b48fdf126
2 changed files with 28 additions and 1 deletions
+10 -1
View File
@@ -146,7 +146,16 @@ are heavy; allow several minutes.
Industry-appropriate, minimal but believable, generated from the brief — the client's own
partners, products, projects and orders, staged so each hero has a record to fire on.
Drive it from a `demo_config.json` (see `demo_config.example.json`) and
`scripts/build_demo.py`. Rules:
`scripts/build_demo.py`.
**`build_demo.py` is a per-engagement template, not an engine.** It implements one shape
(products, fleet, credit limits, prestaged receivables) and reads every key with
`cfg.get()`, so anything it does not implement would otherwise be skipped in silence — a
`DONE` over an empty database. It now refuses to run on config keys it cannot build, listing
them; extend the script, or drop the keys. `DEMO_ALLOW_UNKNOWN_KEYS=1` overrides for a
deliberate partial run. Extend `KNOWN_KEYS` whenever you add a block.
Rules:
- **Get-or-create by name** so re-runs are idempotent.
- Set the right **currency** first (activate it with `context={'active_test': False}`, set
+18
View File
@@ -14,6 +14,24 @@ from odoo_connect import x, get_or_create, URL, DB
CFG = os.path.join(os.path.dirname(os.path.abspath(__file__)), "demo_config.json")
cfg = json.load(open(CFG, encoding="utf-8"))
# Every key below is read with cfg.get(), so anything this script does not know about is
# silently skipped. That is how a vertical config (take-offs, progress statements, ...) fed
# to the stock builder prints DONE over an empty database. Fail loudly instead: this script
# is a per-engagement TEMPLATE, and an unknown key means it has not been adapted yet.
KNOWN_KEYS = {
"client", "currency", "use_credit_limit", "scope_modules", "products", "customers",
"vehicles", "pricelist", "prestage_receivables", "heroes",
}
unknown = sorted(k for k in cfg if k not in KNOWN_KEYS and not k.startswith("_"))
if unknown:
print("!! demo_config.json has keys this builder does not implement:")
for k in unknown:
print(f" {k}")
print("!! They will NOT be created. Either extend this script to handle them, or")
print("!! remove them so the config reflects what actually gets built.")
if os.environ.get("DEMO_ALLOW_UNKNOWN_KEYS") != "1":
raise SystemExit("aborting: unimplemented config keys (set DEMO_ALLOW_UNKNOWN_KEYS=1 to override)")
# 1. currency (must run before invoices)
cur = cfg.get("currency")
if cur: