nncg 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. nncg-0.2.0/.bandit +2 -0
  2. nncg-0.2.0/.claude/commands/rhiza_book.md +53 -0
  3. nncg-0.2.0/.claude/commands/rhiza_quality.md +98 -0
  4. nncg-0.2.0/.claude/commands/rhiza_release.md +82 -0
  5. nncg-0.2.0/.claude/commands/rhiza_update.md +100 -0
  6. nncg-0.2.0/.editorconfig +41 -0
  7. nncg-0.2.0/.github/CONFIG.md +66 -0
  8. nncg-0.2.0/.github/DISCUSSION_TEMPLATE/help-wanted.yml +48 -0
  9. nncg-0.2.0/.github/DISCUSSION_TEMPLATE/ideas.yml +40 -0
  10. nncg-0.2.0/.github/DISCUSSION_TEMPLATE/q-and-a.yml +25 -0
  11. nncg-0.2.0/.github/ISSUE_TEMPLATE/bug_report.yml +57 -0
  12. nncg-0.2.0/.github/ISSUE_TEMPLATE/feature_request.yml +41 -0
  13. nncg-0.2.0/.github/dependabot.yml +100 -0
  14. nncg-0.2.0/.github/pull_request_template.md +24 -0
  15. nncg-0.2.0/.github/release.yml +67 -0
  16. nncg-0.2.0/.github/rulesets/main-branch-protection.json +47 -0
  17. nncg-0.2.0/.github/secret_scanning.yml +20 -0
  18. nncg-0.2.0/.github/workflows/rhiza_book.yml +37 -0
  19. nncg-0.2.0/.github/workflows/rhiza_ci.yml +30 -0
  20. nncg-0.2.0/.github/workflows/rhiza_codeql.yml +35 -0
  21. nncg-0.2.0/.github/workflows/rhiza_release.yml +692 -0
  22. nncg-0.2.0/.github/workflows/rhiza_sync.yml +45 -0
  23. nncg-0.2.0/.gitignore +141 -0
  24. nncg-0.2.0/.pre-commit-config.yaml +100 -0
  25. nncg-0.2.0/.python-version +2 -0
  26. nncg-0.2.0/.rhiza/.cfg.toml +50 -0
  27. nncg-0.2.0/.rhiza/.gitignore +2 -0
  28. nncg-0.2.0/.rhiza/.rhiza-version +1 -0
  29. nncg-0.2.0/.rhiza/assets/rhiza-logo.svg +81 -0
  30. nncg-0.2.0/.rhiza/completions/README.md +263 -0
  31. nncg-0.2.0/.rhiza/completions/rhiza-completion.bash +75 -0
  32. nncg-0.2.0/.rhiza/completions/rhiza-completion.zsh +119 -0
  33. nncg-0.2.0/.rhiza/make.d/book.mk +58 -0
  34. nncg-0.2.0/.rhiza/make.d/bootstrap.mk +116 -0
  35. nncg-0.2.0/.rhiza/make.d/custom-env.mk +9 -0
  36. nncg-0.2.0/.rhiza/make.d/custom-task.mk +12 -0
  37. nncg-0.2.0/.rhiza/make.d/doctor.mk +60 -0
  38. nncg-0.2.0/.rhiza/make.d/github.mk +70 -0
  39. nncg-0.2.0/.rhiza/make.d/marimo.mk +50 -0
  40. nncg-0.2.0/.rhiza/make.d/quality.mk +69 -0
  41. nncg-0.2.0/.rhiza/make.d/releasing.mk +57 -0
  42. nncg-0.2.0/.rhiza/make.d/test.mk +226 -0
  43. nncg-0.2.0/.rhiza/requirements/README.md +27 -0
  44. nncg-0.2.0/.rhiza/requirements/docs.txt +5 -0
  45. nncg-0.2.0/.rhiza/requirements/marimo.txt +2 -0
  46. nncg-0.2.0/.rhiza/requirements/tests.txt +19 -0
  47. nncg-0.2.0/.rhiza/requirements/tools.txt +8 -0
  48. nncg-0.2.0/.rhiza/rhiza.mk +238 -0
  49. nncg-0.2.0/.rhiza/semgrep.yml +84 -0
  50. nncg-0.2.0/.rhiza/template.lock +107 -0
  51. nncg-0.2.0/.rhiza/template.yml +5 -0
  52. nncg-0.2.0/.rhiza/tests/README.md +172 -0
  53. nncg-0.2.0/.rhiza/tests/api/conftest.py +90 -0
  54. nncg-0.2.0/.rhiza/tests/api/test_github_targets.py +56 -0
  55. nncg-0.2.0/.rhiza/tests/api/test_make_variable_overrides.py +178 -0
  56. nncg-0.2.0/.rhiza/tests/api/test_makefile_api.py +370 -0
  57. nncg-0.2.0/.rhiza/tests/api/test_makefile_targets.py +449 -0
  58. nncg-0.2.0/.rhiza/tests/api/test_releasing_targets.py +66 -0
  59. nncg-0.2.0/.rhiza/tests/conftest.py +211 -0
  60. nncg-0.2.0/.rhiza/tests/integration/test_book_targets.py +163 -0
  61. nncg-0.2.0/.rhiza/tests/integration/test_docs_targets.py +57 -0
  62. nncg-0.2.0/.rhiza/tests/integration/test_test_mk.py +170 -0
  63. nncg-0.2.0/.rhiza/tests/integration/test_virtual_env_unexport.py +37 -0
  64. nncg-0.2.0/.rhiza/tests/shell/test_scripts.sh +196 -0
  65. nncg-0.2.0/.rhiza/tests/stress/README.md +142 -0
  66. nncg-0.2.0/.rhiza/tests/stress/__init__.py +5 -0
  67. nncg-0.2.0/.rhiza/tests/stress/conftest.py +50 -0
  68. nncg-0.2.0/.rhiza/tests/structure/test_project_layout.py +55 -0
  69. nncg-0.2.0/.rhiza/tests/structure/test_pyproject.py +217 -0
  70. nncg-0.2.0/.rhiza/tests/structure/test_requirements.py +51 -0
  71. nncg-0.2.0/.rhiza/tests/sync/conftest.py +93 -0
  72. nncg-0.2.0/.rhiza/tests/sync/test_docstrings.py +123 -0
  73. nncg-0.2.0/.rhiza/tests/sync/test_readme_validation.py +197 -0
  74. nncg-0.2.0/.rhiza/tests/test_utils.py +70 -0
  75. nncg-0.2.0/.rhiza/tests/utils/test_git_repo_fixture.py +132 -0
  76. nncg-0.2.0/.rhiza/tests/utils/test_pip_audit_policy.py +147 -0
  77. nncg-0.2.0/.rhiza/tests/utils/test_suppression_audit.py +398 -0
  78. nncg-0.2.0/.rhiza/utils/pip_audit_policy.py +101 -0
  79. nncg-0.2.0/.rhiza/utils/suppression_audit.py +85 -0
  80. nncg-0.2.0/.rhiza/utils/suppression_parse.py +251 -0
  81. nncg-0.2.0/.rhiza/utils/suppression_report.py +196 -0
  82. nncg-0.2.0/CHANGELOG.md +43 -0
  83. nncg-0.2.0/CITATION.cff +23 -0
  84. nncg-0.2.0/CLAUDE.md +53 -0
  85. nncg-0.2.0/CODE_OF_CONDUCT.md +27 -0
  86. nncg-0.2.0/CONTRIBUTING.md +182 -0
  87. nncg-0.2.0/LICENSE +21 -0
  88. nncg-0.2.0/Makefile +13 -0
  89. nncg-0.2.0/PKG-INFO +138 -0
  90. nncg-0.2.0/README.md +119 -0
  91. nncg-0.2.0/SECURITY.md +98 -0
  92. nncg-0.2.0/cliff.toml +84 -0
  93. nncg-0.2.0/docs/api.md +15 -0
  94. nncg-0.2.0/docs/assets/rhiza-logo.svg +81 -0
  95. nncg-0.2.0/docs/index.md +25 -0
  96. nncg-0.2.0/docs/mkdocs-base.yml +120 -0
  97. nncg-0.2.0/mkdocs.yml +36 -0
  98. nncg-0.2.0/pyproject.toml +55 -0
  99. nncg-0.2.0/pytest.ini +26 -0
  100. nncg-0.2.0/ruff.toml +169 -0
  101. nncg-0.2.0/src/nncg/__init__.py +29 -0
  102. nncg-0.2.0/src/nncg/krylov.py +107 -0
  103. nncg-0.2.0/src/nncg/solver.py +408 -0
  104. nncg-0.2.0/tests/__init__.py +6 -0
  105. nncg-0.2.0/tests/problems.py +171 -0
  106. nncg-0.2.0/tests/test_eq.py +57 -0
  107. nncg-0.2.0/tests/test_fallback.py +64 -0
  108. nncg-0.2.0/tests/test_krylov.py +77 -0
  109. nncg-0.2.0/tests/test_operators.py +151 -0
  110. nncg-0.2.0/tests/test_package_metadata.py +35 -0
  111. nncg-0.2.0/tests/test_problems.py +50 -0
  112. nncg-0.2.0/tests/test_solver.py +108 -0
  113. nncg-0.2.0/uv.lock +259 -0
