UAT: JSON/YAML envelope timing field uses wrong structure — spec requires {duration_ms: N} but implementation produces {start_time, end_time, duration} #1944

Open
opened 2026-04-03 00:20:05 +00:00 by freemo · 1 comment
Owner

Metadata

  • Branch: bugfix/m5-output-timing-duration-ms
  • Commit Message: fix(output): correct timing envelope to use duration_ms per spec
  • Milestone: v3.5.0
  • Parent Epic: #936

Bug Report

Feature Area: CLI output formatting — JSON/YAML envelope structure

Severity: Medium

Parent Epic: #936 (Output Rendering Pipeline Integration)

Summary

The JsonMaterializer and YamlMaterializer produce a timing field in the output envelope with the wrong structure. The spec requires {"duration_ms": N} (a single integer in milliseconds), but the implementation produces {"start_time": ..., "end_time": ..., "duration": ...} (epoch floats and fractional seconds).

Steps to Reproduce

from cleveragents.cli.output import OutputSession
from cleveragents.cli.output.materializers import JsonMaterializer
import json

strategy = JsonMaterializer()
with OutputSession(format='json', command='test', strategy=strategy) as session:
    panel = session.panel('Test')
    panel.set_entry('key', 'value')
    panel.close()

output = strategy.get_output()
data = json.loads(output)
print(data['timing'])
# {'start_time': 1775173623.387, 'end_time': 1775173623.387, 'duration': 0.000155}

Actual Behavior

{
  "timing": {
    "start_time": 1775173623.3870337,
    "end_time": 1775173623.3871891,
    "duration": 0.00015544891357421875
  }
}

Expected Behavior

Per the specification (§Output Rendering Framework / JSON envelope, and all command examples):

{
  "timing": {
    "duration_ms": 42
  }
}

The timing field should contain only duration_ms (an integer representing milliseconds), not raw epoch timestamps or fractional seconds.

Root Cause

In src/cleveragents/cli/output/session.py, the close() method sets timing as:

self._timing = {
    "start_time": self.created_at,
    "end_time": now,
    "duration": now - self.created_at,
}

This produces epoch floats and fractional seconds. The spec requires only duration_ms (integer milliseconds).

Fix Required

Change the timing calculation in OutputSession.close() to:

duration_ms = int((now - self.created_at) * 1000)
self._timing = {"duration_ms": duration_ms}

Code Location

  • src/cleveragents/cli/output/session.py: OutputSession.close() method, timing calculation

Subtasks

  • Create TDD issue-capture test (see companion TDD issue) tagged @tdd_issue, @tdd_issue_<N>, @tdd_expected_fail
  • Fix OutputSession.close() in src/cleveragents/cli/output/session.py to compute duration_ms = int((now - self.created_at) * 1000) and set self._timing = {"duration_ms": duration_ms}
  • Verify JsonMaterializer output envelope timing field matches {"duration_ms": N}
  • Verify YamlMaterializer output envelope timing field matches {duration_ms: N}
  • Remove @tdd_expected_fail tag from TDD test after fix is implemented
  • Tests (Behave): Add/update scenarios asserting correct timing envelope structure for JSON and YAML formats
  • Tests (Robot): Add integration test verifying timing.duration_ms is an integer in command output
  • Verify coverage >=97% via nox -s coverage_report
  • Run nox (all default sessions), fix any errors

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • The companion TDD issue is closed (its PR merged to master before the fix branch is created).
  • A Git commit is created where the first line of the commit message matches the Commit Message in Metadata exactly (fix(output): correct timing envelope to use duration_ms per spec), followed by a blank line, then additional lines providing relevant details about the implementation.
  • The commit is pushed to the remote on the branch matching the Branch in Metadata exactly (bugfix/m5-output-timing-duration-ms).
  • The @tdd_expected_fail tag has been removed from the TDD test; the test now passes normally.
  • The commit is submitted as a pull request to master, reviewed, and merged before this issue is marked done.
  • All nox stages pass.
  • Coverage >= 97%

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-new-issue-creator

