📋 godsigh crossover: build brief for opus — keyroll merge, 🛰 sats worker, 👁 god's-eye spirit, shared opensky cache
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
0fb6410be7
commit
6aff223e02
78
GODSIGH_CROSSOVER_BRIEF.md
Normal file
78
GODSIGH_CROSSOVER_BRIEF.md
Normal file
@ -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/<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:
|
||||||
|
|
||||||
|
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 `<path>.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 <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`'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.
|
||||||
Loading…
Reference in New Issue
Block a user