@hasna/instructions 0.7.0 → 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 (74) hide show
  1. package/README.md +52 -11
  2. package/dist/chunks/{apply-7svah2qm.js → apply-ps6jjt6k.js} +3 -3
  3. package/dist/chunks/{apply-jp13sa1e.js → apply-wj7wh5km.js} +3 -3
  4. package/dist/chunks/{index-1cnyjnd7.js → index-18j7x3xw.js} +2 -2
  5. package/dist/chunks/{index-3djthcm6.js → index-27az1qb1.js} +28 -1
  6. package/dist/chunks/{index-fwbs6tma.js → index-ape24zc0.js} +2 -2
  7. package/dist/chunks/{index-bzyxvwcd.js → index-ek15201v.js} +2 -2
  8. package/dist/chunks/{index-arrrx0ed.js → index-mvckkf15.js} +39 -20
  9. package/dist/chunks/{index-7m4j8a33.js → index-n6nh6f5r.js} +235 -20
  10. package/dist/chunks/{index-4pfq42t5.js → index-pq18fdbj.js} +146 -32
  11. package/dist/chunks/{index-n3fjspr0.js → index-preyvj8n.js} +28 -1
  12. package/dist/chunks/{index-z3ma4aqk.js → index-y8410ve0.js} +3 -3
  13. package/dist/chunks/{local-5wvv5xv3.js → local-1c1qxzvx.js} +155 -4
  14. package/dist/chunks/{local-zxa5dpf4.js → local-hc67bynj.js} +155 -4
  15. package/dist/chunks/{s3-backup-n2z4fwyh.js → s3-backup-hxe3zpfz.js} +1 -1
  16. package/dist/chunks/{s3-object-store-90tgbh6k.js → s3-object-store-n0s82swt.js} +1 -1
  17. package/dist/chunks/{sync-r8t7zsp3.js → sync-12m3vs6g.js} +4 -4
  18. package/dist/chunks/{sync-2075deve.js → sync-azd9t4p8.js} +4 -4
  19. package/dist/chunks/{template-wgnzdn7h.js → template-e4qrxs8p.js} +1 -1
  20. package/dist/chunks/{template-fsfxpe4p.js → template-nhn124zd.js} +1 -1
  21. package/dist/cli/index.js +860 -181
  22. package/dist/data/config-store.d.ts +22 -6
  23. package/dist/data/config-store.d.ts.map +1 -1
  24. package/dist/db/configs.d.ts +4 -1
  25. package/dist/db/configs.d.ts.map +1 -1
  26. package/dist/db/local.d.ts +1 -1
  27. package/dist/db/local.d.ts.map +1 -1
  28. package/dist/index.d.ts +5 -3
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +940 -134
  31. package/dist/lib/asset-plan.d.ts.map +1 -1
  32. package/dist/lib/codewith-shared-todos-storage-standard.d.ts.map +1 -1
  33. package/dist/lib/compact-output.d.ts +2 -18
  34. package/dist/lib/compact-output.d.ts.map +1 -1
  35. package/dist/lib/dangerous-operation-guard-standard.d.ts.map +1 -1
  36. package/dist/lib/export.d.ts.map +1 -1
  37. package/dist/lib/global-agent-rules-standard.d.ts.map +1 -1
  38. package/dist/lib/global-source-coverage.d.ts +12 -7
  39. package/dist/lib/global-source-coverage.d.ts.map +1 -1
  40. package/dist/lib/import.d.ts.map +1 -1
  41. package/dist/lib/instruction-graph.d.ts +1 -1
  42. package/dist/lib/instruction-graph.d.ts.map +1 -1
  43. package/dist/lib/instruction-source-policy.d.ts +6 -0
  44. package/dist/lib/instruction-source-policy.d.ts.map +1 -0
  45. package/dist/lib/platform-profiles.d.ts.map +1 -1
  46. package/dist/lib/project-dashboard-standard.d.ts.map +1 -1
  47. package/dist/lib/session-apply.d.ts +24 -0
  48. package/dist/lib/session-apply.d.ts.map +1 -1
  49. package/dist/lib/session-refresh.d.ts +30 -0
  50. package/dist/lib/session-refresh.d.ts.map +1 -0
  51. package/dist/lib/session-render.d.ts +34 -1
  52. package/dist/lib/session-render.d.ts.map +1 -1
  53. package/dist/lib/transforms.d.ts +1 -0
  54. package/dist/lib/transforms.d.ts.map +1 -1
  55. package/dist/mcp/index.js +23 -22
  56. package/dist/mcp/server.d.ts.map +1 -1
  57. package/dist/sdk/index.js +46 -3
  58. package/dist/sdk/v1-client.d.ts +10 -3
  59. package/dist/sdk/v1-client.d.ts.map +1 -1
  60. package/dist/sdk/v1.generated.d.ts +52 -2
  61. package/dist/sdk/v1.generated.d.ts.map +1 -1
  62. package/dist/server/index.d.ts +1 -1
  63. package/dist/server/index.d.ts.map +1 -1
  64. package/dist/server/index.js +215 -15
  65. package/dist/server/openapi.d.ts +240 -3
  66. package/dist/server/openapi.d.ts.map +1 -1
  67. package/dist/server/v1.d.ts.map +1 -1
  68. package/dist/storage/cloud-store.d.ts +2 -15
  69. package/dist/storage/cloud-store.d.ts.map +1 -1
  70. package/dist/storage/index.js +39 -20
  71. package/dist/storage/s3-object-store.d.ts.map +1 -1
  72. package/dist/types/index.d.ts +49 -2
  73. package/dist/types/index.d.ts.map +1 -1
  74. package/package.json +3 -3
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"),
@@ -13326,7 +13447,145 @@ function listConfigs(filter, db) {
13326
13447
  const rows = d.query(`SELECT * FROM configs ${where} ORDER BY category, name`).all(...params);
13327
13448
  return rows.map(rowToConfig);
13328
13449
  }
