Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/issue-templates/good-first-issue-1.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
title: "Add a `glyph_render --watch` mode that re-renders on spec change"
labels: [good first issue, cli]
body: |
## Goal
Add a `--watch` flag to the `glyph render` CLI so a JSON spec edit triggers an
automatic re-render (with the existing byte-stable pipeline).

## Why
Tightens the agent ↔ human authoring loop. Pairs with the playground.

## Hints
- Entry point: `packages/cli/src/render.ts`
- Use `chokidar` (already a transitive dep) or `node:fs.watch`.
- Re-run the same `compileSpec` + `renderSvg` path; print the new SHA-256.

## Definition of done
- `glyph render spec.json --watch` re-renders on save.
- Test under `packages/cli/__tests__/watch.test.ts`.
20 changes: 20 additions & 0 deletions .github/issue-templates/good-first-issue-2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
title: "New audit rule: detect overlapping axis labels"
labels: [good first issue, auditor]
body: |
## Goal
Add an audit rule that flags overlapping x-axis or y-axis tick labels at the
rendered SVG layer.

## Why
Most agent-generated charts get the data right but pile labels on each other.
Catching this in the auditor lets agents fix it without a human in the loop.

## Hints
- Existing rules: `packages/core/src/audit/rules/`
- Compute label bounding boxes via the existing text-measure helper.
- Threshold: any horizontal overlap > 0 px on the major-axis ticks.

## Definition of done
- New rule file `axis-label-overlap.ts` with unit tests.
- Listed in `docs/AUDIT.md`.
- Bumped rule count in README ("11 → 12").
18 changes: 18 additions & 0 deletions .github/issue-templates/good-first-issue-3.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
title: "New brand preset: `theme: \"oss-newsletter\"`"
labels: [good first issue, theming]
body: |
## Goal
Add a fifth brand preset suited to OSS newsletters and dev.to thumbnails:
warm cream background, single-accent navy, mono-numeric axis labels.

## Why
Lowers the activation energy for community writeups.

## Hints
- Existing presets: `packages/core/src/brand/presets/`
- Mirror the `playground` preset structure.

## Definition of done
- New preset file + snapshot fixture under
`packages/core/__fixtures__/brand/oss-newsletter.svg`.
- Documented in `site/index.html#themes`.
18 changes: 18 additions & 0 deletions .github/issue-templates/good-first-issue-4.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
title: "Add Vega-Lite → Glyph translator quickstart in docs/LEARN.md"
labels: [good first issue, docs]
body: |
## Goal
Add a 200-word section to `docs/LEARN.md` that walks a reader through using
`vegaLiteToGlyph` to migrate a single Vega-Lite spec.

## Why
Lowers the migration barrier for data-viz folks already on Vega-Lite.

## Hints
- Translator lives in `packages/core/src/translate/vega-lite.ts`.
- Pick a small but interesting Vega-Lite example (e.g., interactive scatter)
and show the side-by-side spec + the resulting byte-stable SVG.

## Definition of done
- Section added near the end of `docs/LEARN.md`.
- Spec + rendered SVG checked into `packages/core/__fixtures__/translate/`.
20 changes: 20 additions & 0 deletions .github/issue-templates/good-first-issue-5.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
title: "Add LangChain `GlyphTool` to packages/integrations/langchain"
labels: [good first issue, integrations]
body: |
## Goal
Ship a one-file LangChain tool wrapper around `@glyph/mcp`, exposing
`glyph_render` and `glyph_audit_spec` as standard tools.

## Why
Makes Glyph one-line-usable from any LangChain agent.

## Hints
- Use `@langchain/core/tools` `tool` helper.
- Spawn `npx -y @glyph/mcp` as a subprocess; talk to it over stdio.
- Stub a small test that renders the existing `bar.json` fixture and asserts
the SHA-256 hash matches.

## Definition of done
- `packages/integrations/langchain/glyph_tool.py` (or `.ts`).
- Test that runs against the local MCP server.
- PR opened against the LangChain examples repo.
32 changes: 32 additions & 0 deletions .github/workflows/cowork-triage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Cowork triage

on:
issues:
types: [opened, reopened]
pull_request:
types: [opened, reopened, ready_for_review]

permissions:
issues: write
pull-requests: write
contents: read

jobs:
triage:
runs-on: ubuntu-latest
steps:
- name: Acknowledge
uses: actions/github-script@v7
with:
script: |
const isPR = !!context.payload.pull_request;
const num = (context.payload.issue || context.payload.pull_request).number;
const body = isPR
? "Thanks for the PR! Cowork (AI maintainer) is reviewing now. Routine PRs are typically merged within 24 hours; anything touching architecture or licensing will be tagged for a human review. See CONTRIBUTING.md → 'AI-maintained'."
: "Thanks for the issue! Cowork (AI maintainer) will triage within 24 hours. If it's a clear bug we'll label it 'confirmed' and propose a patch; if it's a feature request we'll label it 'rfc' and link related work.";
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: num,
body,
});
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,8 @@ sandbox/
# entries above only covered specific paths — this catches subdirs like
# bindings/python/tests/__pycache__/ that pytest creates per test file).
**/__pycache__/

