Commit Graph
19 Commits
Author SHA1 Message Date
james.maesandClaude Opus 5.5 c27994c432 feat: answer presentation: present_results tool, presentation parts and the default presentation skill
Owner priority: answers must be easy to read and act on.

- present_results tool: summary, metrics, table (computed percent
  columns, per-row filtered-list links), bar/pie/line chart from the
  table, filter and record links, follow-up actions. Every table and
  field is checked against what the user can see through the UI API;
  hrefs (/app/<table>?filter=<QQQ filter JSON>, records) and number
  formats are built server-side from metadata; the model never writes
  URLs.
- presentation message part (persisted, SSE event) with a server-built
  multi-line GFM markdown fallback for clients without blocks.
- Static system-prompt Presentation section (built-in default skill):
  answer first, no restating, tables for 3+ items, charts for shares and
  trends, filterLinks whenever a list is offered.
- Golden eval of the owner's example: summary, 2-row table with 80.2% /
  19.8%, a 2-point pie and two mimeType filter links; negative cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:54:05 -05:00
james.maesandClaude Opus 5.5 cb7d5d4d5a refactor: budget alerts through core QAlerts (QQQ 4.1.0-RC.5), alert types declared
Closes #28 (first half; the DataClassification and loopback gateway
stand-ins go with RC.6).

- Default QQQ is 4.1.0-RC.5.
- BudgetAlerts calls QAlerts.raise(AlertSignal...) directly instead of
  binding by reflection.
- The producer declares assistant.budget.warning, .downgraded and .stopped
  as QAlertTypeMetaData (assistant.admin, subject assistant_budget).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:30:01 -05:00
james.maesandClaude Opus 5.5 55804d9059 feat: simple/complex model routing and fallback chains across providers (P-e)
- Profiles gain routing (OFF, HEURISTIC, CLASSIFIER) with simple, complex
  and classifier models. The heuristic is a small documented rule set; the
  classifier is one 4-token call on the question text only (ROUTE usage,
  3 s timeout, heuristic on any failure, skipped for PHI on a
  non-eligible provider).
- assistant_model.fallback_model_id chains (cycle-checked, max 4 hops)
  across providers; retryable failures before any output fall back.
  Candidates that are disabled, down, over a STOP budget or fail the PHI
  rule are skipped; without a chain, LOCAL falls back only to LOCAL.
- Circuit breaker (provider health UP/DOWN, down_until) and a cached
  health probe for stale LOCAL providers.
- A mid-turn provider switch rebuilds history from neutral parts and drops
  adapter state (Anthropic thinking signatures).
- Turn route decision, source and fallback count; home shows health and
  fallbacks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:09:26 -05:00
james.maesandClaude Opus 5.5 51fcfa6a33 feat: data-driven budgets with warn, downgrade, stop and admin overrides (P-d)
- assistant_budget (scope INSTANCE/USER/ROLE/PROVIDER/MODEL, DAY/MONTH,
  cost or tokens, warn %, DOWNGRADE or STOP at 100%, hard ceiling),
  assistant_budget_override (reason, grantor, expiry) and
  assistant_budget_event (deduplicated WARNED/DOWNGRADED/STOPPED).
- BudgetService checks before every model call; strictest outcome wins.
  Warnings raise a panel notice and an optional Alerts signal; downgrade
  prefers a cheaper LOCAL model and never crosses the PHI rule.
- assistant_budget_usage: an owner-lock-free accounting projection of
  usage counters so shared-scope sums run under the caller's own session.
- App home: budgets card with state and overrides, 30-day cost and token
  bars with user, model, provider and tool breakdowns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 18:43:45 -05:00
james.maesandClaude Opus 5.5 d15c7dce12 feat: data classification, PHI routing and HIPAA mode (P-c)
- DataClassification (PUBLIC < CONFIDENTIAL < PII < PHI): a qbit
  stand-in for core's (QRun-IO/qqq#1142) behind a pluggable
  ClassificationSource (config by default; core metadata or
  qbit-secured-data overrides later).
- Each turn tracks the highest classification its page context, history
  and tool results touched (turn.classification, conversation
  max_classification, never lowered).
- PhiRoutingGuard before EVERY model call: PHI only to hipaa_eligible
  provider rows; otherwise the turn ends PHI_BLOCKED with the reason and
  the tool results are never sent.
- HIPAA mode: no non-eligible providers (resolve, enable, code fallback),
  AES-256-GCM conversation storage (key by env-var reference, required),
  PHI retention period, no provider messages or stack traces in logs.
- assistant_data_audit: one row per model call that carried PII/PHI and
  per block (who, classification, tables, provider, model, decision).
- System rule 11: masked values stay masked; never ask to reveal them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 18:20:13 -05:00
james.maes 88e1081396 Merge remote-tracking branch 'origin/feature/p1-provider-registry' into feature/p2-bedrock-vertex 2026-10-13 17:47:42 -05:00
james.maesandClaude Opus 5.5 c9ccd4c79b feat: AWS Bedrock and Google Vertex adapters (P-b)
- qbit-assistant-provider-bedrock: Claude on Bedrock through the
  anthropic-java Bedrock backend (AnthropicMapping reused), credentials
  from the server's AWS default chain, region required, no key reference.
  IRSA/web identity needs the host to add software.amazon.awssdk:sts.
