wicked-crew 0.7.40 → 0.7.46
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.
- package/dist/api/audit.d.ts +3 -0
- package/dist/api/audit.d.ts.map +1 -1
- package/dist/api/audit.js +2 -0
- package/dist/api/audit.js.map +1 -1
- package/dist/api/capture.d.ts +149 -0
- package/dist/api/capture.d.ts.map +1 -0
- package/dist/api/capture.js +330 -0
- package/dist/api/capture.js.map +1 -0
- package/dist/api/chat-citations.d.ts +174 -0
- package/dist/api/chat-citations.d.ts.map +1 -0
- package/dist/api/chat-citations.js +528 -0
- package/dist/api/chat-citations.js.map +1 -0
- package/dist/api/chat-transcripts.d.ts +20 -1
- package/dist/api/chat-transcripts.d.ts.map +1 -1
- package/dist/api/chat-transcripts.js +29 -0
- package/dist/api/chat-transcripts.js.map +1 -1
- package/dist/api/delivery-cache.d.ts +2 -2
- package/dist/api/delivery-freeze.d.ts +66 -0
- package/dist/api/delivery-freeze.d.ts.map +1 -0
- package/dist/api/delivery-freeze.js +104 -0
- package/dist/api/delivery-freeze.js.map +1 -0
- package/dist/api/delivery-index.d.ts +53 -9
- package/dist/api/delivery-index.d.ts.map +1 -1
- package/dist/api/delivery-index.js +115 -22
- package/dist/api/delivery-index.js.map +1 -1
- package/dist/api/demo.d.ts +90 -0
- package/dist/api/demo.d.ts.map +1 -0
- package/dist/api/demo.js +492 -0
- package/dist/api/demo.js.map +1 -0
- package/dist/api/diagnostics.d.ts +64 -1
- package/dist/api/diagnostics.d.ts.map +1 -1
- package/dist/api/diagnostics.js +129 -1
- package/dist/api/diagnostics.js.map +1 -1
- package/dist/api/eval-sample.d.ts +6 -6
- package/dist/api/governance-steering.d.ts +2 -2
- package/dist/api/mcp.d.ts +282 -0
- package/dist/api/mcp.d.ts.map +1 -0
- package/dist/api/mcp.js +521 -0
- package/dist/api/mcp.js.map +1 -0
- package/dist/api/plan-schema.d.ts +56 -0
- package/dist/api/plan-schema.d.ts.map +1 -0
- package/dist/api/plan-schema.js +26 -0
- package/dist/api/plan-schema.js.map +1 -0
- package/dist/api/roster-standing.d.ts +15 -2
- package/dist/api/roster-standing.d.ts.map +1 -1
- package/dist/api/roster-standing.js +59 -3
- package/dist/api/roster-standing.js.map +1 -1
- package/dist/api/routes.d.ts +630 -51
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +738 -127
- package/dist/api/routes.js.map +1 -1
- package/dist/api/run-files.d.ts.map +1 -1
- package/dist/api/run-files.js +31 -2
- package/dist/api/run-files.js.map +1 -1
- package/dist/api/run-liveness.d.ts +41 -0
- package/dist/api/run-liveness.d.ts.map +1 -0
- package/dist/api/run-liveness.js +166 -0
- package/dist/api/run-liveness.js.map +1 -0
- package/dist/api/seat-health.d.ts +35 -0
- package/dist/api/seat-health.d.ts.map +1 -1
- package/dist/api/seat-health.js +92 -4
- package/dist/api/seat-health.js.map +1 -1
- package/dist/api/seat-probe.d.ts +141 -0
- package/dist/api/seat-probe.d.ts.map +1 -0
- package/dist/api/seat-probe.js +257 -0
- package/dist/api/seat-probe.js.map +1 -0
- package/dist/api/seat-record.d.ts +40 -0
- package/dist/api/seat-record.d.ts.map +1 -0
- package/dist/api/seat-record.js +218 -0
- package/dist/api/seat-record.js.map +1 -0
- package/dist/api/seat-signin.d.ts.map +1 -1
- package/dist/api/seat-signin.js +3 -1
- package/dist/api/seat-signin.js.map +1 -1
- package/dist/api/seat-standing.d.ts +25 -5
- package/dist/api/seat-standing.d.ts.map +1 -1
- package/dist/api/seat-standing.js +76 -9
- package/dist/api/seat-standing.js.map +1 -1
- package/dist/api/server.d.ts +34 -48
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +283 -107
- package/dist/api/server.js.map +1 -1
- package/dist/api/skills.d.ts +3 -1
- package/dist/api/skills.d.ts.map +1 -1
- package/dist/api/skills.js +7 -2
- package/dist/api/skills.js.map +1 -1
- package/dist/api/stall-watchdog.d.ts +34 -3
- package/dist/api/stall-watchdog.d.ts.map +1 -1
- package/dist/api/stall-watchdog.js +107 -8
- package/dist/api/stall-watchdog.js.map +1 -1
- package/dist/api/steering-landing.d.ts +6 -6
- package/dist/api/steering-landing.d.ts.map +1 -1
- package/dist/api/steering-landing.js +7 -9
- package/dist/api/steering-landing.js.map +1 -1
- package/dist/api/testing.d.ts +6 -4
- package/dist/api/testing.d.ts.map +1 -1
- package/dist/api/testing.js +82 -47
- package/dist/api/testing.js.map +1 -1
- package/dist/campaign/boot-resume.d.ts +34 -0
- package/dist/campaign/boot-resume.d.ts.map +1 -0
- package/dist/campaign/boot-resume.js +45 -0
- package/dist/campaign/boot-resume.js.map +1 -0
- package/dist/campaigns/rollup.d.ts +4 -1
- package/dist/campaigns/rollup.d.ts.map +1 -1
- package/dist/campaigns/rollup.js +6 -1
- package/dist/campaigns/rollup.js.map +1 -1
- package/dist/campaigns/routes.d.ts +2 -2
- package/dist/cli/bearer.d.ts +27 -1
- package/dist/cli/bearer.d.ts.map +1 -1
- package/dist/cli/bearer.js +62 -2
- package/dist/cli/bearer.js.map +1 -1
- package/dist/cli/governance.d.ts +11 -0
- package/dist/cli/governance.d.ts.map +1 -1
- package/dist/cli/governance.js +8 -2
- package/dist/cli/governance.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +140 -75
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp.d.ts +11 -0
- package/dist/cli/mcp.d.ts.map +1 -1
- package/dist/cli/mcp.js +40 -9
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/service.d.ts +78 -0
- package/dist/cli/service.d.ts.map +1 -0
- package/dist/cli/service.js +334 -0
- package/dist/cli/service.js.map +1 -0
- package/dist/core/adapter.d.ts +238 -12
- package/dist/core/adapter.d.ts.map +1 -1
- package/dist/core/adapter.js +619 -157
- package/dist/core/adapter.js.map +1 -1
- package/dist/core/bridge-reaper.d.ts +4 -1
- package/dist/core/bridge-reaper.d.ts.map +1 -1
- package/dist/core/bridge-reaper.js +15 -1
- package/dist/core/bridge-reaper.js.map +1 -1
- package/dist/core/bus-notice.d.ts +27 -0
- package/dist/core/bus-notice.d.ts.map +1 -0
- package/dist/core/bus-notice.js +24 -0
- package/dist/core/bus-notice.js.map +1 -0
- package/dist/core/bus.d.ts +99 -0
- package/dist/core/bus.d.ts.map +1 -0
- package/dist/core/bus.js +176 -0
- package/dist/core/bus.js.map +1 -0
- package/dist/core/deliver-exclusions.d.ts +71 -0
- package/dist/core/deliver-exclusions.d.ts.map +1 -0
- package/dist/core/deliver-exclusions.js +110 -0
- package/dist/core/deliver-exclusions.js.map +1 -0
- package/dist/core/deliver-text.d.ts +61 -14
- package/dist/core/deliver-text.d.ts.map +1 -1
- package/dist/core/deliver-text.js +178 -30
- package/dist/core/deliver-text.js.map +1 -1
- package/dist/core/deliver-triage.d.ts +11 -2
- package/dist/core/deliver-triage.d.ts.map +1 -1
- package/dist/core/deliver-triage.js +19 -1
- package/dist/core/deliver-triage.js.map +1 -1
- package/dist/core/deliver.d.ts +161 -3
- package/dist/core/deliver.d.ts.map +1 -1
- package/dist/core/deliver.js +463 -25
- package/dist/core/deliver.js.map +1 -1
- package/dist/core/deliverable-floor.d.ts.map +1 -1
- package/dist/core/deliverable-floor.js +5 -7
- package/dist/core/deliverable-floor.js.map +1 -1
- package/dist/core/engine-bus.d.ts +40 -0
- package/dist/core/engine-bus.d.ts.map +1 -0
- package/dist/core/engine-bus.js +27 -0
- package/dist/core/engine-bus.js.map +1 -0
- package/dist/core/estate-mcp-client.d.ts +87 -5
- package/dist/core/estate-mcp-client.d.ts.map +1 -1
- package/dist/core/estate-mcp-client.js +90 -11
- package/dist/core/estate-mcp-client.js.map +1 -1
- package/dist/core/linked-issues.d.ts +46 -0
- package/dist/core/linked-issues.d.ts.map +1 -0
- package/dist/core/linked-issues.js +123 -0
- package/dist/core/linked-issues.js.map +1 -0
- package/dist/core/run-identity.d.ts +100 -0
- package/dist/core/run-identity.d.ts.map +1 -0
- package/dist/core/run-identity.js +178 -0
- package/dist/core/run-identity.js.map +1 -0
- package/dist/core/shutdown.d.ts +16 -0
- package/dist/core/shutdown.d.ts.map +1 -0
- package/dist/core/shutdown.js +39 -0
- package/dist/core/shutdown.js.map +1 -0
- package/dist/core/types.d.ts +15 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +4 -0
- package/dist/core/types.js.map +1 -1
- package/dist/interactive/bridge-pool.d.ts +67 -3
- package/dist/interactive/bridge-pool.d.ts.map +1 -1
- package/dist/interactive/bridge-pool.js +129 -13
- package/dist/interactive/bridge-pool.js.map +1 -1
- package/dist/interactive/bridge-root.d.ts +9 -0
- package/dist/interactive/bridge-root.d.ts.map +1 -1
- package/dist/interactive/bridge-root.js +11 -4
- package/dist/interactive/bridge-root.js.map +1 -1
- package/dist/interactive/chat-events.d.ts +14 -9
- package/dist/interactive/chat-events.d.ts.map +1 -1
- package/dist/interactive/chat-events.js +55 -57
- package/dist/interactive/chat-events.js.map +1 -1
- package/dist/interactive/council-outcome.d.ts +1 -0
- package/dist/interactive/council-outcome.d.ts.map +1 -1
- package/dist/interactive/council-outcome.js +33 -0
- package/dist/interactive/council-outcome.js.map +1 -1
- package/dist/interactive/draft-events.d.ts +36 -17
- package/dist/interactive/draft-events.d.ts.map +1 -1
- package/dist/interactive/draft-events.js +121 -92
- package/dist/interactive/draft-events.js.map +1 -1
- package/dist/interactive/draft-skill.d.ts +59 -0
- package/dist/interactive/draft-skill.d.ts.map +1 -1
- package/dist/interactive/draft-skill.js +233 -0
- package/dist/interactive/draft-skill.js.map +1 -1
- package/dist/interactive/edit-events.d.ts +1 -14
- package/dist/interactive/edit-events.d.ts.map +1 -1
- package/dist/interactive/edit-events.js +37 -70
- package/dist/interactive/edit-events.js.map +1 -1
- package/dist/interactive/proxy-routes.d.ts +2 -2
- package/dist/interactive/proxy-routes.d.ts.map +1 -1
- package/dist/interactive/proxy-routes.js +4 -13
- package/dist/interactive/proxy-routes.js.map +1 -1
- package/dist/interactive/ws-relay.d.ts +9 -10
- package/dist/interactive/ws-relay.d.ts.map +1 -1
- package/dist/interactive/ws-relay.js +23 -50
- package/dist/interactive/ws-relay.js.map +1 -1
- package/dist/mcp/broker.d.ts +88 -0
- package/dist/mcp/broker.d.ts.map +1 -0
- package/dist/mcp/broker.js +307 -0
- package/dist/mcp/broker.js.map +1 -0
- package/dist/mcp/call-records.d.ts +61 -0
- package/dist/mcp/call-records.d.ts.map +1 -0
- package/dist/mcp/call-records.js +135 -0
- package/dist/mcp/call-records.js.map +1 -0
- package/dist/mcp/classify.d.ts +45 -0
- package/dist/mcp/classify.d.ts.map +1 -0
- package/dist/mcp/classify.js +83 -0
- package/dist/mcp/classify.js.map +1 -0
- package/dist/mcp/discovery.d.ts +24 -0
- package/dist/mcp/discovery.d.ts.map +1 -0
- package/dist/mcp/discovery.js +78 -0
- package/dist/mcp/discovery.js.map +1 -0
- package/dist/mcp/invoke.d.ts +36 -0
- package/dist/mcp/invoke.d.ts.map +1 -0
- package/dist/mcp/invoke.js +80 -0
- package/dist/mcp/invoke.js.map +1 -0
- package/dist/mcp/policies.d.ts +110 -0
- package/dist/mcp/policies.d.ts.map +1 -0
- package/dist/mcp/policies.js +400 -0
- package/dist/mcp/policies.js.map +1 -0
- package/dist/mcp/probe.d.ts +66 -0
- package/dist/mcp/probe.d.ts.map +1 -0
- package/dist/mcp/probe.js +116 -0
- package/dist/mcp/probe.js.map +1 -0
- package/dist/mcp/redact.d.ts +34 -0
- package/dist/mcp/redact.d.ts.map +1 -0
- package/dist/mcp/redact.js +84 -0
- package/dist/mcp/redact.js.map +1 -0
- package/dist/mcp/registry-store.d.ts +69 -0
- package/dist/mcp/registry-store.d.ts.map +1 -0
- package/dist/mcp/registry-store.js +82 -0
- package/dist/mcp/registry-store.js.map +1 -0
- package/dist/mcp/registry.d.ts +147 -0
- package/dist/mcp/registry.d.ts.map +1 -0
- package/dist/mcp/registry.js +509 -0
- package/dist/mcp/registry.js.map +1 -0
- package/dist/mcp/rest.d.ts +111 -0
- package/dist/mcp/rest.d.ts.map +1 -0
- package/dist/mcp/rest.js +606 -0
- package/dist/mcp/rest.js.map +1 -0
- package/dist/mcp/secrets.d.ts +66 -0
- package/dist/mcp/secrets.d.ts.map +1 -0
- package/dist/mcp/secrets.js +180 -0
- package/dist/mcp/secrets.js.map +1 -0
- package/dist/mcp/tool-list.d.ts +25 -0
- package/dist/mcp/tool-list.d.ts.map +1 -0
- package/dist/mcp/tool-list.js +62 -0
- package/dist/mcp/tool-list.js.map +1 -0
- package/dist/mcp/upstream-error.d.ts +12 -0
- package/dist/mcp/upstream-error.d.ts.map +1 -0
- package/dist/mcp/upstream-error.js +14 -0
- package/dist/mcp/upstream-error.js.map +1 -0
- package/dist/mcp/usage.d.ts +31 -0
- package/dist/mcp/usage.d.ts.map +1 -0
- package/dist/mcp/usage.js +159 -0
- package/dist/mcp/usage.js.map +1 -0
- package/dist/presets/routes.d.ts +53 -0
- package/dist/presets/routes.d.ts.map +1 -0
- package/dist/presets/routes.js +115 -0
- package/dist/presets/routes.js.map +1 -0
- package/dist/projects/activity.d.ts +6 -18
- package/dist/projects/activity.d.ts.map +1 -1
- package/dist/projects/activity.js +17 -60
- package/dist/projects/activity.js.map +1 -1
- package/dist/projects/events.d.ts +6 -5
- package/dist/projects/events.d.ts.map +1 -1
- package/dist/projects/events.js +33 -58
- package/dist/projects/events.js.map +1 -1
- package/dist/projects/routes.d.ts.map +1 -1
- package/dist/projects/routes.js +19 -0
- package/dist/projects/routes.js.map +1 -1
- package/dist/projects/state-home-preflight.d.ts.map +1 -1
- package/dist/projects/state-home-preflight.js +7 -0
- package/dist/projects/state-home-preflight.js.map +1 -1
- package/dist/projects/state-home-registry.d.ts.map +1 -1
- package/dist/projects/state-home-registry.js +9 -1
- package/dist/projects/state-home-registry.js.map +1 -1
- package/dist/qe/acceptance.d.ts +28 -28
- package/dist/qe/acceptance.d.ts.map +1 -1
- package/dist/qe/acceptance.js +60 -61
- package/dist/qe/acceptance.js.map +1 -1
- package/dist/qe/test-sets.d.ts +3 -5
- package/dist/qe/test-sets.d.ts.map +1 -1
- package/dist/qe/test-sets.js +5 -7
- package/dist/qe/test-sets.js.map +1 -1
- package/dist/skills/installed.d.ts +51 -0
- package/dist/skills/installed.d.ts.map +1 -0
- package/dist/skills/installed.js +46 -0
- package/dist/skills/installed.js.map +1 -0
- package/dist/standing-orders/evaluator.d.ts +113 -0
- package/dist/standing-orders/evaluator.d.ts.map +1 -0
- package/dist/standing-orders/evaluator.js +225 -0
- package/dist/standing-orders/evaluator.js.map +1 -0
- package/dist/standing-orders/history.d.ts +58 -0
- package/dist/standing-orders/history.d.ts.map +1 -0
- package/dist/standing-orders/history.js +117 -0
- package/dist/standing-orders/history.js.map +1 -0
- package/dist/standing-orders/parse.d.ts +19 -0
- package/dist/standing-orders/parse.d.ts.map +1 -0
- package/dist/standing-orders/parse.js +75 -0
- package/dist/standing-orders/parse.js.map +1 -0
- package/dist/standing-orders/routes.d.ts +180 -0
- package/dist/standing-orders/routes.d.ts.map +1 -0
- package/dist/standing-orders/routes.js +95 -0
- package/dist/standing-orders/routes.js.map +1 -0
- package/dist/standing-orders/store.d.ts +154 -0
- package/dist/standing-orders/store.d.ts.map +1 -0
- package/dist/standing-orders/store.js +189 -0
- package/dist/standing-orders/store.js.map +1 -0
- package/dist/studio/assets/index-CvV5qITf.css +32 -0
- package/dist/studio/assets/index-jCOy6Ns7.js +568 -0
- package/dist/studio/index.html +3 -3
- package/dist/studio/testid-inventory.json +3274 -894
- package/dist/team/key.d.ts +5 -0
- package/dist/team/key.d.ts.map +1 -0
- package/dist/team/key.js +21 -0
- package/dist/team/key.js.map +1 -0
- package/dist/team/routes.d.ts +196 -0
- package/dist/team/routes.d.ts.map +1 -0
- package/dist/team/routes.js +274 -0
- package/dist/team/routes.js.map +1 -0
- package/dist/team/ws-relay.d.ts +39 -0
- package/dist/team/ws-relay.d.ts.map +1 -0
- package/dist/team/ws-relay.js +63 -0
- package/dist/team/ws-relay.js.map +1 -0
- package/endpoint-manifest.json +502 -6
- package/package.json +6 -6
- package/dist/interactive/demo-events.d.ts +0 -367
- package/dist/interactive/demo-events.d.ts.map +0 -1
- package/dist/interactive/demo-events.js +0 -1293
- package/dist/interactive/demo-events.js.map +0 -1
- package/dist/qe/gate-events.d.ts +0 -113
- package/dist/qe/gate-events.d.ts.map +0 -1
- package/dist/qe/gate-events.js +0 -172
- package/dist/qe/gate-events.js.map +0 -1
- package/dist/studio/assets/index-Bg7Z3BR-.css +0 -32
- package/dist/studio/assets/index-BvOFMjf9.js +0 -554
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE CREW BUS (wicked-core#631) — every bus row in-daemon crew code writes or reads goes through
|
|
3
|
+
* the ENGINE that holds the bus.
|
|
4
|
+
*
|
|
5
|
+
* The daemon's bus file is the engine's (DES-TEAMING-002 T0): the engine opens it once, through its
|
|
6
|
+
* bundled SQLite, and never closes it. A second SQLite library in the same process cannot share that
|
|
7
|
+
* file safely: POSIX locks belong to the process, so two libraries do not exclude each other's
|
|
8
|
+
* writes, and a close in either drops the other's locks (sqlite.org/howtocorrupt.html §2.2.1,
|
|
9
|
+
* F-E2E-021). So crew holds no SQLite library at all. It emits with `Core.busEmit` and reads with
|
|
10
|
+
* `Core.busRead`; the engine is the one writer and the one reader on its bus.
|
|
11
|
+
*
|
|
12
|
+
* The adapter attaches its engine to the bus file it handed it (`attachEngineBus`), and each seam
|
|
13
|
+
* names the bus it uses by path. A seam whose bus no engine holds cannot arm: it throws, and the
|
|
14
|
+
* seam logs and disables itself. tests/bus-no-write.test.ts fails the build if in-daemon code
|
|
15
|
+
* names a SQLite library or wicked-bus.
|
|
16
|
+
*/
|
|
17
|
+
/** The engine's two bus calls (wicked-core-ts `Core.busEmit` / `Core.busRead`). */
|
|
18
|
+
export interface EngineBus {
|
|
19
|
+
busEmit(eventJson: string): Promise<number>;
|
|
20
|
+
busRead(afterId: number, limit: number, typePrefix?: string | null, includeExpired?: boolean | null): Promise<string>;
|
|
21
|
+
}
|
|
22
|
+
/** One row, as wicked-bus `emit` takes it. */
|
|
23
|
+
export interface BusRow {
|
|
24
|
+
event_type: string;
|
|
25
|
+
domain: string;
|
|
26
|
+
subdomain?: string;
|
|
27
|
+
payload: unknown;
|
|
28
|
+
idempotency_key?: string;
|
|
29
|
+
producer_id?: string;
|
|
30
|
+
/** Per-event TTL in whole hours (wicked-bus `emit`'s override); default the bus config's. */
|
|
31
|
+
ttl_hours?: number;
|
|
32
|
+
}
|
|
33
|
+
/** One `events` row as the engine reads it back: every column the file has, `payload` parsed
|
|
34
|
+
* (the stored string when it is not JSON). */
|
|
35
|
+
export interface BusEvent {
|
|
36
|
+
event_id: number;
|
|
37
|
+
event_type: string;
|
|
38
|
+
domain: string;
|
|
39
|
+
subdomain: string;
|
|
40
|
+
payload: unknown;
|
|
41
|
+
idempotency_key: string;
|
|
42
|
+
emitted_at: number;
|
|
43
|
+
[k: string]: unknown;
|
|
44
|
+
}
|
|
45
|
+
/** Test seam only: the bus for a path no engine is attached to (tests/setup/bus-double.ts). */
|
|
46
|
+
export declare const busTesting: {
|
|
47
|
+
unattached: ((dbPath: string) => EngineBus) | undefined;
|
|
48
|
+
};
|
|
49
|
+
/** The engine at `dbPath` serves every seam that names that bus (the adapter, once its engine is up). */
|
|
50
|
+
export declare function attachEngineBus(dbPath: string, engine: EngineBus): void;
|
|
51
|
+
/** Undo {@link attachEngineBus} (the adapter, on close) — only if `engine` is still the one attached. */
|
|
52
|
+
export declare function detachEngineBus(dbPath: string, engine: EngineBus): void;
|
|
53
|
+
/** The resolved path of the bus at `dbPath` when an engine holds it; throws when none does (a seam
|
|
54
|
+
* checks this at arm time, so a seam with no bus disables itself before arming anything). */
|
|
55
|
+
export declare function requireEngineBus(dbPath: string | undefined): string;
|
|
56
|
+
/**
|
|
57
|
+
* Emit one row on the bus at `dbPath`. Resolves to the row's `event_id`; a key already on the bus
|
|
58
|
+
* resolves to the existing row's id (the engine's dedup: success, as wicked-bus's WB-002 was).
|
|
59
|
+
* Rejects when no engine holds the bus or the engine refuses the row (`WB-001 …`).
|
|
60
|
+
*/
|
|
61
|
+
export declare function emitOnBus(dbPath: string, row: BusRow): Promise<number>;
|
|
62
|
+
/**
|
|
63
|
+
* Every row on the bus at `dbPath` whose type starts with `typePrefix`, oldest first. `history:
|
|
64
|
+
* true` includes rows past their TTL: the daemon's bus is never swept, so an expired row is still
|
|
65
|
+
* the record (the activity feed, the team route); a live consumer leaves it off.
|
|
66
|
+
*/
|
|
67
|
+
export declare function readBus(dbPath: string, typePrefix: string, opts?: {
|
|
68
|
+
history?: boolean;
|
|
69
|
+
}): Promise<BusEvent[]>;
|
|
70
|
+
export interface BusTapOptions {
|
|
71
|
+
/** The bus db (the one the daemon handed its engine). */
|
|
72
|
+
dbPath: string | undefined;
|
|
73
|
+
/** `<prefix>.**` or an exact type, optionally `@<domain>` (`wicked.interactive.**`, `wicked.qe.**`, …). */
|
|
74
|
+
filter: string;
|
|
75
|
+
/** Poll cadence, ms. */
|
|
76
|
+
pollIntervalMs?: number | undefined;
|
|
77
|
+
/** Called once per matching row, in order; awaited before the next row. */
|
|
78
|
+
handler: (event: BusEvent) => void | Promise<void>;
|
|
79
|
+
/** A failed read (`event` null) or a failed handler (the row). Never retried; the cursor moves on. */
|
|
80
|
+
onError?: ((err: Error, event?: BusEvent | null) => void) | undefined;
|
|
81
|
+
}
|
|
82
|
+
export interface BusTap {
|
|
83
|
+
/** The bus file this tap reads. */
|
|
84
|
+
readonly dbPath: string;
|
|
85
|
+
/** Stop polling; resolves once an in-flight handler has returned. */
|
|
86
|
+
stop(): Promise<void>;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Arm a tap: poll the engine's bus from its newest row (rows already on the bus are history, as
|
|
90
|
+
* wicked-bus's `latest` cursor treated them), cursor in memory, handing each matching row to the
|
|
91
|
+
* handler in order. Rejects when no engine holds the bus or the filter is not one crew supports
|
|
92
|
+
* (the caller logs and disables its seam); a failed read goes to `onError` and the next poll
|
|
93
|
+
* retries it. A
|
|
94
|
+
* restart starts at the newest row again, so rows emitted while the daemon was down are not
|
|
95
|
+
* delivered; a failed handler is not retried. A bus file replaced under the same path is followed:
|
|
96
|
+
* the engine answers cursor 0 and the tap reads the new file from its first row.
|
|
97
|
+
*/
|
|
98
|
+
export declare function tapBus(opts: BusTapOptions): Promise<BusTap>;
|
|
99
|
+
//# sourceMappingURL=bus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bus.d.ts","sourceRoot":"","sources":["../../src/core/bus.ts"],"names":[],"mappings":"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"}
|
package/dist/core/bus.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE CREW BUS (wicked-core#631) — every bus row in-daemon crew code writes or reads goes through
|
|
3
|
+
* the ENGINE that holds the bus.
|
|
4
|
+
*
|
|
5
|
+
* The daemon's bus file is the engine's (DES-TEAMING-002 T0): the engine opens it once, through its
|
|
6
|
+
* bundled SQLite, and never closes it. A second SQLite library in the same process cannot share that
|
|
7
|
+
* file safely: POSIX locks belong to the process, so two libraries do not exclude each other's
|
|
8
|
+
* writes, and a close in either drops the other's locks (sqlite.org/howtocorrupt.html §2.2.1,
|
|
9
|
+
* F-E2E-021). So crew holds no SQLite library at all. It emits with `Core.busEmit` and reads with
|
|
10
|
+
* `Core.busRead`; the engine is the one writer and the one reader on its bus.
|
|
11
|
+
*
|
|
12
|
+
* The adapter attaches its engine to the bus file it handed it (`attachEngineBus`), and each seam
|
|
13
|
+
* names the bus it uses by path. A seam whose bus no engine holds cannot arm: it throws, and the
|
|
14
|
+
* seam logs and disables itself. tests/bus-no-write.test.ts fails the build if in-daemon code
|
|
15
|
+
* names a SQLite library or wicked-bus.
|
|
16
|
+
*/
|
|
17
|
+
import { resolve } from 'node:path';
|
|
18
|
+
/** Rows per read: a burst drains over a few polls instead of one unbounded read. */
|
|
19
|
+
const BATCH = 500;
|
|
20
|
+
const engines = new Map();
|
|
21
|
+
/** Test seam only: the bus for a path no engine is attached to (tests/setup/bus-double.ts). */
|
|
22
|
+
export const busTesting = {
|
|
23
|
+
unattached: undefined,
|
|
24
|
+
};
|
|
25
|
+
/** The engine at `dbPath` serves every seam that names that bus (the adapter, once its engine is up). */
|
|
26
|
+
export function attachEngineBus(dbPath, engine) {
|
|
27
|
+
engines.set(resolve(dbPath), engine);
|
|
28
|
+
}
|
|
29
|
+
/** Undo {@link attachEngineBus} (the adapter, on close) — only if `engine` is still the one attached. */
|
|
30
|
+
export function detachEngineBus(dbPath, engine) {
|
|
31
|
+
const key = resolve(dbPath);
|
|
32
|
+
if (engines.get(key) === engine)
|
|
33
|
+
engines.delete(key);
|
|
34
|
+
}
|
|
35
|
+
/** The resolved path of the bus at `dbPath` when an engine holds it; throws when none does (a seam
|
|
36
|
+
* checks this at arm time, so a seam with no bus disables itself before arming anything). */
|
|
37
|
+
export function requireEngineBus(dbPath) {
|
|
38
|
+
engineFor(dbPath);
|
|
39
|
+
return resolve(dbPath);
|
|
40
|
+
}
|
|
41
|
+
/** The engine holding the bus at `dbPath`; throws when there is none. */
|
|
42
|
+
function engineFor(dbPath) {
|
|
43
|
+
if (dbPath === undefined)
|
|
44
|
+
throw new Error('no bus named (the daemon hands each seam its engine bus)');
|
|
45
|
+
const key = resolve(dbPath);
|
|
46
|
+
const engine = engines.get(key) ?? busTesting.unattached?.(key);
|
|
47
|
+
if (engine === undefined) {
|
|
48
|
+
throw new Error(`no engine holds the bus at ${key} (the engine was handed no bus, or another one)`);
|
|
49
|
+
}
|
|
50
|
+
return engine;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Emit one row on the bus at `dbPath`. Resolves to the row's `event_id`; a key already on the bus
|
|
54
|
+
* resolves to the existing row's id (the engine's dedup: success, as wicked-bus's WB-002 was).
|
|
55
|
+
* Rejects when no engine holds the bus or the engine refuses the row (`WB-001 …`).
|
|
56
|
+
*/
|
|
57
|
+
export async function emitOnBus(dbPath, row) {
|
|
58
|
+
return engineFor(dbPath).busEmit(JSON.stringify(row));
|
|
59
|
+
}
|
|
60
|
+
/** One page of rows after `afterId` whose type starts with `typePrefix` (live ones unless
|
|
61
|
+
* `includeExpired`). */
|
|
62
|
+
async function readPage(engine, afterId, typePrefix, includeExpired = false) {
|
|
63
|
+
return JSON.parse(await engine.busRead(afterId, BATCH, typePrefix, includeExpired));
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Every row on the bus at `dbPath` whose type starts with `typePrefix`, oldest first. `history:
|
|
67
|
+
* true` includes rows past their TTL: the daemon's bus is never swept, so an expired row is still
|
|
68
|
+
* the record (the activity feed, the team route); a live consumer leaves it off.
|
|
69
|
+
*/
|
|
70
|
+
export async function readBus(dbPath, typePrefix, opts = {}) {
|
|
71
|
+
const engine = engineFor(dbPath);
|
|
72
|
+
const out = [];
|
|
73
|
+
for (let after = 0;;) {
|
|
74
|
+
const page = await readPage(engine, after, typePrefix, opts.history === true);
|
|
75
|
+
out.push(...page.rows);
|
|
76
|
+
if (page.rows.length < BATCH || page.next <= after)
|
|
77
|
+
return out;
|
|
78
|
+
after = page.next;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* A tap filter: `<prefix>.**` (every type under the prefix) or `<type>` (exactly that type), either
|
|
83
|
+
* with an optional `@<domain>` (only that publisher) — the two wicked-bus filter forms crew's seams
|
|
84
|
+
* use, meaning what they mean to wicked-bus `matchesFilter`. Any other form throws at arm.
|
|
85
|
+
*/
|
|
86
|
+
function compileFilter(filter) {
|
|
87
|
+
const at = filter.indexOf('@');
|
|
88
|
+
const type = at === -1 ? filter : filter.slice(0, at);
|
|
89
|
+
const domain = at === -1 ? '' : filter.slice(at + 1);
|
|
90
|
+
const ofDomain = (e) => domain === '' || e.domain === domain;
|
|
91
|
+
if (type.endsWith('.**') && !type.slice(0, -3).includes('*')) {
|
|
92
|
+
const typePrefix = type.slice(0, -2);
|
|
93
|
+
return { typePrefix, matches: (e) => ofDomain(e) && e.event_type.length > typePrefix.length };
|
|
94
|
+
}
|
|
95
|
+
if (type !== '' && !type.includes('*')) {
|
|
96
|
+
return { typePrefix: type, matches: (e) => ofDomain(e) && e.event_type === type };
|
|
97
|
+
}
|
|
98
|
+
throw new Error(`unsupported bus filter ${JSON.stringify(filter)} (use <prefix>.** or an exact type, optionally @<domain>)`);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Arm a tap: poll the engine's bus from its newest row (rows already on the bus are history, as
|
|
102
|
+
* wicked-bus's `latest` cursor treated them), cursor in memory, handing each matching row to the
|
|
103
|
+
* handler in order. Rejects when no engine holds the bus or the filter is not one crew supports
|
|
104
|
+
* (the caller logs and disables its seam); a failed read goes to `onError` and the next poll
|
|
105
|
+
* retries it. A
|
|
106
|
+
* restart starts at the newest row again, so rows emitted while the daemon was down are not
|
|
107
|
+
* delivered; a failed handler is not retried. A bus file replaced under the same path is followed:
|
|
108
|
+
* the engine answers cursor 0 and the tap reads the new file from its first row.
|
|
109
|
+
*/
|
|
110
|
+
export async function tapBus(opts) {
|
|
111
|
+
const engine = engineFor(opts.dbPath);
|
|
112
|
+
const dbPath = resolve(opts.dbPath);
|
|
113
|
+
const { typePrefix, matches } = compileFilter(opts.filter);
|
|
114
|
+
let stopped = false;
|
|
115
|
+
let inFlight = null;
|
|
116
|
+
const report = (err, event) => {
|
|
117
|
+
opts.onError?.(err instanceof Error ? err : new Error(String(err)), event);
|
|
118
|
+
};
|
|
119
|
+
// Where the tap starts: the bus tail as of arming. `null` until that read succeeds — a failed
|
|
120
|
+
// first read is reported and retried by the next poll, never a guessed start.
|
|
121
|
+
let cursor = null;
|
|
122
|
+
const start = async () => {
|
|
123
|
+
try {
|
|
124
|
+
cursor = JSON.parse(await engine.busRead(0, 0, null)).next;
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
report(err, null);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
await start();
|
|
131
|
+
const poll = async () => {
|
|
132
|
+
if (cursor === null)
|
|
133
|
+
return start();
|
|
134
|
+
let page;
|
|
135
|
+
try {
|
|
136
|
+
page = await readPage(engine, cursor, typePrefix);
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
report(err, null);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
for (const row of page.rows) {
|
|
143
|
+
if (stopped)
|
|
144
|
+
return;
|
|
145
|
+
cursor = row.event_id;
|
|
146
|
+
if (!matches(row))
|
|
147
|
+
continue;
|
|
148
|
+
try {
|
|
149
|
+
await opts.handler(row);
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
report(err, row);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (!stopped)
|
|
156
|
+
cursor = page.next;
|
|
157
|
+
};
|
|
158
|
+
const timer = setInterval(() => {
|
|
159
|
+
if (stopped || inFlight !== null)
|
|
160
|
+
return;
|
|
161
|
+
inFlight = poll().finally(() => {
|
|
162
|
+
inFlight = null;
|
|
163
|
+
});
|
|
164
|
+
}, opts.pollIntervalMs ?? 2000);
|
|
165
|
+
timer.unref();
|
|
166
|
+
return {
|
|
167
|
+
dbPath,
|
|
168
|
+
stop: async () => {
|
|
169
|
+
stopped = true;
|
|
170
|
+
clearInterval(timer);
|
|
171
|
+
if (inFlight !== null)
|
|
172
|
+
await inFlight;
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=bus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bus.js","sourceRoot":"","sources":["../../src/core/bus.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WHAT THE DELIVER PUSH LEAVES BEHIND — the crew#434 classifier, as one reusable predicate.
|
|
3
|
+
*
|
|
4
|
+
* The rules themselves are not new: they have run inside `deliverPrScript`'s generated bash since
|
|
5
|
+
* crew#434 (an untracked candidate is staged UNLESS it looks like scratch or key material, and
|
|
6
|
+
* every exclusion is printed with its reason). What is new is that they are now readable from
|
|
7
|
+
* TypeScript, because a second consumer needs the SAME answer.
|
|
8
|
+
*
|
|
9
|
+
* ## Why (F3, ship-proof C7)
|
|
10
|
+
*
|
|
11
|
+
* The deliver gate's consent diffstat is computed from `GET /runs/:id/diff`, whose untracked pass
|
|
12
|
+
* appended every non-ignored untracked path as an all-addition hunk. The push does not carry every
|
|
13
|
+
* non-ignored untracked path. On a run whose creator left a `tmp/` behind, the gate read
|
|
14
|
+
* **"109 files changed, +258, -2"** and the commit pushed **4 files, +47, -2** — 27x over, on the
|
|
15
|
+
* one gate with an irreversible external side effect. The script printed
|
|
16
|
+
* `deliver: EXCLUDED (scratch-dir): tmp/ (105 files)`, so the exclusion applied to the push and
|
|
17
|
+
* not to the number the operator approved.
|
|
18
|
+
*
|
|
19
|
+
* The number on a consent surface has to be the number that ships, so the diff the gate reads now
|
|
20
|
+
* runs this classifier over its untracked candidates.
|
|
21
|
+
*
|
|
22
|
+
* ## Drift
|
|
23
|
+
*
|
|
24
|
+
* There are necessarily TWO implementations — this one runs in the daemon, the other is generated
|
|
25
|
+
* bash running in the run worktree — and only one of them decides what is actually pushed. The
|
|
26
|
+
* shell is therefore the source of truth and this module tracks it; they are pinned together by
|
|
27
|
+
* `tests/deliver-gate-diffstat.test.ts`, which runs the REAL script over a fixture tree and
|
|
28
|
+
* requires the committed set to equal the set this function keeps.
|
|
29
|
+
*
|
|
30
|
+
* It is a GUARD, NOT A SILENT DROP: the script still prints every excluded path with its reason
|
|
31
|
+
* into the phase output (retained and served on the run wire), and this module only changes which
|
|
32
|
+
* files a *preview* of the push counts.
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* The deliver script's untracked RECOVERY SENTINEL (crew#432): a failed push leaves this empty file
|
|
36
|
+
* at the worktree root so the engine's terminal reap never removes a worktree whose work was
|
|
37
|
+
* committed but not delivered, and the next attempt removes it before staging. It is never part of
|
|
38
|
+
* the push, so it is never part of the consent diffstat either (N2, ship re-proof): the retry gate
|
|
39
|
+
* read "5 files changed" for a commit of 4 because this predicate did not know the name. The
|
|
40
|
+
* script's `S=` line is generated FROM this constant, so the name cannot drift between the two.
|
|
41
|
+
*/
|
|
42
|
+
export declare const DELIVER_STRANDED_SENTINEL = ".wicked-crew-delivery-stranded";
|
|
43
|
+
/** Past this, an otherwise-unrecognised file is scratch by size alone (the generic net). */
|
|
44
|
+
export declare const OVERSIZE_BYTES = 1048576;
|
|
45
|
+
/**
|
|
46
|
+
* Why the deliver push would exclude this path on its NAME alone — the arms that need no `stat`:
|
|
47
|
+
* the denylist, the `socket` basename, `.DS_Store`, and a scratch directory at any depth. `null`
|
|
48
|
+
* means "no name rule fires"; the caller still owes the size rule ({@link deliverExclusionReason}).
|
|
49
|
+
*
|
|
50
|
+
* Split out so a caller can classify 100 000 untracked paths without 100 000 synchronous `stat`
|
|
51
|
+
* calls on the daemon's event loop (codex review of the F3 PR, MEDIUM): only a path that survives
|
|
52
|
+
* every name rule is ever stat'd, and under a scratch directory none of them are.
|
|
53
|
+
*
|
|
54
|
+
* `relPath` is repo-relative with `/` separators — git's own spelling, which
|
|
55
|
+
* `git status --porcelain -z` and `git ls-files -z` emit on every platform.
|
|
56
|
+
*
|
|
57
|
+
* The order of the arms is the script's order, and it matters: a `tmp/x.db` reports
|
|
58
|
+
* `denylisted-name`, exactly as the shell's `[ -n "$RN" ] ||` guards do.
|
|
59
|
+
*/
|
|
60
|
+
export declare function deliverExclusionByName(relPath: string): string | null;
|
|
61
|
+
/**
|
|
62
|
+
* Why the deliver push would EXCLUDE this untracked path, or `null` when it rides — the whole
|
|
63
|
+
* ladder, name rules first and then the size rule.
|
|
64
|
+
*
|
|
65
|
+
* `sizeBytes` is the file's size, or `null` when it could not be stat'd; an unknown size is never
|
|
66
|
+
* treated as oversize (the shell's `wc -c < "$F" 2>/dev/null || echo 0` degrades the same way).
|
|
67
|
+
* A caller that wants to avoid the `stat` for a path a name rule already rejects calls
|
|
68
|
+
* {@link deliverExclusionByName} first.
|
|
69
|
+
*/
|
|
70
|
+
export declare function deliverExclusionReason(relPath: string, sizeBytes: number | null): string | null;
|
|
71
|
+
//# sourceMappingURL=deliver-exclusions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deliver-exclusions.d.ts","sourceRoot":"","sources":["../../src/core/deliver-exclusions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,mCAAmC,CAAC;AAgB1E,4FAA4F;AAC5F,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAerE;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAK/F"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WHAT THE DELIVER PUSH LEAVES BEHIND — the crew#434 classifier, as one reusable predicate.
|
|
3
|
+
*
|
|
4
|
+
* The rules themselves are not new: they have run inside `deliverPrScript`'s generated bash since
|
|
5
|
+
* crew#434 (an untracked candidate is staged UNLESS it looks like scratch or key material, and
|
|
6
|
+
* every exclusion is printed with its reason). What is new is that they are now readable from
|
|
7
|
+
* TypeScript, because a second consumer needs the SAME answer.
|
|
8
|
+
*
|
|
9
|
+
* ## Why (F3, ship-proof C7)
|
|
10
|
+
*
|
|
11
|
+
* The deliver gate's consent diffstat is computed from `GET /runs/:id/diff`, whose untracked pass
|
|
12
|
+
* appended every non-ignored untracked path as an all-addition hunk. The push does not carry every
|
|
13
|
+
* non-ignored untracked path. On a run whose creator left a `tmp/` behind, the gate read
|
|
14
|
+
* **"109 files changed, +258, -2"** and the commit pushed **4 files, +47, -2** — 27x over, on the
|
|
15
|
+
* one gate with an irreversible external side effect. The script printed
|
|
16
|
+
* `deliver: EXCLUDED (scratch-dir): tmp/ (105 files)`, so the exclusion applied to the push and
|
|
17
|
+
* not to the number the operator approved.
|
|
18
|
+
*
|
|
19
|
+
* The number on a consent surface has to be the number that ships, so the diff the gate reads now
|
|
20
|
+
* runs this classifier over its untracked candidates.
|
|
21
|
+
*
|
|
22
|
+
* ## Drift
|
|
23
|
+
*
|
|
24
|
+
* There are necessarily TWO implementations — this one runs in the daemon, the other is generated
|
|
25
|
+
* bash running in the run worktree — and only one of them decides what is actually pushed. The
|
|
26
|
+
* shell is therefore the source of truth and this module tracks it; they are pinned together by
|
|
27
|
+
* `tests/deliver-gate-diffstat.test.ts`, which runs the REAL script over a fixture tree and
|
|
28
|
+
* requires the committed set to equal the set this function keeps.
|
|
29
|
+
*
|
|
30
|
+
* It is a GUARD, NOT A SILENT DROP: the script still prints every excluded path with its reason
|
|
31
|
+
* into the phase output (retained and served on the run wire), and this module only changes which
|
|
32
|
+
* files a *preview* of the push counts.
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* The deliver script's untracked RECOVERY SENTINEL (crew#432): a failed push leaves this empty file
|
|
36
|
+
* at the worktree root so the engine's terminal reap never removes a worktree whose work was
|
|
37
|
+
* committed but not delivered, and the next attempt removes it before staging. It is never part of
|
|
38
|
+
* the push, so it is never part of the consent diffstat either (N2, ship re-proof): the retry gate
|
|
39
|
+
* read "5 files changed" for a commit of 4 because this predicate did not know the name. The
|
|
40
|
+
* script's `S=` line is generated FROM this constant, so the name cannot drift between the two.
|
|
41
|
+
*/
|
|
42
|
+
export const DELIVER_STRANDED_SENTINEL = '.wicked-crew-delivery-stranded';
|
|
43
|
+
/** Basename globs that mean "scratch or key material, never a run's product" (crew#434). */
|
|
44
|
+
const DENYLISTED = [
|
|
45
|
+
/\.db$/, /\.db-wal$/, /\.db-shm$/,
|
|
46
|
+
/\.sqlite$/, /\.sqlite2$/, /\.sqlite3$/, /\.sqlite-wal$/, /\.sqlite-shm$/,
|
|
47
|
+
/\.sock$/, /\.pid$/,
|
|
48
|
+
/\.env$/, /\.env\./, /^\.envrc$/,
|
|
49
|
+
/\.gif$/, /\.webm$/, /\.mp4$/, /\.mov$/,
|
|
50
|
+
/\.pem$/, /\.key$/, /\.p12$/, /\.pfx$/,
|
|
51
|
+
/^id_rsa/, /credentials/,
|
|
52
|
+
];
|
|
53
|
+
/** The scratch/cache directory names the push never carries, at any depth. */
|
|
54
|
+
const SCRATCH_DIRS = ['tmp', '.tmp', 'scratch', '.cache', 'coverage'];
|
|
55
|
+
/** Past this, an otherwise-unrecognised file is scratch by size alone (the generic net). */
|
|
56
|
+
export const OVERSIZE_BYTES = 1048576;
|
|
57
|
+
/**
|
|
58
|
+
* Why the deliver push would exclude this path on its NAME alone — the arms that need no `stat`:
|
|
59
|
+
* the denylist, the `socket` basename, `.DS_Store`, and a scratch directory at any depth. `null`
|
|
60
|
+
* means "no name rule fires"; the caller still owes the size rule ({@link deliverExclusionReason}).
|
|
61
|
+
*
|
|
62
|
+
* Split out so a caller can classify 100 000 untracked paths without 100 000 synchronous `stat`
|
|
63
|
+
* calls on the daemon's event loop (codex review of the F3 PR, MEDIUM): only a path that survives
|
|
64
|
+
* every name rule is ever stat'd, and under a scratch directory none of them are.
|
|
65
|
+
*
|
|
66
|
+
* `relPath` is repo-relative with `/` separators — git's own spelling, which
|
|
67
|
+
* `git status --porcelain -z` and `git ls-files -z` emit on every platform.
|
|
68
|
+
*
|
|
69
|
+
* The order of the arms is the script's order, and it matters: a `tmp/x.db` reports
|
|
70
|
+
* `denylisted-name`, exactly as the shell's `[ -n "$RN" ] ||` guards do.
|
|
71
|
+
*/
|
|
72
|
+
export function deliverExclusionByName(relPath) {
|
|
73
|
+
// The script's own recovery sentinel, at the worktree root only — the shell's first arm.
|
|
74
|
+
if (relPath === DELIVER_STRANDED_SENTINEL)
|
|
75
|
+
return 'delivery-sentinel';
|
|
76
|
+
const base = relPath.slice(relPath.lastIndexOf('/') + 1);
|
|
77
|
+
// The script classifies on a LOWERCASED basename so DEPLOY.KEY / .ENV / SOCKET.PATH cannot
|
|
78
|
+
// bypass the denylist by case (crew#439).
|
|
79
|
+
const lower = base.toLowerCase();
|
|
80
|
+
if (DENYLISTED.some((re) => re.test(lower)))
|
|
81
|
+
return 'denylisted-name';
|
|
82
|
+
if (lower.includes('socket'))
|
|
83
|
+
return 'socket-name';
|
|
84
|
+
// `.DS_Store` is matched on the ORIGINAL basename, as the shell does.
|
|
85
|
+
if (base === '.DS_Store')
|
|
86
|
+
return 'ds-store';
|
|
87
|
+
const segments = relPath.split('/');
|
|
88
|
+
// Every segment BUT the last is a directory of the path (`/$F` against `*/tmp/*` in the shell).
|
|
89
|
+
if (segments.slice(0, -1).some((s) => SCRATCH_DIRS.includes(s)))
|
|
90
|
+
return 'scratch-dir';
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Why the deliver push would EXCLUDE this untracked path, or `null` when it rides — the whole
|
|
95
|
+
* ladder, name rules first and then the size rule.
|
|
96
|
+
*
|
|
97
|
+
* `sizeBytes` is the file's size, or `null` when it could not be stat'd; an unknown size is never
|
|
98
|
+
* treated as oversize (the shell's `wc -c < "$F" 2>/dev/null || echo 0` degrades the same way).
|
|
99
|
+
* A caller that wants to avoid the `stat` for a path a name rule already rejects calls
|
|
100
|
+
* {@link deliverExclusionByName} first.
|
|
101
|
+
*/
|
|
102
|
+
export function deliverExclusionReason(relPath, sizeBytes) {
|
|
103
|
+
const byName = deliverExclusionByName(relPath);
|
|
104
|
+
if (byName !== null)
|
|
105
|
+
return byName;
|
|
106
|
+
if (sizeBytes !== null && sizeBytes > OVERSIZE_BYTES)
|
|
107
|
+
return 'oversize-1mib';
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=deliver-exclusions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deliver-exclusions.js","sourceRoot":"","sources":["../../src/core/deliver-exclusions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,gCAAgC,CAAC;AAE1E,4FAA4F;AAC5F,MAAM,UAAU,GAAG;IACjB,OAAO,EAAE,WAAW,EAAE,WAAW;IACjC,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe;IACzE,SAAS,EAAE,QAAQ;IACnB,QAAQ,EAAE,SAAS,EAAE,WAAW;IAChC,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ;IACvC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ;IACtC,SAAS,EAAE,aAAa;CACzB,CAAC;AAEF,8EAA8E;AAC9E,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;AAEtE,4FAA4F;AAC5F,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AAEtC;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAe;IACpD,yFAAyF;IACzF,IAAI,OAAO,KAAK,yBAAyB;QAAE,OAAO,mBAAmB,CAAC;IACtE,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACzD,2FAA2F;IAC3F,0CAA0C;IAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAAE,OAAO,iBAAiB,CAAC;IACtE,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,aAAa,CAAC;IACnD,sEAAsE;IACtE,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,UAAU,CAAC;IAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpC,gGAAgG;IAChG,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,aAAa,CAAC;IACtF,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAe,EAAE,SAAwB;IAC9E,MAAM,MAAM,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAC/C,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IACnC,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,GAAG,cAAc;QAAE,OAAO,eAAe,CAAC;IAC7E,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -28,8 +28,14 @@
|
|
|
28
28
|
* run either way; only the deliver phase's own commit is guaranteed to match it.
|
|
29
29
|
*/
|
|
30
30
|
import type { GateSpec, PhaseDef, SessionView } from './types.js';
|
|
31
|
-
/**
|
|
32
|
-
|
|
31
|
+
/**
|
|
32
|
+
* The PR title cap — GitHub's own limit (crew#550 P-1: a 72-character cap on the PR title still
|
|
33
|
+
* severed the intent inside a quoted phrase). The COMMIT subject keeps git's conventional width,
|
|
34
|
+
* {@link COMMIT_SUBJECT_MAX}; a longer title then opens the commit body in full.
|
|
35
|
+
*/
|
|
36
|
+
export declare const DELIVER_TITLE_MAX = 256;
|
|
37
|
+
/** The commit subject cap — git's conventional subject width (crew#550). */
|
|
38
|
+
export declare const COMMIT_SUBJECT_MAX = 72;
|
|
33
39
|
/** One phase of the run, with as much as is known about it at composition time. */
|
|
34
40
|
export interface DeliverPhaseFact {
|
|
35
41
|
id: string;
|
|
@@ -89,9 +95,16 @@ export interface DeliverTextFacts {
|
|
|
89
95
|
number: number;
|
|
90
96
|
url: string;
|
|
91
97
|
} | null;
|
|
98
|
+
/** crew#550: extra git trailers for the commit (`Co-Authored-By: …`), from
|
|
99
|
+
* {@link DELIVER_TRAILERS_ENV}; absent/empty = only the `Delivered-By:` trailer. */
|
|
100
|
+
trailers?: string[];
|
|
101
|
+
/** crew#550 P-7: the follow-ups the evaluator flagged (its `FOLLOW-UPS:` block, read from the
|
|
102
|
+
* evaluator units' output by {@link extractFollowUps}). `[]` = read, none flagged; absent = not
|
|
103
|
+
* read (a definition-time composition), and the section is left out. */
|
|
104
|
+
followUps?: string[];
|
|
92
105
|
}
|
|
93
106
|
export interface DeliverText {
|
|
94
|
-
/** ≤ {@link DELIVER_TITLE_MAX} characters, one line, never cut mid-word. */
|
|
107
|
+
/** The PR title: ≤ {@link DELIVER_TITLE_MAX} characters, one line, never cut mid-word. */
|
|
95
108
|
title: string;
|
|
96
109
|
/** Markdown; never empty. */
|
|
97
110
|
body: string;
|
|
@@ -110,7 +123,7 @@ export interface IssueRefs {
|
|
|
110
123
|
export declare function conventionalPrefix(workflowId: string | null | undefined): string;
|
|
111
124
|
/**
|
|
112
125
|
* The PR title / commit subject: the intent's first line, whole when it fits, otherwise cut at the
|
|
113
|
-
* last word boundary that leaves room for a single `…` — so the result is ≤
|
|
126
|
+
* last word boundary that leaves room for a single `…` — so the result is ≤ 256 characters and never
|
|
114
127
|
* ends mid-word (the F-3R2-014 headline `…scenario CLN-2) aga`). Dangling punctuation before the
|
|
115
128
|
* ellipsis is dropped. A blank intent names the run instead — through the SAME bounded cut, so a
|
|
116
129
|
* long caller-supplied session id (the CLI passes `--session` through) is never cut mid-id either
|
|
@@ -118,13 +131,19 @@ export declare function conventionalPrefix(workflowId: string | null | undefined
|
|
|
118
131
|
*/
|
|
119
132
|
export declare function deliverTitle(intent: string, runId: string, workflowId?: string | null): string;
|
|
120
133
|
/**
|
|
121
|
-
* `line` whole when it fits, else cut at a word boundary with a single `…` — ≤
|
|
134
|
+
* `line` whole when it fits, else cut at a word boundary with a single `…` — ≤ `max` characters —
|
|
122
135
|
* choosing the LAST boundary at nesting depth 0: never inside a quoted or bracketed phrase (crew#550
|
|
123
136
|
* P-1: `… truncated at '(Failed):' and 'sign a seat…`). A straight apostrophe opens a quote only
|
|
124
137
|
* after a space or at the start (so `daemon's` is a word, not a quote). When no depth-0 boundary
|
|
125
138
|
* exists inside the room, any word boundary is taken; a single 72+ character token is cut hard.
|
|
126
139
|
*/
|
|
127
|
-
export declare function boundedTitle(line: string): string;
|
|
140
|
+
export declare function boundedTitle(line: string, max?: number): string;
|
|
141
|
+
/**
|
|
142
|
+
* The commit subject for a PR title (crew#550): the title itself when it fits git's 72-character
|
|
143
|
+
* subject width, else the same depth-aware word-boundary cut at 72. The deliver script puts the
|
|
144
|
+
* full title at the top of the commit body whenever the two differ.
|
|
145
|
+
*/
|
|
146
|
+
export declare function commitSubject(title: string): string;
|
|
128
147
|
/**
|
|
129
148
|
* The issues the intent names, split into the ones it says it fixes and the rest.
|
|
130
149
|
*
|
|
@@ -134,7 +153,7 @@ export declare function boundedTitle(line: string): string;
|
|
|
134
153
|
* on a wicked-studio delivery must close #214). Any other owner-less `repo#N` rides verbatim as
|
|
135
154
|
* information; `owner/repo#N` is left exactly as written.
|
|
136
155
|
*/
|
|
137
|
-
export declare function issueRefs(
|
|
156
|
+
export declare function issueRefs(rawIntent: string, repoRef?: string | null): IssueRefs;
|
|
138
157
|
/**
|
|
139
158
|
* How much of the intent the deliver SCRIPT carries in its embedded fallback text. The script is
|
|
140
159
|
* one `bash -lc` argument, and `LaunchSchema.problem` has no length cap, so an unbounded intent
|
|
@@ -184,10 +203,9 @@ export declare function baseWorkflowId(workflowId: string, runId: string): strin
|
|
|
184
203
|
* The facts from a persisted run view — what the daemon answers on `GET /runs/:id/deliver-text`.
|
|
185
204
|
* The deliver phase itself (running while it asks) is listed as `this PR`.
|
|
186
205
|
*
|
|
187
|
-
* `resolved.workflowId` is the
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
* `workflow wf-…` here. Absent, the view's id is used (with the per-run composition suffix cut).
|
|
206
|
+
* `resolved.workflowId` is the run's preset or workflow NAME the route resolved from the engine's
|
|
207
|
+
* record (`runIdentityOf`, seam X2) — `null` for a user plan or a free-text run, which names no
|
|
208
|
+
* workflow. Absent (`undefined`), the view's id is used (with the per-run composition suffix cut).
|
|
191
209
|
*/
|
|
192
210
|
export declare function factsFromRun(view: SessionView, runUrl: string | null, resolved?: {
|
|
193
211
|
workflowId?: string | null;
|
|
@@ -195,6 +213,8 @@ export declare function factsFromRun(view: SessionView, runUrl: string | null, r
|
|
|
195
213
|
number: number;
|
|
196
214
|
url: string;
|
|
197
215
|
} | null;
|
|
216
|
+
/** crew#550: the evaluator follow-ups, when the caller read the evaluator units' output. */
|
|
217
|
+
followUps?: string[];
|
|
198
218
|
}): DeliverTextFacts;
|
|
199
219
|
/** What is known at LAUNCH, from the workflow definition — the script's embedded fallback. */
|
|
200
220
|
export declare function factsFromWorkflow(input: {
|
|
@@ -209,6 +229,22 @@ export declare function factsFromWorkflow(input: {
|
|
|
209
229
|
url: string;
|
|
210
230
|
} | null;
|
|
211
231
|
}): DeliverTextFacts;
|
|
232
|
+
/**
|
|
233
|
+
* The environment variable naming extra commit trailers for delivered work (crew#550), one per
|
|
234
|
+
* line — e.g. `Co-Authored-By: Name <address>`. Only well-formed single-line `Token: value`
|
|
235
|
+
* trailers are kept; anything else is dropped rather than breaking the commit's trailer block.
|
|
236
|
+
*/
|
|
237
|
+
export declare const DELIVER_TRAILERS_ENV = "WICKED_CREW_DELIVER_TRAILERS";
|
|
238
|
+
/** The configured trailers, validated; `[]` when none. */
|
|
239
|
+
export declare function configuredTrailers(env?: NodeJS.ProcessEnv): string[];
|
|
240
|
+
/**
|
|
241
|
+
* The environment variable naming the PUBLIC origin a PR's run link may use (crew#550 P-2) — the
|
|
242
|
+
* studio address a reviewer can open (`https://studio.example.com`). Unset, a PR body names the run
|
|
243
|
+
* id and carries no link: the daemon's own loopback address opens only on the daemon's host.
|
|
244
|
+
*/
|
|
245
|
+
export declare const PUBLIC_ORIGIN_ENV = "WICKED_CREW_PUBLIC_ORIGIN";
|
|
246
|
+
/** The configured public origin, or `null`. */
|
|
247
|
+
export declare function configuredPublicOrigin(env?: NodeJS.ProcessEnv): string | null;
|
|
212
248
|
/**
|
|
213
249
|
* `s` as ONE URL path segment, RFC 3986 strict: everything but unreserved characters is
|
|
214
250
|
* percent-encoded — `encodeURIComponent` alone leaves `!'()*` alone, and `'` in particular must not
|
|
@@ -216,9 +252,20 @@ export declare function factsFromWorkflow(input: {
|
|
|
216
252
|
*/
|
|
217
253
|
export declare function urlPathSegment(s: string): string;
|
|
218
254
|
/**
|
|
219
|
-
* The
|
|
220
|
-
* null
|
|
221
|
-
*
|
|
255
|
+
* The run link for a PR body under the configured PUBLIC origin ({@link configuredPublicOrigin}),
|
|
256
|
+
* or null (crew#550 P-2). Never a loopback URL: `http://127.0.0.1:<port>/runs/<id>` opens only on
|
|
257
|
+
* the daemon's own host, so a PR carrying it gave every other reader a dead link. A loopback,
|
|
258
|
+
* unparseable or non-http(s) origin yields no link; the run id itself is always named in the text.
|
|
222
259
|
*/
|
|
223
260
|
export declare function runUrlFor(origin: string | null | undefined, runId: string): string | null;
|
|
261
|
+
/** At most this many follow-ups ride a PR body; each is cut to {@link FOLLOW_UP_MAX_CHARS}. */
|
|
262
|
+
export declare const FOLLOW_UPS_MAX = 10;
|
|
263
|
+
export declare const FOLLOW_UP_MAX_CHARS = 300;
|
|
264
|
+
/**
|
|
265
|
+
* The follow-ups an evaluator's output flags (crew#550 P-7): the list under its `FOLLOW-UPS:`
|
|
266
|
+
* heading (or the heading line's own text), ending at the first line that is neither an item nor
|
|
267
|
+
* the continuation of one. `none` / `n/a` yields nothing. Every block in the text is read, in order,
|
|
268
|
+
* de-duplicated, capped at {@link FOLLOW_UPS_MAX}.
|
|
269
|
+
*/
|
|
270
|
+
export declare function extractFollowUps(text: string): string[];
|
|
224
271
|
//# sourceMappingURL=deliver-text.d.ts.map
|