ENG-815 - Three collateral smells from PR #82's blind startswith-sweep - #188
Conversation
There was a problem hiding this comment.
Verdict: approve
All four acceptance criteria are satisfied by 500d0dd, and the change stays inside the stated behavior-preserving scope.
AC1 — backtick checks (backend/druks/harnesses/subprocess.py:19,21). Both opening-fence checks are .startswith("```") again; no slice comparison remains in the file. Closing-fence stripping, JSON parsing, and HarnessInvalidOutputError are untouched.
AC2 — registry import seam (backend/druks/harnesses/registry.py). The module-level from druks.user_settings.models import HarnessSettings is gone; the import now sits at function scope inside get_harness_for_model() immediately before the HarnessSettings.all() loop. Bare-name match, allowed_models ID match, row.harness return, and the loud HarnessError miss are all preserved. test_shipped_tuple_fallback_routes_shipped_models, test_fetched_list_routes_provider_models, test_bare_harness_name_routes, and test_unknown_model_raises_harness_error still cover the four routing paths and pass.
AC3 — single raise (backend/druks/user_settings/routes.py:71-81). Resolution and the harness-mismatch check now live in one try; the mismatch translates into HarnessError and a single except HarnessError raises HTTP 422 with the exact detail f"{updates['model']!r} is not a {harness.name} model." and from exc. Effort/timeout validation and the success path are unchanged.
AC4 — test coverage (backend/tests/test_harness_model_routing.py:47-68). test_settings_reject_invalid_model_returns_422 is parametrized over gpt-5.5 (another harness's registered model) and llama-3-70b (unregistered), asserting exact status 422 and the exact detail string for each, plus settings.model == original_model so a rejected update leaves the row alone. The _validate_model test for the distinct "No installed harness runs model ..." detail is retained.
Verification
uv run ruff check backend— pass (local: "All checks passed!").uv run pytest backend/— pass, 1116 passed (local, againstdeploy/compose.dev.yamlPostgres + Redis).uv pip install -e backend/tests/druks-field_notes+ the three proof-extension test files — pass, 5 passed.- GitHub check
checks— success on500d0dd. npm --prefix frontend run lint/run build/test— not run: no Node toolchain in this sandbox (npm: command not found), and no frontend check ran on this commit because the diff is backend-only and the frontend workflow's path filters exclude it. Not a blocker for a backend-only change.
Open findings
backend/druks/harnesses/routes.py:14andbackend/druks/harnesses/models.py:14still importdruks.user_settingsat module level. Pre-existing, outside this ticket's scope (ENG-815 names onlyregistry.py), and untouched by this diff — noting it because the layering concern the ticket raises applies there too, and it may be worth a follow-up that either moves those seams or addsdruks.harnessesto the boundary rule's named list. No change requested here.raise HarnessErrorinside thetrymakes the synthetic exception the__cause__rather than the original miss, which slightly shortens the traceback for the unregistered-model case. This is exactly what the plan specified ("translate a resolved harness whose name differs from the requested harness intoHarnessError"), so it is intended, not a defect.
If you read either open finding differently — particularly if you think the __cause__ shape deserves a distinct sentinel subclass — push back; neither is blocking and I'd rather hear the counter-argument than have you work around a note.
|
Code review: Clean, tightly-scoped fix for all three ENG-815 smells — startswith restored in subprocess.py, the harnesses/user_settings import cycle broken with a function-scoped import (consistent with the existing precedent in HarnessSettings.harness), and the duplicate 422 branches in routes.py collapsed into one, with a new parametrized test covering both rejection paths and asserting the settings row is left untouched on failure. |
Linear ticket: ENG-815
Plan
Implementation plan
In
backend/druks/harnesses/subprocess.py, restore the two purpose-built prefix checks inread_result_json()verbatim totext.startswith("```")andlines[0].startswith("```"). Leave closing-fence stripping, JSON parsing, andHarnessInvalidOutputErrorbehavior untouched.In
backend/druks/harnesses/registry.py, remove the module-levelfrom druks.user_settings.models import HarnessSettingsdependency. ImportHarnessSettingsinsideget_harness_for_model()immediately before the settings query, preserving the current iteration overHarnessSettings.all(), bare-harness-name match,allowed_modelsID match, returnedrow.harness, and exact miss error. This is the narrow cycle seam already used byHarnessSettings.harness, which resolves back throughdruks.harnesses.registry.In
backend/druks/user_settings/routes.py, consolidate the two invalid-model branches inupdate_harness_settings(). Keep resolution within onetryblock, translate a resolved harness whose name differs from the requested harness intoHarnessError, and let oneexcept HarnessErrorraise the existing HTTP 422 with the exact detailf"{updates['model']!r} is not a {harness.name} model."and exception chaining. Do not alter successful updates or effort/timeout validation.In
backend/tests/test_harness_model_routing.py, expand the existing harness-update rejection test to exercise both failure sources—another harness's registered model and an unregistered model—and assert the exact 422 detail for each. Retain the existing routing coverage for shipped lists, fetched lists, bare harness names, and misses.The preserved HTTP behavior is:
{"detail":"'gpt-5.5' is not a claude model."}and an unknown model such as
{"model":"llama-3-70b"}returns status 422 with{"detail":"'llama-3-70b' is not a claude model."}.Out of scope: changing model-routing semantics, fetched or shipped model data, endpoint schemas, status codes, user-facing error text, or the repository's named author-surface boundary list.
Acceptance criteria
AC1
Description: Both opening-fence checks in
backend/druks/harnesses/subprocess.pyuse.startswith("```"); neither uses a three-character slice comparison.Verification: Inspect
read_result_json: the outertextcheck and first-line check both call.startswith("```").AC2
Description:
backend/druks/harnesses/registry.pyhas no module-level import fromdruks.user_settings;get_harness_for_model()importsHarnessSettingsat function scope and retains the existing fetched-or-shipped model-list lookup andHarnessErrormiss behavior.Verification: Inspect the module imports and
get_harness_for_model, then read the existing routing tests covering shipped models, fetched models, bare harness names, and unknown models.AC3
Description: Model validation in
update_harness_settings()contains oneHTTPExceptionraise for both an unknown model and a model belonging to another harness, preserving status 422 and the exact detail template{model!r} is not a {harness.name} model.Verification: Inspect the
if "model" in updatesbranch and confirm focused tests assert exact status and detail for both failure sources.AC4
Description:
backend/tests/test_harness_model_routing.pycovers both invalid update cases:gpt-5.5when updatingclaude, and an unregistered model such asllama-3-70b; each produces the corresponding exact 422 detail without updating settings.Verification: Read the parametrized or equivalent route-level tests and their exact
HTTPException.status_codeanddetailassertions.Ruled out
druks.harnessesto the named architectural boundary rule while retaining the module-leveluser_settingsimport: this would legitimize the cross-concern import instead of removing it and would leave the registry coupled to model initialization at import time.Noneor a boolean after catchingHarnessError: this would turn a typed resolution failure into sentinel state and discard the original exception cause..startswithor import placement: those tests would pin implementation syntax rather than behavior; these two code-shape requirements are directly inspectable acceptance criteria.Acceptance Criteria
backend/druks/harnesses/subprocess.pyuse.startswith("```"); neither uses a three-character slice comparison.read_result_json: the outertextcheck and first-line check both call.startswith("```").backend/druks/harnesses/registry.pyhas no module-level import fromdruks.user_settings;get_harness_for_model()importsHarnessSettingsat function scope and retains the existing fetched-or-shipped model-list lookup andHarnessErrormiss behavior.get_harness_for_model, then read the existing routing tests covering shipped models, fetched models, bare harness names, and unknown models.update_harness_settings()contains oneHTTPExceptionraise for both an unknown model and a model belonging to another harness, preserving status 422 and the exact detail template{model!r} is not a {harness.name} model.if "model" in updatesbranch and confirm focused tests assert exact status and detail for both failure sources.backend/tests/test_harness_model_routing.pycovers both invalid update cases:gpt-5.5when updatingclaude, and an unregistered model such asllama-3-70b; each produces the corresponding exact 422 detail without updating settings.HTTPException.status_codeanddetailassertions.