@ainova-systems/intelligence 0.19.0 → 0.20.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/cli/commands/registry.sh +1 -1
- package/cli/commands/source.sh +1 -1
- package/cli/commands/sync.sh +78 -6
- package/cli/intelligence +15 -2
- package/cli/internal/convert-legacy.sh +1 -1
- package/cli/internal/package-search.sh +1 -1
- package/cli/internal/package-update.sh +2 -2
- package/cli/internal/restore.sh +3 -2
- package/cli/lib/cli-common.sh +145 -33
- package/cli/lib/lockfile.sh +14 -4
- package/cli/lib/manifest.sh +147 -1
- package/cli/lib/qmap.awk +97 -32
- package/cli/lib/registry.sh +1 -1
- package/cli/lib/sync-cache.sh +596 -142
- package/cli/lib/sync-lock.sh +19 -2
- package/engine/ENGINE_SHA +1 -1
- package/engine/VERSION +1 -1
- package/engine/adapters/agents.sh +5 -2
- package/engine/adapters/antigravity.sh +3 -1
- package/engine/adapters/claude.sh +8 -2
- package/engine/adapters/codex.sh +3 -1
- package/engine/adapters/copilot.sh +8 -2
- package/engine/adapters/cursor.sh +7 -1
- package/engine/adapters/opencode.sh +7 -1
- package/engine/adapters/pi.sh +3 -1
- package/engine/lib/adapter-contract.sh +36 -4
- package/engine/lib/common.sh +665 -121
- package/engine/lib/contract.sh +5 -0
- package/engine/sync.sh +119 -28
- package/package.json +1 -1
- package/packages/sync/references/adapters.md +6 -1
- package/packages/sync/references/conventions.md +4 -1
package/cli/lib/sync-lock.sh
CHANGED
|
@@ -31,7 +31,11 @@ sync_lock_pgid() {
|
|
|
31
31
|
local stat
|
|
32
32
|
local -a fields
|
|
33
33
|
IS_PGID=""
|
|
34
|
-
|
|
34
|
+
# Cygwin and MSYS publish the group on its own; composing their stat file
|
|
35
|
+
# takes tens of milliseconds.
|
|
36
|
+
if [ -r "/proc/$$/pgid" ] && IFS= read -r IS_PGID < "/proc/$$/pgid"; then
|
|
37
|
+
:
|
|
38
|
+
elif [ -r "/proc/$$/stat" ] && IFS= read -r stat < "/proc/$$/stat"; then
|
|
35
39
|
# pid (comm) state ppid pgrp …: comm may hold spaces, so cut after it.
|
|
36
40
|
read -r -a fields <<< "${stat##*) }"
|
|
37
41
|
IS_PGID="${fields[2]:-}"
|
|
@@ -87,7 +91,8 @@ sync_lock_is_stale() {
|
|
|
87
91
|
# sync_lock_acquire <root> — take <root>/.intelligence/sync.lock or refuse.
|
|
88
92
|
sync_lock_acquire() {
|
|
89
93
|
local root="$1" lock="$1/.intelligence/sync.lock" took=0 age=""
|
|
90
|
-
|
|
94
|
+
# A process start costs tens of milliseconds on Git Bash: skip the usual case.
|
|
95
|
+
[ -d "$root/.intelligence" ] || mkdir -p "$root/.intelligence" || die "cannot create $root/.intelligence"
|
|
91
96
|
if mkdir "$lock" 2>/dev/null; then
|
|
92
97
|
took=1
|
|
93
98
|
elif mkdir "$lock.takeover" 2>/dev/null; then
|
|
@@ -146,3 +151,15 @@ sync_lock_release() {
|
|
|
146
151
|
fi
|
|
147
152
|
SYNC_LOCK_HELD=""
|
|
148
153
|
}
|
|
154
|
+
|
|
155
|
+
# project_lock_scratch <root> — set IS_LOCK_SCRATCH to a path prefix inside the
|
|
156
|
+
# lock this process holds or joined, for files that live only as long as the
|
|
157
|
+
# run: releasing the lock removes them with it, so a hot path needs no process
|
|
158
|
+
# to create or delete a temporary directory. Names carry the pid, because a
|
|
159
|
+
# joined child shares the directory with its holder.
|
|
160
|
+
# shellcheck disable=SC2034 # IS_LOCK_SCRATCH is the return channel
|
|
161
|
+
project_lock_scratch() {
|
|
162
|
+
local lock="$1/.intelligence/sync.lock"
|
|
163
|
+
[ -d "$lock" ] && [ ! -L "$lock" ] || return 1
|
|
164
|
+
IS_LOCK_SCRATCH="$lock/scratch.$$"
|
|
165
|
+
}
|
package/engine/ENGINE_SHA
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
c8058f91133b86479a03d7ae950191e2d21b68a6
|
package/engine/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.20.0
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
# Every per-file loop batches its work into one awk process (see the batched
|
|
15
15
|
# helpers in lib/common.sh): process spawns dominate sync time on Windows.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
# The engine and the CLI load the shared library before any adapter. Only a
|
|
18
|
+
# standalone source of this file loads it here: that costs a dirname process.
|
|
19
|
+
declare -F finalize_output_file >/dev/null 2>&1 || source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
|
|
18
20
|
|
|
19
21
|
# Repo-relative paths to the project's content dir and to the installed sync
|
|
20
22
|
# package, taken from the env contract — never hardcoded. The content dir is
|
|
@@ -212,7 +214,8 @@ agents_md_append_rules_list() {
|
|
|
212
214
|
# Main entry point for AGENTS.md adapter
|
|
213
215
|
adapter_contract_agents() {
|
|
214
216
|
local output
|
|
215
|
-
|
|
217
|
+
agents_output_path_var "$1"
|
|
218
|
+
output="$IS_AGENTS_OUTPUT_PATH"
|
|
216
219
|
adapter_contract_version 1
|
|
217
220
|
adapter_contract_owned "$output"
|
|
218
221
|
adapter_contract_legacy "AGENTS.md"
|
|
@@ -42,7 +42,9 @@
|
|
|
42
42
|
# Every per-file loop batches its work into one awk process (see the batched
|
|
43
43
|
# helpers in lib/common.sh): process spawns dominate sync time on Windows.
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
# The engine and the CLI load the shared library before any adapter. Only a
|
|
46
|
+
# standalone source of this file loads it here: that costs a dirname process.
|
|
47
|
+
declare -F finalize_output_file >/dev/null 2>&1 || source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
|
|
46
48
|
|
|
47
49
|
adapter_contract_antigravity() {
|
|
48
50
|
local output="${1%/}"
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
# Every per-file loop batches its work into one awk process (see the batched
|
|
11
11
|
# helpers in lib/common.sh): process spawns dominate sync time on Windows.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
# The engine and the CLI load the shared library before any adapter. Only a
|
|
14
|
+
# standalone source of this file loads it here: that costs a dirname process.
|
|
15
|
+
declare -F finalize_output_file >/dev/null 2>&1 || source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
|
|
14
16
|
|
|
15
17
|
adapter_contract_claude() {
|
|
16
18
|
local output="${1%/}"
|
|
@@ -61,6 +63,9 @@ sync_claude_skills() {
|
|
|
61
63
|
|
|
62
64
|
local src d skill_name
|
|
63
65
|
local -a skill_dirs=()
|
|
66
|
+
# The inventory decides which skills render, symlinked ones included
|
|
67
|
+
# (decision 0017); the glob keeps this adapter's own listing order.
|
|
68
|
+
skill_source_inventory "$repo_root" "$config_file"
|
|
64
69
|
load_yaml_list "$config_file" "skills"
|
|
65
70
|
local list="$IS_YAML_LIST"
|
|
66
71
|
while IFS= read -r src; do
|
|
@@ -70,6 +75,7 @@ sync_claude_skills() {
|
|
|
70
75
|
for d in "$dir"/*/; do
|
|
71
76
|
[ -d "$d" ] || continue
|
|
72
77
|
[ -f "$d/SKILL.md" ] || continue
|
|
78
|
+
skill_source_rendered "$d" || continue
|
|
73
79
|
skill_dirs+=("$d")
|
|
74
80
|
done
|
|
75
81
|
done <<< "$list"
|
|
@@ -176,7 +182,7 @@ sync_to_claude() {
|
|
|
176
182
|
# commands/, statusline.sh, etc.).
|
|
177
183
|
rm -rf "$output_dir/rules" "$output_dir/agents"
|
|
178
184
|
if [ -d "$output_dir/skills" ]; then
|
|
179
|
-
find "$output_dir/skills" -mindepth 1 -maxdepth 1 -type d -exec rm -rf {} +
|
|
185
|
+
find "$output_dir/skills" -mindepth 1 -maxdepth 1 \( -type d -o -type l \) -exec rm -rf {} +
|
|
180
186
|
fi
|
|
181
187
|
mkdir -p "$output_dir/rules" "$output_dir/skills" "$output_dir/agents"
|
|
182
188
|
|
package/engine/adapters/codex.sh
CHANGED
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
# Every per-file loop batches its work into one awk process (see the batched
|
|
17
17
|
# helpers in lib/common.sh): process spawns dominate sync time on Windows.
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
# The engine and the CLI load the shared library before any adapter. Only a
|
|
20
|
+
# standalone source of this file loads it here: that costs a dirname process.
|
|
21
|
+
declare -F finalize_output_file >/dev/null 2>&1 || source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
|
|
20
22
|
|
|
21
23
|
adapter_contract_codex() {
|
|
22
24
|
local output="${1%/}"
|
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
# Every per-file loop batches its work into one awk process (see the batched
|
|
23
23
|
# helpers in lib/common.sh): process spawns dominate sync time on Windows.
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
# The engine and the CLI load the shared library before any adapter. Only a
|
|
26
|
+
# standalone source of this file loads it here: that costs a dirname process.
|
|
27
|
+
declare -F finalize_output_file >/dev/null 2>&1 || source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
|
|
26
28
|
|
|
27
29
|
adapter_contract_copilot() {
|
|
28
30
|
local output="${1%/}" record=adapter_contract_ignore sub
|
|
@@ -166,6 +168,9 @@ sync_copilot_skills() {
|
|
|
166
168
|
|
|
167
169
|
local src d skill_name
|
|
168
170
|
local -a skill_dirs=()
|
|
171
|
+
# The inventory decides which skills render, symlinked ones included
|
|
172
|
+
# (decision 0017); the glob keeps this adapter's own listing order.
|
|
173
|
+
skill_source_inventory "$repo_root" "$config_file"
|
|
169
174
|
load_yaml_list "$config_file" "skills"
|
|
170
175
|
local list="$IS_YAML_LIST"
|
|
171
176
|
while IFS= read -r src; do
|
|
@@ -175,6 +180,7 @@ sync_copilot_skills() {
|
|
|
175
180
|
for d in "$dir"/*/; do
|
|
176
181
|
[ -d "$d" ] || continue
|
|
177
182
|
[ -f "$d/SKILL.md" ] || continue
|
|
183
|
+
skill_source_rendered "$d" || continue
|
|
178
184
|
skill_dirs+=("$d")
|
|
179
185
|
done
|
|
180
186
|
done <<< "$list"
|
|
@@ -268,7 +274,7 @@ sync_to_copilot() {
|
|
|
268
274
|
# Clean generated content (preserve workflows, etc.)
|
|
269
275
|
rm -rf "$output_dir/instructions" "$output_dir/prompts"
|
|
270
276
|
if [ -d "$output_dir/skills" ]; then
|
|
271
|
-
find "$output_dir/skills" -mindepth 1 -maxdepth 1 -type d -exec rm -rf {} +
|
|
277
|
+
find "$output_dir/skills" -mindepth 1 -maxdepth 1 \( -type d -o -type l \) -exec rm -rf {} +
|
|
272
278
|
fi
|
|
273
279
|
rm -rf "$output_dir/agents"
|
|
274
280
|
mkdir -p "$output_dir" "$output_dir/skills" "$output_dir/agents"
|
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
# Every per-file loop batches its work into one awk process (see the batched
|
|
17
17
|
# helpers in lib/common.sh): process spawns dominate sync time on Windows.
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
# The engine and the CLI load the shared library before any adapter. Only a
|
|
20
|
+
# standalone source of this file loads it here: that costs a dirname process.
|
|
21
|
+
declare -F finalize_output_file >/dev/null 2>&1 || source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
|
|
20
22
|
|
|
21
23
|
adapter_contract_cursor() {
|
|
22
24
|
local output="${1%/}"
|
|
@@ -102,6 +104,9 @@ sync_cursor_skills() {
|
|
|
102
104
|
|
|
103
105
|
local src d skill_name
|
|
104
106
|
local -a skill_dirs=()
|
|
107
|
+
# The inventory decides which skills render, symlinked ones included
|
|
108
|
+
# (decision 0017); the glob keeps this adapter's own listing order.
|
|
109
|
+
skill_source_inventory "$repo_root" "$config_file"
|
|
105
110
|
load_yaml_list "$config_file" "skills"
|
|
106
111
|
local list="$IS_YAML_LIST"
|
|
107
112
|
while IFS= read -r src; do
|
|
@@ -111,6 +116,7 @@ sync_cursor_skills() {
|
|
|
111
116
|
for d in "$dir"/*/; do
|
|
112
117
|
[ -d "$d" ] || continue
|
|
113
118
|
[ -f "$d/SKILL.md" ] || continue
|
|
119
|
+
skill_source_rendered "$d" || continue
|
|
114
120
|
skill_dirs+=("$d")
|
|
115
121
|
done
|
|
116
122
|
done <<< "$list"
|
|
@@ -27,7 +27,9 @@
|
|
|
27
27
|
# Every per-file loop batches its work into one awk process (see the batched
|
|
28
28
|
# helpers in lib/common.sh): process spawns dominate sync time on Windows.
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
# The engine and the CLI load the shared library before any adapter. Only a
|
|
31
|
+
# standalone source of this file loads it here: that costs a dirname process.
|
|
32
|
+
declare -F finalize_output_file >/dev/null 2>&1 || source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
|
|
31
33
|
|
|
32
34
|
adapter_contract_opencode() {
|
|
33
35
|
local output="${1%/}"
|
|
@@ -88,6 +90,9 @@ sync_opencode_commands() {
|
|
|
88
90
|
|
|
89
91
|
local src d skill_name
|
|
90
92
|
local -a skill_mds=()
|
|
93
|
+
# The inventory decides which skills render, symlinked ones included
|
|
94
|
+
# (decision 0017); the glob keeps this adapter's own listing order.
|
|
95
|
+
skill_source_inventory "$repo_root" "$config_file"
|
|
91
96
|
load_yaml_list "$config_file" "skills"
|
|
92
97
|
local list="$IS_YAML_LIST"
|
|
93
98
|
while IFS= read -r src; do
|
|
@@ -97,6 +102,7 @@ sync_opencode_commands() {
|
|
|
97
102
|
for d in "$dir"/*/; do
|
|
98
103
|
[ -d "$d" ] || continue
|
|
99
104
|
[ -f "$d/SKILL.md" ] || continue
|
|
105
|
+
skill_source_rendered "$d" || continue
|
|
100
106
|
skill_mds+=("${d%/}/SKILL.md")
|
|
101
107
|
done
|
|
102
108
|
done <<< "$list"
|
package/engine/adapters/pi.sh
CHANGED
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
# Every per-file loop batches its work into one awk process (see the batched
|
|
17
17
|
# helpers in lib/common.sh): process spawns dominate sync time on Windows.
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
# The engine and the CLI load the shared library before any adapter. Only a
|
|
20
|
+
# standalone source of this file loads it here: that costs a dirname process.
|
|
21
|
+
declare -F finalize_output_file >/dev/null 2>&1 || source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
|
|
20
22
|
|
|
21
23
|
adapter_contract_pi() {
|
|
22
24
|
local output="${1%/}"
|
|
@@ -122,7 +122,7 @@ adapter_contract_safe_concrete_path() {
|
|
|
122
122
|
# into the caller. Project adapters are trusted executable code during sync;
|
|
123
123
|
# the isolation here is for correctness, not a security boundary.
|
|
124
124
|
adapter_contract_records() (
|
|
125
|
-
local name="$1" file="$2" output="$3" manifest="${4:-}" fn
|
|
125
|
+
local name="$1" file="$2" output="$3" manifest="${4:-}" fn
|
|
126
126
|
# shellcheck source=/dev/null
|
|
127
127
|
source "$file"
|
|
128
128
|
printf -v fn 'adapter_contract_%s' "$name"
|
|
@@ -130,6 +130,38 @@ adapter_contract_records() (
|
|
|
130
130
|
echo "ERROR: adapter '$name' has no $fn contract" >&2
|
|
131
131
|
return 1
|
|
132
132
|
}
|
|
133
|
+
_adapter_contract_emit "$name" '' < <("$fn" "$output" "$manifest")
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
# adapter_contract_records_batch <scratch-file> <name> <file> <output>... —
|
|
137
|
+
# adapter_contract_records for several built-in adapters in one subshell, each
|
|
138
|
+
# record prefixed with "<name><TAB>". One process instead of two per adapter:
|
|
139
|
+
# on Git Bash every fork costs tens of milliseconds. <scratch-file> receives
|
|
140
|
+
# each contract's raw lines before they are checked.
|
|
141
|
+
adapter_contract_records_batch() (
|
|
142
|
+
local scratch="$1" name file output fn
|
|
143
|
+
shift
|
|
144
|
+
while [ "$#" -ge 3 ]; do
|
|
145
|
+
name="$1" file="$2" output="$3"
|
|
146
|
+
shift 3
|
|
147
|
+
# shellcheck source=/dev/null
|
|
148
|
+
source "$file"
|
|
149
|
+
printf -v fn 'adapter_contract_%s' "$name"
|
|
150
|
+
declare -F "$fn" >/dev/null 2>&1 || {
|
|
151
|
+
echo "ERROR: adapter '$name' has no $fn contract" >&2
|
|
152
|
+
return 1
|
|
153
|
+
}
|
|
154
|
+
# Like the process substitution above, a contract's own status is not
|
|
155
|
+
# its verdict: the records it printed are.
|
|
156
|
+
"$fn" "$output" > "$scratch" || true
|
|
157
|
+
_adapter_contract_emit "$name" "$name"$'\t' < "$scratch" || return 1
|
|
158
|
+
done
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
# _adapter_contract_emit <adapter-name> <prefix> — check the contract records
|
|
162
|
+
# on stdin and print each one after <prefix>; return 1 on the first bad one.
|
|
163
|
+
_adapter_contract_emit() {
|
|
164
|
+
local name="$1" prefix="$2" line kind value saw_version=0
|
|
133
165
|
while IFS= read -r line; do
|
|
134
166
|
[ -n "$line" ] || continue
|
|
135
167
|
kind="${line%%$'\t'*}"
|
|
@@ -171,10 +203,10 @@ adapter_contract_records() (
|
|
|
171
203
|
return 1
|
|
172
204
|
;;
|
|
173
205
|
esac
|
|
174
|
-
printf '%s\n' "$line"
|
|
175
|
-
done
|
|
206
|
+
printf '%s%s\n' "$prefix" "$line"
|
|
207
|
+
done
|
|
176
208
|
[ "$saw_version" -eq 1 ] || {
|
|
177
209
|
echo "ERROR: adapter '$name' contract did not declare version 1" >&2
|
|
178
210
|
return 1
|
|
179
211
|
}
|
|
180
|
-
|
|
212
|
+
}
|