dreamteamer 0.17.0 → 0.19.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.
@@ -115,14 +115,29 @@ schema:
115
115
  opened on its own. It is stated here as DATA precisely so the record layer never has to
116
116
  learn what a module is; a bare string list rather than `x-reference: collections`, because
117
117
  the whole point is that the target is absent.
118
+ module:
119
+ type: string
120
+ description: >-
121
+ The module that OWNS this concept, as its bare id — DERIVED by compile from the base source,
122
+ and the one field a `dt set` may write: `dt set collections/<c> module=<m>` MOVES the
123
+ descriptor into that module. An overlay adds fields to somebody else's collection and does
124
+ not take it over, so the owner is the source declaring no `extends`. This is the workspace's
125
+ real partition, and what the nav groups by.
126
+ overlays:
127
+ type: array
128
+ items: { type: string }
129
+ description: >-
130
+ DERIVED by compile, never authored — the modules contributing an `extends:` overlay to this
131
+ collection, by id. ABSENT when there are none: an empty list is a statement nobody made.
132
+ `dt get collections/<c> --module <m>` prints one contribution alone.
118
133
  owner:
119
134
  type: string
120
135
  x-reference: modules
121
136
  description: >-
122
- The module that OWNS this concept DERIVED by compile from the base source, never authored.
123
- An overlay adds fields to somebody else's collection and does not take it over, so `meetings`
124
- stays owned by crm even though the workspace module overlays it. This is the workspace's real partition, and
125
- what the nav groups by.
137
+ COMPAT, ONE RELEASE ONLYsuperseded by `module`, which carries the same fact as the bare
138
+ id the operator actually types. Kept because a surface groups its nav by this key and reads
139
+ it as a reference; both are written by compile until that surface has moved. Removed in the
140
+ release after 0.19.0.
126
141
  group:
127
142
  type: string
128
143
  description: >-
@@ -26,7 +26,7 @@ id:
26
26
  title_template: "{{ name }}"
27
27
  schema:
28
28
  type: object
29
- required: [name, channel]
29
+ required: [name, location]
30
30
  properties:
31
31
  name:
32
32
  type: string
@@ -37,10 +37,32 @@ schema:
37
37
  What to CALL this module — authored as `dreamteamer.title` in its package.json, else derived
38
38
  from the id. Authored because deriving cannot know an acronym: titleCase("crm") is "Crm".
39
39
  A module names itself, which is what replaces a display-name map maintained in a surface.
40
- channel:
40
+ description:
41
41
  type: string
42
- enum: [path, git, npm, inline]
43
- description: How this module reached the workspace. `inline` is the workspace's own sources.
42
+ description: >-
43
+ What this module is FOR, in one line authored as `dreamteamer.description` in its
44
+ package.json, never derived. Written by `dt add modules --description` and
45
+ `dt set modules/<id> description=…`.
46
+ namespaces:
47
+ type: array
48
+ items: { type: string }
49
+ description: >-
50
+ The namespaces this module DECLARES and owns — authored as `dreamteamer.namespaces` in its
51
+ package.json (§8). The workspace's effective set is the union of every module's declarations
52
+ plus its own; two modules declaring one namespace is a compile error, and USING another
53
+ module's namespace requires that module in `dependencies`. ABSENT means this module ships
54
+ into the default namespace — the empty prefix, which is the commons.
55
+ location:
56
+ type: string
57
+ enum: [modules, git_modules, node_modules, root]
58
+ description: >-
59
+ WHERE this module's sources sit — the folder name the operator already knows, so `dt status`
60
+ needs no legend. `root` is the classic no-workspace-module layout, where the workspace's own
61
+ sources live at its root rather than under `modules/<id>/`.
62
+ ⚠ Renamed from `channel` in 0.19.0, and the enum's `path` value was DELETED rather than
63
+ renamed: discovery never emitted it, so it was an enum advertising work nobody had done.
64
+ `origin` was rejected (one token from `origin/main`, which `update` literally pulls) and
65
+ `shape` was rejected (`storage.shape` owns that word).
44
66
  path:
45
67
  type: string
46
68
  description: Workspace-relative root of the module's sources.
@@ -84,6 +106,9 @@ schema:
84
106
  type: string
85
107
  x-reference: collections
86
108
  order: 140
