Skip to content

Releases: asao-vn/asao-odoo-tools

v0.17.1

Choose a tag to compare

@github-actions github-actions released this 18 Oct 06:34
  • Fixed, operation packs (found in a review of packs on 2026-10-18):

    • Crash. A WIZARD operation without its wizard crashed odoo-cli when the pack was read: on
      pack add, or on pack sync from a module that ships the mistake. It is now refused with a reason.
    • Reaching outside the company. A pack could open a wizard that reaches outside the company or grants
      access. Packs now refuse what odoo-cli leaves out on purpose:
      • e-mail and SMS composers, and mailings;
      • sending an invoice (account.move.send) and post;
      • portal access, and invitations.
    • Money rated too low. Every accounting and payment model is HIGH risk at least, matched by prefix.
      account.payment.register was MEDIUM.
  • Changed: at data level operate, resolve finds what is named and cannot count. mcp serve --data-access operate runs it strictly:

    • conditions on a name, a reference, a state or the partner, by =, !=, in or ilike;
    • no range on a date, an amount or an id;
    • at most 5 ids, with no count;
    • 30 calls a session.

    As 0.17.0 shipped it, an agent at operate counted 54 invoices by paging ids. Measured again with the
    strict build: every write that names its record is done (5 of 5), and no figure is read (0 of 6).

This release's rehearsal

Before the tag, the public workflows ran on this release's commit, f91a10f:

  • Conformance (run 39102583899):
    • 19.0: 1252 of 1301 re-agreed, 0 regressed;
    • 20.0: 1161 of 1187 re-agreed, 0 regressed;
    • K01 to K11 AGREE on both series.
  • Packs proof (run 39102587608):
    19 of 19 checks agree on Odoo 19.0. It covers packs, data levels, the secret page, and the pack fixes of
    this release.

The privacy-cost pilot measured strict resolve at operate: 5 of 5 writes that name their record, and 0 of
6 figures read.

This release's own conformance

The tag ran the conformance workflow again
(run 39104322319):

  • 19.0: 1253 of 1301 re-agreed, and 0 regressed;
  • 20.0: 1161 of 1187 re-agreed, and 0 regressed;
  • Controls and alerts: K01 to K11 AGREE on both series.

Its evidence, conformance-19.0.tar.gz and conformance-20.0.tar.gz, is attached below.

v0.17.0

Choose a tag to compare

@github-actions github-actions released this 17 Oct 15:18

