Skip to content

discovery(slm/infra): 59 pre-existing datetime.utcnow().isoformat() / + Z sites in autobot-slm-backend, autobot-slm-agent, autobot-infrastructure #5263

Description

@mrveiss

Discovered while implementing #5178 Part C

#5178's audit + migration scoped to `autobot-backend/` + `autobot_shared/` only. The new regression-prevention hook (tools/lint/check_no_utcnow_isoformat.py from PR for #5178 Part C) full-scan reveals 59 sites in 19 files outside that scope:

```
=== autobot-slm-backend/ (8 files, 14 sites) ===
slm/agent/agent.py:156, 509
slm/agent/version.py:105
slm/agent/health_collector.py:65
ansible/roles/slm_agent/files/slm/agent/{agent.py:156,509, version.py:105, health_collector.py:56}
api/code_source.py:486
api/websocket.py:147
api/npu.py:198
api/updates.py:553, 578, 612, 619
services/{reconciler.py:920, service_orchestrator.py:539, blue_green.py:1370, code_distributor.py:103, 301}
tests/services/version_checker_test.py:81, 117, 184, 215

=== autobot-slm-agent/ (4 files, 4 sites) ===
agent.py:158, 496
version.py:105
health_collector.py:56

=== autobot-infrastructure/ (7 files) ===
shared/scripts/comprehensive_log_aggregator.py:193, 420, 442 (1 + Z mixed format)
shared/scripts/seq_log_forwarder.py:57 (1 + Z mixed format)
shared/scripts/logging/log_forwarder.py:529, 937 (2 + Z mixed format)
shared/scripts/setup/analytics/setup_seq_analytics.py:296 (1 + Z mixed format)
autobot-backend/scripts/migrations/{migrate_secrets_ownership.py:274,
backfill_activity_user_ids.py:152, 255,
migrate_sessions_user_attribution.py:175, 179,
validate_migration.py:423}

=== autobot-backend/ tests (4 files, 9 sites) ===
tests/api/test_analytics_stratified.py:48, 49
knowledge/knowledge_context_suggestions_test.py:61
security/threat_detection_refactor_test.py:35, 135, 147, 205, 396
security/enterprise/threat_detection/test_learner.py:261, 273, 286, 299
```

Bug class summary

Pattern Count Severity
`datetime.utcnow().isoformat()` 51 tz-naive output (same bug class as #5178)
`datetime.utcnow().isoformat() + "Z"` 8 invalid mixed format (same bug as #5238)

Subscope-by-subscope

autobot-slm-backend/ (Phase 4 candidate)

```
api/, services/, slm/agent/ ← production producers
tests/ ← test fixtures (lower priority)
ansible/roles/.../files/ ← duplicates of slm/agent/ (Ansible-synced node copies)
```

This is a separate component with its own `autobot_shared` import path (the embedded copy per CLAUDE.md memory: "Two `autobot_shared` copies: embedded vs standalone"). Verify imports work before bulk migration.

autobot-slm-agent/ (small)

4 files, 4 sites. Trivial.

autobot-infrastructure/scripts (medium)

Migration scripts + log forwarders. The 4 `+ "Z"` sites match the #5238 pattern. Less-frequently-touched code; still worth fixing for consistency.

Tests

Test files were deliberately excluded from #5178's audit. Whether tests should migrate is a stylistic choice — they don't run in production but mock the data shape. Preserving the exact format the production code USED to produce would mean leaving them. Migrating preserves consistency with the canonical `utc_timestamp()` going forward.

Migration approach

Same mechanical pattern as #5178 Phases 1-3:

  • `datetime.utcnow().isoformat()` → `utc_timestamp()`
  • `datetime.utcnow().isoformat() + "Z"` → `utc_timestamp()` (drops the `+ "Z"`, fixes invalid format)
  • Add `from autobot_shared.time_utils import utc_timestamp` import

Per-component safety check: verify each component imports work (esp. autobot-slm-* which has its own embedded autobot_shared copy).

Sequencing

Phase Scope Risk
4a `autobot-slm-backend/api/`, `services/` (10 files) medium — coordinate with SLM frontend
4b `autobot-slm-backend/slm/agent/`, `autobot-slm-agent/` (8 files including ansible duplicates) low — internal
4c `autobot-infrastructure/scripts/` (7 files) low — scripts
4d tests (4 files) low — stylistic

Acceptance criteria

  • All 59 sites migrated to `utc_timestamp()`
  • `tools/lint/check_no_utcnow_isoformat.py` full-scan returns 0 hits
  • No regression in tests
  • Ansible-synced `autobot-slm-backend/ansible/roles/slm_agent/files/` duplicates kept in sync with originals

Discovered during

#5178 Part C implementation. The regression-prevention hook scanned the WHOLE repo (vs the audit's autobot-backend/ + autobot_shared/ scope) and surfaced these. Filed separately so #5178 stays cleanly scoped to its original target.

Activity

  1. mrveiss commented on Apr 21, 2026

    @mrveiss
    OwnerAuthor

    ✅ Closed with proof — split across 2 PRs to keep deployment isolation concerns separated

    Commits:

    Acceptance Criteria Met:

    • ✅ All 59 sites listed in issue body migrated (17 + 41 = 58; 1 site at knowledge_context_suggestions_test.py:61 skipped intentionally — variable named naive, test deliberately exercises naive-timestamp handling)
    • ✅ datetime.utcnow().isoformat() pattern → utc_timestamp() (where autobot_shared available) or datetime.now(timezone.utc).isoformat() (inline pattern in slm/infra)
    • ✅ datetime.utcnow().isoformat() + "Z" mixed-format bug class (4 sites in shared/scripts/) fixed — concat dropped, canonical +00:00 form produced
    • ✅ Ansible-synced copies (autobot-slm-backend/ansible/roles/slm_agent/files/slm/agent/) updated in lockstep with production source
    • ✅ Per-component verification: each component's autobot_shared availability checked before chosen pattern applied (top-level vs lazy vs inline)

    Evidence: grep -rn 'datetime\.utcnow().isoformat' --include="*.py" autobot-backend autobot-slm-backend autobot-slm-agent autobot-infrastructure → 0 sites remaining (only knowledge_context_suggestions_test.py:61 deliberately retained, documented in PR #5380)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions