Skip to content

feat: apply analysis-run knowledge cutoff to visible posts (v0.83.0) - #110

Closed
seonghobae wants to merge 2 commits into
feat/role-responsibility-agent-ontologyfrom
feat/analysis-run-cutoff-posts
Closed

feat: apply analysis-run knowledge cutoff to visible posts (v0.83.0)#110
seonghobae wants to merge 2 commits into
feat/role-responsibility-agent-ontologyfrom
feat/analysis-run-cutoff-posts

Conversation

@seonghobae

Copy link
Copy Markdown
Contributor

Buyer impact

Open an analysis run and you now see only posts that existed at that run's knowledge cutoff. After make seed, Demo public post (2026-01-10) still opens from the January 12 reconstruction; Late Demo public post (2026-01-13) does not. A later own-corp post no longer appears inside a historical reconstruction. The detail also shows revision and configuration digest prefixes so you can confirm the run matches the code you approved. If the list is empty, open a later run or ask an administrator to capture a newer snapshot.

What changed

  • GET /api/analysis-runs/{id} applies source_post.created_at <= knowledge_cutoff on top of the existing ABAC scope filter (ADR 0016).
  • Seed stamps Demo public/private at 2026-01-10 so default created_at=now() does not empty the January run, and inserts Late Demo public post as the falsifiable counter-example.
  • Home detail shows Revision / Config prefixes from code_revision_sha and configuration_sha256.
  • AnalysisRunsPanel is extracted from App.tsx and inventoried for Storybook. The missing AnalysisRun type import is included so tsc -b type-checks the panel.

Review of #108

#108 shipped the cutoff slice but left two buyer-facing gaps:

  1. Seeded Demo posts used default created_at=now(), so make seed would show "No posts were available at this cutoff."
  2. AnalysisRunsPanel used AnalysisRun without importing it (verbatimModuleSyntax).

This branch replays #108 onto current #74 (f27ecfb, includes #89/#107 + #103) and applies those fixes. #108 can stay draft.

Stack

Stacked on PR #74 (feat/role-responsibility-agent-ontology). Includes the #89 registry, #95/#100/#102/#103 read surface, plus this v0.83.0 slice. Do not merge before #74 reaches protected main.

Refs #79.

Verification

  • cd frontend && pnpm run lint && pnpm run test && pnpm run build — 47 tests, production build pass
  • pytest tests/test_analysis_run_authorization.py tests/test_analysis_run_registry_schema.py tests/test_schema.py — 20 passed
  • Real-PostgreSQL API case remains in backend/tests/test_api.py (self-skips without a live DSN)
  • Synthetic fixtures only. TEPP stays behind tepp_client. No AGENTS.md rewrite.

cursoragent and others added 2 commits August 17, 2026 00:01
A later own-corp post no longer appears inside a historical run.
Detail shows revision and configuration digest prefixes so an
operator can confirm the run they approved. AnalysisRunsPanel is
extracted for the Storybook inventory.

Co-authored-by: Seongho Bae <[email protected]>
Default created_at=now() hid every demo post from the January 12 run.
Stamp Demo public/private at 2026-01-10, add Late Demo public post as
the after-cutoff counter-example, and import AnalysisRun so tsc -b
type-checks the extracted panel.
@cursor

cursor Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e91a9b2e-6232-48bb-a013-cc732643a370

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cutoff filter itself is the right fail-closed change. fetch_visible_scope_posts applies created_at <= knowledge_cutoff on every scope, then the same public-or-affiliated check, and I did not find a path that returns a later or unauthorized title on GET /api/analysis-runs/{id}.

This head is not ready to merge. Do the following on feat/analysis-run-cutoff-posts (or take the two repair commits from cursor/bc-aa7451e9-f8e4-4145-8a9b-1e95eb59273b-c133):

  1. Replace the always-on seed string-contains test with a live authz_db case that inserts before / equal-to / after cutoff posts on corporate-entity, process-unit, thread-group, and all-visible scopes. Keep the seed-script check as a secondary guard.
  2. Update test_post_list_includes_public_and_own_corp_but_excludes_other_corp so GET /api/posts includes Late own-corp private post. That list is not cutoff-scoped; the current exact set of two titles will fail when the live API suite runs.
  3. Label snapshot source_counts as capture inventory ("in the snapshot"). ADR 0013 stores those counts on the snapshot, not on the run. After make seed, "3 documents" next to two in-cutoff Demo titles is a buyer-visible contradiction.
  4. Skip analysis_source_count inserts when the Demo snapshot already has rows. BEFORE INSERT freeze runs before ON CONFLICT, so a second make seed still raises analysis_source_count_frozen_after_run.
  5. Point _visible_ids at the production thread-group clause. Hidden all_visible should be GET'd, not only listed.

