@owlmeans/planning 0.1.18-rc.13 → 0.1.18-rc.15

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.13 ajv ajv-formats
12
+ bun add @owlmeans/planning@^0.1.18-rc.15 ajv ajv-formats
13
13
  ```
14
14
 
15
15
  ## Concepts
@@ -188,7 +188,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
188
188
  your project's skill store (`.agents/skills/`):
189
189
 
190
190
  ```sh
191
- npx @owlmeans/agent-skills@^0.1.18-rc.44
191
+ npx @owlmeans/agent-skills@^0.1.18-rc.46
192
192
  ```
193
193
 
194
194
  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.13",
5
- "generatedAt": "2026-09-30T09:41:02.827Z",
4
+ "version": "0.1.18-rc.15",
5
+ "generatedAt": "2026-10-03T11:19:50.783Z",
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.13"` in `dependencies` (`ajv` and `ajv-formats` are peers)
11
+ **Install:** `"@owlmeans/planning": "^0.1.18-rc.15"` 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
@@ -37,26 +37,8 @@ entityId, profileId })`) and the remote one (`@owlmeans/client-planning`).
37
37
  - The **options** are `{ wait?, timeout? }`, always the second argument. Only the wire body
38
38
  (`ExecuteRequest`) carries them beside the execution.
39
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).
40
+ The worked example (facade, create, read back, transit, a data-defined type and flow) and the wrong
41
+ forms generated code keeps writing are `server-planning` → Creating and reading a card.
60
42
 
61
43
  ## Key exports
62
44
 
@@ -91,7 +73,9 @@ type and flow).
91
73
  `status`, `labels`, `order`, `parent` are generic and indexable; everything a type adds lives in
92
74
  `fields` and is validated by the type's `fields` JSON schema. Generic code reads only the top.
93
75
  A `fields` key never holds `.` or `$` at any depth (`invalidFieldKeys`).
94
- - **`entityId` is the organization's stable id**, never a slug. Every read is scoped by it.
76
+ - **`entityId` is the organization's stable record id** — never the wire `entitySlug`, never a body
77
+ value. Every read is scoped by it; where a request's comes from is `server-planning` → Scope and
78
+ security.
95
79
  - **Membership is `parent` + `parents`, never a relationship.** `parents` always contains `parent`
96
80
  (first), so many-to-many membership needs no junction row. `within` queries `parents`.
97
81
  - **Specification is a workcard** (`kind: specification`) with `category`, `format`, `body`, `ref`,
@@ -162,7 +146,7 @@ excess-property check catches it — keep the literal typed.
162
146
  Card types and status flows may also be DATA — `ScopedSchemaRecord`s a store keeps behind the
163
147
  optional `PlanningStore.schemas` port — layered **code → entity → project**:
164
148
 
165
- - `code` is the plugin registry (unchanged, the default), `entity` an organization-wide record
149
+ - `code` is the plugin registry (the default), `entity` an organization-wide record
166
150
  (`project` absent), `project` a record of one project card. A project record overrides an
167
151
  organization one of the same key.
168
152
  - **Only card types and flows are data.** A code key is sealed unless its declaration says
@@ -189,18 +173,8 @@ optional `PlanningStore.schemas` port — layered **code → entity → project*
189
173
  `define` (each at its layer's next version, flows first), `seed` (only the keys the layer lacks),
190
174
  `retire(kind, key, { project? })`. The declaration still carries its own `version` (any number
191
175
  ≥ 1 for `define`/`seed`, which assign the layer's next one; the exact next one for `put*`), and
192
- a project layer is `{ project: <project card id> }` in the second argument:
193
-
194
- ```ts
195
- await planning.definitions!.define({
196
- flows: [{ id: 'shed:repair', version: 1, label: 'Repair',
197
- statuses: [{ key: 'reported', intrinsic: IntrinsicStatus.Planned, initial: true },
198
- { key: 'fixed', intrinsic: IntrinsicStatus.Closed, terminal: true }],
199
- transitions: [{ name: 'fix', from: ['reported'], to: 'fixed', explicit: true }] }],
200
- types: [{ type: 'shed:repair', kind: WorkcardKind.Card, version: 1, label: 'Repair ticket',
201
- fields: { type: 'object' }, flows: ['shed:repair'], specifications: [] }],
202
- }, { project: shedId }) // admitted under the shed when its type says `scopedCardTypes: true` (or lists it in `cardTypes`)
203
- ```
176
+ a project layer is `{ project: <project card id> }` in the second argument (a `define` call:
177
+ `server-planning` → Creating and reading a card).
204
178
 
205
179
  ## The fold
206
180
 
@@ -215,9 +189,9 @@ await planning.definitions!.define({
215
189
  never written or cleared;
216
190
  - `link`/`unlink` move only `seq`/`head`/`updatedAt`; `delete` answers `null`;
217
191
  - every result carries `seq = transition.seq`, `head = max(head, seq)`, `updatedAt = transition.at`;
218
- - the log is replayed AS WRITTEN: a row the executor would refuse today (an update naming
219
- `createdBy`, appended before that refusal existed) still folds. Guards live at admission
220
- (`assertMutable`, the executor), never in the fold, so a stored log never stops projecting.
192
+ - the log is replayed AS WRITTEN: a stored row admission would refuse (an update naming
193
+ `createdBy`) still folds. Guards live at admission (`assertMutable`, the executor), never in the
194
+ fold, so a stored log never stops projecting.
221
195
 
222
196
  `applyRelationship(links, transition)` folds the edges: a create's `links`, `link`, `unlink`, and a
223
197
  `delete` dropping every edge touching the card. An existing edge is kept, so re-folding adds nothing.
@@ -234,7 +208,6 @@ await planning.definitions!.define({
234
208
  - transit — `flows[flow] = rule.to`, `status` on the primary flow, `intrinsic` when it moves,
235
209
  `closedAt` set on entering closed and cleared on leaving; throws `IllegalTransition`;
236
210
  - link/unlink/delete — nothing.
237
- - `createdBy` only ever comes from a create's draft: `changes` and `unset` never carry it.
238
211
 
239
212
  `assertMutable(exec, type)` refuses (`planning:immutable:<field>`) identity keys (`createdAt`
240
213
  among them), `createdBy` in `changes` or `unset` on any action (a create included),
@@ -251,8 +224,8 @@ description `$ilike` (wildcards escaped) and code `$startsWith`, `updatedSince`
251
224
  $gte }`. `entityId` always comes from the scope; `undefined` is omitted. Paging and sort are
