wicked-crew 0.6.0 → 0.7.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 (99) hide show
  1. package/dist/api/audit.d.ts +13 -0
  2. package/dist/api/audit.d.ts.map +1 -1
  3. package/dist/api/audit.js +18 -2
  4. package/dist/api/audit.js.map +1 -1
  5. package/dist/api/guidance-index.d.ts +39 -0
  6. package/dist/api/guidance-index.d.ts.map +1 -0
  7. package/dist/api/guidance-index.js +67 -0
  8. package/dist/api/guidance-index.js.map +1 -0
  9. package/dist/api/open-path.d.ts +16 -0
  10. package/dist/api/open-path.d.ts.map +1 -1
  11. package/dist/api/open-path.js +22 -0
  12. package/dist/api/open-path.js.map +1 -1
  13. package/dist/api/retry-index.d.ts +30 -0
  14. package/dist/api/retry-index.d.ts.map +1 -0
  15. package/dist/api/retry-index.js +45 -0
  16. package/dist/api/retry-index.js.map +1 -0
  17. package/dist/api/routes.d.ts +53 -1
  18. package/dist/api/routes.d.ts.map +1 -1
  19. package/dist/api/routes.js +352 -23
  20. package/dist/api/routes.js.map +1 -1
  21. package/dist/api/run-files.d.ts +63 -0
  22. package/dist/api/run-files.d.ts.map +1 -0
  23. package/dist/api/run-files.js +271 -0
  24. package/dist/api/run-files.js.map +1 -0
  25. package/dist/api/server.d.ts +79 -0
  26. package/dist/api/server.d.ts.map +1 -1
  27. package/dist/api/server.js +135 -6
  28. package/dist/api/server.js.map +1 -1
  29. package/dist/api/stall-watchdog.d.ts +62 -0
  30. package/dist/api/stall-watchdog.d.ts.map +1 -0
  31. package/dist/api/stall-watchdog.js +138 -0
  32. package/dist/api/stall-watchdog.js.map +1 -0
  33. package/dist/cli/index.js +78 -13
  34. package/dist/cli/index.js.map +1 -1
  35. package/dist/core/adapter.d.ts +24 -10
  36. package/dist/core/adapter.d.ts.map +1 -1
  37. package/dist/core/adapter.js +191 -30
  38. package/dist/core/adapter.js.map +1 -1
  39. package/dist/core/bridge-reaper.d.ts +134 -0
  40. package/dist/core/bridge-reaper.d.ts.map +1 -0
  41. package/dist/core/bridge-reaper.js +286 -0
  42. package/dist/core/bridge-reaper.js.map +1 -0
  43. package/dist/core/deliver.d.ts +118 -0
  44. package/dist/core/deliver.d.ts.map +1 -0
  45. package/dist/core/deliver.js +241 -0
  46. package/dist/core/deliver.js.map +1 -0
  47. package/dist/core/deliverable-floor.d.ts +103 -0
  48. package/dist/core/deliverable-floor.d.ts.map +1 -0
  49. package/dist/core/deliverable-floor.js +173 -0
  50. package/dist/core/deliverable-floor.js.map +1 -0
  51. package/dist/core/exec.d.ts +2 -0
  52. package/dist/core/exec.d.ts.map +1 -1
  53. package/dist/core/exec.js.map +1 -1
  54. package/dist/core/types.d.ts +79 -1
  55. package/dist/core/types.d.ts.map +1 -1
  56. package/dist/core/types.js +3 -0
  57. package/dist/core/types.js.map +1 -1
  58. package/dist/interactive/bridge-pool.d.ts +28 -0
  59. package/dist/interactive/bridge-pool.d.ts.map +1 -1
  60. package/dist/interactive/bridge-pool.js +67 -10
  61. package/dist/interactive/bridge-pool.js.map +1 -1
  62. package/dist/interactive/chat-events.d.ts +207 -0
  63. package/dist/interactive/chat-events.d.ts.map +1 -0
  64. package/dist/interactive/chat-events.js +769 -0
  65. package/dist/interactive/chat-events.js.map +1 -0
  66. package/dist/interactive/demo-events.d.ts +283 -0
  67. package/dist/interactive/demo-events.d.ts.map +1 -0
  68. package/dist/interactive/demo-events.js +889 -0
  69. package/dist/interactive/demo-events.js.map +1 -0
  70. package/dist/interactive/draft-events.d.ts +87 -7
  71. package/dist/interactive/draft-events.d.ts.map +1 -1
  72. package/dist/interactive/draft-events.js +352 -49
  73. package/dist/interactive/draft-events.js.map +1 -1
  74. package/dist/interactive/edit-events.d.ts +22 -0
  75. package/dist/interactive/edit-events.d.ts.map +1 -1
  76. package/dist/interactive/edit-events.js +73 -2
  77. package/dist/interactive/edit-events.js.map +1 -1
  78. package/dist/interactive/repo-snapshot.d.ts +100 -0
  79. package/dist/interactive/repo-snapshot.d.ts.map +1 -0
  80. package/dist/interactive/repo-snapshot.js +289 -0
  81. package/dist/interactive/repo-snapshot.js.map +1 -0
  82. package/dist/projects/graph-paths.d.ts +92 -0
  83. package/dist/projects/graph-paths.d.ts.map +1 -0
  84. package/dist/projects/graph-paths.js +130 -0
  85. package/dist/projects/graph-paths.js.map +1 -0
  86. package/dist/projects/graph.d.ts +179 -0
  87. package/dist/projects/graph.d.ts.map +1 -0
  88. package/dist/projects/graph.js +775 -0
  89. package/dist/projects/graph.js.map +1 -0
  90. package/dist/projects/routes.d.ts +7 -0
  91. package/dist/projects/routes.d.ts.map +1 -1
  92. package/dist/projects/routes.js +122 -0
  93. package/dist/projects/routes.js.map +1 -1
  94. package/dist/studio/assets/index-8p8uwCxG.js +530 -0
  95. package/dist/studio/assets/index-D6S9zUtO.css +32 -0
  96. package/dist/studio/index.html +5 -3
  97. package/package.json +3 -3
  98. package/dist/studio/assets/index-CCwXa1cn.js +0 -428
  99. package/dist/studio/assets/index-HWxo0h41.css +0 -32
