diff --git a/.github/_render_social_preview.py b/.github/_render_social_preview.py new file mode 100644 index 0000000..deb3a3e --- /dev/null +++ b/.github/_render_social_preview.py @@ -0,0 +1,207 @@ +"""Render the GitHub social-preview image for instinct. + +Movement: Mnemonic Cartography. +Output: 1280x640 PNG to D:/dev/instinct/.github/social-preview.png +""" +from __future__ import annotations + +from pathlib import Path +from PIL import Image, ImageDraw, ImageFont + +# ---- Geometry -------------------------------------------------------------- +W, H = 1280, 640 +MARGIN = 64 + +# ---- Palette (Mnemonic Cartography) --------------------------------------- +INK = (10, 14, 20) # near-black ocean +PAPER = (228, 224, 214) # weathered chart paper +PAPER_DIM = (158, 154, 144) # field-note ink, half-strength +HAIRLINE = (60, 66, 76) # grid substrate +ACCENT = (214, 158, 46) # marker-buoy amber — single accent +ACCENT_DIM = (130, 96, 28) # accent shadow on dim chips + +# ---- Fonts ----------------------------------------------------------------- +FONT_DIR = Path( + r"C:/Users/lenovo/AppData/Roaming/Claude/local-agent-mode-sessions/skills-plugin" + r"/30baa525-858e-447e-844e-85425ba98a2d" + r"/f8d43373-1929-4517-a905-02da865582fd" + r"/skills/canvas-design/canvas-fonts" +) +F_MONO_BOLD = FONT_DIR / "GeistMono-Bold.ttf" +F_MONO_REG = FONT_DIR / "GeistMono-Regular.ttf" +F_MONO_ALT = FONT_DIR / "IBMPlexMono-Regular.ttf" + + +def font(path: Path, size: int) -> ImageFont.FreeTypeFont: + return ImageFont.truetype(str(path), size=size) + + +def draw_grid(d: ImageDraw.ImageDraw) -> None: + """A faint cartographer's grid — substrate, never feature.""" + step = 32 + for x in range(0, W + 1, step): + d.line([(x, 0), (x, H)], fill=HAIRLINE, width=1) + for y in range(0, H + 1, step): + d.line([(0, y), (W, y)], fill=HAIRLINE, width=1) + # Stronger latitudes at every 4th line — survey-style + strong = (74, 80, 90) + for x in range(0, W + 1, step * 4): + d.line([(x, 0), (x, H)], fill=strong, width=1) + for y in range(0, H + 1, step * 4): + d.line([(0, y), (W, y)], fill=strong, width=1) + + +def draw_corner_register(d: ImageDraw.ImageDraw) -> None: + """Tiny clinical reference marker — top-left corner.""" + f = font(F_MONO_REG, 14) + label = "CARTE Nº 01.04.00" + d.text((MARGIN, MARGIN - 32), label, font=f, fill=PAPER_DIM) + # short tick under the label + tx = MARGIN + d.line([(tx, MARGIN - 10), (tx + 96, MARGIN - 10)], fill=PAPER_DIM, width=1) + + +def text_size(d: ImageDraw.ImageDraw, txt: str, f: ImageFont.FreeTypeFont) -> tuple[int, int]: + bbox = d.textbbox((0, 0), txt, font=f) + return bbox[2] - bbox[0], bbox[3] - bbox[1] + + +def draw_wordmark(d: ImageDraw.ImageDraw) -> int: + """Monumental 'instinct' — single inscription on the chord of the composition. + + Uses font ascent metric to find the true visual bottom (avoids the + misleading textbbox vertical, which clips above descenders). + """ + f = font(F_MONO_BOLD, 152) + txt = "instinct" + tw, _ = text_size(d, txt, f) + x = (W - tw) // 2 + y = 152 + d.text((x, y), txt, font=f, fill=PAPER) + + ascent, descent = f.getmetrics() + visual_bottom = y + ascent + descent + return visual_bottom + + +def draw_tagline(d: ImageDraw.ImageDraw, baseline_y: int) -> int: + f = font(F_MONO_REG, 22) + txt = "self-learning memory for ai coding agents" + tw, _ = text_size(d, txt, f) + x = (W - tw) // 2 + y = baseline_y + 18 + d.text((x, y), txt, font=f, fill=PAPER_DIM) + return y + 28 + + +def draw_transect(d: ImageDraw.ImageDraw, top_y: int) -> None: + """A horizontal survey transect — observe / track / promote / suggest. + + Four pins connected by hairline rules with arrowheads. Only the final + arrow uses the accent; only the final pin is filled. + """ + stages = [ + ("observe", "+1"), + ("track", "n+1"), + ("promote", "≥5"), + ("suggest", "≥10"), + ] + n = len(stages) + transect_top = top_y + 36 + + # Lay pins on a single latitude + inner_w = W - 2 * MARGIN - 80 # extra inset + pin_radius = 9 + pin_y = transect_top + 14 + pin_xs = [MARGIN + 40 + round(inner_w * i / (n - 1)) for i in range(n)] + + f_label = font(F_MONO_BOLD, 24) + f_field = font(F_MONO_REG, 14) + + # Hairline between pins + for i in range(n - 1): + x1, x2 = pin_xs[i] + pin_radius + 4, pin_xs[i + 1] - pin_radius - 4 + is_final = i == n - 2 + color = ACCENT if is_final else PAPER_DIM + d.line([(x1, pin_y), (x2, pin_y)], fill=color, width=1) + # arrowhead + ah = 5 + d.line([(x2, pin_y), (x2 - ah, pin_y - ah)], fill=color, width=1) + d.line([(x2, pin_y), (x2 - ah, pin_y + ah)], fill=color, width=1) + + # Pins + for i, ((label, field), px) in enumerate(zip(stages, pin_xs)): + is_final = i == n - 1 + if is_final: + d.ellipse( + [(px - pin_radius, pin_y - pin_radius), + (px + pin_radius, pin_y + pin_radius)], + fill=ACCENT, outline=ACCENT, width=1, + ) + else: + d.ellipse( + [(px - pin_radius, pin_y - pin_radius), + (px + pin_radius, pin_y + pin_radius)], + fill=INK, outline=PAPER_DIM, width=1, + ) + # tiny inner dot + inner = 2 + d.ellipse( + [(px - inner, pin_y - inner), (px + inner, pin_y + inner)], + fill=PAPER_DIM, + ) + + # Label below the pin — bold mono + lw, _ = text_size(d, label, f_label) + lx = px - lw // 2 + ly = pin_y + pin_radius + 22 + label_color = ACCENT if is_final else PAPER + d.text((lx, ly), label, font=f_label, fill=label_color) + + # Field note further below — clinical, dim, generous breathing + fw, _ = text_size(d, field, f_field) + fx = px - fw // 2 + fy = ly + 38 + d.text((fx, fy), field, font=f_field, fill=PAPER_DIM) + + +def draw_footer(d: ImageDraw.ImageDraw) -> None: + """Bottom edge: clinical references at the smallest defensible scale.""" + f = font(F_MONO_REG, 14) + + # Bottom-left: license + protocol + left = "MIT · MCP · PYTHON ≥ 3.11 · SQLITE · LOCAL-FIRST" + lw, lh = text_size(d, left, f) + d.text((MARGIN, H - MARGIN - lh + 4), left, font=f, fill=PAPER_DIM) + + # Bottom-right: handle + repo + right = "github.com/yakuphanycl/instinct" + rw, rh = text_size(d, right, f) + d.text((W - MARGIN - rw, H - MARGIN - rh + 4), right, font=f, fill=PAPER) + + # short tick above the right handle — survey-pin shorthand + tick_y = H - MARGIN - rh - 6 + d.line( + [(W - MARGIN - rw, tick_y), (W - MARGIN, tick_y)], + fill=PAPER_DIM, width=1, + ) + + +def render() -> None: + img = Image.new("RGB", (W, H), INK) + d = ImageDraw.Draw(img) + + draw_grid(d) + draw_corner_register(d) + rule_y = draw_wordmark(d) + tagline_bottom = draw_tagline(d, rule_y) + draw_transect(d, tagline_bottom) + draw_footer(d) + + out = Path(__file__).parent / "social-preview.png" + img.save(out, format="PNG", optimize=True) + print(f"wrote {out} ({out.stat().st_size:,} bytes)") + + +if __name__ == "__main__": + render() diff --git a/.github/design-philosophy.md b/.github/design-philosophy.md new file mode 100644 index 0000000..7bbb52f --- /dev/null +++ b/.github/design-philosophy.md @@ -0,0 +1,31 @@ +# Mnemonic Cartography + +## Manifesto + +A movement of disciplined remembrance. The visual language of a surveyor mapping unmappable terrain — the topology of repetition, the geology of pattern. Where ordinary cartography fixes a coast in space, **Mnemonic Cartography** fixes the moment a fleeting habit becomes a known landmark. The work is meticulously crafted, the product of deep expertise: every coordinate placed with the painstaking attention of someone who has spent years learning when *not* to draw. + +The aesthetic is forensic, monumental, hushed. A field-notebook from an imaginary discipline that studies cognition the way a hydrographer studies tides. Nothing romantic. Nothing decorative. The reverence is in the precision — the master-level execution of restraint. A reader who lingers feels the labor: the dozens of micro-adjustments to a tick mark, the calibration of a single stroke against the rule of negative space. + +## Spatial language + +Space is the primary instrument. Vast tracts of dark, deep, oceanic ground — undisturbed except by the single architectural gesture that anchors the eye. Information is arranged on imagined latitudes: a horizon line, a baseline, a meridian. Every element earns its longitude. Crowding is heresy. Composition leans on Swiss formalism but speaks with the gravity of an Admiralty chart. + +## Form and material + +Geometry is austere, drawn as if etched. Thin rules at hairline weight; small filled dots that read like survey-pins; rectangles whose edges are neither bevelled nor decorated. The aesthetic refuses ornament because ornament is an apology. Where typography appears, it is the work of countless refinements: a single weight, a single family, a single rhythm. Letters sit on their baseline as instruments sit on their bench — placed, not arranged. + +## Color + +A palette of patient calibration: a dark substrate (deep ink, near-black), a single chromatic accent that behaves like a found object — a marker buoy, a beacon — and the off-white of weathered paper for marks. Color does not decorate; it locates. The accent is reserved for the one element that *moves*: a single arrow, a single chip, a single index pin. Master-level restraint means no second accent, ever. + +## Rhythm and scale + +Two scales coexist: a monumental one, where a wordmark or a single line of text occupies the chord of the composition like a found inscription; and a clinical one, where the field notes — measurements, captions, references — whisper at the bottom of the frame in the smallest defensible size. The contrast between the two is the entire emotional content. Nothing in between. Nothing transitional. The piece breathes through this gap. + +## Hierarchy + +Information lives in the diagram, not in sentences. Sequence is shown by the relative length of journey between points; significance by the weight of the survey-pin. A reader who knows how to read a chart will read this; a reader who does not will still feel the discipline of the drawing. That dual legibility — to the practitioner an artifact of method, to the layperson a quiet field of marks — is the goal. Painstaking attention to this dual register is what separates a master's chart from a draftsman's exercise. + +## Final note on craftsmanship + +This is not graphic design. This is the slow, museum-grade work of a cartographer who has learned that the most powerful map is the one that proves something invisible can be located. Every alignment, every kerning, every margin is the residue of countless decisions. The piece must look as though it took hundreds of hours of patient labor by someone at the absolute peak of their craft — and it must look that way at thumbnail scale, at full scale, and held at arm's length. Anything less is unworthy of the discipline. diff --git a/.github/social-preview.png b/.github/social-preview.png new file mode 100644 index 0000000..8d1a76c Binary files /dev/null and b/.github/social-preview.png differ