Skip to content

giltine/cc-hackaton

Repository files navigation

cc-hackaton

A hackathon fork of giltine/cc exploring a typed-chat surface inside the cc app.

This experiment replaces the Claude.ai workflow for planning and triaging giltine-stack work with first-class chats backed by Convex. Each chat has a type (planning, general) that determines which docs are injected into the system prompt, which MCP tools the agent gets, and whether the agent can propose vairas batchRuns. Round-trips run through stampas on the same batchRuns queue the rest of the workflow uses. The chat itself becomes the planning and triage surface — no external Claude.ai project required.

For the broader autonomous workflow this plugs into, see giltine/cc/docs/claude.ai/autonomous-workflow-spec.md.

What's inside

The typed-chat architecture landed across nine PRs between 2026-05-02 and 2026-05-03. Here's what exists today:

Schema (convex/schema.ts): Four new tables power the chat surface:

  • chatTypes — defines chat types with their system prompt templates, default docs to inject, MCP servers, and whether they can spawn agents
  • chats — individual chat instances, each linked to a chatType, with session state, runner preference, and message metadata
  • messages — Anthropic-shaped content blocks (text, tool_use, tool_result) plus token counts and status tracking
  • injectedDocs — cached doc content fetched from Forgejo, keyed by (repoSlug, path, ref) with content hashing so re-fetches are no-ops when the file hasn't changed

The existing batchRuns table was extended with runner (claude|bob), spawnedFromChatId, the "chat_message" kind, and chatId/messageId params for chat-dispatched runs.

A new batchProposals table implements the propose-then-approve flow: when the planning agent identifies a batch worth running, it emits a PROPOSE_BATCH_START … PROPOSE_BATCH_END JSON block. Stampas parses it into a batchProposals row; the chat UI renders a ProposalCard next to the message; the user clicks approve to enqueue the actual kind: "run" batchRun. The agent never spawns directly — every batch goes through human approval.

Seeds (convex/chats/seed.ts): Two chat types ship out of the box:

  • planning — compass icon, can spawn agents, injects the giltine workflow docs (autonomous-workflow-spec.md, issue-process-giltine.md, giltine-project-context.md), emits PROPOSE_BATCH markers when it identifies a coherent batch
  • general — message-square icon, open-ended, no injected docs, no agent spawning

Run bunx convex run chats/seed:seedChatTypes to populate or update them.

Doc fetcher: A Convex action pulls doc files from Forgejo and caches them in injectedDocs keyed by (repoSlug, path, ref). Content hashing ensures re-fetches are no-ops when the file hasn't changed. The system prompt assembly logic reads from this cache and injects the docs into the agent's context.

Chat dispatch: The chat composer calls chats.send, which inserts a user message and enqueues a kind: "chat_message" batchRun. Stampas claims it, GETs /api/stampas/chats/dispatch?chatId=... to fetch the assembled system prompt + latest user message, runs the agent (default runner: bob), and POSTs the assistant message back to /api/stampas/chats/assistant-message. Both endpoints are gated by X-CC-Secret matching STAMPAS_API_SECRET.

Propose-then-approve: When the planning agent identifies a batch worth running, it emits a PROPOSE_BATCH_START … PROPOSE_BATCH_END JSON block. Stampas parses it into a batchProposals row; the chat UI renders a ProposalCard next to the message; the user clicks approve to enqueue the actual kind: "run" batchRun. The agent never spawns directly — every batch goes through human approval.

UI: Chat list page (app/in/chats/page.tsx) + new-chat dialog wired into the sidebar, plus ChatDetailClient (lib/components/chats/ChatDetailClient.tsx) rendering the message stream and the proposal cards inline. The ProposalCard component (lib/components/chats/ProposalCard.tsx) displays the batch title, rationale, and approve/reject buttons.

Recently shipped

  • #8 — Schema additions for typed conversations + chatTypes seed
  • #12 — Forgejo doc fetcher action + injectedDocs cache + system prompt assembly
  • #18 — Chat list page, new chat dialog, sidebar entry, ChatDetailClient
  • #32 — Fix chats/dispatch to read chatId from POST body
  • #34chatsGetDispatch includes chatTypeSlug in dispatch response
  • #39batchProposals table + queries/mutations
  • #46ProposalCard component + ChatDetailClient integration
  • #49 — Append PROPOSE_BATCH instructions to the seeded planning prompt
  • #54 — Cosmetic fixes + http endpoint adjustments

Forgejo integration

Org-scoped actions (listOrgRepos, listOpenIssues, reconcileOrg, etc.) gate access through assertOrgMember, which resolves the caller's Forgejo username from their session email via /api/v1/users/search.

FORGEJO_TOKEN must be an admin-scoped (site admin) token. Forgejo only includes user email fields in the search response when the requester is a site admin. A non-admin token returns results without emails, email-based user resolution always fails, and every org-gated action returns NOT_ORG_MEMBER — effectively locking out the entire user base.

To create the token:

  1. Sign in to Forgejo as a site admin.
  2. Go to Settings → Applications → Generate New Token.
  3. Grant the token the scopes needed to read users, orgs, repos, issues, and pull requests (at minimum read:admin, read:user, read:organization, read:repository, read:issue).
  4. Set it on the Convex deployment: bunx convex env set FORGEJO_TOKEN=<token>.

If you see NOT_ORG_MEMBER for users you expect to have access, check the Convex logs for the one-shot warning emitted by fetchForgejoUsernameByEmail — it surfaces a mis-scoped token.

Hackathon evaluation: bob runner artifacts

The bob/ folder contains artifacts from bob, the alternative agent runner used by stampas for chat dispatch (default runner for new chats — see runner: "bob" in the dispatch flow).

  • bob/custom_modes.yaml — the custom modes bob runs against the giltine pipeline (giltine-reviewer, giltine-triager, planner modes, etc.). These define role definitions, tool groups, and per-mode instructions used by the autonomous workflow.
  • bob/tmp/<session-hash>/chats/session-*.json — raw chat session transcripts captured while bob was driving the typed-chat surface end-to-end. Useful for inspecting how the agent handled real planning rounds, tool calls, and PROPOSE_BATCH emissions.

These are checked in for hackathon reviewers and are not consumed by the running app.

Running it

Standard cycle:

  1. bun install
  2. bunx convex dev (and bunx convex env set FORGEJO_TOKEN=… per the section above)
  3. bunx convex run chats/seed:seedChatTypes to populate the two chat types
  4. bun run dev for the Next.js front

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages