« get me outta code hell

cacheable-object, data: depend on computed values; initial compat - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2025-11-25 12:03:13 -0400
committer(quasar) nebula <qznebula@protonmail.com>2025-11-25 12:04:49 -0400
commit95c7c7032556d3adfc3107d11a3e14ab0f4c9145 (patch)
tree800d4f7dfe0997d9be1a16cd9586228b1a832dbd
parent3afd5e8f8d6b08ccb9e49e53b0da4423a7d23542 (diff)
cacheable-object, data: depend on computed values; initial compat
reaches live-dev-server serve with no errors and serves
homepage at all and apparently correctly

no page navigation performed
no full build performed

aimed for preserving existing logic
should be no subsequent changes to this commit (amend)
-rw-r--r--src/aggregate.js5
-rw-r--r--src/data/cacheable-object.js86
-rw-r--r--src/data/composite.js3
-rw-r--r--src/data/composite/data/helpers/property-from-helpers.js6
-rw-r--r--src/data/composite/things/album/withCoverArtDate.js6
-rw-r--r--src/data/composite/things/art-tag/withAllDescendantArtTags.js4
-rw-r--r--src/data/composite/things/artwork/withArtTags.js2
-rw-r--r--src/data/composite/things/artwork/withDate.js2
-rw-r--r--src/data/composite/things/content/withAnnotationParts.js4
-rw-r--r--src/data/composite/things/contribution/withContainingReverseContributionList.js2
-rw-r--r--src/data/composite/things/language/withStrings.js2
-rw-r--r--src/data/composite/things/track-section/withStartCountingFrom.js2
-rw-r--r--src/data/composite/things/track/alwaysReferenceByDirectory.js2
-rw-r--r--src/data/composite/things/track/withCoverArtistContribs.js2
-rw-r--r--src/data/composite/things/track/withHasUniqueCoverArt.js6
-rw-r--r--src/data/composite/things/track/withMainRelease.js2
-rw-r--r--src/data/composite/things/track/withMainReleaseTrack.js6
-rw-r--r--src/data/composite/things/track/withSuffixDirectoryFromAlbum.js8
-rw-r--r--src/data/composite/things/track/withTrackArtDate.js2
-rw-r--r--src/data/composite/wiki-data/gobbleSoupyFind.js2
-rw-r--r--src/data/composite/wiki-data/gobbleSoupyReverse.js2
-rw-r--r--src/data/composite/wiki-data/helpers/withSimpleDirectory.js2
-rw-r--r--src/data/composite/wiki-data/withDirectory.js4
-rw-r--r--src/data/composite/wiki-data/withResolvedContribs.js4
-rw-r--r--src/data/composite/wiki-properties/referencedArtworkList.js2
-rw-r--r--src/data/things/album.js70
-rw-r--r--src/data/things/content.js2
-rw-r--r--src/data/things/group.js12
-rw-r--r--src/data/things/index.js10
-rw-r--r--src/data/things/track.js6
-rw-r--r--src/data/things/wiki-info.js2
31 files changed, 152 insertions, 118 deletions
diff --git a/src/aggregate.js b/src/aggregate.js
index 3ff1846b..23a67d20 100644
--- a/src/aggregate.js
+++ b/src/aggregate.js
@@ -417,6 +417,7 @@ export function showAggregate(topError, {
   pathToFileURL = f => f,
   showTraces = true,
   showTranslucent = showTraces,
+  showClasses = showTraces,
   print = true,
 } = {}) {
   const getTranslucency = error =>
@@ -569,10 +570,10 @@ export function showAggregate(topError, {
       message || `(no message)`;
 
     const kindPart =
-      kind || `unnamed kind`;
+      kind || `unnamed class`;
 
     let headerPart =
-      (showTraces
+      (showClasses
         ? `[${kindPart}] ${messagePart}`
      : errors
         ? `[${messagePart}]`
diff --git a/src/data/cacheable-object.js b/src/data/cacheable-object.js
index 3aa3ecf7..dead009a 100644
--- a/src/data/cacheable-object.js
+++ b/src/data/cacheable-object.js
@@ -120,18 +120,14 @@ export default class CacheableObject {
 
           const dependencies = Object.create(null);
           for (const key of expose.dependencies ?? []) {
-            switch (key) {
-              case 'this':
-                dependencies.this = this;
-                break;
-
-              case 'thisProperty':
-                dependencies.thisProperty = property;
-                break;
-
-              default:
-                dependencies[key] = this[CacheableObject.updateValue][key];
-                break;
+            if (key === 'this') {
+              dependencies.this = this;
+            } else if (key === 'thisProperty') {
+              dependencies.thisProperty = property;
+            } else if (key.startsWith('_')) {
+              dependencies[key] = this[CacheableObject.updateValue][key.slice(1)];
+            } else {
+              dependencies[key] = this[key];
             }
           }
 
@@ -150,27 +146,11 @@ export default class CacheableObject {
       if (flags.expose) recordAsDependant: {
         const dependantsMap = this[CacheableObject.propertyDependants];
 
-        if (flags.update && expose?.transform) {
-          if (dependantsMap[property]) {
-            dependantsMap[property].push(property);
+        for (const dependency of dependenciesOf(property, propertyDescriptors)) {
+          if (dependantsMap[dependency]) {
+            dependantsMap[dependency].push(dependency);
           } else {
-            dependantsMap[property] = [property];
-          }
-        }
-
-        for (const dependency of expose?.dependencies ?? []) {
-          switch (dependency) {
-            case 'this':
-            case 'thisProperty':
-              continue;
-
-            default: {
-              if (dependantsMap[dependency]) {
-                dependantsMap[dependency].push(property);
-              } else {
-                dependantsMap[dependency] = [property];
-              }
-            }
+            dependantsMap[dependency] = [dependency];
           }
         }
       }
@@ -261,6 +241,7 @@ export class CacheableObjectPropertyValueError extends Error {
 }
 
 // good ol' module-scope utility functions
+
 function validatePropertyValue(property, oldValue, newValue, update) {
   try {
     const result = update.validate(newValue);
@@ -274,3 +255,44 @@ function validatePropertyValue(property, oldValue, newValue, update) {
       property, oldValue, newValue, {cause: caughtError});
   }
 }
+
+function* dependenciesOf(property, propertyDescriptors, cycle = []) {
+  const descriptor = propertyDescriptors[property];
+
+  if (descriptor?.flags?.update && descriptor?.expose?.transform) {
+    yield property;
+  }
+
+  const dependencies = descriptor?.expose?.dependencies;
+  if (!dependencies) return;
+
+  for (const dependency of dependencies) {
+    if (dependency === 'this') continue;
+    if (dependency === 'thisProperty') continue;
+
+    if (dependency.startsWith('_')) {
+      yield dependency.slice(1);
+      continue;
+    }
+
+    if (dependency === property) {
+      throw new Error(
+        `property ${dependency} directly depends on its own computed value`);
+    }
+
+    if (cycle.includes(dependency)) {
+      const subcycle = cycle.slice(cycle.indexOf(dependency));
+      const supercycle = cycle.slice(0, cycle.indexOf(dependency));
+      throw new Error(
+        `property ${dependency} indirectly depends on its own computed value\n` +
+        `  via: ` + subcycle.map(p => p + ' -> ').join('') + property + ' -> ' + dependency +
+        (supercycle.length
+          ? '\n   in: ' + supercycle.join(' -> ')
+          : ''));
+    }
+
+    cycle.push(property);
+    yield* dependenciesOf(dependency, propertyDescriptors, cycle);
+    cycle.pop();
+  }
+}
diff --git a/src/data/composite.js b/src/data/composite.js
index 3dad52f2..b70dbcaf 100644
--- a/src/data/composite.js
+++ b/src/data/composite.js
@@ -713,8 +713,9 @@ export function compositeFrom(description) {
       stepExposeDescriptions
         .flatMap(expose => expose?.dependencies ?? [])
         .map(dependency => {
-          if (typeof dependency === 'string')
+          if (typeof dependency === 'string') {
             return (dependency.startsWith('#') ? null : dependency);
+          }
 
           const tokenShape = getInputTokenShape(dependency);
           const tokenValue = getInputTokenValue(dependency);
diff --git a/src/data/composite/data/helpers/property-from-helpers.js b/src/data/composite/data/helpers/property-from-helpers.js
index 3d1e12a5..00251f3b 100644
--- a/src/data/composite/data/helpers/property-from-helpers.js
+++ b/src/data/composite/data/helpers/property-from-helpers.js
@@ -2,7 +2,11 @@ export function getOutputName({property, from, prefix = null}) {
   if (property && prefix) {
     return `${prefix}.${property}`;
   } else if (property && from) {
-    return `${from}.${property}`;
+    if (from.startsWith('_')) {
+      return `${from.slice(1)}.${property}`;
+    } else {
+      return `${from}.${property}`;
+    }
   } else {
     if (!property) throw new Error(`guard property outside getOutputName(), c'mon`);
     if (!from) throw new Error(`guard from in getOutputName(), c'mon`);
diff --git a/src/data/composite/things/album/withCoverArtDate.js b/src/data/composite/things/album/withCoverArtDate.js
index 978f566a..c006fab9 100644
--- a/src/data/composite/things/album/withCoverArtDate.js
+++ b/src/data/composite/things/album/withCoverArtDate.js
@@ -10,7 +10,7 @@ export default templateCompositeFrom({
   inputs: {
     from: input({
       validate: isDate,
-      defaultDependency: 'coverArtDate',
+      defaultDependency: '_coverArtDate',
       acceptsNull: true,
     }),
   },
@@ -19,8 +19,8 @@ export default templateCompositeFrom({
 
   steps: () => [
     withHasArtwork({
-      contribs: 'coverArtistContribs',
-      artworks: 'coverArtworks',
+      contribs: '_coverArtistContribs',
+      artworks: '_coverArtworks',
     }),
 
     raiseOutputWithoutDependency({
diff --git a/src/data/composite/things/art-tag/withAllDescendantArtTags.js b/src/data/composite/things/art-tag/withAllDescendantArtTags.js
index 795f96cd..934999a3 100644
--- a/src/data/composite/things/art-tag/withAllDescendantArtTags.js
+++ b/src/data/composite/things/art-tag/withAllDescendantArtTags.js
@@ -18,13 +18,13 @@ export default templateCompositeFrom({
 
   steps: () => [
     raiseOutputWithoutDependency({
-      dependency: 'directDescendantArtTags',
+      dependency: '_directDescendantArtTags',
       mode: input.value('empty'),
       output: input.value({'#allDescendantArtTags': []})
     }),
 
     withResolvedReferenceList({
-      list: 'directDescendantArtTags',
+      list: '_directDescendantArtTags',
       find: soupyFind.input('artTag'),
     }),
 
diff --git a/src/data/composite/things/artwork/withArtTags.js b/src/data/composite/things/artwork/withArtTags.js
index 1fed3c31..1f605d68 100644
--- a/src/data/composite/things/artwork/withArtTags.js
+++ b/src/data/composite/things/artwork/withArtTags.js
@@ -16,7 +16,7 @@ export default templateCompositeFrom({
     from: input({
       type: 'array',
       acceptsNull: true,
-      defaultDependency: 'artTags',
+      defaultDependency: '_artTags',
     }),
   },
 
diff --git a/src/data/composite/things/artwork/withDate.js b/src/data/composite/things/artwork/withDate.js
index 5e05b814..4666ff1b 100644
--- a/src/data/composite/things/artwork/withDate.js
+++ b/src/data/composite/things/artwork/withDate.js
@@ -8,7 +8,7 @@ export default templateCompositeFrom({
 
   inputs: {
     from: input({
-      defaultDependency: 'date',
+      defaultDependency: '_date',
       acceptsNull: true,
     }),
   },
diff --git a/src/data/composite/things/content/withAnnotationParts.js b/src/data/composite/things/content/withAnnotationParts.js
index 0c5a0294..15eb74a5 100644
--- a/src/data/composite/things/content/withAnnotationParts.js
+++ b/src/data/composite/things/content/withAnnotationParts.js
@@ -19,12 +19,12 @@ export default templateCompositeFrom({
 
   steps: () => [
     raiseOutputWithoutDependency({
-      dependency: 'annotation',
+      dependency: '_annotation',
       output: input.value({'#annotationParts': []}),
     }),
 
     withContentNodes({
-      from: 'annotation',
+      from: '_annotation',
     }),
 
     splitContentNodesAround({
diff --git a/src/data/composite/things/contribution/withContainingReverseContributionList.js b/src/data/composite/things/contribution/withContainingReverseContributionList.js
index 175d6cbb..7f226ff1 100644
--- a/src/data/composite/things/contribution/withContainingReverseContributionList.js
+++ b/src/data/composite/things/contribution/withContainingReverseContributionList.js
@@ -16,7 +16,7 @@ export default templateCompositeFrom({
 
   inputs: {
     artistProperty: input({
-      defaultDependency: 'artistProperty',
+      defaultDependency: '_artistProperty',
       acceptsNull: true,
     }),
   },
diff --git a/src/data/composite/things/language/withStrings.js b/src/data/composite/things/language/withStrings.js
index 3b8d46b3..761e7506 100644
--- a/src/data/composite/things/language/withStrings.js
+++ b/src/data/composite/things/language/withStrings.js
@@ -9,7 +9,7 @@ export default templateCompositeFrom({
   annotation: `withStrings`,
 
   inputs: {
-    from: input({defaultDependency: 'strings'}),
+    from: input({defaultDependency: '_strings'}),
   },
 
   outputs: ['#strings'],
diff --git a/src/data/composite/things/track-section/withStartCountingFrom.js b/src/data/composite/things/track-section/withStartCountingFrom.js
index 20e18edb..6cf03802 100644
--- a/src/data/composite/things/track-section/withStartCountingFrom.js
+++ b/src/data/composite/things/track-section/withStartCountingFrom.js
@@ -9,7 +9,7 @@ export default templateCompositeFrom({
   inputs: {
     from: input({
       type: 'number',
-      defaultDependency: 'startCountingFrom',
+      defaultDependency: '_startCountingFrom',
       acceptsNull: true,
     }),
   },
diff --git a/src/data/composite/things/track/alwaysReferenceByDirectory.js b/src/data/composite/things/track/alwaysReferenceByDirectory.js
index a342d38b..7b72865b 100644
--- a/src/data/composite/things/track/alwaysReferenceByDirectory.js
+++ b/src/data/composite/things/track/alwaysReferenceByDirectory.js
@@ -40,7 +40,7 @@ export default templateCompositeFrom({
     }),
 
     exitWithoutDependency({
-      dependency: 'mainRelease',
+      dependency: '_mainRelease',
       value: input.value(false),
     }),
 
diff --git a/src/data/composite/things/track/withCoverArtistContribs.js b/src/data/composite/things/track/withCoverArtistContribs.js
index 9057cfeb..313d4552 100644
--- a/src/data/composite/things/track/withCoverArtistContribs.js
+++ b/src/data/composite/things/track/withCoverArtistContribs.js
@@ -18,7 +18,7 @@ export default templateCompositeFrom({
 
   inputs: {
     from: input({
-      defaultDependency: 'coverArtistContribs',
+      defaultDependency: '_coverArtistContribs',
       validate: isContributionList,
       acceptsNull: true,
     }),
diff --git a/src/data/composite/things/track/withHasUniqueCoverArt.js b/src/data/composite/things/track/withHasUniqueCoverArt.js
index 85d3b92a..c52abb98 100644
--- a/src/data/composite/things/track/withHasUniqueCoverArt.js
+++ b/src/data/composite/things/track/withHasUniqueCoverArt.js
@@ -37,7 +37,7 @@ export default templateCompositeFrom({
     },
 
     withResultOfAvailabilityCheck({
-      from: 'coverArtistContribs',
+      from: '_coverArtistContribs',
       mode: input.value('empty'),
     }),
 
@@ -76,13 +76,13 @@ export default templateCompositeFrom({
     },
 
     raiseOutputWithoutDependency({
-      dependency: 'trackArtworks',
+      dependency: '_trackArtworks',
       mode: input.value('empty'),
       output: input.value({'#hasUniqueCoverArt': false}),
     }),
 
     withPropertyFromList({
-      list: 'trackArtworks',
+      list: '_trackArtworks',
       property: input.value('artistContribs'),
       internal: input.value(true),
     }),
diff --git a/src/data/composite/things/track/withMainRelease.js b/src/data/composite/things/track/withMainRelease.js
index 67a312ae..fb1342ec 100644
--- a/src/data/composite/things/track/withMainRelease.js
+++ b/src/data/composite/things/track/withMainRelease.js
@@ -18,7 +18,7 @@ export default templateCompositeFrom({
 
   inputs: {
     from: input({
-      defaultDependency: 'mainRelease',
+      defaultDependency: '_mainRelease',
       acceptsNull: true,
     }),
 
diff --git a/src/data/composite/things/track/withMainReleaseTrack.js b/src/data/composite/things/track/withMainReleaseTrack.js
index 6371e895..70d55dd4 100644
--- a/src/data/composite/things/track/withMainReleaseTrack.js
+++ b/src/data/composite/things/track/withMainReleaseTrack.js
@@ -35,7 +35,7 @@ export default templateCompositeFrom({
 
   steps: () => [
     withResultOfAvailabilityCheck({
-      from: 'mainRelease',
+      from: '_mainRelease',
     }),
 
     {
@@ -85,10 +85,10 @@ export default templateCompositeFrom({
     },
 
     {
-      dependencies: ['name', 'directory'],
+      dependencies: ['name', '_directory'],
       compute: (continuation, {
         ['name']: ownName,
-        ['directory']: ownDirectory,
+        ['_directory']: ownDirectory,
       }) => {
         const ownNameKebabed = getKebabCase(ownName);
 
diff --git a/src/data/composite/things/track/withSuffixDirectoryFromAlbum.js b/src/data/composite/things/track/withSuffixDirectoryFromAlbum.js
index 047077fd..b9d8848d 100644
--- a/src/data/composite/things/track/withSuffixDirectoryFromAlbum.js
+++ b/src/data/composite/things/track/withSuffixDirectoryFromAlbum.js
@@ -8,7 +8,7 @@ export default templateCompositeFrom({
 
   inputs: {
     flagValue: input({
-      defaultDependency: 'suffixDirectoryFromAlbum',
+      defaultDependency: '_suffixDirectoryFromAlbum',
       acceptsNull: true,
     }),
   },
@@ -17,18 +17,18 @@ export default templateCompositeFrom({
 
   steps: () => [
     withResultOfAvailabilityCheck({
-      from: 'suffixDirectoryFromAlbum',
+      from: input('flagValue'),
     }),
 
     {
       dependencies: [
         '#availability',
-        'suffixDirectoryFromAlbum'
+        input('flagValue'),
       ],
 
       compute: (continuation, {
         ['#availability']: availability,
-        ['suffixDirectoryFromAlbum']: flagValue,
+        [input('flagValue')]: flagValue,
       }) =>
         (availability
           ? continuation.raiseOutput({['#suffixDirectoryFromAlbum']: flagValue})
diff --git a/src/data/composite/things/track/withTrackArtDate.js b/src/data/composite/things/track/withTrackArtDate.js
index 9b7b61c7..f524afb9 100644
--- a/src/data/composite/things/track/withTrackArtDate.js
+++ b/src/data/composite/things/track/withTrackArtDate.js
@@ -13,7 +13,7 @@ export default templateCompositeFrom({
   inputs: {
     from: input({
       validate: isDate,
-      defaultDependency: 'coverArtDate',
+      defaultDependency: '_coverArtDate',
       acceptsNull: true,
     }),
   },
diff --git a/src/data/composite/wiki-data/gobbleSoupyFind.js b/src/data/composite/wiki-data/gobbleSoupyFind.js
index aec3f5b1..98d5f5c9 100644
--- a/src/data/composite/wiki-data/gobbleSoupyFind.js
+++ b/src/data/composite/wiki-data/gobbleSoupyFind.js
@@ -30,7 +30,7 @@ export default templateCompositeFrom({
     },
 
     withPropertyFromObject({
-      object: 'find',
+      object: '_find',
       property: '#key',
     }).outputs({
       '#value': '#find',
diff --git a/src/data/composite/wiki-data/gobbleSoupyReverse.js b/src/data/composite/wiki-data/gobbleSoupyReverse.js
index 86a1061c..26052f28 100644
--- a/src/data/composite/wiki-data/gobbleSoupyReverse.js
+++ b/src/data/composite/wiki-data/gobbleSoupyReverse.js
@@ -30,7 +30,7 @@ export default templateCompositeFrom({
     },
 
     withPropertyFromObject({
-      object: 'reverse',
+      object: '_reverse',
       property: '#key',
     }).outputs({
       '#value': '#reverse',
diff --git a/src/data/composite/wiki-data/helpers/withSimpleDirectory.js b/src/data/composite/wiki-data/helpers/withSimpleDirectory.js
index 08ca3bfc..0b225847 100644
--- a/src/data/composite/wiki-data/helpers/withSimpleDirectory.js
+++ b/src/data/composite/wiki-data/helpers/withSimpleDirectory.js
@@ -15,7 +15,7 @@ export default templateCompositeFrom({
   inputs: {
     directory: input({
       validate: isDirectory,
-      defaultDependency: 'directory',
+      defaultDependency: '_directory',
       acceptsNull: true,
     }),
 
diff --git a/src/data/composite/wiki-data/withDirectory.js b/src/data/composite/wiki-data/withDirectory.js
index f3bedf2e..e7c3960e 100644
--- a/src/data/composite/wiki-data/withDirectory.js
+++ b/src/data/composite/wiki-data/withDirectory.js
@@ -17,13 +17,13 @@ export default templateCompositeFrom({
   inputs: {
     directory: input({
       validate: isDirectory,
-      defaultDependency: 'directory',
+      defaultDependency: '_directory',
       acceptsNull: true,
     }),
 
     name: input({
       validate: isName,
-      defaultDependency: 'name',
+      defaultDependency: '_name',
       acceptsNull: true,
     }),
 
diff --git a/src/data/composite/wiki-data/withResolvedContribs.js b/src/data/composite/wiki-data/withResolvedContribs.js
index 838c991f..60b5d4c6 100644
--- a/src/data/composite/wiki-data/withResolvedContribs.js
+++ b/src/data/composite/wiki-data/withResolvedContribs.js
@@ -110,7 +110,7 @@ export default templateCompositeFrom({
         '#thingProperty',
         input('artistProperty'),
         input.myself(),
-        'find',
+        '_find',
       ],
 
       compute: (continuation, {
@@ -118,7 +118,7 @@ export default templateCompositeFrom({
         ['#thingProperty']: thingProperty,
         [input('artistProperty')]: artistProperty,
         [input.myself()]: myself,
-        ['find']: find,
+        ['_find']: find,
       }) => continuation({
         ['#contributions']:
           details.map(details => {
diff --git a/src/data/composite/wiki-properties/referencedArtworkList.js b/src/data/composite/wiki-properties/referencedArtworkList.js
index 4f243493..278f063d 100644
--- a/src/data/composite/wiki-properties/referencedArtworkList.js
+++ b/src/data/composite/wiki-properties/referencedArtworkList.js
@@ -22,7 +22,7 @@ export default templateCompositeFrom({
     annotatedReferenceList({
       referenceType: input.value(['album', 'track']),
 
-      data: 'artworkData',
+      data: '_artworkData',
       find: '#find',
 
       thing: input.value('artwork'),
diff --git a/src/data/things/album.js b/src/data/things/album.js
index defb8a87..594046b9 100644
--- a/src/data/things/album.js
+++ b/src/data/things/album.js
@@ -155,7 +155,7 @@ export class Album extends Thing {
     // > Update & expose - Credits and contributors
 
     artistContribs: contributionList({
-      date: 'date',
+      date: '_date',
       artistProperty: input.value('albumArtistContributions'),
     }),
 
@@ -166,7 +166,7 @@ export class Album extends Thing {
         from: input.updateValue({validate: isContributionList}),
         thingProperty: input.thisProperty(),
         artistProperty: input.value('albumTrackArtistContributions'),
-        date: 'date',
+        date: '_date',
       }).outputs({
         '#resolvedContribs': '#trackArtistContribs',
       }),
@@ -177,7 +177,7 @@ export class Album extends Thing {
       }),
 
       withResolvedContribs({
-        from: 'artistContribs',
+        from: '_artistContribs',
         thingProperty: input.thisProperty(),
         artistProperty: input.value('albumTrackArtistContributions'),
         date: 'date',
@@ -209,13 +209,9 @@ export class Album extends Thing {
     // > Update & expose - Artworks
 
     coverArtworks: [
-      // This works, lol, because this array describes `expose.transform` for
-      // the coverArtworks property, and compositions generally access the
-      // update value, not what's exposed by property access out in the open.
-      // There's no recursion going on here.
       exitWithoutArtwork({
-        contribs: 'coverArtistContribs',
-        artworks: 'coverArtworks',
+        contribs: '_coverArtistContribs',
+        artworks: '_coverArtworks',
         value: input.value([]),
       }),
 
@@ -244,8 +240,8 @@ export class Album extends Thing {
 
     coverArtFileExtension: [
       exitWithoutArtwork({
-        contribs: 'coverArtistContribs',
-        artworks: 'coverArtworks',
+        contribs: '_coverArtistContribs',
+        artworks: '_coverArtworks',
       }),
 
       fileExtension('jpg'),
@@ -253,8 +249,8 @@ export class Album extends Thing {
 
     coverArtDimensions: [
       exitWithoutArtwork({
-        contribs: 'coverArtistContribs',
-        artworks: 'coverArtworks',
+        contribs: '_coverArtistContribs',
+        artworks: '_coverArtworks',
       }),
 
       dimensions(),
@@ -262,8 +258,8 @@ export class Album extends Thing {
 
     artTags: [
       exitWithoutArtwork({
-        contribs: 'coverArtistContribs',
-        artworks: 'coverArtworks',
+        contribs: '_coverArtistContribs',
+        artworks: '_coverArtworks',
         value: input.value([]),
       }),
 
@@ -275,8 +271,8 @@ export class Album extends Thing {
 
     referencedArtworks: [
       exitWithoutArtwork({
-        contribs: 'coverArtistContribs',
-        artworks: 'coverArtworks',
+        contribs: '_coverArtistContribs',
+        artworks: '_coverArtworks',
         value: input.value([]),
       }),
 
@@ -286,7 +282,7 @@ export class Album extends Thing {
     trackCoverArtistContribs: contributionList({
       // May be null, indicating cover art was added for tracks on the date
       // each track specifies, or else the track's own release date.
-      date: 'trackArtDate',
+      date: '_trackArtDate',
 
       // This is the "correct" value, but it gets overwritten - with the same
       // value - regardless.
@@ -301,7 +297,7 @@ export class Album extends Thing {
 
     wallpaperArtwork: [
       exitWithoutDependency({
-        dependency: 'wallpaperArtistContribs',
+        dependency: '_wallpaperArtistContribs',
         mode: input.value('empty'),
         value: input.value(null),
       }),
@@ -321,8 +317,8 @@ export class Album extends Thing {
 
     wallpaperFileExtension: [
       exitWithoutArtwork({
-        contribs: 'wallpaperArtistContribs',
-        artwork: 'wallpaperArtwork',
+        contribs: '_wallpaperArtistContribs',
+        artwork: '_wallpaperArtwork',
       }),
 
       fileExtension('jpg'),
@@ -330,8 +326,8 @@ export class Album extends Thing {
 
     wallpaperStyle: [
       exitWithoutArtwork({
-        contribs: 'wallpaperArtistContribs',
-        artwork: 'wallpaperArtwork',
+        contribs: '_wallpaperArtistContribs',
+        artwork: '_wallpaperArtwork',
       }),
 
       simpleString(),
@@ -340,8 +336,8 @@ export class Album extends Thing {
     wallpaperParts: [
       // kinda nonsensical or at least unlikely lol, but y'know
       exitWithoutArtwork({
-        contribs: 'wallpaperArtistContribs',
-        artwork: 'wallpaperArtwork',
+        contribs: '_wallpaperArtistContribs',
+        artwork: '_wallpaperArtwork',
         value: input.value([]),
       }),
 
@@ -350,7 +346,7 @@ export class Album extends Thing {
 
     bannerArtwork: [
       exitWithoutDependency({
-        dependency: 'bannerArtistContribs',
+        dependency: '_bannerArtistContribs',
         mode: input.value('empty'),
         value: input.value(null),
       }),
@@ -370,8 +366,8 @@ export class Album extends Thing {
 
     bannerFileExtension: [
       exitWithoutArtwork({
-        contribs: 'bannerArtistContribs',
-        artwork: 'bannerArtwork',
+        contribs: '_bannerArtistContribs',
+        artwork: '_bannerArtwork',
       }),
 
       fileExtension('jpg'),
@@ -379,8 +375,8 @@ export class Album extends Thing {
 
     bannerDimensions: [
       exitWithoutArtwork({
-        contribs: 'bannerArtistContribs',
-        artwork: 'bannerArtwork',
+        contribs: '_bannerArtistContribs',
+        artwork: '_bannerArtwork',
       }),
 
       dimensions(),
@@ -388,8 +384,8 @@ export class Album extends Thing {
 
     bannerStyle: [
       exitWithoutArtwork({
-        contribs: 'bannerArtistContribs',
-        artwork: 'bannerArtwork',
+        contribs: '_bannerArtistContribs',
+        artwork: '_bannerArtwork',
       }),
 
       simpleString(),
@@ -445,15 +441,15 @@ export class Album extends Thing {
 
     hasCoverArt: [
       withHasArtwork({
-        contribs: 'coverArtistContribs',
-        artworks: 'coverArtworks',
+        contribs: '_coverArtistContribs',
+        artworks: '_coverArtworks',
       }),
 
       exposeDependency({dependency: '#hasArtwork'}),
     ],
 
-    hasWallpaperArt: contribsPresent({contribs: 'wallpaperArtistContribs'}),
-    hasBannerArt: contribsPresent({contribs: 'bannerArtistContribs'}),
+    hasWallpaperArt: contribsPresent({contribs: '_wallpaperArtistContribs'}),
+    hasBannerArt: contribsPresent({contribs: '_bannerArtistContribs'}),
 
     tracks: [
       withTracks(),
@@ -1087,7 +1083,7 @@ export class TrackSection extends Thing {
       }),
 
       withDirectory({
-        directory: 'unqualifiedDirectory',
+        directory: '_unqualifiedDirectory',
       }).outputs({
         '#directory': '#unqualifiedDirectory',
       }),
diff --git a/src/data/things/content.js b/src/data/things/content.js
index 95836abd..21ee88f8 100644
--- a/src/data/things/content.js
+++ b/src/data/things/content.js
@@ -51,7 +51,7 @@ export class ContentEntry extends Thing {
 
     accessKind: [
       exitWithoutDependency({
-        dependency: 'accessDate',
+        dependency: '_accessDate',
       }),
 
       exposeUpdateValueOrContinue({
diff --git a/src/data/things/group.js b/src/data/things/group.js
index ac051343..076f0c8f 100644
--- a/src/data/things/group.js
+++ b/src/data/things/group.js
@@ -119,8 +119,8 @@ export class Group extends Thing {
       flags: {expose: true},
 
       expose: {
-        dependencies: ['this', 'reverse'],
-        compute: ({this: group, reverse}) =>
+        dependencies: ['this', '_reverse'],
+        compute: ({this: group, _reverse: reverse}) =>
           reverse.albumsWhoseGroupsInclude(group),
       },
     },
@@ -129,8 +129,8 @@ export class Group extends Thing {
       flags: {expose: true},
 
       expose: {
-        dependencies: ['this', 'reverse'],
-        compute: ({this: group, reverse}) =>
+        dependencies: ['this', '_reverse'],
+        compute: ({this: group, _reverse: reverse}) =>
           reverse.groupCategoriesWhichInclude(group, {unique: true})
             ?.color,
       },
@@ -140,8 +140,8 @@ export class Group extends Thing {
       flags: {expose: true},
 
       expose: {
-        dependencies: ['this', 'reverse'],
-        compute: ({this: group, reverse}) =>
+        dependencies: ['this', '_reverse'],
+        compute: ({this: group, _reverse: reverse}) =>
           reverse.groupCategoriesWhichInclude(group, {unique: true}) ??
           null,
       },
diff --git a/src/data/things/index.js b/src/data/things/index.js
index 1e9a5e52..09765fd2 100644
--- a/src/data/things/index.js
+++ b/src/data/things/index.js
@@ -58,6 +58,7 @@ const __dirname = path.dirname(
 function niceShowAggregate(error, ...opts) {
   showAggregate(error, {
     pathToFileURL: (f) => path.relative(__dirname, fileURLToPath(f)),
+    showClasses: false,
     ...opts,
   });
 }
@@ -152,6 +153,15 @@ function descriptorAggregateHelper({
   } catch (error) {
     niceShowAggregate(error);
     showFailedClasses(failedClasses);
+
+    /*
+    if (error.errors) {
+      for (const sub of error.errors) {
+        console.error(sub);
+      }
+    }
+    */
+
     return false;
   }
 }
diff --git a/src/data/things/track.js b/src/data/things/track.js
index 4a24a9e0..ff27e665 100644
--- a/src/data/things/track.js
+++ b/src/data/things/track.js
@@ -209,7 +209,7 @@ export class Track extends Thing {
       }),
 
       exposeDependencyOrContinue({
-        dependency: 'artistText',
+        dependency: '_artistText',
       }),
 
       withPropertyFromAlbum({
@@ -318,13 +318,13 @@ export class Track extends Thing {
       }),
 
       exitWithoutDependency({
-        dependency: 'lyrics',
+        dependency: '_lyrics',
         mode: input.value('empty'),
         value: input.value(false),
       }),
 
       withPropertyFromList({
-        list: 'lyrics',
+        list: '_lyrics',
         property: input.value('helpNeeded'),
       }),
 
diff --git a/src/data/things/wiki-info.js b/src/data/things/wiki-info.js
index 89248d11..73470b7d 100644
--- a/src/data/things/wiki-info.js
+++ b/src/data/things/wiki-info.js
@@ -92,7 +92,7 @@ export class WikiInfo extends Thing {
 
     enableSearch: [
       exitWithoutDependency({
-        dependency: 'searchDataAvailable',
+        dependency: '_searchDataAvailable',
         mode: input.value('falsy'),
         value: input.value(false),
       }),