verify_code
Skill0 starsChanged 6 months agoMITView on GitHub
ACTIVATE before finalizing ANY Python code in an Odoo 19 module, especially after writing models, tests, or manifest. Audits for: (1) view_type=='tree' without 'list' in _get_view methods; (2) f-string or %-format in cr.execute (SQL injection); (3) chart_template_ref in setUpClass (removed Odoo 19); (4) manifest version not starting with '19.0.'; (5) uom_po_id field usage (removed Odoo 19); (6) currency_data['currency'] in tests (removed — use company_data['currency']); (7) detailed_type field usage (removed Odoo 19); (8) domain pipe count errors (N conditions need N-1 pipes for OR); (9) post-correction anti-pattern (create then write); (10) i18n PO files missing #: reference lines (only #. comments = install error in production — every msgid entry MUST have a #: model: or #: code: line). MARK AUDIT FAILED on any violation. Do NOT auto-fix complex issues — report file + line. Only auto-fix trivially obvious single-line changes.
- Reads credentials
In this repository7 other files it gives its agents.
- create_agent_ruleSkill
- create_deploy_specSkill
- create_repo_readmeSkill
- create_skillSkill
- discover_awac_in_fresh_workspaceSkill
- manage_project_stateSkill
- use_wsp_cliSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
17 rules. About 0 are common, 2 are distinctive, and 15 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
15
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 21
Run this skill to strictly audit the Python codebase (*.py) for compliance with project standards and Odoo version rules.
- Very specific: line 26
Scan: Search for view_type == 'tree' or view_type in (..., 'tree', ...) in _get_view methods and tests.
- Very specific: line 27
Audit Failure: If code checks ONLY for 'tree' without also accounting for 'list'.
- Very specific: line 28
Fix: Update conditions to view_type in ('tree', 'list').
- Very specific: line 33
Audit Failure: Use of f-strings or % formatting within the query string (SQL Injection risk).
- Very specific: line 34
Fix: Use parameterized queries: cr.execute("...
- Very specific: line 58
Fix: Remove the argument: super().setUpClass() with no kwargs.
- Very specific: line 60
Fix: Remove uom_po_id from product.product / product.template creation dicts.
- Very specific: line 62
Fix: Use self.company_data['currency'] instead.
- Very specific: line 66
Audit Failure (Mixin Missing): If _tags_invisible_per_country is used, the model MUST inherit l10n.country.filter.mixin.
- Very specific: line 68
Fix: Use the Mixin strategy documented in core_architecture.md.
- Very specific: line 80
Fix: Use type='consu' with is_storable=True for Storable Products.
- Very specific: line 112
Correct: Use #, python-format ONLY when the msgid contains at least one Python format placeholder.
- Very specific: line 212
Test uses self.assertLogs(...) to verify the log message explicitly — in that case muting would break the assertion.
- Very specific: line 222
Use grep_search to find instances of violations.
- Distinctive: line 223
If violations are found, MARK THE AUDIT AS FAILED until resolved.
- Distinctive: line 224
Do not auto-fix unless completely trivial.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Verify Code (Static Analysis)
Run this skill to strictly audit the Python codebase (*.py) for compliance with project standards and Odoo version rules.
1. Odoo 19 Compatibility Checks
- View Types:
- Rule:
treeview type is deprecated in favor oflistfor list views, buttreeis still used for hierarchy views. - Scan: Search for
view_type == 'tree'orview_type in (..., 'tree', ...)in_get_viewmethods and tests. - Audit Failure: If code checks ONLY for
'tree'without also accounting for'list'. - Fix: Update conditions to
view_type in ('tree', 'list').
- Rule:
2. ORM Usage & Safety
- Safe Execution:
- Scan:
cr.execute(...)calls. - Audit Failure: Use of f-strings or
%formatting within the query string (SQL Injection risk). - Fix: Use parameterized queries:
cr.execute("... WHERE id = %s", (id,)).
- Scan:
- Domain Validity:
- Scan:
search(...)domains. - Audit Failure: Incorrect number of
|operators for the number of conditions. - Fix: N conditions joined by OR need N-1 pipes.
- Scan:
3. Deployment & Environment
- Module Structure:
- Audit Failure: Missing
__manifest__.pyor__init__.pyin expected directories. - Audit Failure: Manifest missing
license,maintainer, oriconkeys. - Audit Failure: Duplicate keys in
__manifest__.py(e.g., twoiconentries). - Audit Failure:
post_init_hookusing[(5, 0, 0)](Delete All) on shared fields. - Audit Failure (XML Order): XML data files in
datalist inside__manifest__.pyordered incorrectly. Files defining parent menus or base views MUST precede files that reference them viaparent="..."or<xpath>. (e.g.,menu_views.xmlmust come before files adding submenus).
- Audit Failure: Missing
- Version & License (Odoo 19):
- Audit Failure: Manifest
versionnot starting with19.0.(must be19.0.X.X.X). - Audit Failure: Manifest
licenseset toOther proprietaryinstead ofOPL-1(required for Odoo 19 Apps Store).
- Audit Failure: Manifest
4. Test Code Quality
- Scan:
tests/*.pyfiles. - Audit Failure: Tests that rely on hardcoded IDs or deprecated methods.
- Audit Failure: Tests checking
invisibleattribute on List/Tree view columns (Must checkcolumn_invisiblefor Odoo 19). - Audit Failure:
setUpClassusingchart_template_refargument (REMOVED in Odoo 19). The base classAccountTestInvoicingCommonno longer accepts this parameter.- Fix: Remove the argument:
super().setUpClass()with no kwargs.
- Fix: Remove the argument:
- Audit Failure: Product creation using
uom_po_idfield (REMOVED in Odoo 19, unified intouom_id).- Fix: Remove
uom_po_idfromproduct.product/product.templatecreation dicts.
- Fix: Remove
- Audit Failure: Using
self.currency_data['currency'](REMOVED in Odoo 19 test base classes).- Fix: Use
self.company_data['currency']instead. If you need a specific currency like PEN, activate it explicitly.
- Fix: Use
5. Core Architecture (Multi-Company Caching)
- Scan:
models/*.pyfiles. - Audit Failure (Mixin Missing): If
_tags_invisible_per_countryis used, the model MUST inheritl10n.country.filter.mixin. - Audit Failure (Bad Practice): Manually patching
_get_view_cache_keyon ANY model (especiallybase) is strictly forbidden. - Fix: Use the Mixin strategy documented in
core_architecture.md.
6. Accounting & Financial Logic
- Scan:
models/*.pyinvolved in Account Moves/Payments. - Audit Failure: Loop updating
line_ids(Debit/Credit/Balance) withoutwith env.context(check_move_validity=False):. - Audit Failure: Currency conversion using logic
1.0 / rate(suggests misunderstanding of Indirect Rate). - Audit Failure (Anti-Pattern): "Post-Correction" logic. creating a record and immediately using
write()to fix values (e.g.move = create(...); move.line_ids.write(...)). Must use Pre-Calculation.
7. Product Compatibility
- Scan:
models/*.pyandtests/*.py. - Audit Failure: Usage of
detailed_typewithout strict version check (Removed in Odoo 19). - Audit Failure: Usage of
type='product'(Invalid value). - Fix: Use
type='consu'withis_storable=Truefor Storable Products.
8. User Groups Compatibility
- Scan:
models/*.pyandtests/*.py. - Audit Failure: Usage of
.groups_id(likely meantgroup_ids). - Fix: Correct to
group_idsforres.users.
9. i18n / PO File Format (Producción Risk)
- Scan:
i18n/*.pofiles in any module that has them. - Audit Failure: Any
msgidentry that has ONLY#.comment lines and NO#:reference line.#.lines are informational comments — Odoo IGNORES them for translation loading.#:lines are the actual indexed references that tell Odoo where to apply eachmsgstr.
- Correct pattern (every entry needs a
#:line):#. module: my_module #: model:ir.model.fields,field_description:my_module.field_model__fieldname msgid "My Label" msgstr "Mi Etiqueta" #:reference types by source:- Field
string=→model:ir.model.fields,field_description:mod.field_model__fname - Field
help=→model:ir.model.fields,help:mod.field_model__fname - Selection label →
model:ir.model.fields.selection,name:mod.selection__model__field__val ir.ui.menuname →model:ir.ui.menu,name:mod.xml_idir.actions.act_windowname/help →model:ir.actions.act_window,name:mod.xml_id- Python
_("...")→code:models/file.py:0 - XML
string=attribute →model_terms:ir.ui.view,arch_db:mod.view_xml_id
- Field
- Fix: Derive the correct
#:from the patterns above. NEVER ship a PO file where entries only have#.comment lines. - Audit Failure (Silent Translation Drop):
#, python-formatflag on an entry whosemsgidhas NO%sor%(x)splaceholders.- Odoo validates format strings at install time — mismatched flags cause the entire msgstr to be silently discarded. The message will appear in English in production even though the PO entry looks correct.
- Scan pattern: grep for
#, python-formatand verify the NEXTmsgidline contains%s,%(, or%d. If not → remove the flag. - Correct: Use
#, python-formatONLY when the msgid contains at least one Python format placeholder. - Wrong (causes silent drop):
#: code:models/project_task.py:34 #, python-format msgid "You must start the timer before adding products." msgstr "Debe iniciar el temporizador antes de agregar productos." - Correct (no flag when no placeholders):
#: code:models/project_task.py:34 msgid "You must start the timer before adding products." msgstr "Debe iniciar el temporizador antes de agregar productos."
- Audit Failure (Missing odoo-python Marker — CRITICAL):
code:PO entry missing#. odoo-pythoncomment.- Root cause:
translate.py:1855filters entries byPYTHON_TRANSLATION_COMMENT in row['comments']wherePYTHON_TRANSLATION_COMMENT = 'odoo-python'. Without it, translation is silently discarded. - Root cause 2:
translate.py:853re.match(r"(module[s]?): (\w+)", entry.comment)requires#. module: <name>in the same entry. Without it →AttributeError: 'NoneType'.groups()(server crash). - Both comment lines are REQUIRED for
code:entries:#. module: my_module ← translate.py:853 regex (extract module name — REQUIRED) #. odoo-python ← translate.py:1855 filter (Python translation — REQUIRED) #: code:addons/my_module/models/project_task.py:0 msgid "Error message" msgstr "Mensaje de error" - Scan pattern: for every
#: code:line, check the PRECEDING#.lines. There MUST be BOTHmodule: <name>andodoo-python. - Wrong 1 (silent translation loss — no odoo-python):
#. module: my_module #: code:addons/my_module/models/project_task.py:0 msgid "Error" msgstr "Error" - Wrong 2 (server crash — no module:):
#. odoo-python #: code:addons/my_module/models/project_task.py:0 msgid "Error" msgstr "Error" - Verified empirically in
addons_nativos/industry_fsm_sale/i18n/ar.po— native Odoo uses both.
- Root cause:
10. json.dumps Safety in Model Methods Called During Tests
- Scan:
json.dumps(inmodels/*.pywhere the input comes fromresp.json(). - Audit Failure:
json.dumps(resp.json().get('key', []))without type validation. During tests,resp.json()may return a Mock object (not a dict), causingTypeError: Object of type Mock is not JSON serializable. - Fix: Validate types before serializing:
data = resp.json() if not isinstance(data, dict): return tokens = data.get('key', []) rec.field = json.dumps(tokens if isinstance(tokens, list) else [])
11. Odoo 19 Deprecated Class Attributes (_sql_constraints)
- Scan:
_sql_constraints = [inmodels/*.py. - Audit Failure: ANY occurrence of
_sql_constraintsas a class attribute in a model. No exceptions — the legacy API is deprecated in Odoo 19. - Why this matters (not cosmetic): During module load, the registry emits
WARNING odoo.registry: Model attribute '_sql_constraints' is no longer supported, please define model.Constraint on the model.This warning is written toir.loggingon every Odoo.SH build instance and toodoo.log. The Odoo.SH build health detector countsir.loggingentries above INFO — a single custom module with_sql_constraintsis enough to make the build appear aswarningorerrorin the builds page even when all tests pass. It will also stop working entirely in a future Odoo release. - Fix: Migrate each
(name, sql, message)tuple to a separate class attribute_<name> = models.Constraint(sql, message). The attribute name MUST start with_(ORM descriptor). No new imports required —models.Constraintlives in the already-importedodoo.models.# ❌ WRONG (Odoo ≤18, deprecated in 19) class SaasTenant(models.Model): _name = 'saas.tenant' _sql_constraints = [ ('slug_unique', 'UNIQUE(slug)', 'Tenant slug must be unique.'), ] # ✅ CORRECT (Odoo 19+) class SaasTenant(models.Model): _name = 'saas.tenant' _slug_unique = models.Constraint( 'UNIQUE(slug)', 'Tenant slug must be unique.', ) - Verification after fix:
grep -r _sql_constraints addons/<module>/must return empty. The warning disappears fromir.loggingon the next deploy. - Cross-ref (development):
.agents/skills/check_pitfalls/SKILL.md§25 has the full pitfall context for devs writing new models. This verify-layer check is the safety net in case it was missed during development.
12. Test Logger Hygiene (mute_logger on Error-Path Tests)
- Scan:
tests/*.pyfiles for tests that mock exceptions — grep forside_effect=Exception,side_effect=ConnectionError,side_effect=Timeout, or anyside_effect=<ExceptionClass>pattern insidepatch(...)orMock(...). - Audit Warning (NOT automatic failure — heuristic, false positives possible): For each match, check if the containing test function has a
@mute_logger('odoo.addons.<module>...')decorator AND whether the code path being tested has a_logger.warning/error(...)call. If both are true but the decorator is missing, flag as WARNING for review. - Why this matters: Tests that mock exceptions trigger error-handling code paths in production code. Those handlers legitimately emit
_logger.warning/error(...)— behavior we WANT in production for observability. During--test-enableruns, however, those warnings are written toir.loggingon the build instance. On Odoo.SH, the build health detector counts any entry above INFO, so two unmuted error-path tests are enough to mark a build aswarningeven with0 failed / 0 error of N tests. - Fix (when the warning is legitimately expected during the test):
from odoo.tools import mute_logger @mute_logger('odoo.addons.saas_orchestrator.models.saas_instance') def test_cron_sync_handles_api_error(self): with patch(MOCK_PATH, side_effect=Exception("Connection refused")): # The cron calls _logger.warning(...) when catching — that's the # desired production behavior, but during this test it would # pollute ir.logging on the build instance. self.env['saas.instance']._cron_sync_instance_status() self.assertEqual(self.instance.state, 'running') - False positives to accept (do NOT flag as failure — leave as review item):
- Test uses
self.assertLogs(...)to verify the log message explicitly — in that case muting would break the assertion. Leave it alone. - The code path under test does NOT call
_logger.warning/error— nothing to mute. - The exception propagates out of the handler (test verifies
assertRaises) — there's no warning being emitted.
- Test uses
- Decorator scope rules (see
scaffold_test §8for full reasoning):- One decorator per test, NEVER at class level (would silence unrelated tests).
- Logger name must match exactly:
odoo.addons.<module>.<submodule>.<file>— same as__name__of the file containing_logger. - Production is unaffected —
tests/is never imported in runtime without--test-enable.
- Cross-ref (development):
.agents/skills/scaffold_test/SKILL.md§8 has the development-side rule with all three conditions for applying mute_logger. This verify-layer check is the safety net when that skill was not consulted.
Execution Guide
- Use
grep_searchto find instances of violations. - If violations are found, MARK THE AUDIT AS FAILED until resolved.
- Do not auto-fix unless completely trivial; prefer reporting the specific file and line.
- For heuristic checks (like §12), report as WARNING with source context — let the user decide whether each instance is a false positive.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

