wicked-crew 0.4.0 → 0.6.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 (132) hide show
  1. package/dist/api/api-prefix.d.ts +13 -0
  2. package/dist/api/api-prefix.d.ts.map +1 -0
  3. package/dist/api/api-prefix.js +13 -0
  4. package/dist/api/api-prefix.js.map +1 -0
  5. package/dist/api/audit.d.ts +57 -0
  6. package/dist/api/audit.d.ts.map +1 -0
  7. package/dist/api/audit.js +115 -0
  8. package/dist/api/audit.js.map +1 -0
  9. package/dist/api/auth.d.ts +192 -0
  10. package/dist/api/auth.d.ts.map +1 -0
  11. package/dist/api/auth.js +515 -0
  12. package/dist/api/auth.js.map +1 -0
  13. package/dist/api/evidence.d.ts +11 -0
  14. package/dist/api/evidence.d.ts.map +1 -1
  15. package/dist/api/evidence.js +8 -3
  16. package/dist/api/evidence.js.map +1 -1
  17. package/dist/api/gate-cache.d.ts +8 -0
  18. package/dist/api/gate-cache.d.ts.map +1 -1
  19. package/dist/api/gate-cache.js +10 -0
  20. package/dist/api/gate-cache.js.map +1 -1
  21. package/dist/api/open-path.d.ts +18 -0
  22. package/dist/api/open-path.d.ts.map +1 -0
  23. package/dist/api/open-path.js +79 -0
  24. package/dist/api/open-path.js.map +1 -0
  25. package/dist/api/routes.d.ts +113 -1
  26. package/dist/api/routes.d.ts.map +1 -1
  27. package/dist/api/routes.js +516 -27
  28. package/dist/api/routes.js.map +1 -1
  29. package/dist/api/seat-health.d.ts +55 -0
  30. package/dist/api/seat-health.d.ts.map +1 -0
  31. package/dist/api/seat-health.js +273 -0
  32. package/dist/api/seat-health.js.map +1 -0
  33. package/dist/api/seat-signin.d.ts +27 -0
  34. package/dist/api/seat-signin.d.ts.map +1 -0
  35. package/dist/api/seat-signin.js +143 -0
  36. package/dist/api/seat-signin.js.map +1 -0
  37. package/dist/api/server.d.ts +111 -3
  38. package/dist/api/server.d.ts.map +1 -1
  39. package/dist/api/server.js +236 -11
  40. package/dist/api/server.js.map +1 -1
  41. package/dist/api/unit-output.d.ts +62 -0
  42. package/dist/api/unit-output.d.ts.map +1 -0
  43. package/dist/api/unit-output.js +108 -0
  44. package/dist/api/unit-output.js.map +1 -0
  45. package/dist/cli/index.js +97 -3
  46. package/dist/cli/index.js.map +1 -1
  47. package/dist/cli/mcp.d.ts +14 -0
  48. package/dist/cli/mcp.d.ts.map +1 -0
  49. package/dist/cli/mcp.js +119 -0
  50. package/dist/cli/mcp.js.map +1 -0
  51. package/dist/core/adapter.d.ts +106 -1
  52. package/dist/core/adapter.d.ts.map +1 -1
  53. package/dist/core/adapter.js +293 -12
  54. package/dist/core/adapter.js.map +1 -1
  55. package/dist/core/bridge-path.d.ts +17 -6
  56. package/dist/core/bridge-path.d.ts.map +1 -1
  57. package/dist/core/bridge-path.js +17 -6
  58. package/dist/core/bridge-path.js.map +1 -1
  59. package/dist/core/types.d.ts +23 -352
  60. package/dist/core/types.d.ts.map +1 -1
  61. package/dist/core/types.js +11 -4
  62. package/dist/core/types.js.map +1 -1
  63. package/dist/interactive/bridge-pool.d.ts +71 -0
  64. package/dist/interactive/bridge-pool.d.ts.map +1 -0
  65. package/dist/interactive/bridge-pool.js +187 -0
  66. package/dist/interactive/bridge-pool.js.map +1 -0
  67. package/dist/interactive/bridge-root.d.ts +36 -0
  68. package/dist/interactive/bridge-root.d.ts.map +1 -0
  69. package/dist/interactive/bridge-root.js +48 -0
  70. package/dist/interactive/bridge-root.js.map +1 -0
  71. package/dist/interactive/draft-events.d.ts +144 -0
  72. package/dist/interactive/draft-events.d.ts.map +1 -0
  73. package/dist/interactive/draft-events.js +490 -0
  74. package/dist/interactive/draft-events.js.map +1 -0
  75. package/dist/interactive/edit-events.d.ts +172 -0
  76. package/dist/interactive/edit-events.d.ts.map +1 -0
  77. package/dist/interactive/edit-events.js +530 -0
  78. package/dist/interactive/edit-events.js.map +1 -0
  79. package/dist/interactive/ledger.d.ts +39 -0
  80. package/dist/interactive/ledger.d.ts.map +1 -0
  81. package/dist/interactive/ledger.js +93 -0
  82. package/dist/interactive/ledger.js.map +1 -0
  83. package/dist/interactive/proxy-routes.d.ts +39 -0
  84. package/dist/interactive/proxy-routes.d.ts.map +1 -0
  85. package/dist/interactive/proxy-routes.js +189 -0
  86. package/dist/interactive/proxy-routes.js.map +1 -0
  87. package/dist/interactive/ws-relay.d.ts +85 -0
  88. package/dist/interactive/ws-relay.d.ts.map +1 -0
  89. package/dist/interactive/ws-relay.js +191 -0
  90. package/dist/interactive/ws-relay.js.map +1 -0
  91. package/dist/projects/activity.d.ts +29 -0
  92. package/dist/projects/activity.d.ts.map +1 -0
  93. package/dist/projects/activity.js +172 -0
  94. package/dist/projects/activity.js.map +1 -0
  95. package/dist/projects/charter.d.ts +28 -0
  96. package/dist/projects/charter.d.ts.map +1 -0
  97. package/dist/projects/charter.js +53 -0
  98. package/dist/projects/charter.js.map +1 -0
  99. package/dist/projects/events.d.ts +55 -0
  100. package/dist/projects/events.d.ts.map +1 -0
  101. package/dist/projects/events.js +141 -0
  102. package/dist/projects/events.js.map +1 -0
  103. package/dist/projects/membership-index.d.ts +25 -0
  104. package/dist/projects/membership-index.d.ts.map +1 -0
  105. package/dist/projects/membership-index.js +46 -0
  106. package/dist/projects/membership-index.js.map +1 -0
  107. package/dist/projects/routes.d.ts +90 -0
  108. package/dist/projects/routes.d.ts.map +1 -0
  109. package/dist/projects/routes.js +388 -0
  110. package/dist/projects/routes.js.map +1 -0
  111. package/dist/projects/settings.d.ts +32 -0
  112. package/dist/projects/settings.d.ts.map +1 -0
  113. package/dist/projects/settings.js +64 -0
  114. package/dist/projects/settings.js.map +1 -0
  115. package/dist/qe/acceptance.d.ts +137 -0
  116. package/dist/qe/acceptance.d.ts.map +1 -0
  117. package/dist/qe/acceptance.js +249 -0
  118. package/dist/qe/acceptance.js.map +1 -0
  119. package/dist/qe/gate-events.d.ts +111 -0
  120. package/dist/qe/gate-events.d.ts.map +1 -0
  121. package/dist/qe/gate-events.js +168 -0
  122. package/dist/qe/gate-events.js.map +1 -0
  123. package/dist/qe/ledger.d.ts +100 -0
  124. package/dist/qe/ledger.d.ts.map +1 -0
  125. package/dist/qe/ledger.js +154 -0
  126. package/dist/qe/ledger.js.map +1 -0
  127. package/dist/studio/assets/index-CCwXa1cn.js +428 -0
  128. package/dist/studio/assets/index-HWxo0h41.css +32 -0
  129. package/dist/studio/index.html +2 -2
  130. package/package.json +10 -4
  131. package/dist/studio/assets/index-Ci_R6ARr.js +0 -423
  132. package/dist/studio/assets/index-Dio_c1Q3.css +0 -32
