@astrale-os/cli 0.8.1-alpha.7 → 1.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +15 -3
  2. package/dist/astrale.js +86 -35
  3. package/package.json +5 -5
  4. package/src/commands/__tests__/domain-install-operation.test.ts +121 -0
  5. package/src/commands/__tests__/domain-install-owned.test.ts +66 -0
  6. package/src/commands/__tests__/install-direct.test.ts +3 -2
  7. package/src/commands/domain/install.ts +78 -15
  8. package/src/connection/__tests__/errors.test.ts +82 -6
  9. package/src/connection/command.ts +9 -1
  10. package/src/connection/errors.ts +19 -8
  11. package/src/connection/index.ts +1 -1
  12. package/src/connection/reasons.ts +26 -12
  13. package/src/program/__tests__/program.test.ts +1 -1
  14. package/studio/client/dist/assets/{elk-api-D0cBetPW.js → elk-api-D2xgMJvi.js} +1 -1
  15. package/studio/client/dist/assets/{index-BQnJ5sgd.css → index-BMdnsIJA.css} +1 -1
  16. package/studio/client/dist/assets/index-D-vRV8w7.js +8 -0
  17. package/studio/client/dist/assets/index-LGSWRrk8.js +81 -0
  18. package/studio/client/dist/index.html +2 -2
  19. package/studio/package.json +1 -1
  20. package/studio/server/agent/prompts/anchors.test.ts +74 -0
  21. package/studio/server/agent/prompts/anchors.ts +85 -15
  22. package/studio/server/agent/prompts/system.test.ts +12 -0
  23. package/studio/server/agent/prompts/system.ts +6 -6
  24. package/studio/server/api.ts +1 -5
  25. package/studio/server/cache.ts +5 -2
  26. package/studio/server/domain.test.ts +67 -0
  27. package/studio/server/domain.ts +29 -6
  28. package/studio/server/index.ts +1 -3
  29. package/studio/server/introspect/anatomy-extras.test.ts +104 -1
  30. package/studio/server/introspect/anatomy-extras.ts +340 -8
  31. package/studio/server/introspect/anatomy.test.ts +33 -0
  32. package/studio/server/introspect/anatomy.ts +22 -7
  33. package/studio/server/introspect/bundle.ts +7 -1
  34. package/studio/server/introspect/canonical-schema.test.ts +395 -0
  35. package/studio/server/introspect/canonical-schema.ts +751 -0
  36. package/studio/server/introspect/core-extractor.ts +30 -10
  37. package/studio/server/introspect/core.ts +4 -2
  38. package/studio/server/introspect/diff.test.ts +124 -0
  39. package/studio/server/introspect/diff.ts +252 -23
  40. package/studio/server/introspect/extractor.ts +46 -14
  41. package/studio/server/introspect/overlay-tsmorph.test.ts +164 -1
  42. package/studio/server/introspect/overlay-tsmorph.ts +381 -106
  43. package/studio/server/introspect/overlay.test.ts +72 -0
  44. package/studio/server/introspect/overlay.ts +16 -6
  45. package/studio/server/introspect/runtime.test.ts +217 -0
  46. package/studio/server/introspect/runtime.ts +18 -6
  47. package/studio/server/introspect/schema-refs.test.ts +100 -0
  48. package/studio/server/introspect/schema-refs.ts +23 -2
  49. package/studio/server/state/baseline.test.ts +51 -0
  50. package/studio/server/state/baseline.ts +31 -2
  51. package/studio/server/state/create.test.ts +37 -0
  52. package/studio/server/state/create.ts +21 -15
  53. package/studio/server/state/instance.test.ts +63 -0
  54. package/studio/server/state/instance.ts +65 -29
  55. package/studio/server/state/views.test.ts +209 -9
  56. package/studio/server/state/views.ts +176 -69
  57. package/studio/server/watch.test.ts +36 -0
  58. package/studio/server/watch.ts +24 -16
  59. package/studio/server/workspace-watch.ts +8 -3
  60. package/studio/shared/types.ts +164 -33
  61. package/studio/client/dist/assets/index-Dspir4w7.js +0 -81
  62. package/studio/client/dist/assets/index-bVD2KJgz.js +0 -8
  63. package/studio/server/view-dev-server.test.ts +0 -111
  64. package/studio/server/view-dev-server.ts +0 -372
