Repository navigation
[fix] - Ponytail-style tests-refactor pass over tests/ and .github/workflows - #1652
Conversation
…audit.yml with the grep instruction Both comments sent a future torch bump to devskim.yml (no torch) and copilot-setup-steps.yml (hashed lock, no literal pin) while omitting nemo-guardrails.yml. The grep they already recommend cannot drift. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0145zL6RjeL5rrT7RWULBN1g
…files Six byte-identical copies of the walker collapse into tests/import_graph.py (not test_-named, so not collected). Each guard aliases it to its old local name, so no test body or file name changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0145zL6RjeL5rrT7RWULBN1g
test_device_token_caller_with_no_browser_headers_still_works sent the same request with the same fixtures and assertions as test_device_token_works. Its rationale moves onto the surviving test as the docstring. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0145zL6RjeL5rrT7RWULBN1g
… 54% to 79% Pins the policy-derived service name and its missing-row refusal, the macOS Keychain exit codes (44 absent, other nonzero an error, one newline stripped), Linux's no-keystore None, the usage and missing-rclone exits, and that a real run hands the sync CLI only the prepared environment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0145zL6RjeL5rrT7RWULBN1g
… to 83% Real httpx.Client over MockTransport pins: a dead /query gateway is retryable, names only the exception type, and audits a fingerprint without the query text; GET /me sends the bearer and classifies 401/503/non-object replies; transport errors toward OpenTweet never echo the key or host; a non-JSON 201 from /posts is a hard failure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0145zL6RjeL5rrT7RWULBN1g
…ed_executor.py 83% to 100% Gate tests mock it with an AsyncMock, so the semaphore behind /query and the auth workers was never run. Event-coordinated tests pin refusal at capacity, release after completion, a cancelled caller holding its slot while its worker runs, slot release on a failed submit (mutation-checked), and context propagation into the worker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0145zL6RjeL5rrT7RWULBN1g
…er HTTP Role set, disable, enable and hard delete had no HTTP test of their success paths. Pins last-admin protection on all three mutations (AUTH_LAST_ADMIN with the action named), operator-on-non-admin toggling, disable blocking login until enable, 404 for unknown users, CSRF on each write, and the audit event each success emits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0145zL6RjeL5rrT7RWULBN1g
…te_memory.py 66% to 88% The apply-time injection scan had no HTTP-level test. Pins a 400 PROMPT_INJECTION_BLOCKED with its audit event and no fact written; reject being final (apply and re-reject both 400) with the rejected listing and the unknown-status fallback; an unknown proposal id as 400 not 500; and the episodes listing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0145zL6RjeL5rrT7RWULBN1g
|
PR is a complete fill of |
Await the cancelled task through asyncio.gather so the cancellation is an asserted value (CodeQL read the bare await as a no-op), and move each state-changing request out of its assert so python -O cannot strip it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0145zL6RjeL5rrT7RWULBN1g
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Didn't find any major issues. You're on a roll. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
… run-path test clear=True stripped USERPROFILE, so Path.home() raised inside load_sync_config on windows-latest. main() replaces os.environ itself, so the test now injects only GH_TOKEN; removing os.environ.clear() still fails it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0145zL6RjeL5rrT7RWULBN1g
Proposed changes
A
/tests-refactorloop run with the retired/ponytaildiscipline (YAGNI, no dead code, abstract only at ≥4 identical copies; seedocs/audits/PONYTAIL_PLUGIN_6.29.md) overtests/and.github/workflows/. Today'sdocs/audits/2026-10-13-ponytail-audit.mdexplicitly lefttests/untriaged, and this pass covers it.Cuts (ponytail):
tests/import_graph.py: replaces six byte-identical AST import walkers in thetest_*_isolation.pyI6 guards. Each guard aliases it to its old local name, so no test body or file name changes. Those files are cited by name across the docs. Registered intests/README.md.tests/test_gate_query_auth.py: dropstest_device_token_caller_with_no_browser_headers_still_works, a byte-identical copy oftest_device_token_works(same fixtures, request and asserts). Its rationale moves onto the surviving test as the docstring.ci.ymlandpip-audit.yml: the torch-pin "duplicated in" comments had drifted. They sent a future bump todevskim.yml(no torch) andcopilot-setup-steps.yml(hashed lock, no literal pin) and left outnemo-guardrails.yml. They now keep only the grep instruction, which cannot drift.Coverage, aimed at real logic rather than at 100%:
sync/scheduled.py54→79%: policy-derived keystore service and its missing-row refusal; macOS Keychain exit codes (44 means absent; any other nonzero is an error; exactly one newline is stripped); Linux returnsNone; usage and missing-rcloneexits; a real run hands the sync CLI only the prepared env (GH_TOKENgone).opentweet/client.py60→83%: uses a realhttpx.ClientoverMockTransport. Transport errors never echo the key or host. The/queryfailure is audited by fingerprint without the query text. Covers/me, plus a non-JSON 201.utils/bounded_executor.py83→100%: the real/queryand auth capacity bound, which gate tests replace with anAsyncMock. Covers refusal at capacity, release after completion, a cancelled caller keeping its slot, slot release when a submit fails (mutation-checked: deleting thatrelease()fails the test), and context propagation.gate_auth.py81→93%: the RBAC lifecycle routes (role, disable, enable, delete). Covers success paths,AUTH_LAST_ADMINon all three mutations, operators acting only on non-admins, disable blocking login until enable, 404s, CSRF, and the audit events.gate_memory.py66→88%: the apply-time injection block over HTTP (400PROMPT_INJECTION_BLOCKED, an audit event, no fact written), reject being final, and the listings.Follow-up commits from CI and review:
c44e994: addresses two CodeQL findings on the new tests.asyncio.gather, with an assert on the result. CodeQL had read the bareawaitas a no-op and turned the check red.assert, sopython -Ocannot strip it.b7cf992: fixes windows-latest.clear=True, which removedUSERPROFILE, soPath.home()raised insideload_sync_config. It now injects onlyGH_TOKEN.os.environ.clear()fromsync/scheduled.pystill fails the test.c44e994: no findings.Deliberately kept (ponytail "keep"): the 27× per-file
reset_config_cacheautouse fixture (making it global would re-parseconfig.yamlin ~6,000 tests); the torch cache/download steps ×4 across 3 workflows (dep-guard reads per-file pins);policy.fallback.enabledin conftest (it mirrors a deadconfig.yamlkey; removing it is the audit's Tier 2 owner call). Allpytest.skipcalls are conditional, no module-level test helper is unreferenced, and every workflowenv:var has a consumer.Invariant / Governance Impact: none. Only
tests/and comments in two workflows changed; no source file is touched. Graph topology, the RAG-first entry, audit convergence, the I3 gate, soul writes and I6 imports are unchanged.check_invariants.py: 46 passed, 0 failed.Types of changes
Scope: tests + Infrastructure / CI comments only.
Benefits / why
/queryconcurrency bound, and keystore exit codes. Coverage went from 90.14% to 90.83%, with 37 net new tests.Risks to monitor
tests/import_graph.pyis a new non-test_*module intests/. It is imported astests.import_graph, the same waytests.executor_sandbox_doublealready is.test_bounded_executor.pyuses real threads coordinated withthreading.Event, with no sleeps. It is green on all four legs.BoundedExecutor.runis ever deleted, the cancel test hangs (the job's 30-minute timeout) instead of failing fast.sys.platform(and are skipped on Windows because they importpwd).Checklist
docs/THREAT_MODEL.md,INVARIANTS.mdandSECURITY.md(and any relevant Phase docs)GROK_API_KEY=dummy pytest tests/ -q --tb=short, andbash .claude/skills/CyClaw-Sandbox/verify.shfor core RAG/agentic paths) and passes with no regressionsFurther comments
Run directly in this session (Python 3.12 venv, Linux):
--cov, twice. The explicit/tests-refactorinvocation allows this.HardSandboxUnavailable: bubblewrap is required. The container had no bwrap; after installing it, both pass. This is environmental, not a code fault.python -m guardrails.verify_install: all PASS.ruff check --select F,B,S .clean; advisory ruff clean on every touched test file. The pre-existingruff formatdrift in the isolation files is unchanged, not reformatted.CI on
b7cf992: all green, including the four test legs (ubuntu-latest, ubuntu-22.04, windows-latest, macos-latest), condaci (3.12), postgres-backend, verify-install on all three OSes, all 13 verify-skills jobs, workflow-lint (actionlint + zizmor), and CodeQL.Branch note: the session runtime asked for
cc/zen-archimedes-sehyrr, but the tracked hooks refusecc/*. With the owner's OK this usesclaude/ponytail-tests-refactor, which the template prescribes, and no hook was bypassed.Rollback: revert the PR. It is tests and comments only.
Suggested merge order of open PRs
Trial merge verified: branch contains main @ 522b3f7 (2026-10-13); no other open PRs.
This PR · Safe ✅
Impact: independent, only open PR; tests + workflow comments.
Action: Mark ready and merge; CI green on all legs, mergeable clean.
ELI5
The test suite had some copy-pasted parts and some important doors nobody had ever tried to open.
Copy-paste: six safety tests each carried their own identical "which modules does this file import?" scanner. Now there is one, in
tests/import_graph.py. One test intests/test_gate_query_auth.pywas an exact twin of another and was removed. Two workflow comments (ci.yml,pip-audit.yml) told whoever bumps torch to look in the wrong files; they now just say "grep for it".Untested doors, now tested:
gate_auth.py).gate_memory.py)./queryrequests run at once (utils/bounded_executor.py).sync/scheduled.py).opentweet/client.py).Two later fixes, both to my own new tests:
assert, whichpython -Owould silently skip.USERPROFILE. That test now only adds the one variable it checks.No app code changed. Only tests and comments did. CI is green on Linux, Windows and macOS. One thing to know: if someone deletes the concurrency limit in
BoundedExecutor, the cancel test notices by hanging until the 30-minute job timeout, not by failing straight away.🤖 Generated with Claude Code
https://claude.ai/code/session_0145zL6RjeL5rrT7RWULBN1g
Generated by Claude Code
Last updated: 2026-10-13 14:46 ET