Skip to content

Oracle Waves 2+3: capability catch-up + UI v3 bundle (v2.48.0-v2.49.0)#29

Merged
drknowhow merged 12 commits into
mainfrom
oracle-wave-2
Jul 2, 2026
Merged

Oracle Waves 2+3: capability catch-up + UI v3 bundle (v2.48.0-v2.49.0)#29
drknowhow merged 12 commits into
mainfrom
oracle-wave-2

Conversation

@drknowhow

Copy link
Copy Markdown
Owner

Completes the stacked chain: #26 (Wave 1) squash-merged to main, but #27/#28 merged into their stacked bases (oracle-wave-1 / oracle-wave-2) and never cascaded. This branch tip contains Waves 2+3 exactly as reviewed in #27 and #28 (wave-1 content is identical to what #26 already landed).

See #27 and #28 for the full summaries: c3_project/c3_artifacts read-tier tools, sub-project awareness, scheduled digest, multi-backend agents, UI v3 concat bundle + /legacy, c3 oracle serve, oracle-guide refresh. Full suite at branch tip: 1015 passed / 1 skipped.

drknowhow and others added 12 commits July 2, 2026 13:47
…ot 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.
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.
…m-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.
…llback

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).
…/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.
…y, 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).
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).
…ni/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.
…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.
@drknowhow drknowhow merged commit 68b13f0 into main Jul 2, 2026
10 checks passed
@drknowhow drknowhow deleted the oracle-wave-2 branch July 2, 2026 19:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant