Skip to content

feat(config): upstream ContextMod check-shape compat + dashboard post lifecycle#35

Merged
StephenSook merged 3 commits into
mainfrom
fix/samplenone-feedback-2026-06-09
Jun 9, 2026
Merged

feat(config): upstream ContextMod check-shape compat + dashboard post lifecycle#35
StephenSook merged 3 commits into
mainfrom
fix/samplenone-feedback-2026-06-09

Conversation

@StephenSook

Copy link
Copy Markdown
Owner

Summary

Three pieces of senior-dev feedback from SampleOfNone (2026-06-09) on the Observatory dashboard and config compatibility.

Changes

  • Dashboard post lifecycle (fix(menu)): "View recent actions" now reuses the sub's existing Observatory post (stored id + getPostById) instead of creating a new one each click; immediately removes the post from the public feed after creation (mods reach it via the stored permalink, non-mods hit the server-gated "Moderators only" screen); sets a splash cover. On a remove failure the mod is told the post needs manual removal.
  • Upstream ContextMod config compat (feat(config)): real ContextMod check configs now validate. A pre-validate normalization maps condition to combinator (default AND) and lifts check-level itemIs/authorIs into filters. enable, description, kind are accepted natively and honored: enable: false skips the check; kind scopes it to submissions or comments. An unrecognized condition value is left for the validator to reject with a clear error rather than silently coerced to AND.

Verification

  • 937 tests green (+10 new). tsc + lint clean.
  • Two adversarial review passes; one real silent-coercion issue found and fixed.
  • Dashboard data access audited end-to-end: every /api/* data and action endpoint enforces moderator status server-side and fails closed.

Notes

  • Splash uses the deprecated-in-0.12.24-but-functional submitCustomPost splash option; migrate to an inline HTML splash entrypoint with the 0.13.x framework bump.

🤖 Generated with Claude Code

StephenSook and others added 3 commits June 9, 2026 15:29
Addresses SampleOfNone feedback (2026-06-09) on the dashboard custom-post
lifecycle. The "View recent actions" menu previously created a brand-new
Observatory post on every click, left it sitting in the public feed, and
set no splash cover.

- Reuse: store the post id per sub (K.dashboardPostId) and reopen the
  existing post via getPostById; only create a new one when none exists or
  the stored post is gone.
- Remove: immediately reddit.remove() the post after creation so the
  dashboard never sits in the public feed. Mods reach it via the stored
  permalink; non-mods hit the server-gated "Moderators only" screen.
  Best-effort (a remove failure still returns the mod a working link).
- Splash: set a splash cover on the post. NB SubmitCustomPostSplashOptions
  is deprecated in @devvit 0.12.24 (migrate to an inline HTML splash
  entrypoint with the 0.13.x bump) but is the only splash API in-version.

Tests: +4 cases (create-removes-and-stores, reuse-existing, recreate-when-
gone, remove-failure-still-returns-link). Full suite 927 green; tsc + lint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dition/itemIs)

SampleOfNone (2026-06-09) hit validation errors pasting a real ContextMod
config: our MVP-trim Check schema rejected upstream-only fields (enable,
description, kind, itemIs) and required `combinator`, which upstream calls
`condition`.

- Normalize upstream shape pre-validate (config.ts): map `condition` (AND/OR)
  to `combinator`, default a missing combinator to AND, and lift check-level
  `itemIs`/`authorIs` into our nested `filters`. Genuinely unsupported fields
  are still rejected with a clear error rather than silently dropped (a mod
  must know when a field is ignored).
- Schema: `combinator` is now optional; `enable`, `description`, `kind` are
  accepted natively.
- Honor the semantics, not just accept (runCheck.ts): a check with enable:false
  is skipped entirely; `kind` scopes a check to submissions or comments only.
- Types: Check gains enable?/description?/kind?.

Tests: +8 (upstream-shape parse + normalization, enable-skips, kind-targeting);
re-pointed the "missing required field" test at `rules` since combinator is now
optional. Full suite 935 green; tsc + lint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adversarial-review follow-up. The post-create reddit.remove() is best-effort;
on failure the post stays in the public feed but the mod (who cannot read
server logs) was told 'Observatory dashboard ready' with no caveat. Now the
toast says the post could not be hidden and to remove it manually. Also pins
the reuse-path no-rewrite invariant in tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@StephenSook StephenSook requested a review from vinhbin as a code owner June 9, 2026 19:53
@StephenSook StephenSook merged commit 2b6fe34 into main Jun 9, 2026
12 checks passed
@StephenSook StephenSook deleted the fix/samplenone-feedback-2026-06-09 branch June 9, 2026 19:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant