@lensmcp/cluster 1.23.12 → 1.24.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.
Files changed (107) hide show
  1. package/build-host.d.ts +1 -0
  2. package/build-host.js +1 -0
  3. package/create-webpack-dev.d.ts +75 -39
  4. package/create-webpack-dev.js +1 -1
  5. package/dev-devtool.d.ts +45 -0
  6. package/dev-devtool.js +1 -0
  7. package/devserver-notifier.d.ts +57 -0
  8. package/devserver-notifier.js +1 -0
  9. package/executors/gateway/body-stall.d.ts +13 -1
  10. package/executors/gateway/body-stall.js +1 -1
  11. package/executors/gateway/canonical-path.d.ts +1 -1
  12. package/executors/gateway/client-ip.d.ts +1 -1
  13. package/executors/gateway/gateway.impl.js +1 -1
  14. package/executors/gateway/jwt-claims.d.ts +1 -1
  15. package/executors/gateway/prod-config.d.ts +1 -1
  16. package/executors/gateway/prod-runtime/body-stall.d.ts +1 -1
  17. package/executors/gateway/rate-limit.d.ts +1 -1
  18. package/executors/gateway/runtime/auth.d.ts +1 -1
  19. package/executors/gateway/runtime/chooser.d.ts +2 -2
  20. package/executors/gateway/runtime/control.d.ts +3 -3
  21. package/executors/gateway/runtime/control.js +2 -2
  22. package/executors/gateway/runtime/dev-auth.d.ts +1 -1
  23. package/executors/gateway/runtime/edge.d.ts +3 -3
  24. package/executors/gateway/runtime/guest-graph.d.ts +113 -0
  25. package/executors/gateway/runtime/guest-graph.js +2 -0
  26. package/executors/gateway/runtime/lens-children.d.ts +11 -1
  27. package/executors/gateway/runtime/lens-children.js +1 -1
  28. package/executors/gateway/runtime/lifecycle.d.ts +74 -3
  29. package/executors/gateway/runtime/lifecycle.js +3 -3
  30. package/executors/gateway/runtime/process-names.d.ts +18 -0
  31. package/executors/gateway/runtime/process-names.js +1 -0
  32. package/executors/gateway/runtime/project-graph-store.d.ts +74 -0
  33. package/executors/gateway/runtime/project-graph-store.js +1 -0
  34. package/executors/gateway/runtime/proxy.d.ts +2 -2
  35. package/executors/gateway/runtime/proxy.js +1 -1
  36. package/executors/gateway/runtime/registration-guards.d.ts +32 -0
  37. package/executors/gateway/runtime/registration-guards.js +1 -0
  38. package/executors/gateway/runtime/scope.d.ts +1 -1
  39. package/executors/gateway/runtime/serve-launch.d.ts +118 -0
  40. package/executors/gateway/runtime/serve-launch.js +3 -0
  41. package/executors/gateway/runtime/server.d.ts +3 -3
  42. package/executors/gateway/runtime/server.js +2 -2
  43. package/executors/gateway/runtime/shared-build.d.ts +65 -0
  44. package/executors/gateway/runtime/shared-build.js +4 -0
  45. package/executors/gateway/runtime/types.d.ts +35 -9
  46. package/executors/gateway/runtime/types.js +1 -1
  47. package/executors/gateway/runtime/workspace-log.js +1 -1
  48. package/executors/gateway/schema.d.ts +3 -0
  49. package/executors/gateway/schema.json +4 -0
  50. package/executors/serve/schema.d.ts +2 -0
  51. package/executors/serve/schema.json +4 -0
  52. package/executors/serve/serve.impl.d.ts +12 -6
  53. package/executors/serve/serve.impl.js +1 -1
  54. package/executors/trust/hostname.d.ts +1 -1
  55. package/exit-reason.d.ts +1 -1
  56. package/fork-ts-check-reporter.d.ts +12 -0
  57. package/fork-ts-check-reporter.js +1 -1
  58. package/graph-snapshot.d.ts +1 -0
  59. package/graph-snapshot.js +1 -0
  60. package/heap-snapshot.d.ts +66 -0
  61. package/heap-snapshot.js +1 -0
  62. package/hot-swap-registries.d.ts +1 -1
  63. package/inspector-secret.d.ts +39 -0
  64. package/inspector-secret.js +1 -0
  65. package/main.devserver.d.ts +50 -4
  66. package/main.devserver.js +11 -9
  67. package/package.json +4 -4
  68. package/perf/heavy-barrel-import.d.ts +135 -0
  69. package/perf/heavy-barrel-import.js +1 -0
  70. package/perf/perf-config.d.ts +29 -0
  71. package/perf/perf-config.js +1 -0
  72. package/perf/perf-rule-events.d.ts +71 -0
  73. package/perf/perf-rule-events.js +2 -0
  74. package/perf/perf-rules-analysis.d.ts +28 -0
  75. package/perf/perf-rules-analysis.js +1 -0
  76. package/perf/perf-rules-plugin.d.ts +71 -0
  77. package/perf/perf-rules-plugin.js +1 -0
  78. package/perf/perf-rules-worker.d.ts +1 -0
  79. package/perf/perf-rules-worker.js +1 -0
  80. package/perf/source-scan.d.ts +59 -0
  81. package/perf/source-scan.js +5 -0
  82. package/perf/workspace-libraries.d.ts +52 -0
  83. package/perf/workspace-libraries.js +2 -0
  84. package/pod-memory-events.d.ts +71 -0
  85. package/pod-memory-events.js +2 -0
  86. package/pod-memory.d.ts +258 -0
  87. package/pod-memory.js +1 -0
  88. package/process-name.d.ts +45 -0
  89. package/process-name.js +1 -1
  90. package/serve-runner.d.ts +2 -0
  91. package/serve-runner.js +1 -0
  92. package/shared-build/attach.d.ts +56 -0
  93. package/shared-build/attach.js +3 -0
  94. package/shared-build/host.d.ts +52 -0
  95. package/shared-build/host.js +4 -0
  96. package/shared-build/protocol.d.ts +118 -0
  97. package/shared-build/protocol.js +1 -0
  98. package/shared-build/shared-compilation.d.ts +91 -0
  99. package/shared-build/shared-compilation.js +3 -0
  100. package/shared-build/signature.d.ts +52 -0
  101. package/shared-build/signature.js +1 -0
  102. package/stdio-guard.d.ts +1 -1
  103. package/swap-recycle.d.ts +21 -0
  104. package/swap-recycle.js +1 -1
  105. package/tsgo-check-plugin.d.ts +1 -1
  106. package/workspace-paths.d.ts +76 -0
  107. package/workspace-paths.js +1 -0
@@ -0,0 +1,4 @@
1
+ "use strict";var T=Object.defineProperty;var S=(r,t)=>T(r,"name",{value:t,configurable:!0});var L=Object.defineProperty,i=S((r,t)=>L(r,"name",{value:t,configurable:!0}),"i");Object.defineProperty(exports,"__esModule",{value:!0}),exports.HOST_MAX_RESTARTS=void 0,exports.buildHostScript=buildHostScript,exports.workspaceBuildHostScript=workspaceBuildHostScript,exports.createSharedBuildRelay=createSharedBuildRelay;const tslib_1=require("tslib"),node_child_process_1=require("node:child_process"),fs=tslib_1.__importStar(require("node:fs")),node_module_1=require("node:module"),path=tslib_1.__importStar(require("node:path")),process_name_1=require("../../../process-name"),protocol_1=require("../../../shared-build/protocol"),pod_env_1=require("./pod-env"),registration_guards_1=require("./registration-guards");exports.HOST_MAX_RESTARTS=3;const CRASH_WINDOW_MS=6e4;function buildHostScript(r=path.join(__dirname,"../../..")){const t=path.join(r,"build-host.js");if(fs.existsSync(t))return{path:t,execArgv:[]};const u=path.join(r,"build-host.ts");if(fs.existsSync(u))try{return{path:u,execArgv:["--require",require.resolve("@swc-node/register")]}}catch{return}}S(buildHostScript,"buildHostScript"),i(buildHostScript,"buildHostScript");function workspaceBuildHostScript(r){try{return{path:(0,node_module_1.createRequire)(path.join(r,"package.json")).resolve("@lensmcp/cluster/build-host.js"),execArgv:[]}}catch{return}}S(workspaceBuildHostScript,"workspaceBuildHostScript"),i(workspaceBuildHostScript,"workspaceBuildHostScript");function createSharedBuildRelay(r,t={}){const u=t.script===void 0?buildHostScript():t.script??void 0,_=t.scriptFor??workspaceBuildHostScript,h=new Map,f=new WeakMap,d=(0,registration_guards_1.canonicalRoot)(r.root),v=i(e=>{const a=(0,registration_guards_1.canonicalRoot)(e.root);let c=h.get(a);return c||(c=a===d?createWorkspaceRelay(r,{root:r.root,...r.wsKey?{wsKey:r.wsKey}:{},eventFile:r.eventFile},u,t):createWorkspaceRelay(r,{root:e.root,...e.wsKey?{wsKey:e.wsKey}:{},eventFile:path.join(e.root,".lensmcp","events.jsonl")},_(e.root),t),h.set(a,c)),c},"relayFor");return{offeredTo:i(e=>(0,protocol_1.sharedCompilerEnabled)(t.gatewayEnv??process.env,r.sharedCompiler)&&v(e).offered(),"offeredTo"),attach(e,a,c){const y=v(e);f.set(c,y),y.attach(`${e.project}#g${a}`,c)},detach:i(e=>f.get(e)?.detach(e),"detach"),hostPid:i((e=r.root)=>h.get((0,registration_guards_1.canonicalRoot)(e))?.hostPid(),"hostPid"),release(e){const a=(0,registration_guards_1.canonicalRoot)(e),c=h.get(a);return h.delete(a),c?.stop()??Promise.resolve()},async stop(){const e=[...h.values()];h.clear(),await Promise.all(e.map(a=>a.stop()))}}}S(createSharedBuildRelay,"createSharedBuildRelay"),i(createSharedBuildRelay,"createSharedBuildRelay");function createWorkspaceRelay(r,t,u,_){const h=_.spawnProcess??node_child_process_1.spawn,f=_.log??(o=>console.log(o)),d=new Map,v=new WeakMap;let e,a=[],c,y=!1;const E=(0,registration_guards_1.canonicalRoot)(t.root)===(0,registration_guards_1.canonicalRoot)(r.root)?"this workspace":`'${t.wsKey??path.basename(t.root)}'`,b=i((o,s)=>{if(!o.connected)return;const n={channel:protocol_1.SHARED_BUILD_CHANNEL,event:s};try{o.send(n,void 0,void 0,()=>{})}catch{}},"toRunner"),R=i(o=>{if(e?.connected)try{e.send(o,void 0,void 0,()=>{})}catch{}},"toHost"),A=i(()=>{if(_.reapStale===!1)return;let o;try{o=(0,node_child_process_1.execFileSync)("ps",["ax","-ww","-o","pid=,pgid=,command="],{encoding:"utf8",timeout:5e3})}catch{return}for(const s of o.split(`
2
+ `)){const n=s.match(/^\s*(\d+)\s+(\d+)\s+(.*)$/);if(!n||!(0,protocol_1.isBuildHostCommandOf)(n[3],t.root))continue;const l=Number(n[1]),p=Number(n[2]);if(!(l===e?.pid||l===process.pid)){try{process.kill(-p,"SIGKILL")}catch{try{process.kill(l,"SIGKILL")}catch{}}f(`[gateway] reaped a stale build host (pid ${l}) of ${E}`)}}},"reapStaleHosts"),x=i(()=>{if(e||y||c||!u)return e;A();const o=t.wsKey||path.basename(t.root),s={...(0,pod_env_1.podBaseEnv)(process.env,r.root,t.root),NX_DAEMON:"false",NODE_ENV:"development",NX_WORKSPACE_ROOT:t.root,...t.wsKey?{LENSMCP_WS_KEY:t.wsKey}:{},LENSMCP_EVENT_FILE:t.eventFile,LENSMCP_GATEWAY_PID:String(process.pid)},n=h((0,process_name_1.namedExecPath)((0,process_name_1.processName)(o,protocol_1.BUILD_HOST_ROLE)),[...u.execArgv,u.path,...(0,protocol_1.buildHostArgs)(t.root)],{cwd:t.root,detached:!0,env:s,stdio:["ignore","pipe","pipe","ipc"]});e=n,f(`[gateway] build host starting (one compilation for the services of ${E} \u2014 LENSMCP_SHARED_COMPILER)`);const l=i(p=>m=>{if(!r.stopped())for(const g of m.toString().split(`
3
+ `))g.trim()&&p.write(`[build] ${g}
4
+ `)},"relayOut");return n.stdout?.on("data",l(process.stdout)),n.stderr?.on("data",l(process.stderr)),n.on("message",p=>{if(p?.type==="member"){const m=d.get(p.member);m&&b(m.proc,p.event)}}),n.on("exit",(p,m)=>{if(e===n&&(e=void 0),y||r.stopped())return;const g=Date.now();if(a=[...a.filter(w=>g-w<CRASH_WINDOW_MS),g],a.length>=exports.HOST_MAX_RESTARTS){c=`the build host exited ${a.length} times in a minute (last: ${p??m})`,f(`[gateway] ${c} \u2014 every service compiles on its own from now on`);for(const w of d.values())b(w.proc,{type:"refused",reason:c});d.clear();return}if(d.size!==0&&(f(`[gateway] build host exited (${p??m}) \u2014 restarting it for ${d.size} service tree(s)`),x()))for(const[w,{join:P}]of d)R({type:"join",member:w,join:P})}),n},"start"),j=i(o=>{const s=v.get(o);!s||d.get(s)?.proc!==o||(d.delete(s),R({type:"leave",member:s}))},"detach");return{offered:i(()=>!!u&&!c,"offered"),attach:i((o,s)=>{v.set(s,o),s.on("message",n=>{if((0,protocol_1.isRunnerJoinMessage)(n)){if(c||!x()){b(s,{type:"refused",reason:c??"the build host could not be started"});return}d.set(o,{proc:s,join:n.join}),R({type:"join",member:o,join:n.join})}}),s.once("exit",()=>j(s))},"attach"),detach:j,hostPid:i(()=>e?.pid,"hostPid"),stop(){y=!0,d.clear();const o=e;return e=void 0,!o||o.exitCode!==null||o.signalCode!==null?Promise.resolve():new Promise(s=>{const n=i(()=>{clearTimeout(l),s()},"done");o.once("exit",n);try{process.kill(-o.pid,"SIGTERM")}catch{try{o.kill("SIGTERM")}catch{}}const l=setTimeout(()=>{try{process.kill(-o.pid,"SIGKILL")}catch{try{o.kill("SIGKILL")}catch{}}s()},6e3);l.unref?.()})}}}S(createWorkspaceRelay,"createWorkspaceRelay"),i(createWorkspaceRelay,"createWorkspaceRelay");
@@ -14,6 +14,7 @@ import type { AuthPolicy, Attrs } from '../manifest';
14
14
  import type { GatewayErrorReason } from '../gateway-errors';
15
15
  import type { RouteRegistry } from './route-registry';
16
16
  import type { PodFaults } from './pod-output';
17
+ import type { ProjectGraphStore, ProjectGraphStores } from './project-graph-store';
17
18
  export type { Attrs };
18
19
  export interface GatewayContext {
19
20
  root: string;
@@ -25,6 +26,10 @@ export interface GatewayContext {
25
26
  };
26
27
  /** Nx project-graph adjacency, populated by the executor wrapper when available. */
27
28
  projectDependencies?: Record<string, string[]>;
29
+ /** The workspace's project graph, kept current by the executor wrapper — what lets the gateway start a
30
+ * service's serve task without an `nx run` client (serve-launch.ts). Absent ⇒ every service starts
31
+ * through `nx run`, as before. */
32
+ projectGraphStore?: ProjectGraphStore;
28
33
  }
29
34
  /** Per-project declaration: top-level `cluster` field in project.json (`davnx` legacy). */
30
35
  export interface ClusterProjectDecl {
@@ -145,7 +150,7 @@ export interface SourceSetChange {
145
150
  * COMPLETION, but the fs event happened anywhere after the PREVIOUS scan started — so the window is
146
151
  * "now − previous scan start" (+ the settle margin), not a fixed fraction of the scan period. The old
147
152
  * fixed `min(scanPeriod, 15s) + settle` = 23s against a 30s period falsely read a heard add as `missed`
148
- * whenever the event fell in the first 7+ seconds of the period (issues/dev-gateway/03).
153
+ * whenever the event fell in the first 7+ seconds of the period (issues/closed/dev-gateway-03).
149
154
  */
150
155
  windowMs?: number;
151
156
  }
@@ -227,6 +232,9 @@ export interface ServiceCtl {
227
232
  rolling?: Promise<boolean>;
228
233
  /** The pod GENERATION the current `proc` was spawned as (`LENSMCP_POD_GENERATION`, echoed in `/__lensmcp/alive`). */
229
234
  generation?: number;
235
+ /** How the current `proc` was started: the gateway's serve runner, or `nx run` (serve-launch.ts). An `nx run`
236
+ * tree holds nx's task lock for its target, so no second generation can start beside it. */
237
+ launcher?: 'runner' | 'nx';
230
238
  lastScaleAt: number;
231
239
  spawnAt?: number;
232
240
  lastErrors?: string[];
@@ -390,7 +398,7 @@ export declare const LENS_WATCHER_UNVERIFIED: 'recycle' | 'keep';
390
398
  * roots to Vite's chokidar. Vite watches only `config.root`; a file outside it is watched one-at-a-time
391
399
  * as it is imported, so a NEW file in `shared/` or `web/libs/` never produced an `add` event, the
392
400
  * watcher-health endpoint never stamped it, and the verdict above was `missed` BY CONSTRUCTION for every
393
- * out-of-root add — 16 of 16 rolling handoffs in one foodguard day (issues/dev-gateway/02). With the scope
401
+ * out-of-root add — 16 of 16 rolling handoffs in one foodguard day (issues/closed/dev-gateway-02). With the scope
394
402
  * watched, the add is heard, the verdict is `heard`, and Vite's own create-handling works for those files
395
403
  * too. Set `LENSMCP_LENS_WATCH_SCOPE=0` to hand nothing over (inotify-constrained Linux hosts).
396
404
  */
@@ -399,7 +407,7 @@ export declare const LENS_WATCH_SCOPE_ENABLED: boolean;
399
407
  * POD watcher testimony ({@link PodWatcherTestimony}) — the pod-side twin of the two lens knobs above.
400
408
  * The stale-source-set signal scaled EVERY pod to zero on EVERY source-set change in its scope — 83 cold
401
409
  * recycles of six services in one foodguard day, each a ~30-60s API outage the app rendered as "not
402
- * connected" (issues/dev-gateway/07). Now the sweeper reads the pod's testimony first.
410
+ * connected" (issues/closed/dev-gateway-07). Now the sweeper reads the pod's testimony first.
403
411
  *
404
412
  * `LENSMCP_POD_WATCHER_UNVERIFIED` — no testimony at all (a pod on an older `@lensmcp/cluster` bundle,
405
413
  * or an unreachable probe). `recycle` (default) is today's behaviour for those pods; `keep` leaves them.
@@ -414,7 +422,7 @@ export declare const POD_WATCHER_UNVERIFIED: 'recycle' | 'keep';
414
422
  */
415
423
  export declare const POD_WATCHER_SILENT: 'recycle' | 'keep';
416
424
  /**
417
- * HOW a pod is recycled (stale-source-set / max-age) — issues/dev-gateway/09. `rolling` (default): spawn a
425
+ * HOW a pod is recycled (stale-source-set / max-age) — issues/closed/dev-gateway-09. `rolling` (default): spawn a
418
426
  * STANDBY `serve-hmr` generation for the same service, wait until one of its pods answers
419
427
  * `/__lensmcp/alive` with the new generation number, then retire the old tree — the pool dir is shared, the
420
428
  * devserver's bind-steal hands each socket path to the newer pod, and the gateway's rotation never runs
@@ -425,6 +433,15 @@ export declare const POD_RECYCLE_MODE: 'rolling' | 'in-place';
425
433
  * generation kept (a cold nx + webpack compile of a large service can take minutes). Override
426
434
  * `LENSMCP_POD_ROLL_READY_MS`. Default 3 min. */
427
435
  export declare const POD_ROLL_READY_MS: number;
436
+ /**
437
+ * How many rolling recycles may be IN FLIGHT at once, gateway-wide (issues/closed/dev-gateway-17). Each roll
438
+ * holds a standby `serve-hmr` tree — an nx client, a devserver parent, its pods and a cold webpack compile —
439
+ * beside the live one for up to {@link POD_ROLL_READY_MS}, and a shared-lib edit makes every service stale
440
+ * in the same sweep: uncapped, that doubled the fleet (twelve concurrent cold compiles for foodguard's six
441
+ * eager services). The rest queue and roll as slots free. Override `LENSMCP_POD_MAX_CONCURRENT_ROLLS`;
442
+ * `0` removes the cap. Default 2.
443
+ */
444
+ export declare const POD_MAX_CONCURRENT_ROLLS: number;
428
445
  /** Spawn grace: a child is never probed (and so never recycled) until it has had this long to BIND its port
429
446
  * — a cold vite/nx boot in a big monorepo takes many seconds, and killing a still-booting dev server would
430
447
  * be a self-inflicted outage. Override `LENSMCP_LENS_PROBE_GRACE_MS`. Default 45s. */
@@ -518,7 +535,7 @@ export declare const LENS_REQUEST_RECOVERY_WAIT_MS: number;
518
535
  * Override `LENSMCP_KEEPALIVE_TIMEOUT_MS`. Default 76s. */
519
536
  export declare const GATEWAY_KEEPALIVE_TIMEOUT_MS: number;
520
537
  /**
521
- * The HEADER-phase bound, INDEPENDENT of `keepAliveTimeout` (issues/dev-gateway/12, the prod-gateway-2 #14
538
+ * The HEADER-phase bound, INDEPENDENT of `keepAliveTimeout` (issues/closed/dev-gateway-12, the prod-gateway-2 #14
522
539
  * twin). The old derivation (`keepAliveTimeout + 5s` = 81s) rested on a premise verified obsolete on Node
523
540
  * 24: an idle keep-alive socket is NOT closed by a shorter `headersTimeout` — only a connection that has
524
541
  * begun a request and stalled mid-headers is. So a partial-header hold was 81s for no reason; Node's own
@@ -539,7 +556,7 @@ export declare const GATEWAY_MAX_CONNECTIONS: number;
539
556
  * 90s). 0 (default) keeps Node's value. Override `LENSMCP_CONN_CHECK_MS`. */
540
557
  export declare const GATEWAY_CONN_CHECK_MS: number;
541
558
  /**
542
- * The transfer STALL bound (issues/dev-gateway/12, the prod-gateway-2 #06 / round-1 #10 twins): a request
559
+ * The transfer STALL bound (issues/closed/dev-gateway-12, the prod-gateway-2 #06 / round-1 #10 twins): a request
543
560
  * body or a response that has moved NOTHING for this long is cut, in either direction. A slow-but-moving
544
561
  * upload, a draining download and an idle SSE stream (nothing queued) are never candidates. Dev streams
545
562
  * long (MCP streamable-HTTP, SSE), so this is a stall bound, never a duration bound. `0` disables.
@@ -547,7 +564,7 @@ export declare const GATEWAY_CONN_CHECK_MS: number;
547
564
  */
548
565
  export declare const BODY_STALL_MS: number;
549
566
  /**
550
- * The h2 front door's RST_STREAM budget, PER SESSION (issues/foodguard/14). nghttp2's Rapid-Reset mitigation
567
+ * The h2 front door's RST_STREAM budget, PER SESSION (issues/closed/foodguard-14). nghttp2's Rapid-Reset mitigation
551
568
  * (CVE-2023-44487) allows 1000 resets per session, refilling at 33/s, and CLOSES the session (GOAWAY
552
569
  * INTERNAL_ERROR) on the next one — with NO 'error' event on the server side. A browser keeps ONE h2 session
553
570
  * per origin for the life of the tab and cancels every in-flight stream on each navigation (a Vite dev page:
@@ -587,7 +604,7 @@ export interface GatewayRuntimeOptions extends GatewayExecutorSchema {
587
604
  bodyStallMs?: number;
588
605
  /** Per-session h2 RST_STREAM budget — burst (`LENSMCP_H2_RESET_BURST`, default 100k) and refill per second
589
606
  * (`LENSMCP_H2_RESET_RATE`, default 10k). nghttp2's 1000 / 33 default tears a dev browser's session down
590
- * after a few navigations (issues/foodguard/14). Both must be set for Node to apply either. */
607
+ * after a few navigations (issues/closed/foodguard-14). Both must be set for Node to apply either. */
591
608
  h2ResetBurst?: number;
592
609
  h2ResetRate?: number;
593
610
  /** Customer-supplied lifecycle hooks layered on top of the built-in pipeline. */
@@ -602,6 +619,8 @@ export interface GatewayHandle {
602
619
  /** The lens-frontend supervisor (rolling handoffs) — `recover(route.lens, reason)` rolls an app on demand.
603
620
  * Present when the gateway runs in `rolling` mode; what an operator command or an e2e drives. */
604
621
  lensSupervisor?: LensFrontendSupervisor;
622
+ /** The project graphs services are planned from, one per workspace root (guest-graph.ts) — for the spec and `gateway status`. */
623
+ graphStores?: ProjectGraphStores;
605
624
  }
606
625
  export interface GwTrace {
607
626
  startedAt: number;
@@ -651,7 +670,7 @@ export interface GatewayRuntime {
651
670
  * workspace that joins a running daemon via `POST /register` adopts its keys here. */
652
671
  readonly keyToProject: Map<string, string>;
653
672
  /** key → owning workspace slug, the twin of `keyToProject` — so an internal caller can be attributed to
654
- * `<wsKey>/<project>`, not just a bare project name (issues/dev-gateway/13). Mutable like its twin. */
673
+ * `<wsKey>/<project>`, not just a bare project name (issues/closed/dev-gateway-13). Mutable like its twin. */
655
674
  readonly keyToWorkspace: Map<string, string>;
656
675
  /** The client-address resolver (shared with prod — `../client-ip`), built from options/env at boot. Optional
657
676
  * only so a partial runtime in a spec still works: the edge helpers fall back to a peer-only resolver. */
@@ -684,6 +703,13 @@ export interface GatewayRuntime {
684
703
  readonly projectRoots?: Readonly<Record<string, string>>;
685
704
  /** Project root plus transitive Nx dependency roots. */
686
705
  readonly projectSourceRoots?: Readonly<Record<string, string[]>>;
706
+ /** The project graphs the serve runner is planned from, one per workspace root: the daemon's own
707
+ * ({@link GatewayContext.projectGraphStore}) and each registered workspace's (guest-graph.ts). The sweeper keeps
708
+ * each current. Absent when the gateway was started without a graph — every service then starts through `nx run`. */
709
+ readonly graphStores?: ProjectGraphStores;
710
+ /** The gateway's `sharedCompiler` option — one webpack compilation for this workspace's services
711
+ * (shared-build.ts, issues/open/pod-memory-05). `LENSMCP_SHARED_COMPILER` wins over it. */
712
+ readonly sharedCompiler?: boolean;
687
713
  /** Managed lens frontend handoff state, installed by the child supervisor. */
688
714
  lensSupervisor?: LensFrontendSupervisor;
689
715
  /** frontend identity (`workspace:project`) → live HMR sockets, registered by the WS upgrade pipeline. A
@@ -1 +1 @@
1
- "use strict";var M=Object.defineProperty;var e=(_,E)=>M(_,"name",{value:E,configurable:!0});var T=Object.defineProperty,R=e((_,E)=>T(_,"name",{value:E,configurable:!0}),"R");Object.defineProperty(exports,"__esModule",{value:!0}),exports.GATEWAY_H2_RESET_RATE=exports.GATEWAY_H2_RESET_BURST=exports.BODY_STALL_MS=exports.GATEWAY_CONN_CHECK_MS=exports.GATEWAY_MAX_CONNECTIONS=exports.GATEWAY_STOP_GRACE_MS=exports.GATEWAY_HEADERS_TIMEOUT_MS=exports.GATEWAY_KEEPALIVE_TIMEOUT_MS=exports.LENS_REQUEST_RECOVERY_WAIT_MS=exports.LENS_REPLACEMENT_DRAIN_MS=exports.LENS_REPLACEMENT_READY_MS=exports.LENS_RESTART_MODE=exports.LENS_RECYCLE_KILL_GRACE_MS=exports.LENS_PARKED_PORT_REPROBE_MS=exports.MAX_PORT_CONFLICT_RETRIES=exports.CHILD_START_FAIL_MS=exports.PORT_FREE_POLL_MS=exports.PORT_FREE_WAIT_MS=exports.LENS_PROBE_BOOT_GRACE_MS=exports.LENS_PROBE_COOLDOWN_MS=exports.LENS_PROBE_TIMEOUT_MS=exports.LENS_PROBE_FAILS=exports.LENS_PROBE_GRACE_MS=exports.POD_ROLL_READY_MS=exports.POD_RECYCLE_MODE=exports.POD_WATCHER_SILENT=exports.POD_WATCHER_UNVERIFIED=exports.LENS_WATCH_SCOPE_ENABLED=exports.LENS_WATCHER_UNVERIFIED=exports.LENS_WATCHER_PROBE_ENABLED=exports.LENS_PROBE_ENABLED=exports.POD_STALE_RECYCLE_COOLDOWN_MS=exports.POD_STALE_SCAN_MS=exports.POD_RECYCLE_SETTLE_MS=exports.POD_STALE_GRACE_MS=exports.POD_MAX_AGE_MS=exports.POD_RECYCLE_ENABLED=exports.WEDGE_RECYCLE_GRACE_MS=exports.POD_ALIVE_PATH=exports.POD_ALIVE_PROBE_TIMEOUT_MS=exports.POD_SLOW_FIRST_BYTE_MS=exports.POD_RESPONSE_TIMEOUT_MS=exports.UPSTREAM_HEAL_STEP_MS=exports.UPSTREAM_HEAL_WINDOW_MS=exports.SERVICE_RESTART_WINDOW_MS=exports.SERVICE_MAX_RESTARTS=exports.SERVICE_ERROR_THROTTLE_MS=void 0;function envInt(_,E,L=!1){const S=Number(process.env[_]);return!Number.isFinite(S)||S<0?E:S===0?L?0:E:S}e(envInt,"envInt"),R(envInt,"envInt"),exports.SERVICE_ERROR_THROTTLE_MS=5e3,exports.SERVICE_MAX_RESTARTS=5,exports.SERVICE_RESTART_WINDOW_MS=6e4,exports.UPSTREAM_HEAL_WINDOW_MS=8e3,exports.UPSTREAM_HEAL_STEP_MS=300,exports.POD_RESPONSE_TIMEOUT_MS=(()=>{const _=Number(process.env.LENSMCP_POD_RESPONSE_TIMEOUT_MS);return Number.isFinite(_)&&_>0?_:3e4})(),exports.POD_SLOW_FIRST_BYTE_MS=envInt("LENSMCP_POD_SLOW_FIRST_BYTE_MS",10*6e4,!0),exports.POD_ALIVE_PROBE_TIMEOUT_MS=envInt("LENSMCP_POD_ALIVE_PROBE_TIMEOUT_MS",1e3),exports.POD_ALIVE_PATH="/__lensmcp/alive",exports.WEDGE_RECYCLE_GRACE_MS=(()=>{const _=Number(process.env.LENSMCP_WEDGE_RECYCLE_GRACE_MS);return Number.isFinite(_)&&_>0?_:15e3})(),exports.POD_RECYCLE_ENABLED=process.env.LENSMCP_POD_RECYCLE!=="0",exports.POD_MAX_AGE_MS=envInt("LENSMCP_POD_MAX_AGE_MS",240*6e4,!0),exports.POD_STALE_GRACE_MS=envInt("LENSMCP_POD_STALE_GRACE_MS",1e4),exports.POD_RECYCLE_SETTLE_MS=envInt("LENSMCP_POD_RECYCLE_SETTLE_MS",8e3),exports.POD_STALE_SCAN_MS=envInt("LENSMCP_POD_STALE_SCAN_MS",3e4),exports.POD_STALE_RECYCLE_COOLDOWN_MS=envInt("LENSMCP_POD_STALE_RECYCLE_COOLDOWN_MS",6e4),exports.LENS_PROBE_ENABLED=process.env.LENSMCP_LENS_PROBE!=="0",exports.LENS_WATCHER_PROBE_ENABLED=process.env.LENSMCP_LENS_WATCHER_PROBE!=="0",exports.LENS_WATCHER_UNVERIFIED=process.env.LENSMCP_LENS_WATCHER_UNVERIFIED==="keep"?"keep":"recycle",exports.LENS_WATCH_SCOPE_ENABLED=process.env.LENSMCP_LENS_WATCH_SCOPE!=="0",exports.POD_WATCHER_UNVERIFIED=process.env.LENSMCP_POD_WATCHER_UNVERIFIED==="keep"?"keep":"recycle",exports.POD_WATCHER_SILENT=process.env.LENSMCP_POD_WATCHER_SILENT==="recycle"?"recycle":"keep",exports.POD_RECYCLE_MODE=process.env.LENSMCP_POD_RECYCLE_MODE==="in-place"?"in-place":"rolling",exports.POD_ROLL_READY_MS=envInt("LENSMCP_POD_ROLL_READY_MS",18e4),exports.LENS_PROBE_GRACE_MS=envInt("LENSMCP_LENS_PROBE_GRACE_MS",45e3),exports.LENS_PROBE_FAILS=envInt("LENSMCP_LENS_PROBE_FAILS",2),exports.LENS_PROBE_TIMEOUT_MS=envInt("LENSMCP_LENS_PROBE_TIMEOUT_MS",1e3),exports.LENS_PROBE_COOLDOWN_MS=envInt("LENSMCP_LENS_PROBE_COOLDOWN_MS",3e4),exports.LENS_PROBE_BOOT_GRACE_MS=envInt("LENSMCP_LENS_PROBE_BOOT_GRACE_MS",24e4),exports.PORT_FREE_WAIT_MS=envInt("LENSMCP_PORT_FREE_WAIT_MS",1e4),exports.PORT_FREE_POLL_MS=envInt("LENSMCP_PORT_FREE_POLL_MS",250),exports.CHILD_START_FAIL_MS=envInt("LENSMCP_CHILD_START_FAIL_MS",1e4),exports.MAX_PORT_CONFLICT_RETRIES=envInt("LENSMCP_MAX_PORT_CONFLICT_RETRIES",5),exports.LENS_PARKED_PORT_REPROBE_MS=envInt("LENSMCP_PARKED_PORT_REPROBE_MS",3e5),exports.LENS_RECYCLE_KILL_GRACE_MS=envInt("LENSMCP_RECYCLE_KILL_GRACE_MS",5e3),exports.LENS_RESTART_MODE=process.env.LENSMCP_LENS_RESTART_MODE==="in-place"?"in-place":"rolling",exports.LENS_REPLACEMENT_READY_MS=envInt("LENSMCP_LENS_REPLACEMENT_READY_MS",3e4),exports.LENS_REPLACEMENT_DRAIN_MS=envInt("LENSMCP_LENS_REPLACEMENT_DRAIN_MS",2e3,!0),exports.LENS_REQUEST_RECOVERY_WAIT_MS=envInt("LENSMCP_LENS_REQUEST_RECOVERY_WAIT_MS",15e3),exports.GATEWAY_KEEPALIVE_TIMEOUT_MS=envInt("LENSMCP_KEEPALIVE_TIMEOUT_MS",76e3),exports.GATEWAY_HEADERS_TIMEOUT_MS=envInt("LENSMCP_HEADERS_TIMEOUT_MS",6e4),exports.GATEWAY_STOP_GRACE_MS=envInt("LENSMCP_STOP_GRACE_MS",3e3),exports.GATEWAY_MAX_CONNECTIONS=envInt("LENSMCP_MAX_CONNECTIONS",0,!0),exports.GATEWAY_CONN_CHECK_MS=envInt("LENSMCP_CONN_CHECK_MS",0,!0),exports.BODY_STALL_MS=envInt("LENSMCP_BODY_STALL_MS",6e4,!0),exports.GATEWAY_H2_RESET_BURST=envInt("LENSMCP_H2_RESET_BURST",1e5),exports.GATEWAY_H2_RESET_RATE=envInt("LENSMCP_H2_RESET_RATE",1e4);
1
+ "use strict";var M=Object.defineProperty;var e=(_,E)=>M(_,"name",{value:E,configurable:!0});var O=Object.defineProperty,R=e((_,E)=>O(_,"name",{value:E,configurable:!0}),"R");Object.defineProperty(exports,"__esModule",{value:!0}),exports.GATEWAY_H2_RESET_RATE=exports.GATEWAY_H2_RESET_BURST=exports.BODY_STALL_MS=exports.GATEWAY_CONN_CHECK_MS=exports.GATEWAY_MAX_CONNECTIONS=exports.GATEWAY_STOP_GRACE_MS=exports.GATEWAY_HEADERS_TIMEOUT_MS=exports.GATEWAY_KEEPALIVE_TIMEOUT_MS=exports.LENS_REQUEST_RECOVERY_WAIT_MS=exports.LENS_REPLACEMENT_DRAIN_MS=exports.LENS_REPLACEMENT_READY_MS=exports.LENS_RESTART_MODE=exports.LENS_RECYCLE_KILL_GRACE_MS=exports.LENS_PARKED_PORT_REPROBE_MS=exports.MAX_PORT_CONFLICT_RETRIES=exports.CHILD_START_FAIL_MS=exports.PORT_FREE_POLL_MS=exports.PORT_FREE_WAIT_MS=exports.LENS_PROBE_BOOT_GRACE_MS=exports.LENS_PROBE_COOLDOWN_MS=exports.LENS_PROBE_TIMEOUT_MS=exports.LENS_PROBE_FAILS=exports.LENS_PROBE_GRACE_MS=exports.POD_MAX_CONCURRENT_ROLLS=exports.POD_ROLL_READY_MS=exports.POD_RECYCLE_MODE=exports.POD_WATCHER_SILENT=exports.POD_WATCHER_UNVERIFIED=exports.LENS_WATCH_SCOPE_ENABLED=exports.LENS_WATCHER_UNVERIFIED=exports.LENS_WATCHER_PROBE_ENABLED=exports.LENS_PROBE_ENABLED=exports.POD_STALE_RECYCLE_COOLDOWN_MS=exports.POD_STALE_SCAN_MS=exports.POD_RECYCLE_SETTLE_MS=exports.POD_STALE_GRACE_MS=exports.POD_MAX_AGE_MS=exports.POD_RECYCLE_ENABLED=exports.WEDGE_RECYCLE_GRACE_MS=exports.POD_ALIVE_PATH=exports.POD_ALIVE_PROBE_TIMEOUT_MS=exports.POD_SLOW_FIRST_BYTE_MS=exports.POD_RESPONSE_TIMEOUT_MS=exports.UPSTREAM_HEAL_STEP_MS=exports.UPSTREAM_HEAL_WINDOW_MS=exports.SERVICE_RESTART_WINDOW_MS=exports.SERVICE_MAX_RESTARTS=exports.SERVICE_ERROR_THROTTLE_MS=void 0;function envInt(_,E,L=!1){const S=Number(process.env[_]);return!Number.isFinite(S)||S<0?E:S===0?L?0:E:S}e(envInt,"envInt"),R(envInt,"envInt"),exports.SERVICE_ERROR_THROTTLE_MS=5e3,exports.SERVICE_MAX_RESTARTS=5,exports.SERVICE_RESTART_WINDOW_MS=6e4,exports.UPSTREAM_HEAL_WINDOW_MS=8e3,exports.UPSTREAM_HEAL_STEP_MS=300,exports.POD_RESPONSE_TIMEOUT_MS=(()=>{const _=Number(process.env.LENSMCP_POD_RESPONSE_TIMEOUT_MS);return Number.isFinite(_)&&_>0?_:3e4})(),exports.POD_SLOW_FIRST_BYTE_MS=envInt("LENSMCP_POD_SLOW_FIRST_BYTE_MS",10*6e4,!0),exports.POD_ALIVE_PROBE_TIMEOUT_MS=envInt("LENSMCP_POD_ALIVE_PROBE_TIMEOUT_MS",1e3),exports.POD_ALIVE_PATH="/__lensmcp/alive",exports.WEDGE_RECYCLE_GRACE_MS=(()=>{const _=Number(process.env.LENSMCP_WEDGE_RECYCLE_GRACE_MS);return Number.isFinite(_)&&_>0?_:15e3})(),exports.POD_RECYCLE_ENABLED=process.env.LENSMCP_POD_RECYCLE!=="0",exports.POD_MAX_AGE_MS=envInt("LENSMCP_POD_MAX_AGE_MS",240*6e4,!0),exports.POD_STALE_GRACE_MS=envInt("LENSMCP_POD_STALE_GRACE_MS",1e4),exports.POD_RECYCLE_SETTLE_MS=envInt("LENSMCP_POD_RECYCLE_SETTLE_MS",8e3),exports.POD_STALE_SCAN_MS=envInt("LENSMCP_POD_STALE_SCAN_MS",3e4),exports.POD_STALE_RECYCLE_COOLDOWN_MS=envInt("LENSMCP_POD_STALE_RECYCLE_COOLDOWN_MS",6e4),exports.LENS_PROBE_ENABLED=process.env.LENSMCP_LENS_PROBE!=="0",exports.LENS_WATCHER_PROBE_ENABLED=process.env.LENSMCP_LENS_WATCHER_PROBE!=="0",exports.LENS_WATCHER_UNVERIFIED=process.env.LENSMCP_LENS_WATCHER_UNVERIFIED==="keep"?"keep":"recycle",exports.LENS_WATCH_SCOPE_ENABLED=process.env.LENSMCP_LENS_WATCH_SCOPE!=="0",exports.POD_WATCHER_UNVERIFIED=process.env.LENSMCP_POD_WATCHER_UNVERIFIED==="keep"?"keep":"recycle",exports.POD_WATCHER_SILENT=process.env.LENSMCP_POD_WATCHER_SILENT==="recycle"?"recycle":"keep",exports.POD_RECYCLE_MODE=process.env.LENSMCP_POD_RECYCLE_MODE==="in-place"?"in-place":"rolling",exports.POD_ROLL_READY_MS=envInt("LENSMCP_POD_ROLL_READY_MS",18e4),exports.POD_MAX_CONCURRENT_ROLLS=envInt("LENSMCP_POD_MAX_CONCURRENT_ROLLS",2,!0),exports.LENS_PROBE_GRACE_MS=envInt("LENSMCP_LENS_PROBE_GRACE_MS",45e3),exports.LENS_PROBE_FAILS=envInt("LENSMCP_LENS_PROBE_FAILS",2),exports.LENS_PROBE_TIMEOUT_MS=envInt("LENSMCP_LENS_PROBE_TIMEOUT_MS",1e3),exports.LENS_PROBE_COOLDOWN_MS=envInt("LENSMCP_LENS_PROBE_COOLDOWN_MS",3e4),exports.LENS_PROBE_BOOT_GRACE_MS=envInt("LENSMCP_LENS_PROBE_BOOT_GRACE_MS",24e4),exports.PORT_FREE_WAIT_MS=envInt("LENSMCP_PORT_FREE_WAIT_MS",1e4),exports.PORT_FREE_POLL_MS=envInt("LENSMCP_PORT_FREE_POLL_MS",250),exports.CHILD_START_FAIL_MS=envInt("LENSMCP_CHILD_START_FAIL_MS",1e4),exports.MAX_PORT_CONFLICT_RETRIES=envInt("LENSMCP_MAX_PORT_CONFLICT_RETRIES",5),exports.LENS_PARKED_PORT_REPROBE_MS=envInt("LENSMCP_PARKED_PORT_REPROBE_MS",3e5),exports.LENS_RECYCLE_KILL_GRACE_MS=envInt("LENSMCP_RECYCLE_KILL_GRACE_MS",5e3),exports.LENS_RESTART_MODE=process.env.LENSMCP_LENS_RESTART_MODE==="in-place"?"in-place":"rolling",exports.LENS_REPLACEMENT_READY_MS=envInt("LENSMCP_LENS_REPLACEMENT_READY_MS",3e4),exports.LENS_REPLACEMENT_DRAIN_MS=envInt("LENSMCP_LENS_REPLACEMENT_DRAIN_MS",2e3,!0),exports.LENS_REQUEST_RECOVERY_WAIT_MS=envInt("LENSMCP_LENS_REQUEST_RECOVERY_WAIT_MS",15e3),exports.GATEWAY_KEEPALIVE_TIMEOUT_MS=envInt("LENSMCP_KEEPALIVE_TIMEOUT_MS",76e3),exports.GATEWAY_HEADERS_TIMEOUT_MS=envInt("LENSMCP_HEADERS_TIMEOUT_MS",6e4),exports.GATEWAY_STOP_GRACE_MS=envInt("LENSMCP_STOP_GRACE_MS",3e3),exports.GATEWAY_MAX_CONNECTIONS=envInt("LENSMCP_MAX_CONNECTIONS",0,!0),exports.GATEWAY_CONN_CHECK_MS=envInt("LENSMCP_CONN_CHECK_MS",0,!0),exports.BODY_STALL_MS=envInt("LENSMCP_BODY_STALL_MS",6e4,!0),exports.GATEWAY_H2_RESET_BURST=envInt("LENSMCP_H2_RESET_BURST",1e5),exports.GATEWAY_H2_RESET_RATE=envInt("LENSMCP_H2_RESET_RATE",1e4);
@@ -1 +1 @@
1
- "use strict";var a=Object.defineProperty;var r=(e,t)=>a(e,"name",{value:t,configurable:!0});var c=Object.defineProperty,n=r((e,t)=>c(e,"name",{value:t,configurable:!0}),"n");Object.defineProperty(exports,"__esModule",{value:!0}),exports.workspaceLogWriter=workspaceLogWriter,exports.closeWorkspaceLogs=closeWorkspaceLogs;const tslib_1=require("tslib"),fs=tslib_1.__importStar(require("node:fs")),path=tslib_1.__importStar(require("node:path")),fds=new Map,written=new Map,MAX_BYTES=50*1024*1024,CHECK_EVERY=1024*1024;function ensureFd(e){const t=fds.get(e);if(t!==void 0)return t;try{fs.mkdirSync(path.dirname(e),{recursive:!0});const o=fs.openSync(e,"a");return fds.set(e,o),written.set(e,0),o}catch{return}}r(ensureFd,"ensureFd"),n(ensureFd,"ensureFd");function closeFd(e){const t=fds.get(e);if(fds.delete(e),written.delete(e),t!==void 0)try{fs.closeSync(t)}catch{}}r(closeFd,"closeFd"),n(closeFd,"closeFd");function rotateIfHuge(e){try{if(fs.statSync(e).size<=MAX_BYTES)return}catch{return}closeFd(e);try{fs.renameSync(e,`${e}.1`)}catch{}}r(rotateIfHuge,"rotateIfHuge"),n(rotateIfHuge,"rotateIfHuge");function workspaceLogWriter(e){const t=path.join(e,".lensmcp","gateway.log");if(ensureFd(t)!==void 0)return o=>{const s=ensureFd(t);if(s===void 0)return;try{fs.writeSync(s,o)}catch{closeFd(t);return}const i=(written.get(t)??0)+o.length;i>=CHECK_EVERY?(written.set(t,0),rotateIfHuge(t)):written.set(t,i)}}r(workspaceLogWriter,"workspaceLogWriter"),n(workspaceLogWriter,"workspaceLogWriter");function closeWorkspaceLogs(){for(const e of[...fds.keys()])closeFd(e)}r(closeWorkspaceLogs,"closeWorkspaceLogs"),n(closeWorkspaceLogs,"closeWorkspaceLogs");
1
+ "use strict";var a=Object.defineProperty;var r=(e,t)=>a(e,"name",{value:t,configurable:!0});var s=Object.defineProperty,n=r((e,t)=>s(e,"name",{value:t,configurable:!0}),"n");Object.defineProperty(exports,"__esModule",{value:!0}),exports.workspaceLogWriter=workspaceLogWriter,exports.closeWorkspaceLogs=closeWorkspaceLogs;const tslib_1=require("tslib"),fs=tslib_1.__importStar(require("node:fs")),path=tslib_1.__importStar(require("node:path")),inspector_secret_1=require("../../../inspector-secret"),fds=new Map,written=new Map,MAX_BYTES=50*1024*1024,CHECK_EVERY=1024*1024;function ensurePrivateDir(e){fs.mkdirSync(e,{recursive:!0,mode:448});try{const t=fs.statSync(e);(t.mode&63)!==0&&(typeof process.getuid!="function"||t.uid===process.getuid())&&fs.chmodSync(e,448)}catch{}}r(ensurePrivateDir,"ensurePrivateDir"),n(ensurePrivateDir,"ensurePrivateDir");function ownerOnly(e){try{fs.chmodSync(e,384)}catch{}}r(ownerOnly,"ownerOnly"),n(ownerOnly,"ownerOnly");function ensureFd(e){const t=fds.get(e);if(t!==void 0)return t;try{ensurePrivateDir(path.dirname(e));const o=fs.openSync(e,"a",384);return ownerOnly(e),fds.set(e,o),written.set(e,0),o}catch{return}}r(ensureFd,"ensureFd"),n(ensureFd,"ensureFd");function closeFd(e){const t=fds.get(e);if(fds.delete(e),written.delete(e),t!==void 0)try{fs.closeSync(t)}catch{}}r(closeFd,"closeFd"),n(closeFd,"closeFd");function rotateIfHuge(e){try{if(fs.statSync(e).size<=MAX_BYTES)return}catch{return}closeFd(e);try{fs.renameSync(e,`${e}.1`)}catch{}ownerOnly(`${e}.1`)}r(rotateIfHuge,"rotateIfHuge"),n(rotateIfHuge,"rotateIfHuge");function workspaceLogWriter(e){const t=path.join(e,".lensmcp","gateway.log");if(ensureFd(t)!==void 0)return o=>{const c=ensureFd(t);if(c===void 0)return;try{fs.writeSync(c,(0,inspector_secret_1.redactInspectorUrls)(o))}catch{closeFd(t);return}const i=(written.get(t)??0)+o.length;i>=CHECK_EVERY?(written.set(t,0),rotateIfHuge(t)):written.set(t,i)}}r(workspaceLogWriter,"workspaceLogWriter"),n(workspaceLogWriter,"workspaceLogWriter");function closeWorkspaceLogs(){for(const e of[...fds.keys()])closeFd(e)}r(closeWorkspaceLogs,"closeWorkspaceLogs"),n(closeWorkspaceLogs,"closeWorkspaceLogs");
@@ -16,4 +16,7 @@ export interface GatewayExecutorSchema {
16
16
  dashboardPort?: number;
17
17
  /** Override the dashboard hostname. Default lens.<baseDomain>. */
18
18
  lensHost?: string;
19
+ /** Compile every service of this workspace in ONE webpack compilation (a build host) instead of one watcher per
20
+ * service. `LENSMCP_SHARED_COMPILER=1|0` wins over it. */
21
+ sharedCompiler?: boolean;
19
22
  }
@@ -42,6 +42,10 @@
42
42
  "lensHost": {
43
43
  "type": "string",
44
44
  "description": "Override the dashboard's dev hostname. Default lens.<baseDomain>, where <baseDomain> is the longest common dotted suffix of the declared cluster hosts (e.g. lens.tetros.ai.local)."
45
+ },
46
+ "sharedCompiler": {
47
+ "type": "boolean",
48
+ "description": "Compile every service of this workspace in ONE webpack compilation (a build host) instead of one watcher per service: shared libraries are compiled once. LENSMCP_SHARED_COMPILER=1|0 wins over it."
45
49
  }
46
50
  },
47
51
  "additionalProperties": false
@@ -54,4 +54,6 @@ export interface ServeExecutorSchema {
54
54
  debugPort?: number;
55
55
  /** Tee pod/worker logs (ANSI-stripped) to this file for IDE tailing (WebStorm Logs tab). Env fallback: LENSMCP_LOG_FILE. */
56
56
  logFile?: string;
57
+ /** webpack `devtool` for the dev build (default `eval`: no source maps). Env fallback: LENSMCP_DEV_DEVTOOL. */
58
+ devtool?: string;
57
59
  }
@@ -194,6 +194,10 @@
194
194
  "logFile": {
195
195
  "type": "string",
196
196
  "description": "Tee every pod/worker log line (ANSI-stripped) to this file, relative to workspace root (e.g. '.lensmcp/logs/my-service.log'). Point an IDE at it — WebStorm: Run/Debug configuration → Logs tab — to see live service logs next to the debugger. Truncated once per serve run. Also settable via the LENSMCP_LOG_FILE env var (this option wins)."
197
+ },
198
+ "devtool": {
199
+ "type": "string",
200
+ "description": "webpack devtool for the dev build. Default 'eval': no source maps — every stack frame names its module by absolute path, at the transpiled line, and pods hold one copy of the bundle's text. A map-carrying value (e.g. 'cheap-module-source-map', the cheapest for pods) maps frames to TypeScript lines: ts-loader is told to emit maps and pods run with --enable-source-maps. 'false' = none. Also settable via the LENSMCP_DEV_DEVTOOL env var (this option wins)."
197
201
  }
198
202
  },
199
203
  "required": [
@@ -2,23 +2,29 @@ import type { ServeExecutorSchema } from './schema';
2
2
  interface ExecutorContext {
3
3
  root: string;
4
4
  projectName?: string;
5
+ targetName?: string;
6
+ configurationName?: string;
5
7
  projectsConfigurations?: {
6
8
  projects: Record<string, {
7
9
  root: string;
8
10
  }>;
9
11
  };
10
12
  }
13
+ interface ServeResult {
14
+ success: boolean;
15
+ baseUrl?: string;
16
+ }
11
17
  /**
12
18
  * Dev serve executor — webpack watch mode with integrated devserver.
13
19
  *
14
20
  * Owns the full devserver lifecycle:
15
- * 1. Starts webpack in watch mode
21
+ * 1. Starts webpack in watch mode — or, under a gateway running the shared compiler, joins the workspace's ONE
22
+ * compilation (shared-build/attach.ts, issues/open/pod-memory-05) and is told about each build of its bundle
16
23
  * 2. On first successful build, forks main.devserver.js with proper env vars
17
- * 3. On subsequent builds, POSTs /webpack/reload to devserver
24
+ * 3. On subsequent builds, POSTs /webpack/reload to devserver — attached: only when ITS bundle changed
18
25
  * 4. On shutdown, cleans up devserver and webpack watcher
26
+ *
27
+ * webpack and the dev config are loaded only when this process compiles: an attached executor holds neither.
19
28
  */
20
- declare function serveExecutor(options: ServeExecutorSchema, context: ExecutorContext): AsyncGenerator<{
21
- success: boolean;
22
- baseUrl?: string;
23
- }>;
29
+ declare function serveExecutor(options: ServeExecutorSchema, context: ExecutorContext): AsyncGenerator<ServeResult>;
24
30
  export default serveExecutor;
@@ -1 +1 @@
1
- "use strict";var V=Object.defineProperty;var l=(e,r)=>V(e,"name",{value:r,configurable:!0});var J=Object.defineProperty,a=l((e,r)=>J(e,"name",{value:r,configurable:!0}),"a");Object.defineProperty(exports,"__esModule",{value:!0});const tslib_1=require("tslib"),path=tslib_1.__importStar(require("node:path")),fs=tslib_1.__importStar(require("node:fs")),node_child_process_1=require("node:child_process"),yaml=tslib_1.__importStar(require("js-yaml")),create_webpack_dev_1=require("../../create-webpack-dev"),process_name_1=require("../../process-name"),webpack=require("webpack");async function*serveExecutor(e,r){process.env.NODE_ENV="development";const D=r.projectsConfigurations.projects[r.projectName],i=r.root,d=path.join(i,D.root),R=e.outputPath?path.join(i,e.outputPath):path.join(i,"dist",D.root),T=e.configEnv||"development",_=path.join(i,"config",`config.${T}.yaml`),S=3050;let p=S,s=r.projectName,m={};fs.existsSync(_)?(m=yaml.load(fs.readFileSync(_,"utf8")),p=Number(m.port)||p,s=m.serviceName||s):console.warn(`[serve] ${r.projectName}: no config file at ${_} \u2014 public devserver port defaults to ${S}. If another service also lacks its config, both bind ${S} \u2192 EADDRINUSE. Add config/config.${T}.yaml with a distinct \`port:\` (matching this project's cluster.port).`),e.serviceName&&(s=e.serviceName);const y=e.servePrefix??"",u=e.debugPort??(Number(process.env.LENSMCP_DEBUG_PORT)||void 0),x=/^(1|true|yes|on)$/i.test((process.env.LENSMCP_DEBUG_FIXED_PORTS??"").trim()),c=e.logFile?path.resolve(i,e.logFile):process.env.LENSMCP_LOG_FILE||void 0;if(c){fs.mkdirSync(path.dirname(c),{recursive:!0}),fs.writeFileSync(c,"",{mode:384});try{fs.chmodSync(c,384)}catch{}}let P,N;e.gateway?.middleware&&(P=path.resolve(d,e.gateway.middleware),N=JSON.stringify(m));const A=e.entryFile||"./src/deployments/service/main.ts",$=e.tsConfigFile||"./tsconfig.app.json",G=path.resolve(d,A),F=path.resolve(d,$),M=(e.workers||[]).map(o=>({entryName:o.name,entryPath:path.resolve(d,o.entryPath)})),C=(0,create_webpack_dev_1.createDevWebpackConfig)({appName:r.projectName,appRoot:d,outputDir:R,main:G,tsConfig:F,assets:e.assets||[],additionalEntryPoints:M,port:p,serviceName:s,memoryLimit:e.memoryLimit||8192,buildLibsFromSource:e.buildLibsFromSource!==!1,workspaceRoot:i,orgScopes:e.orgScopes||[],bundlePackages:e.bundlePackages||[],nodeExternalsConfig:e.nodeExternalsConfig,webpackConfigPath:e.webpackConfigPath,httpsReload:e.gateway?.https===!0});let n=null,b=!1;const O=path.join(__dirname,"../../main.devserver.js"),k=path.join(__dirname,"../../main.devserver.ts"),I=!fs.existsSync(O)&&fs.existsSync(k),w=I?k:O,U=path.join(R,"main.js");function v(){n&&!n.killed&&(n.kill("SIGTERM"),n=null)}l(v,"g"),a(v,"cleanup");const W=["SIGINT","SIGTERM","SIGHUP","SIGQUIT"].map(o=>{const t=a(()=>v(),"handler");return process.on(o,t),{sig:o,handler:t}});process.on("exit",v);function h(){if(!fs.existsSync(w)){console.error(`[serve] devserver script not found at ${w}`);return}const o=["--enable-source-maps"];I&&o.unshift("--require","@swc-node/register"),n=(0,node_child_process_1.fork)(w,{cwd:i,env:{...process.env,PORT:String(p),SERVICE_NAME:s,SERVE_PREFIX:y,LENSMCP_PROJECT:process.env.LENSMCP_PROJECT||r.projectName||s,LENSMCP_EVENT_FILE:process.env.LENSMCP_EVENT_FILE||path.join(i,".lensmcp","events.jsonl"),CHILD_COUNT:String(e.childCount||process.env.CHILD_COUNT||1),BUNDLE_PATH:U,...P&&{GATEWAY_MIDDLEWARE:P},...N&&{GATEWAY_CONFIG:N},...e.gateway?.routes?.length&&{GATEWAY_ROUTES:JSON.stringify(e.gateway.routes)},...e.gateway?.https&&{GATEWAY_HTTPS:"1"},...e.gateway?.extraPorts?.length&&{GATEWAY_EXTRA_PORTS:JSON.stringify(e.gateway.extraPorts)},...e.internalPort&&{INTERNAL_PORT:String(e.internalPort)},...u&&{LENSMCP_DEBUG_PORT:String(u)},...c&&{LENSMCP_LOG_FILE:c},...e.workers?.length&&{WORKERS:JSON.stringify(e.workers.map(t=>t.name))}},stdio:["inherit","inherit","inherit","ipc"],execArgv:o,execPath:(0,process_name_1.namedExecPath)((0,process_name_1.processName)(process.env.LENSMCP_WS_KEY||path.basename(i),s,"dev"))}),n.on("exit",(t,f)=>{n=null,!f&&(console.error(`[serve] devserver exited unexpectedly (code=${t}, signal=${f}) \u2014 respawning in 1.5s`),setTimeout(()=>{!n&&b&&h()},1500).unref?.())}),console.log(`[serve] Devserver started on port ${p} (service: ${s}${y?`, prefix: /${y}`:""})`),u?(console.warn(`[serve] DEBUGGER ENABLED for ${s}. Node's inspector has NO authentication \u2014 the ws:// UUID is the whole credential, and any account on this host that obtains it runs code as you. Do not enable this on a shared machine.`),x?console.warn(`[serve] LENSMCP_DEBUG_FIXED_PORTS=1 \u2014 pod inspectors bind PREDICTABLE ports 127.0.0.1:${u}+slot (workers ${u}+20+i), reachable by any account on this host. Attach WebStorm (Attach to Node.js/Chrome) to ${u}. Unset it to bind ephemeral ports instead.`):console.log(`[serve] Debug: pod inspectors bind an EPHEMERAL 127.0.0.1 port \u2014 click the "Debugger listening" link in this console, or run \`lensmcp debug ${s}\` to get the ws:// URLs over the owner-only control socket. Set LENSMCP_DEBUG_FIXED_PORTS=1 if your IDE needs a fixed attach port.`)):console.log(`[serve] Debug on demand: \`lensmcp debug ${s}\` opens pod inspectors without a restart`),c&&console.log(`[serve] Logs teed to ${c} \u2014 tail it in WebStorm via Run/Debug configuration \u2192 Logs tab`)}l(h,"v"),a(h,"startDevServer");function q(){if(!n||n.killed){console.log("[serve] Devserver not running, restarting..."),h();return}fetch(`http://localhost:${p}/webpack/reload`,{method:"POST",headers:{"content-type":"application/json"},body:"{}"}).then(()=>console.log("[serve] Notified devserver to reload")).catch(o=>{console.warn("[serve] Failed to notify devserver, restarting...",o.message),v(),h()})}l(q,"Y"),a(q,"_notifyDevServerReload");const{watch:X,...B}=C,Y=webpack(B);let g=null;const L=[];function E(o){if(g){const t=g;g=null,t(o)}else L.push(o)}l(E,"w"),a(E,"pushResult");function j(){return L.length>0?Promise.resolve(L.shift()):new Promise(o=>{g=o})}l(j,"B"),a(j,"waitForNext");const H=Y.watch(C.watchOptions||{},(o,t)=>{if(o){console.error("[serve] Webpack error:",o),E({success:!1});return}const f=t.hasErrors();if(console.info(t.toString({colors:!0,chunks:!1,assets:!0})),f){E({success:!1});return}(!b||!n)&&(b=!0,h()),E({success:!0,baseUrl:`http://localhost:${p}`})});try{for(;;)yield await j()}finally{H.close(()=>{}),v(),W.forEach(({sig:o,handler:t})=>process.removeListener(o,t))}}l(serveExecutor,"serveExecutor"),a(serveExecutor,"serveExecutor"),exports.default=serveExecutor,module.exports=serveExecutor,module.exports.default=serveExecutor;
1
+ "use strict";var ne=Object.defineProperty;var c=(e,r)=>ne(e,"name",{value:r,configurable:!0});var te=Object.defineProperty,o=c((e,r)=>te(e,"name",{value:r,configurable:!0}),"o");Object.defineProperty(exports,"__esModule",{value:!0});const tslib_1=require("tslib"),path=tslib_1.__importStar(require("node:path")),fs=tslib_1.__importStar(require("node:fs")),node_child_process_1=require("node:child_process"),yaml=tslib_1.__importStar(require("js-yaml")),dev_devtool_1=require("../../dev-devtool"),devserver_notifier_1=require("../../devserver-notifier"),process_name_1=require("../../process-name"),attach_1=require("../../shared-build/attach");function definedEnv(e){const r={};for(const[_,i]of Object.entries(e))typeof i=="string"&&(r[_]=i);return r}c(definedEnv,"definedEnv"),o(definedEnv,"definedEnv");async function*serveExecutor(e,r){process.env.NODE_ENV="development";const _=r.projectsConfigurations.projects[r.projectName],i=r.root,g=path.join(i,_.root),M=e.outputPath?path.join(i,e.outputPath):path.join(i,"dist",_.root),U=e.configEnv||"development",L=path.join(i,"config",`config.${U}.yaml`),C=3050;let u=C,l=r.projectName,S={};fs.existsSync(L)?(S=yaml.load(fs.readFileSync(L,"utf8")),u=Number(S.port)||u,l=S.serviceName||l):console.warn(`[serve] ${r.projectName}: no config file at ${L} \u2014 public devserver port defaults to ${C}. If another service also lacks its config, both bind ${C} \u2192 EADDRINUSE. Add config/config.${U}.yaml with a distinct \`port:\` (matching this project's cluster.port).`),e.serviceName&&(l=e.serviceName);const R=e.servePrefix??"",v=e.debugPort??(Number(process.env.LENSMCP_DEBUG_PORT)||void 0),H=/^(1|true|yes|on)$/i.test((process.env.LENSMCP_DEBUG_FIXED_PORTS??"").trim()),p=e.logFile?path.resolve(i,e.logFile):process.env.LENSMCP_LOG_FILE||void 0;if(p){fs.mkdirSync(path.dirname(p),{recursive:!0}),fs.writeFileSync(p,"",{mode:384});try{fs.chmodSync(p,384)}catch{}}let O,T;e.gateway?.middleware&&(O=path.resolve(g,e.gateway.middleware),T=JSON.stringify(S));const K=e.entryFile||"./src/deployments/service/main.ts",Q=e.tsConfigFile||"./tsconfig.app.json",z=path.resolve(g,K),F=path.resolve(g,Q),Z=(e.workers||[]).map(t=>({entryName:t.name,entryPath:path.resolve(g,t.entryPath)})),B={appName:r.projectName,appRoot:g,outputDir:M,main:z,tsConfig:F,assets:e.assets||[],additionalEntryPoints:Z,port:u,serviceName:l,memoryLimit:e.memoryLimit||8192,buildLibsFromSource:e.buildLibsFromSource!==!1,workspaceRoot:i,orgScopes:e.orgScopes||[],bundlePackages:e.bundlePackages||[],nodeExternalsConfig:e.nodeExternalsConfig,webpackConfigPath:e.webpackConfigPath,httpsReload:e.gateway?.https===!0,...e.devtool!==void 0&&{devtool:e.devtool}};let d=null,$=!1,D=!1,m=!1;const W=path.join(__dirname,"../../main.devserver.js"),q=path.join(__dirname,"../../main.devserver.ts"),V=!fs.existsSync(W)&&fs.existsSync(q),k=V?q:W,ee=path.join(M,"main.js");function I(){d&&!d.killed&&(d.kill("SIGTERM"),d=null)}c(I,"W"),o(I,"cleanup");function y(){m=!0,I()}c(y,"O"),o(y,"stop");const oe=["SIGINT","SIGTERM","SIGHUP","SIGQUIT"].map(t=>{const n=o(()=>y(),"handler");return process.on(t,n),{sig:t,handler:n}});process.on("exit",y);function E(){if(m)return;if(!fs.existsSync(k)){console.error(`[serve] devserver script not found at ${k}`);return}const t=["--enable-source-maps"];V&&t.unshift("--require","@swc-node/register");const n=(0,node_child_process_1.fork)(k,{cwd:i,env:{...process.env,PORT:String(u),SERVICE_NAME:l,SERVE_PREFIX:R,LENSMCP_PROJECT:process.env.LENSMCP_PROJECT||r.projectName||l,LENSMCP_EVENT_FILE:process.env.LENSMCP_EVENT_FILE||path.join(i,".lensmcp","events.jsonl"),CHILD_COUNT:String(e.childCount||process.env.CHILD_COUNT||1),BUNDLE_PATH:ee,...O&&{GATEWAY_MIDDLEWARE:O},...T&&{GATEWAY_CONFIG:T},...e.gateway?.routes?.length&&{GATEWAY_ROUTES:JSON.stringify(e.gateway.routes)},...e.gateway?.https&&{GATEWAY_HTTPS:"1"},...e.gateway?.extraPorts?.length&&{GATEWAY_EXTRA_PORTS:JSON.stringify(e.gateway.extraPorts)},...e.internalPort&&{INTERNAL_PORT:String(e.internalPort)},...v&&{LENSMCP_DEBUG_PORT:String(v)},...p&&{LENSMCP_LOG_FILE:p},...e.workers?.length&&{WORKERS:JSON.stringify(e.workers.map(a=>a.name))},[dev_devtool_1.DEV_SOURCE_MAPS_ENV]:D?"1":"0"},stdio:["inherit","inherit","inherit","ipc"],execArgv:t,execPath:(0,process_name_1.namedExecPath)((0,process_name_1.processName)(process.env.LENSMCP_WS_KEY||path.basename(i),l,"dev"))});d=n,n.on("exit",(a,f)=>{d===n&&(d=null),!(f||a===0||m)&&(console.error(`[serve] devserver exited unexpectedly (code=${a}, signal=${f}) \u2014 respawning in 1.5s`),setTimeout(()=>{!m&&!d&&$&&E()},1500).unref?.())}),console.log(`[serve] Devserver started on port ${u} (service: ${l}${R?`, prefix: /${R}`:""})`),v?(console.warn(`[serve] DEBUGGER ENABLED for ${l}. Node's inspector has NO authentication \u2014 the ws:// UUID is the whole credential, and any account on this host that obtains it runs code as you. Do not enable this on a shared machine.`),H?console.warn(`[serve] LENSMCP_DEBUG_FIXED_PORTS=1 \u2014 pod inspectors bind PREDICTABLE ports 127.0.0.1:${v}+slot (workers ${v}+20+i), reachable by any account on this host. Attach WebStorm (Attach to Node.js/Chrome) to ${v}. Unset it to bind ephemeral ports instead.`):console.log(`[serve] Debug: pod inspectors bind an EPHEMERAL 127.0.0.1 port. Get the ws:// URLs with \`lensmcp debug ${l}\` (the owner-only control socket); a devserver run in your own terminal also prints them there. Set LENSMCP_DEBUG_FIXED_PORTS=1 if your IDE needs a fixed attach port.`)):console.log(`[serve] Debug on demand: \`lensmcp debug ${l}\` opens pod inspectors without a restart`),p&&console.log(`[serve] Logs teed to ${p} \u2014 tail it in WebStorm via Run/Debug configuration \u2192 Logs tab`)}c(E,"S"),o(E,"startDevServer");function re(){if(!d||d.killed){console.log("[serve] Devserver not running, restarting..."),E();return}fetch(`http://localhost:${u}/webpack/reload`,{method:"POST",headers:{"content-type":"application/json"},body:"{}"}).then(()=>console.log("[serve] Notified devserver to reload")).catch(t=>{console.warn("[serve] Failed to notify devserver, restarting...",t.message),I(),E()})}c(re,"oe"),o(re,"_notifyDevServerReload");let N=null;const x=[];function h(t){if(N){const n=N;N=null,n(t)}else x.push(t)}c(h,"p"),o(h,"pushResult");function J(){return x.length>0?Promise.resolve(x.shift()):new Promise(t=>{N=t})}c(J,"Z"),o(J,"waitForNext");let w=o(()=>{},"closeBuild");function A(){return!$||!d?($=!0,E(),!0):!1}c(A,"q"),o(A,"builtOk");function b(){if(m)return;const{createDevWebpackConfig:t}=require("../../create-webpack-dev"),n=require("webpack"),a=t(B),{watch:f,...P}=a,s=n(P);D=(0,dev_devtool_1.bundleCarriesSourceMaps)(s.options.devtool);const G=s.watch(a.watchOptions||{},(j,X)=>{if(j){console.error("[serve] Webpack error:",j),h({success:!1});return}const se=X.hasErrors();if(console.info(X.toString({colors:!0,chunks:!1,assets:!0})),se){h({success:!1});return}A(),h({success:!0,baseUrl:`http://localhost:${u}`})});w=o(()=>G.close(()=>{}),"closeBuild")}c(b,"k"),o(b,"compileOnItsOwn");function Y(t){const n=t.accepted.projects.filter(s=>s!==r.projectName);console.log(`[serve] ${r.projectName}: compiled by the workspace's shared compilation ${t.accepted.group.slice(0,8)}${n.length?` with ${n.join(", ")}`:""} \u2014 no webpack in this process`);const a=new devserver_notifier_1.DevserverNotifier(u,e.gateway?.https===!0,(0,devserver_notifier_1.devserverControlSock)(l)),f=(0,attach_1.createAttachedTypecheck)({appName:r.projectName,tsConfig:F,workspaceRoot:i,memoryLimit:e.memoryLimit||8192});let P;w=o(()=>{t.close(),f.dispose()},"closeBuild"),t.listen(s=>{if(!m)switch(s.type){case"watch-run":a.watchRun(s.paths);return;case"watch-closed":a.degrade("watch closed");return;case"failed":console.error(`[serve] the shared compiler failed: ${s.message}`),a.degrade(`compiler failed: ${s.message}`),h({success:!1});return;case"refused":console.log(`[serve] ${r.projectName}: compiling on its own from now on \u2014 ${s.reason}`),w(),b();return;case"built":{if(console.info(s.text),D=s.sourceMaps,f.built(s),!s.ok){a.tellWatching(),h({success:!1});return}const G=s.hash!==P;P=s.hash;const j=A();a.built(G&&!j),h({success:!0,baseUrl:`http://localhost:${u}`});return}default:return}})}if(c(Y,"ee"),o(Y,"attachToSharedBuild"),(0,attach_1.sharedBuildOffered)()){const t=await(0,attach_1.joinSharedBuild)({project:r.projectName,target:r.targetName??"serve-hmr",...r.configurationName?{configuration:r.configurationName}:{},options:B,targetOptions:{...e},env:definedEnv(process.env)});t.kind==="attached"?Y(t.session):(console.log(`[serve] ${r.projectName}: compiling on its own \u2014 ${t.reason}`),b())}else b();try{for(;;)yield await J()}finally{y(),w(),oe.forEach(({sig:t,handler:n})=>process.removeListener(t,n))}}c(serveExecutor,"serveExecutor"),o(serveExecutor,"serveExecutor"),exports.default=serveExecutor,module.exports=serveExecutor,module.exports.default=serveExecutor;
@@ -4,7 +4,7 @@
4
4
  * `nx trust` collects host strings from every project's `project.json`, from embedded route options,
5
5
  * and from its own `hosts` option, then writes them into `/etc/hosts` as root. Workspace
6
6
  * configuration therefore reaches a privileged command, and the only check was "does not contain
7
- * `*`" (issues/codex-security/33).
7
+ * `*`" (issues/closed/codex-security-33).
8
8
  *
9
9
  * This is the first of two defences. The second — removing the shell — is what actually closes the
10
10
  * injection; this one means a value that could never be a hostname fails loudly at the point it is
package/exit-reason.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Why a pod died, in words (issues/foodguard/22). "socket hang up" was the only trace a pod left when
2
+ * Why a pod died, in words (issues/closed/foodguard-22). "socket hang up" was the only trace a pod left when
3
3
  * it died mid-work: a crash, a SIGKILL and an OOM kill read the same, and the stderr that explained
4
4
  * which was gone with the process. Pure helpers so the devserver's exit handler stays a few lines.
5
5
  */
@@ -5,6 +5,18 @@ export interface ForkTsCheckReporterOptions {
5
5
  /** Override the lens bus file; defaults to `LENSMCP_EVENT_FILE` / `<root>/.lensmcp/events.jsonl`. */
6
6
  eventFile?: string;
7
7
  }
8
+ /**
9
+ * Load the SAME module instance `@nx/webpack` loaded.
10
+ *
11
+ * `getCompilerHooks` reads a module-level `WeakMap` keyed by compiler, so hooks registered
12
+ * through a second copy of the package are a different map and never fire. `@nx/webpack` does a
13
+ * bare `require('fork-ts-checker-webpack-plugin')` from its own directory, so resolving from
14
+ * there first is what guarantees we get its copy; the workspace root and our own resolution are
15
+ * fallbacks for a layout that hoists differently.
16
+ */
17
+ export declare function loadForkTsChecker(workspaceRoot: string): {
18
+ getCompilerHooks?: (c: unknown) => unknown;
19
+ } | null;
8
20
  export declare class ForkTsCheckReporterPlugin {
9
21
  private readonly opts;
10
22
  private startedAt;
@@ -1 +1 @@
1
- "use strict";var p=Object.defineProperty;var s=(e,t)=>p(e,"name",{value:t,configurable:!0});var a=Object.defineProperty,r=s((e,t)=>a(e,"name",{value:t,configurable:!0}),"r");Object.defineProperty(exports,"__esModule",{value:!0}),exports.ForkTsCheckReporterPlugin=void 0;const tslib_1=require("tslib"),path=tslib_1.__importStar(require("node:path")),typecheck_bus_1=require("./typecheck-bus");function loadForkTsChecker(e){const t=[];try{t.push(path.dirname(require.resolve("@nx/webpack/package.json",{paths:[e]})))}catch{}t.push(e,__dirname);for(const o of t)try{return require(require.resolve("fork-ts-checker-webpack-plugin",{paths:[o]}))}catch{}return null}s(loadForkTsChecker,"loadForkTsChecker"),r(loadForkTsChecker,"loadForkTsChecker");function toDiagnostic(e,t){return{file:e.file?path.relative(t,e.file)||e.file:"<unknown>",line:e.location?.start?.line??0,column:e.location?.start?.column??0,severity:e.severity==="warning"?"warning":"error",code:/^TS\d+$/.test(e.code)?e.code:`TS${e.code}`,message:e.message}}s(toDiagnostic,"toDiagnostic"),r(toDiagnostic,"toDiagnostic");class ForkTsCheckReporterPlugin{static{s(this,"ForkTsCheckReporterPlugin")}static{r(this,"ForkTsCheckReporterPlugin")}constructor(t){this.startedAt=0,this.opts=t}apply(t){const o=loadForkTsChecker(this.opts.workspaceRoot)?.getCompilerHooks;if(typeof o!="function")return;let c;try{c=o(t)}catch{return}c.start?.tapPromise("LensmcpForkTsCheckReporter",async i=>(this.startedAt=Date.now(),i)),c.issues?.tap("LensmcpForkTsCheckReporter",i=>{try{(0,typecheck_bus_1.publishTypecheckDiagnostics)({workspaceRoot:this.opts.workspaceRoot,project:this.opts.appName,tool:"fork-ts-checker",tsConfig:this.opts.tsConfig,diagnostics:(i??[]).map(n=>toDiagnostic(n,this.opts.workspaceRoot)),durationMs:this.startedAt?Date.now()-this.startedAt:0,...this.opts.eventFile?{eventFile:this.opts.eventFile}:{}})}catch{}return i})}}exports.ForkTsCheckReporterPlugin=ForkTsCheckReporterPlugin;
1
+ "use strict";var p=Object.defineProperty;var o=(e,t)=>p(e,"name",{value:t,configurable:!0});var a=Object.defineProperty,r=o((e,t)=>a(e,"name",{value:t,configurable:!0}),"r");Object.defineProperty(exports,"__esModule",{value:!0}),exports.ForkTsCheckReporterPlugin=void 0,exports.loadForkTsChecker=loadForkTsChecker;const tslib_1=require("tslib"),path=tslib_1.__importStar(require("node:path")),typecheck_bus_1=require("./typecheck-bus");function loadForkTsChecker(e){const t=[];try{t.push(path.dirname(require.resolve("@nx/webpack/package.json",{paths:[e]})))}catch{}t.push(e,__dirname);for(const s of t)try{return require(require.resolve("fork-ts-checker-webpack-plugin",{paths:[s]}))}catch{}return null}o(loadForkTsChecker,"loadForkTsChecker"),r(loadForkTsChecker,"loadForkTsChecker");function toDiagnostic(e,t){return{file:e.file?path.relative(t,e.file)||e.file:"<unknown>",line:e.location?.start?.line??0,column:e.location?.start?.column??0,severity:e.severity==="warning"?"warning":"error",code:/^TS\d+$/.test(e.code)?e.code:`TS${e.code}`,message:e.message}}o(toDiagnostic,"toDiagnostic"),r(toDiagnostic,"toDiagnostic");class ForkTsCheckReporterPlugin{static{o(this,"ForkTsCheckReporterPlugin")}static{r(this,"ForkTsCheckReporterPlugin")}constructor(t){this.startedAt=0,this.opts=t}apply(t){const s=loadForkTsChecker(this.opts.workspaceRoot)?.getCompilerHooks;if(typeof s!="function")return;let c;try{c=s(t)}catch{return}c.start?.tapPromise("LensmcpForkTsCheckReporter",async i=>(this.startedAt=Date.now(),i)),c.issues?.tap("LensmcpForkTsCheckReporter",i=>{try{(0,typecheck_bus_1.publishTypecheckDiagnostics)({workspaceRoot:this.opts.workspaceRoot,project:this.opts.appName,tool:"fork-ts-checker",tsConfig:this.opts.tsConfig,diagnostics:(i??[]).map(n=>toDiagnostic(n,this.opts.workspaceRoot)),durationMs:this.startedAt?Date.now()-this.startedAt:0,...this.opts.eventFile?{eventFile:this.opts.eventFile}:{}})}catch{}return i})}}exports.ForkTsCheckReporterPlugin=ForkTsCheckReporterPlugin;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ "use strict";var i=Object.defineProperty;var o=(r,e)=>i(r,"name",{value:e,configurable:!0});var t=Object.defineProperty,s=o((r,e)=>t(r,"name",{value:e,configurable:!0}),"s");Object.defineProperty(exports,"__esModule",{value:!0});const tslib_1=require("tslib"),fs=tslib_1.__importStar(require("node:fs")),guest_graph_1=require("./executors/gateway/runtime/guest-graph");function main(){const r=process.argv[2];r||(console.error("usage: graph-snapshot.js <output file> \u2014 run in the workspace root"),process.exit(2)),(0,guest_graph_1.snapshotWorkspaceGraph)(process.cwd()).then(e=>{fs.writeFileSync(r,JSON.stringify(e),{mode:384}),process.exit(0)},e=>{console.error(`[graph-snapshot] ${e?.message??String(e)}`),process.exit(1)})}o(main,"main"),s(main,"main"),require.main===module&&main();
@@ -0,0 +1,66 @@
1
+ export interface HeapSnapshotPolicy {
2
+ /** Refuse above this live heap. */
3
+ maxHeapBytes: number;
4
+ /** Never take one with less than this available on the machine… */
5
+ minFreeBytes: number;
6
+ /** …or less than this many times the live heap (the snapshot graph is built in native memory first). */
7
+ freeFactor: number;
8
+ /** Snapshots kept per directory; older ones are deleted before a new one is written. */
9
+ keep: number;
10
+ /** Snapshots older than this are deleted. */
11
+ maxAgeMs: number;
12
+ }
13
+ /**
14
+ * - `LENSMCP_HEAP_SNAPSHOT_MAX_MB` — default `1024`.
15
+ * - `LENSMCP_HEAP_SNAPSHOT_MIN_FREE_MB` — default `1024`.
16
+ * - `LENSMCP_HEAP_SNAPSHOT_FREE_FACTOR` — default `3`.
17
+ * - `LENSMCP_HEAP_SNAPSHOT_KEEP` — default `3`.
18
+ * - `LENSMCP_HEAP_SNAPSHOT_MAX_AGE_H` — default `24`.
19
+ */
20
+ export declare function heapSnapshotPolicy(env?: NodeJS.ProcessEnv): HeapSnapshotPolicy;
21
+ /** Memory the machine can hand out without paging, and how that was read. */
22
+ export interface AvailableMemory {
23
+ bytes: number;
24
+ source: string;
25
+ }
26
+ /**
27
+ * What the machine could give a snapshot without swapping.
28
+ *
29
+ * `os.freemem()` is the wrong number on macOS: it counts only FREE pages, and a Mac under normal use keeps a few
30
+ * hundred MB free while gigabytes of inactive (reclaimable) pages sit beside them — it would refuse every time.
31
+ * `vm_stat`'s free + inactive + speculative + purgeable is what the kernel can reclaim without compressing or
32
+ * swapping. Linux has `MemAvailable` for exactly this. Elsewhere `os.freemem()` is all there is.
33
+ */
34
+ export declare function availableSystemMemory(platform?: NodeJS.Platform): AvailableMemory | undefined;
35
+ /** Why a snapshot must not be taken now, in the words the caller will print — or `undefined`. */
36
+ export declare function heapSnapshotRefusal(policy: HeapSnapshotPolicy, input: {
37
+ live: number;
38
+ available?: AvailableMemory;
39
+ }): string | undefined;
40
+ /**
41
+ * Where snapshots go: `LENSMCP_HEAP_DIR`, else `heap/` beside the workspace's bus (`<root>/.lensmcp/heap`), else
42
+ * `<cwd>/.lensmcp/heap`.
43
+ */
44
+ export declare function heapSnapshotDir(env?: NodeJS.ProcessEnv, cwd?: string): string;
45
+ /** A snapshot's file name: service, pod, pid, app generation, time. */
46
+ export declare function heapSnapshotFileName(service: string, pod: number, pid: number, gen: number, at: number): string;
47
+ /**
48
+ * Make `dir` exist and be owner-only — and refuse a symlink there: snapshots carry everything the app holds
49
+ * (tokens, keys, customer data), so where they land must be ours.
50
+ */
51
+ export declare function ensureHeapDir(dir: string): void;
52
+ /** Delete this directory's snapshots older than `maxAgeMs`, then all but the newest `keep - 1` (room for one more). */
53
+ export declare function pruneHeapSnapshots(dir: string, policy: HeapSnapshotPolicy, now?: number): string[];
54
+ /** What a written snapshot weighs and cost. */
55
+ export interface HeapSnapshotWritten {
56
+ bytes: number;
57
+ ms: number;
58
+ }
59
+ /**
60
+ * Stream a heap snapshot of THIS process to `file` through an in-process inspector session.
61
+ *
62
+ * The chunks arrive as the snapshot is serialised and are written as they come, so the JS heap never holds the
63
+ * whole thing. The file is created exclusively (`O_EXCL | O_NOFOLLOW`, `0600`): never someone else's file,
64
+ * never through a planted link. A failure removes what was written.
65
+ */
66
+ export declare function writeHeapSnapshot(file: string): Promise<HeapSnapshotWritten>;
@@ -0,0 +1 @@
1
+ "use strict";var _=Object.defineProperty;var p=(e,t)=>_(e,"name",{value:t,configurable:!0});var h=Object.defineProperty,i=p((e,t)=>h(e,"name",{value:t,configurable:!0}),"i");Object.defineProperty(exports,"__esModule",{value:!0}),exports.heapSnapshotPolicy=heapSnapshotPolicy,exports.availableSystemMemory=availableSystemMemory,exports.heapSnapshotRefusal=heapSnapshotRefusal,exports.heapSnapshotDir=heapSnapshotDir,exports.heapSnapshotFileName=heapSnapshotFileName,exports.ensureHeapDir=ensureHeapDir,exports.pruneHeapSnapshots=pruneHeapSnapshots,exports.writeHeapSnapshot=writeHeapSnapshot;const tslib_1=require("tslib"),node_child_process_1=require("node:child_process"),fs=tslib_1.__importStar(require("node:fs")),inspector=tslib_1.__importStar(require("node:inspector")),os=tslib_1.__importStar(require("node:os")),path=tslib_1.__importStar(require("node:path")),MB=1024*1024,numberFrom=i((e,t,o)=>{if(e===void 0||e.trim()==="")return t;const a=Number(e);return Number.isFinite(a)&&a>=o?a:t},"numberFrom");function heapSnapshotPolicy(e=process.env){return{maxHeapBytes:numberFrom(e.LENSMCP_HEAP_SNAPSHOT_MAX_MB,1024,1)*MB,minFreeBytes:numberFrom(e.LENSMCP_HEAP_SNAPSHOT_MIN_FREE_MB,1024,0)*MB,freeFactor:numberFrom(e.LENSMCP_HEAP_SNAPSHOT_FREE_FACTOR,3,0),keep:Math.max(1,Math.floor(numberFrom(e.LENSMCP_HEAP_SNAPSHOT_KEEP,3,1))),maxAgeMs:numberFrom(e.LENSMCP_HEAP_SNAPSHOT_MAX_AGE_H,24,0)*36e5}}p(heapSnapshotPolicy,"heapSnapshotPolicy"),i(heapSnapshotPolicy,"heapSnapshotPolicy");function availableSystemMemory(e=process.platform){try{if(e==="darwin"){const t=(0,node_child_process_1.spawnSync)("vm_stat",[],{encoding:"utf8",timeout:2e3}).stdout??"",o=Number(/page size of (\d+) bytes/.exec(t)?.[1]??4096),a=i(r=>Number(new RegExp(`Pages ${r}:\\s+(\\d+)`).exec(t)?.[1]??0),"pages"),n=a("free")+a("inactive")+a("speculative")+a("purgeable");if(n>0)return{bytes:n*o,source:"vm_stat free+inactive+speculative+purgeable"}}else if(e==="linux"){const t=/MemAvailable:\s+(\d+) kB/.exec(fs.readFileSync("/proc/meminfo","utf8"));if(t)return{bytes:Number(t[1])*1024,source:"/proc/meminfo MemAvailable"}}return{bytes:os.freemem(),source:"os.freemem()"}}catch{return}}p(availableSystemMemory,"availableSystemMemory"),i(availableSystemMemory,"availableSystemMemory");function heapSnapshotRefusal(e,t){if(t.live>e.maxHeapBytes)return`the pod's live heap is ${Math.round(t.live/MB)} MB, over the ${Math.round(e.maxHeapBytes/MB)} MB bound (LENSMCP_HEAP_SNAPSHOT_MAX_MB) \u2014 a snapshot this size needs several times that in memory while it is written`;if(t.available){const o=Math.max(e.minFreeBytes,e.freeFactor*t.live);if(t.available.bytes<o)return`only ${Math.round(t.available.bytes/MB)} MB of memory is available (${t.available.source}) and a snapshot of a ${Math.round(t.live/MB)} MB heap needs about ${Math.round(o/MB)} MB \u2014 free some memory first, or lower the floor with LENSMCP_HEAP_SNAPSHOT_MIN_FREE_MB / LENSMCP_HEAP_SNAPSHOT_FREE_FACTOR`}}p(heapSnapshotRefusal,"heapSnapshotRefusal"),i(heapSnapshotRefusal,"heapSnapshotRefusal");function heapSnapshotDir(e=process.env,t=process.cwd()){return e.LENSMCP_HEAP_DIR?path.resolve(e.LENSMCP_HEAP_DIR):e.LENSMCP_EVENT_FILE?path.join(path.dirname(path.resolve(e.LENSMCP_EVENT_FILE)),"heap"):path.join(t,".lensmcp","heap")}p(heapSnapshotDir,"heapSnapshotDir"),i(heapSnapshotDir,"heapSnapshotDir");function heapSnapshotFileName(e,t,o,a,n){const r=(e||"service").replace(/[^A-Za-z0-9_.-]/g,"_"),s=new Date(n).toISOString().replace(/[:.]/g,"-");return`${r}-pod${t}-pid${o}-g${a}-${s}.heapsnapshot`}p(heapSnapshotFileName,"heapSnapshotFileName"),i(heapSnapshotFileName,"heapSnapshotFileName");function ensureHeapDir(e){fs.mkdirSync(e,{recursive:!0,mode:448});const t=fs.lstatSync(e);if(!t.isDirectory())throw new Error(`${e} is not a directory`);(t.mode&63)!==0&&fs.chmodSync(e,448)}p(ensureHeapDir,"ensureHeapDir"),i(ensureHeapDir,"ensureHeapDir");function pruneHeapSnapshots(e,t,o=Date.now()){const a=[];let n;try{n=fs.readdirSync(e).filter(r=>r.endsWith(".heapsnapshot")).map(r=>{const s=path.join(e,r),u=fs.lstatSync(s);return u.isFile()?{file:s,mtime:u.mtimeMs}:void 0}).filter(r=>r!==void 0).sort((r,s)=>s.mtime-r.mtime)}catch{return a}return n.forEach((r,s)=>{if(s>=t.keep-1||o-r.mtime>t.maxAgeMs)try{fs.unlinkSync(r.file),a.push(r.file)}catch{}}),a}p(pruneHeapSnapshots,"pruneHeapSnapshots"),i(pruneHeapSnapshots,"pruneHeapSnapshots");function writeHeapSnapshot(e){const t=Date.now(),o=fs.constants.O_WRONLY|fs.constants.O_CREAT|fs.constants.O_EXCL|(fs.constants.O_NOFOLLOW??0),a=fs.openSync(e,o,384),n=new inspector.Session;let r=0,s;return new Promise((u,S)=>{const m=i(c=>{n.removeAllListeners("HeapProfiler.addHeapSnapshotChunk");try{n.disconnect()}catch{}try{fs.closeSync(a)}catch{}const l=c??s;if(l){try{fs.unlinkSync(e)}catch{}S(l);return}u({bytes:r,ms:Date.now()-t})},"finish");try{n.connect(),n.on("HeapProfiler.addHeapSnapshotChunk",c=>{if(!s)try{r+=fs.writeSync(a,c.params.chunk)}catch(l){s=l}}),n.post("HeapProfiler.takeHeapSnapshot",{reportProgress:!1},c=>m(c))}catch(c){m(c)}})}p(writeHeapSnapshot,"writeHeapSnapshot"),i(writeHeapSnapshot,"writeHeapSnapshot");
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Why a pod's heap grew by a whole bundle on every hot swap (issues/foodguard/24).
2
+ * Why a pod's heap grew by a whole bundle on every hot swap (issues/closed/foodguard-24).
3
3
  *
4
4
  * A swap re-requires the webpack bundle in the SAME process, so every decorated class is created again.
5
5
  * The old app is closed and its module graph should go with it — but a library loaded from node_modules
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The inspector credential, and where it may go (issues/closed/pod-memory-06).
3
+ *
4
+ * A Node inspector has no authentication: whoever holds its `ws://127.0.0.1:<port>/<uuid>` URL can run code in
5
+ * the pod as the developer. The UUID is the whole credential. It used to reach `.lensmcp/gateway.log` — mode
6
+ * 0644, readable by every account on the machine — three ways: the pod's own "Debugger listening on …" line
7
+ * (Node prints it to the pod's stderr, which the devserver relays), the devserver's echo of it, and the
8
+ * "Debugger ending on …" line at close. The gateway's stdout IS that file.
9
+ *
10
+ * So the URL is handed out on exactly one path, the owner-only control socket (`lensmcp debug <svc>`, and the
11
+ * owner's own `lensmcp logs`), and redacted everywhere it would land in a file. A terminal is the developer's own
12
+ * screen and keeps the attachable link — IDE run consoles make it a click-to-attach — unless what the devserver
13
+ * writes is going into a gateway's log.
14
+ *
15
+ * The inspector itself published the UUID too: `GET /json/list` on its port answers it to anyone who can
16
+ * connect, and an ephemeral loopback port is one `connect()` sweep away. `--inspect-publish-uid=stderr` turns
17
+ * every HTTP endpoint of the inspector off (`/json`, `/json/list`, `/json/version` all answer 404), leaving the
18
+ * URL to the process that opened it — which reports it to the devserver over IPC.
19
+ */
20
+ /** `text` with every inspector session UUID replaced — host and port kept, so the line still says where. */
21
+ export declare function redactInspectorUrls(text: string): string;
22
+ /** A stream this process writes, as far as the decision needs to know it. */
23
+ export interface StdioStream {
24
+ isTTY?: boolean;
25
+ }
26
+ /**
27
+ * May `stream` carry an attachable inspector URL? Only when it is a terminal AND this process is not writing into
28
+ * a gateway's log — a devserver the gateway started has its stdout piped to the gateway, whose own stdout is
29
+ * `.lensmcp/gateway.log` (`LENSMCP_GATEWAY_PID` marks one, main.devserver.ts `gatewayManaged`).
30
+ */
31
+ export declare function streamMayCarrySecrets(stream: StdioStream, underGateway: boolean): boolean;
32
+ /** What to write to `stream`: the text itself where it may carry the URL, redacted anywhere else. */
33
+ export declare function forStream(stream: StdioStream, underGateway: boolean, text: string): string;
34
+ /**
35
+ * The flag a pod or worker runs under so its inspector never answers the UUID over HTTP. Left off only under
36
+ * `LENSMCP_DEBUG_FIXED_PORTS` — the opt-in for an IDE that attaches by host:port, which it does by asking
37
+ * `/json/list` for the target. That opt-out already warns that its ports are reachable by every account.
38
+ */
39
+ export declare function inspectorPublishExecArgv(fixedPorts: boolean): string[];
@@ -0,0 +1 @@
1
+ "use strict";var n=Object.defineProperty;var s=(r,e)=>n(r,"name",{value:e,configurable:!0});var c=Object.defineProperty,t=s((r,e)=>c(r,"name",{value:e,configurable:!0}),"t");Object.defineProperty(exports,"__esModule",{value:!0}),exports.redactInspectorUrls=redactInspectorUrls,exports.streamMayCarrySecrets=streamMayCarrySecrets,exports.forStream=forStream,exports.inspectorPublishExecArgv=inspectorPublishExecArgv;const INSPECTOR_TOKEN_RE=/((?:wss?:\/\/[^\s/]+\/|ws=[^\s/]+\/))([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/gi;function redactInspectorUrls(r){return r.replace(INSPECTOR_TOKEN_RE,"$1<inspector-token-redacted>")}s(redactInspectorUrls,"redactInspectorUrls"),t(redactInspectorUrls,"redactInspectorUrls");function streamMayCarrySecrets(r,e){return!e&&r.isTTY===!0}s(streamMayCarrySecrets,"streamMayCarrySecrets"),t(streamMayCarrySecrets,"streamMayCarrySecrets");function forStream(r,e,a){return streamMayCarrySecrets(r,e)?a:redactInspectorUrls(a)}s(forStream,"forStream"),t(forStream,"forStream");function inspectorPublishExecArgv(r){return r?[]:["--inspect-publish-uid=stderr"]}s(inspectorPublishExecArgv,"inspectorPublishExecArgv"),t(inspectorPublishExecArgv,"inspectorPublishExecArgv");