@openengio/cli 0.23.3 → 0.24.4

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.23.3",
3
+ "version": "0.24.4",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "engines": {
@@ -13,6 +13,10 @@ catalogue the platform validates against. The CLI does not yet ship that generat
13
13
  use this guide's examples and `openeng help types draft revise` for the wire shape, then validate the change
14
14
  set; the host decides which components, props, bounds and bindings your version admits.
15
15
 
16
+ An **App** is an organisation entity with its own pages and drafts, linked by `openeng link app`.
17
+ An **App view** is a type's collection content in `presentationBindings.views.app`, root `AppBody`,
18
+ and cannot be linked by `link app`.
19
+
16
20
  Work through the steps in order, and stop where a step says so.
17
21
 
18
22
  ## 1. Know what the view must answer
@@ -101,6 +101,10 @@ the first view.
101
101
  drawer; an **App view** (`.app`, root `AppBody`) lays out the type's page. Only components the view
102
102
  catalogue admits may appear, each with the props it takes.
103
103
 
104
+ An **App** is an organisation entity with its own pages and drafts, linked by `openeng link app`.
105
+ An **App view** is a type's collection content in `presentationBindings.views.app`, root `AppBody`,
106
+ and cannot be linked by `link app`.
107
+
104
108
  ## 6. Versions
105
109
 
106
110
  - A new type key starts at version 1. A changed type is sent at its published version plus one;
@@ -132,6 +136,64 @@ for a lifecycle state. A wrong edge is replaced by a new edge type key and a rec
132
136
  {"value": <the new value>}}}`; `{"absent": true}` stands for no value on either side. A `from` that no
133
137
  longer matches is refused, so read the object first.
134
138
 
139
+ ## Property kinds
140
+
141
+ An enum's `members` is a list of strings or finite numbers. A published member cannot be removed.
142
+
143
+ ### enum
144
+
145
+ ```json
146
+ {"kind": "enum", "members": ["open", "closed"]}
147
+ ```
148
+
149
+ ### null
150
+
151
+ ```json
152
+ {"kind": "null"}
153
+ ```
154
+
155
+ ### boolean
156
+
157
+ ```json
158
+ {"kind": "boolean"}
159
+ ```
160
+
161
+ ### string
162
+
163
+ ```json
164
+ {"kind": "string"}
165
+ ```
166
+
167
+ ### number
168
+
169
+ ```json
170
+ {"kind": "number"}
171
+ ```
172
+
173
+ ### integer
174
+
175
+ ```json
176
+ {"kind": "integer"}
177
+ ```
178
+
179
+ ### person
180
+
181
+ ```json
182
+ {"kind": "person"}
183
+ ```
184
+
185
+ ### array
186
+
187
+ ```json
188
+ {"kind": "array", "items": {"kind": "string"}, "maxItems": 10}
189
+ ```
190
+
191
+ ### object
192
+
193
+ ```json
194
+ {"kind": "object", "properties": {"name": {"kind": "string"}}, "required": ["name"]}
195
+ ```
196
+
135
197
  ## 9. Examples
136
198
 
137
199
  A minimal object type and a structural edge, every key at version 1:
@@ -1,112 +1,139 @@
1
1
  ---
2
2
  name: demo
3
- description: Use when a person new to OpenEngineering wants a hands-on tour, or has just signed in and has no task of their own yet. Builds a small example with them on a familiar workflow (requirements, product lifecycle, project tracking) or their own, optionally connects Onshape or a small local OAuth app, alternating your configuration with links and actions they take in the app.
3
+ description: Use when a person new to OpenEngineering wants a hands-on tour, or has just signed in and has no task of their own yet. Offers the example plant seed, a free-form capability tour around their workflow, or a task they name.
4
4
  ---
5
5
 
6
6
  # Give a person a tour of OpenEngineering
7
7
 
8
- The aim is one outcome the person cares about, experienced in the app with their own hands. Covering
9
- features is not the aim: a tour is done when they have seen that outcome and know how to carry on.
10
- Ask at most two questions at a time. Do not turn routine commands into permission questions.
11
-
12
- ## 1. Offer the tour once
13
-
14
- After sign-in, when the person has no task of their own, offer once: "I can set up a small example
15
- around your work, then we can explore it together in the app." They may accept, decline, or go to
16
- their own task. An accepted tour covers work inside a demo organisation. It does not cover inviting
17
- anyone, connecting an external account (Onshape), registering an app, or touching an existing
18
- organisation's data: ask before each of those.
19
-
20
- ## 2. Learn what matters to them
21
-
22
- Ask about their work first: "What do you design or manage, and where does the work get hard today?"
23
-
24
- Then anchor the tour on a workflow they will recognise, and offer two or three that fit what they said,
25
- each with one line on why:
26
- - a requirements platform in the style of Jama or DOORS: requirements, their decomposition, and the
27
- verification that proves them (`openeng skill playbook engineering-requirements`);
28
- - a product lifecycle platform in the style of Arena or Windchill: parts, revisions, the bill of
29
- materials, and changes that are requested, approved and released (`openeng skill playbook
30
- product-lifecycle`);
31
- - a project and work tracker (`openeng skill playbook project-management`).
32
-
33
- Say plainly that they can go smaller, or ask for something entirely their own, and follow that when
34
- they do. Then refine the chosen one in their terms: who is involved, what starts the work, what they
35
- need to see, and what a good result looks like. Use their names for things inside the familiar shape.
36
- If they would rather look around a fuller example before building their own, build a slightly larger
37
- one from the chosen playbook first, and say which data is invented.
38
-
39
- ## 3. Agree a small story
40
-
41
- Propose a short flow with a visible result, for example: "We make the controller and its thermal
42
- requirement, record a failed test, then propose a fix on a branch for review." Keep it to two or three
43
- types, a handful of objects, one relationship that shows structure, and one change that shows a
44
- branch and a review. Create a new organisation for the tour (`openeng org create`) unless they ask to
45
- use an existing one. Say which data is invented.
46
-
47
- Design the types with `openeng skill new-use-case`, and keep its stop points. Read `openeng skill
48
- conventions` before you choose relationships: structure (one parent) is not navigation (declared
49
- relationships), and the difference shows in their tree.
50
-
51
- ## 4. Build in small steps, each with something to see
52
-
53
- For each step:
54
- 1. Say in their words what you will do next and why.
55
- 2. Make the smallest useful change with `openeng`. Use one atomic batch for related writes.
56
- 3. Read the result back in the organisation, project and ref you meant. Validate before you publish.
57
- Keep apart: accepted, validated, published, and seen rendered in the app.
58
- 4. Give a link from `openeng link` at once. Say what they should see there, and any limit of that page.
59
- 5. Invite one action that matters: edit a value, comment, subscribe, compare a branch with main, or
60
- accept a proposal if their role allows it. Say what to do and what you will check afterwards.
61
- 6. Check the result with a read, not with their click. Then use their reaction to choose the next step.
62
-
63
- Leave a state on screen until they have had a chance to see it. If they say a step is dull or already
64
- clear, move on.
65
-
66
- ## 5. Make it usable in the app
67
-
68
- Choose readable names and a distinct icon per type from the supported set. Build object views and
69
- apps with `openeng skill build-ui` and the component catalogue it names; do not guess components or
70
- bindings. A view is worth building when it serves the story; most tours need none.
71
-
72
- ## 6. Connect their tools, when it serves the story
73
-
74
- Two extensions show that the platform is open. Offer each one when it fits; ask before starting either.
75
-
76
- **Onshape, if they use it.** Ask whether they have an Onshape account and which document, team or
77
- company they would like to mirror. Create a connector with `openeng connector create`. The person enters
78
- their Onshape key pair themselves at the prompt of `openeng connector set-credential`: never ask for a key
79
- in the conversation, never accept one pasted there, and never type one. Agree the import scope before
80
- `openeng connector run`, then read `openeng connector runs` and show what arrived. Mirrored objects are owned by
81
- the connector and are not edited here; trace them into the story with links. If a run imports nothing,
82
- say what was looked for and ask them to check the scope.
83
-
84
- **A small app of their own, using OAuth.** Offer to build a tiny local web app that signs in to
85
- OpenEngineering and reads their data, for example a dashboard of failed tests. Register it as a public
86
- client of their organisation with `openeng admin-sdk registerClient` (read `openeng help admin-sdk
87
- registerClient` first), using a `http://127.0.0.1:<port>/callback` redirect. The app uses the
88
- authorization-code flow with PKCE against the issuer the help names, so the person signs in and
89
- consents on OpenEngineering's own page; the app never sees their password. Keep it read-only unless
90
- they ask for more, run it on their machine, and give them the local link. Read the platform's published
91
- client contract before you write the app; do not guess the request shape.
92
-
93
- ## 7. When something goes wrong
94
-
95
- Read the refusal and fix the input. When the help does not say enough, make a minimal example, record
96
- the exact command and answer, and ask the person; do not guess in a loop. When an outcome is unknown,
97
- read the state before you write again. Never claim to have contacted the OpenEngineering team.
98
-
99
- ## 8. End on the outcome
100
-
101
- Recap what they saw, with the links to come back to, and one or two next steps for their own work. Say
102
- what remains in the demo organisation: types, objects, branches, proposals and drafts, and any
103
- connector or registered client, which they can revoke (`openeng connector revoke`). Agree before
104
- deleting anything. Do not imply that a short tour proves every feature or permission.
8
+ ## 1. Offer three paths
9
+
10
+ After sign-in, when the person has no task of their own, offer once:
11
+
12
+ - **Seed demo**: create a project, run `openeng demo seed --project <id>`, then follow the
13
+ [Quickstart](https://docs.openeng.io/get-started/quickstart/) together.
14
+ - **Free-form tour** (the main path): build a small example around their work and explore its
15
+ capabilities together in the app.
16
+ - **Something else**: follow the task the person names. They may decline the tour.
17
+
18
+ Before the tour starts, load every capability below into your own native task or plan tool,
19
+ whatever your harness provides: one item per capability, its Checklist line as the title and its
20
+ Features shown line as the detail. Show the person the list and say they may skip any item.
21
+ Run one item at a time. Tick it only when the person has seen its result in the app and you have
22
+ checked that result with a read. Drop a declined item from the remaining work and mark it skipped,
23
+ never done. If you have no task or plan tool, write the same checklist in the conversation and
24
+ show each item's state again whenever it changes.
25
+
26
+ Offer C1, C3 and C5 first, then the others by the person's interest. Use the chosen playbook or
27
+ the example plant for the stories. All capabilities below are shipped. Leave per-field conflicts
28
+ out of every story.
29
+
30
+ - [ ] C1. Describe your workflow, and use the tool five minutes later
31
+ Checklist: Build a working tool from a description of the person's workflow.
32
+ Features shown: Organisations and projects; Familiar workflow playbooks; Types and the ontology;
33
+ Ontology agent; Rail groups and type icons; Objects; Table of one type; The object card.
34
+
35
+ - [ ] C2. One data model, two ways of working: a CRUD app or a branch-first engineering workflow
36
+ Checklist: Switch one project between direct edits on `main` and branch-only edits.
37
+ Features shown: Objects; Branches; Branch diff and changed-object accents; Proposals; Roles and
38
+ membership; Ref rules.
39
+
40
+ - [ ] C3. Follow one question across every tool
41
+ Checklist: Answer one question that crosses requirements, parts and tests.
42
+ Features shown: Relationships; Structure tree; Graph and Explore; Paths between two objects;
43
+ Counts and rollups; The object card.
44
+
45
+ - [ ] C4. Every record carries its own story
46
+ Checklist: Show who changed a record, why, and what a delete would take with it.
47
+ Features shown: The object card; Object history with per-field attribution; Comments and
48
+ subscribers; Delete preview; Branch history and the audit trail.
49
+
50
+ - [ ] C5. An agent does the work, a person makes the call
51
+ Checklist: Have the in-product agent make a change that a person approves and merges.
52
+ Features shown: Branches; Branch diff and changed-object accents; Proposals; Branch history and
53
+ the audit trail; Object agent; Agent model per organisation; Agent ceiling.
54
+
55
+ - [ ] C6. Freeze what shipped, keep building what comes next
56
+ Checklist: Freeze a released part and keep a read-only release baseline.
57
+ Features shown: Types and the ontology; Objects; Relationships; Organisation refs; Instance
58
+ locks; Type rules.
59
+
60
+ - [ ] C7. Your CAD system stays the source of truth
61
+ Checklist: Mirror Onshape parts and link a requirement to one of them.
62
+ Features shown: Types and the ontology; Relationships; Service identities; Onshape mirror; Type
63
+ rules.
64
+
65
+ - [ ] C8. Build on it: a screen for each team, and your own app
66
+ Checklist: Build a team page from configuration, then a small OAuth app on the same data.
67
+ Features shown: Counts and rollups; Object views and App views; Apps with several pages; Roles
68
+ and membership; OAuth apps.
69
+
70
+ ## 2. Agree the workflow and keep its stop points
71
+
72
+ Ask what the person designs or manages and where the work gets hard. Offer a fitting playbook:
73
+ `openeng skill playbook engineering-requirements`, `product-lifecycle` or `project-management`,
74
+ or use their own vocabulary. Agree a small story with a visible result. Create a demo organisation
75
+ with `openeng org create` unless asked to use an existing one; say which data is invented.
76
+ Ask before touching existing data, inviting anyone, connecting Onshape or registering an app.
77
+ Ask at most two questions at a time; do not turn routine commands into permission questions.
78
+
79
+ Whenever the tour designs types, read `openeng skill new-use-case` and follow every stop point
80
+ in order: show the person the work and wait for agreement at each one. Do not skip a stop point
81
+ to speed up the tour. Read `openeng skill conventions` before choosing relationships, properties,
82
+ icons and rail groups. Draft nothing before new-use-case's drafting step; accept a change set
83
+ only on the person's word naming it.
84
+
85
+ ## 3. Show one story at a time
86
+
87
+ Use `openeng help <module> <route>` for request shapes. Each story answers a question the person
88
+ cares about; do not explain a primitive in isolation.
89
+
90
+ - C1: agree and publish types from the chosen playbook, write believable data with
91
+ `objects-sdk mutateBatch`, then show the rail, table and object card with `link type`.
92
+ - C2: edit on main, add a merge-only rule, show the same edit refused `protected`, then branch,
93
+ edit, compare and submit a proposal. The person merges; remove the rule and show direct edits.
94
+ - C3: narrow with `objects-sdk readStructure`, show `link explore`, and answer a question
95
+ across requirements, parts and tests with `queryObjects`, `findPaths` and `aggregateObjects`.
96
+ - C4: open a record's history, comment and subscribe; use `objects-sdk previewDelete` before
97
+ any deletion, and read branch history and `admin-sdk listAudit`.
98
+ - C5: show the organisation's agent model and project's `ceiling show`. The person uses
99
+ "Open agent", approves its plan, inspects the branch diff, submits and merges. Read the audit
100
+ naming the person and run; show the agent refused on protected main.
101
+ - C6: use `locks set --lock frozen` on a released part, show an edit refused, create its successor
102
+ and relationship, and keep a baseline with `org-refs create --read-only`. Show an immutable
103
+ test result refusing changes on a branch too.
104
+ - C7: for an Onshape user, agree the import scope; use `connector create`, `set-credential`,
105
+ `draft-types`, publish agreed types, `run` and `runs`. Link a requirement to a mirrored part,
106
+ show it cannot be edited here, and show a repeat import preserves the requirement.
107
+ - C8: read `openeng skill build-ui` and its component catalogue, publish a team page through
108
+ the App draft workflow, and show `link app`. Offer a small local OAuth app reading the same
109
+ data; show consent and how to disconnect it.
110
+
111
+ At each step, say what comes next and why, make the smallest useful change (one atomic batch
112
+ for related writes), validate before publishing, and read the result in the intended organisation,
113
+ project and ref. Give a link from `openeng link`, say what they should see, and leave time to see it.
114
+ Invite an action that matters, then check its result with a read. Keep accepted, validated,
115
+ published and seen in the app distinct. Drive through the CLI; the person operates the app.
116
+
117
+ The person enters Onshape keys themselves at `openeng connector set-credential`'s prompt;
118
+ never ask for keys in conversation or type them. Mirrored objects are owned by the connector.
119
+ For OAuth, read the published client contract and `openeng help admin-sdk registerClient`.
120
+ Register a public client with a `http://127.0.0.1:<port>/callback` redirect; use authorization code
121
+ with PKCE. Keep the local app read-only unless asked for more; it never sees their password.
122
+
123
+ ## 4. Handle refusals and finish
124
+
125
+ Read a refusal and fix the input. If help is insufficient, record one minimal command and answer
126
+ and ask the person; do not guess in a loop. For an unknown outcome, read state before writing again.
127
+ Never claim to have contacted the OpenEngineering team.
128
+
129
+ Recap completed and skipped tasks, return links and next steps. Say what remains: types, objects,
130
+ branches, proposals, drafts and any connector or registered client, and how to revoke the connector
131
+ (`openeng connector revoke`) or disconnect the app. Agree before deleting anything.
132
+ Do not imply a short tour proves every feature or permission.
105
133
 
106
134
  ## Dogfood mode (only when the person asks for feedback capture)
107
135
 
108
- The OpenEngineering team uses this mode to test the product. Record each friction as it happens, with
109
- the command, the answer and your confidence, classed as: your own omission, a help gap, an observed
110
- defect, a user-reported issue, a feature request, or an open question. Merge later corrections into
111
- earlier entries. At the end, hand over one file: the findings grouped, with evidence, a proposed
112
- priority and the open questions, kept apart from the recap. Never send feedback anywhere yourself.
136
+ Record friction as it happens: command, answer, confidence, and whether it is your omission, a help
137
+ gap, an observed defect, a user-reported issue, a feature request or an open question. Merge later
138
+ corrections into earlier entries. Hand over one file with evidence, proposed priorities and open
139
+ questions, separate from the recap. Never send feedback anywhere yourself.
@@ -105,6 +105,10 @@ Stop: the person agrees the properties and the rail.
105
105
 
106
106
  ## 6. Decide views, if any
107
107
 
108
+ An **App** is an organisation entity with its own pages and drafts, linked by `openeng link app`.
109
+ An **App view** is a type's collection content in `presentationBindings.views.app`, root `AppBody`,
110
+ and cannot be linked by `link app`.
111
+
108
112
  An object view shapes the object's drawer; an App view shapes the type's page. Propose one only when the
109
113
  default layout does not answer step 1's questions. Use only the components the view catalogue admits.
110
114
 
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: openeng
3
- description: Use when you need to work with an OpenEngineering platform through its command line, `openeng`. Signing in, listing projects and types, editing object types, writing objects on a branch and submitting them for review.
3
+ description: >-
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
6
+ and submitting branches for review.
4
7
  ---
5
8
 
6
9
  # Working with the platform through `openeng`
@@ -11,12 +14,6 @@ description: Use when you need to work with an OpenEngineering platform through
11
14
  npm install -g @openengio/cli
12
15
  ```
13
16
 
14
- Upgrading from `@benjaminfh/oe2`: first run the earlier package's `logout` command, so its stored
15
- session does not stay on this machine; then uninstall it and install `@openengio/cli`. The command
16
- is now `openeng`, the environment variables are
17
- `OPENENG_HOST`, `OPENENG_SIGN_IN_ORIGIN` and `OPENENG_SESSION_STORE`, and you sign in again once
18
- with `openeng login`.
19
-
20
17
  This skill gives the commands and their order. It gives no input shapes, because the commands print
21
18
  their own. Before you send a generated command (`objects-sdk`, `branches-sdk` and the other
22
19
  `<module> <method>` commands), run `openeng help <module> <method>`. It prints the fields, the kinds a
@@ -46,7 +43,10 @@ field may take, the selector keys and one example input, and needs no sign-in.
46
43
  does, an example and the shape of its output. `openeng help <group>` lists a group's commands.
47
44
  `openeng --version` prints the published version.
48
45
  - `openeng` has no host built in. The production host is `https://api.openeng.io`: pass
49
- `--host https://api.openeng.io`, or set `OPENENG_HOST=https://api.openeng.io` once.
46
+ `--host https://api.openeng.io` on every command, or prefix it as
47
+ `OPENENG_HOST=https://api.openeng.io openeng ...`. An export in `~/.zshrc` does not reach
48
+ an agent's shell or a Claude Code `!` shell. In zsh, persist it in `~/.zshenv`.
49
+ Fix `no-host` by adding the flag or prefix.
50
50
  - `openeng orgs list` and `openeng organisations list` mean `openeng org list`; `openeng project list` means
51
51
  `openeng projects list`.
52
52
  - A mutation or a branch command that needs a `correlation` mints it for you when your input has
@@ -58,7 +58,10 @@ field may take, the selector keys and one example input, and needs no sign-in.
58
58
  ## 1. Sign in and orient
59
59
 
60
60
  1. `openeng help` to see what exists.
61
- 2. `openeng login`. It opens a browser to sign in; `openeng login --no-open` prints the address instead.
61
+ 2. Run `openeng login` yourself with the host flag. It opens the person's browser and waits;
62
+ tell the person to finish sign-in there. Do not ask the person to run it. If your tool cuts a
63
+ command off before it returns, run it in the background or use `openeng login --no-open`
64
+ with the host flag and give the person the printed address.
62
65
  3. `openeng whoami` to confirm who you are.
63
66
  4. `openeng org list --json` prints the organisations you belong to. `openeng org attach <id>` attaches
64
67
  your session to one. If you have no organisation, create one with
@@ -85,10 +88,11 @@ For a generic open-cycle gas turbine demonstration project, run `openeng demo se
85
88
  `org: <name> (<id>)`, then `· project: <id>` and `· ref: <ref>` when you named them. Read it
86
89
  before you trust an answer.
87
90
  - With `--json`, the one value on standard output carries the same scope as a `scope` object:
88
- `{"organisation": {"id", "name"}, "project"?, "ref"?}`. An object value gains a `scope` key.
91
+ `{"organisation": {"id", "name"}, "project"?, "ref"?}`. An object value normally gains a `scope` key.
89
92
  A value that is an array or null, such as the list from `openeng projects list`, comes wrapped as
90
- `{"scope": {...}, "value": <the original value>}`. A command with no scope carries no `scope`
91
- field.
93
+ `{"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
95
+ successes also always use `{ scope, value }`. A command with no scope carries no `scope` field.
92
96
  - A `not-found` in an organisation is often a project or a ref that belongs to another one. The
93
97
  command prints "not found in organisation <name>: check that you are attached to the correct
94
98
  organisation (openeng org current)". Run `openeng org current`; if it names the wrong organisation,
@@ -137,28 +141,117 @@ watchers are admitted; the publication validator decides whether a declaration i
137
141
 
138
142
  ## 3. Write data
139
143
 
140
- Data is written on a branch and then submitted for review.
144
+ Write on the ref agreed with the person and within their authority. That may be `main` when
145
+ 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.
141
147
 
142
148
  1. `openeng help objects-sdk mutate` and `openeng help branches-sdk createBranch` for the fields, the
143
149
  selector keys and an example each.
144
- 2. `openeng branches-sdk createBranch` makes a branch in the project. It answers the branch's ref,
145
- written `<project id>/<name>`.
150
+ 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>`.
146
152
  3. `openeng objects-sdk mutate` creates, changes or deletes an object or an edge on that ref. A ref in
147
- a selector takes one of two forms: the project's trunk is the bare `main`, with no project id;
148
- a branch is its whole ref, `<project id>/<name>`, the slash and the project id included. Use
149
- `main` to read what is published, and the branch's ref to read or write your own work, here and
150
- for `openeng objects-sdk readObject` and `openeng objects-sdk queryObjects`.
153
+ 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
157
+ `openeng objects-sdk readObject` and `openeng objects-sdk queryObjects`.
151
158
  4. Read back what you wrote: `openeng objects-sdk readObject` for one object, or
152
159
  `openeng objects-sdk queryObjects` for a list. Use the type key and version the project's
153
- `openeng types list` showed.
160
+ `openeng types list` showed. For an object's edges use `openeng objects-sdk queryGraph`;
161
+ for paths use `openeng objects-sdk findPaths`. Confirm relationships through the CLI;
162
+ do not hand the check to the web app.
154
163
  5. `openeng objects-sdk executeVerb` runs a verb a type defines. `openeng objects-sdk discoverVerbs` lists
155
164
  the verbs available.
156
- 6. `openeng branches-sdk submitProposal` sends the branch for review. It names the branch by its
157
- `name` alone, the part of the ref after the slash.
165
+ 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.
158
167
 
159
168
  If a command is refused, the refusal names the field and its allowed kinds. Run
160
169
  `openeng help <module> <method>` again and compare.
161
170
 
171
+ ### Read relationships back after a write
172
+
173
+ Run `openeng help objects-sdk queryGraph` first. Take the project and object identifiers from
174
+ the confirmed write and replace the placeholders below. One start address and one hop step
175
+ read that object's connections, including the edges in the answer:
176
+
177
+ ```sh
178
+ openeng objects-sdk queryGraph --host https://api.openeng.io --selector '{"projectId":"<project-id>","ref":"<project-id>/<branch>"}' --input '{"kind":"graph","start":{"kind":"objects","objects":[{"projectId":"<project-id>","objectId":"<object-id>"}]},"steps":[{"depth":1}]}' --json
179
+ ```
180
+
181
+ Check the returned hops against the relationships you wrote. Use `findPaths` for paths across
182
+ several objects; read its help before supplying input.
183
+
184
+ ## Project ref rules
185
+
186
+ A project rule may protect `main` or refs under that project's identifier. A matching
187
+ `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.
189
+
190
+ Rule management is the person's workflow: they must hold `administer projects` on the project
191
+ and run these commands themselves. Never add or remove rules on their behalf, including to
192
+ get past a refusal.
193
+
194
+ 1. The person runs `openeng rules add --project <id> --pattern main --consequence merge-only`
195
+ to protect the project's trunk. The answer includes the rule's identifier. Adding the same
196
+ content again returns the existing rule.
197
+ 2. `openeng rules list --project <id>` reads the visible rules, their identifiers, patterns and
198
+ consequences; it needs `read` on the project.
199
+ 3. To lift one rule, the person runs `openeng rules remove --project <id> --rule-id <id>` with
200
+ the identifier from the list. An absent identifier or one from another project answers
201
+ `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.
203
+
204
+ ## Organisation rules, refs, locks and agent ceilings
205
+
206
+ These protections are managed by the person. Never change rules, refs or locks yourself,
207
+ including to get past a refusal. Read their current state and ask the person to make a change.
208
+ Each command's `--help` names the person's capability. A `not-permitted` refusal carries no
209
+ capability; read the help line before asking the person to seek permission.
210
+
211
+ - The person uses the rules commands above with `--organisation` instead of `--project <id>`
212
+ for organisation rules, for example
213
+ `openeng rules add --organisation --pattern release-v1 --consequence merge-only`.
214
+ Choose exactly one flag. `--organisation` takes no value and uses the attached organisation.
215
+ `openeng rules list --organisation` reads the rules;
216
+ `openeng rules remove --organisation --rule-id <id>` removes one by its identifier.
217
+ 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
220
+ `openeng org-refs mark-read-only --name <name>`, or deletes a writable one with
221
+ `openeng org-refs delete --name <name>`. Names are single segments, such as `release-v1`.
222
+ Creating, deleting and marking need `administer projects` in the attached organisation;
223
+ listing needs `read`.
224
+ - The person sets or lifts an object's lock with
225
+ `openeng locks set --project <id> --ref <ref> --object <objectId> --lock <none|merge-only|frozen>`.
226
+ `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.
229
+ - `openeng ceiling show --project <id>` reads the maximum agent role. The person sets it with
230
+ `openeng ceiling set --project <id> --ceiling <contributor|maintainer>`.
231
+ Showing needs `read`; setting needs `administer projects` on the selected project.
232
+
233
+ ## Protection refusals
234
+
235
+ When a command returns one of these rules, follow its action and do not repeat the same request:
236
+
237
+ - `immutable`: the type forbids changing or deleting the record on every ref. Leave it unchanged.
238
+ - `owned`: a connected system alone writes the record. Ask that system to make the change.
239
+ - `frozen`: someone with the lock capability must lift the lock. Ask that person; do not try a
240
+ different ref.
241
+ - `protected`: a rule allows the record to change only through a merge from a branch. Make the
242
+ 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
246
+ person can run `openeng schema-update request --ref <ref>` to record a request, then
247
+ `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;
250
+ showing reads only the requester's records in the token organisation and needs no project read
251
+ access. A branch whose name contains `/` cannot request or show a schema update today.
252
+ - `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.
254
+
162
255
  ## 4. Link to a page
163
256
 
164
257
  To give the person a page, run `openeng link` and hand them the address it prints; never write a path
@@ -170,6 +263,15 @@ project. `openeng link ontology --ref <ref>` and `openeng link change-set --ref
170
263
  project, and `openeng link organisation-page <page>` takes neither flag. The organisation is the one
171
264
  your session is attached to.
172
265
 
266
+ Every kind with `--ref`, including `ontology` and `change-set`, takes `main` or
267
+ `<projectId>/<branch>`, the ref the platform returns. A bare branch name or change-set id is
268
+ refused by `openeng link`. Before printing, the command reads the ref and the page's own subject;
269
+ a subject it cannot find is a refusal with a reason and no printed address.
270
+
271
+ An **App** is an organisation entity with its own pages and drafts, linked by `openeng link app`.
272
+ An **App view** is a type's collection content in `presentationBindings.views.app`, root `AppBody`,
273
+ and cannot be linked by `link app`.
274
+
173
275
  ## 5. Show data to the person
174
276
 
175
277
  The CLI draws nothing. Read the `--json` output of a query or a read and draw it yourself, as a
@@ -209,10 +311,10 @@ The order, from no connection to a first imported document:
209
311
  `succeeded` or `failed`.
210
312
  5. `openeng connector revoke <connection>` ends the connection.
211
313
 
212
- Mirrored objects are read-only in practice: the next import sets back a person's change to a
213
- mirrored property and counts it `overwritten`. The next import also creates a deleted mirrored
214
- object again, with a new identifier, and counts it `created`; links people made to the old object
215
- are gone. Do not write to a mirror project expecting the change to stay.
314
+ The connected system alone writes records of its owned types. A person's write is refused as
315
+ `owned`. People put their own information in separate rows and link those rows to the mirrored
316
+ records. The importer counts updates to mirrored properties as `overwritten`. If a mirrored
317
+ record is absent, the importer creates it with a new identifier and counts it as `created`.
216
318
 
217
319
  Refusals you will meet, with what each means and what to do:
218
320