@ainova-systems/intelligence 0.11.0-rc.1

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.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +46 -0
  3. package/bin/intelligence.js +59 -0
  4. package/cli/commands/add.sh +133 -0
  5. package/cli/commands/doctor.sh +100 -0
  6. package/cli/commands/init.sh +96 -0
  7. package/cli/commands/install.sh +84 -0
  8. package/cli/commands/list.sh +28 -0
  9. package/cli/commands/migrate.sh +251 -0
  10. package/cli/commands/registry.sh +51 -0
  11. package/cli/commands/remove.sh +39 -0
  12. package/cli/commands/status.sh +34 -0
  13. package/cli/commands/sync.sh +22 -0
  14. package/cli/commands/update.sh +59 -0
  15. package/cli/commands/upgrade.sh +27 -0
  16. package/cli/intelligence +71 -0
  17. package/cli/lib/cli-common.sh +149 -0
  18. package/cli/lib/lockfile.sh +97 -0
  19. package/cli/lib/manifest.sh +211 -0
  20. package/cli/lib/registry.sh +141 -0
  21. package/cli/lib/semver.sh +127 -0
  22. package/engine/INIT.md +498 -0
  23. package/engine/agents/intelligence-architect.md +53 -0
  24. package/engine/agents/intelligence-operator.md +49 -0
  25. package/engine/docs/ADAPTERS.md +212 -0
  26. package/engine/docs/CLI.md +91 -0
  27. package/engine/docs/CONVENTIONS.md +440 -0
  28. package/engine/rules/intelligence-authoring.md +114 -0
  29. package/engine/scripts/VERSION +1 -0
  30. package/engine/scripts/adapters/_template.sh +86 -0
  31. package/engine/scripts/adapters/agents.sh +299 -0
  32. package/engine/scripts/adapters/claude.sh +136 -0
  33. package/engine/scripts/adapters/codex.sh +118 -0
  34. package/engine/scripts/adapters/copilot.sh +193 -0
  35. package/engine/scripts/adapters/cursor.sh +146 -0
  36. package/engine/scripts/adapters/opencode.sh +200 -0
  37. package/engine/scripts/adapters/pi.sh +256 -0
  38. package/engine/scripts/lib/common.sh +1602 -0
  39. package/engine/scripts/lib/layout.sh +51 -0
  40. package/engine/scripts/lib/migrations.sh +708 -0
  41. package/engine/scripts/sync.sh +311 -0
  42. package/engine/scripts/update.sh +237 -0
  43. package/engine/skills/intelligence-add-agent/SKILL.md +62 -0
  44. package/engine/skills/intelligence-add-rule/SKILL.md +54 -0
  45. package/engine/skills/intelligence-add-skill/SKILL.md +53 -0
  46. package/engine/skills/intelligence-extract-skill/SKILL.md +47 -0
  47. package/engine/skills/intelligence-install-adapter/SKILL.md +31 -0
  48. package/engine/skills/intelligence-learn-from-context/SKILL.md +69 -0
  49. package/engine/skills/intelligence-review-skills/SKILL.md +86 -0
  50. package/engine/skills/intelligence-sync/SKILL.md +18 -0
  51. package/engine/skills/intelligence-uninstall-adapter/SKILL.md +42 -0
  52. package/engine/skills/intelligence-update/SKILL.md +159 -0
  53. package/package.json +39 -0
  54. package/registry/index.yaml +15 -0
