@hasna/instructions 0.6.0 → 0.7.0

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 (265) hide show
  1. package/README.md +149 -8
  2. package/dist/chunks/apply-7svah2qm.js +25 -0
  3. package/dist/chunks/apply-jp13sa1e.js +25 -0
  4. package/dist/chunks/database-wstmr56z.js +23 -0
  5. package/dist/chunks/index-1cnyjnd7.js +623 -0
  6. package/dist/chunks/index-35z65jsa.js +198 -0
  7. package/dist/chunks/index-3djthcm6.js +117 -0
  8. package/dist/chunks/index-4pfq42t5.js +7300 -0
  9. package/dist/chunks/index-5d7zdftc.js +186 -0
  10. package/dist/chunks/index-7m4j8a33.js +12578 -0
  11. package/dist/chunks/index-8rb7ng2y.js +148 -0
  12. package/dist/chunks/index-arrrx0ed.js +344 -0
  13. package/dist/chunks/index-bsan4c16.js +48 -0
  14. package/dist/chunks/index-bzyxvwcd.js +625 -0
  15. package/dist/chunks/index-fpeyzn3n.js +186 -0
  16. package/dist/chunks/index-fwbs6tma.js +534 -0
  17. package/dist/chunks/index-ma2xmp6c.js +14 -0
  18. package/dist/chunks/index-n3fjspr0.js +119 -0
  19. package/dist/chunks/index-nnwp92tk.js +19 -0
  20. package/dist/chunks/index-z3ma4aqk.js +532 -0
  21. package/dist/chunks/legacy-store-migration-z2m5yzyk.js +322 -0
  22. package/dist/chunks/local-5wvv5xv3.js +694 -0
  23. package/dist/chunks/local-zxa5dpf4.js +518 -0
  24. package/dist/chunks/package-manager-guard-x70xrwk2.js +391 -0
  25. package/dist/chunks/redact-hnq4sc4r.js +16 -0
  26. package/dist/chunks/s3-backup-n2z4fwyh.js +240 -0
  27. package/dist/chunks/s3-config-hhght91k.js +14 -0
  28. package/dist/chunks/s3-object-store-90tgbh6k.js +14 -0
  29. package/dist/chunks/sync-2075deve.js +34 -0
  30. package/dist/chunks/sync-r8t7zsp3.js +34 -0
  31. package/dist/chunks/template-fsfxpe4p.js +16 -0
  32. package/dist/chunks/template-wgnzdn7h.js +16 -0
  33. package/dist/cli/index.js +1681 -15643
  34. package/dist/data/config-store.d.ts +2 -1
  35. package/dist/data/config-store.d.ts.map +1 -1
  36. package/dist/db/database.d.ts +3 -5
  37. package/dist/db/database.d.ts.map +1 -1
  38. package/dist/db/local.d.ts +38 -0
  39. package/dist/db/local.d.ts.map +1 -0
  40. package/dist/index.d.ts +1 -1
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +13809 -12998
  43. package/dist/lib/apply.d.ts +7 -0
  44. package/dist/lib/apply.d.ts.map +1 -1
  45. package/dist/lib/compact-output.d.ts +1 -0
  46. package/dist/lib/compact-output.d.ts.map +1 -1
  47. package/dist/lib/export.d.ts +22 -3
  48. package/dist/lib/export.d.ts.map +1 -1
  49. package/dist/lib/ids.d.ts +4 -0
  50. package/dist/lib/ids.d.ts.map +1 -0
  51. package/dist/lib/import.d.ts +18 -0
  52. package/dist/lib/import.d.ts.map +1 -1
  53. package/dist/lib/instruction-graph.d.ts.map +1 -1
  54. package/dist/lib/legacy-store-migration.d.ts +39 -0
  55. package/dist/lib/legacy-store-migration.d.ts.map +1 -0
  56. package/dist/lib/managed-skill-runtimes.d.ts +1 -0
  57. package/dist/lib/managed-skill-runtimes.d.ts.map +1 -1
  58. package/dist/lib/session-render.d.ts +3 -0
  59. package/dist/lib/session-render.d.ts.map +1 -1
  60. package/dist/lib/sync-dir.d.ts.map +1 -1
  61. package/dist/mcp/index.js +73 -9462
  62. package/dist/sdk/index.d.ts +2 -0
  63. package/dist/sdk/index.d.ts.map +1 -1
  64. package/dist/sdk/index.js +205 -10
  65. package/dist/sdk/resolve.d.ts +1 -1
  66. package/dist/sdk/resolve.d.ts.map +1 -1
  67. package/dist/sdk/v1-client.d.ts +57 -0
  68. package/dist/sdk/v1-client.d.ts.map +1 -0
  69. package/dist/sdk/v1.generated.d.ts +212 -21
  70. package/dist/sdk/v1.generated.d.ts.map +1 -1
  71. package/dist/server/cloud.d.ts.map +1 -1
  72. package/dist/server/index.d.ts +13 -5
  73. package/dist/server/index.d.ts.map +1 -1
  74. package/dist/server/index.js +8337 -7495
  75. package/dist/server/openapi.d.ts +1264 -92
  76. package/dist/server/openapi.d.ts.map +1 -1
  77. package/dist/server/v1.d.ts +25 -1
  78. package/dist/server/v1.d.ts.map +1 -1
  79. package/dist/status.d.ts +12 -2
  80. package/dist/status.d.ts.map +1 -1
  81. package/dist/storage/cloud-store.d.ts +57 -1
  82. package/dist/storage/cloud-store.d.ts.map +1 -1
  83. package/dist/storage/index.d.ts +7 -0
  84. package/dist/storage/index.d.ts.map +1 -0
  85. package/dist/storage/index.js +725 -0
  86. package/dist/storage/s3-backup.d.ts +76 -0
  87. package/dist/storage/s3-backup.d.ts.map +1 -0
  88. package/dist/storage/s3-config.d.ts +46 -0
  89. package/dist/storage/s3-config.d.ts.map +1 -0
  90. package/dist/storage/s3-object-store.d.ts +70 -0
  91. package/dist/storage/s3-object-store.d.ts.map +1 -0
  92. package/dist/types/index.d.ts +65 -3
  93. package/dist/types/index.d.ts.map +1 -1
  94. package/hasna.contract.json +110 -0
  95. package/migrations/0001_instructions.sql +63 -0
  96. package/migrations/0002_api_keys.sql +20 -0
  97. package/migrations/0003_idempotency_receipts.sql +24 -0
  98. package/package.json +29 -14
  99. package/assets/skills/inbox/SKILL.md +0 -86
  100. package/dist/cli/add-duplicate-target.test.d.ts +0 -2
  101. package/dist/cli/add-duplicate-target.test.d.ts.map +0 -1
  102. package/dist/cli/add-reference-update.test.d.ts +0 -2
  103. package/dist/cli/add-reference-update.test.d.ts.map +0 -1
  104. package/dist/cli/apply-unchanged-snapshot-bloat.test.d.ts +0 -2
  105. package/dist/cli/apply-unchanged-snapshot-bloat.test.d.ts.map +0 -1
  106. package/dist/cli/doctor-reference-duplicates.test.d.ts +0 -2
  107. package/dist/cli/doctor-reference-duplicates.test.d.ts.map +0 -1
  108. package/dist/cli/fail-closed-no-env.test.d.ts +0 -2
  109. package/dist/cli/fail-closed-no-env.test.d.ts.map +0 -1
  110. package/dist/cli/output.test.d.ts +0 -2
  111. package/dist/cli/output.test.d.ts.map +0 -1
  112. package/dist/cli/profile-binding.test.d.ts +0 -2
  113. package/dist/cli/profile-binding.test.d.ts.map +0 -1
  114. package/dist/cli/profile-reads.test.d.ts +0 -2
  115. package/dist/cli/profile-reads.test.d.ts.map +0 -1
  116. package/dist/cli/profile-update.test.d.ts +0 -2
  117. package/dist/cli/profile-update.test.d.ts.map +0 -1
  118. package/dist/cli/project-context.test.d.ts +0 -2
  119. package/dist/cli/project-context.test.d.ts.map +0 -1
  120. package/dist/cli/raw-store-root.test.d.ts +0 -2
  121. package/dist/cli/raw-store-root.test.d.ts.map +0 -1
  122. package/dist/cli/session-apply-managed-input-bound.test.d.ts +0 -2
  123. package/dist/cli/session-apply-managed-input-bound.test.d.ts.map +0 -1
  124. package/dist/cli/session.test.d.ts +0 -2
  125. package/dist/cli/session.test.d.ts.map +0 -1
  126. package/dist/cli/station-profile.test.d.ts +0 -2
  127. package/dist/cli/station-profile.test.d.ts.map +0 -1
  128. package/dist/data/config-store.test.d.ts +0 -2
  129. package/dist/data/config-store.test.d.ts.map +0 -1
  130. package/dist/db/configs.test.d.ts +0 -2
  131. package/dist/db/configs.test.d.ts.map +0 -1
  132. package/dist/db/database.test.d.ts +0 -2
  133. package/dist/db/database.test.d.ts.map +0 -1
  134. package/dist/db/machines.test.d.ts +0 -2
  135. package/dist/db/machines.test.d.ts.map +0 -1
  136. package/dist/db/profile-assets.test.d.ts +0 -2
  137. package/dist/db/profile-assets.test.d.ts.map +0 -1
  138. package/dist/db/profile-config-bindings.test.d.ts +0 -2
  139. package/dist/db/profile-config-bindings.test.d.ts.map +0 -1
  140. package/dist/db/profiles.test.d.ts +0 -2
  141. package/dist/db/profiles.test.d.ts.map +0 -1
  142. package/dist/db/snapshots.test.d.ts +0 -2
  143. package/dist/db/snapshots.test.d.ts.map +0 -1
  144. package/dist/lib/app-home.test.d.ts +0 -2
  145. package/dist/lib/app-home.test.d.ts.map +0 -1
  146. package/dist/lib/apply-batch.test.d.ts +0 -2
  147. package/dist/lib/apply-batch.test.d.ts.map +0 -1
  148. package/dist/lib/apply-dry-run-verdict.test.d.ts +0 -2
  149. package/dist/lib/apply-dry-run-verdict.test.d.ts.map +0 -1
  150. package/dist/lib/apply-secret-placeholder-guard.test.d.ts +0 -2
  151. package/dist/lib/apply-secret-placeholder-guard.test.d.ts.map +0 -1
  152. package/dist/lib/apply-text-format-credential-guard.test.d.ts +0 -2
  153. package/dist/lib/apply-text-format-credential-guard.test.d.ts.map +0 -1
  154. package/dist/lib/apply.test.d.ts +0 -2
  155. package/dist/lib/apply.test.d.ts.map +0 -1
  156. package/dist/lib/asset-plan.test.d.ts +0 -2
  157. package/dist/lib/asset-plan.test.d.ts.map +0 -1
  158. package/dist/lib/client-types.test.d.ts +0 -2
  159. package/dist/lib/client-types.test.d.ts.map +0 -1
  160. package/dist/lib/codewith-shared-todos-storage-standard.test.d.ts +0 -2
  161. package/dist/lib/codewith-shared-todos-storage-standard.test.d.ts.map +0 -1
  162. package/dist/lib/compact-output.test.d.ts +0 -2
  163. package/dist/lib/compact-output.test.d.ts.map +0 -1
  164. package/dist/lib/config-target-identity.test.d.ts +0 -2
  165. package/dist/lib/config-target-identity.test.d.ts.map +0 -1
  166. package/dist/lib/cursor-authority.test.d.ts +0 -2
  167. package/dist/lib/cursor-authority.test.d.ts.map +0 -1
  168. package/dist/lib/dangerous-operation-guard-standard.test.d.ts +0 -2
  169. package/dist/lib/dangerous-operation-guard-standard.test.d.ts.map +0 -1
  170. package/dist/lib/diff-redaction.test.d.ts +0 -2
  171. package/dist/lib/diff-redaction.test.d.ts.map +0 -1
  172. package/dist/lib/export-import.test.d.ts +0 -2
  173. package/dist/lib/export-import.test.d.ts.map +0 -1
  174. package/dist/lib/global-agent-rules-render-integration.test.d.ts +0 -2
  175. package/dist/lib/global-agent-rules-render-integration.test.d.ts.map +0 -1
  176. package/dist/lib/global-agent-rules-standard.test.d.ts +0 -2
  177. package/dist/lib/global-agent-rules-standard.test.d.ts.map +0 -1
  178. package/dist/lib/global-agent-rules-stored-content.test.d.ts +0 -2
  179. package/dist/lib/global-agent-rules-stored-content.test.d.ts.map +0 -1
  180. package/dist/lib/global-source-coverage.test.d.ts +0 -2
  181. package/dist/lib/global-source-coverage.test.d.ts.map +0 -1
  182. package/dist/lib/instruction-graph-apply.test.d.ts +0 -2
  183. package/dist/lib/instruction-graph-apply.test.d.ts.map +0 -1
  184. package/dist/lib/instruction-graph.test.d.ts +0 -2
  185. package/dist/lib/instruction-graph.test.d.ts.map +0 -1
  186. package/dist/lib/machine.test.d.ts +0 -2
  187. package/dist/lib/machine.test.d.ts.map +0 -1
  188. package/dist/lib/managed-skill-runtimes.test.d.ts +0 -2
  189. package/dist/lib/managed-skill-runtimes.test.d.ts.map +0 -1
  190. package/dist/lib/package-manager-guard.test.d.ts +0 -2
  191. package/dist/lib/package-manager-guard.test.d.ts.map +0 -1
  192. package/dist/lib/project-context-prepared-file.test.d.ts +0 -2
  193. package/dist/lib/project-context-prepared-file.test.d.ts.map +0 -1
  194. package/dist/lib/project-context.test.d.ts +0 -2
  195. package/dist/lib/project-context.test.d.ts.map +0 -1
  196. package/dist/lib/project-dashboard-standard.test.d.ts +0 -2
  197. package/dist/lib/project-dashboard-standard.test.d.ts.map +0 -1
  198. package/dist/lib/provider-assets-adapters.test.d.ts +0 -2
  199. package/dist/lib/provider-assets-adapters.test.d.ts.map +0 -1
  200. package/dist/lib/provider-context.test.d.ts +0 -2
  201. package/dist/lib/provider-context.test.d.ts.map +0 -1
  202. package/dist/lib/provider-version-adapters.test.d.ts +0 -2
  203. package/dist/lib/provider-version-adapters.test.d.ts.map +0 -1
  204. package/dist/lib/redact.test.d.ts +0 -2
  205. package/dist/lib/redact.test.d.ts.map +0 -1
  206. package/dist/lib/session-apply.test.d.ts +0 -2
  207. package/dist/lib/session-apply.test.d.ts.map +0 -1
  208. package/dist/lib/session-authority.test.d.ts +0 -2
  209. package/dist/lib/session-authority.test.d.ts.map +0 -1
  210. package/dist/lib/session-render-managed-output-bound.test.d.ts +0 -2
  211. package/dist/lib/session-render-managed-output-bound.test.d.ts.map +0 -1
  212. package/dist/lib/session-render-ownership.test.d.ts +0 -2
  213. package/dist/lib/session-render-ownership.test.d.ts.map +0 -1
  214. package/dist/lib/session-render-rule-currency-floor.test.d.ts +0 -2
  215. package/dist/lib/session-render-rule-currency-floor.test.d.ts.map +0 -1
  216. package/dist/lib/session-render-silent-source-drop.test.d.ts +0 -2
  217. package/dist/lib/session-render-silent-source-drop.test.d.ts.map +0 -1
  218. package/dist/lib/session-render-state-hermeticity.test.d.ts +0 -2
  219. package/dist/lib/session-render-state-hermeticity.test.d.ts.map +0 -1
  220. package/dist/lib/session-render-state.test.d.ts +0 -2
  221. package/dist/lib/session-render-state.test.d.ts.map +0 -1
  222. package/dist/lib/session-render.test.d.ts +0 -2
  223. package/dist/lib/session-render.test.d.ts.map +0 -1
  224. package/dist/lib/station-profile.test.d.ts +0 -2
  225. package/dist/lib/station-profile.test.d.ts.map +0 -1
  226. package/dist/lib/sync-dir.test.d.ts +0 -2
  227. package/dist/lib/sync-dir.test.d.ts.map +0 -1
  228. package/dist/lib/sync-dry-run-unchanged.test.d.ts +0 -2
  229. package/dist/lib/sync-dry-run-unchanged.test.d.ts.map +0 -1
  230. package/dist/lib/sync-known.test.d.ts +0 -2
  231. package/dist/lib/sync-known.test.d.ts.map +0 -1
  232. package/dist/lib/sync.test.d.ts +0 -2
  233. package/dist/lib/sync.test.d.ts.map +0 -1
  234. package/dist/lib/template.test.d.ts +0 -2
  235. package/dist/lib/template.test.d.ts.map +0 -1
  236. package/dist/lib/transforms.test.d.ts +0 -2
  237. package/dist/lib/transforms.test.d.ts.map +0 -1
  238. package/dist/lib/transport-resolver.test.d.ts +0 -2
  239. package/dist/lib/transport-resolver.test.d.ts.map +0 -1
  240. package/dist/mcp/create-config-target-guard.test.d.ts +0 -2
  241. package/dist/mcp/create-config-target-guard.test.d.ts.map +0 -1
  242. package/dist/mcp/early-args.test.d.ts +0 -2
  243. package/dist/mcp/early-args.test.d.ts.map +0 -1
  244. package/dist/mcp/http.test.d.ts +0 -2
  245. package/dist/mcp/http.test.d.ts.map +0 -1
  246. package/dist/mcp/mcp.test.d.ts +0 -2
  247. package/dist/mcp/mcp.test.d.ts.map +0 -1
  248. package/dist/sdk/resolve.test.d.ts +0 -2
  249. package/dist/sdk/resolve.test.d.ts.map +0 -1
  250. package/dist/sdk/sdk-bundle-self-contained.test.d.ts +0 -2
  251. package/dist/sdk/sdk-bundle-self-contained.test.d.ts.map +0 -1
  252. package/dist/server/cloud-auth.test.d.ts +0 -2
  253. package/dist/server/cloud-auth.test.d.ts.map +0 -1
  254. package/dist/server/cloud.test.d.ts +0 -2
  255. package/dist/server/cloud.test.d.ts.map +0 -1
  256. package/dist/server/early-args.test.d.ts +0 -2
  257. package/dist/server/early-args.test.d.ts.map +0 -1
  258. package/dist/server/profile-contract.test.d.ts +0 -2
  259. package/dist/server/profile-contract.test.d.ts.map +0 -1
  260. package/dist/status.test.d.ts +0 -2
  261. package/dist/status.test.d.ts.map +0 -1
  262. package/dist/storage/cloud-store.test.d.ts +0 -2
  263. package/dist/storage/cloud-store.test.d.ts.map +0 -1
  264. package/dist/test-support/preload-state-home.d.ts +0 -2
  265. package/dist/test-support/preload-state-home.d.ts.map +0 -1
