@astrale-os/cli 1.0.0-beta.2 → 1.0.0-beta.20

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 (282) hide show
  1. package/README.md +16 -1
  2. package/dist/astrale.js +51105 -58057
  3. package/dist/public/connect-core.js +2085 -30702
  4. package/dist/public/keys/index.js +884 -29476
  5. package/dist/public/paths/index.js +13101 -41452
  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 +7 -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/package.json +15 -20
  40. package/src/__tests__/fixtures/publication.ts +20 -0
  41. package/src/admin/.spec/architecture.md +12 -5
  42. package/src/admin/__tests__/fixture.ts +25 -0
  43. package/src/admin/catalog/.spec/api.d.ts +1 -3
  44. package/src/admin/catalog/.spec/architecture.md +5 -4
  45. package/src/admin/catalog/__tests__/client.test.ts +143 -69
  46. package/src/admin/catalog/client.ts +40 -54
  47. package/src/admin/catalog/model.ts +3 -4
  48. package/src/admin/contract.ts +46 -0
  49. package/src/admin/graph/.spec/api.d.ts +4 -10
  50. package/src/admin/graph/nodes.ts +1 -1
  51. package/src/admin/instance/.spec/api.d.ts +5 -9
  52. package/src/admin/instance/.spec/architecture.md +7 -7
  53. package/src/admin/instance/__tests__/client.test.ts +157 -175
  54. package/src/admin/instance/client.ts +39 -128
  55. package/src/admin/instance/index.ts +1 -2
  56. package/src/admin/instance/model.ts +12 -18
  57. package/src/commands/__tests__/admin-instance.test.ts +11 -8
  58. package/src/commands/__tests__/call-describe.test.ts +46 -33
  59. package/src/commands/__tests__/call.test.ts +34 -0
  60. package/src/commands/__tests__/domain-install-operation.test.ts +7 -22
  61. package/src/commands/__tests__/domain-install-owned.test.ts +1 -1
  62. package/src/commands/__tests__/domain-list.test.ts +5 -25
  63. package/src/commands/__tests__/install-direct.test.ts +115 -8
  64. package/src/commands/__tests__/install-identity-override.test.ts +3 -14
  65. package/src/commands/__tests__/instance-list-rows.test.ts +1 -1
  66. package/src/commands/__tests__/instance-status.test.ts +139 -0
  67. package/src/commands/__tests__/introspect-parse.test.ts +80 -1
  68. package/src/commands/__tests__/logs.test.ts +250 -2
  69. package/src/commands/__tests__/read-commands.test.ts +62 -10
  70. package/src/commands/__tests__/token-ttl.test.ts +49 -4
  71. package/src/commands/__tests__/update.test.ts +25 -3
  72. package/src/commands/__tests__/view.test.ts +49 -0
  73. package/src/commands/call-describe.ts +60 -68
  74. package/src/commands/call.ts +71 -59
  75. package/src/commands/domain/install.ts +54 -35
  76. package/src/commands/domain/list.ts +1 -1
  77. package/src/commands/domain/publish.ts +14 -11
  78. package/src/commands/domain/uninstall.ts +2 -2
  79. package/src/commands/get.ts +14 -15
  80. package/src/commands/identity/__tests__/register.test.ts +3 -3
  81. package/src/commands/identity/register.ts +5 -4
  82. package/src/commands/instance/create.ts +8 -16
  83. package/src/commands/instance/delete.ts +12 -9
  84. package/src/commands/instance/list.ts +2 -2
  85. package/src/commands/instance/status.ts +66 -20
  86. package/src/commands/instance/use.ts +16 -12
  87. package/src/commands/introspect.ts +48 -35
  88. package/src/commands/logs.ts +123 -33
  89. package/src/commands/mutate.ts +6 -5
  90. package/src/commands/query.ts +35 -32
  91. package/src/commands/token.ts +42 -27
  92. package/src/commands/ui/__tests__/commands.test.ts +152 -0
  93. package/src/commands/ui/add.ts +51 -0
  94. package/src/commands/ui/doctor.ts +13 -0
  95. package/src/commands/ui/init.ts +38 -0
  96. package/src/commands/ui/list.ts +26 -0
  97. package/src/commands/ui/preset-apply.ts +19 -0
  98. package/src/commands/ui/preset-list.ts +12 -0
  99. package/src/commands/ui/shared.ts +25 -0
  100. package/src/commands/update.ts +31 -11
  101. package/src/commands/view.ts +82 -37
  102. package/src/connection/.spec/api.d.ts +7 -8
  103. package/src/connection/.spec/architecture.md +5 -4
  104. package/src/connection/.spec/flows/session.ts +2 -2
  105. package/src/connection/.spec/laws/connection.ts +6 -2
  106. package/src/connection/.spec/layout.ts +1 -0
  107. package/src/connection/__tests__/credential.test.ts +20 -1
  108. package/src/connection/__tests__/errors.test.ts +27 -20
  109. package/src/connection/__tests__/exchange.test.ts +30 -1
  110. package/src/connection/__tests__/failure-fixtures.ts +39 -0
  111. package/src/connection/__tests__/failure-safety.test.ts +75 -0
  112. package/src/connection/__tests__/self.test.ts +31 -11
  113. package/src/connection/__tests__/session.test.ts +3 -3
  114. package/src/connection/__tests__/target.test.ts +1 -0
  115. package/src/connection/auth.ts +13 -0
  116. package/src/connection/call.ts +1 -1
  117. package/src/connection/credential.ts +2 -2
  118. package/src/connection/errors.ts +1 -355
  119. package/src/connection/exchange.ts +47 -23
  120. package/src/connection/failure/classify.ts +110 -0
  121. package/src/connection/failure/index.ts +18 -0
  122. package/src/connection/failure/model.ts +28 -0
  123. package/src/connection/failure/render.ts +116 -0
  124. package/src/connection/reasons.ts +16 -0
  125. package/src/connection/self.ts +39 -21
  126. package/src/connection/session.ts +19 -8
  127. package/src/errors.ts +3 -2
  128. package/src/graph/.spec/api.d.ts +12 -5
  129. package/src/graph/.spec/layout.ts +9 -1
  130. package/src/graph/__tests__/mutation.test.ts +2 -2
  131. package/src/graph/__tests__/query.test.ts +25 -6
  132. package/src/graph/class.ts +30 -0
  133. package/src/graph/index.ts +1 -0
  134. package/src/graph/query.ts +21 -32
  135. package/src/identity/.spec/api.d.ts +2 -2
  136. package/src/identity/__tests__/registration.test.ts +1 -1
  137. package/src/identity/registration.ts +3 -3
  138. package/src/keys/__tests__/keys.test.ts +4 -0
  139. package/src/keys/credential.ts +1 -0
  140. package/src/lib/__tests__/admin-target.test.ts +12 -0
  141. package/src/lib/__tests__/binary.test.ts +16 -1
  142. package/src/lib/__tests__/command-dx.test.ts +1 -1
  143. package/src/lib/__tests__/domain-publication.test.ts +10 -16
  144. package/src/lib/__tests__/idp.test.ts +34 -4
  145. package/src/lib/__tests__/instance-candidates.test.ts +1 -3
  146. package/src/lib/__tests__/instance-target.test.ts +7 -39
  147. package/src/lib/__tests__/log-errors.test.ts +64 -0
  148. package/src/lib/__tests__/studio-server-deps.test.ts +1 -1
  149. package/src/lib/__tests__/update.test.ts +264 -11
  150. package/src/lib/__tests__/view-assets.test.ts +14 -0
  151. package/src/lib/__tests__/view-external-open-intent.test.ts +150 -0
  152. package/src/lib/__tests__/view-external-open-origins.test.ts +27 -0
  153. package/src/lib/__tests__/view-open-intent.test.ts +0 -2
  154. package/src/lib/__tests__/view-server.test.ts +26 -3
  155. package/src/lib/__tests__/view-session.test.ts +2 -1
  156. package/src/lib/admin-instance.ts +14 -8
  157. package/src/lib/admin-target.ts +21 -2
  158. package/src/lib/binary.ts +22 -5
  159. package/src/lib/command-dx.ts +9 -9
  160. package/src/lib/domain-publication.ts +9 -7
  161. package/src/lib/failure-debug.ts +26 -0
  162. package/src/lib/idp.ts +34 -3
  163. package/src/lib/instance-candidates.ts +2 -2
  164. package/src/lib/instance-target.ts +3 -14
  165. package/src/lib/instance.ts +16 -11
  166. package/src/lib/log.ts +16 -9
  167. package/src/lib/output.ts +1 -1
  168. package/src/lib/proc.ts +7 -2
  169. package/src/lib/provision-instance.ts +34 -57
  170. package/src/lib/update.ts +298 -45
  171. package/src/lib/validation.ts +2 -2
  172. package/src/lib/view/assets.ts +11 -2
  173. package/src/lib/view/external-open-intent.ts +41 -0
  174. package/src/lib/view/external-open-origins.ts +37 -0
  175. package/src/lib/view/host-capabilities.ts +17 -0
  176. package/src/lib/view/resolve.ts +1 -1
  177. package/src/lib/view/server.ts +18 -3
  178. package/src/lib/view/session.ts +2 -0
  179. package/src/program/.spec/api.d.ts +1 -0
  180. package/src/program/__tests__/program.test.ts +163 -6
  181. package/src/program/argv.ts +14 -0
  182. package/src/program/build.ts +26 -4
  183. package/src/program/command.ts +1 -0
  184. package/src/program/index.ts +1 -0
  185. package/src/program/registry.ts +2 -1
  186. package/src/setup/__tests__/instance-step.test.ts +27 -10
  187. package/src/setup/steps/instance.ts +22 -15
  188. package/src/telemetry/__tests__/recorder.test.ts +1 -0
  189. package/src/telemetry/recorder.ts +9 -1
  190. package/src/ui/.spec/api.d.ts +14 -0
  191. package/src/ui/.spec/architecture.md +10 -0
  192. package/src/ui/.spec/laws.ts +36 -0
  193. package/src/ui/.spec/layout.ts +16 -0
  194. package/src/ui/__tests__/ui.test.ts +981 -0
  195. package/src/ui/index.ts +13 -0
  196. package/src/ui/lock.ts +87 -0
  197. package/src/ui/model.ts +83 -0
  198. package/src/ui/operations.ts +710 -0
  199. package/src/ui/project.ts +219 -0
  200. package/src/ui/release.ts +321 -0
  201. package/src/ui/runner.ts +18 -0
  202. package/studio/client/dist/assets/elk-api-DjmKsHXc.js +1 -0
  203. package/studio/client/dist/assets/index-7YHdeCxp.js +81 -0
  204. package/studio/client/dist/assets/index-C0FAnwNw.css +2 -0
  205. package/studio/client/dist/assets/rolldown-runtime-Dd_uD5pT.js +1 -0
  206. package/studio/client/dist/assets/schema-studio-BilUNb6Z.css +1 -0
  207. package/studio/client/dist/assets/schema-studio-CABpTfvH.js +8 -0
  208. package/studio/client/dist/index.html +3 -2
  209. package/studio/package.json +7 -13
  210. package/studio/server/agent/ask.test.ts +1 -1
  211. package/studio/server/agent/bridge/grant.test.ts +1 -1
  212. package/studio/server/agent/bridge/routes.test.ts +1 -1
  213. package/studio/server/agent/harness/claude/adapter.test.ts +15 -5
  214. package/studio/server/agent/harness/gateway/token.test.ts +1 -1
  215. package/studio/server/agent/harness/gateway/token.ts +3 -3
  216. package/studio/server/agent/prompts/anchors.test.ts +32 -36
  217. package/studio/server/agent/prompts/anchors.ts +20 -49
  218. package/studio/server/agent/prompts/system.test.ts +3 -2
  219. package/studio/server/agent/prompts/system.ts +3 -3
  220. package/studio/server/agent/routes.test.ts +1 -1
  221. package/studio/server/agent/run/coordinator.test.ts +1 -1
  222. package/studio/server/api/canvas.ts +0 -1
  223. package/studio/server/api-agent-loadout.test.ts +1 -1
  224. package/studio/server/api.test.ts +1 -1
  225. package/studio/server/cache.test.ts +23 -12
  226. package/studio/server/cache.ts +12 -15
  227. package/studio/server/domain.test.ts +50 -68
  228. package/studio/server/domain.ts +82 -63
  229. package/studio/server/handoff/copy.ts +1 -1
  230. package/studio/server/index.ts +1 -1
  231. package/studio/server/instances/probe.test.ts +1 -1
  232. package/studio/server/introspect/anatomy/views/routes.ts +46 -37
  233. package/studio/server/introspect/anatomy/views.ts +9 -14
  234. package/studio/server/introspect/anatomy-extras.test.ts +26 -42
  235. package/studio/server/introspect/anatomy.test.ts +22 -14
  236. package/studio/server/introspect/anatomy.ts +6 -9
  237. package/studio/server/introspect/bundle.ts +0 -3
  238. package/studio/server/introspect/canonical-schema.test.ts +94 -389
  239. package/studio/server/introspect/canonical-schema.ts +227 -457
  240. package/studio/server/introspect/core-extractor.ts +18 -127
  241. package/studio/server/introspect/core.ts +1 -2
  242. package/studio/server/introspect/diff.test.ts +11 -7
  243. package/studio/server/introspect/diff.ts +18 -55
  244. package/studio/server/introspect/extractor.ts +22 -117
  245. package/studio/server/introspect/overlay-tsmorph.test.ts +119 -240
  246. package/studio/server/introspect/overlay.test.ts +26 -54
  247. package/studio/server/introspect/overlay.ts +10 -37
  248. package/studio/server/introspect/revision.test.ts +1 -1
  249. package/studio/server/introspect/revision.ts +1 -1
  250. package/studio/server/introspect/runtime.test.ts +65 -183
  251. package/studio/server/introspect/runtime.ts +8 -25
  252. package/studio/server/introspect/schema-ir-json.test.ts +70 -0
  253. package/studio/server/introspect/schema-ir-json.ts +38 -68
  254. package/studio/server/introspect/schema-refs.test.ts +43 -88
  255. package/studio/server/introspect/schema-refs.ts +14 -49
  256. package/studio/server/introspect/source-overlay/handlers.ts +116 -636
  257. package/studio/server/introspect/source-overlay/kernel-calls.ts +0 -3
  258. package/studio/server/introspect/source-overlay/spans.ts +15 -45
  259. package/studio/server/state/baseline.test.ts +14 -9
  260. package/studio/server/state/baseline.ts +3 -5
  261. package/studio/server/state/visibility.ts +1 -5
  262. package/studio/server/views/model.ts +3 -3
  263. package/studio/server/views/target.test.ts +17 -74
  264. package/studio/server/views/target.ts +24 -50
  265. package/studio/server/watch.test.ts +11 -11
  266. package/studio/server/watch.ts +8 -4
  267. package/studio/server/workspace-watch.ts +2 -2
  268. package/studio/shared/contracts/schema.ts +38 -107
  269. package/studio/shared/contracts/surface.test.ts +13 -15
  270. package/studio/shared/contracts/workspace.ts +2 -11
  271. package/studio/shared/schema/identity.test.ts +20 -44
  272. package/studio/shared/schema/identity.ts +9 -23
  273. package/viewer/dist/main.js +30 -51
  274. package/.check-workspace.cjs +0 -40
  275. package/src/admin/binding.ts +0 -168
  276. package/src/commands/__tests__/instance-create-hosts.test.ts +0 -29
  277. package/studio/client/dist/assets/elk-api-lwhFo7vB.js +0 -1
  278. package/studio/client/dist/assets/index-B-c-smo9.js +0 -8
  279. package/studio/client/dist/assets/index-BckHuAWk.js +0 -81
  280. package/studio/client/dist/assets/index-C4aNQ6dz.css +0 -1
  281. package/studio/client/dist/assets/index-ChOr3yP0.css +0 -1
  282. package/studio/server/introspect/anatomy/views/legacy.ts +0 -232
