@hasna/instructions 0.5.5 → 0.5.6

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/dist/index.js CHANGED
@@ -200,6 +200,9 @@ function resolvePath(kind, options) {
200
200
  function configDir(options) {
201
201
  return resolvePath("config", options);
202
202
  }
203
+ function stateDir(options) {
204
+ return resolvePath("state", options);
205
+ }
203
206
 
204
207
  // src/lib/app-home.ts
205
208
  var HASNA_CONFIGS_HOME_ENV = "HASNA_CONFIGS_HOME";
@@ -849,9 +852,9 @@ import { createHash as createHash7 } from "crypto";
849
852
 
850
853
  // src/lib/session-render.ts
851
854
  import { createHash as createHash6 } from "crypto";
852
- import { existsSync as existsSync6, readFileSync as readFileSync4, realpathSync as realpathSync2, statSync as statSync3 } from "fs";
853
- import { homedir as homedir6 } from "os";
854
- import { basename as basename4, dirname as dirname3, extname as extname2, isAbsolute as isAbsolute3, join as join8, parse as parse2, posix as posix2, relative as relative2, resolve as resolve7 } from "path";
855
+ import { existsSync as existsSync7, readFileSync as readFileSync4, realpathSync as realpathSync2, statSync as statSync3 } from "fs";
856
+ import { homedir as homedir7 } from "os";
857
+ import { basename as basename4, dirname as dirname4, extname as extname2, isAbsolute as isAbsolute3, join as join9, parse as parse2, posix as posix2, relative as relative2, resolve as resolve8 } from "path";
855
858
 
856
859
  // src/lib/global-agent-rules-standard.ts
857
860
  import { createHash } from "crypto";
@@ -1164,7 +1167,7 @@ import { dlopen, FFIType } from "bun:ffi";
1164
1167
  import {
1165
1168
  closeSync,
1166
1169
  constants,
1167
- existsSync as existsSync4,
1170
+ existsSync as existsSync5,
1168
1171
  fstatSync,
1169
1172
  fsyncSync,
1170
1173
  lstatSync,
@@ -1177,7 +1180,7 @@ import {
1177
1180
  statSync,
1178
1181
  writeFileSync
1179
1182
  } from "fs";
1180
- import { basename, dirname, isAbsolute, join as join5, parse, relative, resolve as resolve3 } from "path";
1183
+ import { basename, dirname as dirname2, isAbsolute, join as join6, parse, relative, resolve as resolve4 } from "path";
1181
1184
 
1182
1185
  // ../../node_modules/.bun/zod@3.25.76/node_modules/zod/v3/external.js
1183
1186
  var exports_external = {};
@@ -5370,6 +5373,52 @@ var SESSION_INSTRUCTION_LAYERS = [
5370
5373
  "local"
5371
5374
  ];
5372
5375
 
5376
+ // src/lib/session-render-state.ts
5377
+ import { existsSync as existsSync4, readdirSync } from "fs";
5378
+ import { homedir as homedir4 } from "os";
5379
+ import { dirname, join as join5, resolve as resolve3 } from "path";
5380
+ var SESSION_RENDER_STATE_APP = "instructions";
5381
+ function homeDir2(env = process.env) {
5382
+ return env["HOME"] || env["USERPROFILE"] || homedir4();
5383
+ }
5384
+ function legacySnapshotDir(targetHome) {
5385
+ return resolve3(join5(targetHome, ".hasna", "session-render-snapshots"));
5386
+ }
5387
+ function resolverSnapshotDir(env = process.env) {
5388
+ const override = env.HASNA_STATE_HOME;
5389
+ if (typeof override === "string" && override.trim().length > 0 && !existsSync4(override)) {
5390
+ return stateDir({
5391
+ app: SESSION_RENDER_STATE_APP,
5392
+ env: { ...env, HASNA_STATE_HOME: undefined },
5393
+ home: homeDir2(env)
5394
+ });
5395
+ }
5396
+ return stateDir({ app: SESSION_RENDER_STATE_APP, env, home: homeDir2(env) });
5397
+ }
5398
+ function adoptResolverSnapshotDir(resolved, env = process.env) {
5399
+ const override = env.HASNA_STATE_HOME;
5400
+ if (typeof override === "string" && override.trim().length > 0 && existsSync4(override)) {
5401
+ return true;
5402
+ }
5403
+ if (!existsSync4(resolved))
5404
+ return false;
5405
+ return readdirSync(resolved).some((name) => name.endsWith(".json"));
5406
+ }
5407
+ function resolveSessionRenderSnapshotLocation(targetHome, env = process.env) {
5408
+ const resolved = resolverSnapshotDir(env);
5409
+ if (!adoptResolverSnapshotDir(resolved, env)) {
5410
+ return { dir: legacySnapshotDir(targetHome), workspaceRoot: targetHome, adopted: false };
5411
+ }
5412
+ const resolvedPath = resolve3(resolved);
5413
+ return { dir: resolvedPath, workspaceRoot: dirname(resolvedPath), adopted: true };
5414
+ }
5415
+ function getSessionRenderSnapshotDir(targetHome, env = process.env) {
5416
+ return resolveSessionRenderSnapshotLocation(targetHome, env).dir;
5417
+ }
5418
+ function sessionRenderSnapshotWorkspaceRoot(targetHome, env = process.env) {
5419
+ return resolveSessionRenderSnapshotLocation(targetHome, env).workspaceRoot;
5420
+ }
5421
+
5373
5422
  // src/lib/project-context.ts
5374
5423
  var PROJECT_CONTEXT_SCHEMA = "hasna.projects.project_context_bundle.v1";
5375
5424
  var PROJECT_CONTEXT_SCHEMA_V2 = "hasna.projects.project_context_bundle.v2";
@@ -5673,7 +5722,7 @@ function planProjectContext(input) {
5673
5722
  const inlineMarkerOverhead = nativeImports ? 0 : Buffer.byteLength(buildManagedBlock(bundle, "", `
5674
5723
  `), "utf8");
5675
5724
  const generated = buildCanonicalFragment(bundle, status, ageSeconds, PROJECT_CONTEXT_MAX_RENDERED_BYTES - Math.max(320, inlineMarkerOverhead), PROJECT_CONTEXT_MAX_APPROX_TOKENS - Math.max(80, Math.ceil(inlineMarkerOverhead / 4)));
5676
- const previousTargetContent = existsSync4(paths.target) ? readUtf8RegularFile(paths.target, workspaceRoot, managedObservationMaxBytes(relativePosix(workspaceRoot, paths.target))) : null;
5725
+ const previousTargetContent = existsSync5(paths.target) ? readUtf8RegularFile(paths.target, workspaceRoot, managedObservationMaxBytes(relativePosix(workspaceRoot, paths.target))) : null;
5677
5726
  const markerParse = parseManagedBlock(previousTargetContent ?? "", input.force === true);
5678
5727
  if (markerParse.block && markerParse.block.id !== bundle.project.id) {
5679
5728
  throw new ProjectContextError("MANAGED_BLOCK_CONFLICT", "managed block belongs to a different project");
@@ -5724,7 +5773,7 @@ function composeProjectContextSessionRender(input) {
5724
5773
  return null;
5725
5774
  const { runtime, workspace_root: workspaceRoot, observed_hashes: observedHashes } = guard;
5726
5775
  const paths = runtimePaths(workspaceRoot, runtime);
5727
- if (!existsSync4(paths.manifest))
5776
+ if (!existsSync5(paths.manifest))
5728
5777
  return null;
5729
5778
  assertCodewithTargetIsConsumed(workspaceRoot, runtime);
5730
5779
  const manifest = readProjectContextManifest(paths.manifest, workspaceRoot);
@@ -5753,7 +5802,7 @@ function composeProjectContextSessionRender(input) {
5753
5802
  }
5754
5803
  const fragment = readUtf8RegularFile(paths.fragment, workspaceRoot, PROJECT_CONTEXT_MAX_RENDERED_BYTES);
5755
5804
  scanGeneratedContent(fragment);
5756
- if (!existsSync4(paths.target)) {
5805
+ if (!existsSync5(paths.target)) {
5757
5806
  throw new ProjectContextError("MANAGED_BLOCK_CONFLICT", "project-context provider target is missing while durable context is active");
5758
5807
  }
5759
5808
  const currentTarget = readUtf8RegularFile(paths.target, workspaceRoot, managedObservationMaxBytes(relativePosix(workspaceRoot, paths.target)));
@@ -5764,7 +5813,7 @@ function composeProjectContextSessionRender(input) {
5764
5813
  if (currentMarkers.block.id !== cache.project_id || currentMarkers.block.revision !== cache.revision || currentMarkers.block.hash !== cache.hash) {
5765
5814
  throw new ProjectContextError("MANAGED_BLOCK_CONFLICT", "project-context provider markers differ from the durable cache");
5766
5815
  }
5767
- const plannedIndexes = input.files.filter((file) => file.role === "index" && resolve3(file.path) === paths.target);
5816
+ const plannedIndexes = input.files.filter((file) => file.role === "index" && resolve4(file.path) === paths.target);
5768
5817
  if (plannedIndexes.length !== 1) {
5769
5818
  throw new ProjectContextError("PROJECT_CONTEXT_MANIFEST_INVALID", "session renderer does not own the selected project-context provider target");
5770
5819
  }
@@ -5822,7 +5871,7 @@ function withProjectContextSessionGuard(guard, action, options = {}) {
5822
5871
  verify();
5823
5872
  return action(null);
5824
5873
  }
5825
- const lockPath = resolve3(validated.workspace_root, ...PROJECT_CONTEXT_LOCK_PATH.split("/"));
5874
+ const lockPath = resolve4(validated.workspace_root, ...PROJECT_CONTEXT_LOCK_PATH.split("/"));
5826
5875
  const lock = acquireWorkspaceLock(validated.workspace_root, lockPath);
5827
5876
  try {
5828
5877
  verify();
@@ -5848,7 +5897,7 @@ function validateProjectContextSessionGuard(guard) {
5848
5897
  if (!isRecord(observed) || typeof observed.path !== "string") {
5849
5898
  throw new ProjectContextError("PROJECT_CONTEXT_SESSION_STALE", "session project-context guard contains malformed hash metadata");
5850
5899
  }
5851
- const path = resolve3(observed.path);
5900
+ const path = resolve4(observed.path);
5852
5901
  if (!allowedPaths.has(path) || observedPaths.has(path)) {
5853
5902
  throw new ProjectContextError("PROJECT_CONTEXT_SESSION_STALE", "session project-context guard contains an unexpected or duplicate path");
5854
5903
  }
@@ -5870,7 +5919,7 @@ function validateProjectContextSessionGuard(guard) {
5870
5919
  function applyProjectContext(options) {
5871
5920
  const workspaceRoot = assertSafeWorkspaceRoot(options.workspace_root);
5872
5921
  const now2 = options.now ?? new Date;
5873
- const lockPath = resolve3(workspaceRoot, ...PROJECT_CONTEXT_LOCK_PATH.split("/"));
5922
+ const lockPath = resolve4(workspaceRoot, ...PROJECT_CONTEXT_LOCK_PATH.split("/"));
5874
5923
  const lock = options.dry_run ? null : acquireWorkspaceLock(workspaceRoot, lockPath, options.test_hooks?.after_lock_open, options.test_hooks?.before_stale_lock_remove, options.test_hooks?.process_start_identity);
5875
5924
  try {
5876
5925
  const resolved = resolveBundleForApply(options, workspaceRoot, now2);
@@ -6017,7 +6066,7 @@ function resolveBundleForApply(options, workspaceRoot, now2) {
6017
6066
  if (!options.expected_project_id) {
6018
6067
  throw new ProjectContextError("PROJECT_CONTEXT_CACHE_ID_REQUIRED", "expected_project_id is required for stale-cache fallback");
6019
6068
  }
6020
- const cachePath = resolve3(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/"));
6069
+ const cachePath = resolve4(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/"));
6021
6070
  const cache = readProjectContextCache(cachePath, workspaceRoot);
6022
6071
  if (!cache)
6023
6072
  throw new ProjectContextError("PROJECT_CONTEXT_CACHE_MISSING", "no last-known-good project context cache exists");
@@ -6219,7 +6268,7 @@ function findLegacyCodewithWorkspaceSection(workspaceRoot, runtime, content, bun
6219
6268
  if (runtime !== "codewith" || !content)
6220
6269
  return null;
6221
6270
  const sessionManifestPath = runtimePaths(workspaceRoot, runtime).sessionManifest;
6222
- if (!existsSync4(sessionManifestPath))
6271
+ if (!existsSync5(sessionManifestPath))
6223
6272
  return null;
6224
6273
  const manifest = readSessionManifestRecord(sessionManifestPath, workspaceRoot);
6225
6274
  if (!manifest || manifest["schema"] !== SESSION_RENDER_SCHEMA) {
@@ -6270,7 +6319,7 @@ function assertRevisionOrdering(plan, force) {
6270
6319
  const manifest = readProjectContextManifest(plan.manifest_path, plan.workspace_root);
6271
6320
  if (manifest) {
6272
6321
  const manifestHashHasRecoveryProof = manifest.projectContext.hash === plan.bundle.hash || metadataSnapshotMatchesManifest(plan, manifest);
6273
- const canonicalStateAlreadyInstalled = cache !== null && canonicalCacheHash === plan.bundle.hash && cache.project_id === plan.bundle.project.id && cache.revision === plan.bundle.revision && plan.marker !== null && plan.marker.id === plan.bundle.project.id && plan.marker.revision === plan.bundle.revision && plan.marker.hash === plan.bundle.hash && existsSync4(plan.fragment_path) && fragmentMatchesBundle(plan.fragment_path, plan.bundle, plan.workspace_root) && manifestHashHasRecoveryProof;
6322
+ const canonicalStateAlreadyInstalled = cache !== null && canonicalCacheHash === plan.bundle.hash && cache.project_id === plan.bundle.project.id && cache.revision === plan.bundle.revision && plan.marker !== null && plan.marker.id === plan.bundle.project.id && plan.marker.revision === plan.bundle.revision && plan.marker.hash === plan.bundle.hash && existsSync5(plan.fragment_path) && fragmentMatchesBundle(plan.fragment_path, plan.bundle, plan.workspace_root) && manifestHashHasRecoveryProof;
6274
6323
  observations.push({
6275
6324
  source: "manifest",
6276
6325
  id: manifest.projectContext.projectId,
@@ -6278,7 +6327,7 @@ function assertRevisionOrdering(plan, force) {
6278
6327
  hash: canonicalStateAlreadyInstalled && manifest.projectContext.projectId === plan.bundle.project.id && manifest.projectContext.revision === plan.bundle.revision ? plan.bundle.hash : normalizePersistedHash(manifest.projectContext.revision, manifest.projectContext.hash)
6279
6328
  });
6280
6329
  const fragmentEntry = manifest.files.find((file) => file.relativePath === PROJECT_CONTEXT_FRAGMENT_PATH);
6281
- if (fragmentEntry && existsSync4(plan.fragment_path)) {
6330
+ if (fragmentEntry && existsSync5(plan.fragment_path)) {
6282
6331
  const actual = currentFileHash(plan.fragment_path, plan.workspace_root);
6283
6332
  if (actual !== fragmentEntry.sha256 && !fragmentMatchesBundle(plan.fragment_path, plan.bundle, plan.workspace_root) && !force) {
6284
6333
  throw new ProjectContextError("MANAGED_BLOCK_CONFLICT", "canonical project-context fragment changed outside Instructions");
@@ -6373,9 +6422,9 @@ function buildManifest(plan, now2) {
6373
6422
  function buildSessionCompatibilityManifest(plan, now2) {
6374
6423
  const paths = runtimePaths(plan.workspace_root, plan.runtime);
6375
6424
  const tool = manifestTool(plan.runtime);
6376
- const targetHome = plan.runtime === "codewith" ? resolve3(plan.workspace_root, ".codewith") : plan.workspace_root;
6425
+ const targetHome = plan.runtime === "codewith" ? resolve4(plan.workspace_root, ".codewith") : plan.workspace_root;
6377
6426
  const targetRelativePath = sessionTargetRelativePath(plan.runtime);
6378
- const existing = existsSync4(paths.sessionManifest) ? readSessionManifestRecord(paths.sessionManifest, plan.workspace_root) : {
6427
+ const existing = existsSync5(paths.sessionManifest) ? readSessionManifestRecord(paths.sessionManifest, plan.workspace_root) : {
6379
6428
  schema: SESSION_RENDER_SCHEMA,
6380
6429
  tool,
6381
6430
  adapterMode: plan.native_imports ? "native-imports" : "flattened-markdown",
@@ -6395,7 +6444,7 @@ function buildSessionCompatibilityManifest(plan, now2) {
6395
6444
  throw new ProjectContextError("PROJECT_CONTEXT_MANIFEST_INVALID", "provider session manifest is malformed or incompatible");
6396
6445
  }
6397
6446
  const existingTargetHome = safeLegacyMetadataString(existing["targetHome"], null);
6398
- if (existingTargetHome !== null && resolve3(existingTargetHome) !== targetHome) {
6447
+ if (existingTargetHome !== null && resolve4(existingTargetHome) !== targetHome) {
6399
6448
  throw new ProjectContextError("PROJECT_CONTEXT_MANIFEST_INVALID", "provider session manifest targets a different workspace");
6400
6449
  }
6401
6450
  const sources = sanitizeLegacySources(existing["sources"]).filter((source) => source["id"] !== "project-context-bundle");
@@ -6681,9 +6730,9 @@ function writeMetadataSnapshot(plan, now2) {
6681
6730
  const previous = readProjectContextManifest(plan.manifest_path, plan.workspace_root);
6682
6731
  if (!previous || previous.projectContext.revision === plan.bundle.revision && previous.projectContext.hash === plan.bundle.hash)
6683
6732
  return null;
6684
- const snapshotDir = resolve3(plan.workspace_root, ...PROJECT_CONTEXT_SNAPSHOT_DIR.split("/"));
6733
+ const snapshotDir = resolve4(plan.workspace_root, ...PROJECT_CONTEXT_SNAPSHOT_DIR.split("/"));
6685
6734
  ensureSafeDirectory(snapshotDir, plan.workspace_root, 448);
6686
- const snapshotPath = resolve3(snapshotDir, `${safeFilename(previous.projectContext.revision)}-${previous.projectContext.hash.slice(-12)}.json`);
6735
+ const snapshotPath = resolve4(snapshotDir, `${safeFilename(previous.projectContext.revision)}-${previous.projectContext.hash.slice(-12)}.json`);
6687
6736
  const snapshot = {
6688
6737
  schema: "hasna.configs.session-render-snapshot/v1",
6689
6738
  kind: "project-context-metadata",
@@ -6699,9 +6748,9 @@ function writeMetadataSnapshot(plan, now2) {
6699
6748
  return snapshotPath;
6700
6749
  }
6701
6750
  function metadataSnapshotMatchesManifest(plan, manifest) {
6702
- const snapshotDir = resolve3(plan.workspace_root, ...PROJECT_CONTEXT_SNAPSHOT_DIR.split("/"));
6703
- const snapshotPath = resolve3(snapshotDir, `${safeFilename(manifest.projectContext.revision)}-${manifest.projectContext.hash.slice(-12)}.json`);
6704
- if (!existsSync4(snapshotPath))
6751
+ const snapshotDir = resolve4(plan.workspace_root, ...PROJECT_CONTEXT_SNAPSHOT_DIR.split("/"));
6752
+ const snapshotPath = resolve4(snapshotDir, `${safeFilename(manifest.projectContext.revision)}-${manifest.projectContext.hash.slice(-12)}.json`);
6753
+ if (!existsSync5(snapshotPath))
6705
6754
  return false;
6706
6755
  const record = readJsonRecord(snapshotPath, plan.workspace_root);
6707
6756
  const result = projectContextMetadataSnapshotSchema.safeParse(record);
@@ -6749,10 +6798,11 @@ function writeProjectContextRollbackSnapshot(plan, now2, outputs) {
6749
6798
  sha256: nextHash
6750
6799
  };
6751
6800
  });
6752
- const snapshotDir = resolve3(plan.workspace_root, ...SESSION_RENDER_SNAPSHOT_RELATIVE_DIR.split("/"));
6753
- ensureSafeDirectory(snapshotDir, plan.workspace_root, 448);
6801
+ const snapshotWorkspaceRoot = sessionRenderSnapshotWorkspaceRoot(plan.workspace_root);
6802
+ const snapshotDir = getSessionRenderSnapshotDir(plan.workspace_root);
6803
+ ensureSafeDirectory(snapshotDir, snapshotWorkspaceRoot, 448);
6754
6804
  const timestamp = now2.toISOString().replace(/[:.]/g, "-");
6755
- const snapshotPath = resolve3(snapshotDir, `${timestamp}-${randomUUID2()}.json`);
6805
+ const snapshotPath = resolve4(snapshotDir, `${timestamp}-${randomUUID2()}.json`);
6756
6806
  const snapshot = {
6757
6807
  schema: "hasna.configs.session-render-snapshot/v2",
6758
6808
  createdAt: now2.toISOString(),
@@ -6766,11 +6816,11 @@ function writeProjectContextRollbackSnapshot(plan, now2, outputs) {
6766
6816
  afterFiles
6767
6817
  };
6768
6818
  atomicWriteFile(snapshotPath, `${JSON.stringify(snapshot, null, 2)}
6769
- `, plan.workspace_root, 384, null);
6819
+ `, snapshotWorkspaceRoot, 384, null);
6770
6820
  return snapshotPath;
6771
6821
  }
6772
6822
  function readProjectContextManifest(path, workspaceRoot) {
6773
- if (!existsSync4(path))
6823
+ if (!existsSync5(path))
6774
6824
  return null;
6775
6825
  const record = readJsonRecord(path, workspaceRoot);
6776
6826
  const result = storedManifestObservationSchema.safeParse(record);
@@ -6785,7 +6835,7 @@ function readProjectContextManifest(path, workspaceRoot) {
6785
6835
  };
6786
6836
  }
6787
6837
  function readProjectContextCache(path, workspaceRoot) {
6788
- if (!existsSync4(path))
6838
+ if (!existsSync5(path))
6789
6839
  return null;
6790
6840
  const record = readJsonRecord(path, workspaceRoot);
6791
6841
  const result = projectContextCacheSchema.safeParse(record);
@@ -6817,7 +6867,7 @@ function readSessionManifestRecord(path, workspaceRoot) {
6817
6867
  }
6818
6868
  }
6819
6869
  function atomicWriteFile(path, content, workspaceRoot, defaultMode, expectedHash, afterExchange, atomicExchangeUnavailable = false, beforeInstall, portableCreateOnly = false, maxObservedBytes, allowPortableReplacement = false) {
6820
- const dir = resolve3(path, "..");
6870
+ const dir = resolve4(path, "..");
6821
6871
  ensureSafeDirectory(dir, workspaceRoot, 448);
6822
6872
  assertNoSymlinkSegments(workspaceRoot, path);
6823
6873
  const anchoredOps = portableCreateOnly ? null : resolveAnchoredFsOps();
@@ -6834,7 +6884,7 @@ function atomicWriteFile(path, content, workspaceRoot, defaultMode, expectedHash
6834
6884
  const previous = anchoredFileObservation(directory, targetName);
6835
6885
  const previousMode = previous?.mode ?? defaultMode;
6836
6886
  const tempName = `.project-context-${randomUUID2()}.tmp`;
6837
- const tempPath = join5(dir, tempName);
6887
+ const tempPath = join6(dir, tempName);
6838
6888
  let fd = null;
6839
6889
  let preserveTemp = false;
6840
6890
  let directoryChanged = false;
@@ -6963,9 +7013,9 @@ function atomicWritePortable(path, content, workspaceRoot, defaultMode, expected
6963
7013
  if (currentHash !== null) {
6964
7014
  throw new ProjectContextHashRace(`managed path appeared before portable creation: ${relativePosix(workspaceRoot, path)}`);
6965
7015
  }
6966
- const dir = dirname(path);
7016
+ const dir = dirname2(path);
6967
7017
  const directoryIdentity = captureManagedDirectoryIdentity(dir, workspaceRoot);
6968
- const tempPath = join5(dir, `.project-context-${randomUUID2()}.tmp`);
7018
+ const tempPath = join6(dir, `.project-context-${randomUUID2()}.tmp`);
6969
7019
  let fd = null;
6970
7020
  let tempIdentity = null;
6971
7021
  try {
@@ -7020,9 +7070,9 @@ function atomicWritePortableReplacement(path, content, workspaceRoot, expectedHa
7020
7070
  if (current.isSymbolicLink() || !current.isFile()) {
7021
7071
  throw new ProjectContextHashRace(`managed path is not a regular file: ${relativePosix(workspaceRoot, path)}`);
7022
7072
  }
7023
- const dir = dirname(path);
7073
+ const dir = dirname2(path);
7024
7074
  const directoryIdentity = captureManagedDirectoryIdentity(dir, workspaceRoot);
7025
- const tempPath = join5(dir, `.project-context-${randomUUID2()}.tmp`);
7075
+ const tempPath = join6(dir, `.project-context-${randomUUID2()}.tmp`);
7026
7076
  const desiredHash = sha2562(content);
7027
7077
  let fd = null;
7028
7078
  let tempIdentity = null;
@@ -7079,7 +7129,7 @@ function portablePreparedHash(tempPath, path, workspaceRoot, maxObservedBytes, s
7079
7129
  function portableFileHash(path, workspaceRoot, maxObservedBytes) {
7080
7130
  if (maxObservedBytes === undefined)
7081
7131
  return currentFileHash(path, workspaceRoot);
7082
- if (!existsSync4(path))
7132
+ if (!existsSync5(path))
7083
7133
  return null;
7084
7134
  assertNoSymlinkSegments(workspaceRoot, path);
7085
7135
  const stat = lstatSync(path);
@@ -7091,13 +7141,13 @@ function portableFileHash(path, workspaceRoot, maxObservedBytes) {
7091
7141
  return createHash2("sha256").update(readFileSync(path)).digest("hex");
7092
7142
  }
7093
7143
  function writeProjectContextCoordinatedFile(input) {
7094
- atomicWriteFile(resolve3(input.path), input.content, assertSafeWorkspaceRoot(input.workspace_root), input.default_mode ?? 420, input.expected_hash, undefined, false, input.test_hooks?.before_install, input.force_portable_file_ops ?? false, input.max_observed_bytes, input.allow_portable_replacement ?? false);
7144
+ atomicWriteFile(resolve4(input.path), input.content, assertSafeWorkspaceRoot(input.workspace_root), input.default_mode ?? 420, input.expected_hash, undefined, false, input.test_hooks?.before_install, input.force_portable_file_ops ?? false, input.max_observed_bytes, input.allow_portable_replacement ?? false);
7095
7145
  }
7096
7146
  function removeProjectContextCoordinatedFile(input) {
7097
7147
  const workspaceRoot = assertSafeWorkspaceRoot(input.workspace_root);
7098
- const path = resolve3(input.path);
7148
+ const path = resolve4(input.path);
7099
7149
  assertNoSymlinkSegments(workspaceRoot, path);
7100
- const dir = dirname(path);
7150
+ const dir = dirname2(path);
7101
7151
  const anchoredOps = input.force_portable_file_ops ? null : resolveAnchoredFsOps();
7102
7152
  if (!anchoredOps) {
7103
7153
  if (!input.allow_portable_removal) {
@@ -7121,7 +7171,7 @@ function removeProjectContextCoordinatedFile(input) {
7121
7171
  throw new ProjectContextHashRace(`managed path changed during deletion: ${relativePosix(workspaceRoot, path)}`);
7122
7172
  }
7123
7173
  displaced = true;
7124
- input.test_hooks?.after_displace?.(join5(dir, displacedName));
7174
+ input.test_hooks?.after_displace?.(join6(dir, displacedName));
7125
7175
  const moved = anchoredFileObservation(directory, displacedName);
7126
7176
  if (!moved || moved.dev !== observed.dev || moved.ino !== observed.ino || moved.hash !== input.expected_hash || anchoredFileObservation(directory, targetName) !== null) {
7127
7177
  throw new ProjectContextHashRace(`managed path changed during deletion validation: ${relativePosix(workspaceRoot, path)}`);
@@ -7165,9 +7215,9 @@ function removePortableCoordinatedFile(path, workspaceRoot, expectedHash, maxObs
7165
7215
  if (observed.isSymbolicLink() || !observed.isFile()) {
7166
7216
  throw new ProjectContextHashRace(`managed path is not a regular file: ${relativePosix(workspaceRoot, path)}`);
7167
7217
  }
7168
- const dir = dirname(path);
7218
+ const dir = dirname2(path);
7169
7219
  const directoryIdentity = captureManagedDirectoryIdentity(dir, workspaceRoot);
7170
- const displacedPath = join5(dir, `.project-context-delete-${randomUUID2()}.tmp`);
7220
+ const displacedPath = join6(dir, `.project-context-delete-${randomUUID2()}.tmp`);
7171
7221
  let displaced = false;
7172
7222
  try {
7173
7223
  assertManagedDirectoryStable(dir, workspaceRoot, directoryIdentity);
@@ -7178,7 +7228,7 @@ function removePortableCoordinatedFile(path, workspaceRoot, expectedHash, maxObs
7178
7228
  displaced = true;
7179
7229
  afterDisplace?.(displacedPath);
7180
7230
  const moved = lstatSync(displacedPath);
7181
- if (moved.isSymbolicLink() || !moved.isFile() || moved.dev !== observed.dev || moved.ino !== observed.ino || portableFileHash(displacedPath, workspaceRoot, maxObservedBytes) !== expectedHash || existsSync4(path)) {
7231
+ if (moved.isSymbolicLink() || !moved.isFile() || moved.dev !== observed.dev || moved.ino !== observed.ino || portableFileHash(displacedPath, workspaceRoot, maxObservedBytes) !== expectedHash || existsSync5(path)) {
7182
7232
  throw new ProjectContextHashRace(`managed path changed during portable deletion: ${relativePosix(workspaceRoot, path)}`);
7183
7233
  }
7184
7234
  rmSync2(displacedPath);
@@ -7204,7 +7254,7 @@ function restorePortableDisplacedFile(displacedPath, path, workspaceRoot, expect
7204
7254
  if (displaced.isSymbolicLink() || installed.isSymbolicLink() || !displaced.isFile() || !installed.isFile() || displaced.dev !== expected.dev || displaced.ino !== expected.ino || displaced.dev !== installed.dev || displaced.ino !== installed.ino || portableFileHash(displacedPath, workspaceRoot, maxObservedBytes) !== expectedHash || portableFileHash(path, workspaceRoot, maxObservedBytes) !== expectedHash)
7205
7255
  return false;
7206
7256
  rmSync2(displacedPath);
7207
- fsyncDirectory(dirname(path));
7257
+ fsyncDirectory(dirname2(path));
7208
7258
  return true;
7209
7259
  } catch {
7210
7260
  return false;
@@ -7239,7 +7289,7 @@ function anchoredOpenExclusive(directory, name, mode) {
7239
7289
  const requestedMode = mode & 4095;
7240
7290
  let fd;
7241
7291
  try {
7242
- fd = openSync(join5(directory.path, name), constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, requestedMode);
7292
+ fd = openSync(join6(directory.path, name), constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, requestedMode);
7243
7293
  } catch {
7244
7294
  throw new ProjectContextHashRace(`could not create prepared managed file in ${relativePosix(directory.workspaceRoot, directory.path)}`);
7245
7295
  }
@@ -7282,7 +7332,7 @@ function anchoredFileObservation(directory, name) {
7282
7332
  const stat = fstatSync(fd);
7283
7333
  if (!stat.isFile())
7284
7334
  throw new ProjectContextHashRace("managed output is not a regular file");
7285
- const relativePath = relativePosix(directory.workspaceRoot, join5(directory.path, name));
7335
+ const relativePath = relativePosix(directory.workspaceRoot, join6(directory.path, name));
7286
7336
  const maxBytes = directory.maxObservedBytes === undefined ? managedObservationMaxBytes(relativePath) : directory.maxObservedBytes;
7287
7337
  if (maxBytes !== null && stat.size > maxBytes) {
7288
7338
  throw new ProjectContextHashRace(`managed output exceeds the safe read limit: ${relativePath}`);
@@ -7308,7 +7358,7 @@ function anchoredPreparedObservation(directory, name, path, stage) {
7308
7358
  return observed;
7309
7359
  }
7310
7360
  function captureManagedDirectoryIdentity(path, workspaceRoot) {
7311
- assertNoSymlinkSegments(workspaceRoot, join5(path, ".project-context-directory-guard"));
7361
+ assertNoSymlinkSegments(workspaceRoot, join6(path, ".project-context-directory-guard"));
7312
7362
  let stat;
7313
7363
  try {
7314
7364
  stat = lstatSync(path);
@@ -7321,7 +7371,7 @@ function captureManagedDirectoryIdentity(path, workspaceRoot) {
7321
7371
  return { dev: stat.dev, ino: stat.ino };
7322
7372
  }
7323
7373
  function assertManagedDirectoryStable(path, workspaceRoot, expected) {
7324
- assertNoSymlinkSegments(workspaceRoot, join5(path, ".project-context-directory-guard"));
7374
+ assertNoSymlinkSegments(workspaceRoot, join6(path, ".project-context-directory-guard"));
7325
7375
  let current;
7326
7376
  try {
7327
7377
  current = lstatSync(path);
@@ -7456,10 +7506,10 @@ function resolveAnchoredFsOps() {
7456
7506
  return null;
7457
7507
  }
7458
7508
  function acquireWorkspaceLock(workspaceRoot, lockPath, afterOpen, beforeStaleRemove, processStartIdentityLookup = processStartIdentity) {
7459
- const lockDirectory = resolve3(lockPath, "..");
7509
+ const lockDirectory = resolve4(lockPath, "..");
7460
7510
  ensureSafeDirectory(lockDirectory, workspaceRoot, 448);
7461
7511
  assertNoSymlinkSegments(workspaceRoot, lockPath);
7462
- const tempPath = join5(lockDirectory, `.project-context-lock-${randomUUID2()}.tmp`);
7512
+ const tempPath = join6(lockDirectory, `.project-context-lock-${randomUUID2()}.tmp`);
7463
7513
  let fd = null;
7464
7514
  let openedIdentity = null;
7465
7515
  let openedContentHash = null;
@@ -7493,7 +7543,7 @@ function acquireWorkspaceLock(workspaceRoot, lockPath, afterOpen, beforeStaleRem
7493
7543
  linked = true;
7494
7544
  }
7495
7545
  fsyncDirectory(lockDirectory);
7496
- if (existsSync4(tempPath)) {
7546
+ if (existsSync5(tempPath)) {
7497
7547
  rmSync2(tempPath);
7498
7548
  fsyncDirectory(lockDirectory);
7499
7549
  }
@@ -7508,7 +7558,7 @@ function acquireWorkspaceLock(workspaceRoot, lockPath, afterOpen, beforeStaleRem
7508
7558
  if (linked && openedIdentity && openedContentHash) {
7509
7559
  removeOwnedLockByInode(lockPath, openedIdentity, openedContentHash);
7510
7560
  }
7511
- if (!preserveTemp && existsSync4(tempPath)) {
7561
+ if (!preserveTemp && existsSync5(tempPath)) {
7512
7562
  try {
7513
7563
  rmSync2(tempPath);
7514
7564
  } catch {}
@@ -7523,7 +7573,7 @@ function acquireWorkspaceLock(workspaceRoot, lockPath, afterOpen, beforeStaleRem
7523
7573
  }
7524
7574
  function removeOwnedLockByInode(lockPath, identity, expectedHash) {
7525
7575
  try {
7526
- if (!existsSync4(lockPath))
7576
+ if (!existsSync5(lockPath))
7527
7577
  return;
7528
7578
  const current = lstatSync(lockPath);
7529
7579
  if (current.isSymbolicLink() || current.dev !== identity.dev || current.ino !== identity.ino)
@@ -7531,7 +7581,7 @@ function removeOwnedLockByInode(lockPath, identity, expectedHash) {
7531
7581
  if (expectedHash !== undefined && sha2562(readFileSync(lockPath, "utf8")) !== expectedHash)
7532
7582
  return;
7533
7583
  rmSync2(lockPath);
7534
- fsyncDirectory(resolve3(lockPath, ".."));
7584
+ fsyncDirectory(resolve4(lockPath, ".."));
7535
7585
  } catch {}
7536
7586
  }
7537
7587
  function observeStaleWorkspaceLock(lockPath, workspaceRoot, processStartIdentityLookup = processStartIdentity) {
@@ -7602,7 +7652,7 @@ function tryTakeoverStaleWorkspaceLock(candidatePath, lockPath, workspaceRoot, c
7602
7652
  const candidateInstalled = !current.isSymbolicLink() && current.dev === candidateIdentity.dev && current.ino === candidateIdentity.ino && currentFileHash(lockPath, workspaceRoot) === candidateHash;
7603
7653
  const staleDisplaced = !displaced.isSymbolicLink() && displaced.dev === stale.identity.dev && displaced.ino === stale.identity.ino && currentFileHash(candidatePath, workspaceRoot) === stale.contentHash;
7604
7654
  if (!candidateInstalled || !staleDisplaced) {
7605
- if (candidateInstalled && existsSync4(candidatePath)) {
7655
+ if (candidateInstalled && existsSync5(candidatePath)) {
7606
7656
  atomicExchangePaths(candidatePath, lockPath);
7607
7657
  exchanged = false;
7608
7658
  return false;
@@ -7610,13 +7660,13 @@ function tryTakeoverStaleWorkspaceLock(candidatePath, lockPath, workspaceRoot, c
7610
7660
  throw new ProjectContextError("PROJECT_CONTEXT_LOCK_LOST", "workspace lock changed during stale-lock takeover and could not be restored safely");
7611
7661
  }
7612
7662
  rmSync2(candidatePath);
7613
- fsyncDirectory(resolve3(lockPath, ".."));
7663
+ fsyncDirectory(resolve4(lockPath, ".."));
7614
7664
  exchanged = false;
7615
7665
  return true;
7616
7666
  } catch (error) {
7617
7667
  if (exchanged) {
7618
7668
  try {
7619
- if (currentFileHash(lockPath, workspaceRoot) === candidateHash && existsSync4(candidatePath)) {
7669
+ if (currentFileHash(lockPath, workspaceRoot) === candidateHash && existsSync5(candidatePath)) {
7620
7670
  atomicExchangePaths(candidatePath, lockPath);
7621
7671
  exchanged = false;
7622
7672
  }
@@ -7629,7 +7679,7 @@ function tryTakeoverStaleWorkspaceLock(candidatePath, lockPath, workspaceRoot, c
7629
7679
  }
7630
7680
  }
7631
7681
  function assertWorkspaceLockHeld(lockPath, lock, workspaceRoot) {
7632
- if (!existsSync4(lockPath)) {
7682
+ if (!existsSync5(lockPath)) {
7633
7683
  throw new ProjectContextError("PROJECT_CONTEXT_LOCK_LOST", "workspace project-context lock changed during render");
7634
7684
  }
7635
7685
  const current = lstatSync(lockPath);
@@ -7689,8 +7739,8 @@ function releaseWorkspaceLock(lockPath, lock, workspaceRoot) {
7689
7739
  }
7690
7740
  return;
7691
7741
  }
7692
- const lockDirectory = resolve3(lockPath, "..");
7693
- const releasePath = join5(lockDirectory, `.project-context-release-${randomUUID2()}.tmp`);
7742
+ const lockDirectory = resolve4(lockPath, "..");
7743
+ const releasePath = join6(lockDirectory, `.project-context-release-${randomUUID2()}.tmp`);
7694
7744
  let releaseFd = null;
7695
7745
  let releaseIdentity = null;
7696
7746
  let releaseHash = null;
@@ -7719,7 +7769,7 @@ function releaseWorkspaceLock(lockPath, lock, workspaceRoot) {
7719
7769
  const releaseInstalled = !installed.isSymbolicLink() && installed.dev === releaseIdentity.dev && installed.ino === releaseIdentity.ino && currentFileHash(lockPath, workspaceRoot) === releaseHash;
7720
7770
  const ownedDisplaced = !displaced.isSymbolicLink() && displaced.dev === lock.identity.dev && displaced.ino === lock.identity.ino && currentFileHash(releasePath, workspaceRoot) === lock.contentHash;
7721
7771
  if (!releaseInstalled || !ownedDisplaced) {
7722
- if (releaseInstalled && existsSync4(releasePath)) {
7772
+ if (releaseInstalled && existsSync5(releasePath)) {
7723
7773
  atomicExchangePaths(releasePath, lockPath);
7724
7774
  exchanged = false;
7725
7775
  }
@@ -7732,7 +7782,7 @@ function releaseWorkspaceLock(lockPath, lock, workspaceRoot) {
7732
7782
  } catch {
7733
7783
  if (exchanged) {
7734
7784
  try {
7735
- if (releaseHash && currentFileHash(lockPath, workspaceRoot) === releaseHash && existsSync4(releasePath)) {
7785
+ if (releaseHash && currentFileHash(lockPath, workspaceRoot) === releaseHash && existsSync5(releasePath)) {
7736
7786
  atomicExchangePaths(releasePath, lockPath);
7737
7787
  exchanged = false;
7738
7788
  }
@@ -7744,7 +7794,7 @@ function releaseWorkspaceLock(lockPath, lock, workspaceRoot) {
7744
7794
  closeSync(releaseFd);
7745
7795
  } catch {}
7746
7796
  }
7747
- if (!exchanged && existsSync4(releasePath)) {
7797
+ if (!exchanged && existsSync5(releasePath)) {
7748
7798
  try {
7749
7799
  rmSync2(releasePath);
7750
7800
  } catch {}
@@ -7770,15 +7820,15 @@ function ensureSafeDirectory(path, workspaceRoot, mode) {
7770
7820
  const segments = rel.split(/[\\/]+/).filter(Boolean);
7771
7821
  let current = workspaceRoot;
7772
7822
  for (const segment of segments) {
7773
- current = join5(current, segment);
7774
- if (existsSync4(current)) {
7823
+ current = join6(current, segment);
7824
+ if (existsSync5(current)) {
7775
7825
  if (lstatSync(current).isSymbolicLink())
7776
7826
  throw new ProjectContextError("PROJECT_CONTEXT_SYMLINK_REJECTED", `managed path uses a symlink: ${current}`);
7777
7827
  if (!statSync(current).isDirectory())
7778
7828
  throw new ProjectContextError("PROJECT_CONTEXT_PATH_INVALID", `managed path is not a directory: ${current}`);
7779
7829
  } else {
7780
7830
  mkdirSync2(current, { mode });
7781
- fsyncDirectory(resolve3(current, ".."));
7831
+ fsyncDirectory(resolve4(current, ".."));
7782
7832
  }
7783
7833
  }
7784
7834
  }
@@ -7834,11 +7884,11 @@ function scanGeneratedContent(content) {
7834
7884
  function runtimePaths(workspaceRoot, runtime) {
7835
7885
  const relativeTarget = runtime === "claude" ? "CLAUDE.md" : runtime === "codewith" ? ".codewith/CODEWITH.md" : "AGENTS.md";
7836
7886
  return {
7837
- target: resolve3(workspaceRoot, ...relativeTarget.split("/")),
7838
- fragment: resolve3(workspaceRoot, ...PROJECT_CONTEXT_FRAGMENT_PATH.split("/")),
7839
- manifest: resolve3(workspaceRoot, ...PROJECT_CONTEXT_MANIFEST_PATH.split("/")),
7840
- cache: resolve3(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/")),
7841
- sessionManifest: runtime === "codewith" ? resolve3(workspaceRoot, ".codewith", ".hasna", "session-render-manifest.json") : resolve3(workspaceRoot, ".hasna", "session-render-manifest.json")
7887
+ target: resolve4(workspaceRoot, ...relativeTarget.split("/")),
7888
+ fragment: resolve4(workspaceRoot, ...PROJECT_CONTEXT_FRAGMENT_PATH.split("/")),
7889
+ manifest: resolve4(workspaceRoot, ...PROJECT_CONTEXT_MANIFEST_PATH.split("/")),
7890
+ cache: resolve4(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/")),
7891
+ sessionManifest: runtime === "codewith" ? resolve4(workspaceRoot, ".codewith", ".hasna", "session-render-manifest.json") : resolve4(workspaceRoot, ".hasna", "session-render-manifest.json")
7842
7892
  };
7843
7893
  }
7844
7894
  function projectContextSessionGuardPaths(paths, runtime) {
@@ -7848,7 +7898,7 @@ function projectContextSessionGuardPaths(paths, runtime) {
7848
7898
  paths.fragment,
7849
7899
  paths.target,
7850
7900
  paths.sessionManifest,
7851
- ...runtime === "codewith" ? [resolve3(paths.target, "..", "CODEWITH.override.md")] : []
7901
+ ...runtime === "codewith" ? [resolve4(paths.target, "..", "CODEWITH.override.md")] : []
7852
7902
  ];
7853
7903
  }
7854
7904
  function sessionTargetRelativePath(runtime) {
@@ -7868,27 +7918,27 @@ function projectContextRuntimeForSessionTool(tool) {
7868
7918
  return null;
7869
7919
  }
7870
7920
  function projectContextWorkspaceForSession(input, runtime) {
7871
- const targetHome = resolve3(input.target_home);
7921
+ const targetHome = resolve4(input.target_home);
7872
7922
  if (runtime === "codewith") {
7873
- const workspaceRoot = basename(targetHome) === ".codewith" ? dirname(targetHome) : null;
7923
+ const workspaceRoot = basename(targetHome) === ".codewith" ? dirname2(targetHome) : null;
7874
7924
  if (!workspaceRoot)
7875
7925
  return null;
7876
- if (input.project_root && resolve3(input.project_root) !== workspaceRoot) {
7926
+ if (input.project_root && resolve4(input.project_root) !== workspaceRoot) {
7877
7927
  throw new ProjectContextError("PROJECT_CONTEXT_PATH_INVALID", "Codewith project_root must be the parent workspace of target_home");
7878
7928
  }
7879
- if (!existsSync4(workspaceRoot) || !lstatSync(workspaceRoot).isDirectory())
7929
+ if (!existsSync5(workspaceRoot) || !lstatSync(workspaceRoot).isDirectory())
7880
7930
  return null;
7881
7931
  return assertSafeWorkspaceRoot(workspaceRoot);
7882
7932
  }
7883
- if (!existsSync4(targetHome) || !lstatSync(targetHome).isDirectory())
7933
+ if (!existsSync5(targetHome) || !lstatSync(targetHome).isDirectory())
7884
7934
  return null;
7885
7935
  return assertSafeWorkspaceRoot(targetHome);
7886
7936
  }
7887
7937
  function assertCodewithTargetIsConsumed(workspaceRoot, runtime) {
7888
7938
  if (runtime !== "codewith")
7889
7939
  return;
7890
- const override = resolve3(workspaceRoot, ".codewith", "CODEWITH.override.md");
7891
- if (!existsSync4(override))
7940
+ const override = resolve4(workspaceRoot, ".codewith", "CODEWITH.override.md");
7941
+ if (!existsSync5(override))
7892
7942
  return;
7893
7943
  assertNoSymlinkSegments(workspaceRoot, override);
7894
7944
  if (!lstatSync(override).isFile())
@@ -7898,10 +7948,10 @@ function assertCodewithTargetIsConsumed(workspaceRoot, runtime) {
7898
7948
  function assertSafeWorkspaceRoot(path) {
7899
7949
  if (!isAbsolute(path))
7900
7950
  throw new ProjectContextError("PROJECT_CONTEXT_PATH_INVALID", "workspace root must be absolute");
7901
- const normalized = resolve3(path);
7951
+ const normalized = resolve4(path);
7902
7952
  if (normalized === parse(normalized).root)
7903
7953
  throw new ProjectContextError("PROJECT_CONTEXT_PATH_INVALID", "workspace root cannot be the filesystem root");
7904
- if (!existsSync4(normalized) || !lstatSync(normalized).isDirectory())
7954
+ if (!existsSync5(normalized) || !lstatSync(normalized).isDirectory())
7905
7955
  throw new ProjectContextError("PROJECT_CONTEXT_PATH_INVALID", "workspace root must be an existing directory");
7906
7956
  assertNoSymlinkAncestors(normalized);
7907
7957
  if (lstatSync(normalized).isSymbolicLink())
@@ -7915,18 +7965,18 @@ function assertNoSymlinkSegments(root, target) {
7915
7965
  }
7916
7966
  let current = root;
7917
7967
  for (const segment of rel.split(/[\\/]+/).filter(Boolean)) {
7918
- current = join5(current, segment);
7919
- if (existsSync4(current) && lstatSync(current).isSymbolicLink()) {
7968
+ current = join6(current, segment);
7969
+ if (existsSync5(current) && lstatSync(current).isSymbolicLink()) {
7920
7970
  throw new ProjectContextError("PROJECT_CONTEXT_SYMLINK_REJECTED", `managed path uses a symlink: ${current}`);
7921
7971
  }
7922
7972
  }
7923
7973
  }
7924
7974
  function assertNoSymlinkAncestors(path) {
7925
- const normalized = resolve3(path);
7975
+ const normalized = resolve4(path);
7926
7976
  let current = parse(normalized).root;
7927
7977
  for (const segment of relative(current, normalized).split(/[\\/]+/).filter(Boolean)) {
7928
- current = join5(current, segment);
7929
- if (!existsSync4(current))
7978
+ current = join6(current, segment);
7979
+ if (!existsSync5(current))
7930
7980
  return;
7931
7981
  if (lstatSync(current).isSymbolicLink())
7932
7982
  throw new ProjectContextError("PROJECT_CONTEXT_SYMLINK_REJECTED", `workspace ancestor is a symlink: ${current}`);
@@ -7942,7 +7992,7 @@ function readUtf8RegularFile(path, workspaceRoot, maxBytes = FOREIGN_INPUT_MAX_B
7942
7992
  return readFileSync(path, "utf8");
7943
7993
  }
7944
7994
  function currentFileHash(path, workspaceRoot) {
7945
- if (!existsSync4(path))
7995
+ if (!existsSync5(path))
7946
7996
  return null;
7947
7997
  const relativePath = relativePosix(workspaceRoot, path);
7948
7998
  return sha2562(readUtf8RegularFile(path, workspaceRoot, managedObservationMaxBytes(relativePath)));
@@ -7961,10 +8011,10 @@ function fragmentMatchesBundle(path, bundle, workspaceRoot) {
7961
8011
  }
7962
8012
  function durableSourcePath(path, workspaceRoot) {
7963
8013
  if (!path || path.startsWith("/dev/fd/"))
7964
- return resolve3(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/"));
7965
- const normalized = isAbsolute(path) ? resolve3(path) : resolve3(workspaceRoot, path);
8014
+ return resolve4(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/"));
8015
+ const normalized = isAbsolute(path) ? resolve4(path) : resolve4(workspaceRoot, path);
7966
8016
  if (normalized.startsWith("/dev/fd/"))
7967
- return resolve3(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/"));
8017
+ return resolve4(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/"));
7968
8018
  return normalized;
7969
8019
  }
7970
8020
  function compareRevisions(incoming, previous) {
@@ -8305,7 +8355,7 @@ function compareProviderVersions(left, right) {
8305
8355
 
8306
8356
  // src/lib/asset-plan.ts
8307
8357
  import { createHash as createHash3 } from "crypto";
8308
- import { isAbsolute as isAbsolute2, posix, resolve as resolve4 } from "path";
8358
+ import { isAbsolute as isAbsolute2, posix, resolve as resolve5 } from "path";
8309
8359
  var ASSET_PLAN_SCHEMA = "hasna.instructions.asset-plan/v1";
8310
8360
  var ASSET_CAPABILITY_SCHEMA = "hasna.instructions.asset-capability/v1";
8311
8361
  var ASSET_BUNDLE_SCHEMA = "hasna.instructions.asset-bundle/v1";
@@ -8570,8 +8620,8 @@ function resolveAssetDestination(item, roots) {
8570
8620
  if (!isAbsolute2(root))
8571
8621
  throw new Error(`Asset ${item.assetKey} destination root must be absolute.`);
8572
8622
  const relativePath = safeRelativePath(item.destination.relativePath);
8573
- const target = resolve4(root, ...relativePath.split("/"));
8574
- const normalizedRoot = resolve4(root);
8623
+ const target = resolve5(root, ...relativePath.split("/"));
8624
+ const normalizedRoot = resolve5(root);
8575
8625
  if (target === normalizedRoot)
8576
8626
  throw new Error(`Asset ${item.assetKey} destination cannot replace its root.`);
8577
8627
  if (!target.startsWith(`${normalizedRoot}/`))
@@ -8693,8 +8743,8 @@ function deepFreeze(value) {
8693
8743
  // src/lib/cursor-authority.ts
8694
8744
  import { createHash as createHash4 } from "crypto";
8695
8745
  import { lstatSync as lstatSync2, readFileSync as readFileSync2 } from "fs";
8696
- import { homedir as homedir4 } from "os";
8697
- import { join as join6, resolve as resolve5 } from "path";
8746
+ import { homedir as homedir5 } from "os";
8747
+ import { join as join7, resolve as resolve6 } from "path";
8698
8748
  var CURSOR_GLOBAL_AUTHORITY_RELATIVE_PATH = ".cursor/rules/hasna-global.mdc";
8699
8749
  var CURSOR_GLOBAL_AUTHORITY_MAX_BYTES = 256 * 1024;
8700
8750
  var CURSOR_GLOBAL_AUTHORITY_MANAGED_MARKER = "Managed by @hasna/configs cursor global authority";
@@ -8703,8 +8753,8 @@ var CURSOR_GLOBAL_AUTHORITY_FRONTMATTER_PATTERN = /^---\n[\s\S]*?\n---(?:\n|$)/;
8703
8753
  function sha2564(content) {
8704
8754
  return createHash4("sha256").update(content).digest("hex");
8705
8755
  }
8706
- function homeDir2() {
8707
- return process.env["HOME"] || homedir4();
8756
+ function homeDir3() {
8757
+ return process.env["HOME"] || homedir5();
8708
8758
  }
8709
8759
  function markerPayload(content, markerLine, markerIndex) {
8710
8760
  const index = markerIndex ?? content.indexOf(markerLine);
@@ -8720,12 +8770,12 @@ function baseObservation(path) {
8720
8770
  };
8721
8771
  }
8722
8772
  function observeCursorGlobalAuthority(options = {}) {
8723
- const authorityPath = resolve5(join6(options.home ?? homeDir2(), CURSOR_GLOBAL_AUTHORITY_RELATIVE_PATH));
8773
+ const authorityPath = resolve6(join7(options.home ?? homeDir3(), CURSOR_GLOBAL_AUTHORITY_RELATIVE_PATH));
8724
8774
  const readFile = options.readFile ?? ((path) => readFileSync2(path, "utf8"));
8725
8775
  return observeCursorGlobalAuthorityPath(authorityPath, readFile);
8726
8776
  }
8727
8777
  function observeCursorGlobalAuthorityAtPath(authorityPath) {
8728
- return observeCursorGlobalAuthorityPath(resolve5(authorityPath), (path) => readFileSync2(path, "utf8"));
8778
+ return observeCursorGlobalAuthorityPath(resolve6(authorityPath), (path) => readFileSync2(path, "utf8"));
8729
8779
  }
8730
8780
  function observeCursorGlobalAuthorityPath(authorityPath, readFile) {
8731
8781
  const base = baseObservation(authorityPath);
@@ -8870,7 +8920,7 @@ function observeCursorGlobalAuthorityPath(authorityPath, readFile) {
8870
8920
  };
8871
8921
  }
8872
8922
  function isCursorGlobalAuthorityPath(path) {
8873
- return resolve5(path) === resolve5(join6(homeDir2(), CURSOR_GLOBAL_AUTHORITY_RELATIVE_PATH));
8923
+ return resolve6(path) === resolve6(join7(homeDir3(), CURSOR_GLOBAL_AUTHORITY_RELATIVE_PATH));
8874
8924
  }
8875
8925
  function stampCursorGlobalAuthorityMarker(content) {
8876
8926
  const existing = content.match(CURSOR_GLOBAL_AUTHORITY_MARKER_PATTERN);
@@ -8920,8 +8970,8 @@ function detectCursorAuthorityConflicts(observation = observeCursorGlobalAuthori
8920
8970
  // src/lib/session-authority.ts
8921
8971
  import { createHash as createHash5 } from "crypto";
8922
8972
  import { lstatSync as lstatSync3, readFileSync as readFileSync3, realpathSync, statSync as statSync2 } from "fs";
8923
- import { homedir as homedir5 } from "os";
8924
- import { join as join7, resolve as resolve6 } from "path";
8973
+ import { homedir as homedir6 } from "os";
8974
+ import { join as join8, resolve as resolve7 } from "path";
8925
8975
  var CLAUDE_LEGACY_AUTHORITY_RELATIVE_PATH = "AGENTS.md";
8926
8976
  var CLAUDE_LEGACY_AUTHORITY_MAX_BYTES = 256 * 1024;
8927
8977
  var CLAUDE_LEGACY_MARKERS = [
@@ -8933,10 +8983,10 @@ function sha2565(content) {
8933
8983
  return createHash5("sha256").update(content).digest("hex");
8934
8984
  }
8935
8985
  function configHomeDir() {
8936
- return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir5();
8986
+ return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir6();
8937
8987
  }
8938
8988
  function normalizeOwnedTargetPath(p) {
8939
- const expanded = p.startsWith("~/") ? resolve6(configHomeDir(), p.slice(2)) : resolve6(p);
8989
+ const expanded = p.startsWith("~/") ? resolve7(configHomeDir(), p.slice(2)) : resolve7(p);
8940
8990
  try {
8941
8991
  return realpathSync(expanded);
8942
8992
  } catch {
@@ -8944,7 +8994,7 @@ function normalizeOwnedTargetPath(p) {
8944
8994
  }
8945
8995
  }
8946
8996
  function detectClaudeAuthorityConflicts(targetHome, ownedAuthorities = []) {
8947
- const authorityPath = resolve6(join7(targetHome, CLAUDE_LEGACY_AUTHORITY_RELATIVE_PATH));
8997
+ const authorityPath = resolve7(join8(targetHome, CLAUDE_LEGACY_AUTHORITY_RELATIVE_PATH));
8948
8998
  let stat;
8949
8999
  try {
8950
9000
  stat = lstatSync3(authorityPath);
@@ -9303,13 +9353,13 @@ function yamlQuote2(value) {
9303
9353
  return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
9304
9354
  }
9305
9355
  function defaultTargetHome(tool, profile, sessionId) {
9306
- const home = process.env["HOME"] || homedir6();
9307
- return join8(home, ".hasna", "accounts", "profiles", tool, slug(profile));
9356
+ const home = process.env["HOME"] || homedir7();
9357
+ return join9(home, ".hasna", "accounts", "profiles", tool, slug(profile));
9308
9358
  }
9309
9359
  function joinTarget(targetHome, relativePath) {
9310
9360
  const safeTargetHome = assertSafeTargetRoot(targetHome);
9311
9361
  const safeRelativePath2 = assertSafeRelativePath(relativePath);
9312
- return join8(safeTargetHome, ...safeRelativePath2.split("/"));
9362
+ return join9(safeTargetHome, ...safeRelativePath2.split("/"));
9313
9363
  }
9314
9364
  function makeFile(targetHome, relativePath, role, content, sourceIds) {
9315
9365
  const safeTargetHome = assertSafeTargetRoot(targetHome);
@@ -9879,7 +9929,7 @@ function buildOpenCodeFiles(targetHome, adapter, profile, sources, providerConfi
9879
9929
  ...sources.flatMap((source) => source.resolvedRules.map((rule) => rule.id))
9880
9930
  ]);
9881
9931
  const existingConfigPath = joinTarget(targetHome, adapter.configFile);
9882
- const selectedConfig = existsSync6(existingConfigPath) ? readOpenCodeConfig(readFileSync4(existingConfigPath, "utf8"), existingConfigPath) : providerConfig ? readOpenCodeConfig(providerConfig.content, providerConfig.sourceId) : {};
9932
+ const selectedConfig = existsSync7(existingConfigPath) ? readOpenCodeConfig(readFileSync4(existingConfigPath, "utf8"), existingConfigPath) : providerConfig ? readOpenCodeConfig(providerConfig.content, providerConfig.sourceId) : {};
9883
9933
  const preservedInstructions = normalizeOpenCodeInstructions(selectedConfig["instructions"]).filter((path) => !pathIsManagedOpenCodeInstruction(path, adapter.managedDir));
9884
9934
  const config = {
9885
9935
  ...selectedConfig,
@@ -10068,7 +10118,7 @@ function adapterFor(input) {
10068
10118
  return gatedNativeImports ? CODEWITH_NATIVE_ADAPTER : CODEWITH_FLATTENED_ADAPTER;
10069
10119
  }
10070
10120
  function getHomeDir() {
10071
- return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir6();
10121
+ return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir7();
10072
10122
  }
10073
10123
  function cleanSessionPathInput(path) {
10074
10124
  const trimmed = path.trim();
@@ -10083,16 +10133,16 @@ function resolveSessionPath(path) {
10083
10133
  throw new Error("Session render path cannot be empty.");
10084
10134
  const home = getHomeDir();
10085
10135
  if (cleaned === "~")
10086
- return resolve7(home);
10136
+ return resolve8(home);
10087
10137
  if (cleaned.startsWith("~/"))
10088
- return resolve7(home, cleaned.slice(2));
10138
+ return resolve8(home, cleaned.slice(2));
10089
10139
  if (cleaned === "{{HOME}}" || cleaned === "${HOME}")
10090
- return resolve7(home);
10140
+ return resolve8(home);
10091
10141
  if (cleaned.startsWith("{{HOME}}/"))
10092
- return resolve7(home, cleaned.slice("{{HOME}}/".length));
10142
+ return resolve8(home, cleaned.slice("{{HOME}}/".length));
10093
10143
  if (cleaned.startsWith("${HOME}/"))
10094
- return resolve7(home, cleaned.slice("${HOME}/".length));
10095
- return resolve7(cleaned);
10144
+ return resolve8(home, cleaned.slice("${HOME}/".length));
10145
+ return resolve8(cleaned);
10096
10146
  }
10097
10147
  function assertSafeRelativePath(relativePath) {
10098
10148
  if (!relativePath.trim())
@@ -10108,7 +10158,7 @@ function assertSafeRelativePath(relativePath) {
10108
10158
  function assertSafeTargetRoot(targetHome) {
10109
10159
  if (!isAbsolute3(targetHome))
10110
10160
  throw new Error(`Session render target must be an absolute path: ${targetHome}`);
10111
- const normalized = resolve7(targetHome);
10161
+ const normalized = resolve8(targetHome);
10112
10162
  if (normalized === parse2(normalized).root) {
10113
10163
  throw new Error(`Session render target cannot be the filesystem root: ${targetHome}`);
10114
10164
  }
@@ -10344,7 +10394,7 @@ function planSessionRender(input) {
10344
10394
  sourceId: input.providerConfig.sourceId,
10345
10395
  selectedPayloadSha256: sha2566(input.providerConfig.content),
10346
10396
  renderedPayloadSha256: files.find((file) => file.relativePath === adapter.configFile)?.sha256 ?? sha2566(input.providerConfig.content),
10347
- selected: !existsSync6(joinTarget(targetHome, adapter.configFile))
10397
+ selected: !existsSync7(joinTarget(targetHome, adapter.configFile))
10348
10398
  }
10349
10399
  } : {},
10350
10400
  ...projectContext ? {
@@ -10706,7 +10756,7 @@ function layerFromIdentityKind(kind, exportShape) {
10706
10756
  function contentFromIdentitySourcePaths(sourcePaths, exportPath, sourceId) {
10707
10757
  if (sourcePaths.length === 0 || !exportPath)
10708
10758
  return;
10709
- const baseDir2 = dirname3(resolveSessionPath(exportPath));
10759
+ const baseDir2 = dirname4(resolveSessionPath(exportPath));
10710
10760
  const contents = [];
10711
10761
  for (const sourcePath of sourcePaths) {
10712
10762
  const content = readIdentitySourcePath(sourcePath, baseDir2, sourceId);
@@ -10724,7 +10774,7 @@ ${item.content.trimEnd()}`).join(`
10724
10774
  }
10725
10775
  function readIdentitySourcePath(sourcePath, baseDir2, sourceId) {
10726
10776
  const resolvedPath = resolveIdentitySourcePath(sourcePath.path, baseDir2, sourceId);
10727
- if (!existsSync6(resolvedPath)) {
10777
+ if (!existsSync7(resolvedPath)) {
10728
10778
  if (sourcePath.required) {
10729
10779
  throw new Error(`Required identity instruction source path not found for ${sourceId}: ${sourcePath.path}`);
10730
10780
  }
@@ -10747,8 +10797,8 @@ function resolveIdentitySourcePath(path, baseDir2, sourceId) {
10747
10797
  throw new Error(`Identity instruction source path cannot be empty for ${sourceId}.`);
10748
10798
  if (cleaned.includes("\\"))
10749
10799
  throw new Error(`Identity instruction source path must use POSIX separators for ${sourceId}: ${path}`);
10750
- const resolvedPath = isAbsolute3(cleaned) ? resolve7(cleaned) : resolve7(baseDir2, cleaned);
10751
- if (!pathIsInside(resolvedPath, resolve7(baseDir2))) {
10800
+ const resolvedPath = isAbsolute3(cleaned) ? resolve8(cleaned) : resolve8(baseDir2, cleaned);
10801
+ if (!pathIsInside(resolvedPath, resolve8(baseDir2))) {
10752
10802
  throw new Error(`Identity instruction source path escapes export directory for ${sourceId}: ${path}`);
10753
10803
  }
10754
10804
  return resolvedPath;
@@ -12155,16 +12205,16 @@ function resolveConfigStore(env = process.env) {
12155
12205
  return cloud ? new CloudConfigStore(cloud) : new LocalConfigStore;
12156
12206
  }
12157
12207
  // src/status.ts
12158
- import { existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
12208
+ import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
12159
12209
 
12160
12210
  // src/lib/apply.ts
12161
- import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync6, realpathSync as realpathSync3, writeFileSync as writeFileSync2 } from "fs";
12162
- import { basename as basename5, dirname as dirname5, join as join10, resolve as resolve8 } from "path";
12163
- import { homedir as homedir7 } from "os";
12211
+ import { existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync6, realpathSync as realpathSync3, writeFileSync as writeFileSync2 } from "fs";
12212
+ import { basename as basename5, dirname as dirname6, join as join11, resolve as resolve9 } from "path";
12213
+ import { homedir as homedir8 } from "os";
12164
12214
 
12165
12215
  // src/lib/session-render-ownership.ts
12166
- import { existsSync as existsSync7, readFileSync as readFileSync5, statSync as statSync4 } from "fs";
12167
- import { dirname as dirname4, join as join9, parse as parse3, relative as relative3, sep } from "path";
12216
+ import { existsSync as existsSync8, readFileSync as readFileSync5, statSync as statSync4 } from "fs";
12217
+ import { dirname as dirname5, join as join10, parse as parse3, relative as relative3, sep } from "path";
12168
12218
  var MANIFEST_ANCESTOR_LIMIT = 24;
12169
12219
  var MANAGED_PATH_SEGMENTS = SESSION_RENDER_EXCLUSIVE_MANAGED_PATHS.map((managedPath) => managedPath.split("/").filter(Boolean));
12170
12220
  var manifestCache = new Map;
@@ -12186,7 +12236,7 @@ function pathIsSessionRenderManagedDir(absolutePath2) {
12186
12236
  function readManifestRelativePaths(manifestPath) {
12187
12237
  let stats;
12188
12238
  try {
12189
- if (!existsSync7(manifestPath))
12239
+ if (!existsSync8(manifestPath))
12190
12240
  return null;
12191
12241
  stats = statSync4(manifestPath);
12192
12242
  } catch {
@@ -12213,16 +12263,16 @@ function readManifestRelativePaths(manifestPath) {
12213
12263
  }
12214
12264
  function sessionRenderManifestClaimsPath(absolutePath2) {
12215
12265
  const root = parse3(absolutePath2).root;
12216
- let home = dirname4(absolutePath2);
12266
+ let home = dirname5(absolutePath2);
12217
12267
  for (let depth = 0;depth < MANIFEST_ANCESTOR_LIMIT; depth += 1) {
12218
- const manifestPath = join9(home, ...SESSION_RENDER_MANIFEST_RELATIVE_PATH.split("/"));
12268
+ const manifestPath = join10(home, ...SESSION_RENDER_MANIFEST_RELATIVE_PATH.split("/"));
12219
12269
  const relativePaths = readManifestRelativePaths(manifestPath);
12220
12270
  if (relativePaths) {
12221
12271
  const claimed = relative3(home, absolutePath2).split(sep).join("/");
12222
12272
  if (relativePaths.has(claimed))
12223
12273
  return true;
12224
12274
  }
12225
- const parent = dirname4(home);
12275
+ const parent = dirname5(home);
12226
12276
  if (parent === home || home === root)
12227
12277
  break;
12228
12278
  home = parent;
@@ -12235,13 +12285,13 @@ function sessionRenderOwnsPath(absolutePath2) {
12235
12285
 
12236
12286
  // src/lib/apply.ts
12237
12287
  function getConfigHome() {
12238
- return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir7();
12288
+ return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir8();
12239
12289
  }
12240
12290
  function expandPath(p) {
12241
12291
  if (p.startsWith("~/")) {
12242
- return resolve8(getConfigHome(), p.slice(2));
12292
+ return resolve9(getConfigHome(), p.slice(2));
12243
12293
  }
12244
- return resolve8(p);
12294
+ return resolve9(p);
12245
12295
  }
12246
12296
  function normalizeTargetPath(p) {
12247
12297
  const expanded = expandPath(p);
@@ -12251,14 +12301,14 @@ function normalizeTargetPath(p) {
12251
12301
  let current = expanded;
12252
12302
  const missingSegments = [];
12253
12303
  while (true) {
12254
- if (existsSync8(current)) {
12304
+ if (existsSync9(current)) {
12255
12305
  try {
12256
- return resolve8(realpathSync3(current), ...missingSegments);
12306
+ return resolve9(realpathSync3(current), ...missingSegments);
12257
12307
  } catch {
12258
12308
  return expanded;
12259
12309
  }
12260
12310
  }
12261
- const parent = dirname5(current);
12311
+ const parent = dirname6(current);
12262
12312
  const name = basename5(current);
12263
12313
  if (parent === current)
12264
12314
  return expanded;
@@ -12282,11 +12332,11 @@ async function writeConfigResult(config, targetPath, content, opts, meta = {}) {
12282
12332
  }
12283
12333
  const path = expandPath(renderedTargetPath);
12284
12334
  const renderedForTarget = isCursorGlobalAuthorityPath(path) ? stampCursorGlobalAuthorityMarker(renderedContent) : renderedContent;
12285
- const previousContent = existsSync8(path) ? readFileSync6(path, "utf-8") : null;
12335
+ const previousContent = existsSync9(path) ? readFileSync6(path, "utf-8") : null;
12286
12336
  const changed = previousContent !== renderedForTarget;
12287
12337
  if (!opts.dryRun) {
12288
- const dir = dirname5(path);
12289
- if (!existsSync8(dir)) {
12338
+ const dir = dirname6(path);
12339
+ if (!existsSync9(dir)) {
12290
12340
  mkdirSync3(dir, { recursive: true });
12291
12341
  }
12292
12342
  if (previousContent !== null && changed) {
@@ -12320,7 +12370,7 @@ function wouldDestroyACredential(targetPath, renderedContent, format) {
12320
12370
  let current;
12321
12371
  try {
12322
12372
  const path = expandPath(targetPath);
12323
- if (!existsSync8(path))
12373
+ if (!existsSync9(path))
12324
12374
  return [];
12325
12375
  current = readFileSync6(path, "utf-8");
12326
12376
  } catch {
@@ -12646,31 +12696,31 @@ function sessionRendererOwnsCanonicalTarget(normalized, opts) {
12646
12696
  getConfigHome(),
12647
12697
  opts.vars?.["HOME_DIR"]
12648
12698
  ].filter((home) => typeof home === "string" && home.length > 0));
12649
- if ([...homes].some((home) => SESSION_RENDER_OWNED_CONFIG_TARGETS.some((relativePath) => normalized === normalizeTargetPath(join10(home, ...relativePath.split("/"))))))
12699
+ if ([...homes].some((home) => SESSION_RENDER_OWNED_CONFIG_TARGETS.some((relativePath) => normalized === normalizeTargetPath(join11(home, ...relativePath.split("/"))))))
12650
12700
  return true;
12651
12701
  return sessionRenderOwnsPath(normalized);
12652
12702
  }
12653
12703
 
12654
12704
  // src/lib/package-version.ts
12655
- import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
12656
- import { dirname as dirname6, join as join11 } from "path";
12705
+ import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
12706
+ import { dirname as dirname7, join as join12 } from "path";
12657
12707
  import { fileURLToPath } from "url";
12658
12708
  var cached = null;
12659
12709
  function getPackageVersion() {
12660
12710
  if (cached)
12661
12711
  return cached;
12662
12712
  try {
12663
- let dir = dirname6(fileURLToPath(import.meta.url));
12713
+ let dir = dirname7(fileURLToPath(import.meta.url));
12664
12714
  for (let i = 0;i < 8; i++) {
12665
- const pkgPath = join11(dir, "package.json");
12666
- if (existsSync9(pkgPath)) {
12715
+ const pkgPath = join12(dir, "package.json");
12716
+ if (existsSync10(pkgPath)) {
12667
12717
  const pkg = JSON.parse(readFileSync7(pkgPath, "utf8"));
12668
12718
  if (pkg.name === "@hasna/instructions" && pkg.version) {
12669
12719
  cached = pkg.version;
12670
12720
  return cached;
12671
12721
  }
12672
12722
  }
12673
- const parent = dirname6(dir);
12723
+ const parent = dirname7(dir);
12674
12724
  if (parent === dir)
12675
12725
  break;
12676
12726
  dir = parent;
@@ -12684,7 +12734,7 @@ function getPackageVersion() {
12684
12734
  import { createHash as createHash8 } from "crypto";
12685
12735
  import { spawnSync } from "child_process";
12686
12736
  import {
12687
- existsSync as existsSync10,
12737
+ existsSync as existsSync11,
12688
12738
  lstatSync as lstatSync4,
12689
12739
  mkdirSync as mkdirSync4,
12690
12740
  readFileSync as readFileSync8,
@@ -12692,8 +12742,8 @@ import {
12692
12742
  rmSync as rmSync3,
12693
12743
  writeFileSync as writeFileSync3
12694
12744
  } from "fs";
12695
- import { homedir as homedir8 } from "os";
12696
- import { dirname as dirname7, join as join12, parse as parse4, relative as relative4, resolve as resolve9 } from "path";
12745
+ import { homedir as homedir9 } from "os";
12746
+ import { dirname as dirname8, join as join13, parse as parse4, relative as relative4, resolve as resolve10 } from "path";
12697
12747
  var INBOX_CONVERSATIONS_MINIMUM_VERSION = "0.5.28";
12698
12748
  var INBOX_SKILL_MARKERS = [
12699
12749
  [".claude", "skills", "inbox", "SKILL.md"],
@@ -12714,13 +12764,13 @@ function lstatOrNull(path) {
12714
12764
  }
12715
12765
  }
12716
12766
  function findSymlinkedAncestor(path) {
12717
- const normalized = resolve9(path);
12767
+ const normalized = resolve10(path);
12718
12768
  const parsed = parse4(normalized);
12719
12769
  let current = parsed.root;
12720
12770
  const rel = relative4(parsed.root, normalized);
12721
12771
  for (const segment of rel.split(/[\\/]+/).filter(Boolean)) {
12722
- current = join12(current, segment);
12723
- if (!existsSync10(current))
12772
+ current = join13(current, segment);
12773
+ if (!existsSync11(current))
12724
12774
  return null;
12725
12775
  if (lstatSync4(current).isSymbolicLink())
12726
12776
  return current;
@@ -12737,11 +12787,11 @@ function packagedInboxSkillPath(explicitPath) {
12737
12787
  if (explicitPath)
12738
12788
  return explicitPath;
12739
12789
  const candidates = [
12740
- join12(import.meta.dir, "..", "..", "assets", "skills", "inbox", "SKILL.md"),
12741
- join12(import.meta.dir, "..", "assets", "skills", "inbox", "SKILL.md"),
12742
- join12(process.cwd(), "assets", "skills", "inbox", "SKILL.md")
12790
+ join13(import.meta.dir, "..", "..", "assets", "skills", "inbox", "SKILL.md"),
12791
+ join13(import.meta.dir, "..", "assets", "skills", "inbox", "SKILL.md"),
12792
+ join13(process.cwd(), "assets", "skills", "inbox", "SKILL.md")
12743
12793
  ];
12744
- const found = candidates.find((candidate) => existsSync10(candidate));
12794
+ const found = candidates.find((candidate) => existsSync11(candidate));
12745
12795
  if (!found) {
12746
12796
  throw new Error(`packaged inbox skill contract is missing (checked ${candidates.length} package-relative locations)`);
12747
12797
  }
@@ -12790,8 +12840,8 @@ function compareVersions(left, right) {
12790
12840
  }
12791
12841
  return 0;
12792
12842
  }
12793
- function inspectSkillMarkers(homeDir3) {
12794
- return INBOX_SKILL_MARKERS.map((parts) => join12(homeDir3, ...parts)).map((path) => {
12843
+ function inspectSkillMarkers(homeDir4) {
12844
+ return INBOX_SKILL_MARKERS.map((parts) => join13(homeDir4, ...parts)).map((path) => {
12795
12845
  const stat = lstatOrNull(path);
12796
12846
  if (!stat)
12797
12847
  return null;
@@ -12807,9 +12857,9 @@ function inspectSkillMarkers(homeDir3) {
12807
12857
  }).filter((snapshot) => snapshot !== null);
12808
12858
  }
12809
12859
  function inspectInbox(options) {
12810
- const homeDir3 = options.homeDir ?? homedir8();
12860
+ const homeDir4 = options.homeDir ?? homedir9();
12811
12861
  const runtimeCommand = options.conversationsCommand ?? "conversations";
12812
- const snapshots = inspectSkillMarkers(homeDir3);
12862
+ const snapshots = inspectSkillMarkers(homeDir4);
12813
12863
  const skillPresent = snapshots.length > 0;
12814
12864
  let canonicalContent = null;
12815
12865
  let canonicalSha256 = null;
@@ -12835,7 +12885,7 @@ function inspectInbox(options) {
12835
12885
  let reason = "skill not installed";
12836
12886
  if (skillPresent) {
12837
12887
  const nonRegular = snapshots.some((snapshot) => !snapshot.regular);
12838
- const symlinkAncestor = snapshots.map((snapshot) => snapshot.path).map((path) => findSymlinkedAncestor(dirname7(path))).find((found) => found !== null);
12888
+ const symlinkAncestor = snapshots.map((snapshot) => snapshot.path).map((path) => findSymlinkedAncestor(dirname8(path))).find((found) => found !== null);
12839
12889
  if (nonRegular)
12840
12890
  reason = "managed skill target is not a regular file";
12841
12891
  else if (symlinkAncestor)
@@ -12922,10 +12972,10 @@ function cleanup(path) {
12922
12972
  rmSync3(path, { force: true });
12923
12973
  }
12924
12974
  function writeAtomic(path, content, mode) {
12925
- assertNoSymlinkAncestors2(dirname7(path));
12975
+ assertNoSymlinkAncestors2(dirname8(path));
12926
12976
  const tempPath = `${path}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
12927
12977
  try {
12928
- mkdirSync4(dirname7(path), { recursive: true, mode: 493 });
12978
+ mkdirSync4(dirname8(path), { recursive: true, mode: 493 });
12929
12979
  writeFileSync3(tempPath, content, { mode, flag: "wx" });
12930
12980
  renameSync2(tempPath, path);
12931
12981
  } finally {
@@ -13001,7 +13051,7 @@ async function reconcileManagedSkillRuntimes(options = {}) {
13001
13051
  dry_run: dryRun
13002
13052
  };
13003
13053
  }
13004
- const symlinkedAncestor = before.snapshots.map((snapshot) => snapshot.path).map((path) => findSymlinkedAncestor(dirname7(path))).find((found) => found !== null);
13054
+ const symlinkedAncestor = before.snapshots.map((snapshot) => snapshot.path).map((path) => findSymlinkedAncestor(dirname8(path))).find((found) => found !== null);
13005
13055
  if (symlinkedAncestor) {
13006
13056
  return {
13007
13057
  runtimes: [{ ...status, action: "failed", dry_run: dryRun, skill_contracts_changed: 0 }],
@@ -13123,7 +13173,7 @@ async function getConfigsStatus(store = resolveConfigStore(), options = {}) {
13123
13173
  continue;
13124
13174
  knownTargets += 1;
13125
13175
  const targetPath = expandPath(config.target_path);
13126
- if (!existsSync11(targetPath)) {
13176
+ if (!existsSync12(targetPath)) {
13127
13177
  missingTargets += 1;
13128
13178
  continue;
13129
13179
  }
@@ -13219,8 +13269,8 @@ async function getConfigsStatus(store = resolveConfigStore(), options = {}) {
13219
13269
  }
13220
13270
  // src/lib/provider-context.ts
13221
13271
  import { createHash as createHash9 } from "crypto";
13222
- import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as readFileSync10, writeFileSync as writeFileSync4 } from "fs";
13223
- import { join as join13 } from "path";
13272
+ import { existsSync as existsSync13, mkdirSync as mkdirSync5, readFileSync as readFileSync10, writeFileSync as writeFileSync4 } from "fs";
13273
+ import { join as join14 } from "path";
13224
13274
  var PROVIDER_CONTEXT_DIR = ".hasna/provider-context";
13225
13275
  var PROVIDER_CONTEXT_MANIFEST = "manifest.json";
13226
13276
  var PROVIDER_CONTEXT_SCHEMA = "hasna.instructions.provider-context/v1";
@@ -13365,17 +13415,17 @@ function resolveAndRenderProviderContext(opts) {
13365
13415
  const recordedEndpoint = originAccepted ? `${opts.origin.host}${opts.origin.pathPrefix || ""}` : null;
13366
13416
  const reason = entry === null && opts.rawEndpoint ? originAccepted ? `endpoint "${recordedEndpoint}" is not in the provider-context registry; using the invariant fragment` : "endpoint rejected (embedded credentials or unparseable); using the invariant fragment" : null;
13367
13417
  const content = renderProviderFragment(entry);
13368
- const dir = join13(opts.homeDir, PROVIDER_CONTEXT_DIR);
13369
- if (!existsSync12(dir))
13418
+ const dir = join14(opts.homeDir, PROVIDER_CONTEXT_DIR);
13419
+ if (!existsSync13(dir))
13370
13420
  mkdirSync5(dir, { recursive: true });
13371
13421
  const filename = `${entry ? entry.key : "invariant"}.md`;
13372
- const fragmentPath2 = join13(dir, filename);
13422
+ const fragmentPath2 = join14(dir, filename);
13373
13423
  const fragmentSha256 = sha2569(content);
13374
13424
  writeFileSync4(fragmentPath2, content, "utf8");
13375
- const manifestPath = join13(dir, PROVIDER_CONTEXT_MANIFEST);
13425
+ const manifestPath = join14(dir, PROVIDER_CONTEXT_MANIFEST);
13376
13426
  let manifest = { schema: PROVIDER_CONTEXT_SCHEMA, fragments: {} };
13377
13427
  try {
13378
- if (existsSync12(manifestPath)) {
13428
+ if (existsSync13(manifestPath)) {
13379
13429
  const parsed = JSON.parse(readFileSync10(manifestPath, "utf8"));
13380
13430
  if (parsed && typeof parsed === "object")
13381
13431
  manifest = parsed;
@@ -13487,9 +13537,9 @@ var PG_MIGRATIONS = [
13487
13537
  ];
13488
13538
  // src/lib/station-profile.ts
13489
13539
  import { spawnSync as spawnSync2 } from "child_process";
13490
- import { existsSync as existsSync13, lstatSync as lstatSync5, mkdirSync as mkdirSync6, readFileSync as readFileSync11, readdirSync, writeFileSync as writeFileSync5 } from "fs";
13491
- import { arch as osArch, homedir as homedir9, hostname as osHostname, platform as osPlatform, userInfo as osUserInfo } from "os";
13492
- import { dirname as dirname8, join as join14 } from "path";
13540
+ import { existsSync as existsSync14, lstatSync as lstatSync5, mkdirSync as mkdirSync6, readFileSync as readFileSync11, readdirSync as readdirSync2, writeFileSync as writeFileSync5 } from "fs";
13541
+ import { arch as osArch, homedir as homedir10, hostname as osHostname, platform as osPlatform, userInfo as osUserInfo } from "os";
13542
+ import { dirname as dirname9, join as join15 } from "path";
13493
13543
  var STATION_PROFILE_CACHE_FILENAME = "station-profile.md";
13494
13544
  var STATION_PROFILE_SOURCE_ID = "station-profile";
13495
13545
  var STATION_PROFILE_LAYER = "machine";
@@ -13499,21 +13549,21 @@ var STATION_PROFILE_FULL_NAMES_MAX = 6;
13499
13549
  var STATION_PROFILE_PRIMARY_SCOPE = "@hasna";
13500
13550
  var MACHINES_MANIFEST_PATH_ENV = "HASNA_MACHINES_MANIFEST_PATH";
13501
13551
  var BUN_INSTALL_ENV = "BUN_INSTALL";
13502
- function homeDir3(env = process.env) {
13503
- return env["HOME"] || env["USERPROFILE"] || homedir9();
13552
+ function homeDir4(env = process.env) {
13553
+ return env["HOME"] || env["USERPROFILE"] || homedir10();
13504
13554
  }
13505
13555
  function getStationProfileCachePath(env = process.env) {
13506
- return join14(getRawStoreRoot(env), STATION_PROFILE_CACHE_FILENAME);
13556
+ return join15(getRawStoreRoot(env), STATION_PROFILE_CACHE_FILENAME);
13507
13557
  }
13508
13558
  function getMachinesManifestPath(env = process.env) {
13509
- return env[MACHINES_MANIFEST_PATH_ENV] || join14(homeDir3(env), ".hasna", "machines", "machines.json");
13559
+ return env[MACHINES_MANIFEST_PATH_ENV] || join15(homeDir4(env), ".hasna", "machines", "machines.json");
13510
13560
  }
13511
13561
  function getBunGlobalModulesDir(env = process.env) {
13512
- return join14(env[BUN_INSTALL_ENV] || join14(homeDir3(env), ".bun"), "install", "global", "node_modules");
13562
+ return join15(env[BUN_INSTALL_ENV] || join15(homeDir4(env), ".bun"), "install", "global", "node_modules");
13513
13563
  }
13514
13564
  function readMachinesManifest(path) {
13515
13565
  try {
13516
- if (!existsSync13(path))
13566
+ if (!existsSync14(path))
13517
13567
  return null;
13518
13568
  const parsed = JSON.parse(readFileSync11(path, "utf8"));
13519
13569
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
@@ -13569,9 +13619,9 @@ function probeMachineStatus(machineId) {
13569
13619
  function resolveStationProfileMachine(env = process.env, options = {}) {
13570
13620
  const hostname2 = osHostname();
13571
13621
  const record = findLocalManifestMachine(readMachinesManifest(getMachinesManifestPath(env)), hostname2);
13572
- const home = homeDir3(env);
13622
+ const home = homeDir4(env);
13573
13623
  const platform = stringField(record, "platform") ?? osPlatform();
13574
- const workspacePath = stringField(record, "workspacePath") ?? join14(home, platform === "darwin" ? "Workspace" : "workspace");
13624
+ const workspacePath = stringField(record, "workspacePath") ?? join15(home, platform === "darwin" ? "Workspace" : "workspace");
13575
13625
  const machine = {
13576
13626
  id: stringField(record, "id") ?? hostname2,
13577
13627
  hostname: stringField(record, "hostname") ?? hostname2,
@@ -13588,9 +13638,9 @@ function resolveStationProfileMachine(env = process.env, options = {}) {
13588
13638
  return machine;
13589
13639
  }
13590
13640
  function scopedPackageNames(modulesDir, scope) {
13591
- const scopeDir = join14(modulesDir, scope);
13641
+ const scopeDir = join15(modulesDir, scope);
13592
13642
  try {
13593
- if (!existsSync13(scopeDir))
13643
+ if (!existsSync14(scopeDir))
13594
13644
  return null;
13595
13645
  return readdirNames(scopeDir).sort();
13596
13646
  } catch {
@@ -13598,9 +13648,9 @@ function scopedPackageNames(modulesDir, scope) {
13598
13648
  }
13599
13649
  }
13600
13650
  function readdirNames(dir) {
13601
- return readdirSync(dir).filter((name) => {
13651
+ return readdirSync2(dir).filter((name) => {
13602
13652
  try {
13603
- return lstatSync5(join14(dir, name)).isDirectory();
13653
+ return lstatSync5(join15(dir, name)).isDirectory();
13604
13654
  } catch {
13605
13655
  return false;
13606
13656
  }
@@ -13610,7 +13660,7 @@ function resolveStationProfilePackages(env = process.env) {
13610
13660
  const modulesDir = getBunGlobalModulesDir(env);
13611
13661
  let scopeDirs;
13612
13662
  try {
13613
- if (!existsSync13(modulesDir))
13663
+ if (!existsSync14(modulesDir))
13614
13664
  return null;
13615
13665
  scopeDirs = readdirNames(modulesDir).filter((name) => name.startsWith("@") && name.toLowerCase().includes("hasna"));
13616
13666
  } catch {
@@ -13685,9 +13735,9 @@ function refreshStationProfile(options = {}) {
13685
13735
  const path = getStationProfileCachePath(env);
13686
13736
  const generatedAt = new Date().toISOString();
13687
13737
  if (!options.dryRun) {
13688
- const existing = existsSync13(path) ? readFileSync11(path, "utf8") : null;
13738
+ const existing = existsSync14(path) ? readFileSync11(path, "utf8") : null;
13689
13739
  if (existing !== content) {
13690
- mkdirSync6(dirname8(path), { recursive: true });
13740
+ mkdirSync6(dirname9(path), { recursive: true });
13691
13741
  writeFileSync5(path, content, "utf8");
13692
13742
  }
13693
13743
  }
@@ -13704,7 +13754,7 @@ function refreshStationProfile(options = {}) {
13704
13754
  function readStationProfile(env = process.env) {
13705
13755
  const path = getStationProfileCachePath(env);
13706
13756
  try {
13707
- if (!existsSync13(path))
13757
+ if (!existsSync14(path))
13708
13758
  return null;
13709
13759
  return readFileSync11(path, "utf8");
13710
13760
  } catch {
@@ -13728,14 +13778,14 @@ function stationProfileSource(env = process.env) {
13728
13778
  // src/lib/session-apply.ts
13729
13779
  import { createHash as createHash10, randomUUID as randomUUID4 } from "crypto";
13730
13780
  import {
13731
- existsSync as existsSync14,
13781
+ existsSync as existsSync15,
13732
13782
  lstatSync as lstatSync6,
13733
13783
  mkdirSync as mkdirSync7,
13734
13784
  readFileSync as readFileSync12,
13735
- readdirSync as readdirSync2,
13785
+ readdirSync as readdirSync3,
13736
13786
  statSync as statSync5
13737
13787
  } from "fs";
13738
- import { dirname as dirname9, isAbsolute as isAbsolute4, join as join15, parse as parse5, relative as relative5, resolve as resolve10 } from "path";
13788
+ import { dirname as dirname10, isAbsolute as isAbsolute4, join as join16, parse as parse5, relative as relative5, resolve as resolve11 } from "path";
13739
13789
  class SessionApplyError extends Error {
13740
13790
  constructor(message) {
13741
13791
  super(message);
@@ -13866,13 +13916,13 @@ function assertClaudeAuthorityStillClear(plan, targetHome, ownedClaudeAuthoritie
13866
13916
  throw new SessionApplyError(`Claude authority changed after planning; refusing to apply: ${summary}`);
13867
13917
  }
13868
13918
  function ensureSessionTargetHome(targetHome) {
13869
- if (!existsSync14(targetHome))
13919
+ if (!existsSync15(targetHome))
13870
13920
  mkdirSync7(targetHome, { recursive: true, mode: 448 });
13871
13921
  assertSafeTargetHome(targetHome);
13872
13922
  }
13873
13923
  function checkSessionRenderDrift(targetHome, manifestPath) {
13874
13924
  const safeTargetHome = assertSafeTargetHome(targetHome);
13875
- const resolvedManifestPath = manifestPath ? resolveManifestRelativePath(relative5(safeTargetHome, resolve10(manifestPath)), safeTargetHome) : resolve10(safeTargetHome, ".hasna", "session-render-manifest.json");
13925
+ const resolvedManifestPath = manifestPath ? resolveManifestRelativePath(relative5(safeTargetHome, resolve11(manifestPath)), safeTargetHome) : resolve11(safeTargetHome, ".hasna", "session-render-manifest.json");
13876
13926
  const checkedAt = new Date().toISOString();
13877
13927
  const previousManifest = readPreviousManifest(resolvedManifestPath);
13878
13928
  if (!previousManifest) {
@@ -13889,7 +13939,7 @@ function checkSessionRenderDrift(targetHome, manifestPath) {
13889
13939
  const drifted = [];
13890
13940
  for (const file of previousManifest.files) {
13891
13941
  const target = resolveManifestRelativePath(file.relativePath, safeTargetHome);
13892
- if (!existsSync14(target)) {
13942
+ if (!existsSync15(target)) {
13893
13943
  missing.push({
13894
13944
  path: target,
13895
13945
  relativePath: file.relativePath,
@@ -13922,12 +13972,17 @@ function checkSessionRenderDrift(targetHome, manifestPath) {
13922
13972
  function restoreSessionRenderSnapshot(snapshotPath, options = {}) {
13923
13973
  const snapshot = readSessionRenderSnapshot(snapshotPath);
13924
13974
  const targetHome = assertSafeTargetHome(snapshot.targetHome);
13925
- const resolvedSnapshotPath = resolve10(snapshotPath);
13926
- const snapshotRelativePath = relative5(targetHome, resolvedSnapshotPath);
13927
- if (snapshotRelativePath === "" || snapshotRelativePath === ".." || snapshotRelativePath.startsWith("../") || isAbsolute4(snapshotRelativePath)) {
13928
- throw new SessionApplyError("Session snapshot must be stored inside its target home.");
13975
+ const resolvedSnapshotPath = resolve11(snapshotPath);
13976
+ const snapshotDir = getSessionRenderSnapshotDir(targetHome);
13977
+ const snapshotDirRelative = relative5(snapshotDir, resolvedSnapshotPath);
13978
+ const insideSnapshotDir = snapshotDirRelative !== ".." && !snapshotDirRelative.startsWith("../") && !isAbsolute4(snapshotDirRelative);
13979
+ if (!insideSnapshotDir) {
13980
+ const snapshotRelativePath = relative5(targetHome, resolvedSnapshotPath);
13981
+ if (snapshotRelativePath === "" || snapshotRelativePath === ".." || snapshotRelativePath.startsWith("../") || isAbsolute4(snapshotRelativePath)) {
13982
+ throw new SessionApplyError("Session snapshot must be stored inside its session-render snapshot location.");
13983
+ }
13929
13984
  }
13930
- assertNoSymlinkSegments2(targetHome, resolvedSnapshotPath);
13985
+ assertNoSymlinkSegments2(sessionRenderSnapshotWorkspaceRoot(targetHome), resolvedSnapshotPath);
13931
13986
  const guard = observeProjectContextSessionGuard({
13932
13987
  tool: snapshot.tool,
13933
13988
  target_home: targetHome,
@@ -14040,8 +14095,8 @@ function requiredRestoreHash(file) {
14040
14095
  return file.previousSha256;
14041
14096
  }
14042
14097
  function readSessionRenderSnapshot(snapshotPath) {
14043
- const resolved = resolve10(snapshotPath);
14044
- if (!existsSync14(resolved))
14098
+ const resolved = resolve11(snapshotPath);
14099
+ if (!existsSync15(resolved))
14045
14100
  throw new SessionApplyError(`Session snapshot not found: ${snapshotPath}`);
14046
14101
  const stat = lstatSync6(resolved);
14047
14102
  if (stat.isSymbolicLink() || !stat.isFile()) {
@@ -14121,7 +14176,7 @@ function readSessionRenderSnapshot(snapshotPath) {
14121
14176
  }
14122
14177
  function reconstructPreRollbackLegacyV1Snapshot(snapshot, previousFiles, previousManifestFiles, targetHome, snapshotPath) {
14123
14178
  assertNoNewerSessionSnapshot(snapshotPath, snapshot.createdAt, targetHome);
14124
- const manifestPath = resolve10(snapshot.manifestPath);
14179
+ const manifestPath = resolve11(snapshot.manifestPath);
14125
14180
  const manifestRelativePath = relative5(targetHome, manifestPath).replaceAll("\\", "/");
14126
14181
  resolveSnapshotFilePath(manifestRelativePath, snapshot.manifestPath, targetHome);
14127
14182
  const manifestSha256 = currentSessionFileHash(manifestPath, targetHome);
@@ -14138,7 +14193,7 @@ function reconstructPreRollbackLegacyV1Snapshot(snapshot, previousFiles, previou
14138
14193
  throw new SessionApplyError(`Pre-rollback legacy v1 applied manifest is invalid: ${snapshotPath}`);
14139
14194
  }
14140
14195
  const appliedManifest = parsedManifest;
14141
- if (appliedManifest.schema !== SESSION_RENDER_SCHEMA || appliedManifest.tool !== snapshot.tool || appliedManifest.profile !== snapshot.profile || typeof appliedManifest.targetHome !== "string" || resolve10(appliedManifest.targetHome) !== targetHome || appliedManifest.targetKind !== "session-home" && appliedManifest.targetKind !== "project-root" || !Array.isArray(appliedManifest.files)) {
14196
+ if (appliedManifest.schema !== SESSION_RENDER_SCHEMA || appliedManifest.tool !== snapshot.tool || appliedManifest.profile !== snapshot.profile || typeof appliedManifest.targetHome !== "string" || resolve11(appliedManifest.targetHome) !== targetHome || appliedManifest.targetKind !== "session-home" && appliedManifest.targetKind !== "project-root" || !Array.isArray(appliedManifest.files)) {
14142
14197
  throw new SessionApplyError(`Pre-rollback legacy v1 applied manifest does not match its snapshot: ${snapshotPath}`);
14143
14198
  }
14144
14199
  const afterFiles = [];
@@ -14222,9 +14277,9 @@ function assertNoNewerSessionSnapshot(snapshotPath, createdAt, targetHome) {
14222
14277
  if (!Number.isFinite(createdAtMs)) {
14223
14278
  throw new SessionApplyError(`Pre-rollback legacy v1 snapshot has an invalid creation time: ${snapshotPath}`);
14224
14279
  }
14225
- for (const entry of readdirSync2(dirname9(snapshotPath))) {
14226
- const candidatePath = resolve10(dirname9(snapshotPath), entry);
14227
- if (candidatePath === resolve10(snapshotPath) || !entry.endsWith(".json"))
14280
+ for (const entry of readdirSync3(dirname10(snapshotPath))) {
14281
+ const candidatePath = resolve11(dirname10(snapshotPath), entry);
14282
+ if (candidatePath === resolve11(snapshotPath) || !entry.endsWith(".json"))
14228
14283
  continue;
14229
14284
  const candidateStat = lstatSync6(candidatePath);
14230
14285
  if (candidateStat.isSymbolicLink() || !candidateStat.isFile() || candidateStat.size > 32 * 1024 * 1024)
@@ -14232,7 +14287,7 @@ function assertNoNewerSessionSnapshot(snapshotPath, createdAt, targetHome) {
14232
14287
  try {
14233
14288
  const candidate = JSON.parse(readFileSync12(candidatePath, "utf8"));
14234
14289
  const candidateCreatedAtMs = typeof candidate.createdAt === "string" ? Date.parse(candidate.createdAt) : Number.NaN;
14235
- if ((candidate.schema === "hasna.configs.session-render-snapshot/v1" || candidate.schema === "hasna.configs.session-render-snapshot/v2") && typeof candidate.targetHome === "string" && resolve10(candidate.targetHome) === targetHome && Number.isFinite(candidateCreatedAtMs) && candidateCreatedAtMs >= createdAtMs) {
14290
+ if ((candidate.schema === "hasna.configs.session-render-snapshot/v1" || candidate.schema === "hasna.configs.session-render-snapshot/v2") && typeof candidate.targetHome === "string" && resolve11(candidate.targetHome) === targetHome && Number.isFinite(candidateCreatedAtMs) && candidateCreatedAtMs >= createdAtMs) {
14236
14291
  throw new SessionApplyError(`Cannot restore pre-rollback legacy v1 snapshot after a newer session snapshot exists: ${candidatePath}`);
14237
14292
  }
14238
14293
  } catch (error) {
@@ -14301,14 +14356,14 @@ function inferLegacySnapshotAction(file, previousFiles, previousManifestFiles, p
14301
14356
  }
14302
14357
  function resolveSnapshotFilePath(relativePath, recordedPath, targetHome) {
14303
14358
  const path = resolveManifestRelativePath(relativePath, targetHome);
14304
- if (resolve10(recordedPath) !== path) {
14359
+ if (resolve11(recordedPath) !== path) {
14305
14360
  throw new SessionApplyError(`Session snapshot file path mismatch for ${relativePath}`);
14306
14361
  }
14307
14362
  return path;
14308
14363
  }
14309
14364
  function planFileResult(plan, file, targetHome, previousHashes, previousManifest, options) {
14310
14365
  const target = resolvePlannedFilePath(plan, file, targetHome);
14311
- const previousContent = existsSync14(target) ? readFileSync12(target, "utf-8") : null;
14366
+ const previousContent = existsSync15(target) ? readFileSync12(target, "utf-8") : null;
14312
14367
  const previousSha256 = previousContent === null ? null : sha25610(previousContent);
14313
14368
  const previouslyManaged = isPreviouslyManaged(file, previousSha256, previousHashes, previousManifest);
14314
14369
  const changed = previousContent !== file.content;
@@ -14407,7 +14462,7 @@ function planStaleFileResults(plan, targetHome, previousManifest, currentRelativ
14407
14462
  }
14408
14463
  function planStaleFileResult(file, targetHome, options) {
14409
14464
  const target = resolveManifestRelativePath(file.relativePath, targetHome);
14410
- if (!existsSync14(target))
14465
+ if (!existsSync15(target))
14411
14466
  return null;
14412
14467
  const previousContent = readFileSync12(target, "utf-8");
14413
14468
  const previousSha256 = sha25610(previousContent);
@@ -14454,19 +14509,19 @@ function isPreviouslyManaged(file, previousSha256, previousHashes, previousManif
14454
14509
  return previousHashes.get(file.relativePath) === previousSha256;
14455
14510
  }
14456
14511
  function resolvePlannedFilePath(plan, file, targetHome) {
14457
- const target = resolve10(targetHome, ...file.relativePath.split("/"));
14512
+ const target = resolve11(targetHome, ...file.relativePath.split("/"));
14458
14513
  const rel = relative5(targetHome, target);
14459
14514
  if (rel === "" || rel === ".." || rel.startsWith("../") || isAbsolute4(rel)) {
14460
14515
  throw new SessionApplyError(`Session file escapes target home: ${file.relativePath}`);
14461
14516
  }
14462
- if (resolve10(file.path) !== target) {
14517
+ if (resolve11(file.path) !== target) {
14463
14518
  throw new SessionApplyError(`Session file path mismatch for ${file.relativePath}: ${file.path}`);
14464
14519
  }
14465
14520
  assertNoSymlinkSegments2(targetHome, target);
14466
14521
  return target;
14467
14522
  }
14468
14523
  function resolveManifestRelativePath(relativePath, targetHome) {
14469
- const target = resolve10(targetHome, ...relativePath.split(/[\\/]+/));
14524
+ const target = resolve11(targetHome, ...relativePath.split(/[\\/]+/));
14470
14525
  const rel = relative5(targetHome, target);
14471
14526
  if (rel === "" || rel === ".." || rel.startsWith("../") || isAbsolute4(rel)) {
14472
14527
  throw new SessionApplyError(`Session manifest file escapes target home: ${relativePath}`);
@@ -14475,7 +14530,7 @@ function resolveManifestRelativePath(relativePath, targetHome) {
14475
14530
  return target;
14476
14531
  }
14477
14532
  function readPreviousManifest(path) {
14478
- if (!existsSync14(path))
14533
+ if (!existsSync15(path))
14479
14534
  return null;
14480
14535
  try {
14481
14536
  const parsed = JSON.parse(readFileSync12(path, "utf-8"));
@@ -14517,7 +14572,7 @@ function assertExpectedSessionFileHash(path, targetHome, expectedHash) {
14517
14572
  }
14518
14573
  function currentSessionFileHash(path, targetHome) {
14519
14574
  assertNoSymlinkSegments2(targetHome, path);
14520
- if (!existsSync14(path))
14575
+ if (!existsSync15(path))
14521
14576
  return null;
14522
14577
  const stat = lstatSync6(path);
14523
14578
  if (stat.isSymbolicLink() || !stat.isFile()) {
@@ -14532,7 +14587,7 @@ function requiredPreviousHash(result) {
14532
14587
  return result.previousSha256;
14533
14588
  }
14534
14589
  function writeSessionSnapshot(plan, targetHome, manifestPath, results, previousManifest, coordination, allowPortableFallback, forcePortableFileOps) {
14535
- const existingFiles = results.filter((result) => result.action === "update" || result.action === "delete").filter((result) => existsSync14(result.path)).map((result) => {
14590
+ const existingFiles = results.filter((result) => result.action === "update" || result.action === "delete").filter((result) => existsSync15(result.path)).map((result) => {
14536
14591
  const content = readFileSync12(result.path, "utf-8");
14537
14592
  return {
14538
14593
  path: result.path,
@@ -14551,7 +14606,7 @@ function writeSessionSnapshot(plan, targetHome, manifestPath, results, previousM
14551
14606
  };
14552
14607
  }
14553
14608
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
14554
- const snapshotPath = resolve10(targetHome, ".hasna", "session-render-snapshots", `${timestamp}-${randomUUID4()}.json`);
14609
+ const snapshotPath = join16(getSessionRenderSnapshotDir(targetHome), `${timestamp}-${randomUUID4()}.json`);
14555
14610
  const afterFiles = results.map((result) => {
14556
14611
  if (result.action === "conflict") {
14557
14612
  throw new SessionApplyError(`Cannot snapshot unresolved conflict: ${result.relativePath}`);
@@ -14581,7 +14636,7 @@ function writeSessionSnapshot(plan, targetHome, manifestPath, results, previousM
14581
14636
  path: snapshotPath,
14582
14637
  content: `${JSON.stringify(snapshot, null, 2)}
14583
14638
  `,
14584
- workspace_root: targetHome,
14639
+ workspace_root: sessionRenderSnapshotWorkspaceRoot(targetHome),
14585
14640
  default_mode: 384,
14586
14641
  expected_hash: null,
14587
14642
  max_observed_bytes: null,
@@ -14599,12 +14654,12 @@ function writeSessionSnapshot(plan, targetHome, manifestPath, results, previousM
14599
14654
  function assertSafeTargetHome(targetHome) {
14600
14655
  if (!isAbsolute4(targetHome))
14601
14656
  throw new SessionApplyError(`Session target home must be absolute: ${targetHome}`);
14602
- const normalized = resolve10(targetHome);
14657
+ const normalized = resolve11(targetHome);
14603
14658
  if (normalized === parse5(normalized).root) {
14604
14659
  throw new SessionApplyError(`Session target home cannot be the filesystem root: ${targetHome}`);
14605
14660
  }
14606
14661
  assertNoSymlinkAncestors3(normalized);
14607
- if (existsSync14(normalized) && lstatSync6(normalized).isSymbolicLink()) {
14662
+ if (existsSync15(normalized) && lstatSync6(normalized).isSymbolicLink()) {
14608
14663
  throw new SessionApplyError(`Session target home cannot be a symlink: ${normalized}`);
14609
14664
  }
14610
14665
  return normalized;
@@ -14614,20 +14669,20 @@ function assertNoSymlinkSegments2(root, target) {
14614
14669
  const rel = relative5(root, target);
14615
14670
  let current = root;
14616
14671
  for (const segment of rel.split(/[\\/]+/).filter(Boolean)) {
14617
- current = join15(current, segment);
14618
- if (existsSync14(current) && lstatSync6(current).isSymbolicLink()) {
14672
+ current = join16(current, segment);
14673
+ if (existsSync15(current) && lstatSync6(current).isSymbolicLink()) {
14619
14674
  throw new SessionApplyError(`Session apply path uses a symlink: ${current}`);
14620
14675
  }
14621
14676
  }
14622
14677
  }
14623
14678
  function assertNoSymlinkAncestors3(path) {
14624
- const normalized = resolve10(path);
14679
+ const normalized = resolve11(path);
14625
14680
  const parsed = parse5(normalized);
14626
14681
  let current = parsed.root;
14627
14682
  const rel = relative5(parsed.root, normalized);
14628
14683
  for (const segment of rel.split(/[\\/]+/).filter(Boolean)) {
14629
- current = join15(current, segment);
14630
- if (!existsSync14(current))
14684
+ current = join16(current, segment);
14685
+ if (!existsSync15(current))
14631
14686
  return;
14632
14687
  if (lstatSync6(current).isSymbolicLink()) {
14633
14688
  throw new SessionApplyError(`Session apply path uses a symlink ancestor: ${current}`);
@@ -14938,13 +14993,13 @@ async function ensureDangerousOperationGuardStandardConfig(store = resolveConfig
14938
14993
  }
14939
14994
  }
14940
14995
  // src/lib/sync.ts
14941
- import { existsSync as existsSync16, readdirSync as readdirSync4, readFileSync as readFileSync14 } from "fs";
14942
- import { basename as basename6, extname as extname3, join as join17 } from "path";
14996
+ import { existsSync as existsSync17, readdirSync as readdirSync5, readFileSync as readFileSync14 } from "fs";
14997
+ import { basename as basename6, extname as extname3, join as join18 } from "path";
14943
14998
 
14944
14999
  // src/lib/sync-dir.ts
14945
- import { existsSync as existsSync15, readdirSync as readdirSync3, readFileSync as readFileSync13, statSync as statSync6 } from "fs";
14946
- import { join as join16, relative as relative6 } from "path";
14947
- import { homedir as homedir10 } from "os";
15000
+ import { existsSync as existsSync16, readdirSync as readdirSync4, readFileSync as readFileSync13, statSync as statSync6 } from "fs";
15001
+ import { join as join17, relative as relative6 } from "path";
15002
+ import { homedir as homedir11 } from "os";
14948
15003
  var SKIP = [".db", ".db-shm", ".db-wal", ".log", ".lock", ".DS_Store", "node_modules", ".git"];
14949
15004
  function shouldSkip(p) {
14950
15005
  return SKIP.some((s) => p.includes(s));
@@ -14952,11 +15007,11 @@ function shouldSkip(p) {
14952
15007
  async function syncFromDir(dir, opts = {}) {
14953
15008
  const store = opts.store ?? resolveConfigStore();
14954
15009
  const absDir = expandPath(dir);
14955
- if (!existsSync15(absDir))
15010
+ if (!existsSync16(absDir))
14956
15011
  return { added: 0, updated: 0, unchanged: 0, skipped: [`Not found: ${absDir}`] };
14957
- const files = opts.recursive !== false ? walkDir(absDir) : readdirSync3(absDir).map((f) => join16(absDir, f)).filter((f) => statSync6(f).isFile());
15012
+ const files = opts.recursive !== false ? walkDir(absDir) : readdirSync4(absDir).map((f) => join17(absDir, f)).filter((f) => statSync6(f).isFile());
14958
15013
  const result = { added: 0, updated: 0, unchanged: 0, skipped: [] };
14959
- const home = homedir10();
15014
+ const home = homedir11();
14960
15015
  const allConfigs = await store.listConfigs();
14961
15016
  for (const file of files) {
14962
15017
  if (shouldSkip(file)) {
@@ -14991,7 +15046,7 @@ async function syncFromDir(dir, opts = {}) {
14991
15046
  }
14992
15047
  async function syncToDir(dir, opts = {}) {
14993
15048
  const store = opts.store ?? resolveConfigStore();
14994
- const home = homedir10();
15049
+ const home = homedir11();
14995
15050
  const absDir = expandPath(dir);
14996
15051
  const normalized = dir.startsWith("~/") ? dir : absDir.replace(home, "~");
14997
15052
  const configs = (await store.listConfigs()).filter((c) => c.target_path && (c.target_path.startsWith(normalized) || c.target_path.startsWith(absDir)));
@@ -15014,8 +15069,8 @@ async function syncToDir(dir, opts = {}) {
15014
15069
  return result;
15015
15070
  }
15016
15071
  function walkDir(dir, files = []) {
15017
- for (const entry of readdirSync3(dir, { withFileTypes: true })) {
15018
- const full = join16(dir, entry.name);
15072
+ for (const entry of readdirSync4(dir, { withFileTypes: true })) {
15073
+ const full = join17(dir, entry.name);
15019
15074
  if (shouldSkip(full))
15020
15075
  continue;
15021
15076
  if (entry.isDirectory())
@@ -15076,7 +15131,7 @@ function isGeneratedOutputTarget2(config, owners) {
15076
15131
  return !!ownerIds && !ownerIds.has(config.id);
15077
15132
  }
15078
15133
  function hasClaudePromptSource() {
15079
- return existsSync16(expandPath("~/.claude/CLAUDE.md"));
15134
+ return existsSync17(expandPath("~/.claude/CLAUDE.md"));
15080
15135
  }
15081
15136
  function hasClaudeRuleSourceForCursorTarget(targetPath) {
15082
15137
  const absoluteTargetPath = expandPath(targetPath);
@@ -15084,7 +15139,7 @@ function hasClaudeRuleSourceForCursorTarget(targetPath) {
15084
15139
  if (!absoluteTargetPath.startsWith(`${absolutePrefix}/`) || !absoluteTargetPath.endsWith(".mdc"))
15085
15140
  return false;
15086
15141
  const stem = basename6(absoluteTargetPath, ".mdc");
15087
- return existsSync16(expandPath(`~/.claude/rules/${stem}.md`)) || existsSync16(expandPath(`~/.claude/rules/${stem}.mdc`));
15142
+ return existsSync17(expandPath(`~/.claude/rules/${stem}.md`)) || existsSync17(expandPath(`~/.claude/rules/${stem}.mdc`));
15088
15143
  }
15089
15144
  function isKnownGeneratedTargetPath(targetPath) {
15090
15145
  const normalizedTargetPath = normalizeTargetPath(targetPath);
@@ -15149,8 +15204,8 @@ async function syncProject(opts) {
15149
15204
  const allConfigs = await store.listConfigs();
15150
15205
  const machine = detectMachineContext();
15151
15206
  for (const pf of PROJECT_CONFIG_FILES) {
15152
- const abs = join17(absDir, pf.file);
15153
- if (!existsSync16(abs))
15207
+ const abs = join18(absDir, pf.file);
15208
+ if (!existsSync17(abs))
15154
15209
  continue;
15155
15210
  try {
15156
15211
  const rawContent = readFileSync14(abs, "utf-8");
@@ -15182,19 +15237,19 @@ async function syncProject(opts) {
15182
15237
  }
15183
15238
  }
15184
15239
  for (const ruleDir of [
15185
- { dir: join17(absDir, ".claude", "rules"), agent: "claude", namePrefix: "rules" },
15186
- { dir: join17(absDir, ".agents", "rules"), agent: "antigravity", namePrefix: "antigravity-rules" },
15187
- { dir: join17(absDir, ".cursor", "rules"), agent: "cursor", namePrefix: "cursor-rules" },
15188
- { dir: join17(absDir, ".github", "instructions"), agent: "copilot", namePrefix: "copilot-instructions" },
15189
- { dir: join17(absDir, ".devin", "rules"), agent: "devin", namePrefix: "devin-rules" },
15190
- { dir: join17(absDir, ".windsurf", "rules"), agent: "windsurf-legacy", namePrefix: "windsurf-rules" },
15191
- { dir: join17(absDir, ".clinerules"), agent: "cline", namePrefix: "cline-rules" }
15240
+ { dir: join18(absDir, ".claude", "rules"), agent: "claude", namePrefix: "rules" },
15241
+ { dir: join18(absDir, ".agents", "rules"), agent: "antigravity", namePrefix: "antigravity-rules" },
15242
+ { dir: join18(absDir, ".cursor", "rules"), agent: "cursor", namePrefix: "cursor-rules" },
15243
+ { dir: join18(absDir, ".github", "instructions"), agent: "copilot", namePrefix: "copilot-instructions" },
15244
+ { dir: join18(absDir, ".devin", "rules"), agent: "devin", namePrefix: "devin-rules" },
15245
+ { dir: join18(absDir, ".windsurf", "rules"), agent: "windsurf-legacy", namePrefix: "windsurf-rules" },
15246
+ { dir: join18(absDir, ".clinerules"), agent: "cline", namePrefix: "cline-rules" }
15192
15247
  ]) {
15193
- if (!existsSync16(ruleDir.dir))
15248
+ if (!existsSync17(ruleDir.dir))
15194
15249
  continue;
15195
- const mdFiles = readdirSync4(ruleDir.dir).filter((f) => f.endsWith(".md") || f.endsWith(".mdc"));
15250
+ const mdFiles = readdirSync5(ruleDir.dir).filter((f) => f.endsWith(".md") || f.endsWith(".mdc"));
15196
15251
  for (const f of mdFiles) {
15197
- const abs = join17(ruleDir.dir, f);
15252
+ const abs = join18(ruleDir.dir, f);
15198
15253
  const raw = readFileSync14(abs, "utf-8");
15199
15254
  const redacted = redactContent(raw, "markdown");
15200
15255
  const machineAware = templateizeMachineContent(redacted.content, machine);
@@ -15234,14 +15289,14 @@ async function syncKnown(opts = {}) {
15234
15289
  for (const known of targets) {
15235
15290
  if (known.rulesDir) {
15236
15291
  const absDir = expandPath(known.rulesDir);
15237
- if (!existsSync16(absDir)) {
15292
+ if (!existsSync17(absDir)) {
15238
15293
  result.skipped.push(known.rulesDir);
15239
15294
  continue;
15240
15295
  }
15241
15296
  const extensions = known.rulesExtensions ?? [".md", ".mdc"];
15242
- const ruleFiles = readdirSync4(absDir).filter((f) => extensions.some((ext) => f.endsWith(ext)));
15297
+ const ruleFiles = readdirSync5(absDir).filter((f) => extensions.some((ext) => f.endsWith(ext)));
15243
15298
  for (const f of ruleFiles) {
15244
- const abs2 = join17(absDir, f);
15299
+ const abs2 = join18(absDir, f);
15245
15300
  const targetPath = abs2.replace(home, "~");
15246
15301
  if (existingOutputOwners.has(normalizeTargetPath(targetPath)) || isKnownGeneratedTargetPath(targetPath)) {
15247
15302
  result.skipped.push(`${targetPath} (generated output)`);
@@ -15275,7 +15330,7 @@ async function syncKnown(opts = {}) {
15275
15330
  continue;
15276
15331
  }
15277
15332
  const abs = expandPath(known.path);
15278
- if (!existsSync16(abs)) {
15333
+ if (!existsSync17(abs)) {
15279
15334
  result.skipped.push(known.path);
15280
15335
  continue;
15281
15336
  }
@@ -15383,7 +15438,7 @@ function storedPlaceholderIsLiteralOnDisk(storedLine, diskLine) {
15383
15438
  }
15384
15439
  function buildDiff(expectedContent, targetPath, storedFormat, showSecrets) {
15385
15440
  const path = expandPath(targetPath);
15386
- if (!existsSync16(path))
15441
+ if (!existsSync17(path))
15387
15442
  return `(file not found on disk: ${path})`;
15388
15443
  const diskContent = readFileSync14(path, "utf-8");
15389
15444
  if (diskContent === expectedContent)
@@ -15543,15 +15598,15 @@ function detectFormat(filePath) {
15543
15598
  return "text";
15544
15599
  }
15545
15600
  // src/lib/export.ts
15546
- import { existsSync as existsSync17, mkdirSync as mkdirSync8, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "fs";
15547
- import { join as join18, resolve as resolve11 } from "path";
15601
+ import { existsSync as existsSync18, mkdirSync as mkdirSync8, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "fs";
15602
+ import { join as join19, resolve as resolve12 } from "path";
15548
15603
  import { tmpdir } from "os";
15549
15604
  async function exportConfigs(outputPath, opts = {}) {
15550
15605
  const store = opts.store ?? resolveConfigStore();
15551
15606
  const configs = await store.listConfigs(opts.filter);
15552
- const absOutput = resolve11(outputPath);
15553
- const tmpDir = join18(tmpdir(), `configs-export-${Date.now()}`);
15554
- const contentsDir = join18(tmpDir, "contents");
15607
+ const absOutput = resolve12(outputPath);
15608
+ const tmpDir = join19(tmpdir(), `configs-export-${Date.now()}`);
15609
+ const contentsDir = join19(tmpDir, "contents");
15555
15610
  try {
15556
15611
  mkdirSync8(contentsDir, { recursive: true });
15557
15612
  const manifest = {
@@ -15559,10 +15614,10 @@ async function exportConfigs(outputPath, opts = {}) {
15559
15614
  exported_at: new Date().toISOString(),
15560
15615
  configs: configs.map(({ content: _content, ...meta }) => meta)
15561
15616
  };
15562
- writeFileSync6(join18(tmpDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
15617
+ writeFileSync6(join19(tmpDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
15563
15618
  for (const config of configs) {
15564
15619
  const fileName = `${config.slug}.${config.format === "text" ? "txt" : config.format}`;
15565
- writeFileSync6(join18(contentsDir, fileName), config.content, "utf-8");
15620
+ writeFileSync6(join19(contentsDir, fileName), config.content, "utf-8");
15566
15621
  }
15567
15622
  const proc = Bun.spawn(["tar", "czf", absOutput, "-C", tmpDir, "."], {
15568
15623
  stdout: "pipe",
@@ -15575,20 +15630,20 @@ async function exportConfigs(outputPath, opts = {}) {
15575
15630
  }
15576
15631
  return { path: absOutput, count: configs.length };
15577
15632
  } finally {
15578
- if (existsSync17(tmpDir)) {
15633
+ if (existsSync18(tmpDir)) {
15579
15634
  rmSync4(tmpDir, { recursive: true, force: true });
15580
15635
  }
15581
15636
  }
15582
15637
  }
15583
15638
  // src/lib/import.ts
15584
- import { existsSync as existsSync18, mkdirSync as mkdirSync9, readFileSync as readFileSync15, rmSync as rmSync5 } from "fs";
15585
- import { join as join19, resolve as resolve12 } from "path";
15639
+ import { existsSync as existsSync19, mkdirSync as mkdirSync9, readFileSync as readFileSync15, rmSync as rmSync5 } from "fs";
15640
+ import { join as join20, resolve as resolve13 } from "path";
15586
15641
  import { tmpdir as tmpdir2 } from "os";
15587
15642
  async function importConfigs(bundlePath, opts = {}) {
15588
15643
  const store = opts.store ?? resolveConfigStore();
15589
15644
  const conflict = opts.conflict ?? "skip";
15590
- const absPath = resolve12(bundlePath);
15591
- const tmpDir = join19(tmpdir2(), `configs-import-${Date.now()}`);
15645
+ const absPath = resolve13(bundlePath);
15646
+ const tmpDir = join20(tmpdir2(), `configs-import-${Date.now()}`);
15592
15647
  const result = { created: 0, updated: 0, skipped: 0, errors: [] };
15593
15648
  try {
15594
15649
  mkdirSync9(tmpDir, { recursive: true });
@@ -15601,15 +15656,15 @@ async function importConfigs(bundlePath, opts = {}) {
15601
15656
  const stderr = await new Response(proc.stderr).text();
15602
15657
  throw new Error(`tar extraction failed: ${stderr}`);
15603
15658
  }
15604
- const manifestPath = join19(tmpDir, "manifest.json");
15605
- if (!existsSync18(manifestPath))
15659
+ const manifestPath = join20(tmpDir, "manifest.json");
15660
+ if (!existsSync19(manifestPath))
15606
15661
  throw new Error("Invalid bundle: missing manifest.json");
15607
15662
  const manifest = JSON.parse(readFileSync15(manifestPath, "utf-8"));
15608
15663
  for (const meta of manifest.configs) {
15609
15664
  try {
15610
15665
  const ext = meta.format === "text" ? "txt" : meta.format;
15611
- const contentFile = join19(tmpDir, "contents", `${meta.slug}.${ext}`);
15612
- const content = existsSync18(contentFile) ? readFileSync15(contentFile, "utf-8") : "";
15666
+ const contentFile = join20(tmpDir, "contents", `${meta.slug}.${ext}`);
15667
+ const content = existsSync19(contentFile) ? readFileSync15(contentFile, "utf-8") : "";
15613
15668
  let existing = null;
15614
15669
  try {
15615
15670
  existing = await store.getConfig(meta.slug);
@@ -15643,16 +15698,16 @@ async function importConfigs(bundlePath, opts = {}) {
15643
15698
  }
15644
15699
  return result;
15645
15700
  } finally {
15646
- if (existsSync18(tmpDir)) {
15701
+ if (existsSync19(tmpDir)) {
15647
15702
  rmSync5(tmpDir, { recursive: true, force: true });
15648
15703
  }
15649
15704
  }
15650
15705
  }
15651
15706
  // src/lib/package-manager-guard.ts
15652
15707
  import { execFileSync as execFileSync2 } from "child_process";
15653
- import { existsSync as existsSync19, lstatSync as lstatSync7, readdirSync as readdirSync5, readFileSync as readFileSync16 } from "fs";
15654
- import { homedir as homedir11 } from "os";
15655
- import { basename as basename7, dirname as dirname10, isAbsolute as isAbsolute5, join as join20, relative as relative7, resolve as resolve13 } from "path";
15708
+ import { existsSync as existsSync20, lstatSync as lstatSync7, readdirSync as readdirSync6, readFileSync as readFileSync16 } from "fs";
15709
+ import { homedir as homedir12 } from "os";
15710
+ import { basename as basename7, dirname as dirname11, isAbsolute as isAbsolute5, join as join21, relative as relative7, resolve as resolve14 } from "path";
15656
15711
  var SKIP_DIRS = new Set([
15657
15712
  ".git",
15658
15713
  "node_modules",
@@ -15689,12 +15744,12 @@ var TOKEN_VALUE_PATTERNS = [
15689
15744
  { re: /xoxb-[0-9]+-[A-Za-z0-9-]+/, rule: "literal-slack-token", detail: "literal Slack token-like value" }
15690
15745
  ];
15691
15746
  function scanPackageManagerSecrets(options = {}) {
15692
- const cwd = options.cwd ? resolve13(options.cwd) : process.cwd();
15693
- const roots = (options.roots && options.roots.length > 0 ? options.roots : [cwd]).map((root) => resolve13(cwd, root));
15747
+ const cwd = options.cwd ? resolve14(options.cwd) : process.cwd();
15748
+ const roots = (options.roots && options.roots.length > 0 ? options.roots : [cwd]).map((root) => resolve14(cwd, root));
15694
15749
  const findings = [];
15695
15750
  let scannedFiles = 0;
15696
15751
  for (const root of roots) {
15697
- if (!existsSync19(root))
15752
+ if (!existsSync20(root))
15698
15753
  continue;
15699
15754
  const stat = lstatSync7(root);
15700
15755
  if (stat.isFile()) {
@@ -15704,7 +15759,7 @@ function scanPackageManagerSecrets(options = {}) {
15704
15759
  if (text === null)
15705
15760
  continue;
15706
15761
  scannedFiles++;
15707
- findings.push(...scanFile(root, text, classifyRepoFile(root), isTrackedFile(root), dirname10(root)));
15762
+ findings.push(...scanFile(root, text, classifyRepoFile(root), isTrackedFile(root), dirname11(root)));
15708
15763
  continue;
15709
15764
  }
15710
15765
  if (!stat.isDirectory())
@@ -15721,10 +15776,10 @@ function scanPackageManagerSecrets(options = {}) {
15721
15776
  }
15722
15777
  }
15723
15778
  if (options.includeHome) {
15724
- const home = homedir11();
15779
+ const home = homedir12();
15725
15780
  for (const name of HOME_FILES) {
15726
- const file = join20(home, name);
15727
- if (!existsSync19(file))
15781
+ const file = join21(home, name);
15782
+ if (!existsSync20(file))
15728
15783
  continue;
15729
15784
  const text = readTextFile(file);
15730
15785
  if (text === null)
@@ -15744,16 +15799,16 @@ function scanPackageManagerSecrets(options = {}) {
15744
15799
  function collectRepoFiles(root) {
15745
15800
  const out = [];
15746
15801
  const visit = (dir) => {
15747
- for (const entry of readdirSync5(dir, { withFileTypes: true })) {
15802
+ for (const entry of readdirSync6(dir, { withFileTypes: true })) {
15748
15803
  if (entry.isDirectory()) {
15749
15804
  if (SKIP_DIRS.has(entry.name))
15750
15805
  continue;
15751
- visit(join20(dir, entry.name));
15806
+ visit(join21(dir, entry.name));
15752
15807
  continue;
15753
15808
  }
15754
15809
  if (!entry.isFile())
15755
15810
  continue;
15756
- const file = join20(dir, entry.name);
15811
+ const file = join21(dir, entry.name);
15757
15812
  if (shouldScanRepoFile(file))
15758
15813
  out.push(file);
15759
15814
  }
@@ -15991,7 +16046,7 @@ function trackedFiles(root) {
15991
16046
  }
15992
16047
  function isTrackedFile(file) {
15993
16048
  try {
15994
- const repoRoot = execFileSync2("git", ["-C", dirname10(file), "rev-parse", "--show-toplevel"], {
16049
+ const repoRoot = execFileSync2("git", ["-C", dirname11(file), "rev-parse", "--show-toplevel"], {
15995
16050
  encoding: "utf-8",
15996
16051
  stdio: ["ignore", "pipe", "ignore"]
15997
16052
  }).trim();
@@ -16021,7 +16076,7 @@ function stripInlineComment(value) {
16021
16076
  return value.replace(/\s[#;].*$/, "").trim();
16022
16077
  }
16023
16078
  function displayPath(file, root) {
16024
- const home = homedir11();
16079
+ const home = homedir12();
16025
16080
  if (root === home && (file === home || file.startsWith(home + "/")))
16026
16081
  return "~/" + toPosix(relative7(home, file));
16027
16082
  if (isAbsolute5(root) && file.startsWith(root + "/"))