Skip to content

feat(signals): support editable scout display names - #96996

Merged
trunk-io[bot] merged 20 commits into
masterfrom
posthog/safe-scout-renames
Sep 9, 2026
Merged

trunk-io[bot] merged 20 commits into
masterfrom
posthog/safe-scout-renames

Conversation

@dmarticus

@dmarticus dmarticus commented Sep 8, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Why: People need to correct a scout name in Replay Vision without changing the identifiers used by its history and delivery. Refs #94896.

Changes

The existing settings update now saves an optional display name. Scout lists and settings use that label; the internal skill name, history, and delivery filters stay unchanged. Existing scouts keep their current names until edited.

Generated API and MCP types include the new field. There is no separate rename endpoint or MCP tool.

Editable scout display name

How did you test this code?

Backend and frontend tests cover label updates during active runs, unchanged history and delivery, input validation, and default labels. Full frontend and MCP type checks, schema snapshot tests, and migration checks pass.

Browser checks confirm that changing only the name enables Save changes. Custom and default labels were checked at desktop widths.

🤖 Agent context

Human-directed, with Codex. Skills: writing-pr-descriptions and writing-user-facing-copy. This replaces the earlier internal rename implementation with display-only edits.

Source: Slack thread. Coding conventions.


Created with PostHog Desktop

@dmarticus dmarticus self-assigned this Sep 8, 2026
@trunk-io

trunk-io Bot commented Sep 8, 2026 •

Copy link
Copy Markdown

😎 Merged successfully - details.

@github-actions

github-actions Bot commented Sep 8, 2026 •

Copy link
Copy Markdown
Contributor

🤖 CI report

⚠️ Trunk lane — backend Python lane

This PR is assigned to the backend Python lane. It runs backend Python tests and may merge in parallel with PRs in other lanes.

⚠️ Complexity (TypeScript) — 16 functions above the limit (max 30)

Cyclomatic complexity above the limit in changed typescript files (10 for production files, 15 for test files). Warn only: worth simplifying when you next touch these functions.

Function Location Complexity Limit
ScannerScoutFormModal products/replay_vision/frontend/replay_scanners/components/ScannerScoutFormModal.tsx:90 30 10
ScannerScoutRow products/replay_vision/frontend/replay_scanners/components/ScannerScoutRow.tsx:27 27 10
ScoutConfigForm products/signals/frontend/inbox/components/config/scouts/ScoutConfigControls.tsx:85 24 10
parseCronField products/signals/frontend/inbox/utils/scoutRunsWindow.ts:617 18 10
saveScoutSettings products/replay_vision/frontend/replay_scanners/scannerScoutLogic.ts:852 16 10
applyFromUrl products/signals/frontend/inbox/logics/scoutFleetLogic.ts:1588 16 10
scoutSubtitle products/signals/frontend/inbox/utils/scoutGroups.ts:117 16 10
computeScoutRollups products/signals/frontend/inbox/utils/scoutRunsWindow.ts:352 16 10
updateScoutConfig products/signals/frontend/inbox/logics/scoutFleetLogic.ts:1340 15 10
reconcileDelivery products/replay_vision/frontend/replay_scanners/scannerScoutLogic.ts:654 14 10
createScout products/replay_vision/frontend/replay_scanners/scannerScoutLogic.ts:752 14 10
deleteScout products/signals/frontend/inbox/logics/scoutFleetLogic.ts:1404 14 10
scoutCronScheduleError products/signals/frontend/inbox/utils/scoutRunsWindow.ts:673 13 10
loadScoutRunCosts products/signals/frontend/inbox/logics/scoutFleetLogic.ts:760 12 10
scoutRunOutcomeLabel products/signals/frontend/inbox/utils/scoutRunsWindow.ts:287 12 10
ScoutAttentionBanner products/signals/frontend/inbox/components/config/scouts/ScoutDetailHeader.tsx:170 11 10
✅ Comment density — 0% of added code lines are comments (0 of 138)

This section warns when comments are more than 3% of the code lines a PR adds, and alerts above 6%. Before agent-assisted PRs, the typical share was about 2%. Only full-line comments count. Docstrings, generated files, snapshots, migrations, and workflow files are left out.

Comments that restate the code, record how the change came about, or narrate the next line add noise for the next reader. Keep the comments that explain a reason the code cannot show, and remove the rest. See .agents/skills/writing-code-comments/SKILL.md for the house rules.

