@gamaze/hicortex 0.14.4 → 0.15.1

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.
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ /**
3
+ * `hicortex telemetry` — transparency surface for anonymous usage telemetry.
4
+ *
5
+ * Read-only BY DESIGN (owner decision 30.07.2026). It shows the exact payload
6
+ * and both documented ways to switch telemetry off, but it does not flip the
7
+ * switch itself: the `telemetry` key is deliberately NOT scaffolded into
8
+ * config.json, and opting out is a deliberate edit the operator makes. Turning
9
+ * it off must stay completely possible and completely documented — just not a
10
+ * one-keystroke default-path action.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.runTelemetryCommand = runTelemetryCommand;
14
+ const node_fs_1 = require("node:fs");
15
+ const node_path_1 = require("node:path");
16
+ const paths_js_1 = require("./paths.js");
17
+ const telemetry_js_1 = require("./telemetry.js");
18
+ function readConfig(home) {
19
+ try {
20
+ return JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(home, "config.json"), "utf-8"));
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ function printHowToDisable(home) {
27
+ console.log("To turn it off (either one works, both are permanent):");
28
+ console.log(` 1. add "telemetry": false to ${(0, node_path_1.join)(home, "config.json")}`);
29
+ console.log(" 2. or set HICORTEX_TELEMETRY=off in the environment");
30
+ }
31
+ function runTelemetryCommand(args) {
32
+ const home = (0, paths_js_1.hicortexHome)();
33
+ const sub = args[0] ?? "status";
34
+ if (sub === "on" || sub === "off") {
35
+ // Intentionally not a write command — see the module docstring.
36
+ console.log(`[hicortex] telemetry is not toggled by this command; it reports state only.`);
37
+ printHowToDisable(home);
38
+ return;
39
+ }
40
+ if (sub !== "status") {
41
+ console.error(`[hicortex] telemetry: unknown subcommand '${sub}' (only 'status' is supported)`);
42
+ process.exit(1);
43
+ }
44
+ const config = readConfig(home);
45
+ const reason = (0, telemetry_js_1.telemetryDisabledReason)(config);
46
+ const mode = config?.mode === "client" ? "client" : "server";
47
+ console.log("Hicortex telemetry");
48
+ console.log("──────────────────────────────────────────");
49
+ if (reason) {
50
+ console.log(`Status: DISABLED (via ${reason === "env" ? "HICORTEX_TELEMETRY env var" : 'config.json "telemetry": false'})`);
51
+ console.log("Nothing is sent. Remove that setting to re-enable.");
52
+ return;
53
+ }
54
+ console.log("Status: ENABLED (anonymous, aggregate only) — the default");
55
+ console.log(`Endpoint: ${telemetry_js_1.TELEMETRY_URL}`);
56
+ console.log("When: once at the end of each full nightly run");
57
+ console.log("");
58
+ console.log("Exactly what is sent (counts from this install; values vary per run):");
59
+ const example = {
60
+ id: (0, telemetry_js_1.getTelemetryId)(home),
61
+ v: "<package version>",
62
+ pv: telemetry_js_1.TELEMETRY_PAYLOAD_VERSION,
63
+ mode,
64
+ agent: "<cc|hermes|pi|oc|mixed>",
65
+ mem: "<total memories>",
66
+ lessons: "<total lessons>",
67
+ sessions: "<sessions captured this run>",
68
+ ok: "<nightly succeeded>",
69
+ };
70
+ if (mode === "server") {
71
+ example.shown = "<sum of shown_count>";
72
+ example.uses = "<sum of access_count>";
73
+ example.cold = "<memories never shown or used>";
74
+ }
75
+ console.log(JSON.stringify(example, null, 2));
76
+ console.log("");
77
+ console.log("NOT sent: memory content, prompts, file paths, project names,");
78
+ console.log("hostnames, tokens, or IP addresses (the server stores no IPs).");
79
+ console.log("Every install sends the same fields — nothing marks yours as special.");
80
+ console.log("");
81
+ printHowToDisable(home);
82
+ }
@@ -1,18 +1,32 @@
1
1
  /**
2
2
  * Anonymous telemetry — sends aggregate stats after each nightly run.
3
3
  *
4
- * What's sent (8 fields, all aggregate):
4
+ * What's sent (all aggregate, payload version 2 since 0.15.1):
5
5
  * id — random UUID, generated once on first run, stored in state.json
6
6
  * v — package version
7
+ * pv — payload schema version
7
8
  * mode — server or client
8
9
  * agent — cc, pi, oc, or mixed (detected from session sources)
9
10
  * mem — total memory count
10
11
  * lessons — total lesson count
11
12
  * sessions — sessions distilled this run
12
13
  * ok — nightly succeeded (true/false)
14
+ * shown — sum of shown_count (server mode only)
15
+ * uses — sum of access_count (server mode only)
16
+ * cold — memories never shown and never used (server mode only)
17
+ *
18
+ * Every install sends the SAME fields — nothing marks an install as special
19
+ * (a rare label would be a fingerprint, i.e. no longer anonymous). Excluding
20
+ * the maintainer's own installs from adoption stats is an analysis-side
21
+ * concern, done by anonymous id at the admin endpoint.
13
22
  *
14
23
  * What's NOT sent:
15
- * No personal data, no session content, no file paths, no IPs stored.
24
+ * No personal data, no session content, no file paths, no project names,
25
+ * no hostnames, no tokens. The server stores no IPs.
26
+ *
27
+ * Inspect / control:
28
+ * `hicortex telemetry` prints the exact payload shape and current state;
29
+ * `hicortex telemetry off` / `on` flips it.
16
30
  *
17
31
  * Opt-out:
18
32
  * Set "telemetry": false in ~/.hicortex/config.json
@@ -21,6 +35,7 @@
21
35
  * The ping is fire-and-forget with a 5s timeout. If it fails, nothing
22
36
  * happens — the nightly result is unaffected.
23
37
  */
