@hasna/instructions 0.4.8 → 0.4.10

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" });
@@ -6715,7 +6807,7 @@ function atomicWriteFile(path, content, workspaceRoot, defaultMode, expectedHash
6715
6807
  fd = null;
6716
6808
  beforeInstall?.(tempPath);
6717
6809
  assertManagedDirectoryStable(dir, workspaceRoot, directory.identity);
6718
- if (anchoredFileHash(directory, tempName) !== desiredHash) {
6810
+ if (anchoredPreparedObservation(directory, tempName, path, "before installation").hash !== desiredHash) {
6719
6811
  throw new ProjectContextHashRace(`prepared bytes changed before installation: ${relativePosix(workspaceRoot, path)}`);
6720
6812
  }
6721
6813
  if (expectedHash === undefined) {
@@ -6724,8 +6816,8 @@ function atomicWriteFile(path, content, workspaceRoot, defaultMode, expectedHash
6724
6816
  }
6725
6817
  directoryChanged = true;
6726
6818
  } else if (expectedHash === null) {
6727
- const prepared = anchoredFileObservation(directory, tempName);
6728
- if (!prepared || anchoredFileObservation(directory, targetName) !== null) {
6819
+ const prepared = anchoredPreparedObservation(directory, tempName, path, "before creation");
6820
+ if (anchoredFileObservation(directory, targetName) !== null) {
6729
6821
  throw new ProjectContextHashRace(`managed path appeared before creation: ${relativePosix(workspaceRoot, path)}`);
6730
6822
  }
6731
6823
  if (!directory.ops.linkat(directory.fd, tempName, directory.fd, targetName)) {
@@ -6733,7 +6825,8 @@ function atomicWriteFile(path, content, workspaceRoot, defaultMode, expectedHash
6733
6825
  }
6734
6826
  directoryChanged = true;
6735
6827
  const installed = anchoredFileObservation(directory, targetName);
6736
- if (!installed || installed.dev !== prepared.dev || installed.ino !== prepared.ino || anchoredFileHash(directory, tempName) !== desiredHash || installed.hash !== desiredHash) {
6828
+ const stagedHash = anchoredFileHash(directory, tempName);
6829
+ if (!installed || installed.dev !== prepared.dev || installed.ino !== prepared.ino || stagedHash !== desiredHash || installed.hash !== desiredHash) {
6737
6830
  directory.ops.unlinkat(directory.fd, tempName);
6738
6831
  preserveTemp = true;
6739
6832
  throw new ProjectContextHashRace(`prepared bytes changed during creation: ${relativePosix(workspaceRoot, path)}`);
@@ -6750,7 +6843,7 @@ function atomicWriteFile(path, content, workspaceRoot, defaultMode, expectedHash
6750
6843
  if (anchoredFileHash(directory, targetName) !== expectedHash) {
6751
6844
  throw new ProjectContextHashRace(`managed path changed before atomic replacement: ${relativePosix(workspaceRoot, path)}`);
6752
6845
  }
6753
- if (anchoredFileHash(directory, tempName) !== desiredHash) {
6846
+ if (anchoredPreparedObservation(directory, tempName, path, "before atomic replacement").hash !== desiredHash) {
6754
6847
  throw new ProjectContextHashRace(`prepared bytes changed before atomic replacement: ${relativePosix(workspaceRoot, path)}`);
6755
6848
  }
6756
6849
  atomicExchangeEntries(directory.fd, tempName, targetName);
@@ -6816,7 +6909,7 @@ function atomicWriteFile(path, content, workspaceRoot, defaultMode, expectedHash
6816
6909
  }
6817
6910
  }
6818
6911
  function atomicWritePortable(path, content, workspaceRoot, defaultMode, expectedHash, beforeInstall, maxObservedBytes, allowReplacement = false) {
6819
- const desiredHash = sha256(content);
6912
+ const desiredHash = sha2562(content);
6820
6913
  const currentHash = portableFileHash(path, workspaceRoot, maxObservedBytes);
6821
6914
  if (expectedHash === undefined && currentHash === desiredHash)
6822
6915
  return;
@@ -6847,7 +6940,7 @@ function atomicWritePortable(path, content, workspaceRoot, defaultMode, expected
6847
6940
  assertManagedDirectoryStable(dir, workspaceRoot, directoryIdentity);
6848
6941
  assertNoSymlinkSegments(workspaceRoot, tempPath);
6849
6942
  assertNoSymlinkSegments(workspaceRoot, path);
6850
- if (portableFileHash(tempPath, workspaceRoot, maxObservedBytes) !== desiredHash || portableFileHash(path, workspaceRoot, maxObservedBytes) !== null) {
6943
+ if (portablePreparedHash(tempPath, path, workspaceRoot, maxObservedBytes, "before portable creation") !== desiredHash || portableFileHash(path, workspaceRoot, maxObservedBytes) !== null) {
6851
6944
  throw new ProjectContextHashRace(`managed path changed before portable creation: ${relativePosix(workspaceRoot, path)}`);
6852
6945
  }
6853
6946
  const prepared = lstatSync(tempPath);
@@ -6890,7 +6983,7 @@ function atomicWritePortableReplacement(path, content, workspaceRoot, expectedHa
6890
6983
  const dir = dirname(path);
6891
6984
  const directoryIdentity = captureManagedDirectoryIdentity(dir, workspaceRoot);
6892
6985
  const tempPath = join3(dir, `.project-context-${randomUUID3()}.tmp`);
6893
- const desiredHash = sha256(content);
6986
+ const desiredHash = sha2562(content);
6894
6987
  let fd = null;
6895
6988
  let tempIdentity = null;
6896
6989
  try {
@@ -6905,7 +6998,7 @@ function atomicWritePortableReplacement(path, content, workspaceRoot, expectedHa
6905
6998
  assertManagedDirectoryStable(dir, workspaceRoot, directoryIdentity);
6906
6999
  assertNoSymlinkSegments(workspaceRoot, tempPath);
6907
7000
  assertNoSymlinkSegments(workspaceRoot, path);
6908
- if (portableFileHash(path, workspaceRoot, maxObservedBytes) !== expectedHash || portableFileHash(tempPath, workspaceRoot, maxObservedBytes) !== desiredHash) {
7001
+ if (portableFileHash(path, workspaceRoot, maxObservedBytes) !== expectedHash || portablePreparedHash(tempPath, path, workspaceRoot, maxObservedBytes, "before portable replacement") !== desiredHash) {
6909
7002
  throw new ProjectContextHashRace(`managed path changed before portable replacement: ${relativePosix(workspaceRoot, path)}`);
6910
7003
  }
6911
7004
  renameSync(tempPath, path);
@@ -6929,6 +7022,20 @@ function atomicWritePortableReplacement(path, content, workspaceRoot, expectedHa
6929
7022
  throw error;
6930
7023
  }
6931
7024
  }
7025
+ function portablePreparedHash(tempPath, path, workspaceRoot, maxObservedBytes, stage) {
7026
+ const unreadable = (cause) => new ProjectContextError("PROJECT_CONTEXT_PREPARED_FILE_UNREADABLE", `the prepared managed file could not be read back ${stage}: ${relativePosix(workspaceRoot, path)}`, { staged_path: tempPath, stage, ...cause === undefined ? {} : { cause } });
7027
+ let hash;
7028
+ try {
7029
+ hash = portableFileHash(tempPath, workspaceRoot, maxObservedBytes);
7030
+ } catch (error) {
7031
+ if (error instanceof ProjectContextError || error instanceof ProjectContextHashRace)
7032
+ throw error;
7033
+ throw unreadable(error.message);
7034
+ }
7035
+ if (hash === null)
7036
+ throw unreadable();
7037
+ return hash;
7038
+ }
6932
7039
  function portableFileHash(path, workspaceRoot, maxObservedBytes) {
6933
7040
  if (maxObservedBytes === undefined)
6934
7041
  return currentFileHash(path, workspaceRoot);
@@ -6941,10 +7048,10 @@ function portableFileHash(path, workspaceRoot, maxObservedBytes) {
6941
7048
  if (maxObservedBytes !== null && stat.size > maxObservedBytes) {
6942
7049
  throw new ProjectContextHashRace(`managed output exceeds the safe read limit: ${relativePosix(workspaceRoot, path)}`);
6943
7050
  }
6944
- return createHash("sha256").update(readFileSync(path)).digest("hex");
7051
+ return createHash2("sha256").update(readFileSync(path)).digest("hex");
6945
7052
  }
6946
7053
  function writeProjectContextCoordinatedFile(input) {
6947
- 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);
7054
+ atomicWriteFile(resolve(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);
6948
7055
  }
6949
7056
  function removeProjectContextCoordinatedFile(input) {
6950
7057
  const workspaceRoot = assertSafeWorkspaceRoot(input.workspace_root);
@@ -7089,15 +7196,43 @@ function openAnchoredDirectory(path, workspaceRoot, providedOps, maxObservedByte
7089
7196
  }
7090
7197
  }
7091
7198
  function anchoredOpenExclusive(directory, name, mode) {
7092
- const fd = directory.ops.openat(directory.fd, name, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, mode);
7093
- if (fd < 0)
7199
+ const requestedMode = mode & 4095;
7200
+ let fd;
7201
+ try {
7202
+ fd = openSync(join3(directory.path, name), constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, requestedMode);
7203
+ } catch {
7094
7204
  throw new ProjectContextHashRace(`could not create prepared managed file in ${relativePosix(directory.workspaceRoot, directory.path)}`);
7095
- const opened = fstatSync(fd);
7096
- if (!opened.isFile()) {
7205
+ }
7206
+ try {
7207
+ const opened = fstatSync(fd);
7208
+ if (!opened.isFile()) {
7209
+ throw new ProjectContextHashRace("prepared managed output is not a regular file");
7210
+ }
7211
+ if (!isPreparedManagedFileModeUsable(requestedMode, opened.mode)) {
7212
+ throw new ProjectContextError("PROJECT_CONTEXT_PREPARED_FILE_MODE_REJECTED", `the platform created the prepared managed file with an unusable mode in ${relativePosix(directory.workspaceRoot, directory.path)}`, { requested_mode: modeLiteral(requestedMode), observed_mode: modeLiteral(opened.mode) });
7213
+ }
7214
+ assertManagedDirectoryStable(directory.path, directory.workspaceRoot, directory.identity);
7215
+ const anchored = anchoredFileObservation(directory, name);
7216
+ if (!anchored || anchored.dev !== opened.dev || anchored.ino !== opened.ino) {
7217
+ throw new ProjectContextHashRace(`prepared managed file is not the one anchored in ${relativePosix(directory.workspaceRoot, directory.path)}`);
7218
+ }
7219
+ return fd;
7220
+ } catch (error) {
7097
7221
  closeSync(fd);
7098
- throw new ProjectContextHashRace("prepared managed output is not a regular file");
7222
+ throw error;
7099
7223
  }
7100
- return fd;
7224
+ }
7225
+ function modeLiteral(mode) {
7226
+ return `0o${(mode & 4095).toString(8).padStart(3, "0")}`;
7227
+ }
7228
+ function isPreparedManagedFileModeUsable(requestedMode, observedMode) {
7229
+ const requested = requestedMode & 4095;
7230
+ const observed = observedMode & 4095;
7231
+ if ((observed & ~requested) !== 0)
7232
+ return false;
7233
+ if ((requested & 256) !== 0 && (observed & 256) === 0)
7234
+ return false;
7235
+ return true;
7101
7236
  }
7102
7237
  function anchoredFileObservation(directory, name) {
7103
7238
  const fd = directory.ops.openat(directory.fd, name, constants.O_RDONLY | constants.O_NOFOLLOW, 0);
@@ -7115,7 +7250,7 @@ function anchoredFileObservation(directory, name) {
7115
7250
  return {
7116
7251
  dev: stat.dev,
7117
7252
  ino: stat.ino,
7118
- hash: createHash("sha256").update(readFileSync(fd)).digest("hex"),
7253
+ hash: createHash2("sha256").update(readFileSync(fd)).digest("hex"),
7119
7254
  mode: stat.mode & 511
7120
7255
  };
7121
7256
  } finally {
@@ -7125,6 +7260,13 @@ function anchoredFileObservation(directory, name) {
7125
7260
  function anchoredFileHash(directory, name) {
7126
7261
  return anchoredFileObservation(directory, name)?.hash ?? null;
7127
7262
  }
7263
+ function anchoredPreparedObservation(directory, name, path, stage) {
7264
+ const observed = anchoredFileObservation(directory, name);
7265
+ if (!observed) {
7266
+ throw new ProjectContextError("PROJECT_CONTEXT_PREPARED_FILE_UNREADABLE", `the prepared managed file could not be read back ${stage}: ${relativePosix(directory.workspaceRoot, path)}`, { staged_name: name, stage });
7267
+ }
7268
+ return observed;
7269
+ }
7128
7270
  function captureManagedDirectoryIdentity(path, workspaceRoot) {
7129
7271
  assertNoSymlinkSegments(workspaceRoot, join3(path, ".project-context-directory-guard"));
7130
7272
  let stat;
@@ -7295,7 +7437,7 @@ function acquireWorkspaceLock(workspaceRoot, lockPath, afterOpen, beforeStaleRem
7295
7437
  process_start_id: processStartIdentityLookup(process.pid)
7296
7438
  })}
7297
7439
  `;
7298
- openedContentHash = sha256(content);
7440
+ openedContentHash = sha2562(content);
7299
7441
  writeFileSync(fd, content);
7300
7442
  fsyncSync(fd);
7301
7443
  try {
@@ -7346,7 +7488,7 @@ function removeOwnedLockByInode(lockPath, identity, expectedHash) {
7346
7488
  const current = lstatSync(lockPath);
7347
7489
  if (current.isSymbolicLink() || current.dev !== identity.dev || current.ino !== identity.ino)
7348
7490
  return;
7349
- if (expectedHash !== undefined && sha256(readFileSync(lockPath, "utf8")) !== expectedHash)
7491
+ if (expectedHash !== undefined && sha2562(readFileSync(lockPath, "utf8")) !== expectedHash)
7350
7492
  return;
7351
7493
  rmSync2(lockPath);
7352
7494
  fsyncDirectory(resolve(lockPath, ".."));
@@ -7363,7 +7505,7 @@ function observeStaleWorkspaceLock(lockPath, workspaceRoot, processStartIdentity
7363
7505
  } catch {
7364
7506
  return null;
7365
7507
  }
7366
- const contentHash = sha256(content);
7508
+ const contentHash = sha2562(content);
7367
7509
  if (currentFileHash(lockPath, workspaceRoot) !== contentHash)
7368
7510
  return null;
7369
7511
  let pid = null;
@@ -7525,7 +7667,7 @@ function releaseWorkspaceLock(lockPath, lock, workspaceRoot) {
7525
7667
  created_at: new Date().toISOString()
7526
7668
  })}
7527
7669
  `;
7528
- releaseHash = sha256(releaseContent);
7670
+ releaseHash = sha2562(releaseContent);
7529
7671
  writeFileSync(releaseFd, releaseContent);
7530
7672
  fsyncSync(releaseFd);
7531
7673
  closeSync(releaseFd);
@@ -7764,7 +7906,7 @@ function currentFileHash(path, workspaceRoot) {
7764
7906
  return null;
7765
7907
  const relativePath = relativePosix(workspaceRoot, path);
7766
7908
  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));
7909
+ return sha2562(readUtf8RegularFile(path, workspaceRoot, maxBytes));
7768
7910
  }
7769
7911
  function hashesStillMatch(expected, workspaceRoot) {
7770
7912
  for (const [path, hash] of expected) {
@@ -7933,8 +8075,8 @@ function removeHashForFingerprint(value) {
7933
8075
  }
7934
8076
  return copy;
7935
8077
  }
7936
- function sha256(content) {
7937
- return createHash("sha256").update(content).digest("hex");
8078
+ function sha2562(content) {
8079
+ return createHash2("sha256").update(content).digest("hex");
7938
8080
  }
7939
8081
  function isRecord(value) {
7940
8082
  return !!value && typeof value === "object" && !Array.isArray(value);
@@ -8078,7 +8220,7 @@ var CODEWITH_FLATTENED_ADAPTER = {
8078
8220
  tool: "codewith",
8079
8221
  mode: "flattened-markdown",
8080
8222
  indexFile: "CODEWITH.md",
8081
- managedDir: ".hasna/instructions",
8223
+ managedDir: SESSION_RENDER_INSTRUCTIONS_MANAGED_DIR,
8082
8224
  envVar: "CODEWITH_HOME",
8083
8225
  nativeImports: false,
8084
8226
  description: "Codewith CODEWITH.md flattened until native @ imports are implemented in Codewith."
@@ -8087,7 +8229,7 @@ var CODEWITH_NATIVE_ADAPTER = {
8087
8229
  tool: "codewith",
8088
8230
  mode: "native-imports",
8089
8231
  indexFile: "CODEWITH.md",
8090
- managedDir: ".hasna/instructions",
8232
+ managedDir: SESSION_RENDER_INSTRUCTIONS_MANAGED_DIR,
8091
8233
  envVar: "CODEWITH_HOME",
8092
8234
  nativeImports: true,
8093
8235
  description: "Codewith CODEWITH.md with gated @ imports into managed fragments."
@@ -8097,7 +8239,7 @@ var SESSION_TOOL_ADAPTERS = {
8097
8239
  tool: "claude",
8098
8240
  mode: "native-imports",
8099
8241
  indexFile: "CLAUDE.md",
8100
- managedDir: ".hasna/instructions",
8242
+ managedDir: SESSION_RENDER_INSTRUCTIONS_MANAGED_DIR,
8101
8243
  envVar: "CLAUDE_CONFIG_DIR",
8102
8244
  nativeImports: true,
8103
8245
  description: "Claude Code CLAUDE.md with @ imports into managed fragments."
@@ -8106,7 +8248,7 @@ var SESSION_TOOL_ADAPTERS = {
8106
8248
  tool: "codex",
8107
8249
  mode: "flattened-markdown",
8108
8250
  indexFile: "AGENTS.md",
8109
- managedDir: ".hasna/instructions",
8251
+ managedDir: SESSION_RENDER_INSTRUCTIONS_MANAGED_DIR,
8110
8252
  envVar: "CODEX_HOME",
8111
8253
  nativeImports: false,
8112
8254
  description: "Codex AGENTS.md flattened instruction file."
@@ -8123,7 +8265,7 @@ var SESSION_TOOL_ADAPTERS = {
8123
8265
  mode: "opencode-instructions",
8124
8266
  indexFile: "AGENTS.md",
8125
8267
  configFile: "opencode.json",
8126
- managedDir: ".hasna/instructions",
8268
+ managedDir: SESSION_RENDER_INSTRUCTIONS_MANAGED_DIR,
8127
8269
  envVar: "OPENCODE_CONFIG_DIR",
8128
8270
  nativeImports: false,
8129
8271
  description: "OpenCode AGENTS.md plus opencode.json instructions pointing at managed fragments."
@@ -8132,7 +8274,7 @@ var SESSION_TOOL_ADAPTERS = {
8132
8274
  tool: "aicopilot",
8133
8275
  mode: "flattened-markdown",
8134
8276
  indexFile: "AICOPILOT.md",
8135
- managedDir: ".hasna/instructions",
8277
+ managedDir: SESSION_RENDER_INSTRUCTIONS_MANAGED_DIR,
8136
8278
  envVar: "AICOPILOT_CONFIG_DIR",
8137
8279
  nativeImports: false,
8138
8280
  description: "AI Copilot AICOPILOT.md flattened instruction file."
@@ -8155,6 +8297,19 @@ var SESSION_TOOL_ADAPTERS = {
8155
8297
  },
8156
8298
  codewith: CODEWITH_FLATTENED_ADAPTER
8157
8299
  };
8300
+ var SESSION_RENDER_MANAGED_DIRS = [
8301
+ ...new Set([
8302
+ CODEWITH_FLATTENED_ADAPTER,
8303
+ CODEWITH_NATIVE_ADAPTER,
8304
+ ...Object.values(SESSION_TOOL_ADAPTERS)
8305
+ ].map((adapter) => adapter.managedDir))
8306
+ ];
8307
+ var SESSION_RENDER_SHARED_MANAGED_DIRS = [".cursor/rules"];
8308
+ var SESSION_RENDER_EXCLUSIVE_MANAGED_PATHS = [
8309
+ ...SESSION_RENDER_MANAGED_DIRS.filter((dir) => !SESSION_RENDER_SHARED_MANAGED_DIRS.includes(dir)),
8310
+ SESSION_RENDER_MANIFEST_RELATIVE_PATH,
8311
+ SESSION_RENDER_SNAPSHOT_RELATIVE_DIR
8312
+ ];
8158
8313
  var SESSION_LAYER_RANK = {
8159
8314
  global: 10,
8160
8315
  tool: 20,
@@ -8184,11 +8339,11 @@ function ensureTrailingNewline3(content) {
8184
8339
  `) ? content : `${content}
8185
8340
  `;
8186
8341
  }
8187
- function sha2562(content) {
8188
- return createHash2("sha256").update(content).digest("hex");
8342
+ function sha2563(content) {
8343
+ return createHash3("sha256").update(content).digest("hex");
8189
8344
  }
8190
8345
  function fingerprint(value) {
8191
- return sha2562(JSON.stringify(value));
8346
+ return sha2563(JSON.stringify(value));
8192
8347
  }
8193
8348
  function canonicalFingerprintValue(value) {
8194
8349
  if (Array.isArray(value))
@@ -8254,18 +8409,59 @@ function makeFile(targetHome, relativePath, role, content, sourceIds) {
8254
8409
  relativePath: safeRelativePath,
8255
8410
  role,
8256
8411
  content: normalizedContent,
8257
- sha256: sha2562(normalizedContent),
8412
+ sha256: sha2563(normalizedContent),
8258
8413
  sourceIds
8259
8414
  };
8260
8415
  }
8416
+ function claimsAgentOperatingRulesPolicy(source, content) {
8417
+ if (!AGENT_OPERATING_RULES_SENTINEL_PATTERN.test(content))
8418
+ return false;
8419
+ if (source.nonOverridable === true)
8420
+ return true;
8421
+ if (source.id === GLOBAL_AGENT_RULES_STANDARD_SLUG || source.id === AGENT_OPERATING_RULES_SOURCE_ID)
8422
+ return true;
8423
+ if (source.metadata?.["role"] === AGENT_OPERATING_RULES_ROLE)
8424
+ return true;
8425
+ return AGENT_OPERATING_RULES_HEADING_PATTERN.test(content.trimStart());
8426
+ }
8427
+ function applyAgentOperatingRulesFloor(source, content) {
8428
+ const unchanged = {
8429
+ content,
8430
+ provenance: source.provenance ?? null,
8431
+ metadata: source.metadata ?? null
8432
+ };
8433
+ if (!claimsAgentOperatingRulesPolicy(source, content))
8434
+ return unchanged;
8435
+ const payload = resolveAgentOperatingRulesPayload(content);
8436
+ if (payload.content === content) {
8437
+ return {
8438
+ content,
8439
+ provenance: { ...source.provenance ?? {}, payloadIntegrity: payload.integrity },
8440
+ metadata: { ...source.metadata ?? {}, payloadIntegrity: payload.integrity }
8441
+ };
8442
+ }
8443
+ const floored = {
8444
+ payloadFloorApplied: true,
8445
+ flooredFromRulesVersion: parseAgentOperatingRulesVersion(content),
8446
+ flooredFromPayloadSha256: sha2563(content)
8447
+ };
8448
+ return {
8449
+ content: payload.content,
8450
+ provenance: { ...source.provenance ?? {}, ...payload.provenance, ...floored },
8451
+ metadata: { ...source.metadata ?? {}, ...payload.metadata, ...floored }
8452
+ };
8453
+ }
8261
8454
  function normalizeSources(sources, tool, allowEmptySources) {
8262
8455
  const normalized = sources.map((source, index) => {
8263
8456
  if (!source.id.trim())
8264
8457
  throw new Error("Session instruction source id is required.");
8265
- const content = filterProviderOnlyBlocks(source.content ?? "", tool);
8458
+ const floored = applyAgentOperatingRulesFloor(source, source.content ?? "");
8459
+ const content = filterProviderOnlyBlocks(floored.content, tool);
8266
8460
  const normalized2 = {
8267
8461
  ...source,
8268
8462
  content,
8463
+ provenance: floored.provenance,
8464
+ metadata: floored.metadata,
8269
8465
  normalizedId: slug(source.id),
8270
8466
  resolvedLabel: source.label ?? source.id,
8271
8467
  resolvedLayer: source.layer === undefined ? "agent" : normalizeSessionInstructionLayer(source.layer),
@@ -8288,30 +8484,36 @@ function deduplicateSemanticPolicySources(sources) {
8288
8484
  const selected = [];
8289
8485
  const policySources = new Map;
8290
8486
  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);
8487
+ const sentinel = source.content.match(AGENT_OPERATING_RULES_SENTINEL_PATTERN);
8292
8488
  if (!sentinel) {
8293
8489
  selected.push(source);
8294
8490
  continue;
8295
8491
  }
8296
- const key = `hasna:agent-operating-rules/v${sentinel[1]}`;
8492
+ const version = sentinel[1];
8493
+ const key = AGENT_OPERATING_RULES_SEMANTIC_POLICY_KEY;
8297
8494
  const normalizedContent = source.content.replace(/\r\n/g, `
8298
8495
  `).trim();
8299
8496
  const existing = policySources.get(key);
8300
8497
  if (!existing) {
8301
- policySources.set(key, { index: selected.length, normalizedContent });
8498
+ policySources.set(key, { index: selected.length, version, normalizedContent });
8302
8499
  selected.push(source);
8303
8500
  continue;
8304
8501
  }
8305
- if (existing.normalizedContent !== normalizedContent) {
8306
- throw new Error(`Conflicting semantic policy sources declare ${key} with different content.`);
8502
+ const versionOrder = compareAgentOperatingRulesVersions(version, existing.version);
8503
+ if (versionOrder === 0 && existing.normalizedContent !== normalizedContent) {
8504
+ throw new Error(`Conflicting semantic policy sources declare ${key}/v${version} with different content.`);
8307
8505
  }
8308
8506
  const current = selected[existing.index];
8309
- if (semanticPolicySourcePriority(source) <= semanticPolicySourcePriority(current))
8507
+ const priorityOrder = semanticPolicySourcePriority(source) - semanticPolicySourcePriority(current);
8508
+ if (priorityOrder < 0)
8509
+ continue;
8510
+ if (priorityOrder === 0 && versionOrder <= 0)
8310
8511
  continue;
8311
8512
  selected[existing.index] = {
8312
8513
  ...source,
8313
8514
  resolvedOrder: current.resolvedOrder
8314
8515
  };
8516
+ policySources.set(key, { index: existing.index, version, normalizedContent });
8315
8517
  }
8316
8518
  return selected;
8317
8519
  }
@@ -8321,7 +8523,7 @@ function semanticPolicySourcePriority(source) {
8321
8523
  priority += 4;
8322
8524
  if (source.id === GLOBAL_AGENT_RULES_STANDARD_SLUG)
8323
8525
  priority += 2;
8324
- if (source.metadata?.["role"] === "agent-operating-rules")
8526
+ if (source.metadata?.["role"] === AGENT_OPERATING_RULES_ROLE)
8325
8527
  priority += 1;
8326
8528
  return priority;
8327
8529
  }
@@ -8810,7 +9012,7 @@ function planSessionRender(input) {
8810
9012
  globs: rule.globs ?? [],
8811
9013
  hash: rule.hash ?? null
8812
9014
  })),
8813
- renderedPayloadSha256: sha2562(source.content),
9015
+ renderedPayloadSha256: sha2563(source.content),
8814
9016
  provenance: source.provenance ?? null,
8815
9017
  metadata: source.metadata ?? null
8816
9018
  })),
@@ -8828,8 +9030,8 @@ function planSessionRender(input) {
8828
9030
  ...input.providerConfig ? {
8829
9031
  providerConfig: {
8830
9032
  sourceId: input.providerConfig.sourceId,
8831
- selectedPayloadSha256: sha2562(input.providerConfig.content),
8832
- renderedPayloadSha256: files.find((file) => file.relativePath === adapter.configFile)?.sha256 ?? sha2562(input.providerConfig.content),
9033
+ selectedPayloadSha256: sha2563(input.providerConfig.content),
9034
+ renderedPayloadSha256: files.find((file) => file.relativePath === adapter.configFile)?.sha256 ?? sha2563(input.providerConfig.content),
8833
9035
  selected: !existsSync4(joinTarget(targetHome, adapter.configFile))
8834
9036
  }
8835
9037
  } : {},
@@ -8873,15 +9075,16 @@ function sourceFromFilePath(path, content, order = 0) {
8873
9075
  }
8874
9076
  function sourceFromConfig(config, order = 0, layer) {
8875
9077
  const isAgentOperatingRules = config.slug === GLOBAL_AGENT_RULES_STANDARD_SLUG;
9078
+ const rules = isAgentOperatingRules ? resolveAgentOperatingRulesPayload(config.content) : null;
8876
9079
  return {
8877
9080
  id: config.slug,
8878
9081
  label: config.name,
8879
- content: isAgentOperatingRules ? GLOBAL_AGENT_RULES_STANDARD_CONTENT : config.content,
9082
+ content: rules ? rules.content : config.content,
8880
9083
  layer: layer ?? (config.agent === "global" ? "global" : "agent"),
8881
9084
  order,
8882
9085
  path: config.target_path ?? undefined,
8883
- provenance: isAgentOperatingRules ? {
8884
- ...AGENT_OPERATING_RULES_PROVENANCE,
9086
+ provenance: rules ? {
9087
+ ...rules.provenance,
8885
9088
  configSlug: config.slug,
8886
9089
  configAgent: config.agent
8887
9090
  } : {
@@ -8889,7 +9092,7 @@ function sourceFromConfig(config, order = 0, layer) {
8889
9092
  configSlug: config.slug,
8890
9093
  configAgent: config.agent
8891
9094
  },
8892
- metadata: isAgentOperatingRules ? { ...AGENT_OPERATING_RULES_METADATA } : null,
9095
+ metadata: rules ? { ...rules.metadata } : null,
8893
9096
  nonOverridable: isAgentOperatingRules
8894
9097
  };
8895
9098
  }
@@ -8927,7 +9130,7 @@ function selectProfileConfigsForSessionRender(configs, tool) {
8927
9130
  const selectedSources = [];
8928
9131
  const equivalentSources = new Map;
8929
9132
  for (const candidate of sources) {
8930
- const key = sha2562(candidate.source.content);
9133
+ const key = sha2563(candidate.source.content);
8931
9134
  const existing = equivalentSources.get(key);
8932
9135
  if (!existing) {
8933
9136
  equivalentSources.set(key, {
@@ -9273,6 +9476,77 @@ function asStringArray(value) {
9273
9476
  return value.filter((item) => typeof item === "string");
9274
9477
  }
9275
9478
 
9479
+ // src/lib/session-render-ownership.ts
9480
+ import { existsSync as existsSync5, readFileSync as readFileSync3, statSync as statSync3 } from "fs";
9481
+ import { dirname as dirname3, join as join5, parse as parse3, relative as relative3, sep } from "path";
9482
+ var MANIFEST_ANCESTOR_LIMIT = 24;
9483
+ var MANAGED_PATH_SEGMENTS = SESSION_RENDER_EXCLUSIVE_MANAGED_PATHS.map((managedPath) => managedPath.split("/").filter(Boolean));
9484
+ var manifestCache = new Map;
9485
+ function toSegments(absolutePath2) {
9486
+ return absolutePath2.replaceAll("\\", "/").split("/").filter(Boolean);
9487
+ }
9488
+ function pathIsSessionRenderManagedDir(absolutePath2) {
9489
+ const segments = toSegments(absolutePath2);
9490
+ return MANAGED_PATH_SEGMENTS.some((managed) => {
9491
+ if (managed.length === 0 || managed.length > segments.length)
9492
+ return false;
9493
+ for (let start = 0;start + managed.length <= segments.length; start += 1) {
9494
+ if (managed.every((segment, offset) => segments[start + offset] === segment))
9495
+ return true;
9496
+ }
9497
+ return false;
9498
+ });
9499
+ }
9500
+ function readManifestRelativePaths(manifestPath) {
9501
+ let stats;
9502
+ try {
9503
+ if (!existsSync5(manifestPath))
9504
+ return null;
9505
+ stats = statSync3(manifestPath);
9506
+ } catch {
9507
+ return null;
9508
+ }
9509
+ const cached = manifestCache.get(manifestPath);
9510
+ if (cached && cached.mtimeMs === stats.mtimeMs && cached.size === stats.size) {
9511
+ return cached.relativePaths;
9512
+ }
9513
+ let manifest;
9514
+ try {
9515
+ manifest = JSON.parse(readFileSync3(manifestPath, "utf-8"));
9516
+ } catch {
9517
+ return null;
9518
+ }
9519
+ if (manifest?.schema !== SESSION_RENDER_SCHEMA || !Array.isArray(manifest.files))
9520
+ return null;
9521
+ const writerId = manifest.targetOwner?.writer?.id;
9522
+ if (writerId !== undefined && writerId !== SESSION_RENDERER_OWNER_ID)
9523
+ return null;
9524
+ const relativePaths = new Set(manifest.files.map((file) => file?.relativePath).filter((relativePath) => typeof relativePath === "string").map((relativePath) => relativePath.replaceAll("\\", "/")));
9525
+ manifestCache.set(manifestPath, { mtimeMs: stats.mtimeMs, size: stats.size, relativePaths });
9526
+ return relativePaths;
9527
+ }
9528
+ function sessionRenderManifestClaimsPath(absolutePath2) {
9529
+ const root = parse3(absolutePath2).root;
9530
+ let home = dirname3(absolutePath2);
9531
+ for (let depth = 0;depth < MANIFEST_ANCESTOR_LIMIT; depth += 1) {
9532
+ const manifestPath = join5(home, ...SESSION_RENDER_MANIFEST_RELATIVE_PATH.split("/"));
9533
+ const relativePaths = readManifestRelativePaths(manifestPath);
9534
+ if (relativePaths) {
9535
+ const claimed = relative3(home, absolutePath2).split(sep).join("/");
9536
+ if (relativePaths.has(claimed))
9537
+ return true;
9538
+ }
9539
+ const parent = dirname3(home);
9540
+ if (parent === home || home === root)
9541
+ break;
9542
+ home = parent;
9543
+ }
9544
+ return false;
9545
+ }
9546
+ function sessionRenderOwnsPath(absolutePath2) {
9547
+ return pathIsSessionRenderManagedDir(absolutePath2) || sessionRenderManifestClaimsPath(absolutePath2);
9548
+ }
9549
+
9276
9550
  // src/lib/apply.ts
9277
9551
  function getConfigHome() {
9278
9552
  return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir3();
@@ -9291,14 +9565,14 @@ function normalizeTargetPath(p) {
9291
9565
  let current = expanded;
9292
9566
  const missingSegments = [];
9293
9567
  while (true) {
9294
- if (existsSync5(current)) {
9568
+ if (existsSync6(current)) {
9295
9569
  try {
9296
9570
  return resolve3(realpathSync2(current), ...missingSegments);
9297
9571
  } catch {
9298
9572
  return expanded;
9299
9573
  }
9300
9574
  }
9301
- const parent = dirname3(current);
9575
+ const parent = dirname4(current);
9302
9576
  const name = basename4(current);
9303
9577
  if (parent === current)
9304
9578
  return expanded;
@@ -9320,11 +9594,11 @@ async function writeConfigResult(config, targetPath, content, opts, meta = {}) {
9320
9594
  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
9595
  }
9322
9596
  const path = expandPath(renderedTargetPath);
9323
- const previousContent = existsSync5(path) ? readFileSync3(path, "utf-8") : null;
9597
+ const previousContent = existsSync6(path) ? readFileSync4(path, "utf-8") : null;
9324
9598
  const changed = previousContent !== renderedContent;
9325
9599
  if (!opts.dryRun) {
9326
- const dir = dirname3(path);
9327
- if (!existsSync5(dir)) {
9600
+ const dir = dirname4(path);
9601
+ if (!existsSync6(dir)) {
9328
9602
  mkdirSync3(dir, { recursive: true });
9329
9603
  }
9330
9604
  if (previousContent !== null && changed) {
@@ -9627,35 +9901,37 @@ function sessionRendererOwnsTarget(targetPath, opts) {
9627
9901
  return sessionRendererOwnsCanonicalTarget(canonicalApplyTargetPath(targetPath, opts), opts);
9628
9902
  }
9629
9903
  function sessionRendererOwnsCanonicalTarget(normalized, opts) {
9904
+ if (opts.allowSessionRendererOwned)
9905
+ return false;
9630
9906
  const homes = new Set([
9631
9907
  getConfigHome(),
9632
9908
  opts.vars?.["HOME_DIR"]
9633
9909
  ].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("/"))))))
9910
+ if ([...homes].some((home) => SESSION_RENDER_OWNED_CONFIG_TARGETS.some((relativePath) => normalized === normalizeTargetPath(join6(home, ...relativePath.split("/"))))))
9635
9911
  return true;
9636
- return normalized.replaceAll("\\", "/").includes("/.agents/rules/");
9912
+ return sessionRenderOwnsPath(normalized);
9637
9913
  }
9638
9914
 
9639
9915
  // 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";
9916
+ import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
9917
+ import { dirname as dirname5, join as join7 } from "path";
9642
9918
  import { fileURLToPath } from "url";
9643
9919
  var cached = null;
9644
9920
  function getPackageVersion() {
9645
9921
  if (cached)
9646
9922
  return cached;
9647
9923
  try {
9648
- let dir = dirname4(fileURLToPath(import.meta.url));
9924
+ let dir = dirname5(fileURLToPath(import.meta.url));
9649
9925
  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"));
9926
+ const pkgPath = join7(dir, "package.json");
9927
+ if (existsSync7(pkgPath)) {
9928
+ const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
9653
9929
  if (pkg.name === "@hasna/instructions" && pkg.version) {
9654
9930
  cached = pkg.version;
9655
9931
  return cached;
9656
9932
  }
9657
9933
  }
9658
- const parent = dirname4(dir);
9934
+ const parent = dirname5(dir);
9659
9935
  if (parent === dir)
9660
9936
  break;
9661
9937
  dir = parent;
@@ -9711,11 +9987,11 @@ async function getConfigsStatus(store = resolveConfigStore()) {
9711
9987
  continue;
9712
9988
  knownTargets += 1;
9713
9989
  const targetPath = expandPath(config.target_path);
9714
- if (!existsSync7(targetPath)) {
9990
+ if (!existsSync8(targetPath)) {
9715
9991
  missingTargets += 1;
9716
9992
  continue;
9717
9993
  }
9718
- const disk = readFileSync5(targetPath, "utf-8");
9994
+ const disk = readFileSync6(targetPath, "utf-8");
9719
9995
  const { content: redactedDisk } = redactContent(disk, config.format);
9720
9996
  if (redactedDisk !== config.content) {
9721
9997
  driftedTargets += 1;
@@ -9858,16 +10134,16 @@ var PG_MIGRATIONS = [
9858
10134
  `ALTER TABLE configs ADD COLUMN IF NOT EXISTS outputs TEXT NOT NULL DEFAULT '[]'`
9859
10135
  ];
9860
10136
  // src/lib/session-apply.ts
9861
- import { createHash as createHash3, randomUUID as randomUUID4 } from "crypto";
10137
+ import { createHash as createHash4, randomUUID as randomUUID4 } from "crypto";
9862
10138
  import {
9863
- existsSync as existsSync8,
10139
+ existsSync as existsSync9,
9864
10140
  lstatSync as lstatSync2,
9865
10141
  mkdirSync as mkdirSync4,
9866
- readFileSync as readFileSync6,
10142
+ readFileSync as readFileSync7,
9867
10143
  readdirSync,
9868
- statSync as statSync3
10144
+ statSync as statSync4
9869
10145
  } from "fs";
9870
- import { dirname as dirname5, isAbsolute as isAbsolute3, join as join7, parse as parse3, relative as relative3, resolve as resolve4 } from "path";
10146
+ import { dirname as dirname6, isAbsolute as isAbsolute3, join as join8, parse as parse4, relative as relative4, resolve as resolve4 } from "path";
9871
10147
  class SessionApplyError extends Error {
9872
10148
  constructor(message) {
9873
10149
  super(message);
@@ -9947,13 +10223,13 @@ function applySessionRenderUnlocked(plan, options, coordination) {
9947
10223
  };
9948
10224
  }
9949
10225
  function ensureSessionTargetHome(targetHome) {
9950
- if (!existsSync8(targetHome))
10226
+ if (!existsSync9(targetHome))
9951
10227
  mkdirSync4(targetHome, { recursive: true, mode: 448 });
9952
10228
  assertSafeTargetHome(targetHome);
9953
10229
  }
9954
10230
  function checkSessionRenderDrift(targetHome, manifestPath) {
9955
10231
  const safeTargetHome = assertSafeTargetHome(targetHome);
9956
- const resolvedManifestPath = manifestPath ? resolveManifestRelativePath(relative3(safeTargetHome, resolve4(manifestPath)), safeTargetHome) : resolve4(safeTargetHome, ".hasna", "session-render-manifest.json");
10232
+ const resolvedManifestPath = manifestPath ? resolveManifestRelativePath(relative4(safeTargetHome, resolve4(manifestPath)), safeTargetHome) : resolve4(safeTargetHome, ".hasna", "session-render-manifest.json");
9957
10233
  const checkedAt = new Date().toISOString();
9958
10234
  const previousManifest = readPreviousManifest(resolvedManifestPath);
9959
10235
  if (!previousManifest) {
@@ -9970,7 +10246,7 @@ function checkSessionRenderDrift(targetHome, manifestPath) {
9970
10246
  const drifted = [];
9971
10247
  for (const file of previousManifest.files) {
9972
10248
  const target = resolveManifestRelativePath(file.relativePath, safeTargetHome);
9973
- if (!existsSync8(target)) {
10249
+ if (!existsSync9(target)) {
9974
10250
  missing.push({
9975
10251
  path: target,
9976
10252
  relativePath: file.relativePath,
@@ -9980,7 +10256,7 @@ function checkSessionRenderDrift(targetHome, manifestPath) {
9980
10256
  });
9981
10257
  continue;
9982
10258
  }
9983
- const actualSha256 = sha2563(readFileSync6(target, "utf-8"));
10259
+ const actualSha256 = sha2564(readFileSync7(target, "utf-8"));
9984
10260
  if (actualSha256 !== file.sha256) {
9985
10261
  drifted.push({
9986
10262
  path: target,
@@ -10004,7 +10280,7 @@ function restoreSessionRenderSnapshot(snapshotPath, options = {}) {
10004
10280
  const snapshot = readSessionRenderSnapshot(snapshotPath);
10005
10281
  const targetHome = assertSafeTargetHome(snapshot.targetHome);
10006
10282
  const resolvedSnapshotPath = resolve4(snapshotPath);
10007
- const snapshotRelativePath = relative3(targetHome, resolvedSnapshotPath);
10283
+ const snapshotRelativePath = relative4(targetHome, resolvedSnapshotPath);
10008
10284
  if (snapshotRelativePath === "" || snapshotRelativePath === ".." || snapshotRelativePath.startsWith("../") || isAbsolute3(snapshotRelativePath)) {
10009
10285
  throw new SessionApplyError("Session snapshot must be stored inside its target home.");
10010
10286
  }
@@ -10122,18 +10398,18 @@ function requiredRestoreHash(file) {
10122
10398
  }
10123
10399
  function readSessionRenderSnapshot(snapshotPath) {
10124
10400
  const resolved = resolve4(snapshotPath);
10125
- if (!existsSync8(resolved))
10401
+ if (!existsSync9(resolved))
10126
10402
  throw new SessionApplyError(`Session snapshot not found: ${snapshotPath}`);
10127
10403
  const stat = lstatSync2(resolved);
10128
10404
  if (stat.isSymbolicLink() || !stat.isFile()) {
10129
10405
  throw new SessionApplyError(`Session snapshot is not a regular file: ${snapshotPath}`);
10130
10406
  }
10131
- if (statSync3(resolved).size > 32 * 1024 * 1024) {
10407
+ if (statSync4(resolved).size > 32 * 1024 * 1024) {
10132
10408
  throw new SessionApplyError(`Session snapshot exceeds the 32 MiB restore limit: ${snapshotPath}`);
10133
10409
  }
10134
10410
  let parsed;
10135
10411
  try {
10136
- parsed = JSON.parse(readFileSync6(resolved, "utf8"));
10412
+ parsed = JSON.parse(readFileSync7(resolved, "utf8"));
10137
10413
  } catch {
10138
10414
  throw new SessionApplyError(`Session snapshot is not valid JSON: ${snapshotPath}`);
10139
10415
  }
@@ -10155,7 +10431,7 @@ function readSessionRenderSnapshot(snapshotPath) {
10155
10431
  const previousManifest = snapshot.previousManifest;
10156
10432
  const previousFiles = new Map;
10157
10433
  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) {
10434
+ if (!file || typeof file.relativePath !== "string" || typeof file.path !== "string" || typeof file.sha256 !== "string" || typeof file.content !== "string" || sha2564(file.content) !== file.sha256) {
10159
10435
  throw new SessionApplyError(`Session snapshot previous file metadata is invalid: ${snapshotPath}`);
10160
10436
  }
10161
10437
  resolveSnapshotFilePath(file.relativePath, file.path, targetHome);
@@ -10203,7 +10479,7 @@ function readSessionRenderSnapshot(snapshotPath) {
10203
10479
  function reconstructPreRollbackLegacyV1Snapshot(snapshot, previousFiles, previousManifestFiles, targetHome, snapshotPath) {
10204
10480
  assertNoNewerSessionSnapshot(snapshotPath, snapshot.createdAt, targetHome);
10205
10481
  const manifestPath = resolve4(snapshot.manifestPath);
10206
- const manifestRelativePath = relative3(targetHome, manifestPath).replaceAll("\\", "/");
10482
+ const manifestRelativePath = relative4(targetHome, manifestPath).replaceAll("\\", "/");
10207
10483
  resolveSnapshotFilePath(manifestRelativePath, snapshot.manifestPath, targetHome);
10208
10484
  const manifestSha256 = currentSessionFileHash(manifestPath, targetHome);
10209
10485
  if (manifestSha256 === null) {
@@ -10211,7 +10487,7 @@ function reconstructPreRollbackLegacyV1Snapshot(snapshot, previousFiles, previou
10211
10487
  }
10212
10488
  let parsedManifest;
10213
10489
  try {
10214
- parsedManifest = JSON.parse(readFileSync6(manifestPath, "utf8"));
10490
+ parsedManifest = JSON.parse(readFileSync7(manifestPath, "utf8"));
10215
10491
  } catch {
10216
10492
  throw new SessionApplyError(`Pre-rollback legacy v1 applied manifest is not valid JSON: ${snapshotPath}`);
10217
10493
  }
@@ -10303,15 +10579,15 @@ function assertNoNewerSessionSnapshot(snapshotPath, createdAt, targetHome) {
10303
10579
  if (!Number.isFinite(createdAtMs)) {
10304
10580
  throw new SessionApplyError(`Pre-rollback legacy v1 snapshot has an invalid creation time: ${snapshotPath}`);
10305
10581
  }
10306
- for (const entry of readdirSync(dirname5(snapshotPath))) {
10307
- const candidatePath = resolve4(dirname5(snapshotPath), entry);
10582
+ for (const entry of readdirSync(dirname6(snapshotPath))) {
10583
+ const candidatePath = resolve4(dirname6(snapshotPath), entry);
10308
10584
  if (candidatePath === resolve4(snapshotPath) || !entry.endsWith(".json"))
10309
10585
  continue;
10310
10586
  const candidateStat = lstatSync2(candidatePath);
10311
10587
  if (candidateStat.isSymbolicLink() || !candidateStat.isFile() || candidateStat.size > 32 * 1024 * 1024)
10312
10588
  continue;
10313
10589
  try {
10314
- const candidate = JSON.parse(readFileSync6(candidatePath, "utf8"));
10590
+ const candidate = JSON.parse(readFileSync7(candidatePath, "utf8"));
10315
10591
  const candidateCreatedAtMs = typeof candidate.createdAt === "string" ? Date.parse(candidate.createdAt) : Number.NaN;
10316
10592
  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
10593
  throw new SessionApplyError(`Cannot restore pre-rollback legacy v1 snapshot after a newer session snapshot exists: ${candidatePath}`);
@@ -10371,7 +10647,7 @@ function inferLegacySnapshotAction(file, previousFiles, previousManifestFiles, p
10371
10647
  return "create";
10372
10648
  }
10373
10649
  if (file.role === "manifest" && previousManifest) {
10374
- const previousManifestSha256 = sha2563(`${JSON.stringify(previousManifest, null, 2)}
10650
+ const previousManifestSha256 = sha2564(`${JSON.stringify(previousManifest, null, 2)}
10375
10651
  `);
10376
10652
  if (previousManifestSha256 !== file.sha256) {
10377
10653
  throw new SessionApplyError(`Cannot infer legacy v1 manifest action without a before-image: ${file.relativePath}`);
@@ -10389,8 +10665,8 @@ function resolveSnapshotFilePath(relativePath, recordedPath, targetHome) {
10389
10665
  }
10390
10666
  function planFileResult(plan, file, targetHome, previousHashes, previousManifest, options) {
10391
10667
  const target = resolvePlannedFilePath(plan, file, targetHome);
10392
- const previousContent = existsSync8(target) ? readFileSync6(target, "utf-8") : null;
10393
- const previousSha256 = previousContent === null ? null : sha2563(previousContent);
10668
+ const previousContent = existsSync9(target) ? readFileSync7(target, "utf-8") : null;
10669
+ const previousSha256 = previousContent === null ? null : sha2564(previousContent);
10394
10670
  const previouslyManaged = isPreviouslyManaged(file, previousSha256, previousHashes, previousManifest);
10395
10671
  const changed = previousContent !== file.content;
10396
10672
  if (previousContent !== null && !options.force && !previouslyManaged) {
@@ -10472,10 +10748,10 @@ function planStaleFileResults(plan, targetHome, previousManifest, currentRelativ
10472
10748
  }
10473
10749
  function planStaleFileResult(file, targetHome, options) {
10474
10750
  const target = resolveManifestRelativePath(file.relativePath, targetHome);
10475
- if (!existsSync8(target))
10751
+ if (!existsSync9(target))
10476
10752
  return null;
10477
- const previousContent = readFileSync6(target, "utf-8");
10478
- const previousSha256 = sha2563(previousContent);
10753
+ const previousContent = readFileSync7(target, "utf-8");
10754
+ const previousSha256 = sha2564(previousContent);
10479
10755
  if (!options.force && previousSha256 !== file.sha256) {
10480
10756
  return {
10481
10757
  path: target,
@@ -10520,7 +10796,7 @@ function isPreviouslyManaged(file, previousSha256, previousHashes, previousManif
10520
10796
  }
10521
10797
  function resolvePlannedFilePath(plan, file, targetHome) {
10522
10798
  const target = resolve4(targetHome, ...file.relativePath.split("/"));
10523
- const rel = relative3(targetHome, target);
10799
+ const rel = relative4(targetHome, target);
10524
10800
  if (rel === "" || rel === ".." || rel.startsWith("../") || isAbsolute3(rel)) {
10525
10801
  throw new SessionApplyError(`Session file escapes target home: ${file.relativePath}`);
10526
10802
  }
@@ -10532,7 +10808,7 @@ function resolvePlannedFilePath(plan, file, targetHome) {
10532
10808
  }
10533
10809
  function resolveManifestRelativePath(relativePath, targetHome) {
10534
10810
  const target = resolve4(targetHome, ...relativePath.split(/[\\/]+/));
10535
- const rel = relative3(targetHome, target);
10811
+ const rel = relative4(targetHome, target);
10536
10812
  if (rel === "" || rel === ".." || rel.startsWith("../") || isAbsolute3(rel)) {
10537
10813
  throw new SessionApplyError(`Session manifest file escapes target home: ${relativePath}`);
10538
10814
  }
@@ -10540,10 +10816,10 @@ function resolveManifestRelativePath(relativePath, targetHome) {
10540
10816
  return target;
10541
10817
  }
10542
10818
  function readPreviousManifest(path) {
10543
- if (!existsSync8(path))
10819
+ if (!existsSync9(path))
10544
10820
  return null;
10545
10821
  try {
10546
- const parsed = JSON.parse(readFileSync6(path, "utf-8"));
10822
+ const parsed = JSON.parse(readFileSync7(path, "utf-8"));
10547
10823
  if (parsed.schema !== SESSION_RENDER_SCHEMA)
10548
10824
  return null;
10549
10825
  if (!Array.isArray(parsed.files))
@@ -10577,18 +10853,18 @@ function applyPlannedFile(plan, file, targetHome, resultsByPath, coordination, a
10577
10853
  function assertExpectedSessionFileHash(path, targetHome, expectedHash) {
10578
10854
  const actualHash = currentSessionFileHash(path, targetHome);
10579
10855
  if (actualHash !== expectedHash) {
10580
- throw new SessionApplyError(`Session apply path changed after planning: ${relative3(targetHome, path)}`);
10856
+ throw new SessionApplyError(`Session apply path changed after planning: ${relative4(targetHome, path)}`);
10581
10857
  }
10582
10858
  }
10583
10859
  function currentSessionFileHash(path, targetHome) {
10584
10860
  assertNoSymlinkSegments2(targetHome, path);
10585
- if (!existsSync8(path))
10861
+ if (!existsSync9(path))
10586
10862
  return null;
10587
10863
  const stat = lstatSync2(path);
10588
10864
  if (stat.isSymbolicLink() || !stat.isFile()) {
10589
10865
  throw new SessionApplyError(`Session apply path is not a regular file: ${path}`);
10590
10866
  }
10591
- return sha2563(readFileSync6(path, "utf-8"));
10867
+ return sha2564(readFileSync7(path, "utf-8"));
10592
10868
  }
10593
10869
  function requiredPreviousHash(result) {
10594
10870
  if (result.previousSha256 === null) {
@@ -10597,13 +10873,13 @@ function requiredPreviousHash(result) {
10597
10873
  return result.previousSha256;
10598
10874
  }
10599
10875
  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");
10876
+ const existingFiles = results.filter((result) => result.action === "update" || result.action === "delete").filter((result) => existsSync9(result.path)).map((result) => {
10877
+ const content = readFileSync7(result.path, "utf-8");
10602
10878
  return {
10603
10879
  path: result.path,
10604
10880
  relativePath: result.relativePath,
10605
10881
  role: result.role,
10606
- sha256: sha2563(content),
10882
+ sha256: sha2564(content),
10607
10883
  content
10608
10884
  };
10609
10885
  });
@@ -10654,42 +10930,42 @@ function assertSafeTargetHome(targetHome) {
10654
10930
  if (!isAbsolute3(targetHome))
10655
10931
  throw new SessionApplyError(`Session target home must be absolute: ${targetHome}`);
10656
10932
  const normalized = resolve4(targetHome);
10657
- if (normalized === parse3(normalized).root) {
10933
+ if (normalized === parse4(normalized).root) {
10658
10934
  throw new SessionApplyError(`Session target home cannot be the filesystem root: ${targetHome}`);
10659
10935
  }
10660
10936
  assertNoSymlinkAncestors2(normalized);
10661
- if (existsSync8(normalized) && lstatSync2(normalized).isSymbolicLink()) {
10937
+ if (existsSync9(normalized) && lstatSync2(normalized).isSymbolicLink()) {
10662
10938
  throw new SessionApplyError(`Session target home cannot be a symlink: ${normalized}`);
10663
10939
  }
10664
10940
  return normalized;
10665
10941
  }
10666
10942
  function assertNoSymlinkSegments2(root, target) {
10667
10943
  assertNoSymlinkAncestors2(root);
10668
- const rel = relative3(root, target);
10944
+ const rel = relative4(root, target);
10669
10945
  let current = root;
10670
10946
  for (const segment of rel.split(/[\\/]+/).filter(Boolean)) {
10671
- current = join7(current, segment);
10672
- if (existsSync8(current) && lstatSync2(current).isSymbolicLink()) {
10947
+ current = join8(current, segment);
10948
+ if (existsSync9(current) && lstatSync2(current).isSymbolicLink()) {
10673
10949
  throw new SessionApplyError(`Session apply path uses a symlink: ${current}`);
10674
10950
  }
10675
10951
  }
10676
10952
  }
10677
10953
  function assertNoSymlinkAncestors2(path) {
10678
10954
  const normalized = resolve4(path);
10679
- const parsed = parse3(normalized);
10955
+ const parsed = parse4(normalized);
10680
10956
  let current = parsed.root;
10681
- const rel = relative3(parsed.root, normalized);
10957
+ const rel = relative4(parsed.root, normalized);
10682
10958
  for (const segment of rel.split(/[\\/]+/).filter(Boolean)) {
10683
- current = join7(current, segment);
10684
- if (!existsSync8(current))
10959
+ current = join8(current, segment);
10960
+ if (!existsSync9(current))
10685
10961
  return;
10686
10962
  if (lstatSync2(current).isSymbolicLink()) {
10687
10963
  throw new SessionApplyError(`Session apply path uses a symlink ancestor: ${current}`);
10688
10964
  }
10689
10965
  }
10690
10966
  }
10691
- function sha2563(content) {
10692
- return createHash3("sha256").update(content).digest("hex");
10967
+ function sha2564(content) {
10968
+ return createHash4("sha256").update(content).digest("hex");
10693
10969
  }
10694
10970
  // src/lib/project-dashboard-standard.ts
10695
10971
  var PROJECT_DASHBOARD_STANDARD_SLUG = "agent-managed-project-dashboard-standard";
@@ -10987,12 +11263,12 @@ async function ensureDangerousOperationGuardStandardConfig(store = resolveConfig
10987
11263
  }
10988
11264
  }
10989
11265
  // 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";
11266
+ import { existsSync as existsSync11, readdirSync as readdirSync3, readFileSync as readFileSync9 } from "fs";
11267
+ import { basename as basename5, extname as extname3, join as join10 } from "path";
10992
11268
 
10993
11269
  // 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";
11270
+ import { existsSync as existsSync10, readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync5 } from "fs";
11271
+ import { join as join9, relative as relative5 } from "path";
10996
11272
  import { homedir as homedir4 } from "os";
10997
11273
  var SKIP = [".db", ".db-shm", ".db-wal", ".log", ".lock", ".DS_Store", "node_modules", ".git"];
10998
11274
  function shouldSkip(p) {
@@ -11001,9 +11277,9 @@ function shouldSkip(p) {
11001
11277
  async function syncFromDir(dir, opts = {}) {
11002
11278
  const store = opts.store ?? resolveConfigStore();
11003
11279
  const absDir = expandPath(dir);
11004
- if (!existsSync9(absDir))
11280
+ if (!existsSync10(absDir))
11005
11281
  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());
11282
+ const files = opts.recursive !== false ? walkDir(absDir) : readdirSync2(absDir).map((f) => join9(absDir, f)).filter((f) => statSync5(f).isFile());
11007
11283
  const result = { added: 0, updated: 0, unchanged: 0, skipped: [] };
11008
11284
  const home = homedir4();
11009
11285
  const allConfigs = await store.listConfigs();
@@ -11013,7 +11289,7 @@ async function syncFromDir(dir, opts = {}) {
11013
11289
  continue;
11014
11290
  }
11015
11291
  try {
11016
- const content = readFileSync7(file, "utf-8");
11292
+ const content = readFileSync8(file, "utf-8");
11017
11293
  if (content.length > 500000) {
11018
11294
  result.skipped.push(file + " (too large)");
11019
11295
  continue;
@@ -11022,7 +11298,7 @@ async function syncFromDir(dir, opts = {}) {
11022
11298
  const existing = allConfigs.find((c) => c.target_path === targetPath);
11023
11299
  if (!existing) {
11024
11300
  if (!opts.dryRun)
11025
- await store.createConfig({ name: relative4(absDir, file), category: detectCategory(file), agent: detectAgent(file), target_path: targetPath, format: detectFormat(file), content });
11301
+ await store.createConfig({ name: relative5(absDir, file), category: detectCategory(file), agent: detectAgent(file), target_path: targetPath, format: detectFormat(file), content });
11026
11302
  result.added++;
11027
11303
  } else if (existing.content !== content) {
11028
11304
  if (!opts.dryRun)
@@ -11063,7 +11339,7 @@ async function syncToDir(dir, opts = {}) {
11063
11339
  }
11064
11340
  function walkDir(dir, files = []) {
11065
11341
  for (const entry of readdirSync2(dir, { withFileTypes: true })) {
11066
- const full = join8(dir, entry.name);
11342
+ const full = join9(dir, entry.name);
11067
11343
  if (shouldSkip(full))
11068
11344
  continue;
11069
11345
  if (entry.isDirectory())
@@ -11115,7 +11391,7 @@ function isGeneratedOutputTarget2(config, owners) {
11115
11391
  return !!ownerIds && !ownerIds.has(config.id);
11116
11392
  }
11117
11393
  function hasClaudePromptSource() {
11118
- return existsSync10(expandPath("~/.claude/CLAUDE.md"));
11394
+ return existsSync11(expandPath("~/.claude/CLAUDE.md"));
11119
11395
  }
11120
11396
  function hasClaudeRuleSourceForCursorTarget(targetPath) {
11121
11397
  const absoluteTargetPath = expandPath(targetPath);
@@ -11123,7 +11399,7 @@ function hasClaudeRuleSourceForCursorTarget(targetPath) {
11123
11399
  if (!absoluteTargetPath.startsWith(`${absolutePrefix}/`) || !absoluteTargetPath.endsWith(".mdc"))
11124
11400
  return false;
11125
11401
  const stem = basename5(absoluteTargetPath, ".mdc");
11126
- return existsSync10(expandPath(`~/.claude/rules/${stem}.md`)) || existsSync10(expandPath(`~/.claude/rules/${stem}.mdc`));
11402
+ return existsSync11(expandPath(`~/.claude/rules/${stem}.md`)) || existsSync11(expandPath(`~/.claude/rules/${stem}.mdc`));
11127
11403
  }
11128
11404
  function isKnownGeneratedTargetPath(targetPath) {
11129
11405
  const normalizedTargetPath = normalizeTargetPath(targetPath);
@@ -11186,11 +11462,11 @@ async function syncProject(opts) {
11186
11462
  const allConfigs = await store.listConfigs();
11187
11463
  const machine = detectMachineContext();
11188
11464
  for (const pf of PROJECT_CONFIG_FILES) {
11189
- const abs = join9(absDir, pf.file);
11190
- if (!existsSync10(abs))
11465
+ const abs = join10(absDir, pf.file);
11466
+ if (!existsSync11(abs))
11191
11467
  continue;
11192
11468
  try {
11193
- const rawContent = readFileSync8(abs, "utf-8");
11469
+ const rawContent = readFileSync9(abs, "utf-8");
11194
11470
  if (rawContent.length > 500000) {
11195
11471
  result.skipped.push(pf.file);
11196
11472
  continue;
@@ -11219,15 +11495,15 @@ async function syncProject(opts) {
11219
11495
  }
11220
11496
  }
11221
11497
  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" }
11498
+ { dir: join10(absDir, ".claude", "rules"), agent: "claude", namePrefix: "rules" },
11499
+ { dir: join10(absDir, ".agents", "rules"), agent: "antigravity", namePrefix: "antigravity-rules" }
11224
11500
  ]) {
11225
- if (!existsSync10(ruleDir.dir))
11501
+ if (!existsSync11(ruleDir.dir))
11226
11502
  continue;
11227
11503
  const mdFiles = readdirSync3(ruleDir.dir).filter((f) => f.endsWith(".md") || f.endsWith(".mdc"));
11228
11504
  for (const f of mdFiles) {
11229
- const abs = join9(ruleDir.dir, f);
11230
- const raw = readFileSync8(abs, "utf-8");
11505
+ const abs = join10(ruleDir.dir, f);
11506
+ const raw = readFileSync9(abs, "utf-8");
11231
11507
  const redacted = redactContent(raw, "markdown");
11232
11508
  const machineAware = templateizeMachineContent(redacted.content, machine);
11233
11509
  const content = machineAware.content;
@@ -11266,20 +11542,20 @@ async function syncKnown(opts = {}) {
11266
11542
  for (const known of targets) {
11267
11543
  if (known.rulesDir) {
11268
11544
  const absDir = expandPath(known.rulesDir);
11269
- if (!existsSync10(absDir)) {
11545
+ if (!existsSync11(absDir)) {
11270
11546
  result.skipped.push(known.rulesDir);
11271
11547
  continue;
11272
11548
  }
11273
11549
  const extensions = known.rulesExtensions ?? [".md", ".mdc"];
11274
11550
  const ruleFiles = readdirSync3(absDir).filter((f) => extensions.some((ext) => f.endsWith(ext)));
11275
11551
  for (const f of ruleFiles) {
11276
- const abs2 = join9(absDir, f);
11552
+ const abs2 = join10(absDir, f);
11277
11553
  const targetPath = abs2.replace(home, "~");
11278
11554
  if (existingOutputOwners.has(normalizeTargetPath(targetPath)) || isKnownGeneratedTargetPath(targetPath)) {
11279
11555
  result.skipped.push(`${targetPath} (generated output)`);
11280
11556
  continue;
11281
11557
  }
11282
- const raw = readFileSync8(abs2, "utf-8");
11558
+ const raw = readFileSync9(abs2, "utf-8");
11283
11559
  const redacted = redactContent(raw, "markdown");
11284
11560
  const machineAware = templateizeMachineContent(redacted.content, machine);
11285
11561
  const content = machineAware.content;
@@ -11307,12 +11583,12 @@ async function syncKnown(opts = {}) {
11307
11583
  continue;
11308
11584
  }
11309
11585
  const abs = expandPath(known.path);
11310
- if (!existsSync10(abs)) {
11586
+ if (!existsSync11(abs)) {
11311
11587
  result.skipped.push(known.path);
11312
11588
  continue;
11313
11589
  }
11314
11590
  try {
11315
- const rawContent = readFileSync8(abs, "utf-8");
11591
+ const rawContent = readFileSync9(abs, "utf-8");
11316
11592
  if (rawContent.length > 500000) {
11317
11593
  result.skipped.push(known.path + " (too large)");
11318
11594
  continue;
@@ -11400,9 +11676,9 @@ async function syncToDisk(opts = {}) {
11400
11676
  }
11401
11677
  function buildDiff(expectedContent, targetPath) {
11402
11678
  const path = expandPath(targetPath);
11403
- if (!existsSync10(path))
11679
+ if (!existsSync11(path))
11404
11680
  return `(file not found on disk: ${path})`;
11405
- const diskContent = readFileSync8(path, "utf-8");
11681
+ const diskContent = readFileSync9(path, "utf-8");
11406
11682
  if (diskContent === expectedContent)
11407
11683
  return "(no diff \u2014 identical)";
11408
11684
  const stored = expectedContent.split(`
@@ -11516,15 +11792,15 @@ function detectFormat(filePath) {
11516
11792
  return "text";
11517
11793
  }
11518
11794
  // 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";
11795
+ import { existsSync as existsSync12, mkdirSync as mkdirSync5, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "fs";
11796
+ import { join as join11, resolve as resolve5 } from "path";
11521
11797
  import { tmpdir } from "os";
11522
11798
  async function exportConfigs(outputPath, opts = {}) {
11523
11799
  const store = opts.store ?? resolveConfigStore();
11524
11800
  const configs = await store.listConfigs(opts.filter);
11525
11801
  const absOutput = resolve5(outputPath);
11526
- const tmpDir = join10(tmpdir(), `configs-export-${Date.now()}`);
11527
- const contentsDir = join10(tmpDir, "contents");
11802
+ const tmpDir = join11(tmpdir(), `configs-export-${Date.now()}`);
11803
+ const contentsDir = join11(tmpDir, "contents");
11528
11804
  try {
11529
11805
  mkdirSync5(contentsDir, { recursive: true });
11530
11806
  const manifest = {
@@ -11532,10 +11808,10 @@ async function exportConfigs(outputPath, opts = {}) {
11532
11808
  exported_at: new Date().toISOString(),
11533
11809
  configs: configs.map(({ content: _content, ...meta }) => meta)
11534
11810
  };
11535
- writeFileSync3(join10(tmpDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
11811
+ writeFileSync3(join11(tmpDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
11536
11812
  for (const config of configs) {
11537
11813
  const fileName = `${config.slug}.${config.format === "text" ? "txt" : config.format}`;
11538
- writeFileSync3(join10(contentsDir, fileName), config.content, "utf-8");
11814
+ writeFileSync3(join11(contentsDir, fileName), config.content, "utf-8");
11539
11815
  }
11540
11816
  const proc = Bun.spawn(["tar", "czf", absOutput, "-C", tmpDir, "."], {
11541
11817
  stdout: "pipe",
@@ -11548,20 +11824,20 @@ async function exportConfigs(outputPath, opts = {}) {
11548
11824
  }
11549
11825
  return { path: absOutput, count: configs.length };
11550
11826
  } finally {
11551
- if (existsSync11(tmpDir)) {
11827
+ if (existsSync12(tmpDir)) {
11552
11828
  rmSync3(tmpDir, { recursive: true, force: true });
11553
11829
  }
11554
11830
  }
11555
11831
  }
11556
11832
  // 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";
11833
+ import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync10, rmSync as rmSync4 } from "fs";
11834
+ import { join as join12, resolve as resolve6 } from "path";
11559
11835
  import { tmpdir as tmpdir2 } from "os";
11560
11836
  async function importConfigs(bundlePath, opts = {}) {
11561
11837
  const store = opts.store ?? resolveConfigStore();
11562
11838
  const conflict = opts.conflict ?? "skip";
11563
11839
  const absPath = resolve6(bundlePath);
11564
- const tmpDir = join11(tmpdir2(), `configs-import-${Date.now()}`);
11840
+ const tmpDir = join12(tmpdir2(), `configs-import-${Date.now()}`);
11565
11841
  const result = { created: 0, updated: 0, skipped: 0, errors: [] };
11566
11842
  try {
11567
11843
  mkdirSync6(tmpDir, { recursive: true });
@@ -11574,15 +11850,15 @@ async function importConfigs(bundlePath, opts = {}) {
11574
11850
  const stderr = await new Response(proc.stderr).text();
11575
11851
  throw new Error(`tar extraction failed: ${stderr}`);
11576
11852
  }
11577
- const manifestPath = join11(tmpDir, "manifest.json");
11578
- if (!existsSync12(manifestPath))
11853
+ const manifestPath = join12(tmpDir, "manifest.json");
11854
+ if (!existsSync13(manifestPath))
11579
11855
  throw new Error("Invalid bundle: missing manifest.json");
11580
- const manifest = JSON.parse(readFileSync9(manifestPath, "utf-8"));
11856
+ const manifest = JSON.parse(readFileSync10(manifestPath, "utf-8"));
11581
11857
  for (const meta of manifest.configs) {
11582
11858
  try {
11583
11859
  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") : "";
11860
+ const contentFile = join12(tmpDir, "contents", `${meta.slug}.${ext}`);
11861
+ const content = existsSync13(contentFile) ? readFileSync10(contentFile, "utf-8") : "";
11586
11862
  let existing = null;
11587
11863
  try {
11588
11864
  existing = await store.getConfig(meta.slug);
@@ -11616,16 +11892,16 @@ async function importConfigs(bundlePath, opts = {}) {
11616
11892
  }
11617
11893
  return result;
11618
11894
  } finally {
11619
- if (existsSync12(tmpDir)) {
11895
+ if (existsSync13(tmpDir)) {
11620
11896
  rmSync4(tmpDir, { recursive: true, force: true });
11621
11897
  }
11622
11898
  }
11623
11899
  }
11624
11900
  // src/lib/package-manager-guard.ts
11625
11901
  import { execFileSync as execFileSync2 } from "child_process";
11626
- import { existsSync as existsSync13, lstatSync as lstatSync3, readdirSync as readdirSync4, readFileSync as readFileSync10 } from "fs";
11902
+ import { existsSync as existsSync14, lstatSync as lstatSync3, readdirSync as readdirSync4, readFileSync as readFileSync11 } from "fs";
11627
11903
  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";
11904
+ import { basename as basename6, dirname as dirname7, isAbsolute as isAbsolute4, join as join13, relative as relative6, resolve as resolve7 } from "path";
11629
11905
  var SKIP_DIRS = new Set([
11630
11906
  ".git",
11631
11907
  "node_modules",
@@ -11667,7 +11943,7 @@ function scanPackageManagerSecrets(options = {}) {
11667
11943
  const findings = [];
11668
11944
  let scannedFiles = 0;
11669
11945
  for (const root of roots) {
11670
- if (!existsSync13(root))
11946
+ if (!existsSync14(root))
11671
11947
  continue;
11672
11948
  const stat = lstatSync3(root);
11673
11949
  if (stat.isFile()) {
@@ -11677,14 +11953,14 @@ function scanPackageManagerSecrets(options = {}) {
11677
11953
  if (text === null)
11678
11954
  continue;
11679
11955
  scannedFiles++;
11680
- findings.push(...scanFile(root, text, classifyRepoFile(root), isTrackedFile(root), dirname6(root)));
11956
+ findings.push(...scanFile(root, text, classifyRepoFile(root), isTrackedFile(root), dirname7(root)));
11681
11957
  continue;
11682
11958
  }
11683
11959
  if (!stat.isDirectory())
11684
11960
  continue;
11685
11961
  const tracked = trackedFiles(root);
11686
11962
  for (const file of collectRepoFiles(root)) {
11687
- const rel = toPosix(relative5(root, file));
11963
+ const rel = toPosix(relative6(root, file));
11688
11964
  const isTracked = tracked.has(rel);
11689
11965
  const text = readTextFile(file);
11690
11966
  if (text === null)
@@ -11696,8 +11972,8 @@ function scanPackageManagerSecrets(options = {}) {
11696
11972
  if (options.includeHome) {
11697
11973
  const home = homedir5();
11698
11974
  for (const name of HOME_FILES) {
11699
- const file = join12(home, name);
11700
- if (!existsSync13(file))
11975
+ const file = join13(home, name);
11976
+ if (!existsSync14(file))
11701
11977
  continue;
11702
11978
  const text = readTextFile(file);
11703
11979
  if (text === null)
@@ -11721,12 +11997,12 @@ function collectRepoFiles(root) {
11721
11997
  if (entry.isDirectory()) {
11722
11998
  if (SKIP_DIRS.has(entry.name))
11723
11999
  continue;
11724
- visit(join12(dir, entry.name));
12000
+ visit(join13(dir, entry.name));
11725
12001
  continue;
11726
12002
  }
11727
12003
  if (!entry.isFile())
11728
12004
  continue;
11729
- const file = join12(dir, entry.name);
12005
+ const file = join13(dir, entry.name);
11730
12006
  if (shouldScanRepoFile(file))
11731
12007
  out.push(file);
11732
12008
  }
@@ -11764,7 +12040,7 @@ function readTextFile(file) {
11764
12040
  const stat = lstatSync3(file);
11765
12041
  if (!stat.isFile() || stat.size > 5000000)
11766
12042
  return null;
11767
- const buf = readFileSync10(file);
12043
+ const buf = readFileSync11(file);
11768
12044
  if (buf.includes(0))
11769
12045
  return null;
11770
12046
  return buf.toString("utf-8");
@@ -11964,11 +12240,11 @@ function trackedFiles(root) {
11964
12240
  }
11965
12241
  function isTrackedFile(file) {
11966
12242
  try {
11967
- const repoRoot = execFileSync2("git", ["-C", dirname6(file), "rev-parse", "--show-toplevel"], {
12243
+ const repoRoot = execFileSync2("git", ["-C", dirname7(file), "rev-parse", "--show-toplevel"], {
11968
12244
  encoding: "utf-8",
11969
12245
  stdio: ["ignore", "pipe", "ignore"]
11970
12246
  }).trim();
11971
- const rel = toPosix(relative5(repoRoot, file));
12247
+ const rel = toPosix(relative6(repoRoot, file));
11972
12248
  execFileSync2("git", ["-C", repoRoot, "ls-files", "--error-unmatch", "--", rel], {
11973
12249
  stdio: ["ignore", "ignore", "ignore"]
11974
12250
  });
@@ -11996,11 +12272,11 @@ function stripInlineComment(value) {
11996
12272
  function displayPath(file, root) {
11997
12273
  const home = homedir5();
11998
12274
  if (root === home && (file === home || file.startsWith(home + "/")))
11999
- return "~/" + toPosix(relative5(home, file));
12275
+ return "~/" + toPosix(relative6(home, file));
12000
12276
  if (isAbsolute4(root) && file.startsWith(root + "/"))
12001
- return toPosix(relative5(root, file));
12277
+ return toPosix(relative6(root, file));
12002
12278
  if (file === home || file.startsWith(home + "/"))
12003
- return "~/" + toPosix(relative5(home, file));
12279
+ return "~/" + toPosix(relative6(home, file));
12004
12280
  return file;
12005
12281
  }
12006
12282
  function toPosix(path) {
@@ -12029,6 +12305,7 @@ export {
12029
12305
  resolveProfileVariables,
12030
12306
  resolveConfigStore,
12031
12307
  resolveCloudConfig,
12308
+ resolveAgentOperatingRulesPayload,
12032
12309
  renderTemplatePreview,
12033
12310
  renderTemplate,
12034
12311
  renderMachineAwareContentPreview,
@@ -12039,6 +12316,7 @@ export {
12039
12316
  planProjectContext,
12040
12317
  parseTemplateVars,
12041
12318
  parseProjectContextBundle,
12319
+ parseAgentOperatingRulesVersion,
12042
12320
  now,
12043
12321
  normalizeOsFamily,
12044
12322
  machineContextToVariables,
@@ -12063,6 +12341,7 @@ export {
12063
12341
  currentHostname2 as currentHostname,
12064
12342
  currentArch2 as currentArch,
12065
12343
  computeProjectContextSourceHash,
12344
+ compareAgentOperatingRulesVersions,
12066
12345
  cleanSessionPathInput,
12067
12346
  checkSessionRenderDrift,
12068
12347
  buildOpenCodeAgentsMd,
@@ -12118,5 +12397,7 @@ export {
12118
12397
  CONFIG_FORMATS,
12119
12398
  CONFIG_CATEGORIES,
12120
12399
  CONFIG_AGENTS,
12121
- CODEWITH_NATIVE_IMPORTS_ENV
12400
+ CODEWITH_NATIVE_IMPORTS_ENV,
12401
+ AGENT_OPERATING_RULES_SENTINEL_PATTERN,
12402
+ AGENT_OPERATING_RULES_SEMANTIC_POLICY_KEY
12122
12403
  };