@zeph-to/cli 1.15.2 → 1.15.3

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.
@@ -8,6 +8,13 @@ export declare const RULES_REFRESH_INTERVAL_MS: number;
8
8
  * back to bundled rules.
9
9
  */
10
10
  export declare const validateManifest: (value: unknown) => DetectionManifest | null;
11
+ /**
12
+ * Segment-wise numeric compare of dotted date versions
13
+ * ("2026.07.04.3"). Plain string compare fails on ".10" vs ".9";
14
+ * non-numeric segments compare as equal so a malformed version can
15
+ * never crash the refresh path.
16
+ */
17
+ export declare const compareManifestVersions: (a: string, b: string) => number;
11
18
  export type ManifestSource = 'remote' | 'cache' | 'bundled';
12
19
  export declare const getActiveManifest: () => DetectionManifest;
13
20
  export declare const getActiveManifestSource: () => ManifestSource;
@@ -21,7 +28,7 @@ export declare const loadManifestFromCache: () => ManifestSource;
21
28
  export declare const rulesUrl: () => string;
22
29
  export interface RefreshResult {
23
30
  source: ManifestSource;
24
- /** 'updated' | 'not-modified' | 'invalid' | 'error' — for verbose logs. */
31
+ /** 'updated' | 'not-modified' | 'stale-ignored' | 'invalid' | 'error' — for verbose logs. */
25
32
  outcome: string;
26
33
  version?: string;
27
34
  }