1368 operations: 1301 verified on 19.0, and 1187 of the 1306 that 20.0 can run. The Python companion asao-erp 0.4.0 is released with it (pip install asao-erp).

  • New: bounds on an agent, and a stop switch (DEC-2026-0182).

    • agents stop --profile P refuses every call of every mcp serve on that profile, from its next
      call, with the reason you give. It also stops routines run and routines due. agents resume
      lifts it.
    • mcp serve --max-calls N --max-writes N bound a session.
    • --rate N caps the calls in a minute (60 by default), since each call takes one of Odoo's workers
      while it runs.
    • Every refusal is in the trace, and nothing runs.
  • New: --accept, a write judged at three levels (DEC-2026-0183).

    • ODOO_VALID: Odoo answered, the operation is verified, and its postcondition held.
    • INTENT_VERIFIED: every value asked for, read back, is what Odoo holds.
    • RESULT_ACCEPTED: the review checks over the weeks around the record find nothing that names it, for
      example an invoice made twice or a tax rate that is not the product's.
    • The result says the level reached, and why it stopped there.
  • New: resolve, find records without seeing them. It answers ids only, at most 20, from a filter on
    plain fields. A filter on personal data or free text is refused. It is offered at data level operate, so
    an agent that may not see the data can still find the customer's latest draft and act on it.

  • Settings: stock_text_confirmation (text the customer when a delivery is done, Odoo's paid SMS) can
    be switched off. While it is on, validating a delivery for a customer with a phone opens a blocking
    dialog. It was verified on 19.0 and 20.0, read through the CLI and through an independent oracle.

  • Fixed: a line could not be added to a quotation or an RFQ. --order, the order a line belongs to,
    was refused as a read's sort order. An agent in the privacy-cost experiment found it.

  • New: review checks as files (DEC-2026-0181). A check can be a file, odoo-cli.check/v1, run by one
    engine.

    • What a file holds: the read operation it needs, how records match (pairs or groups), how a
      finding reads, and its own cases, at least one to flag and one to leave alone.
    • Commands:
      • review test-check checks a file and runs its cases;
      • review add-check and remove-check keep a team's own checks per profile. These run beside the
        built-in ones, and their cases run again each time they load.
    • Two built-in checks moved: O22 and O23 are now files. Both versions gave byte-identical findings
      on 786 random cases before the Go code was removed. Guide: docs/checks.md.
  • New: verdicts and precision.

    • Every finding has a stable key.
    • review verdict --finding KEY --real|--false-alarm keeps the person's judgement, which later runs show
      on the finding.
    • review precision gives each check's share of real findings, and lists the false alarms to turn into
      cases.
  • The review simulation runs every week, on a new seed: 12 months, with noise and the held-out set.

  • New: a trace of what agents did. Every tool call an agent makes through mcp serve is appended
    to a local journal of the profile it ran against, chained by hashes. An entry holds:

    • when, which agent host, and the command line you saw;
    • whether you confirmed it, its status and error code, and the record it wrote;
    • the data level the server ran at.

    It never holds what a read returned.

    • Commands: trace list shows the entries, and trace verify finds an entry that was removed or
      changed. Both are yours alone, never an agent's.
    • Turning it off: ODOO_CLI_TRACE=off.
    • Not traced: an agent that runs odoo-cli in a shell.
  • Review, measured on a bigger and messier business. The review-sim workflow can now run 12 months
    or more, with a real shop's everyday noise and three kinds of business (--profile trader|retail|service).

    • Four checks fixed: a year with that noise found four formulas that only held on a small, clean
      business: O25 (round claims), O19 (below cost), O21 (refund after payment) and O02 (an invoice twice).
      All four were fixed, and the invoice read gained invoice_origin, re-verified on 19.0 and 20.0.
    • The held-out set: 18 cases and 13 look-alikes written after the fixes (--fresh). On all three
      kinds of business, every case was found and no look-alike was flagged
      (run 38995070451).
  • The secret page's code moved to a package of its own (agentkit/secretpage), beside the trace
    (agentkit/trace). Neither knows Odoo.

Install

curl -fsSL https://raw.githubusercontent.com/asao-vn/asao-odoo-tools/main/scripts/install.sh | sh
pip install asao-erp      # the Python companion, for analysis

This release's rehearsal

Before the tag, the public conformance workflow ran on this release's commit, bcc7b9c
(run 39042150205).

  • 19.0: 1251 of 1301 verified operations re-agreed, and 0 regressed. Two were unstable:
    people.expense.submit and manufacturing.order.mark_done_confirm_consumption_with_backorder.
  • 20.0: 1161 of 1187 re-agreed, 0 regressed, and 12 new agreements. event.lead_rule.execute_rule
    was unstable.
  • Controls and alerts: K01 to K11 AGREE on both series.

The review's measurements, in the public review-sim workflow:

  • The held-out set, written after the last change to the checks: 19/19 cases caught and 13/13
    look-alikes left alone, on three kinds of business.
  • Real sales from UCI Online Retail II, with nothing planted in them: every planted case was still
    caught. O21 raised 4 alarms on 59 real returns from customers it had not seen, down from 36 alarms on
    79 returns.

This release's own conformance

The tag ran the conformance workflow again
(run 39044236011):

  • 19.0: 1253 of 1301 re-agreed, and 0 regressed. people.expense.submit was unstable, as before.
  • 20.0: 1161 of 1187 re-agreed, 0 regressed, and 12 new agreements. event.lead_rule.execute_rule
    was unstable, as before.
  • Controls and alerts: K01 to K11 AGREE on both series.

Its evidence, conformance-19.0.tar.gz and conformance-20.0.tar.gz, is attached below.

v0.16.0

Choose a tag to compare

@github-actions github-actions released this 17 Oct 00:37

1368 operations, unchanged: 1301 verified on 19.0, and 1187 of the 1306 that 20.0 can run.

  • New: operation packs (DEC-2026-0176). A custom module brings its own operations as a pack, a
    JSON file it ships as static/odoo-cli/pack.json that names its reads, writes, object buttons,
    wizards and reports. It holds data, never code.

    • Commands:
      • pack sync finds the packs of the installed custom modules and keeps them for the profile;
      • pack add keeps one from a file, for Studio or Odoo Online;
      • pack list, pack show and pack remove manage them;
      • pack generate writes a first pack for a module's author.
    • Checks against your Odoo before a pack is kept:
      • the module is installed;
      • its models and fields exist;
      • every method is an object button of the model's views;
      • every wizard is a wizard;
      • every report exists.
    • Never allowed: a pack never names users, rights, company settings, code, mail or a credential,
      never deletes, and never calls a private or ORM method.
    • Running them:
      • a pack's operations are commands and MCP tools of the profile, and need --allow-unverified;
      • an agent's write through a pack always asks the person, even under --confirm-writes=false;
      • risk floors: a button or a wizard is MEDIUM at least, and a write to a payment, a journal
        entry or a bank account is HIGH.
    • Documentation and proof: docs/packs.md is the guide. The packs workflow
      (conformance/packs/prove.sh) proves it on a demo module: on Odoo 19.0, 15 of 15 checks agree
      (run 38981143110). The
      checks cover generate, sync, the MCP access, the list, a create by customer name, an update,
      three buttons, a wizard, Odoo's own refusal, a PDF, and a method the pack does not name.
  • New: how much of the data an agent sees (DEC-2026-0178). mcp serve --data-access sets the
    level, and odoo-cli enforces it in every result and error it gives the agent:

    • act, the default: personal data, free text and files are withheld from every record;
    • operate: no read tool but discovery, and status, ids, verdicts and error codes only;
    • full: what 0.15 gave.

    profile set --agent-data-access records a profile's level, and a server can lower it, never
    raise it. mcp tools --data-access shows what each level offers. This changes the default:
    pass --data-access full for what 0.15 gave. Proven live by a scripted MCP host on the pack lab
    (run 38981985013):

    • at act, a customer's email, phone and comment were withheld, and the name was kept;
    • at operate, there was no read tool, and a create gave the agent its id only.
  • New: a secret is typed on a one-time local page, never in the chat (DEC-2026-0179).

    • The commands: credential set --browser stores an Odoo password or API key. secret env --file .env --name KEY --browser writes one line of a .env file, kept at mode 600.
    • The page: it is served on 127.0.0.1 under a random path, takes one submission, lasts 5
      minutes, and loads nothing from elsewhere. It refuses a form without its own token, or from
      another origin.
    • The agent: it may call both as CONFIRM tools and gets only "stored". The value never passes
      through it.
    • Settings: ODOO_CLI_SECRET_INPUT=off refuses the page, and ODOO_CLI_THEME=plain drops its
      colours. credential set now takes --password-stdin or --browser, exactly one.
    • Proven live in the packs workflow
      (run 38983358156, 19 of 19):
      an agent asked over MCP, and a second process stood in for the person and typed on the page.
      The .env file got its line at mode 600, and the agent got stored without the value.
  • MCP: pack list and pack show are read tools: 619 by default, and 1390 with --allow-writes
    (771 CONFIRM). At --data-access operate, 10 read tools remain, all discovery.
    mcp tools takes --profile, so its listing has that profile's packs, as serve's does.

  • JSON-2: get_views goes by name, so its views are never taken for record ids.

  • explore and packs share one list of the models and fields that hold credentials.

  • Conformance: the write runner gives an attendance the date of its check-in where the employee works,
    so a run near midnight in that time zone agrees. The 0.15.0 release run did not.

Install

curl -fsSL https://raw.githubusercontent.com/asao-vn/asao-odoo-tools/main/scripts/install.sh | sh

This release's rehearsal

Before the tag, the public conformance workflow ran on this release's commit, 0818168
(run 38984549949).

  • 19.0: 1252 of 1301 verified operations re-agreed, and 0 regressed. Two were unstable:
    people.expense.submit, as since 0.11, and manufacturing.workorder.start, whose twins differ in
    a date and time field.
  • 20.0: 1160 of 1187 re-agreed, 0 regressed, and 12 new agreements. Two were unstable:
    event.lead_rule.execute_rule, as before, and manufacturing.workorder.start.
  • Controls and alerts: K01 to K11 AGREE on both series.
  • The new features were proven in the packs workflow on Odoo 19.0, 19 of 19 checks
    (run 38983358156), as each
    section above says.

This release's own conformance

The tag ran the conformance workflow again
(run 38987004391):

  • 19.0: 1251 of 1301 re-agreed, and 0 regressed. people.expense.submit was unstable, as before.
  • 20.0: 1161 of 1187 re-agreed, 0 regressed, and 12 new agreements. event.lead_rule.execute_rule
    was unstable, as before.
  • Controls and alerts: K01 to K11 AGREE on both series.

Its evidence, conformance-19.0.tar.gz and conformance-20.0.tar.gz, is attached below.

v0.15.0

Choose a tag to compare

@github-actions github-actions released this 16 Oct 21:49

1368 operations, unchanged: 1301 verified on 19.0, and 1187 of the 1306 that 20.0 can run.

  • New: odoo-cli upgrade check --to 20.0. Before an upgrade, it says which customizations people
    made in the database will stop working on 20.0, and why.

    • What it reads: saved filters, automation rules, server actions, custom fields, email templates,
      views, record rules, access rights, export templates, default values and window actions.
    • How it checks them: it resolves every model and field they reference against a map made from
      the 19.0 and 20.0 conformance labs. A renamed field gets its probable new name. A module the map
      does not cover, such as an Enterprise or a third-party one, gets UNKNOWN.
    • What it never does: it reads only, and never prints the code or the templates it reads.
    • Options: --markdown-file writes a report in Vietnamese. upgrade maps lists the pairs this
      build can check.
  • What 20.0 changes for customizations. Record rules and access rights move into one new model,
    ir.access, so every custom one has to be written again. 44 models and 618 fields are gone, and 56
    selection fields lose values.

  • Measured on real Odoo, in the open. The new upgrade-check workflow
    (run 38968869331) used 23
    customizations, written after the check was finished:

    • it made them on a throwaway 19.0 and ran the check there;
    • it made them again on a throwaway 20.0, which refused 13; the check had flagged all 13;
    • among the 10 that still work there was no false alarm, and one CHECK: a filter on a value 20.0
      dropped;
    • it found nothing on the 56 customizations the lab makes itself.

    The people who wrote the set knew what 20.0 changes. So the run shows that the map holds on a real
    20.0, not how much of a real database the check can read.

  • MCP: upgrade_check and upgrade_maps are read tools: 617 by default, 1386 with --allow-writes.

  • An Odoo on a private address can be allowed by name. ASAO_PRIVATE_PROVIDER_ENDPOINTS takes exact
    host:port pairs, such as 192.168.1.10:8069. Only those skip the refusal of private addresses.
    ASAO_ALLOW_PRIVATE_PROVIDER_ENDPOINTS=true still allows them all.

Install

curl -fsSL https://raw.githubusercontent.com/asao-vn/asao-odoo-tools/main/scripts/install.sh | sh

This release's rehearsal

Before the tag, the public conformance workflow ran on main at f6a4460
(run 38969032952). The tagged
commit, 652934b, changes only the wording of the Vietnamese report (with its test), the README and the
CHANGELOG.

  • 19.0: 1251 of 1301 verified operations re-agreed, and 0 regressed. Two were unstable:
    • people.expense.submit, the flake seen since 0.11;
    • manufacturing.order.mark_done_confirm_consumption_with_backorder. Its twins differed once, only in
      date_start, a date and time field, and the recheck agreed.
  • 20.0: 1161 of 1187 re-agreed, 0 regressed, and 12 new agreements. One was unstable:
    event.lead_rule.execute_rule, the flake seen in 0.13.1.
  • Controls and alerts: K01 to K11 AGREE on both series.

This release's own conformance

The release's own conformance
(run 38971763212) failed on one
operation, on both series: workforce.attendance_log.create disagreed on date. The cause was the
conformance runner, not odoo-cli:

  • Odoo computes an attendance's date from its check-in, in the employee's time zone (Europe/Brussels
    in the demo data). The runner wrote today's date by its own UTC clock.
  • That write pass ran at 22:03 to 22:10 UTC, just after midnight in Brussels, so Odoo stored the next
    day. The rehearsal had written at 21:33 UTC and agreed.
  • Nothing else regressed in that run. On 19.0, 1253 of 1301 re-agreed; on 20.0, 1160 of 1187. K01 to
    K11 AGREE.

The fix. The runner now writes the date in the employee's time zone, by each series' own rule
(public cb94469 and 82da99c). The first fix read a calendar time zone, which Odoo 20 no longer has.

The re-run. Conformance then ran again on main, with the same odoo-cli code and the fixed runner
(run 38977694022). Its writes
again came after midnight in Brussels.

  • 19.0: 1254 of 1301 re-agreed, and 0 regressed. people.expense.submit was unstable, as
    before.
  • 20.0: 1160 of 1187 re-agreed, 0 regressed, and 12 new agreements. Two were unstable:
    • event.lead_rule.execute_rule, as before;
    • manufacturing.workorder.start, whose twins differed once, only in production_date, a date and
      time field. The recheck agreed.
  • Controls and the attendance: workforce.attendance_log.create agreed on both series, and K01
    to K11 AGREE on both.

Its evidence, conformance-19.0.tar.gz and conformance-20.0.tar.gz, is attached below.

v0.14.0

Choose a tag to compare

@github-actions github-actions released this 16 Oct 10:39

1368 operations, unchanged: 1301 verified on 19.0, and 1187 of the 1306 that 20.0 can run.

  • Every write an agent asks for needs your confirmation. mcp serve --allow-writes now asks you in
    the agent host before every write, not only before the 61 high-risk, destructive and bank-account
    operations. Almost any text an agent reads in Odoo can be written outside the company (a website
    form, an email that became a lead or a task, a sign-up), and such text can carry instructions. A host
    that cannot ask gets a refusal with the odoo-cli ... command line for you to run yourself.
    mcp tools --allow-writes shows 769 CONFIRM.
  • --confirm-writes=false gives back what 0.13 did, for an agent that reads no such text: the low-
    and medium-risk writes run without asking, and the 61 still ask. --confirm-writes, added in 0.13.1,
    is now the default and is still accepted.
  • Fixed: explore refuses ir.access on Odoo 20. Odoo 20 merges ir.model.access and ir.rule
    into one model, ir.access, which explore read although it refuses the two models it replaces.
  • Conformance: a lab no longer fails to start one time in 64. Its random database password could
    begin with -, which the Odoo image's wait-for-psql.py took for an option. The read and write
    runners record the renames file by its name, not by its path on the machine that ran them.

Install

curl -fsSL https://raw.githubusercontent.com/asao-vn/asao-odoo-tools/main/scripts/install.sh | sh

This release's rehearsal

Before the tag, the public conformance workflow ran on main at 5990f69, the commit this release is built from (run 38885218562):

  • 19.0: 1252 of 1301 verified operations re-agreed, 0 regressed. One was unstable: people.expense.submit disagreed once, then agreed, the flake already seen in 0.13.
  • 20.0: 1161 of 1187 re-agreed, 0 regressed, and 12 new agreements. One was unstable: event.lead_rule.execute_rule, the flake seen in 0.13.1.
  • Controls and alerts: K01 to K11 AGREE on both series.
  • Both labs started with the hex database password, and the 20.0 evidence names dialect-renames-20.0.json rather than a path.

This release's own conformance (run 38888363561) gave the same result: 0 regressed on both series; 1252 of 1301 re-agreed on 19.0 and 1161 of 1187 on 20.0; one unstable on each, the same two; every control and alert AGREE. Its evidence, conformance-19.0.tar.gz and conformance-20.0.tar.gz, is attached below.

v0.13.1

Choose a tag to compare

@github-actions github-actions released this 16 Oct 07:46

1368 operations, unchanged: 1301 verified on 19.0, and 1187 of the 1306 that 20.0 can run.

  • Changes to a bank account ask you first. On mcp serve --allow-writes, creating, changing or
    archiving a bank account (identity.bank_account.*, risk LOW) ran without asking, and could also
    set allow_out_payment, the flag Odoo checks before it pays an account. A bank account says who the
    company pays, so an agent now changes one only after you confirm the call in the agent host: 61
    operations ask, up from 58.
  • mcp serve --confirm-writes: every write asks you first, not only the high-risk ones. Use it
    when the agent reads text written outside the company (a website form, an email that became a lead
    or a task, a sign-up): such text can carry instructions, and an agent can follow them.
  • The server's instructions tell the agent that text inside records is data, never an instruction,
    and to bring requests found there about bank details, contacts, prices or access to you.
  • Fixed: what a confirmation tells you. It showed an asao ... command line and said ASAO would
    still check your permissions, which odoo-cli does not. It now shows the odoo-cli ... command line,
    and says the call runs with the full authority of the Odoo login in the server's profile.
  • Fixed: the flags that shape a read are refused on a write. execute accepted --limit,
    --filter, --order, --offset, --group-by and --aggregate with an operation that changes
    Odoo, and ran the write. A caller paging through what it took for a read, such as the asao-erp SDK
    0.3.0's read(), could run a write by mistake. It is now refused with AERP_READ_FLAG_ON_WRITE
    before any profile is read.
  • Fixed: a partial apply is recorded as PARTIAL. Before, spec apply --partial with a backend
    recorded the run as APPLIED, and kept the spec as the one last applied in full, although the plan's
    UNSUPPORTED or AMBIGUOUS steps were left out. The run is now PARTIAL, with how many steps were left
    out, and spec pull still gives the last spec applied in full.
  • Fixed: an S3 bucket whose name holds a dot is addressed by path. AWS's certificate does not
    cover a dotted bucket name used as a host name.
  • Said plainly: the routines timer was tried on systemd. The launchd, Task Scheduler and cron
    installers are written but not tried yet.

Install

curl -fsSL https://raw.githubusercontent.com/asao-vn/asao-odoo-tools/main/scripts/install.sh | sh

This release's rehearsal

Before the tag, the public conformance workflow ran on main at c937594 (run 38865552037), one commit before the MCP change, which does not touch how an operation runs on Odoo:

  • 19.0: 1252 of 1301 verified operations re-agreed, 0 regressed. One was unstable: people.expense.submit disagreed once, then agreed, the flake already seen in 0.13.0.
  • 20.0: 1161 of 1187 re-agreed, 0 regressed, and 12 new agreements. event.lead_rule.execute_rule and people.expense.approve disagreed once and were sampled again: 0 regressed, one unstable.
  • Controls and alerts: AGREE on both series.

This release's own conformance (run 38869034604) gave the same result: 0 regressed on both series; 1251 of 1301 re-agreed on 19.0 and 1161 of 1187 on 20.0; one unstable on each, people.expense.submit on 19.0 and event.lead_rule.execute_rule on 20.0, the flakes seen in 0.13.0; every control and alert AGREE. Its evidence, conformance-19.0.tar.gz and conformance-20.0.tar.gz, is attached below.

v0.13.0

Choose a tag to compare

@github-actions github-actions released this 16 Oct 06:04

1368 operations, unchanged: 1301 verified on 19.0, and 1187 of the 1306 that 20.0 can run.

  • odoo-cli routines: a business's daily, weekly and monthly checks, with no Python. The routines
    the asao-erp SDK introduced now run in the command line itself:

    • templates: ten starter routines (sales yesterday, overdue receivables, money in and out, late
      transfers, late tasks, last week's and last month's books review, stalled opportunities, monthly
      revenue, recurring tasks);
    • init, list, run, due and status;
    • install: a timer on systemd, launchd, Task Scheduler or cron.

    Each run is kept in a folder: what Odoo answered, a computed summary, and the reading of the agent
    you chose (Claude Code, Codex, Gemini CLI, agy, any command, or none). The same file format as the
    SDK (TOML, and now YAML or JSON).

    What changed on the way:

    • a read or group step can only run a read operation;
    • a routine changes Odoo only through steps that say so, never by installing a module;
    • a run that reached Odoo at no step leaves the slot open for the next timer tick;
    • one due runs at a time.

    An agent over MCP may list the starter routines and read a file's routines and their latest runs
    (three read tools, from the file the server was started with); running routines, writing a file
    and installing a timer stay with you.

  • A team on one Odoo: odoo-cli spec --backend. spec plan and apply can share a backend:

    • where: an S3 bucket (or Cloudflare R2, MinIO, Backblaze B2), signed by odoo-cli itself with no
      SDK, or a shared folder;
    • the lock: one apply at a time, and spec unlock for an apply that died;
    • the plans: each one is saved under its hash with the spec as written, so a colleague can review
      it (spec pull --plan);
    • the record: every apply is recorded as REFUSED, FAILED or APPLIED, with plan and report
      (spec runs);
    • the spec last applied in full, which anyone can pull back (spec pull);
    • spec state shows it all.

    With a backend, apply needs the reviewed plan's hash (or --auto-approve). A backend belongs to
    one Odoo, and another one is refused before it is read. There is no state file: every plan reads
    Odoo itself. "Who" is a label (user and host); the bucket's permissions decide who writes, and
    odoo-cli trust says so. For approval by a colleague whose identity is checked, see
    docs/team-spec.md.

  • Proof:

    • Routines on an Odoo 19 lab: all ten templates ran; the recurring-task routine created its
      tasks once and found them on the next run; a timer ran the due routines.
    • The backend against MinIO: the signature matches AWS's published example; plan, review, apply
      and pull round-trip the spec byte for byte; five concurrent applies gave one APPLIED and four
      SPEC_LOCKED.

Install

curl -fsSL https://raw.githubusercontent.com/asao-vn/asao-odoo-tools/main/scripts/install.sh | sh

This release's rehearsal

Before the tag, the public conformance workflow ran on main (run 38856361228) and was green on both series:

  • 19.0: 1252 of 1301 verified operations re-agreed, 0 regressed. One was unstable: people.expense.submit disagreed once, then agreed, a flake already seen before 0.11.0.
  • 20.0: 1161 of 1187 re-agreed, 0 regressed, and 12 new agreements. One was unstable: event.lead_rule.execute_rule disagreed once, then agreed with no change, because of the order of its twins.
  • Controls K01-K08 and alerts K09-K11: AGREE on both series.

This release's own conformance (run 38858980412) gave the same result: 0 regressed on both series, the same two flakes, and every control and alert AGREE. Its evidence, conformance-19.0.tar.gz and conformance-20.0.tar.gz, is attached below.

v0.12.0

Choose a tag to compare

@github-actions github-actions released this 15 Oct 21:35

1368 operations: 1301 verified on 19.0, and 1187 of the 1306 that 20.0 can run.

  • Alerts: K09-K11 in odoo-cli controls. Notify-only Odoo automation rules (module
    base_automation, which you install) whose only action schedules an activity for the person you name:

    • K09: a bank account is added, or its number, holder or trusted flag changes;
    • K10: a posted entry is reset to draft (posting it again adds nothing);
    • K11: a partner that has invoices changes its tax number or name (one that never traded is not
      reported).

    Plan and apply them like any control: --param K09.user="Ngọc Lan" (or the user's id) and
    K09.lang=vi|en for the activity's summary. A plan of an alert already on is NO_CHANGE. There is no
    alert for a changed lock date: Odoo cannot schedule an activity on a company, and the change history
    shows it.

  • Eleven operations under them, all verified:

    • rules (structure.alert_rule.list|describe|create|update) held to names that start with odoo-cli: ;
    • their actions (structure.alert_action.*), whose type is forced to an activity;
    • three reads that resolve what a rule names (structure.registry_model.list,
      structure.registry_field.list, structure.activity_type.list).

    A rule or action you made is out of their reach. An action that runs code, writes records, sends a
    message or calls a webhook is refused before Odoo is reached; so is an action without its rule, and a
    rule or action on a model that cannot carry activities (never base, which every model inherits).
    Proven by
    conformance/odoo-alerts-conformance.py, now part of the lab run; the labs install base_automation.

  • Fixed: an archived record of an operation's own subset can be updated. The check that a target
    belongs to an operation's subset ran with Odoo's default active test, so an archived record (an alert
    rule switched off) could never be brought back. It now sees archived records; the subset still decides.

  • Fixed: a plan compares lists of ids as sets. A list of two ids was read as a many2one's
    [id, name], so a record with a two-record many2many was planned as a change on every run.

  • Conformance: the action runner leaves a payment transaction's state-change stamp out of the twin
    comparison. It is a clock stamp to the second, and it failed 0.11.0's release run on 19.0.

    • The lab seeder no longer makes automation rules or server actions. Its generic rules on the model
      base made every model run them inside its own create, and creating a bank account with K09 on then
      failed in the rehearsal before this release.

This release's rehearsal

Before this tag, the full conformance ran on main twice. The first run caught a real failure, which
was fixed before the tag: with K09 on, creating a bank account was refused, caused by automation rules
the lab seeder had made on the model base (see Conformance above). The second run was green on 19.0
and 20.0. Every control and alert agreed, with 0 regressed operations.

Install: curl -fsSL https://raw.githubusercontent.com/asao-vn/asao-odoo-tools/main/scripts/install.sh | sh

v0.11.0

Choose a tag to compare

@github-actions github-actions released this 15 Oct 17:20

1357 operations: 1290 verified on 19.0, and 1176 of the 1295 that 20.0 can run.

  • odoo-cli controls: Odoo's own switches that stop what the review finds. Eight controls:
    purchase approval from an amount, locked purchase and sales orders, lock dates, the restrictive
    audit trail, hashed entries, customer credit limits and two-step sign-in for employees. Each says
    what Odoo does once it is on (read in Odoo's source), where Odoo enforces it (server, web client
    only, or a warning) and whether it can be undone.

    • controls status reads them; controls plan and controls apply --plan-hash turn the reversible
      ones on through the spec engine and the catalog's verified operations.
    • It never moves a lock date back, never sets the hard lock date, never hashes a journal (Odoo never
      lets that be undone) and never weakens a stronger setting already on.
    • Odoo Community has no screen for lock dates: odoo-cli sets them.
    • Agents may list, read and plan; applying stays with the person. review checks and the markdown
      report name the control that would have prevented a finding.
    • Proven on 19.0 and 20.0 by conformance/odoo-controls-conformance.py: each control turned on
      through the CLI, then what Odoo does exercised through an independent oracle (an order over the
      amount waits for approval, an entry of a locked period cannot be reset to draft, a posted bill
      cannot be deleted, an employee's password is refused over RPC), then everything restored.
    • Two things the run found in Odoo itself are now in the controls' text. A document dated in a
      locked period is posted with its accounting date moved after the lock, not refused. Once two-step
      sign-in is required of employees, their passwords no longer work over RPC.
  • Saving the Settings page is verified. structure.settings.update had no runner: it has no
    record and no button. conformance/odoo-settings-conformance.py sets every setting through the
    CLI, reads it back as the page opens it, and restores it. Verified on 19.0 and 20.0; the two
    settings 20.0 removed are left out of the read and refused on write.

    • New settings: the purchase approval amount, the restrictive audit trail, the customer credit
      limit and its default.
    • The timesheet reminders are gone: Community declares them but keeps neither.
    • Company reads and writes take the four soft lock dates. Reads also show the hard lock date and a
      journal's hash switch, which the catalog never writes.
    • The labs install hr_timesheet, whose settings the page offers, and run both new workflows.
  • Agents can report a fault in odoo-cli, and you decide whether it is filed. odoo-cli report draft builds a scrubbed report on your machine and sends nothing; you file it through a prefilled
    GitHub link. Internal errors and the MCP server's instructions point agents at it.

  • Six more review checks, 20 in all. Each was planted, with a look-alike it must leave alone, in the
    simulated business the review is proven on:

    • O02 a customer invoiced twice for one sale (the same lines are XEM_NGAY);
    • O07 a payment cut into pieces under the approval limit: parts of one bill, or no bill at all;
    • O26 documents dated back into a month that had ended: customer invoices, credit notes and manual
      journal entries, with a closing allowance;
    • O27 revenue booked in the last days of a month and credited early in the next;
    • O28 and O29, Vietnam: purchases of 5 million đồng or more paid in cash, alone or as several bills of
      one seller on one day, lose their input VAT deduction (Nghị định 181/2025/NĐ-CP, Điều 26, read in the
      Official Gazette).

    A check whose read does not return a field it needs is reported as not run, with the reason, never as
    clean.

  • The change history, read. structure.field_change.list|describe (old and new values) and
    structure.change_note.list|describe (who changed which record, when), held to the fields a review
    needs: payee bank accounts, partners' tax numbers, document states and dates, lock dates, prices.
    Odoo shows them to administrators only. On 20.0 they need the mail_tracking module (Discuss
    Tracking), which 20.0 split out of mail; the check before a call says so.

  • Payments and journal entries say more. finance.payment.list returns the bank account paid into, the
    bills and invoices a payment settles, and who made it when; finance.journal_entry.list|describe, who made
    an entry when and whether a payment or a bank statement line made it. All verified again on 19.0 and 20.0.

  • conformance/odoo-read-conformance.py --only runs a few reads; odoo-conformance-lab.sh --setup-only builds
    a lab and keeps it, without a pass.

  • Recurring tasks. work.task.create and work.task.update take recurring, repeat_every,
    repeat_unit (day, week, month, year), repeat_type (forever, until) and repeat_until, with
    due_on, priority (low, medium, high, urgent), tags (by name or id) and description;
    work.task.list and work.task.describe return them. Odoo makes the next occurrence when the
    current one is closed (done or cancelled), not on a calendar date.

  • Verified as a workflow, on 19.0 and 20.0. A new conformance pass
    (conformance/odoo-task-recurrence-conformance.py, part of the weekly lab run) creates a recurring
    task with every new field, reads it back through an independent JSON-RPC oracle and through the
    CLI, changes its recurrence, closes it, and checks that Odoo opened exactly one next occurrence a
    month later.

This release's conformance

The release's own run on 19.0 flagged finance.payment_transaction.capture. Its two twins both went
from authorized to done and differed only in last_state_change, a timestamp Odoo stamps to the
second, so a twin captured in the second it was authorized looked unchanged. The runner now leaves
that stamp out, as it already did for opportunities and orders (commit b1bbcdd); odoo-cli's code is
this release's own. The conformance-19.0 evidence attached here is from the re-run on that commit
(0 regressed, 1241 of 1290 agreed again, people.expense.submit unstable); conformance-20.0 is
from the release run. Both include the controls workflow: K01 to K08 agreed.

Install: curl -fsSL https://raw.githubusercontent.com/asao-vn/asao-odoo-tools/main/scripts/install.sh | sh

v0.10.0

Choose a tag to compare

@github-actions github-actions released this 14 Oct 17:24

Install: curl -fsSL https://raw.githubusercontent.com/asao-vn/asao-odoo-tools/main/scripts/install.sh | sh