dreamteamer 0.18.0 → 0.19.1
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.
- package/collections/collections.collection.yaml +19 -4
- package/collections/modules.collection.yaml +30 -5
- package/package.json +1 -1
- package/skills/using-dreamteamer/SKILL.md +34 -4
- package/skills/using-dreamteamer/references/before-you-build.md +2 -2
- package/skills/using-dreamteamer/references/collections.md +29 -9
- package/skills/using-dreamteamer/references/data-modeling.md +24 -12
- package/skills/using-dreamteamer/references/getting-started.md +6 -5
- package/skills/using-dreamteamer/references/ui-views.md +2 -2
- package/src/cli.js +119 -63
- package/src/collections-cli.js +525 -49
- package/src/compile.js +168 -23
- package/src/harnesses.js +7 -1
- package/src/init.js +12 -1
- package/src/runtime.js +7 -1
- package/src/schema-ops.js +1583 -86
- package/src/server.js +87 -15
- package/src/store.js +19 -4
|
@@ -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
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
137
|
+
⚠ COMPAT, ONE RELEASE ONLY — superseded 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,
|
|
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
|
-
|
|
40
|
+
description:
|
|
41
41
|
type: string
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
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.
|
|
3
|
+
"version": "0.19.1",
|
|
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>",
|
|
@@ -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,
|
|
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
|
-
-
|
|
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
|
|
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
|
|
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
|
-
`
|
|
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,
|
|
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
|
|
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
|
|
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 "
|
|
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
|
-
- **`
|
|
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
|
|
132
|
+
| declare in the OWNING MODULE's `package.json` | create it | lands in | referenced as |
|
|
133
133
|
|---|---|---|---|
|
|
134
|
-
| `"namespaces": ["health"]` | `dt
|
|
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
|
-
- **
|
|
143
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
226
|
-
- **
|
|
227
|
-
|
|
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
|
|
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
|
|
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**:
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
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
|
|
64
|
-
itself).
|
|
65
|
-
extraction is a decision for the
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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:
|