@yanlinglabs/winter-runtime-sdk 0.0.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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +249 -0
  3. package/dist/directory/directory.d.ts +55 -0
  4. package/dist/directory/entries.d.ts +82 -0
  5. package/dist/directory/recovery.d.ts +49 -0
  6. package/dist/door.d.ts +247 -0
  7. package/dist/errors.d.ts +104 -0
  8. package/dist/index.d.ts +25 -0
  9. package/dist/index.js +6679 -0
  10. package/dist/messaging/attribution.d.ts +47 -0
  11. package/dist/messaging/dispatch.d.ts +78 -0
  12. package/dist/messaging/handlers.d.ts +56 -0
  13. package/dist/messaging/inbound.d.ts +110 -0
  14. package/dist/messaging/index.d.ts +39 -0
  15. package/dist/messaging/official-adapter.d.ts +36 -0
  16. package/dist/messaging/router.d.ts +101 -0
  17. package/dist/messaging/sessions.d.ts +49 -0
  18. package/dist/messaging/winter-adapter.d.ts +47 -0
  19. package/dist/native-args.d.ts +76 -0
  20. package/dist/official/adapter.d.ts +88 -0
  21. package/dist/official/aliases.d.ts +48 -0
  22. package/dist/official/auth.d.ts +117 -0
  23. package/dist/official/branding.d.ts +31 -0
  24. package/dist/official/callbacks.d.ts +143 -0
  25. package/dist/official/containment.d.ts +130 -0
  26. package/dist/official/env-allowlist.d.ts +237 -0
  27. package/dist/official/env-registry-rule.d.ts +12 -0
  28. package/dist/official/env-registry.d.ts +3 -0
  29. package/dist/official/errors.d.ts +250 -0
  30. package/dist/official/index.d.ts +31 -0
  31. package/dist/official/mcp-descriptors.d.ts +130 -0
  32. package/dist/official/options-template.d.ts +110 -0
  33. package/dist/official/spawn-proxy.d.ts +144 -0
  34. package/dist/official/spool.d.ts +80 -0
  35. package/dist/official/supervision.d.ts +49 -0
  36. package/dist/official/sweep.d.ts +65 -0
  37. package/dist/sdk.d.ts +214 -0
  38. package/dist/seams/context.d.ts +26 -0
  39. package/dist/seams/directory-store.d.ts +274 -0
  40. package/dist/seams/directory.d.ts +46 -0
  41. package/dist/seams/global-messaging.d.ts +30 -0
  42. package/dist/seams/handoff.d.ts +77 -0
  43. package/dist/seams/index.d.ts +11 -0
  44. package/dist/seams/keychain.d.ts +11 -0
  45. package/dist/seams/materialized-resume.d.ts +46 -0
  46. package/dist/seams/messaging-contract.d.ts +29 -0
  47. package/dist/seams/official-adapter.d.ts +125 -0
  48. package/dist/seams/official-sdk-shapes.d.ts +126 -0
  49. package/dist/seams/stubs.d.ts +34 -0
  50. package/dist/selection/child-runtime.d.ts +81 -0
  51. package/dist/selection/runtime-selection.d.ts +217 -0
  52. package/dist/selection/select-runtime.d.ts +213 -0
  53. package/dist/store/handoff-barrier.d.ts +238 -0
  54. package/dist/store/index.d.ts +11 -0
  55. package/dist/store/materialized-resume.d.ts +100 -0
  56. package/dist/store/pinned-probes.d.ts +17 -0
  57. package/dist/store/reconcile.d.ts +157 -0
  58. package/dist/store/temp-continuity.d.ts +92 -0
  59. package/dist/store/wiring.d.ts +250 -0
  60. package/dist/vendor-paths.d.ts +21 -0
  61. package/dist/version-matrix.d.ts +84 -0
  62. package/docs/conformance-rows.md +195 -0
  63. package/package.json +65 -0
