From ff7dcde83565c7d3fda3c749e346624e17258df3 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 2 Nov 2026 21:26:39 +0000 Subject: [PATCH] State the intent to publish, and get ready for outside contributors Write down where and why we mean to publish jupyddl as citable research software (.docs/PUBLISHING.md): 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 and its Cite section now says which version the 2021 preprint describes. Add the community files an outside contributor expects: a security policy, a pull-request template, a "Propose an algorithm" issue template, and an "Adding an algorithm" section in CONTRIBUTING.md. Run tests and build on pull requests. They were `on: [push]`, which never fires for a fork, so a contributor's PR showed no checks at all. Fix AGENTS.md drift: the Python floor is 3.10 and Mergify is retired. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_014RbGtRHF8XhkiPQCDVHtV2 --- .docs/PUBLISHING.md | 114 ++++++++++++++++++++++++++++ .docs/README.md | 9 ++- .github/CONTRIBUTING.md | 26 +++++++ .github/ISSUE_TEMPLATE/algorithm.md | 27 +++++++ .github/PULL_REQUEST_TEMPLATE.md | 15 ++++ .github/SECURITY.md | 38 ++++++++++ .github/workflows/build.yml | 10 ++- .github/workflows/tests.yml | 10 ++- AGENTS.md | 12 ++- CHANGELOG.md | 16 ++++ CITATION.cff | 3 + README.md | 17 +++++ 12 files changed, 287 insertions(+), 10 deletions(-) create mode 100644 .docs/PUBLISHING.md create mode 100644 .github/ISSUE_TEMPLATE/algorithm.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/SECURITY.md diff --git a/.docs/PUBLISHING.md b/.docs/PUBLISHING.md new file mode 100644 index 0000000..028f4fc --- /dev/null +++ b/.docs/PUBLISHING.md @@ -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 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. diff --git a/.docs/README.md b/.docs/README.md index f175546..39de28f 100644 --- a/.docs/README.md +++ b/.docs/README.md @@ -7,10 +7,10 @@ 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 | |---|---| @@ -18,6 +18,7 @@ not find them here. | [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 diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 1755e92..1818066 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -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 diff --git a/.github/ISSUE_TEMPLATE/algorithm.md b/.github/ISSUE_TEMPLATE/algorithm.md new file mode 100644 index 0000000..bb5ed01 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/algorithm.md @@ -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. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..2c63ca7 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,15 @@ +## What and why + + + +## How it was checked + + + +## 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 diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000..e854fb2 --- /dev/null +++ b/.github/SECURITY.md @@ -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:`). 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. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 62b7e1b..fc5331e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -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. diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 42a0d7e..0811216 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -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. diff --git a/AGENTS.md b/AGENTS.md index d94f625..52053d6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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. @@ -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` @@ -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 diff --git a/CHANGELOG.md b/CHANGELOG.md index c58ca64..6ba0bb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 — diff --git a/CITATION.cff b/CITATION.cff index 27a0688..1eaefa2 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -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" diff --git a/README.md b/README.md index 4d61dcf..214919f 100644 --- a/README.md +++ b/README.md @@ -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. +
@@ -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},