@hasna/instructions 0.4.8 → 0.4.9

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
@@ -1100,11 +1100,11 @@ function resolveConfigStore(env = process.env) {
1100
1100
  return cloud ? new CloudConfigStore(cloud) : new LocalConfigStore;
1101
1101
  }
1102
1102
  // src/status.ts
1103
- import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
1103
+ import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
1104
1104
 
1105
1105
  // src/lib/apply.ts
1106
- import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync3, realpathSync as realpathSync2, writeFileSync as writeFileSync2 } from "fs";
1107
- import { basename as basename4, dirname as dirname3, join as join5, resolve as resolve3 } from "path";
1106
+ import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync4, realpathSync as realpathSync2, writeFileSync as writeFileSync2 } from "fs";
1107
+ import { basename as basename4, dirname as dirname4, join as join6, resolve as resolve3 } from "path";
1108
1108
  import { homedir as homedir3 } from "os";
1109
1109
 
1110
1110
  // src/lib/config-agents.ts
@@ -1127,18 +1127,23 @@ function retiredOrUnsupportedAgentReason(agent) {
1127
1127
  }
1128
1128
 
1129
1129
  // src/lib/session-render.ts
1130
- import { createHash as createHash2 } from "crypto";
1130
+ import { createHash as createHash3 } from "crypto";
1131
1131
  import { existsSync as existsSync4, readFileSync as readFileSync2, realpathSync, statSync as statSync2 } from "fs";
1132
1132
  import { homedir as homedir2 } from "os";
1133
1133
  import { basename as basename3, dirname as dirname2, extname as extname2, isAbsolute as isAbsolute2, join as join4, parse as parse2, posix, relative as relative2, resolve as resolve2 } from "path";
1134
1134
 
1135
1135
  // src/lib/global-agent-rules-standard.ts
1136
+ import { createHash } from "crypto";
1136
1137
  var GLOBAL_AGENT_RULES_STANDARD_SLUG = "global-agent-rules-standard";
1137
1138
  var AGENT_OPERATING_RULES_SOURCE_SET_ID = "hasna-global-agent-rules-standard";
1138
1139
  var AGENT_OPERATING_RULES_SOURCE_ID = "hasna-agent-operating-rules";
1140
+ var AGENT_OPERATING_RULES_ROLE = "agent-operating-rules";
1139
1141
  var AGENT_OPERATING_RULES_VERSION = "1.1.6";
1140
1142
  var AGENT_OPERATING_RULES_SOURCE_SET_VERSION = "2026-07-23";
1141
1143
  var AGENT_OPERATING_RULES_SENTINEL = "<!-- hasna:agent-operating-rules v=1.1.6 -->";
1144
+ var AGENT_OPERATING_RULES_SEMANTIC_POLICY_KEY = "hasna:agent-operating-rules";
1145
+ var AGENT_OPERATING_RULES_SENTINEL_PATTERN = /<!--\s*hasna:agent-operating-rules\s+v=([0-9]+\.[0-9]+\.[0-9]+)\s*-->/i;
1146
+ var AGENT_OPERATING_RULES_HEADING_PATTERN = /^#\s*Hasna Agent Operating Rules\s+\u2014\s+v[0-9]+\.[0-9]+\.[0-9]+\s+\(([0-9]{4}-[0-9]{2}-[0-9]{2})\)/;
1142
1147
  var AGENT_OPERATING_RULES_PAYLOAD_SHA256 = "8b236086b82e94490516e0b00dffa03fb5f6841b68d95f80fc3e3c8fb7087420";
1143
1148
  var AGENT_OPERATING_RULES_UPSTREAM_FILE_SHA256 = "b8e89cdb49e207e5b497ac51384d67022b94fe5645cc9273db60384eb2c2fb32";
1144
1149
  var SCOPED_OPERATIONAL_CONTROL_POLICY_REFERENCE = "hasna-agent-operating-rules/scoped-operational-control/v1";
@@ -1170,7 +1175,7 @@ var AGENT_OPERATING_RULES_PROVENANCE = {
1170
1175
  };
