@giamme/forge 0.0.0-stage → 0.8.0
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.
- package/CHANGELOG.md +181 -0
- package/LICENSE +21 -0
- package/README.md +1854 -2
- package/SKILL.md +122 -0
- package/VERSION +1 -0
- package/forge +74 -0
- package/package.json +26 -4
- package/references/dataset.md +329 -0
- package/references/decompose.md +667 -0
- package/references/fractal-dashboard.md +21 -0
- package/references/fractal.md +307 -0
- package/references/harnesses.md +353 -0
- package/references/jev.md +865 -0
- package/references/memory.md +228 -0
- package/references/planning.md +42 -0
- package/references/ripwire.md +47 -0
- package/references/runtime.md +64 -0
- package/references/solo.md +113 -0
- package/references/ui.md +112 -0
- package/registry.tsv +81 -0
- package/scripts/forge-artifact.sh +78 -0
- package/scripts/forge-contract.py +430 -0
- package/scripts/forge-dataset.py +6 -0
- package/scripts/forge-dispatch.sh +665 -0
- package/scripts/forge-fail-first.py +195 -0
- package/scripts/forge-fractal-dispatch.sh +4 -0
- package/scripts/forge-fractal-options.sh +54 -0
- package/scripts/forge-fractal.py +6 -0
- package/scripts/forge-guard.py +266 -0
- package/scripts/forge-install-fractal.sh +4 -0
- package/scripts/forge-install-ripwire.sh +52 -0
- package/scripts/forge-install.sh +135 -0
- package/scripts/forge-jev-options.sh +259 -0
- package/scripts/forge-jev.py +6 -0
- package/scripts/forge-lib-plans.sh +785 -0
- package/scripts/forge-lib-review.sh +494 -0
- package/scripts/forge-lib-task.sh +302 -0
- package/scripts/forge-lib-verify.sh +30 -0
- package/scripts/forge-memory.sh +575 -0
- package/scripts/forge-metrics.sh +39 -0
- package/scripts/forge-parallel-options.sh +76 -0
- package/scripts/forge-parallel.sh +1717 -0
- package/scripts/forge-plan-check.py +118 -0
- package/scripts/forge-prompt.py +45 -0
- package/scripts/forge-ripwire.py +136 -0
- package/scripts/forge-route.py +344 -0
- package/scripts/forge-runtime.py +533 -0
- package/scripts/forge-schedule.py +312 -0
- package/scripts/forge-shadow.py +305 -0
- package/scripts/forge-solo.sh +347 -0
- package/scripts/forge-ui-options.sh +42 -0
- package/scripts/forge-ui.py +435 -0
- package/scripts/forge-update.sh +71 -0
- package/scripts/forge-verify-coverage.py +956 -0
- package/scripts/forge-version.py +198 -0
- package/scripts/forge_dataset/__init__.py +439 -0
- package/scripts/forge_dataset/capture.py +330 -0
- package/scripts/forge_dataset/checks.py +109 -0
- package/scripts/forge_dataset/cli.py +233 -0
- package/scripts/forge_dataset/export.py +1009 -0
- package/scripts/forge_dataset/harvest.py +716 -0
- package/scripts/forge_dataset/importer.py +412 -0
- package/scripts/forge_dataset/outcomes.py +275 -0
- package/scripts/forge_dataset/routing.py +278 -0
- package/scripts/forge_fractal/__init__.py +83 -0
- package/scripts/forge_fractal/bridge.py +46 -0
- package/scripts/forge_fractal/cli.py +202 -0
- package/scripts/forge_fractal/dashboard.css +138 -0
- package/scripts/forge_fractal/dashboard.html +41 -0
- package/scripts/forge_fractal/dashboard.js +687 -0
- package/scripts/forge_fractal/decomposition.py +262 -0
- package/scripts/forge_fractal/execution.py +659 -0
- package/scripts/forge_fractal/inspection.py +261 -0
- package/scripts/forge_fractal/install.py +158 -0
- package/scripts/forge_fractal/invocation.py +94 -0
- package/scripts/forge_fractal/pipeline.py +124 -0
- package/scripts/forge_fractal/selection.py +179 -0
- package/scripts/forge_jev/__init__.py +376 -0
- package/scripts/forge_jev/backtest.py +322 -0
- package/scripts/forge_jev/cli.py +980 -0
- package/scripts/forge_jev/client.py +418 -0
- package/scripts/forge_jev/corpus.py +156 -0
- package/scripts/forge_jev/coupling.py +244 -0
- package/scripts/forge_jev/features.py +24 -0
- package/scripts/forge_jev/gates.py +100 -0
- package/scripts/forge_jev/memory.py +163 -0
- package/scripts/forge_jev/outcome.py +49 -0
- package/scripts/forge_jev/predict.py +204 -0
- package/scripts/forge_jev/questions.py +661 -0
- package/scripts/forge_jev/review.py +73 -0
- package/scripts/forge_jev/routing.py +271 -0
- package/scripts/forge_jev/subset.py +123 -0
- package/scripts/forge_jev/verify.py +453 -0
- package/scripts/forge_registry.py +140 -0
- package/ui/README.md +287 -0
- package/ui/THIRD_PARTY_NOTICES.md +69 -0
- package/ui/docs/api.md +888 -0
- package/ui/forge_ui/__init__.py +20 -0
- package/ui/forge_ui/__main__.py +135 -0
- package/ui/forge_ui/diffs.py +454 -0
- package/ui/forge_ui/executions.py +436 -0
- package/ui/forge_ui/export.py +204 -0
- package/ui/forge_ui/findings.py +132 -0
- package/ui/forge_ui/fractal.py +583 -0
- package/ui/forge_ui/models.py +216 -0
- package/ui/forge_ui/reader.py +1336 -0
- package/ui/forge_ui/server.py +303 -0
- package/ui/forge_ui/static/app.js +924 -0
- package/ui/forge_ui/static/cloud3d.js +646 -0
- package/ui/forge_ui/static/cloudmodel.js +375 -0
- package/ui/forge_ui/static/cloudui.js +394 -0
- package/ui/forge_ui/static/diffview.js +216 -0
- package/ui/forge_ui/static/favicon.svg +1 -0
- package/ui/forge_ui/static/files.js +776 -0
- package/ui/forge_ui/static/gantt.js +97 -0
- package/ui/forge_ui/static/graph.js +266 -0
- package/ui/forge_ui/static/index.html +55 -0
- package/ui/forge_ui/static/iso.js +765 -0
- package/ui/forge_ui/static/leaderboard.js +315 -0
- package/ui/forge_ui/static/map3d.js +45 -0
- package/ui/forge_ui/static/modelstats.js +249 -0
- package/ui/forge_ui/static/notify.js +179 -0
- package/ui/forge_ui/static/panel.js +526 -0
- package/ui/forge_ui/static/runmodel.js +651 -0
- package/ui/forge_ui/static/scene3d.js +996 -0
- package/ui/forge_ui/static/search.js +119 -0
- package/ui/forge_ui/static/style.css +618 -0
package/ui/README.md
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# forge-ui
|
|
2
|
+
|
|
3
|
+
forge-ui is a small, read-only local web UI for forge runs. It draws them the way
|
|
4
|
+
[archivision](https://github.com/Giamme/archivision) draws a codebase: a 3D isometric map of
|
|
5
|
+
blocks on a plate, with cables between them and lamps that light up as things happen.
|
|
6
|
+
|
|
7
|
+
- **A map of every run**, one district per repo and one block per run, with a lamp per task.
|
|
8
|
+
Filter it by state, repo, kind, model, age or review verdict; what does not match fades
|
|
9
|
+
instead of disappearing.
|
|
10
|
+
- **A run, as planned and as it ran.** *Planned waves* puts each task in its wave, with
|
|
11
|
+
dependency cables, and ends in a *finish* line of three nodes: integration, verification
|
|
12
|
+
and the whole-run **final review**. *Execution* lays the same work out on wall-clock time:
|
|
13
|
+
one block per attempt, in the lane it really ran in, with its dwarf and review inside, the
|
|
14
|
+
attempts that have not started projected by forge-schedule's own rules, and a strip of how
|
|
15
|
+
many slots were busy against `--max-parallel`. Switching between the two moves each task
|
|
16
|
+
from its wave to where it ran.
|
|
17
|
+
- **Click to open.** A task opens to show its attempts, each with its dwarf, its reviewer and
|
|
18
|
+
any shadow reviews, linked; an escalation is a labelled cable between attempts. The
|
|
19
|
+
inspector beside the stage shows what launched each step and what came of it: the exact
|
|
20
|
+
prompt, the model (alias, harness, model, effort, clamping), the timings by phase, tokens,
|
|
21
|
+
the verdict, and every **P0–P3 finding** of every review, the final review included.
|
|
22
|
+
- **Live.** Statuses change in place while a run works (every 2 s while something runs, 5 s
|
|
23
|
+
otherwise); running nodes pulse and show their current phase.
|
|
24
|
+
- **Extras:** replay a run from its recorded times, light its critical path, set block height
|
|
25
|
+
and colour by duration, tokens, attempts or model, and mark shadow reviews that disagreed
|
|
26
|
+
with the primary and how sure Clef was that each task would pass.
|
|
27
|
+
- **Beyond one run:** a full-screen **run cloud** of every run, grouped by project, in five
|
|
28
|
+
layouts with filters and runs you can drag anywhere; **diffs** with each finding under the
|
|
29
|
+
line it names; a **model leaderboard**; a **files heatmap**; **Fractal** child-task trees;
|
|
30
|
+
**quick jump** and **notifications**; and **export** of a run as one HTML file. See
|
|
31
|
+
[What you see](#what-you-see).
|
|
32
|
+
|
|
33
|
+
<p align="center">
|
|
34
|
+
<img src="docs/media/hero.webp" width="860" alt="A decomposed run on its 3D plate: eight tasks in their planned waves, then the same run on wall-clock time, where two first attempts that failed review show in red beside the retries that passed.">
|
|
35
|
+
</p>
|
|
36
|
+
|
|
37
|
+
The 3D view loads three.js from a CDN the first time it is used (see [Privacy](#privacy)).
|
|
38
|
+
Without it (offline, an old browser, no WebGL) the same page shows the 2D dependency graph,
|
|
39
|
+
an execution chart and the same inspector. The server is Python's standard library; there
|
|
40
|
+
is no install or build step.
|
|
41
|
+
|
|
42
|
+
It lives inside forge, in `ui/`, and is forge's companion: runs open it with `--ui`.
|
|
43
|
+
|
|
44
|
+
## Run it
|
|
45
|
+
|
|
46
|
+
Normally forge launches it. `forge ui open [DIR]` (from the forge checkout) starts or
|
|
47
|
+
reuses one shared detached server and prints the link to a run dir, `forge ui status`
|
|
48
|
+
shows it and `forge ui stop` ends it; see [references/ui.md](../references/ui.md). A run
|
|
49
|
+
starts it itself with `forge-solo.sh --ui` or `forge-parallel.sh plan --ui`.
|
|
50
|
+
|
|
51
|
+
To run the server directly, from `ui/`:
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
python3 -m forge_ui
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Open the printed URL (default `http://127.0.0.1:8765/`). Stop with Ctrl-C.
|
|
58
|
+
|
|
59
|
+
- `--plan DIR`: add one plan directory; repeatable, default none.
|
|
60
|
+
- `--root DIR`: scan for plan directories at depth 0–2; repeatable, default none.
|
|
61
|
+
- `--no-registry`: disable the registry, which is read by default.
|
|
62
|
+
- `--registry-dir DIR`: override the registry directory described below.
|
|
63
|
+
- `--port N`: use port N, default `8765`; `0` selects a free port.
|
|
64
|
+
- `--quiet`: suppress request logging; off by default (errors can still be logged).
|
|
65
|
+
- `--open`: open the browser after startup; off by default.
|
|
66
|
+
- `--idle-exit SECONDS`: exit after that many idle seconds; default `0` (never). `forge ui` sets it from `FORGE_UI_IDLE_S`.
|
|
67
|
+
- `--version`: print the version and exit.
|
|
68
|
+
- `-h`, `--help`: print usage and exit.
|
|
69
|
+
|
|
70
|
+
Three examples (replace the example paths with your own):
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
# Registry only
|
|
74
|
+
python3 -m forge_ui
|
|
75
|
+
# One plan directory only
|
|
76
|
+
python3 -m forge_ui --no-registry --plan /path/to/plan
|
|
77
|
+
# A root containing many runs, without registry entries
|
|
78
|
+
python3 -m forge_ui --no-registry --root /path/to/runs
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
No runs yet? `tools/demo_runs.py` writes made-up ones, the same that fill the pictures here: a
|
|
82
|
+
live run and a few weeks of history across five projects.
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
python3 tools/demo_runs.py /tmp/forge-demo
|
|
86
|
+
python3 -m forge_ui --no-registry --root /tmp/forge-demo --open
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Where runs come from
|
|
90
|
+
|
|
91
|
+
Sources are checked in this order:
|
|
92
|
+
|
|
93
|
+
1. Explicit `--plan DIR` directories.
|
|
94
|
+
2. `--root DIR` itself, its children and grandchildren. Scanning stops when a plan
|
|
95
|
+
directory is found; hidden children and symlinked child directories are skipped.
|
|
96
|
+
3. Forge's registry: `*.txt` files in `$XDG_CONFIG_HOME/forge/runs/`, defaulting
|
|
97
|
+
to `~/.config/forge/runs/` when XDG_CONFIG_HOME is unset or empty. Each file
|
|
98
|
+
supplies absolute paths, one per line; blank lines and `#` comments are ignored.
|
|
99
|
+
`--registry-dir` replaces this location; `--no-registry` disables it.
|
|
100
|
+
|
|
101
|
+
Plan directories (containing a `tasks.tsv` file) and solo run directories (a `prompt.md`
|
|
102
|
+
and a `repo` file) appear through `--plan` and the registry; `--root` finds plan directories
|
|
103
|
+
only. Stale or invalid paths are skipped. Duplicate real paths appear once,
|
|
104
|
+
with the first source winning. Discovery and disk reads repeat on each API request.
|
|
105
|
+
|
|
106
|
+
## What you see
|
|
107
|
+
|
|
108
|
+
- **Map (`#/`):** every discovered run, newest first, grouped by repo. By default the last
|
|
109
|
+
60 runs from the past 14 days; *older runs too* shows the rest. The sidebar list follows
|
|
110
|
+
the same filter.
|
|
111
|
+
|
|
112
|
+
<img src="docs/media/map.png" width="760" alt="The map: one block per run, in a district per repo, green when done, blue while running, red with failures.">
|
|
113
|
+
- **Run cloud (`#/cloud`):** every run at once, full screen, floating in 3D and grouped by project
|
|
114
|
+
(repo). Pick a layout: *Helix* (one spiral per project, oldest at the bottom), *Sphere*,
|
|
115
|
+
*Galaxy* (a disc per project, newest at the centre), *Timeline* (left to right by start time,
|
|
116
|
+
one lane per project) or *Constellation* (pulled together by project and shared models, with
|
|
117
|
+
lines joining each project's nearest runs). Runs are *Blocks* (a lamp per task on the roof) or
|
|
118
|
+
*Orbs* (a ring of task segments); size is the number of tasks, colour the run's state. The
|
|
119
|
+
filter panel narrows the cloud to exactly the runs wanted: projects, state, kind, difficulty
|
|
120
|
+
(has a task of, or mostly), tasks per run, models (any role, implementer or reviewer), recent
|
|
121
|
+
activity, final review, verification, decompose level and text (goals, ids, task titles).
|
|
122
|
+
Orbit, pan and zoom anywhere; drag a run to put it where you want (Shift: nearer or further,
|
|
123
|
+
Alt: up or down). Dropped positions are kept in this browser per layout; *Positions* resets them
|
|
124
|
+
(with undo) or exports and imports them as a JSON file. Click a run for its card, double-click
|
|
125
|
+
to open it; `#/cloud/runs/<key>` and `#/cloud/projects/<id>` link to a selection. Keys:
|
|
126
|
+
arrows orbit, + − zoom, F frames, P steps through projects, [ ] through runs, L changes the
|
|
127
|
+
layout, B the shape, 0 resets the view, Esc steps back. With *2D*, the cloud lists the same
|
|
128
|
+
filtered runs and offers *Load 3D*.
|
|
129
|
+
|
|
130
|
+
<img src="docs/media/cloud.webp" width="760" alt="The run cloud orbited, then laid out as galaxies and as a timeline with one lane per project.">
|
|
131
|
+
- **Run (`#/runs/<key>`):** a header (goal, repo, counts, and *Run details*: settings, request,
|
|
132
|
+
waves, verification output), a toolbar (*Planned waves* / *Execution*, *3D* / *2D*, height
|
|
133
|
+
and colour overlays, *Critical path*, *Review marks*, *Projected*, *Replay*), the stage with
|
|
134
|
+
the inspector beside it, and the task table.
|
|
135
|
+
|
|
136
|
+
<img src="docs/media/run.png" width="49%" alt="Planned waves: a run's tasks on a 3D plate with dependency cables and the finish nodes, beside the run's inspector."> <img src="docs/media/execution.png" width="49%" alt="Execution: one block per attempt on wall-clock time, failed attempts in red, with the timeline and critical path in the inspector.">
|
|
137
|
+
- **Inspector:** for the run, its timeline, critical path, peak concurrency and finish line;
|
|
138
|
+
for a task, its models and routing, escalations, timings (busy, model time, overhead,
|
|
139
|
+
queue wait after its dependencies merged), attempts and their executions, review findings
|
|
140
|
+
with the gate decision, Clef predictions against outcomes, and its prompts; for one
|
|
141
|
+
execution, its model, phases, tokens, exact prompt and final message; for the final
|
|
142
|
+
review, its verdict, findings, report, prompt and history.
|
|
143
|
+
- **Files (the run toolbar's third mode):** a heatmap of files (grouped and collapsible by
|
|
144
|
+
directory) against tasks (grouped by wave): planned files outlined, touched files filled by how
|
|
145
|
+
many attempts changed them, drift hatched, merge conflicts ringed, and a dot where another task
|
|
146
|
+
of the same wave planned or touched the file too. Filter by path, sort by path, most touched or
|
|
147
|
+
most tasks, and hide any kind of mark; a cell selects its task and offers that file's diff.
|
|
148
|
+
Below: overlaps, drift, merge conflicts and deferrals as lists.
|
|
149
|
+
|
|
150
|
+
<img src="docs/media/files.png" width="560" alt="The files heatmap: files by directory against tasks by wave, with planned, touched, drift and same-wave overlap marks.">
|
|
151
|
+
- **Models (`#/models`):** a leaderboard of the models forge used. Implementers: tasks, first-attempt
|
|
152
|
+
pass rate with its 95% Wilson interval, censored attempts, retries, escalations away from the
|
|
153
|
+
model, timeouts, gate and human accepts, median model time and tokens. Reviewers: primary,
|
|
154
|
+
shadow and final reviews, the PASS/FAIL split, findings per review by severity, and how often a
|
|
155
|
+
shadow review agreed with the primary. Filter by project, difficulty, kind and period, or keep
|
|
156
|
+
only exploratory picks; open a difficulty for its own table. Routing is not random, so the
|
|
157
|
+
numbers compare what happened, not what would have: the page says so. A model's name opens the
|
|
158
|
+
run cloud filtered to its runs.
|
|
159
|
+
|
|
160
|
+
<img src="docs/media/models.png" width="760" alt="The implementers table: tasks, first-attempt pass rate with its 95% interval, retries, escalations, timeouts, accepts, median model time and tokens per model.">
|
|
161
|
+
- **Diffs (`…/tasks/<id>/diff[/<source>][/file/<path>]`, `…/final-review/<name>/diff`):** a task's
|
|
162
|
+
`changes.diff`, its previous or committed diff, or exactly the diff one reviewer read (the last
|
|
163
|
+
diff in that review's prompt), picked from a row of sources with each review's verdict; a final
|
|
164
|
+
review's combined diff. Files are listed with their +/− counts and how many findings point
|
|
165
|
+
into them; each finding is shown under the line it names, those on a line outside the changed
|
|
166
|
+
hunks at the top of their file, and those whose file is not in the diff (or that name no
|
|
167
|
+
location) in a section of their own. n and p move between findings, j and k between files.
|
|
168
|
+
Open it from a task, an attempt's review, an execution or the final review in the inspector.
|
|
169
|
+
|
|
170
|
+
<img src="docs/media/diff.png" width="760" alt="The diff a reviewer read, with a P1 finding under the line that compares token digests and a P2 finding under the revoke function.">
|
|
171
|
+
- **Fractal child tasks:** when a run used Fractal, a task's inspector shows the tree it was split
|
|
172
|
+
into (status, difficulty, model, phase, cost, the split decision), and the opened task in 3D
|
|
173
|
+
carries the same tree floating above it. A node (`…/tasks/<id>/fractal/<node>`) shows its goal,
|
|
174
|
+
paths, timings, cost and tokens, its decomposition and the children it admitted, its last
|
|
175
|
+
messages, and its candidate diff. Fractal's state is read under `$XDG_STATE_HOME/forge/fractal`
|
|
176
|
+
(default `~/.local/state`), read-only, without following symlinks.
|
|
177
|
+
- **Export:** *Export…* in a run's header downloads the run as one HTML file that opens in any
|
|
178
|
+
browser without forge-ui, offline included (in 2D; in 3D when cdn.jsdelivr.net is reachable).
|
|
179
|
+
It asks each time: by default prompts, reviewer reports, logs, finding details and diffs are
|
|
180
|
+
left out (each finding's headline stays) and local paths are reduced to their last component.
|
|
181
|
+
The file states what it left out, and fetches nothing but three.js: its own policy allows only
|
|
182
|
+
its inline scripts, by hash.
|
|
183
|
+
- **Quick jump:** Ctrl K (⌘K on a Mac), `/` or *Search* opens one search over every run (goal,
|
|
184
|
+
run id, repo, models), task (id and title), project, model and command. Enter opens the pick;
|
|
185
|
+
Shift+Enter shows a run in the cloud; a model shows its runs in the cloud. With nothing typed,
|
|
186
|
+
recent picks and running runs come first.
|
|
187
|
+
- **Notifications:** the bell lists what changed while the page was open: a run that finished or
|
|
188
|
+
ended with failures, a task that failed (FAIL, ERROR, CONFLICT, TIMEOUT, INVALIDATED,
|
|
189
|
+
INTERRUPTED or BLOCKED; INFRA retries are not failures) and a final review's verdict, each
|
|
190
|
+
linked to it. Unread ones show as a count in the tab title and a dot on its icon. *Enable
|
|
191
|
+
browser notifications* asks the browser once; then changes also show as system notifications
|
|
192
|
+
while the tab is in the background, and a hidden tab checks the run list every 30 seconds
|
|
193
|
+
(browsers may check less often after a while). Open tabs share one log and notify once. Runs
|
|
194
|
+
that have not changed for two hours never notify.
|
|
195
|
+
- **Keys on the stage:** ← → move between tasks, Esc closes, `e` switches plan and
|
|
196
|
+
execution. Drag to orbit, right-drag to pan, scroll to zoom once the stage is clicked.
|
|
197
|
+
|
|
198
|
+
URLs such as `http://127.0.0.1:8765/#/runs/<key>/tasks/<id>` are shareable within the
|
|
199
|
+
machine while this server is running and discovering that run dir. *Live refresh* pauses
|
|
200
|
+
polling; a hidden tab polls only the run list, every 30 seconds, and only with browser
|
|
201
|
+
notifications on. Failed requests keep the last good data and show a banner.
|
|
202
|
+
|
|
203
|
+
## Layout of the code
|
|
204
|
+
|
|
205
|
+
- `forge_ui/reader.py`: discover runs, parse their files and produce summaries and details.
|
|
206
|
+
- `forge_ui/executions.py`: the per-dispatch records (`attempts/<role>-<uuid>/`), nested and
|
|
207
|
+
matched to attempts, through a cache keyed by each file's identity and mtime.
|
|
208
|
+
- `forge_ui/findings.py`: P0–P3 findings and the gate, parsed by forge's own `scripts/forge-contract.py`.
|
|
209
|
+
- `forge_ui/server.py`: serve the JSON API and static assets, with GET/HEAD only.
|
|
210
|
+
- `forge_ui/__main__.py`: CLI options, local startup and optional browser opening.
|
|
211
|
+
- `forge_ui/__init__.py`: package version and the build id `forge ui` compares to find a stale server.
|
|
212
|
+
- `forge_ui/static/index.html`, `style.css`, `app.js`: the page shell, styles, routes, views and polling.
|
|
213
|
+
- `forge_ui/static/runmodel.js`: the pure run model (layouts, schedule projection, critical path, replay).
|
|
214
|
+
- `forge_ui/static/panel.js`, `gantt.js`, `graph.js`: the inspector, the execution chart and strip, the 2D graph.
|
|
215
|
+
- `forge_ui/static/map3d.js`, `scene3d.js`, `iso.js`: the 3D loader, scenes and engine (ported from archivision).
|
|
216
|
+
- `forge_ui/static/cloudmodel.js`, `cloud3d.js`, `cloudui.js`: the run cloud's pure model (projects,
|
|
217
|
+
filters, layouts, layout files), its scene on the shared stage, and its controls.
|
|
218
|
+
- `forge_ui/static/diffview.js`: the diff viewer, with findings pinned to their lines.
|
|
219
|
+
- `forge_ui/static/files.js`: the files heatmap (`matrix()` is pure and node-tested).
|
|
220
|
+
- `forge_ui/export.py`: a run as one HTML file (the page's scripts and styles inlined, the API
|
|
221
|
+
responses it reads, the 3D stage's modules as one module text, a hash-based policy).
|
|
222
|
+
- `forge_ui/static/modelstats.js`, `leaderboard.js`: the leaderboard's aggregation (outcomes as
|
|
223
|
+
`scripts/forge_dataset/export.py` labels them, the interval of its `routing.py`) and its page.
|
|
224
|
+
- `forge_ui/diffs.py`, `fractal.py`, `models.py`: diff parsing and finding pins, the Fractal state
|
|
225
|
+
reader, and the facts behind the model leaderboard.
|
|
226
|
+
- `forge_ui/static/search.js`, `notify.js`, `favicon.svg`: the quick jump and the notifications
|
|
227
|
+
(ranking and change detection are in `runmodel.js`).
|
|
228
|
+
- `tests/`: reader, executions, endpoints, server, static-script and browser checks; `run_fixture.py`
|
|
229
|
+
builds realistic runs in a temp dir (`python3 tests/run_fixture.py DIR` writes two you can open),
|
|
230
|
+
and `many_fixture.py` many small ones across repos for the cloud (`python3 tests/many_fixture.py DIR 300`).
|
|
231
|
+
- `tools/demo_runs.py`, `tools/readme_media.py`: made-up runs to look around with (one live run
|
|
232
|
+
and five projects of history), and the script that turns them into the READMEs' pictures in
|
|
233
|
+
`docs/media/`.
|
|
234
|
+
- [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md): the licences of the ported and loaded code;
|
|
235
|
+
forge-ui itself is under forge's [MIT License](../LICENSE).
|
|
236
|
+
|
|
237
|
+
[docs/api.md](docs/api.md) is the data contract between the reader, server and page.
|
|
238
|
+
|
|
239
|
+
### Known differences from docs/api.md
|
|
240
|
+
|
|
241
|
+
- Root discovery stops at a discovered plan and skips symlinked child directories;
|
|
242
|
+
it does not visit every nested plan within depth 2.
|
|
243
|
+
- The reader accepts wave numbers only from 1 to 10,000 and warns about other values.
|
|
244
|
+
- List `updated` timestamps cover the directory and summary inputs; detail timestamps
|
|
245
|
+
additionally cover files read for the task panels and other run details.
|
|
246
|
+
- The server rejects Host headers other than `127.0.0.1` or `localhost` (optional
|
|
247
|
+
port) with `403`; an absent Host is accepted. This also precedes method rejection.
|
|
248
|
+
- Static filenames must contain only letters, digits, `_`, `-` and `.` and must
|
|
249
|
+
not contain `..`; resolved files must be directly inside the static directory.
|
|
250
|
+
|
|
251
|
+
## Develop
|
|
252
|
+
|
|
253
|
+
Use Python 3.9+ to run the server and tests. Node.js 18+ runs the JavaScript checks; use a
|
|
254
|
+
modern browser for the page (import maps: Chrome 89, Firefox 108, Safari 16.4). No Python or
|
|
255
|
+
Node packages need installing.
|
|
256
|
+
|
|
257
|
+
Run these from `ui/`:
|
|
258
|
+
|
|
259
|
+
```sh
|
|
260
|
+
python3 -m unittest discover -s tests # includes the syntax checks and node --test
|
|
261
|
+
node --test tests/js/*.test.js # the run and cloud models alone
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
`tests/test_browser.py` drives the page in Chromium when Python Playwright is installed, and
|
|
265
|
+
skips otherwise. Its 3D tests need three.js: the CDN, or a local copy of the npm package
|
|
266
|
+
(`npm pack three@0.160.0`, unpacked) named by `FORGE_UI_TEST_THREE=<dir>/package`.
|
|
267
|
+
|
|
268
|
+
The pictures in this README and forge's come from `tools/readme_media.py`. After a change you
|
|
269
|
+
can see, run it again: it builds the demo runs, serves them, and captures each view in
|
|
270
|
+
Chromium with Playwright (three.js as for the browser tests; ffmpeg with libwebp and ImageMagick
|
|
271
|
+
to encode the animations and PNGs). `--only cloud diff` retakes some of them.
|
|
272
|
+
|
|
273
|
+
```sh
|
|
274
|
+
python3 tools/readme_media.py # writes docs/media/
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Privacy
|
|
278
|
+
|
|
279
|
+
Run dirs can contain prompts, diffs and review text from private repos. The server binds
|
|
280
|
+
only `127.0.0.1`, makes no network requests, and writes nothing to run dirs, repositories or
|
|
281
|
+
forge's config. Anyone with access to the local server can read the runs it discovers, and
|
|
282
|
+
forge now registers every run, so that is every run on the machine.
|
|
283
|
+
|
|
284
|
+
The 3D view loads three.js 0.160.0 from `cdn.jsdelivr.net` the first time it is shown in a
|
|
285
|
+
tab: the browser asks the CDN for those script files and sends nothing about your runs
|
|
286
|
+
(`Referrer-Policy: no-referrer`, and the page's CSP allows only that one package). Choose
|
|
287
|
+
**2D** in the toolbar and the browser remembers it and never contacts the CDN.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
forge-ui's 3D view is ported from archivision and draws in the iso-glow style. The served
|
|
4
|
+
copies of that code (`forge_ui/static/iso.js`, `scene3d.js` and `runmodel.js`) carry these
|
|
5
|
+
notices in their head comments; this file keeps them with the source.
|
|
6
|
+
|
|
7
|
+
## archivision
|
|
8
|
+
|
|
9
|
+
`forge_ui/static/iso.js` and `scene3d.js` port `assets/shell-3d.html` and `assets/figure.js`;
|
|
10
|
+
`forge_ui/static/runmodel.js` ports `lib/layout.js` (https://github.com/Giamme/archivision).
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
MIT License
|
|
14
|
+
|
|
15
|
+
Copyright (c) 2026 Giamme
|
|
16
|
+
|
|
17
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
18
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
19
|
+
in the Software without restriction, including without limitation the rights
|
|
20
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
21
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
22
|
+
furnished to do so, subject to the following conditions:
|
|
23
|
+
|
|
24
|
+
The above copyright notice and this permission notice shall be included in all
|
|
25
|
+
copies or substantial portions of the Software.
|
|
26
|
+
|
|
27
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
28
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
29
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
30
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
31
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
32
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
33
|
+
SOFTWARE.
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## iso-glow and iso-figure
|
|
37
|
+
|
|
38
|
+
archivision's shell and the drawing style of its figures come from iso-glow, which is based
|
|
39
|
+
on iso-figure. The same code is in `forge_ui/static/iso.js` and `scene3d.js`.
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
MIT License
|
|
43
|
+
|
|
44
|
+
Copyright (c) 2026 April Zhu (iso-glow: lighting, palettes, gallery shell, examples)
|
|
45
|
+
Copyright (c) 2026 Tolga Cohce (iso-figure, on which iso-glow is based)
|
|
46
|
+
|
|
47
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
48
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
49
|
+
in the Software without restriction, including without limitation the rights
|
|
50
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
51
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
52
|
+
furnished to do so, subject to the following conditions:
|
|
53
|
+
|
|
54
|
+
The above copyright notice and this permission notice shall be included in all
|
|
55
|
+
copies or substantial portions of the Software.
|
|
56
|
+
|
|
57
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
58
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
59
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
60
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
61
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
62
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
63
|
+
SOFTWARE.
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## three.js
|
|
67
|
+
|
|
68
|
+
three.js 0.160.0 (MIT, Copyright © 2010-2023 three.js authors) is not part of forge. The page
|
|
69
|
+
loads it, with its `examples/jsm` add-ons, from `cdn.jsdelivr.net` when the 3D view is used.
|