Pending: 0 Building: 0 Running: 5 Failed: 223
Created Date Type Name Commit Description State Age Up Time Life Time Action
merged [IMP] viin_ai_brain, viin_brain, docs: Brain Standard-17 closeout (11 tools + native OT + drift reconcile) [IMP] viin_brain: harden CW2 collab tests per code-review Post-review hardening for PR #68 (review report .odoo-ai/reviews/pr68-2026-06-22/viin_brain.md): - test_brain_collab_activation_tour.py: make the native-collab precondition deterministic so the tour's channel assertion actually runs instead of being silently skipped - set the admin notification_type to 'inbox' in setUpClass (drives session.notification_type truthy -> _hasICEServers -> _isCollaborationEnabled). The assertion still FAILS when wiring is wrong (collaborationChannel/busService remain required). Add tearDownClass to restore notification_type and reset realtime_collab=False (no state leak). - test_brain_collab_block_roundtrip.py: exercise the real ORM path (write content_html/blocks -> re-read) instead of calling the private _derive_from_* helpers directly, keeping the suite red-able. - test_brain_realtime_collab.py: assertEqual(stored, 'True') (exact) instead of a permissive membership check. - brain_collab_activation_tour.js: keep the canonical odoo.loader.modules.get(...) pattern (matches Odoo 17 core rte.js; require() is not a global in tour run callbacks) - add a comment to prevent re-flagging. Review finding F-1 (switch to require) was a false positive. - CHANGELOG.md: link ADR-002 for traceability. Browser tour verified by Runbot (headless tour not runnable locally). Killed
merged [IMP] viin_ai_brain, viin_brain, docs: Brain Standard-17 closeout (11 tools + native OT + drift reconcile) [FIX] viin_ai_brain, viin_brain: prettier/prettier in QUnit tests (test_eslint gate) test_pylint/tests/test_eslint::TestESLint.test_eslint failed with 84 prettier/prettier errors across 3 JS test files. The gate runs eslint with web/tooling/_eslintrc.json, which sets no trailingComma and therefore follows the bundled prettier 2.8.8 default (es5): no trailing comma after the last function-call argument, and short multiline calls collapsed. Fix applied via `eslint --no-eslintrc -c web/tooling/_eslintrc.json --fix` resolved against prettier 2.8.8 (NOT prettier 3.x, whose trailingComma=all default produces the opposite and would keep the gate red), bound strictly to: - viin_ai_brain/static/tests/components/ai_block_tests.js (47) - viin_ai_brain/static/tests/registries/powerbox_commands_tests.js (32) - viin_brain/static/tests/tours/brain_collab_activation_tour.js (5) Formatting only (remove trailing commas, join short multiline calls); no test logic, assertion, or message string changed. Post-fix: gate exit 0; full 118-file eslint sweep of both modules exit 0. Killed Not finished
merged [IMP] viin_ai_brain, viin_brain, docs: Brain Standard-17 closeout (11 tools + native OT + drift reconcile) [IMP] viin_ai_brain, viin_brain, docs: Brain Standard-17 closeout (11 tools + native OT + drift reconcile) PR #68 - Brain cluster closeout on Viindoo Standard 17, grounded in a code-level deep-survey of the cluster. CW1 (viin_ai_brain): wire the 2 Wave-2 KG-temporal tools (brain_temporal_diff, brain_record_state_as_of) to the Knowledge Base Assistant topic so the agent reaches all 11 tools; version 0.1.0 -> 0.1.1 (noupdate=0 re-seed on -u); membership-asserting RED-GREEN test; CHANGELOG. CW2 (viin_brain): native OdooEditor WebRTC OT collaboration (ADR-002 Option 1). _buildWysiwygOptions passes collaborationChannel {model,field,resId} + collaborativeTrigger to the standalone Wysiwyg, gated on the realtime_collab flag + canEdit; OdooEditor's own WebRTC P2P + ICE (mail.ice.server) handles OT - zero OT logic reimplemented. The interim snapshot-relay (collab.py, collab_step_service.js, viin.brain.collab.step) is retired. Flag-OFF path (autosave + version-token + conflict dialog) unchanged. block_parser roundtrip test for native-serialized HTML; activation tour + flag tests adapted. Live 2-peer WebRTC convergence is a manual staging check (not headless-CI-testable). CW3 (viin_ai_brain): QUnit for the AIBlock 5-state machine + powerbox Brain-context gate; new web.qunit_suite_tests bundle. Docs (reconcile SSOT to shipped code): adr-003 Accepted (P16 shipped); adr-002 closeout (native OT shipped, relay retired); security.md (WI-005 declined / WI-006 closed); roadmap Track B (P16 date, W18-22 panels shipped, OT-final native DONE); "9 tool" -> "11 tool"; adr-001 ADR-012 supersede note; new docs/brain/install-tiers.md (Standard vs Enterprise). Failed
merged [IMP] viin_ai_agent, viin_ai_base: streaming trace header lifecycle + provider Test Connection [IMP] viin_ai_agent, viin_ai_base: streaming trace header lifecycle + provider Test Connection WI-A (viin_ai_agent): run_streaming() now materializes + closes the viin.ai.trace header symmetric to run(); run() also closes its header (end_time/status/final_response); _ensure_trace_header stamps agent_id. Closes the ADR-019 deferred follow-up - streamed sessions are now observable in the P-OPS-4 cockpit, retention, and proposal.trace_id. Header create-to-loop span is guarded so an error still closes the header (AGENTS.md #7). WI-B (viin_ai_base): provider "Test Connection" button (WI-008 WI-F) - a BYOK reachability/auth probe routed through call_completion (satisfies AGENTS.md #7/#11/#12), returns {status, latency_ms, model_list} via the built-in display_notification. Vendor error text is redacted (_redact_secrets) so a BYOK api_key can never leak to the surface. Docs: roadmap, AGENTS status, observability, wi-008 updated to reflect both changes. Tests: 333 Odoo-native tests (viin_ai_agent 181 + viin_ai_base 318), 0 failed / 0 error. Failed
merged [IMP] viin_ai_brain, viin_brain, docs: Brain Standard-17 closeout (11 tools + native OT + drift reconcile) [IMP] viin_ai_brain, docs: Brain Standard-17 closeout - wire 11 tools to KBA + doc-drift reconcile CW1: wire the 2 Wave-2 KG-temporal tools (brain_temporal_diff, brain_record_state_as_of) to the Knowledge Base Assistant topic so the agent can reach all 11 tools; bump viin_ai_brain 0.1.0 -> 0.1.1 (noupdate=0 re-seed on -u); add membership-asserting RED-GREEN test (135 viin_ai_brain tests pass, 0 failed); add viin_ai_brain CHANGELOG. Docs (current-state reconciliation to shipped code): - adr-003 Status active -> Accepted (P16 shipped 2026-06-07) + checklist - adr-002 correct false 'collaborative=True already wired' claim (post-P16) - security.md: admin audit-read DECLINED (WI-005); 7 daily-note cells closed hard-DENY (WI-006) - roadmap Track B: P16 date, W18-22 panels shipped, P14/P15 header current - '9 tool' -> '11 tool' across module + docs + AGENTS - adr-001 inline ADR-012 supersede note on bridge removal clause - add docs/brain/install-tiers.md (Standard-vs-Enterprise install matrix) Killed Not finished
merged [ADD] Phase 4 Buoc 2: viin_ai accounting write-tools (create_invoice_draft / match_payment / tax_lookup) [DOC] AGENTS, roadmap, decisions, observability: reflect Phase 4 Buoc 2 account write-tools (ADR-019, PR #67) Killed
merged [ADD] Phase 4 Buoc 2: viin_ai accounting write-tools (create_invoice_draft / match_payment / tax_lookup) [DOC] AGENTS, roadmap, decisions, observability: reflect Phase 4 Buoc 2 account write-tools (ADR-019, PR #67) Failed
merged [ADD] Phase 4 Buoc 2: viin_ai accounting write-tools (create_invoice_draft / match_payment / tax_lookup) [ADD] l10n_vn_viin_ai_account: VN accounting AI guidance (TT99/TT133 additive topic) Killed Not finished
merged [ADD] viin_ai_helpdesk, viin_ai_crm: Phase 4 AI connectors (helpdesk seed + CRM advisory tools) [REM] docs, viin_ai_account, viin_ai_skill, viin_brain_account_reports: drop superseded TT200 accounting refs TT200 (Thong tu 200/2014/TT-BTC) is superseded by TT99 (Thong tu 99/2025). TT133 (Thong tu 133/2016, for SMEs) and TT99 both remain in effect and are kept. - Replace every TT200 reference with its successor TT99: docs (roadmap, architecture diagram, data-models), README, the account connector manifest + seed comment, the accounting skill pack, and the brain account-reports bridge. The architecture box-drawing diagram keeps its column alignment. - Keep TT133 and TT99 (both current): the accounting skill pack teaches TT99 (enterprises) / TT133 (SMEs). - Attribute receivable-provision rates to the current doubtful-debt provisioning regulation generically, not to the accounting regime. The "200h" effort figure in adr-008 is hours, not a circular, and is left untouched (ADRs are append-only). Killed
merged [ADD] viin_ai_helpdesk, viin_ai_crm: Phase 4 AI connectors (helpdesk seed + CRM advisory tools) [IMP] viin_ai_agent, viin_ai_crm, viin_ai_helpdesk: strip HTML from AI tool payloads Connector tools fed raw Html-field values (lead/ticket description, activity note, message body) straight into the payload the LLM reads - HTML tags are token noise and can confuse the model. - viin_ai_agent: add _tool_plain_text on ir.actions.server, a sibling of _tool_result that runs a value through html2plaintext ('' for falsy), callable from a server-action code body (safe_eval). Mirrors the existing viin_ai_chat plain-text helper; no viin_brain coupling. - viin_ai_crm: strip crm.lead.description and mail.activity.note. - viin_ai_helpdesk: strip viin.helpdesk.ticket.description and mail.message.body (strip first, then truncate so the cap applies to plain text). - Surveyed the other connectors (account/sale/sale_crm/stock) and the AI/Brain tool surface: no other tool returns a raw Html field (Brain already returns the content_plain T1 representation). - Tests: red-green behaviour tests assert the payload value carries no '<' and preserves the readable text, driven through a real ir.actions.server.run() as the tool's low-privilege group. - docs: note the _tool_plain_text sibling next to _tool_result in ai/architecture.md so future connectors strip Html-field values. Killed Not finished
merged [ADD] viin_ai_helpdesk, viin_ai_crm: Phase 4 AI connectors (helpdesk seed + CRM advisory tools) [IMP] viin_ai_agent, viin_ai_crm, viin_ai_helpdesk: strip HTML from AI tool payloads Connector tools fed raw Html-field values (lead/ticket description, activity note, message body) straight into the payload the LLM reads - HTML tags are token noise and can confuse the model. - viin_ai_agent: add _tool_plain_text on ir.actions.server, a sibling of _tool_result that runs a value through html2plaintext ('' for falsy), callable from a server-action code body (safe_eval). Mirrors the existing viin_ai_chat plain-text helper; no viin_brain coupling. - viin_ai_crm: strip crm.lead.description and mail.activity.note. - viin_ai_helpdesk: strip viin.helpdesk.ticket.description and mail.message.body (strip first, then truncate so the cap applies to plain text). - Surveyed the other connectors (account/sale/sale_crm/stock) and the AI/Brain tool surface: no other tool returns a raw Html field (Brain already returns the content_plain T1 representation). - Tests: red-green behaviour tests assert the payload value carries no '<' and preserves the readable text, driven through a real ir.actions.server.run() as the tool's low-privilege group. Killed Not finished
merged [ADD] viin_ai_helpdesk, viin_ai_crm: Phase 4 AI connectors (helpdesk seed + CRM advisory tools) [ADD] viin_ai_helpdesk, viin_ai_crm: Phase 4 AI connectors (helpdesk seed + CRM advisory tools) Phase 4 (Track C) per-app AI connectors, unlocked by M3: - viin_ai_helpdesk (NEW): AI connector for viin_helpdesk. Seeds 1 agent (Helpdesk Assistant) + 1 topic (Helpdesk Triage) + 3 READ-only tools on viin.helpdesk.ticket: triage_ticket, suggest_canned_response, generate_faq_from_thread. Data-XML, zero Python (Layer-3 convention). - viin_ai_crm (IMP): adds 3 advisory READ tools (qualify_lead, next_action_suggest, email_draft_for_lead) wired into the Lead Qualification topic. - All tools: requires_confirmation=False (read-only), runs_as_sudo=False, group_ids ACL-gated; model_id write-gate satisfied (group has perm_write on the target model). run()-driven boundary tests prove the safe_eval + write-gate path. - docs: AGENTS.md + docs/roadmap.md reflect Phase 4 progress; reconcile a pre-existing roadmap drift (helpdesk dependency named the Odoo-EE 'helpdesk' module instead of Viindoo 'viin_helpdesk'). Killed Not finished
merged [IMP] viin_ai_base, viin_ai_agent: bidirectional data-driven message adapter (close #64 #62 #63) [IMP] viin_ai_base, viin_ai_agent: bidirectional data-driven message adapter (close #64 #62 #63) Symmetric follow-up to the outgoing adapter (#59): make the INCOMING response normalizer data-driven via viin.ai.message.adapter, add a per-vendor empty-content knob, and route the streaming path through the adapter with a contract guard. - #64: viin.ai.message.adapter gains a `direction` discriminator (outgoing|incoming) + incoming response-map knobs; viin.ai.provider._normalize_completion_response is rewired to dispatch data-driven incoming primitives (output byte-stable for the 3 seeded protocols). An admin can hotfix a vendor response-key rename with no release. - #62: per-vendor `empty_content_repr` knob (empty_string|null|omit), default empty_string (byte-identical to prior behaviour) for strict gateways (Azure OpenAI). - #63: viin_ai_agent._do_llm_stream redacts-then-adapts before transport + a contract guard test that fails if a future streaming multi-turn path bypasses the adapter (also patches a latent streaming PII-redaction gap). - Hardening (post code-review): incoming rows must declare all leaf-key paths (finish/usage/text/tool); incoming rows for an unsupported protocol are rejected at write time (no silent mis-parse); clearer parse-error diagnostics; tightened guard tests (per-location PII, value-switch data-driven proof, assertRaises). - ADR-018 (bidirectional data-driven message adapter); docs/roadmap/module-map reconcile (32 modules, PR #57/#59/#60 history, ADR ledger, adr-015/016 status sync). Tests: Odoo native, no-API-key; 302 non-tour tests green (normalize/wire byte-stable non-regression + incoming data-driven proof + #62 matrix + #63 guard + multiturn loop + new validation guards). flake8 clean on the Runbot lint gate. Pre-existing HttpCase browser tours need a live http server and fail identically on base 17.0 under --no-http. Claude-Session: https://claude.ai/code/session_01MpghN1mdjfEzHd1yuSqdut Killed
merged [IMP] viin_ai_base, viin_ai_agent: bidirectional data-driven message adapter (close #64 #62 #63) [IMP] viin_ai_base, viin_ai_agent: bidirectional data-driven message adapter (close #64 #62 #63) Symmetric follow-up to the outgoing adapter (#59): make the INCOMING response normalizer data-driven via viin.ai.message.adapter, add a per-vendor empty-content knob, and route the streaming path through the adapter with a contract guard. - #64: viin.ai.message.adapter gains a `direction` discriminator (outgoing|incoming) + incoming response-map knobs; viin.ai.provider._normalize_completion_response is rewired to dispatch data-driven incoming primitives (output byte-stable for the 3 seeded protocols). An admin can hotfix a vendor response-key rename with no release. - #62: per-vendor `empty_content_repr` knob (empty_string|null|omit), default empty_string (byte-identical to prior behaviour) for strict gateways (Azure OpenAI). - #63: viin_ai_agent._do_llm_stream redacts-then-adapts before transport + a contract guard test that fails if a future streaming multi-turn path bypasses the adapter (also patches a latent streaming PII-redaction gap). - Hardening (post code-review): incoming rows must declare all leaf-key paths (finish/usage/text/tool); incoming rows for an unsupported protocol are rejected at write time (no silent mis-parse); clearer parse-error diagnostics; tightened guard tests (per-location PII, value-switch data-driven proof, assertRaises). - ADR-018 (bidirectional data-driven message adapter); docs/roadmap/module-map reconcile (32 modules, PR #57/#59/#60 history, ADR ledger, adr-015/016 status sync). Tests: Odoo native, no-API-key; 302 non-tour tests green (normalize/wire byte-stable non-regression + incoming data-driven proof + #62 matrix + #63 guard + multiturn loop + new validation guards). Pre-existing HttpCase browser tours need a live http server and fail identically on base 17.0 under --no-http (not part of this change). Claude-Session: https://claude.ai/code/session_01MpghN1mdjfEzHd1yuSqdut Failed
merged [IMP] viin_ai_base, viin_ai_agent: bidirectional data-driven message adapter (close #64 #62 #63) [IMP] viin_ai_base, viin_ai_agent: bidirectional data-driven message adapter (close #64 #62 #63) Symmetric follow-up to the outgoing adapter (#59): make the INCOMING response normalizer data-driven via viin.ai.message.adapter, add a per-vendor empty-content knob, and route the streaming path through the adapter with a contract guard. - #64: viin.ai.message.adapter gains a `direction` discriminator (outgoing|incoming) + incoming response-map knobs; viin.ai.provider._normalize_completion_response is rewired to dispatch data-driven incoming primitives (output byte-stable for the 3 seeded protocols). An admin can hotfix a vendor response-key rename with no release. - #62: per-vendor `empty_content_repr` knob (empty_string|null|omit), default empty_string (byte-identical to prior behaviour) for strict gateways (Azure OpenAI). - #63: viin_ai_agent._do_llm_stream redacts-then-adapts before transport + a contract guard test that fails if a future streaming multi-turn path bypasses the adapter (also patches a latent streaming PII-redaction gap). - ADR-018 (bidirectional data-driven message adapter); docs/roadmap/module-map reconcile (32 modules, PR #57/#59/#60 history, ADR ledger, adr-015/016 status sync). Tests: Odoo native, no-API-key; 74-class net green (normalize/wire byte-stable non-regression + incoming data-driven proof + #62 matrix + #63 guard + multiturn loop). Claude-Session: https://claude.ai/code/session_01MpghN1mdjfEzHd1yuSqdut Failed
merged [ADD] KG temporal Wave-2 (ADR-006): _as_of reconstruction + live KG tools + memory-brain bridge [FIX] viin_ai_brain: revert record_historian as-of boundary to inclusive-at-ts + lock-in test verify2 (review iter-2) flagged a silent, undocumented boundary flip in record_historian._as_of_record Step-4: the tracking-message revert filter had been changed from ('date','>',ts) to '>=', making a change stamped exactly at ts get reverted (exclusive-at-ts) - the opposite of the whole-codebase convention (viin_brain._find_active_at inclusive-at-ts; memory recall <= as_of; the Step-2 create_date boundary in the same method). "State as of ts" must reflect a change effective at ts, so revert only strictly-after-ts changes. - record_historian.py: ('date','>=',ts) -> ('date','>',ts) + convention comment. - test_record_historian.py: add boundary-exact lock-in test H7 (RED under '>=' AssertionError partner_before reverted; GREEN under '>'). Claude-Session: https://claude.ai/code/session_01EVjERtZ9dnk5fhZHns8vLv Killed
merged [ADD] KG temporal Wave-2 (ADR-006): _as_of reconstruction + live KG tools + memory-brain bridge [FIX] viin_ai: PR #60 review-2 - W8150 lint blocker + record_state_as_of ACL guard + temporal test hardening - viin_ai_brain: fix Runbot test_pylint W8150 (module-level relative import in test_record_historian.py); add caller-env ACL gate (check_access_rights/rule) before record_state_as_of reconstruction, return {} on AccessError; RED-GREEN test as low_priv; perm_write=1 lock-in test + rationale. - viin_ai_memory: neutralize-proof UUID tokens in as-of recall tests; defensive str as_of normalize via fields.Datetime.to_datetime + cross-module contract comment. - viin_brain: boundary-exact active-at fixtures (valid_to==ts / valid_from==ts) guarding the inclusive operator; expression.AND for temporal domain combine. - viin_ai_memory_brain: explicit required=False/default=False on vault_id. - docs: propagate _search_active_at -> _find_active_at; correct stale 2-condition active-at domain to the shipped 3-condition predicate (ADR-006 append-only Wave-2 note). Claude-Session: https://claude.ai/code/session_01EVjERtZ9dnk5fhZHns8vLv Killed Not finished
merged [ADD] KG temporal Wave-2 (ADR-006): _as_of reconstruction + live KG tools + memory-brain bridge [FIX] viin_ai: PR #60 review-2 - W8150 lint blocker + record_state_as_of ACL guard + temporal test hardening - viin_ai_brain: fix Runbot test_pylint W8150 (module-level relative import in test_record_historian.py); add caller-env ACL gate (check_access_rights/rule) before record_state_as_of reconstruction, return {} on AccessError; RED-GREEN test as low_priv; perm_write=1 lock-in test + rationale. - viin_ai_memory: neutralize-proof UUID tokens in as-of recall tests; defensive str as_of normalize via fields.Datetime.to_datetime + cross-module contract comment. - viin_brain: boundary-exact active-at fixtures (valid_to==ts / valid_from==ts) guarding the inclusive operator; expression.AND for temporal domain combine. - viin_ai_memory_brain: explicit required=False/default=False on vault_id. - docs: propagate _search_active_at -> _find_active_at; correct stale 2-condition active-at domain to the shipped 3-condition predicate (ADR-006 append-only Wave-2 note). Claude-Session: https://claude.ai/code/session_01EVjERtZ9dnk5fhZHns8vLv Killed Not finished
merged [FIX] viin_ai_base: provider-native outgoing message adapter (#59) [FIX] viin_ai_base: provider-native outgoing message adapter (#59) The agentic tool loop shipped turn-2 canonical history (assistant tool_calls, tool role tool_results) to the wire verbatim - no outgoing adapter existed, only an incoming normalizer. A real tool-using turn returned HTTP 400 on anthropic_native/openai_compat and silently dropped the tool result on google_native. The same payload builder dropped the system prompt on all 3 protocols, and the PII redactor skipped tool-turn free-text (tool_calls arguments, tool_results result/error). Add a data-driven, UI-editable viin.ai.message.adapter (protocol-keyed with an optional vendor override, noupdate seed) that reshapes the canonical history into each provider's native wire format via vetted code primitives - zero eval/template on the BYOK egress path. A write-time coherence constraint rejects incoherent (protocol, shape/strategy) admin edits. System-prompt placement is handled per protocol (anthropic top-level system, google systemInstruction, openai role=system) with the system kwarg as the single source of truth, which also fixes viin_ai_search Path B on anthropic/google. PII redaction is extended to tool-turn free-text and runs before the adapt step (redact-then-adapt). Add honest tests that stub only the transport seam and assert the built outgoing payload per protocol (the seam #59 slipped through), plus data-driven, coherence-gate, and PII-redaction tests. Claude-Session: https://claude.ai/code/session_0128GTfwboHEZqJZ5xgfkxoL Killed
merged [ADD] KG temporal Wave-2 (ADR-006): _as_of reconstruction + live KG tools + memory-brain bridge [FIX] viin_ai: address PR #60 review (temporal_diff ACL, BFS N+1, as-of test gaps, conventions) H-A: add ACL post-filter in tool_brain_temporal_diff - batch-search readable page ids after edge set-diff, drop edges where either endpoint is unreadable (same D6 fix class applied to graph_traverse in Wave-1). H-B: batch the fallback BFS _acl_filter call - collect all candidate to_page ids per BFS step BEFORE the ACL check (single Page.search per step, not one per link, mirroring the primary delegate path). H-C: add test_observation_recall_as_of_filters - protects the third temporal leg (created_at <= as_of on observations); RED-then-GREEN verified. M1: rename _search_active_at -> _find_active_at in viin.brain.link and all call sites in brain_tools.py and tests (avoids ORM _search_<field> prefix collision, no active_at field exists). M2: fix assertIsNotNone(link_a.superseded_at) -> assertTrue (Odoo Datetime null is False, not None; assertIsNotNone(False) passes silently). M3: replace (6, 0, [...]) legacy tuples with Command.set([...]) in viin_ai_memory_brain/tests/test_vault_id_isolation.py (AGENTS.md #7). M4: move imports (datetime, fields.Datetime/Date) from inside function body to module top-level in brain_tools.py (python.md imports rule). Claude-Session: https://claude.ai/code/session_01JTYAzu8ndxtrQGJeTNa3pf Failed
merged [ADD] KG temporal Wave-2 (ADR-006): _as_of reconstruction + live KG tools + memory-brain bridge [ADD] viin_ai_memory_brain: AI memory <-> Brain vault bridge (KG temporal Wave-2) New auto-install bridge (depends viin_ai_memory + viin_brain). Adds an optional vault_id Many2one('viin.brain.vault') to viin.ai.memory so a memory can be scoped to a Brain vault, plus a GLOBAL ir.rule that restricts memory visibility to vaults the user can access (member or access-group), while vault-less memories remain governed by the existing per-owner rule. The vault rule is GLOBAL (AND-combines = restricts), not non-global: a non-global rule with an OR(vault_id=False, ...) disjunct would OR-union with the owner rule and leak every vault-less memory across owners. Tests cover cross-vault, cross-company, owner-only vault-less, and the cross-owner vault-less regression. Part of ADR-006 KG temporal Wave-2. Claude-Session: https://claude.ai/code/session_01JTYAzu8ndxtrQGJeTNa3pf Failed
merged [REF] viin_ai: standardize AI tool server-action return envelope as ir.actions.client [REF] viin_ai_stock: return AI tool results via the standard envelope helper The 3 stock tools (get_stock_level, get_low_stock_products, get_product_moves) now use env['ir.actions.server']._tool_result(payload); tests assert the ir.actions.client envelope (tag viin_ai_tool_result) under params['data']. Claude-Session: https://claude.ai/code/session_0128GTfwboHEZqJZ5xgfkxoL Killed Not finished
merged [FIX] viin_ai_account/stock: ADR-012 seed runtime crashes + review-driven hardening [IMP] viin_brain: reconcile linkable docstring with ADR-012 carrier reality The viin_brain_linkable docstring still claimed the per-app bridges "explicitly inherit this mixin" (their concrete models were deleted) and that "WI-7 will set installable:False" (contradicted by the ADR-012 revive). Correct both claims; the _brain_form_sidebar flag and all logic are untouched. Claude-Session: https://claude.ai/code/session_01JTYAzu8ndxtrQGJeTNa3pf Killed
merged [REF] viin_ai: standardize AI tool server-action return envelope as ir.actions.client [REF] viin_ai_search: tidy stale arguments wording in web_query tool comment/docstring Replace residual 'tool_web_query(arguments)' prose (which implied 'arguments' is a safe_eval dispatch-scope variable) with 'tool_web_query(...)'. The bare 'arguments' is the method parameter name, not a server-action context variable. Comment/docstring only - no behavior change. Claude-Session: https://claude.ai/code/session_0128GTfwboHEZqJZ5xgfkxoL Killed
merged [REF] viin_ai: standardize AI tool server-action return envelope as ir.actions.client [REF] viin_ai_search: return web_query result via the standard envelope helper Rewrite the web_query server-action body to build its result through `env['ir.actions.server']._tool_result(...)`, returning a valid ir.actions.client action instead of the non-standard `tool_result` dict. Update the header comment and the server-action test to assert the new envelope while preserving the domain/fallback_used assertions. Killed Not finished
merged [IMP] ADR-012: per-app seed master data - 9 modules (AI connectors + Brain bridges) [DOC] AGENTS,docs,README: reconcile full ADR-012 per-app seed (9 modules) + correct tool names + viin_brain_sale rename Killed
merged [IMP] ADR-012: per-app seed master data - 9 modules (AI connectors + Brain bridges) [DOC] AGENTS,docs,README: reconcile ADR-012 CRM+Sale seed state + viin_brain_sale rename across docs Killed Not finished
merged [FIX] viin_ai_brain: tool server-actions read args from context (fix NameError through agent loop) [FIX] viin_ai_search: correct stale tool-args injection comment The comment claimed `viin_ai_tool_args` is mapped to `arguments` via a `_get_eval_context` override; no such override exists. The server-action already reads its arguments via env.context.get('viin_ai_tool_args', {}). Comment only - no code change. Killed Not finished
merged [IMP] ADR-012: per-app seed master data - 9 modules (AI connectors + Brain bridges) [DOC] AGENTS,docs,README: reconcile ADR-012 CRM+Sale seed state + viin_brain_sale rename across docs Revoked
merged [IMP] ADR-012: per-app seed master data - 9 modules (AI connectors + Brain bridges) [DOC] AGENTS,docs,viin_brain: rename viin_brain_sale_management -> viin_brain_sale references + ADR-012 addendum Killed Not finished
merged [IMP] ADR-012: per-app seed master data - 9 modules (AI connectors + Brain bridges) [IMP] viin_ai_sale_crm: cross-domain handoff topic + targeted auto_install (ADR-012) Killed Not finished
merged [ADD] AI Cognitive Wave-1: Memory L0-L3 + Skill runtime + Pulse cost gate + KG temporal (supersedes #53) [FIX] viin_ai: clear Runbot errors and warnings (PR #54) Resolve every Runbot build error and warning on the Cognitive Wave-1 branch without masking any behavior. Each fix is root-cause proven and verified by a real Odoo 17 test run on a fresh DB (--skip-auto-install). - viin_ai_chat: fix stale mock signature in test_user_error_passed_through. _user_err now matches _collect_allowed_tools(self, applied_skills=None), which viin_ai_skill's _resolve_run_skills override calls positionally. This was the only build-breaking failure. - viin_ai_base: guard the _record_error_usage separate-cursor write so a provider_id/model_id not yet visible to that cursor is set NULL instead of raising a ForeignKeyViolation. Removes the odoo.sql_db ERROR noise while preserving the trace-durability invariant. Add a regression test that verifies via a fresh cursor (the row is committed by a separate cursor, invisible to the REPEATABLE READ test cursor). - viin_ai_approval: remove the dead advisory tool ACL-gap warning in _advisory_agent_has_tools (unreachable - every caller runs sudo, so it could never detect a real gap). Assert the H8 executable-tools refusal warning via assertLogs. Add mail_notify_force_send=False to TestAdvisoryInfra.setUpClass. - viin_ai_memory: align the promotion.log / observation owner ir.rule perms with ir.model.access.csv (promotion.log read-only, observation append-only), clearing the to_base record-rule validator warning. Add ACL regression tests driven via with_user. Downgrade the BYOK no-provider summarize-skip log from WARNING to INFO (expected steady-state when no key is configured), and keep the cron test asserting its real contract (zero external call) rather than a data-state-dependent log. - viin_ai_agent: assert the sudo-escalation refusal security warning via assertLogs so the expected signal is captured, not leaked to the log. - viin_ai_ops / viin_ai_ops_brain / viin_ai_approval_sale: add the mail_notify_force_send=False test-context guard (OpsBaseTestCase and the evidence/advisory-sale test classes) so confirm/route/notify flows do not attempt a synchronous mail send that fails on a runner with no mail.catchall ICP. These tests assert routing/state, not email delivery. Killed
merged [ADD] AI Cognitive Wave-1: Memory L0-L3 + Skill runtime + Pulse cost gate + KG temporal (supersedes #53) [FIX] viin_ai: clear Runbot errors and warnings (PR #54) Resolve every Runbot build error and warning on the Cognitive Wave-1 branch without masking any behavior. Each fix is root-cause proven and verified by a real Odoo 17 test run on a fresh DB (--skip-auto-install). - viin_ai_chat: fix stale mock signature in test_user_error_passed_through. _user_err now matches _collect_allowed_tools(self, applied_skills=None), which viin_ai_skill's _resolve_run_skills override calls positionally. This was the only build-breaking failure. - viin_ai_base: guard the _record_error_usage separate-cursor write so a provider_id/model_id not yet visible to that cursor is set NULL instead of raising a ForeignKeyViolation. Removes the odoo.sql_db ERROR noise while preserving the trace-durability invariant (the error usage.log is still committed independently). Add a regression test that verifies via a fresh cursor. - viin_ai_approval: remove the dead advisory tool ACL-gap warning in _advisory_agent_has_tools (unreachable - every caller runs sudo, so it could never detect a real gap); this clears the false-positive log. Assert the H8 executable-tools refusal warning via assertLogs instead of letting it leak. Add mail_notify_force_send=False to TestAdvisoryInfra.setUpClass to stop the mail.catchall send ERROR. - viin_ai_memory: align the promotion.log / observation owner ir.rule perms with ir.model.access.csv (promotion.log read-only, observation append-only), clearing the to_base record-rule validator warning. Assert the BYOK no-provider skip warning via assertLogs. Add ACL regression tests driven via with_user. - viin_ai_agent: assert the sudo-escalation refusal security warning via assertLogs so the expected signal is captured, not leaked to the log. Failed
merged [ADD] AI Cognitive Wave-1: Memory L0-L3 + Skill runtime + Pulse cost gate + KG temporal (supersedes #53) [FIX] viin_ai: clear Runbot errors and warnings (PR #54) Resolve every Runbot build error and warning on the Cognitive Wave-1 branch without masking any behavior. Each fix is root-cause proven and verified by a real Odoo 17 test run on a fresh DB (--skip-auto-install). - viin_ai_chat: fix stale mock signature in test_user_error_passed_through. _user_err now matches _collect_allowed_tools(self, applied_skills=None), which viin_ai_skill's _resolve_run_skills override calls positionally. This was the only build-breaking failure. - viin_ai_base: guard the _record_error_usage separate-cursor write so a provider_id/model_id not yet visible to that cursor is set NULL instead of raising a ForeignKeyViolation. Removes the odoo.sql_db ERROR noise while preserving the trace-durability invariant (the error usage.log is still committed independently). Add a regression test that verifies via a fresh cursor. - viin_ai_approval: remove the dead advisory tool ACL-gap warning in _advisory_agent_has_tools (unreachable - every caller runs sudo, so it could never detect a real gap); this clears the false-positive log. Assert the H8 executable-tools refusal warning via assertLogs instead of letting it leak. Add mail_notify_force_send=False to TestAdvisoryInfra.setUpClass to stop the mail.catchall send ERROR. - viin_ai_memory: align the promotion.log / observation owner ir.rule perms with ir.model.access.csv (promotion.log read-only, observation append-only), clearing the to_base record-rule validator warning. Assert the BYOK no-provider skip warning via assertLogs. Add ACL regression tests driven via with_user. - viin_ai_agent: assert the sudo-escalation refusal security warning via assertLogs so the expected signal is captured, not leaked to the log. Failed
merged [ADD] AI Cognitive Wave-1: Memory L0-L3 + Skill runtime + Pulse cost gate + KG temporal (supersedes #53) [DOC] docs,AGENTS: reconcile Cognitive Wave-1 + ADR status drift ADR-009 ratified; module maps + roadmap + AGENTS.md status; ADR-015/016 append-only Accepted; testing.md verify cmd. Failed
merged [ADD] AI Cognitive Wave-1: Memory L0-L3 + Skill runtime + Pulse cost gate + KG temporal (supersedes #53) [DOC] docs,AGENTS: reconcile Cognitive Wave-1 + ADR status drift ADR-009 ratified; module maps + roadmap + AGENTS.md status; ADR-015/016 append-only Accepted; testing.md verify cmd. (= PR #53 docs reconcile.) Killed Not finished
closed [ADD] Phase 3.9 Cognitive Wave-1: Memory + Skill + KG temporal + Pulse + CoWork bundle [DOC] docs,AGENTS: reconcile Cognitive Wave-1 + ADR status drift (PR #53) PR #53 (Cognitive Wave-1) shipped viin_ai_memory/skill/pulse + KG temporal signature + CoWork 5-pack and ratified ADR-009, but the living status docs stayed stale. Reconcile across the count-bearing + map docs: - AGENTS.md §3: Track A now reflects M3 achieved (PR #50) + P-OPS-3/4 shipped; Phase 3.9 Cognitive Wave-1 marked shipped (PR #53), not future. - AGENTS.md §2 + docs/ai/architecture.md: add viin_ai_memory/skill/pulse (+ viin_ai_workflow) to the module / dependency maps with real depends. - docs/roadmap.md: ADR-009 footnotes/open-list resolved (3 separate modules, Accepted PR #53); W13-W17 drift-note (Wave-1 code shipped); ADR counts reconciled to 16 ADR (14 accepted + 2 proposed). - docs/decisions/README.md: ADR-015/016 status proposed -> accepted (PR #47); index date bumped. - adr-015/adr-016: append-only Status update line (Accepted, PR #47). - docs/ai/testing.md: add the 3 cognitive modules to the no-key verify command. Docs-only, no code touched. Killed Not finished
closed [ADD] Phase 3.9 Cognitive Wave-1: Memory + Skill + KG temporal + Pulse + CoWork bundle [FIX] viin_ai_memory,viin_ai_skill: Runbot lint (default manifest key + W391) - viin_ai_memory/__manifest__.py: remove auto_install=False (equals the default; the Viindoo manifest linter test_manifests rejects redundant default keys). - viin_ai_skill/tests/test_cowork_bundle.py: strip trailing blank line (flake8 W391). Killed Not finished
closed [ADD] Phase 3.9 Cognitive Wave-1: Memory + Skill + KG temporal + Pulse + CoWork bundle [FIX] viin_ai cluster,viin_brain: full-width text fields across form views (colspan sweep) Repo-wide sweep of the same layout bug fixed earlier: a free-text/tag field that is the sole (or last) child of a default two-column <group> renders squeezed into a one-character-wide column. The canonical Odoo idiom is colspan="2" (core sale_order_views.xml note field). Added it to 8 more fields: - viin_ai_agent: system_prompt (agent form), ai_prompt (ir.actions.server form) - viin_ai_base: final_response (trace form) - viin_ai_ops: payload (action proposal form), description (goal form) - viin_ai_approval: prompt_snapshot (action proposal form) - viin_brain: ambiguous_candidate_ids (link form) - viin_ai_skill: description (skill pack form) Pure view-XML (no SCSS/JS). Found by a form-view scan, pre-checked for layout edge cases (all default col=2 groups; no sibling-field regression), and verified full-width by live render after -u. Failed
closed [ADD] Phase 3.9 Cognitive Wave-1: Memory + Skill + KG temporal + Pulse + CoWork bundle [FIX] viin_ai_skill,viin_ai_memory,viin_ai_pulse: full-width text fields in form views The Level-1/Level-2 description fields (skill), the summary (memory) and the signal payload/evidence fields rendered squeezed into a one-character-wide column. A nolabel field inside a default two-column <group> lands in the narrow label slot; the canonical Odoo idiom (e.g. sale.order note, sale_order_views.xml) is to add colspan="2" so the field spans the full group width. - viin_ai_skill: description, manifest_text - viin_ai_memory: summary, access_group_ids - viin_ai_pulse: signal payload, evidence_refs Pure view-XML fix (no SCSS/JS). Verified full-width by live render. Failed