@erclx/aitk 0.83.0 → 0.85.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.
@@ -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.83.0",
4
+ "version": "0.85.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -40,7 +40,13 @@ The map is authored by hand and nothing detects a directory it fails to cover, s
40
40
 
41
41
  Apply labels after the pull request resolves, never as a flag on the create. `gh pr create --label` fails whole on a label the remote does not carry, so a name the map got wrong opens no pull request at all and the run stops with the branch pushed and nothing to review. A `gh pr edit --add-label` against a pull request that already exists costs a warning instead, and it is one command across both the create and the edit path rather than two flags that have to stay in step.
42
42
 
43
- `--add-label` adds and never removes. A label a person applied by hand is not this skill's to strip, so a domain that stops applying between two pushes keeps its label until someone takes it off.
43
+ Labelling runs whenever this skill runs and at no other time. Nothing else computes the set, so a push made any other way leaves the labels exactly as the last run left them. Any caller invoking this skill again reaches the step again, and it recomputes over the whole branch diff rather than over the new commits.
44
+
45
+ An ordinary branch therefore labels once, when the pull request opens. The return leg that answers a review hands its push to `git-followup`, which refreshes the body without invoking this skill, so the commits that answer a review reach no labelling step.
46
+
47
+ A follow-up push reaching a surface the earlier ones did not merges under-labelled, with nothing to report the miss. Keeping the step in one skill is worth that cost, since a review fix lands in the files the review named and rarely opens a surface the branch had not already touched.
48
+
49
+ `--add-label` adds and never removes. A label a person applied by hand is not this skill's to strip, and a re-run over a branch that has since dropped a surface keeps the label that surface earned.
44
50
 
45
51
  ## A label the remote does not carry
46
52
 
@@ -116,7 +116,9 @@ Four surfaces read the ban sets and two of them go through this verb. `.claude/h
116
116
 
117
117
  The other two read the standards directly and neither is a consolidation left half done. `claude/skills/claude-standards-audit/SKILL.md` greps the banned tokens agent-side, which is a session reading prose rather than a process it can shell out to, and it ships to every target. The seed copy of the hook keeps its awk, because a scaffolded project may carry no `aitk` and `scripts/core/check-seed-independence.sh` exists to catch seed content depending on the toolkit CLI. Both are the likelier place for the next drift, since nothing compares either against the verb.
118
118
 
119
- The hook prefers a checkout's own `src/cli.ts` over a globally installed binary, so it and the push stage read one build. A published binary lags a branch by whatever has not been released, which would put a ban kind added on the branch into the push and not into the edit. It reads its findings out of the `--json` record rather than off the exit code, so an older binary still reports where the fallback applies. A machine with neither runner gets no enforcement at edit time rather than a blocked edit, and the push stage still holds.
119
+ The hook prefers a checkout's own `src/cli.ts` over a globally installed binary, so it and the push stage read one build. A published binary lags a branch by whatever has not been released, which would put a ban kind added on the branch into the push and not into the edit. It reads its findings out of the `--json` record rather than off the exit code, so an older binary still reports where the fallback applies. It reads `bans.missingStandards` out of the same record, so a standard the verb found under neither root reaches the author as a check narrowed to what it could read.
120
+
121
+ A machine with neither runner still blocks no edit, and it says so rather than exiting clean. The push stage holds either way. An edit nobody checked and an edit carrying no violation are one silence to a reader, so the enforcement a machine lacks is reported rather than inferred.
120
122
 
121
123
  The stage measures the whole corpus rather than the changed files. A `Do not use` bullet added to a standard bans a token retroactively, and no file in the push that adds the bullet was edited.
122
124
 
@@ -6,7 +6,15 @@ paths:
6
6
 
7
7
  # Wireframe standards
8
8
 
9
+ ## Layout and intent
10
+
11
+ - Draw each surface as an ASCII block inside a `plaintext` fence, one fence per distinct layout.
12
+ - Label a region with its role. Never label one with a class name, a token name, or a computed value.
13
+ - Carry on-screen copy verbatim, and mark copy the surface templates.
14
+ - State interaction intent, never the mechanism behind it. Send algorithms, handlers, and thresholds to a `.claude/context/` entry.
15
+ - Update a surface's wireframe in the same pull request that changes its layout or its interaction.
16
+
9
17
  ## Authority
10
18
 
11
19
  - Follow `.claude/standards/wireframes.md` for layout and interaction intent: ASCII layout, region labels, variants, copy, and what moves to `.claude/context/`. It is the single source.
12
- - A wireframe carries layout and intent, not implementation. Read the standard before adding or revising a surface.
20
+ - Read it before adding or revising a surface.
@@ -6,6 +6,14 @@ paths:
6
6
 
7
7
  # Requirements standards
8
8
 
9
+ ## Scope and non-goals
10
+
11
+ - State a goal as a user-facing outcome, never as the implementation delivering it.
12
+ - Record explicit non-goals. Mark a deferred item `(deferred)`.
13
+ - Leave the MVP list as written once its features ship. Do not renumber it, extend it, or annotate an entry with status.
14
+ - Add later scope as a new section rather than as an extension of the MVP list.
15
+ - Drop a section rather than pad it. Include `## Distribution` only when the project ships outside its own repository.
16
+
9
17
  ## Authority
10
18
 
11
19
  - Follow `.claude/standards/requirements.md` for what belongs in the problem, goals, non-goals, MVP features, tech stack, and constraints. It is the single source.
@@ -6,6 +6,16 @@ paths:
6
6
 
7
7
  # Architecture standards
8
8
 
9
+ ## Decisions
10
+
11
+ - Give each decision its own H3 under `## Key technical decisions`, naming what it chose and the alternative it passed over.
12
+ - Keep line-by-line function behavior and full type definitions out.
13
+
14
+ ## Verification anchors
15
+
16
+ - Close a decision citing a measured number with `Measured at <short-sha> on <YYYY-MM-DD>.` Leave a decision citing none unanchored.
17
+ - Refresh that anchor whenever the number is re-read, whether or not it moved.
18
+
9
19
  ## Authority
10
20
 
11
21
  - Follow `.claude/standards/architecture.md` for the overview, named decision entries, and risks. It is the single source.
@@ -6,6 +6,14 @@ paths:
6
6
 
7
7
  # Design standards
8
8
 
9
+ ## Tokens
10
+
11
+ - Describe a token as intent rather than as a computed value.
12
+ - Keep CSS classes, component filenames, and prop names out.
13
+ - Carry a token system as a table, one row per token, and a component rule as a short bullet.
14
+ - Keep the token table headers verbatim.
15
+ - Record a non-obvious omission, such as no motion or no custom icons.
16
+
9
17
  ## Authority
10
18
 
11
19
  - Follow `.claude/standards/design.md` for visual intent, the token tables, and the render contract. It is the single source.
@@ -6,6 +6,14 @@ paths:
6
6
 
7
7
  # Tasks standards
8
8
 
9
+ ## What a task carries
10
+
11
+ - Name where the task came from, through a `Plan:`, `Groundwork:`, `Intake:`, or `Issue:` line under the title.
12
+ - Size the outcomes so one pull request closes all of them. Split the task before handing it off.
13
+ - Use `## Outcomes` and `## Findings` and add no third heading. Note status inline on an outcome.
14
+ - Keep class names, file paths, function names, and prop names out of every entry and title.
15
+ - Never delete a task file. A shipped task moves to the archive under its own name.
16
+
9
17
  ## Authority
10
18
 
11
19
  - Follow `.claude/standards/tasks.md` for filenames, frontmatter, what belongs, and the task file format. It is the single source.
@@ -6,6 +6,14 @@ paths:
6
6
 
7
7
  # README standards
8
8
 
9
+ ## Audience and voice
10
+
11
+ - Write a repository-root README for someone deciding whether to commit to the project. A nested README keeps the reference voice.
12
+ - Address the reader in second person.
13
+ - Ground a claim in a command, a number, or a named constraint rather than an adjective.
14
+ - Name what the project does not do.
15
+ - Link out to full API documentation, license text, contribution guidelines, and troubleshooting rather than carrying them.
16
+
9
17
  ## Authority
10
18
 
11
19
  - Follow `.claude/standards/readme.md` for voice, structure, required and optional sections, heading hierarchy, badge classes, per-project-type content, and what to link out rather than inline. It is the single source.
@@ -6,6 +6,17 @@ paths:
6
6
 
7
7
  # Rule authoring standards
8
8
 
9
+ ## Numbering
10
+
11
+ - Name a rule `.claude/rules/<subdirectory>/<n>-<slug>.md`, taking a number that collides with neither the project's rules nor any installed shared set.
12
+ - Give every rule a numeric prefix and keep the slug to one to three kebab words.
13
+
14
+ ## Body
15
+
16
+ - State one directive per bullet in imperative voice. Do not explain the reasoning behind a rule.
17
+ - Cut a rule that resists crisp one-line phrasing.
18
+ - Do not restate a rule a sibling rule or `CLAUDE.md` already owns. Point once.
19
+
9
20
  ## Authority
10
21
 
11
22
  - Follow `.claude/standards/rule.md` for rule frontmatter, body shape, and voice. It is the single source.
@@ -7,6 +7,14 @@ paths:
7
7
 
8
8
  # Standard authoring standards
9
9
 
10
+ ## The scope statement
11
+
12
+ - Govern one document type per standard, or one attribute across every document.
13
+ - Open with a `## Scope` section naming what the standard governs and a `Does not govern:` list, placed above the shape rules.
14
+ - Put the governed path in backticks in the first sentence, anchored deep enough to resolve from a project root. Keep an attribute standard's first sentence free of backticks and say in it that it governs an attribute.
15
+ - Give each `Does not govern:` entry an excluded concern and the owner it goes to. Cut an entry naming no owner.
16
+ - Declare a yield, an exemption, or a handoff from both sides of the boundary.
17
+
10
18
  ## Authority
11
19
 
12
20
  - Follow `.claude/standards/standard.md` for a standard's frontmatter, shape, scope, and success criterion. It is the single source.
@@ -12,4 +12,5 @@ description: Enforce planning standards before implementation
12
12
  - State where the search ran and why each candidate was rejected. Do not assert a search without naming its results.
13
13
  - Propose the simplest solution that satisfies the requirement before implementing complex patterns.
14
14
  - Write or update tests as part of every implementation plan.
15
+ - Write the test for a behavior before the code that implements it. Confirm visual output after implementing it, not before.
15
16
  - Do not modify code without a confirmed plan.
@@ -0,0 +1,25 @@
1
+ ---
2
+ description: Require a dependency to be declared in the manifest before it is imported
3
+ paths:
4
+ - '**/*.ts'
5
+ - '**/*.tsx'
6
+ - '**/*.js'
7
+ - '**/*.jsx'
8
+ - '**/*.py'
9
+ - '**/package.json'
10
+ - '**/pyproject.toml'
11
+ ---
12
+
13
+ # Dependency standards
14
+
15
+ ## Declaration
16
+
17
+ - Declare a package in the project manifest before importing it anywhere in the source.
18
+ - Add a package with the package manager command that writes the manifest and the lockfile together, such as `bun add` or `uv add`. Never hand-edit the manifest and never install without recording the result.
19
+ - Commit the lockfile with the manifest change in the same commit.
20
+ - Declare a package used only by tests, builds, or tooling as a development dependency.
21
+ - Never import a package that arrives only as a transitive dependency of another package.
22
+
23
+ ## Removal
24
+
25
+ - Remove a package from the manifest in the change that removes its last import.
@@ -32,7 +32,7 @@ paths:
32
32
  ## Conventions
33
33
 
34
34
  - Use `.test.ts` / `.test.tsx` for unit tests.
35
- - Use `.spec.ts` / `.spec.tsx` for integration tests.
35
+ - Use `.spec.ts` / `.spec.tsx` for integration tests and for Playwright tests under `e2e/`.
36
36
  - Do not make real network calls in unit tests.
37
37
  - `describe()` labels use the exact identifier of the subject under test in its natural casing.
38
38
  - `it()` descriptions use "should" + sentence case.
@@ -0,0 +1,39 @@
1
+ ---
2
+ description: Enforce server-side authorization, secret handling, and abuse limits on request handlers
3
+ paths:
4
+ - '**/*.py'
5
+ - '**/*.ts'
6
+ - '**/*.js'
7
+ ---
8
+
9
+ # Server security standards
10
+
11
+ ## Authorization
12
+
13
+ - Authorize every request on the server, whatever the client already checked.
14
+ - Derive the caller identity from the verified session or token. Never read it from a request body, query string, or header the client sets.
15
+ - Check that the caller owns or may reach the specific record a request names, not only that the caller is signed in.
16
+ - Deny by default. Grant a route access through an explicit allow.
17
+
18
+ ## Credentials
19
+
20
+ - Hash passwords with a memory-hard algorithm and a per-record salt. Never store a reversible password.
21
+ - Compare tokens, signatures, and password hashes with a constant-time function.
22
+ - Expire and revoke sessions and refresh tokens on the server. Do not rely on client-side deletion.
23
+
24
+ ## Secrets
25
+
26
+ - Read every secret from the environment or a secret manager at runtime.
27
+ - Never commit a secret, connection string, or private key to the repository.
28
+ - Never return a secret, connection string, or internal hostname in a response body.
29
+
30
+ ## Abuse limits
31
+
32
+ - Rate-limit authentication, password reset, and any endpoint that sends mail or costs money per call.
33
+ - Set an explicit maximum body size and request timeout on every endpoint.
34
+ - Bound pagination parameters with a server-side maximum.
35
+
36
+ ## Transport
37
+
38
+ - Serve every route over TLS and reject plaintext requests.
39
+ - Restrict CORS to an explicit origin list. Never reflect the request origin or pair a wildcard with credentials.
@@ -0,0 +1,35 @@
1
+ ---
2
+ description: Enforce persistence boundaries for migrations, query construction, transactions, and rollback
3
+ paths:
4
+ - '**/*.py'
5
+ - '**/*.ts'
6
+ - '**/*.js'
7
+ - '**/*.sql'
8
+ ---
9
+
10
+ # Persistence standards
11
+
12
+ ## Schema changes
13
+
14
+ - Express every schema change as a migration file committed to version control.
15
+ - Ship a tested rollback path with every migration that changes a schema.
16
+ - Never alter a deployed schema outside a migration.
17
+ - Never edit a migration that has run in a shared environment. Add a new one.
18
+ - Separate a destructive migration from the deploy that stops reading the dropped column.
19
+
20
+ ## Query construction
21
+
22
+ - Pass every runtime value as a bound parameter.
23
+ - Never interpolate, concatenate, or format a value into a statement string.
24
+ - Name the columns a read needs. Do not select every column by wildcard.
25
+
26
+ ## Transactions
27
+
28
+ - Give each transaction one owner that opens it, commits it, and rolls it back.
29
+ - Never open a transaction inside a function that was handed one.
30
+ - Keep network calls, queue publishes, and filesystem writes outside an open transaction.
31
+
32
+ ## Access patterns
33
+
34
+ - Load related rows in the query that fetches their parents. Do not resolve a relation lazily inside an iteration.
35
+ - Scope a connection or session to the request that opened it and release it on exit.
@@ -1,2 +1,2 @@
1
1
  extends = "base"
2
- rules = ["110-python", "340-pydantic", "330-testing-py"]
2
+ rules = ["110-python", "340-pydantic", "330-testing-py", "360-security-server", "370-database"]
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/aitk",
3
3
  "type": "module",
4
- "version": "0.83.0",
4
+ "version": "0.85.0",
5
5
  "description": "Infrastructure and quality tooling for developer workflows",
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -33,6 +33,7 @@ esac
33
33
  # bullet added to markdown.md is parsed by nothing and enforces silently.
34
34
  standard="${CLAUDE_PROJECT_DIR:-.}/.claude/standards/prose.md"
35
35
  words=""
36
+ unread=""
36
37
  if [ -f "$standard" ]; then
37
38
  words=$(grep '^- Do not use ' "$standard" |
38
39
  grep -o '`[^`]*`' |
@@ -40,6 +41,12 @@ if [ -f "$standard" ]; then
40
41
  grep -x '[a-z][a-z]*' |
41
42
  sort -u |
42
43
  paste -sd '|' -)
44
+ else
45
+ # An absent standard empties the word list, and the awk below reads an empty
46
+ # list as nothing to look for rather than as nothing found. The path is kept
47
+ # so the report names what could not be read, since a file carrying no banned
48
+ # word and a file nobody checked produce the same silence otherwise.
49
+ unread="$standard"
43
50
  fi
44
51
 
45
52
  hits=$(awk -v words="$words" '
@@ -66,8 +73,18 @@ hits=$(awk -v words="$words" '
66
73
  }
67
74
  ' "$file")
68
75
 
69
- [ -z "$hits" ] && exit 0
76
+ [ -z "$hits" ] && [ -z "$unread" ] && exit 0
70
77
 
71
- msg=$(printf 'Standards-audit: prose.md and markdown.md violations in %s. Rewrite or restructure (do not lazy-swap).\n%s' "$file" "$hits")
78
+ nl=$'\n'
79
+ msg=""
80
+
81
+ if [ -n "$unread" ]; then
82
+ msg=$(printf 'Standards-audit: no word ban checked in %s. Found no standard at %s, so only the character bans ran. Restore it with `aitk standards install`.' "$file" "$unread")
83
+ fi
84
+
85
+ if [ -n "$hits" ]; then
86
+ found=$(printf 'Standards-audit: prose.md and markdown.md violations in %s. Rewrite or restructure (do not lazy-swap).\n%s' "$file" "$hits")
87
+ msg="${msg:+$msg$nl}$found"
88
+ fi
72
89
 
73
90
  jq -nc --arg msg "$msg" '{hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:$msg}}'