phi47-superpowers 0.1.0__py3-none-any.whl

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.
phi47/__init__.py ADDED
@@ -0,0 +1,13 @@
1
+ # Copyright (c) 2025 wcalmels -- TUCH Systems Research Laboratory
2
+ # SPDX-License-Identifier: MIT
3
+ __version__ = "0.1.0"
4
+ __author__ = "wcalmels"
5
+ __email__ = "wcalmels@phi47.cl"
6
+ __license__ = "MIT"
7
+ __copyright__ = "Copyright (c) 2025 TUCH Systems Research Laboratory"
8
+
9
+ from phi47.linter.phi_linter import Phi47Linter
10
+ from phi47.wrapper.llm_wrapper import Phi47LLMWrapper
11
+ from phi47.core.phi_calculator import PhiCalculator
12
+
13
+ __all__ = ["Phi47Linter", "Phi47LLMWrapper", "PhiCalculator"]
phi47/cli/__init__.py ADDED
@@ -0,0 +1,2 @@
1
+ # Copyright (c) 2025 wcalmels -- TUCH Systems Research Laboratory
2
+ # SPDX-License-Identifier: MIT
phi47/cli/main.py ADDED
@@ -0,0 +1,102 @@
1
+ # Copyright (c) 2025 wcalmels -- TUCH Systems Research Laboratory
2
+ # SPDX-License-Identifier: MIT
3
+ from __future__ import annotations
4
+ import json
5
+ from pathlib import Path
6
+ import click
7
+ from rich.console import Console
8
+ from rich.table import Table
9
+ from phi47.linter.phi_linter import Phi47Linter
10
+ from phi47.wrapper.llm_wrapper import Phi47LLMWrapper
11
+
12
+ console = Console()
13
+
14
+
15
+ @click.group()
16
+ @click.version_option("0.1.0", prog_name="phi47")
17
+ def cli():
18
+ """phi47 -- structural code quality layer based on IIT 4.0."""
19
+
20
+
21
+ @cli.command()
22
+ @click.argument("path", default=".")
23
+ @click.option("--json", "as_json", is_flag=True, help="Output JSON")
24
+ @click.option("--quiet", is_flag=True, help="Only show errors")
25
+ def analyze(path, as_json, quiet):
26
+ """Analyze Phi of a file or directory."""
27
+ linter = Phi47Linter()
28
+ p = Path(path)
29
+ if p.is_file():
30
+ diags = linter.lint_file(str(p))
31
+ if as_json:
32
+ click.echo(json.dumps([d.to_dict() for d in diags], indent=2))
33
+ return
34
+ phi = next((d.phi_value for d in diags if d.code == "P001"), 0.65)
35
+ icon = "G" if phi > 0.6 else "Y" if phi > 0.3 else "R"
36
+ console.print(f"[{icon}] {p.name} Phi={phi:.3f}")
37
+ show = diags if not quiet else [d for d in diags if d.severity == "error"]
38
+ for d in show[:8]:
39
+ c = {"error":"red","warning":"yellow","info":"blue","hint":"dim"}.get(d.severity,"white")
40
+ console.print(f" [{c}][{d.code}][/{c}] L{d.line}: {d.message}")
41
+ if not quiet:
42
+ console.print(f" [dim]-> {d.suggestion}[/dim]")
43
+ else:
44
+ all_d = linter.lint_directory(str(p))
45
+ if as_json:
46
+ click.echo(json.dumps(
47
+ {fp: [d.to_dict() for d in ds] for fp, ds in all_d.items()}, indent=2))
48
+ return
49
+ import numpy as np
50
+ t = Table(title=f"Phi47: {p}")
51
+ t.add_column("File", style="cyan")
52
+ t.add_column("Phi", justify="right")
53
+ t.add_column("E", justify="right", style="red")
54
+ t.add_column("W", justify="right", style="yellow")
55
+ phis = []
56
+ for fp, ds in sorted(all_d.items()):
57
+ phi = next((d.phi_value for d in ds if d.code == "P001"), 0.65)
58
+ phis.append(phi)
59
+ e = sum(1 for d in ds if d.severity == "error")
60
+ w = sum(1 for d in ds if d.severity == "warning")
61
+ t.add_row(Path(fp).name, f"{phi:.3f}", str(e), str(w))
62
+ console.print(t)
63
+ if phis:
64
+ console.print(f"System Phi = {float(np.mean(phis)):.3f}")
65
+
66
+
67
+ @cli.command()
68
+ @click.argument("task")
69
+ @click.option("--output", "-o", default=None)
70
+ @click.option("--backend", "-b", default="claude")
71
+ @click.option("--threshold", default=0.5)
72
+ def generate(task, output, backend, threshold):
73
+ """Generate code with Phi analysis and auto-refinement."""
74
+ console.print(f"[cyan]Task:[/cyan] {task} [cyan]Backend:[/cyan] {backend}")
75
+ w = Phi47LLMWrapper(backend=backend, phi_threshold=threshold)
76
+ r = w.generate(task)
77
+ ok = "OK" if r["phi_ok"] else "!!"
78
+ console.print(f"[{ok}] Phi={r['phi']:.3f} refinements={r['refinements']}")
79
+ if output:
80
+ Path(output).write_text(r["code"], encoding="utf-8")
81
+ console.print(f"Saved: {output}")
82
+ else:
83
+ click.echo(r["code"])
84
+ for s in r["suggestions"][:3]:
85
+ console.print(f" -> {s}")
86
+
87
+
88
+ @cli.command()
89
+ @click.argument("path", default=".")
90
+ def init(path):
91
+ """Initialize Phi47 in a project."""
92
+ p = Path(path)
93
+ cfg = {"version": "0.1.0", "phi_threshold": 0.5,
94
+ "auto_refine": True, "backend": "claude"}
95
+ (p / ".phi47.json").write_text(json.dumps(cfg, indent=2), encoding="utf-8")
96
+ hook = p / ".git" / "hooks" / "pre-commit"
97
+ if hook.parent.exists():
98
+ hook.write_text("#!/bin/bash\nphi47 analyze . --quiet || exit 1\n", encoding="utf-8")
99
+ import stat
100
+ hook.chmod(hook.stat().st_mode | stat.S_IEXEC)
101
+ console.print("[green]Git hook installed[/green]")
102
+ console.print("[bold green]Phi47 initialized![/bold green] Run: phi47 analyze .")
phi47/core/__init__.py ADDED
@@ -0,0 +1,2 @@
1
+ # Copyright (c) 2025 wcalmels -- TUCH Systems Research Laboratory
2
+ # SPDX-License-Identifier: MIT
@@ -0,0 +1,67 @@
1
+ # Copyright (c) 2025 wcalmels -- TUCH Systems Research Laboratory
2
+ # SPDX-License-Identifier: MIT
3
+ from __future__ import annotations
4
+ import numpy as np
5
+ from scipy import linalg
6
+
7
+
8
+ class PhiCalculator:
9
+ """Calculates Phi for a connectivity matrix using spectral approximation (IIT 4.0).
10
+
11
+ Example::
12
+
13
+ calc = PhiCalculator()
14
+ import numpy as np
15
+ phi, meta = calc.calculate(np.random.rand(5, 5))
16
+ print(phi)
17
+ """
18
+
19
+ def calculate(self, connectivity: np.ndarray, method: str = "spectral") -> tuple:
20
+ """Calculate Phi.
21
+
22
+ Args:
23
+ connectivity: Square NxN float matrix.
24
+ method: 'spectral' (fast, O(n^3)) or 'exact' (n<=8 only).
25
+
26
+ Returns:
27
+ Tuple of (phi: float, metadata: dict).
28
+ """
29
+ if connectivity.ndim != 2 or connectivity.shape[0] != connectivity.shape[1]:
30
+ raise ValueError(f"Expected square matrix, got {connectivity.shape}")
31
+ m = (connectivity + connectivity.T) / 2.0
32
+ m = np.nan_to_num(m, nan=0.0)
33
+ if method == "exact" and m.shape[0] <= 8:
34
+ return self._exact(m)
35
+ return self._spectral(m)
36
+
37
+ def _spectral(self, m: np.ndarray) -> tuple:
38
+ cov = m @ m.T
39
+ eigv = linalg.eigvalsh(cov)
40
+ eigv = eigv[eigv > 1e-10]
41
+ if not len(eigv):
42
+ return 0.0, {"method": "spectral", "phi": 0.0}
43
+ eigv /= eigv.sum()
44
+ h = float(-np.sum(eigv * np.log2(eigv + 1e-12)))
45
+ k = float(np.mean(np.abs(m)))
46
+ phi = h * (1.0 - np.exp(-k))
47
+ return float(phi), {"method": "spectral", "phi": phi,
48
+ "total_information": h, "integration_factor": 1 - np.exp(-k)}
49
+
50
+ def _exact(self, m: np.ndarray) -> tuple:
51
+ from itertools import combinations
52
+ n = m.shape[0]
53
+ all_idx = list(range(n))
54
+ min_phi = float("inf")
55
+ mip = None
56
+ for k in range(1, n // 2 + 1):
57
+ for pa in combinations(all_idx, k):
58
+ pa = list(pa)
59
+ pb = [i for i in all_idx if i not in pa]
60
+ mi = max(0.0,
61
+ np.linalg.norm(m[np.ix_(pa, pa)], "fro")
62
+ + np.linalg.norm(m[np.ix_(pb, pb)], "fro")
63
+ - np.linalg.norm(m, "fro"))
64
+ if mi < min_phi:
65
+ min_phi, mip = mi, (pa, pb)
66
+ phi = float(min_phi) if min_phi != float("inf") else 0.0
67
+ return phi, {"method": "exact", "phi": phi, "mip": mip}
@@ -0,0 +1,2 @@
1
+ # Copyright (c) 2025 wcalmels -- TUCH Systems Research Laboratory
2
+ # SPDX-License-Identifier: MIT
@@ -0,0 +1,177 @@
1
+ # Copyright (c) 2025 wcalmels -- TUCH Systems Research Laboratory
2
+ # SPDX-License-Identifier: MIT
3
+ from __future__ import annotations
4
+ import ast, json
5
+ from dataclasses import dataclass, asdict
6
+ from pathlib import Path
7
+ import numpy as np
8
+ from phi47.core.phi_calculator import PhiCalculator
9
+
10
+
11
+ @dataclass(frozen=True)
12
+ class Diagnostic:
13
+ file: str
14
+ line: int
15
+ col: int
16
+ severity: str
17
+ code: str
18
+ message: str
19
+ phi_value: float
20
+ suggestion: str
21
+
22
+ def to_dict(self): return asdict(self)
23
+ def __str__(self):
24
+ return f"{self.file}:{self.line}:{self.col}: {self.severity} [{self.code}] {self.message}"
25
+
26
+
27
+ class Phi47Linter:
28
+ """Phi-based linter compatible with any LSP editor.
29
+
30
+ Example::
31
+
32
+ linter = Phi47Linter()
33
+ for d in linter.lint_file("mycode.py"):
34
+ print(d)
35
+ """
36
+
37
+ def __init__(self, phi_error=0.3, phi_warning=0.5,
38
+ complexity_error=15, complexity_warning=10, max_lines=80):
39
+ self.phi_error = phi_error
40
+ self.phi_warning = phi_warning
41
+ self.complexity_error = complexity_error
42
+ self.complexity_warning = complexity_warning
43
+ self.max_lines = max_lines
44
+ self._calc = PhiCalculator()
45
+
46
+ def lint_file(self, filepath: str) -> list:
47
+ p = Path(filepath)
48
+ try:
49
+ tree = ast.parse(p.read_text(encoding="utf-8"), filename=str(p))
50
+ except SyntaxError as e:
51
+ return [Diagnostic(str(p), e.lineno or 1, 0, "error", "P000",
52
+ f"Syntax: {e.msg}", 0.0, "Fix syntax first.")]
53
+ except OSError as e:
54
+ return [Diagnostic(str(p), 1, 0, "error", "P000",
55
+ f"IO: {e}", 0.0, "Check permissions.")]
56
+ funcs = _extract_functions(tree)
57
+ clss = _extract_classes(tree)
58
+ matrix = _build_dep_matrix(funcs)
59
+ diags = []
60
+ diags += self._check_phi(str(p), matrix)
61
+ diags += self._check_funcs(str(p), funcs)
62
+ diags += self._check_cd(str(p), matrix)
63
+ diags += self._check_classes(str(p), clss)
64
+ return sorted(diags, key=lambda d: (d.line, d.code))
65
+
66
+ def lint_directory(self, directory: str) -> dict:
67
+ skip = {".venv", "venv", "__pycache__", ".git", "dist", "build"}
68
+ out = {}
69
+ for f in Path(directory).rglob("*.py"):
70
+ if any(p in skip for p in f.parts): continue
71
+ d = self.lint_file(str(f))
72
+ if d: out[str(f)] = d
73
+ return out
74
+
75
+ def lint_to_json(self, path: str) -> str:
76
+ if Path(path).is_dir():
77
+ data = {fp: [d.to_dict() for d in ds]
78
+ for fp, ds in self.lint_directory(path).items()}
79
+ else:
80
+ data = {path: [d.to_dict() for d in self.lint_file(path)]}
81
+ return json.dumps(data, indent=2)
82
+
83
+ def _check_phi(self, fp, matrix):
84
+ if matrix.shape[0] < 2: return []
85
+ phi, _ = self._calc.calculate(matrix)
86
+ if phi < self.phi_error:
87
+ return [Diagnostic(fp, 1, 0, "error", "P001",
88
+ f"System Phi={phi:.3f} critically low (threshold {self.phi_error})",
89
+ phi, "Add connections between functions.")]
90
+ if phi < self.phi_warning:
91
+ return [Diagnostic(fp, 1, 0, "warning", "P001",
92
+ f"System Phi={phi:.3f} below recommended (threshold {self.phi_warning})",
93
+ phi, "Consider increasing causal connections.")]
94
+ return []
95
+
96
+ def _check_funcs(self, fp, funcs):
97
+ diags = []
98
+ for name, data in funcs.items():
99
+ calls = set(data["calls"])
100
+ callers = {n for n, d in funcs.items() if name in d["calls"]}
101
+ cx, ln, lines = data["complexity"], data["lineno"], data["lines"]
102
+ if not calls and not callers and name not in {"main","__init__","__new__"}:
103
+ diags.append(Diagnostic(fp, ln, 0, "warning", "P002",
104
+ f"Zombie function: '{name}' has no callers and no callees",
105
+ 0.0, f"Connect or remove '{name}'."))
106
+ if cx > self.complexity_error:
107
+ diags.append(Diagnostic(fp, ln, 0, "error", "P003",
108
+ f"'{name}' complexity={cx} > {self.complexity_error}",
109
+ 0.0, "Decompose into smaller functions."))
110
+ elif cx > self.complexity_warning:
111
+ diags.append(Diagnostic(fp, ln, 0, "warning", "P003",
112
+ f"'{name}' complexity={cx}", 0.0, "Consider splitting."))
113
+ if lines > self.max_lines:
114
+ diags.append(Diagnostic(fp, ln, 0, "hint", "P007",
115
+ f"'{name}' is {lines} lines (limit {self.max_lines})",
116
+ 0.0, "Functions over 80 lines often have multiple responsibilities."))
117
+ return diags
118
+
119
+ def _check_cd(self, fp, matrix):
120
+ n = matrix.shape[0]
121
+ if n < 3: return []
122
+ cd = float(np.sum(matrix > 0) / (n * (n - 1) + 1e-10))
123
+ if cd < 0.05:
124
+ return [Diagnostic(fp, 1, 0, "info", "P004",
125
+ f"Low causal density={cd:.3f}: modules mostly isolated",
126
+ cd, "Consider a shared utility module.")]
127
+ return []
128
+
129
+ def _check_classes(self, fp, classes):
130
+ diags = []
131
+ for name, data in classes.items():
132
+ if not data["bases"] and not data["methods"]:
133
+ diags.append(Diagnostic(fp, data["lineno"], 0, "hint", "P006",
134
+ f"Class '{name}' has no base class and no methods",
135
+ 0.0, "Consider @dataclass or adding methods."))
136
+ return diags
137
+
138
+
139
+ def _extract_functions(tree):
140
+ funcs = {}
141
+ for node in ast.walk(tree):
142
+ if isinstance(node, ast.FunctionDef):
143
+ calls = []
144
+ for c in ast.walk(node):
145
+ if isinstance(c, ast.Call):
146
+ if isinstance(c.func, ast.Name): calls.append(c.func.id)
147
+ elif isinstance(c.func, ast.Attribute): calls.append(c.func.attr)
148
+ cx = 1 + sum(1 for n in ast.walk(node)
149
+ if isinstance(n, (ast.If, ast.For, ast.While,
150
+ ast.Try, ast.ExceptHandler)))
151
+ end = getattr(node, "end_lineno", node.lineno)
152
+ funcs[node.name] = {"calls": list(set(calls)), "complexity": cx,
153
+ "lineno": node.lineno, "lines": end - node.lineno}
154
+ return funcs
155
+
156
+
157
+ def _extract_classes(tree):
158
+ out = {}
159
+ for node in ast.walk(tree):
160
+ if isinstance(node, ast.ClassDef):
161
+ bases = [b.id if isinstance(b, ast.Name) else "?" for b in node.bases]
162
+ methods = [n.name for n in ast.walk(node) if isinstance(n, ast.FunctionDef)]
163
+ out[node.name] = {"bases": bases, "methods": methods, "lineno": node.lineno}
164
+ return out
165
+
166
+
167
+ def _build_dep_matrix(funcs):
168
+ names = list(funcs.keys())
169
+ n = len(names)
170
+ if n < 2: return np.zeros((2, 2))
171
+ idx = {name: i for i, name in enumerate(names)}
172
+ matrix = np.zeros((n, n), dtype=float)
173
+ for name, data in funcs.items():
174
+ i = idx[name]
175
+ for c in data["calls"]:
176
+ if c in idx: matrix[i, idx[c]] = 1.0
177
+ return matrix
@@ -0,0 +1,2 @@
1
+ # Copyright (c) 2025 wcalmels -- TUCH Systems Research Laboratory
2
+ # SPDX-License-Identifier: MIT
@@ -0,0 +1,105 @@
1
+ # Copyright (c) 2025 wcalmels -- TUCH Systems Research Laboratory
2
+ # SPDX-License-Identifier: MIT
3
+ from __future__ import annotations
4
+ import os
5
+ from pathlib import Path
6
+ from phi47.linter.phi_linter import Phi47Linter
7
+
8
+
9
+ class Phi47LLMWrapper:
10
+ """Universal LLM wrapper that adds Phi analysis to generated code.
11
+
12
+ Supports Claude, GPT-4, and any chat-compatible API.
13
+ Caller keeps their own API key -- no markup, no vendor lock-in.
14
+
15
+ Example::
16
+
17
+ w = Phi47LLMWrapper(backend="claude")
18
+ r = w.generate("Build a binary search tree")
19
+ print(r["phi"], r["code"])
20
+ """
21
+
22
+ SYSTEM = ("You are an expert Python developer. Write clean code with high "
23
+ "causal cohesion. Include type hints and docstrings. "
24
+ "Return ONLY Python code, no explanation.")
25
+
26
+ def __init__(self, backend="claude", api_key=None,
27
+ phi_threshold=0.5, auto_refine=True, max_refinements=2):
28
+ self.backend = backend
29
+ self.api_key = api_key or os.environ.get(
30
+ {"claude": "ANTHROPIC_API_KEY", "openai": "OPENAI_API_KEY"}.get(backend, ""), "")
31
+ self.phi_threshold = phi_threshold
32
+ self.auto_refine = auto_refine
33
+ self.max_refinements = max_refinements
34
+ self._linter = Phi47Linter()
35
+ self._client = None
36
+
37
+ def generate(self, task: str, context: str = "") -> dict:
38
+ """Generate code and run Phi analysis. Auto-refines if Phi < threshold."""
39
+ prompt = task if not context else f"{task}\n\nContext:\n{context}"
40
+ code = self._extract(self._call(prompt))
41
+ phi, diags = self._phi_of(code)
42
+ refs = 0
43
+ if self.auto_refine and phi < self.phi_threshold:
44
+ for _ in range(self.max_refinements):
45
+ issues = "\n".join(f"- [{d.code}] {d.message}" for d in diags[:3])
46
+ code = self._extract(self._call(
47
+ f"Refactor for higher Phi.\nIssues:\n{issues}\n\n`python\n{code}\n`"))
48
+ phi, diags = self._phi_of(code)
49
+ refs += 1
50
+ if phi >= self.phi_threshold:
51
+ break
52
+ return {
53
+ "code": code,
54
+ "phi": phi,
55
+ "phi_ok": phi >= self.phi_threshold,
56
+ "diagnostics": [{"code": d.code, "message": d.message} for d in diags],
57
+ "suggestions": list({d.suggestion for d in diags})[:4],
58
+ "refinements": refs,
59
+ "backend": self.backend,
60
+ }
61
+
62
+ def _call(self, prompt: str) -> str:
63
+ c = self._get_client()
64
+ if self.backend == "claude":
65
+ r = c.messages.create(
66
+ model="claude-sonnet-4-6", max_tokens=2048,
67
+ system=self.SYSTEM,
68
+ messages=[{"role": "user", "content": prompt}])
69
+ return r.content[0].text
70
+ if self.backend == "openai":
71
+ r = c.chat.completions.create(
72
+ model="gpt-4o", max_tokens=2048,
73
+ messages=[{"role": "system", "content": self.SYSTEM},
74
+ {"role": "user", "content": prompt}])
75
+ return r.choices[0].message.content
76
+ return f"# {prompt}\ndef solution(): pass\n"
77
+
78
+ def _get_client(self):
79
+ if self._client:
80
+ return self._client
81
+ if self.backend == "claude":
82
+ import anthropic
83
+ self._client = anthropic.Anthropic(api_key=self.api_key)
84
+ elif self.backend == "openai":
85
+ import openai
86
+ openai.api_key = self.api_key
87
+ self._client = openai
88
+ return self._client
89
+
90
+ def _phi_of(self, code: str):
91
+ tmp = Path("_phi47_tmp.py")
92
+ try:
93
+ tmp.write_text(code, encoding="utf-8")
94
+ diags = self._linter.lint_file(str(tmp))
95
+ phi = next((d.phi_value for d in diags if d.code == "P001"), 0.65)
96
+ return phi, diags
97
+ finally:
98
+ if tmp.exists():
99
+ tmp.unlink()
100
+
101
+ @staticmethod
102
+ def _extract(text: str) -> str:
103
+ if "`python" in text: return text.split("`python")[1].split("`")[0].strip()
104
+ if "`" in text: return text.split("`")[1].split("`")[0].strip()
105
+ return text.strip()
@@ -0,0 +1,98 @@
1
+ Metadata-Version: 2.4
2
+ Name: phi47-superpowers
3
+ Version: 0.1.0
4
+ Summary: Structural code quality layer based on IIT 4.0
5
+ Author-email: wcalmels <wcalmels@phi47.cl>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2025 wcalmels
9
+ TUCH Systems Research Laboratory -- Buenos Aires / Santiago
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in
19
+ all copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
+ THE SOFTWARE.
28
+
29
+ Project-URL: Homepage, https://phi47.tuch.systems
30
+ Project-URL: Repository, https://github.com/wcalmels/phi47-superpowers
31
+ Keywords: linter,code-quality,iit,phi,ast,developer-tools
32
+ Requires-Python: >=3.10
33
+ Description-Content-Type: text/markdown
34
+ License-File: LICENSE
35
+ Requires-Dist: numpy>=1.24
36
+ Requires-Dist: scipy>=1.11
37
+ Requires-Dist: click>=8.1
38
+ Requires-Dist: rich>=13.0
39
+ Provides-Extra: llm
40
+ Requires-Dist: anthropic>=0.20; extra == "llm"
41
+ Requires-Dist: openai>=1.0; extra == "llm"
42
+ Provides-Extra: dev
43
+ Requires-Dist: pytest>=7.4; extra == "dev"
44
+ Requires-Dist: pytest-cov>=4.1; extra == "dev"
45
+ Requires-Dist: black>=23.0; extra == "dev"
46
+ Requires-Dist: ruff>=0.1; extra == "dev"
47
+ Dynamic: license-file
48
+
49
+ # Phi47 Superpowers Layer
50
+
51
+ [![CI](https://github.com/TUCHSystems/phi47-superpowers/actions/workflows/ci.yml/badge.svg)](https://github.com/TUCHSystems/phi47-superpowers/actions)
52
+ [![PyPI](https://img.shields.io/pypi/v/phi47-superpowers)](https://pypi.org/project/phi47-superpowers/)
53
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
54
+
55
+ > Structural code quality layer based on Integrated Information Theory (IIT 4.0).
56
+ > Works on top of any editor (VS Code, Cursor, Neovim) or LLM (Claude, GPT-4, Gemini).
57
+ > No vendor lock-in. Use your own API keys.
58
+
59
+ ## Install
60
+
61
+ pip install phi47-superpowers
62
+ pip install "phi47-superpowers[llm]"
63
+
64
+ ## Quick start
65
+
66
+ phi47 analyze mycode.py
67
+ phi47 analyze .
68
+ phi47 generate "Build a REST API" --output api.py
69
+ phi47 init
70
+
71
+ ## Diagnostic codes
72
+
73
+ | Code | Issue | Severity |
74
+ |------|---------------------------|-----------------|
75
+ | P001 | Low system Phi | error / warning |
76
+ | P002 | Zombie function | warning |
77
+ | P003 | High cyclomatic complexity| error / warning |
78
+ | P004 | Low causal density | info |
79
+ | P006 | Disconnected class | hint |
80
+ | P007 | God function | hint |
81
+
82
+ ## Use as a library
83
+
84
+ from phi47 import Phi47Linter
85
+ linter = Phi47Linter()
86
+ for d in linter.lint_file("mycode.py"):
87
+ print(d)
88
+
89
+ ## Scientific background
90
+
91
+ Phi47 applies spectral IIT 4.0 to dependency graphs:
92
+ Phi = H(eigenvalues(C*C^T)) * (1 - e^(-k))
93
+ Runs in O(n^3) instead of exact O(2^n).
94
+
95
+ ## License
96
+
97
+ MIT License -- Copyright (c) 2025 Walter Calmels Von dem Knesebeck
98
+ TUCH Systems Research Laboratory
@@ -0,0 +1,15 @@
1
+ phi47/__init__.py,sha256=IkrSV5JME5GAJP-fqXDqiiEKcO11Dk9WWAn56jtuozo,499
2
+ phi47/cli/__init__.py,sha256=UUrV17MlE_BsxYvdVXHoNiUHzaBWVPn3TVLHPqB_-o4,100
3
+ phi47/cli/main.py,sha256=fZKafJRXbRCFmiDoP2crXiePjDk51eSixmzjCd4NuqE,4069
4
+ phi47/core/__init__.py,sha256=UUrV17MlE_BsxYvdVXHoNiUHzaBWVPn3TVLHPqB_-o4,100
5
+ phi47/core/phi_calculator.py,sha256=XUKHhz3tBzdviWCoGGgpSOwuuATWWMg3TEh6TQfsay0,2500
6
+ phi47/linter/__init__.py,sha256=UUrV17MlE_BsxYvdVXHoNiUHzaBWVPn3TVLHPqB_-o4,100
7
+ phi47/linter/phi_linter.py,sha256=CVnOyO6cwhx26tSxEPdhsZa8vQ-WVnBZgf2q6nUYU08,7220
8
+ phi47/wrapper/__init__.py,sha256=UUrV17MlE_BsxYvdVXHoNiUHzaBWVPn3TVLHPqB_-o4,100
9
+ phi47/wrapper/llm_wrapper.py,sha256=HhepME-POnM8BnsFLVrWytY6NmLAzXPHIxFjhA02WSU,4242
10
+ phi47_superpowers-0.1.0.dist-info/licenses/LICENSE,sha256=8pPQ3CTgxNqPcGHfkvjGC_CEuSfF1vEYZekvJwOljxk,1128
11
+ phi47_superpowers-0.1.0.dist-info/METADATA,sha256=5QTnctUHof3Q012wrym-hz6Zs3b3XlHi6RWxdm4efxI,3857
12
+ phi47_superpowers-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
13
+ phi47_superpowers-0.1.0.dist-info/entry_points.txt,sha256=V0nte5OpgHZmZ1cTw6ALD3TbiExJv3nyJamMZXZ8XVs,45
14
+ phi47_superpowers-0.1.0.dist-info/top_level.txt,sha256=qb0JezuO_gAiSqkyrvadUUnXfldsCweaWqxeoa8iRvc,6
15
+ phi47_superpowers-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ phi47 = phi47.cli.main:cli
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 wcalmels
4
+ TUCH Systems Research Laboratory -- Buenos Aires / Santiago
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
@@ -0,0 +1 @@
1
+ phi47