38
+ export declare const TELEMETRY_URL = "https://hicortex.gamaze.com/api/telemetry";
24
39
  export interface TelemetryPayload {
25
40
  id: string;
26
41
  v: string;
@@ -30,6 +45,18 @@ export interface TelemetryPayload {
30
45
  lessons: number;
31
46
  sessions: number;
32
47
  ok: boolean;
48
+ /** Payload schema version (2 = adoption fields, 0.15.1). Absent = v1. */
49
+ pv?: number;
50
+ /**
51
+ * Adoption aggregates (server mode only — a client install has no DB).
52
+ * `shown`/`uses` are corpus-wide sums of shown_count/access_count; their
53
+ * ratio (uses per showing) is the recall-quality signal. `cold` counts
54
+ * memories never shown AND never used. Aggregate counts only — no content,
55
+ * no ids, nothing per-memory.
56
+ */
57
+ shown?: number;
58
+ uses?: number;
59
+ cold?: number;
33
60
  }
34
61
  /**
35
62
  * Check if telemetry is enabled. Disabled by:
@@ -42,6 +69,13 @@ export declare function isTelemetryEnabled(config: Record<string, unknown> | nul
42
69
  * Generated once, stored in state.json, never linked to any personal info.
43
70
  */
44
71
  export declare function getTelemetryId(stateDir: string): string;
72
+ /** Payload schema version sent by this release. */
73
+ export declare const TELEMETRY_PAYLOAD_VERSION = 2;
74
+ /**
75
+ * Why telemetry is off, or null when it is on. Exposed so `hicortex telemetry`
76
+ * can tell the operator WHICH switch is in effect (config vs env).
77
+ */
78
+ export declare function telemetryDisabledReason(config: Record<string, unknown> | null): "config" | "env" | null;
45
79
  /**
46
80
  * Send anonymous telemetry. Fire-and-forget — failures are silently ignored.
47
81
  */
package/dist/telemetry.js CHANGED
@@ -2,18 +2,32 @@
2
2
  /**
3
3
  * Anonymous telemetry — sends aggregate stats after each nightly run.
4
4
  *
5
- * What's sent (8 fields, all aggregate):
5
+ * What's sent (all aggregate, payload version 2 since 0.15.1):
6
6
  * id — random UUID, generated once on first run, stored in state.json
7
7
  * v — package version
8
+ * pv — payload schema version
8
9
  * mode — server or client
9
10
  * agent — cc, pi, oc, or mixed (detected from session sources)
10
11
  * mem — total memory count
11
12
  * lessons — total lesson count
12
13
  * sessions — sessions distilled this run
13
14
  * ok — nightly succeeded (true/false)
15
+ * shown — sum of shown_count (server mode only)
16
+ * uses — sum of access_count (server mode only)
17
+ * cold — memories never shown and never used (server mode only)
18
+ *
19
+ * Every install sends the SAME fields — nothing marks an install as special
20
+ * (a rare label would be a fingerprint, i.e. no longer anonymous). Excluding
21
+ * the maintainer's own installs from adoption stats is an analysis-side
22
+ * concern, done by anonymous id at the admin endpoint.
14
23
  *
15
24
  * What's NOT sent:
16
- * No personal data, no session content, no file paths, no IPs stored.
25
+ * No personal data, no session content, no file paths, no project names,
26
+ * no hostnames, no tokens. The server stores no IPs.
27
+ *
28
+ * Inspect / control:
29
+ * `hicortex telemetry` prints the exact payload shape and current state;
30
+ * `hicortex telemetry off` / `on` flips it.
17
31
  *
18
32
  * Opt-out:
19
33
  * Set "telemetry": false in ~/.hicortex/config.json
@@ -23,12 +37,14 @@
23
37
  * happens — the nightly result is unaffected.
24
38
  */
25
39
  Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.TELEMETRY_PAYLOAD_VERSION = exports.TELEMETRY_URL = void 0;
26
41
  exports.isTelemetryEnabled = isTelemetryEnabled;
27
42
  exports.getTelemetryId = getTelemetryId;
43
+ exports.telemetryDisabledReason = telemetryDisabledReason;
28
44
  exports.sendTelemetry = sendTelemetry;
29
45
  const node_crypto_1 = require("node:crypto");
30
46
  const state_js_1 = require("./state.js");
31
- const TELEMETRY_URL = "https://hicortex.gamaze.com/api/telemetry";
47
+ exports.TELEMETRY_URL = "https://hicortex.gamaze.com/api/telemetry";
32
48
  /**
33
49
  * Check if telemetry is enabled. Disabled by:
34
50
  * - config.telemetry === false
@@ -59,10 +75,24 @@ function getTelemetryId(stateDir) {
59
75
  }, stateDir);
60
76
  return id;
61
77
  }
78
+ /** Payload schema version sent by this release. */
79
+ exports.TELEMETRY_PAYLOAD_VERSION = 2;
80
+ /**
81
+ * Why telemetry is off, or null when it is on. Exposed so `hicortex telemetry`
82
+ * can tell the operator WHICH switch is in effect (config vs env).
83
+ */
84
+ function telemetryDisabledReason(config) {
85
+ const env = process.env.HICORTEX_TELEMETRY?.toLowerCase();
86
+ if (env === "off" || env === "false" || env === "0")
87
+ return "env";
88
+ if (config?.telemetry === false)
89
+ return "config";
90
+ return null;
91
+ }
62
92
  /**
63
93
  * Send anonymous telemetry. Fire-and-forget — failures are silently ignored.
64
94
  */
65
- async function sendTelemetry(payload, serverUrl = TELEMETRY_URL) {
95
+ async function sendTelemetry(payload, serverUrl = exports.TELEMETRY_URL) {
66
96
  try {
67
97
  await fetch(serverUrl, {
68
98
  method: "POST",
package/dist/types.d.ts CHANGED
@@ -108,6 +108,21 @@ export interface ConsolidationReport {
108
108
  heuristic_fallback?: number;
109
109
  failed: number;
110
110
  };
111
+ /** Supersession detection (#191 Phase B) — runs after linking, before decay/prune. */
112
+ supersession?: {
113
+ /** Decision/correction-shaped candidates examined this run. */
114
+ scanned: number;
115
+ /** Older-neighbor pairs actually sent to the classify-tier LLM. */
116
+ evaluated: number;
117
+ /** Pairs the LLM judged superseded — a `superseded_by` link was created. */
118
+ superseded: number;
119
+ /** Pairs skipped on a parse/infra error (retried naturally next night). */
120
+ skipped_infra: number;
121
+ /** Pairs skipped because a superseded_by link already existed (either direction). */
122
+ skipped_idempotent: number;
123
+ /** supersessionCursor after this run (unchanged in dry-run). */
124
+ cursor: number;
125
+ };
111
126
  decay_prune?: {
112
127
  candidates: number;
113
128
  pruned: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gamaze/hicortex",
3
- "version": "0.14.4",
3
+ "version": "0.15.1",
4
4
  "description": "Self-learning memory for AI agents — experience captured automatically, distilled into lessons overnight, shared across your whole fleet. Works with Hermes, OpenClaw, Claude Code, and Pi.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -37,6 +37,7 @@
37
37
  "build": "rm -rf dist && tsc",
38
38
  "test": "vitest run",
39
39
  "test:watch": "vitest",
40
+ "eval": "node dist/eval/run-eval.js",
40
41
  "prepack": "npm run build && rm -rf ./hermes-plugin && mkdir -p ./hermes-plugin && cp -r ../../hermes-plugin/hicortex ./hermes-plugin/ && find ./hermes-plugin -name __pycache__ -type d -exec rm -rf {} + 2>/dev/null || true",
41
42
  "prepublishOnly": "npm run build && rm -rf ./hermes-plugin && mkdir -p ./hermes-plugin && cp -r ../../hermes-plugin/hicortex ./hermes-plugin/ && find ./hermes-plugin -name __pycache__ -type d -exec rm -rf {} + 2>/dev/null || true"
42
43
  },