@@ -0,0 +1,251 @@
1
+ #!/bin/bash
2
+ # intelligence migrate [--dry-run] [--force] — convert a vendored (v1) setup
3
+ # to the CLI setup: root intelligence.yaml, .intelligence/ store,
4
+ # intelligence.lock, no vendored engine.
5
+ #
6
+ # Transactional in the migrations.sh spirit: STAGE everything next to the
7
+ # project, VERIFY the staged state, then COMMIT in an order where every
8
+ # destructive step happens only after a real sync of the new state reported
9
+ # IS_STATUS=ok. Any earlier failure leaves the project untouched.
10
+ set -euo pipefail
11
+ source "$CLI_DIR/lib/cli-common.sh"
12
+
13
+ dry_run=0 force=0
14
+ while [ $# -gt 0 ]; do
15
+ case "$1" in
16
+ --dry-run) dry_run=1 ;;
17
+ --force) force=1 ;;
18
+ *) die "unknown option '$1'" ;;
19
+ esac
20
+ shift || true
21
+ done
22
+
23
+ # ---- Preconditions (fail closed, nothing written) -------------------------
24
+ detect_project
25
+ case "$IP_MODE" in
26
+ legacy) ;;
27
+ v2) die "already on the CLI setup ($IP_ROOT/intelligence.yaml)" ;;
28
+ *) die "no vendored setup found here — 'intelligence init' starts a fresh project" ;;
29
+ esac
30
+ root="$IP_ROOT"
31
+ umbrella="$IP_UMBRELLA"
32
+ module_dir="$IP_MODULE_DIR"
33
+ config="$umbrella/config.yaml"
34
+ module_rel="${module_dir#"$root"/}"
35
+
36
+ [ -f "$root/intelligence.yaml" ] && die "intelligence.yaml already exists at the root — half-migrated state; resolve it manually"
37
+ if [ "$dry_run" -eq 0 ] && [ "$force" -eq 0 ]; then
38
+ if [ -n "$(git -C "$root" status --porcelain 2>/dev/null)" ]; then
39
+ die "working tree is not clean — commit or stash first (or --force); migrate wants a one-commit diff you can review and revert"
40
+ fi
41
+ fi
42
+
43
+ stamp="$(read_engine_stamp "$config")"
44
+ eng="$(bundled_engine_version)"
45
+ [ -n "$stamp" ] && _ver_gt "$stamp" "$eng" && die "project schema $stamp is newer than this CLI's engine $eng — update the CLI first"
46
+
47
+ # A schema gap is closed by the engine's own proven chain before conversion.
48
+ if [ "$dry_run" -eq 0 ] && { [ -z "$stamp" ] || _ver_gt "$eng" "$stamp"; }; then
49
+ echo "== applying the engine migration chain ($stamp -> $eng) =="
50
+ run_migrations "$umbrella" "$(basename "$module_dir")" "" || die "engine migration chain failed (IS_STATUS above) — nothing converted"
51
+ stamp_version "$config" "$eng"
52
+ fi
53
+
54
+ # ---- Stage ----------------------------------------------------------------
55
+ stage="$root/.intelligence-migrate-stage.$$"
56
+ [ "$dry_run" -eq 1 ] && stage="$(mktemp -d -t intelligence-migrate-XXXXXX 2>/dev/null || mktemp -d)"
57
+ cleanup_stage() { rm -rf "$stage"; }
58
+ trap cleanup_stage EXIT INT TERM
59
+ mkdir -p "$stage/.intelligence/packages"
60
+
61
+ echo "== staging =="
62
+ stage_engine_content "$stage/.intelligence/engine"
63
+
64
+ # Legacy pack name -> v2 package name (@org/repo derived from the url), plus
65
+ # per-pack source facts. Recorded as rows for the config rewrite and the lock.
66
+ pack_rows="$stage/packs.rows"
67
+ : > "$pack_rows"
68
+ while IFS= read -r pack; do
69
+ [ -n "$pack" ] || continue
70
+ url="$(get_pack_field "$config" "$pack" "url")"
71
+ ref="$(get_pack_field "$config" "$pack" "ref")"
72
+ mirror="$(get_pack_field "$config" "$pack" "mirror")"
73
+ [ -n "$url" ] || die "pack '$pack' has no url in config.yaml"
74
+ base="${url%.git}"; base="${base%/}"
75
+ repo="$(basename "$base")"
76
+ org="$(basename "$(dirname "$base")")"
77
+ case "$org" in ""|*[!A-Za-z0-9._-]*) org="local" ;; esac
78
+ case "$repo" in ""|*[!A-Za-z0-9._-]*) repo="$(printf '%s' "$repo" | tr -c 'A-Za-z0-9._-' '-')" ;; esac
79
+ name="@$org/$repo"
80
+ assert_valid_pkg_name "$name"
81
+ printf '%s\n' "$pack$LOCK_SEP$name$LOCK_SEP$url$LOCK_SEP$ref$LOCK_SEP$mirror"
82
+ done < <(read_yaml_keys "$config" "packs") >> "$pack_rows"
83
+
84
+ # Stage the store: mirrored packs are COPIED from their mirrors (content the
85
+ # repo already holds — the network is not consulted, and the mirror is not
86
+ # touched); transient packs are fetched.
87
+ lock_rows="$stage/lock.rows"
88
+ : > "$lock_rows"
89
+ while IFS="$LOCK_SEP" read -r pack name url ref mirror; do
90
+ [ -n "$pack" ] || continue
91
+ dest="$stage/.intelligence/packages/$name"
92
+ sha=""
93
+ if [ -n "$mirror" ] && [ -d "$root/$mirror" ]; then
94
+ mkdir -p "$dest"
95
+ cp -R "$root/$mirror/." "$dest/"
96
+ if [ -f "$dest/.pack" ]; then
97
+ sha="$(awk -F= '$1 == "sha" {print $2; exit}' "$dest/.pack")"
98
+ rm -f "$dest/.pack"
99
+ fi
100
+ echo " pack '$pack' -> $name (from mirror $mirror)"
101
+ else
102
+ sha="$(fetch_package "$url" "$ref" "" "$dest")"
103
+ echo " pack '$pack' -> $name (fetched)"
104
+ fi
105
+ if [ -z "$sha" ] || [ "$sha" = "unknown" ]; then
106
+ sha="$(GIT_TERMINAL_PROMPT=0 git ls-remote "$url" "$ref" 2>/dev/null | awk '{print $1; exit}')"
107
+ fi
108
+ printf '%s\037%s\037%s\037%s\037%s\037%s\n' \
109
+ "$name" "" "$url" "" "$ref" "$sha" >> "$lock_rows"
110
+ done < "$pack_rows"
111
+
112
+ # The manifest: config.yaml transformed line by line — comments and unknown
113
+ # blocks survive verbatim; `sync_version` and `packs:` are dropped (restamped
114
+ # / converted); sources entries are rewritten onto the store.
115
+ manifest_stage="$stage/intelligence.yaml"
116
+ rewrite_source_value() {
117
+ local v="$1" pack name rest
118
+ case "$v" in
119
+ "$module_rel"/rules|"$module_rel"/agents|"$module_rel"/skills)
120
+ printf '.intelligence/engine/%s' "${v##*/}"
121
+ return 0 ;;
122
+ @*)
123
+ rest="${v#@}"
124
+ pack="${rest%%/*}"
125
+ while IFS="$LOCK_SEP" read -r p name _ _ _; do
126
+ if [ "$p" = "$pack" ]; then
127
+ if [ "$rest" = "$pack" ]; then
128
+ printf '.intelligence/packages/%s' "$name"
129
+ else
130
+ printf '.intelligence/packages/%s/%s' "$name" "${rest#*/}"
131
+ fi
132
+ return 0
133
+ fi
134
+ done < "$pack_rows"
135
+ ;;
136
+ esac
137
+ printf '%s' "$v"
138
+ }
139
+ in_packs=0 in_sources=0
140
+ while IFS= read -r line || [ -n "$line" ]; do
141
+ line="${line%$'\r'}"
142
+ case "$line" in
143
+ sync_version:*) continue ;;
144
+ packs:*) in_packs=1; continue ;;
145
+ sources:*) in_sources=1; in_packs=0; echo "$line"; continue ;;
146
+ [!\ \#]*) in_packs=0; in_sources=0 ;;
147
+ esac
148
+ [ "$in_packs" -eq 1 ] && continue
149
+ if [ "$in_sources" -eq 1 ]; then
150
+ case "$line" in
151
+ *"- "*)
152
+ indent="${line%%-*}"
153
+ v="${line#*- }"
154
+ v="${v%\"}"; v="${v#\"}"; v="${v%\'}"; v="${v#\'}"
155
+ echo "$indent- \"$(rewrite_source_value "$v")\""
156
+ continue
157
+ ;;
158
+ esac
159
+ fi
160
+ echo "$line"
161
+ done < "$config" > "$manifest_stage"
162
+ stamp_version "$manifest_stage" "$eng"
163
+
164
+ # packages: entries (pin preserved — no invented ranges).
165
+ while IFS="$LOCK_SEP" read -r pack name url ref mirror; do
166
+ [ -n "$pack" ] || continue
167
+ qmap_set "$manifest_stage" "packages" "$name" "url" "$url"
168
+ [ -n "$ref" ] && qmap_set "$manifest_stage" "packages" "$name" "ref" "$ref"
169
+ done < "$pack_rows"
170
+
171
+ # ---- Verify ---------------------------------------------------------------
172
+ echo "== verifying staged state =="
173
+ fail=0
174
+ for section in rules agents skills; do
175
+ while IFS= read -r src; do
176
+ [ -n "$src" ] || continue
177
+ case "$src" in
178
+ .intelligence/*) [ -d "$stage/$src" ] || { echo " MISSING (staged): $src"; fail=1; } ;;
179
+ git+*|@*) echo " UNCONVERTED source token: $src"; fail=1 ;;
180
+ *) [ -d "$root/$src" ] || echo " NOTE: local source '$src' does not exist (kept — same as before)" ;;
181
+ esac
182
+ done < <(read_yaml_list "$manifest_stage" "$section")
183
+ done
184
+ for adapter in agents claude cursor copilot codex pi opencode; do
185
+ old_e="$(is_target_enabled "$config" "$adapter")"
186
+ new_e="$(is_target_enabled "$manifest_stage" "$adapter")"
187
+ [ "$old_e" = "$new_e" ] || { echo " TARGET DRIFT: $adapter enabled '$old_e' -> '$new_e'"; fail=1; }
188
+ old_o="$(get_target_output "$config" "$adapter")"
189
+ new_o="$(get_target_output "$manifest_stage" "$adapter")"
190
+ [ "$old_o" = "$new_o" ] || { echo " TARGET DRIFT: $adapter output '$old_o' -> '$new_o'"; fail=1; }
191
+ done
192
+ [ "$fail" -eq 0 ] || die "staged state failed verification — nothing changed"
193
+
194
+ if [ "$dry_run" -eq 1 ]; then
195
+ echo ""
196
+ echo "== dry run — the project is untouched. Staged manifest: =="
197
+ cat "$manifest_stage"
198
+ echo ""
199
+ echo "Would: write intelligence.yaml + intelligence.lock, move the store in,"
200
+ echo "sync, then remove $module_rel/, config.yaml and the pack mirrors."
201
+ exit 0
202
+ fi
203
+
204
+ # ---- Commit ---------------------------------------------------------------
205
+ echo "== committing =="
206
+ if [ ! -f "$root/.gitignore" ] || ! grep -q '^\.intelligence/' "$root/.gitignore"; then
207
+ {
208
+ [ -f "$root/.gitignore" ] && [ -n "$(tail -c 1 "$root/.gitignore" 2>/dev/null)" ] && echo ""
209
+ echo "# intelligence CLI package store (restored by 'intelligence install')"
210
+ echo ".intelligence/"
211
+ } >> "$root/.gitignore"
212
+ fi
213
+ rollback() {
214
+ rm -rf "$root/.intelligence" "$root/intelligence.yaml" "$root/intelligence.lock"
215
+ echo "rolled back — the vendored setup is untouched" >&2
216
+ }
217
+ mv "$stage/.intelligence" "$root/.intelligence"
218
+ cp "$manifest_stage" "$root/intelligence.yaml"
219
+ lock_write_from_tsv "$root/intelligence.lock" "$lock_rows"
220
+
221
+ sync_out="$(cd "$root" && IS_SUPPRESS_CLI_NOTE=1 bash "$CLI_DIR/commands/sync.sh" 2>&1)" || {
222
+ echo "$sync_out"
223
+ rollback
224
+ die "sync of the migrated state failed — rolled back"
225
+ }
226
+ echo "$sync_out" | grep -q '^IS_STATUS=ok' || {
227
+ echo "$sync_out"
228
+ rollback
229
+ die "sync of the migrated state did not report ok — rolled back"
230
+ }
231
+
232
+ # Only now is anything of the old setup removed — and config.yaml is kept as
233
+ # a reviewable backup inside the store.
234
+ mkdir -p "$root/.intelligence/backup"
235
+ cp "$config" "$root/.intelligence/backup/config.yaml"
236
+ while IFS="$LOCK_SEP" read -r pack name url ref mirror; do
237
+ if [ -n "$mirror" ] && [ -d "$root/$mirror" ]; then
238
+ rm -rf "${root:?}/$mirror"
239
+ # An emptied mirror parent (e.g. <umbrella>/external/) goes with it.
240
+ rmdir "$(dirname "$root/$mirror")" 2>/dev/null || true
241
+ fi
242
+ done < "$pack_rows"
243
+ rm -rf "$module_dir"
244
+ rm -f "$config"
245
+ # An emptied umbrella dir (config-only setups) is dropped; one with project
246
+ # content stays.
247
+ rmdir "$umbrella" 2>/dev/null || true
248
+
249
+ echo ""
250
+ echo "migrated. Review the diff, then commit. The old config.yaml is kept at .intelligence/backup/config.yaml."
251
+ echo "From now on: intelligence sync | add | install | doctor."
@@ -0,0 +1,51 @@
1
+ #!/bin/bash
2
+ # intelligence registry <list | add @scope <registry-repo-url> | remove @scope>
3
+ #
4
+ # A registry binding is rare, per-scope configuration (npm's @scope:registry
5
+ # analog): the URL of a git repo whose index.yaml maps names to sources.
6
+ set -euo pipefail
7
+ source "$CLI_DIR/lib/cli-common.sh"
8
+
9
+ sub="${1:-list}"
10
+ case "$sub" in
11
+ list)
12
+ detect_project
13
+ if [ "$IP_MODE" = "v2" ] && [ -f "$IP_ROOT/intelligence.yaml" ]; then
14
+ echo "Project bindings (intelligence.yaml):"
15
+ found=0
16
+ while IFS= read -r scope; do
17
+ [ -n "$scope" ] || continue
18
+ found=1
19
+ echo " $scope -> $(qmap_value "$IP_ROOT/intelligence.yaml" "registries" "$scope")"
20
+ done < <(qmap_keys "$IP_ROOT/intelligence.yaml" "registries")
21
+ [ "$found" -eq 0 ] && echo " (none)"
22
+ fi
23
+ bundled="$(default_index_file)"
24
+ if [ -n "$bundled" ]; then
25
+ echo "Bundled index:"
26
+ while IFS= read -r name; do
27
+ [ -n "$name" ] || continue
28
+ echo " $name -> $(qmap_field "$bundled" "packages" "$name" "url")"
29
+ done < <(qmap_keys "$bundled" "packages")
30
+ fi
31
+ echo "Fallback: @org/name -> https://github.com/org/name.git"
32
+ ;;
33
+ add)
34
+ scope="${2:-}"; url="${3:-}"
35
+ { [ -n "$scope" ] && [ -n "$url" ]; } || die "usage: intelligence registry add @scope <registry-repo-url>"
36
+ case "$scope" in @*/*) die "bind a scope (@acme), not a package name" ;; @*) ;; *) die "scope must start with @" ;; esac
37
+ require_v2
38
+ qmap_set_value "$IP_ROOT/intelligence.yaml" "registries" "$scope" "$url"
39
+ echo "$scope -> $url"
40
+ ;;
41
+ remove)
42
+ scope="${2:-}"
43
+ [ -n "$scope" ] || die "usage: intelligence registry remove @scope"
44
+ require_v2
45
+ qmap_delete_key "$IP_ROOT/intelligence.yaml" "registries" "$scope"
46
+ echo "unbound $scope"
47
+ ;;
48
+ *)
49
+ die "usage: intelligence registry <list | add @scope <url> | remove @scope>"
50
+ ;;
51
+ esac
@@ -0,0 +1,39 @@
1
+ #!/bin/bash
2
+ # intelligence remove <@scope/name> [--no-sync]
3
+ set -euo pipefail
4
+ source "$CLI_DIR/lib/cli-common.sh"
5
+
6
+ name="${1:-}"
7
+ [ -n "$name" ] || die "usage: intelligence remove <@scope/name>"
8
+ shift || true
9
+ no_sync=0
10
+ for a in "$@"; do
11
+ case "$a" in
12
+ --no-sync) no_sync=1 ;;
13
+ *) die "unknown option '$a'" ;;
14
+ esac
15
+ done
16
+
17
+ require_v2
18
+ assert_valid_pkg_name "$name"
19
+ manifest="$IP_ROOT/intelligence.yaml"
20
+ lock="$IP_ROOT/intelligence.lock"
21
+ rel=".intelligence/packages/$name"
22
+
23
+ known=0
24
+ while IFS= read -r k; do
25
+ [ "$k" = "$name" ] && known=1
26
+ done < <(qmap_keys "$manifest" "packages")
27
+ [ "$known" -eq 1 ] || die "package '$name' is not in the manifest"
28
+
29
+ unwire_package_sources "$manifest" "$rel"
30
+ qmap_delete_key "$manifest" "packages" "$name"
31
+ lock_remove "$lock" "$name"
32
+ rm -rf "${IP_ROOT:?}/$rel"
33
+ # Drop the now-empty scope dir so the store stays tidy.
34
+ rmdir "$IP_ROOT/.intelligence/packages/${name%%/*}" 2>/dev/null || true
35
+ echo "- $name"
36
+
37
+ if [ "$no_sync" -eq 0 ]; then
38
+ exec bash "$CLI_DIR/commands/sync.sh"
39
+ fi
@@ -0,0 +1,34 @@
1
+ #!/bin/bash
2
+ # intelligence status — project state at a glance.
3
+ set -euo pipefail
4
+ source "$CLI_DIR/lib/cli-common.sh"
5
+
6
+ detect_project
7
+ case "$IP_MODE" in
8
+ v2)
9
+ echo "Project: $IP_ROOT (CLI setup)"
10
+ echo "Manifest: intelligence.yaml (sync_version $(read_engine_stamp "$IP_ROOT/intelligence.yaml"))"
11
+ if [ -f "$IP_ROOT/intelligence.lock" ]; then
12
+ echo "Lockfile: intelligence.lock"
13
+ else
14
+ echo "Lockfile: none (no packages added yet)"
15
+ fi
16
+ if [ -f "$IP_ROOT/.intelligence/engine/.version" ]; then
17
+ echo "Store: .intelligence/engine at $(tr -d ' \t\r\n' < "$IP_ROOT/.intelligence/engine/.version")"
18
+ else
19
+ echo "Store: not staged — run 'intelligence install'"
20
+ fi
21
+ echo "Engine: $(bundled_engine_version) (bundled)"
22
+ ;;
23
+ legacy)
24
+ echo "Project: $IP_ROOT (vendored v1 setup)"
25
+ echo "Umbrella: $IP_UMBRELLA"
26
+ echo "Engine: $(tr -d ' \t\r\n' < "$IP_MODULE_DIR/scripts/VERSION") (vendored at $IP_MODULE_DIR)"
27
+ echo "Stamp: $(read_engine_stamp "$IP_UMBRELLA/config.yaml")"
28
+ echo ""
29
+ echo "Convert to the CLI setup: intelligence migrate"
30
+ ;;
31
+ *)
32
+ echo "No intelligence project here. Start one: intelligence init"
33
+ ;;
34
+ esac
@@ -0,0 +1,22 @@
1
+ #!/bin/bash
2
+ # intelligence sync [target] — render intelligence to every enabled tool.
3
+ set -euo pipefail
4
+ source "$CLI_DIR/lib/cli-common.sh"
5
+
6
+ detect_project
7
+ case "$IP_MODE" in
8
+ v2)
9
+ ensure_engine_staged "$IP_ROOT"
10
+ export_engine_env "$IP_ROOT"
11
+ exec bash "$IS_ENGINE_DIR/scripts/sync.sh" "$@"
12
+ ;;
13
+ legacy)
14
+ # A vendored project syncs with ITS engine — its pin is the contract,
15
+ # and a newer bundled engine must not generate against an older schema.
16
+ echo "NOTE: vendored (v1) setup — delegating to its own engine. 'intelligence migrate' converts it to the CLI setup." >&2
17
+ exec bash "$IP_MODULE_DIR/scripts/sync.sh" "$@"
18
+ ;;
19
+ *)
20
+ die "no intelligence project found here — run 'intelligence init'"
21
+ ;;
22
+ esac
@@ -0,0 +1,59 @@
1
+ #!/bin/bash
2
+ # intelligence update [name] [--no-sync]
3
+ #
4
+ # Re-resolve version ranges against the remotes and rewrite the lock. Pinned
5
+ # packages (`ref:`) never move here — repin by editing the manifest or
6
+ # re-adding. `update <name>` limits the pass to one package.
7
+ set -euo pipefail
8
+ source "$CLI_DIR/lib/cli-common.sh"
9
+
10
+ only="" no_sync=0
11
+ while [ $# -gt 0 ]; do
12
+ case "$1" in
13
+ --no-sync) no_sync=1 ;;
14
+ @*) only="$1" ;;
15
+ *) die "unknown argument '$1'" ;;
16
+ esac
17
+ shift || true
18
+ done
19
+
20
+ require_v2
21
+ manifest="$IP_ROOT/intelligence.yaml"
22
+ lock="$IP_ROOT/intelligence.lock"
23
+
24
+ moved=0 checked=0
25
+ while IFS= read -r name; do
26
+ [ -n "$name" ] || continue
27
+ [ -n "$only" ] && [ "$name" != "$only" ] && continue
28
+ ref="$(qmap_field "$manifest" "packages" "$name" "ref")"
29
+ [ -n "$ref" ] && { echo " $name: pinned to ref '$ref' — skipped"; continue; }
30
+ range="$(qmap_field "$manifest" "packages" "$name" "version")"
31
+ url="$(qmap_field "$manifest" "packages" "$name" "url")"
32
+ path="$(qmap_field "$manifest" "packages" "$name" "path")"
33
+ if [ -z "$url" ]; then
34
+ resolve_package_source "$manifest" "$name"
35
+ url="$RES_URL"; path="$RES_PATH"
36
+ fi
37
+ checked=$((checked + 1))
38
+ picked="$(list_remote_versions "$url" | semver_pick_highest "$range")"
39
+ [ -n "$picked" ] || { echo " $name: nothing satisfies '${range:-*}' at $url" >&2; continue; }
40
+ read -r tag _ <<< "$(remote_tag_for_version "$url" "$picked")"
41
+ current="$(qmap_field "$lock" "packages" "$name" "resolved")"
42
+ if [ "$tag" = "$current" ]; then
43
+ echo " $name: ${current:-<none>} (up to date)"
44
+ continue
45
+ fi
46
+ rel=".intelligence/packages/$name"
47
+ sha="$(fetch_package "$url" "$tag" "$path" "$IP_ROOT/$rel")"
48
+ wire_package_sources "$manifest" "$name" "$rel" "$IP_ROOT"
49
+ lock_upsert "$lock" "$name" "$range" "$url" "$path" "$tag" "$sha"
50
+ echo " $name: ${current:-<none>} -> $tag"
51
+ moved=$((moved + 1))
52
+ done < <(qmap_keys "$manifest" "packages")
53
+
54
+ [ -n "$only" ] && [ "$checked" -eq 0 ] && die "package '$only' is not in the manifest"
55
+ echo "updated: $moved package(s)"
56
+
57
+ if [ "$moved" -gt 0 ] && [ "$no_sync" -eq 0 ]; then
58
+ exec bash "$CLI_DIR/commands/sync.sh"
59
+ fi
@@ -0,0 +1,27 @@
1
+ #!/bin/bash
2
+ # intelligence upgrade — bring the project to this CLI's engine: restage the
3
+ # engine content, apply v2 schema migrations (none yet — the chain starts
4
+ # empty by design), restamp sync_version, sync.
5
+ set -euo pipefail
6
+ source "$CLI_DIR/lib/cli-common.sh"
7
+
8
+ require_v2
9
+ manifest="$IP_ROOT/intelligence.yaml"
10
+
11
+ stamp="$(read_engine_stamp "$manifest")"
12
+ eng="$(bundled_engine_version)"
13
+ if [ -n "$stamp" ] && _ver_gt "$stamp" "$eng"; then
14
+ die "manifest schema $stamp is newer than this CLI's engine $eng — update the CLI first: npm i -g @ainova-systems/intelligence@latest"
15
+ fi
16
+
17
+ # v2 schema migrations live HERE, not in the engine's chain (that one owns
18
+ # vendored layouts). Same discipline: ascending, append-only, each migration
19
+ # self-detects and no-ops when already applied.
20
+ # V2_MIGRATIONS=( ) — first entry arrives with the first breaking v2 change.
21
+
22
+ stage_engine_content "$IP_ROOT/.intelligence/engine"
23
+ echo " engine content restaged ($eng)"
24
+ stamp_version "$manifest" "$eng"
25
+ echo " sync_version -> $eng"
26
+
27
+ exec bash "$CLI_DIR/commands/sync.sh"
@@ -0,0 +1,71 @@
1
+ #!/bin/bash
2
+ # intelligence — the CLI for Intelligence Packages and the sync engine.
3
+ #
4
+ # Dispatcher only: each command lives in commands/<name>.sh so commands can be
5
+ # ported to Node one at a time without touching the others. The engine is the
6
+ # vendored bash engine bundled next to the CLI (npm package) or, when running
7
+ # from the intelligence-sync repo itself, the repo's own module.
8
+
9
+ set -euo pipefail
10
+
11
+ CLI_DIR="$(cd "$(dirname "$0")" && pwd)"
12
+ export CLI_DIR
13
+
14
+ # Engine discovery, by role (scripts/sync.sh + scripts/VERSION), never by
15
+ # guessing names beyond the two shipped layouts:
16
+ # 1. npm package: <pkg>/cli/intelligence + <pkg>/engine/scripts/
17
+ # 2. this repo: <repo>/cli/intelligence + <repo>/intelligence/sync/scripts/
18
+ IS_ENGINE_DIR=""
19
+ for _cand in "$CLI_DIR/../engine" "$CLI_DIR/../intelligence/sync"; do
20
+ if [ -f "$_cand/scripts/sync.sh" ] && [ -f "$_cand/scripts/VERSION" ]; then
21
+ IS_ENGINE_DIR="$(cd "$_cand" && pwd)"
22
+ break
23
+ fi
24
+ done
25
+ if [ -z "$IS_ENGINE_DIR" ]; then
26
+ echo "ERROR: bundled sync engine not found next to the CLI ($CLI_DIR)." >&2
27
+ echo " Reinstall: npm i -g @ainova-systems/intelligence" >&2
28
+ exit 1
29
+ fi
30
+ export IS_ENGINE_DIR
31
+
32
+ cmd="${1:-}"
33
+ case "$cmd" in
34
+ ""|help|-h|--help)
35
+ engine_ver="$(tr -d ' \t\r\n' < "$IS_ENGINE_DIR/scripts/VERSION")"
36
+ cat <<EOF
37
+ intelligence — build, version and distribute AI agent intelligence
38
+ (engine $engine_ver${INTELLIGENCE_NPM_VERSION:+, package $INTELLIGENCE_NPM_VERSION})
39
+
40
+ Usage: intelligence <command> [args]
41
+
42
+ init Set up this project (manifest, content skeleton, targets)
43
+ add <spec> Add a package: @scope/name[@range] | github:org/repo[#path] | git+<url>[@ref][#path]
44
+ remove <name> Remove a package
45
+ install [--frozen] Restore .intelligence/ exactly from intelligence.lock
46
+ update [name] Re-resolve version ranges and rewrite the lockfile
47
+ upgrade Upgrade the project to this CLI's engine (restage + restamp)
48
+ list Installed packages with requested/locked versions
49
+ sync [target] Render intelligence to every enabled tool (.claude, AGENTS.md, ...)
50
+ registry <list|add|remove> Bind a scope to a registry index
51
+ migrate [--dry-run] Convert a vendored (v1) setup to the CLI setup
52
+ doctor Check manifest, lockfile, store and engine consistency
53
+ status Project state at a glance
54
+ version Print CLI and engine versions
55
+ EOF
56
+ exit 0
57
+ ;;
58
+ version|-v|--version)
59
+ engine_ver="$(tr -d ' \t\r\n' < "$IS_ENGINE_DIR/scripts/VERSION")"
60
+ echo "${INTELLIGENCE_NPM_VERSION:-$engine_ver} (engine $engine_ver)"
61
+ exit 0
62
+ ;;
63
+ esac
64
+ shift
65
+
66
+ cmd_file="$CLI_DIR/commands/$cmd.sh"
67
+ if [ ! -f "$cmd_file" ]; then
68
+ echo "ERROR: unknown command '$cmd'. Run 'intelligence help'." >&2
69
+ exit 1
70
+ fi
71
+ exec bash "$cmd_file" "$@"