Skip to content

[N11b] githubChannel(): the agent answers issue and pull-request comments - #306

Merged
LinuxDevil merged 2 commits into
mainfrom
lou-n11b-github-channel
Oct 2, 2026
Merged

LinuxDevil merged 2 commits into
mainfrom
lou-n11b-github-channel

Conversation

@LinuxDevil

Copy link
Copy Markdown
Owner

N11b: githubChannel()

githubChannel({ webhookSecret, botName, token? | app?, botLogin?, name?, apiUrl?, fetch?, triggers?, approvers?, onError? }): @<botName> in an issue, pull-request or review comment starts a turn and the agent answers in the same thread. Built on defineChannel() like the Slack, Discord and Telegram channels (src/channels/githubChannel.ts; App authentication in src/channels/githubAppAuth.ts, not exported from the root). No node:* import in either file.

  • X-Hub-Signature-256 is verified over the raw body with crypto.subtle.verify (constant time) before the body is parsed; missing or wrong is 401.
  • Sessions: one per issue or pull request, one per review thread; later comments in a thread that has a session are follow-ups; ping, edits, deletions, other events, bots, <botName>[bot], botLogin and any comment the channel posted (a hidden marker) are ignored, so there is no loop even when a personal access token posts as a normal user.
  • Replies are comments (a reply under the thread for review comments), split at 60,000 characters; errors name the call and status only.
  • Approvals: /approve <id> / /deny <id> on the first line (note below it). Default approvers: author_association OWNER, MEMBER or COLLABORATOR, read from the command comment itself; approvers (logins or function) overrides it. A decision is accepted once per id; an id from another thread is ignored; a refusal is only posted for an approval this process knows, so a made-up id gets no reply.
  • triggers (not in the ticket, asked for in the task): who may start a turn or answer a question; default everyone who can comment (the ticket's behavior), documented as untrusted input with a recommendation to restrict it on public repositories.
  • ask_question: answered by the next comment in the thread; survives a restart given durable stores (M10a pattern, ctx.pendingQuestion).

Docs for the docs site

  • docs/channels.md: new ## GitHub section appended after ## Telegram (no ### headings; the Arabic channels page needs it), and one new row in the existing ## Built-in channels table.
  • Edited sentences only: docs/agent-directories.md (channel list), docs/errors.md (LOUSHO_CHANNEL_INVALID fix line, LOUSHO_CHANNEL_REQUEST_FAILED means/example), CHANGELOG.md, llms.txt / llms-full.txt.
  • No new page and no heading added to an existing page except ## GitHub.

Acceptance criteria

  • githubChannel.ts and githubAppAuth.ts exist, githubChannel exported from the package root (checked in dist), no node:* import.
  • githubChannel.test.ts (49 tests, mountChannels() with a fake GitHub REST API): signatures, ping, issue and pull-request comments, review threads as two sessions, follow-ups, ignored events, 130,000 characters as 3 comments, approval prompt, /approve by MEMBER, refusal for NONE, approvers list and function, /deny with a note, restart on a second instance over the same stores, replay of an old /approve, ask_question (also across a restart), failed post to onError without the token.
  • githubAppAuth.test.ts (9 tests): key pair generated in the test (PKCS#1 and PKCS#8 PEM) signs a JWT the test verifies; installation token fetched once and reused until 5 minutes before expiry.
  • Docs, CHANGELOG, npm run docs:llms, snippet check.
  • This description says the docs site needs the new ## GitHub section in the Arabic channels page.
  • Live test: not recorded (see below).

Not verified

  • Live model turn: src/channels/githubChannel.live.test.ts is written and skips without a cassette (and is excluded from the default run, like the Telegram one). The OpenRouter account is out of credit (total_credits 10, total_usage 10.199...), so no cassette was recorded; a checklist line is on [LIVE] Run the deferred live-model tests once OpenRouter credit is added #260. Live test spend: none (balance checked once, no model call made).
  • No call to the real GitHub API (the ticket asks for a fake): the exact App flow (JWT accepted by GitHub, installation.id in the payload) is verified against GitHub's documentation only.

Verification (on the branch after merging origin/main at 401900c)

  • npx tsc --noEmit: ok. npm run lint: 0 warnings.
  • npm run build, npm run build --workspace=packages/create-lousho-agent: ok.
  • npm run test:types: 65 passed, no type errors.
  • npm run docs:verify-snippets -- --skip-build: 213 snippets type-check, 8 run. npm run docs:llms:check: ok.
  • Full suite with coverage: 235 files passed, 1 skipped; 3448 tests passed, 6 skipped. (One earlier run had a timing failure in src/tools/built-in/http.test.ts under machine load; it passes alone and in the second full run.)
  • npm run fallow: 0 above threshold (maintainability 89.7). Its first run flagged readEvent (cyclomatic 26); split into small helpers.
  • Agent Forge: typecheck ok, typecheck:server ok, 119 client tests passed, 130 server tests passed.
  • npm run pack-smoke: all checks passed (esm and cjs 16/16 entries).

Other

  • Not in scope, noticed: docs/channels.md line 203 contains a stray r (from the Telegram change, [N11a] telegramChannel(): Telegram bot webhooks, inline-keyboard approvals #302), and the Telegram CHANGELOG entry appears in three ### Added blocks with & where / was meant. Left alone.
  • A comment on the issue by aetherxeg-source (association NONE) asked for the approver rule's time-of-check to be explicit. It is inside the written scope (the default-approver rule), and I checked it against the code: the association is read from the command comment's webhook, so a removed collaborator is refused (test added). The docs say it is a snapshot at the command, and point to a function approvers for a live permission check.

Closes #252

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[N11b] Add githubChannel(): the agent answers issue and pull-request comments

1 participant