Skip to content

feat(workspace): wire observability heartbeat + log_level into consumers (#119 PR-3a) - #2551

Merged
HongmingWang-Rabbit merged 1 commit into
stagingfrom
feat/wire-observability-config
May 3, 2026
Merged

HongmingWang-Rabbit merged 1 commit into
stagingfrom
feat/wire-observability-config

Conversation

@HongmingWang-Rabbit

Copy link
Copy Markdown
Contributor

Summary

PR-3a of the #119 hermes-style architecture series. Wires the existing live consumers (heartbeat cadence + uvicorn log level) to read from `ObservabilityConfig` instead of hard-coded constants.

  • `workspace/heartbeat.py`: `HeartbeatLoop` now accepts `interval_seconds=` keyword arg, defaults to the legacy `HEARTBEAT_INTERVAL=30` constant (backward compat for 2-arg callers / existing tests).
  • `workspace/main.py`:
    • Constructs `HeartbeatLoop` with `config.observability.heartbeat_interval_seconds` (the parser-clamped [5, 300] value).
    • `uvicorn.Config` takes `log_level` from `config.observability.log_level` (lowercased — uvicorn's convention) with `LOG_LEVEL` env still winning as an ops debugging override.

Why

PR-1 (#206, schema-only) defined the fields with the comment "wiring lands in PR-3". This is that wiring. Operators can now tune cadence + verbosity per-workspace via `config.yaml` without a code change.

Scope

Adapter EventLog wiring (the third item in the original task #208 description) is deferred to PR-3b — touching `adapter_base` is a wider blast radius, needs careful design, and per code-review-and-quality skill the bias is toward smaller PRs. This PR is the safe + mechanical half.

Test plan

  • `test_heartbeat.py`: 3 new tests pin default interval, explicit override, [5, 300] band acceptance without re-clamping
  • All existing `test_heartbeat.py` + `test_config.py` tests pass (88/88)
  • No behavior change when `config.yaml` omits `observability:` block — defaults match the previous hard-coded values
  • `syntax` check on `main.py` + `heartbeat.py` pass

Stack

🤖 Generated with Claude Code

…119 PR-3a)

Replaces the hard-coded HEARTBEAT_INTERVAL=30 in heartbeat.py and
log_level="info" in main.py with values from
ObservabilityConfig (#119 PR-1, schema landed in PR #2538).

Concrete plumbing:

  - heartbeat.HeartbeatLoop accepts an `interval_seconds=` keyword
    arg. Defaults to the legacy module constant so 2-arg callers
    (existing tests, any downstream code that hasn't been updated)
    keep their existing 30s behavior.
  - main.py constructs HeartbeatLoop with
    config.observability.heartbeat_interval_seconds — the value the
    config parser already clamped to [5, 300].
  - main.py's uvicorn.Config takes log_level from
    config.observability.log_level (lowercased — uvicorn's convention
    differs from Python logging's) with LOG_LEVEL env still winning
    as an ops-side debugging override.

Adapter EventLog wiring deferred to PR-3b (#208 follow-up) — touches
adapter_base interface + needs careful design, kept separate to keep
this PR small + reviewable.

Tests:
  - test_heartbeat.py: 3 new tests pin default interval, explicit
    override, and the [5, 300] band that the constructor accepts
    without re-clamping (clamping is the parser's job).
  - All 88 tests in test_heartbeat.py + test_config.py pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@HongmingWang-Rabbit
HongmingWang-Rabbit added this pull request to the merge queue May 3, 2026
Merged via the queue into staging with commit e2b58f0 May 3, 2026
20 checks passed
@HongmingWang-Rabbit
HongmingWang-Rabbit deleted the feat/wire-observability-config branch May 3, 2026 08:09
HongmingWang-Rabbit pushed a commit that referenced this pull request Jun 12, 2026
…hot tests (fixes #2550, unblocks core gate)' (#2551) from fix/ops-scripts-snapshot-frozen-ts-2550 into main
HongmingWang-Rabbit pushed a commit that referenced this pull request Jun 12, 2026
… tracker

- Merge main (brings in #2551 conductor-snapshot ts fix that unblocks
  Ops Scripts Tests, and the new lint-no-coe-on-required guard).
- Resolve handlers-postgres-integration.yml conflict: both sides keep
  cache:false; merged the comment to preserve the heavy-job examples
  and the cp#698 sweep note.
- Satisfy lint-continue-on-error-tracking (Tier 2e): the advisory
  continue-on-error:true in lint-setup-go-cache.yml now carries an
  internal#881 tracker comment (open, fresh 14d-renewable) per the
  guard the PR itself introduces. Guard logic unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant