@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 +22 -3
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/planning/SKILL.md +66 -3
- package/package.json +2 -2
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.
|
|
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/
|
|
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.
|
|
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
|
package/agent-meta/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"package": "@owlmeans/planning",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-09-
|
|
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
|
+
**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.
|
|
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.
|
|
32
|
+
"@owlmeans/resource": "^0.1.18-rc.37",
|
|
33
33
|
"@owlmeans/route": "^0.1.18-rc.33"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|