Commit Graph

3132 Commits

Author SHA1 Message Date
rcourtman 50295914c1 Remove hidden discovery provider fallback 2026-06-08 03:48:33 +01:00
rcourtman 92f08a1f16 Add FormatCloudSafeContext: PII-free discovery context for cloud models
Discovery-side enablement for making the Assistant useful on CLOUD models.
Today, sensitive resources route to cloud as a terse redacted summary, so
the Assistant never receives discovery's access context and gives generic
answers — invisibly broken for the majority of users who run cloud AI.

FormatCloudSafeContext returns the operational context the Assistant needs
(service identity, access pattern, config/data/log paths, port numbers)
while omitting PII by construction (no hostname, IP, bind addresses). The
chat sanitizer (Codex's ai/chat + unifiedresources policy lane) can include
this in cloud-routed summaries behind an opt-in, instead of withholding
everything. Local routing keeps using FormatForAIContext (full context).

Tested: includes service/access/paths/ports; rejects hostname + IP.
2026-06-07 23:19:44 +01:00
rcourtman c4523aaf11 Flag stale discoveries (pre-engine-version) for re-run in the panel
Cached discoveries from before the surface/fast-path/nested fixes still
counted as 'fresh' by the time-based window, so the panel showed worse
pre-fix data (what 'surely this isnt done?' surfaced on esphome).

Add servicediscovery.DiscoveryEngineVersion (currently 1), stamped onto
every freshly built discovery (LXC/VM and Docker build sites). Unlike
CLIAccessVersion it is NOT auto-upgraded on read, so a missing/older value
reliably means the result predates the current engine. The per-guest panel
shows an amber 're-run for improved results' nudge when engine version is
below current (CURRENT_DISCOVERY_ENGINE_VERSION, kept in sync).

Contract-neutral re: unified-resources (DiscoveryTab is a consumer; this is
a UI nudge + discovery field, no consumption-contract delta) — landed via
PULSE_ALLOW_CONTRACT_NEUTRAL_COMMIT. Go package + version-stamp test pass;
type-check + eslint clean.
2026-06-07 23:05:46 +01:00
rcourtman 3e0e150f7e Keep same-route retry after hidden stream artifacts 2026-06-07 22:15:52 +01:00
rcourtman ac1628f9b4 Add distinctive-port fast-path for un-named workloads
The name fast-path identifies workloads named after their service, but a
workload with a generic name (ct101, db1) still fell through to the model —
which, with a slow reasoning model configured, times out rather than just
being slow. Many such workloads are still identifiable instantly by a
DISTINCTIVE listening port.

Add a Ports field to the identity table (only single-service ports: 8123
HA, 32400 Plex, 5432 postgres, 6379 redis, 1883/8883 mosquitto, 3306
mariadb, 8086 influxdb, 8096 jellyfin, 9090 prometheus, 6052 esphome) and
a second fast-path inferSurfaceIdentityFromPorts that runs after the name
path and before the model. Ambiguous ports (80, 443, 8080, 3000, 5000) are
deliberately excluded — a bad port guess is worse than asking the model.

Parser validated against real ss -tlnp output from LXC 101 (extracts 8123,
ignores ephemeral ports / PIDs / docker-proxy noise → home-assistant).
Unit tests cover distinctive-port matches and ambiguous-only non-matches.
2026-06-07 21:52:41 +01:00
rcourtman 3bbbee323f Detect nested-container access topology in discovery
The fast-path nailed identity but emitted the bare-guest access path, so
for a service running in Docker inside an LXC/VM (e.g. Home Assistant
Container) it told the Assistant to 'pct exec' into the guest shell —
wrong: the service is one layer deeper.

Access topology is index-level 'how to reach it' (only a probe can know a
service runs in a nested container), so re-add a LIGHT nested-container
probe (docker ps names+images, not the deep enumeration) to the LXC/VM
surface sets. When a nested container matches the identified service,
layer cli_access: '... docker exec <container> <command>'. Identity stays
instant from the name; the access path is corrected by one cheap command
when the agent is connected, and falls back to bare-guest guidance when not.

Verified live: HA LXC 101 (homeassistant container under Docker, alongside
watchtower) now yields cli_access including 'docker exec homeassistant',
in ~1s. Tests cover the match (HA by name, postgres by image), non-matches
(watchtower, unrelated service, no docker), and the cli_access layering.
2026-06-07 21:39:22 +01:00
rcourtman 623d3e7749 Add deterministic surface fast-path to discovery (no model for obvious services)
Discovery should be instant for the obvious case: a workload named after
its service ('home-assistant', 'frigate', 'mqtt'…) is identified from the
name alone, with no model call and no command scan needed. This is the
'surface index' — identity + how-to-reach — with depth left to the
Assistant's own knowledge and on-demand commands.

Expand knownServiceIdentities from one entry (esphome) to the common
homelab set, and run inferSurfaceIdentity BEFORE the model: on a
name match, build the identity result and skip the (slow reasoning-model)
analysis entirely. Conservative — name signals only, never broad
command-output guesses — so the model is skipped only on an obvious match;
ambiguous workloads still fall through to full analysis.

Verified live on real infra: HA LXC now identifies in ~0s as Home
Assistant (0.9), no model call, even with the agent disconnected —
previously it timed out at 45s on the reasoning model.

Tests: new inferSurfaceIdentity coverage; updated three tests whose
fixtures were named after known services (they now take the fast-path) —
abstention test uses a generic name, repair test expects 0 model calls,
cached test uses a complete identity. Full package green.
2026-06-07 21:15:11 +01:00
rcourtman f18fb88cdc Make discovery a fast surface scan, not a deep scan
Discovery is the index, not the encyclopedia: it needs to quickly answer
'what is this and how do I reach it', then the Assistant supplies
standard-service knowledge and runs commands on demand for specifics.

Trim the guest command sets to surface identity signals only (OS,
hostname, running services, listening ports, top processes for
LXC/VM; OS, processes, ports, env for Docker). Drop the deep
enumeration — installed_packages, config_files, docker_mounts,
hardware/GPU, disk, cron, nested docker_check — which bloated the
evidence payload (and the AI analysis) for no benefit the Assistant
can't get live. Remove the now-unused dockerMountsCommand const and
retire its test; add TestGuestCommandSetsAreSurfaceOnly to pin the
surface intent (verified live: HA LXC went from 13 commands to 5).

Note: full speed also needs a fast identification path (the configured
reasoning model still exceeds the 45s analysis timeout on its own) —
that's the follow-up.
2026-06-07 20:54:46 +01:00
rcourtman 2d4c98d513 Reject cross-provider Assistant route fallback 2026-06-07 18:13:21 +01:00
rcourtman 738fc4eb13 Reject unsupported Assistant session diff/revert 2026-06-07 18:01:55 +01:00
rcourtman 84ec1a7214 Align Assistant provider retry with OpenCode 2026-06-07 17:04:42 +01:00
rcourtman 5c4b54251d Clarify Assistant gateway fallback and command copy 2026-06-07 16:17:31 +01:00
rcourtman d20017cdb2 Route Assistant gateway fallback through model resolution 2026-06-07 15:45:00 +01:00
rcourtman 8d55796fa1 Add Kubernetes (kubectl exec) cell to the Discovery oracle
Completes the resource-type matrix in the scenario corpus: LXC, Docker,
VM, and now k8s. A redis-pod cache-loss/restart question that needs
kubectl exec access, redis.conf, the rollout-restart command, and the
memory-limit fact — verified through both chat and remediation packs.
Test-only coverage; full servicediscovery package green.
2026-06-07 15:23:25 +01:00
rcourtman 77538f23d0 Add VM (qm guest exec) cell to the Discovery scenario oracle
The corpus covered LXC and Docker workloads but not VMs, which the agent
reaches via the QEMU guest agent (qm guest exec) rather than pct/docker
exec. Add a Plex-on-VM cell — a transcode-failure question that needs the
guest-exec access, the GPU decoder (hardware fact), and the restart
command — verified through both the chat and remediation packs. Test-only
coverage; full servicediscovery package green.
2026-06-07 15:14:13 +01:00
rcourtman 5af2d95df4 Preserve queued Assistant workflow pacing 2026-06-07 15:02:01 +01:00
rcourtman d7f0de0ba2 Add data directories to remediation context
FormatForRemediation surfaced config and log paths but not data paths,
while FormatForAIContext (chat) does. For remediation those matter —
backup targets, disk-full triage, restore points (e.g. a database data
dir or HA's /config/.storage). Add a Data Directories section, matching
the chat pack. Extends the remediation test to assert a data path
reaches it; teeth-checked. Full servicediscovery package green.
2026-06-07 13:36:09 +01:00
rcourtman db28d8bcc3 Grow Discovery scenario oracle: nginx + mosquitto cells
Add two common-service cells to the context oracle. Beyond documenting
nginx and MQTT, they pin two code paths the existing cells did not cover:
the read-only bind-mount marker (nginx config mounted read-only) and
security-category fact surfacing (mosquitto auth). Both pass against the
current formatters (no production gap) — regression protection for the
iter4/iter5 mount + fact-filter work. Corpus now 6 cells (HA-LXC,
HA-Docker, postgres, frigate, nginx, mosquitto). Full package green.
2026-06-07 13:26:30 +01:00
rcourtman 35ae43ca48 Give remediation context the same actionable detail as chat
FormatForRemediation (the discovery context Patrol/remediation consume)
surfaced CLI access, config/log paths and ONLY hardware facts — so the
context meant for fixing a workload never told you how to restart it or
where to edit its files on the host, the two core fix actions. Add a
'Service Control' section (service-category facts: systemd unit / restart
command) and a 'Bind Mounts (host -> container)' section, matching the
parity FormatForAIContext already has after iters 4-7.

New test asserts the restart command and host bind-mount source reach the
remediation context; teeth-checked. Build + vet + gofmt clean, full
servicediscovery package green.
2026-06-07 13:03:32 +01:00
rcourtman af78b1431a Make Assistant startup status feel active 2026-06-07 13:00:53 +01:00
rcourtman b3dc0d1573 Rank facts by actionability so the cap never drops service-control
Iter 5 added service+storage to the surfaced fact categories but the
context pack still capped at the first 5 facts by insertion order — so a
trailing service-control fact (how to restart the workload, the most
actionable one we just started capturing) could be silently dropped,
undermining iter 5-6.

Sort the priority facts by actionability (service > security >
dependency > hardware > version > storage, stable within category)
before capping, and raise the cap 5 -> 8 (still under the analyzer's
12-fact limit). The most useful facts now always survive.

Corpus: add a fact-heavy Frigate cell (6 priority facts, service-control
last). Filter test now asserts cap=8 and that a trailing service fact
sorts first and survives. Both teeth-checked. Full package green.
2026-06-07 12:39:04 +01:00
rcourtman bc864074d6 Ask the analyzer to capture service control + key files
Iterations 4-5 made the context pack SURFACE Docker mounts and
service/storage facts; this closes the CAPTURE side so the analyzer
actually produces them. The workload analysis prompt asked for config
dirs but never for how to restart/reload the service or the specific
files a user edits. Add: (q9) how the service is managed/restarted; an
instruction to put specific key files (configuration.yaml,
automations.yaml, postgresql.conf) in config_paths rather than just the
parent dir; and an instruction to record the service-control mechanism
as a 'service'-category fact. Directly serves the 'reload my automation'
case.

Test pins both instructions in the built deep prompt; teeth-checked.
Build + vet + gofmt clean, full servicediscovery package green.
2026-06-07 12:28:26 +01:00
rcourtman b216e38304 Surface service + storage facts in the AI context pack
filterImportantFacts kept only hardware/dependency/security/version
facts, dropping 'service' and 'storage'. But a service fact (e.g. the
systemd unit) is exactly how the Assistant restarts/reloads a workload,
and a storage fact (the backing dataset/disk) is where its data lives —
neither is redundant with the CLI/path sections, and both are what a
real question like 'the database is slow, restart it' needs. Add both to
the priority categories.

Corpus: add a postgresql LXC cell whose required context includes the
systemd unit and data filesystem. Teeth-checked — the case fails without
the filter change. Build + vet + gofmt clean, full servicediscovery
package green.
2026-06-07 12:19:02 +01:00
rcourtman a256742ab5 Surface Docker bind mounts in the AI context pack + seed Discovery scenario oracle
Two-part start of the Discovery->Assistant context-completeness work.

1. FormatForAIContext (the context pack Chat/Patrol consume) dropped
   DockerMounts, even though the model captures them. A container path
   like /config is meaningless for editing or backing up persistent files
   without its host source, so the Assistant could not act on a real
   request like 'edit my blinds automation on the host'. Surface the
   host -> container mapping (with read-only marker).

2. Add scenario_corpus_test.go — the verifiable oracle for the goal:
   given a realistic discovered workload, the context pack must surface
   everything the Assistant needs to answer a concrete user question with
   zero re-explanation. Seeded with Home Assistant (LXC: pct exec +
   automations.yaml + log; Docker: docker exec + bind-mount source). The
   corpus grows one service-type cell at a time; a missing substring is a
   concrete gap to close in the analyzer or formatter.

Teeth-checked: the Docker case fails without change #1. Build + vet clean,
full servicediscovery package green.
2026-06-07 12:09:27 +01:00
rcourtman 50d9fcd021 Add Assistant session compaction 2026-06-07 10:55:13 +01:00
rcourtman 67444c3fb9 Restore Assistant session model route 2026-06-07 08:43:10 +01:00
rcourtman 59e23a8030 Bound Assistant fallback startup latency 2026-06-07 04:33:37 +01:00
rcourtman eda53f0b1a Suppress compacted Assistant artifact text 2026-06-07 04:09:45 +01:00
rcourtman b04a7f5938 Show skipped Assistant tools in transcript 2026-06-07 03:59:52 +01:00
rcourtman 132b466f39 Anchor Assistant final answers after tools 2026-06-07 01:09:51 +01:00
rcourtman c25629ddf0 Keep provider reasoning out of visible answers 2026-06-07 01:01:41 +01:00
rcourtman 42f4a7028d Surface Assistant idle progress on SSE streams 2026-06-07 00:06:34 +01:00
rcourtman 335c37b01a Preserve explicit Assistant tool intent 2026-06-06 23:48:15 +01:00
rcourtman ad8373eec6 Show Assistant provider route start events 2026-06-06 23:30:12 +01:00
rcourtman e44b11f4d0 Improve Assistant tool activity rows 2026-06-06 21:58:17 +01:00
rcourtman 3c74fe2ca0 Start Assistant runtime in mock mode 2026-06-06 21:39:39 +01:00
rcourtman d674d11ae8 Add Assistant mock tool stream fixture 2026-06-06 21:21:03 +01:00
rcourtman e4ac092876 Add Assistant stream idle progress 2026-06-06 19:59:34 +01:00
rcourtman 44e8a1b2bd Add Assistant turn undo and redo 2026-06-06 19:42:27 +01:00
rcourtman 5503e15d23 Add Assistant session rename
Add persisted session rename support across the chat store, API contract, and Assistant session picker.
2026-06-06 18:32:21 +01:00
rcourtman d7c5e9c4f9 Implement Assistant session forking 2026-06-06 17:10:09 +01:00
rcourtman 2291924cb6 Show Assistant provider retry progress 2026-06-06 15:55:59 +01:00
rcourtman 49c23d6bed Search Assistant session history 2026-06-06 09:14:06 +01:00
rcourtman 0ad040bdf0 Resolve Assistant plain-text resource context
Attach backend-resolved current_resource context for live Assistant read prompts.
2026-06-06 07:13:05 +01:00
rcourtman 0d8b90ce00 Suppress stale Assistant workflow status 2026-06-06 06:15:20 +01:00
rcourtman 3d5e4b7345 Strip Assistant decorative status symbols 2026-06-06 06:00:53 +01:00
rcourtman d5d8999734 Preserve Assistant restored tool evidence 2026-06-06 05:44:02 +01:00
rcourtman b55f50a482 Stream Anthropic tool argument progress 2026-06-06 05:20:42 +01:00
rcourtman 93344d61b3 Stream Assistant tool argument progress 2026-06-06 05:13:09 +01:00
rcourtman f70c0214db Align Assistant tool context and progress visibility 2026-06-06 04:02:07 +01:00