Skip to content

CODAP-1537: document the five undocumented plugin API resources - #2710

Open
bfinzer wants to merge 2 commits into
CODAP-1547-plugin-api-doc-structurefrom
CODAP-1537-undocumented-resources
Open

bfinzer wants to merge 2 commits into
CODAP-1547-plugin-api-doc-structurefrom
CODAP-1537-undocumented-resources

Conversation

@bfinzer

@bfinzer bfinzer commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Stacked on #2709 (CODAP-1547). Base is CODAP-1547-plugin-api-doc-structure, not main — retarget to main once #2709 merges. Review that one first; the diff here is the four new pages.

Phase 2 of the plan. Five resources have handlers in v3 with no documentation anywhere, which is how plugin authors have been discovering them by reading source. dataDisplay was done in #2709 as the template exemplar; this adds the remaining four.

New pages

  • resources/adornment.md — covers adornment and adornmentList. The largest gap, and the one the plan identifies as what authors actually ask for.
  • resources/document.md
  • resources/interactive-api.md
  • resources/tour-elements.md

What writing them turned up

All read from source:

  • Only 8 of the 15 adornment types support create/update. The other seven can be read and hidden but cannot be turned on through the API at all — the graph component handler accepts no adornments property either. Now filed as CODAP-1551; see below.
  • An adornment exists in a graph's store only once shown. get on a type the user has never enabled returns Adornment not found.; one shown and later hidden returns isVisible: false. delete hides rather than removes.
  • adornmentList splits Count into Count and Percent sharing one id, and filters by the graph's current plot type.
  • Neither document action returns the document. get replies success immediately and delivers it as a newDocumentState notification — but only to plugins that set subscribeToDocuments on their interactiveFrame. Without that, the request looks like a silent no-op. update is bracketed by updateDocumentBegun/Ended on documentChangeNotice, sent only to the requesting plugin.
  • interactiveApi always returns success: true — availability is in values.available, so branching on success is wrong.

Stories filed from this work

  • CODAP-1551 — the seven adornment types plugins can't enable. Confirmed as a gap rather than a deliberate limitation. The story notes that four of the seven are univariate measures whose siblings already get create/update free from univariateMeasureAdornmentBaseHandler, so they should be cheap; the other three carry position or expression state and need design.
  • CODAP-1550 — dataDisplay's malformed error response, filed earlier from CODAP-1547: establish the Plugin API reference structure #2709.

Files touched from the parent branch

Three, which is why the diff is wider than four new files:

  • README.md — six resource rows now point into the repo.
  • conventions.md — records two rules this work surfaced: JavaScript examples must not assume a helper library, and a shared page's supported-actions table gains a column per resource.
  • resources/data-display.md — same helper-library fix, and cites CODAP-1550 now that the bug is filed.

Where I'd most value your judgment

Facts I can check myself, and did. The questions I can't answer alone:

  1. Does per-page duplication of the selector rules age well? The conventions say each page restates them rather than linking back, for self-containment and retrieval. That's a bet — it could read as bloat once there are 38 pages.
  2. Is the adornment per-type capability table the right emphasis, or just the thing I found most interesting? A plugin author might want the measure-data shapes first, which the page explicitly defers.

Fixes CODAP-1537

🤖 Generated with Claude Code

bfinzer and others added 2 commits September 25, 2026 12:45
Phase 2 of the plan. These resources have handlers in v3 but no
documentation anywhere, which is how plugin authors discovered them only
by reading source. dataDisplay was done in CODAP-1547 as the template
exemplar; this adds the remaining four.

New pages:

- resources/adornment.md — covers adornment and adornmentList. The
  largest gap and the one the plan says authors ask for.
- resources/document.md
- resources/interactive-api.md
- resources/tour-elements.md

Findings worth knowing, all read from source:

- Only 8 of the 15 adornment types support create/update. The other
  seven can be read and hidden but cannot be turned on through the API
  at all, since the graph component handler accepts no adornments
  property either. Documented as a per-type table, since this is the
  most likely surprise.
