agnes-the-ai-analyst/docs
Vojtech a694a30a5e
fix(store): surface review failures + harden publish gate (#316)
* fix(store): surface review failures + harden publish gate

Four independent fixes to the flea-market submission pipeline, all surfaced
by an admin upload that landed at status='approved' without an LLM review.

1. LLM truncation no longer pins submissions in review_error.
   - Raised MAX_RESPONSE_TOKENS 2500 → 6000 in llm_review.py
   - Added one-shot retry-with-doubled-budget in anthropic_provider.py
     (capped at 4× initial)

2. Flea detail page surfaces the latest submission's failure verdict even
   when a previously-approved version is still serving (deferred-promotion
   path). The _quarantine_banner gate widened from `visibility != approved`
   to also fire on `blocked_inline / blocked_llm / review_error`, with copy
   that distinguishes the v2+ edit case ("Latest edit failed review —
   previously approved version (vN) keeps serving") from the initial-upload
   quarantine wording.

3. Restore button + endpoint no longer allow restoring a version that was
   never approved. Added StoreEntitiesRepository.get_with_version_approvals
   joining store_submissions, gated the UI button on submission_status in
   ('approved', None), rendered status pills for non-restorable rows, and
   added a 400 version_not_approved guard in POST /restore.

4. **BREAKING (operator-facing)**: publish gate is now fail-CLOSED on
   misconfig. The previous get_guardrails_enabled() silently fell back to
   "disabled, auto-approve everything" when guardrails.enabled=true in YAML
   but no ANTHROPIC_API_KEY was in env. Split into:
     - get_guardrails_enabled()              (intent — YAML)
     - get_guardrails_llm_provider_ready()   (readiness — env)
   Three-state matrix:
     enabled=false                       → auto-approve (unchanged)
     enabled=true + ready=true           → normal pipeline (unchanged)
     enabled=true + ready=false (NEW)    → submissions hold at pending_llm
                                           awaiting admin retry or override
                                           (was: silent auto-approve)
   Admin "Retry review" eligibility broadened to include pending_llm.
   Boot-time WARNING banner surfaces the misconfig in app/main.py.
   docs/STORE_GUARDRAILS.md updated with the three-state matrix.
   Operators relying on the auto-fallback for local-dev no-LLM setups must
   now explicitly set `guardrails.enabled: false` in instance.yaml.

Tests: 4623 passed. Added TestPublishGateFailClosed (4 tests) and
TestRestoreVersion::test_restore_rejects_* (3 tests). conftest.py adds an
autouse fixture defaulting guardrails OFF so legacy tests don't need to
know about the new toggle.

* fix(store): admin override promotes v2+ edits to current

The override handler at app/api/admin.py:3708 only flipped submission
status → 'overridden' and entity visibility → 'approved'. Under the v37+
deferred-promotion model that's insufficient for v2+ edits / restores:
the new bundle sits in versions/v<N>/plugin/ and the entity row stays at
the prior approved version_no + hash + on-disk live bundle. Installers
kept getting the OLD bytes the admin had just intended to replace.

Mirror the runner.run_llm_review auto-approval branch: look up the
submission's version_hash in entity.version_history, and if its `n`
differs from entity.version_no, promote_version + _swap_live_to_version.
Initial v1 overrides are unaffected — the loop finds n=1 == version_no
and skips promotion.

Tests:
- test_override_v2_edit_promotes_to_current: stage v1 approved + v2
  blocked_llm; override the v2 sub; assert entity.version_no=2,
  entity.version flips off the v1 hash, and the live plugin/ dir
  mirrors versions/v2/plugin/.
- test_override_v1_initial_upload_no_promote: regression guard so the
  promote loop doesn't accidentally bump a v1 override.

Audit log gains a promoted_to_version_no field on the override action.

* fix(store): retry/rescan review staged bundle; override forward-only

Two adversarial-review findings from a Codex pass on the publish-gate
work.

C1. Admin retry + rescan were passing live `plugin/` to the LLM. For a
v2+ submission held at `pending_llm` / `blocked_llm` / `review_error`,
live still holds the prior approved version's bytes — so the LLM
reviewed the WRONG bytes, and the runner's hash-match promotion in
`run_llm_review` would then advance the entity to staged bytes that
were never actually reviewed. Resolve the staged
`<entity>/versions/v<N>/plugin/` from the submission's
`version_history` entry, with a fall-back to live for legacy pre-v37
rows that never seeded a versions/ dir. Helpers
`_submission_plugin_dir` and `_version_no_for_submission` added to
`app/api/store.py` so override / retry / rescan share one path.

H1. Override's promote loop used `target != current`, which would
silently demote the live bundle when admin overrode a stale v2
submission while v3 was already approved + live. Changed to
`target > current` so override flips status + visibility on the row
regardless, but on-disk promotion only fires forward. Same `>`
defensive guard applied in `runner.run_llm_review` so a late LLM
verdict racing with a newer approval can't demote either.

Tests:
- TestAdminRetryReviewsStagedBundle::test_retry_v2_blocked_passes_staged_dir_not_live
- TestAdminRetryReviewsStagedBundle::test_rescan_v2_blocked_passes_staged_dir_not_live
- TestOverrideForwardOnly::test_override_stale_v2_does_not_demote_when_v3_current

* review polish: CHANGELOG drift, override eligibility, defensive copy

Three small additions on top of the retry/rescan staged-bundle fix:

1. CHANGELOG: the PR's bullets had drifted into the released
   [0.54.17] section during rebase (context-match landed them next
   to already-released content). Moved them up to [Unreleased] where
   they belong; [0.54.17] now holds only what was actually released
   (refresh-marketplace ls-remote, /me/activity hero, CI sharding +
   workflow polish).

2. app/api/admin.py: admin override eligibility now accepts
   pending_llm alongside blocked_inline + blocked_llm + review_error.
   Closes a UX gap from the new fail-CLOSED behavior: under
   enabled-but-not-ready, a known-good submission would otherwise
   sit indefinitely until the admin set credentials AND clicked
   Retry. Override already routes through version_history (and is
   now forward-only on promote), so it stays safe for v2+ deferred-
   promotion submissions.

3. src/repositories/store_entities.py: get_with_version_approvals
   defensively copies each version_history entry before annotating
   with submission_status. self.get() re-parses JSON each call today
   so this is belt-and-suspenders against any future caching layer
   leaking the annotated key into a subsequent plain get() call.

Tests: 112 passed (focused on test_store_entity_versions +
test_admin_store_submissions, covering the retry/rescan staged-
bundle fix the author shipped + this polish).

---------

Co-authored-by: ZdenekSrotyr <zdenek.srotyr@keboola.com>
2026-05-15 15:52:07 +02:00
..
admin release: 0.47.0 — source-agnostic catalog metadata + cache discipline (#223) 2026-05-07 18:33:55 +02:00
archive docs: consolidate and de-clutter the documentation tree (#306) 2026-05-14 18:54:22 +00:00
examples Marketplace UX overhaul: rich plugin/skill/agent detail + filename rename (#251) 2026-05-12 08:38:39 +00:00
HOWTO feat(cli): agnes marketplace search/detail/add/remove + retire stale subcommands (#280) 2026-05-13 05:20:56 +00:00
metrics chore(docs): replace stale da verbs and vendor-specific install paths 2026-05-04 21:22:19 +02:00
operator feat(home): state-aware /home + /setup-advanced + schema v26 (#228) 2026-05-08 18:28:47 +02:00
setup release: 0.47.1 — Keboola connector v27 (incremental, partitioned, where_filters, typed parquet) (#217) 2026-05-07 19:01:27 +02:00
testing docs(testing): add coverage honesty + prerequisites to E2E plan 2026-05-04 19:59:47 +02:00
ADR-corporate-memory-v1.md feat(memory): corporate memory v1+v1.5 + 0.15.0 (#72) 2026-04-29 07:16:22 +02:00
agent-setup-prompt.md fix(api): align PUT validation autoescape with runtime (False); docs match 2026-05-03 21:30:24 +02:00
agent-workspace-prompt.md chore(docs): replace stale da verbs and vendor-specific install paths 2026-05-04 21:22:19 +02:00
architecture.md fix(compose): drop corporate-memory + session-collector services (#176) 2026-05-04 23:59:44 +02:00
auth-google-oauth.md refactor(docs): sweep DA_* env vars + surviving da-verbs in docs/*.md (Task 0.5 fix) 2026-05-04 16:43:15 +02:00
auth-groups.md refactor(docs): sweep DA_* env vars + surviving da-verbs in docs/*.md (Task 0.5 fix) 2026-05-04 16:43:15 +02:00
CONFIGURATION.md Activity Center: audit log + telemetry + sessions + agnes_* tables (#278) 2026-05-12 22:41:19 +02:00
corporate-memory-governance.md
curated-marketplace-format.md Marketplace UX overhaul: rich plugin/skill/agent detail + filename rename (#251) 2026-05-12 08:38:39 +00:00
DATA_SOURCES.md remove agnes query --register-bq from client CLI 2026-05-12 18:18:13 +02:00
DEPLOYMENT.md Activity Center: audit log + telemetry + sessions + agnes_* tables (#278) 2026-05-12 22:41:19 +02:00
development.md feat(observability): request_id end-to-end + dev debug toolbar + centralized logging (#136) 2026-04-29 22:54:21 +02:00
HEADLESS_USAGE.md feat(web): consolidate the personal /me/* surface — /me/activity + /me/profile (#304) 2026-05-14 21:29:51 +02:00
initial-workspace-override.md fix: refresh-marketplace enables stack plugins; override sentinel is init-time only (#307) 2026-05-14 18:43:32 +02:00
llm-routing.md docs,tests: anonymize customer references 2026-04-21 11:56:19 +02:00
local-development.md feat(web): consolidate the personal /me/* surface — /me/activity + /me/profile (#304) 2026-05-14 21:29:51 +02:00
marketplace.md docs: consolidate and de-clutter the documentation tree (#306) 2026-05-14 18:54:22 +00:00
observability.md feat(observability): optional PostHog integration (#231) 2026-05-08 17:57:10 +04:00
ONBOARDING.md Activity Center: audit log + telemetry + sessions + agnes_* tables (#278) 2026-05-12 22:41:19 +02:00
PLATFORM_SETUP.md Activity Center: audit log + telemetry + sessions + agnes_* tables (#278) 2026-05-12 22:41:19 +02:00
QUICKSTART.md docs: consolidate and de-clutter the documentation tree (#306) 2026-05-14 18:54:22 +00:00
RBAC.md refactor(docs): sweep DA_* env vars + surviving da-verbs in docs/*.md (Task 0.5 fix) 2026-05-04 16:43:15 +02:00
README.md docs: consolidate and de-clutter the documentation tree (#306) 2026-05-14 18:54:22 +00:00
RELEASE_CHECKLIST.md docs: consolidate and de-clutter the documentation tree (#306) 2026-05-14 18:54:22 +00:00
RELEASING.md ci: consolidate release pipeline (salvageable subset of #139) (#314) 2026-05-15 14:06:59 +02:00
sample-data.md chore(docs): replace stale da verbs and vendor-specific install paths 2026-05-04 21:22:19 +02:00
state-dir.md fix: Devin Review on #194 round 2 — 3 BUG-class findings 2026-05-05 20:02:50 +02:00
STORE_GUARDRAILS.md fix(store): surface review failures + harden publish gate (#316) 2026-05-15 15:52:07 +02:00
theme-reference.html

Agnes documentation

Index of all documentation, organized by who needs it. New here? Start with the row that matches your role.

You are… Start with
Analyst — using Agnes to query data QUICKSTART.md, then HOWTO/
Operator — deploying & running an instance PLATFORM_SETUP.md
Developer — working on Agnes itself ../ARCHITECTURE.md + architecture.md

For analysts

Using the platform to analyze data.

  • QUICKSTART.md — local setup + first sync
  • HOWTO/ — task-oriented cookbook (querying, snapshots, common workflows)
  • DATA_SOURCES.md — data source connectors (Keboola, BigQuery, CSV) and how tables surface
  • metrics/ — canonical business-metric definitions (YAML)
  • HEADLESS_USAGE.md — PAT auth for CI / headless clients

For operators

Deploying, configuring, and running an Agnes instance.

For developers

Working on the Agnes codebase.

Code-adjacent READMEs: ../connectors/jira/README.md, ../services/corporate_memory/README.md, ../scripts/README.md. Agent skill files: ../cli/skills/.

Other