@@ -55,6 +55,84 @@ export interface LaunchRunInput {
55
55
  * fails the launch with no session persisted. Omit for runs that deliver inside their workdir.
56
56
  */
57
57
  extraWriteRoots?: string[];
58
+ /**
59
+ * The PROJECT's co-located code graph this run's governed workers should query instead of the
60
+ * run repo's own — resolved by `projects/graph.ts::resolveProjectGraphBinding`, which is the ONE
61
+ * thing that knows where a project graph lives and what each repo is labelled inside it.
62
+ *
63
+ * `repoLabel` is optional in the TYPE because a repo-LESS run legitimately has none — there is
64
+ * no own repo to name. It is not optional in MEANING for a repo-bound run: the engine uses it to
65
+ * confirm the co-located graph actually holds this run's repo.
66
+ *
67
+ * TypeScript cannot catch a missing label here — the invariant ties this field to `repoRef`, a
68
+ * sibling field — so `CoreAdapter.launchRun` enforces it at RUNTIME. Two failure modes, and they
69
+ * are NOT the same thing:
70
+ *
71
+ * - **crew refuses the launch outright.** Passing `projectGraph` without `projectId`, or with
72
+ * `repoRef` set and no `repoLabel`, THROWS: no session is created and nothing runs. These are
73
+ * caller bugs with no sensible degraded reading, so they fail before anything is persisted.
74
+ * - **the ENGINE declines the binding.** A well-formed binding whose graph turns out not to hold
75
+ * the named label is refused engine-side and the run proceeds against its own repo graph — a
76
+ * real launch, quietly narrower. That is the fallback; it is not what a missing `repoLabel`
77
+ * gets you.
78
+ *
79
+ * Omit the whole field for the per-repo behaviour.
80
+ */
81
+ projectGraph?: {
82
+ dbPath: string;
83
+ repoLabel?: string;
84
+ };
85
+ /**
86
+ * Delivery mode (crew#293). `"pr"` ⇒ the adapter appends the hardened deliver Tool phase
87
+ * (push the run branch + `gh pr create`, see `core/deliver.ts`) to a PER-RUN copy of the
88
+ * selected workflow def and launches that copy — the shared def is never mutated. Requires
89
+ * `workflow`; a free-text run has no def to append to. Omit ⇒ no delivery phase (default).
90
+ */
91
+ deliver?: 'pr';
92
+ /**
93
+ * THE DELIVERABLE FLOOR (crew#311) — absolute paths this run MUST have produced by the time
94
+ * it finishes. When non-empty (and `workflow` is set), the adapter appends a deterministic
95
+ * verification Tool phase to a PER-RUN copy of the def (see `core/deliverable-floor.ts`)
96
+ * which re-derives "done" from the artifacts: every declared path must exist and carry bytes,
97
+ * or the phase exits non-zero and the RUN FAILS, naming what was expected and what was found.
98
+ *
99
+ * This is the instrument for runs whose deliverable is a FILE in a declared write root rather
100
+ * than a worktree diff — every crew interactive seam. The engine's own two floors do not
101
+ * reach them: the built-in evidence floor re-verifies a git diff and is fail-closed on a
102
+ * repo-less run, and `required_deliverables` is checked only by the wrapped-CLI runner and
103
+ * only against the unit's cwd (an absolute path counts as missing there by construction).
104
+ *
105
+ * Omit for runs whose evidence is the worktree diff — those are the engine's to floor.
106
+ */
107
+ requireDeliverables?: string[];
108
+ }
109
+ /** Default `workerStallMinutes` (crew#287): silent minutes before the stall watchdog fires. */
110
+ export declare const DEFAULT_WORKER_STALL_MINUTES = 15;
111
+ /**
112
+ * LOCAL extension of the published `SystemSettings` (wicked-crew-api-types 0.6.0): the crew#287
113
+ * stall-watchdog knob is daemon-owned until the contract picks it up. NOTE for the next
114
+ * api-types release: fold `workerStallMinutes` into `SystemSettings` (and the synthetic
115
+ * `workerStalled` /ws frame — see `api/stall-watchdog.ts` `WorkerStalledFrame` — into the
116
+ * event documentation). Extra fields are forward-additive on the wire (DES-STUDIO-001 §5.1),
117
+ * so shipping it daemon-side first breaks no consumer.
118
+ */
119
+ export interface CrewSystemSettings extends SystemSettings {
120
+ /**
121
+ * Minutes a run in `executing` may go without ANY engine event on the daemon's relay before
122
+ * a synthetic `workerStalled` frame is broadcast on /ws (detection only; default 15).
123
+ */
124
+ workerStallMinutes?: number;
125
+ /**
126
+ * Skin-owned preference blobs, round-tripped verbatim (crew#323). RESTATED here rather than
127
+ * merely inherited from `SystemSettings` so the daemon's own type SAYS the settings store is
128
+ * shared with the experience plane — the fact that used to live only in a comment in the
129
+ * studio's client, which is how `studio.appearance` / `studio.notifications` could be
130
+ * silently dropped by `PUT /settings` without either side's types objecting.
131
+ *
132
+ * The daemon never interprets a value here; it enforces only "JSON-serializable, under the
133
+ * per-key byte cap" at the PUT boundary (`api/routes.ts` `STUDIO_SETTINGS_MAX_BYTES`).
134
+ */
135
+ [key: `studio.${string}`]: unknown;
58
136
  }
