dreamteamer 0.26.0 → 0.27.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.
@@ -172,10 +172,19 @@ schema:
172
172
  group:
173
173
  type: string
174
174
  description: >-
175
- DEPRECATED as a nav axis since 2026-08-11 — the nav groups by `owner` (a module, which has a
176
- title of its own) instead of by this string with a display-name map maintained in a surface.
177
- Still read by nothing; kept so the change is a code revert rather than a data migration, and
178
- because a workspace may yet want a partition that deliberately DIFFERS from its modules.
175
+ The collection's PARTITION — which family of nouns it belongs to, authored freely (`crm`,
176
+ `finance`, `family`, `content`…) and set with `dt set collections/<c> group=<g>`. One value
177
+ is reserved and load-bearing: `group: system` says the collection is the workspace's own
178
+ MACHINERY rather than one of its domain nouns, so it is left out of the generated block's
179
+ domain listing, named on the system-collections line instead, and drawn on a surface's
180
+ schema surface rather than in the record tree. ⚠ It does NOT change where records live or
181
+ whether they can be written — that is `storage.base`, asked separately, and `repos` is the
182
+ collection where the two answers split: `group: system` and workspace-stored records the
183
+ operator edits by hand. Nearly removed on 2026-08-11, when the nav stopped grouping by it in
184
+ favour of `owner` (a module, which has a title of its own) and nothing else read it; kept
185
+ then so the change would be a code revert rather than a data migration, and because a
186
+ workspace may want a partition that deliberately DIFFERS from its modules. That is what it
187
+ became.
179
188
  order: 10
180
189
  list_fields: [name, last-modified]
181
190
  icon: schema
@@ -52,4 +52,10 @@ schema:
52
52
  order: 145
53
53
  list_fields: [name, identity, ref, url]
54
54
  icon: source
