@mindfoldhq/trellis 0.6.11 → 0.6.12

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,9 @@
1
+ {
2
+ "version": "0.6.12",
3
+ "description": "Pi session isolation for concurrent windows.",
4
+ "breaking": false,
5
+ "recommendMigrate": false,
6
+ "changelog": "**Bug Fixes:**\n- fix(pi): isolate each main window by native Pi session ID and prevent normalized key collisions",
7
+ "migrations": [],
8
+ "notes": "Upgrade to 0.6.12, then run trellis update to refresh the Pi extension. No --migrate required."
9
+ }
@@ -1,4 +1,4 @@
1
- import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
1
+ import { existsSync, readFileSync, statSync } from "node:fs";
2
2
  import { createHash, randomBytes } from "node:crypto";
3
3
  import {
4
4
  delimiter,
@@ -432,10 +432,13 @@ function exists(p: string) {
432
432
  function shellQuote(v: string) {
433
433
  return `'${v.replace(/'/g, `'\\''`)}'`;
434
434
  }
435
- function callStr(cb: (() => string | undefined) | undefined): string | null {
435
+ function callStr(
436
+ cb: (() => string | undefined) | undefined,
437
+ receiver?: unknown,
438
+ ): string | null {
436
439
  if (!cb) return null;
437
440
  try {
438
- return str(cb());
441
+ return str(cb.call(receiver));
439
442
  } catch {
440
443
  return null;
441
444
  }
@@ -1027,17 +1030,18 @@ function parseAgentFM(c: string): AgentConfig {
1027
1030
  }
1028
1031
 
1029
1032
  function contextKey(input?: unknown, ctx?: PiExtensionContext): string | null {
1030
- const ov = str(process.env.TRELLIS_CONTEXT_ID);
1031
- if (ov) return ov.replace(/[^A-Za-z0-9._-]+/g, "_").slice(0, 160) || hash(ov);
1032
1033
  const sessionId =
1033
- callStr(ctx?.sessionManager?.getSessionId) ??
1034
+ callStr(ctx?.sessionManager?.getSessionId, ctx?.sessionManager) ??
1034
1035
  str(process.env.PI_SESSION_ID) ??
1035
1036
  str(process.env.PI_SESSIONID) ??
1036
1037
  lookupStr(input, ["session_id", "sessionId", "sessionID"]);
1037
- if (sessionId)
1038
- return `pi_${sessionId.replace(/[^A-Za-z0-9._-]+/g, "_") || hash(sessionId)}`;
1038
+ if (sessionId) {
1039
+ const normalized = sessionId.replace(/[^A-Za-z0-9._-]+/g, "_");
1040
+ if (!normalized) return `pi_${hash(sessionId)}`;
1041
+ return `pi_${normalized}${normalized === sessionId ? "" : `_${hash(sessionId)}`}`;
1042
+ }
1039
1043
  const transcriptPath =
1040
- callStr(ctx?.sessionManager?.getSessionFile) ??
1044
+ callStr(ctx?.sessionManager?.getSessionFile, ctx?.sessionManager) ??
1041
1045
  lookupStr(input, ["transcript_path", "transcriptPath", "transcript"]);
1042
1046
  if (transcriptPath) return `pi_transcript_${hash(transcriptPath)}`;
1043
1047
  return null;
@@ -1063,32 +1067,6 @@ function readTaskDir(root: string, key: string | null): string | null {
1063
1067
  return null;
1064
1068
  }
1065
1069
  }
1066
- function sessionHasTask(root: string, key: string): boolean {
1067
- try {
1068
- const ctx = JSON.parse(
1069
- readText(join(root, ".trellis", ".runtime", "sessions", `${key}.json`)),
1070
- ) as JsonObject;
1071
- return !!str(ctx.current_task);
1072
- } catch {
1073
- return false;
1074
- }
1075
- }
1076
- function adoptKey(root: string, key: string): string {
1077
- if (sessionHasTask(root, key)) return key;
1078
- try {
1079
- const dir = join(root, ".trellis", ".runtime", "sessions");
1080
- const keys = readdirSync(dir)
1081
- .filter(
1082
- (f) => f.endsWith(".json") && sessionHasTask(root, f.slice(0, -5)),
1083
- )
1084
- .map((f) => f.slice(0, -5));
1085
- const proc = keys.filter((k) => k.startsWith("pi_process_"));
1086
- const cands = proc.length ? proc : keys;
1087
- return cands.length === 1 ? cands[0]! : key;
1088
- } catch {
1089
- return key;
1090
- }
1091
- }
1092
1070
 
1093
1071
  // ── Workflow State Breadcrumb ─────────────────────────────────────────
1094
1072
  const WF_RE =
@@ -1669,7 +1647,7 @@ export default function trellisExtension(pi: {
1669
1647
  let curKey: string | null = null;
1670
1648
 
1671
1649
  const getKey = (input?: unknown, ctx?: PiExtensionContext) => {
1672
- const k = adoptKey(root, contextKey(input, ctx) ?? curKey ?? procKey);
1650
+ const k = contextKey(input, ctx) ?? curKey ?? procKey;
1673
1651
  curKey = k;
1674
1652
  return k;
1675
1653
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindfoldhq/trellis",
3
- "version": "0.6.11",
3
+ "version": "0.6.12",
4
4
  "description": "AI capabilities grow like ivy — Trellis provides the structure to guide them along a disciplined path",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -34,7 +34,7 @@
34
34
  "inquirer": "^9.3.7",
35
35
  "undici": "^6.21.0",
36
36
  "zod": "^4.4.2",
37
- "@mindfoldhq/trellis-core": "0.6.11"
37
+ "@mindfoldhq/trellis-core": "0.6.12"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@eslint/js": "^9.18.0",