Repository navigation
Require OpenStation — the desktop is the product - #14
Merged
Merged
Conversation
The plugin was built shell-optional, but the builder was never anything except an OpenStation window, and a plugin that quietly ships a lesser version of itself teaches nobody what it actually is. `Requires Plugins: desktop-mode` lets WordPress 6.5+ enforce the dependency at activation and keep the shell from being deactivated underneath us. The function_exists gates in shell-api.php stay as defense in depth: an older WordPress or a force-removed shell gets an admin notice naming the fix, and published forms keep rendering — a missing admin dependency must never take down somebody's front end. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0119U4sRRWGcTQdwYreTwpAp
A fork that stripped the dependency header used to inherit a quietly lesser builder mounted on a plain admin page — misrepresenting what this plugin is. The builder, entries, analytics and Theme Studio pages now render an explanation and an install link when no shell is on the site; Import keeps working, and published forms never stopped rendering for visitors. And one product wears one name: the windows are AllTerrain Forms, AllTerrain Forms — Entries, — Analytics, — Theme Studio; the commands and the admin menu say AllTerrain Forms too. The dock tile's flyout rows stay short — they already sit under the branded tile. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0119U4sRRWGcTQdwYreTwpAp
The directory listing now leads with the phrases people actually type — contact form, drag and drop form builder, multi-step forms, conditional logic, surveys, quizzes — in the title, the tags, and a heading per feature, with an FAQ phrased as the questions get asked. Everything it claims stays true, which is the part of SEO nobody can take away. Four screenshots are new, captured live off the OpenStation desktop: the builder window, the Theme tab wearing Neon with its instant preview, Entries with a submission open, and Analytics with its NPS panel. The conditional-logic and merge-tag shots stay, renumbered. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0119U4sRRWGcTQdwYreTwpAp
An empty themeOverrides map serialises from PHP as [], so the schema arrived holding a real Array. Every token written into it by name was a stray expando property JSON.stringify silently drops — the preview showed the override, the autosave lost it, and the control snapped back the moment the saved schema was adopted. Repaired at the API layer, the single door every form response walks through, so no caller can meet the Array again. Four regression tests pin the shape. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0119U4sRRWGcTQdwYreTwpAp
The first captures used whatever positions the session had left the windows in, which put them in a corner and made the desktop look like an accident. Recaptured with each window placed deliberately: builder centred, entries cascaded over it with a submission open, the Theme tab wearing Neon, analytics on its own. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0119U4sRRWGcTQdwYreTwpAp
…re/openstation # Conflicts: # assets/js/analytics.min.js # assets/js/builder.min.js # assets/js/entries.min.js
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0119U4sRRWGcTQdwYreTwpAp
The Theme tab's server re-render is gone. It existed to "reconcile" what the inline paint had already shown, and what it actually did was blink the preview, reset both scrollbars and wipe anything typed into the test form — to arrive at the same pixels. Every token is either a custom property or one of two structural classes (atf-labels-*, atf-fields-*), and a theme switch adds only atf-theme-* and the dark flag; all of it is known client-side, so all of it is painted in place, the same tick it is clicked. The server renders the preview once, at mount. The dials stopped rebuilding themselves too: a click now flips is-on in place instead of replacing the very button under the pointer, the 69-token Advanced list syncs off the click's critical path with its scroll preserved, and the builder's post-autosave rebind — which was remounting the whole studio for the benefit of field cards the Theme tab does not have — no longer runs outside the Build tab. Verified against the reported sequence with a MutationObserver on the preview: two edits spanning two autosaves, zero structural mutations, zero preview round trips. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0119U4sRRWGcTQdwYreTwpAp
WordPress's Abilities API is how a site describes what it can do to AI agents and MCP clients; this registers the forms' whole working surface there. An agent can list forms and read their questions, learn the field-type vocabulary, build a form from a loose description and get its shortcode back, apply a theme, submit answers through the same validated anti-spam pipeline a visitor uses, query entries with the labels resolved, and pull the analytics report as structured data. None of them grows logic of its own — each is a thin adapter over the functions the windows and the REST API already call, so an agent and a human clicking the same button get the same behaviour, the same validation and the same capability checks. The descriptions are written for the agent that reads them: what it returns, and when to prefer it. One honest liberty, documented where it happens: submit-form mints a valid time-trap signature stamped a minute in the past. The trap hunts bots that post faster than a human reads; an authenticated agent invoking a described ability is not that traffic. Everything else — honeypot, rate limit, blocklist, Akismet, validation — runs untouched. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0119U4sRRWGcTQdwYreTwpAp
The abilities existed in docs/abilities.md and as a paragraph of prose; neither readme said their names or what each one does. Now both do: the directory listing gets the named list, and the repository README gets the table, so an agent's owner can see what their assistant will call before installing anything. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0119U4sRRWGcTQdwYreTwpAp
Floating positioned every label absolutely — including a radio group's legend, a scale's heading and a signature pad's label, none of which have a field to float into — so choosing it painted questions straight across their own answers. And the lift never fired for anyone: the selector expected the label after the input, and the renderer has always emitted it before. Floating is now scoped to the twelve types a label can sit inside of. Text-shaped inputs lift on focus or value, told apart by :placeholder-shown against a reserved single-space placeholder the renderer now actually emits (the stylesheet had been promising it for some time). Selects and date inputs, which are never visually empty, keep their label permanently lifted — the only honest float for them. The lift rises into headroom reserved above the input rather than straddling its top border, because a border-straddling label needs a background mask and no one mask survives ten themes of gradients and glass. Every other type keeps its label on top, untouched. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0119U4sRRWGcTQdwYreTwpAp
The canvas paints the form's theme tokens onto the field previews, but a dark theme's text colours assume the theme's own background — and the cards are builder-white, so Midnight's near-white labels vanished into them. The server marks dark themes on the form it renders; the canvas previews are builder-built and never carry that class, so the flag is hoisted onto the builder root and every preview paints its ground from it — the same #101418 the Theme tab's frame already uses. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0119U4sRRWGcTQdwYreTwpAp
# Conflicts: # readme.txt
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.
What
A deliberate product pivot: OpenStation goes from optional to required.
Requires Plugins: desktop-modein the plugin header (+Requires at least: 6.5, the version that introduced plugin dependencies). WordPress now installs/activates OpenStation alongside this plugin, refuses activation without it, and blocks deactivating the shell underneath us.function_exists()gates inshell-api.phpstay — reframed as defense in depth, not a supported mode: on an older WordPress or a site that force-removed the shell, admins withactivate_pluginsget an error notice linking to the fix, and published forms keep rendering on the front end — a missing admin dependency must never take down a visitor-facing form.Why
The builder was never anything except an OpenStation window; the drag-between-forms, media-onto-choice, entries-onto-other-apps interactions are the product. Shipping a quietly lesser shell-less version taught users the wrong thing about what this plugin is.
Tests
requiresOpenstation.php): the header declares the dependency, the notice renders for admins on shell-less sites, stays silent for non-admins, and is actually hooked.🤖 Generated with Claude Code
https://claude.ai/code/session_0119U4sRRWGcTQdwYreTwpAp