[finding] os explain's 11 other catalog entries are hand-maintained against no schema — the flow entry's sample was unparseable and nothing said so #14811

Description

@os-trump

Found while implementing #14782 (the os explain flow sample); out of scope there, filed
unassigned for triage. Suggested domain: domain:cli.

The observation

packages/cli/src/commands/explain.ts holds a SCHEMAS catalog of 12 entries —
object, fields, field, view, flow, agent, app, query, dashboard,
action, workflow, trigger. Each carries a required list, an optional list and an
example string, and every one of them is hand-maintained: nothing derives them from
the schema they describe, and until now nothing checked them against it.

The existing test block in packages/cli/test/commands.test.ts states the hazard in its
own words, and its comment is worth quoting because it was written after this already
happened twice:

The token set is asserted EXACTLY, and that exactness is the point: this catalog is
hand-maintained and does NOT derive from the spec enum, so a spec-side enum change that
stops here is invisible to any review that only reads packages/spec.

That guard covers exactly one field of one entry (object.ownership, from #3244, widened
again at #5678).

Why this is worth a card rather than a note

#14782 measured what an unguarded entry drifts into. The flow entry's example did not
merely carry a wrong token — it did not parse as a Flow at all:

ISSUE [nodes] Invalid input: expected array, received undefined
ISSUE [edges] Invalid input: expected array, received undefined
ISSUE [] Unrecognized key(s) on this flow: `trigger`, `steps`.
Did you mean `trigger` -> `type`, `steps` -> `nodes`?

Its required / optional lists named two keys (steps, trigger) that are strict-object
aliases, i.e. loud parse errors, and omitted two that are required (nodes, edges).
Meanwhile os generate flow, in the same package, was scaffolding the correct shape all
along — so the drift was not for want of the truth being known locally.

PR #14809 pins the flow entry by parsing its example against the real FlowSchema. That
technique generalises, and it is the only kind of guard that cannot drift alongside the
catalog it checks, because it re-derives the truth from the spec on every run. It was
deliberately not generalised in that PR: the other entries are outside that card's
face, and turning the guard on all 12 at once would fail on entries nobody has mandate to
rewrite in a p3 documentation fix.

What is NOT claimed

I did not audit the other 11 entries. This card records that they are unguarded and
that one of the twelve was measured badly wrong — not that any specific other entry is
wrong. The first step for whoever takes this is cheap: extend the parse-the-example
technique entry by entry and see which ones fail.

Suggested shape

  1. For each catalog entry with a resolvable schema in @objectstack/spec, parse its
    example against that schema in commands.test.ts.
  2. Where an entry has no single schema to parse against (fields is a fragment, query may
    be one), say so explicitly in the test rather than skipping silently.
  3. Fix whatever the parse turns up, one entry at a time.

Triage may well decide the audit is worth more than the generalised guard, or split them.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
       blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
      }
      } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
      })();
      (function(){
      try {
      var __m = "github.com";
      var __re = new RegExp('^' + "github\\.com" + '
      
      Skip to content

      [finding] os explain's 11 other catalog entries are hand-maintained against no schema — the flow entry's sample was unparseable and nothing said so #14811

      Description

      @os-trump

      Found while implementing #14782 (the os explain flow sample); out of scope there, filed
      unassigned for triage. Suggested domain: domain:cli.

      The observation

      packages/cli/src/commands/explain.ts holds a SCHEMAS catalog of 12 entries —
      object, fields, field, view, flow, agent, app, query, dashboard,
      action, workflow, trigger. Each carries a required list, an optional list and an
      example string, and every one of them is hand-maintained: nothing derives them from
      the schema they describe, and until now nothing checked them against it.

      The existing test block in packages/cli/test/commands.test.ts states the hazard in its
      own words, and its comment is worth quoting because it was written after this already
      happened twice:

      The token set is asserted EXACTLY, and that exactness is the point: this catalog is
      hand-maintained and does NOT derive from the spec enum, so a spec-side enum change that
      stops here is invisible to any review that only reads packages/spec.

      That guard covers exactly one field of one entry (object.ownership, from #3244, widened
      again at #5678).

      Why this is worth a card rather than a note

      #14782 measured what an unguarded entry drifts into. The flow entry's example did not
      merely carry a wrong token — it did not parse as a Flow at all:

      ISSUE [nodes] Invalid input: expected array, received undefined
      ISSUE [edges] Invalid input: expected array, received undefined
      ISSUE [] Unrecognized key(s) on this flow: `trigger`, `steps`.
      Did you mean `trigger` -> `type`, `steps` -> `nodes`?
      

      Its required / optional lists named two keys (steps, trigger) that are strict-object
      aliases, i.e. loud parse errors, and omitted two that are required (nodes, edges).
      Meanwhile os generate flow, in the same package, was scaffolding the correct shape all
      along — so the drift was not for want of the truth being known locally.

      PR #14809 pins the flow entry by parsing its example against the real FlowSchema. That
      technique generalises, and it is the only kind of guard that cannot drift alongside the
      catalog it checks, because it re-derives the truth from the spec on every run. It was
      deliberately not generalised in that PR: the other entries are outside that card's
      face, and turning the guard on all 12 at once would fail on entries nobody has mandate to
      rewrite in a p3 documentation fix.

      What is NOT claimed

      I did not audit the other 11 entries. This card records that they are unguarded and
      that one of the twelve was measured badly wrong — not that any specific other entry is
      wrong. The first step for whoever takes this is cheap: extend the parse-the-example
      technique entry by entry and see which ones fail.

      Suggested shape

      1. For each catalog entry with a resolvable schema in @objectstack/spec, parse its
        example against that schema in commands.test.ts.
      2. Where an entry has no single schema to parse against (fields is a fragment, query may
        be one), say so explicitly in the test rather than skipping silently.
      3. Fix whatever the parse turns up, one entry at a time.

      Triage may well decide the audit is worth more than the generalised guard, or split them.

      Activity

      Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

      Metadata

      Metadata

      Assignees

      No one assigned

        Type

        No type

        Projects

        No projects

          Milestone

          No milestone

          Relationships

          None yet

          Development

          No branches or pull requests

          Issue actions

          , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
          Skip to content

          [finding] os explain's 11 other catalog entries are hand-maintained against no schema — the flow entry's sample was unparseable and nothing said so #14811

          Description

          @os-trump

          Found while implementing #14782 (the os explain flow sample); out of scope there, filed
          unassigned for triage. Suggested domain: domain:cli.

          The observation

          packages/cli/src/commands/explain.ts holds a SCHEMAS catalog of 12 entries —
          object, fields, field, view, flow, agent, app, query, dashboard,
          action, workflow, trigger. Each carries a required list, an optional list and an
          example string, and every one of them is hand-maintained: nothing derives them from
          the schema they describe, and until now nothing checked them against it.

          The existing test block in packages/cli/test/commands.test.ts states the hazard in its
          own words, and its comment is worth quoting because it was written after this already
          happened twice:

          The token set is asserted EXACTLY, and that exactness is the point: this catalog is
          hand-maintained and does NOT derive from the spec enum, so a spec-side enum change that
          stops here is invisible to any review that only reads packages/spec.

          That guard covers exactly one field of one entry (object.ownership, from #3244, widened
          again at #5678).

          Why this is worth a card rather than a note

          #14782 measured what an unguarded entry drifts into. The flow entry's example did not
          merely carry a wrong token — it did not parse as a Flow at all:

          ISSUE [nodes] Invalid input: expected array, received undefined
          ISSUE [edges] Invalid input: expected array, received undefined
          ISSUE [] Unrecognized key(s) on this flow: `trigger`, `steps`.
          Did you mean `trigger` -> `type`, `steps` -> `nodes`?
          

          Its required / optional lists named two keys (steps, trigger) that are strict-object
          aliases, i.e. loud parse errors, and omitted two that are required (nodes, edges).
          Meanwhile os generate flow, in the same package, was scaffolding the correct shape all
          along — so the drift was not for want of the truth being known locally.

          PR #14809 pins the flow entry by parsing its example against the real FlowSchema. That
          technique generalises, and it is the only kind of guard that cannot drift alongside the
          catalog it checks, because it re-derives the truth from the spec on every run. It was
          deliberately not generalised in that PR: the other entries are outside that card's
          face, and turning the guard on all 12 at once would fail on entries nobody has mandate to
          rewrite in a p3 documentation fix.

          What is NOT claimed

          I did not audit the other 11 entries. This card records that they are unguarded and
          that one of the twelve was measured badly wrong — not that any specific other entry is
          wrong. The first step for whoever takes this is cheap: extend the parse-the-example
          technique entry by entry and see which ones fail.

          Suggested shape

          1. For each catalog entry with a resolvable schema in @objectstack/spec, parse its
            example against that schema in commands.test.ts.
          2. Where an entry has no single schema to parse against (fields is a fragment, query may
            be one), say so explicitly in the test rather than skipping silently.
          3. Fix whatever the parse turns up, one entry at a time.

          Triage may well decide the audit is worth more than the generalised guard, or split them.

          Activity

          Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

          Metadata

          Metadata

          Assignees

          No one assigned

            Type

            No type

            Projects

            No projects

              Milestone

              No milestone

              Relationships

              None yet

              Development

              No branches or pull requests

              Issue actions

              , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
              Skip to content

              [finding] os explain's 11 other catalog entries are hand-maintained against no schema — the flow entry's sample was unparseable and nothing said so #14811

              Description

              @os-trump

              Found while implementing #14782 (the os explain flow sample); out of scope there, filed
              unassigned for triage. Suggested domain: domain:cli.

              The observation

              packages/cli/src/commands/explain.ts holds a SCHEMAS catalog of 12 entries —
              object, fields, field, view, flow, agent, app, query, dashboard,
              action, workflow, trigger. Each carries a required list, an optional list and an
              example string, and every one of them is hand-maintained: nothing derives them from
              the schema they describe, and until now nothing checked them against it.

              The existing test block in packages/cli/test/commands.test.ts states the hazard in its
              own words, and its comment is worth quoting because it was written after this already
              happened twice:

              The token set is asserted EXACTLY, and that exactness is the point: this catalog is
              hand-maintained and does NOT derive from the spec enum, so a spec-side enum change that
              stops here is invisible to any review that only reads packages/spec.

              That guard covers exactly one field of one entry (object.ownership, from #3244, widened
              again at #5678).

              Why this is worth a card rather than a note

              #14782 measured what an unguarded entry drifts into. The flow entry's example did not
              merely carry a wrong token — it did not parse as a Flow at all:

              ISSUE [nodes] Invalid input: expected array, received undefined
              ISSUE [edges] Invalid input: expected array, received undefined
              ISSUE [] Unrecognized key(s) on this flow: `trigger`, `steps`.
              Did you mean `trigger` -> `type`, `steps` -> `nodes`?
              

              Its required / optional lists named two keys (steps, trigger) that are strict-object
              aliases, i.e. loud parse errors, and omitted two that are required (nodes, edges).
              Meanwhile os generate flow, in the same package, was scaffolding the correct shape all
              along — so the drift was not for want of the truth being known locally.

              PR #14809 pins the flow entry by parsing its example against the real FlowSchema. That
              technique generalises, and it is the only kind of guard that cannot drift alongside the
              catalog it checks, because it re-derives the truth from the spec on every run. It was
              deliberately not generalised in that PR: the other entries are outside that card's
              face, and turning the guard on all 12 at once would fail on entries nobody has mandate to
              rewrite in a p3 documentation fix.

              What is NOT claimed

              I did not audit the other 11 entries. This card records that they are unguarded and
              that one of the twelve was measured badly wrong — not that any specific other entry is
              wrong. The first step for whoever takes this is cheap: extend the parse-the-example
              technique entry by entry and see which ones fail.

              Suggested shape

              1. For each catalog entry with a resolvable schema in @objectstack/spec, parse its
                example against that schema in commands.test.ts.
              2. Where an entry has no single schema to parse against (fields is a fragment, query may
                be one), say so explicitly in the test rather than skipping silently.
              3. Fix whatever the parse turns up, one entry at a time.

              Triage may well decide the audit is worth more than the generalised guard, or split them.

              Activity

              Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

              Metadata

              Metadata

              Assignees

              No one assigned

                Type

                No type

                Projects

                No projects

                  Milestone

                  No milestone

                  Relationships

                  None yet

                  Development

                  No branches or pull requests

                  Issue actions

                  , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
                  Skip to content

                  [finding] os explain's 11 other catalog entries are hand-maintained against no schema — the flow entry's sample was unparseable and nothing said so #14811

                  Description

                  @os-trump

                  Found while implementing #14782 (the os explain flow sample); out of scope there, filed
                  unassigned for triage. Suggested domain: domain:cli.

                  The observation

                  packages/cli/src/commands/explain.ts holds a SCHEMAS catalog of 12 entries —
                  object, fields, field, view, flow, agent, app, query, dashboard,
                  action, workflow, trigger. Each carries a required list, an optional list and an
                  example string, and every one of them is hand-maintained: nothing derives them from
                  the schema they describe, and until now nothing checked them against it.

                  The existing test block in packages/cli/test/commands.test.ts states the hazard in its
                  own words, and its comment is worth quoting because it was written after this already
                  happened twice:

                  The token set is asserted EXACTLY, and that exactness is the point: this catalog is
                  hand-maintained and does NOT derive from the spec enum, so a spec-side enum change that
                  stops here is invisible to any review that only reads packages/spec.

                  That guard covers exactly one field of one entry (object.ownership, from #3244, widened
                  again at #5678).

                  Why this is worth a card rather than a note

                  #14782 measured what an unguarded entry drifts into. The flow entry's example did not
                  merely carry a wrong token — it did not parse as a Flow at all:

                  ISSUE [nodes] Invalid input: expected array, received undefined
                  ISSUE [edges] Invalid input: expected array, received undefined
                  ISSUE [] Unrecognized key(s) on this flow: `trigger`, `steps`.
                  Did you mean `trigger` -> `type`, `steps` -> `nodes`?
                  

                  Its required / optional lists named two keys (steps, trigger) that are strict-object
                  aliases, i.e. loud parse errors, and omitted two that are required (nodes, edges).
                  Meanwhile os generate flow, in the same package, was scaffolding the correct shape all
                  along — so the drift was not for want of the truth being known locally.

                  PR #14809 pins the flow entry by parsing its example against the real FlowSchema. That
                  technique generalises, and it is the only kind of guard that cannot drift alongside the
                  catalog it checks, because it re-derives the truth from the spec on every run. It was
                  deliberately not generalised in that PR: the other entries are outside that card's
                  face, and turning the guard on all 12 at once would fail on entries nobody has mandate to
                  rewrite in a p3 documentation fix.

                  What is NOT claimed

                  I did not audit the other 11 entries. This card records that they are unguarded and
                  that one of the twelve was measured badly wrong — not that any specific other entry is
                  wrong. The first step for whoever takes this is cheap: extend the parse-the-example
                  technique entry by entry and see which ones fail.

                  Suggested shape

                  1. For each catalog entry with a resolvable schema in @objectstack/spec, parse its
                    example against that schema in commands.test.ts.
                  2. Where an entry has no single schema to parse against (fields is a fragment, query may
                    be one), say so explicitly in the test rather than skipping silently.
                  3. Fix whatever the parse turns up, one entry at a time.

                  Triage may well decide the audit is worth more than the generalised guard, or split them.

                  Activity

                  Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

                  Metadata

                  Metadata

                  Assignees

                  No one assigned

                    Type

                    No type

                    Projects

                    No projects

                      Milestone

                      No milestone

                      Relationships

                      None yet

                      Development

                      No branches or pull requests

                      Issue actions

                      , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
                      Skip to content

                      [finding] os explain's 11 other catalog entries are hand-maintained against no schema — the flow entry's sample was unparseable and nothing said so #14811

                      Description

                      @os-trump

                      Found while implementing #14782 (the os explain flow sample); out of scope there, filed
                      unassigned for triage. Suggested domain: domain:cli.

                      The observation

                      packages/cli/src/commands/explain.ts holds a SCHEMAS catalog of 12 entries —
                      object, fields, field, view, flow, agent, app, query, dashboard,
                      action, workflow, trigger. Each carries a required list, an optional list and an
                      example string, and every one of them is hand-maintained: nothing derives them from
                      the schema they describe, and until now nothing checked them against it.

                      The existing test block in packages/cli/test/commands.test.ts states the hazard in its
                      own words, and its comment is worth quoting because it was written after this already
                      happened twice:

                      The token set is asserted EXACTLY, and that exactness is the point: this catalog is
                      hand-maintained and does NOT derive from the spec enum, so a spec-side enum change that
                      stops here is invisible to any review that only reads packages/spec.

                      That guard covers exactly one field of one entry (object.ownership, from #3244, widened
                      again at #5678).

                      Why this is worth a card rather than a note

                      #14782 measured what an unguarded entry drifts into. The flow entry's example did not
                      merely carry a wrong token — it did not parse as a Flow at all:

                      ISSUE [nodes] Invalid input: expected array, received undefined
                      ISSUE [edges] Invalid input: expected array, received undefined
                      ISSUE [] Unrecognized key(s) on this flow: `trigger`, `steps`.
                      Did you mean `trigger` -> `type`, `steps` -> `nodes`?
                      

                      Its required / optional lists named two keys (steps, trigger) that are strict-object
                      aliases, i.e. loud parse errors, and omitted two that are required (nodes, edges).
                      Meanwhile os generate flow, in the same package, was scaffolding the correct shape all
                      along — so the drift was not for want of the truth being known locally.

                      PR #14809 pins the flow entry by parsing its example against the real FlowSchema. That
                      technique generalises, and it is the only kind of guard that cannot drift alongside the
                      catalog it checks, because it re-derives the truth from the spec on every run. It was
                      deliberately not generalised in that PR: the other entries are outside that card's
                      face, and turning the guard on all 12 at once would fail on entries nobody has mandate to
                      rewrite in a p3 documentation fix.

                      What is NOT claimed

                      I did not audit the other 11 entries. This card records that they are unguarded and
                      that one of the twelve was measured badly wrong — not that any specific other entry is
                      wrong. The first step for whoever takes this is cheap: extend the parse-the-example
                      technique entry by entry and see which ones fail.

                      Suggested shape

                      1. For each catalog entry with a resolvable schema in @objectstack/spec, parse its
                        example against that schema in commands.test.ts.
                      2. Where an entry has no single schema to parse against (fields is a fragment, query may
                        be one), say so explicitly in the test rather than skipping silently.
                      3. Fix whatever the parse turns up, one entry at a time.

                      Triage may well decide the audit is worth more than the generalised guard, or split them.

                      Activity

                      Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

                      Metadata

                      Metadata

                      Assignees

                      No one assigned

                        Type

                        No type

                        Projects

                        No projects

                          Milestone

                          No milestone

                          Relationships

                          None yet

                          Development

                          No branches or pull requests

                          Issue actions

                          , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
                          Skip to content

                          [finding] os explain's 11 other catalog entries are hand-maintained against no schema — the flow entry's sample was unparseable and nothing said so #14811

                          Description

                          @os-trump

                          Found while implementing #14782 (the os explain flow sample); out of scope there, filed
                          unassigned for triage. Suggested domain: domain:cli.

                          The observation

                          packages/cli/src/commands/explain.ts holds a SCHEMAS catalog of 12 entries —
                          object, fields, field, view, flow, agent, app, query, dashboard,
                          action, workflow, trigger. Each carries a required list, an optional list and an
                          example string, and every one of them is hand-maintained: nothing derives them from
                          the schema they describe, and until now nothing checked them against it.

                          The existing test block in packages/cli/test/commands.test.ts states the hazard in its
                          own words, and its comment is worth quoting because it was written after this already
                          happened twice:

                          The token set is asserted EXACTLY, and that exactness is the point: this catalog is
                          hand-maintained and does NOT derive from the spec enum, so a spec-side enum change that
                          stops here is invisible to any review that only reads packages/spec.

                          That guard covers exactly one field of one entry (object.ownership, from #3244, widened
                          again at #5678).

                          Why this is worth a card rather than a note

                          #14782 measured what an unguarded entry drifts into. The flow entry's example did not
                          merely carry a wrong token — it did not parse as a Flow at all:

                          ISSUE [nodes] Invalid input: expected array, received undefined
                          ISSUE [edges] Invalid input: expected array, received undefined
                          ISSUE [] Unrecognized key(s) on this flow: `trigger`, `steps`.
                          Did you mean `trigger` -> `type`, `steps` -> `nodes`?
                          

                          Its required / optional lists named two keys (steps, trigger) that are strict-object
                          aliases, i.e. loud parse errors, and omitted two that are required (nodes, edges).
                          Meanwhile os generate flow, in the same package, was scaffolding the correct shape all
                          along — so the drift was not for want of the truth being known locally.

                          PR #14809 pins the flow entry by parsing its example against the real FlowSchema. That
                          technique generalises, and it is the only kind of guard that cannot drift alongside the
                          catalog it checks, because it re-derives the truth from the spec on every run. It was
                          deliberately not generalised in that PR: the other entries are outside that card's
                          face, and turning the guard on all 12 at once would fail on entries nobody has mandate to
                          rewrite in a p3 documentation fix.

                          What is NOT claimed

                          I did not audit the other 11 entries. This card records that they are unguarded and
                          that one of the twelve was measured badly wrong — not that any specific other entry is
                          wrong. The first step for whoever takes this is cheap: extend the parse-the-example
                          technique entry by entry and see which ones fail.

                          Suggested shape

                          1. For each catalog entry with a resolvable schema in @objectstack/spec, parse its
                            example against that schema in commands.test.ts.
                          2. Where an entry has no single schema to parse against (fields is a fragment, query may
                            be one), say so explicitly in the test rather than skipping silently.
                          3. Fix whatever the parse turns up, one entry at a time.

                          Triage may well decide the audit is worth more than the generalised guard, or split them.

                          Activity

                          Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

                          Metadata

                          Metadata

                          Assignees

                          No one assigned

                            Type

                            No type

                            Projects

                            No projects

                              Milestone

                              No milestone

                              Relationships

                              None yet

                              Development

                              No branches or pull requests

                              Issue actions

                              , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
                              Skip to content

                              [finding] os explain's 11 other catalog entries are hand-maintained against no schema — the flow entry's sample was unparseable and nothing said so #14811

                              Description

                              @os-trump

                              Found while implementing #14782 (the os explain flow sample); out of scope there, filed
                              unassigned for triage. Suggested domain: domain:cli.

                              The observation

                              packages/cli/src/commands/explain.ts holds a SCHEMAS catalog of 12 entries —
                              object, fields, field, view, flow, agent, app, query, dashboard,
                              action, workflow, trigger. Each carries a required list, an optional list and an
                              example string, and every one of them is hand-maintained: nothing derives them from
                              the schema they describe, and until now nothing checked them against it.

                              The existing test block in packages/cli/test/commands.test.ts states the hazard in its
                              own words, and its comment is worth quoting because it was written after this already
                              happened twice:

                              The token set is asserted EXACTLY, and that exactness is the point: this catalog is
                              hand-maintained and does NOT derive from the spec enum, so a spec-side enum change that
                              stops here is invisible to any review that only reads packages/spec.

                              That guard covers exactly one field of one entry (object.ownership, from #3244, widened
                              again at #5678).

                              Why this is worth a card rather than a note

                              #14782 measured what an unguarded entry drifts into. The flow entry's example did not
                              merely carry a wrong token — it did not parse as a Flow at all:

                              ISSUE [nodes] Invalid input: expected array, received undefined
                              ISSUE [edges] Invalid input: expected array, received undefined
                              ISSUE [] Unrecognized key(s) on this flow: `trigger`, `steps`.
                              Did you mean `trigger` -> `type`, `steps` -> `nodes`?
                              

                              Its required / optional lists named two keys (steps, trigger) that are strict-object
                              aliases, i.e. loud parse errors, and omitted two that are required (nodes, edges).
                              Meanwhile os generate flow, in the same package, was scaffolding the correct shape all
                              along — so the drift was not for want of the truth being known locally.

                              PR #14809 pins the flow entry by parsing its example against the real FlowSchema. That
                              technique generalises, and it is the only kind of guard that cannot drift alongside the
                              catalog it checks, because it re-derives the truth from the spec on every run. It was
                              deliberately not generalised in that PR: the other entries are outside that card's
                              face, and turning the guard on all 12 at once would fail on entries nobody has mandate to
                              rewrite in a p3 documentation fix.

                              What is NOT claimed

                              I did not audit the other 11 entries. This card records that they are unguarded and
                              that one of the twelve was measured badly wrong — not that any specific other entry is
                              wrong. The first step for whoever takes this is cheap: extend the parse-the-example
                              technique entry by entry and see which ones fail.

                              Suggested shape

                              1. For each catalog entry with a resolvable schema in @objectstack/spec, parse its
                                example against that schema in commands.test.ts.
                              2. Where an entry has no single schema to parse against (fields is a fragment, query may
                                be one), say so explicitly in the test rather than skipping silently.
                              3. Fix whatever the parse turns up, one entry at a time.

                              Triage may well decide the audit is worth more than the generalised guard, or split them.

                              Activity

                              Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

                              Metadata

                              Metadata

                              Assignees

                              No one assigned

                                Type

                                No type

                                Projects

                                No projects

                                  Milestone

                                  No milestone

                                  Relationships

                                  None yet

                                  Development

                                  No branches or pull requests

                                  Issue actions