The API can only prove a record is correct, not that the screen looks right, and
a Studio-modified form, a portal page or a report PDF can be wrong while every
API read passes. Adds a "Look at the screen" step: prefer Claude in Chrome (uses
the user's own Odoo session), fall back to a Playwright MCP, and where neither is
installed offer the choice once and accept screenshots rather than blocking the
build on a tool install.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The previous commit moved to /jsonrpc, which the v19 docs list as deprecated
alongside /xmlrpc — both go away in Odoo 22. The actual v19 external API is
JSON-2: POST /json/2/<model>/<method>, API key as a bearer token.
Three consequences, all of which change calling code:
- no uid and no password; UID now comes from res.users/context_get
- every argument is named, positional args do not exist, so x() becomes
x(model, method, ids=None, **kwargs) and callers pass domain=/vals=/fields=
- one call is one transaction and nothing chains, which is the mechanical
reason state changes must go through a button method
Batching: no multi-call envelope exists, so batching means widening a call, not
bundling calls. Added get_or_create_many() (one search_read + one create for a
whole set) and put build_demo.py's product, customer, vehicle, invoice and
headroom loops through set-based calls.
test_odoo_connect.py checks the call shape and the batching offline, with a
faked urlopen — none of this can be exercised without a live instance otherwise.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
JSON-RPC is the recommended Odoo API from 19 on. odoo_connect.py now posts to
/jsonrpc over stdlib urllib instead of xmlrpc.client — same x()/get_or_create()/
fields_named() surface, common.version() becomes version(), server errors raise
OdooError with Odoo's message, 600s timeout so module installs survive.
Also: state changes must go through the model's own button method, never a write
on state. Writing the field skips the delivery order, the journal entries, the
sequence and the validations a hero feature exists to demonstrate.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>
Callista consumes this pipeline for both plain Odoo implementations and
vertical demos, and is not a maintainer upstream — so the generic demo craft
that had accumulated in the buildease-demo vertical skill lands here instead,
where every engagement can reach it.
Moved in from buildease-demo (they were never construction-specific):
- Phase A: discovery brief from a transcript, notes, email, Knowcap, or a
batched interview. Replaces the Knowcap-bound step 1. Infers before it asks.
- Fork the slow half: instance prep and client research as two parallel
subagents, then join.
- Purge test residue: ordering, traps, read-back-the-counts evidence.
- Phase C: objection sheet, scoped quote, implementation timeline, SOW.
New here:
- Extension points — a vertical supplies module routing, solution precedence,
purge chain, demo-data policy and follow-through framing, and nothing else.
Anything it needs beyond those is a gap to fix here, not to work around.
- Named steps instead of numbered ones. Numbering meant an upstream renumber
silently misrouted an extending skill with nothing to detect it.
Renamed the skill to callista-odoo-demo: skills resolve by directory name, so
a same-named fork shadows upstream depending on install order, and two people
would build different demos from the same brief.
MIT retained; SMEtools copyright kept, Callista added for modifications.
Fork point and divergence recorded in UPSTREAM.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Public skill for Claude Code. Mines a discovery call, researches native-vs-custom,
stands up a working Odoo demo over XML-RPC (modules + data + tested hero features),
and generates run-of-show, one-pager, and a 1-page demo script.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SBytQq5dcASi4ETm7n6THb