Pending: 0 Building: 0 Running: 2 Failed: 79
Created Date Type Name Commit Description State Age Up Time Life Time Action
merged [DOC] docs,ci: close M1 — SQL template ACL ✅ + Runbot-only CI model + local pre-commit hook [REM] docs: purge viinForge residue — deprecated product viinForge (orchestration platform/wrapper) đã bị loại bỏ. Gỡ toàn bộ 13 reference trên 9 file: - CONTRIBUTING.md: thay wrapper ~/viinforge/ops/scripts/run_{tests,odoo}.sh + venv rỗng viindoo17 bằng lệnh odoo-bin native (venv odoo17 + addons-path deps) — giải luôn gốc 'không biết cách chạy test'. - conventions.md, brain/architecture.md, brain/ui-design.md: gỡ con trỏ tới viinForge workspace/knowledge/reuse-map, giữ quy tắc cứng inline. - decisions/wi-001, wi-003, history/release-notes-v1.3, contenteditable_policy: gỡ con trỏ audit/pattern/worktree tới viinforge repo (dead pointer), giữ nội dung coherent. - brain/mockups/v3/ui_design_v3.html: gỡ checklist item 'viinForge Monitor TUI' (demo data). Verify: grep -rIni viinforge + git grep = 0 match. Append-only decision records chỉ gỡ dead pointer, không sửa nội dung quyết định. Succeed
merged [DOC] docs,ci: close M1 — SQL template ACL ✅ + Runbot-only CI model + local pre-commit hook [DOC] docs,ci: close M1 — SQL template ACL ✅ + Runbot-only CI model + local pre-commit hook Phase 3.7 carry-over / Gate M1 closure: - roadmap §5 + security.md checklist: tick SQL template ACL (evidence: sql_template.py _check_sql_safety + ACL CTE __acl_allowed + group_ids allowlist + JSON Schema params; test_sql_template.py ma trận ACL/multi-company all pass). - roadmap §6: định nghĩa CI gate = Viindoo Runbot 'CI/runbot' (Runbot-only theo chuẩn org, tvtmaaddons cũng zero GitHub Actions); gỡ giả định P15 tour gate khóa bởi Chrome runner GitHub Actions — tour chạy trên Runbot. Đồng bộ M1 condition + Track B refs + REPO_LAYOUT. - tooling: thêm husky + mở rộng lint-staged (ruff check/format cho *.py) làm lớp verify local; CONTRIBUTING hướng dẫn chạy test qua odoo-bin --test-tags (không phải pytest thuần). Why: PR #34 chủ động drop CI repo-specific để dùng Runbot external; docs cần khớp thực tế để M1 đóng sạch và dev có lớp verify nhanh trước push. Killed Not finished
merged M1 Wave 1: 3 security HIGH gap closure (trace ir.rule + nl_query sanitize + confirmation nonce) [REMOVE] ci: drop all repo-specific CI — workflows + scripts (PR #34) Stop maintaining ai17's own GitHub Actions CI; rely on the external Viindoo Runbot check instead. Deleted: .github/workflows/{brain-tours,ci,preflight-pgvector}.yml; ops/ci/* (5 files); tools/brain_v3_ci_check.py; docs/brain/ci-tour-gate.md (runbook for the removed gate). Docs cleaned (no history/changelog touched): README.md drops CI Tour Gate link; pgvector_install.md replaces check_pgvector.sh with inline psql, removes the CI section, renumbers §6-§8; tools/README.md drops the brain_v3_ci_check.py section + pre-push runbook. Part of Wave 1 — PR #34. Succeed
merged M1 Wave 1: 3 security HIGH gap closure (trace ir.rule + nl_query sanitize + confirmation nonce) [REVERT] .github: back out CI runner switch — return to GitHub-hosted (PR #34) Per decision to abandon the self-hosted Viindoo Runbot switch (M1 W4/W6): - ci.yaml: restore all 5 jobs to runs-on: ubuntu-latest + setup-python steps - preflight-pgvector.yml: restore ubuntu-22.04 + original branch/path triggers Both files now match origin/17.0 byte-for-byte. Security fixes (trace ir.rule, nl_query sanitize, confirmation nonce) untouched. ai17 returns to GitHub-hosted runners; quota strategy handled separately. Part of Wave 1 — PR #34. Killed Not finished
merged M1 Wave 1: 3 security HIGH gap closure (trace ir.rule + nl_query sanitize + confirmation nonce) [FIX] viin_ai_*: root-cause boil-the-lake of /code-review findings — preflight self-hosted + SSOT + dedupe + aggregation fixture + nonce burn (M1 W6) Root-cause fix all 5 findings from /code-review of PR #34. Per boil-the-lake, no shortcuts. 1. preflight-pgvector.yml: switch runs-on from ubuntu-22.04 to [self-hosted, "Viindoo Runbot"]. Root cause of "preflight dead" was org-Free-tier GH Actions quota exhaustion, not workflow code (proven by run 26076812824 which succeeded in 38s before quota hit). Self-hosted Runbot has identical pgvector/pgvector:0.8.2-pg14 service container confirmed via brain-tours.yml. 2. viin_ai_search/controllers/search_controller.py: error message now uses MAX_NL_QUERY_CHARS constant via %d interpolation (SSOT — CLAUDE.md Rule 10). 3. viin_ai_base/tests/test_trace_acl.py: remove duplicate .browse().read() call in test_user_cannot_read_other_users_trace — the first call's result was discarded, dead code. 4. viin_ai_search/tests/test_search_controller.py: replace TODO stub with full integration test for the aggregation path — seeds topic+template+ provider, mocks call_completion, asserts <untrusted_context> wrap in the captured user message of the aggregation LLM call. 5. viin_ai_chat/controllers/chat_controller.py: nonce now single-use — _clear_pending_tool called on NONCE_MISMATCH to burn pending state. Adds AC10 test. Updates security.md §3.1 to document single-use semantics. Part of Wave 1 — PR #34. Killed Not started Not finished
merged [REF] all modules: switch to short version scheme (strip 17.0. prefix) [REF] all modules: switch to short version scheme (strip 17.0. prefix) Odoo recommends short version format (x.y.z) over full (17.0.x.y.z) so that porting to a new Odoo series requires no manifest version bump. - 11 __manifest__.py: strip 17.0. prefix - docs/ai/README.md, roadmap.md, conventions.md, migration.md: update version references and remove stale note about viin_ai_rag alignment - viin_ai_rag/migrations/17.0.0.1.0/pre-migrate.py: update docstring - viin_brain/tests: update migration version reference in comment Migration folder 17.0.0.1.0/ kept as-is (must match what Odoo stored in DB on existing installs). Killed
merged [REF] all modules: switch to short version scheme (strip 17.0. prefix) [REF] all modules: switch to short version scheme (strip 17.0. prefix) Odoo recommends short version format (x.y.z) over full (17.0.x.y.z) so that porting to a new Odoo series requires no manifest version bump. - 11 __manifest__.py: strip 17.0. prefix - docs/ai/README.md, roadmap.md, conventions.md, migration.md: update version references and remove stale note about viin_ai_rag alignment - viin_ai_rag/migrations/17.0.0.1.0/pre-migrate.py: update docstring - viin_brain/tests: update migration version reference in comment Migration folder 17.0.0.1.0/ kept as-is (must match what Odoo stored in DB on existing installs). Killed Not finished
merged [Phase 3.7] Gate M1 carry-over: SQL templates, aggregation router, AI Draft smart button, Brain bridge deprecate [FIX] viin_brain: remove orphan test_ir_http.py — ir_http.py deleted in f815901 (TipTap rejected) Commit f815901 deleted viin_brain/models/ir_http.py and its __init__ import when TipTap editor was rejected in favour of OdooEditor (ADR-003 update). The companion test file viin_brain/tests/test_ir_http.py was not removed, leaving 2 HttpCase tests (test_session_info_includes_editor_backend_flag, test_session_info_defaults_to_odoo_when_invalid) that assert on viin_web_editor_editor_backend in session_info — a key that no longer exists because the injector (ir_http.py) was deleted. Runbot build 381692 (rb-84f5047-221719) caught both failures: AssertionError: None != 'tiptap' AssertionError: None != 'odoo' Fix: delete test_ir_http.py and remove its import from tests/__init__.py. No functional change — the WI-11 classmethod regression guard is no longer needed since the override that triggered it no longer exists. Killed
merged [Phase 3.7] Gate M1 carry-over: SQL templates, aggregation router, AI Draft smart button, Brain bridge deprecate [REF] viin_ai_account,viin_ai_sale,viin_ai_stock: remove <delete> migration guards — no existing installs to upgrade Failed
merged [Phase 3.7] Gate M1 carry-over: SQL templates, aggregation router, AI Draft smart button, Brain bridge deprecate [FIX] viin_ai_account,viin_ai_sale,viin_ai_stock: add <delete> to remove legacy viin_ai_agent placeholder records on install (UniqueViolation fix) Killed Not started Not finished
merged [Phase 3.7] Gate M1 carry-over: SQL templates, aggregation router, AI Draft smart button, Brain bridge deprecate [FIX] viin_ai_agent: stock_on_hand template — use parent_path/view_location_id FK join instead of fragile name LIKE Failed
merged [DOC] Fix documentation drift — editor ADR (OdooEditor), stale state, nav breadcrumbs, Brain bridge timeline [DOC] docs: fix documentation drift — editor ADR, stale state, nav breadcrumbs, Brain bridge timeline Group A — Stale / Navigation (8 fixes): - REPO_LAYOUT.md: replace stale 2026-04-16 skeleton status with accurate Phase 0-3 / P0-P13 ship state - README.md: remove duplicate conventions row, add docs/README.md persona pointer, update date - docs/README.md: add breadcrumb back to root README - docs/brain/README.md: add breadcrumb, remove absolute local path from footer, update date - CONTRIBUTING.md: add Brain cluster onboarding step (step 7) - docs/ai/README.md: add note explaining viin_ai_rag version scheme divergence - docs/brain/data-models.md: add v1.0 note clarifying viin.brain.block is v1.1+ spec Group B — Architecture drift (6 fixes): - docs/decisions/adr-003-wysiwyg-path-b.md: update status Proposed→active; rewrite Decision section — OdooEditor proper extension (NOT TipTap); move TipTap to Alternatives Considered - docs/decisions/README.md: update ADR-003 summary to reflect OdooEditor + TipTap rejected - docs/roadmap.md: fix Track B W12-W17 TipTap→OdooEditor; fix Brain bridge deprecation timeline (W4-W6 bridges redundant, formal remove deferred to v1.2 per ADR-001) - docs/brain/architecture.md: add v1.0 interim callout (raw contenteditable, migration P16) - docs/history/wysiwyg-migration-progress.md: add SUPERSEDED banner (TipTap rejected) - viin_brain/docs/brain/contenteditable_policy.md: rewrite §8 to reflect OdooEditor decision, remove TipTap activation requirements, note tiptap_adapter.js deleted Group C — Code cleanup (1 artifact removed): - viin_web_editor/__manifest__.py: remove tiptap_adapter.js asset entry - viin_brain/models/__init__.py: remove ir_http import - viin_web_editor/static/src/adapters/tiptap_adapter.js: delete TipTap stub - viin_brain/models/ir_http.py: delete TipTap feature flag injector Killed Not finished
merged [DOC] Fix 7 doc conflicts: viin_ai_documents rescope, version pin, branch naming, encapsulation, stub cleanup [DOC] docs: fix 7 conflicts — rescope viin_ai_documents, fix version pin, branch naming, encapsulation, eliminate stub redirects C1: rescope viin_ai_documents from SKIP to Phase 7.4 Wave-C - architecture.md: depends documents -> viin_document (Viindoo Enterprise) - roadmap.md: add to Wave-C W28-W30; footnote fix; inventory 30->31; §10 count update C2: README.md: viin_api_request_logger >= 0.2 -> >= 0.1.1 (actual version in tvtmaaddons17) C3: CONTRIBUTING.md: clarify external vs internal branch naming convention C4: docs/conventions.md: add note that ai17 daily branch is 17.0 (not master) C5: docs/ai/operating-model.md §4.1: remove optional external deps from viin_ai_ops C6: docs/brain/README.md: update roadmap description (absorbed into C7) C7: eliminate 2 stub redirect files (docs/ai/roadmap.md, docs/brain/roadmap.md) - reroute all relative roadmap.md links in docs/ai/*.md and docs/brain/*.md to ../roadmap.md - fix stale anchor in observability.md - update frozen decision records historical notes - update docs/README.md mention of stubs Killed Not started Not finished
merged [DOC] docs: consolidate AI + Brain roadmap into unified W1-W30 plan [DOC] research/cowork-docs: restructure to match CoWork-OS repo layout Move 12 files from flat root into docs/ subdirectory to mirror the original CoWork-OS docs/ layout. The import had flattened this structure, creating 116+ broken links with docs/ prefix in root-level files. Files moved to docs/: - architecture.md, features.md, providers.md, core-automation.md - context-compaction.md, workflow-intelligence.md, heartbeat-v3.md - skills-runtime-model.md, knowledge-graph.md, memory-observations.md - operator-runtime-visibility.md, integration-skill-bootstrap-lifecycle.md Cross-reference fixes (8 links): - docs/architecture.md: managed-agents.md → ../managed-agents.md - docs/core-automation.md: permission-system.md → ../permission-system.md - docs/features.md: managed-agents.md → ../managed-agents.md - execution-runtime-model.md: bare architecture/features → docs/ prefix - permission-system.md: bare core-automation/architecture/features → docs/ prefix Result: broken links reduced from 213 to 185 (-28). Remaining 185 are Type 2 (files never imported from CoWork-OS — not fixable without importing additional source material). Killed Not finished
merged [DOC] docs: consolidate AI + Brain roadmap into unified W1-W30 plan [DOC] compact: merge ui-design pair + merge glossary into conventions A — Merge ui-design files: - docs/brain/ui-design-overview.md (190 lines) + ui-design-waves.md (528 lines) → docs/brain/ui-design.md (single spec, Overview + Component & Wave Specs sections). Removes cross-file navigation overhead. - Update references in brain/README.md, brain/architecture.md, brain/roadmap.md. B — Merge glossary into conventions: - docs/glossary.md (155 lines) absorbed into docs/conventions.md as new §Thuật ngữ section (terminology rules + 10 term tables for phases 3.8/3.9 + Cognitive Layer). - Remove duplicate "Vendor vs Provider" English dispatch section from conventions.md; keep the Vietnamese-focused table from glossary. - Update references in README.md, docs/README.md, docs/roadmap.md, CONTRIBUTING.md, SUPPORT.md, decisions/adr-004. Net: -3 files, -2 cross-file nav sections, conventions.md now single coding-standards-and-terminology reference. Killed Not finished
merged [DOC] docs: consolidate AI + Brain roadmap into unified W1-W30 plan [DOC] dead content cleanup: placeholders, history, orphan links - Remove screenshot placeholder sections from 3 module READMEs (viin_brain, viin_ai_brain, viin_brain_account_reports): TODO images violate ETHOS §4.4 visual evidence — remove until real screenshots exist. - Move 4 cancelled Phase 3.5 dogfood files to docs/history/ (CANCELLED). - Move 2 UAT files (2026-04-17) to docs/history/ (historical artifacts). - Update docs/history/README.md index with 6 new entries. - Fix wi-001-cluster-audit.md: Phase 3.5 status was "Not started" → "CANCELLED — zero legacy traffic; replaced by internal QA gate". - Rewrite docs/roadmap.md §1: remove historical narrative ("trước đây có hai roadmap song song...") — forward-looking only. - Add "See also" links in 3 docs to resolve orphaned files: docs/ai/security.md → phase1/phase2 security checklists docs/brain/security.md → conflict_registry + contenteditable_policy docs/ai/architecture.md → pgvector_install guide Killed Not finished
merged [DOC] docs: consolidate AI + Brain roadmap into unified W1-W30 plan [DOC] research/README.md: document external CoWork-OS origin + known dead-link limitation research/cowork-docs/ and research/cowork-skills/ are partial imports of the CoWork-OS repo (MIT), used as reference input for ADR-004 through ADR-008. Only a subset of CoWork-OS files was imported, so ~220 internal cross-links within those files are broken when navigating on GitHub. Add README explaining: - Source: CoWork-OS (MIT license) - Purpose: design reference, not production code - Known limitation: internal links broken (full import is out of scope) - Navigation workaround: use upstream CoWork-OS repo docs/ and all root .md files: verified 0 dead links. Killed Not finished
merged [IMP] viin_brain,viin_web_editor: UI hardening v1 (token + polish + Odoo-native + v2 seams) [IMP] viin_brain: extend TourCaseBase with _ensure_contracts_database (round 4 follow-up) Address Gap 2 from CEO intent review: 7 tour JS files hardcode :contains("Contracts Database") + :contains("Contract Alpha") selectors, making those tours fail with --without-demo=all even after Phase B switch to TourCaseBase. Per CEO directive (Boil-the-Lake max): seed the demo_db_page_contracts fixture inside cls._tour_vault so tours pass deterministically regardless of demo data state. _ensure_contracts_database() seeds (idempotent — prefer demo, fallback search, finally create): - Contracts Database page (page_type=database, icon 🗂️) - Status property (select with Draft/Review/Signed options) - Effective Date property (date) - Contract Alpha + Contract Beta child pages (Gamma omitted — tours reference only Alpha; Beta provides second row for List/Kanban) - Property values for Alpha (Status=Review, Date=2025-01-15) - Default database view (kind=list, is_default=True) Sets cls._contracts_db_page + cls._contract_alpha_page for subclasses. Tours now pass with both --without-demo=all and demo loaded: brain_database_view, brain_database_calendar_tour, brain_database_gallery_tour, brain_database_board_tour, brain_properties, brain_wikilink (line 97 Contracts Database step) WI14 cluster (graph_panel tour) already covered by test_brain_graph_panel_tour.py's own setUpClass — no fixture extension needed. Refs PR #27. Killed
merged [IMP] viin_brain,viin_web_editor: UI hardening v1 (token + polish + Odoo-native + v2 seams) [FIX] viin_brain: brain_ux_batch_a_tour line 127 indent 15→16 sp (round 4 follow-up) Off-by-1 from round 4 sprint A. Original CI stdout said "Insert ⏎···············" (displayed as 15 dots) but prettier 2.7.1 actually wants 16 spaces (12 parent + 4 sp continuation indent — standard Odoo eslint config printWidth=100, tabWidth=4). Verified local with prettier 2.7.1 (CI runbot version, /tmp/prettier-test): $ eslint --no-eslintrc -c web/tooling/_eslintrc.json \ --resolve-plugins-relative-to /tmp/prettier-test \ <4 round-4 fixed files> exit=0 Refs PR #27. Killed Not finished
merged [IMP] viin_brain,viin_web_editor: UI hardening v1 (token + polish + Odoo-native + v2 seams) [ADD] tools: brain_v3_ci_check Rule 12 — no demo ref in tests (round 4 sprint C) Add CI guard preventing reintroduction of env.ref('*.demo_*') in test files across all 14 ai17 modules. Rule scans tests/test_*.py and tests/*_tests.py, skipping: - Python comment lines (#-prefixed) - Multi-line docstring blocks (tracked via triple-quote parity) - Files containing the marker '# CI-RULE12-EXEMPT: <reason>' Wired into main checkers list. Strict-mode invariant updates from 8 PASS / 1 pre-existing WARN baseline → 9 PASS / 1 pre-existing WARN (rule2 contenteditable=14 unchanged). Verified: $ python3 tools/brain_v3_ci_check.py --strict ✓ rule12_no_demo_ref_in_tests: Zero demo refs in test files across 14 module(s); 0 file(s) exempt via marker. Refs PR #27. Killed Not finished
merged 17.0 cognitive layer docs [ADD] docs: Phase 3.9 Cognitive Layer — 5 capability + 5 ADR + 1 WI Adopts CoWork-OS patterns: Memory cross-session L0-L3, Skill system additive runtime, KG temporal validity, Pulse cost gate, CoWork skill bundle (140 skill, 15 sub-pack, drop ~7 game). ADR-004 Memory layered + observation sidecar + data residency opt-in ADR-005 Skill additive runtime + version semver + skill pack ADR-006 KG temporal validity + as_of trên 4 Odoo model ADR-007 Pulse cost gate option A (compliant WI-002) ADR-008 CoWork-OS skill adoption + provenance MIT->AGPL WI-004 Cognitive Layer integration + operational runbook Campaign: 2026-05-03-ai17-cognitive-layer Plan: ~/.claude/plans/reflective-snuggling-gosling.md Killed Not started Not finished
merged [IMP] viin_brain,viin_web_editor: UI hardening v1 (token + polish + Odoo-native + v2 seams) [IMP] viin_brain: P7 H4 fix + WI-4 universal injector wire (round 3 sprint 3) P7 H4 — content_html sanitize_attributes=False - Brain embed blocks use data-snapshot-id, data-snapshot-kind, data-block-anchor, data-is-stale, data-mode attributes that are NOT in Odoo's safe_attrs whitelist (odoo/tools/mail.py:44-55). - With default sanitize_attributes=True, html_sanitize() with safe_attrs_only=True strips all data-snapshot-* on every WRITE, breaking embed chrome render after save→reload. - Fix: explicit sanitize_attributes=False preserves data-* while sanitize_tags=True (implicit) still blocks script/iframe/object tags so XSS posture intact. - Verified via JSON-RPC ORM write of 950-byte embed HTML → read back returns 906 bytes with data-snapshot-kind + o_brain_snapshot_chrome--snapshot class preserved. WI-4 (ADR-001) Universal Brain sidebar injection — restored - Original __manifest__.py:270-271 declares "WI-4 (ADR-001) — universal hook injection for mail.thread descendants" but stage 1 (function definition) shipped without stage 2 (caller wiring) per git archaeology of commit 26f2190. - Per ETHOS §4.1.1 boil-the-lake: the function intent was clear, only the wiring was missing; restore (wire) rather than delete. - Rewrote brain_form_sidebar_universal.js to patch FormCompiler .prototype.compile() (not FormController) and mutate source arch this.templates[key] BEFORE super.compile(). Detection: presence of <div class="oe_chatter"> proxies for mail.thread descendant (= has brain_page_count via mail_thread.py inheritance). Guards against double-inject (existing .o_brain_form_sidebar_hook from bridge XML) + WeakSet on processed templates. - Verified on 2 models with NO bridge XML: * project.project (Office Design ID=1) — BRAIN rail sidebar auto-renders * crm.team (Sales ID=1) — BRAIN rail sidebar auto-renders - Existing 5 bridges (res.partner, crm.lead, hr.employee, project.task, sale.order) continue to work unchanged — hookAlreadyPresent guard prevents double injection. NOTE — separate page_editor render race exists: bodyRef.el.innerHTML stays empty despite state.page.content_html containing 906 bytes after ORM write. JSON-RPC verifies content delivery; OWL render does not materialize. Investigation deferred — not introduced by this commit; unrelated to H4 sanitization fix. NOTE — universal injector stat button (Brain Pages count) appears on forms with <div name="button_box"> but the inserted <field name= "brain_page_count" widget="statinfo"> child does not visually render in project.project capture. Sidebar (primary deliverable) works on both test models. Stat button compilation pipeline interaction worth follow-up; sidebar functionality unblocked. AC-1 hex grep PASS, brain_v3_ci_check.py --strict 8 PASS / 1 pre-existing WARN (rule2 contenteditable baseline = 14 unchanged). Refs PR #27. Failed
merged 17.0 cognitive layer docs [ADD] docs: Phase 3.9 Cognitive Layer — 5 capability + 5 ADR + 1 WI Adopts CoWork-OS patterns: Memory cross-session L0-L3, Skill system additive runtime, KG temporal validity, Pulse cost gate, CoWork skill bundle (140 skill, 15 sub-pack, drop ~7 game). ADR-004 Memory layered + observation sidecar + data residency opt-in ADR-005 Skill additive runtime + version semver + skill pack ADR-006 KG temporal validity + as_of trên 4 Odoo model ADR-007 Pulse cost gate option A (compliant WI-002) ADR-008 CoWork-OS skill adoption + provenance MIT->AGPL WI-004 Cognitive Layer integration + operational runbook Campaign: 2026-05-03-ai17-cognitive-layer Plan: ~/.claude/plans/reflective-snuggling-gosling.md Killed Not finished
merged [IMP] viin_brain,viin_web_editor: UI hardening v1 (token + polish + Odoo-native + v2 seams) [IMP] viin_brain: P6 brand parity + P9 ShareDialog polish (round 3 sprint 2) P6 Properties — scope brand cyan to .o_brain_app .btn-primary - Add explicit cascade override in _app_shell.scss (Bootstrap 5.1.3 compiles .btn-primary to hex literals so --bs-primary scope override has zero effect; explicit property cascade is the only safe approach). - Switch '+ Add property' button class btn-light → btn-primary so it picks up the brand accent. Hover via color-mix() (same darkening visual as $darken-10% on Bootstrap baseline). - Scope is .o_brain_app to prevent leak into form/list views in sibling apps that share global Bootstrap tokens. P9 ShareDialog — iOS-style switch + dynamic title - Replace native <input type='checkbox'> for 'Public link' with OWL CheckBox component using Bootstrap 5 form-switch class (matches Odoo 17 boolean_toggle_field iOS-pill pattern). - Load page name via Promise.all alongside share-link search; render Dialog title 'Share <Page Name>' via dialogTitle getter (was hardcoded 'Share this page'). - onToggleLink signature updated for OWL CheckBox onChange contract (passes value, not DOM event). Evidence (visual-evidence MCP, ephemeral): - Session 20260503-2016-p8r3-sprint1-final shot-005: P11 CRM Lead ID=13 form sidebar rail mode renders with Brain stat buttons. - Session 20260503-2031-p8r3-sprint2-polish shot-002: P11 Project Task ID=1 form sidebar rail mode renders with Brain Pages + Brain Note stat buttons. - Session 20260503-2031 shot-005: P9 ShareDialog title 'Share Welcome' + iOS-switch toggle render confirmed. - Round 3 deferred items documented in phase-8-retroactive-evidence.md. AC-1 hex grep PASS, brain_v3_ci_check.py --strict 8 PASS / 1 pre-existing WARN (rule2 contenteditable baseline = 14, unchanged). Refs PR #27. Failed
merged [IMP] viin_brain,viin_web_editor: UI hardening v1 (token + polish + Odoo-native + v2 seams) [FIX] viin_brain: P11 BrainFormSidebar visible — display:contents wrapper Pre-existing P11 gap surfaced by P8 round 3 capture verification: BrainFormSidebar (panel/rail/strip layout modes) was completely invisible on every bridge form (HR Employee, Sale Order, CRM Lead, Project Task) despite the bridge XML hook + form_compilers registry entry + OWL component being correctly wired. Root cause: - brain_form_sidebar_compiler.js wraps the OWL component instance in <div class="o_brain_form_sidebar_container">, then appends that wrapper alongside the chatter container under parentEl(o_form_sheet_bg) — exactly matching mail's chatter pattern. - The wrapper had NO matching CSS rule in brain_form_sidebar.scss. - Default block layout: width:100% + display:block. - The form's flex-flow row container (.o_form_view.o_xxl_form_view, form_controller.scss:1099) treated the wrapper as a full-width row child, pushing the actual sidebar (.o_brain_form_sidebar.--{panel, rail,strip}) off the visible flex track. On standard desktop this put the sidebar below the page content, frequently off-viewport. Fix: - Add display:contents on .o_brain_form_sidebar_container so the wrapper participates in DOM but disappears from layout — its single child .o_brain_form_sidebar.--{mode} becomes the direct flex sibling of o_form_sheet_bg and o-mail-Form-chatter, matching the layout intent expressed in the compiler's append() call. Verified via Visual Evidence MCP session 20260503-1931-brain-ui-p8r3-batch4 on Sale Order S00007 at 1600x1100 viewport (≥SIZES.XXL → rail mode): - shot-002: rail collapsed (44px vertical "BRAIN" label) on far right alongside chatter - shot-003: rail expanded (320px panel) showing "Brain · Knowledge linked to this record" header + "PAGES MENTIONING THIS RECORD" section + empty state + "+ Create a note about this record" CTA — matches mockup P11 (docs/brain/mockups/v3/screenshots/P11.png) structurally. Brain v3 CI: 8 PASS / 1 pre-existing WARN (rule2 contenteditable). AC-1 hex grep: 0 violations (display:contents is a CSS keyword, no literals introduced). Refs PR #27. Failed
merged [IMP] viin_brain,viin_web_editor: UI hardening v1 (token + polish + Odoo-native + v2 seams) [FIX] viin_brain: P8 round 3 — ShareDialog uses dialog.add() service Pre-existing OwlError "Cannot make the given value reactive" surfaced in P8 round 3 boil-the-lake captures: clicking Share in the page header consistently overlayed the full-page Odoo Client Error. Root cause: <ShareDialog/> was rendered directly inside the BrainApp template via t-if="state.showShareDialog". Odoo 17 base Dialog.setup() calls useState(this.env.dialogData), and dialogData is only injected when a dialog is opened through the dialog service (DialogWrapper + WithEnv). With direct child rendering, env.dialogData is undefined and useState(undefined) throws. Refactor to canonical Odoo 17 pattern (per @web/core/dialog/dialog and ConfirmationDialog reference): open ShareDialog imperatively via dialog.add(), let the service inject `close` and provide env.dialogData. Changes: - brain_app.js: useService("dialog"); onOpenShare() now calls this.dialog.add(ShareDialog, {...}); state.showShareDialog and onCloseShare removed; ShareDialog dropped from static components. - brain_app.xml: removed <ShareDialog/> render block (replaced with a comment explaining the imperative-open requirement). - share_dialog.js: props.onClose -> props.close (service-injected); prop schema updated. - share_dialog.xml: <Dialog onClose=...> attribute removed (Dialog closes itself via env.dialogData); Cancel button calls props.close(). Verified via Visual Evidence MCP session 20260503-1844-brain-ui-p8r3-batch2: ShareDialog now opens cleanly with public-link toggle visible (shot-004). Brain v3 CI: 8 PASS / 1 pre-existing WARN (rule2 contenteditable baseline). AC-1 hex grep: 0 violations. Refs PR #27. Killed Not finished
merged [IMP] viin_brain,viin_web_editor: UI hardening v1 (token + polish + Odoo-native + v2 seams) [FIX] viin_brain: P8 retroactive UI polish — selected highlight + breadcrumb path Root cause for missing sidebar-active highlight: the brand-accent token chain `--o-brain-accent: var(--o-brand-primary, var(--bs-primary))` referenced CSS custom properties that Odoo 17 only exposes as Sass compile-time variables, never as runtime `:root{--bs-primary}`. The chain therefore resolved to nothing, `color-mix(in srgb, var(--o-brain- accent) 12%, transparent)` evaluated to fully transparent, and the `.o_brain_page_node.active > .o_brain_page_row` rule painted a zero-alpha background — making the active page indistinguishable from its neighbours even though the `.active` class was correctly added. The Viindoo Odoo 17 build exposes the runtime brand colour as `--primary` (Viindoo cyan #00bbce) plus the theme slot `--o-color-1`. Re-chain `--o-brain-accent` to `var(--primary, var(--o-color-1))` so the brand colour reaches every downstream token (`--o-brain-bg-hover`, `--o-brain-bg-selected`, focus rings, presence palette, AI badge, chip styles). Reviewer-side capture (commit binding via Visual Evidence manifest) now shows a visible cyan tint on the selected row — pixel sample (213, 239, 243) at 14% accent over light gray sidebar bg. Defensive `Number()` cast in `rowClass()` keeps the active class attached even when `activePageId` arrives as a string from URL hash or localStorage restore (was not the original culprit but cheap to keep). Breadcrumb now appends the current page name as a final segment so the visible breadcrumb reads `Vault › [Folder ›] Page` instead of just `Vault`. `breadcrumbDisplay.fullPath` (tooltip on truncated chains) tracks the same change so the tooltip stays consistent with the rendered breadcrumb. Tour AC-P7-2 (root page) updated to expect exactly 1 separator + a non-empty `.o_brain_breadcrumb_current` segment; AC-P7-3 (truncated deep path) tooltip expectation extended with the leaf page name. Evidence (P8 retroactive, reviewer-side, ephemeral 24h auto-cleanup): - session 20260503-1735-brain-ui-verify-g1-jsfix - shot-005-verify-g1-final-r2.png — sha256 9e438c47… - sidebar Welcome row paints (213, 239, 243) cyan tint vs Contracts row (118, 124, 129) plain gray (control sample) - breadcrumb header reads "Personal › Welcome" CI gate: brain_v3_ci_check.py --strict — 8 PASS, 1 pre-existing WARN (rule2_contenteditable in test file, unrelated). AC-1 hex grep PASS (0 hex in components/apps SCSS). Failed
merged [IMP] viin_brain,viin_web_editor: UI hardening v1 (token + polish + Odoo-native + v2 seams) [FIX] viin_brain: P8 revert ShareDialog collab seam wiring (pre-existing Share crash) P8 retroactive visual-evidence run captured ShareDialog crash on Share button click (Odoo Client Error). Initial hypothesis: P7 added `<t t-slot="collabSection"/>` caused regression. Root-cause analysis via baseline test on `~/git/ai17` at branch 17.0 (no hardening changes) showed identical crash hash on Share button click — **pre-existing bug**, NOT introduced by P7. Pre-existing crash blocks any in-place verification of the collab seam wiring. Reverted the JS slots prop + XML t-slot: - share_dialog.js: removed `slots: { type: Object, optional: true, shape: { collabSection: ... } }` from static props. - share_dialog.xml: removed `<t t-slot="collabSection"/>` and the earlier guarded `<t t-if=...><t t-slot/></t>`. Replaced with a `<!-- v2 inject point -->` comment marker as anchor for v2 xpath-inheritance. Updated docs/brain/v2-extension-points.md (seam #4) to: - Mark seam as DOC-ONLY in v1. - Document v2 attach pattern requiring (a) fix pre-existing Share crash first, (b) patch ShareDialog props to add slots, (c) xpath inherit template to inject t-slot at the comment marker. Other 5 P7 seams (presence palette, GraphPanel canvas mount, AIBlock state registry, Property type registry, Decorator providers doc) remain wired in v1 and verified via compiled-CSS evidence in P8 retroactive run (15x `0.15s ease` transitions, 68x `:focus-visible` rules, 8x `--o-brain-presence-color-1..8` vars, etc.). Phase: P8 convergence (visual-evidence retroactive) Pipeline: 20260503-brain-ui-hardening-v1 Plan: ~/.claude/plans/parsed-spinning-peacock.md Failed
merged [IMP] viin_brain,viin_web_editor: UI hardening v1 (token + polish + Odoo-native + v2 seams) [FIX] viin_brain: P8 remove duplicate imports in v2 extension seams test P7 added side-effect imports for ai_block_states and property_types registries followed by named imports from the same modules. The named imports already trigger module side-effects on first import, so the side-effect imports are redundant and trip eslint no-duplicate-imports. Verified registries call registry.add() at module top level; named import alone is sufficient. Fixes 2 NEW eslint errors discovered by P8 full-suite run. All other P8 test failures (11 TestBrainAclPortalShare + 4 TestCollabStepController + tour tests + 1 TestPyLint W0012) confirmed pre-existing on baseline 17.0 — NOT caused by this hardening pipeline. Verified via dedicated baseline runs on ~/git/ai17 at branch 17.0 (see ops/logs/runs/p0-baseline-* + dropdb cleanup). Phase: P8 convergence Pipeline: 20260503-brain-ui-hardening-v1 Plan: ~/.claude/plans/parsed-spinning-peacock.md Failed
merged docs: fix 4 broken viinforge cross-repo refs (DRY into conventions.md) [FIX] docs: replace 4 broken viinforge cross-repo refs with in-repo conventions section Pre-existing issue surfaced by post-merge audit of PR #24: 4 module READMEs (viin_brain, viin_ai_brain, viin_brain_account_reports, viin_web_editor) had identical paragraph linking to `../knowledge/viindoo/modules/viin_brain_v17_reuse_contract.md` — a file that lives in the viinForge repo, breaking when ai17 is checked out standalone. Resolution: - Add new section `§Brain JS/OWL — Odoo 17 import paths` (anchor `#brain-js-owl-imports`) to docs/conventions.md with the critical rule inline (use `@web_editor`, not `@html_editor` — v18+ only, silent blank-page JS resolution error). - Reference viinForge reuse-map doc as plain-text mention (not a markdown link) — viinForge is optional reference, not required for build/run. - Replace 4 README paragraphs (each 8 lines) with 1-line link to the conventions section. Net: 4 broken markdown links -> 0; copy-pasted bullet 4 places -> 1 canonical source; standalone ai17 checkout works. Killed Not started Not finished
merged docs(brain): index orphan ci-tour-gate.md + waves pointer [FIX] docs(brain): index ci-tour-gate.md in README The CI Tour Gate Infrastructure doc has been orphan since it was created (commit 825fae9, 2026-04-29 — pre-existing, surfaced by the post-merge audit of PR #24). Add it to the brain/README.md nav table. Also add explicit pointer from UI Design row to ui-design-waves.md (currently reachable in 2 hops via overview; this makes wave detail discoverable in 1 hop). Killed Not started Not finished
merged docs: compact and restructure ai17/docs (symmetric ai/ + brain/, integration.md, drift fix) [FIX] Update doc references outside docs/ for new paths After the docs/ restructure (commit dbb29f6), 13 files outside docs/ still pointed to old paths. Update them all: - README.md, REPO_LAYOUT.md, CONTRIBUTING.md, SUPPORT.md (top-level) -> docs/ai/{architecture,data-models,security,observability, operating-model,roadmap}.md - viin_ai_rag/__manifest__.py + viin_ai_rag/models/source.py - viin_ai_agent/models/agent.py + source_ext.py - viin_brain/CHANGELOG.md (release notes path) - viin_brain/docs/brain/contenteditable_policy.md (ADR-003 + wysiwyg progress) - viin_ai_base/docs/uat/checklist_2026-04-17.md - docs/decisions/wi-002-phase-3-7-vs-3-8.md (file:line citations) - docs/brain/graph.md (display label) Module-internal docs that already use stable docs/brain/* paths (viin_brain/models/*.py, viin_brain/tests/, viin_ai_brain/models/brain_page.py, viin_web_editor/tools/block_parser.py, ops/conflict_registry.md) require no change — those targets are unchanged by the restructure. Killed Not finished
merged docs: compact and restructure ai17/docs (symmetric ai/ + brain/, integration.md, drift fix) [FIX] docs(brain): remove ghost reference _drift_audit_2026-04-29.md The file docs/_drift_audit_2026-04-29.md never existed in this repo (was an artifact of campaign 2026-04-29 in viinforge). Replace the broken link with a reference to decisions/wi-001-cluster-audit.md, which is the audit summary card that IS in repo. After this, all internal markdown links resolve (broken-link gate returns 0). Killed Not finished
merged [ADD/FIX] viin_ai: Phase 3.5 hardening + Phase 3.7 features (SRS v1.1 follow-up) [FIX] cluster ai17: align prettier trailingComma to es5 (CI default) Runbot build 221688 build 381380 reported 261 prettier "Insert `,`" errors after build 221687's fix added trailing commas via local prettier --trailing-comma=all. Root cause: local eslint resolves eslint-plugin-prettier@5.5.5 from /home/tuan/node_modules (bundled prettier 3.x → default trailingComma=all), while the cluster-local node_modules carries eslint-plugin-prettier@4.2.5 with prettier 2.8.8 whose default is trailingComma=es5. CI runbot uses the cluster-local plugin chain (matches package.json), so trailing commas in function calls/parameters trip "Insert `,`" with all but "Delete `,`" with es5. Re-ran prettier 2.8.8 with no --trailing-comma override on all 149 ai17 static JS files; 76 files re-formatted (+261 −264 lines). Verified locally with eslint --resolve-plugins-relative-to ai17 (forces v4.x resolution that matches CI) → 0 errors on full set. Out of scope: - Build 381388 MemoryError on web/tests/test_assets.py test_logs_assets_generate_time during JS bundle minify is a runbot infra flake (Odoo upstream test, not in 221687 on same branch); net prettier delta of -3 lines cannot tip memory budget. Will retry on next build. Killed
merged [ADD/FIX] viin_ai: Phase 3.5 hardening + Phase 3.7 features (SRS v1.1 follow-up) [FIX] cluster ai17: address runbot lint + sql_template ACL failures (build 221687) CI runner Viindoo runbot exposed real failures on PR #23 commit abcb66e that local Chrome-flaky test runs had hidden: * test_pylint test_eslint (267 violations) — eslint v6 on dev box could not parse the ``es2022`` env key so every lint check silently exited config-error; CI runs eslint v8 cleanly. * test_pylint test_flake8 — 2 unused name lints * test_pylint test_pylint — UserError missing translation * viin_ai_agent.tests.test_sql_template — postgres ``operator does not exist: jsonb ~~ unknown`` on ``res_partner.name LIKE ...`` Fixes: page_editor.js:1484 — drop unused catch binding ``_err`` (eslint no-unused-vars). The empty ``catch {}`` form is supported since Odoo 17 ships ECMAScript 2019+ asset bundles. mail_compose_message.py:19 — drop unused ``api`` import (no decorators in this module). test_sql_template.py:156-193 — restore ``p_visible`` local (was flagged unused after the names→ids assertion rewrite). Switch the SQL template to ``name::text LIKE '%%TPL-%%-PARTNER%%'`` and the Python assertion to compare ids: in Odoo 17 ``res_partner.name`` is a translated ``Char``, persisted as jsonb (e.g. ``{"en_US": "TPL-VISIBLE-PARTNER"}``), so the previous direct ``name LIKE`` invokes the missing ``jsonb ~~`` operator. The ``::text`` cast matches the JSON-serialised form regardless of which language key the row uses, and asserting on ids removes the test's reliance on a specific language key in the SELECT clause. test_parallel_tool_execution.py:25 + :366 — wrap the boom string in ``_(…)``. Test fixtures still flow through Odoo's UserError translation path so pylint's ``odoolint-translation-required`` rule needs to see ``_()`` even on hard-coded test text. Tour JS files (brain_content_type_tokens, brain_floating_toolbar, brain_slash_autosave, brain_slash_focus) — additional prettier trailing-comma + parenthesis fixes that eslint v8 ``--fix`` surfaces over the v6 configuration error. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Failed
merged [ADD/FIX] viin_ai: Phase 3.5 hardening + Phase 3.7 features (SRS v1.1 follow-up) [IMP] cluster ai17: PR23 round 3 follow-up — Chrome timeout mixin, QUnit guard, tour bugs, prettier Round 3 follow-up after PR #23's first 9 fixes shipped — addresses 2 issues exposed by reviewer round 2 plus a batch of tour bugs that became visible once Chrome devtools port detection had enough time to start in the local heavy-bundle environment. T1 — BrowserTimeoutBoostMixin (viin_brain/tests/common.py) * Module-level snapshot of odoo.tests.common.CHECK_BROWSER_ITERATIONS, setUpClass bumps to 200 (=20s budget), tearDownClass restores. Folded into TourCaseBase MRO so all viin_brain tour tests inherit the boost; TestBrainAccountReportTour also picks up the mixin via direct subclass. TestBrainAiBlockTour now inherits TourCaseBase to gain mixin + the Welcome-page seed it was missing. * Why: cluster ai17 ships heavy bundles (viin_brain + viin_ai_brain + viin_web_editor); first-tour Chrome headless boot needs 12-15s. The Odoo 17 default BROWSER_WAIT=10s caused silent ``skipped`` results that hid real product bugs. T2 — QUnit guard for BacklinkPanel.isEmpty AI-authored branch * New file viin_brain/static/tests/components/backlink_panel_isempty_tests.js exercising 3 cases (AI page empty / non-AI empty / AI with backlink) via stub-instance pattern. Registered in __manifest__.py. * Why: the ``&& !this.state.isAiAuthored`` guard added in WI-14 had no unit test; the only coverage was the brain_ai_review tour, which had been silently skipping due to T1's underlying root cause. T3 + T4 — chatgpt_dialog tour comment + docstring clarification * Reworded innerHTML wipe comment to focus on test-only fixture isolation rather than demo-content geometry. * Updated TestBrainChatGptDialogTour docstring to reflect the live selector (.o_brain_sidebar) and explicit MockedProviderMixin wiring. Prettier 2.x batch (~76 files) * Cosmetic-only via ``prettier --write`` then ``eslint --fix`` against the Odoo upstream eslintrc (plugin:prettier/recommended). No logic changes — eslint v8 strict mode would have failed without these. Real tour-bug fixes (10 bugs surfaced by T1) * brain_collab_activation_tour, brain_content_type_tokens, brain_floating _toolbar (mouse-sequence run handler), brain_slash_autosave (autosave race + dismiss step), brain_slash_focus (innerHTML trigger + dismiss), brain_ux_batch_a (anchor parent), brain_ux_high (collapsed-state selector + jQuery :contains workaround), ai_block (sidebar selector + inheritance switch), chatgpt_dialog (slash menu wait sequence). * Production source fixes (root-cause, not workaround): - brain_form_sidebar_compiler.js: ``compile(key, params)`` — ``key`` is a string identifier, not a DOM node. Old ``key.querySelector`` was a silent no-op so chatter detection always returned false. Now scans the compiled ``res`` DOM for ``.o-mail-Form-chatter`` (mirrors mail's own compiler). - page_editor.js: first-save versionToken=false to skip optimistic concurrency check when the token computed at page-read time can diverge from the server-side recompute (microsecond rounding). FIXME marker tracks restore once compute determinism is fixed. - page_context_menu.js: ``useExternalListener`` import path — ``@odoo/owl`` (not ``@web/core/utils/hooks``). - ai_bridge_service.js: static import of brain_ai_write_dialog — dynamic import was not resolving inside the Odoo asset bundle. * 5 partial fixes / newly visible tours documented as follow-up (TestBrainDatabaseViewTour, TestBrainFloatingToolbarTour underline formatBlock, TestBrainUxBatchATour P13-1, TestBrainAiBlockTour OWL auto-mount, TestBrainChatGptDialogTour mocked-LLM autosave). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Failed
merged [ADD/FIX] viin_ai: Phase 3.5 hardening + Phase 3.7 features (SRS v1.1 follow-up) [FIX] viin_ai_brain: chatgpt_dialog tour replaces dead vault selector and slash-trigger The chatgpt_dialog tour was failing on three pre-existing issues that together blocked the entire run: 1. ``.o_brain_vault_item`` is a dead selector — VaultSidebar now renders ``<select class="o_brain_sidebar_vault_select">`` and auto-selects the first vault when only one exists. The tour now waits for ``.o_brain_sidebar`` instead and lets the auto-select happen. 2. ``run: "text /ai_write"`` only works on input/textarea — the editor body is a contenteditable div, so the legacy helper threw ``$element.focusIn is not a function``. Synthesise the keystroke by appending a fresh text node, placing the caret at its end, and dispatching the ``input`` event the editor listens on. 3. The post-tour assertion silently no-op'd when ``demo_page_welcome`` was absent. Reuse ``TourCaseBase`` (which now backfills the Welcome page) so the assertion always runs, and make the test class actually inherit it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Failed
merged [ADD/FIX] viin_ai: Phase 3.5 hardening + Phase 3.7 features (SRS v1.1 follow-up) [FIX] viin_ai_chat: widen exception tuple in AI draft attribution path message_post can raise ValueError (subject/recipient validation) and UserError (sender email config) per Odoo CE 17 mail_thread.py. Previous narrow tuple (AccessError, MissingError) caused user to lose draft when hitting these. Expanded to keep best-effort attribution intent. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Failed
merged [ADD/FIX] viin_ai: Phase 3.5 hardening + Phase 3.7 features (SRS v1.1 follow-up) [FIX] viin_ai_chat: tour menu xmlid typo (legacy cleanup) Tour tour_c2_ux_newbie_onboarding searched for an Apps tile with data-menu-xmlid='viin_ai_base.menu_root_viin_ai', but the actual xmlid declared in viin_ai_base/views/menus.xml is 'menu_root_ai'. Mismatch surfaced as a tour failure on every install — pre-existing legacy typo (not caused by this campaign). Plan §"Quy tắc fix legacy errors/warnings" allows root-cause fixes in cluster viin_ai_*; this is a 1-character correction with zero behavioural change beyond letting the tour find its target. Failed
merged [Campaign] Brain v17 Complete: v1.4 + v2.0 Foundation — WI-1..WI-11 [FIX] viin_ai_agent: contain UNIQUE constraint test in cr.savepoint to prevent transaction poison The test_tool_technical_name_unique negative-path test triggered a psycopg2 IntegrityError without isolating it via cr.savepoint(). The poisoned outer transaction surfaced an ERROR-level odoo.sql_db log line that the runbot post-install sweep tagged as failure (PR #22 build campaign-brain-v17-complete-...221679, "duplicate key value violates unique constraint viin_ai_tool_viin_ai_tool_technical_name_unique"). Apply the canonical pattern already used in viin_brain test suites (test_brain_property, test_brain_tag, test_brain_template): wrap the violation in env.cr.savepoint() and silence the expected ERROR log via mute_logger('odoo.sql_db'). Tighten the assertion from bare Exception to psycopg2.IntegrityError. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Killed Not finished