feat: wire task workspace and Strix GPT-5 - #230
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR enforces GitHub Models GPT‑5+ and github.token for Strix, modifies Strix model/auth inputs and CI assertions, refactors dashboard mail routing and mobile-hash behavior, adds a live Tasks queue and AI Hub checkpoint UI, implements reply‑tracking helpers integrated into /api/emails with tests, and updates Next.js config and documentation. ChangesGitHub Models Security Hardening for Strix Workflow
Dashboard Navigation and Responsive Layout Refactoring
Tasks Page and TasksLayout API Integration
AI Hub Execution Checkpoints Navigation and Cards
Backend Reply-Tracking, Emails API, LLM Handling, and Tests
POP3 Tenant Config & POP3 Worker
Documentation and Plans
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
|
|
@coderabbitai review Updated |
|
✏️ Learnings added
✅ Actions performedReview triggered.
|
|
@coderabbitai review Current head is now |
|
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
frontend/tests/e2e/dashboard-branding.spec.ts (1)
135-142: 💤 Low valueConsider adding an explicit existence check before the height assertion.
If
metricLabeldoesn't exist,boundingBox()returnsnull, andmetricLabelBox?.height ?? 0evaluates to0, causing the test to pass silently (since0 < 48). This could mask layout regressions.♻️ Suggested fix to add explicit existence check
if (viewport.width <= 390) { const metricLabel = page .getByRole('article', { name: '받은 메일' }) .first() .getByText('받은 메일', { exact: true }); + await expect(metricLabel).toBeVisible(); const metricLabelBox = await metricLabel.boundingBox(); - expect(metricLabelBox?.height ?? 0).toBeLessThan(48); + expect(metricLabelBox?.height).toBeLessThan(48); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@frontend/tests/e2e/dashboard-branding.spec.ts` around lines 135 - 142, The test should explicitly verify the locator exists before using boundingBox: insert an existence check on the Locator `metricLabel` (e.g., `expect(await metricLabel.count()).toBeGreaterThan(0)` or `expect(await metricLabel.isVisible()).toBeTruthy()`) immediately before calling `metricLabel.boundingBox()`, then proceed to get `metricLabelBox` and assert its height; reference the `metricLabel`, `metricLabelBox`, `getByRole`/`getByText`, and `boundingBox` symbols when making the change.frontend/src/components/AIHubLayout.tsx (1)
57-67: ⚡ Quick winConsider adding smooth scrolling for better UX.
The hash navigation works correctly, but adding
scroll-behavior: smoothto the scrollable container would provide a more polished user experience when clicking checkpoint links.📜 Suggested enhancement
Add a style rule to the main container:
- <main className="flex-1 overflow-y-auto p-8"> + <main className="flex-1 overflow-y-auto p-8 scroll-smooth"> <div className="max-w-5xl mx-auto space-y-8">Or add to your global CSS:
html { scroll-behavior: smooth; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@frontend/src/components/AIHubLayout.tsx` around lines 57 - 67, The nav that renders EXECUTION_SECTIONS should enable smooth scrolling; update the <nav aria-label="AI hub execution checkpoints"> element to add scroll-behavior: smooth (either via inline style e.g. style={{ scrollBehavior: 'smooth' }} or by adding a CSS class and rule .your-class { scroll-behavior: smooth; }) so clicks on the hash links smoothly scroll to their targets; ensure the change targets the same nav rendering the EXECUTION_SECTIONS links.docs/threading-contract.md (1)
43-43: 💤 Low valueSimplify redundant phrase.
The phrase "Duplicate copies" is redundant. Consider using "Duplicates" or "Duplicate entries" instead.
📝 Suggested simplification
-creating a new canonical message. Duplicate copies should attach provenance to +creating a new canonical message. Duplicates should attach provenance toBased on learnings: Static analysis tools like LanguageTool can identify redundant phrases, but as an AI agent I verify these are genuine improvements rather than false positives.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/threading-contract.md` at line 43, Replace the redundant phrase "Duplicate copies" in the sentence fragment "creating a new canonical message. Duplicate copies should attach provenance to" with a simpler term such as "Duplicates" (e.g., "creating a new canonical message. Duplicates should attach provenance to") or "Duplicate entries" to remove redundancy while preserving meaning.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@frontend/src/components/AIHubLayout.tsx`:
- Around line 82-84: The action button in the AIHubLayout component is missing
an explicit type which can cause accidental form submissions; update the JSX
button element (the one with className "shrink-0 rounded-lg border border-border
bg-background px-3 py-1.5 text-xs font-bold hover:bg-secondary" and rendering
{section.action}) to include type="button" so it won't submit a parent form if
nested; ensure you add the attribute to the button in the AIHubLayout component
where section.action is rendered.
In `@frontend/src/components/TasksLayout.tsx`:
- Around line 67-71: The catch block currently collapses all failures into the
generic error state; update it to inspect the error HTTP status (e.g. const
status = (err?.status ?? err?.response?.status) ) and if status === 401 ||
status === 403 call setTicketTasks([]) and setTicketStatus('auth') (so auth
failures render the auth-specific copy), otherwise call setTicketTasks([]) and
setTicketStatus('error') for network/5xx errors; preserve the cancelled check
and apply this change in the same catch handler that references cancelled,
setTicketTasks, and setTicketStatus.
---
Nitpick comments:
In `@docs/threading-contract.md`:
- Line 43: Replace the redundant phrase "Duplicate copies" in the sentence
fragment "creating a new canonical message. Duplicate copies should attach
provenance to" with a simpler term such as "Duplicates" (e.g., "creating a new
canonical message. Duplicates should attach provenance to") or "Duplicate
entries" to remove redundancy while preserving meaning.
In `@frontend/src/components/AIHubLayout.tsx`:
- Around line 57-67: The nav that renders EXECUTION_SECTIONS should enable
smooth scrolling; update the <nav aria-label="AI hub execution checkpoints">
element to add scroll-behavior: smooth (either via inline style e.g. style={{
scrollBehavior: 'smooth' }} or by adding a CSS class and rule .your-class {
scroll-behavior: smooth; }) so clicks on the hash links smoothly scroll to their
targets; ensure the change targets the same nav rendering the EXECUTION_SECTIONS
links.
In `@frontend/tests/e2e/dashboard-branding.spec.ts`:
- Around line 135-142: The test should explicitly verify the locator exists
before using boundingBox: insert an existence check on the Locator `metricLabel`
(e.g., `expect(await metricLabel.count()).toBeGreaterThan(0)` or `expect(await
metricLabel.isVisible()).toBeTruthy()`) immediately before calling
`metricLabel.boundingBox()`, then proceed to get `metricLabelBox` and assert its
height; reference the `metricLabel`, `metricLabelBox`, `getByRole`/`getByText`,
and `boundingBox` symbols when making the change.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 44822243-c480-4a83-87ef-5c82091a1ae3
⛔ Files ignored due to path filters (4)
backend/tests/live/__pycache__/conftest.cpython-310-pytest-9.0.3.pycis excluded by!**/*.pycbackend/tests/live/__pycache__/mail_smoke_test.cpython-310-pytest-9.0.3.pycis excluded by!**/*.pycbackend/tests/live/__pycache__/test_live_api_sequence.cpython-310-pytest-9.0.3.pycis excluded by!**/*.pycfrontend/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (24)
.coderabbit.yaml.github/workflows/strix.yml.gitignoreAGENTS.mdARCHITECTURE.mdREADME.mdbackend/README.mdbackend/api/llm.pybackend/tests/test_llm_api.pydocs/operations/open-source-apm.mddocs/operations/source-of-truth-and-writeback-sovereignty.mddocs/plans/2026-05-17-startup-view-responsive-mobile-menu.mddocs/plans/2026-05-19-branding-menu-task-tracking-gap-closure.mddocs/threading-contract.mdfrontend/next.config.tsfrontend/src/app/tasks/page.test.tsxfrontend/src/components/AIHubLayout.tsxfrontend/src/components/DashboardLayout.test.tsxfrontend/src/components/DashboardLayout.tsxfrontend/src/components/SearchLayout.tsxfrontend/src/components/TasksLayout.tsxfrontend/src/components/WorkspaceHome.tsxfrontend/tests/e2e/dashboard-branding.spec.tsscripts/ci/test_strix_quick_gate.sh
💤 Files with no reviewable changes (1)
- .coderabbit.yaml
|
@coderabbitai review Latest head
Local verification passed: frontend tests, lint, typecheck, Next build, responsive Playwright screenshots/E2E, backend governance tests, npm audit, and Strix quick gate. |
|
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
frontend/src/app/tasks/page.test.tsx (1)
74-104:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAdd signed-session header assertions in the success-path task API test.
Line 97 currently verifies only
Content-Type, so this test can still pass even ifAuthorization: Bearer <naruon_session_token>is missing or a forbidden public identity header leaks.Suggested test patch
it("loads source-linked tickets from the signed task API", async () => { + localStorage.setItem("naruon_session_token", "test-session-token"); const fetchMock = vi.fn(async () => jsonResponse([ { id: "task_public_123", @@ expect(fetchMock).toHaveBeenCalledWith("/api/tasks", expect.objectContaining({ - headers: expect.objectContaining({ "Content-Type": "application/json" }), + headers: expect.objectContaining({ + "Content-Type": "application/json", + Authorization: "Bearer test-session-token", + }), })); + const [, requestInit] = fetchMock.mock.calls[0] as [string, RequestInit | undefined]; + const headers = new Headers((requestInit?.headers as HeadersInit) ?? {}); + expect(headers.get("X-User-Id")).toBeNull(); + expect(headers.get("X-Organization-Id")).toBeNull(); + expect(headers.get("X-Group-Id")).toBeNull(); + expect(headers.get("X-Group-Ids")).toBeNull(); + expect(headers.get("X-User-Role")).toBeNull(); + expect(headers.get("X-Dev-Auth-Token")).toBeNull();As per coding guidelines
**/*.{ts,tsx,js,jsx}: Browser frontend signed-route calls must useAuthorization: Bearerfromnaruon_session_token, must not forward public identity headers, and tests/mocks must exercise the signed-session path.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@frontend/src/app/tasks/page.test.tsx` around lines 74 - 104, The test currently only asserts Content-Type on the fetch call; update the fetch header assertions for the TasksPage signed-route path (fetchMock, TasksPage) to also assert that the Authorization header is present and uses the naruon_session_token (e.g. expect.objectContaining({ Authorization: expect.stringMatching(/^Bearer\s+/) }) or the exact `Bearer ${naruon_session_token}` if that variable is available) and assert that public identity headers are NOT forwarded (e.g. ensure headers do not contain "x-public-identity" or "x-naruon-public-identity" via expect.not.objectContaining or an explicit negative check on fetchMock.calls).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@frontend/src/app/tasks/page.test.tsx`:
- Around line 74-104: The test currently only asserts Content-Type on the fetch
call; update the fetch header assertions for the TasksPage signed-route path
(fetchMock, TasksPage) to also assert that the Authorization header is present
and uses the naruon_session_token (e.g. expect.objectContaining({ Authorization:
expect.stringMatching(/^Bearer\s+/) }) or the exact `Bearer
${naruon_session_token}` if that variable is available) and assert that public
identity headers are NOT forwarded (e.g. ensure headers do not contain
"x-public-identity" or "x-naruon-public-identity" via
expect.not.objectContaining or an explicit negative check on fetchMock.calls).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 1148b162-07b5-4631-8cdd-709ec0c325cc
📒 Files selected for processing (6)
.coderabbit.yamldocs/threading-contract.mdfrontend/src/app/tasks/page.test.tsxfrontend/src/components/AIHubLayout.tsxfrontend/src/components/TasksLayout.tsxfrontend/tests/e2e/dashboard-branding.spec.ts
|
Merge gate update for head
This is being treated as a merge wait state for missing required Actions contexts, not as a CodeRabbit review blocker. |
|
Cycling this PR open state to force GitHub pull_request/pull_request_target event evaluation for missing required Actions contexts. No branch protection or scanner setting is being changed. |
Pull request was closed
|
@coderabbitai review Latest head Validation passed:
|
|
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@backend/services/reply_tracking_service.py`:
- Around line 53-55: The grouping key can differ when IDs include angle
brackets, so update reply_tracking_thread_key(Email) to normalize the chosen id
by trimming whitespace, removing surrounding '<' and '>' if present, and
optionally lowercasing the result (i.e., compute key = (thread_id or
message_id).strip(); if key startswith '<' and endswith '>' then strip those;
then key = key.lower()); replace usages that group by raw thread_id/message_id
with this normalized key and apply the same normalization in the other grouping
location that uses thread keys so both places use the identical normalized
value.
In `@backend/tests/test_emails_api.py`:
- Around line 276-317: The new unit test
test_get_emails_marks_self_sent_and_pending_reply_threads only exercises a
mocked db_session; add a real-PostgreSQL smoke/integration path that bootstraps
the DB and verifies the same /api/emails and /api/emails/pending-replies
behaviors: create an integration-style test that uses the real DB-backed fixture
(the project’s postgres bootstrap fixture or CI-local postgres container), seed
the emails table with rows matching the Email objects used in
test_get_emails_marks_self_sent_and_pending_reply_threads, call the same
client.get("/api/emails?limit=10") and assert requires_reply and is_self_sent
per thread, and mark the test with the appropriate e2e/postgres marker so it
runs against the real DB bootstrap in CI. Ensure you reference the same
identifiers (test_get_emails_marks_self_sent_and_pending_reply_threads,
/api/emails, /api/emails/pending-replies, and the Email-like seed rows) when
adding the smoke test.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 6b3d23c1-ae29-472f-9c31-4cd48cf4971c
📒 Files selected for processing (5)
backend/api/emails.pybackend/services/reply_tracking_service.pybackend/tests/test_emails_api.pybackend/tests/test_reply_tracking.pydocs/plans/2026-05-19-branding-menu-task-tracking-gap-closure.md
✅ Files skipped from review due to trivial changes (1)
- docs/plans/2026-05-19-branding-menu-task-tracking-gap-closure.md
|
@coderabbitai review Latest head
Validation passed:
|
|
✅ Actions performedReview triggered.
|
|
CI gate update for head
This is a repository/account access blocker in GitHub-hosted Actions, not a failing application/security finding from the PR code. |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
backend/services/ontology_service.py (1)
114-131:⚠️ Potential issue | 🟠 Major | 🏗️ Heavy liftUse tenant owner addresses for the self-sent gate.
This path currently feeds the parsed sender back into both
process_self_to_self(...)andextract_knowledge_from_self_sent(...), so it never proves that the address belongs to the mailbox owner/tenant. A message where the sender is also a recipient can be treated as self-sent even when that address is not owner-scoped.Suggested fix
async def process_knowledge_node( self, session, email_data: dict, user_id: str, organization_id: str | None, + owner_addresses: list[str], source_email: Email | None = None, ): sender = str(email_data.get("sender") or "") _, sender_address = email_utils.parseaddr(sender) - if not process_self_to_self(email_data, sender_address): + if not process_self_to_self(email_data, owner_addresses): return None if source_email is None: logger.info( "Skipping self-sent knowledge extraction for user %s without source email row", user_id, @@ - return await extract_knowledge_from_self_sent( - session, source_email, [sender_address] - ) + return await extract_knowledge_from_self_sent( + session, source_email, owner_addresses + )As per coding guidelines, "Self-sent knowledge extraction must first prove true self-to-self addressing" and "Email-derived tasks must stay source-linked to the email/thread and tenant owner scope."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/services/ontology_service.py` around lines 114 - 131, The code currently uses the parsed sender_address for both process_self_to_self(...) and extract_knowledge_from_self_sent(...), which can treat non-owner addresses as self-sent; replace that by resolving the tenant/mailbox owner addresses and using those for the self-to-self check and extraction. Concretely: fetch the owner address list for the tenant/user (e.g., via an existing helper or a new get_tenant_owner_addresses(session, user_id, organization_id) or from source_email owner metadata), call process_self_to_self(email_data, owner_addresses) instead of process_self_to_self(email_data, sender_address), and pass that same owner_addresses list into extract_knowledge_from_self_sent(session, source_email, owner_addresses); keep the existing source_email.user_id/organization_id checks intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@backend/api/tenant_config.py`:
- Around line 37-40: The new POP3 fields (pop3_server, pop3_port) are not being
validated on write by _validate_smtp_config_update, so unsafe/internal POP3
endpoints can be stored; update _validate_smtp_config_update (or rename/extend
it, e.g., _validate_mail_config_update) to also validate pop3_server and
pop3_port using the same host/port safety checks you already apply to
smtp_server/smtp_port, and ensure any error messages mention the POP3 field
names (pop3_server/pop3_port) so writes are rejected when the POP3 destination
is unsafe.
In `@backend/services/knowledge_extractor.py`:
- Around line 26-34: _owner_addresses passed to _normalized_owner_addresses may
be a single string and list(owner_addresses) will split it into characters;
change the candidates construction to explicitly handle str: if owner_addresses
is None -> empty list, if isinstance(owner_addresses, str) -> treat as a
single-item list [owner_addresses], else cast to list(owner_addresses). Keep the
rest of the function (checking email.user_id and calling
email_utils.getaddresses) unchanged so getaddresses receives whole address
strings rather than characters.
In `@backend/services/pop3_worker.py`:
- Around line 86-93: The current branch logs and continues when
config.pop3_username or config.pop3_password are missing; instead, make the POP3
credential check fail fast: in the block around the pop3 login (where
config.pop3_username/config.pop3_password are checked before calling
pop3_client.user and pop3_client.pass_), replace the logger.info path with a
logger.error and raise an exception (e.g., RuntimeError or custom
SyncConfigurationError) including the user id and which credential is missing so
the sync worker stops rather than silently skipping login; keep the successful
login calls to pop3_client.user and pop3_client.pass_ unchanged.
In `@backend/tests/test_tenant_config_api.py`:
- Around line 77-80: Add a Postgres-backed smoke test in
backend/tests/test_tenant_config_api.py (e.g.,
test_create_read_pop3_postgres_smoke) that uses the project’s real Postgres
bootstrap fixture (the same DB fixture used by other smoke tests) to perform a
create+read roundtrip against the /api/config endpoint: POST a payload including
"pop3_server", "pop3_port", "pop3_username", and "pop3_password", then GET the
config and assert the returned pop3_password is masked (not the plaintext) and
other POP3 fields round-trip; additionally query the raw DB row for the tenant
config (via the same repository/ORM used in production) and assert the stored
value is not the plaintext (proving encryption/persistence). Ensure the test
cleans up and uses the real DB fixture rather than mocks.
---
Outside diff comments:
In `@backend/services/ontology_service.py`:
- Around line 114-131: The code currently uses the parsed sender_address for
both process_self_to_self(...) and extract_knowledge_from_self_sent(...), which
can treat non-owner addresses as self-sent; replace that by resolving the
tenant/mailbox owner addresses and using those for the self-to-self check and
extraction. Concretely: fetch the owner address list for the tenant/user (e.g.,
via an existing helper or a new get_tenant_owner_addresses(session, user_id,
organization_id) or from source_email owner metadata), call
process_self_to_self(email_data, owner_addresses) instead of
process_self_to_self(email_data, sender_address), and pass that same
owner_addresses list into extract_knowledge_from_self_sent(session,
source_email, owner_addresses); keep the existing
source_email.user_id/organization_id checks intact.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 8c582931-26fc-423d-a530-3cb0b0054b9b
📒 Files selected for processing (22)
.github/workflows/strix.ymlAGENTS.mdREADME.mdbackend/api/accounts.pybackend/api/tenant_config.pybackend/db/models.pybackend/scripts/bootstrap_db.pybackend/services/imap_worker.pybackend/services/knowledge_extractor.pybackend/services/ontology_service.pybackend/services/pop3_worker.pybackend/tests/test_accounts_api.pybackend/tests/test_bootstrap_db.pybackend/tests/test_knowledge_extractor.pybackend/tests/test_ontology_pipeline.pybackend/tests/test_tenant_config_api.pybackend/tests/test_tenant_config_model.pybackend/tests/test_threading_pipeline.pydocs/operations/email-relay-proxy-boundary.mddocs/plans/2026-05-19-branding-menu-task-tracking-gap-closure.mddocs/plans/2026-05-19-north-star-gap-closure.mdscripts/ci/test_strix_quick_gate.sh
✅ Files skipped from review due to trivial changes (3)
- docs/plans/2026-05-19-north-star-gap-closure.md
- docs/plans/2026-05-19-branding-menu-task-tracking-gap-closure.md
- README.md
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
Current gate evidence for head dbf4e5d:
The Strix job is still executing trusted workflow code from base SHA ebf2608 because this is The PR branch already changes Strix to the GPT-5 path, but that cannot affect this required No admin merge or security-check suppression was used. Auto-merge remains enabled and will wait for required gates. |
5866f11 to
2181e0b
Compare
|
PR governance metadata gate is not ready for
|
Summary
/api/tasksdata and show source-linked ticket status, priority, email, and thread provenance.openai/gpt-5withmodels: read, GitHub token auth, OpenAI-compatible endpoint, and fail-closed artifact handling.Verification
PYTHONDONTWRITEBYTECODE=1 DISABLE_BACKGROUND_WORKERS=1 PYTHONWARNINGS=error python3 -m pytest backend/tests/test_llm_api.py backend/tests/test_release_governance.py backend/tests/test_repo_hygiene.py -qnpm test -- src/components/DashboardLayout.test.tsx src/app/page.test.tsx src/app/tasks/page.test.tsxnpm run lintnpm run typecheckNEXT_STATIC_GENERATION_MAX_CONCURRENCY=2 NEXT_STATIC_GENERATION_MIN_PAGES_PER_WORKER=50 npm run buildenv -u NO_COLOR LIVE_BASE_URL=http://127.0.0.1:18124 npm run test:e2e -- tests/e2e/dashboard-branding.spec.tsbash scripts/ci/test_strix_quick_gate.shnpm audit --audit-level=moderateNotes
gh api https://models.github.ai/catalog/modelscurrently listsopenai/gpt-5;openai/gpt-5.4was not available to this token, so the Strix default is nowopenai/gpt-5per latest maintainer direction.Summary by CodeRabbit
New Features
Improvements
Documentation
Tests