Docs/Documentation
Docs/GitHub Commit-Sync Guide
🔀

GitHub Commit-Sync Guide

Drive tasks from commit messages — create, add subtasks, and close, all without touching GitHub Issues.

What it does

A project can bind one or more GitHub repos. A background poller reads new commits on each bound repo's default branch and parses commit messages for a task-command tag.

📡
This is polling, not a webhook. There's nothing to register on GitHub's side — the worker checks each active binding on its own schedule (1–1440 min, configurable per binding). Near-real-time, not instant.

Commit Message Patterns

Case-insensitive. taskKey is 2-40 alphanumeric characters (no hyphens) — reuse it across commits to keep referring to the same task.

1

Create — new task + first subtask

[Create-t8] Task Name - Subtask Name
[Create-t8-reqId] Task Name - Subtask Name          (optional Requirement link)
[Create-t8] Task Name - Subtask Name | start=2026-08-10 end=2026-08-20 mh=5

The - between Task Name and Subtask Name is required — a commit with no separator is silently ignored (no task, no error). The trailing | start= end= mh= segment is optional and sets startAt/endAt/estimatedManHour on creation. A malformed field (bad date, non-numeric mh, unrecognized key) is dropped individually — it never fails the task/subtask creation.

2

Add — append a finished subtask

[Add-t8] Subtask Name

Adds a subtask to an existing task, created already DONE — this pattern means “log work that's already finished,” not “add a TODO.”

3

Close — mark a subtask done

[Close-t8] Subtask Name

Matches an existing subtask under that task by title (case-insensitive) and marks it DONE — creates it pre-closed if no subtask with that title exists yet. Once every subtask under the task is DONE, the task itself cascades to DONE automatically.

⚠️
Add/Close referencing a taskKey with no matching task are silently skipped (logged as a worker warning, nothing surfaces in the UI). Double-check the Create commit actually landed first if a follow-up seems to have done nothing. And a repo that was never bound to a project is never polled at all — no binding means no automatic task creation, ever, by construction.

Manual Task Creation with a Commit Key

A task created by hand (not from a commit) can also be given a taskKey, via the “Task Key for GitHub commits” field on the New Task form — same 2-40 alphanumeric format, validated and lowercased the same way.

This makes it addressable by future [Add-key]/[Close-key] commits the same way a commit-created task already is. Leave it blank if the task never needs to be touched from a commit — it's entirely optional.

🔑
Keys are unique per project. Reusing a key that's already taken returns a clear 409 error rather than silently overwriting the existing task.

Setup (Org Owner only)

1

Open the GitHub tab

Go to a project → GitHub tab → Bind Repo.

2

Enter repo and token

Repo in owner/repo form. Personal Access Token needs Contents: Read-only (fine-grained, scoped to just that repo) or the classic repo scope for private repos.

3

Save

The token is validated against the GitHub API immediately — a bad token or inaccessible repo fails fast instead of silently creating a dead binding. It's encrypted at rest and never shown again after this point.

👑
Only an Org Owner (or a custom role explicitly granted infra.github.manage) can bind/rebind/delete a repo, change its sync interval, or trigger a manual sync. Writing correctly-tagged commits doesn't require this permission — every project member can see this guide and the commit patterns above.

Optional: GitHub OAuth Account Linking

A user's githubUsername (shown in commit attribution) can be set two ways:

  • Typed free-text in Profile — unverified, display-only.
  • “Connect GitHub” button in Profile — a real OAuth flow that marks it verified.

Both are optional and independent of repo binding — this is about who a commit's author resolves to, not which repos sync.