@yawlabs/ctxlint 0.8.0 → 0.9.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/AGENT_SESSION_LINT_SPEC.md +50 -1
- package/CONTEXT_LINT_SPEC.md +42 -3
- package/README.md +3 -1
- package/agent-session-lint-rules.json +18 -0
- package/context-lint-rules.json +30 -0
- package/dist/index.js +593 -186
- package/package.json +1 -1
|
@@ -44,6 +44,8 @@ This is the third pillar alongside context file linting (`CLAUDE.md`, `.cursorru
|
|
|
44
44
|
- [2.3 session/missing-workflow](#23-sessionmissing-workflow)
|
|
45
45
|
- [2.4 session/stale-memory](#24-sessionstale-memory)
|
|
46
46
|
- [2.5 session/duplicate-memory](#25-sessionduplicate-memory)
|
|
47
|
+
- [2.6 session/consecutive-repeat](#26-sessionconsecutive-repeat)
|
|
48
|
+
- [2.7 session/cyclic-pattern](#27-sessioncyclic-pattern)
|
|
47
49
|
- [3. Rule Catalog (machine-readable)](#3-rule-catalog-machine-readable)
|
|
48
50
|
- [4. Implementing This Specification](#4-implementing-this-specification)
|
|
49
51
|
- [5. Contributing](#5-contributing)
|
|
@@ -125,7 +127,7 @@ Skip hidden directories (starting with `.`) and `node_modules`.
|
|
|
125
127
|
|
|
126
128
|
## 2. Lint Rules
|
|
127
129
|
|
|
128
|
-
|
|
130
|
+
7 rules in 1 category (`session`). All rules in this category perform cross-project checks using sibling detection or per-project history analysis.
|
|
129
131
|
|
|
130
132
|
Severity levels:
|
|
131
133
|
- **error** -- the session data reveals a verifiably missing configuration. Should fail CI.
|
|
@@ -263,6 +265,53 @@ Detects memory entries from different projects that have significant content ove
|
|
|
263
265
|
|
|
264
266
|
---
|
|
265
267
|
|
|
268
|
+
### 2.6 session/consecutive-repeat
|
|
269
|
+
|
|
270
|
+
Detects when an agent runs the same command 3 or more times consecutively, indicating a loop.
|
|
271
|
+
|
|
272
|
+
| Field | Value |
|
|
273
|
+
|---|---|
|
|
274
|
+
| **Rule ID** | `session/consecutive-repeat` |
|
|
275
|
+
| **Severity** | warning |
|
|
276
|
+
| **Trigger** | 3+ consecutive history entries with identical `display` values for the current project |
|
|
277
|
+
| **Message** | `Command run <N> times consecutively: "<command>"` |
|
|
278
|
+
|
|
279
|
+
**Detection algorithm:**
|
|
280
|
+
|
|
281
|
+
1. Filter history entries to the current project path (normalized).
|
|
282
|
+
2. Sort entries by timestamp.
|
|
283
|
+
3. Slide a window over the sorted entries. For each run of 3+ entries with identical `display` values, emit a warning.
|
|
284
|
+
|
|
285
|
+
**Notes:**
|
|
286
|
+
- Truncates long command strings to 80 characters in the message for readability.
|
|
287
|
+
- This rule helps surface cases where an agent is stuck retrying a failing command instead of changing approach.
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
### 2.7 session/cyclic-pattern
|
|
292
|
+
|
|
293
|
+
Detects short repeating cycles of commands, indicating an agent stuck in a loop.
|
|
294
|
+
|
|
295
|
+
| Field | Value |
|
|
296
|
+
|---|---|
|
|
297
|
+
| **Rule ID** | `session/cyclic-pattern` |
|
|
298
|
+
| **Severity** | warning |
|
|
299
|
+
| **Trigger** | A sequence of 2-3 distinct commands repeating 2+ times consecutively (e.g. A,B,A,B) |
|
|
300
|
+
| **Message** | `Cyclic pattern repeated <N> times: <cycle>` |
|
|
301
|
+
|
|
302
|
+
**Detection algorithm:**
|
|
303
|
+
|
|
304
|
+
1. Filter history entries to the current project, sorted by timestamp.
|
|
305
|
+
2. For cycle lengths 2 and 3, slide a window checking if the next `cycleLen` entries match the current cycle.
|
|
306
|
+
3. Cycles where every element is the same are excluded (already caught by `session/consecutive-repeat`).
|
|
307
|
+
4. Subsumption: if a shorter cycle is fully contained within an already-reported longer cycle at the same position, skip it.
|
|
308
|
+
|
|
309
|
+
**Notes:**
|
|
310
|
+
- A cycle like "edit file → run tests → edit file → run tests" is a common pattern when an agent is making iterative fixes. This rule flags when the cycle repeats enough times to suggest the agent isn't making progress.
|
|
311
|
+
- The suggestion directs users to check if a context file is missing workflow instructions.
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
266
315
|
## 3. Rule Catalog (machine-readable)
|
|
267
316
|
|
|
268
317
|
A machine-readable JSON catalog of all rules is available at [`agent-session-lint-rules.json`](./agent-session-lint-rules.json).
|
package/CONTEXT_LINT_SPEC.md
CHANGED
|
@@ -15,7 +15,7 @@ This specification defines a standard set of lint rules for validating AI agent
|
|
|
15
15
|
|
|
16
16
|
The specification includes:
|
|
17
17
|
- A complete reference of context file formats across 17 AI coding clients (21+ file patterns)
|
|
18
|
-
-
|
|
18
|
+
- 21 lint rules organized into 9 categories with defined severities
|
|
19
19
|
- A machine-readable rule and format catalog ([`context-lint-rules.json`](./context-lint-rules.json))
|
|
20
20
|
- Auto-fix definitions for rules that support automated correction
|
|
21
21
|
- Frontmatter schema requirements per client
|
|
@@ -45,6 +45,8 @@ The specification includes:
|
|
|
45
45
|
- [3.5 redundancy — inferable content](#35-redundancy--inferable-content)
|
|
46
46
|
- [3.6 contradictions — cross-file conflicts](#36-contradictions--cross-file-conflicts)
|
|
47
47
|
- [3.7 frontmatter — client metadata validation](#37-frontmatter--client-metadata-validation)
|
|
48
|
+
- [3.8 ci-coverage — CI workflow documentation](#38-ci-coverage--ci-workflow-documentation)
|
|
49
|
+
- [3.9 ci-secrets — CI secrets documentation](#39-ci-secrets--ci-secrets-documentation)
|
|
48
50
|
- [4. Rule Catalog (machine-readable)](#4-rule-catalog-machine-readable)
|
|
49
51
|
- [5. Implementing This Specification](#5-implementing-this-specification)
|
|
50
52
|
- [6. Contributing](#6-contributing)
|
|
@@ -298,7 +300,7 @@ Context files consume an agent's context window. Counting tokens helps teams und
|
|
|
298
300
|
|
|
299
301
|
## 3. Lint Rules
|
|
300
302
|
|
|
301
|
-
|
|
303
|
+
21 rules organized into 9 categories.
|
|
302
304
|
|
|
303
305
|
Severity levels:
|
|
304
306
|
- **error** — the context file has a verifiably incorrect reference or invalid metadata. Should fail CI.
|
|
@@ -537,6 +539,43 @@ Validates YAML frontmatter required by specific clients. Only applies to file fo
|
|
|
537
539
|
|
|
538
540
|
---
|
|
539
541
|
|
|
542
|
+
### 3.8 ci-coverage — CI workflow documentation
|
|
543
|
+
|
|
544
|
+
Checks that release/deploy CI workflows are documented in context files. When agents encounter a project with CI release workflows but no documentation about how releases work, they guess — often incorrectly.
|
|
545
|
+
|
|
546
|
+
| Rule ID | Severity | Trigger | Message |
|
|
547
|
+
|---|---|---|---|
|
|
548
|
+
| `ci/no-release-docs` | info | `.github/workflows/` contains release/deploy/publish workflow(s) but no context file mentions the release process | `Release workflow(s) found but no context file documents the release process` |
|
|
549
|
+
|
|
550
|
+
**Detection algorithm:**
|
|
551
|
+
|
|
552
|
+
1. Check if `.github/workflows/` exists. If not, skip.
|
|
553
|
+
2. Scan workflow filenames for release-related patterns: `release`, `deploy`, `publish`, `cd`.
|
|
554
|
+
3. For workflows not matched by filename, read the YAML `name:` field and check for the same patterns.
|
|
555
|
+
4. If no release-related workflows exist, skip (only CI/test workflows — no documentation gap).
|
|
556
|
+
5. Search all context file content for release documentation phrases (e.g., "release process", "push a v* tag", "npm publish", "deploy to").
|
|
557
|
+
6. If no context file mentions release processes, emit one info-level issue.
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
561
|
+
### 3.9 ci-secrets — CI secrets documentation
|
|
562
|
+
|
|
563
|
+
Checks that secrets referenced in CI workflow files are mentioned in context files. Undocumented secrets are a common source of agent looping — agents try to create new tokens, pull from `.npmrc`, or guess at auth setup.
|
|
564
|
+
|
|
565
|
+
| Rule ID | Severity | Trigger | Message |
|
|
566
|
+
|---|---|---|---|
|
|
567
|
+
| `ci/undocumented-secret` | info | `${{ secrets.NAME }}` found in workflow YAML but `NAME` not mentioned in any context file | `CI secret "{name}" is used in {workflow} but not mentioned in any context file` |
|
|
568
|
+
|
|
569
|
+
**Detection algorithm:**
|
|
570
|
+
|
|
571
|
+
1. Check if `.github/workflows/` exists. If not, skip.
|
|
572
|
+
2. Read all `.yml`/`.yaml` files and extract `${{ secrets.NAME }}` references via regex.
|
|
573
|
+
3. Exclude GitHub-provided secrets: `GITHUB_TOKEN`, `ACTIONS_RUNTIME_TOKEN`, `ACTIONS_RUNTIME_URL`, `ACTIONS_CACHE_URL`, `ACTIONS_ID_TOKEN_REQUEST_TOKEN`, `ACTIONS_ID_TOKEN_REQUEST_URL`, `ACTIONS_RESULTS_URL`.
|
|
574
|
+
4. For each remaining secret, search all context files for the secret name (case-insensitive, flexible underscore/space matching).
|
|
575
|
+
5. Emit one info-level issue per undocumented secret.
|
|
576
|
+
|
|
577
|
+
---
|
|
578
|
+
|
|
540
579
|
## 4. Rule Catalog (machine-readable)
|
|
541
580
|
|
|
542
581
|
A machine-readable JSON catalog of all rules and supported context file formats is available at [`context-lint-rules.json`](./context-lint-rules.json).
|
|
@@ -572,7 +611,7 @@ For each discovered file:
|
|
|
572
611
|
|
|
573
612
|
Run per-file checks (paths, commands, staleness, tokens, redundancy, frontmatter) independently per file. These can be parallelized.
|
|
574
613
|
|
|
575
|
-
Run cross-file checks (aggregate tokens, duplicate content, contradictions) after all per-file parsing is complete. These need the full set of parsed files.
|
|
614
|
+
Run cross-file checks (aggregate tokens, duplicate content, contradictions, ci-coverage, ci-secrets) after all per-file parsing is complete. These need the full set of parsed files.
|
|
576
615
|
|
|
577
616
|
### Reporting
|
|
578
617
|
|
package/README.md
CHANGED
|
@@ -75,6 +75,8 @@ Useful if you want `ctxlint` available in every project without per-project setu
|
|
|
75
75
|
| **Redundancy** | Content the agent can already infer (e.g. "We use React" when react is in package.json) |
|
|
76
76
|
| **Contradictions** | Conflicting directives across context files (e.g. "use Jest" in one, "use Vitest" in another) |
|
|
77
77
|
| **Frontmatter** | Invalid or missing YAML frontmatter in Cursor .mdc, Copilot instructions, and Windsurf rules |
|
|
78
|
+
| **CI coverage** | Release/deploy workflows in `.github/workflows/` not documented in any context file |
|
|
79
|
+
| **CI secrets** | Secrets used in CI workflows (`${{ secrets.X }}`) not mentioned in context files |
|
|
78
80
|
|
|
79
81
|
## Supported Context Files
|
|
80
82
|
|
|
@@ -221,7 +223,7 @@ Commands:
|
|
|
221
223
|
init Set up a git pre-commit hook
|
|
222
224
|
```
|
|
223
225
|
|
|
224
|
-
**Available checks:** `paths`, `commands`, `staleness`, `tokens`, `redundancy`, `contradictions`, `frontmatter`, `mcp-schema`, `mcp-security`, `mcp-commands`, `mcp-deprecated`, `mcp-env`, `mcp-urls`, `mcp-consistency`, `mcp-redundancy`
|
|
226
|
+
**Available checks:** `paths`, `commands`, `staleness`, `tokens`, `redundancy`, `contradictions`, `frontmatter`, `ci-coverage`, `ci-secrets`, `mcp-schema`, `mcp-security`, `mcp-commands`, `mcp-deprecated`, `mcp-env`, `mcp-urls`, `mcp-consistency`, `mcp-redundancy`
|
|
225
227
|
|
|
226
228
|
Passing any `mcp-*` check name implies `--mcp`.
|
|
227
229
|
|
|
@@ -68,6 +68,24 @@
|
|
|
68
68
|
"trigger": "Two memory files from different projects have >60% line overlap.",
|
|
69
69
|
"message": "\"{file1}\" and \"{file2}\" have {overlap}% content overlap",
|
|
70
70
|
"fixable": false
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"id": "session/consecutive-repeat",
|
|
74
|
+
"category": "session",
|
|
75
|
+
"severity": "warning",
|
|
76
|
+
"description": "Same command run 3+ times consecutively in agent history.",
|
|
77
|
+
"trigger": "Agent history for the current project shows the same display string 3+ times in a row.",
|
|
78
|
+
"message": "Command run {count} times consecutively: \"{command}\"",
|
|
79
|
+
"fixable": false
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"id": "session/cyclic-pattern",
|
|
83
|
+
"category": "session",
|
|
84
|
+
"severity": "warning",
|
|
85
|
+
"description": "Cyclic command pattern detected in agent history.",
|
|
86
|
+
"trigger": "Agent history shows a repeating sequence of 2-3 commands (e.g. A,B,A,B) repeated 2+ times.",
|
|
87
|
+
"message": "Cyclic pattern repeated {count} times: {cycle}",
|
|
88
|
+
"fixable": false
|
|
71
89
|
}
|
|
72
90
|
],
|
|
73
91
|
"dataSources": [
|
package/context-lint-rules.json
CHANGED
|
@@ -46,6 +46,18 @@
|
|
|
46
46
|
"name": "Client Metadata Validation",
|
|
47
47
|
"description": "Validates YAML frontmatter required by specific AI coding clients.",
|
|
48
48
|
"scope": "per-file"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"id": "ci-coverage",
|
|
52
|
+
"name": "CI Workflow Documentation",
|
|
53
|
+
"description": "Checks that release/deploy CI workflows are documented in context files.",
|
|
54
|
+
"scope": "cross-file"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"id": "ci-secrets",
|
|
58
|
+
"name": "CI Secrets Documentation",
|
|
59
|
+
"description": "Checks that CI secrets used in workflows are documented in context files.",
|
|
60
|
+
"scope": "cross-file"
|
|
49
61
|
}
|
|
50
62
|
],
|
|
51
63
|
"rules": [
|
|
@@ -269,6 +281,24 @@
|
|
|
269
281
|
"message": "No activation field — rule may not be applied automatically",
|
|
270
282
|
"fixable": false,
|
|
271
283
|
"appliesTo": ["cursor-mdc"]
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
"id": "ci/no-release-docs",
|
|
287
|
+
"category": "ci-coverage",
|
|
288
|
+
"severity": "info",
|
|
289
|
+
"description": "Release/deploy CI workflow exists but no context file documents the process.",
|
|
290
|
+
"trigger": ".github/workflows/ contains release/deploy/publish workflow but no context file mentions the release process.",
|
|
291
|
+
"message": "Release workflow found but no context file documents the release process",
|
|
292
|
+
"fixable": false
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
"id": "ci/undocumented-secret",
|
|
296
|
+
"category": "ci-secrets",
|
|
297
|
+
"severity": "info",
|
|
298
|
+
"description": "CI workflow references a secret not mentioned in any context file.",
|
|
299
|
+
"trigger": "${{ secrets.NAME }} found in workflow YAML but NAME not mentioned in any context file. GitHub-provided secrets (GITHUB_TOKEN, etc.) are excluded.",
|
|
300
|
+
"message": "CI secret \"{name}\" is used in {workflow} but not mentioned in any context file",
|
|
301
|
+
"fixable": false
|
|
272
302
|
}
|
|
273
303
|
],
|
|
274
304
|
"formats": [
|