Add buildease-demo skill
Wraps odoo-demo-architect for BuildEase (callista-tools/mev) construction demos: discovery brief from any source instead of Knowcap, pain-to-module routing onto the 33 BuildEase modules, parallel instance-prep/research agents, throwaway-record verification with a full purge, and the post-demo follow-through set. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
---
|
||||
name: buildease-demo
|
||||
description: Wraps odoo-demo-architect for BuildEase (callista-tools/mev) construction demos. Builds the discovery brief from any source — transcript file, notes, email thread, or a live interview — instead of requiring Knowcap, routes client pains onto BuildEase modules before considering custom work, and after the demo generates the follow-through set (objection sheet, scoped quote, implementation timeline, SOW). Use for "BuildEase demo", "QTO demo", "construction Odoo demo", "prep a demo from these notes", or "write the follow-up after the demo".
|
||||
---
|
||||
|
||||
# BuildEase Demo
|
||||
|
||||
Three phases. `odoo-demo-architect` does the middle one; this skill owns the ends.
|
||||
|
||||
**Requires** `odoo-demo-architect` installed (`~/.claude/skills/odoo-demo-architect/`,
|
||||
from github.com/Smetools/odoo-demo-architect). If it is missing, say so and stop —
|
||||
do not reimplement its XML-RPC connector or data builder.
|
||||
|
||||
---
|
||||
|
||||
## Phase A — Discovery brief (no Knowcap)
|
||||
|
||||
Goal: produce `discovery_brief.md` in exactly the shape odoo-demo-architect's step 1
|
||||
would have emitted, from whatever the user actually has.
|
||||
|
||||
**Source, in order of preference:**
|
||||
1. A transcript, meeting notes, or email thread — read it.
|
||||
2. Knowcap MCP, if it happens to be available and the user wants it.
|
||||
3. Nothing written down → interview the user (see intake below).
|
||||
|
||||
### 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, 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 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 build — from the site if you fetched it.
|
||||
|
||||
## Top pains
|
||||
3–5 items. Direct client quotes where you have them. Mark anything you inferred as (inferred).
|
||||
|
||||
## Hero features
|
||||
1–2. Each names the pain it kills and the decision-maker it lands on.
|
||||
|
||||
## Phase 1 scope
|
||||
Odoo apps + BuildEase modules, from reference/buildease.md.
|
||||
|
||||
## 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, via odoo-demo-architect
|
||||
|
||||
Hand `discovery_brief.md` to `odoo-demo-architect` and let it run its pipeline
|
||||
(research → connect → install → data → heroes → test → sales docs).
|
||||
|
||||
### Fork the slow half
|
||||
|
||||
Module installation and client research are independent — the install list comes from the
|
||||
brief plus the routing table, the research feeds hero *building* which happens after both.
|
||||
Installing over XML-RPC is minutes of waiting and produces log spew nobody needs in context.
|
||||
So run them as two parallel subagents, launched in **one** message:
|
||||
|
||||
**Agent 1 — instance prep.** Give it the Odoo credentials, the routed module list, and
|
||||
odoo-demo-architect's `scripts/odoo_connect.py`. It sets the company, currency, UoM and
|
||||
UI language, installs the localisation, installs `buildease` + the routed modules, then
|
||||
walks Settings for the BuildEase toggles 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 **BuildEase → native Odoo 19 → custom**, in that order.
|
||||
Returns: per hero, which of the three it lands in, and the click-path if it already exists.
|
||||
|
||||
**Join.** Both done → install any module Agent 2's research turned up that Agent 1 didn't
|
||||
know about (incremental, cheap), then generate and load the client-specific dataset into
|
||||
the empty database, then build and test heroes.
|
||||
|
||||
Two agents, not five. Do not fan out further — hero building is sequential against one
|
||||
database and parallel writes will fight.
|
||||
|
||||
Two things to inject before it starts:
|
||||
|
||||
1. **Read `reference/buildease.md`** and pass the routed module list. The research step's
|
||||
native-vs-custom question becomes **BuildEase → native Odoo → custom**, in that order.
|
||||
Most construction pains are already solved in mev; custom work is the last resort.
|
||||
2. **This skill is the demo data loader.** Do not install `buildease_demo_data` — that is
|
||||
the old, one-size-fits-all Belgian dataset it replaces. The database starts empty and
|
||||
gets a dataset generated from the brief: the client's own partners, articles, projects
|
||||
and orders, staged so each hero feature has a record to fire on. Install it only if the
|
||||
user explicitly asks for the generic sandbox.
|
||||
|
||||
Its step 7 (test every hero on throwaway records) is not optional here either. A QTO →
|
||||
sale order → project → progress statement → invoice chain that breaks mid-demo is the
|
||||
one failure mode that loses the deal.
|
||||
|
||||
### Verify on throwaway records, then delete them
|
||||
|
||||
Test against a partner named `ZZ Test…`, never against 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.
|
||||
|
||||
**Then purge. A demo environment ships with zero test residue.** Debugging the chain takes
|
||||
several runs, each leaving a full take-off → order → project → statement → invoice 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 of this unless you go in order:
|
||||
|
||||
```
|
||||
transient wizard rows → statements (cancelled only, newest first) → invoices
|
||||
→ timesheet lines → tasks → projects → sale orders → take-offs → the partner
|
||||
```
|
||||
|
||||
The traps, all of which cost a debugging round:
|
||||
- **A take-off with no sale order cannot be deleted at all.** Its state is derived from the
|
||||
order, so there is nothing to cancel. Convert it to a quotation, cancel that, then delete.
|
||||
- `search` will not find the partner once archived — pass `context={"active_test": False}`
|
||||
or the purge silently no-ops and reports success.
|
||||
- Statements cancel newest-first only; invoices must go to draft before cancel; leftover
|
||||
`add.dynamic.article.template.line` rows pin take-offs.
|
||||
- **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 and putting them in the
|
||||
verification log. "No test residue" is a claim; the counts are the evidence.
|
||||
|
||||
### Sanity-check the staged numbers before calling it done
|
||||
|
||||
A chain that passes every assertion can still look broken on screen. Check the staged data
|
||||
reads plausibly: **booked hours well under ordered hours** (over 100% makes the progress
|
||||
statement 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.
|
||||
|
||||
---
|
||||
|
||||
## 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. Reuse odoo-demo-architect's `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 BuildEase 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 step 7.
|
||||
- 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.
|
||||
|
||||
---
|
||||
|
||||
## Guardrails
|
||||
|
||||
- Never claim a BuildEase feature works without having seen it work in the demo DB.
|
||||
- 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 the leftovers off as a note
|
||||
in the verification log.
|
||||
- Never send anything client-facing without the user reading it first.
|
||||
- `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.
|
||||
@@ -0,0 +1,78 @@
|
||||
# BuildEase (callista-tools/mev) — module map & pain routing
|
||||
|
||||
Odoo **19.0** vertical for construction / contracting. Repo: `git@github.com:callista-tools/mev.git`.
|
||||
34 modules, all LGPL-3. Umbrella module `buildease` depends on nothing and installs the set.
|
||||
|
||||
## The four core concepts
|
||||
|
||||
| Concept | Model | What it replaces at the client |
|
||||
|---|---|---|
|
||||
| **Quantity Take-Off (QTO)** | `quantity.take.off`, `.line`, `.line.calculation` | The measurement/estimating spreadsheet that gets re-keyed into a quote |
|
||||
| **Sale Progress** | `sale.progress`, `sale.progress.line` | Monthly progress statements (BE: *vorderingsstaat*) and % -complete invoicing |
|
||||
| **Adjustments** | `adjustment.create` + QTO/SP extensions | Variation orders / change orders (BE: *verrekeningen*) |
|
||||
| **Revision formula** | `revision.formula`, `revision.scheme`, `revision.parameter`, `index.value.date` | Contractual price-indexation formulas on progress statements |
|
||||
|
||||
A QTO holds lines; lines hold *calculation* lines (the measurement math). QTO → sale order → project → progress statements → invoices is the spine of every demo.
|
||||
|
||||
## Pain → module routing
|
||||
|
||||
Match the client's own words on the left; install the right.
|
||||
|
||||
| Client says | Install |
|
||||
|---|---|
|
||||
| "we measure in Excel then re-type it into the quote" | `quantity_take_off_base`, `quantity_take_off_sale` |
|
||||
| "every project starts from the same standard items" | + `quantity_take_off_base` template sets (`quantity.take.off.line.template.set`) |
|
||||
| "the same item recalculates from a few parameters" | `quantity_take_off_dynamic_calculation` |
|
||||
| "we add a % for general costs / site overhead" | `quantity_take_off_overhead` (+ `_dynamic_calculation_overhead` if both) |
|
||||
| "we invoice monthly on % complete" / "vorderingsstaat" | `sale_progress_base` |
|
||||
| "prices are indexed per the contract formula" | `sale_progress_revision_formula` |
|
||||
| "extra work / change orders are a mess" | `adjustments_base` (+ `sale_progress_revision_formula_adjustments` if both) |
|
||||
| "hours worked must land on the progress statement" | `sale_progress_base_timesheet`, `adjustments_base_timesheet` |
|
||||
| "subcontractors send us their own progress statements" | `sale_progress_purchase` (`subcontractor.progress.statement.wizard`) |
|
||||
| "we ask 3 suppliers for prices per item" | `quantity_take_off_purchase` (`purchase.request.wizard`, uses `purchase_requisition`) |
|
||||
| "made-to-order items priced from their bill of materials" | `buildease_custom_product`, `buildease_custom_product_bom_price_sync` (+ `_overhead`) |
|
||||
| "the client has to sign off" | `quantity_take_off_sale_signature`, `sale_progress_base_signature` |
|
||||
| "plans and datasheets must be on the site project" | `project_product_documents_link` |
|
||||
| "we track material deliveries to site" | `quantity_take_off_sale_stock`, `_sale_delivery` |
|
||||
| "one project, many purchase orders" | `quantity_take_off_sale_project_purchase`, `_project_stock` |
|
||||
| "our techs do call-outs / maintenance visits" | `quantity_take_off_sale_industry_fsm` |
|
||||
| "recurring maintenance contracts" | `quantity_take_off_sale_subscription` |
|
||||
| "estimates start from a lead" | `quantity_take_off_sale_crm` |
|
||||
| "supplier article numbers differ from ours" | `quantity_take_off_extra_article_nr` |
|
||||
| "same item in several sizes/finishes" | `sale_quantity_takeoff_variant` |
|
||||
| "management wants margin per project" | `sale_progress_quantity_take_off_report` (QTO carries `margin`, `margin_percentage` natively) |
|
||||
| "we live in spreadsheets" | `quantity_take_off_spreadsheet` |
|
||||
|
||||
## Demo data — `buildease_demo_data` is the OLD way
|
||||
|
||||
**Do not install `buildease_demo_data` or `buildease_demo_data_sale_progress` by default.**
|
||||
They are the previous generation of environment setup: one fixed Belgian construction
|
||||
dataset, the same for every prospect. This skill replaces them — demo data is generated
|
||||
per client from the discovery brief and loaded through odoo-demo-architect's
|
||||
`build_demo.py` / `demo_config.json`.
|
||||
|
||||
Install them only if the user explicitly asks, or when there is genuinely no client
|
||||
context and a generic sandbox is wanted. If you do, know what comes with them:
|
||||
`sale_management, purchase_stock, project, timesheet_grid, sale_timesheet, maintenance,
|
||||
quantity_take_off_sale, industry_fsm, l10n_be, accountant, uom` — including the Belgian
|
||||
localisation, which is wrong for most non-BE clients.
|
||||
|
||||
The app-level dependencies that dataset used to drag in (`sale_management`, `project`,
|
||||
`purchase_stock`, `sale_timesheet`, `industry_fsm`, `accountant`, `uom`) still need
|
||||
installing on their own — route them from the pain table above, not from the demo bundle.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Three dependencies are not in this repo**: `custom_product_sale`, `custom_product_bom`,
|
||||
`bom_on_sale_order_line`. Anything under `buildease_custom_product*` fails to install
|
||||
without them. Confirm their source before promising a BOM-pricing hero feature.
|
||||
- **Odoo 19 only.** Manifests are all `19.0.x`; do not attempt against 17/18.
|
||||
- `l10n_be` and `accountant` are pulled in by demo data — the demo DB is Belgian-localised.
|
||||
Wrong-country client → set `demo_config.json` company/fiscal position explicitly, or skip
|
||||
`buildease_demo_data` and stage minimal data instead.
|
||||
- `quantity.take.off` inherits `mail.thread` + `mail.activity.mixin` — chatter and activities
|
||||
work for free, good cheap demo beats.
|
||||
- `res.config.settings` and `res.company` are extended by 8 modules each. After installing,
|
||||
walk Settings once; several BuildEase behaviours are off by default.
|
||||
- `post_migrate.py` sits at repo root — relevant when upgrading an existing demo DB, not a
|
||||
fresh build.
|
||||
Reference in New Issue
Block a user