@@ -1,12 +1,14 @@
1
1
  /**
2
2
  * shared/types.ts — the ONE contract shared by the Bun server and the React
3
- * client. Shapes under "DSL Schema IR" mirror EXACTLY what `D.$.ir` /
4
- * `serialize(schema)` emit (verified empirically against my-domain + evaluation):
5
- * ir = { version, domain, types, interfaces, classes, imports }
3
+ * client. Shapes under "DSL Schema IR" retain the legacy `D.$.ir` projection
4
+ * while carrying the richer canonical DomainSchema V1 coordinates when they
5
+ * are available:
6
+ * ir = { version, domain, types, interfaces, classes, imports, functions, views? }
6
7
  * class = { type:'node'|'edge', name, implements?, endpoints?(edge), properties, methods }
7
8
  * interface = { type:'interface', name, extends?, properties, methods }
8
9
  * method = { name, params:{name->JsonSchema}, returns:JsonSchema, static, inheritance }
9
- * imports = { name -> { origin, definition:'interface'|'class' } }
10
+ * importsByKey = { 'origin:kind.Name' -> exact imported definition }
11
+ * imports = unambiguous legacy aliases by short name
10
12
  * Everything under "Studio overlay/state" is the studio's own augmentation.
11
13
  */
12
14
 
