@astrale-os/cli 1.0.0-beta.3 → 1.0.0-beta.30

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 (343) hide show
  1. package/README.md +80 -6
  2. package/dist/astrale.js +55471 -58674
  3. package/dist/public/connect-core.js +2158 -30706
  4. package/dist/public/keys/index.js +1016 -29541
  5. package/dist/public/paths/index.js +370 -28654
  6. package/dist/types/admin/contract.d.ts +26 -0
  7. package/dist/types/admin/instance/client.d.ts +20 -0
  8. package/dist/types/admin/instance/index.d.ts +2 -0
  9. package/dist/types/admin/instance/model.d.ts +6 -10
  10. package/dist/types/connection/auth.d.ts +3 -0
  11. package/dist/types/connection/call.d.ts +3 -0
  12. package/dist/types/connection/command.d.ts +27 -0
  13. package/dist/types/connection/credential.d.ts +14 -0
  14. package/dist/types/connection/errors.d.ts +1 -0
  15. package/dist/types/connection/exchange.d.ts +9 -0
  16. package/dist/types/connection/failure/classify.d.ts +2 -0
  17. package/dist/types/connection/failure/index.d.ts +5 -0
  18. package/dist/types/connection/failure/model.d.ts +25 -0
  19. package/dist/types/connection/failure/render.d.ts +3 -0
  20. package/dist/types/connection/index.d.ts +8 -0
  21. package/dist/types/connection/reasons.d.ts +37 -0
  22. package/dist/types/connection/self.d.ts +37 -0
  23. package/dist/types/connection/session.d.ts +31 -0
  24. package/dist/types/connection/target.d.ts +38 -0
  25. package/dist/types/errors.d.ts +1 -1
  26. package/dist/types/lib/admin-instance.d.ts +17 -0
  27. package/dist/types/lib/admin-target.d.ts +11 -36
  28. package/dist/types/lib/config.d.ts +13 -59
  29. package/dist/types/lib/failure-debug.d.ts +1 -0
  30. package/dist/types/lib/idp.d.ts +25 -173
  31. package/dist/types/lib/instance-target.d.ts +1 -1
  32. package/dist/types/lib/instance.d.ts +30 -88
  33. package/dist/types/lib/log.d.ts +5 -3
  34. package/dist/types/lib/output.d.ts +1 -1
  35. package/dist/types/lib/proc.d.ts +43 -0
  36. package/dist/types/lib/self.d.ts +9 -0
  37. package/dist/types/lib/update.d.ts +109 -0
  38. package/dist/types/lib/validation.d.ts +4 -1
  39. package/dist/types/state/exchange-credentials.d.ts +6 -2
  40. package/dist/types/state/files.d.ts +2 -0
  41. package/dist/types/state/index.d.ts +3 -2
  42. package/dist/types/state/paths.d.ts +2 -0
  43. package/dist/types/state/session-routes.d.ts +10 -0
  44. package/package.json +16 -19
  45. package/src/__tests__/fixtures/publication.ts +20 -0
  46. package/src/admin/.spec/architecture.md +12 -5
  47. package/src/admin/__tests__/fixture.ts +25 -0
  48. package/src/admin/catalog/.spec/api.d.ts +1 -3
  49. package/src/admin/catalog/.spec/architecture.md +5 -4
  50. package/src/admin/catalog/__tests__/client.test.ts +143 -69
  51. package/src/admin/catalog/client.ts +40 -54
  52. package/src/admin/catalog/model.ts +3 -4
  53. package/src/admin/contract.ts +47 -0
  54. package/src/admin/graph/.spec/api.d.ts +4 -10
  55. package/src/admin/graph/nodes.ts +1 -1
  56. package/src/admin/instance/.spec/api.d.ts +5 -9
  57. package/src/admin/instance/.spec/architecture.md +7 -7
  58. package/src/admin/instance/__tests__/client.test.ts +157 -175
  59. package/src/admin/instance/client.ts +39 -128
  60. package/src/admin/instance/index.ts +1 -2
  61. package/src/admin/instance/model.ts +12 -18
  62. package/src/commands/__tests__/admin-instance.test.ts +11 -8
  63. package/src/commands/__tests__/call-describe.test.ts +46 -33
  64. package/src/commands/__tests__/call.test.ts +34 -0
  65. package/src/commands/__tests__/domain-install-operation.test.ts +30 -22
  66. package/src/commands/__tests__/domain-install-owned.test.ts +1 -1
  67. package/src/commands/__tests__/domain-list.test.ts +5 -25
  68. package/src/commands/__tests__/install-direct.test.ts +115 -8
  69. package/src/commands/__tests__/install-identity-override.test.ts +6 -17
  70. package/src/commands/__tests__/instance-list-rows.test.ts +1 -1
  71. package/src/commands/__tests__/instance-status.test.ts +139 -0
  72. package/src/commands/__tests__/introspect-parse.test.ts +80 -1
  73. package/src/commands/__tests__/logs.test.ts +250 -2
  74. package/src/commands/__tests__/read-commands.test.ts +118 -10
  75. package/src/commands/__tests__/token-ttl.test.ts +49 -4
  76. package/src/commands/__tests__/update.test.ts +25 -3
  77. package/src/commands/__tests__/view.test.ts +50 -2
  78. package/src/commands/auth/logout.ts +2 -1
  79. package/src/commands/browser.ts +29 -0
  80. package/src/commands/call-describe.ts +60 -68
  81. package/src/commands/call.ts +71 -59
  82. package/src/commands/domain/install.ts +73 -46
  83. package/src/commands/domain/list.ts +1 -1
  84. package/src/commands/domain/publish.ts +14 -11
  85. package/src/commands/domain/uninstall.ts +2 -2
  86. package/src/commands/get.ts +15 -16
  87. package/src/commands/identity/__tests__/register.test.ts +3 -3
  88. package/src/commands/identity/register.ts +8 -8
  89. package/src/commands/instance/create.ts +8 -16
  90. package/src/commands/instance/delete.ts +12 -9
  91. package/src/commands/instance/list.ts +2 -2
  92. package/src/commands/instance/status.ts +66 -20
  93. package/src/commands/instance/use.ts +16 -12
  94. package/src/commands/introspect.ts +53 -41
  95. package/src/commands/logs.ts +123 -36
  96. package/src/commands/mutate.ts +6 -5
  97. package/src/commands/query.ts +35 -32
  98. package/src/commands/session/analyze.ts +26 -4
  99. package/src/commands/token.ts +42 -27
  100. package/src/commands/ui/__tests__/commands.test.ts +152 -0
  101. package/src/commands/ui/add.ts +51 -0
  102. package/src/commands/ui/doctor.ts +21 -0
  103. package/src/commands/ui/init.ts +38 -0
  104. package/src/commands/ui/list.ts +26 -0
  105. package/src/commands/ui/preset-apply.ts +19 -0
  106. package/src/commands/ui/preset-list.ts +12 -0
  107. package/src/commands/ui/shared.ts +25 -0
  108. package/src/commands/update.ts +89 -48
  109. package/src/commands/view.ts +82 -37
  110. package/src/connection/.spec/api.d.ts +7 -8
  111. package/src/connection/.spec/architecture.md +14 -5
  112. package/src/connection/.spec/flows/session.ts +2 -2
  113. package/src/connection/.spec/laws/connection.ts +6 -2
  114. package/src/connection/.spec/layout.ts +1 -0
  115. package/src/connection/__tests__/auth.test.ts +1 -0
  116. package/src/connection/__tests__/credential.test.ts +21 -1
  117. package/src/connection/__tests__/errors.test.ts +27 -20
  118. package/src/connection/__tests__/exchange.test.ts +64 -11
  119. package/src/connection/__tests__/failure-fixtures.ts +39 -0
  120. package/src/connection/__tests__/failure-safety.test.ts +75 -0
  121. package/src/connection/__tests__/self.test.ts +31 -11
  122. package/src/connection/__tests__/session.test.ts +8 -4
  123. package/src/connection/__tests__/target.test.ts +2 -0
  124. package/src/connection/auth.ts +13 -0
  125. package/src/connection/call.ts +1 -1
  126. package/src/connection/credential.ts +2 -2
  127. package/src/connection/errors.ts +1 -355
  128. package/src/connection/exchange.ts +110 -61
  129. package/src/connection/failure/classify.ts +110 -0
  130. package/src/connection/failure/index.ts +18 -0
  131. package/src/connection/failure/model.ts +28 -0
  132. package/src/connection/failure/render.ts +116 -0
  133. package/src/connection/reasons.ts +16 -0
  134. package/src/connection/self.ts +39 -21
  135. package/src/connection/session.ts +27 -9
  136. package/src/errors.ts +3 -2
  137. package/src/graph/.spec/api.d.ts +12 -5
  138. package/src/graph/.spec/layout.ts +9 -1
  139. package/src/graph/__tests__/mutation.test.ts +2 -2
  140. package/src/graph/__tests__/query.test.ts +25 -6
  141. package/src/graph/class.ts +30 -0
  142. package/src/graph/index.ts +1 -0
  143. package/src/graph/query.ts +21 -32
  144. package/src/identity/.spec/api.d.ts +2 -2
  145. package/src/identity/__tests__/fixtures/registry-journey.ts +13 -1
  146. package/src/identity/__tests__/registration.test.ts +1 -1
  147. package/src/identity/__tests__/registry.test.ts +4 -0
  148. package/src/identity/registration.ts +3 -3
  149. package/src/identity/registry.ts +2 -0
  150. package/src/keys/__tests__/keys.test.ts +4 -0
  151. package/src/keys/credential.ts +1 -0
  152. package/src/lib/__tests__/admin-target.test.ts +12 -0
  153. package/src/lib/__tests__/binary.test.ts +16 -1
  154. package/src/lib/__tests__/browser-retention.test.ts +212 -0
  155. package/src/lib/__tests__/command-dx.test.ts +1 -1
  156. package/src/lib/__tests__/config.test.ts +27 -0
  157. package/src/lib/__tests__/domain-publication.test.ts +10 -16
  158. package/src/lib/__tests__/idp.test.ts +34 -4
  159. package/src/lib/__tests__/instance-candidates.test.ts +1 -3
  160. package/src/lib/__tests__/instance-target.test.ts +7 -39
  161. package/src/lib/__tests__/log-errors.test.ts +64 -0
  162. package/src/lib/__tests__/skills.test.ts +809 -0
  163. package/src/lib/__tests__/studio-server-deps.test.ts +1 -1
  164. package/src/lib/__tests__/update.test.ts +264 -11
  165. package/src/lib/__tests__/view-assets.test.ts +25 -0
  166. package/src/lib/__tests__/view-external-open-intent.test.ts +150 -0
  167. package/src/lib/__tests__/view-external-open-origins.test.ts +27 -0
  168. package/src/lib/__tests__/view-open-intent.test.ts +0 -2
  169. package/src/lib/__tests__/view-server.test.ts +26 -3
  170. package/src/lib/__tests__/view-session.test.ts +2 -1
  171. package/src/lib/admin-instance.ts +14 -8
  172. package/src/lib/admin-target.ts +21 -2
  173. package/src/lib/binary.ts +22 -5
  174. package/src/lib/browser-retention.ts +210 -0
  175. package/src/lib/command-dx.ts +9 -9
  176. package/src/lib/config.ts +12 -1
  177. package/src/lib/domain-publication.ts +9 -7
  178. package/src/lib/failure-debug.ts +26 -0
  179. package/src/lib/idp.ts +34 -3
  180. package/src/lib/instance-candidates.ts +2 -2
  181. package/src/lib/instance-target.ts +3 -14
  182. package/src/lib/instance.ts +16 -11
  183. package/src/lib/log.ts +16 -9
  184. package/src/lib/output.ts +1 -1
  185. package/src/lib/proc.ts +7 -2
  186. package/src/lib/provision-instance.ts +34 -57
  187. package/src/lib/skills/lock.ts +117 -0
  188. package/src/lib/skills/sync.ts +814 -0
  189. package/src/lib/skills.ts +1 -52
  190. package/src/lib/update.ts +298 -45
  191. package/src/lib/validation.ts +2 -2
  192. package/src/lib/view/assets.ts +11 -2
  193. package/src/lib/view/external-open-intent.ts +41 -0
  194. package/src/lib/view/external-open-origins.ts +37 -0
  195. package/src/lib/view/host-capabilities.ts +17 -0
  196. package/src/lib/view/resolve.ts +1 -1
  197. package/src/lib/view/server.ts +18 -3
  198. package/src/lib/view/session.ts +2 -0
  199. package/src/program/.spec/api.d.ts +1 -0
  200. package/src/program/__tests__/program.test.ts +163 -6
  201. package/src/program/argv.ts +14 -0
  202. package/src/program/build.ts +26 -4
  203. package/src/program/command.ts +1 -0
  204. package/src/program/index.ts +1 -0
  205. package/src/program/registry.ts +2 -1
  206. package/src/setup/__tests__/instance-step.test.ts +27 -10
  207. package/src/setup/steps/instance.ts +22 -15
  208. package/src/setup/steps/skills.ts +40 -38
  209. package/src/state/.spec/api.d.ts +21 -2
  210. package/src/state/.spec/architecture.md +18 -4
  211. package/src/state/.spec/layout.ts +1 -0
  212. package/src/state/__tests__/exchange-credentials.test.ts +88 -42
  213. package/src/state/__tests__/files.test.ts +24 -1
  214. package/src/state/__tests__/fixtures/session-route-process.ts +93 -0
  215. package/src/state/__tests__/paths.test.ts +1 -0
  216. package/src/state/__tests__/session-routes.test.ts +138 -0
  217. package/src/state/exchange-credentials.ts +22 -9
  218. package/src/state/files.ts +41 -0
  219. package/src/state/index.ts +3 -1
  220. package/src/state/paths.ts +3 -0
  221. package/src/state/session-routes.ts +34 -0
  222. package/src/telemetry/__tests__/analyze-log.test.ts +38 -0
  223. package/src/telemetry/__tests__/recorder.test.ts +1 -0
  224. package/src/telemetry/__tests__/retention.test.ts +267 -0
  225. package/src/telemetry/__tests__/settings.test.ts +102 -0
  226. package/src/telemetry/__tests__/store-scan.test.ts +128 -0
  227. package/src/telemetry/__tests__/trigger.test.ts +33 -4
  228. package/src/telemetry/analyze.ts +24 -2
  229. package/src/telemetry/recorder.ts +15 -4
  230. package/src/telemetry/retention.ts +176 -0
  231. package/src/telemetry/session.ts +18 -12
  232. package/src/telemetry/settings.ts +64 -11
  233. package/src/telemetry/store.ts +92 -9
  234. package/src/telemetry/trigger.ts +16 -28
  235. package/src/ui/.spec/api.d.ts +14 -0
  236. package/src/ui/.spec/architecture.md +14 -0
  237. package/src/ui/.spec/laws.ts +50 -0
  238. package/src/ui/.spec/layout.ts +16 -0
  239. package/src/ui/__tests__/ui.test.ts +1742 -0
  240. package/src/ui/index.ts +13 -0
  241. package/src/ui/lock.ts +89 -0
  242. package/src/ui/model.ts +83 -0
  243. package/src/ui/operations.ts +1044 -0
  244. package/src/ui/project.ts +333 -0
  245. package/src/ui/release.ts +398 -0
  246. package/src/ui/runner.ts +18 -0
  247. package/studio/client/dist/assets/elk-api-DjmKsHXc.js +1 -0
  248. package/studio/client/dist/assets/index-BFVFs_8x.js +81 -0
  249. package/studio/client/dist/assets/index-DuB9iUdu.css +2 -0
  250. package/studio/client/dist/assets/rolldown-runtime-Dd_uD5pT.js +1 -0
  251. package/studio/client/dist/assets/schema-studio--a0kX3QU.css +1 -0
  252. package/studio/client/dist/assets/schema-studio-DH6oEWME.js +8 -0
  253. package/studio/client/dist/index.html +4 -3
  254. package/studio/package.json +8 -14
  255. package/studio/server/agent/ask.test.ts +1 -1
  256. package/studio/server/agent/bridge/grant.test.ts +1 -1
  257. package/studio/server/agent/bridge/routes.test.ts +1 -1
  258. package/studio/server/agent/harness/claude/adapter.test.ts +15 -5
  259. package/studio/server/agent/harness/gateway/token.test.ts +1 -1
  260. package/studio/server/agent/harness/gateway/token.ts +3 -3
  261. package/studio/server/agent/prompts/anchors.test.ts +41 -32
  262. package/studio/server/agent/prompts/anchors.ts +23 -51
  263. package/studio/server/agent/prompts/system.test.ts +4 -4
  264. package/studio/server/agent/prompts/system.ts +5 -5
  265. package/studio/server/agent/routes.test.ts +1 -1
  266. package/studio/server/agent/run/coordinator.test.ts +1 -1
  267. package/studio/server/agent/run/preparation.ts +1 -1
  268. package/studio/server/api/canvas.ts +0 -1
  269. package/studio/server/api/context.ts +1 -1
  270. package/studio/server/api/deployment.ts +1 -1
  271. package/studio/server/api/views.ts +2 -2
  272. package/studio/server/api/workspace.ts +1 -1
  273. package/studio/server/api-agent-loadout.test.ts +1 -1
  274. package/studio/server/api.test.ts +1 -1
  275. package/studio/server/cache.test.ts +24 -18
  276. package/studio/server/cache.ts +10 -54
  277. package/studio/server/cli-consumers.test.ts +31 -3
  278. package/studio/server/domain.test.ts +50 -68
  279. package/studio/server/domain.ts +82 -63
  280. package/studio/server/handoff/copy.ts +2 -2
  281. package/studio/server/index.ts +1 -1
  282. package/studio/server/instances/probe.test.ts +1 -1
  283. package/studio/server/introspect/anatomy/views/routes.ts +46 -37
  284. package/studio/server/introspect/anatomy/views.ts +10 -16
  285. package/studio/server/introspect/anatomy-extras.test.ts +29 -56
  286. package/studio/server/introspect/anatomy.test.ts +22 -14
  287. package/studio/server/introspect/anatomy.ts +6 -9
  288. package/studio/server/introspect/bundle.ts +0 -3
  289. package/studio/server/introspect/canonical-schema.test.ts +155 -424
  290. package/studio/server/introspect/canonical-schema.ts +248 -601
  291. package/studio/server/introspect/core.ts +14 -22
  292. package/studio/server/introspect/diff.test.ts +21 -9
  293. package/studio/server/introspect/diff.ts +19 -64
  294. package/studio/server/introspect/extractor.ts +23 -122
  295. package/studio/server/introspect/overlay-tsmorph.test.ts +116 -241
  296. package/studio/server/introspect/overlay-tsmorph.ts +0 -1
  297. package/studio/server/introspect/overlay.ts +3 -51
  298. package/studio/server/introspect/revision.test.ts +24 -28
  299. package/studio/server/introspect/revision.ts +11 -22
  300. package/studio/server/introspect/runtime.test.ts +77 -195
  301. package/studio/server/introspect/runtime.ts +5 -67
  302. package/studio/server/introspect/schema-ir-json.test.ts +81 -0
  303. package/studio/server/introspect/schema-ir-json.ts +39 -69
  304. package/studio/server/introspect/schema-refs.test.ts +43 -88
  305. package/studio/server/introspect/schema-refs.ts +14 -49
  306. package/studio/server/introspect/source-overlay/handlers.ts +116 -636
  307. package/studio/server/introspect/source-overlay/kernel-calls.ts +0 -3
  308. package/studio/server/introspect/source-overlay/spans.ts +15 -45
  309. package/studio/server/lifecycle.ts +4 -1
  310. package/studio/server/state/baseline.test.ts +14 -9
  311. package/studio/server/state/baseline.ts +3 -5
  312. package/studio/server/state/documents.test.ts +69 -0
  313. package/studio/server/state/documents.ts +57 -10
  314. package/studio/server/state/visibility.ts +1 -5
  315. package/studio/server/views/model.ts +3 -3
  316. package/studio/server/views/target.test.ts +18 -76
  317. package/studio/server/views/target.ts +24 -50
  318. package/studio/server/watch.test.ts +11 -11
  319. package/studio/server/watch.ts +8 -4
  320. package/studio/server/workspace/updates.ts +23 -1
  321. package/studio/server/workspace-watch.ts +2 -2
  322. package/studio/shared/contracts/runtime.ts +4 -0
  323. package/studio/shared/contracts/schema.ts +44 -131
  324. package/studio/shared/contracts/surface.test.ts +15 -17
  325. package/studio/shared/contracts/workspace.ts +5 -11
  326. package/studio/shared/schema/identity.test.ts +20 -44
  327. package/studio/shared/schema/identity.ts +9 -24
  328. package/studio/tsconfig.json +2 -1
  329. package/tsconfig.json +1 -1
  330. package/viewer/dist/index.html +21 -0
  331. package/viewer/dist/main.js +41 -62
  332. package/.check-workspace.cjs +0 -40
  333. package/src/admin/binding.ts +0 -168
  334. package/src/commands/__tests__/instance-create-hosts.test.ts +0 -29
  335. package/studio/client/dist/assets/elk-api-lwhFo7vB.js +0 -1
  336. package/studio/client/dist/assets/index-B-c-smo9.js +0 -8
  337. package/studio/client/dist/assets/index-BckHuAWk.js +0 -81
  338. package/studio/client/dist/assets/index-C4aNQ6dz.css +0 -1
  339. package/studio/client/dist/assets/index-ChOr3yP0.css +0 -1
  340. package/studio/server/introspect/anatomy/views/legacy.ts +0 -232
  341. package/studio/server/introspect/core-extractor.ts +0 -139
  342. package/studio/server/introspect/overlay.test.ts +0 -72
  343. package/studio/server/introspect/source-overlay/annotations.ts +0 -14
