@owlmeans/planning 0.1.18-rc.11 → 0.1.18-rc.12

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 CHANGED
@@ -9,7 +9,7 @@ the executor with `@owlmeans/server-planning` and reads remotely with `@owlmeans
9
9
  ## Installation
10
10
 
11
11
  ```sh
12
- bun add @owlmeans/planning@^0.1.18-rc.11 ajv ajv-formats
12
+ bun add @owlmeans/planning@^0.1.18-rc.12 ajv ajv-formats
13
13
  ```
14
14
 
15
15
  ## Concepts
@@ -78,6 +78,20 @@ const page = await context.entrypoint(planningProtocols.card.list).call({ query
78
78
  const where = criteriaOf(decodeWorkcardQuery(req.query), { entityId })
79
79
  ```
80
80
 
81
+ Create a card and read it back through a facade — in process the one of `@owlmeans/server-planning`
82
+ (`ctx.service<PlanningHostService>(PLANNING_SERVICE).for({ entityId, profileId })`), remotely the one
83
+ of `@owlmeans/client-planning`:
84
+
85
+ ```ts
86
+ import { TransitionAction, WorkcardKind } from '@owlmeans/planning'
87
+
88
+ const drill = await planning.execute({
89
+ action: TransitionAction.Create,
90
+ card: { kind: WorkcardKind.Card, type: 'shed:tool', parent: shedId, title: 'Cordless drill' },
91
+ }, { wait: true }) // the options are the SECOND argument
92
+ const again = await planning.cards.get(drill.card!.id!)
93
+ ```
94
+
81
95
  Work through a model — the same code on either side of the wire:
82
96
 
83
97
  ```ts
@@ -141,6 +155,11 @@ const links = transitions.reduce(applyRelationship, [])
141
155
 
142
156
  ## Common pitfalls
143
157
 
158
+ - A create's draft goes under `card` (never `draft`), and `{ wait, timeout }` is the second argument
159
+ of `execute` — inside the execution an in-process facade ignores it.
160
+ - A type or flow declaration has no `name` or `key`: the display name is `label`, the key is `type`
161
+ (a type) or `id` (a flow); a status has `key`, a transition rule `name`. The declaration schemas
162
+ are closed — `definitions.define` refuses an extra key with `SchemaInvalid`.
144
163
  - Pass a query through `encode*Query` before an HTTP call — arrays and objects do not survive a
145
164
  query string as they are.
146
165
  - `status`, `intrinsic` and `flows` move only through `transit`; an `update` naming them is refused.
@@ -157,7 +176,7 @@ const links = transitions.reduce(applyRelationship, [])
157
176
  - `@owlmeans/server-planning` — executor, plugin registry, memory store, handlers
158
177
  - `@owlmeans/client-planning` — remote facade, state mirror, commit waiting
159
178
  - `@owlmeans/resource` — the criteria language
160
- - `@owlmeans/server-planning` — server execution and projection implementations
179
+ - `@owlmeans/planning-postgres` — the durable Postgres store
161
180
 
162
181
  <!-- owlmeans:agent-guidance:start -->
163
182
  ## Agent guidance
@@ -167,7 +186,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
167
186
  your project's skill store (`.agents/skills/`):
168
187
 
169
188
  ```sh
