@legioncodeinc/hive 0.1.0
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/LICENSE +661 -0
- package/README.md +262 -0
- package/dist/cli-commands.d.ts +41 -0
- package/dist/cli-commands.js +76 -0
- package/dist/cli-commands.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +46 -0
- package/dist/cli.js.map +1 -0
- package/dist/daemon/dashboard/app.js +118 -0
- package/dist/daemon/dashboard/host.d.ts +90 -0
- package/dist/daemon/dashboard/host.js +172 -0
- package/dist/daemon/dashboard/host.js.map +1 -0
- package/dist/daemon/dashboard/web-assets.d.ts +88 -0
- package/dist/daemon/dashboard/web-assets.js +195 -0
- package/dist/daemon/dashboard/web-assets.js.map +1 -0
- package/dist/daemon/fleet-status.d.ts +15 -0
- package/dist/daemon/fleet-status.js +56 -0
- package/dist/daemon/fleet-status.js.map +1 -0
- package/dist/daemon/gate.d.ts +55 -0
- package/dist/daemon/gate.js +128 -0
- package/dist/daemon/gate.js.map +1 -0
- package/dist/daemon/proxy.d.ts +38 -0
- package/dist/daemon/proxy.js +126 -0
- package/dist/daemon/proxy.js.map +1 -0
- package/dist/daemon/registry.d.ts +31 -0
- package/dist/daemon/registry.js +120 -0
- package/dist/daemon/registry.js.map +1 -0
- package/dist/daemon/server.d.ts +41 -0
- package/dist/daemon/server.js +126 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/daemon/setup-auth.d.ts +37 -0
- package/dist/daemon/setup-auth.js +51 -0
- package/dist/daemon/setup-auth.js.map +1 -0
- package/dist/daemon/telemetry-proxy.d.ts +47 -0
- package/dist/daemon/telemetry-proxy.js +63 -0
- package/dist/daemon/telemetry-proxy.js.map +1 -0
- package/dist/dashboard/contracts.d.ts +235 -0
- package/dist/dashboard/contracts.js +43 -0
- package/dist/dashboard/contracts.js.map +1 -0
- package/dist/dashboard/web/app.d.ts +44 -0
- package/dist/dashboard/web/app.js +179 -0
- package/dist/dashboard/web/app.js.map +1 -0
- package/dist/dashboard/web/boot-route.d.ts +23 -0
- package/dist/dashboard/web/boot-route.js +29 -0
- package/dist/dashboard/web/boot-route.js.map +1 -0
- package/dist/dashboard/web/build-graph-button.d.ts +46 -0
- package/dist/dashboard/web/build-graph-button.js +81 -0
- package/dist/dashboard/web/build-graph-button.js.map +1 -0
- package/dist/dashboard/web/buzzing-screen.d.ts +30 -0
- package/dist/dashboard/web/buzzing-screen.js +135 -0
- package/dist/dashboard/web/buzzing-screen.js.map +1 -0
- package/dist/dashboard/web/folder-picker.d.ts +54 -0
- package/dist/dashboard/web/folder-picker.js +125 -0
- package/dist/dashboard/web/folder-picker.js.map +1 -0
- package/dist/dashboard/web/graph-layout.d.ts +101 -0
- package/dist/dashboard/web/graph-layout.js +0 -0
- package/dist/dashboard/web/graph-layout.js.map +1 -0
- package/dist/dashboard/web/harness-strip.d.ts +38 -0
- package/dist/dashboard/web/harness-strip.js +65 -0
- package/dist/dashboard/web/harness-strip.js.map +1 -0
- package/dist/dashboard/web/health-rail.d.ts +26 -0
- package/dist/dashboard/web/health-rail.js +61 -0
- package/dist/dashboard/web/health-rail.js.map +1 -0
- package/dist/dashboard/web/main.d.ts +22 -0
- package/dist/dashboard/web/main.js +51 -0
- package/dist/dashboard/web/main.js.map +1 -0
- package/dist/dashboard/web/needs-project.d.ts +51 -0
- package/dist/dashboard/web/needs-project.js +69 -0
- package/dist/dashboard/web/needs-project.js.map +1 -0
- package/dist/dashboard/web/page-frame.d.ts +95 -0
- package/dist/dashboard/web/page-frame.js +98 -0
- package/dist/dashboard/web/page-frame.js.map +1 -0
- package/dist/dashboard/web/pages/coming-soon.d.ts +23 -0
- package/dist/dashboard/web/pages/coming-soon.js +19 -0
- package/dist/dashboard/web/pages/coming-soon.js.map +1 -0
- package/dist/dashboard/web/pages/dashboard.d.ts +32 -0
- package/dist/dashboard/web/pages/dashboard.js +205 -0
- package/dist/dashboard/web/pages/dashboard.js.map +1 -0
- package/dist/dashboard/web/pages/graph.d.ts +72 -0
- package/dist/dashboard/web/pages/graph.js +362 -0
- package/dist/dashboard/web/pages/graph.js.map +1 -0
- package/dist/dashboard/web/pages/harnesses.d.ts +65 -0
- package/dist/dashboard/web/pages/harnesses.js +210 -0
- package/dist/dashboard/web/pages/harnesses.js.map +1 -0
- package/dist/dashboard/web/pages/health.d.ts +22 -0
- package/dist/dashboard/web/pages/health.js +91 -0
- package/dist/dashboard/web/pages/health.js.map +1 -0
- package/dist/dashboard/web/pages/lifecycle-panel.d.ts +60 -0
- package/dist/dashboard/web/pages/lifecycle-panel.js +187 -0
- package/dist/dashboard/web/pages/lifecycle-panel.js.map +1 -0
- package/dist/dashboard/web/pages/logs.d.ts +55 -0
- package/dist/dashboard/web/pages/logs.js +311 -0
- package/dist/dashboard/web/pages/logs.js.map +1 -0
- package/dist/dashboard/web/pages/memories.d.ts +35 -0
- package/dist/dashboard/web/pages/memories.js +439 -0
- package/dist/dashboard/web/pages/memories.js.map +1 -0
- package/dist/dashboard/web/pages/projects.d.ts +38 -0
- package/dist/dashboard/web/pages/projects.js +325 -0
- package/dist/dashboard/web/pages/projects.js.map +1 -0
- package/dist/dashboard/web/pages/roi-chart.d.ts +52 -0
- package/dist/dashboard/web/pages/roi-chart.js +133 -0
- package/dist/dashboard/web/pages/roi-chart.js.map +1 -0
- package/dist/dashboard/web/pages/roi.d.ts +93 -0
- package/dist/dashboard/web/pages/roi.js +375 -0
- package/dist/dashboard/web/pages/roi.js.map +1 -0
- package/dist/dashboard/web/pages/settings.d.ts +103 -0
- package/dist/dashboard/web/pages/settings.js +420 -0
- package/dist/dashboard/web/pages/settings.js.map +1 -0
- package/dist/dashboard/web/pages/sync.d.ts +59 -0
- package/dist/dashboard/web/pages/sync.js +280 -0
- package/dist/dashboard/web/pages/sync.js.map +1 -0
- package/dist/dashboard/web/panels.d.ts +178 -0
- package/dist/dashboard/web/panels.js +471 -0
- package/dist/dashboard/web/panels.js.map +1 -0
- package/dist/dashboard/web/primitives.d.ts +80 -0
- package/dist/dashboard/web/primitives.js +208 -0
- package/dist/dashboard/web/primitives.js.map +1 -0
- package/dist/dashboard/web/readiness-splash.d.ts +39 -0
- package/dist/dashboard/web/readiness-splash.js +201 -0
- package/dist/dashboard/web/readiness-splash.js.map +1 -0
- package/dist/dashboard/web/registry.d.ts +96 -0
- package/dist/dashboard/web/registry.js +99 -0
- package/dist/dashboard/web/registry.js.map +1 -0
- package/dist/dashboard/web/router.d.ts +48 -0
- package/dist/dashboard/web/router.js +76 -0
- package/dist/dashboard/web/router.js.map +1 -0
- package/dist/dashboard/web/scope-context.d.ts +155 -0
- package/dist/dashboard/web/scope-context.js +266 -0
- package/dist/dashboard/web/scope-context.js.map +1 -0
- package/dist/dashboard/web/service-icons.d.ts +33 -0
- package/dist/dashboard/web/service-icons.js +80 -0
- package/dist/dashboard/web/service-icons.js.map +1 -0
- package/dist/dashboard/web/setup-gate.d.ts +116 -0
- package/dist/dashboard/web/setup-gate.js +272 -0
- package/dist/dashboard/web/setup-gate.js.map +1 -0
- package/dist/dashboard/web/sidebar.d.ts +63 -0
- package/dist/dashboard/web/sidebar.js +91 -0
- package/dist/dashboard/web/sidebar.js.map +1 -0
- package/dist/dashboard/web/use-fleet-telemetry.d.ts +111 -0
- package/dist/dashboard/web/use-fleet-telemetry.js +278 -0
- package/dist/dashboard/web/use-fleet-telemetry.js.map +1 -0
- package/dist/dashboard/web/wire.d.ts +1937 -0
- package/dist/dashboard/web/wire.js +1837 -0
- package/dist/dashboard/web/wire.js.map +1 -0
- package/dist/errors.d.ts +5 -0
- package/dist/errors.js +11 -0
- package/dist/errors.js.map +1 -0
- package/dist/install/registry.d.ts +35 -0
- package/dist/install/registry.js +110 -0
- package/dist/install/registry.js.map +1 -0
- package/dist/lock.d.ts +10 -0
- package/dist/lock.js +87 -0
- package/dist/lock.js.map +1 -0
- package/dist/service/commands.d.ts +15 -0
- package/dist/service/commands.js +49 -0
- package/dist/service/commands.js.map +1 -0
- package/dist/service/index.d.ts +38 -0
- package/dist/service/index.js +174 -0
- package/dist/service/index.js.map +1 -0
- package/dist/service/platform.d.ts +37 -0
- package/dist/service/platform.js +67 -0
- package/dist/service/platform.js.map +1 -0
- package/dist/service/templates.d.ts +10 -0
- package/dist/service/templates.js +120 -0
- package/dist/service/templates.js.map +1 -0
- package/dist/shared/constants.d.ts +15 -0
- package/dist/shared/constants.js +19 -0
- package/dist/shared/constants.js.map +1 -0
- package/dist/shared/daemon-routing.d.ts +11 -0
- package/dist/shared/daemon-routing.js +38 -0
- package/dist/shared/daemon-routing.js.map +1 -0
- package/dist/shared/fleet-readiness.d.ts +18 -0
- package/dist/shared/fleet-readiness.js +9 -0
- package/dist/shared/fleet-readiness.js.map +1 -0
- package/dist/shared/fleet-telemetry.d.ts +68 -0
- package/dist/shared/fleet-telemetry.js +61 -0
- package/dist/shared/fleet-telemetry.js.map +1 -0
- package/dist/shared/lifecycle-flags.d.ts +34 -0
- package/dist/shared/lifecycle-flags.js +39 -0
- package/dist/shared/lifecycle-flags.js.map +1 -0
- package/dist/shared/memory-types.d.ts +55 -0
- package/dist/shared/memory-types.js +75 -0
- package/dist/shared/memory-types.js.map +1 -0
- package/dist/shared/service-status.d.ts +82 -0
- package/dist/shared/service-status.js +97 -0
- package/dist/shared/service-status.js.map +1 -0
- package/dist/telemetry/emit.d.ts +197 -0
- package/dist/telemetry/emit.js +196 -0
- package/dist/telemetry/emit.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared fleet-TELEMETRY shapes — hive PRD-004/PRD-005, mirroring doctor's
|
|
3
|
+
* `src/telemetry/schema.ts` (Contract C in `library/ledger/EXECUTION_LEDGER.md`).
|
|
4
|
+
*
|
|
5
|
+
* hive does not depend on the doctor package (each fleet member is its own published
|
|
6
|
+
* npm package), so this module is a hand-kept, browser-and-server-safe COPY of the wire shape
|
|
7
|
+
* doctor's SSE stream (`GET http://127.0.0.1:3852/events`, event `fleet-telemetry`) actually
|
|
8
|
+
* emits. Keep it in lockstep with doctor's schema.ts if that contract ever changes.
|
|
9
|
+
*
|
|
10
|
+
* `metrics` is deliberately `Readonly<Record<string, number>>`: honeycomb ships three counters
|
|
11
|
+
* (`actionsTaken`, `filesProcessed`, `memoriesCreated`), nectar ships five
|
|
12
|
+
* (`filesRegistered`, `nectarsMinted`, `descriptionsGenerated`, `hiveGraphVersions`,
|
|
13
|
+
* `embeddingsComputed`) — every reader built on this module (PRD-005b's metrics render, PRD-004c's
|
|
14
|
+
* derivation) is schema-tolerant by construction: it never hardcodes one service's key names.
|
|
15
|
+
*/
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
/** The one SSE event name doctor's stream ever emits (mirrors doctor's `ingestion/sse.ts`). */
|
|
18
|
+
export const FLEET_TELEMETRY_EVENT_NAME = "fleet-telemetry";
|
|
19
|
+
// ── Defensive parse (untrusted transport boundary: the SSE frame body / the JSON fetch body) ──
|
|
20
|
+
const FleetHealthSchema = z.enum(["ok", "degraded", "unreachable", "unknown"]);
|
|
21
|
+
const TelemetryFaultReasonSchema = z.enum(["missing", "locked", "malformed", "read-error"]);
|
|
22
|
+
const FleetDeeplakeStatsSchema = z.object({
|
|
23
|
+
connected: z.boolean().nullable(),
|
|
24
|
+
lastCommunicationAt: z.string().nullable(),
|
|
25
|
+
});
|
|
26
|
+
const FleetServiceModelSchema = z.object({
|
|
27
|
+
name: z.string().min(1),
|
|
28
|
+
health: FleetHealthSchema,
|
|
29
|
+
lastSeen: z.string().nullable(),
|
|
30
|
+
metrics: z.record(z.string(), z.number()),
|
|
31
|
+
deeplake: FleetDeeplakeStatsSchema.nullable(),
|
|
32
|
+
telemetryFault: TelemetryFaultReasonSchema.nullable(),
|
|
33
|
+
});
|
|
34
|
+
const FleetLogEntrySchema = z.object({
|
|
35
|
+
service: z.string().min(1),
|
|
36
|
+
ts: z.string().min(1),
|
|
37
|
+
level: z.string().min(1),
|
|
38
|
+
message: z.string(),
|
|
39
|
+
});
|
|
40
|
+
const FleetTelemetryEventSchema = z.object({
|
|
41
|
+
asOf: z.string().min(1),
|
|
42
|
+
services: z.array(FleetServiceModelSchema),
|
|
43
|
+
logs: z.array(FleetLogEntrySchema),
|
|
44
|
+
});
|
|
45
|
+
/**
|
|
46
|
+
* Defensively parse one `fleet-telemetry` SSE frame's `data:` JSON (or the same shape from any
|
|
47
|
+
* future JSON transport). Returns `null` on anything malformed rather than throwing, so one bad
|
|
48
|
+
* frame never crashes the consuming hook (mirrors `fleet-status.ts`'s `safeParse`-and-degrade posture).
|
|
49
|
+
*/
|
|
50
|
+
export function parseFleetTelemetryEvent(raw) {
|
|
51
|
+
let parsedJson;
|
|
52
|
+
try {
|
|
53
|
+
parsedJson = JSON.parse(raw);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const parsed = FleetTelemetryEventSchema.safeParse(parsedJson);
|
|
59
|
+
return parsed.success ? parsed.data : null;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=fleet-telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fleet-telemetry.js","sourceRoot":"","sources":["../../src/shared/fleet-telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAsDxB,+FAA+F;AAC/F,MAAM,CAAC,MAAM,0BAA0B,GAAG,iBAA0B,CAAC;AAErE,iGAAiG;AAEjG,MAAM,iBAAiB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC;AAC/E,MAAM,0BAA0B,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC;AAE5F,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACjC,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC1C,CAAC,CAAC;AAEH,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,MAAM,EAAE,iBAAiB;IACzB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IACzC,QAAQ,EAAE,wBAAwB,CAAC,QAAQ,EAAE;IAC7C,cAAc,EAAE,0BAA0B,CAAC,QAAQ,EAAE;CACrD,CAAC,CAAC;AAEH,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;CACnB,CAAC,CAAC;AAEH,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,uBAAuB,CAAC;IAC1C,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC;CAClC,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,GAAW;IACnD,IAAI,UAAmB,CAAC;IACxB,IAAI,CAAC;QACJ,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;IACD,MAAM,MAAM,GAAG,yBAAyB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC/D,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRD-058d — the single-sourced `memory.lifecycle.*` FLAG REFERENCE (symbol, default, effect).
|
|
3
|
+
*
|
|
4
|
+
* This is the ONE table the settings page renders AND the config-reference doc lists AND the daemon
|
|
5
|
+
* config module re-exports, so the symbol / default / master-equation effect can never drift between
|
|
6
|
+
* the operator surface and the documentation (AC-55d.1.3). It lives in `src/shared` (browser-safe, no
|
|
7
|
+
* `zod`/`process.env`/daemon import) so the DASHBOARD bundle can render it without pulling daemon code
|
|
8
|
+
* across the bundle boundary, while `src/daemon/runtime/memories/lifecycle-config.ts` re-exports it
|
|
9
|
+
* (and OWNS the matching schema defaults, asserted in parity by the lifecycle-config spec).
|
|
10
|
+
*
|
|
11
|
+
* The defaults below are the documented values from `memory-lifecycle-scoring.md`'s "Parameters and
|
|
12
|
+
* defaults" table; the daemon config module's `DEFAULT_*` constants resolve to these same values from
|
|
13
|
+
* the owning engines, and the lifecycle-config spec asserts the two agree (so a future engine default
|
|
14
|
+
* change is caught, not silently drifted).
|
|
15
|
+
*/
|
|
16
|
+
/** One row of the operator-facing flag reference. */
|
|
17
|
+
export interface LifecycleFlagRef {
|
|
18
|
+
/** The mathematical symbol from the scoring doc (`a`, `h(memories)`, `θ_detect`, …). */
|
|
19
|
+
readonly symbol: string;
|
|
20
|
+
/** The `memory.lifecycle.*` config path. */
|
|
21
|
+
readonly configPath: string;
|
|
22
|
+
/** The `HONEYCOMB_LIFECYCLE_*` env override. */
|
|
23
|
+
readonly envOverride: string;
|
|
24
|
+
/** The documented default, rendered for display. */
|
|
25
|
+
readonly defaultValue: string;
|
|
26
|
+
/** The effect on the master equation `P = R · A^a · C^c · (1 − σ)^s · κ` / on detection. */
|
|
27
|
+
readonly effect: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The single source of the lifecycle flag reference (AC-55d.1.3). Every flag from the scoring-doc
|
|
31
|
+
* parameter table plus the two posture flags, each with its symbol, default, config path, env
|
|
32
|
+
* override, and master-equation effect. The settings page + the config-reference doc both read THIS.
|
|
33
|
+
*/
|
|
34
|
+
export declare const LIFECYCLE_FLAG_REFERENCE: readonly LifecycleFlagRef[];
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRD-058d — the single-sourced `memory.lifecycle.*` FLAG REFERENCE (symbol, default, effect).
|
|
3
|
+
*
|
|
4
|
+
* This is the ONE table the settings page renders AND the config-reference doc lists AND the daemon
|
|
5
|
+
* config module re-exports, so the symbol / default / master-equation effect can never drift between
|
|
6
|
+
* the operator surface and the documentation (AC-55d.1.3). It lives in `src/shared` (browser-safe, no
|
|
7
|
+
* `zod`/`process.env`/daemon import) so the DASHBOARD bundle can render it without pulling daemon code
|
|
8
|
+
* across the bundle boundary, while `src/daemon/runtime/memories/lifecycle-config.ts` re-exports it
|
|
9
|
+
* (and OWNS the matching schema defaults, asserted in parity by the lifecycle-config spec).
|
|
10
|
+
*
|
|
11
|
+
* The defaults below are the documented values from `memory-lifecycle-scoring.md`'s "Parameters and
|
|
12
|
+
* defaults" table; the daemon config module's `DEFAULT_*` constants resolve to these same values from
|
|
13
|
+
* the owning engines, and the lifecycle-config spec asserts the two agree (so a future engine default
|
|
14
|
+
* change is caught, not silently drifted).
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* The single source of the lifecycle flag reference (AC-55d.1.3). Every flag from the scoring-doc
|
|
18
|
+
* parameter table plus the two posture flags, each with its symbol, default, config path, env
|
|
19
|
+
* override, and master-equation effect. The settings page + the config-reference doc both read THIS.
|
|
20
|
+
*/
|
|
21
|
+
export const LIFECYCLE_FLAG_REFERENCE = Object.freeze([
|
|
22
|
+
{ symbol: "a", configPath: "memory.lifecycle.activationExponent", envOverride: "HONEYCOMB_LIFECYCLE_ACTIVATION_EXPONENT", defaultValue: "1", effect: "exponent on the activation/freshness term A^a" },
|
|
23
|
+
{ symbol: "c", configPath: "memory.lifecycle.confidenceExponent", envOverride: "HONEYCOMB_LIFECYCLE_CONFIDENCE_EXPONENT", defaultValue: "0", effect: "exponent on the calibrated-confidence term C^c (dormant until calibrated)" },
|
|
24
|
+
{ symbol: "s", configPath: "memory.lifecycle.stalenessExponent", envOverride: "HONEYCOMB_LIFECYCLE_STALENESS_EXPONENT", defaultValue: "0", effect: "exponent on the staleness term (1 − σ)^s (0 under observe)" },
|
|
25
|
+
{ symbol: "h(memories)", configPath: "memory.lifecycle.halfLifeDaysByClass.memories", envOverride: "HONEYCOMB_LIFECYCLE_HALFLIFE_MEMORIES_DAYS", defaultValue: "180 d", effect: "shapes A for distilled facts (slower decay)" },
|
|
26
|
+
{ symbol: "h(memory)", configPath: "memory.lifecycle.halfLifeDaysByClass.memory", envOverride: "HONEYCOMB_LIFECYCLE_HALFLIFE_MEMORY_DAYS", defaultValue: "45 d", effect: "shapes A for session summaries" },
|
|
27
|
+
{ symbol: "h(sessions)", configPath: "memory.lifecycle.halfLifeDaysByClass.sessions", envOverride: "HONEYCOMB_LIFECYCLE_HALFLIFE_SESSIONS_DAYS", defaultValue: "10 d", effect: "shapes A for raw dialogue (fastest decay)" },
|
|
28
|
+
{ symbol: "d", configPath: "memory.lifecycle.actrDecay", envOverride: "HONEYCOMB_LIFECYCLE_ACTR_DECAY", defaultValue: "0.5", effect: "ACT-R decay shaping A (Stage 2)" },
|
|
29
|
+
{ symbol: "A_min", configPath: "memory.lifecycle.activationFloor", envOverride: "HONEYCOMB_LIFECYCLE_ACTIVATION_FLOOR", defaultValue: "0.05", effect: "clamps A so a cold memory keeps a sliver of salience" },
|
|
30
|
+
{ symbol: "h_verify", configPath: "memory.lifecycle.verificationHalfLifeDays", envOverride: "HONEYCOMB_LIFECYCLE_VERIFICATION_HALFLIFE_DAYS", defaultValue: "14 d", effect: "shapes σ via the verification-freshness factor v(m,t)" },
|
|
31
|
+
{ symbol: "θ_detect", configPath: "memory.lifecycle.contradictionThreshold", envOverride: "HONEYCOMB_LIFECYCLE_CONTRADICTION_THRESHOLD", defaultValue: "0.6", effect: "gates conflict detection (Contra > θ_detect)" },
|
|
32
|
+
{ symbol: "γ", configPath: "memory.lifecycle.corroborationWeight", envOverride: "HONEYCOMB_LIFECYCLE_CORROBORATION_WEIGHT", defaultValue: "0.5", effect: "shapes the conflict vote weight w_i" },
|
|
33
|
+
{ symbol: "τ_supersede", configPath: "memory.lifecycle.supersedeMargin", envOverride: "HONEYCOMB_LIFECYCLE_SUPERSEDE_MARGIN", defaultValue: "0.5", effect: "conflict verdict cut (margin ≥ τ_supersede → supersede)" },
|
|
34
|
+
{ symbol: "τ_review", configPath: "memory.lifecycle.reviewMargin", envOverride: "HONEYCOMB_LIFECYCLE_REVIEW_MARGIN", defaultValue: "0.15", effect: "conflict verdict cut (τ_review ≤ margin < τ_supersede → review)" },
|
|
35
|
+
{ symbol: "ρ", configPath: "memory.lifecycle.openConflictSuppression", envOverride: "HONEYCOMB_LIFECYCLE_OPEN_CONFLICT_SUPPRESSION", defaultValue: "0", effect: "κ for the open-conflict loser (0 fully suppress, reversible)" },
|
|
36
|
+
{ symbol: "auto-resolve", configPath: "memory.lifecycle.conflictAutoResolve", envOverride: "HONEYCOMB_LIFECYCLE_CONFLICT_AUTORESOLVE", defaultValue: "false", effect: "when off, conflicts are detected + queued only (human-in-the-loop)" },
|
|
37
|
+
{ symbol: "posture", configPath: "memory.lifecycle.staleRefPosture", envOverride: "HONEYCOMB_LIFECYCLE_STALEREF_POSTURE", defaultValue: "observe", effect: "observe (s = 0, inert) vs execute (s > 0, demote)" },
|
|
38
|
+
]);
|
|
39
|
+
//# sourceMappingURL=lifecycle-flags.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle-flags.js","sourceRoot":"","sources":["../../src/shared/lifecycle-flags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAgBH;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAgC,MAAM,CAAC,MAAM,CAAC;IAClF,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,qCAAqC,EAAE,WAAW,EAAE,yCAAyC,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,+CAA+C,EAAE;IACtM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,qCAAqC,EAAE,WAAW,EAAE,yCAAyC,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,2EAA2E,EAAE;IAClO,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,oCAAoC,EAAE,WAAW,EAAE,wCAAwC,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,4DAA4D,EAAE;IACjN,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,+CAA+C,EAAE,WAAW,EAAE,4CAA4C,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,6CAA6C,EAAE;IAC/N,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,6CAA6C,EAAE,WAAW,EAAE,0CAA0C,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,gCAAgC,EAAE;IAC3M,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,+CAA+C,EAAE,WAAW,EAAE,4CAA4C,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,2CAA2C,EAAE;IAC5N,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,4BAA4B,EAAE,WAAW,EAAE,gCAAgC,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,iCAAiC,EAAE;IACxK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,kCAAkC,EAAE,WAAW,EAAE,sCAAsC,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,sDAAsD,EAAE;IAC9M,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,2CAA2C,EAAE,WAAW,EAAE,gDAAgD,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,uDAAuD,EAAE;IACrO,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,yCAAyC,EAAE,WAAW,EAAE,6CAA6C,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,8CAA8C,EAAE;IACtN,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,sCAAsC,EAAE,WAAW,EAAE,0CAA0C,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,qCAAqC,EAAE;IAChM,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,kCAAkC,EAAE,WAAW,EAAE,sCAAsC,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,yDAAyD,EAAE;IACtN,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,+BAA+B,EAAE,WAAW,EAAE,mCAAmC,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,iEAAiE,EAAE;IACtN,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,0CAA0C,EAAE,WAAW,EAAE,+CAA+C,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,8DAA8D,EAAE;IAChO,EAAE,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,sCAAsC,EAAE,WAAW,EAAE,0CAA0C,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,oEAAoE,EAAE;IAC5O,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,kCAAkC,EAAE,WAAW,EAAE,sCAAsC,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,mDAAmD,EAAE;CAChN,CAAC,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The CLOSED memory-type taxonomy — the SINGLE SOURCE OF TRUTH for the six fixed
|
|
3
|
+
* memory `type` tokens, their human/LLM-facing descriptions, and the default.
|
|
4
|
+
*
|
|
5
|
+
* Every surface that constrains or describes a memory `type` imports from HERE and
|
|
6
|
+
* NEVER re-declares the list:
|
|
7
|
+
* - the daemon's `POST /api/memories` zod gate (`src/daemon/runtime/memories/api.ts`)
|
|
8
|
+
* validates the user-supplied `type` against {@link MEMORY_TYPES};
|
|
9
|
+
* - the dashboard Add-memory form renders the {@link MEMORY_TYPES} as a `<select>`;
|
|
10
|
+
* - the MCP `memory_store` tool publishes the enum + the LLM guidance string so an
|
|
11
|
+
* agent classifies the memory it is about to store;
|
|
12
|
+
* - the `honeycomb remember --type` CLI validates against the same set.
|
|
13
|
+
* A parity test (`tests/shared/memory-types-parity.test.ts`) asserts every surface
|
|
14
|
+
* draws from THIS module so the four surfaces cannot drift. Duplicating the list into
|
|
15
|
+
* another file is a drift bug and is flagged by `npm run dup` (jscpd).
|
|
16
|
+
*
|
|
17
|
+
* ── Pure by design (no zod) ──────────────────────────────────────────────────
|
|
18
|
+
* This module declares ONLY plain tuples/records — no zod import. {@link MEMORY_TYPES}
|
|
19
|
+
* is a `readonly [...]` tuple so it feeds `z.enum(MEMORY_TYPES)` under BOTH zod majors
|
|
20
|
+
* the repo uses: the app's `zod ^4` (daemon/dashboard) and the MCP server's `zod/v3`
|
|
21
|
+
* (the MCP SDK's major). Keeping the tuple zod-free is what lets one source feed both.
|
|
22
|
+
*
|
|
23
|
+
* ── Closed-set, write-time gate (back-compat) ────────────────────────────────
|
|
24
|
+
* The gate constrains USER-FACING writes (API / dashboard / CLI / MCP) only. It is a
|
|
25
|
+
* WRITE-TIME validation; it never rewrites stored rows. Existing rows whose `type` is a
|
|
26
|
+
* legacy/free-form value keep that value and still display. The autonomous capture
|
|
27
|
+
* pipeline (`fan-out.ts` → controlled-writes) enqueues its own `fact_type` directly and
|
|
28
|
+
* does NOT pass through this gate, so a model-assigned type outside the six never breaks
|
|
29
|
+
* (the column DDL keeps its `DEFAULT 'fact'`; no schema migration).
|
|
30
|
+
*/
|
|
31
|
+
/**
|
|
32
|
+
* The six fixed memory types — the closed set. ORDER IS LOAD-BEARING for the
|
|
33
|
+
* dashboard dropdown render; `fact` is first (the default). A `readonly` tuple so
|
|
34
|
+
* `z.enum(MEMORY_TYPES)` infers the exact union under both zod majors.
|
|
35
|
+
*/
|
|
36
|
+
export declare const MEMORY_TYPES: readonly ["fact", "convention", "preference", "decision", "gotcha", "reference"];
|
|
37
|
+
/** One memory type token (the union of the six). */
|
|
38
|
+
export type MemoryType = (typeof MEMORY_TYPES)[number];
|
|
39
|
+
/** The default applied when a user-facing write omits `type` — matches the column DDL `DEFAULT 'fact'`. */
|
|
40
|
+
export declare const DEFAULT_MEMORY_TYPE: MemoryType;
|
|
41
|
+
/**
|
|
42
|
+
* The one-line description of each type — how a reader OR an agent decides which to
|
|
43
|
+
* apply. The MCP tool schema + the CLI `--help` enumerate these so the LLM/user
|
|
44
|
+
* classifies correctly. Keyed by token so a lookup can never name a non-enum type.
|
|
45
|
+
*/
|
|
46
|
+
export declare const MEMORY_TYPE_DESCRIPTIONS: Readonly<Record<MemoryType, string>>;
|
|
47
|
+
/** Narrow an arbitrary string to a {@link MemoryType} (the closed-set membership test). */
|
|
48
|
+
export declare function isMemoryType(value: string): value is MemoryType;
|
|
49
|
+
/**
|
|
50
|
+
* The LLM/user-facing guidance string: every token paired with WHEN to use it, on its
|
|
51
|
+
* own line. Built ONCE from {@link MEMORY_TYPES} + {@link MEMORY_TYPE_DESCRIPTIONS} so the
|
|
52
|
+
* MCP tool description and the CLI `--help` enumerate the identical set — they cannot
|
|
53
|
+
* drift from the gate. `fact` is annotated as the default.
|
|
54
|
+
*/
|
|
55
|
+
export declare function memoryTypeGuidance(): string;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The CLOSED memory-type taxonomy — the SINGLE SOURCE OF TRUTH for the six fixed
|
|
3
|
+
* memory `type` tokens, their human/LLM-facing descriptions, and the default.
|
|
4
|
+
*
|
|
5
|
+
* Every surface that constrains or describes a memory `type` imports from HERE and
|
|
6
|
+
* NEVER re-declares the list:
|
|
7
|
+
* - the daemon's `POST /api/memories` zod gate (`src/daemon/runtime/memories/api.ts`)
|
|
8
|
+
* validates the user-supplied `type` against {@link MEMORY_TYPES};
|
|
9
|
+
* - the dashboard Add-memory form renders the {@link MEMORY_TYPES} as a `<select>`;
|
|
10
|
+
* - the MCP `memory_store` tool publishes the enum + the LLM guidance string so an
|
|
11
|
+
* agent classifies the memory it is about to store;
|
|
12
|
+
* - the `honeycomb remember --type` CLI validates against the same set.
|
|
13
|
+
* A parity test (`tests/shared/memory-types-parity.test.ts`) asserts every surface
|
|
14
|
+
* draws from THIS module so the four surfaces cannot drift. Duplicating the list into
|
|
15
|
+
* another file is a drift bug and is flagged by `npm run dup` (jscpd).
|
|
16
|
+
*
|
|
17
|
+
* ── Pure by design (no zod) ──────────────────────────────────────────────────
|
|
18
|
+
* This module declares ONLY plain tuples/records — no zod import. {@link MEMORY_TYPES}
|
|
19
|
+
* is a `readonly [...]` tuple so it feeds `z.enum(MEMORY_TYPES)` under BOTH zod majors
|
|
20
|
+
* the repo uses: the app's `zod ^4` (daemon/dashboard) and the MCP server's `zod/v3`
|
|
21
|
+
* (the MCP SDK's major). Keeping the tuple zod-free is what lets one source feed both.
|
|
22
|
+
*
|
|
23
|
+
* ── Closed-set, write-time gate (back-compat) ────────────────────────────────
|
|
24
|
+
* The gate constrains USER-FACING writes (API / dashboard / CLI / MCP) only. It is a
|
|
25
|
+
* WRITE-TIME validation; it never rewrites stored rows. Existing rows whose `type` is a
|
|
26
|
+
* legacy/free-form value keep that value and still display. The autonomous capture
|
|
27
|
+
* pipeline (`fan-out.ts` → controlled-writes) enqueues its own `fact_type` directly and
|
|
28
|
+
* does NOT pass through this gate, so a model-assigned type outside the six never breaks
|
|
29
|
+
* (the column DDL keeps its `DEFAULT 'fact'`; no schema migration).
|
|
30
|
+
*/
|
|
31
|
+
/**
|
|
32
|
+
* The six fixed memory types — the closed set. ORDER IS LOAD-BEARING for the
|
|
33
|
+
* dashboard dropdown render; `fact` is first (the default). A `readonly` tuple so
|
|
34
|
+
* `z.enum(MEMORY_TYPES)` infers the exact union under both zod majors.
|
|
35
|
+
*/
|
|
36
|
+
export const MEMORY_TYPES = [
|
|
37
|
+
"fact",
|
|
38
|
+
"convention",
|
|
39
|
+
"preference",
|
|
40
|
+
"decision",
|
|
41
|
+
"gotcha",
|
|
42
|
+
"reference",
|
|
43
|
+
];
|
|
44
|
+
/** The default applied when a user-facing write omits `type` — matches the column DDL `DEFAULT 'fact'`. */
|
|
45
|
+
export const DEFAULT_MEMORY_TYPE = "fact";
|
|
46
|
+
/**
|
|
47
|
+
* The one-line description of each type — how a reader OR an agent decides which to
|
|
48
|
+
* apply. The MCP tool schema + the CLI `--help` enumerate these so the LLM/user
|
|
49
|
+
* classifies correctly. Keyed by token so a lookup can never name a non-enum type.
|
|
50
|
+
*/
|
|
51
|
+
export const MEMORY_TYPE_DESCRIPTIONS = Object.freeze({
|
|
52
|
+
fact: "A stable, verifiable truth about the system, codebase, or domain.",
|
|
53
|
+
convention: "How things are done here: idioms, standards, patterns to follow by default.",
|
|
54
|
+
preference: "The user/team's stated way of working; corrections and do/don't guidance.",
|
|
55
|
+
decision: "An architectural or design choice and its rationale; don't relitigate it.",
|
|
56
|
+
gotcha: "A non-obvious trap, failure mode, or constraint to watch out for.",
|
|
57
|
+
reference: "A pointer to an external resource (URL, dashboard, ticket, doc).",
|
|
58
|
+
});
|
|
59
|
+
/** Narrow an arbitrary string to a {@link MemoryType} (the closed-set membership test). */
|
|
60
|
+
export function isMemoryType(value) {
|
|
61
|
+
return MEMORY_TYPES.includes(value);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The LLM/user-facing guidance string: every token paired with WHEN to use it, on its
|
|
65
|
+
* own line. Built ONCE from {@link MEMORY_TYPES} + {@link MEMORY_TYPE_DESCRIPTIONS} so the
|
|
66
|
+
* MCP tool description and the CLI `--help` enumerate the identical set — they cannot
|
|
67
|
+
* drift from the gate. `fact` is annotated as the default.
|
|
68
|
+
*/
|
|
69
|
+
export function memoryTypeGuidance() {
|
|
70
|
+
return MEMORY_TYPES.map((t) => {
|
|
71
|
+
const suffix = t === DEFAULT_MEMORY_TYPE ? " (default)" : "";
|
|
72
|
+
return `- ${t}${suffix}: ${MEMORY_TYPE_DESCRIPTIONS[t]}`;
|
|
73
|
+
}).join("\n");
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=memory-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-types.js","sourceRoot":"","sources":["../../src/shared/memory-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC3B,MAAM;IACN,YAAY;IACZ,YAAY;IACZ,UAAU;IACV,QAAQ;IACR,WAAW;CACF,CAAC;AAKX,2GAA2G;AAC3G,MAAM,CAAC,MAAM,mBAAmB,GAAe,MAAM,CAAC;AAEtD;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAyC,MAAM,CAAC,MAAM,CAAC;IAC3F,IAAI,EAAE,mEAAmE;IACzE,UAAU,EAAE,6EAA6E;IACzF,UAAU,EAAE,2EAA2E;IACvF,QAAQ,EAAE,2EAA2E;IACrF,MAAM,EAAE,mEAAmE;IAC3E,SAAS,EAAE,kEAAkE;CAC7E,CAAC,CAAC;AAEH,2FAA2F;AAC3F,MAAM,UAAU,YAAY,CAAC,KAAa;IACzC,OAAQ,YAAkC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB;IACjC,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC7B,MAAM,MAAM,GAAG,CAAC,KAAK,mBAAmB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,OAAO,KAAK,CAAC,GAAG,MAAM,KAAK,wBAAwB,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1D,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bee-loader status STATE model + derivation — hive PRD-004b (state contract) / PRD-004c
|
|
3
|
+
* (derivation). Locked state set (PRD-004 index): `error`, `degraded`, `starting`, `warming`,
|
|
4
|
+
* `active`. This is the SINGLE shared derivation `/buzzing` (PRD-004a) and the health rail
|
|
5
|
+
* (PRD-005a) both resolve through, so a service means the same thing on both surfaces (svg-AC-4).
|
|
6
|
+
*
|
|
7
|
+
* The derivation is a PURE function of a normalized {@link ServiceSignal} plus a small amount of
|
|
8
|
+
* externally-tracked timing context (`now`, `firstActiveAt`) — never a re-derivation of doctor's
|
|
9
|
+
* own health classification, and never reaching out to doctor itself. Both the SSE-fed live path
|
|
10
|
+
* and the `GET /api/fleet-status` fail-soft path normalize into the SAME {@link ServiceSignal} shape
|
|
11
|
+
* before calling {@link deriveServiceState}, which is what makes the derivation source-agnostic
|
|
12
|
+
* (sd-AC-6): the same underlying condition yields the same state regardless of which feed reported it.
|
|
13
|
+
*/
|
|
14
|
+
import type { FleetHealth, FleetServiceModel, TelemetryFaultReason } from "./fleet-telemetry.js";
|
|
15
|
+
import type { FleetDaemonStatus } from "./fleet-readiness.js";
|
|
16
|
+
/** The five locked bee-loader states (PRD-004 index, svg-AC-6). No additional/renamed state. */
|
|
17
|
+
export declare const SERVICE_STATES: readonly ["error", "degraded", "starting", "warming", "active"];
|
|
18
|
+
/** One of the five locked states. */
|
|
19
|
+
export type ServiceState = (typeof SERVICE_STATES)[number];
|
|
20
|
+
/** True iff `value` is one of the five locked {@link ServiceState}s (svg-AC-5's fallback guard). */
|
|
21
|
+
export declare function isServiceState(value: string): value is ServiceState;
|
|
22
|
+
/**
|
|
23
|
+
* The minimal, source-agnostic per-service signal the derivation reads (sd-AC-6). Both the rich
|
|
24
|
+
* SSE-fed {@link FleetServiceModel} and the coarser REST `/api/fleet-status` projection normalize
|
|
25
|
+
* into this shape (see {@link fromFleetServiceModel} / {@link fromFleetDaemonStatus}) before the
|
|
26
|
+
* SAME {@link deriveServiceState} call runs, so the rule never branches on which feed produced it.
|
|
27
|
+
*/
|
|
28
|
+
export interface ServiceSignal {
|
|
29
|
+
readonly health: FleetHealth;
|
|
30
|
+
/** ISO-8601 of the last confirmed check-in, or `null` when the feed does not carry one (e.g. the REST projection). */
|
|
31
|
+
readonly lastSeen: string | null;
|
|
32
|
+
/** Non-null when this tick's telemetry read for this service was skipped/faulted (SSE-only signal; REST fallback never carries one). */
|
|
33
|
+
readonly telemetryFault: TelemetryFaultReason | null;
|
|
34
|
+
}
|
|
35
|
+
/** Normalize a live SSE {@link FleetServiceModel} into the source-agnostic {@link ServiceSignal}. */
|
|
36
|
+
export declare function fromFleetServiceModel(model: FleetServiceModel): ServiceSignal;
|
|
37
|
+
/** Normalize a fail-soft REST {@link FleetDaemonStatus} row into the same {@link ServiceSignal} shape. */
|
|
38
|
+
export declare function fromFleetDaemonStatus(daemon: FleetDaemonStatus): ServiceSignal;
|
|
39
|
+
/** How long (ms) a service stays `warming` after it is FIRST observed healthy (PRD-004 index's "very recently first-seen"). */
|
|
40
|
+
export declare const DEFAULT_WARMING_GRACE_MS = 10000;
|
|
41
|
+
/** How stale (ms) a reported `lastSeen` may be before the derivation overrides to `error` regardless of the reported health (sd-AC-3). */
|
|
42
|
+
export declare const DEFAULT_STALE_AFTER_MS = 20000;
|
|
43
|
+
/** Input to {@link deriveServiceState}. */
|
|
44
|
+
export interface ServiceDerivationInput {
|
|
45
|
+
/**
|
|
46
|
+
* The service's current normalized signal, or `null` when it is a REGISTERED service that has
|
|
47
|
+
* not yet appeared in any tick / any projection row (sd-AC-2 — never omitted, never `active`).
|
|
48
|
+
*/
|
|
49
|
+
readonly signal: ServiceSignal | null;
|
|
50
|
+
/** The clock reading (ms) the derivation runs at (injectable for deterministic tests). */
|
|
51
|
+
readonly now: number;
|
|
52
|
+
/**
|
|
53
|
+
* The wall-clock time (ms) this service was FIRST observed `health === "ok"`, tracked by the
|
|
54
|
+
* caller across ticks/reconnects (e.g. `use-fleet-telemetry.ts`'s per-service reducer). `null`
|
|
55
|
+
* when it has never been observed healthy. Kept OUTSIDE this pure function so the function
|
|
56
|
+
* itself stays a deterministic, unit-testable mapping (sd-AC-1) while the stateful bookkeeping
|
|
57
|
+
* lives in one place the caller owns.
|
|
58
|
+
*/
|
|
59
|
+
readonly firstActiveAt: number | null;
|
|
60
|
+
/** Override the warming grace window (ms). Defaults to {@link DEFAULT_WARMING_GRACE_MS}. */
|
|
61
|
+
readonly warmingGraceMs?: number;
|
|
62
|
+
/** Override the staleness threshold (ms). Defaults to {@link DEFAULT_STALE_AFTER_MS}. */
|
|
63
|
+
readonly staleAfterMs?: number;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Derive exactly one of the five locked states from a service's merged registration+runtime
|
|
67
|
+
* signal (PRD-004c derivation table, sd-AC-1). Pure and source-agnostic: the SAME output for the
|
|
68
|
+
* same `(signal, now, firstActiveAt)` triple regardless of whether `signal` came from the SSE
|
|
69
|
+
* stream or the REST fallback projection (sd-AC-6/sd-AC-7). Per-service — this function never
|
|
70
|
+
* looks at any OTHER service's state, so a per-service update can never affect a sibling's derived
|
|
71
|
+
* state (sd-AC-8/sd-AC-9).
|
|
72
|
+
*/
|
|
73
|
+
export declare function deriveServiceState(input: ServiceDerivationInput): ServiceState;
|
|
74
|
+
/**
|
|
75
|
+
* Advance the per-service "first observed healthy" bookkeeping {@link deriveServiceState}'s
|
|
76
|
+
* `warming` branch needs (PRD-004 index's "very recently first-seen"). Called once per received
|
|
77
|
+
* signal for a service: returns the SAME `firstActiveAt` when health stays non-`"ok"` or was
|
|
78
|
+
* already marked active-since some earlier time, records `now` the FIRST time health flips to
|
|
79
|
+
* `"ok"`, and resets to `null` if the service leaves `"ok"` (so a later re-activation re-enters the
|
|
80
|
+
* warming grace, honestly reflecting a fresh checked-in-and-healthy transition).
|
|
81
|
+
*/
|
|
82
|
+
export declare function nextFirstActiveAt(health: FleetHealth, previous: number | null, now: number): number | null;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bee-loader status STATE model + derivation — hive PRD-004b (state contract) / PRD-004c
|
|
3
|
+
* (derivation). Locked state set (PRD-004 index): `error`, `degraded`, `starting`, `warming`,
|
|
4
|
+
* `active`. This is the SINGLE shared derivation `/buzzing` (PRD-004a) and the health rail
|
|
5
|
+
* (PRD-005a) both resolve through, so a service means the same thing on both surfaces (svg-AC-4).
|
|
6
|
+
*
|
|
7
|
+
* The derivation is a PURE function of a normalized {@link ServiceSignal} plus a small amount of
|
|
8
|
+
* externally-tracked timing context (`now`, `firstActiveAt`) — never a re-derivation of doctor's
|
|
9
|
+
* own health classification, and never reaching out to doctor itself. Both the SSE-fed live path
|
|
10
|
+
* and the `GET /api/fleet-status` fail-soft path normalize into the SAME {@link ServiceSignal} shape
|
|
11
|
+
* before calling {@link deriveServiceState}, which is what makes the derivation source-agnostic
|
|
12
|
+
* (sd-AC-6): the same underlying condition yields the same state regardless of which feed reported it.
|
|
13
|
+
*/
|
|
14
|
+
/** The five locked bee-loader states (PRD-004 index, svg-AC-6). No additional/renamed state. */
|
|
15
|
+
export const SERVICE_STATES = ["error", "degraded", "starting", "warming", "active"];
|
|
16
|
+
/** True iff `value` is one of the five locked {@link ServiceState}s (svg-AC-5's fallback guard). */
|
|
17
|
+
export function isServiceState(value) {
|
|
18
|
+
return SERVICE_STATES.includes(value);
|
|
19
|
+
}
|
|
20
|
+
/** Normalize a live SSE {@link FleetServiceModel} into the source-agnostic {@link ServiceSignal}. */
|
|
21
|
+
export function fromFleetServiceModel(model) {
|
|
22
|
+
return { health: model.health, lastSeen: model.lastSeen, telemetryFault: model.telemetryFault };
|
|
23
|
+
}
|
|
24
|
+
/** Normalize a fail-soft REST {@link FleetDaemonStatus} row into the same {@link ServiceSignal} shape. */
|
|
25
|
+
export function fromFleetDaemonStatus(daemon) {
|
|
26
|
+
// The coarse projection carries no `lastSeen`/`telemetryFault` — normalize to the "unknown" values
|
|
27
|
+
// so the SAME derivation function runs on either feed (sd-AC-6/sd-AC-7) rather than a parallel rule.
|
|
28
|
+
return { health: daemon.health, lastSeen: null, telemetryFault: null };
|
|
29
|
+
}
|
|
30
|
+
/** How long (ms) a service stays `warming` after it is FIRST observed healthy (PRD-004 index's "very recently first-seen"). */
|
|
31
|
+
export const DEFAULT_WARMING_GRACE_MS = 10_000;
|
|
32
|
+
/** How stale (ms) a reported `lastSeen` may be before the derivation overrides to `error` regardless of the reported health (sd-AC-3). */
|
|
33
|
+
export const DEFAULT_STALE_AFTER_MS = 20_000;
|
|
34
|
+
/**
|
|
35
|
+
* Derive exactly one of the five locked states from a service's merged registration+runtime
|
|
36
|
+
* signal (PRD-004c derivation table, sd-AC-1). Pure and source-agnostic: the SAME output for the
|
|
37
|
+
* same `(signal, now, firstActiveAt)` triple regardless of whether `signal` came from the SSE
|
|
38
|
+
* stream or the REST fallback projection (sd-AC-6/sd-AC-7). Per-service — this function never
|
|
39
|
+
* looks at any OTHER service's state, so a per-service update can never affect a sibling's derived
|
|
40
|
+
* state (sd-AC-8/sd-AC-9).
|
|
41
|
+
*/
|
|
42
|
+
export function deriveServiceState(input) {
|
|
43
|
+
const { signal, now, firstActiveAt } = input;
|
|
44
|
+
const warmingGraceMs = input.warmingGraceMs ?? DEFAULT_WARMING_GRACE_MS;
|
|
45
|
+
const staleAfterMs = input.staleAfterMs ?? DEFAULT_STALE_AFTER_MS;
|
|
46
|
+
// sd-AC-2: registered but no runtime signal yet (never appeared in a tick/projection row).
|
|
47
|
+
if (signal === null)
|
|
48
|
+
return "starting";
|
|
49
|
+
// sd-AC-9: an isolated per-service telemetry read fault degrades that service alone.
|
|
50
|
+
if (signal.telemetryFault !== null)
|
|
51
|
+
return "degraded";
|
|
52
|
+
// sd-AC-3: failed/unreachable, OR a stale last-seen beyond threshold even if the reported
|
|
53
|
+
// health still says otherwise (a safety net for a cached/stale snapshot).
|
|
54
|
+
if (signal.health === "unreachable")
|
|
55
|
+
return "error";
|
|
56
|
+
if (signal.lastSeen !== null) {
|
|
57
|
+
const lastSeenMs = Date.parse(signal.lastSeen);
|
|
58
|
+
if (Number.isFinite(lastSeenMs) && now - lastSeenMs > staleAfterMs)
|
|
59
|
+
return "error";
|
|
60
|
+
}
|
|
61
|
+
switch (signal.health) {
|
|
62
|
+
case "degraded":
|
|
63
|
+
// sd-AC-4: up but unhealthy/partial.
|
|
64
|
+
return "degraded";
|
|
65
|
+
case "unknown":
|
|
66
|
+
// Registered, checked in per the poll loop's Contract C convention of a not-yet-bound
|
|
67
|
+
// service reporting `"unknown"` — treated the same as sd-AC-2's never-seen case.
|
|
68
|
+
return "starting";
|
|
69
|
+
case "ok": {
|
|
70
|
+
// sd-AC-5: checked in and healthy. `warming` for a brief grace window right after the
|
|
71
|
+
// FIRST observed transition to healthy, `active` once settled.
|
|
72
|
+
if (firstActiveAt !== null && now - firstActiveAt < warmingGraceMs)
|
|
73
|
+
return "warming";
|
|
74
|
+
return "active";
|
|
75
|
+
}
|
|
76
|
+
default: {
|
|
77
|
+
// `"unreachable"` is excluded here by the early return above (TS narrows `signal.health`
|
|
78
|
+
// across that guard), so the remaining exhaustive member set is exactly ok/degraded/unknown.
|
|
79
|
+
const exhaustive = signal.health;
|
|
80
|
+
return exhaustive;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Advance the per-service "first observed healthy" bookkeeping {@link deriveServiceState}'s
|
|
86
|
+
* `warming` branch needs (PRD-004 index's "very recently first-seen"). Called once per received
|
|
87
|
+
* signal for a service: returns the SAME `firstActiveAt` when health stays non-`"ok"` or was
|
|
88
|
+
* already marked active-since some earlier time, records `now` the FIRST time health flips to
|
|
89
|
+
* `"ok"`, and resets to `null` if the service leaves `"ok"` (so a later re-activation re-enters the
|
|
90
|
+
* warming grace, honestly reflecting a fresh checked-in-and-healthy transition).
|
|
91
|
+
*/
|
|
92
|
+
export function nextFirstActiveAt(health, previous, now) {
|
|
93
|
+
if (health !== "ok")
|
|
94
|
+
return null;
|
|
95
|
+
return previous ?? now;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=service-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-status.js","sourceRoot":"","sources":["../../src/shared/service-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,gGAAgG;AAChG,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAU,CAAC;AAK9F,oGAAoG;AACpG,MAAM,UAAU,cAAc,CAAC,KAAa;IAC3C,OAAQ,cAAoC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC9D,CAAC;AAgBD,qGAAqG;AACrG,MAAM,UAAU,qBAAqB,CAAC,KAAwB;IAC7D,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,cAAc,EAAE,KAAK,CAAC,cAAc,EAAE,CAAC;AACjG,CAAC;AAED,0GAA0G;AAC1G,MAAM,UAAU,qBAAqB,CAAC,MAAyB;IAC9D,mGAAmG;IACnG,qGAAqG;IACrG,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;AACxE,CAAC;AAED,+HAA+H;AAC/H,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC;AAE/C,0IAA0I;AAC1I,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAyB7C;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAA6B;IAC/D,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,KAAK,CAAC;IAC7C,MAAM,cAAc,GAAG,KAAK,CAAC,cAAc,IAAI,wBAAwB,CAAC;IACxE,MAAM,YAAY,GAAG,KAAK,CAAC,YAAY,IAAI,sBAAsB,CAAC;IAElE,2FAA2F;IAC3F,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,UAAU,CAAC;IAEvC,qFAAqF;IACrF,IAAI,MAAM,CAAC,cAAc,KAAK,IAAI;QAAE,OAAO,UAAU,CAAC;IAEtD,0FAA0F;IAC1F,0EAA0E;IAC1E,IAAI,MAAM,CAAC,MAAM,KAAK,aAAa;QAAE,OAAO,OAAO,CAAC;IACpD,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,GAAG,GAAG,UAAU,GAAG,YAAY;YAAE,OAAO,OAAO,CAAC;IACpF,CAAC;IAED,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC;QACvB,KAAK,UAAU;YACd,qCAAqC;YACrC,OAAO,UAAU,CAAC;QACnB,KAAK,SAAS;YACb,sFAAsF;YACtF,iFAAiF;YACjF,OAAO,UAAU,CAAC;QACnB,KAAK,IAAI,CAAC,CAAC,CAAC;YACX,sFAAsF;YACtF,+DAA+D;YAC/D,IAAI,aAAa,KAAK,IAAI,IAAI,GAAG,GAAG,aAAa,GAAG,cAAc;gBAAE,OAAO,SAAS,CAAC;YACrF,OAAO,QAAQ,CAAC;QACjB,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACT,yFAAyF;YACzF,6FAA6F;YAC7F,MAAM,UAAU,GAAU,MAAM,CAAC,MAAM,CAAC;YACxC,OAAO,UAAU,CAAC;QACnB,CAAC;IACF,CAAC;AACF,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAmB,EAAE,QAAuB,EAAE,GAAW;IAC1F,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,QAAQ,IAAI,GAAG,CAAC;AACxB,CAAC"}
|