@volter/supercode-health 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -51,8 +51,9 @@ with the same outcome, the same expiry reason, ids and numbers taken out). A kin
51
51
  `windowMin` (60) raises `supercode.failing:<kind>`; it clears when the window holds none of it.
52
52
 
53
53
  `failures.json` in the health directory is the machine's ledger: the releases it ran, each from when it was first
54
- seen running, and when each kind was first seen and under which release. The ledger's first run records what is
55
- already failing as seeded, naming no release for it. A kind first seen under a release the ledger saw the machine
54
+ seen running, and when each kind was first seen and under which release. The ledger's first run records every
55
+ failure the machine's records hold (all of the slow log it keeps, every expiry), not only the window's, as seeded,
56
+ naming no release for it; a run that could not read them seeds at the next. A kind first seen under a release the ledger saw the machine
56
57
  change to, after that change, is new with that release, and its alarm names that release's pull requests (the
57
58
  release writes them into `@volter/supercode`'s `lib/release-changes.json`). With `"failures": { "sayOnChanges":
58
59
  true }` in the config, the pack also comments such a kind once on each of those pull requests through `gh`, as the
package/lib/sample.mjs CHANGED
@@ -3,6 +3,7 @@
3
3
  import { cpus, homedir, loadavg } from 'node:os';
4
4
  import { existsSync, readFileSync, statSync } from 'node:fs';
5
5
  import { run } from './run.mjs';
6
+ import { daemonCall } from './mail.mjs';
6
7
  import { rendererOrigins, originOf, localPort } from './chrome.mjs';
7
8
  import { expiredFailures, failureSummary, keyFor, Ledger, runningRelease, sayOnChanges, slowFailures } from './failures.mjs';
8
9
  import { healthDir } from './paths.mjs';
@@ -423,7 +424,9 @@ export class Sampler {
423
424
  run(bin, ['teams', 'describe'], { timeoutMs: 15_000, env: this.env }).then((r) => ({ ...r, ms: Date.now() - t0 })),
424
425
  run(bin, ['teams', 'launches', 'list'], { timeoutMs: 45_000, env: this.env }),
425
426
  run(bin, ['teams', 'machines', 'list', '--json'], { timeoutMs: 20_000, env: this.env }),
426
- run(bin, ['message', 'expired', '--json'], { timeoutMs: 20_000, env: this.env }),
427
+ // the mailbox's expiries are the daemon's own records (mail step 1): asked of it, never of the native binary
428
+ daemonCall('harness.v1.mail.expired', {}, { env: this.env, timeoutMs: 20_000 })
429
+ .then((answer) => ({ stdout: JSON.stringify(answer?.rows ?? []), error: null }), (error) => ({ stdout: '', error: error.message })),
427
430
  ]);
428
431
  let described = null; try { described = JSON.parse(describe.stdout); } catch { /* the daemon did not answer */ }
429
432
  let data = null; try { data = JSON.parse(status.stdout).data; } catch { /* unreadable */ }
@@ -474,6 +477,12 @@ export class Sampler {
474
477
  const release = runningRelease();
475
478
  this.ledger ??= new Ledger(join(healthDir(this.env), 'failures.json'));
476
479
  this.ledger.running(release, now);
480
+ // the ledger's first run seeds from all the records the machine keeps, not the window alone: a failure that comes
481
+ // and goes (once a few hours) was here before anything watched, and is never named new with a later release
482
+ if (this.ledger.fresh && !unread.length) {
483
+ for (const [kind, seen] of slowFailures(this.env, 0)) this.ledger.seen(kind, seen.last, release);
484
+ for (const [kind, seen] of expiredFailures(expiries, 0)) this.ledger.seen(kind, seen.last, release);
485
+ }
477
486
  const failing = [];
478
487
  for (const [kind, seen] of kinds) {
479
488
  const first = this.ledger.seen(kind, seen.last, release);
@@ -482,7 +491,8 @@ export class Sampler {
482
491
  slow.observations.push({ key: keyFor(kind), family: 'supercode', def: fdef, value: seen.count, unit: `in ${fdef.windowMin} min`, summary, detail: { kind, firstRelease: first.firstRelease, seeded: first.seeded, newWithRelease: isNew, running: release?.version ?? null, prs: isNew ? first.changes?.prs ?? [] : [] } });
483
492
  if (seen.count >= fdef.warn) failing.push({ kind, count: seen.count, first, summary });
484
493
  }
485
- this.ledger.settled();
494
+ // settled only by a cycle that read both records: one that could not read them has not seeded the ledger
495
+ if (!unread.length) this.ledger.settled();
486
496
  slow.readings.supercode.failing = failing.map((f) => ({ kind: f.kind, count: f.count, firstRelease: f.first.firstRelease }));
487
497
  await sayOnChanges({ failing, machine: this.machine, release, ledger: this.ledger, env: this.env, config: cfg });
488
498
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-health",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "type": "module",
5
5
  "description": "Optional machine pack: a cheap, deterministic probe of a machine's vitals that mails the machine's maintainer when a threshold is crossed. Each feature sits behind its own permission barrier.",
6
6
  "license": "MIT",