This check does not block merging. It updates on every push and clears when the share drops.

✅ Bundle size — 🟢 -102 B (-0.0%)

Uncompressed size of every built .js bundle, compared against the base branch.

Total: 68.64 MiB · 🟢 -102 B (-0.0%)

No file changed by more than 1000 B.

Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report

⚠️ Eager graph — 1 over budget, 1 forbidden import(s)

How much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy import() / React.lazy chunks are not counted.

Root Eager (shipped) Δ vs base Budget
entry (logged-out pages, app bootstrap)
src/index.tsx
1.54 MiB · 22 files no change ███░░░░░░░ 34.1% of 4.51 MiB
🟡 logged-out boot: index + App + bootApp (preloaded by every page, including /login)
src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
10.31 MiB · 2,628 files no change ██████████ 183.3% of 5.63 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
7.68 MiB · 2,679 files no change █████████░ 87.5% of 8.77 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟡 node_modules/monaco-editor/ ships eagerly from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts:

src/scenes/bootApp.ts
  -> ../products/logs/frontend/agentTools/registerLogsToolRenderers.tsx
  -> ../products/posthog_ai/frontend/api/tools.ts
  -> ../products/posthog_ai/frontend/components/tool/DiffEvidenceCard.tsx
  -> ../products/posthog_ai/frontend/components/tool/EditDiffRenderer.tsx
  -> src/lib/components/MonacoDiffEditor.tsx
  -> ../node_modules/.pnpm/monaco-editor@0.55.1/node_modules/monaco-editor/esm/vs/editor/editor.main.js

🟢 src/layout/navigation-3000/navigationLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/scenes/dashboard/dashboardLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx

Largest files eagerly shipped from src/index.tsx
Size File
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
24.6 KiB ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js
6.3 KiB ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js
4.5 KiB ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js
3.9 KiB ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js
1.4 KiB ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js
1.3 KiB src/index.tsx
1.3 KiB src/RootErrorBoundary.tsx
912 B ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js
854 B src/scenes/ChunkLoadErrorBoundary.tsx
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
Size File
283.2 KiB ../node_modules/.pnpm/posthog-js@1.428.8_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
267.7 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
261.0 KiB src/taxonomy/core-filter-definitions-by-group.json
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
103.7 KiB src/lib/api.ts
97.9 KiB ../node_modules/.pnpm/monaco-editor@0.55.1/node_modules/monaco-editor/esm/vs/editor/common/config/editorOptions.js
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
90.6 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js
79.4 KiB src/products.tsx
73.1 KiB ../node_modules/.pnpm/monaco-editor@0.55.1/node_modules/monaco-editor/esm/external/monaco-lsp-client/out/index.js
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
283.2 KiB ../node_modules/.pnpm/posthog-js@1.428.8_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
267.7 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
261.0 KiB src/taxonomy/core-filter-definitions-by-group.json
153.8 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
103.7 KiB src/lib/api.ts
95.9 KiB ../packages/quill/packages/quill/dist/index.js
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
90.6 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js
79.4 KiB src/products.tsx

Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479

✅ Toolbar bundle — eager 2.30 MiB within budget

What the toolbar ships to customer pages, measured from the esbuild output (minified, post-tree-shake). The eager set is the entry plus everything statically imported from it — fetched before any feature runs; deferred chunks load lazily. The eager guardrail is 5.72 MiB. Each output file must also stay below 10 MB, where CloudFront stops compressing it. The module boundary is enforced separately by check-toolbar-graph.

Metric Size Δ vs base Budget
Eager (shipped)
entry + static imports
2.30 MiB · 18 files no change ████░░░░░░ 40.1% of 5.72 MiB
Deferred (lazy) 2.12 MiB · 45 files no change n/a — loads on demand
Loader dist/toolbar.js 1.1 KiB no change █░░░░░░░░░ 5.8% of 19.5 KiB
Largest eagerly-shipped chunks
Size File
762.2 KiB dist/toolbar/toolbar-app-TO3UN45E.css
610.4 KiB dist/toolbar/chunk-chunk-QRZZDSCI.js
484.8 KiB dist/toolbar/chunk-chunk-L7IJGZND.js
136.6 KiB dist/toolbar/chunk-chunk-A6ULPA3H.js
131.8 KiB dist/toolbar/chunk-chunk-FDH2IBXT.js
72.2 KiB dist/toolbar/toolbar-app-QXLOBCL6.js
69.0 KiB dist/toolbar/chunk-chunk-TSAL54PB.js
35.6 KiB dist/toolbar/chunk-chunk-OCGZ4NGO.js
21.0 KiB dist/toolbar/chunk-chunk-OSKWS54H.js
6.8 KiB dist/toolbar/chunk-chunk-DV7IWQNF.js

Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile

