agnes-the-ai-analyst/app/web/templates
Vojtech 50a974f196
feat(store-guardrails): admin-configurable content thresholds (#281)
* feat(store-guardrails): admin-configurable content thresholds

Adds the flea-market content guardrail floors to the /admin/server-config
editor so operators can tune the bar without code changes. Defaults are
unchanged (60 chars description, 25 chars command, 5 distinct words, 200
chars body) — patching guardrails.* in instance.yaml or via the admin UI
overrides any of them and the next inline check picks up the new value.

src/store_guardrails/content_check.py now resolves the four floors via
helper functions (_min_desc_chars / _min_command_desc_chars /
_min_distinct_words / _min_body_chars) that read app.instance_config at
call time. Module-level _DEFAULT_* constants remain as fallbacks if
the import fails (defensive — keeps the guardrail module loadable
without the app package on its path).

app/instance_config.py grows four matching getters returning the live
value with sane defaults + integer coercion.

app/api/admin.py registers 'guardrails' as an editable section + ships
nine known-fields entries (min_description_chars,
min_command_description_chars, min_distinct_words, min_body_chars,
enabled, review_model, blocked_quota_per_day, blocked_bundle_ttl_days,
stuck_review_grace_seconds) with operator-facing hint copy explaining
what each knob does.

app/web/templates/admin_server_config.html gets a SECTION_META entry
so the section renders as 'Flea-market guardrails' with a help string
instead of a bare section ID.

app/web/router.py threads the live thresholds into /store/new and
/store/examples via a small _guardrail_thresholds() helper so the
disclosure copy, char counter, and "Why these limits" table render
the configured value (not a hardcoded 60). End-to-end smoke verified:
PATCH guardrails.min_description_chars=90 → /store/new immediately
renders "90 characters" + JS DESC_MIN=90 on the next request, no
restart required (helpers read live config per call).

* chore(store-guardrails): address PR review safe-fix findings

Code-review safe_auto findings on PR #281 (review run
20260513-100126-64052520):

- CHANGELOG: add Unreleased entry covering the new
  /admin/server-config Flea-market guardrails section, the four live
  threshold getters, and the route-helper rendering knobs. Required by
  the project's non-negotiable "Changelog discipline" rule.
- content_check.py: narrow `except Exception` to `except ImportError`
  on the four `_min_*()` resolver helpers. Surface-level TypeError /
  ValueError on a malformed YAML value belongs to the
  instance_config getters' own try/except — the resolvers should only
  defend against the in-tree import itself failing, not silently
  swallow real bugs in the getters.
- store_upload.html: refresh the stale "30-char threshold" comment to
  reflect the configurable floor (default 60), and add `|default(60)`
  / `|default(25)` / `|default(5)` filters to the disclosure-copy
  bindings so the upload form matches store_examples.html's
  belt-and-suspenders rendering if a future route ever renders the
  template without populating the `guardrail` context.
- router.py: tighten `_guardrail_thresholds()` return annotation
  from bare `dict` to `dict[str, int]`.

Residual work (left for separate change after operator direction):
- Add round-trip test (PATCH guardrails -> next inline check uses
  new value) — primary testing gap.
- Decide policy on `min_*=0` (currently coerced to 1 via
  `max(1, int(val))`) vs treating 0 as a disable sentinel like
  neighbour getters (`blocked_quota_per_day`,
  `blocked_bundle_ttl_days`).
- Add POST-time integer validation for `guardrails.*` so a typo'd
  YAML value (bool / string / float) errors loudly instead of
  silently falling back to the default.

* test(store-guardrails): cover admin-configurable thresholds + PATCH round-trip

Closes the "primary testing gap" Vojta noted in the safe-fix commit
on PR #281 — the four new `get_guardrails_min_*` getters and the
PATCH-takes-effect-on-next-check live-config flow had no direct
coverage.

10 new tests in `tests/test_store_guardrails_admin_config.py`:

- TestGuardrailGetterDefaults (4 tests) — each new getter returns the
  documented default (60 / 25 / 5 / 200) when nothing is configured.
- TestGuardrailGetterOverlay (5 tests) — overlay-driven overrides win,
  string values that look numeric coerce via int(), garbage strings
  fall back to default via the (TypeError, ValueError) branch, and the
  `max(1, int(val))` floor pins zero/negative inputs to 1.
- TestPatchRoundTrip (1 test) — PATCH `/api/admin/server-config`
  `guardrails.min_description_chars=90`, then call content_check
  against a 75-char description that previously passed: must now fail
  with `too_short`. Then PATCH back to 60 and verify the next check
  passes again. Closes the cache-invalidation contract Vojta relies on
  for the "no app restart" claim — broken without the
  reset_cache() bracket in /api/admin/server-config.

The TestGuardrailGetterOverlay.test_zero_or_negative_floored_to_one
test pins the current `max(1, int(val))` policy. Vojta's safe-fix
commit explicitly left "policy on min_*=0 vs disable-sentinel" as
residual work — pinning the current behavior here ensures any future
change to use 0 as a disable sentinel must update this test (and the
reviewer sees the policy decision).

