@erclx/aitk 0.72.0 → 0.74.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/README.md +1 -1
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/toolkit-operator/REQUIREMENT.md +4 -0
- package/claude/skills/toolkit-operator/SKILL.md +7 -2
- package/docs/agents/install-and-sync.md +6 -0
- package/docs/agents/markdown-audit.md +8 -2
- package/docs/target-projects.md +1 -1
- package/package.json +1 -1
- package/scripts/lib/sandbox-fixtures.sh +61 -0
- package/src/markdown/structure.ts +1 -1
- package/standards/markdown.md +1 -1
package/README.md
CHANGED
|
@@ -62,7 +62,7 @@ Two limits worth knowing before you install. Claude Code is the only agent runti
|
|
|
62
62
|
Each domain has a canonical source in this repo and a thin install or sync CLI on your side. The links run to internal narrative, written for someone maintaining the toolkit rather than installing it, so skip them on a first pass.
|
|
63
63
|
|
|
64
64
|
- [Claude Code plugin](.claude/context/claude-plugin/index.md): skills for planning, review, docs sync, and the git ship chain
|
|
65
|
-
- [Governance rules](.claude/context/governance.md):
|
|
65
|
+
- [Governance rules](.claude/context/governance/index.md): Claude rules and stacks, installable per project
|
|
66
66
|
- [Standards](.claude/context/standards/index.md): shared authoring conventions, synced to projects
|
|
67
67
|
- [Snippets](.claude/context/snippets.md): reusable prompts for Claude and Gemini chat
|
|
68
68
|
- [Tooling stacks](.claude/context/tooling.md): golden configs, seeds, and references per framework
|
|
@@ -21,6 +21,8 @@ The last failure is writing without re-checking. A domain sync brought a stricte
|
|
|
21
21
|
- Map the stated intent to one lifecycle phase, then either run the simplest command that satisfies it or hand off
|
|
22
22
|
- Resolve every stack, rule, snippet, and standard name from a catalog at runtime
|
|
23
23
|
- Run the CLI non-interactively and report the command run, what changed, and the full path of anything written
|
|
24
|
+
- Read the reverse walk beside the forward sections, so a folder the toolkit stopped shipping and a migration with a live case both reach the user
|
|
25
|
+
- Hand off a named migration to the skill the report names, the way an unmigrated domain reaches `migration-standards`
|
|
24
26
|
- Offer every audit whose surface the target carries, and offer none whose surface it lacks
|
|
25
27
|
- Re-check the target after any operation that wrote, and report what those writes changed against the state read before acting
|
|
26
28
|
|
|
@@ -29,6 +31,7 @@ The last failure is writing without re-checking. A domain sync brought a stricte
|
|
|
29
31
|
- Edit a managed file by hand instead of running the CLI that owns it
|
|
30
32
|
- Reimplement a flow another skill owns
|
|
31
33
|
- Hardcode a catalog name
|
|
34
|
+
- Move, delete, or name a command against a folder in `unclaimed`. The toolkit stopped claiming the path and only the user knows whether the project owns what sits there
|
|
32
35
|
- Run an audit the user did not pick, which turns a front door into a full sweep
|
|
33
36
|
- Refuse to finish an operation over an audit finding, since every audit reports judgments beside facts and a router that stops on one is a router a target works around
|
|
34
37
|
- Auto-trigger. It is a door the user opens, and a router that fires on its own routes requests nobody made.
|
|
@@ -38,6 +41,7 @@ The last failure is writing without re-checking. A domain sync brought a stricte
|
|
|
38
41
|
- An intent matching a deep flow hands off rather than running a shallow version of it, since a partial scaffold is harder to recover from than none
|
|
39
42
|
- An ignore-only fix on an unmeasured tooling report stops, names which cause applies, and names the command answering that cause. Unmeasured has several causes and they do not share a remedy, so one suggested command is wrong for at least one of them. No cause asks the user to supply a stack name, and none reads the zero counts under an unmeasured report as a clean target.
|
|
40
43
|
- A re-check with no earlier report to compare against says the write ran without a baseline, rather than describing the target from scratch
|
|
44
|
+
- A report missing a field this skill reads names the CLI version as the cause and reports that section as unread. Neither an absent key nor a hand-rolled substitute for it may be reported as a finding, since the first reads as a clean target and the second reaches a verdict only the field's attribution can make
|
|
41
45
|
|
|
42
46
|
## Out of scope
|
|
43
47
|
|
|
@@ -22,23 +22,28 @@ Load a domain doc with `aitk docs <topic>` only when the intent touches that dom
|
|
|
22
22
|
|
|
23
23
|
Run `aitk sync --check . --json` before routing. It reports what a target is behind on across every surface, so the intent comes from the project state rather than from the user having to know it already. Skip only when the user named a single operation to run.
|
|
24
24
|
|
|
25
|
-
Read
|
|
25
|
+
Read seven fields off the report and carry each to `## Route`:
|
|
26
26
|
|
|
27
27
|
- `unmigrated`: a domain sitting at the root layout with nothing under `.claude/`. The most urgent finding, because that domain reports no drift of its own while being entirely behind
|
|
28
28
|
- `superseded`: a file a newer seed folder replaced. Report it and stop. No command moves it, since the content is the project's own
|
|
29
29
|
- `seeds`: entries are `matching`, `stale`, `drifted`, or `missing`. Anything but `matching` needs the seed handoff
|
|
30
30
|
- `domains[].entries`: per-file `stale`, `customized`, `stranded`, and `orphaned` as before
|
|
31
|
-
- `
|
|
31
|
+
- `reverse`: what the target holds that no live catalog claims. `unclaimed` lists folders at roots the toolkit stopped shipping, each with an `attribution` of `dropped`, `unattributed`, or `project`. Act on the first two and leave `project` alone, which history proved the project owns. `migrations` names a proposal-only skill with a live case here and the `reason` it was measured from
|
|
32
|
+
- `historyUnavailable` on a domain, on `seeds`, or on `reverse`: nothing could be dated, so treat every difference as unverified and say so rather than reporting a file as untouched. It is set on `reverse` when the toolkit itself ships without history, which is the registry-install case, so the walk found nothing rather than finding a clean target
|
|
32
33
|
- `tooling`: read `measured` first. Every count under it is zero when it is false, which is an absence of measurement rather than a measured zero. Past that, `chain` names the stacks the install resolved, nearest first, and `counts.gitignore` counts the managed ignore entries the target is missing.
|
|
33
34
|
|
|
34
35
|
State what the report found in one line per finding before acting on any of it.
|
|
35
36
|
|
|
37
|
+
A `reverse` key the report does not carry at all is a CLI predating the field rather than a target with nothing unclaimed. Say the walk did not run and name the CLI version as the cause. Reading the absent key as an empty answer reports a clean target to a project nobody has looked at, and answering it from a filesystem walk of your own is worse, since that reaches a verdict the attribution the field carries is the only thing entitled to make.
|
|
38
|
+
|
|
36
39
|
## Route
|
|
37
40
|
|
|
38
41
|
Map the stated intent, or what `## Diagnose` found, to one lifecycle phase, then act:
|
|
39
42
|
|
|
40
43
|
- A domain in `unmigrated`: hand off to `migration-standards`
|
|
44
|
+
- An entry in `migrations`: hand off to the skill its `skill` field names, spelled as the report spells it. Both of them propose without writing, so the handoff is where this stops
|
|
41
45
|
- Anything in `superseded`: tell the user which files and what replaced them. Do not move or delete them
|
|
46
|
+
- A folder in `unclaimed`: name it and the attribution it carries. No command moves it and the content may be the project's own, so the decision is the user's
|
|
42
47
|
|
|
43
48
|
- First-time scaffold of a fresh project: hand off to `setup-init`
|
|
44
49
|
- Governance rules for the project stack: hand off to `setup-gov`
|
|
@@ -210,6 +210,12 @@ code change. Scoping to those roots is what keeps the walk useful: walking the
|
|
|
210
210
|
whole tree reports every project folder as unclaimed, which is true and says
|
|
211
211
|
nothing.
|
|
212
212
|
|
|
213
|
+
The managed gate above applies here too, and it is the one place it surprises.
|
|
214
|
+
A directory holding a dropped folder and nothing else reports an empty `reverse`
|
|
215
|
+
rather than the folder, because it carries none of the three markers. Read an
|
|
216
|
+
empty section on an unmanaged target as a walk that never ran rather than as a
|
|
217
|
+
clean result.
|
|
218
|
+
|
|
213
219
|
Each entry carries `rel`, a file count, and an `attribution` of `dropped`,
|
|
214
220
|
`project`, or `unattributed`. A dropped folder and one the project wrote are the
|
|
215
221
|
same bytes at the same path, so the verdict is traced from history rather than
|
|
@@ -55,14 +55,16 @@ Every weight and depth measure counts the text a reader is shown. A link reduces
|
|
|
55
55
|
|
|
56
56
|
A code span is walked around rather than through, so a path quoting link or angle-bracket syntax keeps the width the page gives it. Masking inside one takes back the decision to count it, and the placeholders this toolkit writes are where that shows.
|
|
57
57
|
|
|
58
|
-
The paragraph check measures both halves of one rule. `markdown.md` caps a paragraph at four sentences, and a sentence cap on its own is satisfied by writing fewer and longer ones:
|
|
58
|
+
The paragraph check measures both halves of one rule. `markdown.md` caps a paragraph at four sentences, and a sentence cap on its own is satisfied by writing fewer and longer ones: 36 paragraphs in this corpus sit inside four sentences and past the weight checkpoint, and the heaviest of those runs 1121 characters. The standard therefore states a weight beside the sentence cap, and the verb reads it as its own checkpoint.
|
|
59
59
|
|
|
60
|
-
The paragraph weight sits at
|
|
60
|
+
The paragraph weight sits at 700 and the bullet weight at 400. Both shipped at 400, because the paragraph number was borrowed from the bullet rule when the two checks landed together, and each has since been read against a sample of its own. They are separate checkpoints in the standard and separate patterns in the parser, so a read that moves one leaves the other where it is.
|
|
61
61
|
|
|
62
62
|
#### The sample behind the paragraph number
|
|
63
63
|
|
|
64
64
|
The checkpoint shipped at 400 as a borrowed number and was decided against a read of the prose it reports. Thirty-six findings were sampled, six from each of six weight bands, drawn at even spacing through each band ordered by path and line, and each was classed as prose a reader wants split or prose the checkpoint should not have reported.
|
|
65
65
|
|
|
66
|
+
Every band below was measured before the scan stopped counting link syntax as prose, so a paragraph sitting in one of these bands is heavier than a paragraph reported at the same number today. The re-sample in the section below re-reads the same range against the corrected measure and reaches the opposite verdict on it, which is the measure moving rather than the reader.
|
|
67
|
+
|
|
66
68
|
| Band | Wants the split | Reads as written |
|
|
67
69
|
| --------- | --------------- | ---------------- |
|
|
68
70
|
| 400 - 425 | 1 | 5 |
|
|
@@ -78,6 +80,10 @@ Nothing inside the 500 to 600 band separated the two classes by length, which is
|
|
|
78
80
|
|
|
79
81
|
The sample is thirty-six paragraphs against a reported population in the hundreds, and one reader classed all of them. Treat a band's rate as the order of magnitude it is rather than as a measured precision, and re-sample before moving the number again.
|
|
80
82
|
|
|
83
|
+
#### The re-sample that moved the number to 700
|
|
84
|
+
|
|
85
|
+
That re-sample ran once the scan stopped counting link syntax as prose. Findings at 604, 633, and 677 characters each read as an ordinary four-sentence paragraph on one topic, density arrived around 760 and was plain by 860, and the move cut the weight half of the report roughly in half while leaving the sentence cap untouched.
|
|
86
|
+
|
|
81
87
|
A bullet, a heading, a table row, a blockquote, a blank line, and a fence each end a paragraph, so a heavy bullet is reported by the bullet check alone and never counted twice.
|
|
82
88
|
|
|
83
89
|
## Exit codes
|
package/docs/target-projects.md
CHANGED
|
@@ -193,5 +193,5 @@ Sync also refuses a target whose working tree is dirty, so commit or stash befor
|
|
|
193
193
|
|
|
194
194
|
- [agents](agents/index.md): CLI flags, exit codes, and JSON output shapes
|
|
195
195
|
- [AI workflow](ai-workflow.md): feature-development loop inside a toolkit-managed project
|
|
196
|
-
- [tooling](../.claude/context/tooling.md), [governance](../.claude/context/governance.md), [claude plugin](../.claude/context/claude-plugin/index.md), [indexes](../.claude/context/indexes.md), [snippets](../.claude/context/snippets.md), [standards](../.claude/context/standards/index.md): per-domain mechanics
|
|
196
|
+
- [tooling](../.claude/context/tooling.md), [governance](../.claude/context/governance/index.md), [claude plugin](../.claude/context/claude-plugin/index.md), [indexes](../.claude/context/indexes.md), [snippets](../.claude/context/snippets.md), [standards](../.claude/context/standards/index.md): per-domain mechanics
|
|
197
197
|
- [sandbox](../.claude/context/sandbox/index.md): scenario catalog for verifying domain flows
|
package/package.json
CHANGED
|
@@ -99,6 +99,67 @@ stage_toolkit_markdown() {
|
|
|
99
99
|
done < <(find "$src" -maxdepth 1 -type f -name "*.md" ! -name "index.md" | sort | head -n "$count")
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
# The newest top-level path history records a deletion under that the toolkit no
|
|
103
|
+
# longer ships. Read from history rather than hardcoded, so an arm stages a root
|
|
104
|
+
# the walk will actually recognize instead of a name that has since come back.
|
|
105
|
+
# `prompts` is preferred because it is the case measured in a real target, and
|
|
106
|
+
# any other dropped root exercises the same walk.
|
|
107
|
+
pick_dropped_root() {
|
|
108
|
+
local preferred="prompts"
|
|
109
|
+
local first=""
|
|
110
|
+
local candidate
|
|
111
|
+
|
|
112
|
+
while IFS= read -r candidate; do
|
|
113
|
+
[ -e "$PROJECT_ROOT/$candidate" ] && continue
|
|
114
|
+
[ "$candidate" = "$preferred" ] && {
|
|
115
|
+
echo "$preferred"
|
|
116
|
+
return 0
|
|
117
|
+
}
|
|
118
|
+
[ -n "$first" ] || first="$candidate"
|
|
119
|
+
done < <(git -C "$PROJECT_ROOT" log --all --diff-filter=D --name-only --format= |
|
|
120
|
+
awk -F/ 'NF > 1 { print $1 }' | sort -u)
|
|
121
|
+
|
|
122
|
+
echo "$first"
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
# Restores one file's exact published bytes from the commit before it was
|
|
126
|
+
# deleted. Content is what the attribution matches on, so a file written by hand
|
|
127
|
+
# would report unattributed and an arm would assert the wrong verdict.
|
|
128
|
+
#
|
|
129
|
+
# Both reads take the whole listing through a process substitution rather than a
|
|
130
|
+
# pipeline ending in an early exit. `set -o pipefail` is on, and a `grep -m 1`
|
|
131
|
+
# that matches the first line closes the pipe while git is still writing, so the
|
|
132
|
+
# substitution returns git's SIGPIPE status and the arm fails on a listing it
|
|
133
|
+
# actually read.
|
|
134
|
+
restore_dropped_file() {
|
|
135
|
+
local root="$1"
|
|
136
|
+
local rel="" commit="" line
|
|
137
|
+
|
|
138
|
+
while IFS= read -r line; do
|
|
139
|
+
case "$line" in
|
|
140
|
+
"$root"/*)
|
|
141
|
+
rel="$line"
|
|
142
|
+
break
|
|
143
|
+
;;
|
|
144
|
+
esac
|
|
145
|
+
done < <(git -C "$PROJECT_ROOT" log --all --diff-filter=D --name-only \
|
|
146
|
+
--format= -- "$root/")
|
|
147
|
+
|
|
148
|
+
[ -n "$rel" ] || return 1
|
|
149
|
+
|
|
150
|
+
while IFS= read -r line; do
|
|
151
|
+
commit="$line"
|
|
152
|
+
break
|
|
153
|
+
done < <(git -C "$PROJECT_ROOT" log --all --diff-filter=D --format=%H -- "$rel")
|
|
154
|
+
|
|
155
|
+
[ -n "$commit" ] || return 1
|
|
156
|
+
|
|
157
|
+
mkdir -p "$(dirname "$rel")"
|
|
158
|
+
git -C "$PROJECT_ROOT" show "$commit^:$rel" >"$rel" || return 1
|
|
159
|
+
|
|
160
|
+
echo "$rel"
|
|
161
|
+
}
|
|
162
|
+
|
|
102
163
|
# Stages one step of a scenario arm into the sandbox working directory.
|
|
103
164
|
# Scenarios call this once per step so their own git operations stay between
|
|
104
165
|
# the steps, where they are visible.
|
package/standards/markdown.md
CHANGED
|
@@ -34,7 +34,7 @@ Does not govern:
|
|
|
34
34
|
|
|
35
35
|
- Use prose by default. Reserve bullets for discrete, unrelated items.
|
|
36
36
|
- Keep paragraphs to four sentences or fewer. Split longer blocks at the next logical boundary.
|
|
37
|
-
- Past roughly
|
|
37
|
+
- Past roughly 700 characters in one paragraph, folding in the lines that wrap it, split at the next logical boundary as well. A paragraph written as two long sentences satisfies the sentence cap above and still asks the reader to hold too much at once. This number sits well above the bullet checkpoint because a paragraph is read straight through and a bullet is scanned.
|
|
38
38
|
- Keep bullets tight. Past roughly 400 characters in one top-level bullet, counting the lines that continue it and excluding any bullet nested under it, the overflow belongs in prose. The number is a checkpoint rather than a cap, and a bullet reading well past it means the number is wrong rather than the rule.
|
|
39
39
|
- Collapse a stack of bullets narrating one subsystem into a single `###` subsection carrying one narrative. Splitting a heavy bullet into three light ones satisfies the checkpoint above and leaves the reader no better off, and subdividing a block does not lighten the bullets inside it, so the two rules answer different defects.
|
|
40
40
|
- Use dashes (`-`) not asterisks (`*`) for bulleted lists
|