- library/components/WARNING.md, library/dashboards/README.md and
documentation/contributing/README.md taught "graduate into the library at the second
consumer". They now teach the plugin-designer skill's rule (section 3): a component that
could serve more than one map is built once in library/, driven by props, and landed through
the build owner; one-off or experimental pieces stay in a map's folder; a new pattern is a
pilot, then approved, then rolled out. The contributing guide's "full reasoning" link pointed
to an index without it; it now points to the skill.
- The app shell doxa-maps-spa is labelled Deep Research. Ten docs still called it the Research
Gallery (15 mentions): DEPLOY.md, the desktop how-to, embeddability, develop-a-plugin,
reference-universal-props, reference.md, the shell's EMBED.md, and the plugin-designer skill
with two of its references. Identifiers (doxa-maps-spa, branch and route names) are unchanged;
README.md is not touched.
- The clone examples in README.md and documentation/DEPLOY.md name a private server; they
now read `git clone --depth 1 <your-repo-url>`.
- skills/plugin-designer/references/backend.md quoted a planning heading that names a
platform; it now says the tiers are recorded "as an open, unproven assumption".
- The desktop app (Tauri; Rudder runs as one) works: the capability table's Desktop column
is ✅, and the outputs table, the Output 3 heading and its screenshot's alt text say so.
The WordPress column keeps 🧪, so the table's legend is unchanged.
- delegation-model.svg: the desktop output's label reads WORKING, in the green of the other
two outputs. delegation-model.png is re-rendered from it at 2x in Chromium. Rendering the
previous SVG the same way reproduced the committed PNG with 0 pixels different, and the
new render differs only inside the desktop box. The PNG carries only IHDR, IDAT and IEND.
THIRD-PARTY.md's two open licensing items "need an owner's decision" instead of going to a named person.
needs-eyes describes the browser policy and a maintainer's laptop as the second pair of eyes. The
skill and its glossary say the Experimental section was replaced by capability tiers, with the same
pointers into plugin-studio.vue. grep -w Driver over documentation/ and skills/ is now 0;
check:no-new-driver-references passes.
The joining page, DEPLOY and the laptop sync default moved to development in the
commit before this one. This finishes the move and closes what a fresh clone's
friend test found.
- landing-preconditions diffs against origin/development when no landing branch
is exported, instead of main.
- CLOUD-DEVELOPMENT-ENVIRONMENT, the plugin-designer skill (SKILL.md, workflow,
glossary) and the shared dev server's notes land on and follow development;
the skill says never to push to main.
- The sync fetches with the laptop's own credentials. git runs with prompts off,
so on a clone with no credential helper it failed every interval with a bare
"fetch-failed / remote: Unauthorized", which read as a broken server. That case
is now its own state, needs-credentials: the log (once, not every tick) and
/api/dev-sync say "dev-sync needs git credentials for <remote>". The joining
page and .env.example say so, and that a fresh clone starts on main and must
switch to development before the sync can fast-forward it.
Measured in scratch repos: the private remote with no helper gives
needs-credentials and one warning over two ticks; a local remote with no
DX_SYNC_BRANCH follows development and fast-forwards; a missing remote stays
fetch-failed.
skills/plugin-designer/references/i18n.md, beside backend/glossary/targets/workflow. Every example is
real code with a file and line, and every claim was checked against main rather than written from
memory — a reference that is wrong costs more than no reference.
★ ONE CORRECTION TO THE BRIEF, and it matters for whoever reads this next. The ask named poster-wall.vue
as the fleet's `<i18n-t>` example. It is the opposite: that file's comment explains why `<i18n-t>` could
NOT be used there — the string is a prop rendered by a library component with no slots — and there is no
`<i18n-t>` usage anywhere in the tree. So the rule is written as "compose the parts, do not reach for
i18n-t", which is what the code actually does and what a plugin author can actually follow. Telling them
to use a component the codebase has never used would have sent them down a path with no example to copy.
The rules: one key per SENTENCE with named placeholders (the Hindi tail case, where "." in English is
" प्रार्थना करते हुए।" in Hindi and a wrapper would have dropped it); label form for counts while there is
no pluralRules layer; compose markup from escaped parts; dir="ltr" for deliberate English so the gate can
tell it from a leak; te()/proxy-t fallbacks are NOT leaks and must not be "fixed"; no resolved labels at
module scope (getters, or the first locale freezes); a namespaced translator hides the prefix from every
scanner; and the two gates that cover your code rather than the catalogue.
Rule 8 carries the precision dx-shepherd gave me today: check:hardcoded-english is ON DEMAND, and
gates:pre runs only its self-test — so an author who assumes the suite covers it will land leaks.
skills/ is shared, so this is a source sha for studio rather than something I land.
A plugin's <profile>.meta.json targets (web, mobile, desktop, widget; absent = web)
now decide where it is built. internal/plugin-targets.mjs is the one reading.
desktop:build builds a desktop plugin into .desktop/<plugin>/ with a page that
names its engine, builds its backend as a Tauri sidecar for this machine, and runs
tauri build with a --config override; tauri.conf.json and public/ are untouched.
The shell starts the bundled rudder-engine (RUDDER_AUDIO=browser, RUDDER_HOME in the
app data folder) and stops it on exit. A plugin whose targets leave out web
(Rudder: desktop + widget) is no longer built for the web tree: run-parallel,
generate-tree and check-composite-freshness skip it, and its public/ folder is
removed; the dev server still gives the Studio its corner. check:targets
(gates:pre, with a self-test of five planted violations) validates the values,
widget corners and backend folders and fails if a non-web plugin reaches the built
tree. Measured: desktop:build rudder-voice on Linux produced Rudder_0.1.0_amd64.deb
(8.8 MB) with the app and the engine side by side; the app has not been launched.
SKILL.md claimed new plugins land in a Research Gallery Experimental section.
That section was replaced by capability tiers (plugin-studio.vue:630); stage is
now a label prefix, not a place. Both stale lines corrected.
Adds what the skill never said:
- capability is DERIVED from composes and an explicit type is CHECKED against it
(check-capability-derived.mjs), with its two traps;
- rail labels come from meta, and check-studio-rail.mjs:68 fails a bare id;
- presets merge OVER the profile's meta config, key by key -- rule 3 of
documentation/PRESET-PLUGIN-STANDARD.md, asserted by check:preset-config-merge
(generate-tree.mjs:1094, the comment there records the pinHint bug);
- targets is read (profile-meta.mjs:28) and consequential: the Research Gallery
skips a bundle that does not list web (doxa-maps-spa.vue:605).
Depth moves to references/: glossary, targets, backend, workflow. backend.md
carries the PocketBase user tiers marked DESIGN INTENT, NOT BUILT -- quoted
rather than linked, because their source lives outside this repo.
Verified against this tree, rebased on main: 61 path citations resolve, 10 line
citations land on the code they claim.
README: one line pointing an agent at the skill.