@openengio/cli 0.27.1 → 0.36.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openengio/cli",
3
- "version": "0.27.1",
3
+ "version": "0.36.0",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "engines": {
@@ -79,7 +79,7 @@ differences:
79
79
 
80
80
  | json-render teaches | here | why |
81
81
  |---|---|---|
82
- | props naming a project, ref, organisation, namespace, object, type version, URL or path | refused, always | a view never chooses its own scope: the host derives the page's project and ref from its address, so a view cannot read or link outside it |
82
+ | props naming a project, branch or baseline, organisation, namespace, object, type version, URL or path | refused, always | a view never chooses its own scope: the host derives the page's project and branch or baseline from its address, so a view cannot read or link outside it |
83
83
  | `className`, `style`, `html`, `color` | refused, always | a visual choice is a design-token name, such as a Badge's `tone`, so every view keeps the platform's look and carries no raw HTML |
84
84
  | defining your own catalog and components | not possible | a view is display data, not a capability: the web renders only the catalogue's components |
85
85
  | fetching data from json-render | not possible | data enters only through a `Query` element, which the host scopes |
@@ -88,6 +88,14 @@ Check: the model's convention is written down, and every edge follows it.
88
88
  Check: each type's default tree is the one the person expects; a type with views has its main tree as
89
89
  the first view.
90
90
 
91
+ The `relationships` array is the ordered list of natural parent edge types: the first declared edge
92
+ that supplies a parent places an object in the default tree. Climbing farther uses each ancestor
93
+ type's own declaration. A `structureDeclaration.views` entry is a navigation tree; declaring views
94
+ replaces the relationship picker with those views, so include the usual tree first. A two-step view
95
+ can pass through a shared intermediate object, omit it from the tree, and show its properties as
96
+ decoration. A traceability edge with a `parentEnd` can give one object several parents; the object
97
+ then appears once at each placement, and its ancestry depends on the selected tree.
98
+
91
99
  ## 5. The rail and the page
92
100
 
93
101
  - The organisation holds one list of rail groups, in the order the rail draws them; it is sent whole
@@ -96,7 +104,13 @@ the first view.
96
104
  `rail` is listed under "More types": leave it off for a type that is the detail of another, not a
97
105
  destination.
98
106
  - `presentationBindings.title` names the property that titles the object in tables, trees and the graph view.
99
- `presentationBindings.typeIcon` is a Material Symbols glyph name.
107
+ `presentationBindings.typeIcon` is a Material Symbols glyph name. A new object type needs one, and so does
108
+ every later version of a type whose current version has one; publication refuses it otherwise
109
+ (`missing-type-icon`). Before choosing, read the organisation's existing type icons (`openeng types export`)
110
+ and pick a glyph that is relevant to the type and distinct from theirs.
111
+ `presentationBindings.propertyLabels` maps a property key to a display label of at most 80 characters,
112
+ and `presentationBindings.propertyOrder` lists property keys in display order, each once. Both name
113
+ only properties the version defines.
100
114
  - An **object view** (`presentationBindings.views.object`, root `ObjectBody`) lays out the object's
101
115
  drawer; an **App view** (`.app`, root `AppBody`) lays out the type's page. Only components the view
102
116
  catalogue admits may appear, each with the props it takes.
@@ -135,6 +149,12 @@ for a lifecycle state. A wrong edge is replaced by a new edge type key and a rec
135
149
  - An update is a compare-and-set per property: `{"<property>": {"from": {"value": <what it holds now>}, "to":
136
150
  {"value": <the new value>}}}`; `{"absent": true}` stands for no value on either side. A `from` that no
137
151
  longer matches is refused, so read the object first.
152
+ - A `datetime` property takes an RFC 3339 date-time with an explicit offset and zero to three fraction digits
153
+ (`2026-10-19T22:30:00+01:00`); a value with no offset, an impossible date or time, or four or more
154
+ fraction digits is refused, never truncated. It is stored as `YYYY-MM-DDTHH:MM:SS.sssZ`, the same
155
+ instant in UTC, and a `from` naming the stored instant in another offset still matches. A calendar
156
+ date is its midnight in UTC; there is no date kind. A type that declares `datetime` is schema
157
+ language version `2` or later, and a type's version never decreases.
138
158
 
139
159
  ## Property kinds
140
160
 
@@ -166,8 +186,12 @@ An enum's `members` is a list of strings or finite numbers. A published member c
166
186
 
167
187
  ### number
168
188
 
189
+ A number or integer may declare a unit under schema language version `4`. The value is still
190
+ a number, displayed with that unit. Publication refuses unknown symbols (`unknown-unit`), and
191
+ a later version may add a unit but cannot change or remove it (`changed-unit`).
192
+
169
193
  ```json
170
- {"kind": "number"}
194
+ {"kind": "number", "unit": "kg"}
171
195
  ```
172
196
 
173
197
  ### integer
@@ -194,8 +218,80 @@ An enum's `members` is a list of strings or finite numbers. A published member c
194
218
  {"kind": "object", "properties": {"name": {"kind": "string"}}, "required": ["name"]}
195
219
  ```
196
220
 
221
+ ### datetime
222
+
223
+ An instant, under schema language version `2`.
224
+
225
+ ```json
226
+ {"kind": "datetime"}
227
+ ```
228
+
229
+ ### attachment
230
+
231
+ A file descriptor on a top-level object property, under schema language version `3`. The kind is
232
+ refused inside object or array properties and in edge and verb schemas. `accept` lists admitted
233
+ classes: adding a class is compatible; removing one or changing the property's kind is refused.
234
+ The accepted classes are `image` (`.png`, `.jpg`, `.jpeg`, `.webp`, `.gif`), `pdf` (`.pdf`),
235
+ `step` (`.step`, `.stp`), `mesh` (`.stl`) and `text` (`.txt`, `.md`, `.csv`, `.json`, `.yaml`,
236
+ `.yml`, `.toml`, `.ini`, `.log`, `.xml`, `.ts`, `.tsx`, `.js`, `.py`, `.c`, `.h`, `.cpp`, `.hpp`,
237
+ `.rs`, `.go`, `.java`, `.m`, `.sql`, `.sh`). The maximum file body is 26,214,400 bytes (25 MiB).
238
+ Use `openeng attachment add <object> <property> <file> --project <id> --ref <ref>` to attach a
239
+ file, `openeng attachment list <object> --project <id> --ref <ref>` to list attachment properties,
240
+ and `openeng attachment get <object> <property> [--out <path>] --project <id> --ref <ref>` to save
241
+ one property's bytes.
242
+
243
+ ```json
244
+ {
245
+ "typeCategory": "object",
246
+ "typeKey": "drawing_record",
247
+ "version": 1,
248
+ "displayName": "Drawing record",
249
+ "description": null,
250
+ "schemaLanguageVersion": "3",
251
+ "propertyDefinitions": {
252
+ "drawing": {"kind": "attachment", "accept": ["image", "pdf", "step", "mesh", "text"]}
253
+ },
254
+ "requiredPropertyKeys": []
255
+ }
256
+ ```
257
+
258
+ ### bound
259
+
260
+ A quantitative constraint on a top-level object property, or an entry in a top-level array of
261
+ bounds, under schema language version `4`. A value such as
262
+ `{"over":"each","quantity":"mass","comparison":"<=","value":100,"unit":"kg"}` compares
263
+ each linked object's mass against 100 kg. `sum`, `min`, `max` and `count` aggregate the linked
264
+ values. A limit may instead be `{ "property": "allocation" }`, read from this object's own
265
+ numeric property. `within` requires a non-negative `tolerance`; other comparisons take none.
266
+ Compatible units are converted for comparison; incompatible units answer `unit-mismatch`.
267
+ Bounds answer independently of review: clearing a suspect link does not make an `out` bound `in`.
268
+
269
+ ```json
270
+ {"kind": "bound"}
271
+ ```
272
+
197
273
  ## 9. Examples
198
274
 
275
+ These are small type documents to adapt and validate in a change set before accepting it.
276
+
277
+ ### Example: object type
278
+
279
+ ```json
280
+ {"typeCategory":"object","typeKey":"task","version":1,"displayName":"Task","description":null,"schemaLanguageVersion":"1","propertyDefinitions":{"name":{"kind":"string"}},"requiredPropertyKeys":["name"],"presentationBindings":{"title":"name","typeIcon":"task"}}
281
+ ```
282
+
283
+ ### Example: edge type
284
+
285
+ ```json
286
+ {"typeCategory":"edge","typeKey":"depends-on","version":1,"displayName":"Depends on","sourceObjectType":"task","targetObjectType":"task","kind":"traceability","subjectEnd":"source","parentEnd":"source","sourceLabel":"depends on","targetLabel":"is depended on by","schemaLanguageVersion":"1","propertyDefinitions":{},"requiredPropertyKeys":[],"readRule":"both-endpoints","writeRule":"both-endpoints"}
287
+ ```
288
+
289
+ ### Example: template verb with its result contract
290
+
291
+ ```json
292
+ {"typeCategory":"verb","typeKey":"create-task","version":1,"displayName":"Create task","description":null,"allowedSubjectTypes":"none","inputSchema":{"kind":"object","properties":{"name":{"kind":"string"}},"required":["name"]},"resultSchema":{"kind":"null"},"schemaLanguageVersion":"1","template":{"operations":[{"kind":"create-object","typeKey":"task","properties":{"name":{"slot":"input","key":"name"}}}]}}
293
+ ```
294
+
199
295
  A minimal object type and a structural edge, every key at version 1:
200
296
 
201
297
  ```json
@@ -44,7 +44,7 @@ out of every story.
44
44
  - [ ] C2. One data model, two ways of working: a CRUD app or a branch-first engineering workflow
45
45
  Checklist: Switch one project between direct edits on `main` and branch-only edits.
46
46
  Features shown: Objects; Branches; Branch diff and changed-object accents; Proposals; Roles and
47
- membership; Ref rules.
47
+ membership; Branch rules.
48
48
 
49
49
  - [ ] C3. Follow one question across every tool
50
50
  Checklist: Answer one question that crosses requirements, parts and tests.
@@ -57,13 +57,15 @@ out of every story.
57
57
  subscribers; Delete preview; Branch history and the audit trail.
58
58
 
59
59
  - [ ] C5. An agent does the work, a person makes the call
60
- Checklist: Have the in-product agent make a change that a person approves and merges.
60
+ Checklist: Explain that the organisation's agent model is chosen in the web app under Admin,
61
+ Agent model; open or link that page. Have the in-product agent make a change that a person
62
+ approves and merges.
61
63
  Features shown: Branches; Branch diff and changed-object accents; Proposals; Branch history and
62
64
  the audit trail; Object agent; Agent model per organisation; Agent ceiling.
63
65
 
64
66
  - [ ] C6. Freeze what shipped, keep building what comes next
65
67
  Checklist: Freeze a released part and keep a read-only release baseline.
66
- Features shown: Types and the ontology; Objects; Relationships; Organisation refs; Instance
68
+ Features shown: Types and the ontology; Objects; Relationships; Organisation branches and baselines; Instance
67
69
  locks; Type rules.
68
70
 
69
71
  - [ ] C7. Your CAD system stays the source of truth
@@ -99,11 +101,14 @@ cares about; do not explain a primitive in isolation.
99
101
  `objects-sdk mutateBatch`, then show the rail, table and object card with `link type`.
100
102
  - C2: edit on main, add a merge-only rule, show the same edit refused `protected`, then branch,
101
103
  edit, compare and submit a proposal. The person merges; remove the rule and show direct edits.
102
- - C3: narrow with `objects-sdk readStructure`, show `link explore`, and answer a question
104
+ - C3: narrow with `objects-sdk readStructure`, show `link explore --object <id>` for the selected
105
+ object, and answer a question
103
106
  across requirements, parts and tests with `queryObjects`, `findPaths` and `aggregateObjects`.
104
107
  - C4: open a record's history, comment and subscribe; use `objects-sdk previewDelete` before
105
108
  any deletion, and read branch history and `admin-sdk listAudit`.
106
- - C5: show the organisation's agent model and project's `ceiling show`. The person uses
109
+ - C5: explain that the organisation's agent model is chosen in the web app under **Admin**, **Agent model**.
110
+ Run `openeng link organisation-page agent-model` and open or share the returned link. The CLI
111
+ has no read of the selected model; do not claim to have read it. Show the project's `ceiling show`. The person uses
107
112
  "Open agent", approves its plan, inspects the branch diff, submits and merges. Read the audit
108
113
  naming the person and run; show the agent refused on protected main.
109
114
  - C6: use `locks set --lock frozen` on a released part, show an edit refused, create its successor
@@ -118,7 +123,7 @@ cares about; do not explain a primitive in isolation.
118
123
 
119
124
  At each step, say what comes next and why, make the smallest useful change (one atomic batch
120
125
  for related writes), validate before publishing, and read the result in the intended organisation,
121
- project and ref. Give a link from `openeng link`, say what they should see, and leave time to see it.
126
+ project and branch or baseline. Give a link from `openeng link`, say what they should see, and leave time to see it.
122
127
  Invite an action that matters, then check its result with a read. Keep accepted, validated,
123
128
  published and seen in the app distinct. Drive through the CLI; the person operates the app.
124
129
 
@@ -2,7 +2,7 @@
2
2
  name: openeng
3
3
  description: >-
4
4
  Use when you need to work with an OpenEngineering platform through its command line, `openeng`.
5
- Signing in, listing projects and types, editing object types, writing objects on an agreed ref
5
+ Signing in, listing projects and types, editing object types, writing objects on an agreed branch
6
6
  and submitting branches for review.
7
7
  ---
8
8
 
@@ -14,11 +14,27 @@ description: >-
14
14
  npm install -g @openengio/cli
15
15
  ```
16
16
 
17
+ Set `OPENENG_NO_UPDATE_CHECK=1` to disable the daily npm update check and standard-error notice; `CI`, help and `--version` also skip it.
18
+
17
19
  This skill gives the commands and their order. It gives no input shapes, because the commands print
18
20
  their own. Before you send a generated command (`objects-sdk`, `branches-sdk` and the other
19
21
  `<module> <method>` commands), run `openeng help <module> <method>`. It prints the fields, the kinds a
20
22
  field may take, the selector keys and one example input, and needs no sign-in.
21
23
 
24
+ ## Explain each step
25
+
26
+ When guiding a person, say what you intend to learn or change, give the command, then report what it
27
+ answered and what follows. When the step has a GUI page, include the address from `openeng link` at
28
+ that step; do not construct a page address yourself. For example:
29
+
30
+ 1. Intent: identify the project and its namespace. Run `openeng projects list --json`; report the
31
+ project id and namespace it returned.
32
+ 2. Intent: show the project in the web app. Run `openeng link project --project <id> --ref main`
33
+ and give the returned address with what the page should show.
34
+ 3. Intent: inspect one object in the chosen branch. Run the relevant read command and report its
35
+ result; when the person needs its page, run `openeng link object <object-id> --project <id>
36
+ --ref <ref>` and give that returned address.
37
+
22
38
  ## Read the topic for your task
23
39
 
24
40
  - A person new to OpenEngineering who wants a tour, or has just signed in with no task of their own: `openeng skill demo`.
@@ -29,6 +45,53 @@ field may take, the selector keys and one example input, and needs no sign-in.
29
45
  - A domain model: `openeng skill playbook engineering-requirements`,
30
46
  `openeng skill playbook product-lifecycle`, or `openeng skill playbook project-management`.
31
47
 
48
+ ## Attachments
49
+
50
+ For a top-level object property declared with kind `attachment`, use
51
+ `openeng attachment add <object> <property> <file> --project <id> --ref <ref>` to stage a file and
52
+ save its descriptor, `openeng attachment list <object> --project <id> --ref <ref>` to read its
53
+ attachment properties, and `openeng attachment get <object> <property> [--out <path>]` with the
54
+ project and ref flags to download it. The `get` command uses the descriptor's file name when `--out`
55
+ is omitted. The accepted classes and file-size limit are in `openeng skill conventions`.
56
+
57
+ ## Link review and impact
58
+
59
+ Read `openeng links status <object> --project <id> --ref <ref>` before reviewing a tracked
60
+ link. Review states are `cleared` (reviewed against the current upstream), `suspect` (significant
61
+ upstream content changed), `unreviewed` (never cleared), `not-visible` (the upstream cannot be
62
+ read) and `too-many-links` (the chain exceeds its bound). Bounds have their own states: `in`,
63
+ `out`, `none`, `no-value`, `unit-mismatch` and `not-visible`; clearing does not change them.
64
+ Aggregates also show coverage and hidden or missing counts. Numeric output shows its unit.
65
+
66
+ After reviewing the upstream, run `openeng links clear <link> --version <upstreamVersion>
67
+ --project <id> --ref <ref>`. Take the opaque version from the status answer. For an atomic batch,
68
+ list up to 100 link ids and repeat `--version` once per link in the same order. On
69
+ `upstream-changed`, read status and review before sending its new version; do not replace the
70
+ precondition blindly. `upstream-not-readable` requires upstream read access. There is no
71
+ organisation clearing setting: the edge's write rule decides who may clear. User, run-apply,
72
+ client and service tokens are admitted; run-explore and run-types are refused at admission.
73
+ The object agent has no clearing tool; clear through this CLI or the SDK. Recover an unknown
74
+ outcome by correlation before retrying.
75
+
76
+ Use `openeng branches impact <ref> --base <base> --project <id>` to review changes against
77
+ the merge base: review, bounds and aggregate changes, downstream reach to depth three and
78
+ hidden counts. Added and removed links are marked. `head-moved` requires reading again;
79
+ `over-bound` refuses the entire read. Add `--json` for each complete answer.
80
+
81
+ ## Hosted apps
82
+
83
+ A hosted app is a React bundle that runs inside a project, in a sandbox, with the viewer's authority.
84
+ Export a component that takes `{ client }` and start it by calling the runtime's
85
+ `globalThis.__oe2HostedApp.mount(App)` as the bundle's last statement (the `@openengio/hosted-app`
86
+ package that wraps this call is not published yet). Publish the built bundle with
87
+ `openeng hosted-app publish <bundle> --project <id> --key <app key>`; it creates the app when the
88
+ project has none under that key, and prints the version and its SHA-256. If the app holds the
89
+ one-wall permission, the output also carries a warning: read it to the person and do not hide it.
90
+ `openeng hosted-app list --project <id>` lists the apps, `openeng hosted-app versions <app key>
91
+ --project <id>` lists an app's versions, and `openeng hosted-app revoke <app key | app id | version id>
92
+ --project <id>` revokes a version (an id starting `hav_`) or the whole app by its key or `app_` id. Revoke only when the
93
+ person asks. Hosted apps run only in Google Chrome.
94
+
32
95
  ## Rules that hold for every command
33
96
 
34
97
  - Add `--json` when you read the answer yourself. It prints one JSON value on standard output.
@@ -91,9 +154,9 @@ For a generic open-cycle gas turbine demonstration project, run `openeng demo se
91
154
  `{"organisation": {"id", "name"}, "project"?, "ref"?}`. An object value normally gains a `scope` key.
92
155
  A value that is an array or null, such as the list from `openeng projects list`, comes wrapped as
93
156
  `{"scope": {...}, "value": <the original value>}`. Rules command successes always use this wrapper
94
- to preserve the rule's own `scope` field. Organisation-ref, lock, ceiling and schema-update
157
+ to preserve the rule's own `scope` field. Organisation branch or baseline, lock, ceiling and schema-update
95
158
  successes also always use `{ scope, value }`. A command with no scope carries no `scope` field.
96
- - A `not-found` in an organisation is often a project or a ref that belongs to another one. The
159
+ - A `not-found` in an organisation is often a project or a branch or baseline that belongs to another one. The
97
160
  command prints "not found in organisation <name>: check that you are attached to the correct
98
161
  organisation (openeng org current)". Run `openeng org current`; if it names the wrong organisation,
99
162
  `openeng org list` and `openeng org attach <id>`.
@@ -111,6 +174,8 @@ to understand each part, then design the model with the person before you draft
111
174
  it writes them as one JSON object keyed by type key, each at the next version, ready to send
112
175
  with revise. If it has no published types, create `draft.json` from the `changes` map in the
113
176
  example input printed by `openeng help ontology-sdk reviseChangeSet`.
177
+ A new object type needs `presentationBindings.typeIcon`; read the existing types' icons in the
178
+ export and choose a relevant glyph that no other type uses.
114
179
  2. Make `draft.json` hold only the types you change: delete every other key, and keep each type you
115
180
  keep whole, as the export wrote it. Accepting a type you did not change publishes an identical
116
181
  new version of it.
@@ -121,12 +186,31 @@ to understand each part, then design the model with the person before you draft
121
186
  5. `openeng types draft validate --change-set <id> --revision <revision>` must report no violations.
122
187
  It exits 0 when there are no violations, and exits 4 with the violations on standard output
123
188
  otherwise; then edit the file and revise again.
189
+ To try a sample instance against a type in the draft before you accept it, write the sample as a
190
+ JSON object of raw property values and run `openeng types draft try --type <type key> --sample
191
+ sample.json`. It reads the open change set and writes nothing, and checks the sample the way a
192
+ write does: it exits 0 when the sample fits and exits 4 with each violation's path and rule
193
+ otherwise. Add `--change-set <id>` to name the change set instead of using the open one.
124
194
  6. `openeng types draft show --change-set <id> --project <project id>` shows what changes against the
125
195
  published types, per type and per field. Check that it is exactly the change you meant.
126
196
  7. `openeng types draft accept --change-set <id> --revision <revision>` publishes it. The new version
127
197
  is now the published one: from here on, take a type's version for data writes from
128
198
  `openeng types list`.
129
199
 
200
+ Property kinds are `null`, `boolean`, `string`, `number`, `integer`, `person`, `enum`, `array`,
201
+ `object`, `datetime`, `attachment` and `bound`. Under language version `4`, numeric properties may
202
+ declare a `unit`, such as `kg`; publication refuses an unknown symbol (`unknown-unit`) or a later
203
+ change or removal (`changed-unit`). A `bound` is a top-level object property, or a top-level array
204
+ of bounds, under version `4`. See `openeng skill conventions` for its shape. Use `datetime` for an instant. A value is an RFC 3339 date-time
205
+ with an explicit offset and zero to three fraction digits, such as `2026-10-19T22:30:00+01:00` or
206
+ `2026-10-19T21:30:00Z`; a value with no offset, an impossible date or time, or four or more fraction
207
+ digits is refused. The platform stores it as `YYYY-MM-DDTHH:MM:SS.sssZ`, the same instant in UTC.
208
+ A calendar date is midnight UTC; there is no date kind. A type declaring `datetime` needs language
209
+ version `2` or later. An `attachment` is a top-level object property under version `3`, with a
210
+ non-empty `accept` listing classes such as `image` and `pdf`; it is refused inside an object or
211
+ array property and in an edge or verb schema. See the named property example in
212
+ `openeng skill conventions`. Never lower a published type's language version when revising it.
213
+
130
214
  To abandon a draft, `openeng types draft discard --change-set <id>`.
131
215
 
132
216
  `presentationBindings.typeIcon` is a Material Symbols Rounded name from the installed
@@ -141,29 +225,35 @@ watchers are admitted; the publication validator decides whether a declaration i
141
225
 
142
226
  ## 3. Write data
143
227
 
144
- Write on the ref agreed with the person and within their authority. That may be `main` when
228
+ Write on the branch agreed with the person and within their authority. That may be `main` when
145
229
  the applicable protections permit the write; an approved agent plan may also name an unprotected
146
- project's `main`. Use a branch and review when a rule protects the ref or the person asks for it.
230
+ project's `main`. Use a branch and review when a rule protects the branch or the person asks for it.
147
231
 
148
232
  1. `openeng help objects-sdk mutate` and `openeng help branches-sdk createBranch` for the fields, the
149
233
  selector keys and an example each.
150
234
  2. When a branch is needed, `openeng branches-sdk createBranch` makes one in the project. It
151
- answers the branch's ref, written `<project id>/<name>`.
152
- 3. `openeng objects-sdk mutate` creates, changes or deletes an object or an edge on that ref. A ref in
235
+ answers the branch's full name, written `<project id>/<name>`.
236
+ 3. `openeng objects-sdk mutate` creates, changes or deletes an object or an edge on that branch. The `ref` field in
153
237
  a selector takes one of three forms: the organisation trunk is the bare `main`; a project
154
- branch is its whole ref, `<project id>/<name>`; an organisation ref is its bare name.
155
- The server derives the organisation from the token. Use the agreed ref for writes and read
156
- back from that same ref with
238
+ branch is its full name, `<project id>/<name>`; an organisation branch or baseline is its bare name.
239
+ `--ref` takes a branch (`main` or `<projectId>/<branch>`) or a baseline for commands that admit organisation names.
240
+ The server derives the organisation from the token. Use the agreed branch for writes and read
241
+ back from that same branch with
157
242
  `openeng objects-sdk readObject` and `openeng objects-sdk queryObjects`.
158
243
  4. Read back what you wrote: `openeng objects-sdk readObject` for one object, or
159
- `openeng objects-sdk queryObjects` for a list. Use the type key and version the project's
244
+ `openeng objects-sdk queryObjects` for a list. Use `openeng objects-sdk queryRows` when you need
245
+ selected row cells, a count or grouped values; it answers these in one call instead of paging
246
+ `queryObjects` to count locally. Use the type key and version the project's
160
247
  `openeng types list` showed. For an object's edges use `openeng objects-sdk queryGraph`;
161
248
  for paths use `openeng objects-sdk findPaths`. Confirm relationships through the CLI;
162
249
  do not hand the check to the web app.
163
250
  5. `openeng objects-sdk executeVerb` runs a verb a type defines. `openeng objects-sdk discoverVerbs` lists
164
251
  the verbs available.
165
252
  6. When using a branch for review, `openeng branches-sdk submitProposal` sends it for review. It
166
- names the branch by its `name` alone, the part of the ref after the slash.
253
+ names the branch by its `name` alone, the part of the full branch name after the slash.
254
+
255
+ If a verb name is unknown, use `openeng objects-sdk discoverVerbs` for the object and choose a
256
+ listed verb; do not guess a verb key.
167
257
 
168
258
  If a command is refused, the refusal names the field and its allowed kinds. Run
169
259
  `openeng help <module> <method>` again and compare.
@@ -181,11 +271,35 @@ openeng objects-sdk queryGraph --host https://api.openeng.io --selector '{"proje
181
271
  Check the returned hops against the relationships you wrote. Use `findPaths` for paths across
182
272
  several objects; read its help before supplying input.
183
273
 
184
- ## Project ref rules
274
+ ### Review object and relationship changes
185
275
 
186
- A project rule may protect `main` or refs under that project's identifier. A matching
276
+ Run `openeng help branches-sdk diffBranches` for a live branch comparison, or
277
+ `openeng help branches-sdk readBranchDiff` for a submitted proposal's reviewed comparison.
278
+ Read both the object collection (`changes` for a live diff, `objects` for a proposal) and
279
+ `edges`. One page holds at most 200 changes total; follow its cursor until it is null before
280
+ describing the whole change. An edge's source and target carry object and project identifiers,
281
+ plus the edge's own properties before and after. An unreadable endpoint's identifiers do not
282
+ grant access to its title, type or properties. A cursor from an older client is refused;
283
+ start the comparison again with no cursor.
284
+
285
+ ## Project branch rules
286
+
287
+ `openeng branches-sdk disposeRef` is a writer's cleanup of a branch with no pending proposal.
288
+
289
+ ### Resolve a merge conflict
290
+
291
+ When merge answers `merge-conflict`, read the conflicts with
292
+ `openeng branches-sdk readMergeConflicts --selector '{"projectId":"<project-id>"}'
293
+ --input '{"name":"<source-branch-name>"}'`. The `name` is the source branch's name. For each
294
+ field, `base` is its value before either side changed it, `ours` is `main`, and `theirs` is the
295
+ source branch's value. A value may be absent on a side. The read always compares the source with
296
+ `main`, even if the merge targeted another branch, so it does not report conflicts from a merge
297
+ whose target was not `main`. Reconcile the changes on the source branch, then submit a new merge
298
+ with the reviewed head; reading conflicts makes no changes.
299
+
300
+ A project rule may protect `main` or branches under that project's identifier. A matching
187
301
  `merge-only` rule requires changes through a branch and merge. A `locked-rows-only` rule binds
188
- merge-only row locks on the matching ref while leaving unlocked rows direct.
302
+ merge-only row locks on the matching branch while leaving unlocked rows direct.
189
303
 
190
304
  Rule management is the person's workflow: they must hold `administer projects` on the project
191
305
  and run these commands themselves. Never add or remove rules on their behalf, including to
@@ -199,11 +313,11 @@ get past a refusal.
199
313
  3. To lift one rule, the person runs `openeng rules remove --project <id> --rule-id <id>` with
200
314
  the identifier from the list. An absent identifier or one from another project answers
201
315
  `not-found`. Removal is audited, as is addition, and takes effect on the next request.
202
- Other matching rules and row locks may still protect the ref's rows.
316
+ Other matching rules and row locks may still protect that branch's rows.
203
317
 
204
- ## Organisation rules, refs, locks and agent ceilings
318
+ ## Organisation rules, branches and baselines, locks and agent ceilings
205
319
 
206
- These protections are managed by the person. Never change rules, refs or locks yourself,
320
+ These protections are managed by the person. Never change rules, branches, baselines or locks yourself,
207
321
  including to get past a refusal. Read their current state and ask the person to make a change.
208
322
  Each command's `--help` names the person's capability. A `not-permitted` refusal carries no
209
323
  capability; read the help line before asking the person to seek permission.
@@ -215,8 +329,8 @@ capability; read the help line before asking the person to seek permission.
215
329
  `openeng rules list --organisation` reads the rules;
216
330
  `openeng rules remove --organisation --rule-id <id>` removes one by its identifier.
217
331
  Adding or removing needs `administer projects` in the attached organisation; listing needs `read`.
218
- - `openeng org-refs list` reads organisation refs and their read-only state. The person creates
219
- one with `openeng org-refs create --name <name> [--read-only]`, marks it read-only with
332
+ - `openeng org-refs list` reads organisation branches and baselines with their read-only state. The person creates
333
+ a branch with `openeng org-refs create --name <name>` or a baseline by adding `--read-only`. A branch becomes a baseline with
220
334
  `openeng org-refs mark-read-only --name <name>`, or deletes a writable one with
221
335
  `openeng org-refs delete --name <name>`. Names are single segments, such as `release-v1`.
222
336
  Creating, deleting and marking need `administer projects` in the attached organisation;
@@ -224,8 +338,8 @@ capability; read the help line before asking the person to seek permission.
224
338
  - The person sets or lifts an object's lock with
225
339
  `openeng locks set --project <id> --ref <ref> --object <objectId> --lock <none|merge-only|frozen>`.
226
340
  `none` lifts it. The lock also applies to its existing structural child edges in the selected
227
- project. New children on a live ref are not thereby frozen. Use a read-only organisation ref
228
- for a fixed baseline. This needs `lock objects` on the selected project.
341
+ project. New children on a writable branch are not thereby frozen. Use a baseline
342
+ to preserve a fixed snapshot. This needs `lock objects` on the selected project.
229
343
  - `openeng ceiling show --project <id>` reads the maximum agent role. The person sets it with
230
344
  `openeng ceiling set --project <id> --ceiling <contributor|maintainer>`.
231
345
  Showing needs `read`; setting needs `administer projects` on the selected project.
@@ -234,50 +348,76 @@ capability; read the help line before asking the person to seek permission.
234
348
 
235
349
  When a command returns one of these rules, follow its action and do not repeat the same request:
236
350
 
237
- - `immutable`: the type forbids changing or deleting the record on every ref. Leave it unchanged.
351
+ - `immutable`: the type forbids changing or deleting the record on every branch or baseline. Leave it unchanged.
238
352
  - `owned`: a connected system alone writes the record. Ask that system to make the change.
239
353
  - `frozen`: someone with the lock capability must lift the lock. Ask that person; do not try a
240
- different ref.
354
+ different branch or baseline.
241
355
  - `protected`: a rule allows the record to change only through a merge from a branch. Make the
242
356
  change on a branch and merge it.
243
- - `not-a-ref-head`: the commit is not the head of a ref you can use. Read the usable refs and
244
- choose one of their heads; the refusal does not identify which commit or ref was involved.
245
- - `branch-needs-schema-update`: the ref's schema must be updated before writing. The
357
+ - `stale-source`: read a branch you can use and merge its current head. Optional merge `name`
358
+ requires that bound branch's current head to equal `sourceHash`; it never selects a proposal.
359
+ A successful merge into main closes every pending proposal in the project at that reviewed hash.
360
+ - `not-a-ref-head`: the branch has new commits since the review began. Reload the proposal to
361
+ review its latest commit; the refusal does not identify the branch or its newer head.
362
+ - `branch-needs-schema-update`: the branch's schema must be updated before writing. The
246
363
  person can run `openeng schema-update request --ref <ref>` to record a request, then
247
364
  `openeng schema-update show --ref <ref>` to read its state or `no request`. Stop writing while
248
- the ref needs an update; recording a request does not execute the update. Requesting needs
249
- `write ref` on the branch's home project, or `administer projects` for an organisation ref;
365
+ the branch needs an update; recording a request does not execute the update. Requesting needs
366
+ `write ref` on the branch's home project, or `administer projects` for an organisation branch or baseline;
250
367
  showing reads only the requester's records in the token organisation and needs no project read
251
368
  access. A branch whose name contains `/` cannot request or show a schema update today.
252
369
  - `organisation-not-ready`: the organisation's trunk is not ready. Try again shortly.
253
- - `read-only-ref`: nothing can be written or merged into this ref. Choose a writable ref.
370
+ - `read-only-ref`: nothing can be written or merged into this branch or baseline. Choose a writable branch.
254
371
 
255
372
  ## 4. Link to a page
256
373
 
257
374
  To give the person a page, run `openeng link` and hand them the address it prints; never write a path
258
- or an address yourself. `openeng link <kind> --project <id> --ref <ref>` takes `explore`, `branch-diff`
375
+ or an address yourself. `openeng link <kind> --project <id> --ref <ref>` takes `branch-diff`
259
376
  or `project`; `openeng link <kind> <identifier> --project <id> --ref <ref>` takes `object`, `type`, `proposal` or
260
377
  `app` (the app's first page); `openeng link app-page <appKey> <pageKey> --project <id> --ref <ref>` takes
261
378
  one page of an app; `openeng link app-draft <appKey> --ref <ref>` takes the app's draft screen and no
262
- project. `openeng link ontology --ref <ref>` and `openeng link change-set --ref <ref>` take a ref and no
379
+ project. `openeng link ontology --ref <ref>` and `openeng link change-set --ref <ref>` take a branch and no
263
380
  project, and `openeng link organisation-page <page>` takes neither flag. The organisation is the one
264
381
  your session is attached to.
265
382
 
383
+ | kind | destination |
384
+ |---|---|
385
+ | `object <id>` | The object's type page with the object open; the type comes from its read. |
386
+ | `type <key>` | The type's page. |
387
+ | `explore` | Explore with exactly one `--object <id>` or `--object-set <id>` seed. |
388
+ | `branch-diff` | The branch comparison page. |
389
+ | `project` | The project page. |
390
+ | `proposal <id>` | The proposal review page. |
391
+ | `ontology` | The organisation's Types workspace. |
392
+ | `change-set` | The organisation's Change set workspace. |
393
+ | `app <key>` | The published app's first page. |
394
+ | `app-page <appKey> <pageKey>` | The named page of a published app. |
395
+ | `app-draft <key>` | The app's draft screen in the Types workspace. |
396
+ | `organisation-page <page>` | The named organisation administration page or settings. |
397
+
398
+ Only `explore` opens Explore. Use `openeng link explore --project <id> --ref <ref>` with exactly
399
+ one of `--object <id>` or `--object-set <id>`; neither or both refuse before a host call.
400
+ The seed flags are only for `explore`. `link object <id>` opens the type page with that object,
401
+ using the type key from the object read. Explore also reads its selected object or saved set first.
402
+
266
403
  ### Save an object set and link to its canvas
267
404
 
268
405
  1. Run `openeng help objects-sdk createObjectSet` and `openeng help objects-sdk readObjectSet`.
269
406
  2. Query the objects you need with `openeng objects-sdk queryObjects --json`. Keep each object's
270
407
  project with its identifier; one set may contain objects of several projects in your organisation.
408
+ To combine two selections on the same ref, send `{ "kind": "set", "op": "difference", "left": { "kind": "objects", "typeKey": "..." }, "right": { "kind": "objects", "typeKey": "..." }, "limit": 100, "continuation": null }`. `op` may be `union`, `intersection` or `difference`. Each operand may have its own `projects`, `filters` and `steps`; operands cannot be nested set operations.
409
+ To select several object types in one paged query, use `typeKey: null` with a top-level `{ "kind": "type", "op": "in", "values": ["part", "system"] }` filter. The list holds 1 to 100 published type keys; combine it with a text filter to search those types. Follow the returned continuation without changing the selection.
410
+ `aggregateObjects` also accepts `operation: "average"` with one numeric `property`; the result includes its mean and the count averaged, and omits the mean when that count is zero.
271
411
  3. Call `openeng objects-sdk createObjectSet` with a name and the selected addresses, following its
272
412
  help. Keep the returned set identifier and revision. Retrying with the same idempotency key
273
413
  returns that original answer.
274
414
  4. Run `openeng link explore --project <page project> --ref <ref> --object-set <set id>` and give the
275
415
  person the address it prints. It reads the set first; a refused read prints no link. The set
276
- stores no ref, so the link's ref chooses which version of its objects opens.
416
+ stores no branch or baseline, so the link's branch chooses which version of its objects opens.
277
417
 
278
418
  Every kind with `--ref`, including `ontology` and `change-set`, takes `main` or
279
- `<projectId>/<branch>`, the ref the platform returns. A bare branch name or change-set id is
280
- refused by `openeng link`. Before printing, the command reads the ref and the page's own subject;
419
+ `<projectId>/<branch>`, the branch name the platform returns. Baseline names are not accepted by `openeng link`. A bare branch name or change-set id is
420
+ refused by `openeng link`. Before printing, the command reads the branch and the page's own subject;
281
421
  a subject it cannot find is a refusal with a reason and no printed address.
282
422
 
283
423
  An **App** is an organisation entity with its own pages and drafts, linked by `openeng link app`.
@@ -350,3 +490,47 @@ Refusals you will meet, with what each means and what to do:
350
490
  - `change-set-open`: the organisation already has an open change set, so drafting the types
351
491
  stopped. Read it with `openeng types draft current` and continue with it; the connection exists, and
352
492
  `openeng connector draft-types <connection>` drafts once that change set is settled.
493
+
494
+ ## Inviting a person
495
+
496
+ Run `openeng help admin-sdk createInvitation` before inviting. The request takes `email`, an
497
+ organisation `roleKey`, and optional `projectRoles`: up to 50 `{ projectId, roleKey }` entries,
498
+ one per project in the attached organisation. The inviter must administer members on the
499
+ organisation and each project, and may offer no role above their own there. Send no organisation
500
+ field; the server derives it. Deliver the returned link to the person.
501
+
502
+ `openeng admin-sdk listInvitations --input '{}' --json` lists pending invitations and their
503
+ project roles. Re-issuing keeps the roles; revoking removes the invitation from that list.
504
+ Acceptance skips and audits a project role when the project ended, the person already holds an
505
+ equal or higher project role, or the inviter lost the required standing. Sign-in continues.
506
+
507
+ Membership roles are `owner`, `maintainer`, `contributor` and `reader`. They grant, respectively:
508
+
509
+ - `owner`: administer members, projects and service identities; write trunk, branches and protected
510
+ rows; merge; and read.
511
+ - `maintainer`: write trunk, branches and protected rows; merge; and read.
512
+ - `contributor`: write branches and read. For example, a project contributor may edit on a branch
513
+ and read the project, but does not gain merge or trunk-write permission.
514
+ - `reader`: read.
515
+
516
+ A membership can be scoped to an organisation or a project. An organisation role supplies its
517
+ capabilities in each project of that organisation too; a project role applies to its named project.
518
+ For a project-specific exception, grant the role on that project rather than assuming a membership
519
+ in one project applies to another.
520
+
521
+ An unknown role on an invitation or membership grant answers `unknown-role` with `roleKeys`, the
522
+ deployment's role keys. Choose one of those keys. A known role above your own answers
523
+ `above-caller-role`.
524
+
525
+ ## Recover an interrupted operation
526
+
527
+ `openeng objects-sdk recover` checks the record of a mutation or verb whose result was unknown. Give
528
+ the same project and ref, and the original correlation id:
529
+
530
+ ```sh
531
+ openeng objects-sdk recover --selector '{"projectId":"<project-id>","ref":"<project-id>/<branch>"}' --input '{"correlationId":"<correlation-id>"}' --json
532
+ ```
533
+
534
+ Recovery can report a committed change and its hash, and finish the recovery record. It never sends
535
+ the original mutation again. If the saved evidence still cannot establish an outcome, it returns
536
+ `unknown`; it cannot undo a successful write, restore a deleted object, or retry a failed operation.
@@ -112,4 +112,4 @@ reached through a part or a plant.
112
112
  a structure by it.
113
113
  - **Mass change** of many lines, and a **cost roll-up** across a structure: a count per question is a query, a
114
114
  roll-up is not built.
115
- - **CAD geometry**: an object view can show an STL property (`STLViewer`); there is no live CAD link.
115
+ - **CAD geometry**: an object view can show an STL attachment (`STLViewer`); there is no live CAD link.