Skip to content

Latest commit

 

History

History
61 lines (47 loc) · 8.87 KB

File metadata and controls

61 lines (47 loc) · 8.87 KB

AGENTS.md

This file provides guidance to Codex (Codex.ai/code) when working with code in this repository.

What Fizzygum is

A CoffeeScript GUI framework — a "web operating system" (windows, desktop, drag-and-drop, live in-system editing tools) rendered on a single HTML5 <canvas>. It descends from Morphic.js. ~470 .coffee files live in src/.

Build, run, watch

Prerequisites are installed globally, not via npm: coffee (npm i -g coffeescript), terser, python3, and fswatch (watch script only). npm test is a do-nothing stub — see Testing.

  • Build: ./build_it_please.sh → output goes to ../Fizzygum-builds/latest.
    • --keepTestsDirectoryAsIs — skip recopying tests; much faster, use while iterating.
    • --homepage — production build: strips tests + experimental code, ships a pre-compiled image.
    • --notests — drop tests, keep experimental code.
    • --includeVideoPlayer --includeVideos — bundle the video player + assets.
    • --noSyntaxCheck — skip the build-time CoffeeScript syntax gate (see Testing).
  • ✅ Test a change — PREFERRED / DEFAULT: ./build_and_test.sh — full build + the whole SystemTest suite run headless, in parallel shards, at speed=fastest, dpr 1 (~1 min on a many-core box). This is the standard way to verify a behaviour change; don't watch the suite in a browser (~15 min) or run tests one-by-one unless debugging a single test. One-time setup: cd ../Fizzygum-tests && npm i (Puppeteer).
  • Build + boot-smoke gate: ./build_and_smoke.sh builds (incl. the syntax gate) then headless-boots the world (native + SWCanvas), failing on any console error — a lighter boot-only check (use when a full suite run is overkill).
  • Watch + rebuild on save: ./build_as_soon_as_anything_changes.sh (fswatch over src/; the syntax gate runs on every save).
  • Run: open ../Fizzygum-builds/latest/index.html in a browser. It loads over file://; no dev server needed.

The build requires this sibling layout and aborts without it:

Fizzygum-all/
  Fizzygum/          ← this repo (source only)
  Fizzygum-builds/   ← build output (generated; never hand-edit)
  Fizzygum-tests/    ← SystemTests + Automator source (separate repo)
  Fizzygum-website/

Architecture (the non-obvious parts)

  • Source-as-text + in-browser compilation. buildSystem/build.py does not compile src/ classes. It wraps each class's CoffeeScript source into an escaped JS string (window.Foo_coffeSource = "…"), grouped into ~12 sources_batch_*.js files; the browser compiles them at boot with the bundled CoffeeScript compiler. --homepage instead ships a pre-compiled.js image (generated by loading the page with ?generatePreCompiled) for instant startup. Only src/boot/* is compiled to JS at build time.
  • No imports / no module system. Zero require/import; every class is a global. Load order is auto-discovered by src/boot/dependencies-finding.coffee, which regex-scans source text for extends X, @augmentWith X, and new X. To reference another class just name it — but use those literal forms so the dependency finder sees the edge.
  • Class hierarchy: TreeNodeWidgetPanelWdgt → … → WorldWdgt, the global singleton window.world. Widgets form a tree, painted recursively; a Widget with no owner is never drawn.
  • Meta classes. src/meta/Class.coffee and Mixin.coffee parse each source at runtime, which is what enables live inspection/editing of any class from inside the running world.
  • Rendering is a broken-rectangles (dirty-region) repaint loop on the canvas. Call changed() to invalidate just this widget, fullChanged() for it + its subtree. Pluggable *Appearance objects do the drawing; widgets opting into BackBufferMixin cache themselves to an offscreen canvas.
  • Mixins are applied with @augmentWith SomeMixin (see src/mixins/). The whole widget tree can be serialized/deserialized via DeepCopierMixin — that is how SystemTests snapshot state. Mixins are being phased out in favour of plain-OO delegation; the first example is MacroToolkit (world.macroToolkit, in src/macros/), the macro-test helper toolkit split out of WorldWdgt.

Testing

Two fast automated checks complement the (manual/browser) SystemTests:

  • Build-time syntax gate (buildSystem/check-coffee-syntax.js, run automatically by build_it_please.sh): since the ~470 class/mixin sources ship as text and compile in-browser, this is what catches CoffeeScript parse errors at build time. It LOADS the real src/meta/Class.coffee/Mixin.coffee and compiles each source the same fragmented way the browser does — a whole-file CoffeeScript.compile(src,{bare:true}) is NOT faithful (it false-fails on most files). Skip with --noSyntaxCheck.
  • Headless boot smoke (../Fizzygum-tests/scripts/smoke-boot-headless.js, via ./build_and_smoke.sh or cd ../Fizzygum-tests && npm run smoke): boots the built world headless (native + SWCanvas) and fails on any console/page error — catching the load-order/runtime faults the syntax gate cannot.

Behavioural tests are SystemTests: each one drives the running world from a high-level macro (a generator that asks the live world where things are and synthesises real input events), then compares canvas screenshots pixel-by-pixel against reference images. The Automator source and 160 tests live in the sibling Fizzygum-tests repo (not here); any non---homepage build copies them in. (Macros are the only authoring path — the old input recorder has been removed.)

  • Author: write the test directly as a macro — the framework-side helper toolkit lives in src/macros/ (engine Macro.coffee + MacroToolkit.coffee, reached as world.macroToolkit) and is documented in src/macros/AGENTS.md; see also the /author-macro-test skill in Fizzygum-tests.
  • ✅ Run the whole suite — PREFERRED / DEFAULT: ./build_and_test.sh (build + suite), or against an existing build cd ../Fizzygum-tests && npm test (= scripts/run-all-headless.js). Runs all 160 tests headless, in parallel shards, at speed=fastest, dpr 1 — ~1 min on a many-core box (vs ~15 min watching a browser). npm run test:all is the single-process variant. This is the default way to verify a change. The suite can also run headless under Safari/WebKit (Chrome stays default) as a cross-engine determinism check — --browser=webkit / npm run test:webkit, reusing the same references; see ../Fizzygum-tests/AGENTS.md.
  • Run one (debugging a single test): open the built worldWithSystemTestHarness.html, then world.automator.loader.loadAndRunSingleTestFromName('SystemTest_name'); or headless node scripts/run-macro-test-headless.js SystemTest_<name>.
  • Determinism (the suite asserts byte-exact pixels — keep it deterministic): render/layout/input code must be a pure function of the event stream and final geometry, never of wall-clock timers (setTimeout/Date.now), frame/cycle counts, or intermediate layout passes — those diverge at dpr 2 under parallel load (heavy cycles starve timers and drain multiple events per frame). The contract, the recurring bug-class with worked case law, and the diagnosis playbook (deterministic heavy-cycle reproduction, pixel-delta forensics, disable-the-mechanism proof) are in ../Fizzygum-tests/DETERMINISM.md — read it before touching the rendering loop, doLayout, or ActivePointerWdgt input recognition.

Conventions & gotchas

  • One class per file; filename must equal the class name (Widget.coffeeclass Widget). build.py keys off this.
  • Wdgt is the modern name for the legacy Morph (both extend Widget). The intended end state is all-WdgtMorph is legacy. New widgets are *Wdgt from the start, and existing *Morph classes ARE meant to migrate to *Wdgt over time. Do it incrementally, not in one sweep: rename a coherent group (a class + its family) when you're already touching it, with a reason, because (a) a rename here is not always pixel-free — menu/hierarchy labels strip Wdgt, so renaming a class whose colloquial name is drawn (e.g. menu items) shifts that label and forces SystemTest screenshot recapture; verify per class — and (b) each rename is a whole-tree identifier+file+serialization sweep, best done one verifiable batch at a time.
  • nil means undefined (defined in src/boot/globalFunctions.coffee); the codebase uses it instead of null/undefined.
  • Edit only src/**/*.coffee. Never edit ../Fizzygum-builds/** — it is regenerated every build.
  • # … excluded from the fizzygum homepage build comments and if Automator? guards mark test/experimental code that --homepage strips as dead code — keep them intact.
  • For subsystem-specific depth, check for a local AGENTS.md in that subdirectory (e.g. src/boot/, src/meta/, src/patch-programming/) before assuming this file is complete.