Yioop — Development process for LLM co-implementers

How Chris Pollett likes development to run, written for an LLM working with him on Yioop. Most of this is shared with his other projects; what is specific to Yioop — the gold/work sync, the Createdb check, the locale and library rules — is marked. When something says "always" or "never," treat it as a hard rule.

Round counter. Keep a count of rounds since you last re-read this file. A round is one exchange: Chris says something, you respond. Echo the current count in every response so it is visible. When the count reaches 10, re-read this whole file before writing your next response, then reset the count to 0 and tell Chris you re-read it. This is a memory aid: it keeps these conventions fresh over a long session instead of letting them drift. The same counter runs in atto's copy of this file.

How changes move (Yioop-specific): gold and work

Yioop is developed against a two-clone discipline, not a shared remote you push to:

gold is a vault, not a workbench. Exactly two operations ever touch gold: cloning it to make work, and fast-forwarding it with git apply of a patch Chris has confirmed. Nothing else, ever. Never run a build, a test, a golden regeneration, a Createdb, a ConfigureTool, or any other command inside gold; never create a work_directory there; never hand-edit, hand-copy, or hand-commit a file into it. Every build, test, and regeneration happens in a work clone, and a regenerated golden reaches gold only inside a patch. Reconciling a divergence is no exception: rebuild the wanted state in work, cut a patch, and apply that to gold. If you ever find yourself about to go into gold to run something — even just to check a result or to get back in sync — that urge is the process breaking; stop, and do it in work.

The loop each round, and this must be done prior to any new work: the moment Chris confirms a patch by pasting its hash, and before writing or changing a single line for the next task, apply Chris's latest confirmed patch to gold, commit it, move the confirmed-head tag, re-clone work, and restore work_directory. Starting new work on a gold that has not been synced is the most common way the two lines drift: the next cut is taken against a stale confirmed-head and silently double-includes the patch Chris already confirmed. If you notice that a round's work has already begun on an unsynced gold, do not re-clone work — that would discard the in-progress changes. Instead advance gold to the confirmed commit, move confirmed-head to that commit in both gold and work, and only then cut. Cut a delivery as git diff confirmed-head..HEAD, and dry-run it with git apply --check on a fresh clone checked out at confirmed-head before presenting. Apply patches forward only — never reverse-diff. Never assume anything is committed until Chris reports the hash. Name a patch for what it does in plain terms, never a sequence number or a plan-item number.

Setting up the dev environment (Yioop-specific)

Beyond the gold/work clones above, a work clone needs a configured work_directory before it will build or run. Restore the configured work_directory into the fresh work clone, point Yioop at it with php8.3 src/configs/ConfigureTool.php work-dir, then build the two SQLite databases with php8.3 src/configs/Createdb.php, which should print “Create DB succeeded.” Without a configured work_directory, Config.php stops short of defining its later constants (for example MAX_GROUP_PAGE_LEN) and Createdb dies with an undefined-constant error — that failure is the environment, not your patch. Createdb also regenerates work_directory/app/locale; since LOCALE_DIR prefers that copy, delete it after Createdb so translations fall back to the current src/locale when you render a page.

Tools that ship with Yioop

Getting a headless browser

You have used a headless renderer here before: wkhtmltoimage and wkhtmltopdf are installed and turn a page or an HTML fragment into a PNG or PDF with no X server. They are built on WebKit, which descends from Konqueror's KHTML, so they draw a page much as a browser would — enough to eyeball a layout or confirm a fragment renders. The bundled /usr/bin/chromium-browser, by contrast, is a snap wrapper that cannot launch here and errors that it “requires the chromium snap.” For scripted measurement of computed styles (reading getBoundingClientRect), a scriptable browser is needed: install a Chrome-for-Testing build with npx @puppeteer/browsers install chrome and drive it from puppeteer-core with --no-sandbox and --disable-dev-shm-usage (not --single-process, which breaks the DevTools pipe); its download host is not in the default network allowlist, so add it to the sandbox network settings first. When no scriptable browser is set up, render to an image with wkhtmltoimage, reason about the cascade, and ask Chris to confirm the pixels.

Presenting Options

Coding conventions (shared across projects)

Yioop-specific rules

Tests

As code is developed, unit tests should be created. Unit tests live in tests/; a case is a method named <name>TestCase() (not test<Name>) and asserts with assertEqual, assertTrue, and the like. Run one with php src/executables/CodeTool.php unit <TestFile>, and list or target cases with unit list / unit ClassName methodName. Pull pure logic out so it can be checked on its own. Flag any test over about 0.01 seconds — it usually means unintended I/O. When patching a locale, edit src/locale/<tag>/configure.ini directly; it takes effect immediately, no extraction step. Call the data a test stands up its "test set-up" or "test data," never a "fixture."

The audit before every patch

Run these as separate checks and report PASS or FAIL for each. The CodeTool commands used are noted where they apply.

  1. php -l on every touched file.
  2. CodeTool.php needsdocs <file> returns 0 — every class and method has a docblock.
  3. No new single-letter PHP variables except i/j/k.
  4. No banned identifier suffixes.
  5. No // comments.
  6. No new single-letter JavaScript variables except i/j/k.
  7. CodeTool.php longlines <file> clean — no line over 80 columns in a touched file.
  8. Every if body is braced.
  9. No banned words and no dead code.
  10. A fresh php src/configs/Createdb.php against a configured SQLite work directory prints "Create DB succeeded" (verify the USERS column count and the root/public rows).

Verify before you state

Delivering a patch

Devlog

Work is logged under devlog/v10/ in dated arc folders named YYYY-MM-DD Arc Name/, each with an HTML plan document. The devlog is append-only: a finished item keeps its checkmark and note as a permanent record, and a later hotfix goes under the current arc's plan as "other work accomplished," not a new dated folder. The only circumstance where a new arc should be created is Chris says so first; until he does, everything, including work that feels like a separate concern such as a production hotfix, goes under the current arc's plan as other work. Before presenting, check that the plan's numbering is internally consistent and that what is marked done lines up with what is next. Try to follow the rules for traditional outlining call for outlines to begin with Roman numerals (I, II, III) and to proceed through letters (A, B, C, and a, b, c) and Arabic numerals (1, 2, 3).

Getting oriented at the start of a session: if you are new to the v10 to-do and its development phases, read the master list devlog/v10/yioop_v10_todo.html first, then the current arc's plan. Each finished arc from 2026-06-16A Mail Refactor Arc onward carries a three-to-four sentence “Arc Post-Mortem Summary” paragraph just under its title that says what the arc accomplished, so you can catch up quickly without reading every item. When an arc is finished, add such a summary to its plan so the next co-implementer gets the same head start.

Words and phrases to avoid at All Costs

These words and phrasings should be excluded from all of your output even transient.

Acronyms and citations

Running things in this environment