@descryy/runtime-contracts 0.2.0 → 0.3.1

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/LICENSE ADDED
@@ -0,0 +1,6 @@
1
+ Copyright (c) Descry
2
+
3
+ All rights reserved. This software is proprietary and confidential.
4
+ No license, express or implied, to reproduce, distribute, modify, or
5
+ create derivative works is granted except as explicitly agreed in
6
+ writing.
@@ -1,19 +1,11 @@
1
1
  /**
2
- * Capability model.
2
+ * Capability model: `{ availability, reason }` per capability, per
3
+ * §16 (runtime capability model), §10.3 (environment tiers), §16.3
4
+ * (fidelity levels).
3
5
  *
4
- * Purpose and shape (`{ availability, reason }` per capability, so the AI
5
- * planner reads realistic answers like `distributedTrace: unavailable`
6
- * instead of a silent gap) come from `documents/descry-runtime-plan.md`
7
- * §16 (Runtime capability model). Environment/fidelity concepts are
8
- * grounded in the architecture doc's §10.3 (environment tiers: CI-attached
9
- * → preview → container → API-only → static-only) and §16.3 (fidelity
10
- * levels 1-4: stub, real+disposable DB, real+recordings, real staging).
11
- *
12
- * The point of this file: `distributedTrace: unavailable` must be a
13
- * first-class, structured answer the AI planner can read — never an absent
14
- * field, never a thrown error, never a silent gap that reads as "not
15
- * checked" only after something downstream fails to find data. Absence is
16
- * data, and this contract makes it representable.
6
+ * `distributedTrace: unavailable` must be a first-class structured answer
7
+ * the AI planner can read — never an absent field, thrown error, or silent
8
+ * gap. Absence is data.
17
9
  */
18
10
  export declare const ENVIRONMENT_TIERS: readonly ["tier-0-ci-attached", "tier-1-preview", "tier-2-container", "tier-2b-api-only", "tier-3-static-only"];
19
11
  export type EnvironmentTier = (typeof ENVIRONMENT_TIERS)[number];
@@ -45,64 +37,26 @@ export interface CollectorCapabilities {
45
37
  /** Whether stack capture is possible at all, independent of whether the runtime's concurrency model fragments it — ties to StackFidelity in evidence.ts. */
46
38
  readonly stackCapture: CapabilityStatus;
47
39
  /**
48
- * Whether this collector observes **process lifecycle** — spawn, ready,
49
- * exit — as `PROCESS_STARTED` / `PROCESS_READY` / `PROCESS_EXITED`.
50
- *
51
- * **Added because its absence produced an actively wrong report.** The
52
- * seven fields above are all DOM, console, network, log, trace, mapping
53
- * and stack; none describes watching a process. So `ProcessCollector`
54
- * (RT-053) — a collector doing its job correctly — had no honest way to
55
- * say what it does, and reported `unavailable` on all seven with real
56
- * reasons. Every reason was true and the overall picture was false: a
57
- * healthy collector reading as one that can do nothing.
58
- *
59
- * That is §22's own distinction inverted. The section exists to keep
60
- * "unsupported" from being read as "no failure"; a capability model with
61
- * no field for a real capability produces the mirror image — **"we
62
- * cannot" reported by something that can.** The lane that hit it declined
63
- * to invent a field and flagged it instead, which was right; the fix
64
- * belongs in the contract, not in a collector working around the
65
- * contract.
40
+ * Observes process lifecycle (`PROCESS_STARTED`/`READY`/`EXITED`). Added
41
+ * (RT-053) because without it a healthy `ProcessCollector` reported
42
+ * `unavailable` on all seven other fields — every reason true, overall
43
+ * picture false.
66
44
  */
67
45
  readonly processLifecycle: CapabilityStatus;
68
46
  /**
69
- * Whether this collector observes **database queries** — `DATABASE_QUERY`
70
- * evidence, via real driver instrumentation (`node:sqlite` today,
71
- * RT-141) — as opposed to inferring them from logs.
72
- *
73
- * **The same gap `processLifecycle` closed, reopened by §18.** RT-141
74
- * built a real `DatabaseQueryCollector` and it had no honest field to
75
- * report itself in — every one of the eight fields above is DOM,
76
- * console, network, log, trace, mapping, stack or process; none
77
- * describes watching a database driver. Deferred at the time (RT-142)
78
- * with an explicit trigger — "lanes converge, no collector work in
79
- * flight" — because a field with no consumer is exactly the shape that
80
- * drifts, and this repo's rule is to land a capability field in the same
81
- * change as its first real collector, not ahead of it (§18's own
82
- * `TEST_SKIPPED`/`DATABASE_QUERY` precedent, `runtime-event.ts`). Closed
83
- * now (RT-146) alongside `externalServiceObservation`, together with
84
- * §18's other collector.
47
+ * Observes database queries (`DATABASE_QUERY`, via real `node:sqlite`
48
+ * instrumentation, RT-141) rather than inferring from logs. Same gap as
49
+ * `processLifecycle`; closed at RT-146 alongside `externalServiceObservation`.
85
50
  */
86
51
  readonly databaseObservation: CapabilityStatus;
87
52
  /**
88
- * Whether this collector observes **outbound requests to external
89
- * services** — `EXTERNAL_REQUEST` evidence, via real client
90
- * instrumentation (`fetch`, RT-146) — the process-initiated counterpart
91
- * to `databaseObservation` above, added in the same change for the same
92
- * reason.
93
- *
94
- * **Deliberately distinct from `networkObservation`, not a widening of
95
- * it.** Every existing claimant of `networkObservation` is
96
- * `BrowserNetworkCollector` — browser-page-originated requests captured
97
- * through Playwright's own request/response events. A backend process's
98
- * own outbound `fetch()` calls are a different mechanism (driver
99
- * instrumentation, not a browser event stream) observing a different
100
- * thing (server-to-service traffic, not page-to-server traffic) — the
101
- * §6/§18 split this file's own checklist already keeps apart. Folding
102
- * this into `networkObservation` would make an execution with only an
103
- * external-request collector report `networkObservation: available` and
104
- * mislead a reader into expecting browser network evidence that was
105
- * never captured.
53
+ * Observes outbound requests to external services (`EXTERNAL_REQUEST`,
54
+ * `fetch` instrumentation, RT-146) — process-initiated counterpart to
55
+ * `databaseObservation`. Distinct from `networkObservation`, whose only
56
+ * claimant (`BrowserNetworkCollector`) captures page-originated requests
57
+ * via Playwright — different mechanism, different traffic. Folding this
58
+ * in would make an external-request-only execution falsely report
59
+ * `networkObservation: available`.
106
60
  */
107
61
  readonly externalServiceObservation: CapabilityStatus;
108
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,eAAO,MAAM,iBAAiB,iHAMpB,CAAC;AACX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE,eAAO,MAAM,eAAe,uBAAwB,CAAC;AACrD,wIAAwI;AACxI,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,eAAO,MAAM,uBAAuB,mDAAoD,CAAC;AACzF,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,YAAY,EAAE,sBAAsB,CAAC;IAC9C,0HAA0H;IAC1H,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAEzE;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,cAAc,EAAE,gBAAgB,CAAC;IAC1C,QAAQ,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;IAC9C,QAAQ,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;IAC9C,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,2IAA2I;IAC3I,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,mIAAmI;IACnI,QAAQ,CAAC,aAAa,EAAE,gBAAgB,CAAC;IACzC,4JAA4J;IAC5J,QAAQ,CAAC,YAAY,EAAE,gBAAgB,CAAC;IACxC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAE5C;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,mBAAmB,EAAE,gBAAgB,CAAC;IAE/C;;;;;;;;;;;;;;;;;;;OAmBG;IACH,QAAQ,CAAC,0BAA0B,EAAE,gBAAgB,CAAC;CACvD;AAED,8HAA8H;AAC9H,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,UAAU,EAAE,SAAS;QAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAC;KAC9C,EAAE,CAAC;CACL"}
1
+ {"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,iBAAiB,iHAMpB,CAAC;AACX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE,eAAO,MAAM,eAAe,uBAAwB,CAAC;AACrD,wIAAwI;AACxI,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,eAAO,MAAM,uBAAuB,mDAAoD,CAAC;AACzF,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,YAAY,EAAE,sBAAsB,CAAC;IAC9C,0HAA0H;IAC1H,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAEzE;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,cAAc,EAAE,gBAAgB,CAAC;IAC1C,QAAQ,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;IAC9C,QAAQ,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;IAC9C,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,2IAA2I;IAC3I,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,mIAAmI;IACnI,QAAQ,CAAC,aAAa,EAAE,gBAAgB,CAAC;IACzC,4JAA4J;IAC5J,QAAQ,CAAC,YAAY,EAAE,gBAAgB,CAAC;IACxC;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAE5C;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,EAAE,gBAAgB,CAAC;IAE/C;;;;;;;;OAQG;IACH,QAAQ,CAAC,0BAA0B,EAAE,gBAAgB,CAAC;CACvD;AAED,8HAA8H;AAC9H,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,UAAU,EAAE,SAAS;QAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAC;KAC9C,EAAE,CAAC;CACL"}
@@ -1,19 +1,11 @@
1
1
  /**
2
- * Capability model.
2
+ * Capability model: `{ availability, reason }` per capability, per
3
+ * §16 (runtime capability model), §10.3 (environment tiers), §16.3
4
+ * (fidelity levels).
3
5
  *
4
- * Purpose and shape (`{ availability, reason }` per capability, so the AI
5
- * planner reads realistic answers like `distributedTrace: unavailable`
6
- * instead of a silent gap) come from `documents/descry-runtime-plan.md`
7
- * §16 (Runtime capability model). Environment/fidelity concepts are
8
- * grounded in the architecture doc's §10.3 (environment tiers: CI-attached
9
- * → preview → container → API-only → static-only) and §16.3 (fidelity
10
- * levels 1-4: stub, real+disposable DB, real+recordings, real staging).
11
- *
12
- * The point of this file: `distributedTrace: unavailable` must be a
13
- * first-class, structured answer the AI planner can read — never an absent
14
- * field, never a thrown error, never a silent gap that reads as "not
15
- * checked" only after something downstream fails to find data. Absence is
16
- * data, and this contract makes it representable.
6
+ * `distributedTrace: unavailable` must be a first-class structured answer
7
+ * the AI planner can read — never an absent field, thrown error, or silent
8
+ * gap. Absence is data.
17
9
  */
18
10
  export const ENVIRONMENT_TIERS = [
19
11
  "tier-0-ci-attached",
@@ -1 +1 @@
1
- {"version":3,"file":"capability.js","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,oBAAoB;IACpB,gBAAgB;IAChB,kBAAkB;IAClB,kBAAkB;IAClB,oBAAoB;CACZ,CAAC;AAGX,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAU,CAAC;AAIrD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,WAAW,EAAE,UAAU,EAAE,aAAa,CAAU,CAAC;AASzF,MAAM,UAAU,uBAAuB,CAAC,MAAwB;IAC9D,OAAO,MAAM,CAAC,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC;AAC/F,CAAC"}
1
+ {"version":3,"file":"capability.js","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,oBAAoB;IACpB,gBAAgB;IAChB,kBAAkB;IAClB,kBAAkB;IAClB,oBAAoB;CACZ,CAAC;AAGX,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAU,CAAC;AAIrD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,WAAW,EAAE,UAAU,EAAE,aAAa,CAAU,CAAC;AASzF,MAAM,UAAU,uBAAuB,CAAC,MAAwB;IAC9D,OAAO,MAAM,CAAC,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC;AAC/F,CAAC"}
@@ -1,24 +1,13 @@
1
1
  /**
2
- * Collector interface.
2
+ * Collector interface: start/stop/capabilities/emit per §15, enforcing
3
+ * §17's rule "a collector failure must not be mistaken for an application
4
+ * success or absence of failure."
3
5
  *
4
- * `start()` / `stop()` / `capabilities()` / `emit()` are named directly in
5
- * `documents/descry-runtime-plan.md` §15 (Collector architecture), whose
6
- * §17 (Runtime failure model) states the rule this file exists to enforce
7
- * in types: "A collector failure must not be mistaken for an application
8
- * success or absence of failure." Also grounded in the architecture doc's
9
- * §17.2 (the observe stream) and §26 (the failure/degradation matrix's
10
- * governing rule: "say what could not be checked, never silently do less").
11
- *
12
- * Design note, since this diverges slightly from a literal reading of
13
- * "start / stop / capabilities / emit" as four flat methods: `emit` is
14
- * delivered through `CollectorContext` passed into `start()`, not exposed
15
- * as a fourth method other code calls *on* the collector. A collector
16
- * pushes evidence by calling `context.emit()` as events occur — that is
17
- * the only shape consistent with streaming-first (§17.6: partial results
18
- * reach the core as they happen, never batched until a run ends). An
19
- * `emit()` method callable from outside would mean something else feeds
20
- * data *into* the collector, which inverts the actual data flow. Flagging
21
- * this as a deliberate interpretation, not a literal one.
6
+ * `emit` is delivered via `CollectorContext` passed into `start()`, not a
7
+ * fourth method callable on the collector — a collector pushes evidence by
8
+ * calling `context.emit()` as events occur (streaming-first, §17.6: partial
9
+ * results reach the core as they happen, never batched). An external
10
+ * `emit()` would invert the data flow.
22
11
  */
23
12
  import type { ExecutionConfiguration } from "./execution.ts";
24
13
  import type { Evidence } from "./evidence.ts";
@@ -33,25 +22,17 @@ export interface CollectorContext {
33
22
  readonly emit: EmitFn;
34
23
  /**
35
24
  * Resolves a browser origin to its serving service's declared root, when
36
- * the orchestrator assembling this context has enough state to build one
37
- * (needs `Execution.processes`, which `CollectorContext` itself does not
38
- * carry -- RT-023 decided the join belongs to whoever already holds both
39
- * `processes` and `configuration`, never a collector reasoning about
40
- * processes on its own; this field is how that decision reaches a
41
- * collector without handing it the process list to join itself).
42
- *
43
- * Absent for a context built without that state — not a function that
44
- * always refuses. A collector with no resolver at all degrades to
45
- * exactly the same `unavailable` capability report as one whose resolver
46
- * returns `found: false`; there is no separate branch for "no resolver
47
- * provided" versus "resolver had nothing to say."
25
+ * the orchestrator has enough state to build one (needs
26
+ * `Execution.processes`, which `CollectorContext` doesn't carry — RT-023:
27
+ * the join belongs to whoever already holds both `processes` and
28
+ * `configuration`, never the collector itself).
48
29
  *
49
- * A `found: false` result is not, on its own, a failure worth surfacing
50
- * distinctly — most origins a browser collector observes (a CDN, an
51
- * extension, `about:blank`) never correspond to a spawned service at
52
- * all, and `originNoPort`/`noProcessOnPort` (`ServiceRootRefusal`)
53
- * already say so honestly. A collector should treat "not ours" the same
54
- * as any other unmapped origin, not as a distinguishable error.
30
+ * Absent for a context built without that state, not "always refuses" —
31
+ * a missing resolver degrades to the same `unavailable` report as one
32
+ * returning `found: false`. A `found: false` result isn't a distinct
33
+ * failure either: most observed origins (CDN, extension, `about:blank`)
34
+ * never map to a spawned service, and `ServiceRootRefusal` already says
35
+ * so honestly.
55
36
  */
56
37
  readonly resolveSourceRoot?: SourceRootResolver;
57
38
  }
@@ -62,63 +43,30 @@ export type CollectorStartResult = {
62
43
  readonly reason: string;
63
44
  };
64
45
  /**
65
- * The attach-mode-mitigations lane's forward-looking scope guarantee,
66
- * checked against this repo as it stands: no fix-application or
67
- * code-execution mechanism (`applyFix`, `fixApplication`, `applyPatch` or
68
- * equivalent) exists anywhere in `packages/*\/src` today -- that is
69
- * deliberately AI-layer/V2 territory (`descry-core/CLAUDE.md`'s repo
70
- * split), not something this repo has and forgot to guard. So this is a
71
- * contract for something that does not exist yet, not a removal of
72
- * something that does. Its point is to fix the *shape* of `Collector` now,
73
- * while it is cheap and there is nothing to migrate, rather than
74
- * discovering after a fix-application mechanism is built that the natural
75
- * place to wire it in was this interface, which every attach-mode collector
76
- * (`attachToRunningProcess`, `attachToRunningNodeProcess`,
77
- * `attachToRunningJvmProcess`, in `descry-runtime`'s `packages/orchestrator`)
78
- * already implements and would then need retrofitting.
46
+ * Forward-looking guarantee: no fix-application or code-execution
47
+ * mechanism exists in this repo today (deliberately AI-layer/V2 territory)
48
+ * — this fixes the *shape* of `Collector` now, cheaply, before any
49
+ * attach-mode collector needs retrofitting for it.
79
50
  */
80
51
  export declare const ATTACH_MODE_SCOPE_DISCLOSURE: string;
81
52
  /**
82
- * **Every `Collector` -- attach-mode collectors in particular -- is
83
- * contractually observation-only.** No method on a `Collector`, present
84
- * or future, may execute code against the thing it observes or apply a
85
- * change to it; `start()`/`stop()`/`capabilities()` govern the
86
- * collector's own lifecycle, and `context.emit()` (`CollectorContext`,
87
- * above) is a one-way push of evidence outward, never a channel for
88
- * commands going the other way in. This matters most for attach-mode: a
89
- * process Descry did not spawn was never sandboxed by anything this
90
- * runtime controls (see `@descryy/runtime-controller`'s `sandbox.ts` for
91
- * why that is structural, not a gap), so an attach-mode collector that
92
- * could execute code or apply a fix against its target would be doing so
93
- * against a completely unconfined process with no boundary of any kind --
94
- * a materially worse shape than the read-only observation this interface
95
- * actually permits. See `ATTACH_MODE_SCOPE_DISCLOSURE`, above, for the
96
- * in-product statement of this guarantee, and its own comment for why it
97
- * is a forward-looking contract rather than a removal of an existing
98
- * capability: no fix-application or code-execution mechanism exists
99
- * anywhere in this repo yet for this contract to be tested against. Any
100
- * future one belongs in a new, separate interface a caller opts into
101
- * explicitly -- never added as a new method here.
53
+ * Every `Collector` is contractually observation-only — no method, present
54
+ * or future, may execute code against or change the thing it observes;
55
+ * `context.emit()` is a one-way push out, never a command channel in.
56
+ * Matters most for attach-mode: a process Descry didn't spawn is never
57
+ * sandboxed by this runtime (`@descryy/runtime-controller`'s `sandbox.ts`),
58
+ * so a collector that could act on its target would do so against a fully
59
+ * unconfined process. See `ATTACH_MODE_SCOPE_DISCLOSURE` above. Any future
60
+ * execution/fix capability belongs in a new interface a caller opts into —
61
+ * never a method added here.
102
62
  */
103
63
  export interface Collector {
104
64
  readonly collectorId: string;
105
- /**
106
- * Begin collecting for this execution. Must resolve with
107
- * `{ available: false, reason }` for a routine unavailability rather
108
- * than throwing — absence has to be representable data the caller can
109
- * act on, never an exception a caller has to remember to catch and
110
- * reinterpret. Reserve rejection for genuine defects in the collector
111
- * itself.
112
- */
65
+ /** Resolve with `{ available: false, reason }` for routine unavailability, never throw — reserve rejection for genuine collector defects. */
113
66
  start(context: CollectorContext): Promise<CollectorStartResult>;
114
- /** Stop collecting and release everything held (processes, sockets, file handles). Idempotent — safe to call on an already-stopped collector. */
67
+ /** Stop and release everything held (processes, sockets, file handles). Idempotent. */
115
68
  stop(): Promise<void>;
116
- /**
117
- * What this collector can and cannot see. Computed once at start() and
118
- * stable for the collector's lifetime — an unimplemented capability is
119
- * reported as `unavailable` here, never simply omitted from the evidence
120
- * stream and left for a reader to notice its absence.
121
- */
69
+ /** Computed once at start(), stable for the collector's lifetime. An unimplemented capability reports `unavailable`, never omitted silently. */
122
70
  capabilities(): CollectorCapabilities;
123
71
  }
124
72
  //# sourceMappingURL=collector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,MAAM,MAAM,MAAM,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,YAAY,GAAG,aAAa,CAAC,KAAK,IAAI,CAAC;AAEtF,2MAA2M;AAC3M,MAAM,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,iBAAiB,CAAC;AAEvE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,sBAAsB,CAAC;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,kBAAkB,CAAC;CACjD;AAED,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,4BAA4B,QAG6D,CAAC;AAEvG;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B;;;;;;;OAOG;IACH,KAAK,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAEhE,iJAAiJ;IACjJ,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtB;;;;;OAKG;IACH,YAAY,IAAI,qBAAqB,CAAC;CACvC"}
1
+ {"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,MAAM,MAAM,MAAM,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,YAAY,GAAG,aAAa,CAAC,KAAK,IAAI,CAAC;AAEtF,2MAA2M;AAC3M,MAAM,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,iBAAiB,CAAC;AAEvE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,sBAAsB,CAAC;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,kBAAkB,CAAC;CACjD;AAED,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,QAG6D,CAAC;AAEvG;;;;;;;;;;GAUG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B,6IAA6I;IAC7I,KAAK,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAEhE,uFAAuF;IACvF,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtB,gJAAgJ;IAChJ,YAAY,IAAI,qBAAqB,CAAC;CACvC"}
package/dist/collector.js CHANGED
@@ -1,40 +1,19 @@
1
1
  /**
2
- * Collector interface.
2
+ * Collector interface: start/stop/capabilities/emit per §15, enforcing
3
+ * §17's rule "a collector failure must not be mistaken for an application
4
+ * success or absence of failure."
3
5
  *
4
- * `start()` / `stop()` / `capabilities()` / `emit()` are named directly in
5
- * `documents/descry-runtime-plan.md` §15 (Collector architecture), whose
6
- * §17 (Runtime failure model) states the rule this file exists to enforce
7
- * in types: "A collector failure must not be mistaken for an application
8
- * success or absence of failure." Also grounded in the architecture doc's
9
- * §17.2 (the observe stream) and §26 (the failure/degradation matrix's
10
- * governing rule: "say what could not be checked, never silently do less").
11
- *
12
- * Design note, since this diverges slightly from a literal reading of
13
- * "start / stop / capabilities / emit" as four flat methods: `emit` is
14
- * delivered through `CollectorContext` passed into `start()`, not exposed
15
- * as a fourth method other code calls *on* the collector. A collector
16
- * pushes evidence by calling `context.emit()` as events occur — that is
17
- * the only shape consistent with streaming-first (§17.6: partial results
18
- * reach the core as they happen, never batched until a run ends). An
19
- * `emit()` method callable from outside would mean something else feeds
20
- * data *into* the collector, which inverts the actual data flow. Flagging
21
- * this as a deliberate interpretation, not a literal one.
6
+ * `emit` is delivered via `CollectorContext` passed into `start()`, not a
7
+ * fourth method callable on the collector — a collector pushes evidence by
8
+ * calling `context.emit()` as events occur (streaming-first, §17.6: partial
9
+ * results reach the core as they happen, never batched). An external
10
+ * `emit()` would invert the data flow.
22
11
  */
23
12
  /**
24
- * The attach-mode-mitigations lane's forward-looking scope guarantee,
25
- * checked against this repo as it stands: no fix-application or
26
- * code-execution mechanism (`applyFix`, `fixApplication`, `applyPatch` or
27
- * equivalent) exists anywhere in `packages/*\/src` today -- that is
28
- * deliberately AI-layer/V2 territory (`descry-core/CLAUDE.md`'s repo
29
- * split), not something this repo has and forgot to guard. So this is a
30
- * contract for something that does not exist yet, not a removal of
31
- * something that does. Its point is to fix the *shape* of `Collector` now,
32
- * while it is cheap and there is nothing to migrate, rather than
33
- * discovering after a fix-application mechanism is built that the natural
34
- * place to wire it in was this interface, which every attach-mode collector
35
- * (`attachToRunningProcess`, `attachToRunningNodeProcess`,
36
- * `attachToRunningJvmProcess`, in `descry-runtime`'s `packages/orchestrator`)
37
- * already implements and would then need retrofitting.
13
+ * Forward-looking guarantee: no fix-application or code-execution
14
+ * mechanism exists in this repo today (deliberately AI-layer/V2 territory)
15
+ * — this fixes the *shape* of `Collector` now, cheaply, before any
16
+ * attach-mode collector needs retrofitting for it.
38
17
  */
39
18
  export const ATTACH_MODE_SCOPE_DISCLOSURE = "Attach mode observes an already-running process; it never executes code in it or applies changes to it. " +
40
19
  "This is a permanent, documented architectural limitation, not a temporary gap -- there is no honest way to " +
@@ -1 +1 @@
1
- {"version":3,"file":"collector.js","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AA6CH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,4BAA4B,GACvC,0GAA0G;IAC1G,6GAA6G;IAC7G,oGAAoG,CAAC"}
1
+ {"version":3,"file":"collector.js","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAqCH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,4BAA4B,GACvC,0GAA0G;IAC1G,6GAA6G;IAC7G,oGAAoG,CAAC"}
@@ -1,60 +1,28 @@
1
1
  /**
2
- * Correlation contract.
2
+ * Correlation contract. Six-level preference order per §10: trace ID →
3
+ * request ID → W3C trace context → framework-provided → runtime-generated
4
+ * → timing/process/context fallback.
3
5
  *
4
- * The six-level preference order is verbatim from
5
- * `documents/descry-runtime-plan.md` §10 (Request and distributed
6
- * correlation): trace ID → request ID → W3C trace context →
7
- * framework-provided correlation → controlled runtime-generated
8
- * correlation → timing/process/context fallback. Also grounded in the
9
- * architecture doc's §18.2/§18.3a (evidence bundling and the
10
- * RootCauseScore's RuntimeEvidence term both depend on evidence being
11
- * linkable across sources).
12
- *
13
- * The rule that matters most here (this project's version of the
14
- * hypothesis boundary, one layer down): never silently convert an inferred
15
- * correlation into a confirmed one. The first five methods are all actual
16
- * shared identifiers — found in the wild or injected and controlled by the
17
- * runtime itself. Only the sixth, timing/context fallback, is a genuine
6
+ * Never silently convert an inferred correlation into a confirmed one: the
7
+ * first five methods are real shared identifiers; only the sixth is
18
8
  * inference with no identifier behind it. `isConfirmed` is derived
19
- * mechanically from `method`, not set by hand, so that boundary can't drift.
9
+ * mechanically from `method`, never set by hand.
20
10
  */
21
11
  export declare const CORRELATION_METHODS: readonly ["trace-id", "request-id", "w3c-trace-context", "framework-provided", "runtime-generated", "timing-context-fallback"];
22
12
  export type CorrelationMethod = (typeof CORRELATION_METHODS)[number];
23
- /**
24
- * Strongest first. Exported as an explicit ordered array — not inferred
25
- * from CORRELATION_METHODS' declaration order — so the ranking is a fact
26
- * on its own, not an accident of listing order that a future edit could
27
- * silently reorder.
28
- */
13
+ /** Strongest first. A separate explicit array, not inferred from CORRELATION_METHODS' order, so ranking can't silently reorder on an edit. */
29
14
  export declare const CORRELATION_PREFERENCE_ORDER: readonly CorrelationMethod[];
30
15
  export declare function correlationRank(method: CorrelationMethod): number;
31
- /**
32
- * True for every method except timing-context-fallback. This is the
33
- * structural distinction Agent 3 asked for: a timing-inferred link must be
34
- * distinguishable from a trace-ID match by type, not merely by a lower
35
- * confidence number that a careless reader could ignore.
36
- */
16
+ /** True for every method except timing-context-fallback — a timing-inferred link must be distinguishable by type, not just a lower confidence number. */
37
17
  export declare function isStructuralCorrelation(method: CorrelationMethod): boolean;
38
18
  export interface Correlation {
39
19
  readonly correlationId: string;
40
20
  readonly executionId: string;
41
21
  readonly method: CorrelationMethod;
42
- /**
43
- * 0-1, independent of rank. Rank says which method produced this
44
- * correlation; confidence says how sure this particular instance of that
45
- * method's result is. A low-confidence trace-id match and a
46
- * high-confidence timing match can coexist — they answer different
47
- * questions.
48
- */
22
+ /** 0-1, independent of rank — rank says which method, confidence says how sure this instance is. A low-confidence trace-id match and high-confidence timing match can coexist. */
49
23
  readonly confidence: number;
50
24
  readonly evidenceIds: readonly string[];
51
- /**
52
- * Derived from `method` via isStructuralCorrelation — never set
53
- * independently. A caller cannot construct a Correlation with
54
- * method: "timing-context-fallback" and isConfirmed: true; use
55
- * `createCorrelation` rather than a bare object literal to keep that
56
- * true in practice, not just in a comment.
57
- */
25
+ /** Derived from `method` via isStructuralCorrelation, never set independently — use `createCorrelation`, not a bare object literal. */
58
26
  readonly isConfirmed: boolean;
59
27
  }
60
28
  export declare function createCorrelation(input: Omit<Correlation, "isConfirmed">): Correlation;
@@ -1 +1 @@
1
- {"version":3,"file":"correlation.d.ts","sourceRoot":"","sources":["../src/correlation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,eAAO,MAAM,mBAAmB,gIAOtB,CAAC;AACX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAErE;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,EAAE,SAAS,iBAAiB,EAOpE,CAAC;AAEF,wBAAgB,eAAe,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAMjE;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAE1E;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC;;;;;;OAMG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC/B;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,GACtC,WAAW,CAEb"}
1
+ {"version":3,"file":"correlation.d.ts","sourceRoot":"","sources":["../src/correlation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,eAAO,MAAM,mBAAmB,gIAOtB,CAAC;AACX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAErE,8IAA8I;AAC9I,eAAO,MAAM,4BAA4B,EAAE,SAAS,iBAAiB,EAOpE,CAAC;AAEF,wBAAgB,eAAe,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAMjE;AAED,yJAAyJ;AACzJ,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAE1E;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,kLAAkL;IAClL,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,uIAAuI;IACvI,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC/B;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,GACtC,WAAW,CAEb"}
@@ -1,22 +1,12 @@
1
1
  /**
2
- * Correlation contract.
2
+ * Correlation contract. Six-level preference order per §10: trace ID →
3
+ * request ID → W3C trace context → framework-provided → runtime-generated
4
+ * → timing/process/context fallback.
3
5
  *
4
- * The six-level preference order is verbatim from
5
- * `documents/descry-runtime-plan.md` §10 (Request and distributed
6
- * correlation): trace ID → request ID → W3C trace context →
7
- * framework-provided correlation → controlled runtime-generated
8
- * correlation → timing/process/context fallback. Also grounded in the
9
- * architecture doc's §18.2/§18.3a (evidence bundling and the
10
- * RootCauseScore's RuntimeEvidence term both depend on evidence being
11
- * linkable across sources).
12
- *
13
- * The rule that matters most here (this project's version of the
14
- * hypothesis boundary, one layer down): never silently convert an inferred
15
- * correlation into a confirmed one. The first five methods are all actual
16
- * shared identifiers — found in the wild or injected and controlled by the
17
- * runtime itself. Only the sixth, timing/context fallback, is a genuine
6
+ * Never silently convert an inferred correlation into a confirmed one: the
7
+ * first five methods are real shared identifiers; only the sixth is
18
8
  * inference with no identifier behind it. `isConfirmed` is derived
19
- * mechanically from `method`, not set by hand, so that boundary can't drift.
9
+ * mechanically from `method`, never set by hand.
20
10
  */
21
11
  export const CORRELATION_METHODS = [
22
12
  "trace-id",
@@ -26,12 +16,7 @@ export const CORRELATION_METHODS = [
26
16
  "runtime-generated",
27
17
  "timing-context-fallback",
28
18
  ];
29
- /**
30
- * Strongest first. Exported as an explicit ordered array — not inferred
31
- * from CORRELATION_METHODS' declaration order — so the ranking is a fact
32
- * on its own, not an accident of listing order that a future edit could
33
- * silently reorder.
34
- */
19
+ /** Strongest first. A separate explicit array, not inferred from CORRELATION_METHODS' order, so ranking can't silently reorder on an edit. */
35
20
  export const CORRELATION_PREFERENCE_ORDER = [
36
21
  "trace-id",
37
22
  "request-id",
@@ -47,12 +32,7 @@ export function correlationRank(method) {
47
32
  }
48
33
  return rank;
49
34
  }
50
- /**
51
- * True for every method except timing-context-fallback. This is the
52
- * structural distinction Agent 3 asked for: a timing-inferred link must be
53
- * distinguishable from a trace-ID match by type, not merely by a lower
54
- * confidence number that a careless reader could ignore.
55
- */
35
+ /** True for every method except timing-context-fallback — a timing-inferred link must be distinguishable by type, not just a lower confidence number. */
56
36
  export function isStructuralCorrelation(method) {
57
37
  return method !== "timing-context-fallback";
58
38
  }
@@ -1 +1 @@
1
- {"version":3,"file":"correlation.js","sourceRoot":"","sources":["../src/correlation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,UAAU;IACV,YAAY;IACZ,mBAAmB;IACnB,oBAAoB;IACpB,mBAAmB;IACnB,yBAAyB;CACjB,CAAC;AAGX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAiC;IACxE,UAAU;IACV,YAAY;IACZ,mBAAmB;IACnB,oBAAoB;IACpB,mBAAmB;IACnB,yBAAyB;CAC1B,CAAC;AAEF,MAAM,UAAU,eAAe,CAAC,MAAyB;IACvD,MAAM,IAAI,GAAG,4BAA4B,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1D,IAAI,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,gCAAgC,MAAM,EAAE,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAyB;IAC/D,OAAO,MAAM,KAAK,yBAAyB,CAAC;AAC9C,CAAC;AAyBD,MAAM,UAAU,iBAAiB,CAC/B,KAAuC;IAEvC,OAAO,EAAE,GAAG,KAAK,EAAE,WAAW,EAAE,uBAAuB,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;AAC1E,CAAC"}
1
+ {"version":3,"file":"correlation.js","sourceRoot":"","sources":["../src/correlation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,UAAU;IACV,YAAY;IACZ,mBAAmB;IACnB,oBAAoB;IACpB,mBAAmB;IACnB,yBAAyB;CACjB,CAAC;AAGX,8IAA8I;AAC9I,MAAM,CAAC,MAAM,4BAA4B,GAAiC;IACxE,UAAU;IACV,YAAY;IACZ,mBAAmB;IACnB,oBAAoB;IACpB,mBAAmB;IACnB,yBAAyB;CAC1B,CAAC;AAEF,MAAM,UAAU,eAAe,CAAC,MAAyB;IACvD,MAAM,IAAI,GAAG,4BAA4B,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1D,IAAI,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,gCAAgC,MAAM,EAAE,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,yJAAyJ;AACzJ,MAAM,UAAU,uBAAuB,CAAC,MAAyB;IAC/D,OAAO,MAAM,KAAK,yBAAyB,CAAC;AAC9C,CAAC;AAaD,MAAM,UAAU,iBAAiB,CAC/B,KAAuC;IAEvC,OAAO,EAAE,GAAG,KAAK,EAAE,WAAW,EAAE,uBAAuB,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;AAC1E,CAAC"}