Claude Doctor Updates

This commit is contained in:
Renn F
2026-07-29 16:38:49 +02:00
parent 95e7d5df7c
commit f99215213a
5 changed files with 62 additions and 189 deletions
+11
View File
@@ -0,0 +1,11 @@
---
paths:
- "roboco/services/vault*.py"
- "roboco/vault/**"
- "roboco/vault_assets/**"
- "roboco/foundation/policy/vault_notes.py"
---
# Obsidian vault (V1+V2)
**Obsidian vault V1+V2 (default-off).** The org's human-readable memory palace as a rebuildable DB projection — tasks, journals, and A2A digests as wikilinked markdown — gated by `ROBOCO_OBSIDIAN_VAULT_ENABLED` + `ROBOCO_VAULT_PATH` (default off, but both compose files arm it `true`). `VaultWriter` (`roboco/services/vault_writer.py`) is a pure, DB-free materializer under `RoboCo/{Tasks/<project-slug>,Journals/<agent-slug>,A2A,Agents,Archive/<year>/Tasks/<project-slug>,Reports}/`; every note carries a stable `aliases: [<id8>]` so a title rename (or an archival move) never breaks a `[[id8|title]]` cross-link, and private journals are excluded. Four best-effort event seams (`TaskService.create`'s materialize-on-create, `TaskService`'s status-transition frontmatter touch, `JournalService`, `A2AService`) patch/append on the relevant transition — a vault write failure never blocks the real action; materialize-on-create means a task's note exists from the moment it's created, not just at curation/rebuild. `python -m roboco.vault rebuild` re-projects every entity from the DB (preserving an existing task's Auditor-authored `## Narrative`, archive-aware so an old terminal task lands directly in `Archive/<year>/`) and materializes the shipped `.obsidian/` config (Dataview, Kanban, graph groups) + `RoboCo/_meta/` dashboards + `.base` Bases views from `roboco/vault_assets/`; `relocate <path>` moves the tree, grafting `RoboCo/` into an existing personal vault without touching its own config. The Auditor gets a one-shot `curate_vault(task_id, narrative)` do-tool, spawned by the orchestrator on each completed root task, writing the `## Narrative` section a deterministic write otherwise leaves as a placeholder. A second, independently-gated `ROBOCO_VAULT_INTAKE_ENABLED` watcher (`VaultIntakeEngine`) turns `#roboco`-tagged notes under the vault's inbox folder into PENDING, Product-Owner-assigned board-review drafts (`source=vault_note`) — the identical board-review path a chat-confirmed draft takes, never straight into delivery. Extraction runs on the local model with a deterministic fallback; the note body is screened through `foundation/policy/injection_guard.screen_external_text` (the same untrusted-content envelope `XEngine` applies to X mentions — flags an injection-pattern line inline, never removes content) before it reaches the prompt or the fallback. Deduped per `(vault-relative path, content hash)` via `vault_seen_notes`, so an edit re-qualifies a previously-seen note — the same hashing convention (every RoboCo feedback callout stripped first, `foundation/policy/vault_notes.py`) is now shared with the KB engine below. V2 adds three things on top: a **drift janitor** (`services/vault_janitor.py`, `_vault_janitor_loop`) hourly-ticked but gated by a `RoboCo/_meta/.janitor_state.json` state file so real work (a daily changed-task re-projection + random-sample drift check + archival pass, each capped at 200/cycle and per-item isolated so one bad row never wedges the sweep) and a weekly org-report (`vault_report_enabled`, default true — `VaultWriter.write_org_report` from `MetricsService`/`UsageService`, best-effort CEO notification) each fire exactly once per elapsed period regardless of loop/restart cadence; **archival** (`vault_archive_days`, default 30, `0`=off) moving old terminal tasks' notes into `RoboCo/Archive/<year>/Tasks/<project>/` during the sweep, alias links making the move free and the shipped Dataview/graph assets `Archive/`-aware; and **KB ingest** (`vault_kb_enabled`, default false — NAS compose arms it `true`, registry compose leaves it `false`) embedding the CEO's own `RoboCo/Notes/` (config `vault_kb_dirs`, csv, load-time-validated against traversal/overlap with reserved projection dirs) into a new `IndexType.VAULT_NOTES` corpus via `_vault_kb_loop` (`services/vault_kb_engine.py`, default 900s), with every note re-checked for symlink/path-escape at read time and screened through the injection guard as a hard GATE (a flagged note is quarantined — skipped, logged, callout-marked, never embedded) rather than the intake watcher's screen-and-still-process posture — reaching `roboco_kb_search`, `MentorService`'s default domain, and `EvidenceRepo.similar_memory` (claim-time briefings, relevance-floored, labeled `vault_note`) so the CEO's own writing finally becomes fleet-retrievable institutional memory.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -165
View File
File diff suppressed because one or more lines are too long
Generated
+24 -24
View File
@@ -129,11 +129,11 @@ wheels = [
[[package]] [[package]]
name = "annotated-doc" name = "annotated-doc"
version = "0.0.4" version = "0.0.5"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" } sdist = { url = "https://files.pythonhosted.org/packages/5a/8e/38aa427ed5402449e226975b649c5dc73ccadfefeb95e6aecb8f8ea4b6b6/annotated_doc-0.0.5.tar.gz", hash = "sha256:c7e58ce09192557605d8bbd92836d7e1d520ac9580096042c0bfd197efacf1bb", size = 10758, upload-time = "2026-07-28T13:50:58.129Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" }, { url = "https://files.pythonhosted.org/packages/3e/30/e900b21425a860e195f32e37657aa1f7c7f2b1bfb26f03ca209b90933c06/annotated_doc-0.0.5-py3-none-any.whl", hash = "sha256:117bac03a25ede5df5440e855b32d556049ca169ead221505badf432fed4b101", size = 5302, upload-time = "2026-07-28T13:50:57.239Z" },
] ]
[[package]] [[package]]
@@ -147,7 +147,7 @@ wheels = [
[[package]] [[package]]
name = "anthropic" name = "anthropic"
version = "0.120.0" version = "0.120.2"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "anyio" }, { name = "anyio" },
@@ -159,9 +159,9 @@ dependencies = [
{ name = "sniffio" }, { name = "sniffio" },
{ name = "typing-extensions" }, { name = "typing-extensions" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/92/5c/3331da4fc009d448008a50c78d86cc929e8c937cd1442245ce3f80561c4e/anthropic-0.120.0.tar.gz", hash = "sha256:6ba6007dc9b00365b20f6101a6618f5196ac1ceef81512e4b5cc0e7436d4975d", size = 1008042, upload-time = "2026-07-24T16:32:52.384Z" } sdist = { url = "https://files.pythonhosted.org/packages/d7/10/4ca013cb166f226bd89e0aeb0fcaff94f45ddf716d4925ce89475d3c587b/anthropic-0.120.2.tar.gz", hash = "sha256:9722efc10c27a30a69f5338ddacdb35bc6a64297a4e4ba729bf83af873d5fb3a", size = 1008421, upload-time = "2026-07-28T17:38:26.986Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/1b/8a/8522bdf809e1f95f0d9c936540987a3f6afba01d2921a2bf488dedf836a8/anthropic-0.120.0-py3-none-any.whl", hash = "sha256:591bd531563ec7b63a1e138f5c11f14cb94edda99623b349c2ce2ece8e08b8a5", size = 1022602, upload-time = "2026-07-24T16:32:50.506Z" }, { url = "https://files.pythonhosted.org/packages/63/af/0f5db57b9397a0f3b7fc204cbef143401a7cadaf982330f97f1ce3d39f34/anthropic-0.120.2-py3-none-any.whl", hash = "sha256:0f0bc2b381dc0eb41c8d886b815d79c2041cd2374f83aed36f574b6dc9c579c1", size = 1022851, upload-time = "2026-07-28T17:38:25.466Z" },
] ]
[[package]] [[package]]
@@ -816,7 +816,7 @@ wheels = [
[[package]] [[package]]
name = "fastapi" name = "fastapi"
version = "0.140.0" version = "0.140.13"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "annotated-doc" }, { name = "annotated-doc" },
@@ -825,9 +825,9 @@ dependencies = [
{ name = "typing-extensions" }, { name = "typing-extensions" },
{ name = "typing-inspection" }, { name = "typing-inspection" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/0d/fb/fd7671137d9fa3df1d93a2f5111eb982709201724b29f211e4beb2d58688/fastapi-0.140.0.tar.gz", hash = "sha256:f338951b82fd74ca8f843163aec43ea1a1ce84d515415a50fa98fa25572a5544", size = 420968, upload-time = "2026-07-24T21:16:41.187Z" } sdist = { url = "https://files.pythonhosted.org/packages/2f/cb/7a4d2c2eb5a5d8a91763c05b7383d72917862e32f780daa0e27ffbb34cc6/fastapi-0.140.13.tar.gz", hash = "sha256:500172a08cf1459901f90b05c37d93060dada3b573fec8f0862445db52ba6b4b", size = 424843, upload-time = "2026-07-28T15:37:00.805Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/eb/76/6d9e25ad88da9d3ff744bcdbec4736e38c2288611d43f673a5d9bfa27c07/fastapi-0.140.0-py3-none-any.whl", hash = "sha256:e951c0a0d9540bf5d9a2a9e078fd415da2ab7e312d435139e7d9e2e7fe9f0b23", size = 130863, upload-time = "2026-07-24T21:16:42.89Z" }, { url = "https://files.pythonhosted.org/packages/84/4e/f9e8c762ef5e05c40482131e3d5e8b36bca13fa127578261f1d6b35a25d4/fastapi-0.140.13-py3-none-any.whl", hash = "sha256:8b017110e1e9f30a95e8bdb8f71fbe2f0fe3af5717109e5b14f9e069df54f6d4", size = 131222, upload-time = "2026-07-28T15:37:02.124Z" },
] ]
[[package]] [[package]]
@@ -1047,7 +1047,7 @@ wheels = [
[[package]] [[package]]
name = "guard-core" name = "guard-core"
version = "3.5.0" version = "3.6.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "aiohttp" }, { name = "aiohttp" },
@@ -1058,9 +1058,9 @@ dependencies = [
{ name = "requests" }, { name = "requests" },
{ name = "typing-extensions" }, { name = "typing-extensions" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/3d/fa/f98609f0a40ba159819dc86c6471f3b6139d0d25e79b69abd877c5d7381e/guard_core-3.5.0.tar.gz", hash = "sha256:758ed9c803cfe42fee1f78da6f6d96bc237be29cee7ccf9cca997674b13eb357", size = 196080, upload-time = "2026-07-15T03:38:43.175Z" } sdist = { url = "https://files.pythonhosted.org/packages/91/05/d2f7e36a5cf5cbfce3f19b818faa8590eec81a38c8e2b9f45859c969c58c/guard_core-3.6.0.tar.gz", hash = "sha256:f7dddc354f13a67014e1eea40ba11522ed1470c2c53db21a7f1e85bbf53ec2dc", size = 197012, upload-time = "2026-07-29T01:39:56.888Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/11/46/b2a01d03aad56609fe3ec53f235c645f5529cf7df6da32d5a9747ba27f60/guard_core-3.5.0-py3-none-any.whl", hash = "sha256:0967b710d3432cccffdb2e97764658856e58c888c2c1796b6c5d8ebafa29ecb5", size = 243700, upload-time = "2026-07-15T03:38:42.101Z" }, { url = "https://files.pythonhosted.org/packages/c4/04/17e8d18d5d35b54cab732e8df4baf70ece96ee2e9c15fc7dbc587a98dcbd/guard_core-3.6.0-py3-none-any.whl", hash = "sha256:2f8c555c483ff998d48522180c3b2021b9db1948618626b246e9936a5923e927", size = 244102, upload-time = "2026-07-29T01:39:55.515Z" },
] ]
[[package]] [[package]]
@@ -1562,7 +1562,7 @@ wheels = [
[[package]] [[package]]
name = "mcp" name = "mcp"
version = "1.28.1" version = "1.29.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "anyio" }, { name = "anyio" },
@@ -1580,9 +1580,9 @@ dependencies = [
{ name = "typing-inspection" }, { name = "typing-inspection" },
{ name = "uvicorn", marker = "sys_platform != 'emscripten'" }, { name = "uvicorn", marker = "sys_platform != 'emscripten'" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/6e/77/9450b8f251a13affb6281997d0523c4615f8a8b35d0b21ff30db3a5aac9d/mcp-1.28.1.tar.gz", hash = "sha256:d51e36a5f5644faea4f85ea649bfffa6bc6c26770d42798ad6a3de3d2ba69683", size = 638501, upload-time = "2026-06-26T12:57:29.093Z" } sdist = { url = "https://files.pythonhosted.org/packages/30/d3/f9acc21dfc886e4f78e2add1a47db46ce16884346afde53f8a064c02c891/mcp-1.29.0.tar.gz", hash = "sha256:52d01f334de1868cc3bb2d6604931126a67631f99a6c5d3b82ba47290315ec36", size = 643148, upload-time = "2026-07-28T13:41:41.939Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/e2/5e/d118fce19f87a2e7d8101c35c8ae0ec289098a4df0ff244cec23e415aca0/mcp-1.28.1-py3-none-any.whl", hash = "sha256:2726bca5e7193f61c5dde8b12500a6de2d9acf6d1a1c0be9e8c2e706437991df", size = 222620, upload-time = "2026-06-26T12:57:27.218Z" }, { url = "https://files.pythonhosted.org/packages/01/c8/248b201f6d753d69fd5d6506011abbb35a946d9142b2ae311a948fd0be3d/mcp-1.29.0-py3-none-any.whl", hash = "sha256:f5a075bb611f23d6f4d080c6a1699fa62772eebc562ba9e66b306ddde1c755f7", size = 223436, upload-time = "2026-07-28T13:41:40.337Z" },
] ]
[[package]] [[package]]
@@ -1781,7 +1781,7 @@ wheels = [
[[package]] [[package]]
name = "openai" name = "openai"
version = "2.48.0" version = "2.50.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "anyio" }, { name = "anyio" },
@@ -1793,9 +1793,9 @@ dependencies = [
{ name = "tqdm" }, { name = "tqdm" },
{ name = "typing-extensions" }, { name = "typing-extensions" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/2a/ae/d4d1835488c0350424009dac5095b9a3e173bee12fd2e421ee27e2142c42/openai-2.48.0.tar.gz", hash = "sha256:231b1e7661dda14574986c2f71451e9d584b7fe69e0ee6480e12ed090b48fc16", size = 1093427, upload-time = "2026-07-23T20:15:50.402Z" } sdist = { url = "https://files.pythonhosted.org/packages/d8/f5/e7735f2af272ee179a287911a698b3cbdb59d7a4ac4874571363adf1e4de/openai-2.50.0.tar.gz", hash = "sha256:5128f7caf4a6b01aefd6e7e93efe170a2c3427b8de286b9af5cdff3aa47e02c8", size = 1081965, upload-time = "2026-07-28T22:16:31.674Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/b5/2a/dcb891114e303c4379d4a498f10222e33eee540bcef4e1e493bd0af2b242/openai-2.48.0-py3-none-any.whl", hash = "sha256:c98df30aaaf93c51979f64d3e7c5b76464f8be0173368266229eb8fe6bd30f2c", size = 1648520, upload-time = "2026-07-23T20:15:48.052Z" }, { url = "https://files.pythonhosted.org/packages/00/ca/db315b3bb748c26c644a3f85b7d509e774354d6518d47080b1446005ee41/openai-2.50.0-py3-none-any.whl", hash = "sha256:90bdddcc5a2fa529b350fac9c5780d87e5c361dcc6090ab57b0d470b0d7af7fa", size = 1650721, upload-time = "2026-07-28T22:16:29.48Z" },
] ]
[[package]] [[package]]
@@ -2967,14 +2967,14 @@ wheels = [
[[package]] [[package]]
name = "tqdm" name = "tqdm"
version = "4.69.1" version = "4.70.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "colorama", marker = "sys_platform == 'win32'" }, { name = "colorama", marker = "sys_platform == 'win32'" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/dd/84/da0e5038228fa34dfd77c5026b173ed035d2a3ba31f1077590c013de2bff/tqdm-4.69.1.tar.gz", hash = "sha256:2be21080a0ce17e902c2f1baeb6a74bf551b67bbdfa4bc0109fad471d0b4cb0d", size = 793046, upload-time = "2026-07-24T14:22:02.08Z" } sdist = { url = "https://files.pythonhosted.org/packages/21/3b/6c24bec5be5e743ffd99576daa5cc077722fc7d5bbc00bd133fa0c698dc6/tqdm-4.70.0.tar.gz", hash = "sha256:55b0b0dbd97462d06ebee91e4dac24ed4d4702be82b24f07e6c1d27e08cea220", size = 795438, upload-time = "2026-07-27T11:33:15.271Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/01/50/5817619a0fca56aff06383dbfde7ae017b3ca383915b3f1e4713164273cf/tqdm-4.69.1-py3-none-any.whl", hash = "sha256:0a654b96f7a2660cceb615b56f307ec2bef96c515409014a429a561981ab52b4", size = 675452, upload-time = "2026-07-24T14:22:00.048Z" }, { url = "https://files.pythonhosted.org/packages/f9/1c/01bfd571a64e7f270e6bab5e33777debe0edc56759233ce84f27dec92d14/tqdm-4.70.0-py3-none-any.whl", hash = "sha256:7f585706bfddbdebf89daac705b2dfcc16890130727d3197ca62c732b4310953", size = 80184, upload-time = "2026-07-27T11:33:13.167Z" },
] ]
[[package]] [[package]]
@@ -3100,15 +3100,15 @@ wheels = [
[[package]] [[package]]
name = "uvicorn" name = "uvicorn"
version = "0.51.0" version = "0.52.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "click" }, { name = "click" },
{ name = "h11" }, { name = "h11" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/a2/65/b7c6c443ccc58678c91e1e973bbe2a878591538655d6e1d47f24ba1c51f3/uvicorn-0.51.0.tar.gz", hash = "sha256:f6f4b69b657c312f516dd2d268ab9ae6f254b11e4bac504f37b2ab58b24dd0b0", size = 94412, upload-time = "2026-07-08T10:59:05.962Z" } sdist = { url = "https://files.pythonhosted.org/packages/05/c8/2d307868453a4bca6e64fa3581d122ae0748a0869c53f159339def179c7c/uvicorn-0.52.0.tar.gz", hash = "sha256:ca8876ad6c1983f394157c168b39d52f6dd56dabf5602fa0982751cffc2293ae", size = 97504, upload-time = "2026-07-29T08:45:34.065Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/45/ec/dbb7e5a6b91f86bfb9eb7d2988a2730907b6a729875b949c7f022e8b88fa/uvicorn-0.51.0-py3-none-any.whl", hash = "sha256:5d38af6cd620f2ae3849fb44fd4879e0890aa1febe8d47eb355fb45d93fe6a5b", size = 73219, upload-time = "2026-07-08T10:59:04.44Z" }, { url = "https://files.pythonhosted.org/packages/39/e6/b5c0630ace9757232aec07112be8146b812787db52141ff9d50674aa7634/uvicorn-0.52.0-py3-none-any.whl", hash = "sha256:3d887809810b89ed33501bcf0a9aba469b06ecd608158efce04bd6b48d8c9b08", size = 79058, upload-time = "2026-07-29T08:45:32.492Z" },
] ]
[package.optional-dependencies] [package.optional-dependencies]