dreamteamer 0.23.0 → 0.24.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.
Files changed (3) hide show
  1. package/README.md +13 -0
  2. package/package.json +1 -1
  3. package/src/compile.js +34 -16
package/README.md CHANGED
@@ -111,6 +111,19 @@ node_modules/<name>/ # published package
111
111
  Precedence runs top to bottom, so a local copy shadows a published one — which is how you develop a
112
112
  module and use it in the same workspace at the same time.
113
113
 
114
+ A published package or a git clone may carry **several** modules: when its root has a `modules/`
115
+ folder, each `modules/<name>/` with a `dreamteamer` key in its `package.json` is a module on that
116
+ channel, and the root itself is never compiled. One `npm install` then delivers a whole family, and the
117
+ workspace keeps what it wants — a bare module name in `dreamteamer.disable` drops a module before
118
+ compile looks at it (an entry with a slash, `<module>/<entity>`, still disables one entity):
119
+
120
+ ```json
121
+ "dreamteamer": { "disable": ["recordings", "introspection"] }
122
+ ```
123
+
124
+ Disabling a module another one declares in `dependencies` is refused, naming what is present. The
125
+ workspace's own `modules/*` never nest.
126
+
114
127
  Sources live **flat at a module root** — `modules/crm/skills/`, beside `package.json` — and a folder
115
128
  at a module root that isn't a known kind is a compile error rather than a silent skip.
116
129
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dreamteamer",
3
- "version": "0.23.0",
3
+ "version": "0.24.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/compile.js CHANGED
@@ -523,33 +523,51 @@ export const locationOf = (source, wsRoot) =>
523
523
  export function discoverModules(root, pkg) {
524
524
  const byName = new Map(); // name -> {name, root, channel}
525
525
  const shadows = []; // {name, winner, loser} — channels
526
+ // A BARE `dreamteamer.disable` entry names a whole module; `<module>/<entity>` names one entity and
527
+ // is applied per source at compile time. The bare form is what lets a workspace take a PACKAGE of
528
+ // modules and keep only the ones it wants — a disabled module is simply never discovered, so every
529
+ // caller (compile, status, install) sees the same set.
530
+ const disabledModules = new Set((pkg?.dreamteamer?.disable ?? []).filter((d) => typeof d === 'string' && !d.includes('/')));
531
+ const disabledHits = new Set();
526
532
  const tryAdd = (name, srcRoot, channel) => {
533
+ if (disabledModules.has(name)) { disabledHits.add(name); return; }
527
534
  const existing = byName.get(name);
528
535
  if (existing) { shadows.push({ name, winner: existing.channel, loser: channel }); return; }
529
536
  byName.set(name, { name, root: srcRoot, channel });
530
537
  };
531
- const scanDir = (dir, channel) => {
538
+ const readPkg = (dir) => {
539
+ try {
540
+ const mpkg = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8'));
541
+ return 'dreamteamer' in mpkg ? mpkg : null;
542
+ } catch { return null; } // no package.json, or unparseable — not a module
543
+ };
544
+ // A PACKAGE OF MODULES: a dependency or a git clone whose root carries `modules/` bundles several
545
+ // modules — its sub-modules are the modules, and the root itself is never compiled. One
546
+ // `npm install` (or one clone) then delivers a whole family, and `disable` cherry-picks from it.
547
+ // Inline `modules/*` never nest: a `modules/` folder at an inline module root stays the
548
+ // unknown-folder compile error it always was, because the workspace's own tree has no reason to
549
+ // bundle.
550
+ const scanDir = (dir, channel, unpack) => {
532
551
  if (!fs.existsSync(dir)) return;
533
552
  for (const name of fs.readdirSync(dir).sort()) {
534
553
  const srcRoot = path.join(dir, name);
535
- const pkgPath = path.join(srcRoot, 'package.json');
536
- if (!fs.existsSync(pkgPath)) continue;
537
- try {
538
- const mpkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
539
- if ('dreamteamer' in mpkg) tryAdd(mpkg.name ?? name, srcRoot, channel);
540
- } catch { /* unparseable package.json — skip */ }
554
+ const mpkg = readPkg(srcRoot);
555
+ if (mpkg) (unpack ? tryAddOrUnpack : tryAdd)(mpkg.name ?? name, srcRoot, channel);
541
556
  }
542
557
  };
543
- scanDir(path.join(root, 'modules'), 'inline');
544
- scanDir(path.join(root, 'git_modules'), 'git');
558
+ const tryAddOrUnpack = (name, srcRoot, channel) => {
559
+ const bundle = path.join(srcRoot, 'modules');
560
+ if (fs.existsSync(bundle) && fs.statSync(bundle).isDirectory()) { scanDir(bundle, channel, false); return; }
561
+ tryAdd(name, srcRoot, channel);
562
+ };
563
+ scanDir(path.join(root, 'modules'), 'inline', false);
564
+ scanDir(path.join(root, 'git_modules'), 'git', true);
545
565
  for (const dep of Object.keys({ ...pkg.dependencies, ...pkg.devDependencies }).sort()) {
546
566
  const srcRoot = path.join(root, 'node_modules', dep);
547
- try {
548
- const mpkg = JSON.parse(fs.readFileSync(path.join(srcRoot, 'package.json'), 'utf8'));
549
- if ('dreamteamer' in mpkg) tryAdd(mpkg.name ?? dep, srcRoot, 'npm');
550
- } catch { /* dep not installed or no package.json — skip */ }
567
+ const mpkg = readPkg(srcRoot);
568
+ if (mpkg) tryAddOrUnpack(mpkg.name ?? dep, srcRoot, 'npm');
551
569
  }
552
- return { modules: [...byName.values()], shadows };
570
+ return { modules: [...byName.values()], shadows, disabledModules: [...disabledHits] };
553
571
  }
554
572
 
555
573
  // ---- module-owned data ----------------------------------------------------------
@@ -629,7 +647,7 @@ export function compile({ root, pkg }) {
629
647
  };
630
648
 
631
649
  // ---- discover sources: channel modules then the workspace's own -----------------
632
- const { modules: discovered, shadows } = discoverModules(root, pkg);
650
+ const { modules: discovered, shadows, disabledModules } = discoverModules(root, pkg);
633
651
  for (const s of shadows) console.warn(shadowWarning(s));
634
652
  const sources = [...discovered];
635
653
  // workspace-owned sources: either at the root (classic layout) or in the designated
@@ -809,7 +827,7 @@ export function compile({ root, pkg }) {
809
827
  const dataOwners = dataOwningModules(sources, fail, rel);
810
828
 
811
829
  const disabled = new Set(config.disable ?? []);
812
- const disabledHits = new Set();
830
+ const disabledHits = new Set(disabledModules); // bare entries were applied at discovery
813
831
 
814
832
  /** entries: runtime-relative path -> { sources: [workspace-relative], bytes } */
815
833
  const entries = new Map();