Repository navigation
feat(signals): support editable scout display names - #96996
Conversation
|
😎 Merged successfully - details. |
🤖 CI report
|
| 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
⚠️ 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/.
|
👋 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. |
🦔 Hogbox preview · ✅ ready▶ Open the preview
commit |
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 Review reviewed this pull requestFound 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 |
PR overviewAll previously flagged issues have been addressed. No open security concerns remain on this pull request. Security reviewNo open security issues remain on this pull request. Fixed/addressed: 1 · PR risk: 0/10 |
|
PostHog Review alpha 🦔 If you find any issues helpful - please reply "valid", "invalid", etc., for evaluation purposes 🙏 |
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
baf6225 to
d478fc2
Compare
Generated-By: PostHog Desktop Task-Id: 93fe8b2e-841d-4aa9-bc7d-c0a43648a304
|
Reviews (2): Last reviewed commit: "style(signals): format scout name after ..." | Re-trigger Greptile |
There was a problem hiding this comment.
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 |
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.
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