@@ -0,0 +1,250 @@
1
+ import type { BrandProfile, SessionKey, SessionStore, SessionStoreEntry, SessionSummaryEntry } from "@yanlinglabs/winter-agent-sdk";
2
+ import { RuntimeSdkError } from "../errors.js";
3
+ import type { RuntimeSdkPeers } from "../sdk.js";
4
+ /**
5
+ * The concrete store's surface, as the router uses it.
6
+ *
7
+ * STRUCTURAL, not `InstanceType<typeof peers.winter.WinterCompatibilitySessionStore>`, for the same
8
+ * reason `seams/official-sdk-shapes.ts` types the official module structurally: the peer is INJECTED,
9
+ * so the router must describe what it needs rather than name a class it never imports. The four
10
+ * Winter-only members below are on the concrete class and deliberately NOT on the pinned
11
+ * `SessionStore` type (WS-03 §10 pins that at exactly six members) — the store's own comments say so.
12
+ */
13
+ export interface CanonicalSessionStore extends SessionStore {
14
+ append(key: SessionKey, entries: SessionStoreEntry[]): Promise<void>;
15
+ load(key: SessionKey): Promise<SessionStoreEntry[] | null>;
16
+ listSessions(projectKey: string): Promise<Array<{
17
+ sessionId: string;
18
+ mtime: number;
19
+ }>>;
20
+ listSessionSummaries(projectKey: string): Promise<SessionSummaryEntry[]>;
21
+ delete(key: SessionKey): Promise<void>;
22
+ listSubkeys(key: {
23
+ projectKey: string;
24
+ sessionId: string;
25
+ }): Promise<string[]>;
26
+ listProjectKeys(): Promise<string[]>;
27
+ readSessionSummary(key: {
28
+ projectKey: string;
29
+ sessionId: string;
30
+ }): Promise<SessionSummaryEntry | null>;
31
+ acquireSessionLease(key: {
32
+ projectKey: string;
33
+ sessionId: string;
34
+ }): Promise<void>;
35
+ }
36
+ /** The constructor the injected peer exports. */
37
+ export type CanonicalSessionStoreConstructor = new (opts: {
38
+ winterHome: string;
39
+ }) => CanonicalSessionStore;
40
+ /** WS-14 §5.1: an options combination the shared store cannot be used with. */
41
+ export declare class SharedStoreOptionsError extends RuntimeSdkError {
42
+ readonly option: "persistSession" | "enableFileCheckpointing" | "sessionStore";
43
+ constructor(args: {
44
+ option: "persistSession" | "enableFileCheckpointing" | "sessionStore";
45
+ reason: string;
46
+ });
47
+ }
48
+ /**
49
+ * WS-14 §5: "Blind `importSessionToStore()` after partial mirror failure is forbidden."
50
+ *
51
+ * A THROW AND NOT A WARNING. The import transports a whole local transcript into the canonical store;
52
+ * run after a PARTIAL mirror it re-imports entries that already landed and re-orders around the ones
53
+ * that did not, which is the one failure the canonical file cannot recover from by itself. The safe
54
+ * door is `reconcile.ts`'s suffix-only reconciliation, and this class names it.
55
+ */
56
+ export declare class BlindStoreImportError extends RuntimeSdkError {
57
+ readonly key: Readonly<SessionKey>;
58
+ constructor(key: SessionKey, detail: string);
59
+ }
60
+ /** The injected Winter peer does not carry the concrete store (a peer built for a different purpose). */
61
+ export declare class SharedStoreUnavailableError extends RuntimeSdkError {
62
+ constructor();
63
+ }
64
+ export interface MirrorPolicy {
65
+ /** §5's "~100 ms batches". Appends inside one window become ONE canonical append. */
66
+ batchWindowMs: number;
67
+ /** §5's "≤3 append attempts". */
68
+ maxAttempts: number;
69
+ /** §5's "short backoff" between attempts. */
70
+ backoffMs: number;
71
+ /**
72
+ * How long ONE attempt may take before it is abandoned.
73
+ *
74
+ * §5: "a timed-out append is **not** retried". The reason is not politeness — a timed-out append may
75
+ * still land, so a retry is the one action that can duplicate entries in an append-only file.
76
+ */
77
+ attemptTimeoutMs: number;
78
+ }
79
+ export declare const DEFAULT_MIRROR_POLICY: MirrorPolicy;
80
+ export type TranscriptHealth = "ok" | "repair-required";
81
+ /** What a failed mirror records. COUNTS AND A CAUSE — never entry content (WS-05 §13). */
82
+ export interface MirrorErrorRecord {
83
+ projectKey: string;
84
+ sessionId: string;
85
+ subpath?: string;
86
+ /** How many entries were in the batch that failed. Never what they were. */
87
+ entryCount: number;
88
+ attempts: number;
89
+ cause: "append-failed" | "timed-out";
90
+ /** The failure's own message, from the store's typed error — never an entry. */
91
+ detail: string;
92
+ at: string;
93
+ }
94
+ export interface SessionMirrorHealth {
95
+ transcriptHealth: TranscriptHealth;
96
+ errors: readonly MirrorErrorRecord[];
97
+ /** Canonical appends this session has completed — the "~100 ms batches" observation. */
98
+ batchesCommitted: number;
99
+ /** `append()` calls received from a branch. Two inside one window commit as one batch. */
100
+ appendsReceived: number;
101
+ }
102
+ export interface SettleReport {
103
+ /** True when every pending batch reached a terminal state (committed or recorded as a mirror error). */
104
+ settled: boolean;
105
+ batchesCommitted: number;
106
+ errors: readonly MirrorErrorRecord[];
107
+ transcriptHealth: TranscriptHealth;
108
+ }
109
+ /** The identity that makes "one instance, one version" checkable rather than asserted. */
110
+ export interface SharedStoreIdentity {
111
+ packageName: string;
112
+ /** The injected peer's own version identity — the version BOTH branches are therefore using. */
113
+ packageVersion: string;
114
+ /** Unique per `createSharedSessionStore` call, so "the same store" is provable by value. */
115
+ instanceId: string;
116
+ winterHome: string;
117
+ }
118
+ /** Options members WS-14 §5.1 rules on. Structural, so both branches' option objects fit. */
119
+ export interface StoreBearingOptions {
120
+ sessionStore?: unknown;
121
+ persistSession?: boolean;
122
+ enableFileCheckpointing?: boolean;
123
+ }
124
+ export interface SharedSessionStore {
125
+ /** THE object handed to both branches as `Options.sessionStore`. */
126
+ readonly store: SessionStore;
127
+ /** The underlying concrete store, for the barrier's lease/summary doors. Never handed to a branch. */
128
+ readonly canonical: CanonicalSessionStore;
129
+ readonly identity: SharedStoreIdentity;
130
+ readonly policy: MirrorPolicy;
131
+ /** WS-05 §12 step 3's host-side pending barrier. No key = every session. */
132
+ settle(key?: SessionKey): Promise<SettleReport>;
133
+ health(key: SessionKey): SessionMirrorHealth;
134
+ /**
135
+ * Clears a session's `repair-required` flag. THE ONLY CALLER IS A COMPLETED RECONCILIATION
136
+ * (`reconcile.ts`) — the flag exists to block a handoff until the canonical store is reconciled, so
137
+ * anything else clearing it would be clearing the evidence rather than the cause.
138
+ */
139
+ markReconciled(key: SessionKey, detail: string): void;
140
+ /** Attaches the shared store to an options object, refusing §5.1's two combinations. */
141
+ attach<T extends StoreBearingOptions>(options: T): T & {
142
+ sessionStore: SessionStore;
143
+ };
144
+ /** WS-14 §5's blind-import ban, as a guard a host calls before `importSessionToStore()`. */
145
+ assertImportAllowed(key: SessionKey): void;
146
+ /** WS-13 §8.2's no-wash-back mechanism. Shared with the decorator and the reconciler. */
147
+ readonly decorations: DecorationRegistry;
148
+ }
149
+ /**
150
+ * The uuids of entries that exist ONLY in a materialized resume copy.
151
+ *
152
+ * WHY THIS EXISTS AT ALL. WS-13 §8.2's PREFERRED door bakes decorations into the copy the destination
153
+ * runtime reads, "the canonical file stays byte-pure". But the destination then WRITES its next turn
154
+ * with `parentUuid` pointing at whatever it read last — including a decoration — and mirrors that turn
155
+ * back through this store. Without a registry, the byte-pure canonical file would acquire either the
156
+ * decoration itself (via reconciliation's suffix append) or an entry whose parent is unreachable in it
157
+ * (WS-05 §12 step 5's own validation would then fail the NEXT handoff). Both are the wash-back the
158
+ * probe is about; this is the mechanism that makes the probe pass rather than a hope that it does.
159
+ *
160
+ * IN-MEMORY BY DESIGN. §8.2: "decorations are recomputed fresh at every leg spawn (never stale)". A
161
+ * copy outlives neither the generation that staged it nor the process that decorated it, so a durable
162
+ * ledger would only ever hold entries about copies that no longer exist.
163
+ */
164
+ export interface DecorationRegistry {
165
+ /** Records an entry that lives only in the copy, with the parent the canonical chain should keep. */
166
+ record(key: SessionKey, decoration: {
167
+ uuid: string;
168
+ parentUuid: string | null;
169
+ }): void;
170
+ has(key: SessionKey, uuid: string): boolean;
171
+ list(key: SessionKey): readonly string[];
172
+ /** The parent a decoration stands in front of, resolving a chain of them. */
173
+ canonicalParentOf(key: SessionKey, uuid: string): string | null;
174
+ forget(key: SessionKey): void;
175
+ }
176
+ export declare function createDecorationRegistry(): DecorationRegistry;
177
+ export interface StripDecorationsResult {
178
+ entries: SessionStoreEntry[];
179
+ dropped: number;
180
+ reparented: number;
181
+ }
182
+ /**
183
+ * Removes copy-only entries from a batch on its way into the canonical store, and re-links the chain.
184
+ *
185
+ * RE-PARENTING IS NOT OPTIONAL. Dropping a decoration whose child points at it would leave the child
186
+ * with an unreachable `parentUuid` — exactly what WS-05 §12 step 5 validates and refuses. The child's
187
+ * `parentUuid` becomes the decoration's own parent, which is the link the canonical file would have had
188
+ * if the decoration had never been staged. Nothing else about the entry is touched, and an entry with
189
+ * no decorated parent is returned by IDENTITY (never a copy), so a batch with no decorations in it is
190
+ * byte-identical to the one the branch handed us.
191
+ */
192
+ export declare function stripDecorations(key: SessionKey, entries: readonly SessionStoreEntry[], registry: DecorationRegistry): StripDecorationsResult;
193
+ /**
194
+ * WS-14 §5.1's two refusals, over any options object carrying a store.
195
+ *
196
+ * BOTH BRANCHES, ONE RULE. The Winter SDK's own `query()` refuses the same two combinations at
197
+ * construction (`packages/sdk/src/query.ts`), and Lane A's `assertOptionsInvariants` refuses them on
198
+ * the official template. This is the third site on purpose: it is the one that runs when the ROUTER
199
+ * attaches the store, i.e. before either branch exists, and it throws a TYPED class rather than the
200
+ * bare `Error` the SDK's constructor-time check throws.
201
+ */
202
+ export declare function assertStoreCompatibleOptions(options: StoreBearingOptions): void;
203
+ /**
204
+ * Asserts that every options object listed carries the SAME store object (WS-05 §6).
205
+ *
206
+ * BY IDENTITY, because that is the only check that means anything: two stores over one home are
207
+ * type-identical, version-identical, and still two writers.
208
+ */
209
+ export declare function assertOneSharedStore(shared: SharedSessionStore, ...options: ReadonlyArray<{
210
+ sessionStore?: unknown;
211
+ }>): void;
212
+ export interface SharedSessionStoreInput {
213
+ peers: RuntimeSdkPeers;
214
+ winterHome: string;
215
+ policy?: Partial<MirrorPolicy>;
216
+ /** Injectable clock for the records' timestamps. */
217
+ now?: () => Date;
218
+ /** WS-13 §8.2's decoration registry. A fresh one per store unless a host shares one deliberately. */
219
+ decorations?: DecorationRegistry;
220
+ }
221
+ /**
222
+ * Builds the one store both branches share.
223
+ *
224
+ * THE CLASS COMES FROM THE INJECTED PEER, never from an import of this package's own: a host that
225
+ * vendored its own copy of the Winter SDK gets ITS store, ITS lease semantics and ITS typed errors —
226
+ * the same argument `createRuntimeSdk` already makes for `resolveBrand`/`InvalidBrandError`.
227
+ */
228
+ export declare function createSharedSessionStore(input: SharedSessionStoreInput): SharedSessionStore;
229
+ /**
230
+ * A shared store resolved on FIRST USE, from the injected peer's own `resolveWinterHome()`.
231
+ *
232
+ * WHY LAZY MATTERS, and it is not a micro-optimisation. The spine's wiring line is
233
+ * `stubHandoffBarrier(context)` becoming `createHandoffBarrier(context)`, called for EVERY
234
+ * `createRuntimeSdk` — including the ones in `test/spine/*`, whose fake peer exports five members and
235
+ * neither a store class nor `resolveWinterHome`. A factory that built its store eagerly would throw at
236
+ * construction for every host that never hands a session off, and would break every spine test the day
237
+ * it was wired in. Resolved on the first `plan()`/`execute()`, it costs nothing until a handoff exists,
238
+ * and a host that already has a store passes it and never reaches this at all.
239
+ */
240
+ export declare function lazySharedSessionStore(input: {
241
+ peers: RuntimeSdkPeers;
242
+ winterHome?: string;
243
+ /**
244
+ * The RESOLVED profile. NOT optional in practice: `resolveWinterHome()` defaults to `WINTER_BRAND`,
245
+ * so a call without it would send a rebranded host's sessions to Winter's own home directory — the
246
+ * exact failure the brand sweep gate exists to catch, and did catch, on this line.
247
+ */
248
+ brand: Pick<BrandProfile, "envPrefix" | "homeDirName">;
249
+ policy?: Partial<MirrorPolicy>;
250
+ }): () => SharedSessionStore;
@@ -0,0 +1,21 @@
1
+ /** The vendor's fixed staging prefix (WS-05 §9, WS-14 §1: disclosed, never faked, never rebranded). */
2
+ export declare const RESUME_STAGING_PREFIX = "claude-resume-";
3
+ /**
4
+ * `<base>/claude-resume-<uuid>` — the root a store-backed resume stages under.
5
+ *
6
+ * WS-05 §9: "Store-backed resume still stages under SDK-parent `os.tmpdir()/claude-resume-<uuid>`."
7
+ *
8
+ * EXPORTED FOR RECOGNITION AND FOR STAGING, NEVER FOR CONFIGURATION on the official branch: the
9
+ * vendor's wrapper builds its own path there and we never set it ("`Options.env`/spawn hook are too
10
+ * late" — WS-14 §2's controls table), so the only base a host can move is the SDK PARENT's process
11
+ * `TMPDIR`. Lane C's decorator, by contrast, stages a copy at a root it owns and passes `base`.
12
+ */
13
+ export declare function resumeStagingRoot(uuid: string, base?: string): string;
14
+ /**
15
+ * True when a path is a `claude-resume-<uuid>` staging root.
16
+ *
17
+ * BY BASENAME, NEVER BY SUBSTRING: `<tmp>/claude-resume-9/projects/key` is a file INSIDE a staging
18
+ * root, not the root, and a reconciler that confused the two would delete or import the wrong thing.
19
+ * The bare prefix with no uuid is not one either.
20
+ */
21
+ export declare function isResumeStagingRoot(path: string): boolean;
@@ -0,0 +1,84 @@
1
+ import type { RuntimeSdkPeers } from "./sdk.js";
2
+ /**
3
+ * THE MATRIX. The plan pins this object verbatim.
4
+ *
5
+ * `winterAgentSdk` is a RANGE because the Winter SDK is this repository's sibling and moves with it;
6
+ * `claudeAgentSdk` is an EXACT pin because WS-02 §6.1 says declaration identity alone must not
7
+ * approve an upgrade — a new official version is a reviewed compatibility event (WS-17's drift gate),
8
+ * not a range that quietly widens.
9
+ */
10
+ export declare const SUPPORTED: {
11
+ readonly winterAgentSdk: ">=0.0.2 <0.1.0";
12
+ readonly claudeAgentSdk: "0.3.250";
13
+ };
14
+ /**
15
+ * The Winter wire protocol versions this router is tested against (`PROTOCOL_VERSION` in the SDK's
16
+ * own `protocol/frames.ts`). Separate from `SUPPORTED` because the plan pins that object's shape and
17
+ * because these are two independent identities: a wrapper can be re-released without moving its wire.
18
+ */
19
+ export declare const SUPPORTED_PROTOCOL_VERSIONS: readonly ["1.0"];
20
+ /** Where a peer's package version came from. See this module's header. */
21
+ export type PeerVersionSource = "peer-export" | "resolved-manifest";
22
+ export interface PeerVersionIdentity {
23
+ /** The package name the identity was read for. */
24
+ packageName: string;
25
+ /** The version string that was matched against the matrix. */
26
+ packageVersion: string;
27
+ source: PeerVersionSource;
28
+ /** The matrix entry this peer satisfied. */
29
+ supported: string;
30
+ }
31
+ export interface VersionMatrixReport {
32
+ winterAgentSdk: PeerVersionIdentity & {
33
+ protocolVersion: string;
34
+ };
35
+ /** Absent when no official peer was injected — which is allowed (a Winter-only host). */
36
+ claudeAgentSdk?: PeerVersionIdentity;
37
+ /** The matrix the report was produced against, so a diagnostic never has to guess. */
38
+ supported: typeof SUPPORTED;
39
+ supportedProtocolVersions: readonly string[];
40
+ /** ISO-8601, so a persisted report says when it was taken. */
41
+ checkedAt: string;
42
+ }
43
+ interface ParsedVersion {
44
+ major: number;
45
+ minor: number;
46
+ patch: number;
47
+ /** The `-alpha.1` tail, or "" for a release. */
48
+ prerelease: string;
49
+ }
50
+ /** Parses `X.Y.Z`, `vX.Y.Z`, `X.Y.Z-tag`, `X.Y.Z+build`. Returns undefined for anything else. */
51
+ export declare function parseVersion(raw: string): ParsedVersion | undefined;
52
+ /**
53
+ * Whether `version` satisfies `range`.
54
+ *
55
+ * Supported forms, and deliberately only these: a space-separated conjunction of `>=`/`>`/`<=`/`<`
56
+ * comparators, a caret (`^X.Y.Z`), and a bare or `=`-prefixed exact version. An UNRECOGNISED range
57
+ * throws rather than returning false — a matrix entry nobody can parse is a bug in the matrix, and
58
+ * silently refusing every peer would look like a peer problem.
59
+ */
60
+ export declare function satisfiesRange(version: string, range: string): boolean;
61
+ /** The export names a peer may use to publish its own package version, in probe order. */
62
+ export declare const VERSION_EXPORT_NAMES: readonly ["SDK_VERSION", "VERSION", "PACKAGE_VERSION", "version"];
63
+ /** Step 1: a version identity exported by the injected module namespace itself. */
64
+ export declare function readExportedVersion(namespace: unknown): string | undefined;
65
+ /**
66
+ * Step 2: the `version` of the copy of `packageName` THIS module can resolve.
67
+ *
68
+ * Walks up from the resolved entry file rather than resolving `<name>/package.json` directly,
69
+ * because a package whose `exports` map is closed to `"."` (the Winter SDK's is) does not expose its
70
+ * own manifest as a subpath. Every failure mode — no such package, a manifest that will not parse, a
71
+ * manifest with no `version` — returns `undefined`, which the caller turns into the loud refusal.
72
+ * Never throws: a missing OPTIONAL peer must not crash the matrix on its way to reporting itself.
73
+ */
74
+ export declare function readResolvedManifestVersion(packageName: string): string | undefined;
75
+ /**
76
+ * Reads each injected peer's version identity and refuses loudly on a miss.
77
+ *
78
+ * Three outcomes, and the third is the one worth naming: an ABSENT official peer is allowed. A
79
+ * Winter-only host injects `{ winter }` and never loads the official runtime (that is the whole
80
+ * point of the optional peer), so "no claude peer" is a valid, fully-supported configuration and the
81
+ * report simply omits the row.
82
+ */
83
+ export declare function assertVersionMatrix(peers: RuntimeSdkPeers): VersionMatrixReport;
84
+ export {};
@@ -0,0 +1,195 @@
1
+ # `@yanlinglabs/winter-runtime-sdk` — conformance rows
2
+
3
+ > GENERATED from `test/conformance/rows.test.ts`. Do not edit by hand — change the table there and
4
+ > re-run `WINTER_ROWS_WRITE=1 bun test test/conformance/rows.test.ts`. Every citation below is
5
+ > machine-verified by that test: the cited file is read and the cited test title searched for, so a
6
+ > renamed test fails the suite rather than leaving this page claiming a proof that no longer exists.
7
+
8
+ WS-17 §8's closing line is why this page exists: **no release may claim drop-in compatibility while a
9
+ router-owned row is unproven.** Rows 6, 9, 10, 16 and 18 are excluded by WS-17 §8 itself.
10
+
11
+ ## WS-17 §8 — the router's proof rows
12
+
13
+ | Row | Status | Owner | Obligation | Scope / note |
14
+ | --- | --- | --- | --- | --- |
15
+ | WS17-1 | **proven** | Lane B (the handlers the official branch's aliases reach), with Lane A's `toolAliases` | Real model-emitted `SendMessage` through the TS alias reaches `mcp__winter__send_message` with native args and returns the visible result. | PROVEN WHOLE-ROW IN THE FIX WAVE (item 14). Each lane's half was already green against a DOUBLE of the other — Lane A's alias test used a recording handler, Lane B's router tests used a scripted caller — and the row is the join. `test/joint/` drives one real 0.3.250 process through its own `toolAliases` into Lane B's real handler and router, and the delivered frame, the class, the summary and the typed outcome are read at the far end. The joint run also established what no report knew: the WS-10 §12 retry key survives the whole path, because the caller is bound with NO tool-use id and the message id still carries the model's own (item 15). |
16
+ | WS17-2 | **proven** | Lane B (handlers), with Lane A's alias table | `ListAgents` aliasing; canonical MCP duplicate deferred/hidden visibility; behavior without Tool Search. | The visibility half is RECORDED, not asserted-as-wished: with no Tool Search active the pinned runtime advertises the native name AND the canonical twin, so `deferred` is this package's intent and the runtime's own decision is what the test writes down. Re-measured under the hermetic child env (F-1), where the advertised set is the artifact's own 21 names rather than 25 including three remotely-flagged tools. |
17
+ | WS17-3 | **proven** | Lane A (aliases + deny floor, WS-14 §7) | `disallowedTools` + permission floor cover harness-internal/direct paths aliases miss. | The measurement behind it: denying only the built-in leaves the alias resolving and the handler RUNNING, because the deny check happens after alias resolution. `aliasDenyNames` is the door that stops a host tripping over it, and row 3 is why it exists. |
18
+ | WS17-4 | **proven** | Lane A (spool isolation, WS-14 §1) with Lane B (delivery, hold/refuse, idle wake) | Two official sessions under the spool: isolated discovery, delivery, hold/refuse, idle wake, zero visibility into `~/.claude`. | Both halves are now measured against two REAL 0.3.250 processes over one shared directory (item 14) — run SEQUENTIALLY, each with its own spool, which is what the isolation assertion compares; not one lane's real runtime beside the other lane's double. The `idle wake` clause resolves to WS-10 §14's WHOLE-CALL REFUSAL on this branch — the pinned SDK's `Query` exposes no session-status surface, so an adapter without a reliable idle signal must refuse rather than subscribe. That is a measurement about the artifact, not a gap in the row. |
19
+ | WS17-5 | **proven** | Lane A (parent-restart child restoration, WS-14 §15) with Lane B (the resume route) | Official parent resume after restart restores completed children for native SendMessage resume. | The joint half is a REAL `resume()` (round 2, NEW-B): generation one's `system/init` session id and its own spool are handed to `adapter.resume()`, the second generation reports the SAME backend session id and the same observed root, and a native SendMessage to a completed child is asserted `delivered`/`queued` with the frame arriving in the resumed parent's stream. The earlier version launched two fresh sessions and closed on `not.toBe("not_found")`, which `unavailable` and `held` also satisfy. |
20
+ | WS17-7 | **proven** | Lane B (the messaging router, WS-15 §6.2–6.3 / WS-10 §11–§13) | Messaging: addressing, ambiguity/staleness, dedupe, queue bounds, TTL, retries, crash windows, loop prevention, reply routing, `notify_when_idle`. | Ten clauses, ten named proofs. The crash-window clause is the one worth reading twice: the envelope and the CLAIM are persisted before the adapter is invoked, so a crash between them is recoverable as `delivery_uncertain` rather than as silence. |
21
+ | WS17-8 | **proven** (router-scoped — see the note) | Lane C (store wiring, WS-05 §6/§7) | Shared filesystem `SessionStore` + pinned dialect: Claude→Winter, Winter→Claude, and both round-trips at every advertised level. | SCOPED, and the scope is what this row's own tests cover: both legs are produced by the SHARED STORE over the pinned dialect, at every advertised level, over real `mkdtemp` homes. A Claude leg written by the PINNED RUNTIME is covered next door rather than here — `docs/probes/materialized-resume.md`'s probe (c) drives both round-trip orders with the real artifact producing every Claude leg, and as of round 2 it PASSES (its round-1 failure was two probe-side defects: a seed that never reached the canonical store, and a line-adjacency rule stricter than the dialect and than the barrier's own step 5). All four probes now pass measured, so `probe()` reports `preferred`; the SHIPPED default is still `fallback`, because the door follows a measurement a host takes on its own pin. No `agent-state` or `full-filesystem` compatibility claim rests on this row. |
22
+ | WS17-11 | **proven** | Lane C (store wiring) | Delete/rebuild of the disposable `sessions/index.db` preserves runtime mappings, backend IDs, cursors. | Proven the strong way and the structural way: the data survives a delete/rebuild BECAUSE none of it lives in the index, and a source scan pins that the router never reads the index at all. |
23
+ | WS17-12 | **proven** | Lane B (the inbound policy and the mailbox, WS-10 §13) | Documented message-size, 50-accepted/100-held queues, 5-minute dialog expiry, 12-hour idle subscription, permission-class behavior; inert `@` mentions retained. | The expiry clause carries one interim behaviour a host must know and the README states: the sweep is LAZY — a held message's receipt is rewritten to `refused` when something next addresses that receiver, not on a timer of its own. |
24
+ | WS17-13 | **proven** (router-scoped — see the note) | the spine (the packing and source gates), with this file's lockfile-integrity check | No verbatim all-rights-reserved artifacts in the Winter distribution; ephemeral CI fetch only. | Scoped to the ROUTER's own distribution: the artifact exists only in gitignored `node_modules`, is pinned by lockfile integrity (the plan's Global Constraints), and is rejected by the pack scan if it ever reaches a tarball. WS-02 §6's checksum-verified ephemeral FETCH is the SDK repository's own harness gate and stays there. |
25
+ | WS17-14 | **proven** | Lane A (builtin-path containment, WS-14 §8) | Native + aliased Agent/worktree, durable Cron, workflow, saved-approval, plan-mode, and arbitrary file/shell paths cannot create `CLAUDE.md`, `.claude/`, or `~/.claude/plans` under strict policy. | Two layers, and the scope is exact. PRE-HOC: the permission floor refuses any call whose arguments name a forbidden target — path fields (case-folded, NFKC), command text (un-normalized, quote-stripped), and the §8 writers with no path argument at all — installed by `launch()` itself on EVERY launch — merged ahead of the caller's own hooks and never replaced by one of them (the floor is recognised by IDENTITY: a hook merely stamped with the exported floor mark is not the floor, and a genuine floor built under a looser template policy does not stand in for the adapter's own) — and required by `assertOptionsInvariants` by that same identity, not merely offered by the options builder. POST-HOC: a sweep registered on PostToolUse, PostToolUseFailure and PostToolBatch snapshots the forbidden names under the session's cwd AND the child's HOME, to a bounded depth (6 by default), around every filesystem-touching call; it removes what APPEARED under its roots during the call, records a typed containment breach, and ends the turn. SCOPE, stated rather than implied: shell-escape and constructed-name spellings are caught POST-HOC by the sweep, never pre-hoc; the sweep sees the SYNCHRONOUSLY-VISIBLE effects of the call it brackets (a background write that lands later is caught opportunistically by the next swept call), and its diff is TIME-BASED rather than causal — under the child's HOME that means a vendor home created by something else during a long call is removed and attributed to that call, which is narrow (an existing one is in every baseline and is never touched) but is what the wording says; it does not look outside cwd and HOME, nor below its depth bound; and the TURN ends only for a call that SUCCEEDS — for a failing call the guarantee is that the artifact does not survive it. |
26
+ | WS17-15 | **proven** (router-scoped — see the note) | Lane C (temp continuity and the barrier) with Lane A (the supervised proxy) | Canonical memory + the D18 temp layout, cross-engine temp continuity, vendor temp roots reported honestly, supervised pre-cleanup reconciliation, default-spawn `mirror_error` handoff refusal, entire-adapter projection, `$bunfs` extraction avoided or tested. | SCOPED: six of the row's seven clauses are proven, four of them against the pinned runtime. The seventh — `$bunfs` extraction avoided or tested — is NOT claimed here: it is a property of how a HOST packages this package (a single-file Bun executable extracting its own embedded runtime), and nothing in this repository builds one. A row that counted it would be counting somebody else's build. The `entire-adapter projection` clause is likewise the projector's (Phase 8, WS-15 §4), and what this row proves for it is the durable half — the roots and records a projector reads. |
27
+ | WS17-17 | **proven** | Lane D | Two identical raw model IDs behind different providers keep distinct provider-qualified identity/credentials/continuation/resume routes. | The fixture mirrors the generated catalog, where `claude-opus-5` really is six rows behind six providers. |
28
+
29
+ ## Phase 7b rulings discharged (not WS-17 rows)
30
+
31
+ | Ruling | Status | Owner | Obligation | Scope / note |
32
+ | --- | --- | --- | --- | --- |
33
+ | D13/D28 | **proven** | Lane D | The runtime-selection table: Claude OAuth → official always (D14-gated); a Claude-family model on a backend the official branch serves in Code mode → official; Claude through other endpoints and all Dispatch/Chat → Winter; never a raw model-ID substring; the persisted selection wins. | — |
34
+ | D14 gate | **proven** | Lane D | The Claude OAuth ship gate is closed by default, and a closed gate refuses rather than falling back to the Winter runtime. | — |
35
+ | R-7b-1 | **proven** | Lane D (the selection half; the delivery half is Lane B's) | A child runs on the runtime its OWN slot's family selects, independent of the parent's; the child's selection is persisted with the child, resume follows the child's record, and a cross-runtime pair talks only through the RuntimeDirectory. | — |
36
+ | WS13c-SM1/2/3 | **proven** | Lane D (selection level; the `DeliveryOutcome` half is Lane B's) | A parent switching family leaves its child's record untouched (both directions), and a child whose provider credential is gone refuses with `child-provider-unavailable` while the parent's turn continues. | — |
37
+ | R-7b-8 | **proven** | Lane D | The D29 probe: whether the pinned official runtime exposes an advisor server tool in an SDK session, and under which condition, measured against the pinned artifact through the loopback capture and recorded. | REWRITTEN IN THE FIX WAVE (whole-branch F-1). The first version's citations pointed at tests asserting that `settings.advisorModel` put an advisor on the wire; that was the pinned artifact PLUS its remote feature configuration, and it went red whenever the CDN fetch timed out. With the runtime's four traffic opt-outs set, no condition puts an advisor anywhere — it is a remotely-flagged capability, not a property of the pin. D29's split is unaffected either way (nothing client-side to alias under either condition). One labelled non-hermetic leg survives behind `WINTER_D29_ALLOW_REMOTE_CONFIG=1` and is evidence for nothing. The probe skips with a printed reason where the pinned runtime cannot start, so the citation is to the tests AND to the record they produce. |
38
+
39
+ ## Citations
40
+
41
+ ### WS17-1
42
+
43
+ - `test/joint/rows-1-2.test.ts` — `row 1 — a model-emitted SendMessage is delivered by the REAL router, and the router's typed outcome is what the model sees`
44
+ - `test/joint/rows-1-2.test.ts` — `row 1 — a refusal is rendered as a classified failure the model can act on, not as a crash`
45
+ - `test/joint/rows-1-2.test.ts` — `the REVERSE direction — a peer's message reaches the live official session's own row, through the router`
46
+ - `test/official/runtime-aliases.test.ts` — `row 1: a model-emitted `SendMessage` reaches the canonical handler with NATIVE args, and its result is what the model sees`
47
+ - `test/messaging/handlers.test.ts` — `a retry with the SAME vendor tool-use id returns the stored outcome, not a second delivery`
48
+
49
+ ### WS17-2
50
+
51
+ - `test/joint/rows-1-2.test.ts` — `row 2 — a model-emitted ListAgents renders the REAL directory, and both canonical twins are advertised`
52
+ - `test/official/runtime-aliases.test.ts` — `row 2: `ListAgents` aliases the same way, and the advertised set records what 0.3.250 actually does`
53
+ - `test/official/aliases-containment.test.ts` — `the canonical duplicates are DEFERRED rather than hidden — they stay addressable by name`
54
+
55
+ ### WS17-3
56
+
57
+ - `test/official/runtime-aliases.test.ts` — `row 3: the paths the alias does not cover — the canonical name direct, and where a deny rule must be spelled`
58
+ - `test/official/aliases-containment.test.ts` — `the floor is a PATH rule, so it covers tools no disposition anticipated`
59
+
60
+ ### WS17-4
61
+
62
+ - `test/official/runtime-spool.test.ts` — `row 4: two sessions under ONE spool stay isolated, and neither can see the vendor home`
63
+ - `test/messaging/official-pair.test.ts` — `DISCOVERY is isolated: each sees the other session and its OWN children, never the other's`
64
+ - `test/messaging/official-pair.test.ts` — `DELIVERY between the two lands in the receiver's own handle, attributed to the sender`
65
+ - `test/messaging/official-pair.test.ts` — `HOLD and REFUSE are the receiver's, and neither delivers anything`
66
+ - `test/messaging/official-pair.test.ts` — `IDLE WAKE: an idle official session starts one turn (`delivered`), a running one queues`
67
+ - `test/joint/rows-4-5.test.ts` — `two live official sessions get DIFFERENT config dirs, each under its own spool`
68
+ - `test/joint/rows-4-5.test.ts` — `a model in one official session DISCOVERS and ADDRESSES the other, and the delivery lands in it`
69
+ - `test/joint/rows-4-5.test.ts` — `a receiver whose permission class cannot be known is HELD, not delivered — fail-closed, with the real runtime as the sender`
70
+ - `test/joint/rows-4-5.test.ts` — `notify_when_idle against an OFFICIAL target refuses the whole call — measured, because this branch has no idle signal`
71
+
72
+ ### WS17-5
73
+
74
+ - `test/messaging/official-pair.test.ts` — `recovery keeps the completed children, and a native SendMessage to one routes through the resumed parent`
75
+ - `test/messaging/official-pair.test.ts` — `before the parent is resumed, the same send is retryably unavailable rather than not-found`
76
+ - `test/joint/rows-4-5.test.ts` — `generation two is a real `resume()` of generation one's backend session, and the completed children are addressable through it`
77
+
78
+ ### WS17-7
79
+
80
+ - `test/messaging/directory.test.ts` — `rule 4 — ambiguity RETURNS CANDIDATES rather than choosing, and the candidates are directory rows`
81
+ - `test/messaging/directory.test.ts` — `rule 5 — a name whose only holder is gone is STALE, not not-found (the lease outlives the row)`
82
+ - `test/messaging/router.test.ts` — `a retry of the same (sender, tool-call) pair returns the STORED outcome and starts no second turn`
83
+ - `test/messaging/router.test.ts` — `the dedupe survives a RESTART, because the id is derived rather than counted`
84
+ - `test/messaging/router.test.ts` — `the envelope and its resolved generation are persisted, and the delivery is CLAIMED, before the adapter runs`
85
+ - `test/messaging/router.test.ts` — `an adapter that THROWS is delivery_uncertain, and the record keeps the claim`
86
+ - `test/messaging/router.test.ts` — `an identical rapid repeat is suppressed with a VISIBLE outcome, and allowed again after the window`
87
+ - `test/messaging/router.test.ts` — `a reply chain is stopped at MAX_HOP_COUNT — the bound is machinery, not documentation`
88
+ - `test/messaging/router.test.ts` — `the subscription SURVIVES A RESTART — a new router over the same store still fires it`
89
+ - `test/messaging/recovery.test.ts` — `step 5 turns every claimed-but-unreceipted delivery into delivery_uncertain, and redelivers nothing`
90
+
91
+ ### WS17-8
92
+
93
+ - `test/store/rows.test.ts` — `Claude -> Winter, Winter -> Claude and both round trips at level`
94
+ - `test/store/rows.test.ts` — `the subagent level round-trips too: a subkey survives both directions`
95
+
96
+ ### WS17-11
97
+
98
+ - `test/store/rows.test.ts` — `runtime mappings, backend ids and cursors all survive, because none of them live there`
99
+ - `test/store/rows.test.ts` — `the router never reads the product index: its name appears nowhere in this lane's source`
100
+
101
+ ### WS17-12
102
+
103
+ - `test/messaging/router.test.ts` — `a body over MAX_GLOBAL_MESSAGE_SIZE is refused before anything is resolved`
104
+ - `test/messaging/policy.test.ts` — `a DELIVERED message (an idle receiver, one turn started) frees its slot; a QUEUED one does not`
105
+ - `test/messaging/policy.test.ts` — `the held cap survives a RESTART — the in-memory box is rehydrated from the durable store`
106
+ - `test/messaging/policy.test.ts` — `a DEFAULT-class hold expires after five minutes; an EXPLICIT hold never does`
107
+ - `test/messaging/router.test.ts` — `a subscription past its 12-hour expiry fires nothing and is swept`
108
+ - `test/messaging/policy.test.ts` — `prompts receiver x BYPASSES sender holds, visibly, with the envelope kept durably`
109
+ - `test/messaging/policy.test.ts` — ``@` mentions and slash-command text survive the router's own rendering byte-identically`
110
+
111
+ ### WS17-13
112
+
113
+ - `test/gates/release-gates.test.ts` — `nothing tracked is the pinned package, its bundle, or a vendored copy`
114
+ - `test/gates/scripts.test.ts` — `an embedded Anthropic artifact is rejected, by directory name and by file name`
115
+ - `test/gates/scripts.test.ts` — `rule 7: the OPTIONAL peer named in a REACHABLE declaration is rejected -- and only there`
116
+ - `test/conformance/rows.test.ts` — `row 13's other half — the pinned artifact is fetched by integrity hash into a gitignored tree`
117
+
118
+ ### WS17-14
119
+
120
+ - `test/official/runtime-containment.test.ts` — `the native writers: every §8 row is EXERCISED, and the tally says which containment stopped it`
121
+ - `test/official/runtime-containment.test.ts` — `arbitrary file and shell paths: an approving broker does not lift the floor`
122
+ - `test/official/runtime-containment.test.ts` — `review r2, NEW-3: a command that BUILDS the name is caught post-hoc — swept, reported, and the call blocked`
123
+ - `test/official/runtime-containment.test.ts` — `review r3, NEW-9: a command whose side effect precedes a FAILURE is swept too`
124
+ - `test/official/runtime-containment.test.ts` — `review r3, NEW-11: the saved-approval path, for real — the durable update is stripped and no vendor settings file appears`
125
+ - `test/official/runtime-containment.test.ts` — `review r4, NEW-18 (a): a host hook stamped with the exported floor mark does not REPLACE the floor — the floor is recognised by identity`
126
+ - `test/official/runtime-containment.test.ts` — `the whole session's writes stay inside the spool, the cwd and the product home`
127
+
128
+ ### WS17-15
129
+
130
+ - `test/store/rows.test.ts` — `the temp home stabilizes in the vendor engine dir across a full round trip`
131
+ - `test/store/rows.test.ts` — `the vendor temp roots are reported honestly, including the one a copy left behind`
132
+ - `test/store/rows.test.ts` — `supervised PRE-CLEANUP reconciliation: the entries are in the store before the staging root is deleted`
133
+ - `test/store/rows.test.ts` — `a DEFAULT-SPAWN session with a mirror error is refused, never reconciled by guesswork`
134
+ - `test/official/runtime-spool.test.ts` — `row 15: the vendor temp root is what we configured PLUS the engine's own segment, reported honestly`
135
+ - `test/official/runtime-spool.test.ts` — `§1 profile 2 + §6 rules 2/3: a store-backed resume is observed as a staging root, and reconciliation runs BEFORE cleanup`
136
+
137
+ ### WS17-17
138
+
139
+ - `test/selection/row-17.test.ts` — `row 17 — the fixture really is one raw model id behind several providers`
140
+ - `test/selection/row-17.test.ts` — `row 17 identity — two selections of the same raw id keep distinct provider-qualified identities`
141
+ - `test/selection/row-17.test.ts` — `row 17 credentials — each row is admitted by ITS OWN provider's credential ref, never a sibling's`
142
+ - `test/selection/row-17.test.ts` — `row 17 continuation — the same raw id routes to DIFFERENT runtimes depending on the provider`
143
+ - `test/selection/row-17.test.ts` — `row 17 resume — a record on one provider never resumes onto its twin behind another provider`
144
+ - `test/selection/row-17.test.ts` — `row 17 — two children on the same raw id under one parent stay two distinct records`
145
+
146
+ ### D13/D28
147
+
148
+ - `test/selection/select-runtime.test.ts` — `D13 row 1 — a Claude OAuth credential routes to the official runtime, always`
149
+ - `test/selection/select-runtime.test.ts` — `D13 row 2 — a Claude-family model on an Anthropic-protocol backend in Code mode routes to the official runtime`
150
+ - `test/selection/select-runtime.test.ts` — `D13 row 2 — a Console OAuth bearer on the Anthropic-dialect backend routes to the official runtime`
151
+ - `test/selection/select-runtime.test.ts` — `D13 row 2 — a cloud credential chain is a backend the official branch serves, dialect notwithstanding`
152
+ - `test/selection/select-runtime.test.ts` — `officialServesBackend agrees with OFFICIAL_SERVED_AUTH_FAMILIES for every auth family`
153
+ - `test/selection/select-runtime.test.ts` — `D13 row 3 — the same Claude model through a non-Anthropic-protocol endpoint routes to Winter`
154
+ - `test/selection/select-runtime.test.ts` — `D13 row 3 — Dispatch and Chat run on Winter even on the Anthropic-protocol backend`
155
+ - `test/selection/select-runtime.test.ts` — `D28 — a gpt-family slot routes to Winter even with an official peer present`
156
+ - `test/selection/select-runtime.test.ts` — `no branch reads a raw model id — renaming every model id leaves the decision unchanged`
157
+ - `test/selection/select-runtime.test.ts` — `the persisted selection wins and is returned by identity, never re-decided`
158
+ - `test/selection/select-runtime.test.ts` — `a persisted selection that no longer matches a fresh decision is reported as handoff-required, not rewritten`
159
+
160
+ ### D14 gate
161
+
162
+ - `test/selection/select-runtime.test.ts` — `the D14 ship gate ships closed — the shipped default flag refuses a Claude OAuth session`
163
+ - `test/selection/select-runtime.test.ts` — `D13 row 1 — Claude OAuth with the D14 ship gate closed is refused, never downgraded to Winter`
164
+ - `test/selection/select-runtime.test.ts` — `D13 row 1 — Claude OAuth outside Code mode is refused: Code-only even after D14 approval`
165
+ - `test/selection/select-runtime.test.ts` — `D13 row 1 — Claude OAuth with no official peer is refused, because it never routes to Winter`
166
+
167
+ ### R-7b-1
168
+
169
+ - `test/selection/child-runtime.test.ts` — `R-7b-1 — the same child under two different parents produces the identical record`
170
+ - `test/selection/child-runtime.test.ts` — `R-7b-1 — a Claude-family child of a Winter parent runs on the official runtime`
171
+ - `test/selection/child-runtime.test.ts` — `R-7b-1 — a gpt-family child of an official parent runs on the Winter runtime`
172
+ - `test/selection/child-runtime.test.ts` — `R-7b-1 — a cross-runtime parent/child pair is flagged for the directory channel`
173
+ - `test/selection/child-runtime.test.ts` — `WS-13c §8 — a resume never re-decides the runtime, even when the table would now differ`
174
+ - `test/selection/child-runtime.test.ts` — `WS-13c §8 — a resume succeeds on a recorded row that is not its provider's first row`
175
+ - `test/selection/child-runtime.test.ts` — `WS-13c §8 — a resume refuses when the recorded ROW is unservable though its provider still serves the model`
176
+ - `test/selection/child-runtime.test.ts` — `WS-13c §8 — a resume refuses when the recorded row has moved into another family`
177
+
178
+ ### WS13c-SM1/2/3
179
+
180
+ - `test/selection/child-runtime.test.ts` — `WS13c-SM1 — a gpt parent's sonnet child is unchanged when the parent switches to claude`
181
+ - `test/selection/child-runtime.test.ts` — `WS13c-SM2 — a claude parent's gpt child is unchanged when the parent switches to gpt`
182
+ - `test/selection/child-runtime.test.ts` — `WS13c-SM3 — a child whose credential is gone refuses with child-provider-unavailable and is not retryable`
183
+
184
+ ### R-7b-8
185
+
186
+ - `test/selection/d29-advisor-probe.test.ts` — `the probe drove the PINNED artifact, over loopback only, and printed its inventories`
187
+ - `test/selection/d29-advisor-probe.test.ts` — `D29 — no condition puts an advisor tool in the session's advertised tool inventory`
188
+ - `test/selection/d29-advisor-probe.test.ts` — `D29 — configuring an advisor model puts NOTHING advisor-shaped on the wire (the pinned artifact, alone)`
189
+ - `test/selection/d29-advisor-probe.test.ts` — `D29 — no advisor appears in ANY hermetic condition, on the wire or in the inventory`
190
+ - `test/selection/d29-advisor-probe.test.ts` — `the remote-configuration leg, when it is explicitly enabled, shows what the CDN adds`
191
+ - `docs/probes/d29-advisor.md` — `## 3. Verdict`
192
+
193
+ ## Still unproven
194
+
195
+ None — every row above carries at least one machine-verified citation.
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@yanlinglabs/winter-runtime-sdk",
3
+ "version": "0.0.1",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "description": "One door over the Winter Agent SDK and the official Claude Agent SDK: runtime selection, the official-SDK adapter, the shared session store, the handoff barrier and the cross-runtime messaging router.",
7
+ "engines": {
8
+ "node": ">=18"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/yanlingLabs/winter-runtime-sdk.git"
13
+ },
14
+ "homepage": "https://github.com/yanlingLabs/winter-runtime-sdk",
15
+ "bugs": {
16
+ "url": "https://github.com/yanlingLabs/winter-runtime-sdk/issues"
17
+ },
18
+ "main": "./dist/index.js",
19
+ "types": "./dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "default": "./dist/index.js"
24
+ }
25
+ },
26
+ "files": [
27
+ "dist",
28
+ "README.md",
29
+ "LICENSE",
30
+ "docs/conformance-rows.md"
31
+ ],
32
+ "publishConfig": {
33
+ "access": "restricted"
34
+ },
35
+ "winter": {
36
+ "publish": {
37
+ "npm": true
38
+ }
39
+ },
40
+ "peerDependencies": {
41
+ "@anthropic-ai/claude-agent-sdk": "0.3.250",
42
+ "@yanlinglabs/winter-agent-sdk": ">=0.0.2 <0.1.0"
43
+ },
44
+ "peerDependenciesMeta": {
45
+ "@anthropic-ai/claude-agent-sdk": {
46
+ "optional": true
47
+ }
48
+ },
49
+ "devDependencies": {
50
+ "@anthropic-ai/claude-agent-sdk": "0.3.250",
51
+ "@types/bun": "^1.3.0",
52
+ "@types/node": "^26.4.0",
53
+ "@yanlinglabs/winter-agent-sdk": "^0.0.2",
54
+ "@yanlinglabs/winter-conformance": "^0.0.2",
55
+ "@yanlinglabs/winter-provider-conformance": "^0.0.2",
56
+ "typescript": "^5.9.0"
57
+ },
58
+ "scripts": {
59
+ "build:packages": "bun run scripts/build-packages.ts",
60
+ "release:pack": "bun run scripts/release-pack.ts",
61
+ "smoke:installed": "bun run scripts/smoke-installed.ts",
62
+ "typecheck": "tsc --noEmit -p tsconfig.typecheck.json",
63
+ "test": "bun test"
64
+ }
65
+ }