@nac3/forge-cli 1.2.2 → 1.2.4

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.
@@ -6,7 +6,17 @@ export interface InstanceIdentity {
6
6
  pid: number;
7
7
  }
8
8
  /** The identity for THIS process (created once, then cached). id =
9
- * "<hostname>-<6 hex>" so it is both unique and human-legible in logs. */
9
+ * "<hostname>-<6 hex>" so it is both unique and human-legible in logs.
10
+ *
11
+ * STABLE per (host, project dir) since 2026-09-03. It used to be
12
+ * randomBytes -> a brand-new id on EVERY process start, so each desktop
13
+ * restart orphaned a GHOST instance on the relay: its retained presence
14
+ * events lingered in the log and the phone (which replays them on reconnect)
15
+ * listed the dead instance as live -> duplicated projects in the picker and,
16
+ * worse, the phone would target a ghost id (no board switch, no chat reply).
17
+ * Deriving the suffix from the working directory -- and item 1 guarantees at
18
+ * most ONE live instance per project root -- means a restart REUSES the same
19
+ * id (replace, not accumulate) and the phone's saved pick survives it. */
10
20
  export declare function getInstanceIdentity(): InstanceIdentity;
11
21
  /** Test seam: force a known identity (and reset with null). */
12
22
  export declare function _setInstanceIdentityForTests(id: InstanceIdentity | null): void;
@@ -1 +1 @@
1
- {"version":3,"file":"instance_identity.d.ts","sourceRoot":"","sources":["../../src/relay/instance_identity.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,gBAAgB;IAC/B,2DAA2D;IAC3D,EAAE,EAAE,MAAM,CAAC;IACX,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAID;2EAC2E;AAC3E,wBAAgB,mBAAmB,IAAI,gBAAgB,CAOtD;AAED,+DAA+D;AAC/D,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,gBAAgB,GAAG,IAAI,GAAG,IAAI,CAE9E"}
1
+ {"version":3,"file":"instance_identity.d.ts","sourceRoot":"","sources":["../../src/relay/instance_identity.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,gBAAgB;IAC/B,2DAA2D;IAC3D,EAAE,EAAE,MAAM,CAAC;IACX,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAID;;;;;;;;;;;2EAW2E;AAC3E,wBAAgB,mBAAmB,IAAI,gBAAgB,CAStD;AAED,+DAA+D;AAC/D,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,gBAAgB,GAAG,IAAI,GAAG,IAAI,CAE9E"}
@@ -13,11 +13,21 @@
13
13
  *
14
14
  * ASCII-only.
15
15
  */
16
- import { randomBytes } from 'node:crypto';
16
+ import { createHash, randomBytes } from 'node:crypto';
17
17
  import * as os from 'node:os';
18
18
  let _identity = null;
19
19
  /** The identity for THIS process (created once, then cached). id =
20
- * "<hostname>-<6 hex>" so it is both unique and human-legible in logs. */
20
+ * "<hostname>-<6 hex>" so it is both unique and human-legible in logs.
21
+ *
22
+ * STABLE per (host, project dir) since 2026-09-03. It used to be
23
+ * randomBytes -> a brand-new id on EVERY process start, so each desktop
24
+ * restart orphaned a GHOST instance on the relay: its retained presence
25
+ * events lingered in the log and the phone (which replays them on reconnect)
26
+ * listed the dead instance as live -> duplicated projects in the picker and,
27
+ * worse, the phone would target a ghost id (no board switch, no chat reply).
28
+ * Deriving the suffix from the working directory -- and item 1 guarantees at
29
+ * most ONE live instance per project root -- means a restart REUSES the same
30
+ * id (replace, not accumulate) and the phone's saved pick survives it. */
21
31
  export function getInstanceIdentity() {
22
32
  if (_identity)
23
33
  return _identity;
@@ -26,7 +36,13 @@ export function getInstanceIdentity() {
26
36
  host = (os.hostname() || 'host').split('.')[0].slice(0, 24);
27
37
  }
28
38
  catch { /* keep default */ }
29
- const suffix = randomBytes(3).toString('hex');
39
+ let suffix;
40
+ try {
41
+ suffix = createHash('sha256').update(process.cwd()).digest('hex').slice(0, 6);
42
+ }
43
+ catch {
44
+ suffix = randomBytes(3).toString('hex');
45
+ }
30
46
  _identity = { id: host + '-' + suffix, hostname: host, pid: process.pid };
31
47
  return _identity;
32
48
  }
@@ -1 +1 @@
1
- {"version":3,"file":"instance_identity.js","sourceRoot":"","sources":["../../src/relay/instance_identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAU9B,IAAI,SAAS,GAA4B,IAAI,CAAC;AAE9C;2EAC2E;AAC3E,MAAM,UAAU,mBAAmB;IACjC,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IAChC,IAAI,IAAI,GAAG,MAAM,CAAC;IAClB,IAAI,CAAC;QAAC,IAAI,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;IAClG,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,SAAS,GAAG,EAAE,EAAE,EAAE,IAAI,GAAG,GAAG,GAAG,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1E,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,4BAA4B,CAAC,EAA2B;IACtE,SAAS,GAAG,EAAE,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"instance_identity.js","sourceRoot":"","sources":["../../src/relay/instance_identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAU9B,IAAI,SAAS,GAA4B,IAAI,CAAC;AAE9C;;;;;;;;;;;2EAW2E;AAC3E,MAAM,UAAU,mBAAmB;IACjC,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IAChC,IAAI,IAAI,GAAG,MAAM,CAAC;IAClB,IAAI,CAAC;QAAC,IAAI,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;IAClG,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QAAC,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAAC,CAAC;IACtF,MAAM,CAAC;QAAC,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAAC,CAAC;IAClD,SAAS,GAAG,EAAE,EAAE,EAAE,IAAI,GAAG,GAAG,GAAG,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1E,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,4BAA4B,CAAC,EAA2B;IACtE,SAAS,GAAG,EAAE,CAAC;AACjB,CAAC"}
package/dist/version.d.ts CHANGED
@@ -2,5 +2,5 @@
2
2
  * Yujin Forge CLI version. Kept in sync with package.json by the npm
3
3
  * "version" lifecycle (scripts/sync_version.mjs) so the two never drift.
4
4
  */
5
- export declare const VERSION = "1.2.2";
5
+ export declare const VERSION = "1.2.4";
6
6
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -2,5 +2,5 @@
2
2
  * Yujin Forge CLI version. Kept in sync with package.json by the npm
3
3
  * "version" lifecycle (scripts/sync_version.mjs) so the two never drift.
4
4
  */
5
- export const VERSION = '1.2.2';
5
+ export const VERSION = '1.2.4';
6
6
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nac3/forge-cli",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "description": "Yujin Forge -- voice-first NAC-3 React development framework. CLI + chat panel + spec ingest + 10-format document reader + voice loop.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Pablo Kuschnirof <pablo@rpaforce.com>",