@ainova-systems/intelligence 0.11.0-rc.8 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/cli/commands/adapter.sh +46 -6
- package/cli/commands/init.sh +138 -33
- package/cli/commands/package.sh +2 -2
- package/cli/commands/registry.sh +3 -3
- package/cli/commands/status.sh +4 -4
- package/cli/commands/sync.sh +76 -23
- package/cli/commands/update.sh +1 -1
- package/cli/intelligence +18 -3
- package/cli/internal/{upgrade-v2.sh → align-project.sh} +33 -7
- package/cli/internal/check.sh +49 -20
- package/cli/internal/{migrate-v1.sh → convert-legacy.sh} +36 -34
- package/cli/internal/package-add.sh +9 -14
- package/cli/internal/package-list.sh +1 -1
- package/cli/internal/package-remove.sh +1 -1
- package/cli/internal/package-search.sh +1 -1
- package/cli/internal/package-update.sh +31 -25
- package/cli/internal/restore.sh +5 -16
- package/cli/internal/target-state.sh +26 -18
- package/cli/lib/adapter-lifecycle.sh +33 -0
- package/cli/lib/cli-common.sh +28 -20
- package/cli/lib/gitignore.sh +174 -0
- package/cli/lib/manifest.sh +58 -1
- package/cli/lib/onboarding.sh +63 -0
- package/engine/ENGINE_SHA +1 -1
- package/engine/adapters/_template.sh +19 -2
- package/engine/adapters/agents.sh +14 -3
- package/engine/adapters/claude.sh +15 -0
- package/engine/adapters/codex.sh +11 -1
- package/engine/adapters/copilot.sh +11 -0
- package/engine/adapters/cursor.sh +15 -0
- package/engine/adapters/opencode.sh +11 -0
- package/engine/adapters/pi.sh +18 -5
- package/engine/lib/adapter-contract.sh +100 -0
- package/engine/lib/common.sh +5 -0
- package/engine/lib/contract.sh +2 -2
- package/engine/sync.sh +87 -25
- package/package.json +1 -1
- package/packages/sync/agents/intelligence-architect.md +2 -2
- package/packages/sync/references/adapters.md +51 -7
- package/packages/sync/references/conventions.md +57 -22
- package/packages/sync/references/onboarding-migration.md +79 -0
- package/packages/sync/skills/intelligence-install-adapter/SKILL.md +12 -5
- package/packages/sync/skills/intelligence-learn-from-context/SKILL.md +23 -4
- package/packages/sync/skills/intelligence-learn-from-repository/SKILL.md +90 -38
- package/packages/sync/skills/intelligence-review-skills/SKILL.md +1 -1
- package/packages/sync/skills/intelligence-sync/SKILL.md +1 -1
package/engine/adapters/pi.sh
CHANGED
|
@@ -15,6 +15,20 @@
|
|
|
15
15
|
|
|
16
16
|
source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
|
|
17
17
|
|
|
18
|
+
adapter_contract_pi() {
|
|
19
|
+
local output="${1%/}"
|
|
20
|
+
adapter_contract_version 1
|
|
21
|
+
adapter_contract_requires agents
|
|
22
|
+
adapter_contract_managed ".agents/skills"
|
|
23
|
+
adapter_contract_owned "$output/intelligence-sync"
|
|
24
|
+
adapter_contract_managed "$output/extensions"
|
|
25
|
+
adapter_contract_managed "$output/prompts"
|
|
26
|
+
adapter_contract_ignore ".agents/skills/"
|
|
27
|
+
adapter_contract_ignore "$output/intelligence-sync/"
|
|
28
|
+
adapter_contract_ignore "$output/extensions/intelligence-sync-rules.ts"
|
|
29
|
+
adapter_contract_ignore "$output/prompts/intelligence-agent-*.md"
|
|
30
|
+
}
|
|
31
|
+
|
|
18
32
|
pi_ts_escape() {
|
|
19
33
|
local s="$1"
|
|
20
34
|
s="${s//\\/\\\\}"
|
|
@@ -193,13 +207,12 @@ sync_pi_agents() {
|
|
|
193
207
|
|
|
194
208
|
access_note=""
|
|
195
209
|
if [ "$access" = "readonly" ]; then
|
|
196
|
-
|
|
197
|
-
|
|
210
|
+
# Bash 3.2 (the macOS system shell) misparses an apostrophe in
|
|
211
|
+
# a quoted heredoc nested inside command substitution.
|
|
212
|
+
access_note="## Access Mode
|
|
198
213
|
|
|
199
214
|
Default to read-only analysis. Do not change files or run mutating commands unless the user explicitly asks you to override this agent's normal restriction.
|
|
200
|
-
|
|
201
|
-
EOF
|
|
202
|
-
)
|
|
215
|
+
"
|
|
203
216
|
fi
|
|
204
217
|
|
|
205
218
|
{
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Declarative adapter ownership contract shared by the engine and CLI.
|
|
3
|
+
#
|
|
4
|
+
# Every adapter exposes adapter_contract_<name> <configured-output>. The
|
|
5
|
+
# function emits tab-separated records through the helpers below. Keeping the
|
|
6
|
+
# declaration beside sync_to_<name>() makes backup, rollback, git policy and
|
|
7
|
+
# lifecycle checks consume the same ownership model as the writer itself.
|
|
8
|
+
|
|
9
|
+
adapter_contract_version() { printf 'version\t%s\n' "$1"; }
|
|
10
|
+
adapter_contract_requires() { printf 'requires\t%s\n' "$1"; }
|
|
11
|
+
adapter_contract_owned() { printf 'owned\t%s\n' "$1"; }
|
|
12
|
+
adapter_contract_managed() { printf 'managed\t%s\n' "$1"; }
|
|
13
|
+
adapter_contract_legacy() { printf 'legacy\t%s\n' "$1"; }
|
|
14
|
+
adapter_contract_preserve() { printf 'preserve\t%s\n' "$1"; }
|
|
15
|
+
adapter_contract_ignore() { printf 'ignore\t%s\n' "$1"; }
|
|
16
|
+
adapter_contract_include() { printf 'include\t%s\n' "$1"; }
|
|
17
|
+
|
|
18
|
+
adapter_contract_function() {
|
|
19
|
+
printf 'adapter_contract_%s' "$1"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
# Reject records that could address anything outside the repository. Contract
|
|
23
|
+
# paths are always repo-relative; ignore/include records may contain globs.
|
|
24
|
+
adapter_contract_safe_path() {
|
|
25
|
+
local path="$1"
|
|
26
|
+
case "$path" in
|
|
27
|
+
""|/*|*\\*|[A-Za-z]:*|..|../*|*/../*|*/..|*$'\t'*|*$'\n'*) return 1 ;;
|
|
28
|
+
*) return 0 ;;
|
|
29
|
+
esac
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
adapter_contract_safe_concrete_path() {
|
|
33
|
+
adapter_contract_safe_path "$1" || return 1
|
|
34
|
+
case "$1" in
|
|
35
|
+
*'*'*|*'?'*|*'['*) return 1 ;;
|
|
36
|
+
*) return 0 ;;
|
|
37
|
+
esac
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# adapter_contract_records <adapter-name> <adapter-file> <configured-output>
|
|
41
|
+
# Source and query in a subshell so a project adapter cannot leak shell state
|
|
42
|
+
# into the caller. Project adapters are trusted executable code during sync;
|
|
43
|
+
# the isolation here is for correctness, not a security boundary.
|
|
44
|
+
adapter_contract_records() (
|
|
45
|
+
local name="$1" file="$2" output="$3" fn line kind value saw_version=0
|
|
46
|
+
# shellcheck source=/dev/null
|
|
47
|
+
source "$file"
|
|
48
|
+
fn="$(adapter_contract_function "$name")"
|
|
49
|
+
declare -F "$fn" >/dev/null 2>&1 || {
|
|
50
|
+
echo "ERROR: adapter '$name' has no $fn contract" >&2
|
|
51
|
+
return 1
|
|
52
|
+
}
|
|
53
|
+
while IFS= read -r line; do
|
|
54
|
+
[ -n "$line" ] || continue
|
|
55
|
+
kind="${line%%$'\t'*}"
|
|
56
|
+
if [ "$kind" = "$line" ]; then
|
|
57
|
+
echo "ERROR: adapter '$name' emitted a malformed contract record" >&2
|
|
58
|
+
return 1
|
|
59
|
+
fi
|
|
60
|
+
value="${line#*$'\t'}"
|
|
61
|
+
case "$kind" in
|
|
62
|
+
version)
|
|
63
|
+
[ "$value" = "1" ] || {
|
|
64
|
+
echo "ERROR: adapter '$name' uses unsupported contract version '$value'" >&2
|
|
65
|
+
return 1
|
|
66
|
+
}
|
|
67
|
+
saw_version=1
|
|
68
|
+
;;
|
|
69
|
+
requires)
|
|
70
|
+
case "$value" in
|
|
71
|
+
""|[!abcdefghijklmnopqrstuvwxyz]*|*[!abcdefghijklmnopqrstuvwxyz0123456789_]*)
|
|
72
|
+
echo "ERROR: adapter '$name' declares invalid requirement '$value'" >&2
|
|
73
|
+
return 1
|
|
74
|
+
;;
|
|
75
|
+
esac
|
|
76
|
+
;;
|
|
77
|
+
owned|managed|legacy|preserve)
|
|
78
|
+
adapter_contract_safe_concrete_path "$value" || {
|
|
79
|
+
echo "ERROR: adapter '$name' declares unsafe $kind path '$value'" >&2
|
|
80
|
+
return 1
|
|
81
|
+
}
|
|
82
|
+
;;
|
|
83
|
+
ignore|include)
|
|
84
|
+
adapter_contract_safe_path "$value" || {
|
|
85
|
+
echo "ERROR: adapter '$name' declares unsafe $kind path '$value'" >&2
|
|
86
|
+
return 1
|
|
87
|
+
}
|
|
88
|
+
;;
|
|
89
|
+
*)
|
|
90
|
+
echo "ERROR: adapter '$name' emitted unknown contract record '$kind'" >&2
|
|
91
|
+
return 1
|
|
92
|
+
;;
|
|
93
|
+
esac
|
|
94
|
+
printf '%s\n' "$line"
|
|
95
|
+
done < <("$fn" "$output")
|
|
96
|
+
[ "$saw_version" -eq 1 ] || {
|
|
97
|
+
echo "ERROR: adapter '$name' contract did not declare version 1" >&2
|
|
98
|
+
return 1
|
|
99
|
+
}
|
|
100
|
+
)
|
package/engine/lib/common.sh
CHANGED
|
@@ -806,6 +806,11 @@ warn_unsynced() {
|
|
|
806
806
|
case "$rel_dir" in
|
|
807
807
|
.claude/*|.cursor/*|.github/*|.codex/*|.agents/*|.intelligence/*|*/node_modules/*|*/vendor/*|*/dist/*) continue ;;
|
|
808
808
|
esac
|
|
809
|
+
# Initial onboarding backups are immutable migration evidence, never
|
|
810
|
+
# source directories. Suggesting one would reintroduce legacy content.
|
|
811
|
+
case "/$rel_dir/" in
|
|
812
|
+
*"/$intel_basename/_backup/"*) continue ;;
|
|
813
|
+
esac
|
|
809
814
|
|
|
810
815
|
# Skip ignore/submodule patterns.
|
|
811
816
|
local skip=false
|
package/engine/lib/contract.sh
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
# * the IS_STATUS / IS_RC_* codes every engine flow reports.
|
|
10
10
|
#
|
|
11
11
|
# Schema migrations themselves are NOT here: the CLI owns them behind
|
|
12
|
-
# `intelligence init`, and a
|
|
13
|
-
# engine before `intelligence init` converts it.
|
|
12
|
+
# `intelligence init`, and a legacy Intelligence Sync project is brought forward
|
|
13
|
+
# by its archived engine before `intelligence init` converts it.
|
|
14
14
|
|
|
15
15
|
# The applied-schema version is a managed key in the manifest.
|
|
16
16
|
#
|
package/engine/sync.sh
CHANGED
|
@@ -19,6 +19,7 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
|
19
19
|
|
|
20
20
|
source "$SCRIPT_DIR/lib/common.sh"
|
|
21
21
|
source "$SCRIPT_DIR/lib/contract.sh"
|
|
22
|
+
source "$SCRIPT_DIR/lib/adapter-contract.sh"
|
|
22
23
|
|
|
23
24
|
if [ -z "${CONFIG_FILE:-}" ] || [ ! -f "${CONFIG_FILE:-}" ]; then
|
|
24
25
|
is_status config-missing "CONFIG_FILE=${CONFIG_FILE:-}"
|
|
@@ -85,31 +86,6 @@ echo " Config: $CONFIG_FILE"
|
|
|
85
86
|
echo " Root: $REPO_ROOT"
|
|
86
87
|
echo ""
|
|
87
88
|
|
|
88
|
-
# Invariant: AGENTS.md is the canonical carrier of always-on rules for
|
|
89
|
-
# Cursor / Copilot / Codex / Pi / opencode (their adapters skip always-on
|
|
90
|
-
# rules to avoid duplication, since each tool reads AGENTS.md natively for
|
|
91
|
-
# baseline project context). If those targets are enabled, `agents` must
|
|
92
|
-
# also be enabled — otherwise always-on rules go nowhere for those tools.
|
|
93
|
-
# Skip the check when the user requested a single target via $TARGET_FILTER:
|
|
94
|
-
# they may be syncing only one IDE intentionally.
|
|
95
|
-
if [ -z "$TARGET_FILTER" ]; then
|
|
96
|
-
agents_enabled=$(is_target_enabled "$CONFIG_FILE" "agents")
|
|
97
|
-
if [ "$agents_enabled" != "1" ]; then
|
|
98
|
-
# AGENTS.md-dependent adapters: any tool whose adapter skips always-on
|
|
99
|
-
# rule emission (because the tool reads AGENTS.md natively) must be
|
|
100
|
-
# listed here. Add new adapters to this list when they ship.
|
|
101
|
-
for tool in cursor copilot codex pi opencode; do
|
|
102
|
-
if [ "$(is_target_enabled "$CONFIG_FILE" "$tool")" = "1" ]; then
|
|
103
|
-
echo "ERROR: targets.$tool is enabled but targets.agents is not." >&2
|
|
104
|
-
echo " $tool relies on AGENTS.md to deliver always-on rules — without it," >&2
|
|
105
|
-
echo " always-on rules would be invisible to $tool." >&2
|
|
106
|
-
echo " Either enable targets.agents in $CONFIG_FILE, or disable targets.$tool." >&2
|
|
107
|
-
exit 1
|
|
108
|
-
fi
|
|
109
|
-
done
|
|
110
|
-
fi
|
|
111
|
-
fi
|
|
112
|
-
|
|
113
89
|
# Lint frontmatter across all source files (rules, agents, skills).
|
|
114
90
|
# Catches issues like unquoted colons that strict YAML consumers reject.
|
|
115
91
|
for section in rules agents skills; do
|
|
@@ -167,6 +143,88 @@ for adapters_dir in "$SCRIPT_DIR/adapters" "$INTELLIGENCE_DIR/adapters"; do
|
|
|
167
143
|
done
|
|
168
144
|
done
|
|
169
145
|
|
|
146
|
+
# Validate every selected adapter contract before any output is touched, then
|
|
147
|
+
# snapshot the declared write-set. If a later adapter fails, the EXIT handler
|
|
148
|
+
# restores all earlier adapter outputs so sync is atomic from the repository's
|
|
149
|
+
# point of view.
|
|
150
|
+
SYNC_TX_DIR="$(mktemp -d -t intelligence-sync-XXXXXX)"
|
|
151
|
+
SYNC_TX_INDEX="$SYNC_TX_DIR/paths.tsv"
|
|
152
|
+
SYNC_TX_SEEN="$SYNC_TX_DIR/seen"
|
|
153
|
+
mkdir -p "$SYNC_TX_DIR/data"
|
|
154
|
+
: > "$SYNC_TX_INDEX"
|
|
155
|
+
: > "$SYNC_TX_SEEN"
|
|
156
|
+
SYNC_TX_ACTIVE=0
|
|
157
|
+
|
|
158
|
+
snapshot_sync_path() {
|
|
159
|
+
local adapter_name="$1" rel="$2" src index present=0
|
|
160
|
+
grep -Fqx -- "$rel" "$SYNC_TX_SEEN" && return 0
|
|
161
|
+
printf '%s\n' "$rel" >> "$SYNC_TX_SEEN"
|
|
162
|
+
validate_output_path "$REPO_ROOT" "$CONFIG_FILE" "$adapter_name" "$REPO_ROOT/$rel"
|
|
163
|
+
index="$(wc -l < "$SYNC_TX_INDEX" | tr -d ' ')"
|
|
164
|
+
src="$REPO_ROOT/$rel"
|
|
165
|
+
if [ -e "$src" ] || [ -L "$src" ]; then
|
|
166
|
+
cp -a "$src" "$SYNC_TX_DIR/data/$index"
|
|
167
|
+
present=1
|
|
168
|
+
fi
|
|
169
|
+
printf '%s\t%s\t%s\n' "$index" "$rel" "$present" >> "$SYNC_TX_INDEX"
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
restore_sync_snapshot() {
|
|
173
|
+
local index rel present dst
|
|
174
|
+
while IFS=$'\t' read -r index rel present; do
|
|
175
|
+
[ -n "$rel" ] || continue
|
|
176
|
+
dst="$REPO_ROOT/$rel"
|
|
177
|
+
rm -rf "$dst"
|
|
178
|
+
if [ "$present" = "1" ]; then
|
|
179
|
+
mkdir -p "$(dirname "$dst")"
|
|
180
|
+
cp -a "$SYNC_TX_DIR/data/$index" "$dst"
|
|
181
|
+
fi
|
|
182
|
+
done < "$SYNC_TX_INDEX"
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
finish_sync_transaction() {
|
|
186
|
+
local rc=$?
|
|
187
|
+
trap - EXIT INT TERM
|
|
188
|
+
set +e
|
|
189
|
+
if [ "${SYNC_TX_ACTIVE:-0}" = "1" ] && [ "$rc" -ne 0 ]; then
|
|
190
|
+
restore_sync_snapshot
|
|
191
|
+
echo "ERROR: sync failed; all adapter-owned paths were restored to their pre-sync state." >&2
|
|
192
|
+
fi
|
|
193
|
+
rm -rf "$SYNC_TX_DIR"
|
|
194
|
+
exit "$rc"
|
|
195
|
+
}
|
|
196
|
+
trap finish_sync_transaction EXIT
|
|
197
|
+
trap 'exit 130' INT TERM
|
|
198
|
+
|
|
199
|
+
preflight_idx=0
|
|
200
|
+
while [ "$preflight_idx" -lt "${#ADAPTERS[@]}" ]; do
|
|
201
|
+
adapter="${ADAPTERS[$preflight_idx]}"
|
|
202
|
+
adapter_file="${ADAPTER_FILES[$preflight_idx]}"
|
|
203
|
+
preflight_idx=$((preflight_idx + 1))
|
|
204
|
+
if [ -n "$TARGET_FILTER" ] && [ "$adapter" != "$TARGET_FILTER" ]; then
|
|
205
|
+
continue
|
|
206
|
+
fi
|
|
207
|
+
[ "$(is_target_enabled "$CONFIG_FILE" "$adapter")" = "1" ] || continue
|
|
208
|
+
output="$(get_target_output "$CONFIG_FILE" "$adapter")"
|
|
209
|
+
[ -n "$output" ] || output=".$adapter"
|
|
210
|
+
validate_output_path "$REPO_ROOT" "$CONFIG_FILE" "$adapter" "$REPO_ROOT/$output"
|
|
211
|
+
records="$(adapter_contract_records "$adapter" "$adapter_file" "$output")" || exit 1
|
|
212
|
+
while IFS=$'\t' read -r kind value; do
|
|
213
|
+
[ "$kind" = "requires" ] || continue
|
|
214
|
+
if [ "$(is_target_enabled "$CONFIG_FILE" "$value")" != "1" ]; then
|
|
215
|
+
echo "ERROR: targets.$adapter requires enabled target '$value'." >&2
|
|
216
|
+
echo " Enable it first: intelligence adapter enable $value" >&2
|
|
217
|
+
exit 1
|
|
218
|
+
fi
|
|
219
|
+
done <<< "$records"
|
|
220
|
+
while IFS=$'\t' read -r kind value; do
|
|
221
|
+
case "$kind" in
|
|
222
|
+
owned|managed) snapshot_sync_path "$adapter" "$value" ;;
|
|
223
|
+
esac
|
|
224
|
+
done <<< "$records"
|
|
225
|
+
done
|
|
226
|
+
SYNC_TX_ACTIVE=1
|
|
227
|
+
|
|
170
228
|
synced=0
|
|
171
229
|
adapter_count=${#ADAPTERS[@]}
|
|
172
230
|
adapter_idx=0
|
|
@@ -224,6 +282,10 @@ if [ $synced -eq 0 ]; then
|
|
|
224
282
|
exit 1
|
|
225
283
|
fi
|
|
226
284
|
|
|
285
|
+
SYNC_TX_ACTIVE=0
|
|
286
|
+
rm -rf "$SYNC_TX_DIR"
|
|
287
|
+
trap - EXIT INT TERM
|
|
288
|
+
|
|
227
289
|
# Warn about unsynced directories
|
|
228
290
|
warn_unsynced "$REPO_ROOT" "$CONFIG_FILE"
|
|
229
291
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainova-systems/intelligence",
|
|
3
|
-
"version": "0.11.0
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Build, version and distribute AI agent intelligence across your organization — one CLI, versioned Intelligence Packages, and a sync engine for Claude Code, Cursor, Copilot, Codex, Pi and OpenCode.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"intelligence": "bin/intelligence.js"
|
|
@@ -46,8 +46,8 @@ The per-artifact checks are procedure, so they live in the meta-skills rather th
|
|
|
46
46
|
| `intelligence-add-rule` / `intelligence-add-agent` / `intelligence-add-skill` | author one artifact |
|
|
47
47
|
| `intelligence-extract-skill` | turn an observed workflow into a skill |
|
|
48
48
|
| `intelligence-review-skills` | audit the layer for duplication, drift, size, hardcoded paths |
|
|
49
|
-
| `intelligence-learn-from-repository` |
|
|
50
|
-
| `intelligence-learn-from-context` | fold
|
|
49
|
+
| `intelligence-learn-from-repository` | recover and complete first-time repository onboarding |
|
|
50
|
+
| `intelligence-learn-from-context` | fold one later session lesson into an established layer |
|
|
51
51
|
| `intelligence-sync` | project the source to every tool channel |
|
|
52
52
|
| `intelligence-update` | interpret and apply the CLI's unified update plan |
|
|
53
53
|
| `intelligence-install-adapter` / `intelligence-uninstall-adapter` | research and manage a tool adapter |
|
|
@@ -42,14 +42,25 @@ To stop syncing a target:
|
|
|
42
42
|
intelligence adapter disable mytool
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
Disabling changes only target state. Generated output is deliberately kept
|
|
45
|
+
Disabling changes only target state. Generated output is deliberately kept so disabling is reversible; the adapter contract identifies its paths for review. A disabled project adapter can be deleted with `intelligence adapter remove mytool`; removal prompts by default, accepts `--apply` for explicit non-interactive use, and also keeps generated output. Built-in adapter source cannot be removed. Use `intelligence adapter list` to inspect source, state and output.
|
|
46
46
|
|
|
47
|
-
## Required
|
|
47
|
+
## Required interface
|
|
48
48
|
|
|
49
|
-
The file name and function
|
|
49
|
+
The file name, contract function and sync function form the adapter's identity:
|
|
50
50
|
|
|
51
51
|
```bash
|
|
52
52
|
# <content-dir>/adapters/mytool.sh
|
|
53
|
+
adapter_contract_mytool() {
|
|
54
|
+
local output="${1%/}"
|
|
55
|
+
adapter_contract_version 1
|
|
56
|
+
adapter_contract_owned "$output/rules"
|
|
57
|
+
adapter_contract_owned "$output/agents"
|
|
58
|
+
adapter_contract_owned "$output/skills"
|
|
59
|
+
adapter_contract_ignore "$output/rules/"
|
|
60
|
+
adapter_contract_ignore "$output/agents/"
|
|
61
|
+
adapter_contract_ignore "$output/skills/"
|
|
62
|
+
}
|
|
63
|
+
|
|
53
64
|
sync_to_mytool() {
|
|
54
65
|
local repo_root="$1"
|
|
55
66
|
local config_file="$2"
|
|
@@ -59,6 +70,30 @@ sync_to_mytool() {
|
|
|
59
70
|
}
|
|
60
71
|
```
|
|
61
72
|
|
|
73
|
+
The contract accepts the configured repo-relative output path and emits only
|
|
74
|
+
records through these helpers:
|
|
75
|
+
|
|
76
|
+
| Record | Meaning |
|
|
77
|
+
|---|---|
|
|
78
|
+
| `adapter_contract_version 1` | Required interface version |
|
|
79
|
+
| `adapter_contract_requires <name>` | Another target that must be enabled for a full sync |
|
|
80
|
+
| `adapter_contract_owned <path>` | Path exclusively regenerated by this adapter |
|
|
81
|
+
| `adapter_contract_managed <path>` | Shared or marker-managed path modified by this adapter |
|
|
82
|
+
| `adapter_contract_legacy <path>` | Pre-Intelligence input preserved in the initial backup |
|
|
83
|
+
| `adapter_contract_preserve <path>` | Settings or state preserved in place and included in the initial backup |
|
|
84
|
+
| `adapter_contract_ignore <pattern>` | Exact `.gitignore` pattern managed on enable/init |
|
|
85
|
+
| `adapter_contract_include <pattern>` | Exact negated `.gitignore` pattern managed on enable/init |
|
|
86
|
+
|
|
87
|
+
All paths are repository-relative. The CLI refuses missing, malformed, unsafe,
|
|
88
|
+
or unsupported contracts before enabling or syncing an adapter. `owned` and
|
|
89
|
+
`managed` paths form the transactional write-set: if any adapter fails, the
|
|
90
|
+
engine restores every selected adapter path to its pre-sync state.
|
|
91
|
+
|
|
92
|
+
For an existing `.vscodeignore`, `.npmignore`, or `.dockerignore`, enable/init
|
|
93
|
+
also excludes the configured adapter output plus its `owned`, `managed`, and
|
|
94
|
+
`legacy` paths from published or build artifacts. This packaging policy is
|
|
95
|
+
separate from the narrower Git policy expressed by `ignore` and `include`.
|
|
96
|
+
|
|
62
97
|
The engine calls:
|
|
63
98
|
|
|
64
99
|
```text
|
|
@@ -162,7 +197,7 @@ Built-ins currently emit Claude and Cursor Markdown, Copilot `.agent.md`, Codex
|
|
|
162
197
|
|
|
163
198
|
Content shipped in `@ainova-systems/sync` cannot assume the project's content-directory name or package-store location. It uses these tokens:
|
|
164
199
|
|
|
165
|
-
| Token |
|
|
200
|
+
| Token | Expansion |
|
|
166
201
|
|---|---|
|
|
167
202
|
| `<content-dir>` | Project content directory, usually `intelligence` |
|
|
168
203
|
| `<module>` | Installed sync package, usually `.intelligence/packages/@ainova-systems/sync` |
|
|
@@ -177,8 +212,8 @@ Call `finalize_output_file` on every text file after transformation. It expands
|
|
|
177
212
|
|
|
178
213
|
Adapters regenerate output, so cleanup is part of their public contract.
|
|
179
214
|
|
|
180
|
-
1. Delete only paths
|
|
181
|
-
2.
|
|
215
|
+
1. Delete only paths declared `owned`. Preserve sibling settings, commands, extensions, workflows and hand-authored files.
|
|
216
|
+
2. Keep `adapter_contract_<name>()` exactly aligned with every path `sync_to_<name>()` writes or deletes.
|
|
182
217
|
3. Use marker-based cleanup when generated and hand-authored files share a directory. The OpenCode adapter is the reference implementation.
|
|
183
218
|
4. Use `sync_open_skill_dirs` for `.agents/skills/`; multiple adapters share it.
|
|
184
219
|
5. Write only beneath the supplied `output_dir`, except for an explicitly shared standard path handled by a shared helper.
|
|
@@ -211,6 +246,13 @@ sync_mytool_rules() {
|
|
|
211
246
|
done < <(read_yaml_list "$config_file" "rules")
|
|
212
247
|
}
|
|
213
248
|
|
|
249
|
+
adapter_contract_mytool() {
|
|
250
|
+
local output="${1%/}"
|
|
251
|
+
adapter_contract_version 1
|
|
252
|
+
adapter_contract_owned "$output/rules"
|
|
253
|
+
adapter_contract_ignore "$output/rules/"
|
|
254
|
+
}
|
|
255
|
+
|
|
214
256
|
sync_to_mytool() {
|
|
215
257
|
local repo_root="$1" config_file="$2" output_dir="$3"
|
|
216
258
|
|
|
@@ -221,7 +263,7 @@ sync_to_mytool() {
|
|
|
221
263
|
|
|
222
264
|
## Testing
|
|
223
265
|
|
|
224
|
-
Use a disposable Git repository with
|
|
266
|
+
Use a disposable Git repository with an Intelligence manifest and representative always-on/scoped rules, agents, skills and bundled skill resources.
|
|
225
267
|
|
|
226
268
|
```bash
|
|
227
269
|
intelligence sync mytool
|
|
@@ -234,6 +276,8 @@ Verify:
|
|
|
234
276
|
- skill resources are present;
|
|
235
277
|
- no literal layout tokens remain;
|
|
236
278
|
- hand-authored siblings under the tool root survive;
|
|
279
|
+
- a deliberately failing later adapter restores all earlier output byte-for-byte;
|
|
280
|
+
- `intelligence status --check` accepts the contract and its Git policy;
|
|
237
281
|
- output paths cannot overlap sources or escape the repository;
|
|
238
282
|
- a second sync produces no Git diff.
|
|
239
283
|
|
|
@@ -18,7 +18,7 @@ Use these tests:
|
|
|
18
18
|
|
|
19
19
|
Do not bury conventions in agents, workflows in rules or reusable expertise in skills. Each misplaced concern either fails to load when needed or consumes context when it is not needed.
|
|
20
20
|
|
|
21
|
-
##
|
|
21
|
+
## Intelligence project structure
|
|
22
22
|
|
|
23
23
|
```text
|
|
24
24
|
project/
|
|
@@ -92,11 +92,11 @@ intelligence package add github:acme/backend-intelligence
|
|
|
92
92
|
intelligence package add 'git+https://git.example.com/acme/backend.git@main#package'
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
-
Registries are an ordered trust list and the only resolver for a package name. There is no built-in catalog and no `@org/name` → GitHub guessing. An explicit `github:` or `git+` spec bypasses registry lookup
|
|
95
|
+
Registries are an ordered trust list and the only resolver for a package name. There is no built-in catalog and no `@org/name` → GitHub guessing. An explicit `github:` or `git+` spec bypasses registry lookup. In every case the manifest stores only requested `version` or `ref`; resolved URL/path and SHA live in the lock.
|
|
96
96
|
|
|
97
97
|
Stable Git tags provide package versions. Semver ranges select the highest matching stable tag; a `ref:` pin names a branch or commit and does not move during `intelligence update`. One package name has one version per project.
|
|
98
98
|
|
|
99
|
-
Commit `intelligence.lock`. It records requested versions, source URLs and paths, resolved refs and commit SHAs. After cloning, `intelligence sync` restores a missing store strictly from that lock before rendering; manifest/lock or SHA drift is refused.
|
|
99
|
+
Commit `intelligence.lock`. It records requested versions, source URLs and paths, resolved refs and commit SHAs. After cloning, `intelligence sync` restores a missing store strictly from that lock before rendering; manifest/lock or SHA drift is refused. Re-run `package add` when deliberately changing a source.
|
|
100
100
|
|
|
101
101
|
`@ainova-systems/sync` is ordinary package content exact-pinned to the bundled engine version. `intelligence init` installs it unless `--bare` is used. Lifecycle preflight keeps that pin and `schema_version` aligned with the installed CLI; package-range updates never move it independently.
|
|
102
102
|
|
|
@@ -104,7 +104,7 @@ Commit `intelligence.lock`. It records requested versions, source URLs and paths
|
|
|
104
104
|
|
|
105
105
|
Package-owned artifacts cannot assume the project's content-directory name or their installed package path. They use tokens expanded by every adapter through `finalize_output_file`:
|
|
106
106
|
|
|
107
|
-
| Token |
|
|
107
|
+
| Token | Expansion |
|
|
108
108
|
|---|---|
|
|
109
109
|
| `<content-dir>` | Repo-relative content directory, usually `intelligence` |
|
|
110
110
|
| `<module>` | Installed sync package, usually `.intelligence/packages/@ainova-systems/sync` |
|
|
@@ -283,7 +283,7 @@ Size limits are backstops, not quotas:
|
|
|
283
283
|
|
|
284
284
|
Every line enters a finite context budget. Prefer subtraction, consolidation and precise scope over exhaustive prose.
|
|
285
285
|
|
|
286
|
-
## Generated output
|
|
286
|
+
## Generated output and version control
|
|
287
287
|
|
|
288
288
|
| Target | Rules | Skills | Agents |
|
|
289
289
|
|---|---|---|---|
|
|
@@ -297,22 +297,24 @@ Every line enters a finite context budget. Prefer subtraction, consolidation and
|
|
|
297
297
|
|
|
298
298
|
`AGENTS.md` is regenerated by the `agents` adapter. Its optional static header is `targets.agents.header` in `intelligence.yaml`; generated rule, agent and skill sections follow it. Commit `AGENTS.md` when it is the project's shared canonical context.
|
|
299
299
|
|
|
300
|
-
|
|
300
|
+
By default, commit the manifest, lock, project-owned content, `AGENTS.md`, and shared `.github/` output. Ignore the restorable package store and tool output owned by enabled adapters. `intelligence init` and `intelligence adapter enable` add these patterns without ignoring shared tool roots or settings:
|
|
301
301
|
|
|
302
302
|
```gitignore
|
|
303
303
|
# CLI-managed package store
|
|
304
304
|
.intelligence/
|
|
305
305
|
|
|
306
|
-
#
|
|
307
|
-
.
|
|
308
|
-
.
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
.
|
|
312
|
-
.
|
|
306
|
+
# Local root instructions migrate into project rules; local preferences stay ignored
|
|
307
|
+
CLAUDE.md
|
|
308
|
+
.cursorrules
|
|
309
|
+
|
|
310
|
+
# Generated Claude and Cursor content; shared settings remain trackable
|
|
311
|
+
.claude/*
|
|
312
|
+
!.claude/settings.json
|
|
313
|
+
.cursor/*
|
|
314
|
+
!.cursor/settings.json
|
|
313
315
|
|
|
314
316
|
# Generated open-standard and Codex content
|
|
315
|
-
.agents/
|
|
317
|
+
.agents/skills/
|
|
316
318
|
.codex/agents/
|
|
317
319
|
|
|
318
320
|
# Generated Pi content
|
|
@@ -320,12 +322,45 @@ Generated IDE output may be gitignored when every collaborator can reproduce it
|
|
|
320
322
|
.pi/extensions/intelligence-sync-rules.ts
|
|
321
323
|
.pi/prompts/intelligence-agent-*.md
|
|
322
324
|
|
|
323
|
-
# Generated OpenCode agents.
|
|
324
|
-
#
|
|
325
|
+
# Generated OpenCode agents. Commands share a directory with hand-authored
|
|
326
|
+
# files, so they remain tracked unless the project chooses exact file ignores.
|
|
325
327
|
.opencode/agents/
|
|
326
328
|
```
|
|
327
329
|
|
|
328
|
-
Copilot output lives under `.github
|
|
330
|
+
Copilot output lives under `.github/` and is committed with other repository-level GitHub configuration. Do not ignore `.github/` wholesale. `AGENTS.md` is also committed so every clone has the shared tool-neutral entry point before sync.
|
|
331
|
+
|
|
332
|
+
Git tracking and release packaging are separate policies. When a project
|
|
333
|
+
already has `.vscodeignore`, `.npmignore`, or `.dockerignore`, the CLI appends a
|
|
334
|
+
small idempotent block excluding the package store, `intelligence.yaml`,
|
|
335
|
+
`intelligence.lock`, the complete project content directory, and enabled
|
|
336
|
+
adapter output. Existing entries remain untouched and absent secondary ignore
|
|
337
|
+
files are not created.
|
|
338
|
+
|
|
339
|
+
An ignore rule does not untrack a file already in Git. After init or adapter
|
|
340
|
+
enable, the CLI reports each affected tracked path with an exact
|
|
341
|
+
`git rm --cached -- '<path>'` command; this preserves the local file while
|
|
342
|
+
removing it from the index.
|
|
343
|
+
|
|
344
|
+
Before release, inspect the packager's actual file list. An npm `files`
|
|
345
|
+
allowlist can force inclusion despite `.npmignore`, and a Dockerfile-specific
|
|
346
|
+
`<name>.Dockerfile.dockerignore` takes precedence over the root
|
|
347
|
+
`.dockerignore`. Use the relevant pack/list command as the final proof rather
|
|
348
|
+
than inferring contents from Git status.
|
|
349
|
+
|
|
350
|
+
`AGENTS.md` is the only shared root instruction entry point. During onboarding,
|
|
351
|
+
move useful repository guidance from legacy root files such as `.cursorrules`
|
|
352
|
+
and instruction-bearing `CLAUDE.md` into project-owned rules, verify the
|
|
353
|
+
generated tool output, then remove the legacy file. Keep a root tool-specific
|
|
354
|
+
file only when it contains genuinely local configuration that an adapter cannot
|
|
355
|
+
represent; keep that exception gitignored rather than maintaining a second
|
|
356
|
+
committed instruction source.
|
|
357
|
+
|
|
358
|
+
Before the first render, `intelligence init` preserves existing AI prompt paths
|
|
359
|
+
under `<content-dir>/_backup/`. Its `manifest.tsv` labels the snapshot
|
|
360
|
+
`initial-onboarding` and lists exact original paths. The context-learning skill
|
|
361
|
+
first recovers or verifies CLI setup, then routes that state through
|
|
362
|
+
`onboarding-migration.md` and repository learning. The backup remains until the
|
|
363
|
+
user approves removal.
|
|
329
364
|
|
|
330
365
|
## Project-owned adapters
|
|
331
366
|
|
|
@@ -337,7 +372,7 @@ intelligence adapter create mytool
|
|
|
337
372
|
intelligence adapter enable mytool
|
|
338
373
|
```
|
|
339
374
|
|
|
340
|
-
Project adapters survive CLI upgrades and may override a built-in by name. `intelligence adapter enable mytool` runs a full sync so shared context stays current. `intelligence adapter disable mytool` keeps generated output for explicit
|
|
375
|
+
Project adapters survive CLI upgrades and may override a built-in by name. Each adapter declares a versioned ownership contract beside its sync function; backup, rollback, dependencies and Git policy all consume it. `intelligence adapter enable mytool` runs a full transactional sync so shared context stays current. `intelligence adapter disable mytool` keeps generated output for explicit cleanup; a disabled project adapter can then be deleted with `intelligence adapter remove mytool`. See `adapters.md` for the interface and safety contract.
|
|
341
376
|
|
|
342
377
|
## Schema and command boundaries
|
|
343
378
|
|
|
@@ -345,14 +380,14 @@ The permanent applied-schema key is the top-level scalar `schema_version` in `in
|
|
|
345
380
|
|
|
346
381
|
The public lifecycle is deliberately compact:
|
|
347
382
|
|
|
348
|
-
- `intelligence init [--preview|--apply]` is universal: it creates a new setup, aligns an existing
|
|
349
|
-
- `intelligence sync [adapter]` first aligns an existing
|
|
383
|
+
- `intelligence init [--preview|--apply]` is universal: it creates a new setup, aligns an existing Intelligence project, or plans/applies conversion of an eligible legacy Intelligence Sync project.
|
|
384
|
+
- `intelligence sync [adapter] [--compact]` first aligns an existing Intelligence project with the installed CLI, restores a missing store strictly from `intelligence.lock`, then renders. Compact mode shows only final status on success and all diagnostics on failure. In CI it refuses an alignment that would change tracked files and points to a local `intelligence init --apply` plus review/commit.
|
|
350
385
|
- `intelligence update [@scope/name] [--preview|--apply]` is the only update surface. It prints the CLI/project/package plan; default mode prompts, `--preview` never writes, and `--apply` does not prompt. It never moves `ref:` pins.
|
|
351
386
|
- `intelligence package add|remove|list|search` owns package inventory.
|
|
352
387
|
- `intelligence adapter list|create|enable|disable|remove` owns adapter inventory and target state.
|
|
353
388
|
- `intelligence status [--check]` reports state; `--check` runs deep consistency checks.
|
|
354
389
|
|
|
355
|
-
Implement
|
|
390
|
+
Implement Intelligence schema changes as idempotent structural checks. Stage and verify replacement state before deleting or replacing prior state. A stale engine refuses a manifest whose `schema_version` is newer; normal project entry points close a behind-project gap through lifecycle preflight.
|
|
356
391
|
|
|
357
392
|
Breaking changelog entries use a `### Breaking` checklist of verifiable post-conditions. The update skill reads every release across the version gap, chooses the package/CLI/project command sequence and verifies those conditions after the deterministic command completes.
|
|
358
393
|
|
|
@@ -382,4 +417,4 @@ Callers capture the real code with `command || rc=$?`. Do not use `if ! command;
|
|
|
382
417
|
| `<content-dir>/{rules,agents,skills,adapters}/` | Project source of truth | Tracked |
|
|
383
418
|
| `.intelligence/` | Restorable package store | Ignored |
|
|
384
419
|
| `AGENTS.md` | Generated canonical project context | Normally tracked |
|
|
385
|
-
| Tool output directories | Generated native content |
|
|
420
|
+
| Tool output directories | Generated native content | Built-in adapter-owned paths ignored; shared settings tracked |
|