@owlmeans/viable-common 0.0.32 → 0.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/README.md +3 -3
  2. package/agent-meta/manifest.json +2 -2
  3. package/agent-meta/skills/agent-presentation/SKILL.md +1 -1
  4. package/agent-meta/skills/viable-common/SKILL.md +109 -57
  5. package/build/ba/index.d.ts +0 -1
  6. package/build/ba/index.d.ts.map +1 -1
  7. package/build/ba/index.js +0 -1
  8. package/build/ba/index.js.map +1 -1
  9. package/build/blueprint/case.js +3 -3
  10. package/build/blueprint/consts.d.ts +38 -0
  11. package/build/blueprint/consts.d.ts.map +1 -1
  12. package/build/blueprint/consts.js +40 -0
  13. package/build/blueprint/consts.js.map +1 -1
  14. package/build/blueprint/index.d.ts +0 -3
  15. package/build/blueprint/index.d.ts.map +1 -1
  16. package/build/blueprint/index.js +0 -3
  17. package/build/blueprint/index.js.map +1 -1
  18. package/build/blueprint/types.d.ts +5 -5
  19. package/build/connect/errors.d.ts +23 -0
  20. package/build/connect/errors.d.ts.map +1 -1
  21. package/build/connect/errors.js +50 -0
  22. package/build/connect/errors.js.map +1 -1
  23. package/build/intent/consts.d.ts +57 -0
  24. package/build/intent/consts.d.ts.map +1 -0
  25. package/build/intent/consts.js +58 -0
  26. package/build/intent/consts.js.map +1 -0
  27. package/build/intent/entrypoints.d.ts +27 -0
  28. package/build/intent/entrypoints.d.ts.map +1 -0
  29. package/build/intent/entrypoints.js +28 -0
  30. package/build/intent/entrypoints.js.map +1 -0
  31. package/build/intent/errors.d.ts +20 -0
  32. package/build/intent/errors.d.ts.map +1 -0
  33. package/build/intent/errors.js +28 -0
  34. package/build/intent/errors.js.map +1 -0
  35. package/build/intent/flow.d.ts +17 -0
  36. package/build/intent/flow.d.ts.map +1 -0
  37. package/build/intent/flow.js +65 -0
  38. package/build/intent/flow.js.map +1 -0
  39. package/build/intent/index.d.ts +7 -0
  40. package/build/intent/index.d.ts.map +1 -0
  41. package/build/intent/index.js +6 -0
  42. package/build/intent/index.js.map +1 -0
  43. package/build/intent/schemas.d.ts +10 -0
  44. package/build/intent/schemas.d.ts.map +1 -0
  45. package/build/intent/schemas.js +24 -0
  46. package/build/intent/schemas.js.map +1 -0
  47. package/build/intent/types.d.ts +40 -0
  48. package/build/intent/types.d.ts.map +1 -0
  49. package/build/intent/types.js +2 -0
  50. package/build/intent/types.js.map +1 -0
  51. package/build/skills/catalogue.d.ts.map +1 -1
  52. package/build/skills/catalogue.js +15 -1
  53. package/build/skills/catalogue.js.map +1 -1
  54. package/build/skills/consts.d.ts +0 -34
  55. package/build/skills/consts.d.ts.map +1 -1
  56. package/build/skills/consts.js +0 -106
  57. package/build/skills/consts.js.map +1 -1
  58. package/build/skills/index.d.ts +0 -1
  59. package/build/skills/index.d.ts.map +1 -1
  60. package/build/skills/index.js +0 -1
  61. package/build/skills/index.js.map +1 -1
  62. package/build/skills/roles.d.ts +0 -9
  63. package/build/skills/roles.d.ts.map +1 -1
  64. package/build/skills/roles.js +0 -226
  65. package/build/skills/roles.js.map +1 -1
  66. package/package.json +18 -8
  67. package/src/ba/index.ts +0 -1
  68. package/src/blueprint/consts.ts +40 -0
  69. package/src/blueprint/index.ts +0 -3
  70. package/src/blueprint/types.ts +5 -5
  71. package/src/connect/errors.ts +55 -0
  72. package/src/intent/consts.ts +66 -0
  73. package/src/intent/entrypoints.ts +43 -0
  74. package/src/intent/errors.ts +33 -0
  75. package/src/intent/flow.ts +67 -0
  76. package/src/intent/index.ts +6 -0
  77. package/src/intent/schemas.ts +27 -0
  78. package/src/intent/types.ts +45 -0
  79. package/src/skills/consts.ts +0 -112
  80. package/src/skills/index.ts +0 -1
  81. package/src/skills/roles.ts +0 -267
  82. package/tests/blueprint.spec.ts +2 -66
  83. package/tests/connect-errors.spec.ts +31 -1
  84. package/tests/error-status.spec.ts +6 -1
  85. package/tests/intent.spec.ts +121 -0
  86. package/src/ba/schemas.ts +0 -196
  87. package/src/blueprint/case.ts +0 -320
  88. package/src/blueprint/resolve.ts +0 -136
  89. package/src/blueprint/schemas.ts +0 -44
  90. package/src/skills/catalogue.ts +0 -1850
  91. package/tests/skills.spec.ts +0 -110
package/README.md CHANGED
@@ -21,7 +21,7 @@ filesystem, no inference SDK. It is safe to import from a browser bundle.
21
21
  ## Installation
22
22
 
23
23
  ```bash
24
- bun add @owlmeans/viable-common@^0.0.32
24
+ bun add @owlmeans/viable-common@^0.0.34
25
25
  ```
26
26
 
27
27
  ## Rules worth knowing before you change something
@@ -39,7 +39,7 @@ means "inherit" has no other spelling. `tests/convert.spec.ts` walks every expor
39
39
  both faults, and for draft-04 tuple `items`.
40
40
 
41
41
  **A field that crosses a version skew carries no `enum`.** A connector is installed with
42
- `npx -y @owlmeans/viable-mcp@^0.1.18-rc.29` and talks to a separately deployed platform, so an executor kind it
42
+ `npx -y @owlmeans/viable-mcp@^0.1.18-rc.31` and talks to a separately deployed platform, so an executor kind it
43
43
  sends must remain an unused capability on an older platform rather than a refused session.
44
44
 
45
45
  **A ceiling exists once.** The inquiry answer cap here equals `DEFAULT_INQUIRY_ANSWER_CHARS` in
@@ -59,7 +59,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
59
59
  your project's skill store (`.agents/skills/`):
60
60
 
61
61
  ```sh
62
- npx @owlmeans/agent-skills@^0.1.18-rc.36
62
+ npx @owlmeans/agent-skills@^0.1.18-rc.39
63
63
  ```
64
64
 
65
65
  The embedded files are version-matched to this package release. Do not edit them
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@owlmeans/viable-common",
4
- "version": "0.0.32",
5
- "generatedAt": "2026-09-22T22:23:07.739Z",
4
+ "version": "0.0.34",
5
+ "generatedAt": "2026-09-24T14:00:40.411Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -6,7 +6,7 @@ description: Shared, runtime-free taxonomy for presenting OwlMeans Viable agent
6
6
 
7
7
  # Agent output presentation
8
8
 
9
- **Install:** `"@owlmeans/viable-common": "^0.0.32"` in `dependencies`
9
+ **Install:** `"@owlmeans/viable-common": "^0.0.34"` in `dependencies`
10
10
 
11
11
  `@owlmeans/viable-common`'s `agent/presentation.ts` owns the browser-safe vocabulary for agent
12
12
  output. Keep the server and every client on `classifyAgentMessage()`; consumers may refine a
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: viable-common
3
- description: How to use @owlmeans/viable-common — the runtime-free contract package of the OwlMeans Viable platform. Covers planning cards and flows (including the landing-gate fields), project/story refusals, slot commands and layouts, slot metadata keys, target integrity, connector domain statuses and routes, conversion vocabulary, blueprint layers and cases, the persona/skill catalogue and its design house style, generated-project analysis/design/scaffold/metadata shapes, StoryDesignPort, schema conventions, and wire-version rules. Auto-invoked when importing a viable card type or flow, a slot command, a connector or conversion type, a target-integrity helper, or any *Schema this package exports.
3
+ description: How to use @owlmeans/viable-common — the runtime-free contract package of the OwlMeans Viable platform. Covers planning cards and flows (including the landing-gate fields), project/story refusals, slot commands and layouts, slot metadata keys, target integrity, connector domain statuses and routes, the intent-first hand-off (`./intent`), conversion vocabulary, blueprint layer types and the case vocabulary, the ViableSkill/ViablePersona names (never the catalogue behind them), what belongs here versus in @owlmeans/viable, generated-project analysis/design/scaffold/metadata shapes, StoryDesignPort, schema conventions, and wire-version rules. Auto-invoked when importing a viable card type or flow, a slot command, a connector or conversion type, a target-integrity helper, or any *Schema this package exports.
4
4
  user-invocable: false
5
5
  ---
6
6
  <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
@@ -8,12 +8,13 @@ user-invocable: false
8
8
  # @owlmeans/viable-common
9
9
 
10
10
  **Layer:** Cross-cutting domain (contracts only)
11
- **Install:** `"@owlmeans/viable-common": "^0.0.32"` in `dependencies`
12
- **Subpaths:** `.` · `./slot` · `./connect` · `./convert` · `./integrity`
11
+ **Install:** `"@owlmeans/viable-common": "^0.0.34"` in `dependencies`
12
+ **Subpaths:** `.` · `./slot` · `./connect` · `./convert` · `./integrity` · `./intent`
13
13
  **Runtime-free:** no `@langchain/*`, no filesystem, no Ajv at run time (a devDependency, for the
14
14
  tests that compile the schemas). It depends on `@owlmeans/planning`, `@owlmeans/resource`,
15
- `@owlmeans/entrypoint`, `@owlmeans/route`, `@owlmeans/error`, `@owlmeans/agent-common` and
16
- `@owlmeans/llm-common` and on nothing else.
15
+ `@owlmeans/entrypoint`, `@owlmeans/route`, `@owlmeans/error`, `@owlmeans/agent-common`,
16
+ `@owlmeans/llm-common` and — for `./intent` alone — `@owlmeans/flow`, `@owlmeans/auth` and
17
+ `@owlmeans/context`, and on nothing else.
17
18
 
18
19
  Every name the OwlMeans Viable platform puts on a wire, on a volume or in a prompt is declared
19
20
  here once, and the four runtimes that must agree about it — the manager API, the agent, the
@@ -21,15 +22,24 @@ publisher/production runtime, and the connector SDK on somebody's laptop — all
21
22
  declaration. A vocabulary copied instead of imported is how one tree gets two totals, one
22
23
  refusal two spellings, and one ceiling two values.
23
24
 
25
+ **Names, not agent-only data.** This package is imported by the BROWSER too, so everything in it
26
+ ships in every visitor's bundle. Prompt, persona and blueprint-case DATA that only the AI agent
27
+ library ever reads — never the browser or another server package — belongs in `@owlmeans/viable`
28
+ instead: the skill bodies and their order, the persona prompt
29
+ policies, the blueprint case table and resolution, the BA model-answer schemas. What stays here is
30
+ what another package's contract references by type — the `ViableSkill` / `ViablePersona` enums and
31
+ the `Blueprint` types and vocabulary that execution state and card fields name.
32
+
24
33
  ## Key Exports
25
34
 
26
35
  | Subpath | What it declares |
27
36
  |---|---|
28
- | `.` (barrel) | The planning module (`VIABLE_*_TYPE`, `VIABLE_TYPE_SCHEMAS`, `VIABLE_FLOW_SCHEMAS`, `ViableStoryStatus`/`ViableProjectStatus` and their transitions, `ViableSpecCategory`, `ViableRelationship`, `ViableChannel`, `ViableProjectCard`/`ViableStoryCard`, the card helpers, the landing sentence helpers, the `Project*` refusals); `SlotMetadata` and the three metadata vocabularies (`metadataConfigs`, `metadataLists`, `metadataSecrets`), `BRANDING_ENV_KEYS` / `brandingEnv`; `ProjectArea` / `AREA_PATHS` / `AREA_ACCESS` / `AREA_TIER`; `ModelRole` and the viable `ExecutionState`; `ViableSkill` / `ViablePersona` / `VIABLE_SKILLS`; the blueprint, its cases and `landingGatePreferenceOf`; the BA, dev, UX, design and scaffold shapes and their schemas, `StoryDesignPort`; `ModerationCategory` / `ModerationSubject` / `decideModeration`; the `docs/` metadata paths; `PreviewEventType` |
37
+ | `.` (barrel) | The planning module (`VIABLE_*_TYPE`, `VIABLE_TYPE_SCHEMAS`, `VIABLE_FLOW_SCHEMAS`, `ViableStoryStatus`/`ViableProjectStatus` and their transitions, `ViableSpecCategory`, `ViableRelationship`, `ViableChannel`, `ViableProjectCard`/`ViableStoryCard`, the card helpers, the landing sentence helpers, the `Project*` refusals); `SlotMetadata` and the three metadata vocabularies (`metadataConfigs`, `metadataLists`, `metadataSecrets`), `BRANDING_ENV_KEYS` / `brandingEnv`; `ProjectArea` / `AREA_PATHS` / `AREA_ACCESS` / `AREA_TIER`; `ModelRole` and the viable `ExecutionState`; the `ViableSkill` / `ViablePersona` enums (names only); the `Blueprint` layer types, `BlueprintRef` / `BlueprintPatch`, `BlueprintCase` / `GameKind`, `DEFAULT_BLUEPRINT_ID` / `BLUEPRINT_META_KEY` and `landingGatePreferenceOf`; the BA shapes and helpers (`mergeConnectingStories`), the dev, UX, design and scaffold shapes and their schemas, `StoryDesignPort`; `ModerationCategory` / `ModerationSubject` / `decideModeration`; the `docs/` metadata paths; `PreviewEventType` |
29
38
  | `./slot` | `SlotCommandType` and the `SlotFileCommand` / `SlotShellCommand` / `SlotGitCommand` sets, `SubProject`, `WorkloadKind`, the target ports and process markers, `slotOrigin` / `targetRedirectUrisForOrigin` |
