@senad-d/observme 0.1.5 → 0.1.6

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/CHANGELOG.md CHANGED
@@ -21,8 +21,9 @@
21
21
 
22
22
  ### Changed
23
23
 
24
+ - Raised the release-tested Pi and exact compatibility CI target to 0.81.1 while retaining 0.80.5 as the earliest validated target.
24
25
  - Made the 0.1.5 hardening patch self-contained with explicit review units, all imported production modules included, and unrelated specification history preserved.
25
- - Established a typed Pi event registration contract, removed non-event legacy registrations, pinned the release-resolved Pi API, and added minimum/release compatibility validation with pre-registration diagnostics.
26
+ - Established a typed Pi event registration contract, removed non-event legacy registrations, pinned the release-tested Pi API for validation, and added capability-based pre-registration diagnostics.
26
27
  - Centralized embedded-credential Grafana URL diagnostics so configuration validation, readiness checks, URL construction, and transports share one safe failure class and operator guidance.
27
28
  - Documented credential-free Grafana base URLs and the fail-closed canonical project-file boundary across configuration, security, query, and troubleshooting guidance.
28
29
  - Completed production active-agent lease documentation, raw-query migration guidance, GitHub Actions/self-hosted clock and cleanup runbooks, missing/expired-lease troubleshooting, Collector restart semantics, and sanitized release-validation evidence.
@@ -42,9 +43,8 @@
42
43
 
43
44
  ### Fixed
44
45
 
45
- - Simplified Pi SemVer validation into focused numeric-core and metadata checks, and made missing project-path component reversal explicit.
46
- - Accepted supported stable Pi versions with SemVer build metadata while preserving bounded diagnostics and prerelease rejection.
47
- - Rejected prerelease Pi builds excluded by the declared stable compatibility range before extension registration.
46
+ - Removed Pi version gating from extension startup entirely; tested versions are evidence only, essential ExtensionAPI capabilities are checked before registration, and optional APIs remain feature-detected.
47
+ - Made missing project-path component reversal explicit.
48
48
  - Applied one control-safe 64-row/8,192-character policy to every `/obs` notification and capped query result counts at configuration and runtime boundaries.
49
49
  - Coupled canonical project config, `.env`, and starter-config I/O to identity-verified file handles so concurrent symlink and ancestor swaps fail closed without exposing external paths.
50
50
  - Rejected credentials embedded in Grafana base URLs during config validation, query readiness, and transport preflight without exposing their values.
@@ -1,14 +1,14 @@
1
1
  # ObservMe Compatibility Matrix
2
2
 
3
- Last updated: 2026-07-14
3
+ Last updated: 2026-07-22
4
4
 
5
5
  This matrix records the ObservMe runtime and observability-stack versions exercised or pinned for the current release line. A component is marked **validated** only when the named command actually exercised it; configured CI targets remain distinct from completed local or workflow evidence.
6
6
 
7
7
  ## Pi version policy
8
8
 
9
- ObservMe 0.1.x supports `@earendil-works/pi-coding-agent` `>=0.80.5 <0.81.0`. The Pi-mandated core package peers remain in `peerDependencies` with `"*"`, while release development dependencies are pinned exactly to 0.80.6 and CI installs both the 0.80.5 minimum and the 0.80.6 release-resolved target explicitly. Extension startup checks Pi's exported `VERSION` and required APIs before registering any handler or command.
9
+ ObservMe never uses Pi's reported version as a startup gate. The Pi-mandated core package peers remain in `peerDependencies` with `"*"`, while exact 0.80.5 and 0.81.1 targets record compatibility evidence in CI. Before registering anything, startup checks only the essential `ExtensionAPI` capabilities `on` and `registerCommand`. When those methods exist, ObservMe starts regardless of whether Pi's version is older, newer, prerelease, malformed, or unavailable. Optional APIs are feature-detected by the handlers that use them.
10
10
 