252
225
  `listOptionsOf` (`size: 0` = no limit). `summaryOf(cards, parents)` counts DIRECT children by
253
226
  intrinsic state and gives no key to a parent with none. A scope naming `projects` is narrowed by
254
- the SERVER facade on top of this translation (`server-planning`); `TransitionWhere.project` and
255
- `RelationshipWhere.project` take one id or a list.
227
+ the SERVER facade on top of this translation (`server-planning` → The access resolver);
228
+ `TransitionWhere.project` and `RelationshipWhere.project` take one id or a list.
256
229
 
257
230
  **A query crosses HTTP in its wire form.** The OwlMeans transport cannot carry arrays or nested
258
231
  objects in a query string (the client writes `key[]=`, the server reads that key literally), so
@@ -264,7 +237,7 @@ A client calls `encodeWorkcardQuery(query)` before `call({ query })`; a handler
264
237
 
265
238
  ## The protocol tree and mounting
266
239
 
267
- `makePlanningProtocols({ base: { alias, path?, parent?, service? }, guards, gate?, socketBase? })`:
240
+ `makePlanningProtocols({ base: { alias, path?, parent?, service? }, guards, gate?, socketBase?, definitions? })`:
268
241
 
269
242
  | Leaf | Route | Request → reply |
270
243
  |---|---|---|
@@ -349,7 +322,7 @@ throw a `ResilientError` that declares nothing.
349
322
 
350
323
  ## i18n
351
324
 
352
- Importing the package registers, in all seven languages, `lib:planning.*` labels (`kind.*`,
325
+ Importing the package registers, in eight languages (en, pl, ru, be, uk, es, de, fr), `lib:planning.*` labels (`kind.*`,
353
326
  `intrinsic.*`, `action.*`, `commit.*`, `format.*`) and one text per refusal type under the shared
354
327
  `errors` resource (`errors.<TypeName>`), where a panel's error lookup finds it.
355
328
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/planning",
3
- "version": "0.1.18-rc.13",
3
+ "version": "0.1.18-rc.15",
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",
@@ -23,10 +23,10 @@
23
23
  }
24
24
  },
25
25
  "dependencies": {
26
- "@owlmeans/auth": "^0.1.18-rc.36",
26
+ "@owlmeans/auth": "^0.1.18-rc.38",
27
27
  "@owlmeans/basic-ids": "^0.1.18-rc.34",
28
28
  "@owlmeans/context": "^0.1.18-rc.32",
29
- "@owlmeans/entrypoint": "^0.1.18-rc.37",
29
+ "@owlmeans/entrypoint": "^0.1.18-rc.39",
30
30
  "@owlmeans/error": "^0.1.18-rc.36",
31
31
  "@owlmeans/i18n": "^0.1.18-rc.37",
32
32
  "@owlmeans/resource": "^0.1.18-rc.37",