30
39
  | `./connect` | `ConnectTarget`, `ConnectLlm`, `ConnectHarness`, `ConnectExecutor`, `ConnectOpKind`, `ConnectProjectStatus`, `ConnectStoryStatus`, `ConnectPipelineState`, `ConnectWaitReason`, `ConnectProjectBranding` / `ConnectProjectBrandingSave`, `ModelTier` + `tierOfRole`/`clampTier`, `ModelTask*`, `InquiryPayload` + `ConnectInquiryKind`, the session and domain-status views, the `Connect*` error family, `connectProtocols(opts)` and every `*Schema` behind them |
31
40
  | `./convert` | `ConversionStage`/`Status`/`Decision` and the `stageAfter`/`decisionFor`/`canEnter` transitions, `OriginKind`/`Shape`/`State`, `StackId` + `STACK_FAMILY`, `ArchitectureCase`, `ConvertibilityVerdict`/`Reason`, the census classifiers (`fileClassOf`, `sizeClassOf`, `entropyClassOf`, `binaryByExtension`), the `docs/conversion/` paths, `CONVERTED_ORIGIN_DIR`, `SOURCE_LIST_EXCLUSIONS`, `CENSUS_SKIP_DIRS`, `RELOCATE_ALWAYS_KEEP`, and the model-answer schemas the conversion asks with |
32
41
  | `./integrity` | `TargetLayout` + `TARGET_LAYOUTS`, `detectTargetLayout`, `verifyTargetShape`, `TARGET_INTEGRITY_FILES`, `TARGET_PROTECTED_FILES`, `isLegacyLayout`, `targetPackageName` |
42
+ | `./intent` | The intent-first hand-off from the public site to the platform: `intent` (the four aliases), `makeIntentProtocols(opts?)` (two GUEST API routes + the `/start` landing screen), `intentFlow` + `IntentFlowStep` + `INTENT_PAYLOAD_REF`, `IntentStashBodySchema` / `IntentPickupBodySchema`, the `INTENT_*` constants (TTL, prompt cap, reference pattern, draft and suspend windows), `IntentDraft`, `IntentExpired` (404) / `IntentThrottled` (429) |
33
43
 
34
44
  ## The planning module
35
45
 
@@ -253,7 +263,7 @@ code, never as `minItems`/`maxItems`. The descriptions are what the planning mod
253
263
  state each field's purpose and bounds; `gate.target` is filled by code and described as such.
254
264
 
255
265
  **A field that crosses a version skew carries no `enum`.** Users run
256
- `npx -y @owlmeans/viable-mcp@^0.1.18-rc.29` (the moving prerelease tag) against a separately deployed
266
+ `npx -y @owlmeans/viable-mcp@^0.1.18-rc.31` (the moving prerelease tag) against a separately deployed
257
267
  platform, so `ConnectCapabilitiesSchema.executors.items`
258
268
  is a bare string: a newer executor kind must stay an unused capability on an older platform, never
259
269
  a refused session. Apply the same reasoning to anything else a newer connector may send an older
@@ -295,6 +305,45 @@ pending inquiry and `waitingFor` reason; none exposes a generic technical operat
295
305
  new long-running domain by extending its status view and endpoint, not by adding a parallel polling
296
306
  vocabulary.
297
307
 
308
+ ## The intent-first hand-off (`./intent`)
309
+
310
+ A prompt typed on the PUBLIC site (owlmeans.com, a static Astro app that cannot import the platform
311
+ repo) reaches the platform through this one subpath, which is why it lives here and not in viable:
312
+ the site, the manager API and the manager web must agree on every address, schema and step.
313
+
314
+ - **Two guest routes and one screen, no guard, no gate, no service.** `makeIntentProtocols()` declares
315
+ `stash` (POST `/public/intent`, body `{ prompt 1..8192, consent: const true }` → `{ ref, expiresAt }`),
316
+ `pickup` (POST `/public/intent/pickup`, body `{ ref }` where `ref` is exactly `createIdOfLength(24)`
317
+ Base58 → `{ prompt }`) and `landing` (`frontend()` at `/start`, `sticky`). A consumer mounts the
318
+ tree OUTSIDE any guarded parent — a route inherits every ancestor's guard, so under the account
319
+ base a visitor with no account would be refused — and fills `service` itself (the site binds
320
+ `landing` with `{ routeOptions: { overrides: { service } } }`, which is also what makes its `url()`
321
+ absolute). `consent` is a schema constant so a request without the data-processing confirmation
322
+ cannot exist on the wire.
323
+ - **The prompt never travels in a URL or a flow token.** The server keeps it `INTENT_TTL_SECONDS`
324
+ (120) under the unguessable `ref`, and collects it with one `GETDEL` (`pickup`); only `?ref=`
325
+ crosses. The flow payload is CSV-joined without escaping and the token is unsigned, so the flow
326
+ carries the reference or nothing.
327
+ - **`intentFlow` is walked on both sides and never becomes the live flow model.** `compose`
328
+ (initial, the site) →`handoff`→ `land` (initial, module = the landing) →`review`→ `review`
329
+ (module `HOME`), plus the EXPLICIT `land` →`sign-in`→ `sign-in` (module `DISPATCHER`) →`next`→
330
+ `review`. The site does `transit('handoff', true, { ref })` and redirects to `land`'s module URL
331
+ with the payload as query; the landing enters at `land` fresh, and a signed-out visitor is parked
332
+ with `suspendFlow` at `sign-in`, whose `next()` is the home screen. The parameter is `?ref=` —
333
+ never `?flow=`, which `web-flow`'s `lazyInit` parses on every page load of an app that registered
334
+ the flow service, and never `?intent=`, which the login surrogate window owns.
335
+ - **CORS is not declared here.** The routes ride the framework's global `origin: '*'` (no
336
+ credentials); `makeIntentProtocols` carries a `TODO(cors)` naming the origins to keep allowed if a
337
+ deployment ever restricts them globally.
338
+ - **The browser draft is IndexedDB, per origin.** `IntentDraft` (`id`, `ref`, `prompt`, `expiresAt`) is
339
+ what the platform's own browser keeps between pickup and the decision (`INTENT_DRAFT_TTL_MS`, 24 h,
340
+ checked on read — a client resource has no TTL). The public site cannot write it; that is the whole
341
+ reason for the server detour.
342
+
343
+ Tests: `tests/intent.spec.ts` (the four declarations and their absence of guards, the schema
344
+ accept/reject cases including crafted references, the flow walk both sides and what `suspendFlow`
345
+ would persist, the error statuses).
346
+
298
347
  ## Slot metadata keys: optional means omitted
