@oriro/orirocli 0.1.9 → 0.1.12
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/README.md +16 -18
- package/dist/cli.js +4776 -2964
- package/package.json +2 -2
- package/skills/craft/ai-engineering/SKILL.md +2 -2
- package/skills/graphify/SKILL.md +0 -619
- package/skills/graphify/__init__.py +0 -28
- package/skills/graphify/__main__.py +0 -4582
- package/skills/graphify/affected.py +0 -154
- package/skills/graphify/always_on/agents-md.md +0 -12
- package/skills/graphify/always_on/antigravity-rules.md +0 -14
- package/skills/graphify/always_on/claude-md.md +0 -9
- package/skills/graphify/always_on/gemini-md.md +0 -9
- package/skills/graphify/always_on/kiro-steering.md +0 -5
- package/skills/graphify/always_on/vscode-instructions.md +0 -17
- package/skills/graphify/analyze.py +0 -724
- package/skills/graphify/benchmark.py +0 -155
- package/skills/graphify/build.py +0 -487
- package/skills/graphify/cache.py +0 -417
- package/skills/graphify/callflow_html.py +0 -2020
- package/skills/graphify/cluster.py +0 -272
- package/skills/graphify/command-kilo.md +0 -15
- package/skills/graphify/dedup.py +0 -429
- package/skills/graphify/detect.py +0 -1379
- package/skills/graphify/diagnostics.py +0 -390
- package/skills/graphify/export.py +0 -1408
- package/skills/graphify/extract.py +0 -11570
- package/skills/graphify/global_graph.py +0 -159
- package/skills/graphify/google_workspace.py +0 -223
- package/skills/graphify/hooks.py +0 -457
- package/skills/graphify/ingest.py +0 -331
- package/skills/graphify/llm.py +0 -1896
- package/skills/graphify/manifest.py +0 -4
- package/skills/graphify/mcp_ingest.py +0 -392
- package/skills/graphify/multigraph_compat.py +0 -212
- package/skills/graphify/pg_introspect.py +0 -142
- package/skills/graphify/prs.py +0 -748
- package/skills/graphify/querylog.py +0 -70
- package/skills/graphify/report.py +0 -218
- package/skills/graphify/scip_ingest.py +0 -363
- package/skills/graphify/security.py +0 -336
- package/skills/graphify/semantic_cleanup.py +0 -319
- package/skills/graphify/serve.py +0 -1309
- package/skills/graphify/skill-aider.md +0 -1246
- package/skills/graphify/skill-amp.md +0 -613
- package/skills/graphify/skill-claw.md +0 -616
- package/skills/graphify/skill-codex.md +0 -613
- package/skills/graphify/skill-copilot.md +0 -616
- package/skills/graphify/skill-devin.md +0 -1372
- package/skills/graphify/skill-droid.md +0 -613
- package/skills/graphify/skill-kilo.md +0 -625
- package/skills/graphify/skill-kiro.md +0 -615
- package/skills/graphify/skill-opencode.md +0 -608
- package/skills/graphify/skill-pi.md +0 -615
- package/skills/graphify/skill-trae.md +0 -614
- package/skills/graphify/skill-vscode.md +0 -612
- package/skills/graphify/skill-windows.md +0 -651
- package/skills/graphify/skills/amp/references/add-watch.md +0 -56
- package/skills/graphify/skills/amp/references/exports.md +0 -71
- package/skills/graphify/skills/amp/references/extraction-spec.md +0 -68
- package/skills/graphify/skills/amp/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/amp/references/hooks.md +0 -33
- package/skills/graphify/skills/amp/references/query.md +0 -249
- package/skills/graphify/skills/amp/references/transcribe.md +0 -48
- package/skills/graphify/skills/amp/references/update.md +0 -179
- package/skills/graphify/skills/claude/references/add-watch.md +0 -56
- package/skills/graphify/skills/claude/references/exports.md +0 -71
- package/skills/graphify/skills/claude/references/extraction-spec.md +0 -68
- package/skills/graphify/skills/claude/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/claude/references/hooks.md +0 -33
- package/skills/graphify/skills/claude/references/query.md +0 -103
- package/skills/graphify/skills/claude/references/transcribe.md +0 -48
- package/skills/graphify/skills/claude/references/update.md +0 -179
- package/skills/graphify/skills/claw/references/add-watch.md +0 -56
- package/skills/graphify/skills/claw/references/exports.md +0 -71
- package/skills/graphify/skills/claw/references/extraction-spec.md +0 -29
- package/skills/graphify/skills/claw/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/claw/references/hooks.md +0 -33
- package/skills/graphify/skills/claw/references/query.md +0 -249
- package/skills/graphify/skills/claw/references/transcribe.md +0 -48
- package/skills/graphify/skills/claw/references/update.md +0 -179
- package/skills/graphify/skills/codex/references/add-watch.md +0 -56
- package/skills/graphify/skills/codex/references/exports.md +0 -71
- package/skills/graphify/skills/codex/references/extraction-spec.md +0 -29
- package/skills/graphify/skills/codex/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/codex/references/hooks.md +0 -33
- package/skills/graphify/skills/codex/references/query.md +0 -249
- package/skills/graphify/skills/codex/references/transcribe.md +0 -48
- package/skills/graphify/skills/codex/references/update.md +0 -179
- package/skills/graphify/skills/copilot/references/add-watch.md +0 -56
- package/skills/graphify/skills/copilot/references/exports.md +0 -71
- package/skills/graphify/skills/copilot/references/extraction-spec.md +0 -68
- package/skills/graphify/skills/copilot/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/copilot/references/hooks.md +0 -33
- package/skills/graphify/skills/copilot/references/query.md +0 -249
- package/skills/graphify/skills/copilot/references/transcribe.md +0 -48
- package/skills/graphify/skills/copilot/references/update.md +0 -179
- package/skills/graphify/skills/droid/references/add-watch.md +0 -56
- package/skills/graphify/skills/droid/references/exports.md +0 -71
- package/skills/graphify/skills/droid/references/extraction-spec.md +0 -68
- package/skills/graphify/skills/droid/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/droid/references/hooks.md +0 -33
- package/skills/graphify/skills/droid/references/query.md +0 -249
- package/skills/graphify/skills/droid/references/transcribe.md +0 -48
- package/skills/graphify/skills/droid/references/update.md +0 -179
- package/skills/graphify/skills/kilo/references/add-watch.md +0 -56
- package/skills/graphify/skills/kilo/references/exports.md +0 -71
- package/skills/graphify/skills/kilo/references/extraction-spec.md +0 -68
- package/skills/graphify/skills/kilo/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/kilo/references/hooks.md +0 -33
- package/skills/graphify/skills/kilo/references/query.md +0 -249
- package/skills/graphify/skills/kilo/references/transcribe.md +0 -48
- package/skills/graphify/skills/kilo/references/update.md +0 -179
- package/skills/graphify/skills/kiro/references/add-watch.md +0 -56
- package/skills/graphify/skills/kiro/references/exports.md +0 -71
- package/skills/graphify/skills/kiro/references/extraction-spec.md +0 -29
- package/skills/graphify/skills/kiro/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/kiro/references/hooks.md +0 -33
- package/skills/graphify/skills/kiro/references/query.md +0 -249
- package/skills/graphify/skills/kiro/references/transcribe.md +0 -48
- package/skills/graphify/skills/kiro/references/update.md +0 -179
- package/skills/graphify/skills/opencode/references/add-watch.md +0 -56
- package/skills/graphify/skills/opencode/references/exports.md +0 -71
- package/skills/graphify/skills/opencode/references/extraction-spec.md +0 -68
- package/skills/graphify/skills/opencode/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/opencode/references/hooks.md +0 -33
- package/skills/graphify/skills/opencode/references/query.md +0 -249
- package/skills/graphify/skills/opencode/references/transcribe.md +0 -48
- package/skills/graphify/skills/opencode/references/update.md +0 -179
- package/skills/graphify/skills/pi/references/add-watch.md +0 -56
- package/skills/graphify/skills/pi/references/exports.md +0 -71
- package/skills/graphify/skills/pi/references/extraction-spec.md +0 -29
- package/skills/graphify/skills/pi/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/pi/references/hooks.md +0 -33
- package/skills/graphify/skills/pi/references/query.md +0 -249
- package/skills/graphify/skills/pi/references/transcribe.md +0 -48
- package/skills/graphify/skills/pi/references/update.md +0 -179
- package/skills/graphify/skills/trae/references/add-watch.md +0 -56
- package/skills/graphify/skills/trae/references/exports.md +0 -71
- package/skills/graphify/skills/trae/references/extraction-spec.md +0 -68
- package/skills/graphify/skills/trae/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/trae/references/hooks.md +0 -35
- package/skills/graphify/skills/trae/references/query.md +0 -249
- package/skills/graphify/skills/trae/references/transcribe.md +0 -48
- package/skills/graphify/skills/trae/references/update.md +0 -179
- package/skills/graphify/skills/vscode/references/add-watch.md +0 -56
- package/skills/graphify/skills/vscode/references/exports.md +0 -71
- package/skills/graphify/skills/vscode/references/extraction-spec.md +0 -68
- package/skills/graphify/skills/vscode/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/vscode/references/hooks.md +0 -33
- package/skills/graphify/skills/vscode/references/query.md +0 -249
- package/skills/graphify/skills/vscode/references/transcribe.md +0 -48
- package/skills/graphify/skills/vscode/references/update.md +0 -179
- package/skills/graphify/skills/windows/references/add-watch.md +0 -56
- package/skills/graphify/skills/windows/references/exports.md +0 -71
- package/skills/graphify/skills/windows/references/extraction-spec.md +0 -68
- package/skills/graphify/skills/windows/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/windows/references/hooks.md +0 -33
- package/skills/graphify/skills/windows/references/query.md +0 -249
- package/skills/graphify/skills/windows/references/transcribe.md +0 -48
- package/skills/graphify/skills/windows/references/update.md +0 -179
- package/skills/graphify/symbol_resolution.py +0 -538
- package/skills/graphify/transcribe.py +0 -184
- package/skills/graphify/tree_html.py +0 -582
- package/skills/graphify/validate.py +0 -72
- package/skills/graphify/watch.py +0 -898
- package/skills/graphify/wiki.py +0 -282
package/skills/graphify/wiki.py
DELETED
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
# Wiki export - Wikipedia-style markdown articles from the knowledge graph
|
|
2
|
-
# Generates an agent-crawlable wiki: index.md + one article per community + god node articles
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
from collections import Counter
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
import networkx as nx
|
|
7
|
-
|
|
8
|
-
from graphify.build import edge_data
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def _safe_filename(name: str) -> str:
|
|
12
|
-
"""Make a label safe for use as a filename across platforms.
|
|
13
|
-
|
|
14
|
-
Substitutes characters that Windows reserves in filenames
|
|
15
|
-
(< > : " / \\ | ? *) and strips trailing dots/spaces, also reserved.
|
|
16
|
-
Falls back to 'unnamed' for empty results and caps length at 200
|
|
17
|
-
chars to stay well under common filesystem limits.
|
|
18
|
-
"""
|
|
19
|
-
import re
|
|
20
|
-
s = name.replace("/", "-").replace(" ", "_").replace(":", "-")
|
|
21
|
-
s = re.sub(r'[<>:"/\\|?*]', '_', s)
|
|
22
|
-
s = s.strip('. ')
|
|
23
|
-
return s[:200] if s else 'unnamed'
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def _cross_community_links(G: nx.Graph, nodes: list[str], own_cid: int, labels: dict[int, str], node_community: dict[str, int]) -> list[tuple[str, int]]:
|
|
27
|
-
"""Return (community_label, edge_count) pairs for cross-community connections, sorted descending."""
|
|
28
|
-
counts: dict[str, int] = Counter()
|
|
29
|
-
for nid in nodes:
|
|
30
|
-
for neighbor in G.neighbors(nid):
|
|
31
|
-
ncid = node_community.get(neighbor)
|
|
32
|
-
if ncid is not None and ncid != own_cid:
|
|
33
|
-
counts[labels.get(ncid, f"Community {ncid}")] += 1
|
|
34
|
-
return sorted(counts.items(), key=lambda x: -x[1])
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def _community_article(
|
|
38
|
-
G: nx.Graph,
|
|
39
|
-
cid: int,
|
|
40
|
-
nodes: list[str],
|
|
41
|
-
label: str,
|
|
42
|
-
labels: dict[int, str],
|
|
43
|
-
cohesion: float | None,
|
|
44
|
-
node_community: dict[str, int] | None = None,
|
|
45
|
-
) -> str:
|
|
46
|
-
top_nodes = sorted(nodes, key=lambda n: G.degree(n), reverse=True)[:25]
|
|
47
|
-
cross = _cross_community_links(G, nodes, cid, labels, node_community or {})
|
|
48
|
-
|
|
49
|
-
# Edge confidence breakdown
|
|
50
|
-
conf_counts: Counter = Counter()
|
|
51
|
-
for nid in nodes:
|
|
52
|
-
for neighbor in G.neighbors(nid):
|
|
53
|
-
ed = edge_data(G, nid, neighbor)
|
|
54
|
-
conf_counts[ed.get("confidence", "EXTRACTED")] += 1
|
|
55
|
-
total_edges = sum(conf_counts.values()) or 1
|
|
56
|
-
|
|
57
|
-
sources = sorted({G.nodes[n].get("source_file") or "" for n in nodes} - {""})
|
|
58
|
-
|
|
59
|
-
lines: list[str] = []
|
|
60
|
-
lines += [f"# {label}", ""]
|
|
61
|
-
|
|
62
|
-
meta_parts = [f"{len(nodes)} nodes"]
|
|
63
|
-
if cohesion is not None:
|
|
64
|
-
meta_parts.append(f"cohesion {cohesion:.2f}")
|
|
65
|
-
lines += [f"> {' · '.join(meta_parts)}", ""]
|
|
66
|
-
|
|
67
|
-
lines += ["## Key Concepts", ""]
|
|
68
|
-
for nid in top_nodes:
|
|
69
|
-
d = G.nodes[nid]
|
|
70
|
-
node_label = d.get("label", nid)
|
|
71
|
-
src = d.get("source_file", "")
|
|
72
|
-
degree = G.degree(nid)
|
|
73
|
-
src_str = f" — `{src}`" if src else ""
|
|
74
|
-
lines.append(f"- **{node_label}** ({degree} connections){src_str}")
|
|
75
|
-
remaining = len(nodes) - len(top_nodes)
|
|
76
|
-
if remaining > 0:
|
|
77
|
-
lines.append(f"- *... and {remaining} more nodes in this community*")
|
|
78
|
-
lines.append("")
|
|
79
|
-
|
|
80
|
-
lines += ["## Relationships", ""]
|
|
81
|
-
if cross:
|
|
82
|
-
for other_label, count in cross[:12]:
|
|
83
|
-
lines.append(f"- [[{other_label}]] ({count} shared connections)")
|
|
84
|
-
else:
|
|
85
|
-
lines.append("- No strong cross-community connections detected")
|
|
86
|
-
lines.append("")
|
|
87
|
-
|
|
88
|
-
if sources:
|
|
89
|
-
lines += ["## Source Files", ""]
|
|
90
|
-
for src in sources[:20]:
|
|
91
|
-
lines.append(f"- `{src}`")
|
|
92
|
-
lines.append("")
|
|
93
|
-
|
|
94
|
-
lines += ["## Audit Trail", ""]
|
|
95
|
-
for conf in ("EXTRACTED", "INFERRED", "AMBIGUOUS"):
|
|
96
|
-
n = conf_counts.get(conf, 0)
|
|
97
|
-
pct = round(n / total_edges * 100)
|
|
98
|
-
lines.append(f"- {conf}: {n} ({pct}%)")
|
|
99
|
-
lines.append("")
|
|
100
|
-
|
|
101
|
-
lines += ["---", "", "*Part of the graphify knowledge wiki. See [[index]] to navigate.*"]
|
|
102
|
-
return "\n".join(lines)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
def _god_node_article(G: nx.Graph, nid: str, labels: dict[int, str], node_community: dict[str, int] | None = None) -> str:
|
|
106
|
-
d = G.nodes[nid]
|
|
107
|
-
node_label = d.get("label", nid)
|
|
108
|
-
src = d.get("source_file", "")
|
|
109
|
-
cid = (node_community or {}).get(nid)
|
|
110
|
-
community_name = labels.get(cid, f"Community {cid}") if cid is not None else None
|
|
111
|
-
|
|
112
|
-
lines: list[str] = []
|
|
113
|
-
lines += [f"# {node_label}", ""]
|
|
114
|
-
lines += [f"> God node · {G.degree(nid)} connections · `{src}`", ""]
|
|
115
|
-
|
|
116
|
-
if community_name:
|
|
117
|
-
lines += [f"**Community:** [[{community_name}]]", ""]
|
|
118
|
-
|
|
119
|
-
# Group neighbors by relation type
|
|
120
|
-
by_relation: dict[str, list[str]] = {}
|
|
121
|
-
for neighbor in sorted(G.neighbors(nid), key=lambda n: G.degree(n), reverse=True):
|
|
122
|
-
nd = G.nodes[neighbor]
|
|
123
|
-
ed = edge_data(G, nid, neighbor)
|
|
124
|
-
rel = ed.get("relation", "related")
|
|
125
|
-
neighbor_label = nd.get("label", neighbor)
|
|
126
|
-
conf = ed.get("confidence", "")
|
|
127
|
-
conf_str = f" `{conf}`" if conf else ""
|
|
128
|
-
by_relation.setdefault(rel, []).append(f"[[{neighbor_label}]]{conf_str}")
|
|
129
|
-
|
|
130
|
-
lines += ["## Connections by Relation", ""]
|
|
131
|
-
for rel, targets in sorted(by_relation.items()):
|
|
132
|
-
lines.append(f"### {rel}")
|
|
133
|
-
for t in targets[:20]:
|
|
134
|
-
lines.append(f"- {t}")
|
|
135
|
-
lines.append("")
|
|
136
|
-
|
|
137
|
-
lines += ["---", "", "*Part of the graphify knowledge wiki. See [[index]] to navigate.*"]
|
|
138
|
-
return "\n".join(lines)
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
def _index_md(
|
|
142
|
-
communities: dict[int, list[str]],
|
|
143
|
-
labels: dict[int, str],
|
|
144
|
-
god_nodes_data: list[dict],
|
|
145
|
-
total_nodes: int,
|
|
146
|
-
total_edges: int,
|
|
147
|
-
) -> str:
|
|
148
|
-
lines: list[str] = [
|
|
149
|
-
"# Knowledge Graph Index",
|
|
150
|
-
"",
|
|
151
|
-
"> Auto-generated by graphify. Start here — read community articles for context, then drill into god nodes for detail.",
|
|
152
|
-
"",
|
|
153
|
-
f"**{total_nodes} nodes · {total_edges} edges · {len(communities)} communities**",
|
|
154
|
-
"",
|
|
155
|
-
"---",
|
|
156
|
-
"",
|
|
157
|
-
"## Communities",
|
|
158
|
-
"(sorted by size, largest first)",
|
|
159
|
-
"",
|
|
160
|
-
]
|
|
161
|
-
|
|
162
|
-
for cid, nodes in sorted(communities.items(), key=lambda x: -len(x[1])):
|
|
163
|
-
label = labels.get(cid, f"Community {cid}")
|
|
164
|
-
lines.append(f"- [[{label}]] — {len(nodes)} nodes")
|
|
165
|
-
lines.append("")
|
|
166
|
-
|
|
167
|
-
if god_nodes_data:
|
|
168
|
-
lines += ["## God Nodes", "(most connected concepts — the load-bearing abstractions)", ""]
|
|
169
|
-
for node in god_nodes_data:
|
|
170
|
-
lines.append(f"- [[{node['label']}]] — {node['degree']} connections")
|
|
171
|
-
lines.append("")
|
|
172
|
-
|
|
173
|
-
lines += [
|
|
174
|
-
"---",
|
|
175
|
-
"",
|
|
176
|
-
"*Generated by [graphify](https://github.com/safishamsi/graphify)*",
|
|
177
|
-
]
|
|
178
|
-
return "\n".join(lines)
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
def to_wiki(
|
|
182
|
-
G: nx.Graph,
|
|
183
|
-
communities: dict[int, list[str]],
|
|
184
|
-
output_dir: str | Path,
|
|
185
|
-
community_labels: dict[int, str] | None = None,
|
|
186
|
-
cohesion: dict[int, float] | None = None,
|
|
187
|
-
god_nodes_data: list[dict] | None = None,
|
|
188
|
-
) -> int:
|
|
189
|
-
"""Generate a Wikipedia-style wiki from the graph.
|
|
190
|
-
|
|
191
|
-
Writes:
|
|
192
|
-
- index.md — agent entry point, catalog of all articles
|
|
193
|
-
- <CommunityName>.md — one article per community
|
|
194
|
-
- <GodNodeLabel>.md — one article per god node
|
|
195
|
-
|
|
196
|
-
Returns the number of articles written (excluding index.md).
|
|
197
|
-
"""
|
|
198
|
-
out = Path(output_dir)
|
|
199
|
-
out.mkdir(parents=True, exist_ok=True)
|
|
200
|
-
|
|
201
|
-
if not communities:
|
|
202
|
-
raise ValueError(
|
|
203
|
-
"communities dict is empty — refusing to clear wiki/. "
|
|
204
|
-
"Run `graphify extract .` or `graphify cluster-only .` first."
|
|
205
|
-
)
|
|
206
|
-
|
|
207
|
-
# Filter stale node IDs that exist in communities but not in G.
|
|
208
|
-
# Analysis JSON can drift from the graph after dedup / re-extract / update.
|
|
209
|
-
# NetworkX 3.x returns DegreeView({}) for missing nodes instead of raising,
|
|
210
|
-
# which crashes sorted() with TypeError; G.neighbors()/G.nodes[] also raise.
|
|
211
|
-
import sys as _sys
|
|
212
|
-
_g_nodes = set(G.nodes)
|
|
213
|
-
_orig_total = sum(len(ns) for ns in communities.values())
|
|
214
|
-
communities = {cid: [n for n in nodes if n in _g_nodes] for cid, nodes in communities.items()}
|
|
215
|
-
communities = {cid: nodes for cid, nodes in communities.items() if nodes}
|
|
216
|
-
_kept_total = sum(len(ns) for ns in communities.values())
|
|
217
|
-
if _kept_total < _orig_total:
|
|
218
|
-
print(
|
|
219
|
-
f"wiki: dropped {_orig_total - _kept_total} stale node ID(s) not in graph "
|
|
220
|
-
f"({len(communities)} communities remaining)",
|
|
221
|
-
file=_sys.stderr,
|
|
222
|
-
)
|
|
223
|
-
|
|
224
|
-
if not communities:
|
|
225
|
-
raise ValueError(
|
|
226
|
-
"all community node IDs are stale — none exist in the graph. "
|
|
227
|
-
"Re-run `graphify extract .` to regenerate .graphify_analysis.json."
|
|
228
|
-
)
|
|
229
|
-
|
|
230
|
-
# Clear stale .md files from previous runs to prevent orphan accumulation.
|
|
231
|
-
# Community labels are LLM-generated (per skill.md Step 5) and non-deterministic
|
|
232
|
-
# across runs — the same conceptual community may be named differently each time
|
|
233
|
-
# (e.g. "AutoAgent Skills" → "AutoAgent Methodology"), leaving the previous file
|
|
234
|
-
# as an orphan. Since to_wiki() owns wiki/ entirely (always writes the full set),
|
|
235
|
-
# it can safely clear .md files at the start of each call.
|
|
236
|
-
for old_article in out.glob("*.md"):
|
|
237
|
-
old_article.unlink()
|
|
238
|
-
|
|
239
|
-
labels = community_labels or {cid: f"Community {cid}" for cid in communities}
|
|
240
|
-
cohesion = cohesion or {}
|
|
241
|
-
god_nodes_data = god_nodes_data or []
|
|
242
|
-
|
|
243
|
-
# Build node->community lookup once; node attrs never carry community (it lives in
|
|
244
|
-
# the communities dict), so _cross_community_links and _god_node_article need this.
|
|
245
|
-
node_community: dict[str, int] = {n: cid for cid, nodes in communities.items() for n in nodes}
|
|
246
|
-
|
|
247
|
-
count = 0
|
|
248
|
-
used_slugs: set[str] = set()
|
|
249
|
-
|
|
250
|
-
def _unique_slug(base: str) -> str:
|
|
251
|
-
slug = base
|
|
252
|
-
n = 2
|
|
253
|
-
while slug in used_slugs:
|
|
254
|
-
slug = f"{base}_{n}"
|
|
255
|
-
n += 1
|
|
256
|
-
used_slugs.add(slug)
|
|
257
|
-
return slug
|
|
258
|
-
|
|
259
|
-
# Community articles
|
|
260
|
-
for cid, nodes in communities.items():
|
|
261
|
-
label = labels.get(cid, f"Community {cid}")
|
|
262
|
-
article = _community_article(G, cid, nodes, label, labels, cohesion.get(cid), node_community)
|
|
263
|
-
slug = _unique_slug(_safe_filename(label))
|
|
264
|
-
(out / f"{slug}.md").write_text(article, encoding="utf-8")
|
|
265
|
-
count += 1
|
|
266
|
-
|
|
267
|
-
# God node articles
|
|
268
|
-
for node_data in god_nodes_data:
|
|
269
|
-
nid = node_data.get("id")
|
|
270
|
-
if nid and nid in G:
|
|
271
|
-
article = _god_node_article(G, nid, labels, node_community)
|
|
272
|
-
slug = _unique_slug(_safe_filename(node_data['label']))
|
|
273
|
-
(out / f"{slug}.md").write_text(article, encoding="utf-8")
|
|
274
|
-
count += 1
|
|
275
|
-
|
|
276
|
-
# Index
|
|
277
|
-
(out / "index.md").write_text(
|
|
278
|
-
_index_md(communities, labels, god_nodes_data, G.number_of_nodes(), G.number_of_edges()),
|
|
279
|
-
encoding="utf-8",
|
|
280
|
-
)
|
|
281
|
-
|
|
282
|
-
return count
|