@gamaze/hicortex 0.17.0 → 0.17.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.
package/README.md CHANGED
@@ -218,6 +218,7 @@ Config at `~/.hicortex/config.json`. Created by `init`. Key options:
218
218
  | `captureCooldownHours` | Success-cooldown (hours) for the **capture watchdog** (0.17). The capture timer polls every ~20 min; the watchdog captures only if more than this has elapsed since the last *successful* capture (`state.lastNightly`). Default `6` (≈4 captures/day). A failed preflight retries on the next poll (~20 min) — so a transient fire-instant network miss costs minutes, not a day (#239) |
219
219
  | `consolidationHours` | Hours (0–23, local) for the **consolidation** timer — the full nightly (capture + distill + score + reflect + link). Installed for **server/co-located only** (clients have no local DB). Default `[10, 22]`: the 22:00 evening slot runs after the day's capture waves (same-day results); the 10:00 morning slot runs *after* the morning capture so wake-up pushes are caught. Omitted on clients |
220
220
  | `consolidateMaxLlmCalls` | Ceiling on total LLM calls across all classify-tier consolidation stages (content-domain, link discovery, supersession) per run. A runaway **backstop**, not a throughput throttle — on a free local model the binding constraint is the nightly unit's wall-clock timeout, not call count. Default `5000` (was a hard-coded 200 that starved link/supersession during a classification backlog) |
221
+ | `updateChannel` | Release channel pinned into the generated daemon/timer ExecStart for **npx-thin** installs (global-binary installs use the absolute binary and are unaffected). A dist-tag (`"rc"`, `"next"`) or an exact version (`"0.17.1"`). E.g. `"rc"` → the timer runs `npx -y @gamaze/hicortex@rc nightly`, so the host tracks the rc dist-tag (an internal fleet can ride rc through a pre-promotion soak). Validated as `[\w.\-]+` (rejects anything that'd break the unit/plist templates). Absent → auto-detect (bare on `latest`, else `@next`). (0.17.1) |
221
222
  | `nightlyHour` | **Deprecated (0.17) single-slot fallback.** Local hour (0–23) honoured only when `consolidationHours` is absent — yields one daily consolidation slot at that hour (preserves the pre-0.17 "one daily job" intent). New installs should use `consolidationHours` |
222
223
  | `preflightTimeoutMs` | **Client mode only.** Per-attempt timeout for the nightly's server-reachability check before it starts capturing (default: 20000 ms, bumped from 15000 in 0.17 to absorb a cold Tailscale handshake on a roaming laptop) |
223
224
  | `preflightAttempts` | **Client mode only.** Reachability-check retries before the nightly aborts (default: 3; floored at 1). `1` = single try, no retry |
package/dist/init.d.ts CHANGED
@@ -262,6 +262,23 @@ export declare const GENERIC_DEFAULT_DOMAINS: DomainDef[];
262
262
  export declare function scaffoldDefaultDomains(configPath: string): {
263
263
  scaffolded: boolean;
264
264
  };
265
+ /**
266
+ * Determine the npm package specifier used in the generated daemon/timer
267
+ * ExecStart (for npx-thin installs — global-binary installs use the absolute
268
+ * binary path and never call this). Tag-based so restarts pick up new versions.
269
+ *
270
+ * Priority:
271
+ * 1. `updateChannel` config key (e.g. "rc") → `@gamaze/hicortex@<channel>`.
272
+ * Lets an install pin a release channel — the internal fleet sets "rc" so
273
+ * its npx-thin hosts track the rc dist-tag through a pre-promotion soak
274
+ * (otherwise the auto-detect below pins @next, which lags rc).
275
+ * 2. Auto-detect: bare `@gamaze/hicortex` if the running version matches the
276
+ * npm `latest` tag, else `@gamaze/hicortex@next` (legacy pre-0.10 cron
277
+ * installs follow @next).
278
+ *
279
+ * Exported + `configDir`-parametrised so the channel override is unit-testable.
280
+ */
281
+ export declare function getPackageSpec(configDir?: string): string;
265
282
  /**
266
283
  * True if a resolved binary path lives in npm's ephemeral npx cache
267
284
  * (`~/.npm/_npx/<hash>/node_modules/.bin/…`). When `hicortex init` is itself
package/dist/init.js CHANGED
@@ -32,6 +32,7 @@ exports.decideAgentName = decideAgentName;
32
32
  exports.writeAgentNameConfig = writeAgentNameConfig;
33
33
  exports.writeClientConfig = writeClientConfig;
34
34
  exports.scaffoldDefaultDomains = scaffoldDefaultDomains;
35
+ exports.getPackageSpec = getPackageSpec;
35
36
  exports.isEphemeralNpxPath = isEphemeralNpxPath;
36
37
  exports.installSessionStartHook = installSessionStartHook;
37
38
  exports.installRecallHooks = installRecallHooks;
@@ -242,15 +243,23 @@ function verifyCcMcp() {
242
243
  }
243
244
  }
244
245
  function allowHicortexTools() {
245
- let settings = {};
246
- if ((0, node_fs_1.existsSync)(CC_SETTINGS)) {
247
- try {
248
- settings = JSON.parse((0, node_fs_1.readFileSync)(CC_SETTINGS, "utf-8"));
249
- }
250
- catch {
251
- console.log(` ${CC_SETTINGS} exists but is not valid JSON — skipping tool permissions. Fix the file, then re-run init or add "mcp__hicortex__*" to permissions.allow manually.`);
252
- return;
253
- }
246
+ // Only EDIT an existing CC settings file — never invent one. On a host with
247
+ // no CC client (a server, or a Hermes-only box) ~/.claude/settings.json is
248
+ // absent; creating a stub there is wrong, and the earlier mkdir+write was the
249
+ // ENOENT throw on bedrock's init. Without this entry CC just PROMPTS before
250
+ // tool use instead of auto-allowing — the MCP still works either way.
251
+ if (!(0, node_fs_1.existsSync)(CC_SETTINGS)) {
252
+ console.log(` ${CC_SETTINGS} not found — skipping CC tool permissions (no CC client here; ` +
253
+ `the MCP works, CC will ask before tool use).`);
254
+ return;
255
+ }
256
+ let settings;
257
+ try {
258
+ settings = JSON.parse((0, node_fs_1.readFileSync)(CC_SETTINGS, "utf-8"));
259
+ }
260
+ catch {
261
+ console.log(` ⚠ ${CC_SETTINGS} exists but is not valid JSON — skipping tool permissions. Fix the file, then re-run init or add "mcp__hicortex__*" to permissions.allow manually.`);
262
+ return;
254
263
  }
255
264
  if (!settings.permissions)
256
265
  settings.permissions = {};
@@ -261,7 +270,6 @@ function allowHicortexTools() {
261
270
  const rule = "mcp__hicortex__*";
262
271
  if (!allow.includes(rule)) {
263
272
  allow.push(rule);
264
- (0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(CC_SETTINGS), { recursive: true });
265
273
  (0, node_fs_1.writeFileSync)(CC_SETTINGS, JSON.stringify(settings, null, 2));
266
274
  console.log(` ✓ Added Hicortex tool permissions to ${CC_SETTINGS}`);
267
275
  }
@@ -1068,14 +1076,38 @@ function scaffoldDefaultDomains(configPath) {
1068
1076
  return { scaffolded: true };
1069
1077
  }
1070
1078
  /**
1071
- * Determine the npm package specifier for the daemon.
1072
- * Uses tag-based resolution so restarts pick up new versions automatically.
1079
+ * Determine the npm package specifier used in the generated daemon/timer
1080
+ * ExecStart (for npx-thin installs global-binary installs use the absolute
1081
+ * binary path and never call this). Tag-based so restarts pick up new versions.
1073
1082
  *
1074
- * Checks if the current version matches the npm `latest` tag.
1075
- * If not (e.g. running from @next), uses @gamaze/hicortex@next.
1076
- * If it does match latest, uses bare @gamaze/hicortex.
1083
+ * Priority:
1084
+ * 1. `updateChannel` config key (e.g. "rc") `@gamaze/hicortex@<channel>`.
1085
+ * Lets an install pin a release channel the internal fleet sets "rc" so
1086
+ * its npx-thin hosts track the rc dist-tag through a pre-promotion soak
1087
+ * (otherwise the auto-detect below pins @next, which lags rc).
1088
+ * 2. Auto-detect: bare `@gamaze/hicortex` if the running version matches the
1089
+ * npm `latest` tag, else `@gamaze/hicortex@next` (legacy pre-0.10 cron
1090
+ * installs follow @next).
1091
+ *
1092
+ * Exported + `configDir`-parametrised so the channel override is unit-testable.
1077
1093
  */
1078
- function getPackageSpec() {
1094
+ function getPackageSpec(configDir = HICORTEX_HOME) {
1095
+ try {
1096
+ const { config } = loadConfigStrict((0, node_path_1.join)(configDir, "config.json"));
1097
+ const ch = config.updateChannel;
1098
+ if (typeof ch === "string") {
1099
+ const trimmed = ch.trim();
1100
+ // A dist-tag (rc/next/latest) or an exact version — alphanumerics, dot,
1101
+ // dash, underscore only. Reject anything else: a newline would break the
1102
+ // systemd `ExecStart=` one-liner and `<`/`&` would break the launchd plist
1103
+ // XML the timer writes. Fall through to auto-detect + warn.
1104
+ if (/^[\w.\-]+$/.test(trimmed))
1105
+ return `@gamaze/hicortex@${trimmed}`;
1106
+ console.warn(`[hicortex] config "updateChannel" = ${JSON.stringify(ch)} is not a valid dist-tag/version ` +
1107
+ `(use e.g. "rc", "next", or "0.17.1") — ignored.`);
1108
+ }
1109
+ }
1110
+ catch { /* no config yet, or malformed — fall through to auto-detect */ }
1079
1111
  try {
1080
1112
  const currentVersion = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(__dirname, "..", "package.json"), "utf-8")).version;
1081
1113
  const latestVersion = (0, node_child_process_1.execSync)("npm view @gamaze/hicortex version 2>/dev/null", {
package/dist/types.d.ts CHANGED
@@ -244,6 +244,15 @@ export interface HicortexConfig {
244
244
  * classification backlog and drained large backlogs at ~cap/night).
245
245
  */
246
246
  consolidateMaxLlmCalls?: number;
247
+ /**
248
+ * Release channel pinned into the generated daemon/timer ExecStart for
249
+ * **npx-thin** installs (global-binary installs use the absolute binary path
250
+ * and are unaffected). E.g. `"rc"` → the timer runs
251
+ * `npx -y @gamaze/hicortex@rc nightly`, so the host tracks the rc dist-tag
252
+ * (the internal fleet uses this to ride rc through a pre-promotion soak).
253
+ * Absent → auto-detect (bare on `latest`, else `@next`). (0.17.1)
254
+ */
255
+ updateChannel?: string;
247
256
  /**
248
257
  * Minimum cosine(memory embedding, best domain prototype) for a no-fit
249
258
  * memory to earn a WEAK primary instead of decaying (see nofit.ts).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gamaze/hicortex",
3
- "version": "0.17.0",
3
+ "version": "0.17.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": {