@hasna/instructions 0.5.2 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -103,8 +103,8 @@ import { randomUUID as randomUUID3 } from "crypto";
103
103
 
104
104
  // src/db/database.ts
105
105
  import { Database } from "bun:sqlite";
106
- import { existsSync, mkdirSync, rmSync } from "fs";
107
- import { join as join2 } from "path";
106
+ import { existsSync as existsSync2, mkdirSync, rmSync } from "fs";
107
+ import { join as join3 } from "path";
108
108
  import { randomUUID } from "crypto";
109
109
 
110
110
  // src/lib/retired-storage-mode.ts
@@ -129,11 +129,111 @@ function assertNoLegacyStorageMode(env = process.env) {
129
129
  }
130
130
 
131
131
  // src/lib/raw-store-root.ts
132
+ import { resolve as resolve2 } from "path";
133
+
134
+ // src/lib/app-home.ts
135
+ import { existsSync } from "fs";
136
+ import { homedir as homedir2 } from "os";
137
+ import { join as join2, resolve } from "path";
138
+
139
+ // ../../node_modules/.bun/@hasna+paths@0.1.0/node_modules/@hasna/paths/dist/index.js
132
140
  import { homedir } from "os";
133
- import { join, resolve } from "path";
141
+ import { join } from "path";
142
+ var KIND_ENV = {
143
+ config: "HASNA_CONFIG_HOME",
144
+ data: "HASNA_DATA_HOME",
145
+ state: "HASNA_STATE_HOME",
146
+ cache: "HASNA_CACHE_HOME"
147
+ };
148
+ var APP_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
149
+ function assertApp(app) {
150
+ if (typeof app !== "string" || app.length === 0) {
151
+ throw new TypeError("paths: app must be a non-empty string");
152
+ }
153
+ if (!APP_SLUG_RE.test(app)) {
154
+ throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
155
+ }
156
+ }
157
+ function envOf(options) {
158
+ return options.env ?? process.env;
159
+ }
160
+ function envValue(options, kind) {
161
+ const value = envOf(options)[KIND_ENV[kind]];
162
+ return typeof value === "string" && value.length > 0 ? value : undefined;
163
+ }
164
+ function isMacOS(platform) {
165
+ return platform === "darwin";
166
+ }
167
+ function baseDir(kind, options) {
168
+ const override = envValue(options, kind);
169
+ if (override)
170
+ return override;
171
+ const home = options.home ?? homedir();
172
+ const platform = options.platform ?? process.platform;
173
+ if (isMacOS(platform)) {
174
+ switch (kind) {
175
+ case "config":
176
+ case "data":
177
+ return join(home, "Library", "Application Support", "Hasna");
178
+ case "cache":
179
+ return join(home, "Library", "Caches", "Hasna");
180
+ case "state":
181
+ return join(home, "Library", "Logs", "Hasna");
182
+ }
183
+ }
184
+ switch (kind) {
185
+ case "config":
186
+ return join(home, ".config", "hasna");
187
+ case "data":
188
+ return join(home, ".local", "share", "hasna");
189
+ case "state":
190
+ return join(home, ".local", "state", "hasna");
191
+ case "cache":
192
+ return join(home, ".cache", "hasna");
193
+ }
194
+ }
195
+ function resolvePath(kind, options) {
196
+ assertApp(options.app);
197
+ const appSegment = options.internal === true ? join("internal", options.app) : options.app;
198
+ return join(baseDir(kind, options), appSegment);
199
+ }
200
+ function configDir(options) {
201
+ return resolvePath("config", options);
202
+ }
203
+
204
+ // src/lib/app-home.ts
205
+ var HASNA_CONFIGS_HOME_ENV = "HASNA_CONFIGS_HOME";
206
+ function homeDir(env = process.env) {
207
+ return env["HOME"] || env["USERPROFILE"] || homedir2();
208
+ }
209
+ function legacyStoreHome(env = process.env) {
210
+ return resolve(join2(homeDir(env), ".hasna", "instructions"));
211
+ }
212
+ function resolverStoreHome(env = process.env) {
213
+ return configDir({ app: "configs", env, home: env.HOME || env.USERPROFILE || homedir2() });
214
+ }
215
+ function adoptResolverStoreHome(resolved, env = process.env) {
216
+ const override = env.HASNA_CONFIG_HOME;
217
+ if (typeof override === "string" && override.trim().length > 0)
218
+ return true;
219
+ return existsSync(join2(resolved, "instructions.db"));
220
+ }
221
+ function exactStoreHome(env = process.env) {
222
+ const v = env[HASNA_CONFIGS_HOME_ENV];
223
+ return v && v.trim() ? v.trim() : undefined;
224
+ }
225
+ function getConfigsStoreHome(env = process.env) {
226
+ const exact = exactStoreHome(env);
227
+ if (exact)
228
+ return resolve(exact);
229
+ const resolved = resolverStoreHome(env);
230
+ return adoptResolverStoreHome(resolved, env) ? resolve(resolved) : legacyStoreHome(env);
231
+ }
232
+
233
+ // src/lib/raw-store-root.ts
134
234
  var RAW_STORE_ROOT_ENV = "HASNA_CONFIGS_HOME";
135
- function getRawStoreRoot() {
136
- return resolve(process.env[RAW_STORE_ROOT_ENV] || join(process.env["HOME"] || homedir(), ".hasna", "instructions"));
235
+ function getRawStoreRoot(env = process.env) {
236
+ return resolve2(getConfigsStoreHome(env));
137
237
  }
138
238
 
139
239
  // src/db/database.ts
@@ -143,7 +243,7 @@ function getDbPath() {
143
243
  }
144
244
  const dir = getRawStoreRoot();
145
245
  mkdirSync(dir, { recursive: true });
146
- return join2(dir, "instructions.db");
246
+ return join3(dir, "instructions.db");
147
247
  }
148
248
  function uuid() {
149
249
  return randomUUID();
@@ -267,7 +367,7 @@ function resetLocalDatabase() {
267
367
  if (dbPath === ":memory:")
268
368
  return;
269
369
  for (const p of [dbPath, `${dbPath}-wal`, `${dbPath}-shm`]) {
270
- if (existsSync(p))
370
+ if (existsSync2(p))
271
371
  rmSync(p);
272
372
  }
273
373
  }
@@ -539,9 +639,9 @@ function getConfigStats(db) {
539
639
  }
540
640
 
541
641
  // src/lib/machine.ts
542
- import { arch as currentArch, homedir as homedir2, hostname as currentHostname, type as currentOsType } from "os";
543
- import { existsSync as existsSync2 } from "fs";
544
- import { join as join3 } from "path";
642
+ import { arch as currentArch, homedir as homedir3, hostname as currentHostname, type as currentOsType } from "os";
643
+ import { existsSync as existsSync3 } from "fs";
644
+ import { join as join4 } from "path";
545
645
 
546
646
  // src/lib/template.ts
547
647
  var VAR_PATTERN = /\{\{([A-Z0-9_]+)(?::([^}]*))?\}\}/g;
@@ -614,11 +714,11 @@ function normalizeOsFamily(os) {
614
714
  return value || "unknown";
615
715
  }
