@ainova-systems/intelligence 0.20.0 → 0.21.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/init.sh +2 -1
- package/cli/internal/check.sh +39 -0
- package/cli/lib/gitignore.sh +19 -2
- package/engine/ENGINE_SHA +1 -1
- package/engine/VERSION +1 -1
- package/engine/adapters/_template.sh +32 -8
- package/engine/adapters/agents.sh +42 -50
- package/engine/adapters/antigravity.sh +68 -52
- package/engine/adapters/claude.sh +38 -59
- package/engine/adapters/codex.sh +74 -15
- package/engine/adapters/copilot.sh +50 -67
- package/engine/adapters/cursor.sh +85 -81
- package/engine/adapters/opencode.sh +20 -35
- package/engine/adapters/pi.sh +137 -41
- package/engine/lib/common.sh +735 -56
- package/engine/sync.sh +49 -33
- package/package.json +1 -1
- package/packages/sync/references/adapters.md +44 -39
- package/packages/sync/references/conventions.md +57 -11
- package/packages/sync/references/onboarding-migration.md +4 -4
- package/packages/sync/rules/intelligence-authoring.md +2 -2
- package/packages/sync/skills/intelligence-learn-from-repository/SKILL.md +7 -5
- package/packages/sync/skills/intelligence-review-context/references/audit-checks.md +1 -1
- package/packages/sync/skills/intelligence-update-context/references/rules.md +5 -0
|
@@ -35,23 +35,15 @@ sync_claude_rules() {
|
|
|
35
35
|
local config_file="$2"
|
|
36
36
|
local output_dir="$3"
|
|
37
37
|
|
|
38
|
-
local
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
[ -f "$f" ] || continue
|
|
48
|
-
files+=("$f")
|
|
49
|
-
done
|
|
50
|
-
done <<< "$list"
|
|
51
|
-
[ "${#files[@]}" -gt 0 ] || return 0
|
|
52
|
-
finalize_copy_files "$output_dir/rules" "${files[@]}"
|
|
53
|
-
for f in "${files[@]}"; do
|
|
54
|
-
echo " rule: ${f##*/}"
|
|
38
|
+
local name
|
|
39
|
+
# Every source reaches this adapter through the source catalog (decision
|
|
40
|
+
# 0021): rendered names, overrides and local artifacts are settled there.
|
|
41
|
+
output_rel_var "$repo_root" "$output_dir"
|
|
42
|
+
source_artifacts_var "$repo_root" "$config_file" rules claude "$IS_OUTPUT_REL/rules/{}.md"
|
|
43
|
+
[ "${#IS_SOURCE_FILES[@]}" -gt 0 ] || return 0
|
|
44
|
+
finalize_copy_named "$output_dir/rules" "$IS_SOURCE_NAME_MAP" "${IS_SOURCE_FILES[@]}"
|
|
45
|
+
for name in "${IS_SOURCE_NAMES[@]}"; do
|
|
46
|
+
echo " rule: $name.md"
|
|
55
47
|
done
|
|
56
48
|
}
|
|
57
49
|
|
|
@@ -61,29 +53,19 @@ sync_claude_skills() {
|
|
|
61
53
|
local config_file="$2"
|
|
62
54
|
local output_dir="$3"
|
|
63
55
|
|
|
64
|
-
local
|
|
56
|
+
local i name
|
|
65
57
|
local -a skill_dirs=()
|
|
66
|
-
# The
|
|
67
|
-
# (decision 0017)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
[ -f "$d/SKILL.md" ] || continue
|
|
78
|
-
skill_source_rendered "$d" || continue
|
|
79
|
-
skill_dirs+=("$d")
|
|
80
|
-
done
|
|
81
|
-
done <<< "$list"
|
|
82
|
-
[ "${#skill_dirs[@]}" -gt 0 ] || return 0
|
|
83
|
-
copy_skill_bundle_dirs_for claude "$output_dir/skills" "${skill_dirs[@]}"
|
|
84
|
-
for d in "${skill_dirs[@]}"; do
|
|
85
|
-
skill_name="${d%/}"
|
|
86
|
-
echo " skill: ${skill_name##*/}"
|
|
58
|
+
# The catalog's skills are the ones the inventory renders, symlinked ones
|
|
59
|
+
# included (decision 0017).
|
|
60
|
+
output_rel_var "$repo_root" "$output_dir"
|
|
61
|
+
source_artifacts_var "$repo_root" "$config_file" skills claude "$IS_OUTPUT_REL/skills/{}"
|
|
62
|
+
[ "${#IS_SOURCE_FILES[@]}" -gt 0 ] || return 0
|
|
63
|
+
for ((i = 0; i < ${#IS_SOURCE_FILES[@]}; i++)); do
|
|
64
|
+
skill_dirs+=("${IS_SOURCE_FILES[i]%/SKILL.md}/")
|
|
65
|
+
done
|
|
66
|
+
copy_skill_bundle_dirs_named claude "$output_dir/skills" "$IS_SOURCE_NAME_MAP" "${skill_dirs[@]}"
|
|
67
|
+
for name in "${IS_SOURCE_NAMES[@]}"; do
|
|
68
|
+
echo " skill: $name"
|
|
87
69
|
done
|
|
88
70
|
}
|
|
89
71
|
|
|
@@ -94,32 +76,27 @@ sync_claude_agents() {
|
|
|
94
76
|
local config_file="$2"
|
|
95
77
|
local output_dir="$3"
|
|
96
78
|
|
|
97
|
-
local
|
|
98
|
-
local -a files=()
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
for f in "$dir"/*.md; do
|
|
106
|
-
[ -f "$f" ] || continue
|
|
107
|
-
files+=("$f")
|
|
108
|
-
done
|
|
109
|
-
done <<< "$list"
|
|
110
|
-
[ "${#files[@]}" -gt 0 ] || return 0
|
|
79
|
+
local i
|
|
80
|
+
local -a files=() names=()
|
|
81
|
+
output_rel_var "$repo_root" "$output_dir"
|
|
82
|
+
source_artifacts_var "$repo_root" "$config_file" agents claude "$IS_OUTPUT_REL/agents/{}.md"
|
|
83
|
+
[ "${#IS_SOURCE_FILES[@]}" -gt 0 ] || return 0
|
|
84
|
+
files=("${IS_SOURCE_FILES[@]}")
|
|
85
|
+
names=("${IS_SOURCE_NAMES[@]}")
|
|
86
|
+
local name_map="$IS_SOURCE_NAME_MAP"
|
|
111
87
|
|
|
112
88
|
load_model_tiers "$config_file" "claude"
|
|
113
89
|
|
|
114
90
|
local path tier access effort spec="" report=""
|
|
91
|
+
i=0
|
|
115
92
|
while IFS=$'\x1f' read -r path tier access effort; do
|
|
116
|
-
[ -n "$path" ] || continue
|
|
117
93
|
resolve_model_var "$tier"
|
|
118
94
|
map_effort_var claude "$effort"
|
|
119
95
|
map_access_to_claude_tools_var "$access"
|
|
120
96
|
map_access_to_claude_disallowed_var "$access"
|
|
121
97
|
spec+="$path"$'\x1f'"$IS_MODEL"$'\x1f'"$IS_CLAUDE_TOOLS"$'\x1f'"$IS_CLAUDE_DISALLOWED"$'\x1f'"$IS_EFFORT"$'\n'
|
|
122
|
-
report+=" agent: ${
|
|
98
|
+
report+=" agent: ${names[i]}.md (tier=$tier -> model=$IS_MODEL, access=$access)"$'\n'
|
|
99
|
+
i=$((i + 1))
|
|
123
100
|
done < <(frontmatter_index "tier,access,effort" "${files[@]}")
|
|
124
101
|
|
|
125
102
|
# The transform used to run per file with the values injected via -v;
|
|
@@ -128,7 +105,7 @@ sync_claude_agents() {
|
|
|
128
105
|
# becomes Claude's level in place, or goes when there is none; a later
|
|
129
106
|
# one goes too, since frontmatter_index read only the first.
|
|
130
107
|
is_fin_awk_vars
|
|
131
|
-
IS_MAP_SPEC="$spec" awk "${IS_FIN_V[@]}" -v dst="$output_dir/agents" "$IS_AWK_LIB"'
|
|
108
|
+
IS_NAME_MAP="$name_map" IS_MAP_SPEC="$spec" awk "${IS_FIN_V[@]}" -v dst="$output_dir/agents" "$IS_AWK_LIB"'
|
|
132
109
|
BEGIN {
|
|
133
110
|
US = sprintf("%c", 31)
|
|
134
111
|
n = split(ENVIRON["IS_MAP_SPEC"], recs, "\n")
|
|
@@ -140,16 +117,18 @@ sync_claude_agents() {
|
|
|
140
117
|
}
|
|
141
118
|
FNR == 1 {
|
|
142
119
|
if (out != "") close(out)
|
|
143
|
-
out = dst "/"
|
|
120
|
+
out = dst "/" art_file(FILENAME, ".md")
|
|
144
121
|
count = 0
|
|
145
122
|
fm = 0
|
|
146
123
|
effort_seen = 0
|
|
124
|
+
tgt_reset()
|
|
147
125
|
}
|
|
148
126
|
/^tier:/ { next }
|
|
149
127
|
/^access:/ { next }
|
|
150
128
|
{ sub(/\r$/, "") }
|
|
151
129
|
FNR == 1 && $0 == "---" { fm = 1 }
|
|
152
130
|
/^---$/ { count++ }
|
|
131
|
+
fm && count == 1 && !/^---$/ && tgt_drop($0) { next }
|
|
153
132
|
fm && count == 1 && substr($0, 1, 7) == "effort:" {
|
|
154
133
|
if (!effort_seen++ && EFFORT[FILENAME] != "") print fin_line("effort: " EFFORT[FILENAME]) > out
|
|
155
134
|
next
|
|
@@ -163,8 +142,8 @@ sync_claude_agents() {
|
|
|
163
142
|
' "${files[@]}"
|
|
164
143
|
# awk never reads a record from an empty source; the old per-file shell
|
|
165
144
|
# redirect still created an empty output for it.
|
|
166
|
-
for
|
|
167
|
-
[ -s "$
|
|
145
|
+
for ((i = 0; i < ${#files[@]}; i++)); do
|
|
146
|
+
[ -s "${files[i]}" ] || : > "$output_dir/agents/${names[i]}.md"
|
|
168
147
|
done
|
|
169
148
|
printf '%s' "$report"
|
|
170
149
|
}
|
package/engine/adapters/codex.sh
CHANGED
|
@@ -6,6 +6,13 @@
|
|
|
6
6
|
# inlines always-on rules into AGENTS.md, so this adapter only emits skills
|
|
7
7
|
# and subagent definitions.
|
|
8
8
|
#
|
|
9
|
+
# Rules: an always-on rule AGENTS.md does not carry — a local one, or one whose
|
|
10
|
+
# targets leave `agents` out — goes into AGENTS.override.md beside it
|
|
11
|
+
# (decision 0021). Codex reads that file instead of AGENTS.md in the same
|
|
12
|
+
# directory, so it holds the whole AGENTS.md plus those rules. The contract
|
|
13
|
+
# ignores it, and it exists only while such a rule does; one Intelligence did
|
|
14
|
+
# not generate is never touched, and refuses a render that needs the path.
|
|
15
|
+
#
|
|
9
16
|
# Skills: copy skill directories in full to .agents/skills/{name}/ (Codex
|
|
10
17
|
# reads from $REPO_ROOT/.agents/skills exclusively per official docs)
|
|
11
18
|
# Agents: -> .codex/agents/{name}.toml (name, description, model,
|
|
@@ -26,8 +33,61 @@ adapter_contract_codex() {
|
|
|
26
33
|
adapter_contract_requires agents
|
|
27
34
|
adapter_contract_managed ".agents/skills"
|
|
28
35
|
adapter_contract_owned "$output/agents"
|
|
36
|
+
# Marker-managed: a hand-written override is left alone.
|
|
37
|
+
adapter_contract_managed "AGENTS.override.md"
|
|
29
38
|
adapter_contract_ignore ".agents/skills/"
|
|
30
39
|
adapter_contract_ignore "$output/agents/"
|
|
40
|
+
adapter_contract_ignore "AGENTS.override.md"
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
CODEX_OVERRIDE_MARKER="<!-- Generated by intelligence-sync. Do not edit manually. -->"
|
|
44
|
+
|
|
45
|
+
# sync_codex_override <repo_root> <config_file> — write AGENTS.override.md
|
|
46
|
+
# while an always-on rule AGENTS.md does not carry is for Codex, and remove a
|
|
47
|
+
# generated one otherwise.
|
|
48
|
+
sync_codex_override() {
|
|
49
|
+
local repo_root="$1" config_file="$2" override="$1/AGENTS.override.md" first="" agents_file i
|
|
50
|
+
local -a files=() names=()
|
|
51
|
+
source_artifacts_var "$repo_root" "$config_file" rules codex "AGENTS.override.md"
|
|
52
|
+
for ((i = 0; i < ${#IS_SOURCE_FILES[@]}; i++)); do
|
|
53
|
+
[ "${IS_SOURCE_SCOPED[i]}" = 0 ] && [ "${IS_SOURCE_IN_AGENTS[i]}" = 0 ] || continue
|
|
54
|
+
files+=("${IS_SOURCE_FILES[i]}")
|
|
55
|
+
names+=("${IS_SOURCE_NAMES[i]}")
|
|
56
|
+
done
|
|
57
|
+
if [ -f "$override" ]; then
|
|
58
|
+
IFS= read -r first < "$override" || true
|
|
59
|
+
if [ "${first%$'\r'}" != "$CODEX_OVERRIDE_MARKER" ]; then
|
|
60
|
+
[ "${#files[@]}" -gt 0 ] || return 0
|
|
61
|
+
echo "ERROR: AGENTS.override.md was not generated by intelligence-sync, but ${names[*]} need it: always-on rules for Codex that AGENTS.md does not carry go there. Move its guidance into a rule, remove it, then sync." >&2
|
|
62
|
+
return 1
|
|
63
|
+
fi
|
|
64
|
+
fi
|
|
65
|
+
if [ "${#files[@]}" -eq 0 ]; then
|
|
66
|
+
rm -f "$override"
|
|
67
|
+
return 0
|
|
68
|
+
fi
|
|
69
|
+
target_output_var "$config_file" "agents"
|
|
70
|
+
agents_output_path_var "${IS_TGT_OUTPUT:-.agents}"
|
|
71
|
+
agents_file="$repo_root/$IS_AGENTS_OUTPUT_PATH"
|
|
72
|
+
{
|
|
73
|
+
if [ -f "$agents_file" ]; then
|
|
74
|
+
cat "$agents_file"
|
|
75
|
+
else
|
|
76
|
+
printf '%s\n\n' "$CODEX_OVERRIDE_MARKER"
|
|
77
|
+
fi
|
|
78
|
+
echo "---"
|
|
79
|
+
echo ""
|
|
80
|
+
echo "## Codex Project Context"
|
|
81
|
+
echo ""
|
|
82
|
+
echo "<!-- Always-on rules AGENTS.md does not carry. Codex reads this file instead of AGENTS.md. -->"
|
|
83
|
+
echo ""
|
|
84
|
+
emit_rule_bodies "${files[@]}"
|
|
85
|
+
} > "$override"
|
|
86
|
+
finalize_output_file "$override"
|
|
87
|
+
for ((i = 0; i < ${#names[@]}; i++)); do
|
|
88
|
+
echo " rule: ${names[i]} (always-on, AGENTS.override.md)"
|
|
89
|
+
done
|
|
90
|
+
echo " -> AGENTS.override.md"
|
|
31
91
|
}
|
|
32
92
|
|
|
33
93
|
# Codex-specific guard for its documented project-instruction byte budget.
|
|
@@ -52,6 +112,8 @@ codex_warn_project_doc_size() {
|
|
|
52
112
|
target_output_var "$config_file" "agents"
|
|
53
113
|
local output
|
|
54
114
|
output="$(agents_output_path "${IS_TGT_OUTPUT:-.agents}")"
|
|
115
|
+
# Codex reads AGENTS.override.md instead of AGENTS.md when it exists.
|
|
116
|
+
[ ! -f "$repo_root/AGENTS.override.md" ] || output="AGENTS.override.md"
|
|
55
117
|
|
|
56
118
|
local output_file="$repo_root/$output"
|
|
57
119
|
[ -f "$output_file" ] || return 0
|
|
@@ -83,19 +145,13 @@ sync_codex_agents() {
|
|
|
83
145
|
local config_file="$2"
|
|
84
146
|
local output_dir="$3"
|
|
85
147
|
|
|
86
|
-
local
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
[ -d "$dir" ] || continue
|
|
94
|
-
for f in "$dir"/*.md; do
|
|
95
|
-
[ -f "$f" ] || continue
|
|
96
|
-
files+=("$f")
|
|
97
|
-
done
|
|
98
|
-
done <<< "$list"
|
|
148
|
+
local -a files=() names=()
|
|
149
|
+
output_rel_var "$repo_root" "$output_dir"
|
|
150
|
+
source_artifacts_var "$repo_root" "$config_file" agents codex "$IS_OUTPUT_REL/{}.toml"
|
|
151
|
+
if [ "${#IS_SOURCE_FILES[@]}" -gt 0 ]; then
|
|
152
|
+
files=("${IS_SOURCE_FILES[@]}")
|
|
153
|
+
names=("${IS_SOURCE_NAMES[@]}")
|
|
154
|
+
fi
|
|
99
155
|
|
|
100
156
|
local count=0
|
|
101
157
|
if [ "${#files[@]}" -gt 0 ]; then
|
|
@@ -103,8 +159,7 @@ sync_codex_agents() {
|
|
|
103
159
|
|
|
104
160
|
local path tier access description effort name sandbox spec="" report="" LS=$'\x1e'
|
|
105
161
|
while IFS=$'\x1f' read -r path tier access description effort; do
|
|
106
|
-
|
|
107
|
-
name="${path##*/}"; name="${name%.md}"
|
|
162
|
+
name="${names[count]}"
|
|
108
163
|
resolve_model_var "$tier"
|
|
109
164
|
map_effort_var codex "$effort"
|
|
110
165
|
case "$access" in
|
|
@@ -155,5 +210,9 @@ sync_to_codex() {
|
|
|
155
210
|
mkdir -p "$agents_dir"
|
|
156
211
|
sync_codex_agents "$repo_root" "$config_file" "$agents_dir"
|
|
157
212
|
|
|
213
|
+
# Rules AGENTS.md does not carry -> AGENTS.override.md. The contract
|
|
214
|
+
# requires `agents`, so AGENTS.md has rendered by now.
|
|
215
|
+
sync_codex_override "$repo_root" "$config_file" || return 1
|
|
216
|
+
|
|
158
217
|
codex_warn_project_doc_size "$repo_root" "$config_file"
|
|
159
218
|
}
|
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
# natively, and the `agents` adapter inlines always-on rule content
|
|
9
9
|
# into AGENTS.md. We also do not generate .github/copilot-instructions.md
|
|
10
10
|
# because Copilot bug copilot-cli#489 makes AGENTS.md ignored when
|
|
11
|
-
# copilot-instructions.md is present.
|
|
11
|
+
# copilot-instructions.md is present. An always-on rule AGENTS.md does not
|
|
12
|
+
# carry — a local one, or one whose targets leave `agents` out — becomes
|
|
13
|
+
# an .instructions.md file with `applyTo: "**"` (decision 0021).
|
|
12
14
|
# Skills: copy skill directories in full to .github/skills/{name}/
|
|
13
15
|
# Agents: -> .github/agents/{name}.agent.md (description, tools, model)
|
|
14
16
|
#
|
|
@@ -100,8 +102,8 @@ copilot_paths_rows() {
|
|
|
100
102
|
' "$@"
|
|
101
103
|
}
|
|
102
104
|
|
|
103
|
-
# Sync rules to Copilot format.
|
|
104
|
-
#
|
|
105
|
+
# Sync rules to Copilot format. Path-scoped rules are emitted, and an always-on
|
|
106
|
+
# rule only when AGENTS.md (read by Copilot natively) does not carry it.
|
|
105
107
|
sync_copilot_rules() {
|
|
106
108
|
local repo_root="$1"
|
|
107
109
|
local config_file="$2"
|
|
@@ -112,35 +114,28 @@ sync_copilot_rules() {
|
|
|
112
114
|
|
|
113
115
|
local scoped_count=0
|
|
114
116
|
|
|
115
|
-
local
|
|
116
|
-
local -a
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
[
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if [ "${#files[@]}" -gt 0 ]; then
|
|
131
|
-
local path hp
|
|
132
|
-
while IFS=$'\x1f' read -r path hp; do
|
|
133
|
-
[ -n "$path" ] || continue
|
|
134
|
-
[ "$hp" -eq 0 ] && continue
|
|
135
|
-
scoped+=("$path")
|
|
136
|
-
done < <(frontmatter_index "paths#" "${files[@]}")
|
|
137
|
-
fi
|
|
117
|
+
local i always_count=0 spec="" report="" LS=$'\x1e'
|
|
118
|
+
local -a scoped=() scoped_names=()
|
|
119
|
+
output_rel_var "$repo_root" "$instructions_dir"
|
|
120
|
+
source_artifacts_var "$repo_root" "$config_file" rules copilot "$IS_OUTPUT_REL/{}.instructions.md"
|
|
121
|
+
for ((i = 0; i < ${#IS_SOURCE_FILES[@]}; i++)); do
|
|
122
|
+
if [ "${IS_SOURCE_SCOPED[i]}" = 1 ]; then
|
|
123
|
+
scoped+=("${IS_SOURCE_FILES[i]}")
|
|
124
|
+
scoped_names+=("${IS_SOURCE_NAMES[i]}")
|
|
125
|
+
elif [ "${IS_SOURCE_IN_AGENTS[i]}" = 0 ]; then
|
|
126
|
+
# An always-on rule AGENTS.md does not carry applies everywhere.
|
|
127
|
+
spec+="${IS_SOURCE_FILES[i]}"$'\x1f'"$instructions_dir/${IS_SOURCE_NAMES[i]}.instructions.md"$'\x1f'"fence_nofm"$'\x1f'"0"$'\x1f'"none"$'\x1f'"${LS}---${LS}applyTo: \"**\"${LS}---${LS}"$'\x1f\n'
|
|
128
|
+
report+=" rule: ${IS_SOURCE_NAMES[i]}.instructions.md (always-on)"$'\n'
|
|
129
|
+
always_count=$((always_count + 1))
|
|
130
|
+
fi
|
|
131
|
+
done
|
|
138
132
|
|
|
139
133
|
if [ "${#scoped[@]}" -gt 0 ]; then
|
|
140
|
-
local base paths_line
|
|
134
|
+
local path base paths_line
|
|
135
|
+
i=0
|
|
141
136
|
while IFS=$'\x1f' read -r path paths_line; do
|
|
142
|
-
|
|
143
|
-
|
|
137
|
+
base="${scoped_names[i]}"
|
|
138
|
+
i=$((i + 1))
|
|
144
139
|
|
|
145
140
|
local header
|
|
146
141
|
header="${LS}---"
|
|
@@ -152,12 +147,17 @@ sync_copilot_rules() {
|
|
|
152
147
|
report+=" rule: $base.instructions.md (scoped)"$'\n'
|
|
153
148
|
scoped_count=$((scoped_count + 1))
|
|
154
149
|
done < <(copilot_paths_rows "${scoped[@]}")
|
|
155
|
-
|
|
150
|
+
fi
|
|
151
|
+
if [ -n "$spec" ]; then
|
|
156
152
|
emit_wrapped_bodies "$spec"
|
|
157
153
|
printf '%s' "$report"
|
|
158
154
|
fi
|
|
159
155
|
|
|
160
|
-
|
|
156
|
+
if [ "$always_count" -gt 0 ]; then
|
|
157
|
+
echo " rules: $scoped_count scoped, $always_count always-on"
|
|
158
|
+
else
|
|
159
|
+
echo " rules: $scoped_count scoped"
|
|
160
|
+
fi
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
# Sync skills to Copilot format (SKILL.md in .github/skills/)
|
|
@@ -166,33 +166,23 @@ sync_copilot_skills() {
|
|
|
166
166
|
local config_file="$2"
|
|
167
167
|
local output_dir="$3"
|
|
168
168
|
|
|
169
|
-
local
|
|
169
|
+
local i name
|
|
170
170
|
local -a skill_dirs=()
|
|
171
|
-
# The
|
|
172
|
-
# (decision 0017)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
local dir="$repo_root/$src"
|
|
179
|
-
[ -d "$dir" ] || continue
|
|
180
|
-
for d in "$dir"/*/; do
|
|
181
|
-
[ -d "$d" ] || continue
|
|
182
|
-
[ -f "$d/SKILL.md" ] || continue
|
|
183
|
-
skill_source_rendered "$d" || continue
|
|
184
|
-
skill_dirs+=("$d")
|
|
185
|
-
done
|
|
186
|
-
done <<< "$list"
|
|
171
|
+
# The catalog's skills are the ones the inventory renders, symlinked ones
|
|
172
|
+
# included (decision 0017).
|
|
173
|
+
output_rel_var "$repo_root" "$output_dir"
|
|
174
|
+
source_artifacts_var "$repo_root" "$config_file" skills copilot "$IS_OUTPUT_REL/skills/{}"
|
|
175
|
+
for ((i = 0; i < ${#IS_SOURCE_FILES[@]}; i++)); do
|
|
176
|
+
skill_dirs+=("${IS_SOURCE_FILES[i]%/SKILL.md}/")
|
|
177
|
+
done
|
|
187
178
|
|
|
188
179
|
local count=0
|
|
189
180
|
if [ "${#skill_dirs[@]}" -gt 0 ]; then
|
|
190
181
|
# Copilot has no effort field: the copy carries no `effort:`.
|
|
191
|
-
|
|
192
|
-
for
|
|
193
|
-
skill_name="${d%/}"
|
|
182
|
+
copy_skill_bundle_dirs_named copilot "$output_dir/skills" "$IS_SOURCE_NAME_MAP" "${skill_dirs[@]}"
|
|
183
|
+
for name in "${IS_SOURCE_NAMES[@]}"; do
|
|
194
184
|
count=$((count + 1))
|
|
195
|
-
echo " skill: $
|
|
185
|
+
echo " skill: $name"
|
|
196
186
|
done
|
|
197
187
|
fi
|
|
198
188
|
|
|
@@ -205,19 +195,13 @@ sync_copilot_agents() {
|
|
|
205
195
|
local config_file="$2"
|
|
206
196
|
local output_dir="$3"
|
|
207
197
|
|
|
208
|
-
local
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
[ -d "$dir" ] || continue
|
|
216
|
-
for f in "$dir"/*.md; do
|
|
217
|
-
[ -f "$f" ] || continue
|
|
218
|
-
files+=("$f")
|
|
219
|
-
done
|
|
220
|
-
done <<< "$list"
|
|
198
|
+
local -a files=() names=()
|
|
199
|
+
output_rel_var "$repo_root" "$output_dir"
|
|
200
|
+
source_artifacts_var "$repo_root" "$config_file" agents copilot "$IS_OUTPUT_REL/agents/{}.agent.md"
|
|
201
|
+
if [ "${#IS_SOURCE_FILES[@]}" -gt 0 ]; then
|
|
202
|
+
files=("${IS_SOURCE_FILES[@]}")
|
|
203
|
+
names=("${IS_SOURCE_NAMES[@]}")
|
|
204
|
+
fi
|
|
221
205
|
|
|
222
206
|
local count=0
|
|
223
207
|
if [ "${#files[@]}" -gt 0 ]; then
|
|
@@ -225,8 +209,7 @@ sync_copilot_agents() {
|
|
|
225
209
|
|
|
226
210
|
local path tier access description name tools_line spec="" report="" LS=$'\x1e'
|
|
227
211
|
while IFS=$'\x1f' read -r path tier access description; do
|
|
228
|
-
|
|
229
|
-
name="${path##*/}"; name="${name%.md}"
|
|
212
|
+
name="${names[count]}"
|
|
230
213
|
resolve_model_var "$tier"
|
|
231
214
|
|
|
232
215
|
# Build tools list based on access. Tool aliases per Copilot custom-agent
|