@@ -0,0 +1,187 @@
1
+ /**
2
+ * The wicked-interactive bridge pool — discovery, health, reuse-or-start (DES-MERGE-001 §5.3/§5.6).
3
+ *
4
+ * A bridge is a local `wicked-interactive serve` process that records itself in
5
+ * `<root>/.wi-serve.json` = `{ port, host, pid, startedAt, version }` (ADR-0022). Its port is
6
+ * DYNAMIC — the first free port above its base — which is precisely why crew, a server process
7
+ * that can read that lockfile, proxies it instead of the browser dialling a port literal.
8
+ *
9
+ * LOCAL-ONLY BY DESIGN. Every mechanism here (a pid, a file in a directory, spawning a child)
10
+ * is single-host. That is the slice-1 posture, not an oversight: when the execution seam goes
11
+ * remote, this module is the seam that gets a remote implementation, and the proxy above it
12
+ * does not change.
13
+ *
14
+ * Pooling is keyed by the RESOLVED root (see `bridge-root.ts`), so two projects that share the
15
+ * default root share one bridge and one port; projects bound to different roots get their own.
16
+ *
17
+ * Health follows ADR-0025's hardened reuse check, and the ORDER matters: a recorded pid that is
18
+ * alive but slow (cold first hit, busy materializing) must be REUSED, not duplicated — so a
19
+ * live pid earns three 1.5 s attempts before the bridge is declared dead. Identity is checked
20
+ * too: `/api/health` must report THIS root, or a recycled port belonging to some other service
21
+ * would be proxied as if it were ours.
22
+ */
23
+ import { spawn as nodeSpawn } from 'node:child_process';
24
+ import { mkdirSync, readFileSync } from 'node:fs';
25
+ import { join, resolve } from 'node:path';
26
+ export const LOCK_NAME = '.wi-serve.json';
27
+ /** ADR-0025: 1.5 s × 3 while the pid lives. */
28
+ export const HEALTH_TIMEOUT_MS = 1500;
29
+ export const HEALTH_ATTEMPTS = 3;
30
+ /** A cold `npx wicked-interactive serve` may have to resolve and fetch the package first. */
31
+ export const START_TIMEOUT_MS = 60_000;
32
+ /** The 503 the proxy renders as `{"code":"bridge_unavailable","hint":...}` (§5.6). */
33
+ export class BridgeUnavailableError extends Error {
34
+ /** An ACTIONABLE command an operator can actually run — never a bare "try again". */
35
+ hint;
36
+ constructor(message, hint) {
37
+ super(message);
38
+ this.name = 'BridgeUnavailableError';
39
+ this.hint = hint;
40
+ }
41
+ }
42
+ /** The one command that reproduces a failed start in a terminal, where its output is visible. */
43
+ function serveCommand(root) {
44
+ return `npx wicked-interactive serve --root ${root}`;
45
+ }
46
+ /** `<root>/.wi-serve.json`, or null when absent/unparseable/incomplete. */
47
+ export function readLock(root) {
48
+ try {
49
+ const raw = JSON.parse(readFileSync(join(root, LOCK_NAME), 'utf8'));
50
+ if (typeof raw.port !== 'number' || typeof raw.pid !== 'number')
51
+ return null;
52
+ return { host: typeof raw.host === 'string' && raw.host !== '' ? raw.host : '127.0.0.1', port: raw.port, pid: raw.pid };
53
+ }
54
+ catch {
55
+ return null;
56
+ }
57
+ }
58
+ /** Signal 0 probes existence without delivering: EPERM means alive-but-not-ours. */
59
+ export function pidAlive(pid) {
60
+ if (!Number.isInteger(pid) || pid <= 0)
61
+ return false;
62
+ try {
63
+ process.kill(pid, 0);
64
+ return true;
65
+ }
66
+ catch (err) {
67
+ return err.code === 'EPERM';
68
+ }
69
+ }
70
+ /** `GET /api/health` → the root that bridge is serving, or null (timeout, refusal, non-200). */
71
+ async function bridgeIdentity(bridge, timeoutMs) {
72
+ try {
73
+ const res = await fetch(`http://${bridge.host}:${bridge.port}/api/health`, {
74
+ signal: AbortSignal.timeout(timeoutMs),
75
+ });
76
+ if (!res.ok)
77
+ return null;
78
+ const body = (await res.json());
79
+ return typeof body.root === 'string' ? body.root : null;
80
+ }
81
+ catch {
82
+ return null;
83
+ }
84
+ }
85
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
86
+ export class InteractiveBridgePool {
87
+ io;
88
+ /** Last bridge known good per root — the fast path that keeps the proxy off `fetch` per request. */
89
+ live = new Map();
90
+ /** In-flight resolutions per root, so a burst of first requests starts ONE bridge, not N. */
91
+ inflight = new Map();
92
+ constructor(io = {}) {
93
+ this.io = io;
94
+ }
95
+ /** Reuse-or-start, idempotent per root. Throws `BridgeUnavailableError` when start is impossible. */
96
+ async ensure(root) {
97
+ // Fast path: we started/adopted it and its pid is still alive. A full health round-trip on
98
+ // every proxied request would put a 1.5 s timeout budget in front of every asset fetch.
99
+ const cached = this.live.get(root);
100
+ if (cached && pidAlive(cached.pid))
101
+ return cached;
102
+ this.live.delete(root);
103
+ const pending = this.inflight.get(root);
104
+ if (pending)
105
+ return pending;
106
+ const started = this.resolveOrStart(root).finally(() => this.inflight.delete(root));
107
+ this.inflight.set(root, started);
108
+ return started;
109
+ }
110
+ /** Drop the cached bridge for a root — called when a proxied connection is refused. */
111
+ invalidate(root) {
112
+ this.live.delete(root);
113
+ }
114
+ /** Live bridges, for tests and future operator introspection. */
115
+ keys() {
116
+ return [...this.live.keys()];
117
+ }
118
+ 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;
127
+ }
128
+ /** The lockfile points at a bridge that is alive, answering, and serving THIS root. */
129
+ async healthy(root) {
130
+ const lock = readLock(root);
131
+ if (lock === null || !pidAlive(lock.pid))
132
+ return null;
133
+ const timeout = this.io.healthTimeoutMs ?? HEALTH_TIMEOUT_MS;
134
+ for (let attempt = 0; attempt < HEALTH_ATTEMPTS; attempt++) {
135
+ const identity = await bridgeIdentity(lock, timeout);
136
+ if (identity !== null && resolve(identity) === root)
137
+ return lock;
138
+ // Only keep retrying while the pid still lives — a bridge that exited mid-probe is dead,
139
+ // not slow, and burning the remaining attempts on it just delays the restart.
140
+ if (!pidAlive(lock.pid))
141
+ return null;
142
+ if (attempt < HEALTH_ATTEMPTS - 1)
143
+ await sleep(300);
144
+ }
145
+ return null;
146
+ }
147
+ async start(root) {
148
+ try {
149
+ // `npx` runs with cwd=root; a missing directory fails the spawn with an opaque error.
150
+ mkdirSync(root, { recursive: true });
151
+ }
152
+ catch (err) {
153
+ throw new BridgeUnavailableError(`interactive root ${root} is not usable: ${err.message}`, `create the docs root and retry: mkdir -p ${root} && ${serveCommand(root)}`);
154
+ }
155
+ let spawnFailure = null;
156
+ const child = (this.io.spawn ?? defaultSpawn)(root);
157
+ // Detached + unref: the bridge is a SHARED instance keyed by root, so it must outlive the
158
+ // daemon that happened to start it (and be adoptable by the next one via the lockfile).
159
+ child.on('error', (err) => {
160
+ spawnFailure = err.message;
161
+ });
162
+ child.unref?.();
163
+ const deadline = Date.now() + (this.io.startTimeoutMs ?? START_TIMEOUT_MS);
164
+ while (Date.now() < deadline) {
165
+ if (spawnFailure !== null) {
166
+ throw new BridgeUnavailableError(`could not spawn the interactive bridge in ${root}: ${spawnFailure}`, `install Node 22+ so \`npx\` is on PATH, then run: ${serveCommand(root)}`);
167
+ }
168
+ const healthy = await this.healthy(root);
169
+ if (healthy)
170
+ return healthy;
171
+ await sleep(150);
172
+ }
173
+ this.io.log?.(`interactive bridge for ${root} did not come up within the start budget`);
174
+ throw new BridgeUnavailableError(`the interactive bridge for ${root} did not become healthy in time`, `run \`${serveCommand(root)}\` in a terminal to see the failure (or check ${join(root, '.wi-serve.log')})`);
175
+ }
176
+ }
177
+ /** `npx wicked-interactive serve` in `<root>`, detached, output to the bridge's own log. */
178
+ function defaultSpawn(root) {
179
+ // `--yes` is load-bearing: without it npx PROMPTS when the package is not installed, and a
180
+ // daemon has no tty to answer with — the request would hang instead of failing to a 503.
181
+ return nodeSpawn('npx', ['--yes', 'wicked-interactive', 'serve', '--root', root], {
182
+ cwd: root,
183
+ detached: true,
184
+ stdio: 'ignore',
185
+ });
186
+ }
187
+ //# sourceMappingURL=bridge-pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-pool.js","sourceRoot":"","sources":["../../src/interactive/bridge-pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Which wicked-interactive document root a crew project speaks to (DES-MERGE-001 §7.1/§7.2).
3
+ *
4
+ * §7.1 closed the identity question: a crew Project is THE entity, and an interactive
5
+ * "instance" (a docs directory) maps onto it through ONE nullable setting, `interactiveRoot`.
6
+ * Null means "the shared default root" — it is a default, never a constraint (§7.2): two
7
+ * projects that leave it null share one bridge, a project that sets it gets its own.
8
+ *
9
+ * The resolved string is also the BRIDGE POOL KEY, which is why every spelling of the same
10
+ * directory has to collapse to one value here rather than in the pool. `~/decks`, `decks`
11
+ * (relative), and `/Users/me/decks/` are the same instance; keying on the raw setting would
12
+ * start a second `wicked-interactive serve` on a second port for each spelling — exactly the
13
+ * "why is it on 5 ports" confusion ADR-0025 exists to prevent.
14
+ */
15
+ /** The setting carrier — a `Project` record or a crew-side settings row both satisfy this. */
16
+ export interface InteractiveRootSetting {
17
+ /** Absolute or `~`-relative docs root; null/absent ⇒ the shared default. */
18
+ interactiveRoot?: string | null | undefined;
19
+ }
20
+ /** Env override for the SHARED DEFAULT only (never for an explicit per-project setting).
21
+ * Exists so a test harness or an e2e run can point "the default root" at a scratch dir. */
22
+ export declare const ROOT_ENV = "WICKED_INTERACTIVE_ROOT";
23
+ /**
24
+ * What `wicked-interactive serve` uses with no `--root`: the canonical shared root
25
+ * `~/wicked-interactive/docs` (ADR-0025 amended, `bin/wicked-interactive.js:181`). Kept
26
+ * byte-identical to interactive's own default on purpose — that is what lets an operator's
27
+ * already-running default bridge be ADOPTED by the pool instead of duplicated.
28
+ */
29
+ export declare function defaultInteractiveRoot(home?: string): string;
30
+ /**
31
+ * The resolved, canonical docs root for a project — and therefore its bridge pool key.
32
+ * Precedence: the project's own `interactiveRoot` › `WICKED_INTERACTIVE_ROOT` › the shared
33
+ * default. A blank/whitespace setting is treated as null, not as "the cwd".
34
+ */
35
+ export declare function resolveInteractiveRoot(setting: InteractiveRootSetting | null | undefined, env?: Record<string, string | undefined>, home?: string): string;
36
+ //# sourceMappingURL=bridge-root.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-root.d.ts","sourceRoot":"","sources":["../../src/interactive/bridge-root.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,8FAA8F;AAC9F,MAAM,WAAW,sBAAsB;IACrC,4EAA4E;IAC5E,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CAC7C;AAED;4FAC4F;AAC5F,eAAO,MAAM,QAAQ,4BAA4B,CAAC;AAElD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,GAAE,MAAkB,GAAG,MAAM,CAEvE;AASD;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,sBAAsB,GAAG,IAAI,GAAG,SAAS,EAClD,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,EACrD,IAAI,GAAE,MAAkB,GACvB,MAAM,CAMR"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Which wicked-interactive document root a crew project speaks to (DES-MERGE-001 §7.1/§7.2).
3
+ *
4
+ * §7.1 closed the identity question: a crew Project is THE entity, and an interactive
5
+ * "instance" (a docs directory) maps onto it through ONE nullable setting, `interactiveRoot`.
6
+ * Null means "the shared default root" — it is a default, never a constraint (§7.2): two
7
+ * projects that leave it null share one bridge, a project that sets it gets its own.
8
+ *
9
+ * The resolved string is also the BRIDGE POOL KEY, which is why every spelling of the same
10
+ * directory has to collapse to one value here rather than in the pool. `~/decks`, `decks`
11
+ * (relative), and `/Users/me/decks/` are the same instance; keying on the raw setting would
12
+ * start a second `wicked-interactive serve` on a second port for each spelling — exactly the
13
+ * "why is it on 5 ports" confusion ADR-0025 exists to prevent.
14
+ */
15
+ import { homedir } from 'node:os';
16
+ import { resolve } from 'node:path';
17
+ /** Env override for the SHARED DEFAULT only (never for an explicit per-project setting).
18
+ * Exists so a test harness or an e2e run can point "the default root" at a scratch dir. */
19
+ export const ROOT_ENV = 'WICKED_INTERACTIVE_ROOT';
20
+ /**
21
+ * What `wicked-interactive serve` uses with no `--root`: the canonical shared root
22
+ * `~/wicked-interactive/docs` (ADR-0025 amended, `bin/wicked-interactive.js:181`). Kept
23
+ * byte-identical to interactive's own default on purpose — that is what lets an operator's
24
+ * already-running default bridge be ADOPTED by the pool instead of duplicated.
25
+ */
26
+ export function defaultInteractiveRoot(home = homedir()) {
27
+ return resolve(home, 'wicked-interactive', 'docs');
28
+ }
29
+ /** Expand a leading `~` and absolutize, so every spelling of one directory keys the same. */
30
+ function canonicalize(value, home) {
31
+ const expanded = value === '~' ? home : value.startsWith('~/') || value.startsWith('~\\') ? resolve(home, value.slice(2)) : value;
32
+ return resolve(expanded);
33
+ }
34
+ /**
35
+ * The resolved, canonical docs root for a project — and therefore its bridge pool key.
36
+ * Precedence: the project's own `interactiveRoot` › `WICKED_INTERACTIVE_ROOT` › the shared
37
+ * default. A blank/whitespace setting is treated as null, not as "the cwd".
38
+ */
39
+ export function resolveInteractiveRoot(setting, env = process.env, home = homedir()) {
40
+ const own = setting?.interactiveRoot;
41
+ if (typeof own === 'string' && own.trim() !== '')
42
+ return canonicalize(own.trim(), home);
43
+ const shared = env[ROOT_ENV];
44
+ if (typeof shared === 'string' && shared.trim() !== '')
45
+ return canonicalize(shared.trim(), home);
46
+ return defaultInteractiveRoot(home);
47
+ }
48
+ //# sourceMappingURL=bridge-root.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-root.js","sourceRoot":"","sources":["../../src/interactive/bridge-root.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC;4FAC4F;AAC5F,MAAM,CAAC,MAAM,QAAQ,GAAG,yBAAyB,CAAC;AAElD;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAe,OAAO,EAAE;IAC7D,OAAO,OAAO,CAAC,IAAI,EAAE,oBAAoB,EAAE,MAAM,CAAC,CAAC;AACrD,CAAC;AAED,6FAA6F;AAC7F,SAAS,YAAY,CAAC,KAAa,EAAE,IAAY;IAC/C,MAAM,QAAQ,GACZ,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACnH,OAAO,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC3B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAkD,EAClD,MAA0C,OAAO,CAAC,GAAG,EACrD,OAAe,OAAO,EAAE;IAExB,MAAM,GAAG,GAAG,OAAO,EAAE,eAAe,CAAC;IACrC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;IACxF,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7B,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;IACjG,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Opt-in governed answering of wicked-interactive's first-draft generation (task #86 spike,
3
+ * Phase 7c first leg).
4
+ *
5
+ * wicked-interactive's service is model-free: when a doc is created with `kind: "source"` it
6
+ * seeds a placeholder v0 and emits `wicked.interactive.doc.created`, expecting *something with
7
+ * intelligence* to answer with `wicked.interactive.draft.completed` carrying the first draft
8
+ * (the service then instruments `data-wid` anchors, themes it, and lands `_v1.html`). Today
9
+ * that answerer is an ad-hoc `assist` agent session. This module makes a crew-governed run the
10
+ * answerer instead — same bus vocabulary, zero interactive-service changes beyond the additive
11
+ * producer row (`wi-crew`) in interactive's events.js ownership table.
12
+ *
13
+ * Shape mirrors `qe/gate-events.ts` (crew's existing bus seam, Phase 6a): OPT-IN, dynamic
14
+ * wicked-bus import, graceful degradation when the bus is absent, durable cursor with
15
+ * `cursor_init: 'latest'` under a dedicated plugin name.
16
+ *
17
+ * Behavioral invariants honored (recon-verified against interactive):
18
+ * - Heartbeat: the canvas shows a working veil and the browser fires ~20s
19
+ * `status.requested` heartbeats; a silent answerer reads as a frozen UI. We narrate
20
+ * `wicked.interactive.status.posted` on every phase transition AND on a ≤15s timer.
21
+ * - Idempotency: the durable cursor redelivers under at-least-once semantics, and a replayed
22
+ * `doc.created` must not produce a duplicate `_v2.html`. A durable per-doc ledger
23
+ * (JSON file, atomic rename) gates the launch, and the final `draft.completed` emit carries
24
+ * a deterministic idempotency key (`crew:interactive.draft:<doc>:v1`) so even a double
25
+ * emit dedupes at the bus (WB-002).
26
+ * - INV-2 (`data-wid`): first drafts are whole documents with no pre-existing anchors — the
27
+ * service instruments fresh ones — so the worker contract explicitly forbids inventing
28
+ * `data-wid` attributes rather than requiring preservation. The feedback→edit leg (fragment
29
+ * preservation at scale) is the structural seam next door: edit-events.ts.
30
+ */
31
+ import { InteractiveHandoffLedger } from './ledger.js';
32
+ import type { CoreAdapter } from '../core/adapter.js';
33
+ import type { WorkflowDef } from '../core/types.js';
34
+ export declare const INTERACTIVE_DOMAIN = "wicked-interactive";
35
+ export declare const DOC_CREATED = "wicked.interactive.doc.created";
36
+ export declare const DRAFT_COMPLETED = "wicked.interactive.draft.completed";
37
+ export declare const STATUS_POSTED = "wicked.interactive.status.posted";
38
+ /** Exact-type filter with a domain guard — no wildcard, one event type is the whole trigger. */
39
+ export declare const INTERACTIVE_BUS_FILTER = "wicked.interactive.doc.created@wicked-interactive";
40
+ /** Dedicated durable-cursor identity — NOT the qe subscriber's `wicked-crew`, so the two
41
+ * seams advance independent cursors and stopping one never strands the other. */
42
+ export declare const INTERACTIVE_BUS_PLUGIN = "wicked-crew-interactive-draft";
43
+ /** The producer identity stamped on every event crew's interactive seams emit (this module and
44
+ * edit-events.ts). Must appear in interactive's events.js ownership table for DRAFT_COMPLETED,
45
+ * EDIT_COMPLETED, and STATUS_POSTED — the additive vocabulary rows that are the only
46
+ * interactive changes Phase 7c is allowed. */
47
+ export declare const INTERACTIVE_PRODUCER = "wi-crew";
48
+ /** Interactive's doc-name grammar (server.js DOC_NAME) — re-checked before any launch so a
49
+ * malformed document_id can't name a ledger key or a draft file path. Shared with the
50
+ * structural-edit seam (edit-events.ts), which guards the same identity. */
51
+ export declare const DOC_NAME: RegExp;
52
+ export declare const INTERACTIVE_DRAFT_WORKFLOW = "interactive-draft";
53
+ /**
54
+ * The governed workflow that produces a first draft. Two agent phases — outline (recon) then
55
+ * draft (build, creator role) — so the run narrates a real phase transition and the drafting
56
+ * worker builds on a planned structure instead of one-shotting the whole document.
57
+ *
58
+ * The phase `instructions` adapt the draft-production contract from interactive's assist skill
59
+ * (Step 5): honor the brief/sources/style, ground content in what the brief supports, produce a
60
+ * complete self-contained HTML document, and NEVER mint `data-wid` attributes (the service
61
+ * instruments fresh anchors itself). They are SINGLE-LINE by contract: the engine folds
62
+ * instructions onto the unit description with a single-line separator, and the PTY seat runner
63
+ * refuses any prompt carrying an embedded newline (wicked-core FINDING-011).
64
+ *
65
+ * All gates are `auto` with `validator_pin: null` — no human gate, no deterministic floor —
66
+ * because the acceptance gate for a draft is the INTERACTIVE side (the service's INV-2
67
+ * instrument+theme pipeline and the user's own eyes on the canvas). Registered via
68
+ * `adapter.registerWorkflow()` at arm time (validate-before-persist, hot-registered into the
69
+ * engine), not added to BUILTIN_WORKFLOWS: this def is crew-only data owned by this seam, not a
70
+ * mirror of a wicked-core drop-in.
71
+ */
72
+ export declare const INTERACTIVE_DRAFT_WORKFLOW_DEF: WorkflowDef;
73
+ /** The doc-creation fields this seam acts on. */
74
+ export interface SourceDocCreated {
75
+ documentId: string;
76
+ brief: string;
77
+ sourcePaths: string[];
78
+ style: string;
79
+ /** The crew project this doc is bound to (required — parseSourceDocCreated returns null when
80
+ * absent; unbound docs are handled solo by the assist skill, not by this seam). */
81
+ projectId: string;
82
+ }
83
+ /**
84
+ * Parse a bus frame into a {@link SourceDocCreated}, or `null` when it is not an actionable
85
+ * `doc.created` (wrong type, non-`source` kind, missing/malformed document_id). `kind: "demo"`
86
+ * and plain html docs are the assist loop's business, not this seam's.
87
+ */
88
+ export declare function parseSourceDocCreated(eventType: string, payload: unknown): SourceDocCreated | null;
89
+ /** Collapse whitespace/newlines to single spaces and cap length — the intent must stay a
90
+ * single line (the PTY seat runner refuses embedded newlines) and a pasted-novel brief must
91
+ * not balloon the worker prompt. Shared with the structural-edit seam. */
92
+ export declare function oneLine(text: string, cap: number): string;
93
+ /**
94
+ * The run's problem statement (the engine scopes it per phase and folds each phase's
95
+ * instructions on top). Carries everything doc-specific: identity, brief, sources, style, and
96
+ * the absolute path the finished HTML must land at.
97
+ */
98
+ export declare function draftProblem(doc: SourceDocCreated, outPath: string): string;
99
+ /** Deterministic bus idempotency key for the one draft this seam may land per document. */
100
+ export declare function draftIdempotencyKey(documentId: string): string;
101
+ export { InteractiveHandoffLedger, type HandoffLedgerEntry } from './ledger.js';
102
+ /** Options for {@link startInteractiveDraftSubscriber}. */
103
+ export interface InteractiveDraftOptions {
104
+ /** Bus SQLite db path. Omit to let wicked-bus resolve its own default
105
+ * (honors `WICKED_BUS_DATA_DIR`) — which is where interactive's service emits unless
106
+ * redirected, so the default is usually right. */
107
+ dbPath?: string;
108
+ /** Poll cadence, ms (default 2000; tests shorten it). */
109
+ pollIntervalMs?: number;
110
+ /** Heartbeat narration cadence while a run is in flight, ms (default 15000 — inside the
111
+ * UI's ~20s `status.requested` window so the canvas never reads frozen). */
112
+ heartbeatMs?: number;
113
+ /** Ledger file (default `~/.wicked-crew/interactive-draft-ledger.json`). */
114
+ ledgerPath?: string;
115
+ /** Where governed workers write finished drafts (default `~/.wicked-crew/interactive-drafts`). */
116
+ draftDir?: string;
117
+ /** Seat roster JSON for the governed run (default: the production council roster).
118
+ * The functional-test harness passes a deterministic stub seat here. */
119
+ clisJson?: string;
120
+ /** Called after a launch that FILED the run into a project (doc.created carried
121
+ * `project_id`). The server wires this to the same post-commit half the launch route
122
+ * performs: tag the run in the live membership index + emit `wicked.crew.membership.attached`
123
+ * (the engine already attached the crew.run membership atomically with the launch). */
124
+ onRunFiled?: (runId: string, projectId: string) => void;
125
+ /** Diagnostics sink (default: console.error). */
126
+ log?: (message: string) => void;
127
+ }
128
+ /** Handle for a running subscription. */
129
+ export interface InteractiveDraftSubscription {
130
+ stop(): Promise<void> | void;
131
+ /** The durable ledger (diagnostics / tests). */
132
+ ledger: InteractiveHandoffLedger;
133
+ }
134
+ /**
135
+ * Arm the seam: register the `interactive-draft` workflow, open a durable
136
+ * `wicked.interactive.doc.created` subscription, and answer each `kind: "source"` creation
137
+ * with a governed run that ends in `wicked.interactive.draft.completed`.
138
+ *
139
+ * Graceful degradation mirrors `startQeGateSubscriber`: a missing wicked-bus package or an
140
+ * unopenable db LOGS and returns `null` — the daemon must still boot on a machine whose bus is
141
+ * broken; interactive's assist loop remains the (always-available) fallback answerer.
142
+ */
143
+ export declare function startInteractiveDraftSubscriber(adapter: CoreAdapter, opts?: InteractiveDraftOptions): Promise<InteractiveDraftSubscription | null>;
144
+ //# sourceMappingURL=draft-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draft-events.d.ts","sourceRoot":"","sources":["../../src/interactive/draft-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAOH,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAa,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAI/D,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AACvD,eAAO,MAAM,WAAW,mCAAmC,CAAC;AAC5D,eAAO,MAAM,eAAe,uCAAuC,CAAC;AACpE,eAAO,MAAM,aAAa,qCAAqC,CAAC;AAEhE,gGAAgG;AAChG,eAAO,MAAM,sBAAsB,sDAAyC,CAAC;AAE7E;kFACkF;AAClF,eAAO,MAAM,sBAAsB,kCAAkC,CAAC;AAEtE;;;+CAG+C;AAC/C,eAAO,MAAM,oBAAoB,YAAY,CAAC;AAE9C;;6EAE6E;AAC7E,eAAO,MAAM,QAAQ,QAA8B,CAAC;AAIpD,eAAO,MAAM,0BAA0B,sBAAsB,CAAC;AAE9D;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,8BAA8B,EAAE,WAqC5C,CAAC;AAIF,iDAAiD;AACjD,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd;wFACoF;IACpF,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,gBAAgB,GAAG,IAAI,CAiBlG;AAED;;2EAE2E;AAC3E,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAW3E;AAED,2FAA2F;AAC3F,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE9D;AAQD,OAAO,EAAE,wBAAwB,EAAE,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAIhF,2DAA2D;AAC3D,MAAM,WAAW,uBAAuB;IACtC;;uDAEmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;iFAC6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kGAAkG;IAClG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;6EACyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;4FAGwF;IACxF,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,iDAAiD;IACjD,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAED,yCAAyC;AACzC,MAAM,WAAW,4BAA4B;IAC3C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC7B,gDAAgD;IAChD,MAAM,EAAE,wBAAwB,CAAC;CAClC;AAoBD;;;;;;;;GAQG;AACH,wBAAsB,+BAA+B,CACnD,OAAO,EAAE,WAAW,EACpB,IAAI,GAAE,uBAA4B,GACjC,OAAO,CAAC,4BAA4B,GAAG,IAAI,CAAC,CAmW9C"}