59
- export declare const DEFAULT_SETTINGS: SystemSettings;
137
+ export declare const DEFAULT_SETTINGS: CrewSystemSettings;
60
138
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,mBAAmB,uBAAuB,CAAC;AAE3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,2EAA2E;AAC3E,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,8FAA8F;AAC9F,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sFAAsF;IACtF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,eAAO,MAAM,gBAAgB,EAAE,cAE9B,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,mBAAmB,uBAAuB,CAAC;AAE3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,2EAA2E;AAC3E,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,8FAA8F;AAC9F,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sFAAsF;IACtF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,YAAY,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD;;;;;OAKG;IACH,OAAO,CAAC,EAAE,IAAI,CAAC;IACf;;;;;;;;;;;;;;OAcG;IACH,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC;AAED,+FAA+F;AAC/F,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAE/C;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAmB,SAAQ,cAAc;IACxD;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;;;;;OASG;IACH,CAAC,GAAG,EAAE,UAAU,MAAM,EAAE,GAAG,OAAO,CAAC;CACpC;AAED,eAAO,MAAM,gBAAgB,EAAE,kBAG9B,CAAC"}
@@ -18,7 +18,10 @@
18
18
  * daemon speaks these daemon-owned shapes, which is what quarantines the
19
19
  * FINALIZING core-ts `subscribe` seam to a single file (DES-STUDIO-001 §5.2).
20
20
  */
21
+ /** Default `workerStallMinutes` (crew#287): silent minutes before the stall watchdog fires. */
22
+ export const DEFAULT_WORKER_STALL_MINUTES = 15;
21
23
  export const DEFAULT_SETTINGS = {
22
24
  graphNodeLimit: 150,
25
+ workerStallMinutes: DEFAULT_WORKER_STALL_MINUTES,
23
26
  };
24
27
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AA4CH,MAAM,CAAC,MAAM,gBAAgB,GAAmB;IAC9C,cAAc,EAAE,GAAG;CACpB,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AA2FH,+FAA+F;AAC/F,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,CAAC;AA6B/C,MAAM,CAAC,MAAM,gBAAgB,GAAuB;IAClD,cAAc,EAAE,GAAG;IACnB,kBAAkB,EAAE,4BAA4B;CACjD,CAAC"}
@@ -19,8 +19,14 @@
19
19
  * live pid earns three 1.5 s attempts before the bridge is declared dead. Identity is checked
20
20
  * too: `/api/health` must report THIS root, or a recycled port belonging to some other service
21
21
  * would be proxied as if it were ours.
22
+ *
23
+ * On start/adopt the pool also records the daemon's own origin with the bridge (crew#298,
24
+ * `POST /api/studio-origin`, interactive ≥ 0.8.0) so the bridge's `GET /` redirects a direct
25
+ * visitor into studio instead of its API-only fallback page. Fire-and-forget, once per pooled
26
+ * bridge: recording can never fail — or slow down — a proxied request.
22
27
  */
23
28
  import { type ChildProcess } from 'node:child_process';
29
+ import type { AddressInfo } from 'node:net';
24
30
  export declare const LOCK_NAME = ".wi-serve.json";
25
31
  /** ADR-0025: 1.5 s × 3 while the pid lives. */
26
32
  export declare const HEALTH_TIMEOUT_MS = 1500;
@@ -45,7 +51,21 @@ export interface BridgePoolIo {
45
51
  startTimeoutMs?: number;
46
52
  healthTimeoutMs?: number;
47
53
  log?: (msg: string) => void;
54
+ /** Lower-severity channel for EXPECTED skips (a pre-0.8.0 bridge without the endpoint, #298). */
55
+ debug?: (msg: string) => void;
56
+ /**
57
+ * The daemon's own origin (`http://<bound host>:<bound port>`), resolved LAZILY — the pool is
58
+ * built before `listen`, but only consulted while serving a request, i.e. after the address is
59
+ * bound. Null (or absent) means "nothing to record" and the pool never POSTs (#298).
60
+ */
61
+ studioOrigin?: () => string | null;
48
62
  }
63
+ /**
64
+ * The daemon's own http origin from its bound server address, or null before `listen`. Wildcard
65
+ * binds (`0.0.0.0` / `::`) are not dialable from a browser, so they normalize to loopback — the
66
+ * bridge is local-only anyway, so whoever hits its port can reach the daemon at 127.0.0.1 too.
67
+ */
68
+ export declare function boundOrigin(addr: AddressInfo | string | null): string | null;
49
69
  /** `<root>/.wi-serve.json`, or null when absent/unparseable/incomplete. */
50
70
  export declare function readLock(root: string): LiveBridge | null;
51
71
  /** Signal 0 probes existence without delivering: EPERM means alive-but-not-ours. */
