dsh-odoo-sdd
Spec-Driven Development pipeline for Odoo as a DeepSeek Harness plugin: connects to an existing Odoo instance (JSON-RPC), orchestrates the 5-phase SDD workflow, and enforces fail-closed safety gates.
AI Analysis
核心用途是自动化进行 Odoo 模块的规范驱动开发与测试。适合 Odoo 开发者,用于在安全的闭环反馈中自动生成、调整和验证 Odoo 代码。
Install
This plugin has no verified bundle, or compatibility checks failed. Read the repository notes first. Read the full README ↗
README
Read the full README ↗description: "Spec-Driven Development pipeline for Odoo as a DSH plugin: closed feedback loop against a developer-provided Odoo instance (JSON-RPC) with fail-closed safety gates — approvals, honest verdicts, bounded fix loops, and a file-persisted knowledge base." kind: "package-bundle"
English | Español
Spec-Driven Development for Odoo
From an idea to a tested Odoo module — with or without human intervention.
Author: Franyer Hidalgo — fhidalgo.dev@gmail.com
Summary
dsh-odoo-sdd turns DeepSeek Harness into a specification-driven (SDD) Odoo
development pipeline built on two core principles:
- Closed feedback loop: the agent installs/upgrades modules, reads server
tracebacks, and retries against a real, running Odoo instance. This
plugin never starts Docker or
odoo-binprocesses: the developer supplies the URL and credentials of an existing instance (dev/staging) through a gitignored.env, and the tools speak standard JSON-RPC. - Pipeline safety: phases persist to disk (
state.json+ KB graph), gates are fail-closed on an explicitAPPROVEDmarker, three consecutive failures force a deep-diagnosis step, verify/fix iterations are capped,stop.mdhalts everything, and verdicts are honest: a failed verification persists as FAILED and can never be reported as success.
What it is NOT: an infrastructure orchestrator, a credential manager over chat, or an auto-committer.
Security & network posture
- No phone-home: the plugin's ONLY outbound network calls go to the
instance URL the developer put in
.env. No telemetry, no update checks, no third-party endpoints. - Transport guard (fail-closed):
http://is accepted only for loopback hosts (localhost,127.x,::1,*.localhost); any other target must behttps://, otherwise credential loading is refused (plain http to a remote host would ship the API key in clear text). - Secret containment: the secret is read once by
credentials.tsand only injected into RPC parameters. Every tool output passes through two-layer redaction (known secret + genericpassword=/Bearer/api_key=/session_idshapes) and home-path masking (/home/user/...→~/...) before being shown to the model or persisted to the KB. - Session cookies never reach the model:
odoo_sessionwrites the cookie to.sdd/session.json(chmod 600) and returns only the path. - No build scripts: the package executes no install scripts (market's pnpm ≥10 default stays in force); it ships source + documented build step.
- Host requirement declared twice, following dsh-market discovery
conventions:
engines.dsh(>=0.1.2-rc.1) and lockstep optional peer ranges on@deepseek-ai/{cordis,dsh-tools,schemastery}. On a host without thetoolsservice the plugin refuses to mount with an explicit error instead of booting broken (fail-closed, like the market itself).
Use this package
1. Configure credentials (once per project)
The easiest path is the onboarding tool: when the pipeline starts, the agent
runs odoo_setup mode=check and offers three choices — configure now
(collects only the non-secret fields and writes a chmod-600 scaffold; the
developer fills ODOO_PASSWORD by hand), configure later (re-asked before
the VERIFY phase), or skip (no instance; RPC/UI layers become manual
verification). The decision is persisted per project and never re-asked.
Credentials are resolved through a location cascade (first existing wins):
ODOO_SDD_ENV_FILE(explicit environment override)/.sdd/.env— project scope, plugin-owned hidden dir~/.config/dsh-odoo-sdd/.env($XDG_CONFIG_HOMEhonored) — user scope, the generic default: one set of dev credentials serves every project/.env— legacy location, still supported (reported as legacy)
Manual setup (alternative to the tool):
mkdir -p ~/.config/dsh-odoo-sdd && cd ~/.config/dsh-odoo-sdd
cp
/.env.example .env
chmod 600 .env
# The developer fills in: ODOO_URL, ODOO_DB, ODOO_USERNAME, ODOO_PASSWORD
# (an Odoo API key is recommended over the account password)
The plugin refuses a group/world-readable .env, redacts the secret
in every log/tool output, and never returns session cookies to the model
(they land in .sdd/session.json, mode 600, referenced only by path).
2. Compose the plugin into a DSH profile
// ~/.dsh/profiles/odoo/package.json
{
"name": "dsh-profile-odoo",
"private": true,
"dsh": { "profile": { "bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dsh-odoo-sdd"
], "patchReload": "live" } }
}
dsh plugin --profile odoo add
dsh --profile odoo --dump-config # inspect composition without booting
Optional configuration via the patch layer (cordis.patch.yml): projectRoot
(workspace root) and specsDir (specs folder, default specs/).
3. Registered tools (model-facing)
| Tool | Purpose |
|---|---|
odoo_connect | Probe the instance: server version + authentication. Masked report; distinguishes NEEDS_SETUP / NEEDS_SECRET / DEFERRED / SKIPPED states (never asks for secrets in chat). |
odoo_setup | Onboarding: check (cascade + gitignore + delegation mode), interactive (secret-free chmod-600 scaffold), later, skip, reset, autonomy (supervised |
odoo_module | info / install / upgrade on ir.module.module (button_immediate_*). Returns the server's own output or traceback, redacted — the closed feedback loop. |
odoo_execute | Generic CRUD/RPC (execute_kw) with a fail-closed allowlist: reads for allowlisted models, mutations (create/write/unlink) require confirm_destructive=true AND the model in executeAllowlist. No instance needed to evaluate denials. |
odoo_validate | LOCAL, instance-free module structure check: __manifest__.py present + depends, declared data XML files exist, security/ir.model.access.csv when models declared. Returns file:line findings. |
odoo_errors | Reads recent ir.logging server errors — the remote equivalent of fetching environment logs. |
odoo_session | Mints a passwordless web session (the connect_as_user pattern) stored in .sdd/session.json (chmod 600) for Playwright UI tests. The cookie itself is never returned. |
sdd_phase | The phase state machine: init, status (includes logbook summary), mark_spec_loaded, advance (fail-closed gates + approval_source provenance), fail (failure ladder + FAILED verdict), succeed (PASSED verdict). |
3b. Delegation mode (from one idea, supervised or autonomous)
The plugin starts by asking how much of the pipeline to delegate — recorded
once per project via odoo_setup mode=autonomy decision=...:
- Supervised (default): each gated phase asks the human for
APPROVED. - Autonomous (idea → architecture with no human in the loop): a
human-proxy agent (
agents/human-proxy.md) answers the gates, emitting only a fail-closed line-startAPPROVEDorNEEDS_REVISION. The human does the initial interview and leaves;create_goalcontinues unattended rounds untilDONEorBLOCKED. Emergency brakes stay armed (stop.md, iteration ceilings, diagnosis ladder);BLOCKEDis the only way to page a human.
3c. Context Engineering layers
| Layer | Component |
|---|---|
| identity | agents/*.md — architect, developer, qa, consultant, human-proxy personas with role + limits |
| odoo_connection | odoo-client.ts — JSON-RPC auth, execute_kw, session minting |
| executors | odoo_module, odoo_execute, odoo_validate, odoo_errors |
| schemas | staged templates with required sections; transition() rejects a phase whose deliverable lacks them |
| knowledge | version-pinned Odoo pattern skills (delegated, verified by the skill) |
| skills | SKILL.md — the 5-phase orchestration flow |
| logbook | kb.json — decisions, discarded options, blockers; read before proposing |
| audit | .sdd/audit.jsonl — sanitized append-only tool-activity log |
| test | tests/smoke.mjs — instance-free invariant suite |
4. Working protocol
The skill skills/odoo-sdd-workflow/SKILL.md
defines the 5-phase protocol the agent must follow:
- READ_SPEC — assimilate
spec.md(immutable); writing code is forbidden;APPROVEDgate. - ARCHITECTURE — design models/views/security in
architecture.md+test-plan.md; search existing functionality first;APPROVEDgate. - WRITE_CODE — implement with version-pinned Odoo patterns; static gates first (pre-commit, pylint, ruff).
- VERIFY — ascending pyramid: static → install/upgrade via
odoo_module→ RPC/data → UI (Playwright +odoo_session) only for critical flows. - FIX_LOOP — fix root causes; 3 failures ⇒ mandatory consultant diagnosis; 5 iterations ⇒
BLOCKED, escalate to the human.
Per-spec artifacts (everything on disk, resumable):
specs/-/
├── spec.md · architecture.md · test-plan.md
├── verify-verdict.txt # honest persisted verdict
├── state.json # phase, failures, iterations
└── kb.json # decisions, blockers, diagnoses, learnings
Understand the implementation
Implementation internals — click to expand
Plugin shape
Follows the DSH tool-plugin convention (dsh-tool-todo, dsh-tool-goal):
named exports name, inject (["tools"]), Config (schemastery schema)
and apply(ctx, config), registering each tool with defineTool from
@deepseek-ai/dsh-tools.
Source map
| File | Role |
|---|---|
src/index.ts | Plugin entry: registration of the 5 tools and config resolution |
src/types.ts | Public payload types (never contain secret material) |
src/credentials.ts | .env load/validation, 600 permissions, redact(), fail-closed |
src/odoo-client.ts | JSON-RPC client: common.version, authenticate, execute_kw, button_immediate_*, ir.logging, /web/session/authenticate |
src/sdd-state.ts | Phase machine, gates, append-only KB, verdicts, stop.md |
Security decisions
- The secret only exists inside
credentials.tsand the RPC call parameters; every output passes throughredact()(includinguser:pass@URL shapes). mintSessionstores the cookie with mode 600 and returns only the path.- Corrupted state ⇒ restart (progress is never faked); ambiguous gate ⇒
rejection; absent verification ⇒
DONEunreachable.
Model Experience
The agent sees 5 tools with self-contained descriptions. Typical flow:
sdd_phase init → read spec → odoo_connect → gated phases with APPROVED
→ code → odoo_module install → on traceback, odoo_errors + sdd_phase fail (which may force a diagnosis) → fix → re-verify → sdd_phase succeed →
DONE. Tool responses are actionable text: server tracebacks, gate rejection
reasons and remediation instructions.
Known Limitations and Deferred Work
- Remote tests: without shell access to the instance there is no way to
run
--test-enable; layer 2 is RPC/UI testing. Pending: an optionalodoo_run_teststool if the developer exposes a test runner. - Data rollback: tests write to the connected DB; there is no ephemeral cloning (design decision: the developer provisions and manages the target). Mitigation is documented: use a disposable database.
- Multi-instance: one target per project (
.env). Pending: instance profiles (dev,staging). - No rich
presentCall/UI renderer in the DSH web GUI (text render only).
Star History
Chart generated live by the star-history.com API.
Acknowledgments
Built for the Odoo developer community, this plugin rests on two ecosystems:
- Odoo Community Association (OCA) — the coding conventions, module layout and quality gates this pipeline enforces.
- DeepSeek Harness (DSH) — the plugin architecture (Cordis tools/plugins, skills, subagents) this plugin runs on.
Thank you to everyone who contributes patterns, reviews, and ideas that shape the SDD workflow. Contributors:
License
MIT