Imported from andreasronge/ptc_runner (
AGENTS.md). Install upstream withnpx skills add andreasronge/ptc_runner. Copyright stays with the author.
Repository Instructions
Canonical agent instructions for this repo. CLAUDE.md is a symlink to this
file, so Claude Code and Codex read the same rules. Edit only this file.
PtcRunner is a BEAM-native Elixir runtime for Programmatic Tool Calling (PTC):
hosts compile immutable PTC-Lisp bundles, assemble explicit workflow and
mission environments, and execute them through a bounded owner-based Kernel.
Key docs: Kernel architecture in docs/maintainers/kernel.md,
documentation guidance in docs/maintainers/documentation.md, language
reference in docs/ptc-lisp-specification.md, and built-ins in
docs/function-reference.md.
To debug the runtime itself (not a manifest under it) — query canonical
traces or private inspection records (model exchanges, generated source,
capability payloads) non-interactively — use mix ptc repl --profile private-run-analysis-v2 --private-unattended. See "Private analysis without a
terminal".
Working Style
This is a 0.x library — expect breaking changes. Backward compatibility is not a priority. When refactoring: delete old code rather than deprecate, simplify aggressively, add no compatibility shims.
Explore the codebase before proposing changes — never claim a feature is missing without evidence from the source files. When you find a problem, fix the code and the docs together.
Do not copy a helper into a second module to avoid an import. For the root
project, mix precommit fails on duplication that is not already in
.duplication-baseline.json; extract the shared logic, or suppress it with a
reason when the repetition is deliberate. See the
duplication gate.
Work is tracked in GitHub issues. A large issue may keep its plan under
docs/plans/ while it is implemented; plans are disposable, and the pull
request that completes one deletes it. Code documentation must not link to
docs/plans/; move durable contracts into module docs, guides, or retained
specifications first.
Commits and pull requests
Use a concise Conventional Commit subject, e.g. feat(mcp): add stateful sessions. For non-trivial commits, add a short body covering what changed and
how it was verified.
A pull request description has three sections and closes its issue with
Closes #N:
- Summary — what changed, as bullets.
- Validation — only what you ran beyond the tracked hooks and CI: focused test files, a live probe, a manual check. Never list test counts and never repeat the gates the hooks run.
- Retrospective — two items, each of which may be
none: untracked follow-up work with a reproduction, and one repository instruction that was missing, wrong, or that you had to guess at. No narrative.
GitHub issues
ptc:ready, ptc:blocked, and ptc:needs-decision are the only workflow
labels, and an open issue carries at most one of them. Remove the legacy
needs-review, ready-for-implementation, needs-clarification,
needs-breakdown, and needs-maintainer-input labels from any issue you
update. A dependency is the canonical Blocked by #<number> line in the issue
body; record the same ordering as a native GitHub issue dependency so the
console can order admission. An assignee marks the issue as taken. A research
experiment issue also carries the experiment label and follows the shape in
docs/research/README.md; its pull request is never merged.
Documentation
- Any edit under
docs/guides/, including a one-line fix, starts by reading.claude/skills/write-guide/SKILL.mdand ends with its checklist. The file path is the contract, so Claude Code, Codex, and Cursor all follow it. - A bug fix may correct a wrong sentence in a guide but never adds one. New explanation goes to the reference page that owns the surface; the guide gets at most a link.
- Which layer owns what (module docs, guides, references, specifications,
plans) is in
docs/maintainers/documentation.md. - Research programs, their reports, and what an experiment may merge are
in
docs/research/README.md. Only a report reaches main; the experiment's branch is retained and tagged.
Commands
mix compile— run once after changingmix.exs,mix.lock, dependency sources, or a local path dependency (ptc_runner_launcher/,ptc_viewer/).mix ptc ...otherwise skips dependency validation for fast startup.mix precommit— quality gate: format, compile, cycles, Credo, duplication, spec, and generated-artifact staleness. It does not run the suite, Viewer, launcher, Dialyzer, ExDoc, or release.git push— the tracked pre-push hook runs the local test, static, Dialyzer, Viewer, launcher, and ExDoc gates selected by the paths you changed. Required pull-request CI additionally runs release-package verification in parallel;FORCE_FULL_PRE_PUSH=1 git pushadds it locally for release preparation or diagnosis. When a staleness check fires, run its write form (mix ptc.gen_docsfor generated docs and schemas,mix ptc.conformance_report --write-inventoryforconformance_inventory.json) and stage the result. Never push with--no-verify; never runmix prepushbefore an ordinary push (it is for static/Dialyzer diagnosis or when hooks are unavailable); never reduce test concurrency to make a failing push pass.scripts/ci/core-tests.sh— the core compile/test gate used by pre-push and CI (CI=1, 300 StreamData cases).--schedulers 4reproduces GitHub's CPU shape.scripts/ci/flake-hunt.sh N— run the suite N times at four schedulers and tabulate failing tests by frequency and seed. Use it before calling a failure a flake and after any change that moves a module toasync: true.MIX_ENV=dev mix docs --warnings-as-errors— ExDoc gate; run when changing user-facing documentation.mix test --include e2e— E2E tests (requiresOPENROUTER_API_KEY). The optional MCP prerequisites and the:scheduled_e2elive probes are in the development setup guide.mix nightlyandmix soak— the:nightlyand:soaksuites, run by their scheduled workflows. Runmix nightlylocally when you touch themix ptc rundownstream path, example operator walks, Mix-process CLI wrappers, or the benchmark task. Never add--traceor--slowestto a suite you want to finish quickly: they pin--max-casesto 1.- Test tags:
:e2e,:scheduled_e2e,:nightly,:soak, and:clojureare excluded frommix test(:clojureneeds Babashka).:nightlymeans an operator-path Mix/OS subprocess or an intentional multi-second wait, not an in-process case that takes a few hundred milliseconds.:slowonly skips the pre-commit hook's scoped test run; those tests still run in pre-push and CI. - Fix all failures before committing or pushing.
Worktrees
Work in an isolated worktree, using the prepared worktree when the task
provides one. Otherwise, create a worktree before the first edit, even for a
plan-only document. scripts/worktree.sh new <branch> [issue] branches from
origin/main, claims the issue when given (assign, comment, refuse one
already taken), and seeds and initializes the worktree. scripts/worktree.sh gc removes worktrees merged into origin/main that are clean and a day idle
and keeps their branches; run it before creating a new one. Fresh-clone
setup, seeding, hooks, the Dialyzer PLT, the MCP E2E server, and headless
Linux VM notes are in the
development setup guide. Two rules
from it that bite mid-task: never regenerate
priv/semantic_build_projection.json on a feature branch, and never
hand-merge its hashes.
If a timing-sensitive test fails only in the full suite, rerun the exact file and line ExUnit reported with the same seed. Do not bypass or throttle the hook; fix the shared-state race or brittle deadline.
Project Structure
lib/ptc_runner/— the library (kernel/,lisp/,sandbox.ex, …).ptc_runner_launcher/— optional macOS/Linux MCP stdio launcher companion.docs/— specifications, guides, and implementation records.priv/preludes/kernel/— shipped Lisp libraries; recompile after editing. Generatedpriv/preludes/kernel/agent.failure.cljis projected fromPtcRunner.Kernel.LLMFailureCatalogbymix ptc.gen_docs; do not edit it by hand.docs/function-reference.md,docs/java-interop.md,docs/kernel-limits-reference.md,docs/prelude-reference.md,docs/conformance/,priv/preludes/kernel/agent.failure.clj, and the site documentation pages undersite/guides/,site/installation/, andsite/reference/are generated, as are the exit-status and profile diagnostic catalogs between theBEGIN GENERATED/END GENERATEDmarkers indocs/reference/cli.md. Edit their owning catalogs, hand-authored shipped prelude sources, guides, or generator and runmix ptc.gen_docs. The sections shown on ptc-runner.dev and HexDocs both come from the documentation groups inmix.exs.ptc_viewer/— separate nested Mix project and canonical trace viewer. Rootmix precommitdoes not run Viewer tests; the pre-push hook does. Format Viewer edits from that directory.examples/— runnable example manifests. Their tests use the:nativeprojection while the CLI forces:json, so a green suite does not provemix ptc runworks.scripts/labs/— maintainer labs (the Viewer demo journeys and the Kernel inspection lab). They run from a checkout withmixand are not shipped examples.bench/— benchmarks (mix bench.check,mix bench.heap) with committed baselines inbench/baselines/.
Conventions
- Timestamps:
:utc_datetime, never:naive_datetime. Durations: integer milliseconds (duration_ms). - Never nest multiple modules in one file. Avoid
mix deps.clean --all. - After fixing a dialyzer/Credo issue, re-run the tool to verify — never assume.
- Owner-process state (Agent, GenServer) is mutated only through single
atomic operations (
Agent.get_and_update/2, or run the work inside the owner). A separateAgent.getfollowed byAgent.updateon the same agent is a read-modify-write race and review-blocking. - Use
ghfor GitHub tasks. When touching LLM integrations, verify model IDs are current and check.envoverrides.
PTC-Lisp Changes
Clojure compatibility is the default, but sandbox safety and recoverable signal
values take precedence for Clojure-named functions where Clojure would raise;
Java-named dot methods keep Java semantics. See
docs/clojure-conformance-gaps.md for the DIV-* rationale.
Prompts (domain-blind)
System prompts, planner prompts, and agent configurations must not contain hints about test data, benchmark domains, or expected answer patterns. The orchestration layer must work across unrelated domains without prompt changes. Tool descriptions may reference their own domain. Benchmarks and test prompts must be generic and not overlap existing domains unless asked.
Testing
- Bug fixes: write a failing test that reproduces the bug before fixing it.
- Prefer integration tests over unit tests that mirror the implementation; if a
test is as simple as the code it tests, delete it. Test at the boundary a
user hits — the CLI, REPL,
doctor, and manifest paths — not only the internal function; several regressions survived unit coverage until a command-boundary test existed. - Adding or changing an embedded example, enum, catalog, or schema changes
generated schemas and site pages; run
mix ptc.gen_docsand stage the output with the change. - No
Process.sleep— use monitors or async helpers.
usage_rules usage
A config-driven dev tool for Elixir projects to manage AGENTS.md files and agent skills from dependencies
Using Usage Rules
Many packages have usage rules, which you should thoroughly consult before taking any action. These usage rules contain guidelines and rules directly from the package authors. They are your best source of knowledge for making decisions.
Modules & functions in the current app and dependencies
When looking for docs for modules & functions that are dependencies of the current project,
or for Elixir itself, use mix usage_rules.docs
# Search a whole module
mix usage_rules.docs Enum
# Search a specific function
mix usage_rules.docs Enum.zip
# Search a specific function & arity
mix usage_rules.docs Enum.zip/1
Searching Documentation
You should also consult the documentation of any tools you are using, early and often. The best
way to accomplish this is to use the usage_rules.search_docs mix task. Once you have
found what you are looking for, use the links in the search results to get more detail. For example:
# Search docs for all packages in the current application, including Elixir
mix usage_rules.search_docs Enum.zip
# Search docs for specific packages
mix usage_rules.search_docs Req.get -p req
# Search docs for multi-word queries
mix usage_rules.search_docs "making requests" -p req
# Search only in titles (useful for finding specific functions/modules)
mix usage_rules.search_docs "Enum.zip" --query-by title
usage_rules:elixir usage
usage_rules:elixir usage rules