)]}'
{
  "commit": "fa1aac16ce913cb35bf8b8d7bc92a6cd89c93d4a",
  "tree": "0b7dd4094f94084c8be9219caaf1d6b37576539f",
  "parents": [
    "9df700a52abdd2e38527b7e77274e0bb25a61401"
  ],
  "author": {
    "name": "Primiano Tucci",
    "email": "primiano@google.com",
    "time": "Thu Apr 16 19:49:57 2026 +0100"
  },
  "committer": {
    "name": "Primiano Tucci",
    "email": "primiano@google.com",
    "time": "Thu Apr 16 19:49:57 2026 +0100"
  },
  "message": "ui: allow ui/build to act as a client of a running dev-server\n\nPreviously, running ui/build while ui/run-dev-server was already active\nwould fail out: the two would clash in out/ui/ and a PID lockfile\nprevented the second invocation. This made it awkward to iterate on\nTypeScript sources while a watch-mode server was keeping tsc/rollup\nwarm, especially for AI agents that edit code and need synchronous\nfeedback on whether the build succeeded.\n\nRepurpose ui/build, when a watch-mode server is detected, as a thin\nclient that rides the server\u0027s existing tsc-watch/rollup-watch\npipeline. Communication is purely file-based under out/ui/:\n\n  - out/ui/watch.lock: JSON with {pid, watch}. Replaces the\n    previous PID-only lockfile. prepareBuildLock() now also detects\n    \"server alive + watch: true\" and returns the server\u0027s info so the\n    caller can enter client mode; concurrent full builds still bail.\n\n  - out/ui/ui_build.log: append-mode log of tsc/rollup/sass/etc. stdout+stderr\n    plus this script\u0027s console.log, each line timestamped and\n    ANSI-stripped. Truncated at server startup and after each client\n    run, so it acts as a per-iteration buffer.\n\n  - out/ui/dev_server.port: written on HTTP \"listening\" so other tools (test\n    runners, agents) can discover the dev server\u0027s port without\n    parsing logs.\n\n  - out/ui/tsc/gen/perfetto_version.ts: the client rewrites SCM_REVISION to\n    \"perfetto_incremental_build:N\" (monotonic). tsc-watch and\n    rollup-watch cascade this through the bundle as a fence -- once\n    frontend_bundle.js contains the same marker, every edit made before\n    the client ran is guaranteed to be in the bundle.\n\nThe client polls the bundle for the fence while tailing ui_build.log\nto its own stdout. Exit codes: 0 on fence match, 1 on tsc \"Found N\nerrors\" or rollup \"[!] ...\" detection or 120s timeout.\n\nServer-side plumbing: exec() now pipes and tees subprocess output when\nlogStream is active; the one synchronous stdout-capturing call (the\nversion script) was inlined with spawnSync to keep exec() simple.\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "049eacdb06923f4e036d3d557458403382fd5569",
      "old_mode": 33188,
      "old_path": "docs/AGENTS-ui.md",
      "new_id": "daa9023bd88d0afdd56cf60e15a912d6cd32d0ca",
      "new_mode": 33188,
      "new_path": "docs/AGENTS-ui.md"
    },
    {
      "type": "modify",
      "old_id": "881ff6d5c0da5dc99beb39497b228472bfa8852e",
      "old_mode": 33188,
      "old_path": "ui/build.js",
      "new_id": "1a1532667537c67a6285102759f88854793a0287",
      "new_mode": 33188,
      "new_path": "ui/build.js"
    }
  ]
}