@@ -22,10 +22,7 @@ const KERNEL_TOKENS: KernelToken[] = [
22
22
  { token: 'auth.check' },
23
23
  { token: 'graph.tree' },
24
24
  { token: 'graph.node' },
25
- { token: 'revokePerm', label: 'revokePerm (legacy)' },
26
- { token: 'checkPerm', label: 'checkPerm (legacy)' },
27
25
  { token: 'graph.get' },
28
- { token: 'grantPerm', label: 'grantPerm (legacy)' },
29
26
  ]
30
27
 
31
28
  /** Scan handler file text for kernel-op tokens. */
@@ -58,18 +58,14 @@ function cleanComment(raw: string): string {
58
58
  return lines.join(' ').replace(/\s+/g, ' ').trim()
59
59
  }
60
60
 
61
- const DECL_HELPERS: Record<string, 'node' | 'interface' | 'edge' | 'function'> = {
61
+ const DECL_HELPERS: Record<string, 'node' | 'edge' | 'function'> = {
62
62
  nodeClass: 'node',
63
- nodeInterface: 'interface',
64
63
  edgeClass: 'edge',
65
64
  fn: 'function',
66
65
  }
67
66
 
68
- /** Recognize both legacy `edgeClass(...)` and current
69
- * `edgeClass.directed/undirected({...})` authoring forms. */
70
- function declarationHelper(
71
- call: CallExpression,
72
- ): 'node' | 'interface' | 'edge' | 'function' | undefined {
67
+ /** Recognize current Class and Function declaration helpers. */
68
+ function declarationHelper(call: CallExpression): 'node' | 'edge' | 'function' | undefined {
73
69
  const direct = calleeName(call)
74
70
  if (direct && direct in DECL_HELPERS) return DECL_HELPERS[direct]
75
71
  const expression = call.getExpression()
@@ -85,22 +81,17 @@ function declarationHelper(
85
81
 
86
82
  /**
87
83
  * A schema member's true NAME + section, resolved from the `defineSchema` map.
88
- * The declaration helpers (nodeClass/nodeInterface/edgeClass) carry no name a
89
- * member is named by the KEY it is registered under, not by its variable — and a
90
- * domain may register a class and an interface under the SAME name (the
91
- * intentional same-name pattern: the `iUser` interface alongside the `User`
92
- * class). So the map is the sole authority for both the anchor name and the
93
- * interface-vs-class distinction; the variable identifier alone tells us neither.
84
+ * Declaration helpers carry no name: the `defineSchema` key is authoritative.
94
85
  */
95
86
  interface MemberName {
96
87
  schemaName: string
97
- section: 'interface' | 'class' | 'function' // the `classes` map also holds edge classes
88
+ section: 'class' | 'function'
98
89
  }
99
90
 
100
91
  interface MemberNameMap {
101
92
  /** Exact declaration initializer, robust to imported/local aliases. */
102
93
  byValue: Map<string, MemberName>
103
- /** Legacy fallback when a symbol cannot be resolved. */
94
+ /** Fallback when a symbol cannot be resolved. */
104
95
  byIdentifier: Map<string, MemberName>
105
96
  }
106
97
 
@@ -132,7 +123,6 @@ function buildMemberNameMap(files: SourceFile[]): MemberNameMap {
132
123
  const input = call.getArguments()[1]
133
124
  const cfg = input ? resolveObjectLiteral(input) : undefined
134
125
  if (!cfg) continue
135
- collectSchemaSection(map, cfg, 'interfaces', 'interface')
136
126
  collectSchemaSection(map, cfg, 'classes', 'class')
137
127
  collectSchemaSection(map, cfg, 'functions', 'function')
138
128
  }
@@ -145,8 +135,8 @@ function buildMemberNameMap(files: SourceFile[]): MemberNameMap {
145
135
  function collectSchemaSection(
146
136
  map: MemberNameMap,
147
137
  cfg: Node,
148
- prop: 'interfaces' | 'classes' | 'functions',
149
- section: 'interface' | 'class' | 'function',
138
+ prop: 'classes' | 'functions',
139
+ section: 'class' | 'function',
150
140
  ): void {
151
141
  const obj = getObjectProp(cfg, prop)
152
142
  if (!obj) return
@@ -163,24 +153,18 @@ function collectSchemaSection(
163
153
  }
164
154
 
165
155
  /**
166
- * The anchor namespace ('class' | 'interface' | 'edge') for a declared member.
167
- * The `defineSchema` SECTION is authoritative for interface-vs-class — a
168
- * `nodeClass` whose name collides with a same-named interface must still anchor
169
- * as a class. Within the class section, an `edgeClass` (or an IR edge type)
170
- * anchors as 'edge'. Falls back to the declaration helper when the member isn't
171
- * in a parseable `defineSchema` map (e.g. an imported kernel member).
156
+ * The anchor namespace for a declared member. The Class section plus helper/IR
157
+ * kind distinguishes Node and Edge Classes.
172
158
  */
173
159
  function resolveMemberKind(
174
160
  ir: SchemaIR | null,
175
161
  name: string,
176
- section: 'interface' | 'class' | 'function' | undefined,
177
- helperKind: 'node' | 'interface' | 'edge' | 'function',
178
- ): 'class' | 'interface' | 'edge' | 'function' {
162
+ section: 'class' | 'function' | undefined,
163
+ helperKind: 'node' | 'edge' | 'function',
164
+ ): 'class' | 'edge' | 'function' {
179
165
  if (section === 'function' || helperKind === 'function') return 'function'
180
- if (section === 'interface') return 'interface'
181
166
  const isEdge = helperKind === 'edge' || ir?.classes?.[name]?.type === 'edge'
182
167
  if (section === 'class') return isEdge ? 'edge' : 'class'
183
- if (helperKind === 'interface') return 'interface'
184
168
  return isEdge ? 'edge' : 'class'
185
169
  }
186
170
 
@@ -206,9 +190,7 @@ export function buildSourceSpans(args: {
206
190
  const spans: Record<string, SourceSpan> = {}
207
191
 
208
192
  const sourceFiles = files.map((f) => project.getSourceFile(f)).filter((f): f is SourceFile => !!f)
209
- // The domain's `defineSchema` map is authoritative for each member's name +
210
- // interface-vs-class kind, so an aliased interface (`iUser`→`User`) and a class
211
- // sharing its name (`User`) each anchor correctly instead of colliding.
193
+ // The Domain's `defineSchema` map is authoritative for each member's name.
212
194
  const memberNames = buildMemberNameMap(sourceFiles)
213
195
 
214
196
  for (const sf of sourceFiles) {
@@ -287,7 +269,7 @@ function collectPropsAndMethods(
287
269
  }
288
270
  }
289
271
 
290
- /** Record edge endpoint spans `edge.<Name>.endpoint.<role>` from the two args. */
272
+ /** Record edge endpoint and property spans from current directed/undirected forms. */
291
273
  function collectEdge(
292
274
  spans: Record<string, SourceSpan>,
293
275
  name: string,
@@ -331,18 +313,6 @@ function collectEdge(
331
313
  if (!role) continue
332
314
  spans[`edge.${name}.endpoint.${role}`] = makeSpan(domainRoot, fileRel, ep, ep)
333
315
  }
334
- // Legacy edge props live in the third (config) arg.
335
- const cfgArg = argsList[2]
336
- if (cfgArg && Node.isObjectLiteralExpression(cfgArg)) {
337
- const propsObj = getObjectProp(cfgArg, 'properties') ?? getObjectProp(cfgArg, 'props')
338
- if (propsObj) {
339
- for (const p of propsObj.getProperties()) {
340
- const pName = propertyKey(p)
341
- if (!pName) continue
342
- spans[`edge.${name}.property.${pName}`] = makeSpan(domainRoot, fileRel, p, p)
343
- }
344
- }
345
- }
346
316
  }
347
317
 
348
318
  /** The object-literal value of a named property, if it is itself an object. */
@@ -21,13 +21,13 @@ afterEach(() => {
21
21
  while (roots.length) rmSync(roots.pop()!, { recursive: true, force: true })
22
22
  })
23
23
 
24
- test('hashes current implementation and semantic layer files alongside legacy anatomy', () => {
24
+ test('hashes current Application and vertical authoring files', () => {
25
25
  const root = mkdtempSync(join(tmpdir(), 'studio-current-baseline-'))
26
26
  roots.push(root)
27
27
  for (const dir of [
28
28
  'schema',
29
29
  'actions/risk',
30
- 'handlers/risk',
30
+ 'providers/mail',
31
31
  'queries/risk',
32
32
  'ui/risk',
33
33
  'views/risk',
@@ -36,9 +36,10 @@ test('hashes current implementation and semantic layer files alongside legacy an
36
36
  }
37
37
  for (const file of [
38
38
  'schema/index.ts',
39
- 'implementation.ts',
39
+ 'application.ts',
40
+ 'runtime.ts',
40
41
  'actions/risk/index.ts',
41
- 'handlers/risk/index.ts',
42
+ 'providers/mail/index.ts',
42
43
  'queries/risk/index.ts',
43
44
  'ui/risk/screen.tsx',
44
45
  'views/risk/index.ts',
@@ -50,10 +51,11 @@ test('hashes current implementation and semantic layer files alongside legacy an
50
51
 
51
52
  expect(Object.keys(hashAnatomyFiles(root, 'schema')).sort()).toEqual([
52
53
  'actions/risk/index.ts',
53
- 'handlers/risk/index.ts',
54
- 'implementation.ts',
54
+ 'application.ts',
55
55
  'package.json',
56
+ 'providers/mail/index.ts',
56
57
  'queries/risk/index.ts',
58
+ 'runtime.ts',
57
59
  'schema/index.ts',
58
60
  'ui/risk/screen.tsx',
59
61
  'views/risk/index.ts',
@@ -64,11 +66,14 @@ const schema = (domain: string): SchemaIR => ({
64
66
  format: 'astrale.dsl',
65
67
  version: 'v1',
66
68
  domain,
67
- types: {},
68
- interfaces: {},
69
69
  classes: {},
70
- imports: {},
70
+ importsByKey: {},
71
+ importedClassesByKey: {},
71
72
  functions: {},
73
+ views: {},
74
+ policies: {},
75
+ dependencies: [],
76
+ core: {},
72
77
  })
73
78
 
74
79
  const canonicalRoot = {
@@ -45,12 +45,10 @@ const SKIP_DIRS = new Set(['node_modules', '.dist', 'dist', '.domain-studio', '.
45
45
  export const ANATOMY_GLOBS = {
46
46
  dirs: [
47
47
  'actions',
48
- 'capabilities',
49
48
  'core',
49
+ 'providers',
50
50
  'runtime',
51
51
  'views',
52
- 'functions',
53
- 'handlers',
54
52
  'integrations',
55
53
  'migrations',
56
54
  'mutations',
@@ -64,8 +62,8 @@ export const ANATOMY_GLOBS = {
64
62
  'client/src',
65
63
  ],
66
64
  files: [
67
- 'implementation.ts',
68
- 'domain.ts',
65
+ 'application.ts',
66
+ 'runtime.ts',
69
67
  'index.ts',
70
68
  'core.ts',
71
69
  'deps.ts',
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * visibility.ts — persisted per-domain canvas visibility (the manual hide-set,
3
- * inherited-edge category toggle, and materialized-interface set). Sibling of
3
+ * and inherited-edge category toggle). Sibling of
4
4
  * layout.ts: layout owns node POSITIONS, this owns what's SHOWN. All entries use
5
5
  * stable refs, so they survive schema edits (a removed ref is harmless).
6
6
  * Persisted via the allow-listed store (visibility.json).
@@ -14,7 +14,6 @@ const FILE = 'visibility.json'
14
14
  const DEFAULT: VisibilityState = {
15
15
  hidden: {},
16
16
  showInheritedEdges: true,
17
- materializedInterfaces: {},
18
17
  }
19
18
 
20
19
  function trueSet(value: unknown): Record<string, true> {
@@ -31,13 +30,10 @@ function decodeVisibility(value: unknown): VisibilityState | undefined {
31
30
  return {
32
31
  hidden: trueSet(record.hidden),
33
32
  showInheritedEdges: asBoolean(record.showInheritedEdges) ?? DEFAULT.showInheritedEdges,
34
- materializedInterfaces: trueSet(record.materializedInterfaces),
35
33
  }
36
34
  }
37
35
 
38
36
  export function readVisibility(root: string): VisibilityState {
39
- // merge over DEFAULT so a file written before a field existed (e.g. pre-materialize)
40
- // still returns the complete shape — the client reads every field unconditionally.
41
37
  return readJson(root, FILE, decodeVisibility, { ...DEFAULT })
42
38
  }
43
39
 
@@ -4,9 +4,9 @@ import type {
4
4
  ViewTargetResult,
5
5
  } from '../../shared/types'
6
6
 
7
- const NAMED_NAME = 'kernel.astrale.ai:interface.Named.property.name'
8
- const DESCRIPTABLE_DESCRIPTION = 'kernel.astrale.ai:interface.Descriptable.property.description'
9
- const STATUSED_STATUS = 'kernel.astrale.ai:interface.Statused.property.status'
7
+ const NAMED_NAME = 'kernel.astrale.ai:class.Named.property.name'
8
+ const DESCRIPTABLE_DESCRIPTION = 'kernel.astrale.ai:class.Descriptable.property.description'
9
+ const STATUSED_STATUS = 'kernel.astrale.ai:class.Statused.property.status'
10
10
 
11
11
  export interface RawTargetRow {
12
12
  id?: unknown
@@ -4,37 +4,12 @@ import type { StudioSchemaBundle, ViewInfo } from '../../shared/types'
4
4
 
5
5
  import { targetDefinition, viewDefinitionBindings } from './target'
6
6
 
7
- describe('view target definitions', () => {
8
- test('preserves canonical interface View target coordinates', () => {
9
- const view = { slug: 'users', kind: 'unknown' } satisfies ViewInfo
10
- const bundle = {
11
- ir: {
12
- views: {
13
- users: {
14
- name: 'users',
15
- auth: 'required',
16
- target: {
17
- kind: 'definition',
18
- definitions: [{ origin: 'kernel.astrale.ai', kind: 'interface', name: 'Identity' }],
19
- },
20
- },
21
- },
22
- },
23
- } as unknown as StudioSchemaBundle
24
-
25
- expect(viewDefinitionBindings('shell.astrale.ai', view, bundle)).toEqual([
26
- { className: 'Identity', classOrigin: 'kernel.astrale.ai', kind: 'interface' },
27
- ])
28
- expect(targetDefinition('Identity', 'kernel.astrale.ai', 'interface')).toBe(
29
- '/:kernel.astrale.ai:interface.Identity',
30
- )
31
- })
32
-
33
- test('preserves every exact canonical homonym and ignores short-name metadata', () => {
7
+ describe('View target definitions', () => {
8
+ test('preserves every exact canonical Class target and ignores short-name metadata', () => {
34
9
  const view = {
35
10
  slug: 'named',
36
11
  kind: 'unknown',
37
- viewFor: 'WrongLegacyTarget',
12
+ viewFor: 'WrongFallback',
38
13
  } satisfies ViewInfo
39
14
  const bundle = {
40
15
  ir: {
@@ -45,24 +20,21 @@ describe('view target definitions', () => {
45
20
  target: {
46
21
  kind: 'definition',
47
22
  definitions: [
48
- { origin: 'directory.example.dev', kind: 'interface', name: 'Named' },
49
- { origin: 'people.example.dev', kind: 'interface', name: 'Named' },
50
- { origin: 'catalog.example.dev', kind: 'class', name: 'Named' },
23
+ { origin: 'directory.example.dev', kind: 'class', name: 'Named' },
24
+ { origin: 'people.example.dev', kind: 'class', name: 'Named' },
51
25
  ],
52
26
  },
53
27
  },
54
28
  },
55
29
  },
56
30
  } as unknown as StudioSchemaBundle
57
-
58
31
  expect(viewDefinitionBindings('shell.astrale.ai', view, bundle)).toEqual([
59
- { className: 'Named', classOrigin: 'directory.example.dev', kind: 'interface' },
60
- { className: 'Named', classOrigin: 'people.example.dev', kind: 'interface' },
61
- { className: 'Named', classOrigin: 'catalog.example.dev', kind: 'class' },
32
+ { className: 'Named', classOrigin: 'directory.example.dev', kind: 'class' },
33
+ { className: 'Named', classOrigin: 'people.example.dev', kind: 'class' },
62
34
  ])
63
35
  })
64
36
 
65
- test('treats an exact Domain target as authoritative over legacy viewFor', () => {
37
+ test('treats a canonical Domain target as authoritative', () => {
66
38
  const view = { slug: 'home', kind: 'unknown', viewFor: 'User' } satisfies ViewInfo
67
39
  const bundle = {
68
40
  ir: { views: { home: { name: 'home', auth: 'required', target: { kind: 'domain' } } } },
@@ -70,66 +42,37 @@ describe('view target definitions', () => {
70
42
  expect(viewDefinitionBindings('shell.astrale.ai', view, bundle)).toEqual([])
71
43
  })
72
44
 
73
- test('uses every exact fallback candidate across origin and definition-kind collisions', () => {
74
- const view = { slug: 'legacy-named', kind: 'unknown', viewFor: 'Named' } satisfies ViewInfo
45
+ test('resolves fallback targets through local and exact imported Classes', () => {
46
+ const view = { slug: 'named', kind: 'unknown', viewFor: 'Named' } satisfies ViewInfo
75
47
  const bundle = {
76
48
  ir: {
77
49
  domain: 'shell.astrale.ai',
78
50
  views: {},
79
51
  classes: {
80
52
  Named: {
53
+ type: 'node',
54
+ name: 'Named',
81
55
  origin: 'shell.astrale.ai',
82
- ref: { origin: 'shell.astrale.ai', kind: 'class', name: 'Named' },
83
- },
84
- },
85
- interfaces: {
86
- Named: {
87
- origin: 'shell.astrale.ai',
88
- ref: { origin: 'shell.astrale.ai', kind: 'interface', name: 'Named' },
56
+ properties: {},
57
+ methods: {},
89
58
  },
90
59
  },
91
- imports: { Named: { origin: 'legacy.invalid', definition: 'class' } },
92
60
  importsByKey: {
93
- 'directory.example.dev:interface.Named': {
94
- origin: 'directory.example.dev',
95
- definition: 'interface',
96
- },
97
61
  'catalog.example.dev:class.Named': {
98
62
  origin: 'catalog.example.dev',
99
- definition: 'class',
63
+ ref: { origin: 'catalog.example.dev', kind: 'class', name: 'Named' },
64
+ key: 'catalog.example.dev:class.Named',
100
65
  },
101
66
  },
102
67
  },
103
68
  } as unknown as StudioSchemaBundle
104
-
105
69
  expect(viewDefinitionBindings('shell.astrale.ai', view, bundle)).toEqual([
106
70
  { className: 'Named', classOrigin: 'shell.astrale.ai', kind: 'class' },
107
- { className: 'Named', classOrigin: 'shell.astrale.ai', kind: 'interface' },
108
- { className: 'Named', classOrigin: 'directory.example.dev', kind: 'interface' },
109
71
  { className: 'Named', classOrigin: 'catalog.example.dev', kind: 'class' },
110
72
  ])
111
73
  })
112
74
 
113
- test('uses the short-name import only for legacy bundles without an exact index', () => {
114
- const view = { slug: 'legacy-users', kind: 'unknown', viewFor: 'User' } satisfies ViewInfo
115
- const legacy = {
116
- ir: {
117
- domain: 'shell.astrale.ai',
118
- views: {},
119
- classes: {},
120
- interfaces: {},
121
- imports: { User: { origin: 'accounts.example.dev', definition: 'interface' } },
122
- },
123
- } as unknown as StudioSchemaBundle
124
- const exact = { ir: { ...legacy.ir, importsByKey: {} } } as unknown as StudioSchemaBundle
125
-
126
- expect(viewDefinitionBindings('shell.astrale.ai', view, legacy)).toEqual([
127
- { className: 'User', classOrigin: 'accounts.example.dev', kind: 'interface' },
128
- ])
129
- expect(viewDefinitionBindings('shell.astrale.ai', view, exact)).toEqual([])
130
- })
131
-
132
- test('addresses exact class instances through a canonical Definition source', () => {
75
+ test('addresses exact Class instances through a canonical Definition source', () => {
133
76
  expect(targetDefinition('Issue', 'issues.astrale.ai')).toBe('/:issues.astrale.ai:class.Issue')
134
77
  })
135
78
  })
@@ -61,7 +61,7 @@ export async function listViewTargets(
61
61
 
62
62
  const queried = await Promise.all(
63
63
  bindings.map(async (binding) => {
64
- const definition = targetDefinition(binding.className, binding.classOrigin, binding.kind)
64
+ const definition = targetDefinition(binding.className, binding.classOrigin)
65
65
  const result = await runAstraleJson<RawQueryResult>(
66
66
  [
67
67
  'query',
@@ -116,21 +116,17 @@ export async function listViewTargets(
116
116
  }
117
117
  }
118
118
 
119
- export function targetDefinition(
120
- className: string,
121
- classOrigin: string,
122
- kind: 'class' | 'interface' = 'class',
123
- ): string {
124
- return `/:${assertOrigin(classOrigin)}:${kind}.${assertSchemaName(className)}`
119
+ export function targetDefinition(className: string, classOrigin: string): string {
120
+ return `/:${assertOrigin(classOrigin)}:class.${assertSchemaName(className)}`
125
121
  }
126
122
 
127
123
  export interface ViewDefinitionBinding {
128
124
  className: string
129
125
  classOrigin: string
130
- kind: 'class' | 'interface'
126
+ kind: 'class'
131
127
  }
132
128
 
133
- /** Preserve exact canonical View target coordinates; short-name anatomy is legacy-only. */
129
+ /** Preserve exact canonical View target coordinates. */
134
130
  export function viewDefinitionBindings(
135
131
  origin: string,
136
132
  view: ViewInfo,
@@ -140,16 +136,17 @@ export function viewDefinitionBindings(
140
136
  if (target) {
141
137
  if (target.kind === 'domain') return []
142
138
  return uniqueViewBindings(
143
- target.definitions
144
- .filter(
145
- (definition): definition is typeof definition & { kind: 'class' | 'interface' } =>
146
- definition.kind === 'class' || definition.kind === 'interface',
147
- )
148
- .map((definition) => ({
149
- className: definition.name,
150
- classOrigin: definition.origin,
151
- kind: definition.kind,
152
- })),
139
+ target.definitions.flatMap((definition) =>
140
+ definition.kind === 'class'
141
+ ? [
142
+ {
143
+ className: definition.name,
144
+ classOrigin: definition.origin,
145
+ kind: 'class' as const,
146
+ },
147
+ ]
148
+ : [],
149
+ ),
153
150
  )
154
151
  }
155
152
 
@@ -165,7 +162,6 @@ export function viewDefinitionBindings(
165
162
  names.flatMap((className) => {
166
163
  const local: ViewDefinitionBinding[] = []
167
164
  const localClass = ir.classes[className]
168
- const localInterface = ir.interfaces[className]
169
165
  if (localClass) {
170
166
  local.push({
171
167
  className,
@@ -173,33 +169,11 @@ export function viewDefinitionBindings(
173
169
  kind: 'class',
174
170
  })
175
171
  }
176
- if (localInterface) {
177
- local.push({
178
- className,
179
- classOrigin: localInterface.ref?.origin ?? localInterface.origin ?? ir.domain ?? origin,
180
- kind: 'interface',
181
- })
182
- }
183
-
184
- if (ir.importsByKey !== undefined) {
185
- const imported = Object.keys(ir.importsByKey).flatMap((key) => {
186
- const binding = viewBindingFromDefinitionKey(key)
187
- return binding?.className === className ? [binding] : []
188
- })
189
- return [...local, ...imported]
190
- }
191
-
192
- const legacy = ir.imports[className]
193
- if (legacy) {
194
- return [
195
- ...local,
196
- {
197
- className,
198
- classOrigin: legacy.origin,
199
- kind: legacy.definition,
200
- } satisfies ViewDefinitionBinding,
201
- ]
202
- }
172
+ const imported = Object.keys(ir.importsByKey).flatMap((key) => {
173
+ const binding = viewBindingFromDefinitionKey(key)
174
+ return binding?.className === className ? [binding] : []
175
+ })
176
+ if (imported.length > 0) return [...local, ...imported]
203
177
 
204
178
  return local.length > 0 ? local : [{ className, classOrigin: origin, kind: 'class' }]
205
179
  }),
@@ -211,12 +185,12 @@ function viewBindingFromDefinitionKey(key: string): ViewDefinitionBinding | null
211
185
  if (separator <= 0) return null
212
186
  const classOrigin = key.slice(0, separator)
213
187
  const ref = key.slice(separator + 1)
214
- const match = /^(class|interface)\.([A-Za-z_$][\w$]*)$/.exec(ref)
188
+ const match = /^class\.([A-Za-z_$][\w$]*)$/.exec(ref)
215
189
  if (!match) return null
216
190
  return {
217
- className: match[2]!,
191
+ className: match[1]!,
218
192
  classOrigin,
219
- kind: match[1] as ViewDefinitionBinding['kind'],
193
+ kind: 'class',
220
194
  }
221
195
  }
222
196
 
@@ -10,27 +10,27 @@ const handle: DomainHandle = {
10
10
  id: 'current',
11
11
  root: '/workspace/current',
12
12
  configFile: '/workspace/current/astrale.config.ts',
13
- domainFile: '/workspace/current/implementation.ts',
13
+ applicationFile: '/workspace/current/application.ts',
14
14
  schemaDirName: 'schema',
15
15
  schemaDir: '/workspace/current/schema',
16
16
  schemaIndex: '/workspace/current/schema/index.ts',
17
17
  }
18
18
 
19
- test('watches current layout roots and reconciles either composition entry', () => {
20
- expect(ANATOMY_PATHS).toContain('implementation.ts')
19
+ test('watches current Application, Runtime, and vertical authoring roots', () => {
20
+ expect(ANATOMY_PATHS).toContain('application.ts')
21
+ expect(ANATOMY_PATHS).toContain('runtime.ts')
21
22
  expect(ANATOMY_PATHS).toContain('ui')
22
- expect(ANATOMY_PATHS).toContain('handlers')
23
+ expect(ANATOMY_PATHS).toContain('providers')
23
24
  expect(ANATOMY_PATHS).toContain('queries')
24
25
  expect(ANATOMY_PATHS).toContain('workflows')
25
- expect(DOMAIN_SET_TRIGGER_FILES.has('implementation.ts')).toBe(true)
26
- expect(DOMAIN_SET_TRIGGER_FILES.has('domain.ts')).toBe(true)
26
+ expect(DOMAIN_SET_TRIGGER_FILES.has('application.ts')).toBe(true)
27
+ expect(DOMAIN_SET_TRIGGER_FILES.has('schema.ts')).toBe(true)
27
28
  })
28
29
 
29
- test('composition and handler source changes invalidate the schema bundle', () => {
30
- expect(affectsBundle(handle, join(handle.root, 'implementation.ts'))).toBe(true)
31
- expect(affectsBundle(handle, join(handle.root, 'domain.ts'))).toBe(true)
30
+ test('Application, Runtime, Action, and Workflow changes invalidate the schema bundle', () => {
31
+ expect(affectsBundle(handle, join(handle.root, 'application.ts'))).toBe(true)
32
+ expect(affectsBundle(handle, join(handle.root, 'runtime.ts'))).toBe(true)
32
33
  expect(affectsBundle(handle, join(handle.root, 'actions', 'risk', 'create.ts'))).toBe(true)
33
- expect(affectsBundle(handle, join(handle.root, 'functions', 'user', 'ensure.ts'))).toBe(true)
34
- expect(affectsBundle(handle, join(handle.root, 'handlers', 'create.ts'))).toBe(true)
34
+ expect(affectsBundle(handle, join(handle.root, 'workflows', 'user', 'ensure.ts'))).toBe(true)
35
35
  expect(affectsBundle(handle, join(handle.root, 'views', 'routes.ts'))).toBe(false)
36
36
  })
@@ -19,10 +19,9 @@ export const ANATOMY_PATHS = [...ANATOMY_GLOBS.files, ...ANATOMY_GLOBS.dirs]
19
19
  // part of the schema bundle cache even though they are outside schema/ itself.
20
20
  const BUNDLE_SOURCE_DIRS = new Set([
21
21
  'actions',
22
- 'capabilities',
23
- 'functions',
24
- 'handlers',
22
+ 'integrations',
25
23
  'mutations',
24
+ 'providers',
26
25
  'queries',
27
26
  'rules',
28
27
  'runtime',
@@ -42,7 +41,12 @@ function ignored(p: string): boolean {
42
41
  export function affectsBundle(handle: DomainHandle, path: string): boolean {
43
42
  const rel = relative(handle.root, path).split('\\').join('/')
44
43
  const topLevel = rel.split('/')[0]
45
- return rel === 'implementation.ts' || rel === 'domain.ts' || BUNDLE_SOURCE_DIRS.has(topLevel)
44
+ return (
45
+ path === handle.applicationFile ||
46
+ rel === 'runtime.ts' ||
47
+ rel.endsWith('/runtime.ts') ||
48
+ BUNDLE_SOURCE_DIRS.has(topLevel)
49
+ )
46
50
  }
47
51
 
48
52
  export function watchDomain(handle: DomainHandle): () => void {
@@ -19,8 +19,8 @@ const IGNORED =
19
19
  // only these file changes can change the domain SET (vs. ordinary in-domain edits)
20
20
  export const DOMAIN_SET_TRIGGER_FILES = new Set([
21
21
  'astrale.config.ts',
22
- 'implementation.ts',
23
- 'domain.ts',
22
+ 'application.ts',
23
+ 'schema.ts',
24
24
  'index.ts',
25
25
  ])
26
26