@owlmeans/viable-common 0.0.33 → 0.0.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/agent-presentation/SKILL.md +1 -1
- package/agent-meta/skills/viable-common/SKILL.md +93 -62
- package/build/ba/index.d.ts +0 -1
- package/build/ba/index.d.ts.map +1 -1
- package/build/ba/index.js +0 -1
- package/build/ba/index.js.map +1 -1
- package/build/blueprint/consts.d.ts +38 -0
- package/build/blueprint/consts.d.ts.map +1 -1
- package/build/blueprint/consts.js +40 -0
- package/build/blueprint/consts.js.map +1 -1
- package/build/blueprint/index.d.ts +0 -3
- package/build/blueprint/index.d.ts.map +1 -1
- package/build/blueprint/index.js +0 -3
- package/build/blueprint/index.js.map +1 -1
- package/build/blueprint/types.d.ts +5 -5
- package/build/intent/consts.d.ts +57 -0
- package/build/intent/consts.d.ts.map +1 -0
- package/build/intent/consts.js +58 -0
- package/build/intent/consts.js.map +1 -0
- package/build/intent/entrypoints.d.ts +27 -0
- package/build/intent/entrypoints.d.ts.map +1 -0
- package/build/intent/entrypoints.js +28 -0
- package/build/intent/entrypoints.js.map +1 -0
- package/build/intent/errors.d.ts +20 -0
- package/build/intent/errors.d.ts.map +1 -0
- package/build/intent/errors.js +28 -0
- package/build/intent/errors.js.map +1 -0
- package/build/intent/flow.d.ts +17 -0
- package/build/intent/flow.d.ts.map +1 -0
- package/build/intent/flow.js +65 -0
- package/build/intent/flow.js.map +1 -0
- package/build/intent/index.d.ts +7 -0
- package/build/intent/index.d.ts.map +1 -0
- package/build/intent/index.js +6 -0
- package/build/intent/index.js.map +1 -0
- package/build/intent/schemas.d.ts +10 -0
- package/build/intent/schemas.d.ts.map +1 -0
- package/build/intent/schemas.js +24 -0
- package/build/intent/schemas.js.map +1 -0
- package/build/intent/types.d.ts +40 -0
- package/build/intent/types.d.ts.map +1 -0
- package/build/intent/types.js +2 -0
- package/build/intent/types.js.map +1 -0
- package/build/scaffold/consts.d.ts +14 -1
- package/build/scaffold/consts.d.ts.map +1 -1
- package/build/scaffold/consts.js +10 -0
- package/build/scaffold/consts.js.map +1 -1
- package/build/scaffold/schemas.d.ts +7 -0
- package/build/scaffold/schemas.d.ts.map +1 -1
- package/build/scaffold/schemas.js +119 -68
- package/build/scaffold/schemas.js.map +1 -1
- package/build/scaffold/types.d.ts +62 -24
- package/build/scaffold/types.d.ts.map +1 -1
- package/build/skills/consts.d.ts +0 -34
- package/build/skills/consts.d.ts.map +1 -1
- package/build/skills/consts.js +0 -106
- package/build/skills/consts.js.map +1 -1
- package/build/skills/index.d.ts +0 -1
- package/build/skills/index.d.ts.map +1 -1
- package/build/skills/index.js +0 -1
- package/build/skills/index.js.map +1 -1
- package/build/skills/roles.d.ts +0 -9
- package/build/skills/roles.d.ts.map +1 -1
- package/build/skills/roles.js +0 -226
- package/build/skills/roles.js.map +1 -1
- package/build/ux/schemas.js +2 -2
- package/build/ux/schemas.js.map +1 -1
- package/package.json +17 -7
- package/src/ba/index.ts +0 -1
- package/src/blueprint/consts.ts +40 -0
- package/src/blueprint/index.ts +0 -3
- package/src/blueprint/types.ts +5 -5
- package/src/intent/consts.ts +66 -0
- package/src/intent/entrypoints.ts +43 -0
- package/src/intent/errors.ts +33 -0
- package/src/intent/flow.ts +67 -0
- package/src/intent/index.ts +6 -0
- package/src/intent/schemas.ts +27 -0
- package/src/intent/types.ts +45 -0
- package/src/scaffold/consts.ts +14 -1
- package/src/scaffold/schemas.ts +125 -69
- package/src/scaffold/types.ts +64 -23
- package/src/skills/consts.ts +0 -112
- package/src/skills/index.ts +0 -1
- package/src/skills/roles.ts +0 -267
- package/src/ux/schemas.ts +2 -2
- package/tests/blueprint.spec.ts +2 -66
- package/tests/intent.spec.ts +121 -0
- package/tests/scaffold.spec.ts +73 -13
- package/src/ba/schemas.ts +0 -196
- package/src/blueprint/case.ts +0 -320
- package/src/blueprint/resolve.ts +0 -136
- package/src/blueprint/schemas.ts +0 -44
- package/src/skills/catalogue.ts +0 -1864
- package/tests/skills.spec.ts +0 -125
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.
|
|
24
|
+
bun add @owlmeans/viable-common@^0.0.35
|
|
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.
|
|
42
|
+
`npx -y @owlmeans/viable-mcp@^0.1.18-rc.32` 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.
|
|
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
|
package/agent-meta/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"package": "@owlmeans/viable-common",
|
|
4
|
-
"version": "0.0.
|
|
5
|
-
"generatedAt": "2026-09-
|
|
4
|
+
"version": "0.0.35",
|
|
5
|
+
"generatedAt": "2026-09-25T12:22:06.208Z",
|
|
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.
|
|
9
|
+
**Install:** `"@owlmeans/viable-common": "^0.0.35"` 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
|
|
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.
|
|
12
|
-
**Subpaths:** `.` · `./slot` · `./connect` · `./convert` · `./integrity`
|
|
11
|
+
**Install:** `"@owlmeans/viable-common": "^0.0.35"` 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
|
|
16
|
-
`@owlmeans/llm-common` and
|
|
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`
|
|
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.
|
|
266
|
+
`npx -y @owlmeans/viable-mcp@^0.1.18-rc.32` (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,55 +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
|
|
315
|
-
|
|
316
|
-
A `Blueprint` has five REQUIRED build layers
|
|
317
|
-
`packages`) and one OPTIONAL `experience` layer —
|
|
318
|
-
changing no dependency and no coder prompt. Read it only
|
|
319
|
-
for an absent layer: `landingGatePreferenceOf(blueprint)`
|
|
320
|
-
no layer, no key or a value this deploy does not know.
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
to the
|
|
342
|
-
the
|
|
343
|
-
|
|
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.
|
|
355
|
-
|
|
356
|
-
`OwlMeansServer` and `FixerHeuristics` teach one rule from both ends: the PROTOCOL decides a
|
|
357
|
-
handler's types. A handler's parameter and return types are exactly what its declaration in the
|
|
358
|
-
target's shared entrypoints module names, imported from the shared package — never an input or
|
|
359
|
-
record type declared in the api or backend package, which the shared package cannot import. The
|
|
360
|
-
example handler therefore takes the shared `Task`, never an invented `…Payload`/`…Input` type
|
|
361
|
-
(an example wins over the rule beside it), and a `TS2345` function-vs-function mismatch at a binding
|
|
362
|
-
line is repaired in the HANDLER, never by bending the declaration toward it.
|
|
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.
|
|
363
393
|
|
|
364
394
|
## Closed sets that mean something
|
|
365
395
|
|
|
@@ -463,10 +493,8 @@ the field schemas accepting `null` and refusing an undeclared field or a value o
|
|
|
463
493
|
set, the landing fields and the landing sentence, the card helpers, the `follows` anchor, and the
|
|
464
494
|
refusals' type names surviving a marshal), `scaffold.spec.ts` (an old-shape and a new-shape plan
|
|
465
495
|
both passing the schema and the `scaffold` slot, `null` optionals accepted, no `minItems`),
|
|
466
|
-
`blueprint.spec.ts` (
|
|
467
|
-
`branding.spec.ts` (the build env and the metadata vocabulary),
|
|
468
|
-
body and a weight, the handler wrap-once teaching, handler types taken from the protocol and the
|
|
469
|
-
mismatch repaired in the handler, 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),
|
|
470
498
|
`connect-entrypoints.spec.ts` (the tree's protocol count, no story route, the job-id round trip,
|
|
471
499
|
the branding routes and their save body),
|
|
472
500
|
`convert.spec.ts` (the three structural walks over the barrel, the
|
|
@@ -486,14 +514,17 @@ marshal round trip), `connect-errors.spec.ts` (the packed fields of `ConnectOutO
|
|
|
486
514
|
- `@owlmeans/resource` — the `ResourceError` base of the project refusals
|
|
487
515
|
- `@owlmeans/entrypoint`, `@owlmeans/route` — the entrypoint declarations
|
|
488
516
|
- `@owlmeans/error` — the `Connect*` error family
|
|
489
|
-
- `@owlmeans/llm-common` — `ExecutionEffort`/`ExecutionLevel`, `
|
|
490
|
-
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
|
|
491
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
|
|
492
522
|
|
|
493
523
|
## Related
|
|
494
524
|
|
|
495
525
|
- [[viable-sdk]] — the connector SDK written entirely against these contracts
|
|
496
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
|
|
497
528
|
- [[inquiry]] — the primitive `InquiryPayload` mirrors, and the one answer ceiling
|
|
498
529
|
- [[llm-common]] — the contracts half of the model runtime
|
|
499
530
|
- [[planning]] — the workcard model, flows, fold and protocol tree the planning module builds on
|
package/build/ba/index.d.ts
CHANGED
package/build/ba/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ba/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAC5B,cAAc,
|
|
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
package/build/ba/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ba/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAC5B,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ba/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA"}
|
|
@@ -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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/blueprint/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAE1B,cAAc,aAAa,CAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/blueprint/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAE1B,cAAc,aAAa,CAAA"}
|
package/build/blueprint/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/blueprint/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAE1B,cAAc,aAAa,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
|
|
175
|
-
* true of the whole stack; this is what is true of one performer — the analyst
|
|
176
|
-
* that a game brief is a core loop rather than a numbered flow, the architect who
|
|
177
|
-
* when a tool loop is warranted. Without it a case could only change what a CODER is
|
|
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. */
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The intent-first hand-off — how a prompt typed on the public site reaches the platform.
|
|
3
|
+
*
|
|
4
|
+
* A visitor types the idea for a project on the marketing site before they have an account. The
|
|
5
|
+
* site cannot write into the platform's browser storage (IndexedDB is per origin) and must not put
|
|
6
|
+
* the prompt in a URL, so the prompt takes a short detour through the platform's own cache: the
|
|
7
|
+
* site stashes it behind an unguessable reference, sends the browser to the platform with only that
|
|
8
|
+
* reference, and the platform picks the prompt up once — after which it lives in the visitor's own
|
|
9
|
+
* browser until they decide what to do with it.
|
|
10
|
+
*
|
|
11
|
+
* Everything here is serializable and runtime-free: the site, the manager API and the manager web
|
|
12
|
+
* read the same declarations, and none of them may reinvent a name the others parse.
|
|
13
|
+
*/
|
|
14
|
+
/** Every address of the hand-off. API routes are guest routes; the landing is a screen. */
|
|
15
|
+
export declare const intent: Readonly<{
|
|
16
|
+
readonly base: 'viable:manager-api:intent:base';
|
|
17
|
+
readonly stash: 'viable:manager-api:intent:stash';
|
|
18
|
+
readonly pickup: 'viable:manager-api:intent:pickup';
|
|
19
|
+
readonly landing: 'viable:manager-web:intent:landing';
|
|
20
|
+
}>;
|
|
21
|
+
/** Where the guest API lives, and the screen the visitor's browser is sent to. */
|
|
22
|
+
export declare const INTENT_API_PATH = "/public/intent";
|
|
23
|
+
export declare const INTENT_LANDING_PATH = "/start";
|
|
24
|
+
/** The flow the two sides walk. */
|
|
25
|
+
export declare const INTENT_FLOW = "viable:intent";
|
|
26
|
+
/**
|
|
27
|
+
* How long the platform keeps a stashed prompt waiting for pickup. Short on purpose: the pickup
|
|
28
|
+
* happens the moment the browser lands, so anything older was abandoned, and a prompt is personal
|
|
29
|
+
* data the platform has no business holding once nobody is coming for it.
|
|
30
|
+
*/
|
|
31
|
+
export declare const INTENT_TTL_SECONDS = 120;
|
|
32
|
+
/** The longest prompt the platform will create a project from (`PromptSchema` in viable). */
|
|
33
|
+
export declare const INTENT_PROMPT_MAX = 8192;
|
|
34
|
+
/**
|
|
35
|
+
* The reference's shape: `createIdOfLength(24)` — Base58, so no `0`, `O`, `I` or `l`. Anything else
|
|
36
|
+
* is refused before the cache is asked, which keeps a crafted reference from ever being a key.
|
|
37
|
+
*/
|
|
38
|
+
export declare const INTENT_REF_LENGTH = 24;
|
|
39
|
+
export declare const INTENT_REF_PATTERN = "^[1-9A-HJ-NP-Za-km-z]{24}$";
|
|
40
|
+
/** The flow payload key carrying the reference — short, because a payload is CSV-joined. */
|
|
41
|
+
export declare const INTENT_PAYLOAD_REF = "ref";
|
|
42
|
+
/** How long the visitor's draft survives in their own browser waiting for a decision. */
|
|
43
|
+
export declare const INTENT_DRAFT_TTL_MS: number;
|
|
44
|
+
/** How long a suspended landing waits while the visitor signs in or registers. */
|
|
45
|
+
export declare const INTENT_SUSPEND_TTL_MS: number;
|
|
46
|
+
/** Steps of {@link intentFlow}, exported so a screen never spells one as a literal. */
|
|
47
|
+
export declare enum IntentFlowStep {
|
|
48
|
+
/** The public site: the prompt is typed and stashed. */
|
|
49
|
+
Compose = "compose",
|
|
50
|
+
/** The platform's landing screen: the stash is picked up. */
|
|
51
|
+
Land = "land",
|
|
52
|
+
/** The platform's own sign-in dispatcher. */
|
|
53
|
+
SignIn = "sign-in",
|
|
54
|
+
/** The platform's home screen, where the draft is offered back. */
|
|
55
|
+
Review = "review"
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=consts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../../src/intent/consts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,2FAA2F;AAC3F,eAAO,MAAM,MAAM;mBACX,gCAAgC;oBAC/B,iCAAiC;qBAChC,kCAAkC;sBACjC,mCAAmC;EACnC,CAAA;AAEX,kFAAkF;AAClF,eAAO,MAAM,eAAe,mBAAmB,CAAA;AAC/C,eAAO,MAAM,mBAAmB,WAAW,CAAA;AAE3C,mCAAmC;AACnC,eAAO,MAAM,WAAW,kBAAkB,CAAA;AAE1C;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,MAAM,CAAA;AAErC,6FAA6F;AAC7F,eAAO,MAAM,iBAAiB,OAAO,CAAA;AAErC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,KAAK,CAAA;AACnC,eAAO,MAAM,kBAAkB,+BAA+B,CAAA;AAE9D,4FAA4F;AAC5F,eAAO,MAAM,kBAAkB,QAAQ,CAAA;AAEvC,yFAAyF;AACzF,eAAO,MAAM,mBAAmB,QAAsB,CAAA;AAEtD,kFAAkF;AAClF,eAAO,MAAM,qBAAqB,QAAiB,CAAA;AAEnD,uFAAuF;AACvF,oBAAY,cAAc;IACxB,wDAAwD;IACxD,OAAO,YAAY;IACnB,6DAA6D;IAC7D,IAAI,SAAS;IACb,6CAA6C;IAC7C,MAAM,YAAY;IAClB,mEAAmE;IACnE,MAAM,WAAW;CAClB"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The intent-first hand-off — how a prompt typed on the public site reaches the platform.
|
|
3
|
+
*
|
|
4
|
+
* A visitor types the idea for a project on the marketing site before they have an account. The
|
|
5
|
+
* site cannot write into the platform's browser storage (IndexedDB is per origin) and must not put
|
|
6
|
+
* the prompt in a URL, so the prompt takes a short detour through the platform's own cache: the
|
|
7
|
+
* site stashes it behind an unguessable reference, sends the browser to the platform with only that
|
|
8
|
+
* reference, and the platform picks the prompt up once — after which it lives in the visitor's own
|
|
9
|
+
* browser until they decide what to do with it.
|
|
10
|
+
*
|
|
11
|
+
* Everything here is serializable and runtime-free: the site, the manager API and the manager web
|
|
12
|
+
* read the same declarations, and none of them may reinvent a name the others parse.
|
|
13
|
+
*/
|
|
14
|
+
/** Every address of the hand-off. API routes are guest routes; the landing is a screen. */
|
|
15
|
+
export const intent = Object.freeze({
|
|
16
|
+
base: 'viable:manager-api:intent:base',
|
|
17
|
+
stash: 'viable:manager-api:intent:stash',
|
|
18
|
+
pickup: 'viable:manager-api:intent:pickup',
|
|
19
|
+
landing: 'viable:manager-web:intent:landing',
|
|
20
|
+
});
|
|
21
|
+
/** Where the guest API lives, and the screen the visitor's browser is sent to. */
|
|
22
|
+
export const INTENT_API_PATH = '/public/intent';
|
|
23
|
+
export const INTENT_LANDING_PATH = '/start';
|
|
24
|
+
/** The flow the two sides walk. */
|
|
25
|
+
export const INTENT_FLOW = 'viable:intent';
|
|
26
|
+
/**
|
|
27
|
+
* How long the platform keeps a stashed prompt waiting for pickup. Short on purpose: the pickup
|
|
28
|
+
* happens the moment the browser lands, so anything older was abandoned, and a prompt is personal
|
|
29
|
+
* data the platform has no business holding once nobody is coming for it.
|
|
30
|
+
*/
|
|
31
|
+
export const INTENT_TTL_SECONDS = 120;
|
|
32
|
+
/** The longest prompt the platform will create a project from (`PromptSchema` in viable). */
|
|
33
|
+
export const INTENT_PROMPT_MAX = 8192;
|
|
34
|
+
/**
|
|
35
|
+
* The reference's shape: `createIdOfLength(24)` — Base58, so no `0`, `O`, `I` or `l`. Anything else
|
|
36
|
+
* is refused before the cache is asked, which keeps a crafted reference from ever being a key.
|
|
37
|
+
*/
|
|
38
|
+
export const INTENT_REF_LENGTH = 24;
|
|
39
|
+
export const INTENT_REF_PATTERN = '^[1-9A-HJ-NP-Za-km-z]{24}$';
|
|
40
|
+
/** The flow payload key carrying the reference — short, because a payload is CSV-joined. */
|
|
41
|
+
export const INTENT_PAYLOAD_REF = 'ref';
|
|
42
|
+
/** How long the visitor's draft survives in their own browser waiting for a decision. */
|
|
43
|
+
export const INTENT_DRAFT_TTL_MS = 24 * 60 * 60 * 1000;
|
|
44
|
+
/** How long a suspended landing waits while the visitor signs in or registers. */
|
|
45
|
+
export const INTENT_SUSPEND_TTL_MS = 30 * 60 * 1000;
|
|
46
|
+
/** Steps of {@link intentFlow}, exported so a screen never spells one as a literal. */
|
|
47
|
+
export var IntentFlowStep;
|
|
48
|
+
(function (IntentFlowStep) {
|
|
49
|
+
/** The public site: the prompt is typed and stashed. */
|
|
50
|
+
IntentFlowStep["Compose"] = "compose";
|
|
51
|
+
/** The platform's landing screen: the stash is picked up. */
|
|
52
|
+
IntentFlowStep["Land"] = "land";
|
|
53
|
+
/** The platform's own sign-in dispatcher. */
|
|
54
|
+
IntentFlowStep["SignIn"] = "sign-in";
|
|
55
|
+
/** The platform's home screen, where the draft is offered back. */
|
|
56
|
+
IntentFlowStep["Review"] = "review";
|
|
57
|
+
})(IntentFlowStep || (IntentFlowStep = {}));
|
|
58
|
+
//# sourceMappingURL=consts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.js","sourceRoot":"","sources":["../../src/intent/consts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,2FAA2F;AAC3F,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAClC,IAAI,EAAE,gCAAgC;IACtC,KAAK,EAAE,iCAAiC;IACxC,MAAM,EAAE,kCAAkC;IAC1C,OAAO,EAAE,mCAAmC;CACpC,CAAC,CAAA;AAEX,kFAAkF;AAClF,MAAM,CAAC,MAAM,eAAe,GAAG,gBAAgB,CAAA;AAC/C,MAAM,CAAC,MAAM,mBAAmB,GAAG,QAAQ,CAAA;AAE3C,mCAAmC;AACnC,MAAM,CAAC,MAAM,WAAW,GAAG,eAAe,CAAA;AAE1C;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAA;AAErC,6FAA6F;AAC7F,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAA;AAErC;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAA;AACnC,MAAM,CAAC,MAAM,kBAAkB,GAAG,4BAA4B,CAAA;AAE9D,4FAA4F;AAC5F,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CAAA;AAEvC,yFAAyF;AACzF,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAEtD,kFAAkF;AAClF,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAEnD,uFAAuF;AACvF,MAAM,CAAN,IAAY,cASX;AATD,WAAY,cAAc;IACxB,wDAAwD;IACxD,qCAAmB,CAAA;IACnB,6DAA6D;IAC7D,+BAAa,CAAA;IACb,6CAA6C;IAC7C,oCAAkB,CAAA;IAClB,mEAAmE;IACnE,mCAAiB,CAAA;AACnB,CAAC,EATW,cAAc,KAAd,cAAc,QASzB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { IntentPickupBody, IntentPickupResult, IntentProtocolOptions, IntentStashBody, IntentStashResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Declare the intent-first hand-off: two GUEST API routes and the landing screen's address.
|
|
4
|
+
*
|
|
5
|
+
* No guard and no gate anywhere on the API — the caller is a visitor who has no account yet — and
|
|
6
|
+
* no `service` on any route: each consumer fills it in (the public site names the platform's
|
|
7
|
+
* services in its own configuration; the manager binds them to its own).
|
|
8
|
+
*
|
|
9
|
+
* TODO(cors): these routes ride the framework's global `origin: '*'` CORS policy (no credentials).
|
|
10
|
+
* If viable ever restricts allowed origins globally, this entrypoint must keep answering the public
|
|
11
|
+
* site's origins — owlmeans.com, owlmeans.pl and, in dev/stage, `http://localhost:4321`.
|
|
12
|
+
*
|
|
13
|
+
* The landing screen is `sticky`, like the OAuth consent screens: it is an ordinary in-app screen
|
|
14
|
+
* that a visitor arrives at directly from another origin.
|
|
15
|
+
*/
|
|
16
|
+
export declare const makeIntentProtocols: (opts?: IntentProtocolOptions) => {
|
|
17
|
+
base: import("@owlmeans/entrypoint").EntrypointProtocol<import("@owlmeans/entrypoint").OpenRequest, import("@owlmeans/entrypoint").OpenValue>;
|
|
18
|
+
stash: import("@owlmeans/entrypoint").EntrypointProtocol<{
|
|
19
|
+
body: IntentStashBody;
|
|
20
|
+
}, IntentStashResult>;
|
|
21
|
+
pickup: import("@owlmeans/entrypoint").EntrypointProtocol<{
|
|
22
|
+
body: IntentPickupBody;
|
|
23
|
+
}, IntentPickupResult>;
|
|
24
|
+
landing: import("@owlmeans/entrypoint").EntrypointProtocol<import("@owlmeans/entrypoint").OpenRequest, import("@owlmeans/entrypoint").OpenValue>;
|
|
25
|
+
};
|
|
26
|
+
export type IntentProtocols = ReturnType<typeof makeIntentProtocols>;
|
|
27
|
+
//# sourceMappingURL=entrypoints.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entrypoints.d.ts","sourceRoot":"","sources":["../../src/intent/entrypoints.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,gBAAgB,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,eAAe,EAAE,iBAAiB,EAChG,MAAM,YAAY,CAAA;AAEnB;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,UAAU,qBAAqB;;;;;;;;;CAkB9D,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAA"}
|