rohitsar567 commited on
Commit
5ff5598
Β·
1 Parent(s): 4e551b8

feat(audit): Tier 2 code-soundness (corrected spec) + core.selftest hardening

Browse files

Supersedes the flawed-spec 12f33ae: DEAD now module/import-qualified (no
faithfulness_passed over-match), audit/ self-excluded, T2.4 redesigned as a
string/comment state machine that actually detects the orphan-*/ footgun,
_py() re-queried per call (fixtures validate), T2.6 robust to missing
ruff/tsc, core.selftest wraps each check (a raising check can't abort it).
11/11 self-verifying; --static 10 pass/1 warn/0 fail. Local only.

Files changed (3) hide show
  1. audit/core.py +7 -3
  2. audit/selftest_fixtures.py +58 -39
  3. audit/tier2_code.py +97 -32
audit/core.py CHANGED
@@ -78,9 +78,13 @@ def selftest() -> int:
78
  for c in CHECKS:
79
  fx = FIXTURES.get(c.id)
80
  if fx is None:
81
- bad.append(f"{c.id}: NO selftest fixture"); continue
82
- with fx():
83
- r = c.fn()
 
 
 
 
84
  if r.status is not Status.FAIL:
85
  bad.append(f"{c.id}: expected FAIL on broken fixture, got {r.status.value}")
86
  for b in bad: print(f" FAIL {b}")
 
78
  for c in CHECKS:
79
  fx = FIXTURES.get(c.id)
80
  if fx is None:
81
+ bad.append(f"{c.id}: NO selftest fixture")
82
+ continue
83
+ try:
84
+ with fx():
85
+ r = c.fn()
86
+ except Exception as e:
87
+ r = Result(c.id, Status.FAIL, f"raised {type(e).__name__}: {e}")
88
  if r.status is not Status.FAIL:
89
  bad.append(f"{c.id}: expected FAIL on broken fixture, got {r.status.value}")
90
  for b in bad: print(f" FAIL {b}")
audit/selftest_fixtures.py CHANGED
@@ -90,70 +90,87 @@ def _f_t1_5():
90
 
91
  @contextlib.contextmanager
92
  def _f_t2_1():
93
- """Track a .py with a syntax error so T2.1 FAILs."""
94
- f = REPO / "_audit_selftest_syntax.py"
95
- f.write_text("def broken(:\n pass\n", encoding="utf-8")
96
- sh(["git", "add", "-f", "_audit_selftest_syntax.py"])
 
97
  try:
98
  yield
99
  finally:
100
- sh(["git", "rm", "--cached", "-q", "_audit_selftest_syntax.py"])
101
  if f.exists():
102
  f.unlink()
103
 
104
 
105
  @contextlib.contextmanager
106
  def _f_t2_2():
107
- """Track backend/_audit_selftest_mod.py that raises NameError at import."""
108
- f = REPO / "backend" / "_audit_selftest_mod.py"
109
- f.write_text("x = undefined_thing\n", encoding="utf-8")
110
- sh(["git", "add", "-f", "backend/_audit_selftest_mod.py"])
 
111
  try:
112
  yield
113
  finally:
114
- sh(["git", "rm", "--cached", "-q", "backend/_audit_selftest_mod.py"])
115
  if f.exists():
116
  f.unlink()
117
 
118
 
119
  @contextlib.contextmanager
120
  def _f_t2_3():
121
- """Track backend/_audit_selftest_dead.py with a code ref to a deleted module."""
122
- f = REPO / "backend" / "_audit_selftest_dead.py"
 
 
 
 
 
123
  f.write_text("from backend.orchestrator import handle_turn\n", encoding="utf-8")
124
- sh(["git", "add", "-f", "backend/_audit_selftest_dead.py"])
125
  try:
126
  yield
127
  finally:
128
- sh(["git", "rm", "--cached", "-q", "backend/_audit_selftest_dead.py"])
129
  if f.exists():
130
  f.unlink()
131
 
132
 
133
  @contextlib.contextmanager
134
  def _f_t2_4():
135
- """Track a .css file with a nested */ inside a block comment so T2.4 FAILs."""
136
- f = REPO / "_audit_selftest.css"
137
- f.write_text("/* a */ b */\n.x { color: red; }\n", encoding="utf-8")
138
- sh(["git", "add", "-f", "_audit_selftest.css"])
 
 
 
 
 
 
139
  try:
140
  yield
141
  finally:
142
- sh(["git", "rm", "--cached", "-q", "_audit_selftest.css"])
143
  if f.exists():
144
  f.unlink()
145
 
146
 
147
  @contextlib.contextmanager
148
  def _f_t2_5():
149
- """Track backend/_audit_selftest_path.py with a hardcoded 40-data path."""
150
- f = REPO / "backend" / "_audit_selftest_path.py"
151
- f.write_text('x = something / "40-data" / "y"\n', encoding="utf-8")
152
- sh(["git", "add", "-f", "backend/_audit_selftest_path.py"])
 
 
 
 
153
  try:
154
  yield
155
  finally:
156
- sh(["git", "rm", "--cached", "-q", "backend/_audit_selftest_path.py"])
157
  if f.exists():
158
  f.unlink()
159
 
@@ -170,12 +187,12 @@ def _tsc_available() -> bool:
170
  def _f_t2_6():
171
  """Force a lint/type failure so T2.6 FAILs.
172
 
173
- Prefer ruff (a flagrant unused-import + bare-except .py under audit/). If
174
- ruff is unavailable in this env T2.6 would SKIP (not FAIL) on a ruff-only
175
- fixture, so fall back to forcing a tsc error via a broken .ts under
176
- frontend/src/. If NEITHER ruff nor tsc is available this single fixture
177
- cannot legitimately force a FAIL β€” raise a clear RuntimeError so selftest
178
- surfaces it rather than reporting a false pass.
179
  """
180
  have_ruff = _ruff_available()
181
  have_tsc = _tsc_available()
@@ -184,17 +201,19 @@ def _f_t2_6():
184
 
185
  created = []
186
  try:
187
- if have_ruff:
188
- f = REPO / "audit" / "_audit_selftest_lint.py"
 
 
 
 
 
 
 
189
  f.write_text("import os\ntry:\n pass\nexcept:\n pass\n",
190
  encoding="utf-8")
191
- sh(["git", "add", "-f", "audit/_audit_selftest_lint.py"])
192
- created.append("audit/_audit_selftest_lint.py")
193
- else:
194
- f = REPO / "frontend" / "src" / "_audit_selftest_bad.ts"
195
- f.write_text("export const x: number = ;\n", encoding="utf-8")
196
- sh(["git", "add", "-f", "frontend/src/_audit_selftest_bad.ts"])
197
- created.append("frontend/src/_audit_selftest_bad.ts")
198
  yield
199
  finally:
200
  for rel in created:
 
90
 
91
  @contextlib.contextmanager
92
  def _f_t2_1():
93
+ """Track backend/_audit_st_syntax.py with a SyntaxError so T2.1 FAILs."""
94
+ rel = "backend/_audit_st_syntax.py"
95
+ f = REPO / rel
96
+ f.write_text("def (:\n pass\n", encoding="utf-8")
97
+ sh(["git", "add", "-f", rel])
98
  try:
99
  yield
100
  finally:
101
+ sh(["git", "rm", "--cached", "-q", rel])
102
  if f.exists():
103
  f.unlink()
104
 
105
 
106
  @contextlib.contextmanager
107
  def _f_t2_2():
108
+ """Track backend/_audit_st_import.py that raises ImportError at import time."""
109
+ rel = "backend/_audit_st_import.py"
110
+ f = REPO / rel
111
+ f.write_text('raise ImportError("audit selftest")\n', encoding="utf-8")
112
+ sh(["git", "add", "-f", rel])
113
  try:
114
  yield
115
  finally:
116
+ sh(["git", "rm", "--cached", "-q", rel])
117
  if f.exists():
118
  f.unlink()
119
 
120
 
121
  @contextlib.contextmanager
122
  def _f_t2_3():
123
+ """Track backend/_audit_st_dead.py with a CODE ref to a deleted module.
124
+
125
+ The line is a real import statement (not a comment/docstring) so T2.3 must
126
+ classify it as a code_hit and return FAIL, not WARN.
127
+ """
128
+ rel = "backend/_audit_st_dead.py"
129
+ f = REPO / rel
130
  f.write_text("from backend.orchestrator import handle_turn\n", encoding="utf-8")
131
+ sh(["git", "add", "-f", rel])
132
  try:
133
  yield
134
  finally:
135
+ sh(["git", "rm", "--cached", "-q", rel])
136
  if f.exists():
137
  f.unlink()
138
 
139
 
140
  @contextlib.contextmanager
141
  def _f_t2_4():
142
+ """Track frontend/_audit_st.css with an orphan */ so T2.4 FAILs.
143
+
144
+ `/* a */ b */` β€” the first `*/` legitimately closes the comment; the
145
+ trailing ` */` is then an orphan terminator outside any comment, which is
146
+ exactly the comment-terminator footgun T2.4's state machine flags.
147
+ """
148
+ rel = "frontend/_audit_st.css"
149
+ f = REPO / rel
150
+ f.write_text("/* a */ b */\n", encoding="utf-8")
151
+ sh(["git", "add", "-f", rel])
152
  try:
153
  yield
154
  finally:
155
+ sh(["git", "rm", "--cached", "-q", rel])
156
  if f.exists():
157
  f.unlink()
158
 
159
 
160
  @contextlib.contextmanager
161
  def _f_t2_5():
162
+ """Track backend/_audit_st_path.py with a hardcoded 40-data path so T2.5 FAILs."""
163
+ rel = "backend/_audit_st_path.py"
164
+ f = REPO / rel
165
+ f.write_text(
166
+ 'x = settings.CORPUS_DIR.parent.parent / "40-data" / "y.json"\n',
167
+ encoding="utf-8",
168
+ )
169
+ sh(["git", "add", "-f", rel])
170
  try:
171
  yield
172
  finally:
173
+ sh(["git", "rm", "--cached", "-q", rel])
174
  if f.exists():
175
  f.unlink()
176
 
 
187
  def _f_t2_6():
188
  """Force a lint/type failure so T2.6 FAILs.
189
 
190
+ Prefer a tsc type error (a .ts under frontend/src/ that fails strict type
191
+ checking). If tsc is unavailable, fall back to a ruff-only fixture (a
192
+ flagrant unused-import + bare-except .py under audit/). If NEITHER ruff nor
193
+ tsc is available this single fixture cannot legitimately force a FAIL β€”
194
+ raise a clear RuntimeError; the hardened core.selftest treats that raise as
195
+ the check failing on the broken fixture, which is the acceptable outcome.
196
  """
197
  have_ruff = _ruff_available()
198
  have_tsc = _tsc_available()
 
201
 
202
  created = []
203
  try:
204
+ if have_tsc:
205
+ rel = "frontend/src/_audit_st_bad.ts"
206
+ f = REPO / rel
207
+ f.write_text('const x: number = "str";\n', encoding="utf-8")
208
+ sh(["git", "add", "-f", rel])
209
+ created.append(rel)
210
+ else:
211
+ rel = "audit/_audit_st_lint.py"
212
+ f = REPO / rel
213
  f.write_text("import os\ntry:\n pass\nexcept:\n pass\n",
214
  encoding="utf-8")
215
+ sh(["git", "add", "-f", rel])
216
+ created.append(rel)
 
 
 
 
 
217
  yield
218
  finally:
219
  for rel in created:
audit/tier2_code.py CHANGED
@@ -3,27 +3,47 @@ from __future__ import annotations
3
  import ast, re
4
  from audit.core import register, Result, Status, REPO, git, sh
5
 
6
- PY = [p for p in git("ls-files").splitlines() if p.endswith(".py")]
7
- DEAD = ("backend.orchestrator", "import sales_brain", "qa_brain", "faithfulness",
8
- "backend.translator", "profile_extractor", "get_judge_llm", "get_fast_brain_llm")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
 
11
  @register("T2.1", "static", "all .py parse (AST)")
12
  def t2_1() -> Result:
13
  bad = []
14
- for p in PY:
15
  try:
16
  ast.parse((REPO / p).read_text(encoding="utf-8", errors="replace"), p)
17
  except SyntaxError as e:
18
  bad.append(f"{p}: {e}")
19
  return (Result("T2.1", Status.FAIL, "; ".join(bad[:5]), "fix the syntax error")
20
- if bad else Result("T2.1", Status.PASS, f"{len(PY)} files parse"))
21
 
22
 
23
  @register("T2.2", "static", "runtime-import every backend/rag module")
24
  def t2_2() -> Result:
25
  mods = []
26
- for p in PY:
27
  if (p.startswith("backend/") or p.startswith("rag/")) and not p.endswith("__init__.py") \
28
  and "_smoke_test" not in p and "/tests/" not in p:
29
  mods.append(p[:-3].replace("/", "."))
@@ -33,41 +53,79 @@ def t2_2() -> Result:
33
  r = sh([".venv/bin/python", "-c", code], timeout=300)
34
  if r.returncode != 0:
35
  return Result("T2.2", Status.FAIL, r.stdout.strip()[:600],
36
- "fix the import (often: import wrongly placed inside a docstring)")
37
  return Result("T2.2", Status.PASS, f"{len(mods)} modules import clean")
38
 
39
 
40
  @register("T2.3", "static", "no refs to deleted modules/symbols")
41
  def t2_3() -> Result:
42
  code_hits, doc_hits = [], []
43
- for p in PY:
44
- for i, ln in enumerate(open(REPO / p, encoding="utf-8", errors="replace"), 1):
 
 
45
  for d in DEAD:
46
  if d in ln:
47
  s = ln.strip()
48
- (doc_hits if s.startswith("#") or s.startswith(('"', "'", "*")) else code_hits
49
  ).append(f"{p}:{i} {d}")
 
50
  if code_hits:
51
  return Result("T2.3", Status.FAIL, "; ".join(code_hits[:6]),
52
- "remove/replace the dead reference (e.g. get_judge_llm -> get_brain_llm)")
53
  if doc_hits:
54
  return Result("T2.3", Status.WARN, f"{len(doc_hits)} stale comment refs e.g. {doc_hits[:3]}",
55
  "tidy the stale comment")
56
  return Result("T2.3", Status.PASS, "no dead-symbol references")
57
 
58
 
59
- @register("T2.4", "static", "no */ inside CSS/JS block-comment body")
60
  def t2_4() -> Result:
61
  bad = []
62
  for p in git("ls-files").splitlines():
63
  if not p.endswith((".css", ".scss")):
64
  continue
65
- txt = (REPO / p).read_text(encoding="utf-8", errors="replace")
66
- for m in re.finditer(r"/\*.*?\*/", txt, re.S):
67
- body = m.group(0)[2:-2]
68
- if "*/" in body:
69
- bad.append(f"{p}: nested */ in comment")
70
- return (Result("T2.4", Status.FAIL, "; ".join(bad), "space the token: '* /' or reword")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  if bad else Result("T2.4", Status.PASS, "no comment-terminator footgun"))
72
 
73
 
@@ -75,12 +133,12 @@ def t2_4() -> Result:
75
  def t2_5() -> Result:
76
  pat = re.compile(r'/\s*["\']40-data["\']')
77
  bad = []
78
- for p in PY:
79
- if not (p.startswith("backend/") or p.startswith("rag/")):
80
  continue
81
  if p.endswith("config.py"):
82
  continue
83
- for i, ln in enumerate(open(REPO / p, encoding="utf-8", errors="replace"), 1):
84
  if pat.search(ln) and not ln.strip().startswith("#"):
85
  bad.append(f"{p}:{i}")
86
  return (Result("T2.5", Status.FAIL, "; ".join(bad[:8]), "use settings.DATA_DIR")
@@ -89,16 +147,23 @@ def t2_5() -> Result:
89
 
90
  @register("T2.6", "static", "ruff + tsc clean")
91
  def t2_6() -> Result:
92
- ruff = sh([".venv/bin/ruff", "check", "backend", "rag", "audit"], timeout=120)
93
- tsc = sh(["npx", "--prefix", "frontend", "--no-install", "tsc", "-p", "frontend", "--noEmit"], timeout=240)
 
 
 
 
 
94
  probs = []
95
- if ruff.returncode not in (0, 127):
96
- tail = (ruff.stdout or ruff.stderr).strip().splitlines()
97
- probs.append("ruff: " + (tail[-1][:200] if tail else "error"))
98
- if tsc.returncode not in (0, 127):
99
- tail = (tsc.stdout or tsc.stderr).strip().splitlines()
100
- probs.append("tsc: " + (tail[-1][:200] if tail else "error"))
101
- if 127 in (ruff.returncode, tsc.returncode) and not probs:
102
- return Result("T2.6", Status.SKIP, "ruff/tsc not installed", "pip install ruff / npm i")
 
 
103
  return (Result("T2.6", Status.FAIL, " | ".join(probs), "fix lint/type errors")
104
- if probs else Result("T2.6", Status.PASS, "ruff + tsc clean"))
 
3
  import ast, re
4
  from audit.core import register, Result, Status, REPO, git, sh
5
 
6
+ # DEAD = deleted modules/accessors, matched in MODULE/IMPORT/CALL form so we
7
+ # do NOT false-match live field-name substrings (e.g. faithfulness_passed is
8
+ # an active log field; the backend.faithfulness *module* is gone).
9
+ DEAD = (
10
+ "backend.orchestrator", "import orchestrator",
11
+ "import sales_brain", "from backend import sales_brain", "backend.sales_brain",
12
+ "import qa_brain", "backend.qa_brain",
13
+ "import faithfulness", "from backend import faithfulness", "backend.faithfulness",
14
+ "import translator", "backend.translator",
15
+ "import profile_extractor", "backend.profile_extractor",
16
+ "get_judge_llm", "get_fast_brain_llm",
17
+ )
18
+
19
+
20
+ def _py() -> list[str]:
21
+ """Re-queried per call (NOT a frozen import-time snapshot) so selftest
22
+ fixtures that add a file are actually seen by the checks."""
23
+ return [p for p in git("ls-files").splitlines() if p.endswith(".py")]
24
+
25
+
26
+ def _audit_self(p: str) -> bool:
27
+ # the framework's own files contain the DEAD strings as detection DATA
28
+ return p.startswith("audit/") or p == "tests/test_audit_selftest.py"
29
 
30
 
31
  @register("T2.1", "static", "all .py parse (AST)")
32
  def t2_1() -> Result:
33
  bad = []
34
+ for p in _py():
35
  try:
36
  ast.parse((REPO / p).read_text(encoding="utf-8", errors="replace"), p)
37
  except SyntaxError as e:
38
  bad.append(f"{p}: {e}")
39
  return (Result("T2.1", Status.FAIL, "; ".join(bad[:5]), "fix the syntax error")
40
+ if bad else Result("T2.1", Status.PASS, f"{len(_py())} files parse"))
41
 
42
 
43
  @register("T2.2", "static", "runtime-import every backend/rag module")
44
  def t2_2() -> Result:
45
  mods = []
46
+ for p in _py():
47
  if (p.startswith("backend/") or p.startswith("rag/")) and not p.endswith("__init__.py") \
48
  and "_smoke_test" not in p and "/tests/" not in p:
49
  mods.append(p[:-3].replace("/", "."))
 
53
  r = sh([".venv/bin/python", "-c", code], timeout=300)
54
  if r.returncode != 0:
55
  return Result("T2.2", Status.FAIL, r.stdout.strip()[:600],
56
+ "fix the import (often: import wrongly placed inside a docstring, or a deleted symbol)")
57
  return Result("T2.2", Status.PASS, f"{len(mods)} modules import clean")
58
 
59
 
60
  @register("T2.3", "static", "no refs to deleted modules/symbols")
61
  def t2_3() -> Result:
62
  code_hits, doc_hits = [], []
63
+ for p in _py():
64
+ if _audit_self(p):
65
+ continue
66
+ for i, ln in enumerate((REPO / p).read_text(encoding="utf-8", errors="replace").splitlines(), 1):
67
  for d in DEAD:
68
  if d in ln:
69
  s = ln.strip()
70
+ (doc_hits if s.startswith(("#", '"', "'", "*")) else code_hits
71
  ).append(f"{p}:{i} {d}")
72
+ break
73
  if code_hits:
74
  return Result("T2.3", Status.FAIL, "; ".join(code_hits[:6]),
75
+ "remove/replace the dead reference (e.g. get_fast_brain_llm -> get_brain_llm)")
76
  if doc_hits:
77
  return Result("T2.3", Status.WARN, f"{len(doc_hits)} stale comment refs e.g. {doc_hits[:3]}",
78
  "tidy the stale comment")
79
  return Result("T2.3", Status.PASS, "no dead-symbol references")
80
 
81
 
82
+ @register("T2.4", "static", "no orphan */ (CSS comment-terminator footgun)")
83
  def t2_4() -> Result:
84
  bad = []
85
  for p in git("ls-files").splitlines():
86
  if not p.endswith((".css", ".scss")):
87
  continue
88
+ s = (REPO / p).read_text(encoding="utf-8", errors="replace")
89
+ i, n, line = 0, len(s), 1
90
+ in_comment = False
91
+ in_str = "" # "" | "'" | '"'
92
+ while i < n:
93
+ ch = s[i]
94
+ nx = s[i + 1] if i + 1 < n else ""
95
+ if ch == "\n":
96
+ line += 1
97
+ if in_str:
98
+ if ch == "\\":
99
+ i += 2
100
+ continue
101
+ if ch == in_str:
102
+ in_str = ""
103
+ i += 1
104
+ continue
105
+ if in_comment:
106
+ if ch == "*" and nx == "/":
107
+ in_comment = False
108
+ i += 2
109
+ continue
110
+ i += 1
111
+ continue
112
+ if ch in ("'", '"'):
113
+ in_str = ch
114
+ i += 1
115
+ continue
116
+ if ch == "/" and nx == "*":
117
+ in_comment = True
118
+ i += 2
119
+ continue
120
+ if ch == "*" and nx == "/":
121
+ # a */ outside any comment/string: an earlier stray */ closed
122
+ # a comment prematurely (the exact app-wide-500 footgun).
123
+ bad.append(f"{p}:{line} orphan '*/' (a stray '*/' earlier closed a comment early)")
124
+ i += 2
125
+ continue
126
+ i += 1
127
+ return (Result("T2.4", Status.FAIL, "; ".join(bad[:5]),
128
+ "a comment body contains '*/' (e.g. .snap-*/.rev-*) β€” space it '* /' or reword")
129
  if bad else Result("T2.4", Status.PASS, "no comment-terminator footgun"))
130
 
131
 
 
133
  def t2_5() -> Result:
134
  pat = re.compile(r'/\s*["\']40-data["\']')
135
  bad = []
136
+ for p in _py():
137
+ if _audit_self(p) or not (p.startswith("backend/") or p.startswith("rag/")):
138
  continue
139
  if p.endswith("config.py"):
140
  continue
141
+ for i, ln in enumerate((REPO / p).read_text(encoding="utf-8", errors="replace").splitlines(), 1):
142
  if pat.search(ln) and not ln.strip().startswith("#"):
143
  bad.append(f"{p}:{i}")
144
  return (Result("T2.5", Status.FAIL, "; ".join(bad[:8]), "use settings.DATA_DIR")
 
147
 
148
  @register("T2.6", "static", "ruff + tsc clean")
149
  def t2_6() -> Result:
150
+ def _try(cmd, timeout):
151
+ try:
152
+ return sh(cmd, timeout=timeout)
153
+ except FileNotFoundError:
154
+ return None
155
+ ruff = _try([".venv/bin/ruff", "check", "backend", "rag", "audit"], 120)
156
+ tsc = _try(["npx", "--prefix", "frontend", "--no-install", "tsc", "-p", "frontend", "--noEmit"], 240)
157
  probs = []
158
+ if ruff is not None and ruff.returncode not in (0, 127):
159
+ t = (ruff.stdout or ruff.stderr).strip().splitlines()
160
+ probs.append("ruff: " + (t[-1][:200] if t else "error"))
161
+ if tsc is not None and tsc.returncode not in (0, 127):
162
+ t = (tsc.stdout or tsc.stderr).strip().splitlines()
163
+ probs.append("tsc: " + (t[-1][:200] if t else "error"))
164
+ avail = [x for x in (ruff, tsc) if x is not None and x.returncode != 127]
165
+ if not avail and not probs:
166
+ return Result("T2.6", Status.SKIP, "ruff and tsc both unavailable",
167
+ "pip install ruff / npm i in frontend to enable this gate")
168
  return (Result("T2.6", Status.FAIL, " | ".join(probs), "fix lint/type errors")
169
+ if probs else Result("T2.6", Status.PASS, "ruff/tsc clean (available tools)"))