- An adornment exists in a graph's store only once shown, so get on a
  type the user has never enabled returns "Adornment not found.", while
  one shown and later hidden returns isVisible: false. delete hides
  rather than removes.
- adornmentList splits Count into Count and Percent sharing one id, and
  filters by the graph's current plot type.
- Neither document action returns the document. get replies success
  immediately and delivers the document as a newDocumentState
  notification, but only to plugins that set subscribeToDocuments on
  their interactiveFrame — without it the request looks like a silent
  no-op. update is bracketed by updateDocumentBegun/Ended on the
  documentChangeNotice resource, sent only to the requesting plugin.
- interactiveApi always returns success: true; availability is reported
  in values.available, so branching on success is wrong.

Also touches three files from CODAP-1547, the parent branch:

- README.md: six resource rows now point into the repo.
- conventions.md: records two rules this work surfaced — JavaScript
  examples must not assume a helper library, and a shared page's
  supported-actions table gains a column per resource.
- resources/data-display.md: replaces a codapInterface example for the
  same reason, and cites CODAP-1550 now that the bug is filed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The seven adornment types that cannot be enabled through the API turned
out to be a gap rather than a deliberate limitation, so the paragraph
naming them now points at the story that will close it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@bfinzer bfinzer added the v3 CODAP v3 label Sep 25, 2026
@bfinzer
bfinzer requested a review from kswenson September 25, 2026 19:54
@codecov

codecov Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.42%. Comparing base (51ea37a) to head (cb33d28).

Additional details and impacted files
@@                          Coverage Diff                          @@
##           CODAP-1547-plugin-api-doc-structure    #2710    +/-   ##
=====================================================================
  Coverage                                73.42%   73.42%            
=====================================================================
  Files                                      822      822            
  Lines                                    47657    47657            
  Branches                                 11717    12071   +354     
=====================================================================
  Hits                                     34994    34994            
+ Misses                                   12648    12628    -20     
- Partials                                    15       35    +20     
Flag Coverage Δ
cypress 38.11% <ø> (ø)
jest 63.43% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cypress

cypress Bot commented Sep 25, 2026

Copy link
Copy Markdown

codap-v3    Run #12312

Run Properties:  status check passed Passed #12312  •  git commit cb33d2892a: CODAP-1537: cite CODAP-1551 for the read-only adornment gap
Project codap-v3
Branch Review CODAP-1537-undocumented-resources
Run status status check passed Passed #12312
Run duration 03m 15s
Commit git commit cb33d2892a: CODAP-1537: cite CODAP-1551 for the read-only adornment gap
Committer William Finzer
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 0
Tests that did not run due to a developer annotating a test with .skip  Pending 0
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 4
View all changes introduced in this branch ↗︎

@kswenson kswenson left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review Summary

