Skip to content

release: Fleetbase AI v0.0.5 - #7

Merged
roncodes merged 11 commits into
mainfrom
release/v0.0.5
Sep 22, 2026
Merged

roncodes merged 11 commits into
mainfrom
release/v0.0.5

Conversation

@roncodes

Copy link
Copy Markdown
Member

Summary

  • open the Fleetbase AI v0.0.5 release branch
  • synchronize the extension, frontend package, and API package versions
  • prepare release notes for docs-grounded answers, console actions, and the redesigned log and analytics views
  • run CI on pull requests into release branches, as fleetops does

Planned release work

  • feat: ground answers in the docs and let the AI propose console actions #6: ground answers in fleetbase.io/docs, let the AI propose console actions confirmed with a button, tool calling for Anthropic and OpenAI, redesigned Task & Chat Logs (split view, full transcripts) and Usage Analytics, removal of Reveal Content, and fixes for tasks resolved to the wrong record, inline code rendering and clickable docs links

Depends on

An audit against a production log export (57 turns, 9 companies) found that
almost every question was a product how-to, 47 of 57 turns reached the model
with no Fleetbase context at all, and 6 of 10 sampled answers were false:
invented menus, fields and features. Conversation history kept only the first
140 characters of each answer, so follow-ups looped.

Grounding
- Crawl fleetbase.io/docs into `ai_knowledge_documents` and `ai_knowledge_chunks`,
  chunked by heading with FULLTEXT search, behind a `KnowledgeSourceInterface`.
- `search_docs` and `read_doc` tools, with `ai:sync-docs` (weekly), a gzipped
  snapshot shipped with the package for offline and self-hosted installs, and an
  admin Knowledge Base page with a sync button.
- Shared `AiSystemPrompt` for every provider: answer only from docs or tool
  results, reply in the user's language while quoting console labels exactly,
  carry out the previous offer on "yes", and never print internal route names.

Audience
- `AiAudience` treats only `$user->type === 'admin'` as a system admin; an
  organization Administrator role is not one.
- Docs pages, doc passages and console commands are filtered server-side, so an
  organization user never receives admin paths, credentials or env vars. Admin
  setup lines inside end-user pages are redacted to a "contact your system
  administrator" note.

Console actions
- `AiCommandRegistry` with navigate and service steps for IAM, Developers,
  settings, account, extensions and the admin pages; engines register their own.
- `find_console_commands` and `propose_console_command` let the model only
  propose. The user confirms in `ai-ui-action-confirmation`, the server
  re-authorizes permissions and audience, and `ai-commands` then runs the steps
  through the engine resource-action services. Nothing runs without the click.
- `scripts/verify-ai-commands.mjs` checks every route and service method exists.

Runtime
- `AiAgentRunner` with real multi-turn tool calling over Anthropic
  `tool_use`/`tool_result` and the OpenAI Responses API, prompt caching, adaptive
  thinking, truncation and refusal handling, and a `tool_calling` setting.
- Generic `count_records`, `group_count` and `list_records` tools from the query
  registry, reporting `total_matching` and truncation.
- Capability failures no longer send exception text to the provider; the turn is
  marked degraded instead.
- Action previews carry a `preview_id`, so one answer can hold several.

Logs, feedback and evaluation
- Rebuilt admin log viewer: pagination, task status, feedback, degraded and
  cut-off filters, expandable tool call steps, and JSONL/CSV export. Also
  `ai:export-logs`.
- Thumbs up/down feedback on each answer.
- `ai:eval` runs 19 golden cases taken from the logs, each as an end user and as
  a system admin, and `ai:replay` re-runs a logged turn.
Codecov requires full coverage on the diff. The gaps were the declined
confirmation in `ai:eval` and `ai:replay`, the replay guard for providers
without tool calling and its leaked-route warning, verbose `ai:sync-docs`
output, the uuid hooks on the knowledge models, the attachment step in tool
mode, the export download stream, the `listRecords` permission guard, and the
docs parser's comment and non-list-item handling.

Also moves the scripted provider double into the shared test doubles so both the
runner and eval tests can use it, and folds `pageSections`' defensive null guard
into its return.
Live testing of the console actions surfaced four defects.

**Tasks resolved to the wrong record.** `findTask` and its siblings matched
`uuid = $id OR id = $id`. MySQL casts a UUID such as `4dcd1b1f-...` to the
integer 4, so the lookup matched an unrelated task by its numeric key and
`firstOrFail()` returned whichever row came first. Confirming a console action
answered "This AI action was not found", and apply, cancel and feedback would
have written to the wrong task. Roughly 62% of UUIDs start with a digit, so
this fired constantly. The numeric key is now only compared when the value is
actually numeric, at all five lookup sites.

**Inline code was destroyed by the emphasis pass.** The placeholder
`@@AI_CODE_0@@` contains underscores, so the italic rule rewrote it to
`@@ai<em>CODE</em>0@@` and the code span could no longer be restored; users saw
`@@AIcode0@@` in answers. Placeholders now use private-use sentinels that no
markdown rule can touch.

**Documentation links were dead text.** Only `[text](url)` was linkified, but
answers cite docs as bare URLs. Bare URLs are now linked too, leaving code
spans, trailing punctuation and underscores in paths intact.

**Actions were offered in prose only.** The model wrote "I can take you there"
without calling `propose_console_command`, so no card appeared and the user had
to ask again. The prompt now states that offering means calling the tool in the
same turn.

