HumboldtJoker commited on
Commit
879085f
·
verified ·
1 Parent(s): 0c45639

Clean up nested duplicate: v2/v2/skills/code_analysis.py

Browse files
Files changed (1) hide show
  1. v2/v2/skills/code_analysis.py +0 -138
v2/v2/skills/code_analysis.py DELETED
@@ -1,138 +0,0 @@
1
- """Code analysis chip — reads actual campus source before anyone opines.
2
-
3
- Extracts file paths and symbols from the request, reads those files from
4
- the repo (when present), follows one level of imports, and grabs recent
5
- git history for each file. Everything read is recorded in the session's
6
- evidence log — this is what lets the discipline gate honestly say HIGH
7
- confidence ("I read the file") vs LOW ("I'm reasoning from the map").
8
- """
9
-
10
- import re
11
-
12
- from kintsugi_core import (
13
- BaseSkillChip,
14
- EFEWeights,
15
- SkillCapability,
16
- SkillContext,
17
- SkillDomain,
18
- SkillRequest,
19
- SkillResponse,
20
- )
21
-
22
- PATH_RE = re.compile(
23
- r"\b((?:server|client|shared|design-system)/[\w./-]+\.(?:ts|tsx|js|jsx|sql|json))\b"
24
- )
25
- SYMBOL_RE = re.compile(r"\b([a-z][a-zA-Z0-9]+(?:Handler|Store|Service|Middleware|Router))\b")
26
- IMPORT_RE = re.compile(r"""from\s+['"]([^'"]+)['"]""")
27
-
28
- MAX_FILES = 6
29
- MAX_EXCERPT = 4000
30
-
31
-
32
- class CodeAnalysisChip(BaseSkillChip):
33
- name = "code_analysis"
34
- description = "Read and trace campus source files named in the request"
35
- version = "2.0.0"
36
- domain = SkillDomain.RESEARCH
37
- efe_weights = EFEWeights(
38
- mission_alignment=0.20, stakeholder_benefit=0.20,
39
- resource_efficiency=0.25, transparency=0.25, equity=0.10,
40
- )
41
- capabilities = [SkillCapability.READ_DATA]
42
-
43
- def __init__(self, repo_files=None, git_tools=None):
44
- super().__init__()
45
- self.repo_files = repo_files
46
- self.git_tools = git_tools
47
-
48
- async def handle(self, request: SkillRequest,
49
- context: SkillContext) -> SkillResponse:
50
- question = context.metadata.get("question", request.raw_input)
51
- session = context.metadata.get("session")
52
-
53
- paths = list(dict.fromkeys(PATH_RE.findall(question)))[:MAX_FILES]
54
- symbols = list(dict.fromkeys(SYMBOL_RE.findall(question)))[:5]
55
-
56
- analysis = {
57
- "repo_available": self.repo_files is not None,
58
- "requested_paths": paths,
59
- "symbols": symbols,
60
- "files": [], # [{path, excerpt, git_status, recent_history, imports}]
61
- "symbol_sites": [],
62
- "notes": [],
63
- }
64
-
65
- if self.repo_files is None:
66
- analysis["notes"].append(
67
- "Campus repo is not on this machine — analysis is limited "
68
- "to the architecture map. Confidence will be capped."
69
- )
70
- return self._done(analysis, session)
71
-
72
- # Locate files for bare symbols the user named.
73
- for sym in symbols:
74
- hits = self.repo_files.search(rf"\b{re.escape(sym)}\b")[:3]
75
- analysis["symbol_sites"].extend(hits)
76
- for h in hits:
77
- if h["path"] not in paths and len(paths) < MAX_FILES:
78
- paths.append(h["path"])
79
-
80
- for path in paths[:MAX_FILES]:
81
- read = self.repo_files.read(path)
82
- if not read.ok:
83
- analysis["notes"].append(f"could not read {path}: {read.error}")
84
- continue
85
- entry = {
86
- "path": path,
87
- "excerpt": read.content[:MAX_EXCERPT],
88
- "truncated": read.truncated or len(read.content) > MAX_EXCERPT,
89
- "git_status": read.git_status,
90
- "imports": IMPORT_RE.findall(read.content)[:20],
91
- "recent_history": (
92
- self.git_tools.recent_authors(path) if self.git_tools else ""
93
- ),
94
- }
95
- analysis["files"].append(entry)
96
- if session:
97
- session.record_file_read(path, self.name)
98
-
99
- # One level of local-import tracing for the first file.
100
- if analysis["files"]:
101
- first = analysis["files"][0]
102
- local = [imp for imp in first["imports"] if imp.startswith(".")][:3]
103
- for imp in local:
104
- resolved = self._resolve_import(first["path"], imp)
105
- if resolved and len(analysis["files"]) < MAX_FILES:
106
- read = self.repo_files.read(resolved)
107
- if read.ok:
108
- analysis["files"].append({
109
- "path": resolved,
110
- "excerpt": read.content[:MAX_EXCERPT // 2],
111
- "truncated": True,
112
- "git_status": read.git_status,
113
- "imports": [],
114
- "recent_history": "",
115
- "traced_from": first["path"],
116
- })
117
- if session:
118
- session.record_file_read(resolved, self.name)
119
-
120
- return self._done(analysis, session)
121
-
122
- def _resolve_import(self, from_path: str, import_spec: str) -> str:
123
- base = "/".join(from_path.split("/")[:-1])
124
- candidate = f"{base}/{import_spec.lstrip('./')}"
125
- for suffix in (".ts", ".tsx", "/index.ts", ".js"):
126
- probe = candidate + suffix
127
- if self.repo_files.read(probe).ok:
128
- return probe
129
- return ""
130
-
131
- def _done(self, analysis: dict, session) -> SkillResponse:
132
- n_files = len(analysis["files"])
133
- summary = (
134
- f"read {n_files} file(s), "
135
- f"{len(analysis['symbol_sites'])} symbol site(s); "
136
- f"repo_available={analysis['repo_available']}"
137
- )
138
- return SkillResponse(content=summary, success=True, data=analysis)