-
Notifications
You must be signed in to change notification settings - Fork 0
Contributing
This release branch does not include the root Python tests/ directory.
Runtime installs do not need it. For a public change, start from the v1.2 branch:
git clone --branch AGENT8088-v1.2 https://github.com/palindrome-rl/AGENT8088.git
cd AGENT8088
python -m venv .venv
.venv/bin/pip install -e ".[gateway,dev]"
AGENT8088_CONFIG=/nonexistent .venv/bin/python scripts/verify_features.pyInstall both extras. Without gateway, test_gateway_core.py and
test_gateway_startup.py fail at import (they import the Slack/Discord
adapters directly) and look like real breakage.
These come from real incidents in this repo, not hypotheticals.
A bare agent8088 --help triggers the one-time .env key migration against the
developer's real ~/.agent8088/config.txt. It happened.
HOME="$(mktemp -d)" AGENT8088_CONFIG=/nonexistent python -m agent8088.cli --helpForces packaged defaults so tests never read or write real config.
No touching dotfiles, SSH config, crontab or system files. Use a fake HOME in
a tmpdir.
Verification scripts must not execute real destructive commands.
Most tools need no Python at all — add a row to src/agent8088/tools.txt:
my_tool|What it does|mode=http_get|args=query|url=https://api.example.com?q={query_q}|timeout=25
Pick an existing mode and it inherits that mode's permission gating
automatically. Then:
- Add a test in
tests/asserting the spec and, if it has logic, its behaviour. - If it's a new
mode, add gating incheck_permission()and a test for each permission mode. - Update
expected_toolsinscripts/verify_everything.py— it's the single source of truth for the inventory, and the count assertions derive from it. - Update Tools.
Never add a tool that bypasses run_tool().
- Decide the layer — see Architecture. Layers can only refuse, never grant.
- If it belongs on the always-on floor, prove it holds in all three modes
and after
grant_escalation(). Both properties need explicit tests. - Be precise about read vs write. The shell-startup-file guard blocks writes
only, matched on exact filename, so
.editorconfigand "read my.zshrc" still work. Over-broad blocking is its own failure mode. - Add the adversarial cases:
sh -cnesting,&&/;chaining, symlinks, relative paths, redirects.
Write the failing test first, then the fix — every fix in this repo's recent history has a repro that failed before and passed after.
- Establish the target branch's baseline before comparing. Otherwise you cannot tell "I broke this" from "this was already broken." Run the baseline in a separate worktree.
-
Don't silently flip a test whose expectation changed. If code and test
disagree about intent, that's a decision to surface, not to resolve by editing
whichever is convenient. If you must park it,
xfailwith a reason explaining why it's unresolved — and prefer actually resolving it. - Prefer real behaviour over mocks for verification scripts, and report unavailable dependencies as explicit skips, never silent passes.
AGENT8088_CONFIG=/nonexistent .venv/bin/python -m pytest tests/ -q
.venv/bin/python scripts/check_duplicate_defs.py
VERIFY_HOME="$(mktemp -d)"; AGENT8088_CONFIG=/nonexistent AGENT8088_HOME="$VERIFY_HOME" \
.venv/bin/python scripts/verify_features.py; rm -rf -- "$VERIFY_HOME"CI runs the lint, static and install checks on every push and pull request (see CI). The checks above go further, so run them locally too.
- Branch from
AGENT8088-v1.2, notmain. -
Never push to
mainorAGENT8088-v1.2directly. Open a PR. (There is no repo-level hook enforcing this — it's discipline, backed by whatever branch protection is configured on GitHub.) - Commit messages follow Conventional Commits:
feat:,fix:,docs:,refactor:,test:,ci:orchore:, then a short imperative summary. See CONTRIBUTING.md. - In the PR body, state: what changed, the repro that proves it, verification output, and anything you deliberately left out.
- Flag behaviour changes that could break an existing setup. A security tightening that silently locks users out needs a grace path or an explicit call-out.
python scripts/check_duplicate_defs.pyPython keeps only the last definition of a repeated top-level name — silently.
Two _wrap_untrusted functions once coexisted in engine.py, and ruff's F811
did not catch it here. Run the AST check.
- Code-level facts belong in this wiki, kept accurate against the source. Where the README drifts, the wiki notes the discrepancy rather than mirroring it.
- Record design decisions in the relevant PR; keep enduring implementation facts in this wiki.
- Update the relevant wiki page in the same PR as the code change.
docs/wiki/ is the source of truth. The Wiki tab is a separate git
repository (<repo>.wiki.git) and a generated mirror — never edit it
directly, since the next sync overwrites it.
python scripts/sync_wiki.py --dry-run # verify link rewriting
python scripts/sync_wiki.py # convert, commit, pushThe script handles the conversion the wiki requires: README.md → Home.md,
numeric prefixes dropped, internal [x](Tools) links rewritten to
[x](Tools), and a generated _Sidebar.md. It fails rather than publishing if
any internal link would end up broken.
Adding or renaming a page means updating the PAGES list in the script — that
list also defines sidebar order.
See Architecture for the module map and the reason every front end shares one engine.
Source of truth: docs/wiki/ in the main repository. Edits here are overwritten by the next sync.
Start here
Guides
- Permissions and Security
- Sandboxing
- Model Providers
- MCP
- Messaging Gateway
- Skills and Subagents
- Memory
- Docker
Reference
Development