Repository navigation
editor: streaming, live work motion, inbox sidebar, approvals, context meter #502
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6688190
cce1587
7eedc9d
a1ed801
685fd19
5634666
e5cf606
3a164b9
dc19f2b
ee81080
b21660c
06be98b
aaee7c0
f725d31
429f43a
2328682
f7a3412
56c10fc
b4a0917
01b0913
e17d444
690a7bf
dde17d4
02805c1
e26c297
c24b57f
6289d26
bf18811
dd15bf7
c305573
9278979
cf397f1
709f020
379bc33
3ff2db6
1266e83
837f72f
5de5979
b3a9568
3fdf308
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| # Editor and Forge flight recorder | ||
|
|
||
| Debug payloads from `nix run .#dev` include the local flight recorder and start | ||
| it automatically. Use the app normally. A stalled UI, stalled operation, busy | ||
| admission, failed request, or failed navigation saves a Chrome Trace Event JSON | ||
| file that opens directly in [Perfetto](https://ui.perfetto.dev/). | ||
|
|
||
| Press **Ctrl+Shift+F11** to save recent Editor activity immediately. Automatic | ||
| incidents retain two seconds after the trigger; normal exit saves another | ||
| snapshot. This works for detached Windows launches without stdout capture. | ||
|
|
||
| Files go to `%TEMP%\artisan-traces` on Windows and `$TMPDIR/artisan-traces` | ||
| on Unix, normally `/tmp/artisan-traces`. `ARTISAN_TRACE_DIR` selects another | ||
| directory. Editor and Forge write on their respective machines, so a WSL | ||
| Forge's files are on Linux. The newest sixteen JSON files per application are | ||
| retained across process restarts. `ARTISAN_TRACE=0` disables recording at launch. | ||
| Set these variables in the environment of the actual Editor/Forge process; | ||
| an already running Forge service does not inherit a new terminal environment. | ||
|
|
||
| ## What to inspect | ||
|
|
||
| The history covers up to two minutes or 32,768 events, whichever fits first. | ||
| High frame rates shorten the retained time window. Traces contain: | ||
|
|
||
| - UI and transport heartbeats, with stalled/resumed breadcrumbs; | ||
| - GPUI CPU draws and renderer submission durations, dirty-to-draw latency, | ||
| animation intervals, and foreground task polls over ten milliseconds; | ||
| - UI handlers, route mounting, snapshots, patch processing, and event batches; | ||
| - command queue depth, admission/rejection, queue waits, execution spans, | ||
| producer-to-consumer flow arrows, and thread identities; | ||
| - correlated wire requests, response-family expectations, outcomes, and | ||
| reconnect/subscription work; | ||
| - recent-thread waits, thread-switch generations/phases, project intake, | ||
| navigation gates, pending unsubscribe, and connection holds; | ||
| - matching Forge request spans and event-loop stall reports. | ||
|
|
||
| Async spans have unique IDs and use `b`/`e`, so concurrent work and executor | ||
| migration do not produce falsely nested synchronous slices. Unfinished spans | ||
| are closed at the capture boundary with `unfinished=true`. A beginning that | ||
| aged out is marked `begin_truncated=true`. `dropped_records` and | ||
| `evicted_records` make recording loss explicit. Thread-switch state includes | ||
| its owning span ID; request spans include the command span that issued them. | ||
|
|
||
| For the delayed busy notification, search for `recent_thread.failed`, then | ||
| inspect `navigation.gates` immediately before it. The ten-second recent-thread | ||
| wait ends with that failure if navigation is still inadmissible. Follow the | ||
| switch phase, outstanding command, and request rather than inferring that the | ||
| clicked thread itself was busy. | ||
|
|
||
| Use `python3 scripts/trace.py summary TRACE.json` for a text report of the | ||
| longest operations and the last navigation gates. To combine local Editor and | ||
| Forge exports into one Perfetto timeline: | ||
|
|
||
| ```sh | ||
| python3 scripts/trace.py merge combined.json editor-TRACE.json forge-TRACE.json | ||
| ``` | ||
|
|
||
| Matching `request_id` values connect processes. Timestamps use Unix | ||
| microseconds anchored to each process's monotonic clock. Different machines | ||
| need synchronized wall clocks for visual alignment; IDs remain useful when | ||
| their clocks differ. Merge remaps process IDs to avoid Windows/Linux PID | ||
| collisions and distinguishes process restarts. Overlapping captures are | ||
| deduplicated; real span completions supersede synthetic snapshot boundaries. | ||
|
|
||
| ## Build-time removal | ||
|
|
||
| The shared `artisan-tracing` module has no default features. Without `enabled`, | ||
| it contains only macros that erase their arguments. It has no recorder, | ||
| serialization dependency, environment handling, filesystem writer, or watchdog. | ||
| Each application also gates all tracing fields, startup tasks, and adapters | ||
| behind its `flight-recorder` Cargo feature. Production's Nix feature list is | ||
| empty, so the tracing implementation is absent from the binaries. | ||
|
|
||
| For a Cargo diagnostic build, enable `artisan-frontend/flight-recorder` and | ||
| `artisan-backend/flight-recorder`. Build without either for the normal | ||
| production behavior. Cargo features are additive; deliberately enabling these | ||
| features on a custom release build deliberately includes the recorder. | ||
|
|
||
| ## Cost and limits | ||
|
|
||
| UI and transport producers use bounded, nonblocking sends. History collection | ||
| and filesystem output run on separate threads. Saturation drops records rather | ||
| than waiting. Arguments accept only bounded scalar values. Instrumentation | ||
| records fixed operation names, opaque IDs, enum states, counters, and source | ||
| locations; it does not record prompts, thread titles, file targets, credentials, | ||
| URLs, snapshots, screenshots, or provider payloads. Files are local, and Unix | ||
| exports are created with owner-only permissions. | ||
|
|
||
| The UI watchdog triggers after 500 ms without a foreground heartbeat. A long | ||
| navigation/project/request span triggers after five seconds. Automatic | ||
| captures have a ten-second cooldown. The existing Forge watchdog triggers at | ||
| two seconds. Whole-process suspension is reported separately by the watchdogs. | ||
| Recording is instrumentation, not native stack sampling: an uninstrumented | ||
| blocking function may still need an OS profiler. Completed GPUI task records | ||
| can attribute a slow poll to its source location after the UI resumes. | ||
|
|
||
| File writing never blocks the UI while the application runs. Normal process | ||
| exit joins the recorder and writer to finish the final file; force-killing the | ||
| process can lose the latest in-memory history. Export failures go to stderr. | ||
| The recorder does not require a GUI viewer to be open and makes no network | ||
| requests. | ||
|
|
||
| ## Verification | ||
|
|
||
| ```sh | ||
| cargo test -p artisan-tracing --features enabled | ||
| cargo test -p artisan-tracing --no-default-features | ||
| python3 tests/tracing/merge.py | ||
| ``` | ||
|
|
||
| Set `ARTISAN_TRACE_KEEP_FIXTURE=1` on the enabled test command and add | ||
| `-- --nocapture` to retain its generated stall, manual, and shutdown captures | ||
| for an importer check. Handoff arrows use one-microsecond endpoint markers; | ||
| their duration represents a marker rather than measured application work. | ||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,36 @@ | ||||||||||
| # Recent-thread project icons | ||||||||||
|
|
||||||||||
| The icon beside a thread's project subtitle is 14 pixels wide. Disk-only | ||||||||||
| projects and Git repositories without a network remote show a folder. | ||||||||||
|
|
||||||||||
| For a remote repository, the first available icon wins: | ||||||||||
|
|
||||||||||
| 1. A project file, checked in this order: `.artisan/icon.png`, | ||||||||||
| `.artisan/icon.webp`, `icon.png`, `favicon.png`, `public/favicon.png`. | ||||||||||
| 2. Repository artwork supplied by the Git host. | ||||||||||
| 3. Organization, namespace, or user artwork supplied by the Git host. | ||||||||||
| 4. The hosting service's bundled logo, or the Git logo for unknown hosts. | ||||||||||
|
|
||||||||||
| GitHub resolves the public organization/user avatar. GitLab, Bitbucket, | ||||||||||
| Codeberg, and Gitea resolve repository artwork before owner artwork. GitHub | ||||||||||
| has no dedicated repository avatar endpoint, so a local project file provides | ||||||||||
| its project-specific artwork. Private or inaccessible metadata requires no | ||||||||||
| login and falls back to the logo. No credentials are sent by this resolver. | ||||||||||
|
Comment on lines
+17
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: This says private repositories fall back to the logo, but GitHub can return the owner's public avatar even when the repository cannot be read. Clarify that GitHub may still show that avatar. Prompt for AI agents
Suggested change
|
||||||||||
|
|
||||||||||
| Forge discovers and downloads icons in the background. Subtitles and icons | ||||||||||
| come from cached repository observations; listing threads and painting the | ||||||||||
| sidebar perform no Git, file, or network I/O. Successful artwork is refreshed | ||||||||||
| after an hour, absent artwork after five minutes. Changes are pushed through | ||||||||||
| the existing recent-thread subscription. A changed remote invalidates the | ||||||||||
| previous icon. Detached projects leave the cache. | ||||||||||
|
|
||||||||||
| Downloaded input is capped at 512 KiB and decoding runs off the Forge event | ||||||||||
| loop with image allocation and dimension limits. Artwork is normalized to a | ||||||||||
| PNG within 48 by 48 pixels and 16 KiB before crossing the protocol. Editor | ||||||||||
| reuses the decoded image identity between repaints. The added protocol fields | ||||||||||
| are optional, so an older Forge supplies folder fallback and an older Editor | ||||||||||
| ignores the artwork. | ||||||||||
|
|
||||||||||
| Metadata field references: [GitHub account avatars](https://docs.github.com/en/rest/users/users#get-a-user), | ||||||||||
| [GitLab project and namespace avatars](https://docs.gitlab.com/api/projects/), | ||||||||||
| and [Gitea repository metadata](https://docs.gitea.com/api/operations/repo-get/). | ||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: The writer uses
std::env::temp_dir(), which prefersTMPoverTEMPon Windows, so%TEMP%is not always the capture directory. Describe the process temp directory instead.Prompt for AI agents