Commit Graph

8329 Commits

Author SHA1 Message Date
rcourtman 42c4d7549c style(actions): prettier-collapse a one-line expect in the watch-only empty-state test 2026-07-17 23:12:19 +01:00
rcourtman 83909bd19a feat(patrol,actions): route Watch-only installs toward their first governed action
Production telemetry (30d) shows the Pulse Intelligence funnel collapsing at
governed actions: 332 installs enabled chat actions but only 23 created an
action plan. Root cause: both action dials default off, and an install in the
default Watch only mode has no forward path — findings on unlocked installs
show neither an Investigate button (gated on non-monitor modes) nor any nudge
(the Pro handoff only renders when the capability is plan-locked), and the
empty Actions inbox never says why it is empty.

- Patrol findings on unlocked Watch-only installs now offer 'Switch to Ask
  first' in the expanded row (same slot as the Pro handoff), driving
  handleAutonomyChange('approval') so the Investigate action appears in place.
- The empty Actions Open tab now explains that Watch only never queues fixes
  and points at the Patrol mode switch, or names the Pro capability on locked
  installs (presentation-policy aware, upgrade link suppressed with
  hideUpgrade).
- Contracts updated: patrol-intelligence (expanded-row forward-path rule),
  unified-resources (Actions calm-state producer explanation), api-contracts
  (canonical autonomy read/save reuse), frontend-primitives (guidance stays in
  governed presentation helpers).

Verified live on a scratch instance (locked drawer keeps the Pro handoff with
no nudge; empty inbox renders the locked explanation) plus DOM tests for the
unlocked slot, which needs the Pro runtime to exercise live.
2026-07-17 23:09:31 +01:00
rcourtman 0f15de6a4a fix(telemetry): suppress outbound pings while mock mode is enabled
Every mock-mode boot (e2e/CI managed backends, qual runs, demo containers)
was sending startup/heartbeat pings describing the synthetic fixture fleet,
registering as real installs in the license-server telemetry DB and
dominating the VMware/Kubernetes/TrueNAS adoption aggregates (346 of 6,225
weekly-active installs matched the mock signature, incl. 120 of 227 on
6.1.0-rc.1).

- internal/telemetry: route startup and heartbeat sends through sendEvent,
  which drops the ping while mock.IsMockEnabled() is true; checked per event
  so runtime mock toggles take effect immediately. Disclosed in the package
  doc and both PRIVACY.md copies.
- scripts/telemetry_adoption_report.py: exclude historical mock-fleet rows
  (kubernetes_pods = 120×N with vmware_hosts = 7×N, the internal/mock
  fixture template) by default, report the excluded row/install counts, and
  add --include-mock-fleet to audit them. Versions through 6.1.0-rc.2 keep
  pinging the mock fleet until upgraded, so report-side filtering stays
  necessary.
- security-privacy contract: record the mock-mode suppression boundary and
  the report-side mock-fleet exclusion as subsystem invariants.
- Tests: Go sendEvent suppression/sending pair against an httptest endpoint;
  Python signature-matcher and summarize_rows exclusion coverage.
