@ainova-systems/intelligence 0.19.0 → 0.20.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/cli/commands/registry.sh +1 -1
- package/cli/commands/source.sh +1 -1
- package/cli/commands/sync.sh +78 -6
- package/cli/intelligence +15 -2
- package/cli/internal/convert-legacy.sh +1 -1
- package/cli/internal/package-search.sh +1 -1
- package/cli/internal/package-update.sh +2 -2
- package/cli/internal/restore.sh +3 -2
- package/cli/lib/cli-common.sh +145 -33
- package/cli/lib/lockfile.sh +14 -4
- package/cli/lib/manifest.sh +147 -1
- package/cli/lib/qmap.awk +97 -32
- package/cli/lib/registry.sh +1 -1
- package/cli/lib/sync-cache.sh +596 -142
- package/cli/lib/sync-lock.sh +19 -2
- package/engine/ENGINE_SHA +1 -1
- package/engine/VERSION +1 -1
- package/engine/adapters/agents.sh +5 -2
- package/engine/adapters/antigravity.sh +3 -1
- package/engine/adapters/claude.sh +8 -2
- package/engine/adapters/codex.sh +3 -1
- package/engine/adapters/copilot.sh +8 -2
- package/engine/adapters/cursor.sh +7 -1
- package/engine/adapters/opencode.sh +7 -1
- package/engine/adapters/pi.sh +3 -1
- package/engine/lib/adapter-contract.sh +36 -4
- package/engine/lib/common.sh +665 -121
- package/engine/lib/contract.sh +5 -0
- package/engine/sync.sh +119 -28
- package/package.json +1 -1
- package/packages/sync/references/adapters.md +6 -1
- package/packages/sync/references/conventions.md +4 -1
package/engine/lib/contract.sh
CHANGED
|
@@ -84,6 +84,11 @@ IS_RC_AMBIGUOUS=3 # conflicting state; agent/human-only — bash never
|
|
|
84
84
|
IS_RC_AHEAD=4 # project stamped newer than this engine understands
|
|
85
85
|
IS_RC_ABORTED_INCOMPLETE=5 # staged state incomplete; the project was left untouched
|
|
86
86
|
IS_RC_NEEDS_UPDATE=6 # pending schema changes (stamp < engine) — run `intelligence init --apply`
|
|
87
|
+
# `intelligence sync --check` only: generated files differ from what sync would
|
|
88
|
+
# leave, or alignment is pending (IS_STATUS=out-of-date). It shares 2 with
|
|
89
|
+
# config-missing, which a check never reports: the CLI found the manifest, and
|
|
90
|
+
# the check turns any other failure that ends in 2 into 1.
|
|
91
|
+
IS_RC_OUT_OF_DATE=2
|
|
87
92
|
|
|
88
93
|
# is_status <code-name> [detail] — emit one parseable line for the skill.
|
|
89
94
|
is_status() {
|
package/engine/sync.sh
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
# IS_CONTENT_REL the project's content dir, repo-relative
|
|
11
11
|
# IS_MODULE_REL the installed sync package, repo-relative
|
|
12
12
|
# IS_PROTECTED_DIRS dirs an adapter output may never overlap
|
|
13
|
+
# IS_SYNC_CHECK optional: render, compare and restore, then write
|
|
14
|
+
# `same` or `differs` to this file (`sync --check`)
|
|
13
15
|
#
|
|
14
16
|
# Usage: intelligence sync [target]
|
|
15
17
|
|
|
@@ -111,46 +113,43 @@ while IFS=$'\037' read -r section src state _dir alias holders; do
|
|
|
111
113
|
echo "WARNING: sources.$section '$src' $IS_SOURCE_PROBLEM — skipped; 'intelligence status --check' reports it" >&2
|
|
112
114
|
done <<< "${IS_YL_UNRESOLVED:-}"
|
|
113
115
|
|
|
116
|
+
|
|
117
|
+
# Sources stay read-only for the whole run (validate_output_path refuses an
|
|
118
|
+
# output inside one), so read_source_artifact_files enumerates each section
|
|
119
|
+
# once, in this shell, and its later callers — the agents adapter, the shared
|
|
120
|
+
# skill directory, the context report — replay it. Adapters that list sources
|
|
121
|
+
# with in-shell globs spawn nothing and keep their own, locale-ordered listing.
|
|
122
|
+
# The skills pass also settles every symlink in a skills source and warns once
|
|
123
|
+
# about each it leaves out (decision 0017).
|
|
124
|
+
# shellcheck disable=SC2034 # read by read_source_artifact_files in lib/common.sh
|
|
125
|
+
IS_SOURCE_FILES_MEMO=1
|
|
126
|
+
for section in rules agents skills; do
|
|
127
|
+
read_source_artifact_files "$REPO_ROOT" "$CONFIG_FILE" "$section"
|
|
128
|
+
done
|
|
129
|
+
|
|
114
130
|
# Lint frontmatter across all source files (rules, agents, skills).
|
|
115
131
|
# Catches issues like unquoted colons that strict YAML consumers reject.
|
|
132
|
+
# Skills are the rendered ones the pass above settled: SKILL.md behind a link
|
|
133
|
+
# inside its source is linted, one that leaves its source is never read.
|
|
116
134
|
LINT_FILES=()
|
|
117
|
-
|
|
118
|
-
|
|
135
|
+
LINT_SKILLS=()
|
|
136
|
+
[ "${#IS_SOURCE_FILES[@]}" -eq 0 ] || LINT_SKILLS=("${IS_SOURCE_FILES[@]}")
|
|
137
|
+
for section in rules agents; do
|
|
119
138
|
load_yaml_list "$CONFIG_FILE" "$section"
|
|
120
139
|
while IFS= read -r src; do
|
|
121
140
|
[ -z "$src" ] && continue
|
|
122
141
|
src_dir="$REPO_ROOT/$src"
|
|
123
142
|
[ -d "$src_dir" ] || continue
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
for f in "$src_dir"/*.md; do
|
|
128
|
-
[ -f "$f" ] && LINT_FILES+=("$f")
|
|
129
|
-
done
|
|
130
|
-
fi
|
|
143
|
+
for f in "$src_dir"/*.md; do
|
|
144
|
+
[ -f "$f" ] && LINT_FILES+=("$f")
|
|
145
|
+
done
|
|
131
146
|
done <<< "$IS_YAML_LIST"
|
|
132
147
|
done
|
|
133
|
-
#
|
|
134
|
-
if [ "${#LINT_SKILL_DIRS[@]}" -gt 0 ]; then
|
|
135
|
-
while IFS= read -r f; do
|
|
136
|
-
[ -n "$f" ] && LINT_FILES+=("$f")
|
|
137
|
-
done < <(find "${LINT_SKILL_DIRS[@]}" -mindepth 2 -maxdepth 2 -name 'SKILL.md' 2>/dev/null)
|
|
138
|
-
fi
|
|
148
|
+
[ "${#LINT_SKILLS[@]}" -eq 0 ] || LINT_FILES+=("${LINT_SKILLS[@]}")
|
|
139
149
|
if [ "${#LINT_FILES[@]}" -gt 0 ]; then
|
|
140
150
|
lint_frontmatter_files "${LINT_FILES[@]}"
|
|
141
151
|
fi
|
|
142
152
|
|
|
143
|
-
# Sources stay read-only for the whole run (validate_output_path refuses an
|
|
144
|
-
# output inside one), so read_source_artifact_files enumerates each section
|
|
145
|
-
# once, in this shell, and its later callers — the agents adapter, the shared
|
|
146
|
-
# skill directory, the context report — replay it. Adapters that list sources
|
|
147
|
-
# with in-shell globs spawn nothing and keep their own, locale-ordered listing.
|
|
148
|
-
# shellcheck disable=SC2034 # read by read_source_artifact_files in lib/common.sh
|
|
149
|
-
IS_SOURCE_FILES_MEMO=1
|
|
150
|
-
for section in rules agents skills; do
|
|
151
|
-
read_source_artifact_files "$REPO_ROOT" "$CONFIG_FILE" "$section"
|
|
152
|
-
done
|
|
153
|
-
|
|
154
153
|
# Adapters come from two places, discovered by filename (minus `.sh`,
|
|
155
154
|
# `_template` excluded):
|
|
156
155
|
#
|
|
@@ -211,6 +210,17 @@ SYNC_PARALLEL=1
|
|
|
211
210
|
SYNC_BG_PIDS=()
|
|
212
211
|
SYNC_COPY_INDEXES=()
|
|
213
212
|
|
|
213
|
+
# An accepted output-root directory link is a write path, unlike a nested
|
|
214
|
+
# generated asset link. Checks must retain the bytes behind that root too.
|
|
215
|
+
snapshot_sync_entry() {
|
|
216
|
+
local src="$1" index="$2"
|
|
217
|
+
cp -a "$src" "$SYNC_TX_DIR/data/$index" || return $?
|
|
218
|
+
if [ -n "${IS_SYNC_CHECK:-}" ] && [ -L "$src" ] && [ -d "$src" ]; then
|
|
219
|
+
mkdir -p "$SYNC_TX_DIR/targets/$index" || return $?
|
|
220
|
+
cp -a "$src/." "$SYNC_TX_DIR/targets/$index" || return $?
|
|
221
|
+
fi
|
|
222
|
+
}
|
|
223
|
+
|
|
214
224
|
snapshot_sync_path() {
|
|
215
225
|
local adapter_name="$1" rel="$2" src index present=0
|
|
216
226
|
case "$SYNC_TX_SEEN_LIST" in
|
|
@@ -224,11 +234,11 @@ snapshot_sync_path() {
|
|
|
224
234
|
# Copies of distinct paths into distinct slots: they can overlap, and
|
|
225
235
|
# The snapshot wait before the render collects every status.
|
|
226
236
|
if [ "$SYNC_PARALLEL" = 1 ]; then
|
|
227
|
-
|
|
237
|
+
snapshot_sync_entry "$src" "$index" 2> "$SYNC_TX_DIR/copy.$index.err" &
|
|
228
238
|
SYNC_BG_PIDS+=("$!")
|
|
229
239
|
SYNC_COPY_INDEXES+=("$index")
|
|
230
240
|
else
|
|
231
|
-
|
|
241
|
+
snapshot_sync_entry "$src" "$index"
|
|
232
242
|
fi
|
|
233
243
|
present=1
|
|
234
244
|
fi
|
|
@@ -274,6 +284,68 @@ wait_sync_jobs() {
|
|
|
274
284
|
return "$first"
|
|
275
285
|
}
|
|
276
286
|
|
|
287
|
+
# Compare each entry without following links: copied relative and dangling
|
|
288
|
+
# links describe their targets, not bytes at the snapshot's new location.
|
|
289
|
+
compare_sync_entries() {
|
|
290
|
+
local snap="$1" live="$2" rc=0 target before
|
|
291
|
+
if [ -L "$snap" ]; then
|
|
292
|
+
[ -L "$live" ] || return 1
|
|
293
|
+
before="$(readlink "$snap")" || return 2
|
|
294
|
+
target="$(readlink "$live")" || return 2
|
|
295
|
+
# Source links inside the private copy refer to its root. Compare the
|
|
296
|
+
# generated target in the original project's coordinate system.
|
|
297
|
+
if [ -n "${IS_SYNC_CHECK_ROOT:-}" ] && [ -n "${IS_SYNC_CHECK:-}" ]; then
|
|
298
|
+
case "$before" in "$REPO_ROOT") before="$IS_SYNC_CHECK_ROOT" ;; "$REPO_ROOT"/*) before="$IS_SYNC_CHECK_ROOT/${before#"$REPO_ROOT/"}" ;; esac
|
|
299
|
+
case "$target" in "$REPO_ROOT") target="$IS_SYNC_CHECK_ROOT" ;; "$REPO_ROOT"/*) target="$IS_SYNC_CHECK_ROOT/${target#"$REPO_ROOT/"}" ;; esac
|
|
300
|
+
fi
|
|
301
|
+
[ "$before" = "$target" ] || return 1
|
|
302
|
+
elif [ -L "$live" ]; then
|
|
303
|
+
return 1
|
|
304
|
+
elif [ -f "$snap" ] && [ -f "$live" ]; then
|
|
305
|
+
cmp -s "$snap" "$live" || rc=$?
|
|
306
|
+
case "$rc" in 0) ;; 1) return 1 ;; *) return 2 ;; esac
|
|
307
|
+
if [ -x "$snap" ]; then [ -x "$live" ] || return 1; else [ ! -x "$live" ] || return 1; fi
|
|
308
|
+
elif [ -d "$snap" ] && [ -d "$live" ]; then
|
|
309
|
+
return 0
|
|
310
|
+
else
|
|
311
|
+
return 1
|
|
312
|
+
fi
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
compare_sync_snapshot() {
|
|
316
|
+
local index rel present live snap entry sub
|
|
317
|
+
while IFS=$'\t' read -r index rel present; do
|
|
318
|
+
[ -n "$rel" ] || continue
|
|
319
|
+
live="$REPO_ROOT/$rel"
|
|
320
|
+
snap="$SYNC_TX_DIR/data/$index"
|
|
321
|
+
if [ "$present" != 1 ]; then
|
|
322
|
+
if [ -e "$live" ] || [ -L "$live" ]; then return 1; fi
|
|
323
|
+
continue
|
|
324
|
+
fi
|
|
325
|
+
compare_sync_entries "$snap" "$live" || return $?
|
|
326
|
+
if [ -d "$SYNC_TX_DIR/targets/$index" ]; then
|
|
327
|
+
# validate_output_path permitted this physical directory inside
|
|
328
|
+
# the private project. Only its root is followed; descendants
|
|
329
|
+
# still use the entry-kind and literal-target comparison.
|
|
330
|
+
snap="$SYNC_TX_DIR/targets/$index"
|
|
331
|
+
live="$(cd "$live" && pwd -P)" || return 2
|
|
332
|
+
fi
|
|
333
|
+
[ ! -L "$snap" ] && [ -d "$snap" ] || continue
|
|
334
|
+
# NUL-delimited paths also preserve whitespace and newlines. find's
|
|
335
|
+
# default walk does not dereference links on GNU or BSD userland.
|
|
336
|
+
find "$snap" -print0 > "$SYNC_TX_DIR/snapshot.list" || return 2
|
|
337
|
+
find "$live" -print0 > "$SYNC_TX_DIR/live.list" || return 2
|
|
338
|
+
while IFS= read -r -d '' entry; do
|
|
339
|
+
sub="${entry#"$snap"}"
|
|
340
|
+
compare_sync_entries "$entry" "$live$sub" || return $?
|
|
341
|
+
done < "$SYNC_TX_DIR/snapshot.list"
|
|
342
|
+
while IFS= read -r -d '' entry; do
|
|
343
|
+
sub="${entry#"$live"}"
|
|
344
|
+
[ -e "$snap$sub" ] || [ -L "$snap$sub" ] || return 1
|
|
345
|
+
done < "$SYNC_TX_DIR/live.list"
|
|
346
|
+
done < "$SYNC_TX_INDEX"
|
|
347
|
+
}
|
|
348
|
+
|
|
277
349
|
finish_sync_transaction() {
|
|
278
350
|
local rc=$?
|
|
279
351
|
trap - EXIT INT TERM
|
|
@@ -625,6 +697,25 @@ if [ $synced -eq 0 ]; then
|
|
|
625
697
|
exit 1
|
|
626
698
|
fi
|
|
627
699
|
|
|
700
|
+
# A check renders exactly like a sync, then compares every snapshotted path
|
|
701
|
+
# with what the render left and restores the snapshot whatever the answer: it
|
|
702
|
+
# never changes a file. The transaction stays active until the restore is
|
|
703
|
+
# complete, so an interrupted restore is finished by the EXIT handler.
|
|
704
|
+
if [ -n "${IS_SYNC_CHECK:-}" ]; then
|
|
705
|
+
check_rc=0
|
|
706
|
+
compare_sync_snapshot || check_rc=$?
|
|
707
|
+
case "$check_rc" in
|
|
708
|
+
0) check_verdict=same ;;
|
|
709
|
+
1) check_verdict=differs ;;
|
|
710
|
+
*)
|
|
711
|
+
echo "ERROR: sync --check could not compare the rendered output with its snapshot." >&2
|
|
712
|
+
exit 1
|
|
713
|
+
;;
|
|
714
|
+
esac
|
|
715
|
+
restore_sync_snapshot
|
|
716
|
+
printf '%s\n' "$check_verdict" > "$IS_SYNC_CHECK"
|
|
717
|
+
fi
|
|
718
|
+
|
|
628
719
|
SYNC_TX_ACTIVE=0
|
|
629
720
|
|
|
630
721
|
# After rendering, three read-only reports, in this order:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainova-systems/intelligence",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "Build, version and distribute AI agent intelligence across your organization — one CLI, versioned Intelligence Packages, and a sync engine for Claude Code, Cursor, Copilot, Codex, Pi and OpenCode.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"intelligence": "bin/intelligence.js"
|
|
@@ -178,6 +178,7 @@ Use the engine library instead of copying parsers or file-handling logic.
|
|
|
178
178
|
| `copy_skill_bundle(src, dest)` | Copy `SKILL.md` and all resources safely, normalize Markdown, quote free-text frontmatter, and keep a valid `effort:` as written, as the shared skills tree does. |
|
|
179
179
|
| `copy_skill_bundle_dirs(dest_root, src...)` | Batch form: copy every skill directory into `dest_root/<name>` with one copy and one finalize pass. |
|
|
180
180
|
| `copy_skill_bundle_dirs_for(tool, dest_root, src...)` | The batch form for a tree one tool reads: `SKILL.md`'s `effort:` becomes that tool's level, or is removed when it has none. |
|
|
181
|
+
| `skill_source_rendered(skill_dir)` | Whether sync renders a skill directory an adapter listed with its own glob; a skill left out for its symlinks fails it. |
|
|
181
182
|
| `sync_open_skill_dirs(root, config, dest)` | Own and populate a shared Agent Skills directory such as `.agents/skills/`, deriving Codex's `agents/openai.yaml` for a skill with `disable-model-invocation: true`. |
|
|
182
183
|
| `finalize_output_file(file)` | Expand layout tokens and normalize line endings; required for every emitted text file. |
|
|
183
184
|
| `finalize_output_files(file...)` / `finalize_copy_files(dest, src...)` | Batch forms: finalize in place, or copy-and-finalize into a directory, in one process. |
|
|
@@ -212,6 +213,8 @@ If a new adapter relies on `AGENTS.md` for always-on rules, its target must requ
|
|
|
212
213
|
|
|
213
214
|
Every successful sync prints an adapter-agnostic `CONTEXT:` summary with source byte totals and file counts. It separates always-on rules from custom context (scoped rules, agent prompts and skill entry points), then reports a numeric `agents-md` byte count and `generated`, `not-generated`, or `disabled` status; supporting skill assets are excluded until explicitly read. Adapter-specific hard limits and suppression controls stay inside the adapter that owns them.
|
|
214
215
|
|
|
216
|
+
Print an adapter warning on stderr as one unindented line starting `WARNING:`. `sync --compact`, which `intelligence init` runs, keeps exactly those lines and drops indented progress, so a warning in any other form never reaches the reader.
|
|
217
|
+
|
|
215
218
|
The Codex adapter checks its `project_doc_max_bytes` default (32 KiB). When generated `AGENTS.md` exceeds it, sync prints the byte count and a sufficient Codex setting. The warning says "may truncate" because a developer can already have a larger override. `targets.codex.warn_project_doc_limit` accepts `true` or omission for the default threshold, a positive byte count to match another effective limit, or `false` to disable the Intelligence warning. Both inline and block target forms work, and the field does not change Codex configuration. The warning remains visible in `sync --compact`.
|
|
216
219
|
|
|
217
220
|
The Antigravity adapter checks the 12,000-character limit its documentation
|
|
@@ -237,7 +240,9 @@ Skills follow the [Agent Skills standard](https://agentskills.io). Copy each ski
|
|
|
237
240
|
copy_skill_bundle "$source_skill_dir" "$output_dir/skills/$skill_name"
|
|
238
241
|
```
|
|
239
242
|
|
|
240
|
-
Do not use plain `cp` for skill bundles. `copy_skill_bundle` preserves non-Markdown assets,
|
|
243
|
+
Do not use plain `cp` for skill bundles. `copy_skill_bundle` preserves non-Markdown assets, normalizes Markdown, expands layout tokens and quotes `description` and `argument-hint` where strict YAML readers require strings. It renders `effort:` as the shared tree does; a tree only one tool reads uses `copy_skill_bundle_dirs_for <tool>`, so the copy carries that tool's level or no effort at all. It never writes a symlink; how a link in a skills source renders is defined in [conventions](conventions.md#skill-body-and-resources).
|
|
244
|
+
|
|
245
|
+
An adapter that lists a skills source with its own glob checks each directory with `skill_source_rendered`. A skill whose directory or `SKILL.md` is a link leaving its source is left out of every output, and sync has already warned about it once.
|
|
241
246
|
|
|
242
247
|
Antigravity, Codex, Pi and OpenCode share `.agents/skills/`. Any adapter writing that open-standard directory must call `sync_open_skill_dirs`; it is the single lifecycle owner for immediate skill subdirectories.
|
|
243
248
|
|
|
@@ -311,6 +311,8 @@ skill-name/
|
|
|
311
311
|
|
|
312
312
|
The engine copies the complete skill directory. Promote a helper outside the skill only when multiple skills share it.
|
|
313
313
|
|
|
314
|
+
A symlink inside a skills source renders as the file or directory it points at when that stays inside the same source, so one source can alias a skill or share a resource between skills. A link that leaves its source, dangles or points at a directory enclosing it is left out with a `WARNING:` line; a skill whose directory or `SKILL.md` is such a link is left out entirely. Add a skill kept elsewhere as its own source or package instead of linking it in. Generated skill directories never contain symlinks.
|
|
315
|
+
|
|
314
316
|
Size limits are backstops, not quotas:
|
|
315
317
|
|
|
316
318
|
| Artifact | Hard cap | Response |
|
|
@@ -458,7 +460,7 @@ The permanent applied-schema key is the top-level scalar `schema_version` in `in
|
|
|
458
460
|
The public lifecycle is deliberately compact:
|
|
459
461
|
|
|
460
462
|
- `intelligence init [--preview|--apply]` is universal: it creates a new setup, aligns an existing Intelligence project, or plans/applies conversion of an eligible legacy Intelligence Sync project.
|
|
461
|
-
- `intelligence sync [adapter] [--compact] [--force]` first aligns an existing Intelligence project with the installed CLI and restores every package the store lacks or holds at another commit, strictly from `intelligence.lock`. It skips rendering when local inputs and outputs match a previous successful run. Changes or missing outputs trigger rendering; `--force` always renders and refreshes the search for unconfigured source directories. An unchanged run replays the last full run's useful diagnostics. Compact mode shows context sizes, actionable warnings and final status on success, and all diagnostics on failure. In CI it refuses an alignment that would change tracked files and points to a local `intelligence init --apply` plus review/commit.
|
|
463
|
+
- `intelligence sync [adapter] [--compact] [--force] [--check]` first aligns an existing Intelligence project with the installed CLI and restores every package the store lacks or holds at another commit, strictly from `intelligence.lock`. It skips rendering when local inputs and outputs match a previous successful run. Changes or missing outputs trigger rendering; `--force` always renders and refreshes the search for unconfigured source directories. An unchanged run replays the last full run's useful diagnostics. Compact mode shows context sizes, actionable warnings and final status on success, and all diagnostics on failure. In CI it refuses an alignment that would change tracked files and points to a local `intelligence init --apply` plus review/commit. `--check` changes no generated file: it prints one `IS_STATUS` line and exits 0 when generated files are up to date and 2 (`out-of-date`) when sync would change them or alignment is pending; it never applies alignment.
|
|
462
464
|
- `intelligence update [@scope/name] [--preview|--apply]` is the only update surface. It prints the CLI/project/package plan; default mode prompts, `--preview` never writes, and `--apply` does not prompt. It never moves `ref:` pins.
|
|
463
465
|
- `intelligence upgrade [--next] [--preview|--apply]` replaces the installed CLI with the newest version on its npm channel (`next` for a prerelease or with `--next`, otherwise `latest`) with the same modes. It touches no project, never downgrades, and refuses an installation that npm did not make.
|
|
464
466
|
- `intelligence package add|remove|list|search` owns package inventory.
|
|
@@ -479,6 +481,7 @@ The engine emits one machine-readable line, `IS_STATUS=<code> [IS_DETAIL=...]`,
|
|
|
479
481
|
| `migrated` | 0 | Initialization converted an older layout |
|
|
480
482
|
| `error` | 1 | Generic failure |
|
|
481
483
|
| `config-missing` | 2 | Required manifest is absent |
|
|
484
|
+
| `out-of-date` | 2 | `sync --check` only: sync would change generated files, or alignment is pending. A check never reports `config-missing`, and turns any other failure that would end in 2 into 1 |
|
|
482
485
|
| `ambiguous` | 3 | Conflicting state requiring agent/human judgment; reserved |
|
|
483
486
|
| `ahead-of-engine` | 4 | Manifest schema is a newer major than the engine (a newer minor or patch warns and continues) |
|
|
484
487
|
| `aborted-incomplete` | 5 | Staged replacement was incomplete; prior state remains |
|