Skip to content

theCodeForgerHQ/Gappy

Repository files navigation

Grappy

A governed, auditable, human-gated bug-fix workflow for Python maintainers

Built as a Lemma pod and Vite/React Lemma App for the Gappy AI Hackathon, "Ship to Get Hired".

platform backend frontend scope trust

Coding agents can already write patches. The maintainer's harder question is: can I trust this patch enough to let it enter my repository?

Grappy makes that trust layer the product. It reproduces a bug with a real failing pytest run before writing code, fixes against that maintainer-approved oracle, records every step as an append-only audit log, asks a Lemma Agent reviewer for a second opinion, pauses for human approval, and only then opens a pull request whose body is the evidence trail.

The coding loop is useful. The audit is the moat.


Table Of Contents

  1. What Grappy Solves
  2. The Product
  3. Architecture
  4. One Change Run
  5. Lemma SDK Usage
  6. Repository Structure
  7. Backend Pod
  8. Frontend App
  9. Data Model
  10. Functions
  11. Workflow And Agent
  12. Trust, Safety, And Verification
  13. GitHub Connector
  14. Observability And Replay
  15. Development
  16. Deployment
  17. Demo Script
  18. Design Decisions
  19. Roadmap

What Grappy Solves

Solo and small-team Python maintainers can already ask an AI coding agent to produce a patch. That is no longer the scarce part.

The remaining bottleneck is trust:

  • Did the agent reproduce the bug before it changed code?
  • Was the failing test supplied or approved by a maintainer?
  • Did the agent localize the fault from real execution evidence?
  • Did the patch actually flip the failing test from RED to GREEN?
  • Did nearby regression tests stay green?
  • Is there enough evidence for a reviewer to understand the change?
  • Who approved the automation before it opened a pull request?
  • Can the run be inspected later without asking the model to explain itself?

Grappy chooses a narrow problem statement on purpose:

Enable a maintainer to safely delegate the repair of a known Python bug while preserving trust, auditability, and human control throughout the workflow.

The goal is not fully autonomous software development. The goal is a repair workflow where every AI-generated change is reproducible, inspectable, independently validated, and explicitly approved before becoming a pull request.

The One User

Field Choice
User Solo or small-team maintainer of a Python repository
Repository shape Python project with pytest
Starting input Repo context, issue description, and a failing pytest target or built-in demo
Unit of work One repo, one bug, one governed change_run
Human role Owns the merge decision and must approve before PR creation
Non-goal Autonomous merge or broad multi-language repair

The Core Trust Contract

Grappy is designed around one acceptance rule:

The agent may write the patch, but it does not get to write the truth it is trying to satisfy.

The truth is the failing test. For real runs, that test comes from the maintainer or a maintainer-approved source. For the built-in demo, the repository carries a known seed bug and test. Grappy's job is to move that independent oracle from RED to GREEN, not to manufacture its own definition of success.


The Product

Grappy is a governed bug-fix workflow built as:

The maintainer picks a repository, describes the bug, optionally provides a failing test and target file, and starts a run. Grappy then:

  1. Creates a change_runs row.
  2. Runs the unpatched code in a clean workspace with pytest.
  3. Requires a real non-zero exit code before patching.
  4. Localizes the likely fault using indexed repo symbols and traceback output.
  5. Drafts a plan and records it.
  6. Asks the model for a minimal SEARCH/REPLACE patch.
  7. Applies the patch deterministically.
  8. Runs pytest again.
  9. Retries under cost, wall-clock, stuck, and circuit-breaker caps.
  10. Marks the run needs_approval only after RED->GREEN proof.
  11. Invokes a Lemma Agent reviewer for an independent second opinion.
  12. Pauses at a human approval form.
  13. Opens a PR only after approval.
  14. Builds the PR body from the audit log.
  15. Supports replay from recorded fix_events.

The current live path is deliberately tight. It is not an open-ended shell agent and not a multi-language repair platform. It is a trust-preserving Python/pytest repair workflow with one visible, inspectable spine.


Architecture