2026-07-17 18:19:18 +01:00
rcourtman 5abb2d8f48 refactor(agentexec): dedupe host operation dispatch and receipt-identity validation
Contract-Neutral: dupl lint dedupe refactor; no behavior or contract delta (typed host-operation dispatch and receipt-identity validation extracted to shared generic helpers)
2026-07-17 17:36:17 +01:00
rcourtman 488731aed3 refactor(hostagent): dedupe the host APT operation handlers behind shared begin/complete helpers
Contract-Neutral: dupl lint dedupe refactor; no behavior or contract delta (host APT handler admission prefix and terminal suffix extracted to shared helpers)
2026-07-17 17:34:01 +01:00
rcourtman a2bcf2e821 refactor(config): dedupe the activity-history record cycle behind a generic helper
Contract-Neutral: dupl lint dedupe refactor; no behavior or contract delta (activity-history record cycle extracted to generic helper)
2026-07-17 17:31:35 +01:00
rcourtman b862723b93 refactor(ai): dedupe guest lifecycle snapshot loops and check the tool-loop helper return
Contract-Neutral: dupl/errcheck lint dedupe refactor; no behavior or contract delta (findings_proxmox_lifecycle snapshot loops extracted to shared helper)
2026-07-17 17:29:22 +01:00
rcourtman dadffe8a26 fix(tlsutil): discard the subprocess kill error explicitly 2026-07-17 17:26:55 +01:00
rcourtman 52eaf49444 style(operationreceipt): goimports the sqlite blank import 2026-07-17 17:24:57 +01:00
rcourtman efe1526aa8 refactor(api): dedupe the dupl lint pairs behind shared helpers
make lint (dupl) flagged two clone pairs: shouldRestartAIChat vs
aiSettingsUpdateTouchesPatrolReadiness shared the forty-field provider
config block, and the approved/rejected action decision-ID collectors in
Pulse Intelligence telemetry differed only by lifecycle state and audit
predicate.

Extract aiSettingsUpdateTouchesProviderConfig for the shared field
check and parameterize pulseIntelligenceActionDecisionIDs by state,
label, and audit predicate, keeping the two named wrappers. The
decision-telemetry contract tests now pin the wrapper call sites, which
still fix the lifecycle state and audit predicate per decision kind.

Contract-Neutral: behavior-preserving dedup of internal helpers to clear dupl lint findings; no public-contract delta
2026-07-17 17:02:24 +01:00
rcourtman 18cb497de1 test(unifiedresources): drop the retired run-command validator pin
The upstream removal of HandleRunCommand's dead legacy body (ec5e44da0)
deleted TestNormalizeRunCommandApprovalTarget with it, but the v6
host-alias standards test still required that test's snippet in
ai_handlers_test.go, so TestV6DirectHostAliasValidatorCoverage failed.
Drop only the retired validator's snippet; the surviving execute and
investigate-alert validator pins keep host-alias rejection covered.
2026-07-17 17:00:12 +01:00
rcourtman e60ae5fc48 style(unifiedresources): goimports the action dispatch store test
Move the blank modernc.org/sqlite driver import into its own group so
the file passes the goimports formatting check in make lint.
2026-07-17 16:58:56 +01:00
rcourtman 12f2611024 fix(ci): stop cancelling in-progress Build and Test runs
cancel-in-progress meant a busy main never completed a verdict: four
consecutive runs were cancelled by follow-up pushes this afternoon, so
the workflow produced neither green nor red for hours. Adopt the Core
E2E concurrency policy instead and let the in-progress run finish while
queued runs collapse to the newest pending one.
2026-07-17 16:47:00 +01:00
rcourtman ec5e44da0c refactor(api): drop dead body of retired HandleRunCommand
The raw-command endpoint answers 410 Gone unconditionally; the old
implementation below the retirement return was unreachable (govet) and
kept normalizeRunCommandApprovalTarget, normalizeAIExecuteTargetType,
and AIRunCommandRequest alive with no live callers. Remove them and the
tests that only exercised the removed helpers.

Contract-Neutral: remove unreachable dead code below the 410 retirement return in HandleRunCommand; endpoint behavior unchanged
2026-07-17 16:39:40 +01:00
rcourtman 971520a8e5 fix(release-control): scrub hook git env in remaining scratch-repo git users
The core.bare=true corruption of the shared repository recurred on
2026-07-17: a script that runs scratch git commands while the pre-commit
environment from a linked worktree (absolute GIT_DIR) is still exported
re-initializes the REAL repository as bare. a0fda6b26 fixed four helper
test files but missed two spots in scripts/release_control/internal:

- verify_commit_slice_test.py's git() helper only popped GIT_INDEX_FILE,
  so its scratch 'git init' calls re-init the real repo when GIT_DIR is
  inherited. It now scrubs via the shared repo_file_io.strip_local_git_env.
