diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..ffd9b53 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,61 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## What this repository is + +This repo *is* a Claude Code skill, not an application. It contains no source code, tests, or build tooling — only prompt content: + +- `SKILL.md` — the skill body (`name: buildease-demo`), loaded by Claude Code when the skill is invoked. +- `reference/buildease.md` — the BuildEase module map and pain→module routing table, read at Phase A. + +Editing this repo means editing instructions that another Claude instance will follow. There is nothing to compile or lint; the only meaningful verification is running the skill end to end against a real Odoo instance. + +### Installing / testing a change + +```bash +ln -s "$PWD" ~/.claude/skills/buildease-demo +``` + +Claude Code discovers skills from the `name:`/`description:` frontmatter in `SKILL.md`. Changing `name:` changes how the skill is invoked; changing `description:` changes when it triggers — both are the routing surface, so treat them as API. + +## Architecture + +`buildease-demo` is a **thin vertical overlay** on `callista-odoo-demo`. It does not own a pipeline. It supplies exactly five overlays, each applied at a *named* step of the substrate skill: + +| Overlay | Applied at | +|---|---| +| Module routing (`reference/buildease.md`) | *Install modules*, Phase A `## Phase 1 scope` | +| Solution precedence — BuildEase → native Odoo 19 → custom | *Research native-vs-custom* | +| Demo data policy — never `buildease_demo_data` | *Load demo data* | +| Purge chain — take-off / progress-statement teardown order | *Purge test residue* | +| Follow-through framing | Phase C | + +**The boundary is the point of this repo.** Anything needed that isn't one of those five is a gap in `callista-odoo-demo` — fix it *there*, so the next vertical inherits it. Do not work around it here, and never reimplement the substrate's `scripts/`, `templates/`, or `demo_config.json` handling. + +This repo was previously a full three-phase skill. The generic two-thirds (discovery brief from any source, the two-agent parallel build, the follow-through doc set) moved into the substrate on 2026-07-31 because Callista runs it for plain Odoo implementations too, and that content was stranded behind a construction trigger. + +### Substrate and upstream + +| Repo | Role | +|---|---| +| `admin/callista-odoo-demo` (Gitea) | The pipeline this skill overlays. Hard dependency, installed as `~/.claude/skills/callista-odoo-demo/` | +| `github.com/Smetools/odoo-demo-architect` | What the substrate was forked from at `ada2751`. Callista has no commit rights; changes land in the fork. See its `UPSTREAM.md` | +| `git@github.com:callista-tools/mev.git` | BuildEase — 34 Odoo 19 modules, umbrella module `buildease`. Not vendored; `reference/buildease.md` is a distilled map | + +**Never install the substrate under the name `odoo-demo-architect`.** Skills resolve by directory name, so a same-named fork silently shadows upstream depending on install order, and two people build different demos from the same brief. + +### Editing rules that carry weight + +- **Reference substrate steps by name** (*Test heroes*, *Purge test residue*), never by number. Numbered references are how an upstream renumbering silently misroutes this skill with nothing to detect it. +- **The purge ordering** (transient wizard rows → statements → invoices → timesheets → tasks → projects → sale orders → take-offs → partner last) is ordered because Odoo blocks deletion otherwise. Do not reorder or summarise. The take-off-without-a-sale-order trap in particular is non-obvious and cost a debugging round. +- **Not installing `buildease_demo_data`** is the reason this overlay exists at all; the app-level dependencies that bundle used to drag in must still be routed from the pain table. +- `reference/buildease.md` drifts when mev changes. When updating it, keep the two things that make it useful: the pain→module table keyed on *the client's own words*, and the gotchas (missing `custom_product_*` deps, Odoo 19 only, settings that default off). + +## Writing style for this repo + +Match the existing prose: imperative, second person, no hedging, tables for anything enumerable. Rules state what to do *and* the failure that motivates them ("a fabricated quote read back to the client in the demo is not"). Avoid generic agent boilerplate — everything here should be specific to BuildEase or it belongs in the substrate. + +## Related + +The parent workspace `../CLAUDE.md` (Callista BV multi-customer workspace) covers Odoo module conventions — naming, manifests, version numbering — and applies when editing the mev modules themselves, not this repo. diff --git a/SKILL.md b/SKILL.md index 43f1471..113ada8 100644 --- a/SKILL.md +++ b/SKILL.md @@ -1,208 +1,119 @@ --- 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". +description: BuildEase (callista-tools/mev) construction overlay for the callista-odoo-demo skill. Routes the client's pains onto the 34 BuildEase Odoo 19 modules before any custom work is considered, replaces the generic teardown with the take-off → progress-statement chain, and keeps the per-client dataset instead of the old buildease_demo_data bundle. Use for "BuildEase demo", "QTO demo", "quantity take-off demo", "construction Odoo demo", "vorderingsstaat demo", or a follow-up after one. --- # BuildEase Demo -Three phases. `odoo-demo-architect` does the middle one; this skill owns the ends. +A **vertical overlay** on `callista-odoo-demo`. That skill owns the pipeline — discovery +brief, build, test, purge, sales docs, follow-through. This one supplies the five things +that are specific to construction, and nothing else. -**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. +**Requires** `callista-odoo-demo` installed at `~/.claude/skills/callista-odoo-demo/` +(Callista's fork of Smetools/odoo-demo-architect). If it is missing, say so and stop — +do not reimplement its XML-RPC connector, data builder, or pipeline here. + +> Do **not** substitute an `odoo-demo-architect` install for it. That is upstream, without +> Phase A's source-agnostic discovery, without Phase C, and without the extension points +> this file plugs into. + +**Run `callista-odoo-demo` and apply the overlays below at the named steps.** Everything +not listed here is that skill's job — follow it as written. --- -## Phase A — Discovery brief (no Knowcap) +## Overlay 1 — Module routing -Goal: produce `discovery_brief.md` in exactly the shape odoo-demo-architect's step 1 -would have emitted, from whatever the user actually has. +*Applies at:* **Install modules**, and Phase A's `## Phase 1 scope`. -**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). +Read `reference/buildease.md` and route the client's pains onto BuildEase modules using +its pain → module table. Match on **the client's own words** — the table is keyed on what +they actually say ("we measure in Excel then re-type it into the quote"), not on module +names they will never utter. -### Intake — infer first, ask only the gaps +Install the umbrella module `buildease` plus the routed set. `buildease` depends on +nothing and installs the set. -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. +## Overlay 2 — Solution precedence -| 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 | +*Applies at:* **Research native-vs-custom**. -Anything still missing after that batch: write it into the brief as `(unknown)` and -carry on. One unknown does not block building the demo. +The precedence becomes **BuildEase → native Odoo 19 → custom**, in that order. Most +construction pains are already solved in mev; custom work is the last resort, and native +Odoo is the middle tier, not the first question. -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. +Odoo 19 only — every mev manifest is `19.0.x`. Do not attempt this against 17 or 18. -**Write `discovery_brief.md` with these six sections and no others:** +## Overlay 3 — Demo data policy -```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. +*Applies at:* **Load demo data**. -## Top pains -3–5 items. Direct client quotes where you have them. Mark anything you inferred as (inferred). +**Do not install `buildease_demo_data` or `buildease_demo_data_sale_progress`.** They are +the previous generation of environment setup: one fixed Belgian construction dataset, the +same for every prospect, dragging in `l10n_be` and `accountant` whether or not the client +is Belgian. The per-client dataset generated from the discovery brief replaces them — the +client's own partners, articles, projects and orders, staged so each hero has a record to +fire on. -## Hero features -1–2. Each names the pain it kills and the decision-maker it lands on. +Install them only if the user explicitly asks for the generic sandbox. The app-level +dependencies that bundle used to drag in (`sale_management`, `project`, `purchase_stock`, +`sale_timesheet`, `industry_fsm`, `accountant`, `uom`) still need installing — route them +from the pain table, not from the demo bundle. -## Phase 1 scope -Odoo apps + BuildEase modules, from reference/buildease.md. +## Overlay 4 — Purge chain -## 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: +*Applies at:* **Purge test residue**, replacing the generic chain. ``` 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: +The generic traps still apply. These are the BuildEase-specific ones, each 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. +- Leftover `add.dynamic.article.template.line` rows pin take-offs. Clear them first. +- Statements cancel newest-first only. -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. +## Overlay 5 — Follow-through framing -### Sanity-check the staged numbers before calling it done +*Applies at:* **Phase C**. -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. +Where an objection is already covered by BuildEase, name the **module and the screen** on +the objection sheet — "that's `sale_progress_revision_formula`, on the statement's Revision +tab" lands better than "yes, we support that". Where mev does not cover it, say so and give +the workaround or the build estimate. + +Check the scoped quote against `reference/buildease.md`'s gotchas before pricing: +`custom_product_sale`, `custom_product_bom` and `bom_on_sale_order_line` are **not in the +mev repo**, so anything under `buildease_custom_product*` is not a "just install it" line. --- -## Phase C — Follow-through +## BuildEase-specific checks -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. - ---- +- After installing, **walk Settings once**. `res.config.settings` and `res.company` are + extended by 8 modules each and several BuildEase behaviours default to off. +- At the staged-numbers sanity check: **booked hours well under ordered hours**. Over 100% + makes the progress statement look wrong on screen even when every assertion passed. +- The spine of every BuildEase demo is QTO → sale order → project → progress statement → + invoice. If that chain breaks mid-demo you lose the deal, so it is the chain **Test + heroes** must exercise end to end. +- `quantity.take.off` inherits `mail.thread` + `mail.activity.mixin` — chatter and + activities work for free. Cheap demo beats. ## 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. +- Never invent a pain quote. `(inferred)` is fine; a fabricated quote read back to the + client in the demo is not. +- If something you need is not one of the five overlays above, that is a gap in + `callista-odoo-demo` — fix it there, so the next vertical gets it free. Do not work + around it here. + +## Files + +- `reference/buildease.md` — the module map, the pain → module routing table, and the mev + gotchas. Read it at Phase A. diff --git a/reference/buildease.md b/reference/buildease.md index c6a298e..0d62cda 100644 --- a/reference/buildease.md +++ b/reference/buildease.md @@ -48,8 +48,8 @@ Match the client's own words on the left; install the right. **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`. +per client from the discovery brief and loaded through `callista-odoo-demo`'s +`scripts/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: