Name: [ADD] viin_ai_approval(+account,+sale,+ops_brain): P-OPS-2 approval governance + AI advisory on human approvals

State: Killed

PR State: merged

PR Author: David Tran

PR Author Email:

PR: #47

Committer: David Tran

Committer Email: davidtran.hp@gmail.com

Commit: 37725af9c513b168e8839c222ffc1f46c26cdd29

Description:

                                            [ADD] viin_ai_approval,viin_ai_approval_account,viin_ai_approval_sale,viin_ai_ops_brain: P-OPS-2 approval governance + AI advisory on human approvals

Phase 3.8 P-OPS-2. Two cleanly separated concerns on top of viin_ai_ops, wired to
the existing OmniApproval (viin_approval) engine. Behaviour + tests do NOT depend
on viin_workflow_automation (identical with or without it installed).

Concern A - "Approval OF AI" (viin_ai_approval, viin_ai_ops_brain):
- Routes a side-effecting viin.ai.action.proposal (medium/high risk, or a
  runs_as_sudo tool) to a human viin.approval.request; on the human decision the
  proposal state syncs (approved/rejected/draft) and the approved action is handed
  to execution. State sync is data-driven via the approval type's code_* hooks
  (code_validate_post / code_refuse_post / code_cancel_post) calling the proposal's
  public callbacks - NOT via action_* overrides (the viin_approval idiom).
- Post-approval execution is environment-independent (no workflow-engine gate;
  P-OPS-3 viin_ai_workflow overrides execution later).
- viin_ai_ops_brain writes an attributed "Approval Rationale" Brain page (T5:
  is_ai_authored + agent + trace + confidence; html_escape on untrusted text).

Concern B - "AI IN approval" (viin_ai_approval infra + per-app pilots):
- Posts an AI risk-advisory card (risk score + summary + recommendation + signals)
  to the chatter of a human approval request, for the approver. Advisory only (no
  auto-approve). Data-driven trigger: code_confirm_post enqueues (none->pending)
  and wakes a cron; the cron runs the LLM out-of-band and posts the card.
- The cron uses cr.savepoint() per record for failure isolation and relies on the
  ir.cron row-lock for non-concurrency - NO manual cr.commit(). Graceful 'skipped'
  when the BYOK key is not configured; silent 'error' on failure (no chatter noise).
- Per-app pilots (ADR-015 convention; auto_install; data-XML agent/topic seed + a
  non-clobbering post_init_hook wiring the approval type by stable code;
  PII-minimised signal builder): viin_ai_approval_account (CUSTOMER_INVOICE /
  VENDOR_PAYMENTS / CUSTOMER_REFUNDS) and viin_ai_approval_sale (QUOTE).
- UX: band-coloured chatter card (AA-contrast, "AI advisory - not a decision"
  disclaimer), a form status badge, and a list AI-risk column + "High risk" filter.

Cluster decoupling kept: only viin_ai_approval depends viin_approval; the per-app
modules reach it through the bridge. ADR-015 records the per-app advisory
convention (decisions/README updated).

Tests: Odoo native TransactionCase/@tagged, behaviour-protecting (no live LLM - the
provider boundary is stubbed at agent.run / _do_llm_call). 36 tests, 0 failed and
0 error in BOTH a Community addons set AND a full Viindoo-EE set (with
viin_workflow_automation). flake8 + the full test_pylint enable-list both pass with
NO lint suppressions.
                                            

Branch: 17.0

Instance ID: 0

Age:

Up-time: Not finished