Copier provenance#186
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds copier-managed provenance metadata, manifest ownership tracking, copier wiring updates, managed-file header rollouts, and asyncio task tracking utilities with tests. ChangesCopier-managed provenance and header system
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
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 |
Sync from copier-base-template: normalize all directory parts so conditional
dirs like {% if has_backend %}backend{% endif %} resolve correctly.
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tests/unit/copier_tasks/helpers.py (1)
12-23: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winPreserve inherited env vars in the subprocess helper.
Passing
env=directly replaces the whole environment, so callers that only want to tweakPATHalso drop everything else from the parent process state. Merge overrides intoos.environinstead.♻️ Proposed fix
+import os import subprocess import sys from pathlib import Path @@ return subprocess.run( # noqa: S603 -- these are our own scripts [sys.executable, str(script_path), *args], check=False, capture_output=True, text=True, - env=env, + env={**os.environ, **(env or {})}, )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/unit/copier_tasks/helpers.py` around lines 12 - 23, The helper run_copier_task currently passes env directly to subprocess.run which replaces the entire process environment; instead, merge any provided env overrides into a copy of the current environment (os.environ.copy()), apply the overrides, and pass that merged dict to subprocess.run so callers can tweak PATH or other vars without losing inherited environment variables.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.coderabbit.yaml:
- Around line 21-26: The PR touches copier-managed files but lacks the required
single summary comment; add one consolidated comment (not per-file) stating
which files in this change are listed in .copier-managed-files.json and that
these changes may need backporting to the owning template chain, and include the
template ownership info resolved from the manifest "templates" array by tracing
parent_src to the authoritative owner (use the manifest entries to map
.coderabbit.yaml, copier.yml, AGENTS.md, and
src/copier_tasks/copier_provenance.py to their template repo); ensure the
comment mentions that ownership is decided per template chain and not per-file.
In `@src/copier_tasks/copier_provenance.py`:
- Around line 106-121: The file marker write path in _write_file_marker uses
Path.open(file, "r+") without specifying encoding, risking locale-dependent
corruption for non-ASCII files; change the open call(s) to explicitly use
encoding="utf-8" (e.g., Path.open(file, "r+", encoding="utf-8")) so reads and
writes use UTF-8 consistently and avoid data loss when manipulating content in
_write_file_marker.
---
Outside diff comments:
In `@tests/unit/copier_tasks/helpers.py`:
- Around line 12-23: The helper run_copier_task currently passes env directly to
subprocess.run which replaces the entire process environment; instead, merge any
provided env overrides into a copy of the current environment
(os.environ.copy()), apply the overrides, and pass that merged dict to
subprocess.run so callers can tweak PATH or other vars without losing inherited
environment variables.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 6f8e2b78-31be-480e-be85-e8f7c1df343f
📒 Files selected for processing (96)
.coderabbit.yaml.copier-answers.yml.copier-managed-files.json.coveragerc.devcontainer/Dockerfile.devcontainer/create-aws-profile.sh.devcontainer/devcontainer.json.devcontainer/docker-compose.yml.devcontainer/initialize-command.sh.devcontainer/install-ci-tooling.py.devcontainer/manual-setup-deps.py.devcontainer/on-create-command-boilerplate.sh.devcontainer/on-create-command.sh.devcontainer/post-start-command.sh.devcontainer/windows-host-helper.sh.github/actions/check-skip-duplicates/action.yml.github/actions/install_deps/action.yml.github/actions/update-devcontainer-hash/action.yml.github/dependabot.yml.github/pull_request_template.md.github/reusable_workflows/build-docker-image.yaml.github/workflows/ci.yaml.github/workflows/confirm-on-tagged-copier-template.yaml.github/workflows/get-values.yaml.github/workflows/hash_git_files.py.github/workflows/pre-commit.yaml.github/workflows/replace_private_package_registries.py.github/workflows/tag-on-merge.yaml.github/zizmor.yml.gitignore.pre-commit-config.yamlAGENTS.mdCHANGELOG.mdCLAUDE.mdCODE_OF_CONDUCT.mdCONTRIBUTING.mdLICENSEREADME.md_typos.tomlcopier.ymlcopier_template_resources/eslint.config.mjscopier_template_resources/vcrpy_fixtures.pyextensions/context.pypylintrc.tomlpyproject.tomlpyrefly.tomlpytest.iniruff-non-src.tomlruff.tomlscripts/delete_false_positive_rej.pysh.batsrc/copier_tasks/__init__.pysrc/copier_tasks/copier_provenance.pysrc/copier_tasks/ensure_pnpm_minimum_release_age_exclude.pysrc/copier_tasks/remove_precommit_hooks.pytemplate/.coderabbit.yamltemplate/.copier-managed-files.jsontemplate/.coveragerctemplate/.devcontainer/Dockerfiletemplate/.devcontainer/initialize-command.shtemplate/.devcontainer/manual-setup-deps.pytemplate/.devcontainer/on-create-command-boilerplate.shtemplate/.devcontainer/windows-host-helper.shtemplate/.github/pull_request_template.mdtemplate/.github/workflows/confirm-on-tagged-copier-template.yamltemplate/.github/workflows/extract_project_version.pytemplate/.github/workflows/get-values.yamltemplate/.github/workflows/git_tag.pytemplate/.github/workflows/hash_git_files.pytemplate/.github/workflows/pre-commit.yamltemplate/.gitignoretemplate/.python-version.jinjatemplate/AGENTS.mdtemplate/CHANGELOG.mdtemplate/CLAUDE.mdtemplate/CONTRIBUTING.mdtemplate/README.md.jinjatemplate/_typos.tomltemplate/pnpm-workspace.yamltemplate/pylintrc.tomltemplate/pyrefly.mutmut.tomltemplate/pyrefly.tomltemplate/pytest.initemplate/ruff-non-src.tomltemplate/ruff.tomltemplate/scripts/delete_false_positive_rej.pytemplate/sh.battemplate/ty.tomltests/copier_data/data1.yamltests/copier_data/data2.yamltests/unit/copier_tasks/__init__.pytests/unit/copier_tasks/helpers.pytests/unit/copier_tasks/test_copier_provenance.pytests/unit/copier_tasks/test_ensure_pnpm_minimum_release_age_exclude.pytests/unit/copier_tasks/test_remove_precommit_hooks.pyty.toml
Adds a second provenance task invocation that runs with src=dst=template/, so template source files like template/backend/src/__init__.py get the managed-file header and appear in the nuxt template's own manifest entry.
The symlink template/.copier-managed-files.json → ../.copier-managed-files.json caused copier to inject the nuxt repo's own manifest (listing internal paths) into every downstream repo, producing a corrupt manifest. The provenance task creates the file fresh in the destination, so no pre-seeding is needed.
The task runs in all destination repos (downstream + the nuxt repo itself). Downstream repos have no ./template/ dir, so the script crashed with FileNotFoundError. Skip the task when ./template/ is absent.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
copier_template_resources/python_asyncio/asyncio_fixtures.py (2)
22-23: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winDrop this one-line docstring or expand it into a real multi-line docstring.
The function name already explains the behavior, so the current one-line docstring just violates the repo docstring rule without adding useful detail. As per coding guidelines, “Never write a one-line docstring — either the name is sufficient or the behavior warrants a full explanation.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@copier_template_resources/python_asyncio/asyncio_fixtures.py` around lines 22 - 23, The one-line docstring for fail_on_background_task_errors should be removed or expanded into a proper multi-line docstring: either delete the triple-quoted line so the function name stands alone, or replace it with a multi-line docstring that describes what the fixture does, when it is applied, what exceptions it watches for, expected behavior (how tests fail), and any side-effects or usage notes (e.g., scope or return value). Locate the fail_on_background_task_errors definition and implement one of these two options to comply with the repo docstring rule.Source: Coding guidelines
28-36:⚠️ Potential issue | 🟠 MajorFix asyncio teardown: wait tasks on their originating event loop + remove one-line docstring
fail_on_background_task_errors()teardown (lines 28-36) waits forasyncio.Taskobjects frombackground_tasks_setusingasyncio.run(...)orloop.run_until_complete(...). Both are incompatible with task/loop ownership (new-loop waiting fromasyncio.run, orrun_until_completeon an already-running loop), so the fixture can error instead of reliably surfacing background task failures. Make the teardown an async fixture andawait _wait_for_tasks(...)on the originating loop.- Remove/expand the one-line docstring on
fail_on_background_task_errors()(line 23).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@copier_template_resources/python_asyncio/asyncio_fixtures.py` around lines 28 - 36, Convert the fail_on_background_task_errors fixture teardown to be async so it awaits _wait_for_tasks on the originating event loop rather than calling asyncio.run or loop.run_until_complete; specifically, change the fixture (fail_on_background_task_errors) to async def and in the teardown await _wait_for_tasks(list(background_tasks_set)) so tasks are awaited on their proper loop/ownership, and remove the one-line docstring on fail_on_background_task_errors (replace with a short multi-line docstring if needed) to satisfy the review comment.copier_template_resources/python_asyncio/background_tasks.py (1)
15-18:⚠️ Potential issue | 🟠 MajorKeep strong references to registered background tasks.
background_tasks_setis aWeakSet[asyncio.Task[None]](Lines 15-18); if the caller doesn’t keep another strong reference, the task can be garbage-collected before_task_done_callback()runs, breaking “fire-and-forget” reliability and exception tracking. Replace it withset[asyncio.Task[None]]and keep the existingdiscard()cleanup in_task_done_callback()(Lines 51-52).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@copier_template_resources/python_asyncio/background_tasks.py` around lines 15 - 18, Replace the WeakSet with a strong reference set so background tasks aren't GC'd: change the declaration of background_tasks_set from WeakSet[asyncio.Task[None]] to set[asyncio.Task[None]] (preserve the name background_tasks_set and the existing background_task_exceptions deque), and retain the existing cleanup call to background_tasks_set.discard(...) inside _task_done_callback() so tasks are removed when done.src/copier_tasks/copier_provenance.py (1)
137-148:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAdd explicit UTF-8 encoding and keyword-only parameter marker.
Two issues:
- Line 138 opens the file without specifying encoding, which can cause locale-dependent corruption for non-ASCII content (as noted in previous review).
- Per coding guidelines, this function should use keyword-only parameters (has three parameters).
🛡️ Proposed fix
-def _write_file_marker(file: Path, comment_format: CommentFormat, specific_header: str) -> None: - with Path.open(file, "r+") as f: +def _write_file_marker(*, file: Path, comment_format: CommentFormat, specific_header: str) -> None: + with Path.open(file, "r+", encoding="utf-8") as f: content = f.read() content = _strip_existing_header(content, comment_format)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/copier_tasks/copier_provenance.py` around lines 137 - 148, Change _write_file_marker to require keyword-only parameters and open files with explicit UTF-8 encoding: update the signature from def _write_file_marker(file: Path, comment_format: CommentFormat, specific_header: str) -> None: to def _write_file_marker(file: Path, *, comment_format: CommentFormat, specific_header: str) -> None: and add encoding="utf-8" to the file open call (currently Path.open(file, "r+")) so the with statement becomes an open that specifies encoding="utf-8" (preserving mode "r+"); keep the existing logic in _write_file_marker and _strip_existing_header unchanged.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/copier_tasks/copier_provenance.py`:
- Around line 95-110: Several helper functions accept multiple positional
parameters and must enforce keyword-only arguments per project style; update the
function definitions for _build_specific_header, _strip_existing_header,
_resolve_file_src, and _get_comment_format_for_file to include a keyword-only
marker (*) so subsequent parameters must be passed by name. Locate each function
(e.g., def _build_specific_header(comment_type: CommentType, template_src: str =
"") -> str | None:) and change the signature to put a lone * before the second+
parameters (for example def _build_specific_header(comment_type: CommentType, *,
template_src: str = "") -> str | None:), doing the analogous change for
_strip_existing_header, _resolve_file_src, and _get_comment_format_for_file so
all non-first parameters become keyword-only while preserving types, defaults,
and return annotations.
---
Outside diff comments:
In `@copier_template_resources/python_asyncio/asyncio_fixtures.py`:
- Around line 22-23: The one-line docstring for fail_on_background_task_errors
should be removed or expanded into a proper multi-line docstring: either delete
the triple-quoted line so the function name stands alone, or replace it with a
multi-line docstring that describes what the fixture does, when it is applied,
what exceptions it watches for, expected behavior (how tests fail), and any
side-effects or usage notes (e.g., scope or return value). Locate the
fail_on_background_task_errors definition and implement one of these two options
to comply with the repo docstring rule.
- Around line 28-36: Convert the fail_on_background_task_errors fixture teardown
to be async so it awaits _wait_for_tasks on the originating event loop rather
than calling asyncio.run or loop.run_until_complete; specifically, change the
fixture (fail_on_background_task_errors) to async def and in the teardown await
_wait_for_tasks(list(background_tasks_set)) so tasks are awaited on their proper
loop/ownership, and remove the one-line docstring on
fail_on_background_task_errors (replace with a short multi-line docstring if
needed) to satisfy the review comment.
In `@copier_template_resources/python_asyncio/background_tasks.py`:
- Around line 15-18: Replace the WeakSet with a strong reference set so
background tasks aren't GC'd: change the declaration of background_tasks_set
from WeakSet[asyncio.Task[None]] to set[asyncio.Task[None]] (preserve the name
background_tasks_set and the existing background_task_exceptions deque), and
retain the existing cleanup call to background_tasks_set.discard(...) inside
_task_done_callback() so tasks are removed when done.
In `@src/copier_tasks/copier_provenance.py`:
- Around line 137-148: Change _write_file_marker to require keyword-only
parameters and open files with explicit UTF-8 encoding: update the signature
from def _write_file_marker(file: Path, comment_format: CommentFormat,
specific_header: str) -> None: to def _write_file_marker(file: Path, *,
comment_format: CommentFormat, specific_header: str) -> None: and add
encoding="utf-8" to the file open call (currently Path.open(file, "r+")) so the
with statement becomes an open that specifies encoding="utf-8" (preserving mode
"r+"); keep the existing logic in _write_file_marker and _strip_existing_header
unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 7be30e7a-fb93-4b3b-9620-6754c25f6f8e
📒 Files selected for processing (97)
.coderabbit.yaml.copier-answers.yml.copier-managed-files.json.coveragerc.devcontainer/Dockerfile.devcontainer/create-aws-profile.sh.devcontainer/devcontainer.json.devcontainer/docker-compose.yml.devcontainer/initialize-command.sh.devcontainer/install-ci-tooling.py.devcontainer/manual-setup-deps.py.devcontainer/on-create-command-boilerplate.sh.devcontainer/on-create-command.sh.devcontainer/post-start-command.sh.devcontainer/windows-host-helper.sh.github/actions/check-skip-duplicates/action.yml.github/actions/install_deps/action.yml.github/actions/update-devcontainer-hash/action.yml.github/dependabot.yml.github/pull_request_template.md.github/reusable_workflows/build-docker-image.yaml.github/workflows/ci.yaml.github/workflows/confirm-on-tagged-copier-template.yaml.github/workflows/get-values.yaml.github/workflows/hash_git_files.py.github/workflows/pre-commit.yaml.github/workflows/replace_private_package_registries.py.github/workflows/tag-on-merge.yaml.github/zizmor.yml.gitignore.pre-commit-config.yamlAGENTS.mdCHANGELOG.mdCLAUDE.mdCODE_OF_CONDUCT.mdCONTRIBUTING.mdLICENSEREADME.md_typos.tomlcopier.ymlcopier_template_resources/eslint.config.mjscopier_template_resources/python_asyncio/asyncio_fixtures.pycopier_template_resources/python_asyncio/background_tasks.pycopier_template_resources/vcrpy_fixtures.pyextensions/context.pypylintrc.tomlpyproject.tomlpyrefly.tomlpytest.iniruff-non-src.tomlruff.tomlscripts/delete_false_positive_rej.pysh.batsrc/copier_tasks/__init__.pysrc/copier_tasks/copier_provenance.pysrc/copier_tasks/ensure_pnpm_minimum_release_age_exclude.pysrc/copier_tasks/remove_precommit_hooks.pytemplate/.coderabbit.yamltemplate/.coveragerctemplate/.devcontainer/Dockerfiletemplate/.devcontainer/initialize-command.shtemplate/.devcontainer/manual-setup-deps.pytemplate/.devcontainer/on-create-command-boilerplate.shtemplate/.devcontainer/windows-host-helper.shtemplate/.github/pull_request_template.mdtemplate/.github/workflows/confirm-on-tagged-copier-template.yamltemplate/.github/workflows/extract_project_version.pytemplate/.github/workflows/get-values.yamltemplate/.github/workflows/git_tag.pytemplate/.github/workflows/hash_git_files.pytemplate/.github/workflows/pre-commit.yamltemplate/.gitignoretemplate/.python-version.jinjatemplate/AGENTS.mdtemplate/CHANGELOG.mdtemplate/CLAUDE.mdtemplate/CONTRIBUTING.mdtemplate/README.md.jinjatemplate/_typos.tomltemplate/pnpm-workspace.yamltemplate/pylintrc.tomltemplate/pyrefly.mutmut.tomltemplate/pyrefly.tomltemplate/pytest.initemplate/ruff-non-src.tomltemplate/ruff.tomltemplate/scripts/delete_false_positive_rej.pytemplate/sh.battemplate/ty.tomltests/copier_data/data1.yamltests/copier_data/data2.yamltests/unit/copier_tasks/__init__.pytests/unit/copier_tasks/helpers.pytests/unit/copier_tasks/test_copier_provenance.pytests/unit/copier_tasks/test_ensure_pnpm_minimum_release_age_exclude.pytests/unit/copier_tasks/test_remove_precommit_hooks.pyty.toml
090f274 to
b9394ce
Compare
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
copier.yml (1)
389-411: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winMoving
.coveragercbefore provenance drops it from the managed-files contract.
copier_provenance.pyonly stamps files whose destination-relative path matches a template-relative path. The template still contributes.coveragerc, but this task renames it tobackend/.coveragercbefore the provenance pass runs, so that file will no longer get a header or appear in.copier-managed-files.jsonfor backend repos.Please either keep the move after the provenance task or teach the provenance matcher about this relocation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@copier.yml` around lines 389 - 411, The `.coveragerc` relocation in the copier tasks is happening before provenance is generated, so `copier_provenance.py` no longer sees the file under its template-relative path. Fix the task order in `copier.yml` so the provenance step runs before moving `.coveragerc`, or update `copier_provenance.py` to recognize the `backend/.coveragerc` destination when stamping managed files. Use the existing `copier_provenance.py` calls and the `.coveragerc` move block as the place to make the change.template/.claude/skills/fix-mutants/utils.py (1)
209-228: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winExpand or remove the one-line docstring.
The coding guidelines prohibit one-line docstrings. Either the function name
run_mutmutis sufficient (in which case remove the docstring) or the behavior warrants a fuller explanation (e.g., describing how the returnedCompletedProcessshould be interpreted, timeout behavior, and exit conditions).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@template/.claude/skills/fix-mutants/utils.py` around lines 209 - 228, The `run_mutmut` helper currently has a prohibited one-line docstring, so either remove it entirely if the function name is self-explanatory or expand it into a proper multi-line docstring. If you keep documentation, update `run_mutmut` to describe the `CompletedProcess` return value, the `uv run mutmut` invocation context, and the `FileNotFoundError`/`TimeoutExpired` exit behavior so the comment matches the function’s actual behavior.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/copier_tasks/copier_provenance.py`:
- Around line 177-185: The symlink-following walk in
_collect_template_base_paths (and the matching destination traversal) needs
cycle and escape protection: os.walk(..., followlinks=True) can loop forever on
directory symlink cycles and can leave the intended root. Update the traversal
to track visited real paths for each directory before descending, and reject or
skip symlink targets whose resolved path is outside src_template_directory or
dst_directory. Keep the existing symlink support, but make the walk in
_collect_template_base_paths and the destination-marking logic stop on
already-seen real directories and anything that escapes the repo root.
In `@template/.claude/skills/fix-mutants/group-by-line.py`:
- Around line 181-185: The tests-for-mutant call in group_by_line.py is not
checking for command failure, so a nonzero result can be misread as test names.
Update the logic around run_mutmut(["tests-for-mutant", key], ...) to validate
the returncode the same way the earlier mutmut show handling does, and only
parse stdout into tests after a successful run; on failure, surface the
stderr/exit status instead of silently continuing. Use the existing run_mutmut
and tests_result handling in the mutant grouping loop as the fix point.
In `@template/.claude/skills/fix-mutants/list-survived.py`:
- Around line 74-80: The copier warning block in list_survived.py is placed as a
footer instead of a header, which is inconsistent with the rest of the codebase.
Move the managed-by-copier warning comment to the top of the file so it matches
the other Python files, keeping the same warning text and ensuring the file
still remains a valid copier-managed template artifact.
- Around line 37-43: Update parse_status_filter so its optional flag handling is
expressed with keyword-only parameters by adding a * in the signature, and
adjust the main() call site to pass sys.argv[1:] using the new explicit argument
style. Keep the behavior for "--all", "--status", and the ACTIONABLE_STATUSES
fallback unchanged while updating the unique symbols parse_status_filter and
main accordingly.
- Around line 62-68: The call to emit in list_survived.py is discarding a likely
non-void return value, which violates reportUnusedCallResult. Update the code at
the emit call site to explicitly capture the return value in _ if emit returns
something, and keep the surrounding logic unchanged; use the emit helper
invocation and the by_file/total_actionable payload as the anchor for the fix.
In `@template/.claude/skills/fix-mutants/utils.py`:
- Around line 56-58: The `emit` helper currently uses a prohibited one-line
docstring, so either remove the docstring entirely if the function name is
sufficient or expand it into a multi-line description of what `obj` represents
and why output is written to stdout. Update the `emit` function in `utils.py`
accordingly while keeping its JSON serialization behavior unchanged.
---
Outside diff comments:
In `@copier.yml`:
- Around line 389-411: The `.coveragerc` relocation in the copier tasks is
happening before provenance is generated, so `copier_provenance.py` no longer
sees the file under its template-relative path. Fix the task order in
`copier.yml` so the provenance step runs before moving `.coveragerc`, or update
`copier_provenance.py` to recognize the `backend/.coveragerc` destination when
stamping managed files. Use the existing `copier_provenance.py` calls and the
`.coveragerc` move block as the place to make the change.
In `@template/.claude/skills/fix-mutants/utils.py`:
- Around line 209-228: The `run_mutmut` helper currently has a prohibited
one-line docstring, so either remove it entirely if the function name is
self-explanatory or expand it into a proper multi-line docstring. If you keep
documentation, update `run_mutmut` to describe the `CompletedProcess` return
value, the `uv run mutmut` invocation context, and the
`FileNotFoundError`/`TimeoutExpired` exit behavior so the comment matches the
function’s actual behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: b94ce3fb-61b6-4c0a-ae8e-750ccf17212b
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (103)
.claude/.beads/.gitignore.claude/.beads/config.yaml.claude/commands/add-command.md.claude/commands/commit.md.claude/commands/create-adr.md.claude/commands/create-issues.md.claude/commands/gap.md.claude/commands/green.md.claude/commands/issue.md.claude/commands/polish.md.claude/commands/red.md.claude/commands/refactor.md.claude/commands/research.md.claude/commands/simplify.md.claude/commands/spike.md.claude/commands/summarize.md.claude/commands/tdd-review.md.claude/commands/tdd.md.claude/helpers/merge-claude-settings.sh.claude/hooks/bash-chain-guard.js.claude/hooks/caveman-activate.js.claude/hooks/caveman-config.js.claude/hooks/caveman-mode-tracker.js.claude/settings/basics.jsonc.claude/settings/hooks.jsonc.claude/settings/permissions/additional-dirs.jsonc.claude/settings/permissions/bash.jsonc.claude/settings/permissions/read.jsonc.claude/settings/permissions/write.jsonc.claude/skills/address-pr-comments/SKILL.md.claude/skills/address-pr-comments/check-footer.py.claude/skills/address-pr-comments/fetch-pr-comments.py.claude/skills/address-pr-comments/post-reply.py.claude/skills/address-pr-comments/utils.py.claude/skills/caveman/SKILL.md.claudeignore.copier-answers.yml.copier-managed-files.json.devcontainer/devcontainer.json.github/ISSUE_TEMPLATE/bug-report.yml.github/ISSUE_TEMPLATE/config.yml.github/ISSUE_TEMPLATE/feature-request.yml.github/ISSUE_TEMPLATE/tech-debt.ymlbiome.jsonccopier.ymlextensions/context.pypyproject.tomlpyrefly.tomlsrc/copier_tasks/copier_provenance.pytemplate/.claude/.beads/.gitignoretemplate/.claude/.beads/config.yamltemplate/.claude/commands/add-command.mdtemplate/.claude/commands/commit.mdtemplate/.claude/commands/create-adr.mdtemplate/.claude/commands/create-issues.mdtemplate/.claude/commands/gap.mdtemplate/.claude/commands/green.mdtemplate/.claude/commands/issue.mdtemplate/.claude/commands/polish.mdtemplate/.claude/commands/red.mdtemplate/.claude/commands/refactor.mdtemplate/.claude/commands/research.mdtemplate/.claude/commands/simplify.mdtemplate/.claude/commands/spike.mdtemplate/.claude/commands/summarize.mdtemplate/.claude/commands/tdd-review.mdtemplate/.claude/commands/tdd.mdtemplate/.claude/helpers/merge-claude-settings.shtemplate/.claude/hooks/bash-chain-guard.jstemplate/.claude/hooks/caveman-activate.jstemplate/.claude/hooks/caveman-config.jstemplate/.claude/hooks/caveman-mode-tracker.jstemplate/.claude/settings/basics.jsonctemplate/.claude/settings/hooks.jsonctemplate/.claude/settings/permissions/additional-dirs.jsonctemplate/.claude/settings/permissions/bash.jsonctemplate/.claude/settings/permissions/read.jsonctemplate/.claude/settings/permissions/write.jsonctemplate/.claude/skills/address-pr-comments/SKILL.mdtemplate/.claude/skills/address-pr-comments/check-footer.pytemplate/.claude/skills/address-pr-comments/fetch-pr-comments.pytemplate/.claude/skills/address-pr-comments/post-reply.pytemplate/.claude/skills/address-pr-comments/utils.pytemplate/.claude/skills/caveman/SKILL.mdtemplate/.claude/skills/fix-mutants/SKILL.mdtemplate/.claude/skills/fix-mutants/check-results.pytemplate/.claude/skills/fix-mutants/group-by-line.pytemplate/.claude/skills/fix-mutants/list-survived.pytemplate/.claude/skills/fix-mutants/run-mutmut.pytemplate/.claude/skills/fix-mutants/show-mutant.pytemplate/.claude/skills/fix-mutants/utils.pytemplate/.claude/skills/fix-mutants/verify-mutant.pytemplate/.github/ISSUE_TEMPLATE/bug-report.ymltemplate/.github/ISSUE_TEMPLATE/config.ymltemplate/.github/ISSUE_TEMPLATE/feature-request.ymltemplate/.github/ISSUE_TEMPLATE/tech-debt.ymltemplate/.github/actions/check-skip-duplicates/action.ymltemplate/.github/actions/install_deps/action.ymltemplate/.github/actions/update-devcontainer-hash/action.ymltemplate/biome.jsonctemplate/pyrefly.mutmut.tomltemplate/pyrefly.tomltests/unit/copier_tasks/test_copier_provenance.py
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
copier.yml (1)
389-411: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winMoving
.coveragercbefore provenance drops it from the managed-files contract.
copier_provenance.pyonly stamps files whose destination-relative path matches a template-relative path. The template still contributes.coveragerc, but this task renames it tobackend/.coveragercbefore the provenance pass runs, so that file will no longer get a header or appear in.copier-managed-files.jsonfor backend repos.Please either keep the move after the provenance task or teach the provenance matcher about this relocation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@copier.yml` around lines 389 - 411, The `.coveragerc` relocation in the copier tasks is happening before provenance is generated, so `copier_provenance.py` no longer sees the file under its template-relative path. Fix the task order in `copier.yml` so the provenance step runs before moving `.coveragerc`, or update `copier_provenance.py` to recognize the `backend/.coveragerc` destination when stamping managed files. Use the existing `copier_provenance.py` calls and the `.coveragerc` move block as the place to make the change.template/.claude/skills/fix-mutants/utils.py (1)
209-228: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winExpand or remove the one-line docstring.
The coding guidelines prohibit one-line docstrings. Either the function name
run_mutmutis sufficient (in which case remove the docstring) or the behavior warrants a fuller explanation (e.g., describing how the returnedCompletedProcessshould be interpreted, timeout behavior, and exit conditions).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@template/.claude/skills/fix-mutants/utils.py` around lines 209 - 228, The `run_mutmut` helper currently has a prohibited one-line docstring, so either remove it entirely if the function name is self-explanatory or expand it into a proper multi-line docstring. If you keep documentation, update `run_mutmut` to describe the `CompletedProcess` return value, the `uv run mutmut` invocation context, and the `FileNotFoundError`/`TimeoutExpired` exit behavior so the comment matches the function’s actual behavior.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/copier_tasks/copier_provenance.py`:
- Around line 177-185: The symlink-following walk in
_collect_template_base_paths (and the matching destination traversal) needs
cycle and escape protection: os.walk(..., followlinks=True) can loop forever on
directory symlink cycles and can leave the intended root. Update the traversal
to track visited real paths for each directory before descending, and reject or
skip symlink targets whose resolved path is outside src_template_directory or
dst_directory. Keep the existing symlink support, but make the walk in
_collect_template_base_paths and the destination-marking logic stop on
already-seen real directories and anything that escapes the repo root.
In `@template/.claude/skills/fix-mutants/group-by-line.py`:
- Around line 181-185: The tests-for-mutant call in group_by_line.py is not
checking for command failure, so a nonzero result can be misread as test names.
Update the logic around run_mutmut(["tests-for-mutant", key], ...) to validate
the returncode the same way the earlier mutmut show handling does, and only
parse stdout into tests after a successful run; on failure, surface the
stderr/exit status instead of silently continuing. Use the existing run_mutmut
and tests_result handling in the mutant grouping loop as the fix point.
In `@template/.claude/skills/fix-mutants/list-survived.py`:
- Around line 74-80: The copier warning block in list_survived.py is placed as a
footer instead of a header, which is inconsistent with the rest of the codebase.
Move the managed-by-copier warning comment to the top of the file so it matches
the other Python files, keeping the same warning text and ensuring the file
still remains a valid copier-managed template artifact.
- Around line 37-43: Update parse_status_filter so its optional flag handling is
expressed with keyword-only parameters by adding a * in the signature, and
adjust the main() call site to pass sys.argv[1:] using the new explicit argument
style. Keep the behavior for "--all", "--status", and the ACTIONABLE_STATUSES
fallback unchanged while updating the unique symbols parse_status_filter and
main accordingly.
- Around line 62-68: The call to emit in list_survived.py is discarding a likely
non-void return value, which violates reportUnusedCallResult. Update the code at
the emit call site to explicitly capture the return value in _ if emit returns
something, and keep the surrounding logic unchanged; use the emit helper
invocation and the by_file/total_actionable payload as the anchor for the fix.
In `@template/.claude/skills/fix-mutants/utils.py`:
- Around line 56-58: The `emit` helper currently uses a prohibited one-line
docstring, so either remove the docstring entirely if the function name is
sufficient or expand it into a multi-line description of what `obj` represents
and why output is written to stdout. Update the `emit` function in `utils.py`
accordingly while keeping its JSON serialization behavior unchanged.
---
Outside diff comments:
In `@copier.yml`:
- Around line 389-411: The `.coveragerc` relocation in the copier tasks is
happening before provenance is generated, so `copier_provenance.py` no longer
sees the file under its template-relative path. Fix the task order in
`copier.yml` so the provenance step runs before moving `.coveragerc`, or update
`copier_provenance.py` to recognize the `backend/.coveragerc` destination when
stamping managed files. Use the existing `copier_provenance.py` calls and the
`.coveragerc` move block as the place to make the change.
In `@template/.claude/skills/fix-mutants/utils.py`:
- Around line 209-228: The `run_mutmut` helper currently has a prohibited
one-line docstring, so either remove it entirely if the function name is
self-explanatory or expand it into a proper multi-line docstring. If you keep
documentation, update `run_mutmut` to describe the `CompletedProcess` return
value, the `uv run mutmut` invocation context, and the
`FileNotFoundError`/`TimeoutExpired` exit behavior so the comment matches the
function’s actual behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: b94ce3fb-61b6-4c0a-ae8e-750ccf17212b
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (103)
.claude/.beads/.gitignore.claude/.beads/config.yaml.claude/commands/add-command.md.claude/commands/commit.md.claude/commands/create-adr.md.claude/commands/create-issues.md.claude/commands/gap.md.claude/commands/green.md.claude/commands/issue.md.claude/commands/polish.md.claude/commands/red.md.claude/commands/refactor.md.claude/commands/research.md.claude/commands/simplify.md.claude/commands/spike.md.claude/commands/summarize.md.claude/commands/tdd-review.md.claude/commands/tdd.md.claude/helpers/merge-claude-settings.sh.claude/hooks/bash-chain-guard.js.claude/hooks/caveman-activate.js.claude/hooks/caveman-config.js.claude/hooks/caveman-mode-tracker.js.claude/settings/basics.jsonc.claude/settings/hooks.jsonc.claude/settings/permissions/additional-dirs.jsonc.claude/settings/permissions/bash.jsonc.claude/settings/permissions/read.jsonc.claude/settings/permissions/write.jsonc.claude/skills/address-pr-comments/SKILL.md.claude/skills/address-pr-comments/check-footer.py.claude/skills/address-pr-comments/fetch-pr-comments.py.claude/skills/address-pr-comments/post-reply.py.claude/skills/address-pr-comments/utils.py.claude/skills/caveman/SKILL.md.claudeignore.copier-answers.yml.copier-managed-files.json.devcontainer/devcontainer.json.github/ISSUE_TEMPLATE/bug-report.yml.github/ISSUE_TEMPLATE/config.yml.github/ISSUE_TEMPLATE/feature-request.yml.github/ISSUE_TEMPLATE/tech-debt.ymlbiome.jsonccopier.ymlextensions/context.pypyproject.tomlpyrefly.tomlsrc/copier_tasks/copier_provenance.pytemplate/.claude/.beads/.gitignoretemplate/.claude/.beads/config.yamltemplate/.claude/commands/add-command.mdtemplate/.claude/commands/commit.mdtemplate/.claude/commands/create-adr.mdtemplate/.claude/commands/create-issues.mdtemplate/.claude/commands/gap.mdtemplate/.claude/commands/green.mdtemplate/.claude/commands/issue.mdtemplate/.claude/commands/polish.mdtemplate/.claude/commands/red.mdtemplate/.claude/commands/refactor.mdtemplate/.claude/commands/research.mdtemplate/.claude/commands/simplify.mdtemplate/.claude/commands/spike.mdtemplate/.claude/commands/summarize.mdtemplate/.claude/commands/tdd-review.mdtemplate/.claude/commands/tdd.mdtemplate/.claude/helpers/merge-claude-settings.shtemplate/.claude/hooks/bash-chain-guard.jstemplate/.claude/hooks/caveman-activate.jstemplate/.claude/hooks/caveman-config.jstemplate/.claude/hooks/caveman-mode-tracker.jstemplate/.claude/settings/basics.jsonctemplate/.claude/settings/hooks.jsonctemplate/.claude/settings/permissions/additional-dirs.jsonctemplate/.claude/settings/permissions/bash.jsonctemplate/.claude/settings/permissions/read.jsonctemplate/.claude/settings/permissions/write.jsonctemplate/.claude/skills/address-pr-comments/SKILL.mdtemplate/.claude/skills/address-pr-comments/check-footer.pytemplate/.claude/skills/address-pr-comments/fetch-pr-comments.pytemplate/.claude/skills/address-pr-comments/post-reply.pytemplate/.claude/skills/address-pr-comments/utils.pytemplate/.claude/skills/caveman/SKILL.mdtemplate/.claude/skills/fix-mutants/SKILL.mdtemplate/.claude/skills/fix-mutants/check-results.pytemplate/.claude/skills/fix-mutants/group-by-line.pytemplate/.claude/skills/fix-mutants/list-survived.pytemplate/.claude/skills/fix-mutants/run-mutmut.pytemplate/.claude/skills/fix-mutants/show-mutant.pytemplate/.claude/skills/fix-mutants/utils.pytemplate/.claude/skills/fix-mutants/verify-mutant.pytemplate/.github/ISSUE_TEMPLATE/bug-report.ymltemplate/.github/ISSUE_TEMPLATE/config.ymltemplate/.github/ISSUE_TEMPLATE/feature-request.ymltemplate/.github/ISSUE_TEMPLATE/tech-debt.ymltemplate/.github/actions/check-skip-duplicates/action.ymltemplate/.github/actions/install_deps/action.ymltemplate/.github/actions/update-devcontainer-hash/action.ymltemplate/biome.jsonctemplate/pyrefly.mutmut.tomltemplate/pyrefly.tomltests/unit/copier_tasks/test_copier_provenance.py
🛑 Comments failed to post (6)
src/copier_tasks/copier_provenance.py (1)
177-185: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Guard the symlink-following walks before this can hang or escape the repo root.
Both new
os.walk(..., followlinks=True)traversals descend through directory symlinks without tracking visited real paths. A cycle likea -> ..will recurse forever, and the destination walk can also follow a symlink out ofdst_directory, letting the marker pass rewrite files outside the project tree.Please keep the symlink support, but stop descending into already-seen real directories and reject symlink targets outside the traversal root.
Also applies to: 205-207
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/copier_tasks/copier_provenance.py` around lines 177 - 185, The symlink-following walk in _collect_template_base_paths (and the matching destination traversal) needs cycle and escape protection: os.walk(..., followlinks=True) can loop forever on directory symlink cycles and can leave the intended root. Update the traversal to track visited real paths for each directory before descending, and reject or skip symlink targets whose resolved path is outside src_template_directory or dst_directory. Keep the existing symlink support, but make the walk in _collect_template_base_paths and the destination-marking logic stop on already-seen real directories and anything that escapes the repo root.template/.claude/skills/fix-mutants/group-by-line.py (1)
181-185: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Add error handling for
mutmut tests-for-mutantfailure.The returncode of
run_mutmut(["tests-for-mutant", key], ...)is not checked, unlike themutmut showcall above. If this command fails, the error output is silently parsed as test names, producing confusing results. Add a returncode check consistent with line 157.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@template/.claude/skills/fix-mutants/group-by-line.py` around lines 181 - 185, The tests-for-mutant call in group_by_line.py is not checking for command failure, so a nonzero result can be misread as test names. Update the logic around run_mutmut(["tests-for-mutant", key], ...) to validate the returncode the same way the earlier mutmut show handling does, and only parse stdout into tests after a successful run; on failure, surface the stderr/exit status instead of silently continuing. Use the existing run_mutmut and tests_result handling in the mutant grouping loop as the fix point.template/.claude/skills/fix-mutants/list-survived.py (3)
37-43: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
Use keyword-only parameters for optional flags.
The
parse_status_filterfunction accepts a positionalargvlist but is only called withsys.argv[1:]inmain. Since this is a script entry-point helper that shouldn't be called with keyword arguments, but per project guidelines prefer*in Python signatures to enforce clarity:-def parse_status_filter(argv: list[str]) -> set[str] | None: +def parse_status_filter(*, argv: list[str]) -> set[str] | None:This would require updating the call site in
main()accordingly.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@template/.claude/skills/fix-mutants/list-survived.py` around lines 37 - 43, Update parse_status_filter so its optional flag handling is expressed with keyword-only parameters by adding a * in the signature, and adjust the main() call site to pass sys.argv[1:] using the new explicit argument style. Keep the behavior for "--all", "--status", and the ACTIONABLE_STATUSES fallback unchanged while updating the unique symbols parse_status_filter and main accordingly.Source: Coding guidelines
62-68: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
Assign unused
emitreturn value to_if it returns a value.The
emithelper likely returns a value (e.g., the JSON string or bytes), but the result is discarded here. Per project guidelines, respectreportUnusedCallResultby assigning to_:- emit( + _ = emit( { "backend_root": str(backend_root), "total_actionable": total, "by_file": dict(sorted(by_file.items())), } )📝 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._ = emit( { "backend_root": str(backend_root), "total_actionable": total, "by_file": dict(sorted(by_file.items())), } )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@template/.claude/skills/fix-mutants/list-survived.py` around lines 62 - 68, The call to emit in list_survived.py is discarding a likely non-void return value, which violates reportUnusedCallResult. Update the code at the emit call site to explicitly capture the return value in _ if emit returns something, and keep the surrounding logic unchanged; use the emit helper invocation and the by_file/total_actionable payload as the anchor for the fix.Source: Coding guidelines
74-80: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
Consider moving the copier warning header to the top of the file for consistency.
Other files in this PR place the warning comment block at the top (header), but this file places it at the bottom (footer). If the tooling supports headers in Python files, consider moving it to the top for consistency with the rest of the codebase.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@template/.claude/skills/fix-mutants/list-survived.py` around lines 74 - 80, The copier warning block in list_survived.py is placed as a footer instead of a header, which is inconsistent with the rest of the codebase. Move the managed-by-copier warning comment to the top of the file so it matches the other Python files, keeping the same warning text and ensuring the file still remains a valid copier-managed template artifact.template/.claude/skills/fix-mutants/utils.py (1)
56-58: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Expand or remove the one-line docstring.
The coding guidelines prohibit one-line docstrings. Either the function name
emitis self-explanatory (in which case remove the docstring) or the behavior warrants a fuller explanation (e.g., describing the expected shape ofobjand why stdout is used).🧰 Tools
🪛 ast-grep (0.44.0)
[info] 57-57: use jsonify instead of json.dumps for JSON output
Context: json.dumps(obj, indent=2)
Note: [CWE-116] Improper Encoding or Escaping of Output.(use-jsonify)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@template/.claude/skills/fix-mutants/utils.py` around lines 56 - 58, The `emit` helper currently uses a prohibited one-line docstring, so either remove the docstring entirely if the function name is sufficient or expand it into a multi-line description of what `obj` represents and why output is written to stdout. Update the `emit` function in `utils.py` accordingly while keeping its JSON serialization behavior unchanged.Source: Coding guidelines
Link to Issue or Message thread
Downstream repo PR conversation
Why is this change necessary?
Knowing where files come from as far as copier templates go is a pain unless you are Eli
How does this change address the issue?
Adds header/footer to files that support it, creates a json file that contains which template owns which file and AI guidance to add a comment/summary about which files touched copier related files.
What side effects does this change have?
Tons of files touched
How is this change tested?
Unit tests and downstream
Summary by CodeRabbit
Release Notes
New Features
Chores
Tests