299
348
 
300
349
  `SlotMetadata` is what the platform signs and pushes into a slot, and a slot publisher validates it
@@ -311,47 +360,36 @@ an owner setting, so it is declared on the type and kept out of them. The Google
311
360
  never travel in it: the publisher derives them from `brandingGoogleTag` itself (and from the record a
312
361
  production build writes), so the tag and the hosts it needs cannot disagree.
313
362
 
314
- ## Blueprint layers and the case table
315
-
316
- A `Blueprint` has five REQUIRED build layers (`technology`, `stack`, `template`, `createApp`,
317
- `packages`) and one OPTIONAL `experience` layer — what the product should do for its users,
318
- changing no dependency and no coder prompt. Read it only through a helper that answers the default
319
- for an absent layer: `landingGatePreferenceOf(blueprint)` answers `LandingGatePreference.Allow` for
320
- no layer, no key or a value this deploy does not know. `freezeBlueprint` freezes the layer when
321
- present and never adds it when absent.
322
-
323
- The preference is a PRIOR for the model that decides the landing gate, never the decision:
324
-
325
- | Case | `experience.landingGate` | `ViableSkill.LandingGate` added to |
326
- |---|---|---|
327
- | `web`, `ai-pipeline`, `ai-agent` | `encourage` | `BusinessAnalyst`, `UxDesigner`, `LayoutArchitect`, `ComponentArchitect`, `UiViewCoder`, `UiNavCoder` |
328
- | `scalable` | `allow` | — |
329
- | `game` | `discourage` | — |
330
-
331
- A case's `personaSkills` are composed with `joinPersonaSkills`, which UNIONS a persona two maps
332
- both name — an object spread keeps only the last list and silently drops the other case's skill.
333
- `applyBlueprintCase` then unions the case's persona skills with the base blueprint's.
334
-
335
- ## The design house style in the catalogue
336
-
337
- The `VisualDesigner` persona and the `ShadcnUi` skill teach one house style, and the template seed
338
- ships the same values: a white ground (black in dark mode) on `bg-background`; colour from ONE
339
- product accent, never from a background; depth only from a hairline, the neutral tile (`bg-muted`)
340
- and one `shadow-floating`; a heavy grotesk display face with tight tracking; motion that belongs
341
- to the illustration. The older classes (`gradient-heading`, `glass-card`, `eyebrow`, `glow-orb`,
342
- the soft/raised/glow shadows, `pulse-soft`, `spin-slow`) stay DEFINED because existing targets use
343
- them, are repainted flat, and are never taught as decoration. Any of it changes only when the
344
- customer's specification explicitly asks — a named background colour, a dark-only or coloured
345
- theme, a brand palette, gradients; the product's subject matter is not a request.
346
- `tests/skills.spec.ts` pins both texts against drifting back.
347
-
348
- `ViableSkill.LandingGate` teaches the gate-worthy story, the gate card, the synchronous handoff
349
- (`useLandingStart(target)` from the seed's `@/lib/handoff`: write, then navigate when signed in or
350
- start the plain sign-in; the guest home's `useLandingContinuation` sends the visitor on after
351
- sign-in — never `useLogin(target)`, whose continuation lands on the guarded screen) and the
352
- full-scale screen that reads and clears it. Every `ViableSkill` member has a body in `VIABLE_SKILLS` and a weight in
353
- `SKILL_ORDER`: the prompt service skips an alias it cannot resolve, so a missing body is a rule no
354
- model ever receives.
363
+ ## Blueprint types and the case vocabulary
364
+
365
+ `src/blueprint/` holds only types and constants. A `Blueprint` has five REQUIRED build layers
366
+ (`technology`, `stack`, `template`, `createApp`, `packages`) and one OPTIONAL `experience` layer —
367
+ what the product should do for its users, changing no dependency and no coder prompt. Read it only
368
+ through a helper that answers the default for an absent layer: `landingGatePreferenceOf(blueprint)`
369
+ answers `LandingGatePreference.Allow` for no layer, no key or a value this deploy does not know.
370
+ An execution carries a `BlueprintRef` — an id, an optional `case` and an override patch — never a
371
+ resolved blueprint.
372
+
373
+ `BlueprintCase` (`web`, `scalable`, `ai-pipeline`, `ai-agent`, `game`) and `GameKind` are the
374
+ vocabulary a project card's `fields.blueprintCase` / `fields.gameKind` carry. What a case MEANS —
375
+ the `BLUEPRINT_CASES` table with each case's patch, landing-gate prior and persona skills,
376
+ `applyBlueprintCase`, `applyBlueprintPatch` / `freezeBlueprint`, `joinPersonaSkills` and the
377
+ classification schema — lives in `@owlmeans/viable` (its `blueprints` / `blueprint-cases` skills).
378
+ That table is typed `Record<BlueprintCase, …>`, so a member added here fails to compile there until
379
+ it has a row.
380
+
381
+ ## Skill and persona names
382
+
383
+ `src/skills/` holds two enums and nothing else: `ViableSkill` (prompt-skill aliases) and
384
+ `ViablePersona` (who a helper's model is told it is). They are here because a `Blueprint`'s
385
+ `stack.skills` / `packages.skills` / `personaSkills` name them. The catalogue behind them — every
386
+ skill body (`VIABLE_SKILLS`) and weight (`SKILL_ORDER`), `FRAMEWORK_OWNED_SKILLS` /
387
+ `skillsForBlueprint`, each persona's prompt policy (`VIABLE_PERSONAS`), the design house style and
388
+ the landing-gate teaching — lives in `@owlmeans/viable` `src/skills/` (its `personas-and-skills`
389
+ skill). Adding a member here is half a change: `SKILL_ORDER` and `VIABLE_PERSONAS` are total records
390
+ and fail to compile until the new member has a weight or a policy, but `VIABLE_SKILLS` is a list,
391
+ and the prompt service skips an alias it cannot resolve — a missing body is a rule no model ever
392
+ receives.
355
393
 
356
394
  ## Closed sets that mean something
357
395
 
@@ -367,7 +405,7 @@ model ever receives.
367
405
  send, and no role but `Common` may resolve to the `common` directory.
368
406
  - **`ConversionStage`** — advanced only through `stageAfter` / `canEnter` / `decisionFor`. A stage
369
407
  transition computed at a call site is how a conversion re-enters a stage it already paid for.
370
- - **`ModerationCategory`** — a wire contract with seven languages of wording behind it. A fifth
408
+ - **`ModerationCategory`** — a wire contract with eight languages of wording behind it. A fifth
371
409
  shape is PHRASED into one of the four, never added.
372
410
 
373
411
  ## The conversion vocabulary is shared with three executors that walk the same tree
@@ -404,8 +442,18 @@ actually gave. Never introduce a local cap; import the one that exists.
404
442
  ## Errors: declared here, phrased where they are read
405
443
 
406
444
  `ConnectError` and its family (`ConnectSessionNotFound`, `ConnectSessionGone`, `ConnectOpTimeout`,
407
- `ConnectOpRefused`, `LocalSlotUnsupported`, `ConnectOpUnknown`) are `ResilientError` classes with
408
- markers under `viable-connect:`. `ConnectSessionGone` is registered FATAL on the agent side: a run
445
+ `ConnectOpRefused`, `LocalSlotUnsupported`, `ConnectOpUnknown`, `ConnectOutOfCredits`,
446
+ `ConnectConsentRequired`) are `ResilientError` classes with markers under `viable-connect:`. The two
447
+ refusals a connector turns into words for a person pack their fields into the message (only `type`
448
+ and `message` survive a marshal) and rebuild them in `finalizeUnmarshal()`: `ConnectOutOfCredits`
449
+ `out-of-credits:<gate>:<requiredUsd>:<balanceUsd>:<encodeURIComponent(topUpUrl)>` →
450
+ `gate`, `requiredUsd`, `balanceUsd`, `topUpUrl`; `ConnectConsentRequired`
451
+ `consent-required:<gate>:<deadline epoch ms | 0>:<encodeURIComponent(consentUrl)>` → `gate`,
452
+ `deadline?` (the latest withdrawal deadline waiting for consent; `0` = unknown), `consentUrl` —
453
+ build either with its `static encode(...)`. The deadline is epoch milliseconds and the URL goes
454
+ last because an ISO date and a URL both contain colons. `ConnectConsentRequired` is the connector's
455
+ face of the EU spend consent (`@owlmeans/payment` `PerformanceConsentRequired` on the web): only a
456
+ PERSON can give it, in the browser at `consentUrl`. `ConnectSessionGone` is registered FATAL on the agent side: a run
409
457
  whose executor has gone away must stop at once rather than spend a retry ladder, and the step fails