## Metadata - **Branch**: `bugfix/m5-output-timing-duration-ms` - **Commit Message**: `fix(output): correct timing envelope to use duration_ms per spec` - **Milestone**: v3.5.0 - **Parent Epic**: #936 ## Bug Report **Feature Area:** CLI output formatting — JSON/YAML envelope structure **Severity:** Medium **Parent Epic:** #936 (Output Rendering Pipeline Integration) ### Summary The `JsonMaterializer` and `YamlMaterializer` produce a `timing` field in the output envelope with the wrong structure. The spec requires `{"duration_ms": N}` (a single integer in milliseconds), but the implementation produces `{"start_time": ..., "end_time": ..., "duration": ...}` (epoch floats and fractional seconds). ### Steps to Reproduce ```python from cleveragents.cli.output import OutputSession from cleveragents.cli.output.materializers import JsonMaterializer import json strategy = JsonMaterializer() with OutputSession(format='json', command='test', strategy=strategy) as session: panel = session.panel('Test') panel.set_entry('key', 'value') panel.close() output = strategy.get_output() data = json.loads(output) print(data['timing']) # {'start_time': 1775173623.387, 'end_time': 1775173623.387, 'duration': 0.000155} ``` ### Actual Behavior ```json { "timing": { "start_time": 1775173623.3870337, "end_time": 1775173623.3871891, "duration": 0.00015544891357421875 } } ``` ### Expected Behavior Per the specification (§Output Rendering Framework / JSON envelope, and all command examples): ```json { "timing": { "duration_ms": 42 } } ``` The `timing` field should contain only `duration_ms` (an integer representing milliseconds), not raw epoch timestamps or fractional seconds. ### Root Cause In `src/cleveragents/cli/output/session.py`, the `close()` method sets timing as: ```python self._timing = { "start_time": self.created_at, "end_time": now, "duration": now - self.created_at, } ``` This produces epoch floats and fractional seconds. The spec requires only `duration_ms` (integer milliseconds). ### Fix Required Change the timing calculation in `OutputSession.close()` to: ```python duration_ms = int((now - self.created_at) * 1000) self._timing = {"duration_ms": duration_ms} ``` ### Code Location - `src/cleveragents/cli/output/session.py`: `OutputSession.close()` method, timing calculation ## Subtasks - [ ] Create TDD issue-capture test (see companion TDD issue) tagged `@tdd_issue`, `@tdd_issue_<N>`, `@tdd_expected_fail` - [ ] Fix `OutputSession.close()` in `src/cleveragents/cli/output/session.py` to compute `duration_ms = int((now - self.created_at) * 1000)` and set `self._timing = {"duration_ms": duration_ms}` - [ ] Verify `JsonMaterializer` output envelope `timing` field matches `{"duration_ms": N}` - [ ] Verify `YamlMaterializer` output envelope `timing` field matches `{duration_ms: N}` - [ ] Remove `@tdd_expected_fail` tag from TDD test after fix is implemented - [ ] Tests (Behave): Add/update scenarios asserting correct `timing` envelope structure for JSON and YAML formats - [ ] Tests (Robot): Add integration test verifying `timing.duration_ms` is an integer in command output - [ ] Verify coverage >=97% via `nox -s coverage_report` - [ ] Run `nox` (all default sessions), fix any errors ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - The companion TDD issue is closed (its PR merged to `master` before the fix branch is created). - A Git commit is created where the **first line** of the commit message matches the Commit Message in Metadata exactly (`fix(output): correct timing envelope to use duration_ms per spec`), followed by a blank line, then additional lines providing relevant details about the implementation. - The commit is pushed to the remote on the branch matching the **Branch** in Metadata exactly (`bugfix/m5-output-timing-duration-ms`). - The `@tdd_expected_fail` tag has been removed from the TDD test; the test now passes normally. - The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done. - All nox stages pass. - Coverage >= 97% --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-new-issue-creator
freemo added this to the v3.4.0 milestone 2026-04-03 00:22:05 +00:00
freemo modified the milestone from v3.4.0 to v3.5.0 2026-04-03 00:22:35 +00:00
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • MoSCoW: MoSCoW/Should Have — bug or error handling improvement.

Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: ca-project-owner

Issue triaged by project owner: - **State**: Verified - **MoSCoW**: MoSCoW/Should Have — bug or error handling improvement. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
cleveragents/cleveragents-core#1944
No description provided.