@lotics/cli 0.86.1 → 0.87.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/README.md +0 -78
- package/dist/args.d.ts +0 -39
- package/dist/args.js +2 -83
- package/dist/args.test.js +0 -49
- package/dist/cli.js +1 -283
- package/dist/cli_dispatch.test.js +43 -109
- package/dist/client.d.ts +34 -13
- package/dist/client.js +18 -12
- package/dist/src/cli.js +1620 -19314
- package/package.json +1 -1
- package/dist/package_commands.d.ts +0 -221
- package/dist/package_commands.js +0 -1007
- package/dist/package_commands.test.d.ts +0 -1
- package/dist/package_commands.test.js +0 -309
package/README.md
CHANGED
|
@@ -195,84 +195,6 @@ lotics ui link card --remove # finalize: PR + publish, then drop t
|
|
|
195
195
|
|
|
196
196
|
`app codegen` reads `package.json#lotics.queries` to decide which tables to put in `app_fields.ts`; widen the set with `package.json#lotics.codegen.tables` (an array of `tbl_…` ids) for tables the app only writes via workflows.
|
|
197
197
|
|
|
198
|
-
## Packages
|
|
199
|
-
|
|
200
|
-
A maintained, versioned package library: author once, install into many workspaces, upgrade per-workspace. A package carries an app, content (knowledge docs and/or document templates), or both. **Nothing starts as a package** — build a bespoke app first (the `lotics app` loop above), then first-release it as a package when it proves worth distributing. Any org authors its own packages (publishing is owner-org-only); Lotics-backed packages carry the `official` badge. See `docs/packages.md` for the model.
|
|
201
|
-
|
|
202
|
-
```bash
|
|
203
|
-
# 1. Make the app distributable — first-release it as a package (one call: extract
|
|
204
|
-
# an alias-keyed contract, create the registry package, publish v1 from the
|
|
205
|
-
# deployed source + dist, pin the app as installation #1). Blocking findings
|
|
206
|
-
# (a hardcoded fld_/opt_ id in src/ or a workflow body, a button field) → 409.
|
|
207
|
-
lotics app publish # from the pulled app project (or: app publish app_...)
|
|
208
|
-
lotics app publish --rename item=deal -m "v1" # fix an auto-minted alias before v1 freezes it
|
|
209
|
-
|
|
210
|
-
# 2. Iterate IN PLACE — the origin app is the permanent working copy
|
|
211
|
-
lotics app pull app_... # the same loop as any app: pull, edit, dev
|
|
212
|
-
lotics app deploy -m "Add quote drawer" # commit a new app version
|
|
213
|
-
|
|
214
|
-
# 3. Release the next package version from the origin you are happy with
|
|
215
|
-
lotics app release -m "v2: adds deals" # preview (new/changed aliases + findings)
|
|
216
|
-
lotics app release -m "v2: adds deals" --yes # publish v2 + re-pin the origin
|
|
217
|
-
|
|
218
|
-
# Take it off the shelf (existing installations keep working + upgrading)
|
|
219
|
-
lotics app unpublish app_... [--undo] # by app id (resolves the package) or package id
|
|
220
|
-
|
|
221
|
-
# Operate installations (workspace admin). The high-traffic verbs are top-level
|
|
222
|
-
# (install / uninstall / upgrade); low-traffic ops live on `lotics package`.
|
|
223
|
-
lotics package show apg_... # registry metadata + version history (trust badge, yank)
|
|
224
|
-
lotics install apg_... --version 2 # scaffold + materialize + deploy + pin
|
|
225
|
-
lotics install apg_... --config heading="Ops board" # per-knob overrides over contract defaults
|
|
226
|
-
lotics package config app_... --set show_done=false # edit a live installation's config (partial merge)
|
|
227
|
-
lotics uninstall app_... [--archive-tables] # remove an installation; workflows stop firing
|
|
228
|
-
lotics package doctor app_... # version pin vs latest + drift + local edits (exit 1 on findings)
|
|
229
|
-
lotics upgrade app_... # preview, then apply (additive; overlay preserved)
|
|
230
|
-
lotics upgrade apg_... # APP package → FLEET: upgrade EVERY org installation (clean ones apply; findings skip, exit 1)
|
|
231
|
-
lotics upgrade app_... --resolve fields.deal.stage=recreate # resolve reported drift
|
|
232
|
-
lotics upgrade app_... --resolve queries.tasks=keep # consent for a local edit (or =revert)
|
|
233
|
-
lotics upgrade app_... --resolve template.quote=revert # a locally-edited template (clean ones auto-update; or =keep)
|
|
234
|
-
lotics upgrade app_... --resolve knowledge.playbook=apply # a bundled knowledge doc: apply|keep|archive|recreate|unbind
|
|
235
|
-
lotics upgrade app_... --resolve roles.approver=grp_... # re-point a LIVE package role at another group
|
|
236
|
-
lotics package yank apg_... 3 [--undo] # refuse new installs/upgrades of a broken version
|
|
237
|
-
lotics package eject app_... # one-way: sever the package link
|
|
238
|
-
lotics workspace doctor # dangling schema references across the workspace (exit 1 on findings)
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
After the first publish **the origin is the master** — develop it in its workspace (`app pull` / `app deploy` / `app workflow set` / table tools), and `lotics app release` snapshots each version. Its **binding-aware re-extract** keeps aliases stable through the origin's current binding, so re-extraction never churns the upgrade diff (which is why extract-again is the loop, not a hazard). Release is also the **bundled-knowledge declaration surface**: run from the app project, the manifest's `lotics.knowledge` (`[{alias,doc_id}]`) re-declares which docs the package bundles — an alias added ships as a new doc, a bound alias dropped surfaces to consumers as `removed` (archive|keep), a present one re-snapshots; a bare id from elsewhere reconstructs the current corpus from the pin (never drops it). So a published app package evolves its bundled docs across versions without ejecting.
|
|
242
|
-
|
|
243
|
-
### Content packages
|
|
244
|
-
|
|
245
|
-
A **content** package ships **knowledge docs and/or document templates** — no app, just the artifacts. Knowledge is the reference corpus an agent looks up by name; templates are standalone document templates. Content comes two ways: bundled *with an app* (installing the app delivers its agents' docs) or as a standalone content package (a versioned corpus). Install delivers, upgrade refreshes — preserving stable `kdc_`/`tmpl_` ids + a version snapshot per change. See `docs/packages.md` § Content.
|
|
246
|
-
|
|
247
|
-
```bash
|
|
248
|
-
# Publish a content package from a SET of live knowledge docs + templates — the
|
|
249
|
-
# publish_content tool (there is no content-package project). Aliases + shas are
|
|
250
|
-
# computed from live content; v1 is created and the origin workspace is pinned.
|
|
251
|
-
lotics run publish_content '{"name":"My SOPs","knowledge_doc_ids":["kdc_..."],"template_ids":["tmpl_..."]}'
|
|
252
|
-
|
|
253
|
-
# Cut the next version after editing those docs/templates in place (add "dry_run":true to preview the diff)
|
|
254
|
-
lotics run release_content '{"package_id":"apg_...","changelog":"v2: revised SOPs"}'
|
|
255
|
-
|
|
256
|
-
# Install into a workspace (a same-named local DOC collides — consent with --bind-to; templates never collide)
|
|
257
|
-
lotics install apg_... # app OR content, shape-branched
|
|
258
|
-
lotics install apg_... --bind-to policy=kdc_... # adopt an existing doc as package-managed
|
|
259
|
-
|
|
260
|
-
# Discover installed content (each row leads with the PACKAGE id)
|
|
261
|
-
lotics package list-content # package id · package · version (standalone content installs)
|
|
262
|
-
|
|
263
|
-
# Refresh this workspace's content install — addressed by PACKAGE id (one install per
|
|
264
|
-
# package per workspace, so the package id is the address; one gate over docs + templates)
|
|
265
|
-
lotics upgrade apg_... # CONTENT package → preview, then apply (this workspace's install)
|
|
266
|
-
lotics upgrade apg_... --resolve knowledge.policy=apply # a doc: apply|keep|archive|recreate|unbind
|
|
267
|
-
lotics upgrade apg_... --resolve template.quote=revert # a locally-edited template: revert|keep (clean ones auto-update)
|
|
268
|
-
lotics upgrade apg_... --apply-all # accept upstream for every doc + template (OVERWRITES local edits)
|
|
269
|
-
lotics uninstall apg_... --keep-content # remove the pin; keep docs + templates (default archives them)
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
A package's knowledge can also arrive **bundled with an app**. Upgrading such an app (`lotics upgrade <app_id>`) previews its bundled-knowledge changes alongside the plan and resolves them in the SAME namespaced grammar — `--resolve knowledge.<alias>=apply|keep|archive|recreate|unbind` (the flags pass to the server verbatim; no routing, no ambiguity), `--bind-to` consents an added-doc collision, `--apply-all` takes the package's version for every consent-requiring doc.
|
|
273
|
-
|
|
274
|
-
To package the knowledge an existing app's agents route to, declare it in the app project's `package.json#lotics.knowledge` (`[{ alias, doc_id }]`, + `lotics.knowledge_expects` for docs the agents assume but the package doesn't own), then `lotics app publish` from the app project — it forwards the declaration, and the docs ship with the package.
|
|
275
|
-
|
|
276
198
|
## SDK
|
|
277
199
|
|
|
278
200
|
```typescript
|
package/dist/args.d.ts
CHANGED
|
@@ -36,45 +36,6 @@ export declare function parseArgs(argv: string[]): {
|
|
|
36
36
|
printCreated: boolean;
|
|
37
37
|
/** `--cleanup`: also delete the harvested created records (records only). */
|
|
38
38
|
cleanup: boolean;
|
|
39
|
-
/**
|
|
40
|
-
* `--version <n>`: a package version number (`lotics install … --version 2`).
|
|
41
|
-
* Distinct from the boolean `version` flag below: `--version` followed by an
|
|
42
|
-
* integer captures the number; a bare `--version` (or `-v`) prints the CLI
|
|
43
|
-
* version. No other command takes a numeric value after `--version`, so the
|
|
44
|
-
* peek is unambiguous.
|
|
45
|
-
*/
|
|
46
|
-
packageVersion?: string;
|
|
47
|
-
/**
|
|
48
|
-
* `--resolve <key>=recreate|revert|keep|<id>` (repeatable): upgrade
|
|
49
|
-
* resolutions — drift entries (`<namespace.alias>`) take `recreate` or an
|
|
50
|
-
* existing id; modified-core entries (`<kind>.<alias>`) take `revert` or
|
|
51
|
-
* `keep`. For a standalone KNOWLEDGE upgrade, `<alias>=apply|keep|archive|
|
|
52
|
-
* recreate|unbind`.
|
|
53
|
-
*/
|
|
54
|
-
resolve: string[];
|
|
55
|
-
/**
|
|
56
|
-
* `--bind-to <alias>=<kdc_id>` (repeatable): consent to adopt an existing
|
|
57
|
-
* same-named doc as package-managed — resolves a knowledge name collision at
|
|
58
|
-
* install / a created-doc collision at upgrade.
|
|
59
|
-
*/
|
|
60
|
-
bindTo: string[];
|
|
61
|
-
/** `--keep-content` (`package uninstall` of a content install): retain the package-bound docs instead of archiving them. */
|
|
62
|
-
keepContent: boolean;
|
|
63
|
-
/** `--apply-all` (knowledge `package upgrade`): accept the package's version for every consent entry. */
|
|
64
|
-
applyAll: boolean;
|
|
65
|
-
/**
|
|
66
|
-
* `--rename <old>=<new>` (repeatable, `lotics app publish`): fix an auto-minted
|
|
67
|
-
* alias before the package's v1 contract freezes it.
|
|
68
|
-
*/
|
|
69
|
-
rename: string[];
|
|
70
|
-
/** `--config key=value` (repeatable): per-knob config overrides at `package install`. */
|
|
71
|
-
config: string[];
|
|
72
|
-
/** `--set key=value` (repeatable): per-knob config edits at `package config`. */
|
|
73
|
-
set: string[];
|
|
74
|
-
/** `--archive-tables` (`package uninstall` of an app install): also archive the scaffolded tables. */
|
|
75
|
-
archiveTables: boolean;
|
|
76
|
-
/** `--undo`: reverse a `package retire` / `package yank`. */
|
|
77
|
-
undo: boolean;
|
|
78
39
|
version: boolean;
|
|
79
40
|
help: boolean;
|
|
80
41
|
};
|
package/dist/args.js
CHANGED
|
@@ -28,16 +28,6 @@ export function parseArgs(argv) {
|
|
|
28
28
|
yes: false,
|
|
29
29
|
printCreated: false,
|
|
30
30
|
cleanup: false,
|
|
31
|
-
packageVersion: undefined,
|
|
32
|
-
resolve: [],
|
|
33
|
-
bindTo: [],
|
|
34
|
-
keepContent: false,
|
|
35
|
-
applyAll: false,
|
|
36
|
-
rename: [],
|
|
37
|
-
config: [],
|
|
38
|
-
set: [],
|
|
39
|
-
archiveTables: false,
|
|
40
|
-
undo: false,
|
|
41
31
|
version: false,
|
|
42
32
|
help: false,
|
|
43
33
|
};
|
|
@@ -102,81 +92,10 @@ export function parseArgs(argv) {
|
|
|
102
92
|
case "--cleanup":
|
|
103
93
|
flags.cleanup = true;
|
|
104
94
|
break;
|
|
105
|
-
case "--resolve": {
|
|
106
|
-
const value = argv[++i];
|
|
107
|
-
if (value === undefined || value.startsWith("-")) {
|
|
108
|
-
throw new Error("--resolve requires a value: <key>=recreate|revert|keep or <key>=<existing_id> (drift: <namespace.alias>; modified core: <kind>.<alias>).");
|
|
109
|
-
}
|
|
110
|
-
flags.resolve.push(value);
|
|
111
|
-
break;
|
|
112
|
-
}
|
|
113
|
-
case "--bind-to": {
|
|
114
|
-
const value = argv[++i];
|
|
115
|
-
if (value === undefined || value.startsWith("-")) {
|
|
116
|
-
throw new Error("--bind-to requires a value: <alias>=<kdc_id>.");
|
|
117
|
-
}
|
|
118
|
-
flags.bindTo.push(value);
|
|
119
|
-
break;
|
|
120
|
-
}
|
|
121
|
-
case "--keep-content":
|
|
122
|
-
flags.keepContent = true;
|
|
123
|
-
break;
|
|
124
|
-
case "--apply-all":
|
|
125
|
-
flags.applyAll = true;
|
|
126
|
-
break;
|
|
127
|
-
case "--rename": {
|
|
128
|
-
const value = argv[++i];
|
|
129
|
-
if (value === undefined || value.startsWith("-")) {
|
|
130
|
-
throw new Error("--rename requires a value: old=new (an alias to rename before v1 freezes it).");
|
|
131
|
-
}
|
|
132
|
-
flags.rename.push(value);
|
|
133
|
-
break;
|
|
134
|
-
}
|
|
135
|
-
case "--config": {
|
|
136
|
-
const value = argv[++i];
|
|
137
|
-
if (value === undefined || value.startsWith("-")) {
|
|
138
|
-
throw new Error("--config requires a value: key=value (repeatable).");
|
|
139
|
-
}
|
|
140
|
-
flags.config.push(value);
|
|
141
|
-
break;
|
|
142
|
-
}
|
|
143
|
-
case "--set": {
|
|
144
|
-
const value = argv[++i];
|
|
145
|
-
if (value === undefined || value.startsWith("-")) {
|
|
146
|
-
throw new Error("--set requires a value: key=value (repeatable).");
|
|
147
|
-
}
|
|
148
|
-
flags.set.push(value);
|
|
149
|
-
break;
|
|
150
|
-
}
|
|
151
|
-
case "--archive-tables":
|
|
152
|
-
flags.archiveTables = true;
|
|
153
|
-
break;
|
|
154
|
-
case "--undo":
|
|
155
|
-
flags.undo = true;
|
|
156
|
-
break;
|
|
157
95
|
case "--version":
|
|
158
|
-
case "-v":
|
|
159
|
-
|
|
160
|
-
// consumer verbs `install` / `upgrade`), `--version` carries a value
|
|
161
|
-
// (the package version) and the value is REQUIRED — a bare or malformed
|
|
162
|
-
// `--version` here must never fall back to the CLI-version early-exit
|
|
163
|
-
// boolean, which would print the CLI version and exit 0 (a provisioning
|
|
164
|
-
// script reads that as a successful install). The value is captured raw;
|
|
165
|
-
// the consuming command validates integer-ness with a loud error.
|
|
166
|
-
// Everywhere else, this is the CLI-version boolean.
|
|
167
|
-
const next = argv[i + 1];
|
|
168
|
-
if (command === "package" || command === "install" || command === "upgrade") {
|
|
169
|
-
if (next === undefined || next.startsWith("-")) {
|
|
170
|
-
throw new Error("--version requires a version number for install/upgrade/package commands (e.g. --version 2).");
|
|
171
|
-
}
|
|
172
|
-
flags.packageVersion = next;
|
|
173
|
-
i++;
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
flags.version = true;
|
|
177
|
-
}
|
|
96
|
+
case "-v":
|
|
97
|
+
flags.version = true;
|
|
178
98
|
break;
|
|
179
|
-
}
|
|
180
99
|
case "--help":
|
|
181
100
|
case "-h":
|
|
182
101
|
flags.help = true;
|
package/dist/args.test.js
CHANGED
|
@@ -23,53 +23,13 @@ describe("parseArgs", () => {
|
|
|
23
23
|
const r = parseArgs(["app", "deploy"]);
|
|
24
24
|
expect(r.flags.message).toBeUndefined();
|
|
25
25
|
});
|
|
26
|
-
it("captures --version <int> as packageVersion on the top-level install verb", () => {
|
|
27
|
-
const r = parseArgs(["install", "apg_123", "--version", "2"]);
|
|
28
|
-
expect(r.command).toBe("install");
|
|
29
|
-
expect(r.subcommand).toBe("apg_123");
|
|
30
|
-
expect(r.flags.packageVersion).toBe("2");
|
|
31
|
-
expect(r.flags.version).toBe(false);
|
|
32
|
-
expect(r.restArgs).toEqual([]);
|
|
33
|
-
});
|
|
34
|
-
it("captures --version <int> as packageVersion on the top-level upgrade verb", () => {
|
|
35
|
-
const r = parseArgs(["upgrade", "app_1", "--version", "3"]);
|
|
36
|
-
expect(r.command).toBe("upgrade");
|
|
37
|
-
expect(r.subcommand).toBe("app_1");
|
|
38
|
-
expect(r.flags.packageVersion).toBe("3");
|
|
39
|
-
expect(r.flags.version).toBe(false);
|
|
40
|
-
});
|
|
41
26
|
it("treats a bare --version as the boolean CLI-version flag", () => {
|
|
42
27
|
const r = parseArgs(["--version"]);
|
|
43
28
|
expect(r.flags.version).toBe(true);
|
|
44
|
-
expect(r.flags.packageVersion).toBeUndefined();
|
|
45
29
|
});
|
|
46
30
|
it("treats -v as the boolean CLI-version flag", () => {
|
|
47
31
|
const r = parseArgs(["-v"]);
|
|
48
32
|
expect(r.flags.version).toBe(true);
|
|
49
|
-
expect(r.flags.packageVersion).toBeUndefined();
|
|
50
|
-
});
|
|
51
|
-
it("captures a non-integer --version value under version-taking commands for loud command-level validation", () => {
|
|
52
|
-
const r = parseArgs(["install", "apg_123", "--version", "2.0"]);
|
|
53
|
-
expect(r.flags.packageVersion).toBe("2.0");
|
|
54
|
-
expect(r.flags.version).toBe(false);
|
|
55
|
-
});
|
|
56
|
-
it("collects repeated --resolve values", () => {
|
|
57
|
-
const r = parseArgs([
|
|
58
|
-
"upgrade",
|
|
59
|
-
"app_1",
|
|
60
|
-
"--resolve",
|
|
61
|
-
"fields.deal.stage=recreate",
|
|
62
|
-
"--resolve",
|
|
63
|
-
"templates.quote=dtl_abc",
|
|
64
|
-
]);
|
|
65
|
-
expect(r.flags.resolve).toEqual(["fields.deal.stage=recreate", "templates.quote=dtl_abc"]);
|
|
66
|
-
});
|
|
67
|
-
it("errors on --resolve without a value", () => {
|
|
68
|
-
expect(() => parseArgs(["upgrade", "app_1", "--resolve"])).toThrow(/--resolve requires a value/);
|
|
69
|
-
});
|
|
70
|
-
it("errors loudly on a bare --version under version-taking commands instead of printing the CLI version", () => {
|
|
71
|
-
expect(() => parseArgs(["install", "apg_123", "--version"])).toThrow(/requires a version number/);
|
|
72
|
-
expect(() => parseArgs(["install", "apg_123", "--version", "--json"])).toThrow(/requires a version number/);
|
|
73
33
|
});
|
|
74
34
|
it("parses --workspace as a value flag", () => {
|
|
75
35
|
const r = parseArgs(["run", "query_tables", "{}", "--workspace", "wsp_123"]);
|
|
@@ -111,15 +71,6 @@ describe("parseArgs", () => {
|
|
|
111
71
|
expect(parseArgs(["app", "workflow", "run", "wf"]).flags.cleanup).toBe(false);
|
|
112
72
|
expect(parseArgs(["app", "workflow", "run", "wf"]).flags.printCreated).toBe(false);
|
|
113
73
|
});
|
|
114
|
-
it("collects repeated --rename old=new flags (default empty)", () => {
|
|
115
|
-
const r = parseArgs(["app", "publish", ".", "--rename", "item=deal", "--rename", "don_hang=orders"]);
|
|
116
|
-
expect(r.flags.rename).toEqual(["item=deal", "don_hang=orders"]);
|
|
117
|
-
expect(r.toolArgs).toBe(".");
|
|
118
|
-
expect(parseArgs(["app", "publish"]).flags.rename).toEqual([]);
|
|
119
|
-
});
|
|
120
|
-
it("throws when --rename has no value", () => {
|
|
121
|
-
expect(() => parseArgs(["app", "publish", "--rename"])).toThrow(/--rename requires a value/);
|
|
122
|
-
});
|
|
123
74
|
it("parses --yes and -y as the same boolean confirmation flag (default false)", () => {
|
|
124
75
|
expect(parseArgs(["workspace", "delete", "wsp_1", "--yes"]).flags.yes).toBe(true);
|
|
125
76
|
expect(parseArgs(["workspace", "delete", "wsp_1", "-y"]).flags.yes).toBe(true);
|
package/dist/cli.js
CHANGED
|
@@ -14,7 +14,6 @@ import { LoticsClient, API_BASE_URL } from "./client.js";
|
|
|
14
14
|
import { resolveContext, deleteConfig, getConfigPath, loadGlobalConfig, saveGlobalConfig, loadLocalConfig, upsertProfile, removeProfile, setActiveOrg, setSelectedWorkspace, resolveProfileByNameOrId, checkForUpdate, } from "./config.js";
|
|
15
15
|
import { VERSION } from "./version.js";
|
|
16
16
|
import { appCreate, appPull, appDeploy, appDev, appSetSubdomain, appRename, appVersions, appCodegen, appExecuteWorkflow, appWorkflowSet, appWorkflowPull, appWorkflowCheck, appQuerySet, appUiLink, } from "./app_commands.js";
|
|
17
|
-
import { packageInstall, packageUninstall, packageListContent, packageConfig, packageShow, parseInstallConfigFlags, packageEject, packageDoctor, packageUpgrade, packageUpgradeByPackageId, redirectContentPciForm, parseBindToFlags, appPublish, appRelease, appUnpublish, packageYank, } from "./package_commands.js";
|
|
18
17
|
import { parseArgs } from "./args.js";
|
|
19
18
|
import { ingestJsonArgs } from "./inputs.js";
|
|
20
19
|
import { runXlsxCommand } from "./xlsx.js";
|
|
@@ -75,18 +74,6 @@ COMMANDS
|
|
|
75
74
|
(-m is required — it's the version's audit trail;
|
|
76
75
|
carries code + queries only — workflow bindings are
|
|
77
76
|
managed by set_app_workflow / remove_app_workflow)
|
|
78
|
-
lotics app publish [app_id|.] [--rename old=new ...] [-m <changelog>] [--yes]
|
|
79
|
-
Make the app DISTRIBUTABLE — first-release it (v1) as a
|
|
80
|
-
package; later versions ship via "lotics app release".
|
|
81
|
-
Previews the auto-minted aliases + findings; --yes applies
|
|
82
|
-
(extract → create → publish v1 → pin origin). --rename fixes
|
|
83
|
-
an alias before v1 freezes; -m is an optional v1 changelog
|
|
84
|
-
lotics app release [app_id|.] -m <changelog> [--yes]
|
|
85
|
-
RELEASE the next package version from the origin app you
|
|
86
|
-
are happy with (preview; --yes publishes + re-pins)
|
|
87
|
-
lotics app unpublish <app_id|package_id> [--undo]
|
|
88
|
-
Take the published package off the shelf (installations
|
|
89
|
-
keep working); --undo restores it
|
|
90
77
|
lotics app versions [app_id] Show deploy history newest-first (version,
|
|
91
78
|
timestamp, deployer, build status, -m message;
|
|
92
79
|
* marks the currently served version)
|
|
@@ -108,42 +95,6 @@ COMMANDS
|
|
|
108
95
|
lotics app subdomain <new-subdomain> Rename the app's public <slug>.lotics.app address
|
|
109
96
|
lotics app rename "<new name>" Rename the app's display name (launcher title)
|
|
110
97
|
lotics app dev [path] Run the app locally with HMR (RPC forwarded to prod)
|
|
111
|
-
# PACKAGES — consumer verbs are top-level; low-traffic ops live on "lotics package"
|
|
112
|
-
# (author verbs live on "lotics app")
|
|
113
|
-
lotics install <package_id> [--version N] [--bind-to <alias>=<kdc_id> ...] [--config key=value ...]
|
|
114
|
-
Install a package (app: scaffolds/deploys/materializes,
|
|
115
|
-
--config sets its knobs; content: installs the doc corpus,
|
|
116
|
-
--bind-to consents to adopt a same-named doc on a collision)
|
|
117
|
-
lotics uninstall <app_id|package_id> [--archive-tables] [--keep-content]
|
|
118
|
-
Uninstall — dispatched by id. App (app_id): archives
|
|
119
|
-
artifacts (+ --archive-tables also archives scaffolded
|
|
120
|
-
tables). Content package (apg_): archives its package-bound
|
|
121
|
-
docs unless --keep-content
|
|
122
|
-
lotics upgrade <app_id|package_id> [--version N] [--resolve <key>=... ] [--bind-to ...] [--apply-all]
|
|
123
|
-
Preview-then-apply an upgrade, dispatched by id. App
|
|
124
|
-
(app_id): refuses while any drift/modified/bundled-knowledge
|
|
125
|
-
finding lacks a --resolve. Package (apg_): a CONTENT package
|
|
126
|
-
upgrades THIS workspace's install (--resolve
|
|
127
|
-
<alias>=apply|keep|archive|recreate|unbind); an APP package
|
|
128
|
-
FLEET-upgrades every installation across your org (clean
|
|
129
|
-
apply, findings skip). --apply-all accepts the package's version
|
|
130
|
-
lotics package doctor [app_id] Installation health: version pin vs latest, binding
|
|
131
|
-
drift, locally modified core, knowledge drift/edits
|
|
132
|
-
(exit 1 on findings)
|
|
133
|
-
lotics package config <app_id> [--set key=value ...]
|
|
134
|
-
Show or edit an installation's config knobs
|
|
135
|
-
lotics package eject <app_id> Sever an installation's package link
|
|
136
|
-
(re-deploys the pinned source as a bespoke app)
|
|
137
|
-
lotics package show <package_id> Registry metadata + version history
|
|
138
|
-
lotics package list-content List the workspace's content installations
|
|
139
|
-
(standalone content installs) — each row leads with
|
|
140
|
-
the package id for upgrade/uninstall
|
|
141
|
-
lotics package yank <package_id> <version> [--undo]
|
|
142
|
-
Refuse new installs/upgrades of a broken published
|
|
143
|
-
version (pinned installations keep running)
|
|
144
|
-
lotics run publish_content '{"name":"…","knowledge_doc_ids":[…],"template_ids":[…]}'
|
|
145
|
-
Publish a SET of live docs + templates as a content
|
|
146
|
-
package (v1 + origin pin); release_content cuts the next
|
|
147
98
|
lotics ui link <component> [--ui-src <path>] [--remove]
|
|
148
99
|
Dev-link @lotics/ui to packages/ui/src (Vite alias
|
|
149
100
|
+ tsc paths) for live HMR + typecheck. Monorepo apps
|
|
@@ -172,13 +123,6 @@ FLAGS
|
|
|
172
123
|
is_current_member / row-scoping resolve to them (also
|
|
173
124
|
LOTICS_VIEW_AS env; admin key only; writes stay yours)
|
|
174
125
|
--local Pin the current directory (lotics org use / auth api-key)
|
|
175
|
-
--rename <old>=<new> (lotics app publish, repeatable) Fix an auto-minted alias before
|
|
176
|
-
the package's v1 contract freezes it
|
|
177
|
-
--bind-to <a>=<id> (lotics install/upgrade, repeatable) Adopt an existing
|
|
178
|
-
same-named doc as package-managed (resolves a knowledge collision)
|
|
179
|
-
--keep-content (lotics uninstall) Keep the docs instead of archiving them
|
|
180
|
-
--apply-all (lotics upgrade, knowledge) Accept the package's version
|
|
181
|
-
for every doc (overwrites local edits)
|
|
182
126
|
--all (lotics auth logout) Remove every saved credential
|
|
183
127
|
--version Show version
|
|
184
128
|
|
|
@@ -680,11 +624,7 @@ async function main() {
|
|
|
680
624
|
command !== "run" &&
|
|
681
625
|
command !== "download" &&
|
|
682
626
|
command !== "workspace" &&
|
|
683
|
-
command !== "app"
|
|
684
|
-
command !== "package" &&
|
|
685
|
-
command !== "install" &&
|
|
686
|
-
command !== "uninstall" &&
|
|
687
|
-
command !== "upgrade") {
|
|
627
|
+
command !== "app") {
|
|
688
628
|
console.error(`Unknown command: ${command}`);
|
|
689
629
|
console.error('Run "lotics --help" for usage.');
|
|
690
630
|
process.exit(1);
|
|
@@ -706,27 +646,6 @@ async function main() {
|
|
|
706
646
|
console.error(" lotics app subdomain <new-subdomain> Rename the app's public <slug>.lotics.app address");
|
|
707
647
|
console.error(" lotics app rename \"<new name>\" Rename the app's display name (launcher title)");
|
|
708
648
|
console.error(" lotics app dev [path] Run the app locally with HMR + RPC forwarding");
|
|
709
|
-
console.error(" lotics app publish [app_id|.] [--rename old=new ...] [-m <changelog>] [--yes] First-release the app as a package (v1; preview, --yes applies)");
|
|
710
|
-
console.error(" lotics app release [app_id|.] -m <changelog> [--yes] Release the next package version from the origin");
|
|
711
|
-
console.error(" lotics app unpublish <app_id|package_id> [--undo] Take a published package off the shelf (any kind — app or content)");
|
|
712
|
-
process.exit(1);
|
|
713
|
-
}
|
|
714
|
-
if (command === "package" && !subcommand) {
|
|
715
|
-
console.error("Usage (low-traffic consumer / registry ops — author verbs live on `lotics app`):");
|
|
716
|
-
console.error(" The high-traffic consumer verbs are top-level:");
|
|
717
|
-
console.error(" lotics install <package_id> [--version N] [--bind-to <alias>=<kdc_id>] [--config key=value ...] Install a package (app or content)");
|
|
718
|
-
console.error(" lotics uninstall <app_id|package_id> [--archive-tables] [--keep-content] Uninstall — dispatched by id (app vs content)");
|
|
719
|
-
console.error(" lotics upgrade <app_id|package_id> [--version N] [--resolve <key>=... ] [--bind-to ...] [--apply-all] Upgrade — app install / content install / whole app fleet (apg_)");
|
|
720
|
-
console.error(" lotics package doctor [app_id] Health: version pin vs latest + binding/knowledge drift");
|
|
721
|
-
console.error(" lotics package config <app_id> [--set key=value ...] Show or edit an installation's config knobs");
|
|
722
|
-
console.error(" lotics package eject <app_id> Sever an installation's package link");
|
|
723
|
-
console.error(" lotics package show <package_id> Registry metadata + version history (channel, yank, changelog)");
|
|
724
|
-
console.error(" lotics package list-content List the workspace's content installations (standalone content installs)");
|
|
725
|
-
console.error(" lotics package yank <package_id> <version> [--undo] Refuse new installs/upgrades of a broken published version (pinned installations keep running)");
|
|
726
|
-
console.error(" A content package (a SET of live docs + templates) — publish + release with the tools, retire on `lotics app`:");
|
|
727
|
-
console.error(" lotics run publish_content '{\"name\":\"…\",\"knowledge_doc_ids\":[…],\"template_ids\":[…]}' Publish v1 (a fixed set)");
|
|
728
|
-
console.error(" lotics run release_content '{\"package_id\":\"apg_…\",\"changelog\":\"…\"}' Cut the next version (add \"dry_run\":true to preview)");
|
|
729
|
-
console.error(" lotics app unpublish <package_id> Take the whole package off the shelf (kind-agnostic — retires content too)");
|
|
730
649
|
process.exit(1);
|
|
731
650
|
}
|
|
732
651
|
if (command === "run" && !subcommand) {
|
|
@@ -873,173 +792,6 @@ async function main() {
|
|
|
873
792
|
}
|
|
874
793
|
// Ensure workspace is resolved for all remaining commands
|
|
875
794
|
await resolveWorkspace(client, ctx);
|
|
876
|
-
// --- lotics install / uninstall / upgrade — top-level CONSUMER verbs ---
|
|
877
|
-
// The high-traffic operator surface reads noun-less: `lotics install <pkg>`,
|
|
878
|
-
// `lotics uninstall <id>`, `lotics upgrade <id>`. Low-traffic ops keep their
|
|
879
|
-
// `lotics package <verb>` home. The package id is the SECOND positional at top
|
|
880
|
-
// level, which the parser puts in `subcommand` (not `toolArgs`).
|
|
881
|
-
if (command === "install") {
|
|
882
|
-
const packageId = subcommand;
|
|
883
|
-
if (!packageId) {
|
|
884
|
-
console.error("Usage: lotics install <package_id> [--version N] [--bind-to <alias>=<kdc_id> ...] [--config key=value ...]");
|
|
885
|
-
process.exit(1);
|
|
886
|
-
}
|
|
887
|
-
let version;
|
|
888
|
-
if (flags.packageVersion !== undefined) {
|
|
889
|
-
version = Number(flags.packageVersion);
|
|
890
|
-
if (!Number.isInteger(version) || version <= 0) {
|
|
891
|
-
console.error(`Invalid --version "${flags.packageVersion}" — expected a positive integer.`);
|
|
892
|
-
process.exit(1);
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
const config = flags.config.length > 0 ? parseInstallConfigFlags(flags.config) : undefined;
|
|
896
|
-
await packageInstall(client, {
|
|
897
|
-
package_id: packageId,
|
|
898
|
-
version,
|
|
899
|
-
bind_to: parseBindToFlags(flags.bindTo),
|
|
900
|
-
...(config !== undefined ? { config } : {}),
|
|
901
|
-
});
|
|
902
|
-
return;
|
|
903
|
-
}
|
|
904
|
-
if (command === "uninstall") {
|
|
905
|
-
const id = subcommand;
|
|
906
|
-
if (!id) {
|
|
907
|
-
console.error("Usage: lotics uninstall <app_id|package_id> [--archive-tables] [--keep-content]");
|
|
908
|
-
console.error("Dispatched by id: an app installation (app_id; --archive-tables to also archive its " +
|
|
909
|
-
"scaffolded tables) or a content package (apg_ id from `lotics install` / " +
|
|
910
|
-
"lotics package list-content; --keep-content to retain its docs).");
|
|
911
|
-
process.exit(1);
|
|
912
|
-
}
|
|
913
|
-
// A `pci_` resource id is retired from human sight — redirect to the package-id form.
|
|
914
|
-
if (id.startsWith("pci_")) {
|
|
915
|
-
await redirectContentPciForm(client, id, "uninstall");
|
|
916
|
-
return;
|
|
917
|
-
}
|
|
918
|
-
await packageUninstall(client, {
|
|
919
|
-
id,
|
|
920
|
-
keep_content: flags.keepContent,
|
|
921
|
-
archive_tables: flags.archiveTables,
|
|
922
|
-
});
|
|
923
|
-
return;
|
|
924
|
-
}
|
|
925
|
-
if (command === "upgrade") {
|
|
926
|
-
const target = subcommand;
|
|
927
|
-
if (!target) {
|
|
928
|
-
console.error("Usage: lotics upgrade <app_id | package_id> [--version N] [--resolve <key>=... ...] [--bind-to ...] [--apply-all]");
|
|
929
|
-
console.error("Dispatched by id: an app installation (app_id), or a package id (apg_) — a CONTENT package " +
|
|
930
|
-
"upgrades this workspace's install; an APP package fleet-upgrades every installation across your org.");
|
|
931
|
-
process.exit(1);
|
|
932
|
-
}
|
|
933
|
-
let version;
|
|
934
|
-
if (flags.packageVersion !== undefined) {
|
|
935
|
-
version = Number(flags.packageVersion);
|
|
936
|
-
if (!Number.isInteger(version) || version <= 0) {
|
|
937
|
-
console.error(`Invalid --version "${flags.packageVersion}" — expected a positive integer.`);
|
|
938
|
-
process.exit(1);
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
// A `pci_` resource id is retired from human sight — redirect to the package-id form.
|
|
942
|
-
if (target.startsWith("pci_")) {
|
|
943
|
-
await redirectContentPciForm(client, target, "upgrade");
|
|
944
|
-
return;
|
|
945
|
-
}
|
|
946
|
-
// A package id (apg_) is kind-branched: a content package upgrades THIS
|
|
947
|
-
// workspace's install; an app package fleet-upgrades the whole org.
|
|
948
|
-
if (target.startsWith("apg_")) {
|
|
949
|
-
await packageUpgradeByPackageId(client, {
|
|
950
|
-
package_id: target,
|
|
951
|
-
version,
|
|
952
|
-
resolve: flags.resolve,
|
|
953
|
-
bindTo: flags.bindTo,
|
|
954
|
-
applyAll: flags.applyAll,
|
|
955
|
-
});
|
|
956
|
-
return;
|
|
957
|
-
}
|
|
958
|
-
// Anything else is an app installation (addressed by its app id).
|
|
959
|
-
await packageUpgrade(client, {
|
|
960
|
-
app_id: target,
|
|
961
|
-
version,
|
|
962
|
-
resolve: flags.resolve,
|
|
963
|
-
bindTo: flags.bindTo,
|
|
964
|
-
applyAll: flags.applyAll,
|
|
965
|
-
});
|
|
966
|
-
return;
|
|
967
|
-
}
|
|
968
|
-
// lotics package <verb> — the low-traffic consumer / registry surface. The
|
|
969
|
-
// high-traffic install / uninstall / upgrade / fleet-upgrade verbs moved to
|
|
970
|
-
// the top level above; they are refused here (below) so the old forms fail
|
|
971
|
-
// loudly instead of silently doing nothing.
|
|
972
|
-
if (command === "package") {
|
|
973
|
-
if (subcommand === "list-content") {
|
|
974
|
-
await packageListContent(client);
|
|
975
|
-
return;
|
|
976
|
-
}
|
|
977
|
-
if (subcommand === "config") {
|
|
978
|
-
const appId = toolArgs;
|
|
979
|
-
if (!appId) {
|
|
980
|
-
console.error("Usage: lotics package config <app_id> [--set key=value ...]");
|
|
981
|
-
process.exit(1);
|
|
982
|
-
}
|
|
983
|
-
await packageConfig(client, { app_id: appId, sets: flags.set });
|
|
984
|
-
return;
|
|
985
|
-
}
|
|
986
|
-
if (subcommand === "show") {
|
|
987
|
-
const packageId = toolArgs;
|
|
988
|
-
if (!packageId) {
|
|
989
|
-
console.error("Usage: lotics package show <package_id>");
|
|
990
|
-
process.exit(1);
|
|
991
|
-
}
|
|
992
|
-
await packageShow(client, { package_id: packageId });
|
|
993
|
-
return;
|
|
994
|
-
}
|
|
995
|
-
if (subcommand === "eject") {
|
|
996
|
-
const appId = toolArgs;
|
|
997
|
-
if (!appId) {
|
|
998
|
-
console.error("Usage: lotics package eject <app_id>");
|
|
999
|
-
process.exit(1);
|
|
1000
|
-
}
|
|
1001
|
-
await packageEject(client, { app_id: appId });
|
|
1002
|
-
return;
|
|
1003
|
-
}
|
|
1004
|
-
if (subcommand === "yank") {
|
|
1005
|
-
const packageId = toolArgs;
|
|
1006
|
-
const version = Number(restArgs[0]);
|
|
1007
|
-
if (!packageId || !Number.isInteger(version) || version <= 0) {
|
|
1008
|
-
console.error("Usage: lotics package yank <package_id> <version> [--undo]");
|
|
1009
|
-
process.exit(1);
|
|
1010
|
-
}
|
|
1011
|
-
await packageYank(client, { package_id: packageId, version, undo: flags.undo });
|
|
1012
|
-
return;
|
|
1013
|
-
}
|
|
1014
|
-
if (subcommand === "doctor") {
|
|
1015
|
-
await packageDoctor(client, { app_id: toolArgs });
|
|
1016
|
-
return;
|
|
1017
|
-
}
|
|
1018
|
-
// Re-pointing a live role rides the upgrade's ONE resolutions grammar —
|
|
1019
|
-
// redirect the removed verb loudly, never a silent unknown-command fall-through.
|
|
1020
|
-
if (subcommand === "rebind-role") {
|
|
1021
|
-
const appId = toolArgs;
|
|
1022
|
-
const [roleAlias, groupId] = restArgs;
|
|
1023
|
-
console.error("`lotics package rebind-role` was folded into the upgrade grammar. Re-point a live role with:\n" +
|
|
1024
|
-
` lotics upgrade ${appId ?? "<app_id>"} --resolve roles.${roleAlias ?? "<alias>"}=${groupId ?? "<grp_id>"}`);
|
|
1025
|
-
process.exit(1);
|
|
1026
|
-
}
|
|
1027
|
-
// The high-traffic consumer verbs moved to the top level. Refuse the old
|
|
1028
|
-
// `lotics package <verb>` forms loudly with a redirect, never a silent no-op.
|
|
1029
|
-
const movedVerbs = {
|
|
1030
|
-
install: "lotics install <package_id>",
|
|
1031
|
-
uninstall: "lotics uninstall <app_id|package_id>",
|
|
1032
|
-
upgrade: "lotics upgrade <app_id|package_id>",
|
|
1033
|
-
"fleet-upgrade": "lotics upgrade <package_id>",
|
|
1034
|
-
};
|
|
1035
|
-
if (subcommand !== undefined && subcommand in movedVerbs) {
|
|
1036
|
-
console.error(`\`lotics package ${subcommand}\` moved to the top level — run \`${movedVerbs[subcommand]}\` instead.`);
|
|
1037
|
-
process.exit(1);
|
|
1038
|
-
}
|
|
1039
|
-
console.error(`Unknown package subcommand: ${subcommand}`);
|
|
1040
|
-
console.error("Run 'lotics package' for usage.");
|
|
1041
|
-
process.exit(1);
|
|
1042
|
-
}
|
|
1043
795
|
// lotics app create / pull / deploy
|
|
1044
796
|
if (command === "app") {
|
|
1045
797
|
if (subcommand === "create") {
|
|
@@ -1075,40 +827,6 @@ async function main() {
|
|
|
1075
827
|
await appDeploy(client, { message });
|
|
1076
828
|
return;
|
|
1077
829
|
}
|
|
1078
|
-
if (subcommand === "publish") {
|
|
1079
|
-
// First-release a bespoke app AS a package. Positional app id (`.`/omitted →
|
|
1080
|
-
// the local app project manifest). Previews the minted aliases + findings,
|
|
1081
|
-
// then applies only with `--yes` (mirrors `app release`). `--rename old=new`
|
|
1082
|
-
// fixes an auto-minted alias before v1 freezes it; `-m` is an optional v1 changelog.
|
|
1083
|
-
await appPublish(client, {
|
|
1084
|
-
app_id: toolArgs,
|
|
1085
|
-
renames: flags.rename,
|
|
1086
|
-
changelog: flags.message,
|
|
1087
|
-
yes: flags.yes,
|
|
1088
|
-
});
|
|
1089
|
-
return;
|
|
1090
|
-
}
|
|
1091
|
-
if (subcommand === "release") {
|
|
1092
|
-
// -m <changelog> is REQUIRED — each release is a version row read back by
|
|
1093
|
-
// `lotics package show`, so a blank changelog loses the audit trail.
|
|
1094
|
-
if (!flags.message) {
|
|
1095
|
-
console.error("Usage: lotics app release [app_id|.] -m <changelog> [--yes]");
|
|
1096
|
-
console.error("Snapshots the origin app into its next package version (preview, then --yes to publish).");
|
|
1097
|
-
process.exit(1);
|
|
1098
|
-
}
|
|
1099
|
-
await appRelease(client, { app_id: toolArgs, changelog: flags.message, yes: flags.yes });
|
|
1100
|
-
return;
|
|
1101
|
-
}
|
|
1102
|
-
if (subcommand === "unpublish") {
|
|
1103
|
-
const id = toolArgs;
|
|
1104
|
-
if (!id) {
|
|
1105
|
-
console.error("Usage: lotics app unpublish <app_id|package_id> [--undo]");
|
|
1106
|
-
console.error("Takes a published package off the shelf; existing installations keep working.");
|
|
1107
|
-
process.exit(1);
|
|
1108
|
-
}
|
|
1109
|
-
await appUnpublish(client, { id, undo: flags.undo });
|
|
1110
|
-
return;
|
|
1111
|
-
}
|
|
1112
830
|
if (subcommand === "subdomain") {
|
|
1113
831
|
const newSubdomain = toolArgs;
|
|
1114
832
|
if (!newSubdomain) {
|