@astrale-os/cli 1.0.0-beta.1 → 1.0.0-beta.11

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 (329) hide show
  1. package/README.md +23 -12
  2. package/dist/astrale.js +48048 -56798
  3. package/dist/public/connect-core.js +2011 -30765
  4. package/dist/public/keys/index.js +884 -29483
  5. package/dist/public/paths/index.js +13101 -41459
  6. package/dist/types/admin/binding.d.ts +19 -0
  7. package/dist/types/admin/instance/client.d.ts +22 -0
  8. package/dist/types/admin/instance/index.d.ts +2 -0
  9. package/dist/types/admin/instance/model.d.ts +5 -12
  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 +26 -168
  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/meta.d.ts +2 -2
  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 +91 -0
  38. package/dist/types/lib/validation.d.ts +4 -1
  39. package/package.json +16 -19
  40. package/src/__tests__/fixtures/publication.ts +20 -0
  41. package/src/admin/__tests__/binding.test.ts +31 -0
  42. package/src/admin/__tests__/fixture.ts +101 -0
  43. package/src/admin/binding.ts +98 -0
  44. package/src/admin/catalog/.spec/api.d.ts +2 -2
  45. package/src/admin/catalog/__tests__/client.test.ts +20 -49
  46. package/src/admin/catalog/client.ts +36 -32
  47. package/src/admin/catalog/model.ts +3 -4
  48. package/src/admin/graph/.spec/api.d.ts +4 -10
  49. package/src/admin/graph/nodes.ts +1 -1
  50. package/src/admin/instance/.spec/api.d.ts +2 -2
  51. package/src/admin/instance/__tests__/client.test.ts +39 -164
  52. package/src/admin/instance/client.ts +35 -124
  53. package/src/admin/instance/index.ts +1 -2
  54. package/src/admin/instance/model.ts +11 -20
  55. package/src/commands/__tests__/admin-instance.test.ts +11 -8
  56. package/src/commands/__tests__/auth-login.test.ts +54 -1
  57. package/src/commands/__tests__/call-describe.test.ts +46 -33
  58. package/src/commands/__tests__/call.test.ts +5 -1
  59. package/src/commands/__tests__/domain-install-operation.test.ts +12 -7
  60. package/src/commands/__tests__/domain-install-owned.test.ts +6 -2
  61. package/src/commands/__tests__/domain-list.test.ts +63 -4
  62. package/src/commands/__tests__/install-identity-override.test.ts +19 -19
  63. package/src/commands/__tests__/instance-list-rows.test.ts +1 -1
  64. package/src/commands/__tests__/instance-status.test.ts +139 -0
  65. package/src/commands/__tests__/read-commands.test.ts +35 -10
  66. package/src/commands/__tests__/studio-descriptor.test.ts +22 -0
  67. package/src/commands/__tests__/update.test.ts +48 -19
  68. package/src/commands/call-describe.ts +60 -68
  69. package/src/commands/call.ts +43 -56
  70. package/src/commands/domain/install.ts +13 -17
  71. package/src/commands/domain/list.ts +18 -13
  72. package/src/commands/domain/publish.ts +14 -11
  73. package/src/commands/domain/uninstall.ts +2 -2
  74. package/src/commands/get.ts +14 -15
  75. package/src/commands/identity/__tests__/register.test.ts +3 -3
  76. package/src/commands/identity/register.ts +5 -4
  77. package/src/commands/instance/create.ts +8 -16
  78. package/src/commands/instance/delete.ts +12 -9
  79. package/src/commands/instance/list.ts +2 -2
  80. package/src/commands/instance/status.ts +66 -20
  81. package/src/commands/instance/use.ts +16 -12
  82. package/src/commands/introspect.ts +9 -16
  83. package/src/commands/logs.ts +24 -25
  84. package/src/commands/mutate.ts +6 -5
  85. package/src/commands/query.ts +27 -30
  86. package/src/commands/studio.ts +20 -0
  87. package/src/commands/token.ts +8 -7
  88. package/src/commands/update.ts +38 -14
  89. package/src/commands/view.ts +7 -6
  90. package/src/connection/.spec/api.d.ts +7 -8
  91. package/src/connection/.spec/architecture.md +5 -4
  92. package/src/connection/.spec/flows/session.ts +2 -2
  93. package/src/connection/.spec/laws/connection.ts +6 -2
  94. package/src/connection/.spec/layout.ts +1 -0
  95. package/src/connection/__tests__/credential.test.ts +20 -1
  96. package/src/connection/__tests__/errors.test.ts +43 -32
  97. package/src/connection/__tests__/exchange.test.ts +36 -6
  98. package/src/connection/__tests__/failure-fixtures.ts +39 -0
  99. package/src/connection/__tests__/failure-safety.test.ts +75 -0
  100. package/src/connection/__tests__/self.test.ts +31 -11
  101. package/src/connection/__tests__/session.test.ts +3 -3
  102. package/src/connection/__tests__/target.test.ts +1 -0
  103. package/src/connection/auth.ts +13 -0
  104. package/src/connection/call.ts +1 -1
  105. package/src/connection/credential.ts +2 -2
  106. package/src/connection/errors.ts +1 -355
  107. package/src/connection/exchange.ts +52 -27
  108. package/src/connection/failure/classify.ts +110 -0
  109. package/src/connection/failure/index.ts +18 -0
  110. package/src/connection/failure/model.ts +28 -0
  111. package/src/connection/failure/render.ts +116 -0
  112. package/src/connection/reasons.ts +16 -0
  113. package/src/connection/self.ts +39 -21
  114. package/src/connection/session.ts +19 -8
  115. package/src/errors.ts +3 -2
  116. package/src/graph/.spec/api.d.ts +12 -5
  117. package/src/graph/.spec/layout.ts +9 -1
  118. package/src/graph/__tests__/mutation.test.ts +2 -2
  119. package/src/graph/__tests__/query.test.ts +25 -6
  120. package/src/graph/class.ts +30 -0
  121. package/src/graph/index.ts +1 -0
  122. package/src/graph/query.ts +21 -32
  123. package/src/identity/.spec/api.d.ts +2 -2
  124. package/src/identity/__tests__/registration.test.ts +1 -1
  125. package/src/identity/registration.ts +3 -3
  126. package/src/keys/__tests__/keys.test.ts +4 -0
  127. package/src/keys/credential.ts +1 -0
  128. package/src/lib/__tests__/admin-target.test.ts +12 -0
  129. package/src/lib/__tests__/command-dx.test.ts +1 -1
  130. package/src/lib/__tests__/domain-publication.test.ts +138 -0
  131. package/src/lib/__tests__/idp-session.test.ts +22 -0
  132. package/src/lib/__tests__/idp.test.ts +36 -4
  133. package/src/lib/__tests__/instance-candidates.test.ts +1 -3
  134. package/src/lib/__tests__/instance-target.test.ts +7 -39
  135. package/src/lib/__tests__/instance.test.ts +6 -0
  136. package/src/lib/__tests__/log-errors.test.ts +64 -0
  137. package/src/lib/__tests__/studio-server-deps.test.ts +53 -16
  138. package/src/lib/__tests__/update.test.ts +113 -8
  139. package/src/lib/__tests__/view-open-intent.test.ts +0 -2
  140. package/src/lib/__tests__/view-server.test.ts +18 -3
  141. package/src/lib/__tests__/view-session.test.ts +1 -1
  142. package/src/lib/admin-instance.ts +14 -8
  143. package/src/lib/admin-target.ts +21 -2
  144. package/src/lib/command-dx.ts +9 -9
  145. package/src/lib/domain-publication.ts +104 -0
  146. package/src/lib/failure-debug.ts +26 -0
  147. package/src/lib/idp.ts +39 -4
  148. package/src/lib/instance-candidates.ts +2 -2
  149. package/src/lib/instance-target.ts +3 -14
  150. package/src/lib/instance.ts +22 -12
  151. package/src/lib/log.ts +16 -9
  152. package/src/lib/login-flow.ts +13 -3
  153. package/src/lib/meta.ts +2 -2
  154. package/src/lib/provision-instance.ts +34 -57
  155. package/src/lib/update.ts +124 -30
  156. package/src/lib/validation.ts +2 -2
  157. package/src/lib/view/resolve.ts +1 -1
  158. package/src/lib/view/server.ts +17 -3
  159. package/src/program/__tests__/program.test.ts +20 -4
  160. package/src/program/build.ts +2 -2
  161. package/src/setup/__tests__/instance-step.test.ts +27 -10
  162. package/src/setup/steps/instance.ts +22 -15
  163. package/studio/client/dist/assets/elk-api-DjmKsHXc.js +1 -0
  164. package/studio/client/dist/assets/index-7YHdeCxp.js +81 -0
  165. package/studio/client/dist/assets/index-C0FAnwNw.css +2 -0
  166. package/studio/client/dist/assets/rolldown-runtime-Dd_uD5pT.js +1 -0
  167. package/studio/client/dist/assets/schema-studio-BilUNb6Z.css +1 -0
  168. package/studio/client/dist/assets/schema-studio-CABpTfvH.js +8 -0
  169. package/studio/client/dist/index.html +3 -2
  170. package/studio/package.json +10 -14
  171. package/studio/server/agent/ask.test.ts +1 -1
  172. package/studio/server/agent/bridge/grant.test.ts +1 -1
  173. package/studio/server/agent/bridge/routes.test.ts +1 -1
  174. package/studio/server/agent/bridge/stdio.ts +8 -1
  175. package/studio/server/agent/conversation.test.ts +10 -5
  176. package/studio/server/agent/conversation.ts +56 -8
  177. package/studio/server/agent/harness/claude/adapter.test.ts +15 -5
  178. package/studio/server/agent/harness/codex/loadout.ts +18 -21
  179. package/studio/server/agent/harness/gateway/config.ts +20 -18
  180. package/studio/server/agent/harness/selection.ts +9 -1
  181. package/studio/server/agent/prompts/anchors.test.ts +32 -36
  182. package/studio/server/agent/prompts/anchors.ts +20 -49
  183. package/studio/server/agent/prompts/system.test.ts +3 -2
  184. package/studio/server/agent/prompts/system.ts +6 -5
  185. package/studio/server/agent/prompts/turn.ts +13 -4
  186. package/studio/server/agent/routes.test.ts +1 -1
  187. package/studio/server/agent/run/completion.ts +2 -2
  188. package/studio/server/agent/run/coordinator.test.ts +1 -1
  189. package/studio/server/agent/run/preparation.ts +6 -5
  190. package/studio/server/agent/run/transcript.test.ts +35 -1
  191. package/studio/server/agent/run/transcript.ts +169 -3
  192. package/studio/server/agent/run/usage.test.ts +24 -0
  193. package/studio/server/agent/run/usage.ts +26 -1
  194. package/studio/server/api/canvas.ts +43 -0
  195. package/studio/server/api/comments.ts +85 -0
  196. package/studio/server/api/context.ts +61 -0
  197. package/studio/server/api/deployment.ts +39 -0
  198. package/studio/server/api/documents.ts +55 -0
  199. package/studio/server/api/domain.ts +59 -0
  200. package/studio/server/api/http.ts +45 -0
  201. package/studio/server/api/project.ts +57 -0
  202. package/studio/server/api/schema.ts +12 -0
  203. package/studio/server/api/views.ts +57 -0
  204. package/studio/server/api/workspace.ts +60 -0
  205. package/studio/server/api-agent-loadout.test.ts +1 -1
  206. package/studio/server/api.test.ts +147 -0
  207. package/studio/server/api.ts +20 -422
  208. package/studio/server/cache.test.ts +122 -0
  209. package/studio/server/cache.ts +162 -11
  210. package/studio/server/cli-consumers.test.ts +494 -0
  211. package/studio/server/cli.test.ts +88 -0
  212. package/studio/server/cli.ts +240 -0
  213. package/studio/server/client-package.ts +25 -1
  214. package/studio/server/domain.test.ts +50 -40
  215. package/studio/server/domain.ts +83 -52
  216. package/studio/server/environment/dotenv-preview.test.ts +39 -0
  217. package/studio/server/environment/dotenv-preview.ts +27 -0
  218. package/studio/server/environment/files.test.ts +53 -0
  219. package/studio/server/{state/env.ts → environment/files.ts} +7 -48
  220. package/studio/server/{state → handoff}/copy.ts +21 -6
  221. package/studio/server/handoff/service.test.ts +22 -0
  222. package/studio/server/{state/handoff.ts → handoff/service.ts} +21 -14
  223. package/studio/server/index.ts +1 -1
  224. package/studio/server/instances/active.ts +72 -0
  225. package/studio/server/instances/deploy-record.test.ts +31 -0
  226. package/studio/server/instances/deploy-record.ts +37 -0
  227. package/studio/server/instances/deploy.ts +56 -0
  228. package/studio/server/{state/instance.test.ts → instances/probe.test.ts} +25 -21
  229. package/studio/server/instances/probe.ts +67 -0
  230. package/studio/server/instances/status.test.ts +12 -0
  231. package/studio/server/instances/status.ts +49 -0
  232. package/studio/server/introspect/anatomy/client-tree.ts +57 -0
  233. package/studio/server/introspect/anatomy/env-fields.ts +66 -0
  234. package/studio/server/introspect/anatomy/schema-definition.ts +53 -0
  235. package/studio/server/introspect/anatomy/source.ts +181 -0
  236. package/studio/server/introspect/anatomy/views/routes.ts +114 -0
  237. package/studio/server/introspect/anatomy/views.ts +53 -0
  238. package/studio/server/introspect/anatomy-extras.test.ts +106 -35
  239. package/studio/server/introspect/anatomy-extras.ts +7 -726
  240. package/studio/server/introspect/anatomy.test.ts +22 -14
  241. package/studio/server/introspect/anatomy.ts +52 -28
  242. package/studio/server/introspect/bundle.ts +15 -9
  243. package/studio/server/introspect/canonical-schema.test.ts +93 -309
  244. package/studio/server/introspect/canonical-schema.ts +257 -425
  245. package/studio/server/introspect/config-preview.test.ts +32 -0
  246. package/studio/server/introspect/config-preview.ts +119 -0
  247. package/studio/server/introspect/core-extractor.ts +18 -127
  248. package/studio/server/introspect/core.ts +1 -2
  249. package/studio/server/introspect/diff.test.ts +18 -18
  250. package/studio/server/introspect/diff.ts +44 -90
  251. package/studio/server/introspect/extractor.ts +23 -116
  252. package/studio/server/introspect/hash.ts +5 -2
  253. package/studio/server/introspect/overlay-tsmorph.test.ts +119 -240
  254. package/studio/server/introspect/overlay-tsmorph.ts +7 -1305
  255. package/studio/server/introspect/overlay.test.ts +26 -54
  256. package/studio/server/introspect/overlay.ts +10 -37
  257. package/studio/server/introspect/revision.test.ts +54 -0
  258. package/studio/server/introspect/revision.ts +49 -0
  259. package/studio/server/introspect/runtime.test.ts +83 -143
  260. package/studio/server/introspect/runtime.ts +40 -11
  261. package/studio/server/introspect/schema-ir-json.test.ts +70 -0
  262. package/studio/server/introspect/schema-ir-json.ts +151 -0
  263. package/studio/server/introspect/schema-refs.test.ts +43 -88
  264. package/studio/server/introspect/schema-refs.ts +14 -49
  265. package/studio/server/introspect/source-overlay/annotations.ts +14 -0
  266. package/studio/server/introspect/source-overlay/handlers.ts +161 -0
  267. package/studio/server/introspect/source-overlay/kernel-calls.ts +46 -0
  268. package/studio/server/introspect/source-overlay/project.ts +248 -0
  269. package/studio/server/introspect/source-overlay/spans.ts +330 -0
  270. package/studio/server/json.ts +46 -0
  271. package/studio/server/lifecycle.ts +5 -1
  272. package/studio/server/sse.test.ts +26 -0
  273. package/studio/server/sse.ts +4 -1
  274. package/studio/server/state/baseline.test.ts +223 -7
  275. package/studio/server/state/baseline.ts +148 -34
  276. package/studio/server/state/comments.test.ts +66 -1
  277. package/studio/server/state/comments.ts +173 -10
  278. package/studio/server/state/context.ts +34 -2
  279. package/studio/server/state/documents.ts +42 -1
  280. package/studio/server/state/integrations.ts +27 -1
  281. package/studio/server/state/layout.test.ts +34 -0
  282. package/studio/server/state/layout.ts +44 -17
  283. package/studio/server/state/settings.ts +29 -22
  284. package/studio/server/state/store.test.ts +122 -0
  285. package/studio/server/state/store.ts +66 -17
  286. package/studio/server/state/visibility.ts +22 -11
  287. package/studio/server/views/model.test.ts +57 -0
  288. package/studio/server/views/model.ts +66 -0
  289. package/studio/server/views/runtime.ts +40 -0
  290. package/studio/server/views/selection-repository.test.ts +31 -0
  291. package/studio/server/views/selection-repository.ts +60 -0
  292. package/studio/server/views/session.test.ts +73 -0
  293. package/studio/server/views/session.ts +166 -0
  294. package/studio/server/views/target.test.ts +78 -0
  295. package/studio/server/views/target.ts +222 -0
  296. package/studio/server/watch.test.ts +11 -11
  297. package/studio/server/watch.ts +9 -5
  298. package/studio/server/workspace/catalog.test.ts +17 -0
  299. package/studio/server/workspace/catalog.ts +43 -0
  300. package/studio/server/{state → workspace}/create.test.ts +1 -1
  301. package/studio/server/{state → workspace}/create.ts +1 -1
  302. package/studio/server/{state → workspace}/git.ts +1 -1
  303. package/studio/server/workspace/updates.ts +83 -0
  304. package/studio/server/workspace-state.ts +1 -1
  305. package/studio/server/workspace-watch.ts +2 -2
  306. package/studio/shared/contracts/README.md +16 -0
  307. package/studio/shared/contracts/agent.ts +270 -0
  308. package/studio/shared/contracts/runtime.ts +50 -0
  309. package/studio/shared/contracts/schema.ts +393 -0
  310. package/studio/shared/contracts/surface.test.ts +317 -0
  311. package/studio/shared/contracts/workspace.ts +265 -0
  312. package/studio/shared/layout.test.ts +116 -0
  313. package/studio/shared/schema/identity.test.ts +34 -0
  314. package/studio/shared/schema/identity.ts +68 -0
  315. package/studio/shared/types.ts +11 -1099
  316. package/studio/tsconfig.json +1 -1
  317. package/viewer/dist/main.js +40 -61
  318. package/.check-workspace.cjs +0 -40
  319. package/src/commands/__tests__/instance-create-hosts.test.ts +0 -29
  320. package/studio/client/dist/assets/elk-api-D2xgMJvi.js +0 -1
  321. package/studio/client/dist/assets/index-BMdnsIJA.css +0 -1
  322. package/studio/client/dist/assets/index-ChOr3yP0.css +0 -1
  323. package/studio/client/dist/assets/index-D-vRV8w7.js +0 -8
  324. package/studio/client/dist/assets/index-LGSWRrk8.js +0 -81
  325. package/studio/server/state/catalog.ts +0 -117
  326. package/studio/server/state/instance.ts +0 -280
  327. package/studio/server/state/updates.ts +0 -63
  328. package/studio/server/state/views.test.ts +0 -286
  329. package/studio/server/state/views.ts +0 -535