- verify_commit_slice.py's production git_env() kept the inherited hook
  env even when unit tests patch REPO_ROOT to a temporary repository,
  pointing git plumbing (including index writes) at the wrong repo. It
  now scrubs in the test-patched branch only, matching format_staged_go.

Regression teeth:
- verify_commit_slice_test.py gains a canary test that exports the real
  hook env shape (absolute GIT_DIR + GIT_INDEX_FILE, no GIT_WORK_TREE —
  with GIT_WORK_TREE set the corruption does not reproduce) against a
  scratch repo + linked worktree and asserts core.bare stays false.
- repo_file_io_test.py (runs in the pre-commit battery) gains a static
  guard failing any release-control *_test.py that runs scratch
  'git init' without referencing strip_local_git_env.
- The six hand-rolled 4-var pop loops from a0fda6b26 migrate to the
  shared strip_local_git_env helper so the guard enforces one pattern.

Verified: full release-control battery green; every touched test file
also green with GIT_DIR/GIT_INDEX_FILE pointed at a canary repo's linked
worktree, canary config and status intact afterward.
2026-07-17 16:39:17 +01:00
rcourtman 065b4a1995 style(frontend): prettier pass on the update-alerts card test 2026-07-17 16:13:04 +01:00
rcourtman 68bdf84508 test(frontend): exercise the container update-alerts card controls
The card from f8e8135a3 had model-level coverage only; nothing rendered
the toggle or delay input. Pin the interaction contract: toggle off
writes -1 and hides the delay input, toggle on restores the previous
positive delay (factory 24 when enabling from a persisted off state),
and delay edits clamp to a positive whole hour so 0 (backend 'unset',
silently reset to 24) can never be produced from the UI.
2026-07-17 16:09:06 +01:00
rcourtman a6f0f9a2ae fix(mock): evaluate docker host alerts in mock mode
checkMockAlerts checked guests, nodes, storage, PBS, and PMG but never
looped over the mock estate's DockerHosts, so no docker container state,
health, metric, update, or swarm service alert could ever fire against
mock data. The generator deliberately keeps one container unhealthy per
estate, and the docker alert lifecycle (disable-all sweeps, update-alert
delay, config reconciliation) was unexercisable in the mock QA surface.

