1use crate::error::Severity;
19
20pub struct DiagnosticInfo {
24 pub code: &'static str,
25 pub summary: &'static str,
26 pub grammar_symbol: &'static [&'static str],
34 pub severity: Severity,
42}
43
44pub const BOOK_BASE_URL: &str = "https://bynk-lang.org";
48
49pub struct Explain {
64 pub code: &'static str,
67 pub blurb: &'static str,
70 pub example: &'static str,
72 pub page: &'static str,
77 pub anchor: &'static str,
79}
80
81impl Explain {
82 pub fn href(&self) -> String {
85 let mut url = format!("{BOOK_BASE_URL}{}/", self.page);
86 if !self.anchor.is_empty() {
87 url.push('#');
88 url.push_str(self.anchor);
89 }
90 url
91 }
92
93 pub fn in_site_link(&self) -> String {
99 let mut link = format!("{}/", self.page);
100 if !self.anchor.is_empty() {
101 link.push('#');
102 link.push_str(self.anchor);
103 }
104 link
105 }
106}
107
108pub const EXPLANATIONS: &[Explain] = &[
113 Explain {
114 code: "bynk.given.undeclared_capability",
115 blurb: "A handler may only use a capability it has itself declared with \
116 `given`. Effects in Bynk are explicit: the `given` clause is the \
117 handler's honest, checkable statement of every capability it \
118 reaches for, so a reader (and the compiler) can see a handler's \
119 full reach from its signature alone. Using a capability that is \
120 not in `given` is the missing half of that contract.",
121 example: "on get \"/now\" -> Text { // ✗ uses Clock without declaring it\n \
122 Clock.now()\n}\n\n\
123 on get \"/now\" given Clock -> Text { // ✓ declared, then used\n \
124 Clock.now()\n}",
125 page: "/book/guides/effects-and-capabilities/understand-the-capability-model",
126 anchor: "",
127 },
128 Explain {
129 code: "bynk.given.unknown_capability",
130 blurb: "A `given` clause names a capability that no provider declares. A \
131 capability is a typed interface to the outside world; it has to be \
132 *declared* (as a `capability`, or brought in from a consumed \
133 context) before a handler can ask for it. This usually means a \
134 typo in the capability name, or a missing `uses`/`consumes` that \
135 would bring the capability into scope.",
136 example: "on get \"/\" given Clok -> Text { … } // ✗ no capability named `Clok`\n\n\
137 on get \"/\" given Clock -> Text { … } // ✓ matches the declared capability",
138 page: "/book/reference/capabilities",
139 anchor: "declaring-a-capability",
140 },
141 Explain {
142 code: "bynk.resolve.missing_field",
143 blurb: "A record must be constructed with every one of its fields. Bynk \
144 records have no defaults and no partial construction: a value of a \
145 record type is only valid once all its fields are present, so a \
146 downstream reader never has to wonder whether a field was set. \
147 Omitting a field is therefore an error, not a fill-in-later.",
148 example: "type User = { name: Text, age: Int }\n\n\
149 User { name: \"Ada\" } // ✗ missing `age`\n\
150 User { name: \"Ada\", age: 36 } // ✓ every field present",
151 page: "/book/reference/types",
152 anchor: "record-types",
153 },
154 Explain {
155 code: "bynk.resolve.unknown_field",
156 blurb: "A field access names a field the record type does not have. A \
157 record's fields are fixed by its type declaration; only those \
158 names exist on the value. This is usually a typo in the field \
159 name, or an access meant for a different type.",
160 example: "type User = { name: Text }\n\n\
161 user.nmae // ✗ no field `nmae`\n\
162 user.name // ✓ the declared field",
163 page: "/book/reference/types",
164 anchor: "record-types",
165 },
166 Explain {
167 code: "bynk.resolve.unknown_name",
168 blurb: "A name was referenced that is not in scope. Every name in Bynk \
169 must be introduced before use — as a `let` binding, a parameter, \
170 a `fn`, a type, or a member brought in through `uses`/`consumes`. \
171 An unknown name is typically a typo, a missing declaration, or a \
172 reference to something defined in a module that has not been \
173 brought into scope.",
174 example: "let greeting = \"hi\"\n\
175 greetng // ✗ no name `greetng` in scope\n\
176 greeting // ✓ the bound name",
177 page: "/book/guides/program-structure/how-a-program-is-shaped",
178 anchor: "",
179 },
180 Explain {
181 code: "bynk.resolve.unknown_type",
182 blurb: "A type name was referenced that does not exist. Types must be \
183 declared (with `type`), be one of Bynk's built-in types, or be \
184 brought into scope from another module before they can be named. \
185 An unknown type is usually a typo or a missing declaration/import.",
186 example: "fn greet(u: Usr) -> Text { … } // ✗ no type `Usr`\n\
187 fn greet(u: User) -> Text { … } // ✓ the declared type",
188 page: "/book/reference/types",
189 anchor: "",
190 },
191];
192
193pub fn explain(code: &str) -> Option<&'static Explain> {
196 EXPLANATIONS.iter().find(|e| e.code == code)
197}
198
199pub fn lookup(code: &str) -> Option<&'static DiagnosticInfo> {
203 REGISTRY.iter().find(|d| d.code == code)
204}
205
206pub const REGISTRY: &[DiagnosticInfo] = &[
208 d(
209 "bynk.actor.bearer_identity_not_string_constructible",
210 "A `Bearer` actor's identity is not a string-constructible type.",
211 ),
212 d(
213 "bynk.actor.bearer_missing_secret",
214 "A `Bearer` actor does not name its signing secret.",
215 ),
216 d(
217 "bynk.actor.binder_shadows_param",
218 "A `by` actor binder collides with a handler parameter of the same name.",
219 ),
220 d(
221 "bynk.actor.by_on_agent",
222 "A `by` actor clause was placed on an agent `on call` handler, which has no actor.",
223 ),
224 d(
225 "bynk.actor.duplicate_sum_scheme",
226 "Two peers in a multi-actor sum share an authentication scheme.",
227 ),
228 d(
229 "bynk.actor.foreign_context_name_unkeyable",
230 "A context declaring a `Foreign` actor has a name no call key can be named from.",
231 ),
232 d(
233 "bynk.actor.foreign_duplicate_secret",
234 "A `Foreign` actor's secret is also another actor's secret in the same context.",
235 ),
236 d(
237 "bynk.actor.foreign_identity_unsupported",
238 "A `Foreign` actor declares an `identity`.",
239 ),
240 d(
241 "bynk.actor.foreign_missing_secret",
242 "A `Foreign` actor does not name the secret its calls are signed with.",
243 ),
244 d(
245 "bynk.actor.foreign_name_is_context_name",
246 "A `Foreign` actor's name could be read as a context's name.",
247 ),
248 d(
249 "bynk.actor.foreign_reserved_secret",
250 "A `Foreign` actor's secret uses a `BYNK_CALL_` edge key's name.",
251 ),
252 d(
253 "bynk.actor.foreign_secret_not_string",
254 "A `Foreign` actor's secret is not a string.",
255 ),
256 d(
257 "bynk.actor.identity_not_sealed",
258 "An actor identity type is not a context-ownable (sealed) value type.",
259 ),
260 d(
261 "bynk.actor.missing_by_on_http",
262 "An HTTP handler lacks the required `by` actor clause.",
263 ),
264 d(
265 "bynk.actor.oidc_identity_not_string_constructible",
266 "An `Oidc` actor's identity is not a string-constructible type.",
267 ),
268 d(
269 "bynk.actor.oidc_missing_audience",
270 "An `Oidc` actor does not name its `audience`.",
271 ),
272 d(
273 "bynk.actor.oidc_missing_issuer",
274 "An `Oidc` actor does not name its `issuer`.",
275 ),
276 d(
277 "bynk.actor.oidc_missing_jwks",
278 "An `Oidc` actor does not name its `jwks` endpoint.",
279 ),
280 d(
281 "bynk.actor.oidc_not_in_sum",
282 "An `Oidc` actor appears as a member of a multi-actor sum.",
283 ),
284 d(
285 "bynk.actor.outside_context",
286 "An `actor` was declared outside a context (e.g. in a commons).",
287 ),
288 d(
289 "bynk.actor.refinement_base_unsupported",
290 "A refinement actor's base is not a `Bearer` actor (no claims to authorise against).",
291 ),
292 d(
293 "bynk.actor.refinement_in_sum",
294 "A refinement actor appears as a member of a multi-actor sum.",
295 ),
296 d(
297 "bynk.actor.refinement_predicate_unsupported",
298 "A refinement actor's `where` predicate is outside the closed claim-predicate set.",
299 ),
300 d(
301 "bynk.actor.scheme_not_admissible",
302 "An actor's scheme is not admissible on this handler's protocol.",
303 ),
304 d(
305 "bynk.actor.signature_identity_unsupported",
306 "A `Signature` actor declared an `identity`, which is not yet supported.",
307 ),
308 d(
309 "bynk.actor.signature_missing_header",
310 "A `Signature` actor does not name its signature header.",
311 ),
312 d(
313 "bynk.actor.signature_missing_secret",
314 "A `Signature` actor does not name its signing secret.",
315 ),
316 d(
317 "bynk.actor.signature_requires_body",
318 "A `Signature` handler does not take a `body` parameter.",
319 ),
320 d(
321 "bynk.actor.signature_tolerance_without_timestamp",
322 "A `Signature` actor set `tolerance` without a `timestamp` header.",
323 ),
324 d(
325 "bynk.actor.sum_requires_binder",
326 "A multi-actor sum `by` clause has no binder to match the resolved actor.",
327 ),
328 d(
329 "bynk.actor.unknown_actor",
330 "A handler's `by` clause names an actor that is not declared.",
331 ),
332 d(
333 "bynk.actor.unknown_scheme",
334 "An actor declares an authentication scheme that is not compiler-known.",
335 ),
336 d(
337 "bynk.actor.unreachable_sum_arm",
338 "A multi-actor sum has an arm unreachable after a catch-all (`None`) peer.",
339 ),
340 dg(
341 "bynk.adapter.consumes_context",
342 "An `adapter` consumed a context; adapter dependencies are adapter-to-adapter.",
343 &["consumes_decl"],
344 ),
345 dg(
346 "bynk.adapter.consumes_requires_selection",
347 "An `adapter` used a whole-unit or aliased `consumes`; adapters must select capabilities with `consumes U { Cap, … }`.",
348 &["consumes_decl"],
349 ),
350 dg(
351 "bynk.adapter.disallowed_item",
352 "An `adapter` declared a `service`, `agent`, or other item it may not contain.",
353 &["adapter_decl"],
354 ),
355 dg(
356 "bynk.adapter.duplicate_binding",
357 "An `adapter` declared more than one `binding` clause.",
358 &["binding_decl"],
359 ),
360 dg(
361 "bynk.adapter.no_binding",
362 "An `adapter` declares an external provider but no `binding` module to supply it.",
363 &["adapter_decl"],
364 ),
365 dg(
366 "bynk.adapter.provider_has_body",
367 "A provider inside an `adapter` has a Bynk body; adapter providers must be external.",
368 &["provider_decl"],
369 ),
370 dg(
371 "bynk.agent.construction_arity",
372 "An agent was constructed with the wrong number of key arguments.",
373 &["agent_decl"],
374 ),
375 dg(
376 "bynk.agent.handler_arity",
377 "An agent handler was called with the wrong number of arguments.",
378 &["agent_decl"],
379 ),
380 dg(
381 "bynk.agent.handler_not_found",
382 "Called a handler the agent does not declare.",
383 &["agent_decl"],
384 ),
385 dg(
386 "bynk.agent.key_mismatch",
387 "An agent key argument has the wrong type.",
388 &["agent_decl"],
389 ),
390 dg(
391 "bynk.agent.outside_context",
392 "An `agent` was declared outside a context.",
393 &["agent_decl"],
394 ),
395 dg(
396 "bynk.agent.return_not_effect",
397 "An agent handler's return type is not an `Effect`.",
398 &["agent_decl"],
399 ),
400 d(
401 "bynk.agent.state_name_conflict",
402 "A type is named `<Agent>State` beside agent `<Agent>`; that name is the agent's state record (its `Cell` fields), which its handlers and invariants see in place of the type.",
403 ),
404 dg(
405 "bynk.agents.bad_state_initialiser",
406 "An agent `store` field initialiser is not a static value of the field's type.",
407 &["store_field"],
408 ),
409 dg(
410 "bynk.agents.non_zeroable_state_field",
411 "An agent `store` field has no initialiser and no implicit zero value.",
412 &["store_field"],
413 ),
414 d(
415 "bynk.asset.duplicate",
416 "An `asset` name is declared more than once in the same unit.",
417 ),
418 d(
419 "bynk.asset.invalid_at_path",
420 "An `asset`'s `at` path is not a URL path naming one file, or lies under `/_assets/` or `/_bynk/`.",
421 ),
422 warn(d(
423 "bynk.asset.may_shadow_route",
424 "A parameterised HTTP route matches a fixed asset path, so it never sees requests for that path (a warning).",
425 )),
426 d(
427 "bynk.asset.missing_file",
428 "An `asset` names a file that is not in the project's `assets/` folder.",
429 ),
430 d(
431 "bynk.asset.needs_project",
432 "A single-file build met an `asset` declaration; assets need a project build.",
433 ),
434 warn(d(
435 "bynk.asset.not_served",
436 "A deployable Bundle build met an `asset`; a Bundle ships no files, so its `.url` would not be served (a warning).",
437 )),
438 d(
439 "bynk.asset.outside_assets_dir",
440 "An `asset` path does not name a file in the project's `assets/` folder.",
441 ),
442 d(
443 "bynk.asset.outside_context_or_commons",
444 "An `asset` declaration appears outside a context or commons.",
445 ),
446 d(
447 "bynk.asset.path_conflict",
448 "Two different asset files would be served at one fixed path by the same Worker.",
449 ),
450 d(
451 "bynk.asset.shadows_route",
452 "A fixed asset path equals a literal HTTP route, which the platform-served asset makes unreachable.",
453 ),
454 d(
455 "bynk.asset.unreadable_file",
456 "An `asset` names a file in the project's `assets/` folder that could not be read.",
457 ),
458 d(
459 "bynk.asset.unsafe_path",
460 "An `asset` path is empty, absolute, or contains a `..` segment.",
461 ),
462 d(
463 "bynk.boundary.ambiguous_type",
464 "A value's type is declared, with different shapes, by more than one consumed context, so its fields cannot be read.",
465 ),
466 d(
467 "bynk.boundary.structural_mismatch",
468 "Data crossing a context boundary did not match the expected shape.",
469 ),
470 dg(
471 "bynk.capability.base_not_instantiable",
472 "A derived capability's base is not a platform resource that can be instantiated.",
473 &["capability_decl"],
474 ),
475 dg(
476 "bynk.capability.derived_outside_context",
477 "A derived capability was declared outside a context.",
478 &["capability_decl"],
479 ),
480 dg(
481 "bynk.capability.instance_only",
482 "A platform capability that is used only through named instances (`Service`) was used bare, in a `given` clause.",
483 &["given_clause"],
484 ),
485 dg(
486 "bynk.capability.invalid_option",
487 "A derived capability's option is not one string literal, is given twice, or (`@worker`) is not a Worker name outside the project.",
488 &["capability_decl"],
489 ),
490 dg(
491 "bynk.capability.missing_option",
492 "A derived capability lacks an option its base requires, such as a `Service` instance's `@worker`.",
493 &["capability_decl"],
494 ),
495 dg(
496 "bynk.capability.not_provided",
497 "On the Workers target, a capability a context requires has no provider in it.",
498 &["given_clause"],
499 ),
500 dg(
501 "bynk.capability.op_arity",
502 "A capability operation was called with the wrong number of arguments.",
503 &["capability_decl"],
504 ),
505 dg(
506 "bynk.capability.outside_context",
507 "A `capability` was declared outside a context.",
508 &["capability_decl"],
509 ),
510 dg(
511 "bynk.capability.unknown_base",
512 "A derived capability's base is not a capability the context consumes.",
513 &["capability_decl"],
514 ),
515 dg(
516 "bynk.capability.unknown_operation",
517 "Referenced an operation the capability does not declare.",
518 &["capability_decl"],
519 ),
520 dg(
521 "bynk.capability.unknown_option",
522 "A derived capability carries an option its base does not take.",
523 &["capability_decl"],
524 ),
525 d(
526 "bynk.cell.invalid_target",
527 "A `:=` write targets something that is not a `store Cell` field.",
528 ),
529 d(
530 "bynk.cell.self_reference",
531 "A `:=` right-hand side reads the cell being written (a read-modify-write); use `.update`.",
532 ),
533 dg(
534 "bynk.consumes.alias_conflict",
535 "Two `consumes` aliases collide.",
536 &["consumes_decl"],
537 ),
538 dg(
539 "bynk.consumes.capability_name_clash",
540 "Two flattened `consumes U { Cap }` capabilities collide, or one clashes with a local capability.",
541 &["consumes_decl"],
542 ),
543 dg(
544 "bynk.consumes.name_conflict",
545 "A `consumes` name collides with another name in scope.",
546 &["consumes_decl"],
547 ),
548 dg(
549 "bynk.consumes.self_reference",
550 "A context `consumes` itself.",
551 &["consumes_decl"],
552 ),
553 dg(
554 "bynk.consumes.service_arity",
555 "A consumed service was called with the wrong number of arguments.",
556 &["consumes_decl"],
557 ),
558 dg(
559 "bynk.consumes.signature_type_unconsumed",
560 "A cross-context call reaches a service whose signature names a type the consumed context itself consumes from a third context, which the caller does not consume.",
561 &["consumes_decl"],
562 ),
563 dg(
564 "bynk.consumes.target_is_commons",
565 "`consumes` targets a `commons` instead of a context.",
566 &["consumes_decl"],
567 ),
568 dg(
569 "bynk.consumes.unknown_context",
570 "`consumes` names a context that does not exist.",
571 &["consumes_decl"],
572 ),
573 dg(
574 "bynk.consumes.unknown_service",
575 "Called a service the consumed context does not declare.",
576 &["consumes_decl"],
577 ),
578 d(
579 "bynk.context.consumes_cycle",
580 "Contexts form a `consumes` dependency cycle.",
581 ),
582 d(
583 "bynk.context.duplicate_binding",
584 "A Worker would declare two bindings with the same name, such as an agent `Kv` and the `bynk.cloudflare` KV namespace (both `KV`).",
585 ),
586 d(
587 "bynk.context.external_construction",
588 "A context-owned type was constructed from outside that context.",
589 ),
590 dg(
591 "bynk.context.external_provider",
592 "A bodiless (external) provider was declared outside an `adapter`.",
593 &["provider_decl"],
594 ),
595 d(
596 "bynk.context.opaque_inspection",
597 "An opaquely-exported type was inspected from outside its context.",
598 ),
599 d(
600 "bynk.context.rebrand_construction",
601 "A variant of a `uses`-sourced commons sum type was constructed directly inside a context, where the emitter's per-context rebrand leaves its constructors out of scope.",
602 ),
603 d(
604 "bynk.contract.duplicate_name",
605 "A function declares two contract clauses (`requires`/`ensures`) with the same name.",
606 ),
607 d(
608 "bynk.contract.impure_predicate",
609 "A contract predicate uses an effectful or test-only construct; a contract clause must be pure.",
610 ),
611 d(
612 "bynk.contract.not_bool",
613 "A contract predicate does not have type `Bool`.",
614 ),
615 d(
616 "bynk.contract.restated_by_test",
617 "A `case`/`property` merely restates a contract clause already declared at the function; the test is redundant.",
618 ),
619 d(
620 "bynk.contract.result_in_requires",
621 "A precondition (`requires`) references `result`; the return value is only in scope inside an `ensures`.",
622 ),
623 dg(
624 "bynk.cron.bad_params",
625 "A cron handler declares more than one parameter, or a non-`Int` one.",
626 &["cron_handler"],
627 ),
628 dg(
629 "bynk.cron.duplicate_schedule",
630 "Two cron handlers declare the same schedule.",
631 &["cron_handler"],
632 ),
633 dg(
634 "bynk.cron.invalid_schedule",
635 "A cron expression is not five whitespace-separated fields.",
636 &["cron_handler"],
637 ),
638 dg(
639 "bynk.cron.return_not_effect_result",
640 "A cron handler does not return `Effect[Result[(), E]]`.",
641 &["cron_handler"],
642 ),
643 d(
644 "bynk.deploy.contract_skew",
645 "A worker was compiled against a contract its live dependencies no longer provide, or no longer provides the contract its live callers were compiled against, so `bynk deploy --context` refuses to ship it.",
646 ),
647 d(
648 "bynk.deploy.foreign_contract_skew",
649 "A build breaks the contract a declared foreign caller's client was generated at, as pinned in `bynk.foreign.toml`, so `bynk deploy` refuses to ship it.",
650 ),
651 d(
652 "bynk.duration.literal_overflow",
653 "A `Duration` literal (`<int>.<unit>`) exceeds the representable millisecond range.",
654 ),
655 dg(
656 "bynk.effect.bind_in_pure_context",
657 "An `<-` bind was used in a pure (non-effectful) context.",
658 &["effect_let_stmt"],
659 ),
660 dg(
661 "bynk.effect.bind_on_non_effect",
662 "An `<-` bind was applied to a non-`Effect` value.",
663 &["effect_let_stmt"],
664 ),
665 d(
666 "bynk.effect.capability_in_pure_context",
667 "A capability was used in a pure context.",
668 ),
669 d(
670 "bynk.effect.cross_context_in_pure_context",
671 "A cross-context call was made in a pure context.",
672 ),
673 dg(
674 "bynk.effect.do_in_pure_context",
675 "A `do` statement was used in a pure (non-effectful) context.",
676 &["do_stmt"],
677 ),
678 dg(
679 "bynk.effect.do_on_non_effect",
680 "A `do` statement was applied to a non-`Effect` value.",
681 &["do_stmt"],
682 ),
683 dg(
684 "bynk.effect.do_requires_unit",
685 "A `do` statement was applied to a valued `Effect[T]`; `do` performs a unit effect, so a real result would be dropped — use `let _ <- e` instead.",
686 &["do_stmt"],
687 ),
688 dg(
689 "bynk.effect.fn_value_in_pure_context",
690 "An effectful function value was called in a pure context; like a capability call, it is legal only where the enclosing body is effectful.",
691 &["call"],
692 ),
693 d(
694 "bynk.effect.unbound_effect",
695 "An `Effect` value in an effectful body was built but not bound with `<-`, sequenced with `do` or returned — in a plain `let`, a list element or a constructor payload — so it runs eagerly and unawaited (#1658).",
696 ),
697 d(
698 "bynk.event.bad_field_default",
699 "An event field's default expression (`field: T = expr`) is not a static, wire-representable value of the field's declared type — a literal (including one admitted to a refined type), a sum variant, `Some`/`None`/`Ok`/`Err`, a record, or `T.unsafe(lit)` for an opaque type whose literal also satisfies the refinement.",
700 ),
701 d(
702 "bynk.event.bad_params",
703 "An `on event` handler declared the wrong number of parameters, or a second parameter whose type is not `EventEnvelope` — it takes the event payload and, optionally, the runtime envelope.",
704 ),
705 d(
706 "bynk.event.bad_schema_dispatch",
707 "A `via schema(...)` dispatch clause's argument is malformed — it must be a single, positive, positional `Int` literal.",
708 ),
709 d(
710 "bynk.event.bad_schema_version",
711 "An event's `@schema(N)` annotation is malformed — `N` must be a single, positive, positional `Int` literal, and `@schema` may appear at most once on an event.",
712 ),
713 d(
714 "bynk.event.default_outside_event",
715 "A field default (`field: T = expr`) was written on a record field outside an `event` declaration — a default is only meaningful on an event's own field, since it exists to let an older wire event missing this key still deserialise.",
716 ),
717 dg(
718 "bynk.event.duplicate_handler",
719 "A `from Events` service declares more than one `on event` handler; it has exactly one.",
720 &["event_handler"],
721 ),
722 d(
723 "bynk.event.emit_not_an_event",
724 "`Events.emit[E]` named a type `E` that is declared in this context, but is not itself an `event` — only an `event` type may be emitted.",
725 ),
726 d(
727 "bynk.event.emit_outside_owner",
728 "`Events.emit[E]` named an event `E` not declared in the emitting context — only an event's declaring context may emit it.",
729 ),
730 d(
731 "bynk.event.handler_param_type_mismatch",
732 "An `on event(e: T)` handler's declared parameter type does not match its `from Events(E)` header's event type.",
733 ),
734 d(
735 "bynk.event.non_additive_schema_change",
736 "An event's field shape changed in a way the schema registry cannot evolve additively — a field was removed, retyped, added without a default, or lost a default it previously had. Give the new shape a new event type name, or make the change additive.",
737 ),
738 d(
739 "bynk.event.outside_context",
740 "An `event` was declared outside a context.",
741 ),
742 d(
743 "bynk.event.pattern_duplicate_field",
744 "A `from Events(E { ... })` subscription pattern listed the same field more than once.",
745 ),
746 d(
747 "bynk.event.pattern_type_mismatch",
748 "A `from Events(E { ... })` subscription pattern field's matched value is not compatible with that field's declared type.",
749 ),
750 d(
751 "bynk.event.pattern_unknown_field",
752 "A `from Events(E { ... })` subscription pattern named a field that `E` does not declare.",
753 ),
754 d(
755 "bynk.event.pattern_unknown_variant",
756 "A `from Events(E { ... })` subscription pattern's variant value names a variant that does not exist on the field's declared sum type.",
757 ),
758 d(
759 "bynk.event.pattern_variant_payload",
760 "A `from Events(E { ... })` subscription pattern's variant value names a variant that carries a payload — only nullary variants are admitted, since testing the tag alone would silently ignore the payload.",
761 ),
762 dg(
763 "bynk.event.return_not_effect_unit",
764 "An `on event` handler returns an `Effect` of something other than `()`; emission is fire-and-forget, so it returns `Effect[()]`.",
765 &["event_handler"],
766 ),
767 d(
768 "bynk.event.schema_version_mismatch",
769 "An event's `@schema(N)` annotation disagrees with the version the schema registry computes from the event's build history.",
770 ),
771 d(
772 "bynk.event.unknown_annotation",
773 "An `event` declaration carried an `@`-annotation other than `@schema` — event annotations are a closed set.",
774 ),
775 d(
776 "bynk.event.unknown_subscription",
777 "A `from Events(E)` subscription named `E`, which is not a declared event in this context or any consumed context.",
778 ),
779 dg(
780 "bynk.expect.faults_not_effect",
781 "A fault claim's subject (`expect <call> faults`) is not an effectful call: a value, or a call whose type is not `Effect[_]`.",
782 &["faults_expr"],
783 ),
784 dg(
785 "bynk.expect.not_bool",
786 "`expect` was given a non-`Bool` predicate.",
787 &["expect_expr"],
788 ),
789 dg(
790 "bynk.expect.outside_case",
791 "`expect` was used outside a `case` body.",
792 &["expect_expr"],
793 ),
794 dg(
795 "bynk.exports.capability_not_provided",
796 "An exported capability has no provider in its context.",
797 &["exports_decl"],
798 ),
799 dg(
800 "bynk.exports.conflicting_visibility",
801 "A type is exported with conflicting visibilities.",
802 &["exports_decl"],
803 ),
804 dg(
805 "bynk.exports.derived_capability",
806 "`exports capability` names a derived capability, whose instance stays with its context.",
807 &["exports_decl"],
808 ),
809 dg(
810 "bynk.exports.duplicate_export",
811 "The same name is exported more than once.",
812 &["exports_decl"],
813 ),
814 dg(
815 "bynk.exports.duplicate_in_clause",
816 "A name appears twice in one `exports` clause.",
817 &["exports_decl"],
818 ),
819 dg(
820 "bynk.exports.undeclared_capability",
821 "`exports capability` names a capability that is not declared.",
822 &["exports_decl"],
823 ),
824 dg(
825 "bynk.exports.undeclared_type",
826 "`exports` names a type that is not declared.",
827 &["exports_decl"],
828 ),
829 d(
830 "bynk.fmt.comment_loss",
831 "The formatter would drop a comment, so it leaves the file unchanged.",
832 ),
833 d(
834 "bynk.fmt.roundtrip",
835 "The formatter's output does not re-parse to the same program, so it leaves the file unchanged.",
836 ),
837 dg(
838 "bynk.generics.duplicate_type_param",
839 "A `type` or `fn` declares the same type-parameter name more than once (v0.157, ADR 0183).",
840 &[],
841 ),
842 dg(
843 "bynk.generics.generic_non_record",
844 "A `type` declaration carries type parameters on a refined or opaque body; only a record (`type Name[T] = { … }`) or sum (`type Name[T] = | … | …`) body may be generic (v0.157/#593, ADRs 0183/0197).",
845 &["type_decl"],
846 ),
847 dg(
848 "bynk.generics.generic_record_at_boundary",
849 "A `Val[…]` fabricates a value of a generic type; per-instantiation value fabrication is not yet wired (ADR 0197). Since v0.174 a generic-record instantiation may otherwise cross a boundary through its monomorphised codec.",
850 &[],
851 ),
852 dg(
853 "bynk.generics.generic_sum_embeds",
854 "A generic sum type carries an `embeds` clause; embedding into a generic sum is not supported (#593).",
855 &["type_decl"],
856 ),
857 dg(
858 "bynk.generics.method_on_generic_type",
859 "A *static* method is attached to a generic type; static methods on generic types are deferred (they have no receiver to supply the type's parameters). Instance methods on generic types are supported (#594).",
860 &["fn_decl"],
861 ),
862 dg(
863 "bynk.generics.no_bounds",
864 "A type parameter carries a bound (`[A: …]`); bounded generics are not in v0.20a.",
865 &["fn_decl"],
866 ),
867 dg(
868 "bynk.generics.recursive_generic_at_boundary",
869 "A recursive generic record (one that transitively contains itself, through any wrapper or generic argument) appears at a boundary; it has no finite set of monomorphised codecs, so it is not yet boundary-serialisable (ADR 0197).",
870 &[],
871 ),
872 dg(
873 "bynk.generics.type_arg_count",
874 "A user-declared generic type is applied to the wrong number of type arguments, or a generic type is named without its `[…]` arguments (v0.157, ADR 0183).",
875 &["applied_type_ref"],
876 ),
877 dg(
878 "bynk.generics.type_arg_mismatch",
879 "Inferred or explicit type arguments conflict, have the wrong arity, target a non-generic function, or a type parameter shadows a declared type.",
880 &["call"],
881 ),
882 dg(
883 "bynk.generics.uninferable_type_arg",
884 "A generic function's type parameter could not be inferred from the arguments and was not given explicitly (`name[T](…)`); a bare generic function also cannot be passed as a value in v0.20a.",
885 &["call"],
886 ),
887 dg(
888 "bynk.given.cross_context_unknown_capability",
889 "`given B.Cap` names a capability the consumed context does not export.",
890 &["given_clause"],
891 ),
892 dg(
893 "bynk.given.undeclared_capability",
894 "A handler uses a capability it did not declare with `given`.",
895 &["given_clause"],
896 ),
897 dg(
898 "bynk.given.unknown_capability",
899 "`given` names a capability that does not exist.",
900 &["given_clause"],
901 ),
902 warn(dg(
903 "bynk.given.unused_capability",
904 "A `given` capability is never used (warning).",
905 &["given_clause"],
906 )),
907 d(
908 "bynk.held.branch_divergence",
909 "Branches of a conditional leave a held value (e.g. `Connection[F]`) in inconsistent ownership states — one consumes or stores it, another leaves it owned (§2.9.5, real-time track slice 2).",
910 ),
911 d(
912 "bynk.held.consume_on_borrow",
913 "A consuming operation (`close`/`put`/`take`) is called on a *borrowed* held reference — borrows admit only non-consuming operations like `send` (§2.9.3, real-time track slice 2).",
914 ),
915 d(
916 "bynk.held.leak",
917 "A held value (`Connection[F]`) is still owned at scope exit — it must be disposed (stored, closed, or transferred) before the handler or function returns (§2.9.1, real-time track slice 2).",
918 ),
919 d(
920 "bynk.held.query_accessor_on_held_map",
921 "A key-aware query accessor (`.entries`/`.keys`/`.values`) is used on a held `Map[K, Connection]` — a held resource is iterated with the broadcast ops (`forEach`/`parTraverse`), not a key query.",
922 ),
923 d(
924 "bynk.held.unsupported_map_op",
925 "A held `Map[K, Connection]` is given an `update`/`upsert` — a held resource cannot be transformed by a `(Connection) -> Connection` function; use `put`/`get`/`remove` (real-time track slice 3b-ii).",
926 ),
927 d(
928 "bynk.held.unsupported_storage",
929 "A held value (`Connection[F]`) is stored in a `Set`/`Log`/`Cache` — held values may only live in `Cell[Option[Connection]]` or `Map[K, Connection]` (§2.9.3, real-time track slice 2).",
930 ),
931 d(
932 "bynk.held.use_after_consume",
933 "A held value (`Connection[F]`) is used after a consuming operation (`close`/`put`/`take`) ended its lifetime (§2.9.2, real-time track slice 2).",
934 ),
935 d(
936 "bynk.history.not_an_agent",
937 "A `for all run: History[T]` names a `T` that is not an agent — only an agent has handlers to sequence and reachable states to observe (testing track slice 7, ADR 0155).",
938 ),
939 d(
940 "bynk.history.not_generable",
941 "A `for all run: History[Agent]` targets an agent with a handler parameter whose type cannot be generated (e.g. a `Matches` refinement), so its call-history cannot be driven (testing track slice 7, ADR 0155).",
942 ),
943 d(
944 "bynk.history.outside_property",
945 "`History[Agent]` appears outside a `property`'s `for all` binding — it is a test-only generator, not a value type (testing track slice 7, ADR 0155).",
946 ),
947 d(
948 "bynk.history.restates_invariant",
949 "A history property merely re-checks a guarantee a declared `invariant`/`transition` already enforces on every reached state (testing track slice 7, ADR 0155).",
950 ),
951 dg(
952 "bynk.http.body_on_get_or_delete",
953 "A GET or DELETE handler declares a `body` parameter.",
954 &["http_handler"],
955 ),
956 d(
957 "bynk.http.cache_bad_max_age",
958 "A `@cache` annotation's `maxAge` is missing or not a positive `Duration` literal.",
959 ),
960 d(
961 "bynk.http.cache_bad_scope",
962 "A `@cache` annotation's `scope` is not `public` or `private`.",
963 ),
964 d(
965 "bynk.http.cache_duplicate",
966 "A handler carries more than one `@cache` annotation.",
967 ),
968 d(
969 "bynk.http.cache_max_age_fractional_seconds",
970 "A `@cache` annotation's `maxAge` is positive but does not resolve to a whole number of seconds.",
971 ),
972 d(
973 "bynk.http.cache_on_non_get",
974 "A `@cache` annotation is placed on a handler that is not `on http GET`.",
975 ),
976 d(
977 "bynk.http.cache_unknown_arg",
978 "A `@cache` annotation has an argument outside the closed set (`maxAge`/`scope`).",
979 ),
980 d(
981 "bynk.http.cors_invalid_field",
982 "A `cors` policy field (`headers`/`credentials`/`maxAge`) has the wrong value shape.",
983 ),
984 d(
985 "bynk.http.cors_invalid_origins",
986 "A `cors` policy's `origins` is missing, empty, or not a list of string literals.",
987 ),
988 d(
989 "bynk.http.cors_not_http",
990 "A `cors { }` policy appears on a service that is not `from http`.",
991 ),
992 d(
993 "bynk.http.cors_unknown_field",
994 "A `cors { }` policy declares a field outside the closed set.",
995 ),
996 d(
997 "bynk.http.cors_wildcard_credentials",
998 "A `cors` policy combines `credentials: true` with the wildcard origin `[\"*\"]`.",
999 ),
1000 dg(
1001 "bynk.http.duplicate_route",
1002 "Two handlers share the same method and route.",
1003 &["http_handler"],
1004 ),
1005 dg(
1006 "bynk.http.extra_param",
1007 "A handler parameter is neither a path parameter nor `body`.",
1008 &["http_handler"],
1009 ),
1010 dg(
1011 "bynk.http.invalid_path",
1012 "An HTTP route path is malformed.",
1013 &["http_handler"],
1014 ),
1015 d(
1016 "bynk.http.limit_bad_max_body",
1017 "A `@limit` annotation's `maxBody` is missing or not a positive `Int` literal.",
1018 ),
1019 d(
1020 "bynk.http.limit_duplicate",
1021 "A handler carries more than one `@limit` annotation.",
1022 ),
1023 d(
1024 "bynk.http.limit_on_bodyless",
1025 "A `@limit` annotation is placed on a handler that takes no body (a GET or DELETE).",
1026 ),
1027 d(
1028 "bynk.http.limit_unknown_arg",
1029 "A `@limit` annotation has an argument outside the closed set (`maxBody`).",
1030 ),
1031 d(
1032 "bynk.http.limits_invalid_field",
1033 "A `limits` policy field (`maxBody`) has the wrong value shape.",
1034 ),
1035 d(
1036 "bynk.http.limits_not_http",
1037 "A `limits { }` policy appears on a service that is not `from http`.",
1038 ),
1039 d(
1040 "bynk.http.limits_unknown_field",
1041 "A `limits { }` policy declares a field outside the closed set.",
1042 ),
1043 dg(
1044 "bynk.http.path_param_not_stringy",
1045 "A path parameter's type is not constructible from a string.",
1046 &["http_handler"],
1047 ),
1048 dg(
1049 "bynk.http.reserved_prefix",
1050 "A route uses the reserved `/_bynk/` prefix.",
1051 &["http_handler"],
1052 ),
1053 dg(
1054 "bynk.http.return_not_effect_http_result",
1055 "An HTTP handler does not return `Effect[HttpResult[T]]`.",
1056 &["http_handler"],
1057 ),
1058 d(
1059 "bynk.http.security_invalid_field",
1060 "A `security` policy field (`hsts`/`nosniff`) has the wrong value shape.",
1061 ),
1062 d(
1063 "bynk.http.security_not_http",
1064 "A `security { }` policy appears on a service that is not `from http`.",
1065 ),
1066 d(
1067 "bynk.http.security_unknown_field",
1068 "A `security { }` policy declares a field outside the closed set.",
1069 ),
1070 dg(
1071 "bynk.http.unbound_path_param",
1072 "A `:name` route segment has no matching handler parameter.",
1073 &["http_handler"],
1074 ),
1075 d(
1076 "bynk.http.unknown_handler_annotation",
1077 "A handler carries an annotation outside the closed set (`@cache`/`@limit`).",
1078 ),
1079 d(
1080 "bynk.index.bad_argument",
1081 "An `@indexed` argument is not a `by: <field>` label.",
1082 ),
1083 warn(d(
1084 "bynk.index.missing",
1085 "A query filters a map by equality on a field that is not `@indexed` (a perf-hint warning).",
1086 )),
1087 d(
1088 "bynk.index.unkeyable_key",
1089 "An `@indexed(by: k)` field is not value-keyable.",
1090 ),
1091 d(
1092 "bynk.index.unknown_key",
1093 "An `@indexed(by: k)` field is not a field of the map's value type.",
1094 ),
1095 warn(d(
1096 "bynk.index.unused",
1097 "A declared `@indexed(by: k)` is never used by an equality filter (a hygiene warning).",
1098 )),
1099 d(
1100 "bynk.invariant.cross_agent_reference",
1101 "An invariant predicate references another agent; invariants are per-agent.",
1102 ),
1103 d(
1104 "bynk.invariant.duplicate_name",
1105 "An agent declares two invariants with the same name.",
1106 ),
1107 d(
1108 "bynk.invariant.impure_predicate",
1109 "An invariant predicate uses an effectful or test-only construct.",
1110 ),
1111 d(
1112 "bynk.invariant.not_bool",
1113 "An invariant predicate does not have type `Bool`.",
1114 ),
1115 dg(
1116 "bynk.lambda.unannotated_param",
1117 "A lambda parameter has no type annotation in a position where no function type is expected to infer it from.",
1118 &["lambda_expr"],
1119 ),
1120 dg(
1121 "bynk.lex.bad_escape",
1122 "An invalid escape sequence in a string literal.",
1123 &["string_literal"],
1124 ),
1125 dg(
1126 "bynk.lex.float_literal_overflow",
1127 "A float literal does not fit a finite 64-bit float.",
1128 &["float_literal"],
1129 ),
1130 dg(
1131 "bynk.lex.integer_overflow",
1132 "An integer literal is outside the `Int` range, the JS safe integers ±(2^53 − 1).",
1133 &["number_literal"],
1134 ),
1135 dg(
1136 "bynk.lex.interpolation_too_deep",
1137 "A string interpolation `\\(…)` nests deeper than the lexer's fixed limit.",
1138 &["string_literal"],
1139 ),
1140 d(
1141 "bynk.lex.unclosed_doc_block",
1142 "A documentation block is not closed.",
1143 ),
1144 d(
1145 "bynk.lex.unexpected_character",
1146 "An unexpected character in the source.",
1147 ),
1148 dg(
1149 "bynk.lex.unterminated_interpolation",
1150 "An interpolation hole `\\(…)` is not closed on its line.",
1151 &["string_literal"],
1152 ),
1153 dg(
1154 "bynk.lex.unterminated_string",
1155 "A string literal is not terminated.",
1156 &["string_literal"],
1157 ),
1158 warn(d(
1159 "bynk.list.deprecated_function",
1160 "A `bynk.list` free function (`map`/`filter`/`find`/`any`/`all`) is deprecated in favour of the `List` method form (warning; auto-fixable).",
1161 )),
1162 d(
1163 "bynk.locale.multiple_message_bundles",
1164 "A context consumes `Locale` but its direct `uses` reaches two or more message-bundle commons — there is no single bundle to negotiate against.",
1165 ),
1166 d(
1167 "bynk.messages.format_mismatch",
1168 "A code's placeholder is formatted as a different ICU kind (plain/plural/select/number/date) across declared locales.",
1169 ),
1170 d(
1171 "bynk.messages.incomplete",
1172 "A locale is missing a code the reference locale declares.",
1173 ),
1174 d(
1175 "bynk.messages.invalid_locale_tag",
1176 "A `messages` block's locale tag is not a valid `LocaleTag` (e.g. `messages \"xx\"` where `xx` doesn't match the tag pattern).",
1177 ),
1178 d(
1179 "bynk.messages.malformed_icu_syntax",
1180 "A message template's ICU placeholder syntax is invalid — unbalanced arm braces, an unknown format keyword, `#` outside a plural arm, a missing mandatory `other` arm, or an explicitly out-of-scope construct (`selectordinal`, `offset:`/`=N`, a CLDR skeleton).",
1181 ),
1182 d(
1183 "bynk.messages.missing_locale_dependency",
1184 "A commons declaring `messages` doesn't `uses bynk.locale` and/or `uses bynk.locale.types`, which its generated `render` and the types its signature names need.",
1185 ),
1186 d(
1187 "bynk.messages.missing_reference",
1188 "A message bundle has no `@reference` block.",
1189 ),
1190 d(
1191 "bynk.messages.multiple_reference",
1192 "A message bundle has more than one `@reference` block.",
1193 ),
1194 d(
1195 "bynk.messages.outside_commons",
1196 "A `messages` declaration appears outside a commons.",
1197 ),
1198 d(
1199 "bynk.messages.placeholder_mismatch",
1200 "A locale's template for a code uses a different set of `{name}` placeholders than the reference locale's.",
1201 ),
1202 d(
1203 "bynk.namespace.reserved",
1204 "A user unit is named `bynk` or `bynk.*`; the `bynk` root is reserved for the toolchain.",
1205 ),
1206 d(
1207 "bynk.observe.impure_with",
1208 "A `with` predicate uses an effectful or test-only construct; it must be pure.",
1209 ),
1210 d(
1211 "bynk.observe.not_a_seam",
1212 "An observation targets a capability the unit under test does not consume.",
1213 ),
1214 d(
1215 "bynk.observe.trace_outside_test",
1216 "`trace(Cap.op)` appears outside a `case` body.",
1217 ),
1218 d(
1219 "bynk.observe.unknown_op",
1220 "An observation names an operation the capability does not declare.",
1221 ),
1222 d(
1223 "bynk.observe.with_not_bool",
1224 "A `with` predicate does not have type `Bool`.",
1225 ),
1226 dg(
1227 "bynk.parse.consumes_after_decls",
1228 "`consumes` appears after other declarations.",
1229 &["consumes_decl"],
1230 ),
1231 d(
1232 "bynk.parse.dangling_handler_annotation",
1233 "A handler-position annotation (e.g. `@cache`) is not followed by an `on` handler.",
1234 ),
1235 d(
1236 "bynk.parse.doc_block_contains_code",
1237 "A documentation block's content (outside Markdown code fences) parses as declarations, so a pair of dash dividers has turned code into documentation.",
1238 ),
1239 d(
1240 "bynk.parse.doc_forms_mixed",
1241 "A declaration or member carries both a `---` doc block and `--|` doc lines; a doc is written in one form.",
1242 ),
1243 dg(
1244 "bynk.parse.duplicate_cors",
1245 "A service declares more than one `cors { }` policy.",
1246 &["service_decl"],
1247 ),
1248 dg(
1249 "bynk.parse.duplicate_limits",
1250 "A service declares more than one `limits { }` policy.",
1251 &["service_decl"],
1252 ),
1253 dg(
1254 "bynk.parse.duplicate_security",
1255 "A service declares more than one `security { }` policy.",
1256 &["service_decl"],
1257 ),
1258 dg(
1259 "bynk.parse.empty_agent",
1260 "An `agent` body is empty.",
1261 &["agent_decl"],
1262 ),
1263 dg(
1264 "bynk.parse.empty_capability",
1265 "A `capability` body is empty.",
1266 &["capability_decl"],
1267 ),
1268 d(
1269 "bynk.parse.empty_interpolation",
1270 "An interpolation hole `\\(…)` contains no expression.",
1271 ),
1272 dg(
1273 "bynk.parse.empty_match",
1274 "A `match` has no arms.",
1275 &["match_expr"],
1276 ),
1277 dg(
1278 "bynk.parse.empty_service",
1279 "A `service` body is empty.",
1280 &["service_decl"],
1281 ),
1282 d(
1283 "bynk.parse.event_pattern_empty",
1284 "A `from Events(E { ... })` subscription pattern listed no fields — use `from Events(E)` (no braces) for an unfiltered subscription.",
1285 ),
1286 dg(
1287 "bynk.parse.expected_agent_key",
1288 "Expected a `key` declaration in an agent.",
1289 &["agent_decl"],
1290 ),
1291 d(
1292 "bynk.parse.expected_agent_storage",
1293 "An agent declares no storage — it has no `store` fields.",
1294 ),
1295 dg(
1296 "bynk.parse.expected_base_type",
1297 "Expected a base type.",
1298 &["base_type"],
1299 ),
1300 dg(
1301 "bynk.parse.expected_capability_op",
1302 "Expected a capability operation.",
1303 &["capability_op"],
1304 ),
1305 d("bynk.parse.expected_expression", "Expected an expression."),
1306 dg(
1307 "bynk.parse.expected_handler",
1308 "Expected a handler.",
1309 &["handler"],
1310 ),
1311 d("bynk.parse.expected_item", "Expected a declaration."),
1312 dg(
1313 "bynk.parse.expected_predicate",
1314 "Expected a refinement predicate.",
1315 &["refinement"],
1316 ),
1317 dg(
1318 "bynk.parse.expected_provider_op",
1319 "Expected a provider operation.",
1320 &["provider_op"],
1321 ),
1322 d("bynk.parse.expected_token", "Expected a specific token."),
1323 d("bynk.parse.expected_type", "Expected a type."),
1324 d(
1325 "bynk.parse.expected_unit_header",
1326 "Expected a `commons` or `context` header.",
1327 ),
1328 dg(
1329 "bynk.parse.expected_visibility",
1330 "Expected a visibility keyword.",
1331 &["exports_decl"],
1332 ),
1333 dg(
1334 "bynk.parse.exports_after_decls",
1335 "`exports` appears after other declarations.",
1336 &["exports_decl"],
1337 ),
1338 d(
1339 "bynk.parse.extra_tokens",
1340 "Unexpected tokens after an otherwise complete construct.",
1341 ),
1342 dg(
1343 "bynk.parse.generic_arg_count",
1344 "Wrong number of generic type arguments.",
1345 &["generic_type_ref"],
1346 ),
1347 dg(
1348 "bynk.parse.handler_in_agent",
1349 "A protocol handler (`on GET`/`schedule`/`message`) was declared in an agent.",
1350 &["handler"],
1351 ),
1352 d(
1353 "bynk.parse.invariant_after_handler",
1354 "An `invariant` was declared after a handler; invariants precede handlers.",
1355 ),
1356 dg(
1357 "bynk.parse.let_else_on_binding",
1358 "An `else` follows a plain `let name = …` binding, which matches every value, so the `else` could never run.",
1359 &["let_stmt", "effect_let_stmt"],
1360 ),
1361 dg(
1362 "bynk.parse.let_pattern_annotation",
1363 "A `let` with a pattern carries a type annotation; the pattern's names take their types from the value.",
1364 &["let_else_stmt"],
1365 ),
1366 dg(
1367 "bynk.parse.let_pattern_without_else",
1368 "A `let` binds a pattern but has no `else` saying what the block produces when the value does not match.",
1369 &["let_else_stmt"],
1370 ),
1371 dg(
1372 "bynk.parse.malformed_float_literal",
1373 "A float literal is missing a digit on one side of the `.` (`1.`, `.5`).",
1374 &["float_literal"],
1375 ),
1376 d(
1377 "bynk.parse.nesting_too_deep",
1378 "An expression or type nests deeper than the parser's fixed limit.",
1379 ),
1380 dg(
1381 "bynk.parse.non_associative",
1382 "A non-associative operator was chained (e.g. `a == b == c`).",
1383 &["binary_expr"],
1384 ),
1385 warn(d(
1386 "bynk.parse.orphan_doc_block",
1387 "A documentation block is not attached to a declaration (warning).",
1388 )),
1389 dg(
1390 "bynk.parse.policy_order",
1391 "A service's `cors`/`security`/`limits` policy is out of order or follows a handler; they open the body in the order `cors`, `security`, `limits`.",
1392 &["service_decl"],
1393 ),
1394 dg(
1395 "bynk.parse.refined_pattern_inner",
1396 "A refined pattern's inner form is something other than `_`.",
1397 &["refined_pattern"],
1398 ),
1399 dg(
1400 "bynk.parse.reserved_keyword",
1401 "A reserved keyword was used as an identifier.",
1402 &["identifier"],
1403 ),
1404 dg(
1405 "bynk.parse.self_outside_method",
1406 "`self` used outside a method or handler.",
1407 &["self_expr"],
1408 ),
1409 d(
1410 "bynk.parse.storage_after_phase",
1411 "Agent storage (`state` / `store`) is declared after the invariants or handlers.",
1412 ),
1413 d(
1414 "bynk.parse.transition_after_handler",
1415 "A `transition` is declared after an agent handler; step invariants precede the handlers.",
1416 ),
1417 d(
1418 "bynk.parse.unexpected_adapter",
1419 "An `adapter` appeared where it is not allowed.",
1420 ),
1421 dg(
1422 "bynk.parse.unexpected_context",
1423 "A `context` appeared where it is not allowed.",
1424 &["context_decl"],
1425 ),
1426 d("bynk.parse.unexpected_eof", "Unexpected end of input."),
1427 dg(
1428 "bynk.parse.unexpected_suite",
1429 "A `suite` appeared where it is not allowed.",
1430 &["suite_decl"],
1431 ),
1432 d(
1433 "bynk.parse.unknown_effect_method",
1434 "An unknown method on `Effect`.",
1435 ),
1436 dg(
1437 "bynk.parse.unknown_handler_kind",
1438 "An unknown handler form (expected `call`, an HTTP method, `schedule`, or `message`).",
1439 &["handler"],
1440 ),
1441 dg(
1442 "bynk.parse.unknown_predicate",
1443 "An unknown refinement predicate.",
1444 &["predicate_name"],
1445 ),
1446 d(
1447 "bynk.parse.unknown_tier",
1448 "A `case`/`suite` `as <tier>` clause names something other than `unit`, `integration`, or `system`.",
1449 ),
1450 dg(
1451 "bynk.parse.uses_after_decls",
1452 "`uses` appears after other declarations.",
1453 &["uses_decl"],
1454 ),
1455 dg(
1456 "bynk.parse.variant_name_case",
1457 "A sum-type or enum variant name is not capitalised.",
1458 &["sum_variant", "enum_type"],
1459 ),
1460 warn(d(
1461 "bynk.project.duplicate_compatibility_flag",
1462 "`bynk.toml`'s `[workers] compatibility_flags` lists a flag twice, or one every Bynk Worker already has; the duplicate is dropped (warning).",
1463 )),
1464 d(
1465 "bynk.project.duplicate_module_doc",
1466 "More than one file of a multi-file unit carries a module doc.",
1467 ),
1468 d(
1469 "bynk.project.file_and_directory",
1470 "A unit exists as both a file and a directory.",
1471 ),
1472 d(
1473 "bynk.project.inconsistent_commons_name",
1474 "A source file's path does not match its declared name.",
1475 ),
1476 d(
1477 "bynk.project.kind_conflict",
1478 "A name is declared as both a commons and a context.",
1479 ),
1480 d(
1481 "bynk.project.no_root",
1482 "No project root could be determined.",
1483 ),
1484 d(
1485 "bynk.project.no_sources",
1486 "The project contains no source files.",
1487 ),
1488 d(
1489 "bynk.project.read_failed",
1490 "A source file could not be read.",
1491 ),
1492 d(
1493 "bynk.project.schema_registry_corrupt",
1494 "`bynk.schema.lock` (the events schema registry) is missing its version field, empty, truncated, or otherwise unparseable — restore it from version control rather than deleting it, since deleting it would silently re-baseline every event's history.",
1495 ),
1496 warn(d(
1497 "bynk.project.unstable_not_experimental",
1498 "`bynk.toml`'s `[unstable] allow` lists an item that nothing experimental lies in or under: it is stable now, so the entry can go (warning).",
1499 )),
1500 d(
1501 "bynk.project.unstable_unknown_item",
1502 "`bynk.toml`'s `[unstable] allow` lists a path that names no standard-library unit, exported item or operation.",
1503 ),
1504 dg(
1505 "bynk.property.restates_refinement",
1506 "A `property` merely re-checks a refinement its type already guarantees.",
1507 &["for_all"],
1508 ),
1509 dg(
1510 "bynk.property.where_not_bool",
1511 "A `for all ... where` filter does not type to `Bool`.",
1512 &["for_all"],
1513 ),
1514 dg(
1515 "bynk.provider.dependency_cycle",
1516 "Providers form a capability dependency cycle through `given`.",
1517 &["provider_decl"],
1518 ),
1519 dg(
1520 "bynk.provider.extra_operation",
1521 "A `provides` block implements an operation not in the capability.",
1522 &["provider_decl"],
1523 ),
1524 dg(
1525 "bynk.provider.generic_op_requires_external",
1526 "A Bynk-bodied `provides` implements a capability operation that declares its own type parameter — only an external (bodiless) provider can.",
1527 &["provider_decl"],
1528 ),
1529 dg(
1530 "bynk.provider.missing_operation",
1531 "A `provides` block is missing a capability operation.",
1532 &["provider_decl"],
1533 ),
1534 dg(
1535 "bynk.provider.outside_context",
1536 "`provides` was declared outside a context.",
1537 &["provider_decl"],
1538 ),
1539 dg(
1540 "bynk.provider.signature_mismatch",
1541 "A `provides` operation's signature does not match the capability.",
1542 &["provider_decl"],
1543 ),
1544 dg(
1545 "bynk.provider.unknown_capability",
1546 "`provides` names a capability that does not exist.",
1547 &["provider_decl"],
1548 ),
1549 d(
1550 "bynk.query.join_key_mismatch",
1551 "A `joinOn`/`leftJoin` left and right key function return different types.",
1552 ),
1553 dg(
1554 "bynk.query.sum_needs_numeric",
1555 "A `sum`/`average` key function does not return a numeric type (`Int`, `Float`, or `Duration`).",
1556 &[],
1557 ),
1558 dg(
1559 "bynk.queue.bad_params",
1560 "An `on message` handler does not take exactly one `message` parameter.",
1561 &["queue_handler"],
1562 ),
1563 dg(
1564 "bynk.queue.duplicate_consumer",
1565 "Two `on message` handlers consume the same queue.",
1566 &["queue_handler"],
1567 ),
1568 dg(
1569 "bynk.queue.invalid_name",
1570 "A `from queue(\"…\")` binding has an empty queue name.",
1571 &["queue_handler"],
1572 ),
1573 dg(
1574 "bynk.queue.return_not_queue_result",
1575 "An `on message` handler does not return `Effect[QueueResult]`.",
1576 &["handler"],
1577 ),
1578 dg(
1579 "bynk.record_spread.field_type_mismatch",
1580 "A record-spread override has the wrong type for the field.",
1581 &["record_spread"],
1582 ),
1583 dg(
1584 "bynk.record_spread.non_record_base",
1585 "The base of a record spread is not a record.",
1586 &["record_spread"],
1587 ),
1588 dg(
1589 "bynk.record_spread.type_mismatch",
1590 "A record spread's base is a different record type.",
1591 &["record_spread"],
1592 ),
1593 dg(
1594 "bynk.record_spread.unknown_field",
1595 "A record spread overrides a field the record does not have.",
1596 &["record_spread"],
1597 ),
1598 dg(
1599 "bynk.refine.literal_violates",
1600 "A literal does not satisfy the refined type's predicate.",
1601 &["refined_type"],
1602 ),
1603 dg(
1604 "bynk.requires.unpinned_dependency",
1605 "An adapter `binding … requires { … }` entry has an unpinned version range.",
1606 &["binding_decl"],
1607 ),
1608 d(
1609 "bynk.resolve.ambiguous_variant",
1610 "A variant name is ambiguous across several sum types.",
1611 ),
1612 dg(
1613 "bynk.resolve.arity_mismatch",
1614 "A function was called with the wrong number of arguments.",
1615 &["call"],
1616 ),
1617 d("bynk.resolve.duplicate_actor", "Two actors share a name."),
1618 dg(
1619 "bynk.resolve.duplicate_agent",
1620 "Two agents share a name.",
1621 &["agent_decl"],
1622 ),
1623 dg(
1624 "bynk.resolve.duplicate_capability",
1625 "Two capabilities share a name.",
1626 &["capability_decl"],
1627 ),
1628 dg(
1629 "bynk.resolve.duplicate_field",
1630 "A record declares a field twice.",
1631 &["record_type"],
1632 ),
1633 dg(
1634 "bynk.resolve.duplicate_field_init",
1635 "A record construction initialises a field twice.",
1636 &["record_construction"],
1637 ),
1638 dg(
1639 "bynk.resolve.duplicate_fn",
1640 "Two functions share a name.",
1641 &["fn_decl"],
1642 ),
1643 d(
1644 "bynk.resolve.duplicate_message_code",
1645 "A message bundle declares the same code twice in one block.",
1646 ),
1647 d(
1648 "bynk.resolve.duplicate_message_locale",
1649 "Two `messages` blocks in one bundle declare the same locale tag.",
1650 ),
1651 dg(
1652 "bynk.resolve.duplicate_method",
1653 "Two methods share a name.",
1654 &["fn_decl"],
1655 ),
1656 dg(
1657 "bynk.resolve.duplicate_param",
1658 "A parameter name is repeated.",
1659 &["param"],
1660 ),
1661 dg(
1662 "bynk.resolve.duplicate_provider",
1663 "A capability is provided more than once.",
1664 &["provider_decl"],
1665 ),
1666 dg(
1667 "bynk.resolve.duplicate_service",
1668 "Two services share a name.",
1669 &["service_decl"],
1670 ),
1671 dg(
1672 "bynk.resolve.duplicate_type",
1673 "Two types share a name.",
1674 &["type_decl"],
1675 ),
1676 dg(
1677 "bynk.resolve.duplicate_variant",
1678 "A sum type declares a variant twice.",
1679 &["sum_type"],
1680 ),
1681 d(
1682 "bynk.resolve.fn_without_call",
1683 "A function was referenced without being called.",
1684 ),
1685 dg(
1686 "bynk.resolve.let_shadows_fn",
1687 "A `let` binding shadows a function.",
1688 &["let_stmt"],
1689 ),
1690 dg(
1691 "bynk.resolve.let_shadows_type",
1692 "A `let` binding shadows a type.",
1693 &["let_stmt"],
1694 ),
1695 d(
1696 "bynk.resolve.method_unknown_type",
1697 "A method is defined on an unknown type.",
1698 ),
1699 dg(
1700 "bynk.resolve.missing_field",
1701 "A record construction omits a required field.",
1702 &["record_construction"],
1703 ),
1704 d(
1705 "bynk.resolve.name_conflict",
1706 "Two declarations share a name.",
1707 ),
1708 dg(
1709 "bynk.resolve.not_a_record_type",
1710 "Record syntax was used on a non-record type.",
1711 &["record_construction"],
1712 ),
1713 dg(
1714 "bynk.resolve.opaque_record_construction",
1715 "An opaque type was constructed with record syntax.",
1716 &["record_construction"],
1717 ),
1718 dg(
1719 "bynk.resolve.param_as_function",
1720 "A value (such as a parameter) was called as a function.",
1721 &["call"],
1722 ),
1723 dg(
1724 "bynk.resolve.recursive_record_field",
1725 "A record directly contains a field of its own type.",
1726 &["record_type"],
1727 ),
1728 dg(
1729 "bynk.resolve.reserved_builtin_type",
1730 "A type declaration reuses a compiler-known built-in type name.",
1731 &["type_decl"],
1732 ),
1733 dg(
1734 "bynk.resolve.reserved_host_name",
1735 "A declaration is named `globalThis`, which the generated TypeScript uses to reach host globals.",
1736 &["type_decl", "fn_decl", "agent_decl", "provider_decl"],
1737 ),
1738 dg(
1739 "bynk.resolve.reserved_payload_field",
1740 "A sum variant declares a payload field named `kind`, the variant's wire discriminant.",
1741 &["sum_type"],
1742 ),
1743 dg(
1744 "bynk.resolve.self_outside_method",
1745 "`self` referenced outside a method or handler.",
1746 &["self_expr"],
1747 ),
1748 dg(
1749 "bynk.resolve.type_as_function",
1750 "A type name was called as if it were a function.",
1751 &["call"],
1752 ),
1753 d(
1754 "bynk.resolve.type_in_expr",
1755 "A type name was used where a value is expected.",
1756 ),
1757 dg(
1758 "bynk.resolve.unconsumed_context",
1759 "A context's service was called without a `consumes` declaration.",
1760 &["consumes_decl"],
1761 ),
1762 dg(
1763 "bynk.resolve.unknown_field",
1764 "Accessed a field the record does not have.",
1765 &["field_access"],
1766 ),
1767 dg(
1768 "bynk.resolve.unknown_function",
1769 "Called a function that does not exist.",
1770 &["call"],
1771 ),
1772 d(
1773 "bynk.resolve.unknown_name",
1774 "Referenced a name that is not in scope.",
1775 ),
1776 dg(
1777 "bynk.resolve.unknown_static_member",
1778 "Referenced an unknown static member (e.g. `T.x`).",
1779 &["field_access"],
1780 ),
1781 d(
1782 "bynk.resolve.unknown_type",
1783 "Referenced a type that does not exist.",
1784 ),
1785 warn(d(
1786 "bynk.secrets.computed_name",
1787 "A `bynk.Secrets` read names its secret with a computed expression rather than a literal, so `bynk deploy` cannot plan it (warning).",
1788 )),
1789 dg(
1790 "bynk.send.in_agent_handler",
1791 "A `~>` send was used in an agent handler, which has no execution context to keep a fire-and-forget send alive.",
1792 &["effect_send_stmt"],
1793 ),
1794 dg(
1795 "bynk.send.in_pure_context",
1796 "A `~>` send was used in a pure (non-effectful) context.",
1797 &["effect_send_stmt"],
1798 ),
1799 dg(
1800 "bynk.send.non_effect",
1801 "A `~>` send was applied to a non-`Effect` value.",
1802 &["effect_send_stmt"],
1803 ),
1804 dg(
1805 "bynk.send.requires_unit",
1806 "A `~>` send targets an operation whose reply is not `Effect[()]`.",
1807 &["effect_send_stmt"],
1808 ),
1809 dg(
1810 "bynk.send.store_op",
1811 "A `~>` send targets an agent store operation, which is part of the handler's atomic commit and cannot be sent without waiting.",
1812 &["effect_send_stmt"],
1813 ),
1814 dg(
1815 "bynk.service.missing_from",
1816 "A `from`-less service has a handler other than `on call`.",
1817 &["service_decl"],
1818 ),
1819 dg(
1820 "bynk.service.mixed_protocols",
1821 "A service mixes handler forms that do not match its `from <protocol>`.",
1822 &["service_decl"],
1823 ),
1824 dg(
1825 "bynk.service.outside_context",
1826 "A `service` was declared outside a context.",
1827 &["service_decl"],
1828 ),
1829 dg(
1830 "bynk.service.return_not_effect",
1831 "A service handler's return type is not an `Effect`.",
1832 &["service_decl"],
1833 ),
1834 dg(
1835 "bynk.service.unknown_protocol",
1836 "A `from <protocol>` names an unknown protocol (e.g. a transport like Kafka).",
1837 &["service_decl"],
1838 ),
1839 d(
1840 "bynk.service.unknown_via_clause",
1841 "A `via <name>(...)` clause on a `from Events(...)` header named something other than `schema` — `via` clauses are a closed set, and only `via schema(...)` exists today.",
1842 ),
1843 d(
1844 "bynk.service.websocket_header",
1845 "The `from websocket` header is malformed — it binds frame types as `websocket(in: <type>, out: <type>)` (real-time track slice 3).",
1846 ),
1847 d(
1848 "bynk.service.websocket_multiple",
1849 "A context holds more than one `from websocket` service — at v1 the Workers upgrade routes by the `Upgrade: websocket` header alone, so one WebSocket service per context (real-time track slice 3b).",
1850 ),
1851 d(
1852 "bynk.service.websocket_open_arity",
1853 "A `from websocket` service must hold exactly one `on open` handler (the edge upgrade), and at most one `on message` (inbound) and one `on close` (real-time track slice 3/3b-iii).",
1854 ),
1855 d(
1856 "bynk.service.websocket_param_not_stringy",
1857 "A `from websocket` service's `on open` parameter has a type not constructible from `String`; it arrives as a query-string value (#1657).",
1858 ),
1859 d(
1860 "bynk.stability.experimental",
1861 "An experimental standard-library item is used without an `[unstable] allow` entry in `bynk.toml` covering it.",
1862 ),
1863 d(
1864 "bynk.store.annotation_kind_mismatch",
1865 "A storage annotation is used on a kind it does not apply to (e.g. `@ttl` on a `Map`).",
1866 ),
1867 d(
1868 "bynk.store.annotation_unsupported",
1869 "A known storage annotation (`@ttl`/`@retain`/`@indexed`/`@bounded`) is used before the slice that supports it.",
1870 ),
1871 d(
1872 "bynk.store.cache_needs_clock",
1873 "A handler performs a `Cache` operation (TTL expiry reads the clock) without declaring `given Clock`.",
1874 ),
1875 d(
1876 "bynk.store.cache_ttl_required",
1877 "A `Cache` field is missing its required `@ttl(<duration>)` annotation (a keyed store with no expiry is a `Map`).",
1878 ),
1879 d(
1880 "bynk.store.kind_arity",
1881 "A storage kind was applied to the wrong number of type arguments (e.g. `Cell[A, B]`).",
1882 ),
1883 d(
1884 "bynk.store.kind_unsupported",
1885 "A known storage kind (`Queue`) is used before the slice that supports it.",
1886 ),
1887 d(
1888 "bynk.store.log_needs_clock",
1889 "A handler calls `Log.append` (which stamps the current time) without declaring `given Clock`.",
1890 ),
1891 d(
1892 "bynk.store.unkeyable_key",
1893 "A store `Set` element or `Map`/`Cache` key is not value-keyable — it must be `String`, `Int`, or a refined/opaque type over them (#1680).",
1894 ),
1895 d(
1896 "bynk.store.unknown_annotation",
1897 "A `store` field carries an annotation outside the closed `@indexed`/`@ttl`/`@retain`/`@bounded` set.",
1898 ),
1899 d(
1900 "bynk.store.unknown_kind",
1901 "A `store` field's type is not a known storage kind.",
1902 ),
1903 d(
1904 "bynk.store.unknown_map_accessor",
1905 "A `store Map` field access is not one of its query accessors (`entries`/`keys`/`values`).",
1906 ),
1907 d(
1908 "bynk.store.unknown_op",
1909 "A storage-`Map`/`Set` operation is not a recognised entry/membership method.",
1910 ),
1911 dg(
1912 "bynk.stub.at_system",
1913 "A test `stub` is in a `system`-tier case, or at the scope of a `suite … as system` (or a suite whose cases run `as system`); each context runs as the Worker it deploys as, which builds its own capability providers, so there is no seam to override.",
1914 &["stub_clause"],
1915 ),
1916 d(
1917 "bynk.stub.bad_sequence",
1918 "A `stub … returns each […]` sequence is malformed (e.g. empty).",
1919 ),
1920 d(
1921 "bynk.stub.generic_op",
1922 "A test `stub` targets a capability operation that declares its own type parameter — not supported at v1.",
1923 ),
1924 d(
1925 "bynk.stub.not_a_seam",
1926 "A test `stub` overrides a capability the unit under test does not consume.",
1927 ),
1928 d(
1929 "bynk.stub.rhs_type",
1930 "A test `stub … returns <value>` right-hand side does not match the operation's return type.",
1931 ),
1932 d(
1933 "bynk.stub.unknown_op",
1934 "A test `stub` names an operation the capability does not declare.",
1935 ),
1936 dg(
1937 "bynk.suite.duplicate_case_name",
1938 "Two `case`s share a description.",
1939 &["case"],
1940 ),
1941 dg(
1942 "bynk.suite.duplicate_env",
1943 "An `env { … }` clause gives the same name twice at one scope (a suite's `env` clauses, or one case's); a case's `env` may override a suite's name, but not repeat its own.",
1944 &["env_clause"],
1945 ),
1946 dg(
1947 "bynk.suite.env_binding_clash",
1948 "A `system`-tier suite's or case's `env` names a binding a participant's Worker already declares (a Service Binding, KV namespace, or Durable Object namespace), or a key the test harness sets on it (a call-edge key, a `Foreign` caller's secret), so the entry would clash with it on the Worker's `env`.",
1949 &["env_clause"],
1950 ),
1951 dg(
1952 "bynk.suite.env_not_literal",
1953 "An `env { … }` entry's value is not a `String` literal; a Worker's variables and secrets are strings, given verbatim.",
1954 &["env_clause"],
1955 ),
1956 dg(
1957 "bynk.suite.unknown_target",
1958 "A `suite` targets a unit that does not exist.",
1959 &["suite_decl"],
1960 ),
1961 d(
1962 "bynk.target.browser_bundle_only",
1963 "The `browser` platform builds only the in-process `Bundle` topology; `--target workers` is not a browser build.",
1964 ),
1965 dg(
1966 "bynk.target.vendor_conflict",
1967 "One deployment unit's in-process closure uses platform-native capabilities from two mutually-exclusive platforms.",
1968 &["consumes_decl"],
1969 ),
1970 dg(
1971 "bynk.target.vendor_required",
1972 "A deployment unit uses a platform-native capability but the build selects another `--platform`.",
1973 &["consumes_decl"],
1974 ),
1975 dg(
1976 "bynk.test.actor_identity_required",
1977 "A test omits the identity an identity-carrying actor requires: a bare call-site `by <Actor>`, or no `by` at all on a handler that binds its `Caller`.",
1978 &["case"],
1979 ),
1980 dg(
1981 "bynk.test.actor_no_identity",
1982 "A call-site `by <Actor>(x)` supplies an identity to an actor that takes none — a unit-identity actor (e.g. `Visitor`) or `Nobody`.",
1983 &["case"],
1984 ),
1985 dg(
1986 "bynk.test.advance_not_clock",
1987 "An `advance` statement names a capability other than `Clock`; the test harness owns one time source, the first-party `Clock`.",
1988 &["advance_stmt"],
1989 ),
1990 dg(
1991 "bynk.test.advance_not_duration",
1992 "An `advance Clock by` statement's amount is not a `Duration`.",
1993 &["advance_stmt"],
1994 ),
1995 dg(
1996 "bynk.test.advance_outside_case",
1997 "An `advance Clock by` statement appears outside a test `case` body; only the test harness has a clock to move.",
1998 &["advance_stmt"],
1999 ),
2000 dg(
2001 "bynk.test.asset_address_method",
2002 "A suite fetches an asset with a method other than `GET`; the platform serves assets to `GET` and answers other methods with 405.",
2003 &["case"],
2004 ),
2005 dg(
2006 "bynk.test.credential_needs_system",
2007 "A case drives `by Nobody` (the no-credential principal, which tests the auth seam's 401) outside a `system`-tier case, where there is no real seam to reject it.",
2008 &["case"],
2009 ),
2010 dg(
2011 "bynk.test.event_needs_in_process",
2012 "A `system`-tier case delivers an event with `svc.event(e)`; at `system` an event reaches a subscriber only through its publisher's fan-out, so the case drives the emitting handler instead, or delivers the event at `unit` or `integration`.",
2013 &["case"],
2014 ),
2015 dg(
2016 "bynk.test.event_not_subscribed",
2017 "A test body's `svc.event(e)` delivers an event the `from Events(E)` service does not subscribe to.",
2018 &["case"],
2019 ),
2020 dg(
2021 "bynk.test.event_publisher_ambiguous",
2022 "A test body's `svc.event(e)` omits the envelope, but the event's publisher, which the default envelope names, is not one context the target declares or consumes.",
2023 &["case"],
2024 ),
2025 dg(
2026 "bynk.test.faults_needs_in_process",
2027 "A `system`-tier case claims a fault with `expect <call> faults`, or a fault claim at any tier is driven `by Nobody`, `by Forged` or `by Stale`; at `system` a fault reaches the case as an error response from the deployed Worker, never a throw, so the claim belongs at `unit` or `integration`.",
2028 &["case"],
2029 ),
2030 dg(
2031 "bynk.test.forged_needs_signature_route",
2032 "A case drives `by Forged` or `by Stale` at an address that is not an http route with a `Signature` actor (alone, or as a member of an actor sum); they send a bad signature, so only a `Signature` seam can refuse them.",
2033 &["case"],
2034 ),
2035 dg(
2036 "bynk.test.forged_needs_system",
2037 "A case drives `by Forged` or `by Stale` outside a `system`-tier case; only the `system` driver signs a request, so only there does the real `Signature` seam see the bad signature.",
2038 &["case"],
2039 ),
2040 dg(
2041 "bynk.test.nobody_needs_secured_route",
2042 "A case drives `by Nobody` at a route with no Bearer or Signature actor (alone, or as a member of an actor sum) (e.g. a public `Visitor` route) — there is no auth seam to reject the missing credential.",
2043 &["case"],
2044 ),
2045 dg(
2046 "bynk.test.oidc_needs_in_process",
2047 "A `system`-tier case calls an http route whose actor is `Oidc`-secured; the `system` driver has no token issuer yet, so the request without a token could only be refused with a `401`, and the call belongs at `unit` or `integration`.",
2048 &["case"],
2049 ),
2050 dg(
2051 "bynk.test.principal_identity_mismatch",
2052 "A call-site `by <Actor>` acts as an actor whose identity is incompatible with the addressed handler's actor, or names no member of the handler's actor sum.",
2053 &["case"],
2054 ),
2055 dg(
2056 "bynk.test.principal_on_asset",
2057 "A suite's asset fetch carries a `by` clause; an asset is public and served before the Worker runs.",
2058 &["case"],
2059 ),
2060 dg(
2061 "bynk.test.principal_on_wrong_method",
2062 "A wrong-method `405` test carries a `by <Actor>` clause; it reaches no handler, so a principal is meaningless.",
2063 &["case"],
2064 ),
2065 dg(
2066 "bynk.test.principal_required",
2067 "A test drives an identity-carrying handler, or one guarded by an actor sum, with no call-site `by <Actor>`.",
2068 &["case"],
2069 ),
2070 warn(dg(
2071 "bynk.test.remote_clock_dependent",
2072 "Under `bynk test --against`, a `system` case's `expect` compares an `Instant` that isn't derived from the run (a constant such as `Instant.fromEpochMillis(0)`); in process the clock starts at the epoch, but a real runtime's Workers read wall-clock time.",
2073 &["case"],
2074 )),
2075 dg(
2076 "bynk.test.remote_unsupported_advance",
2077 "A `system` case moves the harness clock with `advance Clock`, which a run against a real runtime (`bynk test --against`) can't honour: the deployed Workers read wall-clock time.",
2078 &["case"],
2079 ),
2080 dg(
2081 "bynk.test.remote_unsupported_asset",
2082 "A `system` case fetches an asset with `svc.GET(asset)`, which a run against a real runtime (`bynk test --against`) can't honour: the fetch is answered in process.",
2083 &["case"],
2084 ),
2085 dg(
2086 "bynk.test.remote_unsupported_call",
2087 "A `system` case addresses an `on call` service, which a run against a real runtime (`bynk test --against`) can't honour: the service is internal, and each call is signed for one caller.",
2088 &["case"],
2089 ),
2090 dg(
2091 "bynk.test.remote_unsupported_env",
2092 "A `system` case's `env` disagrees with the named target it would run against (`bynk test --against`): it sets a secret, sets a name the target doesn't declare under `vars` or declares with another value, or leaves unset a name the target declares.",
2093 &["case"],
2094 ),
2095 dg(
2096 "bynk.test.remote_unsupported_queue",
2097 "A `system` case delivers a queue message with `q.message(m)`, which a run against a real runtime (`bynk test --against`) can't honour: no public wire reaches a queue consumer.",
2098 &["case"],
2099 ),
2100 dg(
2101 "bynk.test.remote_unsupported_schedule",
2102 "A `system` case runs a cron handler with `svc.schedule(…)`, which a run against a real runtime (`bynk test --against`) can't honour: no public wire reaches a cron handler.",
2103 &["case"],
2104 ),
2105 dg(
2106 "bynk.test.service_bad_address",
2107 "A test body addresses a service the wrong way for its protocol (e.g. an http route without a leading path string).",
2108 &["case"],
2109 ),
2110 dg(
2111 "bynk.test.service_call_arity",
2112 "A test body's `svc.call(...)` passes the wrong number of arguments for the service's `on call` handler.",
2113 &["case"],
2114 ),
2115 dg(
2116 "bynk.test.service_no_call_handler",
2117 "A test body invokes `svc.call(...)` on a service with no `on call` handler (a `from http`/`cron`/`queue` service).",
2118 &["case"],
2119 ),
2120 dg(
2121 "bynk.test.service_unknown_route",
2122 "A test body addresses an http route / cron schedule / queue message the service does not declare.",
2123 &["case"],
2124 ),
2125 dg(
2126 "bynk.test.stale_needs_timestamp",
2127 "A case drives `by Stale` at a `Signature` route whose actor declares no `timestamp` header and `tolerance`, so there is no replay window for the seam to refuse a stale signature by.",
2128 &["case"],
2129 ),
2130 dg(
2131 "bynk.test.unknown_actor",
2132 "A call-site `by <Actor>` names an actor the target context does not declare and that is not a prelude actor.",
2133 &["case"],
2134 ),
2135 dg(
2136 "bynk.test.wire_needs_system",
2137 "A `Wire(...)` raw argument is used outside a `system`-tier service address; `Wire` hands pre-validation input to the boundary and is meaningless at `unit` or in any other position.",
2138 &["case"],
2139 ),
2140 dg(
2141 "bynk.tier.cross_context_needs_system",
2142 "A `unit` or `integration` case, or a `property`, reaches another context's service, directly or through a target service or agent handler that calls one; below `system` no other context is stood up to call, so the flow belongs in a `suite … as system`.",
2143 &["case"],
2144 ),
2145 dg(
2146 "bynk.tier.mixed_system_suite",
2147 "A suite mixes `system` cases with `unit` or `integration` ones; a `system` case runs against deployed Workers and addresses services by context path, so it needs a `suite … as system` of its own.",
2148 &["case"],
2149 ),
2150 d(
2151 "bynk.tier.system_needs_wire",
2152 "An `as system` test stands up fewer than two contexts; the system tier wires across contexts.",
2153 ),
2154 d(
2155 "bynk.transition.cross_agent_reference",
2156 "A transition predicate references another agent; step invariants are per-agent.",
2157 ),
2158 d(
2159 "bynk.transition.duplicate_name",
2160 "An agent declares two transitions with the same name.",
2161 ),
2162 d(
2163 "bynk.transition.impure_predicate",
2164 "A transition predicate uses an effectful or test-only construct; a step invariant must be pure.",
2165 ),
2166 d(
2167 "bynk.transition.no_step_reference",
2168 "A transition references neither `old` nor `new`; it constrains one state, so it is an `invariant`, not a step.",
2169 ),
2170 d(
2171 "bynk.transition.not_bool",
2172 "A transition predicate does not have type `Bool`.",
2173 ),
2174 dg(
2175 "bynk.types.argument_mismatch",
2176 "A call, method, capability, or constructor argument has the wrong type.",
2177 &["call"],
2178 ),
2179 d(
2180 "bynk.types.asset_at_boundary",
2181 "An `Asset` type appears in a record field, boundary or store position; pass its `.url` instead.",
2182 ),
2183 dg(
2184 "bynk.types.call_arity",
2185 "A function value was applied with the wrong number of arguments.",
2186 &["call"],
2187 ),
2188 dg(
2189 "bynk.types.cannot_infer_option_type_param",
2190 "The value type of `None` could not be inferred.",
2191 &["none_expr"],
2192 ),
2193 d(
2194 "bynk.types.cannot_infer_result_type_params",
2195 "The type parameters of a `Result` could not be inferred.",
2196 ),
2197 dg(
2198 "bynk.types.catastrophic_regex",
2199 "A `Matches` pattern can match the same text in exponentially many ways (nested or ambiguous repetition, bounded or not), or cannot be analysed, risking catastrophic backtracking (ReDoS).",
2200 &["refinement"],
2201 ),
2202 dg(
2203 "bynk.types.combinator_return_mismatch",
2204 "A callback passed to a combinator (`map`/`andThen`/`flatMap`/`traverseAll`/…) returns the wrong type.",
2205 &["call"],
2206 ),
2207 d(
2208 "bynk.types.constructor_arity",
2209 "A variant constructor got the wrong number of arguments.",
2210 ),
2211 d(
2212 "bynk.types.constructor_base_mismatch",
2213 "A `.of` constructor was given an argument of the wrong base type.",
2214 ),
2215 dg(
2216 "bynk.types.duplicate_literal_arm",
2217 "A `match` has two arms for the same literal value.",
2218 &["match_arm"],
2219 ),
2220 dg(
2221 "bynk.types.duplicate_variant_arm",
2222 "A `match` has two arms for the same variant.",
2223 &["match_arm"],
2224 ),
2225 d(
2226 "bynk.types.embeds_ambiguous",
2227 "A type is embedded by more than one variant of a sum, so `?`'s conversion would be ambiguous.",
2228 ),
2229 d(
2230 "bynk.types.embeds_unknown_variant",
2231 "An `embeds … as V` clause names a variant the sum does not declare.",
2232 ),
2233 d(
2234 "bynk.types.embeds_variant_shape",
2235 "An `embeds E as V` target variant must have exactly one payload field, of type `E`.",
2236 ),
2237 dg(
2238 "bynk.types.empty_refinement",
2239 "A refinement admits no values (contradictory predicates).",
2240 &["refinement"],
2241 ),
2242 dg(
2243 "bynk.types.err_value_mismatch",
2244 "An `Err` payload has the wrong type.",
2245 &["err_expr"],
2246 ),
2247 d(
2248 "bynk.types.extensible_match_needs_wildcard",
2249 "A `match` covers an extensible standard-library enum (`FetchError`, `Method`) without a wildcard; it may gain variants in a minor release.",
2250 ),
2251 dg(
2252 "bynk.types.field_access_on_non_record",
2253 "Field access on a value that is not a record.",
2254 &["field_access"],
2255 ),
2256 dg(
2257 "bynk.types.field_refinement_not_base",
2258 "An inline field refinement requires a base or refined type.",
2259 &["record_field"],
2260 ),
2261 dg(
2262 "bynk.types.field_value_mismatch",
2263 "A record field was given a value of the wrong type.",
2264 &["record_construction"],
2265 ),
2266 dg(
2267 "bynk.types.function_at_boundary",
2268 "A function type appeared in a serialisable or boundary position (a record field, sum payload, service/agent handler signature, capability operation signature, agent state field, or agent key); functions cannot serialise or cross a boundary.",
2269 &["function_type_ref"],
2270 ),
2271 dg(
2272 "bynk.types.guard_not_bool",
2273 "A match-arm `if` guard is not a `Bool` expression.",
2274 &["match_arm"],
2275 ),
2276 d(
2277 "bynk.types.held_at_boundary",
2278 "A held value (`Connection[F]`) appears in a serialisable or boundary position — a held resource is built and disposed in place, never persisted or sent across a boundary (§2.9, real-time track slice 2).",
2279 ),
2280 d(
2281 "bynk.types.held_not_comparable",
2282 "A held value (`Connection[F]`) is compared with `==`/`!=` — held values have identity, not value-equality (§2.9.3, real-time track slice 2).",
2283 ),
2284 dg(
2285 "bynk.types.if_branch_mismatch",
2286 "The branches of an `if` have different types.",
2287 &["if_expr"],
2288 ),
2289 dg(
2290 "bynk.types.if_non_bool_cond",
2291 "An `if` condition is not a `Bool`.",
2292 &["if_expr"],
2293 ),
2294 dg(
2295 "bynk.types.if_without_else_requires_unit",
2296 "An `if` with no `else` branch has a non-unit then-branch; the missing else defaults to `()`, so the branch must be `()` or `Effect[()]`.",
2297 &["if_expr"],
2298 ),
2299 d(
2300 "bynk.types.interpolation_non_scalar",
2301 "An interpolation hole holds a value with no string form.",
2302 ),
2303 dg(
2304 "bynk.types.invalid_regex",
2305 "A `Matches` predicate contains an invalid regular expression.",
2306 &["refinement"],
2307 ),
2308 dg(
2309 "bynk.types.inverted_range",
2310 "An `InRange` predicate has its bounds inverted.",
2311 &["refinement"],
2312 ),
2313 dg(
2314 "bynk.types.is_base_mismatch",
2315 "An `is` refinement check is applied to a value of the wrong base type.",
2316 &["is_expr"],
2317 ),
2318 dg(
2319 "bynk.types.is_literal_pattern",
2320 "A literal was used on the right of `is`; `is` tests type/refinement, not value equality (use `==`).",
2321 &["is_expr"],
2322 ),
2323 dg(
2324 "bynk.types.is_non_sum",
2325 "`is` was applied to a value that is not a sum type.",
2326 &["is_expr"],
2327 ),
2328 dg(
2329 "bynk.types.is_refined_pattern",
2330 "A refined (`where`) pattern was used on the right of `is`; refined patterns are `match`-only.",
2331 &["is_expr"],
2332 ),
2333 dg(
2334 "bynk.types.is_unknown_variant",
2335 "`is` names a variant the type does not have.",
2336 &["is_expr"],
2337 ),
2338 dg(
2339 "bynk.types.json_uncodable",
2340 "A `Json.encode`/`Json.decode` target type cannot pass through the typed JSON codec (functions, effects, error builtins).",
2341 &["method_call"],
2342 ),
2343 dg(
2344 "bynk.types.key_not_orderable",
2345 "A `sortBy`/`min`/`max` key function does not return an orderable type (`Int`, `Float`, `String`, `Duration`, or `Instant`).",
2346 &[],
2347 ),
2348 dg(
2349 "bynk.types.lambda_mismatch",
2350 "A lambda's parameter count, parameter annotations, or body type do not match the expected function type.",
2351 &["lambda_expr"],
2352 ),
2353 dg(
2354 "bynk.types.let_annotation_mismatch",
2355 "A `let` value does not match its type annotation.",
2356 &["let_stmt"],
2357 ),
2358 dg(
2359 "bynk.types.list_element_mismatch",
2360 "A list-literal element has a different type from the list's element type.",
2361 &["list_literal"],
2362 ),
2363 dg(
2364 "bynk.types.match_arm_mismatch",
2365 "A `match` arm has a different type from the others.",
2366 &["match_arm"],
2367 ),
2368 dg(
2369 "bynk.types.match_non_sum_discriminant",
2370 "`match` was applied to a value that is not a sum type.",
2371 &["match_expr"],
2372 ),
2373 dg(
2374 "bynk.types.method_arity",
2375 "A method was called with the wrong number of arguments.",
2376 &["method_call"],
2377 ),
2378 dg(
2379 "bynk.types.method_not_found",
2380 "Called a method the type does not have.",
2381 &["method_call"],
2382 ),
2383 dg(
2384 "bynk.types.method_on_non_named_type",
2385 "A method was called on a built-in type that has no methods.",
2386 &["method_call"],
2387 ),
2388 dg(
2389 "bynk.types.mixed_pattern_bindings",
2390 "A pattern mixes named and positional bindings.",
2391 &["variant_pattern"],
2392 ),
2393 dg(
2394 "bynk.types.negative_length",
2395 "A length predicate was given a negative value.",
2396 &["refinement"],
2397 ),
2398 dg(
2399 "bynk.types.no_numeric_coercion",
2400 "`Int` and `Float` were mixed without an explicit conversion — in an operation or in refinement bounds.",
2401 &["binary_expr", "refinement"],
2402 ),
2403 dg(
2404 "bynk.types.non_exhaustive_match",
2405 "A `match` does not cover every variant.",
2406 &["match_expr"],
2407 ),
2408 d(
2409 "bynk.types.not_comparable",
2410 "A value compared with `==`/`!=` contains a function, `Effect`, or `Query` somewhere inside it — those have no value equality, so the type is not equality-supporting (type-system §2.3.5, #1652).",
2411 ),
2412 dg(
2413 "bynk.types.ok_value_mismatch",
2414 "An `Ok` payload has the wrong type.",
2415 &["ok_expr"],
2416 ),
2417 dg(
2418 "bynk.types.opaque_raw_outside",
2419 "`.raw` on an opaque type was used outside its defining commons.",
2420 &["field_access"],
2421 ),
2422 dg(
2423 "bynk.types.opaque_unsafe_outside",
2424 "`.unsafe` on an opaque type was used outside its defining context.",
2425 &["field_access"],
2426 ),
2427 dg(
2428 "bynk.types.or_pattern_binding_mismatch",
2429 "An or-pattern's alternatives don't all bind the same set of names.",
2430 &["match_arm", "is_expr"],
2431 ),
2432 dg(
2433 "bynk.types.or_pattern_type_mismatch",
2434 "An or-pattern's alternatives give a shared binding different types (or refinements).",
2435 &["match_arm", "is_expr"],
2436 ),
2437 dg(
2438 "bynk.types.pattern_arity",
2439 "A pattern binds the wrong number of payload fields.",
2440 &["variant_pattern"],
2441 ),
2442 dg(
2443 "bynk.types.pattern_type_mismatch",
2444 "A pattern's type does not match the matched value.",
2445 &["variant_pattern"],
2446 ),
2447 dg(
2448 "bynk.types.polynomial_regex",
2449 "A `Matches` pattern can split the same text between repetitions, so matching time grows polynomially with input length, and no length predicate bounds the input small enough for its degree.",
2450 &["refinement"],
2451 ),
2452 warn(dg(
2453 "bynk.types.polynomial_regex_capped",
2454 "A `Matches` pattern's matching time grows polynomially with input length, but a `MaxLength` or `Length` predicate bounds the input small enough for its degree (warning).",
2455 &["refinement"],
2456 )),
2457 dg(
2458 "bynk.types.predicate_base_mismatch",
2459 "A predicate does not apply to the type's base (e.g. a string predicate on an `Int`).",
2460 &["refinement"],
2461 ),
2462 d(
2463 "bynk.types.query_at_boundary",
2464 "A `Query` type appears in a storable or boundary-crossing position — a query is built and executed in place, never persisted or sent (ADR 0115).",
2465 ),
2466 dg(
2467 "bynk.types.question_error_mismatch",
2468 "`?` propagates an error type incompatible with the function's.",
2469 &["question_expr"],
2470 ),
2471 dg(
2472 "bynk.types.question_on_non_result",
2473 "`?` was applied to a non-`Result` value.",
2474 &["question_expr"],
2475 ),
2476 dg(
2477 "bynk.types.question_option_outside_http",
2478 "`?` lifts an `Option` only inside a handler returning `HttpResult` (`None` becomes `NotFound`); elsewhere use `.okOr(err)`.",
2479 &["question_expr"],
2480 ),
2481 dg(
2482 "bynk.types.question_outside_result",
2483 "`?` used in a function that does not return a `Result`.",
2484 &["question_expr"],
2485 ),
2486 d(
2487 "bynk.types.return_mismatch",
2488 "A returned value does not match the declared return type.",
2489 ),
2490 dg(
2491 "bynk.types.some_value_mismatch",
2492 "A `Some` payload has the wrong type.",
2493 &["some_expr"],
2494 ),
2495 d(
2496 "bynk.types.stream_at_boundary",
2497 "A `Stream` type appears in a storable or boundary-crossing position — a stream is a live value-over-time source, never persisted or sent across a boundary (real-time track slice 0).",
2498 ),
2499 d(
2500 "bynk.types.stream_not_comparable",
2501 "A `Stream` value is compared with `==`/`!=` — a stream is a live value-over-time source, not a comparable value (real-time track slice 0).",
2502 ),
2503 d(
2504 "bynk.types.type_mismatch",
2505 "Two types that were required to match did not.",
2506 ),
2507 dg(
2508 "bynk.types.uninferable_element_type",
2509 "An empty `[]` (or `List.empty()` / `Map.empty()`) has no expected type to infer its element type from.",
2510 &["list_literal"],
2511 ),
2512 dg(
2513 "bynk.types.unkeyable_distinct",
2514 "A `distinct`/`distinctBy` element or key is not value-keyable (`String`, `Int`, or a refined/opaque type over them).",
2515 &[],
2516 ),
2517 dg(
2518 "bynk.types.unkeyable_map_key",
2519 "A `Map` key type is not value-keyable (`String`, `Int`, or a refined/opaque type over them).",
2520 &["generic_type_ref"],
2521 ),
2522 dg(
2523 "bynk.types.unknown_field",
2524 "Referenced a field the record type does not declare.",
2525 &["field_access"],
2526 ),
2527 dg(
2528 "bynk.types.unknown_pattern_field",
2529 "A pattern names a field the variant does not have.",
2530 &["variant_pattern"],
2531 ),
2532 dg(
2533 "bynk.types.unknown_static_member",
2534 "Referenced an unknown static member on a type.",
2535 &["field_access"],
2536 ),
2537 dg(
2538 "bynk.types.unknown_variant_in_pattern",
2539 "A pattern names a variant the sum type does not have.",
2540 &["variant_pattern"],
2541 ),
2542 dg(
2543 "bynk.types.unreachable_arm",
2544 "A `match` arm is unreachable.",
2545 &["match_arm"],
2546 ),
2547 d(
2548 "bynk.types.variant_arity",
2549 "A variant constructor got the wrong number of payload values.",
2550 ),
2551 d(
2552 "bynk.types.variant_missing_payload",
2553 "A variant requiring a payload was used without one.",
2554 ),
2555 d(
2556 "bynk.types.variant_payload_mismatch",
2557 "A variant payload has the wrong type.",
2558 ),
2559 dg(
2560 "bynk.uses.name_conflict",
2561 "A `uses` name collides with another name, a value crosses between a unit's code and an imported declaration's position whose type the unit shadows, or a reference names an import the unit's own declaration shadows.",
2562 &["uses_decl"],
2563 ),
2564 dg(
2565 "bynk.uses.self_reference",
2566 "A commons `uses` itself.",
2567 &["uses_decl"],
2568 ),
2569 dg(
2570 "bynk.uses.target_is_context",
2571 "`uses` targets a context instead of a commons.",
2572 &["uses_decl"],
2573 ),
2574 dg(
2575 "bynk.uses.unknown_commons",
2576 "`uses` names a commons that does not exist.",
2577 &["uses_decl"],
2578 ),
2579 dg(
2580 "bynk.val.agent_not_generable",
2581 "A `for all`/`Val` cannot generate an agent — fabricated agent states need not be reachable.",
2582 &["for_all"],
2583 ),
2584 dg(
2585 "bynk.val.arity",
2586 "`Val[T]` was given the wrong number of pin arguments.",
2587 &["val_expr"],
2588 ),
2589 dg(
2590 "bynk.val.literal_violates",
2591 "A pinned `Val[T]` value violates the type's refinement.",
2592 &["val_expr"],
2593 ),
2594 dg(
2595 "bynk.val.needs_pin",
2596 "A bare `Val[T]` cannot generate a value (e.g. a `Matches` string); pin one.",
2597 &["val_expr"],
2598 ),
2599 dg(
2600 "bynk.val.outside_test",
2601 "`Val[T]` was used outside a test case body.",
2602 &["val_expr"],
2603 ),
2604 dg(
2605 "bynk.val.pin_not_literal",
2606 "A `Val[T]` pin argument is not a compile-time literal.",
2607 &["val_expr"],
2608 ),
2609 dg(
2610 "bynk.val.pin_unsupported",
2611 "A pin was given for a type kind that does not support pinning.",
2612 &["val_expr"],
2613 ),
2614 dg(
2615 "bynk.val.unknown_type",
2616 "`Val[T]` names a type that does not resolve.",
2617 &["val_expr"],
2618 ),
2619 dg(
2620 "bynk.val.unsupported_kind",
2621 "`Val[T]` cannot fabricate a value for this kind of type.",
2622 &["val_expr"],
2623 ),
2624 d(
2625 "bynk.wasm.panic",
2626 "The in-browser compiler panicked internally (a compiler bug, reported as a diagnostic instead of crashing the page).",
2627 ),
2628 d(
2629 "bynk.wasm.strip_failed",
2630 "The in-browser compiler could not strip the emitted TypeScript to JavaScript.",
2631 ),
2632 d(
2633 "bynk.ws.message_frame_param",
2634 "A WebSocket `on message` handler does not have exactly one parameter of the service's inbound (`in:`) frame type — the decoded frame (real-time track slice 3b-iii).",
2635 ),
2636 d(
2637 "bynk.ws.open_given_unsupported",
2638 "A WebSocket `on open` handler declares `given` capabilities — unsupported at v1, since on Workers the handler runs inside the connection-hosting Durable Object, which has no composition root to supply them (real-time track slice 3b).",
2639 ),
2640 d(
2641 "bynk.ws.open_transfer_shape",
2642 "A WebSocket `on open` handler does not transfer its `connection` into exactly one agent, so the Workers upgrade has no single Durable Object to route to (real-time track slice 3b).",
2643 ),
2644 d(
2645 "bynk.ws.route_param_mismatch",
2646 "A WebSocket `on message`/`on close` route parameter does not match the `on open` parameter at the same position — route values are recovered positionally from the connection, so they must be a type-compatible prefix of the `on open` parameters (real-time track slice 3b-iii).",
2647 ),
2648];
2649
2650const fn d(code: &'static str, summary: &'static str) -> DiagnosticInfo {
2652 DiagnosticInfo {
2653 code,
2654 summary,
2655 grammar_symbol: &[],
2656 severity: Severity::Error,
2657 }
2658}
2659
2660const fn dg(
2662 code: &'static str,
2663 summary: &'static str,
2664 grammar_symbol: &'static [&'static str],
2665) -> DiagnosticInfo {
2666 DiagnosticInfo {
2667 code,
2668 summary,
2669 grammar_symbol,
2670 severity: Severity::Error,
2671 }
2672}
2673
2674const fn warn(mut info: DiagnosticInfo) -> DiagnosticInfo {
2678 info.severity = Severity::Warning;
2679 info
2680}
2681
2682pub fn category(code: &str) -> &str {
2685 code.split('.').nth(1).unwrap_or("")
2686}
2687
2688fn category_title(cat: &str) -> &'static str {
2690 match cat {
2691 "agent" | "agents" => "Agents",
2692 "asset" => "Static assets",
2693 "boundary" => "Boundaries",
2694 "capability" => "Capabilities",
2695 "consumes" => "Consumes",
2696 "context" => "Contexts",
2697 "contract" => "Contracts",
2698 "cron" => "Cron",
2699 "effect" => "Effects",
2700 "expect" => "Expectations",
2701 "exports" => "Exports",
2702 "given" => "Given capabilities",
2703 "http" => "HTTP",
2704 "lex" => "Lexer",
2705 "messages" => "Message bundles",
2706 "mock" => "Mocks (collaborators)",
2707 "observe" => "Observation",
2708 "parse" => "Parser",
2709 "project" => "Project",
2710 "property" => "Properties (generative tests)",
2711 "provider" => "Providers",
2712 "queue" => "Queue",
2713 "record_spread" => "Record spread",
2714 "refine" => "Refinement",
2715 "resolve" => "Resolution",
2716 "service" => "Services",
2717 "stability" => "Stability",
2718 "suite" => "Suites and cases",
2719 "transition" => "Transitions (step invariants)",
2720 "types" => "Type checking",
2721 "uses" => "Uses",
2722 "val" => "Value fabrication",
2723 _ => "Other",
2724 }
2725}
2726
2727pub fn render_markdown() -> String {
2731 use std::collections::BTreeMap;
2732
2733 let mut by_category: BTreeMap<&str, Vec<&DiagnosticInfo>> = BTreeMap::new();
2735 for info in REGISTRY {
2736 by_category
2737 .entry(category_title(category(info.code)))
2738 .or_default()
2739 .push(info);
2740 }
2741
2742 let mut out = String::new();
2743 out.push_str("# Diagnostic index\n\n");
2744 out.push_str(
2745 "<!-- GENERATED FILE — do not edit by hand.\n \
2746 Source: bynkc/src/diagnostics.rs (`render_markdown`).\n \
2747 Regenerate with: BYNK_BLESS=1 cargo test -p bynkc --test diagnostics_registry -->\n\n",
2748 );
2749 out.push_str(
2750 "Every diagnostic code the compiler can emit, with a one-line summary of \
2751 the cause, grouped by category. For step-by-step cause-and-fix guidance \
2752 on the most common ones, see the [troubleshooting guides](../troubleshooting/index.md). \
2753 For a code with a curated explanation, `bynk explain <code>` prints it in a \
2754 terminal, and in VS Code the diagnostic's **Explain** quick fix (or \
2755 **Bynk: Explain Diagnostic Code…**) shows the same text in a panel, offline.\n\n",
2756 );
2757 out.push_str(&format!(
2758 "There are **{}** codes in total.\n",
2759 REGISTRY.len()
2760 ));
2761
2762 for (title, infos) in &by_category {
2763 out.push_str(&format!("\n## {title}\n\n"));
2764 out.push_str("| Code | Summary | Construct | Severity |\n|---|---|---|---|\n");
2765 for info in infos {
2766 let construct = info
2771 .grammar_symbol
2772 .iter()
2773 .map(|sym| format!("[`{sym}`](grammar.md#rule-{sym})"))
2774 .collect::<Vec<_>>()
2775 .join(", ");
2776 let code_cell = match explain(info.code) {
2781 Some(e) => format!("[`{}`]({})", info.code, e.in_site_link()),
2782 None => format!("`{}`", info.code),
2783 };
2784 let severity = match info.severity {
2789 Severity::Error => "—",
2790 Severity::Warning => "Warning",
2791 };
2792 out.push_str(&format!(
2793 "| {} | {} | {} | {} |\n",
2794 code_cell, info.summary, construct, severity
2795 ));
2796 }
2797 }
2798
2799 out
2800}
2801
2802pub fn render_grammar_semantics_json() -> String {
2808 use std::collections::BTreeMap;
2809
2810 let mut by_symbol: BTreeMap<&str, Vec<&DiagnosticInfo>> = BTreeMap::new();
2813 for info in REGISTRY {
2814 for sym in info.grammar_symbol {
2815 by_symbol.entry(sym).or_default().push(info);
2816 }
2817 }
2818
2819 let mut map = serde_json::Map::new();
2820 map.insert(
2821 "_generated".to_string(),
2822 serde_json::Value::String(
2823 "Generated from the grammar_symbol field of bynkc/src/diagnostics.rs. \
2824 Do not edit by hand. Regenerate with: BYNK_BLESS=1 cargo test -p \
2825 bynkc --test diagnostics_registry"
2826 .to_string(),
2827 ),
2828 );
2829 for (sym, infos) in by_symbol {
2830 let arr: Vec<serde_json::Value> = infos
2831 .iter()
2832 .map(|info| serde_json::json!({ "code": info.code, "summary": info.summary }))
2833 .collect();
2834 map.insert(sym.to_string(), serde_json::Value::Array(arr));
2835 }
2836
2837 let mut s =
2838 serde_json::to_string_pretty(&serde_json::Value::Object(map)).expect("serialise semantics");
2839 s.push('\n');
2840 s
2841}