@ainova-systems/intelligence 0.20.0 → 0.22.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/commands/sync.sh +9 -0
- package/cli/internal/check.sh +39 -0
- package/cli/lib/gitignore.sh +19 -2
- package/cli/lib/sync-lock.sh +103 -21
- 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-plugin/.claude-plugin/plugin.json +6 -0
- package/engine/adapters/claude-plugin/README.md +14 -0
- package/engine/adapters/claude-plugin/hooks/hooks.json +3 -0
- package/engine/adapters/claude-plugin/hooks/register.js +324 -0
- package/engine/adapters/claude.sh +129 -59
- package/engine/adapters/codex.sh +74 -15
- package/engine/adapters/copilot.sh +56 -79
- 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 +753 -56
- package/engine/lib/contract.sh +15 -6
- package/engine/sync.sh +49 -33
- package/package.json +1 -1
- package/packages/sync/references/adapters.md +56 -40
- 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
package/engine/lib/contract.sh
CHANGED
|
@@ -100,18 +100,27 @@ is_status() {
|
|
|
100
100
|
fi
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
# engine_root_var — set IS_ENGINE_ROOT to the engine directory, one level above
|
|
104
|
+
# this lib. A project adapter that overrides a built-in finds the engine's own
|
|
105
|
+
# files through it, never beside itself.
|
|
106
|
+
engine_root_var() {
|
|
107
|
+
local lib="${BASH_SOURCE[0]}"
|
|
108
|
+
case "$lib" in
|
|
109
|
+
*/*) lib="${lib%/*}" ;;
|
|
110
|
+
*) lib="." ;;
|
|
111
|
+
esac
|
|
112
|
+
IS_ENGINE_ROOT="$lib/.."
|
|
113
|
+
}
|
|
114
|
+
|
|
103
115
|
# Engine version = VERSION one level above this lib (BASH_SOURCE works when
|
|
104
116
|
# sourced). Empty if unreadable — callers treat empty as "no guard".
|
|
105
117
|
# engine_version_var sets IS_ENGINE_VERSION, and IS_ENGINE_VERSION_FOUND=1 when
|
|
106
118
|
# the file exists; it reads the file once per process.
|
|
107
119
|
engine_version_var() {
|
|
108
120
|
[ -z "${IS_ENGINE_VERSION_FOUND:-}" ] || return 0
|
|
109
|
-
local
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
*) lib="." ;;
|
|
113
|
-
esac
|
|
114
|
-
vf="$lib/../VERSION"
|
|
121
|
+
local vf content=""
|
|
122
|
+
engine_root_var
|
|
123
|
+
vf="$IS_ENGINE_ROOT/VERSION"
|
|
115
124
|
IS_ENGINE_VERSION=""
|
|
116
125
|
IS_ENGINE_VERSION_FOUND=0
|
|
117
126
|
[ -f "$vf" ] || return 0
|
package/engine/sync.sh
CHANGED
|
@@ -115,40 +115,17 @@ done <<< "${IS_YL_UNRESOLVED:-}"
|
|
|
115
115
|
|
|
116
116
|
|
|
117
117
|
# Sources stay read-only for the whole run (validate_output_path refuses an
|
|
118
|
-
# output inside one), so
|
|
119
|
-
#
|
|
120
|
-
#
|
|
121
|
-
#
|
|
122
|
-
#
|
|
123
|
-
#
|
|
118
|
+
# output inside one), so the source catalog is built once, in this shell, and
|
|
119
|
+
# every renderer replays it: AGENTS.md, every adapter, the shared skill
|
|
120
|
+
# directory and the context report read sources through source_artifacts_var
|
|
121
|
+
# (decision 0021). Building it names every artifact, settles which of a name
|
|
122
|
+
# renders, refuses ambiguous names before any output is touched, settles every
|
|
123
|
+
# symlink in a skills source (decision 0017), and lints the frontmatter of every
|
|
124
|
+
# source — skills as the inventory renders them: SKILL.md behind a link inside
|
|
125
|
+
# its source is linted, one that leaves its source is never read.
|
|
124
126
|
# shellcheck disable=SC2034 # read by read_source_artifact_files in lib/common.sh
|
|
125
127
|
IS_SOURCE_FILES_MEMO=1
|
|
126
|
-
|
|
127
|
-
read_source_artifact_files "$REPO_ROOT" "$CONFIG_FILE" "$section"
|
|
128
|
-
done
|
|
129
|
-
|
|
130
|
-
# Lint frontmatter across all source files (rules, agents, skills).
|
|
131
|
-
# Catches issues like unquoted colons that strict YAML consumers reject.
|
|
132
|
-
# Skills are the rendered ones the pass above settled: SKILL.md behind a link
|
|
133
|
-
# inside its source is linted, one that leaves its source is never read.
|
|
134
|
-
LINT_FILES=()
|
|
135
|
-
LINT_SKILLS=()
|
|
136
|
-
[ "${#IS_SOURCE_FILES[@]}" -eq 0 ] || LINT_SKILLS=("${IS_SOURCE_FILES[@]}")
|
|
137
|
-
for section in rules agents; do
|
|
138
|
-
load_yaml_list "$CONFIG_FILE" "$section"
|
|
139
|
-
while IFS= read -r src; do
|
|
140
|
-
[ -z "$src" ] && continue
|
|
141
|
-
src_dir="$REPO_ROOT/$src"
|
|
142
|
-
[ -d "$src_dir" ] || continue
|
|
143
|
-
for f in "$src_dir"/*.md; do
|
|
144
|
-
[ -f "$f" ] && LINT_FILES+=("$f")
|
|
145
|
-
done
|
|
146
|
-
done <<< "$IS_YAML_LIST"
|
|
147
|
-
done
|
|
148
|
-
[ "${#LINT_SKILLS[@]}" -eq 0 ] || LINT_FILES+=("${LINT_SKILLS[@]}")
|
|
149
|
-
if [ "${#LINT_FILES[@]}" -gt 0 ]; then
|
|
150
|
-
lint_frontmatter_files "${LINT_FILES[@]}"
|
|
151
|
-
fi
|
|
128
|
+
source_catalog_build "$REPO_ROOT" "$CONFIG_FILE" lint
|
|
152
129
|
|
|
153
130
|
# Adapters come from two places, discovered by filename (minus `.sh`,
|
|
154
131
|
# `_template` excluded):
|
|
@@ -189,6 +166,11 @@ for adapters_dir in "$SCRIPT_DIR/adapters" "$INTELLIGENCE_DIR/adapters"; do
|
|
|
189
166
|
done
|
|
190
167
|
done
|
|
191
168
|
|
|
169
|
+
# A `targets:` or `exclude_targets:` id must name an adapter this project has,
|
|
170
|
+
# enabled or not, or the group `committed` (decision 0021). Refused here,
|
|
171
|
+
# before anything is snapshotted or written.
|
|
172
|
+
source_catalog_check_ids "$REPO_ROOT" "${ADAPTERS[*]}" || exit 1
|
|
173
|
+
|
|
192
174
|
# Validate every selected adapter contract before any output is touched, then
|
|
193
175
|
# snapshot the declared write-set. If a later adapter fails, the EXIT handler
|
|
194
176
|
# restores all earlier adapter outputs so sync is atomic from the repository's
|
|
@@ -377,6 +359,20 @@ note_agents_dependent() {
|
|
|
377
359
|
}
|
|
378
360
|
SELECTED_RECORDS=()
|
|
379
361
|
RENDER_PARALLEL="$SYNC_PARALLEL"
|
|
362
|
+
# What a source may render into depends on Git policy only when the catalog
|
|
363
|
+
# holds a local artifact: then every contract is read with the manifest, which
|
|
364
|
+
# may choose that policy (targets.copilot.commit_output), and its ignore and
|
|
365
|
+
# include records become IS_COMMIT_POLICY. Every other sync reads ownership
|
|
366
|
+
# alone, as decision 0020 keeps it (decision 0021).
|
|
367
|
+
policy_manifest=""
|
|
368
|
+
[ "$IS_CAT_NEED_COMMITTED" != 1 ] || policy_manifest="$CONFIG_FILE"
|
|
369
|
+
IS_COMMIT_POLICY=""
|
|
370
|
+
# The tools that read .agents/skills/ and AGENTS.md, by their contracts: a
|
|
371
|
+
# skill lands in .agents/skills/ when it is for any of them, and a shared path
|
|
372
|
+
# that delivers an artifact to a tool outside its targets is named.
|
|
373
|
+
IS_OPEN_SKILLS_READERS=""
|
|
374
|
+
IS_AGENTS_READERS=""
|
|
375
|
+
IS_ENABLED_ADAPTERS=""
|
|
380
376
|
preflight_idx=0
|
|
381
377
|
while [ "$preflight_idx" -lt "${#ADAPTERS[@]}" ]; do
|
|
382
378
|
adapter="${ADAPTERS[$preflight_idx]}"
|
|
@@ -387,13 +383,26 @@ while [ "$preflight_idx" -lt "${#ADAPTERS[@]}" ]; do
|
|
|
387
383
|
target_output_var "$CONFIG_FILE" "$adapter"
|
|
388
384
|
output="$IS_TGT_OUTPUT"
|
|
389
385
|
[ -n "$output" ] || output=".$adapter"
|
|
390
|
-
records="$(adapter_contract_records "$adapter" "$adapter_file" "$output")" || exit 1
|
|
386
|
+
records="$(adapter_contract_records "$adapter" "$adapter_file" "$output" "$policy_manifest")" || exit 1
|
|
391
387
|
|
|
392
388
|
if ! adapter_claims_add_records "$adapter" "$records"; then
|
|
393
389
|
echo "ERROR: $IS_ADAPTER_CLAIM_CONFLICT." >&2
|
|
394
390
|
echo " Give each adapter its own output: intelligence adapter list" >&2
|
|
395
391
|
exit 1
|
|
396
392
|
fi
|
|
393
|
+
IS_ENABLED_ADAPTERS="$IS_ENABLED_ADAPTERS${IS_ENABLED_ADAPTERS:+ }$adapter"
|
|
394
|
+
while IFS=$'\t' read -r kind value; do
|
|
395
|
+
case "$kind" in
|
|
396
|
+
requires) [ "$value" != agents ] || IS_AGENTS_READERS="$IS_AGENTS_READERS${IS_AGENTS_READERS:+ }$adapter" ;;
|
|
397
|
+
ignore|include) IS_COMMIT_POLICY="$IS_COMMIT_POLICY$adapter"$'\t'"$kind"$'\t'"$value"$'\n' ;;
|
|
398
|
+
owned|managed)
|
|
399
|
+
adapter_contract_rel_path "$value"
|
|
400
|
+
if [ "$IS_ADAPTER_REL_PATH" = ".agents/skills" ]; then
|
|
401
|
+
IS_OPEN_SKILLS_READERS="$IS_OPEN_SKILLS_READERS${IS_OPEN_SKILLS_READERS:+ }$adapter"
|
|
402
|
+
fi
|
|
403
|
+
;;
|
|
404
|
+
esac
|
|
405
|
+
done <<< "$records"
|
|
397
406
|
|
|
398
407
|
if [ -n "$TARGET_FILTER" ] && [ "$adapter" != "$TARGET_FILTER" ]; then
|
|
399
408
|
# Not selected: its claims are registered, its output is not touched.
|
|
@@ -428,6 +437,13 @@ while [ "$preflight_idx" -lt "${#ADAPTERS[@]}" ]; do
|
|
|
428
437
|
esac
|
|
429
438
|
done <<< "$records"
|
|
430
439
|
done
|
|
440
|
+
# shellcheck disable=SC2034 # read by output_committed in lib/common.sh
|
|
441
|
+
[ -z "$policy_manifest" ] || IS_COMMIT_POLICY_SET=1
|
|
442
|
+
# A local artifact that names a committed output in its targets is refused
|
|
443
|
+
# before any adapter writes; then every shared path that delivers an artifact
|
|
444
|
+
# beyond its targets, and every target no channel reaches, is named once.
|
|
445
|
+
source_catalog_check_local "$REPO_ROOT" || exit 1
|
|
446
|
+
source_catalog_warn "$REPO_ROOT"
|
|
431
447
|
|
|
432
448
|
# Every adapter that requires `agents` skips always-on rules because AGENTS.md
|
|
433
449
|
# carries them — and each of those tools reads AGENTS.md at the workspace root
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainova-systems/intelligence",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.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"
|
|
@@ -129,6 +129,17 @@ Code ignore theirs, and never `.github/` itself. `targets.copilot.commit_output:
|
|
|
129
129
|
true` keeps them tracked for Copilot on github.com; the setting is defined in
|
|
130
130
|
[Generated output and version control](conventions.md#generated-output-and-version-control).
|
|
131
131
|
|
|
132
|
+
The Claude adapter renders a Claude Code plugin into `<output>/skills/intelligence/`
|
|
133
|
+
when `targets.claude.plugin` is `true` (decision 0022): a mod that checks
|
|
134
|
+
`intelligence sync --check` at session start and every five minutes, shows the
|
|
135
|
+
verdict in a line above the prompt and runs sync from a button there or
|
|
136
|
+
`/intelligence sync`.
|
|
137
|
+
The template is `engine/adapters/claude-plugin/`, copied with the engine version
|
|
138
|
+
stamped into `plugin.json`. It lives inside the owned `skills` path, so it needs
|
|
139
|
+
no contract record of its own. The field's values, the name collision it refuses
|
|
140
|
+
and the plugin's limits are defined in the
|
|
141
|
+
[CLI reference](https://github.com/ainova-systems/intelligence/blob/main/docs/cli.md#intelligence-sync).
|
|
142
|
+
|
|
132
143
|
The engine calls:
|
|
133
144
|
|
|
134
145
|
```text
|
|
@@ -141,22 +152,26 @@ The engine has already loaded `engine/lib/common.sh` before it sources the adapt
|
|
|
141
152
|
|
|
142
153
|
`sources.rules`, `sources.agents` and `sources.skills` contain repo-relative directory paths. Packages have already been resolved, fetched and pinned by the CLI, so package content appears as an ordinary path under `.intelligence/packages/`. The manifest may name a package's directory by the package's full name or alias instead; `read_yaml_list` and `load_yaml_list` hand an adapter the store path either way, and leave out a reference that names nothing, so an adapter reads every source the same way. Adapters never perform network access or parse `packages:`.
|
|
143
154
|
|
|
144
|
-
|
|
155
|
+
Read a section through the source catalog, never with a glob of your own. `AGENTS.md`, every built-in adapter and the template read it the same way (decision 0021):
|
|
145
156
|
|
|
146
157
|
```bash
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
[
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
# transform file
|
|
155
|
-
done
|
|
156
|
-
done < <(read_yaml_list "$config_file" "rules")
|
|
158
|
+
output_rel_var "$repo_root" "$output_dir"
|
|
159
|
+
source_artifacts_var "$repo_root" "$config_file" rules mytool "$IS_OUTPUT_REL/rules/{}.md"
|
|
160
|
+
for ((i = 0; i < ${#IS_SOURCE_FILES[@]}; i++)); do
|
|
161
|
+
# IS_SOURCE_FILES[i] is the source, IS_SOURCE_NAMES[i] its rendered name,
|
|
162
|
+
# IS_SOURCE_SCOPED[i] is 1 for a rule with paths:
|
|
163
|
+
:
|
|
164
|
+
done
|
|
157
165
|
```
|
|
158
166
|
|
|
159
|
-
|
|
167
|
+
The last argument is the repository-relative path an artifact lands at, `{}` standing for its name. The catalog lists sources in manifest order and each directory's entries in byte order, and settles four things before any adapter runs:
|
|
168
|
+
|
|
169
|
+
- **Names.** An artifact is named by its file name without a leading `.`, `.md` and a trailing `.local`, a skill by its directory name without the leading `.` and `.local`: `.draft.md` renders as `draft`, `deploy.local/` as `deploy/`. Write each output under `IS_SOURCE_NAMES`, never under the source file name; `finalize_copy_named` and `copy_skill_bundle_dirs_named` take the `IS_SOURCE_NAME_MAP` the call leaves.
|
|
170
|
+
- **Overrides.** Of two artifacts with one name, only the later source's is listed. Package sources are wired before project sources, so project content overrides a package artifact by name. Two of one name in one directory, or a local and a non-local one anywhere, refuse the sync before any adapter runs.
|
|
171
|
+
- **Local artifacts.** A `*.local.md` rule or agent and a `*.local/` skill are listed only for an output path no `ignore` record of your contract covers — what Git tracks never holds one. That is why the path must be the real one: an adapter that globs sources itself, or names a path it does not write, can put a teammate's local file into a committed output.
|
|
172
|
+
- **Targets.** An artifact whose `targets:` leaves your adapter out, or whose `exclude_targets:` names it, is not listed for it; `committed` in either field is resolved against the path you pass ([Selecting adapters](conventions.md#selecting-adapters)). Your adapter's id is a valid target as soon as its file exists, and sync has removed both fields from every copy the shared helpers write; strip them from any frontmatter you copy yourself.
|
|
173
|
+
|
|
174
|
+
`IS_SOURCE_IN_AGENTS` is 1 when `AGENTS.md` carries the artifact too. An adapter whose tool reads `AGENTS.md` renders an always-on rule only where it is 0: that is a local rule, or one whose targets leave `agents` out, and the tool's own always-on channel is the only way it arrives.
|
|
160
175
|
|
|
161
176
|
## Shared functions
|
|
162
177
|
|
|
@@ -164,6 +179,10 @@ Use the engine library instead of copying parsers or file-handling logic.
|
|
|
164
179
|
|
|
165
180
|
| Function | Purpose |
|
|
166
181
|
|---|---|
|
|
182
|
+
| `source_artifacts_var(root, config, section, adapters, output)` | The artifacts of a section that render for one of `adapters` at `output` (`{}` is the name): `IS_SOURCE_FILES`, `IS_SOURCE_NAMES`, `IS_SOURCE_SCOPED`, `IS_SOURCE_IN_AGENTS`, `IS_SOURCE_NAME_MAP`. |
|
|
183
|
+
| `output_rel_var(root, output_dir)` | The output's repository-relative path in `IS_OUTPUT_REL`, as `source_artifacts_var` takes it. |
|
|
184
|
+
| `finalize_copy_named(dest, map, src...)` | Copy-and-finalize every source into `dest` under its rendered name, in one process. |
|
|
185
|
+
| `copy_skill_bundle_dirs_named(tool, dest_root, map, src...)` | `copy_skill_bundle_dirs_for` with each skill copied under its rendered name. |
|
|
167
186
|
| `resolve_source_dir(repo_root, source)` | Resolve a manifest source to its local directory. |
|
|
168
187
|
| `read_yaml_list(config, section)` | Stream entries from `sources.<section>`, package references as their store paths. |
|
|
169
188
|
| `load_yaml_list(config, section)` | Same list into `IS_YAML_LIST`, cached — no subprocess on repeat reads. |
|
|
@@ -178,7 +197,6 @@ Use the engine library instead of copying parsers or file-handling logic.
|
|
|
178
197
|
| `copy_skill_bundle(src, dest)` | Copy `SKILL.md` and all resources safely, normalize Markdown, quote free-text frontmatter, and keep a valid `effort:` as written, as the shared skills tree does. |
|
|
179
198
|
| `copy_skill_bundle_dirs(dest_root, src...)` | Batch form: copy every skill directory into `dest_root/<name>` with one copy and one finalize pass. |
|
|
180
199
|
| `copy_skill_bundle_dirs_for(tool, dest_root, src...)` | The batch form for a tree one tool reads: `SKILL.md`'s `effort:` becomes that tool's level, or is removed when it has none. |
|
|
181
|
-
| `skill_source_rendered(skill_dir)` | Whether sync renders a skill directory an adapter listed with its own glob; a skill left out for its symlinks fails it. |
|
|
182
200
|
| `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`. |
|
|
183
201
|
| `finalize_output_file(file)` | Expand layout tokens and normalize line endings; required for every emitted text file. |
|
|
184
202
|
| `finalize_output_files(file...)` / `finalize_copy_files(dest, src...)` | Batch forms: finalize in place, or copy-and-finalize into a directory, in one process. |
|
|
@@ -196,18 +214,20 @@ Prefer the batched forms inside per-file loops: a process spawn costs tens of mi
|
|
|
196
214
|
|
|
197
215
|
Rules without `paths:` are always-on. Rules with `paths:` are scoped.
|
|
198
216
|
|
|
199
|
-
Intelligence routes always-on rules once through `AGENTS.md` for tools that consume it. An adapter for such a tool should not copy those rules again. If the tool has a native scoped-rule channel, transform `paths:` to the tool's equivalent.
|
|
217
|
+
Intelligence routes always-on rules once through `AGENTS.md` for tools that consume it. An adapter for such a tool should not copy those rules again — except one `AGENTS.md` does not carry (`IS_SOURCE_IN_AGENTS` is 0), which reaches the tool only through its own always-on channel. If the tool has a native scoped-rule channel, transform `paths:` to the tool's equivalent.
|
|
200
218
|
|
|
201
|
-
| Built-in | Always-on rules | Scoped rules |
|
|
202
|
-
|
|
203
|
-
| `agents` | Inline in `AGENTS.md` | List with links |
|
|
204
|
-
| `antigravity` | Omit; reads `AGENTS.md` | `.agents/rules/*.md` with `trigger: glob` and `globs:` |
|
|
205
|
-
| `claude` | Copy | Copy with `paths:` preserved |
|
|
206
|
-
| `cursor` | Omit; reads `AGENTS.md` | `.mdc` with `globs:` |
|
|
207
|
-
| `copilot` | Omit; reads `AGENTS.md` | `.instructions.md` with `applyTo:` |
|
|
208
|
-
| `codex` | Omit; reads `AGENTS.md` | No native channel |
|
|
209
|
-
| `pi` | Omit; reads `AGENTS.md` | Generated on-demand files and extension |
|
|
210
|
-
| `opencode` | Omit; reads `AGENTS.md` | No native channel |
|
|
219
|
+
| Built-in | Always-on rules | Always-on, not in `AGENTS.md` | Scoped rules |
|
|
220
|
+
|---|---|---|---|
|
|
221
|
+
| `agents` | Inline in `AGENTS.md` | — | List with links |
|
|
222
|
+
| `antigravity` | Omit; reads `AGENTS.md` | `.agents/rules/*.md` with `trigger: always_on` | `.agents/rules/*.md` with `trigger: glob` and `globs:` |
|
|
223
|
+
| `claude` | Copy | Copy | Copy with `paths:` preserved |
|
|
224
|
+
| `cursor` | Omit; reads `AGENTS.md` | `.mdc` with `alwaysApply: true` | `.mdc` with `globs:` |
|
|
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 | No native channel |
|
|
227
|
+
| `pi` | Omit; reads `AGENTS.md` | Added to the system prompt by the generated extension | Generated on-demand files and extension |
|
|
228
|
+
| `opencode` | Omit; reads `AGENTS.md` | No channel; sync warns | No native channel |
|
|
229
|
+
|
|
230
|
+
Codex reads `AGENTS.override.md` instead of `AGENTS.md` in the same directory, so the Codex adapter writes it — the whole rendered `AGENTS.md`, then the rules only Codex receives — while such a rule exists, and removes it when none does. 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.
|
|
211
231
|
|
|
212
232
|
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.
|
|
213
233
|
|
|
@@ -242,7 +262,7 @@ copy_skill_bundle "$source_skill_dir" "$output_dir/skills/$skill_name"
|
|
|
242
262
|
|
|
243
263
|
Do not use plain `cp` for skill bundles. `copy_skill_bundle` preserves non-Markdown assets, normalizes Markdown, expands layout tokens and quotes `description` and `argument-hint` where strict YAML readers require strings. It renders `effort:` as the shared tree does; a tree only one tool reads uses `copy_skill_bundle_dirs_for <tool>`, so the copy carries that tool's level or no effort at all. It never writes a symlink; how a link in a skills source renders is defined in [conventions](conventions.md#skill-body-and-resources).
|
|
244
264
|
|
|
245
|
-
|
|
265
|
+
`source_artifacts_var ... skills` lists only the skills sync renders: one whose directory or `SKILL.md` is a link leaving its source is left out of every output, and sync has already warned about it once. Copy them with `copy_skill_bundle_dirs_named` and the call's `IS_SOURCE_NAME_MAP`, so `deploy.local/` lands as `deploy/`.
|
|
246
266
|
|
|
247
267
|
Antigravity, Codex, Pi and OpenCode share `.agents/skills/`. Any adapter writing that open-standard directory must call `sync_open_skill_dirs`; it is the single lifecycle owner for immediate skill subdirectories.
|
|
248
268
|
|
|
@@ -308,21 +328,16 @@ This example copies rules without frontmatter. A real adapter must decide how th
|
|
|
308
328
|
#!/bin/bash
|
|
309
329
|
|
|
310
330
|
sync_mytool_rules() {
|
|
311
|
-
local repo_root="$1" config_file="$2" output_dir="$3"
|
|
331
|
+
local repo_root="$1" config_file="$2" output_dir="$3" i out
|
|
312
332
|
mkdir -p "$output_dir/rules"
|
|
313
333
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
[
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
[ -f "$file" ] || continue
|
|
322
|
-
strip_frontmatter "$file" > "$output_dir/rules/$(basename "$file")"
|
|
323
|
-
finalize_output_file "$output_dir/rules/$(basename "$file")"
|
|
324
|
-
done
|
|
325
|
-
done < <(read_yaml_list "$config_file" "rules")
|
|
334
|
+
output_rel_var "$repo_root" "$output_dir"
|
|
335
|
+
source_artifacts_var "$repo_root" "$config_file" rules mytool "$IS_OUTPUT_REL/rules/{}.md"
|
|
336
|
+
for ((i = 0; i < ${#IS_SOURCE_FILES[@]}; i++)); do
|
|
337
|
+
out="$output_dir/rules/${IS_SOURCE_NAMES[i]}.md"
|
|
338
|
+
strip_frontmatter "${IS_SOURCE_FILES[i]}" > "$out"
|
|
339
|
+
finalize_output_file "$out"
|
|
340
|
+
done
|
|
326
341
|
}
|
|
327
342
|
|
|
328
343
|
adapter_contract_mytool() {
|
|
@@ -352,6 +367,7 @@ Verify:
|
|
|
352
367
|
|
|
353
368
|
- native file names, frontmatter and model/permission mappings;
|
|
354
369
|
- scoped and always-on routing without duplicated context;
|
|
370
|
+
- a dotfile or `*.local.md` source renders under its name, and a local one only into outputs the contract ignores;
|
|
355
371
|
- skill resources are present;
|
|
356
372
|
- no literal layout tokens remain;
|
|
357
373
|
- hand-authored siblings under the tool root survive;
|
|
@@ -368,9 +384,9 @@ For a built-in adapter, add the same assertions to the repository's smoke or lif
|
|
|
368
384
|
|---|---|
|
|
369
385
|
| `agents` | `AGENTS.md` |
|
|
370
386
|
| `antigravity` | `.agents/rules`, `.agents/agents`, `.agents/skills` |
|
|
371
|
-
| `claude` | `.claude/rules`, `.claude/agents`, `.claude/skills` |
|
|
387
|
+
| `claude` | `.claude/rules`, `.claude/agents`, `.claude/skills` (with `plugin: true`, `.claude/skills/intelligence` is the Claude Code plugin) |
|
|
372
388
|
| `cursor` | `.cursor/rules`, `.cursor/agents`, `.cursor/skills` |
|
|
373
389
|
| `copilot` | `.github/instructions`, `.github/agents`, `.github/skills` |
|
|
374
|
-
| `codex` | `.codex/agents`, `.agents/skills` |
|
|
390
|
+
| `codex` | `.codex/agents`, `.agents/skills`, marker-owned `AGENTS.override.md` |
|
|
375
391
|
| `pi` | `.pi/intelligence-sync`, `.pi/extensions`, `.pi/prompts`, `.agents/skills` |
|
|
376
392
|
| `opencode` | `.opencode/agents`, marker-owned `.opencode/commands`, `.agents/skills` |
|
|
@@ -73,7 +73,7 @@ sources:
|
|
|
73
73
|
|
|
74
74
|
A package's directory may also be named by the package instead of its store path: `@ainova-systems/sync/rules` names folder `rules` of the package `packages:` declares as `@ainova-systems/sync`, and `sync:rules` names it through the alias that package declares (`intelligence package alias @ainova-systems/sync sync`). Both render exactly as the store path, and both are installed package content like it: edit that content in its source repository. The CLI writes store paths and never rewrites a reference a person wrote; an `@scope/name/...` entry for a package `packages:` does not declare is an ordinary project path.
|
|
75
75
|
|
|
76
|
-
Missing project-owned source directories are skipped, so a package-only project need not create empty `rules/`, `agents/` or `skills/` directories. Source order matters:
|
|
76
|
+
Missing project-owned source directories are skipped, so a package-only project need not create empty `rules/`, `agents/` or `skills/` directories. Source order matters: of two artifacts with one name, the later source's renders everywhere, `AGENTS.md` included, and the earlier one renders nowhere (see [Artifact names](#artifact-names-and-local-artifacts)). Package sources are wired before project sources so the project can override a package artifact deliberately.
|
|
77
77
|
|
|
78
78
|
Project-owned entries are managed with `intelligence source add|remove|list` rather than by hand — it validates the path against the way the engine resolves it and prints the resulting order. `add` appends by default; `--before <entry>` / `--after <entry>` place content that should behave like a package ahead of the project's own directories.
|
|
79
79
|
|
|
@@ -164,6 +164,41 @@ Common skill verbs:
|
|
|
164
164
|
|
|
165
165
|
The verb describes the outcome, not whether the skill implements the work or delegates to another command or skill.
|
|
166
166
|
|
|
167
|
+
## Artifact names and local artifacts
|
|
168
|
+
|
|
169
|
+
An artifact's name is its file name without a leading `.`, `.md` and a trailing `.local`; a skill's is its directory name without the leading `.` and the trailing `.local`. `backend.md`, `.backend.md` and `backend.local.md` are all the rule `backend`, `deploy.local/` is the skill `deploy`, and every generated copy carries the name: `.claude/rules/backend.md`, `.cursor/rules/backend.mdc`, `.claude/skills/deploy/`. A leading dot means nothing — a dotfile source renders like any other.
|
|
170
|
+
|
|
171
|
+
Names stay unique. Across sources the later source's artifact renders and the earlier one does not, in `AGENTS.md` as in every tool's output; a skill a later source overrides is replaced whole, resources included. Sync refuses two artifacts with one name in one source directory (`backend.md` beside `.backend.md`), and a local and a non-local artifact with one name anywhere in the sources: a local file that overrode or yielded to a committed one would change what committed output holds.
|
|
172
|
+
|
|
173
|
+
A **local** artifact is personal or machine-specific guidance — the OS, the shell, a local service, a personal habit — that only this clone loads: a rule or agent named `*.local.md`, or a skill directory named `*.local/`. `intelligence init` writes the matching patterns, for the project's content directory, into its managed `.gitignore` block, so Git and sync agree on which files are local:
|
|
174
|
+
|
|
175
|
+
```gitignore
|
|
176
|
+
intelligence/rules/*.local.md
|
|
177
|
+
intelligence/agents/*.local.md
|
|
178
|
+
intelligence/skills/*.local/
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Sync renders a local artifact only into outputs Git ignores, and never into one it tracks: not `AGENTS.md`, not OpenCode's slash commands, not Copilot's output under `commit_output: true`. A clone without the file therefore renders the same committed files, and `intelligence sync --check` passes in CI. A local always-on rule reaches each tool through that tool's own always-on channel (see [Routing](#routing)), since `AGENTS.md` cannot carry it; OpenCode has none, and sync says so. `intelligence status --check` reports a missing pattern, and `intelligence init` restores it.
|
|
182
|
+
|
|
183
|
+
A pattern never applies to a file Git already tracks, and a source outside the content directory has no pattern at all. `intelligence status --check` therefore names every file with a local name that Git tracks in a project-owned source: rename it to share it, or `git rm --cached` it to keep it on this machine.
|
|
184
|
+
|
|
185
|
+
## Selecting adapters
|
|
186
|
+
|
|
187
|
+
Every rule, agent and skill renders to every enabled adapter. Two frontmatter fields narrow that, for guidance that matters to one tool or should cost no other tool context:
|
|
188
|
+
|
|
189
|
+
```yaml
|
|
190
|
+
---
|
|
191
|
+
targets: [claude, cursor] # only these adapters; without it, every enabled one
|
|
192
|
+
exclude_targets: [committed] # remove these from that set
|
|
193
|
+
---
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Both take adapter ids — built-in or the project's own — and the group `committed`: every output path Git tracks, resolved per path from each adapter's contract. `AGENTS.md` always belongs to it, and so do OpenCode's slash commands and, under `commit_output: true`, Copilot's output; OpenCode's agents and the shared `.agents/skills/` do not. Write them in the list syntax `paths:` takes — a flow list `[a, b]` or a block list — and in `SKILL.md` for a skill. `targets: []` renders the artifact nowhere. Sync removes both fields from every generated copy.
|
|
197
|
+
|
|
198
|
+
An id that names no adapter refuses the sync. An adapter that is not enabled is simply no target: enablement stays the manifest's decision. A local artifact excludes `committed` already, and one whose `targets` names a committed output — `agents`, `committed`, or an adapter all of whose output Git tracks — refuses the sync, because every other clone and CI render that output without it.
|
|
199
|
+
|
|
200
|
+
Two paths are shared, not per tool, and a filter can withhold an artifact from a shared path but never from one of its readers. An artifact whose set contains `agents` goes into `AGENTS.md` and reaches every tool that reads it. A skill whose set contains any reader of `.agents/skills/` — Antigravity, Codex, Pi, OpenCode — lands there for all of them. Sync prints a `WARNING:` line when a shared path delivers an artifact to an enabled adapter outside its set, and when an adapter in its set can receive it through no channel. An artifact with neither field nor a `.local` name keeps the routing, and the warnings, it always had.
|
|
201
|
+
|
|
167
202
|
## Agent conventions
|
|
168
203
|
|
|
169
204
|
```yaml
|
|
@@ -246,9 +281,12 @@ Rule content in Markdown.
|
|
|
246
281
|
|---|---|---|---|---|---|
|
|
247
282
|
| Scoped | copied with `paths:` | `.mdc` with `globs:` | `.md` with `trigger: glob` and `globs:` | `.instructions.md` with `applyTo:` | listed in `AGENTS.md`; Pi also gets on-demand files and an extension |
|
|
248
283
|
| Always-on | copied | omitted | omitted | omitted | inlined once into `AGENTS.md` |
|
|
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 |
|
|
249
285
|
|
|
250
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. OpenCode and Codex have no generated path-scoped rule channel; OpenCode users may configure `instructions:` globs themselves.
|
|
251
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 the rules only Codex receives; it is ignored, exists only while such a rule does, 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
|
+
|
|
252
290
|
Keep always-on rules small. Put narrow framework or component guidance behind `paths:` so unrelated tasks do not pay its context cost.
|
|
253
291
|
|
|
254
292
|
## Skill conventions
|
|
@@ -270,7 +308,7 @@ argument-hint: "<route-name>"
|
|
|
270
308
|
4. Report the changed route and verification.
|
|
271
309
|
```
|
|
272
310
|
|
|
273
|
-
Standard optional fields (`license`, `compatibility`, `metadata`, `allowed-tools`) and tool extensions pass through unchanged. A tool ignores fields it does not understand. `effort:` is the exception: sync renders it per tool, as [Effort mappings](#effort-mappings) describes.
|
|
311
|
+
Standard optional fields (`license`, `compatibility`, `metadata`, `allowed-tools`) and tool extensions pass through unchanged. A tool ignores fields it does not understand. `effort:` is the exception: sync renders it per tool, as [Effort mappings](#effort-mappings) describes. `targets:` and `exclude_targets:` select the adapters that receive the skill and are removed from every copy ([Selecting adapters](#selecting-adapters)).
|
|
274
312
|
|
|
275
313
|
`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:`.
|
|
276
314
|
|
|
@@ -338,12 +376,12 @@ Every line enters a finite context budget. Prefer subtraction, consolidation and
|
|
|
338
376
|
| Target | Rules | Skills | Agents |
|
|
339
377
|
|---|---|---|---|
|
|
340
378
|
| `agents` | Always-on inlined; scoped listed in `AGENTS.md` | Listed | Listed |
|
|
341
|
-
| Antigravity | `AGENTS.md` plus
|
|
379
|
+
| Antigravity | `AGENTS.md` plus `.agents/rules/*.md` | `.agents/skills/` | `.agents/agents/*.md` |
|
|
342
380
|
| Claude | `.claude/rules/` | `.claude/skills/` | `.claude/agents/` |
|
|
343
|
-
| Cursor |
|
|
344
|
-
| Copilot |
|
|
345
|
-
| Codex | `AGENTS.md`
|
|
346
|
-
| Pi | `AGENTS.md` plus scoped `.pi/intelligence-sync/rules/` | `.agents/skills/` | `.pi/prompts/intelligence-agent-*.md` |
|
|
381
|
+
| Cursor | `AGENTS.md` plus `.cursor/rules/*.mdc` | `.cursor/skills/` | `.cursor/agents/` |
|
|
382
|
+
| Copilot | `AGENTS.md` plus `.github/instructions/*.instructions.md` | `.github/skills/` | `.github/agents/` |
|
|
383
|
+
| Codex | `AGENTS.md`, or `AGENTS.override.md` while a rule needs it | `.agents/skills/` | `.codex/agents/*.toml` |
|
|
384
|
+
| Pi | `AGENTS.md` plus scoped `.pi/intelligence-sync/rules/` and its extension | `.agents/skills/` | `.pi/prompts/intelligence-agent-*.md` |
|
|
347
385
|
| OpenCode | `AGENTS.md` only | `.agents/skills/` plus slash commands | `.opencode/agents/*.md` |
|
|
348
386
|
|
|
349
387
|
`AGENTS.md` is regenerated by the `agents` adapter. Its optional static header is `targets.agents.header` in `intelligence.yaml`; generated rule, agent and skill sections follow it. Commit `AGENTS.md` when it is the project's shared canonical context.
|
|
@@ -354,7 +392,12 @@ By default, commit the manifest, lock, project-owned content and `AGENTS.md`. Ig
|
|
|
354
392
|
# CLI-managed package store
|
|
355
393
|
.intelligence/
|
|
356
394
|
|
|
357
|
-
# Local
|
|
395
|
+
# Local rules, agents and skills of the content directory stay on this machine
|
|
396
|
+
intelligence/rules/*.local.md
|
|
397
|
+
intelligence/agents/*.local.md
|
|
398
|
+
intelligence/skills/*.local/
|
|
399
|
+
|
|
400
|
+
# Root tool instructions migrate into project rules and stay ignored
|
|
358
401
|
CLAUDE.md
|
|
359
402
|
.cursorrules
|
|
360
403
|
GEMINI.md
|
|
@@ -374,6 +417,7 @@ GEMINI.md
|
|
|
374
417
|
.agents/rules/
|
|
375
418
|
.agents/agents/
|
|
376
419
|
.codex/agents/
|
|
420
|
+
AGENTS.override.md
|
|
377
421
|
|
|
378
422
|
# Generated Pi content
|
|
379
423
|
.pi/intelligence-sync/
|
|
@@ -430,9 +474,10 @@ than inferring contents from Git status.
|
|
|
430
474
|
move useful repository guidance from legacy root files such as `.cursorrules`
|
|
431
475
|
and instruction-bearing `CLAUDE.md` out of their quarantined backup copies and
|
|
432
476
|
into project-owned rules, then verify the generated tool output. Do not restore
|
|
433
|
-
the original root monolith.
|
|
434
|
-
|
|
435
|
-
|
|
477
|
+
the original root monolith. Genuinely machine-local guidance becomes a local
|
|
478
|
+
rule, agent or skill (see
|
|
479
|
+
[Artifact names and local artifacts](#artifact-names-and-local-artifacts)), not
|
|
480
|
+
a new root tool-specific file.
|
|
436
481
|
|
|
437
482
|
Before the first render, `intelligence init` preserves existing AI prompt paths
|
|
438
483
|
under `<content-dir>/_backup/`. Its `manifest.tsv` labels the snapshot
|
|
@@ -496,6 +541,7 @@ Callers capture the real code with `command || rc=$?`. Do not use `if ! command;
|
|
|
496
541
|
| `intelligence.yaml` | Manifest and schema contract | Tracked |
|
|
497
542
|
| `intelligence.lock` | Resolved package state | Tracked |
|
|
498
543
|
| `<content-dir>/{rules,agents,skills,adapters}/` | Project source of truth | Tracked |
|
|
544
|
+
| `<content-dir>/{rules,agents}/*.local.md`, `<content-dir>/skills/*.local/` | Local artifacts, this clone only | Ignored |
|
|
499
545
|
| `.intelligence/` | Restorable package store | Ignored |
|
|
500
546
|
| `AGENTS.md` | Generated canonical project context | Normally tracked |
|
|
501
547
|
| Tool output directories | Generated native content | Built-in adapter-owned paths ignored; shared settings tracked |
|
|
@@ -47,7 +47,7 @@ Migrate meaning, not tool syntax:
|
|
|
47
47
|
|
|
48
48
|
| Existing format | Project-owned destination |
|
|
49
49
|
|---|---|
|
|
50
|
-
| Root `AGENTS.md`, `CLAUDE.md`, `.cursorrules`, Copilot root instructions | Split verified guidance by topic into rules;
|
|
50
|
+
| Root `AGENTS.md`, `CLAUDE.md`, `.cursorrules`, Copilot root instructions | Split verified guidance by topic into rules; move machine-local preferences into local rules (`<content-dir>/rules/<name>.local.md`), which Git ignores and sync keeps out of committed output |
|
|
51
51
|
| `.claude/rules/*.md` | Rule; preserve valid `paths:` |
|
|
52
52
|
| `.cursor/rules/*.mdc` | Rule; rename `globs:` to `paths:` and remove `alwaysApply:` |
|
|
53
53
|
| Claude/Cursor/Copilot agents, Codex `.codex/agents/*.toml` | Agent; map native model/readonly/tool fields back to `tier:` and `access:`, and a native effort level (`effort:`, `model_reasoning_effort`) back to `effort:` |
|
|
@@ -64,9 +64,9 @@ Obtain approval per `CREATE`, `UPDATE`, `REMOVE`, or `KEEP` proposal. Apply
|
|
|
64
64
|
project-owned source changes first, then run `intelligence sync` and
|
|
65
65
|
`intelligence status --check`. Inspect the enabled targets to prove the
|
|
66
66
|
migrated guidance arrived and verify quarantined old root instructions remain
|
|
67
|
-
absent.
|
|
68
|
-
|
|
69
|
-
original instruction monolith.
|
|
67
|
+
absent. A separately approved, genuinely machine-local subset becomes a local
|
|
68
|
+
rule, `<content-dir>/rules/<name>.local.md`, not a new root tool file; never
|
|
69
|
+
restore the original instruction monolith.
|
|
70
70
|
|
|
71
71
|
For every removed or renamed path, search all tracked files with `git ls-files`
|
|
72
72
|
and report remaining references with file and line number. Apply an unambiguous
|
|
@@ -48,13 +48,13 @@ The mistakes that actually happen, in order of frequency:
|
|
|
48
48
|
|
|
49
49
|
## Rules
|
|
50
50
|
|
|
51
|
-
**Scope with `paths:`.** A rule without `paths:` is loaded into *every* session and inlined into `AGENTS.md` — the most expensive context real estate there is. Earn it. A rule that only matters when someone touches the frontend belongs scoped to the frontend.
|
|
51
|
+
**Scope with `paths:`.** A rule without `paths:` is loaded into *every* session and inlined into `AGENTS.md` — the most expensive context real estate there is. Earn it. A rule that only matters when someone touches the frontend belongs scoped to the frontend. Guidance about one tool belongs to that tool: `targets: [claude]` keeps it out of every other tool's context. A rule whose targets leave `agents` out also leaves `AGENTS.md`, and sync names any tool that can then no longer receive it.
|
|
52
52
|
|
|
53
53
|
**Lead with the positive default, then the invariant.** The model acts on the first instruction it reads, and it follows whatever is named — negation ("never do X") draws attention to X. Reserve absolute language (NEVER, MUST) for true must-nots: safety, security, output format. A judgement call written as a NEVER only teaches the model that NEVERs are negotiable.
|
|
54
54
|
|
|
55
55
|
**Derive from the code, not from prose that already exists.** Every REQUIRED and every invariant must be backed by something observed in the repository. Documentation is a claim, not evidence — read the file.
|
|
56
56
|
|
|
57
|
-
**Describe the repository, not a machine.** The OS, the shell, the editor, a local dev stack, personal tooling — these are environment facts. They belong in a
|
|
57
|
+
**Describe the repository, not a machine.** The OS, the shell, the editor, a local dev stack, personal tooling — these are environment facts. They belong in a local rule, `<content-dir>/rules/<name>.local.md`: Git ignores it, and sync renders it only into outputs Git ignores. A rule is committed and read by everyone, so a shell-specific command or an absolute local path in it is simply wrong for whoever is on another platform.
|
|
58
58
|
|
|
59
59
|
**Explain the why — but only a why you can back.** A reason the reader can check is what makes an instruction survive a judgement call. An invented reason is worse than none: it sounds like evidence.
|
|
60
60
|
|
|
@@ -59,9 +59,10 @@ mechanics; this skill supplies repository judgement.
|
|
|
59
59
|
Treat backed-up legacy root instructions such as `.cursorrules` and an
|
|
60
60
|
instruction-bearing `CLAUDE.md` as migration sources, not permanent parallel
|
|
61
61
|
entry points. Move still-valid shared guidance into project-owned rules; do
|
|
62
|
-
not restore the original monolith.
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
not restore the original monolith. Approved machine-local guidance becomes a
|
|
63
|
+
local rule, `<content-dir>/rules/<name>.local.md`, which Git ignores and sync
|
|
64
|
+
keeps out of committed output. `AGENTS.md` remains the shared root
|
|
65
|
+
instruction entry point.
|
|
65
66
|
|
|
66
67
|
Review `.gitignore` and every existing `.vscodeignore`, `.npmignore`, and
|
|
67
68
|
`.dockerignore` against the CLI-managed policy. Detect tracked files which
|
|
@@ -95,8 +96,9 @@ explains itself well.
|
|
|
95
96
|
relevant generated `AGENTS.md`, Cursor rules, Claude rules, and any
|
|
96
97
|
packaging/build file list affected by ignore policy. Verify quarantined
|
|
97
98
|
legacy root entry points remain absent. If the user approved a genuinely
|
|
98
|
-
machine-local exception,
|
|
99
|
-
|
|
99
|
+
machine-local exception, write only that content to a local rule
|
|
100
|
+
(`<content-dir>/rules/<name>.local.md`); never copy the backed-up monolith
|
|
101
|
+
back. Completion requires
|
|
100
102
|
`IS_STATUS=ok`, a clean final check, and no `onboarding is pending` header
|
|
101
103
|
after accepted migration.
|
|
102
104
|
11. Report what was created, updated, removed, or deliberately kept. Remind the
|
|
@@ -9,7 +9,7 @@ Apply these checks to the source groups resolved by the review skill.
|
|
|
9
9
|
| **Over the cap** | `SKILL.md` over 1000 lines, rule over 500, agent over 200 | `SPLIT` — two artifacts, or move detail into `references/<topic>.md` |
|
|
10
10
|
| **Shared instruction budget** | The measured shared agents output, or `agents-md` in sync's `CONTEXT:` summary, is over 32 KiB (32,768 bytes) | `COMPACT` — this is Intelligence's recommended maximum, not an adapter rejection threshold; use the compaction procedure in `intelligence-review-context` to reduce the owning sources without teaching terse output |
|
|
11
11
|
| **Rule links to a rule** | A markdown link from one rule to another (`R1`) | `UNLINK` — name the rule instead: always-on rules are inlined into `AGENTS.md` and the scoped channels carry only scoped rules, so the link is dead in at least one output |
|
|
12
|
-
| **Machine facts in a rule** | OS, shell, editor or a local absolute path (`R2`) | `MOVE` — these belong in a
|
|
12
|
+
| **Machine facts in a rule** | OS, shell, editor or a local absolute path (`R2`) | `MOVE` — these belong in a local rule, `<content-dir>/rules/<name>.local.md`, which Git ignores and sync keeps out of committed output; a rule is committed and read by everyone, including whoever is on another platform |
|
|
13
13
|
| **Literal path or command in a skill** | A path *outside the skill's own folder* baked into a procedure (`R3`) | `PARAMETERIZE` — a skill is *executed*, so a literal path breaks the moment the layout moves; resolve it from a rule or from `<manifest>`. **Exempt:** the skill's own bundle (`references/`, `scripts/`, `assets/` — content is co-located with its skill by default); rules and agents (describing the repository is their job); an example inside an output-format block; the resolution step itself |
|
|
14
14
|
| **Skill with no verification** | Nothing at the end proves the procedure worked (`R4`) | `FLAG` — a procedure that proves nothing is a note, or just the work: give it a verification, or delete it |
|
|
15
15
|
| **Pressure marker** | A heading or section named CRITICAL / MANDATORY / HARD RULE / READ FIRST, or a density of `MUST` / `NEVER` / `ALWAYS` with no reason beside it (`R5`) | `REWRITE` - plain heading, one reason per constraint; when several instructions are each marked critical the marker stops carrying information, so keep emphasis for the one instruction demonstrably under-weighted without it |
|
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
Architecture, Build and test, Examples, and Patterns to recognize and replace.
|
|
14
14
|
Keep reasons that guide judgment and reference real examples. An accepted
|
|
15
15
|
user preference is identified as a preference, not a claim about existing code.
|
|
16
|
+
5. Guidance that belongs to one machine or one person — the OS, the shell, a
|
|
17
|
+
local service, a personal habit — goes in a local rule,
|
|
18
|
+
`<content-dir>/rules/<name>.local.md`. Git ignores it, and sync renders it
|
|
19
|
+
only into outputs Git ignores, so it never reaches `AGENTS.md` or a teammate.
|
|
20
|
+
A local rule cannot share a name with a committed one.
|
|
16
21
|
|
|
17
22
|
For a scoped rule:
|
|
18
23
|
|