✅ Dist folder size — 🔺 +1.3 KiB (+0.0%)

Total size of the built frontend/dist folder (all assets), compared against the base branch.

Total: 1468.75 MiB · 🔺 +1.3 KiB (+0.0%)

ℹ️ MCP UI apps size — 33 app(s), 17701.0 KB JS

Built size of each MCP UI app (main.js + styles.css).

App JS CSS
debug 601.1 KB 197.0 KB
action 459.3 KB 197.0 KB
action-list 565.9 KB 197.0 KB
cohort 458.3 KB 197.0 KB
cohort-list 564.9 KB 197.0 KB
email-template 458.1 KB 197.0 KB
error-details 473.9 KB 197.0 KB
error-issue 458.9 KB 197.0 KB
error-issue-list 565.8 KB 197.0 KB
experiment 563.0 KB 197.0 KB
experiment-list 566.7 KB 197.0 KB
experiment-results 568.2 KB 197.0 KB
feature-flag 568.7 KB 197.0 KB
feature-flag-list 572.4 KB 197.0 KB
feature-flag-testing 462.5 KB 197.0 KB
inline-scan 458.7 KB 197.0 KB
insight-actors 564.1 KB 197.0 KB
invite-email-preview 457.5 KB 197.0 KB
llm-costs 561.0 KB 197.0 KB
session-recording 460.0 KB 197.0 KB
survey 459.8 KB 197.0 KB
survey-global-stats 563.7 KB 197.0 KB
survey-list 566.6 KB 197.0 KB
survey-stats 563.7 KB 197.0 KB
trace-span 458.6 KB 197.0 KB
trace-span-list 565.8 KB 197.0 KB
vision-observation-list 565.0 KB 197.0 KB
workflow 458.6 KB 197.0 KB
workflow-list 565.2 KB 197.0 KB
loops-review 462.9 KB 197.0 KB
query-results 757.8 KB 197.0 KB
render-ui 841.1 KB 197.0 KB
visual-review-snapshots 463.1 KB 197.0 KB
✅ Playwright — all passed

All tests passed.

✅ Backend coverage — all changed backend lines covered

🧪 Backend test coverage

Patch coverage — changed backend lines (products + core): ████████████████████ 100.0% (34 / 34)

All changed backend lines are covered ✅

