brain-wiki 0.1.0.dev0__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.
- brain_wiki-0.1.0.dev0.dist-info/METADATA +231 -0
- brain_wiki-0.1.0.dev0.dist-info/RECORD +141 -0
- brain_wiki-0.1.0.dev0.dist-info/WHEEL +4 -0
- brain_wiki-0.1.0.dev0.dist-info/entry_points.txt +4 -0
- brain_wiki-0.1.0.dev0.dist-info/licenses/LICENSE +202 -0
- brainwiki/__init__.py +17 -0
- brainwiki/__main__.py +5 -0
- brainwiki/assets/plugin/.claude-plugin/marketplace.json +16 -0
- brainwiki/assets/plugin/.claude-plugin/plugin.json +19 -0
- brainwiki/assets/plugin/.mcp.json +16 -0
- brainwiki/assets/plugin/mcp.json +17 -0
- brainwiki/assets/plugin/mcp_config.json +15 -0
- brainwiki/assets/plugin/plugin.json +37 -0
- brainwiki/assets/plugin/rules/brain-wiki.md +30 -0
- brainwiki/assets/plugin/server.json +30 -0
- brainwiki/assets/plugin/skills/brain/SKILL.md +145 -0
- brainwiki/assets/plugin/skills/brain/references/format.md +149 -0
- brainwiki/assets/plugin/skills/brain-maintain/SKILL.md +111 -0
- brainwiki/assets/plugin/skills/brain-maintain/references/consolidate.md +91 -0
- brainwiki/assets/plugin/skills/brain-maintain/references/harvest.md +144 -0
- brainwiki/assets/plugin/skills/brain-setup/SKILL.md +184 -0
- brainwiki/assets/plugin/skills/brain-setup/references/hosts.md +88 -0
- brainwiki/assets/plugin/skills/brain-setup/references/privacy.md +67 -0
- brainwiki/assets/prompts/consolidate.md +89 -0
- brainwiki/assets/prompts/distill.md +96 -0
- brainwiki/assets/prompts/harvest.md +142 -0
- brainwiki/bench/__init__.py +8 -0
- brainwiki/bench/_generate.py +440 -0
- brainwiki/bench/_report.py +166 -0
- brainwiki/bench/_suites.py +959 -0
- brainwiki/cli/__init__.py +7 -0
- brainwiki/cli/_cmd_bench.py +101 -0
- brainwiki/cli/_cmd_browse.py +281 -0
- brainwiki/cli/_cmd_consolidate.py +108 -0
- brainwiki/cli/_cmd_core.py +155 -0
- brainwiki/cli/_cmd_harvest.py +137 -0
- brainwiki/cli/_cmd_hosts.py +52 -0
- brainwiki/cli/_cmd_import.py +149 -0
- brainwiki/cli/_cmd_lint.py +117 -0
- brainwiki/cli/_cmd_read.py +131 -0
- brainwiki/cli/_cmd_runs.py +66 -0
- brainwiki/cli/_cmd_viz.py +57 -0
- brainwiki/cli/_cmd_write.py +122 -0
- brainwiki/cli/_main.py +511 -0
- brainwiki/cli/_output.py +19 -0
- brainwiki/config/__init__.py +56 -0
- brainwiki/config/_dirs.py +69 -0
- brainwiki/config/_manifest.py +307 -0
- brainwiki/config/_resolve.py +169 -0
- brainwiki/config/_user.py +183 -0
- brainwiki/consolidate/__init__.py +19 -0
- brainwiki/consolidate/_apply.py +408 -0
- brainwiki/consolidate/_packet.py +489 -0
- brainwiki/consolidate/_pipeline.py +215 -0
- brainwiki/consolidate/_presets.py +230 -0
- brainwiki/consolidate/_review.py +104 -0
- brainwiki/consolidate/_schema.py +153 -0
- brainwiki/consolidate/_validate.py +252 -0
- brainwiki/doctor.py +216 -0
- brainwiki/engine.py +80 -0
- brainwiki/errors.py +81 -0
- brainwiki/format/__init__.py +112 -0
- brainwiki/format/_agents_md.py +26 -0
- brainwiki/format/_claims.py +95 -0
- brainwiki/format/_document.py +203 -0
- brainwiki/format/_edit.py +94 -0
- brainwiki/format/_episode.py +67 -0
- brainwiki/format/_fields.py +350 -0
- brainwiki/format/_frontmatter.py +175 -0
- brainwiki/format/_links.py +72 -0
- brainwiki/format/_meta.py +67 -0
- brainwiki/format/_normalize.py +70 -0
- brainwiki/format/_relations.py +211 -0
- brainwiki/format/_rules.py +41 -0
- brainwiki/harvest.py +414 -0
- brainwiki/hosts/__init__.py +22 -0
- brainwiki/hosts/_antigravity.py +163 -0
- brainwiki/hosts/_claude_code.py +174 -0
- brainwiki/hosts/_codex.py +149 -0
- brainwiki/hosts/_connect.py +443 -0
- brainwiki/hosts/_detect.py +39 -0
- brainwiki/hosts/_instructions.py +220 -0
- brainwiki/hosts/_sessions.py +176 -0
- brainwiki/ids.py +69 -0
- brainwiki/importer/__init__.py +17 -0
- brainwiki/importer/_episodes.py +112 -0
- brainwiki/importer/_into.py +102 -0
- brainwiki/importer/_normalize.py +64 -0
- brainwiki/importer/_overlay.py +199 -0
- brainwiki/importer/_survey.py +167 -0
- brainwiki/index/__init__.py +44 -0
- brainwiki/index/_brains.py +119 -0
- brainwiki/index/_db.py +131 -0
- brainwiki/index/_guards.py +154 -0
- brainwiki/index/_neighbors.py +174 -0
- brainwiki/index/_orient.py +400 -0
- brainwiki/index/_read.py +285 -0
- brainwiki/index/_resolver.py +147 -0
- brainwiki/index/_scanner.py +665 -0
- brainwiki/index/_schema.py +164 -0
- brainwiki/index/_search.py +659 -0
- brainwiki/index/_topics.py +253 -0
- brainwiki/index/_written.py +29 -0
- brainwiki/lifecycle.py +158 -0
- brainwiki/lint/__init__.py +20 -0
- brainwiki/lint/_catalog.py +85 -0
- brainwiki/lint/_cross.py +649 -0
- brainwiki/lint/_files.py +483 -0
- brainwiki/lint/_fixes.py +87 -0
- brainwiki/lint/_hook.py +54 -0
- brainwiki/lint/_model.py +103 -0
- brainwiki/lint/_reports.py +242 -0
- brainwiki/lint/_runner.py +156 -0
- brainwiki/logs.py +34 -0
- brainwiki/mcp/__init__.py +7 -0
- brainwiki/mcp/_server.py +917 -0
- brainwiki/origin.py +97 -0
- brainwiki/runs/__init__.py +21 -0
- brainwiki/runs/_git.py +89 -0
- brainwiki/runs/_lock.py +42 -0
- brainwiki/runs/_record.py +145 -0
- brainwiki/runs/_transaction.py +441 -0
- brainwiki/runs/_undo.py +159 -0
- brainwiki/setup_wizard.py +143 -0
- brainwiki/store/__init__.py +7 -0
- brainwiki/store/_local.py +153 -0
- brainwiki/viz/__init__.py +9 -0
- brainwiki/viz/_export.py +414 -0
- brainwiki/viz/_lod.py +455 -0
- brainwiki/viz/_server.py +327 -0
- brainwiki/viz/app/BUILD_INFO.json +5 -0
- brainwiki/viz/app/THIRD_PARTY_NOTICES.txt +1519 -0
- brainwiki/viz/app/assets/index-gK1pnQdO.js +4496 -0
- brainwiki/viz/app/assets/style-Cg8NUCst.css +1 -0
- brainwiki/viz/app/index.html +14 -0
- brainwiki/write/__init__.py +23 -0
- brainwiki/write/_edits.py +730 -0
- brainwiki/write/_episode.py +195 -0
- brainwiki/write/_move.py +181 -0
- brainwiki/write/_rules.py +204 -0
- brainwiki/write/_secrets.py +108 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"""Bench output: results.json, report.md, a terminal table, and comparisons (design doc 11 §5)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from collections import defaultdict
|
|
7
|
+
from datetime import UTC, datetime
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from brainwiki.bench._suites import SuiteResult
|
|
12
|
+
|
|
13
|
+
_SCHEMA = 1
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def build(results: list[SuiteResult], **meta: Any) -> dict[str, Any]:
|
|
17
|
+
import brainwiki
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
"schema": _SCHEMA,
|
|
21
|
+
"version": brainwiki.__version__,
|
|
22
|
+
"created": datetime.now(UTC).replace(microsecond=0).isoformat(),
|
|
23
|
+
**meta,
|
|
24
|
+
"suites": {
|
|
25
|
+
r.name: {"status": r.status, "skipped": r.skipped, "details": r.details}
|
|
26
|
+
for r in results
|
|
27
|
+
},
|
|
28
|
+
"metrics": [m.to_json() for r in results for m in r.metrics],
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def hard_failures(data: dict[str, Any]) -> list[dict[str, Any]]:
|
|
33
|
+
return [m for m in data["metrics"] if m["hard"] and m["pass"] is False]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _value(value: Any) -> str:
|
|
37
|
+
if isinstance(value, float):
|
|
38
|
+
return f"{value:.4g}"
|
|
39
|
+
text = "-" if value is None else str(value)
|
|
40
|
+
return text if len(text) <= 60 else text[:59] + "…" # results.json keeps the full text
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _ok(row: dict[str, Any]) -> str:
|
|
44
|
+
return {True: "ok", False: "FAIL" if row["hard"] else "miss", None: ""}[row["pass"]]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _render(rows: list[list[str]], header: list[str], markdown: bool) -> list[str]:
|
|
48
|
+
if markdown:
|
|
49
|
+
lines = ["| " + " | ".join(header) + " |", "|" + "---|" * len(header)]
|
|
50
|
+
return lines + ["| " + " | ".join(r) + " |" for r in rows]
|
|
51
|
+
widths = [max(len(x) for x in col) for col in zip(header, *rows, strict=False)]
|
|
52
|
+
return [
|
|
53
|
+
" ".join(cell.ljust(w) for cell, w in zip(row, widths, strict=False)).rstrip()
|
|
54
|
+
for row in [header, *rows]
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def table(data: dict[str, Any], *, markdown: bool = False, collapse: int = 6) -> str:
|
|
59
|
+
"""One line per metric; groups larger than `collapse` (lint rules) fold into their worst value."""
|
|
60
|
+
header = ["suite", "case", "backend", "metric", "value", "target", "ok"]
|
|
61
|
+
groups: dict[tuple[str, str, str], list[dict[str, Any]]] = defaultdict(list)
|
|
62
|
+
for row in data["metrics"]:
|
|
63
|
+
groups[(row["suite"], row["metric"], row["backend"])].append(row)
|
|
64
|
+
rows: list[list[str]] = []
|
|
65
|
+
for (suite, metric, backend), members in groups.items():
|
|
66
|
+
numeric = [m for m in members if isinstance(m["value"], int | float)]
|
|
67
|
+
if len(members) <= collapse or len(numeric) != len(members):
|
|
68
|
+
for m in members:
|
|
69
|
+
rows.append(
|
|
70
|
+
[
|
|
71
|
+
suite,
|
|
72
|
+
m["case"],
|
|
73
|
+
backend,
|
|
74
|
+
metric,
|
|
75
|
+
_value(m["value"]),
|
|
76
|
+
m["target"] or "",
|
|
77
|
+
_ok(m),
|
|
78
|
+
]
|
|
79
|
+
)
|
|
80
|
+
continue
|
|
81
|
+
failed = [m["case"] for m in members if m["pass"] is False]
|
|
82
|
+
worst = min(numeric, key=lambda m: m["value"] if metric != "violations" else -m["value"])
|
|
83
|
+
case = f"{len(members)} cases" + (f"; failing: {', '.join(failed)}" if failed else "")
|
|
84
|
+
rows.append(
|
|
85
|
+
[
|
|
86
|
+
suite,
|
|
87
|
+
case,
|
|
88
|
+
backend,
|
|
89
|
+
metric,
|
|
90
|
+
_value(worst["value"]),
|
|
91
|
+
worst["target"] or "",
|
|
92
|
+
_ok(worst),
|
|
93
|
+
]
|
|
94
|
+
)
|
|
95
|
+
for name, suite in data["suites"].items():
|
|
96
|
+
if suite["skipped"]:
|
|
97
|
+
rows.append([name, "-", "-", "status", "skipped", "", ""])
|
|
98
|
+
return "\n".join(_render(rows, header, markdown))
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _markdown(data: dict[str, Any]) -> str:
|
|
102
|
+
lines = [
|
|
103
|
+
"# brain-wiki bench",
|
|
104
|
+
"",
|
|
105
|
+
f"`{data.get('command', 'brain bench')}` · brain-wiki {data['version']} · {data['created']}",
|
|
106
|
+
"",
|
|
107
|
+
"| suite | status |",
|
|
108
|
+
"|---|---|",
|
|
109
|
+
*[f"| {n} | {s['status']} |" for n, s in data["suites"].items()],
|
|
110
|
+
"",
|
|
111
|
+
]
|
|
112
|
+
for name, suite in data["suites"].items():
|
|
113
|
+
lines += [f"## {name}", ""]
|
|
114
|
+
if suite["skipped"]:
|
|
115
|
+
lines += [f"Skipped: {suite['skipped']}", ""]
|
|
116
|
+
continue
|
|
117
|
+
rows = [m for m in data["metrics"] if m["suite"] == name]
|
|
118
|
+
worst = [m for m in rows if m["metric"].startswith("worst_model")]
|
|
119
|
+
sub = {"metrics": worst + [m for m in rows if m not in worst], "suites": {}}
|
|
120
|
+
lines += [table(sub, markdown=True, collapse=10_000), ""]
|
|
121
|
+
for key, value in suite["details"].items():
|
|
122
|
+
if value in ({}, [], None):
|
|
123
|
+
continue
|
|
124
|
+
text = json.dumps(value, indent=1, ensure_ascii=False)
|
|
125
|
+
lines += [f"**{key}**", "", "```json", text, "```", ""]
|
|
126
|
+
return "\n".join(lines)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def write(out: Path, data: dict[str, Any]) -> tuple[Path, Path]:
|
|
130
|
+
out.mkdir(parents=True, exist_ok=True)
|
|
131
|
+
results, report = out / "results.json", out / "report.md"
|
|
132
|
+
results.write_text(json.dumps(data, indent=1, ensure_ascii=False) + "\n", encoding="utf-8")
|
|
133
|
+
report.write_text(_markdown(data), encoding="utf-8")
|
|
134
|
+
return results, report
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def compare(a: Path, b: Path) -> tuple[str, int]:
|
|
138
|
+
"""Metric deltas from results file A to B, and the number of regressions (pass -> fail)."""
|
|
139
|
+
old, new = (json.loads(Path(p).read_text(encoding="utf-8")) for p in (a, b))
|
|
140
|
+
|
|
141
|
+
def key(m: dict[str, Any]) -> tuple[str, str, str, str]:
|
|
142
|
+
return (m["suite"], m["case"], m["backend"], m["metric"])
|
|
143
|
+
|
|
144
|
+
before = {key(m): m for m in old["metrics"]}
|
|
145
|
+
after = {key(m): m for m in new["metrics"]}
|
|
146
|
+
lines, regressions = [], 0
|
|
147
|
+
for k in sorted(before.keys() | after.keys()):
|
|
148
|
+
x, y = before.get(k), after.get(k)
|
|
149
|
+
name = " ".join(p for p in k if p != "-")
|
|
150
|
+
if x is None or y is None:
|
|
151
|
+
lines.append(f"{'+' if x is None else '-'} {name}: {_value((y or x)['value'])}")
|
|
152
|
+
continue
|
|
153
|
+
if x["value"] == y["value"] and x["pass"] == y["pass"]:
|
|
154
|
+
continue
|
|
155
|
+
mark = " "
|
|
156
|
+
if x["pass"] is not False and y["pass"] is False:
|
|
157
|
+
mark, regressions = "!", regressions + 1
|
|
158
|
+
elif x["pass"] is False and y["pass"] is not False:
|
|
159
|
+
mark = "*"
|
|
160
|
+
delta = ""
|
|
161
|
+
if isinstance(x["value"], int | float) and isinstance(y["value"], int | float):
|
|
162
|
+
delta = f" ({y['value'] - x['value']:+.4g})"
|
|
163
|
+
lines.append(f"{mark} {name}: {_value(x['value'])} -> {_value(y['value'])}{delta}")
|
|
164
|
+
head = f"{a} ({old['version']}) -> {b} ({new['version']}): {regressions} regression(s)"
|
|
165
|
+
legend = "! regression (pass -> fail) * fixed (fail -> pass) +/- metric added/removed"
|
|
166
|
+
return "\n".join([head, legend, *(lines or ["no metric changed"])]), regressions
|