@@ -30,25 +32,91 @@ export interface JsonSchema {
30
32
 
31
33
  export type MethodInheritance = 'default' | 'abstract' | 'sealed'
32
34
 
35
+ /** Exact structural coordinate embedded in a canonical DomainSchema V1 root. */
36
+ export interface IrSchemaRef {
37
+ origin: string
38
+ kind: 'type' | 'interface' | 'class' | 'function' | 'policy' | 'view' | 'core'
39
+ name: string
40
+ }
41
+
42
+ /** Canonical DSL Key for a schema member: `origin:kind.name`. */
43
+ export type IrSchemaKey = `${string}:${IrSchemaRef['kind']}.${string}`
44
+
45
+ export type IrDefinitionRef = Omit<IrSchemaRef, 'kind'> & {
46
+ kind: 'class' | 'interface'
47
+ }
48
+
49
+ export type IrDefinitionKey = `${string}:${IrDefinitionRef['kind']}.${string}`
50
+
51
+ export type IrCallableAuth = 'anonymous' | 'authenticated' | 'authorized'
52
+
53
+ export type IrCallableOutput =
54
+ | { mode: 'value'; schema: JsonSchema }
55
+ | { mode: 'stream'; item: JsonSchema }
56
+ | { mode: 'binary' }
57
+
33
58
  export interface IrMethod {
34
59
  name: string
60
+ /** Canonical callable input. Legacy projections expose only `params`. */
61
+ input?: JsonSchema
35
62
  params: Record<string, JsonSchema>
63
+ /** Names required by canonical `input.required`; absent on legacy Methods. */
64
+ requiredParams?: string[]
65
+ /** Canonical discriminated output. Legacy projections expose only `returns`. */
66
+ output?: IrCallableOutput
36
67
  returns: JsonSchema
37
68
  static: boolean
38
69
  inheritance: MethodInheritance
70
+ description?: string
71
+ auth?: IrCallableAuth
72
+ policy?: unknown
73
+ }
74
+
75
+ /** Standalone Domain Function projected into the Studio's callable vocabulary. */
76
+ export interface IrFunction {
77
+ name: string
78
+ input: JsonSchema
79
+ params: Record<string, JsonSchema>
80
+ /** Names required by canonical `input.required`. */
81
+ requiredParams?: string[]
82
+ output: IrCallableOutput
83
+ returns: JsonSchema
84
+ /** Standalone Functions have no receiver; these legacy-compatible fields let
85
+ * existing callable renderers consume them alongside static Methods. */
86
+ static: true
87
+ inheritance: 'default'
88
+ description?: string
89
+ auth?: IrCallableAuth
90
+ policy?: unknown
39
91
  }
40
92
 
41
93
  export interface IrInterface {
42
94
  type: 'interface'
43
95
  name: string
96
+ /** Canonical declaration owner/family; absent on legacy projections. */
97
+ origin?: string
98
+ family?: 'node' | 'edge' | 'both'
99
+ ref?: IrSchemaRef
44
100
  extends?: string[]
101
+ extendsRefs?: IrSchemaRef[]
45
102
  properties: Record<string, JsonSchema>
103
+ /** Canonical `properties.required`; absence, unlike null, encodes optionality. */
104
+ required?: string[]
46
105
  methods: Record<string, IrMethod>
106
+ endpoints?: IrEndpoint[]
107
+ orientation?: 'directed' | 'undirected'
108
+ constraints?: { noSelf?: true; acyclic?: true }
109
+ description?: string
110
+ propertyMetadata?: Record<string, unknown>
111
+ /** Canonical data declaration; `mediaType` is required and extensions stay lossless. */
112
+ data?: { mediaType: string; [key: string]: unknown }
47
113
  }
48
114
 
49
115
  export interface IrEndpoint {
50
116
  name: string
51
117
  types: string[]
118
+ /** Exact accepted Definition coordinates. `types` remains for existing UI consumers. */
119
+ refs?: IrSchemaRef[]
52
120
  /** declared multiplicity for this end; max:null = unbounded ("many"). Absent ⇒ unconstrained. */
53
121
  cardinality?: { min: number; max: number | null }
54
122
  }
@@ -56,37 +124,78 @@ export interface IrEndpoint {
56
124
  export interface IrClass {
57
125
  type: 'node' | 'edge'
58
126
  name: string
127
+ /** Canonical declaration owner/ref; absent on legacy projections. */
128
+ origin?: string
129
+ ref?: IrSchemaRef
59
130
  implements?: string[]
131
+ implementsRefs?: IrSchemaRef[]
60
132
  /** edges only: the two (source,target) endpoints with role names + allowed types */
61
133
  endpoints?: IrEndpoint[]
134
+ orientation?: 'directed' | 'undirected'
135
+ constraints?: { noSelf?: true; acyclic?: true }
62
136
  properties: Record<string, JsonSchema>
137
+ /** Canonical `properties.required`; absence, unlike null, encodes optionality. */
138
+ required?: string[]
63
139
  methods: Record<string, IrMethod>
64
140
  /** class-level icon: raw (lucide-style) SVG markup, `stroke="currentColor"` */
65
141
  icon?: string
142
+ description?: string
143
+ propertyMetadata?: Record<string, unknown>
144
+ /** Canonical data declaration; `mediaType` is required and extensions stay lossless. */
145
+ data?: { mediaType: string; [key: string]: unknown }
146
+ policies?: Record<string, IrSchemaRef>
66
147
  }
67
148
 
68
149
  export interface IrImportDescriptor {
69
150
  origin: string
70
151
  definition: 'interface' | 'class'
152
+ ref?: IrDefinitionRef
153
+ /** Canonical qualified identity; absent on legacy import descriptors. */
154
+ key?: IrDefinitionKey
155
+ }
156
+
157
+ export type IrViewTarget = { kind: 'domain' } | { kind: 'definition'; definitions: IrSchemaRef[] }
158
+
159
+ export interface IrView {
160
+ name: string
161
+ target: IrViewTarget
162
+ auth: 'required' | 'optional' | 'public'
163
+ description?: string
71
164
  }
72
165
 
73
166
  export interface SchemaIR {
74
167
  version: string
75
168
  domain: string
169
+ /** Canonical document format; absent on legacy projections. */
170
+ format?: 'astrale.dsl'
76
171
  types: Record<string, JsonSchema>
77
172
  interfaces: Record<string, IrInterface>
78
173
  classes: Record<string, IrClass>
79
174
  imports: Record<string, IrImportDescriptor>
175
+ /**
176
+ * Canonical authoritative import index, keyed by `origin:kind.name`.
177
+ * `imports` remains the unambiguous short-name compatibility index.
178
+ */
179
+ importsByKey?: Record<IrDefinitionKey, IrImportDescriptor>
180
+ /** Exact imported Interface bodies under the same collision-free identity. */
181
+ importedInterfacesByKey?: Record<IrDefinitionKey, IrInterface>
182
+ /** Canonical V1 members absent from the legacy serializer projection. */
183
+ functions: Record<string, IrFunction>
184
+ views?: Record<string, IrView>
185
+ policies?: Record<string, unknown>
186
+ dependencies?: Array<{ origin: string; revision: string }>
187
+ /** Exact canonical genesis declaration; absent on legacy projections. */
188
+ core?: unknown
80
189
  }
81
190
 
82
191
  // ─────────────────────────── Studio schema overlay ───────────────────────────
83
192
 
84
193
  export interface HandlerLink {
85
194
  owner: string
86
- ownerKind: 'class' | 'interface'
195
+ ownerKind: 'class' | 'interface' | 'function'
87
196
  method: string
88
197
  static: boolean
89
- /** the runtime/index.ts wiring site */
198
+ /** the legacy runtime registry or current implementation.ts wiring site */
90
199
  wiringFile?: string
91
200
  wiringLine?: number
92
201
  /** the resolved handler file (followed from the `execute` import) */
@@ -96,6 +205,8 @@ export interface HandlerLink {
96
205
  kernelCalls?: string[]
97
206
  /** declared auth policy on the runtime config; absent ⇒ defaults to 'required'. */
98
207
  auth?: 'public' | 'optional' | 'required'
208
+ /** Canonical V1 callable auth, when the handler comes from implementation.ts. */
209
+ callableAuth?: IrCallableAuth
99
210
  /** authorize hook shape: 'absent' (none), 'noop' (allow-all), 'custom' (real check). */
100
211
  authorize?: 'absent' | 'noop' | 'custom'
101
212
  /** raw source of the authorize hook (for the hover preview). */
@@ -117,7 +228,7 @@ export interface SchemaAnnotation {
117
228
  /** anchor ref key, e.g. 'class.Monitor.property.status' */
118
229
  target: string
119
230
  severity: 'warn' | 'info'
120
- code: 'ENUM_DROPPED_BY_UPDATE' | 'COMPILE_ERROR' | 'EDGE_PROP_TYPE_MISSING'
231
+ code: 'COMPILE_ERROR' | 'EDGE_PROP_TYPE_MISSING'
121
232
  message: string
122
233
  }
123
234
 
@@ -153,15 +264,17 @@ export interface StudioSchemaBundle {
153
264
  extractedBy: 'runtime-bun' | 'static-tsmorph-fallback'
154
265
  depsInstalled: boolean
155
266
  ir: SchemaIR | null
267
+ /**
268
+ * Exact canonical DomainSchema V1 root emitted by the domain. This is kept
269
+ * separate from the render-oriented IR so drift hashes the same root the
270
+ * Kernel installs. Absent for legacy `D.$.ir` domains.
271
+ */
272
+ schemaRoot?: unknown
156
273
  overlay: SchemaOverlay
157
274
  /**
158
- * Member bodies of the interfaces this domain IMPORTS — kernel mixins (Named,
159
- * Iconable, Timestamped…) and cross-domain interfaces (e.g. Notifiable). The
160
- * serializer drops these from `ir` (they appear in `ir.imports` as
161
- * {origin,definition} descriptors only), so the extractor re-serializes each
162
- * imported schema to recover them. Keyed by interface name; the origin lives in
163
- * `ir.imports[name]`. Lets the detail pane surface inherited members like
164
- * Named→name without re-parsing the kernel. Empty when deps aren't installed.
275
+ * Unambiguous short-name aliases for imported Interface bodies, retained for
276
+ * legacy renderers. Canonical consumers use `ir.importedInterfacesByKey`, whose
277
+ * `origin:interface.Name` keys cannot collide. Empty when deps aren't installed.
165
278
  */
166
279
  importedInterfaces?: Record<string, IrInterface>
167
280
  /** present when the runtime import failed to compile (render state, not a crash) */
@@ -173,6 +286,8 @@ export interface StudioSchemaBundle {
173
286
 
174
287
  export interface DomainOverview {
175
288
  origin: string
289
+ /** Active SDK composition entry; `domain.ts` is retained for legacy projects. */
290
+ compositionFile?: 'implementation.ts' | 'domain.ts'
176
291
  adapter: 'astrale' | 'cloudflare' | 'unknown'
177
292
  prodTarget?: string
178
293
  devSecrets?: string
@@ -217,17 +332,6 @@ export interface RememberedViewTarget {
217
332
  label: string
218
333
  }
219
334
 
220
- export type ViewDevServerStatus =
221
- | {
222
- status: 'running'
223
- url: string
224
- port: number
225
- startedAt: string
226
- idleTimeoutMs: number
227
- }
228
- | { status: 'failed'; reason: string }
229
- | { status: 'unavailable'; reason: string }
230
-
231
335
  export interface ViewTargetResult {
232
336
  status: 'available' | 'unavailable'
233
337
  items: ViewTargetCandidate[]
@@ -237,12 +341,11 @@ export interface ViewTargetResult {
237
341
  reason?: string
238
342
  }
239
343
 
240
- /** Full launch context shown before Studio asks `astrale view` to open locally. */
344
+ /** Full launch context shown before Studio asks `astrale view` to resolve and open the View. */
241
345
  export interface ViewRuntime {
242
346
  slug: string
243
347
  instance: string | null
244
348
  targetRequired: boolean
245
- server: ViewDevServerStatus
246
349
  targets: ViewTargetResult
247
350
  }
248
351
 
@@ -349,7 +452,7 @@ export interface InstanceStatus {
349
452
  deployTarget: string | null
350
453
  /** has a `prod` script → deployable via `pnpm prod` */
351
454
  deployable: boolean
352
- /** GROUND TRUTH — queried from the target instance (`astrale get /<origin>`), not local state.
455
+ /** GROUND TRUTH — queried from `astrale introspect <origin> --bundle`, not local state.
353
456
  * 'unknown' = the instance couldn't be reached/queried (no target, not authed, offline). */
354
457
  install: 'installed' | 'not-installed' | 'unknown'
355
458
  /** local schema vs the schema actually INSTALLED on the instance (ground truth) */
@@ -427,19 +530,47 @@ export interface MergeResult {
427
530
  // ─────────────────────────── Change tracking ───────────────────────────
428
531
 
429
532
  export type SchemaChangeKind =
533
+ | 'schema-metadata-changed'
534
+ | 'type-added'
535
+ | 'type-removed'
536
+ | 'type-changed'
537
+ | 'import-added'
538
+ | 'import-removed'
539
+ | 'import-changed'
430
540
  | 'class-added'
431
541
  | 'class-removed'
542
+ | 'class-contract-changed'
432
543
  | 'interface-added'
433
544
  | 'interface-removed'
545
+ | 'interface-contract-changed'
434
546
  | 'edge-added'
435
547
  | 'edge-removed'
548
+ | 'edge-contract-changed'
549
+ | 'definition-metadata-changed'
436
550
  | 'prop-added'
437
551
  | 'prop-removed'
438
552
  | 'prop-type-changed'
553
+ | 'prop-schema-changed'
439
554
  | 'prop-required-changed'
440
555
  | 'method-added'
441
556
  | 'method-removed'
442
557
  | 'method-signature-changed'
558
+ | 'method-metadata-changed'
559
+ | 'function-added'
560
+ | 'function-removed'
561
+ | 'function-signature-changed'
562
+ | 'function-metadata-changed'
563
+ | 'view-added'
564
+ | 'view-removed'
565
+ | 'view-changed'
566
+ | 'view-metadata-changed'
567
+ | 'policy-added'
568
+ | 'policy-removed'
569
+ | 'policy-changed'
570
+ | 'dependency-added'
571
+ | 'dependency-removed'
572
+ | 'dependency-changed'
573
+ | 'core-changed'
443
574
 
444
575
  export interface SchemaChange {
445
576
  kind: SchemaChangeKind
@@ -465,13 +596,13 @@ export interface ChangeSet {
465
596
  }
466
597
 
467
598
  // ─────────────────────────── Core (genesis) data ───────────────────────────
468
- // A domain's `core` is its baked-in genesis graph: the concrete node/edge
469
- // instances `defineCore(schema, { nodes, edges })` ships in the install bundle.
599
+ // A domain's `core` is its baked-in genesis graph. Canonical V1 stores it in the
600
+ // DomainSchema; legacy projects may still expose `defineCore(...)` separately.
470
601
  // Read-only here — the studio renders it and lets you comment to request changes.
471
602
 
472
603
  /** One materialized node instance in a domain's core graph. */
473
604
  export interface StudioCoreNode {
474
- /** stable slash-path identity, e.g. `/big-shop.example.dev/core/brands/acme` (also the comment anchor key) */
605
+ /** canonical CoreRef identity, e.g. `/:big-shop.example.dev:core.acme` */
475
606
  path: string
476
607
  /** the IR class this node instantiates (keys into StudioSchemaBundle.ir.classes) */
477
608
  className: string
@@ -483,9 +614,9 @@ export interface StudioCoreNode {
483
614
 
484
615
  /** One materialized edge instance wiring two core nodes. */
485
616
  export interface StudioCoreEdge {
486
- /** source node `path` (or `self(ClassName)` for a meta-node endpoint) */
617
+ /** source Core path, owning Domain path, or a legacy meta-node endpoint */
487
618
  from: string
488
- /** target node `path` (or `self(ClassName)`) */
619
+ /** target Core path, owning Domain path, or a legacy meta-node endpoint */
489
620
  to: string
490
621
  /** the IR edge class name (keys into StudioSchemaBundle.ir.classes, type:'edge') */
491
622
  edgeName: string