flowchart TB
    classDef app fill:#f8fafc,stroke:#111827,color:#111827
    classDef lemma fill:#ffffff,stroke:#111827,color:#111827
    classDef data fill:#f3f4f6,stroke:#374151,color:#111827
    classDef ext fill:#ecfdf5,stroke:#166534,color:#052e16
    classDef risk fill:#fef2f2,stroke:#991b1b,color:#450a0a

    User["Maintainer"] --> App["grappy-app<br/>Vite + React Lemma App"]
    App --> Workflow["change_run Workflow<br/>FORM -> fix_loop -> reviewer -> approval -> open_pr"]

    subgraph Pod["grappy-pod on Lemma"]
        Workflow --> FixLoop["fix_loop Function<br/>reproduce -> plan -> patch -> test -> guard"]
        Workflow --> Reviewer["reviewer Lemma Agent<br/>second opinion"]
        Workflow --> Approval["Human approval FORM<br/>approve or reject"]
        Workflow --> OpenPR["open_pr Function<br/>PR-as-evidence"]
        Workflow --> Reject["record_rejection Function"]

        FixLoop --> Tables[(Lemma Tables)]
        Reviewer --> Tables
        OpenPR --> Tables
        Reject --> Tables

        FixLoop --> Files[(Lemma Files)]
        OpenPR --> Files
        FixLoop --> LLM["Azure OpenAI<br/>coder + triage deployments"]
        FixLoop --> Pytest["Lemma-native pytest sandbox<br/>real exit codes"]
    end

    Tables --> Replay["replay Function<br/>ordered event trajectory"]
    OpenPR --> GitHub["GitHub App<br/>branch + pull request"]
    Index["index_repo Function<br/>AST repo map + symbols"] --> Tables
    Index --> Files
    GitHub --> Index

    class App app
    class Workflow,FixLoop,Reviewer,Approval,OpenPR,Reject,Replay,Index lemma
    class Tables,Files data
    class GitHub,LLM ext
    class Pytest risk
Loading

The Spine

Every major product capability collapses onto two data structures:

  • change_runs: the state of one governed repair.
  • fix_events: the append-only evidence log for that repair.

That is the product architecture in one sentence. The app, workflow, functions, agent, approval form, replay function, and PR body all read from or write to this spine.


One Change Run

stateDiagram-v2
    [*] --> queued
    queued --> reproducing
    reproducing --> unreproducible: unpatched pytest exits 0
    reproducing --> localizing: unpatched pytest exits non-zero
    localizing --> planning
    planning --> fixing
    fixing --> fixing: failed patch or failing tests
    fixing --> escalated: max iters, cost cap, wallclock, stuck, circuit breaker
    fixing --> reviewing: RED->GREEN
    reviewing --> needs_approval: reviewer verdict recorded
    needs_approval --> rejected: human rejects
    needs_approval --> pr_opened: human approves
    unreproducible --> [*]
    escalated --> [*]
    rejected --> [*]
    pr_opened --> [*]
Loading

Sequence

sequenceDiagram
    participant M as Maintainer
    participant A as Lemma App
    participant W as change_run Workflow
    participant F as fix_loop Function
    participant T as Lemma Tables
    participant R as reviewer Agent
    participant P as open_pr Function
    participant G as GitHub

    M->>A: Pick repo, describe bug, provide failing pytest target
    A->>W: Start manual workflow
    W->>F: Run caged fix loop
    F->>T: create change_run + run_created
    F->>F: run pytest on unpatched code
    F->>T: repro_attempted + repro_confirmed
    F->>T: localization_ranked + plan_drafted
    loop bounded attempts
        F->>F: ask model for minimal patch
        F->>F: apply SEARCH/REPLACE patch
        F->>F: run pytest
        F->>T: patch_proposed + test_run
    end
    F->>T: regression_passed and status needs_approval
    W->>R: Review change_run evidence
    R->>T: append review_verdict
    W->>M: Pause on approval form
    M->>W: Approve or reject
    W->>P: If approved, open evidence PR
    P->>G: Create branch and PR via Git Data API
    P->>T: append pr_opened
Loading

Event Log Shape

A successful run reads like a lab notebook:

run_created
repro_attempted
repro_confirmed
localization_ranked
plan_drafted
patch_proposed
test_run
regression_failed
reflexion_note
patch_proposed
test_run
regression_passed
review_verdict
pr_opened

The exact event types are declared in grappy-pod/tables/fix_events/fix_events.json. On the approve path, the approver is recorded in the pr_opened payload. On the reject path, record_rejection writes an approval_decision event.


Lemma SDK Usage

