docs(roadmap): add agent manifest timestamp test gap

This commit is contained in:
Yeachan-Heo
2026-05-21 17:30:46 +00:00
parent 02b68555f5
commit 2bc85c54c8

View File

@@ -6653,3 +6653,5 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed)
548. **Two timestamp helpers in `tools/src/lib.rs` disagree on their contract: `iso8601_timestamp()` shells out to `/bin/date` for RFC3339, then falls back to `iso8601_now()` which returns epoch seconds, so the same JSON field can change format by host/tool availability** — dogfooded 2026-05-21 from the `#clawcode-building-in-public` 16:30 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@832098c` and binary built from source SHA `25d663d`. Code inspection: `tools/src/lib.rs:6091-6100` implements `iso8601_timestamp()` by spawning `date -u +%Y-%m-%dT%H:%M:%SZ`; if that command is unavailable or fails, it calls `iso8601_now()`. But `iso8601_now()` at `tools/src/lib.rs:5262-5268` serializes `SystemTime::now().duration_since(UNIX_EPOCH).as_secs().to_string()`, yielding strings like `1748004000`, not an ISO/RFC3339 timestamp. `execute_brief` uses `iso8601_timestamp()` for `BriefOutput.sent_at`, so `sent_at` is RFC3339 on hosts with GNU/BSD `date`, but silently becomes epoch-seconds on minimal/sandboxed hosts where `date` is missing or fails. This is adjacent to the LaneEvent timestamp bug reported in the same channel, but distinct: the brief/notification surface has an environment-dependent timestamp format because one helper's fallback violates the other helper's named contract. **Required fix shape:** (a) replace both helpers with one pure Rust RFC3339 UTC formatter using an existing time crate or a tiny internal formatter; (b) remove shelling out to `date` from timestamp generation so output format is host-independent and deterministic; (c) if an epoch timestamp is desired anywhere, name it `unix_epoch_seconds_now` and type it separately, never as an ISO helper fallback; (d) add tests asserting `BriefOutput.sent_at`, AgentOutput `created_at/completed_at`, and LaneEvent timestamps parse as RFC3339 under both normal and forced-fallback conditions; (e) add a contract comment/schema note that string timestamps are RFC3339/ISO-8601 UTC. **Why this matters:** timestamp fields are coordination/log ordering primitives. If the same field is `"2026-05-21T16:30:00Z"` on one host and `"1747845000"` on another, downstream parsers, JSON schemas, and UI timelines cannot trust event ordering or distinguish parse failures from host quirks. Source: gaebal-gajae dogfood response to Clawhip message `1507057919278190654` on 2026-05-21.
549. **G004 conformance validates `laneEvents[].emittedAt` only as a non-empty string, so epoch-seconds timestamps pass the contract even though fixtures and field names imply RFC3339/ISO date-time** — dogfooded 2026-05-21 from the `#clawcode-building-in-public` 17:00 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@d670b43` and binary built from source SHA `25d663d`. Code inspection: `runtime/src/g004_conformance.rs:66-69` requires `/event`, `/status`, and `/emittedAt` to be non-empty strings, but never parses or pattern-checks `/emittedAt`. In `runtime/src/lane_events.rs`, `LaneEvent.emitted_at` is serialized as `emittedAt` and tests/fixtures use RFC3339-looking values like `2026-04-04T00:00:00Z`, but the validator would accept `"1748004000"`, `"not-a-date"`, or any other non-empty string. This compounds #548 and Jobdori's timestamp helper finding: even if producers emit epoch strings from `iso8601_now()`, the advertised machine-checkable G004 contract will not catch the timestamp-format regression. **Required fix shape:** (a) add an RFC3339/ISO-8601 UTC validator for `laneEvents[].emittedAt` in `validate_lane_events`; (b) reject numeric-looking epoch strings and arbitrary prose with a clear error like `expected RFC3339 timestamp`; (c) apply the same validation to report/approval-token date-time fields if the bundle schema has them; (d) add negative tests showing `"1748004000"` and `"not-a-date"` fail while `"2026-04-04T00:00:00Z"` passes; (e) align producer helpers from #548/#549 so conformance and production agree on timestamp contract. **Why this matters:** conformance helpers are supposed to prevent log/event opacity bugs from reaching downstream claws. If the contract only checks non-empty strings, timestamp regressions become invisible until UI parsers, JSON-schema validators, or ordering logic fail later. Source: gaebal-gajae dogfood response to Clawhip message `1507065465552507033` on 2026-05-21.
550. **Agent manifest timestamp tests only assert non-empty/presence, so epoch-seconds `createdAt`/`startedAt`/`completedAt` and lane-event timestamps are baked into tests as acceptable output** — dogfooded 2026-05-21 from the `#clawcode-building-in-public` 17:30 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@02b6855` and binary built from source SHA `25d663d`. Code inspection: `tools/src/lib.rs:2734-2755` defines `AgentOutput.createdAt`, `startedAt`, `completedAt`, and `laneEvents`. Production fills them via `iso8601_now()` at `tools/src/lib.rs:3663`, `3693-3696`, `3912`, and terminal `LaneEvent::*` calls. But the main manifest regression at `tools/src/lib.rs:8147-8152` only asserts `!manifest.created_at.is_empty()`, `started_at.is_some()`, and `completed_at.is_none()`; later completed/failed manifest tests assert event names/status/details/data but never assert that `createdAt`, `startedAt`, `completedAt`, or `laneEvents[].emittedAt` parse as RFC3339. As a result, the current epoch-seconds strings from `iso8601_now()` satisfy the test suite, and a future producer fix could regress again without a red test. **Required fix shape:** (a) add a shared test helper that validates RFC3339/ISO-8601 UTC strings for AgentOutput top-level timestamps and every lane event `emittedAt`; (b) update creation, completion, failure, spawn-error, recovery, review, selection, and artifact manifest tests to call it; (c) add explicit negative/unit coverage proving epoch strings like `"1748004000"` fail the helper; (d) align test fixtures with the G004 conformance timestamp validation required by #549; (e) ensure tests check serialized JSON fields, not only in-memory struct presence. **Why this matters:** tests are currently encoding the broken contract as acceptable by checking only non-empty strings. Without semantic timestamp assertions, timestamp-format fixes in #548/#549 have no durable safety net and downstream parser breakage can reappear silently. Source: gaebal-gajae dogfood response to Clawhip message `1507073019296874608` on 2026-05-21.