feat(docs): Initial draft of new contributing policies
This commit is contained in:
parent
65bc079033
commit
cf7877f96f
|
|
@ -8,6 +8,48 @@
|
|||
#
|
||||
# The workflow gates only understand individual @usernames (no @org/team
|
||||
# entries).
|
||||
#
|
||||
# Order matters: GitHub applies the LAST matching pattern, so narrower rules
|
||||
# go further down. Paths not listed here have no automatic reviewer.
|
||||
|
||||
# Telemetry, tracing, metrics.
|
||||
/src/telemetry/ @akattelu @Rajat-Ahuja1997
|
||||
|
||||
# Data model, connections, configuration, LLM transport.
|
||||
/src/db.py @akattelu @eisene @VVoruganti
|
||||
/src/models.py @akattelu @eisene @VVoruganti
|
||||
/src/config.py @akattelu @eisene @VVoruganti
|
||||
/src/cache/ @akattelu @eisene @VVoruganti
|
||||
/src/crud/ @akattelu @eisene @VVoruganti
|
||||
/migrations/ @akattelu @eisene @VVoruganti
|
||||
/src/llm/ @akattelu @eisene @VVoruganti
|
||||
|
||||
# Client-facing surfaces and API shape.
|
||||
/sdks/ @ajspig @akattelu
|
||||
/mcp/ @ajspig @akattelu
|
||||
/honcho-cli/ @ajspig @akattelu
|
||||
/src/routers/ @ajspig @akattelu
|
||||
/src/schemas/ @ajspig @akattelu
|
||||
|
||||
# The reasoning agents, their prompts, and shared agent tooling.
|
||||
/src/deriver/ @eisene @akattelu @matthewlanders
|
||||
/src/dreamer/ @eisene @akattelu @matthewlanders
|
||||
/src/dialectic/ @eisene @akattelu @matthewlanders
|
||||
/src/utils/ @eisene @akattelu @matthewlanders
|
||||
|
||||
# Deployment, and swappable storage and inference backends.
|
||||
# /src/llm/backends/ must stay below /src/llm/ above — last match wins.
|
||||
/docker/ @eisene @Rajat-Ahuja1997 @akattelu
|
||||
/Dockerfile @eisene @Rajat-Ahuja1997 @akattelu
|
||||
/docker-compose.yml.example @eisene @Rajat-Ahuja1997 @akattelu
|
||||
/src/vector_store/ @eisene @Rajat-Ahuja1997 @akattelu
|
||||
/src/llm/backends/ @eisene @Rajat-Ahuja1997 @akattelu
|
||||
|
||||
# Documentation and contributor-facing policy.
|
||||
/docs/ @ajspig @akattelu @VVoruganti
|
||||
/README.md @ajspig @akattelu @VVoruganti
|
||||
/CONTRIBUTING.md @akattelu @ajspig @VVoruganti
|
||||
/SECURITY.md @akattelu @ajspig @VVoruganti
|
||||
|
||||
# Reviewers auto-requested on changes under .github/ (workflows, this file,
|
||||
# templates).
|
||||
|
|
@ -16,4 +58,4 @@
|
|||
# CI-trigger allowlist only: this path matches no real file, so these people
|
||||
# are never auto-requested for review, but the workflow gates still pick
|
||||
# them up.
|
||||
/ci-trigger-allowlist @3un01a @adavyas @ajspig @courtlandleer @erosika @lowyelling @matthewlanders @vintrocode
|
||||
/ci-trigger-allowlist @ajspig @courtlandleer @erosika @lowyelling @vintrocode
|
||||
|
|
|
|||
|
|
@ -0,0 +1,120 @@
|
|||
name: Issue Gate
|
||||
|
||||
# Closes pull requests that are not linked to an issue carrying the
|
||||
# `maintainer-approved` label. See CONTRIBUTING.md for the policy.
|
||||
#
|
||||
# `pull_request_target` is required so the job has write access on PRs from
|
||||
# forks. This workflow must therefore NEVER check out or execute code from the
|
||||
# pull request — it only calls the GitHub API.
|
||||
#
|
||||
# Not triggered on `synchronize`: re-running the gate on every push to an
|
||||
# in-flight PR would be noise. Drafts are ignored until marked ready.
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, edited, reopened, ready_for_review]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
gate:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
const { owner, repo } = context.repo;
|
||||
const GATE_LABEL = 'needs-approved-issue';
|
||||
const EXEMPT_LABEL = 'gate-exempt';
|
||||
const REQUIRED_LABEL = 'maintainer-approved';
|
||||
const MARKER = '<!-- issue-gate -->';
|
||||
|
||||
const skip = (why) => core.info(`Skipping gate: ${why}`);
|
||||
|
||||
if (pr.state !== 'open') return skip('pull request is not open');
|
||||
if (pr.draft) return skip('pull request is a draft');
|
||||
if (pr.user.type === 'Bot') return skip('author is a bot');
|
||||
if (['OWNER', 'MEMBER', 'COLLABORATOR'].includes(pr.author_association)) {
|
||||
return skip(`author_association is ${pr.author_association}`);
|
||||
}
|
||||
if ((pr.labels || []).some((l) => l.name === EXEMPT_LABEL)) {
|
||||
return skip(`pull request carries the ${EXEMPT_LABEL} label`);
|
||||
}
|
||||
|
||||
// Collect candidate issue numbers from the PR body. HTML comments are
|
||||
// stripped first so the commented-out `Fixes #XXX` hint in the template
|
||||
// never counts. Any `#123` is treated as a candidate, not just the
|
||||
// closing keywords — being generous here only risks letting a PR
|
||||
// through, while being strict risks closing a legitimate one.
|
||||
const body = (pr.body || '').replace(/<!--[\s\S]*?-->/g, '');
|
||||
const numbers = new Set();
|
||||
for (const m of body.matchAll(/#(\d+)\b/g)) numbers.add(Number(m[1]));
|
||||
const urlPattern = new RegExp(`github\\.com/${owner}/${repo}/issues/(\\d+)`, 'gi');
|
||||
for (const m of body.matchAll(urlPattern)) numbers.add(Number(m[1]));
|
||||
|
||||
let approved = null;
|
||||
const seen = [];
|
||||
for (const n of [...numbers].slice(0, 10)) {
|
||||
let issue;
|
||||
try {
|
||||
({ data: issue } = await github.rest.issues.get({ owner, repo, issue_number: n }));
|
||||
} catch (e) {
|
||||
if (e.status === 404) { seen.push(`#${n} (not found)`); continue; }
|
||||
throw e;
|
||||
}
|
||||
if (issue.pull_request) { seen.push(`#${n} (is a pull request)`); continue; }
|
||||
if (issue.labels.some((l) => (l.name || l) === REQUIRED_LABEL)) { approved = n; break; }
|
||||
seen.push(`#${n} (not approved)`);
|
||||
}
|
||||
|
||||
if (approved) {
|
||||
core.info(`Gate passed via #${approved}`);
|
||||
if ((pr.labels || []).some((l) => l.name === GATE_LABEL)) {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner, repo, issue_number: pr.number, name: GATE_LABEL,
|
||||
}).catch(() => {});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const reason = numbers.size === 0
|
||||
? 'This pull request does not reference an issue in its description.'
|
||||
: `The referenced ${seen.length === 1 ? 'issue does' : 'issues do'} not have the \`${REQUIRED_LABEL}\` label: ${seen.join(', ')}.`;
|
||||
|
||||
core.warning(`Gate failed: ${reason}`);
|
||||
|
||||
await github.rest.issues.addLabels({
|
||||
owner, repo, issue_number: pr.number, labels: [GATE_LABEL],
|
||||
});
|
||||
|
||||
const comments = await github.paginate(github.rest.issues.listComments, {
|
||||
owner, repo, issue_number: pr.number, per_page: 100,
|
||||
});
|
||||
if (!comments.some((c) => (c.body || '').includes(MARKER))) {
|
||||
await github.rest.issues.createComment({
|
||||
owner, repo, issue_number: pr.number,
|
||||
body: [
|
||||
MARKER,
|
||||
'Thanks for the contribution. Closing this for now, because it does not clear our issue gate.',
|
||||
'',
|
||||
`**${reason}**`,
|
||||
'',
|
||||
`Every pull request to Honcho needs to be linked to an issue carrying the \`${REQUIRED_LABEL}\` label. We do this so the review queue only holds work we have already agreed should be built — it means nobody spends time on a change we cannot merge.`,
|
||||
'',
|
||||
'To get this moving:',
|
||||
'',
|
||||
`1. Find or open an issue describing the change. [Approved issues are here](https://github.com/${owner}/${repo}/issues?q=is%3Aissue+is%3Aopen+label%3A${REQUIRED_LABEL}).`,
|
||||
'2. Make the case for it in [Discord](http://discord.gg/honcho) — maintainers are most active there, and it is by far the fastest route to a decision.',
|
||||
`3. Once the issue has the \`${REQUIRED_LABEL}\` label, add \`Fixes #<number>\` to this pull request's description and reopen it.`,
|
||||
'',
|
||||
`See [CONTRIBUTING.md](https://github.com/${owner}/${repo}/blob/main/CONTRIBUTING.md) for the full process. If you think this was closed in error, comment here and a maintainer will take a look.`,
|
||||
].join('\n'),
|
||||
});
|
||||
}
|
||||
|
||||
await github.rest.pulls.update({
|
||||
owner, repo, pull_number: pr.number, state: 'closed',
|
||||
});
|
||||
448
CONTRIBUTING.md
448
CONTRIBUTING.md
|
|
@ -1,219 +1,367 @@
|
|||
# Contributing to Honcho
|
||||
|
||||
Thank you for your interest in contributing to Honcho! This guide outlines the process for contributing to the project and our development conventions.
|
||||
<!-- This file is mirrored at docs/v3/contributing/guidelines.mdx. Update both. -->
|
||||
|
||||
## Getting Started
|
||||
Thanks for your interest in contributing. This guide covers how work gets accepted, how
|
||||
Honcho is put together, and what a mergeable pull request looks like.
|
||||
|
||||
Before you start contributing, please:
|
||||
Honcho is a small team maintaining a project that gets more proposals than we can review.
|
||||
The rules below exist so that the work you do has somewhere to land — not to keep you out.
|
||||
|
||||
1. **Set up your development environment** - Follow the [Local Development guide](./README.md#local-development) in the README to get Honcho running locally.
|
||||
## Contents
|
||||
|
||||
2. **Join our community** - Feel free to join us in our [Discord](http://discord.gg/honcho) to discuss your changes, get help, or ask questions.
|
||||
- [Before you write code](#before-you-write-code)
|
||||
- [What gets prioritized](#what-gets-prioritized)
|
||||
- [If you're an agent](#if-youre-an-agent)
|
||||
- [How Honcho works](#how-honcho-works)
|
||||
- [Where to change what](#where-to-change-what)
|
||||
- [Local setup](#local-setup)
|
||||
- [Making the change](#making-the-change)
|
||||
- [Opening the pull request](#opening-the-pull-request)
|
||||
- [Reporting bugs and requesting features](#reporting-bugs-and-requesting-features)
|
||||
- [Security](#security)
|
||||
- [License](#license)
|
||||
|
||||
3. **Review existing issues** - Check the [issues tab](https://github.com/plastic-labs/honcho/issues) to see what's already being worked on or to find something to contribute to.
|
||||
## Before you write code
|
||||
|
||||
## Contribution Workflow
|
||||
**Every pull request needs an issue, and that issue needs the `maintainer-approved` label.**
|
||||
|
||||
### 1. Fork and Clone
|
||||
A pull request that is not linked to an issue, or that is linked to an issue without the
|
||||
label, will be closed without review. This is automated. We do this because an unreviewable
|
||||
backlog helps nobody: a PR against an unapproved issue is work you did that we may not be
|
||||
able to merge, no matter how good it is.
|
||||
|
||||
1. Fork the repository on GitHub
|
||||
2. Clone your fork locally:
|
||||
So, in order:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/YOUR_USERNAME/honcho.git
|
||||
cd honcho
|
||||
```
|
||||
1. **Find approved work.** Browse
|
||||
[issues labelled `maintainer-approved`](https://github.com/plastic-labs/honcho/issues?q=is%3Aissue+is%3Aopen+label%3Amaintainer-approved).
|
||||
That label is the queue of things we have agreed should be built. Anything in it is fair
|
||||
game — comment on the issue to claim it.
|
||||
|
||||
3. Add the upstream repository as a remote:
|
||||
2. **Or open an issue and get it approved.** Use the
|
||||
[issue templates](https://github.com/plastic-labs/honcho/issues/new/choose). Maintainers
|
||||
triage and apply the label.
|
||||
|
||||
```bash
|
||||
git remote add upstream https://github.com/plastic-labs/honcho.git
|
||||
```
|
||||
3. **If you feel strongly about an issue, come to [Discord](https://discord.gg/honcho).**
|
||||
This is the fastest path by a wide margin. Maintainers are more active there than in the
|
||||
issue tracker, and a five-minute conversation about what you want to build usually
|
||||
resolves whether it fits before either side spends real time on it.
|
||||
|
||||
### 2. Create a Branch
|
||||
4. **Then open the PR**, with `Fixes #123` in the body.
|
||||
|
||||
Create a new branch for your feature or bug fix:
|
||||
Small exceptions we will not be pedantic about: fixing a typo, a broken link, or an
|
||||
obviously wrong code sample. Open the PR, explain it in one line, and we will sort out the
|
||||
issue linkage.
|
||||
|
||||
## What gets prioritized
|
||||
|
||||
Roughly, work on Honcho falls along these axes. Knowing which one your idea sits on tells
|
||||
you a lot about how likely it is to get approved.
|
||||
|
||||
| Axis | What it covers |
|
||||
| --- | --- |
|
||||
| **Observability** | Understanding how Honcho behaves in production — telemetry, tracing, CloudEvents, metrics. |
|
||||
| **Memory quality** | Better conclusions from the same input — the deriver, dreamer, and dialectic; eval results. |
|
||||
| **Developer experience** | Fitting cleanly into more application architectures — SDKs, scopes, composable peers, the CLI. |
|
||||
| **Breadth of input** | Widening what Honcho can ingest and represent — multimodal and non-conversational data. |
|
||||
| **Ubiquity** | Reachable wherever a developer already works — integrations, self-hosting, alternate vector-store and inference backends, local-first defaults. |
|
||||
| **Reliability and cost** | Trustworthy in production — connection and concurrency hardening, queue throughput, cost per token. |
|
||||
|
||||
In practice, **Ubiquity** and **Developer experience** are where outside contributions land
|
||||
most easily. A new integration, a self-hosting rough edge, a vector-store or inference
|
||||
backend, an SDK ergonomics fix — these are additive and rarely collide with work already in
|
||||
flight.
|
||||
|
||||
Changes to the reasoning pipeline itself — deriver prompts, dialectic tool design, dreamer
|
||||
strategy — are the hardest to accept from outside. Not because they are unwelcome, but
|
||||
because they are measured against eval results we run internally, and they frequently
|
||||
conflict with in-flight work. Talk to us in Discord first, always.
|
||||
|
||||
## If you're an agent
|
||||
|
||||
If you are a coding agent working on this repository, read this section before writing code.
|
||||
The most common failure we see is a well-formed, well-tested pull request against an issue
|
||||
that was never approved. That gets closed, and the work is wasted.
|
||||
|
||||
- **Check the gate first.** Before writing code:
|
||||
|
||||
```bash
|
||||
gh issue view <N> --repo plastic-labs/honcho --json number,title,state,labels
|
||||
```
|
||||
|
||||
Stop if there is no issue number, if the issue is closed, or if `maintainer-approved` is
|
||||
not in the labels. Report that to the person you are working with instead of proceeding.
|
||||
|
||||
- **Do not open a PR in order to establish the issue link afterwards.** The issue comes
|
||||
first.
|
||||
|
||||
- **Do not report checks you did not run.** If you did not execute the test command, say so.
|
||||
A PR body claiming a green run that did not happen costs a maintainer more time than no
|
||||
claim at all.
|
||||
|
||||
- **Use the checklist.** [`skills/pre-pr/SKILL.md`](./skills/pre-pr/SKILL.md) in this repo
|
||||
encodes the gate, the test-layer matrix, and the PR body format. If your harness supports
|
||||
skills, invoke it rather than reimplementing the checks.
|
||||
|
||||
## How Honcho works
|
||||
|
||||
Enough architecture to find your way around. For the user-facing model — what a Peer is, what
|
||||
`get_context` returns — see [Core Concepts in the README](./README.md#core-concepts) and the
|
||||
[documentation](https://honcho.dev/docs/).
|
||||
|
||||
### Two processes
|
||||
|
||||
Honcho runs as two cooperating processes over a shared Postgres database and Redis cache.
|
||||
|
||||
| | API server | Deriver worker |
|
||||
| --- | --- | --- |
|
||||
| Start | `uv run fastapi dev src/main.py` | `uv run python -m src.deriver` |
|
||||
| Entry | `src/main.py` | `src/deriver/__main__.py` |
|
||||
| Does | Serves HTTP, enqueues background work, returns immediately | Consumes the queue: Deriver, Summarizer, Dreamer, Reconciler |
|
||||
| Hosts | The Dialectic agent, inline on the request path | Everything else |
|
||||
|
||||
The split is the load-bearing design decision: **an HTTP request never blocks on LLM work**,
|
||||
with the single exception of the Dialectic chat endpoint, which is synchronous by nature.
|
||||
If you are adding something slow, it belongs in the worker.
|
||||
|
||||
The deriver is a separate process. If messages go in and nothing ever comes out, the usual
|
||||
cause is that nobody started it.
|
||||
|
||||
### The path of a message
|
||||
|
||||
Worth tracing once, because it crosses most of the codebase:
|
||||
|
||||
1. `POST /v3/workspaces/{w}/sessions/{s}/messages` lands in `src/routers/messages.py`.
|
||||
2. The row is written, then `enqueue()` in `src/deriver/enqueue.py` creates `queue_item`
|
||||
rows — one set of work per observing peer.
|
||||
3. `src/deriver/queue_manager.py` polls the queue, claiming work units so that messages in a
|
||||
session are processed in order.
|
||||
4. `process_item()` in `src/deriver/consumer.py` dispatches on task type — representation,
|
||||
summary, deletion, reconciliation.
|
||||
5. For a representation task, `process_representation_tasks_batch()` in
|
||||
`src/deriver/deriver.py` makes **one structured-output LLM call for the whole batch** and
|
||||
writes the resulting conclusions into the collection keyed by the
|
||||
`(observer, observed)` peer pair.
|
||||
6. Later, `src/dialectic/` reads those conclusions back at recall time to answer a chat
|
||||
request.
|
||||
|
||||
Embedding is deliberately *not* on this path. `MessageEmbedding` rows are written with
|
||||
`sync_state='pending'` and embedded asynchronously by the Reconciler
|
||||
(`src/reconciler/sync_vectors.py`), which runs on a scheduler inside the deriver process.
|
||||
|
||||
### The four agents
|
||||
|
||||
They share tool definitions in `src/utils/agent_tools.py` and the provider-agnostic LLM
|
||||
client in `src/llm/`. Each has its own `MODEL_CONFIG` with a fallback chain in
|
||||
`src/config.py`.
|
||||
|
||||
| Agent | Where | Shape |
|
||||
| --- | --- | --- |
|
||||
| **Deriver** | `src/deriver/` | A single structured-output call per message batch. Not a tool loop — this is a deliberate cost and latency tradeoff. |
|
||||
| **Dialectic** | `src/dialectic/` | The one tool-using agent on the request path. Loops over tools until it can answer. Five reasoning tiers from `minimal` to `max`, each with its own model and tool set. |
|
||||
| **Dreamer** | `src/dreamer/` | Off-queue consolidation. Two specialist phases (deduction, then induction) that build reasoning trees over existing conclusions. |
|
||||
| **Summarizer** | `src/utils/summarizer.py` | Direct LLM call, no tools. Two tiers — short and long summaries at different message counts. |
|
||||
|
||||
Prompts live in `src/deriver/prompts.py`, `src/dialectic/prompts.py`, and
|
||||
`src/dreamer/specialists.py`.
|
||||
|
||||
### A note on naming
|
||||
|
||||
What the public API and documentation call **conclusions** are called **observations**
|
||||
throughout the code — `create_observations`, `get_observation_context`, and so on. Likewise
|
||||
**collections** and **documents** are internal storage concepts that are not exposed
|
||||
directly through the API. Do not rename across that boundary in a drive-by change; the
|
||||
public and internal vocabularies are being reconciled deliberately.
|
||||
|
||||
## Where to change what
|
||||
|
||||
| I want to change... | Start here |
|
||||
| --- | --- |
|
||||
| An HTTP endpoint | `src/routers/` — one module per resource |
|
||||
| A database query | `src/crud/` — mirrors the router layout |
|
||||
| The database schema | `src/models.py`, plus a migration in `migrations/versions/` |
|
||||
| A configuration value | `src/config.py`, and add it to `config.toml.example` and `.env.template` |
|
||||
| A tool an agent can call | `src/utils/agent_tools.py` — definitions plus the per-agent tool lists |
|
||||
| A prompt | `src/deriver/prompts.py`, `src/dialectic/prompts.py`, `src/dreamer/specialists.py` |
|
||||
| LLM provider behavior | `src/llm/backends/` — `anthropic.py`, `gemini.py`, `openai.py` |
|
||||
| Embeddings or vector storage | `src/embedding_client.py`, `src/vector_store/` |
|
||||
| Telemetry or metrics | `src/telemetry/` — see the notes in `CLAUDE.md` before adding an event type |
|
||||
| Authentication and scoping | `src/security.py`, `src/dependencies.py` |
|
||||
| The Python or TypeScript SDK | `sdks/python/`, `sdks/typescript/` |
|
||||
| The CLI | `honcho-cli/` |
|
||||
| The MCP server | `mcp/` |
|
||||
| Public documentation | `docs/v3/` — Mintlify; nav lives in `docs/docs.json` |
|
||||
|
||||
Tests in `tests/` mirror `src/`. `CLAUDE.md` at the repo root has more detail on house
|
||||
conventions, and is worth skimming even if you are not using an agent.
|
||||
|
||||
## Local setup
|
||||
|
||||
Get a stack running first — [Self-hosting in the README](./README.md#self-hosting) covers
|
||||
both the Docker path and a manual Postgres setup. Then, for development:
|
||||
|
||||
```bash
|
||||
uv sync # create the venv and install dependencies
|
||||
uv run alembic upgrade head # apply migrations
|
||||
```
|
||||
|
||||
Run both processes, in separate terminals:
|
||||
|
||||
```bash
|
||||
uv run fastapi dev src/main.py # API server, reloads on change
|
||||
uv run python -m src.deriver # background worker
|
||||
```
|
||||
|
||||
Everything Python goes through `uv run`. Redis is optional for local development; without it
|
||||
caching is simply disabled.
|
||||
|
||||
## Making the change
|
||||
|
||||
### Branches and commits
|
||||
|
||||
```bash
|
||||
git checkout -b feature/your-feature-name
|
||||
# or
|
||||
git checkout -b fix/your-bug-fix-name
|
||||
```
|
||||
|
||||
**Branch naming conventions:**
|
||||
Prefixes: `feature/`, `fix/`, `docs/`, `refactor/`, `test/`.
|
||||
|
||||
- `feature/description` - for new features
|
||||
- `fix/description` - for bug fixes
|
||||
- `docs/description` - for documentation updates
|
||||
- `refactor/description` - for code refactoring
|
||||
- `test/description` - for adding or updating tests
|
||||
|
||||
### 3. Make Your Changes
|
||||
|
||||
- Write clean, readable code that follows our coding standards (see below)
|
||||
- Add tests for new functionality
|
||||
- Update documentation as needed
|
||||
- Make sure your changes don't break existing functionality
|
||||
|
||||
### 4. Commit Your Changes
|
||||
|
||||
We follow conventional commit standards. Format your commit messages as:
|
||||
|
||||
```
|
||||
type(scope): description
|
||||
|
||||
[optional body]
|
||||
|
||||
[optional footer]
|
||||
```
|
||||
|
||||
**Types:**
|
||||
|
||||
- `feat`: A new feature
|
||||
- `fix`: A bug fix
|
||||
- `docs`: Documentation only changes
|
||||
- `style`: Changes that do not affect the meaning of the code
|
||||
- `refactor`: A code change that neither fixes a bug nor adds a feature
|
||||
- `test`: Adding missing tests or correcting existing tests
|
||||
- `chore`: Changes to the build process or auxiliary tools
|
||||
|
||||
**Examples:**
|
||||
Commits follow [Conventional Commits](https://www.conventionalcommits.org/), enforced by a
|
||||
`commit-msg` hook:
|
||||
|
||||
```bash
|
||||
git commit -m "feat(api): add new dialectic endpoint for user insights"
|
||||
git commit -m "fix(db): resolve connection pool timeout issue"
|
||||
git commit -m "docs(readme): update installation instructions"
|
||||
```
|
||||
|
||||
### 5. Submit a Pull Request
|
||||
Types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`.
|
||||
|
||||
1. Push your branch to your fork:
|
||||
### Pre-commit hooks
|
||||
|
||||
```bash
|
||||
git push origin your-branch-name
|
||||
```
|
||||
|
||||
2. Create a pull request on GitHub from your branch to the `main` branch
|
||||
|
||||
3. Fill out the pull request template with:
|
||||
- A clear description of what changes you've made
|
||||
- The motivation for the changes
|
||||
- Any relevant issue numbers (use "Closes #123" to auto-close issues)
|
||||
- Screenshots or examples if applicable
|
||||
|
||||
## Pre-commit Hooks
|
||||
|
||||
Honcho uses pre-commit hooks to enforce code quality and consistency. They run linting, formatting, type checking, and security scans before each commit.
|
||||
|
||||
### Installation
|
||||
Install them. CI runs the same checks, and it is much faster to find out locally.
|
||||
|
||||
```bash
|
||||
uv add --dev pre-commit
|
||||
uv run pre-commit install \
|
||||
--hook-type pre-commit \
|
||||
--hook-type commit-msg \
|
||||
--hook-type pre-push
|
||||
```
|
||||
|
||||
### What the hooks do
|
||||
At **commit** time: ruff lint and format, biome for TypeScript, basedpyright, bandit,
|
||||
markdownlint, and file hygiene. At **push** time: pytest, the alembic migration tests, and
|
||||
the SDK builds.
|
||||
|
||||
- **Code Quality** — Python linting and formatting (ruff), TypeScript linting (biome)
|
||||
- **Type Checking** — Static analysis with basedpyright
|
||||
- **Security** — Vulnerability scanning with bandit
|
||||
- **Documentation** — Markdown linting and license header checks
|
||||
- **Testing** — Automated test runs for Python and TypeScript
|
||||
- **File Hygiene** — Trailing whitespace, line endings, file size checks
|
||||
- **Commit Standards** — Conventional commit message validation
|
||||
That split matters — **a clean commit is not a clean push.** The test suite only runs at
|
||||
`pre-push`, so the first time you see test failures may be well after you thought you were
|
||||
done.
|
||||
|
||||
### Manual execution
|
||||
|
||||
Run against all files without committing:
|
||||
Run them by hand at any time:
|
||||
|
||||
```bash
|
||||
uv run pre-commit run --all-files
|
||||
uv run pre-commit run ruff --all-files
|
||||
```
|
||||
|
||||
Run a specific hook:
|
||||
Or the individual tools:
|
||||
|
||||
```bash
|
||||
uv run pre-commit run ruff --all-files
|
||||
uv run pre-commit run basedpyright --all-files
|
||||
uv run ruff check src/
|
||||
uv run ruff format src/
|
||||
uv run basedpyright
|
||||
```
|
||||
|
||||
## Coding Standards
|
||||
### Tests
|
||||
|
||||
### Python Code Style
|
||||
Write tests for new functionality, in the directory under `tests/` that mirrors the code you
|
||||
changed. Which layer you need depends on what you touched:
|
||||
|
||||
- Follow [PEP 8](https://www.python.org/dev/peps/pep-0008/) style guidelines
|
||||
- Use [ruff](https://docs.astral.sh/ruff/) for linting and code formatting
|
||||
- Use type hints where possible
|
||||
- Write docstrings for functions and classes using Google style docstrings
|
||||
| What you changed | What to run |
|
||||
| --- | --- |
|
||||
| Anything in `src/` | Unit tests in the matching `tests/` tree — `uv run pytest tests/...` |
|
||||
| Deriver, dialectic, dreamer, or the LLM path | Unit tests, and consider `tests/live_llm/` (gated behind `--live-llm`) |
|
||||
| Queue behavior, config hierarchy, multi-turn flows, SDK contracts | `uv run python -m tests.unified.run` |
|
||||
| A `/v3` endpoint or deriver queue behavior | Actually run the stack and exercise it — not just pytest |
|
||||
| A migration | `uv run python scripts/run_alembic_tests.py`; every revision needs a test file |
|
||||
|
||||
### Code Organization
|
||||
|
||||
- Keep functions focused and single-purpose
|
||||
- Use meaningful variable and function names
|
||||
- Add comments for complex logic
|
||||
- Follow existing patterns in the codebase
|
||||
|
||||
### Testing
|
||||
|
||||
- Write unit tests for new functionality
|
||||
- Ensure existing tests pass before submitting
|
||||
- Use descriptive test names that explain what is being tested
|
||||
- Mock external dependencies appropriately
|
||||
The TypeScript SDK tests need a running server with a database and Redis, which pytest
|
||||
orchestrates. Run them with `uv run pytest tests/ -k typescript` from the repo root —
|
||||
`bun test` on its own will fail. To type-check the SDK alone:
|
||||
`cd sdks/typescript && bun run tsc --noEmit`.
|
||||
|
||||
### Documentation
|
||||
|
||||
- Update relevant documentation for new features
|
||||
- Include examples in docstrings where helpful
|
||||
- Keep README and other docs up to date with changes
|
||||
Update docs in the same PR when you change a public surface: `/v3` endpoints, SDK exports,
|
||||
or anything in `config.toml` / settings. Docs live in `docs/v3/`, and new pages need an entry
|
||||
in `docs/docs.json` or they will not appear in the nav.
|
||||
|
||||
## Review Process
|
||||
## Opening the pull request
|
||||
|
||||
1. **Automated checks** - Your PR will run through automated checks including tests and linting
|
||||
2. **Project maintainer review** - A project maintainer will review your code for:
|
||||
- Code quality and adherence to standards
|
||||
- Functionality and correctness
|
||||
- Test coverage
|
||||
- Documentation completeness
|
||||
3. **Discussion and iteration** - You may be asked to make changes or clarifications
|
||||
4. **Approval and merge** - Once approved, your PR will be merged into `main`
|
||||
### Leave "Allow edits by maintainers" checked
|
||||
|
||||
## Types of Contributions
|
||||
This is the single most useful thing you can do to get your PR merged quickly.
|
||||
|
||||
We welcome various types of contributions:
|
||||
Most contributor PRs arrive nearly right, needing a rename, a missing test, or a lint fix.
|
||||
If we can push that commit ourselves, it merges the same day. If we cannot, it becomes a
|
||||
review comment, and then we wait — sometimes for weeks — for a round trip on a two-line
|
||||
change.
|
||||
|
||||
- **Bug fixes** - Help us squash bugs and improve stability
|
||||
- **New features** - Add functionality that benefits the community
|
||||
- **Documentation** - Improve or expand our documentation
|
||||
- **Tests** - Increase test coverage and reliability
|
||||
- **Performance improvements** - Help make Honcho faster and more efficient
|
||||
- **Examples and tutorials** - Help other developers use Honcho
|
||||
GitHub checks the box by default when you fork. Leave it checked.
|
||||
|
||||
## Issue Reporting
|
||||
One caveat worth knowing: **the option does not exist on forks owned by an organization.**
|
||||
If you have the choice, fork from your personal account.
|
||||
|
||||
When reporting bugs or requesting features:
|
||||
### Fill out the template
|
||||
|
||||
1. Check if the issue already exists
|
||||
2. Use the appropriate [issue template](https://github.com/plastic-labs/honcho/issues/new/choose) (bug, memory/recall quality, feature, integration, or documentation)
|
||||
3. Provide clear reproduction steps for bugs
|
||||
4. Include relevant environment information (managed vs self-hosted, server version, SDK)
|
||||
5. Be specific about expected vs actual behavior
|
||||
6. Redact secrets, JWTs, and production user content
|
||||
`.github/pull_request_template.md` asks for a description, proofs, and the issue checkbox.
|
||||
|
||||
## Questions and Support
|
||||
"Proofs" means evidence the change works: the command you ran and its result, a log snippet,
|
||||
a screenshot, the failing case before and after. This is the section that most determines
|
||||
how fast your PR gets reviewed. Do not add sections to the template.
|
||||
|
||||
- **General questions** - Join our [Discord](https://discord.gg/honcho)
|
||||
- **Bug reports** - GitHub issues → Bug report template
|
||||
- **Memory / recall quality** - GitHub issues → Memory / recall quality template
|
||||
- **Feature requests** - GitHub issues → Feature request template
|
||||
- **Integrations / plugins / app-store listings** - GitHub issues → Integration request template
|
||||
- **Documentation issues** - GitHub issues → Documentation issue template
|
||||
- **Security issues** - Report **privately** only — see [`SECURITY.md`](./SECURITY.md) (GitHub Private Vulnerability Reporting or email). Do not open a public issue.
|
||||
Include `Fixes #123` so the issue link is machine-readable — the automated gate reads the PR
|
||||
body.
|
||||
|
||||
### Review
|
||||
|
||||
1. Automated checks run — tests, linting, static analysis, and the issue gate.
|
||||
2. A maintainer reviews for correctness, test coverage, and fit with the surrounding code.
|
||||
`.github/CODEOWNERS` routes the request to whoever owns the area you touched.
|
||||
3. You may be asked for changes. Or we may just push them, if you left edits enabled.
|
||||
4. Once approved, we merge to `main`.
|
||||
|
||||
If a PR goes quiet, nudge us in [Discord](https://discord.gg/honcho).
|
||||
|
||||
## Reporting bugs and requesting features
|
||||
|
||||
Use the [issue templates](https://github.com/plastic-labs/honcho/issues/new/choose). There is
|
||||
one per kind of report, and picking the right one is most of what gets an issue triaged
|
||||
quickly:
|
||||
|
||||
- **Bug report** — something is broken or behaves incorrectly
|
||||
- **Memory / recall quality** — the deriver or dialectic returns poor, wrong, or missing context
|
||||
- **Feature request** — a new capability or API surface
|
||||
- **Integration request** — plugins, framework integrations, app-store listings
|
||||
- **Documentation issue** — anything wrong or missing in the docs
|
||||
- **General questions** — not an issue at all; ask in [Discord](https://discord.gg/honcho)
|
||||
|
||||
Before opening one, search existing issues, including closed ones.
|
||||
|
||||
A good bug report has the Honcho version or commit, whether you are self-hosted or on
|
||||
`api.honcho.dev`, the steps to reproduce, and what you expected instead. If it involves the
|
||||
deriver, logs from the worker process are usually the thing we ask for first.
|
||||
|
||||
**Redact before you post.** Issues are public, and Honcho stores conversational data — strip
|
||||
API keys, JWTs, and production user content out of any log or payload you attach.
|
||||
|
||||
## Security
|
||||
|
||||
Do not open a public issue for a suspected vulnerability. Report it privately through
|
||||
[GitHub Private Vulnerability Reporting](https://github.com/plastic-labs/honcho/security/advisories/new),
|
||||
which is the preferred channel, or by email. See [SECURITY.md](./SECURITY.md) for what to
|
||||
include, and note that Honcho does not operate a bug bounty.
|
||||
|
||||
## License
|
||||
|
||||
By contributing to Honcho, you agree that your contributions will be licensed under the same [AGPL-3.0 License](./LICENSE) that covers the project.
|
||||
By contributing to Honcho, you agree that your contributions will be licensed under the same
|
||||
[AGPL-3.0 License](./LICENSE) that covers the project.
|
||||
|
||||
Thank you for helping make Honcho better! 🫡
|
||||
|
|
|
|||
70
README.md
70
README.md
|
|
@ -458,75 +458,15 @@ Contributors: see [`CONTRIBUTING.md`](./CONTRIBUTING.md) for pre-commit setup. D
|
|||
|
||||
Honcho uses a flexible configuration system that supports both TOML files and environment variables. Configuration values are loaded in priority order: **environment variables > `.env` file > `config.toml` > defaults**.
|
||||
|
||||
<!-- markdownlint-disable MD033 -->
|
||||
<details>
|
||||
<summary>Full configuration reference</summary>
|
||||
|
||||
### Using config.toml
|
||||
|
||||
Copy the example configuration file to get started:
|
||||
Copy the example file to get started:
|
||||
|
||||
```bash
|
||||
cp config.toml.example config.toml
|
||||
```
|
||||
|
||||
Then modify the values as needed. The TOML file is organized into sections:
|
||||
The file is organized by subsystem — `[app]`, `[db]`, `[auth]`, `[cache]`, `[llm]`, `[deriver]`, `[dialectic]`, `[summary]`, `[dream]`, `[peer_card]`, `[webhook]`, `[metrics]`, `[telemetry]`, `[vector_store]`, and `[sentry]`. Any value can be overridden by an environment variable named `{SECTION}_{KEY}`, using `__` for nesting (`DIALECTIC_LEVELS__low__MODEL_CONFIG__MODEL`), or just `{KEY}` for app-level settings.
|
||||
|
||||
- `[app]` - Application-level settings (log level, session limits, embedding settings, namespace)
|
||||
- `[db]` - Database connection and pool settings
|
||||
- `[auth]` - Authentication configuration
|
||||
- `[cache]` - Redis cache configuration
|
||||
- `[llm]` - LLM provider API keys and general settings
|
||||
- `[deriver]` - Background worker settings and representation configuration
|
||||
- `[peer_card]` - Peer card generation settings
|
||||
- `[dialectic]` - Chat Endpoint configuration with per-level reasoning settings
|
||||
- `[summary]` - Session summarization settings
|
||||
- `[dream]` - Dream processing configuration (including specialist models and surprisal settings)
|
||||
- `[webhook]` - Webhook configuration
|
||||
- `[metrics]` - Prometheus pull-based metrics
|
||||
- `[telemetry]` - CloudEvents telemetry for analytics
|
||||
- `[vector_store]` - Vector store configuration (pgvector, turbopuffer, or lancedb)
|
||||
- `[sentry]` - Error tracking and monitoring settings
|
||||
|
||||
### Using Environment Variables
|
||||
|
||||
All configuration values can be overridden using environment variables. The environment variable names follow this pattern:
|
||||
|
||||
- `{SECTION}_{KEY}` for top-level section settings
|
||||
- Use `__` inside `{KEY}` for nested settings
|
||||
- Just `{KEY}` for app-level settings
|
||||
|
||||
Examples:
|
||||
|
||||
- `DB_CONNECTION_URI` - Database connection string
|
||||
- `AUTH_JWT_SECRET` - JWT secret key
|
||||
- `DERIVER_MODEL_CONFIG__TRANSPORT` - Transport for the background deriver
|
||||
- `SUMMARY_MODEL_CONFIG__MODEL` - Summary model override
|
||||
- `DIALECTIC_LEVELS__low__MODEL_CONFIG__MODEL` - Model for low reasoning level
|
||||
- `LOG_LEVEL` - Application log level
|
||||
- `METRICS_ENABLED` - Enable Prometheus metrics
|
||||
- `TELEMETRY_ENABLED` - Enable CloudEvents telemetry
|
||||
|
||||
### Example
|
||||
|
||||
If you have this in `config.toml`:
|
||||
|
||||
```toml
|
||||
[db]
|
||||
CONNECTION_URI = "postgresql+psycopg://localhost/honcho_dev"
|
||||
POOL_SIZE = 10
|
||||
```
|
||||
|
||||
You can override just the connection URI in production:
|
||||
|
||||
```bash
|
||||
export DB_CONNECTION_URI="postgresql+psycopg://prod-server/honcho_prod"
|
||||
```
|
||||
|
||||
The application will use the production connection URI while keeping the pool size from config.toml.
|
||||
|
||||
</details>
|
||||
<!-- markdownlint-enable MD033 -->
|
||||
See the [configuration reference](https://honcho.dev/docs/v3/contributing/configuration) for every available option, and [`.env.template`](./.env.template) for an annotated list of environment variables.
|
||||
|
||||
## Architecture
|
||||
|
||||
|
|
@ -680,7 +620,9 @@ See the [SDK Reference](https://honcho.dev/docs/v3/documentation/reference/sdk)
|
|||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions to Honcho! Please read our [Contributing Guide](./CONTRIBUTING.md) for details on our development process, coding conventions, and how to submit pull requests.
|
||||
We welcome contributions to Honcho. One thing to know before you start: **pull requests must be linked to an issue carrying the `maintainer-approved` label**, or they are closed automatically. [Browse the approved queue](https://github.com/plastic-labs/honcho/issues?q=is%3Aissue+is%3Aopen+label%3Amaintainer-approved), or make your case in [Discord](http://discord.gg/honcho) — that is where maintainers are most active.
|
||||
|
||||
See [CONTRIBUTING.md](./CONTRIBUTING.md) for the full process, an architecture walkthrough, and a map of where to change what. For vulnerabilities, see [SECURITY.md](./SECURITY.md) — note that Honcho does not operate a bug bounty.
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
|||
75
SECURITY.md
75
SECURITY.md
|
|
@ -1,31 +1,72 @@
|
|||
# Security Policy
|
||||
|
||||
## Reporting a vulnerability
|
||||
## Supported Versions
|
||||
|
||||
**Do not file a public GitHub issue for security vulnerabilities.**
|
||||
The `main` branch of this repo maps to the latest canary version of Honcho. To see which versions are supported please refer to the git tags in the repo or the [compatibility guide](https://honcho.dev/docs/changelog/compatibility-guide).
|
||||
|
||||
Please report security issues privately using one of:
|
||||
## Reporting a Vulnerability
|
||||
|
||||
1. **[GitHub Private Vulnerability Reporting](https://github.com/plastic-labs/honcho/security/advisories/new)** (preferred)
|
||||
2. Email **<support@honcho.dev>** with subject line `[SECURITY] …`
|
||||
Do not open a public issue for a suspected vulnerability. Report it privately through one of:
|
||||
|
||||
Include as much of the following as you can:
|
||||
1. **[GitHub Private Vulnerability Reporting](https://github.com/plastic-labs/honcho/security/advisories/new)** — preferred; it keeps the report, our replies, and any fix coordinated in one place.
|
||||
2. Email [support@honcho.dev](mailto:support@honcho.dev) with `[SECURITY]` in the subject.
|
||||
|
||||
- Description of the issue and its impact
|
||||
- Steps to reproduce, or a proof of concept
|
||||
- Affected component (API, deriver, auth/JWT, SDK, managed offering, etc.)
|
||||
- Honcho version or image tag, and whether you are on managed or self-hosted
|
||||
Include as much of the following as you have:
|
||||
|
||||
Honcho stores conversational data and peer representations. **Do not** attach production user content, API keys, JWTs, or other secrets to a report unless we explicitly ask for a redacted sample.
|
||||
- **Version** — a git commit SHA, or the release tag you are running
|
||||
- **Deployment** — self-hosted or the managed service at `api.honcho.dev`
|
||||
- **Reproduction** — the exact steps, requests, or script that trigger it
|
||||
- **Proof of concept** — the smallest thing that demonstrates the issue actually works
|
||||
- **Impact** — what an attacker gains, and what they need to already have to get it
|
||||
- **How you found it** — manual review, fuzzing, a scanner, or model-assisted analysis
|
||||
|
||||
## What to expect
|
||||
Reports with a working proof of concept get looked at first. A report that only describes a
|
||||
theoretical problem is much slower for us to act on, because we have to build the repro
|
||||
ourselves before we can confirm anything.
|
||||
|
||||
We will acknowledge valid reports as soon as we can and will keep you updated on remediation status. Please give us a reasonable window to investigate and fix before any public disclosure.
|
||||
Honcho stores conversational data and peer representations. **Do not attach production user
|
||||
content, API keys, or JWTs** to a report — if we need a sample, we will ask for a redacted
|
||||
one.
|
||||
|
||||
## Supported versions
|
||||
## Testing
|
||||
|
||||
Security fixes are applied to the latest release on `main` and, when practical, to the most recent tagged release line. Older versions may not receive backports.
|
||||
Test against an instance you operate. Do not run security testing against `api.honcho.dev`
|
||||
or against any Honcho deployment that is not yours — self-hosting is a first-class path and
|
||||
takes a few minutes to set up, see [Self-hosting](./README.md#self-hosting).
|
||||
|
||||
## Non-security bugs
|
||||
## What to Expect
|
||||
|
||||
For ordinary bugs, memory/recall quality issues, and feature requests, use the [issue templates](https://github.com/plastic-labs/honcho/issues/new/choose).
|
||||
We will acknowledge your report and tell you whether we consider it in scope. If it is, we
|
||||
will let you know when a fix ships.
|
||||
|
||||
We do not commit to a response SLA, we do not coordinate CVE assignment on request, and we
|
||||
do not operate a disclosure timeline you can hold us to. This is a small team.
|
||||
|
||||
## Out of Scope
|
||||
|
||||
The following are not treated as vulnerabilities. Reports consisting only of these will be
|
||||
closed without a detailed response:
|
||||
|
||||
- Automated scanner output with no working proof of concept
|
||||
- Model-generated findings that have not been verified by a human against a running instance
|
||||
- Missing security headers or TLS configuration with no demonstrated exploit
|
||||
- Rate limiting, or resource exhaustion with no demonstrated impact beyond your own instance
|
||||
- Vulnerabilities in dependencies with no demonstrated exploit path through Honcho
|
||||
- Configuration weaknesses that require an already-compromised host, or that come from
|
||||
deliberately insecure settings (for example running with `AUTH_USE_AUTH=false`, which is
|
||||
the documented local-development default and is not intended for a public deployment)
|
||||
- Social engineering, phishing, and physical access
|
||||
|
||||
For ordinary bugs, memory or recall quality problems, and feature requests, use the
|
||||
[issue templates](https://github.com/plastic-labs/honcho/issues/new/choose) instead.
|
||||
|
||||
## No Bug Bounty
|
||||
|
||||
The Honcho project does not offer any rewards for reported bugs or
|
||||
vulnerabilities. We do not aid security researchers to get such rewards for
|
||||
Honcho problems from other sources.
|
||||
|
||||
A bug bounty gives people too strong incentives to find and make up "problems"
|
||||
in bad faith that cause overload and abuse.
|
||||
|
||||
We still appreciate and value valid vulnerability reports.
|
||||
|
|
|
|||
|
|
@ -3,174 +3,354 @@ title: 'Contributing Guidelines'
|
|||
icon: 'handshake'
|
||||
---
|
||||
|
||||
Thank you for your interest in contributing to Honcho! This guide outlines the process for contributing to the project and our development conventions.
|
||||
{/* This file mirrors CONTRIBUTING.md in the repo root. Update both. */}
|
||||
|
||||
## Getting Started
|
||||
Thanks for your interest in contributing. This guide covers how work gets accepted, how
|
||||
Honcho is put together, and what a mergeable pull request looks like.
|
||||
|
||||
Before you start contributing, please:
|
||||
Honcho is a small team maintaining a project that gets more proposals than we can review.
|
||||
The rules below exist so that the work you do has somewhere to land — not to keep you out.
|
||||
|
||||
1. **Set up your development environment** - Follow the [Local Development guide](https://github.com/plastic-labs/honcho/blob/main/CONTRIBUTING.md#local-development) in the Honcho repository to get Honcho running locally.
|
||||
## Before you write code
|
||||
|
||||
2. **Join our community** - Feel free to join us in our [Discord](http://discord.gg/honcho) to discuss your changes, get help, or ask questions.
|
||||
**Every pull request needs an issue, and that issue needs the `maintainer-approved` label.**
|
||||
|
||||
3. **Review existing issues** - Check the [issues tab](https://github.com/plastic-labs/honcho/issues) to see what's already being worked on or to find something to contribute to.
|
||||
A pull request that is not linked to an issue, or that is linked to an issue without the
|
||||
label, will be closed without review. This is automated. We do this because an unreviewable
|
||||
backlog helps nobody: a PR against an unapproved issue is work you did that we may not be
|
||||
able to merge, no matter how good it is.
|
||||
|
||||
## Contribution Workflow
|
||||
So, in order:
|
||||
|
||||
### 1. Fork and Clone
|
||||
1. **Find approved work.** Browse
|
||||
[issues labelled `maintainer-approved`](https://github.com/plastic-labs/honcho/issues?q=is%3Aissue+is%3Aopen+label%3Amaintainer-approved).
|
||||
That label is the queue of things we have agreed should be built. Anything in it is fair
|
||||
game — comment on the issue to claim it.
|
||||
|
||||
1. Fork the repository on GitHub
|
||||
2. Clone your fork locally:
|
||||
```bash
|
||||
git clone https://github.com/YOUR_USERNAME/honcho.git
|
||||
cd honcho
|
||||
```
|
||||
3. Add the upstream repository as a remote:
|
||||
```bash
|
||||
git remote add upstream https://github.com/plastic-labs/honcho.git
|
||||
```
|
||||
2. **Or open an issue and get it approved.** Use the
|
||||
[issue templates](https://github.com/plastic-labs/honcho/issues/new/choose). Maintainers
|
||||
triage and apply the label.
|
||||
|
||||
### 2. Create a Branch
|
||||
3. **If you feel strongly about an issue, come to [Discord](https://discord.gg/honcho).**
|
||||
This is the fastest path by a wide margin. Maintainers are more active there than in the
|
||||
issue tracker, and a five-minute conversation about what you want to build usually
|
||||
resolves whether it fits before either side spends real time on it.
|
||||
|
||||
Create a new branch for your feature or bug fix:
|
||||
4. **Then open the PR**, with `Fixes #123` in the body.
|
||||
|
||||
Small exceptions we will not be pedantic about: fixing a typo, a broken link, or an
|
||||
obviously wrong code sample. Open the PR, explain it in one line, and we will sort out the
|
||||
issue linkage.
|
||||
|
||||
## What gets prioritized
|
||||
|
||||
Roughly, work on Honcho falls along these axes. Knowing which one your idea sits on tells
|
||||
you a lot about how likely it is to get approved.
|
||||
|
||||
| Axis | What it covers |
|
||||
| --- | --- |
|
||||
| **Observability** | Understanding how Honcho behaves in production — telemetry, tracing, CloudEvents, metrics. |
|
||||
| **Memory quality** | Better conclusions from the same input — the deriver, dreamer, and dialectic; eval results. |
|
||||
| **Developer experience** | Fitting cleanly into more application architectures — SDKs, scopes, composable peers, the CLI. |
|
||||
| **Breadth of input** | Widening what Honcho can ingest and represent — multimodal and non-conversational data. |
|
||||
| **Ubiquity** | Reachable wherever a developer already works — integrations, self-hosting, alternate vector-store and inference backends, local-first defaults. |
|
||||
| **Reliability and cost** | Trustworthy in production — connection and concurrency hardening, queue throughput, cost per token. |
|
||||
|
||||
In practice, **Ubiquity** and **Developer experience** are where outside contributions land
|
||||
most easily. A new integration, a self-hosting rough edge, a vector-store or inference
|
||||
backend, an SDK ergonomics fix — these are additive and rarely collide with work already in
|
||||
flight.
|
||||
|
||||
Changes to the reasoning pipeline itself — deriver prompts, dialectic tool design, dreamer
|
||||
strategy — are the hardest to accept from outside. Not because they are unwelcome, but
|
||||
because they are measured against eval results we run internally, and they frequently
|
||||
conflict with in-flight work. Talk to us in Discord first, always.
|
||||
|
||||
## If you're an agent
|
||||
|
||||
If you are a coding agent working on this repository, read this section before writing code.
|
||||
The most common failure we see is a well-formed, well-tested pull request against an issue
|
||||
that was never approved. That gets closed, and the work is wasted.
|
||||
|
||||
- **Check the gate first.** Before writing code:
|
||||
|
||||
```bash
|
||||
gh issue view <N> --repo plastic-labs/honcho --json number,title,state,labels
|
||||
```
|
||||
|
||||
Stop if there is no issue number, if the issue is closed, or if `maintainer-approved` is
|
||||
not in the labels. Report that to the person you are working with instead of proceeding.
|
||||
|
||||
- **Do not open a PR in order to establish the issue link afterwards.** The issue comes
|
||||
first.
|
||||
|
||||
- **Do not report checks you did not run.** If you did not execute the test command, say so.
|
||||
A PR body claiming a green run that did not happen costs a maintainer more time than no
|
||||
claim at all.
|
||||
|
||||
- **Use the checklist.** [`skills/pre-pr/SKILL.md`](https://github.com/plastic-labs/honcho/blob/main/skills/pre-pr/SKILL.md) in this repo
|
||||
encodes the gate, the test-layer matrix, and the PR body format. If your harness supports
|
||||
skills, invoke it rather than reimplementing the checks.
|
||||
|
||||
## How Honcho works
|
||||
|
||||
Enough architecture to find your way around. For the user-facing model — what a Peer is, what
|
||||
`get_context` returns — see [Core Concepts](https://github.com/plastic-labs/honcho#core-concepts) and the
|
||||
[documentation](https://honcho.dev/docs/).
|
||||
|
||||
### Two processes
|
||||
|
||||
Honcho runs as two cooperating processes over a shared Postgres database and Redis cache.
|
||||
|
||||
| | API server | Deriver worker |
|
||||
| --- | --- | --- |
|
||||
| Start | `uv run fastapi dev src/main.py` | `uv run python -m src.deriver` |
|
||||
| Entry | `src/main.py` | `src/deriver/__main__.py` |
|
||||
| Does | Serves HTTP, enqueues background work, returns immediately | Consumes the queue: Deriver, Summarizer, Dreamer, Reconciler |
|
||||
| Hosts | The Dialectic agent, inline on the request path | Everything else |
|
||||
|
||||
The split is the load-bearing design decision: **an HTTP request never blocks on LLM work**,
|
||||
with the single exception of the Dialectic chat endpoint, which is synchronous by nature.
|
||||
If you are adding something slow, it belongs in the worker.
|
||||
|
||||
The deriver is a separate process. If messages go in and nothing ever comes out, the usual
|
||||
cause is that nobody started it.
|
||||
|
||||
### The path of a message
|
||||
|
||||
Worth tracing once, because it crosses most of the codebase:
|
||||
|
||||
1. `POST /v3/workspaces/{w}/sessions/{s}/messages` lands in `src/routers/messages.py`.
|
||||
2. The row is written, then `enqueue()` in `src/deriver/enqueue.py` creates `queue_item`
|
||||
rows — one set of work per observing peer.
|
||||
3. `src/deriver/queue_manager.py` polls the queue, claiming work units so that messages in a
|
||||
session are processed in order.
|
||||
4. `process_item()` in `src/deriver/consumer.py` dispatches on task type — representation,
|
||||
summary, deletion, reconciliation.
|
||||
5. For a representation task, `process_representation_tasks_batch()` in
|
||||
`src/deriver/deriver.py` makes **one structured-output LLM call for the whole batch** and
|
||||
writes the resulting conclusions into the collection keyed by the
|
||||
`(observer, observed)` peer pair.
|
||||
6. Later, `src/dialectic/` reads those conclusions back at recall time to answer a chat
|
||||
request.
|
||||
|
||||
Embedding is deliberately *not* on this path. `MessageEmbedding` rows are written with
|
||||
`sync_state='pending'` and embedded asynchronously by the Reconciler
|
||||
(`src/reconciler/sync_vectors.py`), which runs on a scheduler inside the deriver process.
|
||||
|
||||
### The four agents
|
||||
|
||||
They share tool definitions in `src/utils/agent_tools.py` and the provider-agnostic LLM
|
||||
client in `src/llm/`. Each has its own `MODEL_CONFIG` with a fallback chain in
|
||||
`src/config.py`.
|
||||
|
||||
| Agent | Where | Shape |
|
||||
| --- | --- | --- |
|
||||
| **Deriver** | `src/deriver/` | A single structured-output call per message batch. Not a tool loop — this is a deliberate cost and latency tradeoff. |
|
||||
| **Dialectic** | `src/dialectic/` | The one tool-using agent on the request path. Loops over tools until it can answer. Five reasoning tiers from `minimal` to `max`, each with its own model and tool set. |
|
||||
| **Dreamer** | `src/dreamer/` | Off-queue consolidation. Two specialist phases (deduction, then induction) that build reasoning trees over existing conclusions. |
|
||||
| **Summarizer** | `src/utils/summarizer.py` | Direct LLM call, no tools. Two tiers — short and long summaries at different message counts. |
|
||||
|
||||
Prompts live in `src/deriver/prompts.py`, `src/dialectic/prompts.py`, and
|
||||
`src/dreamer/specialists.py`.
|
||||
|
||||
### A note on naming
|
||||
|
||||
What the public API and documentation call **conclusions** are called **observations**
|
||||
throughout the code — `create_observations`, `get_observation_context`, and so on. Likewise
|
||||
**collections** and **documents** are internal storage concepts that are not exposed
|
||||
directly through the API. Do not rename across that boundary in a drive-by change; the
|
||||
public and internal vocabularies are being reconciled deliberately.
|
||||
|
||||
## Where to change what
|
||||
|
||||
| I want to change... | Start here |
|
||||
| --- | --- |
|
||||
| An HTTP endpoint | `src/routers/` — one module per resource |
|
||||
| A database query | `src/crud/` — mirrors the router layout |
|
||||
| The database schema | `src/models.py`, plus a migration in `migrations/versions/` |
|
||||
| A configuration value | `src/config.py`, and add it to `config.toml.example` and `.env.template` |
|
||||
| A tool an agent can call | `src/utils/agent_tools.py` — definitions plus the per-agent tool lists |
|
||||
| A prompt | `src/deriver/prompts.py`, `src/dialectic/prompts.py`, `src/dreamer/specialists.py` |
|
||||
| LLM provider behavior | `src/llm/backends/` — `anthropic.py`, `gemini.py`, `openai.py` |
|
||||
| Embeddings or vector storage | `src/embedding_client.py`, `src/vector_store/` |
|
||||
| Telemetry or metrics | `src/telemetry/` — see the notes in `CLAUDE.md` before adding an event type |
|
||||
| Authentication and scoping | `src/security.py`, `src/dependencies.py` |
|
||||
| The Python or TypeScript SDK | `sdks/python/`, `sdks/typescript/` |
|
||||
| The CLI | `honcho-cli/` |
|
||||
| The MCP server | `mcp/` |
|
||||
| Public documentation | `docs/v3/` — Mintlify; nav lives in `docs/docs.json` |
|
||||
|
||||
Tests in `tests/` mirror `src/`. `CLAUDE.md` at the repo root has more detail on house
|
||||
conventions, and is worth skimming even if you are not using an agent.
|
||||
|
||||
## Local setup
|
||||
|
||||
Get a stack running first — [Self-hosting](/v3/contributing/self-hosting) covers
|
||||
both the Docker path and a manual Postgres setup. Then, for development:
|
||||
|
||||
```bash
|
||||
uv sync # create the venv and install dependencies
|
||||
uv run alembic upgrade head # apply migrations
|
||||
```
|
||||
|
||||
Run both processes, in separate terminals:
|
||||
|
||||
```bash
|
||||
uv run fastapi dev src/main.py # API server, reloads on change
|
||||
uv run python -m src.deriver # background worker
|
||||
```
|
||||
|
||||
Everything Python goes through `uv run`. Redis is optional for local development; without it
|
||||
caching is simply disabled.
|
||||
|
||||
## Making the change
|
||||
|
||||
### Branches and commits
|
||||
|
||||
```bash
|
||||
git checkout -b feature/your-feature-name
|
||||
# or
|
||||
git checkout -b fix/your-bug-fix-name
|
||||
```
|
||||
|
||||
**Branch naming conventions:**
|
||||
- `feature/description` - for new features
|
||||
- `fix/description` - for bug fixes
|
||||
- `docs/description` - for documentation updates
|
||||
- `refactor/description` - for code refactoring
|
||||
- `test/description` - for adding or updating tests
|
||||
Prefixes: `feature/`, `fix/`, `docs/`, `refactor/`, `test/`.
|
||||
|
||||
### 3. Make Your Changes
|
||||
Commits follow [Conventional Commits](https://www.conventionalcommits.org/), enforced by a
|
||||
`commit-msg` hook:
|
||||
|
||||
- Write clean, readable code that follows our coding standards (see below)
|
||||
- Add tests for new functionality
|
||||
- Update documentation as needed
|
||||
- Make sure your changes don't break existing functionality
|
||||
|
||||
### 4. Commit Your Changes
|
||||
|
||||
We follow conventional commit standards. Format your commit messages as:
|
||||
|
||||
```
|
||||
type(scope): description
|
||||
|
||||
[optional body]
|
||||
|
||||
[optional footer]
|
||||
```
|
||||
|
||||
**Types:**
|
||||
- `feat`: A new feature
|
||||
- `fix`: A bug fix
|
||||
- `docs`: Documentation only changes
|
||||
- `style`: Changes that do not affect the meaning of the code
|
||||
- `refactor`: A code change that neither fixes a bug nor adds a feature
|
||||
- `test`: Adding missing tests or correcting existing tests
|
||||
- `chore`: Changes to the build process or auxiliary tools
|
||||
|
||||
**Examples:**
|
||||
```bash
|
||||
git commit -m "feat(api): add new dialectic endpoint for user insights"
|
||||
git commit -m "fix(db): resolve connection pool timeout issue"
|
||||
git commit -m "docs(readme): update installation instructions"
|
||||
```
|
||||
|
||||
### 5. Submit a Pull Request
|
||||
Types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`.
|
||||
|
||||
1. Push your branch to your fork:
|
||||
```bash
|
||||
git push origin your-branch-name
|
||||
```
|
||||
### Pre-commit hooks
|
||||
|
||||
2. Create a pull request on GitHub from your branch to the `main` branch
|
||||
Install them. CI runs the same checks, and it is much faster to find out locally.
|
||||
|
||||
3. Fill out the pull request template with:
|
||||
- A clear description of what changes you've made
|
||||
- The motivation for the changes
|
||||
- Any relevant issue numbers (use "Closes #123" to auto-close issues)
|
||||
- Screenshots or examples if applicable
|
||||
```bash
|
||||
uv run pre-commit install \
|
||||
--hook-type pre-commit \
|
||||
--hook-type commit-msg \
|
||||
--hook-type pre-push
|
||||
```
|
||||
|
||||
## Coding Standards
|
||||
At **commit** time: ruff lint and format, biome for TypeScript, basedpyright, bandit,
|
||||
markdownlint, and file hygiene. At **push** time: pytest, the alembic migration tests, and
|
||||
the SDK builds.
|
||||
|
||||
### Python Code Style
|
||||
That split matters — **a clean commit is not a clean push.** The test suite only runs at
|
||||
`pre-push`, so the first time you see test failures may be well after you thought you were
|
||||
done.
|
||||
|
||||
- Follow [PEP 8](https://www.python.org/dev/peps/pep-0008/) style guidelines
|
||||
- Use [Black](https://black.readthedocs.io/) for code formatting (we may add this to CI in the future)
|
||||
- Use type hints where possible
|
||||
- Write docstrings for functions and classes using Google style docstrings
|
||||
Run them by hand at any time:
|
||||
|
||||
### Code Organization
|
||||
```bash
|
||||
uv run pre-commit run --all-files
|
||||
uv run pre-commit run ruff --all-files
|
||||
```
|
||||
|
||||
- Keep functions focused and single-purpose
|
||||
- Use meaningful variable and function names
|
||||
- Add comments for complex logic
|
||||
- Follow existing patterns in the codebase
|
||||
Or the individual tools:
|
||||
|
||||
### Testing
|
||||
```bash
|
||||
uv run ruff check src/
|
||||
uv run ruff format src/
|
||||
uv run basedpyright
|
||||
```
|
||||
|
||||
- Write unit tests for new functionality
|
||||
- Ensure existing tests pass before submitting
|
||||
- Use descriptive test names that explain what is being tested
|
||||
- Mock external dependencies appropriately
|
||||
### Tests
|
||||
|
||||
Write tests for new functionality, in the directory under `tests/` that mirrors the code you
|
||||
changed. Which layer you need depends on what you touched:
|
||||
|
||||
| What you changed | What to run |
|
||||
| --- | --- |
|
||||
| Anything in `src/` | Unit tests in the matching `tests/` tree — `uv run pytest tests/...` |
|
||||
| Deriver, dialectic, dreamer, or the LLM path | Unit tests, and consider `tests/live_llm/` (gated behind `--live-llm`) |
|
||||
| Queue behavior, config hierarchy, multi-turn flows, SDK contracts | `uv run python -m tests.unified.run` |
|
||||
| A `/v3` endpoint or deriver queue behavior | Actually run the stack and exercise it — not just pytest |
|
||||
| A migration | `uv run python scripts/run_alembic_tests.py`; every revision needs a test file |
|
||||
|
||||
The TypeScript SDK tests need a running server with a database and Redis, which pytest
|
||||
orchestrates. Run them with `uv run pytest tests/ -k typescript` from the repo root —
|
||||
`bun test` on its own will fail. To type-check the SDK alone:
|
||||
`cd sdks/typescript && bun run tsc --noEmit`.
|
||||
|
||||
### Documentation
|
||||
|
||||
- Update relevant documentation for new features
|
||||
- Include examples in docstrings where helpful
|
||||
- Keep README and other docs up to date with changes
|
||||
Update docs in the same PR when you change a public surface: `/v3` endpoints, SDK exports,
|
||||
or anything in `config.toml` / settings. Docs live in `docs/v3/`, and new pages need an entry
|
||||
in `docs/docs.json` or they will not appear in the nav.
|
||||
|
||||
## Review Process
|
||||
## Opening the pull request
|
||||
|
||||
1. **Automated checks** - Your PR will run through automated checks including tests and linting
|
||||
2. **Project maintainer review** - A project maintainer will review your code for:
|
||||
- Code quality and adherence to standards
|
||||
- Functionality and correctness
|
||||
- Test coverage
|
||||
- Documentation completeness
|
||||
3. **Discussion and iteration** - You may be asked to make changes or clarifications
|
||||
4. **Approval and merge** - Once approved, your PR will be merged into `main`
|
||||
### Leave "Allow edits by maintainers" checked
|
||||
|
||||
## Types of Contributions
|
||||
This is the single most useful thing you can do to get your PR merged quickly.
|
||||
|
||||
We welcome various types of contributions:
|
||||
Most contributor PRs arrive nearly right, needing a rename, a missing test, or a lint fix.
|
||||
If we can push that commit ourselves, it merges the same day. If we cannot, it becomes a
|
||||
review comment, and then we wait — sometimes for weeks — for a round trip on a two-line
|
||||
change.
|
||||
|
||||
- **Bug fixes** - Help us squash bugs and improve stability
|
||||
- **New features** - Add functionality that benefits the community
|
||||
- **Documentation** - Improve or expand our documentation
|
||||
- **Tests** - Increase test coverage and reliability
|
||||
- **Performance improvements** - Help make Honcho faster and more efficient
|
||||
- **Examples and tutorials** - Help other developers use Honcho
|
||||
GitHub checks the box by default when you fork. Leave it checked.
|
||||
|
||||
## Issue Reporting
|
||||
One caveat worth knowing: **the option does not exist on forks owned by an organization.**
|
||||
If you have the choice, fork from your personal account.
|
||||
|
||||
When reporting bugs or requesting features:
|
||||
### Fill out the template
|
||||
|
||||
1. Check if the issue already exists
|
||||
2. Use the appropriate [issue template](https://github.com/plastic-labs/honcho/issues/new/choose) (bug, memory/recall quality, feature, integration, or documentation)
|
||||
3. Provide clear reproduction steps for bugs
|
||||
4. Include relevant environment information (managed vs self-hosted, server version, SDK)
|
||||
5. Be specific about expected vs actual behavior
|
||||
6. Redact secrets, JWTs, and production user content
|
||||
`.github/pull_request_template.md` asks for a description, proofs, and the issue checkbox.
|
||||
|
||||
## Questions and Support
|
||||
"Proofs" means evidence the change works: the command you ran and its result, a log snippet,
|
||||
a screenshot, the failing case before and after. This is the section that most determines
|
||||
how fast your PR gets reviewed. Do not add sections to the template.
|
||||
|
||||
- **General questions** - Join our [Discord](https://discord.gg/honcho)
|
||||
- **Bug reports** - GitHub issues → Bug report template
|
||||
- **Memory / recall quality** - GitHub issues → Memory / recall quality template
|
||||
- **Feature requests** - GitHub issues → Feature request template
|
||||
- **Integrations / plugins / app-store listings** - GitHub issues → Integration request template
|
||||
- **Documentation issues** - GitHub issues → Documentation issue template
|
||||
- **Security issues** - Report **privately** only — see [`SECURITY.md`](https://github.com/plastic-labs/honcho/blob/main/SECURITY.md) (GitHub Private Vulnerability Reporting or email). Do not open a public issue.
|
||||
Include `Fixes #123` so the issue link is machine-readable — the automated gate reads the PR
|
||||
body.
|
||||
|
||||
### Review
|
||||
|
||||
1. Automated checks run — tests, linting, static analysis, and the issue gate.
|
||||
2. A maintainer reviews for correctness, test coverage, and fit with the surrounding code.
|
||||
`.github/CODEOWNERS` routes the request to whoever owns the area you touched.
|
||||
3. You may be asked for changes. Or we may just push them, if you left edits enabled.
|
||||
4. Once approved, we merge to `main`.
|
||||
|
||||
If a PR goes quiet, nudge us in [Discord](https://discord.gg/honcho).
|
||||
|
||||
## Reporting bugs and requesting features
|
||||
|
||||
Use the [issue templates](https://github.com/plastic-labs/honcho/issues/new/choose). There is
|
||||
one per kind of report, and picking the right one is most of what gets an issue triaged
|
||||
quickly:
|
||||
|
||||
- **Bug report** — something is broken or behaves incorrectly
|
||||
- **Memory / recall quality** — the deriver or dialectic returns poor, wrong, or missing context
|
||||
- **Feature request** — a new capability or API surface
|
||||
- **Integration request** — plugins, framework integrations, app-store listings
|
||||
- **Documentation issue** — anything wrong or missing in the docs
|
||||
- **General questions** — not an issue at all; ask in [Discord](https://discord.gg/honcho)
|
||||
|
||||
Before opening one, search existing issues, including closed ones.
|
||||
|
||||
A good bug report has the Honcho version or commit, whether you are self-hosted or on
|
||||
`api.honcho.dev`, the steps to reproduce, and what you expected instead. If it involves the
|
||||
deriver, logs from the worker process are usually the thing we ask for first.
|
||||
|
||||
**Redact before you post.** Issues are public, and Honcho stores conversational data — strip
|
||||
API keys, JWTs, and production user content out of any log or payload you attach.
|
||||
|
||||
## Security
|
||||
|
||||
Do not open a public issue for a suspected vulnerability. Report it privately through
|
||||
[GitHub Private Vulnerability Reporting](https://github.com/plastic-labs/honcho/security/advisories/new),
|
||||
which is the preferred channel, or by email. See [SECURITY.md](https://github.com/plastic-labs/honcho/blob/main/SECURITY.md) for what
|
||||
to include, and note that Honcho does not operate a bug bounty.
|
||||
|
||||
## License
|
||||
|
||||
By contributing to Honcho, you agree that your contributions will be licensed under the same [AGPL-3.0 License](./license) that covers the project.
|
||||
By contributing to Honcho, you agree that your contributions will be licensed under the same
|
||||
[AGPL-3.0 License](./license) that covers the project.
|
||||
|
||||
Thank you for helping make Honcho better! 🫡
|
||||
|
|
|
|||
Loading…
Reference in New Issue