Also: command labels quote the console's own dialog titles (New User, New
Group, New API Key) instead of invented ones, the client addresses tasks by
uuid rather than the autoincrement id, and `verify-ai-commands.mjs` silences PHP
diagnostics that corrupted its JSON on some hosts.
**Capabilities could vanish without a trace.** `AiAgentRunner::toolsFor()` keeps
only capabilities implementing `AIToolCapabilityInterface`, and tool calling is
the default, so any engine or extension registering a plain capability lost it
silently: no error, no log, no degraded flag. That is how Fleet-Ops order
creation stopped working while still appearing registered. The runner now
reports those capabilities as a `capabilities_unreachable` step and in the turn
metadata, and the admin log viewer shows them, so the next one is visible
instead of being discovered by a user.

**The Ember test harness could not boot.** `@ember/legacy-built-in-components`
was never a dependency, so `assets/vendor.js` failed before any test loaded and
no QUnit test in this package had ever run. Adding it lets the harness start.
The engine also builds lazily, and a lazy bundle is unreachable from the dummy
application's test bundle, so addon modules could not be imported even once the
harness booted; it now builds eagerly under `ember test` only, leaving the
shipped lazy bundle unchanged. The six inline-code and autolink tests now
actually execute.

**`composer test:types` never passed.** `--memory-limit=0` is rejected by PHP,
which reads it as zero bytes rather than unlimited, and level max reported 1053
pre-existing errors. The flag is now `-1`, those errors are captured in
`phpstan-baseline.neon` so new code must stay clean, and a stub resolves
`Illuminate\Foundation\Bus\Dispatchable`, which ships in laravel/framework
rather than the split illuminate packages this package depends on. `composer
test` now runs lint, types and tests end to end.
CI installs with a frozen lockfile, so pnpm-lock.yaml has to carry
@ember/legacy-built-in-components alongside package.json.
…Content

Both views were hard to read and slow to use. Logs stacked three 360px
scroll boxes inside a boxed panel, applied its ten filters only on a
"Search logs" click, and hid every prompt and answer behind a Reveal step
with a confirm dialog and an extra request. Analytics was six raw integer
tiles over six stacked tables.

**Logs** is now a full-height split view: a compact toolbar whose filters
apply as they change (search waits for a pause, rarely used filters sit
behind "More filters" with a count), a two-line conversation list showing
the signals a reviewer scans for (negative feedback, failures, degraded or
cut-off answers) with keyboard navigation and load more, and the selected
conversation read as a transcript. Each turn renders the answer's markdown
and shows its status, model, tokens, duration, flags, feedback comment,
errors and unreachable capabilities; its audit steps load on first open.
Exports use the same filters as the list, or a single conversation.

**Reveal Content is gone.** Anyone who can view the logs sees full
conversations, and exports need the same `ai view audit logs` permission
instead of `ai view task content`, which nothing checks any more. Exports
are still written to the access log. This also fixes the task metadata
summary silently dropping `unreachable_capabilities`. Because full
content is now always sent, a conversation's steps are counted rather
than loaded and fetched per turn on demand.

**Analytics** opens on the last 30 days with period presets, a KPI strip
of formatted numbers (conversations, success rate, not helpful, degraded
and cut off, alongside answers and tokens), answers and tokens per day on
a chart, and Who/What rankings with each row's share of tokens; clicking a
row filters the view to it. The usage endpoint adds those counts and the
effective range, and zero-fills days with no activity; all new keys are
additive.

Both views opt in to full-bleed admin pages (fleetbase/fleetbase console
change). On a console without it they still work inside the boxed panel
at a bounded height.

The shared filter state and number formatting replace logic that was
duplicated between the two views. Ember component tests could not run
before: ember-core imports `tracked-built-ins` without declaring it, so the
dummy app failed to boot. Adding it, and giving testem longer than 10
seconds for the first boot, lets all 24 tests run.
…lbar controls

Dates and numbers in the redesigned views came out in Arabic. The console
force-loads formatjs Intl polyfills whose default locale is whichever
locale data registers first, and these views formatted with Intl and no
locale. Dates (relative times, chart days, preset ranges) now use date-fns,
the library behind format-date-fns, and numbers and chart ticks use the
browser's language explicitly, so they are right even on a console that
still force-loads the polyfills.

The toolbar used custom pill buttons that did not match the rest of
Fleetbase. Degraded, Cut off, More filters, Clear and the period presets
are now ember-ui Buttons, fields use form-input-sm like Fleetbase's own
list toolbars, the search text no longer sits under its icon, and the date
field fills its slot instead of leaving a gap before the next control.
Session status (logs) and answer status, organization and user (analytics)
move behind More filters so a normal-width toolbar fits on one row.
Feature pull requests now target a release branch rather than main, but
CI only ran on pull requests into main, so they merged unchecked. Match
fleetops, which already runs on release/v* and the legacy dev-v* branches.
feat: ground answers in the docs and let the AI propose console actions
@codecov

codecov Bot commented Sep 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (7ca84ca) to head (835248e).

Additional details and impacted files
@@              Coverage Diff              @@
##                main        #7     +/-   ##
=============================================
  Coverage     100.00%   100.00%             
- Complexity       348      1025    +677     
=============================================
  Files             23        58     +35     
  Lines           1470      3629   +2159     
=============================================
+ Hits            1470      3629   +2159     
Flag Coverage Δ
backend 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

… latest

ember-core ^0.3.24 and ember-ui ^0.4.2, the latest published versions.
@roncodes roncodes mentioned this pull request Sep 22, 2026
6 tasks
@roncodes
roncodes merged commit 46ebe2b into main Sep 22, 2026
6 checks passed
@roncodes
roncodes deleted the release/v0.0.5 branch September 22, 2026 11:37
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