410
458
  as an OUTCOME so the run row records where it stopped and `pipeline.resume` picks it up when a
411
459
  connector returns.
@@ -424,6 +472,7 @@ Every refusal here declares its HTTP status on its leaf class (the `error` skill
424
472
  | Status | Classes |
425
473
  |---|---|
426
474
  | 402 | `ConnectOutOfCredits` |
475
+ | 428 | `ConnectConsentRequired` (a precondition only a person can meet) |
427
476
  | 404 | `ProjectNotFound`, `ProjectStoryNotFound`, `ConnectSessionNotFound`, `ConnectOpUnknown` |
428
477
  | 409 | `ProjectAgentOccupied`, `ProjectStoryMissconfigured`, `ConnectSessionGone` (no connector attached), `LocalSlotUnsupported` (the project's target) |
429
478
  | 422 | `ConnectOpRefused` (the connector refused the operation) |
@@ -444,9 +493,8 @@ the field schemas accepting `null` and refusing an undeclared field or a value o
444
493
  set, the landing fields and the landing sentence, the card helpers, the `follows` anchor, and the
445
494
  refusals' type names surviving a marshal), `scaffold.spec.ts` (an old-shape and a new-shape plan
446
495
  both passing the schema and the `scaffold` slot, `null` optionals accepted, no `minItems`),
447
- `blueprint.spec.ts` (each case's gate preference, the default, and the persona-skill unions),
448
- `branding.spec.ts` (the build env and the metadata vocabulary), `skills.spec.ts` (every skill has a
449
- body and a weight, the handler wrap-once teaching, the house style and the landing-gate skill),
496
+ `blueprint.spec.ts` (`landingGatePreferenceOf` — the default for an absent layer or an unknown
497
+ value), `branding.spec.ts` (the build env and the metadata vocabulary),
450
498
  `connect-entrypoints.spec.ts` (the tree's protocol count, no story route, the job-id round trip,
451
499
  the branding routes and their save body),
452
500
  `convert.spec.ts` (the three structural walks over the barrel, the
@@ -457,7 +505,8 @@ gate; capabilities accepting an executor kind this platform has never heard of;
457
505
  resume bodies), `design.spec.ts` (the design aggregate, staleness ranking, and the design schema
458
506
  refusing an undeclared field or an area outside the closed set, and `userStoryOfDesign`),
459
507
  `error-status.spec.ts` (every exported refusal's declared status, and its class and status after a
460
- marshal round trip).
508
+ marshal round trip), `connect-errors.spec.ts` (the packed fields of `ConnectOutOfCredits` and
509
+ `ConnectConsentRequired` fresh and after a round trip, an unknown deadline as `0`).
461
510
 
462
511
  ## Depends On
463
512
 
@@ -465,14 +514,17 @@ marshal round trip).
465
514
  - `@owlmeans/resource` — the `ResourceError` base of the project refusals
466
515
  - `@owlmeans/entrypoint`, `@owlmeans/route` — the entrypoint declarations
467
516
  - `@owlmeans/error` — the `Connect*` error family
468
- - `@owlmeans/llm-common` — `ExecutionEffort`/`ExecutionLevel`, `PromptPolicy`, `LlmPurpose`, and the
469
- inquiry ceilings this package's copies are pinned to
517
+ - `@owlmeans/llm-common` — `ExecutionEffort`/`ExecutionLevel`, `LlmPurpose`, the spectator
518
+ contracts, and the inquiry ceilings this package's copies are pinned to
470
519
  - `@owlmeans/agent-common` — the run and pipeline contracts a conversion's runs are declared against
520
+ - `@owlmeans/flow`, `@owlmeans/auth`, `@owlmeans/context` — `./intent` only: `ShallowFlow`/`UnknownFlow`,
521
+ the `DISPATCHER` alias and the `HOME` alias its flow steps address
471
522
 
472
523
  ## Related
473
524
 
474
525
  - [[viable-sdk]] — the connector SDK written entirely against these contracts
475
526
  - [[viable-mcp]] — the npx stdio server built on that SDK
527
+ - [[flow]] · [[client-flow]] — the model `intentFlow` is walked with, and `suspendFlow`, which parks it across sign-in
476
528
  - [[inquiry]] — the primitive `InquiryPayload` mirrors, and the one answer ceiling
477
529
  - [[llm-common]] — the contracts half of the model runtime
478
530
  - [[planning]] — the workcard model, flows, fold and protocol tree the planning module builds on
@@ -1,4 +1,3 @@
1
- export * from './schemas.js';
2
1
  export * from './helpers.js';
3
2
  export * from './consts.js';
4
3
  export type * from './types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ba/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,mBAAmB,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ba/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,mBAAmB,YAAY,CAAA"}
package/build/ba/index.js CHANGED
@@ -1,4 +1,3 @@
1
- export * from './schemas.js';
2
1
  export * from './helpers.js';
3
2
  export * from './consts.js';
4
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ba/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ba/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA"}
@@ -46,8 +46,8 @@ export var GameKind;
46
46
  /** What every AI case installs. The langchain peers are declared here, at ONE range. */