55
+ # MACHINERY, NOT A DOMAIN NOUN, and `group: system` is the whole statement of it. `repos` is the
56
+ # engine's only collection whose records live in `data/`, which used to make every workspace render
57
+ # a **System** module group with one collection under it — the group the block's own renderer says
58
+ # should not exist (harnesses.js). Being in the `system` partition folds it out of the block's
59
+ # domain listing and onto the schema surface instead. The records stay real, writable and committed;
60
+ # only the presentation changes.
55
61
  group: system
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dreamteamer",
3
- "version": "0.26.0",
3
+ "version": "0.27.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>",
package/src/harnesses.js CHANGED
@@ -142,7 +142,16 @@ const NOTEBOOK_PLANS = [
142
142
  function notebooklmBlock(entries, version) {
143
143
  const index = buildCollectionsIndex(entries);
144
144
  const modules = buildModulesIndex(entries);
145
- const data = index.filter((c) => !c.system);
145
+ // ⚠ `generated`, NOT `systemGroup` — the same split the orientation block's system line makes,
146
+ // asked for the opposite reason. There the question is presentational ("group it out of the
147
+ // domain listing"); HERE it is a STORAGE question, because every number and name below has to
148
+ // describe what `dt export notebooklm` will actually ship, and the export ships by storage
149
+ // (`storage.base !== 'runtime'` — export-notebooklm.js). Reading the partition here made this file
150
+ // say "exports 1 collections" and list only `notes` for a workspace whose export shipped
151
+ // `repos.md` as a second source and headed a `## module: System` group for it in the schema map
152
+ // — so the persona generated from this line would not know about a source it had been given.
153
+ // The count and the export are pinned to each other by a test (notebooklm-harness.test.js).
154
+ const data = index.filter((c) => !c.generated);
146
155
  const withheldCollections = data.filter((c) => c.sensitive).map((c) => c.name);
147
156
  const withheldFields = data.flatMap((c) => c.sensitiveFields.map((f) => `${c.name}.${f}`));
148
157
  const exported = data.filter((c) => !c.sensitive);
@@ -245,10 +254,16 @@ function buildCollectionsIndex(entries) {
245
254
  try { d = load(e.bytes.toString('utf8')) ?? {}; } catch { /* unparseable descriptor */ }
246
255
  index.push({
247
256
  name: d.name ?? m[1],
248
- // DERIVED, never a hardcoded name list: `runtime` is exactly the schema-ops set
249
- // (collections, commands, skills, agents, ui-views, command-bindings,
250
- // collection-templates, modules) and stays right in a workspace shipping others.
251
- system: d.storage?.base === 'runtime',
257
+ // ⚠ TWO QUESTIONS, KEPT SEPARATE. `systemGroup` answers "is this machinery, group it out
258
+ // of the domain listing"; `generated` answers "is this build output the hand-edit warning
259
+ // is about" — they agreed until `repos`, machinery whose records are still real files
260
+ // under `data/`. The partition is AUTHORED (`group: system` on the descriptor, ten core
261
+ // collections carry it), never derived from storage: a workspace collection may be its
262
+ // own apparatus, and a runtime-stored one may not be. An unparseable descriptor (`d = {}`
263
+ // from the catch above) carries neither key and answers false to both, which leaves it in
264
+ // the domain listing — the visible failure rather than the silent one.
265
+ systemGroup: d.group === 'system',
266
+ generated: d.storage?.base === 'runtime',
252
267
  description: flat(d.description),
253
268
  useWhen: flat(d.use_when),
254
269
  module: d.module ?? '',
@@ -354,10 +369,10 @@ function collectionsSection(index, modules, workspaceModule) {
354
369
  'collection\'s `write:` line names only what the store REFUSES — required fields that have no',
355
370
  'default (a defaulted one is filled in for you), closed enums with their size, one example.',
356
371
  ];
357
- const data = index.filter((c) => !c.system);
372
+ const data = index.filter((c) => !c.systemGroup);
358
373
  const isWs = (m) => m.path === `modules/${workspaceModule}/`;
359
374
  const groups = modules
360
- .filter((m) => { const own = index.filter((c) => c.module === m.id); return own.some((c) => !c.system) || (!own.length && (m.skills.length || m.commands.length || m.bin.length || m.proofs.length)); })
375
+ .filter((m) => { const own = index.filter((c) => c.module === m.id); return own.some((c) => !c.systemGroup) || (!own.length && (m.skills.length || m.commands.length || m.bin.length || m.proofs.length)); })
361
376
  .sort((a, b) => (isWs(b) - isWs(a)) || a.title.localeCompare(b.title));
362
377
  for (const m of groups) {
363
378
  const where = [`\`${m.id}\``, m.path ? m.path.replace(/\/$/, '') : 'the workspace root', ...(m.namespaces.length ? [`namespaces: ${m.namespaces.join(' · ')}`] : [])];
@@ -370,13 +385,19 @@ function collectionsSection(index, modules, workspaceModule) {
370
385
  if (c.write) lines.push(` write: ${c.write}`);
371
386
  }
372
387
  }
373
- const system = index.filter((c) => c.system).map((c) => c.name);
388
+ const sys = index.filter((c) => c.systemGroup);
389
+ const system = sys.filter((c) => c.generated).map((c) => c.name);
390
+ const kept = sys.filter((c) => !c.generated).map((c) => c.name);
374
391
  // ⚠ THIS LINE IS THE FIRST THING A SESSION READS about the system collections, and until 0.19.0
375
392
  // it said "schema-ops only", which named an internal module and a grammar that no longer exists.
376
393
  // It now names the VERBS and the one policy difference, because an agent that knows the verbs
377
- // exist still has to be told that these commit and records do not.
378
- if (system.length) {
379
- lines.push('', `- system collections — the SAME verbs (add · set · rm · rename · list · get), plus \`dt add-field\`/\`set-field\`/\`rm-field\`/\`rename-field <collection>\`. A system write COMMITS ITSELF, in the repo holding the source; a record write does not (\`dt commit\` publishes). Never hand-edit \`.dreamteamer/\` — it is build output: ${system.join(' · ')}`);
394
+ // exist still has to be told that these commit and records do not. And it is PARTITIONED on
395
+ // `generated`, not `systemGroup`: the partition only answers the grouping question, so a system
396
+ // collection whose records are real files (`repos`) gets its own trailing clause instead of being
397
+ // told "it is build output" — a sentence that was false of it and is false of the next data-backed
398
+ // system collection too, since the split is derived rather than naming one.
399
+ if (sys.length) {
400
+ lines.push('', `- system collections — the SAME verbs (add · set · rm · rename · list · get), plus \`dt add-field\`/\`set-field\`/\`rm-field\`/\`rename-field <collection>\`. A system write COMMITS ITSELF, in the repo holding the source; a record write does not (\`dt commit\` publishes).${system.length ? ` Never hand-edit \`.dreamteamer/\` — it is build output: ${system.join(' · ')}.` : ''}${kept.length ? ` Machinery whose records are real files you edit like any other: ${kept.join(' · ')}` : ''}`);
380
401
  }
381
402
  return lines;
382
403
  }
@@ -82,6 +82,10 @@ function collectionRow(d) {
82
82
  // it — the extension reads the presentation contract, not raw descriptors.
83
83
  if (typeof d.sort_field === 'string') meta.sort_field = d.sort_field;
84
84
 
85
+ // The collection's PARTITION, and the reserved value `system` is how a surface knows to draw this
86
+ // collection as the workspace's machinery rather than in the record tree. It is carried in `meta`
87
+ // beside the other presentation keys because that is the question it answers; the top-level
88
+ // `system` below answers a different one and they must never be folded together.
85
89
  if (typeof d.group === 'string') meta.group = d.group;
86
90
  if (typeof d.description === 'string' && d.description.length > 0) meta.description = d.description;
87
91
  // ⚠ `system` IS NOT `readonly`, AND SAYING SO COST A RELEASE. Until 0.19.0 the two were the
@@ -107,10 +111,25 @@ function collectionRow(d) {
107
111
  // already answers with its own sentence naming the fix, which is the contract the schema
108
112
  // surfaces are built on.
109
113
  //
110
- // `system` STAYS and is unchanged: the CLI and REST dispatch key on it, and it is what puts a
111
- // kind in the schema surface rather than the data one. A consumer that disables editing must
112
- // key on `meta.readonly` (per field, as `id`, `last-modified` and relation mirrors do) or on
113
- // the verb it is about to offer — never on `system`.
114
+ // `system` STAYS and is unchanged: the CLI and REST dispatch key on it. A consumer that disables
115
+ // editing must key on `meta.readonly` (per field, as `id`, `last-modified` and relation mirrors
116
+ // do) or on the verb it is about to offer — never on `system`.
117
+ //
118
+ // ⚠ AND `system` IS NO LONGER WHAT PUTS A KIND ON THE SCHEMA SURFACE — that clause stood here
119
+ // until `repos` and belongs to `meta.group` now. TWO QUESTIONS, KEPT SEPARATE, exactly as
120
+ // `buildCollectionsIndex` in src/harnesses.js keeps them:
121
+ //
122
+ // `system` decides HOW A WRITE IS PERFORMED. Is this collection's storage the compiled
123
+ // runtime? The CLI and the REST layer dispatch on it, and a surface that gets
124
+ // it wrong answers 400 to a write the store would have accepted.
125
+ // `meta.group` decides WHERE THE COLLECTION IS DRAWN. Its reserved value `system` says this
126
+ // is the workspace's machinery rather than one of its domain nouns, and folds
127
+ // the collection out of the record tree and onto the schema surface.
128
+ //
129
+ // The two agreed for every collection until `repos` — machinery whose records are ordinary,
130
+ // hand-edited files under `data/` — and it is why they must never be collapsed into one: a
131
+ // surface routing a `repos` write by the partition sends it to the system write path, whose
132
+ // entity ops know no such kind, and the write dies as a 400. Measured.
114
133
  const system = d.storage?.base === 'runtime';
115
134
  return { collection: d.name, meta, system };
116
135
  }
package/src/schema-ops.js CHANGED
@@ -755,6 +755,9 @@ const COLLECTION_SETTABLE = {
755
755
  title: (v) => String(v),
756
756
  title_template: (v) => String(v),
757
757
  icon: (v) => String(v),
758
+ // The collection's partition. `group=system` is the reserved value: it moves the collection out
759
+ // of the block's domain listing and onto a surface's schema surface, and changes nothing about
760
+ // where its records live or whether they can be written.
758
761
  group: (v) => String(v),
759
762
  sort_field: (v) => String(v),
760
763
  order: (v) => {