dreamteamer 0.13.0 → 0.13.2
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/package.json +2 -2
- package/src/compile.js +29 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dreamteamer",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.2",
|
|
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>",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"node": ">=20"
|
|
30
30
|
},
|
|
31
31
|
"bin": {
|
|
32
|
-
"dreamteamer": "
|
|
32
|
+
"dreamteamer": "bin/dreamteamer.js"
|
|
33
33
|
},
|
|
34
34
|
"files": [
|
|
35
35
|
"NOTICE",
|
package/src/compile.js
CHANGED
|
@@ -12,6 +12,7 @@ import { walk, patternRe } from './records.js';
|
|
|
12
12
|
import { unknownOperators } from './filter.js';
|
|
13
13
|
import {
|
|
14
14
|
normalizeNamespaces, namespaceProblems, unqualifiedProblems, defaultStoragePath, storageOverlaps,
|
|
15
|
+
baseNameOf,
|
|
15
16
|
} from './namespace.js';
|
|
16
17
|
// circular on paper in earlier versions — safe: both sides only
|
|
17
18
|
// call at run time, same pattern as store.js ↔ compile.js.
|
|
@@ -717,7 +718,14 @@ export function compile({ root, pkg }) {
|
|
|
717
718
|
// browse page, the CLI and the extension then read ONE field instead of each carrying its
|
|
718
719
|
// own title-caser. Authored values always win — `??=` never overwrites. After the ajv gate
|
|
719
720
|
// on purpose: a malformed property must fail as a bad schema, not as a TypeError here.
|
|
720
|
-
|
|
721
|
+
// ⚠ From the BARE name, not the qualified one. A namespace is the FOLDER a collection sits in,
|
|
722
|
+
// not part of what it is called — every surface that draws the namespace as a folder was
|
|
723
|
+
// otherwise saying it twice on one screen ("R&D > Rnd Prototypes", "Family > Health >
|
|
724
|
+
// Health Documents"). Workspaces had already worked around it by hand-authoring a title on
|
|
725
|
+
// every namespaced collection, which is the tell: a derivation nobody can use is not a
|
|
726
|
+
// default. `baseNameOf` resolves against the DECLARED list, so an undeclared prefix — which
|
|
727
|
+
// is not a namespace — keeps its whole name in the label.
|
|
728
|
+
merged.title ??= titleCase(baseNameOf(name, namespaces));
|
|
721
729
|
const labelProps = merged.schema?.properties ?? {};
|
|
722
730
|
// how a RECORD of this collection is labelled — the probe presentation.js has always used
|
|
723
731
|
// for `meta.title_field`, promoted to an authorable field. Reference fields pointing here
|
|
@@ -841,6 +849,9 @@ export function compile({ root, pkg }) {
|
|
|
841
849
|
// The descriptor already documented the correct behaviour — ui-views.collection.yaml: "An
|
|
842
850
|
// unregistered id degrades visibly rather than erroring" — and the surface already implements
|
|
843
851
|
// it (presets.ts#resolveRendererEntry falls back to table). Decision 195.
|
|
852
|
+
// ui-views' own field names, read from the descriptor that was just merged rather than hardcoded —
|
|
853
|
+
// a list in here would silently stop covering a field the moment ui-views grew one.
|
|
854
|
+
const ownFields = load(entries.get(path.join('collections', 'ui-views.collection.yaml'))?.bytes?.toString('utf8') ?? '')?.schema?.properties ?? {};
|
|
844
855
|
for (const [rt, e] of entries) {
|
|
845
856
|
if (!rt.startsWith('ui-views/')) continue;
|
|
846
857
|
const view = load(e.bytes.toString('utf8'));
|
|
@@ -854,6 +865,23 @@ export function compile({ root, pkg }) {
|
|
|
854
865
|
if (view?.filter && JSON.stringify(view.filter).includes('"@me"')) {
|
|
855
866
|
fail(`${rt}: filter uses "@me", which was removed with the \`users\` collection in 0.8.0 — it would now match nothing.\n filter on a field this workspace owns instead (e.g. { status: { _eq: "todo" } }).`);
|
|
856
867
|
}
|
|
868
|
+
// ⚠ `options` is a deliberately OPEN object — every key it does not own rides through untouched
|
|
869
|
+
// to whichever surface renders the layout. That openness is right, and it has one sharp edge: a
|
|
870
|
+
// field that belongs ONE LEVEL UP, written inside it, is accepted, saved, round-tripped and read
|
|
871
|
+
// by nobody. `options.filter` cost a real afternoon — the view drew all 429 rows of a collection
|
|
872
|
+
// it was supposed to narrow to 90, and neither compile nor check nor the surface said a word.
|
|
873
|
+
//
|
|
874
|
+
// This is the same rule the block above states, not an exception to it: the engine DOES interpret
|
|
875
|
+
// `filter`, so a `filter` it will never be handed is a value it can catch. A warning rather than a
|
|
876
|
+
// failure because `options` is open by contract and a surface may legitimately want a key that
|
|
877
|
+
// collides — but the operator has to be told, because the symptom is a view that looks like it
|
|
878
|
+
// works.
|
|
879
|
+
const shadowed = view?.options && typeof view.options === 'object' && !Array.isArray(view.options)
|
|
880
|
+
? Object.keys(view.options).filter((k) => k in ownFields)
|
|
881
|
+
: [];
|
|
882
|
+
for (const k of shadowed) {
|
|
883
|
+
console.warn(`⚠ ${rt}: options.${k} is read by nothing — \`${k}\` is a field of ui-views itself, one level up. move it out of \`options\`.`);
|
|
884
|
+
}
|
|
857
885
|
}
|
|
858
886
|
|
|
859
887
|
// ---- command-binding validation --------------------------------------------------
|