Reseam as callista-odoo-demo: source-agnostic discovery, parallel build, follow-through

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>
This commit is contained in:
glenn
2026-07-31 10:54:12 +02:00
co-authored by Claude Opus 5
parent ada2751eea
commit 8ea297e8bf
4 changed files with 368 additions and 86 deletions
+279 -46
View File
@@ -1,77 +1,310 @@
---
name: odoo-demo-architect
description: Build a complete, client-tailored Odoo demo from a discovery call. Mines the client's pains, researches native-vs-custom for each hero feature, stands up a LIVE Odoo database (modules + realistic data + working hero features) over XML-RPC, tests it, and generates the sales docs (run-of-show, one-pager, step-by-step script). Use when prepping an Odoo sales demo, POC, or proof-of-value before a client meeting. Triggers: "build an Odoo demo", "demo DB for <client>", "Odoo proof of concept", "stand up a demo before the meeting".
name: callista-odoo-demo
description: Build a complete, client-tailored Odoo demo end to end — assembles the discovery brief from any source (transcript, notes, email, Knowcap, or a live interview), researches native-vs-custom per hero feature, stands up a LIVE Odoo database over XML-RPC (modules + realistic data + working heroes), tests it, and generates the sales docs and the post-demo follow-through set (objection sheet, scoped quote, timeline, SOW). Use when prepping an Odoo sales demo, POC, or proof-of-value, or when writing the follow-up after one. Triggers: "build an Odoo demo", "demo DB for <client>", "Odoo proof of concept", "stand up a demo before the meeting", "write the follow-up after the demo".
---
# Odoo Demo Architect
# Callista Odoo Demo
Turn a discovery call into a polished, working Odoo demo + the documents to sell it — end to end, with minimal human steering. Built from a real engagement that won on first showing.
Turn a discovery call into a working Odoo demo, then into the documents that sell it.
> **Powered by Claude Code (the agent) + Knowcap (the memory).** The agent pulls the discovery call from **Knowcap** over its MCP — the client's pains in their own words — then researches, builds, writes + ships the custom code, and tests. The agent is only as good as its memory; Knowcap is the memory. → knowcap.ai
Three phases. **Discovery brief****Build****Follow-through**. Each is usable alone:
a brief without a build is still a brief, and Follow-through runs days after the demo.
## What it produces
1. A **live Odoo database** with the client's modules installed, realistic industry data, and the 12 "hero" features that map to their pain — actually working, not slideware.
2. Three **sales documents** (brand-themed, self-contained HTML): a **run-of-show**, a **one-pager** for the decision-maker, and a **1-page step-by-step demo script**.
3. A **verification log** proving each hero feature fired (e.g. "credit block raised at 56,379 > 50,000; override confirmed").
> Fork of [Smetools/odoo-demo-architect](https://github.com/Smetools/odoo-demo-architect)
> (MIT). Diverges in three ways: discovery is source-agnostic rather than Knowcap-bound,
> the build forks two parallel agents, and Follow-through is new. See `UPSTREAM.md`.
## Inputs you need before starting
- **Discovery material** — pull the meeting transcript from **Knowcap** via its MCP (`get_source_transcriptions`; locate it with `list_sources` / `search_memories`). This is the agent's memory of what the client actually said. (No Knowcap? A transcript or notes works too.)
- **Agreed scope** — which Odoo areas are in Phase 1 (Sales, Inventory, Accounting, Fleet, etc.).
- **A reachable Odoo instance + credentials** — `URL`, `DB`, `login`, and an **API key** (Settings → My Profile → Account Security → New API Key). Works on Odoo Online, self-hosted, or Odoo.sh.
- *Odoo.sh note:* create the project + enter any partner trial code FIRST (web UI only — no API for project creation). Then proceed here once the DB is up and you have an API key.
**Vertical skills extend this one** — see [Extension points](#extension-points). If a
vertical skill invoked you, apply its overlays; do not make it restate the pipeline.
## The pipeline (run in order)
---
### 1. Mine the discovery — via Knowcap
Pull the meeting transcript from **Knowcap** over the MCP (`get_source_transcriptions`, after locating the source with `list_sources` / `search_memories`). From it, extract and write down:
- The **business shape** (entities, what they sell, who they sell to). Watch for "it's a group" that is really ONE company in Odoo — confirm chart-of-accounts/P&L/warehouse are shared.
- The **top 35 pains in the client's own words** (quote them). These become the demo beats.
- The **12 hero features** — the differentiators that justify the spend. Everything else is supporting flow.
## Phase A — Discovery brief
### 2. Research native-vs-custom (don't assume)
For EACH hero feature, verify whether Odoo does it natively, no-code, or needs custom code — for the client's **exact Odoo version**. Use the Perplexity MCP (`perplexity_ask`) or web search. Ask precisely, e.g. *"In Odoo <ver>, is there a native hard-block (not warning) on SO confirmation over credit limit?"* Capture the verdict + citations. This step repeatedly overturns assumptions (e.g. credit limit is **warning-only** natively; v19 fleet dispatch IS native but only via `stock_fleet`).
Goal: `discovery_brief.md` in the six-section shape the rest of the pipeline consumes.
### 3. Connect (XML-RPC)
Use `scripts/odoo_connect.py`. Authenticate, print `server_version` to confirm the major version (field names differ across versions — see `reference/odoo19-field-gotchas.md`). All build steps go through the `x(model, method, *args, **kwargs)` helper.
**Source, in order of preference:**
1. A transcript, meeting notes, or email thread — read it.
2. Knowcap over MCP, if available and the user wants it (`get_source_transcriptions`,
after locating the source with `list_sources` / `search_memories`).
3. Nothing written down → interview the user.
### 4. Install modules for the scope
`button_immediate_install` on the `ir.module.module` ids. Common set: `sale_management`, `stock`, `account_accountant`, `stock_delivery`, `stock_picking_batch`, `fleet`, `web_studio`, `base_automation`, `contacts`. For fleet load-by-weight on v19 also install `stock_fleet` (Stock Transport — adds vehicle capacity + batch dispatch). Module installs are heavy; allow several minutes.
### Intake — infer first, ask only the gaps
Before asking anything, **look**: glob the working directory for a transcript, notes,
brief, or `.md`/`.txt`/`.docx` that plausibly is the source, and read it. Then answer
each item below from what you read. Only the items you genuinely cannot answer go to
the user, in **one** `AskUserQuestion` batch — never a serial interrogation, never a
question whose answer is sitting in the file you just read.
| Item | Infer from | Ask only if |
|---|---|---|
| **Source brief location** | A single obvious candidate file in the working directory | Zero or several candidates — ask which, or paste |
| **Odoo UI language** | Language the brief is written in; client country; `l10n_*` in scope | Brief is English but the client clearly isn't anglophone — ask (nl_BE / fr_BE / en_US / other) |
| **Client website / company info** | URL or company name in the brief — fetch the site, mine it for what they build or sell, size, regions, branding | No name or URL anywhere in the source |
| **Odoo instance** | `demo_config.json`, prior session, the brief | Not found — always ask, never guess a URL or API key |
| **Demo audience** | Attendee list in a transcript header or email thread | Source is notes with no names |
| **Rate card** | A rates file in the project | Only needed at Phase C — don't ask now |
Anything still missing after that batch: write it into the brief as `(unknown)` and
carry on. One unknown does not block building the demo.
If nothing written down exists at all, the interview replaces the table — still one
batch: who the client is, what they sell or build, how they quote today, how they
invoice, the top 3 complaints they voiced, who is in the room.
**Write `discovery_brief.md` with these six sections and no others:**
```markdown
## Business shape
Entities, product/customer types, volumes, shared financials.
Company name, website, country, what they actually do — from the site if you fetched it.
Watch for "it's a group" that is really ONE company in Odoo — confirm whether
chart-of-accounts, P&L and warehouse are shared.
## Top pains
35 items. Direct client quotes where you have them. Mark anything you inferred as (inferred).
## Hero features
12. Each names the pain it kills and the decision-maker it lands on.
Everything else is supporting flow.
## Phase 1 scope
Odoo apps in scope, plus any vertical modules routed by an extending skill.
## Odoo instance
URL, database, login, API key. Ask if absent — do not guess.
UI language + `l10n_*` localisation to install.
## Demo audience
Who is in the room and what each one needs to hear.
```
Never invent a pain quote. An inferred pain marked `(inferred)` is fine; a fabricated
quote read back to the client in the demo is not.
Show the brief to the user and get a yes before Phase B.
---
## Phase B — Build
Steps are **named, not numbered** — reference them by name, and never rename a step
casually, because extending skills point at these names.
### Fork the slow half
*Instance prep* and *client research* are independent: the install list comes from the
brief (plus any routing overlay), while research feeds hero *building*, which happens
after both. Installing over XML-RPC is minutes of waiting that produces log spew nobody
needs in context. Run them as two parallel subagents launched in **one** message:
**Agent 1 — instance prep.** Give it the Odoo credentials and the module list. It sets
company, currency, UoM and UI language, installs the localisation, then the modules,
then walks Settings for behaviours that default off. It loads **no data** — that is the
join step's job. Returns: what installed, what failed, the settings it changed.
**Agent 2 — client research.** Give it the brief. It fetches the client's website and
researches each hero feature (see *Research native-vs-custom*). Returns: per hero, the
verdict and the click-path if the capability already exists.
**Join.** Both done → install anything research turned up that prep didn't know about
(incremental, cheap) → *Load demo data**Build heroes**Test heroes*.
Two agents, not five. Do not fan out further — hero building is sequential against one
database, and parallel writes will fight.
### Research native-vs-custom
For EACH hero feature, verify whether Odoo does it natively, no-code, or needs custom
code — for the client's **exact Odoo version**. Use the Perplexity MCP (`perplexity_ask`)
or web search. Ask precisely, e.g. *"In Odoo <ver>, is there a native hard-block (not
warning) on SO confirmation over credit limit?"* Capture the verdict + citations.
This step repeatedly overturns assumptions — credit limit is **warning-only** natively;
v19 fleet dispatch IS native but only via `stock_fleet`. Version assumptions are the #1
source of wasted effort.
An extending skill may insert its own tier ahead of native — see [Extension points](#extension-points).
### Connect
Use `scripts/odoo_connect.py`. Authenticate, print `server_version` to confirm the major
version (field names differ across versions — see `reference/odoo19-field-gotchas.md`).
All build steps go through the `x(model, method, *args, **kwargs)` helper.
### Install modules
`button_immediate_install` on the `ir.module.module` ids. Common set: `sale_management`,
`stock`, `account_accountant`, `stock_delivery`, `stock_picking_batch`, `fleet`,
`web_studio`, `base_automation`, `contacts`. For fleet load-by-weight on v19 also install
`stock_fleet` (Stock Transport — adds vehicle capacity + batch dispatch). Module installs
are heavy; allow several minutes.
### Load demo data
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:
### 5. Generate + load realistic demo data
Industry-appropriate, minimal but believable. Drive it from a `demo_config.json` (see `demo_config.example.json`) and `scripts/build_demo.py`. Rules:
- **Get-or-create by name** so re-runs are idempotent.
- Set the right **currency** first (activate it with `context={'active_test': False}`, set on `res.company`) — BEFORE posting any invoices (currency can't change once journal entries exist).
- Give products a **weight** if fleet is in scope. Give customers **credit limits** (`use_partner_credit_limit=True`, `credit_limit=...`) if credit is in scope.
- **Pre-stage state** to make heroes fire live: e.g. post an unpaid invoice to put a customer's receivable JUST under their limit, so a live order tips them over. Keep one demo quotation in **draft** for the live click.
- Set the right **currency** first (activate it with `context={'active_test': False}`, set
on `res.company`) — BEFORE posting any invoices. Currency can't change once journal
entries exist.
- Give products a **weight** if fleet is in scope. Give customers **credit limits**
(`use_partner_credit_limit=True`, `credit_limit=...`) if credit is in scope.
- **Pre-stage state** so heroes fire live: e.g. post an unpaid invoice putting a
customer's receivable JUST under their limit, so a live order tips them over. Keep one
demo quotation in **draft** for the live click.
- Seed stock with `inventory_mode` context so deliveries can reserve (go Ready).
### 6. Build the hero features — no-code first, module as fallback
- **Prefer no-code:** server actions / automated rules (`base.automation`) / Studio. Portable to any Odoo, no deploy.
- **Custom module only if needed:** generate a minimal module, push to the instance's git (Odoo.sh) or hand it to the user to deploy, then install + test. Keep modules tiny and version-correct.
- Example hero (credit hard-block + manager override): override `sale.order.action_confirm` to raise `UserError` when `partner.credit + amount_total > credit_limit` unless the user is in an approver group; add an "Override" button gated to that group. (No-code equivalent: a Studio approval rule on the Confirm button + a stored "over limit" flag.)
### Build heroes
### 7. Test every hero over XML-RPC
On a THROWAWAY record: trigger the action, assert the block fires, assert the override path works, then delete the throwaway. Leave the real demo objects pristine. Print a verification log with the actual numbers.
- **Prefer no-code:** server actions / automated rules (`base.automation`) / Studio.
Portable to any Odoo, no deploy.
- **Custom module only if needed:** generate a minimal module, push to the instance's git
(Odoo.sh) or hand it to the user to deploy, then install + test. Keep modules tiny and
version-correct.
- Example hero (credit hard-block + manager override): override `sale.order.action_confirm`
to raise `UserError` when `partner.credit + amount_total > credit_limit` unless the user
is in an approver group; add an "Override" button gated to that group.
### Test heroes
**Mandatory.** A demo hero that fails live loses the deal. Trigger each hero, assert the
block fires, assert the override path works. Print a verification log with actual numbers
(e.g. "credit block raised at 56,379 > 50,000; override confirmed").
Test against a **throwaway** partner named `ZZ Test…`, never the client's own records — a
hero you tested is a hero you consumed, and the demo needs its first click to be the first
click.
### Purge test residue
**A demo environment ships with zero test residue.** Debugging a chain takes several runs,
each leaving a full trail; "it's cancelled and the partner is archived" is not clean —
those records still list on screen. Write the purge as a function in the test script and
run it until the counts are zero, not as a one-off you improvise at the end.
Odoo blocks most deletion unless you go in dependency order, leaves last. An extending
skill supplies the exact chain for its own models; the generic order is:
```
transient wizard rows → downstream documents (cancelled only, newest first)
→ invoices → time entries → tasks → projects → sale orders → the partner
```
The traps, each of which costs a debugging round:
- `search` will not find the partner once archived — pass `context={"active_test": False}`
or the purge silently no-ops and reports success.
- Invoices must go to draft before cancel; period-sequenced documents cancel newest-first only.
- **Delete the partner last, and only once nothing references it.** Deleting it first nulls
`partner_id` on whatever survived, so a `partner_id`-based purge can no longer see those
records and a `partner_id`-based assertion reports clean over an environment that isn't.
Sweep by name as well, and assert on both.
- Anything the tests **copy** inherits the source record's customer, not the throwaway one.
Repoint copies at the throwaway partner or they escape the purge.
- Make every step best-effort with its own `try`, and **print what it kept** — a silent
purge that skipped nine records reads exactly like one that worked.
Finish by reading back the counts of every model you touched into the verification log.
"No test residue" is a claim; the counts are the evidence.
### Sanity-check the staged numbers
A chain that passes every assertion can still look broken on screen. Check the staged data
reads plausibly: quantities consumed well under quantities ordered (over 100% makes any
progress or delivery view look wrong), costs under selling prices, dates in the past.
Derive staged quantities from the ordered quantity rather than hard-coding them, so they
cannot drift when a formula changes.
### Sales docs
From `templates/` (brand-themed, `{{placeholder}}`-driven), produce three self-contained
HTML files filled with the client's data:
### 8. Generate the sales docs
From `templates/` (genericized, brand-themed), produce three self-contained HTML files, filling in the client's data:
- **run-of-show** — beats with exact click-paths + what to say.
- **one-pager** — before/after, what's automated, investment, the path to go-live; branded for the *selling* company; decision-maker audience.
- **one-pager** — before/after, what's automated, investment, path to go-live; branded for
the *selling* company; decision-maker audience.
- **demo-script-1pager** — 7-ish numbered steps (Do + Say), prints on one A4.
### 9. Hand off
Output: the login, the pre-loaded data cheat-sheet, the verification log, and links to the three docs. Remind the user to rehearse once and keep the demo quotation in draft.
### Hand off
Output: the login, the pre-loaded data cheat-sheet, the verification log, and links to the
three docs. Remind the user to rehearse once and keep the demo quotation in draft.
---
## Phase C — Follow-through
Runs after the demo happened. Needs: the built demo, the verification log, and what
actually came up in the room. Ask the user for the room notes — objections raised, who
pushed back, what they asked for that wasn't there.
Generate four documents, reusing `templates/` branding and its self-contained-HTML rule
(no external assets, single file, prints to A4).
| Document | Contents |
|---|---|
| **Objection sheet** | Every objection raised → the honest answer. Where the product already covers it, name the module and the screen. Where it doesn't, say so and give the workaround or the build estimate. |
| **Scoped quote** | Line items from the Phase 1 scope: modules, configuration, data migration, custom work, training. Days and rate per line. Flag assumptions separately from committed lines. |
| **Implementation timeline** | Phased, with the client's own dependencies on it (data extraction, sign-offs, who from their side). Weeks, not dates, unless a start date is agreed. |
| **Statement of work** | Deliverables, acceptance criteria, out-of-scope list, change-request process. The out-of-scope list is the point — write it properly. |
Rules:
- Every number traces to something. No invented day-rates, no invented licence costs — ask
the user for the rate card.
- Anything the demo *didn't* prove goes in the quote as build work, not as "included".
Cross-check against the verification log from *Test heroes*.
- The out-of-scope list is where the follow-through earns its keep. Anything discussed and
not quoted goes in it explicitly.
Show all four to the user before anything leaves the machine.
---
## Extension points
A vertical skill (construction, retail, …) wraps this one rather than restating it. It may
override exactly these, and nothing else:
| Extension point | What the vertical supplies | Applied at |
|---|---|---|
| **Module routing** | A pain → module table keyed on the client's own words | *Install modules*, and Phase A's `## Phase 1 scope` |
| **Solution precedence** | An extra tier ahead of native, e.g. `<vertical modules> → native Odoo → custom` | *Research native-vs-custom* |
| **Purge chain** | The exact model teardown order for its own models, replacing the generic chain | *Purge test residue* |
| **Demo data policy** | An override of what dataset gets loaded, or an instruction not to install a stock one | *Load demo data* |
| **Follow-through framing** | Vertical-specific objections and scope lines | Phase C |
Rules for the boundary:
- The vertical does **not** reimplement `scripts/`, `templates/`, or `demo_config.json` handling.
- It references steps by **name** (*Test heroes*, *Purge test residue*), never by number.
- Anything a vertical needs that isn't in the table above is a gap in *this* skill — fix it
here, so the next vertical gets it free.
---
## Guardrails
- **Never invent that a feature works — test it.** Step 7 is mandatory; a demo hero that fails live loses the deal.
- **Research before building** (step 2). Version assumptions are the #1 source of wasted effort.
- **Never invent that a feature works — test it.** *Test heroes* is mandatory.
- **Research before building.** Version assumptions are the #1 source of wasted effort.
- **Don't hard-code the client.** Everything client-specific lives in `demo_config.json`.
- **Currency before invoices. Weight before fleet. Pre-stage before the live click.** Order matters.
- Read `reference/odoo19-field-gotchas.md` before touching Odoo 19 — several core fields were renamed.
- Never hand over an environment holding test records. Purge them and read back the counts;
do not settle for "cancelled and archived" and do not write leftovers off as a note.
- Never send anything client-facing without the user reading it first.
- Read `reference/odoo19-field-gotchas.md` before touching Odoo 19 — several core fields
were renamed.
- `discovery_brief.md`, `demo_config.json` and the follow-through docs hold client data and
API keys — keep them in the project directory, never in a scratchpad you'd forget.
## Files
- `scripts/odoo_connect.py` — XML-RPC connector + `x()` helper (correct context-kwarg passing).
- `scripts/build_demo.py` — config-driven data + hero builder (template to adapt per engagement).
- `demo_config.example.json` — the shape of a per-client config.
- `reference/odoo19-field-gotchas.md` — version-specific field names + footguns learned the hard way.
- `templates/` the three doc templates (brand-themed, `{{placeholder}}` driven).
- `templates/` — doc templates (brand-themed, `{{placeholder}}` driven).
- `UPSTREAM.md` — fork point and divergence from Smetools/odoo-demo-architect.