feat: let an environment publish themes as a file - #187
Merged
Conversation
(cherry picked from commit c1c2d5401de5a352cf6722959de076c3da63d233)
Pylon's theme exporter has written `version: 2` since PR #172 retired the `statusActive` and `statusInfo` roles, but the adopted `EnvironmentThemeFile` schema only accepted `version: 1`. A theme downloaded from Pylon and dropped into `themes/` was rejected by the watcher and by `t3 theme set <file>`, so the feature could not round-trip Pylon's own output. The schema now accepts `1` and `2`; unknown roles are already dropped client-side by `lenientThemeColorOverrides`, so a v1 file carrying the retired roles still loads. Also rewrites the adopted product copy for Pylon: the CLI's invalid-file hint, the environment-theme user doc (including the runtime home, now `~/.pylon-code/userdata/themes/`, and Pylon Mobile), the glossary Appearance entry, and the contracts JSDoc. `t3 theme`, `T3CODE_HOME`, and `.t3` stay as compatibility identifiers. The glossary's new link references are renumbered to 27 and 28 so they do not collide with Pylon's existing 25 and 26.
The publishing section said the themes directory is `~/.pylon-code/userdata/themes/` "by default", which only holds for a server the Pylon app started. A server started from the command line without `--base-dir` or `T3CODE_HOME` resolves a different home, so the stated path would send someone to a directory their server never reads. Scopes the path to the app-started case, says plainly that a command-line server uses the base directory it was given, and points at `t3 theme show` as the way to have the server name that directory itself. Changing the command-line default is a separate maintainer decision and is not touched here.
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Themes lived only in each client's local storage. There was no way for a machine to provide a theme — for a team to ship one, or for a Linux desktop to keep Pylon in step with the system theme — and no way for an environment to set a default.
Fix
Adopts upstream
#8569(c1c2d5401) from thef94a0d646..1f8ed54adT3 review, plus one adaptation commit and one doc fix.A machine drops JSON theme files into
<stateDir>/themes/. The server watches that directory (debounced, capped at 32 files / 32 KB each / 192 KB total, symlinks refused viaO_NOFOLLOW, built-in and reserved ids rejected) and streams the set to subscribers as a newenvironmentThemesUpdatedevent onsubscribeServerConfig. Web and desktop render each as a non-editable card in the theme library with a Duplicate action. A newt3 theme set|clear|showCLI recordsdefaultThemeinsettings.json; clients adopt it once per generation, with the guard persisted so a reload never re-applies.Compatibility: the event is emitted only to subscribers that pass
environmentThemes: true, so older clients see an unchanged payload; the client projection strips themes on reconnect to a server without the capability. Mobile does not request the stream and the user doc says so.Pylon adaptations
EnvironmentThemeFileaccepts onlyversion: 1; Pylon's exporter has writtenversion: 2since PR fix(clients): restore upstream status visuals #172. Without the change a theme exported from Pylon was rejected by both the watcher andt3 theme set <file>. The contract now accepts[1, 2], with tests on the watcher and CLI paths for a v2 file and for a v1 file carrying a retired role (which still loads becauselenientThemeColorOverridesdrops unknown roles).docs/internals/glossary.mdlink refs[25]/[26]were already taken in Pylon; upstream's became[27]/[28]. All 28 refs verified to resolve.~/.t3/userdata/themes/rewritten across the CLI help, user doc, glossary, and contract JSDoc.t3 themeandT3CODE_HOMEprecedence are compatibility identifiers and stay.~/.pylon-code/userdata/themes/to a server the Pylon app started, and says a command-line server uses the base directory it was given. That is becauseresolveBaseDirstill defaults to~/.t3for a CLI-started server while the desktop resolves~/.pylon-code— a pre-existing fork-wide inconsistency this feature is the first user doc to depend on. Maintainer decision needed, separately: change the CLI default fork-wide, or leave it as compatibility behaviour.Verification
vp test runacross the nine specified files pluscli/theme.test.ts— 281 passed, 1 failed. The failure is upstream'senvironmentTheme.test.ts > "streams a set for every change to the directory", which waits on a realfs.watchevent;fs.watchdelivers no events on this macOS host for any directory (confirmed with plain Node, sandboxed and not), and the test file is byte-identical to upstream. CI is Ubuntu/inotify and should be green — confirm on the first run.t3,@t3tools/web,@t3tools/client-runtime,@t3tools/contracts,@t3tools/mobile) clean; lint and format clean on all 32 files.O_NOFOLLOW/fstat-before-read/size-cap ordering, the id pattern that excludes path separators, thews.tsmerge (24/2, no Pylon branch lost), the reconnect strip, and the persisted adoption guard.t3 theme setagainst a running server, and reconnect to an older server.Claude Fable 5 in Pylon.
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.