@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.
Files changed (72) hide show
  1. package/README.md +19 -16
  2. package/cli/commands/adapter.sh +153 -0
  3. package/cli/commands/init.sh +171 -34
  4. package/cli/commands/package.sh +30 -0
  5. package/cli/commands/registry.sh +65 -30
  6. package/cli/commands/status.sh +20 -11
  7. package/cli/commands/sync.sh +9 -4
  8. package/cli/commands/update.sh +80 -46
  9. package/cli/engine-package.yaml +14 -0
  10. package/cli/intelligence +37 -26
  11. package/cli/internal/align-project.sh +134 -0
  12. package/cli/internal/check.sh +128 -0
  13. package/cli/internal/convert-legacy.sh +400 -0
  14. package/cli/{commands/add.sh → internal/package-add.sh} +37 -19
  15. package/cli/{commands/list.sh → internal/package-list.sh} +10 -5
  16. package/cli/{commands/remove.sh → internal/package-remove.sh} +16 -4
  17. package/cli/internal/package-search.sh +83 -0
  18. package/cli/internal/package-update.sh +103 -0
  19. package/cli/internal/restore.sh +130 -0
  20. package/cli/internal/target-state.sh +57 -0
  21. package/cli/lib/cli-common.sh +213 -63
  22. package/cli/lib/lockfile.sh +15 -9
  23. package/cli/lib/manifest.sh +257 -4
  24. package/cli/lib/registry.sh +96 -47
  25. package/cli/lib/semver.sh +12 -4
  26. package/engine/ENGINE_SHA +1 -0
  27. package/engine/{scripts/adapters → adapters}/_template.sh +10 -9
  28. package/engine/{scripts/adapters → adapters}/agents.sh +20 -25
  29. package/engine/{scripts/adapters → adapters}/opencode.sh +1 -1
  30. package/engine/{scripts/lib → lib}/common.sh +30 -538
  31. package/engine/lib/contract.sh +120 -0
  32. package/engine/sync.sh +238 -0
  33. package/package.json +5 -5
  34. package/{engine → packages/sync}/agents/intelligence-architect.md +5 -3
  35. package/{engine → packages/sync}/agents/intelligence-operator.md +10 -13
  36. package/packages/sync/references/adapters.md +252 -0
  37. package/packages/sync/references/conventions.md +385 -0
  38. package/{engine → packages/sync}/rules/intelligence-authoring.md +7 -7
  39. package/{engine → packages/sync}/skills/intelligence-add-agent/SKILL.md +7 -7
  40. package/{engine → packages/sync}/skills/intelligence-add-rule/SKILL.md +5 -5
  41. package/{engine → packages/sync}/skills/intelligence-add-skill/SKILL.md +5 -5
  42. package/{engine → packages/sync}/skills/intelligence-extract-skill/SKILL.md +2 -2
  43. package/packages/sync/skills/intelligence-install-adapter/SKILL.md +38 -0
  44. package/{engine → packages/sync}/skills/intelligence-learn-from-context/SKILL.md +3 -3
  45. package/packages/sync/skills/intelligence-learn-from-repository/SKILL.md +55 -0
  46. package/{engine → packages/sync}/skills/intelligence-review-skills/SKILL.md +7 -7
  47. package/packages/sync/skills/intelligence-sync/SKILL.md +20 -0
  48. package/packages/sync/skills/intelligence-uninstall-adapter/SKILL.md +24 -0
  49. package/packages/sync/skills/intelligence-update/SKILL.md +43 -0
  50. package/cli/commands/doctor.sh +0 -100
  51. package/cli/commands/install.sh +0 -84
  52. package/cli/commands/migrate.sh +0 -251
  53. package/cli/commands/upgrade.sh +0 -27
  54. package/engine/INIT.md +0 -498
  55. package/engine/docs/ADAPTERS.md +0 -212
  56. package/engine/docs/CLI.md +0 -91
  57. package/engine/docs/CONVENTIONS.md +0 -440
  58. package/engine/scripts/lib/layout.sh +0 -51
  59. package/engine/scripts/lib/migrations.sh +0 -708
  60. package/engine/scripts/sync.sh +0 -311
  61. package/engine/scripts/update.sh +0 -237
  62. package/engine/skills/intelligence-install-adapter/SKILL.md +0 -31
  63. package/engine/skills/intelligence-sync/SKILL.md +0 -18
  64. package/engine/skills/intelligence-uninstall-adapter/SKILL.md +0 -42
  65. package/engine/skills/intelligence-update/SKILL.md +0 -159
  66. package/registry/index.yaml +0 -15
  67. /package/engine/{scripts/VERSION → VERSION} +0 -0
  68. /package/engine/{scripts/adapters → adapters}/claude.sh +0 -0
  69. /package/engine/{scripts/adapters → adapters}/codex.sh +0 -0
  70. /package/engine/{scripts/adapters → adapters}/copilot.sh +0 -0
  71. /package/engine/{scripts/adapters → adapters}/cursor.sh +0 -0
  72. /package/engine/{scripts/adapters → adapters}/pi.sh +0 -0
package/README.md CHANGED
@@ -3,11 +3,11 @@
3
3
  **npm for AI agent intelligence.** One CLI that builds, versions and distributes the rules, agents and skills your AI coding tools run on — rendered natively for Claude Code, Cursor, GitHub Copilot, OpenAI Codex, Pi, OpenCode and `AGENTS.md`.
4
4
 
5
5
  ```bash
6
- npm install -g @ainova-systems/intelligence
6
+ npm install -g @ainova-systems/intelligence@next
7
7
 
8
8
  cd your-project
9
9
  intelligence init
10
- intelligence add @ainova-systems/core
10
+ intelligence package add @ainova-systems/core
11
11
  intelligence sync
12
12
  ```
13
13
 
@@ -22,25 +22,28 @@ intelligence/ # your own rules / agents / skills
22
22
  AGENTS.md
23
23
  ```
24
24
 
25
- Teammates need one command after cloning:
25
+ Teammates need one command after cloning; it restores the locked package store before rendering:
26
26
 
27
27
  ```bash
28
- intelligence install
28
+ intelligence sync
29
29
  ```
30
30
 
31
31
  ## Commands
32
32
 
33
33
  | Command | What it does |
34
34
  |---|---|
35
- | `intelligence init` | Detect your tools, write the manifest, first sync |
36
- | `intelligence add <pkg>` | `@scope/name[@range]`, `github:org/repo[#path]`, or `git+<url>[@ref][#path]` |
37
- | `intelligence install [--frozen]` | Restore `.intelligence/` exactly from the lockfile |
38
- | `intelligence update [pkg]` | Re-resolve version ranges, rewrite the lock |
39
- | `intelligence sync [target]` | Render intelligence to every enabled tool |
40
- | `intelligence list` / `doctor` / `status` | Inspect and verify |
41
- | `intelligence registry add @scope <url>` | Bind a scope to a private registry index |
42
- | `intelligence migrate` | Convert a vendored intelligence-sync setup to the CLI |
43
-
44
- Any git repo with `rules/`, `agents/` or `skills/` at its root is already an Intelligence Package: `intelligence add @your-org/your-repo` resolves it straight from GitHub — versions come from its `x.y.z` git tags. A monorepo of packages needs one line in a registry index.
45
-
46
- Requires `git` (and on Windows the bash it ships with — Git for Windows). Engine and docs: [ainova-systems/intelligence-sync](https://github.com/ainova-systems/intelligence-sync).
35
+ | `intelligence init [--preview\|--apply]` | Create, convert, restore or align a project |
36
+ | `intelligence sync [adapter]` | Restore locked content if needed, then render all or one enabled adapter |
37
+ | `intelligence update [@scope/name] [--preview\|--apply]` | Plan or apply project and ranged-package updates |
38
+ | `intelligence package add\|remove\|list\|search` | Manage versioned Intelligence Packages |
39
+ | `intelligence adapter list\|create\|enable\|disable\|remove` | Manage render adapters |
40
+ | `intelligence status [--check]` | Inspect project state and consistency |
41
+ | `intelligence registry list\|add\|remove` | Manage trusted registry repositories |
42
+
43
+ Any git repo with `rules/`, `agents/` or `skills/` at its root is already an Intelligence Package: install it from an explicit source — `intelligence package add github:your-org/your-repo` — with versions from its `x.y.z` git tags. Names (`@scope/name`) resolve only through registries this project explicitly trusts; a monorepo of packages needs one line in such an index.
44
+
45
+ Every package has the same compact manifest entry: requested `version` or
46
+ `ref` only. Repository URL/path, resolved tag/ref and commit SHA are recorded
47
+ in the committed `intelligence.lock`.
48
+
49
+ Requires `git` (and on Windows the bash it ships with — Git for Windows). Engine and docs: [ainova-systems/intelligence](https://github.com/ainova-systems/intelligence).
@@ -0,0 +1,153 @@
1
+ #!/bin/bash
2
+ # intelligence adapter <list|create|enable|disable|remove> [name]
3
+ set -euo pipefail
4
+ source "$CLI_DIR/lib/cli-common.sh"
5
+
6
+ action="${1:-}"
7
+ name="${2:-}"
8
+
9
+ adapter_list() {
10
+ detect_project
11
+ local manifest="" content_dir="" seen=" " file item enabled output configured
12
+ if [ "$IP_MODE" = "cli" ]; then
13
+ manifest="$IP_ROOT/intelligence.yaml"
14
+ content_dir="$(manifest_intelligence_dir "$manifest")"
15
+ fi
16
+
17
+ printf '%-16s %-10s %-10s %s\n' "NAME" "SOURCE" "STATE" "OUTPUT"
18
+ # Project adapters come first because they override built-ins by name.
19
+ if [ -n "$content_dir" ] && [ -d "$IP_ROOT/$content_dir/adapters" ]; then
20
+ for file in "$IP_ROOT/$content_dir/adapters"/*.sh; do
21
+ [ -f "$file" ] || continue
22
+ item="$(basename "$file" .sh)"
23
+ seen="$seen$item "
24
+ enabled="disabled"; output="$(default_target_output "$item")"
25
+ [ "$(is_target_enabled "$manifest" "$item")" = "1" ] && enabled="enabled"
26
+ configured="$(get_target_output "$manifest" "$item")"
27
+ [ -z "$configured" ] || output="$configured"
28
+ printf '%-16s %-10s %-10s %s\n' "$item" "project" "$enabled" "$output"
29
+ done
30
+ fi
31
+ for file in "$IS_ENGINE_DIR/adapters"/*.sh; do
32
+ [ -f "$file" ] || continue
33
+ item="$(basename "$file" .sh)"
34
+ [ "$item" = "_template" ] && continue
35
+ case "$seen" in *" $item "*) continue ;; esac
36
+ enabled="disabled"; output="$(default_target_output "$item")"
37
+ if [ -n "$manifest" ]; then
38
+ [ "$(is_target_enabled "$manifest" "$item")" = "1" ] && enabled="enabled"
39
+ configured="$(get_target_output "$manifest" "$item")"
40
+ [ -z "$configured" ] || output="$configured"
41
+ fi
42
+ printf '%-16s %-10s %-10s %s\n' "$item" "built-in" "$enabled" "$output"
43
+ done
44
+ }
45
+
46
+ adapter_create() {
47
+ [ -n "$name" ] && [ $# -eq 0 ] || die "usage: intelligence adapter create <name>"
48
+ assert_valid_target_name "$name"
49
+ require_cli_project
50
+ ensure_project_current "$IP_ROOT"
51
+ local manifest="$IP_ROOT/intelligence.yaml" content_dir repo_phys probe old_ifs part probe_phys
52
+ local template adapter_dir adapter_phys dest tmp
53
+ local -a parts
54
+ content_dir="$(manifest_intelligence_dir "$manifest")"
55
+ case "$content_dir" in
56
+ ""|/*|.|..|../*|*/../*|*/..|.intelligence|.intelligence/*)
57
+ die "unsafe project.intelligence_dir '$content_dir'"
58
+ ;;
59
+ esac
60
+ repo_phys="$(cd "$IP_ROOT" && pwd -P)"
61
+ probe="$IP_ROOT"
62
+ old_ifs="$IFS"; IFS='/'; read -r -a parts <<< "$content_dir"; IFS="$old_ifs"
63
+ for part in "${parts[@]}"; do
64
+ [ -n "$part" ] || continue
65
+ probe="$probe/$part"
66
+ if [ -e "$probe" ] || [ -L "$probe" ]; then
67
+ probe_phys="$(cd "$probe" 2>/dev/null && pwd -P)" || die "cannot resolve project content path '$content_dir'"
68
+ case "$probe_phys" in "$repo_phys"|"$repo_phys"/*) ;; *) die "project.intelligence_dir resolves outside the repository: '$content_dir'" ;; esac
69
+ fi
70
+ done
71
+ template="$IS_ENGINE_DIR/adapters/_template.sh"
72
+ [ -f "$template" ] || die "corrupt CLI installation: bundled adapter template is missing"
73
+ adapter_dir="$IP_ROOT/$content_dir/adapters"
74
+ dest="$adapter_dir/$name.sh"
75
+ [ ! -e "$dest" ] || die "project adapter already exists: $content_dir/adapters/$name.sh"
76
+ mkdir -p "$adapter_dir"
77
+ adapter_phys="$(cd "$adapter_dir" && pwd -P)"
78
+ case "$adapter_phys" in "$repo_phys"|"$repo_phys"/*) ;; *) die "project adapter directory resolves outside the repository" ;; esac
79
+ tmp="$(mktemp "$adapter_dir/.${name}.XXXXXX")"
80
+ trap '[ -z "${tmp:-}" ] || rm -f "$tmp"' EXIT
81
+ awk -v name="$name" '{ gsub(/<agent-name>/, name); gsub(/<Agent Name>/, name); gsub(/<name>/, name); print }' "$template" > "$tmp"
82
+ [ -s "$tmp" ] || die "adapter template produced an empty file"
83
+ mv "$tmp" "$dest"
84
+ tmp=""
85
+ echo "created: $content_dir/adapters/$name.sh"
86
+ echo " implement sync_to_${name}(), then run: intelligence adapter enable $name"
87
+ }
88
+
89
+ adapter_remove() {
90
+ local apply=0 manifest content_dir file answer repo_phys adapter_dir adapter_phys
91
+ while [ $# -gt 0 ]; do
92
+ case "$1" in --apply) apply=1 ;; *) die "unknown option '$1'" ;; esac
93
+ shift
94
+ done
95
+ [ -n "$name" ] || die "usage: intelligence adapter remove <name> [--apply]"
96
+ assert_valid_target_name "$name"
97
+ require_cli_project
98
+ ensure_project_current "$IP_ROOT"
99
+ manifest="$IP_ROOT/intelligence.yaml"
100
+ content_dir="$(manifest_intelligence_dir "$manifest")"
101
+ case "$content_dir" in
102
+ ""|/*|.|..|../*|*/../*|*/..|.intelligence|.intelligence/*)
103
+ die "unsafe project.intelligence_dir '$content_dir'"
104
+ ;;
105
+ esac
106
+ repo_phys="$(cd "$IP_ROOT" && pwd -P)"
107
+ adapter_dir="$IP_ROOT/$content_dir/adapters"
108
+ [ -d "$adapter_dir" ] || die "project adapter '$name' does not exist"
109
+ adapter_phys="$(cd "$adapter_dir" 2>/dev/null && pwd -P)" || die "cannot resolve project adapter directory"
110
+ case "$adapter_phys" in "$repo_phys"|"$repo_phys"/*) ;; *) die "project adapter directory resolves outside the repository" ;; esac
111
+ file="$adapter_dir/$name.sh"
112
+ [ -f "$file" ] || die "project adapter '$name' does not exist"
113
+ [ "$(is_target_enabled "$manifest" "$name")" != "1" ] || die "adapter '$name' is enabled — disable it first"
114
+ echo "remove project adapter source: $content_dir/adapters/$name.sh"
115
+ if [ "$apply" -ne 1 ]; then
116
+ [ -t 0 ] || die "removal requires confirmation — rerun with --apply"
117
+ printf 'Remove it? [y/N] '
118
+ read -r answer
119
+ case "$answer" in y|Y|yes|YES) ;; *) echo "removal cancelled"; exit 0 ;; esac
120
+ fi
121
+ rm -f "$file"
122
+ echo "removed: $content_dir/adapters/$name.sh"
123
+ echo " generated output was kept"
124
+ }
125
+
126
+ case "$action" in
127
+ list)
128
+ [ $# -eq 1 ] || die "usage: intelligence adapter list"
129
+ adapter_list
130
+ ;;
131
+ create)
132
+ shift 2 || true
133
+ adapter_create "$@"
134
+ ;;
135
+ enable|disable)
136
+ [ -n "$name" ] && [ $# -eq 2 ] || die "usage: intelligence adapter <enable|disable> <name>"
137
+ assert_valid_target_name "$name"
138
+ require_cli_project
139
+ ensure_project_current "$IP_ROOT"
140
+ bash "$CLI_DIR/internal/target-state.sh" "$action" "$name"
141
+ if [ "$action" = "enable" ]; then
142
+ exec bash "$CLI_DIR/commands/sync.sh"
143
+ fi
144
+ ;;
145
+ remove)
146
+ [ -n "$name" ] || die "usage: intelligence adapter remove <name> [--apply]"
147
+ shift 2 || true
148
+ adapter_remove "$@"
149
+ ;;
150
+ *)
151
+ die "usage: intelligence adapter <list|create|enable|disable|remove> [name]"
152
+ ;;
153
+ esac
@@ -1,94 +1,231 @@
1
1
  #!/bin/bash
2
- # intelligence init [--targets a,b,c] [--no-sync]
2
+ # intelligence init [--targets a,b,c] [--dir name] [--bare] [--no-sync]
3
+ # [--preview | --apply] [--force]
3
4
  #
4
5
  # Set up a project: root manifest, content skeleton, .gitignore, staged
5
6
  # engine content, first sync. Targets are detected from IDE markers unless
6
- # named explicitly; `agents` and `claude` are always on (AGENTS.md is the
7
- # canonical carrier of always-on rules, Claude Code does not read it).
7
+ # named explicitly. Only `agents` is unconditional: AGENTS.md is the
8
+ # tool-neutral carrier of always-on rules; tool targets come from markers or
9
+ # --targets.
8
10
  set -euo pipefail
9
11
  source "$CLI_DIR/lib/cli-common.sh"
10
12
 
11
- targets_arg="" no_sync=0
13
+ targets_arg="" no_sync=0 content_dir="intelligence" bare=0
14
+ targets_set=0 dir_set=0 bare_set=0 preview=0 apply=0 force=0
12
15
  while [ $# -gt 0 ]; do
13
16
  case "$1" in
14
- --targets) shift; targets_arg="${1:-}" ;;
17
+ --targets) shift; targets_arg="${1:-}"; targets_set=1 ;;
18
+ --dir) shift; content_dir="${1:-}"; dir_set=1 ;;
15
19
  --no-sync) no_sync=1 ;;
20
+ --bare) bare=1; bare_set=1 ;;
21
+ --preview) preview=1 ;;
22
+ --apply) apply=1 ;;
23
+ --force) force=1 ;;
16
24
  *) die "unknown option '$1'" ;;
17
25
  esac
18
26
  shift || true
19
27
  done
28
+ [ "$preview" -eq 0 ] || [ "$apply" -eq 0 ] || die "choose either --preview or --apply"
29
+ [ "$targets_set" -eq 0 ] || [ -n "$targets_arg" ] || die "--targets needs a comma-separated adapter list"
30
+ [ -n "$content_dir" ] || die "--dir needs a directory name"
31
+ case "$content_dir" in
32
+ /*|*..*|.intelligence|.intelligence/*) die "--dir must be a plain directory inside the repo, and not the package store" ;;
33
+ esac
20
34
 
21
35
  detect_project
22
36
  case "$IP_MODE" in
23
- v2) die "already set up — manifest at $IP_ROOT/intelligence.yaml (use 'intelligence status')" ;;
24
- legacy) die "this is a vendored (v1) setup at $IP_UMBRELLA — run 'intelligence migrate' instead" ;;
37
+ cli)
38
+ [ "$targets_set" -eq 0 ] || die "--targets applies only when creating a new project"
39
+ [ "$dir_set" -eq 0 ] || die "--dir applies only when creating a new project"
40
+ [ "$bare_set" -eq 0 ] || die "--bare applies only when creating a new project"
41
+ [ "$force" -eq 0 ] || die "--force applies only when converting a legacy Intelligence Sync project"
42
+ if [ "$preview" -eq 1 ]; then
43
+ check_version_compat "$IP_ROOT/intelligence.yaml"
44
+ echo "project: Intelligence CLI at $IP_ROOT"
45
+ if project_needs_upgrade "$IP_ROOT"; then
46
+ echo " would align project lifecycle with engine $(bundled_engine_version)"
47
+ else
48
+ echo " schema/content already match engine $(bundled_engine_version)"
49
+ fi
50
+ if project_has_packages "$IP_ROOT" && [ ! -f "$IP_ROOT/intelligence.lock" ]; then
51
+ die "manifest declares packages but intelligence.lock is absent — restore the committed lock before applying"
52
+ fi
53
+ if project_store_missing "$IP_ROOT"; then
54
+ echo " would restore .intelligence/ from intelligence.lock"
55
+ else
56
+ echo " package store already present"
57
+ fi
58
+ if [ "$no_sync" -eq 1 ]; then
59
+ echo " would stop before intelligence sync"
60
+ else
61
+ echo " would run intelligence sync"
62
+ fi
63
+ exit 0
64
+ fi
65
+ if [ "$apply" -eq 1 ]; then
66
+ ensure_project_current "$IP_ROOT" --explicit
67
+ else
68
+ ensure_project_current "$IP_ROOT"
69
+ fi
70
+ restore_project_store_if_missing "$IP_ROOT"
71
+ [ "$no_sync" -eq 1 ] && exit 0
72
+ cd "$IP_ROOT"
73
+ exec bash "$CLI_DIR/commands/sync.sh"
74
+ ;;
75
+ legacy)
76
+ [ "$targets_set" -eq 0 ] || die "--targets applies only when creating a new project"
77
+ [ "$dir_set" -eq 0 ] || die "--dir applies only when creating a new project"
78
+ [ "$bare_set" -eq 0 ] || die "--bare applies only when creating a new project"
79
+ [ "$no_sync" -eq 0 ] || die "--no-sync cannot skip transactional conversion verification"
80
+ conversion_args=()
81
+ [ "$force" -eq 1 ] && conversion_args+=(--force)
82
+ if [ "$preview" -eq 1 ]; then
83
+ exec bash "$CLI_DIR/internal/convert-legacy.sh" --dry-run ${conversion_args[@]+"${conversion_args[@]}"}
84
+ fi
85
+ if [ "$apply" -eq 1 ]; then
86
+ exec bash "$CLI_DIR/internal/convert-legacy.sh" ${conversion_args[@]+"${conversion_args[@]}"}
87
+ fi
88
+ bash "$CLI_DIR/internal/convert-legacy.sh" --dry-run ${conversion_args[@]+"${conversion_args[@]}"}
89
+ [ -t 0 ] || die "legacy project conversion requires confirmation — rerun 'intelligence init --apply'"
90
+ printf 'Apply this conversion? [Y/n] '
91
+ read -r answer
92
+ case "$answer" in
93
+ ""|y|Y|yes|YES) exec bash "$CLI_DIR/internal/convert-legacy.sh" ${conversion_args[@]+"${conversion_args[@]}"} ;;
94
+ *) echo "conversion cancelled"; exit 0 ;;
95
+ esac
96
+ ;;
25
97
  esac
26
98
 
99
+ [ "$force" -eq 0 ] || die "--force applies only when converting a legacy Intelligence Sync project"
27
100
  root="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
28
101
  root="$(cd "$root" && pwd)"
102
+ assert_safe_content_dir "$root" "$content_dir"
29
103
 
30
- targets="agents claude"
104
+ # Never invent a tool the project shows no trace of: every per-tool target is
105
+ # DETECTED from repo markers or named explicitly via --targets. Only `agents`
106
+ # (AGENTS.md, the tool-neutral standard every AGENTS-reading tool shares, and
107
+ # the invariant-required carrier once any of them is on) is unconditional.
108
+ targets="agents"
31
109
  if [ -n "$targets_arg" ]; then
32
- targets="agents $(printf '%s' "$targets_arg" | tr ',' ' ')"
110
+ for target in $(printf '%s' "$targets_arg" | tr ',' ' '); do
111
+ assert_valid_target_name "$target"
112
+ if [ ! -f "$IS_ENGINE_DIR/adapters/$target.sh" ] \
113
+ && [ ! -f "$root/$content_dir/adapters/$target.sh" ]; then
114
+ die "adapter '$target' not found — create it after init with: intelligence adapter create $target"
115
+ fi
116
+ case " $targets " in *" $target "*) ;; *) targets="$targets $target" ;; esac
117
+ done
33
118
  else
119
+ if [ -d "$root/.claude" ] || [ -f "$root/CLAUDE.md" ]; then targets="$targets claude"; fi
34
120
  [ -d "$root/.cursor" ] && targets="$targets cursor"
35
121
  [ -d "$root/.codex" ] && targets="$targets codex"
36
122
  [ -d "$root/.pi" ] && targets="$targets pi"
37
123
  [ -d "$root/.opencode" ] && targets="$targets opencode"
38
124
  [ -d "$root/.github" ] && [ -d "$root/.github/instructions" ] && targets="$targets copilot"
125
+ if [ "$targets" = "agents" ]; then
126
+ echo " NOTE: no tool markers found (.claude/, CLAUDE.md, .cursor/, …) — only AGENTS.md is enabled." >&2
127
+ echo " Name your tools explicitly: intelligence init --targets claude,cursor (or edit targets: later)" >&2
128
+ fi
129
+ fi
130
+
131
+ if [ "$preview" -eq 1 ]; then
132
+ echo "project: no Intelligence setup found"
133
+ echo " would create intelligence.yaml and intelligence.lock"
134
+ if [ "$bare" -eq 1 ]; then
135
+ echo " would omit the bundled sync-content package (--bare)"
136
+ else
137
+ echo " would install the bundled sync-content package"
138
+ fi
139
+ if [ "$no_sync" -eq 1 ]; then
140
+ echo " would enable adapters:$targets and stop before sync"
141
+ else
142
+ echo " would enable adapters:$targets, then sync"
143
+ fi
144
+ exit 0
39
145
  fi
40
146
 
41
147
  manifest="$root/intelligence.yaml"
42
148
  {
43
149
  echo "# Intelligence manifest — what this project's AI tooling knows and where it goes."
44
- echo "# Managed by the intelligence CLI (https://github.com/ainova-systems/intelligence-sync)."
150
+ echo "# Managed by the intelligence CLI. Reference: https://github.com/ainova-systems/intelligence"
45
151
  echo "project:"
46
152
  echo " name: \"$(basename "$root")\""
153
+ [ "$content_dir" = "intelligence" ] || echo " intelligence_dir: \"$content_dir\""
47
154
  echo ""
48
- echo "sync_version: \"$(bundled_engine_version)\""
155
+ echo "# Schema version of this manifest. The CLI keeps it in step with its engine."
156
+ echo "schema_version: \"$(bundled_engine_version)\""
49
157
  echo ""
158
+ echo "# Where content comes from. Nothing here has to exist: a directory that is"
159
+ echo "# absent is skipped, so a project consuming only packages authors nothing of"
160
+ echo "# its own. To write your own, create the directory and sync — no config edit:"
161
+ echo "# $content_dir/rules/context.md an always-on rule; describe the project,"
162
+ echo "# its stack, and the constraints to respect"
163
+ echo "# $content_dir/agents/<name>.md a persona (frontmatter: name, description,"
164
+ echo "# tier: heavy|standard|light, access: full|readonly)"
165
+ echo "# $content_dir/skills/<name>/SKILL.md a procedure invoked as /<name>"
166
+ echo "# '.intelligence/' is CLI-managed (packages + engine content) — never edit it."
50
167
  echo "sources:"
51
168
  echo " rules:"
52
- echo " - \"intelligence/rules\""
53
- echo " - \".intelligence/engine/rules\""
169
+ echo " - \"$content_dir/rules\""
54
170
  echo " agents:"
55
- echo " - \"intelligence/agents\""
56
- echo " - \".intelligence/engine/agents\""
171
+ echo " - \"$content_dir/agents\""
57
172
  echo " skills:"
58
- echo " - \"intelligence/skills\""
59
- echo " - \".intelligence/engine/skills\""
173
+ echo " - \"$content_dir/skills\""
60
174
  echo ""
175
+ echo "# Generated output, one entry per tool. Add or drop tools freely."
61
176
  echo "targets:"
62
177
  for t in $targets; do
63
- case "$t" in
64
- agents) echo " agents: { enabled: true, output: \"AGENTS.md\" }" ;;
65
- *) echo " $t: { enabled: true, output: \".$t\" }" ;;
66
- esac
178
+ echo " $t: { enabled: true, output: \"$(default_target_output "$t")\" }"
67
179
  done
180
+ echo ""
181
+ echo "# Packages are managed with 'intelligence package add|search|list':"
182
+ echo "# intelligence package add @ainova-systems/core from the registry"
183
+ echo "# intelligence package add github:org/repo any repo with rules|agents|skills"
184
+ echo "# packages:"
185
+ echo "# \"@ainova-systems/core\":"
186
+ echo "# version: \"^0.3.0\""
187
+ echo ""
188
+ echo "# Registries are this project's TRUST LIST — the ONLY way a package name"
189
+ echo "# resolves (there is no built-in catalog and no name->github guessing;"
190
+ echo "# registry-less installs are always explicit: github:org/repo, git+<url>)."
191
+ echo "# Git repos holding an index.yaml, consulted in order; first to declare a"
192
+ echo "# name wins; sources are then pinned by url+sha in intelligence.lock."
193
+ echo "# Managed with 'intelligence registry add|remove'. Delete a line to"
194
+ echo "# distrust that catalog — including the default seeded below."
195
+ if [ "$bare" -eq 1 ] || [ -z "$DEFAULT_REGISTRY_URL" ]; then
196
+ echo "# registries:"
197
+ echo "# - \"https://github.com/acme/intelligence-registry.git\""
198
+ else
199
+ echo "registries:"
200
+ echo " - \"$DEFAULT_REGISTRY_URL\""
201
+ fi
68
202
  } > "$manifest"
69
203
 
70
- mkdir -p "$root/intelligence/rules" "$root/intelligence/agents" "$root/intelligence/skills"
71
- if [ ! -f "$root/intelligence/rules/context.md" ]; then
72
- cat > "$root/intelligence/rules/context.md" <<EOF
73
- # Project Context
74
-
75
- <!-- Always-on context every AI tool receives. Describe what this project is,
76
- its stack, and the constraints an agent must respect. -->
77
- EOF
78
- fi
79
-
80
204
  # The package store is restorable state, never committed — the npm model.
81
205
  if [ ! -f "$root/.gitignore" ] || ! grep -q '^\.intelligence/' "$root/.gitignore"; then
82
206
  {
83
207
  [ -f "$root/.gitignore" ] && [ -n "$(tail -c 1 "$root/.gitignore" 2>/dev/null)" ] && echo ""
84
- echo "# intelligence CLI package store (restored by 'intelligence install')"
208
+ echo "# intelligence CLI package store (restored automatically by 'intelligence sync')"
85
209
  echo ".intelligence/"
86
210
  } >> "$root/.gitignore"
87
211
  fi
88
212
 
89
- ensure_engine_staged "$root"
213
+ # The engine's own content (meta-skills, authoring rule, engine agents) is an
214
+ # ordinary package: auto-selected, opted out with --bare, removable later with
215
+ # 'intelligence package remove @ainova-systems/sync --force'.
216
+ if [ "$bare" -eq 0 ]; then
217
+ sync_pkg_entry "$manifest"
218
+ sync_pkg_install "$root"
219
+ fi
220
+
90
221
  echo "initialized: intelligence.yaml (targets:$(printf ' %s' $targets))"
91
- echo "next: add intelligence packages — e.g. 'intelligence add @ainova-systems/core'"
222
+ [ "$bare" -eq 1 ] && echo " bare setup: no packages — engine meta-skills not installed"
223
+ echo " add packages: intelligence package add @ainova-systems/core (browse: intelligence package search)"
224
+ echo " write your own: create $content_dir/rules/context.md, then intelligence sync"
225
+ if [ "$bare" -eq 0 ]; then
226
+ echo " tailor this repository: ask your agent to run /intelligence-learn-from-repository after sync"
227
+ fi
228
+ echo " docs: https://github.com/ainova-systems/intelligence#readme"
92
229
 
93
230
  if [ "$no_sync" -eq 0 ]; then
94
231
  cd "$root"
@@ -0,0 +1,30 @@
1
+ #!/bin/bash
2
+ # intelligence package <add|remove|list|search> ...
3
+ set -euo pipefail
4
+ source "$CLI_DIR/lib/cli-common.sh"
5
+
6
+ action="${1:-}"
7
+ [ -n "$action" ] || die "usage: intelligence package <add|remove|list|search> [args]"
8
+ shift
9
+
10
+ case "$action" in
11
+ add)
12
+ require_cli_project
13
+ ensure_project_current "$IP_ROOT"
14
+ exec bash "$CLI_DIR/internal/package-add.sh" "$@"
15
+ ;;
16
+ remove)
17
+ require_cli_project
18
+ ensure_project_current "$IP_ROOT"
19
+ exec bash "$CLI_DIR/internal/package-remove.sh" "$@"
20
+ ;;
21
+ list)
22
+ exec bash "$CLI_DIR/internal/package-list.sh" "$@"
23
+ ;;
24
+ search)
25
+ exec bash "$CLI_DIR/internal/package-search.sh" "$@"
26
+ ;;
27
+ *)
28
+ die "usage: intelligence package <add|remove|list|search> [args]"
29
+ ;;
30
+ esac
@@ -1,8 +1,10 @@
1
1
  #!/bin/bash
2
- # intelligence registry <list | add @scope <registry-repo-url> | remove @scope>
2
+ # intelligence registry <list | add <registry-repo-url> [--force] | remove <url>>
3
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.
4
+ # The registries block is a TRUST LIST: git repos holding an index.yaml, in
5
+ # trust order. Adding one is a committed, reviewable act — after it, every
6
+ # name that registry declares installs like a bundled one. No scope labels:
7
+ # names carry their own scope, and the first registry to declare a name wins.
6
8
  set -euo pipefail
7
9
  source "$CLI_DIR/lib/cli-common.sh"
8
10
 
@@ -10,42 +12,75 @@ sub="${1:-list}"
10
12
  case "$sub" in
11
13
  list)
12
14
  detect_project
13
- if [ "$IP_MODE" = "v2" ] && [ -f "$IP_ROOT/intelligence.yaml" ]; then
14
- echo "Project bindings (intelligence.yaml):"
15
+ if [ "$IP_MODE" = "cli" ] && [ -f "$IP_ROOT/intelligence.yaml" ]; then
16
+ echo "Project registries (intelligence.yaml, trust order):"
15
17
  found=0
16
- while IFS= read -r scope; do
17
- [ -n "$scope" ] || continue
18
+ while IFS= read -r url; do
19
+ [ -n "$url" ] || continue
18
20
  found=1
19
- echo " $scope -> $(qmap_value "$IP_ROOT/intelligence.yaml" "registries" "$scope")"
20
- done < <(qmap_keys "$IP_ROOT/intelligence.yaml" "registries")
21
+ index="$(_fetch_index "${url#git+}")"
22
+ if [ -n "$index" ]; then
23
+ n="$(qmap_keys "$index" "packages" | grep -c . || true)"
24
+ echo " $url — $n package(s)"
25
+ else
26
+ echo " $url — UNREACHABLE or no index.yaml"
27
+ fi
28
+ done < <(registries_list "$IP_ROOT/intelligence.yaml")
21
29
  [ "$found" -eq 0 ] && echo " (none)"
22
30
  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"
31
+ echo "Names resolve ONLY through the list above. Registry-less installs are explicit: github:org/repo, git+<url>."
32
32
  ;;
33
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"
34
+ url="${2:-}"
35
+ force=0
36
+ [ "${3:-}" = "--force" ] && force=1
37
+ [ -n "$url" ] || die "usage: intelligence registry add <registry-repo-url> [--force]"
38
+ case "$url" in
39
+ @*) die "registries are added by URL — names carry their own scope. To install a package: intelligence package add $url/<name>" ;;
40
+ esac
41
+ assert_safe_source_url "${url#git+}"
42
+ require_cli_project
43
+ ensure_project_current "$IP_ROOT"
44
+ # Fail closed: a URL that cannot produce an index is not a registry,
45
+ # and recording it would turn a typo here into a confusing failure at
46
+ # the first add. --force covers the one honest case: the registry is
47
+ # not published (or reachable) yet.
48
+ index="$(_fetch_index "${url#git+}")"
49
+ if [ -n "$index" ]; then
50
+ n="$(qmap_keys "$index" "packages" | grep -c . || true)"
51
+ echo " index.yaml reachable — $n package(s):"
52
+ qmap_keys "$index" "packages" | sed 's/^/ /'
53
+ elif [ "$force" -eq 1 ]; then
54
+ echo " WARN: no index.yaml at $url — recording anyway (--force)." >&2
55
+ else
56
+ echo "ERROR: no index.yaml found at $url — not adding it." >&2
57
+ echo " A registry is a git repo with index.yaml at its root, mapping names to sources:" >&2
58
+ echo " packages:" >&2
59
+ echo " \"@acme/backend\":" >&2
60
+ echo " url: \"https://github.com/acme/intelligence.git\"" >&2
61
+ echo " path: \"packs/backend\" # omit when the repo IS the package" >&2
62
+ echo " Format and an example: https://github.com/ainova-systems/intelligence-registry" >&2
63
+ echo " A single repository needs no registry at all: intelligence package add github:org/repo" >&2
64
+ echo " Recording it ahead of a registry that does not exist yet: --force" >&2
65
+ exit 1
66
+ fi
67
+ registries_add "$IP_ROOT/intelligence.yaml" "$url"
68
+ echo "added: $url"
40
69
  ;;
41
70
  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"
71
+ url="${2:-}"
72
+ [ -n "$url" ] || die "usage: intelligence registry remove <url>"
73
+ require_cli_project
74
+ ensure_project_current "$IP_ROOT"
75
+ registries_remove "$IP_ROOT/intelligence.yaml" "$url"
76
+ # The retired flat-map form also stored scope keys — drop one if the
77
+ # argument names it, so old manifests clean up with the old command.
78
+ case "$url" in
79
+ @*) qmap_delete_key "$IP_ROOT/intelligence.yaml" "registries" "$url" ;;
80
+ esac
81
+ echo "removed: $url"
47
82
  ;;
48
83
  *)
49
- die "usage: intelligence registry <list | add @scope <url> | remove @scope>"
84
+ die "usage: intelligence registry <list | add <url> [--force] | remove <url>>"
50
85
  ;;
51
86
  esac