Lemma primitive Where it lives What it does
Pod grappy-pod/pod.json Owns the backend, data, functions, workflow, agent, files, and permissions.
Tables grappy-pod/tables/ Store run state, audit events, repo metadata, GitHub installations, symbols, and issue analysis.
Files /repomaps, /patches, /prs, /secrets in pod storage Hold repo maps, winning patches, generated PR bodies, and private credentials.
Functions grappy-pod/functions/ Run deterministic work: fix loop, indexing, sandboxing, LLM calls, PR creation, replay, GitHub sync.
Workflow grappy-pod/workflows/change_run/change_run.json Durable macro state machine with intake, repair, review, approval, rejection, and PR handoff.
Agent grappy-pod/agents/reviewer/ Independent reviewer that reads evidence and appends review_verdict.
App grappy-app/ Maintainer control surface deployed as a Lemma App.
Permissions Function and agent manifests Grant least-privilege access to tables and folders.

This is not a thin wrapper around Lemma. Lemma is the coordination layer, the data layer, the approval layer, and the app host.


Repository Structure

Gappy/
  README.md                         # this file
  AGENTS.md                         # project instructions for Codex agents

  grappy-pod/                       # Lemma pod: backend, data, workflow, agent
    pod.json
    agents/
      reviewer/
        instruction.md
        reviewer.json
    workflows/
      change_run/
        change_run.json
    tables/
      change_runs/
      fix_events/
      github_installations/
      issue_analyses/
      repo_symbols/
      repos/
    functions/
      fix_loop/
      gh_sync/
      gh_token/
      index_repo/
      llm_complete/
      open_pr/
      record_rejection/
      replay/
      run_in_sandbox/
      seed_demo_run/
    executor/
      grappy_executor/              # unit-tested local source of truth
      tests/
      pyproject.toml
    eval/
      autoloop_smoke.py             # live smoke: RED -> model patch -> GREEN
      seed_repo/

  grappy-app/                       # Vite/React Lemma App
    lemma.app.json
    package.json
    src/
      components/
      lib/
      pages/
      routes.tsx
      lemma-client.ts
      styles.css

  design-docs/                      # product, architecture, execution, UI, reliability specs
  knowledge-base/                   # hackathon + Lemma vectorless RAG corpus
    docs/
    fixforge/
    manifest.json

Current Build Root

The live product is:

The design docs record earlier alternatives and cuts. The current direction is the all-Lemma path: Lemma Tables/Files for data, Lemma pod permissions for auth, Lemma Functions for backend actions, and a static Vite SPA deployed as a Lemma App.


Backend Pod

The pod description is stored in grappy-pod/pod.json:

{
  "name": "grappy",
  "description": "Grappy - a supervised, audited, human-gated autonomous bug-fix engineer..."
}

Backend Responsibilities

The pod owns:

  • the repair workflow
  • all durable data
  • the append-only event log
  • the code execution path
  • Azure OpenAI calls
  • GitHub App token minting
  • repo indexing
  • real PR creation
  • rejection recording
  • replay
  • the reviewer Agent

The frontend is intentionally thin. It reads from Lemma Tables, starts workflow/function runs, submits approval decisions, and renders evidence.


Frontend App

The app is a Vite/React SPA deployed to lemma.work as a Lemma App. Its runtime configuration is in grappy-app/lemma.app.json and grappy-app/.env.example.

Routes

Route Purpose
/ Activity list of all recent change runs
/chat Start a new fix run
/chat/:runId Inspect a live or historical run
/settings Account settings
/settings/github GitHub App connection and token verification
/settings/repos Connected repositories and indexing controls

Routes are declared in grappy-app/src/routes.tsx.

App Surfaces

Surface Main files What it shows
Activity HomePage.tsx Minimal list of runs with status glyphs and timestamps.
Composer Composer.tsx Repo picker, bug description, failing test, target file, guardrails.
Run View RunView.tsx Live timeline, exit code proof, event details, diff, approval gate, evidence footer.
Settings SettingsPage.tsx Account, GitHub connection, repos and indexing.

Design Language

The UI follows the project direction in design-docs/11-frontend-dashboard.md:

  • black and white, Linear-style
  • color used only for semantic proof states: RED failure and GREEN success
  • shadcn/Radix primitives and lucide icons
  • Framer Motion via motion/react
  • DiceBear-style identity direction in docs
  • no marketing landing page; the first screen is the work surface

Client Data Flow

The app uses lemma-sdk@0.5.2 and lemma-sdk/react.

flowchart LR
    App["React components"] --> Hooks["src/lib/hooks.ts"]
    Hooks --> SDK["lemma-sdk/react"]
    SDK --> Tables["Lemma Datastore queries"]
    App --> Workflow["useWorkflow / useWorkflowForm"]
    Workflow --> Lemma["Lemma workflow run + approval resume"]
    App --> Functions["useFunctionRun"]
    Functions --> Index["index_repo / gh_sync / gh_token / replay"]
Loading

Core hooks live in grappy-app/src/lib/hooks.ts:

  • useRuns
  • useRun
  • useRunEvents
  • useRepos
  • useInstallations
  • useLivePoll

Data Model

erDiagram
    REPOS ||--o{ CHANGE_RUNS : "selected for"
    REPOS ||--o{ REPO_SYMBOLS : "indexed into"
    CHANGE_RUNS ||--o{ FIX_EVENTS : "emits"
    CHANGE_RUNS ||--o{ ISSUE_ANALYSES : "summarizes"
    GITHUB_INSTALLATIONS ||--o{ REPOS : "grants access to"

    REPOS {
        uuid id
        text github_full_name
        text default_branch
        enum index_status
        file_path repomap_path
        file_path conventions_path
        text indexed_sha
        datetime indexed_at
        text installation_id
        int symbol_count
    }

    CHANGE_RUNS {
        uuid id
        uuid repo_id
        enum status
        text issue_title
        text issue_body
        text fail_to_pass_test
        text buggy_sha
        float cost_spent_usd
        float max_cost_usd
        int iters
        text pr_url
        text repo_full_name
        text langsmith_trace_url
    }

    FIX_EVENTS {
        uuid id
        uuid change_run_id
        int seq
        enum kind
        json payload
        file_path artifact_path
        text langsmith_run_id
        text idempotency_key
        text actor
    }

    REPO_SYMBOLS {
        uuid id
        uuid repo_id
        text symbol
        enum kind
        text file_path
        int start_line
        int end_line
        text signature
        float pagerank
    }
Loading

Tables

Table File Purpose
change_runs change_runs.json One row per governed repair run.
fix_events fix_events.json Ordered append-only event log and replay source.
repos repos.json Connected repositories and index status.
repo_symbols repo_symbols.json AST-extracted functions, classes, methods, and line ranges.
github_installations github_installations.json GitHub App installation metadata.
issue_analyses issue_analyses.json Phase-0 analysis twin for reproduction and plan metadata.

Status Enum

change_runs.status is the maintainer-readable state:

queued
reproducing
unreproducible
localizing
planning
fixing
reviewing
needs_approval
approved
rejected
pr_opened
escalated
failed

Terminal states are honest. If the bug cannot be reproduced, Grappy says so. If the loop cannot converge within caps, it escalates instead of faking success.


Functions

Function Type Purpose
fix_loop JOB Main caged loop: create run, reproduce, localize, plan, propose patch, test, guard, and move to needs_approval or escalated.
run_in_sandbox JOB Keystone executor for the seed demo: materializes workspace, applies optional patch, runs pytest, returns real exit code.
llm_complete API Hardened Azure OpenAI call site for smoke/eval flows.
index_repo JOB GitHub App tarball clone, Python AST parse, repo_symbols rows, repo-map file, repos.index_status='indexed'.
gh_sync JOB Poll GitHub App installations and accessible repos, then upsert installation and repo rows.
gh_token API Mint a 1-hour GitHub App installation token and return masked metadata for verification.
open_pr JOB Render PR body from fix_events, apply winning patch on a branch, open real GitHub PR if possible, else write evidence file.
record_rejection JOB Mark a run rejected and append the human decision.
replay API Read-only replay from the ordered event log.
seed_demo_run JOB Idempotently insert a completed demo run for a populated judge/operator dashboard.

The Main Loop

grappy-pod/functions/fix_loop/code.py is the keystone implementation. It is self-contained because Lemma's hosted runtime loads each function file independently.

The live loop:

  • sources workspace files from a GitHub App tarball, inline files, or the embedded seed repo
  • confirms RED with pytest
  • writes run_created, repro_attempted, and repro_confirmed
  • loads repo-map and symbols when available
  • writes localization_ranked
  • drafts a plan with the triage model
  • asks the coder model for minimal SEARCH/REPLACE blocks
  • applies those blocks deterministically
  • reruns pytest
  • writes test_run, regression_failed, reflexion_note, or regression_passed
  • stops on cost, iteration, wall-clock, stuck, or circuit-breaker caps
  • moves the run to needs_approval only after convergence

The Patch Format

The current live function uses Aider-style SEARCH/REPLACE blocks:

checkout/pricing.py
<<<<<<< SEARCH
    return order_total > FREE_SHIPPING_THRESHOLD
=======
    return order_total >= FREE_SHIPPING_THRESHOLD
>>>>>>> REPLACE

The model proposes text. Grappy's code parses and applies it. The model does not get to mutate files directly.


Workflow And Agent

The macro workflow lives in grappy-pod/workflows/change_run/change_run.json.

flowchart TB
    Intake["FORM: Describe the bug"] --> Run["FUNCTION: fix_loop"]
    Run --> Converged{"DECISION: converged?"}
    Converged -->|yes| Review["AGENT: reviewer"]
    Converged -->|no| Escalated["END: escalated"]
    Review --> Approval["FORM: human approval"]
    Approval --> Decide{"DECISION: approved?"}
    Decide -->|approve| PR["FUNCTION: open_pr"]
    Decide -->|reject| Reject["FUNCTION: record_rejection"]
    PR --> PREnd["END: PR opened"]
    Reject --> RejectEnd["END: rejected"]
Loading

Reviewer Agent

The reviewer Agent is declared in grappy-pod/agents/reviewer/reviewer.json and instructed in grappy-pod/agents/reviewer/instruction.md.

It reads:

  • the change_runs row
  • the ordered fix_events
  • the repro_confirmed event
  • the final regression_passed.winning_patch

It appends exactly one review_verdict event:

{
  "verdict": "pass",
  "rationale": "Minimal, test-backed change."
}

The reviewer does not edit code, open PRs, or change the run status. It gives a second opinion before the human approval gate.


Trust, Safety, And Verification

Real Exit Codes

Grappy treats pytest exit codes as data, not exceptions:

  • non-zero before patching means the bug is real enough to attempt
  • zero after patching means the failing test is satisfied
  • non-zero after patching sends the loop back with real output
  • timeout returns 124

The executor contract is documented in design-docs/09-execution-sandbox.md and mirrored in the tested executor package.

False-Green Defenses

Risk Defense
Agent claims success without running tests Only pytest exit code 0 can converge.
Patch accidentally depends on dirty state The loop materializes a fresh workspace for test runs.
Patch does not apply Parser rejects it and records a reflexion_note.
Model repeats itself Stuck detector escalates repeated identical patches.
Cloud/model failure burns budget Circuit breaker and retry caps stop the run.
Secrets leak into prompts or logs Secret regex redaction and untrusted-data wrappers.
Prompt injection in repo or issue text Injection patterns are flagged and repo content is wrapped as untrusted data.

Guardrails In fix_loop

Guard Default / behavior
max_iters 4 by default in the workflow intake
max_cost_usd 1.0 by default
max_wallclock_s 600 by default
circuit breaker 3 consecutive infra failures
stuck detector repeated identical patch signatures
file cap repo tarball files capped before loading into workspace
output cap prompts wrap and truncate long untrusted blocks

GitHub Connector

Grappy uses a GitHub App, not a broad OAuth token.

Why GitHub App

  • per-repository installation scope
  • short-lived installation tokens
  • bot identity for PRs
  • GitHub's own "all repos vs selected repos" screen acts as the repo picker
  • server-side token minting lives inside Lemma Functions

Connector Functions

Function What it does
gh_sync Lists installations and accessible repositories, updates Lemma Tables.
gh_token Mints a masked, smoke-testable installation token.
index_repo Uses the token to download a tarball and index Python symbols.
fix_loop Uses the token to source a real repo workspace.
open_pr Uses the token to create blobs, tree, commit, branch, and pull request.

PR Creation

open_pr uses the Git Data API:

base ref -> base commit -> base tree
winning patch -> updated blobs
updated blobs -> new tree
new tree -> commit
commit -> branch ref
branch ref -> pull request

If a real repo or patch cannot be recovered, it still writes the evidence body to /prs/pr-<change_run_id>.md and records the fallback as lemma-file:<path>.


Observability And Replay

Grappy's observability is intentionally boring: one row after another, in order.

flowchart LR
    FixLoop["fix_loop"] --> Events["fix_events rows"]
    Reviewer["reviewer Agent"] --> Events
    Approval["Human approval"] --> Events
    OpenPR["open_pr"] --> Events
    Events --> UI["Run timeline"]
    Events --> Replay["replay API"]
    Events --> PRBody["PR body"]
    Events --> Audit["Audit query"]
Loading

What Gets Recorded

fix_events.payload carries the step-specific proof:

  • exit_code
  • passed, failed, errors, skipped
  • duration_ms
  • stdout_tail
  • test list summaries
  • patch text
  • deployment and token usage metadata
  • reviewer verdict
  • approver and PR metadata

Replay

grappy-pod/functions/replay/code.py reconstructs the timeline from the recorded events. It does not rerun the model. It re-shows the ordered trajectory, derived facts, exit codes, iterations, cost, verdict, approver, and PR.

That is an honest replay: it audits what happened rather than asking the agent to re-narrate it.


Development

Prerequisites

  • Node.js compatible with Vite 7 and React 19
  • npm
  • Python 3.11+ for the executor package
  • uv for executor tests
  • Lemma CLI for pod import, function runs, and app deploy
  • GitHub App credentials in pod Files for real repository runs
  • Azure OpenAI credentials in pod Files for model-backed repair

Frontend

cd grappy-app
npm install
npm run dev

Useful scripts:

npm run dev
npm run build
npm run preview

Runtime configuration is read from .env.local or .env.development.local. The template is:

cp grappy-app/.env.example grappy-app/.env.local

Important values:

VITE_LEMMA_API_URL=https://api.lemma.work
VITE_LEMMA_AUTH_URL=https://lemma.work/auth
VITE_LEMMA_POD_ID=<pod uuid>
VITE_LEMMA_APP_BASE_PATH=/

Executor Unit Tests

The executor package is the tested local source of truth for patch parsing, pytest output parsing, guards, prompt helpers, repomap behavior, and safety helpers.

cd grappy-pod/executor
uv run pytest -q

Pod Import

LEMMA_ORG_ID=<org id> lemma pods import grappy-pod --pod grappy

Function Smokes

Run the seed executor without a patch:

lemma functions run run_in_sandbox --pod grappy -d '{"patch":"","test_target":"tests","timeout":120}' --wait

Run the main loop on the built-in seed demo:

lemma functions run fix_loop --pod grappy -d '{"max_iters":4,"max_cost_usd":1.0,"max_wallclock_s":600}' --wait

Run a real repository bug when the GitHub App has access:

lemma functions run fix_loop --pod grappy -d '{
  "repo":"theCodeForgerHQ/grappy-demo",
  "ref":"main",
  "issue_title":"Free shipping boundary off-by-one",
  "issue_body":"Orders exactly at the free-shipping threshold are wrongly charged shipping.",
  "fail_to_pass_test":"tests/test_pricing.py",
  "target_path":"checkout/pricing.py",
  "test_target":"tests/test_pricing.py",
  "max_iters":4
}' --wait

Live Autoloop Smoke

grappy-pod/eval/autoloop_smoke.py drives:

  1. run_in_sandbox unpatched -> RED
  2. llm_complete -> model patch
  3. run_in_sandbox patched -> GREEN
python grappy-pod/eval/autoloop_smoke.py

This smoke uses live Lemma and Azure credentials. It is not a unit test.


Deployment

Backend Pod

LEMMA_ORG_ID=<org id> lemma pods import grappy-pod --pod grappy

Frontend App

cd grappy-app
npm run build
lemma apps deploy grappy-app . --pod grappy --dist-dir dist -y

Required Pod Files / Secrets

These are read from pod Files, not committed:

Pod file Used by
/secrets/azure_openai.json fix_loop, llm_complete
/secrets/langsmith.json best-effort trace link in fix_loop
/secrets/github_app.json GitHub App metadata and optional installation id
/secrets/github_app_key.pem GitHub App JWT signing

Expected Azure OpenAI secret shape:

{
  "endpoint": "https://<resource>.openai.azure.com",
  "api_key": "<key>",
  "api_version": "<api version>",
  "coder_deployment": "<coder deployment>",
  "triage_deployment": "<triage deployment>",
  "fallback_deployment": "<fallback deployment>"
}

Expected GitHub App metadata shape:

{
  "app_id": "<app id>",
  "installation_id": "<optional installation id>"
}

Demo Script

The strongest demo starts with proof, not a prompt.

  1. Open with the maintainer pain. "AI agents can write patches. The scary part is trusting one in a real repo."

  2. Pick an indexed repo. Show that the repository is connected through the GitHub App and indexed into repo_symbols.

  3. Start one scoped run. Provide one bug, one failing pytest target, and one target file.

  4. Show RED before code. The first visual proof is the unpatched pytest result with a non-zero exit_code.

  5. Show localization and plan. The run records why it believes the suspect file/symbol is relevant.

  6. Show the loop. A patch is proposed, applied, tested, and either retried or converged from real output.

  7. Show GREEN. The exit code flips to 0; the final proof strip shows tests, time, cost, and iterations.

  8. Show the reviewer. The Lemma Agent verdict appears before approval.

  9. Approve. The workflow resumes only after the human decision.

  10. Open the PR. The PR body is generated from the audit log.

  11. Replay. Show that the run can be inspected again from fix_events, without asking the model.

The line to land:

Grappy does not ask you to trust an agent. It hands you the evidence a maintainer would need to decide.


Design Decisions

Deliberate Cuts

Cut Why
Autonomous merge The human approval gate is the product.
Multi-language repair Python/pytest keeps the oracle and sandbox path concrete.
Whole-suite CI by default Selected/scoped tests keep runs fast and cost-bounded.
Agent-generated acceptance criteria as the main path The failing test must remain independent of the repair agent.
Broad multi-agent sprawl One repair loop plus one reviewer is easier to audit than an agent zoo.
Separate database/auth stack Lemma Tables, Files, and pod permissions are the intended platform fit.
SSR frontend lemma.work serves the Vite SPA as the Lemma App path.

Current Implementation vs Future Options

Area Current live path Future option
Patch generation Single candidate per attempt, bounded retries Best-of-N execution rerank when budget allows
Patch format SEARCH/REPLACE blocks Codex apply_patch envelope for models optimized for it
Repo indexing Python AST symbols and markdown repo-map richer graph/PageRank or optional semantic column
Replay Recorded trajectory replay deterministic re-execution where safe and cheap
CI Sandbox pytest execution cite GitHub Actions checks after PR opens
Languages Python additional language adapters only after Python path is reliable

Roadmap

The next work should not widen the product until the core loop is undeniable.

  1. Harden real-repo test scoping so every run's test_target matches the single-bug scope.
  2. Add richer regression selection from the repo_symbols graph.
  3. Persist raw stdout/stderr as Files for every test event, not only tails.
  4. Add explicit approval_decision rendering in the UI timeline.
  5. Read GitHub Actions status on opened PRs and cite it in the evidence footer.
  6. Add optional best-of-N candidate sampling behind a cost-aware toggle.
  7. Expand from Python-only only after the maintainer trust loop remains stable.

Knowledge Base

This repository includes a vectorless RAG corpus in knowledge-base/. When answering hackathon, Lemma SDK, judging, timeline, submission, or strategy questions, use the manifest first:

knowledge-base/manifest.json
knowledge-base/INDEX.md
knowledge-base/TAGS.md
knowledge-base/retrieval-guide.md

Key nodes used to frame this README:

  • kb-judging: rubric weights and evaluation focus
  • kb-winning-strategy: one sharp user, one core loop, defend scope
  • kb-lemma-concepts: Pods, Tables, Files, Agents, Workflows, Functions, Approvals, Apps
  • kb-submission: live Lemma App/pod, demo, and writeup expectations

The project-specific design corpus lives in knowledge-base/fixforge/.


The Short Version

Grappy is not trying to be the fastest patch writer. It is trying to be the repair workflow a maintainer can trust:

known failing pytest
  -> reproduce RED
  -> localize and plan
  -> patch under guardrails
  -> verify GREEN
  -> reviewer second opinion
  -> human approval
  -> PR-as-evidence
  -> replayable audit trail

One repo. One bug. One human gate. Real exit codes. Evidence before trust.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors