* 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>
|
||
|---|---|---|
| .. | ||
| admin | ||
| archive | ||
| examples | ||
| HOWTO | ||
| metrics | ||
| operator | ||
| setup | ||
| testing | ||
| ADR-corporate-memory-v1.md | ||
| agent-setup-prompt.md | ||
| agent-workspace-prompt.md | ||
| architecture.md | ||
| auth-google-oauth.md | ||
| auth-groups.md | ||
| CONFIGURATION.md | ||
| corporate-memory-governance.md | ||
| curated-marketplace-format.md | ||
| DATA_SOURCES.md | ||
| DEPLOYMENT.md | ||
| development.md | ||
| HEADLESS_USAGE.md | ||
| initial-workspace-override.md | ||
| llm-routing.md | ||
| local-development.md | ||
| marketplace.md | ||
| observability.md | ||
| ONBOARDING.md | ||
| PLATFORM_SETUP.md | ||
| QUICKSTART.md | ||
| RBAC.md | ||
| README.md | ||
| RELEASE_CHECKLIST.md | ||
| RELEASING.md | ||
| sample-data.md | ||
| state-dir.md | ||
| STORE_GUARDRAILS.md | ||
| 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 syncHOWTO/— task-oriented cookbook (querying, snapshots, common workflows)DATA_SOURCES.md— data source connectors (Keboola, BigQuery, CSV) and how tables surfacemetrics/— canonical business-metric definitions (YAML)HEADLESS_USAGE.md— PAT auth for CI / headless clients
For operators
Deploying, configuring, and running an Agnes instance.
PLATFORM_SETUP.md— the consolidated operator playbook (bootstrap, TLS, marketplaces, scheduler, telemetry)ONBOARDING.md— end-to-end Terraform deployment into a new GCP projectDEPLOYMENT.md— picks between the Terraform and Docker Compose pathsCONFIGURATION.md—instance.yaml, env vars, per-instance optionsstate-dir.md— persistent data layout (data+statetiers, mount layouts, migration)RBAC.md— access control: groups, members, resource grantsauth-google-oauth.md— Google OAuth setup + operator gotchasauth-groups.md— Google Workspace group syncadmin/query-modes.md— table registration query modesagent-setup-prompt.md— customize the/setuppage banneragent-workspace-prompt.md— customize the generated analystCLAUDE.mdinitial-workspace-override.md— per-instance analyst-workspace skeleton overridecurated-marketplace-format.md— authoringmarketplace-metadata.jsonfor curated marketplacesobservability.md— PostHog integration (exceptions, tracing, session replay)operator/news-content-guide.md— editorial guidelines for in-app news content
For developers
Working on the Agnes codebase.
../ARCHITECTURE.md— high-level system overview (the summary)architecture.md— detailed architecture reference (module map, extract.duckdb contract, components)../CLAUDE.md— project instructions for AI agents working in this repodevelopment.md— logging, request correlation, debug toolbarlocal-development.md—LOCAL_DEV_MODEsetup (what's mocked vs. real)RELEASING.md— release process, deploy workflows, CI quirksRELEASE_CHECKLIST.md— pre-merge checks for bootstrap-path changestesting/— test plans (clean-analyst bootstrap, VM test)marketplace.md— Claude Code marketplace ingestion + re-serving internalsSTORE_GUARDRAILS.md— flea-market upload guardrails (static checks + LLM review)corporate-memory-governance.md— knowledge-distribution governance designADR-corporate-memory-v1.md— ADR: corporate-memory v1 decisionsllm-routing.md— design: provider-agnostic LLM routingsample-data.md— sample data generator (e-commerce schema, size presets)theme-reference.html— web UI theme/color reference../dev_docs/— server/developer-internal docs (not synced to analyst machines): server ops, disaster recovery, security audit, desktop app, design system, Telegram bot
Code-adjacent READMEs: ../connectors/jira/README.md,
../services/corporate_memory/README.md,
../scripts/README.md.
Agent skill files: ../cli/skills/.
Other
../CHANGELOG.md— full change history (Keep-a-Changelog format)archive/— historical planning artifacts and superseded docs; not maintained, seearchive/README.md