claude-code-arcane 1.1.1 → 1.2.0
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/CHANGELOG.md +7 -0
- package/dist/cli.js +284 -72
- package/docs/RELEASE-SETUP.md +99 -0
- package/docs/presentations/arcane-overview-12.pptx +0 -0
- package/docs/presentations/arcane-overview.pptx +0 -0
- package/docs/presentations/build_arcane_deck.py +310 -0
- package/docs/presentations/build_arcane_deck_12.py +399 -0
- package/package.json +1 -1
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Genera la presentacion DETALLADA de Claude Code Arcane (12 slides, 16:9)."""
|
|
3
|
+
import os
|
|
4
|
+
from pptx import Presentation
|
|
5
|
+
from pptx.util import Inches, Pt
|
|
6
|
+
from pptx.dml.color import RGBColor
|
|
7
|
+
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
|
|
8
|
+
from pptx.enum.shapes import MSO_SHAPE
|
|
9
|
+
|
|
10
|
+
# ---------- Tema (paleta Arcane: indigo profundo + cian) ----------
|
|
11
|
+
BG = RGBColor(0x1E, 0x1B, 0x4B)
|
|
12
|
+
PANEL = RGBColor(0x2A, 0x25, 0x60)
|
|
13
|
+
PANEL2 = RGBColor(0x31, 0x2E, 0x81)
|
|
14
|
+
VIOLET = RGBColor(0x5B, 0x4F, 0xE8)
|
|
15
|
+
CYAN = RGBColor(0x22, 0xD3, 0xEE)
|
|
16
|
+
WHITE = RGBColor(0xF8, 0xFA, 0xFC)
|
|
17
|
+
LIGHT = RGBColor(0xE5, 0xE7, 0xEB)
|
|
18
|
+
MUTED = RGBColor(0x9C, 0xA3, 0xC4)
|
|
19
|
+
GREEN = RGBColor(0x34, 0xD3, 0x99)
|
|
20
|
+
AMBER = RGBColor(0xFB, 0xBF, 0x24)
|
|
21
|
+
PINK = RGBColor(0xF4, 0x72, 0xB6)
|
|
22
|
+
CODEBG = RGBColor(0x14, 0x11, 0x33)
|
|
23
|
+
FONT = "Calibri"
|
|
24
|
+
MONO = "Consolas"
|
|
25
|
+
|
|
26
|
+
prs = Presentation()
|
|
27
|
+
prs.slide_width = Inches(13.333)
|
|
28
|
+
prs.slide_height = Inches(7.5)
|
|
29
|
+
BLANK = prs.slide_layouts[6]
|
|
30
|
+
SW, SH = prs.slide_width, prs.slide_height
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def slide():
|
|
34
|
+
s = prs.slides.add_slide(BLANK)
|
|
35
|
+
r = s.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0, SW, SH)
|
|
36
|
+
r.fill.solid(); r.fill.fore_color.rgb = BG
|
|
37
|
+
r.line.fill.background(); r.shadow.inherit = False
|
|
38
|
+
return s
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def rect(s, x, y, w, h, color, line=None, radius=False, line_w=1.0):
|
|
42
|
+
shp = MSO_SHAPE.ROUNDED_RECTANGLE if radius else MSO_SHAPE.RECTANGLE
|
|
43
|
+
sp = s.shapes.add_shape(shp, Inches(x), Inches(y), Inches(w), Inches(h))
|
|
44
|
+
if color is None:
|
|
45
|
+
sp.fill.background()
|
|
46
|
+
else:
|
|
47
|
+
sp.fill.solid(); sp.fill.fore_color.rgb = color
|
|
48
|
+
if line is None:
|
|
49
|
+
sp.line.fill.background()
|
|
50
|
+
else:
|
|
51
|
+
sp.line.color.rgb = line; sp.line.width = Pt(line_w)
|
|
52
|
+
sp.shadow.inherit = False
|
|
53
|
+
return sp
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def txt(s, x, y, w, h, runs, align=PP_ALIGN.LEFT, anchor=MSO_ANCHOR.TOP,
|
|
57
|
+
space_after=4, line_spacing=1.0, font=FONT):
|
|
58
|
+
tb = s.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h))
|
|
59
|
+
tf = tb.text_frame; tf.word_wrap = True
|
|
60
|
+
tf.vertical_anchor = anchor
|
|
61
|
+
for i, para in enumerate(runs):
|
|
62
|
+
p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
|
|
63
|
+
p.alignment = align
|
|
64
|
+
p.space_after = Pt(space_after); p.space_before = Pt(0)
|
|
65
|
+
p.line_spacing = line_spacing
|
|
66
|
+
for (t, sz, col, bold) in para:
|
|
67
|
+
r = p.add_run(); r.text = t
|
|
68
|
+
r.font.size = Pt(sz); r.font.color.rgb = col
|
|
69
|
+
r.font.bold = bold; r.font.name = font
|
|
70
|
+
return tb
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def badge(s, n):
|
|
74
|
+
c = s.shapes.add_shape(MSO_SHAPE.OVAL, Inches(12.55), Inches(6.85), Inches(0.42), Inches(0.42))
|
|
75
|
+
c.fill.solid(); c.fill.fore_color.rgb = VIOLET; c.line.fill.background(); c.shadow.inherit = False
|
|
76
|
+
tf = c.text_frame
|
|
77
|
+
p = tf.paragraphs[0]; p.alignment = PP_ALIGN.CENTER
|
|
78
|
+
r = p.add_run(); r.text = str(n)
|
|
79
|
+
r.font.size = Pt(12); r.font.bold = True; r.font.color.rgb = WHITE; r.font.name = FONT
|
|
80
|
+
tf.vertical_anchor = MSO_ANCHOR.MIDDLE
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def footer(s):
|
|
84
|
+
txt(s, 0.55, 7.02, 6, 0.35, [[("Claude Code Arcane", 9, MUTED, False)]])
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def kicker(s, text, color=CYAN):
|
|
88
|
+
rect(s, 0.55, 0.55, 0.12, 0.5, color)
|
|
89
|
+
txt(s, 0.8, 0.5, 11.5, 0.45, [[(text, 12.5, color, True)]])
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def title(s, text, y=0.92, size=32):
|
|
93
|
+
txt(s, 0.78, y, 11.9, 0.9, [[(text, size, WHITE, True)]])
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def chrome(s, n, kick, ttl, color=CYAN, tsize=32):
|
|
97
|
+
kicker(s, kick, color)
|
|
98
|
+
title(s, ttl, size=tsize)
|
|
99
|
+
badge(s, n); footer(s)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
# ================= SLIDE 1 — Portada =================
|
|
103
|
+
s = slide()
|
|
104
|
+
rect(s, 0, 0, 0.25, 7.5, VIOLET)
|
|
105
|
+
rect(s, 0.25, 0, 0.08, 7.5, CYAN)
|
|
106
|
+
txt(s, 1.0, 1.55, 11.5, 0.6, [[("CLAUDE CODE", 20, CYAN, True)]])
|
|
107
|
+
txt(s, 1.0, 2.0, 11.5, 1.4, [[("Arcane", 84, WHITE, True)]])
|
|
108
|
+
txt(s, 1.05, 3.42, 11, 0.6, [[("Un gestor de paquetes de configuracion para Claude Code", 21, LIGHT, False)]])
|
|
109
|
+
txt(s, 1.05, 4.0, 11, 0.5, [[("Skills, agentes, hooks y reglas — instalados selectivamente por stack.", 14, MUTED, False)]])
|
|
110
|
+
metrics = [("322", "Skills"), ("86", "Agentes"), ("29", "Profiles"), ("19", "Rules"), ("16", "Hooks")]
|
|
111
|
+
mx, mw, gap = 1.0, 2.12, 0.18
|
|
112
|
+
for i, (num, lbl) in enumerate(metrics):
|
|
113
|
+
x = mx + i * (mw + gap)
|
|
114
|
+
rect(s, x, 4.95, mw, 1.4, PANEL, radius=True)
|
|
115
|
+
rect(s, x, 4.95, 0.09, 1.4, CYAN if i % 2 else VIOLET)
|
|
116
|
+
txt(s, x, 5.12, mw, 0.7, [[(num, 40, WHITE, True)]], align=PP_ALIGN.CENTER)
|
|
117
|
+
txt(s, x, 5.88, mw, 0.4, [[(lbl.upper(), 12, CYAN, True)]], align=PP_ALIGN.CENTER)
|
|
118
|
+
txt(s, 1.0, 6.7, 11, 0.4, [[("Presentacion tecnica + de negocio · Educabot", 12, MUTED, False)]])
|
|
119
|
+
|
|
120
|
+
# ================= SLIDE 2 — Indice / recorrido =================
|
|
121
|
+
s = slide()
|
|
122
|
+
chrome(s, 2, "RECORRIDO", "Que vamos a ver")
|
|
123
|
+
items = [
|
|
124
|
+
("01", "El problema", "Por que la config de Claude no escala"),
|
|
125
|
+
("02", "La idea", "npm, pero para capacidades de IA"),
|
|
126
|
+
("03", "Arquitectura", "Como instala, mergea y deduplica"),
|
|
127
|
+
("04", "Las 4 piezas", "Skills, Agents, Hooks, Rules"),
|
|
128
|
+
("05", "Anatomia de una skill", "Frontmatter + markdown"),
|
|
129
|
+
("06", "Profiles", "El sistema de combinacion LEGO"),
|
|
130
|
+
("07", "Mecanismos avanzados", "Distribucion, update, worktrees"),
|
|
131
|
+
("08", "Calidad", "Testing automatizado de skills"),
|
|
132
|
+
("09", "Por que gana", "vs. las alternativas"),
|
|
133
|
+
("10", "Trade-offs y cierre", "Honesto + casos reales"),
|
|
134
|
+
]
|
|
135
|
+
positions = [(0.78, 2.0 + (i % 5) * 0.95, 0 if i < 5 else 1) for i in range(10)]
|
|
136
|
+
for (num, h, d), i in zip(items, range(10)):
|
|
137
|
+
col = 0 if i < 5 else 1
|
|
138
|
+
x = 0.78 + col * 6.15
|
|
139
|
+
y = 2.0 + (i % 5) * 0.95
|
|
140
|
+
rect(s, x, y, 5.85, 0.82, PANEL, radius=True)
|
|
141
|
+
txt(s, x + 0.25, y, 0.9, 0.82, [[(num, 22, VIOLET, True)]], anchor=MSO_ANCHOR.MIDDLE)
|
|
142
|
+
txt(s, x + 1.15, y + 0.1, 4.5, 0.4, [[(h, 14.5, CYAN, True)]])
|
|
143
|
+
txt(s, x + 1.15, y + 0.45, 4.6, 0.35, [[(d, 11, MUTED, False)]])
|
|
144
|
+
|
|
145
|
+
# ================= SLIDE 3 — El problema =================
|
|
146
|
+
s = slide()
|
|
147
|
+
chrome(s, 3, "POR QUE EXISTE", "El problema que resuelve")
|
|
148
|
+
problems = [
|
|
149
|
+
("Configuracion manual", "Copiar .claude/ a mano en cada proyecto: repetitivo y diverge con el tiempo."),
|
|
150
|
+
("Todo-o-nada", "Un mega-repo cargaria las 322 skills en CADA proyecto: mas tokens, mas ruido, mas latencia."),
|
|
151
|
+
("Sin estandarizacion", "Cada dev configura su Claude distinto. No hay fuente de verdad compartida."),
|
|
152
|
+
("Sin actualizacion", "Una mejora en una skill nunca llega a los proyectos que ya la copiaron."),
|
|
153
|
+
]
|
|
154
|
+
y = 2.0
|
|
155
|
+
for h, d in problems:
|
|
156
|
+
rect(s, 0.78, y, 11.7, 0.95, PANEL, radius=True)
|
|
157
|
+
rect(s, 0.78, y, 0.1, 0.95, VIOLET)
|
|
158
|
+
txt(s, 1.05, y + 0.1, 3.4, 0.75, [[(h, 16, CYAN, True)]], anchor=MSO_ANCHOR.MIDDLE)
|
|
159
|
+
txt(s, 4.5, y + 0.1, 7.8, 0.75, [[(d, 13, LIGHT, False)]], anchor=MSO_ANCHOR.MIDDLE)
|
|
160
|
+
y += 1.08
|
|
161
|
+
txt(s, 0.78, 6.55, 11.8, 0.5,
|
|
162
|
+
[[("Falta una forma modular, versionada y compartible de configurar Claude Code.", 15, WHITE, True)]])
|
|
163
|
+
|
|
164
|
+
# ================= SLIDE 4 — La idea central =================
|
|
165
|
+
s = slide()
|
|
166
|
+
chrome(s, 4, "LA IDEA CENTRAL", "npm, pero para las capacidades de Claude Code")
|
|
167
|
+
txt(s, 0.78, 1.95, 11.7, 0.9,
|
|
168
|
+
[[("En vez de instalar librerias de codigo, instalas ", 16, LIGHT, False),
|
|
169
|
+
("capacidades", 16, CYAN, True),
|
|
170
|
+
(": hacer commits, disenar APIs, correr un sprint, auditar seguridad — adaptadas a tu stack.", 16, LIGHT, False)]],
|
|
171
|
+
line_spacing=1.12)
|
|
172
|
+
rect(s, 0.78, 3.05, 11.7, 1.45, CODEBG, radius=True, line=VIOLET, line_w=1.5)
|
|
173
|
+
txt(s, 1.1, 3.22, 11, 0.35, [[("terminal", 11, MUTED, False)]], font=MONO)
|
|
174
|
+
txt(s, 1.1, 3.62, 11, 0.7,
|
|
175
|
+
[[("$ ", 24, CYAN, True), ("npx arcane install ", 24, WHITE, True),
|
|
176
|
+
("backend-ts", 24, GREEN, True), ("+agile", 24, AMBER, True), ("+testing", 24, AMBER, True)]], font=MONO)
|
|
177
|
+
cols = [("backend-ts", "base", GREEN), ("+agile", "addon", AMBER), ("+testing", "addon", AMBER)]
|
|
178
|
+
cx = 0.78
|
|
179
|
+
for name, kind, col in cols:
|
|
180
|
+
rect(s, cx, 4.75, 3.0, 1.05, PANEL, radius=True)
|
|
181
|
+
txt(s, cx, 4.9, 3.0, 0.5, [[(name, 17, col, True)]], align=PP_ALIGN.CENTER)
|
|
182
|
+
txt(s, cx, 5.4, 3.0, 0.35, [[(kind.upper(), 11, MUTED, True)]], align=PP_ALIGN.CENTER)
|
|
183
|
+
cx += 3.25
|
|
184
|
+
txt(s, 0.78, 6.05, 11.7, 0.5, [[("base + addon + addon -> solo lo que ESE proyecto necesita.", 15, WHITE, True)]])
|
|
185
|
+
|
|
186
|
+
# ================= SLIDE 5 — Como funciona =================
|
|
187
|
+
s = slide()
|
|
188
|
+
chrome(s, 5, "ARQUITECTURA", "Como funciona la instalacion")
|
|
189
|
+
steps = [
|
|
190
|
+
("1", "Resuelve el contenido", "GitHub -> cache local -> bundled (funciona offline)"),
|
|
191
|
+
("2", "Carga core.yaml siempre", "21 skills base + 15 hooks + permisos de seguridad"),
|
|
192
|
+
("3", "Mergea los profiles", "Combina los profiles pedidos con el separador +"),
|
|
193
|
+
("4", "Deduplica", "Un skill repetido en varios profiles se copia una sola vez"),
|
|
194
|
+
("5", "Genera .claude/", "settings.json + manifest + skills, agents, rules, hooks, docs"),
|
|
195
|
+
]
|
|
196
|
+
y = 1.95
|
|
197
|
+
for num, h, d in steps:
|
|
198
|
+
rect(s, 0.78, y, 11.7, 0.82, PANEL, radius=True)
|
|
199
|
+
c = s.shapes.add_shape(MSO_SHAPE.OVAL, Inches(0.98), Inches(y + 0.16), Inches(0.5), Inches(0.5))
|
|
200
|
+
c.fill.solid(); c.fill.fore_color.rgb = VIOLET; c.line.fill.background(); c.shadow.inherit = False
|
|
201
|
+
ctf = c.text_frame; ctf.vertical_anchor = MSO_ANCHOR.MIDDLE
|
|
202
|
+
cp = ctf.paragraphs[0]; cp.alignment = PP_ALIGN.CENTER
|
|
203
|
+
cr = cp.add_run(); cr.text = num; cr.font.size = Pt(20); cr.font.bold = True
|
|
204
|
+
cr.font.color.rgb = WHITE; cr.font.name = FONT
|
|
205
|
+
txt(s, 1.75, y + 0.04, 4.0, 0.74, [[(h, 15.5, CYAN, True)]], anchor=MSO_ANCHOR.MIDDLE)
|
|
206
|
+
txt(s, 5.9, y + 0.04, 6.4, 0.74, [[(d, 12.5, LIGHT, False)]], anchor=MSO_ANCHOR.MIDDLE)
|
|
207
|
+
y += 0.93
|
|
208
|
+
txt(s, 0.78, 6.6, 11.7, 0.4,
|
|
209
|
+
[[("Resultado: el .claude/ del proyecto contiene exactamente lo necesario — nada mas.", 13, MUTED, True)]])
|
|
210
|
+
|
|
211
|
+
# ================= SLIDE 6 — 4 piezas =================
|
|
212
|
+
s = slide()
|
|
213
|
+
chrome(s, 6, "SEPARACION DE RESPONSABILIDADES", "Cuatro piezas, cuatro responsabilidades")
|
|
214
|
+
cards = [
|
|
215
|
+
("Skills", "Acciones que Claude ejecuta", "/commit · /code-review · /sprint-plan", CYAN),
|
|
216
|
+
("Agents", "Personas que Claude adopta", "backend-architect · game-designer", VIOLET),
|
|
217
|
+
("Hooks", "Automatizacion invisible (eventos)", "valida commits · escanea secrets", GREEN),
|
|
218
|
+
("Rules", "Estandares que Claude obedece", "\"Clean architecture en backend\"", AMBER),
|
|
219
|
+
]
|
|
220
|
+
positions = [(0.78, 1.95), (6.93, 1.95), (0.78, 4.15), (6.93, 4.15)]
|
|
221
|
+
cw, ch = 5.6, 2.0
|
|
222
|
+
for (name, what, ex, col), (x, y) in zip(cards, positions):
|
|
223
|
+
rect(s, x, y, cw, ch, PANEL, radius=True)
|
|
224
|
+
rect(s, x, y, cw, 0.12, col)
|
|
225
|
+
txt(s, x + 0.3, y + 0.22, cw - 0.6, 0.5, [[(name, 23, col, True)]])
|
|
226
|
+
txt(s, x + 0.3, y + 0.82, cw - 0.6, 0.5, [[(what, 14, LIGHT, False)]])
|
|
227
|
+
txt(s, x + 0.3, y + 1.35, cw - 0.6, 0.5, [[(ex, 12, MUTED, True)]])
|
|
228
|
+
txt(s, 0.78, 6.45, 11.7, 0.5,
|
|
229
|
+
[[("Todo en Markdown + YAML: legible, diffeable en git, editable por cualquiera.", 14, WHITE, True)]])
|
|
230
|
+
|
|
231
|
+
# ================= SLIDE 7 — Anatomia de una skill =================
|
|
232
|
+
s = slide()
|
|
233
|
+
chrome(s, 7, "DEEP DIVE", "Anatomia de una skill")
|
|
234
|
+
# bloque de codigo
|
|
235
|
+
rect(s, 0.78, 1.95, 6.7, 4.55, CODEBG, radius=True, line=VIOLET, line_w=1.2)
|
|
236
|
+
txt(s, 1.0, 2.1, 6.3, 0.35, [[("skills/commit/SKILL.md", 11, MUTED, False)]], font=MONO)
|
|
237
|
+
code = [
|
|
238
|
+
[("---", 12.5, MUTED, False)],
|
|
239
|
+
[("name:", 12.5, PINK, True), (" commit", 12.5, LIGHT, False)],
|
|
240
|
+
[("description:", 12.5, PINK, True), (" \"Crea un commit", 12.5, GREEN, False)],
|
|
241
|
+
[(" siguiendo conventional commits...\"", 12.5, GREEN, False)],
|
|
242
|
+
[("category:", 12.5, PINK, True), (" workflow", 12.5, LIGHT, False)],
|
|
243
|
+
[("user-invocable:", 12.5, PINK, True), (" true", 12.5, AMBER, False)],
|
|
244
|
+
[("allowed-tools:", 12.5, PINK, True), (" Read, Bash", 12.5, LIGHT, False)],
|
|
245
|
+
[("model:", 12.5, PINK, True), (" haiku", 12.5, LIGHT, False), (" # opcional", 11, MUTED, False)],
|
|
246
|
+
[("---", 12.5, MUTED, False)],
|
|
247
|
+
[("", 6, MUTED, False)],
|
|
248
|
+
[("Review staged & unstaged changes", 12.5, CYAN, False)],
|
|
249
|
+
[("with git diff, suggest type/scope,", 12.5, CYAN, False)],
|
|
250
|
+
[("write a concise message...", 12.5, CYAN, False)],
|
|
251
|
+
]
|
|
252
|
+
txt(s, 1.0, 2.5, 6.3, 3.9, code, space_after=2, font=MONO)
|
|
253
|
+
# explicacion lado derecho
|
|
254
|
+
rect(s, 7.75, 1.95, 4.72, 4.55, PANEL, radius=True)
|
|
255
|
+
txt(s, 8.0, 2.15, 4.3, 0.4, [[("Dos partes:", 16, WHITE, True)]])
|
|
256
|
+
fields = [
|
|
257
|
+
("Frontmatter (YAML)", "Metadatos: nombre, tools permitidas, si es invocable, modelo a usar, agente asociado."),
|
|
258
|
+
("Cuerpo (Markdown)", "Las instrucciones en lenguaje natural que Claude sigue al invocar la skill."),
|
|
259
|
+
]
|
|
260
|
+
y = 2.7
|
|
261
|
+
for h, d in fields:
|
|
262
|
+
txt(s, 8.0, y, 4.3, 0.4, [[(h, 13.5, CYAN, True)]])
|
|
263
|
+
txt(s, 8.0, y + 0.38, 4.3, 0.9, [[(d, 12, LIGHT, False)]], line_spacing=1.05)
|
|
264
|
+
y += 1.5
|
|
265
|
+
txt(s, 8.0, 5.75, 4.3, 0.7,
|
|
266
|
+
[[("1 skill = 1 carpeta con un SKILL.md. Sin build, sin compilar.", 12.5, MUTED, True)]], line_spacing=1.05)
|
|
267
|
+
|
|
268
|
+
# ================= SLIDE 8 — Profiles =================
|
|
269
|
+
s = slide()
|
|
270
|
+
chrome(s, 8, "EL SISTEMA LEGO", "Profiles: combinar por stack")
|
|
271
|
+
txt(s, 0.78, 1.85, 11.7, 0.5,
|
|
272
|
+
[[("Cada profile es un YAML que agrupa skills, agentes, reglas y permisos. Se combinan con ", 13.5, LIGHT, False),
|
|
273
|
+
("+", 14, AMBER, True), (".", 13.5, LIGHT, False)]])
|
|
274
|
+
# bases
|
|
275
|
+
rect(s, 0.78, 2.5, 5.7, 3.0, PANEL, radius=True)
|
|
276
|
+
txt(s, 1.0, 2.65, 5.3, 0.4, [[("BASE (elegis uno)", 13, GREEN, True)]])
|
|
277
|
+
bases = [("unity-dev", "25"), ("backend-ts", "33"), ("backend-go", "19"),
|
|
278
|
+
("frontend", "14"), ("mobile", "12"), ("flutter / ios / android", "8")]
|
|
279
|
+
y = 3.15
|
|
280
|
+
for name, n in bases:
|
|
281
|
+
txt(s, 1.0, y, 4.2, 0.35, [[(name, 13, LIGHT, False)]])
|
|
282
|
+
txt(s, 5.3, y, 0.9, 0.35, [[(n, 13, CYAN, True)]], align=PP_ALIGN.RIGHT)
|
|
283
|
+
y += 0.37
|
|
284
|
+
# addons
|
|
285
|
+
rect(s, 6.63, 2.5, 5.85, 3.0, PANEL, radius=True)
|
|
286
|
+
txt(s, 6.85, 2.65, 5.4, 0.4, [[("ADDONS (combinas con +)", 13, AMBER, True)]])
|
|
287
|
+
addons = [("+agile", "10"), ("+testing", "11"), ("+infra", "17"),
|
|
288
|
+
("+security", "5"), ("+marketing", "44"), ("+clevel / +regulatory", "28 / 13")]
|
|
289
|
+
y = 3.15
|
|
290
|
+
for name, n in addons:
|
|
291
|
+
txt(s, 6.85, y, 4.4, 0.35, [[(name, 13, LIGHT, False)]])
|
|
292
|
+
txt(s, 11.3, y, 0.9, 0.35, [[(n, 13, CYAN, True)]], align=PP_ALIGN.RIGHT)
|
|
293
|
+
y += 0.37
|
|
294
|
+
rect(s, 0.78, 5.7, 11.7, 0.85, PANEL2, radius=True)
|
|
295
|
+
txt(s, 1.0, 5.78, 11.3, 0.7,
|
|
296
|
+
[[("+ core (siempre): 21 skills universales + 15 hooks + seguridad. ", 13, WHITE, True),
|
|
297
|
+
("Profiles combinados nunca duplican un skill.", 13, CYAN, True)]],
|
|
298
|
+
anchor=MSO_ANCHOR.MIDDLE, line_spacing=1.05)
|
|
299
|
+
|
|
300
|
+
# ================= SLIDE 9 — Mecanismos avanzados =================
|
|
301
|
+
s = slide()
|
|
302
|
+
chrome(s, 9, "PRODUCTION-GRADE", "Mecanismos que lo elevan")
|
|
303
|
+
feats = [
|
|
304
|
+
("Distribucion hibrida", "Resuelve el contenido en cadena: GitHub -> cache local -> bundled en npm. Funciona incluso sin conexion.", CYAN),
|
|
305
|
+
("Smart update (3-way merge)", "Compara base / tu version / upstream. Actualiza lo no tocado, preserva tus cambios, avisa conflictos.", VIOLET),
|
|
306
|
+
("Worktree-aware", "En git worktrees comparte hooks/ y docs/ (symlink), pero copia skills/ por rama (pueden divergir).", GREEN),
|
|
307
|
+
("Auto-release", "semantic-release lee los conventional commits: fix -> patch, feat -> minor. Publica a npm solo.", AMBER),
|
|
308
|
+
]
|
|
309
|
+
positions = [(0.78, 1.95), (6.93, 1.95), (0.78, 4.3), (6.93, 4.3)]
|
|
310
|
+
cw, ch = 5.6, 2.15
|
|
311
|
+
for (h, d, col), (x, y) in zip(feats, positions):
|
|
312
|
+
rect(s, x, y, cw, ch, PANEL, radius=True)
|
|
313
|
+
rect(s, x, y, 0.1, ch, col)
|
|
314
|
+
txt(s, x + 0.32, y + 0.22, cw - 0.6, 0.5, [[(h, 17, col, True)]])
|
|
315
|
+
txt(s, x + 0.32, y + 0.78, cw - 0.62, 1.2, [[(d, 12.5, LIGHT, False)]], line_spacing=1.1)
|
|
316
|
+
|
|
317
|
+
# ================= SLIDE 10 — Calidad / testing =================
|
|
318
|
+
s = slide()
|
|
319
|
+
chrome(s, 10, "CONFIABILIDAD", "Las skills se testean")
|
|
320
|
+
txt(s, 0.78, 1.9, 11.7, 0.5,
|
|
321
|
+
[[("322 prompts hay que mantenerlos con calidad. Arcane trae un framework de QA self-contained: ", 13.5, LIGHT, False),
|
|
322
|
+
("skills-selftest/", 13.5, CYAN, True)]])
|
|
323
|
+
cards = [
|
|
324
|
+
("/skill-test static", "Chequeo estructural: frontmatter valido, paths, tools declaradas.", GREEN),
|
|
325
|
+
("/skill-test spec", "Evaluacion de comportamiento contra casos de prueba esperados.", CYAN),
|
|
326
|
+
("/skill-test audit", "Reporte de cobertura: que skills tienen specs y cuales faltan.", VIOLET),
|
|
327
|
+
("/skill-improve", "Loop test -> diagnostica -> arregla -> re-testea -> mantiene o revierte.", AMBER),
|
|
328
|
+
]
|
|
329
|
+
y = 2.55
|
|
330
|
+
for h, d, col in cards:
|
|
331
|
+
rect(s, 0.78, y, 11.7, 0.85, PANEL, radius=True)
|
|
332
|
+
rect(s, 0.78, y, 0.1, 0.85, col)
|
|
333
|
+
txt(s, 1.05, y + 0.08, 3.6, 0.7, [[(h, 15, col, True)]], anchor=MSO_ANCHOR.MIDDLE, font=MONO)
|
|
334
|
+
txt(s, 4.9, y + 0.08, 7.4, 0.7, [[(d, 12.5, LIGHT, False)]], anchor=MSO_ANCHOR.MIDDLE)
|
|
335
|
+
y += 0.98
|
|
336
|
+
txt(s, 0.78, 6.5, 11.7, 0.4,
|
|
337
|
+
[[("catalog.yaml = registro maestro · quality-rubric.md = criterios pass/fail por categoria.", 12.5, MUTED, True)]])
|
|
338
|
+
|
|
339
|
+
# ================= SLIDE 11 — Por que gana =================
|
|
340
|
+
s = slide()
|
|
341
|
+
chrome(s, 11, "DIFERENCIADORES", "Por que Arcane gana")
|
|
342
|
+
rect(s, 0.78, 1.95, 5.7, 0.52, PANEL2, radius=True)
|
|
343
|
+
rect(s, 6.63, 1.95, 5.85, 0.52, PANEL2, radius=True)
|
|
344
|
+
txt(s, 1.0, 1.98, 5.3, 0.45, [[("ALTERNATIVA", 12.5, MUTED, True)]], anchor=MSO_ANCHOR.MIDDLE)
|
|
345
|
+
txt(s, 6.85, 1.98, 5.4, 0.45, [[("COMO GANA ARCANE", 12.5, CYAN, True)]], anchor=MSO_ANCHOR.MIDDLE)
|
|
346
|
+
rows = [
|
|
347
|
+
("Config a mano", "Un comando, versionado, reproducible"),
|
|
348
|
+
("Mega-repo monolitico", "Selectivo por profile + dedup (menos tokens)"),
|
|
349
|
+
("Copiar config entre proyectos", "Smart update con three-way merge"),
|
|
350
|
+
("Claude \"vanilla\"", "Hooks + rules + 86 agentes especializados"),
|
|
351
|
+
]
|
|
352
|
+
y = 2.58
|
|
353
|
+
for a, b in rows:
|
|
354
|
+
rect(s, 0.78, y, 5.7, 0.68, PANEL, radius=True)
|
|
355
|
+
rect(s, 6.63, y, 5.85, 0.68, PANEL, radius=True)
|
|
356
|
+
txt(s, 1.0, y + 0.04, 5.3, 0.6, [[(a, 13.5, LIGHT, False)]], anchor=MSO_ANCHOR.MIDDLE)
|
|
357
|
+
txt(s, 6.85, y + 0.04, 5.4, 0.6, [[(b, 13, WHITE, True)]], anchor=MSO_ANCHOR.MIDDLE)
|
|
358
|
+
y += 0.78
|
|
359
|
+
rect(s, 0.78, y + 0.05, 11.7, 0.68, VIOLET, radius=True)
|
|
360
|
+
txt(s, 0.78, y + 0.08, 11.7, 0.6,
|
|
361
|
+
[[("Configuracion de IA tratada como software: versionada, modular, testeable y distribuida.", 13.5, WHITE, True)]],
|
|
362
|
+
align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
|
|
363
|
+
|
|
364
|
+
# ================= SLIDE 12 — Trade-offs + cierre =================
|
|
365
|
+
s = slide()
|
|
366
|
+
chrome(s, 12, "BALANCE Y CIERRE", "Trade-offs honestos")
|
|
367
|
+
# pros
|
|
368
|
+
rect(s, 0.78, 1.95, 5.7, 3.05, PANEL, radius=True)
|
|
369
|
+
rect(s, 0.78, 1.95, 5.7, 0.55, RGBColor(0x14, 0x3D, 0x2E), radius=True)
|
|
370
|
+
txt(s, 1.02, 1.98, 5.3, 0.5, [[("FORTALEZAS", 14, GREEN, True)]], anchor=MSO_ANCHOR.MIDDLE)
|
|
371
|
+
pros = ["Eficiencia de tokens", "Un comando, cero friccion",
|
|
372
|
+
"Reproducible (manifest)", "Estandarizacion de equipo",
|
|
373
|
+
"Auto-update sin pisar cambios", "Testeable (skills-selftest)"]
|
|
374
|
+
y = 2.62
|
|
375
|
+
for p in pros:
|
|
376
|
+
txt(s, 1.02, y, 5.3, 0.4, [[("+ ", 13, GREEN, True), (p, 12.5, LIGHT, False)]])
|
|
377
|
+
y += 0.39
|
|
378
|
+
# contras
|
|
379
|
+
rect(s, 6.63, 1.95, 5.85, 3.05, PANEL, radius=True)
|
|
380
|
+
rect(s, 6.63, 1.95, 5.85, 0.55, RGBColor(0x4A, 0x39, 0x12), radius=True)
|
|
381
|
+
txt(s, 6.87, 1.98, 5.4, 0.5, [[("COSTOS", 14, AMBER, True)]], anchor=MSO_ANCHOR.MIDDLE)
|
|
382
|
+
cons = ["Mantener 322 skills con calidad", "Skills = prompts -> no deterministas",
|
|
383
|
+
"Depende de la API de Claude Code", "Curva: saber que profiles combinar"]
|
|
384
|
+
y = 2.62
|
|
385
|
+
for c in cons:
|
|
386
|
+
txt(s, 6.87, y, 5.5, 0.5, [[("! ", 13, AMBER, True), (c, 12.5, LIGHT, False)]])
|
|
387
|
+
y += 0.52
|
|
388
|
+
# CTA
|
|
389
|
+
rect(s, 0.78, 5.25, 11.7, 1.45, VIOLET, radius=True)
|
|
390
|
+
txt(s, 0.78, 5.4, 11.7, 0.5,
|
|
391
|
+
[[("Configuracion de IA, modular y versionada — un comando para empezar.", 17, WHITE, True)]],
|
|
392
|
+
align=PP_ALIGN.CENTER)
|
|
393
|
+
txt(s, 0.78, 5.95, 11.7, 0.5, [[("npx arcane install backend-ts+agile", 21, WHITE, True)]],
|
|
394
|
+
align=PP_ALIGN.CENTER, font=MONO)
|
|
395
|
+
|
|
396
|
+
out = os.path.join(os.path.dirname(os.path.abspath(__file__)), "arcane-overview-12.pptx")
|
|
397
|
+
prs.save(out)
|
|
398
|
+
print("OK ->", out)
|
|
399
|
+
print("Slides:", len(prs.slides._sldIdLst))
|