Per-product line coverage (touched products)
Product Coverage Lines
platform_features ██░░░░░░░░░░░░░░░░░░ 12.1% 7 / 58
warehouse_sources_queue ██████░░░░░░░░░░░░░░ 29.1% 92 / 316
data_tools ████████████░░░░░░░░ 62.1% 90 / 145
demo ████████████░░░░░░░░ 62.1% 1,658 / 2,671
ai_gateway ███████████████░░░░░ 75.0% 9 / 12
batch_exports ████████████████░░░░ 80.0% 19,493 / 24,368
apm █████████████████░░░ 83.3% 1,234 / 1,481
cdp █████████████████░░░ 85.4% 4,367 / 5,112
signals █████████████████░░░ 85.6% 36,860 / 43,043
product_tours ██████████████████░░ 88.0% 1,312 / 1,491
data_warehouse ██████████████████░░ 88.9% 12,824 / 14,424
notebooks ██████████████████░░ 89.2% 11,784 / 13,210
business_knowledge ██████████████████░░ 89.2% 4,469 / 5,008
cohorts ██████████████████░░ 89.3% 7,565 / 8,468
dashboards ██████████████████░░ 89.6% 6,867 / 7,661
engineering_analytics ██████████████████░░ 90.1% 8,391 / 9,310
tasks ██████████████████░░ 90.4% 66,535 / 73,631
data_modeling ██████████████████░░ 90.5% 9,474 / 10,468
streamlit_apps ██████████████████░░ 90.7% 2,619 / 2,889
managed_warehouse ██████████████████░░ 90.7% 9,417 / 10,378
exports ██████████████████░░ 90.9% 9,200 / 10,126
links ██████████████████░░ 91.0% 192 / 211
mcp_analytics ██████████████████░░ 91.2% 4,411 / 4,837
conversations ██████████████████░░ 91.3% 22,057 / 24,163
alerts ██████████████████░░ 91.4% 5,382 / 5,888
canvas ██████████████████░░ 91.6% 5,538 / 6,047
visual_review ██████████████████░░ 91.7% 7,583 / 8,266
error_tracking ██████████████████░░ 92.0% 13,495 / 14,669
notifications ██████████████████░░ 92.5% 1,120 / 1,211
early_access_features ███████████████████░ 92.6% 1,341 / 1,448
managed_migrations ███████████████████░ 92.7% 1,576 / 1,700
slack_app ███████████████████░ 92.8% 12,770 / 13,762
surveys ███████████████████░ 93.1% 6,199 / 6,659
mcp_registry ███████████████████░ 93.2% 1,471 / 1,578
stamphog ███████████████████░ 93.4% 6,543 / 7,009
web_analytics ███████████████████░ 93.4% 19,502 / 20,885
mcp_store ███████████████████░ 93.5% 8,198 / 8,772
context_layer ███████████████████░ 93.5% 2,683 / 2,870
reminders ███████████████████░ 93.5% 477 / 510
posthog_ai ███████████████████░ 93.6% 1,402 / 1,498
ai_observability ███████████████████░ 93.8% 18,265 / 19,473
wizard ███████████████████░ 93.8% 5,371 / 5,724
approvals ███████████████████░ 93.9% 3,570 / 3,803
billing_alerts ███████████████████░ 94.1% 2,079 / 2,210
marketing_analytics ███████████████████░ 94.2% 17,511 / 18,583
endpoints ███████████████████░ 94.2% 9,072 / 9,627
review_hog ███████████████████░ 94.3% 10,214 / 10,826
tracing ███████████████████░ 94.5% 2,726 / 2,885
experiments ███████████████████░ 94.5% 30,133 / 31,873
workflows ███████████████████░ 94.8% 12,009 / 12,666
growth ███████████████████░ 94.9% 8,434 / 8,889
customer_analytics ███████████████████░ 95.0% 19,839 / 20,891
legal_documents ███████████████████░ 95.2% 2,339 / 2,458
annotations ███████████████████░ 95.3% 804 / 844
actions ███████████████████░ 95.4% 749 / 785
replay_vision ███████████████████░ 95.6% 23,251 / 24,333
skills ███████████████████░ 95.6% 5,800 / 6,067
autoresearch ███████████████████░ 95.7% 1,432 / 1,496
feature_flags ███████████████████░ 95.8% 20,533 / 21,440
product_analytics ███████████████████░ 95.8% 28,420 / 29,671
access_control ███████████████████░ 95.8% 6,371 / 6,651
messaging ███████████████████░ 95.9% 3,680 / 3,839
logs ███████████████████░ 96.0% 14,051 / 14,633
revenue_analytics ███████████████████░ 96.3% 1,841 / 1,911
user_interviews ███████████████████░ 96.5% 2,651 / 2,747
warehouse_sources ███████████████████░ 97.2% 409,980 / 421,856
data_quality ████████████████████ 97.6% 4,229 / 4,335
analytics_platform ████████████████████ 98.2% 2,381 / 2,425
metrics ████████████████████ 98.2% 3,586 / 3,650
pulse ████████████████████ 98.4% 2,028 / 2,060
data_catalog ████████████████████ 98.5% 3,404 / 3,457
live_debugger ████████████████████ 99.2% 621 / 626
field_notes ████████████████████ 99.4% 167 / 168

Report-only. Patch coverage = changed backend lines covered vs origin/master. Sorted lowest first.
Known gaps: lines covered only by Temporal tests show as uncovered; core line numbers may drift if master changed the same file.

⚠️ MCP snapshots — 1 updated (0 modified, 1 added, 0 deleted)

Snapshots: MCP unit test snapshots updated

Changes: 1 snapshots (0 modified, 1 added, 0 deleted)

What this means:

  • Snapshots have been automatically updated to match current output