616
716
  function detectMachineContext(overrides = {}) {
617
- const homeDir = overrides.home_dir ?? process.env["CONFIGS_HOME"] ?? process.env["HOME"] ?? homedir2();
717
+ const homeDir2 = overrides.home_dir ?? process.env["CONFIGS_HOME"] ?? process.env["HOME"] ?? homedir3();
618
718
  const os = overrides.os ?? currentOsType();
619
719
  const osFamily = normalizeOsFamily(os);
620
- const bunBinDir = overrides.bun_bin_dir ?? join3(homeDir, ".bun", "bin");
621
- const defaultBunPath = osFamily === "macos" && existsSync2(BREW_BUN_PATH) ? BREW_BUN_PATH : join3(bunBinDir, "bun");
720
+ const bunBinDir = overrides.bun_bin_dir ?? join4(homeDir2, ".bun", "bin");
721
+ const defaultBunPath = osFamily === "macos" && existsSync3(BREW_BUN_PATH) ? BREW_BUN_PATH : join4(bunBinDir, "bun");
622
722
  return {
623
723
  id: "current-machine",
624
724
  hostname: overrides.hostname ?? currentHostname(),
@@ -627,11 +727,11 @@ function detectMachineContext(overrides = {}) {
627
727
  last_applied_at: null,
628
728
  created_at: "",
629
729
  os_family: osFamily,
630
- home_dir: homeDir,
631
- workspace_root: overrides.workspace_root ?? join3(homeDir, osFamily === "macos" ? "Workspace" : "workspace"),
730
+ home_dir: homeDir2,
731
+ workspace_root: overrides.workspace_root ?? join4(homeDir2, osFamily === "macos" ? "Workspace" : "workspace"),
632
732
  bun_bin_dir: bunBinDir,
633
733
  bun_path: overrides.bun_path ?? defaultBunPath,
634
- path_prefix: overrides.path_prefix ?? (osFamily === "macos" ? `${join3("/opt", "homebrew", "bin")}:${bunBinDir}` : bunBinDir)
734
+ path_prefix: overrides.path_prefix ?? (osFamily === "macos" ? `${join4("/opt", "homebrew", "bin")}:${bunBinDir}` : bunBinDir)
635
735
  };
636
736
  }
637
737
  function machineContextToVariables(machine) {
@@ -749,9 +849,9 @@ import { createHash as createHash7 } from "crypto";
749
849
 
750
850
  // src/lib/session-render.ts
751
851
  import { createHash as createHash6 } from "crypto";
752
- import { existsSync as existsSync5, readFileSync as readFileSync4, realpathSync as realpathSync2, statSync as statSync3 } from "fs";
753
- import { homedir as homedir5 } from "os";
754
- import { basename as basename4, dirname as dirname3, extname as extname2, isAbsolute as isAbsolute3, join as join7, parse as parse2, posix as posix2, relative as relative2, resolve as resolve6 } from "path";
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";
755
855
 
756
856
  // src/lib/global-agent-rules-standard.ts
757
857
  import { createHash } from "crypto";
@@ -1064,7 +1164,7 @@ import { dlopen, FFIType } from "bun:ffi";
1064
1164
  import {
1065
1165
  closeSync,
1066
1166
  constants,
1067
- existsSync as existsSync3,
1167
+ existsSync as existsSync4,
1068
1168
  fstatSync,
1069
1169
  fsyncSync,
1070
1170
  lstatSync,
@@ -1077,7 +1177,7 @@ import {
1077
1177
  statSync,
1078
1178
  writeFileSync
1079
1179
  } from "fs";
1080
- import { basename, dirname, isAbsolute, join as join4, parse, relative, resolve as resolve2 } from "path";
1180
+ import { basename, dirname, isAbsolute, join as join5, parse, relative, resolve as resolve3 } from "path";
1081
1181
 
1082
1182
  // ../../node_modules/.bun/zod@3.25.76/node_modules/zod/v3/external.js
1083
1183
  var exports_external = {};
@@ -5573,7 +5673,7 @@ function planProjectContext(input) {
5573
5673
  const inlineMarkerOverhead = nativeImports ? 0 : Buffer.byteLength(buildManagedBlock(bundle, "", `
5574
5674
  `), "utf8");
5575
5675
  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)));
5576
- const previousTargetContent = existsSync3(paths.target) ? readUtf8RegularFile(paths.target, workspaceRoot, managedObservationMaxBytes(relativePosix(workspaceRoot, paths.target))) : null;
5676
+ const previousTargetContent = existsSync4(paths.target) ? readUtf8RegularFile(paths.target, workspaceRoot, managedObservationMaxBytes(relativePosix(workspaceRoot, paths.target))) : null;
5577
5677
  const markerParse = parseManagedBlock(previousTargetContent ?? "", input.force === true);
5578
5678
  if (markerParse.block && markerParse.block.id !== bundle.project.id) {
5579
5679
  throw new ProjectContextError("MANAGED_BLOCK_CONFLICT", "managed block belongs to a different project");
@@ -5624,7 +5724,7 @@ function composeProjectContextSessionRender(input) {
5624
5724
  return null;
5625
5725
  const { runtime, workspace_root: workspaceRoot, observed_hashes: observedHashes } = guard;
5626
5726
  const paths = runtimePaths(workspaceRoot, runtime);
5627
- if (!existsSync3(paths.manifest))
5727
+ if (!existsSync4(paths.manifest))
5628
5728
  return null;
5629
5729
  assertCodewithTargetIsConsumed(workspaceRoot, runtime);
5630
5730
  const manifest = readProjectContextManifest(paths.manifest, workspaceRoot);
@@ -5653,7 +5753,7 @@ function composeProjectContextSessionRender(input) {
5653
5753
  }
5654
5754
  const fragment = readUtf8RegularFile(paths.fragment, workspaceRoot, PROJECT_CONTEXT_MAX_RENDERED_BYTES);
5655
5755
  scanGeneratedContent(fragment);
5656
- if (!existsSync3(paths.target)) {
5756
+ if (!existsSync4(paths.target)) {
5657
5757
  throw new ProjectContextError("MANAGED_BLOCK_CONFLICT", "project-context provider target is missing while durable context is active");
5658
5758
  }
5659
5759
  const currentTarget = readUtf8RegularFile(paths.target, workspaceRoot, managedObservationMaxBytes(relativePosix(workspaceRoot, paths.target)));
@@ -5664,7 +5764,7 @@ function composeProjectContextSessionRender(input) {
5664
5764
  if (currentMarkers.block.id !== cache.project_id || currentMarkers.block.revision !== cache.revision || currentMarkers.block.hash !== cache.hash) {
5665
5765
  throw new ProjectContextError("MANAGED_BLOCK_CONFLICT", "project-context provider markers differ from the durable cache");
5666
5766
  }
5667
- const plannedIndexes = input.files.filter((file) => file.role === "index" && resolve2(file.path) === paths.target);
5767
+ const plannedIndexes = input.files.filter((file) => file.role === "index" && resolve3(file.path) === paths.target);
5668
5768
  if (plannedIndexes.length !== 1) {
5669
5769
  throw new ProjectContextError("PROJECT_CONTEXT_MANIFEST_INVALID", "session renderer does not own the selected project-context provider target");
5670
5770
  }
@@ -5722,7 +5822,7 @@ function withProjectContextSessionGuard(guard, action, options = {}) {
5722
5822
  verify();
5723
5823
  return action(null);
5724
5824
  }
5725
- const lockPath = resolve2(validated.workspace_root, ...PROJECT_CONTEXT_LOCK_PATH.split("/"));
5825
+ const lockPath = resolve3(validated.workspace_root, ...PROJECT_CONTEXT_LOCK_PATH.split("/"));
5726
5826
  const lock = acquireWorkspaceLock(validated.workspace_root, lockPath);
5727
5827
  try {
5728
5828
  verify();
@@ -5748,7 +5848,7 @@ function validateProjectContextSessionGuard(guard) {
5748
5848
  if (!isRecord(observed) || typeof observed.path !== "string") {
5749
5849
  throw new ProjectContextError("PROJECT_CONTEXT_SESSION_STALE", "session project-context guard contains malformed hash metadata");
5750
5850
  }
5751
- const path = resolve2(observed.path);
5851
+ const path = resolve3(observed.path);
5752
5852
  if (!allowedPaths.has(path) || observedPaths.has(path)) {
5753
5853
  throw new ProjectContextError("PROJECT_CONTEXT_SESSION_STALE", "session project-context guard contains an unexpected or duplicate path");
5754
5854
  }
@@ -5770,7 +5870,7 @@ function validateProjectContextSessionGuard(guard) {
5770
5870
  function applyProjectContext(options) {
5771
5871
  const workspaceRoot = assertSafeWorkspaceRoot(options.workspace_root);
5772
5872
  const now2 = options.now ?? new Date;
5773
- const lockPath = resolve2(workspaceRoot, ...PROJECT_CONTEXT_LOCK_PATH.split("/"));
5873
+ const lockPath = resolve3(workspaceRoot, ...PROJECT_CONTEXT_LOCK_PATH.split("/"));
5774
5874
  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);
5775
5875
  try {
5776
5876
  const resolved = resolveBundleForApply(options, workspaceRoot, now2);
@@ -5917,7 +6017,7 @@ function resolveBundleForApply(options, workspaceRoot, now2) {
5917
6017
  if (!options.expected_project_id) {
5918
6018
  throw new ProjectContextError("PROJECT_CONTEXT_CACHE_ID_REQUIRED", "expected_project_id is required for stale-cache fallback");
5919
6019
  }
5920
- const cachePath = resolve2(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/"));
6020
+ const cachePath = resolve3(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/"));
5921
6021
  const cache = readProjectContextCache(cachePath, workspaceRoot);
5922
6022
  if (!cache)
5923
6023
  throw new ProjectContextError("PROJECT_CONTEXT_CACHE_MISSING", "no last-known-good project context cache exists");
@@ -6119,7 +6219,7 @@ function findLegacyCodewithWorkspaceSection(workspaceRoot, runtime, content, bun
6119
6219
  if (runtime !== "codewith" || !content)
6120
6220
  return null;
6121
6221
  const sessionManifestPath = runtimePaths(workspaceRoot, runtime).sessionManifest;
6122
- if (!existsSync3(sessionManifestPath))
6222
+ if (!existsSync4(sessionManifestPath))
6123
6223
  return null;
6124
6224
  const manifest = readSessionManifestRecord(sessionManifestPath, workspaceRoot);
6125
6225
  if (!manifest || manifest["schema"] !== SESSION_RENDER_SCHEMA) {
@@ -6170,7 +6270,7 @@ function assertRevisionOrdering(plan, force) {
6170
6270
  const manifest = readProjectContextManifest(plan.manifest_path, plan.workspace_root);
6171
6271
  if (manifest) {
6172
6272
  const manifestHashHasRecoveryProof = manifest.projectContext.hash === plan.bundle.hash || metadataSnapshotMatchesManifest(plan, manifest);
6173
- 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 && existsSync3(plan.fragment_path) && fragmentMatchesBundle(plan.fragment_path, plan.bundle, plan.workspace_root) && manifestHashHasRecoveryProof;
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;
6174
6274
  observations.push({
6175
6275
  source: "manifest",
6176
6276
  id: manifest.projectContext.projectId,
@@ -6178,7 +6278,7 @@ function assertRevisionOrdering(plan, force) {
6178
6278
  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)
6179
6279
  });
6180
6280
  const fragmentEntry = manifest.files.find((file) => file.relativePath === PROJECT_CONTEXT_FRAGMENT_PATH);
6181
- if (fragmentEntry && existsSync3(plan.fragment_path)) {
6281
+ if (fragmentEntry && existsSync4(plan.fragment_path)) {
6182
6282
  const actual = currentFileHash(plan.fragment_path, plan.workspace_root);
6183
6283
  if (actual !== fragmentEntry.sha256 && !fragmentMatchesBundle(plan.fragment_path, plan.bundle, plan.workspace_root) && !force) {
6184
6284
  throw new ProjectContextError("MANAGED_BLOCK_CONFLICT", "canonical project-context fragment changed outside Instructions");
@@ -6273,9 +6373,9 @@ function buildManifest(plan, now2) {
6273
6373
  function buildSessionCompatibilityManifest(plan, now2) {
6274
6374
  const paths = runtimePaths(plan.workspace_root, plan.runtime);
6275
6375
  const tool = manifestTool(plan.runtime);
6276
- const targetHome = plan.runtime === "codewith" ? resolve2(plan.workspace_root, ".codewith") : plan.workspace_root;
6376
+ const targetHome = plan.runtime === "codewith" ? resolve3(plan.workspace_root, ".codewith") : plan.workspace_root;
6277
6377
  const targetRelativePath = sessionTargetRelativePath(plan.runtime);
6278
- const existing = existsSync3(paths.sessionManifest) ? readSessionManifestRecord(paths.sessionManifest, plan.workspace_root) : {
6378
+ const existing = existsSync4(paths.sessionManifest) ? readSessionManifestRecord(paths.sessionManifest, plan.workspace_root) : {
6279
6379
  schema: SESSION_RENDER_SCHEMA,
6280
6380
  tool,
6281
6381
  adapterMode: plan.native_imports ? "native-imports" : "flattened-markdown",
@@ -6295,7 +6395,7 @@ function buildSessionCompatibilityManifest(plan, now2) {
6295
6395
  throw new ProjectContextError("PROJECT_CONTEXT_MANIFEST_INVALID", "provider session manifest is malformed or incompatible");
6296
6396
  }
6297
6397
  const existingTargetHome = safeLegacyMetadataString(existing["targetHome"], null);
6298
- if (existingTargetHome !== null && resolve2(existingTargetHome) !== targetHome) {
6398
+ if (existingTargetHome !== null && resolve3(existingTargetHome) !== targetHome) {
6299
6399
  throw new ProjectContextError("PROJECT_CONTEXT_MANIFEST_INVALID", "provider session manifest targets a different workspace");
6300
6400
  }
6301
6401
  const sources = sanitizeLegacySources(existing["sources"]).filter((source) => source["id"] !== "project-context-bundle");
@@ -6581,9 +6681,9 @@ function writeMetadataSnapshot(plan, now2) {
6581
6681
  const previous = readProjectContextManifest(plan.manifest_path, plan.workspace_root);
6582
6682
  if (!previous || previous.projectContext.revision === plan.bundle.revision && previous.projectContext.hash === plan.bundle.hash)
6583
6683
  return null;
6584
- const snapshotDir = resolve2(plan.workspace_root, ...PROJECT_CONTEXT_SNAPSHOT_DIR.split("/"));
6684
+ const snapshotDir = resolve3(plan.workspace_root, ...PROJECT_CONTEXT_SNAPSHOT_DIR.split("/"));
6585
6685
  ensureSafeDirectory(snapshotDir, plan.workspace_root, 448);
6586
- const snapshotPath = resolve2(snapshotDir, `${safeFilename(previous.projectContext.revision)}-${previous.projectContext.hash.slice(-12)}.json`);
6686
+ const snapshotPath = resolve3(snapshotDir, `${safeFilename(previous.projectContext.revision)}-${previous.projectContext.hash.slice(-12)}.json`);
6587
6687
  const snapshot = {
6588
6688
  schema: "hasna.configs.session-render-snapshot/v1",
6589
6689
  kind: "project-context-metadata",
@@ -6599,9 +6699,9 @@ function writeMetadataSnapshot(plan, now2) {
6599
6699
  return snapshotPath;
6600
6700
  }
6601
6701
  function metadataSnapshotMatchesManifest(plan, manifest) {
6602
- const snapshotDir = resolve2(plan.workspace_root, ...PROJECT_CONTEXT_SNAPSHOT_DIR.split("/"));
6603
- const snapshotPath = resolve2(snapshotDir, `${safeFilename(manifest.projectContext.revision)}-${manifest.projectContext.hash.slice(-12)}.json`);
6604
- if (!existsSync3(snapshotPath))
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))
6605
6705
  return false;
6606
6706
  const record = readJsonRecord(snapshotPath, plan.workspace_root);
6607
6707
  const result = projectContextMetadataSnapshotSchema.safeParse(record);
@@ -6649,10 +6749,10 @@ function writeProjectContextRollbackSnapshot(plan, now2, outputs) {
6649
6749
  sha256: nextHash
6650
6750
  };
6651
6751
  });
6652
- const snapshotDir = resolve2(plan.workspace_root, ...SESSION_RENDER_SNAPSHOT_RELATIVE_DIR.split("/"));
6752
+ const snapshotDir = resolve3(plan.workspace_root, ...SESSION_RENDER_SNAPSHOT_RELATIVE_DIR.split("/"));
6653
6753
  ensureSafeDirectory(snapshotDir, plan.workspace_root, 448);
6654
6754
  const timestamp = now2.toISOString().replace(/[:.]/g, "-");
6655
- const snapshotPath = resolve2(snapshotDir, `${timestamp}-${randomUUID2()}.json`);
6755
+ const snapshotPath = resolve3(snapshotDir, `${timestamp}-${randomUUID2()}.json`);
6656
6756
  const snapshot = {
6657
6757
  schema: "hasna.configs.session-render-snapshot/v2",
6658
6758
  createdAt: now2.toISOString(),
@@ -6670,7 +6770,7 @@ function writeProjectContextRollbackSnapshot(plan, now2, outputs) {
6670
6770
  return snapshotPath;
6671
6771
  }
6672
6772
  function readProjectContextManifest(path, workspaceRoot) {
6673
- if (!existsSync3(path))
6773
+ if (!existsSync4(path))
6674
6774
  return null;
6675
6775
  const record = readJsonRecord(path, workspaceRoot);
6676
6776
  const result = storedManifestObservationSchema.safeParse(record);
@@ -6685,7 +6785,7 @@ function readProjectContextManifest(path, workspaceRoot) {
6685
6785
  };
6686
6786
  }
6687
6787
  function readProjectContextCache(path, workspaceRoot) {
6688
- if (!existsSync3(path))
6788
+ if (!existsSync4(path))
6689
6789
  return null;
6690
6790
  const record = readJsonRecord(path, workspaceRoot);
6691
6791
  const result = projectContextCacheSchema.safeParse(record);
@@ -6717,7 +6817,7 @@ function readSessionManifestRecord(path, workspaceRoot) {
6717
6817
  }
6718
6818
  }
6719
6819
  function atomicWriteFile(path, content, workspaceRoot, defaultMode, expectedHash, afterExchange, atomicExchangeUnavailable = false, beforeInstall, portableCreateOnly = false, maxObservedBytes, allowPortableReplacement = false) {
6720
- const dir = resolve2(path, "..");
6820
+ const dir = resolve3(path, "..");
6721
6821
  ensureSafeDirectory(dir, workspaceRoot, 448);
6722
6822
  assertNoSymlinkSegments(workspaceRoot, path);
6723
6823
  const anchoredOps = portableCreateOnly ? null : resolveAnchoredFsOps();
@@ -6734,7 +6834,7 @@ function atomicWriteFile(path, content, workspaceRoot, defaultMode, expectedHash
6734
6834
  const previous = anchoredFileObservation(directory, targetName);
6735
6835
  const previousMode = previous?.mode ?? defaultMode;
6736
6836
  const tempName = `.project-context-${randomUUID2()}.tmp`;
6737
- const tempPath = join4(dir, tempName);
6837
+ const tempPath = join5(dir, tempName);
6738
6838
  let fd = null;
6739
6839
  let preserveTemp = false;
6740
6840
  let directoryChanged = false;
@@ -6865,7 +6965,7 @@ function atomicWritePortable(path, content, workspaceRoot, defaultMode, expected
6865
6965
  }
6866
6966
  const dir = dirname(path);
6867
6967
  const directoryIdentity = captureManagedDirectoryIdentity(dir, workspaceRoot);
6868
- const tempPath = join4(dir, `.project-context-${randomUUID2()}.tmp`);
6968
+ const tempPath = join5(dir, `.project-context-${randomUUID2()}.tmp`);
6869
6969
  let fd = null;
6870
6970
  let tempIdentity = null;
6871
6971
  try {
@@ -6922,7 +7022,7 @@ function atomicWritePortableReplacement(path, content, workspaceRoot, expectedHa
6922
7022
  }
6923
7023
  const dir = dirname(path);
6924
7024
  const directoryIdentity = captureManagedDirectoryIdentity(dir, workspaceRoot);
6925
- const tempPath = join4(dir, `.project-context-${randomUUID2()}.tmp`);
7025
+ const tempPath = join5(dir, `.project-context-${randomUUID2()}.tmp`);
6926
7026
  const desiredHash = sha2562(content);
6927
7027
  let fd = null;
6928
7028
  let tempIdentity = null;
@@ -6979,7 +7079,7 @@ function portablePreparedHash(tempPath, path, workspaceRoot, maxObservedBytes, s
6979
7079
  function portableFileHash(path, workspaceRoot, maxObservedBytes) {
6980
7080
  if (maxObservedBytes === undefined)
6981
7081
  return currentFileHash(path, workspaceRoot);
6982
- if (!existsSync3(path))
7082
+ if (!existsSync4(path))
6983
7083
  return null;
6984
7084
  assertNoSymlinkSegments(workspaceRoot, path);
6985
7085
  const stat = lstatSync(path);
@@ -6991,11 +7091,11 @@ function portableFileHash(path, workspaceRoot, maxObservedBytes) {
6991
7091
  return createHash2("sha256").update(readFileSync(path)).digest("hex");
6992
7092
  }
6993
7093
  function writeProjectContextCoordinatedFile(input) {
6994
- atomicWriteFile(resolve2(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);
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);
6995
7095
  }
6996
7096
  function removeProjectContextCoordinatedFile(input) {
6997
7097
  const workspaceRoot = assertSafeWorkspaceRoot(input.workspace_root);
6998
- const path = resolve2(input.path);
7098
+ const path = resolve3(input.path);
6999
7099
  assertNoSymlinkSegments(workspaceRoot, path);
7000
7100
  const dir = dirname(path);
7001
7101
  const anchoredOps = input.force_portable_file_ops ? null : resolveAnchoredFsOps();
@@ -7021,7 +7121,7 @@ function removeProjectContextCoordinatedFile(input) {
7021
7121
  throw new ProjectContextHashRace(`managed path changed during deletion: ${relativePosix(workspaceRoot, path)}`);
7022
7122
  }
7023
7123
  displaced = true;
7024
- input.test_hooks?.after_displace?.(join4(dir, displacedName));
7124
+ input.test_hooks?.after_displace?.(join5(dir, displacedName));
7025
7125
  const moved = anchoredFileObservation(directory, displacedName);
7026
7126
  if (!moved || moved.dev !== observed.dev || moved.ino !== observed.ino || moved.hash !== input.expected_hash || anchoredFileObservation(directory, targetName) !== null) {
7027
7127
  throw new ProjectContextHashRace(`managed path changed during deletion validation: ${relativePosix(workspaceRoot, path)}`);
@@ -7067,7 +7167,7 @@ function removePortableCoordinatedFile(path, workspaceRoot, expectedHash, maxObs
7067
7167
  }
7068
7168
  const dir = dirname(path);
7069
7169
  const directoryIdentity = captureManagedDirectoryIdentity(dir, workspaceRoot);
7070
- const displacedPath = join4(dir, `.project-context-delete-${randomUUID2()}.tmp`);
7170
+ const displacedPath = join5(dir, `.project-context-delete-${randomUUID2()}.tmp`);
7071
7171
  let displaced = false;
7072
7172
  try {
7073
7173
  assertManagedDirectoryStable(dir, workspaceRoot, directoryIdentity);
@@ -7078,7 +7178,7 @@ function removePortableCoordinatedFile(path, workspaceRoot, expectedHash, maxObs
7078
7178
  displaced = true;
7079
7179
  afterDisplace?.(displacedPath);
7080
7180
  const moved = lstatSync(displacedPath);
7081
- if (moved.isSymbolicLink() || !moved.isFile() || moved.dev !== observed.dev || moved.ino !== observed.ino || portableFileHash(displacedPath, workspaceRoot, maxObservedBytes) !== expectedHash || existsSync3(path)) {
7181
+ if (moved.isSymbolicLink() || !moved.isFile() || moved.dev !== observed.dev || moved.ino !== observed.ino || portableFileHash(displacedPath, workspaceRoot, maxObservedBytes) !== expectedHash || existsSync4(path)) {
7082
7182
  throw new ProjectContextHashRace(`managed path changed during portable deletion: ${relativePosix(workspaceRoot, path)}`);
7083
7183
  }
7084
7184
  rmSync2(displacedPath);
@@ -7139,7 +7239,7 @@ function anchoredOpenExclusive(directory, name, mode) {
7139
7239
  const requestedMode = mode & 4095;
7140
7240
  let fd;
7141
7241
  try {
7142
- fd = openSync(join4(directory.path, name), constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, requestedMode);
7242
+ fd = openSync(join5(directory.path, name), constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, requestedMode);
7143
7243
  } catch {
7144
7244
  throw new ProjectContextHashRace(`could not create prepared managed file in ${relativePosix(directory.workspaceRoot, directory.path)}`);
7145
7245
  }
@@ -7182,7 +7282,7 @@ function anchoredFileObservation(directory, name) {
7182
7282
  const stat = fstatSync(fd);
7183
7283
  if (!stat.isFile())
7184
7284
  throw new ProjectContextHashRace("managed output is not a regular file");
7185
- const relativePath = relativePosix(directory.workspaceRoot, join4(directory.path, name));
7285
+ const relativePath = relativePosix(directory.workspaceRoot, join5(directory.path, name));
7186
7286
  const maxBytes = directory.maxObservedBytes === undefined ? managedObservationMaxBytes(relativePath) : directory.maxObservedBytes;
7187
7287
  if (maxBytes !== null && stat.size > maxBytes) {
7188
7288
  throw new ProjectContextHashRace(`managed output exceeds the safe read limit: ${relativePath}`);
@@ -7208,7 +7308,7 @@ function anchoredPreparedObservation(directory, name, path, stage) {
7208
7308
  return observed;
7209
7309
  }
7210
7310
  function captureManagedDirectoryIdentity(path, workspaceRoot) {
7211
- assertNoSymlinkSegments(workspaceRoot, join4(path, ".project-context-directory-guard"));
7311
+ assertNoSymlinkSegments(workspaceRoot, join5(path, ".project-context-directory-guard"));
7212
7312
  let stat;
7213
7313
  try {
7214
7314
  stat = lstatSync(path);
@@ -7221,7 +7321,7 @@ function captureManagedDirectoryIdentity(path, workspaceRoot) {
7221
7321
  return { dev: stat.dev, ino: stat.ino };
7222
7322
  }
7223
7323
  function assertManagedDirectoryStable(path, workspaceRoot, expected) {
7224
- assertNoSymlinkSegments(workspaceRoot, join4(path, ".project-context-directory-guard"));
7324
+ assertNoSymlinkSegments(workspaceRoot, join5(path, ".project-context-directory-guard"));
7225
7325
  let current;
7226
7326
  try {
7227
7327
  current = lstatSync(path);
@@ -7356,10 +7456,10 @@ function resolveAnchoredFsOps() {
7356
7456
  return null;
7357
7457
  }
7358
7458
  function acquireWorkspaceLock(workspaceRoot, lockPath, afterOpen, beforeStaleRemove, processStartIdentityLookup = processStartIdentity) {
7359
- const lockDirectory = resolve2(lockPath, "..");
7459
+ const lockDirectory = resolve3(lockPath, "..");
7360
7460
  ensureSafeDirectory(lockDirectory, workspaceRoot, 448);
7361
7461
  assertNoSymlinkSegments(workspaceRoot, lockPath);
7362
- const tempPath = join4(lockDirectory, `.project-context-lock-${randomUUID2()}.tmp`);
7462
+ const tempPath = join5(lockDirectory, `.project-context-lock-${randomUUID2()}.tmp`);
7363
7463
  let fd = null;
7364
7464
  let openedIdentity = null;
7365
7465
  let openedContentHash = null;
@@ -7393,7 +7493,7 @@ function acquireWorkspaceLock(workspaceRoot, lockPath, afterOpen, beforeStaleRem
7393
7493
  linked = true;
7394
7494
  }
7395
7495
  fsyncDirectory(lockDirectory);
7396
- if (existsSync3(tempPath)) {
7496
+ if (existsSync4(tempPath)) {
7397
7497
  rmSync2(tempPath);
7398
7498
  fsyncDirectory(lockDirectory);
7399
7499
  }
@@ -7408,7 +7508,7 @@ function acquireWorkspaceLock(workspaceRoot, lockPath, afterOpen, beforeStaleRem
7408
7508
  if (linked && openedIdentity && openedContentHash) {
7409
7509
  removeOwnedLockByInode(lockPath, openedIdentity, openedContentHash);
7410
7510
  }
7411
- if (!preserveTemp && existsSync3(tempPath)) {
7511
+ if (!preserveTemp && existsSync4(tempPath)) {
7412
7512
  try {
7413
7513
  rmSync2(tempPath);
7414
7514
  } catch {}
@@ -7423,7 +7523,7 @@ function acquireWorkspaceLock(workspaceRoot, lockPath, afterOpen, beforeStaleRem
7423
7523
  }
7424
7524
  function removeOwnedLockByInode(lockPath, identity, expectedHash) {
7425
7525
  try {
7426
- if (!existsSync3(lockPath))
7526
+ if (!existsSync4(lockPath))
7427
7527
  return;
7428
7528
  const current = lstatSync(lockPath);
7429
7529
  if (current.isSymbolicLink() || current.dev !== identity.dev || current.ino !== identity.ino)
@@ -7431,7 +7531,7 @@ function removeOwnedLockByInode(lockPath, identity, expectedHash) {
7431
7531
  if (expectedHash !== undefined && sha2562(readFileSync(lockPath, "utf8")) !== expectedHash)
7432
7532
  return;
7433
7533
  rmSync2(lockPath);
7434
- fsyncDirectory(resolve2(lockPath, ".."));
7534
+ fsyncDirectory(resolve3(lockPath, ".."));
7435
7535
  } catch {}
7436
7536
  }
7437
7537
  function observeStaleWorkspaceLock(lockPath, workspaceRoot, processStartIdentityLookup = processStartIdentity) {
@@ -7502,7 +7602,7 @@ function tryTakeoverStaleWorkspaceLock(candidatePath, lockPath, workspaceRoot, c
7502
7602
  const candidateInstalled = !current.isSymbolicLink() && current.dev === candidateIdentity.dev && current.ino === candidateIdentity.ino && currentFileHash(lockPath, workspaceRoot) === candidateHash;
7503
7603
  const staleDisplaced = !displaced.isSymbolicLink() && displaced.dev === stale.identity.dev && displaced.ino === stale.identity.ino && currentFileHash(candidatePath, workspaceRoot) === stale.contentHash;
7504
7604
  if (!candidateInstalled || !staleDisplaced) {
7505
- if (candidateInstalled && existsSync3(candidatePath)) {
7605
+ if (candidateInstalled && existsSync4(candidatePath)) {
7506
7606
  atomicExchangePaths(candidatePath, lockPath);
7507
7607
  exchanged = false;
7508
7608
  return false;
@@ -7510,13 +7610,13 @@ function tryTakeoverStaleWorkspaceLock(candidatePath, lockPath, workspaceRoot, c
7510
7610
  throw new ProjectContextError("PROJECT_CONTEXT_LOCK_LOST", "workspace lock changed during stale-lock takeover and could not be restored safely");
7511
7611
  }
7512
7612
  rmSync2(candidatePath);
7513
- fsyncDirectory(resolve2(lockPath, ".."));
7613
+ fsyncDirectory(resolve3(lockPath, ".."));
7514
7614
  exchanged = false;
7515
7615
  return true;
7516
7616
  } catch (error) {
7517
7617
  if (exchanged) {
7518
7618
  try {
7519
- if (currentFileHash(lockPath, workspaceRoot) === candidateHash && existsSync3(candidatePath)) {
7619
+ if (currentFileHash(lockPath, workspaceRoot) === candidateHash && existsSync4(candidatePath)) {
7520
7620
  atomicExchangePaths(candidatePath, lockPath);
7521
7621
  exchanged = false;
7522
7622
  }
@@ -7529,7 +7629,7 @@ function tryTakeoverStaleWorkspaceLock(candidatePath, lockPath, workspaceRoot, c
7529
7629
  }
7530
7630
  }
7531
7631
  function assertWorkspaceLockHeld(lockPath, lock, workspaceRoot) {
7532
- if (!existsSync3(lockPath)) {
7632
+ if (!existsSync4(lockPath)) {
7533
7633
  throw new ProjectContextError("PROJECT_CONTEXT_LOCK_LOST", "workspace project-context lock changed during render");
7534
7634
  }
7535
7635
  const current = lstatSync(lockPath);
@@ -7589,8 +7689,8 @@ function releaseWorkspaceLock(lockPath, lock, workspaceRoot) {
7589
7689
  }
7590
7690
  return;
7591
7691
  }
7592
- const lockDirectory = resolve2(lockPath, "..");
7593
- const releasePath = join4(lockDirectory, `.project-context-release-${randomUUID2()}.tmp`);
7692
+ const lockDirectory = resolve3(lockPath, "..");
7693
+ const releasePath = join5(lockDirectory, `.project-context-release-${randomUUID2()}.tmp`);
7594
7694
  let releaseFd = null;
7595
7695
  let releaseIdentity = null;
7596
7696
  let releaseHash = null;
@@ -7619,7 +7719,7 @@ function releaseWorkspaceLock(lockPath, lock, workspaceRoot) {
7619
7719
  const releaseInstalled = !installed.isSymbolicLink() && installed.dev === releaseIdentity.dev && installed.ino === releaseIdentity.ino && currentFileHash(lockPath, workspaceRoot) === releaseHash;
7620
7720
  const ownedDisplaced = !displaced.isSymbolicLink() && displaced.dev === lock.identity.dev && displaced.ino === lock.identity.ino && currentFileHash(releasePath, workspaceRoot) === lock.contentHash;
7621
7721
  if (!releaseInstalled || !ownedDisplaced) {
7622
- if (releaseInstalled && existsSync3(releasePath)) {
7722
+ if (releaseInstalled && existsSync4(releasePath)) {
7623
7723
  atomicExchangePaths(releasePath, lockPath);
7624
7724
  exchanged = false;
7625
7725
  }
@@ -7632,7 +7732,7 @@ function releaseWorkspaceLock(lockPath, lock, workspaceRoot) {
7632
7732
  } catch {
7633
7733
  if (exchanged) {
7634
7734
  try {
7635
- if (releaseHash && currentFileHash(lockPath, workspaceRoot) === releaseHash && existsSync3(releasePath)) {
7735
+ if (releaseHash && currentFileHash(lockPath, workspaceRoot) === releaseHash && existsSync4(releasePath)) {
7636
7736
  atomicExchangePaths(releasePath, lockPath);
7637
7737
  exchanged = false;
7638
7738
  }
@@ -7644,7 +7744,7 @@ function releaseWorkspaceLock(lockPath, lock, workspaceRoot) {
7644
7744
  closeSync(releaseFd);
7645
7745
  } catch {}
7646
7746
  }
7647
- if (!exchanged && existsSync3(releasePath)) {
7747
+ if (!exchanged && existsSync4(releasePath)) {
7648
7748
  try {
7649
7749
  rmSync2(releasePath);
7650
7750
  } catch {}
@@ -7670,15 +7770,15 @@ function ensureSafeDirectory(path, workspaceRoot, mode) {
7670
7770
  const segments = rel.split(/[\\/]+/).filter(Boolean);
7671
7771
  let current = workspaceRoot;
7672
7772
  for (const segment of segments) {
7673
- current = join4(current, segment);
7674
- if (existsSync3(current)) {
7773
+ current = join5(current, segment);
7774
+ if (existsSync4(current)) {
7675
7775
  if (lstatSync(current).isSymbolicLink())
7676
7776
  throw new ProjectContextError("PROJECT_CONTEXT_SYMLINK_REJECTED", `managed path uses a symlink: ${current}`);
7677
7777
  if (!statSync(current).isDirectory())
7678
7778
  throw new ProjectContextError("PROJECT_CONTEXT_PATH_INVALID", `managed path is not a directory: ${current}`);
7679
7779
  } else {
7680
7780
  mkdirSync2(current, { mode });
7681
- fsyncDirectory(resolve2(current, ".."));
7781
+ fsyncDirectory(resolve3(current, ".."));
7682
7782
  }
7683
7783
  }
7684
7784
  }
@@ -7734,11 +7834,11 @@ function scanGeneratedContent(content) {
7734
7834
  function runtimePaths(workspaceRoot, runtime) {
7735
7835
  const relativeTarget = runtime === "claude" ? "CLAUDE.md" : runtime === "codewith" ? ".codewith/CODEWITH.md" : "AGENTS.md";
7736
7836
  return {
7737
- target: resolve2(workspaceRoot, ...relativeTarget.split("/")),
7738
- fragment: resolve2(workspaceRoot, ...PROJECT_CONTEXT_FRAGMENT_PATH.split("/")),
7739
- manifest: resolve2(workspaceRoot, ...PROJECT_CONTEXT_MANIFEST_PATH.split("/")),
7740
- cache: resolve2(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/")),
7741
- sessionManifest: runtime === "codewith" ? resolve2(workspaceRoot, ".codewith", ".hasna", "session-render-manifest.json") : resolve2(workspaceRoot, ".hasna", "session-render-manifest.json")
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")
7742
7842
  };
7743
7843
  }
7744
7844
  function projectContextSessionGuardPaths(paths, runtime) {
@@ -7748,7 +7848,7 @@ function projectContextSessionGuardPaths(paths, runtime) {
7748
7848
  paths.fragment,
7749
7849
  paths.target,
7750
7850
  paths.sessionManifest,
7751
- ...runtime === "codewith" ? [resolve2(paths.target, "..", "CODEWITH.override.md")] : []
7851
+ ...runtime === "codewith" ? [resolve3(paths.target, "..", "CODEWITH.override.md")] : []
7752
7852
  ];
7753
7853
  }
7754
7854
  function sessionTargetRelativePath(runtime) {
@@ -7768,27 +7868,27 @@ function projectContextRuntimeForSessionTool(tool) {
7768
7868
  return null;
7769
7869
  }
7770
7870
  function projectContextWorkspaceForSession(input, runtime) {
7771
- const targetHome = resolve2(input.target_home);
7871
+ const targetHome = resolve3(input.target_home);
7772
7872
  if (runtime === "codewith") {
7773
7873
  const workspaceRoot = basename(targetHome) === ".codewith" ? dirname(targetHome) : null;
7774
7874
  if (!workspaceRoot)
7775
7875
  return null;
7776
- if (input.project_root && resolve2(input.project_root) !== workspaceRoot) {
7876
+ if (input.project_root && resolve3(input.project_root) !== workspaceRoot) {
7777
7877
  throw new ProjectContextError("PROJECT_CONTEXT_PATH_INVALID", "Codewith project_root must be the parent workspace of target_home");
7778
7878
  }
7779
- if (!existsSync3(workspaceRoot) || !lstatSync(workspaceRoot).isDirectory())
7879
+ if (!existsSync4(workspaceRoot) || !lstatSync(workspaceRoot).isDirectory())
7780
7880
  return null;
7781
7881
  return assertSafeWorkspaceRoot(workspaceRoot);
7782
7882
  }
7783
- if (!existsSync3(targetHome) || !lstatSync(targetHome).isDirectory())
7883
+ if (!existsSync4(targetHome) || !lstatSync(targetHome).isDirectory())
7784
7884
  return null;
7785
7885
  return assertSafeWorkspaceRoot(targetHome);
7786
7886
  }
7787
7887
  function assertCodewithTargetIsConsumed(workspaceRoot, runtime) {
7788
7888
  if (runtime !== "codewith")
7789
7889
  return;
7790
- const override = resolve2(workspaceRoot, ".codewith", "CODEWITH.override.md");
7791
- if (!existsSync3(override))
7890
+ const override = resolve3(workspaceRoot, ".codewith", "CODEWITH.override.md");
7891
+ if (!existsSync4(override))
7792
7892
  return;
7793
7893
  assertNoSymlinkSegments(workspaceRoot, override);
7794
7894
  if (!lstatSync(override).isFile())
@@ -7798,10 +7898,10 @@ function assertCodewithTargetIsConsumed(workspaceRoot, runtime) {
7798
7898
  function assertSafeWorkspaceRoot(path) {
7799
7899
  if (!isAbsolute(path))
7800
7900
  throw new ProjectContextError("PROJECT_CONTEXT_PATH_INVALID", "workspace root must be absolute");
7801
- const normalized = resolve2(path);
7901
+ const normalized = resolve3(path);
7802
7902
  if (normalized === parse(normalized).root)
7803
7903
  throw new ProjectContextError("PROJECT_CONTEXT_PATH_INVALID", "workspace root cannot be the filesystem root");
7804
- if (!existsSync3(normalized) || !lstatSync(normalized).isDirectory())
7904
+ if (!existsSync4(normalized) || !lstatSync(normalized).isDirectory())
7805
7905
  throw new ProjectContextError("PROJECT_CONTEXT_PATH_INVALID", "workspace root must be an existing directory");
7806
7906
  assertNoSymlinkAncestors(normalized);
7807
7907
  if (lstatSync(normalized).isSymbolicLink())
@@ -7815,18 +7915,18 @@ function assertNoSymlinkSegments(root, target) {
7815
7915
  }
7816
7916
  let current = root;
7817
7917
  for (const segment of rel.split(/[\\/]+/).filter(Boolean)) {
7818
- current = join4(current, segment);
7819
- if (existsSync3(current) && lstatSync(current).isSymbolicLink()) {
7918
+ current = join5(current, segment);
7919
+ if (existsSync4(current) && lstatSync(current).isSymbolicLink()) {
7820
7920
  throw new ProjectContextError("PROJECT_CONTEXT_SYMLINK_REJECTED", `managed path uses a symlink: ${current}`);
7821
7921
  }
7822
7922
  }
7823
7923
  }
7824
7924
  function assertNoSymlinkAncestors(path) {
7825
- const normalized = resolve2(path);
7925
+ const normalized = resolve3(path);
7826
7926
  let current = parse(normalized).root;
7827
7927
  for (const segment of relative(current, normalized).split(/[\\/]+/).filter(Boolean)) {
7828
- current = join4(current, segment);
7829
- if (!existsSync3(current))
7928
+ current = join5(current, segment);
7929
+ if (!existsSync4(current))
7830
7930
  return;
7831
7931
  if (lstatSync(current).isSymbolicLink())
7832
7932
  throw new ProjectContextError("PROJECT_CONTEXT_SYMLINK_REJECTED", `workspace ancestor is a symlink: ${current}`);
@@ -7842,7 +7942,7 @@ function readUtf8RegularFile(path, workspaceRoot, maxBytes = FOREIGN_INPUT_MAX_B
7842
7942
  return readFileSync(path, "utf8");
7843
7943
  }
7844
7944
  function currentFileHash(path, workspaceRoot) {
7845
- if (!existsSync3(path))
7945
+ if (!existsSync4(path))
7846
7946
  return null;
7847
7947
  const relativePath = relativePosix(workspaceRoot, path);
7848
7948
  return sha2562(readUtf8RegularFile(path, workspaceRoot, managedObservationMaxBytes(relativePath)));
@@ -7861,10 +7961,10 @@ function fragmentMatchesBundle(path, bundle, workspaceRoot) {
7861
7961
  }
7862
7962
  function durableSourcePath(path, workspaceRoot) {
7863
7963
  if (!path || path.startsWith("/dev/fd/"))
7864
- return resolve2(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/"));
7865
- const normalized = isAbsolute(path) ? resolve2(path) : resolve2(workspaceRoot, path);
7964
+ return resolve3(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/"));
7965
+ const normalized = isAbsolute(path) ? resolve3(path) : resolve3(workspaceRoot, path);
7866
7966
  if (normalized.startsWith("/dev/fd/"))
7867
- return resolve2(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/"));
7967
+ return resolve3(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/"));
7868
7968
  return normalized;
7869
7969
  }
7870
7970
  function compareRevisions(incoming, previous) {
@@ -8205,7 +8305,7 @@ function compareProviderVersions(left, right) {
8205
8305
 
8206
8306
  // src/lib/asset-plan.ts
8207
8307
  import { createHash as createHash3 } from "crypto";
8208
- import { isAbsolute as isAbsolute2, posix, resolve as resolve3 } from "path";
8308
+ import { isAbsolute as isAbsolute2, posix, resolve as resolve4 } from "path";
8209
8309
  var ASSET_PLAN_SCHEMA = "hasna.instructions.asset-plan/v1";
8210
8310
  var ASSET_CAPABILITY_SCHEMA = "hasna.instructions.asset-capability/v1";
8211
8311
  var ASSET_BUNDLE_SCHEMA = "hasna.instructions.asset-bundle/v1";
@@ -8470,8 +8570,8 @@ function resolveAssetDestination(item, roots) {
8470
8570
  if (!isAbsolute2(root))
8471
8571
  throw new Error(`Asset ${item.assetKey} destination root must be absolute.`);
8472
8572
  const relativePath = safeRelativePath(item.destination.relativePath);
8473
- const target = resolve3(root, ...relativePath.split("/"));
8474
- const normalizedRoot = resolve3(root);
8573
+ const target = resolve4(root, ...relativePath.split("/"));
8574
+ const normalizedRoot = resolve4(root);
8475
8575
  if (target === normalizedRoot)
8476
8576
  throw new Error(`Asset ${item.assetKey} destination cannot replace its root.`);
8477
8577
  if (!target.startsWith(`${normalizedRoot}/`))
@@ -8593,8 +8693,8 @@ function deepFreeze(value) {
8593
8693
  // src/lib/cursor-authority.ts
8594
8694
  import { createHash as createHash4 } from "crypto";
8595
8695
  import { lstatSync as lstatSync2, readFileSync as readFileSync2 } from "fs";
8596
- import { homedir as homedir3 } from "os";
8597
- import { join as join5, resolve as resolve4 } from "path";
8696
+ import { homedir as homedir4 } from "os";
8697
+ import { join as join6, resolve as resolve5 } from "path";
8598
8698
  var CURSOR_GLOBAL_AUTHORITY_RELATIVE_PATH = ".cursor/rules/hasna-global.mdc";
8599
8699
  var CURSOR_GLOBAL_AUTHORITY_MAX_BYTES = 256 * 1024;
8600
8700
  var CURSOR_GLOBAL_AUTHORITY_MANAGED_MARKER = "Managed by @hasna/configs cursor global authority";
@@ -8603,8 +8703,8 @@ var CURSOR_GLOBAL_AUTHORITY_FRONTMATTER_PATTERN = /^---\n[\s\S]*?\n---(?:\n|$)/;
8603
8703
  function sha2564(content) {
8604
8704
  return createHash4("sha256").update(content).digest("hex");
8605
8705
  }
8606
- function homeDir() {
8607
- return process.env["HOME"] || homedir3();
8706
+ function homeDir2() {
8707
+ return process.env["HOME"] || homedir4();
8608
8708
  }
8609
8709
  function markerPayload(content, markerLine, markerIndex) {
8610
8710
  const index = markerIndex ?? content.indexOf(markerLine);
@@ -8620,12 +8720,12 @@ function baseObservation(path) {
8620
8720
  };
8621
8721
  }
8622
8722
  function observeCursorGlobalAuthority(options = {}) {
8623
- const authorityPath = resolve4(join5(options.home ?? homeDir(), CURSOR_GLOBAL_AUTHORITY_RELATIVE_PATH));
8723
+ const authorityPath = resolve5(join6(options.home ?? homeDir2(), CURSOR_GLOBAL_AUTHORITY_RELATIVE_PATH));
8624
8724
  const readFile = options.readFile ?? ((path) => readFileSync2(path, "utf8"));
8625
8725
  return observeCursorGlobalAuthorityPath(authorityPath, readFile);
8626
8726
  }
8627
8727
  function observeCursorGlobalAuthorityAtPath(authorityPath) {
8628
- return observeCursorGlobalAuthorityPath(resolve4(authorityPath), (path) => readFileSync2(path, "utf8"));
8728
+ return observeCursorGlobalAuthorityPath(resolve5(authorityPath), (path) => readFileSync2(path, "utf8"));
8629
8729
  }
8630
8730
  function observeCursorGlobalAuthorityPath(authorityPath, readFile) {
8631
8731
  const base = baseObservation(authorityPath);
@@ -8770,11 +8870,21 @@ function observeCursorGlobalAuthorityPath(authorityPath, readFile) {
8770
8870
  };
8771
8871
  }
8772
8872
  function isCursorGlobalAuthorityPath(path) {
8773
- return resolve4(path) === resolve4(join5(homeDir(), CURSOR_GLOBAL_AUTHORITY_RELATIVE_PATH));
8873
+ return resolve5(path) === resolve5(join6(homeDir2(), CURSOR_GLOBAL_AUTHORITY_RELATIVE_PATH));
8774
8874
  }
8775
8875
  function stampCursorGlobalAuthorityMarker(content) {
8776
- if (CURSOR_GLOBAL_AUTHORITY_MARKER_PATTERN.test(content))
8777
- return content;
8876
+ const existing = content.match(CURSOR_GLOBAL_AUTHORITY_MARKER_PATTERN);
8877
+ if (existing) {
8878
+ const markerLine2 = existing[0];
8879
+ const index = existing.index ?? content.indexOf(markerLine2);
8880
+ const payload = markerPayload(content, markerLine2, index);
8881
+ if (sha2564(payload) === existing[1].slice("sha256:".length)) {
8882
+ return content;
8883
+ }
8884
+ const digest2 = sha2564(payload);
8885
+ const freshMarkerLine = `<!-- ${CURSOR_GLOBAL_AUTHORITY_MANAGED_MARKER} hash=sha256:${digest2} -->`;
8886
+ return content.slice(0, index) + freshMarkerLine + content.slice(index + markerLine2.length);
8887
+ }
8778
8888
  const digest = sha2564(content);
8779
8889
  const markerLine = `<!-- ${CURSOR_GLOBAL_AUTHORITY_MANAGED_MARKER} hash=sha256:${digest} -->`;
8780
8890
  const frontmatter = content.match(CURSOR_GLOBAL_AUTHORITY_FRONTMATTER_PATTERN)?.[0];
@@ -8810,8 +8920,8 @@ function detectCursorAuthorityConflicts(observation = observeCursorGlobalAuthori
8810
8920
  // src/lib/session-authority.ts
8811
8921
  import { createHash as createHash5 } from "crypto";
8812
8922
  import { lstatSync as lstatSync3, readFileSync as readFileSync3, realpathSync, statSync as statSync2 } from "fs";
8813
- import { homedir as homedir4 } from "os";
8814
- import { join as join6, resolve as resolve5 } from "path";
8923
+ import { homedir as homedir5 } from "os";
8924
+ import { join as join7, resolve as resolve6 } from "path";
8815
8925
  var CLAUDE_LEGACY_AUTHORITY_RELATIVE_PATH = "AGENTS.md";
8816
8926
  var CLAUDE_LEGACY_AUTHORITY_MAX_BYTES = 256 * 1024;
8817
8927
  var CLAUDE_LEGACY_MARKERS = [
@@ -8823,10 +8933,10 @@ function sha2565(content) {
8823
8933
  return createHash5("sha256").update(content).digest("hex");
8824
8934
  }
8825
8935
  function configHomeDir() {
8826
- return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir4();
8936
+ return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir5();
8827
8937
  }
8828
8938
  function normalizeOwnedTargetPath(p) {
8829
- const expanded = p.startsWith("~/") ? resolve5(configHomeDir(), p.slice(2)) : resolve5(p);
8939
+ const expanded = p.startsWith("~/") ? resolve6(configHomeDir(), p.slice(2)) : resolve6(p);
8830
8940
  try {
8831
8941
  return realpathSync(expanded);
8832
8942
  } catch {
@@ -8834,7 +8944,7 @@ function normalizeOwnedTargetPath(p) {
8834
8944
  }
8835
8945
  }
8836
8946
  function detectClaudeAuthorityConflicts(targetHome, ownedAuthorities = []) {
8837
- const authorityPath = resolve5(join6(targetHome, CLAUDE_LEGACY_AUTHORITY_RELATIVE_PATH));
8947
+ const authorityPath = resolve6(join7(targetHome, CLAUDE_LEGACY_AUTHORITY_RELATIVE_PATH));
8838
8948
  let stat;
8839
8949
  try {
8840
8950
  stat = lstatSync3(authorityPath);
@@ -9193,13 +9303,13 @@ function yamlQuote2(value) {
9193
9303
  return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
9194
9304
  }
9195
9305
  function defaultTargetHome(tool, profile, sessionId) {
9196
- const home = process.env["HOME"] || homedir5();
9197
- return join7(home, ".hasna", "accounts", "profiles", tool, slug(profile));
9306
+ const home = process.env["HOME"] || homedir6();
9307
+ return join8(home, ".hasna", "accounts", "profiles", tool, slug(profile));
9198
9308
  }
9199
9309
  function joinTarget(targetHome, relativePath) {
9200
9310
  const safeTargetHome = assertSafeTargetRoot(targetHome);
9201
9311
  const safeRelativePath2 = assertSafeRelativePath(relativePath);
9202
- return join7(safeTargetHome, ...safeRelativePath2.split("/"));
9312
+ return join8(safeTargetHome, ...safeRelativePath2.split("/"));
9203
9313
  }
9204
9314
  function makeFile(targetHome, relativePath, role, content, sourceIds) {
9205
9315
  const safeTargetHome = assertSafeTargetRoot(targetHome);
@@ -9769,7 +9879,7 @@ function buildOpenCodeFiles(targetHome, adapter, profile, sources, providerConfi
9769
9879
  ...sources.flatMap((source) => source.resolvedRules.map((rule) => rule.id))
9770
9880
  ]);
9771
9881
  const existingConfigPath = joinTarget(targetHome, adapter.configFile);
9772
- const selectedConfig = existsSync5(existingConfigPath) ? readOpenCodeConfig(readFileSync4(existingConfigPath, "utf8"), existingConfigPath) : providerConfig ? readOpenCodeConfig(providerConfig.content, providerConfig.sourceId) : {};
9882
+ const selectedConfig = existsSync6(existingConfigPath) ? readOpenCodeConfig(readFileSync4(existingConfigPath, "utf8"), existingConfigPath) : providerConfig ? readOpenCodeConfig(providerConfig.content, providerConfig.sourceId) : {};
9773
9883
  const preservedInstructions = normalizeOpenCodeInstructions(selectedConfig["instructions"]).filter((path) => !pathIsManagedOpenCodeInstruction(path, adapter.managedDir));
9774
9884
  const config = {
9775
9885
  ...selectedConfig,
@@ -9958,7 +10068,7 @@ function adapterFor(input) {
9958
10068
  return gatedNativeImports ? CODEWITH_NATIVE_ADAPTER : CODEWITH_FLATTENED_ADAPTER;
9959
10069
  }
9960
10070
  function getHomeDir() {
9961
- return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir5();
10071
+ return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir6();
9962
10072
  }
9963
10073
  function cleanSessionPathInput(path) {
9964
10074
  const trimmed = path.trim();
@@ -9973,16 +10083,16 @@ function resolveSessionPath(path) {
9973
10083
  throw new Error("Session render path cannot be empty.");
9974
10084
  const home = getHomeDir();
9975
10085
  if (cleaned === "~")
9976
- return resolve6(home);
10086
+ return resolve7(home);
9977
10087
  if (cleaned.startsWith("~/"))
9978
- return resolve6(home, cleaned.slice(2));
10088
+ return resolve7(home, cleaned.slice(2));
9979
10089
  if (cleaned === "{{HOME}}" || cleaned === "${HOME}")
9980
- return resolve6(home);
10090
+ return resolve7(home);
9981
10091
  if (cleaned.startsWith("{{HOME}}/"))
9982
- return resolve6(home, cleaned.slice("{{HOME}}/".length));
10092
+ return resolve7(home, cleaned.slice("{{HOME}}/".length));
9983
10093
  if (cleaned.startsWith("${HOME}/"))
9984
- return resolve6(home, cleaned.slice("${HOME}/".length));
9985
- return resolve6(cleaned);
10094
+ return resolve7(home, cleaned.slice("${HOME}/".length));
10095
+ return resolve7(cleaned);
9986
10096
  }
9987
10097
  function assertSafeRelativePath(relativePath) {
9988
10098
  if (!relativePath.trim())
@@ -9998,7 +10108,7 @@ function assertSafeRelativePath(relativePath) {
9998
10108
  function assertSafeTargetRoot(targetHome) {
9999
10109
  if (!isAbsolute3(targetHome))
10000
10110
  throw new Error(`Session render target must be an absolute path: ${targetHome}`);
10001
- const normalized = resolve6(targetHome);
10111
+ const normalized = resolve7(targetHome);
10002
10112
  if (normalized === parse2(normalized).root) {
10003
10113
  throw new Error(`Session render target cannot be the filesystem root: ${targetHome}`);
10004
10114
  }
@@ -10234,7 +10344,7 @@ function planSessionRender(input) {
10234
10344
  sourceId: input.providerConfig.sourceId,
10235
10345
  selectedPayloadSha256: sha2566(input.providerConfig.content),
10236
10346
  renderedPayloadSha256: files.find((file) => file.relativePath === adapter.configFile)?.sha256 ?? sha2566(input.providerConfig.content),
10237
- selected: !existsSync5(joinTarget(targetHome, adapter.configFile))
10347
+ selected: !existsSync6(joinTarget(targetHome, adapter.configFile))
10238
10348
  }
10239
10349
  } : {},
10240
10350
  ...projectContext ? {
@@ -10596,10 +10706,10 @@ function layerFromIdentityKind(kind, exportShape) {
10596
10706
  function contentFromIdentitySourcePaths(sourcePaths, exportPath, sourceId) {
10597
10707
  if (sourcePaths.length === 0 || !exportPath)
10598
10708
  return;
10599
- const baseDir = dirname3(resolveSessionPath(exportPath));
10709
+ const baseDir2 = dirname3(resolveSessionPath(exportPath));
10600
10710
  const contents = [];
10601
10711
  for (const sourcePath of sourcePaths) {
10602
- const content = readIdentitySourcePath(sourcePath, baseDir, sourceId);
10712
+ const content = readIdentitySourcePath(sourcePath, baseDir2, sourceId);
10603
10713
  if (content !== undefined)
10604
10714
  contents.push({ path: sourcePath.path, content });
10605
10715
  }
@@ -10612,9 +10722,9 @@ ${item.content.trimEnd()}`).join(`
10612
10722
 
10613
10723
  `));
10614
10724
  }
10615
- function readIdentitySourcePath(sourcePath, baseDir, sourceId) {
10616
- const resolvedPath = resolveIdentitySourcePath(sourcePath.path, baseDir, sourceId);
10617
- if (!existsSync5(resolvedPath)) {
10725
+ function readIdentitySourcePath(sourcePath, baseDir2, sourceId) {
10726
+ const resolvedPath = resolveIdentitySourcePath(sourcePath.path, baseDir2, sourceId);
10727
+ if (!existsSync6(resolvedPath)) {
10618
10728
  if (sourcePath.required) {
10619
10729
  throw new Error(`Required identity instruction source path not found for ${sourceId}: ${sourcePath.path}`);
10620
10730
  }
@@ -10624,27 +10734,27 @@ function readIdentitySourcePath(sourcePath, baseDir, sourceId) {
10624
10734
  if (!stat.isFile()) {
10625
10735
  throw new Error(`Identity instruction source path is not a file for ${sourceId}: ${sourcePath.path}`);
10626
10736
  }
10627
- const realBase = realpathSync2(baseDir);
10737
+ const realBase = realpathSync2(baseDir2);
10628
10738
  const realPath = realpathSync2(resolvedPath);
10629
10739
  if (!pathIsInside(realPath, realBase)) {
10630
10740
  throw new Error(`Identity instruction source path escapes export directory for ${sourceId}: ${sourcePath.path}`);
10631
10741
  }
10632
10742
  return readFileSync4(realPath, "utf-8");
10633
10743
  }
10634
- function resolveIdentitySourcePath(path, baseDir, sourceId) {
10744
+ function resolveIdentitySourcePath(path, baseDir2, sourceId) {
10635
10745
  const cleaned = cleanSessionPathInput(path);
10636
10746
  if (!cleaned)
10637
10747
  throw new Error(`Identity instruction source path cannot be empty for ${sourceId}.`);
10638
10748
  if (cleaned.includes("\\"))
10639
10749
  throw new Error(`Identity instruction source path must use POSIX separators for ${sourceId}: ${path}`);
10640
- const resolvedPath = isAbsolute3(cleaned) ? resolve6(cleaned) : resolve6(baseDir, cleaned);
10641
- if (!pathIsInside(resolvedPath, resolve6(baseDir))) {
10750
+ const resolvedPath = isAbsolute3(cleaned) ? resolve7(cleaned) : resolve7(baseDir2, cleaned);
10751
+ if (!pathIsInside(resolvedPath, resolve7(baseDir2))) {
10642
10752
  throw new Error(`Identity instruction source path escapes export directory for ${sourceId}: ${path}`);
10643
10753
  }
10644
10754
  return resolvedPath;
10645
10755
  }
10646
- function pathIsInside(path, baseDir) {
10647
- const rel = relative2(baseDir, path);
10756
+ function pathIsInside(path, baseDir2) {
10757
+ const rel = relative2(baseDir2, path);
10648
10758
  return rel === "" || !rel.startsWith("..") && !isAbsolute3(rel);
10649
10759
  }
10650
10760
  function providerTargetsTool(targets, tool) {
@@ -12045,16 +12155,16 @@ function resolveConfigStore(env = process.env) {
12045
12155
  return cloud ? new CloudConfigStore(cloud) : new LocalConfigStore;
12046
12156
  }
12047
12157
  // src/status.ts
12048
- import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
12158
+ import { existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
12049
12159
 
12050
12160
  // src/lib/apply.ts
12051
- import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync6, realpathSync as realpathSync3, writeFileSync as writeFileSync2 } from "fs";
12052
- import { basename as basename5, dirname as dirname5, join as join9, resolve as resolve7 } from "path";
12053
- import { homedir as homedir6 } from "os";
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";
12054
12164
 
12055
12165
  // src/lib/session-render-ownership.ts
12056
- import { existsSync as existsSync6, readFileSync as readFileSync5, statSync as statSync4 } from "fs";
12057
- import { dirname as dirname4, join as join8, parse as parse3, relative as relative3, sep } from "path";
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";
12058
12168
  var MANIFEST_ANCESTOR_LIMIT = 24;
12059
12169
  var MANAGED_PATH_SEGMENTS = SESSION_RENDER_EXCLUSIVE_MANAGED_PATHS.map((managedPath) => managedPath.split("/").filter(Boolean));
12060
12170
  var manifestCache = new Map;
@@ -12076,7 +12186,7 @@ function pathIsSessionRenderManagedDir(absolutePath2) {
12076
12186
  function readManifestRelativePaths(manifestPath) {
12077
12187
  let stats;
12078
12188
  try {
12079
- if (!existsSync6(manifestPath))
12189
+ if (!existsSync7(manifestPath))
12080
12190
  return null;
12081
12191
  stats = statSync4(manifestPath);
12082
12192
  } catch {
@@ -12105,7 +12215,7 @@ function sessionRenderManifestClaimsPath(absolutePath2) {
12105
12215
  const root = parse3(absolutePath2).root;
12106
12216
  let home = dirname4(absolutePath2);
12107
12217
  for (let depth = 0;depth < MANIFEST_ANCESTOR_LIMIT; depth += 1) {
12108
- const manifestPath = join8(home, ...SESSION_RENDER_MANIFEST_RELATIVE_PATH.split("/"));
12218
+ const manifestPath = join9(home, ...SESSION_RENDER_MANIFEST_RELATIVE_PATH.split("/"));
12109
12219
  const relativePaths = readManifestRelativePaths(manifestPath);
12110
12220
  if (relativePaths) {
12111
12221
  const claimed = relative3(home, absolutePath2).split(sep).join("/");
@@ -12125,13 +12235,13 @@ function sessionRenderOwnsPath(absolutePath2) {
12125
12235
 
12126
12236
  // src/lib/apply.ts
12127
12237
  function getConfigHome() {
12128
- return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir6();
12238
+ return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir7();
12129
12239
  }
12130
12240
  function expandPath(p) {
12131
12241
  if (p.startsWith("~/")) {
12132
- return resolve7(getConfigHome(), p.slice(2));
12242
+ return resolve8(getConfigHome(), p.slice(2));
12133
12243
  }
12134
- return resolve7(p);
12244
+ return resolve8(p);
12135
12245
  }
12136
12246
  function normalizeTargetPath(p) {
12137
12247
  const expanded = expandPath(p);
@@ -12141,9 +12251,9 @@ function normalizeTargetPath(p) {
12141
12251
  let current = expanded;
12142
12252
  const missingSegments = [];
12143
12253
  while (true) {
12144
- if (existsSync7(current)) {
12254
+ if (existsSync8(current)) {
12145
12255
  try {
12146
- return resolve7(realpathSync3(current), ...missingSegments);
12256
+ return resolve8(realpathSync3(current), ...missingSegments);
12147
12257
  } catch {
12148
12258
  return expanded;
12149
12259
  }
@@ -12172,11 +12282,11 @@ async function writeConfigResult(config, targetPath, content, opts, meta = {}) {
12172
12282
  }
12173
12283
  const path = expandPath(renderedTargetPath);
12174
12284
  const renderedForTarget = isCursorGlobalAuthorityPath(path) ? stampCursorGlobalAuthorityMarker(renderedContent) : renderedContent;
12175
- const previousContent = existsSync7(path) ? readFileSync6(path, "utf-8") : null;
12285
+ const previousContent = existsSync8(path) ? readFileSync6(path, "utf-8") : null;
12176
12286
  const changed = previousContent !== renderedForTarget;
12177
12287
  if (!opts.dryRun) {
12178
12288
  const dir = dirname5(path);
12179
- if (!existsSync7(dir)) {
12289
+ if (!existsSync8(dir)) {
12180
12290
  mkdirSync3(dir, { recursive: true });
12181
12291
  }
12182
12292
  if (previousContent !== null && changed) {
@@ -12210,7 +12320,7 @@ function wouldDestroyACredential(targetPath, renderedContent, format) {
12210
12320
  let current;
12211
12321
  try {
12212
12322
  const path = expandPath(targetPath);
12213
- if (!existsSync7(path))
12323
+ if (!existsSync8(path))
12214
12324
  return [];
12215
12325
  current = readFileSync6(path, "utf-8");
12216
12326
  } catch {
@@ -12536,14 +12646,14 @@ function sessionRendererOwnsCanonicalTarget(normalized, opts) {
12536
12646
  getConfigHome(),
12537
12647
  opts.vars?.["HOME_DIR"]
12538
12648
  ].filter((home) => typeof home === "string" && home.length > 0));
12539
- if ([...homes].some((home) => SESSION_RENDER_OWNED_CONFIG_TARGETS.some((relativePath) => normalized === normalizeTargetPath(join9(home, ...relativePath.split("/"))))))
12649
+ if ([...homes].some((home) => SESSION_RENDER_OWNED_CONFIG_TARGETS.some((relativePath) => normalized === normalizeTargetPath(join10(home, ...relativePath.split("/"))))))
12540
12650
  return true;
12541
12651
  return sessionRenderOwnsPath(normalized);
12542
12652
  }
12543
12653
 
12544
12654
  // src/lib/package-version.ts
12545
- import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
12546
- import { dirname as dirname6, join as join10 } from "path";
12655
+ import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
12656
+ import { dirname as dirname6, join as join11 } from "path";
12547
12657
  import { fileURLToPath } from "url";
12548
12658
  var cached = null;
12549
12659
  function getPackageVersion() {
@@ -12552,8 +12662,8 @@ function getPackageVersion() {
12552
12662
  try {
12553
12663
  let dir = dirname6(fileURLToPath(import.meta.url));
12554
12664
  for (let i = 0;i < 8; i++) {
12555
- const pkgPath = join10(dir, "package.json");
12556
- if (existsSync8(pkgPath)) {
12665
+ const pkgPath = join11(dir, "package.json");
12666
+ if (existsSync9(pkgPath)) {
12557
12667
  const pkg = JSON.parse(readFileSync7(pkgPath, "utf8"));
12558
12668
  if (pkg.name === "@hasna/instructions" && pkg.version) {
12559
12669
  cached = pkg.version;
@@ -12574,7 +12684,7 @@ function getPackageVersion() {
12574
12684
  import { createHash as createHash8 } from "crypto";
12575
12685
  import { spawnSync } from "child_process";
12576
12686
  import {
12577
- existsSync as existsSync9,
12687
+ existsSync as existsSync10,
12578
12688
  lstatSync as lstatSync4,
12579
12689
  mkdirSync as mkdirSync4,
12580
12690
  readFileSync as readFileSync8,
@@ -12582,8 +12692,8 @@ import {
12582
12692
  rmSync as rmSync3,
12583
12693
  writeFileSync as writeFileSync3
12584
12694
  } from "fs";
12585
- import { homedir as homedir7 } from "os";
12586
- import { dirname as dirname7, join as join11, parse as parse4, relative as relative4, resolve as resolve8 } from "path";
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";
12587
12697
  var INBOX_CONVERSATIONS_MINIMUM_VERSION = "0.5.28";
12588
12698
  var INBOX_SKILL_MARKERS = [
12589
12699
  [".claude", "skills", "inbox", "SKILL.md"],
@@ -12604,13 +12714,13 @@ function lstatOrNull(path) {
12604
12714
  }
12605
12715
  }
12606
12716
  function findSymlinkedAncestor(path) {
12607
- const normalized = resolve8(path);
12717
+ const normalized = resolve9(path);
12608
12718
  const parsed = parse4(normalized);
12609
12719
  let current = parsed.root;
12610
12720
  const rel = relative4(parsed.root, normalized);
12611
12721
  for (const segment of rel.split(/[\\/]+/).filter(Boolean)) {
12612
- current = join11(current, segment);
12613
- if (!existsSync9(current))
12722
+ current = join12(current, segment);
12723
+ if (!existsSync10(current))
12614
12724
  return null;
12615
12725
  if (lstatSync4(current).isSymbolicLink())
12616
12726
  return current;
@@ -12627,11 +12737,11 @@ function packagedInboxSkillPath(explicitPath) {
12627
12737
  if (explicitPath)
12628
12738
  return explicitPath;
12629
12739
  const candidates = [
12630
- join11(import.meta.dir, "..", "..", "assets", "skills", "inbox", "SKILL.md"),
12631
- join11(import.meta.dir, "..", "assets", "skills", "inbox", "SKILL.md"),
12632
- join11(process.cwd(), "assets", "skills", "inbox", "SKILL.md")
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")
12633
12743
  ];
12634
- const found = candidates.find((candidate) => existsSync9(candidate));
12744
+ const found = candidates.find((candidate) => existsSync10(candidate));
12635
12745
  if (!found) {
12636
12746
  throw new Error(`packaged inbox skill contract is missing (checked ${candidates.length} package-relative locations)`);
12637
12747
  }
@@ -12680,8 +12790,8 @@ function compareVersions(left, right) {
12680
12790
  }
12681
12791
  return 0;
12682
12792
  }
12683
- function inspectSkillMarkers(homeDir2) {
12684
- return INBOX_SKILL_MARKERS.map((parts) => join11(homeDir2, ...parts)).map((path) => {
12793
+ function inspectSkillMarkers(homeDir3) {
12794
+ return INBOX_SKILL_MARKERS.map((parts) => join12(homeDir3, ...parts)).map((path) => {
12685
12795
  const stat = lstatOrNull(path);
12686
12796
  if (!stat)
12687
12797
  return null;
@@ -12697,9 +12807,9 @@ function inspectSkillMarkers(homeDir2) {
12697
12807
  }).filter((snapshot) => snapshot !== null);
12698
12808
  }
12699
12809
  function inspectInbox(options) {
12700
- const homeDir2 = options.homeDir ?? homedir7();
12810
+ const homeDir3 = options.homeDir ?? homedir8();
12701
12811
  const runtimeCommand = options.conversationsCommand ?? "conversations";
12702
- const snapshots = inspectSkillMarkers(homeDir2);
12812
+ const snapshots = inspectSkillMarkers(homeDir3);
12703
12813
  const skillPresent = snapshots.length > 0;
12704
12814
  let canonicalContent = null;
12705
12815
  let canonicalSha256 = null;
@@ -13013,7 +13123,7 @@ async function getConfigsStatus(store = resolveConfigStore(), options = {}) {
13013
13123
  continue;
13014
13124
  knownTargets += 1;
13015
13125
  const targetPath = expandPath(config.target_path);
13016
- if (!existsSync10(targetPath)) {
13126
+ if (!existsSync11(targetPath)) {
13017
13127
  missingTargets += 1;
13018
13128
  continue;
13019
13129
  }
@@ -13109,8 +13219,8 @@ async function getConfigsStatus(store = resolveConfigStore(), options = {}) {
13109
13219
  }
13110
13220
  // src/lib/provider-context.ts
13111
13221
  import { createHash as createHash9 } from "crypto";
13112
- import { existsSync as existsSync11, mkdirSync as mkdirSync5, readFileSync as readFileSync10, writeFileSync as writeFileSync4 } from "fs";
13113
- import { join as join12 } from "path";
13222
+ import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as readFileSync10, writeFileSync as writeFileSync4 } from "fs";
13223
+ import { join as join13 } from "path";
13114
13224
  var PROVIDER_CONTEXT_DIR = ".hasna/provider-context";
13115
13225
  var PROVIDER_CONTEXT_MANIFEST = "manifest.json";
13116
13226
  var PROVIDER_CONTEXT_SCHEMA = "hasna.instructions.provider-context/v1";
@@ -13255,17 +13365,17 @@ function resolveAndRenderProviderContext(opts) {
13255
13365
  const recordedEndpoint = originAccepted ? `${opts.origin.host}${opts.origin.pathPrefix || ""}` : null;
13256
13366
  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;
13257
13367
  const content = renderProviderFragment(entry);
13258
- const dir = join12(opts.homeDir, PROVIDER_CONTEXT_DIR);
13259
- if (!existsSync11(dir))
13368
+ const dir = join13(opts.homeDir, PROVIDER_CONTEXT_DIR);
13369
+ if (!existsSync12(dir))
13260
13370
  mkdirSync5(dir, { recursive: true });
13261
13371
  const filename = `${entry ? entry.key : "invariant"}.md`;
13262
- const fragmentPath2 = join12(dir, filename);
13372
+ const fragmentPath2 = join13(dir, filename);
13263
13373
  const fragmentSha256 = sha2569(content);
13264
13374
  writeFileSync4(fragmentPath2, content, "utf8");
13265
- const manifestPath = join12(dir, PROVIDER_CONTEXT_MANIFEST);
13375
+ const manifestPath = join13(dir, PROVIDER_CONTEXT_MANIFEST);
13266
13376
  let manifest = { schema: PROVIDER_CONTEXT_SCHEMA, fragments: {} };
13267
13377
  try {
13268
- if (existsSync11(manifestPath)) {
13378
+ if (existsSync12(manifestPath)) {
13269
13379
  const parsed = JSON.parse(readFileSync10(manifestPath, "utf8"));
13270
13380
  if (parsed && typeof parsed === "object")
13271
13381
  manifest = parsed;
@@ -13377,9 +13487,9 @@ var PG_MIGRATIONS = [
13377
13487
  ];
13378
13488
  // src/lib/station-profile.ts
13379
13489
  import { spawnSync as spawnSync2 } from "child_process";
13380
- import { existsSync as existsSync12, lstatSync as lstatSync5, mkdirSync as mkdirSync6, readFileSync as readFileSync11, readdirSync, writeFileSync as writeFileSync5 } from "fs";
13381
- import { arch as osArch, homedir as homedir8, hostname as osHostname, platform as osPlatform, userInfo as osUserInfo } from "os";
13382
- import { dirname as dirname8, join as join13, resolve as resolve9 } from "path";
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";
13383
13493
  var STATION_PROFILE_CACHE_FILENAME = "station-profile.md";
13384
13494
  var STATION_PROFILE_SOURCE_ID = "station-profile";
13385
13495
  var STATION_PROFILE_LAYER = "machine";
@@ -13389,22 +13499,21 @@ var STATION_PROFILE_FULL_NAMES_MAX = 6;
13389
13499
  var STATION_PROFILE_PRIMARY_SCOPE = "@hasna";
13390
13500
  var MACHINES_MANIFEST_PATH_ENV = "HASNA_MACHINES_MANIFEST_PATH";
13391
13501
  var BUN_INSTALL_ENV = "BUN_INSTALL";
13392
- function homeDir2(env = process.env) {
13393
- return env["HOME"] || env["USERPROFILE"] || homedir8();
13502
+ function homeDir3(env = process.env) {
13503
+ return env["HOME"] || env["USERPROFILE"] || homedir9();
13394
13504
  }
13395
13505
  function getStationProfileCachePath(env = process.env) {
13396
- const root = env["HASNA_CONFIGS_HOME"] || join13(homeDir2(env), ".hasna", "instructions");
13397
- return join13(resolve9(root), STATION_PROFILE_CACHE_FILENAME);
13506
+ return join14(getRawStoreRoot(env), STATION_PROFILE_CACHE_FILENAME);
13398
13507
  }
13399
13508
  function getMachinesManifestPath(env = process.env) {
13400
- return env[MACHINES_MANIFEST_PATH_ENV] || join13(homeDir2(env), ".hasna", "machines", "machines.json");
13509
+ return env[MACHINES_MANIFEST_PATH_ENV] || join14(homeDir3(env), ".hasna", "machines", "machines.json");
13401
13510
  }
13402
13511
  function getBunGlobalModulesDir(env = process.env) {
13403
- return join13(env[BUN_INSTALL_ENV] || join13(homeDir2(env), ".bun"), "install", "global", "node_modules");
13512
+ return join14(env[BUN_INSTALL_ENV] || join14(homeDir3(env), ".bun"), "install", "global", "node_modules");
13404
13513
  }
13405
13514
  function readMachinesManifest(path) {
13406
13515
  try {
13407
- if (!existsSync12(path))
13516
+ if (!existsSync13(path))
13408
13517
  return null;
13409
13518
  const parsed = JSON.parse(readFileSync11(path, "utf8"));
13410
13519
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
@@ -13460,9 +13569,9 @@ function probeMachineStatus(machineId) {
13460
13569
  function resolveStationProfileMachine(env = process.env, options = {}) {
13461
13570
  const hostname2 = osHostname();
13462
13571
  const record = findLocalManifestMachine(readMachinesManifest(getMachinesManifestPath(env)), hostname2);
13463
- const home = homeDir2(env);
13572
+ const home = homeDir3(env);
13464
13573
  const platform = stringField(record, "platform") ?? osPlatform();
13465
- const workspacePath = stringField(record, "workspacePath") ?? join13(home, platform === "darwin" ? "Workspace" : "workspace");
13574
+ const workspacePath = stringField(record, "workspacePath") ?? join14(home, platform === "darwin" ? "Workspace" : "workspace");
13466
13575
  const machine = {
13467
13576
  id: stringField(record, "id") ?? hostname2,
13468
13577
  hostname: stringField(record, "hostname") ?? hostname2,
@@ -13479,9 +13588,9 @@ function resolveStationProfileMachine(env = process.env, options = {}) {
13479
13588
  return machine;
13480
13589
  }
13481
13590
  function scopedPackageNames(modulesDir, scope) {
13482
- const scopeDir = join13(modulesDir, scope);
13591
+ const scopeDir = join14(modulesDir, scope);
13483
13592
  try {
13484
- if (!existsSync12(scopeDir))
13593
+ if (!existsSync13(scopeDir))
13485
13594
  return null;
13486
13595
  return readdirNames(scopeDir).sort();
13487
13596
  } catch {
@@ -13491,7 +13600,7 @@ function scopedPackageNames(modulesDir, scope) {
13491
13600
  function readdirNames(dir) {
13492
13601
  return readdirSync(dir).filter((name) => {
13493
13602
  try {
13494
- return lstatSync5(join13(dir, name)).isDirectory();
13603
+ return lstatSync5(join14(dir, name)).isDirectory();
13495
13604
  } catch {
13496
13605
  return false;
13497
13606
  }
@@ -13501,7 +13610,7 @@ function resolveStationProfilePackages(env = process.env) {
13501
13610
  const modulesDir = getBunGlobalModulesDir(env);
13502
13611
  let scopeDirs;
13503
13612
  try {
13504
- if (!existsSync12(modulesDir))
13613
+ if (!existsSync13(modulesDir))
13505
13614
  return null;
13506
13615
  scopeDirs = readdirNames(modulesDir).filter((name) => name.startsWith("@") && name.toLowerCase().includes("hasna"));
13507
13616
  } catch {
@@ -13576,7 +13685,7 @@ function refreshStationProfile(options = {}) {
13576
13685
  const path = getStationProfileCachePath(env);
13577
13686
  const generatedAt = new Date().toISOString();
13578
13687
  if (!options.dryRun) {
13579
- const existing = existsSync12(path) ? readFileSync11(path, "utf8") : null;
13688
+ const existing = existsSync13(path) ? readFileSync11(path, "utf8") : null;
13580
13689
  if (existing !== content) {
13581
13690
  mkdirSync6(dirname8(path), { recursive: true });
13582
13691
  writeFileSync5(path, content, "utf8");
@@ -13595,7 +13704,7 @@ function refreshStationProfile(options = {}) {
13595
13704
  function readStationProfile(env = process.env) {
13596
13705
  const path = getStationProfileCachePath(env);
13597
13706
  try {
13598
- if (!existsSync12(path))
13707
+ if (!existsSync13(path))
13599
13708
  return null;
13600
13709
  return readFileSync11(path, "utf8");
13601
13710
  } catch {
@@ -13619,14 +13728,14 @@ function stationProfileSource(env = process.env) {
13619
13728
  // src/lib/session-apply.ts
13620
13729
  import { createHash as createHash10, randomUUID as randomUUID4 } from "crypto";
13621
13730
  import {
13622
- existsSync as existsSync13,
13731
+ existsSync as existsSync14,
13623
13732
  lstatSync as lstatSync6,
13624
13733
  mkdirSync as mkdirSync7,
13625
13734
  readFileSync as readFileSync12,
13626
13735
  readdirSync as readdirSync2,
13627
13736
  statSync as statSync5
13628
13737
  } from "fs";
13629
- import { dirname as dirname9, isAbsolute as isAbsolute4, join as join14, parse as parse5, relative as relative5, resolve as resolve10 } from "path";
13738
+ import { dirname as dirname9, isAbsolute as isAbsolute4, join as join15, parse as parse5, relative as relative5, resolve as resolve10 } from "path";
13630
13739
  class SessionApplyError extends Error {
13631
13740
  constructor(message) {
13632
13741
  super(message);
@@ -13757,7 +13866,7 @@ function assertClaudeAuthorityStillClear(plan, targetHome, ownedClaudeAuthoritie
13757
13866
  throw new SessionApplyError(`Claude authority changed after planning; refusing to apply: ${summary}`);
13758
13867
  }
13759
13868
  function ensureSessionTargetHome(targetHome) {
13760
- if (!existsSync13(targetHome))
13869
+ if (!existsSync14(targetHome))
13761
13870
  mkdirSync7(targetHome, { recursive: true, mode: 448 });
13762
13871
  assertSafeTargetHome(targetHome);
13763
13872
  }
@@ -13780,7 +13889,7 @@ function checkSessionRenderDrift(targetHome, manifestPath) {
13780
13889
  const drifted = [];
13781
13890
  for (const file of previousManifest.files) {
13782
13891
  const target = resolveManifestRelativePath(file.relativePath, safeTargetHome);
13783
- if (!existsSync13(target)) {
13892
+ if (!existsSync14(target)) {
13784
13893
  missing.push({
13785
13894
  path: target,
13786
13895
  relativePath: file.relativePath,
@@ -13932,7 +14041,7 @@ function requiredRestoreHash(file) {
13932
14041
  }
13933
14042
  function readSessionRenderSnapshot(snapshotPath) {
13934
14043
  const resolved = resolve10(snapshotPath);
13935
- if (!existsSync13(resolved))
14044
+ if (!existsSync14(resolved))
13936
14045
  throw new SessionApplyError(`Session snapshot not found: ${snapshotPath}`);
13937
14046
  const stat = lstatSync6(resolved);
13938
14047
  if (stat.isSymbolicLink() || !stat.isFile()) {
@@ -14199,7 +14308,7 @@ function resolveSnapshotFilePath(relativePath, recordedPath, targetHome) {
14199
14308
  }
14200
14309
  function planFileResult(plan, file, targetHome, previousHashes, previousManifest, options) {
14201
14310
  const target = resolvePlannedFilePath(plan, file, targetHome);
14202
- const previousContent = existsSync13(target) ? readFileSync12(target, "utf-8") : null;
14311
+ const previousContent = existsSync14(target) ? readFileSync12(target, "utf-8") : null;
14203
14312
  const previousSha256 = previousContent === null ? null : sha25610(previousContent);
14204
14313
  const previouslyManaged = isPreviouslyManaged(file, previousSha256, previousHashes, previousManifest);
14205
14314
  const changed = previousContent !== file.content;
@@ -14298,7 +14407,7 @@ function planStaleFileResults(plan, targetHome, previousManifest, currentRelativ
14298
14407
  }
14299
14408
  function planStaleFileResult(file, targetHome, options) {
14300
14409
  const target = resolveManifestRelativePath(file.relativePath, targetHome);
14301
- if (!existsSync13(target))
14410
+ if (!existsSync14(target))
14302
14411
  return null;
14303
14412
  const previousContent = readFileSync12(target, "utf-8");
14304
14413
  const previousSha256 = sha25610(previousContent);
@@ -14366,7 +14475,7 @@ function resolveManifestRelativePath(relativePath, targetHome) {
14366
14475
  return target;
14367
14476
  }
14368
14477
  function readPreviousManifest(path) {
14369
- if (!existsSync13(path))
14478
+ if (!existsSync14(path))
14370
14479
  return null;
14371
14480
  try {
14372
14481
  const parsed = JSON.parse(readFileSync12(path, "utf-8"));
@@ -14408,7 +14517,7 @@ function assertExpectedSessionFileHash(path, targetHome, expectedHash) {
14408
14517
  }
14409
14518
  function currentSessionFileHash(path, targetHome) {
14410
14519
  assertNoSymlinkSegments2(targetHome, path);
14411
- if (!existsSync13(path))
14520
+ if (!existsSync14(path))
14412
14521
  return null;
14413
14522
  const stat = lstatSync6(path);
14414
14523
  if (stat.isSymbolicLink() || !stat.isFile()) {
@@ -14423,7 +14532,7 @@ function requiredPreviousHash(result) {
14423
14532
  return result.previousSha256;
14424
14533
  }
14425
14534
  function writeSessionSnapshot(plan, targetHome, manifestPath, results, previousManifest, coordination, allowPortableFallback, forcePortableFileOps) {
14426
- const existingFiles = results.filter((result) => result.action === "update" || result.action === "delete").filter((result) => existsSync13(result.path)).map((result) => {
14535
+ const existingFiles = results.filter((result) => result.action === "update" || result.action === "delete").filter((result) => existsSync14(result.path)).map((result) => {
14427
14536
  const content = readFileSync12(result.path, "utf-8");
14428
14537
  return {
14429
14538
  path: result.path,
@@ -14495,7 +14604,7 @@ function assertSafeTargetHome(targetHome) {
14495
14604
  throw new SessionApplyError(`Session target home cannot be the filesystem root: ${targetHome}`);
14496
14605
  }
14497
14606
  assertNoSymlinkAncestors3(normalized);
14498
- if (existsSync13(normalized) && lstatSync6(normalized).isSymbolicLink()) {
14607
+ if (existsSync14(normalized) && lstatSync6(normalized).isSymbolicLink()) {
14499
14608
  throw new SessionApplyError(`Session target home cannot be a symlink: ${normalized}`);
14500
14609
  }
14501
14610
  return normalized;
@@ -14505,8 +14614,8 @@ function assertNoSymlinkSegments2(root, target) {
14505
14614
  const rel = relative5(root, target);
14506
14615
  let current = root;
14507
14616
  for (const segment of rel.split(/[\\/]+/).filter(Boolean)) {
14508
- current = join14(current, segment);
14509
- if (existsSync13(current) && lstatSync6(current).isSymbolicLink()) {
14617
+ current = join15(current, segment);
14618
+ if (existsSync14(current) && lstatSync6(current).isSymbolicLink()) {
14510
14619
  throw new SessionApplyError(`Session apply path uses a symlink: ${current}`);
14511
14620
  }
14512
14621
  }
@@ -14517,8 +14626,8 @@ function assertNoSymlinkAncestors3(path) {
14517
14626
  let current = parsed.root;
14518
14627
  const rel = relative5(parsed.root, normalized);
14519
14628
  for (const segment of rel.split(/[\\/]+/).filter(Boolean)) {
14520
- current = join14(current, segment);
14521
- if (!existsSync13(current))
14629
+ current = join15(current, segment);
14630
+ if (!existsSync14(current))
14522
14631
  return;
14523
14632
  if (lstatSync6(current).isSymbolicLink()) {
14524
14633
  throw new SessionApplyError(`Session apply path uses a symlink ancestor: ${current}`);
@@ -14829,13 +14938,13 @@ async function ensureDangerousOperationGuardStandardConfig(store = resolveConfig
14829
14938
  }
14830
14939
  }
14831
14940
  // src/lib/sync.ts
14832
- import { existsSync as existsSync15, readdirSync as readdirSync4, readFileSync as readFileSync14 } from "fs";
14833
- import { basename as basename6, extname as extname3, join as join16 } from "path";
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";
14834
14943
 
14835
14944
  // src/lib/sync-dir.ts
14836
- import { existsSync as existsSync14, readdirSync as readdirSync3, readFileSync as readFileSync13, statSync as statSync6 } from "fs";
14837
- import { join as join15, relative as relative6 } from "path";
14838
- import { homedir as homedir9 } from "os";
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";
14839
14948
  var SKIP = [".db", ".db-shm", ".db-wal", ".log", ".lock", ".DS_Store", "node_modules", ".git"];
14840
14949
  function shouldSkip(p) {
14841
14950
  return SKIP.some((s) => p.includes(s));
@@ -14843,11 +14952,11 @@ function shouldSkip(p) {
14843
14952
  async function syncFromDir(dir, opts = {}) {
14844
14953
  const store = opts.store ?? resolveConfigStore();
14845
14954
  const absDir = expandPath(dir);
14846
- if (!existsSync14(absDir))
14955
+ if (!existsSync15(absDir))
14847
14956
  return { added: 0, updated: 0, unchanged: 0, skipped: [`Not found: ${absDir}`] };
14848
- const files = opts.recursive !== false ? walkDir(absDir) : readdirSync3(absDir).map((f) => join15(absDir, f)).filter((f) => statSync6(f).isFile());
14957
+ const files = opts.recursive !== false ? walkDir(absDir) : readdirSync3(absDir).map((f) => join16(absDir, f)).filter((f) => statSync6(f).isFile());
14849
14958
  const result = { added: 0, updated: 0, unchanged: 0, skipped: [] };
14850
- const home = homedir9();
14959
+ const home = homedir10();
14851
14960
  const allConfigs = await store.listConfigs();
14852
14961
  for (const file of files) {
14853
14962
  if (shouldSkip(file)) {
@@ -14882,7 +14991,7 @@ async function syncFromDir(dir, opts = {}) {
14882
14991
  }
14883
14992
  async function syncToDir(dir, opts = {}) {
14884
14993
  const store = opts.store ?? resolveConfigStore();
14885
- const home = homedir9();
14994
+ const home = homedir10();
14886
14995
  const absDir = expandPath(dir);
14887
14996
  const normalized = dir.startsWith("~/") ? dir : absDir.replace(home, "~");
14888
14997
  const configs = (await store.listConfigs()).filter((c) => c.target_path && (c.target_path.startsWith(normalized) || c.target_path.startsWith(absDir)));
@@ -14906,7 +15015,7 @@ async function syncToDir(dir, opts = {}) {
14906
15015
  }
14907
15016
  function walkDir(dir, files = []) {
14908
15017
  for (const entry of readdirSync3(dir, { withFileTypes: true })) {
14909
- const full = join15(dir, entry.name);
15018
+ const full = join16(dir, entry.name);
14910
15019
  if (shouldSkip(full))
14911
15020
  continue;
14912
15021
  if (entry.isDirectory())
@@ -14967,7 +15076,7 @@ function isGeneratedOutputTarget2(config, owners) {
14967
15076
  return !!ownerIds && !ownerIds.has(config.id);
14968
15077
  }
14969
15078
  function hasClaudePromptSource() {
14970
- return existsSync15(expandPath("~/.claude/CLAUDE.md"));
15079
+ return existsSync16(expandPath("~/.claude/CLAUDE.md"));
14971
15080
  }
14972
15081
  function hasClaudeRuleSourceForCursorTarget(targetPath) {
14973
15082
  const absoluteTargetPath = expandPath(targetPath);
@@ -14975,7 +15084,7 @@ function hasClaudeRuleSourceForCursorTarget(targetPath) {
14975
15084
  if (!absoluteTargetPath.startsWith(`${absolutePrefix}/`) || !absoluteTargetPath.endsWith(".mdc"))
14976
15085
  return false;
14977
15086
  const stem = basename6(absoluteTargetPath, ".mdc");
14978
- return existsSync15(expandPath(`~/.claude/rules/${stem}.md`)) || existsSync15(expandPath(`~/.claude/rules/${stem}.mdc`));
15087
+ return existsSync16(expandPath(`~/.claude/rules/${stem}.md`)) || existsSync16(expandPath(`~/.claude/rules/${stem}.mdc`));
14979
15088
  }
14980
15089
  function isKnownGeneratedTargetPath(targetPath) {
14981
15090
  const normalizedTargetPath = normalizeTargetPath(targetPath);
@@ -15040,8 +15149,8 @@ async function syncProject(opts) {
15040
15149
  const allConfigs = await store.listConfigs();
15041
15150
  const machine = detectMachineContext();
15042
15151
  for (const pf of PROJECT_CONFIG_FILES) {
15043
- const abs = join16(absDir, pf.file);
15044
- if (!existsSync15(abs))
15152
+ const abs = join17(absDir, pf.file);
15153
+ if (!existsSync16(abs))
15045
15154
  continue;
15046
15155
  try {
15047
15156
  const rawContent = readFileSync14(abs, "utf-8");
@@ -15073,19 +15182,19 @@ async function syncProject(opts) {
15073
15182
  }
15074
15183
  }
15075
15184
  for (const ruleDir of [
15076
- { dir: join16(absDir, ".claude", "rules"), agent: "claude", namePrefix: "rules" },
15077
- { dir: join16(absDir, ".agents", "rules"), agent: "antigravity", namePrefix: "antigravity-rules" },
15078
- { dir: join16(absDir, ".cursor", "rules"), agent: "cursor", namePrefix: "cursor-rules" },
15079
- { dir: join16(absDir, ".github", "instructions"), agent: "copilot", namePrefix: "copilot-instructions" },
15080
- { dir: join16(absDir, ".devin", "rules"), agent: "devin", namePrefix: "devin-rules" },
15081
- { dir: join16(absDir, ".windsurf", "rules"), agent: "windsurf-legacy", namePrefix: "windsurf-rules" },
15082
- { dir: join16(absDir, ".clinerules"), agent: "cline", namePrefix: "cline-rules" }
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" }
15083
15192
  ]) {
15084
- if (!existsSync15(ruleDir.dir))
15193
+ if (!existsSync16(ruleDir.dir))
15085
15194
  continue;
15086
15195
  const mdFiles = readdirSync4(ruleDir.dir).filter((f) => f.endsWith(".md") || f.endsWith(".mdc"));
15087
15196
  for (const f of mdFiles) {
15088
- const abs = join16(ruleDir.dir, f);
15197
+ const abs = join17(ruleDir.dir, f);
15089
15198
  const raw = readFileSync14(abs, "utf-8");
15090
15199
  const redacted = redactContent(raw, "markdown");
15091
15200
  const machineAware = templateizeMachineContent(redacted.content, machine);
@@ -15125,14 +15234,14 @@ async function syncKnown(opts = {}) {
15125
15234
  for (const known of targets) {
15126
15235
  if (known.rulesDir) {
15127
15236
  const absDir = expandPath(known.rulesDir);
15128
- if (!existsSync15(absDir)) {
15237
+ if (!existsSync16(absDir)) {
15129
15238
  result.skipped.push(known.rulesDir);
15130
15239
  continue;
15131
15240
  }
15132
15241
  const extensions = known.rulesExtensions ?? [".md", ".mdc"];
15133
15242
  const ruleFiles = readdirSync4(absDir).filter((f) => extensions.some((ext) => f.endsWith(ext)));
15134
15243
  for (const f of ruleFiles) {
15135
- const abs2 = join16(absDir, f);
15244
+ const abs2 = join17(absDir, f);
15136
15245
  const targetPath = abs2.replace(home, "~");
15137
15246
  if (existingOutputOwners.has(normalizeTargetPath(targetPath)) || isKnownGeneratedTargetPath(targetPath)) {
15138
15247
  result.skipped.push(`${targetPath} (generated output)`);
@@ -15166,7 +15275,7 @@ async function syncKnown(opts = {}) {
15166
15275
  continue;
15167
15276
  }
15168
15277
  const abs = expandPath(known.path);
15169
- if (!existsSync15(abs)) {
15278
+ if (!existsSync16(abs)) {
15170
15279
  result.skipped.push(known.path);
15171
15280
  continue;
15172
15281
  }
@@ -15274,7 +15383,7 @@ function storedPlaceholderIsLiteralOnDisk(storedLine, diskLine) {
15274
15383
  }
15275
15384
  function buildDiff(expectedContent, targetPath, storedFormat, showSecrets) {
15276
15385
  const path = expandPath(targetPath);
15277
- if (!existsSync15(path))
15386
+ if (!existsSync16(path))
15278
15387
  return `(file not found on disk: ${path})`;
15279
15388
  const diskContent = readFileSync14(path, "utf-8");
15280
15389
  if (diskContent === expectedContent)
@@ -15434,15 +15543,15 @@ function detectFormat(filePath) {
15434
15543
  return "text";
15435
15544
  }
15436
15545
  // src/lib/export.ts
15437
- import { existsSync as existsSync16, mkdirSync as mkdirSync8, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "fs";
15438
- import { join as join17, resolve as resolve11 } from "path";
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";
15439
15548
  import { tmpdir } from "os";
15440
15549
  async function exportConfigs(outputPath, opts = {}) {
15441
15550
  const store = opts.store ?? resolveConfigStore();
15442
15551
  const configs = await store.listConfigs(opts.filter);
15443
15552
  const absOutput = resolve11(outputPath);
15444
- const tmpDir = join17(tmpdir(), `configs-export-${Date.now()}`);
15445
- const contentsDir = join17(tmpDir, "contents");
15553
+ const tmpDir = join18(tmpdir(), `configs-export-${Date.now()}`);
15554
+ const contentsDir = join18(tmpDir, "contents");
15446
15555
  try {
15447
15556
  mkdirSync8(contentsDir, { recursive: true });
15448
15557
  const manifest = {
@@ -15450,10 +15559,10 @@ async function exportConfigs(outputPath, opts = {}) {
15450
15559
  exported_at: new Date().toISOString(),
15451
15560
  configs: configs.map(({ content: _content, ...meta }) => meta)
15452
15561
  };
15453
- writeFileSync6(join17(tmpDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
15562
+ writeFileSync6(join18(tmpDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
15454
15563
  for (const config of configs) {
15455
15564
  const fileName = `${config.slug}.${config.format === "text" ? "txt" : config.format}`;
15456
- writeFileSync6(join17(contentsDir, fileName), config.content, "utf-8");
15565
+ writeFileSync6(join18(contentsDir, fileName), config.content, "utf-8");
15457
15566
  }
15458
15567
  const proc = Bun.spawn(["tar", "czf", absOutput, "-C", tmpDir, "."], {
15459
15568
  stdout: "pipe",
@@ -15466,20 +15575,20 @@ async function exportConfigs(outputPath, opts = {}) {
15466
15575
  }
15467
15576
  return { path: absOutput, count: configs.length };
15468
15577
  } finally {
15469
- if (existsSync16(tmpDir)) {
15578
+ if (existsSync17(tmpDir)) {
15470
15579
  rmSync4(tmpDir, { recursive: true, force: true });
15471
15580
  }
15472
15581
  }
15473
15582
  }
15474
15583
  // src/lib/import.ts
15475
- import { existsSync as existsSync17, mkdirSync as mkdirSync9, readFileSync as readFileSync15, rmSync as rmSync5 } from "fs";
15476
- import { join as join18, resolve as resolve12 } from "path";
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";
15477
15586
  import { tmpdir as tmpdir2 } from "os";
15478
15587
  async function importConfigs(bundlePath, opts = {}) {
15479
15588
  const store = opts.store ?? resolveConfigStore();
15480
15589
  const conflict = opts.conflict ?? "skip";
15481
15590
  const absPath = resolve12(bundlePath);
15482
- const tmpDir = join18(tmpdir2(), `configs-import-${Date.now()}`);
15591
+ const tmpDir = join19(tmpdir2(), `configs-import-${Date.now()}`);
15483
15592
  const result = { created: 0, updated: 0, skipped: 0, errors: [] };
15484
15593
  try {
15485
15594
  mkdirSync9(tmpDir, { recursive: true });
@@ -15492,15 +15601,15 @@ async function importConfigs(bundlePath, opts = {}) {
15492
15601
  const stderr = await new Response(proc.stderr).text();
15493
15602
  throw new Error(`tar extraction failed: ${stderr}`);
15494
15603
  }
15495
- const manifestPath = join18(tmpDir, "manifest.json");
15496
- if (!existsSync17(manifestPath))
15604
+ const manifestPath = join19(tmpDir, "manifest.json");
15605
+ if (!existsSync18(manifestPath))
15497
15606
  throw new Error("Invalid bundle: missing manifest.json");
15498
15607
  const manifest = JSON.parse(readFileSync15(manifestPath, "utf-8"));
15499
15608
  for (const meta of manifest.configs) {
15500
15609
  try {
15501
15610
  const ext = meta.format === "text" ? "txt" : meta.format;
15502
- const contentFile = join18(tmpDir, "contents", `${meta.slug}.${ext}`);
15503
- const content = existsSync17(contentFile) ? readFileSync15(contentFile, "utf-8") : "";
15611
+ const contentFile = join19(tmpDir, "contents", `${meta.slug}.${ext}`);
15612
+ const content = existsSync18(contentFile) ? readFileSync15(contentFile, "utf-8") : "";
15504
15613
  let existing = null;
15505
15614
  try {
15506
15615
  existing = await store.getConfig(meta.slug);
@@ -15534,16 +15643,16 @@ async function importConfigs(bundlePath, opts = {}) {
15534
15643
  }
15535
15644
  return result;
15536
15645
  } finally {
15537
- if (existsSync17(tmpDir)) {
15646
+ if (existsSync18(tmpDir)) {
15538
15647
  rmSync5(tmpDir, { recursive: true, force: true });
15539
15648
  }
15540
15649
  }
15541
15650
  }
15542
15651
  // src/lib/package-manager-guard.ts
15543
15652
  import { execFileSync as execFileSync2 } from "child_process";
15544
- import { existsSync as existsSync18, lstatSync as lstatSync7, readdirSync as readdirSync5, readFileSync as readFileSync16 } from "fs";
15545
- import { homedir as homedir10 } from "os";
15546
- import { basename as basename7, dirname as dirname10, isAbsolute as isAbsolute5, join as join19, relative as relative7, resolve as resolve13 } from "path";
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";
15547
15656
  var SKIP_DIRS = new Set([
15548
15657
  ".git",
15549
15658
  "node_modules",
@@ -15585,7 +15694,7 @@ function scanPackageManagerSecrets(options = {}) {
15585
15694
  const findings = [];
15586
15695
  let scannedFiles = 0;
15587
15696
  for (const root of roots) {
15588
- if (!existsSync18(root))
15697
+ if (!existsSync19(root))
15589
15698
  continue;
15590
15699
  const stat = lstatSync7(root);
15591
15700
  if (stat.isFile()) {
@@ -15612,10 +15721,10 @@ function scanPackageManagerSecrets(options = {}) {
15612
15721
  }
15613
15722
  }
15614
15723
  if (options.includeHome) {
15615
- const home = homedir10();
15724
+ const home = homedir11();
15616
15725
  for (const name of HOME_FILES) {
15617
- const file = join19(home, name);
15618
- if (!existsSync18(file))
15726
+ const file = join20(home, name);
15727
+ if (!existsSync19(file))
15619
15728
  continue;
15620
15729
  const text = readTextFile(file);
15621
15730
  if (text === null)
@@ -15639,12 +15748,12 @@ function collectRepoFiles(root) {
15639
15748
  if (entry.isDirectory()) {
15640
15749
  if (SKIP_DIRS.has(entry.name))
15641
15750
  continue;
15642
- visit(join19(dir, entry.name));
15751
+ visit(join20(dir, entry.name));
15643
15752
  continue;
15644
15753
  }
15645
15754
  if (!entry.isFile())
15646
15755
  continue;
15647
- const file = join19(dir, entry.name);
15756
+ const file = join20(dir, entry.name);
15648
15757
  if (shouldScanRepoFile(file))
15649
15758
  out.push(file);
15650
15759
  }
@@ -15912,7 +16021,7 @@ function stripInlineComment(value) {
15912
16021
  return value.replace(/\s[#;].*$/, "").trim();
15913
16022
  }
15914
16023
  function displayPath(file, root) {
15915
- const home = homedir10();
16024
+ const home = homedir11();
15916
16025
  if (root === home && (file === home || file.startsWith(home + "/")))
15917
16026
  return "~/" + toPosix(relative7(home, file));
15918
16027
  if (isAbsolute5(root) && file.startsWith(root + "/"))