Changes: 7 files, +635 / -9 lines (docs only; stacked on #2709)

What it does

Phase 2 of the Plugin API documentation plan: documents the four remaining resources that had v3 handlers but no documentation anywhere — adornment/adornmentList, document, interactiveApi and tourElements — using the template established in #2709. It also points the index at the new pages, adds two rules to the conventions (no helper-library assumptions in JavaScript examples; per-resource columns on a shared page's actions table), and updates data-display.md accordingly.

The approach

One page per resource following the #2709 template, with the mechanical tables inside generated-block markers and the behavioral findings in prose around them. The pages lead with whatever is most likely to trip a plugin author up: that adornments exist only once shown and that seven types can't be created; that neither document action returns the document; that interactiveApi always reports success: true. The switch from codapInterface.sendRequest to a neutral sendRequest keeps the examples honest about what the reference covers.

Assessment

The research here is careful, and most of what these pages say checks out against the source — including the parts most likely to be wrong:

  • Adornment capability table — exactly right. 15 types register handlers; the 8 with create/update and the 3 with their own delete (Count, Movable Value, Plotted Value) match the handlers, and the other 12 fall back to hideAdornment.
  • Percent → Count alias and the automatic space-free aliases (adornment-handler.ts:25-31); adornmentList's Count/Percent split sharing one id (resource-parser.ts:175-200); all error strings match en-US.json5.
  • document: get notifies every subscribeToDocuments web view, including non-requesters; updateDocumentBegun/Ended go only to the requesting tile (broadcastMessage's targetTileId, document-content.ts:134-155); both actions return success before doing any work. The undo/redo gap matches what CODAP-1354 describes.
  • interactiveApi: presence-not-truthiness URL check, both notAvailableReason strings, and success: true in every case — all verbatim.
  • tourElements: the flattening and the 7 / 12 / 1 namespace counts are right.

Two things fall short. The tourElements page should wait for the pending tour work (issue 1). And several carry-overs from the #2709 review now apply to more pages: the Jira-ID pattern has grown (the new text in data-display.md cites CODAP-1550, adornment.md cites CODAP-1551, and document.md cites CODAP-1354), and the adornment.md page — correctly — documents string ids, which the index still says can't happen.

On your two questions:

  1. Per-page duplication. At this scale it's cheap: on these pages the restated rule is one or two sentences ("not scoped to a data context…"). The real risk isn't bloat but drift, once 38 hand-maintained copies start to diverge. I'd keep the rule and make the restated text a generated block too (a scope block, say), so the duplication is owned by the generator rather than by authors — which is the bargain the conventions already make for the actions and selectors tables.
  2. Adornment emphasis. Leading with the capability table is right: it's the thing a plugin author can't discover without failing. But the measure-data shapes are what they'll use every day, and part of that is cheaper to document than the page suggests: every type built on univariateMeasureAdornmentBaseHandler (Mean, Median, Standard Deviation) returns the same shape, data: [{ <measureName>: value, categories? }]. Documenting that pattern plus the Box Plot exception would cover most real use without cataloging every type.

Issues

  1. major — Hold tourElements out of this PR until the tour work lands (resources/tour-elements.md). Three approved tour PRs (#2519, #2529, #2532) are merged to the cisco-tours branch but held back from main until after the V3 release. Between them they change registry selectors, replace the driver.js engine (removing the overlay options from highlight and tours), and add a uiNotificationMonitor resource. Documenting the current behavior in a public reference would commit us to a surface we already plan to change, before we've had a chance to exercise the new one. I'd drop the page from this PR and write it once that branch is merged and we've used it.

    Separately, the page's main example doesn't work as written: a plugin runs in its own iframe, so document.querySelector(step.selector) searches the plugin's document, not CODAP's. The registry is meant to be used by passing tourKey to CODAP in a highlight request, which CODAP resolves itself (plugin-tour-api.md) — the page never mentions that. Worth getting right when the page returns.

    For the index: tourElements has no wiki documentation either, so rather than pointing its row back to "wiki", mark it as not yet documented.

  2. minor — update document never sends updateDocumentEnded if the import fails — fix rather than document (resources/document.md, "update" and Errors). asyncUpdate is fire-and-forget with no catch (document-handler.ts:308); any throw during importV2Document, serialization or id remapping (including two explicit throws, :219 and :229) rejects the promise before updateDocumentEnded is sent. The page tells plugins to treat updateDocumentEnded as the completion signal, so a plugin that follows that advice waits forever on a malformed document. Documenting that would invite plugins to code around it with timeouts; the better fix is small — send updateDocumentEnded from a finally (ideally with a success flag), so the signal always arrives and a plugin can tell success from failure. Suggest filing it as a bug, as with dataDisplay's error response, and describing the intended behavior here rather than the hang.

  3. minor — update document preserves the state of subscribed plugins (resources/document.md). Before applying the snapshot, CODAP replaces the incoming state of every web view with subscribeToDocuments: true with that tile's current state (document-handler.ts:233-246) — the mechanism Story Builder relies on so it doesn't overwrite itself. This matters for the page's own round-trip example: the plugin subscribes and then restores savedState, and its own saved state inside that document is silently ignored. Worth a sentence, since that's exactly the plugin most likely to use this resource.

  4. minor — The id-matching paragraph overstates what's preserved (resources/document.md, "update"). "CODAP matches incoming models to existing ones by … data set ids and tile ids — so that applying a snapshot updates existing instances" isn't quite what happens: shared-model entries are remapped by data set id, but content-model ids are deliberately not matched, and their child models are recreated (the long comment at document-handler.ts:138-155). The paragraph also contradicts its own opening ("destroys and rebuilds"). The practical advice — re-read ids afterward — is right; I'd keep that and drop the mechanism.

  5. minor — Carry-overs from the #2709 review, now on more pages. These are the same issues raised on #2709, extended by this PR's new pages; whatever is decided there should be applied here too:

    • Jira IDs in external-facing pages (#2709 issue 3): this PR adds more. The new text in data-display.md cites CODAP-1550, adornment.md cites CODAP-1551, and document.md cites CODAP-1354.
    • "IDs are numbers" (#2709 issue 6): adornment.md rightly types id as String with "ADRN123" examples, which directly contradicts the index. Resolving it in #2709 fixes both.
    • Prose inside generated blocks (#2709 issue 2): adornment.md's actions table has cells like "✓ (some types)" and "✓ (all types)" that no extractor would produce.
  6. minor — adornment.md uses the values generated block for the wrong table. The per-type capability table under "Adornment types" is wrapped in GENERATED: values, while the real ## Values section has no markers. When the generator arrives it will write a values table where the capability table is. Suggest a new block name (e.g. adornment-types) for the capability table, and the values markers around the property table in ## Values.

  7. minor — Gaps in the adornment error and values tables (resources/adornment.md):

    • delete on a type that was never shown returns Adornment not found. (adornment-handler.ts:71), but the table lists that error only for get and update. The intro's "delete works for every type" reads as if it always succeeds.
    • Missing from the errors table: The current plot type does not support Percent., returned by Count's create (count-adornment-handler.ts:39).
    • Box Plot's get also returns top-level showICI and showOutliers (box-plot-adornment-handler.ts:36), which the Values table doesn't cover. That's the kind of type-specific extra the page could flag, even while deferring the full data catalog.

Suggestions (author's discretion)

Not blocking — take or leave these.

  1. nit — adornmentList isn't filtered for Count. The page says the list is filtered by the current plot type, but the Count/Percent branch skips that check (resource-parser.ts:178-192), so they're always listed.

  2. nit — The pages add sections the template doesn't list — "Adornment types", "get — subscribing…", "update — replacing…", "See also". They all earn their place; conventions.md should say where such sections go, since it currently fixes the section order.

  3. nit — Error strings are shown with %@ placeholders in adornment.md (Unsupported component type %@, The %@1 adornment…), while the surrounding prose and data-display.md show what a plugin actually receives. Suggest <type>-style placeholders to match.

  4. nit — interactiveApi has no timeout. get awaits the CFM's initInteractivePromise with no timeout (interactive-api-handler.ts:36), so if the host never sends initInteractive the request never resolves. "Can arrive noticeably later" undersells that; worth "may not arrive at all if the host never initializes".

  5. nit — Embedded-server mode behaves differently for document. get's notification is sent only to web view tiles, never to an embedded-mode parent, and an update from the parent (no interactiveFrame, so an empty target id) broadcasts updateDocumentBegun/Ended to every tile and the parent. Probably fine to defer to the embedded-mode guide, but "not to an embedded-mode parent" is true only when a plugin tile made the request.

Comments and docs

  • adornment.md: "which is the single most common surprise with this resource" is an unverifiable claim; "a common surprise", or dropping the clause, would be safer.
  • document.md: "This is the most important thing to know about this resource, and the rest of this page is mostly about it." The bolded sentence before it already makes the point.

This branch was previously deployed

1 inactive deployment
development — cb33d289 Deployed Sep 25, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v3 CODAP v3

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants