@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.
- package/LICENSE +21 -0
- package/README.md +46 -0
- package/bin/intelligence.js +59 -0
- package/cli/commands/add.sh +133 -0
- package/cli/commands/doctor.sh +100 -0
- package/cli/commands/init.sh +96 -0
- package/cli/commands/install.sh +84 -0
- package/cli/commands/list.sh +28 -0
- package/cli/commands/migrate.sh +251 -0
- package/cli/commands/registry.sh +51 -0
- package/cli/commands/remove.sh +39 -0
- package/cli/commands/status.sh +34 -0
- package/cli/commands/sync.sh +22 -0
- package/cli/commands/update.sh +59 -0
- package/cli/commands/upgrade.sh +27 -0
- package/cli/intelligence +71 -0
- package/cli/lib/cli-common.sh +149 -0
- package/cli/lib/lockfile.sh +97 -0
- package/cli/lib/manifest.sh +211 -0
- package/cli/lib/registry.sh +141 -0
- package/cli/lib/semver.sh +127 -0
- package/engine/INIT.md +498 -0
- package/engine/agents/intelligence-architect.md +53 -0
- package/engine/agents/intelligence-operator.md +49 -0
- package/engine/docs/ADAPTERS.md +212 -0
- package/engine/docs/CLI.md +91 -0
- package/engine/docs/CONVENTIONS.md +440 -0
- package/engine/rules/intelligence-authoring.md +114 -0
- package/engine/scripts/VERSION +1 -0
- package/engine/scripts/adapters/_template.sh +86 -0
- package/engine/scripts/adapters/agents.sh +299 -0
- package/engine/scripts/adapters/claude.sh +136 -0
- package/engine/scripts/adapters/codex.sh +118 -0
- package/engine/scripts/adapters/copilot.sh +193 -0
- package/engine/scripts/adapters/cursor.sh +146 -0
- package/engine/scripts/adapters/opencode.sh +200 -0
- package/engine/scripts/adapters/pi.sh +256 -0
- package/engine/scripts/lib/common.sh +1602 -0
- package/engine/scripts/lib/layout.sh +51 -0
- package/engine/scripts/lib/migrations.sh +708 -0
- package/engine/scripts/sync.sh +311 -0
- package/engine/scripts/update.sh +237 -0
- package/engine/skills/intelligence-add-agent/SKILL.md +62 -0
- package/engine/skills/intelligence-add-rule/SKILL.md +54 -0
- package/engine/skills/intelligence-add-skill/SKILL.md +53 -0
- package/engine/skills/intelligence-extract-skill/SKILL.md +47 -0
- package/engine/skills/intelligence-install-adapter/SKILL.md +31 -0
- package/engine/skills/intelligence-learn-from-context/SKILL.md +69 -0
- package/engine/skills/intelligence-review-skills/SKILL.md +86 -0
- package/engine/skills/intelligence-sync/SKILL.md +18 -0
- package/engine/skills/intelligence-uninstall-adapter/SKILL.md +42 -0
- package/engine/skills/intelligence-update/SKILL.md +159 -0
- package/package.json +39 -0
- 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"
|
package/cli/intelligence
ADDED
|
@@ -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" "$@"
|