From 6aff223e020827f0005812ff513165ada4bff91d Mon Sep 17 00:00:00 2001 From: jing Date: Mon, 13 Jul 2026 13:34:18 +1000 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=8B=20godsigh=20crossover:=20build=20b?= =?UTF-8?q?rief=20for=20opus=20=E2=80=94=20keyroll=20merge,=20=F0=9F=9B=B0?= =?UTF-8?q?=20sats=20worker,=20=F0=9F=91=81=20god's-eye=20spirit,=20shared?= =?UTF-8?q?=20opensky=20cache?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- GODSIGH_CROSSOVER_BRIEF.md | 78 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 GODSIGH_CROSSOVER_BRIEF.md diff --git a/GODSIGH_CROSSOVER_BRIEF.md b/GODSIGH_CROSSOVER_BRIEF.md new file mode 100644 index 0000000..cec80ee --- /dev/null +++ b/GODSIGH_CROSSOVER_BRIEF.md @@ -0,0 +1,78 @@ +# GODSIGH โœ• GODSTRUMENT โ€” Crossover Build Brief + +**Audience:** Claude Opus 4.8, executing autonomously in this repo (`godstrument`). +**Author:** Claude Fable 5, 2026-07-13, after mapping both codebases. +**Companion:** `~/Documents/GODSIGH/SPEC2.md` (the sibling wave in the GODSIGH repo). Task 3 below shares a **cache contract** with it โ€” the contract text must stay in sync. + +**Before anything:** skim `README.md`, `run.py` (worker supervision + profiles), one worker (`workers/world_iss.py` is the cleanest contract example), `config.json` (signals/routes/groups shape), and the Spirits shelf region of `viz/index.html` (~line 5111 on, "one Source, many Spirits, one Matter"). Match house style: workers are argparse + pythonosc standalone processes emitting `/gs//`; commits carry an emoji prefix (`๐Ÿ›ฐ`, `๐Ÿฅ`, `๐Ÿ“–`โ€ฆ); shipped features get a grimoire/manual entry (see the `๐Ÿ“–` commits and `GODSTRUMENT_MANUAL_SOURCE.md`); `*_BRIEF.md` files are deploy-excluded. Verify in the browser (`python3 run.py --profile minimal` + your new worker) before each commit. + +Execute the four tasks in order; commit + push per task. + +--- + +## Task 1 โ€” ๐ŸŽน Land the local "keyroll" work (groove editor) safely + +**Situation.** Branch `local/groove-editor` (commit `c0c3a98`, single commit on top of pre-godrum `3ff105d`) holds ~637 lines of real local work on the sequencer: a piano-roll editor with **draggable note lengths** (`.seqnote` overlay blocks with an `ew-resize` handle), **velocity + chance lanes** (`.explane` draggable bar-per-step lanes), a `seqedit` wrapper with lane toggles/selectors, **Euclidean tools** (`.euc`, `.tnum`), groove **knobs** (`.aknob`), bar-line markers, and a scroll container. Meanwhile `main` merged the whole **godrum** line, which reworked the same sequencer UI area and independently built per-step velocity+chance, Euclidean fills, swing/humanize, and Follow Actions. + +**Do NOT `git merge local/groove-editor` blind** โ€” the branches rewrote the same regions and an auto-merge will produce soup. Instead: + +1. **Feature-gap analysis first.** Read the branch diff (`git diff 3ff105d..local/groove-editor -- viz/index.html`) and the current main sequencer ("Groove" region, ~`viz/index.html:202`/`:238`, plus godrum's beat panel). Build an explicit table: for each keyroll feature โ€” note lengths / velocity lane / chance lane / lane toggles / euclid tools / groove knobs / bar lines / scroll container / big-grid variant โ€” does current main already have an equivalent (however differently spelled)? +2. **Port only the gaps, natively.** Reimplement each missing feature on top of *current* main's structures and naming (the branch is the reference spec, not a patch to apply). Likeliest genuine gaps, from marker analysis: the **note-length piano roll** (`seqnote` spanning blocks with drag-resize โ€” main has none) and possibly the **explane-style aligned drag-lanes UI**; likeliest already-covered: euclid, velocity/chance *data* (godrum has the data model โ€” the gap may be only the lane *editor UI*). +3. Keep godrum's behavior intact โ€” its choke anchors, euclid guard, kick-duck etc. were carefully review-hardened (`fa5aa43`, `b0fad08`); regressions there are worse than missing a keyroll nicety. +4. Verify by playing: place notes with lengths, drag velocities/chances, euclid-fill, confirm godrum voices still behave, MIDI export still valid. +5. When everything valuable is landed on main, delete the branch (`git branch -D local/groove-editor`) and say so in the commit body โ€” that branch is the only copy of the reference work, so delete it **only after** the port is committed and pushed. +6. Grimoire/manual entry for the new editor capabilities, per house convention. + +## Task 2 โ€” ๐Ÿ›ฐ `workers/world_sats.py`: real satellites as a source (SGP4, no polling APIs) + +GODSIGH proved the pattern: TLEs from Celestrak + SGP4 gives *any* satellite's position locally at any rate โ€” no per-fix HTTP like `world_iss.py` needs. Bring that superpower here as a worker: + +- **Dependency:** `sgp4` (pure-python, pip). Add to `requirements.txt`. +- **TLEs:** fetch at startup from `https://celestrak.org/NORAD/elements/gp.php?GROUP=stations&FORMAT=tle` plus `NAME=GAOFEN&FORMAT=tle` and `NAME=COSMOS%202486` / `NAME=COSMOS%202506` (the recon birds โ€” thematic gold). Cache the TLE text to `~/.cache/godverse/tles.txt` and refresh only if the cache is >24 h old (Celestrak politeness; TLEs age slowly). Tolerate fetch failure by using a stale cache; tolerate no-cache-no-net by exiting politely like other workers. +- **Compute** (default `--interval 2`): propagate each satrec to now (`sgp4` gives ECI; convert to lat/lon/alt via the standard GMST rotation โ€” port the math from GODSIGH `js/layers/satellites.js` / satellite.js's `eciToGeodetic`, it's ~15 lines), then derive **elevation angle** above the venue city's horizon (city lat/lon from `cities.json` via the same `--lat/--lon` retargeting `run.py` applies to other geo workers โ€” accept those flags). +- **Emit** (the contract: raw floats, hub normalizes): + - `/gs/sats/best_elev` โ€” highest elevation (degrees, can be negative) among tracked sats: the "something is overhead" continuous signal. + - `/gs/sats/overhead_count` โ€” count with elevation > 10ยฐ. + - `/gs/sats/iss_lat`, `/gs/sats/iss_lon` โ€” keep the ISS sweep available even when `world_iss.py` isn't running. + - `/gs/sats/pass.event` โ€” impulse when any sat **crosses rising 30ยฐ** (a recon bird crests the sky and a bell rings). Include which sat in the printed log line. + - `/gs/sats/recon_elev` โ€” best elevation among only the GAOFEN/COSMOS set (the watchers' own channel). +- **config.json:** declare the new signals with sensible `norm` ranges (elev `lo:-30, hi:90`; count `lo:0, hi:8`) + labels; add 2โ€“3 starter routes (suggest: `sats.best_elev โ†’ pad.brightness` gentle; `sats.pass โ†’ delay.feedback` impulse; `sats.recon_elev โ†’ lfo.rate` โ€” the sky watching back). Add the worker to the `WORLD` profile in `run.py`. +- Grimoire/manual entry: "the sky's schedule joins the orchestra." + +## Task 3 โ€” ๐Ÿค Shared OpenSky cache (reader side) + +**The contract (mirrored verbatim in GODSIGH SPEC2.md ยง4 โ€” keep in sync):** + +> **OpenSky shared cache v1.** Path: `~/.cache/godverse/opensky-states.json`, overridable via env `OPENSKY_CACHE_FILE`. Content: the raw, unmodified OpenSky `/states/all` JSON response body (global, no bbox). Writer: whoever successfully fetches from upstream writes the body **atomically** (write to `.tmp` in the same directory, then `os.replace`). Freshness = file mtime. Readers treat the cache as fresh if `mtime` is within **120 s**; on upstream 429/failure, readers may serve/use a stale cache rather than nothing. + +GODSIGH's dev proxy implements the writer side. Here, make `workers/world_planes.py` cache-aware: + +1. Each poll cycle: if the cache file exists and is **fresh**, read it and skip the HTTP call entirely (log `[world_planes] cache hit`). GODSIGH fetches globally; if this worker uses a bbox, filter the cached global states client-side by lat/lon โ€” same fields, indices 5/6. +2. On a real HTTP poll that succeeds **with a global scope**, write the cache per the contract (atomic tmp+rename, `mkdir -p` the directory). If this worker polls a bbox, do NOT write (never write partial data into a global-contract file). +3. On 429 or network failure: fall back to a stale cache if present (log it), else current behavior. +4. Keep the existing โ‰ฅ450 s cadence โ€” the cache makes the *effective* shared cost whatever the most aggressive consumer pays, once, per window. + +Result: GODSIGH (90 s cadence) + godstrument running together spend ~one poller's quota instead of two. + +## Task 4 โ€” ๐Ÿ‘ "GOD'S EYE" Spirit (a skin for the shelf) + +A new Spirit in the existing shelf system (register exactly like the others โ€” bagua `~:5791`, Kandinsky `~:5689` are good templates): the world's sensor picture as the cosmology. 2D canvas, house style โ€” no new libraries. + +- **Stage:** a minimal equirectangular world (a sparse hand-drawn continent outline is enough โ€” store a small `[[lon,lat],...]` polyline set inline; do NOT ship a heavy geo dataset into the one-file viz), graticule every 30ยฐ, dark ground, the venue city marked with a ring. +- **Seat the feeds geographically, not symbolically** (this Spirit's whole cosmology is *literal coordinates*): quakes flash at their true lat/lon (the quake worker's events carry location โ€” check what reaches the WS feed and use what's available; if only intensity arrives, flash at the venue antipode and note it), ISS/satellites sweep as moving points with short trails (from Task 2's `sats.*` lat/lon signals), planes as a shimmer band whose brightness = `planes.count`-ish signal, market as a ticker pulse at the financial capitals (NY/London/Tokyo dots), solar wind as an aurora wash at the poles, wiki edits as brief sparks at random civilizational coordinates. +- **Tuning:** like every Spirit, choose a scale + palette identity โ€” suggest a cold surveillance palette (near-black, cyan `#35e0ff`, warning amber) and a minor-pentatonic retune, so entering the Spirit *sounds* like a watch floor. +- Register it on the shelf, respect performance mode (`P`) and zen (`Z`), grimoire/manual entry ("the eye that hears"). + +## Verification & workflow + +- Per task: run `python3 run.py --profile minimal` plus the touched worker(s) with explicit flags; watch the hub log for your signals arriving; open the viz and confirm in the browser (Spirit renders, sequencer plays, no console errors). `python3 -m py_compile` every touched .py; keep workers import-safe when optional deps are missing (house rule). +- Commit per task with the emoji house style; push after each. End commit messages with `Co-Authored-By: Claude Opus 4.8 `. +- Do not deploy anything from this brief; deployment of godstrument follows its own conventions and is not part of this work. + +## Pitfalls + +- Task 1: the keyroll branch predates godrum โ€” never trust an auto-merge; port by intent. Delete the reference branch only after the port is pushed. +- `sgp4`'s `Satrec.sgp4()` returns position in **km, TEME frame** โ€” the GMST rotation to geodetic is mandatory, and `satrec.no_kozai` is rad/min (mirror GODSIGH's math, it's verified). +- Celestrak NAME queries can return `No GP data found` plain text โ€” detect (first data line must start with `1`) and treat as empty, not fatal (verified behavior, same as GODSIGH). +- Atomic cache writes: keep the `.tmp` beside the target file (same filesystem), not in `/tmp`. +- The viz is one 9,256-line file โ€” make surgical, well-commented insertions in the established regions; don't reorganize it.