Pending: 0 Building: 0 Running: 3 Failed: 269
Created Date Type Name Commit Description State Age Up Time Life Time Action
merged [ADD] viin_brain, viin_ai_brain: KG-temporal Brain UI - ADR-006 UI-layer (C-gamma scrubber) [FIX] viin_brain: graph canvas off-frame/resize/clip + playhead overshoot + template icon A deep visual-QA sweep (rect/coordinate-measured) found visual defects that pass DOM-presence checks but render wrong: - Graph Canvas force layout centered nodes at the 600px default coordinate space, so in the ~298px context pane 2 of 3 nodes rendered OFF the right edge (DOM-present, invisible). Measure the real container size BEFORE the force layout; re-run the layout (debounced 150ms) on pane resize so nodes re-center within the measured width (verified cx within [0,width] at 213/298/498px). - Canvas SVG was a hard 400px in a non-scrollable pane -> clipped ~6px below the viewport. Size the wrapper to the available pane height (flex). - Validity-strip playhead overshot the track by its own 2px width at max scrub (left:100% + 2px marker). Offset by translateX(-pct*0.02px) so the marker stays flush at 100% and is unchanged mid-track. - "Meeting Notes" template shipped icon "notebook", which is not a Font Awesome 4.7 glyph (Odoo 17 ships FA4.7) -> empty icon box. Use the valid "sticky-note-o". Killed
merged [ADD] viin_brain, viin_ai_brain: KG-temporal Brain UI - ADR-006 UI-layer (C-gamma scrubber) [IMP] viin_brain: mobile/tablet responsive - frozen-backdrop fix + context bottom-sheet Mobile/tablet defects found by a live Playwright survey (phone 390 + tablet 768): - BLOCKER "frozen UI" on phone: a global `.o_brain_drawer_backdrop` rule in brain_create_drawer.scss (pointer-events:all, z-index:1040) collided with the mobile sidebar backdrop of the same class, so the always-present phone backdrop swallowed every tap. Rename the create-drawer backdrop to a private class. - Phone: page context menu clamped on-screen (was off the left edge); header actions wrap; sidebar containing-block fix; sidebar auto-closes after page nav. - Tablet: "More" overflow menu + temporal slider + context-pane toggle handle kept inside the viewport. - NEW: phone context bottom-sheet - the context pane (Graph / temporal scrubber / Fact History / Properties / Backlinks) was display:none on phone; now a bottom-sheet (FAB trigger + backdrop + drag-dismiss) makes it reachable. All changes gated to phone/tablet media queries + isMobileViewport; desktop (>=1024px) byte-identical. Killed Not finished
merged [ADD] viin_brain, viin_ai_brain: KG-temporal Brain UI - ADR-006 UI-layer (C-gamma scrubber) [FIX] viin_brain: temporal tours to tabWidth=4 (real Viindoo Runbot eslint gate) The previous prettier pass used standalone prettier 2.8.8 (tabWidth=2 default) and was verified against odoo/addons/test_lint/tests/eslintrc - which carries NO prettier rule, so it reported a false CLEAN. Viindoo Runbot actually runs the tvtmaaddons17/test_pylint fork of test_eslint, which points at web/tooling/_eslintrc.json (extends plugin:prettier/recommended, tabWidth=4, printWidth=100, semi). Under that real gate the 3 new tour files were 359 prettier/prettier errors (2-space vs required 4-space). Reformat them with `eslint --fix -c web/tooling/_eslintrc.json`. No behavior change (tours stay green). The pre-existing graph_panel tour already used 4-space, hence it passed. Killed
merged [ADD] viin_brain, viin_ai_brain: KG-temporal Brain UI - ADR-006 UI-layer (C-gamma scrubber) [FIX] viin_brain: prettier 2.8.8 on temporal tours + drop unused import (Runbot lint) Runbot test_pylint gate was red: TestESLint flagged 12 prettier/prettier errors across the 3 new temporal tour files, and TestFlake8 flagged F401 unused `from odoo import fields` in test_brain_snapshot_as_of.py (the clock is patched via the string path `patch('odoo.fields.Datetime.now', ...)`, never the symbol). Reformat the tours with the pinned prettier 2.8.8 (es5) and remove the dead import. No logic change. Failed
merged [ADD] viin_brain, viin_ai_brain: KG-temporal Brain UI - ADR-006 UI-layer (C-gamma scrubber) [IMP] viin_ai_brain: Fact-history panel + ai_bridge recordStateAsOf (ADR-006) Bridge the ADR-006 record-state-as-of tool into the Brain UI. - FactHistoryPanel: reconstruct an ERP record's tracked-field state at a chosen instant, mounted in BacklinkPanel via the ai_bridge seam and gated on ai_bridge.available so viin_brain still installs standalone (cluster decoupling, AGENTS.md section 4 #2). - ai_bridge_service.recordStateAsOf(model, resId, asOf) -> orm.call tool_brain_record_state_as_of. READ path: the tool self-guards via check_access_rights + check_access_rule as the calling user (no sudo, no T5 attribution needed for a read/display surface). - ACL no-leak test (a user without access gets {state:{}}, not a sudo bypass) + fact-history tour. Failed
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_agent, viin_ai_base: streaming trace header lifecycle + provider Test Connection [TEST] viin_ai_account, viin_ai_approval_account: capture expected deny-path WARNINGs The negative ACL tests and the C1 confused-deputy guard test exercise deny paths that legitimately log a WARNING (core ir.actions "Forbidden server action"; the match_payment C1 "lacks write authority ... refusing to reconcile"). Wrap each in assertLogs so the warning is both asserted (the guard fired) and captured (no longer leaking to the runbot log). Strengthens the tests; no assertion removed. Killed
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