@hasna/instructions 0.7.1 → 0.7.2

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.
Files changed (59) hide show
  1. package/README.md +34 -7
  2. package/dist/chunks/{apply-c3sd4agz.js → apply-ps6jjt6k.js} +3 -3
  3. package/dist/chunks/{apply-pnn7a3y7.js → apply-wj7wh5km.js} +3 -3
  4. package/dist/chunks/{index-pdpg8a44.js → index-18j7x3xw.js} +2 -2
  5. package/dist/chunks/{index-3djthcm6.js → index-27az1qb1.js} +28 -1
  6. package/dist/chunks/{index-ypcef3a2.js → index-ape24zc0.js} +2 -2
  7. package/dist/chunks/{index-jg8ptcwh.js → index-ek15201v.js} +2 -2
  8. package/dist/chunks/{index-6jncnnw7.js → index-n6nh6f5r.js} +119 -17
  9. package/dist/chunks/{index-aj66f6xr.js → index-pq18fdbj.js} +29 -6
  10. package/dist/chunks/{index-n3fjspr0.js → index-preyvj8n.js} +28 -1
  11. package/dist/chunks/{index-r7nfef2g.js → index-y8410ve0.js} +3 -3
  12. package/dist/chunks/{local-0a9gja58.js → local-1c1qxzvx.js} +15 -4
  13. package/dist/chunks/{local-969ye538.js → local-hc67bynj.js} +15 -4
  14. package/dist/chunks/{sync-q5hvwq6e.js → sync-12m3vs6g.js} +4 -4
  15. package/dist/chunks/{sync-xtkbm5br.js → sync-azd9t4p8.js} +4 -4
  16. package/dist/chunks/{template-wgnzdn7h.js → template-e4qrxs8p.js} +1 -1
  17. package/dist/chunks/{template-fsfxpe4p.js → template-nhn124zd.js} +1 -1
  18. package/dist/cli/index.js +596 -133
  19. package/dist/data/config-store.d.ts +12 -4
  20. package/dist/data/config-store.d.ts.map +1 -1
  21. package/dist/db/configs.d.ts.map +1 -1
  22. package/dist/index.d.ts +5 -3
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +658 -98
  25. package/dist/lib/asset-plan.d.ts.map +1 -1
  26. package/dist/lib/codewith-shared-todos-storage-standard.d.ts.map +1 -1
  27. package/dist/lib/dangerous-operation-guard-standard.d.ts.map +1 -1
  28. package/dist/lib/global-agent-rules-standard.d.ts.map +1 -1
  29. package/dist/lib/global-source-coverage.d.ts +12 -7
  30. package/dist/lib/global-source-coverage.d.ts.map +1 -1
  31. package/dist/lib/instruction-graph.d.ts +1 -1
  32. package/dist/lib/instruction-graph.d.ts.map +1 -1
  33. package/dist/lib/instruction-source-policy.d.ts +6 -0
  34. package/dist/lib/instruction-source-policy.d.ts.map +1 -0
  35. package/dist/lib/platform-profiles.d.ts.map +1 -1
  36. package/dist/lib/project-dashboard-standard.d.ts.map +1 -1
  37. package/dist/lib/session-apply.d.ts +24 -0
  38. package/dist/lib/session-apply.d.ts.map +1 -1
  39. package/dist/lib/session-refresh.d.ts +30 -0
  40. package/dist/lib/session-refresh.d.ts.map +1 -0
  41. package/dist/lib/session-render.d.ts +34 -1
  42. package/dist/lib/session-render.d.ts.map +1 -1
  43. package/dist/lib/transforms.d.ts +1 -0
  44. package/dist/lib/transforms.d.ts.map +1 -1
  45. package/dist/mcp/index.js +13 -12
  46. package/dist/mcp/server.d.ts.map +1 -1
  47. package/dist/sdk/index.js +19 -0
  48. package/dist/sdk/v1-client.d.ts +7 -1
  49. package/dist/sdk/v1-client.d.ts.map +1 -1
  50. package/dist/sdk/v1.generated.d.ts +20 -0
  51. package/dist/sdk/v1.generated.d.ts.map +1 -1
  52. package/dist/server/index.js +122 -8
  53. package/dist/server/openapi.d.ts +123 -0
  54. package/dist/server/openapi.d.ts.map +1 -1
  55. package/dist/server/v1.d.ts.map +1 -1
  56. package/dist/storage/cloud-store.d.ts.map +1 -1
  57. package/dist/types/index.d.ts +16 -2
  58. package/dist/types/index.d.ts.map +1 -1
  59. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -16,7 +16,12 @@ var __export = (target, all) => {
16
16
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
17
17
 
18
18
  // src/types/index.ts
19
- var CONFIG_KINDS, CONFIG_CATEGORIES, CONFIG_AGENTS, CONFIG_TRANSFORMS, CONFIG_FORMATS, PROFILE_CONFIG_BINDING_SCHEMA = "hasna.instructions.profile-config-binding/v1", INSTRUCTION_ACTIVATION_MODES, INSTRUCTION_FALLBACKS, PROFILE_ASSET_BINDING_SCHEMA = "hasna.instructions.profile-asset-binding/v1", ASSET_KINDS, ASSET_DESTINATION_STRATEGIES, ASSET_SCOPES, ASSET_UNINSTALL_POLICIES, ASSET_ROLLBACK_POLICIES, INSTRUCTIONS_DOMAIN_ARCHIVE_SCHEMA = "hasna.instructions.domain-archive/v2", ConfigNotFoundError, ProfileNotFoundError, ConfigApplyError, TemplateRenderError;
19
+ function validateExpectedConfigVersion(value) {
20
+ if (value !== undefined && (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1)) {
21
+ throw new InvalidExpectedVersionError;
22
+ }
23
+ }
24
+ var CONFIG_KINDS, CONFIG_CATEGORIES, CONFIG_AGENTS, CONFIG_TRANSFORMS, CONFIG_FORMATS, PROFILE_CONFIG_BINDING_SCHEMA = "hasna.instructions.profile-config-binding/v1", INSTRUCTION_ACTIVATION_MODES, INSTRUCTION_FALLBACKS, PROFILE_ASSET_BINDING_SCHEMA = "hasna.instructions.profile-asset-binding/v1", ASSET_KINDS, ASSET_DESTINATION_STRATEGIES, ASSET_SCOPES, ASSET_UNINSTALL_POLICIES, ASSET_ROLLBACK_POLICIES, INSTRUCTIONS_DOMAIN_ARCHIVE_SCHEMA = "hasna.instructions.domain-archive/v2", InvalidExpectedVersionError, ConfigVersionConflictError, ConfigNotFoundError, ProfileNotFoundError, ConfigApplyError, TemplateRenderError;
20
25
  var init_types = __esm(() => {
21
26
  CONFIG_KINDS = ["file", "reference"];
22
27
  CONFIG_CATEGORIES = [
@@ -33,6 +38,7 @@ var init_types = __esm(() => {
33
38
  "claude",
34
39
  "codex",
35
40
  "opencode",
41
+ "sumi",
36
42
  "cursor",
37
43
  "codewith",
38
44
  "aicopilot",
@@ -53,6 +59,7 @@ var init_types = __esm(() => {
53
59
  "claude-passthrough",
54
60
  "codex-flat",
55
61
  "opencode-flat",
62
+ "sumi-flat",
56
63
  "cursor-mdc",
57
64
  "skill-neutral"
58
65
  ];
@@ -71,6 +78,25 @@ var init_types = __esm(() => {
71
78
  ASSET_SCOPES = ["global", "project", "session"];
72
79
  ASSET_UNINSTALL_POLICIES = ["remove-managed", "retain"];
73
80
  ASSET_ROLLBACK_POLICIES = ["snapshot", "installer-receipt", "none"];
81
+ InvalidExpectedVersionError = class InvalidExpectedVersionError extends Error {
82
+ code = "INVALID_EXPECTED_VERSION";
83
+ constructor() {
84
+ super("expected_version must be a positive safe integer");
85
+ this.name = "InvalidExpectedVersionError";
86
+ }
87
+ };
88
+ ConfigVersionConflictError = class ConfigVersionConflictError extends Error {
89
+ config_id;
90
+ expected_version;
91
+ code = "CONFIG_VERSION_CONFLICT";
92
+ status = 409;
93
+ constructor(config_id, expected_version) {
94
+ super(`Config version conflict: ${config_id} no longer has expected version ${expected_version}`);
95
+ this.config_id = config_id;
96
+ this.expected_version = expected_version;
97
+ this.name = "ConfigVersionConflictError";
98
+ }
99
+ };
74
100
  ConfigNotFoundError = class ConfigNotFoundError extends Error {
75
101
  constructor(id) {
76
102
  super(`Config not found: ${id}`);
@@ -143,6 +169,31 @@ function boundedReadPage(items, total, options = {}) {
143
169
  }
144
170
  var init_bounded_read = () => {};
145
171
 
172
+ // src/lib/instruction-source-policy.ts
173
+ function isRetiredInstructionSource(config) {
174
+ return config.tags.some((tag) => tag === "retired-global-source" || tag === "retired-instruction-source");
175
+ }
176
+ function instructionSourceRejection(config) {
177
+ if (isRetiredInstructionSource(config) || config.tags.includes("config-only")) {
178
+ return "source is retired or explicitly configuration-only";
179
+ }
180
+ if (config.category !== "rules")
181
+ return `category ${config.category} is not an instruction source; classify reviewed prose as rules`;
182
+ if (config.format !== "markdown" && config.format !== "text")
183
+ return `format ${config.format} is not instruction prose`;
184
+ if (config.is_template)
185
+ return "unresolved templates must be rendered and reviewed before prompt injection";
186
+ if (!config.content.trim())
187
+ return "instruction source is empty";
188
+ if (config.content.includes("\x00"))
189
+ return "instruction source contains binary content";
190
+ const target = config.target_path?.split(/[\\/]/).pop() ?? "";
191
+ if (/\.(?:json|toml|yaml|yml|ini|sh|bash|zsh|fish|js|ts|py|rules)$/i.test(target)) {
192
+ return "target is an executable, provider policy, or settings file rather than a prompt";
193
+ }
194
+ return null;
195
+ }
196
+
146
197
  // src/lib/global-agent-rules-standard.ts
147
198
  import { createHash } from "crypto";
148
199
  function parseAgentOperatingRulesVersion(content) {
@@ -246,9 +297,13 @@ async function ensureGlobalAgentRulesStandardConfig(store = resolveConfigStore()
246
297
  let existing;
247
298
  try {
248
299
  existing = await store.getConfig(GLOBAL_AGENT_RULES_STANDARD_SLUG);
249
- } catch {
300
+ } catch (error) {
301
+ if (!(error instanceof ConfigNotFoundError))
302
+ throw error;
250
303
  return await store.createConfig(standardConfigInput(resolveAgentOperatingRulesPayload(null)));
251
304
  }
305
+ if (isRetiredInstructionSource(existing))
306
+ return existing;
252
307
  const payload = resolveAgentOperatingRulesPayload(existing.content);
253
308
  const input = standardConfigInput(payload);
254
309
  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)) {
@@ -258,6 +313,7 @@ async function ensureGlobalAgentRulesStandardConfig(store = resolveConfigStore()
258
313
  }
259
314
  var GLOBAL_AGENT_RULES_STANDARD_SLUG = "global-agent-rules-standard", AGENT_OPERATING_RULES_SOURCE_SET_ID = "hasna-global-agent-rules-standard", AGENT_OPERATING_RULES_SOURCE_ID = "hasna-agent-operating-rules", AGENT_OPERATING_RULES_ROLE = "agent-operating-rules", AGENT_OPERATING_RULES_VERSION = "1.1.26", AGENT_OPERATING_RULES_SOURCE_SET_VERSION = "2026-08-11", AGENT_OPERATING_RULES_SEMANTIC_POLICY_KEY = "hasna:agent-operating-rules", AGENT_OPERATING_RULES_SENTINEL_PATTERN, AGENT_OPERATING_RULES_HEADING_PATTERN, AGENT_OPERATING_RULES_PAYLOAD_SHA256 = "486844a3d869e3dabc2f33fd66479d4e2fb0a0d1864a3d8a3dd05669eb3f1b77", AGENT_OPERATING_RULES_UPSTREAM_FILE_SHA256 = "b8e89cdb49e207e5b497ac51384d67022b94fe5645cc9273db60384eb2c2fb32", SCOPED_OPERATIONAL_CONTROL_POLICY_REFERENCE = "hasna-agent-operating-rules/scoped-operational-control/v1", AGENT_OPERATING_RULES_UPSTREAM, SCOPED_OPERATIONAL_CONTROL_POLICY, AGENT_OPERATING_RULES_PROVENANCE, AGENT_OPERATING_RULES_METADATA, GLOBAL_AGENT_RULES_STANDARD_CONTENT;
260
315
  var init_global_agent_rules_standard = __esm(() => {
316
+ init_types();
261
317
  init_config_store();
262
318
  AGENT_OPERATING_RULES_SENTINEL_PATTERN = /<!--\s*hasna:agent-operating-rules\s+v=([0-9]+\.[0-9]+\.[0-9]+)\s*-->/i;
263
319
  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})\)/;
@@ -384,21 +440,23 @@ async function ensureCodewithSharedTodosStorageStandardConfig(store = resolveCon
384
440
  let config;
385
441
  try {
386
442
  const existing = await store.getConfig(CODEWITH_SHARED_TODOS_STORAGE_STANDARD_SLUG);
443
+ if (isRetiredInstructionSource(existing))
444
+ return existing;
387
445
  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)) {
388
446
  config = await store.updateConfig(existing.id, input);
389
447
  } else {
390
448
  config = existing;
391
449
  }
392
- } catch {
450
+ } catch (error) {
451
+ if (!(error instanceof ConfigNotFoundError))
452
+ throw error;
393
453
  config = await store.createConfig(input);
394
454
  }
395
- for (const profile of await store.listProfiles()) {
396
- await store.addConfigToProfile(profile.id, config.id);
397
- }
398
455
  return config;
399
456
  }
400
457
  var CODEWITH_SHARED_TODOS_STORAGE_STANDARD_SLUG = "codewith-shared-todos-storage-standard", CODEWITH_SHARED_TODOS_STORAGE_POLICY_REFERENCE = "codewith/shared-todos-storage/v1", CODEWITH_SHARED_TODOS_STORAGE_STANDARD_CONTENT;
401
458
  var init_codewith_shared_todos_storage_standard = __esm(() => {
459
+ init_types();
402
460
  init_config_store();
403
461
  CODEWITH_SHARED_TODOS_STORAGE_STANDARD_CONTENT = `# Codewith Shared Todos Storage Standard
404
462
 
@@ -7292,7 +7350,7 @@ function sha2562(content) {
7292
7350
  function isRecord(value) {
7293
7351
  return !!value && typeof value === "object" && !Array.isArray(value);
7294
7352
  }
7295
- var PROJECT_CONTEXT_SCHEMA = "hasna.projects.project_context_bundle.v1", PROJECT_CONTEXT_SCHEMA_V2 = "hasna.projects.project_context_bundle.v2", PROJECT_CONTEXT_SUPPORTED_SCHEMAS, projectContextSchema, PROJECT_CONTEXT_MAX_INPUT_BYTES, PROJECT_CONTEXT_MAX_RENDERED_BYTES, PROJECT_CONTEXT_MAX_APPROX_TOKENS = 1000, PROJECT_CONTEXT_MAX_COMMANDS = 6, PROJECT_CONTEXT_MAX_WARNINGS = 3, PROJECT_CONTEXT_FRAGMENT_PATH = ".hasna/instructions/project-context.md", PROJECT_CONTEXT_MANIFEST_PATH = ".hasna/projects/project-context-manifest.json", PROJECT_CONTEXT_CACHE_PATH = ".hasna/projects/project-context-cache.json", PROJECT_CONTEXT_LOCK_PATH = ".hasna/projects/project-context.lock", PROJECT_CONTEXT_SNAPSHOT_DIR = ".hasna/projects/project-context-snapshots", PROJECT_CONTEXT_CACHE_SCHEMA = "hasna.instructions.project-context-cache/v1", PROJECT_CONTEXT_MANAGED_COMMENT = "Managed by @hasna/configs project context", SESSION_COMPATIBILITY_MANIFEST_MAX_BYTES, FOREIGN_INPUT_MAX_BYTES, SESSION_MANAGED_OUTPUT_MAX_BYTES, SESSION_MANAGED_OUTPUT_PATHS, SESSION_MANAGED_OUTPUT_WARN_BYTES, PROJECT_CONTEXT_LOCK_STALE_MS, LEGACY_CONFIGS_PACKAGE = "@hasna/configs", LEGACY_CONFIGS_COMPAT_VERSION = "0.2.45", LEGACY_CONFIGS_EXECUTABLE = "configs", PROJECT_KINDS, PROJECT_STATUSES, LINK_STATES, RESOLUTION_SOURCES, safeId, nullableId, producerSlug, producerName, safeOptionalDisplay, isoTimestamp, revisionSchema, hashSchema, absolutePath, commandArg, financeText, financeLegalEntity, financeProjectMetadataSchema, commandSchema, projectContextBundleSchema, storedManifestProjectContextSchema, storedManifestFileSchema, storedManifestObservationSchema, projectContextMetadataSnapshotSchema, projectContextCacheSchema, ProjectContextError, ProjectContextHashRace, anchoredFsOps, atomicExchange, atomicExchangeLibraries;
7353
+ var PROJECT_CONTEXT_SCHEMA = "hasna.projects.project_context_bundle.v1", PROJECT_CONTEXT_SCHEMA_V2 = "hasna.projects.project_context_bundle.v2", PROJECT_CONTEXT_SUPPORTED_SCHEMAS, projectContextSchema, PROJECT_CONTEXT_MAX_INPUT_BYTES, PROJECT_CONTEXT_MAX_RENDERED_BYTES, PROJECT_CONTEXT_MAX_APPROX_TOKENS = 1000, PROJECT_CONTEXT_MAX_COMMANDS = 6, PROJECT_CONTEXT_MAX_WARNINGS = 3, PROJECT_CONTEXT_FRAGMENT_PATH = ".hasna/instructions/project-context.md", PROJECT_CONTEXT_MANIFEST_PATH = ".hasna/projects/project-context-manifest.json", PROJECT_CONTEXT_CACHE_PATH = ".hasna/projects/project-context-cache.json", PROJECT_CONTEXT_LOCK_PATH = ".hasna/projects/project-context.lock", PROJECT_CONTEXT_SNAPSHOT_DIR = ".hasna/projects/project-context-snapshots", PROJECT_CONTEXT_CACHE_SCHEMA = "hasna.instructions.project-context-cache/v1", PROJECT_CONTEXT_MANAGED_COMMENT = "Managed by @hasna/configs project context", SESSION_COMPATIBILITY_MANIFEST_MAX_BYTES, FOREIGN_INPUT_MAX_BYTES, SESSION_MANAGED_OUTPUT_MAX_BYTES, SESSION_MANAGED_INPUT_MAX_BYTES, SESSION_MANAGED_OUTPUT_PATHS, SESSION_MANAGED_OUTPUT_WARN_BYTES, PROJECT_CONTEXT_LOCK_STALE_MS, LEGACY_CONFIGS_PACKAGE = "@hasna/configs", LEGACY_CONFIGS_COMPAT_VERSION = "0.2.45", LEGACY_CONFIGS_EXECUTABLE = "configs", PROJECT_KINDS, PROJECT_STATUSES, LINK_STATES, RESOLUTION_SOURCES, safeId, nullableId, producerSlug, producerName, safeOptionalDisplay, isoTimestamp, revisionSchema, hashSchema, absolutePath, commandArg, financeText, financeLegalEntity, financeProjectMetadataSchema, commandSchema, projectContextBundleSchema, storedManifestProjectContextSchema, storedManifestFileSchema, storedManifestObservationSchema, projectContextMetadataSnapshotSchema, projectContextCacheSchema, ProjectContextError, ProjectContextHashRace, anchoredFsOps, atomicExchange, atomicExchangeLibraries;
7296
7354
  var init_project_context = __esm(() => {
7297
7355
  init_zod();
7298
7356
  init_redact();
@@ -7305,6 +7363,7 @@ var init_project_context = __esm(() => {
7305
7363
  SESSION_COMPATIBILITY_MANIFEST_MAX_BYTES = 8 * 1024 * 1024;
7306
7364
  FOREIGN_INPUT_MAX_BYTES = 256 * 1024;
7307
7365
  SESSION_MANAGED_OUTPUT_MAX_BYTES = SESSION_COMPATIBILITY_MANIFEST_MAX_BYTES;
7366
+ SESSION_MANAGED_INPUT_MAX_BYTES = SESSION_MANAGED_OUTPUT_MAX_BYTES;
7308
7367
  SESSION_MANAGED_OUTPUT_PATHS = [
7309
7368
  ".hasna/session-render-manifest.json",
7310
7369
  ".codewith/.hasna/session-render-manifest.json",
@@ -7604,6 +7663,9 @@ function buildCodexAgentsMd(source, context = {}) {
7604
7663
  function buildOpenCodeAgentsMd(source, context = {}) {
7605
7664
  return flattenWithRules(source, context);
7606
7665
  }
7666
+ function buildSumiAgentsMd(source, context = {}) {
7667
+ return flattenWithRules(source, context);
7668
+ }
7607
7669
  function buildCursorMdc(source) {
7608
7670
  const stem = source.target_path ? basename2(source.target_path, extname(source.target_path)) : source.slug;
7609
7671
  const description = source.name || stem;
@@ -7632,6 +7694,8 @@ function applyTransform(source, output, context = {}) {
7632
7694
  return buildCodexAgentsMd(source, context);
7633
7695
  case "opencode-flat":
7634
7696
  return buildOpenCodeAgentsMd(source, context);
7697
+ case "sumi-flat":
7698
+ return buildSumiAgentsMd(source, context);
7635
7699
  case "cursor-mdc":
7636
7700
  return buildCursorMdc(source);
7637
7701
  case "skill-neutral":
@@ -8050,6 +8114,7 @@ var init_asset_plan = __esm(() => {
8050
8114
  codex: "cli",
8051
8115
  cursor: "ide",
8052
8116
  opencode: "cli",
8117
+ sumi: "cli",
8053
8118
  codewith: "cli",
8054
8119
  qwen: "cli",
8055
8120
  aicopilot: "cli",
@@ -8698,9 +8763,19 @@ function skippedSource(source, reason) {
8698
8763
  };
8699
8764
  }
8700
8765
  function normalizeSources(sources, tool, allowEmptySources) {
8701
- const normalized = sources.map((source, index) => {
8766
+ const providerSkipped = [];
8767
+ const normalized = sources.flatMap((source, index) => {
8702
8768
  if (!source.id.trim())
8703
8769
  throw new Error("Session instruction source id is required.");
8770
+ if (source.targetProviders?.length && !providerTargetsTool(source.targetProviders, tool)) {
8771
+ providerSkipped.push({
8772
+ id: source.id,
8773
+ label: source.label ?? source.id,
8774
+ targetProviders: source.targetProviders,
8775
+ reason: "instruction source targets a different provider"
8776
+ });
8777
+ return [];
8778
+ }
8704
8779
  const floored = applyAgentOperatingRulesFloor(source, source.content ?? "");
8705
8780
  const content = filterProviderOnlyBlocks(floored.content, tool);
8706
8781
  const normalized2 = {
@@ -8719,7 +8794,7 @@ function normalizeSources(sources, tool, allowEmptySources) {
8719
8794
  if (!allowEmptySources && !normalized2.content.trim() && normalized2.resolvedRules.length === 0 && !hasPathReferences) {
8720
8795
  throw new Error(`Session instruction source "${source.id}" is empty. Pass --allow-empty-sources only for explicit empty renders.`);
8721
8796
  }
8722
- return normalized2;
8797
+ return [normalized2];
8723
8798
  });
8724
8799
  const originalOrder = [...normalized].sort(compareSessionInstructionSources);
8725
8800
  const deduplicated = deduplicateSemanticPolicySources(normalized);
@@ -8727,7 +8802,7 @@ function normalizeSources(sources, tool, allowEmptySources) {
8727
8802
  validateTargetedReplacementSources(originalOrder, ordered, deduplicated.skipped, tool);
8728
8803
  rejectDuplicateSourceSlugs(ordered);
8729
8804
  rejectDuplicateRulePaths(ordered);
8730
- return { sources: ordered, skipped: deduplicated.skipped };
8805
+ return { sources: ordered, skipped: [...providerSkipped, ...deduplicated.skipped] };
8731
8806
  }
8732
8807
  function compareSessionInstructionSources(a, b) {
8733
8808
  return SESSION_LAYER_RANK[a.resolvedLayer] - SESSION_LAYER_RANK[b.resolvedLayer] || a.resolvedOrder - b.resolvedOrder || a.id.localeCompare(b.id);
@@ -9332,6 +9407,11 @@ function isNativeProfileSessionTarget(input) {
9332
9407
  return (input.tool === "grok" || input.tool === "devin") && Boolean(input.targetHome?.trim()) && !input.projectRoot;
9333
9408
  }
9334
9409
  function adapterFor(input) {
9410
+ if (input.tool === "sumi" && input.projectRoot) {
9411
+ if (input.providerSurface)
9412
+ throw new Error(`Provider surface ${input.providerSurface} is not valid for Sumi.`);
9413
+ return Object.freeze({ ...SESSION_TOOL_ADAPTERS.sumi, projectScoped: true, envVar: undefined });
9414
+ }
9335
9415
  if (input.tool === "opencode" && input.providerSurface) {
9336
9416
  if (input.providerSurface !== "opencode-config-instructions" && input.providerSurface !== "opencode-agents-md") {
9337
9417
  throw new Error(`Provider surface ${input.providerSurface} is not valid for OpenCode.`);
@@ -9373,7 +9453,7 @@ function adapterFor(input) {
9373
9453
  }
9374
9454
  if (input.tool !== "codewith")
9375
9455
  return SESSION_TOOL_ADAPTERS[input.tool];
9376
- const gatedNativeImports = input.codewithNativeImports === true || process.env[CODEWITH_NATIVE_IMPORTS_ENV] === "1" || process.env[CODEWITH_NATIVE_IMPORTS_ENV] === "true";
9456
+ const gatedNativeImports = input.codewithNativeImports ?? (process.env[CODEWITH_NATIVE_IMPORTS_ENV] === "1" || process.env[CODEWITH_NATIVE_IMPORTS_ENV] === "true");
9377
9457
  return gatedNativeImports ? CODEWITH_NATIVE_ADAPTER : CODEWITH_FLATTENED_ADAPTER;
9378
9458
  }
9379
9459
  function getHomeDir() {
@@ -9424,6 +9504,13 @@ function assertSafeTargetRoot(targetHome) {
9424
9504
  return normalized;
9425
9505
  }
9426
9506
  function resolveRenderTarget(input, adapter) {
9507
+ if (input.tool === "sumi" && !input.projectRoot && !input.targetHome?.trim()) {
9508
+ return {
9509
+ targetHome: defaultTargetHome(input.tool, input.profile, input.sessionId),
9510
+ targetKind: "blocked",
9511
+ blockers: ["Sumi requires --target-home from `sumi debug paths config`, or --project-root for repository AGENTS.md."]
9512
+ };
9513
+ }
9427
9514
  if (adapter.projectScoped) {
9428
9515
  if (!input.projectRoot) {
9429
9516
  const label = input.tool === "cursor" ? "Cursor rules" : input.tool === "antigravity" ? "Antigravity rules" : `${adapter.description.split(".")[0]} files`;
@@ -9525,6 +9612,14 @@ function planSessionRender(input) {
9525
9612
  const normalized = normalizeSources(input.sources, input.tool, allowEmptySources);
9526
9613
  const composed = composeSources(normalized.sources, input.tool);
9527
9614
  const orderedSources = composed.sources;
9615
+ if (input.tool === "sumi") {
9616
+ for (const source of orderedSources) {
9617
+ const activation = source.metadata?.["activation"];
9618
+ if (source.globs?.length || source.resolvedRules.some((rule) => rule.globs?.length) || activation?.mode && activation.mode !== "always") {
9619
+ throw new Error(`Sumi AGENTS.md cannot preserve conditional activation for source ${source.id}; compile a profile with an explicit supported fallback.`);
9620
+ }
9621
+ }
9622
+ }
9528
9623
  const skippedSources = [
9529
9624
  ...input.skippedSources ?? [],
9530
9625
  ...normalized.skipped,
@@ -9568,6 +9663,7 @@ function planSessionRender(input) {
9568
9663
  adapterMode: adapter.mode,
9569
9664
  profile: input.profile,
9570
9665
  sessionId: input.sessionId ?? null,
9666
+ ...input.refreshSelector ? { refreshSelector: input.refreshSelector } : {},
9571
9667
  targetHome,
9572
9668
  targetKind,
9573
9669
  targetOwner,
@@ -9741,8 +9837,9 @@ function selectProfileConfigsForSessionRender(configs, tool) {
9741
9837
  skippedSources.push(skippedProfileConfig(config, ["opencode"], "provider settings belong to OpenCode"));
9742
9838
  continue;
9743
9839
  }
9744
- if (config.category !== "rules") {
9745
- skippedSources.push(skippedProfileConfig(config, [], config.kind === "reference" ? "reference config is not a provider instruction source" : "profile config is handled by direct config preview/apply"));
9840
+ const sourceRejection = instructionSourceRejection(config);
9841
+ if (sourceRejection) {
9842
+ skippedSources.push(skippedProfileConfig(config, [], sourceRejection));
9746
9843
  continue;
9747
9844
  }
9748
9845
  const output = config.outputs.find((candidate) => candidate.agent === tool);
@@ -9750,7 +9847,7 @@ function selectProfileConfigsForSessionRender(configs, tool) {
9750
9847
  skippedSources.push(skippedProfileConfig(config, [config.agent], "rule targets a different provider"));
9751
9848
  continue;
9752
9849
  }
9753
- const selectedContent = output ? applyTransform(config, output, { configs }) : config.content;
9850
+ const selectedContent = output ? applyTransform(config, output, { configs: [config] }) : config.content;
9754
9851
  sources.push({
9755
9852
  config,
9756
9853
  source: sourceFromConfig({ ...config, content: selectedContent }, sources.length)
@@ -10159,6 +10256,7 @@ var init_session_render = __esm(() => {
10159
10256
  "codex",
10160
10257
  "cursor",
10161
10258
  "opencode",
10259
+ "sumi",
10162
10260
  "codewith",
10163
10261
  "qwen",
10164
10262
  "aicopilot",
@@ -10247,6 +10345,15 @@ var init_session_render = __esm(() => {
10247
10345
  description: "OpenCode AGENTS.md plus opencode.json instructions pointing at managed fragments.",
10248
10346
  providerSurface: "legacy-dual"
10249
10347
  },
10348
+ sumi: {
10349
+ tool: "sumi",
10350
+ mode: "flattened-markdown",
10351
+ indexFile: "AGENTS.md",
10352
+ managedDir: SESSION_RENDER_INSTRUCTIONS_MANAGED_DIR,
10353
+ envVar: "SUMI_CONFIG_DIR",
10354
+ nativeImports: false,
10355
+ description: "Sumi native AGENTS.md in the explicit resolved config directory or project root."
10356
+ },
10250
10357
  aicopilot: {
10251
10358
  tool: "aicopilot",
10252
10359
  mode: "flattened-markdown",
@@ -10535,12 +10642,22 @@ function compileInstructionGraph(input) {
10535
10642
  const selector = binding.providers?.find((entry) => entry.provider === input.context.provider || entry.provider === "global");
10536
10643
  if (binding.providers?.length && !selector)
10537
10644
  continue;
10645
+ const output = config.outputs.find((entry) => entry.agent === input.context.provider);
10646
+ if (!binding.providers?.length && config.agent !== "global" && config.agent !== input.context.provider && !output) {
10647
+ diagnostics.push({ severity: "info", code: "SOURCE_PROVIDER_NOT_SELECTED", config_id: configId, message: `${config.slug} targets ${config.agent}, not ${input.context.provider}.` });
10648
+ continue;
10649
+ }
10538
10650
  if (selector?.version_range && !providerVersionSatisfies(input.context.provider_version, selector.version_range)) {
10539
10651
  diagnostics.push({ severity: binding.required ? "error" : "warning", code: "PROVIDER_SELECTOR_VERSION_MISMATCH", config_id: configId, message: `${config.slug} requires ${input.context.provider} ${selector.version_range}; current version is ${input.context.provider_version}.` });
10540
10652
  continue;
10541
10653
  }
10542
10654
  if (!activationMatches(binding.activation, config, input.context))
10543
10655
  continue;
10656
+ const rejection = instructionSourceRejection(config);
10657
+ if (rejection) {
10658
+ diagnostics.push({ severity: !binding.required && binding.fallback === "omit" ? "warning" : "error", code: "SOURCE_NOT_INSTRUCTION", config_id: configId, message: `${config.slug}: ${rejection}.` });
10659
+ continue;
10660
+ }
10544
10661
  if (capability2.activation_modes.includes(binding.activation.mode)) {
10545
10662
  selected.add(configId);
10546
10663
  effective.set(configId, binding.activation);
@@ -10615,7 +10732,9 @@ function compileInstructionGraph(input) {
10615
10732
  assertExactOnce(units, artifacts);
10616
10733
  const sources = units.map((unit, index) => {
10617
10734
  const config = configs.get(unit.config_id);
10618
- return sourceForUnit(config, unit, index);
10735
+ const output = config.outputs.find((entry) => entry.agent === input.context.provider);
10736
+ const content = output ? applyTransform(config, output, { configs: [config] }) : config.content;
10737
+ return sourceForUnit({ ...config, content }, unit, index);
10619
10738
  });
10620
10739
  const planWithoutHash = {
10621
10740
  schema: INSTRUCTION_GRAPH_PLAN_SCHEMA,
@@ -10843,6 +10962,7 @@ var init_instruction_graph = __esm(() => {
10843
10962
  init_types();
10844
10963
  init_session_render();
10845
10964
  init_asset_plan();
10965
+ init_transforms();
10846
10966
  COMMON_FALLBACKS = ["fail", "flatten", "promote-always", "omit"];
10847
10967
  DEFAULT_PROVIDER_CAPABILITIES = Object.freeze({
10848
10968
  claude: capability("claude", ">=1.0.0", "native-import", "CLAUDE.md @ imports plus path-gated rules", {
@@ -10854,6 +10974,7 @@ var init_instruction_graph = __esm(() => {
10854
10974
  codex: capability("codex", ">=0.1.0", "flattened", "AGENTS.md", { asset_surface: "cli" }),
10855
10975
  cursor: capability("cursor", ">=1.0.0", "cursor-rule", ".cursor/rules/*.mdc", { activation_modes: ["always", "glob"], conditional_artifacts: true, asset_surface: "ide" }),
10856
10976
  opencode: capability("opencode", ">=1.0.0", "managed-fragment", "opencode.json instructions", { provider_variant: "v1-instructions", session_surface: "opencode-config-instructions" }),
10977
+ sumi: capability("sumi", ">=0.2.22 <0.3.0", "flattened", "AGENTS.md"),
10857
10978
  codewith: capability("codewith", ">=0.1.0", "flattened", "CODEWITH.md"),
10858
10979
  qwen: capability("qwen", ">=0.1.0", "flattened", "QWEN.md"),
10859
10980
  aicopilot: capability("aicopilot", ">=0.1.0", "flattened", "AICOPILOT.md"),
@@ -13464,6 +13585,7 @@ function listConfigSummariesPage(filter = {}, options = {}, db) {
13464
13585
  })), total, normalized);
13465
13586
  }
13466
13587
  function updateConfig(idOrSlug, input, db) {
13588
+ validateExpectedConfigVersion(input.expected_version);
13467
13589
  const d = db || getDatabase();
13468
13590
  const existing = getConfig(idOrSlug, d);
13469
13591
  const ts = now();
@@ -13519,7 +13641,15 @@ function updateConfig(idOrSlug, input, db) {
13519
13641
  }
13520
13642
  return d.transaction(() => {
13521
13643
  params.push(existing.id);
13522
- d.run(`UPDATE configs SET ${updates.join(", ")} WHERE id = ?`, params);
13644
+ const condition = input.expected_version === undefined ? "" : " AND version = ?";
13645
+ if (input.expected_version !== undefined)
13646
+ params.push(input.expected_version);
13647
+ const result = d.run(`UPDATE configs SET ${updates.join(", ")} WHERE id = ?${condition}`, params);
13648
+ if (result.changes !== 1) {
13649
+ if (input.expected_version !== undefined)
13650
+ throw new ConfigVersionConflictError(existing.id, input.expected_version);
13651
+ throw new ConfigNotFoundError(existing.id);
13652
+ }
13523
13653
  const updated = getConfigById(existing.id, d);
13524
13654
  createSnapshot(updated.id, updated.content, updated.version, d);
13525
13655
  return updated;
@@ -14418,7 +14548,9 @@ class CloudConfigStore {
14418
14548
  return data.config;
14419
14549
  }
14420
14550
  async updateConfig(idOrSlug, input) {
14421
- const { data } = await this.request("PATCH", `/configs/${encodeURIComponent(idOrSlug)}`, input);
14551
+ validateExpectedConfigVersion(input.expected_version);
14552
+ const conditional = input.expected_version !== undefined;
14553
+ const { data } = await this.request(conditional ? "POST" : "PATCH", `/configs/${encodeURIComponent(idOrSlug)}${conditional ? "/conditional-update" : ""}`, input);
14422
14554
  return data.config;
14423
14555
  }
14424
14556
  async deleteConfig(idOrSlug) {
@@ -14495,7 +14627,7 @@ class CloudConfigStore {
14495
14627
  throw new ProfileNotFoundError(idOrSlug);
14496
14628
  return parseBoundedOrLegacyPage(data.configs, data.profile.configs, normalized, "profile membership");
14497
14629
  }
14498
- async getProfileConfigBindings(idOrSlug) {
14630
+ async getProfileConfigBindings(idOrSlug, options = {}) {
14499
14631
  let routeMissing = false;
14500
14632
  const bindings = await aggregateBoundedCollection("profile config bindings", async (cursor) => {
14501
14633
  const normalized = normalizeBoundedReadOptions({ limit: 100, cursor });
@@ -14508,6 +14640,8 @@ class CloudConfigStore {
14508
14640
  }, (binding) => `${binding.profile_id}\x00${binding.config_id}`);
14509
14641
  if (!routeMissing)
14510
14642
  return bindings;
14643
+ if (options.requireExplicit)
14644
+ throw new Error("HOSTED_BINDINGS_REQUIRED: profile config binding route is unavailable; refusing legacy activation fallback.");
14511
14645
  const profile = await this.getProfile(idOrSlug);
14512
14646
  const configs = await this.getProfileConfigs(idOrSlug);
14513
14647
  return configs.map((config, sort_order) => ({
@@ -14572,7 +14706,7 @@ class CloudConfigStore {
14572
14706
  async removeConfigFromProfile(profileIdOrSlug, configId) {
14573
14707
  await this.request("DELETE", `/profiles/${encodeURIComponent(profileIdOrSlug)}/configs/${encodeURIComponent(configId)}`, undefined, { allow404: true });
14574
14708
  }
14575
- async getProfileAssetBindings(profileIdOrSlug) {
14709
+ async getProfileAssetBindings(profileIdOrSlug, options = {}) {
14576
14710
  let routeMissing = false;
14577
14711
  const assets = await aggregateBoundedCollection("profile asset bindings", async (cursor) => {
14578
14712
  const normalized = normalizeBoundedReadOptions({ limit: 100, cursor });
@@ -14585,6 +14719,8 @@ class CloudConfigStore {
14585
14719
  }, (asset) => `${asset.profile_id}\x00${asset.binding.assetKey}`);
14586
14720
  if (!routeMissing)
14587
14721
  return assets;
14722
+ if (options.requireExplicit)
14723
+ throw new Error("HOSTED_ASSETS_REQUIRED: profile asset binding route is unavailable; refusing an empty asset fallback.");
14588
14724
  await this.getProfile(profileIdOrSlug);
14589
14725
  return [];
14590
14726
  }
@@ -16334,7 +16470,6 @@ import {
16334
16470
  statSync as statSync5
16335
16471
  } from "fs";
16336
16472
  import { dirname as dirname10, isAbsolute as isAbsolute7, join as join17, parse as parse5, relative as relative6, resolve as resolve11 } from "path";
16337
-
16338
16473
  class SessionApplyError extends Error {
16339
16474
  constructor(message) {
16340
16475
  super(message);
@@ -16356,14 +16491,20 @@ function applySessionRenderUnlocked(plan, options, coordination) {
16356
16491
  const targetHome = assertSafeTargetHome(plan.targetHome);
16357
16492
  assertClaudeAuthorityStillClear(plan, targetHome, options.ownedClaudeAuthorities);
16358
16493
  const payloadFiles = [...plan.files, ...plan.assetFiles ?? []];
16359
- const files = [...payloadFiles, plan.manifestFile];
16360
16494
  const manifestPath = resolvePlannedFilePath(plan, plan.manifestFile, targetHome);
16495
+ assertManifestPrecondition(manifestPath, targetHome, options.expectedManifestSha256);
16361
16496
  const previousManifest = readPreviousManifest(manifestPath);
16362
16497
  const previousHashes = previousManifest ? new Map(previousManifest.files.map((file) => [file.relativePath, file.sha256])) : new Map;
16498
+ const adoptions = validateFileAdoptions(plan, targetHome, previousHashes, options);
16499
+ const adoptedHashes = new Map(adoptions.map((entry) => [entry.relativePath, entry.preimageSha256]));
16500
+ const reconciliations = validateFileReconciliations(plan, targetHome, previousManifest, options);
16501
+ const reconciledHashes = new Map(reconciliations.map((entry) => [entry.relativePath, entry.preimageSha256]));
16502
+ const manifestFile = manifestWithFileProvenance(plan, previousManifest, adoptions, reconciliations);
16503
+ const files = [...payloadFiles, manifestFile];
16363
16504
  const currentRelativePaths = new Set(files.map((file) => file.relativePath));
16364
16505
  const drift = checkSessionRenderDrift(targetHome, manifestPath);
16365
16506
  const results = [
16366
- ...files.map((file) => planFileResult(plan, file, targetHome, previousHashes, previousManifest, options)),
16507
+ ...files.map((file) => planFileResult(plan, file, targetHome, previousHashes, previousManifest, options, adoptedHashes, reconciledHashes)),
16367
16508
  ...planStaleFileResults(plan, targetHome, previousManifest, currentRelativePaths, options)
16368
16509
  ];
16369
16510
  assertNotSilentManagedWipeout(plan, results);
@@ -16386,7 +16527,9 @@ function applySessionRenderUnlocked(plan, options, coordination) {
16386
16527
  skippedSources: plan.manifest.skippedSources,
16387
16528
  files: results,
16388
16529
  conflicts,
16389
- drift
16530
+ drift,
16531
+ adoptions,
16532
+ reconciliations
16390
16533
  };
16391
16534
  }
16392
16535
  let snapshotPath = null;
@@ -16399,10 +16542,12 @@ function applySessionRenderUnlocked(plan, options, coordination) {
16399
16542
  if (!options.dryRun) {
16400
16543
  const allowPortableFallback = coordination === null;
16401
16544
  const forcePortableFileOps = options.test_hooks?.force_portable_file_ops ?? false;
16545
+ assertManifestPrecondition(manifestPath, targetHome, options.expectedManifestSha256);
16402
16546
  ensureSessionTargetHome(targetHome);
16403
- rollback = writeSessionSnapshot(plan, targetHome, manifestPath, results, previousManifest, coordination, allowPortableFallback, forcePortableFileOps);
16547
+ rollback = writeSessionSnapshot(plan, targetHome, manifestPath, results, previousManifest, coordination, allowPortableFallback, forcePortableFileOps, adoptions, reconciliations);
16404
16548
  snapshotPath = rollback.snapshotPath;
16405
16549
  options.test_hooks?.before_apply_writes?.({ plan, results });
16550
+ assertManifestPrecondition(manifestPath, targetHome, options.expectedManifestSha256);
16406
16551
  const resultsByPath = new Map(results.map((result) => [result.path, result]));
16407
16552
  for (const file of payloadFiles) {
16408
16553
  applyPlannedFile(plan, file, targetHome, resultsByPath, coordination, allowPortableFallback, forcePortableFileOps);
@@ -16422,7 +16567,7 @@ function applySessionRenderUnlocked(plan, options, coordination) {
16422
16567
  });
16423
16568
  coordination?.assert_held();
16424
16569
  }
16425
- applyPlannedFile(plan, plan.manifestFile, targetHome, resultsByPath, coordination, allowPortableFallback, forcePortableFileOps);
16570
+ applyPlannedFile(plan, manifestFile, targetHome, resultsByPath, coordination, allowPortableFallback, forcePortableFileOps);
16426
16571
  }
16427
16572
  return {
16428
16573
  dryRun: options.dryRun ?? false,
@@ -16436,8 +16581,170 @@ function applySessionRenderUnlocked(plan, options, coordination) {
16436
16581
  skippedSources: plan.manifest.skippedSources,
16437
16582
  files: results,
16438
16583
  conflicts,
16439
- drift
16584
+ drift,
16585
+ adoptions,
16586
+ reconciliations
16587
+ };
16588
+ }
16589
+ function assertManifestPrecondition(path, targetHome, expected) {
16590
+ if (expected === undefined)
16591
+ return;
16592
+ if (!/^[a-f0-9]{64}$/.test(expected)) {
16593
+ throw new SessionApplyError("Expected session manifest SHA-256 must contain 64 lowercase hexadecimal characters.");
16594
+ }
16595
+ if (currentSessionFileHash(path, targetHome) !== expected) {
16596
+ throw new SessionApplyError("Session manifest SHA-256 precondition failed; reload the manifest and resolve a new plan.");
16597
+ }
16598
+ }
16599
+ function validateFileAdoptions(plan, targetHome, previousHashes, options) {
16600
+ const requests = options.adoptFiles ?? [];
16601
+ if (!Array.isArray(requests))
16602
+ throw new SessionApplyError("Session file adoptions must be an array.");
16603
+ if (requests.length > 0 && options.force) {
16604
+ throw new SessionApplyError("Exact file adoption cannot be combined with force.");
16605
+ }
16606
+ const seen = new Set;
16607
+ return requests.map((request) => {
16608
+ if (!request || typeof request.relativePath !== "string" || typeof request.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(request.sha256)) {
16609
+ throw new SessionApplyError("Each file adoption requires a plan-relative path and a 64-character lowercase SHA-256.");
16610
+ }
16611
+ if (seen.has(request.relativePath)) {
16612
+ throw new SessionApplyError(`Duplicate file adoption target: ${request.relativePath}`);
16613
+ }
16614
+ seen.add(request.relativePath);
16615
+ const candidates = plan.files.filter((file2) => file2.relativePath === request.relativePath);
16616
+ if (candidates.length !== 1 || candidates[0].role === "manifest") {
16617
+ throw new SessionApplyError(`File adoption target is not a unique planned instruction output: ${request.relativePath}`);
16618
+ }
16619
+ const file = candidates[0];
16620
+ const path = resolvePlannedFilePath(plan, file, targetHome);
16621
+ if (previousHashes.has(file.relativePath) || sessionRenderOwnsPath(path)) {
16622
+ throw new SessionApplyError(`File adoption target is already managed: ${request.relativePath}`);
16623
+ }
16624
+ const observedSha256 = readExactFilePreimage(path, targetHome, request, "adoption");
16625
+ return {
16626
+ path,
16627
+ relativePath: file.relativePath,
16628
+ preimageSha256: observedSha256,
16629
+ renderedSha256: file.sha256,
16630
+ sourceIds: [...file.sourceIds]
16631
+ };
16632
+ });
16633
+ }
16634
+ function readExactFilePreimage(path, targetHome, request, operation) {
16635
+ if (currentSessionFileHash(path, targetHome) === null) {
16636
+ throw new SessionApplyError(`File ${operation} target does not exist: ${request.relativePath}`);
16637
+ }
16638
+ const bytes = readFileSync14(path);
16639
+ if (!bytes.equals(Buffer.from(bytes.toString("utf8"), "utf8"))) {
16640
+ throw new SessionApplyError(`File ${operation} target must contain losslessly restorable UTF-8: ${request.relativePath}`);
16641
+ }
16642
+ const observedSha256 = createHash10("sha256").update(bytes).digest("hex");
16643
+ if (observedSha256 !== request.sha256) {
16644
+ throw new SessionApplyError(`File ${operation} SHA-256 precondition failed: ${request.relativePath}`);
16645
+ }
16646
+ return observedSha256;
16647
+ }
16648
+ function validateFileReconciliations(plan, targetHome, previousManifest, options) {
16649
+ const requests = options.reconcileFiles ?? [];
16650
+ if (!Array.isArray(requests))
16651
+ throw new SessionApplyError("Session file reconciliations must be an array.");
16652
+ if (requests.length === 0)
16653
+ return [];
16654
+ if (options.force)
16655
+ throw new SessionApplyError("Exact file reconciliation cannot be combined with force.");
16656
+ if (options.expectedManifestSha256 === undefined) {
16657
+ throw new SessionApplyError("Exact file reconciliation requires an expected manifest SHA-256 precondition.");
16658
+ }
16659
+ if (!previousManifest || previousManifest.targetOwner?.writer?.id !== SESSION_RENDERER_OWNER_ID || previousManifest.tool !== plan.tool || previousManifest.targetHome !== targetHome) {
16660
+ throw new SessionApplyError("File reconciliation requires this renderer's manifest for the same tool and target home.");
16661
+ }
16662
+ const seen = new Set;
16663
+ return requests.map((request) => {
16664
+ if (!request || typeof request.relativePath !== "string" || typeof request.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(request.sha256)) {
16665
+ throw new SessionApplyError("Each file reconciliation requires a plan-relative path and a 64-character lowercase SHA-256.");
16666
+ }
16667
+ if (seen.has(request.relativePath)) {
16668
+ throw new SessionApplyError(`Duplicate file reconciliation target: ${request.relativePath}`);
16669
+ }
16670
+ seen.add(request.relativePath);
16671
+ const candidates = plan.files.filter((file2) => file2.relativePath === request.relativePath);
16672
+ if (candidates.length !== 1 || candidates[0].role === "manifest") {
16673
+ throw new SessionApplyError(`File reconciliation target is not a unique planned instruction output: ${request.relativePath}`);
16674
+ }
16675
+ const file = candidates[0];
16676
+ const path = resolvePlannedFilePath(plan, file, targetHome);
16677
+ const owned = previousManifest.files.filter((entry) => entry.relativePath === file.relativePath);
16678
+ if (owned.length !== 1 || owned[0].path !== path || owned[0].role !== file.role || !/^[a-f0-9]{64}$/.test(owned[0].sha256)) {
16679
+ throw new SessionApplyError(`File reconciliation target is not owned by the observed manifest: ${request.relativePath}`);
16680
+ }
16681
+ const observedSha256 = readExactFilePreimage(path, targetHome, request, "reconciliation");
16682
+ if (observedSha256 === owned[0].sha256) {
16683
+ throw new SessionApplyError(`File reconciliation target has no managed drift: ${request.relativePath}`);
16684
+ }
16685
+ if (observedSha256 === file.sha256) {
16686
+ throw new SessionApplyError(`File reconciliation target already matches the planned output: ${request.relativePath}`);
16687
+ }
16688
+ return {
16689
+ path,
16690
+ relativePath: file.relativePath,
16691
+ preimageSha256: observedSha256,
16692
+ renderedSha256: file.sha256,
16693
+ previousManagedSha256: owned[0].sha256,
16694
+ sourceIds: [...file.sourceIds]
16695
+ };
16696
+ });
16697
+ }
16698
+ function manifestWithFileProvenance(plan, previousManifest, adoptions, reconciliations) {
16699
+ if (adoptions.length === 0 && previousManifest?.adoptions === undefined && reconciliations.length === 0 && previousManifest?.reconciliations === undefined)
16700
+ return plan.manifestFile;
16701
+ if (previousManifest?.adoptions !== undefined && !Array.isArray(previousManifest.adoptions)) {
16702
+ throw new SessionApplyError("Previous session manifest adoption provenance is invalid.");
16703
+ }
16704
+ const entries = new Map;
16705
+ for (const entry of [
16706
+ ...previousManifest?.adoptions ?? [],
16707
+ ...adoptions.map(({ path: _path, ...receipt }) => receipt)
16708
+ ]) {
16709
+ if (!entry || typeof entry.relativePath !== "string" || !/^[a-f0-9]{64}$/.test(entry.preimageSha256) || !/^[a-f0-9]{64}$/.test(entry.renderedSha256) || !Array.isArray(entry.sourceIds) || entry.sourceIds.some((id) => typeof id !== "string")) {
16710
+ throw new SessionApplyError("Previous session manifest adoption provenance is invalid.");
16711
+ }
16712
+ resolveManifestRelativePath(entry.relativePath, plan.targetHome);
16713
+ const previous = entries.get(entry.relativePath);
16714
+ if (previous && JSON.stringify(previous) !== JSON.stringify(entry)) {
16715
+ throw new SessionApplyError(`Conflicting session file adoption provenance: ${entry.relativePath}`);
16716
+ }
16717
+ entries.set(entry.relativePath, entry);
16718
+ }
16719
+ if (previousManifest?.reconciliations !== undefined && !Array.isArray(previousManifest.reconciliations)) {
16720
+ throw new SessionApplyError("Previous session manifest reconciliation provenance is invalid.");
16721
+ }
16722
+ const reconciledEntries = new Map;
16723
+ for (const entry of [
16724
+ ...previousManifest?.reconciliations ?? [],
16725
+ ...reconciliations.map(({ path: _path, ...receipt }) => receipt)
16726
+ ]) {
16727
+ if (!entry || typeof entry.relativePath !== "string" || !/^[a-f0-9]{64}$/.test(entry.preimageSha256) || !/^[a-f0-9]{64}$/.test(entry.renderedSha256) || !/^[a-f0-9]{64}$/.test(entry.previousManagedSha256) || !Array.isArray(entry.sourceIds) || entry.sourceIds.some((id) => typeof id !== "string")) {
16728
+ throw new SessionApplyError("Previous session manifest reconciliation provenance is invalid.");
16729
+ }
16730
+ resolveManifestRelativePath(entry.relativePath, plan.targetHome);
16731
+ const canonical = {
16732
+ relativePath: entry.relativePath,
16733
+ preimageSha256: entry.preimageSha256,
16734
+ renderedSha256: entry.renderedSha256,
16735
+ previousManagedSha256: entry.previousManagedSha256,
16736
+ sourceIds: [...entry.sourceIds]
16737
+ };
16738
+ reconciledEntries.set(JSON.stringify(canonical), canonical);
16739
+ }
16740
+ const manifest = {
16741
+ ...plan.manifest,
16742
+ ...adoptions.length > 0 || previousManifest?.adoptions !== undefined ? { adoptions: [...entries.values()] } : {},
16743
+ ...reconciliations.length > 0 || previousManifest?.reconciliations !== undefined ? { reconciliations: [...reconciledEntries.values()] } : {}
16440
16744
  };
16745
+ const content = `${JSON.stringify(manifest, null, 2)}
16746
+ `;
16747
+ return { ...plan.manifestFile, content, sha256: sha25610(content) };
16441
16748
  }
16442
16749
  function assertCursorAuthorityUnchanged(plan) {
16443
16750
  if (plan.tool !== "cursor" || plan.targetKind === "blocked")
@@ -16910,12 +17217,29 @@ function resolveSnapshotFilePath(relativePath, recordedPath, targetHome) {
16910
17217
  }
16911
17218
  return path;
16912
17219
  }
16913
- function planFileResult(plan, file, targetHome, previousHashes, previousManifest, options) {
17220
+ function planFileResult(plan, file, targetHome, previousHashes, previousManifest, options, adoptedHashes, reconciledHashes) {
16914
17221
  const target = resolvePlannedFilePath(plan, file, targetHome);
16915
17222
  const previousContent = existsSync15(target) ? readFileSync14(target, "utf-8") : null;
16916
17223
  const previousSha256 = previousContent === null ? null : sha25610(previousContent);
16917
17224
  const previouslyManaged = isPreviouslyManaged(file, previousSha256, previousHashes, previousManifest);
16918
17225
  const changed = previousContent !== file.content;
17226
+ const exactSha256 = adoptedHashes.get(file.relativePath) ?? reconciledHashes.get(file.relativePath);
17227
+ if (exactSha256 !== undefined) {
17228
+ const operation = adoptedHashes.has(file.relativePath) ? "adoption" : "reconciliation";
17229
+ if (previousSha256 !== exactSha256) {
17230
+ throw new SessionApplyError(`File ${operation} SHA-256 precondition failed: ${file.relativePath}`);
17231
+ }
17232
+ return {
17233
+ path: target,
17234
+ relativePath: file.relativePath,
17235
+ role: file.role,
17236
+ action: "update",
17237
+ changed,
17238
+ previousSha256,
17239
+ newSha256: file.sha256,
17240
+ reason: `exact observed SHA-256 ${operation}`
17241
+ };
17242
+ }
16919
17243
  if (previousContent !== null && !options.force && !previouslyManaged) {
16920
17244
  return {
16921
17245
  path: target,
@@ -17135,9 +17459,13 @@ function requiredPreviousHash(result) {
17135
17459
  }
17136
17460
  return result.previousSha256;
17137
17461
  }
17138
- function writeSessionSnapshot(plan, targetHome, manifestPath, results, previousManifest, coordination, allowPortableFallback, forcePortableFileOps) {
17139
- const existingFiles = results.filter((result) => result.action === "update" || result.action === "delete").filter((result) => existsSync15(result.path)).map((result) => {
17462
+ function writeSessionSnapshot(plan, targetHome, manifestPath, results, previousManifest, coordination, allowPortableFallback, forcePortableFileOps, adoptions, reconciliations) {
17463
+ const existingFiles = results.filter((result) => result.action === "update" || result.action === "delete").map((result) => {
17464
+ assertExpectedSessionFileHash(result.path, targetHome, result.previousSha256);
17140
17465
  const content = readFileSync14(result.path, "utf-8");
17466
+ if (sha25610(content) !== result.previousSha256) {
17467
+ throw new SessionApplyError(`Session snapshot preimage changed after planning: ${result.relativePath}`);
17468
+ }
17141
17469
  return {
17142
17470
  path: result.path,
17143
17471
  relativePath: result.relativePath,
@@ -17178,13 +17506,19 @@ function writeSessionSnapshot(plan, targetHome, manifestPath, results, previousM
17178
17506
  manifestPath,
17179
17507
  previousManifest,
17180
17508
  files: existingFiles,
17181
- afterFiles
17509
+ afterFiles,
17510
+ ...adoptions.length > 0 ? { adoptions } : {},
17511
+ ...reconciliations.length > 0 ? { reconciliations } : {}
17182
17512
  };
17513
+ const snapshotContent = `${JSON.stringify(snapshot, null, 2)}
17514
+ `;
17515
+ if ((adoptions.length > 0 || reconciliations.length > 0) && Buffer.byteLength(snapshotContent, "utf8") > 32 * 1024 * 1024) {
17516
+ throw new SessionApplyError("Exact file preimage snapshot exceeds the 32 MiB restore limit.");
17517
+ }
17183
17518
  coordination?.assert_held();
17184
17519
  writeProjectContextCoordinatedFile({
17185
17520
  path: snapshotPath,
17186
- content: `${JSON.stringify(snapshot, null, 2)}
17187
- `,
17521
+ content: snapshotContent,
17188
17522
  workspace_root: sessionRenderSnapshotWorkspaceRoot(targetHome),
17189
17523
  default_mode: 384,
17190
17524
  expected_hash: null,
@@ -17241,6 +17575,211 @@ function assertNoSymlinkAncestors3(path) {
17241
17575
  function sha25610(content) {
17242
17576
  return createHash10("sha256").update(content).digest("hex");
17243
17577
  }
17578
+ // src/lib/session-refresh.ts
17579
+ init_zod();
17580
+ import { createHash as createHash11 } from "crypto";
17581
+ import { closeSync as closeSync4, constants as constants2, fstatSync as fstatSync4, lstatSync as lstatSync7, openSync as openSync4, readFileSync as readFileSync15 } from "fs";
17582
+ import { dirname as dirname11, join as join18, parse as parse6, resolve as resolve12 } from "path";
17583
+
17584
+ // src/lib/global-source-coverage.ts
17585
+ var GLOBAL_SOURCE_SLUG_PREFIX = "global-";
17586
+ function expectedGlobalSourceSlugs(registryConfigs) {
17587
+ return registryConfigs.filter((c) => c.slug.startsWith(GLOBAL_SOURCE_SLUG_PREFIX)).filter((c) => instructionSourceRejection(c) === null).map((c) => c.slug).sort();
17588
+ }
17589
+ function accountedGlobalSourceSlugs(manifest) {
17590
+ return [...manifest.sources, ...manifest.skippedSources].map((source) => source.id).filter((id) => id.startsWith(GLOBAL_SOURCE_SLUG_PREFIX));
17591
+ }
17592
+ function computeGlobalSourceCoverage(registryConfigs, configuredSlugs) {
17593
+ const expected = expectedGlobalSourceSlugs(registryConfigs);
17594
+ const expectedSet = new Set(expected);
17595
+ const configuredSet = new Set(configuredSlugs);
17596
+ const missing = expected.filter((slug2) => !configuredSet.has(slug2));
17597
+ const unexpected = [...configuredSet].filter((slug2) => slug2.startsWith(GLOBAL_SOURCE_SLUG_PREFIX) && !expectedSet.has(slug2)).sort();
17598
+ return {
17599
+ expectedSlugs: expected,
17600
+ excludedSources: registryConfigs.filter((config) => config.slug.startsWith(GLOBAL_SOURCE_SLUG_PREFIX)).flatMap((config) => {
17601
+ const reason = instructionSourceRejection(config);
17602
+ return reason ? [{ slug: config.slug, reason }] : [];
17603
+ }).sort((left, right) => left.slug.localeCompare(right.slug)),
17604
+ configuredSlugs: [...configuredSet].sort(),
17605
+ missingSlugs: missing,
17606
+ unexpectedSlugs: unexpected,
17607
+ complete: missing.length === 0
17608
+ };
17609
+ }
17610
+
17611
+ // src/lib/session-refresh.ts
17612
+ init_instruction_graph();
17613
+ init_project_context();
17614
+ init_session_render();
17615
+ import { basename as basename6 } from "path";
17616
+ var nonempty = exports_external.string().min(1).max(4096);
17617
+ var selectorSchema = exports_external.object({
17618
+ schema: exports_external.literal("hasna.instructions.hosted-profile-selector/v1"),
17619
+ authority: nonempty,
17620
+ profileId: nonempty,
17621
+ providerVersion: nonempty,
17622
+ providerVariant: nonempty.optional(),
17623
+ model: nonempty.optional(),
17624
+ path: nonempty.optional(),
17625
+ manual: exports_external.array(nonempty).max(256),
17626
+ codewithNativeImports: exports_external.boolean(),
17627
+ allowEmptySources: exports_external.boolean(),
17628
+ stationProfile: exports_external.boolean(),
17629
+ checkGlobalCoverage: exports_external.boolean(),
17630
+ assetSurface: nonempty.optional(),
17631
+ assetScope: exports_external.enum(["global", "project", "session"]).optional()
17632
+ }).strict();
17633
+ function authority(value) {
17634
+ const url = new URL(value);
17635
+ if (url.username || url.password || url.search || url.hash || !["https:", "http:"].includes(url.protocol)) {
17636
+ throw new Error("SESSION_REFRESH_AUTHORITY_INVALID: expected a credential-free Instructions API authority.");
17637
+ }
17638
+ return url.toString().replace(/\/$/, "");
17639
+ }
17640
+ function normalizeSessionHostedProfileSelector(value) {
17641
+ const parsed = selectorSchema.parse(value);
17642
+ return { ...parsed, authority: authority(parsed.authority) };
17643
+ }
17644
+ function assertHostedProfileBindings(profileId, configs, bindings) {
17645
+ const configIds = new Set(configs.map((config) => config.id));
17646
+ const bindingIds = new Set(bindings.map((binding) => binding.config_id));
17647
+ if (configIds.size !== configs.length || bindingIds.size !== bindings.length || bindings.some((binding) => binding.profile_id !== profileId || !configIds.has(binding.config_id)) || [...configIds].some((id) => !bindingIds.has(id))) {
17648
+ throw new Error("HOSTED_PROFILE_BINDINGS_INCOMPLETE: exact one-to-one config membership and explicit profile bindings are required; refusing legacy activation fallback.");
17649
+ }
17650
+ for (const row of bindings) {
17651
+ const raw = row.binding;
17652
+ const invalid = () => new Error("HOSTED_PROFILE_BINDINGS_INVALID: each hosted binding must contain a complete explicit schema, activation, required flag and fallback; refusing legacy activation defaults.");
17653
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
17654
+ throw invalid();
17655
+ const record = raw;
17656
+ if (!["schema", "activation", "required", "fallback"].every((key) => Object.hasOwn(record, key)) || typeof record["required"] !== "boolean")
17657
+ throw invalid();
17658
+ try {
17659
+ normalizeProfileConfigBinding(record);
17660
+ } catch {
17661
+ throw invalid();
17662
+ }
17663
+ }
17664
+ }
17665
+ function readManagedManifest(targetHome) {
17666
+ const path = join18(targetHome, SESSION_RENDER_MANIFEST_RELATIVE_PATH);
17667
+ let ancestor = dirname11(path);
17668
+ while (true) {
17669
+ const stat = lstatSync7(ancestor);
17670
+ if (stat.isSymbolicLink() || !stat.isDirectory())
17671
+ throw new Error("SESSION_REFRESH_PATH_INVALID: managed target uses a symlink or non-directory ancestor.");
17672
+ const parent = dirname11(ancestor);
17673
+ if (parent === ancestor)
17674
+ break;
17675
+ ancestor = parent;
17676
+ }
17677
+ const fd = openSync4(path, constants2.O_RDONLY | constants2.O_NOFOLLOW);
17678
+ let raw;
17679
+ try {
17680
+ const stat = fstatSync4(fd);
17681
+ if (!stat.isFile() || stat.size > SESSION_MANAGED_INPUT_MAX_BYTES)
17682
+ throw new Error("SESSION_REFRESH_MANIFEST_INVALID: expected a bounded regular manifest file.");
17683
+ raw = readFileSync15(fd);
17684
+ if (raw.byteLength > SESSION_MANAGED_INPUT_MAX_BYTES)
17685
+ throw new Error("SESSION_REFRESH_MANIFEST_INVALID: manifest grew beyond the read limit.");
17686
+ } finally {
17687
+ closeSync4(fd);
17688
+ }
17689
+ const manifest = JSON.parse(raw.toString("utf8"));
17690
+ if (manifest.schema !== SESSION_RENDER_SCHEMA || !SESSION_RENDER_TOOLS.includes(manifest.tool) || manifest.targetHome !== targetHome || !manifest.profile?.trim() || !["session-home", "project-root"].includes(manifest.targetKind) || !Array.isArray(manifest.files) || !manifest.refreshSelector || manifest.targetOwner?.writer?.id !== SESSION_RENDERER_OWNER_ID || manifest.targetOwner?.targetHome !== targetHome) {
17691
+ throw new Error("SESSION_REFRESH_MANIFEST_INVALID: target is not an owned hosted profile render; apply a hosted --compile-profile first.");
17692
+ }
17693
+ manifest.refreshSelector = normalizeSessionHostedProfileSelector(manifest.refreshSelector);
17694
+ return { manifest, sha256: createHash11("sha256").update(raw).digest("hex") };
17695
+ }
17696
+ async function refreshSessionRender(input) {
17697
+ const { store } = input;
17698
+ if (store.mode !== "api" || !store.v1BaseUrl)
17699
+ throw new Error("SESSION_REFRESH_HOSTED_REQUIRED: refresh requires the configured hosted Instructions API.");
17700
+ const targetHome = resolve12(input.targetHome);
17701
+ if (targetHome === parse6(targetHome).root)
17702
+ throw new Error("SESSION_REFRESH_PATH_INVALID: filesystem root is not a managed target.");
17703
+ const previous = readManagedManifest(targetHome);
17704
+ const selector = previous.manifest.refreshSelector;
17705
+ if (authority(store.v1BaseUrl) !== selector.authority)
17706
+ throw new Error("SESSION_REFRESH_AUTHORITY_MISMATCH: configured API differs from the recorded profile authority.");
17707
+ const profile = await store.getProfile(selector.profileId);
17708
+ if (profile.id !== selector.profileId)
17709
+ throw new Error("SESSION_REFRESH_PROFILE_MISMATCH: hosted profile identity changed.");
17710
+ const [configs, bindings, assetBindings] = await Promise.all([
17711
+ store.getProfileConfigs(profile.id),
17712
+ store.getProfileConfigBindings(profile.id, { requireExplicit: true }),
17713
+ store.getProfileAssetBindings(profile.id, { requireExplicit: true })
17714
+ ]);
17715
+ assertHostedProfileBindings(profile.id, configs, bindings);
17716
+ if (configs.length > 2048 || bindings.length > 8192 || assetBindings.length > 1024)
17717
+ throw new Error("SESSION_REFRESH_INPUT_LIMIT: hosted profile exceeds refresh bounds.");
17718
+ const totalBytes = configs.reduce((sum, config) => sum + Buffer.byteLength(config.content), 0);
17719
+ if (totalBytes > SESSION_MANAGED_INPUT_MAX_BYTES)
17720
+ throw new Error("SESSION_REFRESH_INPUT_LIMIT: hosted instruction payload exceeds refresh byte bounds.");
17721
+ const assetConfigs = await Promise.all([...new Set(assetBindings.map((binding) => binding.source_config_id))].map((id) => store.getConfigById(id)));
17722
+ if (assetConfigs.reduce((sum, config) => sum + Buffer.byteLength(config.content), totalBytes) > SESSION_MANAGED_INPUT_MAX_BYTES)
17723
+ throw new Error("SESSION_REFRESH_INPUT_LIMIT: hosted source and asset payload exceeds refresh byte bounds.");
17724
+ let ownedClaudeAuthorities;
17725
+ if (previous.manifest.tool === "claude") {
17726
+ ownedClaudeAuthorities = (await store.listConfigs({ category: "rules", agent: "claude", kind: "file" })).filter((config) => config.target_path && basename6(normalizeTargetPath(config.target_path)) === "AGENTS.md").map((config) => ({ slug: config.slug, targetPath: config.target_path, content: config.content }));
17727
+ }
17728
+ const station = selector.stationProfile ? stationProfileSource() : null;
17729
+ const plan = planProfileSessionRender({
17730
+ tool: previous.manifest.tool,
17731
+ profile: previous.manifest.profile,
17732
+ profile_id: profile.id,
17733
+ provider_version: selector.providerVersion,
17734
+ targetHome,
17735
+ ...previous.manifest.targetKind === "project-root" ? { projectRoot: targetHome } : {},
17736
+ sessionId: previous.manifest.sessionId ?? undefined,
17737
+ refreshSelector: selector,
17738
+ codewithNativeImports: selector.codewithNativeImports,
17739
+ allowEmptySources: selector.allowEmptySources,
17740
+ configs,
17741
+ bindings,
17742
+ asset_configs: assetConfigs,
17743
+ asset_bindings: assetBindings,
17744
+ asset_plan_mode: input.dryRun ? "dry-run" : "apply",
17745
+ asset_scope: selector.assetScope,
17746
+ asset_surface: selector.assetSurface,
17747
+ extra_sources: station ? [station] : undefined,
17748
+ ownedClaudeAuthorities,
17749
+ graph_context: {
17750
+ ...selector.providerVariant ? { provider_variant: selector.providerVariant } : {},
17751
+ ...selector.model ? { model: selector.model } : {},
17752
+ ...selector.path ? { path: selector.path } : {},
17753
+ ...selector.manual.length ? { manual: selector.manual } : {}
17754
+ }
17755
+ });
17756
+ if (selector.checkGlobalCoverage) {
17757
+ const coverage = computeGlobalSourceCoverage(await store.listConfigs({}), accountedGlobalSourceSlugs(plan.manifest));
17758
+ if (!coverage.complete)
17759
+ throw new Error(`SESSION_REFRESH_COVERAGE_INCOMPLETE: ${coverage.missingSlugs.length} registered global sources are absent.`);
17760
+ }
17761
+ const preview = applySessionRender(plan, { dryRun: true, expectedManifestSha256: previous.sha256, ownedClaudeAuthorities });
17762
+ const common = { checkedAt: new Date().toISOString(), targetHome, selector, sourceHash: plan.manifest.sourceHash };
17763
+ if (preview.conflicts.length)
17764
+ return { ...common, status: "blocked", apply: preview };
17765
+ if (!preview.drift.clean)
17766
+ throw new Error("SESSION_REFRESH_DRIFT: generated files changed or disappeared since their last managed render.");
17767
+ const sameSources = previous.manifest.sourceHash === plan.manifest.sourceHash;
17768
+ const samePayloads = preview.files.filter((file) => file.role !== "manifest").every((file) => file.action === "unchanged");
17769
+ if (sameSources && samePayloads) {
17770
+ if (readManagedManifest(targetHome).sha256 !== previous.sha256 || !checkSessionRenderDrift(targetHome).clean)
17771
+ throw new Error("SESSION_REFRESH_DRIFT: managed target changed during refresh.");
17772
+ return { ...common, status: "unchanged", apply: { ...preview, files: preview.files.map((file) => file.role === "manifest" ? { ...file, action: "unchanged", changed: false, newSha256: previous.sha256, reason: "hosted sources and generated payloads unchanged" } : file) } };
17773
+ }
17774
+ if (input.dryRun)
17775
+ return { ...common, status: "dry-run", apply: preview };
17776
+ const applied = applySessionRender(plan, { expectedManifestSha256: previous.sha256, ownedClaudeAuthorities });
17777
+ if (applied.conflicts.length)
17778
+ return { ...common, status: "blocked", apply: applied };
17779
+ if (!applied.applied || !checkSessionRenderDrift(targetHome).clean)
17780
+ throw new Error("SESSION_REFRESH_READBACK_FAILED: applied instructions did not verify against their manifest.");
17781
+ return { ...common, status: "updated", apply: applied };
17782
+ }
17244
17783
 
17245
17784
  // src/index.ts
17246
17785
  init_project_context();
@@ -17248,9 +17787,11 @@ init_transforms();
17248
17787
  init_machine();
17249
17788
 
17250
17789
  // src/lib/platform-profiles.ts
17790
+ init_types();
17251
17791
  init_config_store();
17252
17792
 
17253
17793
  // src/lib/project-dashboard-standard.ts
17794
+ init_types();
17254
17795
  init_config_store();
17255
17796
  var PROJECT_DASHBOARD_STANDARD_SLUG = "agent-managed-project-dashboard-standard";
17256
17797
  var PROJECT_DASHBOARD_PROFILE_VARIABLES = {
@@ -17343,11 +17884,15 @@ async function ensureProjectDashboardStandardConfig(store = resolveConfigStore()
17343
17884
  };
17344
17885
  try {
17345
17886
  const existing = await store.getConfig(PROJECT_DASHBOARD_STANDARD_SLUG);
17887
+ if (isRetiredInstructionSource(existing))
17888
+ return existing;
17346
17889
  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) {
17347
17890
  return await store.updateConfig(existing.id, input);
17348
17891
  }
17349
17892
  return existing;
17350
- } catch {
17893
+ } catch (error) {
17894
+ if (!(error instanceof ConfigNotFoundError))
17895
+ throw error;
17351
17896
  return await store.createConfig(input);
17352
17897
  }
17353
17898
  }
@@ -17360,10 +17905,9 @@ function profileHasSelectors2(profile) {
17360
17905
  var PLATFORM_PROFILE_PRESETS = [
17361
17906
  {
17362
17907
  name: "linux-arm64",
17363
- description: "Default Linux arm64 profile for linux-node-a/linux-node-b-style machines",
17364
- selectors: { os: ["linux"], arch: ["arm64"], hostnames: ["linux-node-a", "linux-node-b", "station01"] },
17908
+ description: "Default reviewed instruction profile for Linux arm64",
17909
+ selectors: { os: ["linux"], arch: ["arm64"] },
17365
17910
  variables: {
17366
- WORKSPACE_ROOT: "{{HOME_DIR}}/workspace",
17367
17911
  BUN_BIN_DIR: "{{HOME_DIR}}/.bun/bin",
17368
17912
  BUN_PATH: "{{BUN_BIN_DIR}}/bun",
17369
17913
  PATH_PREFIX: "{{BUN_BIN_DIR}}",
@@ -17372,10 +17916,9 @@ var PLATFORM_PROFILE_PRESETS = [
17372
17916
  },
17373
17917
  {
17374
17918
  name: "macos-arm64",
17375
- description: "Default macOS arm64 profile for macos-node-a/macos-node-b-style machines",
17376
- selectors: { os: ["macos"], arch: ["arm64"], hostnames: ["macos-node-a", "macos-node-b"] },
17919
+ description: "Default reviewed instruction profile for macOS arm64",
17920
+ selectors: { os: ["macos"], arch: ["arm64"] },
17377
17921
  variables: {
17378
- WORKSPACE_ROOT: "{{HOME_DIR}}/Workspace",
17379
17922
  BUN_BIN_DIR: "{{HOME_DIR}}/.bun/bin",
17380
17923
  BUN_PATH: "/opt/homebrew/bin/bun",
17381
17924
  PATH_PREFIX: "/opt/homebrew/bin:{{BUN_BIN_DIR}}",
@@ -17384,12 +17927,21 @@ var PLATFORM_PROFILE_PRESETS = [
17384
17927
  }
17385
17928
  ];
17386
17929
  async function ensurePlatformProfiles(store = resolveConfigStore()) {
17387
- const configs = await store.listConfigs();
17388
17930
  const ensured = [];
17389
- for (const preset of PLATFORM_PROFILE_PRESETS) {
17390
- let profile;
17931
+ const existingProfiles = await Promise.all(PLATFORM_PROFILE_PRESETS.map(async (preset) => {
17391
17932
  try {
17392
- profile = await store.getProfile(preset.name);
17933
+ return await store.getProfile(preset.name);
17934
+ } catch (error) {
17935
+ if (error instanceof ProfileNotFoundError)
17936
+ return null;
17937
+ throw error;
17938
+ }
17939
+ }));
17940
+ for (const [index, preset] of PLATFORM_PROFILE_PRESETS.entries()) {
17941
+ let profile;
17942
+ const existing = existingProfiles[index];
17943
+ if (existing) {
17944
+ profile = existing;
17393
17945
  const selectors = mergeProfileSelectors(preset.selectors, profile.selectors);
17394
17946
  const variables = mergeProfileVariables(preset.variables, profile.variables);
17395
17947
  if (JSON.stringify(selectors) !== JSON.stringify(profile.selectors) || JSON.stringify(variables) !== JSON.stringify(profile.variables)) {
@@ -17399,12 +17951,9 @@ async function ensurePlatformProfiles(store = resolveConfigStore()) {
17399
17951
  variables
17400
17952
  });
17401
17953
  }
17402
- } catch {
17954
+ } else {
17403
17955
  profile = await store.createProfile(preset);
17404
17956
  }
17405
- for (const config of configs) {
17406
- await store.addConfigToProfile(profile.id, config.id);
17407
- }
17408
17957
  ensured.push(profile);
17409
17958
  }
17410
17959
  return ensured;
@@ -17438,6 +17987,7 @@ function mergeUnique(preset, existing) {
17438
17987
  init_global_agent_rules_standard();
17439
17988
 
17440
17989
  // src/lib/dangerous-operation-guard-standard.ts
17990
+ init_types();
17441
17991
  init_config_store();
17442
17992
  var DANGEROUS_OPERATION_GUARD_STANDARD_SLUG = "dangerous-operation-guard-standard";
17443
17993
  var DANGEROUS_OPERATION_GUARD_STANDARD_CONTENT = `# Dangerous Operation Guard Standard
@@ -17549,11 +18099,15 @@ async function ensureDangerousOperationGuardStandardConfig(store = resolveConfig
17549
18099
  };
17550
18100
  try {
17551
18101
  const existing = await store.getConfig(DANGEROUS_OPERATION_GUARD_STANDARD_SLUG);
18102
+ if (isRetiredInstructionSource(existing))
18103
+ return existing;
17552
18104
  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)) {
17553
18105
  return await store.updateConfig(existing.id, input);
17554
18106
  }
17555
18107
  return existing;
17556
- } catch {
18108
+ } catch (error) {
18109
+ if (!(error instanceof ConfigNotFoundError))
18110
+ throw error;
17557
18111
  return await store.createConfig(input);
17558
18112
  }
17559
18113
  }
@@ -17563,8 +18117,8 @@ init_codewith_shared_todos_storage_standard();
17563
18117
 
17564
18118
  // src/lib/sync.ts
17565
18119
  init_config_store();
17566
- import { existsSync as existsSync17, readdirSync as readdirSync5, readFileSync as readFileSync16 } from "fs";
17567
- import { basename as basename6, extname as extname3, join as join19 } from "path";
18120
+ import { existsSync as existsSync17, readdirSync as readdirSync5, readFileSync as readFileSync17 } from "fs";
18121
+ import { basename as basename7, extname as extname3, join as join20 } from "path";
17568
18122
  init_config_agents();
17569
18123
  init_redact();
17570
18124
  init_machine();
@@ -17572,8 +18126,8 @@ init_transforms();
17572
18126
 
17573
18127
  // src/lib/sync-dir.ts
17574
18128
  init_config_store();
17575
- import { existsSync as existsSync16, readdirSync as readdirSync4, readFileSync as readFileSync15, statSync as statSync6 } from "fs";
17576
- import { join as join18, relative as relative7 } from "path";
18129
+ import { existsSync as existsSync16, readdirSync as readdirSync4, readFileSync as readFileSync16, statSync as statSync6 } from "fs";
18130
+ import { join as join19, relative as relative7 } from "path";
17577
18131
  init_redact();
17578
18132
  var SKIP = [".db", ".db-shm", ".db-wal", ".log", ".lock", ".DS_Store", "node_modules", ".git"];
17579
18133
  function shouldSkip(p) {
@@ -17584,7 +18138,7 @@ async function syncFromDir(dir, opts = {}) {
17584
18138
  const absDir = expandPath(dir);
17585
18139
  if (!existsSync16(absDir))
17586
18140
  return { added: 0, updated: 0, unchanged: 0, skipped: [`Not found: ${absDir}`] };
17587
- const files = opts.recursive !== false ? walkDir(absDir) : readdirSync4(absDir).map((f) => join18(absDir, f)).filter((f) => statSync6(f).isFile());
18141
+ const files = opts.recursive !== false ? walkDir(absDir) : readdirSync4(absDir).map((f) => join19(absDir, f)).filter((f) => statSync6(f).isFile());
17588
18142
  const result = { added: 0, updated: 0, unchanged: 0, skipped: [] };
17589
18143
  const allConfigs = await store.listConfigs();
17590
18144
  for (const file of files) {
@@ -17593,7 +18147,7 @@ async function syncFromDir(dir, opts = {}) {
17593
18147
  continue;
17594
18148
  }
17595
18149
  try {
17596
- const content = readFileSync15(file, "utf-8");
18150
+ const content = readFileSync16(file, "utf-8");
17597
18151
  if (content.length > 500000) {
17598
18152
  result.skipped.push(file + " (too large)");
17599
18153
  continue;
@@ -17643,7 +18197,7 @@ async function syncToDir(dir, opts = {}) {
17643
18197
  }
17644
18198
  function walkDir(dir, files = []) {
17645
18199
  for (const entry of readdirSync4(dir, { withFileTypes: true })) {
17646
- const full = join18(dir, entry.name);
18200
+ const full = join19(dir, entry.name);
17647
18201
  if (shouldSkip(full))
17648
18202
  continue;
17649
18203
  if (entry.isDirectory())
@@ -17665,7 +18219,7 @@ var CLAUDE_PROMPT_OUTPUTS = [
17665
18219
  { agent: "qwen", target_path: "~/.qwen/QWEN.md", transform: "codex-flat" }
17666
18220
  ];
17667
18221
  function claudeRuleOutputs(fileName) {
17668
- const stem = basename6(fileName, extname3(fileName));
18222
+ const stem = basename7(fileName, extname3(fileName));
17669
18223
  return [
17670
18224
  { agent: "cursor", target_path: `~/.cursor/rules/${stem}.mdc`, transform: "cursor-mdc" }
17671
18225
  ];
@@ -17711,7 +18265,7 @@ function hasClaudeRuleSourceForCursorTarget(targetPath) {
17711
18265
  const absolutePrefix = expandPath("~/.cursor/rules");
17712
18266
  if (!absoluteTargetPath.startsWith(`${absolutePrefix}/`) || !absoluteTargetPath.endsWith(".mdc"))
17713
18267
  return false;
17714
- const stem = basename6(absoluteTargetPath, ".mdc");
18268
+ const stem = basename7(absoluteTargetPath, ".mdc");
17715
18269
  return existsSync17(expandPath(`~/.claude/rules/${stem}.md`)) || existsSync17(expandPath(`~/.claude/rules/${stem}.mdc`));
17716
18270
  }
17717
18271
  function isKnownGeneratedTargetPath(targetPath) {
@@ -17777,11 +18331,11 @@ async function syncProject(opts) {
17777
18331
  const allConfigs = await store.listConfigs();
17778
18332
  const machine = detectMachineContext();
17779
18333
  for (const pf of PROJECT_CONFIG_FILES) {
17780
- const abs = join19(absDir, pf.file);
18334
+ const abs = join20(absDir, pf.file);
17781
18335
  if (!existsSync17(abs))
17782
18336
  continue;
17783
18337
  try {
17784
- const rawContent = readFileSync16(abs, "utf-8");
18338
+ const rawContent = readFileSync17(abs, "utf-8");
17785
18339
  if (rawContent.length > 500000) {
17786
18340
  result.skipped.push(pf.file);
17787
18341
  continue;
@@ -17810,20 +18364,20 @@ async function syncProject(opts) {
17810
18364
  }
17811
18365
  }
17812
18366
  for (const ruleDir of [
17813
- { dir: join19(absDir, ".claude", "rules"), agent: "claude", namePrefix: "rules" },
17814
- { dir: join19(absDir, ".agents", "rules"), agent: "antigravity", namePrefix: "antigravity-rules" },
17815
- { dir: join19(absDir, ".cursor", "rules"), agent: "cursor", namePrefix: "cursor-rules" },
17816
- { dir: join19(absDir, ".github", "instructions"), agent: "copilot", namePrefix: "copilot-instructions" },
17817
- { dir: join19(absDir, ".devin", "rules"), agent: "devin", namePrefix: "devin-rules" },
17818
- { dir: join19(absDir, ".windsurf", "rules"), agent: "windsurf-legacy", namePrefix: "windsurf-rules" },
17819
- { dir: join19(absDir, ".clinerules"), agent: "cline", namePrefix: "cline-rules" }
18367
+ { dir: join20(absDir, ".claude", "rules"), agent: "claude", namePrefix: "rules" },
18368
+ { dir: join20(absDir, ".agents", "rules"), agent: "antigravity", namePrefix: "antigravity-rules" },
18369
+ { dir: join20(absDir, ".cursor", "rules"), agent: "cursor", namePrefix: "cursor-rules" },
18370
+ { dir: join20(absDir, ".github", "instructions"), agent: "copilot", namePrefix: "copilot-instructions" },
18371
+ { dir: join20(absDir, ".devin", "rules"), agent: "devin", namePrefix: "devin-rules" },
18372
+ { dir: join20(absDir, ".windsurf", "rules"), agent: "windsurf-legacy", namePrefix: "windsurf-rules" },
18373
+ { dir: join20(absDir, ".clinerules"), agent: "cline", namePrefix: "cline-rules" }
17820
18374
  ]) {
17821
18375
  if (!existsSync17(ruleDir.dir))
17822
18376
  continue;
17823
18377
  const mdFiles = readdirSync5(ruleDir.dir).filter((f) => f.endsWith(".md") || f.endsWith(".mdc"));
17824
18378
  for (const f of mdFiles) {
17825
- const abs = join19(ruleDir.dir, f);
17826
- const raw = readFileSync16(abs, "utf-8");
18379
+ const abs = join20(ruleDir.dir, f);
18380
+ const raw = readFileSync17(abs, "utf-8");
17827
18381
  const redacted = redactContent(raw, "markdown");
17828
18382
  const machineAware = templateizeMachineContent(redacted.content, machine);
17829
18383
  const content = machineAware.content;
@@ -17869,13 +18423,13 @@ async function syncKnown(opts = {}) {
17869
18423
  const extensions = known.rulesExtensions ?? [".md", ".mdc"];
17870
18424
  const ruleFiles = readdirSync5(absDir).filter((f) => extensions.some((ext) => f.endsWith(ext)));
17871
18425
  for (const f of ruleFiles) {
17872
- const abs2 = join19(absDir, f);
18426
+ const abs2 = join20(absDir, f);
17873
18427
  const targetPath = abs2.replace(home, "~");
17874
18428
  if (existingOutputOwners.has(normalizeTargetPath(targetPath)) || isKnownGeneratedTargetPath(targetPath)) {
17875
18429
  result.skipped.push(`${targetPath} (generated output)`);
17876
18430
  continue;
17877
18431
  }
17878
- const raw = readFileSync16(abs2, "utf-8");
18432
+ const raw = readFileSync17(abs2, "utf-8");
17879
18433
  const redacted = redactContent(raw, "markdown");
17880
18434
  const machineAware = templateizeMachineContent(redacted.content, machine);
17881
18435
  const content = machineAware.content;
@@ -17908,7 +18462,7 @@ async function syncKnown(opts = {}) {
17908
18462
  continue;
17909
18463
  }
17910
18464
  try {
17911
- const rawContent = normalizeKnownConfigSource(known, readFileSync16(abs, "utf-8"));
18465
+ const rawContent = normalizeKnownConfigSource(known, readFileSync17(abs, "utf-8"));
17912
18466
  if (rawContent.length > 500000) {
17913
18467
  result.skipped.push(known.path + " (too large)");
17914
18468
  continue;
@@ -18013,7 +18567,7 @@ function buildDiff(expectedContent, targetPath, storedFormat, showSecrets) {
18013
18567
  const path = expandPath(targetPath);
18014
18568
  if (!existsSync17(path))
18015
18569
  return `(file not found on disk: ${path})`;
18016
- const diskContent = readFileSync16(path, "utf-8");
18570
+ const diskContent = readFileSync17(path, "utf-8");
18017
18571
  if (diskContent === expectedContent)
18018
18572
  return "(no diff \u2014 identical)";
18019
18573
  const format = redactFormatForTarget(targetPath, storedFormat);
@@ -18173,9 +18727,9 @@ function detectFormat(filePath) {
18173
18727
  // src/lib/export.ts
18174
18728
  init_types();
18175
18729
  init_config_store();
18176
- import { createHash as createHash11 } from "crypto";
18730
+ import { createHash as createHash12 } from "crypto";
18177
18731
  import { existsSync as existsSync18, mkdirSync as mkdirSync8, mkdtempSync, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "fs";
18178
- import { dirname as dirname11, join as join20, resolve as resolve12 } from "path";
18732
+ import { dirname as dirname12, join as join21, resolve as resolve13 } from "path";
18179
18733
  import { tmpdir } from "os";
18180
18734
  var ARCHIVE_EXCLUSIONS = [
18181
18735
  {
@@ -18198,7 +18752,7 @@ function compareText(left, right) {
18198
18752
  return left < right ? -1 : left > right ? 1 : 0;
18199
18753
  }
18200
18754
  function sha25611(value) {
18201
- return createHash11("sha256").update(value).digest("hex");
18755
+ return createHash12("sha256").update(value).digest("hex");
18202
18756
  }
18203
18757
  function canonicalize(value) {
18204
18758
  if (Array.isArray(value))
@@ -18511,13 +19065,13 @@ async function exportConfigs(outputPath, opts = {}) {
18511
19065
  integrity,
18512
19066
  exclusions: ARCHIVE_EXCLUSIONS
18513
19067
  };
18514
- const absOutput = resolve12(outputPath);
18515
- mkdirSync8(dirname11(absOutput), { recursive: true });
18516
- const stagingDir = mkdtempSync(join20(tmpdir(), "instructions-domain-export-"));
19068
+ const absOutput = resolve13(outputPath);
19069
+ mkdirSync8(dirname12(absOutput), { recursive: true });
19070
+ const stagingDir = mkdtempSync(join21(tmpdir(), "instructions-domain-export-"));
18517
19071
  try {
18518
- writeFileSync6(join20(stagingDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
19072
+ writeFileSync6(join21(stagingDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
18519
19073
  `, "utf-8");
18520
- writeFileSync6(join20(stagingDir, "domain.json"), payload, "utf-8");
19074
+ writeFileSync6(join21(stagingDir, "domain.json"), payload, "utf-8");
18521
19075
  const proc = Bun.spawn(["tar", "czf", absOutput, "-C", stagingDir, "manifest.json", "domain.json"], {
18522
19076
  stdout: "pipe",
18523
19077
  stderr: "pipe"
@@ -18536,8 +19090,8 @@ async function exportConfigs(outputPath, opts = {}) {
18536
19090
  // src/lib/import.ts
18537
19091
  init_types();
18538
19092
  init_config_store();
18539
- import { createHash as createHash12 } from "crypto";
18540
- import { resolve as resolve13 } from "path";
19093
+ import { createHash as createHash13 } from "crypto";
19094
+ import { resolve as resolve14 } from "path";
18541
19095
  function compareText2(left, right) {
18542
19096
  return left < right ? -1 : left > right ? 1 : 0;
18543
19097
  }
@@ -18562,7 +19116,7 @@ function emptyResult() {
18562
19116
  };
18563
19117
  }
18564
19118
  function sha25612(value) {
18565
- return createHash12("sha256").update(value).digest("hex");
19119
+ return createHash13("sha256").update(value).digest("hex");
18566
19120
  }
18567
19121
  function normalizeMemberName(name) {
18568
19122
  let normalized = name;
@@ -18825,7 +19379,7 @@ async function importV1(reader, manifest, store, conflict) {
18825
19379
  async function importConfigs(bundlePath, opts = {}) {
18826
19380
  const store = opts.store ?? resolveConfigStore();
18827
19381
  const conflict = opts.conflict ?? "skip";
18828
- const reader = await openArchive(resolve13(bundlePath));
19382
+ const reader = await openArchive(resolve14(bundlePath));
18829
19383
  const manifestText = await reader.read("manifest.json");
18830
19384
  let manifest;
18831
19385
  try {
@@ -18853,9 +19407,9 @@ init_redact();
18853
19407
 
18854
19408
  // src/lib/package-manager-guard.ts
18855
19409
  import { execFileSync as execFileSync2 } from "child_process";
18856
- import { existsSync as existsSync19, lstatSync as lstatSync7, readdirSync as readdirSync6, readFileSync as readFileSync17 } from "fs";
19410
+ import { existsSync as existsSync19, lstatSync as lstatSync8, readdirSync as readdirSync6, readFileSync as readFileSync18 } from "fs";
18857
19411
  import { homedir as homedir10 } from "os";
18858
- import { basename as basename7, dirname as dirname12, isAbsolute as isAbsolute8, join as join21, relative as relative8, resolve as resolve14 } from "path";
19412
+ import { basename as basename8, dirname as dirname13, isAbsolute as isAbsolute8, join as join22, relative as relative8, resolve as resolve15 } from "path";
18859
19413
  var SKIP_DIRS = new Set([
18860
19414
  ".git",
18861
19415
  "node_modules",
@@ -18892,14 +19446,14 @@ var TOKEN_VALUE_PATTERNS = [
18892
19446
  { re: /xoxb-[0-9]+-[A-Za-z0-9-]+/, rule: "literal-slack-token", detail: "literal Slack token-like value" }
18893
19447
  ];
18894
19448
  function scanPackageManagerSecrets(options = {}) {
18895
- const cwd = options.cwd ? resolve14(options.cwd) : process.cwd();
18896
- const roots = (options.roots && options.roots.length > 0 ? options.roots : [cwd]).map((root) => resolve14(cwd, root));
19449
+ const cwd = options.cwd ? resolve15(options.cwd) : process.cwd();
19450
+ const roots = (options.roots && options.roots.length > 0 ? options.roots : [cwd]).map((root) => resolve15(cwd, root));
18897
19451
  const findings = [];
18898
19452
  let scannedFiles = 0;
18899
19453
  for (const root of roots) {
18900
19454
  if (!existsSync19(root))
18901
19455
  continue;
18902
- const stat = lstatSync7(root);
19456
+ const stat = lstatSync8(root);
18903
19457
  if (stat.isFile()) {
18904
19458
  if (!shouldScanRepoFile(root))
18905
19459
  continue;
@@ -18907,7 +19461,7 @@ function scanPackageManagerSecrets(options = {}) {
18907
19461
  if (text === null)
18908
19462
  continue;
18909
19463
  scannedFiles++;
18910
- findings.push(...scanFile(root, text, classifyRepoFile(root), isTrackedFile(root), dirname12(root)));
19464
+ findings.push(...scanFile(root, text, classifyRepoFile(root), isTrackedFile(root), dirname13(root)));
18911
19465
  continue;
18912
19466
  }
18913
19467
  if (!stat.isDirectory())
@@ -18926,7 +19480,7 @@ function scanPackageManagerSecrets(options = {}) {
18926
19480
  if (options.includeHome) {
18927
19481
  const home = homedir10();
18928
19482
  for (const name of HOME_FILES) {
18929
- const file = join21(home, name);
19483
+ const file = join22(home, name);
18930
19484
  if (!existsSync19(file))
18931
19485
  continue;
18932
19486
  const text = readTextFile(file);
@@ -18951,12 +19505,12 @@ function collectRepoFiles(root) {
18951
19505
  if (entry.isDirectory()) {
18952
19506
  if (SKIP_DIRS.has(entry.name))
18953
19507
  continue;
18954
- visit(join21(dir, entry.name));
19508
+ visit(join22(dir, entry.name));
18955
19509
  continue;
18956
19510
  }
18957
19511
  if (!entry.isFile())
18958
19512
  continue;
18959
- const file = join21(dir, entry.name);
19513
+ const file = join22(dir, entry.name);
18960
19514
  if (shouldScanRepoFile(file))
18961
19515
  out.push(file);
18962
19516
  }
@@ -18965,11 +19519,11 @@ function collectRepoFiles(root) {
18965
19519
  return out;
18966
19520
  }
18967
19521
  function shouldScanRepoFile(file) {
18968
- const name = basename7(file);
19522
+ const name = basename8(file);
18969
19523
  return isNpmrcName(name) || isBunConfigName(name) || LOCKFILE_NAMES.has(name);
18970
19524
  }
18971
19525
  function classifyRepoFile(file) {
18972
- const name = basename7(file);
19526
+ const name = basename8(file);
18973
19527
  if (isNpmrcName(name))
18974
19528
  return "repo-npmrc";
18975
19529
  if (isBunConfigName(name))
@@ -18991,10 +19545,10 @@ function isNpmrcName(name) {
18991
19545
  }
18992
19546
  function readTextFile(file) {
18993
19547
  try {
18994
- const stat = lstatSync7(file);
19548
+ const stat = lstatSync8(file);
18995
19549
  if (!stat.isFile() || stat.size > 5000000)
18996
19550
  return null;
18997
- const buf = readFileSync17(file);
19551
+ const buf = readFileSync18(file);
18998
19552
  if (buf.includes(0))
18999
19553
  return null;
19000
19554
  return buf.toString("utf-8");
@@ -19194,7 +19748,7 @@ function trackedFiles(root) {
19194
19748
  }
19195
19749
  function isTrackedFile(file) {
19196
19750
  try {
19197
- const repoRoot = execFileSync2("git", ["-C", dirname12(file), "rev-parse", "--show-toplevel"], {
19751
+ const repoRoot = execFileSync2("git", ["-C", dirname13(file), "rev-parse", "--show-toplevel"], {
19198
19752
  encoding: "utf-8",
19199
19753
  stdio: ["ignore", "pipe", "ignore"]
19200
19754
  }).trim();
@@ -19237,6 +19791,7 @@ function toPosix(path) {
19237
19791
  return path.split("\\").join("/");
19238
19792
  }
19239
19793
  export {
19794
+ validateExpectedConfigVersion,
19240
19795
  uuid,
19241
19796
  transformSkillContent,
19242
19797
  templateizeMachineContent,
@@ -19272,6 +19827,7 @@ export {
19272
19827
  renderMachineAwareContentPreview,
19273
19828
  renderMachineAwareContent,
19274
19829
  refreshStationProfile,
19830
+ refreshSessionRender,
19275
19831
  redactContent,
19276
19832
  reconcileManagedSkillRuntimes,
19277
19833
  readStationProfile,
@@ -19285,6 +19841,7 @@ export {
19285
19841
  parseProjectContextBundle,
19286
19842
  parseAgentOperatingRulesVersion,
19287
19843
  now,
19844
+ normalizeSessionHostedProfileSelector,
19288
19845
  normalizeProfileConfigBinding,
19289
19846
  normalizeProfileAssetBinding,
19290
19847
  normalizeOsFamily,
@@ -19331,6 +19888,7 @@ export {
19331
19888
  compareAgentOperatingRulesVersions,
19332
19889
  cleanSessionPathInput,
19333
19890
  checkSessionRenderDrift,
19891
+ buildSumiAgentsMd,
19334
19892
  buildStationProfileBlock,
19335
19893
  buildOpenCodeAgentsMd,
19336
19894
  buildCursorMdc,
@@ -19390,6 +19948,7 @@ export {
19390
19948
  LEGACY_CONFIGS_EXECUTABLE,
19391
19949
  LEGACY_CONFIGS_COMPAT_VERSION,
19392
19950
  KNOWN_CONFIGS,
19951
+ InvalidExpectedVersionError,
19393
19952
  InstructionGraphValidationError,
19394
19953
  INSTRUCTION_GRAPH_PLAN_SCHEMA,
19395
19954
  INSTRUCTION_FALLBACKS,
@@ -19402,6 +19961,7 @@ export {
19402
19961
  GLOBAL_AGENT_RULES_STANDARD_CONTENT,
19403
19962
  DANGEROUS_OPERATION_GUARD_STANDARD_SLUG,
19404
19963
  DANGEROUS_OPERATION_GUARD_STANDARD_CONTENT,
19964
+ ConfigVersionConflictError,
19405
19965
  ConfigNotFoundError,
19406
19966
  ConfigApplyError,
19407
19967
  CloudConfigStore,