fix(web): gate welcome-hero footnotes on instance.overview flag

Bring the original Overview gating contract forward to the new
footnotes block: any non-empty `instance.overview` /
AGNES_INSTANCE_OVERVIEW value enables the footnotes, an empty
value hides them. The raw yaml HTML body is no longer rendered
(the static product framing replaces it) — operators relying on
custom Overview HTML should migrate that content to
instance.custom_scripts or admin-edited news.

Preserves the explanatory comments from the original Overview
section (operator-owned, opt-in, no dismiss button) so future
readers understand why the block is gated.

Splits the test into two halves matching the original gating
pattern: footnotes appear when the flag is set, hidden when
unset. Uses "Get the most out of it" as the marker (unique to
the footnotes copy) since "What leaves your machine" still
appears in the untouched session-privacy annotation lower on
the page.
This commit is contained in:
David Rybar 2026-05-22 11:35:40 +02:00
parent 61262e2bbb
commit 2db1dceca1
3 changed files with 73 additions and 15 deletions

View file

@ -47,9 +47,13 @@ CalVer image tags (`stable-YYYY.MM.N`, `dev-YYYY.MM.N`) are produced for every C
stays local, `/agnes-private` toggles per-session) and the
workspace-layout convention (*"Get the most out of it"* — work
under `~/<workspace_dir>/Projects/`, anything outside the
workspace root is invisible to the platform). Renders for both
onboarded and not-onboarded users so the operating model is
visible on every visit.
workspace root is invisible to the platform). Gated on the same
`instance.overview` / `AGNES_INSTANCE_OVERVIEW` flag that used
to drive the standalone Overview section — any non-empty value
acts as the feature flag — so the OSS keeps a vendor-neutral
default (empty yaml → footnotes absent) while operators who
flip the flag get a consistent message across instances.
Renders for both onboarded and not-onboarded users.
- Welcome hero's *"AI Chief of Staff"* lede gains a trailing
sentence ("*You run all your projects inside and it learns
from it.*") so the workspace-folder framing lands before the
@ -259,11 +263,13 @@ CalVer image tags (`stable-YYYY.MM.N`, `dev-YYYY.MM.N`) are produced for every C
`instance.overview` / `AGNES_INSTANCE_OVERVIEW` HTML body between
the first-session walkthrough and the surfaces grid). The
privacy-posture / workspace-layout copy it carried now ships
inline in the welcome hero footnotes, so a separate operator
surface for the same content is no longer needed. The
`get_instance_overview()` helper and yaml field remain (harmless
if set; just not rendered) so existing instances that override
it don't trip on a removed config key.
inline in the welcome hero footnotes (see *Changed* above). The
`get_instance_overview()` helper and yaml field still drive the
feature flag for the new footnotes block, but the raw HTML body
the operator stored there is no longer rendered (the static
product framing replaces it) — operators who relied on injecting
custom Overview HTML should migrate that content to
`instance.custom_scripts` or admin-edited news.
### Removed

View file

@ -2289,6 +2289,25 @@
<p>Shared analyst knowledge and prior solutions, fed back into Claude's context on demand.</p>
</div>
</div>
{# Welcome-hero footnotes — operator-owned, opt-in. Gated on
the same `instance.overview` yaml field
(`AGNES_INSTANCE_OVERVIEW` env override) that used to
drive the standalone Overview section: any non-empty
value acts as the feature flag. The body itself is no
longer the operator's raw HTML — it's the canonical
product framing (privacy posture + workspace convention)
baked into the template, so the OSS keeps a
vendor-neutral default (empty yaml → footnotes absent)
while operators who flip the flag get a consistent
message across instances. #}
{# Footnotes are operator-owned reference content, not
per-user chrome — no dismiss button on purpose. A
one-time per-device hide would leave returning users
unable to re-read the privacy posture / workspace
convention without clearing localStorage. The whole
block is opt-in at the operator level (empty yaml →
block absent), which is the right axis of control. #}
{% if config.INSTANCE_OVERVIEW %}
<div class="home-hero-footnotes">
<p>
<strong>What leaves your machine.</strong> Session telemetry &mdash; prompts, tool calls,
@ -2306,6 +2325,7 @@
Anything outside <code>~/{{ workspace_dir }}/</code> is invisible to the platform.
</p>
</div>
{% endif %}
</section>
{# Homepage status frame — five counters with 24h/7d toggle.

View file

@ -359,13 +359,17 @@ def test_setup_section_renders_for_not_onboarded(fresh_db):
assert '<div class="setup-section-header"' not in body2
def test_overview_section_never_renders(fresh_db, monkeypatch):
"""The operator-owned Overview `<section>` was removed from
`/home` its privacy / workspace-layout copy now ships inline
in the welcome hero footnotes. The `get_instance_overview()`
helper and `instance.overview` yaml field still exist (to avoid
breaking instances that override them), but the rendered
section MUST NOT appear regardless of the env value."""
def test_overview_section_replaced_by_welcome_footnotes(fresh_db, monkeypatch):
"""The standalone operator-owned Overview `<section>` was removed
from `/home`. Its privacy / workspace-layout copy now ships as
static product framing inside the welcome hero footnotes
(`.home-hero-footnotes`). The `instance.overview` yaml field
(`AGNES_INSTANCE_OVERVIEW`) keeps its gating role any
non-empty value acts as the feature flag but its raw HTML
body is no longer rendered (the static copy replaces it). When
set: the standalone section MUST stay absent and the
footnotes block MUST appear, but the raw yaml HTML body MUST
NOT leak into the page."""
monkeypatch.setenv("AGNES_INSTANCE_OVERVIEW", "<p>OVERVIEW_TEST_MARKER</p>")
from src.db import get_system_db, close_system_db
@ -378,3 +382,31 @@ def test_overview_section_never_renders(fresh_db, monkeypatch):
body = _client().get("/home", cookies={"access_token": sess}).text
assert '<section class="home-overview">' not in body
assert "OVERVIEW_TEST_MARKER" not in body
assert '<div class="home-hero-footnotes">' in body
# "Get the most out of it" is unique to the footnotes block — the
# original "What leaves your machine" copy still exists in the
# session-privacy annotation lower on the page (untouched), so we
# can't use it as a footnotes marker.
assert "Get the most out of it" in body
def test_welcome_footnotes_hidden_when_overview_unset(fresh_db, monkeypatch):
"""Default empty `instance.overview` (no env override) hides the
welcome-hero footnotes entirely so the OSS ships without the
central-catalog privacy framing baked into the welcome card."""
monkeypatch.delenv("AGNES_INSTANCE_OVERVIEW", raising=False)
from src.db import get_system_db, close_system_db
conn = get_system_db()
try:
_, sess = _make_user_and_session(conn)
finally:
conn.close()
close_system_db()
body = _client().get("/home", cookies={"access_token": sess}).text
assert '<div class="home-hero-footnotes">' not in body
# "Get the most out of it" is the unique footnotes marker — the
# original "What leaves your machine" copy in the session-privacy
# annotation lower on the page always renders, so checking that
# would be a false-positive.
assert "Get the most out of it" not in body