87
- list_fields: [title, name, channel, collections]
109
+ # ALL THREE IDENTITY SPELLINGS. A module is one string after `add modules` (folder = package name
110
+ # = id), and three strings for anything that predates it — so the listing shows the id (always
111
+ # printed first), the package `name` and the `path`, which is how an operator sees the fork at all.
112
+ list_fields: [location, path, namespaces, name, collections]
88
113
  icon: deployed_code
89
114
  group: system
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dreamteamer",
3
- "version": "0.17.0",
3
+ "version": "0.19.0",
4
4
  "description": "A workspace compiler for coding agents — schema-validated records as plain files over git, compiled into every harness",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Gilad Khen <giladkhen@gmail.com>",
@@ -48,7 +48,8 @@
48
48
  "ajv-formats": "^3.0.1",
49
49
  "express": "^5.2.1",
50
50
  "fractional-indexing": "^4.0.0",
51
- "js-yaml": "^4.1.0"
51
+ "js-yaml": "^4.1.0",
52
+ "yaml": "2.8.1"
52
53
  },
53
54
  "dreamteamer": {
54
55
  "title": "System"
@@ -53,7 +53,7 @@ id, materializes defaults, and its writes are pathspec-scoped; touch a record fi
53
53
  when the CLI cannot express the change (a long body, a nested map) — and then you owe `dt check`
54
54
  (`references/records.md`).
55
55
 
56
- **`dt help` is the complete command surface** — record verbs, schema verbs, workspace verbs, and
56
+ **`dt help` is the complete command surface** — record verbs, system verbs, field verbs, workspace verbs, and
57
57
  their flags, on one page (there is no per-verb `--help`).
58
58
 
59
59
  the verb names, as a map (semantics and flags live in `help`; a test holds this list to the
@@ -61,7 +61,7 @@ dispatch, so it cannot drift):
61
61
 
62
62
  - read & measure — `list` `get` `values` `history` `diff` `commands` `relations` `resolve`
63
63
  - write & publish — `add` `set` `rm` `rename` `move` `revert` `commit` `ensure`
64
- - schema (sources, through the compile gate) — `schema` `add-collection` `rm-collection` `rename-collection` `add-field` `update-field` `remove-field` `add-view` `set-view` `rm-view`
64
+ - fields (sources, through the compile gate) — `add-field` `update-field` `remove-field` `rename-field` (system entities — modules, collections, skills, ui-views… — take the RECORD verbs above)
65
65
  - workspace — `init` `install` `update` `compile` `check` `status` `start` `changes` `help` don't learn syntax from prose, this skill included: prose drifts, and `help` ships in
66
66
  the same file as the dispatch it documents. run it once before your first write of a session.
67
67
  what prose adds is judgment — *when* a verb is the right move, and the guarantees you can lean
@@ -81,7 +81,7 @@ Load by the map; nothing here is loaded "just in case".
81
81
  | read, create, update, rename, delete, commit — or UNDO — a record | `references/records.md` |
82
82
  | "what changed while I was away" | `references/changes.md` |
83
83
  | the workspace seems unable to do something — a new kind of thing, a missing capability, "don't we already have this?" | `references/before-you-build.md` (look first); a new model then continues `references/data-modeling.md` (decide) → `references/collections.md` (write it) |
84
- | a collection or field, mechanically — the descriptor, the `schema` verbs, `templates:`/`extends:`, a compile or check message | `references/collections.md` |
84
+ | a collection or field, mechanically — the descriptor, the system and field verbs, `templates:`/`extends:`, a compile or check message | `references/collections.md` |
85
85
  | knowledge a session should find on its own | `references/skills.md` |
86
86
  | "let me type one word and have this done" | `references/commands.md` |
87
87
  | "which command applies to this record?" — a binding, a gate | `references/commands.md` |
@@ -105,6 +105,36 @@ domain work — meetings, patients, invoices, whatever this workspace is about
105
105
  and `repos`, and deliberately nothing else. workspace-level rules live in `CLAUDE.md`, and a
106
106
  workspace's decision log (where one exists) wins over older documents.
107
107
 
108
+ ## system entities take the RECORD verbs
109
+
110
+ Modules, collections, skills, agents, commands, command-bindings, ui-views and collection-templates
111
+ are collections in the runtime, and since 0.19.0 the ordinary verbs write them:
112
+
113
+ ```
114
+ dt add modules --name core --description "The shared nouns."
115
+ dt add collections --name people --module core --description "A person."
116
+ dt add-field people --name email --type string --description "Where to write to them."
117
+ dt rename-field people --name email --to work_email
118
+ dt set collections/people module=hr # MOVES it to another module
119
+ dt set modules/hr namespaces=hr dependencies=modules/core
120
+ dt rm modules/hr --force # --dry-run first; it prints its plan
121
+ ```
122
+
123
+ `dt schema <op>` is **gone** since 0.19.0 and fails with the translation printed. `UPDATING.md` has
124
+ the complete mapping table.
125
+
126
+ ⚠ **ONE difference, and it is POLICY rather than spelling: a SYSTEM write commits itself; a RECORD
127
+ write does not.** An uncompilable or unpublished schema is not a state a workspace should sit in, so
128
+ every system verb writes its source, proves it with a real compile, and commits — **in the repo that
129
+ holds the source**, so a write into a `git_modules/` module commits there and says
130
+ `ahead 1 — push when ready`. A record write lands on disk and `dt commit` publishes it.
131
+
132
+ ⚠ **Every verb that moves records or clears values takes `--dry-run` and prints its plan first:**
133
+ `rename collections/…`, `rename-field`, `remove-field`, `set collections/… module=`,
134
+ `rm modules/… --force`. The plan line is one shape — `records N · refs M · descriptors K · values
135
+ cleared V` — so two dry runs are comparable, and a term that reads 0 means zero rather than
136
+ unmeasured (where a number genuinely cannot be known before the run, the plan says so in words).
137
+
108
138
  ## the rules that hold in both acts
109
139
 
110
140
  1. **sources live in a module** — `modules/<module>/<kind>/`; the workspace's own go in its
@@ -124,7 +154,7 @@ workspace's decision log (where one exists) wins over older documents.
124
154
  overwritten and pruned on the next compile — if you found the thing to change there, you are
125
155
  in the wrong file.
126
156
  7. **the CLI refuses system-stored records on purpose** (`dt set skills/<id>` — no): edit the
127
- module source and compile. the `schema` verbs are the sanctioned exception — they write
157
+ module source and compile. the SYSTEM verbs are the sanctioned exception — they write
128
158
  sources *through* a compile gate, so an uncompilable source can never land.
129
159
  8. **never duplicate a procedure across records.** a command body restating a skill, an agent
130
160
  inlining its skill's steps — two copies, and one drifts. reference the owner.
@@ -1,7 +1,7 @@
1
1
  # before you build — look for it first
2
2
 
3
3
  The situation: the operator asked for something the workspace does not seem to do, and you are one
4
- `schema add-collection` or one new skill away from making it exist. This reference is the pause
4
+ `dt add collections` or one new skill away from making it exist. This reference is the pause
5
5
  before that. **When the workspace can't do something, look before you build — and when you do find
6
6
  something, propose concretely, never install or copy silently.** The operator decides what enters
7
7
  their workspace.
@@ -43,7 +43,7 @@ install. The looking still matters; the taking changed shape.
43
43
  | 1 | **this workspace's own modules** | the orientation block's COLLECTIONS list is already in your context — reread it with the concept's *synonyms* in mind; `.dreamteamer/manifest.yaml` names every module and entry; `dt help` shows the verbs and `dt commands <collection>` the bound ones; the skills index shows the techniques | the thing may already exist under a name you didn't guess. This is where misses actually happen, because it is the place you assume you already know |
44
44
  | 2 | **a recipes repo — where this workspace's own CLAUDE.md names one** (reference modules maintained to be **copied and adapted**) | read that repo's own instructions first; they ARE the adoption procedure. no recipes repo declared → skip this row | a working module with its reasoning attached — descriptors, skills, and the trap notes that each cost someone a day |
45
45
  | 3 | **a sibling workspace — where the operator has named one** | read-only; grep its `modules/` for the concept. none named → skip | another vault may have solved it concretely. That is a *reference*, not a source — it holds real personal data, so read the shape, never lift the content |
46
- | 4 | **the engine's own surface** | `dt help` — the complete verb surface, schema verbs included; read it rather than recalling it | the capability may already be a verb (`relations rebuild`, `resolve`, `ensure`) rather than a missing module |
46
+ | 4 | **the engine's own surface** | `dt help` — the complete verb surface, system and field verbs included; read it rather than recalling it | the capability may already be a verb (`relations rebuild`, `resolve`, `ensure`) rather than a missing module |
47
47
 
48
48
  Only after all four: build it, in the module that owns the concept.
49
49
 
@@ -11,7 +11,7 @@ reference is organized for both:
11
11
  | the question | read |
12
12
  |---|---|
13
13
  | what compile actually does to my source | the pipeline |
14
- | create or change shape with the CLI | the schema verbs |
14
+ | create or change shape with the CLI | the system and field verbs |
15
15
  | a brand-new module for a domain | declaring a module |
16
16
  | a prefix / a folder per domain | namespaces |
17
17
  | the same field set on several collections | `templates:` |
@@ -54,13 +54,13 @@ order explains most "why does the compiled file say that" questions:
54
54
  Consequence: **read the compiled file to know what IS; edit the source to change it.** They
55
55
  differ by design, and diffing them is often the fastest way to see what compile decided for you.
56
56
 
57
- ## the schema verbs — writes through a compile gate
57
+ ## the system and field verbs — writes through a compile gate
58
58
 
59
59
  The one sanctioned way to write schema without hand-editing. Every verb round-trips through a
60
60
  **compile gate**, so a change that would not compile is rejected before it lands — and unlike a
61
61
  record write, a schema verb **commits its source write itself**, because an uncompilable or
62
62
  unpublished schema is not a state the workspace should sit in. The verbs and every flag live in
63
- `dt help` under "schema verbs" — read that, not prose. What help cannot tell you:
63
+ `dt help` under "system verbs" and "field verbs" — read that, not prose. What help cannot tell you:
64
64
 
65
65
  - **The field verbs write the WORKSPACE module.** On a collection another module owns, `add-field`
66
66
  and `update-field` author an `extends:` overlay in the workspace module — which compiles only
@@ -84,7 +84,7 @@ unpublished schema is not a state the workspace should sit in. The verbs and eve
84
84
  - **`add-field` inserts before the `x-body` field**, on the same rule as a `templates:` merge
85
85
  below: property order is form order, and a record's body belongs last. `update-field` never
86
86
  reorders — an existing field keeps the place its author gave it.
87
- - **`schema rename-collection <old> <new>`** moves the descriptor **in the module that ships it**
87
+ - **`dt rename collections/<old> <new>`** moves the descriptor **in the module that ships it**
88
88
  (its guard is against writes an `npm install` would erase, not against modules), plus the
89
89
  records, the filenames and every inbound reference — `x-reference` targets in other descriptors
90
90
  and ui-views included — in ONE commit. It refuses: a runtime source, an **overlaid** collection
@@ -129,9 +129,15 @@ module graph (the reference contract, below).
129
129
 
130
130
  A collection name may carry a slash-delimited namespace, and it becomes real directory nesting:
131
131
 
132
- | declare in the workspace `package.json` | create it | lands in | referenced as |
132
+ | declare in the OWNING MODULE's `package.json` | create it | lands in | referenced as |
133
133
  |---|---|---|---|
134
- | `"namespaces": ["health"]` | `dt schema add-collection --namespace health --name doctors` | `data/health/doctors/` | `health/doctors/dana-levi` |
134
+ | `"dreamteamer": {"namespaces": ["health"]}` | `dt add collections --name doctors --module clinic` | `data/health/doctors/` | `health/doctors/dana-levi` |
135
+
136
+ A module declaring exactly ONE namespace **infers** it, and the resolved name is always echoed
137
+ (`✔ health/doctors (namespace inferred from module clinic)`). Two or more declared and it refuses
138
+ to guess: `--namespace health`. `--namespace ''` means no namespace. `--namespace x` where nobody
139
+ declares `x` writes the declaration into the target module — which is what travels when the module
140
+ is copied.
135
141
 
136
142
  - **The default namespace is the empty prefix.** `tasks` stays `data/tasks/` and `tasks/kickoff`,
137
143
  so common entities need no prefix and adopting namespaces migrates nothing. `default` is
@@ -139,8 +145,22 @@ A collection name may carry a slash-delimited namespace, and it becomes real dir
139
145
  - ⚠ **The namespace MUST be declared before the collection compiles.** An id is also a slash path
140
146
  (`meetings/2026/07/kickoff`), so `a/b/c` is ambiguous without the declared set; an undeclared
141
147
  prefix is a compile error rather than a reference that silently names a different collection.
142
- - **Namespaces are declared by the WORKSPACE only, never by a module** a module that could
143
- declare one could rename where another module's records live.
148
+ - **A MODULE declares the namespaces it owns** `"dreamteamer": { "namespaces": ["hr"] }` in its
149
+ own `package.json`, and the workspace's effective set is the **union** with its own
150
+ `dreamteamer.namespaces`. This reversed in 0.19.0. The old rule ("the workspace only, never a
151
+ module") had a real reason — a module that can declare a namespace can rename where another
152
+ module's records live — but it made decision 130's own acceptance test, *"a module compiles alone
153
+ in a bare workspace"*, unpassable for any namespaced module: the consuming workspace had to edit
154
+ its manifest first, which is exactly the coupling that rule forbids.
155
+ - **One owner per namespace.** Two modules declaring it is a compile error naming both.
156
+ - **Using another module's namespace requires the dependency** — shipping `hr/<c>` while only
157
+ `hr` declares `hr` means listing `hr` in your `dreamteamer.dependencies`. Without this rule the
158
+ union would let you squat in another module's namespace silently.
159
+ - **A workspace-level declaration a module also declares is a WARNING**, not an error, and
160
+ `dt set modules/<m> namespaces=<ns>` removes the redundant workspace entry in the same write.
161
+ - **The set is a function of the INSTALLED MODULE SET.** Removing or disabling a namespace-owning
162
+ module re-splits every reference into it; `check` reports the dangle, and the compile error says
163
+ the namespace was declared by a module you just removed. `default` stays reserved.
144
164
  - `--namespace health --name doctors` and `--name health/doctors` are the same thing. The
145
165
  descriptor lands at `collections/health/doctors.collection.yaml` — `collections/` is enumerated
146
166
  recursively, so the source tree mirrors the runtime — and the `suffix` comes off the bare name
@@ -203,7 +223,7 @@ Two gates around it:
203
223
  hardest dependency there is (the overlay does not compile at all without its base), so compile
204
224
  refuses the undeclared case. The workspace module gets **no exemption here** (unlike the
205
225
  mirror-stamp and wildcard gates, which do exempt it) — this is exactly the refusal you meet
206
- when a field verb targets a module-owned collection (the schema verbs, above).
226
+ when a field verb targets a module-owned collection (the field verbs, above).
207
227
  - ⚠ **An overlay can add fields but cannot remove an inherited one.** If the shape is wrong for
208
228
  the module rather than just for this workspace, fix the base.
209
229
 
@@ -4,7 +4,7 @@ The user states a requirement — "track the clinic's visits", "stop losing lab
4
4
  a data architect. This reference is what stands between that sentence and a model: it turns the
5
5
  requirement into collections, fields and relations that are searchable, filterable, legible in any
6
6
  surface, cheap to keep, and still right a year in. Method and judgment live here; mechanics (the
7
- meta verbs, namespaces, `templates:`, registering an existing folder) live in `collections.md`.
7
+ system and field verbs, namespaces, `templates:`, registering an existing folder) live in `collections.md`.
8
8
 
9
9
  It is long on purpose. It is the reference for the single highest-leverage act in a dreamteamer
10
10
  workspace — a model outlives every skill and command written against it — and the reader is usually
@@ -189,7 +189,7 @@ The interview's output is **not prose**. Show, before anything is written:
189
189
  verbatim. Seeding one real record before declaring the schema catches half the field mistakes —
190
190
  the missing unit, the enum value the domain actually spells differently, the id that comes out
191
191
  wrong.
192
- 3. The **`dt schema` commands** (or the hand-written descriptor when the collection is
192
+ 3. The **system verbs** (`dt add collections`, `dt add-field`, …) (or the hand-written descriptor when the collection is
193
193
  module-owned or carries comments worth keeping).
194
194
  4. The **"deliberately not modelled"** list, each with its one-line reason.
195
195
  5. For each relation: which side owns, whether an inverse is declared, and the answer to "which X
@@ -222,9 +222,17 @@ alone in a bare workspace.** Everything else follows from that.
222
222
  - **A cross-module relation is a declared dependency.** An inverse stamps a generated field onto
223
223
  another module's collection, so compile refuses it unless the declaring module lists the
224
224
  target's module in its dependencies — a module may not grow fields on a stranger silently. (The
225
- workspace module is exempt; it overlays everything by design.)
226
- - **Start in the workspace module; extract on the second consumer, not the first hunch.** The meta
227
- verbs write the workspace module, and that is the right first home for everything. A module is
225
+ workspace module's exemption is rule 6 ONLY see below.)
226
+ - **The workspace module's exemption is rule 6 ONLY, and rule 6 is `x-reference: '*'`.** It may
227
+ reference anything, including collections that do not exist yet that is what `tasks.item`
228
+ means, and anywhere else a wildcard draws a warning (an unverifiable cross-module surface). It is
229
+ **NOT** exempt from the `extends` dependency gate: an overlay in the workspace module on another
230
+ module's collection still requires that module in `dreamteamer.dependencies`, exactly as any
231
+ other overlay does. Measured 2026-09-01 — and the reason the two read as one exemption is that
232
+ they are both "the workspace module is special", which it is, in exactly one of the two places.
233
+ - **Start in the workspace module; extract on the second consumer, not the first hunch.** The
234
+ system verbs default to the workspace module (`--module <m>` names another), and that is the
235
+ right first home for everything. A module is
228
236
  worth extracting when its collections form a closed reference graph, when a second workspace
229
237
  wants it, or when its vocabulary has stabilised — not before. Premature extraction buys a
230
238
  boundary you will immediately need to breach.
@@ -251,7 +259,7 @@ sane:
251
259
  owned by a "meeting" namespace).