Next steps:

  • Review the changes to ensure they're intentional
  • If unexpected, investigate what caused the output to change

Review snapshot changes →

⚠️ Django migration SQL — 1 new migration to review

We've detected new migrations on this PR. Review the SQL output for each migration:

products/signals/backend/migrations/0121_signalscoutconfig_display_name.py

/opt/hostedtoolcache/Python/3.13.13/x64/lib/python3.13/site-packages/infi/clickhouse_orm/__init__.py:1: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.
  __import__("pkg_resources").declare_namespace(__name__)
System check identified some issues:

WARNINGS:
?: (axes.W001) You are using the django-axes cache handler for login attempt tracking. Your cache configuration is however invalid and will not work correctly with django-axes. This can leave security holes in your login systems as attempts are not tracked correctly. Reconfigure settings.AXES_CACHE and settings.CACHES per django-axes configuration documentation.
?: (staticfiles.W004) The directory '/home/runner/work/posthog/posthog/frontend/dist' in the STATICFILES_DIRS setting does not exist.
BEGIN;
--
-- Add field display_name to signalscoutconfig
--
ALTER TABLE "signals_signalscoutconfig" ADD COLUMN "display_name" varchar(200) DEFAULT '' NOT NULL;
COMMIT;

Last updated: 2026-09-09 20:56 UTC (6dd75f6)

✅ Django migration risk — migration analysis complete

We've analyzed your migrations for potential risks.

Summary: 1 Safe | 0 Needs Review | 0 Blocked

✅ Safe

Brief or no lock, backwards compatible

signals.0121_signalscoutconfig_display_name
  └─ #1 ✅ AddField
     Adding NOT NULL field with constant default (safe in PG11+)
     model: signalscoutconfig, field: display_name

Last updated: 2026-09-09 20:56 UTC (6dd75f6)

ℹ️ Docs preview — preview build triggered

Docs from this PR will be published at posthog.com.

Project Preview Updated (UTC)
posthog.com Open preview Sep 9, 2026, 6:55 PM

The preview should be ready in about 10 minutes. Open the preview at /handbook/engineering/.

@posthog

posthog Bot commented Sep 8, 2026 •

Copy link
Copy Markdown
Contributor

👋 Visual changes detected for this PR.

Review and approve in PostHog Visual Review

If these changes are unexpected, they may be caused by a flaky test or a broken snapshot on master. Don't approve — rerun the job or wait for a fix.

@trunk-io

trunk-io Bot commented Sep 8, 2026 •

Copy link
Copy Markdown

Static Badge   Static Badge   Static Badge

View Full Report ↗︎ ⋅ Docs

@github-actions

github-actions Bot commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

🦔 Hogbox preview · ✅ ready

▶ Open the preview

🔑 Login test@posthog.com / 12345678 (demo data)
🧩 Running this PR's backend and frontend, on the PostHog :master base
🔗 Link stable across rebuilds — a re-push swaps the box underneath, the URL stays
🔒 Access tailnet only (PostHog VPN)
🛠️ Admin inspect & debug state in hogland
💤 Idle sleeps after ~30 min idle (snapshot to S3, zero node cost) and wakes on your next visit in ~30s, behind a brief "waking up" screen

commit 6dd75f6 · box box-bd92f6672644 · ready in 903s (push → usable) · build log · rebuilds on every push, torn down on close

@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested review from a team, TueHaulund, arnohillen, fasyy612 and ksvat and removed request for a team September 9, 2026 15:03
@greptile-apps

greptile-apps Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor
Prompt To Fix All With AI
### Issue 1
products/signals/backend/scout_harness/views.py:2525-2526
**Scratchpad history stays behind**

The rename moves runs and notes, but not skill-namespaced scratchpad keys such as `followup:<skill-name>:<entity>`. Future runs and derived-metadata checks search these keys using the new skill name, so the renamed scout loses access to its existing self-validation queue.

### Issue 2
products/signals/backend/scout_harness/views.py:2505
**Run start races rename**

The live-run check is not synchronized with run creation. A run can insert its row under the old skill name after the bulk run update but before the rename commits. The skill and config then use the new name while the active run remains under the old one, causing listings and single-flight checks for the renamed scout to miss it.

### Issue 3
products/replay_vision/frontend/replay_scanners/scannerScoutLogic.ts:869-874
**Failed saves cannot retry**