@@ -0,0 +1,532 @@
1
+ // @bun
2
+ import {
3
+ ANTIGRAVITY_RULE_FILE_CHAR_LIMIT,
4
+ SESSION_RENDERER_OWNER_ID,
5
+ SESSION_RENDER_EXCLUSIVE_MANAGED_PATHS,
6
+ SESSION_RENDER_MANIFEST_RELATIVE_PATH,
7
+ SESSION_RENDER_OWNED_CONFIG_TARGETS,
8
+ SESSION_RENDER_SCHEMA,
9
+ applyTransform,
10
+ detectMachineContext,
11
+ isCursorGlobalAuthorityPath,
12
+ isRetiredOrUnsupportedConfigAgent,
13
+ isSecretVarName,
14
+ machineContextToVariables,
15
+ redactFormatForTarget,
16
+ renderMachineAwareContentPreview,
17
+ resolveConfigStore,
18
+ resolveProfileVariables,
19
+ scanSecrets,
20
+ stampCursorGlobalAuthorityMarker
21
+ } from "./index-7m4j8a33.js";
22
+ import {
23
+ ConfigApplyError,
24
+ parseTemplateVars
25
+ } from "./index-n3fjspr0.js";
26
+
27
+ // src/lib/apply.ts
28
+ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, realpathSync, writeFileSync } from "fs";
29
+ import { basename, dirname as dirname2, isAbsolute, join as join2, relative as relative2, resolve, sep as sep2 } from "path";
30
+ import { homedir } from "os";
31
+
32
+ // src/lib/session-render-ownership.ts
33
+ import { existsSync, readFileSync, statSync } from "fs";
34
+ import { dirname, join, parse, relative, sep } from "path";
35
+ var MANIFEST_ANCESTOR_LIMIT = 24;
36
+ var MANAGED_PATH_SEGMENTS = SESSION_RENDER_EXCLUSIVE_MANAGED_PATHS.map((managedPath) => managedPath.split("/").filter(Boolean));
37
+ var manifestCache = new Map;
38
+ function toSegments(absolutePath) {
39
+ return absolutePath.replaceAll("\\", "/").split("/").filter(Boolean);
40
+ }
41
+ function pathIsSessionRenderManagedDir(absolutePath) {
42
+ const segments = toSegments(absolutePath);
43
+ return MANAGED_PATH_SEGMENTS.some((managed) => {
44
+ if (managed.length === 0 || managed.length > segments.length)
45
+ return false;
46
+ for (let start = 0;start + managed.length <= segments.length; start += 1) {
47
+ if (managed.every((segment, offset) => segments[start + offset] === segment))
48
+ return true;
49
+ }
50
+ return false;
51
+ });
52
+ }
53
+ function readManifestRelativePaths(manifestPath) {
54
+ let stats;
55
+ try {
56
+ if (!existsSync(manifestPath))
57
+ return null;
58
+ stats = statSync(manifestPath);
59
+ } catch {
60
+ return null;
61
+ }
62
+ const cached = manifestCache.get(manifestPath);
63
+ if (cached && cached.mtimeMs === stats.mtimeMs && cached.size === stats.size) {
64
+ return cached.relativePaths;
65
+ }
66
+ let manifest;
67
+ try {
68
+ manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
69
+ } catch {
70
+ return null;
71
+ }
72
+ if (manifest?.schema !== SESSION_RENDER_SCHEMA || !Array.isArray(manifest.files))
73
+ return null;
74
+ const writerId = manifest.targetOwner?.writer?.id;
75
+ if (writerId !== undefined && writerId !== SESSION_RENDERER_OWNER_ID)
76
+ return null;
77
+ const relativePaths = new Set(manifest.files.map((file) => file?.relativePath).filter((relativePath) => typeof relativePath === "string").map((relativePath) => relativePath.replaceAll("\\", "/")));
78
+ manifestCache.set(manifestPath, { mtimeMs: stats.mtimeMs, size: stats.size, relativePaths });
79
+ return relativePaths;
80
+ }
81
+ function sessionRenderManifestClaimsPath(absolutePath) {
82
+ const root = parse(absolutePath).root;
83
+ let home = dirname(absolutePath);
84
+ for (let depth = 0;depth < MANIFEST_ANCESTOR_LIMIT; depth += 1) {
85
+ const manifestPath = join(home, ...SESSION_RENDER_MANIFEST_RELATIVE_PATH.split("/"));
86
+ const relativePaths = readManifestRelativePaths(manifestPath);
87
+ if (relativePaths) {
88
+ const claimed = relative(home, absolutePath).split(sep).join("/");
89
+ if (relativePaths.has(claimed))
90
+ return true;
91
+ }
92
+ const parent = dirname(home);
93
+ if (parent === home || home === root)
94
+ break;
95
+ home = parent;
96
+ }
97
+ return false;
98
+ }
99
+ function sessionRenderOwnsPath(absolutePath) {
100
+ return pathIsSessionRenderManagedDir(absolutePath) || sessionRenderManifestClaimsPath(absolutePath);
101
+ }
102
+
103
+ // src/lib/apply.ts
104
+ function getConfigHome() {
105
+ return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir();
106
+ }
107
+ function expandPath(p) {
108
+ if (p.startsWith("~/")) {
109
+ return resolve(getConfigHome(), p.slice(2));
110
+ }
111
+ return resolve(p);
112
+ }
113
+ function compactPathForConfigHome(p) {
114
+ const absolute = resolve(p);
115
+ const configHome = resolve(getConfigHome());
116
+ const conventionalHome = resolve(process.env["HOME"] || homedir());
117
+ if (configHome !== conventionalHome)
118
+ return absolute;
119
+ const rel = relative2(configHome, absolute);
120
+ if (!rel || rel === ".." || rel.startsWith(`..${sep2}`) || isAbsolute(rel))
121
+ return absolute;
122
+ return `~/${rel}`;
123
+ }
124
+ function normalizeTargetPath(p) {
125
+ const expanded = expandPath(p);
126
+ try {
127
+ return realpathSync(expanded);
128
+ } catch {
129
+ let current = expanded;
130
+ const missingSegments = [];
131
+ while (true) {
132
+ if (existsSync2(current)) {
133
+ try {
134
+ return resolve(realpathSync(current), ...missingSegments);
135
+ } catch {
136
+ return expanded;
137
+ }
138
+ }
139
+ const parent = dirname2(current);
140
+ const name = basename(current);
141
+ if (parent === current)
142
+ return expanded;
143
+ missingSegments.unshift(name);
144
+ current = parent;
145
+ }
146
+ }
147
+ }
148
+ async function writeConfigResult(config, targetPath, content, opts, meta = {}) {
149
+ const variables = opts.vars ?? {};
150
+ const renderedTarget = renderForApply(targetPath, variables);
151
+ const rendered = renderForApply(content, variables);
152
+ const renderedTargetPath = renderedTarget.content;
153
+ const renderedContent = rendered.content;
154
+ const targetAgent = meta.agent ?? config.agent;
155
+ if (sessionRendererOwnsTarget(renderedTargetPath, opts)) {
156
+ throw new ConfigApplyError(`Config "${config.name}" targets ${normalizeTargetPath(renderedTargetPath)}, which is owned by ${SESSION_RENDERER_OWNER_ID}; use the Instructions session renderer.`);
157
+ }
158
+ if (isAntigravityRuleTarget(targetAgent, renderedTargetPath) && renderedContent.length > ANTIGRAVITY_RULE_FILE_CHAR_LIMIT) {
159
+ throw new ConfigApplyError(`Antigravity rule file ${renderedTargetPath} is ${renderedContent.length} characters; split it before applying because Antigravity limits rule files to ${ANTIGRAVITY_RULE_FILE_CHAR_LIMIT} characters.`);
160
+ }
161
+ const path = expandPath(renderedTargetPath);
162
+ const renderedForTarget = isCursorGlobalAuthorityPath(path) ? stampCursorGlobalAuthorityMarker(renderedContent) : renderedContent;
163
+ const previousContent = existsSync2(path) ? readFileSync2(path, "utf-8") : null;
164
+ const changed = previousContent !== renderedForTarget;
165
+ if (!opts.dryRun) {
166
+ const dir = dirname2(path);
167
+ if (!existsSync2(dir)) {
168
+ mkdirSync(dir, { recursive: true });
169
+ }
170
+ if (previousContent !== null && changed) {
171
+ const store = opts.store ?? resolveConfigStore();
172
+ await store.createSnapshot(config.id, previousContent, config.version);
173
+ }
174
+ writeFileSync(path, renderedForTarget, "utf-8");
175
+ }
176
+ return {
177
+ config_id: config.id,
178
+ path,
179
+ previous_content: previousContent,
180
+ new_content: renderedForTarget,
181
+ dry_run: opts.dryRun ?? false,
182
+ changed,
183
+ primary_changed: changed,
184
+ unresolved_template_vars: [...new Set([
185
+ ...renderedTarget.unresolved,
186
+ ...rendered.unresolved
187
+ ])].sort(),
188
+ ...meta
189
+ };
190
+ }
191
+ function renderForApply(content, variables) {
192
+ return renderMachineAwareContentPreview(content, variables);
193
+ }
194
+ function wouldDestroyACredential(targetPath, renderedContent, format) {
195
+ const secretTokens = parseTemplateVars(renderedContent).filter(isSecretVarName);
196
+ if (secretTokens.length === 0)
197
+ return [];
198
+ let current;
199
+ try {
200
+ const path = expandPath(targetPath);
201
+ if (!existsSync2(path))
202
+ return [];
203
+ current = readFileSync2(path, "utf-8");
204
+ } catch {
205
+ return secretTokens;
206
+ }
207
+ if (current === renderedContent)
208
+ return [];
209
+ if (scanSecrets(current, redactFormatForTarget(targetPath, format)).length > 0)
210
+ return secretTokens;
211
+ return secretTokens.filter((name) => countPlaceholder(current, name) < countPlaceholder(renderedContent, name));
212
+ }
213
+ function countPlaceholder(content, name) {
214
+ return content.match(new RegExp(`\\{\\{${name}(?::[^}]*)?\\}\\}`, "g"))?.length ?? 0;
215
+ }
216
+ async function resolveApplyVariables(opts) {
217
+ const machine = detectMachineContext();
218
+ let base;
219
+ try {
220
+ const store = opts.store ?? resolveConfigStore();
221
+ const profile = await store.resolveProfileForMachine(machine);
222
+ base = resolveProfileVariables(profile, machine);
223
+ } catch {
224
+ base = machineContextToVariables(machine);
225
+ }
226
+ return { ...base, ...opts.vars ?? {} };
227
+ }
228
+ function isAntigravityRuleTarget(agent, targetPath) {
229
+ return agent === "antigravity" && /\.(md|mdc|markdown)$/i.test(targetPath);
230
+ }
231
+ function isGeneratedOutputTarget(config, configs, opts) {
232
+ const primary = canonicalConfigApplyBehavior(config, opts, configs).primary;
233
+ if (!primary)
234
+ return false;
235
+ return configs.some((candidate) => candidate.id !== config.id && canonicalConfigApplyBehavior(candidate, opts, configs).outputs.some((output) => output.path === primary.path));
236
+ }
237
+ async function applyConfig(config, opts = {}) {
238
+ if (config.kind === "reference") {
239
+ throw new ConfigApplyError(`Config "${config.name}" is a reference (kind=reference) and has no target_path \u2014 cannot apply to disk.`);
240
+ }
241
+ if (opts.outputAgent && isRetiredOrUnsupportedConfigAgent(opts.outputAgent)) {
242
+ throw new ConfigApplyError(`Config output agent "${opts.outputAgent}" is retired or unsupported \u2014 cannot apply to disk.`);
243
+ }
244
+ if (isRetiredOrUnsupportedConfigAgent(config.agent)) {
245
+ throw new ConfigApplyError(`Config "${config.name}" uses retired or unsupported agent "${config.agent}" \u2014 cannot apply to disk.`);
246
+ }
247
+ const report = await applyConfigsWithReport([config], opts);
248
+ if (report.failures.length > 0) {
249
+ throw new ConfigApplyError(report.failures.map((failure) => failure.message).join("; "));
250
+ }
251
+ const result = report.results[0];
252
+ if (result)
253
+ return result;
254
+ const owned = report.skipped.find((entry) => entry.owner === SESSION_RENDERER_OWNER_ID);
255
+ if (owned) {
256
+ throw new ConfigApplyError(`Config "${config.name}" targets ${owned.path}, which is owned by ${SESSION_RENDERER_OWNER_ID}; use the Instructions session renderer.`);
257
+ }
258
+ throw new ConfigApplyError(`Config "${config.name}" has no writable targets after apply ownership checks.`);
259
+ }
260
+ async function applyPreparedConfig(config, opts) {
261
+ const selectedOutputs = opts.outputAgent ? config.outputs.filter((output) => output.agent === opts.outputAgent) : config.outputs.filter((output) => !isRetiredOrUnsupportedConfigAgent(output.agent));
262
+ const shouldApplyPrimary = !opts.outputAgent || config.agent === opts.outputAgent;
263
+ if (config.kind === "reference" || (!config.target_path || !shouldApplyPrimary) && selectedOutputs.length === 0) {
264
+ throw new ConfigApplyError(`Config "${config.name}" is a reference (kind=reference) and has no target_path \u2014 cannot apply to disk.`);
265
+ }
266
+ const store = opts.store ?? resolveConfigStore();
267
+ const contextConfigs = selectedOutputs.length > 0 || config.target_path ? await store.listConfigs() : [config];
268
+ if (isGeneratedOutputTarget(config, contextConfigs, opts)) {
269
+ throw new ConfigApplyError(`Config "${config.name}" targets a generated output path. Apply the canonical source config instead.`);
270
+ }
271
+ const outputResults = [];
272
+ for (const output of selectedOutputs) {
273
+ outputResults.push(await applyOutput(config, output, contextConfigs, opts));
274
+ }
275
+ let result;
276
+ if (config.target_path && shouldApplyPrimary) {
277
+ result = await writeConfigResult(config, config.target_path, config.content, opts);
278
+ result.outputs = outputResults;
279
+ result.changed = result.primary_changed || outputResults.some((output) => output.changed);
280
+ result.unresolved_template_vars = [...new Set([
281
+ ...result.unresolved_template_vars ?? [],
282
+ ...outputResults.flatMap((output) => output.unresolved_template_vars ?? [])
283
+ ])].sort();
284
+ } else {
285
+ result = {
286
+ ...outputResults[0],
287
+ outputs: outputResults.slice(1),
288
+ changed: outputResults.some((output) => output.changed)
289
+ };
290
+ }
291
+ if (!opts.dryRun && result.changed) {
292
+ await store.updateConfig(config.id, { synced_at: new Date().toISOString() });
293
+ }
294
+ return result;
295
+ }
296
+ async function applyOutput(config, output, contextConfigs, opts) {
297
+ const content = applyTransform(config, output, { configs: contextConfigs });
298
+ return writeConfigResult(config, output.target_path, content, opts, {
299
+ agent: output.agent,
300
+ transform: output.transform
301
+ });
302
+ }
303
+ async function applyConfigs(configs, opts = {}) {
304
+ const report = await applyConfigsWithReport(configs, opts);
305
+ if (report.failures.length > 0) {
306
+ throw new ConfigApplyError(report.failures.map((failure) => failure.message).join("; "));
307
+ }
308
+ return report.results;
309
+ }
310
+ async function applyConfigsWithReport(configs, opts = {}) {
311
+ const effective = { ...opts, vars: await resolveApplyVariables(opts) };
312
+ const prepared = prepareConfigBatch(configs, effective);
313
+ if (prepared.failures.length > 0) {
314
+ return {
315
+ results: [],
316
+ skipped: prepared.skipped,
317
+ failures: prepared.failures
318
+ };
319
+ }
320
+ const results = [];
321
+ const failures = [];
322
+ for (const config of prepared.configs) {
323
+ if (config.kind === "reference" || isRetiredOrUnsupportedConfigAgent(config.agent))
324
+ continue;
325
+ try {
326
+ results.push(await applyPreparedConfig(config, effective));
327
+ } catch (error) {
328
+ failures.push({
329
+ config_id: config.id,
330
+ config_slug: config.slug,
331
+ message: error instanceof Error ? error.message : String(error)
332
+ });
333
+ }
334
+ }
335
+ return {
336
+ results,
337
+ skipped: prepared.skipped,
338
+ failures
339
+ };
340
+ }
341
+ async function previewConfigs(configs, opts = {}) {
342
+ return applyConfigsWithReport(configs, { ...opts, dryRun: true });
343
+ }
344
+ function prepareConfigBatch(configs, opts) {
345
+ const skipped = [];
346
+ const outputAgent = opts.outputAgent;
347
+ const selectedConfigs = configs.map((config) => outputAgent ? {
348
+ ...config,
349
+ target_path: config.agent === outputAgent ? config.target_path : null,
350
+ outputs: config.outputs.filter((output) => output.agent === outputAgent)
351
+ } : config);
352
+ const activeConfigs = selectedConfigs.filter((config) => {
353
+ if (!isRetiredOrUnsupportedConfigAgent(config.agent))
354
+ return true;
355
+ for (const target of configTargets(config, opts, selectedConfigs)) {
356
+ skipped.push({
357
+ config_id: config.id,
358
+ config_slug: config.slug,
359
+ path: target.path,
360
+ owner: "retired-provider-config",
361
+ reason: `retired or unsupported provider config "${config.agent}" is excluded from profile apply`
362
+ });
363
+ }
364
+ return false;
365
+ });
366
+ const renderSafeConfigs = activeConfigs.filter((config) => {
367
+ const behavior = canonicalConfigApplyBehavior(config, opts, activeConfigs);
368
+ const targets = [
369
+ ...behavior.primary ? [{ path: behavior.primary.path, content: behavior.primary.content }] : [],
370
+ ...behavior.outputs.map((output) => ({ path: output.path, content: output.content }))
371
+ ];
372
+ const blocked = [...new Set(targets.flatMap((target) => wouldDestroyACredential(target.path, target.content, config.format)))].sort();
373
+ if (blocked.length === 0)
374
+ return true;
375
+ for (const target of targets) {
376
+ skipped.push({
377
+ config_id: config.id,
378
+ config_slug: config.slug,
379
+ path: target.path,
380
+ owner: "unresolved-secret-placeholder",
381
+ reason: `no value for ${blocked.map((name) => `{{${name}}}`).join(", ")} and the file holds something else there; writing the placeholder would overwrite a live credential`
382
+ });
383
+ }
384
+ return false;
385
+ });
386
+ const { configs: deduplicated, duplicates } = deduplicateEquivalentProfileConfigs(renderSafeConfigs, opts);
387
+ for (const duplicate of duplicates) {
388
+ for (const target of configTargets(duplicate, opts, activeConfigs)) {
389
+ skipped.push({
390
+ config_id: duplicate.id,
391
+ config_slug: duplicate.slug,
392
+ path: target.path,
393
+ owner: sessionRendererOwnsCanonicalTarget(target.path, opts) ? SESSION_RENDERER_OWNER_ID : "equivalent-profile-config",
394
+ reason: sessionRendererOwnsCanonicalTarget(target.path, opts) ? "provider instruction entrypoint is owned by the Instructions session renderer" : "equivalent profile config is superseded by the newer identical source"
395
+ });
396
+ }
397
+ }
398
+ const prepared = deduplicated.flatMap((config) => {
399
+ const behavior = canonicalConfigApplyBehavior(config, opts, activeConfigs);
400
+ const primaryOwned = behavior.primary ? sessionRendererOwnsCanonicalTarget(behavior.primary.path, opts) : false;
401
+ const outputs = config.outputs.filter((output, sourceIndex) => {
402
+ const canonicalOutput = behavior.outputs.find((candidate) => candidate.sourceIndex === sourceIndex);
403
+ const retiredOutput = isRetiredOrUnsupportedConfigAgent(output.agent);
404
+ const sessionOwned = sessionRendererOwnsCanonicalTarget(canonicalOutput.path, opts);
405
+ if (!retiredOutput && !sessionOwned)
406
+ return true;
407
+ skipped.push({
408
+ config_id: config.id,
409
+ config_slug: config.slug,
410
+ path: canonicalOutput.path,
411
+ owner: retiredOutput ? "retired-provider-config" : SESSION_RENDERER_OWNER_ID,
412
+ reason: retiredOutput ? `retired or unsupported provider output "${output.agent}" is excluded from profile apply` : output.agent === "antigravity" ? "project-scoped Antigravity rules are owned by the Instructions session renderer" : "provider instruction entrypoint is owned by the Instructions session renderer"
413
+ });
414
+ return false;
415
+ });
416
+ if (primaryOwned && config.target_path) {
417
+ skipped.push({
418
+ config_id: config.id,
419
+ config_slug: config.slug,
420
+ path: behavior.primary.path,
421
+ owner: SESSION_RENDERER_OWNER_ID,
422
+ reason: "provider instruction entrypoint is owned by the Instructions session renderer"
423
+ });
424
+ }
425
+ if (primaryOwned && outputs.length === 0)
426
+ return [];
427
+ if (!primaryOwned && outputs.length === config.outputs.length)
428
+ return [config];
429
+ return [{
430
+ ...config,
431
+ target_path: primaryOwned ? null : config.target_path,
432
+ outputs
433
+ }];
434
+ });
435
+ const failures = duplicateTargetFailures(prepared, opts);
436
+ return { configs: prepared, skipped, failures };
437
+ }
438
+ function deduplicateEquivalentProfileConfigs(configs, opts) {
439
+ const groups = new Map;
440
+ const withoutTargets = [];
441
+ for (const config of configs) {
442
+ const behavior = canonicalConfigApplyBehavior(config, opts, configs);
443
+ if (!behavior.primary && behavior.outputs.length === 0) {
444
+ withoutTargets.push(config);
445
+ continue;
446
+ }
447
+ groups.set(behavior.equivalenceKey, [
448
+ ...groups.get(behavior.equivalenceKey) ?? [],
449
+ config
450
+ ]);
451
+ }
452
+ const kept = [...withoutTargets];
453
+ const duplicates = [];
454
+ for (const group of groups.values()) {
455
+ const ordered = [...group].sort((left, right) => right.updated_at.localeCompare(left.updated_at) || left.slug.localeCompare(right.slug));
456
+ kept.push(ordered[0]);
457
+ duplicates.push(...ordered.slice(1));
458
+ }
459
+ const order = new Map(configs.map((config, index) => [config.id, index]));
460
+ kept.sort((left, right) => (order.get(left.id) ?? 0) - (order.get(right.id) ?? 0));
461
+ return { configs: kept, duplicates };
462
+ }
463
+ function canonicalConfigApplyBehavior(config, opts, contextConfigs) {
464
+ const primary = config.target_path ? {
465
+ path: canonicalApplyTargetPath(config.target_path, opts),
466
+ agent: config.agent,
467
+ content: canonicalApplyContent(config.content, opts)
468
+ } : null;
469
+ const outputs = config.outputs.map((output, sourceIndex) => ({
470
+ sourceIndex,
471
+ path: canonicalApplyTargetPath(output.target_path, opts),
472
+ agent: output.agent,
473
+ transform: output.transform,
474
+ content: canonicalApplyContent(applyTransform(config, output, { configs: contextConfigs }), opts)
475
+ })).sort((left, right) => left.path.localeCompare(right.path) || left.agent.localeCompare(right.agent) || left.transform.localeCompare(right.transform) || left.content.localeCompare(right.content));
476
+ const equivalenceKey = JSON.stringify({
477
+ kind: config.kind,
478
+ category: config.category,
479
+ primary,
480
+ outputs: outputs.map(({ sourceIndex: _sourceIndex, ...output }) => output)
481
+ });
482
+ return { primary, outputs, equivalenceKey };
483
+ }
484
+ function configTargets(config, opts, contextConfigs) {
485
+ const behavior = canonicalConfigApplyBehavior(config, opts, contextConfigs);
486
+ return [
487
+ ...behavior.primary ? [{ path: behavior.primary.path, owner: `${config.slug}:primary` }] : [],
488
+ ...behavior.outputs.map((output) => ({
489
+ path: output.path,
490
+ owner: `${config.slug}:output:${output.agent}`
491
+ }))
492
+ ];
493
+ }
494
+ function duplicateTargetFailures(configs, opts) {
495
+ const targets = new Map;
496
+ for (const config of configs) {
497
+ for (const target of configTargets(config, opts, configs)) {
498
+ targets.set(target.path, [
499
+ ...targets.get(target.path) ?? [],
500
+ { config, owner: target.owner }
501
+ ]);
502
+ }
503
+ }
504
+ return [...targets.entries()].filter(([, owners]) => owners.length > 1).map(([path, owners]) => ({
505
+ config_id: owners[0].config.id,
506
+ config_slug: owners[0].config.slug,
507
+ message: `Multiple profile writers target ${path}: ${owners.map((owner) => owner.owner).join(", ")}`
508
+ }));
509
+ }
510
+ function canonicalApplyContent(content, opts) {
511
+ return opts.vars ? renderMachineAwareContentPreview(content, opts.vars).content : content;
512
+ }
513
+ function canonicalApplyTargetPath(targetPath, opts) {
514
+ const renderedTargetPath = opts.vars ? renderMachineAwareContentPreview(targetPath, opts.vars).content : targetPath;
515
+ return normalizeTargetPath(renderedTargetPath);
516
+ }
517
+ function sessionRendererOwnsTarget(targetPath, opts) {
518
+ return sessionRendererOwnsCanonicalTarget(canonicalApplyTargetPath(targetPath, opts), opts);
519
+ }
520
+ function sessionRendererOwnsCanonicalTarget(normalized, opts) {
521
+ if (opts.allowSessionRendererOwned)
522
+ return false;
523
+ const homes = new Set([
524
+ getConfigHome(),
525
+ opts.vars?.["HOME_DIR"]
526
+ ].filter((home) => typeof home === "string" && home.length > 0));
527
+ if ([...homes].some((home) => SESSION_RENDER_OWNED_CONFIG_TARGETS.some((relativePath) => normalized === normalizeTargetPath(join2(home, ...relativePath.split("/"))))))
528
+ return true;
529
+ return sessionRenderOwnsPath(normalized);
530
+ }
531
+
532
+ export { getConfigHome, expandPath, compactPathForConfigHome, normalizeTargetPath, applyConfig, applyConfigs, applyConfigsWithReport, previewConfigs };