chore(release): activeagent and actionagent 1.6.2 - #455
Conversation
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6 to 7. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](actions/setup-node@v6...v7) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 7. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](actions/upload-artifact@v4...v7) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2 to 3. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](softprops/action-gh-release@v2...v3) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-version: '3' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Releases both gems from one tag, cut from main at 51c7feb. A minor rather than the 1.5.3 originally planned: the cycle adds ActiveAgent::Base#current_user and the as(...) caller seam, SchemaTools .define/.undefine with a per-model registry, the active_agent:schema_tools generator, schema tools served over the MCP facade, caller inheritance through delegate_to, and the ungrounded_answer evaluation fault. Seven new public APIs across both gems is more surface than a patch number advertises, even though 1.5.2 shipped a feature as a patch. The engine's floor on the framework (activeagent >= 1.4) is unchanged and still correct. activeagents-telemetry stays at ~> 0.1: nothing this cycle calls a 0.3-only API, and ~> 0.1 already resolves the published 0.3.0. Verified: CI green on the base commit across Ruby 3.2/3.3/3.4 and rails7/rails8/railsmain (run 34736861631, 1978 runs, 0 failures, 0 errors); bin/lint clean at 542 files; rake build_all produces activeagent-1.6.0.gem (220 KB, 194 files) and actionagent-1.6.0.gem (512 KB, 111 files), both archives carrying VERSION = "1.6.0" and their asserted entry points. A local suite run reports 34 errors that CI does not. All are environmental, and docs/work/release-1.6.0/validation.md records both causes: placeholder keys in .env.test, and gemfiles/rails8.gemfile.lock being untracked, so CI resolves ruby_llm fresh while a local checkout keeps 1.16.0 — whose Message dropped the tool_calls=/input_tokens= writers that the provider test's StubProvider assigns. Worth its own branch; not a release blocker. Not published. Tag-driven release has never succeeded in this repository: every release.yml run fails at "No trusted publisher configured for this workflow found on rubygems.org", which is why 1.5.1 and 1.5.2 have no tags yet are on RubyGems. The archives are built for the owner to push by hand. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKFMuPp7hiQMutW9N8nKST
… that installs
Two defects with the same shape: each turns a broken run into a
plausible-looking success rather than an error, so neither showed up as a
test failure.
SchemaTools#permitted_filters! validated a filter's column against the
allowlist but passed its value through untouched. A range hash therefore
reached `where` unrecognized, and Rails compiled
`where(due_date: {"before" => x})` to `due_date = NULL` — a predicate no row
satisfies. The tool answered `{count: 0}` with no error and the model
reported that as fact: "0 overdue tickets" against a database holding four.
Equality filters were unaffected, which is why it survived. Comparisons now
build through Arel with the column's own type cast (before, after, lt, lte,
gt, gte, on_or_before, on_or_after; two bounds together express a window),
and an operator outside that roster raises UnpermittedAttribute rather than
returning zero — the same "reject rather than silently ignore" rule an
undeclared column already gets. Only date, datetime, time and numeric
columns are offered a range: a lexical `>` on a name column answers a
question nobody asked.
The range form was also undiscoverable. filter_properties described a date
column as a bare {type: "string", format: "date"}, so the surface could not
express "before today" and a model asking correctly still had no way to ask.
Comparable columns now advertise anyOf: [scalar, range object].
Separately, the railtie prepended GenerationInstrumentation only when
Telemetry.enabled? was already true as railties ran — before
config/initializers/*.rb. An app enabling telemetry from its own
initializer, which is what the docs show, was never instrumented: enabled?
answered true, local_storage was on, the trace model resolved, the store
lambda wrote a row when called by hand, and no generation ever produced a
span to store. Telemetry.configure now installs too when the resulting
config is enabled; instrument_telemetry! is idempotent, so the two paths
cannot double-prepend and initializer order stops mattering.
Both fixes carry tests that fail without them: stashing the source changes
takes schema_tools_test from 0 failures to 6 failures and 1 error, and
instrumentation_install_test from 0 to 2 failures.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
AgentRegistrar deduplicates within Agent.for_owner(owner), and a single-tenant dashboard resolves no owner per trace — deliberately, since it owns everything itself. But for_owner(nil) returns `none` whenever an owner association is configured, which is the ordinary `owned_by :user` install. So the dedupe lookup matched nothing and every ingest registered another copy of the same agent, each taking a random slug suffix from the collision-breaker in observed_slug. MAX_OBSERVED_PER_OWNER did not contain it either: the count that cap reads was taken through the same empty relation, so it was always zero. Invisible until now because it takes real telemetry to see — an eighteen-call evaluation left eighteen identical EvaluationJudgeAgent rows. The existing "reuses the agent record across repeated ingests" test passes because this dummy app configures no owner association at all, where for_owner(nil) is `all`; the bug needs a host that configures one and runs single-tenant. Registration now scopes to the whole table when there is no owner to resolve, which is what for_owner already does for a model with no owner association. Multi-tenant behaviour is untouched: the registrar still returns early when an owner cannot be resolved and multi_tenant is on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Releases both gems from one tag, cut from release/1.6.0 at 877ca0f. A patch, not a minor: no new public surface and no behaviour change for anything that already worked. The cycle is three defects that share a failure mode — a date filter that matched nothing reported zero instead of raising, telemetry that was enabled but never instrumented wrote no traces while every configuration signal read healthy, and an observed agent was re-registered on every trace because the dedupe lookup ran through a relation that can never match. All three produce a confident wrong answer or a silently wrong row rather than an error, which is why none appeared in a suite. Two upgrade notes. A suite filtering on a date column will report different numbers after upgrading, because the filter now compares instead of matching nothing; read the first run as a corrected baseline. And duplicate observed agent rows already written are not cleaned up by the upgrade — delete them once. The engine's floor on the framework (activeagent >= 1.4) is unchanged and still correct; activeagents-telemetry stays at ~> 0.1. Verified: bin/lint clean at 543 files; bin/test 1994 runs, 6489 assertions, 2 failures and 34 errors, matching the pre-change baseline exactly (the failures are the RubyLLM suite, whose optional dependency is absent locally, plus one ordering-sensitive dashboard test that fails identically with and without these changes). Each fix carries a test that fails without it. The built archives were installed as real gems into the support-hub app and the full telemetry and evaluation path exercised end to end against live OpenRouter calls. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
MySQL cannot give a JSON column a default, so an evaluation saved there without `config` reads it back as nil, and `compare_models` raised before the runner did anything else. `criteria` had the same gap on the paths that call `partition`, `select` or `reject` on it. `Evaluation#config` and `#criteria` now read as the empty value their column default supplies on other databases, which also covers rows that already exist. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
`judge_class` resolved the provider, model and credentials on every call and then discarded them whenever `@judge_class` was already set. The work now happens once, inside the memoized block, and the test pins that the provider is resolved a single time per service instance. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Both options existed on `ActionAgent.configure` but neither the dashboard guide nor the generated initializer mentioned them, so a host that wanted a browser redirected to its own sign-in page had to read the engine's controller to find the setting. The Authentication section and the initializer template now show them beside `authentication_method`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Merged onto the release branch, the entries from the three pull requests landed inside the 1.6.0 section by surrounding context. They belong to the next release. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Releases both gems from one tag, cut from release/1.6.0. Agents gain releases (a digest of what the model is given, cut on deploy and pinned to every trace, run and evaluation run), the evaluation model reads its JSON columns as empty rather than nil on MySQL, the Tools tab reads the roster the runner reads, the MCP endpoint answers unsupported methods with 405, and sign_in_path / sign_out_path are documented. Three GitHub Actions bumps ride along. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
CI reading for this preview: lint, API gems and both solid_agent integrations green; 3.4/rails8 green; 3.3/rails8, 3.2/rails7 and 3.4/railsmain red. Everything red traces to #453's test isolation (details and the rails7 |
Three hardenings the hosted platform made to its own copy of the dashboard controllers in September, ported to the engine so a host that mounts it gets the same behaviour. A query value can arrive as a container (`minutes[]=1&minutes[]=2`, or `page[x]=1`), and neither Array nor ActionController::Parameters responds to `to_i`. Every list the dashboard paginates or windows read those params directly and turned a malformed query into a 500. Api::BaseController gains integer_param and clamped_param: a multi-valued param means its first value, a nested object floors to the default. Applied to agent runs, agent analytics, the account analytics, interactions and session recordings. Sandboxes#compare read `providers` as a list. A bare string or a nested object raised NoMethodError; it is now a 400. A recording's show response returned the handoff state — a copy of the visitor's cookies and web storage — unscrubbed, both as its own key and nested inside metadata, while every other read path redacted. Both are now stripped of cookies, session_storage and local_storage; only #handoff returns them, to the owner, when they continue the session. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DkXcH6XVKyD5wYnpLuH9iE
…tracer `swap_global_tracer` turned the global configuration's `enabled` and `local_storage` on and its callers' `ensure` called it again to "restore", so both tests left telemetry on with local storage for the rest of the process. With generation instrumentation on `ActiveAgent::Base`, every later generation in the suite was traced, delivered by the batching reporter's thread on its own connection, and committed — surviving the test transaction and surfacing as observed agents in whichever dashboard test ran next. The swap now returns the tracer and both flags, and `restore_global_tracer` puts all three back. Same-seed full suite on a clean database: 0 failures, no rows committed outside a transaction, none left on disk. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
A second, older source of the dashboard order-sensitivity is fixed on this branch in
Measured with a probe on every ingest and on row counts after each test, same seed, before and after: before — background-thread ingests during dozens of unrelated tests, rows surviving rollback; after, on a clean database — 0 failures, 0 leaked rows, 0 background ingests, 0 rows left on disk. One thing to know for local runs: the leaked rows had been committed to |
The merge of #456 brings the container-valued query parameter coercion, the compare providers validation and the recording show scrub onto the release line; the 1.6.2 section now lists them. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DkXcH6XVKyD5wYnpLuH9iE
Both agent gems now pin release/1.6.2 (activeagents/activeagent#455), which resolves to activeagent 1.6.2 and actionagent 1.6.2 and carries the dashboard API hardening this branch depended on from its own engine branch. The engine's add_agent_releases migration names its prefixed tables; this app mounts the engine with an empty table_name_prefix, so the same columns go on the unprefixed tables here: release_digest on agents, release_digest and revision on agent versions, and agent_version_id on traces, runs and evaluation runs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DkXcH6XVKyD5wYnpLuH9iE
Action Cable reads config/cable.yml for the current environment the first time its server class loads, and keeps what it read. The dummy app does not eager load in test, so that first time was whichever test first broadcast or rendered the dashboard. When the seed put engine_integration_test's staging case first, its stubbed Rails.env had no section in cable.yml: the config came back empty, the adapter fell back to redis, and every later broadcast in the process raised Gem::LoadError for redis-client (28 errors and failures on the rails-main job for 8ebff51, none on the same revision an hour earlier). The helper now loads the config under the real test environment before any test runs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DkXcH6XVKyD5wYnpLuH9iE
Preview of the 1.6.2 cut:
release/1.6.0(already carrying 1.6.0 and 1.6.1, whichmaindoes not yet have) plus every open PR that merges cleanly and passes, with the version bump and changelog on top. Merging this also bringsmainup to the release line, as #442 did for 1.5.2.What is in it
add_agent_releasesmigration, rake tasksagent.toolsfor schema tools, and can change itconfig/criteria), judge class memoized once,sign_in_path/sign_out_pathdocumentedcomparevalidatesproviders, a recording'sshowscrubs cookies and web storage from the handoff stateaction-gh-releasev3,upload-artifactv7,setup-nodev7Plus its own commits: the merged PRs' changelog entries moved out of
## [1.6.0](where a merge onto the release branch places them by context) into the new## [1.6.2]section, the version bump, a telemetry test that restores the global configuration after swapping the tracer, the## [1.6.2]entries for #456, and a test-helper fix for an order-dependent failure the suite already had (below).Not in it, and why
json < 4) — edits only the rootGemfile; the tengemfiles/*.gemfileCI uses keep< 3, so it changes nothing CI runs and leaves its own "json 3 breaksdb:migrate" comment in place. Suggest closing.gemfiles/*.gemfilestill pin~> 5.0; Bundler refuses the conflicting requirement.allowed_toolsandrequire_approvalto option transforms #328, Add llms.txt for machine-readable docs index #313 — feature / red CI since July / conflicting.Blockers before this stops being a preview
maincarrying the fix (the two real-generation tests instrument their own agent class and clear what they stored),mainis merged in here, and CI on the branch head is green.ActiveAgent::Release, a migration, rake tasks — which reads as 1.7.0 rather than 1.6.2. Named 1.6.2 here as requested; renaming is a one-commit change.release.yml, which the gem publish depends on; worth watching the first tag that runs through them.Test isolation fixed on this branch
The rails-main job on 8ebff51 failed with 28 errors, every one
Gem::LoadError: Error loading the 'redis' Action Cable pubsub adapterout ofAgentRun#broadcast_update. Action Cable readsconfig/cable.ymlfor the current environment the first time its server class loads, and the dummy app does not eager load in test, so that first time was whichever test first broadcast; when the seed putengine_integration_test's staging case first, its stubbedRails.envhad no section incable.yml, the config came back empty and the adapter fell back to redis for the rest of the process. Reproduced on Rails 8 with a forced order;test/test_helper.rbnow loads the config under the real test environment before any test runs (f995cc9). Independent of #456; any seed could hit it on any Rails.Worth watching
The rails-main job on f995cc9 errored once, on
Integration::OpenAI::Responses::CommonFormat::ToolsTest"tool_choice_auto Request Building":NoMethodError: undefined method 'each_key' for nilinside WebMock's global-stub bookkeeping (DynamicResponse#evaluate), during the second, WebMock-stubbed replay of the cassette. Green on re-run; #456's own rails-main run saw the Anthropic sibling of the same test fail asConnection error. The 343 integration replay tests pass three times in a row locally on Rails 8, and no file either failure touches changes on this branch, so it is filed here rather than fixed.Verified
release/1.6.0without conflict; Coerce container-valued query params and scrub handoff state on read #456 merged onto this branch without conflict.bin/test(Ruby 3.4.9,gemfiles/rails8.gemfile): 2014 runs, 0 failures on the branch head before Coerce container-valued query params and scrub handoff state on read #456; after it and the helper fix, 2016 runs, 0 failures (local errors only from provider credentials the container lacks).actionagent/frontend: 25 tests, 25 pass.bin/lint: no offenses (549 files); rubocop clean on the files Coerce container-valued query params and scrub handoff state on read #456 and the helper fix touch.🤖 Generated with Claude Code