The rename can commit before a later schedule or webhook request fails. The error leaves the modal open, but `settingsSkillName` still contains the old name. A retry therefore cannot find the renamed config and returns without feedback, leaving the user with partially saved changes and no way to retry without closing and reopening the modal.

### Issue 4
products/signals/backend/scout_harness/views.py:2488-2495
**Concurrent renames return 500**

Checking an absent target with `select_for_update()` does not lock anything. Two concurrent renames can both see the same target name as available, after which one violates the skill or config uniqueness constraint. Because the resulting `IntegrityError` is not translated into the documented conflict response, that request returns a server error instead of a name-conflict error.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "chore(visual): update storybook baseline..." | Re-trigger Greptile

@posthog

posthog Bot commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

🦔 PostHog Review reviewed this pull request

Found 2 must fix, 10 should fix, 6 consider.

Published 18 findings (view the review).

Resolved comments: 7 fixed, 1 already settled, 4 left for you

@veria-ai

veria-ai Bot commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

PR overview

All previously flagged issues have been addressed. No open security concerns remain on this pull request.

Security review

No open security issues remain on this pull request.

Fixed/addressed: 1 · PR risk: 0/10

@posthog

posthog Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

PostHog Review alpha 🦔 If you find any issues helpful - please reply "valid", "invalid", etc., for evaluation purposes 🙏

@posthog posthog 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.

PostHog Review

Found 2 must fix, 10 should fix, 6 consider.

Comment thread products/signals/mcp/tools.yaml Resolved
@posthog posthog Bot removed the reviewhog label Sep 9, 2026
@github-actions
github-actions Bot requested a deployment to preview-pr-96996 September 9, 2026 17:26 In progress
@github-actions
github-actions Bot requested a deployment to preview-pr-96996 September 9, 2026 17:31 In progress
@github-actions
github-actions Bot requested a deployment to preview-pr-96996 September 9, 2026 17:35 In progress
@github-actions
github-actions Bot requested a deployment to preview-pr-96996 September 9, 2026 17:41 In progress
Generated-By: PostHog Desktop
Task-Id: 93fe8b2e-841d-4aa9-bc7d-c0a43648a304
Generated-By: PostHog Desktop
Task-Id: 93fe8b2e-841d-4aa9-bc7d-c0a43648a304
The scout-config-rename MCP tool returned `/inbox/<config id>`. That path
matches the inbox tab route, which reads a non-tab segment as a report id, so
the link resolved to a report lookup instead of the renamed scout.

Use `scouts/{skill_name}` so the returned URL is `/inbox/scouts/<new name>`,
which matches the scout detail route. The rename response already carries the
new name in `skill_name`.

Generated-By: PostHog Desktop
Task-Id: 1cab461b-a413-40b6-9768-3f053c5bb54f
The rename serializer stopped at the generic skill-name contract, whose
reserved set does not cover the names the inbox owns as sub-pages of
`/inbox/scouts/`: scratchpad, findings, and runs. Both scout-minting
serializers already refuse them via `reserved_scout_name_error`.

The gap was reachable for a scout without the `signals-scout-` prefix, a
supported shape created through explicit config registration. With no
registered prefix on either name, the prefix guard in `rename_skill` never
fires, so the rename succeeded and left the scout on a name whose detail
route renders the static inbox page instead of the scout.

Apply the same guard the minting paths use, and say so in the field help
text and the MCP tool description. Regenerated the API and MCP clients.

Generated-By: PostHog Desktop
Task-Id: 1cab461b-a413-40b6-9768-3f053c5bb54f
The settings form seeds its name field from the stored skill name, so a save
re-derives that name to decide whether to rename. That converter reused the
creation converter, which holds back three characters for a collision suffix
it may still need to append. An existing name can already be using them.

A second scout on a descriptively named scanner is 62-64 characters, so the
derived name lost its `-2` and became the first scout's name exactly. Every
save then asked to rename onto a taken name, which the backend refuses, and
the schedule and delivery edits were dropped after the prompt had been
written. When the truncated name happened to be free, the scout was renamed
without anyone asking.

Give the rename converter the whole 64-character cap. The name it converts is
already complete, so it has no suffix left to reserve room for.

