First slice of Phase 3 ("real per-instance telemetry"). Defines the
read-only artifact contract from Decision #1 (sessions, cron, memory,
skills, watchdog alerts, backup history) and ships an admin-gated
backend endpoint that probes the live Hermes instance, gracefully
degrading to status:'unknown' wherever the source isn't readable.
What's new
- `backend/src/modules/hermes-telemetry/types.ts` — Zod schemas for
every section of the snapshot, plus a `HermesProbeStatus` reused
from hermes-ops so the UI can distinguish "definitely empty" from
"couldn't read the source" for each section independently.
- `backend/src/modules/hermes-telemetry/repository.ts` — implementation
that:
* shells out via `runuser -u <user> --` for cross-user instances
(Bheem/uma) the same way `hermes-ops/repository.ts` does;
* parses `hermes sessions stats / cron list / memory list /
skills list --json` when the CLI is present, otherwise
reports status:'unknown';
* tails the watchdog log and buckets each line by severity
(critical / warn / info);
* pulls `git -C <repo> log` against the instance's backup repo
for backup history;
* caches per-instance with a 30s TTL + in-flight coalescing,
same pattern as hermes-ops.
- `backend/src/modules/hermes-telemetry/routes.ts` — admin-only GET
`/api/hermes/telemetry/:instance` (the `instance` path param is
Zod-validated; the response is validated against
`HermesTelemetrySnapshotSchema` before send so a shape regression
surfaces here, not in the UI).
- `backend/src/modules/hermes-telemetry/hermes-telemetry.test.ts` —
6 unit tests: ENOENT-on-everything case validates against the
schema, JSON-parse path for sessions/cron/memory/skills, watchdog
log severity bucketing, backup-history `git log` parsing, cache
hit, per-instance cache isolation. Coverage: 95.17% lines on the
new repository module.
- `backend/vitest.config.ts` — telemetry repository added to the
coverage gate's `include` list (ratchet).
- `web/src/lib/api.ts` — typed surface for the new endpoint:
`HermesTelemetrySnapshot` + sub-types + `api.getHermesTelemetry`.
What's NOT in this slice
- UI consumption. The Task Ledger / Agents / History panes still
render mock data; converting them is queued for the next slices.
This slice ships the contract + the backend so those slices can
build on a stable shape.
- Backward-compat replacement of `/api/hermes/ops` (which is
unauthenticated today). That comes with the Phase 7 auth pass.
Verified: backend typecheck ✅, 57/57 unit tests ✅, web typecheck ✅,
lint 0 errors, coverage gate ≥95% lines on every gated file.
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
36 lines
1.1 KiB
TypeScript
36 lines
1.1 KiB
TypeScript
import { defineConfig } from 'vitest/config';
|
|
|
|
export default defineConfig({
|
|
test: {
|
|
globals: true,
|
|
environment: 'node',
|
|
passWithNoTests: true,
|
|
coverage: {
|
|
provider: 'v8',
|
|
reporter: ['text', 'text-summary'],
|
|
// Only the modules we've explicitly committed to keeping covered are
|
|
// subject to the threshold; the rest of the codebase is reported but
|
|
// not gated. Add files here as they gain a real test suite (ratchet,
|
|
// do not relax).
|
|
include: [
|
|
'src/lib/auth.ts',
|
|
'src/lib/csrf.ts',
|
|
'src/modules/health/repository.ts',
|
|
'src/modules/hermes-ops/repository.ts',
|
|
'src/modules/hermes-telemetry/repository.ts',
|
|
'src/modules/deployments/orchestrator.ts',
|
|
'src/modules/services/repository.ts',
|
|
],
|
|
thresholds: {
|
|
// Module-wide minimums — actual numbers today are well above these
|
|
// (≥95% lines for every gated file). Floor is set conservatively so
|
|
// routine refactors don't trip the gate.
|
|
lines: 85,
|
|
functions: 85,
|
|
statements: 85,
|
|
branches: 65,
|
|
},
|
|
},
|
|
},
|
|
});
|