Verified: 4509 tests pass locally (4499 existing + 10 new).

* release: 0.54.2 — admin-configurable flea-market guardrail thresholds + tests

Last commit on the PR per CLAUDE.md hard rule. Patch bump (0.54.1 →
0.54.2) bundling Vojta's admin-configurable thresholds for the
flea-market content guardrail (9 knobs in /admin/server-config) plus
the test coverage closing the "primary testing gap" he punted in the
safe-fix commit.

No DB migration; defaults unchanged from PR #276 — instances that
don't set `guardrails.*` keep the original bar transparently.

---------

Co-authored-by: ZdenekSrotyr <zdenek.srotyr@keboola.com>
Co-authored-by: ZdenekSrotyr <139972147+ZdenekSrotyr@users.noreply.github.com>
2026-05-13 09:20:55 +00:00
..
admin feat(home): state-aware /home + /setup-advanced + schema v26 (#228) 2026-05-08 18:28:47 +02:00
_app_header.html Activity Center: audit log + telemetry + sessions + agnes_* tables (#278) 2026-05-12 22:41:19 +02:00
_claude_setup_cta.jinja fix(cta): clipboard fallback + fold Atlassian MCP into connectors (#249) 2026-05-11 21:54:51 +02:00
_claude_setup_instructions.jinja feat(web): rename /install → /setup; nav label 'Setup local agent' 2026-05-03 16:12:13 +02:00
_content_findings.html feat(store-guardrails): per-component description quality + plain-language UX (#276) 2026-05-12 21:48:27 +02:00
_content_howto_fix.html feat(store-guardrails): per-component description quality + plain-language UX (#276) 2026-05-12 21:48:27 +02:00
_flea_versions.html Flea-market edit feature with version history (schema v37) (#239) 2026-05-10 00:14:33 +04:00
_marketplace_video_embed.html Curated marketplace enrichment via agnes-metadata.json + curator metadata (#234) 2026-05-09 17:01:37 +02:00
_message.html feat(auth): password reset & invite flows for web + admin (#34) (#37) 2026-04-22 17:43:57 +02:00
_page_chrome.html feat(home): state-aware /home + /setup-advanced + schema v26 (#228) 2026-05-08 18:28:47 +02:00
_posthog.html feat(observability): optional PostHog integration (#231) 2026-05-08 17:57:10 +04:00
_quarantine_banner.html feat(store-guardrails): per-component description quality + plain-language UX (#276) 2026-05-12 21:48:27 +02:00
_theme.html feat: complete system — web UI, all API endpoints, governance, admin, CLI commands 2026-03-27 16:52:22 +01:00
_version_badge.html feat(ui): version badge as shared partial, injected into every full-page template 2026-04-21 20:51:55 +02:00
activity_center.html Activity Center: audit log + telemetry + sessions + agnes_* tables (#278) 2026-05-12 22:41:19 +02:00
admin_access.html System plugins (schema v39) + marketplace UX polish + drop legacy pages (#241) 2026-05-10 19:15:41 +00:00
admin_group_detail.html feat(admin): users/groups UI polish + SSO lock + v18 migration (#142) 2026-04-30 15:16:04 +02:00
admin_groups.html feat(admin): users/groups UI polish + SSO lock + v18 migration (#142) 2026-04-30 15:16:04 +02:00
admin_marketplaces.html Marketplace UX overhaul: rich plugin/skill/agent detail + filename rename (#251) 2026-05-12 08:38:39 +00:00
admin_scheduler_runs.html Flea-market upload guardrails + soft delete + JOIN-based admin queue (#233) 2026-05-09 17:32:53 +04:00
admin_server_config.html feat(store-guardrails): admin-configurable content thresholds (#281) 2026-05-13 09:20:55 +00:00
admin_session_detail.html Activity Center: audit log + telemetry + sessions + agnes_* tables (#278) 2026-05-12 22:41:19 +02:00
admin_sessions.html Activity Center: audit log + telemetry + sessions + agnes_* tables (#278) 2026-05-12 22:41:19 +02:00
admin_store_submission_detail.html Flea-market edit feature with version history (schema v37) (#239) 2026-05-10 00:14:33 +04:00
admin_store_submissions.html Flea-market edit feature with version history (schema v37) (#239) 2026-05-10 00:14:33 +04:00
admin_tables.html Activity Center: audit log + telemetry + sessions + agnes_* tables (#278) 2026-05-12 22:41:19 +02:00
admin_tokens.html User management + PAT + CLI distribution + HTML auth redirect (#9 #10 #11 #12) (#28) 2026-04-22 14:24:28 +02:00
admin_usage.html Activity Center: audit log + telemetry + sessions + agnes_* tables (#278) 2026-05-12 22:41:19 +02:00
admin_user_detail.html Activity Center: audit log + telemetry + sessions + agnes_* tables (#278) 2026-05-12 22:41:19 +02:00
admin_users.html feat(admin): users/groups UI polish + SSO lock + v18 migration (#142) 2026-04-30 15:16:04 +02:00
admin_welcome.html Activity Center: audit log + telemetry + sessions + agnes_* tables (#278) 2026-05-12 22:41:19 +02:00
admin_workspace_prompt.html Activity Center: audit log + telemetry + sessions + agnes_* tables (#278) 2026-05-12 22:41:19 +02:00
base.html feat(home): state-aware /home + /setup-advanced + schema v26 (#228) 2026-05-08 18:28:47 +02:00
base_login.html feat(ui): version badge as shared partial, injected into every full-page template 2026-04-21 20:51:55 +02:00
catalog.html Activity Center: audit log + telemetry + sessions + agnes_* tables (#278) 2026-05-12 22:41:19 +02:00
corporate_memory.html Activity Center: audit log + telemetry + sessions + agnes_* tables (#278) 2026-05-12 22:41:19 +02:00
corporate_memory_admin.html fix(memory-admin): pass RBAC user_groups (not YAML config) to /corporate-memory/admin (#253) 2026-05-12 13:16:01 +00:00
dashboard.html Activity Center: audit log + telemetry + sessions + agnes_* tables (#278) 2026-05-12 22:41:19 +02:00
desktop_link.html feat: complete system — web UI, all API endpoints, governance, admin, CLI commands 2026-03-27 16:52:22 +01:00
error.html feat(observability): request_id end-to-end + dev debug toolbar + centralized logging (#136) 2026-04-29 22:54:21 +02:00
home_not_onboarded.html feat(setup): configurable instance brand + connector setup overhaul (#268) 2026-05-12 17:10:08 +02:00
home_onboarded.html feat(setup): configurable instance brand + connector setup overhaul (#268) 2026-05-12 17:10:08 +02:00
install.html feat(setup): configurable instance brand + connector setup overhaul (#268) 2026-05-12 17:10:08 +02:00
login.html feat(setup): configurable instance brand + connector setup overhaul (#268) 2026-05-12 17:10:08 +02:00
login_email.html feat(auth): password reset & invite flows for web + admin (#34) (#37) 2026-04-22 17:43:57 +02:00
login_magic_link.html feat: complete system — web UI, all API endpoints, governance, admin, CLI commands 2026-03-27 16:52:22 +01:00
login_magic_link_sent.html feat: complete system — web UI, all API endpoints, governance, admin, CLI commands 2026-03-27 16:52:22 +01:00
marketplace.html Activity Center: audit log + telemetry + sessions + agnes_* tables (#278) 2026-05-12 22:41:19 +02:00
marketplace_format_guide.html Curated marketplace enrichment via agnes-metadata.json + curator metadata (#234) 2026-05-09 17:01:37 +02:00
marketplace_guide.html Add /marketplace browse page + Model B opt-in stack composition (#230) 2026-05-08 14:22:19 +02:00
marketplace_item_detail.html Marketplace UX overhaul: rich plugin/skill/agent detail + filename rename (#251) 2026-05-12 08:38:39 +00:00
marketplace_plugin_detail.html Marketplace UX overhaul: rich plugin/skill/agent detail + filename rename (#251) 2026-05-12 08:38:39 +00:00
me_debug.html feat(setup): configurable instance brand + connector setup overhaul (#268) 2026-05-12 17:10:08 +02:00
my_tokens.html User management + PAT + CLI distribution + HTML auth redirect (#9 #10 #11 #12) (#28) 2026-04-22 14:24:28 +02:00
news.html feat(home): state-aware /home + /setup-advanced + schema v26 (#228) 2026-05-08 18:28:47 +02:00
password_reset.html feat(auth): password reset & invite flows for web + admin (#34) (#37) 2026-04-22 17:43:57 +02:00
password_setup.html feat(auth): password reset & invite flows for web + admin (#34) (#37) 2026-04-22 17:43:57 +02:00
profile.html feat(admin): users/groups UI polish + SSO lock + v18 migration (#142) 2026-04-30 15:16:04 +02:00
profile_sessions.html Extract session-pipeline framework + UsageProcessor skeleton (#232) 2026-05-08 19:47:46 +02:00
setup.html feat(setup): configurable instance brand + connector setup overhaul (#268) 2026-05-12 17:10:08 +02:00
setup_advanced.html feat(setup): configurable instance brand + connector setup overhaul (#268) 2026-05-12 17:10:08 +02:00
store_edit.html Flea-market edit feature with version history (schema v37) (#239) 2026-05-10 00:14:33 +04:00
store_examples.html feat(store-guardrails): admin-configurable content thresholds (#281) 2026-05-13 09:20:55 +00:00
store_upload.html feat(store-guardrails): admin-configurable content thresholds (#281) 2026-05-13 09:20:55 +00:00