@erclx/aitk 0.35.0 → 0.35.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "aitk",
3
3
  "description": "Automated governance, versioning, and discovery tools for Claude Code.",
4
- "version": "0.35.0",
4
+ "version": "0.35.2",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -9,6 +9,10 @@ Generate production-ready Bash scripts for DevOps and CLI workflows. Enforce str
9
9
 
10
10
  Load `${CLAUDE_SKILL_DIR}/references/patterns.md` for the timeline lifecycle, logging, interactive prompt, help-screen, and full-script code templates. `${CLAUDE_SKILL_DIR}` expands to this skill's own directory, so the path resolves from any project. Copy those definitions verbatim, keeping only the colors and functions the script actually uses.
11
11
 
12
+ ## Guards
13
+
14
+ - A request for a script with no human at the terminal stops and routes to `cli-script`. CI jobs, cron entries, agent-run tasks, and any script whose output is consumed by a pipe render no timeline, so generating one costs the frame and returns nothing.
15
+
12
16
  ## Script setup
13
17
 
14
18
  - Start with `#!/usr/bin/env bash`, `set -e`, and `set -o pipefail`.
@@ -7,6 +7,11 @@ description: Generates GitHub Actions CI workflow files with parallel jobs, emoj
7
7
 
8
8
  Generate GitHub Actions workflow files for CI pipelines. Enforce parallel job execution, emoji job naming, and gated deployment stages.
9
9
 
10
+ ## Guards
11
+
12
+ - A request for what runs inside a deploy, publish, or release job stops at the gate. Credentials, environments, and deploy targets are invisible to this skill, so emit the job with its `needs` wiring and a placeholder step, then name what the caller fills in. Never guess a deploy command.
13
+ - The build, test, and deploy commands belong to the project. Read them from its scripts rather than asserting a second copy in the workflow.
14
+
10
15
  ## Workflow setup
11
16
 
12
17
  - Include `workflow_dispatch` on every workflow alongside the primary trigger.
@@ -49,4 +54,5 @@ Before responding, verify:
49
54
  - E2E uses `needs: build`. Release and deploy use `needs: e2e`.
50
55
  - Artifacts upload on `if: failure()` only with `retention-days: 7`.
51
56
  - Job names use emoji + title format.
57
+ - Deploy, publish, and release jobs carry a placeholder step and a named handoff, never a guessed deploy command.
52
58
  - Bun projects use `oven-sh/setup-bun@v2` with `bun install --frozen-lockfile`.
@@ -55,14 +55,19 @@ Read each discovered file in parallel.
55
55
  For each discovered doc, classify as one of:
56
56
 
57
57
  - `stale`: the diff touches something the doc describes
58
+ - `departed`: the doc records a deliberate contract and the diff broke it
58
59
  - `unrelated`: no overlap between diff and doc content
59
60
 
61
+ The split between `stale` and `departed` is whether the doc was describing or promising. A doc that trailed the code is `stale`. A doc stating a contract the code was meant to keep is `departed`, and rewriting it to match the diff would record the regression as the contract.
62
+
60
63
  Classify at the section level, not the file level. A doc edited earlier in the session can still be partially stale. For each diff surface, verify the corresponding section is synced.
61
64
 
62
65
  ## Action
63
66
 
64
67
  Rewrite only the stale sections. Do not touch sections unrelated to the diff. Write the updated file immediately after the preview. Claude Code's tool permission dialog is the confirmation gate. Do not wait for user input.
65
68
 
69
+ Never rewrite a `departed` section. Leave it as written and report it as a finding, since the repair belongs in the code rather than in the prose.
70
+
66
71
  ## Response format
67
72
 
68
73
  ### Preview
@@ -73,6 +78,7 @@ Rewrite only the stale sections. Do not touch sections unrelated to the diff. Wr
73
78
  | Doc | Status | Action |
74
79
  | ----------- | --------- | ------ |
75
80
  | README.md | stale | update |
81
+ | docs/cli.md | departed | report |
76
82
  | docs/api.md | unrelated | skip |
77
83
 
78
84
  After outputting the preview, write all stale updates immediately.
@@ -84,4 +90,5 @@ One line per file, using the same relative path format as the preview table (e.g
84
90
  ```plaintext
85
91
  ✅ Updated: <relative-path>
86
92
  ⏭️ Skipped: <relative-path>
93
+ ⚠️ Departed: <relative-path> records <the contract>, and the diff <what it did>. Left unwritten.
87
94
  ```
@@ -9,6 +9,8 @@ description: What pull request generation is for, the gaps it closes, and what i
9
9
 
10
10
  Without this skill, a pull request body is written from memory of the branch rather than from its diff, so it describes the intent and omits what the work turned into. Testing boxes get ticked from intent, which records what was meant to run instead of what ran, and a reviewer trusts the list. A second push either errors on create or opens a duplicate pull request, and banned characters survive into a body the hook never sees.
11
11
 
12
+ A lookup that resolves by head branch alone carries its own failure. A branch name reused after an earlier pull request merged resolves to the closed one, so the run rewrites a merged pull request's title and body and reports its URL as the one it opened. Both fields are recoverable only through the issue timeline and the edit history, and nothing reports that the write landed on the wrong object.
13
+
12
14
  ## Must
13
15
 
14
16
  - Refuse a branch name that does not conform, since the name lands on the pull request permanently and renaming it afterward breaks the link
@@ -17,12 +19,15 @@ Without this skill, a pull request body is written from memory of the branch rat
17
19
  - Leave a box unchecked only for a human-only case, naming which human and why on the same line
18
20
  - Scan the title and body for banned characters and internal phase labels as an explicit step, on top of reading the prose standard
19
21
  - Detect an open pull request and edit it in place, so a follow-up push keeps the body in sync instead of failing
22
+ - Scope that detection to an open pull request on the current head and the default base, so neither a reused branch name nor a second base resolves the wrong one
23
+ - Resolve the pull request once and reuse what that resolution returned, so the number recorded never depends on how a lookup ranks two pull requests sharing a head
20
24
 
21
25
  ## Must not
22
26
 
23
27
  - Tick a testing box from intent or from a past session. The box records a run.
24
28
  - Put a request for the reviewer in the Testing list, since a request is not a result
25
29
  - Create a second pull request when one is open
30
+ - Edit a pull request that is not open, or record its number on a task
26
31
  - Emit anything after the result line
27
32
 
28
33
  ## Guards
@@ -71,9 +71,19 @@ Leave a box unchecked only for the human-only cases the reference defines, and n
71
71
 
72
72
  Before running the final command, run the scan in `.claude/standards/publish.md` against the PR title and body, or `${CLAUDE_SKILL_DIR}/../../standards/publish.md` when the project does not have it. The title and body go straight to the remote with nothing checking them on the way, so this scan is the only gate. It covers the phase-label check as well as the characters, since both go to a reader who has no task board. It applies on top of the banned phrases in `${CLAUDE_SKILL_DIR}/references/pr.md`.
73
73
 
74
+ ### Resolving the pull request
75
+
76
+ The run resolves the pull request once, in the final command below, and every later step reads what that command printed. Nothing else looks the number up again.
77
+
78
+ `gh pr view` is the form this replaces. It resolves by head branch and ignores state, so a branch name reused after an earlier pull request merged returns the closed one. The detection then takes the edit path and rewrites a merged pull request's title and body, and the run reports that pull request's URL as the one it opened, so nothing surfaces the write landing on the wrong object. Scoping the lookup with `--state open` returns empty there and sends the run down the create path.
79
+
80
+ The lookup scopes to the base as well as the head. One head can carry open pull requests against two bases, and a lookup reading the first result would pick between them by list order. Resolving the base from the repository's default branch is what makes the detection and `gh pr create` agree on which pull request the run is about.
81
+
82
+ A detached HEAD gives `git branch --show-current` an empty result, which would read as no open pull request and create a second one. The branch-name guard above stops the run first, since an empty name does not match `<type>/<description>`.
83
+
74
84
  ### Final command
75
85
 
76
- Detect an existing PR and branch: edit it in place when one is open, create it otherwise. This keeps the body in sync on a follow-up push instead of erroring on `gh pr create`.
86
+ Detect an open pull request on the current head and branch: edit it in place when one exists, create it otherwise. This keeps the body in sync on a follow-up push instead of erroring on `gh pr create`.
77
87
 
78
88
  ```bash
79
89
  mkdir -p .claude/.tmp/pr
@@ -81,21 +91,21 @@ cat <<'BODY' > .claude/.tmp/pr/body.md
81
91
  <body content following pr.md template exactly>
82
92
  BODY
83
93
  git push -u origin HEAD || exit 1
84
- if gh pr view --json number >/dev/null 2>&1; then
85
- gh pr edit --title "<title>" --body-file .claude/.tmp/pr/body.md
94
+ base_branch=$(gh repo view --json defaultBranchRef --jq .defaultBranchRef.name) || exit 1
95
+ pr_number=$(gh pr list --head "$(git branch --show-current)" --base "$base_branch" --state open --json number --jq '.[0].number // empty')
96
+ if [ -n "$pr_number" ]; then
97
+ pr_url=$(gh pr edit "$pr_number" --title "<title>" --body-file .claude/.tmp/pr/body.md) || exit 1
86
98
  else
87
- gh pr create --title "<title>" --body-file .claude/.tmp/pr/body.md
99
+ pr_url=$(gh pr create --title "<title>" --body-file .claude/.tmp/pr/body.md) || exit 1
100
+ pr_number=${pr_url##*/}
88
101
  fi
89
102
  rm -rf .claude/.tmp/pr
103
+ printf 'number=%s\nurl=%s\n' "$pr_number" "$pr_url"
90
104
  ```
91
105
 
92
106
  ### Record the number on the task
93
107
 
94
- Resolve the number the run created or edited, then write it onto the task the branch is closing:
95
-
96
- ```bash
97
- gh pr view --json number --jq .number
98
- ```
108
+ Write the `number` the final command printed onto the task the branch is closing. Do not resolve it again. A head branch that carried an earlier pull request now has two, and a second `gh pr view` would pick between them by a precedence rule nothing here states. Reading what created or edited the pull request needs no such rule.
99
109
 
100
110
  Find the task by reading `.claude/tasks/` at the main worktree root, resolved with `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`. The board is shared scratch, so a linked worktree writing to its own `pwd` creates a second board nothing reads.
101
111
 
@@ -107,7 +117,7 @@ The number is what lets the merge close the task. Every merge on `main` is a squ
107
117
 
108
118
  ## After execution
109
119
 
110
- Respond with exactly one line:
120
+ Respond with exactly one line, using the `url` the final command printed:
111
121
 
112
122
  `✅ PR: <url>`
113
123
 
@@ -7,6 +7,8 @@ description: Classifies each section of a target project's bloated `CLAUDE.md` i
7
7
 
8
8
  Rebalance a large `CLAUDE.md` so only always-load behavior stays in it, path-scoped behavior becomes a rule, and domain narrative becomes a context entry. Every move is a proposal the user applies by hand.
9
9
 
10
+ Run `migration-context` first when both apply. Its moves populate `.claude/context/`, and Step 3 has to read the folder those moves left so an existing entry resolves to an append rather than blocking the move that should have created it.
11
+
10
12
  ## Guards
11
13
 
12
14
  - If no `CLAUDE.md` exists at `pwd`, stop: `❌ No CLAUDE.md found at the project root.`
@@ -5,6 +5,8 @@ description: Classifies markdown files in a target project's `docs/` folder and
5
5
 
6
6
  # Claude context migrate
7
7
 
8
+ Run this skill before `migration-claude-md` when both apply. That skill proposes entries into the same `.claude/context/` folder, and an entry landing there first makes the corresponding move here read as a conflict and get skipped, which loses the richer `docs/` file.
9
+
8
10
  ## Guards
9
11
 
10
12
  - If no `docs/` directory exists at `pwd`, stop: `❌ No docs/ directory found.`
@@ -36,13 +36,14 @@ Match the detected evidence to the catalog:
36
36
 
37
37
  If a detected technology has no matching rule, stop and surface the gap. Do not guess.
38
38
 
39
- Present three options:
39
+ Present four options:
40
40
 
41
- 1. Author a new rule in the toolkit at `governance/rules/<domain>/<num>-<name>.md` following `.claude/standards/rule.md`, or `${CLAUDE_SKILL_DIR}/../../standards/rule.md` when the project does not have it, commit, then re-run install.
42
- 2. Install the matching non-<tech> rules and skip the tech-specific layer.
43
- 3. Abort.
41
+ 1. Author a new rule in the toolkit at `governance/rules/<domain>/<num>-<name>.md` following `.claude/standards/rule.md`, or `${CLAUDE_SKILL_DIR}/../../standards/rule.md` when the project does not have it, commit, then re-run install. Take this route when the toolkit should ship the rule to every project.
42
+ 2. Invoke `create-rule`, which scaffolds the file into the target project at a non-colliding number. Take this route when the rule is specific to this project and no sync should ever overwrite it.
43
+ 3. Install the matching non-<tech> rules and skip the tech-specific layer.
44
+ 4. Abort.
44
45
 
45
- Rules are authored in the toolkit repository, never in the target project on the fly.
46
+ This skill authors no rule itself. Option 1 writes in the toolkit repository, and option 2 hands the project-local file to `create-rule`.
46
47
 
47
48
  ## Preview
48
49
 
@@ -10,6 +10,7 @@ Orchestrates the onboarding chain. Detects project type, resolves per-domain arg
10
10
  ## Scope
11
11
 
12
12
  - This skill and `aitk init` run once on a fresh scaffold, never on an existing project. They do not guard against clobbering existing configs. When tempted to add guards, mode switches, or an existing-project branch, stop. Extend the per-domain `aitk <domain> install` or `aitk sync` paths instead.
13
+ - The chain does not bootstrap the `index.md` system and does not provision Claude Code plugins. `setup-indexes` owns the first. `setup-plugins` owns the second, which installs once per machine rather than into a project, so no project-scoped chain can carry it. Name both in the report so a clean result does not read as onboarding complete.
13
14
 
14
15
  ## Read catalogs
15
16
 
@@ -112,3 +113,4 @@ After the chain, report:
112
113
  - `setup-verify` outcome
113
114
  - Any domains or scripts that failed
114
115
  - Any detection gaps surfaced during resolve
116
+ - Onboarding steps left to the caller: `setup-indexes` for the `index.md` system, `setup-plugins` for Claude Code plugins
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/aitk",
3
3
  "type": "module",
4
- "version": "0.35.0",
4
+ "version": "0.35.2",
5
5
  "description": "Infrastructure and quality tooling for developer workflows",
6
6
  "license": "MIT",
7
7
  "bin": {