Skip to content

RISE CHANGES

github-actions[bot] edited this page Oct 16, 2026 · 12 revisions

RISE Changes — the shared contract (coordinator, 2026-10-14)

RISE Changes turns what merged into RISE into a narrated RISE reading. Pilot: one digest a week for the TEAM (internal audience), from merged pull requests on SyberLabs/RISE. Readers-facing digests come later, behind a human approval; the schema carries audience now so that is additive.

Flow

  1. GitHub Actions workflow .github/workflows/changes-digest.yml (weekly, Monday 09:00 UTC, plus workflow_dispatch with inputs since (ISO date, optional), dry_run (boolean) and supersede (a published digest id, optional)).
  2. scripts/changes/digest.mjs collects merged PRs since the newest digest's period.to (or 7 days back), routes them (a Jev-style finite-choice decision), composes one rise.current.v2 with Claude, admits it with RISE's own validators, and writes two files.
  3. The files are committed to the orphan data branch changes-data (NOT main; only main is protected). Nothing deploys.
  4. The Worker serves them same-origin at /content/changes/<file> by proxying https://raw.githubusercontent.com/SyberLabs/RISE/changes-data/<file> (the repo is public).
  5. The app shows /changes (the list) and /changes/<id> (the reading, its sources, and how each change was routed).
  6. The workflow opens one issue per digest ("What changed in RISE: ") linking https://rise.syberlabs.io/changes/, with the routing table, so the owner is notified.

Files on changes-data

index.json:

{ "schema": "syberlabs.changes-index/v1",
  "digests": [ { "id": "2026-10-19", "audience": "team", "title": "…", "period": { "from": "2026-10-12T09:00:00Z", "to": "2026-10-19T09:00:00Z" }, "count": 12 } ] }

newest first, at most 200 entries. An entry may carry "supersededBy": "<id>", a listed digest that re-ran its period (--supersede, below): /changes lists that one in its place, and the superseded digest's page links to it. It is optional, so every index written before it stays valid.

<id>.json where id matches ^\d{4}-\d{2}-\d{2}(-[a-z0-9]{1,8})?$ (date of period.to, a short suffix only if two runs share a day):

