
banner("5) Evaluate skills on 5 quality dimensions (quality gate)")
DIMS = ["safety", "completeness", "executability", "maintainability", "cost_awareness"]
LEVEL_SCORE = {"Excellent": 4, "Good": 3, "Fair": 2, "Poor": 1, "Bad": 0}
def evaluate(target):
if USE_SDK and API_KEY:
try:
return client.evaluate(target=target)
except Exception as e:
print(f" evaluate failed for {target}: {e!r}")
return None
def mock_eval(name):
import hashlib
h = int(hashlib.md5(name.encode()).hexdigest(), 16)
levels = ["Excellent", "Good", "Fair", "Poor"]
return {d: {"level": levels[(h >> (i * 3)) % 4], "reason": "offline mock score"}
for i, d in enumerate(DIMS)}
def gate_score(report):
tot = sum(LEVEL_SCORE.get(report.get(d, {}).get("level", "Fair"), 2) for d in DIMS)
return tot / (len(DIMS) * 4)
GATE_THRESHOLD = 0.55
targets = [s["skill_url"] for s in (kw_hits + vec_hits) if s["skill_url"]][:3] \
or [i["name"] for i in inspected] or ["pdf-extractor", "chart-reader", "web-scraper"]
passed, scored = [], []
for t in targets:
rep = evaluate(t)
via = "LLM"
if rep is None:
rep, via = mock_eval(str(t)), "mock"
score = gate_score(rep)
scored.append((t, score, via))
flags = " ".join(f"{d[:4]}={rep.get(d,{}).get('level','?')[:4]}" for d in DIMS)
status = "PASS ✅" if score >= GATE_THRESHOLD else "FAIL ❌"
print(f" [{via:4}] {status} score={score:.2f} {textwrap.shorten(str(t),46,placeholder="...")}")
print(f" {flags}")
if score >= GATE_THRESHOLD:
passed.append(t)
print(f"\n{len(passed)}/{len(targets)} skills passed the quality gate (threshold={GATE_THRESHOLD}).")
banner("6) Analyze relationships and draw the Skill Graph")
def analyze(skills_dir):
if USE_SDK and API_KEY:
try:
return client.analyze(skills_dir=str(skills_dir))
except Exception as e:
print(f" analyze failed: {e!r}")
return None
rels = analyze(SKILLS_DIR)
if not rels:
names = [i["name"] for i in inspected] or ["PDF_Parser", "Text_Summarizer",
"Chart_Reader", "Web_Scraper"]
while len(names) < 4:
names.append(f"Skill_{len(names)}")
rels = [
{"source": names[0], "type": "compose_with", "target": names[1]},
{"source": names[2], "type": "similar_to", "target": names[0]},
{"source": names[3], "type": "depend_on", "target": names[1]},
{"source": names[1], "type": "belong_to", "target": names[2]},
]
print(" (using offline mock relationships — set API_KEY for real analysis)")
for r in rels:
print(f" {r['source']} --[{r['type']}]--> {r['target']}")
try:
import networkx as nx
import matplotlib.pyplot as plt
G = nx.DiGraph()
COLORS = {"similar_to": "#4C9BE8", "belong_to": "#E8A14C",
"compose_with": "#6BBF59", "depend_on": "#D45D79"}
for r in rels:
G.add_edge(r["source"], r["target"], type=r["type"])
pos = nx.spring_layout(G, seed=42, k=1.2)
plt.figure(figsize=(9, 6))
nx.draw_networkx_nodes(G, pos, node_size=2200, node_color="#EDEDED", edgecolors="#444")
nx.draw_networkx_labels(G, pos, font_size=9)
for et, col in COLORS.items():
edges = [(u, v) for u, v, d in G.edges(data=True) if d["type"] == et]
if edges:
nx.draw_networkx_edges(G, pos, edgelist=edges, edge_color=col,
width=2, arrows=True, arrowsize=18,
connectionstyle="arc3,rad=0.08")
plt.legend(handles=[plt.Line2D([0], [0], color=c, lw=2, label=t)
for t, c in COLORS.items()], loc="best", fontsize=8)
plt.title("SkillNet — Skill Relationship Graph")
plt.axis("off"); plt.tight_layout()
plt.savefig(WORKDIR / "skill_graph.png", dpi=130)
plt.show()
print(f" graph saved -> {WORKDIR/'skill_graph.png'}")
except Exception as e:
print(f" graph drawing skipped: {e!r}")





