From 4ac6f6a0fa535ed4a27809e5ea0928e6a8616a81 Mon Sep 17 00:00:00 2001 From: Ali Norouzi Date: Sun, 13 Sep 2026 19:30:40 +0400 Subject: [PATCH 1/2] Expand README for the PyPI project page Add CI, docs, Python and license badges, a documentation link block, and a "When FlowRoute fits" section that states the selector boundary up front. Explain the narrowing guarantee under the pipeline diagram and point the documentation section at the published site rather than local Markdown. The README is the PyPI long description, so this is the first thing a reader sees on the project page. Co-Authored-By: Claude Opus 5 --- README.md | 116 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 82 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index ee2c57c..468870c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,10 @@ # FlowRoute +[![CI](https://github.com/open-first/FlowRoute/actions/workflows/ci.yml/badge.svg)](https://github.com/open-first/FlowRoute/actions/workflows/ci.yml) +[![Docs](https://github.com/open-first/FlowRoute/actions/workflows/docs.yml/badge.svg)](https://open-first.github.io/FlowRoute/) +[![Python](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/downloads/) +[![License](https://img.shields.io/badge/license-Apache--2.0-blue)](LICENSE) + FlowRoute is a small, safety-oriented router that maps a natural-language request to a deterministic workflow without using a generative LLM for the routing decision. @@ -12,6 +17,25 @@ It returns exactly one of three outcomes: FlowRoute never executes workflows. Authorization, argument validation, confirmation, idempotency, and side effects remain in the workflow orchestrator. +**[Read the documentation](https://open-first.github.io/FlowRoute/)** · +[Quick start](#quick-start) · +[Production mode](#production-mode) + +## When FlowRoute fits + +Use FlowRoute when: + +- workflows are narrow, named, and deterministic; +- users express the same intent in varied language; +- a safe fallback is available for ambiguous requests; +- inference cost or latency matters; and +- false routing is more expensive than abstention. + +Use an LLM or planner when the task requires explanation, advice, strategy, open-ended +generation, or several dependent actions. FlowRoute is a selector, not an orchestrator, an agent +framework, or a general-purpose intent classifier; its job is to decide whether a request belongs +to a known workflow and to abstain when it does not. + ## Status Version 0.2 provides a **production-hardened routing runtime and research scaffold**, but it does @@ -37,6 +61,10 @@ flowchart TD F --> I["LLM_REQUIRED"] ``` +Each stage may only narrow the candidate set. Retrieval proposes; the verifier judges one +request-contract pair at a time; calibration decides whether the best candidate clears the risk +tier it was assigned. Schema completeness is deterministic and can override an unsafe prediction. + ## Quick start Requires Python 3.10 or newer. @@ -78,10 +106,14 @@ Run unit tests without installing development tools: PYTHONPATH=src python -m unittest discover -s tests -v ``` -## Developer documentation +## Documentation -The complete developer guide is authored as portable Markdown under `docs/` and configured for -MkDocs: +The complete developer guide is published at +**[open-first.github.io/FlowRoute](https://open-first.github.io/FlowRoute/)**. It covers +installation, contracts, Python, HTTP and CLI integration, routing internals, training, dataset +design, evaluation, safety, production requirements, and troubleshooting. + +The source is portable Markdown under `docs/`, configured for MkDocs: ```bash pip install -r requirements-docs.txt @@ -94,10 +126,6 @@ Build a static site that can be uploaded to any static host: mkdocs build --strict ``` -Start with [the documentation home](docs/index.md). It covers installation, contracts, Python, -HTTP and CLI integration, routing internals, training, dataset design, evaluation, safety, -production requirements, and troubleshooting. - ## Python API ```python @@ -140,6 +168,31 @@ curl -s http://127.0.0.1:8000/v1/route \ The development service also exposes `GET /health`, `GET /health/live`, and `GET /health/ready`. A stale `catalog_version` returns HTTP 409. +## Workflow contracts + +Contracts describe capability boundaries, inputs, effects, and risk—not executable code. + +```yaml +- id: calendar.cancel_event + version: 1.0.0 + name: Cancel a calendar event + description: Cancel one existing event the current user may modify. + positive_capabilities: + - cancel an existing meeting + exclusions: + - decline an invitation + - delete a recurring series without confirmation + required_inputs: + - name: event_id + pattern: '\b(?Pevt_[A-Za-z0-9_-]+)\b' + side_effect: external_write + risk_tier: medium + confirmation: required_if_recurring +``` + +For safety, external or destructive contracts must declare both exclusions and a confirmation +policy. Regex extraction is optional; trusted structured context takes precedence. + ## Production mode ```python @@ -182,33 +235,8 @@ Production mode: - emits privacy-conscious structured telemetry; and - supports atomic bundle reload and rollback through `RouterRuntime`. -See [Production mode](docs/operations/production-mode.md) and -[Artifact manifests](docs/operations/artifact-manifests.md). - -## Workflow contracts - -Contracts describe capability boundaries, inputs, effects, and risk—not executable code. - -```yaml -- id: calendar.cancel_event - version: 1.0.0 - name: Cancel a calendar event - description: Cancel one existing event the current user may modify. - positive_capabilities: - - cancel an existing meeting - exclusions: - - decline an invitation - - delete a recurring series without confirmation - required_inputs: - - name: event_id - pattern: '\b(?Pevt_[A-Za-z0-9_-]+)\b' - side_effect: external_write - risk_tier: medium - confirmation: required_if_recurring -``` - -For safety, external or destructive contracts must declare both exclusions and a confirmation -policy. Regex extraction is optional; trusted structured context takes precedence. +See [Production mode](https://open-first.github.io/FlowRoute/operations/production-mode/) and +[Artifact manifests](https://open-first.github.io/FlowRoute/operations/artifact-manifests/). ## Plug in Hugging Face checkpoints @@ -279,6 +307,26 @@ docs/ architecture and research implementation notes 6. Report false-route rate together with route coverage and confidence intervals. 7. Fill every `TBD` in the model and dataset cards; publish checkpoint hashes. +## Contributing + +Contributions are welcome. [CONTRIBUTING.md](CONTRIBUTING.md) states the rules that protect the +safety boundary: keep the router separate from workflow execution; add a regression test for every +routing or abstention change; never weaken a risk threshold to make one example pass; and do not +add benchmark numbers without a reproducible evaluation artifact. + +`main` is protected. Work on a branch and open a pull request; CI must pass on Python 3.10 and +3.12, and documentation changes must also survive `mkdocs build --strict`. + +## Security + +Do not open a public issue for a suspected vulnerability. Use GitHub's private +vulnerability-reporting feature, or follow [SECURITY.md](SECURITY.md). + +## Citation + +If you use FlowRoute in research, cite the software through [CITATION.cff](CITATION.cff). GitHub +renders a ready-made citation from that file under **Cite this repository**. + ## License Apache-2.0. Dataset and model artifacts may have separate licenses; document them before release. From a8de3e491a597d8c670e31804429289d2abfa20d Mon Sep 17 00:00:00 2001 From: Ali Norouzi Date: Sun, 13 Sep 2026 19:30:40 +0400 Subject: [PATCH 2/2] Publish to PyPI with trusted publishing Release on v* tags via a build job and a separate publish job that holds the only id-token: write permission, so build-time dependencies cannot reach the OIDC credential. No API token is stored in the repository. The build job refuses to publish when the tag does not match the version in pyproject.toml, and smoke tests the built wheel in a clean virtualenv before the artifact is handed to the publish job. Co-Authored-By: Claude Opus 5 --- .github/workflows/release.yml | 68 +++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..6dcd3d2 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,68 @@ +name: Release + +on: + push: + tags: ["v*"] + workflow_dispatch: + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + + - uses: actions/setup-python@v7 + with: + python-version: "3.12" + cache: pip + + - name: Verify tag matches project version + if: startsWith(github.ref, 'refs/tags/') + run: | + project_version="$(python -c 'import tomllib, pathlib; print(tomllib.loads(pathlib.Path("pyproject.toml").read_text())["project"]["version"])')" + tag_version="${GITHUB_REF_NAME#v}" + if [ "$project_version" != "$tag_version" ]; then + echo "::error::Tag ${GITHUB_REF_NAME} does not match pyproject version ${project_version}" + exit 1 + fi + echo "Releasing ${project_version} from ${GITHUB_REF_NAME}" + + - name: Build distributions + run: | + python -m pip install --upgrade build twine + python -m build + twine check dist/* + + - name: Smoke test built wheel + run: | + python -m venv /tmp/smoke + /tmp/smoke/bin/pip install --quiet dist/*.whl + /tmp/smoke/bin/python -c "import flowroute; print(flowroute.__version__)" + /tmp/smoke/bin/flowroute route \ + --catalog examples/workflows.yaml \ + --text "Where is order 4812?" + + - uses: actions/upload-artifact@v7 + with: + name: dist + path: dist/ + + publish: + needs: build + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/flowroute + permissions: + id-token: write + steps: + - uses: actions/download-artifact@v8 + with: + name: dist + path: dist/ + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1