@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.
@@ -31,7 +31,11 @@ sync_lock_pgid() {
31
31
  local stat
32
32
  local -a fields
33
33
  IS_PGID=""
34
- if [ -r "/proc/$$/stat" ] && IFS= read -r stat < "/proc/$$/stat"; then
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
- mkdir -p "$root/.intelligence" || die "cannot create $root/.intelligence"
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
- b1113b0658f6fddb23017e845a4ba79401caedbf
1
+ c8058f91133b86479a03d7ae950191e2d21b68a6
package/engine/VERSION CHANGED
@@ -1 +1 @@
1
- 0.19.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
- source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
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
- output="$(agents_output_path "$1")"
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
- source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
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
- source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
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
 
@@ -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
- source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
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
- source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
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
- source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
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
- source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
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"
@@ -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
- source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
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 line kind value saw_version=0
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 < <("$fn" "$output" "$manifest")
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
+ }