[AISOS-2158] Improve Langfuse span labels for artifact generation and revisions#148
[AISOS-2158] Improve Langfuse span labels for artifact generation and revisions#148ekuris-redhat wants to merge 9 commits into
Conversation
… revisions Detailed description: - Updated _resolve_workflow_step in src/forge/integrations/langfuse/fields.py to return a structured tag. - Parsed stage/node name, operation type, artifact type, and attempt count. - Prevented epic breakdowns from being labeled as spec approval gates. - Added comprehensive unit test coverage. Closes: AISOS-2158
Auto-committed by Forge container fallback.
… Revisions Detailed description: - Refactored in to support structured tagging. - Correctly maps stage/node, operation type (initial, revision, question, approval gate, breakdown), artifact type, and attempt context. - Added corresponding tests in and ran all unit/integration tests successfully. Closes: AISOS-2158
Detailed description: - Reformatted long line exceeding max length in src/forge/integrations/langfuse/fields.py to comply with standard formatting and satisfy the Ruff linter/formatter. Closes: AISOS-2158-ci-fix
ekuris-redhat
left a comment
There was a problem hiding this comment.
The operation-type detection in _resolve_workflow_step reads is_question, is_revision, revision_requested, and task from the
state dict, but none of these keys are included in _TRACE_FIELD_KEYS (agent.py:61-75). The _forward_trace_fields function filters
them out before they reach the resolver, so at runtime they will always be None.
This means distinguishing questions from approval gates won't work in production — e.g. a question at spec_approval_gate will be
labeled approval_gate instead of question_asking. The tests pass because they inject these flags directly into the state dict,
bypassing the _forward_trace_fields filtering.
Either add is_question, is_revision, revision_requested, and task to _TRACE_FIELD_KEYS, or rework the detection to only use
fields that are actually forwarded.
Also please remove the Pipfile
|
Forge is addressing PR review feedback now. This status update is informational. |
Detailed description: - Added 'is_question', 'is_revision', 'revision_requested', and 'task' to _TRACE_FIELD_KEYS in src/forge/integrations/agents/agent.py to ensure trace fields are preserved and forwarded in the tracing context. - Removed the unused vestigial Pipfile from the root. Closes: AISOS-2158-review-fix
ekuris-redhat
left a comment
There was a problem hiding this comment.
The identity mapping for decompose_epics/generate_tasks in _resolve_workflow_step is dead code — both branches produce the same
result as stage_or_node = node_str. Please simplify by removing the if/else and just using stage_or_node = node_str.
|
Forge is addressing PR review feedback now. This status update is informational. |
ekuris-redhat
left a comment
There was a problem hiding this comment.
Tested locally on a feature workflow (AISOS-2160). The label logic in _resolve_workflow_step is
correct, but current_node in the trace context is stale — every node copies it from the incoming
state via state.get("current_node", ""), which still holds the previous gate's name.
Example: decompose_epics receives current_node = "plan_approval_gate", so the Langfuse trace shows
plan_approval_gate:approval_gate:plan instead of decompose_epics:breakdown:epic_breakdown.
Fix this in _forward_trace_fields in src/forge/integrations/agents/agent.py — resolve the actual
executing node name from the LangGraph runtime context instead of trusting the stale current_node
from the state dict.
|
Forge is addressing PR review feedback now. This status update is informational. |
ekuris-redhat
left a comment
There was a problem hiding this comment.
The ensure_config() fix in _forward_trace_fields only covers wrapper methods (generate_prd,
generate_spec, generate_epics). But there's no generate_tasks wrapper — task_generation.py:308
calls run_task() directly with the stale current_node from state, and _forward_trace_fields is
never invoked.
The same ensure_config() override should be applied in run_task when building trace_state
(agent.py:775-779), so all call paths get the correct node name. Same issue applies to other direct
run_task callers like triage.py:78 and task_takeover_planning.py:129.
Verified locally on AISOS-2160: task generation traces still show
plan_approval_gate:approval_gate:plan.
|
Forge is addressing PR review feedback now. This status update is informational. |
Auto-committed by Forge container fallback.
ekuris-redhat
left a comment
There was a problem hiding this comment.
remove the pipfile as its not needed. Keep all the rest of the code as is.
|
Forge is addressing PR review feedback now. This status update is informational. |
ekuris-redhat
left a comment
There was a problem hiding this comment.
Remove the pipfile as its not needed. Keep all the rest of the code as is.
|
Forge is addressing PR review feedback now. This status update is informational. |
| # Determine artifact_type | ||
| # Map based on node name, task, or state properties | ||
| # Target artifacts: spec, prd, plan, tasks, epic_breakdown, etc. | ||
| artifact_type = "unknown" |
There was a problem hiding this comment.
Q&A spans lose their artifact type on the real execution path. run_task() replaces current_node with LangGraph’s answer_question, so this resolver produces answer_question:question_asking:unknown, even though answer_question() includes artifact_type in the trace state. The unit test passes spec_approval_gate directly and therefore does not exercise that overwrite. Could we prefer the explicit state["artifact_type"] value before falling back to the node/task heuristics, and add an integration-level test for this path?
|
Forge is addressing PR review feedback now. This status update is informational. |
Summary
This pull request improves telemetry accuracy by refactoring the Langfuse span labeling logic to support highly structured workflow tagging. By replacing flat, ambiguous labels with structured classifications, it ensures that token costs, latencies, and generation metrics are correctly attributed to their respective stages rather than leaking into incorrect stages like spec approval gates. This enables clear, reliable dashboard visualization in Grafana to distinguish initial artifact generation, revisions, downstream breakdowns, and approval gates.
Changes
Core Integrations & Telemetry
src/forge/integrations/langfuse/fields.pyto structure theworkflow_steptracing field value using a precise[workflow_stage_or_node]:[operation_type]:[artifact_type](:attempt-[retry_count])pattern._resolve_workflow_steplogic to accurately parse and classify breakdown steps (e.g.,decompose_epics,generate_tasks), approval gates, revisions, and clarification or Q&A flows.is_question,is_revision,revision_requested, andtaskto_TRACE_FIELD_KEYSinsrc/forge/integrations/agents/agent.pyto ensure trace fields are preserved and forwarded in the tracing context.Test Suite Updates
tests/unit/integrations/langfuse/test_fields.py.Implementation Notes
[workflow_stage_or_node]:[operation_type]:[artifact_type]) maintains backward compatibility while introducing hierarchical dimensions suitable for robust Grafana dashboard aggregation and filtering.decompose_epicsto prevent them from being misclassified as upstream spec approval gates.Testing
tests/unit/integrations/langfuse/test_fields.pyto cover all new tagging permutations.Related Tickets
Generated by Forge SDLC Orchestrator