{ "schema": "syberlabs.changes-digest/v1",
  "id": "2026-10-19",
  "audience": "team",
  "title": "What changed in RISE, 12–19 October",
  "period": { "from": "ISO-8601", "to": "ISO-8601" },
  "generatedAt": "ISO-8601",
  "model": { "router": "claude-sonnet-5-5", "composer": "claude-sonnet-5-5", "via": "Claude Code" },
  "changes": [
    { "number": 652, "title": "…", "url": "https://github.com/SyberLabs/RISE/pull/652", "mergedAt": "ISO-8601", "mergeSha": "2f13e80a…(40 hex)",
      "route": { "audience": "skip|team|readers|both", "significance": "minor|notable|major", "kind": "feature|fix|performance|design|infrastructure|records" },
      "included": true, "reason": "routed|records-only|limit|unspoken" } ],
  "current": { "schema": "rise.current.v2", "...": "an admitted Current" },
  "sources": { "0": [652], "3": [653, 656] },
  "quality": { "firstPass": false, "repairs": { "composition": 1, "illustrator": 2 }, "checks": { "process-talk": 1, "text-crosses-shape": 2 },
               "density": { "pictures": 6, "includedChanges": 8, "speakingBeats": 17, "pictured": 17, "longestUnpictured": 0 } }
}
  • reason unspoken: a change routed into the reading that no beat spoke of; the run leaves it out (included: false) and says so in notes, rather than repairing the composition.
  • sources maps a beat index (string) of current.beats to the PR numbers that beat speaks about; every number must be in changes with included: true; every included change is cited by at least one beat.
  • quality (optional, before notes): the run's first-pass score (Quality gates, below). firstPass is true only when nothing was repaired and nothing let go; repairs counts the repair requests of each stage; checks maps each rule that fired (a lower-case id, at most 40 of them) to how many times. Every digest the pipeline writes has it; the two written before it do not, and stay valid. density (optional; the digests written before it have none) measures the finished reading: the pictures it shows, the included changes it speaks of, its speaking beats (beats with refs), how many of them are shown a picture of what they speak of, and the longest run of speaking beats without one.
  • notes (optional, last): 1 to 20 sentences of at most 300 characters saying what the run let go, such as a picture not drawn; absent when there is none.
  • current.origin = { kind: "model", name: "<composer model>", provider: "Anthropic, via Claude Code" } (check the Current schema's origin fields and keep within them).
  • Bounds: at most 60 changes listed, at most 24 included; titles ≤ 200 chars; the whole file ≤ 256 KB.

Trust

  • Everything in these files is model-written or PR-written. The app admits current through the SAME admission a card's Current goes through (scene code and SVG admission, the Current validator) before playing, and validates the envelope against this schema; a file that fails is shown as "This digest could not be shown", never played.
  • The Worker proxies only filenames matching ^index\.json$|^\d{4}-\d{2}-\d{2}(-[a-z0-9]{1,8})?\.json$, GET/HEAD only, returns application/json, X-Content-Type-Options: nosniff, caches index 5 minutes and dated files a day (they are immutable once written, but a re-run may replace one).

The generator (PR A), as built

These refine the contract above. The code is in two places. src/core/changes/ holds the pure pieces the app may share, which import nothing from the live layer: contract.js, the envelope check both sides use (digestProblems, indexProblems, sourcesProblems), with collect.js, prefilter.js, write.js, claude-cli.js and the sample in fixtures/. scripts/changes/ holds the Node pipeline that reaches the live layer (the host guide, the MCP size bound): route.js, compose.js, admit.js and run-digest.js, which digest.mjs runs.

  • Run. node scripts/changes/digest.mjs [--since <ISO>] [--out <dir>] [--dry-run] [--supersede <id>]. It reads GitHub through gh and writes <id>.json, index.json, issue.json and run.json to a new or empty out directory. It never commits, pushes or opens an issue; the workflow does, and skips both on a dry run.
  • Period. From the newest period.to in index.json on changes-data (or seven days back, or --since) to the moment of the run; a pull request is in it when merged after from and at or before to. With --supersede <id>, the period starts at that digest's period.from unless --since is given.
  • Supersede. --supersede <id> (the workflow's supersede input) re-runs a published digest's period when the one published falls short (the 2026-10-16 digest showed 2 pictures in 19 beats). The new digest takes the day's next id (-2, as any second run that day), and the index marks the old entry supersededBy the new id; the old file is never touched, so its address still answers and links to the new one. A digest the index does not list, or one already superseded, is refused before any model is asked; supersede the newest instead.
  • Collect. GraphQL repository.pullRequests(baseRefName: "main", states: MERGED), newest-updated first, paged until a pull request was last updated at or before from. Kept: number, title (one line, at most 200 characters), body (first 4,000 characters, for the models only, never written), url, mergedAt, merge commit, labels, the first 100 changed paths and the file count.
  • Records only. Every changed file under docs/product/tasks/, and every changed file seen (a pull request with more than 100 files is never records-only). Listed with route skip/minor/records, never offered to a model.
  • Route. One call; the answer is {"routes": {"<number>": {"audience", "significance", "kind"}}}. Each pull request's answer must have exactly the three keys, each one of the menu's values; otherwise that pull request gets skip/minor/records and stays listed. Answers for pull requests not offered are ignored.
  • Select. Included in the team digest: any audience but skip (team, readers or both) with significance notable or major; the team hears everything that matters, and each change keeps its routed audience for a later readers digest. At most 24, majors first then the newest (limit for the rest). Listed: at most 60, every included one, then the weightiest and newest of the rest, records last. changes is written newest merge first. count in the index is the number of included changes.
  • Compose. One call, taught by CURRENT_GUIDE from src/live/guide/ (unchanged). The included pull requests, and as context only the routed ones left out (marked "included": false, never spoken of or cited, since a later minor fix may settle an included change's caveat), are given in merge order with their merge times; the composer is told that a later pull request may resolve or supersede an earlier one's caveat (unverified, pending, left to decide), to state such a caveat only when no later pull request resolves it, and to speak as RISE in plain words with no flourish; the close says the week's last fact and stops, with no summary or slogan. The answer is {"current", "pictures", "opening"?, "close"?}. RISE's engines are named only in opening and close, each { engine, params? }: the pipeline places the opening on the first beat and the close on the last and declares their scenes (opening, close). A scene in the Current or a picture that names an engine is refused before anything else is checked, in plain words: "RISE's engines open and close a digest; a change is shown with a kit picture" (the rule engine). So an engine in the middle of the reading cannot be written at all; it is no longer repaired (dry run 38696304051 repaired a third engine at beat 16). Each beat carries its own refs, the pull requests it speaks about, beside its words; the pipeline takes them off the beats and writes the contract's sources from them (a separate map drifted from the beats it named: dry run 38666483992 repaired one). Each theme gets one picture, on its first beat, held across its beats: a kit figure { beat, refs, kit: { kind, ... } } whenever the change is a measurement, a sequence, a sorting, a layout, a set of rules or a before and after (a rule or a process change is a list or a compare; The figure kit, below), or, for a diagram no kit kind can express and at most 2 a digest, a brief { beat, refs, medium, brief } for RISE's illustrator (the brief 20 to 300 characters naming every label and number to draw, medium figure by default or scene when motion explains). The composer is shown one compact example of each kind (KIT_EXAMPLES in compose.js) and each slot's budget in characters, written from the kit's own measure (KIT_BUDGETS in figure-kit.js, the same geometry and average character its refusals count with), so the guidance cannot drift from what the kit accepts; a test holds the prompt's numbers to the kit's (dry run 38879838950 repaired a list title one budget over). A picture's refs are the pull requests it shows and must be among its beat's refs, so a picture sits on the beat that speaks of it (dry run 38688524786 showed #668's frame rates on a beat about #652); its numbers, kit values and figure text alike, must be stated by the pull requests it cites, not anywhere in the week. A picture must show something the words alone do not. An included change no beat cites is no longer refused: the run marks it unspoken (above), and the first-pass score counts it as a check that fired (unspoken) and as something let go, so the first pass is lost, though nothing is repaired; more than five share one note. current.origin is set to { kind: "model", name: <composer model>, provider: "Anthropic, via Claude Code" } whatever the model wrote.
  • Admit. The connector door's checks (65,536-byte bound, validateRiseCurrent, admitSceneCode, admitSvg, refusals worded by describeDiagnostic), the sources rules worded for refs (a ref to a change not included, or an included change in no beat's refs, is refused as before), figureProblems for every kit figure (its sentences prefixed "pictures"[n].kit:), and one more: every number the Current says or shows must be stated by an included pull request's number, title or body, or be a date of the period; a kit figure's labels and values are held to it too (a bar's max, a scale never printed, is not). A refusal gets a repair call with the refusal's lines, then one more; a third refusal fails the run without writing.
  • The composition rule (admitted with the composition, its refusals repaired like any other): the composer's Current declares no engine, so the engines are at most the 2 RISE placed, at the opening and the close, for mood; every picture is a kit figure or a brief (at most 2 briefs), at least one, at most as many as the Current's 8 scenes leave beside the opening and the close, each on a beat that names no scene of its own (never the first beat under an opening or the last under a close); no engine is held for more than 4 beats, and no picture for more than 6 while every beat under it cites one of its changes (4 when a beat under it has no refs). RISE's eye is the room at rest, not a picture, so no hold limit binds it (dry run 38699570866 repaired an 8-beat rest). The first real digest (run 38635708731) held one attractor through all 16 beats; this rule is why it cannot happen again. When the pictures need more scenes than the opening and the close leave, RISE gives up the close, then the opening, as long as that makes room (the run log says so); otherwise both stay and the room is refused. The 8 scenes and the beat limits are the connector's and are unchanged.
  • The density floor (rule density, refused and repaired like the composition rule): a speaking beat (one with refs) is pictured when the scene shown on it is a picture whose refs share one of its own. No more than 2 speaking beats in a row may go unpictured, and every included change routed major that a beat speaks of must be in some picture's refs. RISE's eye still rests freely on beats without refs, which neither count nor break a run. The refusal names the beats and their changes, or the major change, and suggests one picture a theme held across its beats, a list or a compare for a rule or a process change. Why: once the eye was exempt from the hold limit (#695), the only floor left was one picture, every picture risked refusals that words do not, and the score rewarded a first pass, so the cheapest valid answer was few pictures: the published 2026-10-16 digest (run 38874190971, first pass) showed 2 pictures in 19 beats, beats 5 to 12 on the eye. A Current within the 8 scenes can meet the floor because a picture held across a theme's beats ends only where they move on, and may be held 6 beats while they cite it.
  • Illustrate. A kit figure is drawn by RISE itself (renderFigure with the Current's theme), held to admitSvg, the number rule, svgLayoutProblems and the rendered check; with no model to repair it, one at fault is let go like a refused picture. The second role: each brief, in beat order, drawn by RISE Live's own illustrator (draw in src/live/illustrator.js, docs/plans/LIVE-CURRENT.md §19) through a text-stream adapter whose one request is an ask. Its instructions are Live's ILLUSTRATOR_INSTRUCTIONS plus a short note on where the digest's pictures are seen (a dark room, the full frame, labels readable 390 pixels wide); its request is Live's promptFor (the brief, the theme, the scene running, the two beats said with it); its admission and repair are Live's (admitSvg, admitSceneCode, three attempts), and every figure is also held to the number rule. An admitted picture becomes picture-<n>, started on its beat. A picture still refused, or whose call fails, is let go: its beat keeps the scene before it, the run log says so, and so does the digest's optional notes (1 to 20 sentences of at most 300 characters, shown under "How this was chosen" and in the issue).
  • Held pictures. After the pictures are placed, the run decides how long each stays (endHeldPictures, scripts/changes/held.js): a picture stays only while each following beat's refs share one of its own; at the first beat that shares none and starts no scene of its own, the reading returns to RISE's eye (a still scene, eye unless the Current declares a still, which the Live room shows as Sophia's eye) until the next picture. A beat with no refs (an opening, a hold, a close) keeps what is showing, and RISE's engines are never ended. The composition rule counts the beats each picture and engine is actually shown under this way, the eye's runs exempt from the hold limit, a picture's run held to 6 beats when every beat in it cites the picture and to 4 otherwise, and the density floor counts the speaking beats under a picture of what they say the same way, and keeps one of the Current's 8 scenes for the eye when a picture will end early and no still is declared (dry run 38691661884 held the naming-a-visual flow under the memory and swarm beats). The page's reasons say why a change was left out in the rule's own words: minor, skipped by the router, records only, over the 24-change limit, or the reading did not speak of it.
  • Ids. The UTC date of period.to; a second digest that day is -2, then -3. A digest file is never replaced; a superseded one stays, marked in the index.
  • Title. What changed in RISE, <period>, the period in UTC dates: 12–19 October, 28 September – 5 October, 28 December 2026 – 4 January 2027. The issue is titled What changed in RISE: <period>.
  • Model calls. Claude Code CLI 2.1.287 (on Node 22.23.3 in the workflow, which the CLI requires) in print mode (-p --output-format json --model claude-sonnet-5-5 --max-turns 1 --tools "" --disallowedTools "mcp__*" --strict-mcp-config --disable-slash-commands --no-session-persistence --permission-mode dontAsk --system-prompt-file system-prompt.txt), the prompt on stdin, run in a fresh temporary directory. The child's environment is an allowlist (PATH, HOME, the temp and locale variables, CLAUDE_CODE_OAUTH_TOKEN) plus CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1; the GitHub token is not in it, and gh is not given the Claude token. Any echo of the token in the CLI's output is redacted before it is logged.
  • Sample. src/core/changes/fixtures/ holds the recorded week of #652–#671 (the GraphQL page, a router answer, a composition) and the illustrator's answers (illustrations.json), and the digest and index the pipeline produced from them (2026-10-14.json, index.json), admitted by the real validators.

The figure kit

The owner's approved study is docs/assets/changes/figure-kit-study.html; src/core/figures/figure-kit.js ports its renderers (pure, shared, nothing from the live layer, so the connector and Live can use it later). The study drew four kinds; list and compare were added in its house style for a week of rules and process changes, which no kind drew (the 2026-10-16 digest). renderFigure(spec, { theme }) answers an SVG string; figureProblems(spec) answers plain sentences, empty when the kit can draw the spec. The model gives data; RISE places every label.

The house style. One accent per figure for what changed: the reading theme's accent (src/core/jev-palette.js, cobalt when the Current names none). Hairlines at a third of the ink instead of boxes. Titles in a serif (Georgia stack), labels in the system sans: a figure is an <img> and cannot load a web font. The viewBox is 800 × 500: labels 25 units, titles 40, values 34, column names 30, so the smallest label is 12.2 pixels on a phone 390 pixels wide. Numbers are printed exactly as given; nothing is computed into text.

Kind Data Bounds What changed
bars items {label, value, changed?}, max (the scale's top), title?, note? (unit or context) 2 to 4 items, each value 0 to max one item, in the accent
flow steps (labels, each once), changed? (a step), loop? {from, to, label} 2 to 7 steps; the loop between two different steps the changed step, filled and outlined in the accent; the loop in the accent
columns columns {name, glyph? (eye, shell, full or dot), items}, title? 2 to 4 columns of 1 to 6 items the glyphs
stack zones bottom to top {label, shape (circle, lines, bar or ticks)}, changed?, dock? (a dot beside a zone that is not ticks), title? 2 to 5 zones, each label once the changed zone's shape, leader and label
list items {label, detail?}, changed? (an item's label), title? 2 to 6 items, each label once the changed item's dot, label and detail; every other item a hairline and ink at reduced strength
compare rows {subject, before, after}, headers? {before, after} (Before and After when none), title? 2 to 4 rows, before and after different every after cell, and the after header; a hairline arrow between the cells

Sparse kinds are refused. Columns need at least two columns of two items or more ("too sparse for columns; say it in words or use a flow"), a list of two items needs a changed item or a detail, a compare row must differ before and after, and a flow of two steps needs a changed step or a loop: four columns of one word each, or two steps with nothing marked, explain nothing a sentence does not (dry run 38688524786).

No collision by construction. Every slot is measured before anything is drawn, with the advance widths the layout check uses (textAdvance), widened by 1.12 for the serif and 1.1 for the system sans (the widest a reader or the Linux runner is likely to set, DejaVu Sans) and by 1.08 for bold. A label too wide for its slot is refused, never shrunk or cut: columns[3].name "An extremely long column name" is 25.5 characters wide at 30 units; its slot holds 8 characters. Shorten it: the kit never shrinks or cuts a label. The tests hold every kit figure, the study's four and specs at every bound (the most items, each slot's longest accepted label), to admitSvg and to svgLayoutProblems with no problem and no note, on the room's ground and each of the nine themes' own; scripts/changes/render-check.test.js measures the same figures in Chromium. A bar chart of 2 bars, a flow of up to 6 steps, 3 columns and the study's room use the study's geometry; more bars narrow the bars and their gaps, a seventh step shortens the nodes to 38 units, columns divide the width evenly, and a stack gives a circle two shares of the frame's inside and every other shape one. A list starts its rows at a fixed baseline, 158, as a flow's steps start under the title, 56 units apart; without details a label has the whole width, and with them the label column is as wide as the widest label (at most 330 units) and each detail has what is left. A compare heads its columns at 146, under a hairline at 162, with up to 4 rows of 104 units at most from 176: the subject (serif italic) above, the before cell at the left margin and the after cell at 428, each 316 units wide.

Quality gates

Every failure seen in a real run becomes a mechanical check that answers with a plain sentence a repair can act on; a sentence in a prompt alone drifts. The checks are pure (src/core/quality/, nothing from the live layer) and are run by the digest pipeline and, count only, by the connector.

Seen in a run The check
A label drawn across its box (dry run 1, "harmonograph") svgLayoutProblems: text-crosses-shape
A closing line about "the next dry run" (two dry runs) processTalkProblems: process-talk
A number no pull request states the number rule (Admit, above)
One visual held through the whole reading (run 38635708731) the composition rule (above), and pictureCadence at the connector

svgLayoutProblems(svg, { roomWidth = 390, ground = '#0a0a0f', maxWork }) reads the figure with the tokenizer that admits it (svgTree in src/core/svg-admission.js; a figure admission refuses is not judged) and answers { problems: [{ rule, line, message }], notes, work }. Each label is a box: its x, y, dx and dy, font-size (16 when none is set), text-anchor, dominant-baseline and textLength, under every ancestor translate, scale and axis-aligned matrix. Its width is Helvetica's advance for each character (Arial's are the same), 0.56 em for a character outside that table, 0.6 em in a monospace family, 8% more when bold; a flat 0.56 em per character was tried first and wrongly refused two published labels made of narrow letters. Its height is the em box, 0.8 em above the baseline and 0.2 em below. The rules:

  • text-overlap: two label boxes meet.
  • text-crosses-shape: a label straddles the edge of a rect, circle or ellipse (their bounding boxes), or touches a line, polyline, polygon or path (their segments, a curve as eight chords, absolute and relative commands alike; the bounding box of a connector is not ink). A stroke widens the edge by half its width, and a label keeps 0.05 em clear of it.
  • text-outside: any part of a label outside the viewBox.
  • text-too-small: font-size × scale × 390 / viewBox width under 12 pixels.
  • text-low-contrast: the label's fill (its attribute, its style, its parent's, currentColor as the words' ink #eef0ff, black when nothing sets one), blended by its opacity, under 4.5:1 (WCAG) against the ground, or against a filled rect it sits wholly on. What it cannot place it never guesses: a rotation or skew, a CSS transform, a <style> sheet, an arc, a <use>, a <textPath>, a nested <svg>, a list of positions, a line placed by y alone and a length in another unit are each skipped with a note. At most ten problems a figure. work is the comparisons it made; past maxWork it compares nothing and says so.

processTalkProblems(texts, { subject }) finds a beat that speaks of the making instead of the change, from a small literal list: dry run; test, trial or practice run; this, next, later, future, following, previous or last run; will show or will tell followed by nothing, in, whether, if, once, after, when, soon or later ("the room will show the picture" passes); remains to be seen; a later, next, coming, future, final, pending or human review, and under review; as of writing; the pipeline, unless the pull requests speak of a pipeline. A phrase an included pull request says itself passes.

pictureCadence(current) is { beats, scenes, longestHold }: the beats, the distinct scenes they start, and the longest run of beats under one picture (a v1 Current by its segments' visuals).

In the pipeline:

  • Composition. admitComposition holds the beats to processTalkProblems with the included pull requests as the subject; a hit is a refusal line like any other, repaired in the same two repairs. Each refusal also says how many lines each rule gave.
  • Illustration. Every figure the illustrator draws is held to svgLayoutProblems as part of its admission, so a problem goes back as a diagnostic (line N (text-crosses-shape): the text "…" at x 72, y 206 crosses the edge of the <rect> on line 11 …) within the same three attempts. A code scene has no static text to place: it keeps the number rule only.
  • Rendered check. scripts/changes/render-check.mjs draws each admitted figure in Playwright's Chromium, fitted whole into 390 × 844 and 1440 × 900 on the room's ground with #eef0ff as its currentColor, and measures every label with getBoundingClientRect: rendered-overlap (two labels' glyph boxes, less a tenth top and bottom for the font's leading, meet by more than a pixel), rendered-outside (a label past the figure's edge) and rendered-too-small (under 12 pixels at 390). The page has JavaScript off, a policy that loads nothing, and every request refused. A figure at fault goes back to the illustrator once, as a refusal carrying its source; a repaired figure still at fault is let go like a refused one (its beat keeps the scene before it, and notes says why). One browser serves the run and starts with the first figure; each check takes about 10 ms after a start of about 1.3 s (measured on 24 real figures). The weekly job installs it with npx playwright install --with-deps chromium, the build the lockfile pins. Its test, scripts/changes/render-check.test.js, needs that browser: the full unit suite runs it (full-validation.yml installs Chromium), and the fast set the required CI check runs excludes it (vitest.fast.config.js).
  • The score. Every rule that fired and every repair asked for is counted into quality (createTally in run-digest.js). The run log prints Quality: First pass: no — 3 repairs (1 composition, 2 illustrator); checks fired: figure (3), process-talk (2) and the object as JSON; the issue carries the same line, and /changes/<id> shows it under "How this was chosen". quality.density is measured on the finished reading (measureDensity), so a picture let go counts against it: the log, the issue and the page carry one more line, Pictures: 6 for 8 changes; every speaking beat pictured, or Pictures: 2 for 8 changes; 6 of 17 speaking beats pictured, at most 8 in a row without one. A first pass is worth nothing if it is bought with an empty reading: the two are read together.

At the connector (worker/mcp-quality.mjs), count only: after the door admits a Current and its answer is built, one log line {"event":"rise.quality","rules":{"<rule>":<count>},"beats":n,"scenes":n,"longestHold":n}, rule ids and counts only, never text or SVG. Nothing the connector accepts, refuses or answers changes, and a test holds every response byte-identical with and without it. It never throws. It reads at most 16 KB of figure text and makes at most 50,000 comparisons a Current; a figure past either bound is counted as unchecked. Measured in Node: 1.5 ms for the published digest's Current (six figures, 9 KB), at most about 4 ms for the worst Currents built to the bounds. Workers Logs keeps the line (observability.enabled in wrangler.production.jsonc).


Published from docs/plans/RISE-CHANGES.md. Edits made here are overwritten on the next push to main.

Start here

Release

Pilot

The Archive - texts and their editing

Authoring - scores, rooms, and rendering

Reading surfaces

Imagery - what may be shown, and on whose authority

The Chapel

Direction and unbuilt work

Affect and the Emotions room

Reading decision service and retired gate

Product direction and team tracking


Documentation index · Repository

Clone this wiki locally