`Create Crew Deployment` fires before the API call that creates the
deployment, so it counts creation ATTEMPTS and cannot carry the uuid - the
call that creates the deployment is the call that returns it. Live effect:
`create_deployment` reads 76,015 events with 0 carrying a uuid (0.000%), so
deployments cannot be joined to anything.
Moving the existing span after the response would fix the uuid and silently
redefine the metric, turning attempts into successes; the deployment churn
figures are built on attempts. So this adds a second span rather than moving
the first.
`Crew Deployment Created` fires after `_validate_response`, which raises
SystemExit on failure - a failed create therefore still counts as an attempt
and reports no creation. Both creation paths, git remote and zip upload,
converge on that line and both return the uuid.
Emits no `deploy:created` feature count: the attempt span already does, and a
second emit would double the deployment count that origin-independent
aggregation depends on.
Tests cover the emitter (uuid carried, distinct span name, no second feature
count, absent-vs-empty uuid) and the call site across both creation paths plus
the failure path.
The warehouse consumer must be widened BEFORE this merges or it delivers
nothing: `mv_span_fanout_forward` filters on a hard-coded 13-name allowlist,
and `mv_fanout_deployment_spans`'s `multiIf` ends in a catch-all `remove_crew`
arm that would mislabel the new span. Runbook prepared separately.
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(core): record the running release on every emitted span
Nine of twenty-four span kinds never recorded crewai_version, including the
two highest-volume ones - Task Created and Task Execution - plus Human
Feedback, Flow Plotting, and the whole deployment family. add_crew_attributes
writes crew_key, crew_id and crew_fingerprint but never the release, so any
question filtered by version silently returned nothing for those spans and
per-release comparison was blind to them.
Add it at the fourteen sites that were missing it across both emitters,
matching each module's existing convention: version("crewai") in crewai,
get_crewai_version() with the file's local-import pattern in crewai_core.
Guarded by a test that parses both modules and fails when any method creates
a span without recording the release, so a span added later cannot
reintroduce the gap. Verified non-vacuous: removing the attribute from one
span makes it fail and names that method.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ASfWmW3RGy4qAQm6s8U9jH
* test(core): count spans against release attributes, and cover both emitters
Two review findings, both real.
The guard only asked whether a method mentioned crewai_version anywhere, so a
method opening two spans while recording the release on one of them passed.
task_started is exactly that shape. It now counts start_span calls against
_add_attribute(..., "crewai_version", ...) calls and fails when the second is
smaller, naming the method and both counts. Verified non-vacuous: removing the
attribute from Task Execution alone - which the previous version accepted -
now fails with "task_started (2 span(s), 1 version attribute(s))".
The behavioural cases only ever ran against crewai's emitter, because _emit
builds that singleton, so the five changed crewai_core methods had no
behavioural coverage at all. Added a parametrized case over all eight spans
crewai_core emits, using the fixture already in that file - covering the three
that already recorded the release as well, so a regression there is caught too.
Also removed the function-local `import crewai`: the paths now come from
inspect.getfile() on the two classes, which is both consistent with the file's
existing import style and more direct than guessing the module layout.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ASfWmW3RGy4qAQm6s8U9jH
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Deployments were only countable through two span types that no aggregation
reads, and cli_usage:deploy counted the TUI button rather than deployments.
Emit deploy:created and deploy:pushed alongside the existing spans so a
deployment is countable from the feature-usage aggregation no matter how it
was started, and tag Create Crew Deployment / Start Deployment with
source=cli|tui so the two origins stay distinguishable.
Separately, the TUI's `t` and `d` key bindings dispatch straight to
action_view_traces / action_deploy_crew, which never recorded anything -
only on_button_pressed did. Every keyboard-driven trace view and deploy was
therefore invisible. Move the recording into the actions, which both input
paths funnel through, and past the completed guard so a mid-run keypress
that does nothing is not counted as usage.
Claude-Session: https://claude.ai/code/session_01ASfWmW3RGy4qAQm6s8U9jH
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>