11
- The 0.80.5 minimum is evidence-based: its exported extension contract includes `session_info_changed`, which ObservMe requires for live rename metadata; 0.80.2 does not. Pi's current extension overloads do not include `bashExecution`, `model_change`, or `thinking_level_change`. `bashExecution` is an `AgentMessage` role observed through `message_end`, while model and thinking changes are session entry types represented at runtime by `model_select` and `thinking_level_select`; ObservMe no longer registers those three non-event names.
11
+ Pi 0.80.5 is the earliest tested version, not a runtime minimum: its exported extension contract includes `session_info_changed`, which ObservMe uses for live rename metadata. Pi's current extension overloads do not include `bashExecution`, `model_change`, or `thinking_level_change`. `bashExecution` is an `AgentMessage` role observed through `message_end`, while model and thinking changes are session entry types represented at runtime by `model_select` and `thinking_level_select`; ObservMe no longer registers those three non-event names. Tested versions provide release evidence only and never define an accepted or rejected runtime range.
12
12
 
13
13
  ## Validation record
14
14
 
@@ -18,9 +18,11 @@ The 0.80.5 minimum is evidence-based: its exported extension contract includes `
18
18
  | 2026-07-07 | Local Docker 29.5.2 with Collector Contrib 0.104.0 | `npm run test:integration:collector` | Starts a local debug-exporter Collector container, exports representative ObservMe traces/metrics/logs, and asserts default-disabled content capture is absent. |
19
19
  | 2026-07-07 | Local Docker 29.5.2 with the pinned Grafana stack | `npm run test:integration:grafana-stack` | Starts `observability-stack/` services, exports representative ObservMe telemetry, queries Tempo by trace ID and lineage attributes, queries Loki by session ID, queries Prometheus token totals, and validates Grafana dashboard provisioning imports. |
20
20
  | Continuous integration target | GitHub Actions `ubuntu-latest`, Node.js 22.19.0 | `npm ci --ignore-scripts` then `npm run validate` | CI target from `.github/workflows/ci.yml`; record the workflow run URL here after each release validation. |
21
- | Pi compatibility CI matrix (configured 2026-07-14) | GitHub Actions `ubuntu-latest`, Node.js 22.19.0; exact Pi 0.80.5 and 0.80.6 matrix targets | Exact Pi install, version assertion, then `npm run validate:pi-compatibility` | Compile-time event fixtures, compatibility diagnostics, package install, handler/lifecycle smoke, and a real Pi RPC runtime are exercised separately at the declared minimum and release-resolved versions. |
22
- | 2026-07-14 | Local Node.js v26.0.0, npm 11.12.1; exact `@earendil-works/pi-coding-agent` and `@earendil-works/pi-ai` 0.80.5 | Exact version assertion then `npm run validate:pi-compatibility` | Passed typecheck, typed event contracts, compatibility diagnostics, packaged install, handler/lifecycle smoke, and real Pi RPC runtime at the declared minimum. |
23
- | 2026-07-14 | Local Node.js v26.0.0, npm 11.12.1; exact `@earendil-works/pi-coding-agent` and `@earendil-works/pi-ai` 0.80.6 | Exact version assertion then `npm run validate:pi-compatibility` | Passed the same compatibility suite at the release-resolved version. |
21
+ | Pi compatibility CI matrix (updated 2026-07-22) | GitHub Actions `ubuntu-latest`, Node.js 22.19.0; exact Pi 0.80.5 and 0.81.1 matrix targets | Exact Pi install, version assertion, then `npm run validate:pi-compatibility` | Compile-time event fixtures, capability diagnostics, package install, handler/lifecycle smoke, and a real Pi RPC runtime are exercised separately at the earliest-tested and release-tested versions. |
22
+ | 2026-07-14 | Local Node.js v26.0.0, npm 11.12.1; exact `@earendil-works/pi-coding-agent` and `@earendil-works/pi-ai` 0.80.5 | Exact version assertion then `npm run validate:pi-compatibility` | Passed typecheck, typed event contracts, capability diagnostics, packaged install, handler/lifecycle smoke, and real Pi RPC runtime at the earliest-tested version. |
23
+ | 2026-07-14 | Local Node.js v26.0.0, npm 11.12.1; exact `@earendil-works/pi-coding-agent` and `@earendil-works/pi-ai` 0.80.6 | Exact version assertion then `npm run validate:pi-compatibility` | Passed the same compatibility suite at the former release-tested version. |
24
+ | 2026-07-22 | Local Node.js v26.0.0, npm 11.12.1; exact `@earendil-works/pi-coding-agent` and `@earendil-works/pi-ai` 0.81.1 | Exact version assertion, typechecks, compatibility tests, packaged install, handler/lifecycle smoke, and real Pi RPC runtime | Passed the complete `npm run validate:pi-compatibility` suite at the current release-tested version. |
25
+ | 2026-07-22 | Local Node.js v26.0.0, npm 11.12.1; exact Pi 0.81.1 development dependencies | `npm run validate` | Passed source/test typechecks, ESLint, formatting, 618 unit/contract tests, package-content checks, packaged-install smoke, handler smoke, Pi lifecycle smoke, and real Pi runtime smoke. |
24
26
  | Lease cancellation CI profile (configured 2026-07-14) | GitHub-hosted Linux `ubuntu-latest` (exact `ImageOS`/`ImageVersion` recorded in the Actions runner log); Node.js 22.19.0; Collector Contrib 0.104.0; Prometheus 2.53.1; Grafana 11.1.0 | `npm run test:active-agent-lease:contracts` then `npm run test:integration:active-agent-lease` | The bounded `lease-cancellation` job validates clean shutdown, `SIGTERM`, and cancellation-oriented `SIGKILL` convergence against the pinned Collector and Prometheus without secrets or a Grafana dependency. Grafana 11.1.0 is the recorded dashboard compatibility baseline validated separately by `npm run test:integration:grafana-stack`. `if: always()` cleanup is best effort; lease expiry is the asserted correctness mechanism. |
25
27
  | 2026-07-14 | Local Node.js v26.0.0, npm 11.12.1 | `npm run validate` | Passed 493 unit/contract tests plus typecheck, ESLint, formatting, script, package-content, packaged-install, handler, Pi lifecycle, and Pi runtime checks for the lease release candidate. |
26
28
  | 2026-07-14 | Local Docker 29.5.2, Compose 5.1.4, Collector Contrib 0.104.0 | `npm run test:integration:collector`; Compose config; pinned Collector `validate` | Passed representative OTLP export, Compose interpolation, and the shipped Collector config validation. |
@@ -34,7 +36,7 @@ Active-agent lease interpretation additionally requires producer and Prometheus
34
36
 
35
37
  | Component | Version tested or pinned | Source of truth | Status | Evidence and notes |
36
38
  | --- | --- | --- | --- | --- |
37
- | Pi package API | Supported: `@earendil-works/pi-coding-agent` >=0.80.5 <0.81.0; release-resolved `@earendil-works/pi-coding-agent` 0.80.6 and `@earendil-works/pi-ai` 0.80.6 | `package.json` `observmeCompatibility`, exact dev dependencies, `package-lock.json`, `.github/workflows/ci.yml` | Validated locally at minimum and release-resolved versions; exact CI matrix configured | `npm run validate:pi-compatibility` typechecks exported event contracts, tests pre-registration diagnostics, installs the package, runs handler/lifecycle smoke, and launches the real Pi RPC runtime. |
39
+ | Pi package API | Runtime policy: required API capabilities only; version never gates startup. Earliest tested Pi: 0.80.5; release-tested `@earendil-works/pi-coding-agent` and `@earendil-works/pi-ai`: 0.81.1 | `package.json` `observmeCompatibility`, exact dev dependencies, `package-lock.json`, `.github/workflows/ci.yml` | Validated locally at earliest-tested 0.80.5 and release-tested 0.81.1; exact CI matrix configured | `npm run validate:pi-compatibility` typechecks exported event contracts, tests pre-registration capability diagnostics, installs the package, runs handler/lifecycle smoke, and launches the real Pi RPC runtime. Pi version values do not participate in startup acceptance. |
38
40
  | Node.js | Local: 26.0.0; CI target/minimum: 22.19.0 | `node --version`, `package.json` `engines.node`, `.github/workflows/ci.yml` | Validated locally for 26.0.0; CI target pinned at 22.19.0 | Local validation ran on 26.0.0. CI is configured to validate on 22.19.0, which is also the minimum supported Node.js version. |
39
41
  | OpenTelemetry JS package set | `@opentelemetry/api` 1.9.1; `@opentelemetry/api-logs` 0.220.0; OTLP proto exporters 0.220.0; `@opentelemetry/resources` 2.9.0; `@opentelemetry/sdk-logs` 0.220.0; `@opentelemetry/sdk-metrics` 2.9.0; `@opentelemetry/sdk-trace-base` 2.9.0; `@opentelemetry/sdk-trace-node` 2.9.0 | `package.json`, `package-lock.json` | Validated locally | `npm run validate` includes the OTEL lifecycle/exporter unit tests under `test/otel-*.test.mjs`. |
40
42
 
@@ -93,6 +93,16 @@ This sanitized record covers the production active-agent lease release candidate
93
93
 
94
94
  Post-run cleanup check found no containers or networks labeled for the active-agent lease integration and no `observme-grafana-it-*` containers or networks. Release remains blocked on the unrelated broad Grafana-stack validation unless the release owner accepts the explicitly allowed pre-existing blocker; all lease-specific release criteria passed.
95
95
 
96
+ ## Pi 0.81.1 compatibility validation — 2026-07-22
97
+
98
+ This sanitized record covers the compatibility-policy correction against exact `@earendil-works/pi-coding-agent` and `@earendil-works/pi-ai` 0.81.1 development dependencies on local Node.js v26.0.0 and npm 11.12.1. No project, model, Grafana, or registry credentials were required or printed.
99
+
100
+ | Command | Result | Evidence and notes |
101
+ | --- | --- | --- |
102
+ | `npm run validate:pi-compatibility` | Pass | Source/test typechecks, compatibility and event-mapping tests, packaged-install smoke, handler and lifecycle smoke, and the real Pi RPC runtime passed against Pi 0.81.1. |
103
+ | `npm run validate` | Pass | ESLint, formatting, script checks, 618 unit/contract tests, package-content validation, packaged-install smoke, handler smoke, Pi lifecycle smoke, and real Pi runtime smoke passed. |
104
+ | `npm audit --omit=dev` | Pass | The production dependency tree reported no vulnerabilities. |
105
+
96
106
  ## Review-closure evidence categories
97
107
 
98
108
  - **Read-only/check-only** — commands that inspect, type-check, lint, audit, run tests, dry-run packaging, or smoke local deterministic fixtures without publishing or writing tracked files.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@senad-d/observme",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "type": "module",
5
5
  "description": "ObservMe: a Pi extension that instruments Pi agent sessions and exports OpenTelemetry traces, metrics, and logs to an external observability stack (OTel Collector, Grafana Tempo/Loki/Prometheus).",
6
6
  "license": "MIT",
@@ -76,9 +76,9 @@
76
76
  },
77
77
  "observmeCompatibility": {
78
78
  "pi": {
79
- "minimumVersion": "0.80.5",
80
- "releaseTestedVersion": "0.80.6",
81
- "supportedRange": ">=0.80.5 <0.81.0"
79
+ "earliestTestedVersion": "0.80.5",
80
+ "releaseTestedVersion": "0.81.1",
81
+ "runtimePolicy": "required-api-capabilities"
82
82
  }
83
83
  },
84
84
  "pi": {
@@ -96,8 +96,8 @@
96
96
  "typebox": "*"
97
97
  },
98
98
  "devDependencies": {
99
- "@earendil-works/pi-ai": "0.80.6",
100
- "@earendil-works/pi-coding-agent": "0.80.6",
99
+ "@earendil-works/pi-ai": "0.81.1",
100
+ "@earendil-works/pi-coding-agent": "0.81.1",
101
101
  "@eslint/js": "^10.0.1",
102
102
  "@types/node": "^26.1.1",
103
103
  "c8": "^11.0.0",
package/src/extension.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
2
  import { registerObsCommand } from "./commands/obs.ts";
3
- import { assertObservMePiCompatibility } from "./pi/compatibility.ts";
3
+ import { assertObservMePiCapabilities } from "./pi/compatibility.ts";
4
4
  import { registerHandlers } from "./pi/handlers.ts";
5
5
  const partialInitializationErrorMessage =
6
6
  "ObservMe extension initialization failed while registering /obs after Pi event handlers were already registered. Pi ExtensionAPI does not expose unregister hooks for event handlers or slash commands, so ObservMe cannot roll back partial registration; restart Pi after fixing command registration.";
7
7
 
8
8
  export default function observme(pi: ExtensionAPI): void {
9
- assertObservMePiCompatibility(pi);
9
+ assertObservMePiCapabilities(pi);
10
10
  // Only the Pi process environment is eligible for launcher-provided lineage.
11
11
  // Session config loading keeps trusted project .env values out of this boundary.
12
12
  registerHandlers(pi, { trustedParentContext: true });
@@ -1,34 +1,17 @@
1
- import { VERSION as PI_VERSION } from "@earendil-works/pi-coding-agent";
2
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
1
+ export const EARLIEST_TESTED_PI_VERSION = "0.80.5";
2
+ export const RELEASE_TESTED_PI_VERSION = "0.81.1";
3
+ export const PI_RUNTIME_COMPATIBILITY_POLICY = "required-api-capabilities" as const;
3
4
 
4
- export const MINIMUM_SUPPORTED_PI_VERSION = "0.80.5";
5
- export const RELEASE_TESTED_PI_VERSION = "0.80.6";
6
- const FIRST_UNSUPPORTED_PI_VERSION = "0.81.0";
7
- export const SUPPORTED_PI_VERSION_RANGE =
8
- `>=${MINIMUM_SUPPORTED_PI_VERSION} <${FIRST_UNSUPPORTED_PI_VERSION}`;
5
+ const capabilityErrorPrefix = "ObservMe/Pi API capability error";
6
+ const requiredPiMethods = ["on", "registerCommand"] as const;
9
7
 
10
- const compatibilityErrorPrefix = "ObservMe/Pi API compatibility error";
11
- const MAX_DETECTED_PI_VERSION_LENGTH = 128;
12
- const piVersionCorePattern = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/u;
13
- const semanticVersionIdentifierPattern = /^[0-9A-Za-z-]+$/u;
14
- const numericIdentifierPattern = /^\d+$/u;
15
- const requiredPiMethods = ["on", "registerCommand", "appendEntry", "getThinkingLevel"] as const;
16
-
17
- export function assertObservMePiCompatibility(
18
- pi: unknown,
19
- piVersion = PI_VERSION,
20
- ): asserts pi is ExtensionAPI {
8
+ /** Pi's reported version is intentionally not part of this startup decision. */
9
+ export function assertObservMePiCapabilities(pi: unknown): void {
21
10
  const missingMethods = findMissingPiMethods(pi);
22
- const detectedVersion = normalizeDetectedVersion(piVersion);
23
- const versionSupported = isSupportedPiVersion(detectedVersion);
24
- if (versionSupported && missingMethods.length === 0) return;
25
-
26
- const reasons: string[] = [];
27
- if (!versionSupported) reasons.push(`detected Pi ${detectedVersion}`);
28
- if (missingMethods.length > 0) reasons.push(`missing required API method(s): ${missingMethods.join(", ")}`);
11
+ if (missingMethods.length === 0) return;
29
12
 
30
13
  throw new TypeError(
31
- `${compatibilityErrorPrefix}: ObservMe requires @earendil-works/pi-coding-agent ${SUPPORTED_PI_VERSION_RANGE}; ${reasons.join("; ")}. No ObservMe event handlers or commands were registered.`,
14
+ `${capabilityErrorPrefix}: ObservMe requires ExtensionAPI method(s): ${missingMethods.join(", ")}. Pi version is not used as a startup gate. No ObservMe event handlers or commands were registered.`,
32
15
  );
33
16
  }
34
17
 
@@ -45,77 +28,3 @@ function findMissingPiMethods(pi: unknown): string[] {
45
28
  function isRecord(value: unknown): value is Record<string, unknown> {
46
29
  return typeof value === "object" && value !== null;
47
30
  }
48
-
49
- function normalizeDetectedVersion(value: unknown): string {
50
- if (typeof value !== "string") return "unknown";
51
- const trimmed = value.trim();
52
- if (trimmed.length === 0 || trimmed.length > MAX_DETECTED_PI_VERSION_LENGTH) return "unknown";
53
- return parsePiVersion(trimmed) ? trimmed : "unknown";
54
- }
55
-
56
- function isSupportedPiVersion(version: string): boolean {
57
- const detected = parsePiVersion(version);
58
- const minimum = parsePiVersion(MINIMUM_SUPPORTED_PI_VERSION);
59
- const maximum = parsePiVersion(FIRST_UNSUPPORTED_PI_VERSION);
60
- if (!detected || detected.prerelease || !minimum || !maximum) return false;
61
-
62
- return comparePiVersions(detected, minimum) >= 0 && comparePiVersions(detected, maximum) < 0;
63
- }
64
-
65
- interface PiVersion {
66
- major: number;
67
- minor: number;
68
- patch: number;
69
- prerelease?: string;
70
- }
71
-
72
- function parsePiVersion(version: string): PiVersion | undefined {
73
- const buildSeparatorIndex = version.indexOf("+");
74
- const versionAndPrerelease = buildSeparatorIndex === -1 ? version : version.slice(0, buildSeparatorIndex);
75
- const build = buildSeparatorIndex === -1 ? undefined : version.slice(buildSeparatorIndex + 1);
76
- if (build !== undefined && !hasValidSemanticVersionIdentifiers(build, true)) return undefined;
77
-
78
- const prereleaseSeparatorIndex = versionAndPrerelease.indexOf("-");
79
- const coreVersion = prereleaseSeparatorIndex === -1
80
- ? versionAndPrerelease
81
- : versionAndPrerelease.slice(0, prereleaseSeparatorIndex);
82
- const prerelease = prereleaseSeparatorIndex === -1
83
- ? undefined
84
- : versionAndPrerelease.slice(prereleaseSeparatorIndex + 1);
85
- if (prerelease !== undefined && !hasValidSemanticVersionIdentifiers(prerelease, false)) return undefined;
86
-
87
- const match = piVersionCorePattern.exec(coreVersion);
88
- if (!match) return undefined;
89
-
90
- const major = Number(match[1]);
91
- const minor = Number(match[2]);
92
- const patch = Number(match[3]);
93
- if (!Number.isSafeInteger(major) || !Number.isSafeInteger(minor) || !Number.isSafeInteger(patch)) {
94
- return undefined;
95
- }
96
-
97
- return {
98
- major,
99
- minor,
100
- patch,
101
- ...(prerelease === undefined ? {} : { prerelease }),
102
- };
103
- }
104
-
105
- function hasValidSemanticVersionIdentifiers(value: string, allowLeadingZeros: boolean): boolean {
106
- for (const identifier of value.split(".")) {
107
- if (!semanticVersionIdentifierPattern.test(identifier)) return false;
108
- if (!allowLeadingZeros && hasInvalidNumericIdentifier(identifier)) return false;
109
- }
110
- return true;
111
- }
112
-
113
- function hasInvalidNumericIdentifier(identifier: string): boolean {
114
- return identifier.length > 1 && identifier.startsWith("0") && numericIdentifierPattern.test(identifier);
115
- }
116
-
117
- function comparePiVersions(left: PiVersion, right: PiVersion): number {
118
- if (left.major !== right.major) return left.major - right.major;
119
- if (left.minor !== right.minor) return left.minor - right.minor;
120
- return left.patch - right.patch;
121
- }
@@ -65,8 +65,8 @@ import type { AgentWaitJoinState, SubagentSpawnState } from "./subagent-types.ts
65
65
 
66
66
  export const OBSERVME_SEMCONV_VERSION = "0.1.0";
67
67
 
68
- const piApiCompatibilityErrorMessage =
69
- "ObservMe/Pi API compatibility error: expected Pi ExtensionAPI with on(eventName, handler) before registering ObservMe handlers.";
68
+ const piApiCapabilityErrorMessage =
69
+ "ObservMe/Pi API capability error: expected Pi ExtensionAPI with on(eventName, handler) before registering ObservMe handlers.";
70
70
  const eventRegistrationOrder = [
71
71
  "session_start",
72
72
  "session_info_changed",
@@ -143,10 +143,10 @@ export class SerializedLifecycleQueue {
143
143
  }
144
144
 
145
145
  export function resolveObservMePiApi(pi: unknown): ObservMePiApi {
146
- if (!isRecord(pi)) throw new TypeError(piApiCompatibilityErrorMessage);
146
+ if (!isRecord(pi)) throw new TypeError(piApiCapabilityErrorMessage);
147
147
 
148
148
  const on = pi.on;
149
- if (typeof on !== "function") throw new TypeError(piApiCompatibilityErrorMessage);
149
+ if (typeof on !== "function") throw new TypeError(piApiCapabilityErrorMessage);
150
150
 
151
151
  const appendEntry = typeof pi.appendEntry === "function"
152
152
  ? (pi.appendEntry.bind(pi) as NonNullable<ObservMePiApi["appendEntry"]>)