Commit 68b13f0
authored
Oracle Waves 2+3: capability catch-up + UI v3 bundle (v2.48.0-v2.49.0) (#29)
* fix(oracle): close unauthenticated local-write kill chain with per-boot session cookie
POST /api/apikey/generate|rotate|clear, /api/chat, /api/suggestions/approve
and /api/config were reachable by any local process; rotate returned the
fresh Discovery token, defeating the Bearer gates on /api/config and
/api/discovery/*.
New oracle/services/local_session.py issues a per-boot HttpOnly
SameSite=Strict cookie on GET / to loopback clients only; a default-deny
_local_write_guard requires session cookie OR Bearer on every mutating
/api/* call outside /api/discovery/*. Session also un-breaks the dashboard
Settings save (the UI never sent a Bearer token) and lets the dashboard
reveal the Discovery key. Discovery stays Bearer-only.
* perf(oracle): TTL-cache ProjectScanner.discover with copy-on-return
discover() re-ran the hub fetch + per-project facts enrichment on every
tool call (validate_project_path) and multiple times per graph request.
Now cached for scanner_ttl_seconds (default 20s) under a lock; cache hits
return deep copies (api_projects mutates the dicts), empty discoveries
are never cached, and the dashboard Scan action forces a refresh.
* refactor(oracle): C3Bridge adopts shared ProjectRuntimeCache with warm-on-build
Deletes the hand-rolled 3-slot LRU (the shared cache's own docstring names
it as the predecessor it was lifted from). C3Bridge now holds a PRIVATE
ProjectRuntimeCache (size 8, C3_RUNTIME_CACHE_SIZE-tunable) so cross-project
search over >3 projects stops thrashing, while keeping its atexit shutdown
semantics. New on_build hook on ProjectRuntimeCache (default None, existing
callers untouched) fires once per newly built runtime; the Oracle uses it to
warm embedding_index + vector_store in a daemon thread, mirroring the MCP
server's lifespan warm, so the first c3_search stops paying chromadb init
on the request thread. Read-only enforcement and validate_project_path are
unchanged.
* feat(oracle): native Ollama tool calling in ChatEngine with legacy fallback
Chat previously described tools in the system prompt and regex-parsed
<tool_call> text blocks, patched with retry/trust heuristics. Now:
- OllamaBridge: show()/supports_tools() capability probe (cached; None =
unknown), set_tools_support() negative-cache poke, stream_chat(tools=)
yielding structured ("tool_call", {name, arguments}) events.
- ChatEngine: native tools array built from TOOL_SPECS (single source of
truth; api_max_tier caps external callers only); one shared _drain_stream
generator replaces three copies of the chunk-unpacking loop (main loop,
visible-retry, delegate sub-agent). Three-way mode: tools-capable models
run native (no stripper, no trust-answer heuristic, role:tool feeding,
no finalize nudge); incapable models keep the legacy text protocol
verbatim; unknown-capability models attempt native and demote mid-turn
on HTTP 400, negative-caching only when the server names tools as the
problem. Sub-agents pick their protocol from their own model.
- SSE event vocabulary, payload shapes, and persisted round_messages roles
unchanged — oracle.html needs no changes; history reloads re-inject
<tool_result> user messages in both modes.
- Hygiene: is_available() no longer reports a 5xx-failing server as up;
LLM disk cache gains TTL (llm_cache_ttl_sec, default 86400) and a
512-entry bound evicting oldest by mtime.
First-ever ChatEngine test coverage (18 tests) + bridge tests (14).
* docs: CHANGELOG entry for v2.47.0 Oracle Wave 1; ruff import-order fix
* feat(oracle): expose c3_project + c3_artifacts as read-tier Discovery/chat tools
Deny-by-default allowlists: c3_project permits list/info/subprojects/search/
read/compress/status/memory/impact/edits/validate — register/unregister,
sub_* mutations, edit/shell, and 'scan' (reveals unregistered .c3 projects,
outside the discovered-project trust boundary) are excluded. The wrapper
signature has no allow_write and no write-op params; the registry drops
undeclared keys, so write verbs cannot reach handle_project from any
transport. Every resolution passes resolve_project THEN validate_project_path
(the resolver accepts any on-disk .c3 folder; Oracle re-checks membership).
c3_artifacts blocks scan (mutates the manifest despite the handler's
READ_ACTIONS listing) and restore; list/history/show/diff/status proxy
through the validated runtime cache. MCP + OpenAPI pick both up from
TOOL_SPECS automatically. Tests pin the allowlist enums, the allow_write
drop, and _BLOCKED_MEMORY_ACTIONS == cli.tools.project._MEMORY_WRITE.
* feat(oracle): sub-project awareness — scanner hierarchy, graph overlay, scoped cross tools
The Oracle treated every project as flat, ignoring the v2.44 parent/child
model. Now: ProjectScanner carries registry parent_path (previously dropped)
and _enrich adds is_subproject / parent_path (child-config back-link as
fallback; broken links degrade to top-level) / subproject_rel_paths / count —
/api/projects and the list_projects chat tool surface hierarchy for free.
FederatedGraph gains a serve-time parent_child overlay applied on BOTH fresh
builds and cache hits (hierarchy lives in .c3/config.json, which the
facts-mtime cache key never sees; the overlay is never baked into the cache
file, and no fact-level edges are added — they would pollute similarity
clustering). c3_search_cross / c3_edits_cross gain an optional scope param:
'' = all, 'top' = top-level only, or a project name/path = that project plus
its direct sub-projects (resolved + validated).
* feat(oracle): scheduled activity digest via the review loop
ActivityReporter was fully built but only reachable on demand. The review
loop now emits a cross-project digest when due: config-gated (digest_enabled
default FALSE — current behavior preserved; digest_interval_seconds daily;
digest_narrate opt-in since narration costs a cloud LLM call), config read
live each cycle so toggling needs no restart, last_digest_at pre-stamped in
review_state.json so an overlapping run_now can't double-digest, digests
persisted to ~/.c3/oracle/activity_digests/<date>.json + latest.json with
retention pruning (digest_retention_days), optional one-line JSONL notify
sink (digest_notify_file), and the whole path try/except-wrapped so a digest
failure never kills the review cycle. New GET /api/activity/digest/latest;
Activity tab shows a last-scheduled-digest banner; Settings gains the toggle
and interval (round-trips through the existing /api/config).
* feat(oracle): multi-backend delegate_task via c3_delegate (codex/gemini/claude/auto)
Oracle agents ran only on Ollama while core C3's delegate layer already had
hardened Codex/Gemini/Claude CLI backends. Agents now carry a per-agent
backend (default 'ollama' = unchanged nested tool loop); CLI backends route
through cli.tools.delegate.handle_delegate against _OracleDelegateRuntime —
a read-only shim of the target project's runtime that forces
codex/gemini memory bridges OFF (they write facts into the target),
notifications None (no NotificationStore writes), and
codex_default_sandbox='read-only', while passing everything else through.
CLI backends need a concrete project (subprocess cwd + the TARGET's own
delegate config; Oracle never force-enables a backend): explicit
project_path arg → conversation's focused project (via thread-local conv
state) → instructive error; never silently picked. delegate_task spec/defs
gain optional project_path; agent modal gains a backend select; delegate
progress notes stream to the UI through the existing agent event sink.
* docs: CHANGELOG entry for v2.48.0 Oracle Wave 2; ruff import-order fix
* Oracle Wave 3: UI v3 concat bundle + c3 oracle serve + docs refresh (v2.49.0) (#28)
* feat(oracle): UI v3 — split the 4,181-line oracle.html monolith into a concat bundle
oracle.html was the pre-refactor hub.html pattern: one file, ~780 lines of
CSS + ~400 lines of markup + a 2,967-line inline script. Following the hub
v2 concat architecture: new oracle_ui.html shell (CSS + markup +
__C3_ORACLE_SCRIPTS__ token) + 18 oracle/ui/ modules split at section
banners (core, busy, theme_tabs, crossgraph, header, projects, insights,
activity, suggestions, settings, agents, chat/{markdown,conversations,
stream_renderer,toolbar,input,send}, app.js LAST — the init IIFE).
_ORACLE_JS_FILES + _build_oracle_html() concatenate server-side with
per-file markers; / serves the cached bundle, /legacy serves the frozen
monolith for one release (both issue the dashboard session cookie).
Extraction is VERBATIM: a splitter script cut exact line ranges with a
tiling assertion (no gaps/overlaps), and a multiset diff proved the bundle
differs from the original script by only the intentional ORACLE_BUILD_TIME
bump. Whole-bundle esbuild parse clean. Deliberate deviation from the Wave-3
plan: no React/babel runtime — the logic is 100%% vanilla imperative and the
transferable hub pattern is the file structure + build pipeline, not the
framework; wrapping unowned vanilla code in React would add a CDN/transpile
failure surface for zero owned UI.
Also: pyproject package-data globs for oracle/ui + oracle/ui/chat (the '*'
top-level-only gotcha), and a new 'c3 oracle serve|start' subcommand (lazy
import, mirrors cmd_hub) so the server no longer requires the python entry
point. New tests/test_oracle_ui_bundle.py; wheel inspection confirms all 18
modules + shell + legacy ship.
* docs(oracle): oracle-guide caught up a full product generation; CHANGELOG v2.49.0
The guide documented the original memory/insight Oracle but none of what it
became: architecture.md gains Chat subsystem (tool loop, native-vs-text
protocol, full SSE event vocabulary), C3Bridge, Federated graph, and
Security model sections, all 17 services listed, stale line counts fixed,
Web UI section rewritten for the 8-tab concat bundle. api-reference.md adds
the /api/apikey, /api/chat, /api/graph/federated, /api/insights/cross and
/api/activity/digest/latest families plus the v2.47.0 write-gate auth note
and fixed /api/health payload. configuration.md now covers all 30 DEFAULTS
keys incl. the agents roster shape with the backend field. README leads
with c3 oracle serve. discovery-api.md lists c3_project/c3_artifacts, the
scope param, and delegate_task's project_path. changelog.md gains v1.3.0
(C3 v2.47.0-v2.48.0), v1.4.0 (C3 v2.49.0), and an honest 'previously
undocumented' block for the v2.32-v2.38 era features. AGENTS.md tree
updated; root CHANGELOG gains the v2.49.0 Wave 3 entry.1 parent a25ebf9 commit 68b13f0
46 files changed
Lines changed: 6185 additions & 50 deletions
File tree
- cli
- commands
- oracle-guide
- oracle
- services
- ui
- chat
- tests
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
133 | 133 | | |
134 | 134 | | |
135 | 135 | | |
136 | | - | |
| 136 | + | |
| 137 | + | |
137 | 138 | | |
138 | | - | |
| 139 | + | |
| 140 | + | |
139 | 141 | | |
140 | 142 | | |
141 | 143 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
7 | 123 | | |
8 | 124 | | |
9 | 125 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5632 | 5632 | | |
5633 | 5633 | | |
5634 | 5634 | | |
5635 | | - | |
| 5635 | + | |
5636 | 5636 | | |
| 5637 | + | |
| 5638 | + | |
| 5639 | + | |
| 5640 | + | |
| 5641 | + | |
| 5642 | + | |
| 5643 | + | |
5637 | 5644 | | |
5638 | | - | |
| 5645 | + | |
| 5646 | + | |
5639 | 5647 | | |
5640 | 5648 | | |
5641 | 5649 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
357 | 357 | | |
358 | 358 | | |
359 | 359 | | |
360 | | - | |
| 360 | + | |
361 | 361 | | |
362 | 362 | | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
363 | 372 | | |
364 | 373 | | |
365 | 374 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
12 | | - | |
| 11 | + | |
| 12 | + | |
13 | 13 | | |
14 | 14 | | |
15 | | - | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
16 | 19 | | |
17 | 20 | | |
18 | 21 | | |
| |||
23 | 26 | | |
24 | 27 | | |
25 | 28 | | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
26 | 33 | | |
27 | 34 | | |
28 | 35 | | |
| |||
0 commit comments