@ainova-systems/intelligence 0.11.0 → 0.11.2

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/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  **npm for AI agent intelligence.** One CLI that builds, versions and distributes the rules, agents and skills your AI coding tools run on — rendered natively for Claude Code, Cursor, GitHub Copilot, OpenAI Codex, Pi, OpenCode and `AGENTS.md`.
4
4
 
5
5
  ```bash
6
- npm install -g @ainova-systems/intelligence@next
6
+ npm install -g @ainova-systems/intelligence
7
7
 
8
8
  cd your-project
9
9
  intelligence init
@@ -12,6 +12,41 @@ source "$CLI_DIR/lib/cli-common.sh"
12
12
 
13
13
  targets_arg="" no_sync=0 content_dir="intelligence" bare=0
14
14
  targets_set=0 dir_set=0 bare_set=0 preview=0 apply=0 force=0
15
+ onboarding_tx_active=0 onboarding_tx_root="" onboarding_tx_content=""
16
+
17
+ onboarding_transaction_exit() {
18
+ local rc=$?
19
+ trap - EXIT
20
+ if [ "$onboarding_tx_active" -eq 1 ]; then
21
+ restore_onboarding_legacy_sources "$onboarding_tx_root" "$onboarding_tx_content"
22
+ fi
23
+ exit "$rc"
24
+ }
25
+
26
+ onboarding_transaction_begin() {
27
+ local tx_root="$1" tx_content="$2"
28
+ onboarding_quarantine_is_pending "$tx_root" "$tx_content" || return 0
29
+ onboarding_tx_root="$tx_root"
30
+ onboarding_tx_content="$tx_content"
31
+ onboarding_tx_active=1
32
+ trap onboarding_transaction_exit EXIT
33
+ quarantine_onboarding_legacy_sources "$tx_root" "$tx_content"
34
+ }
35
+
36
+ onboarding_transaction_rollback() {
37
+ trap - EXIT
38
+ if [ "$onboarding_tx_active" -eq 1 ]; then
39
+ restore_onboarding_legacy_sources "$onboarding_tx_root" "$onboarding_tx_content"
40
+ fi
41
+ onboarding_tx_active=0
42
+ }
43
+
44
+ onboarding_transaction_commit() {
45
+ local tx_root="$1" tx_content="$2"
46
+ complete_onboarding_quarantine "$tx_root" "$tx_content"
47
+ onboarding_tx_active=0
48
+ trap - EXIT
49
+ }
15
50
 
16
51
  print_new_project_onboarding() {
17
52
  local heading="Intelligence ready"
@@ -22,6 +57,9 @@ print_new_project_onboarding() {
22
57
  if [ -n "${ONBOARDING_BACKUP_REL:-}" ]; then
23
58
  echo " Existing AI instructions preserved:"
24
59
  echo " $ONBOARDING_BACKUP_REL ($ONBOARDING_BACKUP_COUNT path(s))"
60
+ if [ "${ONBOARDING_LEGACY_COUNT:-0}" -gt 0 ]; then
61
+ echo " Legacy root entry points were quarantined before the successful render."
62
+ fi
25
63
  if [ "$bare" -eq 0 ]; then
26
64
  echo " The learn skill will migrate them before proposing backup removal."
27
65
  else
@@ -115,11 +153,13 @@ case "$IP_MODE" in
115
153
  ensure_manifest_gitignore "$IP_ROOT" "$IP_ROOT/intelligence.yaml"
116
154
  ensure_manifest_publisher_ignores "$IP_ROOT" "$IP_ROOT/intelligence.yaml"
117
155
  [ "$no_sync" -eq 1 ] && exit 0
156
+ content_dir="$(manifest_intelligence_dir "$IP_ROOT/intelligence.yaml")"
157
+ onboarding_transaction_begin "$IP_ROOT" "$content_dir"
118
158
  cd "$IP_ROOT"
119
159
  sync_rc=0
120
160
  bash "$CLI_DIR/commands/sync.sh" || sync_rc=$?
121
161
  if [ "$sync_rc" -ne 0 ]; then
122
- content_dir="$(manifest_intelligence_dir "$IP_ROOT/intelligence.yaml")"
162
+ onboarding_transaction_rollback
123
163
  recovery_backup=""
124
164
  if [ -f "$IP_ROOT/$content_dir/_backup/manifest.tsv" ]; then
125
165
  recovery_backup="; initial backup: $content_dir/_backup/manifest.tsv"
@@ -131,6 +171,7 @@ case "$IP_MODE" in
131
171
  echo " $SYNC_PKG_STORE/skills/intelligence-learn-from-repository/SKILL.md" >&2
132
172
  echo " and finalize this Intelligence setup$recovery_backup." >&2
133
173
  fi
174
+ [ "$sync_rc" -ne 0 ] || onboarding_transaction_commit "$IP_ROOT" "$content_dir"
134
175
  [ "$sync_rc" -ne 0 ] || report_tracked_managed_ignores "$IP_ROOT" "$IP_ROOT/intelligence.yaml"
135
176
  exit "$sync_rc"
136
177
  ;;
@@ -313,6 +354,7 @@ ensure_manifest_publisher_ignores "$root" "$manifest"
313
354
  echo "initialized: intelligence.yaml (targets:$(printf ' %s' $targets))"
314
355
  [ "$bare" -eq 1 ] && echo " bare setup: no packages — engine meta-skills not installed"
315
356
  if [ "$no_sync" -eq 0 ]; then
357
+ onboarding_transaction_begin "$root" "$content_dir"
316
358
  cd "$root"
317
359
  sync_rc=0
318
360
  echo ""
@@ -320,6 +362,7 @@ if [ "$no_sync" -eq 0 ]; then
320
362
  echo " Rendering enabled adapters in compact mode..."
321
363
  bash "$CLI_DIR/commands/sync.sh" --compact || sync_rc=$?
322
364
  if [ "$sync_rc" -ne 0 ]; then
365
+ onboarding_transaction_rollback
323
366
  echo "" >&2
324
367
  echo "=== Intelligence setup needs recovery ===" >&2
325
368
  echo " No partial adapter update was kept; sync restored its pre-run outputs." >&2
@@ -332,6 +375,7 @@ if [ "$no_sync" -eq 0 ]; then
332
375
  fi
333
376
  exit "$sync_rc"
334
377
  fi
378
+ onboarding_transaction_commit "$root" "$content_dir"
335
379
  echo "=== Sync completed ==="
336
380
  fi
337
381
 
@@ -117,8 +117,17 @@ while IFS= read -r target; do
117
117
  || warn "adapter '$target' Git policy is missing '$value'"
118
118
  ;;
119
119
  include)
120
- grep -Fqx -- "!$value" "$IP_ROOT/.gitignore" 2>/dev/null \
121
- || warn "adapter '$target' Git policy is missing '!$value'"
120
+ if ! grep -Fqx -- "!$value" "$IP_ROOT/.gitignore" 2>/dev/null; then
121
+ warn "adapter '$target' Git policy is missing '!$value'"
122
+ elif git -C "$IP_ROOT" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
123
+ if git -C "$IP_ROOT" check-ignore -q --no-index -- "$value"; then
124
+ warn "adapter '$target' Git policy cannot re-include '$value' because another ignore rule still wins"
125
+ else
126
+ ignore_rc=$?
127
+ [ "$ignore_rc" -eq 1 ] \
128
+ || warn "adapter '$target' Git policy for '$value' could not be evaluated"
129
+ fi
130
+ fi
122
131
  ;;
123
132
  esac
124
133
  fi
@@ -31,3 +31,13 @@ adapter_contract_paths() {
31
31
  adapter_records_for "$root" "$content_dir" "$name" "$output" \
32
32
  | awk -F '\t' '$1 == "owned" || $1 == "managed" || $1 == "legacy" || $1 == "preserve" { print $2 }'
33
33
  }
34
+
35
+ # Keep the record kind for onboarding. A single concrete path may be both an
36
+ # adapter output and a legacy input (AGENTS.md is the important example), so
37
+ # flattening the contract too early loses the information needed to quarantine
38
+ # only legacy entry points.
39
+ adapter_contract_onboarding_records() {
40
+ local root="$1" content_dir="$2" name="$3" output="$4"
41
+ adapter_records_for "$root" "$content_dir" "$name" "$output" \
42
+ | awk -F '\t' '$1 == "owned" || $1 == "managed" || $1 == "legacy" || $1 == "preserve" { print $1 "\t" $2 }'
43
+ }
@@ -9,6 +9,42 @@ gitignore_add_line() {
9
9
  printf '%s\n' "$line" >> "$file"
10
10
  }
11
11
 
12
+ gitignore_path_is_ignored() {
13
+ local root="$1" path="$2"
14
+ git -C "$root" rev-parse --is-inside-work-tree >/dev/null 2>&1 || return 2
15
+ git -C "$root" check-ignore -q --no-index -- "$path"
16
+ }
17
+
18
+ # Git cannot re-include a child of an excluded directory. Add explicit parent
19
+ # reinclusions, then make sure both parent and child negations occur after any
20
+ # pre-existing rule that still wins. The check-ignore probe also catches broad
21
+ # patterns such as an old `.claude/` or `.cursor/**`, not just exact matches.
22
+ gitignore_add_effective_include() {
23
+ local root="$1" value="${2#./}" dir parent="" part rc
24
+ dir="${value%/*}"
25
+ if [ "$dir" != "$value" ]; then
26
+ while IFS= read -r part; do
27
+ [ -n "$part" ] || continue
28
+ if [ -n "$parent" ]; then parent="$parent/$part"; else parent="$part"; fi
29
+ gitignore_add_line "$root" "!$parent/"
30
+ if gitignore_path_is_ignored "$root" "$parent/"; then
31
+ printf '!%s/\n' "$parent" >> "$root/.gitignore"
32
+ else
33
+ rc=$?
34
+ [ "$rc" -eq 1 ] || [ "$rc" -eq 2 ] || return "$rc"
35
+ fi
36
+ done < <(printf '%s\n' "$dir" | tr '/' '\n')
37
+ fi
38
+
39
+ gitignore_add_line "$root" "!$value"
40
+ if gitignore_path_is_ignored "$root" "$value"; then
41
+ printf '!%s\n' "$value" >> "$root/.gitignore"
42
+ else
43
+ rc=$?
44
+ [ "$rc" -eq 1 ] || [ "$rc" -eq 2 ] || return "$rc"
45
+ fi
46
+ }
47
+
12
48
  ensure_gitignore_header() {
13
49
  local root="$1" file="$1/.gitignore"
14
50
  if [ ! -f "$file" ] || ! grep -Fqx '# Intelligence generated state and tool output' "$file"; then
@@ -36,7 +72,7 @@ ensure_target_gitignore() {
36
72
  while IFS=$'\t' read -r kind value; do
37
73
  case "$kind" in
38
74
  ignore) gitignore_add_line "$root" "$value" ;;
39
- include) gitignore_add_line "$root" "!$value" ;;
75
+ include) gitignore_add_effective_include "$root" "$value" ;;
40
76
  esac
41
77
  done <<< "$records"
42
78
  }
@@ -138,10 +174,11 @@ managed_gitignore_patterns() {
138
174
  }
139
175
 
140
176
  # Git does not apply ignore rules retroactively to files already in its index.
141
- # Name each affected path and print a command which only untracks it; the local
142
- # file remains available as migration input.
177
+ # Name each affected path that still exists and print a command which only
178
+ # untracks it. Quarantined legacy paths are already worktree deletions and must
179
+ # not receive a misleading "keep the local copy" instruction.
143
180
  report_tracked_managed_ignores() {
144
- local root="$1" manifest="$2" patterns tracked path quoted posix_quoted powershell_quoted
181
+ local root="$1" manifest="$2" patterns tracked path quoted posix_quoted powershell_quoted announced=0
145
182
  git -C "$root" rev-parse --is-inside-work-tree >/dev/null 2>&1 || return 0
146
183
  patterns="$(mktemp -t intelligence-gitignore-XXXXXX)"
147
184
  tracked="$(mktemp -t intelligence-tracked-XXXXXX)"
@@ -155,9 +192,13 @@ report_tracked_managed_ignores() {
155
192
  rm -f "$tracked"
156
193
  return 0
157
194
  }
158
- echo " Tracked files still bypass these .gitignore rules. Untrack them without deleting local copies:"
159
195
  while IFS= read -r -d '' path; do
160
196
  [ -n "$path" ] || continue
197
+ [ -e "$root/$path" ] || [ -L "$root/$path" ] || continue
198
+ if [ "$announced" -eq 0 ]; then
199
+ echo " Tracked files still bypass these .gitignore rules. Untrack them without deleting local copies:"
200
+ announced=1
201
+ fi
161
202
  if [[ "$path" == *"'"* ]]; then
162
203
  # macOS still ships Bash 3.2; use portable sed rather than newer
163
204
  # parameter-replacement behavior for the embedded quote.
@@ -114,11 +114,9 @@ target_set_enabled() {
114
114
  print
115
115
  next
116
116
  }
117
- in_targets && target_missing && target_entry_seen && !in_target && /^[[:space:]]*$/ {
118
- insert_missing_target()
119
- print
120
- next
121
- }
117
+ # A blank line is not a target-section boundary: it may belong to a
118
+ # block scalar such as targets.agents.header. Wait until the target
119
+ # list reaches a top-level comment/key or EOF before inserting.
122
120
  in_targets && /^[A-Za-z]/ { flush_targets() }
123
121
  in_targets && /^ [A-Za-z]/ {
124
122
  target_entry_seen = 1
@@ -3,12 +3,22 @@
3
3
  # The snapshot is data-only and explicitly identifies itself as initial
4
4
  # onboarding state so recovery skills never mistake it for generated output.
5
5
 
6
- onboarding_source_paths() {
6
+ onboarding_source_records() {
7
7
  local root="$1" content_dir="$2" targets="$3" target output
8
8
  for target in $targets; do
9
9
  output="$(default_target_output "$target")"
10
- adapter_contract_paths "$root" "$content_dir" "$target" "$output"
11
- done | awk 'NF && !seen[$0]++'
10
+ adapter_contract_onboarding_records "$root" "$content_dir" "$target" "$output"
11
+ done | awk -F '\t' 'NF == 2 && !seen[$1 SUBSEP $2]++'
12
+ }
13
+
14
+ onboarding_source_paths() {
15
+ onboarding_source_records "$1" "$2" "$3" \
16
+ | awk -F '\t' 'NF == 2 && !seen[$2]++ { print $2 }'
17
+ }
18
+
19
+ onboarding_legacy_paths() {
20
+ onboarding_source_records "$1" "$2" "$3" \
21
+ | awk -F '\t' '$1 == "legacy" && !seen[$2]++ { print $2 }'
12
22
  }
13
23
 
14
24
  onboarding_source_count() {
@@ -22,12 +32,13 @@ onboarding_source_count() {
22
32
 
23
33
  preserve_onboarding_sources() {
24
34
  local root="$1" content_dir="$2" targets="$3"
25
- local rel src dest backup_rel backup stage target
35
+ local rel src dest backup_rel backup stage target legacy_count=0
26
36
  backup_rel="$content_dir/_backup"
27
37
  backup="$root/$backup_rel"
28
38
  ONBOARDING_BACKUP_COUNT="$(onboarding_source_count "$root" "$content_dir" "$targets")"
29
39
  ONBOARDING_BACKUP_REL=""
30
- export ONBOARDING_BACKUP_COUNT ONBOARDING_BACKUP_REL
40
+ ONBOARDING_LEGACY_COUNT=0
41
+ export ONBOARDING_BACKUP_COUNT ONBOARDING_BACKUP_REL ONBOARDING_LEGACY_COUNT
31
42
  [ "$ONBOARDING_BACKUP_COUNT" -gt 0 ] || return 0
32
43
  [ ! -e "$backup" ] || die "onboarding backup already exists at $backup_rel - review or move it before rerunning init"
33
44
 
@@ -55,9 +66,72 @@ preserve_onboarding_sources() {
55
66
  printf 'path\t%s\n' "$rel" >> "$stage/manifest.tsv"
56
67
  done < <(onboarding_source_paths "$root" "$content_dir" "$targets")
57
68
 
69
+ while IFS= read -r rel; do
70
+ [ -e "$stage/$rel" ] || [ -L "$stage/$rel" ] || continue
71
+ printf 'legacy\t%s\n' "$rel" >> "$stage/manifest.tsv"
72
+ legacy_count=$((legacy_count + 1))
73
+ done < <(onboarding_legacy_paths "$root" "$content_dir" "$targets")
74
+
75
+ # This marker is deliberately outside manifest.tsv: the manifest is the
76
+ # immutable inventory, while the marker is short-lived transaction state.
77
+ [ "$legacy_count" -eq 0 ] || : > "$stage/.quarantine-pending"
78
+
58
79
  mv "$stage" "$backup"
59
80
  ensure_gitignore_header "$root"
60
81
  gitignore_add_line "$root" "$backup_rel/"
61
82
  ONBOARDING_BACKUP_REL="$backup_rel"
62
- export ONBOARDING_BACKUP_REL
83
+ ONBOARDING_LEGACY_COUNT="$legacy_count"
84
+ export ONBOARDING_BACKUP_REL ONBOARDING_LEGACY_COUNT
85
+ }
86
+
87
+ onboarding_quarantine_is_pending() {
88
+ [ -f "$1/$2/_backup/.quarantine-pending" ]
89
+ }
90
+
91
+ onboarding_backup_legacy_paths() {
92
+ local manifest="$1/$2/_backup/manifest.tsv"
93
+ [ -f "$manifest" ] || return 0
94
+ awk -F '\t' '$1 == "legacy" && NF == 2 && !seen[$2]++ { print $2 }' "$manifest"
95
+ }
96
+
97
+ quarantine_onboarding_legacy_sources() {
98
+ local root="$1" content_dir="$2" rel src backup
99
+ onboarding_quarantine_is_pending "$root" "$content_dir" || return 0
100
+ backup="$root/$content_dir/_backup"
101
+ while IFS= read -r rel; do
102
+ [ -n "$rel" ] || continue
103
+ src="$root/$rel"
104
+ [ -e "$src" ] || [ -L "$src" ] || continue
105
+ [ -e "$backup/$rel" ] || [ -L "$backup/$rel" ] \
106
+ || die "initial backup is missing legacy path '$rel'"
107
+ if [ -d "$src" ] && [ ! -L "$src" ]; then
108
+ rm -rf -- "$src"
109
+ else
110
+ rm -f -- "$src"
111
+ fi
112
+ done < <(onboarding_backup_legacy_paths "$root" "$content_dir")
113
+ }
114
+
115
+ restore_onboarding_legacy_sources() {
116
+ local root="$1" content_dir="$2" rel src dest backup
117
+ onboarding_quarantine_is_pending "$root" "$content_dir" || return 0
118
+ backup="$root/$content_dir/_backup"
119
+ while IFS= read -r rel; do
120
+ [ -n "$rel" ] || continue
121
+ src="$backup/$rel"
122
+ [ -e "$src" ] || [ -L "$src" ] || continue
123
+ dest="$root/$rel"
124
+ if [ -d "$dest" ] && [ ! -L "$dest" ]; then
125
+ rm -rf -- "$dest"
126
+ else
127
+ rm -f -- "$dest"
128
+ fi
129
+ mkdir -p "$(dirname "$dest")"
130
+ cp -R "$src" "$dest" || die "failed to restore legacy onboarding path '$rel'"
131
+ done < <(onboarding_backup_legacy_paths "$root" "$content_dir")
132
+ }
133
+
134
+ complete_onboarding_quarantine() {
135
+ local marker="$1/$2/_backup/.quarantine-pending"
136
+ [ ! -f "$marker" ] || rm -f -- "$marker"
63
137
  }
package/engine/ENGINE_SHA CHANGED
@@ -1 +1 @@
1
- 88a9c74ddb8bee338671c7badbebd07669b668c0
1
+ 0230d83b42848492194f593ebdd387714371b682
package/engine/VERSION CHANGED
@@ -1 +1 @@
1
- 0.11.0
1
+ 0.11.2
@@ -39,8 +39,8 @@ adapter_contract_opencode() {
39
39
 
40
40
  # Strip frontmatter, return body only.
41
41
  # Direct call to the shared `strip_frontmatter` helper in lib/common.sh —
42
- # duplicating the awk block here would violate the "all parsing in common.sh"
43
- # convention (see CLAUDE.md / packages/sync/references/conventions.md).
42
+ # duplicating the awk block here would fork frontmatter parsing, which the
43
+ # convention keeps in one place.
44
44
 
45
45
  sync_opencode_skills() {
46
46
  local repo_root="$1"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ainova-systems/intelligence",
3
- "version": "0.11.0",
3
+ "version": "0.11.2",
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"
@@ -79,7 +79,7 @@ records through these helpers:
79
79
  | `adapter_contract_requires <name>` | Another target that must be enabled for a full sync |
80
80
  | `adapter_contract_owned <path>` | Path exclusively regenerated by this adapter |
81
81
  | `adapter_contract_managed <path>` | Shared or marker-managed path modified by this adapter |
82
- | `adapter_contract_legacy <path>` | Pre-Intelligence input preserved in the initial backup |
82
+ | `adapter_contract_legacy <path>` | Pre-Intelligence input backed up, then quarantined for the first transactional render |
83
83
  | `adapter_contract_preserve <path>` | Settings or state preserved in place and included in the initial backup |
84
84
  | `adapter_contract_ignore <pattern>` | Exact `.gitignore` pattern managed on enable/init |
85
85
  | `adapter_contract_include <pattern>` | Exact negated `.gitignore` pattern managed on enable/init |
@@ -57,7 +57,7 @@ project:
57
57
  name: payments
58
58
  intelligence_dir: "intelligence" # optional; this is the default
59
59
 
60
- schema_version: "0.11.0"
60
+ schema_version: "0.11.1"
61
61
 
62
62
  sources:
63
63
  rules:
@@ -309,8 +309,10 @@ CLAUDE.md
309
309
 
310
310
  # Generated Claude and Cursor content; shared settings remain trackable
311
311
  .claude/*
312
+ !.claude/
312
313
  !.claude/settings.json
313
314
  .cursor/*
315
+ !.cursor/
314
316
  !.cursor/settings.json
315
317
 
316
318
  # Generated open-standard and Codex content
@@ -337,9 +339,11 @@ adapter output. Existing entries remain untouched and absent secondary ignore
337
339
  files are not created.
338
340
 
339
341
  An ignore rule does not untrack a file already in Git. After init or adapter
340
- enable, the CLI reports each affected tracked path with an exact
341
- `git rm --cached -- '<path>'` command; this preserves the local file while
342
- removing it from the index.
342
+ enable, the CLI reports each affected tracked path that remains in the
343
+ worktree with an exact `git rm --cached -- '<path>'` command; this preserves
344
+ the local file while removing it from the index. Legacy root entry points
345
+ quarantined into the initial backup are ordinary worktree deletions to review
346
+ and stage, not candidates for `git rm --cached`.
343
347
 
344
348
  Before release, inspect the packager's actual file list. An npm `files`
345
349
  allowlist can force inclusion despite `.npmignore`, and a Dockerfile-specific
@@ -349,18 +353,18 @@ than inferring contents from Git status.
349
353
 
350
354
  `AGENTS.md` is the only shared root instruction entry point. During onboarding,
351
355
  move useful repository guidance from legacy root files such as `.cursorrules`
352
- and instruction-bearing `CLAUDE.md` into project-owned rules, verify the
353
- generated tool output, then remove the legacy file. Keep a root tool-specific
354
- file only when it contains genuinely local configuration that an adapter cannot
355
- represent; keep that exception gitignored rather than maintaining a second
356
- committed instruction source.
356
+ and instruction-bearing `CLAUDE.md` out of their quarantined backup copies and
357
+ into project-owned rules, then verify the generated tool output. Do not restore
358
+ the original root monolith. Create a new root tool-specific file only when it
359
+ contains genuinely local configuration that an adapter cannot represent; keep
360
+ that exception gitignored rather than maintaining a second committed source.
357
361
 
358
362
  Before the first render, `intelligence init` preserves existing AI prompt paths
359
363
  under `<content-dir>/_backup/`. Its `manifest.tsv` labels the snapshot
360
- `initial-onboarding` and lists exact original paths. The context-learning skill
361
- first recovers or verifies CLI setup, then routes that state through
362
- `onboarding-migration.md` and repository learning. The backup remains until the
363
- user approves removal.
364
+ `initial-onboarding`, lists exact original paths, and marks legacy entry points.
365
+ Those legacy paths are quarantined only for the transactional first render; a
366
+ failed render restores them, while a successful render leaves them inactive for
367
+ repository learning. The backup remains until the user approves removal.
364
368
 
365
369
  ## Project-owned adapters
366
370
 
@@ -8,8 +8,10 @@ Git diff showing that the first sync replaced tracked tool output.
8
8
 
9
9
  When `<content-dir>/_backup/manifest.tsv` contains
10
10
  `state<TAB>initial-onboarding`, it is the authoritative inventory from before
11
- the first generated write. Read each `target` and `path` record before looking
12
- at current adapter output. If `path<TAB>AGENTS.md` is present, the backed-up
11
+ the first generated write. Read each `target`, `path`, and `legacy` record
12
+ before looking at current adapter output. A `legacy` record means the CLI
13
+ quarantined that active entry point before the first successful render. If
14
+ `path<TAB>AGENTS.md` is present, the backed-up
13
15
  file is the original custom project contract; keep following it while deciding
14
16
  how to migrate its durable guidance.
15
17
 
@@ -22,7 +24,8 @@ Treat these as migration inputs, not as current generated output:
22
24
  - Codex/Open Agent Skills, Pi rules/prompts, and OpenCode agents/commands;
23
25
  - scripts or documentation that describe an older sync path.
24
26
 
25
- Prefer the copy under `<content-dir>/_backup/`. If it is absent and the first
27
+ Prefer the copy under `<content-dir>/_backup/`; do not restore quarantined root
28
+ monoliths as active instructions. If the backup is absent and the first
26
29
  sync changed tracked files, inspect their pre-sync content read-only through
27
30
  Git (`git diff` and `git show HEAD:<path>`). Never restore old content directly
28
31
  into an adapter output directory.
@@ -60,7 +63,10 @@ Prefer updating an existing project-owned artifact to creating a sibling.
60
63
  Obtain approval per `CREATE`, `UPDATE`, `REMOVE`, or `KEEP` proposal. Apply
61
64
  project-owned source changes first, then run `intelligence sync` and
62
65
  `intelligence status --check`. Inspect the enabled targets to prove the
63
- migrated guidance arrived before removing old root instructions or tool files.
66
+ migrated guidance arrived and verify quarantined old root instructions remain
67
+ absent. Create a new root tool file only from a separately approved, genuinely
68
+ machine-local subset that has no adapter representation; never restore the
69
+ original instruction monolith.
64
70
 
65
71
  For every removed or renamed path, search all tracked files with `git ls-files`
66
72
  and report remaining references with file and line number. Apply an unambiguous
@@ -68,8 +74,10 @@ replacement directly; ask about narrative or otherwise ambiguous references.
68
74
 
69
75
  The CLI owns generated-output `.gitignore` entries and its blocks in existing
70
76
  `.vscodeignore`, `.npmignore`, and `.dockerignore` files. Verify them against
71
- the enabled adapters. Treat CLI-reported tracked ignored paths as unresolved
72
- until the user approves the exact `git rm --cached` commands. Preserve
77
+ the enabled adapters. Treat CLI-reported tracked ignored paths that still exist
78
+ locally as unresolved until the user approves the exact `git rm --cached`
79
+ commands. A quarantined tracked legacy path is already a worktree deletion;
80
+ review and stage that deletion normally instead of using `git rm --cached`. Preserve
73
81
  `AGENTS.md`, `.github/`, shared settings, and unrelated files under shared tool
74
82
  roots in Git, while excluding development-only Intelligence content from
75
83
  published artifacts. Inspect the packager's actual file list before release;
@@ -19,7 +19,9 @@ mechanics; this skill supplies repository judgement.
19
19
  2. Inspect `<content-dir>/_backup/manifest.tsv`. A
20
20
  `state<TAB>initial-onboarding` record identifies the byte-preserved state
21
21
  from before Intelligence first wrote adapter output. Read every `path`
22
- record and treat it as migration input, never generated output. A
22
+ record and treat it as migration input, never generated output. `legacy`
23
+ records name old entry points the CLI quarantined for the first successful
24
+ render; read their backup copies rather than restoring them. A
23
25
  `.intelligence/backup/config.yaml` file identifies a converted legacy
24
26
  Intelligence Sync project; use the converted sources and that config as
25
27
  migration evidence.
@@ -55,12 +57,12 @@ mechanics; this skill supplies repository judgement.
55
57
  materially covered by package content, propose `REMOVE` or a smaller
56
58
  `UPDATE`; require a content comparison, not merely a matching name.
57
59
 
58
- Treat committed legacy root instructions such as `.cursorrules` and an
60
+ Treat backed-up legacy root instructions such as `.cursorrules` and an
59
61
  instruction-bearing `CLAUDE.md` as migration sources, not permanent parallel
60
- entry points. Propose moving still-valid guidance into project-owned rules
61
- and removing the legacy file after generated output is verified. Keep one
62
- only for genuinely local, gitignored configuration an adapter cannot
63
- represent. `AGENTS.md` remains the shared root instruction entry point.
62
+ entry points. Move still-valid shared guidance into project-owned rules; do
63
+ not restore the original monolith. Only when approved machine-local guidance
64
+ remains, create a small new gitignored `CLAUDE.md` from that subset after
65
+ migration. `AGENTS.md` remains the shared root instruction entry point.
64
66
 
65
67
  Review `.gitignore` and every existing `.vscodeignore`, `.npmignore`, and
66
68
  `.dockerignore` against the CLI-managed policy. Detect tracked files which
@@ -92,10 +94,12 @@ explains itself well.
92
94
  installed package content or generated tool output.
93
95
  10. Run `intelligence sync`, then `intelligence status --check`. Inspect the
94
96
  relevant generated `AGENTS.md`, Cursor rules, Claude rules, and any
95
- packaging/build file list affected by ignore policy. Only then remove each
96
- separately approved legacy root instruction file and rerun the consistency
97
- check. Completion requires `IS_STATUS=ok`, a clean final check, and no
98
- `onboarding is pending` header after accepted migration.
97
+ packaging/build file list affected by ignore policy. Verify quarantined
98
+ legacy root entry points remain absent. If the user approved a genuinely
99
+ machine-local exception, create a concise new gitignored root file from only
100
+ that content; never copy the backed-up monolith back. Completion requires
101
+ `IS_STATUS=ok`, a clean final check, and no `onboarding is pending` header
102
+ after accepted migration.
99
103
  11. Report what was created, updated, removed, or deliberately kept. Remind the
100
104
  user to commit source, manifest, lock, `AGENTS.md`, and shared `.github/`
101
105
  changes. Keep or remove the initial backup only by separate user approval.
@@ -18,3 +18,11 @@ context: fork
18
18
  commit its diff; never bypass the gate. A frozen restore refusal means the
19
19
  manifest and lock disagree or a pinned ref moved—report it without
20
20
  hand-copying package content.
21
+ 4. On a probable Intelligence defect, first ask whether to collect a sanitized
22
+ issue draft; collect nothing before approval and never use telemetry. Include
23
+ only approved CLI/version, expected/actual behavior, and safe error details—
24
+ no confidential or project-specific data. Show the draft and obtain separate
25
+ approval before filing. If declined, ask whether the opt-out is for this
26
+ session, a user/gitignored dev-project profile, or a shared team policy; save
27
+ it only with separate approval. Put team policy in a project-owned rule, and
28
+ never invent a profile path or infer the intended scope.