Radd 0.49.2
v0.49.2
137 changes · 43 Bugfixes, 19 New Features, 14 New UI Features, 61 Chores · 464 points.
Bugfix
- RADD-1470 The frontend CI job installs the server, so the four contract proofs can spawn its interpreter
The v0.49.1 publish run (GitHub 36398793337) failed in the frontend job withspawnSync …/server/.venv/bin/python ENOENT. Four mocked browser proofs derive their fixtures from the backend's own contracts by spawning the server interpreter —browser-audit-entity-links.mjs(entity link destinations through…
ciproofs· 1 pts ·393ed8df - RADD-1446 Secrets still stored in plaintext after RADD-1424: AI provider keys, storage host keys, connector tokens and webhook secrets, mail source secrets, TOTP seeds
Found while fixing RADD-1424 (which encrypted the Jira/Confluence credentials, the SSO client secret and the LDAP bind password withsecretbox).
aiattachmentsauthmailintakesecurityvcs· 5 pts ·ac91c48e - RADD-1469 The segmented choice's idle options hold 4.5:1 in the light theme
web/src/components/comments/SegmentedChoice.tsx:84draws an idle option intext-fg-muted. Measured over the built bundle during RADD-1463: the active option holds 4.96:1 dark / 4.70:1 light and the row text 10.9 / 13.1, but the idle option measures 4.41:1 in the light theme — under the 4.5:1 that CLAUDE.md…
a11ycommentsweb· 1 pts ·92ac732c - RADD-1468 The VCS settings page tags its queries with the server's entity types, so realtime reaches them
server/src/radd/modules/vcs/ui/src/queries.ts:37hostEntities(provider)tags the connection and repository queries${provider}Connection/${provider}Repo, a camel-case spelling that exists nowhere else: the server's entity types aregitlab_connection,github_connection,forgejo_connection(each…
realtimevcsweb· 1 pts ·b1a49e6c - RADD-1461 A failed collab bind hands the page back to the single editor, and a remote arriving mid-edit never replaces the draft
RADD-1397 (841cf41) made co-editing the collab remote's: the page asksuseLiveDocumentfor a session and the host editor binds to theEditorBindingit hands back. Two edge cases (reviewer finding, to be reproduced first):
collabpagesweb· 3 pts ·52bde3fb·f466b432 - RADD-1462 Dashboards no longer names the SLA widget, and the bundled automations UI drops its capability gate
Two bundled core packages still carry the patterns RADD-1373/1393 removed elsewhere, and neither guard test can see them because both scanweb/srconly:
automationsdashboardsslasweb· 3 pts ·b32ed0ea - RADD-1457 An undeliverable notification is recorded as undeliverable, not as emailed
RADD-1385 (8cbb3a9) moved the mail transport behind theMAIL_TRANSPORTsocket and deleted the env-relay fallback. When no transport is live,notify/mailer.py record_undeliverablestamps the rowemailed_at = utcnow(), andemailer.run_batchdoes the same for digests. Consequences: (a) monitoring cannot tell…
mailintakenotify· 3 pts ·19a2425b - RADD-1458 A transition check hears only about the moves its rule names
RADD-1383 (573c8db) made approval gates aTRANSITION_CHECKsocket provider.workflow/checks.py state_movedcalls EVERY provider'smoved()on every state change, soApprovalGate.movedspends a banked approval on a move into that target state even when the transition row has norequire_approvalrule. The old…
approvalsworkflow· 1 pts ·6eae65da - RADD-1456 Kernel sockets refuse a duplicate provider, and each socket declares whether it fails open or closed
The RADD-1343 sockets (kernel/sockets.py) have no duplicate-provider check:kernel/registry.py:170-173(target[key(spec)] = spec) and:345overwrite a same(socket, name)registration silently — entity links get a collision error at:160-162, integrations do not. Consumers then choose arbitrarily:…
kernelworkflow· 2 pts ·5c54f4a9 - RADD-1460 Plugin runtime: an enable failure stops only what started, and resume does not duplicate loops
server/src/radd/kernel/runtime.py(RADD-1341/1372):
kernelpluginmgr· 2 pts ·ee268a42 - RADD-1452 The trigger inspector's latest-payload lookup is bounded, and entity search escapes LIKE wildcards
Two small defects from the automation wave:
automationseventssearch· 2 pts ·38313f8b - RADD-1451 "Merge/pull request updated" fires only for changes someone would automate on
RADD-1330 (91f870d) added the "merge/pull request updated" trigger with a kernel diff of the payload.server/src/radd/modules/vcs/triggers.py:37NOISE_FIELDSfilters four bookkeeping keys. GitLab sendsaction: updatewithchangescontaininghead_pipeline_id,merge_status,total_time_spent,time_change…
forgejogithubgitlabvcs· 2 pts ·b447d34b - RADD-1450 A skipped action no longer halts the branch, and an ownerless automation runs as the system actor
Two defects introduced by the RADD-1339 review sweep (bca48bf), found by the 2026-09-27 pre-release review and confirmed in code:
automations· 3 pts ·09cd9efd - RADD-1459 Server status detail stays admin-only, and the Directory page reports a failed capabilities read
RADD-1389 (f54289a) deleted the admin-onlyGET /instance/statusand rendered Server status from/capabilities, which is anActorroute (capabilities/router.py:42). Plugins now put operational detail insummary: the AI provider name (ai/init.py:60), "bind account on" (ldap/init.py:176), outbound-mail…
capabilitiesldapweb· 1 pts ·9a7e08ef - RADD-1455 Bulk move, link targets and parents go through the item row gate
RADD-1413 (a2ea5a4) put item links and stars through the row gate "every other item write uses". Three writers still do not:
itemssecurity· 2 pts ·f96fd18a - RADD-1454 The admin settings list returns a secret as a set marker, never its value
RADD-1424 sealed the LDAP bind password, SSO client secrets and importer credentials at rest and madeGET /scoped-settings/resolverefuse secret keys (403,settings/router.py:47-48). The admin-gated LIST is unchanged:server/src/radd/modules/settings/service.py:233-247builds"value": effectivefrom the…
ldapsecuritysettings· 2 pts ·5ecd5977 - RADD-1425 Contributed automation action nodes can never be saved: hasCoreEditor treats every action. as core*
Found by the RADD-1402 audit (F, automations UI).
automationsmailintakeparticipantstriageweb· 3 pts ·febbdc33 - RADD-1427 Spine defects: events reads a settings field that does not exist, backup tasks are fire-and-forget, group grants show as bare uuids
Found by the RADD-1402 audit (A).
accessbackupeventskerneltriage· 2 pts ·83ae71e2 - RADD-1426 Forms staging sweep has never been scheduled, so abandoned submission attachments live forever
Found by the RADD-1402 audit (C1).
attachmentsformstriage· 2 pts ·fba429e7 - RADD-1424 Importer, SSO and LDAP credentials are stored in plaintext although secretbox landed
Found by the RADD-1402 audit (D1 F9).
confluenceimportjiraimportldapsecurityssotriage· 3 pts ·39bfee06 - RADD-1423 perfseed.py inserts into project_members, a table migration d929grants dropped, so the perf seeder fails on a head database
Found by the RADD-1402 audit ofserver/scripts.
teststooling· 1 pts ·95bdbae8 - RADD-1419 The AI provider Test button ignores the row's reasoning and extra request parameters
Found by the RADD-1402 audit ofai.
ai· 1 pts ·79c108c5 - RADD-1418 AI automation nodes' "Logged time" section has always read "not tracked"
Found by the RADD-1402 audit ofai.
aiautomationstimelogging· 1 pts ·62efa6a8 - RADD-1417 Confluence rollback records the page id as the grant ledger entity, so imported restriction grants survive a rollback
Found by the RADD-1402 audit ofconfluenceimport.
accessconfluenceimport· 1 pts ·f24026c4 - RADD-1416 LDAP login demotes instance admins when no admin groups are configured
Found by the RADD-1402 audit ofldap.
authldap· 2 pts ·e23f1bdf - RADD-1415 GET /pages/by-label/{name} answers 500 whenever the label has pages, which breaks radd:label-list
Found by the RADD-1402 audit ofpages.
pages· 1 pts ·3947ea2b - RADD-1414 Webhook payloads leak email_signature when the description is read-restricted
Found by the RADD-1402 audit ofitems.
itemssecuritywebhooks· 1 pts ·84d3f37f - RADD-1413 Item links and stars skip the row gate: an @own actor can link or unstar items they cannot see
Found by the RADD-1402 audit ofitems.
itemssecurity· 2 pts ·a2ea5a4b - RADD-1422 Five plugin pages gate on instance_role while the SDK reads the credential-aware global_role
Found by the RADD-1402 audit of the plugin UIs.
aiconfluenceimportjiraimportldapleaveplugin-sdk· 1 pts ·7a731de2 - RADD-1421 "Print with subpages" orders pages differently from the tree
Found by the RADD-1402 audit of the pages UI.
pagesweb· 1 pts ·702817d4 - RADD-1420 Pinned wiki pages get the generic link icon: the pins bar still keys on the old /docs prefix
Found by the RADD-1402 audit of the host shell.
pagesweb· 1 pts ·f09bea5a - RADD-1399 The browser-proof harness left a Chrome profile behind on every run, until /tmp filled and Chrome hung at launch
What happened. - The mocked browser suite stopped at its FIRST proof with no output, andtimeoutkilled it after 25 minutes. -/tmpis a 16 GB tmpfs, and it was 100% full. About 900 of the entries were Chrome user-data directories, 40–60 MB each, left by browser proofs. -openBrowser(web/scripts/lib/cdp.mjs)…
testingweb· 1 pts ·cbf17ee0 - RADD-1391 A team-restricted internal comment reaches every internal reader's inbox, excerpt included
Spec 50 lets an internal comment be narrowed to particular teams (visible_to_teams), but that narrowing is lost on the way into notifications, so the comment's excerpt lands in the inbox of people outside those teams. - The comment event carriesvisible_to_teams(comments/service.py~308). -notify/planner.py…
commentsnotifysecurity· 1 pts ·22707311 - RADD-1389 Server status lists what plugins report; Outbound email is read from sender rows, not the environment
Outbound email reads Off on a working instance. Settings → Server status shows it Off whenever mail is configured the way the product configures it now, through sender rows. Thesmtpcapability lives in the corecapabilitiesmodule and checksbool(settings.smtp_host), the env seed that RADD-983 made optional. It…
capabilitiesmailintakeprojectssettings· 3 pts ·f54289a0 - RADD-1388 Error and status text on the VCS, Alertmanager and Backups pages is uncoloured: its classes name tokens that do not exist
Nineteen class usages name status tokens thatweb/src/index.cssnever defines:text-danger-text(13),text-warning-text(3),text-success-text,border-warning-border,border-dangerandbg-danger. The real tokens arestatus-danger,status-danger-ink,status-warning(-ink)andstatus-success(-ink).…
alertmanagerbackupvcsweb· 1 pts ·9f306c27 - RADD-1376 Restore the UI details the isolation moves lost
Reviewing RADD-1340–1366 found small regressions introduced when components moved into the SDK or plugins. Each is a behaviour the old host version had:
auditleaveweb· 3 pts ·fbec1008 - RADD-1372 Live plugin toggling: drain only the changing plugin, never 503 the whole process, and don't replay a re-enabled consumer's backlog
RADD-1341 made enable/disable apply without a restart. A review ofkernel/runtime.py,pluginmgr/live.pyandapp.pyfound availability bugs:
eventskernelpluginmgr· 5 pts ·a7dad0f7 - RADD-1371 Automations after the isolation move: catalog 500s with Milestones on, page-space gate never matches, accepted writes reported as failed
A static review of RADD-1354/1365/1366 found three defects that break real use.
automationspagesplugin-sdk· 3 pts ·a07fa4f3 - RADD-1342 Move Leave settings into plugin-owned slots and withdraw disabled indicators
Disabling Leave hid Holidays in Time logging but left Leave on Profile. Both sections were host-owned imports; only Time logging checked availability, despite the existing profile.section slot. Shared away indicators and timesheet calendars also continued requesting/displaying Leave data.
triage·9bcef957 - RADD-1340 Make plugin disable state and dependent UI reflect runtime availability
Disabling GitHub and Forgejo leaves their automation nodes and Version Control tabs visible. Backend-bearing plugins apply desired state at restart; the manager prominently labels desired state as disabled while they remain loaded. Version Control deliberately renders all providers, and the automation catalog is…
triage·379e498b - RADD-1314 Script writes and VCS backfills escaped the loop guard once RADD-1308 stopped trusting the system actor
These are regressions from RADD-1308 (not yet released). Removing theactor == SYSTEMarm fromis_automation_causedtook away protection in two places that were relying on it without anyone saying so.
automationsscriptsvcs· 2 pts ·7acbbfa5 - RADD-1308 Automations never see an integration's events: the loop guard treats every system-actor write as engine-caused
automations/planning.py::is_automation_causedreturns true forevent.automatedorevent.actor_id == SYSTEM_ACTOR_ID. The second arm predates the spec-116automatedmarker ("older rows predate the marker"). Every integration writes as SYSTEM, so none of its events reach an automation:
automationsevents· 3 pts ·ffd95120 - RADD-1306 Release notes list every issue a version shipped, once: body-named keys count, repeat commits merge
Release notes miss issues whose code rode in another issue's commit, and repeat an issue once per commit. Found in the v0.48.0 notes (Hussein: "the release notes don't mention anything about threads and resolving threads").
docsrelease· 1 pts ·106c85a0
New Feature
- RADD-1369 Version control: per-repository "move merged issues to waiting for release" and "publish version on release" switches
RADD-1309 deleted_transition_mergedfrom the three receivers, along with GitHub/Forgejo's release sweep. The replacement templates (<host>.move_on_merge,<host>.publish_release) make an admin typeowner/repositoryinto a payload gate and name a state literally ("Done"). The old behaviour moved to the…
forgejogithubgitlabreleasesvcs· 5 pts ·f11dc3a6 - RADD-1341 Apply installed plugin enable and disable live across web and workers
Ordinary toggling of an installed plugin currently needs a server restart. Implement a shared runtime lifecycle: stop new plugin work, drain admitted work, pause owned jobs and handlers, withdraw routes and contributions, preserve stored data, and restore everything when enabled. Every web/worker process acknowledges…
triage·25353d97 - RADD-1337 Reversible email signatures with domain regex and optional AI
New email tickets and replies preserve the original body and mark detected signatures for reversible hiding. Show signature reveals the text; Not a signature clears the annotation for authorized editors. Settings → Email supports ordered sender-domain regex rules, optional subdomains, and draft preview. A match starts…
triage·4734039b - RADD-1334 Personal My Work dashboard and activity widget
My Work is now a private, server-persisted dashboard. Defaults are Assigned to Me, Due Soon (including overdue), My Activity, Inbox, and Starred, with relevant approval/request/form widgets added when applicable. Users can add, remove, reorder, configure, and resize widgets, with Save, Cancel, and Reset. Drag movement…
triage·a8ff1e92 - RADD-1335 Readable replies and resolution-aware discussion expansion
Unresolved discussion threads open expanded, resolved replies start collapsed, and each thread toggles independently. Reply counts and controls use modestly larger, clearer text. Reply editors open when Reply is clicked. Direct links reveal the target reply, loading older replies when necessary. Ticket and wiki…
triage·3d363503 - RADD-1338 Keep linked comments highlighted for ten seconds
A comment opened through a direct link stays highlighted for ten seconds after the target actually appears. The timer is cleaned up on navigation. This is a temporary visual highlight, not a scroll lock, and linked replies are revealed before focusing.
triage·2111bfbf - RADD-1333 Emoji and symbol picker in shared editor
The shared rich editor now has a compact searchable emoji/symbol picker. It inserts ordinary Unicode text at the selection, so issue descriptions, comments, wiki pages, exports, and existing MCP Markdown inputs use the same representation. No icon-specific markup or separate MCP command is needed.
triage·5a8ba730 - RADD-1330 "Merge/pull request updated" trigger for GitLab, GitHub and Forgejo
Hussein, testing the wave on the dev instance: the automation trigger list has no "merge request updated". RADD-1309 deliberately let an edit fire nothing.RefActionknows only opened, merged and closed, andmr_action/pr_actionreturn None for: - GitLabupdate; - GitHubeditedandsynchronize; - Forgejo…
automationsforgejogithubgitlabvcs· 2 pts ·91f870db - RADD-1326 Notification kinds are a registry: a plugin event can reach the inbox and the preferences matrix
notify/consumer.py:68-96handles a hardcoded_HANDLEDset of core event types, and_handledispatches with an if/elif chain (:145-167). -NotificationTypeis a closedStrEnum(notify/types.py:8), andkinds.pyis a fixed matrix.
kernelnotifyplugins· 5 pts ·48b541d0 - RADD-1321 VCS time mirror is a per-repository switch, off by default
The MR/PR time mirror (RADD-1258–1261) runs whenever the connection has an API token (gitlab/router.py:114,forgejo/router.py:115,github/router.py:153, and the backfills). It is gated only by per-project time logging. There is no switch saying "copy time from this repository", and by the off-by-default rule…
forgejogithubgitlabtimeloggingvcs· 2 pts ·c9ce22ea - RADD-1320 Missing triggers and subjects: form.submitted, SSO/LDAP user events, auto-watch, SLA met, VCS author, and a subject on every itemless trigger
These happen, but no automation can react to them or reach their subject:
automationseventsformsslassso· 5 pts ·2d7dd2f4 - RADD-1318 Mail: receipt and resolution notice become templates; the outbound relay and SLA response key on comment origin, not the system user
The receipt is hidden and on by default.mail_send_ackis env-only and defaults on (config.py:485,mailintake/service.py:275), so every mailed-in ticket gets a receipt nobody switched on. - The resolution notice (mail_send_resolved) is the same kind of built-in behaviour. - Automation comments never reach the…
automationsmailintakeslas· 5 pts ·23c60e5a - RADD-1317 Alertmanager rebuilt: receivers as rows, its own triggers, no hidden comment or transition
This is the RADD-1309 pattern, still live in Alertmanager: -alertmanager/service.py:88-89comments on the issue on every repeat or resolved alert. -:90-91transitions the issue on resolve. That is controlled byRADD_ALERTMANAGER_RESOLVE_STATE, a state NAME in env, and the docstring claims it "mirrors the…
alertmanagerautomationsconnectors· 5 pts ·f149148d - RADD-1324 Template tokens come from a registry, and contributed nodes can render them
The token roots are hardcoded.automations/templating.py:50(TOKENS) and:111-167hardcode theitem,items,pageandcommentroots, and read the pages and comments payload shapes. A plugin cannot add{{milestone.name}}. - Contributed nodes cannot render tokens at all._NodeContexthas no renderer;…
automationskernel· 3 pts ·535c30c6 - RADD-1323 Trigger kinds become a registry; manual runs and dry runs seed any subject; gates declare whether they read the event
Trigger kinds are a closed enum.AutomationTriggerhas three sentinels, MANUAL, SCHEDULE and VALIDATE (types.py:16-25). Their handling is hardcoded inservice.py:~560-590,engine.py:317and the SPA templates. A plugin cannot add a trigger kind, for example "webhook received on endpoint X". - Manual runs and…
automationskernel· 5 pts ·81746f64 - RADD-1322 Built-in automation nodes move onto the AutomationNodeSpec registry; the executor stops branching on node type
Built-in nodes are a separate, hardcoded path from plugin nodes: -ActionType(automations/types.py:80-120), theTYPE_GATE_*/TYPE_FILTER_SLQ/TYPE_SEARCH_SLQconstants,BUILTIN_PORTS/BUILTIN_OUTPUTS/BUILTIN_ARITY, andgates.GATE_EVALUATORS. - The executor branches on them by name: -…
automationskernel· 8 pts ·d554c6ab - RADD-1310 Automation node "Publish version and sweep": the release loop becomes an automation someone switches on
Once the connectors stop sweeping on their own, nothing an automation can do finds-or-creates a released version and sweeps the project's waiting items into it —set_releaseacts on one item, not a version. The RADD project's own loop (CLAUDE.md step 4) depends on exactly that.
automationsreleases· 3 pts ·b4aef16c - RADD-1309 GitLab, GitHub and Forgejo each register their own trigger events; the hardcoded merge transition and release sweep are deleted
Each receiver ends with a private_transition_merged(three copies) that moves every issue a merged MR/PR names to the project's waiting-for-release state, and GitHub/Forgejo sweep a published release — with no setting to turn either off. Automations cannot stand in: the only VCS triggers are the generic…
automationsforgejogithubgitlabvcs· 8 pts ·19b0c00a - RADD-1283 Threads on wiki pages, and who may resolve a thread is a per-project, per-issue-type policy
Threads on wiki pages, and who may resolve them. Page discussions and inline comments get the same resolvable threads as issues, and each project decides who may resolve a thread (anyone, the thread's author, or chosen roles), with a different rule per issue type if needed.
commentspages· 5 pts ·106c85a0
New UI Feature
- RADD-1448 Comments and threads: replies open by default, Reply is an action, the composer appears on Comment or Start thread with one submit
On the issue Comments tab (and the same kit on page discussions and inline annotations) three things fight each other:
commentspagesplugin-sdkweb· 5 pts ·8236797d - RADD-1395 The editor has extension points; editor AI is the ai plugin's
The ai plugin is optional, but its editor and issue-page UI is host code: 28 files, about 377 references. - Editor.components/editor/RichEditor.tsxhas 65 AI references. There are also the toolbar AI button,AiSelectionToolbar,AiActionPicker,AiReadMenu(Find similar and Summarize on rendered comments,…
aieditorplugin-sdkweb· 8 pts ·1d0a11d5·f9dc9f87 - RADD-1400 The palette and the query bar take contributed modes; Ask and natural-language SLQ are the ai plugin's
Two AI surfaces are still host code after RADD-1395, and the boundary test freezes them: -CommandPalette.tsx's Ask mode. It sends/search/semantichybrid answers to the palette, under its own mode and keyboard handling. -views/QueryBar.tsx's natural-language ask. It sends/slq/nlnatural-language queries to…
aiplugin-sdksearchweb· 5 pts ·7c79cb5b - RADD-1394 Plugins contribute list columns and card cells; SLA timers are the first
SLA timers are part of the host's own column and card vocabulary, even thoughslasis an optional plugin: -lib/columns.tsdeclares anslacolumn; -components/board/card-cells.tsxrendersSlaRowChipfor anslacell; -routes/view.tsxbatch-loadsslaByItemfor list and board rows; -…
plugin-sdkslasviewsweb· 8 pts ·13b739c3 - RADD-1373 Core modules are static plugins: their UI is bundled into the host and registered at boot; only optional plugins load as remotes
RADD-1353–1366 moved core-module UI (auth, teams, projects, cycles, fields, labels, items, workflow, automations, audit, vcs, timelogging…) into federated remote bundles. Core modules cannot be disabled, so the withdrawal lifecycle never pays off. The costs are real:
kernelplugin-sdkweb· 13 pts ·fbec1008 - RADD-1370 Alertmanager: per-receiver comment, label and resolve-state settings, run by the receiver
RADD-1317 made receivers rows, which was right. It also deleted the three things a receiver did to the issue: an internal comment on every repeat and on resolution, analertlabel on creation, and a move toRADD_ALERTMANAGER_RESOLVE_STATEon resolve. All three now exist only as templates opened in the graph editor.
alertmanagerweb· 3 pts ·c28d422c - RADD-1368 Email: new-ticket receipt and resolution notice are settings again, sent by the desk
RADD-1318 deletedmail_send_ack,mail_ack_bodyandmail_send_resolved, along withsend_ackandresolved.py, and offered the two messages only as automation templates ("Acknowledge new email tickets", "Tell the requester when resolved"). Settings → Email now carries a paragraph pointing at Automations instead…
mailintakeweb· 5 pts ·778d6f9f - RADD-1331 Trigger inspector shows an event's declared payload paths before it has ever fired
Hussein, testing on the dev instance: the trigger inspector shows no example payloads. "What this event carries" (RADD-921) samples only events that have actually fired here (GET /automations/samples/events). A GitLab/Alertmanager/form trigger that has never fired reads "none yet", and it names the subjects without…
automationsweb· 2 pts ·bfdbdb5c - RADD-1255 GitLab pipeline events stamp CI state on linked refs; deployment events mark the ref as deployed to an environment
Child 3 of [[RADD-1252]].
connectorsgitlabvcsweb· 8 pts ·a293557a - RADD-1327 Plugin entities are searchable and #-mentionable (EntitySpec.searchable/mentionable finally read)
EntitySpec.searchable(kernel/specs.py:305) andmentionableare declared (bymilestones/spec.py:17) and read by nothing. - The search indexer handles hardcoded_ITEM_EVENTS,_COMMENT_EVENTS,_ACCESS_EVENTSand_SUBJECT_EVENTS(search/indexer.py:34-45,:95-108). -docs/plugin-platform.md:212-214…
kernelpluginssearchweb· 8 pts ·84f6fb3d - RADD-1316 Automation templates: plugins contribute whole automations, created from "New automation → from template"
The behaviours this epic removes (the Alertmanager comment and resolve, the mail receipt and resolution notice, and the Google Chat fan-out) need a place to live that is off until someone chooses them. Radd has node templates (lib/automation-nodes.ts) but no whole-automation templates. A plugin cannot ship "here is…
automationskernelweb· 3 pts ·8280853e - RADD-1325 The automation editor stops hardcoding plugin nodes: served ports/outputs, and an inspector slot the ai and scripts plugins use
Core SPA code knows plugin node types: -GraphInspector.tsx:332-336importsAiClassifyFieldsandScriptNodeFields(scripts iscore=False), and:353/:359special-caseai.*andscript.*. -node-visuals.ts:116-128computes dynamic ports forai.classifyandscript.decide. -…
automationspluginsweb· 5 pts ·28d76804 - RADD-1329 Block submission / Warn submitter verdict nodes; AI check routes pass, fail, warn, can't check; graphs and versions migrated
See RADD-1313: -ai.validateiskind="gate"but callsadd_finding(ai/automation_node_validate.py:244-248). - The refusal is implicit, computed at the end of the walk from the findings and the trigger'smode(validation.py:101-117). - Thevalidation.fail"Report a problem" node is an ACTION that never…
aiautomationsintakeweb· 8 pts ·1d7aeb19 - RADD-1315 Triggers can opt in to other automations' changes, depth-capped (automation chaining)
The loop guard makes every automation-caused event invisible to every automation. So the issues that "Publish version and sweep" (RADD-1310) moves to Done never reach a rule like "when an issue enters Done, notify the reporter", while the same sweep started by hand does. There is no way to chain rules.
automationsweb· 5 pts ·b83acfbd
Chore
- RADD-1453 Migrations keep the mail settings rows and fail honestly; the deploy doc names every switch this release turns off
Four behaviours switch off silently when the live instance takes this release, and nothing tells the operator:
automationsdocsmailintakemigrationsreleasevcs· 2 pts ·64e3d908·b67a6d96·2cbafc8d - RADD-1466 Test hygiene: the flaky columns proof, the MCP-disabled guard, two lost measurements, and a control-byte check
A flaky proof will block releases.web/scripts/browser-plugin-columns.mjs:183assertsbatches.length === 1("the board shares the list's read of the same rows") right after navigating to the board. In the 31-script CI chain it failed once (the board's batch request landed before the list's cache entry was…
automationsmcpproofstests· 2 pts ·d5f08902·c4364d4b - RADD-1441 One build narrative: move the CLAUDE.md wave history and PLAN.md §8/§11 into BUILD-LOG.md
Flagged by the RADD-1402 audit (I wins 2-3, FLAG). The owner's decision; nothing was changed.
docstriage· 3 pts ·532de8b5·28961a54 - RADD-1467 Magic literals in the wave code become enums and named tunables
CLAUDE.md rule 2: anything that names a behaviour, state or type is aStrEnumor a Settings/dataclass field; tunables live inconfig.py. The review found these in code this diff added:
automationsdashboardsforgejoplugin-sdkvcsweb· 3 pts ·387d5d69 - RADD-1465 SDK: the UI API version records the removed exports, and the plugin docs say what the tree does
RADD-1409 (3b05a92) removed public SDK surface —paletteAnswerQuery,ANCHOR_CONTEXT_CHARS,textNodesOffromindex.ts;SlotId.sidebarNav(sidebar.nav) andSlotId.itemAction(item.action) fromslots.tsx;HostComponents.SchemaFormfromhost-registry.ts— while…
docsplugin-sdk· 1 pts ·515a1fed - RADD-1464 Host pages read the credential-aware admin role through the SDK hook, and the pins bar keys on RoutePath
Two one-instance fixes from the bloat audit left their siblings:
authweb· 1 pts ·77aa6b07 - RADD-1463 Frontend conventions sweep: raw palette leftovers, a native checkbox, radiogroup keys, time-input colour scheme
CLAUDE.md: a raw palette class in new code is a review finding; native form controls are banned in favour of the kit. The review found, in code this diff added or rewrote:
aicommentspagesplugin-sdkslasweb· 2 pts ·56b951fc - RADD-1435 Move the connector scaffolding into vcs: gitlab, github and forgejo share 1,046 duplicate lines
Flagged by the RADD-1402 audit (D2 REDUNDANT 1-6); a design step, not a mechanical cleanup, so it was not done there.
forgejogithubgitlabtriagevcs· 8 pts ·567f8e50 - RADD-1440 docs/modules.md: generate the structural columns from the plugin manifests and cap row length
Flagged by the RADD-1402 audit (I win 1).
docskerneltriage· 5 pts ·51c3777a - RADD-1410 Proof scripts: scaffolding moved into lib, dead and drifted proofs removed or repaired, screenshots ignored
web/scriptsholds 193.mjsfiles, 30,974 lines. Only 5 are build tooling, 24 are CI unit tests and 29 are the CI browser suite; 122 are manual proofs and 63 of those are named by no doc or runner. Statically checked against the route table (645 routes), the router, everydata-*/class/aria/placeholder string and…
proofsweb· 5 pts ·9b0eec59 - RADD-1407 Backend tests: one db fixture and shared factories replace 300 per-file copies, history docstrings trimmed
server/testsis 319 files and 72,547 lines. About 6,000 lines are copies or narration:
tests· 5 pts ·c62ce125 - RADD-1406 Importers, directory, AI and connectors: pre-rebuild remnants, duplicate builders and narration removed
Two audits covered jiraimport, confluenceimport, ldap, sso (91 files, 18,439 lines) and ai, vcs, gitlab, github, forgejo, alertmanager (84 files, 14,667 lines).
aialertmanagerconfluenceimportforgejogithubgitlabjiraimportldapssovcs· 8 pts ·18115047 - RADD-1405 Service-desk, mail, pages and notify modules: dead helpers, duplicate copies and history narration removed
Two audits covered automations, scripts, approvals, slas, forms, csat (88 files, 17,182 lines, 24% prose) and notify, mailintake, pages, collab, attachments (123 files, 21,082 lines, 27% prose). About 5,300 lines are removable without a behaviour change, most of it narration.
attachmentsautomationscollabcsatformsmailintakenotifypagesslas· 8 pts ·b1e8e321 - RADD-1404 Work modules (items, views, workflow, fields, auth, projects, teams, time): dead seams, repeated preambles and narration removed
Two audits covered items, views, workflow, fields, comments, participants, weblinks, linktypes, labels (130 files, 20,621 lines) and auth, projects, teams, groups, cycles, releases, milestones, itemtypes, timelogging, leave, reporting, dashboards (139 files, 21,916 lines). Together about 3,700 lines are removable…
authcommentsdashboardsfieldsitemstimeloggingviewsworkflow· 8 pts ·f322c5e2 - RADD-1409 SDK and plugin UIs: one tsconfig base, a bridge factory, drifted copies merged, wave narration removed
Two audits coveredweb/packages/plugin-sdkand everyserver/src/radd/modules/*/uipackage (560 files, 44,760 lines) plus the build tooling andexamples/. About 4,200 lines are removable.
aiautomationsjiraimportmailintakepagesplugin-sdkweb· 8 pts ·3b05a926 - RADD-1408 Host SPA: dead queries and types, duplicated helpers and comment narration removed
Two audits coveredweb/src(437 files, 67,342 TS lines plus 1,123 CSS). No whole file is dead: every file is reachable frommain.tsx,router.tsxor a plugin UI. About 2,700 lines are removable, plus ~175exportkeywords on symbols used only in their own file.
web· 8 pts ·3e308331 - RADD-1411 Docs and research: run evidence and one-off notes removed, dated reviews moved out of docs, stale claims and spec supersessions fixed
The tracked prose is 46.5k lines / 3.85 MB. A reference checker pulled every backticked path, identifier, route and setting key out of each doc and checked it against the tree.
docs· 5 pts ·eb46583c - RADD-1403 Kernel, spine and infra modules: dead protocols, duplicated registry loops and history narration removed
The audit ofserver/src/radd/kernel/,server/src/radd/*.pyand the infra modules (pluginmgr, events, settings, capabilities, realtime, webhooks, mcp, search, access, backup, monitoring, audit, screens, avatars, canned) read 145 files, 18,072 lines, of which 4,414 are comments or docstrings. About 1,950 lines are…
accessbackupeventskernelmcppluginmgrsearch· 5 pts ·61919241 - RADD-1412 Repo hygiene: generated, machine-local and session-only files untracked and ignored
Someone cloning the repository should get the product and its record, not artefacts of one machine, one session or one assistant's workflow. Today the working tree carries untrackeddocs/campaigns/,docs/tutorials/,research/review-2026-09-16/and 24 proof screenshots underweb/scripts/with no ignore rule,…
docstooling· 2 pts ·82dc347a - RADD-1350 Verify the complete ownership inventory and document architecture
Reconcile every inventory entry against authoritative source and tests after remediation. Run boundary, focused/integration and built-browser verification across lifecycle and saved-content cases, update local app preserving plugin choices, document justified exceptions and remaining blockers. Completion requires all…
triage·3b812147 - RADD-1401 The public survey page is the csat plugin's, and email-comment rendering is mailintake's
The RADD-1350 sweep (host string literals vs every optional plugin's route words) left two real residues after RADD-1377–1400: - The public survey page.web/src/routes/public-csat.tsxis the tokened, UNAUTHENTICATED page a requester reaches from the survey email. The host holds its route,apiPublicCsatPath, the…
csatmailintakeweb· 3 pts ·11c2b15b - RADD-1397 Co-editing's UI is the collab plugin's
Thecollabplugin is optional (spec 122), yet its client lives in the host: -components/editor/collab/{provider,model,useCollabSession,EditingNow}.ts(x); - 38 references inRichEditor.tsx; - the wiring incomponents/pages/PageView.tsx/PageEditPanel.tsx: the elected saver, Done replacing Save, and EditingNow…
collabeditorweb· 5 pts ·841cf418 - RADD-1396 The SLA settings page and queue views are the slas plugin's
After RADD-1386 (the report) and RADD-1394 (columns and cells), the host still carries the rest of the service desk's SLA UI: - Project settings.routes/project-settings/sla.tsx,components/settings/SlaPolicyForm.tsxandSlaMetOnField.tsx: policies, business hours and priority first-match. - Queue views.…
slasweb· 5 pts ·bde1a8ee - RADD-1392 Pages is a core plugin, and the wiki's UI is the pages package
Decision (Hussein, 2026-09-26). The wiki is core, not optional.
pagesplugin-sdkweb· 8 pts ·1e30d63a - RADD-1393 Dashboards is a core plugin; its UI and My Work's canvas are the dashboards package, and plugins contribute My Work widgets
Decision (Hussein, 2026-09-26). Dashboards is core. My Work, the home page, is built on it.
approvalsdashboardsweb· 5 pts ·13be95be - RADD-1349 Audit backend service seams and plugin background lifecycle
Review every backend module and shared service for cross-module internal imports, hidden dependencies, stale contributions, queued/in-flight/background work and disable/re-enable behavior. Replace violations with public service or contribution contracts, preserve data and permissions, and test dependency and runtime…
triage·98d482bf - RADD-1387 Automations and storage routing stop reaching into leave, mailintake, participants and ai
Two core modules call optional plugins directly.
aiattachmentsautomationsleavemailintakeparticipants· 3 pts ·0a9e7fd2 - RADD-1385 Notify learns page audiences, participants and the mail transport from their plugins
notify is core, but it hardwires three optional plugins: - pages:pageevents.py,targets.py,options.pyandprefs.py, plus a TOP-LEVEL import ofpages.page_access.guard_pageinauthorization.py. Page comment, mention and watcher notifications, the space-scoped targets and the space options are all written…
mailintakenotifypagesparticipants· 5 pts ·8cbb3a95 - RADD-1384 Search sources are contributed: pages brings wiki results, ai brings semantic candidates
The coresearchmodule imports two optional plugins directly: - pages:router.py,deflect.pyandsemantic.py, for page results, KB deflection and semantic page hits; - ai:deflect.py,semantic.pyandservice.py, for embedding candidates.
aipagessearch· 3 pts ·c8c54879 - RADD-1386 The SLA report belongs to slas; reporting stops importing slas and csat
reporting/service.pyis core, but it importsslas.reportandcsat.reportat module TOP LEVEL. The wholesla_report(per-item SLA state folds, weekly buckets, CSAT averages) is service-desk logic that lives in reporting because of where it started. The host reports page renders it the same way.
csatreportingslas· 3 pts ·a216d8cc - RADD-1390 No host edit per plugin page: settings sections say where they live, and nav icons come from the one icon registry
After the settings moves (RADD-1378–1382), three host-side lists still have to be edited whenever a plugin gains a settings page: -INSTANCE_HOMED_SECTIONS(web/src/lib/types/settings.ts) names the settings sections that ldap, ai, mailintake and sso declare. Settings → General renders its rows by SUBTRACTION, so a…
groupssettingsweb· 2 pts ·e5fec2f3 - RADD-1383 Approval gates are a transition check the approvals plugin contributes
approvals is optional, yet the core workflow and items modules hardcode it: -workflow/types.pynamesTransitionCheck.REQUIRE_APPROVAL, andguards.py/transitions.pyvalidate and evaluate it. -transitions.py:569importsapprovals.servicefor the snapshot. -items/service/core.py:298and…
approvalsitemsworkflow· 5 pts ·573c8db2 - RADD-1380 Settings → Sign-in is the sso plugin's page
sso is optional (core=False) and has no UI package. Its settings page lives in the host: -web/src/routes/settings/sign-in.tsxpluscomponents/settings/signin/*(4 files, ~700 lines): the provider registry, starting access, provisioning rules, the signup allowlist and the test probe; -lib/types/sso.ts,…
settingssso· 3 pts ·50a5b48b - RADD-1382 The Jira and Confluence importers own their pages; Import data is a nav group, not a host page that names them
Both importers are optional plugins with no UI package. The host carries their UI: -routes/settings/jira-import.tsx+components/settings/jira/*(11 files, ~3,300 lines); -routes/settings/confluence-import.tsx+components/settings/confluence/*(5 files, ~1,400 lines); - their types, queries and API paths in…
confluenceimportjiraimportsettings· 5 pts ·6eff089f - RADD-1378 Settings → Email is the mailintake plugin's page
mailintake is optional (core=False), but its whole configuration surface lives in the host: -web/src/routes/settings/email.tsxandcomponents/settings/email/*(11 files, ~1,500 lines): sources, senders, routing rules, signatures and automatic messages; - its query definitions, types and API paths, in the host's…
mailintakesettings· 3 pts ·8222e404 - RADD-1381 Settings → Directory is the ldap plugin's page
ldap is optional (core=False) with no UI package, yet the host carries all of its settings UI: -web/src/routes/settings/directory.tsxplusDirectoryGroupsSection,MirroredGroupsSection,DirectoryImportDialogsandDirectoryImportReview, about 1,200 lines: the connection, sync status and schedule, group…
ldapsettings· 3 pts ·f7f17c75 - RADD-1379 Settings → AI is the ai plugin's page
The ai plugin is optional and already ships a UI remote, but only for health cards and inspectors. Its settings page is host code: -web/src/routes/settings/ai.tsxpluscomponents/settings/Ai{Features,Presets,Providers,Roles}Section.tsx, about 1,000 lines covering providers, model roles, feature toggles and…
aisettings· 3 pts ·2e273764 - RADD-1377 Plugin settings pages reach the host's settings editor, change history, role grants and toasts through the SDK
Six settings pages belong to OPTIONAL plugins but still live in the host: Email (mailintake), AI, Sign-in (sso), Directory (ldap), Jira import and Confluence import. That is about 9,000 lines, imported byweb/src/router.tsxwhether or not the plugin is loaded. A remote cannot take them over yet, because it can only…
plugin-sdksettings· 3 pts ·1bd538ea - RADD-1375 Delete the compatibility re-exports the isolation moves left behind
RADD-1351–1366 moved code into the SDK and plugin packages and left a forwarding file at every old address, "so existing consumers keep working". The standing rule is no backwards-compat shims until V1. The reviews counted about 40.
plugin-sdkweb· 3 pts ·fbec1008 - RADD-1366 Contribute VCS settings and connector-owned configuration UI
The host still enumerates Forgejo/GitHub/GitLab, owns their configuration, queries and transport, and directly renders VCS identity mapping. Move the shared version-control settings workflow into VCS and provider-specific declarations into their connectors through a public VCS contribution contract. Remove host…
8 pts ·8703df10 - RADD-1374 Isolation ledger: keep the module table, drop the per-file hash JSON and its CI gate
research/plugin-isolation/{inventory,review,retired}.jsonis about 4 MB of per-file hashes committed to git. Theisolation-inventoryjob inchecks.yaml(reused bypublish.yaml) fails when any tracked byte changes without regenerating them. - So every PR (a docs typo included) and every release tag must commit…
cidocs· 1 pts ·4e4550f5 - RADD-1365 Move complete automation editor and settings surfaces into Automations
The canvas and schedule already belong to Automations, but the host still owns the full rule editor, inspectors, runs/versions, dry runs, settings and integration policies. Queries and preview seed discovery cross owner boundaries; integration policy matching guesses from display groups. Move the remaining…
8 pts ·0dcd64aa - RADD-1364 Move Audit pages and history contributions into Audit with exact scope access
Audit UI, queries and settings footers remain host-owned; ChangeLines applies Items vocabulary to other entities. The UI guesses audit access from global.manage or any managed project, while the backend requires instance admin or the exact project. Move Audit page/history/footer and transport/types to its remote,…
5 pts ·a8d2b7b8 - RADD-1363 Move audit entity destinations to their owning plugin contracts
web/src/lib/audit.ts centrally hardcodes more than forty entity destinations spanning settings, project settings, Items and Pages. Its links survive provider disablement because row rendering does not consult current owner availability. This prevents Audit UI from becoming an isolated consumer. Introduce a small…
5 pts ·01450cf5 - RADD-1362 Isolate scheduling UI and previews between Automations and Backups
The host ScheduleEditor calls /automations/schedule/preview even in Backups and shows automation action instructions there. Its preview only ignores late results; it does not abort requests or hide the preceding result immediately after a draft change. Actual backend ownership is shared radd.schedule arithmetic,…
5 pts ·d3d361fd - RADD-1361 Contribute field and label catalog queries with plugin-owned lifetimes
Automation usePickerData calls host fieldsQuery/labelsQuery regardless of owner remote availability. Empty or stale catalogs can appear after owner withdrawal or failed loading, while saved custom-field selections appear blank. The platform needs a nonvisual query contract; rendering slots should not wrap data-only…
5 pts ·7a74ad94 - RADD-1360 Contribute custom-field form controls from Fields
CustomFieldsForm and CustomFieldControl live under host issue components, even though Fields owns their type rules and wire values. Automations and intake forms import them from Items. TokenMultiSelect and ErrorText are generic primitives needed by the owner and currently host-only. A saved single-select value absent…
3 pts ·300cbbd6 - RADD-1359 Contribute team relationship selectors and audience editor from Teams
TeamSelect in web/src/components/teams owns an independent saved-reference query; TeamAudience owns reference paging/counts and selection state outside the Teams lifecycle. Both survive owner withdrawal. TeamAudience also defaults to comment-specific copy despite cycle/SLA callers.
3 pts ·aea987c7 - RADD-1358 Contribute project and cycle pickers from their owning plugins
ProjectSelect/ProjectPicker and CycleSelect/CycleChoices currently live in host UI, with host-owned directory queries and cycle status vocabulary. They are dependencies of automation forms and many other pages. Move full picker implementations, relevant wire types/query definitions and cycle presentation into…
8 pts ·f834a075 - RADD-1357 Move directory option providers from host controls into their owning plugins
Confirmed host DirectoryChoices.tsx and queries/options.ts hardcode twelve option resources, labels, endpoints and cache metadata used by automation inspectors and access/settings forms. Move option contributions to Auth, Teams, Workflow, Itemtypes, Releases, Forms, Pages and Groups, using generic SDK option controls…
8 pts ·d86c70dc - RADD-1356 Remove automation and Scripts dependencies from shared schema and code controls
Confirmed in web/src/host-components.tsx: the public SchemaForm imports components/automations/SchemaFields, which depends on automation-node helpers, and CodeEditor imports components/scripts/PythonEditor. The latter ignores the SDK language prop, closes over an old onChange, and imports the Markdown editor solely…
5 pts ·0e908620 - RADD-1355 Make the isolation inventory cover repository source and build artifacts
RADD-1354 exposed a concrete blind spot: scripts/plugin_inventory.py scans four application roots and four suffixes, omitting SDK/build .mjs files, migrations, tooling, packaging and deployment configuration. The current 1497-file scan cannot prove complete codebase coverage. Expand discovery to account for every…
3 pts ·0704d9b8 - RADD-1354 Move automation graph rendering and scoped node shapes into Automations
Confirmed in GraphCanvas.tsx and lib/node-shapes.ts: the host owns the automation canvas and graph algorithms; node shape results live in process-wide mutable maps, requests omit cancellation, and canvas refresh compares catalog lengths rather than content. Move renderer, graph contracts/helpers and shape queries into…
5 pts ·6525dce8 - RADD-1353 Contribute directory pickers from Auth and Teams through a generic SDK control
VCS settings migration is blocked architecturally by a host-owned PeopleDirectorySelect: it owns Auth directory and Teams candidate queries, modal/paging behavior and endpoint branching. Move directory choice providers into Auth/Teams UI remotes, served through a generic SDK DirectorySelect contribution contract.…
triage· 3 pts ·50a8600a - RADD-1352 Move Scripts and Monitoring settings into their owning plugins
Host routes directly own Scripts/Monitoring settings and their queries/types. Move implementations into module UI remotes through settings.page contributions and manifest navigation, preserving package/interpreter forms, monitoring polling, permission/history links and deep links. Monitoring AI coverage must be…
triage·8eb30fa3 - RADD-1351 Provide shared settings UI contracts and truthful plugin page lifecycle
Settings migration exposes missing public layout/control contracts, separate capability caches, plugin-page endless spinners on missing/failed remotes, and slot render callbacks executed outside their error boundary. Add generic SDK contracts backed by existing platform primitives, shared date formatting,…
triage·11f9826b - RADD-1345 Move person status and timesheet annotations into plugin contributions
Leave settings now use slots but PersonName, Avatar and timesheet still import Leave queries/types and implement Leave-specific presentation. Introduce typed data contribution contracts with owned runtime cleanup; move leave queries and behavior into its remote. Verify disabled initial state, live withdrawal,…
triage·c3db093c - RADD-1344 Inventory and enforce module ownership across backend and frontend
Enumerate every backend module, frontend file, declared dependency, UI remote and contribution, host/plugin integration and import edge from current source. Maintain explicit review/remediation/verification status with evidence. Add executable boundary safeguards and keep inventory synchronized through subsequent…
triage·7d90df1f - RADD-1339 Land the completed automation and VCS review corrections
Prerequisite for the September 25 usability work: the earlier user-requested automation/VCS reviews were implemented and verified in this working tree but not yet committed. Preserve those corrections as a separate commit so the later dashboard/signature migrations have their required migration ancestry.
triage·bca48bfc - RADD-1328 SDK exports what a plugin event consumer needs; docs stop claiming what isn't built
The SDK is missing the consumer API.radd/sdk.pyexports onlyread_eventsandemit_event.get_offset,set_offset,offset_existsandevents/runner.run_head_seededare not exported, so a third-party consumer imports module internals. - Realtime narrowing is hardcoded. Record-local narrowing uses a fixed…
docseventsplugins· 2 pts ·29554451 - RADD-1319 Retire the Google Chat env fan-out; a "Post to chat" template replaces it
googlechatis a second, env-only fan-out: a webhook URL and a list of event types inconfig.py:465-466, consumed bygooglechat/consumer.py:28-44. It has no project scope and no UI, and it runs outside automations. Automations already have a Post to chat action (PlanKind.HTTP/post_chat).
automationsgooglechat· 1 pts ·ab12e117
Changes from v0.48.0 to v0.49.2.