@kitelev/exocortex-cli 16.254.1 → 16.255.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 +72 -1
- package/dist/index.js +271 -259
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -124,7 +124,7 @@ npx @kitelev/exocortex-cli apply <cmd> [path] [options]
|
|
|
124
124
|
| `--vault <path>` | cwd | Path to Obsidian vault |
|
|
125
125
|
| `--dry-run` | off | Evaluate precondition and preview; do not write |
|
|
126
126
|
| `--yes` | off | Skip destructive-command confirmation |
|
|
127
|
-
| `--input <json>` | — | JSON object forwarded to
|
|
127
|
+
| `--input <json>` | — | JSON object forwarded to the grounding as `userInput`; its declared REQUIRED keys are checked before the grounding runs (see below) |
|
|
128
128
|
| `--seed <uuid>` | — | Deterministic UID seed for test/replay |
|
|
129
129
|
| `--frozen-clock <iso>` | — | Freeze clock to an ISO timestamp for test/replay |
|
|
130
130
|
| `--json` | off | Emit a machine-readable `{command,target,created:[…]}` envelope |
|
|
@@ -134,6 +134,17 @@ npx @kitelev/exocortex-cli apply <cmd> [path] [options]
|
|
|
134
134
|
**Behavior:**
|
|
135
135
|
|
|
136
136
|
- The precondition is evaluated per target; a non-passing ASK aborts before the grounding runs.
|
|
137
|
+
- When the command's grounding declares an `exocmd__Grounding_inputSchema`, a REQUIRED key it
|
|
138
|
+
declares is checked **after the command resolves and its precondition passes, but before the
|
|
139
|
+
grounding runs** — on the dry-run and the executing path alike (req `656bd2d9`). The refusal
|
|
140
|
+
names the key, and fires only when nothing declared supplies it: the schema's own non-blank
|
|
141
|
+
`defaultValue`, a `propertyDefault` / `inheritanceRule` / `serviceCallPayload` /
|
|
142
|
+
`Grounding_isDefinedBy` anywhere in the grounding tree, or — for the engine-reserved `label` —
|
|
143
|
+
a `labelTemplate` / `omitLabel`. A grounding that declares no schema is not checked at all.
|
|
144
|
+
- ⛤ A key the schema does NOT declare is **accepted**, by design: passing an extra property key
|
|
145
|
+
through `--input` is a supported way to populate the asset a `create_instance` grounding builds
|
|
146
|
+
(`--input '{"label":"…","ems__Effort_blocker":"[[uid]]"}'`). Only `label`, `body` and
|
|
147
|
+
`plannedDate` are consumed by the engine itself rather than written as properties.
|
|
137
148
|
- Commands marked `exocmd__Command_destructive: true` refuse to run without `--dry-run` or `--yes`.
|
|
138
149
|
- Multi-target runs (stdin) use continue-on-error semantics and print a `N/M` summary; the exit code is `5` if any target failed.
|
|
139
150
|
- `--use-cache` (#4264): the triple store comes from `<vault>/.exocortex/cache/triples.json`
|
|
@@ -366,6 +377,66 @@ echo "# Content" | npx @kitelev/exocortex-cli create \
|
|
|
366
377
|
--vault ~/vault
|
|
367
378
|
```
|
|
368
379
|
|
|
380
|
+
### create-batch
|
|
381
|
+
|
|
382
|
+
Create many assets from one JSON file in **one invocation** (issue #4347). Every item goes through the same pipeline as `create` — the same guards, class resolution, status default, wikilink validation and co-location — but the vault-wide scans `create` pays for (class index, TBox walk, shape load, anchor and neighbour resolution) run **once per invocation** instead of once per item. Measured on a 35K-file vault (2026-09-25): one `create` took 17–29 s and read every vault file 4 times; a `create-batch` of 1, 20, 200 or 2,000 items took 26–34 s and read every vault file 3 times, whatever the batch size.
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
npx @kitelev/exocortex-cli create-batch items.json --vault ~/vault
|
|
386
|
+
generate-items | npx @kitelev/exocortex-cli create-batch - --vault ~/vault --dry-run
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
`items.json` is a JSON array; each item maps onto the `create` flags:
|
|
390
|
+
|
|
391
|
+
```json
|
|
392
|
+
[
|
|
393
|
+
{
|
|
394
|
+
"class": "ems__Task",
|
|
395
|
+
"label": "Exercise 1.1",
|
|
396
|
+
"uid": "0b6a3c52-1f0e-4c3a-9d6e-6f1f4d7a2b10",
|
|
397
|
+
"properties": { "exo__Asset_isDefinedBy": "[[<ontology-uid>]]" }
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
"class": "ems__Task",
|
|
401
|
+
"label": "Step 1",
|
|
402
|
+
"aliases": ["First step"],
|
|
403
|
+
"properties": {
|
|
404
|
+
"ems__Effort_parent": "[[0b6a3c52-1f0e-4c3a-9d6e-6f1f4d7a2b10]]",
|
|
405
|
+
"exo__Asset_relates": ["[[<uid-a>]]", "[[<uid-b>]]"]
|
|
406
|
+
},
|
|
407
|
+
"body": "# Step 1\n\nText.",
|
|
408
|
+
"status": "Draft"
|
|
409
|
+
}
|
|
410
|
+
]
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
| Item key | `create` equivalent | Notes |
|
|
414
|
+
| ------------ | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
415
|
+
| `class` | `--class` | **Required.** Short name or UUID |
|
|
416
|
+
| `label` | `--label` | **Required** |
|
|
417
|
+
| `uid` | — | Optional caller-chosen identity (canonical lower-case UUID); omitted → generated anew each run |
|
|
418
|
+
| `aliases` | `--aliases` | Array of strings |
|
|
419
|
+
| `properties` | `--property k=v` | Object; a string / number / boolean value is one flag, an array is the key repeated (multi-value). A number is written as JavaScript prints it (`1.0` → `1`); an integer beyond 2^53 is refused — pass exact text as a string |
|
|
420
|
+
| `body` | `--body-file` | Taken verbatim — no `\n` escape expansion |
|
|
421
|
+
| `status` | `--status <name>` | `false` ⇔ `--no-status` |
|
|
422
|
+
| `createdBy` | `--created-by` | Falls back to the batch-wide `--created-by`, then to the `create` default |
|
|
423
|
+
|
|
424
|
+
| Option | Default | Description |
|
|
425
|
+
| ---------------------------- | ------------- | --------------------------------------------------------------------------------------- |
|
|
426
|
+
| `<file>` | **required** | The JSON file, or `-` for stdin (read to the end, no time limit; a terminal is refused) |
|
|
427
|
+
| `--vault <path>` | cwd | Path to Obsidian vault |
|
|
428
|
+
| `--dry-run` | off | Plan and validate every item, preview each one's exact bytes (stderr), write nothing |
|
|
429
|
+
| `--created-by <uuid>` | — | Creator for items that set no `createdBy` |
|
|
430
|
+
| `--timezone <tz>` | `Asia/Almaty` | Timezone for timestamps |
|
|
431
|
+
| `--skip-wikilink-validation` | off | Skip wikilink existence validation |
|
|
432
|
+
| `--yes` | — | Accepted for symmetry (no-op) |
|
|
433
|
+
|
|
434
|
+
- **All-or-nothing.** Every item is planned and validated before the first write. If any item fails, **nothing** is written, stderr lists every failing item (`✗ item[<index>] "<label>": <reason>` — an item's first shape problem, or else its uid / anchor problems and its first planning failure) and the exit code is `2`. Messages from `create`'s own guards name the equivalent `create` flag. The filesystem is not transactional: an I/O error during the write phase stops the remaining writes, names the items already written and exits `5`.
|
|
435
|
+
- **Links inside the batch.** Give the target item a `uid` and link to it as `[[<uid>]]` (UUID form — a label-form link needs the target on disk); wikilink validation treats the batch's uids as existing. A `uid` that is malformed, repeated in the batch, or already the uid of an asset in the vault (by filename or by `exo__Asset_uid`) is refused — so re-running a file whose items carry `uid`s is refused instead of duplicating. ⚠ Items **without** `uid` get a fresh identity every run: re-running such a file creates them again.
|
|
436
|
+
- **Anchors must exist.** An `exo__Asset_isDefinedBy` that names another item of the same batch — or the item's own uid (a self-anchored ontology) — is refused, in every form the range guard resolves (wikilink, aliased, quoted or bare uid): the range guard and co-location read the anchor's file. Create the ontology first, in its own run.
|
|
437
|
+
- **Output.** On success stdout is one JSON array `[{uuid, path, label}]` in input order, and the command exits only after stdout and stderr have been flushed (safe to pipe); a reader that closes the pipe early (`| head`) does not change the exit code. `--dry-run` prints the planned mapping — for items without `uid` the uids are generated for that run. Diagnostics are prefixed with the item that raised them, printed once, and followed by the list of other items that raised them. `null` for an optional key means "absent"; a UTF-8 BOM is ignored.
|
|
438
|
+
- **Not in v1:** `--validate`, `--use-cache`, `--write-through` (run `validate schema --shapes-mode` after the batch); existing assets are never updated.
|
|
439
|
+
|
|
369
440
|
### resolve-inline-buttons
|
|
370
441
|
|
|
371
442
|
Print the inline command button-set the plugin would render for an asset — binding-match (Layer A, class hierarchy) ∩ precondition-eval (Layer B). Alias: `resolve-buttons`. The authoritative button-visibility oracle (issue #3833): strictly more complete than `apply <cmd> --dry-run`, which checks the precondition only.
|