Add keyword filtering to agentseek create --list-templates - #173
Conversation
webup
left a comment
There was a problem hiding this comment.
Thanks for the contribution. I’m requesting changes at exact head 55fbefc09431063ad74f5e67443f451242e1085d for two merge blockers:
- This branch is based on
d181808d, the commit immediately before PR #111. The requested filter feature, documentation, and focused tests were already merged by #111 (c074ad63) and remain on currentmain. This head is 36 commits behind and conflicts in all six touched files; resolving against currentmainleaves no substantive feature delta. Please rebase and remove the duplicate work; closing this PR as a duplicate is appropriate unless you keep only the narrow safety correction below. --filteris accepted outside listing mode and then silently ignored, so a missing--list-templatescan generate a project instead of failing. The inline comment includes the exact reproduction and required regression.
Verification on this head: the 32 focused create tests, 98-test full suite, Ruff, ty, strict MkDocs build, and git diff --check pass. Current main’s five filter tests also pass, confirming the feature is already present. GitHub reports this PR as CONFLICTING / DIRTY with no hosted checks.
| action="store_true", | ||
| help="List templates available for the chosen type and exit.", | ||
| ) | ||
| parser.add_argument( |
There was a problem hiding this comment.
--filter is registered for every create path, but args.filter is only consumed in the list branch. At this exact head, create bub/default --filter definitely-does-not-match --no-input exits 0 and invokes _run_cookiecutter once for bub/default in the current directory; before this commit, argparse rejects the unknown option with exit 2. Please reject --filter unless list mode is active (or deliberately make it imply listing), and add a non-list regression so omitting --list-templates cannot trigger project generation.
55fbefc to
89a40ec
Compare
|
Thanks for the review — I've reworked the PR per your feedback.
|
webup
left a comment
There was a problem hiding this comment.
Thanks for rebasing onto current main, removing the duplicate #111 implementation, and fixing the original named-template reproduction. One merge-blocking dispatch bypass remains at exact head 89a40ecc137be57d5aaa05b5bdb07acc251f4b66.
The new guard trusts the listing flags, but direct URL/absolute-path specs are dispatched to _handle_external_spec() before the actual listing branch. As a result, create https://example.com/template.git --list-templates --filter needle --no-input still exits 0 and invokes Cookiecutter once; the same occurs with an absolute path and with bare --template. This contradicts the documented contract that listing/filtering do not execute Cookiecutter hooks. Please resolve listing mode before external passthrough or reject direct sources combined with listing/filter flags, and add URL/absolute-path regressions proving Cookiecutter is never invoked.
Everything else revalidated cleanly: the PR is now one commit over main, git diff --check and uv lock --check pass, filter tests are 6/6, the complete create suite is 118 passed / 1 skipped, the full suite is 1144 passed / 1 skipped, Ruff/format/ty pass, and all hosted checks are green. GitHub reports MERGEABLE / CLEAN.
| """Scaffold a new agent project from a pre-built template.""" | ||
| args = _parse_new_args(ctx) | ||
| # --- --filter is only meaningful when listing templates --- | ||
| if args.filter is not None and not (args.list_templates or args.template == _TEMPLATE_LIST_SENTINEL): |
There was a problem hiding this comment.
This condition checks for listing flags, but not whether control flow will actually enter the listing branch. For a direct source, e.g. create https://example.com/template.git --list-templates --filter needle --no-input, the guard passes and the external-spec branch below invokes _run_cookiecutter before reaching the list branch (exit 0, one generation call in a mocked reproduction). Absolute paths and bare --template --filter behave the same way. Please reject these direct-source combinations or route listing before external passthrough, with a regression asserting exit 2 and zero Cookiecutter calls.
|
Thanks for catching the remaining dispatch bypass — fixed in The bypass: direct URL/absolute-path specs were dispatched to The fix: This also covers the no- Regressions added:
Verification on this head: create suite 115 passed / 6 skipped, full suite 1094 passed / 53 skipped, Ruff/ty/ |
|
Added two more regressions to lock the listing-mode boundary (self-review pass):
Head is now |
webup
left a comment
There was a problem hiding this comment.
Thanks for fixing the direct-source dispatch bypass and adding the focused regressions. I revalidated exact head 3dfa84e8893baca169e8315822d7297f42bb7895: the original URL, absolute-path, and bare---template cases now exit 2 without invoking Cookiecutter. Two merge blockers remain. First, the string listing sentinel now collides with a valid direct-source directory value, regressing passthrough for --template __list__. Second, the changed production file fails the repository's Ruff format gate. The inline comments include exact reproductions and requested regressions.
Everything else is clean: the complete create suite is 122 passed / 1 skipped, the full suite is 1148 passed / 1 skipped, Ruff lint, ty, lock checks, and git diff --check pass, and the worktree is clean. GitHub reports MERGEABLE / UNSTABLE; no hosted checks are reported for this head yet.
| def create(ctx: typer.Context) -> None: | ||
| """Scaffold a new agent project from a pre-built template.""" | ||
| args = _parse_new_args(ctx) | ||
| listing_mode = args.list_templates or args.template == _TEMPLATE_LIST_SENTINEL |
There was a problem hiding this comment.
[P2] Avoid colliding with a valid external directory value. _TEMPLATE_LIST_SENTINEL is the user-enterable string __list__, so this comparison cannot distinguish bare --template from --template __list__. At this head, create https://example.com/template.git --template __list__ --no-input exits 2 with zero Cookiecutter calls; at parent 89a40ecc, external dispatch ran first and forwarded directory='__list__'. This newly regresses the promised --template <value> passthrough for direct sources. Please use a non-colliding representation (or preserve option arity) and add a regression proving an explicit __list__ directory is still forwarded.
| # --- External spec (URL or absolute path) → passthrough to cookiecutter --- | ||
| if args.spec and _is_external_spec(args.spec): | ||
| if listing_mode: | ||
| typer.echo( |
There was a problem hiding this comment.
[P1] Restore the repository formatting gate. uv run --locked ruff format --check src tests contrib scripts exits 1 because Ruff joins these adjacent literals into one line. make lint runs pre-commit's ruff-format hook, so this head cannot pass that gate. Please run the formatter and push the result.
|
CI Fixed in Verified locally with the exact CI commands:
Head is now |
|
Thanks — both merge blockers are addressed. Head is now P1 (format gate) — already restored in P2 (sentinel collision) — fixed in
Regression added: Verification on this head: create suite 118 passed / 6 skipped, pre-commit all hooks pass, |
webup
left a comment
There was a problem hiding this comment.
Approved at exact head b30dc69f335a3656795d1b1bc4b5f8aa9ace7169. Both requested fixes are complete: 75230be restores the Ruff-format gate, and b30dc69 replaces the colliding string sentinel with object identity while preserving literal --template __list__ as a direct-source directory. The original URL/absolute-path listing and non-list --filter safety cases still exit 2 with zero Cookiecutter calls; ordinary and valued direct-source generation still pass through.
Fresh validation: 6 focused regressions pass; the full suite is 1149 passed / 1 skipped; Ruff format reports 96 files formatted; Ruff lint, ty, both lock checks, and git diff --check pass; the checkout is clean. No code blocker remains.
Merge gate: the exact-head Main run 31498731461 and OpenVINO run 31498731215 are both action_required with zero jobs, so they still need authorization and a green result before merge. The immediately preceding 75230be runs were green, but they are not exact-head evidence.
|
Thanks for the review and approval! Quick heads-up on the merge gate: the exact-head workflow runs are both
Could you approve these when convenient? The preceding |
|
Thanks for the contribution and for iterating quickly on the review feedback. The safety fixes and focused regression coverage landed cleanly—great work! |
Summary
Narrow safety fixes on top of current main, so listing/filtering never executes Cookiecutter:
--filteroutside listing mode is rejected —create bub/default --filter x --no-inputexits 2 instead of silently generating a project.create <url-or-absolute-path> --list-templates(with or without--filter) and the bare--templateform now exit 2 withListing templates cannot be combined with a direct template source (URL or absolute path).instead of dispatching to Cookiecutter passthrough.Background
Rebased onto current main; the filter feature itself (already merged via #111) is untouched. This PR keeps only the safety corrections requested in review.
Regressions added
test_filter_without_list_mode_is_rejected—--filterwithout listing flags: exit 2, zero Cookiecutter calls.test_list_templates_with_url_spec_rejects_without_cookiecutter— URL +--list-templates --filter: exit 2, zero Cookiecutter calls.test_list_templates_with_absolute_path_spec_rejects_without_cookiecutter— absolute path +--list-templates --filter: exit 2, zero Cookiecutter calls.test_template_flag_no_value_with_url_spec_rejects_without_cookiecutter— bare--template+ URL: exit 2, zero Cookiecutter calls.test_create_with_url_spec_and_template_value_passes_directory— URL +--template <value>still passesdirectoryto Cookiecutter (guards the sentinel-vs-value distinction).Verification
uv run python -m pytest tests/cli_commands/test_create.py— 117 passed, 6 skippeduv run ruff check/uv run ty check/uv lock --locked/git diff --check— pass