@@ -1 +1 @@
1
- {"version":3,"file":"agent-rules-fetch.d.ts","sourceRoot":"","sources":["../src/agent-rules-fetch.ts"],"names":[],"mappings":"AAeA,OAAO,EAEH,KAAK,iBAAiB,EACzB,MAAM,kBAAkB,CAAC;AAG1B,eAAO,MAAM,gBAAgB,QAAuC,CAAC;AACrE,eAAO,MAAM,yBAAyB,QAAqB,CAAC;AA6C5D;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAAI,OAAO,OAAO,KAAG,iBAAiB,GAAG,IAWrE,CAAC;AAIF,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAK5D,eAAO,MAAM,iBAAiB,QAAO,iBAAmC,CAAC;AACzE,eAAO,MAAM,uBAAuB,QAAO,cAA8B,CAAC;AAS1E,iBAAiB;AACjB,eAAO,MAAM,mBAAmB,QAAO,IAEtC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAO,cAWxC,CAAC;AAWF,eAAO,MAAM,QAAQ,QAAO,MAK3B,CAAC;AAEF,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,cAAc,CAAC;IACvB,2EAA2E;IAC3E,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAU,YAAW,OAAO,KAAa,KAAG,OAAO,CAAC,aAAa,CAsC5F,CAAC"}
1
+ {"version":3,"file":"agent-rules-fetch.d.ts","sourceRoot":"","sources":["../src/agent-rules-fetch.ts"],"names":[],"mappings":"AAuBA,OAAO,EAEH,KAAK,iBAAiB,EACzB,MAAM,kBAAkB,CAAC;AAG1B,eAAO,MAAM,gBAAgB,QAAuC,CAAC;AACrE,eAAO,MAAM,yBAAyB,QAAqB,CAAC;AA6C5D;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAAI,OAAO,OAAO,KAAG,iBAAiB,GAAG,IAWrE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,MAU9D,CAAC;AAIF,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAK5D,eAAO,MAAM,iBAAiB,QAAO,iBAAmC,CAAC;AACzE,eAAO,MAAM,uBAAuB,QAAO,cAA8B,CAAC;AAS1E,iBAAiB;AACjB,eAAO,MAAM,mBAAmB,QAAO,IAEtC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAO,cAWxC,CAAC;AAWF,eAAO,MAAM,QAAQ,QAAO,MAK3B,CAAC;AAEF,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,cAAc,CAAC;IACvB,6FAA6F;IAC7F,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAU,YAAW,OAAO,KAAa,KAAG,OAAO,CAAC,aAAa,CA4C5F,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.refreshManifest = exports.rulesUrl = exports.loadManifestFromCache = exports.resetActiveManifest = exports.getActiveManifestSource = exports.getActiveManifest = exports.validateManifest = exports.RULES_REFRESH_INTERVAL_MS = exports.RULES_CACHE_FILE = void 0;
3
+ exports.refreshManifest = exports.rulesUrl = exports.loadManifestFromCache = exports.resetActiveManifest = exports.getActiveManifestSource = exports.getActiveManifest = exports.compareManifestVersions = exports.validateManifest = exports.RULES_REFRESH_INTERVAL_MS = exports.RULES_CACHE_FILE = void 0;
4
4
  /**
5
5
  * OTA delivery for agent detection rules (SPEC-AGENT-AWARENESS §S7).
6
6
  *
@@ -12,6 +12,14 @@ exports.refreshManifest = exports.rulesUrl = exports.loadManifestFromCache = exp
12
12
  * hostile payload can never leave the listener without rules, and
13
13
  * `disabledRuleIds` in a fetched manifest acts as a same-day
14
14
  * kill-switch for a misfiring rule (no release, no restart).
15
+ *
16
+ * Version precedence: a fetched/cached manifest only activates when
17
+ * its version is >= the bundled one. npm publishes land in minutes
18
+ * while the server manifest ships with a full deploy, so a fresh cli
19
+ * routinely carries NEWER rules than the endpoint — without the gate,
20
+ * the older remote manifest would shadow every bundled rule fix until
21
+ * the server caught up. Server-side rollback still works: the server
22
+ * bumps the version even when reverting rule content.
15
23
  */
16
24
  const fs_1 = require("fs");
17
25
  const path_1 = require("path");
@@ -90,6 +98,26 @@ const validateManifest = (value) => {
90
98
  return value;
91
99
  };
92
100
  exports.validateManifest = validateManifest;
101
+ /**
102
+ * Segment-wise numeric compare of dotted date versions
103
+ * ("2026.07.04.3"). Plain string compare fails on ".10" vs ".9";
104
+ * non-numeric segments compare as equal so a malformed version can
105
+ * never crash the refresh path.
106
+ */
107
+ const compareManifestVersions = (a, b) => {
108
+ const as = a.split('.').map(Number);
109
+ const bs = b.split('.').map(Number);
110
+ const len = Math.max(as.length, bs.length);
111
+ for (let i = 0; i < len; i++) {
112
+ const d = (as[i] ?? 0) - (bs[i] ?? 0);
113
+ if (Number.isNaN(d))
114
+ continue;
115
+ if (d !== 0)
116
+ return d < 0 ? -1 : 1;
117
+ }
118
+ return 0;
119
+ };
120
+ exports.compareManifestVersions = compareManifestVersions;
93
121
  let activeManifest = agent_rules_default_js_1.DEFAULT_MANIFEST;
94
122
  let activeSource = 'bundled';
95
123
  const getActiveManifest = () => activeManifest;
@@ -115,7 +143,7 @@ const loadManifestFromCache = () => {
115
143
  try {
116
144
  const cache = JSON.parse((0, fs_1.readFileSync)(exports.RULES_CACHE_FILE, 'utf-8'));
117
145
  const manifest = (0, exports.validateManifest)(cache.manifest);
118
- if (manifest) {
146
+ if (manifest && (0, exports.compareManifestVersions)(manifest.version, agent_rules_default_js_1.DEFAULT_MANIFEST.version) >= 0) {
119
147
  activateManifest(manifest, 'cache');
120
148
  }
121
149
  }
@@ -180,6 +208,12 @@ const refreshManifest = async (fetchImpl = fetch) => {
180
208
  // Cache write failure is non-fatal: the manifest still
181
209
  // activates for this process lifetime.
182
210
  }
211
+ if ((0, exports.compareManifestVersions)(manifest.version, agent_rules_default_js_1.DEFAULT_MANIFEST.version) < 0) {
212
+ // Endpoint hasn't caught up to this build's bundled rules.
213
+ // Cache is still written above (the ETag stops refetch churn)
214
+ // but startup applies the same gate, so bundled stays active.
215
+ return { source: activeSource, outcome: 'stale-ignored', version: manifest.version };
216
+ }
183
217
  activateManifest(manifest, 'remote');
184
218
  return { source: 'remote', outcome: 'updated', version: manifest.version };
185
219
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeph-to/cli",
3
- "version": "1.15.2",
3
+ "version": "1.15.3",
4
4
  "description": "Zeph CLI + push notification SDK for AI agents",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",