feat: split runtime context from coding agent, add project id (#6867)
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Check Documentation Broken Links / Check broken links (push) Has been cancelled
Vulnerability Scan / Detect changes (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Build uv cache / build-cache (3.10) (push) Has been cancelled
Build uv cache / build-cache (3.11) (push) Has been cancelled
Build uv cache / build-cache (3.12) (push) Has been cancelled
Build uv cache / build-cache (3.13) (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled

* feat(telemetry): split runtime context from coding agent, add project id

The coding-agent field answered two questions at once. A run with no TTY
reported "non_interactive" and an editor's integrated terminal reported
"vscode_terminal", both in the same field as the assistant name, so a run
that never had an assistant to detect was indistinguishable from one
whose assistant we failed to recognize. Together those two values were
the majority of what the field reported.

detect_coding_agent now answers only which assistant, returning "unknown"
when no marker matches. detect_runtime_context answers where the process
runs: ci, serverless, hosted_ide, notebook, container, the editor
terminals, and the interactive/non_interactive fallback. Both ride on
every span, so an assistant running inside CI reports both rather than
one masking the other.

The runtime markers are published platform contracts - CI providers,
container and serverless runtimes, hosted IDEs - so unlike the assistant
table they need no per-tool verification step. Presence is checked; no
value is read. The assistant table is unchanged: its entries still
require a confirmed, session-scoped variable, and the existing guard test
still enforces that.

Spans also carry project_id when the project declares one. It is read
through the read-only accessor, since minting an id belongs to the CLI
commands a user invoked rather than to a library call during execution,
and it is omitted entirely for projects without one. The attributes are
computed once per process and memoized, so the project file is not
re-read for each provider.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs: document execution environment telemetry attributes

Adds the execution-environment row to the data table in en, ar, ko and
pt-BR. Covers the assistant and runtime fields this branch splits apart
and the project id, and states that detection reads only whether known
environment variables are set.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(telemetry): detect runtime markers by presence, split paas from serverless

Three findings from the CodeRabbit, code-quality and Cursor reviews.

The runtime loop tested truthiness while constants.py documented presence,
so a platform exporting a bare CI= fell through to the TTY fallback and
was mislabelled as an ordinary local run. Presence is now what it says.
The assistant markers keep truthiness deliberately: there an empty value
means the tool set a placeholder rather than claiming the session.

DYNO and WEBSITE_INSTANCE_ID marked Heroku dynos and Azure App Service
instances as serverless, and since serverless is checked first they could
never reach the container label. They move to a paas context, which is
what they are: long-lived containers rather than per-invocation
functions. AWS_EXECUTION_ENV is dropped entirely - it is set on ECS and
EC2 as well as Lambda, and AWS_LAMBDA_FUNCTION_NAME already covers Lambda
without the collision.

The container probe no longer wraps os.path.exists in a try/except.
os.path.exists handles OSError internally and returns False, so the
handler guarded a condition that cannot occur and only hid the intent.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* feat(telemetry): widen assistant detection from published marker sets

The table previously covered three assistants because the rest were
unverified. They are documented after all: vercel/detect-agent publishes
a machine-readable detection matrix (agents.json), corroborated by the
proposal in agentsmd/agents.md#136 and by microsoft/vscode#311734.

Adds cline, gemini_cli, augment, opencode, antigravity and junie, plus
CLAUDE_CODE alongside CLAUDECODE. Gemini's marker is confirmed by its own
docs, which state that run_shell_command sets GEMINI_CLI=1 in the
subprocess environment.

Rule 2 excluded several entries those sources list. Goose's
GOOSE_PROVIDER and Copilot's COPILOT_MODEL and COPILOT_GITHUB_TOKEN are
user configuration, and a committed .env carrying one would relabel every
ordinary run - the AIDER_MODEL trap the guard test already pins, now
parametrized over all four. Replit's REPL_ID names a hosted environment
rather than an assistant, so it stays a runtime context. Copilot sets no
session marker at all today; that is an open request upstream.

The new assistants are ordered ahead of Cursor, since CURSOR_* is set for
every integrated terminal and would otherwise mask anything spawned
inside it - the same ordering Codex already needed.

Also adds the proposed cross-vendor AI_AGENT marker as a last resort,
reported as "other". It establishes that an assistant is present without
naming one, and its value is an arbitrary vendor string, so the value is
never read.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(deps): raise gitpython and pypdf floors for new advisories

gitpython 3.1.57 carries GHSA-9rj7-rf2p-w77r, GHSA-4gmw-gg2m-w46p,
GHSA-hh9p-6wh2-4mfc, GHSA-wvpp-8hx9-p66j and GHSA-jm78-9fvv-mhgr: further
unguarded git option forwarding in Repo.init, read-tree and git-config,
plus arbitrary file read via --pathspec-from-file. Fixed in 3.1.58.

pypdf 6.14.2 carries GHSA-fwg2-594c-jp42 and GHSA-fp3f-mc75-235c,
unbounded runtime and memory on large content and /ToUnicode streams.
Fixed in 6.15.0.

Both floors were already pinned, so only the versions move. Their
exclude-newer-package cutoffs had to move with them - 3.1.58 landed
2026-08-04 and 6.15.0 on 2026-08-06, both past the existing dates, so the
resolver could not have seen either release.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(telemetry): share assistant precedence with the env-context path

Four findings from the Cursor and CodeRabbit reviews, three of them the
same root cause.

get_env_context restated the precedence the shared table already defines,
so every marker added for telemetry was invisible to it: a session
exposing only CLAUDE_CODE reported claude_code on spans while emitting
DefaultEnvEvent, and an assistant running inside a Cursor terminal
reported that assistant on spans while emitting CursorEnvEvent. It now
walks CODING_AGENT_ENV_MARKERS and maps the three assistants that have an
event class of their own, defaulting the rest to DefaultEnvEvent. A test
now asserts the two paths agree for every marker in the table, so they
cannot drift again.

The generic AI_AGENT marker was documented as presence-only but ran
through the truthiness loop with everything else, so an empty value fell
through to unknown. It moves out of the table and is checked by presence
after it, which also keeps the named markers' truthiness intact.

Azure Functions run on the App Service host and inherit
WEBSITE_INSTANCE_ID, so moving that marker to paas would have relabelled
them. The FUNCTIONS_* markers are checked first to keep them serverless.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(telemetry): stop export assertions depending on test order

test_all_common_attributes_land_on_exported_spans failed in CI with an
IndexError on an empty span list, and only in one shard: the suite runs
with OTEL_SDK_DISABLED set, so TracerProvider hands out no-op tracers and
an export-based assertion sees zero spans rather than a wrong attribute.
It passed only when it happened to run after a test whose fixture flips
the variable, which random ordering decides.

Adds an otel_enabled fixture that sets the variable for the four tests
asserting on exported spans. Three of them predate this branch and had
the same latent dependency - they are fixed here because the new test
made the ordering hit reachable, and leaving them would keep the required
check red.

Verified by running every test in the file individually, all of which
previously exposed the dependency, and the telemetry suite three times
under random ordering.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
João Moura
2026-08-07 21:28:52 -03:00
committed by GitHub
parent 5fa010450b
commit 92012aec55
11 changed files with 715 additions and 125 deletions

View File

@@ -46,6 +46,7 @@ os.environ['OTEL_SDK_DISABLED'] = 'true'
| نعم | بيانات دورة حياة المهمة | تشمل: أوقات الإنشاء وبدء/انتهاء التنفيذ، معرّفات الطاقم والمهمة. مخزنة كنطاقات مع طوابع زمنية. لا بيانات شخصية. |
| نعم | سمات LLM | تشمل: الاسم، model_name، model، top_k، temperature، واسم فئة LLM. كلها بيانات تقنية غير شخصية. |
| نعم | محاولة نشر الطاقم باستخدام CLI الخاص بـ CrewAI | تشمل: حقيقة إجراء النشر ومعرّف الطاقم، وما إذا كان يحاول سحب السجلات، لا بيانات أخرى. |
| نعم | بيئة التنفيذ | تشمل: مساعد البرمجة بالذكاء الاصطناعي الذي يشغّل العملية إن وُجد (واحد من قائمة ثابتة مثل `claude_code` أو `codex` أو `cursor` أو `unknown`)، ومكان تشغيل العملية (واحد من قائمة ثابتة مثل `ci` أو `container` أو `serverless` أو `interactive`)، و`project_id` من ملف `pyproject.toml` عند ضبطه. يتحقق الاكتشاف فقط مما إذا كانت متغيرات البيئة المعروفة مضبوطة، ولا يقرأ قيمها أبدًا. لا بيانات شخصية. |
| لا | بيانات الوكيل الموسّعة | تشمل: وصف الهدف، نص الخلفية، معرّف ملف موجهات i18n. يجب على المستخدمين التأكد من عدم تضمين معلومات شخصية في حقول النص. |
| لا | معلومات المهمة التفصيلية | تشمل: وصف المهمة، وصف المخرجات المتوقعة، مراجع السياق. يجب على المستخدمين التأكد من عدم تضمين معلومات شخصية في هذه الحقول. |
| لا | معلومات البيئة | تشمل: المنصة، الإصدار، النظام، الإصدار، وعدد وحدات المعالجة المركزية. مثال: 'Windows 10'، 'x86_64'. لا بيانات شخصية. |

View File

@@ -46,6 +46,7 @@ os.environ['OTEL_SDK_DISABLED'] = 'true'
| Yes | Task Lifecycle Data | Includes: creation and execution start/end times, crew and task identifiers. Stored as spans with timestamps. No personal data. |
| Yes | LLM Attributes | Includes: name, model_name, model, top_k, temperature, and class name of the LLM. All technical, non-personal data. |
| Yes | Crew Deployment attempt using crewAI CLI | Includes: The fact a deploy is being made and crew id, and if it's trying to pull logs, no other data. |
| Yes | Execution Environment | Includes: which AI coding assistant is running the process, if any (one of a fixed list such as `claude_code`, `codex`, `cursor`, or `unknown`), where the process runs (one of a fixed list such as `ci`, `container`, `serverless`, `interactive`), and the `project_id` from your `pyproject.toml` when one is configured. Detection reads only whether known environment variables are set, never their values. No personal data. |
| No | Agent's Expanded Data | Includes: goal description, backstory text, i18n prompt file identifier. Users should ensure no personal info is included in text fields. |
| No | Detailed Task Information | Includes: task description, expected output description, context references. Users should ensure no personal info is included in these fields. |
| No | Environment Information | Includes: platform, release, system, version, and CPU count. Example: 'Windows 10', 'x86_64'. No personal data. |

View File

@@ -45,6 +45,7 @@ os.environ['OTEL_SDK_DISABLED'] = 'true'
| 예 | 작업 라이프사이클 데이터 | 생성 및 실행 시작/종료 시각, crew 및 작업 식별자가 포함됩니다. 타임스탬프를 포함한 span으로 저장됩니다. 개인 정보 없음. |
| 예 | LLM 속성 | LLM의 이름, model_name, 모델, top_k, temperature 및 클래스명이 포함됩니다. 모두 기술적이고 비개인 정보입니다. |
| 예 | crewAI CLI를 통한 Crew 배포 시도 | 배포가 시도되고 있고 crew id가 포함되며, 로그를 가져오려고 하는 경우에만 해당. 다른 데이터 없음. |
| 예 | 실행 환경 | 포함: 프로세스를 실행 중인 AI 코딩 어시스턴트(있는 경우, `claude_code`, `codex`, `cursor`, `unknown` 등 고정 목록 중 하나), 프로세스가 실행되는 위치(`ci`, `container`, `serverless`, `interactive` 등 고정 목록 중 하나), 그리고 `pyproject.toml`에 설정된 경우 `project_id`. 감지는 알려진 환경 변수의 설정 여부만 확인하며 값은 읽지 않음. 개인 데이터 없음. |
| 아니오 | 에이전트 확장 데이터 | 목표 설명, 배경 이야기 텍스트, i18n 프롬프트 파일 식별자가 포함됩니다. 사용자들은 텍스트 필드에 개인 정보가 포함되지 않도록 해야 합니다. |
| 아니오 | 상세 작업 정보 | 작업 설명, 예상 출력 설명, 컨텍스트 참조가 포함됩니다. 사용자들은 이러한 필드에 개인 정보가 포함되지 않도록 해야 합니다. |
| 아니오 | 환경 정보 | 플랫폼, 릴리즈, 시스템, 버전, CPU 개수가 포함됩니다. 예: 'Windows 10', 'x86_64'. 개인 정보 없음. |

View File

@@ -46,6 +46,7 @@ os.environ['OTEL_SDK_DISABLED'] = 'true'
| Sim | Dados do Ciclo de Vida da Tarefa | Inclui: horários de criação, início/fim de execução, identificadores de crew e tarefa. Armazenado como spans com timestamps. Sem dados pessoais. |
| Sim | Atributos do LLM | Inclui: nome, model_name, model, top_k, temperatura e nome da classe do LLM. Todos técnicos, sem dados pessoais. |
| Sim | Tentativa de Deploy do Crew pelo CLI do crewAI | Inclui: O fato de um deploy estar sendo realizado e o crew id, e se está tentando buscar logs, sem mais dados. |
| Sim | Ambiente de Execução | Inclui: qual assistente de código com IA está executando o processo, se houver (um de uma lista fixa como `claude_code`, `codex`, `cursor` ou `unknown`), onde o processo é executado (um de uma lista fixa como `ci`, `container`, `serverless`, `interactive`) e o `project_id` do seu `pyproject.toml` quando houver um configurado. A detecção lê apenas se variáveis de ambiente conhecidas estão definidas, nunca seus valores. Sem dados pessoais. |
| Não | Dados Expandidos do Agente | Inclui: descrição do objetivo, texto da história, identificador de arquivo i18n prompt. Usuários devem garantir que não haja info pessoal nesses campos de texto. |
| Não | Informações Detalhadas da Tarefa | Inclui: descrição da tarefa, descrição do resultado esperado, referências de contexto. Usuários devem garantir que não haja info pessoal nessas áreas. |
| Não | Informações de Ambiente | Inclui: plataforma, release, sistema, versão e quantidade de CPUs. Exemplo: 'Windows 10', 'x86_64'. Sem dados pessoais. |