@tony01/astroneum 0.4.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +237 -0
  2. package/LICENSE +21 -0
  3. package/README.md +198 -0
  4. package/dist/Indicator-BBI3L_lx.d.ts +1181 -0
  5. package/dist/ar-SA-AEPUSRMF.js +2 -0
  6. package/dist/astroneum.css +1 -0
  7. package/dist/chunk-2SN3RH42.js +2 -0
  8. package/dist/chunk-2YYGUSVX.js +3 -0
  9. package/dist/chunk-3GJSZFLM.js +2 -0
  10. package/dist/chunk-4YOLQ5DC.js +2 -0
  11. package/dist/chunk-I4YQBP2M.js +3 -0
  12. package/dist/chunk-OOMZRONH.js +35 -0
  13. package/dist/chunk-PV2GAINM.js +2 -0
  14. package/dist/chunk-SDXH2WAI.js +3 -0
  15. package/dist/chunk-YFPXTHZX.js +2 -0
  16. package/dist/chunk-YW3STIPY.js +653 -0
  17. package/dist/de-DE-4PR3NRQ7.js +2 -0
  18. package/dist/entries/alerts.d.ts +93 -0
  19. package/dist/entries/alerts.js +2 -0
  20. package/dist/entries/datafeeds/crypto.d.ts +65 -0
  21. package/dist/entries/datafeeds/crypto.js +2 -0
  22. package/dist/entries/datafeeds/polygon.d.ts +113 -0
  23. package/dist/entries/datafeeds/polygon.js +2 -0
  24. package/dist/entries/multichart.d.ts +96 -0
  25. package/dist/entries/multichart.js +2 -0
  26. package/dist/entries/portfolio.d.ts +55 -0
  27. package/dist/entries/portfolio.js +2 -0
  28. package/dist/entries/replay.d.ts +141 -0
  29. package/dist/entries/replay.js +2 -0
  30. package/dist/entries/script.d.ts +68 -0
  31. package/dist/entries/script.js +2 -0
  32. package/dist/entries/watchlist.d.ts +43 -0
  33. package/dist/entries/watchlist.js +2 -0
  34. package/dist/es-ES-HNDVPSLW.js +2 -0
  35. package/dist/fr-FR-Y7XWRGF2.js +2 -0
  36. package/dist/hi-IN-KEGIKIMV.js +2 -0
  37. package/dist/id-ID-QXDIUQUZ.js +2 -0
  38. package/dist/index.d.ts +1434 -0
  39. package/dist/index.js +2 -0
  40. package/dist/it-IT-UDTDFSRB.js +2 -0
  41. package/dist/ja-JP-NIODTBW3.js +2 -0
  42. package/dist/ko-KR-DQHPXKBA.js +2 -0
  43. package/dist/nl-NL-BB3ZHCXS.js +2 -0
  44. package/dist/pl-PL-I5MZDLFD.js +2 -0
  45. package/dist/pt-BR-MAMRTOYR.js +2 -0
  46. package/dist/ru-RU-F43D6B7G.js +2 -0
  47. package/dist/th-TH-KTFIUAD6.js +2 -0
  48. package/dist/tr-TR-WFTKJ22Y.js +2 -0
  49. package/dist/vi-VN-CD3WI2FQ.js +2 -0
  50. package/dist/zh-CN-Y2C6RSOI.js +3 -0
  51. package/docs/STRUCTURE.md +231 -0
  52. package/docs/TODO-DESIGN.md +261 -0
  53. package/docs/TODO.md +222 -0
  54. package/docs/api.md +528 -0
  55. package/docs/datafeed-guide.md +311 -0
  56. package/docs/design-astroneum.md +479 -0
  57. package/docs/plugin-development.md +565 -0
  58. package/docs/tv-functions-skill.md +706 -0
  59. package/package.json +147 -0
