Commit Graph

3557 Commits

Author SHA1 Message Date
rcourtman cdae56df0f Align qualification wait with subscription preflight 2026-07-16 10:05:20 +01:00
rcourtman b84f650e77 Allow bounded subscription-agent preflights 2026-07-16 09:54:34 +01:00
rcourtman 2bc48774c2 Let deleted hosts re-enroll with a freshly generated token
Deleting a host writes a machine-id-keyed removal block that rejected
every future report with HTTP 400, and the error pointed at an Allow
reconnect control that is not wired into the UI, leaving the machine
permanently unable to enroll without changing its machine-id (#1581).

Three holes made the block effectively immortal:
- The 24h TTL sweep only iterated the in-memory removal maps, which
  reset on every restart, so persisted blocks never expired. Sweep the
  persisted entries by their own RemovedAt for host agents, Docker
  hosts, and Kubernetes clusters.
- AllowHostAgentReenroll (and the Docker and Kubernetes equivalents)
  bailed out when the ID was missing from the in-memory map, so even
  the API escape hatch stopped clearing persisted blocks after a
  restart. Check and clear the persisted store independently.
- A report presenting an API token created after the removal is
  explicit re-add intent (the user generated a fresh install command),
  so clear the block and accept it. A still-running old agent keeps
  presenting its pre-removal token and stays blocked.

Also reword the rejection to describe the two working recovery paths
instead of the unwired Settings control.
2026-07-16 09:50:04 +01:00
rcourtman 5867d439a3 Reconcile recovery points against source enumerations
The recovery store was upsert-only: backups and snapshots deleted at
the source lingered as recovery_points rows until the 90-day retention
prune. ListRollups kept returning a rollup with a frozen LastSuccessAt,
so the backup-age alert for a deleted guest re-raised every poll cycle
and acknowledging or clearing it could never stick (#1580).

Each backup poll already publishes a complete per-instance enumeration
(partial failures early-return or carry previous entries forward), so
attach a reconcile scope to that ingest batch. After the upsert, points
in the scope (provider + id class + instance) that were not part of the
enumeration are deleted, which lets the existing per-cycle alert sweep
resolve the alert. An empty enumeration is meaningful and clears the
scope, covering the delete-all-backups case from the report.

Also make the async ingest queue batches instead of overwriting the
single pending slot, which silently dropped a full poll cycle whenever
two sources coalesced behind an active batch.
2026-07-16 09:38:53 +01:00
rcourtman 4bd9b0c079 Show timezone on alert email start times
Alert start times are stored in UTC and the email templates rendered
them with no zone conversion or label, so the Started line read as a
local clock while showing UTC (#1582). Convert to the server's local
zone and include the zone name.
2026-07-16 09:29:01 +01:00
rcourtman c70431caaf Honor configured availability poll interval in the scheduler
An availability target's configured poll interval only seeded the
adaptive scheduler: BuildPlan derived every instance's cadence from the
global adaptive bounds, and a failing probe raised the staleness score
and error penalty, collapsing the probe interval toward the global
5-second minimum. With interval 120s and failure threshold 4 the alert
was promised after ~8 minutes of downtime but fired within the first
minute because the four consecutive failures accumulated at the
collapsed cadence (#1582).

Availability checks promise pollInterval x failureThreshold as the
detection window, so the cadence is a user contract, not a scheduling
hint. Add a FixedIntervalPollProvider extension that pins an instance
to its configured interval, implement it for availability targets, and
bypass adaptive selection wherever the next run is computed (plan
building, rescheduling, and the non-adaptive fallback paths).
2026-07-16 09:26:53 +01:00
rcourtman 362b96dbca Repair rejected Patrol finding batch siblings 2026-07-16 07:22:13 +01:00
rcourtman 7a8a090d37 Harden Patrol multi-finding report guidance 2026-07-16 06:40:17 +01:00
rcourtman c527405f16 Reject invalid Patrol reconfirmation prerequisites 2026-07-15 21:20:56 +01:00
rcourtman f8aac166b6 Treat repeated container restarts as actionable evidence 2026-07-15 20:42:17 +01:00
rcourtman e9b23455ba Prevent Patrol from echoing untrusted instructions 2026-07-15 18:59:40 +01:00
rcourtman 473d5ed1b5 Require grounded actionable Patrol findings 2026-07-15 18:44:33 +01:00
rcourtman e3382c8bcb Use authoritative Docker OOM evidence 2026-07-15 17:55:26 +01:00
rcourtman a39150ba4c Make qualification profiles statistically passable 2026-07-15 17:34:57 +01:00
rcourtman d307fe8869 Preserve Patrol investigation evidence continuity 2026-07-15 15:43:18 +01:00
rcourtman 1eb736e359 Add branch-coverage tests for provider tool-artifact leak detectors
New table-driven tests raise branch coverage on
SplitTrailingProviderToolNamePrefix and the JSON and plain function
tool-call leak-index helpers, covering empty content, no-alnum tails,
prefix-hold versus pass-through and regex no-match paths. Test-only.
2026-07-15 15:11:02 +01:00
rcourtman b6ed899ad5 Add branch-coverage tests for provider context and tool-choice helpers
New table-driven tests raise branch coverage on ContextWindowTokens,
extractModelName, isDigits, rateLimitInfo, normalizeOpenAICompatibleChatURL,
stop-reason normalization and the OpenAI, Anthropic and Gemini tool-choice
converters, covering date-suffix stripping, malformed URLs and default arms.
Test-only, no source changes.
2026-07-15 15:08:59 +01:00
rcourtman c775eed739 Add branch-coverage tests for qualification scorer and report helpers
New table-driven tests raise branch coverage on applyGates, ApplyProTrackGates,
findFault, bestFindingMatch, validatePredicates, ApplyQualificationGates,
canonicalToolInput, sanitizeArtifactText and allObservationsPassed, covering
previously uncovered gate arms, grounding misses, redaction and JSON edge
cases. Test-only, no source changes.
2026-07-15 15:04:26 +01:00
rcourtman 7da4890ce9 Add branch-coverage tests for AI tools command classifiers
New table-driven tests raise branch coverage on the timeout, curl/wget,
env and recovery-point canonicalization helpers in internal/ai/tools,
exercising previously uncovered flag-parsing arms, mutation-method
detection and numeric-detail type cases. Test-only, no source changes.
2026-07-15 15:02:19 +01:00
rcourtman 580093155f Resolve canonical Patrol discovery targets 2026-07-15 12:07:42 +01:00
rcourtman 87699dfff3 Align remediation qualification with advertised actions 2026-07-15 11:31:56 +01:00
rcourtman 03ae7d2b58 Score investigation facts without magic words 2026-07-15 10:56:12 +01:00
rcourtman cdc109d408 Publish Patrol investigation limits live 2026-07-15 10:49:16 +01:00
rcourtman a95edafcf1 Qualify model-led Patrol investigations 2026-07-15 10:32:16 +01:00
rcourtman a717790e90 Pin Patrol qualification routes per suite 2026-07-15 09:46:53 +01:00
rcourtman 2774744b11 Preserve canonical resource IDs in Patrol queries 2026-07-15 09:16:39 +01:00
rcourtman a8e42fc7fe Preserve coding-plan provenance in qualification 2026-07-15 00:06:56 +01:00
rcourtman 61ef640a51 Normalize subscription models before CLI execution 2026-07-14 23:45:10 +01:00
rcourtman f03b0c01e7 Add branch-coverage tests for tools canonical query helpers
New white-box table tests over the pure resource-resolution helpers in
internal/ai/tools/current_resource.go, taking canonicalQueryTypeForResolvedResource,
canonicalQueryIDForResolvedResource and resolvedResourceKindMatchesLocation from
partial to full branch coverage. Every kind switch arm, the provider-uid then
resource-id then alias fallback chain, and the nil guards are pinned to exact
output.

One file, tests only, no source changes. Gates green with go test, gofmt and go
vet, plus an adversarial GLM review scoring three KEEP and zero reject.
2026-07-14 23:38:09 +01:00
rcourtman 63442b7fe4 Add branch-coverage tests for patrol runtime failure classifiers
New white-box table tests over the pure error classifiers in
internal/ai/patrol_runtime_failure.go, taking ClassifyProviderConnectionFailure
from 18 percent to full coverage and closing the residual branches in
patrolRuntimeFailureFromError and summarizePatrolRuntimeFailureDetail. Every
reachable switch arm is pinned to its exact diagnostic output, and the four
grouped causes that only preflight and readiness state can set are documented
as out of reach from a plain error input rather than faked.

One file, tests only, no source changes. Gates green with go test, gofmt and
go vet, plus an adversarial GLM review scoring two KEEP, one WEAK and zero
reject.
2026-07-14 23:23:14 +01:00
rcourtman 89a7b88093 Distinguish subscription allowances from API spend 2026-07-14 23:12:37 +01:00
rcourtman 99615c18e3 Support Patrol streaming on subscription routes 2026-07-14 23:05:28 +01:00
rcourtman 917a9e5421 Add local subscription model routes 2026-07-14 22:57:38 +01:00
rcourtman d0d8426cb9 Add branch-coverage tests for qualification contribution helpers
New white-box table tests over the pure validators, predicates and readme
renderer in internal/ai/qualification/contribution.go, covering
ValidateContributionChallenge, validateContributionIdentity,
everyRunChallengeBound, observationsPassedOrEmpty, reportPhasePassed,
ContributionBundle.Validate and renderContributionReadme.

One file, tests only, no source changes. Gates green with go test, gofmt
and go vet, plus an adversarial GLM review scoring seven KEEP and zero
reject.
2026-07-14 22:50:13 +01:00
rcourtman 280a44ef08 Add branch-coverage tests for AI patrol, qualification, tools and agentcapability helpers
New white-box table tests over previously-untested pure functions in
internal/ai (patrol run recency, patrol findings JSON validation),
internal/ai/tools (read-only violation hints, VM config parsing, node
target matching), internal/ai/qualification (compare predicate,
percentile and model summary, runner helpers), internal/ai/chat
(investigation run error, session compaction formatting) and
internal/agentcapabilities (path parameter substitution, markdown
helpers).

Twelve files, tests only, no source changes. All gates green with go
test, gofmt and go vet, plus an adversarial GLM review scoring twelve
KEEP and zero reject.
2026-07-14 22:33:40 +01:00
rcourtman 538c1baaef Add community Patrol qualification exports 2026-07-14 22:08:32 +01:00
rcourtman b540025ef1 Reserve Patrol final finding decision turn 2026-07-14 21:07:49 +01:00
rcourtman 3487b9a98e Require collected negative control convergence 2026-07-14 20:14:35 +01:00
rcourtman 960e9f5e89 Bound Patrol finding verbosity 2026-07-14 19:58:03 +01:00
rcourtman 12f317364a Separate Watch restart detection from investigation 2026-07-14 19:51:53 +01:00
rcourtman 3f94a8f302 Preserve restart evidence in Patrol scope 2026-07-14 19:47:16 +01:00
rcourtman 6e71bcb151 Preserve resolved provider in qualification scoring 2026-07-14 19:38:25 +01:00
rcourtman 739b0c92d4 Align Patrol quiet-run tool contracts 2026-07-14 19:30:45 +01:00
rcourtman 9ea8cb2aa1 Clarify Patrol scope identities and finding reads 2026-07-14 19:23:36 +01:00
rcourtman e008343b7a Align Docker host query schema and executor 2026-07-14 19:13:11 +01:00
rcourtman 3b1bc65b43 Separate Watch symptoms from injected fault targets 2026-07-14 19:02:32 +01:00
rcourtman aa0f9ea5a7 Require collected fault convergence before Patrol 2026-07-14 18:56:06 +01:00
rcourtman 2b271e3e20 Repair disposable dependency qualification fixtures 2026-07-14 18:49:25 +01:00
rcourtman 44d8614330 Bound Patrol finding summary turns 2026-07-14 18:35:17 +01:00
rcourtman d1e8aece7d Price reviewed OpenRouter qualification routes 2026-07-14 18:24:33 +01:00