@ainova-systems/intelligence 0.23.0 → 0.24.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/engine/ENGINE_SHA
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
6878d4ce559755d55f90ae23296678333e95f775
|
package/engine/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.24.0
|
package/engine/adapters/codex.sh
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
# Transforms source prompts to Codex format.
|
|
4
4
|
#
|
|
5
5
|
# Codex reads AGENTS.md natively for project context — the `agents` adapter
|
|
6
|
-
# inlines always-on rules into AGENTS.md
|
|
7
|
-
# and subagent definitions.
|
|
6
|
+
# inlines shared always-on rules into AGENTS.md.
|
|
8
7
|
#
|
|
9
8
|
# Rules: an always-on rule AGENTS.md does not carry — a local one, or one whose
|
|
10
9
|
# targets leave `agents` out — goes into AGENTS.override.md beside it
|
|
@@ -12,6 +11,8 @@
|
|
|
12
11
|
# directory, so it holds the whole AGENTS.md plus those rules. The contract
|
|
13
12
|
# ignores it, and it exists only while such a rule does; one Intelligence did
|
|
14
13
|
# not generate is never touched, and refuses a render that needs the path.
|
|
14
|
+
# Scoped rules get compact pattern-to-source links in that same override.
|
|
15
|
+
# This is on-demand reading guidance, not a native glob-triggered loader.
|
|
15
16
|
#
|
|
16
17
|
# Skills: copy skill directories in full to .agents/skills/{name}/ (Codex
|
|
17
18
|
# reads from $REPO_ROOT/.agents/skills exclusively per official docs)
|
|
@@ -43,32 +44,50 @@ adapter_contract_codex() {
|
|
|
43
44
|
CODEX_OVERRIDE_MARKER="<!-- Generated by intelligence-sync. Do not edit manually. -->"
|
|
44
45
|
|
|
45
46
|
# sync_codex_override <repo_root> <config_file> — write AGENTS.override.md
|
|
46
|
-
# while
|
|
47
|
-
# generated one otherwise.
|
|
47
|
+
# while Codex needs extra always-on rules or scoped-rule routing, and remove
|
|
48
|
+
# a generated one otherwise.
|
|
48
49
|
sync_codex_override() {
|
|
49
50
|
local repo_root="$1" config_file="$2" override="$1/AGENTS.override.md" first="" agents_file i
|
|
50
|
-
local -a files=() names=()
|
|
51
|
+
local -a files=() names=() scoped=() scoped_names=()
|
|
51
52
|
source_artifacts_var "$repo_root" "$config_file" rules codex "AGENTS.override.md"
|
|
52
53
|
for ((i = 0; i < ${#IS_SOURCE_FILES[@]}; i++)); do
|
|
53
|
-
[ "${IS_SOURCE_SCOPED[i]}" =
|
|
54
|
-
|
|
54
|
+
if [ "${IS_SOURCE_SCOPED[i]}" = 1 ]; then
|
|
55
|
+
scoped+=("${IS_SOURCE_FILES[i]}")
|
|
56
|
+
scoped_names+=("${IS_SOURCE_NAMES[i]}")
|
|
57
|
+
elif [ "${IS_SOURCE_IN_AGENTS[i]}" = 0 ]; then
|
|
58
|
+
files+=("${IS_SOURCE_FILES[i]}")
|
|
59
|
+
else
|
|
60
|
+
continue
|
|
61
|
+
fi
|
|
55
62
|
names+=("${IS_SOURCE_NAMES[i]}")
|
|
56
63
|
done
|
|
57
64
|
if [ -f "$override" ]; then
|
|
58
65
|
IFS= read -r first < "$override" || true
|
|
59
66
|
if [ "${first%$'\r'}" != "$CODEX_OVERRIDE_MARKER" ]; then
|
|
60
|
-
[ "${#
|
|
61
|
-
echo "ERROR: AGENTS.override.md was not generated by intelligence-sync, but ${names[*]} need it:
|
|
67
|
+
[ "${#names[@]}" -gt 0 ] || return 0
|
|
68
|
+
echo "ERROR: AGENTS.override.md was not generated by intelligence-sync, but ${names[*]} need it: additional Codex rules and scoped-rule routing go there. Move its guidance into a rule, remove it, then sync." >&2
|
|
62
69
|
return 1
|
|
63
70
|
fi
|
|
64
71
|
fi
|
|
65
|
-
if [ "${#
|
|
72
|
+
if [ "${#names[@]}" -eq 0 ]; then
|
|
66
73
|
rm -f "$override"
|
|
67
74
|
return 0
|
|
68
75
|
fi
|
|
69
76
|
target_output_var "$config_file" "agents"
|
|
70
77
|
agents_output_path_var "${IS_TGT_OUTPUT:-.agents}"
|
|
71
78
|
agents_file="$repo_root/$IS_AGENTS_OUTPUT_PATH"
|
|
79
|
+
local routes="" rows path patterns link
|
|
80
|
+
if [ "${#scoped[@]}" -gt 0 ]; then
|
|
81
|
+
rows="$(frontmatter_index 'paths[]' "${scoped[@]}")" || return 1
|
|
82
|
+
i=0
|
|
83
|
+
while IFS=$'\x1f' read -r path patterns; do
|
|
84
|
+
repo_rel_link_var "$repo_root" "$path"
|
|
85
|
+
# The override is ignored: external sources may use their real path.
|
|
86
|
+
link="${IS_REPO_REL:-$path}"
|
|
87
|
+
routes+="- \`${patterns:-[]}\` → [${scoped_names[i]}](<$link>)"$'\n'
|
|
88
|
+
i=$((i + 1))
|
|
89
|
+
done <<< "$rows"
|
|
90
|
+
fi
|
|
72
91
|
{
|
|
73
92
|
if [ -f "$agents_file" ]; then
|
|
74
93
|
cat "$agents_file"
|
|
@@ -79,13 +98,18 @@ sync_codex_override() {
|
|
|
79
98
|
echo ""
|
|
80
99
|
echo "## Codex Project Context"
|
|
81
100
|
echo ""
|
|
82
|
-
echo "<!--
|
|
101
|
+
echo "<!-- Codex reads this file instead of AGENTS.md. -->"
|
|
83
102
|
echo ""
|
|
84
|
-
|
|
103
|
+
if [ -n "$routes" ]; then
|
|
104
|
+
echo "Before working on files matching these repo-relative patterns, read and follow the linked rules. Apply each only within its scope."
|
|
105
|
+
echo ""
|
|
106
|
+
printf '%s\n' "$routes"
|
|
107
|
+
fi
|
|
108
|
+
[ "${#files[@]}" -eq 0 ] || emit_rule_bodies "${files[@]}"
|
|
85
109
|
} > "$override"
|
|
86
110
|
finalize_output_file "$override"
|
|
87
111
|
for ((i = 0; i < ${#names[@]}; i++)); do
|
|
88
|
-
echo " rule: ${names[i]} (
|
|
112
|
+
echo " rule: ${names[i]} (AGENTS.override.md)"
|
|
89
113
|
done
|
|
90
114
|
echo " -> AGENTS.override.md"
|
|
91
115
|
}
|
package/engine/lib/common.sh
CHANGED
|
@@ -217,7 +217,9 @@ source_name_map_var() {
|
|
|
217
217
|
# unit separator — never present in frontmatter values). Value semantics are
|
|
218
218
|
# get_frontmatter_value's exactly: first frontmatter block only, first key
|
|
219
219
|
# occurrence wins, first-colon split, symmetric quote strip. The special key
|
|
220
|
-
# `paths#` yields the has_paths count
|
|
220
|
+
# `paths#` yields the has_paths count; `paths[]` folds the first paths list
|
|
221
|
+
# into one display value, preserving YAML quotes and inline list syntax.
|
|
222
|
+
# A file without
|
|
221
223
|
# frontmatter (or an empty file) still gets a row, with empty values.
|
|
222
224
|
frontmatter_index() {
|
|
223
225
|
local keys="$1"
|
|
@@ -235,7 +237,7 @@ frontmatter_index() {
|
|
|
235
237
|
store()
|
|
236
238
|
cur = FILENAME
|
|
237
239
|
for (ri = 1; ri <= nk; ri++) { V[ri] = (K[ri] == "paths#") ? 0 : ""; delete SEEN[ri] }
|
|
238
|
-
in_fm = 0; fm_done = 0
|
|
240
|
+
in_fm = 0; fm_done = 0; paths_list = 0
|
|
239
241
|
}
|
|
240
242
|
{ sub(/\r$/, "") }
|
|
241
243
|
FNR == 1 && $0 == "---" { in_fm = 1; next }
|
|
@@ -243,12 +245,29 @@ frontmatter_index() {
|
|
|
243
245
|
in_fm && !fm_done && $0 == "---" { fm_done = 1; next }
|
|
244
246
|
fm_done || !in_fm { next }
|
|
245
247
|
{
|
|
248
|
+
if (paths_list && /^[[:space:]]*#/) next
|
|
249
|
+
if (paths_list && (/^[[:space:]]+/ || /^-[[:space:]]+/ || /^\]/)) {
|
|
250
|
+
item = $0
|
|
251
|
+
sub(/^[[:space:]]*/, "", item)
|
|
252
|
+
sub(/^-[[:space:]]+/, "", item)
|
|
253
|
+
if (item != "" && item !~ /^#/) {
|
|
254
|
+
for (ki = 1; ki <= nk; ki++)
|
|
255
|
+
if (K[ki] == "paths[]") V[ki] = V[ki] (V[ki] == "" ? "" : " ") item
|
|
256
|
+
}
|
|
257
|
+
next
|
|
258
|
+
}
|
|
259
|
+
if ($0 !~ /^[[:space:]]*$/) paths_list = 0
|
|
246
260
|
idx = index($0, ":")
|
|
247
261
|
if (idx == 0) next
|
|
248
262
|
k = substr($0, 1, idx - 1)
|
|
249
263
|
for (ki = 1; ki <= nk; ki++) {
|
|
250
264
|
if (K[ki] == "paths#") {
|
|
251
265
|
if (k == "paths") V[ki]++
|
|
266
|
+
} else if (K[ki] == "paths[]" && k == "paths" && !(ki in SEEN)) {
|
|
267
|
+
SEEN[ki] = 1
|
|
268
|
+
V[ki] = substr($0, idx + 1)
|
|
269
|
+
sub(/^[[:space:]]+/, "", V[ki])
|
|
270
|
+
paths_list = 1
|
|
252
271
|
} else if (k == K[ki] && !(ki in SEEN)) {
|
|
253
272
|
SEEN[ki] = 1
|
|
254
273
|
V[ki] = fm_value_strip(substr($0, idx + 1))
|
|
@@ -2767,7 +2786,7 @@ source_catalog_check_local() {
|
|
|
2767
2786
|
# A project adapter's channels are its own business: it has one.
|
|
2768
2787
|
builtin_has_channel() {
|
|
2769
2788
|
case "$1:$2" in
|
|
2770
|
-
opencode:always|opencode:scoped
|
|
2789
|
+
opencode:always|opencode:scoped) return 1 ;;
|
|
2771
2790
|
esac
|
|
2772
2791
|
return 0
|
|
2773
2792
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainova-systems/intelligence",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.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"
|
|
@@ -187,7 +187,7 @@ Use the engine library instead of copying parsers or file-handling logic.
|
|
|
187
187
|
| `read_yaml_list(config, section)` | Stream entries from `sources.<section>`, package references as their store paths. |
|
|
188
188
|
| `load_yaml_list(config, section)` | Same list into `IS_YAML_LIST`, cached — no subprocess on repeat reads. |
|
|
189
189
|
| `get_frontmatter_value(key, file)` | Read a scalar from the first frontmatter block. |
|
|
190
|
-
| `frontmatter_index(keys, file...)` | Read several frontmatter scalars for many files in one pass (`\x1f`-separated rows;
|
|
190
|
+
| `frontmatter_index(keys, file...)` | Read several frontmatter scalars for many files in one pass (`\x1f`-separated rows; `paths#` counts `paths:` lines, `paths[]` folds a paths list for display). |
|
|
191
191
|
| `has_frontmatter(file)` / `has_paths(file)` | Inspect source shape. |
|
|
192
192
|
| `strip_frontmatter(file)` | Emit the body without its first frontmatter block. |
|
|
193
193
|
| `get_model(config, tool, tier)` | Resolve a `frontier`, `heavy`, `standard` or `light` model, including manifest overrides. |
|
|
@@ -223,11 +223,13 @@ Intelligence routes always-on rules once through `AGENTS.md` for tools that cons
|
|
|
223
223
|
| `claude` | Copy | Copy | Copy with `paths:` preserved |
|
|
224
224
|
| `cursor` | Omit; reads `AGENTS.md` | `.mdc` with `alwaysApply: true` | `.mdc` with `globs:` |
|
|
225
225
|
| `copilot` | Omit; reads `AGENTS.md` | `.instructions.md` with `applyTo: "**"` | `.instructions.md` with `applyTo:` |
|
|
226
|
-
| `codex` | Omit; reads `AGENTS.md` | `AGENTS.override.md`: all of `AGENTS.md` plus these rules |
|
|
226
|
+
| `codex` | Omit; reads `AGENTS.md` | `AGENTS.override.md`: all of `AGENTS.md` plus these rules | Compact patterns and source links in `AGENTS.override.md`; read on demand |
|
|
227
227
|
| `pi` | Omit; reads `AGENTS.md` | Added to the system prompt by the generated extension | Generated on-demand files and extension |
|
|
228
228
|
| `opencode` | Omit; reads `AGENTS.md` | No channel; sync warns | No native channel |
|
|
229
229
|
|
|
230
|
-
Codex reads `AGENTS.override.md` instead of `AGENTS.md` in the same directory, so the Codex adapter writes
|
|
230
|
+
Codex reads `AGENTS.override.md` instead of `AGENTS.md` in the same directory, so the Codex adapter writes the whole rendered `AGENTS.md`, a compact scoped-rule index, and any additional always-on rules into that override. It exists while either kind needs it. Its contract manages and ignores the path; a file there that Intelligence did not generate is never touched, and a render that needs the path refuses until it is moved.
|
|
231
|
+
|
|
232
|
+
The scoped index pairs source `paths:` patterns with source links and asks Codex to read matching rules before working on files. Local and targeted rules follow the same source filtering as other output. This is model-followed guidance, not a native glob matcher; it creates no nested `AGENTS.md` files and leaves other tools' instruction channels unchanged. Checked 2026-10-23 against OpenAI's [instruction discovery documentation](https://learn.chatgpt.com/docs/agent-configuration/agents-md): startup discovery walks from the project root to the working directory, and an override replaces the base file in the same directory. Restart Codex after syncing updated instructions.
|
|
231
233
|
|
|
232
234
|
If a new adapter relies on `AGENTS.md` for always-on rules, its target must require `agents`. Add that invariant to `engine/sync.sh` when contributing the adapter upstream.
|
|
233
235
|
|
|
@@ -279,13 +279,13 @@ Rule content in Markdown.
|
|
|
279
279
|
|
|
280
280
|
| Source rule | Claude | Cursor | Antigravity | Copilot | Codex / Pi / OpenCode / `AGENTS.md` |
|
|
281
281
|
|---|---|---|---|---|---|
|
|
282
|
-
| Scoped | copied with `paths:` | `.mdc` with `globs:` | `.md` with `trigger: glob` and `globs:` | `.instructions.md` with `applyTo:` | listed in `AGENTS.md`; Pi
|
|
282
|
+
| Scoped | copied with `paths:` | `.mdc` with `globs:` | `.md` with `trigger: glob` and `globs:` | `.instructions.md` with `applyTo:` | listed in `AGENTS.md`; Codex gets routing in its override; Pi gets on-demand files and an extension |
|
|
283
283
|
| Always-on | copied | omitted | omitted | omitted | inlined once into `AGENTS.md` |
|
|
284
284
|
| Always-on, not in `AGENTS.md` | copied | `.mdc` with `alwaysApply: true` | `.md` with `trigger: always_on` | `.instructions.md` with `applyTo: "**"` | Codex: `AGENTS.override.md`; Pi: added to the system prompt by its extension; OpenCode: none |
|
|
285
285
|
|
|
286
|
-
Cursor, Copilot, Codex, Pi, OpenCode and Antigravity consume `AGENTS.md`, so always-on rules are not duplicated in their tool-specific channels. Claude does not consume `AGENTS.md`, so it receives the full rule set.
|
|
286
|
+
Cursor, Copilot, Codex, Pi, OpenCode and Antigravity consume `AGENTS.md`, so always-on rules are not duplicated in their tool-specific channels. Claude does not consume `AGENTS.md`, so it receives the full rule set. Codex's override lists scoped patterns and source links with an instruction to read matching rules on demand; this depends on the model following the instruction, not native glob-triggered loading. OpenCode users may configure `instructions:` globs themselves. See [adapter routing](adapters.md#rules) for delivery details.
|
|
287
287
|
|
|
288
|
-
An always-on rule `AGENTS.md` does not carry — a local one, or one whose set leaves `agents` out (see [Selecting adapters](#selecting-adapters)) — reaches each tool in its set through that tool's own channel instead, the last row. Codex reads `AGENTS.override.md` instead of `AGENTS.md` in the same directory, so the file holds the whole `AGENTS.md` plus
|
|
288
|
+
An always-on rule `AGENTS.md` does not carry — a local one, or one whose set leaves `agents` out (see [Selecting adapters](#selecting-adapters)) — reaches each tool in its set through that tool's own channel instead, the last row. Codex reads `AGENTS.override.md` instead of `AGENTS.md` in the same directory, so the file holds the whole `AGENTS.md` plus scoped routing and additional always-on rules; it is ignored, exists while either needs it, and one Intelligence did not generate is never touched. Antigravity's `trigger: always_on` belongs to the same undocumented key family as its `trigger: glob`. OpenCode reads instructions only from `AGENTS.md` or its committed `opencode.json`, so it can receive neither a local nor a tool-targeted always-on rule.
|
|
289
289
|
|
|
290
290
|
Keep always-on rules small. Put narrow framework or component guidance behind `paths:` so unrelated tasks do not pay its context cost.
|
|
291
291
|
|