Verified live on a scratch mock instance: canonical docker metric alerts
fire, the Containers global-defaults toggle clears all of them via the
DisableAllDockerContainers sweep (the #1545 fix path), and re-enabling
re-fires them on the next cycle.

Contract-Neutral: mock-mode docker alert evaluation wiring fix; no public contract delta
2026-07-17 16:09:06 +01:00
rcourtman 7675f57349 test(monitoring): pin the recovery-point reconcile wiring and availability fixed-interval provider
Release-level regression pass over the alert lifecycle found two seams
with store/scheduler-level coverage but untested wiring:

- ingestRecoveryPointsBestEffort (#1580): a complete enumeration deletes
  in-scope points the source stopped reporting, an empty enumeration
  clears the scope, and a failed upsert skips reconciliation so a broken
  batch cannot delete points the source still reports.
- availabilityPollProvider.FixedInstanceInterval (#1582): the configured
  poll interval reaches the scheduler descriptor exactly (with the
  10s..1h clamp), 0 for disabled or unknown targets, so the adaptive
  scheduler cannot collapse the availability detection window again.
2026-07-17 16:09:06 +01:00
rcourtman 146fdd04e4 test(frontend): capture cache timestamps once in the happy-path hit assertion
Same millisecond-tick flake as the boundary test fixed in 63c2118a1,
one test further down the file: the assertion recomputed now() - 5_000
after the write, so any tick between the two calls failed the exact
oldestDataTimestamp comparison in CI.
2026-07-17 16:02:07 +01:00
rcourtman 72c132d4f0 fix(ci): stub the embedded frontend dist so patrol lifecycle proofs compile
The 'Prove Patrol lifecycle and permission boundaries' step includes
./internal/api, whose frontend_embed.go declares
'//go:embed all:frontend-modern/dist'. CI checkouts never contain that
gitignored build output, so the package failed to compile and the step
died before a single lifecycle test ran (last four runs all red this
way). These proofs exercise Go logic only, so a one-file stub dist
satisfies the embed without paying for a frontend build.
2026-07-17 15:52:22 +01:00
rcourtman ef50c10a9a fix(release-control): scrub inherited git env in hook scratch-repo helpers
Pre-commit runs from a linked git worktree export an absolute GIT_DIR.
The release-control test helpers and the test-patched branch of
git_env() only removed GIT_INDEX_FILE, so their scratch-repo commands
targeted the REAL repository: 'git init' in a tempdir re-initialized it
with core.bare=true (breaking git status/commit for every checkout and
worktree) and the subsequent scratch 'git add' failed the hook.

Scrub GIT_DIR, GIT_WORK_TREE, GIT_INDEX_FILE, and GIT_COMMON_DIR in:
- git_env() of format_staged_go.py, governance_stage_guard.py, and
  subsystem_contracts.py (test-patched branch only; production hook
  behavior unchanged)
- the scratch-repo git() helpers in format_staged_go_test.py,
  governance_stage_guard_test.py, readiness_assertion_guard_test.py,
  subsystem_contracts_test.py

Matches the pattern contract_audit_test.py and status_audit_test.py
already used. Verified the full hook test battery passes with
GIT_DIR/GIT_WORK_TREE/GIT_INDEX_FILE pointed at a canary repo, which
stays un-corrupted.
2026-07-17 15:52:11 +01:00
rcourtman 3f18d78ea0 test(e2e): recover the eight vmware specs from quarantine
Re-pin the six /infrastructure-era specs to the vSphere platform page:
37 keeps its full facets/audit re-pin but is fixme'd because table-row
drawers disable remote history, leaving VMware hosts no reachable
change/action history surface (tracked); 38 and 42 move mention and
chat-turn coverage onto live mock state and the session transport (the
retired /api/ai/chat SSE stub is gone, so 42 proves the rendered
exchange instead of the wire payload); 39 and 41 pin the guest drawer's
read-only vCenter context and admin-action exclusions; 40 pins the
Datastores tab without backup semantics. 22 and 36 pass unchanged.
Verified via the managed local backend with PULSE_MOCK_MODE=true (8
passed, 1 tracked fixme).

Contract-Neutral: E2E quarantine-list shrink is test selection only; no deployment contract delta, mirrors bypass on 725837dc3
2026-07-17 15:37:30 +01:00
rcourtman 8ab5b0b3b4 test(e2e): recover the five truenas specs from quarantine
Re-pin 21 to the consolidated Connected-systems table (the address
column is gone; rows carry source, surfaces, state, and freshness) and
rewrite 26 against live mock websocket state with the stubable
alerts-config activation bypass, since REST resource stubs get
overwritten by state frames. 27, 28, and 31 were environmental-only
failures and pass unchanged against a mock-mode backend. Verified via
the managed local backend with PULSE_MOCK_MODE=true.

Contract-Neutral: E2E quarantine-list shrink is test selection only; no deployment contract delta, mirrors bypass on 725837dc3
2026-07-17 15:02:31 +01:00
rcourtman 725837dc39 test(e2e): quarantine the 50 spec files rotted against the platform-first UI
Core E2E has failed on every push since 2026-06-29. Fifty of the 81 spec
files still assert the pre-platform-first IA (locators, URLs, subheader
copy the June rebuild replaced), and with maxFailures aborting shards at
20 the healthy specs produced no verdict at all. The quarantine list in
playwright.config.ts excludes the rotted files from all three projects so
the remaining 38 files (323 tests, including the smoke and journey
coverage) return to being a live per-push gate.

This is a stopgap, named as such in the config comment. Each quarantined
spec leaves the list by being re-pinned to the current UI, never by
deletion; the recovery effort is tracked separately.

Contract-Neutral: E2E spec quarantine is test selection only; no deployment contract delta, and the contract file is another agent's in-progress work
2026-07-17 14:43:22 +01:00
rcourtman eb5a477dc9 fix(governance): make commit-time guard verdicts survive to CI
Canonical Governance failed on nearly every push today (6 of the last 8
commits) because the local pre-commit hook and the CI workflow disagreed
about the canonical completion guard in two ways.

Frontend-only commits skipped the guard entirely: the hook gated ALL
governance checks behind governance-path detection as a perf
optimization, but subsystem contracts name canonical frontend files, so
those commits landed locally and failed the same guard in CI. The hook
now always runs the (cheap) completion guard; only the multi-minute Go
test and audit battery stays path-gated.

Contract-neutral bypasses did not travel: PULSE_ALLOW_CONTRACT_NEUTRAL_COMMIT
authorized the commit in the local shell and vanished, so CI re-ran the
guard without it and went red. A new prepare-commit-msg hook records the
reason as a Contract-Neutral trailer in the commit message, and the
workflow now evaluates the guard per commit (each commit's file list
against its own parent), honoring the trailer exactly as the commit-time
hook honored the env var. Per-commit evaluation also stops a compliant
commit from being blamed for range-mates.

The new hook is registered as a worktree-sensitive governance file in
governance_stage_guard.py with a matching unit test assert.
2026-07-17 14:35:34 +01:00
rcourtman 63c2118a16 test(frontend): repin four suites to the governed action review and autopilot acknowledgement flows
Build and Test has been red since 2026-07-11 because these tests still
pinned the pre-review-flow behavior:

- apiErrorStatus guardrail expected 3 triggerResourceCommand returns in
  monitoring.ts; the governed container update flow moved two callers out.
- ResourceDetailDrawer docker test drove the retired click-twice confirm;
  the drawer now plans the action and opens ActionReviewDialog, so the
  test pins surface attribution and the dialog handoff instead (the
  dialog's own suite covers approve/execute).
- AIIntelligence patrol tests mocked the old autonomy settings shape and
  expected Autopilot to switch modes directly; settings now carry
  requested/effective levels plus autopilot_acknowledgement, and the
  Autopilot button opens the acknowledgement dialog without saving.
- infrastructureSummaryCache boundary test measured age with real timers,
  so any millisecond tick between write and read flipped the strict >
  verdict; the clock is now frozen for the boundary assertion.
2026-07-17 14:30:06 +01:00
rcourtman f8e8135a32 feat(alerts): expose docker update-alert delay with an off state in the UI
Users hit by unwanted container image update alerts (#1545) had no UI
lever short of disabling all container alerts; updateAlertDelayHours
was backend-only. Add a Container update alerts card to the Docker
thresholds tab with an on/off toggle (off saves -1) and an hours delay
input. The save path normalizes the value so 0 (which the backend
treats as unset and resets to 24) is never emitted, and the snapshot
builder carries the field through unrelated saves.

Also fix the docker-specific-controls gate: it required a legacy
'docker-host' typed resource, which hid the ignored-prefixes and swarm
service cards (and would have hidden this one) for unified-agent Docker
hosts that only appear in the runtime list via their app-containers.
The gate now also accepts any non-TrueNAS container runtime.
2026-07-17 14:23:12 +01:00
rcourtman 8830eb66b7 test(frontend): repin patrol findings badge boundary to getPatrolWorkspaceWorkGroups
The open-work-queue redesign removed findingsBadgePresentation from
PatrolIntelligenceWorkspace; work-group badge tones now resolve in
patrolControlPresentation and render as tone={group.tone} on MetadataBadge.
Repin the boundary assertion to that canonical location.
2026-07-17 14:17:48 +01:00
rcourtman c4433edadf fix(frontend): disable the container update button up front when the server refuses the update capability
The lifecycle buttons already read resource.actionReadiness and render
disabled with the refusal reason before any click. The update button did
not, so a user with a stale or disconnected agent could click Update,
confirm, and only then get the refusal from POST /api/actions/plan
(GitHub #1564). Wire the update button to the same per-resource
readiness data: extract the readiness-refusal resolver shared with the
lifecycle buttons into utils/actionReadiness.ts, thread actionReadiness
through UpdateButtonProps at both render sites (Docker containers table
and the workloads GuestRow via useWorkloads), and render the button
disabled with the refusal reason as its tooltip. The post-click
details.reason path from b3058d47e stays as the backstop for
websocket-hydrated rows, which carry no readiness data until the REST
revalidation lands.
2026-07-17 14:14:38 +01:00
rcourtman b3058d47ea fix(frontend): surface the refusal reason when a container update plan fails
A refused update plan showed only 'Action execution is unavailable'; the
actionable explanation (agent disconnected, agent too old, stale inventory)
arrives in the API error's details.reason and was dropped. Prefer it in the
failure badge and tooltip. Seen in #1564 where the toast gave the reporter
nothing to act on and Actions showed no record (refusal is pre-audit).
2026-07-17 12:07:19 +01:00
rcourtman 562417f847 fix(actions): make the agent-too-old refusal reason actionable
'This agent does not support durable typed-operation receipts' told users
nothing they could act on. Say the agent is on an older version and how to
resolve it. Applies to docker container, host update and host storage
cleanup executors.
2026-07-17 12:05:07 +01:00
rcourtman b75c181888 fix(alerts): clear canonical docker alerts when disable-all toggles are set
The DisableAllDockerContainers and DisableAllDockerServices config sweeps
matched only legacy docker-container-/docker-service- alert ID prefixes.
Canonical stateful alerts (image-update, state, health, replica-gap) are
stored under <resourceID>::<specID> state IDs, so existing alerts survived
the toggle and lingered indefinitely, re-notifying past cooldown.

Match on the docker: resource ID scheme as well as the legacy prefixes.
2026-07-17 12:03:00 +01:00
rcourtman 4a4d8e057a fix(frontend): improve memory bar readability 2026-07-17 11:12:53 +01:00
rcourtman 7ab605452d fix(release): fail closed on malformed release notes 2026-07-17 11:12:22 +01:00
rcourtman d0a0b25c05 Add branch-coverage tests for activeTurnStatus presentation helpers
The active-turn status helpers had 27 uncovered branches its existing suites did
not reach. This covers the tool-label fallback, the retryAfter and startedAt
absent-field fall-throughs, and the skip arms for undefined stream and pending-tool
entries, taking covered branches from 276 to 316.

New test-only file with a distinct branchcov0717 suffix. No source changed.
Verified with vitest and type-check, measured to raise branch coverage over the
pre-existing suite.
2026-07-17 09:01:26 +01:00
rcourtman 22c9e83b15 Add branch-coverage tests for finding, cache and badge presentation modules
aiFindingPresentation had grown a set of badge, tone, label and Patrol
classification helpers its existing suites never called, so this covers 25
previously-uncovered functions plus their fallback and count-edge arms.
workloadsSummaryCache goes from 28 to 76 covered branches across cache
hit/miss/expiry paths, infrastructureSummaryCache picks up its remaining getter
and branch arms, and resourceBadgePresentation covers a further block of edge
branches its two branchcov suites left open.

Four new test-only files with distinct branchcov0717 suffixes alongside the
existing suites. No source changed. Verified with vitest and type-check, each
measured to raise branch or function coverage over the pre-existing suite.
2026-07-17 08:41:04 +01:00
rcourtman 61cdc46ff8 Add branch-coverage tests for four alert and settings presentation modules
These presentation helpers had partial coverage and had grown functions their
existing tests never reached. alertWebhookPresentation goes from 14 to 23 covered
functions, organizationSettingsPresentation from 34 to 42, alertIncidentPresentation
from 37 to 39 with its remaining branches, and ssoProviderPresentation closes its
last four uncovered branches. The new cases exercise the fallback, boundary,
per-role and error-precedence arms the primary tests omit.

Four new test-only files with distinct branchcov0717 suffixes alongside the
existing suites. No source changed. Verified with vitest and type-check, and each
measured to raise branch or function coverage over the pre-existing suite.
2026-07-17 07:41:36 +01:00
rcourtman fe09420bcb Add coverage tests for agentexec lifecycle codec and aicontracts pure helpers
The docker container lifecycle codec in agentexec had a contract test that never
exercised the codec functions at runtime, leaving decode, bind, validate and
identity helpers at zero coverage. This adds a table-driven test taking each to
near or full coverage including every validation error arm. In aicontracts,
CloneActionReference, IsNilAlertPayload and DefaultEngineConfig were uncovered,
so this covers the nil and populated arms and asserts CloneActionReference
produces an independent deep copy.

Both are new test-only files. No source changed. Verified with go test, gofmt
and go vet, with each target function confirmed to move off zero coverage.
2026-07-17 06:53:16 +01:00
rcourtman 4745b34b51 Add branch-coverage tests for three changed frontend model modules
containerUpdateBadgeModel gained update icon and button helpers since its prior
branchcov test, so this covers the three previously-uncovered functions and
their state arms (idle, confirming, updating, success, error and the default).
aiProviderPresentation route-label formatting had fourteen uncovered branches,
now exercised through the four exported entry points. dockerIdentityConflict
conflict collection reaches full branch coverage including the hostnames
fallback and the name fallback chain.

All three are new test-only files under existing __tests__ directories. No source
changed. Each was confirmed with vitest and type-check, and measured to raise
branch or function coverage over the pre-existing suite.
2026-07-17 06:35:00 +01:00
rcourtman 909153a398 Close v6.1.0-rc.2 release claim 2026-07-17 02:17:10 +01:00
rcourtman bb369235d1 Stabilize v5 license migration fixtures v6.1.0-rc.2 2026-07-17 01:02:05 +01:00
rcourtman 2d38cfb9ef Stabilize legacy license exchange test 2026-07-17 00:27:56 +01:00
rcourtman a857c7e783 Prepare v6.1.0-rc.2 release 2026-07-16 23:45:31 +01:00
rcourtman e384c2d762 Release Patrol finding completion claim 2026-07-16 23:06:10 +01:00
rcourtman 76201e89ce Add deep-copy independence and qualification render coverage tests
Two more newly added *_w0716_coverage_test.go files from the same
branch-coverage wave, touching no source and no existing test.

- internal/models deep-copy clone independence for Docker, Kubernetes,
  ZFS and PBS clones, each mutating the original and asserting the clone
  stays unchanged
- internal/ai/qualification lab shell-quoting and resource-name
  rendering plus report replay predicates and markdown renderers
2026-07-16 22:56:24 +01:00
rcourtman e23448df7b Allow Patrol to record sequential findings 2026-07-16 22:50:11 +01:00
rcourtman 82d971d8f0 Reserve Patrol finding completion fix 2026-07-16 22:39:57 +01:00
rcourtman c2b8d6b9a0 Add pure branch-coverage tests for the fresh Patrol and Docker drop
Cover previously-unexecuted branches in modules that gained behavior
since the last wave. All six are newly added *_w0716_coverage_test.go
files that modify no source and no existing test.

- internal/ai/chat investigation-budget injection plus the agentic
  tool-event and string helpers
- internal/ai/qualification manifest Validate error arms and the Patrol
  docker-predicate and finding-prerequisite validators
- internal/unifiedresources adapters transforms and ContractResourceType
- internal/config AIConfig nil-receiver default branches
- pkg/aicontracts orchestrator error methods and investigation config
2026-07-16 22:27:29 +01:00
rcourtman b782cf1165 Release Patrol restart-loop qualification claim 2026-07-16 21:04:56 +01:00