Contributing
How to file bugs, propose features, and submit PRs against `@pleach/core` and the sibling SKUs.
Every shipping @pleach/* package ships under
FSL-1.1-Apache-2.0 (Functional Source License with Apache 2.0
as the future license, auto-transitions to Apache 2.0 two years
after first stable publish): @pleach/core,
@pleach/tools, @pleach/react, @pleach/replay,
@pleach/sandbox, @pleach/base-tools, @pleach/langchain,
@pleach/compliance, @pleach/eval, @pleach/gateway,
@pleach/mcp, @pleach/coding-agent, @pleach/observe, and
@pleach/recipes. @pleach/trust-pack alone remains a reserved
npm name at 0.0.1 · UNLICENSED.
Contributions land through the standard GitHub workflow on each
package's repository. This page is the short version; the upstream
CONTRIBUTING.md in each package is the canonical source.
Where each package lives
| Package | Repository |
|---|---|
@pleach/core | github.com/pleachhq/core |
@pleach/tools | github.com/pleachhq/tools |
Other @pleach/* siblings | Repositories land as each SKU ships its first cut |
Issues and PRs land on the relevant package's repository.
Cross-cutting issues (something that spans two packages, or
something about the docs site itself) land on pleachhq/core
with a label indicating scope.
Filing a bug
A useful bug report has four sections:
- What you did — minimal reproduction. A failing test case
in
defineToolshape is ideal; a code snippet that constructs aSessionRuntimeand reproduces the issue is fine. - What you expected — what the contract says should happen.
- What actually happened — observed behavior, including stack trace and any structured error code (1xxx–7xxx).
- Environment —
@pleach/coreversion, Node version, runtime (Node / Edge / Browser), provider, storage adapter.
Bugs without a reproduction are hard to fix. If the bug is non-deterministic, say so explicitly — the substrate's determinism contracts exist so non-determinism is unusual, and calling it out helps triage.
Proposing a feature
A feature proposal is an issue with a feature label that
answers four questions:
- What problem are you solving? Not "I want X" — "X solves Y, which I can't solve today because Z."
- What does the API surface look like? A type signature is enough; a code sample is better.
- What does it interact with? Which existing primitives
(
SessionRuntime, channels, the audit ledger) does the feature touch? - What can't you build today without this? Concrete; the substrate is intentionally small and resists scope creep.
Features that fit the existing contracts (a new built-in tool, a new prompt section primitive, a new stream observer verdict for an existing concern) land quickly. Features that change the substrate's structural commitments (the lattice, the singleton seam, the family lock) get deep design discussion first.
Submitting a PR
Three checks every PR runs through:
npm test— the substrate's test suite, including determinism fixtures.npm run lint— the lint rules that enforce structural invariants (lint:harness-boundary,lint:callclass-literals, etc.).npm run audit:*— the audit gates that catch wire-format drift and out-of-lattice edges.
A PR that fails any of these is in the wrong shape. The lint rules are the substrate's invariants in CI form — adjust the code, not the lint config.
Commit shape
The upstream uses conventional commit prefixes. Common ones:
| Prefix | Use |
|---|---|
feat: | New feature |
fix: | Bug fix |
docs: | Documentation only |
refactor: | Code change without behavior change |
perf: | Performance improvement |
test: | Test-only change |
chore: | Build / tooling |
Commits are squashed at merge; the squashed message takes the PR title's shape. Aim for one logical change per PR.
Test coverage
New features ship with tests. The substrate's test suite has three layers:
| Layer | What it tests |
|---|---|
| Unit | Pure functions (computeFingerprint, reducers, canonicalize) |
| Integration | Runtime construction + executeMessage with mock providers |
| Determinism | Recorded fixtures replayed for byte equality |
A feature touching the fingerprint, the audit ledger, or the channel reducers belongs in all three layers. A feature touching only a peripheral surface (a new React hook, a new query helper) belongs in unit + integration.
Docs updates
Public-API changes land with docs updates in the same PR. The
docs site here (pleachhq/getpleach) is a separate repository;
small API additions land as a docs PR after the package merges,
or as a single PR that updates the package's own README +
inline JSDoc.
For substantial new surfaces (a new exported subpath, a new plugin hook), the docs site gets a new page. The CLAUDE.md in this repo documents the voice and structure conventions.
Local development
git clone https://github.com/pleachhq/core
cd core
npm install
npm testThe substrate uses the standard npm workflow — no special build
tooling, no monorepo wrangler. The examples/minimal-agent and
examples/host-adapter directories run against the local
source.
cd examples/minimal-agent
npm install
HARNESS_MOCK_MODE=true node index.mjsFor changes that touch the schema bundle:
npm run schema:validate # checks SQL bundle integrity
npm run schema:apply-test # applies against a test DBThe schema bundle's additive rule (no edits to existing files, new files only) is enforced by the validator.
What the substrate intentionally doesn't accept
A short list of patterns that consistently get rejected. Not because the work is bad — because the substrate's contracts foreclose them.
| Pattern | Why rejected |
|---|---|
| Async stream observers | Breaks replay determinism by design |
| New channel kinds without commutative+associative reducers | Same |
| Out-of-lattice graph edges | The lattice is what makes cost / observability structural |
mode: "replace" on safety policies | Safety stacks append-only by contract |
| Storage adapters that aren't append-only for audit | Wire-format break |
| Identity-like fields in the fingerprint cache key | Defeats interactive caching + replay |
eval("...") or runtime code generation | Determinism + safety review impossible |
If your feature looks like one of these, the design discussion needs to surface what you're really trying to accomplish — the substrate likely has a different primitive for the actual goal.
Security disclosures
Report privately, not in public issues
Email getpleach@protonmail.com for vulnerabilities. Public GitHub
issues are the wrong channel — they tip off attackers before a fix
ships.
Include:
- A description of the vulnerability.
- A reproduction (or proof-of-concept).
- Affected versions if known.
- Your preferred attribution (or anonymity).
The upstream SECURITY.md documents response timelines.
No paid bug-bounty program
Reports get a real response, not a payout. The substrate is small enough that triage and credit happen in the open.
Code of conduct
Standard Contributor Covenant. The full text lives at
CODE_OF_CONDUCT.md in each repository. The short version:
be kind, don't harass, don't gatekeep, take disagreement to
substance rather than personalities.
License acknowledgment
By contributing to @pleach/core, you agree that your contribution
is licensed under the same FSL-1.1-Apache-2.0 the package ships
under.
No CLA. The license text in the repo is the agreement.
Where to go next
Architecture
The substrate's structural commitments — what contributions need to fit.
Plugin contract
The contract most third-party contributions extend.
Versioning policy
Semver, deprecation, pinning rules, and the FSL-1.1-Apache-2.0 license posture.
FAQ
Common questions — who's behind this, why FSL-1.1-Apache-2.0, where to report bugs.