nncg-0.2.0/.bandit ADDED
@@ -0,0 +1,2 @@
1
+ [bandit]
2
+ skips = B101
@@ -0,0 +1,53 @@
1
+ ---
2
+ description: Build the documentation book into a local _book folder and open it in the default browser
3
+ allowed-tools: Bash, Read
4
+ ---
5
+
6
+ Build the MkDocs/zensical documentation book locally and open it in the user's
7
+ standard web browser. Follow the command-execution policy: always prefer
8
+ `make <target>`; never invoke `.venv/bin/...` directly.
9
+
10
+ This command depends on the **book** bundle (it expects a root `mkdocs.yml` and a
11
+ `make book` target from `.rhiza/make.d/book.mk`). If `mkdocs.yml` is missing,
12
+ stop and tell the user the `book` bundle is not set up here rather than guessing.
13
+
14
+ Do the following, in order:
15
+
16
+ 1. **Build the book.** Run `make book`. This regenerates the `_book/` output
17
+ folder via zensical (it also runs the `_book-reports` / `_book-notebooks`
18
+ prerequisites). Run it in the foreground so build errors are visible. If it
19
+ fails, show the relevant output, diagnose the root cause, and stop — do not
20
+ try to open a stale or partial book.
21
+
22
+ 2. **Confirm the output.** Verify `_book/index.html` exists after the build. If
23
+ it does not, report what `make book` produced instead and stop.
24
+
25
+ 3. **Serve it locally (background).** Static zensical sites need to be served
26
+ over HTTP — search and navigation break under `file://`. Start a local server
27
+ for the built folder **in the background** so it does not block the session:
28
+
29
+ ```
30
+ (cd _book && uv run python -m http.server 8000)
31
+ ```
32
+
33
+ Use port 8000 by default (this matches `make serve`). If 8000 is already in
34
+ use, pick the next free port (8001, 8002, …) and use that URL throughout.
35
+ Do **not** use `make serve` here — it rebuilds the book a second time and
36
+ blocks the terminal; the book is already built from step 1.
37
+
38
+ 4. **Open the default browser.** Open the served URL with the platform's
39
+ standard opener:
40
+ - macOS: `open http://localhost:8000`
41
+ - Linux: `xdg-open http://localhost:8000`
42
+ - Windows: `start http://localhost:8000`
43
+
44
+ Detect the platform and use the right one.
45
+
46
+ 5. **Report.** Tell the user the book was built at `_book/`, the URL it is being
47
+ served at, and how to stop the background server (e.g. the background task /
48
+ PID, or "kill the `http.server` process on port 8000"). Note that `_book/` is
49
+ a generated, gitignored artifact.
50
+
51
+ If `$ARGUMENTS` is non-empty, treat it as an override hint — e.g. a custom port
52
+ (`/rhiza_book 9000`) or a request to only build without serving/opening (`/rhiza_book
53
+ build-only`) — and adjust accordingly.
@@ -0,0 +1,98 @@
1
+ ---
2
+ description: Run the Rhiza code-quality gate and score the repo (lint, types, docs, deps, security, tests)
3
+ ---
4
+
5
+ Assess the quality of this repo against Rhiza standards. Follow the
6
+ command-execution policy: always prefer `make <target>`; never invoke
7
+ `.venv/bin/...` directly. Run the gates in order — cheapest checks first so fast
8
+ failures surface before the slow test suite — and collect results:
9
+
10
+ 1. `make fmt` — pre-commit hooks + linting (ruff format/check, markdownlint, bandit, actionlint, …)
11
+ 2. `make typecheck` — static type checking (`ty`, and `mypy --strict` if configured) over `src/`
12
+ 3. `make docs-coverage` — docstring coverage (interrogate) over `src/`
13
+ 4. `make deptry` — unused/missing/misplaced dependency analysis
14
+ 5. `make security` — pip-audit + bandit scans
15
+ 6. `make validate` — validate project structure against the Rhiza template (`.rhiza/template.yml`)
16
+ 7. `make test` — full test suite **with** its coverage gate (slowest, run last)
17
+
18
+ Guidelines:
19
+
20
+ - Run each gate as a single, bare `make <target>` command — one Bash call per
21
+ gate. Do **not** pipe (`| tee`, `| tail`), redirect (`2>&1 >`), chain
22
+ (`make fmt && make typecheck`), or prefix with `cd`. Bare `make <target>`
23
+ invocations match the allow-listed `Bash(make *)` rule and run without a
24
+ permission prompt; compound or piped commands do not and will prompt on every
25
+ gate. Read the full output directly from each call rather than capturing it to
26
+ a file.
27
+ - Run all gates even after an early failure, so the full picture is visible
28
+ rather than stopping at the first red.
29
+ - If something fails, show the relevant output, diagnose the root cause, and
30
+ propose (or apply, if clearly correct, low-risk, **and** the fix is in a
31
+ locally-owned file per the scoping rule below) a fix.
32
+ - If `$ARGUMENTS` is non-empty, scope the assessment to that path or topic
33
+ instead of the whole repo.
34
+ - End with a concise PASS/FAIL summary per gate.
35
+
36
+ **Coverage expectation.** `make test` enforces a coverage gate
37
+ (`COVERAGE_FAIL_UNDER`, default 90%; many projects raise it to 100%). Treat
38
+ anything below the configured threshold on locally-owned `src/` as a gap to
39
+ flag, not an acceptable baseline. When scoring the test-coverage subcategory,
40
+ the configured threshold is the bar for a 10; report uncovered lines
41
+ (`file:line`) and the test that would close each.
42
+
43
+ **`make validate`.** A failure means this repo has drifted from the Rhiza
44
+ template (a synced file edited locally, or a missing/extra file). That is
45
+ in-scope: fix it by re-syncing from Rhiza or by adjusting `.rhiza/template.yml`,
46
+ not by editing the synced artifact in place.
47
+
48
+ Then report:
49
+
50
+ - A pass/fail summary per step.
51
+ - Failures grouped by file, with the specific rule/error and line.
52
+ - A prioritized list of what to fix first (blocking errors before style nits).
53
+
54
+ Then analyse the repo and give marks on a scale of 1 to 10 for all relevant
55
+ subcategories. Pick the subcategories that fit what you actually observe — e.g.
56
+ linting/style, type safety, test pass rate, test coverage & depth, code
57
+ structure & readability, documentation, dependency & security hygiene, CI/tooling
58
+ health. For each: the score, a one-line justification grounded in evidence from
59
+ the checks above (and a quick look at the code where needed), and what would
60
+ raise it. Close with an overall score and the single highest-leverage
61
+ improvement.
62
+
63
+ **Scope the scorecard to locally-owned items — not what the mother repo (Rhiza)
64
+ owns.** This project syncs its dev infrastructure from `jebel-quant/rhiza`; see
65
+ `CLAUDE.md` for the authoritative split and the `files:` block of
66
+ `.rhiza/template.lock` for the machine-generated list of synced files. Score
67
+ only what this repo actually controls — `src/`, `tests/`, `pyproject.toml`,
68
+ `README.md`, project-specific docs, `.rhiza/template.yml`, and any
69
+ locally-hardened config. Do **not** let Rhiza-managed files (the
70
+ `.github/workflows/*`, `Makefile`, `.pre-commit-config.yaml`, `pytest.ini`,
71
+ `ruff.toml`, the typecheck/mutation/fuzzing targets, etc.) drive the marks — a
72
+ gap there is fixed upstream in Rhiza, not here. If a relevant signal is
73
+ Rhiza-owned, note it as "upstream/out-of-scope" rather than scoring it against
74
+ this repo.
75
+
76
+ Then, from the scorecard above, identify **actionable issues to improve the
77
+ score** — one per subcategory scoring below 10 (skip any that are maxed). For
78
+ each, give: a concrete title, the subcategory and current→target score it moves,
79
+ the specific file(s)/lines or config to change, and a crisp acceptance criterion
80
+ ("done when…"). Keep them in-scope (locally-owned, per the scoping rule above) —
81
+ flag anything Rhiza-owned as upstream rather than listing it as a local action.
82
+ Order them by leverage (biggest score gain for least effort first). This is a
83
+ list of recommendations only — do not change code unless I explicitly ask.
84
+
85
+ Then offer to file the findings as issues — using a menu, not a free-text prompt.
86
+ Present the actionable findings as a multi-select menu (the AskUserQuestion tool
87
+ with `multiSelect: true`), one option per finding labelled by its title, so I can
88
+ pick exactly which ones to file — including none. Create nothing without an
89
+ explicit selection. For each finding I select, detect the hosting platform from
90
+ the git remote (`git remote get-url origin`) and create one issue with the
91
+ matching CLI — GitHub → `gh issue create`, GitLab → `glab issue create` (skip and
92
+ say so if the relevant CLI is unavailable or unauthenticated). Make each issue
93
+ self-contained: title from the finding, and a body carrying the subcategory, the
94
+ current→target score, the specific file(s)/lines or config to change, and the
95
+ "done when…" acceptance criterion. Report back the created issue URLs.
96
+
97
+ If everything passes, say so plainly — but still produce the 1–10 subcategory
98
+ marks. Do not fix anything unless I ask — this command only assesses.
@@ -0,0 +1,82 @@
1
+ ---
2
+ description: Cut a release — choose the version bump, push the tag, and watch the release workflow
3
+ allowed-tools: Bash, Read
4
+ ---
5
+
6
+ Cut a release for this repository. Follow the command-execution policy: always
7
+ prefer `make <target>`; never invoke `.venv/bin/...` directly.
8
+
9
+ How releasing works here. `make release` delegates to `rhiza-tools release`
10
+ (`.rhiza/make.d/releasing.mk`). It **always bumps** the version, folds a freshly
11
+ generated `CHANGELOG.md` into the version-bump commit (git-cliff pre-commit
12
+ hook), creates a `v*` tag, and pushes it. The tag push triggers the
13
+ `rhiza_release.yml` GitHub Actions workflow (validate → build → SBOM → draft →
14
+ publish → finalize). There is no separate post-tag changelog commit — the tagged
15
+ commit already carries the changelog.
16
+
17
+ **The bump type is a user decision.** Run interactively, `make release` prompts
18
+ the user to pick `MAJOR`, `MINOR`, or `PATCH`. Because this command runs in a
19
+ non-interactive shell (where the tool would silently default to `PATCH`), **you
20
+ must ask the user which bump to apply** and pass their choice through with
21
+ `BUMP=major|minor|patch` (supported by both `make release` and `make bump`).
22
+
23
+ Do the following, in order:
24
+
25
+ 1. **Pre-flight checks.** Confirm the release is safe to cut and stop with a
26
+ clear explanation if any check fails (do not push a tag from a dirty or
27
+ behind branch):
28
+ - Working tree is clean (`git status --porcelain` is empty).
29
+ - On the default branch (`main`) — or confirm with the user if not.
30
+ - Local `main` is up to date with `origin/main` (`git fetch` then compare).
31
+ - `pyproject.toml` exists (the bump is skipped without it).
32
+
33
+ 2. **Ask the user for the bump type.** Just like `make release` does
34
+ interactively, ask the user to choose **MAJOR**, **MINOR**, or **PATCH**
35
+ (semver: breaking / feature / fix). Skip this question only when
36
+ `$ARGUMENTS` already names a bump type or authorises a default (see below).
37
+ Hold the chosen `<bump>` (lowercase: `major` / `minor` / `patch`) for the
38
+ next steps.
39
+
40
+ 3. **Preview the bump (dry run).** Run `make release DRY_RUN=1 BUMP=<bump>` to
41
+ show the user the planned new version and tag **before** anything is pushed.
42
+ The `DRY_RUN=1` flag previews the bump/tag/push without applying them.
43
+ Summarise what the real run will do (old → new version, tag name).
44
+
45
+ 4. **Confirm.** Unless `$ARGUMENTS` explicitly authorises proceeding (see
46
+ below), stop here and ask the user to confirm the previewed version before
47
+ cutting the real release. Pushing a tag triggers a public release workflow —
48
+ treat it as outward-facing and confirm first.
49
+
50
+ 5. **Cut the release.** Run `make release BUMP=<bump> PUSH=1`. This bumps,
51
+ commits (with changelog), tags, and pushes. The `PUSH=1` flag is **required
52
+ here**: without it the tool asks an interactive `Push tag to remote? [y/N]`
53
+ question that this non-interactive shell auto-declines, leaving the bump
54
+ commit and tag stranded locally (unpushed). Since you already confirmed with
55
+ the user in step 4, `PUSH=1` pushes straight through. Run it in the
56
+ foreground so any failure is visible. If it fails, show the relevant output,
57
+ diagnose the root cause, and stop — do not re-run blindly or hand-craft a tag.
58
+
59
+ 6. **Watch the workflow.** Run `make release-status` to show the release
60
+ workflow run and the latest release info. If the workflow is still in
61
+ progress, tell the user it is running and how to re-check
62
+ (`make release-status`). Report the final release URL once available.
63
+
64
+ 7. **Report.** Tell the user the version that was released, the tag, and the
65
+ release/workflow URL. If anything is still pending (workflow running, draft
66
+ not yet published), say so plainly.
67
+
68
+ `$ARGUMENTS` handling:
69
+
70
+ - Empty → run the full ask-bump → preview → confirm flow above.
71
+ - `major` / `minor` / `patch` → use that as the bump type and skip the question
72
+ in step 2 (still preview and confirm).
73
+ - `dry-run` (or `preview`) → do steps 1–3 only and stop; do **not** cut a real
74
+ release. If no bump type is also given, still ask for it in step 2.
75
+ - `yes` / `confirm` / `--force` → skip the interactive confirmation in step 4
76
+ and proceed straight through (still run the dry-run preview in step 3 so the
77
+ user sees what shipped). If no bump type is also given, still ask for it in
78
+ step 2.
79
+ - `status` → skip to step 6 and just report current release/workflow status.
80
+
81
+ Argument tokens combine, e.g. `minor yes` cuts a minor release without the
82
+ confirmation prompt; `minor dry-run` previews a minor bump only.
@@ -0,0 +1,100 @@
1
+ ---
2
+ description: Update the pinned Rhiza version in .rhiza/template.yml, sync, resolve conflicts, and verify
3
+ ---
4
+
5
+ Update this repo's Rhiza template to a newer release: bump the pin in
6
+ `.rhiza/template.yml`, run the sync, resolve every conflict, verify the quality
7
+ gates, and open a PR. Follow the command-execution policy: always prefer
8
+ `make <target>`; never invoke `.venv/bin/...` directly.
9
+
10
+ `$ARGUMENTS` may name a target version (e.g. `v0.19.1`). If empty, target the
11
+ **latest** release of the upstream template repo.
12
+
13
+ ## 1. Determine current and target versions
14
+
15
+ - Read `.rhiza/template.yml`: the `repository:` field is the upstream template
16
+ repo (usually `jebel-quant/rhiza`) and `ref:` is the currently pinned version.
17
+ - Resolve the target version:
18
+ - If `$ARGUMENTS` names a version, use it (verify the tag exists:
19
+ `gh api repos/<repository>/git/ref/tags/<ref>`).
20
+ - Otherwise get the latest release:
21
+ `gh release view --repo <repository> --json tagName,publishedAt`.
22
+ - If `ref:` already equals the target, report "already up to date" and stop.
23
+ - Briefly summarize what's between the two versions when it's cheap to do so
24
+ (`gh release view`/release notes), so the reviewer knows what's landing.
25
+
26
+ ## 2. Bump the pin and commit (the tree must be clean to sync)
27
+
28
+ - `make sync` refuses to run on a dirty tree, so the bump lands first.
29
+ - Branch off the default branch (don't work on `main`/`master` directly):
30
+ `git checkout -b sync/rhiza-<target>`.
31
+ - Edit only `ref:` in `.rhiza/template.yml` to the target version.
32
+ - Commit just that change (e.g. `Chore: bump rhiza template ref <old> → <target>`).
33
+
34
+ ## 3. Sync
35
+
36
+ - Run `make sync` (it invokes `rhiza sync`). Expect it to either complete
37
+ cleanly or report conflicts. It writes the refreshed `.rhiza/template.lock`.
38
+ - If it completes with no conflicts, skip to step 5.
39
+
40
+ ## 4. Resolve every conflict
41
+
42
+ The sync is a 3-way merge. Two kinds of leftovers can appear — handle both, and
43
+ finish with **zero** `*.rej` files and **zero** conflict markers
44
+ (`<<<<<<<` / `=======` / `>>>>>>>`) anywhere tracked
45
+ (`git grep -lE '^(<<<<<<<|=======|>>>>>>>)'`).
46
+
47
+ **`*.rej` files (rejected hunks).** The 3-way merge often *already applied* a
48
+ hunk and still drops a duplicate `.rej`. For each, verify whether the change is
49
+ already present in the file (the added `+` lines exist; no conflict markers
50
+ remain). If it is, the `.rej` is spurious — delete it. If a hunk genuinely did
51
+ not apply, apply it by hand, then delete the `.rej`.
52
+
53
+ **Conflict-marked files.** Resolve by the ownership rule (see `CLAUDE.md` and the
54
+ `files:` block of `.rhiza/template.lock` for the authoritative managed-file list):
55
+
56
+ - **Rhiza-managed files** (the `.github/workflows/*`, `Makefile`,
57
+ `.pre-commit-config.yaml`, `pytest.ini`, the `.rhiza/` engine, etc.): take the
58
+ **incoming/upstream** side — these are owned by the template and should match
59
+ it (`git checkout --theirs -- <file>` then `git add`).
60
+ - **Locally-owned or locally-hardened files** (notably `ruff.toml`, plus
61
+ `pyproject.toml`, `README.md`, `src/`, your `tests/`): **merge by hand** —
62
+ keep the local intent (e.g. stricter lint rules) while folding in genuine
63
+ upstream additions, and make the result internally coherent (dedupe, drop
64
+ comments that now contradict the config).
65
+
66
+ Validate every touched workflow/YAML still parses before moving on.
67
+
68
+ ## 5. Verify the gates and fix fallout
69
+
70
+ A version bump can tighten the gates (new lint rules, `mypy --strict`, expanded
71
+ docs-coverage scope, etc.) and surface pre-existing issues. Run them and get
72
+ them green:
73
+
74
+ 1. `make fmt` — pre-commit + lint
75
+ 2. `make typecheck`
76
+ 3. `make docs-coverage`
77
+ 4. `make deptry`
78
+ 5. `make security`
79
+ 6. `make test`
80
+
81
+ **Scope your fixes.** Fix issues only in **locally-owned** files (`src/`,
82
+ `tests/`, `pyproject.toml`, locally-hardened config). If a gate fails because of
83
+ a **Rhiza-managed** file, that is an upstream problem: fix it in
84
+ `jebel-quant/rhiza` and bump again — do **not** edit the synced artifact in
85
+ place. Call out any such upstream-owned failure explicitly rather than papering
86
+ over it locally.
87
+
88
+ ## 6. Commit, push, open a PR
89
+
90
+ - Commit the resolution and any in-scope fixes with clear messages (one logical
91
+ change per commit: the conflict resolution, then each gate fix).
92
+ - Push the branch and open a PR (`gh pr create`) titled for the bump, e.g.
93
+ `Chore: sync Rhiza template <old> → <target>`. In the body, summarize how each
94
+ conflict was resolved, list any gate fallout you fixed, and flag anything that
95
+ needs an **upstream** fix in Rhiza.
96
+ - Report a concise per-gate PASS/FAIL summary. If the workflow files changed,
97
+ note that pushing them needs a token with the `workflow` scope.
98
+
99
+ Do not merge the PR. Stop after it is open and summarize what landed and what
100
+ (if anything) is blocked on an upstream Rhiza change.
@@ -0,0 +1,41 @@
1
+ # This file is part of the jebel-quant/rhiza repository
2
+ # (https://github.com/jebel-quant/rhiza).
3
+ #
4
+ root = true
5
+
6
+ # Default settings for all files
7
+ [*]
8
+ end_of_line = lf
9
+ trim_trailing_whitespace = true
10
+ insert_final_newline = true
11
+ charset = utf-8
12
+
13
+ # Python, reStructuredText, and text files
14
+ [*.{py,rst,txt}]
15
+ indent_style = space
16
+ indent_size = 4
17
+
18
+ # YAML, JSON, and other config files
19
+ [*.{yml,yaml,json}]
20
+ indent_style = space
21
+ indent_size = 2
22
+
23
+ # Markdown files
24
+ # [*.{md,markdown}]
25
+ # trim_trailing_whitespace = false
26
+
27
+ # Makefiles require tabs
28
+ [{Makefile,*.mk,*.make}]
29
+ indent_style = tab
30
+ indent_size = 4
31
+
32
+ # Don't apply editorconfig rules to vendor/ resources
33
+ # This is a "defensive" rule for the day we may have
34
+ # the vendor folder
35
+ [vendor/**]
36
+ charset = unset
37
+ end_of_line = unset
38
+ indent_size = unset
39
+ indent_style = unset
40
+ insert_final_newline = unset
41
+ trim_trailing_whitespace = unset
@@ -0,0 +1,66 @@
1
+ # GitHub Actions Configuration
2
+
3
+ This document describes the secrets used by the Rhiza-provided GitHub Actions workflows
4
+ (`.github/workflows/rhiza_*.yml`) and how to configure them.
5
+
6
+ ## PAT_TOKEN (template sync)
7
+
8
+ The sync workflow (`.github/workflows/rhiza_sync.yml`) keeps your repository up to date with the
9
+ upstream Rhiza template. It commits the synced files directly to a branch or opens a pull request.
10
+
11
+ By default the workflow authenticates with the automatic `github.token`. That token **cannot push
12
+ changes to files under `.github/workflows/`** — GitHub rejects such pushes unless the token has the
13
+ `workflow` scope. Since template syncs regularly update workflow files, you should configure a
14
+ Personal Access Token (PAT) with that scope and store it as a repository secret named `PAT_TOKEN`.
15
+
16
+ If `PAT_TOKEN` is not configured, the workflow falls back to `github.token` and prints a warning.
17
+ Syncs that touch only non-workflow files will still succeed.
18
+
19
+ ### Creating the token
20
+
21
+ **Fine-grained PAT** (recommended):
22
+
23
+ 1. Go to **Settings → Developer settings → Fine-grained tokens → Generate new token**
24
+ (<https://github.com/settings/personal-access-tokens/new>).
25
+ 2. Restrict **Repository access** to the repository (or repositories) using Rhiza.
26
+ 3. Under **Repository permissions**, grant:
27
+ - **Contents**: Read and write
28
+ - **Workflows**: Read and write
29
+ - **Pull requests**: Read and write (needed for the scheduled sync-PR mode)
30
+ 4. Generate the token and copy it.
31
+
32
+ **Classic PAT** (alternative):
33
+
34
+ 1. Go to **Settings → Developer settings → Tokens (classic) → Generate new token**.
35
+ 2. Select the `repo` and `workflow` scopes.
36
+ 3. Generate the token and copy it.
37
+
38
+ ### Storing the secret
39
+
40
+ In the repository that consumes Rhiza:
41
+
42
+ 1. Go to **Settings → Secrets and variables → Actions → New repository secret**.
43
+ 2. Name: `PAT_TOKEN`
44
+ 3. Value: the token created above.
45
+
46
+ Or with the GitHub CLI:
47
+
48
+ ```bash
49
+ gh secret set PAT_TOKEN
50
+ ```
51
+
52
+ A PAT expires; when sync pushes start failing with a `refusing to allow ... workflow` error,
53
+ regenerate the token and update the secret.
54
+
55
+ ## Release workflow secrets (optional)
56
+
57
+ The release workflow (`.github/workflows/rhiza_release.yml`) supports additional secrets, all
58
+ optional depending on which release features you use:
59
+
60
+ | Secret | Purpose |
61
+ | --- | --- |
62
+ | `PYPI_TOKEN` | Publish the built package to PyPI. Not needed when using trusted publishing (OIDC). |
63
+ | `GH_PAT` | Git authentication for installing private dependencies during the release build. |
64
+ | `UV_EXTRA_INDEX_URL` | Extra package index URL (with credentials) for private dependencies. |
65
+
66
+ `GITHUB_TOKEN` is provided automatically by GitHub Actions and needs no configuration.
@@ -0,0 +1,48 @@
1
+ title: "[Help Wanted] "
2
+ labels: ["help wanted"]
3
+ body:
4
+ - type: markdown
5
+ attributes:
6
+ value: |
7
+ Use this template to surface a contribution opportunity. It lets maintainers
8
+ describe work that is ready to be picked up — without opening a formal issue.
9
+
10
+ - type: input
11
+ id: area
12
+ attributes:
13
+ label: Topic / Area
14
+ description: Which part of the project does this involve?
15
+ placeholder: e.g. CI workflows, documentation, a specific bundle
16
+ validations:
17
+ required: true
18
+
19
+ - type: textarea
20
+ id: help-needed
21
+ attributes:
22
+ label: What Help Is Needed
23
+ description: Describe the task and what "done" looks like.
24
+ validations:
25
+ required: true
26
+
27
+ - type: textarea
28
+ id: getting-started
29
+ attributes:
30
+ label: Getting Started
31
+ description: Pointers to relevant files, docs, or prior discussion that help a contributor begin.
32
+ placeholder: |
33
+ - Relevant files: ...
34
+ - Related docs: ...
35
+ validations:
36
+ required: false
37
+
38
+ - type: dropdown
39
+ id: skill-level
40
+ attributes:
41
+ label: Skill Level
42
+ description: Roughly how much experience is needed to take this on?
43
+ options:
44
+ - Good first issue (beginner friendly)
45
+ - Intermediate
46
+ - Advanced
47
+ validations:
48
+ required: false
@@ -0,0 +1,40 @@
1
+ title: "[Idea] "
2
+ labels: ["enhancement"]
3
+ body:
4
+ - type: markdown
5
+ attributes:
6
+ value: |
7
+ Propose an idea before implementing it. This lightweight RFC process lets the
8
+ community gauge interest and shape the design before any code is written.
9
+
10
+ - type: textarea
11
+ id: idea
12
+ attributes:
13
+ label: The Idea
14
+ description: What are you proposing? Describe it clearly enough that others can react.
15
+ validations:
16
+ required: true
17
+
18
+ - type: textarea
19
+ id: motivation
20
+ attributes:
21
+ label: Motivation
22
+ description: What problem does this solve, and who benefits?
23
+ validations:
24
+ required: true
25
+
26
+ - type: textarea
27
+ id: alternatives
28
+ attributes:
29
+ label: Alternatives Considered
30
+ description: Other approaches you weighed, and why this one is preferable.
31
+ validations:
32
+ required: false
33
+
34
+ - type: textarea
35
+ id: references
36
+ attributes:
37
+ label: References
38
+ description: Links to prior art, related discussions, issues, or external resources.
39
+ validations:
40
+ required: false
@@ -0,0 +1,25 @@
1
+ title: "[Question] "
2
+ labels: ["question"]
3
+ body:
4
+ - type: markdown
5
+ attributes:
6
+ value: |
7
+ Welcome! Use this space to ask questions, share how your use-case, or explore ideas with the community.
8
+
9
+ - type: textarea
10
+ id: question
11
+ attributes:
12
+ label: Your Question or Topic
13
+ description: What would you like to discuss?
14
+ validations:
15
+ required: true
16
+
17
+ - type: textarea
18
+ id: context
19
+ attributes:
20
+ label: Context
21
+ description: Any relevant code, configuration, or background that helps frame your question.
22
+ placeholder: |
23
+ ```python
24
+ # your code snippet here
25
+ ```
@@ -0,0 +1,57 @@
1
+ name: Bug Report
2
+ description: Report a bug or unexpected behaviour
3
+ labels: ["bug"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for taking the time to report a bug. Please fill out the sections below.
9
+
10
+ - type: textarea
11
+ id: description
12
+ attributes:
13
+ label: Description
14
+ description: A clear and concise description of what the bug is.
15
+ placeholder: What happened?
16
+ validations:
17
+ required: true
18
+
19
+ - type: textarea
20
+ id: steps
21
+ attributes:
22
+ label: Steps to reproduce
23
+ description: Minimal steps to reproduce the behaviour.
24
+ placeholder: |
25
+ 1. Run `make ...`
26
+ 2. See error
27
+ validations:
28
+ required: true
29
+
30
+ - type: textarea
31
+ id: expected
32
+ attributes:
33
+ label: Expected behaviour
34
+ description: What did you expect to happen?
35
+ validations:
36
+ required: true
37
+
38
+ - type: textarea
39
+ id: environment
40
+ attributes:
41
+ label: Environment
42
+ description: |
43
+ Relevant versions and system info. Run `make info` if available.
44
+ placeholder: |
45
+ - OS: macOS 14 / Ubuntu 24.04 / Windows 11
46
+ - Python: 3.13.x
47
+ - rhiza version:
48
+ validations:
49
+ required: false
50
+
51
+ - type: textarea
52
+ id: context
53
+ attributes:
54
+ label: Additional context
55
+ description: Logs, screenshots, or anything else that may be helpful.
56
+ validations:
57
+ required: false
@@ -0,0 +1,41 @@
1
+ name: Feature Request
2
+ description: Suggest a new feature or enhancement
3
+ labels: ["enhancement"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for proposing a feature. Please align with the team before investing significant effort.
9
+
10
+ - type: textarea
11
+ id: problem
12
+ attributes:
13
+ label: Problem / motivation
14
+ description: What problem does this solve? Why is it valuable?
15
+ placeholder: As a contributor I find it hard to ... because ...
16
+ validations:
17
+ required: true
18
+
19
+ - type: textarea
20
+ id: solution
21
+ attributes:
22
+ label: Proposed solution
23
+ description: Describe the solution you have in mind.
24
+ validations:
25
+ required: true
26
+
27
+ - type: textarea
28
+ id: alternatives
29
+ attributes:
30
+ label: Alternatives considered
31
+ description: Other approaches you have considered and why you ruled them out.
32
+ validations:
33
+ required: false
34
+
35
+ - type: textarea
36
+ id: context
37
+ attributes:
38
+ label: Additional context
39
+ description: Links, mockups, prior art, or anything else that may be helpful.
40
+ validations:
41
+ required: false