mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
Merge branch 'main' of github.com:bilawalsidhu/gods-eye-view
This commit is contained in:
commit
a0131a027f
1688 files changed
+227571
-38931
No files matched your search
+97
-13
@@ -71,8 +71,8 @@ head -40 scripts/qa-radio.mjs # what this runnable gate proves and how to run i
|
||||
Runnable gate entrypoints document what they assert and how to invoke them.
|
||||
Most need a dev server; some also need a specific provider key or port. Follow
|
||||
the entrypoint's header rather than assuming every matching file accepts the
|
||||
same arguments. Only a couple (`qa:map-source-tray`, `qa:transit`) have an
|
||||
`npm run` alias.
|
||||
same arguments. Four have an `npm run` alias: `qa:map-source-tray`,
|
||||
`qa:street-level`, `qa:street-level:fixtures` and `qa:transit`.
|
||||
|
||||
If you aren't sure which gate covers your change, search `docs/CURRENT-STATE.md`
|
||||
for the feature: it names the gate for many of them, and it's the authoritative
|
||||
@@ -80,12 +80,12 @@ runtime reference either way. `scripts/qa-l9-matrix.mjs` aggregates the broader
|
||||
release-candidate checks and selected harnesses; it does not replace the focused
|
||||
gate for the feature you changed.
|
||||
|
||||
> **CI does not cover this for you.** The workflow runs the setup policy
|
||||
> **CI covers only two of these for you.** The workflow runs the setup policy
|
||||
> checks, the formatting and package-boundary checks, the unit suite and the
|
||||
> production build, plus a Windows onboarding job. It runs neither
|
||||
> `npm run test:track` nor any `qa-*.mjs` gate — both need a live dev server
|
||||
> and a browser. Include the applicable local run in your PR's validation
|
||||
> evidence.
|
||||
> `npm run test:track` nor any `qa-*.mjs` gate except the Street Level fixture
|
||||
> gate (`street-level-browser` job) — they need a live dev server and a
|
||||
> browser. Include the applicable local run in your PR's validation evidence.
|
||||
|
||||
## Share-link layer tokens
|
||||
|
||||
@@ -96,8 +96,8 @@ if its layer is later removed.
|
||||
|
||||
New layers first use the remaining unreserved single-character digits (`0`
|
||||
through `9`), then the two-character base-36 namespace (`00` through `zz`). On the
|
||||
current published ledger, `0`, `1` and `2` are already owned, so the next
|
||||
choices are `3` through `9`, then `00`. After rebasing onto the latest `main`, run
|
||||
current published ledger, `0`, `1`, `2` and `3` are already owned, so the next
|
||||
choices are `4` through `9`, then `00`. After rebasing onto the latest `main`, run
|
||||
`npm run layer-token:next -- <layer-id>`, add that result to both the permanent
|
||||
JSON reservation ledger and registry entry, and keep the exact registered-layer
|
||||
count assertion up to date. The token is assigned against the merge-time base, not
|
||||
@@ -115,7 +115,7 @@ remove only your still-unpublished layer's registry entry and ledger row so the
|
||||
local registry is valid again, then rerun `npm run layer-token:next -- <layer-id>`.
|
||||
For example, if PR A publishes `0` while PR B still provisionally uses `0`,
|
||||
PR B removes only its own provisional entry, reruns the helper, and receives
|
||||
`3`. Put `3` on PR B's registry entry and ledger row, update its pinned count
|
||||
`4`. Put `4` on PR B's registry entry and ledger row, update its pinned count
|
||||
and token tests, then rerun `npm run layer-token:check -- --base-ref origin/main`.
|
||||
An invalid duplicate ledger can fail during module import before the helper
|
||||
prints anything; never fix that by renaming or deleting PR A's published token.
|
||||
@@ -125,15 +125,15 @@ prints anything; never fix that by renaming or deleting PR A's published token.
|
||||
The highest-leverage places to jump in:
|
||||
|
||||
- **🌆 Add a CCTV source pack.** Austin is the reference camera source. Adding another city means a clean public camera catalog with coordinates, attribution, and server-registered frame URLs (the proxy only fetches registered URLs — never client-supplied ones, see [SECURITY.md](SECURITY.md)). City packs are the best first lane.
|
||||
- **🛰️ Add or improve a data layer.** Layer factories live in `src/layers/<family>/`, with source, record, controller and renderer owners implementing the layer interface (`init/enable/disable/update/destroy/getStats`, optional `getDetectableObjects`/`getStats`). Use an existing layer as a template.
|
||||
- **🛰️ Add or improve a data layer.** Layer factories live in `src/layers/<family>/`, with source, record, controller and renderer owners implementing the layer interface (`init/enable/disable/update/destroy/getStats`, optional `getDetectableObjects`/`getStats`). Use an existing layer as a template, and see [Adding a new layer](#adding-a-new-layer) for what the PR needs.
|
||||
- **🎙️ Extend voice control.** Voice arguments are defined in `src/voice/actionSchemas.js`, with server-side descriptions in `server/providers/openai/tools.js` and client-side execution in `src/voice/gevActions.js`. Keep the tool surface tight and the responses honest (confirm only what actually happened).
|
||||
- **🎨 Add a visual style.** Styles are GLSL post-process shaders in `src/styles/`.
|
||||
- **🐛 Fix bugs / improve the first-run experience.** See [docs/KNOWN-ISSUES.md](docs/KNOWN-ISSUES.md).
|
||||
|
||||
## Architecture in one minute
|
||||
|
||||
- **No framework.** Vanilla JS + [CesiumJS](https://cesium.com/platform/cesiumjs/) + [Vite](https://vitejs.dev/).
|
||||
- **Assembly lives in `src/app/`; standalone defaults live in `src/standalone/`.** UI controllers live in `src/ui/`, layer factories in `src/layers/`, portable sources in `src/sources/`, and application operations in `src/services/`. Existing `src/ui.js` and `src/data/<layer>.js` entries retain compatibility; new code belongs with its focused owner.
|
||||
- **Vue 3 + Pinia for the interface,** [CesiumJS](https://cesium.com/platform/cesiumjs/) for the globe and [Vite](https://vitejs.dev/) to build. See [Building UI](#building-ui).
|
||||
- **Assembly lives in `src/app/`; standalone defaults live in `src/standalone/`.** UI controllers live in `src/ui/`, layer factories in `src/layers/`, portable sources in `src/sources/`, and application operations in `src/services/`. Existing `src/data/<layer>.js` entries retain compatibility; new code belongs with its focused owner.
|
||||
- Sources acquire records; renderers own Cesium resources. Import `gods-eye-view/layers/<family>/source` when only a source factory is needed. Common voice controls consume the session interface; protocol adapters own connection details.
|
||||
- **Secrets stay server-side.** Anything needing a private key goes through a local proxy under `server/providers/`. The browser only ever sees the Google Maps key (which you restrict) and ephemeral tokens.
|
||||
- `docs/CURRENT-STATE.md` is the authoritative runtime reference — read it first.
|
||||
@@ -143,8 +143,65 @@ The highest-leverage places to jump in:
|
||||
- ES modules, **2-space indent, single quotes, semicolons.**
|
||||
- JSDoc on exported/public functions.
|
||||
- Match the surrounding code — comment density, naming, and idiom.
|
||||
- User-visible text goes through `t()` or `tn()`, with `msg()` marking English that is stored and translated later. Components call `t()` in their templates, so their text follows the locale; `data-i18n*` attributes are only for static page markup such as the loading screen, and `npm run i18n` rejects them in a template. `npm run i18n` must pass. See [docs/I18N.md](docs/I18N.md).
|
||||
- Prefer small, reviewable commits. Conventional-commit-style prefixes (`feat:`, `fix:`, `perf:`, `docs:`) are appreciated but not required.
|
||||
|
||||
## Building UI
|
||||
|
||||
New UX elements are Vue components whose state lives in a Pinia store, and so
|
||||
are existing ones when a change converts them:
|
||||
|
||||
- **Views are Vue components.** Application views live in `src/ui/views/` and
|
||||
the components they place in `src/ui/views/panels/`; a component that
|
||||
belongs to one feature sits beside its owner (`src/ui/rail/`,
|
||||
`src/ui/weather/`). A view renders what its store holds and forwards
|
||||
clicks and input to the store; it holds no application logic.
|
||||
- **State lives in a Pinia store** in `src/ui/stores/`. The owner presents a
|
||||
plain view object and publishes it to the store; the view renders it. User
|
||||
actions return to the owner through handlers it connects to the store,
|
||||
which replace an earlier owner's. Where several owners answer different
|
||||
actions of one store, use `createOwners()` from `src/ui/stores/owners.js`:
|
||||
`act(name, ...args)` calls the newest connected owner that handles `name`,
|
||||
and the owner calls `detach(token)` when it stops.
|
||||
- **Portable owners stay framework-free.** An owner in a portable export
|
||||
imports neither Vue nor Pinia: it takes a `publish` option or offers a
|
||||
`subscribe…()`, and the application shell connects it to the store.
|
||||
`npm run check:boundaries` enforces this.
|
||||
- **Reuse the kit first.** `src/ui/kit/` has one component per control:
|
||||
`UiButton` (including pressed toggles and pressable chips), `UiSelect`,
|
||||
`UiSlider`, `UiSegmented`, `UiChip` (a label, not a control), `UiBadge`,
|
||||
`UiEmpty`, `UiIcon`, `UiTooltip`, `UiPanel` and `UiRail`. Use these before
|
||||
writing a control. When the kit lacks something, extend a kit component or
|
||||
add one that follows the kit's names, props, events and class names (see
|
||||
[Component kit](docs/VUE-MIGRATION.md#component-kit)), rather than
|
||||
building a one-off.
|
||||
- **No hand-written DOM binding.** Don't build elements or write text,
|
||||
classes or attributes from a controller to show UI state; render it from
|
||||
the store. New controls take input through the store rather than through
|
||||
listeners the owner adds. To render outside the view's host (the body, the
|
||||
globe container, or a slot another surface opens), use `<Teleport>` to
|
||||
`body`, a fixed id or a container the owner publishes; don't move nodes by
|
||||
hand. What stays imperative: classes on `<body>` and `<head>`, which sit
|
||||
outside Vue (`cockpit-mode`, `ui-clean-view`); focus moves; positions a
|
||||
layout pass measures in the same task that writes them; and surfaces an
|
||||
owner paints or plays, such as the Cesium canvas, overlay canvases and live
|
||||
video. A few existing surfaces keep listeners or bindings that
|
||||
[docs/VUE-MIGRATION.md](docs/VUE-MIGRATION.md) records; keep those
|
||||
contracts when you change them, and don't copy them into new UI.
|
||||
- **Text** goes through `t()` or `tn()` where the template renders it.
|
||||
English kept in a constant or a store is marked with `msg()` and passed to
|
||||
`t()` when it renders, since a `t()` at module load would fix the English.
|
||||
- **Test components, not markup strings.** Mount the component over
|
||||
happy-dom with `@vue/test-utils` or `createApp` and assert what it renders
|
||||
from its store (see `src/testSupport/vueDom.mjs`, `src/ui/kit/*.test.mjs`
|
||||
and `src/ui/views/intelHudView.test.mjs`). Run one such file with
|
||||
`node --import=./build/registerVue.js --test <file>`. Don't pass happy-dom
|
||||
nodes to `assert.equal`/`deepEqual`; compare them with `assertSameNode()`
|
||||
from `src/testSupport/domAssert.mjs`.
|
||||
|
||||
[docs/VUE-MIGRATION.md](docs/VUE-MIGRATION.md) records how each surface moved
|
||||
and what stays imperative, and why.
|
||||
|
||||
## Formatting and reusable components
|
||||
|
||||
Run `npm run format` before submitting changes, then `npm run format:check`
|
||||
@@ -166,9 +223,36 @@ ownership and adoption process.
|
||||
|
||||
1. Branch off `main`.
|
||||
2. Keep `npm run build`, `npm test`, and `npm run test:track` green and avoid new console errors, plus the [feature gate](#feature-regression-gates) for the area you touched.
|
||||
3. If you change runtime behavior, update `docs/CURRENT-STATE.md` and `CHANGELOG.md` in the same PR.
|
||||
3. If you change runtime behavior, update `docs/CURRENT-STATE.md` in the same PR, and add your changelog entry as `changelog.d/<pr-number>-<slug>.md` instead of editing `CHANGELOG.md` — see [changelog.d/README.md](changelog.d/README.md). Distinct filenames don't conflict; a release assembles the directory into `CHANGELOG.md`. A documentation claim that needs a regression test should assert against `docs/CURRENT-STATE.md` or `README.md`, which a PR still edits directly.
|
||||
4. If you add or change a data source, update [DATA_SOURCES.md](DATA_SOURCES.md) with its license and attribution. **Don't add data you don't have the right to redistribute** — fetch it at runtime instead.
|
||||
5. Describe what you changed and how you verified it (screenshots welcome for anything visual).
|
||||
6. If you add a new layer, fill in the new-layer section of the PR template. See [Adding a new layer](#adding-a-new-layer).
|
||||
|
||||
## Adding a new layer
|
||||
|
||||
A new layer changes what everyone sees on the globe, so maintainers need to see
|
||||
it working and know where its data comes from before reviewing the code. PRs
|
||||
that add a layer must include all four of these in the description. The PR
|
||||
template has a section for them.
|
||||
|
||||
1. **Screenshots.** At least one of the layer on the globe, plus its info card
|
||||
or panel if it has one.
|
||||
2. **A screen recording**, preferably 15 to 30 seconds: turn the layer on, move
|
||||
around, and open a record. Drag an `.mp4` or `.mov` into the PR description.
|
||||
GitHub accepts videos up to 10 MB on free accounts, so link to a larger file
|
||||
instead of attaching it.
|
||||
3. **The proposed category.** Say which layer-panel group the layer belongs in.
|
||||
The groups are defined in `PANEL_GROUPS` in `src/ui/layerPanel.js` (today:
|
||||
Movement, Cameras, Infrastructure, Events, Weather and Utilities). A layer
|
||||
that isn't listed there falls under "Other layers". If none of the groups
|
||||
fits, propose a new one and explain why.
|
||||
4. **The data source and licence.** Name the provider and endpoint, link its
|
||||
licence or terms, give the attribution shown in the app, and say whether it
|
||||
needs a key and whether the data is fetched at runtime or bundled. Add the
|
||||
same details to [DATA_SOURCES.md](DATA_SOURCES.md) and register the credit
|
||||
in `src/data/dataCredits.js`.
|
||||
|
||||
Maintainers may hold a layer PR until all four are there.
|
||||
|
||||
## Maintainers
|
||||
|
||||
|
||||
Reference in new issue
Block a user