@@ -1,8 +1,9 @@
1
1
  /** Structural admission for persisted Studio render IR. SDK admission is separate. */
2
2
 
3
3
  import type {
4
+ IrClass,
5
+ IrClassRef,
4
6
  IrFunction,
5
- IrInterface,
6
7
  IrMethod,
7
8
  IrSchemaRef,
8
9
  JsonSchema,
@@ -11,10 +12,6 @@ import type {
11
12
 
12
13
  import { asJsonRecord, asStringArray } from '../json'
13
14
 
14
- function optional<T>(value: unknown, guard: (candidate: unknown) => candidate is T): boolean {
15
- return value === undefined || guard(value)
16
- }
17
-
18
15
  function recordOf(value: unknown, guard: (candidate: unknown) => boolean): boolean {
19
16
  const record = asJsonRecord(value)
20
17
  return !!record && Object.values(record).every(guard)
@@ -29,14 +26,12 @@ function isSchemaRef(value: unknown): value is IrSchemaRef {
29
26
  return (
30
27
  typeof record?.origin === 'string' &&
31
28
  typeof record.name === 'string' &&
32
- ['type', 'interface', 'class', 'function', 'policy', 'view', 'core'].includes(
33
- String(record.kind),
34
- )
29
+ ['class', 'function', 'policy', 'view', 'core'].includes(String(record.kind))
35
30
  )
36
31
  }
37
32
 
38
- function isSchemaRefArray(value: unknown): value is IrSchemaRef[] {
39
- return Array.isArray(value) && value.every(isSchemaRef)
33
+ function isClassRef(value: unknown): value is IrClassRef {
34
+ return isSchemaRef(value) && value.kind === 'class'
40
35
  }
41
36
 
42
37
  function isOutput(value: unknown): boolean {
@@ -52,20 +47,22 @@ function isMethod(value: unknown): value is IrMethod {
52
47
  const record = asJsonRecord(value)
53
48
  return (
54
49
  typeof record?.name === 'string' &&
55
- recordOf(record.params, isJsonSchema) &&
56
- isJsonSchema(record.returns) &&
50
+ isJsonSchema(record.input) &&
51
+ isOutput(record.output) &&
57
52
  typeof record.static === 'boolean' &&
58
- ['default', 'abstract', 'sealed'].includes(String(record.inheritance)) &&
59
- optional(record.input, isJsonSchema) &&
60
- (record.requiredParams === undefined || asStringArray(record.requiredParams) !== undefined) &&
61
- (record.output === undefined || isOutput(record.output))
53
+ ['default', 'abstract', 'sealed'].includes(String(record.inheritance))
62
54
  )
63
55
  }
64
56
 
65
57
  function isEndpoint(value: unknown): boolean {
66
58
  const record = asJsonRecord(value)
67
59
  if (!record || typeof record.name !== 'string' || !asStringArray(record.types)) return false
68
- if (record.refs !== undefined && !isSchemaRefArray(record.refs)) return false
60
+ if (
61
+ record.refs !== undefined &&
62
+ (!Array.isArray(record.refs) || !record.refs.every(isSchemaRef))
63
+ ) {
64
+ return false
65
+ }
69
66
  if (record.cardinality !== undefined) {
70
67
  const cardinality = asJsonRecord(record.cardinality)
71
68
  if (
@@ -81,31 +78,19 @@ function isEndpoint(value: unknown): boolean {
81
78
  return true
82
79
  }
83
80
 
84
- function isInterface(value: unknown): value is IrInterface {
85
- const record = asJsonRecord(value)
86
- return (
87
- record?.type === 'interface' &&
88
- typeof record.name === 'string' &&
89
- recordOf(record.properties, isJsonSchema) &&
90
- recordOf(record.methods, isMethod) &&
91
- (record.required === undefined || asStringArray(record.required) !== undefined) &&
92
- (record.extends === undefined || asStringArray(record.extends) !== undefined) &&
93
- (record.extendsRefs === undefined || isSchemaRefArray(record.extendsRefs)) &&
94
- (record.endpoints === undefined ||
95
- (Array.isArray(record.endpoints) && record.endpoints.every(isEndpoint)))
96
- )
97
- }
98
-
99
- function isClass(value: unknown): boolean {
81
+ function isClass(value: unknown): value is IrClass {
100
82
  const record = asJsonRecord(value)
101
83
  return (
102
84
  (record?.type === 'node' || record?.type === 'edge') &&
103
85
  typeof record.name === 'string' &&
86
+ typeof record.origin === 'string' &&
87
+ isClassRef(record.ref) &&
104
88
  recordOf(record.properties, isJsonSchema) &&
105
89
  recordOf(record.methods, isMethod) &&
106
90
  (record.required === undefined || asStringArray(record.required) !== undefined) &&
107
- (record.implements === undefined || asStringArray(record.implements) !== undefined) &&
108
- (record.implementsRefs === undefined || isSchemaRefArray(record.implementsRefs)) &&
91
+ (record.extends === undefined || asStringArray(record.extends) !== undefined) &&
92
+ (record.extendsRefs === undefined ||
93
+ (Array.isArray(record.extendsRefs) && record.extendsRefs.every(isClassRef))) &&
109
94
  (record.endpoints === undefined ||
110
95
  (Array.isArray(record.endpoints) && record.endpoints.every(isEndpoint)))
111
96
  )
@@ -113,24 +98,16 @@ function isClass(value: unknown): boolean {
113
98
 
114
99
  function isFunction(value: unknown): value is IrFunction {
115
100
  const record = asJsonRecord(value)
116
- return (
117
- typeof record?.name === 'string' &&
118
- isJsonSchema(record.input) &&
119
- recordOf(record.params, isJsonSchema) &&
120
- (record.requiredParams === undefined || asStringArray(record.requiredParams) !== undefined) &&
121
- isOutput(record.output) &&
122
- isJsonSchema(record.returns) &&
123
- record.static === true &&
124
- record.inheritance === 'default'
125
- )
101
+ return typeof record?.name === 'string' && isJsonSchema(record.input) && isOutput(record.output)
126
102
  }
127
103
 
128
104
  function isImport(value: unknown): boolean {
129
105
  const record = asJsonRecord(value)
130
106
  return (
131
107
  typeof record?.origin === 'string' &&
132
- (record.definition === 'class' || record.definition === 'interface') &&
133
- optional(record.ref, isSchemaRef)
108
+ isClassRef(record.ref) &&
109
+ typeof record.key === 'string' &&
110
+ record.key === `${record.ref.origin}:class.${record.ref.name}`
134
111
  )
135
112
  }
136
113
 
@@ -139,10 +116,12 @@ function isView(value: unknown): boolean {
139
116
  const target = asJsonRecord(record?.target)
140
117
  return (
141
118
  typeof record?.name === 'string' &&
142
- ['required', 'optional', 'public'].includes(String(record.auth)) &&
119
+ record.auth === undefined &&
143
120
  !!target &&
144
121
  (target.kind === 'domain' ||
145
- (target.kind === 'definition' && isSchemaRefArray(target.definitions)))
122
+ (target.kind === 'definition' &&
123
+ Array.isArray(target.definitions) &&
124
+ target.definitions.every(isSchemaRef)))
146
125
  )
147
126
  }
148
127
 
@@ -150,32 +129,23 @@ export function decodeSchemaIR(value: unknown): SchemaIR | undefined {
150
129
  const record = asJsonRecord(value)
151
130
  if (
152
131
  !record ||
132
+ record.format !== 'astrale.dsl' ||
153
133
  typeof record.version !== 'string' ||
154
134
  typeof record.domain !== 'string' ||
155
- !recordOf(record.types, isJsonSchema) ||
156
- !recordOf(record.interfaces, isInterface) ||
157
135
  !recordOf(record.classes, isClass) ||
158
- !recordOf(record.imports, isImport) ||
159
136
  !recordOf(record.functions, isFunction) ||
160
- (record.importsByKey !== undefined && !recordOf(record.importsByKey, isImport)) ||
161
- (record.importedInterfacesByKey !== undefined &&
162
- !recordOf(record.importedInterfacesByKey, isInterface)) ||
163
- (record.views !== undefined && !recordOf(record.views, isView)) ||
164
- (record.policies !== undefined && !asJsonRecord(record.policies)) ||
165
- (record.dependencies !== undefined &&
166
- (!Array.isArray(record.dependencies) ||
167
- !record.dependencies.every((dependency) => {
168
- const item = asJsonRecord(dependency)
169
- return typeof item?.origin === 'string' && typeof item.revision === 'string'
170
- })))
137
+ !recordOf(record.importsByKey, isImport) ||
138
+ !recordOf(record.importedClassesByKey, isClass) ||
139
+ !recordOf(record.views, isView) ||
140
+ !asJsonRecord(record.policies) ||
141
+ !Array.isArray(record.dependencies) ||
142
+ !record.dependencies.every((dependency) => {
143
+ const item = asJsonRecord(dependency)
144
+ return typeof item?.origin === 'string' && typeof item.revision === 'string'
145
+ }) ||
146
+ !('core' in record)
171
147
  ) {
172
148
  return undefined
173
149
  }
174
150
  return record as unknown as SchemaIR
175
151
  }
176
-
177
- export function decodeIrInterfaceRecord(value: unknown): Record<string, IrInterface> | undefined {
178
- const record = asJsonRecord(value)
179
- if (!record || !Object.values(record).every(isInterface)) return undefined
180
- return record as unknown as Record<string, IrInterface>
181
- }
@@ -1,100 +1,55 @@
1
- import { describe, expect, test } from 'bun:test'
1
+ import { expect, test } from 'bun:test'
2
2
 
3
- import type { IrInterface, StudioSchemaBundle } from '../../shared/types'
3
+ import type { StudioSchemaBundle } from '../../shared/types'
4
4
 
5
5
  import { schemaRefs } from './schema-refs'
6
6
 
7
- function importedInterface(
8
- name: string,
9
- origin: string,
10
- properties: string[] = [],
11
- methods: string[] = [],
12
- ): IrInterface {
13
- return {
14
- type: 'interface',
15
- name,
16
- origin,
17
- ref: { origin, kind: 'interface', name },
18
- properties: Object.fromEntries(properties.map((property) => [property, { type: 'string' }])),
19
- methods: Object.fromEntries(
20
- methods.map((method) => [
21
- method,
22
- {
23
- name: method,
24
- params: {},
25
- returns: {},
26
- static: false,
27
- inheritance: 'default',
28
- },
29
- ]),
30
- ),
7
+ test('enumerates local and exact imported Class anchors without collapsing homonyms', () => {
8
+ const method = {
9
+ name: 'rename',
10
+ params: {},
11
+ returns: {},
12
+ static: false,
13
+ inheritance: 'default' as const,
31
14
  }
32
- }
33
-
34
- function bundleWithImports(
35
- exact: NonNullable<StudioSchemaBundle['ir']>['importedInterfacesByKey'],
36
- legacy: Record<string, IrInterface>,
37
- ): StudioSchemaBundle {
38
- return {
15
+ const bundle = {
39
16
  ir: {
17
+ version: 'v1',
40
18
  domain: 'root.example.dev',
41
- interfaces: {},
42
- classes: {},
19
+ classes: {
20
+ Document: {
21
+ type: 'node',
22
+ name: 'Document',
23
+ properties: { title: { type: 'string' } },
24
+ methods: { rename: method },
25
+ },
26
+ },
43
27
  functions: {},
44
- ...(exact === undefined ? {} : { importedInterfacesByKey: exact }),
45
- },
46
- importedInterfaces: legacy,
47
- } as unknown as StudioSchemaBundle
48
- }
49
-
50
- describe('schema refs for imported interfaces', () => {
51
- test('enumerates every exact homonym without selecting a name-keyed winner', () => {
52
- const refs = schemaRefs(
53
- bundleWithImports(
54
- {
55
- 'directory.example.dev:interface.Named': importedInterface(
56
- 'Named',
57
- 'directory.example.dev',
58
- ['directoryName'],
59
- ),
60
- 'people.example.dev:interface.Named': importedInterface(
61
- 'Named',
62
- 'people.example.dev',
63
- [],
64
- ['rename'],
65
- ),
28
+ importsByKey: {},
29
+ importedClassesByKey: {
30
+ 'directory.example.dev:class.Named': {
31
+ type: 'node',
32
+ name: 'Named',
33
+ properties: { directoryName: { type: 'string' } },
34
+ methods: {},
66
35
  },
67
- {
68
- Named: importedInterface('Named', 'legacy.invalid', ['legacyOnly']),
36
+ 'people.example.dev:class.Named': {
37
+ type: 'node',
38
+ name: 'Named',
39
+ properties: {},
40
+ methods: { rename: method },
69
41
  },
70
- ),
71
- )
72
-
73
- expect(refs).toContain('interface.directory.example.dev:interface.Named')
74
- expect(refs).toContain('interface.directory.example.dev:interface.Named.property.directoryName')
75
- expect(refs).toContain('interface.people.example.dev:interface.Named.method.rename')
76
- expect(refs).not.toContain('interface.Named')
77
- expect(refs).not.toContain('interface.Named.property.legacyOnly')
78
- })
79
-
80
- test('uses the name-keyed imported interface only when the exact index is absent', () => {
81
- expect(
82
- schemaRefs(
83
- bundleWithImports(undefined, {
84
- Named: importedInterface('Named', 'legacy.example.dev', ['name']),
85
- }),
86
- ),
87
- ).toEqual(['interface.Named', 'interface.Named.property.name'])
42
+ },
43
+ },
44
+ } as unknown as StudioSchemaBundle
88
45
 
89
- expect(
90
- schemaRefs(
91
- bundleWithImports(
92
- {},
93
- {
94
- Named: importedInterface('Named', 'legacy.example.dev', ['name']),
95
- },
96
- ),
97
- ),
98
- ).toEqual([])
99
- })
46
+ expect(schemaRefs(bundle)).toEqual([
47
+ 'class.Document',
48
+ 'class.Document.property.title',
49
+ 'class.Document.method.rename',
50
+ 'class.directory.example.dev:class.Named',
51
+ 'class.directory.example.dev:class.Named.property.directoryName',
52
+ 'class.people.example.dev:class.Named',
53
+ 'class.people.example.dev:class.Named.method.rename',
54
+ ])
100
55
  })
@@ -1,17 +1,6 @@
1
1
  import type { StudioSchemaBundle } from '../../shared/types'
2
2
 
3
- /**
4
- * schema-refs.ts — enumerate every SCHEMA anchor ref a bundle can target, derived
5
- * from the IR (the authority), NOT from `overlay.sourceSpans`.
6
- *
7
- * Source spans are a best-effort ts-morph source-location index: they cover only
8
- * locally-authored members and only the declaration helpers the parser recognises.
9
- * Using their keys as the set of "valid" targets falsely orphans real, commentable
10
- * targets — most notably INHERITED members surfaced in the detail pane's Inherited
11
- * section (kernel mixins / cross-domain interfaces, e.g. `interface.Named.property.name`),
12
- * which live in another package and so have no local span. This walks the IR
13
- * instead, mirroring exactly the refs the detail pane stamps.
14
- */
3
+ /** Enumerate every schema anchor represented by the admitted render IR. */
15
4
  export function schemaRefs(bundle: StudioSchemaBundle): string[] {
16
5
  const ir = bundle.ir
17
6
  if (!ir) return []
@@ -22,46 +11,22 @@ export function schemaRefs(bundle: StudioSchemaBundle): string[] {
22
11
  methods: Record<string, unknown> | undefined,
23
12
  ) => {
24
13
  refs.add(base)
25
- for (const p of Object.keys(properties ?? {})) refs.add(`${base}.property.${p}`)
26
- for (const m of Object.keys(methods ?? {})) refs.add(`${base}.method.${m}`)
14
+ for (const property of Object.keys(properties ?? {})) refs.add(`${base}.property.${property}`)
15
+ for (const method of Object.keys(methods ?? {})) refs.add(`${base}.method.${method}`)
27
16
  }
28
17
 
29
- for (const [name, iface] of Object.entries(ir.interfaces))
30
- addMember(`interface.${name}`, iface.properties, iface.methods)
31
-
32
- for (const [name, cls] of Object.entries(ir.classes)) {
33
- const ns = cls.type === 'edge' ? 'edge' : 'class'
34
- addMember(`${ns}.${name}`, cls.properties, cls.methods)
35
- if (cls.type === 'edge')
36
- for (const ep of cls.endpoints ?? [])
37
- if (ep.name) refs.add(`edge.${name}.endpoint.${ep.name}`)
38
- }
39
-
40
- for (const name of Object.keys(ir.functions ?? {})) refs.add(`function.${name}`)
41
-
42
- // Imported interfaces (kernel mixins + cross-domain) are rendered — and so are
43
- // commentable — in the Inherited section, keyed under the `interface.` namespace.
44
- // Canonical bundles retain every exact `(origin, kind, name)` identity. Iterate
45
- // all of them: a short-name map must never pick one homonym by traversal order.
46
- // The name-keyed bundle field remains a legacy-only fallback.
47
- if (ir.importedInterfacesByKey !== undefined) {
48
- for (const [key, iface] of Object.entries(ir.importedInterfacesByKey)) {
49
- const anchor = importedInterfaceAnchor(key)
50
- if (anchor) addMember(anchor, iface.properties, iface.methods)
18
+ for (const [name, definition] of Object.entries(ir.classes)) {
19
+ const namespace = definition.type === 'edge' ? 'edge' : 'class'
20
+ addMember(`${namespace}.${name}`, definition.properties, definition.methods)
21
+ if (definition.type === 'edge') {
22
+ for (const endpoint of definition.endpoints ?? []) {
23
+ if (endpoint.name) refs.add(`edge.${name}.endpoint.${endpoint.name}`)
24
+ }
51
25
  }
52
- } else {
53
- for (const [name, iface] of Object.entries(bundle.importedInterfaces ?? {}))
54
- addMember(`interface.${name}`, iface.properties, iface.methods)
55
26
  }
56
-
27
+ for (const name of Object.keys(ir.functions)) refs.add(`function.${name}`)
28
+ for (const [key, definition] of Object.entries(ir.importedClassesByKey)) {
29
+ addMember(`class.${key}`, definition.properties, definition.methods)
30
+ }
57
31
  return [...refs]
58
32
  }
59
-
60
- function importedInterfaceAnchor(key: string): string | null {
61
- const separator = key.lastIndexOf(':')
62
- if (separator <= 0) return null
63
- const ref = key.slice(separator + 1)
64
- if (!ref.startsWith('interface.')) return null
65
- const name = ref.slice('interface.'.length)
66
- return /^[A-Za-z_$][\w$]*$/.test(name) ? `interface.${key}` : null
67
- }