Name: [ADD] viin_ai_ops: Operating Layer foundation (P-OPS-1)

State: Failed finished in 164m

PR State: merged

PR Author: David Tran

PR Author Email:

PR: #36

Committer: David Tran

Committer Email: davidtran.hp@gmail.com

Commit: c48fa61d93d66f430ec45ce43a353a04ca226c17

Description:

                                            [IMP] viin_ai_ops,viin_ai_agent,viin_ai_chat: address PR #36 review findings

Fixes from OSM-grounded (Viindoo 17.0) code review of this PR.

viin_ai_ops (HIGH):
- control_policy._match_proposal: scope policy search by the proposal's
  company_id ('|' company_id=False / =proposal.company) — ir.rule only
  scopes to the *current user's* allowed companies, not the proposal's,
  so explicit filtering is mandatory for multi-company isolation. Drop
  the redundant ('active','=',True) term (auto-filtered by _active_name).
- goal / work_item / agent_ext / trace_ext compute counts: replace
  search_count() inside a for-loop (N+1) with a single read_group();
  add @api.depends('work_item_ids' / 'proposal_ids') where a reverse
  O2M exists (goal, work_item). agent_ext/trace_ext have no reverse O2M
  yet → empty @api.depends() documented, deferred to P-OPS-2.

viin_ai_ops (MED):
- action_proposal.action_route: gate behind base.group_system so a
  regular internal user (perm_write) cannot self-route a proposal to
  'approved' via a low-risk auto_execute policy. Flow-lock unchanged.
  Documented assumption: swap for a dedicated approval group in P-OPS-2.
- control_policy.model_id: documented as not-yet-matched (proposal has
  no res_model field this phase) with an explicit P-OPS-2 TODO instead
  of a silent no-op.
- trace form: insert the stat button_box before the first <sheet> group
  (was position='inside' → rendered at sheet bottom); rename the div to
  the canonical name='button_box'.

viin_ai_agent (HIGH/MED):
- test_stub_deprecation_contract: replace dead assertIsNotNone(env[...])
  (env[] raises KeyError before the assert → ERROR not FAIL) with
  assertIn(name, env.registry.models); add rogue-field contract tests so
  the suite turns RED if a deprecated stub ever accumulates a field.
- stubs.py: docstring 'AbstractModels' → 'concrete Models'.
- pre-migrate 17.0.0.2.1: document the idempotency contract for future
  SQL (no behaviour change).

viin_ai_chat (LOW):
- wrap the NONCE_MISMATCH content string in _() for i18n parity with
  the NO_PENDING branch.
                                            

Branch: 17.0

Instance ID: 0

Age:

Up-time: