@pragmatiks/lint 0.7.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 CHANGED
@@ -1,5 +1,11 @@
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
+
3
9
  ## js-v0.7.0 (2026-10-07)
4
10
 
5
11
  ### Bug Fixes
package/README.md CHANGED
@@ -142,7 +142,7 @@ Fix these by rewriting the code:
142
142
 
143
143
  ## Development
144
144
 
145
- | Command | Purpose |
146
- | -------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
147
- | `task js:check` / `task js:test` / `task js:build` | Lint and type check / tests (Node `>=22.15` for `module.registerHooks`; `mise.toml` pins Node 26) / build |
148
- | `task js:pack` | Install, build and `npm pack` the committed HEAD with CI's toolchain (Node 26, pnpm 12.6.0, latest npm) in a throwaway worktree, printing all three versions; the tarball lands in `js/` |
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pragmatiks/lint",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Pragmatiks engineering principles eslint config and bundled semgrep rules.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -103,6 +103,16 @@ rules:
103
103
  ...
104
104
  $PATH.rmdir(...)
105
105
  ...
106
+ - pattern-not: |
107
+ def $NAME(...):
108
+ ...
109
+ $PATH.resolve(...)
110
+ ...
111
+ - pattern-not: |
112
+ def $NAME(...):
113
+ ...
114
+ importlib.import_module(...)
115
+ ...
106
116
  - pattern-not: |
107
117
  def $NAME(...):
108
118
  ...
@@ -113,10 +123,10 @@ rules:
113
123
  ...
114
124
  subprocess.$METHOD(...)
115
125
  ...
116
- - 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))\('
117
127
  - pattern-not-regex: '(?s)(database|session|connection|cursor|client)\.(execute|fetch|get|post|put|delete|query|read|write|save)\('
118
128
  message: "principle #7 I/O-prefixed function appears pure. Rename it with compute, build, derive, format, or parse."
119
129
  severity: WARNING
120
130
  languages: [python]
121
131
  metadata:
122
- 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,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."