Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions .docs/PUBLISHING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Publishing jupyddl

**We intend to publish jupyddl as citable, peer-reviewed research software.**
This page says why, where, what is already in place, and what is left.

## Why

jupyddl's goal is to be a framework other people build on: a place to
implement a planning algorithm in readable Python, check it against the ones
already here, and *explain* it. You can watch a search run, chart it, replay it
in the browser and publish the result. That goal only works if people can find
the project, trust it, and give it credit. A software paper does all three. It
also gives everyone who extends jupyddl something stable to cite.

## The plan

| # | Venue | What it gives us | Status |
|---|---|---|---|
| 1 | [Zenodo](https://zenodo.org) | A DOI for **every release**, so a paper can cite the exact code it ran | Needs a one-time maintainer setup ([below](#zenodo-one-time-setup)) |
| 2 | [JOSS](https://joss.theoj.org) — *Journal of Open Source Software* | Peer review of the software itself, held in public on GitHub. Free to publish and free to read; the paper gets a journal DOI | Planned. [Readiness checklist below](#joss-readiness) |
| 3 | ICAPS workshops | Peer review of the *research* results. **PRL** (Planning and Reinforcement Learning) for the learned-heuristic work, **PlanEdu** or the system-demo track for the workbench | After the evaluation protocol in [roadmap §3](roadmap.md#3-a-proper-evaluation-protocol). The current results are single-seed and the notes say so |
| 4 | arXiv | A preprint of the learned-heuristic write-up, citable immediately | Optional, alongside 3 |

We are not targeting journals that charge to publish (SoftwareX, JORS). JOSS
covers the same ground for free.

## Citing jupyddl today

Use **"Cite this repository"** on the GitHub page. It reads
[`CITATION.cff`](../CITATION.cff). The current preferred citation is a 2021
preprint that describes the *original* project, a thin wrapper around the
Julia `PDDL.jl` parser. When the JOSS paper is accepted, it replaces that
preprint in `CITATION.cff` and in the README's [Cite](../README.md#cite)
section. Each release's Zenodo DOI goes in `CITATION.cff` as an identifier.

## Zenodo one-time setup

This needs a maintainer and takes about ten minutes:

1. Sign in at <https://zenodo.org> with the GitHub account that administers
`openplan-labs`.
2. Open **Settings → GitHub** and switch on `openplan-labs/PythonPDDL`. Because
the repository belongs to an organisation, the Zenodo GitHub app may first
need to be granted access to `openplan-labs` under that organisation's
*Third-party access* settings.
3. Cut a release as usual ([RELEASING.md](RELEASING.md)). The `release`
workflow publishes a GitHub Release, and Zenodo archives every published
release and mints a DOI for it. Zenodo takes its metadata from
`CITATION.cff`, so there is nothing else to fill in.
4. Add the *concept* DOI to `CITATION.cff` under `identifiers`, and as a badge
to the README. The concept DOI always resolves to the latest version.

## JOSS readiness

JOSS reviews the software against a public checklist. Here is where we stand.
JOSS revised its scope and submission requirements in 2026, so **re-read the
current [submission guide](https://joss.readthedocs.io/en/latest/submitting.html)
and [policies](https://joss.readthedocs.io/en/latest/policies.html) before
submitting**. This list is a working copy, not a substitute.

| Requirement | Status |
|---|---|
| OSI-approved licence | ✅ Apache-2.0 |
| Public repository, open issue tracker, history in the open | ✅ |
| Substantial scholarly effort | ✅ Parser and grounder covering 20 of 21 PDDL requirement flags, 14 planners, LM-cut and `h^m`, PDDL 3 compiled to the classical core, learned heuristics, search tracing |
| Installation instructions | ✅ README → Install; `pip install jupyddl` |
| Example usage | ✅ README, `demos/`, the browser workbench |
| Automated tests | ✅ CI on Python 3.10–3.14, with and without the optional extras, plus a packaging check on the built wheel |
| Community guidelines | ✅ [`CONTRIBUTING.md`](../.github/CONTRIBUTING.md), [`CODE_OF_CONDUCT.md`](../.github/CODE_OF_CONDUCT.md), [`SECURITY.md`](../.github/SECURITY.md) |
| API documentation | 🟡 Docstrings throughout, but no rendered API reference yet |
| A guide to extending the framework | 🟡 A paragraph in the README's Architecture section; a full guide is in progress |
| Archived release with a DOI | ⏳ Waiting on the Zenodo setup above |
| `paper.md` and `paper.bib` | ⏳ Not written yet. See the outline below |
| Author list, with ORCIDs | ⏳ See [Authorship](#authorship) |
| AI-usage disclosure | ⏳ Required in the paper. See [below](#ai-usage-disclosure) |

### Paper outline

JOSS papers are short, roughly 250–1000 words. The outline:

- **Summary.** A pure-Python PDDL planning framework meant to be read,
extended and taught with: no native dependencies, every search observable,
and the same registries behind the CLI, the benchmark harness and the
browser workbench.
- **Statement of need.** Researchers and students who want to *implement and
explain* a planning algorithm, not only run one. The production planners are
fast, but you have to learn their C++ before you can change anything. The
Python libraries are easy to read but stop at STRIPS, or at parsing.
- **State of the field.** Position jupyddl honestly against Fast Downward,
pyperplan, the Unified Planning Framework, Tarski and the `pddl` parsing
library: what each is for, and where jupyddl overlaps and differs.
- **Design.** Conditions in negation normal form, PDDL 3 compiled away before
grounding, cooperative budgets, zero-overhead observers, and why the core has
no runtime dependencies.
- **Research use.** The learned-heuristic line, including its negative results
and the two published claims that were later corrected.
- **AI usage disclosure** and **Acknowledgements**.

### AI usage disclosure

JOSS allows generative AI in software and papers, provided the use is
disclosed and humans keep oversight. Much of the current code was written with
an AI coding assistant. Those commits carry a `Co-Authored-By: Claude` trailer,
so the history records which work was assisted. The paper must state this
plainly. It should say which parts were assisted, and how the results were
checked: the test suite, the observed-equals-unobserved invariant, and
measurements re-taken at render time rather than typed in.

### Authorship

The maintainers settle the author list before submission, following JOSS's
authorship guidance. If you have made a substantial contribution, such as a
planner, a heuristic, a compilation or sustained review, and want to be
considered, say so in your pull request or open an issue.
9 changes: 5 additions & 4 deletions .docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@ measurement cache under [`assets/`](assets).
These notes are research documents, not user documentation — the user-facing
description of `jupyddl learn` is in the README and the module docstrings.

The two files GitHub reads for its own community features,
`CONTRIBUTING.md` and `CODE_OF_CONDUCT.md`, are in `.github/` instead: GitHub
only looks for them in the repository root, `.github/` or `docs/`, and would
not find them here.
The files GitHub reads for its own community features — `CONTRIBUTING.md`,
`CODE_OF_CONDUCT.md`, `SECURITY.md` and the issue and pull-request templates —
are in `.github/` instead: GitHub only looks for them in the repository root,
`.github/` or `docs/`, and would not find them here.

| Note | What it covers |
|---|---|
| [learned-heuristics.md](learned-heuristics.md) | The imitation stage: prior work, the design we chose, measured results on three domains, and an analysis of the one domain where it loses badly |
| [rl-for-search.md](rl-for-search.md) | The reinforcement stage: the MDP that "minimise expansions" corresponds to, why the obvious policy gradient is hard here, and what we do instead |
| [roadmap.md](roadmap.md) | What to build next, ordered by expected value, with the experiment that would settle each |
| [RELEASING.md](RELEASING.md) | How a release is cut, and the one-time PyPI trusted-publisher setup only a maintainer can do |
| [PUBLISHING.md](PUBLISHING.md) | Our intent to publish jupyddl as citable research software: Zenodo, JOSS, ICAPS workshops, the readiness checklist and authorship |

## The one-paragraph version

Expand Down
26 changes: 26 additions & 0 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,32 @@ New planners and heuristics should cite the paper they implement — name and
year — in the docstring. It tells a later reader which variant they are
getting.

## Adding an algorithm

This is what the project is for. jupyddl aims to be the place where a planning
algorithm is implemented readably, compared fairly and *explained*. A new
planner, heuristic, compilation or generator is the most welcome contribution
there is.

1. Open an issue with the **Propose an algorithm** template first, so the
variant and its guarantees are agreed before you write code.
2. Register it in the matching registry: `jupyddl.search.PLANNERS`,
`jupyddl.heuristics.HEURISTICS` or `jupyddl.generator.GENERATORS`. The CLI,
the benchmark harness and the browser workbench all read from these, so
registering it is all the wiring you need.
3. Test the guarantee, not only that it runs. If you claim optimality, compare
the plan cost against `dijkstra` on small instances. If you claim
admissibility, check `h(s0)` against the optimal cost.
4. Keep the core stdlib-only. Anything that needs a third-party package goes
behind an optional extra, the way `viz` and `learn` do.

## Credit

We intend to publish jupyddl as peer-reviewed research software (see
[`.docs/PUBLISHING.md`](../.docs/PUBLISHING.md)). If you make a substantial
contribution and want to be considered for authorship on the paper, say so in
your pull request.

## Licence

This project is licensed under **Apache 2.0** (see [`LICENSE`](../LICENSE)). By
Expand Down
27 changes: 27 additions & 0 deletions .github/ISSUE_TEMPLATE/algorithm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
name: Propose an algorithm
about: A planner, heuristic, compilation or generator you would like to see in jupyddl, or want to add yourself
title: '[algorithm] '
labels: 'feature'
assignees: ''

---

**Which algorithm?**
Name, paper and year, for example *LM-cut — Helmert & Domshlak, ICAPS 2009*.
Link the paper if it is open access.

**What kind is it?**
Planner (`jupyddl.search.PLANNERS`), heuristic (`jupyddl.heuristics.HEURISTICS`),
PDDL compilation (`jupyddl/compile.py`), instance generator
(`jupyddl.generator.GENERATORS`), or something else.

**What does it guarantee?**
Optimal, complete, admissible, anytime? Under which assumptions, for example
"admissible only without conditional effects"?

**Why is it worth having here?**
What does it show or teach that the existing ones do not?

**Do you want to implement it?**
Yes / no / with help. Read [CONTRIBUTING.md](../CONTRIBUTING.md) first.
15 changes: 15 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## What and why

<!-- One or two sentences: what changes, and the problem it solves. Link the issue if there is one. -->

## How it was checked

<!-- The test you added, the command you ran, the numbers you measured. A performance claim needs the machine and the instance. -->

## Checklist

- [ ] `flake8 jupyddl tests tools` and `pytest` pass locally
- [ ] Anything under `jupyddl/` changed → `python tools/build_web.py` was re-run and `web/dist` is committed
- [ ] A new planner or heuristic cites its paper (name and year) in the docstring
- [ ] If this moves a planner in or out of `OPTIMAL_PLANNERS`, or narrows a guarantee, the description says so
- [ ] `CHANGELOG.md` has an entry under **Unreleased** for anything a user would notice
38 changes: 38 additions & 0 deletions .github/SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Security policy

## Supported versions

Fixes go into the latest release on PyPI. Older releases are not patched, so
upgrade before you report.

## Reporting a vulnerability

Please **do not open a public issue** for a security problem.

Report it privately through GitHub instead: on the repository's **Security**
tab, choose **Report a vulnerability**. If that option is missing, open an
issue that only asks for a private contact. Leave out all details of the
problem.

Include the input that triggers it (domain and problem files, a trace or
model file) and the exact command you ran. We aim to acknowledge a report
within a week.

## What counts

jupyddl reads planning files and its own JSON artefacts, so these are in
scope:

- Code execution, or reading and writing files outside the paths you gave,
from a crafted PDDL file, search trace (`SearchTrace.load`) or learned
heuristic bundle (`learned:<path>`). These formats are plain JSON and text,
and none of them should ever execute anything.
- Script injection in the browser workbench from a crafted domain, problem or
trace.

These are **not** vulnerabilities:

- Planning is PSPACE-complete in general. A small PDDL file can ground into an
enormous task or take a very long time to search. Use a budget
(`--time-limit`, `--max-expansions`) when you plan on input you do not
trust.
10 changes: 9 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,15 @@ name: build
# distributions instead and proves the wheel stands on its own — no source
# tree, no demos folder, no editable install.

on: [push]
on:
# Pull requests, including ones from forks: `push` alone never fires for a
# contributor's fork, so their PR would sit with no checks at all. Pushes to
# main still run so the badge reflects main. A branch pushed without a PR
# gets no CI; open a draft PR to get it.
pull_request:
push:
branches: [main]
workflow_dispatch:

# Nothing here writes to the repository. Said explicitly so it stays true
# even if the repository default is loosened again.
Expand Down
10 changes: 9 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
name: tests

on: [push]
on:
# Pull requests, including ones from forks: `push` alone never fires for a
# contributor's fork, so their PR would sit with no checks at all. Pushes to
# main still run so the badge reflects main. A branch pushed without a PR
# gets no CI; open a draft PR to get it.
pull_request:
push:
branches: [main]
workflow_dispatch:

# Nothing here writes to the repository. Said explicitly so it stays true
# even if the repository default is loosened again.
Expand Down
12 changes: 8 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Julia/`PDDL.jl`/PyCall integration has been removed — there is no Julia, no
native build step, and the core has zero runtime dependencies.

### Environment
- Python ≥ 3.9; a `.venv` (created with `uv`, Python 3.12) with an editable
- Python ≥ 3.10; a `.venv` (created with `uv`, Python 3.12) with an editable
install: `uv pip install -e ".[dev]"` (add `viz` for the matplotlib charts,
animations and benchmark dashboards). `.venv`, `web/vendor/` and
`pddl-examples/` contents are git-ignored.
Expand All @@ -27,7 +27,7 @@ native build step, and the core has zero runtime dependencies.

### What CI actually checks
- **`tests`** — lint (`flake8 jupyddl tests tools`) and the suite on Python
3.9–3.14. Most of the matrix installs `.[dev]` *without* matplotlib, which is
3.10–3.14. Most of the matrix installs `.[dev]` *without* matplotlib, which is
what nearly everyone installs and keeps the core honest about not importing
it; one entry installs `.[dev,viz]` so `jupyddl/viz/` is executed rather than
skipped. `tests/test_viz.py` and `tests/test_cli_viz.py` `importorskip`
Expand All @@ -51,8 +51,12 @@ native build step, and the core has zero runtime dependencies.
**Bump the version in two places** — `pyproject.toml` and
`jupyddl/__init__.py` — and rebuild `web/dist`, which carries it too.
- **`pages`** — bundles, refuses to deploy a stale `web/dist`, then deploys.
Its job is called `bundle`, not `build`, because `.mergify.yml` keys a merge
rule on a check named `build` and that has to mean the packaging workflow.
Its job is called `bundle`, not `build`: a check named `build` has to mean
the packaging workflow, and two checks with one name is a reliable way to gate
a merge on the wrong one. (Mergify used to key a rule on it; it is retired.)
- **Triggers.** `tests` and `build` run on pull requests, so a contributor's
fork gets CI, and on pushes to `main`. A branch pushed without a PR gets no
CI; open a draft PR.

### Layout beyond the core
- `jupyddl/requirements.py` — **the source of truth** for what every PDDL
Expand Down
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,23 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added
- **The intent to publish, written down.** `.docs/PUBLISHING.md` says why and
where we mean to publish jupyddl as citable research software — a Zenodo DOI
per release, a JOSS paper, ICAPS workshops for the research results — with a
readiness checklist, the paper outline, the AI-usage disclosure JOSS requires
and how contributors can be considered for authorship. The README states the
project's aim (a framework to build on and to explain algorithms with) and
its Cite section says which version the 2021 preprint describes.
- **Community files for outside contributors**: a security policy, a
pull-request template, a *Propose an algorithm* issue template, and an
"Adding an algorithm" section in `CONTRIBUTING.md`.

### Changed
- **CI now runs on pull requests, including from forks.** `tests` and `build`
were `on: [push]`, which never fires for a fork, so an outside contributor's
PR showed no checks at all. They now run on every pull request and on pushes
to `main`.
- **Documentation lives in one place: `.docs/`.** It was spread over three
directories — `docs/` for the contributor files and the README charts,
`promo/` for the videos and screenshots, `.docs/` for the research notes —
Expand Down
3 changes: 3 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ keywords:
- automated planning
- heuristic search
- artificial intelligence
# This preprint describes the original, Julia-backed version. A software paper
# on the current framework is planned for JOSS, with a Zenodo DOI per release;
# when it is accepted it replaces this entry (see .docs/PUBLISHING.md).
preferred-citation:
type: article
title: "Jupyddl, an extensible python library for PDDL planning and parsing"
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ language runtime. It has since been **rewritten from scratch as a pure-Python
framework** — no Julia, no native dependencies, just the standard library — so it
is trivial to install, embed, teach with, and build on.

That is the point of it: a framework you can **build on** to implement a planning
algorithm in readable Python, measure it against the ones already here, and
**explain** it to someone else — every search can be traced, charted and
replayed. We intend to publish jupyddl as peer-reviewed research software so that
work built on it has something stable to cite; [the plan](.docs/PUBLISHING.md)
says where and what is left.

<div align="center">

<picture>
Expand Down Expand Up @@ -597,6 +604,16 @@ planners — nothing in it is typed in by hand.

## Cite

If jupyddl helps your work, please cite it. GitHub's **"Cite this repository"**
button gives you APA and BibTeX from [`CITATION.cff`](CITATION.cff).

The citation below is a 2021 preprint describing the project's original,
Julia-backed version. A software paper on the current framework is planned for
the [Journal of Open Source Software](https://joss.theoj.org), with a Zenodo
DOI for every release; once it is accepted it replaces this entry. See
[`.docs/PUBLISHING.md`](.docs/PUBLISHING.md) for the plan, the readiness
checklist, and how contributors can be considered for authorship.

```
@misc{https://doi.org/10.13140/rg.2.2.22418.89282,
doi = {10.13140/RG.2.2.22418.89282},
Expand Down
Loading