47
47
  const AI_DEPS = {
48
48
  [SubProject.Backend]: {
49
- '@owlmeans/llm': '^0.1.18-rc.36',
50
- '@owlmeans/agent': '^0.1.18-rc.37',
49
+ '@owlmeans/llm': '^0.1.18-rc.37',
50
+ '@owlmeans/agent': '^0.1.18-rc.38',
51
51
  '@langchain/core': '^1.2.9',
52
52
  '@langchain/anthropic': '^1.5.8',
53
53
  '@langchain/openai': '^1.5.10',
@@ -230,7 +230,7 @@ in advance.
230
230
  deps: {
231
231
  [SubProject.Backend]: {
232
232
  ...AI_DEPS[SubProject.Backend],
233
- '@owlmeans/agent-skills': '^0.1.18-rc.36',
233
+ '@owlmeans/agent-skills': '^0.1.18-rc.38',
234
234
  },
235
235
  },
236
236
  libraries: AI_LIBRARIES,
@@ -8,4 +8,42 @@
8
8
  export declare const DEFAULT_BLUEPRINT_ID = "owlmeans-fullstack-ts";
9
9
  /** Recorded on a project so a later run knows which blueprint drew it. */
10
10
  export declare const BLUEPRINT_META_KEY = "blueprint";
11
+ /**
12
+ * WHICH KIND of product is being built on a blueprint.
13
+ *
14
+ * A blueprint says what the STACK is — the language, the framework, the topology, the seeds. A
15
+ * case says what is being built ON it, and that is a different question with different consumers:
16
+ * the analyst framing the brief, the architect deciding whether a story needs a queue, the coder
17
+ * choosing which packages it may import.
18
+ *
19
+ * Deliberately NOT a second blueprint. Everything a case has to say is already a blueprint field,
20
+ * so a case is a PATCH and the resolution order stays base → case → per-run overrides. That is
21
+ * also why adding one is a data change: nothing reads `BlueprintCase` except the case table
22
+ * (`BLUEPRINT_CASES` in `@owlmeans/viable`) and the prompt that classifies a project into it.
23
+ */
24
+ export declare enum BlueprintCase {
25
+ /** A web application whose every feature fits inside a request. No queue, no worker, no agents. */
26
+ Web = "web",
27
+ /** A web application with work that genuinely belongs off the request path. */
28
+ Scalable = "scalable",
29
+ /** The product's value comes from ordered, deterministic model-driven steps. */
30
+ AiPipeline = "ai-pipeline",
31
+ /** The product's value comes from an agent that decides its own path through tools. */
32
+ AiAgent = "ai-agent",
33
+ /** A browser game: a three.js scene with an ordinary React interface over it. */
34
+ Game = "game"
35
+ }
36
+ /**
37
+ * How a game is played, which decides who owns its state.
38
+ *
39
+ * Recorded beside the case rather than folded into it, because it changes nothing about the
40
+ * dependencies and everything about where the logic goes. `OnlineTurn` is the default for
41
+ * anything multiplayer unless the brief plainly asks for live play — it is the shape that
42
+ * actually builds, and it needs no socket, no tick loop and no reconciliation.
43
+ */
44
+ export declare enum GameKind {
45
+ Casual = "casual",
46
+ OnlineTurn = "online-turn",
47
+ OnlineLive = "online-live"
48
+ }
11
49
  //# sourceMappingURL=consts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../../src/blueprint/consts.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,0BAA0B,CAAA;AAE3D,0EAA0E;AAC1E,eAAO,MAAM,kBAAkB,cAAc,CAAA"}
1
+ {"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../../src/blueprint/consts.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,0BAA0B,CAAA;AAE3D,0EAA0E;AAC1E,eAAO,MAAM,kBAAkB,cAAc,CAAA;AAE7C;;;;;;;;;;;;GAYG;AACH,oBAAY,aAAa;IACvB,mGAAmG;IACnG,GAAG,QAAQ;IACX,+EAA+E;IAC/E,QAAQ,aAAa;IACrB,gFAAgF;IAChF,UAAU,gBAAgB;IAC1B,uFAAuF;IACvF,OAAO,aAAa;IACpB,iFAAiF;IACjF,IAAI,SAAS;CACd;AAED;;;;;;;GAOG;AACH,oBAAY,QAAQ;IAClB,MAAM,WAAW;IACjB,UAAU,gBAAgB;IAC1B,UAAU,gBAAgB;CAC3B"}
@@ -8,4 +8,44 @@
8
8
  export const DEFAULT_BLUEPRINT_ID = 'owlmeans-fullstack-ts';
9
9
  /** Recorded on a project so a later run knows which blueprint drew it. */
10
10
  export const BLUEPRINT_META_KEY = 'blueprint';
11
+ /**
12
+ * WHICH KIND of product is being built on a blueprint.
13
+ *
14
+ * A blueprint says what the STACK is — the language, the framework, the topology, the seeds. A
15
+ * case says what is being built ON it, and that is a different question with different consumers:
16
+ * the analyst framing the brief, the architect deciding whether a story needs a queue, the coder
17
+ * choosing which packages it may import.
18
+ *
19
+ * Deliberately NOT a second blueprint. Everything a case has to say is already a blueprint field,
20
+ * so a case is a PATCH and the resolution order stays base → case → per-run overrides. That is
21
+ * also why adding one is a data change: nothing reads `BlueprintCase` except the case table
22
+ * (`BLUEPRINT_CASES` in `@owlmeans/viable`) and the prompt that classifies a project into it.
23
+ */
24
+ export var BlueprintCase;
25
+ (function (BlueprintCase) {
26
+ /** A web application whose every feature fits inside a request. No queue, no worker, no agents. */
27
+ BlueprintCase["Web"] = "web";
28
+ /** A web application with work that genuinely belongs off the request path. */
29
+ BlueprintCase["Scalable"] = "scalable";
30
+ /** The product's value comes from ordered, deterministic model-driven steps. */
31
+ BlueprintCase["AiPipeline"] = "ai-pipeline";
32
+ /** The product's value comes from an agent that decides its own path through tools. */
33
+ BlueprintCase["AiAgent"] = "ai-agent";
34
+ /** A browser game: a three.js scene with an ordinary React interface over it. */
35
+ BlueprintCase["Game"] = "game";
36
+ })(BlueprintCase || (BlueprintCase = {}));
37
+ /**
38
+ * How a game is played, which decides who owns its state.
39
+ *
40
+ * Recorded beside the case rather than folded into it, because it changes nothing about the
41
+ * dependencies and everything about where the logic goes. `OnlineTurn` is the default for
42
+ * anything multiplayer unless the brief plainly asks for live play — it is the shape that
43
+ * actually builds, and it needs no socket, no tick loop and no reconciliation.
44
+ */
45
+ export var GameKind;
46
+ (function (GameKind) {
47
+ GameKind["Casual"] = "casual";
48
+ GameKind["OnlineTurn"] = "online-turn";
49
+ GameKind["OnlineLive"] = "online-live";
50
+ })(GameKind || (GameKind = {}));
11
51
  //# sourceMappingURL=consts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"consts.js","sourceRoot":"","sources":["../../src/blueprint/consts.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,uBAAuB,CAAA;AAE3D,0EAA0E;AAC1E,MAAM,CAAC,MAAM,kBAAkB,GAAG,WAAW,CAAA"}
1
+ {"version":3,"file":"consts.js","sourceRoot":"","sources":["../../src/blueprint/consts.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,uBAAuB,CAAA;AAE3D,0EAA0E;AAC1E,MAAM,CAAC,MAAM,kBAAkB,GAAG,WAAW,CAAA;AAE7C;;;;;;;;;;;;GAYG;AACH,MAAM,CAAN,IAAY,aAWX;AAXD,WAAY,aAAa;IACvB,mGAAmG;IACnG,4BAAW,CAAA;IACX,+EAA+E;IAC/E,sCAAqB,CAAA;IACrB,gFAAgF;IAChF,2CAA0B,CAAA;IAC1B,uFAAuF;IACvF,qCAAoB,CAAA;IACpB,iFAAiF;IACjF,8BAAa,CAAA;AACf,CAAC,EAXW,aAAa,KAAb,aAAa,QAWxB;AAED;;;;;;;GAOG;AACH,MAAM,CAAN,IAAY,QAIX;AAJD,WAAY,QAAQ;IAClB,6BAAiB,CAAA;IACjB,sCAA0B,CAAA;IAC1B,sCAA0B,CAAA;AAC5B,CAAC,EAJW,QAAQ,KAAR,QAAQ,QAInB"}
@@ -1,6 +1,3 @@
1
1
  export * from './types.js';
2
2
  export * from './consts.js';
3
- export * from './case.js';
4
- export * from './schemas.js';
5
- export * from './resolve.js';
6
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/blueprint/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAE1B,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/blueprint/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAE1B,cAAc,aAAa,CAAA"}
@@ -1,6 +1,3 @@
1
1
  export * from './types.js';
2
2
  export * from './consts.js';
3
- export * from './case.js';
4
- export * from './schemas.js';
5
- export * from './resolve.js';
6
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/blueprint/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAE1B,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/blueprint/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAE1B,cAAc,aAAa,CAAA"}
@@ -171,11 +171,11 @@ export interface PackagesLayer {
171
171
  /**
172
172
  * Skills added to ONE persona, rather than to every prompt of the blueprint.
173
173
  *
174
- * The additive twin of {@link skillsForBlueprint}, which subtracts. `skills` above is what is
175
- * true of the whole stack; this is what is true of one performer — the analyst who has to know
176
- * that a game brief is a core loop rather than a numbered flow, the architect who has to know
177
- * when a tool loop is warranted. Without it a case could only change what a CODER is told, and
178
- * a case changes the product analysis first.
174
+ * The additive twin of `skillsForBlueprint` (in `@owlmeans/viable`), which subtracts. `skills`
175
+ * above is what is true of the whole stack; this is what is true of one performer — the analyst
176
+ * who has to know that a game brief is a core loop rather than a numbered flow, the architect who
177
+ * has to know when a tool loop is warranted. Without it a case could only change what a CODER is
178
+ * told, and a case changes the product analysis first.
179
179
  */
180
180
  personaSkills?: Partial<Record<ViablePersona, ViableSkill[]>>;
181
181
  /** Extra dependencies a role's manifest carries, beyond what the overlay ships. */
@@ -79,4 +79,27 @@ export declare class ConnectOutOfCredits extends ConnectError {
79
79
  private applyFields;
80
80
  finalizeUnmarshal(): void;
81
81
  }
82
+ /**
83
+ * The action would spend credits bought less than 14 days ago under EU consumer rules, and a person
84
+ * has not yet expressly asked the platform to start using them (the purchase can still be
85
+ * withdrawn from). Only a person can give that request — in the browser, at `consentUrl`.
86
+ *
87
+ * Packed like `ConnectOutOfCredits`, because only `type` and `message` survive a marshal:
88
+ * `consent-required:<gate>:<deadline epoch ms | 0>:<encodeURIComponent(consentUrl)>`. The deadline
89
+ * is epoch milliseconds and the URL goes last, because an ISO date and a URL both contain colons.
90
+ */
91
+ export declare class ConnectConsentRequired extends ConnectError {
92
+ static typeName: string;
93
+ /** A precondition only a person can meet, not a fault: answered 428. */
94
+ static httpStatus: number;
95
+ gate: string;
96
+ /** The latest withdrawal deadline of the purchases waiting for consent, when known. */
97
+ deadline?: Date;
98
+ consentUrl: string;
99
+ /** Build the packed message a caller passes to the constructor. */
100
+ static encode(gate: string, consentUrl: string, deadline?: Date | null): string;
101
+ constructor(message?: string);
102
+ private applyFields;
103
+ finalizeUnmarshal(): void;
104
+ }
82
105
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/connect/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,qBAAa,YAAa,SAAQ,cAAc;IAC9C,OAAuB,QAAQ,SAA4C;IAE3E,YAAY,OAAO,GAAE,MAAgB,EAEpC;CACF;AAED,iEAAiE;AACjE,qBAAa,sBAAuB,SAAQ,YAAY;IACtD,OAAuB,QAAQ,SAA4C;IAC3E,0EAA0E;IAC1E,OAAc,UAAU,SAAM;IAE9B,YAAY,OAAO,GAAE,MAAgB,EAGpC;CACF;AAED;;;;;;;;GAQG;AACH,qBAAa,kBAAmB,SAAQ,YAAY;IAClD,OAAuB,QAAQ,SAAwC;IACvE,2DAA2D;IAC3D,OAAc,UAAU,SAAM;IAE9B,YAAY,OAAO,GAAE,MAAgB,EAGpC;CACF;AAED,iFAAiF;AACjF,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAuB,QAAQ,SAAsC;IAErE,YAAY,OAAO,GAAE,MAAgB,EAGpC;CACF;AAED,6FAA6F;AAC7F,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAuB,QAAQ,SAAsC;IACrE,uEAAuE;IACvE,OAAc,UAAU,SAAM;IAE9B,YAAY,OAAO,GAAE,MAAgB,EAGpC;CACF;AAED;;;;;;GAMG;AACH,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,OAAuB,QAAQ,SAA6C;IAC5E,2EAA2E;IAC3E,OAAc,UAAU,SAAM;IAE9B,YAAY,OAAO,GAAE,MAAgB,EAGpC;CACF;AAED,6EAA6E;AAC7E,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAuB,QAAQ,SAAsC;IACrE,sFAAsF;IACtF,OAAc,UAAU,SAAM;IAE9B,YAAY,OAAO,GAAE,MAAgB,EAGpC;CACF;AAED;;;;;;;GAOG;AACH,qBAAa,mBAAoB,SAAQ,YAAY;IACnD,OAAuB,QAAQ,SAAyC;IACxE,6DAA6D;IAC7D,OAAc,UAAU,SAAM;IAEvB,IAAI,SAAK;IACT,WAAW,SAAI;IACf,UAAU,SAAI;IACd,QAAQ,SAAK;IAEpB,mEAAmE;IACnE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE7F;IAED,YAAY,OAAO,GAAE,MAAgB,EAIpC;IAED,OAAO,CAAC,WAAW;IAWV,iBAAiB,IAAI,IAAI,CAEjC;CACF"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/connect/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,qBAAa,YAAa,SAAQ,cAAc;IAC9C,OAAuB,QAAQ,SAA4C;IAE3E,YAAY,OAAO,GAAE,MAAgB,EAEpC;CACF;AAED,iEAAiE;AACjE,qBAAa,sBAAuB,SAAQ,YAAY;IACtD,OAAuB,QAAQ,SAA4C;IAC3E,0EAA0E;IAC1E,OAAc,UAAU,SAAM;IAE9B,YAAY,OAAO,GAAE,MAAgB,EAGpC;CACF;AAED;;;;;;;;GAQG;AACH,qBAAa,kBAAmB,SAAQ,YAAY;IAClD,OAAuB,QAAQ,SAAwC;IACvE,2DAA2D;IAC3D,OAAc,UAAU,SAAM;IAE9B,YAAY,OAAO,GAAE,MAAgB,EAGpC;CACF;AAED,iFAAiF;AACjF,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAuB,QAAQ,SAAsC;IAErE,YAAY,OAAO,GAAE,MAAgB,EAGpC;CACF;AAED,6FAA6F;AAC7F,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAuB,QAAQ,SAAsC;IACrE,uEAAuE;IACvE,OAAc,UAAU,SAAM;IAE9B,YAAY,OAAO,GAAE,MAAgB,EAGpC;CACF;AAED;;;;;;GAMG;AACH,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,OAAuB,QAAQ,SAA6C;IAC5E,2EAA2E;IAC3E,OAAc,UAAU,SAAM;IAE9B,YAAY,OAAO,GAAE,MAAgB,EAGpC;CACF;AAED,6EAA6E;AAC7E,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAuB,QAAQ,SAAsC;IACrE,sFAAsF;IACtF,OAAc,UAAU,SAAM;IAE9B,YAAY,OAAO,GAAE,MAAgB,EAGpC;CACF;AAED;;;;;;;GAOG;AACH,qBAAa,mBAAoB,SAAQ,YAAY;IACnD,OAAuB,QAAQ,SAAyC;IACxE,6DAA6D;IAC7D,OAAc,UAAU,SAAM;IAEvB,IAAI,SAAK;IACT,WAAW,SAAI;IACf,UAAU,SAAI;IACd,QAAQ,SAAK;IAEpB,mEAAmE;IACnE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE7F;IAED,YAAY,OAAO,GAAE,MAAgB,EAIpC;IAED,OAAO,CAAC,WAAW;IAWV,iBAAiB,IAAI,IAAI,CAEjC;CACF;AAED;;;;;;;;GAQG;AACH,qBAAa,sBAAuB,SAAQ,YAAY;IACtD,OAAuB,QAAQ,SAA4C;IAC3E,wEAAwE;IACxE,OAAc,UAAU,SAAM;IAEvB,IAAI,SAAK;IAChB,uFAAuF;IAChF,QAAQ,CAAC,EAAE,IAAI,CAAA;IACf,UAAU,SAAK;IAEtB,mEAAmE;IACnE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,CAI9E;IAED,YAAY,OAAO,GAAE,MAAgB,EAIpC;IAED,OAAO,CAAC,WAAW;IAiBV,iBAAiB,IAAI,IAAI,CAEjC;CACF"}
@@ -117,6 +117,55 @@ export class ConnectOutOfCredits extends ConnectError {
117
117
  this.applyFields();
118
118
  }
119
119
  }
120
+ /**
121
+ * The action would spend credits bought less than 14 days ago under EU consumer rules, and a person
122
+ * has not yet expressly asked the platform to start using them (the purchase can still be
123
+ * withdrawn from). Only a person can give that request — in the browser, at `consentUrl`.
124
+ *
125
+ * Packed like `ConnectOutOfCredits`, because only `type` and `message` survive a marshal:
126
+ * `consent-required:<gate>:<deadline epoch ms | 0>:<encodeURIComponent(consentUrl)>`. The deadline
127
+ * is epoch milliseconds and the URL goes last, because an ISO date and a URL both contain colons.
128
+ */
129
+ export class ConnectConsentRequired extends ConnectError {
130
+ static typeName = `ConsentRequired${ConnectError.typeName}`;
131
+ /** A precondition only a person can meet, not a fault: answered 428. */
132
+ static httpStatus = 428;
133
+ gate = '';
134
+ /** The latest withdrawal deadline of the purchases waiting for consent, when known. */
135
+ deadline;
136
+ consentUrl = '';
137
+ /** Build the packed message a caller passes to the constructor. */
138
+ static encode(gate, consentUrl, deadline) {
139
+ const at = deadline != null && !Number.isNaN(deadline.getTime()) ? deadline.getTime() : 0;
140
+ return `${gate}:${at}:${encodeURIComponent(consentUrl)}`;
141
+ }
142
+ constructor(message = 'error') {
143
+ super(`consent-required:${message}`);
144
+ this.type = ConnectConsentRequired.typeName;
145
+ this.applyFields();
146
+ }
147
+ applyFields() {
148
+ const marker = 'consent-required:';
149
+ const at = this.message.lastIndexOf(marker);
150
+ if (at < 0)
151
+ return;
152
+ const [gate, deadline, encodedUrl] = this.message.slice(at + marker.length).split(':');
153
+ this.gate = gate ?? '';
154
+ const ms = Number(deadline ?? 0);
155
+ this.deadline = Number.isFinite(ms) && ms > 0 ? new Date(ms) : undefined;
156
+ let url = '';
157
+ try {
158
+ url = encodedUrl != null && encodedUrl !== '' ? decodeURIComponent(encodedUrl) : '';
159
+ }
160
+ catch {
161
+ url = encodedUrl ?? '';
162
+ }
163
+ this.consentUrl = url;
164
+ }
165
+ finalizeUnmarshal() {
166
+ this.applyFields();
167
+ }
168
+ }
120
169
  ResilientError.registerErrorClass(ConnectError);
121
170
  ResilientError.registerErrorClass(ConnectSessionNotFound);
122
171
  ResilientError.registerErrorClass(ConnectSessionGone);
@@ -125,4 +174,5 @@ ResilientError.registerErrorClass(ConnectOpRefused);
125
174
  ResilientError.registerErrorClass(LocalSlotUnsupported);
126
175
  ResilientError.registerErrorClass(ConnectOpUnknown);
127
176
  ResilientError.registerErrorClass(ConnectOutOfCredits);
177
+ ResilientError.registerErrorClass(ConnectConsentRequired);
128
178
  //# sourceMappingURL=errors.js.map