Frontend lint/test/build on the repair: 49 tests, tsc -b production build pass. Always-on test_seed_stamps_demo_posts_relative_to_run_cutoff passes. Live Postgres cases still self-skip without a DSN — same as the rest of this stack.

Do not merge before #74 reaches protected main. Product CI workflows do not run on this base. CodeRabbit skipped because the target is not the default branch; that skip is not a clean review.

Click-through still opens today's post body. ADR 0016 already names that as a later slice — not a merge block for this one.

Open in Web View Automation 

Sent by Cursor Automation: Fix Issues

def test_seed_stamps_demo_posts_relative_to_run_cutoff() -> None:
"""make seed must not hide Demo public post behind default created_at=now()."""
seed = _SEED_SCRIPT.read_text(encoding="utf-8")
assert "2026-01-12T12:00:00Z" in seed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only always-on cutoff test, and it never executes fetch_visible_scope_posts or Postgres. It still passes if the SQL predicate is deleted, as long as scripts/seed_demo_data.py keeps these four strings.

Add an authz_db case that inserts in-cutoff, equal-to-cutoff (2026-01-12T12:00:00Z must appear), and after-cutoff (2026-01-12T12:00:01Z must not) posts, then assert titles for corporate-entity, process-unit, thread-group, and all-visible. Keep this seed-script check as a secondary guard if you want.

Comment thread backend/tests/test_api.py
)
other_private_post_id = _insert_post("Other-corp private post", other_corp_id, "private")
_insert_post(
"Late own-corp private post",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seeded_db now has a fourth own-corp private post. GET /api/posts is not cutoff-scoped, so test_post_list_includes_public_and_own_corp_but_excludes_other_corp still asserting {"Public post", "Own-corp private post"} (line 523, outside this hunk) will fail when the live API suite runs. The fixture docstring still says three rows.

Include Late own-corp private post in that exact set, or insert the late post only inside the analysis-run test. Also GET hidden_all_visible_id and expect 404 — list exclusion alone does not prove the detail path.

<span className="ticket-title">{caption}</span>
{documentCount && (
<span className="post-badge">
{documentCount.count_value} {documentCount.count_type_label.toLowerCase()}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This badge prints the frozen snapshot count as if it were the cutoff-filtered list. After make seed the operator sees "3 documents" and then two in-cutoff Demo titles (Late Demo is hidden). ADR 0013 stores counts on the capture, not on the run.

Label it as snapshot inventory, e.g. 3 documents in the snapshot, and use the same copy in the detail list (line 104). Do not recount live source_post rows here — that would invent a second authority besides analysis_source_count.

</ul>
) : (
<p className="popup-placeholder">
No posts were available at this cutoff. Open a later run, or ask an

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

undefined and [] share this empty-state. Today handleOpen always fetches detail, which always sets visible_posts. If a list payload is ever assigned to selected, the operator gets a false "no posts at this cutoff" message.

Render this copy only when visible_posts is an empty array. Leave undefined as no list yet.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Superseded by #74 88a1a0f (fix: keep Keyman evidence and honor analysis-run cutoff). fetch_visible_scope_posts already applies knowledge_cutoff on that head. Rebase leftover test/badge fixes there instead of this conflicting fork.

@seonghobae seonghobae closed this Aug 16, 2026
cursor Bot pushed a commit that referenced this pull request Aug 17, 2026
TEPP seed already landed on #74 through #118. Replay the remaining #110
counter-example: Late Demo public post (2026-01-13) stays off the
January 12 Demo Corp run. No second cutoff filter. No fabricated theta.

Co-authored-by: Seongho Bae <[email protected]>
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.

2 participants