# Launch toolkit secrets and runtime state
scripts/launch/.env.launch
scripts/launch/.influencer-*.json
scripts/launch/chrome_queue.json
44 changes: 44 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,50 @@ If you're here to **send code**, read on.

---

## AI-maintained

This repository is maintained by **Cowork** (an instance of Claude) on
behalf of the human owner. That means most of the day-to-day work — issue
triage, PR review, doc updates, dependency bumps, release notes,
launch-toolkit changes under `scripts/launch/` — is performed by an AI
agent on a schedule, not by a human watching a notifications inbox.

What that means for you as a contributor:

- **Acknowledgement within minutes.** When you open an issue or PR, the
[`cowork-triage`](./.github/workflows/cowork-triage.yml) workflow posts
an acknowledgement immediately. That comment is from Cowork, not a
human, and explains what happens next.
- **Triage within 24 hours.** Cowork labels the issue (`bug`, `rfc`,
`good first issue`, `needs-human`), proposes a patch path when it's
obvious, and links related work. If the issue is ambiguous, Cowork
asks a single clarifying question rather than guessing.
- **Routine PRs reviewed automatically.** PRs that touch only tests,
docs, fixtures, or a single isolated module are reviewed by Cowork
against the existing style guide and CI signal. Determinism-breaking
changes (byte-stable output, SHA-256 seal, audit-rule semantics,
spec schema) are always tagged `needs-human` and held for the
human owner.
- **Humans tagged for the things that need them.** Anything involving
licensing, security, architecture, or external trust is escalated to
the human owner via the `needs-human` label. Cowork will not merge
PRs with that label.
- **Everything is auditable.** Cowork's comments are signed with
`— Cowork (AI maintainer)`. The launch toolkit logs every action it
takes (PRs opened, emails sent, posts published) under
`scripts/launch/.influencer-emails.json` and similar files so the
human owner can audit at any time.
- **You can always ask for a human.** Reply to any Cowork comment with
`@human` and the issue/PR is re-tagged `needs-human` and held for
the owner.

If you're allergic to AI-maintained software, this isn't the project
for you, and that's fine — Glyph being AI-maintained is part of its
thesis. If you find the experiment interesting, contributions are very
welcome.

---

## Tl;dr

```bash
Expand Down
58 changes: 58 additions & 0 deletions scripts/launch/.env.launch.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Glyph launch toolkit — copy to .env.launch and fill in.
# This file MUST NOT be committed. Add .env.launch to your repo's .gitignore.

# ---- GitHub ----
# Personal access token with: repo, workflow, write:packages
# https://github.com/settings/tokens
GITHUB_TOKEN=

# Repo slug — change if you fork
REPO_SLUG=seanhanca/glyph

# ---- Blogging platforms ----
# dev.to: https://dev.to/settings/extensions
DEVTO_API_KEY=

# Hashnode: https://hashnode.com/settings/developer
HASHNODE_TOKEN=
HASHNODE_PUBLICATION_ID=

# Medium: https://medium.com/me/settings (Integration tokens)
MEDIUM_TOKEN=
MEDIUM_USER_ID=

# ---- Discord webhooks ----
# Right-click channel → Integrations → Webhooks → Copy URL
DISCORD_WEBHOOK_ANTHROPIC=
DISCORD_WEBHOOK_MCP=
DISCORD_WEBHOOK_LANGCHAIN=
DISCORD_WEBHOOK_CREWAI=
DISCORD_WEBHOOK_DUCKDB=
DISCORD_WEBHOOK_AIENGINEER=
DISCORD_WEBHOOK_LLAMAINDEX=

# ---- Bluesky / Mastodon ----
BLUESKY_HANDLE=
BLUESKY_APP_PASSWORD=
MASTODON_INSTANCE=https://fosstodon.org
MASTODON_TOKEN=

# ---- Product Hunt ----
PRODUCTHUNT_TOKEN=

# ---- Resend (newsletter pitches + cold emails) ----
RESEND_API_KEY=
RESEND_FROM=launch@yourdomain.tld

# ---- LLM for the influencer engine (drafting replies) ----
ANTHROPIC_API_KEY=
# or
OPENAI_API_KEY=

# ---- YouTube (for shorts upload) ----
YOUTUBE_OAUTH_CLIENT_JSON=./scripts/launch/.youtube-oauth.json

# ---- Behavior knobs ----
DRY_RUN=true # default true; flip to false when you're ready to actually post
COLD_EMAIL_DAILY_CAP=3
INFLUENCER_POLL_INTERVAL_HOURS=24
Loading
Loading