Skip to content

feat(gui): protocol wire, evidence and combo candidate views (PF-11) - #5817

Closed
lidge-jun wants to merge 26 commits into
feat/pf08-managed-messages-nativefrom
feat/pf11-protocol-evidence-gui
Closed

lidge-jun wants to merge 26 commits into
feat/pf08-managed-messages-nativefrom
feat/pf11-protocol-evidence-gui

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

Summary

PF-11 of the protocol-first-class unit (devlog/_plan/260924_protocol_first_class/030_gui_and_management_api.md#pf-11-evidence-combo-and-provider-views). Stacked on #5816 (PF-08).

Connects the existing Providers, Models → Compatibility, Combos and Logs screens to the protocol contract. No new page and no new write route; delivery mode and Lab verdict stay separate axes.

  • GET /api/protocols?provider=<name> adds the provider's wire summary (src/protocols/provider-summary.ts, side-effect free): adapter, decision source (hard-pin | operator | registry | provider-default), auth mode, upstream wire, and up to 64 model overrides (modelOverridesTruncated when capped). Bad names → 400 invalid_provider, unknown → 404 unknown_provider; neither echoes the name. DTO + validator in the leaf dto.ts.
  • Providers: ProviderProtocolPanel under the adapter field labels it "upstream wire this provider receives" with its source and overrides. It is read-only — PATCH /api/providers only accepts per-model adapters for one provider, so the existing adapter field stays the only editor; the panel shows what will change after save.
  • Compatibility: inbound and upstream protocol filters mapped from Lab subject identities with protocolFromLabProtocol. Absent evidence reads "unverified", never failed/unsupported. Subject details are fetched only while a protocol filter is active (≤ 200, 6 at a time, cached per target).
  • Combos: on-demand (button) per-candidate path preview with the guaranteed/partial feature split from POST /api/protocols/plan.
  • Deep links through hash queries (#providers?provider=…, #models/compatibility?inbound=…&upstream=…): plan candidate → provider settings / compatibility pair; Logs trace → compatibility pair. Links push history; filter edits replace it, so Back/Forward works.
  • All 10 locales; new CSS in gui/src/styles/protocol-evidence.css (capped styles.css untouched).

Verification

  • bun x tsc --noEmit: exit 0 on this head.

  • gui: bun x tsc -b, bun run lint, bun run lint:i18n, bun run build: exit 0.

  • bun run structure:check: passed.

  • Tests (tests/server/protocol-provider-summary.test.ts; gui/tests/{provider-protocol-panel,compatibility-protocol-filter,protocol-deep-links,providers-deep-link,combo-protocol-plan}.test.*) were written and registered but run in the full local suite below.

  • Full local run on the stack head (feat(protocols): protocol paths as a first-class concern — PF-01..PF-12 #5820, which contains this change): bun run test — the only failures are Lab CL-03/CL-07/CL-08/SEC-02 and release helper timeouts, which fail identically on a checkout without this stack (local environment), plus service/toggle cases that pass when run alone; cd gui && bun test --isolate tests — 2398 pass, 0 fail.

  • CI on this head: all required checks pass.

Screenshots

Captured from the stack head in an isolated home (fake providers, no real credentials).

Provider settings, upstream wire panel

Provider settings, upstream wire panel

Compatibility, client API and upstream wire filters

Compatibility, client API and upstream wire filters

Combo detail, candidate paths

Combo detail, candidate paths

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner September 25, 2026 04:08
@coderabbitai

coderabbitai Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

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

🗂️ Base branches to auto review (2)
  • ^dev$
  • ^preview$

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

⚙️ Run configuration

Configuration used: Repository: lidge-jun/opencodex/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: b93abbb9-b549-4f77-b57c-ae218b708f6c

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

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

❤️ Share

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

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-25T04:13:21.873486Z 9ecff38 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

@github-actions

github-actions Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

✅ READY

  • all PR quality gates passed.

Hygiene

✅ Deterministic PR hygiene checks passed.

@github-actions
github-actions Bot marked this pull request as draft September 25, 2026 04:09
@github-actions github-actions Bot added the enhancement New feature or request label Sep 25, 2026

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9ecff384bb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 571 to 572
{matrixRows.length === 0 ? (
<EmptyState title={t("lab.empty")} />

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep later evidence reachable when the filtered page is empty

When an active protocol pair has no match in the first 50 verdicts but does match a later page, the client-side filter makes matrixRows empty and this branch renders only the empty state. The Load more control is inside the opposite branch, so the remaining API pages become unreachable while ProtocolPairStatus labels the pair unverified. Keep pagination available, or fetch until pagination is exhausted, before declaring that no evidence exists.

AGENTS.md reference: gui/AGENTS.md:L10-L10

Useful? React with 👍 / 👎.

</button>
</div>
{failed && <p className="awi-delete-error" role="alert">{t("api.plan.failed")}</p>}
{plan && plan.inbound === inbound && <PlanResult plan={plan} />}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Clear a combo preview after saving configuration changes

After a preview is run, editing a combo's targets or strategy and saving it without renaming the combo preserves the same DetailPanel key and the same ComboProtocolPlan instance. The dirty flag returns to false, but this condition continues rendering the plan captured under the pre-save policy until the operator manually previews again. Reset or remount the preview when the saved baseline changes so the displayed candidates cannot contradict the committed combo configuration.

AGENTS.md reference: gui/AGENTS.md:L10-L10

Useful? React with 👍 / 👎.

@Ingwannu Ingwannu left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Reviewed draft exact head 9ecff384bb048164e29c8be4da0fe73552cd42e9. Blocking evidence-freshness issue: useSubjectProtocolPairs stores null in the process-global pairCache for every detail-read failure, and missingKey treats that as permanently resolved. A single transient network error or server 5xx therefore makes that subject unresolved for the rest of the dashboard session; the 60-second matrix poll, refreshed projection, filter toggles, and Back/Forward never retry it. This can hide real matching evidence and continue reporting the pair as unverified. Cache successful identities durably, but make failures retryable (for example per load generation or with a bounded backoff/TTL) and add a regression where a failed detail fetch succeeds on a later refresh. Focused provider-summary and five GUI suites passed 53/53 under CPUQuota=200%, MemoryMax=4G, MemorySwapMax=0, TasksMax=128. The PR is still draft, screenshots are pending, exact-head CI is red, and lower PF layers #5814-#5816 remain blocked.

The dashboard's provider panel validates the ?provider block with the shared leaf, so an
older or newer server's record is refused instead of half-rendered.
… wire

The provider panel needs the adapter, who decided it and per-model overrides; it is read
from captureRouteStaticPolicy so no second copy of the adapter rules exists.
A pinned model the operator never listed still receives another wire; leaving it out
would make the provider panel claim the provider adapter applies to it.
…ping

Covers the provenance collapse, the 64-override cap, a non-echoing 404 and 400s for
empty, over-long, control-character and repeated provider parameters.
…ovider

An older server answers 404 or ignores the parameter; both read as unavailable so the
provider panel hides quietly rather than showing an error.
Protocol deep links keep their target in the hash so Back/Forward restores it; routing
reads the path alone and drops a query on any route that does not own one.
One place builds and reads the compatibility pair and provider settings hashes, so the
plan panel, the Logs trace and the target pages agree on the spelling.
Shows the wire a provider receives, who decided it and per-model overrides from the
?provider summary; it is read-only so it can never pass for an API exposure switch.
The adapter field stays the only editor and still saves through onUpdateProvider; the
panel beside it says which wire an unsaved choice would send.
Lab records openai-chat and friends; protocolFromLabProtocol maps them, and a filtered
pair with no recorded row reads unverified rather than failed or unsupported.
Subject details are read only while a pair filter is active, bounded and cached, and
the status line keeps Lab verdicts apart from delivery mode.
…otocol

The pair lives in the hash so a deep link survives refresh and Back/Forward; an edit
replaces the entry so Back leaves the page instead of undoing a filter.
…pair

The trace says what a request did; whether that pair is verified is a Lab question,
so the row opens the matrix prefiltered to its client API and upstream wire.
A candidate's wire is decided in provider settings and its pair is verified in the
matrix; the preview links both instead of restating either.
The plan preview links a candidate to the panel that says which wire it receives; the
hash is re-read on Back/Forward and dropped once the user selects another provider.
Asks POST /api/protocols/plan for every feature the client API can express, so the
guaranteed/partial split covers the vocabulary; it runs only on an explicit click.
apiBase is threaded from the Combos page so the preview targets the same machine or
hub as the editor; a new, unsaved combo has nothing to plan and shows no preview.
Fast refresh needs component-only modules, and keying the fetch on the missing ids
removes the exhaustive-deps suppressions that made the React Compiler skip the hook.
…effect

Setting focus inside an effect cascaded a second render; adjusting own state during
render opens the provider and its Settings tab in one paint and satisfies the compiler.
…d-server hide

The panel must name the upstream wire and its decider, expose no switch, and render
nothing on a 404 or a server that ignores ?provider.
Lab identities map through protocolFromLabProtocol, an unknown pair is left out, and a
pair with no rows reads unverified with no verdict or delivery-mode badge.
Queries survive only on providers and compatibility, a provider link waits for the list
and re-applies on hash events, and moving away drops it.
No fetch before the click, the full expressible feature set in the plan body, both
candidates rendered, and a quiet hide on an older server.
…ence views

protocol-paths owns the ?provider builder and its source mapping; the dashboard doc
records the three new panels, the hash-query deep links and their tests.
…erence

Operators reading the reference see the provider block, its bounds and that it reports
the upstream wire without exposing or toggling any client API.
…igin target

The dashboard served by the proxy uses an empty API base, which both views read as
no target, so the panel never fetched and the combo candidate paths never rendered.
Only an absent base means no target.
@lidge-jun

Copy link
Copy Markdown
Owner Author

리뷰 · 우선순위 66 / 80

이 PR은 대시보드에 있는 화면을 프로토콜 계약에 연결한다. 새 페이지는 없고, 새로 저장하는 주소도 없다. 요청이 어떻게 전달되는지는 Lab이 매긴 판정과 따로 보여 준다.

프로바이더 설정 아래에 읽기 전용 칸이 붙는다. GET /api/protocols?provider=이름이 그 프로바이더가 받는 형식, 그 형식을 누가 정했는지, 모델마다 다른 형식이 있는지를 돌려준다. 다른 형식은 한 번에 64개 모델까지다. 더 있으면 잘렸다고 표시한다. 이름이 비었거나 너무 길면 400, 없는 이름이면 404다. 두 오류 모두 그 이름을 응답에 다시 적지 않는다. 어댑터를 고치는 칸은 예전 그대로다. 이 칸은 저장하면 어떤 형식이 될지만 말한다.

호환성 표는 들어오는 API와 나가는 형식으로 거를 수 있다. Lab이 적어 둔 openai-chat 같은 이름을 공개 프로토콜 이름으로 바꾼다. 그 조합의 기록이 없으면 실패가 아니라 "아직 확인 안 함"이다. 필터가 켜져 있을 때만 대상 상세를 읽는다. 한 번에 6개, 최대 200개, 같은 대상은 기억해 둔다.

콤보 상세의 버튼은 저장된 콤보만 서버에 묻는다. POST /api/protocols/plan이 후보 경로와, 모든 후보가 지키는 기능과 일부만 지키는 기능을 돌려준다. 저장하지 않은 수정은 미리보기에 안 들어간다.

해시로 바로 연다. #providers?provider=이름은 그 프로바이더 설정, #models/compatibility?inbound=…&upstream=…는 그 조합의 호환성 표다. 계획 후보와 로그 한 줄도 이 주소로 보낸다. 링크는 방문 기록을 쌓는다. 필터를 고치면 현재 기록을 갈아끼워서, 뒤로 가기는 필터를 취소하지 않고 이전 화면으로 나간다.

베이스는 dev가 아니라 #5816의 feat/pf08-managed-messages-native다. 같은 PF-11을 여는 다른 열린 PR은 없다. src/types.ts를 나누는 변경은 없다.

라인 - gui/src/pages/compatibility-protocol-pairs.ts 53행, 66행 — 대상 상세를 한 번 못 읽으면 null을 기억해 둔다. 53행은 그 키가 있으면 다시 묻지 않는다. 네트워크가 한 번 끊기거나 서버가 잠깐 오류를 내도, 화면을 다시 열기 전까지 그 대상은 표에서 빠진다.

라인 - gui/src/pages/CompatibilityMatrix.tsx 410행, 571행, 657행 — 프로토콜 필터는 이미 받아 온 줄만 거른다. 첫 묶음에 맞는 줄이 없으면 571행이 빈 화면만 그린다. "더 보기"는 657행, 표가 있는 쪽에만 있다. 다음 묶음에 근거가 있어도 누를 수 없다. 410행은 화면에 남은 줄만 보고 "아직 확인 안 함"이라고 말한다.

라인 - gui/src/components/protocols/ComboProtocolPlan.tsx 86행 — 미리보기는 들어오는 API를 바꿀 때만 비운다. gui/src/components/combo-workspace-detail-panel.tsx 384행은 같은 콤보면 이 칸을 다시 만들지 않는다. 대상을 고치고 저장하면 저장 전에 받아 둔 후보가 86행에 그대로 남고, "저장된 콤보를 보여 준다"는 안내도 사라진다.

메인테이너의 판단이 필요한 지점

베이스가 dev가 아니면 게이트는 보통 잘못된 베이스로 본다. 부모가 열린 PR이면 스택 예외로 넘어간다. #5816이 열려 있는 동안은 괜찮다. 부모를 닫거나 머지하면 이 예외가 사라진다. 지금 베이스를 dev로 바꾸면 #5816에 쌓인 커밋이 이 PR에서 풀린다.

아직 초안이다. 작성자는 새 테스트를 로컬에서 돌리지 않았고, CI가 첫 실행이라고 적었다.

너의 추천

방향은 유지해라. 닫을 중복 PR은 없다. 베이스를 지금 dev로 되돌리지 마라. 상세 읽기 실패는 성공한 것처럼 기억하지 마라. 새로고침하면 다시 묻게 해라. 필터가 켜져 있고 다음 묶음이 있으면 빈 화면에도 "더 보기"를 남겨라. 맞는 줄을 끝까지 보기 전에는 "아직 확인 안 함"이라고 쓰지 마라. 콤보를 저장하면 미리보기를 비우고, 버튼을 다시 누르게 해라.

이 댓글은 grok-bot이 작성했습니다

@github-actions
github-actions Bot marked this pull request as ready for review September 25, 2026 05:42
@devin-ai-integration devin-ai-integration Bot added the priority: P3 Low: new provider/client integration, large or experimental feature (>2000 LOC or >50 files), RFC/ro label Sep 25, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor

Maintainer triage: priority: P3 — protocol-first-class series PF-11 (GUI).

Criteria (P3): Low: new provider/client integration, large or experimental feature (>2000 LOC or >50 files), RFC/roadmap, or long-stale branch.

Related / overlapping PRs:

lidge-jun added a commit that referenced this pull request Sep 25, 2026
…12 (#5820)

Squash of the protocol-first-class stack #5808, #5809, #5810, #5811, #5812, #5813, #5814, #5815, #5816, #5817, #5819 and #5820. Every new lane sits behind a protocols.rollout switch that defaults off.
@lidge-jun

Copy link
Copy Markdown
Owner Author

Landed in dev as part of the single squash of the protocol-first-class stack: #5820 (0f4c8d4).

@lidge-jun lidge-jun closed this Sep 25, 2026
@lidge-jun
lidge-jun deleted the feat/pf11-protocol-evidence-gui branch September 26, 2026 01:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request priority: P3 Low: new provider/client integration, large or experimental feature (>2000 LOC or >50 files), RFC/ro

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants