@erclx/aitk 0.55.0 → 0.56.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.
|
@@ -9,10 +9,16 @@ description: Why the root-to-.claude relocation ships as git mv commands the use
|
|
|
9
9
|
|
|
10
10
|
Without this skill, a project whose rules cite `.claude/standards/` while the files sit at the root gets fixed by hand, and the hand fix loses what version control was holding. A plain `mv` breaks the rename chain, so every relocated standard reads as a delete beside an unrelated add and its history stops at the move.
|
|
11
11
|
|
|
12
|
+
A fourth failure comes before those three, from deciding what is unmigrated by listing the folder. A root `standards/` can hold the project's own docs and nothing the toolkit ever installed, and a listing cannot tell the two apart, so the skill proposes moving project files under `.claude/` where a sync walks them. The drift report already answers this, counting only files whose basename the toolkit ships, and it is the same report `toolkit-operator` reads to route here.
|
|
13
|
+
|
|
14
|
+
Taking detection from a command opens a failure the listing never had. A CLI predating the field exits zero with a well-formed report that never mentions it, so a skill treating an absent key as an empty answer tells a project whose every domain sits at the root that it has nothing to relocate. That is the population this skill exists for, and a silent false negative there costs more than the unfiltered count reading the folder would have produced.
|
|
15
|
+
|
|
12
16
|
Three failures follow from acting without looking first. A move onto an existing `.claude/standards/` copy overwrites the files already installed there, which is the case the relocation was supposed to be unnecessary for. A `git mv` on a dirty tree lands the relocation in the same commit as unrelated work, so neither can be reviewed or reverted alone. And a session that rewrites every inbound reference spends its effort on toolkit-owned rules and skills, which the next sync overwrites, while the author-owned lines that actually break go unmentioned.
|
|
13
17
|
|
|
14
18
|
## Must
|
|
15
19
|
|
|
20
|
+
- Take the set of domains to relocate from `aitk sync --check --json`, and report its filtered count rather than a folder listing
|
|
21
|
+
- Keep the listing as the fallback for a target where `aitk` is absent, the command fails, or the report carries no `unmigrated` key, and say that its counts are unfiltered
|
|
16
22
|
- Detect an existing copy under `.claude/` and skip that folder's move rather than merging into it
|
|
17
23
|
- Read the working tree state and require it clean before the moves, since the relocation has to be revertible on its own
|
|
18
24
|
- Propose `git mv` so history follows each file
|
|
@@ -10,21 +10,38 @@ description: Proposes `git mv` commands to relocate a target project's root `sta
|
|
|
10
10
|
- If neither `standards/` nor `snippets/` exists at `pwd`, stop: `❌ No root standards/ or snippets/ to relocate.`
|
|
11
11
|
- If `pwd` is not a git work tree, stop: `❌ Not a git repository. git mv needs version control.`
|
|
12
12
|
|
|
13
|
-
## Step 1:
|
|
13
|
+
## Step 1: read the report
|
|
14
14
|
|
|
15
|
-
Run
|
|
15
|
+
Run `aitk sync --check . --json` from the project root. Its `unmigrated` array is the detection. Each entry carries `domain`, `rootPath`, `installPath`, and `files`, and a domain appears only when the root folder holds a file the toolkit ships and nothing sits at the install path. Report `files` as the count, since it excludes files the project wrote into the same folder.
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
- `ls .claude/standards/ 2>/dev/null`:
|
|
20
|
-
- `ls .claude/snippets/ 2>/dev/null`:
|
|
17
|
+
Run these beside it, in parallel. The report answers which domains to move and neither of these is derivable from it:
|
|
18
|
+
|
|
19
|
+
- `ls .claude/standards/ 2>/dev/null`: separate a domain already relocated from one never installed, which the report cannot, since both are absent from `unmigrated`
|
|
20
|
+
- `ls .claude/snippets/ 2>/dev/null`: the same, for the other domain
|
|
21
21
|
- `git status --short 2>/dev/null`: confirm a clean tree before proposing moves
|
|
22
22
|
|
|
23
|
+
Keep the two listings as separate commands. `ls` labels its output with a `dir:` header only when more than one operand succeeds, so a combined call with one directory present prints that directory's filenames bare while the redirect swallows the other's failure, and the result reads as whichever directory was expected.
|
|
24
|
+
|
|
25
|
+
### When the report is unavailable
|
|
26
|
+
|
|
27
|
+
Fall back to `ls standards/*.md` and `ls snippets/` on any of three conditions. Say in the output that the counts are unfiltered, because a root folder can hold project-authored files the report would have excluded and the fallback counts every one of them.
|
|
28
|
+
|
|
29
|
+
- `aitk` is not on `PATH`
|
|
30
|
+
- The command exits non-zero
|
|
31
|
+
- The report parses and carries no `unmigrated` key at all
|
|
32
|
+
|
|
33
|
+
The third is the one that decides whether this skill works for the projects it exists for. `unmigrated` reached a release in `0.46.0`, and a CLI older than that exits zero with a well-formed report that never mentions the field. Reading an absent key as an empty list sends the run down the nothing-to-relocate branch and reports a clean layout to a project whose every domain sits at the root, which is a silent false negative where the unfiltered count is a visible imprecision.
|
|
34
|
+
|
|
35
|
+
An absent key and an empty array are different states, so test for the key rather than for emptiness. A current CLI reporting `"unmigrated": []` has looked and found nothing, and falling back there would trade a correct answer for a listing that proposes moving whatever the folder happens to hold.
|
|
36
|
+
|
|
37
|
+
Do not fall back on `historyUnavailable`. That field reports failed attribution on a domain or on `seeds`, and `unmigrated` is a filesystem read carrying no attribution of its own, so a report that cannot date a file still detects the layout correctly.
|
|
38
|
+
|
|
23
39
|
## Step 2: check conflicts
|
|
24
40
|
|
|
25
41
|
- If `.claude/standards/` already holds `.md` files, mark standards as "already relocated" and skip its move.
|
|
26
42
|
- If `.claude/snippets/` already holds `.md` files, mark snippets as "already relocated" and skip its move.
|
|
27
43
|
- If `git status` is not clean, add a TODO line telling the user to commit or stash first. `git mv` on a dirty tree mixes the move with unrelated changes.
|
|
44
|
+
- If a root folder holds files and no domain names it in a report that carried the key, propose nothing for it. The content is the project's own, and moving it under `.claude/` puts project files where a sync walks. This reads a present key alone. A report with no `unmigrated` key never reaches here, since Step 1 sends it to the fallback.
|
|
28
45
|
|
|
29
46
|
## Step 3: find author-owned inbound references
|
|
30
47
|
|
|
@@ -70,6 +87,9 @@ aitk gov sync .
|
|
|
70
87
|
Re-syncing reinstalls toolkit-owned rules and standards at the new path. Author-owned references above need a manual one-line fix.
|
|
71
88
|
```
|
|
72
89
|
|
|
73
|
-
|
|
90
|
+
Two states produce no proposal at all, and each gets its own line rather than an empty block:
|
|
91
|
+
|
|
92
|
+
- Both folders already live under `.claude/`: `✅ standards/ and snippets/ already live under .claude/. Nothing to relocate.`
|
|
93
|
+
- A root folder exists and no domain names it in `unmigrated`: `✅ <folder>/ holds no file the toolkit installed. Nothing to relocate.` Name every such folder. The guard passed because the folder is there, so a session that printed nothing would leave the user reading silence as a failed run rather than as the answer.
|
|
74
94
|
|
|
75
95
|
Do not run the `git mv` commands. Do not edit `CLAUDE.md`, rule files, or docs. The user runs the commands and fixes author-owned references after reviewing.
|
|
@@ -164,6 +164,13 @@ to, with nothing at the path the current one reads. It carries `rootPath`,
|
|
|
164
164
|
root reports zero entries for that domain and reads as clean, which is the most
|
|
165
165
|
misleading state the report can produce. Route it to `migration-standards`.
|
|
166
166
|
|
|
167
|
+
That skill reads this field rather than listing the folder itself, so the entry
|
|
168
|
+
is the detection on both sides of the handoff and the two cannot disagree. The
|
|
169
|
+
count is what makes the difference visible: it counts only files whose basename
|
|
170
|
+
the toolkit ships, so a root folder holding the project's own documents beside
|
|
171
|
+
the installed ones reports the installed subset, where a listing reports every
|
|
172
|
+
file and proposes relocating the lot.
|
|
173
|
+
|
|
167
174
|
`unmigrated` counts toward `--exit-code`, since running the relocation closes it.
|
|
168
175
|
`superseded` and every seed state are excluded, for the reason `orphaned` already
|
|
169
176
|
is: only the user can move content they wrote, so failing a job on it leaves the
|
package/package.json
CHANGED
|
@@ -78,6 +78,27 @@ append_from_fixtures() {
|
|
|
78
78
|
done < <(list_fixture_files "$source_dir")
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
# Stages the first `count` markdown files the toolkit ships for a domain into
|
|
82
|
+
# `dest`, flattening any source subfolder. Source rather than fixture tree,
|
|
83
|
+
# because an arm modelling a real install wants the files a target actually
|
|
84
|
+
# received and a copy under `fixtures/` would drift from them silently.
|
|
85
|
+
#
|
|
86
|
+
# The flattening is load-bearing rather than incidental. Both `detectUnmigrated`
|
|
87
|
+
# and the sync engine match a target file to its source by basename against the
|
|
88
|
+
# flat domain root, so a file lifted out of a source subfolder such as `bundled/`
|
|
89
|
+
# has no flat sibling and reads as project-authored. An arm staging one claims a
|
|
90
|
+
# drift or an unmigrated domain it did not stage.
|
|
91
|
+
stage_toolkit_markdown() {
|
|
92
|
+
local src="$1"
|
|
93
|
+
local dest="$2"
|
|
94
|
+
local count="$3"
|
|
95
|
+
|
|
96
|
+
mkdir -p "$dest"
|
|
97
|
+
while IFS= read -r file; do
|
|
98
|
+
cp "$file" "$dest/$(basename "$file")"
|
|
99
|
+
done < <(find "$src" -maxdepth 1 -type f -name "*.md" ! -name "index.md" | sort | head -n "$count")
|
|
100
|
+
}
|
|
101
|
+
|
|
81
102
|
# Stages one step of a scenario arm into the sandbox working directory.
|
|
82
103
|
# Scenarios call this once per step so their own git operations stay between
|
|
83
104
|
# the steps, where they are visible.
|