Skip to content

Add ndi.cloud.api.feedback; fix bridge CI for MATLAB files on an unmerged branch - #323

Merged
stevevanhooser merged 5 commits into
mainfrom
claude/cloud-api-feedback
Oct 12, 2026
Merged

stevevanhooser merged 5 commits into
mainfrom
claude/cloud-api-feedback

Conversation

@stevevanhooser

@stevevanhooser stevevanhooser commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Two pieces of work:

  1. The feedback API. This ports ndi.cloud.api.feedback (submitFeedback, deleteFeedback) from NDI-matlab#1023. The endpoints are the in-app problem report API in ndi-cloud-node#158.
  2. A fix for the bridge CI job. It has been failing on main since 2026-09-26. main records MATLAB files that exist only on the unmerged NDI-matlab branch claude/lightsheet-zarr-ndi-viewer-djp5vk.

1. Feedback API

  • New module src/ndi/cloud/api/feedback.py:
    • submitFeedback(app, category, description, *, appVersion, datasetId, documentId, environment, state, log, traceback) sends POST /feedback with schemaVersion: 1.
    • deleteFeedback(feedbackID) sends DELETE /feedback/{feedbackId}.
    • The private helper _submit() sends a body as-is, like MATLAB's SubmitFeedback class. The tests use it to reach the server's own validation.
  • Argument names: they match MATLAB exactly. The optional arguments keep camelCase because each one is also a key in the request body, which is shared with MATLAB and the server. They are keyword-only, like MATLAB's name-value options.
  • Request body: an option left at None is not sent, like MATLAB's missing / struct.empty. "" and {} are sent.
  • Return values: both functions return an APIResponse that unpacks like MATLAB's outputs: b, feedbackID, status, url = submitFeedback(...).
  • Errors: non-2xx responses raise, like every other ndi.cloud.api function:
    • CloudAPIError with status_code 400, 413 or 429;
    • CloudNotFoundError for a missing report;
    • CloudAuthError for 401/403.
  • FeedbackCategory validator in _validators.py (bug / performance / other), and the module is registered in ndi.cloud.api.__init__.
  • Tests:
    • tests/test_cloud_api_feedback.py (offline): a real CloudClient over a stub transport. It checks the exact request body, each optional field, URL and method, the unpacking, input checks, the error mapping, and that POST is not retried.
    • tests/test_cloud_feedback_live.py: ports the server-facing cases of feedbackTest.m. It skips without credentials, or when the endpoint is not deployed (404 for a malformed id). Every submitted report is deleted, with a cleanup step if a test fails part-way.

2. Bridge CI: MATLAB files on an NDI-matlab branch