- qbit-assistant-provider-vertex: Claude on Vertex through the
  anthropic-java Vertex backend, Gemini through Vertex's OpenAI-compatible
  endpoint with an ADC bearer token refreshed per request (never strict).
  Region and the new cloud_project column are required.
- AnthropicModelProvider.Builder.client(...) and a bearer-token supplier
  on ProviderSettings / the OpenAI adapter.
- Mocked contract tests: a Bedrock event-stream mock with SigV4 checks,
  Vertex rawPredict and OpenAI-compatible mocks, validation, and a golden
  tool round trip per module.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 17:47:40 -05:00
james.maesandClaude Opus 5.5 a7be39db0f feat: readable labels for the provider registry; P-a demo server and screenshots
- Kind, source and field labels (HIPAA-eligible, API version, prices
  per million tokens, timeouts) instead of raw ids.
- Test-only OpenAiDemoServer: a mock OpenAI-compatible host, real
  Discover models / Test connection runs and one turn.
- Screenshots of the home providers card, a local provider, its Models
  child list and a model, light and dark at 390 and 1440 px.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 17:33:43 -05:00
james.maesandClaude Opus 5.5 8d869f65cd feat: provider and model registry, OpenAI-compatible adapter, discovery and health (P-a)
- assistant_provider gains kind, location, hipaa_eligible, region, api
  version, timeouts, a CA bundle reference and discovery status.
- New assistant_model table (child list on the provider): capabilities,
  prices per million tokens, enabled flag, last test.
- Provider SPI: ProviderSettings, kinds, discovery and health as default
  methods; create(apiKey, baseUrl) implementations keep working.
- New module qbit-assistant-provider-openai: OpenAI, Azure OpenAI,
  OpenRouter, Ollama, LM Studio, vLLM and llama.cpp over JDK HTTP, with
  streaming, tool calls, usage, timeouts, cancel, strict only where
  supported (and the existing fallback on refusal), keyless local
  endpoints and per-provider private CA trust.
- Record actions: Discover models (provider), Test connection (model);
  provider Test connection checks health first.
- Mock-server contract tests, a golden tool round trip, TLS tests and a
  config-driven live check (skipped unless configured).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 17:17:39 -05:00
james.maesandClaude Opus 5.5 f2eb20a8bc docs: spec for write mode, the config wall, audit attribution and providers
Owner decisions (2026-10-13), continued, with all recommendations
accepted:
- write mode per conversation (Read-only by default), user preference,
  admin policy, confirmed writes, auto-confirm rules;
- the hard wall: the assistant client channel is denied every assistant_*
  object and the security surfaces in core, plus a startup check;
- audit attribution: the human actor plus via=assistant/<turnId>;
- providers and models as data (OpenAI-compatible, Bedrock, Vertex),
  local models, HIPAA/PHI routing, budgets, routing, RAG and scheduled
  tasks.
Also the phase plan and its dependencies.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 16:20:43 -05:00
james.maesandClaude Opus 5.5 0f34c8a1dc test(demo): the panel proposes a page change; screenshots of the card
The demo queues recorded answers that propose update_record on page 12
(READ_WRITE), so a question in the panel shows the confirmation card;
Save runs it through PATCH /qqq/v1/table/page/12 with the user's session.
Screenshots of the persona, the pending card and the confirmed write
(light/dark, 390/1440), taken locally against the demo server.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:34:36 -05:00
james.maesandClaude Opus 5.5 6634d88286 fix: log denied tool calls against their table; demo seeds persona and data access
- The tool's table is recorded before the call, so a call the UI API
  refuses still names its table in the log and in Recent denials.
- AssistantDemoServer seeds a default profile (Ada), an analysts profile,
  two skills (one linked) and data access rows (page READ_WRITE,
  media NONE).
- Screenshots of the Recent denials card, Explain access widget, Data
  access table, profile, skill and policy (light/dark, 390/1440).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:24:30 -05:00
james.maesandClaude Opus 5.5 0babaa7022 feat: profiles, skills, explain access and recent denials
Owner (2026-10-13): set a name, personality and extra skills for the
assistant, and the assistant stays limited to the UI API and to what the
signed-in user could do through it.

- assistant_profile (persona: display name, icon, bounded personality,
  greeting, starter prompts; default, app- or permission-scoped) and
  assistant_skill (admin Markdown instruction packs, read only when
  relevant, bounded) linked by assistant_profile_skill. Text only: it
  goes into the per-user system block and never reaches tool code.
- Explain access: GET /assistant/access and the assistantAccess home
  widget, per table and tool: allowed or why not, from GET /metaData with
  the user's own session plus data access and policy.