252
260
  - Declare the namespace before the first collection compiles — an id is also a slash path, so an
253
261
  undeclared prefix is ambiguous and compile refuses it rather than guessing.
254
- - Namespacing an existing collection later is `dt schema rename-collection <old> --namespace <ns>`
262
+ - Namespacing an existing collection later is `dt rename collections/<old> --namespace <ns>`
255
263
  — one commit, every inbound reference rewritten, safe at any point. Cheapest early, though: the
256
264
  rewrite is O(records × files), measured at ~3 minutes for a 2,291-record collection — tolerable
257
265
  for a one-time migration, not free. So do not agonise up front; just decide sooner rather than
@@ -807,15 +815,19 @@ useless until the flood is drained.
807
815
 
808
816
  ### 41. Renames
809
817
 
810
- - **Collections**: `dt schema rename-collection <old> <new>` — descriptor, records, filenames and
818
+ - **Collections**: `dt rename collections/<old> <new>` — descriptor, records, filenames and
811
819
  every inbound reference in one commit. Safe, and cheapest early — the rewrite is
812
820
  O(records × files), measured ~3 minutes at ~2,300 records — so do it the day the name is wrong,
813
821
  not the year after.
814
- - **Fields**: there is no rename verb, deliberately (a rename that rewrites every record is a
815
- migration, and pretending otherwise invites half-renames). The honest sequence: add the new
816
- field; a one-shot script moving the values (committed with the records it rewrote, the commit
817
- message being the ledger); `schema remove-field` the old one which clears any leftovers and
818
- reports the count.
822
+ - **Fields**: `dt rename-field <c> --name <f> --to <g>`, since 0.19.0 one commit, and it
823
+ rewrites far more than the records: `list_fields`, `sort_field`, `x-inverse`, `x-inverse-of`,
824
+ `title_template`, `id.generate`, a ui-view's `options.columns` and `filter`, and a
825
+ command-binding's `can-enter`/`can-exit`. A field is referenced BY NAME rather than as a
826
+ `<collection>/<id>` reference, so `store.rewriteRefs` can see none of those — which is exactly
827
+ why this used to be "no rename verb, deliberately", with the honest sequence being add-new,
828
+ script the values, `remove-field` the old. That sequence still works and is what you want when
829
+ the values themselves have to CHANGE shape; when only the name changes, the verb is one command
830
+ and takes `--dry-run`.
819
831
  - **Values** (an id, a reference target): `dt rename <collection>/<old> <new>` rewrites inbound
