doxa-maps/skills/plugin-designer/references/workflow.md
Doxa Maps 1ca78d6d5d A laptop that follows the table says when it needs credentials, and the last main defaults say development
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.
2026-09-29 00:59:14 +00:00

4.3 KiB

The workflow: empty folder to landed on development

1. Develop in the Plugin Studio

bun install          # once
bun run dev          # the Plugin Studio at http://localhost:5173/
  • Your plugin appears in the studio as soon as its folder exists; edits reload live.
  • One screen on its own: http://localhost:5173/__leaf/<your-plugin>/<screen>.
  • Test the universal props from the studio header: switch the engine, the language (include Arabic), and the token (none, a token, a token service). Your plugin must work in every combination — that is the point of the header.
  • bun run check:dev-assets checks that every map's data files load under the dev server.

Your plugin's rail entry comes from <profile>.meta.json "label", and bun run check:studio-rail fails a bare id. Give it a human name.

2. Build

BUNDLE=<your-plugin> bun x vite build      # just your bundle → public/dx-maps/<your-plugin>/
BUILD_ALLOW=1 bun run build                 # every bundle, the tree, the manifest, the studio

The full build rewrites every plugin's output. It refuses to run without BUILD_ALLOW=1, and on a team one agent owns it. Build only your own bundle unless you are that agent. public/dx-maps/manifest.json then lists your plugin with ready-to-paste embed snippets.

3. Check

Run the gates that cover what you touched. The ones most often relevant:

Gate What it protects
bun run check:i18n-parity every new key exists in all 11 catalogues
bun run check:i18n-never-translated a key that was copied rather than translated
bun run check:capability-derived your declared type agrees with what you compose
bun run check:studio-rail your rail entry is a label, not a bare id
bun run check:embed-targets the embed targets in the manifest exist
bun run check:dev-assets data files load under the dev server

package.json holds the full list; they are all prefixed check:.

4. Land it on development

development is where everyone lands; main is production and moves only when development is merged into it, so never push to main.

Three commands, in this order, every time:

git add -A && git commit -m "what you changed"
git pull --rebase origin development
git push origin HEAD:development

A rejected push is normal, not an error. Someone landed first: run the middle command again and push again. In a ten-writer stress test at a far faster rate than a human works, 95% of pushes were rejected and retried, zero became merge conflicts, averaging 1.1 retries per edit (documentation/HOWTO-join-the-table.md).

That result is the one-folder-per-person rule paying off: everyone pushes to one branch, so you collide on who goes first, never on the same lines. A real conflict means two people edited one file — stop and talk to them; that is a coordination problem, not a git problem.

Stage only your own files. git add -A is safe when you own your folder and nothing else is dirty; check git status first if you are unsure. Never commit another agent's uncommitted work.

5. Done means

  • BUNDLE=<your-plugin> bun x vite build succeeds, and your plugin is in manifest.json.
  • It works in the Plugin Studio under both engines, with and without a token, in English and Arabic.
  • Every new string is in all 11 catalogues (bun run check:i18n-parity).
  • Your layer expressions parse under MapLibre (SKILL.md section 5, rule 7).
  • You changed nothing in library/ or in another plugin's folder, or you handed that change to the build owner.

Working when your agent runs on a server

If your coding agent runs somewhere other than your laptop, one line in .env or .env.local makes your local dev server follow the branch the agent pushes to:

DX_SYNC_REMOTE=origin

A full repo URL works too. It only ever fast-forwards, and only when all three are true: you are on that branch, you have no unsaved edits, and you have no local commits. Otherwise it leaves your files alone and says main is N commits ahead in the log. So push your own work often, or you will drift. documentation/CLOUD-DEVELOPMENT-ENVIRONMENT.md covers this and the shared-container alternative.

  • glossary.md — the vocabulary
  • targets.md — capabilities and where a plugin runs
  • backend.md — databases and migrations