@ainova-systems/intelligence 0.17.3 → 0.18.1
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/engine/ENGINE_SHA +1 -1
- package/engine/VERSION +1 -1
- package/engine/adapters/codex.sh +2 -1
- package/engine/lib/common.sh +213 -23
- package/package.json +1 -1
- package/packages/sync/agents/intelligence-operator.md +5 -2
- package/packages/sync/references/adapters.md +3 -3
- package/packages/sync/references/conventions.md +11 -6
- package/packages/sync/rules/intelligence-authoring.md +1 -1
- package/packages/sync/skills/intelligence-manage-adapters/SKILL.md +1 -0
- package/packages/sync/skills/intelligence-update-context/references/agents.md +5 -3
- package/packages/sync/skills/intelligence-upgrade/SKILL.md +1 -0
package/cli/commands/init.sh
CHANGED
|
@@ -295,7 +295,8 @@ manifest="$root/intelligence.yaml"
|
|
|
295
295
|
echo "# $content_dir/rules/context.md an always-on rule; describe the project,"
|
|
296
296
|
echo "# its stack, and the constraints to respect"
|
|
297
297
|
echo "# $content_dir/agents/<name>.md a persona (frontmatter: name, description,"
|
|
298
|
-
echo "# tier: heavy|standard|light,
|
|
298
|
+
echo "# tier: frontier|heavy|standard|light,"
|
|
299
|
+
echo "# access: full|readonly)"
|
|
299
300
|
echo "# $content_dir/skills/<name>/SKILL.md a procedure invoked as /<name>"
|
|
300
301
|
echo "# '.intelligence/' is CLI-managed (packages + engine content) — never edit it."
|
|
301
302
|
echo "sources:"
|
package/engine/ENGINE_SHA
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
7dfbb01c2182f3de05bff94f3e5e080cf267f8c6
|
package/engine/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.18.1
|
package/engine/adapters/codex.sh
CHANGED
|
@@ -103,7 +103,8 @@ sync_codex_agents() {
|
|
|
103
103
|
name="${path##*/}"; name="${name%.md}"
|
|
104
104
|
resolve_model_var "$tier"
|
|
105
105
|
case "$tier" in
|
|
106
|
-
|
|
106
|
+
frontier) effort="xhigh" ;;
|
|
107
|
+
heavy|"") effort="high" ;;
|
|
107
108
|
standard) effort="medium" ;;
|
|
108
109
|
light) effort="low" ;;
|
|
109
110
|
*) effort="medium" ;;
|
package/engine/lib/common.sh
CHANGED
|
@@ -661,6 +661,7 @@ sync_open_skill_dirs() {
|
|
|
661
661
|
# target gets it — not just this open-standard dir.
|
|
662
662
|
if [ "$count" -gt 0 ]; then
|
|
663
663
|
copy_skill_bundle_dirs "$output_dir" "${skill_dirs[@]}"
|
|
664
|
+
open_skill_invocation_policies "$output_dir" || return 1
|
|
664
665
|
fi
|
|
665
666
|
|
|
666
667
|
log+=" -> Skills: $count"$'\n'
|
|
@@ -670,6 +671,162 @@ sync_open_skill_dirs() {
|
|
|
670
671
|
IS_OPEN_SKILLS_LOG="$log"
|
|
671
672
|
}
|
|
672
673
|
|
|
674
|
+
# open_skill_invocation_policies <open_skills_dir> — `disable-model-invocation:
|
|
675
|
+
# true` keeps a skill out of automatic selection in Claude Code, Cursor and
|
|
676
|
+
# Copilot, but Codex ignores that key and reads the same intent from
|
|
677
|
+
# `agents/openai.yaml` beside SKILL.md. Source skills stay tool-neutral: the
|
|
678
|
+
# policy file is derived here, in the open-standard tree Codex reads, so every
|
|
679
|
+
# adapter sharing that tree writes the same bytes. A skill that ships its own
|
|
680
|
+
# `agents/openai.yaml` keeps the rest of it: the output copy gains the policy
|
|
681
|
+
# when the author's file sets none, and a file whose policy says otherwise, or
|
|
682
|
+
# that sync cannot read as saying it, refuses the render — an owner-only skill
|
|
683
|
+
# Codex can still select is the exact failure the field exists to prevent, so
|
|
684
|
+
# it never passes as a success.
|
|
685
|
+
open_skill_invocation_policies() {
|
|
686
|
+
local output_dir="$1" path dir flag rows refusals
|
|
687
|
+
local -a skill_mds=() policy_dirs=() policies=() authored=()
|
|
688
|
+
for path in "$output_dir"/*/SKILL.md; do
|
|
689
|
+
dir="${path%/SKILL.md}"
|
|
690
|
+
# A link is emitted as-is (see _skill_bundle_note): reading through it
|
|
691
|
+
# or writing beside it would reach outside the output tree.
|
|
692
|
+
if [ -L "$dir" ] || [ -L "$path" ]; then
|
|
693
|
+
echo " WARN: ${dir##*/}/SKILL.md is reached through a symlink — Codex gets no invocation policy derived for it" >&2
|
|
694
|
+
elif [ -f "$path" ]; then
|
|
695
|
+
skill_mds+=("$path")
|
|
696
|
+
fi
|
|
697
|
+
done
|
|
698
|
+
[ "${#skill_mds[@]}" -gt 0 ] || return 0
|
|
699
|
+
# Captured, not streamed: a reader cut short must fail the render rather
|
|
700
|
+
# than quietly drop a policy and hand the skill back to the model.
|
|
701
|
+
rows="$(frontmatter_index "disable-model-invocation" "${skill_mds[@]}")" || {
|
|
702
|
+
echo "ERROR: could not read skill frontmatter under $output_dir" >&2
|
|
703
|
+
return 1
|
|
704
|
+
}
|
|
705
|
+
while IFS=$'\x1f' read -r path flag; do
|
|
706
|
+
[ "$flag" = "true" ] || continue
|
|
707
|
+
dir="${path%/SKILL.md}"
|
|
708
|
+
path="$dir/agents"
|
|
709
|
+
if [ -L "$path" ] || [ -L "$path/openai.yaml" ]; then
|
|
710
|
+
echo " WARN: ${dir##*/}/agents/openai.yaml is a symlink — left as-is, its invocation policy is not enforced" >&2
|
|
711
|
+
continue
|
|
712
|
+
fi
|
|
713
|
+
if [ -s "$path/openai.yaml" ]; then
|
|
714
|
+
authored+=("$path/openai.yaml")
|
|
715
|
+
continue
|
|
716
|
+
fi
|
|
717
|
+
policy_dirs+=("$path")
|
|
718
|
+
policies+=("$path/openai.yaml")
|
|
719
|
+
done <<< "$rows"
|
|
720
|
+
if [ "${#authored[@]}" -gt 0 ]; then
|
|
721
|
+
refusals="$(enforce_authored_invocation_policies "${authored[@]}")" || {
|
|
722
|
+
echo "ERROR: could not read or rewrite agents/openai.yaml under $output_dir" >&2
|
|
723
|
+
return 1
|
|
724
|
+
}
|
|
725
|
+
if [ -n "$refusals" ]; then
|
|
726
|
+
while IFS=$'\t' read -r path flag; do
|
|
727
|
+
path="${path%/agents/openai.yaml}"
|
|
728
|
+
echo "ERROR: ${path##*/} sets disable-model-invocation: true, but its agents/openai.yaml $flag — make them agree, or Codex can still select the skill" >&2
|
|
729
|
+
done <<< "$refusals"
|
|
730
|
+
return 1
|
|
731
|
+
fi
|
|
732
|
+
fi
|
|
733
|
+
[ "${#policies[@]}" -gt 0 ] || return 0
|
|
734
|
+
mkdir -p "${policy_dirs[@]}"
|
|
735
|
+
for path in "${policies[@]}"; do
|
|
736
|
+
printf '%s\n' '# Generated by intelligence-sync from disable-model-invocation in SKILL.md. Do not edit manually.' \
|
|
737
|
+
'policy:' ' allow_implicit_invocation: false' > "$path"
|
|
738
|
+
done
|
|
739
|
+
finalize_output_files "${policies[@]}"
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
# enforce_authored_invocation_policies <openai.yaml>... — one awk pass over
|
|
743
|
+
# author-owned Codex files of skills that set `disable-model-invocation: true`.
|
|
744
|
+
# A file already setting `policy.allow_implicit_invocation: false` is left
|
|
745
|
+
# alone; one without that key gains it, inside an existing `policy:` block or
|
|
746
|
+
# as a new block, every other line kept. Only the plain boolean on a direct
|
|
747
|
+
# child of `policy:` counts — the key Codex reads. A file that sets it
|
|
748
|
+
# otherwise, or whose `policy:` sync cannot read or extend safely, is printed
|
|
749
|
+
# as `<file>\t<reason>` and left untouched for the caller to refuse.
|
|
750
|
+
enforce_authored_invocation_policies() {
|
|
751
|
+
awk '
|
|
752
|
+
function reset() {
|
|
753
|
+
file = ""; n = 0; haspol = 0; inpol = 0; polline = 0
|
|
754
|
+
inline = ""; child = ""; val = ""; hasval = 0; bad = ""
|
|
755
|
+
}
|
|
756
|
+
# A one-line policy counts only as a flat flow mapping of plain
|
|
757
|
+
# scalars holding the key itself; a quoted or nested value is not read.
|
|
758
|
+
function inline_ok(s, body, parts, k, i, p) {
|
|
759
|
+
if (s !~ /^\{.*\}$/) return 0
|
|
760
|
+
body = substr(s, 2, length(s) - 2)
|
|
761
|
+
if (body ~ /[{}"\047]/ || index(body, "[") || index(body, "]")) return 0
|
|
762
|
+
k = split(body, parts, ",")
|
|
763
|
+
for (i = 1; i <= k; i++) {
|
|
764
|
+
p = parts[i]
|
|
765
|
+
gsub(/^[[:space:]]+|[[:space:]]+$/, "", p)
|
|
766
|
+
if (p ~ /^allow_implicit_invocation[[:space:]]*:[[:space:]]*false$/) return 1
|
|
767
|
+
}
|
|
768
|
+
return 0
|
|
769
|
+
}
|
|
770
|
+
function finish( i, ind) {
|
|
771
|
+
if (file == "") return
|
|
772
|
+
if (bad == "" && inline != "" && !inline_ok(inline))
|
|
773
|
+
bad = "has policy: " inline ", which does not plainly set allow_implicit_invocation: false"
|
|
774
|
+
if (bad == "" && hasval && val != "false")
|
|
775
|
+
bad = "sets policy.allow_implicit_invocation: " (val == "" ? "null" : val)
|
|
776
|
+
if (bad != "") { printf "%s\t%s\n", file, bad; reset(); return }
|
|
777
|
+
if (inline != "" || hasval) { reset(); return }
|
|
778
|
+
ind = (child != "") ? child : " "
|
|
779
|
+
for (i = 1; i <= n; i++) {
|
|
780
|
+
print L[i] > file
|
|
781
|
+
if (haspol && i == polline) print ind "allow_implicit_invocation: false" > file
|
|
782
|
+
}
|
|
783
|
+
if (!haspol) {
|
|
784
|
+
print "policy:" > file
|
|
785
|
+
print " allow_implicit_invocation: false" > file
|
|
786
|
+
}
|
|
787
|
+
close(file)
|
|
788
|
+
reset()
|
|
789
|
+
}
|
|
790
|
+
BEGIN { reset() }
|
|
791
|
+
FNR == 1 { finish(); file = FILENAME }
|
|
792
|
+
{ sub(/\r$/, ""); L[++n] = $0 }
|
|
793
|
+
/^["\047]?policy["\047]?[[:space:]]*:/ {
|
|
794
|
+
if (haspol) bad = "has more than one policy: key"
|
|
795
|
+
haspol = 1; polline = n; inpol = 1
|
|
796
|
+
rest = $0
|
|
797
|
+
sub(/^[^:]*:[[:space:]]*/, "", rest)
|
|
798
|
+
sub(/[[:space:]]+#.*$/, "", rest)
|
|
799
|
+
sub(/^#.*$/, "", rest)
|
|
800
|
+
sub(/[[:space:]]+$/, "", rest)
|
|
801
|
+
if (rest != "") { inline = rest; inpol = 0 }
|
|
802
|
+
next
|
|
803
|
+
}
|
|
804
|
+
inpol && /^[^[:space:]#]/ { inpol = 0 }
|
|
805
|
+
# The first indented line fixes the depth of the direct children of
|
|
806
|
+
# policy:, and a deeper line belongs to another key, not the one Codex
|
|
807
|
+
# reads.
|
|
808
|
+
inpol && /^[[:space:]]+[^[:space:]#]/ {
|
|
809
|
+
match($0, /^[[:space:]]+/)
|
|
810
|
+
cur = substr($0, 1, RLENGTH)
|
|
811
|
+
if (child == "") {
|
|
812
|
+
child = cur
|
|
813
|
+
if ($0 ~ /^[[:space:]]+-([[:space:]]|$)/) bad = "has a policy: that is not a mapping"
|
|
814
|
+
} else if (length(cur) < length(child)) {
|
|
815
|
+
bad = "has a policy: block indented inconsistently"
|
|
816
|
+
}
|
|
817
|
+
if (cur == child && $0 ~ /^[[:space:]]+["\047]?allow_implicit_invocation["\047]?[[:space:]]*:/) {
|
|
818
|
+
v = $0
|
|
819
|
+
sub(/^[^:]*:[[:space:]]*/, "", v)
|
|
820
|
+
sub(/[[:space:]]+#.*$/, "", v)
|
|
821
|
+
sub(/^#.*$/, "", v)
|
|
822
|
+
sub(/[[:space:]]+$/, "", v)
|
|
823
|
+
hasval = 1; val = v
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
END { finish() }
|
|
827
|
+
' "$@"
|
|
828
|
+
}
|
|
829
|
+
|
|
673
830
|
# Lint YAML frontmatter for common pitfalls (unquoted colons, leading tabs).
|
|
674
831
|
# Print warnings to stderr; do not fail. Strict consumers (Codex CLI) reject
|
|
675
832
|
# these files with cryptic messages — catching them in sync gives better DX.
|
|
@@ -816,33 +973,47 @@ has_paths() {
|
|
|
816
973
|
|
|
817
974
|
# --- Tier/Access Mappings ---
|
|
818
975
|
|
|
819
|
-
# Hardcoded defaults: ide:tier -> model name.
|
|
976
|
+
# Hardcoded defaults: ide:tier -> model name. Where a tool has fewer models
|
|
977
|
+
# than there are tiers, tiers share one (decision 0013). cli/tests/unit-engine.sh
|
|
978
|
+
# pins this table independently, so a bump updates its expected matrix too.
|
|
820
979
|
# When you bump these, re-run sync in projects; any project whose config.yaml
|
|
821
980
|
# `models:` section diverges from these will print a drift warning so users
|
|
822
981
|
# know their override is now stale.
|
|
823
982
|
# get_model_default_var sets IS_MODEL_DEFAULT; get_model_default prints it.
|
|
824
983
|
get_model_default_var() {
|
|
825
984
|
case "$1:$2" in
|
|
985
|
+
# Haiku 4.5 retires no sooner than 2026-10-15 and has no successor, so
|
|
986
|
+
# light shares standard's Sonnet on every Claude-backed target.
|
|
987
|
+
claude:frontier) IS_MODEL_DEFAULT="fable" ;;
|
|
826
988
|
claude:heavy) IS_MODEL_DEFAULT="opus" ;;
|
|
827
989
|
claude:standard) IS_MODEL_DEFAULT="sonnet" ;;
|
|
828
|
-
claude:light) IS_MODEL_DEFAULT="
|
|
990
|
+
claude:light) IS_MODEL_DEFAULT="sonnet" ;;
|
|
991
|
+
# Cursor documents only `inherit` or a concrete model ID, so every
|
|
992
|
+
# tier follows the session model unless the manifest pins one.
|
|
993
|
+
cursor:frontier) IS_MODEL_DEFAULT="inherit" ;;
|
|
829
994
|
cursor:heavy) IS_MODEL_DEFAULT="inherit" ;;
|
|
830
995
|
cursor:standard) IS_MODEL_DEFAULT="inherit" ;;
|
|
831
|
-
cursor:light) IS_MODEL_DEFAULT="
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
copilot:
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
996
|
+
cursor:light) IS_MODEL_DEFAULT="inherit" ;;
|
|
997
|
+
# GPT-6 has no mid model, so frontier and heavy share Astra; Codex
|
|
998
|
+
# separates them by reasoning effort instead.
|
|
999
|
+
copilot:frontier) IS_MODEL_DEFAULT="gpt-6-astra" ;;
|
|
1000
|
+
copilot:heavy) IS_MODEL_DEFAULT="gpt-6-astra" ;;
|
|
1001
|
+
copilot:standard) IS_MODEL_DEFAULT="gpt-6.1-sol" ;;
|
|
1002
|
+
copilot:light) IS_MODEL_DEFAULT="gpt-6-luna" ;;
|
|
1003
|
+
codex:frontier) IS_MODEL_DEFAULT="gpt-6-astra" ;;
|
|
1004
|
+
codex:heavy) IS_MODEL_DEFAULT="gpt-6-astra" ;;
|
|
1005
|
+
codex:standard) IS_MODEL_DEFAULT="gpt-6.1-sol" ;;
|
|
1006
|
+
codex:light) IS_MODEL_DEFAULT="gpt-6-luna" ;;
|
|
1007
|
+
# Antigravity accepts only inherit|flash|pro, so frontier and heavy
|
|
1008
|
+
# share `pro` and standard and light share `flash`.
|
|
1009
|
+
antigravity:frontier) IS_MODEL_DEFAULT="pro" ;;
|
|
840
1010
|
antigravity:heavy) IS_MODEL_DEFAULT="pro" ;;
|
|
841
1011
|
antigravity:standard) IS_MODEL_DEFAULT="flash" ;;
|
|
842
1012
|
antigravity:light) IS_MODEL_DEFAULT="flash" ;;
|
|
843
|
-
opencode:
|
|
844
|
-
opencode:
|
|
845
|
-
opencode:
|
|
1013
|
+
opencode:frontier) IS_MODEL_DEFAULT="anthropic/claude-fable-5-1" ;;
|
|
1014
|
+
opencode:heavy) IS_MODEL_DEFAULT="anthropic/claude-opus-5-5" ;;
|
|
1015
|
+
opencode:standard) IS_MODEL_DEFAULT="anthropic/claude-sonnet-5-5" ;;
|
|
1016
|
+
opencode:light) IS_MODEL_DEFAULT="anthropic/claude-sonnet-5-5" ;;
|
|
846
1017
|
*) IS_MODEL_DEFAULT="" ;;
|
|
847
1018
|
esac
|
|
848
1019
|
}
|
|
@@ -925,25 +1096,29 @@ get_model() {
|
|
|
925
1096
|
fi
|
|
926
1097
|
}
|
|
927
1098
|
|
|
928
|
-
# load_model_tiers <config_file> <ide> — resolve the
|
|
929
|
-
# once per adapter run (
|
|
930
|
-
# so per-file loops map tier -> model
|
|
931
|
-
# consumes them; a non-standard tier value
|
|
932
|
-
# `models:` override for it keeps working.
|
|
1099
|
+
# load_model_tiers <config_file> <ide> — resolve the four standard tiers
|
|
1100
|
+
# once per adapter run (IS_MODEL_FRONTIER / IS_MODEL_HEAVY /
|
|
1101
|
+
# IS_MODEL_STANDARD / IS_MODEL_LIGHT) so per-file loops map tier -> model
|
|
1102
|
+
# without forking. resolve_model_var consumes them; a non-standard tier value
|
|
1103
|
+
# still goes through get_model so a `models:` override for it keeps working.
|
|
1104
|
+
# One manifest pass reads all four.
|
|
933
1105
|
load_model_tiers() {
|
|
934
|
-
local config_file="$1" ide="$2" overrides="" tier val heavy="" standard="" light=""
|
|
1106
|
+
local config_file="$1" ide="$2" overrides="" tier val frontier="" heavy="" standard="" light=""
|
|
935
1107
|
IS_MODEL_CFG="$config_file"
|
|
936
1108
|
IS_MODEL_IDE="$ide"
|
|
937
1109
|
if [ -n "$config_file" ] && [ -f "$config_file" ]; then
|
|
938
|
-
overrides="$(_nested_yaml_values tagged "$config_file" "models" "$ide" heavy standard light)"
|
|
1110
|
+
overrides="$(_nested_yaml_values tagged "$config_file" "models" "$ide" frontier heavy standard light)"
|
|
939
1111
|
fi
|
|
940
1112
|
while IFS=$'\037' read -r tier val; do
|
|
941
1113
|
case "$tier" in
|
|
1114
|
+
frontier) frontier="$val" ;;
|
|
942
1115
|
heavy) heavy="$val" ;;
|
|
943
1116
|
standard) standard="$val" ;;
|
|
944
1117
|
light) light="$val" ;;
|
|
945
1118
|
esac
|
|
946
1119
|
done <<< "$overrides"
|
|
1120
|
+
get_model_default_var "$ide" frontier
|
|
1121
|
+
IS_MODEL_FRONTIER="${frontier:-$IS_MODEL_DEFAULT}"
|
|
947
1122
|
get_model_default_var "$ide" heavy
|
|
948
1123
|
IS_MODEL_HEAVY="${heavy:-$IS_MODEL_DEFAULT}"
|
|
949
1124
|
get_model_default_var "$ide" standard
|
|
@@ -953,14 +1128,29 @@ load_model_tiers() {
|
|
|
953
1128
|
}
|
|
954
1129
|
|
|
955
1130
|
# resolve_model_var <tier> — set IS_MODEL from the tiers load_model_tiers
|
|
956
|
-
# resolved. An empty tier resolves to heavy, like get_model's default.
|
|
1131
|
+
# resolved. An empty tier resolves to heavy, like get_model's default. A tier
|
|
1132
|
+
# the tool has no default for and the manifest overrides nowhere — a typo, as a
|
|
1133
|
+
# rule — still renders an empty model, but never silently: the run warns once
|
|
1134
|
+
# per tool and tier, unindented on purpose because `sync --compact` keeps only
|
|
1135
|
+
# `WARNING:` lines.
|
|
957
1136
|
# shellcheck disable=SC2034 # IS_MODEL is the return channel read by adapters
|
|
958
1137
|
resolve_model_var() {
|
|
959
1138
|
case "$1" in
|
|
1139
|
+
frontier) IS_MODEL="$IS_MODEL_FRONTIER" ;;
|
|
960
1140
|
heavy|"") IS_MODEL="$IS_MODEL_HEAVY" ;;
|
|
961
1141
|
standard) IS_MODEL="$IS_MODEL_STANDARD" ;;
|
|
962
1142
|
light) IS_MODEL="$IS_MODEL_LIGHT" ;;
|
|
963
|
-
*)
|
|
1143
|
+
*)
|
|
1144
|
+
IS_MODEL="$(get_model "$IS_MODEL_CFG" "$IS_MODEL_IDE" "$1")"
|
|
1145
|
+
[ -n "$IS_MODEL" ] && return 0
|
|
1146
|
+
case "${IS_MODEL_WARNED:-|}" in
|
|
1147
|
+
*"|$IS_MODEL_IDE:$1|"*) ;;
|
|
1148
|
+
*)
|
|
1149
|
+
IS_MODEL_WARNED="${IS_MODEL_WARNED:-|}$IS_MODEL_IDE:$1|"
|
|
1150
|
+
echo "WARNING: no $IS_MODEL_IDE model for tier '$1' — agents with it get an empty model; use frontier, heavy, standard or light, or set models.$IS_MODEL_IDE.$1" >&2
|
|
1151
|
+
;;
|
|
1152
|
+
esac
|
|
1153
|
+
;;
|
|
964
1154
|
esac
|
|
965
1155
|
}
|
|
966
1156
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainova-systems/intelligence",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.1",
|
|
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"
|
|
@@ -5,8 +5,6 @@ tier: standard
|
|
|
5
5
|
access: full
|
|
6
6
|
skills:
|
|
7
7
|
- intelligence-sync
|
|
8
|
-
- intelligence-upgrade
|
|
9
|
-
- intelligence-manage-adapters
|
|
10
8
|
---
|
|
11
9
|
|
|
12
10
|
# Intelligence operator
|
|
@@ -28,6 +26,11 @@ the operation in prose.
|
|
|
28
26
|
- **Every flow goes through its skill.** The steps and their guards live in `intelligence-sync`,
|
|
29
27
|
`intelligence-upgrade` and `intelligence-manage-adapters`;
|
|
30
28
|
improvising around them produces an unverified version of the same work.
|
|
29
|
+
- **Upgrades and adapter changes are the owner's to start.** `intelligence-upgrade` moves CLI and
|
|
30
|
+
package versions, the lock and migrations; `intelligence-manage-adapters` adds or removes whole
|
|
31
|
+
tool outputs. Both are decisions about the layer, so they run only when the owner invokes them,
|
|
32
|
+
and a sync never previews an update or inspects adapters on its own. Name the command the owner
|
|
33
|
+
can run and stop there.
|
|
31
34
|
- **Operating is not authoring.** A change to what an artifact says - a rule body, an agent persona,
|
|
32
35
|
a skill's steps - belongs to `intelligence-architect` and the authoring meta-skills. This agent
|
|
33
36
|
ships what exists and never decides what should exist.
|
|
@@ -152,12 +152,12 @@ Use the engine library instead of copying parsers or file-handling logic.
|
|
|
152
152
|
| `frontmatter_index(keys, file...)` | Read several frontmatter scalars for many files in one pass (`\x1f`-separated rows; special key `paths#` counts `paths:` lines). |
|
|
153
153
|
| `has_frontmatter(file)` / `has_paths(file)` | Inspect source shape. |
|
|
154
154
|
| `strip_frontmatter(file)` | Emit the body without its first frontmatter block. |
|
|
155
|
-
| `get_model(config, tool, tier)` | Resolve a `heavy`, `standard` or `light` model, including manifest overrides. |
|
|
155
|
+
| `get_model(config, tool, tier)` | Resolve a `frontier`, `heavy`, `standard` or `light` model, including manifest overrides. |
|
|
156
156
|
| `get_model_default(tool, tier)` | Read the built-in model default. |
|
|
157
|
-
| `load_model_tiers(config, tool)` / `resolve_model_var(tier)` | Resolve the
|
|
157
|
+
| `load_model_tiers(config, tool)` / `resolve_model_var(tier)` | Resolve the four standard tiers once, then map per file without subprocesses. |
|
|
158
158
|
| `copy_skill_bundle(src, dest)` | Copy `SKILL.md` and all resources safely, normalize Markdown and quote free-text frontmatter. |
|
|
159
159
|
| `copy_skill_bundle_dirs(dest_root, src...)` | Batch form: copy every skill directory into `dest_root/<name>` with one copy and one finalize pass. |
|
|
160
|
-
| `sync_open_skill_dirs(root, config, dest)` | Own and populate a shared Agent Skills directory such as `.agents/skills
|
|
160
|
+
| `sync_open_skill_dirs(root, config, dest)` | Own and populate a shared Agent Skills directory such as `.agents/skills/`, deriving Codex's `agents/openai.yaml` for a skill with `disable-model-invocation: true`. |
|
|
161
161
|
| `finalize_output_file(file)` | Expand layout tokens and normalize line endings; required for every emitted text file. |
|
|
162
162
|
| `finalize_output_files(file...)` / `finalize_copy_files(dest, src...)` | Batch forms: finalize in place, or copy-and-finalize into a directory, in one process. |
|
|
163
163
|
| `emit_wrapped_bodies(spec)` | Emit many header + source-body + tail outputs in one process (see `engine/lib/common.sh` for the spec format). |
|
|
@@ -185,13 +185,16 @@ Do not instruct an agent to read rules or restate their content. Claude loads it
|
|
|
185
185
|
|
|
186
186
|
### Tier mappings
|
|
187
187
|
|
|
188
|
-
| Tier | Claude | Cursor | Copilot / Codex | OpenCode | Typical use |
|
|
189
|
-
|
|
190
|
-
| `
|
|
191
|
-
| `
|
|
192
|
-
| `
|
|
188
|
+
| Tier | Claude | Cursor | Copilot / Codex | OpenCode | Antigravity | Typical use |
|
|
189
|
+
|---|---|---|---|---|---|---|
|
|
190
|
+
| `frontier` | `fable` | `inherit` | `gpt-6-astra` | `anthropic/claude-fable-5-1` | `pro` | long-horizon autonomous work, the hardest reasoning, where capability outweighs cost |
|
|
191
|
+
| `heavy` | `opus` | `inherit` | `gpt-6-astra` | `anthropic/claude-opus-5-5` | `pro` | implementation, complex reasoning, migration |
|
|
192
|
+
| `standard` | `sonnet` | `inherit` | `gpt-6.1-sol` | `anthropic/claude-sonnet-5-5` | `flash` | review, validation, analysis |
|
|
193
|
+
| `light` | `sonnet` | `inherit` | `gpt-6-luna` | `anthropic/claude-sonnet-5-5` | `flash` | lookups and simple formatting |
|
|
194
|
+
|
|
195
|
+
Codex also receives a reasoning effort per tier — `xhigh`, `high`, `medium`, `low` — which is what separates `frontier` from `heavy` in Codex. Copilot has no effort field, so its `frontier` and `heavy` agents are identical. Claude's Haiku 4.5 is retiring with no successor announced, so `light` shares `standard`'s Sonnet in Claude and OpenCode; Cursor and Antigravity have fewer native levels than there are tiers, so several tiers share one value there too.
|
|
193
196
|
|
|
194
|
-
The vocabulary is tool-neutral. Adapters resolve it through `get_model()`. Override a default under `models.<tool>.<tier>` in `intelligence.yaml` only when the project needs a pin; sync reports drift when that override differs from the current default.
|
|
197
|
+
The vocabulary is tool-neutral. Adapters resolve it through `get_model()`. Override a default under `models.<tool>.<tier>` in `intelligence.yaml` only when the project needs a pin; sync reports drift when that override differs from the current default. Another tier name works only where `models.<tool>.<tier>` defines it; elsewhere — a typo, as a rule — the agent renders with an empty `model` and sync warns once per tool and tier.
|
|
195
198
|
|
|
196
199
|
### Access mappings
|
|
197
200
|
|
|
@@ -251,6 +254,8 @@ argument-hint: "<route-name>"
|
|
|
251
254
|
|
|
252
255
|
Standard optional fields (`license`, `compatibility`, `metadata`, `allowed-tools`) and tool extensions pass through unchanged. A tool ignores fields it does not understand.
|
|
253
256
|
|
|
257
|
+
`disable-model-invocation: true` makes a skill one only the owner starts, as a slash command: use it for a procedure that changes versions, the lock or generated outputs, where an agent selecting it unasked is the failure. Claude Code, Cursor and Copilot read the field itself; Codex does not, so sync writes `agents/openai.yaml` with `allow_implicit_invocation: false` beside the skill in `.agents/skills/`. Keep the source to the field. A skill that ships its own `agents/openai.yaml` keeps everything else in it: sync adds the policy when the file sets none, and refuses one that sets it otherwise or not as a plain `allow_implicit_invocation: false` directly under `policy:`.
|
|
258
|
+
|
|
254
259
|
These limits reject a skill instead of degrading it:
|
|
255
260
|
|
|
256
261
|
| Field | Limit | Failure mode |
|
|
@@ -109,6 +109,6 @@ The goal is subtraction, above. These are only the line past which something is
|
|
|
109
109
|
|
|
110
110
|
## Verifying a change to this layer
|
|
111
111
|
|
|
112
|
-
The per-artifact authoring checks belong to `intelligence-update-context`. Session learning, repository onboarding, and accepted review findings use that same procedure. Invoke `intelligence-learn-from-session` to capture a lesson or workflow, `intelligence-learn-from-repository` for initial migration and recovery, and `intelligence-review-context` for audits and reductions. Operational work uses `intelligence-sync
|
|
112
|
+
The per-artifact authoring checks belong to `intelligence-update-context`. Session learning, repository onboarding, and accepted review findings use that same procedure. Invoke `intelligence-learn-from-session` to capture a lesson or workflow, `intelligence-learn-from-repository` for initial migration and recovery, and `intelligence-review-context` for audits and reductions. Operational work uses `intelligence-sync`. `intelligence-upgrade` and `intelligence-manage-adapters` change versions and generated outputs, so only the owner invokes them.
|
|
113
113
|
|
|
114
114
|
A change to this layer is done when `<sync-cmd>` reports `IS_STATUS=ok` and the skill you invoked reports clean.
|
|
@@ -3,6 +3,7 @@ name: intelligence-manage-adapters
|
|
|
3
3
|
description: "Enable, disable, or remove adapters and assess generated-output cleanup"
|
|
4
4
|
argument-hint: "<enable|disable|remove> <adapter-name>"
|
|
5
5
|
agent: intelligence-operator
|
|
6
|
+
disable-model-invocation: true
|
|
6
7
|
---
|
|
7
8
|
|
|
8
9
|
# Manage adapters
|
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
`<domain>-<role>` and determine its expertise from the source evidence.
|
|
5
5
|
2. Select tier and access: implementation normally uses `heavy` and `full`;
|
|
6
6
|
review or validation uses `standard` and `readonly`; simple lookup uses
|
|
7
|
-
`light` and `readonly`.
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
`light` and `readonly`. Reserve `frontier` for long-horizon work whose
|
|
8
|
+
difficulty justifies the most capable and most expensive model. Check the
|
|
9
|
+
target's actual permission mapping when external read tools are required.
|
|
10
|
+
If native read-only restrictions exclude those tools, use `full` only with a
|
|
11
|
+
clear read-only boundary in the body.
|
|
10
12
|
3. Keep the body thin: Expertise, Boundaries, and Build & Verify. Carry its own
|
|
11
13
|
completion criteria and limitations. Reference constraints by name instead
|
|
12
14
|
of copying rules, and put reusable procedures in skills.
|