- Recent denials card on the Assistant home.
- Hard guarantee: ArchUnit forbids the tool / UI API / access packages
  from QQQ actions, the AI kernel and the profile/skill classes, and the
  store refuses any non-assistant_ table. A denial matrix proves query,
  get, insert, update and delete are denied identically via the UI API
  and via the assistant.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:10:47 -05:00
james.maesandClaude Opus 5.5 01cc719c5b feat!: assistant tools go through the /qqq/v1 UI API with the user's session
Owner decisions (2026-10-13): tools via the UI API, configurable and
verifiable data access, and confirmation for writes.

- Every data tool runs a spec'd /qqq/v1 operation (UiApiGateway, a
  loopback request carrying the user's own sessionUUID cookie), so it
  passes the UI's authentication, permissions, record locks, validation,
  audit and error mapping. LoopbackUiApiGateway is a stand-in for core's
  UiApiInvoker (QRun-IO/qqq#1128). navigate and search_help (no records)
  stay on the core kernel.
- Data access (assistant_data_access): NONE / READ / READ_WRITE per table
  or process; sensitive tables NONE and cannot be raised; it only narrows.
- Writes (create/update/delete_record) propose a pending action
  (assistant_pending_action) the owner confirms; confirm runs it once
  through the UI API with the confirming request's session.
- Policy: writesRequireConfirmation, allowedTools, maxRowsPerCall,
  redactPii. Tool-call log: UI API operation, HTTP status, audit link,
  pending action; inputs stored with secrets redacted.
- UiApiToolsSecurityTest proves a user without a permission gets the same
  denial through the assistant as through the UI; golden and red-team
  evals run through a real application server.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 13:56:18 -05:00
james.maesandClaude Opus 5.5 38bb123140 fix: stop sending every tool strict; surface provider error reasons
Every kof22 turn failed on its first model call with Anthropic 400
invalid_request_error "The compiled grammar is too large ... reduce the
number of strict tools". All ten read tools were strict, and the API
compiles every strict schema of a request into one grammar.

- Tools are not strict by default; hosts opt in with strictToolNames.
  The kernel validates every tool input (INVALID_INPUT) anyway.
- If a provider still refuses strict schemas, the turn retries once
  without strict tools and logs a warning.
- Provider errors carry the API error type, a sanitized message and the
  request id: logged at WARN on 4xx, request id kept on the usage row,
  the reason shown to assistant.admin holders and in Test connection.
- TurnEngine also catches Errors, so a turn never ends silently.
- AnthropicRequestContractTest checks the exact request against the
  Messages API constraints and a conservative strict-tool budget.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 13:25:28 -05:00
james.maesandClaude Opus 5.5 e54de89a49 feat: provider settings, per-call usage, model prices and the app home
- assistant_provider: type (registered AssistantProviderType; Anthropic),
  model, enabled/default, base URL override, cost cap, output and
  concurrency limits, last connection test. The key is never stored: the
  row names an allow-listed environment variable; apiKeyStatus is
  computed on read (last 4 at most) and dropped on save.
- Test connection: a record action (standard streamed ETL Review/Result)
  making one short live call; result saved on the row and as a TEST
  usage row.
- assistant_usage: one row per model call (turn steps and tests);
  assistant_model_price: editable USD/MTok used for every call's cost.
- The Assistant app home (health, providers, usage by day, costs vs caps,
  by user, top tools, recent failures); nav = home + main tables.
- AI exposure NONE on every assistant_* table.
- Tests, README, DESIGN, UPGRADE, CHANGELOG, reference DDL with the
  Anthropic price seed, demo server and screenshots.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 10:01:33 -05:00
james.maesandClaude Opus 5.5 e95fb90228 feat: red team, golden evals, developer panel, docs and CI
- ArchUnit rules: no system session, no QSession construction, data actions
  only in the persistence package.
- Permission red team (build gate): no-permission denial without leaks,
  other users' conversations, kill switch mid-turn, hard budget, hidden and
  password sentinels never sent, enveloped tool results, no thinking in SSE,
  cancel stops pending tools.
- Golden evals v1 (scripted faithful model) incl. example D and the read
  half of example A, plus an opt-in live run against Claude.
- Record Developer screen Assistant panel on the core developer-panel
  contract (QRun-IO/qqq#1076) fed by AiToolKernel.describeAccess, with the
  ask-the-assistant deep link.
- README, CLAUDE.md, CHANGELOG, reference DDL, CircleCI (qqq-orb 0.6.8).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 06:27:58 -05:00
james.maesandClaude Opus 5.5 003c66e14f feat: assistant qbit skeleton - config, tables, provider SPI, turn engine, SSE routes, Anthropic provider
Multi-module build (qbit-assistant, qbit-assistant-provider-anthropic) on
qbit-build-parent 2.0.0 with the qqq-snapshot BOM profile. Standard visible
assistant* tables with owner record locks, provider-neutral model SPI with a
scripted provider, turn engine on the core AiToolKernel, /qqq/v1/assistant
routes with SSE, and the Anthropic adapter with recorded-stream tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 06:10:59 -05:00
james.maes e62572b0d7 Initial commit 2026-10-12 05:32:28 -05:00