@ainova-systems/intelligence 0.11.0-rc.1 → 0.11.0-rc.10
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 +19 -16
- package/cli/commands/adapter.sh +153 -0
- package/cli/commands/init.sh +171 -34
- package/cli/commands/package.sh +30 -0
- package/cli/commands/registry.sh +65 -30
- package/cli/commands/status.sh +20 -11
- package/cli/commands/sync.sh +9 -4
- package/cli/commands/update.sh +80 -46
- package/cli/engine-package.yaml +14 -0
- package/cli/intelligence +37 -26
- package/cli/internal/align-project.sh +134 -0
- package/cli/internal/check.sh +128 -0
- package/cli/internal/convert-legacy.sh +400 -0
- package/cli/{commands/add.sh → internal/package-add.sh} +37 -19
- package/cli/{commands/list.sh → internal/package-list.sh} +10 -5
- package/cli/{commands/remove.sh → internal/package-remove.sh} +16 -4
- package/cli/internal/package-search.sh +83 -0
- package/cli/internal/package-update.sh +103 -0
- package/cli/internal/restore.sh +130 -0
- package/cli/internal/target-state.sh +57 -0
- package/cli/lib/cli-common.sh +213 -63
- package/cli/lib/lockfile.sh +15 -9
- package/cli/lib/manifest.sh +257 -4
- package/cli/lib/registry.sh +96 -47
- package/cli/lib/semver.sh +12 -4
- package/engine/ENGINE_SHA +1 -0
- package/engine/{scripts/adapters → adapters}/_template.sh +10 -9
- package/engine/{scripts/adapters → adapters}/agents.sh +20 -25
- package/engine/{scripts/adapters → adapters}/opencode.sh +1 -1
- package/engine/{scripts/lib → lib}/common.sh +30 -538
- package/engine/lib/contract.sh +120 -0
- package/engine/sync.sh +238 -0
- package/package.json +5 -5
- package/{engine → packages/sync}/agents/intelligence-architect.md +5 -3
- package/{engine → packages/sync}/agents/intelligence-operator.md +10 -13
- package/packages/sync/references/adapters.md +252 -0
- package/packages/sync/references/conventions.md +385 -0
- package/{engine → packages/sync}/rules/intelligence-authoring.md +7 -7
- package/{engine → packages/sync}/skills/intelligence-add-agent/SKILL.md +7 -7
- package/{engine → packages/sync}/skills/intelligence-add-rule/SKILL.md +5 -5
- package/{engine → packages/sync}/skills/intelligence-add-skill/SKILL.md +5 -5
- package/{engine → packages/sync}/skills/intelligence-extract-skill/SKILL.md +2 -2
- package/packages/sync/skills/intelligence-install-adapter/SKILL.md +38 -0
- package/{engine → packages/sync}/skills/intelligence-learn-from-context/SKILL.md +3 -3
- package/packages/sync/skills/intelligence-learn-from-repository/SKILL.md +55 -0
- package/{engine → packages/sync}/skills/intelligence-review-skills/SKILL.md +7 -7
- package/packages/sync/skills/intelligence-sync/SKILL.md +20 -0
- package/packages/sync/skills/intelligence-uninstall-adapter/SKILL.md +24 -0
- package/packages/sync/skills/intelligence-update/SKILL.md +43 -0
- package/cli/commands/doctor.sh +0 -100
- package/cli/commands/install.sh +0 -84
- package/cli/commands/migrate.sh +0 -251
- package/cli/commands/upgrade.sh +0 -27
- package/engine/INIT.md +0 -498
- package/engine/docs/ADAPTERS.md +0 -212
- package/engine/docs/CLI.md +0 -91
- package/engine/docs/CONVENTIONS.md +0 -440
- package/engine/scripts/lib/layout.sh +0 -51
- package/engine/scripts/lib/migrations.sh +0 -708
- package/engine/scripts/sync.sh +0 -311
- package/engine/scripts/update.sh +0 -237
- package/engine/skills/intelligence-install-adapter/SKILL.md +0 -31
- package/engine/skills/intelligence-sync/SKILL.md +0 -18
- package/engine/skills/intelligence-uninstall-adapter/SKILL.md +0 -42
- package/engine/skills/intelligence-update/SKILL.md +0 -159
- package/registry/index.yaml +0 -15
- /package/engine/{scripts/VERSION → VERSION} +0 -0
- /package/engine/{scripts/adapters → adapters}/claude.sh +0 -0
- /package/engine/{scripts/adapters → adapters}/codex.sh +0 -0
- /package/engine/{scripts/adapters → adapters}/copilot.sh +0 -0
- /package/engine/{scripts/adapters → adapters}/cursor.sh +0 -0
- /package/engine/{scripts/adapters → adapters}/pi.sh +0 -0
package/cli/commands/status.sh
CHANGED
|
@@ -1,32 +1,41 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# intelligence status — project state
|
|
2
|
+
# intelligence status [--check] — project state or deep consistency checks.
|
|
3
3
|
set -euo pipefail
|
|
4
4
|
source "$CLI_DIR/lib/cli-common.sh"
|
|
5
5
|
|
|
6
|
+
case "${1:-}" in
|
|
7
|
+
"") ;;
|
|
8
|
+
--check) [ $# -eq 1 ] || die "usage: intelligence status [--check]"; exec bash "$CLI_DIR/internal/check.sh" ;;
|
|
9
|
+
*) die "usage: intelligence status [--check]" ;;
|
|
10
|
+
esac
|
|
11
|
+
|
|
6
12
|
detect_project
|
|
7
13
|
case "$IP_MODE" in
|
|
8
|
-
|
|
9
|
-
echo "Project: $IP_ROOT (
|
|
10
|
-
echo "Manifest: intelligence.yaml (
|
|
14
|
+
cli)
|
|
15
|
+
echo "Project: $IP_ROOT (Intelligence project)"
|
|
16
|
+
echo "Manifest: intelligence.yaml (schema_version $(read_schema_version "$IP_ROOT/intelligence.yaml"))"
|
|
11
17
|
if [ -f "$IP_ROOT/intelligence.lock" ]; then
|
|
12
18
|
echo "Lockfile: intelligence.lock"
|
|
19
|
+
elif [ -n "$(qmap_keys "$IP_ROOT/intelligence.yaml" "packages")" ]; then
|
|
20
|
+
echo "Lockfile: MISSING (manifest declares packages)"
|
|
13
21
|
else
|
|
14
22
|
echo "Lockfile: none (no packages added yet)"
|
|
15
23
|
fi
|
|
16
|
-
|
|
17
|
-
|
|
24
|
+
sync_locked="$(qmap_field "$IP_ROOT/intelligence.lock" "packages" "$SYNC_PKG_NAME" "resolved")"
|
|
25
|
+
if [ -n "$sync_locked" ]; then
|
|
26
|
+
echo "Content: $SYNC_PKG_NAME at $sync_locked"
|
|
18
27
|
else
|
|
19
|
-
echo "
|
|
28
|
+
echo "Content: no $SYNC_PKG_NAME (bare setup)"
|
|
20
29
|
fi
|
|
21
|
-
echo "Engine: $(bundled_engine_version) (bundled)"
|
|
30
|
+
echo "Engine: $(bundled_engine_version) (bundled with the CLI)"
|
|
22
31
|
;;
|
|
23
32
|
legacy)
|
|
24
|
-
echo "Project: $IP_ROOT (
|
|
33
|
+
echo "Project: $IP_ROOT (legacy Intelligence Sync)"
|
|
25
34
|
echo "Umbrella: $IP_UMBRELLA"
|
|
26
35
|
echo "Engine: $(tr -d ' \t\r\n' < "$IP_MODULE_DIR/scripts/VERSION") (vendored at $IP_MODULE_DIR)"
|
|
27
|
-
echo "Stamp: $(
|
|
36
|
+
echo "Stamp: $(top_scalar "$IP_UMBRELLA/config.yaml" "sync_version")"
|
|
28
37
|
echo ""
|
|
29
|
-
echo "Convert to
|
|
38
|
+
echo "Convert to Intelligence: intelligence init"
|
|
30
39
|
;;
|
|
31
40
|
*)
|
|
32
41
|
echo "No intelligence project here. Start one: intelligence init"
|
package/cli/commands/sync.sh
CHANGED
|
@@ -5,15 +5,20 @@ source "$CLI_DIR/lib/cli-common.sh"
|
|
|
5
5
|
|
|
6
6
|
detect_project
|
|
7
7
|
case "$IP_MODE" in
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
cli)
|
|
9
|
+
# `sync` is the normal fresh-clone command. A newer globally installed
|
|
10
|
+
# CLI aligns the current Intelligence project first (except in CI, where a
|
|
11
|
+
# tracked migration must be reviewed and committed locally), and a
|
|
12
|
+
# missing ignored store is restored strictly from the committed lock.
|
|
13
|
+
ensure_project_current "$IP_ROOT"
|
|
14
|
+
restore_project_store_if_missing "$IP_ROOT"
|
|
10
15
|
export_engine_env "$IP_ROOT"
|
|
11
|
-
exec bash "$IS_ENGINE_DIR/
|
|
16
|
+
exec bash "$IS_ENGINE_DIR/sync.sh" "$@"
|
|
12
17
|
;;
|
|
13
18
|
legacy)
|
|
14
19
|
# A vendored project syncs with ITS engine — its pin is the contract,
|
|
15
20
|
# and a newer bundled engine must not generate against an older schema.
|
|
16
|
-
echo "NOTE:
|
|
21
|
+
echo "NOTE: legacy Intelligence Sync project — delegating to $IP_MODULE_DIR/scripts/sync.sh. 'intelligence init' converts it into an Intelligence project." >&2
|
|
17
22
|
exec bash "$IP_MODULE_DIR/scripts/sync.sh" "$@"
|
|
18
23
|
;;
|
|
19
24
|
*)
|
package/cli/commands/update.sh
CHANGED
|
@@ -1,59 +1,93 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# intelligence update [name] [--
|
|
2
|
+
# intelligence update [@scope/name] [--preview|--apply]
|
|
3
3
|
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
4
|
+
# One update surface: show the installed-CLI/project/package plan, then either
|
|
5
|
+
# stop, ask interactively, or apply without a prompt. Updating the global npm
|
|
6
|
+
# installation remains an explicit package-manager operation.
|
|
7
7
|
set -euo pipefail
|
|
8
8
|
source "$CLI_DIR/lib/cli-common.sh"
|
|
9
9
|
|
|
10
|
-
only=""
|
|
10
|
+
only="" mode="ask" preview_seen=0 apply_seen=0
|
|
11
11
|
while [ $# -gt 0 ]; do
|
|
12
12
|
case "$1" in
|
|
13
|
-
--
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
--preview) preview_seen=1; mode="preview" ;;
|
|
14
|
+
--apply) apply_seen=1; mode="apply" ;;
|
|
15
|
+
@*) [ -z "$only" ] || die "only one package may be selected"; only="$1" ;;
|
|
16
|
+
*) die "usage: intelligence update [@scope/name] [--preview|--apply]" ;;
|
|
16
17
|
esac
|
|
17
|
-
shift
|
|
18
|
+
shift
|
|
18
19
|
done
|
|
20
|
+
[ "$preview_seen" -eq 0 ] || [ "$apply_seen" -eq 0 ] || die "choose either --preview or --apply"
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
require_cli_project
|
|
21
23
|
manifest="$IP_ROOT/intelligence.yaml"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if [ "$tag" = "$current" ]; then
|
|
43
|
-
echo " $name: ${current:-<none>} (up to date)"
|
|
44
|
-
continue
|
|
24
|
+
check_version_compat "$manifest"
|
|
25
|
+
eng="$(bundled_engine_version)"
|
|
26
|
+
stamp="$(read_schema_version "$manifest")"
|
|
27
|
+
project_change=0
|
|
28
|
+
|
|
29
|
+
echo "Update plan"
|
|
30
|
+
echo ""
|
|
31
|
+
echo "CLI:"
|
|
32
|
+
if [ -n "${INTELLIGENCE_NPM_VERSION:-}" ] && [ "${IS_SKIP_NPM_CHECK:-0}" != "1" ] && command -v npm >/dev/null 2>&1; then
|
|
33
|
+
channel="latest"
|
|
34
|
+
case "$INTELLIGENCE_NPM_VERSION" in *-*) channel="next" ;; esac
|
|
35
|
+
available="$(npm view "@ainova-systems/intelligence" "dist-tags.$channel" 2>/dev/null || true)"
|
|
36
|
+
if [ -z "$available" ]; then
|
|
37
|
+
echo " installed: $INTELLIGENCE_NPM_VERSION; registry check unavailable"
|
|
38
|
+
elif [ "$available" = "$INTELLIGENCE_NPM_VERSION" ]; then
|
|
39
|
+
echo " $INTELLIGENCE_NPM_VERSION (up to date on npm $channel)"
|
|
40
|
+
else
|
|
41
|
+
echo " $INTELLIGENCE_NPM_VERSION -> $available (npm $channel)"
|
|
42
|
+
echo " run: npm install -g @ainova-systems/intelligence@$channel"
|
|
43
|
+
echo " then rerun: intelligence update --apply"
|
|
45
44
|
fi
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if [ "$moved" -gt 0 ] && [ "$no_sync" -eq 0 ]; then
|
|
58
|
-
exec bash "$CLI_DIR/commands/sync.sh"
|
|
45
|
+
else
|
|
46
|
+
echo " source checkout/registry check skipped; engine $eng"
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
echo ""
|
|
50
|
+
echo "Project:"
|
|
51
|
+
if project_needs_upgrade "$IP_ROOT"; then
|
|
52
|
+
echo " lifecycle alignment required (stamp ${stamp:-unstamped}, engine $eng)"
|
|
53
|
+
project_change=1
|
|
54
|
+
else
|
|
55
|
+
echo " schema/content $eng (up to date)"
|
|
59
56
|
fi
|
|
57
|
+
|
|
58
|
+
if project_has_packages "$IP_ROOT" && [ ! -f "$IP_ROOT/intelligence.lock" ]; then
|
|
59
|
+
die "manifest declares packages but intelligence.lock is absent — restore the committed lock before planning or applying updates"
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
pkg_args=(--preview)
|
|
63
|
+
[ -z "$only" ] || pkg_args+=("$only")
|
|
64
|
+
pkg_plan="$(bash "$CLI_DIR/internal/package-update.sh" "${pkg_args[@]}")"
|
|
65
|
+
echo ""
|
|
66
|
+
echo "Packages:"
|
|
67
|
+
printf '%s\n' "$pkg_plan"
|
|
68
|
+
package_changes="$(printf '%s\n' "$pkg_plan" | awk '/^updates available:/ {print $3; exit}')"
|
|
69
|
+
package_changes="${package_changes:-0}"
|
|
70
|
+
|
|
71
|
+
if [ "$mode" = "preview" ]; then
|
|
72
|
+
exit 0
|
|
73
|
+
fi
|
|
74
|
+
if [ "$project_change" -eq 0 ] && [ "$package_changes" -eq 0 ]; then
|
|
75
|
+
echo ""
|
|
76
|
+
echo "Nothing to apply with the currently installed CLI."
|
|
77
|
+
exit 0
|
|
78
|
+
fi
|
|
79
|
+
if [ "$mode" = "ask" ]; then
|
|
80
|
+
[ -t 0 ] || die "update requires confirmation — rerun with --preview or --apply"
|
|
81
|
+
printf '\nApply this plan? [Y/n] '
|
|
82
|
+
read -r answer
|
|
83
|
+
case "$answer" in
|
|
84
|
+
""|y|Y|yes|YES) ;;
|
|
85
|
+
*) echo "update cancelled"; exit 0 ;;
|
|
86
|
+
esac
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
ensure_project_current "$IP_ROOT"
|
|
90
|
+
apply_args=(--no-sync)
|
|
91
|
+
[ -z "$only" ] || apply_args+=("$only")
|
|
92
|
+
bash "$CLI_DIR/internal/package-update.sh" "${apply_args[@]}"
|
|
93
|
+
exec bash "$CLI_DIR/commands/sync.sh"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# What THIS CLI distribution ships as its engine-content package, and which
|
|
2
|
+
# registry its init seeds into new manifests. Data, not code: a fork or an
|
|
3
|
+
# enterprise mirror edits this file (or its copy in the npm build) — nothing
|
|
4
|
+
# in cli/ names a vendor.
|
|
5
|
+
#
|
|
6
|
+
# The engine-content package is the one package whose content documents the
|
|
7
|
+
# engine scripts bundled with the CLI: init writes this entry into the
|
|
8
|
+
# manifest (visible, removable), its pin always equals the engine VERSION,
|
|
9
|
+
# lifecycle preflight aligns it with the installed CLI, and at the matching
|
|
10
|
+
# version it materializes from the bundle without network.
|
|
11
|
+
name: "@ainova-systems/sync"
|
|
12
|
+
url: "https://github.com/ainova-systems/intelligence.git"
|
|
13
|
+
path: "packages/sync"
|
|
14
|
+
default_registry: "https://github.com/ainova-systems/intelligence-registry.git"
|
package/cli/intelligence
CHANGED
|
@@ -3,25 +3,20 @@
|
|
|
3
3
|
#
|
|
4
4
|
# Dispatcher only: each command lives in commands/<name>.sh so commands can be
|
|
5
5
|
# ported to Node one at a time without touching the others. The engine is the
|
|
6
|
-
#
|
|
7
|
-
# from the intelligence-sync repo itself, the repo's own module.
|
|
6
|
+
# bash engine shipped next to the CLI.
|
|
8
7
|
|
|
9
8
|
set -euo pipefail
|
|
10
9
|
|
|
11
10
|
CLI_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
12
11
|
export CLI_DIR
|
|
13
12
|
|
|
14
|
-
# Engine discovery, by role (
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
# 2. this repo: <repo>/cli/intelligence + <repo>/intelligence/sync/scripts/
|
|
13
|
+
# Engine discovery, by role (sync.sh + VERSION). The repo and the npm package
|
|
14
|
+
# ship one layout — <root>/{cli,engine,packages/sync} — so there is a single
|
|
15
|
+
# candidate rather than a per-distribution list.
|
|
18
16
|
IS_ENGINE_DIR=""
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
break
|
|
23
|
-
fi
|
|
24
|
-
done
|
|
17
|
+
if [ -f "$CLI_DIR/../engine/sync.sh" ] && [ -f "$CLI_DIR/../engine/VERSION" ]; then
|
|
18
|
+
IS_ENGINE_DIR="$(cd "$CLI_DIR/../engine" && pwd)"
|
|
19
|
+
fi
|
|
25
20
|
if [ -z "$IS_ENGINE_DIR" ]; then
|
|
26
21
|
echo "ERROR: bundled sync engine not found next to the CLI ($CLI_DIR)." >&2
|
|
27
22
|
echo " Reinstall: npm i -g @ainova-systems/intelligence" >&2
|
|
@@ -29,40 +24,56 @@ if [ -z "$IS_ENGINE_DIR" ]; then
|
|
|
29
24
|
fi
|
|
30
25
|
export IS_ENGINE_DIR
|
|
31
26
|
|
|
27
|
+
# The engine's own content, shipped beside the engine as the seed for the
|
|
28
|
+
# @ainova-systems/sync package at exactly this CLI's version. Separate from the
|
|
29
|
+
# engine dir: the store must receive rules/agents/skills, never engine scripts.
|
|
30
|
+
IS_BUNDLED_PKG_DIR=""
|
|
31
|
+
if [ -d "$CLI_DIR/../packages/sync" ]; then
|
|
32
|
+
IS_BUNDLED_PKG_DIR="$(cd "$CLI_DIR/../packages/sync" && pwd)"
|
|
33
|
+
fi
|
|
34
|
+
export IS_BUNDLED_PKG_DIR
|
|
35
|
+
|
|
32
36
|
cmd="${1:-}"
|
|
33
37
|
case "$cmd" in
|
|
34
38
|
""|help|-h|--help)
|
|
35
|
-
engine_ver="$(tr -d ' \t\r\n' < "$IS_ENGINE_DIR/
|
|
39
|
+
engine_ver="$(tr -d ' \t\r\n' < "$IS_ENGINE_DIR/VERSION")"
|
|
36
40
|
cat <<EOF
|
|
37
41
|
intelligence — build, version and distribute AI agent intelligence
|
|
38
42
|
(engine $engine_ver${INTELLIGENCE_NPM_VERSION:+, package $INTELLIGENCE_NPM_VERSION})
|
|
39
43
|
|
|
40
44
|
Usage: intelligence <command> [args]
|
|
41
45
|
|
|
42
|
-
init
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
update [name]
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
status Project state at a glance
|
|
46
|
+
init [--preview|--apply] Initialize, convert, restore or align this project
|
|
47
|
+
--targets a,b --dir name --bare --no-sync New-project options
|
|
48
|
+
--force Accept a dirty worktree during legacy project conversion
|
|
49
|
+
sync [adapter] Restore locked content if needed, then render enabled adapters
|
|
50
|
+
update [@scope/name] Show an update plan; ask before applying it
|
|
51
|
+
--preview Show the plan without asking or writing
|
|
52
|
+
--apply Apply the plan without asking
|
|
53
|
+
package <command> add | remove | list | search
|
|
54
|
+
adapter <command> list | create | enable | disable | remove
|
|
55
|
+
status [--check] Project state; --check runs deep consistency checks
|
|
56
|
+
registry <list|add|remove> Manage the trusted registry list (add <repo-url>)
|
|
54
57
|
version Print CLI and engine versions
|
|
55
58
|
EOF
|
|
56
59
|
exit 0
|
|
57
60
|
;;
|
|
58
61
|
version|-v|--version)
|
|
59
|
-
engine_ver="$(tr -d ' \t\r\n' < "$IS_ENGINE_DIR/
|
|
62
|
+
engine_ver="$(tr -d ' \t\r\n' < "$IS_ENGINE_DIR/VERSION")"
|
|
60
63
|
echo "${INTELLIGENCE_NPM_VERSION:-$engine_ver} (engine $engine_ver)"
|
|
61
64
|
exit 0
|
|
62
65
|
;;
|
|
63
66
|
esac
|
|
64
67
|
shift
|
|
65
68
|
|
|
69
|
+
# The command word builds a path — allow exactly lowercase words, so
|
|
70
|
+
# `intelligence ../x` can never exec a neighbouring script.
|
|
71
|
+
case "$cmd" in
|
|
72
|
+
*[!a-z-]*|-*)
|
|
73
|
+
echo "ERROR: unknown command '$cmd'. Run 'intelligence help'." >&2
|
|
74
|
+
exit 1
|
|
75
|
+
;;
|
|
76
|
+
esac
|
|
66
77
|
cmd_file="$CLI_DIR/commands/$cmd.sh"
|
|
67
78
|
if [ ! -f "$cmd_file" ]; then
|
|
68
79
|
echo "ERROR: unknown command '$cmd'. Run 'intelligence help'." >&2
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Internal: bring an Intelligence project to this CLI's engine: apply schema
|
|
3
|
+
# migrations, align the engine-content package to the bundled version,
|
|
4
|
+
# restamp schema_version, sync.
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
source "$CLI_DIR/lib/cli-common.sh"
|
|
7
|
+
|
|
8
|
+
no_sync=0
|
|
9
|
+
while [ $# -gt 0 ]; do
|
|
10
|
+
case "$1" in
|
|
11
|
+
--no-sync) no_sync=1 ;;
|
|
12
|
+
*) die "internal upgrade: unknown option '$1'" ;;
|
|
13
|
+
esac
|
|
14
|
+
shift
|
|
15
|
+
done
|
|
16
|
+
|
|
17
|
+
require_cli_project
|
|
18
|
+
manifest="$IP_ROOT/intelligence.yaml"
|
|
19
|
+
|
|
20
|
+
stamp="$(read_schema_version "$manifest")"
|
|
21
|
+
legacy_stamp="$(top_scalar "$manifest" "sync_version")"
|
|
22
|
+
schema_key_count="$(awk '/^schema_version:[[:space:]]*/ { n++ } END { print n + 0 }' "$manifest")"
|
|
23
|
+
legacy_key_count="$(awk '/^sync_version:[[:space:]]*/ { n++ } END { print n + 0 }' "$manifest")"
|
|
24
|
+
eng="$(bundled_engine_version)"
|
|
25
|
+
[ "$schema_key_count" -le 1 ] || die "manifest has duplicate schema_version keys"
|
|
26
|
+
[ "$legacy_key_count" -le 1 ] || die "manifest has duplicate sync_version keys"
|
|
27
|
+
if [ -n "$stamp" ] && _ver_gt "$stamp" "$eng"; then
|
|
28
|
+
die "manifest schema $stamp is newer than this CLI's engine $eng — update the global CLI first"
|
|
29
|
+
fi
|
|
30
|
+
if [ -n "$legacy_stamp" ] && _ver_gt "$legacy_stamp" "$eng"; then
|
|
31
|
+
die "manifest schema $legacy_stamp is newer than this CLI's engine $eng — update the global CLI first"
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
# --- project schema migrations --------------------------------------------
|
|
35
|
+
# The engine's own chain owns vendored layouts; this one owns the manifest.
|
|
36
|
+
# Same discipline: ascending, append-only, each migration self-detects and
|
|
37
|
+
# no-ops when already applied.
|
|
38
|
+
|
|
39
|
+
# migration 0: the original RC manifest called the permanent schema key
|
|
40
|
+
# `sync_version`. Rename it without changing its value; the final stamp below
|
|
41
|
+
# then aligns it with this engine. The legacy Intelligence Sync reader remains
|
|
42
|
+
# separate.
|
|
43
|
+
if [ -n "$legacy_stamp" ]; then
|
|
44
|
+
if [ -n "$stamp" ]; then
|
|
45
|
+
[ "$stamp" = "$legacy_stamp" ] || die "manifest has conflicting schema_version '$stamp' and sync_version '$legacy_stamp'"
|
|
46
|
+
_qmap_stage "$manifest" '$0 !~ /^sync_version:[[:space:]]*/'
|
|
47
|
+
else
|
|
48
|
+
_qmap_stage "$manifest" '{ sub(/^sync_version:/, "schema_version:"); print }'
|
|
49
|
+
fi
|
|
50
|
+
echo " migrating: sync_version -> schema_version"
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# migration 1: package entries contain requested intent only. Early RCs
|
|
54
|
+
# also copied resolved url/path into the manifest. Preserve the existing lock
|
|
55
|
+
# as the trusted source and remove that duplicate representation. A direct
|
|
56
|
+
# unversioned package becomes an explicit HEAD pin so its manifest entry stays
|
|
57
|
+
# meaningful after the source fields are removed.
|
|
58
|
+
source_fields_migrated=0
|
|
59
|
+
while IFS= read -r name; do
|
|
60
|
+
[ -n "$name" ] || continue
|
|
61
|
+
m_url="$(qmap_field "$manifest" "packages" "$name" "url")"
|
|
62
|
+
m_path="$(qmap_field "$manifest" "packages" "$name" "path")"
|
|
63
|
+
[ -n "$m_url" ] || [ -n "$m_path" ] || continue
|
|
64
|
+
m_ver="$(qmap_field "$manifest" "packages" "$name" "version")"
|
|
65
|
+
m_ref="$(qmap_field "$manifest" "packages" "$name" "ref")"
|
|
66
|
+
if [ -z "$m_ver" ] && [ -z "$m_ref" ]; then
|
|
67
|
+
locked_ref="$(qmap_field "$IP_ROOT/intelligence.lock" "packages" "$name" "resolved")"
|
|
68
|
+
qmap_set "$manifest" "packages" "$name" "ref" "${locked_ref:-HEAD}"
|
|
69
|
+
fi
|
|
70
|
+
qmap_delete_field "$manifest" "packages" "$name" "url"
|
|
71
|
+
qmap_delete_field "$manifest" "packages" "$name" "path"
|
|
72
|
+
source_fields_migrated=1
|
|
73
|
+
done < <(qmap_keys "$manifest" "packages")
|
|
74
|
+
if [ "$source_fields_migrated" -eq 1 ]; then
|
|
75
|
+
echo " migrating: package url/path -> intelligence.lock"
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
# migration 2: staged engine content -> the @ainova-systems/sync package.
|
|
79
|
+
# Pre-package manifests listed `.intelligence/engine/{rules,agents,skills}`
|
|
80
|
+
# as sources fed by a CLI-staged copy; that copy is now an ordinary package
|
|
81
|
+
# entry seeded from the bundle. Post-condition: no `.intelligence/engine`
|
|
82
|
+
# source entries, the package present in manifest+lock+store, stale dir gone.
|
|
83
|
+
migrated=0
|
|
84
|
+
for section in rules agents skills; do
|
|
85
|
+
while IFS= read -r src; do
|
|
86
|
+
case "$src" in
|
|
87
|
+
.intelligence/engine/*)
|
|
88
|
+
sources_remove_entry "$manifest" "$section" "$src"
|
|
89
|
+
migrated=1
|
|
90
|
+
;;
|
|
91
|
+
esac
|
|
92
|
+
done < <(read_yaml_list "$manifest" "$section")
|
|
93
|
+
done
|
|
94
|
+
if [ "$migrated" -eq 1 ]; then
|
|
95
|
+
echo " migrating: staged engine content -> $SYNC_PKG_NAME package"
|
|
96
|
+
rm -rf "$IP_ROOT/.intelligence/engine"
|
|
97
|
+
sync_pkg_entry "$manifest"
|
|
98
|
+
sync_pkg_install "$IP_ROOT"
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
# --- steady state ---------------------------------------------------------
|
|
102
|
+
# Align the engine-content package with the bundled engine. Only a manifest
|
|
103
|
+
# that HAS the entry is touched — a --bare project opted out, and upgrade
|
|
104
|
+
# respects that.
|
|
105
|
+
have_pkg=0
|
|
106
|
+
while IFS= read -r name; do
|
|
107
|
+
[ "$name" = "$SYNC_PKG_NAME" ] && have_pkg=1
|
|
108
|
+
done < <(qmap_keys "$manifest" "packages")
|
|
109
|
+
if [ "$have_pkg" -eq 1 ] && [ "$migrated" -eq 0 ]; then
|
|
110
|
+
pinned="$(qmap_field "$manifest" "packages" "$SYNC_PKG_NAME" "version")"
|
|
111
|
+
if [ "$pinned" != "$eng" ]; then
|
|
112
|
+
echo " $SYNC_PKG_NAME: $pinned -> $eng"
|
|
113
|
+
fi
|
|
114
|
+
sync_pkg_entry "$manifest"
|
|
115
|
+
sync_pkg_install "$IP_ROOT"
|
|
116
|
+
fi
|
|
117
|
+
if [ "$have_pkg" -eq 0 ] && [ "$migrated" -eq 0 ]; then
|
|
118
|
+
echo " NOTE: $SYNC_PKG_NAME is not in this manifest (bare setup) — engine meta-skills stay uninstalled; 'intelligence package add $SYNC_PKG_NAME' opts back in." >&2
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
# A previous RC could leave this managed directory even after its source
|
|
122
|
+
# entries were already removed. Its presence is itself an upgrade predicate,
|
|
123
|
+
# so always close that post-condition.
|
|
124
|
+
if [ -d "$IP_ROOT/.intelligence/engine" ]; then
|
|
125
|
+
rm -rf "$IP_ROOT/.intelligence/engine"
|
|
126
|
+
echo " removed stale .intelligence/engine"
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
stamp_schema_version "$manifest" "$eng"
|
|
130
|
+
echo " schema_version -> $eng"
|
|
131
|
+
|
|
132
|
+
if [ "$no_sync" -eq 0 ]; then
|
|
133
|
+
exec bash "$CLI_DIR/commands/sync.sh"
|
|
134
|
+
fi
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Internal deep consistency check. No writes; exits 1 on problems.
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
source "$CLI_DIR/lib/cli-common.sh"
|
|
5
|
+
|
|
6
|
+
problems=0
|
|
7
|
+
warn() { echo " ✗ $*"; problems=$((problems + 1)); }
|
|
8
|
+
ok() { echo " ✓ $*"; }
|
|
9
|
+
|
|
10
|
+
echo "environment:"
|
|
11
|
+
command -v git >/dev/null 2>&1 && ok "git $(git --version | awk '{print $3}')" || warn "git not found"
|
|
12
|
+
command -v awk >/dev/null 2>&1 && ok "awk present" || warn "awk not found"
|
|
13
|
+
ok "bash $BASH_VERSION"
|
|
14
|
+
ok "engine $(bundled_engine_version) at $IS_ENGINE_DIR"
|
|
15
|
+
|
|
16
|
+
detect_project
|
|
17
|
+
case "$IP_MODE" in
|
|
18
|
+
none)
|
|
19
|
+
echo "project: none here — 'intelligence init' starts one"
|
|
20
|
+
exit 0
|
|
21
|
+
;;
|
|
22
|
+
legacy)
|
|
23
|
+
echo "project: legacy Intelligence Sync at $IP_ROOT"
|
|
24
|
+
ok "vendored engine $(tr -d ' \t\r\n' < "$IP_MODULE_DIR/scripts/VERSION")"
|
|
25
|
+
echo " → 'intelligence init' converts it into an Intelligence project"
|
|
26
|
+
exit 0
|
|
27
|
+
;;
|
|
28
|
+
esac
|
|
29
|
+
|
|
30
|
+
echo "project: $IP_ROOT"
|
|
31
|
+
manifest="$IP_ROOT/intelligence.yaml"
|
|
32
|
+
lock="$IP_ROOT/intelligence.lock"
|
|
33
|
+
|
|
34
|
+
stamp="$(read_schema_version "$manifest")"
|
|
35
|
+
eng="$(bundled_engine_version)"
|
|
36
|
+
if [ -z "$stamp" ]; then
|
|
37
|
+
warn "manifest has no schema_version — run 'intelligence init'"
|
|
38
|
+
elif _ver_gt "$stamp" "$eng"; then
|
|
39
|
+
warn "manifest schema $stamp is newer than this CLI's engine $eng — update the CLI: npm i -g @ainova-systems/intelligence@latest"
|
|
40
|
+
elif _ver_gt "$eng" "$stamp"; then
|
|
41
|
+
warn "manifest schema $stamp behind engine $eng — run 'intelligence init'"
|
|
42
|
+
else
|
|
43
|
+
ok "schema_version $stamp matches the engine"
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# The engine-content package must sit at the bundled engine version — the
|
|
47
|
+
# content documents exactly the scripts the CLI executes.
|
|
48
|
+
sync_locked="$(qmap_field "$lock" "packages" "$SYNC_PKG_NAME" "resolved")"
|
|
49
|
+
if [ -n "$sync_locked" ]; then
|
|
50
|
+
if [ "${sync_locked#v}" = "$eng" ]; then
|
|
51
|
+
ok "$SYNC_PKG_NAME at $sync_locked (matches the engine)"
|
|
52
|
+
else
|
|
53
|
+
warn "$SYNC_PKG_NAME locked at $sync_locked but the engine is $eng — run 'intelligence init'"
|
|
54
|
+
fi
|
|
55
|
+
fi
|
|
56
|
+
if [ -d "$IP_ROOT/.intelligence/engine" ]; then
|
|
57
|
+
warn "stale .intelligence/engine directory (pre-package layout) — run 'intelligence init'"
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# Manifest packages: names valid, requested intent only, locked and installed.
|
|
61
|
+
# The lock is authoritative for resolved source URL/path until an explicit
|
|
62
|
+
# package re-add changes that trust decision.
|
|
63
|
+
while IFS= read -r name; do
|
|
64
|
+
[ -n "$name" ] || continue
|
|
65
|
+
assert_valid_pkg_name "$name"
|
|
66
|
+
if [ -z "$(qmap_field "$lock" "packages" "$name" "url")" ]; then
|
|
67
|
+
warn "$name is in the manifest but not in intelligence.lock — run 'intelligence init'"
|
|
68
|
+
else
|
|
69
|
+
m_ver="$(qmap_field "$manifest" "packages" "$name" "version")"
|
|
70
|
+
m_ref="$(qmap_field "$manifest" "packages" "$name" "ref")"
|
|
71
|
+
l_req="$(qmap_field "$lock" "packages" "$name" "requested")"
|
|
72
|
+
l_res="$(qmap_field "$lock" "packages" "$name" "resolved")"
|
|
73
|
+
[ -z "$m_ver" ] || [ "$m_ver" = "$l_req" ] \
|
|
74
|
+
|| warn "$name requests '$m_ver' but the lock recorded '$l_req' — run 'intelligence update --preview'"
|
|
75
|
+
[ -z "$m_ref" ] || [ "$m_ref" = "$l_res" ] \
|
|
76
|
+
|| warn "$name pins ref '$m_ref' but the lock resolved '$l_res'"
|
|
77
|
+
if [ -n "$(qmap_field "$manifest" "packages" "$name" "url")" ] \
|
|
78
|
+
|| [ -n "$(qmap_field "$manifest" "packages" "$name" "path")" ]; then
|
|
79
|
+
warn "$name stores source details in the manifest — run 'intelligence init --apply' to move them to the lock-only model"
|
|
80
|
+
fi
|
|
81
|
+
if [ ! -d "$IP_ROOT/.intelligence/packages/$name" ]; then
|
|
82
|
+
warn "$name is locked but not installed — run 'intelligence sync'"
|
|
83
|
+
continue
|
|
84
|
+
fi
|
|
85
|
+
ok "$name @ $(qmap_field "$lock" "packages" "$name" "resolved")"
|
|
86
|
+
fi
|
|
87
|
+
done < <(qmap_keys "$manifest" "packages")
|
|
88
|
+
|
|
89
|
+
# Lock orphans.
|
|
90
|
+
if [ -f "$lock" ]; then
|
|
91
|
+
while IFS= read -r name; do
|
|
92
|
+
[ -n "$name" ] || continue
|
|
93
|
+
found=0
|
|
94
|
+
while IFS= read -r m; do
|
|
95
|
+
[ "$m" = "$name" ] && found=1
|
|
96
|
+
done < <(qmap_keys "$manifest" "packages")
|
|
97
|
+
[ "$found" -eq 1 ] || warn "$name is locked but absent from the manifest — 'intelligence package remove $name' cleans it up"
|
|
98
|
+
done < <(qmap_keys "$lock" "packages")
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
# Sources must exist (a missing dir is silently skipped by the engine, which
|
|
102
|
+
# is exactly why doctor names it).
|
|
103
|
+
for section in rules agents skills; do
|
|
104
|
+
while IFS= read -r src; do
|
|
105
|
+
[ -n "$src" ] || continue
|
|
106
|
+
case "$src" in
|
|
107
|
+
git+*|@*) continue ;;
|
|
108
|
+
esac
|
|
109
|
+
if [ ! -d "$IP_ROOT/$src" ]; then
|
|
110
|
+
case "$src" in
|
|
111
|
+
# Store content is restorable state: absent means un-installed.
|
|
112
|
+
.intelligence/*) warn "sources.$section '$src' missing — run 'intelligence sync'" ;;
|
|
113
|
+
# A project-owned dir that does not exist yet is a legitimate
|
|
114
|
+
# state — a project consuming only packages authors nothing of
|
|
115
|
+
# its own — and the engine simply skips it. Declared up front so
|
|
116
|
+
# authoring later needs no config edit.
|
|
117
|
+
*) ok "sources.$section '$src' — not created yet (optional)" ;;
|
|
118
|
+
esac
|
|
119
|
+
fi
|
|
120
|
+
done < <(read_yaml_list "$manifest" "$section")
|
|
121
|
+
done
|
|
122
|
+
|
|
123
|
+
if [ "$problems" -eq 0 ]; then
|
|
124
|
+
echo "all good."
|
|
125
|
+
else
|
|
126
|
+
echo "$problems problem(s)."
|
|
127
|
+
exit 1
|
|
128
|
+
fi
|