Cause. The bridge job checks out NDI-matlab main, or a branch named like the PR's. These NDI-python main records point at files that are only on claude/lightsheet-zarr-ndi-viewer-djp5vk:

  • resolveOrganizationId
  • LightsheetZarrManager
  • eight +ndi/+fun/+doc/+lightsheet/*.m functions
  • six lightsheet document/schema files in ndi_common

CI reported every one as a stale path. Neither existing escape fits: matlab_path: "N/A" and retired both say the MATLAB file doesn't exist, which is false.

Fix. An entry can now carry matlab_branch: <branch>, and ndi_common files have a matching MATLAB_BRANCH_PENDING map. The checks verify the claim rather than skip it:

  • the branch must exist and the file must be on it (byte-identical for ndi_common);
  • drift (MATLAB changes after the recorded commit) is measured against the branch tip;
  • once the branch merges into NDI-matlab main, the check fails until the marker is removed. "Merged" is checked against main, not the checked-out tree, so CI on the branch itself doesn't trip it.

The helpers are in tests/_matlab_branch.py. tests/test_matlab_branch_pending.py tests them against a throwaway git repo, so it runs in every job.

Entries updated.

  • matlab_branch added to the 10 affected entries.
  • fromOMEZarr, makePyramid and chooseTileShape now record 5c9e8a83 on the branch (default tile budget raised from 8 MB to 32 MB). None has a Python port yet, so there was nothing to follow; each decision_log says so.
  • decodeJwt now records 4a571dce (NDI-matlab#1024). MATLAB replaced a Java base64 decoder it no longer ships with matlab.net.base64decode. Python uses the standard library, so there was nothing to follow.
  • url now records 75f937a76, for the two feedback routes.

Docs. New section 8 in docs/developer_notes/ndi_matlab_python_bridge.yaml says when matlab_branch may be used. It is also in the field table, and PYTHON_PORTING_GUIDE.md points to it.

Test plan

  • black --check and ruff check are clean.
  • All five bridge CI steps pass locally against NDI-matlab main.
  • The new checks catch a wrong branch name, a wrong path and a stale commit. Each was tried by hand.
  • Offline feedback tests pass (36).
  • CI is green on this head.
  • Live feedback tests: they were skipped here (no credentials) and run only in the cloud-API workflow.

🤖 Generated with Claude Code

https://claude.ai/code/session_01B22A1gLVKa1E3uQm3tv4t8

Port of NDI-matlab#1023 (75f937a76): wrappers for the in-app problem
report endpoints from ndi-cloud-node#158.

- submitFeedback(app, category, description, *, appVersion, datasetId,
  documentId, environment, state, log, traceback) POSTs /feedback with
  schemaVersion 1. Optional fields keep MATLAB's camelCase names because
  they are the shared payload keys; None omits a field, as MATLAB's
  missing / struct.empty do. Returns an APIResponse whose data is the
  stored report id.
- deleteFeedback(feedbackID) DELETEs /feedback/{feedbackId} (204).
- FeedbackCategory validator in _validators.py (bug/performance/other).
- Bridge entries for both; url bumped to 75f937a76 for the two new
  routes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B22A1gLVKa1E3uQm3tv4t8
Port of NDI-matlab feedbackTest.m (75f937a76).

- tests/test_cloud_api_feedback.py: real CloudClient over a stub
  transport; pins the exact payload, optional-field omission, URL and
  method, MATLAB-style unpacking, client-side validation, and the
  400/401/403/404/413/429 error mapping. POST is not retried.
- tests/test_cloud_feedback_live.py: the live cases, skipped without
  credentials or where the endpoint is not deployed (404 on a malformed
  id); every submitted report is deleted, with a teardown backstop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B22A1gLVKa1E3uQm3tv4t8

stevevanhooser commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor Author

Update: the bridge failure is fixed on this PR (03e5f26, 26f859a, 8775099). It was already red on main before this PR (run 36277130417).

Cause. main records MATLAB files that exist only on the unmerged NDI-matlab branch claude/lightsheet-zarr-ndi-viewer-djp5vk:

  • resolveOrganizationId
  • LightsheetZarrManager
  • eight +ndi/+fun/+doc/+lightsheet/*.m files
  • six lightsheet ndi_common files

Fix. A bridge entry can now carry matlab_branch: <branch>, and ndi_common files have a matching MATLAB_BRANCH_PENDING list. The checks still apply, just against that branch: the branch must exist, and the file must be on it (byte-identical for ndi_common). Drift is measured against the branch tip. Once the branch merges into NDI-matlab main, the check fails until the marker is removed. The rules are in section 8 of docs/developer_notes/ndi_matlab_python_bridge.yaml.

Drift cleared, no Python change needed:

  • decodeJwt (NDI-matlab#1024): the Java base64 decoder was replaced by matlab.net.base64decode. Python already uses the standard library.
  • fromOMEZarr, makePyramid and chooseTileShape: the branch raised the default tile budget from 8 MB to 32 MB. These three have no Python port yet.

Locally, against NDI-matlab main, all five bridge CI steps pass.


Generated by Claude Code

…branch

NDI-python main records MATLAB files (the lightsheet OME-Zarr functions,
LightsheetZarrManager, resolveOrganizationId, and six ndi_common document
files) that exist only on VH-Lab/NDI-matlab
claude/lightsheet-zarr-ndi-viewer-djp5vk, which has not merged. CI checks
out NDI-matlab main, so the bridge job has been red on main since
2026-09-26, reporting them as stale paths.

Add a matlab_branch field (and MATLAB_BRANCH_PENDING for ndi_common) that
names the branch, and check the claim rather than skip it:
- the branch must exist and the file be on it (ndi_common: byte-identical);
- drift is measured against the branch tip instead of HEAD;
- once the branch merges into NDI-matlab main, the marker must be removed.

Helpers in tests/_matlab_branch.py, tested against a throwaway git repo in
tests/test_matlab_branch_pending.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B22A1gLVKa1E3uQm3tv4t8
…sheet drift

- matlab_branch on resolveOrganizationId, LightsheetZarrManager and the
  eight +ndi/+fun/+doc/+lightsheet entries.
- fromOMEZarr / makePyramid / chooseTileShape: examined against 5c9e8a83
  on that branch (default tile budget 8 MB -> 32 MB). No Python
  counterpart yet, nothing to follow; noted in each decision_log.
- decodeJwt: examined against 4a571dce (NDI-matlab#1024, Java base64
  decoder replaced by matlab.net.base64decode). Python uses the stdlib;
  nothing to follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B22A1gLVKa1E3uQm3tv4t8
Section 8 of docs/developer_notes/ndi_matlab_python_bridge.yaml defines
when an entry may name an NDI-matlab branch and how the checks hold it to
account; the field table and the porting guide point there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B22A1gLVKa1E3uQm3tv4t8
@stevevanhooser stevevanhooser changed the title Add feedback API: submitFeedback and deleteFeedback endpoints Add ndi.cloud.api.feedback; fix bridge CI for MATLAB files on an unmerged branch Oct 12, 2026
@stevevanhooser
stevevanhooser merged commit eb03b80 into main Oct 12, 2026
9 checks passed
@stevevanhooser
stevevanhooser deleted the claude/cloud-api-feedback branch October 12, 2026 00:47
stevevanhooser pushed a commit that referenced this pull request Oct 12, 2026
Brings in ndi.cloud.api.feedback (submitFeedback, deleteFeedback) and its
tests (#323) plus the bridge checks for MATLAB files that live on an
NDI-matlab branch, ahead of the viewer's Report-a-problem button.

Conflict: src/ndi/fun/doc_lightsheet/ndi_matlab_python_bridge.yaml. Both
sides recorded the NDI-matlab 5c9e8a8 tile-budget bump; took main's
entries, which add the matlab_branch field its new bridge checks use.

Semantic fix: this branch's CloudClient re-authenticates on 401/403 when
_can_reauth is set (initialised in __init__). The feedback tests build a
client with CloudClient.__new__, so their helper now sets
_can_reauth = False, as test_cloud_client_retry's helper does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wj6cuvAwgAaYN5dNM1o6L
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants