dreamteamer 0.9.1 → 0.12.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.
- package/README.md +24 -0
- package/collections/collections.collection.yaml +18 -0
- package/collections/repos.collection.yaml +3 -0
- package/package.json +3 -2
- package/skills/building-dreamteamer/SKILL.md +6 -6
- package/skills/building-dreamteamer/references/collections.md +9 -9
- package/skills/building-dreamteamer/references/commands.md +2 -2
- package/skills/building-dreamteamer/references/ui-views.md +1 -1
- package/skills/using-dreamteamer/SKILL.md +30 -2
- package/skills/using-dreamteamer/references/records.md +7 -7
- package/src/cli.js +219 -55
- package/src/collections-cli.js +54 -16
- package/src/compile.js +44 -7
- package/src/env-vars.js +40 -0
- package/src/fractional-index.js +44 -0
- package/src/harnesses.js +167 -7
- package/src/presentation.js +5 -0
- package/src/ref.js +13 -0
- package/src/runtime.js +1 -1
- package/src/server.js +28 -0
package/README.md
CHANGED
|
@@ -63,6 +63,30 @@ The shape of a record is deliberately dull, because dull is what survives:
|
|
|
63
63
|
- a write lands on disk; `dreamteamer commit` publishes it, one commit per repo
|
|
64
64
|
- schemas are JSON Schema in a YAML file, one per collection
|
|
65
65
|
|
|
66
|
+
### Machine-specific references
|
|
67
|
+
|
|
68
|
+
Some things a record points at only exist on one machine — a synced Drive folder, an external disk,
|
|
69
|
+
a checkout somewhere else. Those are written as **templates**, never as absolute paths:
|
|
70
|
+
|
|
71
|
+
```yaml
|
|
72
|
+
source_file: ${env:FILES_FOLDER}/2026/q3.pdf
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Three variables, borrowing VS Code's grammar: `${env:NAME}` — declared in `dreamteamer.vars` in
|
|
76
|
+
`package.json`, valued in the gitignored `.env` — plus `${workspaceFolder}` and `${userHome}`.
|
|
77
|
+
One verb renders them:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
npx dreamteamer resolve '${env:FILES_FOLDER}/x' # → /Volumes/annex/x
|
|
81
|
+
npx dreamteamer resolve <collection>/<id> <field> # render what a record already holds
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Templates are ordinary data — write them literally; nothing substitutes until `resolve` is
|
|
85
|
+
called.** `get`, `list`, `check` and every harness see the template verbatim, which is exactly what
|
|
86
|
+
makes the record mean the same thing on every machine instead of quietly meaning two things. An
|
|
87
|
+
undeclared key and a declared-but-absent one are different errors, and `compile` warns — by name,
|
|
88
|
+
never by value — when a declared var has nothing behind it here.
|
|
89
|
+
|
|
66
90
|
## Modular
|
|
67
91
|
|
|
68
92
|
**Data and skills are the new app structure.** A coding agent with the right skills over the right
|
|
@@ -11,6 +11,17 @@ schema:
|
|
|
11
11
|
description:
|
|
12
12
|
type: string
|
|
13
13
|
description: What kind of thing this collection holds, in one line.
|
|
14
|
+
use_when:
|
|
15
|
+
type: string
|
|
16
|
+
description: >-
|
|
17
|
+
WHEN to reach for this collection, in one clause — rendered into the orientation block every
|
|
18
|
+
agent session loads. OPTIONAL and usually absent: for most collections the trigger IS the
|
|
19
|
+
description (`contacts` = a person; you use it when you have a person), and a restatement
|
|
20
|
+
there costs every session tokens while diluting the few that carry real information. The
|
|
21
|
+
test: author this only when an agent that FULLY UNDERSTANDS the description would still not
|
|
22
|
+
know to reach for the collection. It spans both acts — read ("you are about to diagnose a
|
|
23
|
+
defect — search here first") and write ("a day needs planning"). NOT a place for procedure:
|
|
24
|
+
a `how` belongs in the module's skill, this field holds a `when`.
|
|
14
25
|
title:
|
|
15
26
|
type: string
|
|
16
27
|
description: What to call this collection in the nav and page headers. DERIVED from `name` by title-casing when absent — author it only when that is wrong (`ui-views` → `UI Views`).
|
|
@@ -66,6 +77,13 @@ schema:
|
|
|
66
77
|
type: array
|
|
67
78
|
items: { type: string }
|
|
68
79
|
description: The columns a list view shows by default.
|
|
80
|
+
sort_field:
|
|
81
|
+
type: string
|
|
82
|
+
description: >-
|
|
83
|
+
Which field carries MANUAL order — the one a drag writes. The field must be declared by this
|
|
84
|
+
collection's own schema, and holds a fractional index (`dt <collection> move`), never an
|
|
85
|
+
integer: renumbering is a multi-file commit against git. A surface offers dragging only while
|
|
86
|
+
it is sorted by this field, because a handle that reorders nothing is a lie.
|
|
69
87
|
icon:
|
|
70
88
|
type: string
|
|
71
89
|
description: material-symbols-outlined icon name, drawn in the nav and page header. The VS Code tree maps it to the nearest codicon — an unmapped name falls back to a generic cylinder, so pick one that is already mapped or add the row.
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
name: repos
|
|
2
|
+
description: >-
|
|
3
|
+
A git repository this workspace knows about — where it lives and how a working tree is
|
|
4
|
+
materialized on demand.
|
|
2
5
|
# An external git repo attached to this workspace. Owns CLONE LIFECYCLE ONLY — a repo record
|
|
3
6
|
# never contributes schema, skills or UI (that is what a module is, declared in package.json
|
|
4
7
|
# `dreamteamer.git-modules`, because modules must be restorable BEFORE compile can run).
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dreamteamer",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "A workspace compiler for coding agents
|
|
3
|
+
"version": "0.12.0",
|
|
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>",
|
|
7
7
|
"homepage": "https://github.com/dreamteamer/dreamteamer#readme",
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
"ajv": "^8.17.1",
|
|
48
48
|
"ajv-formats": "^3.0.1",
|
|
49
49
|
"express": "^5.2.1",
|
|
50
|
+
"fractional-indexing": "^4.0.0",
|
|
50
51
|
"js-yaml": "^4.1.0"
|
|
51
52
|
},
|
|
52
53
|
"dreamteamer": {
|
|
@@ -37,7 +37,7 @@ Three tie-breakers worth internalising, because they are the ones that go wrong:
|
|
|
37
37
|
- **a multi-step process is a CHAIN OF COMMANDS, not an entity.** There is no workflow kind: a
|
|
38
38
|
`workflows` collection with run records, triggers and an executor existed until 2026-07-31 and was
|
|
39
39
|
removed after three days of measurement showed the work being done by a command chain instead. Write
|
|
40
|
-
one command per step, bind each to its collection so `dt commands
|
|
40
|
+
one command per step, bind each to its collection so `dt commands <ref>` shows what applies, and
|
|
41
41
|
a command whose body invokes the others in order if the sequence needs a name. The record's own state
|
|
42
42
|
is the progress marker — which is what made the run records redundant.
|
|
43
43
|
|
|
@@ -54,7 +54,7 @@ These were duplicated across seven skills; they are true for all of them.
|
|
|
54
54
|
makes the id lie.
|
|
55
55
|
3. **The meta-descriptor IS the spec.** Every kind is itself a collection:
|
|
56
56
|
`.dreamteamer/collections/<kind>.collection.yaml` lists every key it may carry with its
|
|
57
|
-
allowed values. Read that, plus a real one (`dt
|
|
57
|
+
allowed values. Read that, plus a real one (`dt get <kind>/<id>`), instead of learning the shape
|
|
58
58
|
from prose. Prose drifts; the descriptor cannot.
|
|
59
59
|
4. **`npm run compile`, then `npm run check`.** Compile materializes the runtime and the harness
|
|
60
60
|
adapters; check validates refs and shapes and never modifies files. Neither is optional.
|
|
@@ -66,10 +66,10 @@ These were duplicated across seven skills; they are true for all of them.
|
|
|
66
66
|
7. **Never edit generated output.** `.dreamteamer/`, `.claude/`, `.agents/`, `.cursor/` are all
|
|
67
67
|
overwritten and pruned on the next compile. If you found the thing you want to change in one of
|
|
68
68
|
those, you are in the wrong file.
|
|
69
|
-
8. **The CLI refuses system-stored records on purpose.** `dt skills
|
|
69
|
+
8. **The CLI refuses system-stored records on purpose.** `dt set skills/<id> …` will not work; edit the
|
|
70
70
|
module source and compile. The exceptions are the meta verbs that write sources *through* a
|
|
71
|
-
compile gate — `
|
|
72
|
-
an uncompilable source can never land in history.
|
|
71
|
+
compile gate — `schema add-collection`, `schema add-field <collection>`, `schema add-view|set-view` —
|
|
72
|
+
which exist so an uncompilable source can never land in history.
|
|
73
73
|
9. **Never duplicate a procedure across records.** A command body that restates a skill, an agent
|
|
74
74
|
body that inlines its skill's steps, a command that re-types another command's prompt — each is two
|
|
75
75
|
copies that drift. Reference the one that owns it.
|
|
@@ -99,7 +99,7 @@ a collection about people, meetings, tasks, products, content — belongs in a m
|
|
|
99
99
|
version of it belongs in the `recipes` repo rather than here.
|
|
100
100
|
|
|
101
101
|
**The test is: does the ENGINE read it?** Core's collections are the entity kinds the compiler itself
|
|
102
|
-
materializes, plus `repos` (because `
|
|
102
|
+
materializes, plus `repos` (because `ensure` clones them). Everything else has been ejected on
|
|
103
103
|
exactly that test — `teams` (nothing resolved a
|
|
104
104
|
team), `mounts` (a one-implementation adapter enum over an `.env` key), `module-registries` (zero
|
|
105
105
|
readers), `workflows`/`workflow-runs`/`workflow-triggers`/`cursors` and `migrations`/`migration-runs`
|
|
@@ -7,12 +7,12 @@ One descriptor file: `modules/<module>/collections/<name>.collection.yaml`. The
|
|
|
7
7
|
|
|
8
8
|
| goal | how |
|
|
9
9
|
|---|---|
|
|
10
|
-
| new collection from a template | `dt
|
|
11
|
-
| move one into a namespace | `dt
|
|
12
|
-
| templateless | `dt
|
|
13
|
-
| add a field | `dt
|
|
14
|
-
| change / drop a field | `dt
|
|
15
|
-
| delete a collection | `dt
|
|
10
|
+
| new collection from a template | `dt schema add-collection --name research-docs --template docs` |
|
|
11
|
+
| move one into a namespace | `dt schema rename-collection doctors health/doctors` (or `doctors --namespace health`) |
|
|
12
|
+
| templateless | `dt schema add-collection --name <n>` — emits a minimal compilable schema |
|
|
13
|
+
| add a field | `dt schema add-field <collection> --name urgent --type boolean --default-value false` |
|
|
14
|
+
| change / drop a field | `dt schema update-field <collection> …` · `schema remove-field <collection> --name <f>` |
|
|
15
|
+
| delete a collection | `dt schema rm-collection <name>` |
|
|
16
16
|
| what templates exist | `.dreamteamer/collection-templates/` |
|
|
17
17
|
|
|
18
18
|
`--type` is sugar over JSON Schema: `string`/`text`, `markdown`, `boolean`, `number`, `integer`,
|
|
@@ -21,7 +21,7 @@ or a bare collection name for a reference into it. `--required true` widens `req
|
|
|
21
21
|
|
|
22
22
|
⚠ **The meta verbs write the WORKSPACE module only.** To change a field on a collection another
|
|
23
23
|
module owns, either edit that module's descriptor by hand or add an `extends:` overlay.
|
|
24
|
-
**`dt
|
|
24
|
+
**`dt schema rename-collection <old> <new>`** moves the descriptor, the records, the record filenames and
|
|
25
25
|
every inbound reference in ONE commit — including `x-reference` targets in other descriptors and any
|
|
26
26
|
ui-view pointing at it. `<old> --namespace <ns>` is sugar for moving it into a namespace under the same
|
|
27
27
|
bare name. It refuses a compiled source, a module-owned collection, a taken name, and an undeclared
|
|
@@ -35,7 +35,7 @@ A collection name may carry a slash-delimited namespace, and it becomes real dir
|
|
|
35
35
|
|
|
36
36
|
| declare in the workspace `package.json` | create it | lands in | referenced as |
|
|
37
37
|
|---|---|---|---|
|
|
38
|
-
| `"namespaces": ["health"]` | `dt
|
|
38
|
+
| `"namespaces": ["health"]` | `dt schema add-collection --namespace health --name doctors` | `data/health/doctors/` | `health/doctors/dana-levi` |
|
|
39
39
|
|
|
40
40
|
- **The default namespace is the empty prefix.** `tasks` stays `data/tasks/` and `tasks/kickoff`, so
|
|
41
41
|
common entities need no prefix and adopting namespaces migrates nothing. `default` is RESERVED —
|
|
@@ -93,7 +93,7 @@ templates: [collection-templates/provenance] # merged at compile, every time
|
|
|
93
93
|
reference already inherits its TARGET collection's `title_template`; author it there instead, once,
|
|
94
94
|
rather than on every field pointing at it.
|
|
95
95
|
- **Do not enum a field after the fact.** Enumerating a vocabulary the records already violate makes
|
|
96
|
-
`check` fail on every pre-existing value. `dt <collection>
|
|
96
|
+
`check` fail on every pre-existing value. `dt values <collection> <field>` derives the real
|
|
97
97
|
vocabulary from the data — a filter dropdown gets it for free without locking the set.
|
|
98
98
|
- **`icon` / `group`** are the studio nav's material-symbol icon and folder; ungrouped collections
|
|
99
99
|
list at the top. `list_fields` is the SEED a module ships, not a competing source of truth — a
|
|
@@ -13,7 +13,7 @@ description: triage every open task assigned to me, one at a time
|
|
|
13
13
|
argument-hint: "[assignee]"
|
|
14
14
|
---
|
|
15
15
|
load this workspace's tasks skill. list my open tasks
|
|
16
|
-
(`npm run --silent dt -- tasks
|
|
16
|
+
(`npm run --silent dt -- list tasks --status todo`), then walk them one at a
|
|
17
17
|
time: restate it, ask me to keep / reassign / drop, apply the decision with `tasks set`.
|
|
18
18
|
done when the list is empty or I say stop.
|
|
19
19
|
```
|
|
@@ -55,7 +55,7 @@ description: audio present, no transcript yet
|
|
|
55
55
|
- **Pick the signal carefully.** "Is it transcribed?" is `transcription._nempty` (the provenance
|
|
56
56
|
object), NOT `transcript._nempty` — a body can be filled by hand with no provenance, which is
|
|
57
57
|
exactly the case worth flagging as not-yet-done.
|
|
58
|
-
- Read the queue with `dt commands
|
|
58
|
+
- Read the queue with `dt commands <collection>[/<id>] [--ids a,b] [--json]`.
|
|
59
59
|
|
|
60
60
|
## common mistakes
|
|
61
61
|
|
|
@@ -46,7 +46,7 @@ and silently reverts to a fallback ordering on the next load.
|
|
|
46
46
|
|
|
47
47
|
## the CLI can write these
|
|
48
48
|
|
|
49
|
-
`dt
|
|
49
|
+
`dt schema add-view|set-view|rm-view` — `set-view` takes dotted keys (`options.sort=-date`) and derives the record id
|
|
50
50
|
with the descriptor's own template, so a view saved from the CLI and one saved from the UI land on
|
|
51
51
|
the **same record**. This is the one system-stored kind with full CLI write support, because it goes
|
|
52
52
|
through the same compile gate.
|
|
@@ -45,7 +45,7 @@ demand:
|
|
|
45
45
|
|
|
46
46
|
`npm run --silent dt -- help` is the command surface — don't learn the generic verbs and flags from
|
|
47
47
|
prose; prose drifts. it does **not** list the purpose-built verbs some collections have
|
|
48
|
-
(`
|
|
48
|
+
(`schema add-collection`, `schema add-field <collection>`, `ensure`) — those live in the skill that owns
|
|
49
49
|
them, and a verb absent from `help` still works.
|
|
50
50
|
|
|
51
51
|
what you need to know *about* the CLI: collection verbs validate hard (invalid writes, **including
|
|
@@ -85,10 +85,37 @@ and deliberately nothing else — including nothing about people. There is no `u
|
|
|
85
85
|
- workspace-level rules live in `CLAUDE.md`, and a workspace's decision log (where one exists) wins
|
|
86
86
|
over older documents.
|
|
87
87
|
- **session greeting** — surface the operator's inbox from whatever collection this workspace uses for
|
|
88
|
-
work, e.g. `npm run --silent dt -- tasks
|
|
88
|
+
work, e.g. `npm run --silent dt -- list tasks --status todo`. ⚠ **there is no `users` collection and
|
|
89
89
|
no `@me`** (both removed in 0.8.0); read the operator from `git config user.name` at the point you
|
|
90
90
|
need one, and never filter on a person unless this workspace owns a collection of them.
|
|
91
91
|
|
|
92
|
+
## machine-specific references
|
|
93
|
+
|
|
94
|
+
a path that exists on only one machine — a synced folder, an external disk — is written as a
|
|
95
|
+
**template**, never as an absolute path:
|
|
96
|
+
|
|
97
|
+
```yaml
|
|
98
|
+
source_file: ${env:FILES_FOLDER}/2026/q3.pdf
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
| variable | renders to |
|
|
102
|
+
|---|---|
|
|
103
|
+
| `${env:NAME}` | `NAME`'s value in the workspace's `.env` — and only if `NAME` is listed in `dreamteamer.vars` in `package.json` |
|
|
104
|
+
| `${workspaceFolder}` | the workspace root, absolute |
|
|
105
|
+
| `${userHome}` | the current user's home directory |
|
|
106
|
+
|
|
107
|
+
- **declare the key before using it**: `"dreamteamer": { "vars": ["FILES_FOLDER"] }`. an undeclared
|
|
108
|
+
key and a declared-but-absent one are deliberately different errors — the first is a typo, the
|
|
109
|
+
second is a machine nobody has set up. `npm run compile` warns per declared var with no value in
|
|
110
|
+
`.env`, naming keys only.
|
|
111
|
+
- **render with `dt resolve`, the only substitution point**: `dt resolve '${env:FILES_FOLDER}/x'`, or
|
|
112
|
+
`dt resolve <collection>/<id> <field>` to render what a record already holds (an array field prints
|
|
113
|
+
one item per line). an argument containing `${` is always a template, so a ref-shaped one is never
|
|
114
|
+
split as a reference.
|
|
115
|
+
- ⚠ **templates are ordinary data — write them literally; nothing substitutes until resolve is
|
|
116
|
+
called.** `dt get`, `list`, `check` and every harness read the template verbatim. an un-namespaced
|
|
117
|
+
`${VAR}` is inert, so prose may mention `${…}` freely.
|
|
118
|
+
|
|
92
119
|
## common mistakes
|
|
93
120
|
|
|
94
121
|
| mistake | why it bites |
|
|
@@ -99,3 +126,4 @@ and deliberately nothing else — including nothing about people. There is no `u
|
|
|
99
126
|
| bare refs (`ada`, `data/contacts/x.contact.md`) | refs are `<collection>/<id>`; anything else fails check |
|
|
100
127
|
| assuming a write was committed | it was not, unless `auto-commit` is on — `dt status` says what is pending |
|
|
101
128
|
| `git add -A` in a shared tree | steals another session's uncommitted work, invisibly |
|
|
129
|
+
| an absolute machine path in a record | it is wrong on every other machine — write `${env:NAME}` and declare the key |
|
|
@@ -19,8 +19,8 @@ purpose.
|
|
|
19
19
|
## the verbs
|
|
20
20
|
|
|
21
21
|
`npm run --silent dt -- help` lists the generic record verbs and their flags. read them there.
|
|
22
|
-
but **`help` is not the whole surface** — collections with a purpose-built verb (`
|
|
23
|
-
|
|
22
|
+
but **`help` is not the whole surface** — collections with a purpose-built verb (`schema add-collection`,
|
|
23
|
+
`schema add-field <collection>`, `ensure`) don't appear in it, and a verb missing from `help`
|
|
24
24
|
is not a verb that doesn't exist. when a skill names a verb, use the verb.
|
|
25
25
|
|
|
26
26
|
what the help text can't tell you either way:
|
|
@@ -30,7 +30,7 @@ what the help text can't tell you either way:
|
|
|
30
30
|
got) or an id that misses `id.pattern`. a rejected write leaves no partial state.
|
|
31
31
|
- **every write verb commits by itself**, with the right subject — never stack another commit
|
|
32
32
|
on top.
|
|
33
|
-
- `set <id> <field>=` with an empty value **removes** the field; array fields take a
|
|
33
|
+
- `set <collection>/<id> <field>=` with an empty value **removes** the field; array fields take a
|
|
34
34
|
comma-separated value (`--attendees contacts/a,contacts/b`).
|
|
35
35
|
- `--json` works on every verb — use it whenever you're going to parse the output.
|
|
36
36
|
- `npm run check` validates the whole workspace after the fact: report-only, never rewrites.
|
|
@@ -45,10 +45,10 @@ to label one of its records) — both resolved by compile from the id unless aut
|
|
|
45
45
|
|
|
46
46
|
## writing a record by hand
|
|
47
47
|
|
|
48
|
-
**default to `dt <collection
|
|
48
|
+
**default to `dt add <collection>`** — id, defaults, validation and commit in one line. hand-write
|
|
49
49
|
only when the CLI can't express the value: a nested map, or a long structured body.
|
|
50
50
|
|
|
51
|
-
when you do, don't reconstruct the shape from the schema — **`dt
|
|
51
|
+
when you do, don't reconstruct the shape from the schema — **`dt get <collection>/<existing-id>
|
|
52
52
|
--json` prints the exact shape a valid record has**: which fields, which ref forms, dates as
|
|
53
53
|
strings. copy a sibling, change what differs, and:
|
|
54
54
|
|
|
@@ -81,8 +81,8 @@ A collection may be scoped under a namespace declared in the workspace `package.
|
|
|
81
81
|
QUALIFIED name is the collection's name everywhere:
|
|
82
82
|
|
|
83
83
|
```bash
|
|
84
|
-
dt health/doctors
|
|
85
|
-
dt health/visits
|
|
84
|
+
dt add health/doctors --name "Dana Levi" # → data/health/doctors/dana-levi.doctor.md
|
|
85
|
+
dt add health/visits --name Checkup --date 2026-03-04 --doctor health/doctors/dana-levi
|
|
86
86
|
```
|
|
87
87
|
|
|
88
88
|
- a reference is still `<collection>/<id>` — `health/doctors/dana-levi` is the collection
|