Conversation
📝 WalkthroughWalkthroughThis PR syncs the repository with the Rhiza template, introducing Git authentication for private packages via a new GitHub Action, restructuring the build system with modular Makefile fragments, adding comprehensive test suites across multiple categories, updating CI/CD workflows with new dependency versions, and reorganizing core automation targets. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/rhiza_release.yml (1)
327-337:⚠️ Potential issue | 🟠 MajorMissing git auth step in
finalise-releasebeforeuv sync.The
finalise-releasejob runsuv sync --all-extras --all-groups --frozen(Line 337) without configuring git authentication for private packages. This step also runsuv run python -c ...(Line 359). If any dependency is a private GitHub-hosted package, these commands will fail without git auth configuration. Theconfigure-git-authaction is already used in the Build job and should be added here as well.Proposed fix: add git auth step in finalise-release
- name: Install uv uses: astral-sh/setup-uv@v7.3.0 with: version: "0.10.0" + - name: Configure git auth for private packages + uses: ./.github/actions/configure-git-auth + with: + token: ${{ secrets.GH_PAT }} + - name: "Sync the virtual environment for ${{ github.repository }}" shell: bash run: |
🤖 Fix all issues with AI agents
In @.github/actions/configure-git-auth/README.md:
- Around line 48-49: Add a single blank line before the "## Example Workflow"
heading so the preceding paragraph and the heading are separated; update the
README content near the sentence ending with "will fail with an authentication
error." to insert one blank line immediately before the "## Example Workflow"
heading to ensure proper Markdown rendering.
- Around line 77-80: The "See Also" links in the README's "See Also" section
reference non-existent docs (.rhiza/docs/PRIVATE_PACKAGES.md and
.rhiza/docs/TOKEN_SETUP.md); either create those two markdown files under
.rhiza/docs with the intended guidance (PRIVATE_PACKAGES.md and TOKEN_SETUP.md)
or remove/replace the two bullet links in the README.md See Also list so they no
longer point to missing files—if replacing, update to the correct existing doc
paths or add a short note pointing to the appropriate alternative docs.
In @.rhiza/make.d/docs.mk:
- Around line 28-62: The shell expands $$PKGS, $$TEMPLATE_ARG and $$LOGO_ARG
unquoted into the final pdoc invocation which can break on paths/spaces; fix by
(1) building package list as a proper shell array (e.g., PKG_LIST and append
basename parts as quoted entries) and expand it as "${PKG_LIST[@]}", and (2)
ensure TEMPLATE_ARG and LOGO_ARG are quoted when passed to the command (use
"$$TEMPLATE_ARG" and "$$LOGO_ARG") in the ${UV_BIN} run pdoc --docformat ...
--output-dir _pdoc invocation so each argument with spaces remains a single
token.
In @.rhiza/make.d/quality.mk:
- Around line 8-19: The deptry Make target runs deptry on SOURCE_FOLDER twice
when both SOURCE_FOLDER and MARIMO_FOLDER exist; update the deptry target so the
second invocation does not re-include SOURCE_FOLDER (only run deptry on
MARIMO_FOLDER with --ignore DEP004) or otherwise ensure SOURCE_FOLDER is
excluded from the second $(UVX_BIN) deptry call; modify the branch that
currently executes "$(UVX_BIN) -p ${PYTHON_VERSION} deptry ${MARIMO_FOLDER}
${SOURCE_FOLDER} --ignore DEP004" to only pass ${MARIMO_FOLDER} (keeping
${PYTHON_VERSION}, ${UVX_BIN} and the --ignore DEP004 flag intact).
In @.rhiza/rhiza.mk:
- Around line 108-115: Add the phony declaration for the rhiza-test target:
locate the .PHONY blocks (the main block around the top of the Makefile and the
secondary one near line ~75) and add "rhiza-test" to one of them (preferably the
main .PHONY list where other test/validate targets live) so the rhiza-test
target is treated as phony and won’t collide with any file named "rhiza-test".
In @.rhiza/tests/api/test_makefile_targets.py:
- Around line 251-254: Remove the unnecessary "# noqa: E501" directive at the
end of the triple-quoted test string; locate the block containing the re.sub
call (the lines with new_content = re.sub(...),
pyproject.write_text(new_content), and the print f-string) and delete the
trailing " # noqa: E501" so the test no longer contains the unused noqa
annotation.
In @.rhiza/tests/conftest.py:
- Line 18: The import line in conftest.py includes an unused "# noqa: F401"
directive; remove the trailing comment from the import statement (the one that
imports GIT, MAKE, run_make, setup_rhiza_git_repo, strip_ansi) so the line
simply reads the import without the "# noqa: F401" comment; run ruff (or lint)
to confirm the unused noqa is gone.
In @.rhiza/tests/integration/test_notebook_execution.py:
- Around line 15-25: The docstring for collect_marimo_notebooks says the
fallback MARIMO_FOLDER is "marimo" but the code sets marimo_folder =
values.get("MARIMO_FOLDER", "book/marimo/notebooks"); update the function so the
default used in the values.get call matches the docstring (use "marimo") or, if
the intended path is the longer one, update the docstring accordingly; locate
the marimo_folder assignment in collect_marimo_notebooks and make the default
string consistent with the docstring.
In @.rhiza/tests/sync/test_rhiza_version.py:
- Around line 102-110: The test test_summarise_sync_skips_in_rhiza_repo fails
because running run_make(..., dry_run=True) uses make -n so the printf inside
the summarise-sync recipe (currently prefixed by @) is not executed and nothing
is printed; update the summarise-sync entry in rhiza.mk to emit the skip message
at parse time using $(info "Skipping summarise-sync in rhiza repository")
instead of printf (or remove the leading @ on the printf if you prefer to keep a
recipe-time message), so the message appears even when make is run with -n;
alternatively adjust the test test_summarise_sync_skips_in_rhiza_repo to not
assert on stdout when dry_run=True if you opt not to change the Makefile.
- Around line 41-59: Rename the test function
test_rhiza_version_defaults_to_0_9_0_without_file to reflect the asserted
default version (e.g., test_rhiza_version_defaults_to_0_10_2_without_file) so
the name matches the expectation in the assertion that checks for "0.10.2";
update only the function name (leave the assertion and body unchanged) and run
tests to ensure no other references need adjusting.
In @.rhiza/tests/utils/test_git_repo_fixture.py:
- Around line 52-56: Rename the test function
test_git_repo_has_github_scripts_directory to
test_git_repo_has_rhiza_scripts_directory and update its docstring to accurately
describe the checked path (e.g., '".rhiza/scripts" directory'), so the name and
docstring match the assertions that inspect git_repo / ".rhiza" / "scripts" and
release.sh; leave the assertions unchanged.
🧹 Nitpick comments (24)
.rhiza/make.d/agentic.mk (1)
52-70:install-claudelacks the local-binary fallback thatinstall-copilothas.
install-copilot(lines 29-50) has a three-way check: PATH →INSTALL_DIRbinary → prompt install.install-claudeonly checks PATH before prompting. After a successful install to~/.local/bin/claude, if that path isn't in$PATH, the next invocation will prompt to install again.This is likely fine if the installer script updates PATH or the shell profile, but worth confirming.
.rhiza/.cfg.toml (1)
34-37: Commented-out configuration left as a placeholder.If this is intentional scaffolding for future use, consider adding a brief comment explaining when/why it would be uncommented, so future maintainers don't treat it as dead config.
.rhiza/make.d/test.mk (1)
26-41: Unquoted${SOURCE_FOLDER}in shell conditionals could break with spaces in paths.Lines 27, 37–40 use unquoted
${SOURCE_FOLDER}. While this is consistent with the rest of the file, paths containing spaces would cause shell word-splitting issues. Consider quoting for robustness:🛡️ Suggested quoting
- if [ -d ${SOURCE_FOLDER} ]; then \ + if [ -d "${SOURCE_FOLDER}" ]; then \.rhiza/tests/deps/test_dependency_health.py (1)
35-37: Dead code:README.mdguard is unreachable withglob("*.txt").The
glob("*.txt")pattern on lines 35 and 69 will never yield a file namedREADME.md, making theif req_file.name == "README.md": continuechecks on lines 36 and 70 unreachable.♻️ Remove the dead guards
for req_file in requirements_dir.glob("*.txt"): - if req_file.name == "README.md": - continueAlso applies to: 69-71
.rhiza/tests/api/test_makefile_targets.py (1)
201-217: Commented-out assertions reduce test effectiveness.Lines 206–207 and 215–216 have the actual assertions commented out, leaving only
returncode == 0checks. These tests verify thatvalidateandsynctargets succeed in a rhiza repo context but don't confirm the skip behavior described in the docstrings. Consider re-enabling the assertions or updating the docstrings to reflect what's actually being tested..github/workflows/rhiza_sync.yml (1)
52-53: UV version not pinned in this workflow, unlike others.Other workflows in this PR (e.g.,
rhiza_ci.yml,rhiza_book.yml,rhiza_marimo.yml) pinversion: "0.10.0"in thesetup-uvstep. This workflow omits theversioninput, which means it will use whatever default the action provides. This could lead to inconsistentuv/uvxbehavior across workflows.Proposed fix
- name: Install uv uses: astral-sh/setup-uv@v7.3.0 + with: + version: "0.10.0".github/workflows/rhiza_mypy.yml (1)
37-38: This workflow is a no-op — consider disabling it.The only functional step (
make -f .rhiza/rhiza.mk mypy) is commented out. This job will consume CI runner time just to checkout and configure git auth without performing any checks. Consider either enabling the mypy step or removing/disabling this workflow until it's ready..rhiza/tests/structure/test_project_layout.py (1)
35-37:pytest.skip()in a loop short-circuits on the first missing optional directory.
pytest.skip()raisesSkippedimmediately, so ifsrcis absent, the test is skipped without ever checkingtestsorbook. The same pattern applies to the optional files loop (lines 55-57).If the intent is "skip when none of the optional dirs are present," collect results first. If the intent is "skip when any is missing," the current behavior is correct but the skip message is misleading — it implies only one dir was checked.
♻️ Suggested approach if you want to report all missing optional dirs
- for dirname in optional_dirs: - if not (root / dirname).exists(): - pytest.skip(f"Optional directory {dirname} not present in this project") + missing = [d for d in optional_dirs if not (root / d).exists()] + if missing: + pytest.skip(f"Optional directories not present: {', '.join(missing)}")Same pattern for the optional files loop at lines 55-57.
.rhiza/tests/sync/conftest.py (1)
40-52: Hardcoded makefile list duplicatesSPLIT_MAKEFILESinapi/conftest.py.This list mirrors the one in
.rhiza/tests/api/conftest.py(lines 25-38) but uses bare filenames instead of full relative paths. If a new.mkfile is added or removed, both lists must be updated in lockstep. Consider importing or sharing a single source of truth for this list..rhiza/tests/sync/test_rhiza_version.py (1)
49-57: Move imports to module level; use the sharedMAKEconstant.
osandsubprocessare imported inline, and Line 55 hardcodes"/usr/bin/make"instead of reusing theMAKEconstant fromtest_utils(already imported at the top forrun_make).Proposed fix
At the top of the file, add:
from test_utils import run_make, strip_ansi, MAKEThen in the test:
- import os - import subprocess - - env = os.environ.copy() + env = os.environ.copy() # os already imported at module level if needed env.pop("RHIZA_VERSION", None) - cmd = ["/usr/bin/make", "-s", "print-RHIZA_VERSION"] + cmd = [MAKE, "-s", "print-RHIZA_VERSION"].rhiza/tests/api/test_github_targets.py (1)
24-55: Redundantreturncode == 0assertions.
run_makewithcheck=True(default) already raisesAssertionErroron non-zero exit, so the explicitassert result.returncode == 0on Lines 31, 37, 43, 49, 55 is unreachable on failure. Not harmful, but adds noise..rhiza/make.d/docs.mk (1)
61-62:pdocis installed into the project venv; consider usinguvxfor consistency.
${UV_BIN} pip install pdocmutates the project's virtual environment, whereasmkdocs-build(Line 77) uses${UVX_BIN}for ephemeral, isolated tool execution. Usinguvxfor pdoc would avoid polluting the project venv and stay consistent with the mkdocs targets.Sketch
- ${UV_BIN} pip install pdoc && \ - PYTHONPATH="${SOURCE_FOLDER}" ${UV_BIN} run pdoc --docformat $$DOCFORMAT --output-dir _pdoc $$TEMPLATE_ARG $$LOGO_ARG $$PKGS; \ + PYTHONPATH="${SOURCE_FOLDER}" ${UVX_BIN} --with pdoc pdoc --docformat $$DOCFORMAT --output-dir _pdoc $$TEMPLATE_ARG $$LOGO_ARG $$PKGS; \.rhiza/tests/sync/test_readme_validation.py (1)
17-19: Inconsistent regex patterns for extracting Python code blocks.Lines 17 uses
CODE_BLOCK = re.compile(r"```python\n(.*?)```", re.DOTALL)at module scope, but Line 77 inline usesr"\``python\n(.*?)```"` with unnecessary backslash-escaping of backticks. The two patterns are functionally equivalent, but this divergence may cause confusion if one is updated without the other.Consider reusing the
CODE_BLOCKconstant on Line 77:Proposed fix
def test_readme_code_is_syntactically_valid(self, root): """Python code blocks in README should be syntactically valid.""" readme = root / "README.md" content = readme.read_text(encoding="utf-8") - code_blocks = re.findall(r"\`\`\`python\n(.*?)\`\`\`", content, re.DOTALL) + code_blocks = CODE_BLOCK.findall(content)Also applies to: 77-77
.rhiza/tests/api/conftest.py (2)
92-124:run_makeis a near-verbatim copy oftests/test_utils.py:run_make.The implementation here (Lines 92-124) is functionally identical to the one in
tests/test_utils.py(lines 24-52). SinceMAKEis already imported fromtest_utils(Line 21), consider importingrun_makedirectly as well to avoid maintaining two copies.The module docstring (Line 5) even claims it's "imported from test_utils," but it's actually redefined.
Proposed fix
-from test_utils import MAKE +from test_utils import MAKE, run_make # noqa: F401 (re-exported)Then remove the local
run_makedefinition (Lines 92-124). If the local version needs to diverge in the future, it can be re-added at that time.
127-135:setup_rhiza_git_repoalso duplicates.rhiza/tests/conftest.py(lines 55-62).The only difference is using
shutil.which("git")here vs. aGITconstant in the parent conftest. Both do the same thing. Consider consolidating into a single shared helper intest_utils..rhiza/tests/sync/test_docstrings.py (1)
109-117: Misleading failure summary message.The summary says
{len(failed_modules)} module(s)butfailed_modulesonly contains modules that failed, so this reads as "N tests across N failed modules" rather than the total number of modules tested. Consider tracking total modules separately for a more informative message.Proposed fix
if failed_modules: formatted = "\n".join(f" {name}: {failed}/{attempted} failed" for name, failed, attempted in failed_modules) msg = ( - f"Doctest summary: {total_tests} tests across {len(failed_modules)} module(s)\n" + f"Doctest summary: {total_tests} tests, {len(failed_modules)} module(s) with failures\n" f"Failures: {total_failures}\n" f"Failed modules:\n{formatted}" ).rhiza/tests/test_utils.py (1)
25-53:run_makeis duplicated verbatim from.rhiza/tests/api/conftest.py.Both this module (lines 25–53) and
.rhiza/tests/api/conftest.py(lines 91–123) contain an identicalrun_makeimplementation. Consider havingconftest.pyimport from this shared utility module to keep a single source of truth, since this file was explicitly created to avoid import issues..rhiza/tests/integration/test_notebook_execution.py (1)
62-73:-o /dev/nullis not portable to Windows.This is a minor note — if cross-platform support is ever needed,
/dev/nullwon't work on Windows. Fine if this toolchain is Linux/macOS only..rhiza/tests/integration/test_book_targets.py (1)
36-64: Misleading test function name.The name
test_book_folder_but_no_mksuggests it tests the scenario where the book folder exists butbook.mkis absent. However, the test actually skips whenbook.mkis missing (Line 43-44) and instead verifies behavior when the book folder is empty. Consider renaming to something liketest_empty_book_folderto align with the docstring and actual test logic..rhiza/rhiza.mk (1)
20-37: Duplicate.PHONYdeclarations across two blocks.Several targets (
print-logo,sync,validate,readme,pre-sync,post-sync,pre-validate,post-validate) are declared.PHONYboth at Lines 20-37 and again at Line 75. This is harmless but adds maintenance overhead — consider consolidating into a single declaration block.Also applies to: 75-75
.rhiza/tests/utils/test_git_repo_fixture.py (1)
46-50: Mock tool executability check only coversuv, notmake.The
git_repofixture (in.rhiza/tests/conftest.py, lines ~175-180) creates bothuvandmakemock executables. This test only verifiesuv. Consider adding"make"to the loop for completeness, though this is non-critical.Proposed fix
- for tool in ["uv"]: + for tool in ["uv", "make"]:.rhiza/tests/api/test_makefile_api.py (3)
84-90: Prefermonkeypatch.chdirover manualos.chdirwith try/finally.The
git_repofixture inconftest.pyusesmonkeypatch.chdir()for directory switching, which is automatically restored by pytest. This fixture manually managesos.chdirwith try/finally. While functionally correct, usingmonkeypatchis more idiomatic and resilient to edge cases. You'd need to addmonkeypatchto the fixture parameters.Proposed fix
`@pytest.fixture` -def setup_api_env(logger, root, tmp_path: Path): +def setup_api_env(logger, root, tmp_path: Path, monkeypatch): """Set up the Makefile API test environment in a temp folder.""" ... - # Move to tmp dir - old_cwd = Path.cwd() - os.chdir(tmp_path) - try: - yield tmp_path - finally: - os.chdir(old_cwd) + monkeypatch.chdir(tmp_path) + yield tmp_path
94-94: Remove unusednoqadirective.Static analysis (RUF100) confirms that the
E402rule is not enabled, so the# noqa: E402comment is unnecessary.Proposed fix
-from api.conftest import run_make # noqa: E402 +from api.conftest import run_make
176-182: Remove stream-of-consciousness developer notes.Lines 177-182 read like internal reasoning during development rather than informative code comments. Consider trimming to a concise explanation of the expected behavior with double-colon rules.
Proposed cleanup
# Run sync in dry-run. - # Note: Makefile.rhiza defines pre-sync as empty rule (or with @:). - # Make warns if we redefine a target unless it's a double-colon rule or we are careful. - # But usually the last one loaded wins or they merge if double-colon. - # The current definition in Makefile.rhiza is `pre-sync: ; `@echo` ...` or similar. - # Wait, I defined it as `pre-sync: ; @:` (single colon). - # So redefining it in local.mk (which is included AFTER) might trigger a warning but should work. + # pre-sync is a double-colon rule in rhiza.mk, so local.mk's definition + # accumulates rather than overrides.
| If you configure the step as in the example (`token: ${{ secrets.GH_PAT }}`) and `secrets.GH_PAT` is not defined, GitHub Actions passes an empty string to the action. The composite action then falls back to `github.token`, so the configuration step itself still succeeds. However, any subsequent step that tries to access private repositories that are not covered by the permissions of `GITHUB_TOKEN` will fail with an authentication error. | ||
| ## Example Workflow |
There was a problem hiding this comment.
Minor: Missing blank line before heading.
A blank line is missing before the ## Example Workflow heading on line 49, which may cause rendering issues in some Markdown parsers.
If you configure the step as in the example (`token: ${{ secrets.GH_PAT }}`) and `secrets.GH_PAT` is not defined, GitHub Actions passes an empty string to the action. The composite action then falls back to `github.token`, so the configuration step itself still succeeds. However, any subsequent step that tries to access private repositories that are not covered by the permissions of `GITHUB_TOKEN` will fail with an authentication error.
+
## Example Workflow📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| If you configure the step as in the example (`token: ${{ secrets.GH_PAT }}`) and `secrets.GH_PAT` is not defined, GitHub Actions passes an empty string to the action. The composite action then falls back to `github.token`, so the configuration step itself still succeeds. However, any subsequent step that tries to access private repositories that are not covered by the permissions of `GITHUB_TOKEN` will fail with an authentication error. | |
| ## Example Workflow | |
| If you configure the step as in the example (`token: ${{ secrets.GH_PAT }}`) and `secrets.GH_PAT` is not defined, GitHub Actions passes an empty string to the action. The composite action then falls back to `github.token`, so the configuration step itself still succeeds. However, any subsequent step that tries to access private repositories that are not covered by the permissions of `GITHUB_TOKEN` will fail with an authentication error. | |
| ## Example Workflow |
🧰 Tools
🪛 LanguageTool
[uncategorized] ~48-~48: The official name of this software platform is spelled with a capital “H”.
Context: ...The composite action then falls back to github.token, so the configuration step itsel...
(GITHUB)
🤖 Prompt for AI Agents
In @.github/actions/configure-git-auth/README.md around lines 48 - 49, Add a
single blank line before the "## Example Workflow" heading so the preceding
paragraph and the heading are separated; update the README content near the
sentence ending with "will fail with an authentication error." to insert one
blank line immediately before the "## Example Workflow" heading to ensure proper
Markdown rendering.
| ## See Also | ||
|
|
||
| - [PRIVATE_PACKAGES.md](../../../.rhiza/docs/PRIVATE_PACKAGES.md) - Complete guide to using private packages | ||
| - [TOKEN_SETUP.md](../../../.rhiza/docs/TOKEN_SETUP.md) - Setting up Personal Access Tokens |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if the referenced documentation files exist in the repo
echo "--- Checking PRIVATE_PACKAGES.md ---"
fd "PRIVATE_PACKAGES.md" --type f
echo "--- Checking TOKEN_SETUP.md ---"
fd "TOKEN_SETUP.md" --type fRepository: tschm/monkeys
Length of output: 125
🏁 Script executed:
#!/bin/bash
# Check if .rhiza directory exists
echo "--- Checking .rhiza directory structure ---"
fd --type d "\.rhiza" --type d
echo ""
echo "--- Checking for docs subdirectories ---"
fd --type d "docs" --type dRepository: tschm/monkeys
Length of output: 142
Remove or create the referenced documentation files.
The "See Also" section links to .rhiza/docs/PRIVATE_PACKAGES.md and .rhiza/docs/TOKEN_SETUP.md, but neither file exists in the repository. Either create these documentation files or remove the broken links.
🤖 Prompt for AI Agents
In @.github/actions/configure-git-auth/README.md around lines 77 - 80, The "See
Also" links in the README's "See Also" section reference non-existent docs
(.rhiza/docs/PRIVATE_PACKAGES.md and .rhiza/docs/TOKEN_SETUP.md); either create
those two markdown files under .rhiza/docs with the intended guidance
(PRIVATE_PACKAGES.md and TOKEN_SETUP.md) or remove/replace the two bullet links
in the README.md See Also list so they no longer point to missing files—if
replacing, update to the correct existing doc paths or add a short note pointing
to the appropriate alternative docs.
| @if [ -d "${SOURCE_FOLDER}" ]; then \ | ||
| PKGS=""; for d in "${SOURCE_FOLDER}"/*; do [ -d "$$d" ] && PKGS="$$PKGS $$(basename "$$d")"; done; \ | ||
| if [ -z "$$PKGS" ]; then \ | ||
| printf "${YELLOW}[WARN] No packages found under ${SOURCE_FOLDER}, skipping docs${RESET}\n"; \ | ||
| else \ | ||
| TEMPLATE_ARG=""; \ | ||
| if [ -d "$(PDOC_TEMPLATE_DIR)" ]; then \ | ||
| TEMPLATE_ARG="-t $(PDOC_TEMPLATE_DIR)"; \ | ||
| printf "$(BLUE)[INFO] Using pdoc templates from $(PDOC_TEMPLATE_DIR)$(RESET)\n"; \ | ||
| fi; \ | ||
| DOCFORMAT="$(DOCFORMAT)"; \ | ||
| if [ -z "$$DOCFORMAT" ]; then \ | ||
| if [ -f "ruff.toml" ]; then \ | ||
| DOCFORMAT=$$(${UV_BIN} run python -c "import tomllib; print(tomllib.load(open('ruff.toml', 'rb')).get('lint', {}).get('pydocstyle', {}).get('convention', ''))"); \ | ||
| fi; \ | ||
| if [ -z "$$DOCFORMAT" ]; then \ | ||
| DOCFORMAT="google"; \ | ||
| fi; \ | ||
| printf "${BLUE}[INFO] Detected docformat: $$DOCFORMAT${RESET}\n"; \ | ||
| else \ | ||
| printf "${BLUE}[INFO] Using provided docformat: $$DOCFORMAT${RESET}\n"; \ | ||
| fi; \ | ||
| LOGO_ARG=""; \ | ||
| if [ -n "$(LOGO_FILE)" ]; then \ | ||
| if [ -f "$(LOGO_FILE)" ]; then \ | ||
| MIME=$$(file --mime-type -b "$(LOGO_FILE)"); \ | ||
| DATA=$$(base64 < "$(LOGO_FILE)" | tr -d '\n'); \ | ||
| LOGO_ARG="--logo data:$$MIME;base64,$$DATA"; \ | ||
| printf "${BLUE}[INFO] Embedding logo: $(LOGO_FILE)${RESET}\n"; \ | ||
| else \ | ||
| printf "${YELLOW}[WARN] Logo file $(LOGO_FILE) not found, skipping${RESET}\n"; \ | ||
| fi; \ | ||
| fi; \ | ||
| ${UV_BIN} pip install pdoc && \ | ||
| PYTHONPATH="${SOURCE_FOLDER}" ${UV_BIN} run pdoc --docformat $$DOCFORMAT --output-dir _pdoc $$TEMPLATE_ARG $$LOGO_ARG $$PKGS; \ |
There was a problem hiding this comment.
Unquoted shell variables risk word-splitting on paths with spaces.
$$PKGS, $$TEMPLATE_ARG, and $$LOGO_ARG are expanded unquoted on Line 62. If any package name or path contains spaces, this will break. While unlikely in practice for Python package names, $$TEMPLATE_ARG and $$LOGO_ARG contain paths that could have spaces.
🤖 Prompt for AI Agents
In @.rhiza/make.d/docs.mk around lines 28 - 62, The shell expands $$PKGS,
$$TEMPLATE_ARG and $$LOGO_ARG unquoted into the final pdoc invocation which can
break on paths/spaces; fix by (1) building package list as a proper shell array
(e.g., PKG_LIST and append basename parts as quoted entries) and expand it as
"${PKG_LIST[@]}", and (2) ensure TEMPLATE_ARG and LOGO_ARG are quoted when
passed to the command (use "$$TEMPLATE_ARG" and "$$LOGO_ARG") in the ${UV_BIN}
run pdoc --docformat ... --output-dir _pdoc invocation so each argument with
spaces remains a single token.
| deptry: install-uv ## Run deptry | ||
| @if [ -d ${SOURCE_FOLDER} ]; then \ | ||
| $(UVX_BIN) -p ${PYTHON_VERSION} deptry ${SOURCE_FOLDER}; \ | ||
| fi | ||
|
|
||
| @if [ -d ${MARIMO_FOLDER} ]; then \ | ||
| if [ -d ${SOURCE_FOLDER} ]; then \ | ||
| $(UVX_BIN) -p ${PYTHON_VERSION} deptry ${MARIMO_FOLDER} ${SOURCE_FOLDER} --ignore DEP004; \ | ||
| else \ | ||
| $(UVX_BIN) -p ${PYTHON_VERSION} deptry ${MARIMO_FOLDER} --ignore DEP004; \ | ||
| fi \ | ||
| fi |
There was a problem hiding this comment.
deptry analyzes SOURCE_FOLDER twice when both SOURCE_FOLDER and MARIMO_FOLDER exist.
When both directories are present, the target first runs deptry on SOURCE_FOLDER alone (line 10, no --ignore), then runs it again on MARIMO_FOLDER SOURCE_FOLDER (line 15, with --ignore DEP004). This means SOURCE_FOLDER gets analyzed twice with different flags, which could produce duplicate or contradictory output.
If the intent is to check SOURCE_FOLDER strictly (no ignores) and MARIMO_FOLDER leniently, consider excluding SOURCE_FOLDER from the second invocation:
♻️ Suggested fix
`@if` [ -d ${MARIMO_FOLDER} ]; then \
- if [ -d ${SOURCE_FOLDER} ]; then \
- $(UVX_BIN) -p ${PYTHON_VERSION} deptry ${MARIMO_FOLDER} ${SOURCE_FOLDER} --ignore DEP004; \
- else \
- $(UVX_BIN) -p ${PYTHON_VERSION} deptry ${MARIMO_FOLDER} --ignore DEP004; \
- fi \
+ $(UVX_BIN) -p ${PYTHON_VERSION} deptry ${MARIMO_FOLDER} --ignore DEP004; \
fi📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| deptry: install-uv ## Run deptry | |
| @if [ -d ${SOURCE_FOLDER} ]; then \ | |
| $(UVX_BIN) -p ${PYTHON_VERSION} deptry ${SOURCE_FOLDER}; \ | |
| fi | |
| @if [ -d ${MARIMO_FOLDER} ]; then \ | |
| if [ -d ${SOURCE_FOLDER} ]; then \ | |
| $(UVX_BIN) -p ${PYTHON_VERSION} deptry ${MARIMO_FOLDER} ${SOURCE_FOLDER} --ignore DEP004; \ | |
| else \ | |
| $(UVX_BIN) -p ${PYTHON_VERSION} deptry ${MARIMO_FOLDER} --ignore DEP004; \ | |
| fi \ | |
| fi | |
| deptry: install-uv ## Run deptry | |
| `@if` [ -d ${SOURCE_FOLDER} ]; then \ | |
| $(UVX_BIN) -p ${PYTHON_VERSION} deptry ${SOURCE_FOLDER}; \ | |
| fi | |
| `@if` [ -d ${MARIMO_FOLDER} ]; then \ | |
| $(UVX_BIN) -p ${PYTHON_VERSION} deptry ${MARIMO_FOLDER} --ignore DEP004; \ | |
| fi |
🤖 Prompt for AI Agents
In @.rhiza/make.d/quality.mk around lines 8 - 19, The deptry Make target runs
deptry on SOURCE_FOLDER twice when both SOURCE_FOLDER and MARIMO_FOLDER exist;
update the deptry target so the second invocation does not re-include
SOURCE_FOLDER (only run deptry on MARIMO_FOLDER with --ignore DEP004) or
otherwise ensure SOURCE_FOLDER is excluded from the second $(UVX_BIN) deptry
call; modify the branch that currently executes "$(UVX_BIN) -p ${PYTHON_VERSION}
deptry ${MARIMO_FOLDER} ${SOURCE_FOLDER} --ignore DEP004" to only pass
${MARIMO_FOLDER} (keeping ${PYTHON_VERSION}, ${UVX_BIN} and the --ignore DEP004
flag intact).
| rhiza-test: install ## run rhiza's own tests (if any) | ||
| @if [ -d ".rhiza/tests" ]; then \ | ||
| ${UV_BIN} run pytest .rhiza/tests; \ | ||
| else \ | ||
| printf "${YELLOW}[WARN] No .rhiza/tests directory found, skipping rhiza-tests${RESET}\n"; \ | ||
| fi | ||
|
|
||
| validate: pre-validate rhiza-test ## validate project structure against template repository as defined in .rhiza/template.yml |
There was a problem hiding this comment.
rhiza-test is missing from .PHONY declarations.
The rhiza-test target (Line 108) is not declared in either .PHONY block (Lines 20-37 or Line 75). Since it doesn't produce a file, it should be declared phony to avoid issues if a file named rhiza-test ever exists in the working directory.
Proposed fix
.PHONY: print-logo sync validate readme pre-sync post-sync pre-validate post-validate
+.PHONY: rhiza-testOr add it to the main .PHONY block at Lines 20-37.
🤖 Prompt for AI Agents
In @.rhiza/rhiza.mk around lines 108 - 115, Add the phony declaration for the
rhiza-test target: locate the .PHONY blocks (the main block around the top of
the Makefile and the secondary one near line ~75) and add "rhiza-test" to one of
them (preferably the main .PHONY list where other test/validate targets live) so
the rhiza-test target is treated as phony and won’t collide with any file named
"rhiza-test".
| import pytest | ||
|
|
||
| # Import shared helpers from test_utils (no __init__.py needed) | ||
| from test_utils import GIT, MAKE, run_make, setup_rhiza_git_repo, strip_ansi # noqa: F401 |
There was a problem hiding this comment.
Remove the unused noqa directive.
Ruff reports that the # noqa: F401 directive is unused because F401 is not enabled in the current Ruff configuration. The directive can be safely removed.
-from test_utils import GIT, MAKE, run_make, setup_rhiza_git_repo, strip_ansi # noqa: F401
+from test_utils import GIT, MAKE, run_make, setup_rhiza_git_repo, strip_ansi📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| from test_utils import GIT, MAKE, run_make, setup_rhiza_git_repo, strip_ansi # noqa: F401 | |
| from test_utils import GIT, MAKE, run_make, setup_rhiza_git_repo, strip_ansi |
🧰 Tools
🪛 Ruff (0.14.14)
[warning] 18-18: Unused noqa directive (non-enabled: F401)
Remove unused noqa directive
(RUF100)
🤖 Prompt for AI Agents
In @.rhiza/tests/conftest.py at line 18, The import line in conftest.py includes
an unused "# noqa: F401" directive; remove the trailing comment from the import
statement (the one that imports GIT, MAKE, run_make, setup_rhiza_git_repo,
strip_ansi) so the line simply reads the import without the "# noqa: F401"
comment; run ruff (or lint) to confirm the unused noqa is gone.
| def collect_marimo_notebooks(env_path: Path = RHIZA_ENV_PATH): | ||
| """Return a sorted list of notebook script Paths discovered from .rhiza/.env. | ||
|
|
||
| - Reads MARIMO_FOLDER from .rhiza/.env (if present), otherwise falls back to "marimo". | ||
| - Returns [] if the folder does not exist. | ||
| """ | ||
| values = {} | ||
| if env_path.exists(): | ||
| values = dotenv_values(env_path) | ||
|
|
||
| marimo_folder = values.get("MARIMO_FOLDER", "book/marimo/notebooks") |
There was a problem hiding this comment.
Docstring says fallback is "marimo" but code uses "book/marimo/notebooks".
Line 18 states the default is "marimo", while line 25 actually defaults to "book/marimo/notebooks".
Proposed fix
"""Return a sorted list of notebook script Paths discovered from .rhiza/.env.
- - Reads MARIMO_FOLDER from .rhiza/.env (if present), otherwise falls back to "marimo".
+ - Reads MARIMO_FOLDER from .rhiza/.env (if present), otherwise falls back to "book/marimo/notebooks".
- Returns [] if the folder does not exist.
"""📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def collect_marimo_notebooks(env_path: Path = RHIZA_ENV_PATH): | |
| """Return a sorted list of notebook script Paths discovered from .rhiza/.env. | |
| - Reads MARIMO_FOLDER from .rhiza/.env (if present), otherwise falls back to "marimo". | |
| - Returns [] if the folder does not exist. | |
| """ | |
| values = {} | |
| if env_path.exists(): | |
| values = dotenv_values(env_path) | |
| marimo_folder = values.get("MARIMO_FOLDER", "book/marimo/notebooks") | |
| def collect_marimo_notebooks(env_path: Path = RHIZA_ENV_PATH): | |
| """Return a sorted list of notebook script Paths discovered from .rhiza/.env. | |
| - Reads MARIMO_FOLDER from .rhiza/.env (if present), otherwise falls back to "book/marimo/notebooks". | |
| - Returns [] if the folder does not exist. | |
| """ | |
| values = {} | |
| if env_path.exists(): | |
| values = dotenv_values(env_path) | |
| marimo_folder = values.get("MARIMO_FOLDER", "book/marimo/notebooks") |
🤖 Prompt for AI Agents
In @.rhiza/tests/integration/test_notebook_execution.py around lines 15 - 25,
The docstring for collect_marimo_notebooks says the fallback MARIMO_FOLDER is
"marimo" but the code sets marimo_folder = values.get("MARIMO_FOLDER",
"book/marimo/notebooks"); update the function so the default used in the
values.get call matches the docstring (use "marimo") or, if the intended path is
the longer one, update the docstring accordingly; locate the marimo_folder
assignment in collect_marimo_notebooks and make the default string consistent
with the docstring.
| def test_rhiza_version_defaults_to_0_9_0_without_file(self, logger, tmp_path): | ||
| """RHIZA_VERSION should default to 0.10.2 if .rhiza-version doesn't exist.""" | ||
| # Remove the .rhiza-version file | ||
| version_file = tmp_path / ".rhiza" / ".rhiza-version" | ||
| if version_file.exists(): | ||
| version_file.unlink() | ||
|
|
||
| # Clear RHIZA_VERSION from environment to test the default value | ||
| import os | ||
| import subprocess | ||
|
|
||
| env = os.environ.copy() | ||
| env.pop("RHIZA_VERSION", None) | ||
|
|
||
| cmd = ["/usr/bin/make", "-s", "print-RHIZA_VERSION"] | ||
| logger.info("Running command: %s", " ".join(cmd)) | ||
| proc = subprocess.run(cmd, capture_output=True, text=True, env=env) | ||
| out = strip_ansi(proc.stdout) | ||
| assert "Value of RHIZA_VERSION:\n0.10.2" in out |
There was a problem hiding this comment.
Method name says 0_9_0 but the expected default is 0.10.2.
test_rhiza_version_defaults_to_0_9_0_without_file asserts the default is "0.10.2" (Line 59), contradicting the method name. This will confuse future maintainers.
Proposed fix
- def test_rhiza_version_defaults_to_0_9_0_without_file(self, logger, tmp_path):
+ def test_rhiza_version_defaults_to_0_10_2_without_file(self, logger, tmp_path):📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def test_rhiza_version_defaults_to_0_9_0_without_file(self, logger, tmp_path): | |
| """RHIZA_VERSION should default to 0.10.2 if .rhiza-version doesn't exist.""" | |
| # Remove the .rhiza-version file | |
| version_file = tmp_path / ".rhiza" / ".rhiza-version" | |
| if version_file.exists(): | |
| version_file.unlink() | |
| # Clear RHIZA_VERSION from environment to test the default value | |
| import os | |
| import subprocess | |
| env = os.environ.copy() | |
| env.pop("RHIZA_VERSION", None) | |
| cmd = ["/usr/bin/make", "-s", "print-RHIZA_VERSION"] | |
| logger.info("Running command: %s", " ".join(cmd)) | |
| proc = subprocess.run(cmd, capture_output=True, text=True, env=env) | |
| out = strip_ansi(proc.stdout) | |
| assert "Value of RHIZA_VERSION:\n0.10.2" in out | |
| def test_rhiza_version_defaults_to_0_10_2_without_file(self, logger, tmp_path): | |
| """RHIZA_VERSION should default to 0.10.2 if .rhiza-version doesn't exist.""" | |
| # Remove the .rhiza-version file | |
| version_file = tmp_path / ".rhiza" / ".rhiza-version" | |
| if version_file.exists(): | |
| version_file.unlink() | |
| # Clear RHIZA_VERSION from environment to test the default value | |
| import os | |
| import subprocess | |
| env = os.environ.copy() | |
| env.pop("RHIZA_VERSION", None) | |
| cmd = ["/usr/bin/make", "-s", "print-RHIZA_VERSION"] | |
| logger.info("Running command: %s", " ".join(cmd)) | |
| proc = subprocess.run(cmd, capture_output=True, text=True, env=env) | |
| out = strip_ansi(proc.stdout) | |
| assert "Value of RHIZA_VERSION:\n0.10.2" in out |
🧰 Tools
🪛 Ruff (0.14.14)
[error] 57-57: subprocess call: check for execution of untrusted input
(S603)
🤖 Prompt for AI Agents
In @.rhiza/tests/sync/test_rhiza_version.py around lines 41 - 59, Rename the
test function test_rhiza_version_defaults_to_0_9_0_without_file to reflect the
asserted default version (e.g.,
test_rhiza_version_defaults_to_0_10_2_without_file) so the name matches the
expectation in the assertion that checks for "0.10.2"; update only the function
name (leave the assertion and body unchanged) and run tests to ensure no other
references need adjusting.
| def test_summarise_sync_skips_in_rhiza_repo(self, logger): | ||
| """Summarise-sync target should skip execution in rhiza repository.""" | ||
| # setup_rhiza_git_repo() is already called by fixture | ||
|
|
||
| proc = run_make(logger, ["summarise-sync"], dry_run=True) | ||
| # Should succeed but skip the actual summarise | ||
| assert proc.returncode == 0 | ||
| # Verify the skip message is in the output | ||
| assert "Skipping summarise-sync in rhiza repository" in proc.stdout |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check how the skip message is emitted in the summarise-sync target
rg -n "Skipping summarise-sync" --glob "*.mk" --glob "Makefile"Repository: tschm/monkeys
Length of output: 39
🏁 Script executed:
#!/bin/bash
# Search for "Skipping" messages in all files
rg -n "Skipping" --glob "*.mk" --glob "Makefile" -i
# Also search for summarise-sync target
echo "---"
rg -n "summarise-sync" --glob "*.mk" --glob "Makefile"Repository: tschm/monkeys
Length of output: 60
🏁 Script executed:
#!/bin/bash
# Search for "Skipping" in all files (not just makefiles)
rg -n "Skipping" -i
echo "---searching for summarise-sync---"
# Search for summarise-sync in all files
rg -n "summarise-sync"Repository: tschm/monkeys
Length of output: 91
🏁 Script executed:
#!/bin/bash
# Check if the test file exists
ls -la .rhiza/tests/sync/test_rhiza_version.py 2>&1
echo "---"
# List files in the test directory
ls -la .rhiza/tests/sync/ 2>&1
echo "---"
# Search for run_make function
rg -n "def run_make" -A 5Repository: tschm/monkeys
Length of output: 540
🏁 Script executed:
#!/bin/bash
# Read the test file
cat -n .rhiza/tests/sync/test_rhiza_version.pyRepository: tschm/monkeys
Length of output: 6675
🏁 Script executed:
#!/bin/bash
# Find test_utils module
fd -n "test_utils" -type f
echo "---"
# Search for Makefile files
fd -n "Makefile" -type f
echo "---"
# Search for summarise-sync in all Python and Make files
rg -l "summarise-sync"Repository: tschm/monkeys
Length of output: 543
🏁 Script executed:
#!/bin/bash
# Find test_utils module correctly
fd "test_utils" -type f
echo "---"
# Search for Makefile files
fd "Makefile" -type f
echo "---"
# Search for summarise-sync in all files
rg "summarise-sync"Repository: tschm/monkeys
Length of output: 423
🏁 Script executed:
#!/bin/bash
# Find test_utils module
find . -name "test_utils*" 2>/dev/null
echo "---"
# Find Makefile
find . -name "Makefile*" 2>/dev/null
echo "---"
# Search in all files for summarise-sync and skip message
rg "summarise-sync|Skipping" | head -20Repository: tschm/monkeys
Length of output: 104
🏁 Script executed:
#!/bin/bash
# Read test_utils.py
cat -n ./.rhiza/tests/test_utils.py
echo "---"
# Get size of Makefile
wc -l ./MakefileRepository: tschm/monkeys
Length of output: 2960
🏁 Script executed:
#!/bin/bash
# Read the entire Makefile
cat -n ./MakefileRepository: tschm/monkeys
Length of output: 469
🏁 Script executed:
#!/bin/bash
# Find rhiza.mk
find . -name "rhiza.mk" 2>/dev/null
echo "---"
# Get its size
wc -l ./.rhiza/rhiza.mk 2>/dev/nullRepository: tschm/monkeys
Length of output: 100
🏁 Script executed:
#!/bin/bash
# Read the rhiza.mk file
cat -n ./.rhiza/rhiza.mkRepository: tschm/monkeys
Length of output: 5956
The test will fail with dry_run=True because the skip message won't appear in output.
The summarise-sync target in .rhiza/rhiza.mk (lines 100-106) does emit the skip message via printf, but it's within a recipe prefixed with @. With make -sn, the @ suppresses command echo and -n prevents execution, so the printf output never reaches stdout. The test expects the message on line 110 but will get an empty string instead.
To fix this, either:
- Change the Makefile to use
$(info ...)(evaluated at parse time, appears in all modes) - Remove
@from the recipe so make prints what would execute - Update the test to not expect output when
dry_run=True
🤖 Prompt for AI Agents
In @.rhiza/tests/sync/test_rhiza_version.py around lines 102 - 110, The test
test_summarise_sync_skips_in_rhiza_repo fails because running run_make(...,
dry_run=True) uses make -n so the printf inside the summarise-sync recipe
(currently prefixed by @) is not executed and nothing is printed; update the
summarise-sync entry in rhiza.mk to emit the skip message at parse time using
$(info "Skipping summarise-sync in rhiza repository") instead of printf (or
remove the leading @ on the printf if you prefer to keep a recipe-time message),
so the message appears even when make is run with -n; alternatively adjust the
test test_summarise_sync_skips_in_rhiza_repo to not assert on stdout when
dry_run=True if you opt not to change the Makefile.
| def test_git_repo_has_github_scripts_directory(self, git_repo): | ||
| """Git repo should have .github/rhiza/scripts directory.""" | ||
| scripts_dir = git_repo / ".rhiza" / "scripts" | ||
| assert scripts_dir.exists() | ||
| assert (scripts_dir / "release.sh").exists() |
There was a problem hiding this comment.
Misleading test name and docstring — references .github but tests .rhiza.
The function name test_git_repo_has_github_scripts_directory and the docstring ".github/rhiza/scripts directory" both reference .github, but the test actually asserts against .rhiza/scripts (Line 54). Consider renaming to test_git_repo_has_rhiza_scripts_directory and updating the docstring.
Proposed fix
- def test_git_repo_has_github_scripts_directory(self, git_repo):
- """Git repo should have .github/rhiza/scripts directory."""
+ def test_git_repo_has_rhiza_scripts_directory(self, git_repo):
+ """Git repo should have .rhiza/scripts directory."""
scripts_dir = git_repo / ".rhiza" / "scripts"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def test_git_repo_has_github_scripts_directory(self, git_repo): | |
| """Git repo should have .github/rhiza/scripts directory.""" | |
| scripts_dir = git_repo / ".rhiza" / "scripts" | |
| assert scripts_dir.exists() | |
| assert (scripts_dir / "release.sh").exists() | |
| def test_git_repo_has_rhiza_scripts_directory(self, git_repo): | |
| """Git repo should have .rhiza/scripts directory.""" | |
| scripts_dir = git_repo / ".rhiza" / "scripts" | |
| assert scripts_dir.exists() | |
| assert (scripts_dir / "release.sh").exists() |
🤖 Prompt for AI Agents
In @.rhiza/tests/utils/test_git_repo_fixture.py around lines 52 - 56, Rename the
test function test_git_repo_has_github_scripts_directory to
test_git_repo_has_rhiza_scripts_directory and update its docstring to accurately
describe the checked path (e.g., '".rhiza/scripts" directory'), so the name and
docstring match the assertions that inspect git_repo / ".rhiza" / "scripts" and
release.sh; leave the assertions unchanged.
🔄 Template Synchronization
This PR synchronizes the repository with the jebel-quant/rhiza template.
📊 Change Summary
📁 Changes by Category
Configuration Files
Modified (3)
.gitignore.pre-commit-config.yamlpytest.iniGitHub Actions Workflows
Modified (11)
.github/workflows/rhiza_book.yml.github/workflows/rhiza_ci.yml.github/workflows/rhiza_codeql.yml.github/workflows/rhiza_deptry.yml.github/workflows/rhiza_marimo.yml.github/workflows/rhiza_mypy.yml.github/workflows/rhiza_pre-commit.yml.github/workflows/rhiza_release.yml.github/workflows/rhiza_security.yml.github/workflows/rhiza_sync.yml.github/workflows/rhiza_validate.ymlGitHub Configuration
Added (2)
.github/actions/configure-git-auth/README.md.github/actions/configure-git-auth/action.ymlRhiza Configuration
Added (26)
.rhiza/make.d/bootstrap.mk.rhiza/make.d/docs.mk.rhiza/make.d/quality.mk.rhiza/make.d/releasing.mk.rhiza/template-bundles.yml.rhiza/tests/README.md.rhiza/tests/api/conftest.py.rhiza/tests/api/test_github_targets.py.rhiza/tests/api/test_makefile_api.py.rhiza/tests/api/test_makefile_targets.py.rhiza/tests/conftest.py.rhiza/tests/deps/test_dependency_health.py.rhiza/tests/integration/test_book_targets.py.rhiza/tests/integration/test_marimushka.py.rhiza/tests/integration/test_notebook_execution.py.rhiza/tests/integration/test_release.py.rhiza/tests/structure/test_project_layout.py.rhiza/tests/structure/test_requirements.py.rhiza/tests/sync/conftest.py.rhiza/tests/sync/test_docstrings.py.rhiza/tests/sync/test_readme_validation.py.rhiza/tests/sync/test_rhiza_version.py.rhiza/tests/test_utils.py.rhiza/tests/utils/conftest.py.rhiza/tests/utils/test_git_repo_fixture.py.rhiza/tests/utils/test_version_matrix.pyModified (17)
.rhiza/.cfg.toml.rhiza/.env.rhiza/.rhiza-version.rhiza/history.rhiza/make.d/00-custom-env.mk .rhiza/make.d/custom-env.mk.rhiza/make.d/01-test.mk .rhiza/make.d/test.mk.rhiza/make.d/02-book.mk .rhiza/make.d/book.mk.rhiza/make.d/03-marimo.mk .rhiza/make.d/marimo.mk.rhiza/make.d/04-presentation.mk .rhiza/make.d/presentation.mk.rhiza/make.d/05-github.mk .rhiza/make.d/github.mk.rhiza/make.d/06-agentic.mk .rhiza/make.d/agentic.mk.rhiza/make.d/07-docker.mk .rhiza/make.d/docker.mk.rhiza/make.d/10-custom-task.mk .rhiza/make.d/custom-task.mk.rhiza/make.d/README.md.rhiza/requirements/tests.txt.rhiza/requirements/tools.txt.rhiza/rhiza.mkTests
Added (1)
tests/conftest.py🤖 Generated by rhiza
jebel-quant/rhiza@mainSummary by CodeRabbit
Release Notes
New Features
Improvements