10 KiB
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/<group>/<name>; 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:
- 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)? - 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 (
seqnotespanning 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). - 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. - Verify by playing: place notes with lengths, drag velocities/chances, euclid-fill, confirm godrum voices still behave, MIDI export still valid.
- 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. - 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 torequirements.txt. - TLEs: fetch at startup from
https://celestrak.org/NORAD/elements/gp.php?GROUP=stations&FORMAT=tleplusNAME=GAOFEN&FORMAT=tleandNAME=COSMOS%202486/NAME=COSMOS%202506(the recon birds — thematic gold). Cache the TLE text to~/.cache/godverse/tles.txtand 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 (sgp4gives ECI; convert to lat/lon/alt via the standard GMST rotation — port the math from GODSIGHjs/layers/satellites.js/ satellite.js'seciToGeodetic, it's ~15 lines), then derive elevation angle above the venue city's horizon (city lat/lon fromcities.jsonvia the same--lat/--lonretargetingrun.pyapplies 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 whenworld_iss.pyisn'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
normranges (elevlo:-30, hi:90; countlo:0, hi:8) + labels; add 2–3 starter routes (suggest:sats.best_elev → pad.brightnessgentle;sats.pass → delay.feedbackimpulse;sats.recon_elev → lfo.rate— the sky watching back). Add the worker to theWORLDprofile inrun.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 envOPENSKY_CACHE_FILE. Content: the raw, unmodified OpenSky/states/allJSON response body (global, no bbox). Writer: whoever successfully fetches from upstream writes the body atomically (write to<path>.tmpin the same directory, thenos.replace). Freshness = file mtime. Readers treat the cache as fresh ifmtimeis 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:
- 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. - On a real HTTP poll that succeeds with a global scope, write the cache per the contract (atomic tmp+rename,
mkdir -pthe directory). If this worker polls a bbox, do NOT write (never write partial data into a global-contract file). - On 429 or network failure: fall back to a stale cache if present (log it), else current behavior.
- 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 minimalplus 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_compileevery 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 <noreply@anthropic.com>. - 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'sSatrec.sgp4()returns position in km, TEME frame — the GMST rotation to geodetic is mandatory, andsatrec.no_kozaiis rad/min (mirror GODSIGH's math, it's verified).- Celestrak NAME queries can return
No GP data foundplain text — detect (first data line must start with1) and treat as empty, not fatal (verified behavior, same as GODSIGH). - Atomic cache writes: keep the
.tmpbeside 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.