@@ -64,6 +84,14 @@ export declare class InteractiveBridgePool {
64
84
  /** Live bridges, for tests and future operator introspection. */
65
85
  keys(): string[];
66
86
  private resolveOrStart;
87
+ /**
88
+ * POST the daemon's own origin to the bridge's `/api/studio-origin` (#298), so the bridge's
89
+ * `GET /` redirects a direct visitor into studio instead of the API-only fallback page.
90
+ * At most one attempt per pooled bridge per process; 404/405 means the bridge predates the
91
+ * endpoint (interactive < 0.8.0) and is an expected skip, any other failure is a warn — never
92
+ * an error, because origin recording must never fail a proxy request.
93
+ */
94
+ private recordStudioOrigin;
67
95
  /** The lockfile points at a bridge that is alive, answering, and serving THIS root. */
68
96
  private healthy;
69
97
  private start;
@@ -1 +1 @@
1
- {"version":3,"file":"bridge-pool.d.ts","sourceRoot":"","sources":["../../src/interactive/bridge-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAI3E,eAAO,MAAM,SAAS,mBAAmB,CAAC;AAC1C,+CAA+C;AAC/C,eAAO,MAAM,iBAAiB,OAAO,CAAC;AACtC,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,6FAA6F;AAC7F,eAAO,MAAM,gBAAgB,QAAS,CAAC;AAEvC,yDAAyD;AACzD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,sFAAsF;AACtF,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,qFAAqF;IACrF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBACV,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAK1C;AAOD,gGAAgG;AAChG,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,YAAY,CAAC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAQxD;AAED,oFAAoF;AACpF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQ7C;AAkBD,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAe;IAClC,oGAAoG;IACpG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiC;IACtD,6FAA6F;IAC7F,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0C;gBAEvD,EAAE,GAAE,YAAiB;IAIjC,qGAAqG;IAC/F,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAc/C,uFAAuF;IACvF,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI9B,iEAAiE;IACjE,IAAI,IAAI,MAAM,EAAE;YAIF,cAAc;IAW5B,uFAAuF;YACzE,OAAO;YAeP,KAAK;CAsCpB"}
1
+ {"version":3,"file":"bridge-pool.d.ts","sourceRoot":"","sources":["../../src/interactive/bridge-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAG5C,eAAO,MAAM,SAAS,mBAAmB,CAAC;AAC1C,+CAA+C;AAC/C,eAAO,MAAM,iBAAiB,OAAO,CAAC;AACtC,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,6FAA6F;AAC7F,eAAO,MAAM,gBAAgB,QAAS,CAAC;AAEvC,yDAAyD;AACzD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,sFAAsF;AACtF,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,qFAAqF;IACrF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBACV,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAK1C;AAOD,gGAAgG;AAChG,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,YAAY,CAAC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,iGAAiG;IACjG,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CACpC;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAS5E;AAED,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAQxD;AAED,oFAAoF;AACpF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQ7C;AAyBD,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAe;IAClC,oGAAoG;IACpG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmC;IACxD,6FAA6F;IAC7F,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0C;gBAEvD,EAAE,GAAE,YAAiB;IAIjC,qGAAqG;IAC/F,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAc/C,uFAAuF;IACvF,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI9B,iEAAiE;IACjE,IAAI,IAAI,MAAM,EAAE;YAIF,cAAc;IAW5B;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IA+B1B,uFAAuF;YACzE,OAAO;YAeP,KAAK;CAsCpB"}
@@ -19,6 +19,11 @@
19
19
  * live pid earns three 1.5 s attempts before the bridge is declared dead. Identity is checked
20
20
  * too: `/api/health` must report THIS root, or a recycled port belonging to some other service
21
21
  * would be proxied as if it were ours.
22
+ *
23
+ * On start/adopt the pool also records the daemon's own origin with the bridge (crew#298,
24
+ * `POST /api/studio-origin`, interactive ≥ 0.8.0) so the bridge's `GET /` redirects a direct
25
+ * visitor into studio instead of its API-only fallback page. Fire-and-forget, once per pooled
26
+ * bridge: recording can never fail — or slow down — a proxied request.
22
27
  */
23
28
  import { spawn as nodeSpawn } from 'node:child_process';
24
29
  import { mkdirSync, readFileSync } from 'node:fs';
@@ -43,6 +48,21 @@ export class BridgeUnavailableError extends Error {
43
48
  function serveCommand(root) {
44
49
  return `npx wicked-interactive serve --root ${root}`;
45
50
  }
51
+ /**
52
+ * The daemon's own http origin from its bound server address, or null before `listen`. Wildcard
53
+ * binds (`0.0.0.0` / `::`) are not dialable from a browser, so they normalize to loopback — the
54
+ * bridge is local-only anyway, so whoever hits its port can reach the daemon at 127.0.0.1 too.
55
+ */
56
+ export function boundOrigin(addr) {
57
+ if (addr === null || typeof addr === 'string')
58
+ return null;
59
+ const host = addr.address === '' || addr.address === '0.0.0.0' || addr.address === '::'
60
+ ? '127.0.0.1'
61
+ : addr.address.includes(':')
62
+ ? `[${addr.address}]`
63
+ : addr.address;
64
+ return `http://${host}:${addr.port}`;
65
+ }
46
66
  /** `<root>/.wi-serve.json`, or null when absent/unparseable/incomplete. */
47
67
  export function readLock(root) {
48
68
  try {
@@ -97,8 +117,8 @@ export class InteractiveBridgePool {
97
117
  // Fast path: we started/adopted it and its pid is still alive. A full health round-trip on
98
118
  // every proxied request would put a 1.5 s timeout budget in front of every asset fetch.
99
119
  const cached = this.live.get(root);
100
- if (cached && pidAlive(cached.pid))
101
- return cached;
120
+ if (cached && pidAlive(cached.bridge.pid))
121
+ return cached.bridge;
102
122
  this.live.delete(root);
103
123
  const pending = this.inflight.get(root);
104
124
  if (pending)
@@ -116,14 +136,51 @@ export class InteractiveBridgePool {
116
136
  return [...this.live.keys()];
117
137
  }
118
138
  async resolveOrStart(root) {
119
- const adopted = await this.healthy(root);
120
- if (adopted) {
121
- this.live.set(root, adopted);
122
- return adopted;
123
- }
124
- const started = await this.start(root);
125
- this.live.set(root, started);
126
- return started;
139
+ // Adopt-or-start; either way the bridge just answered `/api/health` for this root, which is
140
+ // exactly the moment #298 wants the studio origin recorded — fire-and-forget, so recording
141
+ // can never delay (let alone fail) the proxied request that triggered the resolution.
142
+ const bridge = (await this.healthy(root)) ?? (await this.start(root));
143
+ const entry = { bridge, originRecorded: false };
144
+ this.live.set(root, entry);
145
+ this.recordStudioOrigin(entry);
146
+ return bridge;
147
+ }
148
+ /**
149
+ * POST the daemon's own origin to the bridge's `/api/studio-origin` (#298), so the bridge's
150
+ * `GET /` redirects a direct visitor into studio instead of the API-only fallback page.
151
+ * At most one attempt per pooled bridge per process; 404/405 means the bridge predates the
152
+ * endpoint (interactive < 0.8.0) and is an expected skip, any other failure is a warn — never
153
+ * an error, because origin recording must never fail a proxy request.
154
+ */
155
+ recordStudioOrigin(entry) {
156
+ if (entry.originRecorded)
157
+ return;
158
+ entry.originRecorded = true;
159
+ const origin = this.io.studioOrigin?.() ?? null;
160
+ if (origin === null)
161
+ return; // no origin to record (pool not bootstrapped from a listening daemon)
162
+ const { host, port } = entry.bridge;
163
+ const timeout = this.io.healthTimeoutMs ?? HEALTH_TIMEOUT_MS;
164
+ void (async () => {
165
+ try {
166
+ const res = await fetch(`http://${host}:${port}/api/studio-origin`, {
167
+ method: 'POST',
168
+ headers: { 'content-type': 'application/json' },
169
+ body: JSON.stringify({ origin }),
170
+ signal: AbortSignal.timeout(timeout),
171
+ });
172
+ await res.arrayBuffer().catch(() => undefined); // drain, so the connection is released
173
+ if (res.status === 404 || res.status === 405) {
174
+ this.io.debug?.(`bridge at ${host}:${port} has no /api/studio-origin (interactive < 0.8.0) — skipping origin record`);
175
+ }
176
+ else if (!res.ok) {
177
+ this.io.log?.(`recording studio origin ${origin} with the bridge at ${host}:${port} failed: HTTP ${res.status}`);
178
+ }
179
+ }
180
+ catch (err) {
181
+ this.io.log?.(`recording studio origin ${origin} with the bridge at ${host}:${port} failed: ${err.message}`);
182
+ }
183
+ })();
127
184
  }
128
185
  /** The lockfile points at a bridge that is alive, answering, and serving THIS root. */
129
186
  async healthy(root) {
@@ -1 +1 @@
1
- {"version":3,"file":"bridge-pool.js","sourceRoot":"","sources":["../../src/interactive/bridge-pool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bridge-pool.js","sourceRoot":"","sources":["../../src/interactive/bridge-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,KAAK,IAAI,SAAS,EAAqB,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAElD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,CAAC,MAAM,SAAS,GAAG,gBAAgB,CAAC;AAC1C,+CAA+C;AAC/C,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AACtC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC;AACjC,6FAA6F;AAC7F,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AASvC,sFAAsF;AACtF,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAC/C,qFAAqF;IAC5E,IAAI,CAAS;IACtB,YAAY,OAAe,EAAE,IAAY;QACvC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,iGAAiG;AACjG,SAAS,YAAY,CAAC,IAAY;IAChC,OAAO,uCAAuC,IAAI,EAAE,CAAC;AACvD,CAAC;AAkBD;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,IAAiC;IAC3D,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3D,MAAM,IAAI,GACR,IAAI,CAAC,OAAO,KAAK,EAAE,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI;QACxE,CAAC,CAAC,WAAW;QACb,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;YAC1B,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,GAAG;YACrB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;IACrB,OAAO,UAAU,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;AACvC,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,CAAwB,CAAC;QAC3F,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC7E,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC;IAC1H,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACrD,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAQ,GAA6B,CAAC,IAAI,KAAK,OAAO,CAAC;IACzD,CAAC;AACH,CAAC;AAED,gGAAgG;AAChG,KAAK,UAAU,cAAc,CAAC,MAAkB,EAAE,SAAiB;IACjE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,UAAU,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,aAAa,EAAE;YACzE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC;SACvC,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QACzB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAuB,CAAC;QACtD,OAAO,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,KAAK,GAAG,CAAC,EAAU,EAAiB,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AASnF,MAAM,OAAO,qBAAqB;IACf,EAAE,CAAe;IAClC,oGAAoG;IACnF,IAAI,GAAG,IAAI,GAAG,EAAwB,CAAC;IACxD,6FAA6F;IAC5E,QAAQ,GAAG,IAAI,GAAG,EAA+B,CAAC;IAEnE,YAAY,KAAmB,EAAE;QAC/B,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACf,CAAC;IAED,qGAAqG;IACrG,KAAK,CAAC,MAAM,CAAC,IAAY;QACvB,2FAA2F;QAC3F,wFAAwF;QACxF,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;YAAE,OAAO,MAAM,CAAC,MAAM,CAAC;QAChE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAEvB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;QAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QACpF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACjC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,uFAAuF;IACvF,UAAU,CAAC,IAAY;QACrB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAED,iEAAiE;IACjE,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/B,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,IAAY;QACvC,4FAA4F;QAC5F,2FAA2F;QAC3F,sFAAsF;QACtF,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACtE,MAAM,KAAK,GAAiB,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;QAC9D,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC3B,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAC/B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;OAMG;IACK,kBAAkB,CAAC,KAAmB;QAC5C,IAAI,KAAK,CAAC,cAAc;YAAE,OAAO;QACjC,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC;QAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE,IAAI,IAAI,CAAC;QAChD,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,CAAC,sEAAsE;QACnG,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,eAAe,IAAI,iBAAiB,CAAC;QAC7D,KAAK,CAAC,KAAK,IAAI,EAAE;YACf,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,UAAU,IAAI,IAAI,IAAI,oBAAoB,EAAE;oBAClE,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;oBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;oBAChC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC;iBACrC,CAAC,CAAC;gBACH,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,uCAAuC;gBACvF,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;oBAC7C,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CACb,aAAa,IAAI,IAAI,IAAI,2EAA2E,CACrG,CAAC;gBACJ,CAAC;qBAAM,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;oBACnB,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,2BAA2B,MAAM,uBAAuB,IAAI,IAAI,IAAI,iBAAiB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;gBACnH,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CACX,2BAA2B,MAAM,uBAAuB,IAAI,IAAI,IAAI,YAAa,GAAa,CAAC,OAAO,EAAE,CACzG,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;IACP,CAAC;IAED,uFAAuF;IAC/E,KAAK,CAAC,OAAO,CAAC,IAAY;QAChC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QACtD,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,eAAe,IAAI,iBAAiB,CAAC;QAC7D,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,eAAe,EAAE,OAAO,EAAE,EAAE,CAAC;YAC3D,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACrD,IAAI,QAAQ,KAAK,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC;YACjE,yFAAyF;YACzF,8EAA8E;YAC9E,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC;YACrC,IAAI,OAAO,GAAG,eAAe,GAAG,CAAC;gBAAE,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,KAAK,CAAC,KAAK,CAAC,IAAY;QAC9B,IAAI,CAAC;YACH,sFAAsF;YACtF,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,sBAAsB,CAC9B,oBAAoB,IAAI,mBAAoB,GAAa,CAAC,OAAO,EAAE,EACnE,4CAA4C,IAAI,OAAO,YAAY,CAAC,IAAI,CAAC,EAAE,CAC5E,CAAC;QACJ,CAAC;QAED,IAAI,YAAY,GAAkB,IAAI,CAAC;QACvC,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC;QACpD,0FAA0F;QAC1F,wFAAwF;QACxF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACxB,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QAEhB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,cAAc,IAAI,gBAAgB,CAAC,CAAC;QAC3E,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;YAC7B,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;gBAC1B,MAAM,IAAI,sBAAsB,CAC9B,6CAA6C,IAAI,KAAK,YAAY,EAAE,EACpE,qDAAqD,YAAY,CAAC,IAAI,CAAC,EAAE,CAC1E,CAAC;YACJ,CAAC;YACD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACzC,IAAI,OAAO;gBAAE,OAAO,OAAO,CAAC;YAC5B,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;QACD,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,0BAA0B,IAAI,0CAA0C,CAAC,CAAC;QACxF,MAAM,IAAI,sBAAsB,CAC9B,8BAA8B,IAAI,iCAAiC,EACnE,SAAS,YAAY,CAAC,IAAI,CAAC,iDAAiD,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,GAAG,CAC3G,CAAC;IACJ,CAAC;CACF;AAED,4FAA4F;AAC5F,SAAS,YAAY,CAAC,IAAY;IAChC,2FAA2F;IAC3F,yFAAyF;IACzF,OAAO,SAAS,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE;QAChF,GAAG,EAAE,IAAI;QACT,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,QAAQ;KAChB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Opt-in governed answering of wicked-interactive's conversational ITERATION asks (CREW-UX-5 —
3
+ * the third interactive leg, beside draft-events.ts and edit-events.ts).
4
+ *
5
+ * A finished doc's thread send in wicked-studio does `postFork` (mints a version) and injects
6
+ * `wicked.interactive.chat.posted` — and NOTHING consumed that topic since the ad-hoc assist
7
+ * agent retired: crew answers `doc.created` (the first draft) and `feedback.processed` (the
8
+ * structural handoff), but the plain conversational ask ("make the intro punchier") had no
9
+ * answerer, so BRIEF-UX-001 J3's "iterate twice" was impossible. This module makes a
10
+ * crew-governed run the answerer: understand-the-ask → revise, announced back on the SAME
11
+ * `draft.completed` wire the first draft rides — the service lands the revised full HTML as a
12
+ * generated version (`materializeDraft` → `applyGeneratedHtml`), which is exactly what an
13
+ * iteration is.
14
+ *
15
+ * Shape mirrors draft-events.ts (dynamic wicked-bus import, graceful degradation, durable
16
+ * cursor `cursor_init: 'latest'` under a dedicated plugin name, durable replay-dedup ledger,
17
+ * `wi-crew` narration via status.posted). The chat-specific deltas:
18
+ *
19
+ * - THE TRIGGER IS A CONVERSATION LINE, so the actionable filter is layered (the contract):
20
+ * (a) `role: "user"` only — agent narration echoes also ride chat.posted;
21
+ * (b) the doc must EXIST under the resolved docs root and not belong to a foreign loop —
22
+ * and the disk truth here is subtle: interactive's `initManifest` only ever RECORDS a
23
+ * `kind` for demo docs (a real `kind: "source"` doc's versions.json carries NO kind
24
+ * field at all — the "source" spelling rides the doc.created EVENT only; verified
25
+ * against interactive 0.8.0 and main, src/service/server.js `initWorkspace(dir, html)`).
26
+ * So the gate accepts `source` (future manifests may record it) and the absent-default
27
+ * `doc`, and rejects explicit foreign kinds (`demo`) — a doc we cannot see is not ours
28
+ * to answer either;
29
+ * (c) per-doc serialization — an ask on a doc whose draft/edit/chat run is still in flight
30
+ * is QUEUED (FIFO per doc), never raced: two concurrent revisions of one doc would
31
+ * land as two forks of the same parent and the second would silently drop the first;
32
+ * (d) the text must be an ASK, not an echo of a machine-composed message — the feedback
33
+ * overlay injects its batch as a chat.posted TOO (same `source_message_id` as its
34
+ * `feedback.submitted`), and that batch is already the edit seam's business.
35
+ * - VERSION SNAPSHOT AT LAUNCH: the seam copies the doc's CURRENT HEAD html into the chat
36
+ * inbox and names the COPY in the task, so (1) the worker never needs read access to the
37
+ * doc workspace (the one declared write root covers input + deliverable — crew#263 /
38
+ * wicked-core#259: write roots are readable) and (2) a queued second ask snapshots the
39
+ * head AFTER the first revision landed — which is what "iterate twice" means.
40
+ * - THE LANDING GATE: `draft.completed` is announced by path and the service lands the new
41
+ * version ASYNCHRONOUSLY. A queued ask drained the instant our run completes would snapshot
42
+ * the stale head and silently drop the revision the user just watched land. So a successful
43
+ * completion arms a per-doc gate — drain only once the manifest head ADVANCES past the head
44
+ * we launched from, or a timeout passes (the service may be down; waiting forever would
45
+ * strand the queue).
46
+ * - IDEMPOTENCY KEYING: one doc legitimately produces many asks over its life, so the dedupe
47
+ * unit is the ASK — `source_message_id` when the frame carries one (the studio reuses the
48
+ * SAME message id on a user-driven resend, so a retry that reached the bus twice dedupes),
49
+ * else the bus `event_id` (pure redelivery). Never the doc lifetime.
50
+ */
51
+ import { InteractiveHandoffLedger } from './ledger.js';
52
+ import type { CoreAdapter } from '../core/adapter.js';
53
+ import type { WorkflowDef } from '../core/types.js';
54
+ export declare const CHAT_POSTED = "wicked.interactive.chat.posted";
55
+ /** Exact-type filter with a domain guard — no wildcard, one event type is the whole trigger. */
56
+ export declare const INTERACTIVE_CHAT_BUS_FILTER = "wicked.interactive.chat.posted@wicked-interactive";
57
+ /** Dedicated durable-cursor identity — NOT the draft/edit seams', so the three interactive
58
+ * seams advance independent cursors and stopping one never strands another. */
59
+ export declare const INTERACTIVE_CHAT_BUS_PLUGIN = "wicked-crew-interactive-chat";
60
+ export declare const INTERACTIVE_CHAT_WORKFLOW = "interactive-chat";
61
+ /**
62
+ * The governed workflow that fulfils an iteration ask. Two agent phases — understand (recon)
63
+ * then revise (build, creator role) — the draft leg's sibling: the reviser builds on a stated
64
+ * plan instead of one-shotting a rewrite, and the run narrates a real phase transition.
65
+ *
66
+ * The phase `instructions` carry the ITERATION contract: start from the CURRENT document (the
67
+ * snapshot path named in the task), change only what the ask touches, KEEP every existing
68
+ * `data-wid` on kept elements (interactive's instrument pass preserves pre-existing anchors —
69
+ * INV-1 — so feedback deep-links survive the iteration) and mint none on added ones. They are
70
+ * SINGLE-LINE by contract (PTY seat runner, wicked-core FINDING-011).
71
+ *
72
+ * All gates are `auto` with `validator_pin: null` — same rationale as the draft leg: the
73
+ * acceptance gate for a revision is interactive's instrument+theme pipeline and the user's own
74
+ * eyes on the canvas.
75
+ */
76
+ export declare const INTERACTIVE_CHAT_WORKFLOW_DEF: WorkflowDef;
77
+ /** The chat-posted fields this seam acts on. */
78
+ export interface ChatAsk {
79
+ documentId: string;
80
+ /** The user's ask, verbatim (flattened later — the problem statement is single-line). */
81
+ text: string;
82
+ /** The thread message behind the ask (studio inject wire, §7.7). The studio REUSES the same
83
+ * id on a user-driven resend, so this is the dedupe unit when present. */
84
+ sourceMessageId?: string;
85
+ /** Present when the doc is project-bound (interactive's DES-PROJECT-001 enrichment). */
86
+ projectId?: string;
87
+ }
88
+ /**
89
+ * Parse a bus frame into a {@link ChatAsk}, or `null` when it is not an actionable ask:
90
+ * wrong type, malformed payload, non-`user` role (contract (a) — agent narration and any
91
+ * transcript echo ride the same topic), slug-invalid document_id, or empty text. Kind and
92
+ * existence checks (contract (b)) happen against the filesystem, not the payload — the frame
93
+ * does not carry `kind`.
94
+ */
95
+ export declare function parseChatPosted(eventType: string, payload: unknown): ChatAsk | null;
96
+ /** Contract (d): `true` when the text is a conversational ask this seam should answer —
97
+ * not the feedback overlay's batch echo (already answered elsewhere). */
98
+ export declare function isIterationAsk(text: string): boolean;
99
+ /** The one dedupe unit of this seam: the ASK — the studio's message id when the frame carries
100
+ * one (a resend reuses it), else the bus event id (pure redelivery). Never the doc lifetime. */
101
+ export declare function chatKey(documentId: string, eventId: number, sourceMessageId?: string): string;
102
+ /** Deterministic bus idempotency key for the one revision this seam may land per ask. */
103
+ export declare function chatIdempotencyKey(documentId: string, eventId: number, sourceMessageId?: string): string;
104
+ /** What the versions.json read yields — enough to gate (kind) and snapshot (head html path). */
105
+ export interface DocHead {
106
+ kind: string;
107
+ head: number;
108
+ /** Absolute path of the head version's html artifact. */
109
+ headHtmlPath: string;
110
+ }
111
+ /**
112
+ * Read a doc workspace's manifest (interactive's `versions.json`, fsstore.js shape) and resolve
113
+ * its head html path. `null` when the doc does not exist under this root or the manifest is
114
+ * unreadable — not ours to answer, per contract (b). Follows interactive's own tolerant read:
115
+ * `kind` defaults to `"doc"` when absent (listDocs does the same) — and ABSENT is what a real
116
+ * source doc looks like on disk (interactive records kind only for demo docs), so the caller
117
+ * gates through {@link isAnswerableDocKind}, never a `=== 'source'` comparison.
118
+ */
119
+ export declare function readDocHead(docsRoot: string, documentId: string): DocHead | null;
120
+ /**
121
+ * Contract (b)'s kind half: `true` when a doc of this manifest kind is this seam's to answer.
122
+ * `source` is the spec's spelling (recorded by no released interactive yet, accepted for the
123
+ * day a manifest carries it); `doc` is the absent-default every REAL source (and plain html)
124
+ * doc reads as — interactive's initManifest keeps non-demo kinds implicit. Explicit foreign
125
+ * kinds (`demo`, anything future) belong to their own loops.
126
+ */
127
+ export declare function isAnswerableDocKind(kind: string): boolean;
128
+ /**
129
+ * The run's problem statement (the engine scopes it per phase and folds each phase's
130
+ * instructions on top). Carries everything ask-specific: identity, the flattened ask, the
131
+ * CURRENT-version snapshot to read, and the absolute path the revised HTML must land at.
132
+ *
133
+ * CREW-UX-8 SPLIT — the revision leg carries NO repo grounding, deliberately. The draft leg
134
+ * (draft-events.ts) grounds its v1 in a launch-scoped repo snapshot and that shape is proven
135
+ * live; the SAME shape on the revise turn wedged 2/2 on the real engine (crew#288 comment —
136
+ * the repo-grounded revise turn hits the known second-turn wedge), while UNGROUNDED revisions
137
+ * are proven to land (the CREW-UX-5 verification). So bound asks launch exactly like unfiled
138
+ * ones — head-copy in the external inbox, one write root, no repoRef (wicked-core#293), no
139
+ * live-repo path in the task (wicked-core#294). Revision grounding returns when either of
140
+ * those is fixed.
141
+ */
142
+ export declare function chatProblem(ask: ChatAsk, currentPath: string, outPath: string): string;
143
+ /** Options for {@link startInteractiveChatSubscriber}. */
144
+ export interface InteractiveChatOptions {
145
+ /** Bus SQLite db path. Omit to let wicked-bus resolve its own default
146
+ * (honors `WICKED_BUS_DATA_DIR`) — where interactive's service emits unless redirected. */
147
+ dbPath?: string;
148
+ /** Poll cadence, ms (default 2000; tests shorten it). */
149
+ pollIntervalMs?: number;
150
+ /** Heartbeat narration cadence while a run is in flight, ms (default 15000 — inside the
151
+ * UI's ~20s `status.requested` window so the canvas never reads frozen; the studio's own
152
+ * 90s silence budget makes the FIRST pickup narration the load-bearing one). */
153
+ heartbeatMs?: number;
154
+ /** Ledger file (default `~/.wicked-crew/interactive-chat-ledger.json`). */
155
+ ledgerPath?: string;
156
+ /** Root under which each ask gets its own per-run subdirectory (`<chatDir>/<safeKey>/`)
157
+ * holding the head snapshot and the revised deliverable; only that subdirectory is declared
158
+ * as the run's extra write root (per-run isolation — Copilot, crew#313: declaring the shared
159
+ * dir wholesale let one doc's worker read every other doc's head and revision).
160
+ * Default `~/.wicked-crew/interactive-chats`. */
161
+ chatDir?: string;
162
+ /** Seat roster JSON for the governed run (default: the production council roster).
163
+ * The functional-test harness passes a deterministic stub seat here. */
164
+ clisJson?: string;
165
+ /** The docs root an ask's doc is read from. Default: the shared-default resolution
166
+ * (`WICKED_INTERACTIVE_ROOT` › `~/wicked-interactive/docs`); the server wires the
167
+ * per-project `interactiveRoot` setting through here so a project on its own root
168
+ * resolves correctly. */
169
+ resolveDocsRoot?: (projectId: string | undefined) => string;
170
+ /** Contract (c)'s cross-seam half: `true` while a DRAFT or EDIT run is in flight for the
171
+ * doc. The server wires the sibling subscriptions' in-flight sets through here; the chat
172
+ * seam's own in-flight runs are tracked internally. */
173
+ isDocBusy?: (documentId: string) => boolean;
174
+ /** Queue-drain sweep cadence, ms (default 1000; tests shorten it). */
175
+ queueSweepMs?: number;
176
+ /** How long a drained ask waits for the PREVIOUS revision's version to land before
177
+ * proceeding on the stale head anyway, ms (default 60000; tests shorten it). */
178
+ landingGateMs?: number;
179
+ /** Called after a launch that FILED the run into a project (chat.posted carried
180
+ * `project_id`). Same wiring as the sibling seams: the server points this at the launch
181
+ * route's post-commit half (membership index tag + membership.attached emit). */
182
+ onRunFiled?: (runId: string, projectId: string) => void;
183
+ /** Diagnostics sink (default: console.error). */
184
+ log?: (message: string) => void;
185
+ }
186
+ /** Handle for a running subscription. */
187
+ export interface InteractiveChatSubscription {
188
+ stop(): Promise<void> | void;
189
+ /** The durable ledger (diagnostics / tests). */
190
+ ledger: InteractiveHandoffLedger;
191
+ /** Documents with a chat run currently in flight (diagnostics / cross-seam wiring). */
192
+ inFlightDocs(): string[];
193
+ /** Asks queued behind a busy doc, per doc (diagnostics / tests). */
194
+ queuedCount(documentId: string): number;
195
+ }
196
+ /**
197
+ * Arm the seam: register the `interactive-chat` workflow, open a durable
198
+ * `wicked.interactive.chat.posted` subscription, and answer each user ask on an existing
199
+ * answerable doc (contract (b)) with a governed run that ends in `wicked.interactive.draft.completed`
200
+ * (the service lands the revised full HTML as a generated version).
201
+ *
202
+ * Graceful degradation mirrors the sibling seams: a missing wicked-bus package or an
203
+ * unopenable db LOGS and returns `null` — the daemon must still boot on a machine whose bus
204
+ * is broken.
205
+ */
206
+ export declare function startInteractiveChatSubscriber(adapter: CoreAdapter, opts?: InteractiveChatOptions): Promise<InteractiveChatSubscription | null>;
207
+ //# sourceMappingURL=chat-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-events.d.ts","sourceRoot":"","sources":["../../src/interactive/chat-events.ts"],"names":[],"mappings":"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"}