@@ -0,0 +1,231 @@
1
+ # Astroneum — Structure Map
2
+
3
+ > Living reference for the Astroneum project deployed at **https://72.62.73.180/astroneum/**.
4
+ > Documents *what lives where*. For design rationale see `docs/design-astroneum.md`.
5
+ > Last updated: **2026-07-10**. Keep this file in sync on every structural change (see §11).
6
+
7
+ ## 1. Overview
8
+
9
+ | | |
10
+ |---|---|
11
+ | Name | `astroneum` |
12
+ | Version | `0.4.1-beta.2` |
13
+ | Description | Professional financial charting library, ready out of the box |
14
+ | License | MIT (author `kowito`, repo `github.com/kowito/astroneum`) |
15
+ | Stack | TypeScript · React 18/19 peer · ESM-only · Canvas + WebGL/WebGPU · tsup · pnpm |
16
+ | Server path | `/opt/astroneum` (owned by `deploy:deploy`) |
17
+ | Git on server | Clone of `Tony1185/Astroneum` (fork). `origin` → fork, `upstream` → `kowito/astroneum`. Deploy via `git pull` → build → PM2 restart. |
18
+ | Served at | `https://72.62.73.180/astroneum/` (nginx → `127.0.0.1:3002`) |
19
+ | Coexistence | Shares host with `trading-bot-v2` (`/opt/trading-bot-v2`, ports 3000/3001). No shared code or DB. |
20
+
21
+ ## 2. Repository layout (`/opt/astroneum`)
22
+
23
+ ```
24
+ /opt/astroneum/
25
+ ├── src/ # library source (see §3)
26
+ ├── dist/ # compiled output: ESM js + astroneum.css + .d.ts + locale chunks (gitignored, build artifact)
27
+ ├── demo/ # Next.js showcase app "astroneum-demo-next" (see §5)
28
+ ├── docs/ # developer docs (see §9)
29
+ ├── .opencode/ # AI OS config (fork-only, never PR to upstream)
30
+ │ ├── opencode.json # references (11 docs), permissions, skills path
31
+ │ ├── agents/ # 6 subagents: builder, demo-builder, deployer, doc-syncer, parity-checker, auditor
32
+ │ ├── commands/ # 5 commands: /deploy, /refresh-structure, /refresh-todo, /verify, /parity-check
33
+ │ └── skills/ # 3 skills: conventions, deploy, doc-sync
34
+ ├── AGENTS.md # project kernel — auto-loaded by opencode as system prompt
35
+ ├── .github/workflows/ # CI: auto-version-bump, benchmark, npm-publish
36
+ ├── ecosystem.config.cjs # PM2 config for astroneum-demo (see §7)
37
+ ├── pnpm-workspace.yaml # workspace: packages=[demo]; allowBuilds: @parcel/watcher, esbuild, sharp
38
+ ├── package.json # public package manifest + exports map (see §4)
39
+ ├── pnpm-lock.yaml
40
+ ├── tsup.config.ts # library bundler config (see §6)
41
+ ├── tsconfig.json
42
+ ├── eslint.config.js
43
+ ├── .size-limit.json # per-entry bundle budgets (see §6)
44
+ ├── .gitignore
45
+ ├── check_dist.mjs # smoke: import dist, check exports
46
+ ├── check_datafeed.mjs # smoke: exercise createStandardCryptoDatafeed
47
+ ├── README.md CHANGELOG.md CONTRIBUTING.md CODE_OF_CONDUCT.md SECURITY.md LICENSE INDICATOR_COMPARISON.md
48
+ └── screenshort-1.png screenshort-2.png # (sic: "screenshort")
49
+ ```
50
+
51
+ ## 3. Library source (`src/`)
52
+
53
+ Root files: `index.ts` (public barrel), `types.ts`, `utils.ts`, `constants.ts`, `react-shared.tsx`, `assets.d.ts`.
54
+
55
+ ### 3.1 `chart/` — high-level chart features (26 modules)
56
+ `AstroneumChart.tsx` (main React component), `index.ts`, `hooks.ts`, plus feature modules:
57
+ `AlertManager`, `BarReplay`, `ChartTemplateManager`, `CompareOverlay`, `DOMPane`, `DrawingSnapper`, `DrawingTemplates`, `EventBus`, `MultiChartLayout`, `MultiPeriodLayout`, `MultiTimeframe`, `NonTimeBars`, `PatternRecognition`, `PerformanceMode`, `PointAndFigure`, `PortfolioTracker`, `PositionVisualizer`, `PriceScaleTransform`, `SessionVisualizer`, `UndoManager`, `VolumeProfilePlugin`, `WatchlistManager`, `ZigzagPattern`.
58
+
59
+ ### 3.2 `component/` — primitive UI (9 atoms)
60
+ Each is a `index.tsx` + `index.scss` pair: `button`, `checkbox`, `empty`, `input`, `list`, `loading`, `modal`, `select`, `switch`. Root `index.tsx` + `index.scss` barrel.
61
+
62
+ ### 3.3 `engine/` — rendering core
63
+ Root: `Chart.ts`, `Event.ts`, `Options.ts`, `Store.ts`, `index.ts`.
64
+ - `common/` (~45 modules) — renderers & primitives: `Canvas`, `WebGLCanvas`, `SharedIndicatorGLCanvas`, `CandleWebGLRenderer`, `CandleWebGPURenderer`, `CandleWorkerRenderer`, `IndicatorLineWebGLRenderer`, `IndicatorPluginWebGLRenderer`, `IndicatorRectWebGLRenderer`, `TextWebGLRenderer`, `GlyphAtlas`, `candleShaders.ts`; data/coord: `Data`, `DataLoader`, `SymbolInfo`, `Period`, `VisibleRange`, `BarSpace`, `Bounding`, `Coordinate`, `Point`; interaction: `Crosshair`, `EventHandler`, `Eventful`, `Action`, `Animation`, `TickAnimator`, `TaskScheduler`, `Updater`; buffers: `RingBuffer`, `SabRingBuffer`; styling/types: `Styles`, `Nullable`, `DeepPartial`, `DeepRequired`, `PickPartial`, `PickRequired`, `ExcludePickPartial`; `utils/`.
65
+ - `component/` — engine-level components: `Axis`, `XAxis`, `YAxis`, `Figure`, `Indicator`, `Overlay`.
66
+ - `pane/` — `Pane`, `CandlePane`, `IndicatorPane`, `DrawPane`, `SeparatorPane`, `XAxisPane`, `types.ts`.
67
+ - `view/` (22) — render views: `View`, `AxisView`, `XAxisView`, `YAxisView`, `GridView`, `CandleAreaView`, `CandleBarView`, `CandleHighLowPriceView`, `CandleLastPriceLineView`, `CandleLastPriceLabelView`, `CandleTooltipView`, `ChildrenView`, `CrosshairFeatureView`, `CrosshairLineView`, `CrosshairHorizontalLabelView`, `CrosshairVerticalLabelView`, `IndicatorView`, `IndicatorTooltipView`, `IndicatorLastValueView`, `OverlayView`, `OverlayXAxisView`, `OverlayYAxisView`.
68
+ - `widget/` — `Widget`, `CandleWidget`, `IndicatorWidget`, `DrawWidget`, `SeparatorWidget`, `XAxisWidget`, `YAxisWidget`, `types.ts`.
69
+ - `workers/` — `IndicatorWorkerPool`, `TypedArrayIndicators`, `WasmIndicators`.
70
+ - `extension/` — extension registries: `figure`, `i18n`, `indicator`, `overlay`, `styles`, `x-axis`, `y-axis`.
71
+
72
+ ### 3.4 `widget/` — UI modals & bars (11)
73
+ Each `index.tsx` + `index.scss` (some with `data.ts`/`types.ts`/`icons/`): `alert-modal`, `drawing-bar` (+`icons/`), `indicator-modal`, `indicator-setting-modal` (+`data.ts`,`types.ts`), `period-bar`, `screenshot-modal`, `script-editor-modal`, `setting-modal` (+`data.ts`), `symbol-search-modal`, `timezone-modal` (+`data.ts`), `watchlist`. Root `index.tsx` + `index.scss`.
74
+
75
+ ### 3.5 `datafeed/` — data transport
76
+ `DefaultDatafeed.ts`, `StandardCryptoDatafeed.ts` (Binance/Bitget/OKX USDT), `WebSocketDatafeed.ts`, `WebTransportDatafeed.ts`, `OPFSCache.ts` (off-thread cache), `codec/BarsCodec.ts`, `index.ts`.
77
+
78
+ ### 3.6 `entries/` — subpath entry bundles
79
+ `replay.ts`, `multichart.ts`, `watchlist.ts`, `portfolio.ts`, `alerts.ts`, `script.ts`, `datafeeds/polygon.ts`, `datafeeds/crypto.ts`. (Mirror the `exports` map in §4.)
80
+
81
+ ### 3.7 `extension/` — drawing tools (20 + utils + index)
82
+ `abcd`, `xabcd`, `arrow`, `circle`, `rect`, `triangle`, `parallelogram`, `pitchfork`, `measure`, `waves`, `gannBox`, `gannFan`, `fibonacciCircle`, `fibonacciExtension`, `fibonacciSegment`, `fibonacciSpeedResistanceFan`, `fibonacciSpiral`; `utils.ts`, `index.ts`.
83
+
84
+ ### 3.8 `scripting/` — `ScriptEngine.ts` (Pine-like scripting runtime).
85
+
86
+ ### 3.9 `store/` — state: `chartStore.ts`, `indicatorStore.ts`, `uiStore.ts`, `index.ts`.
87
+
88
+ ### 3.10 `i18n/` — 18 locales + `format.ts` + `index.ts`
89
+ `ar-SA, de-DE, en-US, es-ES, fr-FR, hi-IN, id-ID, it-IT, ja-JP, ko-KR, nl-NL, pl-PL, pt-BR, ru-RU, th-TH, tr-TR, vi-VN, zh-CN`.
90
+
91
+ ### 3.11 Misc
92
+ - `plugin/index.ts` — plugin API surface.
93
+ - `jsx/` — `jsx-runtime.ts`, `jsx-dev-runtime.ts` (custom JSX runtime; tsconfig `jsxImportSource: @/jsx`).
94
+ - `styles/` — `base.scss`, `index.scss` (built to `dist/astroneum.css`).
95
+ - `assets/` — `logo.svg`, `iconfonts/{fonts, style.css}`.
96
+ - `__tests__/` — `adjustFromTo`, `datafeed-contract`, `pagination`, `persistence`, `plugin`, `script-engine`, `ssr-smoke`, `utils` (`.test.ts`), + `perf/`.
97
+
98
+ ## 4. Public API surface (`package.json` `exports`)
99
+
100
+ | Subpath | Dist target |
101
+ |---|---|
102
+ | `astroneum` (`.`) | `dist/index.js` |
103
+ | `astroneum/replay` | `dist/entries/replay.js` |
104
+ | `astroneum/multichart` | `dist/entries/multichart.js` |
105
+ | `astroneum/watchlist` | `dist/entries/watchlist.js` |
106
+ | `astroneum/portfolio` | `dist/entries/portfolio.js` |
107
+ | `astroneum/alerts` | `dist/entries/alerts.js` |
108
+ | `astroneum/script` | `dist/entries/script.js` |
109
+ | `astroneum/datafeeds/polygon` | `dist/entries/datafeeds/polygon.js` |
110
+ | `astroneum/datafeeds/crypto` | `dist/entries/datafeeds/crypto.js` |
111
+ | `astroneum/style.css` | `dist/astroneum.css` |
112
+ | `astroneum/package.json` | `./package.json` |
113
+
114
+ tsup entries (single source of truth for the above): `src/index.ts` + the 8 `src/entries/**` files. All entries ship with `.d.ts`. esbuild strips `'use client'`; `tsup.onSuccess` re-injects it into every emitted `.js` so Next.js App Router treats each entry as a Client Module.
115
+
116
+ `peerDependencies`: `react` / `react-dom` `^18 || ^19`. `engines.node`: `>=18`.
117
+
118
+ ## 5. Demo app (`demo/` — `astroneum-demo-next`)
119
+
120
+ Next.js 15 + React 19 showcase. Private workspace package, depends on `astroneum: workspace:*`.
121
+
122
+ - `package.json` — scripts: `dev`, `build`, `start` (= `next start -p 3002 -H 127.0.0.1`). Deps: `next ^15.3.1`, `react ^19.2`, `astroneum workspace:*`.
123
+ - `next.config.ts` — `transpilePackages: ['astroneum']`, `basePath: NEXT_PUBLIC_BASE_PATH` (=`/astroneum` in prod), `trailingSlash: true`, `outputFileTracingRoot: ../`.
124
+ - `src/app/` routes (App Router):
125
+ - `layout.tsx`, `page.tsx`, `globals.css`
126
+ - `_components/alerts/` — `AlertDialog`, `ErrorBoundary`, `NotificationsDialog`, `Popover` + `alert-dialog.css`
127
+ - `alerts/page.tsx`
128
+ - `api/alerts/email/route.ts`, `api/alerts/webhook/route.ts`
129
+ - `components/` — `ChartDemo`, `ChartTerminal`, `ChartTypeDropdown`, `CommandPalette`, `DateRangeNavigator`, `ErrorBoundary`, `MultiChartView`, `PatternDialog`, `ReplayToolbar`, `SaveLoadMenu`, `TerminalShell` + `enhancements.css`, `terminal.css`
130
+ - `components/panels/` — `PineEditorPanel`, `WatchlistPanel` + `panels.css`
131
+ - `support/` — `layout.tsx`, `support.css`, `_components/{ArticleBody, Breadcrumb}`, `_lib/{articles/, articles-data.json, data.ts}`, `categories/alerts/page.tsx`, `folders/[folder]/page.tsx`, `solutions/[slug]/page.tsx`
132
+ - `mockDatafeed.ts`, `types/css-imports.d.ts`
133
+ - Other: `.env`, `.gitignore`, `.impeccable/`, `.next/` (build out), `DESIGN.md`, `PRODUCT.md`, `README.md`, `next-env.d.ts`, `tsconfig.json`, `package.json.bak.`.
134
+
135
+ ## 6. Build & tooling
136
+
137
+ - **pnpm workspace** (`pnpm-workspace.yaml`): `packages: [demo]`; `allowBuilds: @parcel/watcher, esbuild, sharp`.
138
+ - **package.json scripts**: `clean`, `build:js` (tsup), `build:css` (sass → esbuild bundle/minify, inlines eot/ttf/woff/svg), `build` (clean + js + css), `typecheck` (`tsc --noEmit`), `test` (`tsx --test src/__tests__/*.test.ts`), `test:watch`, `lint` (`eslint src`), `size` (`size-limit`), `verify` (lint+typecheck+build+test), `prepublishOnly` (verify).
139
+ - **tsup.config.ts** — `format: ['esm']`, `dts: true`, `splitting: true`, `treeshake: true`, `target: 'esnext'`, `outDir: dist`, `external: ['react','react-dom','react-dom/client','react/jsx-runtime']`; esbuild `jsx: 'automatic'`, alias `@ → ./src`, loaders `.less → empty`, `.svg → text`; `onSuccess` walks `dist/` and prepends `'use client';` to every `.js`.
140
+ - **tsconfig.json** — `target/module: ESNext`, `moduleResolution: Bundler`, `jsx: preserve`, `jsxImportSource: @/jsx`, `paths: @/* → ./src/*`, `include: src`, `exclude: src/__tests__`, `noEmit: true` (typecheck only).
141
+ - **.size-limit.json** — 9 budgets (ignore react/react-dom): root `200 KB`; `replay`/`multichart`/`script` `15 KB`; `watchlist`/`portfolio`/`alerts` `10 KB`; `datafeeds/polygon`/`datafeeds/crypto` `30 KB`.
142
+ - **eslint.config.js** — flat config.
143
+ - **Smoke scripts**: `check_dist.mjs` (imports `dist`, asserts `AstroneumChart`, `createStandardCryptoDatafeed`, `STANDARD_CRYPTO_SYMBOLS`); `check_datafeed.mjs` (searchSymbols + bounded history fetch).
144
+
145
+ ## 7. Deployment topology
146
+
147
+ ### nginx (TLS termination, 443/80)
148
+ - `:80` → `301` to `https://$host$request_uri`.
149
+ - `:443` ssl — cert `/etc/nginx/ssl/server.{crt,key}`, TLS 1.2/1.3.
150
+ - Routes:
151
+ - `/astroneum/_next/static/` → `127.0.0.1:3002` — immutable (`max-age=31536000, immutable`)
152
+ - `/astroneum/` → `127.0.0.1:3002` — `no-cache, must-revalidate`
153
+ - `/` → `127.0.0.1:3000` (trading-bot-web, WebSocket upgrade)
154
+ - `/socket.io/` → `127.0.0.1:3001` (trading-bot-ws, WebSocket upgrade)
155
+ - Security headers on all blocks: `X-Frame-Options DENY`, `X-Content-Type-Options nosniff`, `Referrer-Policy strict-origin-when-cross-origin`, HSTS preload.
156
+ - **Caveat:** `sites-enabled/` currently contains **3 overlapping server blocks** for `72.62.73.180` (only the first match wins). Worth consolidating — flag for cleanup.
157
+
158
+ ### PM2 — `astroneum-demo` (`ecosystem.config.cjs`)
159
+ | Field | Value |
160
+ |---|---|
161
+ | name | `astroneum-demo` |
162
+ | script | `pnpm` · args `--filter astroneum-demo-next start` |
163
+ | cwd | `/opt/astroneum` |
164
+ | env | `NODE_ENV=production`, `NEXT_PUBLIC_BASE_PATH=/astroneum`, `NODE_OPTIONS=--max-old-space-size=256`, `TZ=Asia/Bangkok` |
165
+ | max_memory_restart | `512M` |
166
+ | autorestart / watch | true / false |
167
+ | logs | `/home/deploy/.pm2/logs/astroneum-demo-{out,error}.log` |
168
+
169
+ ### Ports
170
+ | Port | Bind | Process |
171
+ |---|---|---|
172
+ | 80 | 0.0.0.0 | nginx (→ 443) |
173
+ | 443 | 0.0.0.0 | nginx (TLS) |
174
+ | 3000 | 127.0.0.1 | trading-bot-web (Next.js) |
175
+ | 3001 | 127.0.0.1 | trading-bot-ws (Socket.io) |
176
+ | 3002 | 127.0.0.1 | **astroneum-demo** (Next.js) |
177
+
178
+ ## 8. Build & deploy flow
179
+
180
+ Library change → demo rebuild → restart (demo only; trading-bot unaffected):
181
+
182
+ ```bash
183
+ ssh 72.62.73.180 "cd /opt/astroneum && pnpm build" # 1. lib → dist/ (tsup + css)
184
+ ssh 72.62.73.180 "cd /opt/astroneum && pnpm --filter astroneum-demo-next build" # 2. demo → demo/.next/ (transpilePackages picks up new dist)
185
+ ssh 72.62.73.180 "pm2 restart astroneum-demo" # 3. serve
186
+ ```
187
+
188
+ - Demo-only change (no lib touch): skip step 1.
189
+ - Docs-only change (e.g. this file): no build, no restart.
190
+ - Lib `build` runs `pnpm clean` first — wipes `dist/`.
191
+
192
+ ## 9. Docs & meta
193
+
194
+ | Doc | Role | NOT for |
195
+ |---|---|---|
196
+ | `STRUCTURE.md` (this file) | Where things live (file tree, deploy, build) | How to use → `api.md` · How to build plugins → `plugin-development.md` |
197
+ | `tv-functions-skill.md` | TV→Astroneum function catalog + **authoritative status** | Actionable gaps → `TODO.md` · Design → `TODO-DESIGN.md` |
198
+ | `design-astroneum.md` | Library UX spec (colors, typography, layout, motion) | Demo app design → `demo/DESIGN.md` · Status → `TODO-DESIGN.md` |
199
+ | `api.md` | API reference (signatures) | How to author plugins → `plugin-development.md` |
200
+ | `datafeed-guide.md` | Datafeed how-to | Plugin authoring → `plugin-development.md` |
201
+ | `plugin-development.md` | Plugin authoring guide | API signatures → `api.md` |
202
+ | `TODO.md` | Actionable function-gap backlog | Status authority → `tv-functions-skill.md` · Design → `TODO-DESIGN.md` |
203
+ | `TODO-DESIGN.md` | Design/layout gap backlog | Function gaps → `TODO.md` · Status authority → `tv-functions-skill.md` |
204
+ | `INDICATOR_COMPARISON.md` | Indicator parity table (50/50) | Other features → `tv-functions-skill.md` §3 |
205
+ | `demo/DESIGN.md` | Demo app design system | Library UX spec → `design-astroneum.md` |
206
+ | `demo/PRODUCT.md` | Product framing | Design system → `demo/DESIGN.md` |
207
+
208
+ - **Root**: `README.md`, `CHANGELOG.md`, `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `SECURITY.md`, `LICENSE` (MIT), `INDICATOR_COMPARISON.md`.
209
+ - **`.github/workflows/`**: `auto-version-bump.yml`, `benchmark.yml`, `npm-publish.yml`.
210
+
211
+ ## 10. Maintenance policy
212
+
213
+ This file is the source of truth for *where things live* in the deployed Astroneum project. Update it whenever any of the following change:
214
+
215
+ - file/dir added / removed / renamed under `src/`, `demo/src/`, `docs/`, `.github/`
216
+ - new / renamed export in `package.json` `exports`, or entry in `tsup.config.ts`
217
+ - new / changed PM2 process, port, or nginx route
218
+ - version bump in `package.json`
219
+ - new dependency that changes the public surface
220
+ - new locale / widget / component / engine module / extension tool
221
+ - build/tooling config edit (`tsup.config.ts`, `tsconfig.json`, `next.config.ts`, `ecosystem.config.cjs`, `.size-limit.json`, `eslint.config.js`)
222
+ - docs / meta file added or removed
223
+
224
+ **Detection model**: the assistant is not always running, so updates happen on invocation — when you ping with a change (or "refresh structure"), re-scan the live tree and patch this file, then append a dated entry to the changelog below. A consistency check (ports, PM2 status, exports vs. entries vs. `dist/` files) runs each refresh.
225
+
226
+ **Apply**: docs-only edit, no `pnpm build` / `pm2 restart` needed (`docs/*.md` is not served by the demo app).
227
+
228
+ ## 12. Change log
229
+
230
+ - **2026-07-07** — Initial map generated from live `/opt/astroneum` snapshot: src/ (12 subdirs), demo/ Next.js app, build/tooling, nginx+PM2 topology, docs/meta. Noted: no `.git` on server; 3 overlapping nginx server blocks in `sites-enabled/`.
231
+ - **2026-07-07 (b)** — `src/widget/alert-modal` rewritten: now ships full Notifications UX (Webhook URL with SSRF guard + status writeback, in-app, toast, email, plain-text email, sound title/duration, notification schedule, message template, expiration, trigger frequency) using library `Modal`/`Input`/`Checkbox` primitives + `--astroneum-*` tokens. New i18n keys in `en-US.json` + `zh-CN.json` (other 16 locales fall back to en-US). Engine (`AlertManager`) + server relay (`demo/src/app/api/alerts/{webhook,email}/route.ts`) were already capable — this change exposes them in the chart-mounted widget. Also fixed `.alert-section-label` No-Eyebrow Rule violation (was `text-transform: uppercase`). design-astroneum.md section 12 updated.
@@ -0,0 +1,261 @@
1
+ # Astroneum — Design TODO: Mirror TradingView Layout
2
+
3
+ > **Master index** of every TV UI surface → Astroneum design mirror. One row per layout element.
4
+ > **Last updated:** 2026-07-08
5
+ > Pair with: `docs/TODO.md` (function gaps) · `docs/STRUCTURE.md` (where things live) · `docs/tv-functions-skill.md` (function catalog) · `docs/design-astroneum.md` (UX spec) · `INDICATOR_COMPARISON.md` (indicators)
6
+ > **Update on every UI/layout/design change** (see §Maintenance).
7
+ >
8
+ > **Scope:** design/layout only. "Inside function" column is filled when Astroneum has the function wired; left blank when not implemented. Function specs live in `TODO.md`.
9
+ >
10
+ > **Authority:** TV-vs-Astroneum status lives in `docs/tv-functions-skill.md` §3 (6-bucket taxonomy). This file tracks design/layout only. When statuses conflict, tv-functions-skill.md wins.
11
+
12
+ ## How to read
13
+
14
+ **Design status legend**
15
+
16
+ | Symbol | Meaning (layout only) |
17
+ |---|---|
18
+ | ✅ | Layout element exists and matches TV |
19
+ | 🔧 | Layout exists but partial (missing sub-elements / wrong placement) |
20
+ | ⏳ | v1-in-scope — layout spec'd to build now |
21
+ | 🟦 | v1.1 — layout deferred |
22
+ | ⟫ | v2-future — layout not in v1 |
23
+ | ❌ | Layout missing |
24
+ | ⚠️ | Layout risk / tech debt |
25
+
26
+ **TV reference IDs**: `#header-toolbar-*` (top bar), `#drawing-toolbar*` / `linetool-group-*` (left bar), `#right-toolbar` / `data-name` (right rail), `#footer-chart-panel` (bottom dock). Astroneum pointers: `src/widget/`, `src/extension/`, `demo/src/app/components/`.
27
+
28
+ ---
29
+
30
+ ## 0. Shell regions → `design-astroneum.md` §4, `STRUCTURE.md` §5
31
+
32
+ | # | TV region | TV container | Astroneum design | Inside function |
33
+ |---|---|---|---|---|
34
+ | 0.1 | Top toolbar (44px) | `#header-toolbar` | 🔧 `TerminalShell` topbar + `PeriodBar` — covers ~8/23 elements | |
35
+ | 0.2 | Left drawing rail (48px) | `#drawing-toolbar` | 🔧 `TerminalShell` rail + `DrawingBar` — 5/8 dropdown groups | |
36
+ | 0.3 | Chart pane (center) | `layout__area--center` | ✅ `TerminalShell` chart slot + `<AstroneumChart>` | Canvas/WebGL render |
37
+ | 0.4 | Right rail toggle bar + panels (260px, 240ms slide, persisted) | `#right-toolbar` | ✅ `TerminalShell` sidebar + `SidebarContent` strip (7 tabs: watchlist/details/alerts/calendar/news/ideas/trading) + `WatchlistPanel`/`AlertsPanel`/`StubPanel` — collapse animates via grid-track transition, state in localStorage `astroneum:shell` | `WatchlistPanel`, `AlertsPanel`, `StubPanel` |
38
+ | 0.5 | Bottom dock (tab bar, 220px, 240ms slide, persisted) | `#footer-chart-panel` | ✅ `TerminalShell` dock + `DockContent` tab bar (Pine Editor / Strategy Tester / Trading Panel) + collapse toggle — collapses to 36px tab strip, state persisted | `PineEditorPanel`, `StrategyTesterPanel`, `TradingPanel` |
39
+ | 0.6 | Footer (date range navigator, 28px) | `withdateranges` | ✅ `DateRangeNavigator` — 7 presets (1D/1W/1M/3M/1Y/5Y/ALL) + live visible-range readout via `ChartPlugin` engine bridge | `DateRangeNavigator` |
40
+
41
+ > **Shell behavior (§4):** Sidebar + dock collapse via `grid-template-columns`/`grid-template-rows` token transitions (240ms, `--term-dur`); collapse state persisted per-user in `localStorage` key `astroneum:shell` (decoupled from chart `serializeState`). Below lg (1024px) the layout is chart-dominant: left rail hidden, sidebar + dock forced collapsed, topbar slimmed to brand + badges (symbol/timeframe live in the chart's `PeriodBar`). FAB overlay for the right rail is 🟦 v1.1.
42
+
43
+ ## 1. Top toolbar — `#header-toolbar` → `design-astroneum.md` §5
44
+
45
+ | # | TV element | TV id / data-name | Astroneum design | Inside function |
46
+ |---|---|---|---|---|
47
+ | 1.1 | Symbol search (value text button) | #header-toolbar-symbol-search | ✅ PeriodBar symbol trigger + SymbolSearchModal - title(symbol_search), data-semantic-id(header.symbol_search), apply-common-tooltip, mobile text-hide @ max-width:600px | PeriodBar + SymbolSearchModal |
48
+ | 1.2 | Switch data type (icon button) | `#header-toolbar-switch-data-type` | ❌ | |
49
+ | 1.3 | Compare symbols button | `#header-toolbar-compare` | 🟦 | |
50
+ | 1.4 | Timeframe radiogroup (1h/4h/D/W) | `#header-toolbar-intervals` | ✅ `PeriodBar` periods | `PeriodBar` |
51
+ | 1.5 | Chart interval dropdown (`,`) | `menuBtn-U9b0TAs4` | 🔧 `PeriodBar` has period buttons, no overflow dropdown — `,` hotkey not wired. Deferred to a library `PeriodBar` pass | |
52
+ | 1.6 | Chart style menu (Candles) | `#header-toolbar-chart-styles` | ✅ `ChartTypeDropdown` | `ChartTypeDropdown` |
53
+ | 1.7 | Indicators dialog button (`/`) | `data-name="open-indicators-dialog"` | ✅ `IndicatorModal` — `/` hotkey wired in `AstroneumChart.tsx` | `IndicatorModal` |
54
+ | 1.8 | Favorite indicators menu | `data-name="show-favorite-indicators"` | 🟦 v1.1 — needs an indicator-favorites model + menu | |
55
+ | 1.9 | Indicator templates menu | `#header-toolbar-study-templates` | ✅ folded into `SaveLoadMenu` — named chart-state presets via `ChartTemplateManager` | `SaveLoadMenu` |
56
+ | 1.10 | Create alert button (Alt+A) | `#header-toolbar-alerts` | ✅ `AlertModal` — Alt+A hotkey wired in `AstroneumChart.tsx` | `AlertModal` |
57
+ | 1.11 | Bar replay button | `#header-toolbar-replay` | ✅ `ReplayToolbar` + `BarReplay` | `BarReplay` |
58
+ | 1.12 | Undo button | `#header-toolbar-undo-redo` | ✅ `UndoManager` + brand-bar button (disabled when empty) + `Ctrl+Z` wired in `ChartTerminal` | `UndoManager` |
59
+ | 1.13 | Redo button | `#header-toolbar-undo-redo` | ✅ `UndoManager` + brand-bar button + `Ctrl+Y` / `Ctrl+Shift+Z` wired in `ChartTerminal` | `UndoManager` |
60
+ | 1.14 | Fill-spacer (push right groups) | `fill-dlFDN0Zd` | ✅ CSS flex auto | |
61
+ | 1.15 | Layout setup (grid picker) | `#header-toolbar-layouts` | ✅ `LayoutPicker` in demo topbar — 1/2/4/8/16 grid | `LayoutPicker` |
62
+ | 1.16 | Save/Load button ("Unnamed" + state) | `#header-toolbar-save-load` | ✅ `SaveLoadMenu` — "Unnamed" label + Save/Load/Clear/Delete dropdown via `ChartTemplateManager` | `SaveLoadMenu` |
63
+ | 1.17 | Manage layouts menu | `data-name="save-load-menu"` | ✅ folded into `SaveLoadMenu` dropdown (save-as / load / delete per layout) | `SaveLoadMenu` |
64
+ | 1.18 | Quick search button (Ctrl+K) | `#header-toolbar-quick-search` | ✅ `CommandPalette` — symbol search + actions, Ctrl+K wired in demo | `CommandPalette` |
65
+ | 1.19 | Settings button | `#header-toolbar-properties` | ✅ `SettingModal` | `SettingModal` |
66
+ | 1.20 | Fullscreen button (Shift+F) | `#header-toolbar-fullscreen` | ✅ `PeriodBar` fullscreen — Shift+F hotkey wired in `AstroneumChart.tsx` | `PeriodBar` fullscreen |
67
+ | 1.21 | Screenshot button (with menu) | `#header-toolbar-screenshot` | ✅ `ScreenshotModal` | `ScreenshotModal` |
68
+ | 1.22 | Mobile trade pill | `#header-toolbar-trade-mobile` | ⟫ mobile (§12) | |
69
+ | 1.23 | Mobile publish button | `#header-toolbar-publish-mobile` | ⟫ | |
70
+
71
+ ## 2. Left drawing toolbar — `#drawing-toolbar` → `design-astroneum.md` §5
72
+
73
+ | # | TV element | TV data-name | Astroneum design | Inside function |
74
+ |---|---|---|---|---|
75
+ | 2.1 | Cursors group (Cross default + submenu) | `linetool-group-cursors` | 🔧 `DrawingBar` default — Cross ✅, submenu unverified | |
76
+ | 2.2 | Trendline + Trend tools submenu | `linetool-group-trend-line` | 🔧 `singleLine` group | |
77
+ | 2.3 | Fib retracement + Gann/Fib submenu | `linetool-group-gann-and-fibonacci` | 🔧 `fibonacci` group — missing pure Fib Retracement, Channel, Wedge, Time Zones, Arcs, Fan | |
78
+ | 2.4 | XABCD pattern + Patterns submenu | `linetool-group-patterns` | 🔧 `wave` group — missing Cypher, Crab, Bat, Butterfly, Three Drives, Elliott Impulse | |
79
+ | 2.5 | Long position + Forecasting submenu | `linetool-group-prediction-and-measurement` | ❌ `measure` only | |
80
+ | 2.6 | Brush + Geometric shapes submenu | `linetool-group-geometric-shapes` | 🔧 `polygon` group — missing Brush, Ellipse, Polygon, Polyline | |
81
+ | 2.7 | Text + Annotation submenu | `linetool-group-annotation` | ❌ | |
82
+ | 2.8 | Icon + Icons submenu (font icons) | `linetool-group-font-icons` | ❌ | |
83
+ | 2.9 | Measure button (Shift+Click) | `data-name="measure"` | 🔧 `measure` extension — Shift+Click not wired | `measure` |
84
+ | 2.10 | Zoom in button | `data-name="zoom"` | 🔧 wheel zoom only — no button | |
85
+ | 2.11 | Magnet mode button (Ctrl) | `data-name="magnet-button"` | ✅ `DrawingBar` magnet + `DrawingSnapper` | `DrawingSnapper` |
86
+ | 2.12 | Keep drawing (sticky) button | `data-name="drawginmode"` | ❌ | |
87
+ | 2.13 | Lock all drawings button | `data-name="lockAllDrawings"` | ✅ `DrawingBar` lock + `lockAllDrawings()` | `lockAllDrawings()` |
88
+ | 2.14 | Hide all drawings button (Ctrl+Alt+H) | `data-name="hide-all"` | 🔧 `DrawingBar` visible toggle — Ctrl+Alt+H not wired | |
89
+ | 2.15 | Remove objects button | `data-name="removeAllDrawingTools"` | ✅ `DrawingBar` remove | |
90
+ | 2.16 | Favorite drawings toolbar toggle | `#drawing-toolbar-favorite-drawings` | ❌ | |
91
+
92
+ ## 3. Right rail — `#right-toolbar` toggle bar + panels → `tv-functions-skill.md` §3.17
93
+
94
+ TV's right rail is a **vertical toggle bar** (`#right-toolbar`, 11 buttons) that switches which panel shows. Astroneum puts panels directly in the sidebar slot with no toggle bar.
95
+
96
+ ### 3a. Right toolbar toggle bar
97
+
98
+ | # | TV element | data-name | Astroneum design | Inside function |
99
+ |---|---|---|---|---|
100
+ | 3.1 | Vertical toggle bar container | `#right-toolbar` | ❌ — panels in sidebar slot directly | |
101
+ | 3.1 | Vertical toggle bar container | `#right-toolbar` | ✅ `TerminalShell` sidebar strip — `term-sidebar-strip` (52px vertical, 7 icon+label tabs) | |
102
+ | 3.2 | Watchlist/details/news toggle (active) | `base` | ✅ `WatchlistPanel` — toggle button in `term-sidebar-strip` | `WatchlistPanel` |
103
+ | 3.3 | Alerts toggle | `alerts` | ✅ `AlertsPanel` — toggle button in `term-sidebar-strip` | `AlertsPanel` |
104
+ | 3.4 | Object tree + data window toggle | `object_tree` | ❌ | |
105
+ | 3.5 | Chats toggle | `union_chats` | ⟫ | |
106
+ | 3.6 | Filler (spacer) | `filler-Sc5Go8G8` | ✅ CSS | |
107
+ | 3.7 | Screeners toggle | `screener-dialog-button` | ⟫ | |
108
+ | 3.8 | Pine toggle | `pine-dialog-button` | 🔧 `PineEditorPanel` — exists in bottom dock, not right rail | `PineEditorPanel` |
109
+ | 3.9 | Calendars toggle | `calendar-dialog-button` | 🔧 `StubPanel` placeholder in sidebar strip | `StubPanel` |
110
+ | 3.10 | Community toggle (with badge counter) | `community-hub-button` | ⟫ | |
111
+ | 3.11 | Notifications toggle | `notifications-button` | ❌ | |
112
+ | 3.12 | Products menu toggle | `products-button` | ❌ | |
113
+ | 3.13 | Separator | `separator-VRj5pi98` | — | |
114
+ | 3.14 | Help Center toggle | `help-button` | 🔧 `demo/src/app/support/` route — not as rail toggle | |
115
+
116
+ ### 3b. Watchlist panel content (when 3.2 active)
117
+
118
+ | # | TV element | Astroneum design | Inside function |
119
+ |---|---|---|---|
120
+ | 3.15 | Multiple watchlists (tabs) | 🔧 `WatchlistPanel` — single list | |
121
+ | 3.16 | Add/remove symbol | ✅ | `WatchlistManager` |
122
+ | 3.17 | Reorder (drag rows) | ❌ | |
123
+ | 3.18 | Details panel (OHLC + P&L + desc) | 🔧 partial | |
124
+ | 3.19 | Highlight selected row | ✅ | |
125
+
126
+ ## 4. Bottom dock — `#footer-chart-panel` tab bar → `tv-functions-skill.md` §3.13/3.15/3.20
127
+
128
+ TV's bottom dock is a **tab bar** with strategy report tabs + open/maximize toggles. Astroneum's dock has a tab bar (Pine Editor / Strategy Tester / Trading Panel) + a collapse toggle.
129
+
130
+ | # | TV element | data-name / qa-id | Astroneum design | Inside function |
131
+ |---|---|---|---|---|
132
+ | 4.1 | Tab bar container | `#footer-chart-panel` | ✅ `TerminalShell` dock slot + `DockContent` `term-dock-tabs` | `DockContent` |
133
+ | 4.2 | Strategy report tab (icon + title + context menu) | `data-qa-id="backtesting"` | ✅ `StrategyTesterPanel` stub — tab present, content is empty state | `StrategyTesterPanel` |
134
+ | 4.3 | Tab context menu (rename/close/duplicate) | `data-qa-id="tab-menu-trigger"` | ❌ | |
135
+ | 4.4 | "More tabs" button (3 dots) | `menuButtonWrap-jogw41q5` | ❌ | |
136
+ | 4.5 | Open panel toggle (chevron) | `toggle-visibility-button` | ✅ `DockContent` collapse toggle (`term-icon-btn`) | `DockContent` |
137
+ | 4.6 | Maximize panel toggle | `toggle-maximize-button` | ❌ | |
138
+ | 4.7 | Pine Editor tab | (when Pine open) | ✅ `PineEditorPanel` — tab in `term-dock-tabs` | `PineEditorPanel` |
139
+ | 4.8 | Trading Panel tab | (when broker connected) | ✅ `TradingPanel` stub — tab present, content is empty state | `TradingPanel` |
140
+ | 4.9 | Resize handle (dock height) | ❌ | |
141
+
142
+ ## 5. Chart pane overlays → `design-astroneum.md` §11
143
+
144
+ | # | TV element | Astroneum design | Inside function |
145
+ |---|---|---|---|
146
+ | 5.1 | OHLC legend (top-left) | ⏳ v1-in-scope — not built | |
147
+ | 5.2 | Right-click context menu | ⏳ v1-in-scope — not built | |
148
+ | 5.3 | Crosshair + labels | ✅ `Crosshair` engine | `Crosshair` |
149
+ | 5.4 | Y-axis scale controls (linear/log/%/indexed) | ✅ `PriceScaleTransform` | `PriceScaleTransform` |
150
+ | 5.5 | X-axis time controls | ✅ engine native | |
151
+ | 5.6 | Data window panel (in right rail — see 3.4) | ❌ | |
152
+ | 5.7 | Last price line + label | ✅ engine native | |
153
+ | 5.8 | Trade markers (entry/exit arrows) | ❌ | |
154
+ | 5.9 | Symbol watermark | ✅ engine native | |
155
+ | 5.10 | Session visualizer lines | ✅ `SessionVisualizer` | `SessionVisualizer` |
156
+
157
+ ## 6. Footer — date range navigator → `design-astroneum.md` §4
158
+
159
+ | # | TV element | Astroneum design | Inside function |
160
+ |---|---|---|---|
161
+ | 6.1 | Date range navigator bar | ✅ `DateRangeNavigator` in `TerminalShell` footer slot — live visible-range readout (scroll/zoom aware via `onVisibleRangeChange`/`onZoom` actions) | `DateRangeNavigator` |
162
+ | 6.2 | Range presets (1D/1W/1M/3M/1Y/5Y/ALL) | ✅ `DateRangeNavigator` — 7 preset buttons, anchor-to-realtime + `zoomAtDataIndex` | `DateRangeNavigator` |
163
+
164
+ ## 7. Modals & dialogs → `STRUCTURE.md` §3.4
165
+
166
+ | # | TV dialog | Astroneum design | Inside function |
167
+ |---|---|---|---|
168
+ | 7.1 | Indicators dialog | ✅ `IndicatorModal` | `IndicatorModal` |
169
+ | 7.2 | Indicator settings (Inputs/Style/Visibility) | 🔧 `IndicatorSettingModal` partial | |
170
+ | 7.3 | Alert dialog | ✅ `AlertModal` | `AlertModal` |
171
+ | 7.4 | Chart settings / properties | ✅ `SettingModal` | `SettingModal` |
172
+ | 7.5 | Screenshot | ✅ `ScreenshotModal` | `ScreenshotModal` |
173
+ | 7.6 | Symbol search | ✅ `SymbolSearchModal` | `SymbolSearchModal` |
174
+ | 7.7 | Timezone | ✅ `TimezoneModal` | `TimezoneModal` |
175
+ | 7.8 | Script editor (Pine) | ✅ `ScriptEditorModal` | `ScriptEditorModal` |
176
+ | 7.9 | Layout templates manager | ❌ | |
177
+ | 7.10 | Indicator templates manager | ❌ | |
178
+
179
+ ## 8. Mobile-specific → `design-astroneum.md` §12
180
+
181
+ | # | TV element | Astroneum design | Inside function |
182
+ |---|---|---|---|
183
+ | 8.1 | Mobile trade pill (`#header-toolbar-trade-mobile`) | ❌ | |
184
+ | 8.2 | Mobile publish button | ⟫ | |
185
+ | 8.3 | Full mobile/touch UX | ⟫ | |
186
+
187
+ ## 9. Structural primitives (shared across all regions)
188
+
189
+ | # | TV element | TV class | Astroneum design | Inside function |
190
+ |---|---|---|---|---|
191
+ | 9.1 | Vertical separator | `separator-LLZAbs0G` | ✅ `DrawingBar` `.split-line` | |
192
+ | 9.2 | Group container | `group-LLZAbs0G` | ✅ `DrawingBar` item `role=group` | |
193
+ | 9.3 | Fill-spacer (push right) | `fill-dlFDN0Zd` | ✅ CSS flex auto | |
194
+ | 9.4 | scrollWrap + noScrollBar | `scrollWrap-wXGVFOC9` | ❌ | |
195
+ | 9.5 | Tooltip system (data-tooltip + hotkey) | apply-common-tooltip | 🔧 class now applied on 1.1 Symbol Search (PeriodBar); rich tooltip layer + hotkey display still missing | |
196
+ | 9.6 | `aria-haspopup="menu"` dropdowns | multiple | 🔧 some modals, menu dropdowns incomplete | |
197
+ | 9.7 | `aria-pressed` toggles | multiple | ✅ `DrawingBar` | |
198
+ | 9.8 | `role=toolbar/radiogroup/group` | multiple | ✅ `PeriodBar` + `DrawingBar` | |
199
+ | 9.9 | Hotkey system (data-tooltip-hotkey) | multiple | 🔧 `useKeyboardShortcuts` chart-nav only | `useKeyboardShortcuts` |
200
+ | 9.10 | SVG icon system (28×28, currentColor) | multiple | ✅ | |
201
+ | 9.11 | Notification badge counter (e.g. Community "5") | `counter-DHGll3AY` | ❌ | |
202
+
203
+ ## 10. Design tokens & CSS → `design-astroneum.md` §2/§3/§7
204
+
205
+ | # | TV element | Astroneum design | Inside function |
206
+ |---|---|---|---|
207
+ | 10.1 | Hashed class names (`button-HdKhcTye`) | ✅ `--astroneum-*` tokens (intentional) | |
208
+ | 10.2 | TV dark palette | ✅ `design-astroneum.md` §2 | |
209
+ | 10.3 | Typography (Trebuchet MS + Inter) | ✅ `design-astroneum.md` §3 | |
210
+ | 10.4 | Motion (none/minimal) | ✅ `design-astroneum.md` §7 | |
211
+ | 10.5 | Light theme | ⟫ | |
212
+ | 10.6 | High-contrast theme | ✅ | `theme="high-contrast"` |
213
+ | 10.7 | 19 locales | 🔧 16 fall back to en-US for new keys | |
214
+
215
+ ---
216
+
217
+ ## Maintenance policy
218
+
219
+ Mirrors `TODO.md` and `STRUCTURE.md` §11. **Update this file on every UI/layout/design change.**
220
+
221
+ ### Triggers — re-scan and patch when any of these change
222
+
223
+ - New / removed / renamed widget in `src/widget/` or component in `demo/src/app/components/`
224
+ - New / removed drawing tool in `src/extension/`
225
+ - New modal / dialog / overlay / panel
226
+ - TopBar / LeftToolbar / RightToolbar / Dock / Footer layout change
227
+ - New hotkey or shortcut (update §9.9 + the relevant §1/§2 row)
228
+ - New tooltip / aria / a11y pattern
229
+ - Theme / palette / typography / motion change
230
+ - New locale or i18n key batch affecting UI strings
231
+ - New chart pane overlay (legend / context menu / data window / markers)
232
+ - Mobile-specific surface added
233
+ - `TerminalShell` slot change
234
+ - New right-rail panel or bottom-dock tab
235
+ - **When a function gets implemented** — fill the "Inside function" cell (was blank)
236
+
237
+ ### Re-scan model
238
+
239
+ On invocation ("refresh design todo"), re-scan live tree (`src/widget/`, `src/extension/`, `demo/src/app/components/`, `src/chart/hooks.ts`), diff against this file, patch rows, append dated changelog entry.
240
+
241
+ ### Consistency check (each refresh)
242
+
243
+ - Every `✅` row still exists in source
244
+ - Every `❌` / `🔧` row hasn't been silently fixed
245
+ - `src/widget/index.tsx` barrel matches `docs/STRUCTURE.md` §3.4
246
+ - `src/extension/index.ts` matches `docs/STRUCTURE.md` §3.7
247
+ - `src/chart/hooks.ts` hotkey list matches §9.9 + §1/§2 hotkey rows
248
+ - "Inside function" cells: blank = no function; filled = function wired. Update when a function lands.
249
+ - Cross-link to `design-astroneum.md` §11/§12 for in-scope/deferred status
250
+ - Cross-link to `tv-functions-skill.md` §3 for TV function catalog
251
+
252
+ ---
253
+
254
+ ## Changelog
255
+ - **2026-07-10** - §1.1 Symbol Search parity pass. PeriodBar symbol trigger now uses title(symbol_search), data-semantic-id(header.symbol_search), and apply-common-tooltip; responsive compact behavior added in period-bar/index.scss (hide symbol text at max-width:600px). Updated §1.1 + §9.5.
256
+
257
+ - **2026-07-08 (d)** — §1 top toolbar: undo/redo + save/load batch (demo-side, no library/`tsup`). **1.12/1.13 ⚠️→✅** — `UndoManager` wired: brand-bar undo/redo buttons (disabled when stack empty) + `Ctrl+Z` / `Ctrl+Y` / `Ctrl+Shift+Z` in `ChartTerminal`'s hotkey `useEffect` (input-field guard so Pine editor/save-prompt aren't hijacked). `record()` via a 600ms poll — `drawing-end` is not emitted (the `EventBus` is defined but never instantiated, and `ActionType` has no overlay action), so mutations are captured by polling `record()` which no-ops when overlays are unchanged (`serializeState` excludes candle data, so cheap); baseline seeded on mount. **1.16/1.17 🔧/❌→✅ + 1.9 🔧→✅** — folded into one `SaveLoadMenu.tsx` (new) backed by `ChartTemplateManager`: "Unnamed" label + Save-as / Load / Clear-drawings / Delete dropdown. **1.5** stays 🔧 — deferred to a library `PeriodBar` pass (overflow dropdown + `,` hotkey). **1.8** ❌→🟦 v1.1 (favorites model). **1.22** ❌→⟫ (mobile). New `terminal.css` `.term-menu*` + `:disabled` rules. Library `hooks.ts` left untouched (Ctrl+Z comment stays — undo is demo-owned, consistent with `/`/`Alt+A`/`Shift+F`). Built (6.2s, types valid) + restarted + verified (HTTP 200, undo button SSR-rendered disabled, PM2 error log empty).
258
+ - **2026-07-08 (c)** — §0 shell grid/behavior aligned to `design-astroneum.md` §4. **G1 dimensions:** `globals.css` tokens 48/60/300/300px+200ms → 44/48/260/220px+240ms (footer 28px unchanged). **G2 sidebar animation:** removed inline `display:none` on `.term-sidebar` (was defeating the grid-track transition → snap instead of slide); added `min-width:0`. **G3 responsive <lg:** `@media(max-width:1024px)` now hides `.term-rail`, forces `--term-sidebar-w:0` + `--term-dock-h:collapsed`, and slims topbar via `.term-spacer ~ *{display:none}` (symbol/timeframe live in the chart's `PeriodBar`). FAB overlay deferred 🟦 v1.1. **G4 persistence:** `TerminalShell` now restores/writes sidebar+dock collapse state to `localStorage` key `astroneum:shell` (decoupled from chart `serializeState` — chrome ≠ chart state); restore deferred to `useEffect` to avoid SSR hydration mismatch. **G5 docs:** fixed stale CSS header comment (footer 22→28px), §0 dimension cells (0.1 42→44, 0.2 52→48), added shell-behavior note + per-row slide/persist annotations; updated `design-astroneum.md` §4 (serializeState wording → localStorage; FAB marked v1.1) + `TODO.md` (shell persistence row). 0.1/0.2 stay 🔧 (content gaps live in §1/§2).
259
+ - **2026-07-08 (b)** — §1 top toolbar audit + build. Three hotkeys wired at library level in `AstroneumChart.tsx` (modal-toggle `useEffect`): 1.7 `/` (indicators), 1.10 `Alt+A` (alerts), 1.20 `Shift+F` (fullscreen) — promoted 🔧→✅. Built **1.18 Quick Search (Ctrl+K)** — `CommandPalette.tsx` in demo: symbol search + timeframe switch + action toggles, `Ctrl+K` listener in `ChartTerminal`. Found 1.15 LayoutPicker stale (already built) — promoted 🟦→✅. Also patched `AstroneumHandle` `useImperativeHandle` (local clone was behind server — missing `createIndicator`/`removeIndicator`/`createOverlay`/`removeOverlay`/`getDataList`/`setData`/`resize`). Library + demo rebuilt, deployed, verified (HTTP 200). Remaining §1 gaps: 1.5 (`,` interval dropdown), 1.16 (save/load UI), 1.12/1.13 (undo/redo buttons), 1.2/1.8/1.17/1.22 (missing).
260
+ - **2026-07-08** — §0 shell regions audit + build. Found server demo ahead of doc: right-rail toggle bar (`SidebarContent` `term-sidebar-strip`, 7 tabs) and bottom-dock tab bar (`DockContent` `term-dock-tabs`, 3 tabs + collapse) already shipped — promoted 0.4, 0.5, 3.1, 3.2, 3.3, 4.1, 4.2, 4.5, 4.7, 4.8 from 🔧/❌ to ✅. Built the one genuinely-missing shell piece: **§0.6 footer date-range navigator** (`DateRangeNavigator.tsx`). 7 presets (1D/1W/1M/3M/1Y/5Y/ALL) anchor to realtime then `zoomAtDataIndex`; live visible-range readout subscribes to engine `onVisibleRangeChange`/`onZoom` actions. Engine bridge via a `ChartPlugin` (`onInit` captures the full `Chart` — `AstroneumHandle` doesn't expose scroll/zoom). Footer token bumped 22px→28px. Deployed + verified (HTTP 200, `term-daterange-*` classes in SSR HTML, no PM2 errors).
261
+ - **2026-07-07** — Initial draft. Design/layout focus — "Inside function" column blank where Astroneum has no function wired. Sourced from three TV HTML snapshots (top toolbar, left drawing toolbar, right toolbar + bottom dock), `docs/STRUCTURE.md`, `docs/tv-functions-skill.md`, `docs/design-astroneum.md`, `INDICATOR_COMPARISON.md`, `docs/TODO.md`, `src/chart/hooks.ts` (hotkey audit), and live source (`src/widget/`, `src/extension/`, `demo/src/app/components/`). 10 sections + shell + maintenance policy. ~110 rows. Hotkey audit confirmed: only chart-nav hotkeys wired; all modal/dialog hotkeys missing. Cross-linked to TODO.md.