@pragmatiks/lint 0.6.0 → 0.8.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/CHANGELOG.md +16 -0
- package/README.md +4 -4
- package/package.json +1 -1
- package/src/semgrep-rules/pra_io_prefix_mismatch.yml +29 -2
- package/src/semgrep-rules/pra_no_block_comments_js.yml +6 -0
- package/src/semgrep-rules/pra_no_todo_comments_js.yml +6 -0
- package/src/semgrep-rules/pra_pure_prefix_mismatch.yml +78 -0
- package/src/semgrep-rules/pra_no_block_comments.yml +0 -11
- package/src/semgrep-rules/pra_no_todo_comments.yml +0 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## js-v0.8.0 (2026-11-07)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- **rules**: flag pure-prefixed functions that perform I/O (PRA-453, PRA-750)
|
|
8
|
+
|
|
9
|
+
## js-v0.7.0 (2026-10-07)
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
- **rules**: recognize Path.open and with-open as file I/O in pra-io-prefix-mismatch
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
- **rules**: drop the Python comment rules the strict comment check replaces
|
|
18
|
+
|
|
3
19
|
## js-v0.6.0 (2026-09-27)
|
|
4
20
|
|
|
5
21
|
### Features
|
package/README.md
CHANGED
|
@@ -142,7 +142,7 @@ Fix these by rewriting the code:
|
|
|
142
142
|
|
|
143
143
|
## Development
|
|
144
144
|
|
|
145
|
-
| Command
|
|
146
|
-
|
|
|
147
|
-
| `
|
|
148
|
-
| `
|
|
145
|
+
| Command | Purpose |
|
|
146
|
+
| -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
147
|
+
| `mise run js:check` / `mise run js:test` / `mise run js:build` | Lint and type check / tests (Node `>=22.15` for `module.registerHooks`; `mise.toml` pins Node 26) / build |
|
|
148
|
+
| `mise run js:pack` | Install, build and `npm pack` the committed HEAD as CI publishes it, with the mise-locked node, pnpm and npm, in a throwaway worktree, printing all three versions; the tarball lands in `js/` |
|
package/package.json
CHANGED
|
@@ -26,6 +26,23 @@ rules:
|
|
|
26
26
|
...
|
|
27
27
|
open(...)
|
|
28
28
|
...
|
|
29
|
+
- pattern-not: |
|
|
30
|
+
def $NAME(...):
|
|
31
|
+
...
|
|
32
|
+
with open(...) as $HANDLE:
|
|
33
|
+
...
|
|
34
|
+
...
|
|
35
|
+
- pattern-not: |
|
|
36
|
+
def $NAME(...):
|
|
37
|
+
...
|
|
38
|
+
$PATH.open(...)
|
|
39
|
+
...
|
|
40
|
+
- pattern-not: |
|
|
41
|
+
def $NAME(...):
|
|
42
|
+
...
|
|
43
|
+
with $PATH.open(...) as $HANDLE:
|
|
44
|
+
...
|
|
45
|
+
...
|
|
29
46
|
- pattern-not: |
|
|
30
47
|
def $NAME(...):
|
|
31
48
|
...
|
|
@@ -86,6 +103,16 @@ rules:
|
|
|
86
103
|
...
|
|
87
104
|
$PATH.rmdir(...)
|
|
88
105
|
...
|
|
106
|
+
- pattern-not: |
|
|
107
|
+
def $NAME(...):
|
|
108
|
+
...
|
|
109
|
+
$PATH.resolve(...)
|
|
110
|
+
...
|
|
111
|
+
- pattern-not: |
|
|
112
|
+
def $NAME(...):
|
|
113
|
+
...
|
|
114
|
+
importlib.import_module(...)
|
|
115
|
+
...
|
|
89
116
|
- pattern-not: |
|
|
90
117
|
def $NAME(...):
|
|
91
118
|
...
|
|
@@ -96,10 +123,10 @@ rules:
|
|
|
96
123
|
...
|
|
97
124
|
subprocess.$METHOD(...)
|
|
98
125
|
...
|
|
99
|
-
- pattern-not-regex: '(?s)\bos\.(mkdir|makedirs|rmdir|removedirs|remove|unlink|rename|replace|kill|chdir|chmod|chown|symlink|link|stat|lstat|listdir|scandir|access|system|popen|path\.(exists|isfile|isdir|islink|getsize))\('
|
|
126
|
+
- pattern-not-regex: '(?s)\bos\.(mkdir|makedirs|rmdir|removedirs|remove|unlink|rename|replace|kill|chdir|chmod|chown|symlink|link|stat|lstat|listdir|scandir|access|system|popen|path\.(exists|isfile|isdir|islink|getsize|realpath))\('
|
|
100
127
|
- pattern-not-regex: '(?s)(database|session|connection|cursor|client)\.(execute|fetch|get|post|put|delete|query|read|write|save)\('
|
|
101
128
|
message: "principle #7 I/O-prefixed function appears pure. Rename it with compute, build, derive, format, or parse."
|
|
102
129
|
severity: WARNING
|
|
103
130
|
languages: [python]
|
|
104
131
|
metadata:
|
|
105
|
-
note: "Heuristic rule; false positives are expected for hidden I/O wrappers."
|
|
132
|
+
note: "Heuristic rule; false positives are expected for hidden I/O wrappers. The I/O vocabulary mirrors pra-pure-prefix-mismatch in opposite polarity; keep both rules in step."
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
rules:
|
|
2
|
+
- id: pra-no-block-comments-js
|
|
3
|
+
pattern-regex: '/\*(?!\*)[\s\S]*?\*/'
|
|
4
|
+
message: "principle #10 Block comments make code harder to trust. Delete the comment; rationale worth keeping goes in the owning docstring."
|
|
5
|
+
severity: ERROR
|
|
6
|
+
languages: [typescript, javascript]
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
rules:
|
|
2
|
+
- id: pra-pure-prefix-mismatch
|
|
3
|
+
patterns:
|
|
4
|
+
- pattern-either:
|
|
5
|
+
- pattern: |
|
|
6
|
+
def $NAME(...):
|
|
7
|
+
...
|
|
8
|
+
- pattern: |
|
|
9
|
+
async def $NAME(...):
|
|
10
|
+
...
|
|
11
|
+
- metavariable-regex:
|
|
12
|
+
metavariable: $NAME
|
|
13
|
+
regex: '^(compute|build|derive|format|parse|extract)_.*'
|
|
14
|
+
- pattern-either:
|
|
15
|
+
- pattern-inside: |
|
|
16
|
+
def $NAME(...):
|
|
17
|
+
...
|
|
18
|
+
$IO
|
|
19
|
+
...
|
|
20
|
+
- pattern-inside: |
|
|
21
|
+
async def $NAME(...):
|
|
22
|
+
...
|
|
23
|
+
$IO
|
|
24
|
+
...
|
|
25
|
+
- metavariable-pattern:
|
|
26
|
+
metavariable: $IO
|
|
27
|
+
pattern-either:
|
|
28
|
+
- pattern: open(...)
|
|
29
|
+
- pattern: $PATH.open(...)
|
|
30
|
+
- patterns:
|
|
31
|
+
- pattern-either:
|
|
32
|
+
- pattern: httpx.$METHOD(...)
|
|
33
|
+
- pattern: requests.$METHOD(...)
|
|
34
|
+
- metavariable-regex:
|
|
35
|
+
metavariable: $METHOD
|
|
36
|
+
regex: '^(get|post|put|patch|delete|head|options|request|stream)$'
|
|
37
|
+
- pattern: $PATH.read_text(...)
|
|
38
|
+
- pattern: $PATH.read_bytes(...)
|
|
39
|
+
- pattern: $PATH.write_text(...)
|
|
40
|
+
- pattern: $PATH.write_bytes(...)
|
|
41
|
+
- pattern: $PATH.unlink(...)
|
|
42
|
+
- pattern: $PATH.mkdir(...)
|
|
43
|
+
- pattern: $PATH.exists(...)
|
|
44
|
+
- pattern: $PATH.iterdir(...)
|
|
45
|
+
- pattern: $PATH.glob(...)
|
|
46
|
+
- pattern: $PATH.rmdir(...)
|
|
47
|
+
- pattern: $PATH.resolve(...)
|
|
48
|
+
- pattern: shutil.$METHOD(...)
|
|
49
|
+
- pattern: subprocess.$METHOD(...)
|
|
50
|
+
- pattern: importlib.import_module(...)
|
|
51
|
+
- patterns:
|
|
52
|
+
- pattern: os.$METHOD(...)
|
|
53
|
+
- metavariable-regex:
|
|
54
|
+
metavariable: $METHOD
|
|
55
|
+
regex: '^(mkdir|makedirs|rmdir|removedirs|remove|unlink|rename|replace|kill|chdir|chmod|chown|symlink|link|stat|lstat|listdir|scandir|access|system|popen)$'
|
|
56
|
+
- patterns:
|
|
57
|
+
- pattern: os.path.$METHOD(...)
|
|
58
|
+
- metavariable-regex:
|
|
59
|
+
metavariable: $METHOD
|
|
60
|
+
regex: '^(exists|isfile|isdir|islink|getsize|realpath)$'
|
|
61
|
+
- patterns:
|
|
62
|
+
- pattern: $CLIENT.$METHOD(...)
|
|
63
|
+
- metavariable-regex:
|
|
64
|
+
metavariable: $CLIENT
|
|
65
|
+
regex: '(database|session|connection|cursor|client)$'
|
|
66
|
+
- metavariable-regex:
|
|
67
|
+
metavariable: $METHOD
|
|
68
|
+
regex: '^(execute|fetch|get|post|put|delete|query|read|write|save)$'
|
|
69
|
+
- patterns:
|
|
70
|
+
- pattern: $CALLEE(...)
|
|
71
|
+
- metavariable-regex:
|
|
72
|
+
metavariable: $CALLEE
|
|
73
|
+
regex: '^(fetch|retrieve|load|save|read|write|query)_\w+$'
|
|
74
|
+
message: "principle #7 pure-prefixed function appears to perform I/O. Rename it with get, fetch, retrieve, load, save, read, write, or query, or move the I/O to the caller."
|
|
75
|
+
severity: WARNING
|
|
76
|
+
languages: [python]
|
|
77
|
+
metadata:
|
|
78
|
+
note: "Heuristic rule; detects I/O written in the body, or a call to a bare function named with an I/O prefix other than get. I/O hidden behind other helpers is not seen. The I/O vocabulary mirrors pra-io-prefix-mismatch in opposite polarity; keep both rules in step."
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
rules:
|
|
2
|
-
- id: pra-no-block-comments-python
|
|
3
|
-
pattern-regex: '(?m)^[ \t]*#(?![ \t]*WHY:).*\n[ \t]*#(?![ \t]*WHY:).*$'
|
|
4
|
-
message: "principle #10 Block comments make code harder to trust. Delete the comment or replace it with one WHY line."
|
|
5
|
-
severity: ERROR
|
|
6
|
-
languages: [python]
|
|
7
|
-
- id: pra-no-block-comments-js
|
|
8
|
-
pattern-regex: '/\*(?!\*)[\s\S]*?\*/'
|
|
9
|
-
message: "principle #10 Block comments make code harder to trust. Delete the comment or replace it with one WHY line."
|
|
10
|
-
severity: ERROR
|
|
11
|
-
languages: [typescript, javascript]
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
rules:
|
|
2
|
-
- id: pra-no-todo-comments-python
|
|
3
|
-
pattern-regex: '(?i)#\s*(TODO(?!\(PRA-[0-9]+\))|FIXME|XXX)\b'
|
|
4
|
-
message: "principle #10 Planning comments decay. Link a Linear issue or remove the comment."
|
|
5
|
-
severity: ERROR
|
|
6
|
-
languages: [python]
|
|
7
|
-
- id: pra-no-todo-comments-js
|
|
8
|
-
pattern-regex: '(?i)(//|/\*)\s*(TODO(?!\(PRA-[0-9]+\))|FIXME|XXX)\b'
|
|
9
|
-
message: "principle #10 Planning comments decay. Link a Linear issue or remove the comment."
|
|
10
|
-
severity: ERROR
|
|
11
|
-
languages: [typescript, javascript]
|