170
- npx @owlmeans/agent-skills@^0.1.18-rc.41
189
+ npx @owlmeans/agent-skills@^0.1.18-rc.42
171
190
  ```
172
191
 
173
192
  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/planning",
4
- "version": "0.1.18-rc.11",
5
- "generatedAt": "2026-09-28T02:06:37.879Z",
4
+ "version": "0.1.18-rc.12",
5
+ "generatedAt": "2026-09-29T08:01:58.127Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -8,7 +8,7 @@ user-invocable: false
8
8
  # @owlmeans/planning
9
9
 
10
10
  **Layer:** Cross-cutting domain
11
- **Install:** `"@owlmeans/planning": "^0.1.18-rc.11"` in `dependencies` (`ajv` and `ajv-formats` are peers)
11
+ **Install:** `"@owlmeans/planning": "^0.1.18-rc.12"` in `dependencies` (`ajv` and `ajv-formats` are peers)
12
12
 
13
13
  The contracts of project planning: record shapes, schemas, refusals, the protocol tree, the pure
14
14
  fold and the models. No database, no fastify, no React. The executor, the plugin registry, the
@@ -22,6 +22,42 @@ transitions in `seq` order. There is one write path (`facade.execute(exec)`), on
22
22
  (`applyTransition`) and one query translation (`criteriaOf`), shared by every store and both sides
23
23
  of the wire, so one log always means one card.
24
24
 
25
+ ## The write call
26
+
27
+ `facade.execute(execution, options?)` — the same signature on the server facade
28
+ (`@owlmeans/server-planning`, reached as `ctx.service<PlanningHostService>(PLANNING_SERVICE).for({
29
+ entityId, profileId })`) and the remote one (`@owlmeans/client-planning`).
30
+
31
+ - The **execution** has exactly these keys — `TransitionExecutionSchema` is closed, but only the
32
+ wire validates against it; in process an unknown key is silently ignored: `card` — the `WorkcardDraft` of a
33
+ create (`kind`, `type`, `title` required; `parent`/`parents`, `description`, `code`, `labels`,
34
+ `order`, `fields`, `status`, and a specification's `category`/`format`/`body`), the card id
35
+ otherwise — and `action` (`TransitionAction`), then per action `transition`, `flow`, `changes`,
36
+ `unset`, `link` / `links`, and `cause`, `key`, `expectSeq`.
37
+ - The **options** are `{ wait?, timeout? }`, always the second argument. Only the wire body
38
+ (`ExecuteRequest`) carries them beside the execution.
39
+
40
+ ```ts
41
+ import { TransitionAction, WorkcardKind } from '@owlmeans/planning'
42
+
43
+ const drill = await planning.execute({
44
+ action: TransitionAction.Create,
45
+ card: { kind: WorkcardKind.Card, type: 'shed:tool', parent: shedId, title: 'Cordless drill', fields: { brand: 'Acme' } },
46
+ }, { wait: true }) // drill.card — the committed record
47
+ await planning.cards.get(drill.card!.id!)
48
+ await planning.execute({ action: TransitionAction.Transit, card: drill.card!.id!, transition: 'lend' }, { wait: true })
49
+ ```
50
+
51
+ | Wrong | What happens | Right |
52
+ |---|---|---|
53
+ | `{ action, draft: { … } }` | `planning:malformed:create-without-draft` | the draft goes under `card` |
54
+ | `{ …, wait: true }` in the execution | ignored in process: the receipt returns before the commit, with no `card` | `execute(exec, { wait: true })` |
55
+ | `action: 'create'` | a type error — `TransitionAction` is an enum | `TransitionAction.Create` |
56
+
57
+ Each is a compile error against the typed `TransitionExecution`; it reaches run time only through a
58
+ value typed `any`. `server-planning` carries the full example (facade, read back, data-defined
59
+ type and flow).
60
+
25
61
  ## Key exports
26
62
 
27
63
  | Export | What it is |
@@ -89,7 +125,21 @@ of the wire, so one log always means one card.
89
125
  ## Declaring a type
90
126
 
91
127
  A `WorkcardTypeSchema` / `ProjectTypeSchema` is plain data registered through a plugin's `schemas`
92
- or `makeSchemaRegistry({ types, flows })`:
128
+ or `makeSchemaRegistry({ types, flows })`. **Every declaration schema is closed** — these are ALL
129
+ the keys:
130
+
131
+ | Declaration | Required | Optional |
132
+ |---|---|---|
133
+ | card / specification type | `type` (its key), `kind`, `version`, `fields`, `flows` (at least one), `specifications` | `intrinsic`, `relationships`, `labels`, `code`, `label`, `overridable` |
134
+ | project type | the same, plus `cardTypes` | `projectTypes`, `scopedCardTypes` |
135
+ | flow | `id` (its key), `version`, `statuses` (at least one), `transitions` | `label`, `overridable` |
136
+ | status | `key`, `intrinsic` | `initial`, `terminal`, `label`, `tone` |
137
+ | transition rule | `name`, `from` (status keys or `'*'`), `to` | `label`, `explicit` |
138
+
139
+ The display name is `label` everywhere; a type or a flow has no `name`, `key` or `description`
140
+ (`key` belongs to a status, `name` to a rule). As data, `definitions` refuses an extra key with
141
+ `SchemaInvalid`; in code the registry does not validate a declaration, so only TypeScript's
142
+ excess-property check catches it — keep the literal typed.
93
143
 
94
144
  - `fields` — the AJV schema of `fields`; the registry compiles and caches it (`validator(type)`).
95
145
  - `specifications` — the slots this type's cards carry as children. A slot may name its
@@ -133,7 +183,20 @@ optional `PlanningStore.schemas` port — layered **code → entity → project*
133
183
  - `PlanningFacade.definitions` (present only where the store has the port): `bundle(project?)`,
134
184
  `registry(project?)`, `records`, `putType`/`putFlow` (CAS on the declaration's version),
135
185
  `define` (each at its layer's next version, flows first), `seed` (only the keys the layer lacks),
136
- `retire(kind, key, { project? })`.
186
+ `retire(kind, key, { project? })`. The declaration still carries its own `version` (any number
187
+ ≥ 1 for `define`/`seed`, which assign the layer's next one; the exact next one for `put*`), and
188
+ a project layer is `{ project: <project card id> }` in the second argument:
189
+
190
+ ```ts
191
+ await planning.definitions!.define({
192
+ flows: [{ id: 'shed:repair', version: 1, label: 'Repair',
193
+ statuses: [{ key: 'reported', intrinsic: IntrinsicStatus.Planned, initial: true },
194
+ { key: 'fixed', intrinsic: IntrinsicStatus.Closed, terminal: true }],
195
+ transitions: [{ name: 'fix', from: ['reported'], to: 'fixed', explicit: true }] }],
196
+ types: [{ type: 'shed:repair', kind: WorkcardKind.Card, version: 1, label: 'Repair ticket',
197
+ fields: { type: 'object' }, flows: ['shed:repair'], specifications: [] }],
198
+ }, { project: shedId }) // admitted under the shed when its type says `scopedCardTypes: true` (or lists it in `cardTypes`)
199
+ ```
137
200
 
138
201
  ## The fold
139
202
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/planning",
3
- "version": "0.1.18-rc.11",
3
+ "version": "0.1.18-rc.12",
4
4
  "license": "MIT",
5
5
  "description": "Runtime-free project-planning contracts — the workcard super type, projects, specifications, typed relationships, status flows with three intrinsic states, the transition event and its pure fold, the schema registry, the models and the protocol tree.",
6
6
  "type": "module",
@@ -29,7 +29,7 @@
29
29
  "@owlmeans/entrypoint": "^0.1.18-rc.37",
30
30
  "@owlmeans/error": "^0.1.18-rc.36",
31
31
  "@owlmeans/i18n": "^0.1.18-rc.37",
32
- "@owlmeans/resource": "^0.1.18-rc.36",
32
+ "@owlmeans/resource": "^0.1.18-rc.37",
33
33
  "@owlmeans/route": "^0.1.18-rc.33"
34
34
  },
35
35
  "peerDependencies": {