@@ -0,0 +1,265 @@
1
+ /**
2
+ * Shared workspace and persisted-state contracts.
3
+ *
4
+ * This module owns the JSON shapes written below `.domain-studio/` and the
5
+ * workspace summaries derived around them. Server stores consume these types;
6
+ * they do not redeclare the persisted state.
7
+ */
8
+
9
+ import type { SchemaRevision } from './schema'
10
+
11
+ /** A kernel instance the CLI knows about (a local bookmark or an admin-managed one). */
12
+ export interface InstanceInfo {
13
+ name: string
14
+ url: string
15
+ active: boolean
16
+ kind: 'bookmark' | 'managed'
17
+ }
18
+
19
+ /** Global (NOT per-domain) — the CLI's instances + which is active. Source of truth: `astrale instance list`. */
20
+ export interface InstancesState {
21
+ active: string | null
22
+ instances: InstanceInfo[]
23
+ }
24
+
25
+ /** What the studio recorded the last time it ran a deploy for this domain. */
26
+ export interface DeployRecord {
27
+ at: string
28
+ /** UI/cache fingerprint recorded by Studio; not a canonical schema revision. */
29
+ renderFingerprint: string
30
+ ok: boolean
31
+ url?: string
32
+ }
33
+
34
+ /** Per-domain deploy/install state (the active instance is global — see InstancesState). */
35
+ export interface InstanceStatus {
36
+ /** the domain's configured deploy target (astrale.config.ts prod.instance) */
37
+ deployTarget: string | null
38
+ /** has a `prod` script → deployable via `pnpm prod` */
39
+ deployable: boolean
40
+ /** GROUND TRUTH — queried from `astrale introspect <origin> --bundle`, not local state.
41
+ * 'unknown' = the instance couldn't be reached/queried (no target, not authed, offline). */
42
+ install: 'installed' | 'not-installed' | 'unknown'
43
+ /** local schema vs the schema actually INSTALLED on the instance (ground truth) */
44
+ drift: 'in-sync' | 'drifted' | 'unknown'
45
+ /** Canonical revisions compared only after local and installed SDK admission. */
46
+ localRevision: SchemaRevision | null
47
+ installedRevision: SchemaRevision | null
48
+ /** the studio's own last deploy — supplementary (service URL / when), not the source of truth */
49
+ lastDeploy: DeployRecord | null
50
+ }
51
+
52
+ export interface DeployResult {
53
+ ok: boolean
54
+ url: string | null
55
+ output: string
56
+ }
57
+
58
+ export type ThreadRole = 'user' | 'author'
59
+ export type ThreadEntryType = 'text' | 'choice'
60
+
61
+ export interface ThreadEntry {
62
+ id: string
63
+ role: ThreadRole
64
+ type: ThreadEntryType
65
+ text: string
66
+ options?: string[]
67
+ answer?: string | null
68
+ }
69
+
70
+ export type AnchorKind = 'schema' | 'section' | 'file' | 'free'
71
+
72
+ export interface AnchorRef {
73
+ ref: string
74
+ kind: AnchorKind
75
+ file?: string
76
+ startLine?: number
77
+ endLine?: number
78
+ label?: string
79
+ /** Flow-canvas coordinates for section-level canvas comments. */
80
+ x?: number
81
+ y?: number
82
+ }
83
+
84
+ export interface Comment {
85
+ id: string
86
+ /** annotate-compatible: array of string excerpts */
87
+ anchors: string[]
88
+ /** studio-only, index-aligned to `anchors` */
89
+ anchorRefs: AnchorRef[]
90
+ status: 'open' | 'closed'
91
+ closeNote?: string
92
+ thread: ThreadEntry[]
93
+ createdAt: string
94
+ /** derived: a thread whose first entry is role:'author' is a question */
95
+ kind: 'comment' | 'question'
96
+ /** set when the anchor ref no longer resolves against the current schema */
97
+ orphaned?: boolean
98
+ }
99
+
100
+ export interface CommentStore {
101
+ /** Historical annotate wire key; contains Studio's render fingerprint. */
102
+ schemaVersion: string
103
+ comments: Comment[]
104
+ }
105
+
106
+ export interface MergeResult {
107
+ merged: number
108
+ closed: number
109
+ unknownIds: string[]
110
+ schemaMismatch: boolean
111
+ pastedSchemaVersion?: string
112
+ }
113
+
114
+ export type SchemaChangeKind =
115
+ | 'schema-metadata-changed'
116
+ | 'import-added'
117
+ | 'import-removed'
118
+ | 'import-changed'
119
+ | 'class-added'
120
+ | 'class-removed'
121
+ | 'class-contract-changed'
122
+ | 'edge-added'
123
+ | 'edge-removed'
124
+ | 'edge-contract-changed'
125
+ | 'definition-metadata-changed'
126
+ | 'prop-added'
127
+ | 'prop-removed'
128
+ | 'prop-type-changed'
129
+ | 'prop-schema-changed'
130
+ | 'prop-required-changed'
131
+ | 'method-added'
132
+ | 'method-removed'
133
+ | 'method-signature-changed'
134
+ | 'method-metadata-changed'
135
+ | 'function-added'
136
+ | 'function-removed'
137
+ | 'function-signature-changed'
138
+ | 'function-metadata-changed'
139
+ | 'view-added'
140
+ | 'view-removed'
141
+ | 'view-changed'
142
+ | 'view-metadata-changed'
143
+ | 'policy-added'
144
+ | 'policy-removed'
145
+ | 'policy-changed'
146
+ | 'dependency-added'
147
+ | 'dependency-removed'
148
+ | 'dependency-changed'
149
+ | 'core-changed'
150
+
151
+ export interface SchemaChange {
152
+ kind: SchemaChangeKind
153
+ target: string
154
+ detail?: string
155
+ }
156
+
157
+ export interface FileChange {
158
+ file: string
159
+ status: 'added' | 'modified' | 'removed'
160
+ }
161
+
162
+ export interface ChangeSet {
163
+ source: 'baseline' | 'git'
164
+ hasGit: boolean
165
+ hasBaseline: boolean
166
+ schemaChanges: SchemaChange[]
167
+ fileChanges: FileChange[]
168
+ schemaDiffText?: string
169
+ /** Describes Studio-observed structure only; never a Runtime migration verdict. */
170
+ structuralStatus: 'none' | 'changed'
171
+ baselineRevision?: SchemaRevision
172
+ currentRevision?: SchemaRevision
173
+ baselineCapturedAt?: string
174
+ }
175
+
176
+ export interface ContextItem {
177
+ id: string
178
+ bucket: 'user' | 'auto'
179
+ title: string
180
+ body: string
181
+ source?: string
182
+ updatedAt: string
183
+ /** auto items: included in the copy payload only when true */
184
+ includeInHandoff?: boolean
185
+ freshness?: string
186
+ }
187
+
188
+ export interface ContextStore {
189
+ user: ContextItem[]
190
+ auto: ContextItem[]
191
+ }
192
+
193
+ /** A document the user drops in as context for the AI agent. */
194
+ export interface DocMeta {
195
+ id: string
196
+ name: string
197
+ type: string
198
+ size: number
199
+ addedAt: string
200
+ updatedAt?: string
201
+ /** relative path under the dotted folder (server-side) */
202
+ stored: string
203
+ }
204
+
205
+ export interface Integration {
206
+ id: string
207
+ name: string
208
+ kind: string
209
+ status: 'planned' | 'active' | 'deprecated' | string
210
+ notes?: string
211
+ }
212
+
213
+ export interface IntegrationsState {
214
+ integrations: Integration[]
215
+ detectedSubfolders: string[]
216
+ }
217
+
218
+ /** A domain in the catalog — local to this workspace, a faked external service, or the kernel. */
219
+ export interface DomainCatalogEntry {
220
+ origin: string
221
+ name: string
222
+ kind: 'kernel' | 'local' | 'external'
223
+ description: string
224
+ /** raw lucide-style SVG icon (stroke="currentColor") */
225
+ icon: string
226
+ /** kernel is always present + required */
227
+ required?: boolean
228
+ }
229
+
230
+ export interface DomainSummary {
231
+ id: string
232
+ origin: string
233
+ path: string
234
+ schemaDir: string
235
+ depsInstalled: boolean
236
+ hasGit: boolean
237
+ configFile: string
238
+ }
239
+
240
+ export interface CopyPayload {
241
+ markdown: string
242
+ openComments: number
243
+ }
244
+
245
+ export interface NodePosition {
246
+ x: number
247
+ y: number
248
+ /** persisted size — only expanded module containers carry one. */
249
+ w?: number
250
+ h?: number
251
+ }
252
+
253
+ /** Persisted manual graph layout. This is the sole authority for its JSON shape. */
254
+ export interface LayoutState {
255
+ renderFingerprint?: string
256
+ positions: Record<string, NodePosition>
257
+ }
258
+
259
+ /** Persisted per-domain canvas visibility. This is the sole authority for its JSON shape. */
260
+ export interface VisibilityState {
261
+ /** Refs hidden on the canvas: `class.X` | `edge.X` | `domain.<origin>`. */
262
+ hidden: Record<string, true>
263
+ /** Whether local Class inheritance edges are rendered. */
264
+ showInheritedEdges: boolean
265
+ }
@@ -0,0 +1,116 @@
1
+ import { expect, test } from 'bun:test'
2
+ import { readdirSync, readFileSync, statSync } from 'node:fs'
3
+ import { dirname, join, relative, resolve } from 'node:path'
4
+
5
+ const STUDIO_ROOT = resolve(import.meta.dir, '..')
6
+ const CLIENT_ROOT = join(STUDIO_ROOT, 'client', 'src')
7
+ const SERVER_ROOT = join(STUDIO_ROOT, 'server')
8
+ const SHARED_ROOT = join(STUDIO_ROOT, 'shared')
9
+ const STATE_ROOT = join(SERVER_ROOT, 'state')
10
+
11
+ function productionFiles(dir: string): string[] {
12
+ return readdirSync(dir)
13
+ .flatMap((entry) => {
14
+ const path = join(dir, entry)
15
+ if (statSync(path).isDirectory()) return productionFiles(path)
16
+ if (!/\.(?:ts|tsx)$/.test(path) || /\.test\.(?:ts|tsx)$/.test(path)) return []
17
+ return [path]
18
+ })
19
+ .sort()
20
+ }
21
+
22
+ const files = [
23
+ ...productionFiles(CLIENT_ROOT),
24
+ ...productionFiles(SERVER_ROOT),
25
+ ...productionFiles(SHARED_ROOT),
26
+ ]
27
+ const fileSet = new Set(files)
28
+
29
+ function resolveLocalImport(file: string, specifier: string): string | null {
30
+ const target = specifier.startsWith('@/')
31
+ ? join(CLIENT_ROOT, specifier.slice(2))
32
+ : specifier.startsWith('@shared/')
33
+ ? join(SHARED_ROOT, specifier.slice('@shared/'.length))
34
+ : specifier.startsWith('.')
35
+ ? resolve(dirname(file), specifier)
36
+ : null
37
+ if (!target) return null
38
+ for (const candidate of [
39
+ target,
40
+ `${target}.ts`,
41
+ `${target}.tsx`,
42
+ join(target, 'index.ts'),
43
+ join(target, 'index.tsx'),
44
+ ]) {
45
+ if (fileSet.has(candidate)) return candidate
46
+ }
47
+ return null
48
+ }
49
+
50
+ function imports(file: string): string[] {
51
+ const source = readFileSync(file, 'utf8')
52
+ const found: string[] = []
53
+ const pattern = /(?:from\s+|import\s*(?:\(\s*)?)['"]([^'"]+)['"]\s*\)?|import\s+['"]([^'"]+)['"]/g
54
+ for (const match of source.matchAll(pattern)) {
55
+ const target = resolveLocalImport(file, match[1] ?? match[2])
56
+ if (target) found.push(target)
57
+ }
58
+ return found
59
+ }
60
+
61
+ const studioPath = (file: string) => relative(STUDIO_ROOT, file).replaceAll('\\', '/')
62
+
63
+ test('Studio production modules form an acyclic dependency graph', () => {
64
+ const graph = new Map(files.map((file) => [file, imports(file)]))
65
+ const visiting = new Set<string>()
66
+ const visited = new Set<string>()
67
+ const stack: string[] = []
68
+ const cycles: string[][] = []
69
+
70
+ const visit = (file: string) => {
71
+ if (visiting.has(file)) {
72
+ const start = stack.indexOf(file)
73
+ cycles.push([...stack.slice(start), file].map(studioPath))
74
+ return
75
+ }
76
+ if (visited.has(file)) return
77
+ visiting.add(file)
78
+ stack.push(file)
79
+ for (const dependency of graph.get(file) ?? []) visit(dependency)
80
+ stack.pop()
81
+ visiting.delete(file)
82
+ visited.add(file)
83
+ }
84
+
85
+ for (const file of files) visit(file)
86
+ expect(cycles).toEqual([])
87
+ })
88
+
89
+ test('production boundaries keep client/shared out of server and shared out of client', () => {
90
+ const violations = files.flatMap((file) =>
91
+ imports(file)
92
+ .filter(
93
+ (dependency) =>
94
+ (dependency.startsWith(SERVER_ROOT) &&
95
+ (file.startsWith(CLIENT_ROOT) || file.startsWith(SHARED_ROOT))) ||
96
+ (file.startsWith(SHARED_ROOT) && dependency.startsWith(CLIENT_ROOT)),
97
+ )
98
+ .map((dependency) => `${studioPath(file)} -> ${studioPath(dependency)}`),
99
+ )
100
+ expect(violations).toEqual([])
101
+ })
102
+
103
+ test('state repositories do not depend on workflow modules', () => {
104
+ const workflowRoots = ['api', 'environment', 'handoff', 'instances', 'views', 'workspace'].map(
105
+ (directory) => join(SERVER_ROOT, directory),
106
+ )
107
+ const edges = files
108
+ .filter((file) => file.startsWith(STATE_ROOT))
109
+ .flatMap((file) =>
110
+ imports(file)
111
+ .filter((dependency) => workflowRoots.some((root) => dependency.startsWith(root)))
112
+ .map((dependency) => `${studioPath(file)} -> ${studioPath(dependency)}`),
113
+ )
114
+
115
+ expect(edges).toEqual([])
116
+ })
@@ -0,0 +1,34 @@
1
+ import { describe, expect, test } from 'bun:test'
2
+
3
+ import {
4
+ classRefKey,
5
+ isIrClassRef,
6
+ isIrSchemaRef,
7
+ parseClassRefKey,
8
+ parseSchemaRefKey,
9
+ schemaRefKey,
10
+ } from './identity'
11
+
12
+ describe('schema identity', () => {
13
+ test('round-trips exact Class identity', () => {
14
+ const ref = { origin: 'docs.example.dev', kind: 'class' as const, name: 'Document' }
15
+ expect(classRefKey(ref)).toBe('docs.example.dev:class.Document')
16
+ expect(parseClassRefKey(classRefKey(ref))).toEqual(ref)
17
+ expect(isIrClassRef(ref)).toBe(true)
18
+ })
19
+
20
+ test('preserves all supported schema reference kinds', () => {
21
+ const ref = { origin: 'docs.example.dev', kind: 'function' as const, name: 'search' }
22
+ expect(schemaRefKey(ref)).toBe('docs.example.dev:function.search')
23
+ expect(parseSchemaRefKey(schemaRefKey(ref))).toEqual(ref)
24
+ expect(isIrSchemaRef(ref)).toBe(true)
25
+ })
26
+
27
+ test('rejects removed Interface coordinates and malformed keys', () => {
28
+ expect(isIrSchemaRef({ origin: 'docs.example.dev', kind: 'interface', name: 'Named' })).toBe(
29
+ false,
30
+ )
31
+ expect(parseSchemaRefKey('docs.example.dev:interface.Named')).toBeUndefined()
32
+ expect(parseClassRefKey('docs.example.dev:function.search')).toBeUndefined()
33
+ })
34
+ })
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Canonical Studio identity for DomainSchema references.
3
+ *
4
+ * These helpers validate and encode only the structural wire coordinate. SDK
5
+ * admission remains the authority for whether a reference is semantically valid.
6
+ */
7
+
8
+ export const IR_SCHEMA_REF_KINDS = ['class', 'function', 'policy', 'view', 'core'] as const
9
+
10
+ export type IrSchemaRefKind = (typeof IR_SCHEMA_REF_KINDS)[number]
11
+
12
+ /** Exact structural coordinate embedded in a canonical DomainSchema V1 root. */
13
+ export interface IrSchemaRef {
14
+ origin: string
15
+ kind: IrSchemaRefKind
16
+ name: string
17
+ }
18
+
19
+ /** Canonical DSL key for a schema member: `origin:kind.name`. */
20
+ export type IrSchemaKey = `${string}:${IrSchemaRefKind}.${string}`
21
+
22
+ export type IrClassRef = Omit<IrSchemaRef, 'kind'> & { kind: 'class' }
23
+
24
+ export type IrClassKey = `${string}:class.${string}`
25
+
26
+ const schemaKinds = new Set<string>(IR_SCHEMA_REF_KINDS)
27
+ const schemaKeyPattern = /^(.+):(class|function|policy|view|core)\.(.+)$/
28
+
29
+ /** Structural guard only; it deliberately does not perform SDK admission. */
30
+ export function isIrSchemaRef(value: unknown): value is IrSchemaRef {
31
+ if (!value || typeof value !== 'object') return false
32
+ const ref = value as Partial<IrSchemaRef>
33
+ return (
34
+ typeof ref.origin === 'string' &&
35
+ typeof ref.name === 'string' &&
36
+ typeof ref.kind === 'string' &&
37
+ schemaKinds.has(ref.kind)
38
+ )
39
+ }
40
+
41
+ export function isIrClassRef(value: unknown): value is IrClassRef {
42
+ return isIrSchemaRef(value) && value.kind === 'class'
43
+ }
44
+
45
+ export function schemaRefKey(ref: IrSchemaRef): IrSchemaKey {
46
+ return `${ref.origin}:${ref.kind}.${ref.name}`
47
+ }
48
+
49
+ export function classRefKey(ref: IrClassRef): IrClassKey {
50
+ return `${ref.origin}:${ref.kind}.${ref.name}`
51
+ }
52
+
53
+ /** Parse a canonical key without asserting that the referenced member exists. */
54
+ export function parseSchemaRefKey(value: unknown): IrSchemaRef | undefined {
55
+ if (typeof value !== 'string') return undefined
56
+ const match = schemaKeyPattern.exec(value)
57
+ if (!match) return undefined
58
+ return {
59
+ origin: match[1],
60
+ kind: match[2] as IrSchemaRefKind,
61
+ name: match[3],
62
+ }
63
+ }
64
+
65
+ export function parseClassRefKey(value: unknown): IrClassRef | undefined {
66
+ const ref = parseSchemaRefKey(value)
67
+ return ref && isIrClassRef(ref) ? ref : undefined
68
+ }