Sources
Docs: Perceptions, Plots, Policies, and Preferences. Web App: Select a Pane and open Programming, Perception, Palette, Policies, Plots, or Panes in its editor drawer.Structure
A Pane carries its Perception and its Policies, and it owns a Palette and its Plots. Adding a Pane opens a dialog that asks for its name, one sentence on what it is for, and an icon; every Pane needs a description, shown in the band under its header. The Perception describes its native value and references to other Panes. Its React source renders the selected value; SQL Plots read or calculate data. Referencing another Pane does not transfer ownership or copy its saved settings. A Pane that owns a Plot declares its primitive in scalar-lib types, withpreferences in its Perception. It owns one Plot, which returns rows of that
type. A second computation gets a Pane of its own, and the Plots that need it read
it by name. A Pane that owns no Plot, such as a settings or layout Pane, needs no
such type. A save, Prepare or Publish that gives a Pane a Plot while its
primitive is null, or a second Plot, is refused with PA-AU-049, naming the
Pane and its Plots. A Pane the published Version already holds that way is
history: its Warnings & Errors show it as info, which never blocks, and every
other change still saves and publishes.
A Pane reads at most 10,000 rows from a Plot. Read only what it draws: a chart
or a total reads rows its Plot’s SQL has already aggregated, heavy work is read
from a stored output, and a table a person browses reads a page at a time. See
Large results.
The editor drawer has one tab for each part:
A Page has the same drawer, with a Plots tab that lists only its Panes’
Plots, because a Page owns none. The tab that holds the React source is
Programming on both, the name the Policies tab gives the code. Switching tabs keeps each draft. Moving
to another Pane or Page keeps the drawer open or closed and on the same tab, so
a Pane’s Policies opens on the next Pane’s Policies. A Piece without
that tab opens on its first tab. In a drawer too narrow for every tab’s name,
the tabs other than the open one show their glyph alone, and name themselves
on hover. In Auto
the preview shows a Pane as a card centred on the canvas, as tall as what it
draws.
A missing or hidden source does not remove the Pane or its other tabs. The source
editor shows Source unavailable, and a Plot remains listed even when its SQL
is hidden. An allowed compiled Page or Pane still renders when its React or
Perception source is hidden. Its declared Pane references remain available.
Unsaved source edits use the editing preview until a matching build is available.
An unsaved Perception or Policies change is not code the preview runs, so the
compiled preview stays on the canvas while it saves.
When Ponder takes a picture of a Pane, it uses the light or dark theme shown
when you sent the Message, including your system theme when you follow it.
A later theme change applies to new pictures; images already in the
conversation keep the appearance in which they were captured.
The host supplies these React props:
A referenced Pane that throws while it loads or renders shows Couldn’t
populate with its name and the error’s message in its place. The Page or Pane
that mounted it and its other Panes keep rendering. When the Page or Pane on
screen itself throws, the frame shows the same card.
policies.capabilities.edit.preferences decides whether an editing action is
enabled. Keep a control the requester cannot use on screen, disabled, with
why: when seatCapabilities allows it, switching to their fullest
participation mode turns it on; otherwise say who can. Hide only what a view
capability or a filter Policy keeps from them.
A true capability describes participant eligibility;
capabilities.conditional means actual values or rows may still need condition
checks: it is true when a filter Policy covers
the Pane, from its holder’s tree, the line’s root Page for a Pane nothing
declares, or the Pane’s own Plots, and does not let this requester read every
row. It does not look at what the Pane’s Plots read. A filter narrows only a
Plot that reads Provider data, so a Pane whose Plots read only settings,
Workspace tables or literal values reads in full even when conditional is
true.
capabilities.writeConditional is true when a filter Policy for create,
edit or delete binds this requester’s writes of the Pane’s shared settings
(This Parable’s and every group’s): the write is checked against the filter’s
conditions and may be refused by its value. It is never true for the Primary.
When it is false, the requester’s shared-setting writes in the Pane pass every
filter; when it is true, a Pane can enable a control only for the settings a
Plot of its own says the requester may change, and say why the others are off.
Neither boolean nor authorityKey authorizes a later request.
When the host reads a Pane’s Policies again, after a setting changes or a write
is refused, the decisions on screen stay until the new ones arrive, which then
apply at once, a lost permission included; a control a capability gates does
not blink out meanwhile. A Pane given another input is denied everything until
that input’s decisions arrive.
policies.admissions says, for each action and part the requester may take,
which grant admitted them: by is participation (with the grant’s lowest
listed level their seat meets), person, or role (with roleId and
roleName), and setting names the This Parable setting whose value was the
grant, when one was. A refused action and part has no entry. viewAs is true
under a View as preview, where grants admit by participation alone.
policies.seatCapabilities is present only while the page works in a
participation mode below the seat the requester holds (under View as, the
previewed person’s), such as a Publishing author in Peeking. It holds the
decisions at that seat, in the shape of capabilities, while capabilities
holds the mode’s. At the seat, and in a mode at or above it, it is absent. It
never authorizes anything: the server refuses a change the mode does not
allow, whatever seatCapabilities says.
Use @parable/<parable>/<pane> for Props, key, preferences, plots, panes,
plotApi, pages, and getParableContext(). These bindings use the saved Perception and
declared Plot contracts. Other application components enter through declared Pane
references; the approved React, Motion, Kysely, scalar, and shared-control
libraries remain available. Only a Page is composition only: its code may import
only the Panes it declares and the runtime layout modules. A Pane whose
primitive is null can still use the shared controls and read its Plots.
Warnings & Errors
Every check reports a warning or error in a Page’s, Pane’s or Plot’s code the same way: what it is, the check that found it, its rule or code, and its line and column.
The editor underlines each warning and error and marks its line in the
gutter. Hovering it shows its message, its rule, and any fix as a button. A fix
labelled changes behaviour can change what the code does; read it before
applying it. The footer under every code editor lists the Warnings & Errors.
Folded, it shows a count for each severity, or No Warnings & Errors. Opened,
it lists each one with the check that found it and its line and column, errors
first; choosing one moves the editor to that line. The footer stays open or
folded as you move between Pieces, and each editor tab shows how many errors and
warnings its document has.
Warnings & Errors never block a save, and viewing a Parable never waits on them.
Publishing does: a Publish refuses Changes while any Page, Pane or Plot in them
has a warning or an error, and the refusal names each one and its counts. The
Publish button says how many there are before you press it. Info findings never
block. No code publishes unchecked: a file over 256 KB is too large to check,
and a Publish refuses it until it is made smaller or split into more Panes; a
file whose check could not finish is refused until a later Publish finds it
checked.
The code check, TypeScript and the build describe the text that was saved. Once
you type, their underlines clear until the next save, and the editing preview
reports errors in the text you typed. Checking for Warnings & Errors… means a
result is not ready yet, and Warnings & Errors could not be checked gives the
reason; neither means the source is clean. The code check runs where the server
has its runner: local development and CI today. Until the runner ships to
deployed Workspaces, the Piece API reports each checked file as
failed with
the reason, so an agent never takes it for clean, and a Publish there is not
held for a check that cannot run; local development says Warnings & Errors are
not checked on this server when the runner is not configured.
A Pane that does not build
Each Page and Pane compiles on its own. A Pane that does not build draws This Pane did not build and its first error where it would be, and the rest of the Page renders around it. Selected alone, it shows … did not build on the canvas, with every error listed under its code. Publishing refuses Changes in which any Page or Pane does not build.Fixing Warnings & Errors with Ponder
Ponder reads and fixes Warnings & Errors with two tools.read_piece_diagnostics returns one Piece’s documents, its code and its
Palette, each with its exact text, that text’s revision, and every current
warning and error from the code check, TypeScript, the build and Plot SQL
validation, with line, column, offsets and the text of the line. pending is true while a check has not answered for that text.
For a Page or Pane it also returns the Perception source and the Policies, so
Ponder reads one Piece whole without reading the whole Parable; Policies are
left out for anyone without view permission on Policies. Ponder reads a whole
Parable as an outline of its Pieces, with no code.
edit_piece_source replaces exact passages of one document. Each passage must
occur exactly once in the text, or nothing is saved and the refusal
(PA-AU-045) says how many times it occurs. The edit is refused (PA-AU-002)
when the document changed after it was read, so it never lands on text Ponder
has not seen. Its answer carries the new revision and every warning and error
after the save.
A refused save tells Ponder which Piece, import or handle is at fault and its
line and column, never the submitted code. When Ponder previews a Pane that does
not build, the answer names the first error and the Pane to read. The Panes and
Plots Powers teach the loop: read the Warnings & Errors, make the smallest edit
that fixes one, and read them again.
The Piece API returns the same Warnings & Errors as sourceLint on every
package read and save result: lint for the code check and TypeScript, or a
Plot’s recorded validation, and build for the compile.
Services
Render a referenced Pane with an inlineprimitive or a saved setting’s
preferenceId. The host resolves the selection and supplies composition, owned
Plots, and current policy decisions. Caller props cannot replace those decisions
or bindings. A null-compatible Pane can render without a selected value; other
Panes stay unfilled. Parable never picks a setting on its own. A Pane whose
Perception declares preferences is always null-compatible and takes no
preferenceId: its settings are its Preferences, which its code reads through
preferences.values. preferences.mode reads live or versioned, and
preferences.plotSql whether the settings are the Pane’s Plot SQL, as the
Perception declares them; a save’s outcome says whether it applied live,
published a Version, or proposed Changes
(Preferences).
The server resolves Panes in bounded batches through resolveParablePanes.
A refused item does not discard permitted siblings. The host can also request
capabilities alone without receiving values, source, bindings, or private schema.
A compiled Page also keeps rendering when a declared Pane’s module is withheld
from its reader. That Pane shows This Pane is unavailable in its place;
the Page and its permitted siblings remain visible. A root Page without its
own compiled module is still an error.
Ordinary React state and Context coordinate inputs and charts without saving
every change. A declared Pane’s module exposes its React exports as a Promise;
React.use(panes.state.module) lets referenced Panes share an exported Context.
Data refreshes and Current/Report changes do not need to recreate that state.
Changing the requesting actor or Workspace replaces the renderer’s context.
Storage
A Pane’s Perception and Policies are fields of the Pane, saved and versioned with it. Its Palette and its Plots are Pieces the Pane owns. Creating a Pane creates its Palette, and deleting a Pane deletes its Palette and its Plots. Deleting a Pane is refused while another Page or Pane still uses it: one whose Perception declares it, or whose code reads one of its Plots. The refusal names them; change or remove them first. Reads never create settings or repair missing configuration. A Pane keeps a choice only when its code saves a setting; see Preferences. Parable applies no fallback between a person’s own setting (Me) and the shared one (This Parable). A Page is composition only. Its primitive is null; it arranges referenced Panes that own application values and queries.Security
Using a Pane and its selected value requires currentview.preferences access.
Inspecting its Perception, Plot source, CSS, or Policies uses the
corresponding view target. Permission to inspect source is not required merely
to render an allowed Pane or read permitted SQL output.
A permitted renderer receives executable JavaScript and CSS. Source-editor
restrictions cannot make delivered assets secret. SQL source can remain private
because named execution resolves it on the server. Every query and stored write
checks current Policies independently of what the component displays.
What a Pane’s code can reach
A Pane’s compiled React runs in the reader’s browser inside a sandboxed frame with an opaque origin. That frame has no forms, no downloads, no pop-ups, no network access, and no remote scripts; everything it renders is inlined. Its only way to the application is the host bridge, which answers requests that name a live Page or Pane of the mounted Parable (its value, its settings and its Plots) under the reader’s own permissions, at a bounded rate, and starts the actions below only after a press. A Pane’s module names that Pane and the Panes it declares, but one frame renders a whole Page, so the host cannot tell which Pane’s code sent a request: Pane code can reach any Pane of the Parable the reader can, not only its own. The bridge also carries what the frame draws but cannot fetch: Font Awesome glyphs, and the company logosBrandLogo
shows, which the host fetches through the app and hands over as image data. A
Pane can preview SQL of its own in place of a Plot’s (plotApi.preview) in the
Piece editor’s canvas and on a Page in Ponder’s chat. The host sends it to the
server, which runs it only for a reader who may save that Plot’s SQL and
refuses anyone else with HTTP 403, PA-AU-019 and the reason before any query
starts (Plots). The preview camera
and Labs refuse it.
The frame cannot move the reader, but it can ask the host to. pages in the
Pane’s module moves between the Parable’s Pages:
The host answers
open and back only just after a click or key press in the
frame, only for a live Page of the mounted Parable (anything else is
HANDLE_UNDECLARED), at most once a second, and only on a surface that has an
address of its own: the Ponder routes do; the preview camera and Labs refuse
with SCOPE_REFUSED. Call them from an event handler, never on mount. A Page is
composition only and cannot import the shared controls, so a designed control
that moves between Pages belongs in a Pane.
A press counts as in the frame only when three things hold: the frame has
focus, the browser reports a fresh click or key press, and the reader has
pressed nothing elsewhere in the app since the frame took focus. Typing in
Ponder’s composer, or clicking the app around the Page, is not a press in the
frame, so Pane code that calls on a timer is refused while the reader works
elsewhere. After a click outside the frame that leaves focus in it, the reader
clicks into the frame again before it may act.
One gap remains. Pane code that moves focus into its own frame, for example by
calling focus() on one of its inputs, passes this check while the reader’s
last press elsewhere is still fresh, about five seconds. The reader sees it:
their typing lands in the Pane instead of where they were typing.
For a reader who can use Ponder, the frame also reaches Ponder through the
host (see Ponder):
Each turn is an ordinary Ponder turn under the reader’s own permissions, with
Ponder’s tools; a tool call that changes something waits for the reader’s
approval in Ponder’s drawer. The host answers
open, ask, path and
continue only just after a click or key press in the frame, as it does
pages.open, so Pane code cannot start a turn on mount, on a timer, or while
the reader types in Ponder, short of the focus gap above. It checks that the calling Pane is
one of the Page’s and that a named Plot is one it declares, and keeps one turn
running per Pane. Labs, the preview camera, unsaved previews and View as get
none of these.
Stopping a turn ends its reply in Ponder, not only on the page: the host calls
Ponder’s stop for the reply, so it runs no further, and the conversation
shows it stopped. A new ask from the same Pane stops the last one
the same way and waits for it to end before it sends, since Ponder runs one
turn at a time per conversation. A turn stopped before its reply has started is
stopped as soon as the reply starts. When a Pane’s remembered conversation no
longer exists, the next ask starts a new one; any other failure, such as a cut
off reply or a refusal, reaches the Pane and keeps the conversation.
A turn a Pane starts is the one exception to a Pane reading only its declared
Plots: it keeps the reader’s whole Workspace reach. The Pane names what the
reader pointed at, and Ponder’s tools then read anything the reader may read,
as they do in Ponder’s drawer. The Pane’s own Policies limit what its Plots
return, not what that turn reads.
Which Providers the Workspace has connected is Pane data: a Pane reads it
with a Plot over workspace.providers and passes the rows to
ImproveParable and PopulateParable,
so anyone who can read the Parable sees connection health. Connecting one is
an action, which the frame asks the host for:
The preview camera, Labs and View as get no
providers.connect, and the
components there offer no Connect. A reader who may not create a connection
reads “View only” on the setup page. It needs a click or key press in the
frame, as pages.open does. Setup never runs in the frame: a credential form there would
run in the author’s code, and OAuth needs a window the frame cannot open.
The trust boundary is therefore the author, not the code. Authored code sees
exactly what the reader it runs for is permitted to read through declared
bindings and, after the reader presses something, what a Ponder turn reads and
streams back as that reader. A sandboxed frame can still navigate itself, so
an author who wanted to could send those rows somewhere else. Treat the
ability to author or propose a Pane like the ability to write its SQL: grant it
through Publishing permissions,
review proposals before accepting them, and use Policies to limit what a Pane’s
Plots return rather than expecting the renderer to hide anything from its own
author. Policies do not limit a Ponder turn the reader starts from a Pane;
the reader’s own permissions do.