Generated-By: PostHog Desktop
Task-Id: 1cab461b-a413-40b6-9768-3f053c5bb54f
The settings form decides its draft has arrived by matching the cached
prompt's skill name against the open scout's. Neither the prompt nor the
delivery cache was cleared when the modal closed, so both stayed in the
logic under the scout's name.

Renaming a scout frees its old name, and a later scout can be created
straight onto it, so that leftover cache reads as the new scout's own. The
form then seeded the previous scout's instructions and webhook URL, and the
next save wrote them onto the new scout and pointed its reports at the old
destination. Deleting a scout does not free a name, so the rename this PR
adds is what makes the collision reachable.

Clear both on close, the way `openReportId` already clears on `closeReport`.
The clearing lives in the reducers block rather than the loaders map, because
two loader values sharing one action key there get a single Success action
that carries only the first value's key, which makes the other reducer return
undefined.

Generated-By: PostHog Desktop
Task-Id: 1cab461b-a413-40b6-9768-3f053c5bb54f
`_create_run_row` locked the config row with `team_id=team.id`, but `_resolve_config` stores it under `team.parent_team_id or team.id`. A child environment id therefore missed the row and raised `DoesNotExist` after the TaskRun already existed, leaving an orphan run.

All three production dispatch paths canonicalize or refuse a child id, so the reachable trigger is the `run_signals_scout --team-id` dogfood command, which passes its id through unchanged.

Adds a child-environment case to the run row tests.

Generated-By: PostHog Desktop
Task-Id: 0e95e3e3-ec3c-4cb1-b991-3fd3167d1a87
The rename moved only the `followup:` scratchpad namespace. A custom scout also keys its self-improvement suggestions on its own name (`improve:<skill-name>:<topic>`), so a rename stranded those entries: the renamed scout writes under the new name, the accumulated evidence and the stashed report id stay at the old key, and no scout can reclaim them because the scratchpad is writable only from a run holding that name.

Both namespaces now move together, under one bounded row selection so the documented per-table history limit still counts memories once. The key-length guard is unchanged in effect: every namespace keeps its literal prefix, so each key grows by the same amount.

`IMPROVE_KEY_PREFIX` joins `FOLLOWUP_KEY_PREFIX` in the prompt module and is interpolated into the section that mandates the key, so the prompt wording and the rename share one definition. The rendered prompt text is unchanged.

Generated-By: PostHog Desktop
Task-Id: 2214beba-5854-4e3a-ae4f-733727d7ebb5
The scanner page reads each scout's runs from a window keyed by skill name. Renaming a scout patched the config locally and reloaded configs, but left the window keyed by the old name, so the scout's runs read as missing until the page remounted. Its card then dropped the "last checked" line and said the first report arrives after the next scheduled run, as if the scout had never run.

The rename branch now reloads the runs window, which is also what the settings modal already does for the other saves it makes.

Generated-By: PostHog Desktop
Task-Id: 2214beba-5854-4e3a-ae4f-733727d7ebb5
A rename pins the notes it will move before it writes, and `leave_note` validated its target and inserted in two unlocked statements. A note write that interleaved with a rename therefore passed validation against the old name, landed after the move, and returned 201 for a note the renamed scout never reads, since note delivery matches the name exactly.

`leave_note` now takes the target config's row lock inside a transaction before it validates, the same lock the rename takes first. A note that gets in first is moved with the rest; one that arrives after is refused, because the old name no longer resolves. Blank and pipeline targets name no config and are unaffected.

Adds a concurrency case that interleaves a note write with a rename.

Generated-By: PostHog Desktop
Task-Id: 2214beba-5854-4e3a-ae4f-733727d7ebb5
The rename prefetched the skill's bundled files before checking where the scout came from. That check reads file contents only for a seeded row it has not yet proved diverged, and a pristine seeded row is rejected right after, so every rename that succeeds loaded a bundle it discarded — inside the transaction, with the config row already locked.

Dropping the prefetch leaves the one branch that needs the files to read them lazily, and matches what the per-run skill loader already does.

Adds a rename case for a seeded scout the team has edited, which is the path that reads the files.

Generated-By: PostHog Desktop
Task-Id: 2214beba-5854-4e3a-ae4f-733727d7ebb5
A dispatch already in flight when a scout is renamed holds no TaskRun yet, so the rename cannot see it and proceeds. The run row guard then refuses the stale dispatch, but the refusal landed in the generic failure path: it booked a failed run and, on the scheduled path, advanced the lane's failure streak toward the auto-pause breaker over a rename nobody has to fix.

The guard now raises a dedicated `ScoutRenamedDuringDispatch`, which the runner reports as a skip like its other stale-dispatch exits. Nothing is lost by reclassifying: the guard fires before the bridge row is written and before the run-started marker, so there is no partial run to finalize and no started event left without a finished one. The two tests that assert the guard's refusal now name the new type.

Generated-By: PostHog Desktop
Task-Id: 2214beba-5854-4e3a-ae4f-733727d7ebb5
Saving scout settings wrote the instructions first and renamed second. The rename is the write the server turns down — a name already taken, a canonical scout, a scout with a run going — so a refused rename left the instructions stored while the modal said the save failed. A name that stays taken made that happen on every attempt, and the scout ran with instructions the user believed had not been saved.

The rename now runs first, and the instructions are written against the name the rename settled on. A save that gets past the rename and then fails behaves as before: the form stays open and a retry patches what is left.

Generated-By: PostHog Desktop
Task-Id: 2214beba-5854-4e3a-ae4f-733727d7ebb5
The rename gate asked whether the row's content still matched what was seeded, and a scout the team had edited in place answered "custom" — so the rename went through and left the canonical name vacant. The next fleet sync finds no row under that name, seeds a fresh canonical scout, and config registration enables it, so the team ends up running the pristine scout beside its own fork: two lanes, overlapping findings, and a slot of the per-team cap it did not ask for.

The gate now asks who owns the name rather than whether the body changed. A fork keeps its seed tag but can never hold a name the fleet ships, so forks stay renameable.

The canonical rejection test now covers all three shapes a seeded row can be in, including the edited one that used to pass the gate, and a new case pins that a fork is still renameable.

Generated-By: PostHog Desktop
Task-Id: 2214beba-5854-4e3a-ae4f-733727d7ebb5
Generated-By: PostHog Desktop
Task-Id: 93fe8b2e-841d-4aa9-bc7d-c0a43648a304
@dmarticus
dmarticus force-pushed the posthog/safe-scout-renames branch from baf6225 to d478fc2 Compare September 9, 2026 20:44
Generated-By: PostHog Desktop
Task-Id: 93fe8b2e-841d-4aa9-bc7d-c0a43648a304
@greptile-apps

greptile-apps Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Reviews (2): Last reviewed commit: "style(signals): format scout name after ..." | Re-trigger Greptile

@dmarticus dmarticus added the stamphog Request AI approval (no full review) label Sep 9, 2026

@stamphog stamphog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Approved.

Adds an optional display_name field (model, migration, serializer, generated API/MCP schemas) and wires it into the UI — additive only, skill_name identity/history/delivery untouched, and covered by backend/frontend tests. Though it touches data-model and public-API surface, an agent security reviewer confirms no open concerns and the review's earlier findings (a since-removed rename endpoint) don't apply to this diff, which shows zero unresolved comments on the current head.

  • Author wrote 0% of the modified lines and has 35 merged PRs in these paths (familiarity MODERATE).
  • 👍 on the PR from greptile-apps[bot].
Gate mechanics and policy version
Gate Result
prerequisites ✓ all clear
deny-list ✓ no deny categories matched
size ✓ 124L, 18F substantive, 278L/30F incl. docs/generated/snapshots — within ceiling
tier ✓ T1-agent / T1d-complex (278L, 30F, two-areas, feat)
stamphog 2.0.0b4 .stamphog/policy.yml @ 6dd75f6 · reviewed head 6dd75f6

@trunk-io
trunk-io Bot merged commit ecead8d into master Sep 9, 2026
364 of 384 checks passed
@trunk-io
trunk-io Bot deleted the posthog/safe-scout-renames branch September 9, 2026 23:51
@deployment-status-posthog

deployment-status-posthog Bot commented Sep 10, 2026 •

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-09-10 00:12 UTC Run
prod-us ✅ Deployed 2026-09-10 00:21 UTC Run
prod-eu ✅ Deployed 2026-09-10 00:27 UTC Run

This branch was successfully deployed

1 active deployment
preview-pr-96996 — 6dd75f6d Deployed Sep 9, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stamphog Request AI approval (no full review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant