Forge
python0d405cb9
1# -*- coding: utf-8 -*-
2from pathlib import Path
3
4CSS = "/assets/css/site.css"
5ORG = "https://github.com/AI-Guiders"
6DOCS_CIDE = "https://ai-guiders.github.io/cascade-ide/"
7
8CARDS_EN = [
9 ("🚀", "cascade-ide", f'C#-first IDE, in-proc MCP, cockpit attention model. <a href="{DOCS_CIDE}">Docs</a>. MIT.', ["IDE", "Agents"]),
10 ("📝", "agent-notes-mcp", "Memory MCP 2.0, one TOML config. With kb-public.", ["MCP", "Memory"]),
11 ("📖", "kb-public", "Public KB slice for agents (CC BY-SA).", ["Knowledge", "CC BY-SA"]),
12 ("🔍", "RoslynMcp", "Roslyn diagnostics, code actions, rename.", ["C#", "Roslyn"]),
13 ("🔧", "dotnet-debug-mcp", "DAP debugging for agents.", ["MCP", "Debug"]),
14 ("📚", "agent-first-learn", "Course: designing with and for AI agents. MIT.", ["Course", "Agents"]),
15]
16
17CARDS_RU = [
18 ("🚀", "cascade-ide", f'IDE на C#, in-proc MCP, модель внимания кокпита. <a href="{DOCS_CIDE}">Документация</a>. MIT.', ["IDE", "Агенты"]),
19 ("📝", "agent-notes-mcp", "MCP памяти 2.0, один TOML. В паре с kb-public.", ["MCP", "Память"]),
20 ("📖", "kb-public", "Публичный срез KB для агентов (CC BY-SA).", ["Knowledge", "CC BY-SA"]),
21 ("🔍", "RoslynMcp", "Диагностики Roslyn, code actions, rename.", ["C#", "Roslyn"]),
22 ("🔧", "dotnet-debug-mcp", "Отладка DAP для агентов.", ["MCP", "Debug"]),
23 ("📚", "agent-first-learn", "Курс: проектирование с агентами и для агентов. MIT.", ["Курс", "Агенты"]),
24]
25
26
27def cards_html(cards):
28 parts = []
29 for icon, slug, desc, tags in cards:
30 d = desc.replace("kb-public", f'<a href="{ORG}/kb-public">kb-public</a>')
31 tag_html = "".join(f'<span class="tag">{t}</span>' for t in tags)
32 parts.append(
33 " <div class=\"project-card\">\n"
34 " <div class=\"card-header\">\n"
35 f" <motion class=\"card-icon\" aria-hidden=\"true\">{icon}</motion>\n"
36 f" <h3><a href=\"{ORG}/{slug}\">{slug}</a></h3>\n"
37 " </motion>\n"
38 f" <p class=\"desc\">{d}</p>\n"
39 f" <div class=\"tags\">{tag_html}</div>\n"
40 " </div>"
41 )
42 text = "\n".join(parts)
43 return text.replace("motion", "div")
44
45
46def page(lang, title, desc, nav_items, hero_label, h1, h1_accent, lead, about_title, about_text,
47 stack_title, stack_sub, handbook_title, handbook_sub, handbook_items, footer_links, css_path, base):
48 nav_lis = "\n".join(f' <li><a href="{href}">{label}</a></li>' for href, label in nav_items)
49 lang_en = 'aria-current="page"' if lang == "en" else ""
50 lang_ru = 'aria-current="page"' if lang == "ru" else ""
51 cards = cards_html(CARDS_EN if lang == "en" else CARDS_RU)
52 hb = "\n".join(
53 f' <li><a href="{u}">{t}</a><span class="meta">{m}</span></li>'
54 for u, t, m in handbook_items
55 )
56 fl = "\n".join(f' <a href="{u}">{t}</a>' for u, t in footer_links)
57 skip = "К содержанию" if lang == "ru" else "Skip to content"
58 nav_aria = "Основная навигация" if lang == "ru" else "Main navigation"
59 lang_aria = "Язык" if lang == "ru" else "Language"
60 btn_org = "GitHub org"
61 btn_stack = "Open stack"
62
63 html = f"""<!DOCTYPE html>
64<html lang="{lang}">
65<head>
66 <meta charset="utf-8" />
67 <meta name="viewport" content="width=device-width, initial-scale=1" />
68 <title>{title}</title>
69 <meta name="description" content="{desc}" />
70 <link rel="alternate" hreflang="en" href="/" />
71 <link rel="alternate" hreflang="ru" href="/ru/" />
72 <link rel="alternate" hreflang="x-default" href="/" />
73 <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>&#x1F916;</text></svg>" />
74 <link rel="stylesheet" href="{css_path}" />
75</head>
76<body>
77 <a href="#main" class="skip-link">{skip}</a>
78 <nav aria-label="{nav_aria}">
79 <div class="nav-inner">
80 <div class="logo"><a href="{base}">AI<span>-</span>Guiders</a></div>
81 <div class="nav-right">
82 <ul>
83{nav_lis}
84 </ul>
85 <ul class="nav-lang" aria-label="{lang_aria}">
86 <li><a href="/" lang="en" {lang_en}>EN</a></li>
87 <li class="nav-sep" aria-hidden="true">|</li>
88 <li><a href="/ru/" lang="ru" {lang_ru}>RU</a></li>
89 </ul>
90 </motion>
91 </motion>
92 </nav>
93 <main id="main">
94 <section class="hero">
95 <div class="container">
96 <div class="hero-content">
97 <div class="hero-label">{hero_label}</div>
98 <h1>{h1}<br /><span class="accent">{h1_accent}</span></h1>
99 <p class="lead">{lead}</p>
100 <div class="hero-buttons">
101 <a href="{ORG}" class="btn btn-primary">{btn_org}</a>
102 <a href="#stack" class="btn btn-outline">{btn_stack}</a>
103 </motion>
104 </motion>
105 </motion>
106 </section>
107 <section id="about">
108 <div class="container">
109 <h2 class="section-title">{about_title}</h2>
110 <p class="section-subtitle">{about_text}</p>
111 </motion>
112 </section>
113 <section id="stack">
114 <div class="container">
115 <h2 class="section-title">{stack_title}</h2>
116 <p class="section-subtitle">{stack_sub}</p>
117 <div class="card-grid">
118{cards}
119 </motion>
120 </motion>
121 </section>
122 <section id="handbook">
123 <div class="container">
124 <h2 class="section-title">{handbook_title}</h2>
125 <p class="section-subtitle">{handbook_sub}</p>
126 <ul class="link-list">
127{hb}
128 </ul>
129 </motion>
130 </section>
131 </main>
132 <footer>
133 <div class="links">
134{fl}
135 </motion>
136 <p>AI-Guiders &copy; 2026</p>
137 </footer>
138</body>
139</html>
140"""
141 return html.replace("motion", "div")
142
143
144root = Path(__file__).resolve().parent.parent / "docs"
145(root / "ru").mkdir(parents=True, exist_ok=True)
146
147en = page(
148 "en",
149 "AI-Guiders — Agent-first open stack for .NET",
150 "Open tools for agent-first .NET work: Cascade IDE, MCP servers, shared libraries.",
151 [("#about", "About"), ("#stack", "Open stack"), (DOCS_CIDE, "CIDE docs"), ("/writing/", "Writing"), ("#handbook", "Handbook"), (ORG, "GitHub")],
152 "Open source · .NET · MCP",
153 "Agent-first tools",
154 "you can verify",
155 "We build an IDE, MCP servers, and shared libraries so humans and coding agents "
156 "share the same ground truth — build, tests, git, Roslyn, and agent memory.",
157 "What we do",
158 "<strong>Parity</strong> — if an agent can do it via MCP, the IDE should not contradict it. "
159 "<strong>Observable loop</strong> — one legible contour for editor, tools, and agent. "
160 "Org essays in <a href=\"/writing/\">Writing</a>; longer personal archive on "
161 "<a href=\"https://karataevdmitry.github.io/writing/\">Dmitry Karataev's site</a>.",
162 "Open stack",
163 f"Full list: <a href=\"{ORG}\">github.com/AI-Guiders</a> · <a href=\"{DOCS_CIDE}\">Cascade IDE documentation</a> (ADR by status, RU/EN)",
164 "Handbook & KB",
165 "Org norms and agent knowledge.",
166 [
167 (f"{ORG}/handbook/wiki", "Handbook wiki", "Mission, values, boundaries (Russian)"),
168 (f"{ORG}/kb-public", "kb-public", "Public KB for agents"),
169 (f"{ORG}/handbook", "handbook repo", "Edit wiki/ folder, sync to GitHub Wiki"),
170 ],
171 [(ORG, "GitHub"), ("/writing/", "Writing"), ("https://karataevdmitry.github.io/writing/", "Personal archive")],
172 CSS,
173 "/",
174)
175ru = page(
176 "ru",
177 "AI-Guiders — open stack для agent-first .NET",
178 "Открытые инструменты для agent-first .NET: Cascade IDE, MCP, общие библиотеки.",
179 [("#about", "О нас"), ("#stack", "Open stack"), (DOCS_CIDE, "Доки CIDE"), ("/ru/writing/", "Тексты"), ("#handbook", "Handbook"), (ORG, "GitHub")],
180 "Open source · .NET · MCP",
181 "Инструменты для агентов",
182 "которым можно доверять",
183 "IDE, MCP-серверы и общие библиотеки — чтобы человек и coding agent смотрели "
184 "на одну правду: сборка, тесты, git, Roslyn, память агента.",
185 "Что делаем",
186 "<strong>Паритет</strong> — если агент делает через MCP, IDE не должна противоречить. "
187 "<strong>Наблюдаемый контур</strong> — редактор, инструменты и агент в одной картине. "
188 "Орг-тексты — в разделе <a href=\"/ru/writing/\">Тексты</a>; личный архив — на "
189 "<a href=\"https://karataevdmitry.github.io/ru/writing/\">сайте Дмитрия Каратаева</a>.",
190 "Open stack",
191 f"Полный список: <a href=\"{ORG}\">github.com/AI-Guiders</a> · <a href=\"{DOCS_CIDE}\">документация Cascade IDE</a> (ADR по статусам, RU/EN)",
192 "Handbook и KB",
193 "Нормы организации и знания для агентов.",
194 [
195 (f"{ORG}/handbook/wiki", "Handbook wiki", "Миссия, ценности, границы (RU)"),
196 (f"{ORG}/kb-public", "kb-public", "Публичный срез KB"),
197 (f"{ORG}/handbook", "репозиторий handbook", "Правки в wiki/, синхрон с GitHub Wiki"),
198 ],
199 [(ORG, "GitHub"), ("/ru/writing/", "Тексты"), ("https://karataevdmitry.github.io/ru/writing/", "Личный архив")],
200 "/assets/css/site.css",
201 "/ru/",
202)
203
204(root / "index.html").write_text(en, encoding="utf-8", newline="\n")
205(root / "ru" / "index.html").write_text(ru, encoding="utf-8", newline="\n")
206print("ok")
207
View only · write via MCP/CIDE