820
832
  references. Prose wikilinks are followed in both spellings — `[[collection/id]]` always, and a
821
833
  bare `[[id]]` when that basename names exactly ONE record in the workspace; when something else
@@ -60,9 +60,10 @@ real records. Not five collections, not a namespace plan, not a module layout.
60
60
  2. **Propose small, then stop.** The proposal contract (`data-modeling.md` §7): the descriptor
61
61
  YAML, one sample record as its `dt add` line, and what is deliberately NOT modelled. The
62
62
  operator says yes before anything lands.
63
- 3. **Create it in the workspace module** — `dt schema add-collection` (it compiles and publishes
64
- itself). The workspace module is the right first home for everything (`data-modeling.md` §8);
65
- extraction is a decision for the second consumer, months away.
63
+ 3. **Create it** — `dt add collections --name <c> [--module <m>]` (it compiles and publishes
64
+ itself). It lands in the module you NAME, defaulting to the workspace module which is the
65
+ right first home for everything (`data-modeling.md` §8); extraction is a decision for the
66
+ second consumer, months away.
66
67
  4. **Seed three to five REAL records immediately** with `dt add` — not test data. Seeding real
67
68
  records before declaring the model finished catches half the field mistakes: the missing unit,
68
69
  the enum the domain spells differently, the id that comes out wrong.
@@ -90,7 +91,7 @@ The pile is evidence; read it before modeling anything.
90
91
  folder), and a record points at each via a `${env:VAR}` template — the filing convention and
91
92
  the mechanics are in `records.md`.
92
93
  4. **Restructure later, with the tools that keep references true** — `dt rename`,
93
- `dt schema rename-collection` — not during the first pass. Model reality first; `check` will
94
+ `dt rename collections/<old> <new>` — not during the first pass. Model reality first; `check` will
94
95
  tell you what reality violates, and that list, not taste, drives the cleanup.
95
96
 
96
97
  ## path C — into a repo that already holds code
@@ -108,6 +109,6 @@ prefers. Nothing about the code moves; `check` and `compile` read only what desc
108
109
  | test data in the seed records | real records are what catch the model's mistakes |
109
110
  | skipping git as "too technical" | one local command, no account — and it is the history, the undo and the publish step |
110
111
  | inventing ids by hand | `id.generate` owns identity — pass `--id` only when the operator named one |
111
- | hand-writing the first descriptor | `dt schema add-collection` is compile-gated and publishes itself; hand-written sources owe `dt compile` |
112
+ | hand-writing the first descriptor | `dt add collections` is compile-gated and publishes itself; hand-written sources owe `dt compile` |
112
113
  | rewriting existing files to fit a guessed schema | describe reality, compile, `check` — then decide which violations are worth fixing in the data |
113
114
  | waiting for a UI before starting | the CLI and the records are the complete system; any surface renders them later, unchanged |
@@ -128,7 +128,7 @@ same record. A misspelled key is read by nobody, silently. The two edges that bi
128
128
  (`options.arrangement`) has only the JSON spelling.
129
129
  - ⚠ **`options.sort` must be written even when empty** (`sort: ''`), or "unsorted" cannot
130
130
  round-trip and silently reverts to a fallback ordering on the next load. The spelling is a
131
- QUOTED value — `dt schema set-view <id> 'options.sort=""'` — because a bare `options.sort=`
131
+ QUOTED value — `dt set ui-views/<id> 'options.sort=""'` — because a bare `options.sort=`
132
132
  removes the key, as an empty value does everywhere else. Quoting any value makes it a literal
133
133
  string (`options.sort='"-date"'` is the same as `options.sort=-date`).
134
134
 
@@ -152,7 +152,7 @@ One shape, one home, both agent-writable, both diffable in git.
152
152
 
153
153
  ## the CLI can write these
154
154
 
155
- `dt schema add-view | set-view | rm-view` — `add-view` derives the record id from `path` with the
155
+ `dt add ui-views` / `dt set ui-views/<id>` / `dt rm ui-views/<id>` — `add` derives the record id from `path` with the
156
156
  descriptor's own template, so a view saved from the CLI and one saved from the UI land on the
157
157
  **same record**; `set-view <id>` takes dotted keys (`options.sort=-date`, `nav.label=Recent`). This is the one system-stored
158
158
  kind with full CLI write support, because it goes through the same compile gate. Two edges: