@ainova-systems/intelligence 0.22.1 → 0.23.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 +1 -1
- package/cli/commands/adapter.sh +3 -3
- package/cli/commands/init.sh +6 -6
- package/cli/commands/package.sh +3 -3
- package/cli/commands/registry.sh +2 -2
- package/cli/commands/source.sh +2 -2
- package/cli/commands/sync.sh +8 -19
- package/cli/internal/check.sh +13 -7
- package/cli/lib/cli-common.sh +70 -27
- package/cli/lib/lockfile.sh +19 -7
- package/engine/ENGINE_SHA +1 -1
- package/engine/VERSION +1 -1
- package/engine/adapters/claude-plugin/hooks/register.js +3 -0
- package/engine/lib/contract.sh +2 -2
- package/engine/sync.sh +14 -9
- package/package.json +1 -1
- package/packages/sync/references/conventions.md +6 -6
- package/packages/sync/skills/intelligence-learn-from-repository/SKILL.md +5 -2
- package/packages/sync/skills/intelligence-sync/SKILL.md +7 -6
package/README.md
CHANGED
|
@@ -32,7 +32,7 @@ intelligence sync
|
|
|
32
32
|
|
|
33
33
|
| Command | What it does |
|
|
34
34
|
|---|---|
|
|
35
|
-
| `intelligence init [--preview\|--apply]` | Create, convert
|
|
35
|
+
| `intelligence init [--preview\|--apply]` | Create, convert or restore a project |
|
|
36
36
|
| `intelligence sync [adapter] [--compact] [--force]` | Restore locked content, then render or reuse verified unchanged output; `--force` renders and refreshes repository discovery |
|
|
37
37
|
| `intelligence update [@scope/name] [--latest] [--preview\|--apply]` | Plan or apply project and ranged-package updates; `--latest` crosses one package's range |
|
|
38
38
|
| `intelligence upgrade [--next] [--preview\|--apply]` | Replace the installed CLI with the newest version on its npm channel |
|
package/cli/commands/adapter.sh
CHANGED
|
@@ -47,7 +47,7 @@ adapter_create() {
|
|
|
47
47
|
[ -n "$name" ] && [ $# -eq 0 ] || die "usage: intelligence adapter create <name>"
|
|
48
48
|
assert_valid_target_name "$name"
|
|
49
49
|
require_cli_project
|
|
50
|
-
|
|
50
|
+
project_as_committed "$IP_ROOT"
|
|
51
51
|
local manifest="$IP_ROOT/intelligence.yaml" content_dir repo_phys probe old_ifs part probe_phys
|
|
52
52
|
local template adapter_dir adapter_phys dest tmp
|
|
53
53
|
local -a parts
|
|
@@ -95,7 +95,7 @@ adapter_remove() {
|
|
|
95
95
|
[ -n "$name" ] || die "usage: intelligence adapter remove <name> [--apply]"
|
|
96
96
|
assert_valid_target_name "$name"
|
|
97
97
|
require_cli_project
|
|
98
|
-
|
|
98
|
+
project_as_committed "$IP_ROOT"
|
|
99
99
|
manifest="$IP_ROOT/intelligence.yaml"
|
|
100
100
|
content_dir="$(manifest_intelligence_dir "$manifest")"
|
|
101
101
|
case "$content_dir" in
|
|
@@ -140,7 +140,7 @@ case "$action" in
|
|
|
140
140
|
require_cli_project
|
|
141
141
|
# Held through the final render: target-state and sync join it.
|
|
142
142
|
project_lock_hold "$IP_ROOT"
|
|
143
|
-
|
|
143
|
+
project_as_committed "$IP_ROOT"
|
|
144
144
|
if [ "$action" = "enable" ]; then
|
|
145
145
|
state_stage="$(mktemp -d -t intelligence-adapter-state-XXXXXX)"
|
|
146
146
|
cp "$IP_ROOT/intelligence.yaml" "$state_stage/intelligence.yaml"
|
package/cli/commands/init.sh
CHANGED
|
@@ -132,7 +132,11 @@ case "$IP_MODE" in
|
|
|
132
132
|
if project_stamped_ahead "$IP_ROOT"; then
|
|
133
133
|
echo " project schema $(read_schema_version "$IP_ROOT/intelligence.yaml") is ahead of engine $(bundled_engine_version) — left as is (update the CLI)"
|
|
134
134
|
elif project_needs_upgrade "$IP_ROOT"; then
|
|
135
|
-
|
|
135
|
+
if [ "$IS_UPGRADE_KIND" = behind ]; then
|
|
136
|
+
echo " project versions trail engine $(bundled_engine_version) — kept as committed; intelligence update moves them"
|
|
137
|
+
else
|
|
138
|
+
echo " project needs a migration to engine $(bundled_engine_version) — run: intelligence update"
|
|
139
|
+
fi
|
|
136
140
|
else
|
|
137
141
|
echo " schema/content already match engine $(bundled_engine_version)"
|
|
138
142
|
fi
|
|
@@ -151,11 +155,7 @@ case "$IP_MODE" in
|
|
|
151
155
|
fi
|
|
152
156
|
exit 0
|
|
153
157
|
fi
|
|
154
|
-
|
|
155
|
-
ensure_project_current "$IP_ROOT" --explicit
|
|
156
|
-
else
|
|
157
|
-
ensure_project_current "$IP_ROOT"
|
|
158
|
-
fi
|
|
158
|
+
project_as_committed "$IP_ROOT"
|
|
159
159
|
restore_project_store_if_missing "$IP_ROOT"
|
|
160
160
|
ensure_manifest_gitignore "$IP_ROOT" "$IP_ROOT/intelligence.yaml"
|
|
161
161
|
ensure_manifest_publisher_ignores "$IP_ROOT" "$IP_ROOT/intelligence.yaml"
|
package/cli/commands/package.sh
CHANGED
|
@@ -10,17 +10,17 @@ shift
|
|
|
10
10
|
case "$action" in
|
|
11
11
|
add)
|
|
12
12
|
require_cli_project
|
|
13
|
-
|
|
13
|
+
project_as_committed "$IP_ROOT"
|
|
14
14
|
exec bash "$CLI_DIR/internal/package-add.sh" "$@"
|
|
15
15
|
;;
|
|
16
16
|
remove)
|
|
17
17
|
require_cli_project
|
|
18
|
-
|
|
18
|
+
project_as_committed "$IP_ROOT"
|
|
19
19
|
exec bash "$CLI_DIR/internal/package-remove.sh" "$@"
|
|
20
20
|
;;
|
|
21
21
|
alias)
|
|
22
22
|
require_cli_project
|
|
23
|
-
|
|
23
|
+
project_as_committed "$IP_ROOT"
|
|
24
24
|
exec bash "$CLI_DIR/internal/package-alias.sh" "$@"
|
|
25
25
|
;;
|
|
26
26
|
list)
|
package/cli/commands/registry.sh
CHANGED
|
@@ -40,7 +40,7 @@ case "$sub" in
|
|
|
40
40
|
esac
|
|
41
41
|
assert_safe_source_url "${url#git+}"
|
|
42
42
|
require_cli_project
|
|
43
|
-
|
|
43
|
+
project_as_committed "$IP_ROOT"
|
|
44
44
|
# Fail closed: a URL that cannot produce an index is not a registry,
|
|
45
45
|
# and recording it would turn a typo here into a confusing failure at
|
|
46
46
|
# the first add. --force covers the one honest case: the registry is
|
|
@@ -71,7 +71,7 @@ case "$sub" in
|
|
|
71
71
|
url="${2:-}"
|
|
72
72
|
[ -n "$url" ] || die "usage: intelligence registry remove <url>"
|
|
73
73
|
require_cli_project
|
|
74
|
-
|
|
74
|
+
project_as_committed "$IP_ROOT"
|
|
75
75
|
registries_remove "$IP_ROOT/intelligence.yaml" "$url"
|
|
76
76
|
# The retired flat-map form also stored scope keys — drop one if the
|
|
77
77
|
# argument names it, so old manifests clean up with the old command.
|
package/cli/commands/source.sh
CHANGED
|
@@ -139,7 +139,7 @@ case "$action" in
|
|
|
139
139
|
dir="$(normalize_source_dir "$dir")"
|
|
140
140
|
assert_valid_source_dir "$IP_ROOT" "$dir"
|
|
141
141
|
[ "$anchor" != "$dir" ] || die "cannot place '$dir' relative to itself"
|
|
142
|
-
|
|
142
|
+
project_as_committed "$IP_ROOT"
|
|
143
143
|
manifest="$IP_ROOT/intelligence.yaml"
|
|
144
144
|
|
|
145
145
|
# The anchor may be spelled differently from the entry it means — a
|
|
@@ -189,7 +189,7 @@ case "$action" in
|
|
|
189
189
|
require_cli_project
|
|
190
190
|
manifest="$IP_ROOT/intelligence.yaml"
|
|
191
191
|
assert_not_package_reference "$manifest" "$dir" remove
|
|
192
|
-
|
|
192
|
+
project_as_committed "$IP_ROOT"
|
|
193
193
|
|
|
194
194
|
if ! sources_has_entry "$manifest" "$section" "$dir"; then
|
|
195
195
|
echo "not listed: sources.$section does not hold $dir"
|
package/cli/commands/sync.sh
CHANGED
|
@@ -58,11 +58,10 @@ run_sync() {
|
|
|
58
58
|
# One writer per project at a time: the store restore and the
|
|
59
59
|
# render below both rewrite shared state (sync-lock.sh).
|
|
60
60
|
hold_project
|
|
61
|
-
# `sync` is the normal fresh-clone command.
|
|
62
|
-
#
|
|
63
|
-
#
|
|
64
|
-
|
|
65
|
-
ensure_project_current "$IP_ROOT" || return $?
|
|
61
|
+
# `sync` is the normal fresh-clone command. It renders the project as
|
|
62
|
+
# committed, whichever CLI runs it, and restores a missing ignored
|
|
63
|
+
# store strictly from the committed lock.
|
|
64
|
+
project_as_committed "$IP_ROOT" || return $?
|
|
66
65
|
restore_project_store_if_missing "$IP_ROOT" || return $?
|
|
67
66
|
export_engine_env "$IP_ROOT" || return $?
|
|
68
67
|
sync_with_cache "$target" "$force" || return $?
|
|
@@ -88,12 +87,10 @@ run_sync() {
|
|
|
88
87
|
esac
|
|
89
88
|
}
|
|
90
89
|
|
|
91
|
-
# run_check — the same preflight as sync,
|
|
92
|
-
#
|
|
93
|
-
#
|
|
94
|
-
# allowed: it is reproducible state, and the comparison needs it.
|
|
90
|
+
# run_check — the same preflight as sync, with everything but the verdict on
|
|
91
|
+
# stderr. Restoring the ignored package store from the lock is allowed: it is
|
|
92
|
+
# reproducible state, and the comparison needs it.
|
|
95
93
|
run_check() {
|
|
96
|
-
local stamp
|
|
97
94
|
detect_project || return $?
|
|
98
95
|
case "$IP_MODE" in
|
|
99
96
|
cli) ;;
|
|
@@ -111,15 +108,7 @@ run_check() {
|
|
|
111
108
|
# shellcheck disable=SC2034 # read by sync-lock.sh when the lock is taken
|
|
112
109
|
SYNC_LOCK_KIND=check
|
|
113
110
|
hold_project
|
|
114
|
-
|
|
115
|
-
if project_needs_upgrade "$IP_ROOT"; then
|
|
116
|
-
read_schema_version_var "$IP_ROOT/intelligence.yaml"
|
|
117
|
-
stamp="$IS_SCHEMA_VERSION"
|
|
118
|
-
bundled_engine_version_var
|
|
119
|
-
IS_CHECK_OUT_OF_DATE=1
|
|
120
|
-
is_status out-of-date "the project needs alignment (stamp ${stamp:-unstamped}, engine $IS_BUNDLED_ENGINE_VERSION); run 'intelligence init --apply' locally, review and commit the diff"
|
|
121
|
-
return "$IS_RC_OUT_OF_DATE"
|
|
122
|
-
fi
|
|
111
|
+
project_as_committed "$IP_ROOT" || return $?
|
|
123
112
|
restore_project_store_if_missing "$IP_ROOT" keep-sources >&2 || return $?
|
|
124
113
|
export_engine_env "$IP_ROOT" || return $?
|
|
125
114
|
sync_check "$target" "$force" || return $?
|
package/cli/internal/check.sh
CHANGED
|
@@ -41,7 +41,7 @@ fi
|
|
|
41
41
|
stamp="$(read_schema_version "$manifest")"
|
|
42
42
|
eng="$(bundled_engine_version)"
|
|
43
43
|
if [ -z "$stamp" ]; then
|
|
44
|
-
warn "manifest has no schema_version — run 'intelligence
|
|
44
|
+
warn "manifest has no schema_version — run 'intelligence update'"
|
|
45
45
|
elif _ver_gt "$stamp" "$eng"; then
|
|
46
46
|
if [ "$(_ver_major "$stamp")" -gt "$(_ver_major "$eng")" ]; then
|
|
47
47
|
warn "manifest schema $stamp is a newer major than this CLI's engine $eng — update the CLI: intelligence upgrade (--next for a prerelease line)"
|
|
@@ -49,13 +49,17 @@ elif _ver_gt "$stamp" "$eng"; then
|
|
|
49
49
|
note "manifest schema $stamp is newer than this CLI's engine $eng — the project uses a newer CLI; update it: intelligence upgrade (--next for a prerelease line)"
|
|
50
50
|
fi
|
|
51
51
|
elif _ver_gt "$eng" "$stamp"; then
|
|
52
|
-
|
|
52
|
+
if [ "$(_ver_major "$stamp")" = "$(_ver_major "$eng")" ]; then
|
|
53
|
+
note "manifest schema $stamp is older than this CLI's engine $eng — kept as committed; move it with: intelligence update"
|
|
54
|
+
else
|
|
55
|
+
warn "manifest schema $stamp is an older major than this CLI's engine $eng — run 'intelligence update'"
|
|
56
|
+
fi
|
|
53
57
|
else
|
|
54
58
|
ok "schema_version $stamp matches the engine"
|
|
55
59
|
fi
|
|
56
60
|
|
|
57
|
-
# The engine-content package
|
|
58
|
-
#
|
|
61
|
+
# The engine-content package follows the project's own version: the stamp,
|
|
62
|
+
# not the CLI, decides which content renders (decision 0023).
|
|
59
63
|
sync_locked=""
|
|
60
64
|
if [ "$lock_valid" -eq 1 ]; then
|
|
61
65
|
sync_locked="$(qmap_field "$lock" "packages" "$SYNC_PKG_NAME" "resolved")"
|
|
@@ -65,12 +69,14 @@ if [ -n "$sync_locked" ]; then
|
|
|
65
69
|
ok "$SYNC_PKG_NAME at $sync_locked (matches the engine)"
|
|
66
70
|
elif [ "${sync_locked#v}" = "$stamp" ] && _ver_gt "$stamp" "$eng"; then
|
|
67
71
|
note "$SYNC_PKG_NAME at $sync_locked (matches the project schema; the engine is $eng)"
|
|
72
|
+
elif [ "${sync_locked#v}" = "$stamp" ] && [ "$(_ver_major "$stamp")" = "$(_ver_major "$eng")" ]; then
|
|
73
|
+
note "$SYNC_PKG_NAME at $sync_locked (matches the project schema; intelligence update moves it to $eng)"
|
|
68
74
|
else
|
|
69
|
-
warn "$SYNC_PKG_NAME locked at $sync_locked but the engine is $eng — run 'intelligence
|
|
75
|
+
warn "$SYNC_PKG_NAME locked at $sync_locked but the engine is $eng — run 'intelligence update'"
|
|
70
76
|
fi
|
|
71
77
|
fi
|
|
72
78
|
if [ -d "$IP_ROOT/.intelligence/engine" ]; then
|
|
73
|
-
warn "stale .intelligence/engine directory (pre-package layout) — run 'intelligence
|
|
79
|
+
warn "stale .intelligence/engine directory (pre-package layout) — run 'intelligence update'"
|
|
74
80
|
fi
|
|
75
81
|
|
|
76
82
|
# Manifest packages: names valid, requested intent only, locked and installed.
|
|
@@ -96,7 +102,7 @@ while IFS= read -r name; do
|
|
|
96
102
|
|| warn "$name pins ref '$m_ref' but the lock resolved '$l_res'"
|
|
97
103
|
if [ -n "$(qmap_field "$manifest" "packages" "$name" "url")" ] \
|
|
98
104
|
|| [ -n "$(qmap_field "$manifest" "packages" "$name" "path")" ]; then
|
|
99
|
-
warn "$name stores source details in the manifest — run 'intelligence
|
|
105
|
+
warn "$name stores source details in the manifest — run 'intelligence update' to move them to the lock-only model"
|
|
100
106
|
fi
|
|
101
107
|
if [ ! -d "$IP_ROOT/.intelligence/packages/$name" ]; then
|
|
102
108
|
warn "$name is locked but not installed — run 'intelligence sync'"
|
package/cli/lib/cli-common.sh
CHANGED
|
@@ -344,17 +344,10 @@ export_engine_env() {
|
|
|
344
344
|
}
|
|
345
345
|
|
|
346
346
|
# --- Project lifecycle preflight -----------------------------------------
|
|
347
|
-
# Public commands are intentionally few. They share this state gate
|
|
348
|
-
#
|
|
349
|
-
#
|
|
350
|
-
#
|
|
351
|
-
|
|
352
|
-
is_ci_environment() {
|
|
353
|
-
case "${CI:-}" in
|
|
354
|
-
1|true|TRUE|True|yes|YES|Yes|on|ON|On) return 0 ;;
|
|
355
|
-
*) return 1 ;;
|
|
356
|
-
esac
|
|
357
|
-
}
|
|
347
|
+
# Public commands are intentionally few. They share this state gate. Only
|
|
348
|
+
# `update` moves a project's versions forward (decision 0023); every other
|
|
349
|
+
# command works on the project as committed, or refuses one that needs a
|
|
350
|
+
# migration first.
|
|
358
351
|
|
|
359
352
|
# Validate a repository-relative project content directory, including every
|
|
360
353
|
# existing symlinked path component. Call before writing a new manifest.
|
|
@@ -395,23 +388,37 @@ project_stamped_ahead() {
|
|
|
395
388
|
[ -n "$stamp" ] && _ver_gt "$stamp" "$IS_BUNDLED_ENGINE_VERSION"
|
|
396
389
|
}
|
|
397
390
|
|
|
391
|
+
# project_needs_upgrade <root> — true when `update` would align the project.
|
|
392
|
+
# IS_UPGRADE_KIND says how far behind it is: `behind` when only the schema
|
|
393
|
+
# stamp or the sync content pin trails this engine within its major, which
|
|
394
|
+
# every command renders around, with IS_UPGRADE_DESC naming what trails;
|
|
395
|
+
# `migrate` when the project needs a change only alignment applies (no stamp,
|
|
396
|
+
# an older major, a legacy manifest shape, a sync content pin that is no
|
|
397
|
+
# version).
|
|
398
398
|
project_needs_upgrade() {
|
|
399
399
|
local root="$1" manifest="$1/intelligence.yaml" stamp eng pinned locked name url path rows
|
|
400
|
-
local lname _requested _url _path resolved _sha
|
|
400
|
+
local lname _requested _url _path resolved _sha behind=0 pin_behind="" value
|
|
401
|
+
IS_UPGRADE_KIND="" IS_UPGRADE_DESC=""
|
|
401
402
|
[ -f "$manifest" ] || return 1
|
|
402
403
|
read_schema_version_var "$manifest"
|
|
403
404
|
stamp="$IS_SCHEMA_VERSION"
|
|
404
405
|
bundled_engine_version_var
|
|
405
406
|
eng="$IS_BUNDLED_ENGINE_VERSION"
|
|
406
|
-
[ -z "$stamp" ]
|
|
407
|
+
if [ -z "$stamp" ]; then IS_UPGRADE_KIND=migrate; return 0; fi
|
|
407
408
|
# A project stamped ahead belongs to a newer CLI. Aligning it here would
|
|
408
409
|
# restamp the schema and re-pin the engine content DOWNWARD, and the next
|
|
409
410
|
# teammate on the current CLI would move both back: leave it as found.
|
|
410
411
|
project_stamped_ahead "$root" && return 1
|
|
411
412
|
_qmap_read_var top "$manifest" '' sync_version || true
|
|
412
|
-
[ -
|
|
413
|
-
|
|
414
|
-
|
|
413
|
+
if [ -n "$IS_QMAP_OUT" ] || [ -d "$root/.intelligence/engine" ]; then
|
|
414
|
+
IS_UPGRADE_KIND=migrate; return 0
|
|
415
|
+
fi
|
|
416
|
+
if _ver_gt "$eng" "$stamp"; then
|
|
417
|
+
if [ "$(_ver_major "$stamp")" != "$(_ver_major "$eng")" ]; then
|
|
418
|
+
IS_UPGRADE_KIND=migrate; return 0
|
|
419
|
+
fi
|
|
420
|
+
behind=1
|
|
421
|
+
fi
|
|
415
422
|
|
|
416
423
|
# One manifest pass for every package's fields, not a reader per field.
|
|
417
424
|
_qmap_read_var fieldrows "$manifest" packages '' 'url path version' || true
|
|
@@ -420,8 +427,7 @@ project_needs_upgrade() {
|
|
|
420
427
|
[ -n "$name" ] || continue
|
|
421
428
|
# Early RC manifests mixed requested intent with resolved source
|
|
422
429
|
# details. Source URL/path now live only in the required lockfile.
|
|
423
|
-
[ -n "$url" ]
|
|
424
|
-
[ -n "$path" ] && return 0
|
|
430
|
+
if [ -n "$url" ] || [ -n "$path" ]; then IS_UPGRADE_KIND=migrate; return 0; fi
|
|
425
431
|
if [ "$name" = "$SYNC_PKG_NAME" ]; then
|
|
426
432
|
# The first lock row for the name: what qmap_field would decode.
|
|
427
433
|
locked=""
|
|
@@ -431,14 +437,52 @@ project_needs_upgrade() {
|
|
|
431
437
|
locked="$resolved"
|
|
432
438
|
break
|
|
433
439
|
done <<< "$IS_QMAP_OUT"
|
|
434
|
-
[ "$
|
|
435
|
-
|
|
436
|
-
[ -n "$locked" ] || return 0
|
|
437
|
-
[ "${locked#v}" = "$eng" ] || return 0
|
|
440
|
+
if [ -f "$root/intelligence.lock" ] && [ -z "$locked" ]; then
|
|
441
|
+
IS_UPGRADE_KIND=migrate; return 0
|
|
438
442
|
fi
|
|
443
|
+
# The manifest pin, then the lock row. One ahead of this engine is
|
|
444
|
+
# a newer CLI's, left as found like a stamp ahead (decision 0005).
|
|
445
|
+
for value in "$pinned" "${locked#v}"; do
|
|
446
|
+
[ -n "$value" ] && [ "$value" != "$eng" ] || continue
|
|
447
|
+
case "$value" in [0-9]*.[0-9]*.[0-9]*) ;; *) IS_UPGRADE_KIND=migrate; return 0 ;; esac
|
|
448
|
+
_ver_gt "$eng" "$value" || continue
|
|
449
|
+
[ "$(_ver_major "$value")" = "$(_ver_major "$eng")" ] || { IS_UPGRADE_KIND=migrate; return 0; }
|
|
450
|
+
behind=1
|
|
451
|
+
[ -n "$pin_behind" ] || pin_behind="$value"
|
|
452
|
+
done
|
|
439
453
|
fi
|
|
440
454
|
done <<< "$rows"
|
|
441
|
-
return 1
|
|
455
|
+
[ "$behind" = 1 ] || return 1
|
|
456
|
+
IS_UPGRADE_KIND=behind
|
|
457
|
+
# What the warning names: only the versions that actually trail.
|
|
458
|
+
if _ver_gt "$eng" "$stamp"; then IS_UPGRADE_DESC="schema $stamp"; fi
|
|
459
|
+
[ -z "$pin_behind" ] || IS_UPGRADE_DESC="${IS_UPGRADE_DESC:+$IS_UPGRADE_DESC, }$SYNC_PKG_NAME $pin_behind"
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
# project_as_committed <root> — the gate of every project-aware command but
|
|
463
|
+
# `update`: the preflight, then the project as committed. One whose versions
|
|
464
|
+
# only trail this engine within its major proceeds behind one warning and
|
|
465
|
+
# keeps its tracked bytes; one that needs a migration is refused with
|
|
466
|
+
# IS_STATUS=needs-update and exit 6.
|
|
467
|
+
project_as_committed() {
|
|
468
|
+
local root="$1" stamp
|
|
469
|
+
project_preflight "$root" || return $?
|
|
470
|
+
project_needs_upgrade "$root" || return 0
|
|
471
|
+
read_schema_version_var "$root/intelligence.yaml"
|
|
472
|
+
stamp="$IS_SCHEMA_VERSION"
|
|
473
|
+
bundled_engine_version_var
|
|
474
|
+
if [ "$IS_UPGRADE_KIND" = behind ]; then
|
|
475
|
+
# Once per command, however many processes check on the way to the
|
|
476
|
+
# engine; unindented, so `sync --compact` keeps it.
|
|
477
|
+
if [ "${IS_PROJECT_BEHIND_WARNED:-}" != "$stamp" ]; then
|
|
478
|
+
echo "WARNING: project versions ($IS_UPGRADE_DESC) trail this CLI's engine $IS_BUNDLED_ENGINE_VERSION — they stay as committed; move them with: intelligence update" >&2
|
|
479
|
+
export IS_PROJECT_BEHIND_WARNED="$stamp"
|
|
480
|
+
fi
|
|
481
|
+
return 0
|
|
482
|
+
fi
|
|
483
|
+
is_status needs-update "stamp=${stamp:-unstamped} engine=$IS_BUNDLED_ENGINE_VERSION"
|
|
484
|
+
echo "ERROR: the project needs a migration this command does not apply (schema ${stamp:-unstamped}, engine $IS_BUNDLED_ENGINE_VERSION) — run: intelligence update" >&2
|
|
485
|
+
return "$IS_RC_NEEDS_UPDATE"
|
|
442
486
|
}
|
|
443
487
|
|
|
444
488
|
# A manifest with packages but no lock has no trustworthy resolved state from
|
|
@@ -466,17 +510,16 @@ project_preflight() {
|
|
|
466
510
|
fi
|
|
467
511
|
}
|
|
468
512
|
|
|
513
|
+
# ensure_project_current <root> — align the project to this engine. `update`
|
|
514
|
+
# alone calls it (decision 0023).
|
|
469
515
|
ensure_project_current() {
|
|
470
|
-
local root="$1"
|
|
516
|
+
local root="$1" manifest="$1/intelligence.yaml" stamp eng
|
|
471
517
|
project_preflight "$root" || return $?
|
|
472
518
|
project_needs_upgrade "$root" || return 0
|
|
473
519
|
read_schema_version_var "$manifest"
|
|
474
520
|
stamp="$IS_SCHEMA_VERSION"
|
|
475
521
|
bundled_engine_version_var
|
|
476
522
|
eng="$IS_BUNDLED_ENGINE_VERSION"
|
|
477
|
-
if is_ci_environment && [ "$explicit" != "--explicit" ]; then
|
|
478
|
-
die "project lifecycle requires alignment (stamp ${stamp:-unstamped}, engine $eng) — run 'intelligence init --apply' locally, review and commit the diff"
|
|
479
|
-
fi
|
|
480
523
|
echo " project alignment: stamp ${stamp:-unstamped}, engine $eng"
|
|
481
524
|
bash "$CLI_DIR/internal/align-project.sh" --no-sync || return $?
|
|
482
525
|
project_reads_refresh "$root"
|
package/cli/lib/lockfile.sh
CHANGED
|
@@ -70,6 +70,15 @@ lock_validate_checks() {
|
|
|
70
70
|
continue
|
|
71
71
|
fi
|
|
72
72
|
fi
|
|
73
|
+
if [ -z "$sha" ] && [ "$url" = "$SYNC_PKG_URL" ] && [ "$path" = "$SYNC_PKG_PATH" ]; then
|
|
74
|
+
# Bundle metadata pins the content a CLI ships; only this CLI's own
|
|
75
|
+
# version restores without a commit. update moves an older pin to it;
|
|
76
|
+
# a newer one needs a newer CLI.
|
|
77
|
+
if [[ "$resolved" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]] && _ver_gt "${resolved#v}" "$current"; then
|
|
78
|
+
die "locked restore: $name $resolved has a missing or invalid commit SHA, and this CLI bundles v$current — update the CLI: intelligence upgrade"
|
|
79
|
+
fi
|
|
80
|
+
die "locked restore: $name $resolved has a missing or invalid commit SHA, and this CLI bundles v$current — run: intelligence update"
|
|
81
|
+
fi
|
|
73
82
|
[[ "$sha" =~ ^[0-9a-f]{40}$ || "$sha" =~ ^[0-9a-f]{64}$ ]] \
|
|
74
83
|
|| die "locked restore: $name has a missing or invalid commit SHA — restore a valid intelligence.lock"
|
|
75
84
|
done <<< "$rows"
|
|
@@ -128,16 +137,19 @@ lock_write_from_tsv() {
|
|
|
128
137
|
}
|
|
129
138
|
|
|
130
139
|
# lock_upsert <lock> <name> <requested> <url> <path> <resolved> <sha>
|
|
131
|
-
# Replace
|
|
140
|
+
# Replace one entry where it stands, or append a new one, keeping the others:
|
|
141
|
+
# an update changes only that package's lines in the committed lock.
|
|
132
142
|
lock_upsert() {
|
|
133
143
|
local lock="$1" name="$2" requested="$3" url="$4" path="$5" resolved="$6" sha="$7"
|
|
134
|
-
local tsv
|
|
144
|
+
local tsv row
|
|
135
145
|
tsv="$(mktemp -t intelligence-lock-XXXXXX 2>/dev/null || mktemp)"
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
146
|
+
printf -v row '%s\037%s\037%s\037%s\037%s\037%s' \
|
|
147
|
+
"$name" "$requested" "$url" "$path" "$resolved" "$sha"
|
|
148
|
+
lock_to_tsv "$lock" | IS_LOCK_ROW="$row" awk -F"$LOCK_SEP" -v n="$name" '
|
|
149
|
+
$1 == n { if (!done) print ENVIRON["IS_LOCK_ROW"]; done = 1; next }
|
|
150
|
+
{ print }
|
|
151
|
+
END { if (!done) print ENVIRON["IS_LOCK_ROW"] }
|
|
152
|
+
' > "$tsv"
|
|
141
153
|
lock_write_from_tsv "$lock" "$tsv"
|
|
142
154
|
rm -f "$tsv"
|
|
143
155
|
}
|
package/engine/ENGINE_SHA
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
79201cedae74ec96e67c3aa94e267f6b1e226c23
|
package/engine/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.23.0
|
|
@@ -196,6 +196,9 @@ async function runCheck($) {
|
|
|
196
196
|
// session's check — is not a fault: the last verdict stays, and the check
|
|
197
197
|
// asks again shortly instead of queueing ahead of a waiting sync.
|
|
198
198
|
else if (LOCK_REFUSAL.test(result.stderr || '')) retrySoon($)
|
|
199
|
+
// A project that needs a migration names the command that applies it on
|
|
200
|
+
// stderr; the status detail only names the versions.
|
|
201
|
+
else if (parsed.status === 'needs-update') setState('error', reasonLine(result.stderr) || 'run intelligence update')
|
|
199
202
|
else setState('error', parsed.detail || reasonLine(result.stderr) || 'exit ' + result.exitCode)
|
|
200
203
|
show($)
|
|
201
204
|
}
|
package/engine/lib/contract.sh
CHANGED
|
@@ -83,9 +83,9 @@ IS_RC_CONFIG_MISSING=2 # no manifest found
|
|
|
83
83
|
IS_RC_AMBIGUOUS=3 # conflicting state; agent/human-only — bash never emits this itself
|
|
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
|
-
IS_RC_NEEDS_UPDATE=6 #
|
|
86
|
+
IS_RC_NEEDS_UPDATE=6 # a migration only `intelligence update` applies (no stamp, older major)
|
|
87
87
|
# `intelligence sync --check` only: generated files differ from what sync would
|
|
88
|
-
# leave
|
|
88
|
+
# leave (IS_STATUS=out-of-date). It shares 2 with
|
|
89
89
|
# config-missing, which a check never reports: the CLI found the manifest, and
|
|
90
90
|
# the check turns any other failure that ends in 2 into 1.
|
|
91
91
|
IS_RC_OUT_OF_DATE=2
|
package/engine/sync.sh
CHANGED
|
@@ -39,10 +39,10 @@ _vc_rc=0
|
|
|
39
39
|
check_version_compat "$_cf" || _vc_rc=$?
|
|
40
40
|
if [ "$_vc_rc" -ne 0 ]; then exit "$_vc_rc"; fi
|
|
41
41
|
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
42
|
+
# sync is a PURE synchronizer: it never changes a schema. The manifest is
|
|
43
|
+
# additive within a major, so an older stamp of the same major renders as
|
|
44
|
+
# committed behind one warning (decision 0023); an older major, or no stamp at
|
|
45
|
+
# all, needs the migration only `intelligence update` applies.
|
|
46
46
|
read_schema_version_var "$_cf"
|
|
47
47
|
_stamp="$IS_SCHEMA_VERSION"
|
|
48
48
|
engine_version_var
|
|
@@ -51,13 +51,18 @@ _eng="$IS_ENGINE_VERSION"
|
|
|
51
51
|
if [ -z "$_stamp" ]; then
|
|
52
52
|
is_status needs-update "stamped= engine=$_eng (no schema_version)"
|
|
53
53
|
echo "ERROR: the manifest has no schema_version — schema un-applied." >&2
|
|
54
|
-
echo " Run: intelligence
|
|
54
|
+
echo " Run: intelligence update" >&2
|
|
55
55
|
exit "$IS_RC_NEEDS_UPDATE"
|
|
56
56
|
elif [ -n "$_eng" ] && _ver_gt "$_eng" "$_stamp"; then
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
if [ "$(_ver_major "$_stamp")" != "$(_ver_major "$_eng")" ]; then
|
|
58
|
+
is_status needs-update "stamped=$_stamp engine=$_eng"
|
|
59
|
+
echo "ERROR: project at $_stamp but engine is $_eng — an older major schema." >&2
|
|
60
|
+
echo " Run: intelligence update" >&2
|
|
61
|
+
exit "$IS_RC_NEEDS_UPDATE"
|
|
62
|
+
fi
|
|
63
|
+
if [ "${IS_PROJECT_BEHIND_WARNED:-}" != "$_stamp" ]; then
|
|
64
|
+
echo "WARNING: project versions (schema $_stamp) trail this CLI's engine $_eng — they stay as committed; move them with: intelligence update" >&2
|
|
65
|
+
fi
|
|
61
66
|
fi
|
|
62
67
|
|
|
63
68
|
# Normalize REPO_ROOT and CONFIG_FILE to one `cd && pwd` spelling so
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainova-systems/intelligence",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.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"
|
|
@@ -125,7 +125,7 @@ Practice:
|
|
|
125
125
|
|
|
126
126
|
Commit `intelligence.lock`. It records requested versions, source URLs and paths, resolved refs and commit SHAs. After cloning, or after a pull that moved the lock, `intelligence sync` restores every package the store lacks or holds at another commit, strictly from that lock, before rendering; manifest/lock or SHA drift is refused. Re-run `package add` when deliberately changing a source.
|
|
127
127
|
|
|
128
|
-
`@ainova-systems/sync` is ordinary package content exact-pinned to the bundled engine version. `intelligence init` installs it unless `--bare` is used.
|
|
128
|
+
`@ainova-systems/sync` is ordinary package content exact-pinned to the bundled engine version. `intelligence init` installs it unless `--bare` is used. Only `intelligence update` moves that pin and `schema_version` to the installed CLI; every other command keeps them as committed, and package-range updates never move the pin independently.
|
|
129
129
|
|
|
130
130
|
## Layout tokens
|
|
131
131
|
|
|
@@ -504,15 +504,15 @@ The permanent applied-schema key is the top-level scalar `schema_version` in `in
|
|
|
504
504
|
|
|
505
505
|
The public lifecycle is deliberately compact:
|
|
506
506
|
|
|
507
|
-
- `intelligence init [--preview|--apply]` is universal: it creates a new setup,
|
|
508
|
-
- `intelligence sync [adapter] [--compact] [--force] [--check]` first
|
|
507
|
+
- `intelligence init [--preview|--apply]` is universal: it creates a new setup, restores an existing Intelligence project as committed, or plans/applies conversion of an eligible legacy Intelligence Sync project.
|
|
508
|
+
- `intelligence sync [adapter] [--compact] [--force] [--check]` first 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. It renders an Intelligence project at its committed versions: versions that trail the installed CLI within its major render behind one warning naming `intelligence update`; a project that needs a migration first — no `schema_version` or an older major — is refused with `needs-update`, locally and in CI alike. `--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; it never moves a version.
|
|
509
509
|
- `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.
|
|
510
510
|
- `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.
|
|
511
511
|
- `intelligence package add|remove|list|search` owns package inventory.
|
|
512
512
|
- `intelligence adapter list|create|enable|disable|remove` owns adapter inventory and target state.
|
|
513
513
|
- `intelligence status [--check]` reports state; `--check` runs deep consistency checks.
|
|
514
514
|
|
|
515
|
-
Implement Intelligence schema changes as idempotent structural checks. Stage and verify replacement state before deleting or replacing prior state. A stale engine refuses a manifest whose `schema_version` is a newer major; a newer minor or patch within the same major warns once and proceeds without restamping the project.
|
|
515
|
+
Implement Intelligence schema changes as idempotent structural checks. Stage and verify replacement state before deleting or replacing prior state. A stale engine refuses a manifest whose `schema_version` is a newer major; a newer minor or patch within the same major warns once and proceeds without restamping the project. A project behind the engine stays as committed until `intelligence update` closes the gap.
|
|
516
516
|
|
|
517
517
|
Breaking changelog entries use a `### Breaking` checklist of verifiable post-conditions. The `intelligence-upgrade` skill reads every release across the version gap, chooses the package/CLI/project command sequence and verifies those conditions after the deterministic command completes.
|
|
518
518
|
|
|
@@ -526,11 +526,11 @@ The engine emits one machine-readable line, `IS_STATUS=<code> [IS_DETAIL=...]`,
|
|
|
526
526
|
| `migrated` | 0 | Initialization converted an older layout |
|
|
527
527
|
| `error` | 1 | Generic failure |
|
|
528
528
|
| `config-missing` | 2 | Required manifest is absent |
|
|
529
|
-
| `out-of-date` | 2 | `sync --check` only: sync would change generated files
|
|
529
|
+
| `out-of-date` | 2 | `sync --check` only: sync would change generated files. A check never reports `config-missing`, and turns any other failure that would end in 2 into 1 |
|
|
530
530
|
| `ambiguous` | 3 | Conflicting state requiring agent/human judgment; reserved |
|
|
531
531
|
| `ahead-of-engine` | 4 | Manifest schema is a newer major than the engine (a newer minor or patch warns and continues) |
|
|
532
532
|
| `aborted-incomplete` | 5 | Staged replacement was incomplete; prior state remains |
|
|
533
|
-
| `needs-update` | 6 |
|
|
533
|
+
| `needs-update` | 6 | The project needs a migration only `intelligence update` applies: no `schema_version`, or an older major |
|
|
534
534
|
|
|
535
535
|
Callers capture the real code with `command || rc=$?`. Do not use `if ! command; then rc=$?`; inside that branch `$?` is the status of the negation.
|
|
536
536
|
|
|
@@ -28,8 +28,11 @@ mechanics; this skill supplies repository judgement.
|
|
|
28
28
|
3. Run `intelligence status --check`. If the project is missing, inconsistent,
|
|
29
29
|
or its first sync failed, run `intelligence init --preview`, show the exact
|
|
30
30
|
repair plan, and request approval. After approval run
|
|
31
|
-
`intelligence init --apply`.
|
|
32
|
-
|
|
31
|
+
`intelligence init --apply`. When the check or the plan names
|
|
32
|
+
`intelligence update` instead, the project's versions need moving: show
|
|
33
|
+
`intelligence update --preview` and run `intelligence update --apply` only
|
|
34
|
+
after approval. Do not reproduce manifest, package, adapter, backup, or
|
|
35
|
+
ignore-file mechanics manually.
|
|
33
36
|
4. Run `intelligence sync`. Sync is transactional: a failure restores every
|
|
34
37
|
adapter-owned path. Resolve the reported cause and retry. Do not begin
|
|
35
38
|
semantic migration until `IS_STATUS=ok` and `intelligence status --check`
|
|
@@ -8,16 +8,17 @@ context: fork
|
|
|
8
8
|
# Sync intelligence
|
|
9
9
|
|
|
10
10
|
1. Run `intelligence sync` (or `intelligence sync <adapter>` when one adapter
|
|
11
|
-
was requested). For Intelligence projects, this command
|
|
12
|
-
|
|
13
|
-
`intelligence.lock`. Unchanged inputs and outputs can reuse a successful run.
|
|
11
|
+
was requested). For Intelligence projects, this command renders the project
|
|
12
|
+
at its committed versions and first restores a missing package store strictly
|
|
13
|
+
from `intelligence.lock`. Unchanged inputs and outputs can reuse a successful run.
|
|
14
14
|
Use `--force` when a fresh render or a new search for unconfigured source
|
|
15
15
|
directories is requested; an unchanged run replays the previous diagnostics.
|
|
16
16
|
2. Require final `IS_STATUS=ok`; relay reported counts and any integrity,
|
|
17
17
|
model-drift or unsynced-source warnings.
|
|
18
|
-
3.
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
3. A warning that project versions trail the CLI is not a failure: relay it.
|
|
19
|
+
`IS_STATUS=needs-update` (exit 6) means the project needs a migration only
|
|
20
|
+
`intelligence update` applies; report that, and never edit the manifest or
|
|
21
|
+
lock by hand to get past it. A frozen restore refusal means the
|
|
21
22
|
manifest and lock disagree or the locked commit cannot be verified/restored—report it without
|
|
22
23
|
hand-copying package content.
|
|
23
24
|
4. On a probable Intelligence defect, first ask whether to collect a sanitized
|