@openengio/cli 0.0.0-stage → 0.23.3
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/LICENSE +202 -0
- package/README.md +326 -2
- package/THIRD-PARTY-NOTICES.md +235 -0
- package/bin/public/openeng.js +10528 -0
- package/package.json +21 -4
- package/skill/build-ui/SKILL.md +132 -0
- package/skill/conventions/SKILL.md +197 -0
- package/skill/demo/SKILL.md +112 -0
- package/skill/new-use-case/SKILL.md +132 -0
- package/skill/openeng/SKILL.md +238 -0
- package/skill/playbooks/engineering-requirements.md +121 -0
- package/skill/playbooks/product-lifecycle.md +115 -0
- package/skill/playbooks/project-management.md +100 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
package/README.md
CHANGED
|
@@ -1,3 +1,327 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @openengio/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`openeng` is the platform's command-line client. It signs a person in through the browser, stores the
|
|
4
|
+
session, and calls the platform's host. It runs on Node 22 and has no argument-parser dependency
|
|
5
|
+
(`node:util`'s `parseArgs` serves because every command takes the same few flags).
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
Install the public npm package:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
npm install -g @openengio/cli
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Upgrading from `@benjaminfh/oe2`: first run the earlier package's `logout` command, so its stored
|
|
16
|
+
session does not stay on this machine; then uninstall it and install `@openengio/cli`. The command
|
|
17
|
+
is now `openeng`, the environment variables are
|
|
18
|
+
`OPENENG_HOST`, `OPENENG_SIGN_IN_ORIGIN` and `OPENENG_SESSION_STORE`, and you sign in again once
|
|
19
|
+
with `openeng login`.
|
|
20
|
+
|
|
21
|
+
`openeng` has no host built in. The production host is `https://api.openeng.io`. Pass `--host
|
|
22
|
+
https://api.openeng.io` to a command, or set `OPENENG_HOST=https://api.openeng.io` once to make it the
|
|
23
|
+
default. An agent starts with `openeng skill`, which prints how to work with the platform.
|
|
24
|
+
|
|
25
|
+
`openeng --version` prints the published version, `0.<protocol>.<patch>`. `openeng organisations` and
|
|
26
|
+
`openeng orgs` run the commands of `openeng org`, and `openeng project` runs the commands of `openeng projects`.
|
|
27
|
+
|
|
28
|
+
`openeng help <command words>` prints one command's help, with or without the positional arguments the
|
|
29
|
+
command takes: a description (`does:`), an example and the shape of its output. `openeng help <group>`,
|
|
30
|
+
such as `openeng help connector`, lists the group's commands. Words that name no command are refused
|
|
31
|
+
with the nearest commands.
|
|
32
|
+
|
|
33
|
+
The package version is `0.<protocol>.<patch>`: its middle number is the host protocol it speaks.
|
|
34
|
+
The installed package contains the bundled command and the skill. It carries no runtime dependencies.
|
|
35
|
+
|
|
36
|
+
## Commands
|
|
37
|
+
|
|
38
|
+
| command | what it does | host calls |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| `openeng login [--no-open]` | binds a loopback listener, opens the browser at the sign-in address (or prints it with `--no-open`), redeems the returned code once and stores the session | one (`redeem`) |
|
|
41
|
+
| `openeng logout` | refreshes first when the access token has expired, calls `logout`, deletes the stored session whatever the host answered | one, two with an expired token |
|
|
42
|
+
| `openeng whoami` | prints the principal, host, store and expiry of the stored session, and the client's protocol version (`protocolVersion` under `--json`); never a token | none |
|
|
43
|
+
| `openeng org list` | lists the organisations the signed-in person holds a live grant in; needs no attachment | one |
|
|
44
|
+
| `openeng org attach <id>` | attaches the session to the organisation, and stores the access token the host answers with the organisation's identifier and name, beside the session and under the same host key; needs no attachment | one |
|
|
45
|
+
| `openeng org create --name <name> [--idempotency-key <key>]` | creates an organisation without an attachment; makes one host call, and prints a minted idempotency key on standard error when none is supplied | one |
|
|
46
|
+
| `openeng org detach` | detaches the session, and stores the access token the host answers with a null organisation; refused while the session has none | one |
|
|
47
|
+
| `openeng org current` | prints the organisation the stored session is attached to, or none (`{ "organisation": null }` under `--json`); sends no request | none |
|
|
48
|
+
| `openeng projects list` | lists the projects the signed-in person may list | one |
|
|
49
|
+
| `openeng demo seed --project <id> [--size standard\|full]` | plays a generic open-cycle gas turbine plant into a project the person may list; `standard` is the default size, and a repeat completes what is left | one listing, one catalogue read, four to publish the types when they are not yet published, then one per object and edge |
|
|
50
|
+
| `openeng link <explore\|branch-diff\|project> --project <id> --ref <ref>`, `openeng link <ontology\|change-set> --ref <ref>`, `openeng link <object\|type\|proposal\|app> <identifier> --project <id> --ref <ref>`, `openeng link app-page <appKey> <pageKey> --project <id> --ref <ref>`, `openeng link app-draft <appKey> --ref <ref>`, `openeng link organisation-page <page>` | prints the address of a page of the web application: the host's web origin joined to the page's path, built for the attached organisation; `--json` answers `{ link }`; a flag the page does not read is refused (exit 2) before any call, and so is a host with no web origin configured; `openeng link --help` prints every form | one (`readWebOrigin`) |
|
|
51
|
+
| `openeng types draft open` | opens a change set on the attached organisation's namespace | one |
|
|
52
|
+
| `openeng projects create --name <text>` | creates a project in the organisation the session is attached to, under a minted idempotency key | one |
|
|
53
|
+
| `openeng types list --project <id>` | lists the project's published types | one |
|
|
54
|
+
| `openeng types draft current` | the attached organisation's open change set, or none | one |
|
|
55
|
+
| `openeng types draft show --change-set <id> [--project <id>]` | the change set's revision and each prospective type's full definition; with `--project`, the delta per type and per field instead (added or changed, the version before and after, each changed field's before and after), and `--json` answers `{ revision, changes, delta }` (with `railGroups` where the change set holds a group change); a line `rail groups <json array>` lists the change set's groups where it holds any; a project whose catalogue listing (category, key and version) is not the change set's is refused (exit 2) before any diff | one; two with `--project` |
|
|
56
|
+
| `openeng types export --project <id>` | prints the project's published types as one JSON object keyed by type key, each the first prospective version of an edit (the next version number, none of the host's bookkeeping); redirect it to a file and edit it for `openeng types draft revise --from`; on an empty catalogue it still prints `{}` and exits 0, with the standard-error note `no published types; start from the example in openeng help ontology-sdk reviseChangeSet` | one |
|
|
57
|
+
| `openeng types draft state --change-set <id>` | whether the change set is open, accepted or discarded | one |
|
|
58
|
+
| `openeng types draft revise --change-set <id> --revision <token> --from <file> [--rail-groups <json>]` | replaces the change set's delta with the JSON object in the file, keyed by type key; a type's rail placement is `presentationBindings.rail` inside its document; `--rail-groups` carries the organisation's whole list of rail groups as a JSON array of strings, and without it the change set keeps the groups its last revision held; a file that is unreadable, not JSON or not an object, or a flag that is not a JSON array of strings, is refused (exit 2) before any call; the host validates the delta | one |
|
|
59
|
+
| `openeng types draft validate --change-set <id> --revision <token>` | the host's violations for that revision, printed with their count; exits 4 when there is one or more and 0 when there are none, so a script can gate `accept` on the exit code | one |
|
|
60
|
+
| `openeng types draft discard --change-set <id>` | discards the change set | one |
|
|
61
|
+
| `openeng types draft accept --change-set <id> --revision <token>` | publishes the change set's types at the revision the person reviewed, under a minted idempotency key | one |
|
|
62
|
+
| `openeng skill [<topic> \| playbook <name>]` | prints the main skill and lists topics, or prints one bundled topic; needs no host and no session | none |
|
|
63
|
+
|
|
64
|
+
An object type's `subscriptionRoles` field declares which roles it admits: owner, approver or watcher.
|
|
65
|
+
Owner is limited to one; approver and watcher may have optional maxima. Without the field, only
|
|
66
|
+
watchers are admitted.
|
|
67
|
+
|
|
68
|
+
## The connector commands
|
|
69
|
+
|
|
70
|
+
A connection imports an Onshape account's documents into a mirror project of its own. Every
|
|
71
|
+
connector command acts with the signed-in person's user token, so it can do what that person may,
|
|
72
|
+
and it needs the organisation the session is attached to. Each command's `--help` names the
|
|
73
|
+
capability it needs.
|
|
74
|
+
|
|
75
|
+
Everyone with access to this project sees every document this Onshape account can see.
|
|
76
|
+
|
|
77
|
+
`openeng connector create` prints that sentence, on standard error, before it makes any call.
|
|
78
|
+
`openeng connector set-credential` prints it again with the account identity the key resolved to.
|
|
79
|
+
|
|
80
|
+
| command | what it does | what the caller must hold |
|
|
81
|
+
|---|---|---|
|
|
82
|
+
| `openeng connector create --system onshape --stack <stack> --name <text> [--company <id>] [--team <id> \| --owner <id>] [--label <text>]` | creates the connection, its mirror project and its service identity, then drafts the connector's types as a change set in the same request; `--name` names the mirror project; `--stack` is the Onshape stack label, the host-name label joined to the suffix, as in `cad`; `--team` or `--owner` limits the import to that team's or owner's documents, and with neither the company's documents are imported, and `--company` is then required and must be the company's own identifier, not a user's, or the command is refused (exit 2) before any call; `--team` with `--owner` is refused (exit 2) before any call. The answer says whether the types were drafted, and if not, which rule stopped it; the connection exists either way | `administer projects` and `administer service identities` in the organisation, which the `owner` role holds |
|
|
83
|
+
| `openeng connector set-credential <connection>` | asks for the Onshape access key and secret key at a terminal prompt with nothing echoed, has the host check them against Onshape, and stores them; no flag or environment variable carries a key, and with no terminal it refuses before any call. Backspace deletes a character, a paste of both keys with a line ending between them fills both prompts, and Control-C or Control-D cancels with a refusal that says no keys were set. Setting it again replaces the stored credential. It prints the Onshape account the key belongs to and the time it was set | `administer projects` in the organisation |
|
|
84
|
+
| `openeng connector draft-types <connection>` | drafts the connector's types as a change set for a person to review, or answers that they are already approved or that a change set is open; use it for a connection whose drafting failed at create, and after a connector update | `administer types` in the organisation, and read on the mirror project |
|
|
85
|
+
| `openeng connector run <connection>` | starts an import run and prints its identifier once its row has committed; the run refuses while the connector's types are not approved | `merge` on the mirror project |
|
|
86
|
+
| `openeng connector runs <connection>` | lists the connection's runs, newest first: state, start and finish times, whether it was complete, the counts (created, updated, unchanged, withdrawn, carried, overwritten) and, for a failed run, its failure kind and fixed text | read on the mirror project |
|
|
87
|
+
| `openeng connector revoke <connection>` | revokes the connection: its running runs end as failed and its service identity can no longer act | `administer projects` and `administer service identities` in the organisation |
|
|
88
|
+
|
|
89
|
+
`<connection>` is the connection identifier that `create` prints.
|
|
90
|
+
|
|
91
|
+
### From no connection to a first imported document
|
|
92
|
+
|
|
93
|
+
1. `openeng connector create ...`, by an organisation owner. Note the connection identifier.
|
|
94
|
+
2. `openeng connector set-credential <connection>`, by a person who holds `administer projects`, at a
|
|
95
|
+
terminal.
|
|
96
|
+
3. A person who holds `administer types` reviews the drafted change set with `openeng types draft show
|
|
97
|
+
--change-set <id> --project <mirror project id>` and accepts it with `openeng types draft accept
|
|
98
|
+
--change-set <id> --revision <token>`. The change set identifier is in `create`'s answer, or in
|
|
99
|
+
`openeng types draft current`. Until it is accepted, a run refuses with `types-not-approved`.
|
|
100
|
+
4. `openeng connector run <connection>`, by a person who holds `merge` on the mirror project.
|
|
101
|
+
5. `openeng connector runs <connection>` until the run's state is `succeeded` or `failed`.
|
|
102
|
+
|
|
103
|
+
### The known gap
|
|
104
|
+
|
|
105
|
+
The next import sets back a person's change to a mirrored property and counts it `overwritten`.
|
|
106
|
+
The next import also creates a deleted mirrored object again, with a new identifier, and counts it
|
|
107
|
+
`created`; links people made to the old object are gone. Mirrored objects are therefore read-only in practice until write-back exists.
|
|
108
|
+
|
|
109
|
+
## The attached organisation
|
|
110
|
+
|
|
111
|
+
A CLI session begins unattached: `openeng login` never attaches. A person runs `openeng org list`, then
|
|
112
|
+
`openeng org attach <id>`, once. If the list is empty, `openeng org create --name <name>` creates an
|
|
113
|
+
organisation that can then be attached. The organisation is stored with the
|
|
114
|
+
session (`StoredEntry.organisation`, an identifier and a name, or null), a refresh keeps it, and
|
|
115
|
+
`openeng login` and `openeng logout` replace or delete the whole entry. The host decides what a call may
|
|
116
|
+
reach; the stored organisation decides only what the CLI prints and whether it runs a command.
|
|
117
|
+
|
|
118
|
+
- **The gate.** Whether a command runs without an organisation comes from its `organisation` field:
|
|
119
|
+
hand-written commands marked `none` run unattached; generated commands run unattached when their
|
|
120
|
+
route subject is `platform` or `creating`. Other commands refuse with "not attached to an
|
|
121
|
+
organisation" (exit 2) before they send a request. With no stored session at all, the command
|
|
122
|
+
answers that it is not signed in.
|
|
123
|
+
- **The scope echo.** The CLI passes no scope when the organisation gate read no organisation
|
|
124
|
+
(for every command whose `organisation` is `none` and every hostless command), and for `org
|
|
125
|
+
detach`. Other commands print when the host answers them, `org: <name> (<id>)` first on standard error,
|
|
126
|
+
then ` · project: <id>` when `--project` or the selector's `projectId` named one, and
|
|
127
|
+
` · ref: <ref>` when the selector named one. No host call finds them.
|
|
128
|
+
- **`--json`.** The one value on standard output gains the same fields as `scope`:
|
|
129
|
+
`{ "organisation": { "id", "name" }, "project"?, "ref"? }`. An object value gains a `scope` key. A
|
|
130
|
+
value that is an array or null is wrapped as `{ "scope": {...}, "value": <the original> }`. A
|
|
131
|
+
failure the host did not answer carries no scope. A command with no scope has no `scope` field.
|
|
132
|
+
- **The hint.** Every `not-found` the host answers to a gated command prints, after the refusal,
|
|
133
|
+
"not found in organisation <name>: check that you are attached to the correct organisation (openeng org
|
|
134
|
+
current)", and one line more when the command named a ref: `ref forms: the trunk is the bare "main";
|
|
135
|
+
a branch is "<project id>/<name>"`. The hint goes to standard error with or without `--json`.
|
|
136
|
+
|
|
137
|
+
A command that reaches the host with a session whose access token has expired sends one `refresh`
|
|
138
|
+
first and then its own call. A command whose call is answered `unauthenticated` refreshes once and
|
|
139
|
+
sends the call once more.
|
|
140
|
+
|
|
141
|
+
## The agent skill
|
|
142
|
+
|
|
143
|
+
`skill/openeng/SKILL.md` is a Claude Code skill that tells an agent which commands to run and in what
|
|
144
|
+
order: sign in and orient, define types, write data, and show it. It names commands and never an
|
|
145
|
+
input shape; for a shape it sends the agent to `openeng help <module> <method>`. `openeng skill` prints it
|
|
146
|
+
and ends with the other topics and the command for each. It reads from the package relative to
|
|
147
|
+
the module, so it works from `dist`. Install it with:
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
mkdir -p ~/.claude/skills/openeng && openeng skill > ~/.claude/skills/openeng/SKILL.md
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`openeng skill` is answered before a host is parsed or a session store is chosen, so it runs on a
|
|
154
|
+
machine with no `OPENENG_HOST`. Its command receives only the topic words, which is how it cannot reach a host.
|
|
155
|
+
|
|
156
|
+
The topic list comes from the files in the bundled `skill/` folder. Print a topic with:
|
|
157
|
+
|
|
158
|
+
| command | when to read it |
|
|
159
|
+
|---|---|
|
|
160
|
+
| `openeng skill demo` | guiding a new person through a hands-on example in the app |
|
|
161
|
+
| `openeng skill new-use-case` | designing types for a new use case against the existing catalogue |
|
|
162
|
+
| `openeng skill build-ui` | laying out an object drawer or App view |
|
|
163
|
+
| `openeng skill conventions` | field meanings, direction, trees, views, the rail and versions |
|
|
164
|
+
| `openeng skill playbook engineering-requirements` | modelling requirements, verification and risk |
|
|
165
|
+
| `openeng skill playbook product-lifecycle` | modelling parts, revisions, manufacturing BOMs and changes |
|
|
166
|
+
| `openeng skill playbook project-management` | modelling work items, cycles, milestones and engineering links |
|
|
167
|
+
|
|
168
|
+
`openeng help skill` and `openeng skill --help` list the topics. Unknown topics are refused with that
|
|
169
|
+
list (exit 2). The material requirements planning draft is held back and is not shipped.
|
|
170
|
+
With `--json`, the main command prints `{ "skill": "...", "topics": ["..."] }`; a topic prints
|
|
171
|
+
`{ "skill": "..." }`, and help uses the CLI's usual `{ "usage": ["..."] }` shape.
|
|
172
|
+
The `build-ui` guide ships as prose; the in-app agent's generated `author-views` reference is
|
|
173
|
+
not yet available through the CLI.
|
|
174
|
+
|
|
175
|
+
## The generated commands
|
|
176
|
+
|
|
177
|
+
Beside the commands above, `openeng` has one command for each route the SDK modules export an entry
|
|
178
|
+
for, built when the process starts from those entries (`OBJECTS_ROUTE_ENTRIES`,
|
|
179
|
+
`BRANCHES_ROUTE_ENTRIES`, `ADMIN_ROUTE_ENTRIES`, `AGENTS_ROUTE_ENTRIES` and
|
|
180
|
+
`ONTOLOGY_ROUTE_ENTRIES`). No list of commands, help text or flags is kept by hand.
|
|
181
|
+
|
|
182
|
+
- **Naming.** `openeng <module> <method>`, the module as its package is named (`objects-sdk`) and the
|
|
183
|
+
method the route's own name (`openeng objects-sdk readObject`).
|
|
184
|
+
- **Which routes.** Every entry whose `carriesCredential` is false and whose `module` is not
|
|
185
|
+
`sdk-core`. A route whose request or answer holds a `Credential` (`issueServiceCredential`,
|
|
186
|
+
`setModelConfiguration`, and the core's `redeem`, `refresh`, `serviceCredential` and
|
|
187
|
+
`signInCallback`) has no generated command, so no generated command takes a secret in its
|
|
188
|
+
arguments or prints one. The core's own routes (`health`, `signInStart`, `logout` and the
|
|
189
|
+
credential ones) are not a module's methods and have none either.
|
|
190
|
+
- **Flags.** `--selector <json>` (required where the route takes a selector, refused where it takes
|
|
191
|
+
none); `--input <json>`, `--input -` (standard input) or `--input-file <path>`, one of them, a JSON
|
|
192
|
+
object, `{}` when none is given; `--idempotency-key <key>` on an idempotent route, where a key is
|
|
193
|
+
minted and printed on standard error when none is given, and refused on a route that is not
|
|
194
|
+
idempotent. A malformed or missing flag is the client's own refusal (exit 2) naming the flag.
|
|
195
|
+
- **Correlation.** A route whose input schema lists `correlation` as required (`mutate`,
|
|
196
|
+
`mutateBatch`, `executeVerb`, `createBranch`, `merge`, `disposeRef`, `abandonBranch`) gets
|
|
197
|
+
`correlation: { kind: "mint" }` when the input has no `correlation` key, and the command prints
|
|
198
|
+
`correlation: minted by the host` on standard error. A `correlation` the person gave is sent as
|
|
199
|
+
given, whatever it holds, and the host's refusal judges it. The condition is read from the
|
|
200
|
+
schema, never from the route's idempotency.
|
|
201
|
+
- **Help.** `openeng <module> <method> --help` prints the route, its method and path, the module, the
|
|
202
|
+
capability, the admitted token kinds, whether it is idempotent, its selector form and what it
|
|
203
|
+
does, each read from the entry; then `input fields:` and, for a route with a selector,
|
|
204
|
+
`selector keys:`, read from the route's schemas, and `example input:`, the route's generated
|
|
205
|
+
example on one line. Map value fields and the members of a top-level `oneOf` are listed. A field
|
|
206
|
+
is one line, `name: required|optional; <type>`; a `oneOf` whose members each pin the same
|
|
207
|
+
discriminator property to a distinct value shows those values, then one line per member with its
|
|
208
|
+
own fields. Nested object, array and map fields are listed to a depth; beyond that, a line says
|
|
209
|
+
fields are nested deeper.
|
|
210
|
+
`openeng help` prints the global usage and `openeng help <module> <method>` prints that command's help,
|
|
211
|
+
as `--help` does; neither needs a host or a session. A hand-written command with no help text
|
|
212
|
+
prints its own usage line for `--help`.
|
|
213
|
+
- **Streamed routes** (`openeng agents-sdk sendMessageStreamed`, `answerPlanStreamed`) print one JSON line
|
|
214
|
+
per event on standard output, after the run ends, and need a `unix:` host.
|
|
215
|
+
- **Calls.** One host call; two when the session had expired. A streamed command holds one
|
|
216
|
+
connection.
|
|
217
|
+
|
|
218
|
+
## Flags and environment
|
|
219
|
+
|
|
220
|
+
Every command takes `--json`, which prints one JSON value on standard output in place of text.
|
|
221
|
+
The flags a command reads, named in its usage above, are `--project`, `--name`, `--change-set`,
|
|
222
|
+
`--revision`, `--from`, `--size`, `--idempotency-key`, `--rail-groups`, and, for
|
|
223
|
+
`openeng connector create`, `--system`, `--stack`, `--company`, `--team`, `--owner` and `--label`; a
|
|
224
|
+
command that needs one it was not given refuses before any call (exit 2).
|
|
225
|
+
|
|
226
|
+
| setting | flag | what it is |
|
|
227
|
+
|---|---|---|
|
|
228
|
+
| `OPENENG_HOST` | `--host` | `unix:<absolute socket path>` or an `https` origin. Every other form, `http:` included, is refused before any request (exit 2). The flag wins. |
|
|
229
|
+
| `OPENENG_SIGN_IN_ORIGIN` | `--sign-in-origin` | for a `unix:` host, the network host's `http://127.0.0.1:<port>` or `http://[::1]:<port>` origin. Only the browser visits it; no credential is sent to it. Any non-loopback origin is refused. The flag wins. |
|
|
230
|
+
| `OPENENG_SESSION_STORE` | none | `file` selects the file store. Unset selects the platform's credential store where its tool answers, else the file store. Any other value is refused. |
|
|
231
|
+
| `XDG_CONFIG_HOME` | none | the configuration directory when it is an absolute path, else `~/.config`. |
|
|
232
|
+
|
|
233
|
+
`openeng` reads no other environment variable.
|
|
234
|
+
|
|
235
|
+
`openeng login` writes one waiting line to standard error while it waits for the browser, so under
|
|
236
|
+
`--json` standard output stays one JSON value. A loopback listener the system refuses to open, and a
|
|
237
|
+
session store that cannot be read, written or deleted, each print one line (exit 2) and no stack: the
|
|
238
|
+
listener line asks you to allow local loopback listeners and run `openeng login` again; the store line
|
|
239
|
+
names the store and the operation and ends with the next step, `openeng login` again, or `openeng org attach
|
|
240
|
+
<id>` again where the host had already switched the session. The line never holds the system's own
|
|
241
|
+
error text.
|
|
242
|
+
|
|
243
|
+
`openeng login` against an `https` host uses the same loopback sign-in as a socket host, with the host's
|
|
244
|
+
own origin as the sign-in origin. The sign-in uses PKCE: `openeng` mints a verifier, sends its S256
|
|
245
|
+
challenge with the request, and presents the verifier when it redeems the code, so a code redeems only
|
|
246
|
+
for the client that asked for it.
|
|
247
|
+
|
|
248
|
+
## Output and exit codes
|
|
249
|
+
|
|
250
|
+
Text goes to standard output on success and to standard error on every failure, with one
|
|
251
|
+
exception: the violations `openeng types draft validate` answers go to standard output with exit 4. A refusal the host
|
|
252
|
+
answered prints its kind or rule and class, then the refusal catalogue's meaning, then each next
|
|
253
|
+
option on its own line, naming the command for an option's read where `openeng` has one. When the text
|
|
254
|
+
is the refusal class's and not the rule's own, the output says so. With `--json` a refusal prints
|
|
255
|
+
its own fields with `explanation` and `explains` as the SDK attached them. The client's own refusals
|
|
256
|
+
(exit 2) and a transport failure with no answer (exit 7) carry no catalogue entry and print their own
|
|
257
|
+
message. An error that is not a transport failure prints as an internal failure with exit 7, and its stack
|
|
258
|
+
follows on standard error, with `--json` too, so standard output stays one JSON value.
|
|
259
|
+
|
|
260
|
+
A refusal that arrived in an envelope ends with one line `reference: <correlation id>`, the id the
|
|
261
|
+
host stamped on the envelope, and the `--json` form carries it as a `reference` field. A refusal
|
|
262
|
+
the client builds itself, and an envelope that carries no id, print none. A result whose arm is
|
|
263
|
+
`refused` prints the `correlationId` its arm carries on the same line, and the `--json` form adds the
|
|
264
|
+
`reference` field beside the arm's own fields. The id is the envelope's
|
|
265
|
+
and not the `correlationId` that an `unknown-outcome`, `in-flight` or `internal` refusal carries in its
|
|
266
|
+
own fields, which stays in the first line.
|
|
267
|
+
|
|
268
|
+
An `invalid-request` that names a field prints `invalid-request: field <path>`. For a generated
|
|
269
|
+
command the path is resolved against the route's schemas (through a `oneOf` by the discriminator the
|
|
270
|
+
person sent, through a map by any key, and through an array by its indexed item); where it lands on a
|
|
271
|
+
`oneOf`, the text adds the allowed values of that field's discriminator and the command's `--help` line,
|
|
272
|
+
and `--json` adds those values beside
|
|
273
|
+
the refusal. A path that does not resolve prints the field alone.
|
|
274
|
+
|
|
275
|
+
An unknown outcome (exit 5) prints its correlation and the read that settles it. `openeng` never
|
|
276
|
+
repeats the operation. For a non-envelope answer with status 500 to 599, exit 5 says the operation
|
|
277
|
+
may or may not have taken effect. It settles with the minted idempotency key for a generated
|
|
278
|
+
command, or with `check what openeng <words> changes before sending it again` for a hand-written
|
|
279
|
+
command. A non-envelope 5xx answer to the session refresh instead exits 7 with
|
|
280
|
+
`refresh-unanswered`: the command was not sent. A retry with the same idempotency key can
|
|
281
|
+
retrieve a recorded outcome or attempt a call that never reached the host; an earlier outcome
|
|
282
|
+
is not guaranteed to exist.
|
|
283
|
+
|
|
284
|
+
A non-envelope answer with a status from 400 to 499, such as a proxy's or a wrong address's page, prints
|
|
285
|
+
one line naming the status, the reason phrase the host sent with it where there is one, and the
|
|
286
|
+
route, and says the request may not have reached the platform (exit 7), with no stack. Under
|
|
287
|
+
`--json` its `error.kind` is `host-answer-not-envelope`.
|
|
288
|
+
|
|
289
|
+
A connection failure before the request was written prints the host and system code, says the
|
|
290
|
+
request was not sent and nothing changed, and confirms that sending it again is safe (exit 7).
|
|
291
|
+
|
|
292
|
+
A refused result arm prints each conflict after the explanation, naming its property and current
|
|
293
|
+
committed envelope as JSON (`absent` when the property is absent), followed by each violation's
|
|
294
|
+
path and rule. Empty conflict and violation lists add no lines. With `--json`, both lists remain
|
|
295
|
+
in the result as the SDK answered them.
|
|
296
|
+
|
|
297
|
+
A protocol mismatch (exit 7) prints the client's protocol version, the addressed host and its
|
|
298
|
+
protocol version. When the host read this `openeng`'s protocol version, it asks you to install an `openeng`
|
|
299
|
+
built for that host. Otherwise it says the host did not read this `openeng`'s protocol version and names
|
|
300
|
+
the version it read, or `none`. The catalogue explanation also prints. Under `--json`, the refusal
|
|
301
|
+
carries the host's key as `host` and this client's version as `clientVersion`. The host's `versions`
|
|
302
|
+
are unchanged: `versions.client` is the version the host read, or null, and `versions.host` is the
|
|
303
|
+
host's version.
|
|
304
|
+
|
|
305
|
+
| exit code | meaning |
|
|
306
|
+
|---|---|
|
|
307
|
+
| 0 | success |
|
|
308
|
+
| 2 | the client's own refusal: configuration, host form, store, a missing flag |
|
|
309
|
+
| 3 | `unauthenticated`: not signed in, a sign-in that was cancelled, timed out or whose state differed, or a logout with nothing stored |
|
|
310
|
+
| 4 | a platform refusal (`refused`), a route result whose arm is `refused`, or the violations `openeng types draft validate` answers (printed on standard output) |
|
|
311
|
+
| 5 | `unknown-outcome`, from the host or from a transport that lost the answer; also a non-envelope answer with status 500 to 599 |
|
|
312
|
+
| 6 | `invalid-request`, `not-found` or `bound-exceeded` |
|
|
313
|
+
| 7 | `internal`, `in-flight`, `protocol-mismatch`, a transport failure with no answer, a non-envelope answer with status 400 to 499, or an internal failure of the client |
|
|
314
|
+
|
|
315
|
+
## Stores
|
|
316
|
+
|
|
317
|
+
The session of one host is stored under that host's key: `unix:` and the canonical absolute socket
|
|
318
|
+
path for a socket host, the origin for an `https` host. A read never falls back to another host's
|
|
319
|
+
entry. The stores:
|
|
320
|
+
|
|
321
|
+
- macOS: the keychain, through `security -i` with the command on standard input.
|
|
322
|
+
- Linux: `secret-tool store`, the secret on standard input.
|
|
323
|
+
- Otherwise, or with `OPENENG_SESSION_STORE=file`: one file per host in
|
|
324
|
+
`$XDG_CONFIG_HOME/openeng/sessions/` (else `~/.config/openeng/sessions/`), mode `0600` in a directory of
|
|
325
|
+
mode `0700`.
|
|
326
|
+
|
|
327
|
+
`openeng whoami` names the store in use.
|