1171
1176
  var AGENT_OPERATING_RULES_METADATA = {
1172
1177
  sourceSet: AGENT_OPERATING_RULES_SOURCE_SET_ID,
1173
- role: "agent-operating-rules",
1178
+ role: AGENT_OPERATING_RULES_ROLE,
1174
1179
  rulesVersion: AGENT_OPERATING_RULES_VERSION,
1175
1180
  sourceSetVersion: AGENT_OPERATING_RULES_SOURCE_SET_VERSION,
1176
1181
  plan: GLOBAL_AGENT_RULES_STANDARD_SLUG,
@@ -1179,7 +1184,7 @@ var AGENT_OPERATING_RULES_METADATA = {
1179
1184
  upstreamFileSha256: AGENT_OPERATING_RULES_UPSTREAM_FILE_SHA256,
1180
1185
  upstreamExportId: AGENT_OPERATING_RULES_SOURCE_SET_ID,
1181
1186
  upstreamSourceId: AGENT_OPERATING_RULES_SOURCE_ID,
1182
- sentinel: "hasna:agent-operating-rules",
1187
+ sentinel: AGENT_OPERATING_RULES_SEMANTIC_POLICY_KEY,
1183
1188
  policyReferences: {
1184
1189
  incidentRecovery: SCOPED_OPERATIONAL_CONTROL_POLICY_REFERENCE
1185
1190
  }
@@ -1219,37 +1224,120 @@ var GLOBAL_AGENT_RULES_STANDARD_CONTENT = [
1219
1224
  ].join(`
1220
1225
  `) + `
1221
1226
  `;
1222
- async function ensureGlobalAgentRulesStandardConfig(store = resolveConfigStore()) {
1223
- const input = {
1227
+ function parseAgentOperatingRulesVersion(content) {
1228
+ return content ? AGENT_OPERATING_RULES_SENTINEL_PATTERN.exec(content)?.[1] ?? null : null;
1229
+ }
1230
+ function compareAgentOperatingRulesVersions(left, right) {
1231
+ const leftParts = left.split(".").map(Number);
1232
+ const rightParts = right.split(".").map(Number);
1233
+ for (let i = 0;i < 3; i++) {
1234
+ const diff = (leftParts[i] ?? 0) - (rightParts[i] ?? 0);
1235
+ if (diff !== 0)
1236
+ return diff;
1237
+ }
1238
+ return 0;
1239
+ }
1240
+ function payloadDate(content) {
1241
+ const canonical = new RegExp(AGENT_OPERATING_RULES_HEADING_PATTERN.source, "m").exec(content)?.[1];
1242
+ if (canonical)
1243
+ return canonical;
1244
+ const heading = /^#[^\S\n].*$/m.exec(content)?.[0];
1245
+ return heading ? /\b([0-9]{4}-[0-9]{2}-[0-9]{2})\b/.exec(heading)?.[1] ?? null : null;
1246
+ }
1247
+ function sha256(content) {
1248
+ return createHash("sha256").update(content).digest("hex");
1249
+ }
1250
+ function resolveAgentOperatingRulesPayload(storedContent) {
1251
+ const stored = storedContent ?? "";
1252
+ const storedVersion = parseAgentOperatingRulesVersion(stored);
1253
+ const baselineOrder = storedVersion === null ? null : compareAgentOperatingRulesVersions(storedVersion, AGENT_OPERATING_RULES_VERSION);
1254
+ const storedIsCurrent = baselineOrder !== null && (baselineOrder > 0 || baselineOrder === 0 && sha256(stored) === AGENT_OPERATING_RULES_PAYLOAD_SHA256);
1255
+ const content = storedIsCurrent ? stored : GLOBAL_AGENT_RULES_STANDARD_CONTENT;
1256
+ const origin = storedIsCurrent ? "stored-config" : "embedded-baseline";
1257
+ const matchesEmbeddedBaseline = content === GLOBAL_AGENT_RULES_STANDARD_CONTENT;
1258
+ const integrity = matchesEmbeddedBaseline ? "pinned-digest" : "unverified-self-declared";
1259
+ const version = storedIsCurrent ? storedVersion : AGENT_OPERATING_RULES_VERSION;
1260
+ const payloadSha256 = matchesEmbeddedBaseline ? AGENT_OPERATING_RULES_PAYLOAD_SHA256 : sha256(content);
1261
+ const sourceSetVersion = matchesEmbeddedBaseline ? AGENT_OPERATING_RULES_SOURCE_SET_VERSION : payloadDate(content);
1262
+ const upstreamPin = matchesEmbeddedBaseline ? {
1263
+ upstreamRepository: AGENT_OPERATING_RULES_UPSTREAM.repository,
1264
+ upstreamCommit: AGENT_OPERATING_RULES_UPSTREAM.commit,
1265
+ upstreamPath: AGENT_OPERATING_RULES_UPSTREAM.path,
1266
+ upstreamFileSha256: AGENT_OPERATING_RULES_UPSTREAM_FILE_SHA256
1267
+ } : {};
1268
+ const policyReference = content.includes(SCOPED_OPERATIONAL_CONTROL_POLICY_REFERENCE) ? { policyReference: SCOPED_OPERATIONAL_CONTROL_POLICY_REFERENCE } : {};
1269
+ return {
1270
+ content,
1271
+ version,
1272
+ origin,
1273
+ matchesEmbeddedBaseline,
1274
+ integrity,
1275
+ provenance: {
1276
+ source: AGENT_OPERATING_RULES_PROVENANCE.source,
1277
+ payloadOrigin: origin,
1278
+ payloadIntegrity: integrity,
1279
+ ...upstreamPin,
1280
+ upstreamExportId: AGENT_OPERATING_RULES_SOURCE_SET_ID,
1281
+ upstreamSourceId: AGENT_OPERATING_RULES_SOURCE_ID,
1282
+ selectedPayloadSha256: payloadSha256,
1283
+ rulesVersion: version,
1284
+ sourceSetVersion,
1285
+ ...policyReference
1286
+ },
1287
+ metadata: {
1288
+ sourceSet: AGENT_OPERATING_RULES_SOURCE_SET_ID,
1289
+ role: AGENT_OPERATING_RULES_METADATA.role,
1290
+ payloadOrigin: origin,
1291
+ payloadIntegrity: integrity,
1292
+ rulesVersion: version,
1293
+ sourceSetVersion,
1294
+ plan: GLOBAL_AGENT_RULES_STANDARD_SLUG,
1295
+ contentSha256: payloadSha256,
1296
+ selectedPayloadSha256: payloadSha256,
1297
+ ...matchesEmbeddedBaseline ? { upstreamFileSha256: AGENT_OPERATING_RULES_UPSTREAM_FILE_SHA256 } : {},
1298
+ upstreamExportId: AGENT_OPERATING_RULES_SOURCE_SET_ID,
1299
+ upstreamSourceId: AGENT_OPERATING_RULES_SOURCE_ID,
1300
+ sentinel: AGENT_OPERATING_RULES_METADATA.sentinel,
1301
+ ...policyReference.policyReference ? { policyReferences: { incidentRecovery: SCOPED_OPERATIONAL_CONTROL_POLICY_REFERENCE } } : {}
1302
+ }
1303
+ };
1304
+ }
1305
+ function standardConfigInput(payload) {
1306
+ return {
1224
1307
  name: "Global Agent Rules Standard",
1225
1308
  category: "rules",
1226
1309
  agent: "global",
1227
1310
  format: "markdown",
1228
- content: GLOBAL_AGENT_RULES_STANDARD_CONTENT,
1311
+ content: payload.content,
1229
1312
  kind: "reference",
1230
- description: `Managed Hasna agent operating rules v${AGENT_OPERATING_RULES_VERSION}; accepted source ${AGENT_OPERATING_RULES_UPSTREAM.repository}@${AGENT_OPERATING_RULES_UPSTREAM.commit}:${AGENT_OPERATING_RULES_UPSTREAM.path}`,
1313
+ description: payload.matchesEmbeddedBaseline ? `Managed Hasna agent operating rules v${payload.version}; accepted source ${AGENT_OPERATING_RULES_UPSTREAM.repository}@${AGENT_OPERATING_RULES_UPSTREAM.commit}:${AGENT_OPERATING_RULES_UPSTREAM.path}` : `Managed Hasna agent operating rules v${payload.version}; stored payload sha256 ${payload.metadata["contentSha256"]}`,
1231
1314
  tags: [
1232
1315
  "global-agent-rules",
1233
1316
  "system-prompt",
1234
1317
  "coding-agent-rules",
1235
1318
  "agent-operating-rules",
1236
- `rules-version:${AGENT_OPERATING_RULES_VERSION}`,
1237
- `source-commit:${AGENT_OPERATING_RULES_UPSTREAM.commit}`
1319
+ `rules-version:${payload.version}`,
1320
+ ...payload.matchesEmbeddedBaseline ? [`source-commit:${AGENT_OPERATING_RULES_UPSTREAM.commit}`] : []
1238
1321
  ]
1239
1322
  };
1323
+ }
1324
+ async function ensureGlobalAgentRulesStandardConfig(store = resolveConfigStore()) {
1325
+ let existing;
1240
1326
  try {
1241
- const existing = await store.getConfig(GLOBAL_AGENT_RULES_STANDARD_SLUG);
1242
- if (existing.content !== input.content || existing.description !== input.description || existing.category !== input.category || existing.agent !== input.agent || existing.format !== input.format || existing.kind !== input.kind || JSON.stringify(existing.tags) !== JSON.stringify(input.tags)) {
1243
- return await store.updateConfig(existing.id, input);
1244
- }
1245
- return existing;
1327
+ existing = await store.getConfig(GLOBAL_AGENT_RULES_STANDARD_SLUG);
1246
1328
  } catch {
1247
- return await store.createConfig(input);
1329
+ return await store.createConfig(standardConfigInput(resolveAgentOperatingRulesPayload(null)));
1330
+ }
1331
+ const payload = resolveAgentOperatingRulesPayload(existing.content);
1332
+ const input = standardConfigInput(payload);
1333
+ if (existing.content !== input.content || existing.description !== input.description || existing.category !== input.category || existing.agent !== input.agent || existing.format !== input.format || existing.kind !== input.kind || JSON.stringify(existing.tags) !== JSON.stringify(input.tags)) {
1334
+ return await store.updateConfig(existing.id, input);
1248
1335
  }
1336
+ return existing;
1249
1337
  }
1250
1338
 
1251
1339
  // src/lib/project-context.ts
1252
- import { createHash, randomUUID as randomUUID3 } from "crypto";
1340
+ import { createHash as createHash2, randomUUID as randomUUID3 } from "crypto";
1253
1341
  import { execFileSync } from "child_process";
1254
1342
  import { dlopen, FFIType } from "bun:ffi";
1255
1343
  import {
@@ -5432,6 +5520,10 @@ function hasSecrets(content, format) {
5432
5520
  var CODEWITH_NATIVE_IMPORTS_ENV = "HASNA_CONFIGS_CODEWITH_NATIVE_IMPORTS";
5433
5521
  var SESSION_RENDER_MANAGED_MARKER = "Managed by @hasna/configs session render";
5434
5522
  var SESSION_RENDER_SCHEMA = "hasna.configs.session-render/v1";
5523
+ var SESSION_RENDER_MANAGED_NAMESPACE = ".hasna";
5524
+ var SESSION_RENDER_INSTRUCTIONS_MANAGED_DIR = `${SESSION_RENDER_MANAGED_NAMESPACE}/instructions`;
5525
+ var SESSION_RENDER_MANIFEST_RELATIVE_PATH = `${SESSION_RENDER_MANAGED_NAMESPACE}/session-render-manifest.json`;
5526
+ var SESSION_RENDER_SNAPSHOT_RELATIVE_DIR = `${SESSION_RENDER_MANAGED_NAMESPACE}/session-render-snapshots`;
5435
5527
  var SESSION_INSTRUCTION_LAYERS = [
5436
5528
  "global",
5437
5529
  "tool",
@@ -5608,7 +5700,7 @@ class ProjectContextHashRace extends Error {
5608
5700
  }
5609
5701
  function computeProjectContextSourceHash(value) {
5610
5702
  const normalized = removeHashForFingerprint(value);
5611
- return `sha256:${sha256(stableStringify(normalized))}`;
5703
+ return `sha256:${sha2562(stableStringify(normalized))}`;
5612
5704
  }
5613
5705
  function parseProjectContextBundle(input) {
5614
5706
  let encoded;
@@ -5778,7 +5870,7 @@ function composeProjectContextSessionRender(input) {
5778
5870
  const files = input.files.map((file) => file === index ? {
5779
5871
  ...file,
5780
5872
  content,
5781
- sha256: sha256(content),
5873
+ sha256: sha2562(content),
5782
5874
  sourceIds: [...new Set([...file.sourceIds, "project-context-bundle"])]
5783
5875
  } : file);
5784
5876
  if (observedHashes.some((observed) => currentFileHash(observed.path, workspaceRoot) !== observed.sha256)) {
@@ -5979,7 +6071,7 @@ function assertRenderedOutputsStable(plan, cacheContent, sessionOutput) {
5979
6071
  sessionOutput
5980
6072
  ];
5981
6073
  for (const output of outputs) {
5982
- if (currentFileHash(output.path, plan.workspace_root) !== sha256(output.content)) {
6074
+ if (currentFileHash(output.path, plan.workspace_root) !== sha2562(output.content)) {
5983
6075
  throw new ProjectContextHashRace(`managed path changed before manifest commit: ${relativePosix(plan.workspace_root, output.path)}`);
5984
6076
  }
5985
6077
  }
@@ -6199,7 +6291,7 @@ function findLegacyCodewithWorkspaceSection(workspaceRoot, runtime, content, bun
6199
6291
  return null;
6200
6292
  const files = Array.isArray(manifest["files"]) ? manifest["files"] : [];
6201
6293
  const codewith = files.find((file) => isRecord(file) && file["relativePath"] === "CODEWITH.md");
6202
- if (!isRecord(codewith) || codewith["sha256"] !== sha256(content)) {
6294
+ if (!isRecord(codewith) || codewith["sha256"] !== sha2562(content)) {
6203
6295
  throw new ProjectContextError("MANAGED_BLOCK_CONFLICT", "legacy /dev/fd session manifest does not match CODEWITH.md");
6204
6296
  }
6205
6297
  const section = /^## Workspace\r?\n/gm.exec(content);
@@ -6269,14 +6361,14 @@ function buildManifest(plan, now2) {
6269
6361
  path: plan.fragment_path,
6270
6362
  relativePath: PROJECT_CONTEXT_FRAGMENT_PATH,
6271
6363
  role: "fragment",
6272
- sha256: sha256(plan.fragment),
6364
+ sha256: sha2562(plan.fragment),
6273
6365
  sourceIds: ["project-context-bundle"]
6274
6366
  },
6275
6367
  {
6276
6368
  path: plan.target_path,
6277
6369
  relativePath: plan.target_relative_path,
6278
6370
  role: "index",
6279
- sha256: sha256(plan.target_content),
6371
+ sha256: sha2562(plan.target_content),
6280
6372
  sourceIds: ["project-context-bundle"]
6281
6373
  }
6282
6374
  ];
@@ -6353,7 +6445,7 @@ function buildSessionCompatibilityManifest(plan, now2) {
6353
6445
  path: plan.target_path,
6354
6446
  relativePath: targetRelativePath,
6355
6447
  role: "index",
6356
- sha256: sha256(plan.target_content),
6448
+ sha256: sha2562(plan.target_content),
6357
6449
  sourceIds: [...new Set([...previousSourceIds ?? [], "project-context-bundle"])]
6358
6450
  };
6359
6451
  const targetOwner = isRecord(existing["targetOwner"]) ? existing["targetOwner"] : {};
@@ -6381,7 +6473,7 @@ function buildSessionCompatibilityManifest(plan, now2) {
6381
6473
  blockers: [],
6382
6474
  generatedAt: now2.toISOString(),
6383
6475
  env: sanitizeLegacyEnvironment(existing["env"]),
6384
- sourceHash: sha256(stableStringify({ previous: typeof existing["sourceHash"] === "string" ? existing["sourceHash"] : null, projectContext: plan.bundle.hash })),
6476
+ sourceHash: sha2562(stableStringify({ previous: typeof existing["sourceHash"] === "string" ? existing["sourceHash"] : null, projectContext: plan.bundle.hash })),
6385
6477
  sources,
6386
6478
  skippedSources: sanitizeLegacySkippedSources(existing["skippedSources"]),
6387
6479
  files: [...files.filter((file) => file["relativePath"] !== targetRelativePath), updatedTarget],
@@ -6584,7 +6676,7 @@ function projectContextManifestSource(cachePath, runtime, bundle) {
6584
6676
  nonOverridable: true,
6585
6677
  replacementScope: "project-context",
6586
6678
  rules: [],
6587
- renderedPayloadSha256: sha256(JSON.stringify(bundle)),
6679
+ renderedPayloadSha256: sha2562(JSON.stringify(bundle)),
6588
6680
  provenance: {
6589
6681
  schema: PROJECT_CONTEXT_SCHEMA,
6590
6682
  projectId: bundle.project.id,
@@ -6706,7 +6798,7 @@ function atomicWriteFile(path, content, workspaceRoot, defaultMode, expectedHash
6706
6798
  let fd = null;
6707
6799
  let preserveTemp = false;
6708
6800
  let directoryChanged = false;
6709
- const desiredHash = sha256(content);
6801
+ const desiredHash = sha2562(content);
6710
6802
  try {
6711
6803
  fd = anchoredOpenExclusive(directory, tempName, previousMode);
6712
6804
  writeFileSync(fd, content, { encoding: "utf8" });
@@ -6816,7 +6908,7 @@ function atomicWriteFile(path, content, workspaceRoot, defaultMode, expectedHash
6816
6908
  }
6817
6909
  }
6818
6910
  function atomicWritePortable(path, content, workspaceRoot, defaultMode, expectedHash, beforeInstall, maxObservedBytes, allowReplacement = false) {
6819
- const desiredHash = sha256(content);
6911
+ const desiredHash = sha2562(content);
6820
6912
  const currentHash = portableFileHash(path, workspaceRoot, maxObservedBytes);
6821
6913
  if (expectedHash === undefined && currentHash === desiredHash)
6822
6914
  return;
@@ -6890,7 +6982,7 @@ function atomicWritePortableReplacement(path, content, workspaceRoot, expectedHa
6890
6982
  const dir = dirname(path);
6891
6983
  const directoryIdentity = captureManagedDirectoryIdentity(dir, workspaceRoot);
6892
6984
  const tempPath = join3(dir, `.project-context-${randomUUID3()}.tmp`);
6893
- const desiredHash = sha256(content);
6985
+ const desiredHash = sha2562(content);
6894
6986
  let fd = null;
6895
6987
  let tempIdentity = null;
6896
6988
  try {
@@ -6941,7 +7033,7 @@ function portableFileHash(path, workspaceRoot, maxObservedBytes) {
6941
7033
  if (maxObservedBytes !== null && stat.size > maxObservedBytes) {
6942
7034
  throw new ProjectContextHashRace(`managed output exceeds the safe read limit: ${relativePosix(workspaceRoot, path)}`);
6943
7035
  }
6944
- return createHash("sha256").update(readFileSync(path)).digest("hex");
7036
+ return createHash2("sha256").update(readFileSync(path)).digest("hex");
6945
7037
  }
6946
7038
  function writeProjectContextCoordinatedFile(input) {
6947
7039
  atomicWriteFile(resolve(input.path), input.content, assertSafeWorkspaceRoot(input.workspace_root), input.default_mode ?? 420, input.expected_hash, undefined, false, undefined, input.force_portable_file_ops ?? false, input.max_observed_bytes, input.allow_portable_replacement ?? false);
@@ -7115,7 +7207,7 @@ function anchoredFileObservation(directory, name) {
7115
7207
  return {
7116
7208
  dev: stat.dev,
7117
7209
  ino: stat.ino,
7118
- hash: createHash("sha256").update(readFileSync(fd)).digest("hex"),
7210
+ hash: createHash2("sha256").update(readFileSync(fd)).digest("hex"),
7119
7211
  mode: stat.mode & 511
7120
7212
  };
7121
7213
  } finally {
@@ -7295,7 +7387,7 @@ function acquireWorkspaceLock(workspaceRoot, lockPath, afterOpen, beforeStaleRem
7295
7387
  process_start_id: processStartIdentityLookup(process.pid)
7296
7388
  })}
7297
7389
  `;
7298
- openedContentHash = sha256(content);
7390
+ openedContentHash = sha2562(content);
7299
7391
  writeFileSync(fd, content);
7300
7392
  fsyncSync(fd);
7301
7393
  try {
@@ -7346,7 +7438,7 @@ function removeOwnedLockByInode(lockPath, identity, expectedHash) {
7346
7438
  const current = lstatSync(lockPath);
7347
7439
  if (current.isSymbolicLink() || current.dev !== identity.dev || current.ino !== identity.ino)
7348
7440
  return;
7349
- if (expectedHash !== undefined && sha256(readFileSync(lockPath, "utf8")) !== expectedHash)
7441
+ if (expectedHash !== undefined && sha2562(readFileSync(lockPath, "utf8")) !== expectedHash)
7350
7442
  return;
7351
7443
  rmSync2(lockPath);
7352
7444
  fsyncDirectory(resolve(lockPath, ".."));
@@ -7363,7 +7455,7 @@ function observeStaleWorkspaceLock(lockPath, workspaceRoot, processStartIdentity
7363
7455
  } catch {
7364
7456
  return null;
7365
7457
  }
7366
- const contentHash = sha256(content);
7458
+ const contentHash = sha2562(content);
7367
7459
  if (currentFileHash(lockPath, workspaceRoot) !== contentHash)
7368
7460
  return null;
7369
7461
  let pid = null;
@@ -7525,7 +7617,7 @@ function releaseWorkspaceLock(lockPath, lock, workspaceRoot) {
7525
7617
  created_at: new Date().toISOString()
7526
7618
  })}
7527
7619
  `;
7528
- releaseHash = sha256(releaseContent);
7620
+ releaseHash = sha2562(releaseContent);
7529
7621
  writeFileSync(releaseFd, releaseContent);
7530
7622
  fsyncSync(releaseFd);
7531
7623
  closeSync(releaseFd);
@@ -7764,7 +7856,7 @@ function currentFileHash(path, workspaceRoot) {
7764
7856
  return null;
7765
7857
  const relativePath = relativePosix(workspaceRoot, path);
7766
7858
  const maxBytes = relativePath === ".hasna/session-render-manifest.json" || relativePath === ".codewith/.hasna/session-render-manifest.json" ? SESSION_COMPATIBILITY_MANIFEST_MAX_BYTES : 256 * 1024;
7767
- return sha256(readUtf8RegularFile(path, workspaceRoot, maxBytes));
7859
+ return sha2562(readUtf8RegularFile(path, workspaceRoot, maxBytes));
7768
7860
  }
7769
7861
  function hashesStillMatch(expected, workspaceRoot) {
7770
7862
  for (const [path, hash] of expected) {
@@ -7933,8 +8025,8 @@ function removeHashForFingerprint(value) {
7933
8025
  }
7934
8026
  return copy;
7935
8027
  }
7936
- function sha256(content) {
7937
- return createHash("sha256").update(content).digest("hex");
8028
+ function sha2562(content) {
8029
+ return createHash2("sha256").update(content).digest("hex");
7938
8030
  }
7939
8031
  function isRecord(value) {
7940
8032
  return !!value && typeof value === "object" && !Array.isArray(value);
@@ -8078,7 +8170,7 @@ var CODEWITH_FLATTENED_ADAPTER = {
8078
8170
  tool: "codewith",
8079
8171
  mode: "flattened-markdown",
8080
8172
  indexFile: "CODEWITH.md",
8081
- managedDir: ".hasna/instructions",
8173
+ managedDir: SESSION_RENDER_INSTRUCTIONS_MANAGED_DIR,
8082
8174
  envVar: "CODEWITH_HOME",
8083
8175
  nativeImports: false,
8084
8176
  description: "Codewith CODEWITH.md flattened until native @ imports are implemented in Codewith."
@@ -8087,7 +8179,7 @@ var CODEWITH_NATIVE_ADAPTER = {
8087
8179
  tool: "codewith",
8088
8180
  mode: "native-imports",
8089
8181
  indexFile: "CODEWITH.md",
8090
- managedDir: ".hasna/instructions",
8182
+ managedDir: SESSION_RENDER_INSTRUCTIONS_MANAGED_DIR,
8091
8183
  envVar: "CODEWITH_HOME",
8092
8184
  nativeImports: true,
8093
8185
  description: "Codewith CODEWITH.md with gated @ imports into managed fragments."
@@ -8097,7 +8189,7 @@ var SESSION_TOOL_ADAPTERS = {
8097
8189
  tool: "claude",
8098
8190
  mode: "native-imports",
8099
8191
  indexFile: "CLAUDE.md",
8100
- managedDir: ".hasna/instructions",
8192
+ managedDir: SESSION_RENDER_INSTRUCTIONS_MANAGED_DIR,
8101
8193
  envVar: "CLAUDE_CONFIG_DIR",
8102
8194
  nativeImports: true,
8103
8195
  description: "Claude Code CLAUDE.md with @ imports into managed fragments."
@@ -8106,7 +8198,7 @@ var SESSION_TOOL_ADAPTERS = {
8106
8198
  tool: "codex",
8107
8199
  mode: "flattened-markdown",
8108
8200
  indexFile: "AGENTS.md",
8109
- managedDir: ".hasna/instructions",
8201
+ managedDir: SESSION_RENDER_INSTRUCTIONS_MANAGED_DIR,
8110
8202
  envVar: "CODEX_HOME",
8111
8203
  nativeImports: false,
8112
8204
  description: "Codex AGENTS.md flattened instruction file."
@@ -8123,7 +8215,7 @@ var SESSION_TOOL_ADAPTERS = {
8123
8215
  mode: "opencode-instructions",
8124
8216
  indexFile: "AGENTS.md",
8125
8217
  configFile: "opencode.json",
8126
- managedDir: ".hasna/instructions",
8218
+ managedDir: SESSION_RENDER_INSTRUCTIONS_MANAGED_DIR,
8127
8219
  envVar: "OPENCODE_CONFIG_DIR",
8128
8220
  nativeImports: false,
8129
8221
  description: "OpenCode AGENTS.md plus opencode.json instructions pointing at managed fragments."
@@ -8132,7 +8224,7 @@ var SESSION_TOOL_ADAPTERS = {
8132
8224
  tool: "aicopilot",
8133
8225
  mode: "flattened-markdown",
8134
8226
  indexFile: "AICOPILOT.md",
8135
- managedDir: ".hasna/instructions",
8227
+ managedDir: SESSION_RENDER_INSTRUCTIONS_MANAGED_DIR,
8136
8228
  envVar: "AICOPILOT_CONFIG_DIR",
8137
8229
  nativeImports: false,
8138
8230
  description: "AI Copilot AICOPILOT.md flattened instruction file."
@@ -8155,6 +8247,19 @@ var SESSION_TOOL_ADAPTERS = {
8155
8247
  },
8156
8248
  codewith: CODEWITH_FLATTENED_ADAPTER
8157
8249
  };
8250
+ var SESSION_RENDER_MANAGED_DIRS = [
8251
+ ...new Set([
8252
+ CODEWITH_FLATTENED_ADAPTER,
8253
+ CODEWITH_NATIVE_ADAPTER,
8254
+ ...Object.values(SESSION_TOOL_ADAPTERS)
8255
+ ].map((adapter) => adapter.managedDir))
8256
+ ];
8257
+ var SESSION_RENDER_SHARED_MANAGED_DIRS = [".cursor/rules"];
8258
+ var SESSION_RENDER_EXCLUSIVE_MANAGED_PATHS = [
8259
+ ...SESSION_RENDER_MANAGED_DIRS.filter((dir) => !SESSION_RENDER_SHARED_MANAGED_DIRS.includes(dir)),
8260
+ SESSION_RENDER_MANIFEST_RELATIVE_PATH,
8261
+ SESSION_RENDER_SNAPSHOT_RELATIVE_DIR
8262
+ ];
8158
8263
  var SESSION_LAYER_RANK = {
8159
8264
  global: 10,
8160
8265
  tool: 20,
@@ -8184,11 +8289,11 @@ function ensureTrailingNewline3(content) {
8184
8289
  `) ? content : `${content}
8185
8290
  `;
8186
8291
  }
8187
- function sha2562(content) {
8188
- return createHash2("sha256").update(content).digest("hex");
8292
+ function sha2563(content) {
8293
+ return createHash3("sha256").update(content).digest("hex");
8189
8294
  }
8190
8295
  function fingerprint(value) {
8191
- return sha2562(JSON.stringify(value));
8296
+ return sha2563(JSON.stringify(value));
8192
8297
  }
8193
8298
  function canonicalFingerprintValue(value) {
8194
8299
  if (Array.isArray(value))
@@ -8254,18 +8359,59 @@ function makeFile(targetHome, relativePath, role, content, sourceIds) {
8254
8359
  relativePath: safeRelativePath,
8255
8360
  role,
8256
8361
  content: normalizedContent,
8257
- sha256: sha2562(normalizedContent),
8362
+ sha256: sha2563(normalizedContent),
8258
8363
  sourceIds
8259
8364
  };
8260
8365
  }
8366
+ function claimsAgentOperatingRulesPolicy(source, content) {
8367
+ if (!AGENT_OPERATING_RULES_SENTINEL_PATTERN.test(content))
8368
+ return false;
8369
+ if (source.nonOverridable === true)
8370
+ return true;
8371
+ if (source.id === GLOBAL_AGENT_RULES_STANDARD_SLUG || source.id === AGENT_OPERATING_RULES_SOURCE_ID)
8372
+ return true;
8373
+ if (source.metadata?.["role"] === AGENT_OPERATING_RULES_ROLE)
8374
+ return true;
8375
+ return AGENT_OPERATING_RULES_HEADING_PATTERN.test(content.trimStart());
8376
+ }
8377
+ function applyAgentOperatingRulesFloor(source, content) {
8378
+ const unchanged = {
8379
+ content,
8380
+ provenance: source.provenance ?? null,
8381
+ metadata: source.metadata ?? null
8382
+ };
8383
+ if (!claimsAgentOperatingRulesPolicy(source, content))
8384
+ return unchanged;
8385
+ const payload = resolveAgentOperatingRulesPayload(content);
8386
+ if (payload.content === content) {
8387
+ return {
8388
+ content,
8389
+ provenance: { ...source.provenance ?? {}, payloadIntegrity: payload.integrity },
8390
+ metadata: { ...source.metadata ?? {}, payloadIntegrity: payload.integrity }
8391
+ };
8392
+ }
8393
+ const floored = {
8394
+ payloadFloorApplied: true,
8395
+ flooredFromRulesVersion: parseAgentOperatingRulesVersion(content),
8396
+ flooredFromPayloadSha256: sha2563(content)
8397
+ };
8398
+ return {
8399
+ content: payload.content,
8400
+ provenance: { ...source.provenance ?? {}, ...payload.provenance, ...floored },
8401
+ metadata: { ...source.metadata ?? {}, ...payload.metadata, ...floored }
8402
+ };
8403
+ }
8261
8404
  function normalizeSources(sources, tool, allowEmptySources) {
8262
8405
  const normalized = sources.map((source, index) => {
8263
8406
  if (!source.id.trim())
8264
8407
  throw new Error("Session instruction source id is required.");
8265
- const content = filterProviderOnlyBlocks(source.content ?? "", tool);
8408
+ const floored = applyAgentOperatingRulesFloor(source, source.content ?? "");
8409
+ const content = filterProviderOnlyBlocks(floored.content, tool);
8266
8410
  const normalized2 = {
8267
8411
  ...source,
8268
8412
  content,
8413
+ provenance: floored.provenance,
8414
+ metadata: floored.metadata,
8269
8415
  normalizedId: slug(source.id),
8270
8416
  resolvedLabel: source.label ?? source.id,
8271
8417
  resolvedLayer: source.layer === undefined ? "agent" : normalizeSessionInstructionLayer(source.layer),
@@ -8288,30 +8434,36 @@ function deduplicateSemanticPolicySources(sources) {
8288
8434
  const selected = [];
8289
8435
  const policySources = new Map;
8290
8436
  for (const source of sources) {
8291
- const sentinel = source.content.match(/<!--\s*hasna:agent-operating-rules\s+v=([0-9]+\.[0-9]+\.[0-9]+)\s*-->/i);
8437
+ const sentinel = source.content.match(AGENT_OPERATING_RULES_SENTINEL_PATTERN);
8292
8438
  if (!sentinel) {
8293
8439
  selected.push(source);
8294
8440
  continue;
8295
8441
  }
8296
- const key = `hasna:agent-operating-rules/v${sentinel[1]}`;
8442
+ const version = sentinel[1];
8443
+ const key = AGENT_OPERATING_RULES_SEMANTIC_POLICY_KEY;
8297
8444
  const normalizedContent = source.content.replace(/\r\n/g, `
8298
8445
  `).trim();
8299
8446
  const existing = policySources.get(key);
8300
8447
  if (!existing) {
8301
- policySources.set(key, { index: selected.length, normalizedContent });
8448
+ policySources.set(key, { index: selected.length, version, normalizedContent });
8302
8449
  selected.push(source);
8303
8450
  continue;
8304
8451
  }
8305
- if (existing.normalizedContent !== normalizedContent) {
8306
- throw new Error(`Conflicting semantic policy sources declare ${key} with different content.`);
8452
+ const versionOrder = compareAgentOperatingRulesVersions(version, existing.version);
8453
+ if (versionOrder === 0 && existing.normalizedContent !== normalizedContent) {
8454
+ throw new Error(`Conflicting semantic policy sources declare ${key}/v${version} with different content.`);
8307
8455
  }
8308
8456
  const current = selected[existing.index];
8309
- if (semanticPolicySourcePriority(source) <= semanticPolicySourcePriority(current))
8457
+ const priorityOrder = semanticPolicySourcePriority(source) - semanticPolicySourcePriority(current);
8458
+ if (priorityOrder < 0)
8459
+ continue;
8460
+ if (priorityOrder === 0 && versionOrder <= 0)
8310
8461
  continue;
8311
8462
  selected[existing.index] = {
8312
8463
  ...source,
8313
8464
  resolvedOrder: current.resolvedOrder
8314
8465
  };
8466
+ policySources.set(key, { index: existing.index, version, normalizedContent });
8315
8467
  }
8316
8468
  return selected;
8317
8469
  }
@@ -8321,7 +8473,7 @@ function semanticPolicySourcePriority(source) {
8321
8473
  priority += 4;
8322
8474
  if (source.id === GLOBAL_AGENT_RULES_STANDARD_SLUG)
8323
8475
  priority += 2;
8324
- if (source.metadata?.["role"] === "agent-operating-rules")
8476
+ if (source.metadata?.["role"] === AGENT_OPERATING_RULES_ROLE)
8325
8477
  priority += 1;
8326
8478
  return priority;
8327
8479
  }
@@ -8810,7 +8962,7 @@ function planSessionRender(input) {
8810
8962
  globs: rule.globs ?? [],
8811
8963
  hash: rule.hash ?? null
8812
8964
  })),
8813
- renderedPayloadSha256: sha2562(source.content),
8965
+ renderedPayloadSha256: sha2563(source.content),
8814
8966
  provenance: source.provenance ?? null,
8815
8967
  metadata: source.metadata ?? null
8816
8968
  })),
@@ -8828,8 +8980,8 @@ function planSessionRender(input) {
8828
8980
  ...input.providerConfig ? {
8829
8981
  providerConfig: {
8830
8982
  sourceId: input.providerConfig.sourceId,
8831
- selectedPayloadSha256: sha2562(input.providerConfig.content),
8832
- renderedPayloadSha256: files.find((file) => file.relativePath === adapter.configFile)?.sha256 ?? sha2562(input.providerConfig.content),
8983
+ selectedPayloadSha256: sha2563(input.providerConfig.content),
8984
+ renderedPayloadSha256: files.find((file) => file.relativePath === adapter.configFile)?.sha256 ?? sha2563(input.providerConfig.content),
8833
8985
  selected: !existsSync4(joinTarget(targetHome, adapter.configFile))
8834
8986
  }
8835
8987
  } : {},
@@ -8873,15 +9025,16 @@ function sourceFromFilePath(path, content, order = 0) {
8873
9025
  }
8874
9026
  function sourceFromConfig(config, order = 0, layer) {
8875
9027
  const isAgentOperatingRules = config.slug === GLOBAL_AGENT_RULES_STANDARD_SLUG;
9028
+ const rules = isAgentOperatingRules ? resolveAgentOperatingRulesPayload(config.content) : null;
8876
9029
  return {
8877
9030
  id: config.slug,
8878
9031
  label: config.name,
8879
- content: isAgentOperatingRules ? GLOBAL_AGENT_RULES_STANDARD_CONTENT : config.content,
9032
+ content: rules ? rules.content : config.content,
8880
9033
  layer: layer ?? (config.agent === "global" ? "global" : "agent"),
8881
9034
  order,
8882
9035
  path: config.target_path ?? undefined,
8883
- provenance: isAgentOperatingRules ? {
8884
- ...AGENT_OPERATING_RULES_PROVENANCE,
9036
+ provenance: rules ? {
9037
+ ...rules.provenance,
8885
9038
  configSlug: config.slug,
8886
9039
  configAgent: config.agent
8887
9040
  } : {
@@ -8889,7 +9042,7 @@ function sourceFromConfig(config, order = 0, layer) {
8889
9042
  configSlug: config.slug,
8890
9043
  configAgent: config.agent
8891
9044
  },
8892
- metadata: isAgentOperatingRules ? { ...AGENT_OPERATING_RULES_METADATA } : null,
9045
+ metadata: rules ? { ...rules.metadata } : null,
8893
9046
  nonOverridable: isAgentOperatingRules
8894
9047
  };
8895
9048
  }
@@ -8927,7 +9080,7 @@ function selectProfileConfigsForSessionRender(configs, tool) {
8927
9080
  const selectedSources = [];
8928
9081
  const equivalentSources = new Map;
8929
9082
  for (const candidate of sources) {
8930
- const key = sha2562(candidate.source.content);
9083
+ const key = sha2563(candidate.source.content);
8931
9084
  const existing = equivalentSources.get(key);
8932
9085
  if (!existing) {
8933
9086
  equivalentSources.set(key, {
@@ -9273,6 +9426,77 @@ function asStringArray(value) {
9273
9426
  return value.filter((item) => typeof item === "string");
9274
9427
  }
9275
9428
 
9429
+ // src/lib/session-render-ownership.ts
9430
+ import { existsSync as existsSync5, readFileSync as readFileSync3, statSync as statSync3 } from "fs";
9431
+ import { dirname as dirname3, join as join5, parse as parse3, relative as relative3, sep } from "path";
9432
+ var MANIFEST_ANCESTOR_LIMIT = 24;
9433
+ var MANAGED_PATH_SEGMENTS = SESSION_RENDER_EXCLUSIVE_MANAGED_PATHS.map((managedPath) => managedPath.split("/").filter(Boolean));
9434
+ var manifestCache = new Map;
9435
+ function toSegments(absolutePath2) {
9436
+ return absolutePath2.replaceAll("\\", "/").split("/").filter(Boolean);
9437
+ }
9438
+ function pathIsSessionRenderManagedDir(absolutePath2) {
9439
+ const segments = toSegments(absolutePath2);
9440
+ return MANAGED_PATH_SEGMENTS.some((managed) => {
9441
+ if (managed.length === 0 || managed.length > segments.length)
9442
+ return false;
9443
+ for (let start = 0;start + managed.length <= segments.length; start += 1) {
9444
+ if (managed.every((segment, offset) => segments[start + offset] === segment))
9445
+ return true;
9446
+ }
9447
+ return false;
9448
+ });
9449
+ }
9450
+ function readManifestRelativePaths(manifestPath) {
9451
+ let stats;
9452
+ try {
9453
+ if (!existsSync5(manifestPath))
9454
+ return null;
9455
+ stats = statSync3(manifestPath);
9456
+ } catch {
9457
+ return null;
9458
+ }
9459
+ const cached = manifestCache.get(manifestPath);
9460
+ if (cached && cached.mtimeMs === stats.mtimeMs && cached.size === stats.size) {
9461
+ return cached.relativePaths;
9462
+ }
9463
+ let manifest;
9464
+ try {
9465
+ manifest = JSON.parse(readFileSync3(manifestPath, "utf-8"));
9466
+ } catch {
9467
+ return null;
9468
+ }
9469
+ if (manifest?.schema !== SESSION_RENDER_SCHEMA || !Array.isArray(manifest.files))
9470
+ return null;
9471
+ const writerId = manifest.targetOwner?.writer?.id;
9472
+ if (writerId !== undefined && writerId !== SESSION_RENDERER_OWNER_ID)
9473
+ return null;
9474
+ const relativePaths = new Set(manifest.files.map((file) => file?.relativePath).filter((relativePath) => typeof relativePath === "string").map((relativePath) => relativePath.replaceAll("\\", "/")));
9475
+ manifestCache.set(manifestPath, { mtimeMs: stats.mtimeMs, size: stats.size, relativePaths });
9476
+ return relativePaths;
9477
+ }
9478
+ function sessionRenderManifestClaimsPath(absolutePath2) {
9479
+ const root = parse3(absolutePath2).root;
9480
+ let home = dirname3(absolutePath2);
9481
+ for (let depth = 0;depth < MANIFEST_ANCESTOR_LIMIT; depth += 1) {
9482
+ const manifestPath = join5(home, ...SESSION_RENDER_MANIFEST_RELATIVE_PATH.split("/"));
9483
+ const relativePaths = readManifestRelativePaths(manifestPath);
9484
+ if (relativePaths) {
9485
+ const claimed = relative3(home, absolutePath2).split(sep).join("/");
9486
+ if (relativePaths.has(claimed))
9487
+ return true;
9488
+ }
9489
+ const parent = dirname3(home);
9490
+ if (parent === home || home === root)
9491
+ break;
9492
+ home = parent;
9493
+ }
9494
+ return false;
9495
+ }
9496
+ function sessionRenderOwnsPath(absolutePath2) {
9497
+ return pathIsSessionRenderManagedDir(absolutePath2) || sessionRenderManifestClaimsPath(absolutePath2);
9498
+ }
9499
+
9276
9500
  // src/lib/apply.ts
9277
9501
  function getConfigHome() {
9278
9502
  return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir3();
@@ -9291,14 +9515,14 @@ function normalizeTargetPath(p) {
9291
9515
  let current = expanded;
9292
9516
  const missingSegments = [];
9293
9517
  while (true) {
9294
- if (existsSync5(current)) {
9518
+ if (existsSync6(current)) {
9295
9519
  try {
9296
9520
  return resolve3(realpathSync2(current), ...missingSegments);
9297
9521
  } catch {
9298
9522
  return expanded;
9299
9523
  }
9300
9524
  }
9301
- const parent = dirname3(current);
9525
+ const parent = dirname4(current);
9302
9526
  const name = basename4(current);
9303
9527
  if (parent === current)
9304
9528
  return expanded;
@@ -9320,11 +9544,11 @@ async function writeConfigResult(config, targetPath, content, opts, meta = {}) {
9320
9544
  throw new ConfigApplyError(`Antigravity rule file ${renderedTargetPath} is ${renderedContent.length} characters; split it before applying because Antigravity limits rule files to ${ANTIGRAVITY_RULE_FILE_CHAR_LIMIT} characters.`);
9321
9545
  }
9322
9546
  const path = expandPath(renderedTargetPath);
9323
- const previousContent = existsSync5(path) ? readFileSync3(path, "utf-8") : null;
9547
+ const previousContent = existsSync6(path) ? readFileSync4(path, "utf-8") : null;
9324
9548
  const changed = previousContent !== renderedContent;
9325
9549
  if (!opts.dryRun) {
9326
- const dir = dirname3(path);
9327
- if (!existsSync5(dir)) {
9550
+ const dir = dirname4(path);
9551
+ if (!existsSync6(dir)) {
9328
9552
  mkdirSync3(dir, { recursive: true });
9329
9553
  }
9330
9554
  if (previousContent !== null && changed) {
@@ -9627,35 +9851,37 @@ function sessionRendererOwnsTarget(targetPath, opts) {
9627
9851
  return sessionRendererOwnsCanonicalTarget(canonicalApplyTargetPath(targetPath, opts), opts);
9628
9852
  }
9629
9853
  function sessionRendererOwnsCanonicalTarget(normalized, opts) {
9854
+ if (opts.allowSessionRendererOwned)
9855
+ return false;
9630
9856
  const homes = new Set([
9631
9857
  getConfigHome(),
9632
9858
  opts.vars?.["HOME_DIR"]
9633
9859
  ].filter((home) => typeof home === "string" && home.length > 0));
9634
- if ([...homes].some((home) => SESSION_RENDER_OWNED_CONFIG_TARGETS.some((relativePath) => normalized === normalizeTargetPath(join5(home, ...relativePath.split("/"))))))
9860
+ if ([...homes].some((home) => SESSION_RENDER_OWNED_CONFIG_TARGETS.some((relativePath) => normalized === normalizeTargetPath(join6(home, ...relativePath.split("/"))))))
9635
9861
  return true;
9636
- return normalized.replaceAll("\\", "/").includes("/.agents/rules/");
9862
+ return sessionRenderOwnsPath(normalized);
9637
9863
  }
9638
9864
 
9639
9865
  // src/lib/package-version.ts
9640
- import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
9641
- import { dirname as dirname4, join as join6 } from "path";
9866
+ import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
9867
+ import { dirname as dirname5, join as join7 } from "path";
9642
9868
  import { fileURLToPath } from "url";
9643
9869
  var cached = null;
9644
9870
  function getPackageVersion() {
9645
9871
  if (cached)
9646
9872
  return cached;
9647
9873
  try {
9648
- let dir = dirname4(fileURLToPath(import.meta.url));
9874
+ let dir = dirname5(fileURLToPath(import.meta.url));
9649
9875
  for (let i = 0;i < 8; i++) {
9650
- const pkgPath = join6(dir, "package.json");
9651
- if (existsSync6(pkgPath)) {
9652
- const pkg = JSON.parse(readFileSync4(pkgPath, "utf8"));
9876
+ const pkgPath = join7(dir, "package.json");
9877
+ if (existsSync7(pkgPath)) {
9878
+ const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
9653
9879
  if (pkg.name === "@hasna/instructions" && pkg.version) {
9654
9880
  cached = pkg.version;
9655
9881
  return cached;
9656
9882
  }
9657
9883
  }
9658
- const parent = dirname4(dir);
9884
+ const parent = dirname5(dir);
9659
9885
  if (parent === dir)
9660
9886
  break;
9661
9887
  dir = parent;
@@ -9711,11 +9937,11 @@ async function getConfigsStatus(store = resolveConfigStore()) {
9711
9937
  continue;
9712
9938
  knownTargets += 1;
9713
9939
  const targetPath = expandPath(config.target_path);
9714
- if (!existsSync7(targetPath)) {
9940
+ if (!existsSync8(targetPath)) {
9715
9941
  missingTargets += 1;
9716
9942
  continue;
9717
9943
  }
9718
- const disk = readFileSync5(targetPath, "utf-8");
9944
+ const disk = readFileSync6(targetPath, "utf-8");
9719
9945
  const { content: redactedDisk } = redactContent(disk, config.format);
9720
9946
  if (redactedDisk !== config.content) {
9721
9947
  driftedTargets += 1;
@@ -9858,16 +10084,16 @@ var PG_MIGRATIONS = [
9858
10084
  `ALTER TABLE configs ADD COLUMN IF NOT EXISTS outputs TEXT NOT NULL DEFAULT '[]'`
9859
10085
  ];
9860
10086
  // src/lib/session-apply.ts
9861
- import { createHash as createHash3, randomUUID as randomUUID4 } from "crypto";
10087
+ import { createHash as createHash4, randomUUID as randomUUID4 } from "crypto";
9862
10088
  import {
9863
- existsSync as existsSync8,
10089
+ existsSync as existsSync9,
9864
10090
  lstatSync as lstatSync2,
9865
10091
  mkdirSync as mkdirSync4,
9866
- readFileSync as readFileSync6,
10092
+ readFileSync as readFileSync7,
9867
10093
  readdirSync,
9868
- statSync as statSync3
10094
+ statSync as statSync4
9869
10095
  } from "fs";
9870
- import { dirname as dirname5, isAbsolute as isAbsolute3, join as join7, parse as parse3, relative as relative3, resolve as resolve4 } from "path";
10096
+ import { dirname as dirname6, isAbsolute as isAbsolute3, join as join8, parse as parse4, relative as relative4, resolve as resolve4 } from "path";
9871
10097
  class SessionApplyError extends Error {
9872
10098
  constructor(message) {
9873
10099
  super(message);
@@ -9947,13 +10173,13 @@ function applySessionRenderUnlocked(plan, options, coordination) {
9947
10173
  };
9948
10174
  }
9949
10175
  function ensureSessionTargetHome(targetHome) {
9950
- if (!existsSync8(targetHome))
10176
+ if (!existsSync9(targetHome))
9951
10177
  mkdirSync4(targetHome, { recursive: true, mode: 448 });
9952
10178
  assertSafeTargetHome(targetHome);
9953
10179
  }
9954
10180
  function checkSessionRenderDrift(targetHome, manifestPath) {
9955
10181
  const safeTargetHome = assertSafeTargetHome(targetHome);
9956
- const resolvedManifestPath = manifestPath ? resolveManifestRelativePath(relative3(safeTargetHome, resolve4(manifestPath)), safeTargetHome) : resolve4(safeTargetHome, ".hasna", "session-render-manifest.json");
10182
+ const resolvedManifestPath = manifestPath ? resolveManifestRelativePath(relative4(safeTargetHome, resolve4(manifestPath)), safeTargetHome) : resolve4(safeTargetHome, ".hasna", "session-render-manifest.json");
9957
10183
  const checkedAt = new Date().toISOString();
9958
10184
  const previousManifest = readPreviousManifest(resolvedManifestPath);
9959
10185
  if (!previousManifest) {
@@ -9970,7 +10196,7 @@ function checkSessionRenderDrift(targetHome, manifestPath) {
9970
10196
  const drifted = [];
9971
10197
  for (const file of previousManifest.files) {
9972
10198
  const target = resolveManifestRelativePath(file.relativePath, safeTargetHome);
9973
- if (!existsSync8(target)) {
10199
+ if (!existsSync9(target)) {
9974
10200
  missing.push({
9975
10201
  path: target,
9976
10202
  relativePath: file.relativePath,
@@ -9980,7 +10206,7 @@ function checkSessionRenderDrift(targetHome, manifestPath) {
9980
10206
  });
9981
10207
  continue;
9982
10208
  }
9983
- const actualSha256 = sha2563(readFileSync6(target, "utf-8"));
10209
+ const actualSha256 = sha2564(readFileSync7(target, "utf-8"));
9984
10210
  if (actualSha256 !== file.sha256) {
9985
10211
  drifted.push({
9986
10212
  path: target,
@@ -10004,7 +10230,7 @@ function restoreSessionRenderSnapshot(snapshotPath, options = {}) {
10004
10230
  const snapshot = readSessionRenderSnapshot(snapshotPath);
10005
10231
  const targetHome = assertSafeTargetHome(snapshot.targetHome);
10006
10232
  const resolvedSnapshotPath = resolve4(snapshotPath);
10007
- const snapshotRelativePath = relative3(targetHome, resolvedSnapshotPath);
10233
+ const snapshotRelativePath = relative4(targetHome, resolvedSnapshotPath);
10008
10234
  if (snapshotRelativePath === "" || snapshotRelativePath === ".." || snapshotRelativePath.startsWith("../") || isAbsolute3(snapshotRelativePath)) {
10009
10235
  throw new SessionApplyError("Session snapshot must be stored inside its target home.");
10010
10236
  }
@@ -10122,18 +10348,18 @@ function requiredRestoreHash(file) {
10122
10348
  }
10123
10349
  function readSessionRenderSnapshot(snapshotPath) {
10124
10350
  const resolved = resolve4(snapshotPath);
10125
- if (!existsSync8(resolved))
10351
+ if (!existsSync9(resolved))
10126
10352
  throw new SessionApplyError(`Session snapshot not found: ${snapshotPath}`);
10127
10353
  const stat = lstatSync2(resolved);
10128
10354
  if (stat.isSymbolicLink() || !stat.isFile()) {
10129
10355
  throw new SessionApplyError(`Session snapshot is not a regular file: ${snapshotPath}`);
10130
10356
  }
10131
- if (statSync3(resolved).size > 32 * 1024 * 1024) {
10357
+ if (statSync4(resolved).size > 32 * 1024 * 1024) {
10132
10358
  throw new SessionApplyError(`Session snapshot exceeds the 32 MiB restore limit: ${snapshotPath}`);
10133
10359
  }
10134
10360
  let parsed;
10135
10361
  try {
10136
- parsed = JSON.parse(readFileSync6(resolved, "utf8"));
10362
+ parsed = JSON.parse(readFileSync7(resolved, "utf8"));
10137
10363
  } catch {
10138
10364
  throw new SessionApplyError(`Session snapshot is not valid JSON: ${snapshotPath}`);
10139
10365
  }
@@ -10155,7 +10381,7 @@ function readSessionRenderSnapshot(snapshotPath) {
10155
10381
  const previousManifest = snapshot.previousManifest;
10156
10382
  const previousFiles = new Map;
10157
10383
  for (const file of snapshot.files) {
10158
- if (!file || typeof file.relativePath !== "string" || typeof file.path !== "string" || typeof file.sha256 !== "string" || typeof file.content !== "string" || sha2563(file.content) !== file.sha256) {
10384
+ if (!file || typeof file.relativePath !== "string" || typeof file.path !== "string" || typeof file.sha256 !== "string" || typeof file.content !== "string" || sha2564(file.content) !== file.sha256) {
10159
10385
  throw new SessionApplyError(`Session snapshot previous file metadata is invalid: ${snapshotPath}`);
10160
10386
  }
10161
10387
  resolveSnapshotFilePath(file.relativePath, file.path, targetHome);
@@ -10203,7 +10429,7 @@ function readSessionRenderSnapshot(snapshotPath) {
10203
10429
  function reconstructPreRollbackLegacyV1Snapshot(snapshot, previousFiles, previousManifestFiles, targetHome, snapshotPath) {
10204
10430
  assertNoNewerSessionSnapshot(snapshotPath, snapshot.createdAt, targetHome);
10205
10431
  const manifestPath = resolve4(snapshot.manifestPath);
10206
- const manifestRelativePath = relative3(targetHome, manifestPath).replaceAll("\\", "/");
10432
+ const manifestRelativePath = relative4(targetHome, manifestPath).replaceAll("\\", "/");
10207
10433
  resolveSnapshotFilePath(manifestRelativePath, snapshot.manifestPath, targetHome);
10208
10434
  const manifestSha256 = currentSessionFileHash(manifestPath, targetHome);
10209
10435
  if (manifestSha256 === null) {
@@ -10211,7 +10437,7 @@ function reconstructPreRollbackLegacyV1Snapshot(snapshot, previousFiles, previou
10211
10437
  }
10212
10438
  let parsedManifest;
10213
10439
  try {
10214
- parsedManifest = JSON.parse(readFileSync6(manifestPath, "utf8"));
10440
+ parsedManifest = JSON.parse(readFileSync7(manifestPath, "utf8"));
10215
10441
  } catch {
10216
10442
  throw new SessionApplyError(`Pre-rollback legacy v1 applied manifest is not valid JSON: ${snapshotPath}`);
10217
10443
  }
@@ -10303,15 +10529,15 @@ function assertNoNewerSessionSnapshot(snapshotPath, createdAt, targetHome) {
10303
10529
  if (!Number.isFinite(createdAtMs)) {
10304
10530
  throw new SessionApplyError(`Pre-rollback legacy v1 snapshot has an invalid creation time: ${snapshotPath}`);
10305
10531
  }
10306
- for (const entry of readdirSync(dirname5(snapshotPath))) {
10307
- const candidatePath = resolve4(dirname5(snapshotPath), entry);
10532
+ for (const entry of readdirSync(dirname6(snapshotPath))) {
10533
+ const candidatePath = resolve4(dirname6(snapshotPath), entry);
10308
10534
  if (candidatePath === resolve4(snapshotPath) || !entry.endsWith(".json"))
10309
10535
  continue;
10310
10536
  const candidateStat = lstatSync2(candidatePath);
10311
10537
  if (candidateStat.isSymbolicLink() || !candidateStat.isFile() || candidateStat.size > 32 * 1024 * 1024)
10312
10538
  continue;
10313
10539
  try {
10314
- const candidate = JSON.parse(readFileSync6(candidatePath, "utf8"));
10540
+ const candidate = JSON.parse(readFileSync7(candidatePath, "utf8"));
10315
10541
  const candidateCreatedAtMs = typeof candidate.createdAt === "string" ? Date.parse(candidate.createdAt) : Number.NaN;
10316
10542
  if ((candidate.schema === "hasna.configs.session-render-snapshot/v1" || candidate.schema === "hasna.configs.session-render-snapshot/v2") && typeof candidate.targetHome === "string" && resolve4(candidate.targetHome) === targetHome && Number.isFinite(candidateCreatedAtMs) && candidateCreatedAtMs >= createdAtMs) {
10317
10543
  throw new SessionApplyError(`Cannot restore pre-rollback legacy v1 snapshot after a newer session snapshot exists: ${candidatePath}`);
@@ -10371,7 +10597,7 @@ function inferLegacySnapshotAction(file, previousFiles, previousManifestFiles, p
10371
10597
  return "create";
10372
10598
  }
10373
10599
  if (file.role === "manifest" && previousManifest) {
10374
- const previousManifestSha256 = sha2563(`${JSON.stringify(previousManifest, null, 2)}
10600
+ const previousManifestSha256 = sha2564(`${JSON.stringify(previousManifest, null, 2)}
10375
10601
  `);
10376
10602
  if (previousManifestSha256 !== file.sha256) {
10377
10603
  throw new SessionApplyError(`Cannot infer legacy v1 manifest action without a before-image: ${file.relativePath}`);
@@ -10389,8 +10615,8 @@ function resolveSnapshotFilePath(relativePath, recordedPath, targetHome) {
10389
10615
  }
10390
10616
  function planFileResult(plan, file, targetHome, previousHashes, previousManifest, options) {
10391
10617
  const target = resolvePlannedFilePath(plan, file, targetHome);
10392
- const previousContent = existsSync8(target) ? readFileSync6(target, "utf-8") : null;
10393
- const previousSha256 = previousContent === null ? null : sha2563(previousContent);
10618
+ const previousContent = existsSync9(target) ? readFileSync7(target, "utf-8") : null;
10619
+ const previousSha256 = previousContent === null ? null : sha2564(previousContent);
10394
10620
  const previouslyManaged = isPreviouslyManaged(file, previousSha256, previousHashes, previousManifest);
10395
10621
  const changed = previousContent !== file.content;
10396
10622
  if (previousContent !== null && !options.force && !previouslyManaged) {
@@ -10472,10 +10698,10 @@ function planStaleFileResults(plan, targetHome, previousManifest, currentRelativ
10472
10698
  }
10473
10699
  function planStaleFileResult(file, targetHome, options) {
10474
10700
  const target = resolveManifestRelativePath(file.relativePath, targetHome);
10475
- if (!existsSync8(target))
10701
+ if (!existsSync9(target))
10476
10702
  return null;
10477
- const previousContent = readFileSync6(target, "utf-8");
10478
- const previousSha256 = sha2563(previousContent);
10703
+ const previousContent = readFileSync7(target, "utf-8");
10704
+ const previousSha256 = sha2564(previousContent);
10479
10705
  if (!options.force && previousSha256 !== file.sha256) {
10480
10706
  return {
10481
10707
  path: target,
@@ -10520,7 +10746,7 @@ function isPreviouslyManaged(file, previousSha256, previousHashes, previousManif
10520
10746
  }
10521
10747
  function resolvePlannedFilePath(plan, file, targetHome) {
10522
10748
  const target = resolve4(targetHome, ...file.relativePath.split("/"));
10523
- const rel = relative3(targetHome, target);
10749
+ const rel = relative4(targetHome, target);
10524
10750
  if (rel === "" || rel === ".." || rel.startsWith("../") || isAbsolute3(rel)) {
10525
10751
  throw new SessionApplyError(`Session file escapes target home: ${file.relativePath}`);
10526
10752
  }
@@ -10532,7 +10758,7 @@ function resolvePlannedFilePath(plan, file, targetHome) {
10532
10758
  }
10533
10759
  function resolveManifestRelativePath(relativePath, targetHome) {
10534
10760
  const target = resolve4(targetHome, ...relativePath.split(/[\\/]+/));
10535
- const rel = relative3(targetHome, target);
10761
+ const rel = relative4(targetHome, target);
10536
10762
  if (rel === "" || rel === ".." || rel.startsWith("../") || isAbsolute3(rel)) {
10537
10763
  throw new SessionApplyError(`Session manifest file escapes target home: ${relativePath}`);
10538
10764
  }
@@ -10540,10 +10766,10 @@ function resolveManifestRelativePath(relativePath, targetHome) {
10540
10766
  return target;
10541
10767
  }
10542
10768
  function readPreviousManifest(path) {
10543
- if (!existsSync8(path))
10769
+ if (!existsSync9(path))
10544
10770
  return null;
10545
10771
  try {
10546
- const parsed = JSON.parse(readFileSync6(path, "utf-8"));
10772
+ const parsed = JSON.parse(readFileSync7(path, "utf-8"));
10547
10773
  if (parsed.schema !== SESSION_RENDER_SCHEMA)
10548
10774
  return null;
10549
10775
  if (!Array.isArray(parsed.files))
@@ -10577,18 +10803,18 @@ function applyPlannedFile(plan, file, targetHome, resultsByPath, coordination, a
10577
10803
  function assertExpectedSessionFileHash(path, targetHome, expectedHash) {
10578
10804
  const actualHash = currentSessionFileHash(path, targetHome);
10579
10805
  if (actualHash !== expectedHash) {
10580
- throw new SessionApplyError(`Session apply path changed after planning: ${relative3(targetHome, path)}`);
10806
+ throw new SessionApplyError(`Session apply path changed after planning: ${relative4(targetHome, path)}`);
10581
10807
  }
10582
10808
  }
10583
10809
  function currentSessionFileHash(path, targetHome) {
10584
10810
  assertNoSymlinkSegments2(targetHome, path);
10585
- if (!existsSync8(path))
10811
+ if (!existsSync9(path))
10586
10812
  return null;
10587
10813
  const stat = lstatSync2(path);
10588
10814
  if (stat.isSymbolicLink() || !stat.isFile()) {
10589
10815
  throw new SessionApplyError(`Session apply path is not a regular file: ${path}`);
10590
10816
  }
10591
- return sha2563(readFileSync6(path, "utf-8"));
10817
+ return sha2564(readFileSync7(path, "utf-8"));
10592
10818
  }
10593
10819
  function requiredPreviousHash(result) {
10594
10820
  if (result.previousSha256 === null) {
@@ -10597,13 +10823,13 @@ function requiredPreviousHash(result) {
10597
10823
  return result.previousSha256;
10598
10824
  }
10599
10825
  function writeSessionSnapshot(plan, targetHome, manifestPath, results, previousManifest, coordination, allowPortableFallback, forcePortableFileOps) {
10600
- const existingFiles = results.filter((result) => result.action === "update" || result.action === "delete").filter((result) => existsSync8(result.path)).map((result) => {
10601
- const content = readFileSync6(result.path, "utf-8");
10826
+ const existingFiles = results.filter((result) => result.action === "update" || result.action === "delete").filter((result) => existsSync9(result.path)).map((result) => {
10827
+ const content = readFileSync7(result.path, "utf-8");
10602
10828
  return {
10603
10829
  path: result.path,
10604
10830
  relativePath: result.relativePath,
10605
10831
  role: result.role,
10606
- sha256: sha2563(content),
10832
+ sha256: sha2564(content),
10607
10833
  content
10608
10834
  };
10609
10835
  });
@@ -10654,42 +10880,42 @@ function assertSafeTargetHome(targetHome) {
10654
10880
  if (!isAbsolute3(targetHome))
10655
10881
  throw new SessionApplyError(`Session target home must be absolute: ${targetHome}`);
10656
10882
  const normalized = resolve4(targetHome);
10657
- if (normalized === parse3(normalized).root) {
10883
+ if (normalized === parse4(normalized).root) {
10658
10884
  throw new SessionApplyError(`Session target home cannot be the filesystem root: ${targetHome}`);
10659
10885
  }
10660
10886
  assertNoSymlinkAncestors2(normalized);
10661
- if (existsSync8(normalized) && lstatSync2(normalized).isSymbolicLink()) {
10887
+ if (existsSync9(normalized) && lstatSync2(normalized).isSymbolicLink()) {
10662
10888
  throw new SessionApplyError(`Session target home cannot be a symlink: ${normalized}`);
10663
10889
  }
10664
10890
  return normalized;
10665
10891
  }
10666
10892
  function assertNoSymlinkSegments2(root, target) {
10667
10893
  assertNoSymlinkAncestors2(root);
10668
- const rel = relative3(root, target);
10894
+ const rel = relative4(root, target);
10669
10895
  let current = root;
10670
10896
  for (const segment of rel.split(/[\\/]+/).filter(Boolean)) {
10671
- current = join7(current, segment);
10672
- if (existsSync8(current) && lstatSync2(current).isSymbolicLink()) {
10897
+ current = join8(current, segment);
10898
+ if (existsSync9(current) && lstatSync2(current).isSymbolicLink()) {
10673
10899
  throw new SessionApplyError(`Session apply path uses a symlink: ${current}`);
10674
10900
  }
10675
10901
  }
10676
10902
  }
10677
10903
  function assertNoSymlinkAncestors2(path) {
10678
10904
  const normalized = resolve4(path);
10679
- const parsed = parse3(normalized);
10905
+ const parsed = parse4(normalized);
10680
10906
  let current = parsed.root;
10681
- const rel = relative3(parsed.root, normalized);
10907
+ const rel = relative4(parsed.root, normalized);
10682
10908
  for (const segment of rel.split(/[\\/]+/).filter(Boolean)) {
10683
- current = join7(current, segment);
10684
- if (!existsSync8(current))
10909
+ current = join8(current, segment);
10910
+ if (!existsSync9(current))
10685
10911
  return;
10686
10912
  if (lstatSync2(current).isSymbolicLink()) {
10687
10913
  throw new SessionApplyError(`Session apply path uses a symlink ancestor: ${current}`);
10688
10914
  }
10689
10915
  }
10690
10916
  }
10691
- function sha2563(content) {
10692
- return createHash3("sha256").update(content).digest("hex");
10917
+ function sha2564(content) {
10918
+ return createHash4("sha256").update(content).digest("hex");
10693
10919
  }
10694
10920
  // src/lib/project-dashboard-standard.ts
10695
10921
  var PROJECT_DASHBOARD_STANDARD_SLUG = "agent-managed-project-dashboard-standard";
@@ -10987,12 +11213,12 @@ async function ensureDangerousOperationGuardStandardConfig(store = resolveConfig
10987
11213
  }
10988
11214
  }
10989
11215
  // src/lib/sync.ts
10990
- import { existsSync as existsSync10, readdirSync as readdirSync3, readFileSync as readFileSync8 } from "fs";
10991
- import { basename as basename5, extname as extname3, join as join9 } from "path";
11216
+ import { existsSync as existsSync11, readdirSync as readdirSync3, readFileSync as readFileSync9 } from "fs";
11217
+ import { basename as basename5, extname as extname3, join as join10 } from "path";
10992
11218
 
10993
11219
  // src/lib/sync-dir.ts
10994
- import { existsSync as existsSync9, readdirSync as readdirSync2, readFileSync as readFileSync7, statSync as statSync4 } from "fs";
10995
- import { join as join8, relative as relative4 } from "path";
11220
+ import { existsSync as existsSync10, readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync5 } from "fs";
11221
+ import { join as join9, relative as relative5 } from "path";
10996
11222
  import { homedir as homedir4 } from "os";
10997
11223
  var SKIP = [".db", ".db-shm", ".db-wal", ".log", ".lock", ".DS_Store", "node_modules", ".git"];
10998
11224
  function shouldSkip(p) {
@@ -11001,9 +11227,9 @@ function shouldSkip(p) {
11001
11227
  async function syncFromDir(dir, opts = {}) {
11002
11228
  const store = opts.store ?? resolveConfigStore();
11003
11229
  const absDir = expandPath(dir);
11004
- if (!existsSync9(absDir))
11230
+ if (!existsSync10(absDir))
11005
11231
  return { added: 0, updated: 0, unchanged: 0, skipped: [`Not found: ${absDir}`] };
11006
- const files = opts.recursive !== false ? walkDir(absDir) : readdirSync2(absDir).map((f) => join8(absDir, f)).filter((f) => statSync4(f).isFile());
11232
+ const files = opts.recursive !== false ? walkDir(absDir) : readdirSync2(absDir).map((f) => join9(absDir, f)).filter((f) => statSync5(f).isFile());
11007
11233
  const result = { added: 0, updated: 0, unchanged: 0, skipped: [] };
11008
11234
  const home = homedir4();
11009
11235
  const allConfigs = await store.listConfigs();
@@ -11013,7 +11239,7 @@ async function syncFromDir(dir, opts = {}) {
11013
11239
  continue;
11014
11240
  }
11015
11241
  try {
11016
- const content = readFileSync7(file, "utf-8");
11242
+ const content = readFileSync8(file, "utf-8");
11017
11243
  if (content.length > 500000) {
11018
11244
  result.skipped.push(file + " (too large)");
11019
11245
  continue;
@@ -11022,7 +11248,7 @@ async function syncFromDir(dir, opts = {}) {
11022
11248
  const existing = allConfigs.find((c) => c.target_path === targetPath);
11023
11249
  if (!existing) {
11024
11250
  if (!opts.dryRun)
11025
- await store.createConfig({ name: relative4(absDir, file), category: detectCategory(file), agent: detectAgent(file), target_path: targetPath, format: detectFormat(file), content });
11251
+ await store.createConfig({ name: relative5(absDir, file), category: detectCategory(file), agent: detectAgent(file), target_path: targetPath, format: detectFormat(file), content });
11026
11252
  result.added++;
11027
11253
  } else if (existing.content !== content) {
11028
11254
  if (!opts.dryRun)
@@ -11063,7 +11289,7 @@ async function syncToDir(dir, opts = {}) {
11063
11289
  }
11064
11290
  function walkDir(dir, files = []) {
11065
11291
  for (const entry of readdirSync2(dir, { withFileTypes: true })) {
11066
- const full = join8(dir, entry.name);
11292
+ const full = join9(dir, entry.name);
11067
11293
  if (shouldSkip(full))
11068
11294
  continue;
11069
11295
  if (entry.isDirectory())
@@ -11115,7 +11341,7 @@ function isGeneratedOutputTarget2(config, owners) {
11115
11341
  return !!ownerIds && !ownerIds.has(config.id);
11116
11342
  }
11117
11343
  function hasClaudePromptSource() {
11118
- return existsSync10(expandPath("~/.claude/CLAUDE.md"));
11344
+ return existsSync11(expandPath("~/.claude/CLAUDE.md"));
11119
11345
  }
11120
11346
  function hasClaudeRuleSourceForCursorTarget(targetPath) {
11121
11347
  const absoluteTargetPath = expandPath(targetPath);
@@ -11123,7 +11349,7 @@ function hasClaudeRuleSourceForCursorTarget(targetPath) {
11123
11349
  if (!absoluteTargetPath.startsWith(`${absolutePrefix}/`) || !absoluteTargetPath.endsWith(".mdc"))
11124
11350
  return false;
11125
11351
  const stem = basename5(absoluteTargetPath, ".mdc");
11126
- return existsSync10(expandPath(`~/.claude/rules/${stem}.md`)) || existsSync10(expandPath(`~/.claude/rules/${stem}.mdc`));
11352
+ return existsSync11(expandPath(`~/.claude/rules/${stem}.md`)) || existsSync11(expandPath(`~/.claude/rules/${stem}.mdc`));
11127
11353
  }
11128
11354
  function isKnownGeneratedTargetPath(targetPath) {
11129
11355
  const normalizedTargetPath = normalizeTargetPath(targetPath);
@@ -11186,11 +11412,11 @@ async function syncProject(opts) {
11186
11412
  const allConfigs = await store.listConfigs();
11187
11413
  const machine = detectMachineContext();
11188
11414
  for (const pf of PROJECT_CONFIG_FILES) {
11189
- const abs = join9(absDir, pf.file);
11190
- if (!existsSync10(abs))
11415
+ const abs = join10(absDir, pf.file);
11416
+ if (!existsSync11(abs))
11191
11417
  continue;
11192
11418
  try {
11193
- const rawContent = readFileSync8(abs, "utf-8");
11419
+ const rawContent = readFileSync9(abs, "utf-8");
11194
11420
  if (rawContent.length > 500000) {
11195
11421
  result.skipped.push(pf.file);
11196
11422
  continue;
@@ -11219,15 +11445,15 @@ async function syncProject(opts) {
11219
11445
  }
11220
11446
  }
11221
11447
  for (const ruleDir of [
11222
- { dir: join9(absDir, ".claude", "rules"), agent: "claude", namePrefix: "rules" },
11223
- { dir: join9(absDir, ".agents", "rules"), agent: "antigravity", namePrefix: "antigravity-rules" }
11448
+ { dir: join10(absDir, ".claude", "rules"), agent: "claude", namePrefix: "rules" },
11449
+ { dir: join10(absDir, ".agents", "rules"), agent: "antigravity", namePrefix: "antigravity-rules" }
11224
11450
  ]) {
11225
- if (!existsSync10(ruleDir.dir))
11451
+ if (!existsSync11(ruleDir.dir))
11226
11452
  continue;
11227
11453
  const mdFiles = readdirSync3(ruleDir.dir).filter((f) => f.endsWith(".md") || f.endsWith(".mdc"));
11228
11454
  for (const f of mdFiles) {
11229
- const abs = join9(ruleDir.dir, f);
11230
- const raw = readFileSync8(abs, "utf-8");
11455
+ const abs = join10(ruleDir.dir, f);
11456
+ const raw = readFileSync9(abs, "utf-8");
11231
11457
  const redacted = redactContent(raw, "markdown");
11232
11458
  const machineAware = templateizeMachineContent(redacted.content, machine);
11233
11459
  const content = machineAware.content;
@@ -11266,20 +11492,20 @@ async function syncKnown(opts = {}) {
11266
11492
  for (const known of targets) {
11267
11493
  if (known.rulesDir) {
11268
11494
  const absDir = expandPath(known.rulesDir);
11269
- if (!existsSync10(absDir)) {
11495
+ if (!existsSync11(absDir)) {
11270
11496
  result.skipped.push(known.rulesDir);
11271
11497
  continue;
11272
11498
  }
11273
11499
  const extensions = known.rulesExtensions ?? [".md", ".mdc"];
11274
11500
  const ruleFiles = readdirSync3(absDir).filter((f) => extensions.some((ext) => f.endsWith(ext)));
11275
11501
  for (const f of ruleFiles) {
11276
- const abs2 = join9(absDir, f);
11502
+ const abs2 = join10(absDir, f);
11277
11503
  const targetPath = abs2.replace(home, "~");
11278
11504
  if (existingOutputOwners.has(normalizeTargetPath(targetPath)) || isKnownGeneratedTargetPath(targetPath)) {
11279
11505
  result.skipped.push(`${targetPath} (generated output)`);
11280
11506
  continue;
11281
11507
  }
11282
- const raw = readFileSync8(abs2, "utf-8");
11508
+ const raw = readFileSync9(abs2, "utf-8");
11283
11509
  const redacted = redactContent(raw, "markdown");
11284
11510
  const machineAware = templateizeMachineContent(redacted.content, machine);
11285
11511
  const content = machineAware.content;
@@ -11307,12 +11533,12 @@ async function syncKnown(opts = {}) {
11307
11533
  continue;
11308
11534
  }
11309
11535
  const abs = expandPath(known.path);
11310
- if (!existsSync10(abs)) {
11536
+ if (!existsSync11(abs)) {
11311
11537
  result.skipped.push(known.path);
11312
11538
  continue;
11313
11539
  }
11314
11540
  try {
11315
- const rawContent = readFileSync8(abs, "utf-8");
11541
+ const rawContent = readFileSync9(abs, "utf-8");
11316
11542
  if (rawContent.length > 500000) {
11317
11543
  result.skipped.push(known.path + " (too large)");
11318
11544
  continue;
@@ -11400,9 +11626,9 @@ async function syncToDisk(opts = {}) {
11400
11626
  }
11401
11627
  function buildDiff(expectedContent, targetPath) {
11402
11628
  const path = expandPath(targetPath);
11403
- if (!existsSync10(path))
11629
+ if (!existsSync11(path))
11404
11630
  return `(file not found on disk: ${path})`;
11405
- const diskContent = readFileSync8(path, "utf-8");
11631
+ const diskContent = readFileSync9(path, "utf-8");
11406
11632
  if (diskContent === expectedContent)
11407
11633
  return "(no diff \u2014 identical)";
11408
11634
  const stored = expectedContent.split(`
@@ -11516,15 +11742,15 @@ function detectFormat(filePath) {
11516
11742
  return "text";
11517
11743
  }
11518
11744
  // src/lib/export.ts
11519
- import { existsSync as existsSync11, mkdirSync as mkdirSync5, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "fs";
11520
- import { join as join10, resolve as resolve5 } from "path";
11745
+ import { existsSync as existsSync12, mkdirSync as mkdirSync5, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "fs";
11746
+ import { join as join11, resolve as resolve5 } from "path";
11521
11747
  import { tmpdir } from "os";
11522
11748
  async function exportConfigs(outputPath, opts = {}) {
11523
11749
  const store = opts.store ?? resolveConfigStore();
11524
11750
  const configs = await store.listConfigs(opts.filter);
11525
11751
  const absOutput = resolve5(outputPath);
11526
- const tmpDir = join10(tmpdir(), `configs-export-${Date.now()}`);
11527
- const contentsDir = join10(tmpDir, "contents");
11752
+ const tmpDir = join11(tmpdir(), `configs-export-${Date.now()}`);
11753
+ const contentsDir = join11(tmpDir, "contents");
11528
11754
  try {
11529
11755
  mkdirSync5(contentsDir, { recursive: true });
11530
11756
  const manifest = {
@@ -11532,10 +11758,10 @@ async function exportConfigs(outputPath, opts = {}) {
11532
11758
  exported_at: new Date().toISOString(),
11533
11759
  configs: configs.map(({ content: _content, ...meta }) => meta)
11534
11760
  };
11535
- writeFileSync3(join10(tmpDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
11761
+ writeFileSync3(join11(tmpDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
11536
11762
  for (const config of configs) {
11537
11763
  const fileName = `${config.slug}.${config.format === "text" ? "txt" : config.format}`;
11538
- writeFileSync3(join10(contentsDir, fileName), config.content, "utf-8");
11764
+ writeFileSync3(join11(contentsDir, fileName), config.content, "utf-8");
11539
11765
  }
11540
11766
  const proc = Bun.spawn(["tar", "czf", absOutput, "-C", tmpDir, "."], {
11541
11767
  stdout: "pipe",
@@ -11548,20 +11774,20 @@ async function exportConfigs(outputPath, opts = {}) {
11548
11774
  }
11549
11775
  return { path: absOutput, count: configs.length };
11550
11776
  } finally {
11551
- if (existsSync11(tmpDir)) {
11777
+ if (existsSync12(tmpDir)) {
11552
11778
  rmSync3(tmpDir, { recursive: true, force: true });
11553
11779
  }
11554
11780
  }
11555
11781
  }
11556
11782
  // src/lib/import.ts
11557
- import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync9, rmSync as rmSync4 } from "fs";
11558
- import { join as join11, resolve as resolve6 } from "path";
11783
+ import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync10, rmSync as rmSync4 } from "fs";
11784
+ import { join as join12, resolve as resolve6 } from "path";
11559
11785
  import { tmpdir as tmpdir2 } from "os";
11560
11786
  async function importConfigs(bundlePath, opts = {}) {
11561
11787
  const store = opts.store ?? resolveConfigStore();
11562
11788
  const conflict = opts.conflict ?? "skip";
11563
11789
  const absPath = resolve6(bundlePath);
11564
- const tmpDir = join11(tmpdir2(), `configs-import-${Date.now()}`);
11790
+ const tmpDir = join12(tmpdir2(), `configs-import-${Date.now()}`);
11565
11791
  const result = { created: 0, updated: 0, skipped: 0, errors: [] };
11566
11792
  try {
11567
11793
  mkdirSync6(tmpDir, { recursive: true });
@@ -11574,15 +11800,15 @@ async function importConfigs(bundlePath, opts = {}) {
11574
11800
  const stderr = await new Response(proc.stderr).text();
11575
11801
  throw new Error(`tar extraction failed: ${stderr}`);
11576
11802
  }
11577
- const manifestPath = join11(tmpDir, "manifest.json");
11578
- if (!existsSync12(manifestPath))
11803
+ const manifestPath = join12(tmpDir, "manifest.json");
11804
+ if (!existsSync13(manifestPath))
11579
11805
  throw new Error("Invalid bundle: missing manifest.json");
11580
- const manifest = JSON.parse(readFileSync9(manifestPath, "utf-8"));
11806
+ const manifest = JSON.parse(readFileSync10(manifestPath, "utf-8"));
11581
11807
  for (const meta of manifest.configs) {
11582
11808
  try {
11583
11809
  const ext = meta.format === "text" ? "txt" : meta.format;
11584
- const contentFile = join11(tmpDir, "contents", `${meta.slug}.${ext}`);
11585
- const content = existsSync12(contentFile) ? readFileSync9(contentFile, "utf-8") : "";
11810
+ const contentFile = join12(tmpDir, "contents", `${meta.slug}.${ext}`);
11811
+ const content = existsSync13(contentFile) ? readFileSync10(contentFile, "utf-8") : "";
11586
11812
  let existing = null;
11587
11813
  try {
11588
11814
  existing = await store.getConfig(meta.slug);
@@ -11616,16 +11842,16 @@ async function importConfigs(bundlePath, opts = {}) {
11616
11842
  }
11617
11843
  return result;
11618
11844
  } finally {
11619
- if (existsSync12(tmpDir)) {
11845
+ if (existsSync13(tmpDir)) {
11620
11846
  rmSync4(tmpDir, { recursive: true, force: true });
11621
11847
  }
11622
11848
  }
11623
11849
  }
11624
11850
  // src/lib/package-manager-guard.ts
11625
11851
  import { execFileSync as execFileSync2 } from "child_process";
11626
- import { existsSync as existsSync13, lstatSync as lstatSync3, readdirSync as readdirSync4, readFileSync as readFileSync10 } from "fs";
11852
+ import { existsSync as existsSync14, lstatSync as lstatSync3, readdirSync as readdirSync4, readFileSync as readFileSync11 } from "fs";
11627
11853
  import { homedir as homedir5 } from "os";
11628
- import { basename as basename6, dirname as dirname6, isAbsolute as isAbsolute4, join as join12, relative as relative5, resolve as resolve7 } from "path";
11854
+ import { basename as basename6, dirname as dirname7, isAbsolute as isAbsolute4, join as join13, relative as relative6, resolve as resolve7 } from "path";
11629
11855
  var SKIP_DIRS = new Set([
11630
11856
  ".git",
11631
11857
  "node_modules",
@@ -11667,7 +11893,7 @@ function scanPackageManagerSecrets(options = {}) {
11667
11893
  const findings = [];
11668
11894
  let scannedFiles = 0;
11669
11895
  for (const root of roots) {
11670
- if (!existsSync13(root))
11896
+ if (!existsSync14(root))
11671
11897
  continue;
11672
11898
  const stat = lstatSync3(root);
11673
11899
  if (stat.isFile()) {
@@ -11677,14 +11903,14 @@ function scanPackageManagerSecrets(options = {}) {
11677
11903
  if (text === null)
11678
11904
  continue;
11679
11905
  scannedFiles++;
11680
- findings.push(...scanFile(root, text, classifyRepoFile(root), isTrackedFile(root), dirname6(root)));
11906
+ findings.push(...scanFile(root, text, classifyRepoFile(root), isTrackedFile(root), dirname7(root)));
11681
11907
  continue;
11682
11908
  }
11683
11909
  if (!stat.isDirectory())
11684
11910
  continue;
11685
11911
  const tracked = trackedFiles(root);
11686
11912
  for (const file of collectRepoFiles(root)) {
11687
- const rel = toPosix(relative5(root, file));
11913
+ const rel = toPosix(relative6(root, file));
11688
11914
  const isTracked = tracked.has(rel);
11689
11915
  const text = readTextFile(file);
11690
11916
  if (text === null)
@@ -11696,8 +11922,8 @@ function scanPackageManagerSecrets(options = {}) {
11696
11922
  if (options.includeHome) {
11697
11923
  const home = homedir5();
11698
11924
  for (const name of HOME_FILES) {
11699
- const file = join12(home, name);
11700
- if (!existsSync13(file))
11925
+ const file = join13(home, name);
11926
+ if (!existsSync14(file))
11701
11927
  continue;
11702
11928
  const text = readTextFile(file);
11703
11929
  if (text === null)
@@ -11721,12 +11947,12 @@ function collectRepoFiles(root) {
11721
11947
  if (entry.isDirectory()) {
11722
11948
  if (SKIP_DIRS.has(entry.name))
11723
11949
  continue;
11724
- visit(join12(dir, entry.name));
11950
+ visit(join13(dir, entry.name));
11725
11951
  continue;
11726
11952
  }
11727
11953
  if (!entry.isFile())
11728
11954
  continue;
11729
- const file = join12(dir, entry.name);
11955
+ const file = join13(dir, entry.name);
11730
11956
  if (shouldScanRepoFile(file))
11731
11957
  out.push(file);
11732
11958
  }
@@ -11764,7 +11990,7 @@ function readTextFile(file) {
11764
11990
  const stat = lstatSync3(file);
11765
11991
  if (!stat.isFile() || stat.size > 5000000)
11766
11992
  return null;
11767
- const buf = readFileSync10(file);
11993
+ const buf = readFileSync11(file);
11768
11994
  if (buf.includes(0))
11769
11995
  return null;
11770
11996
  return buf.toString("utf-8");
@@ -11964,11 +12190,11 @@ function trackedFiles(root) {
11964
12190
  }
11965
12191
  function isTrackedFile(file) {
11966
12192
  try {
11967
- const repoRoot = execFileSync2("git", ["-C", dirname6(file), "rev-parse", "--show-toplevel"], {
12193
+ const repoRoot = execFileSync2("git", ["-C", dirname7(file), "rev-parse", "--show-toplevel"], {
11968
12194
  encoding: "utf-8",
11969
12195
  stdio: ["ignore", "pipe", "ignore"]
11970
12196
  }).trim();
11971
- const rel = toPosix(relative5(repoRoot, file));
12197
+ const rel = toPosix(relative6(repoRoot, file));
11972
12198
  execFileSync2("git", ["-C", repoRoot, "ls-files", "--error-unmatch", "--", rel], {
11973
12199
  stdio: ["ignore", "ignore", "ignore"]
11974
12200
  });
@@ -11996,11 +12222,11 @@ function stripInlineComment(value) {
11996
12222
  function displayPath(file, root) {
11997
12223
  const home = homedir5();
11998
12224
  if (root === home && (file === home || file.startsWith(home + "/")))
11999
- return "~/" + toPosix(relative5(home, file));
12225
+ return "~/" + toPosix(relative6(home, file));
12000
12226
  if (isAbsolute4(root) && file.startsWith(root + "/"))
12001
- return toPosix(relative5(root, file));
12227
+ return toPosix(relative6(root, file));
12002
12228
  if (file === home || file.startsWith(home + "/"))
12003
- return "~/" + toPosix(relative5(home, file));
12229
+ return "~/" + toPosix(relative6(home, file));
12004
12230
  return file;
12005
12231
  }
12006
12232
  function toPosix(path) {
@@ -12029,6 +12255,7 @@ export {
12029
12255
  resolveProfileVariables,
12030
12256
  resolveConfigStore,
12031
12257
  resolveCloudConfig,
12258
+ resolveAgentOperatingRulesPayload,
12032
12259
  renderTemplatePreview,
12033
12260
  renderTemplate,
12034
12261
  renderMachineAwareContentPreview,
@@ -12039,6 +12266,7 @@ export {
12039
12266
  planProjectContext,
12040
12267
  parseTemplateVars,
12041
12268
  parseProjectContextBundle,
12269
+ parseAgentOperatingRulesVersion,
12042
12270
  now,
12043
12271
  normalizeOsFamily,
12044
12272
  machineContextToVariables,
@@ -12063,6 +12291,7 @@ export {
12063
12291
  currentHostname2 as currentHostname,
12064
12292
  currentArch2 as currentArch,
12065
12293
  computeProjectContextSourceHash,
12294
+ compareAgentOperatingRulesVersions,
12066
12295
  cleanSessionPathInput,
12067
12296
  checkSessionRenderDrift,
12068
12297
  buildOpenCodeAgentsMd,
@@ -12118,5 +12347,7 @@ export {
12118
12347
  CONFIG_FORMATS,
12119
12348
  CONFIG_CATEGORIES,
12120
12349
  CONFIG_AGENTS,
12121
- CODEWITH_NATIVE_IMPORTS_ENV
12350
+ CODEWITH_NATIVE_IMPORTS_ENV,
12351
+ AGENT_OPERATING_RULES_SENTINEL_PATTERN,
12352
+ AGENT_OPERATING_RULES_SEMANTIC_POLICY_KEY
12122
12353
  };