-
Notifications
You must be signed in to change notification settings - Fork 0
feat: enrich producer trace correlations #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,4 +2,4 @@ | |
|
|
||
| from __future__ import annotations | ||
|
|
||
| __version__ = "0.4.0" | ||
| __version__ = "0.5.0" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,9 +6,11 @@ | |
| from __future__ import annotations | ||
|
|
||
| import hashlib | ||
| from collections.abc import Mapping | ||
| from typing import Any | ||
|
|
||
| from agent_core.contracts.evidence import EvidencePacket | ||
| from agent_core.contracts.observatory import ObservatoryLink | ||
| from agent_core.contracts.task import TaskEnvelope | ||
| from agent_core.contracts.tracing import TraceEvent | ||
|
|
||
|
|
@@ -73,18 +75,88 @@ def trace_event_from_context_pack( | |
| pack: dict[str, Any], *, run_id: str | None = None | ||
| ) -> TraceEvent: | ||
| ref_count = len(pack.get("included_refs", []) or []) | ||
| first_source = _first_source_ref(pack) | ||
| return TraceEvent.model_validate( | ||
| { | ||
| "event_type": "knowledge_context_pack", | ||
| "node_id": "context_pack", | ||
| "agent_role": _string_or_none(pack.get("role")) or "knowledge_retriever", | ||
| "summary": f"context pack {pack.get('id')} ({ref_count} refs)", | ||
| "payload": { | ||
| "id": pack.get("id"), | ||
| "task_id": pack.get("task_id"), | ||
| "role": pack.get("role"), | ||
| "retrieval_version": pack.get("retrieval_version"), | ||
| "policy_version": pack.get("policy_version"), | ||
| "policy_decision": pack.get("policy_decision"), | ||
| "authority_max": evidence_from_context_pack(pack).authority_max, | ||
| "included_ref_count": ref_count, | ||
| }, | ||
| "run_id": run_id, | ||
| "run_id": run_id | ||
| or _string_or_none(pack.get("run_id") or pack.get("knowledge_snapshot")), | ||
|
Comment on lines
+95
to
+96
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a context pack is emitted without an explicit Useful? React with 👍 / 👎. |
||
| "graph_id": GRAPH_ID, | ||
| "trace_id": _string_or_none(pack.get("id")), | ||
| "case_id": _string_or_none(pack.get("case_id")), | ||
| "handoff_id": _string_or_none(pack.get("handoff_id")), | ||
| "objective_id": _string_or_none(pack.get("objective_id")), | ||
| "change_id": _string_or_none(pack.get("change_id") or pack.get("task_id")), | ||
| "repository": first_source[0], | ||
| "commit_sha": first_source[1], | ||
| "links": _links_for_context_pack(pack), | ||
| } | ||
| ) | ||
|
|
||
|
|
||
| def _links_for_context_pack(pack: Mapping[str, Any]) -> list[ObservatoryLink]: | ||
| links = [ | ||
| ObservatoryLink( | ||
| kind="knowledge", | ||
| label="Context pack", | ||
| ref_id=_string_or_none(pack.get("id")) or "", | ||
| metadata={"knowledge_snapshot": pack.get("knowledge_snapshot")}, | ||
| ) | ||
| ] | ||
| for ref in pack.get("included_refs", []) or []: | ||
| if not isinstance(ref, Mapping): | ||
| continue | ||
| raw_ref = _string_or_none(ref.get("ref") or ref.get("doc_id") or ref.get("doc_path")) | ||
| if raw_ref: | ||
| links.append( | ||
| ObservatoryLink( | ||
| kind="knowledge", | ||
| label=str(ref.get("authority") or ref.get("kind") or "knowledge ref"), | ||
| ref_id=raw_ref, | ||
| metadata={ | ||
| "authority": ref.get("authority"), | ||
| "kind": ref.get("kind"), | ||
| "review_status": ref.get("review_status"), | ||
| "commit_sha": ref.get("commit_sha"), | ||
| }, | ||
| ) | ||
| ) | ||
| return links | ||
|
|
||
|
|
||
| def _first_source_ref(pack: Mapping[str, Any]) -> tuple[str | None, str | None]: | ||
| fallback: tuple[str | None, str | None] = (None, None) | ||
| for ref in pack.get("included_refs", []) or []: | ||
| if not isinstance(ref, Mapping): | ||
| continue | ||
| raw_ref = _string_or_none(ref.get("ref") or ref.get("doc_id") or ref.get("doc_path")) | ||
| if not raw_ref: | ||
| continue | ||
| repository = raw_ref.split(":", 1)[0] if ":" in raw_ref else None | ||
| commit_sha = _string_or_none(ref.get("commit_sha")) | ||
| if repository or commit_sha: | ||
| if commit_sha: | ||
| return repository, commit_sha | ||
| if fallback == (None, None): | ||
| fallback = (repository, commit_sha) | ||
| return fallback | ||
|
|
||
|
|
||
| def _string_or_none(value: Any) -> str | None: | ||
| if value is None: | ||
| return None | ||
| text = str(value).strip() | ||
| return text or None | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a legacy
loop_trace.jsonhas nochange/change_idbut the caller passesrun_id, this fallback stores the run ID inchange_id. The collector surfaceschange_idsin run summaries and filters/v1/actionsby exactchange_id(agent_core/collector/app.py:210-212andagent_core/collector/app.py:249), so runs with no actual change are advertised as if they changedrun-...and can match change filters incorrectly. Leavechange_idnull unless the trace provides a real change identifier.Useful? React with 👍 / 👎.