13450
+ function listConfigsPage(filter = {}, options = {}, db) {
13451
+ const d = db || getDatabase();
13452
+ const conditions = [];
13453
+ const params = [];
13454
+ if (filter.category) {
13455
+ conditions.push("category = ?");
13456
+ params.push(filter.category);
13457
+ }
13458
+ if (filter.agent) {
13459
+ conditions.push("agent = ?");
13460
+ params.push(filter.agent);
13461
+ }
13462
+ if (filter.kind) {
13463
+ conditions.push("kind = ?");
13464
+ params.push(filter.kind);
13465
+ }
13466
+ if (filter.is_template !== undefined) {
13467
+ conditions.push("is_template = ?");
13468
+ params.push(filter.is_template ? 1 : 0);
13469
+ }
13470
+ if (filter.search) {
13471
+ conditions.push("(name LIKE ? OR description LIKE ? OR content LIKE ?)");
13472
+ const q = `%${filter.search}%`;
13473
+ params.push(q, q, q);
13474
+ }
13475
+ if (filter.tags?.length) {
13476
+ conditions.push(`(${filter.tags.map(() => "tags LIKE ?").join(" AND ")})`);
13477
+ for (const tag of filter.tags)
13478
+ params.push(`%"${tag}"%`);
13479
+ }
13480
+ const where = conditions.length ? `WHERE ${conditions.join(" AND ")}` : "";
13481
+ const normalized = normalizeBoundedReadOptions(options);
13482
+ const total = d.query(`SELECT COUNT(*) AS total FROM configs ${where}`).get(...params)?.total ?? 0;
13483
+ const pageParams = [...params, normalized.limit, normalized.cursor];
13484
+ const rows = d.query(`SELECT * FROM configs ${where} ORDER BY id LIMIT ? OFFSET ?`).all(...pageParams);
13485
+ return boundedReadPage(rows.map(rowToConfig), total, normalized);
13486
+ }
13487
+ function listConfigIdentitiesPage(filter = {}, options = {}, db) {
13488
+ const d = db || getDatabase();
13489
+ const conditions = [];
13490
+ const params = [];
13491
+ if (filter.category) {
13492
+ conditions.push("category = ?");
13493
+ params.push(filter.category);
13494
+ }
13495
+ if (filter.agent) {
13496
+ conditions.push("agent = ?");
13497
+ params.push(filter.agent);
13498
+ }
13499
+ if (filter.kind) {
13500
+ conditions.push("kind = ?");
13501
+ params.push(filter.kind);
13502
+ }
13503
+ if (filter.is_template !== undefined) {
13504
+ conditions.push("is_template = ?");
13505
+ params.push(filter.is_template ? 1 : 0);
13506
+ }
13507
+ if (filter.search) {
13508
+ conditions.push("(name LIKE ? OR description LIKE ? OR content LIKE ?)");
13509
+ const q = `%${filter.search}%`;
13510
+ params.push(q, q, q);
13511
+ }
13512
+ if (filter.tags?.length) {
13513
+ conditions.push(`(${filter.tags.map(() => "tags LIKE ?").join(" AND ")})`);
13514
+ for (const tag of filter.tags)
13515
+ params.push(`%"${tag}"%`);
13516
+ }
13517
+ const where = conditions.length ? `WHERE ${conditions.join(" AND ")}` : "";
13518
+ const normalized = normalizeBoundedReadOptions(options);
13519
+ const total = d.query(`SELECT COUNT(*) AS total FROM configs ${where}`).get(...params)?.total ?? 0;
13520
+ const pageParams = [...params, normalized.limit, normalized.cursor];
13521
+ const rows = d.query(`SELECT id, name, slug, kind, category, agent, format, is_template, version, created_at, updated_at, synced_at
13522
+ FROM configs ${where} ORDER BY id LIMIT ? OFFSET ?`).all(...pageParams);
13523
+ return boundedReadPage(rows.map((row) => ({
13524
+ ...row,
13525
+ kind: row.kind,
13526
+ category: row.category,
13527
+ agent: row.agent,
13528
+ format: row.format,
13529
+ is_template: Boolean(row.is_template)
13530
+ })), total, normalized);
13531
+ }
13532
+ function listConfigSummariesPage(filter = {}, options = {}, db) {
13533
+ const d = db || getDatabase();
13534
+ const conditions = [];
13535
+ const params = [];
13536
+ if (filter.category) {
13537
+ conditions.push("category = ?");
13538
+ params.push(filter.category);
13539
+ }
13540
+ if (filter.agent) {
13541
+ conditions.push("agent = ?");
13542
+ params.push(filter.agent);
13543
+ }
13544
+ if (filter.kind) {
13545
+ conditions.push("kind = ?");
13546
+ params.push(filter.kind);
13547
+ }
13548
+ if (filter.is_template !== undefined) {
13549
+ conditions.push("is_template = ?");
13550
+ params.push(filter.is_template ? 1 : 0);
13551
+ }
13552
+ if (filter.search) {
13553
+ conditions.push("(name LIKE ? OR description LIKE ? OR content LIKE ?)");
13554
+ const q = `%${filter.search}%`;
13555
+ params.push(q, q, q);
13556
+ }
13557
+ if (filter.tags && filter.tags.length > 0) {
13558
+ conditions.push(`(${filter.tags.map(() => "tags LIKE ?").join(" AND ")})`);
13559
+ for (const tag of filter.tags)
13560
+ params.push(`%"${tag}"%`);
13561
+ }
13562
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
13563
+ const normalized = normalizeBoundedReadOptions(options);
13564
+ const total = d.query(`SELECT COUNT(*) AS total FROM configs ${where}`).get(...params)?.total ?? 0;
13565
+ const pageParams = [...params, normalized.limit, normalized.cursor];
13566
+ const rows = d.query(`SELECT id, name, slug, kind, category, agent, target_path, format,
13567
+ CASE WHEN json_valid(outputs) AND json_type(outputs) = 'array' THEN json_array_length(outputs) ELSE 0 END AS output_count, description, tags,
13568
+ is_template, version, updated_at
13569
+ FROM configs ${where} ORDER BY category, name, id LIMIT ? OFFSET ?`).all(...pageParams);
13570
+ return boundedReadPage(rows.map((row) => ({
13571
+ id: row.id,
13572
+ slug: row.slug,
13573
+ name: row.name,
13574
+ category: row.category,
13575
+ agent: row.agent,
13576
+ kind: row.kind,
13577
+ format: row.format,
13578
+ target_path: row.target_path,
13579
+ output_count: Number(row.output_count ?? 0),
13580
+ version: row.version,
13581
+ is_template: Boolean(row.is_template),
13582
+ updated_at: row.updated_at,
13583
+ description: row.description,
13584
+ tags: JSON.parse(row.tags || "[]")
13585
+ })), total, normalized);
13586
+ }
13329
13587
  function updateConfig(idOrSlug, input, db) {
13588
+ validateExpectedConfigVersion(input.expected_version);
13330
13589
  const d = db || getDatabase();
13331
13590
  const existing = getConfig(idOrSlug, d);
13332
13591
  const ts = now();
@@ -13382,7 +13641,15 @@ function updateConfig(idOrSlug, input, db) {
13382
13641
  }
13383
13642
  return d.transaction(() => {
13384
13643
  params.push(existing.id);
13385
- 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
+ }
13386
13653
  const updated = getConfigById(existing.id, d);
13387
13654
  createSnapshot(updated.id, updated.content, updated.version, d);
13388
13655
  return updated;
@@ -13407,6 +13674,7 @@ var init_configs = __esm(() => {
13407
13674
  init_types();
13408
13675
  init_database();
13409
13676
  init_snapshots();
13677
+ init_bounded_read();
13410
13678
  });
13411
13679
 
13412
13680
  // src/lib/template.ts
@@ -13847,7 +14115,10 @@ __export(exports_local, {
13847
14115
  listSnapshots: () => listSnapshots,
13848
14116
  listProfilesPage: () => listProfilesPage,
13849
14117
  listMachines: () => listMachines,
14118
+ listConfigsPage: () => listConfigsPage,
13850
14119
  listConfigs: () => listConfigs,
14120
+ listConfigSummariesPage: () => listConfigSummariesPage,
14121
+ listConfigIdentitiesPage: () => listConfigIdentitiesPage,
13851
14122
  insertFeedback: () => insertFeedback,
13852
14123
  getSnapshotByVersion: () => getSnapshotByVersion,
13853
14124
  getSnapshot: () => getSnapshot,
@@ -13902,6 +14173,19 @@ function parseBoundedOrLegacyPage(value, legacyItems, options, label) {
13902
14173
  const page = boundedReadPage(legacyItems.slice(normalized.cursor, normalized.cursor + normalized.limit), legacyItems.length, normalized);
13903
14174
  return { ...page, source_bounded: false };
13904
14175
  }
14176
+ function projectBoundedPage(page, project) {
14177
+ return {
14178
+ items: page.items.map(project),
14179
+ total: page.total,
14180
+ limit: page.limit,
14181
+ cursor: page.cursor,
14182
+ next_cursor: page.next_cursor,
14183
+ has_more: page.has_more,
14184
+ complete: page.complete,
14185
+ truncated: page.truncated,
14186
+ source_bounded: page.source_bounded
14187
+ };
14188
+ }
13905
14189
  async function aggregateBoundedCollection(label, readPage, identity, options = {}) {
13906
14190
  let lastError = null;
13907
14191
  for (let attempt = 0;attempt < COLLECTION_READ_ATTEMPTS; attempt += 1) {
@@ -13997,6 +14281,15 @@ class LocalConfigStore {
13997
14281
  async listConfigs(filter) {
13998
14282
  return (await localStoreModule()).listConfigs(filter, this.db);
13999
14283
  }
14284
+ async listConfigsPage(filter = {}, options = {}) {
14285
+ return (await localStoreModule()).listConfigsPage(filter, options, this.db);
14286
+ }
14287
+ async listConfigIdentitiesPage(filter = {}, options = {}) {
14288
+ return (await localStoreModule()).listConfigIdentitiesPage(filter, options, this.db);
14289
+ }
14290
+ async listConfigSummariesPage(filter = {}, options = {}) {
14291
+ return (await localStoreModule()).listConfigSummariesPage(filter, options, this.db);
14292
+ }
14000
14293
  async getConfig(idOrSlug) {
14001
14294
  return (await localStoreModule()).getConfig(idOrSlug, this.db);
14002
14295
  }
@@ -14100,6 +14393,43 @@ class LocalConfigStore {
14100
14393
  (await localStoreModule()).resetLocalDatabase();
14101
14394
  }
14102
14395
  }
14396
+ function toConfigIdentity(value) {
14397
+ const record = value && typeof value === "object" ? value : {};
14398
+ return {
14399
+ id: String(record.id ?? ""),
14400
+ name: String(record.name ?? ""),
14401
+ slug: String(record.slug ?? ""),
14402
+ kind: String(record.kind ?? ""),
14403
+ category: String(record.category ?? ""),
14404
+ agent: String(record.agent ?? ""),
14405
+ format: String(record.format ?? ""),
14406
+ is_template: Boolean(record.is_template),
14407
+ version: Number(record.version ?? 0),
14408
+ created_at: String(record.created_at ?? ""),
14409
+ updated_at: String(record.updated_at ?? ""),
14410
+ synced_at: record.synced_at == null ? null : String(record.synced_at)
14411
+ };
14412
+ }
14413
+ function toConfigSummary(value) {
14414
+ const record = value && typeof value === "object" ? value : {};
14415
+ const outputs = Array.isArray(record.outputs) ? record.outputs : [];
14416
+ return {
14417
+ id: String(record.id ?? ""),
14418
+ slug: String(record.slug ?? ""),
14419
+ name: String(record.name ?? ""),
14420
+ category: String(record.category ?? ""),
14421
+ agent: String(record.agent ?? ""),
14422
+ kind: String(record.kind ?? ""),
14423
+ format: String(record.format ?? ""),
14424
+ target_path: record.target_path == null ? null : String(record.target_path),
14425
+ output_count: Number(record.output_count ?? outputs.length),
14426
+ version: Number(record.version ?? 0),
14427
+ is_template: Boolean(record.is_template),
14428
+ ...record.updated_at !== undefined ? { updated_at: String(record.updated_at) } : {},
14429
+ ...record.description !== undefined ? { description: record.description == null ? null : String(record.description) } : {},
14430
+ ...Array.isArray(record.tags) ? { tags: record.tags.map(String) } : {}
14431
+ };
14432
+ }
14103
14433
 
14104
14434
  class CloudConfigStore {
14105
14435
  mode = "api";
@@ -14121,7 +14451,7 @@ class CloudConfigStore {
14121
14451
  throw err;
14122
14452
  }
14123
14453
  }
14124
- async listConfigsPageRemote(filter, options) {
14454
+ async listConfigsPage(filter = {}, options = {}) {
14125
14455
  const normalized = normalizeBoundedReadOptions(options);
14126
14456
  const params = new URLSearchParams;
14127
14457
  if (filter.category)
@@ -14132,13 +14462,67 @@ class CloudConfigStore {
14132
14462
  params.set("kind", filter.kind);
14133
14463
  if (filter.search)
14134
14464
  params.set("search", filter.search);
14465
+ for (const tag of filter.tags ?? [])
14466
+ params.append("tag", tag);
14135
14467
  params.set("limit", String(normalized.limit));
14136
14468
  params.set("cursor", String(normalized.cursor));
14137
14469
  const { data } = await this.request("GET", `/configs?${params.toString()}`);
14138
14470
  return parseBoundedOrLegacyPage(data, data?.configs, normalized, "config list");
14139
14471
  }
14472
+ async listConfigIdentitiesPage(filter = {}, options = {}) {
14473
+ const normalized = normalizeBoundedReadOptions(options);
14474
+ const params = new URLSearchParams;
14475
+ if (filter.category)
14476
+ params.set("category", filter.category);
14477
+ if (filter.agent)
14478
+ params.set("agent", filter.agent);
14479
+ if (filter.kind)
14480
+ params.set("kind", filter.kind);
14481
+ if (filter.search)
14482
+ params.set("search", filter.search);
14483
+ for (const tag of filter.tags ?? [])
14484
+ params.append("tag", tag);
14485
+ params.set("view", "identity");
14486
+ params.set("limit", String(normalized.limit));
14487
+ params.set("cursor", String(normalized.cursor));
14488
+ const { data } = await this.request("GET", `/configs?${params.toString()}`);
14489
+ const page = parseBoundedOrLegacyPage(data, data?.configs, normalized, "config identity list");
14490
+ if (page.items.some((item) => {
14491
+ const record = item && typeof item === "object" ? item : {};
14492
+ return ["content", "target_path", "outputs", "description", "tags"].some((field) => Object.prototype.hasOwnProperty.call(record, field));
14493
+ })) {
14494
+ throw new Error("Instructions /v1 config identity projection is unavailable; deploy the identity endpoint before using compact lists");
14495
+ }
14496
+ return projectBoundedPage(page, toConfigIdentity);
14497
+ }
14498
+ async listConfigSummariesPage(filter = {}, options = {}) {
14499
+ const normalized = normalizeBoundedReadOptions(options);
14500
+ const params = new URLSearchParams;
14501
+ if (filter.category)
14502
+ params.set("category", filter.category);
14503
+ if (filter.agent)
14504
+ params.set("agent", filter.agent);
14505
+ if (filter.kind)
14506
+ params.set("kind", filter.kind);
14507
+ if (filter.search)
14508
+ params.set("search", filter.search);
14509
+ for (const tag of filter.tags ?? [])
14510
+ params.append("tag", tag);
14511
+ params.set("view", "summary");
14512
+ params.set("limit", String(normalized.limit));
14513
+ params.set("cursor", String(normalized.cursor));
14514
+ const { data } = await this.request("GET", `/configs?${params.toString()}`);
14515
+ const page = parseBoundedOrLegacyPage(data, data?.configs, normalized, "config summary list");
14516
+ if (page.items.some((item) => {
14517
+ const record = item && typeof item === "object" ? item : {};
14518
+ return Object.prototype.hasOwnProperty.call(record, "content") || Object.prototype.hasOwnProperty.call(record, "outputs");
14519
+ })) {
14520
+ throw new Error("Instructions /v1 config summary projection is unavailable; deploy the summary endpoint before using summary lists");
14521
+ }
14522
+ return projectBoundedPage(page, toConfigSummary);
14523
+ }
14140
14524
  async listConfigs(filter = {}) {
14141
- const configs = await aggregateBoundedCollection("config list", (cursor) => this.listConfigsPageRemote(filter, { limit: 100, cursor }), (config) => config.id, { requireAscendingIdentity: true });
14525
+ const configs = await aggregateBoundedCollection("config list", (cursor) => this.listConfigsPage(filter, { limit: 100, cursor }), (config) => config.id, { requireAscendingIdentity: true });
14142
14526
  let filtered = configs;
14143
14527
  if (filter.tags && filter.tags.length > 0) {
14144
14528
  filtered = filtered.filter((config) => filter.tags.every((tag) => config.tags.includes(tag)));
@@ -14164,7 +14548,9 @@ class CloudConfigStore {
14164
14548
  return data.config;
14165
14549
  }
14166
14550
  async updateConfig(idOrSlug, input) {
14167
- 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);
14168
14554
  return data.config;
14169
14555
  }
14170
14556
  async deleteConfig(idOrSlug) {
@@ -14204,7 +14590,7 @@ class CloudConfigStore {
14204
14590
  return data?.pruned ?? 0;
14205
14591
  }
14206
14592
  async listProfiles() {
14207
- return aggregateBoundedCollection("profile list", (cursor) => this.listProfilesPage({ limit: 100, cursor }), (profile) => profile.id, { requireAscendingIdentity: true });
14593
+ return aggregateBoundedCollection("profile list", (cursor) => this.listProfilesPage({ limit: 100, cursor }), (profile) => profile.id);
14208
14594
  }
14209
14595
  async listProfilesPage(options = {}) {
14210
14596
  const normalized = normalizeBoundedReadOptions(options);
@@ -14241,7 +14627,7 @@ class CloudConfigStore {
14241
14627
  throw new ProfileNotFoundError(idOrSlug);
14242
14628
  return parseBoundedOrLegacyPage(data.configs, data.profile.configs, normalized, "profile membership");
14243
14629
  }
14244
- async getProfileConfigBindings(idOrSlug) {
14630
+ async getProfileConfigBindings(idOrSlug, options = {}) {
14245
14631
  let routeMissing = false;
14246
14632
  const bindings = await aggregateBoundedCollection("profile config bindings", async (cursor) => {
14247
14633
  const normalized = normalizeBoundedReadOptions({ limit: 100, cursor });
@@ -14254,6 +14640,8 @@ class CloudConfigStore {
14254
14640
  }, (binding) => `${binding.profile_id}\x00${binding.config_id}`);
14255
14641
  if (!routeMissing)
14256
14642
  return bindings;
14643
+ if (options.requireExplicit)
14644
+ throw new Error("HOSTED_BINDINGS_REQUIRED: profile config binding route is unavailable; refusing legacy activation fallback.");
14257
14645
  const profile = await this.getProfile(idOrSlug);
14258
14646
  const configs = await this.getProfileConfigs(idOrSlug);
14259
14647
  return configs.map((config, sort_order) => ({
@@ -14318,7 +14706,7 @@ class CloudConfigStore {
14318
14706
  async removeConfigFromProfile(profileIdOrSlug, configId) {
14319
14707
  await this.request("DELETE", `/profiles/${encodeURIComponent(profileIdOrSlug)}/configs/${encodeURIComponent(configId)}`, undefined, { allow404: true });
14320
14708
  }
14321
- async getProfileAssetBindings(profileIdOrSlug) {
14709
+ async getProfileAssetBindings(profileIdOrSlug, options = {}) {
14322
14710
  let routeMissing = false;
14323
14711
  const assets = await aggregateBoundedCollection("profile asset bindings", async (cursor) => {
14324
14712
  const normalized = normalizeBoundedReadOptions({ limit: 100, cursor });
@@ -14331,6 +14719,8 @@ class CloudConfigStore {
14331
14719
  }, (asset) => `${asset.profile_id}\x00${asset.binding.assetKey}`);
14332
14720
  if (!routeMissing)
14333
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.");
14334
14724
  await this.getProfile(profileIdOrSlug);
14335
14725
  return [];
14336
14726
  }
@@ -16080,7 +16470,6 @@ import {
16080
16470
  statSync as statSync5
16081
16471
  } from "fs";
16082
16472
  import { dirname as dirname10, isAbsolute as isAbsolute7, join as join17, parse as parse5, relative as relative6, resolve as resolve11 } from "path";
16083
-
16084
16473
  class SessionApplyError extends Error {
16085
16474
  constructor(message) {
16086
16475
  super(message);
@@ -16102,14 +16491,20 @@ function applySessionRenderUnlocked(plan, options, coordination) {
16102
16491
  const targetHome = assertSafeTargetHome(plan.targetHome);
16103
16492
  assertClaudeAuthorityStillClear(plan, targetHome, options.ownedClaudeAuthorities);
16104
16493
  const payloadFiles = [...plan.files, ...plan.assetFiles ?? []];
16105
- const files = [...payloadFiles, plan.manifestFile];
16106
16494
  const manifestPath = resolvePlannedFilePath(plan, plan.manifestFile, targetHome);
16495
+ assertManifestPrecondition(manifestPath, targetHome, options.expectedManifestSha256);
16107
16496
  const previousManifest = readPreviousManifest(manifestPath);
16108
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];
16109
16504
  const currentRelativePaths = new Set(files.map((file) => file.relativePath));
16110
16505
  const drift = checkSessionRenderDrift(targetHome, manifestPath);
16111
16506
  const results = [
16112
- ...files.map((file) => planFileResult(plan, file, targetHome, previousHashes, previousManifest, options)),
16507
+ ...files.map((file) => planFileResult(plan, file, targetHome, previousHashes, previousManifest, options, adoptedHashes, reconciledHashes)),
16113
16508
  ...planStaleFileResults(plan, targetHome, previousManifest, currentRelativePaths, options)
16114
16509
  ];
16115
16510
  assertNotSilentManagedWipeout(plan, results);
@@ -16132,7 +16527,9 @@ function applySessionRenderUnlocked(plan, options, coordination) {
16132
16527
  skippedSources: plan.manifest.skippedSources,
16133
16528
  files: results,
16134
16529
  conflicts,
16135
- drift
16530
+ drift,
16531
+ adoptions,
16532
+ reconciliations
16136
16533
  };
16137
16534
  }
16138
16535
  let snapshotPath = null;
@@ -16145,10 +16542,12 @@ function applySessionRenderUnlocked(plan, options, coordination) {
16145
16542
  if (!options.dryRun) {
16146
16543
  const allowPortableFallback = coordination === null;
16147
16544
  const forcePortableFileOps = options.test_hooks?.force_portable_file_ops ?? false;
16545
+ assertManifestPrecondition(manifestPath, targetHome, options.expectedManifestSha256);
16148
16546
  ensureSessionTargetHome(targetHome);
16149
- rollback = writeSessionSnapshot(plan, targetHome, manifestPath, results, previousManifest, coordination, allowPortableFallback, forcePortableFileOps);
16547
+ rollback = writeSessionSnapshot(plan, targetHome, manifestPath, results, previousManifest, coordination, allowPortableFallback, forcePortableFileOps, adoptions, reconciliations);
16150
16548
  snapshotPath = rollback.snapshotPath;
16151
16549
  options.test_hooks?.before_apply_writes?.({ plan, results });
16550
+ assertManifestPrecondition(manifestPath, targetHome, options.expectedManifestSha256);
16152
16551
  const resultsByPath = new Map(results.map((result) => [result.path, result]));
16153
16552
  for (const file of payloadFiles) {
16154
16553
  applyPlannedFile(plan, file, targetHome, resultsByPath, coordination, allowPortableFallback, forcePortableFileOps);
@@ -16168,7 +16567,7 @@ function applySessionRenderUnlocked(plan, options, coordination) {
16168
16567
  });
16169
16568
  coordination?.assert_held();
16170
16569
  }
16171
- applyPlannedFile(plan, plan.manifestFile, targetHome, resultsByPath, coordination, allowPortableFallback, forcePortableFileOps);
16570
+ applyPlannedFile(plan, manifestFile, targetHome, resultsByPath, coordination, allowPortableFallback, forcePortableFileOps);
16172
16571
  }
16173
16572
  return {
16174
16573
  dryRun: options.dryRun ?? false,
@@ -16182,9 +16581,171 @@ function applySessionRenderUnlocked(plan, options, coordination) {
16182
16581
  skippedSources: plan.manifest.skippedSources,
16183
16582
  files: results,
16184
16583
  conflicts,
16185
- drift
16584
+ drift,
16585
+ adoptions,
16586
+ reconciliations
16186
16587
  };
16187
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()] } : {}
16744
+ };
16745
+ const content = `${JSON.stringify(manifest, null, 2)}
16746
+ `;
16747
+ return { ...plan.manifestFile, content, sha256: sha25610(content) };
16748
+ }
16188
16749
  function assertCursorAuthorityUnchanged(plan) {
16189
16750
  if (plan.tool !== "cursor" || plan.targetKind === "blocked")
16190
16751
  return;
@@ -16656,12 +17217,29 @@ function resolveSnapshotFilePath(relativePath, recordedPath, targetHome) {
16656
17217
  }
16657
17218
  return path;
16658
17219
  }
16659
- function planFileResult(plan, file, targetHome, previousHashes, previousManifest, options) {
17220
+ function planFileResult(plan, file, targetHome, previousHashes, previousManifest, options, adoptedHashes, reconciledHashes) {
16660
17221
  const target = resolvePlannedFilePath(plan, file, targetHome);
16661
17222
  const previousContent = existsSync15(target) ? readFileSync14(target, "utf-8") : null;
16662
17223
  const previousSha256 = previousContent === null ? null : sha25610(previousContent);
16663
17224
  const previouslyManaged = isPreviouslyManaged(file, previousSha256, previousHashes, previousManifest);
16664
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
+ }
16665
17243
  if (previousContent !== null && !options.force && !previouslyManaged) {
16666
17244
  return {
16667
17245
  path: target,
@@ -16881,9 +17459,13 @@ function requiredPreviousHash(result) {
16881
17459
  }
16882
17460
  return result.previousSha256;
16883
17461
  }
16884
- function writeSessionSnapshot(plan, targetHome, manifestPath, results, previousManifest, coordination, allowPortableFallback, forcePortableFileOps) {
16885
- 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);
16886
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
+ }
16887
17469
  return {
16888
17470
  path: result.path,
16889
17471
  relativePath: result.relativePath,
@@ -16924,13 +17506,19 @@ function writeSessionSnapshot(plan, targetHome, manifestPath, results, previousM
16924
17506
  manifestPath,
16925
17507
  previousManifest,
16926
17508
  files: existingFiles,
16927
- afterFiles
17509
+ afterFiles,
17510
+ ...adoptions.length > 0 ? { adoptions } : {},
17511
+ ...reconciliations.length > 0 ? { reconciliations } : {}
16928
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
+ }
16929
17518
  coordination?.assert_held();
16930
17519
  writeProjectContextCoordinatedFile({
16931
17520
  path: snapshotPath,
16932
- content: `${JSON.stringify(snapshot, null, 2)}
16933
- `,
17521
+ content: snapshotContent,
16934
17522
  workspace_root: sessionRenderSnapshotWorkspaceRoot(targetHome),
16935
17523
  default_mode: 384,
16936
17524
  expected_hash: null,
@@ -16987,6 +17575,211 @@ function assertNoSymlinkAncestors3(path) {
16987
17575
  function sha25610(content) {
16988
17576
  return createHash10("sha256").update(content).digest("hex");
16989
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
+ }
16990
17783
 
16991
17784
  // src/index.ts
16992
17785
  init_project_context();
@@ -16994,9 +17787,11 @@ init_transforms();
16994
17787
  init_machine();
16995
17788
 
16996
17789
  // src/lib/platform-profiles.ts
17790
+ init_types();
16997
17791
  init_config_store();
16998
17792
 
16999
17793
  // src/lib/project-dashboard-standard.ts
17794
+ init_types();
17000
17795
  init_config_store();
17001
17796
  var PROJECT_DASHBOARD_STANDARD_SLUG = "agent-managed-project-dashboard-standard";
17002
17797
  var PROJECT_DASHBOARD_PROFILE_VARIABLES = {
@@ -17089,11 +17884,15 @@ async function ensureProjectDashboardStandardConfig(store = resolveConfigStore()
17089
17884
  };
17090
17885
  try {
17091
17886
  const existing = await store.getConfig(PROJECT_DASHBOARD_STANDARD_SLUG);
17887
+ if (isRetiredInstructionSource(existing))
17888
+ return existing;
17092
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) {
17093
17890
  return await store.updateConfig(existing.id, input);
17094
17891
  }
17095
17892
  return existing;
17096
- } catch {
17893
+ } catch (error) {
17894
+ if (!(error instanceof ConfigNotFoundError))
17895
+ throw error;
17097
17896
  return await store.createConfig(input);
17098
17897
  }
17099
17898
  }
@@ -17106,10 +17905,9 @@ function profileHasSelectors2(profile) {
17106
17905
  var PLATFORM_PROFILE_PRESETS = [
17107
17906
  {
17108
17907
  name: "linux-arm64",
17109
- description: "Default Linux arm64 profile for linux-node-a/linux-node-b-style machines",
17110
- 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"] },
17111
17910
  variables: {
17112
- WORKSPACE_ROOT: "{{HOME_DIR}}/workspace",
17113
17911
  BUN_BIN_DIR: "{{HOME_DIR}}/.bun/bin",
17114
17912
  BUN_PATH: "{{BUN_BIN_DIR}}/bun",
17115
17913
  PATH_PREFIX: "{{BUN_BIN_DIR}}",
@@ -17118,10 +17916,9 @@ var PLATFORM_PROFILE_PRESETS = [
17118
17916
  },
17119
17917
  {
17120
17918
  name: "macos-arm64",
17121
- description: "Default macOS arm64 profile for macos-node-a/macos-node-b-style machines",
17122
- 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"] },
17123
17921
  variables: {
17124
- WORKSPACE_ROOT: "{{HOME_DIR}}/Workspace",
17125
17922
  BUN_BIN_DIR: "{{HOME_DIR}}/.bun/bin",
17126
17923
  BUN_PATH: "/opt/homebrew/bin/bun",
17127
17924
  PATH_PREFIX: "/opt/homebrew/bin:{{BUN_BIN_DIR}}",
@@ -17130,12 +17927,21 @@ var PLATFORM_PROFILE_PRESETS = [
17130
17927
  }
17131
17928
  ];
17132
17929
  async function ensurePlatformProfiles(store = resolveConfigStore()) {
17133
- const configs = await store.listConfigs();
17134
17930
  const ensured = [];
17135
- for (const preset of PLATFORM_PROFILE_PRESETS) {
17136
- let profile;
17931
+ const existingProfiles = await Promise.all(PLATFORM_PROFILE_PRESETS.map(async (preset) => {
17137
17932
  try {
17138
- 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;
17139
17945
  const selectors = mergeProfileSelectors(preset.selectors, profile.selectors);
17140
17946
  const variables = mergeProfileVariables(preset.variables, profile.variables);
17141
17947
  if (JSON.stringify(selectors) !== JSON.stringify(profile.selectors) || JSON.stringify(variables) !== JSON.stringify(profile.variables)) {
@@ -17145,12 +17951,9 @@ async function ensurePlatformProfiles(store = resolveConfigStore()) {
17145
17951
  variables
17146
17952
  });
17147
17953
  }
17148
- } catch {
17954
+ } else {
17149
17955
  profile = await store.createProfile(preset);
17150
17956
  }
17151
- for (const config of configs) {
17152
- await store.addConfigToProfile(profile.id, config.id);
17153
- }
17154
17957
  ensured.push(profile);
17155
17958
  }
17156
17959
  return ensured;
@@ -17184,6 +17987,7 @@ function mergeUnique(preset, existing) {
17184
17987
  init_global_agent_rules_standard();
17185
17988
 
17186
17989
  // src/lib/dangerous-operation-guard-standard.ts
17990
+ init_types();
17187
17991
  init_config_store();
17188
17992
  var DANGEROUS_OPERATION_GUARD_STANDARD_SLUG = "dangerous-operation-guard-standard";
17189
17993
  var DANGEROUS_OPERATION_GUARD_STANDARD_CONTENT = `# Dangerous Operation Guard Standard
@@ -17295,11 +18099,15 @@ async function ensureDangerousOperationGuardStandardConfig(store = resolveConfig
17295
18099
  };
17296
18100
  try {
17297
18101
  const existing = await store.getConfig(DANGEROUS_OPERATION_GUARD_STANDARD_SLUG);
18102
+ if (isRetiredInstructionSource(existing))
18103
+ return existing;
17298
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)) {
17299
18105
  return await store.updateConfig(existing.id, input);
17300
18106
  }
17301
18107
  return existing;
17302
- } catch {
18108
+ } catch (error) {
18109
+ if (!(error instanceof ConfigNotFoundError))
18110
+ throw error;
17303
18111
  return await store.createConfig(input);
17304
18112
  }
17305
18113
  }
@@ -17309,8 +18117,8 @@ init_codewith_shared_todos_storage_standard();
17309
18117
 
17310
18118
  // src/lib/sync.ts
17311
18119
  init_config_store();
17312
- import { existsSync as existsSync17, readdirSync as readdirSync5, readFileSync as readFileSync16 } from "fs";
17313
- 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";
17314
18122
  init_config_agents();
17315
18123
  init_redact();
17316
18124
  init_machine();
@@ -17318,8 +18126,8 @@ init_transforms();
17318
18126
 
17319
18127
  // src/lib/sync-dir.ts
17320
18128
  init_config_store();
17321
- import { existsSync as existsSync16, readdirSync as readdirSync4, readFileSync as readFileSync15, statSync as statSync6 } from "fs";
17322
- 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";
17323
18131
  init_redact();
17324
18132
  var SKIP = [".db", ".db-shm", ".db-wal", ".log", ".lock", ".DS_Store", "node_modules", ".git"];
17325
18133
  function shouldSkip(p) {
@@ -17330,7 +18138,7 @@ async function syncFromDir(dir, opts = {}) {
17330
18138
  const absDir = expandPath(dir);
17331
18139
  if (!existsSync16(absDir))
17332
18140
  return { added: 0, updated: 0, unchanged: 0, skipped: [`Not found: ${absDir}`] };
17333
- 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());
17334
18142
  const result = { added: 0, updated: 0, unchanged: 0, skipped: [] };
17335
18143
  const allConfigs = await store.listConfigs();
17336
18144
  for (const file of files) {
@@ -17339,7 +18147,7 @@ async function syncFromDir(dir, opts = {}) {
17339
18147
  continue;
17340
18148
  }
17341
18149
  try {
17342
- const content = readFileSync15(file, "utf-8");
18150
+ const content = readFileSync16(file, "utf-8");
17343
18151
  if (content.length > 500000) {
17344
18152
  result.skipped.push(file + " (too large)");
17345
18153
  continue;
@@ -17389,7 +18197,7 @@ async function syncToDir(dir, opts = {}) {
17389
18197
  }
17390
18198
  function walkDir(dir, files = []) {
17391
18199
  for (const entry of readdirSync4(dir, { withFileTypes: true })) {
17392
- const full = join18(dir, entry.name);
18200
+ const full = join19(dir, entry.name);
17393
18201
  if (shouldSkip(full))
17394
18202
  continue;
17395
18203
  if (entry.isDirectory())
@@ -17411,7 +18219,7 @@ var CLAUDE_PROMPT_OUTPUTS = [
17411
18219
  { agent: "qwen", target_path: "~/.qwen/QWEN.md", transform: "codex-flat" }
17412
18220
  ];
17413
18221
  function claudeRuleOutputs(fileName) {
17414
- const stem = basename6(fileName, extname3(fileName));
18222
+ const stem = basename7(fileName, extname3(fileName));
17415
18223
  return [
17416
18224
  { agent: "cursor", target_path: `~/.cursor/rules/${stem}.mdc`, transform: "cursor-mdc" }
17417
18225
  ];
@@ -17457,7 +18265,7 @@ function hasClaudeRuleSourceForCursorTarget(targetPath) {
17457
18265
  const absolutePrefix = expandPath("~/.cursor/rules");
17458
18266
  if (!absoluteTargetPath.startsWith(`${absolutePrefix}/`) || !absoluteTargetPath.endsWith(".mdc"))
17459
18267
  return false;
17460
- const stem = basename6(absoluteTargetPath, ".mdc");
18268
+ const stem = basename7(absoluteTargetPath, ".mdc");
17461
18269
  return existsSync17(expandPath(`~/.claude/rules/${stem}.md`)) || existsSync17(expandPath(`~/.claude/rules/${stem}.mdc`));
17462
18270
  }
17463
18271
  function isKnownGeneratedTargetPath(targetPath) {
@@ -17523,11 +18331,11 @@ async function syncProject(opts) {
17523
18331
  const allConfigs = await store.listConfigs();
17524
18332
  const machine = detectMachineContext();
17525
18333
  for (const pf of PROJECT_CONFIG_FILES) {
17526
- const abs = join19(absDir, pf.file);
18334
+ const abs = join20(absDir, pf.file);
17527
18335
  if (!existsSync17(abs))
17528
18336
  continue;
17529
18337
  try {
17530
- const rawContent = readFileSync16(abs, "utf-8");
18338
+ const rawContent = readFileSync17(abs, "utf-8");
17531
18339
  if (rawContent.length > 500000) {
17532
18340
  result.skipped.push(pf.file);
17533
18341
  continue;
@@ -17556,20 +18364,20 @@ async function syncProject(opts) {
17556
18364
  }
17557
18365
  }
17558
18366
  for (const ruleDir of [
17559
- { dir: join19(absDir, ".claude", "rules"), agent: "claude", namePrefix: "rules" },
17560
- { dir: join19(absDir, ".agents", "rules"), agent: "antigravity", namePrefix: "antigravity-rules" },
17561
- { dir: join19(absDir, ".cursor", "rules"), agent: "cursor", namePrefix: "cursor-rules" },
17562
- { dir: join19(absDir, ".github", "instructions"), agent: "copilot", namePrefix: "copilot-instructions" },
17563
- { dir: join19(absDir, ".devin", "rules"), agent: "devin", namePrefix: "devin-rules" },
17564
- { dir: join19(absDir, ".windsurf", "rules"), agent: "windsurf-legacy", namePrefix: "windsurf-rules" },
17565
- { 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" }
17566
18374
  ]) {
17567
18375
  if (!existsSync17(ruleDir.dir))
17568
18376
  continue;
17569
18377
  const mdFiles = readdirSync5(ruleDir.dir).filter((f) => f.endsWith(".md") || f.endsWith(".mdc"));
17570
18378
  for (const f of mdFiles) {
17571
- const abs = join19(ruleDir.dir, f);
17572
- const raw = readFileSync16(abs, "utf-8");
18379
+ const abs = join20(ruleDir.dir, f);
18380
+ const raw = readFileSync17(abs, "utf-8");
17573
18381
  const redacted = redactContent(raw, "markdown");
17574
18382
  const machineAware = templateizeMachineContent(redacted.content, machine);
17575
18383
  const content = machineAware.content;
@@ -17615,13 +18423,13 @@ async function syncKnown(opts = {}) {
17615
18423
  const extensions = known.rulesExtensions ?? [".md", ".mdc"];
17616
18424
  const ruleFiles = readdirSync5(absDir).filter((f) => extensions.some((ext) => f.endsWith(ext)));
17617
18425
  for (const f of ruleFiles) {
17618
- const abs2 = join19(absDir, f);
18426
+ const abs2 = join20(absDir, f);
17619
18427
  const targetPath = abs2.replace(home, "~");
17620
18428
  if (existingOutputOwners.has(normalizeTargetPath(targetPath)) || isKnownGeneratedTargetPath(targetPath)) {
17621
18429
  result.skipped.push(`${targetPath} (generated output)`);
17622
18430
  continue;
17623
18431
  }
17624
- const raw = readFileSync16(abs2, "utf-8");
18432
+ const raw = readFileSync17(abs2, "utf-8");
17625
18433
  const redacted = redactContent(raw, "markdown");
17626
18434
  const machineAware = templateizeMachineContent(redacted.content, machine);
17627
18435
  const content = machineAware.content;
@@ -17654,7 +18462,7 @@ async function syncKnown(opts = {}) {
17654
18462
  continue;
17655
18463
  }
17656
18464
  try {
17657
- const rawContent = normalizeKnownConfigSource(known, readFileSync16(abs, "utf-8"));
18465
+ const rawContent = normalizeKnownConfigSource(known, readFileSync17(abs, "utf-8"));
17658
18466
  if (rawContent.length > 500000) {
17659
18467
  result.skipped.push(known.path + " (too large)");
17660
18468
  continue;
@@ -17759,7 +18567,7 @@ function buildDiff(expectedContent, targetPath, storedFormat, showSecrets) {
17759
18567
  const path = expandPath(targetPath);
17760
18568
  if (!existsSync17(path))
17761
18569
  return `(file not found on disk: ${path})`;
17762
- const diskContent = readFileSync16(path, "utf-8");
18570
+ const diskContent = readFileSync17(path, "utf-8");
17763
18571
  if (diskContent === expectedContent)
17764
18572
  return "(no diff \u2014 identical)";
17765
18573
  const format = redactFormatForTarget(targetPath, storedFormat);
@@ -17919,9 +18727,9 @@ function detectFormat(filePath) {
17919
18727
  // src/lib/export.ts
17920
18728
  init_types();
17921
18729
  init_config_store();
17922
- import { createHash as createHash11 } from "crypto";
18730
+ import { createHash as createHash12 } from "crypto";
17923
18731
  import { existsSync as existsSync18, mkdirSync as mkdirSync8, mkdtempSync, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "fs";
17924
- 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";
17925
18733
  import { tmpdir } from "os";
17926
18734
  var ARCHIVE_EXCLUSIONS = [
17927
18735
  {
@@ -17944,7 +18752,7 @@ function compareText(left, right) {
17944
18752
  return left < right ? -1 : left > right ? 1 : 0;
17945
18753
  }
17946
18754
  function sha25611(value) {
17947
- return createHash11("sha256").update(value).digest("hex");
18755
+ return createHash12("sha256").update(value).digest("hex");
17948
18756
  }
17949
18757
  function canonicalize(value) {
17950
18758
  if (Array.isArray(value))
@@ -17972,7 +18780,12 @@ function logicalAssetLocator(locator, idToSlug) {
17972
18780
  }
17973
18781
  function logicalCollections(domain, options) {
17974
18782
  const configs = [...domain.configs].sort((left, right) => compareText(left.slug, right.slug));
17975
- const snapshots = [...domain.config_snapshots].sort((left, right) => compareText(left.config_slug, right.config_slug) || left.version - right.version || compareText(left.id, right.id));
18783
+ const snapshots = domain.config_snapshots.map((snapshot) => ({
18784
+ config_slug: snapshot.config_slug,
18785
+ version: snapshot.version,
18786
+ content: snapshot.content,
18787
+ ...options.includeOperationalTimestamps ? { created_at: snapshot.created_at } : {}
18788
+ })).sort((left, right) => compareText(left.config_slug, right.config_slug) || left.version - right.version || compareText(left.content, right.content) || compareText("created_at" in left ? left.created_at ?? "" : "", "created_at" in right ? right.created_at ?? "" : ""));
17976
18789
  const profiles = [...domain.profiles].sort((left, right) => compareText(left.slug, right.slug));
17977
18790
  const configBindings = [...domain.profile_config_bindings].sort((left, right) => compareText(left.profile_slug, right.profile_slug) || left.sort_order - right.sort_order || compareText(left.config_slug, right.config_slug));
17978
18791
  const assetBindings = [...domain.profile_asset_bindings].sort((left, right) => compareText(left.profile_slug, right.profile_slug) || left.sort_order - right.sort_order || compareText(left.binding.assetKey, right.binding.assetKey));
@@ -18001,12 +18814,7 @@ function logicalCollections(domain, options) {
18001
18814
  synced_at: config.synced_at
18002
18815
  } : {}
18003
18816
  })),
18004
- config_snapshots: snapshots.map((snapshot) => ({
18005
- config_slug: snapshot.config_slug,
18006
- version: snapshot.version,
18007
- content: snapshot.content,
18008
- ...options.includeOperationalTimestamps ? { created_at: snapshot.created_at } : {}
18009
- })),
18817
+ config_snapshots: snapshots,
18010
18818
  profiles: profiles.map((profile) => ({
18011
18819
  slug: profile.slug,
18012
18820
  name: profile.name,
@@ -18130,10 +18938,11 @@ function validateInstructionsDomainArchive(value) {
18130
18938
  assertUnique(typed.configs.map((row) => row.slug), "config slug");
18131
18939
  assertUnique(typed.profiles.map((row) => row.slug), "profile slug");
18132
18940
  assertUnique(typed.machines.map((row) => row.hostname), "machine hostname");
18133
- assertUnique(typed.config_snapshots.map((row) => `${row.config_slug}@${row.version}`), "config snapshot");
18941
+ assertUnique(typed.config_snapshots.map((row) => row.id), "config snapshot id");
18134
18942
  assertUnique(typed.profile_config_bindings.map((row) => `${row.profile_slug}:${row.config_slug}`), "profile config binding");
18135
18943
  assertUnique(typed.profile_asset_bindings.map((row) => `${row.profile_slug}:${row.binding.assetKey}`), "profile asset binding");
18136
- const configSlugs = new Set(typed.configs.map((row) => row.slug));
18944
+ const configsBySlug = new Map(typed.configs.map((row) => [row.slug, row]));
18945
+ const configSlugs = new Set(configsBySlug.keys());
18137
18946
  const profileSlugs = new Set(typed.profiles.map((row) => row.slug));
18138
18947
  for (const config of typed.configs) {
18139
18948
  assertTimestamp(config.created_at, `config ${config.slug} created_at`);
@@ -18141,24 +18950,15 @@ function validateInstructionsDomainArchive(value) {
18141
18950
  assertTimestamp(config.synced_at, `config ${config.slug} synced_at`, true);
18142
18951
  if (!Number.isSafeInteger(config.version) || config.version < 1)
18143
18952
  throw new Error(`Invalid v2 archive: config ${config.slug} has invalid version`);
18144
- const snapshots = typed.config_snapshots.filter((row) => row.config_slug === config.slug).sort((a, b) => a.version - b.version);
18145
- if (snapshots.some((row) => !Number.isSafeInteger(row.version) || row.version < 1 || row.version > config.version)) {
18146
- throw new Error(`Invalid v2 archive: config ${config.slug} has an invalid snapshot version`);
18147
- }
18148
- if (snapshots.length) {
18149
- const first = snapshots[0].version;
18150
- const expected = Array.from({ length: config.version - first + 1 }, (_, index) => first + index);
18151
- if (canonicalDomainJson(snapshots.map((row) => row.version)) !== canonicalDomainJson(expected) || snapshots.at(-1).version !== config.version) {
18152
- throw new Error(`Invalid v2 archive: snapshots for ${config.slug} must be a contiguous suffix ending at version ${config.version}`);
18153
- }
18154
- if (snapshots.at(-1).content !== config.content) {
18155
- throw new Error(`Invalid v2 archive: latest snapshot content differs from config ${config.slug}`);
18156
- }
18157
- }
18158
18953
  }
18159
18954
  for (const row of typed.config_snapshots) {
18160
- if (!configSlugs.has(row.config_slug))
18955
+ const config = configsBySlug.get(row.config_slug);
18956
+ if (!config) {
18161
18957
  throw new Error(`Invalid v2 archive: snapshot references missing config ${row.config_slug}`);
18958
+ }
18959
+ if (!Number.isSafeInteger(row.version) || row.version < 1 || row.version > config.version) {
18960
+ throw new Error(`Invalid v2 archive: config ${row.config_slug} has an invalid snapshot version`);
18961
+ }
18162
18962
  assertTimestamp(row.created_at, `snapshot ${row.config_slug}@${row.version} created_at`);
18163
18963
  }
18164
18964
  for (const profile of typed.profiles) {
@@ -18265,13 +19065,13 @@ async function exportConfigs(outputPath, opts = {}) {
18265
19065
  integrity,
18266
19066
  exclusions: ARCHIVE_EXCLUSIONS
18267
19067
  };
18268
- const absOutput = resolve12(outputPath);
18269
- mkdirSync8(dirname11(absOutput), { recursive: true });
18270
- 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-"));
18271
19071
  try {
18272
- writeFileSync6(join20(stagingDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
19072
+ writeFileSync6(join21(stagingDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
18273
19073
  `, "utf-8");
18274
- writeFileSync6(join20(stagingDir, "domain.json"), payload, "utf-8");
19074
+ writeFileSync6(join21(stagingDir, "domain.json"), payload, "utf-8");
18275
19075
  const proc = Bun.spawn(["tar", "czf", absOutput, "-C", stagingDir, "manifest.json", "domain.json"], {
18276
19076
  stdout: "pipe",
18277
19077
  stderr: "pipe"
@@ -18290,8 +19090,8 @@ async function exportConfigs(outputPath, opts = {}) {
18290
19090
  // src/lib/import.ts
18291
19091
  init_types();
18292
19092
  init_config_store();
18293
- import { createHash as createHash12 } from "crypto";
18294
- import { resolve as resolve13 } from "path";
19093
+ import { createHash as createHash13 } from "crypto";
19094
+ import { resolve as resolve14 } from "path";
18295
19095
  function compareText2(left, right) {
18296
19096
  return left < right ? -1 : left > right ? 1 : 0;
18297
19097
  }
@@ -18316,7 +19116,7 @@ function emptyResult() {
18316
19116
  };
18317
19117
  }
18318
19118
  function sha25612(value) {
18319
- return createHash12("sha256").update(value).digest("hex");
19119
+ return createHash13("sha256").update(value).digest("hex");
18320
19120
  }
18321
19121
  function normalizeMemberName(name) {
18322
19122
  let normalized = name;
@@ -18413,14 +19213,11 @@ function configInput(config, content) {
18413
19213
  };
18414
19214
  }
18415
19215
  async function restoreNewConfig(store, archived, domain) {
18416
- const snapshots = domain.config_snapshots.filter((row) => row.config_slug === archived.slug).sort((left, right) => left.version - right.version);
18417
- const byVersion = new Map(snapshots.map((snapshot) => [snapshot.version, snapshot.content]));
18418
- let content = byVersion.get(1) ?? snapshots[0]?.content ?? archived.content;
18419
- let restored = await store.createConfig(configInput(archived, content));
19216
+ const snapshots = domain.config_snapshots.filter((row) => row.config_slug === archived.slug).sort((left, right) => left.version - right.version || compareText2(left.content, right.content) || compareText2(left.id, right.id));
19217
+ let restored = await store.createConfig(configInput(archived, archived.content));
18420
19218
  for (let version = 2;version <= archived.version; version++) {
18421
- content = byVersion.get(version) ?? (version === archived.version ? archived.content : content);
18422
19219
  restored = await store.updateConfig(restored.id, {
18423
- content,
19220
+ content: archived.content,
18424
19221
  ...version === archived.version ? {
18425
19222
  name: archived.name,
18426
19223
  kind: archived.kind,
@@ -18436,9 +19233,12 @@ async function restoreNewConfig(store, archived, domain) {
18436
19233
  } : {}
18437
19234
  });
18438
19235
  }
18439
- await store.pruneSnapshots(restored.id, snapshots.length);
18440
- const restoredSnapshots = (await store.listSnapshots(restored.id)).map(({ version, content: snapshotContent }) => ({ version, content: snapshotContent })).sort((left, right) => left.version - right.version);
18441
- const expectedSnapshots = snapshots.map(({ version, content: snapshotContent }) => ({ version, content: snapshotContent }));
19236
+ await store.pruneSnapshots(restored.id, 0);
19237
+ for (const snapshot of snapshots) {
19238
+ await store.createSnapshot(restored.id, snapshot.content, snapshot.version);
19239
+ }
19240
+ const restoredSnapshots = (await store.listSnapshots(restored.id)).map(({ version, content: snapshotContent }) => ({ version, content: snapshotContent })).sort((left, right) => left.version - right.version || compareText2(left.content, right.content));
19241
+ const expectedSnapshots = snapshots.map(({ version, content: snapshotContent }) => ({ version, content: snapshotContent })).sort((left, right) => left.version - right.version || compareText2(left.content, right.content));
18442
19242
  if (restored.version !== archived.version || restored.content !== archived.content || canonicalDomainJson(restoredSnapshots) !== canonicalDomainJson(expectedSnapshots)) {
18443
19243
  throw new Error(`restored config or snapshot history did not match archive for ${archived.slug}`);
18444
19244
  }
@@ -18579,7 +19379,7 @@ async function importV1(reader, manifest, store, conflict) {
18579
19379
  async function importConfigs(bundlePath, opts = {}) {
18580
19380
  const store = opts.store ?? resolveConfigStore();
18581
19381
  const conflict = opts.conflict ?? "skip";
18582
- const reader = await openArchive(resolve13(bundlePath));
19382
+ const reader = await openArchive(resolve14(bundlePath));
18583
19383
  const manifestText = await reader.read("manifest.json");
18584
19384
  let manifest;
18585
19385
  try {
@@ -18607,9 +19407,9 @@ init_redact();
18607
19407
 
18608
19408
  // src/lib/package-manager-guard.ts
18609
19409
  import { execFileSync as execFileSync2 } from "child_process";
18610
- 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";
18611
19411
  import { homedir as homedir10 } from "os";
18612
- 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";
18613
19413
  var SKIP_DIRS = new Set([
18614
19414
  ".git",
18615
19415
  "node_modules",
@@ -18646,14 +19446,14 @@ var TOKEN_VALUE_PATTERNS = [
18646
19446
  { re: /xoxb-[0-9]+-[A-Za-z0-9-]+/, rule: "literal-slack-token", detail: "literal Slack token-like value" }
18647
19447
  ];
18648
19448
  function scanPackageManagerSecrets(options = {}) {
18649
- const cwd = options.cwd ? resolve14(options.cwd) : process.cwd();
18650
- 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));
18651
19451
  const findings = [];
18652
19452
  let scannedFiles = 0;
18653
19453
  for (const root of roots) {
18654
19454
  if (!existsSync19(root))
18655
19455
  continue;
18656
- const stat = lstatSync7(root);
19456
+ const stat = lstatSync8(root);
18657
19457
  if (stat.isFile()) {
18658
19458
  if (!shouldScanRepoFile(root))
18659
19459
  continue;
@@ -18661,7 +19461,7 @@ function scanPackageManagerSecrets(options = {}) {
18661
19461
  if (text === null)
18662
19462
  continue;
18663
19463
  scannedFiles++;
18664
- findings.push(...scanFile(root, text, classifyRepoFile(root), isTrackedFile(root), dirname12(root)));
19464
+ findings.push(...scanFile(root, text, classifyRepoFile(root), isTrackedFile(root), dirname13(root)));
18665
19465
  continue;
18666
19466
  }
18667
19467
  if (!stat.isDirectory())
@@ -18680,7 +19480,7 @@ function scanPackageManagerSecrets(options = {}) {
18680
19480
  if (options.includeHome) {
18681
19481
  const home = homedir10();
18682
19482
  for (const name of HOME_FILES) {
18683
- const file = join21(home, name);
19483
+ const file = join22(home, name);
18684
19484
  if (!existsSync19(file))
18685
19485
  continue;
18686
19486
  const text = readTextFile(file);
@@ -18705,12 +19505,12 @@ function collectRepoFiles(root) {
18705
19505
  if (entry.isDirectory()) {
18706
19506
  if (SKIP_DIRS.has(entry.name))
18707
19507
  continue;
18708
- visit(join21(dir, entry.name));
19508
+ visit(join22(dir, entry.name));
18709
19509
  continue;
18710
19510
  }
18711
19511
  if (!entry.isFile())
18712
19512
  continue;
18713
- const file = join21(dir, entry.name);
19513
+ const file = join22(dir, entry.name);
18714
19514
  if (shouldScanRepoFile(file))
18715
19515
  out.push(file);
18716
19516
  }
@@ -18719,11 +19519,11 @@ function collectRepoFiles(root) {
18719
19519
  return out;
18720
19520
  }
18721
19521
  function shouldScanRepoFile(file) {
18722
- const name = basename7(file);
19522
+ const name = basename8(file);
18723
19523
  return isNpmrcName(name) || isBunConfigName(name) || LOCKFILE_NAMES.has(name);
18724
19524
  }
18725
19525
  function classifyRepoFile(file) {
18726
- const name = basename7(file);
19526
+ const name = basename8(file);
18727
19527
  if (isNpmrcName(name))
18728
19528
  return "repo-npmrc";
18729
19529
  if (isBunConfigName(name))
@@ -18745,10 +19545,10 @@ function isNpmrcName(name) {
18745
19545
  }
18746
19546
  function readTextFile(file) {
18747
19547
  try {
18748
- const stat = lstatSync7(file);
19548
+ const stat = lstatSync8(file);
18749
19549
  if (!stat.isFile() || stat.size > 5000000)
18750
19550
  return null;
18751
- const buf = readFileSync17(file);
19551
+ const buf = readFileSync18(file);
18752
19552
  if (buf.includes(0))
18753
19553
  return null;
18754
19554
  return buf.toString("utf-8");
@@ -18948,7 +19748,7 @@ function trackedFiles(root) {
18948
19748
  }
18949
19749
  function isTrackedFile(file) {
18950
19750
  try {
18951
- const repoRoot = execFileSync2("git", ["-C", dirname12(file), "rev-parse", "--show-toplevel"], {
19751
+ const repoRoot = execFileSync2("git", ["-C", dirname13(file), "rev-parse", "--show-toplevel"], {
18952
19752
  encoding: "utf-8",
18953
19753
  stdio: ["ignore", "pipe", "ignore"]
18954
19754
  }).trim();
@@ -18991,6 +19791,7 @@ function toPosix(path) {
18991
19791
  return path.split("\\").join("/");
18992
19792
  }
18993
19793
  export {
19794
+ validateExpectedConfigVersion,
18994
19795
  uuid,
18995
19796
  transformSkillContent,
18996
19797
  templateizeMachineContent,
@@ -19026,6 +19827,7 @@ export {
19026
19827
  renderMachineAwareContentPreview,
19027
19828
  renderMachineAwareContent,
19028
19829
  refreshStationProfile,
19830
+ refreshSessionRender,
19029
19831
  redactContent,
19030
19832
  reconcileManagedSkillRuntimes,
19031
19833
  readStationProfile,
@@ -19039,6 +19841,7 @@ export {
19039
19841
  parseProjectContextBundle,
19040
19842
  parseAgentOperatingRulesVersion,
19041
19843
  now,
19844
+ normalizeSessionHostedProfileSelector,
19042
19845
  normalizeProfileConfigBinding,
19043
19846
  normalizeProfileAssetBinding,
19044
19847
  normalizeOsFamily,
@@ -19085,6 +19888,7 @@ export {
19085
19888
  compareAgentOperatingRulesVersions,
19086
19889
  cleanSessionPathInput,
19087
19890
  checkSessionRenderDrift,
19891
+ buildSumiAgentsMd,
19088
19892
  buildStationProfileBlock,
19089
19893
  buildOpenCodeAgentsMd,
19090
19894
  buildCursorMdc,
@@ -19144,6 +19948,7 @@ export {
19144
19948
  LEGACY_CONFIGS_EXECUTABLE,
19145
19949
  LEGACY_CONFIGS_COMPAT_VERSION,
19146
19950
  KNOWN_CONFIGS,
19951
+ InvalidExpectedVersionError,
19147
19952
  InstructionGraphValidationError,
19148
19953
  INSTRUCTION_GRAPH_PLAN_SCHEMA,
19149
19954
  INSTRUCTION_FALLBACKS,
@@ -19156,6 +19961,7 @@ export {
19156
19961
  GLOBAL_AGENT_RULES_STANDARD_CONTENT,
19157
19962
  DANGEROUS_OPERATION_GUARD_STANDARD_SLUG,
19158
19963
  DANGEROUS_OPERATION_GUARD_STANDARD_CONTENT,
19964
+ ConfigVersionConflictError,
19159
19965
  ConfigNotFoundError,
19160
19966
  ConfigApplyError,
19161
19967
  CloudConfigStore,