)]}'
{
  "log": [
    {
      "commit": "3ba45ee5a5f641388d1a9eda90afa26a62d70d30",
      "tree": "21b0e38393214e942b8e4b82df3006656941b236",
      "parents": [
        "22b82a2958f8328be2f05044092e2b30e38c56cb"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Wed Oct 21 05:28:38 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 21 05:28:38 2026 +0000"
      },
      "message": "refactor(frontend): remove dead pve-modal selectors (#8926)\n\n### What changes were proposed in this PR?\n\nRemoves two selectors from the global stylesheet\u0027s Python-environment\nmodal (`.pve-modal`) block that match no element. **+1/−8 lines.** There\nis no behaviour change.\n\n- **The `.pve-modal .system-header .subtitle` rule.** The only\n`.system-header` element (in the computing-unit selection modal)\ncontains just a `.title`. No template, TS code or ng-zorro component\nproduces a bare `subtitle` class.\n- **The bare `.package-inputs` token in `.package-header-row,\n.package-inputs`.** The rule and `.package-header-row` stay. The\ntemplates use `system-package-inputs` and `user-package-inputs`, and CSS\nmatches whole class tokens, so neither matches `.package-inputs`.\n\nBecause these are global styles, the check covered every template and TS\nfile in the app, plus ng-zorro\u0027s compiled output.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #4484 (2026-05-01), \"feat: Add Python Virtual\nEnvironment Support: Creating a Virtual Environment\", which added the\nwhole `.pve-modal` block |\n| **Usage removed by** | #4902 (2026-05-12), \"Installing User Defined\nPackages\", renamed the element to `system-package-inputs`, which left\n`.package-inputs` unmatched. `.subtitle` was **never used** |\n\n`.package-inputs` has been dead for nearly five months.\n\n### Any related issues, documentation, discussions?\n\nCloses #8925\n\n### How was this PR tested?\n\nNo new tests; no spec referenced either selector.\n\nFrom `frontend/`:\n\n- `npx ng test --watch\u003dfalse --include\u003d\u0027**/user-venv.component.spec.ts\u0027\n--include\u003d\u0027**/computing-unit-selection.component.spec.ts\u0027`: 2 files, 242\ntests, all pass. These are the only specs that render the modal.\n- `yarn format:ci`: clean.\n- `npx ng build`: success.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "22b82a2958f8328be2f05044092e2b30e38c56cb",
      "tree": "705f9278c1857a35f4fc431f8ed4ba9a473b775a",
      "parents": [
        "a46ddc6eb6588491eb72b27bc975f060c4cb1a75"
      ],
      "author": {
        "name": "Om Kashyap Avashia",
        "email": "147749578+omavashia2005@users.noreply.github.com",
        "time": "Mon Oct 19 23:33:42 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 19 23:33:42 2026 +0000"
      },
      "message": "refactor(frontend): drop unused generated protobuf TypeScript (#9020)\n\n### What changes were proposed in this PR?\n\n`bin/frontend-proto-gen.sh` runs `protoc` on `workflow.proto` and\n`virtualidentity.proto`, but ts-proto also writes TypeScript for their\ntransitive imports. Those imports are used only for ScalaPB options\n(`scalapb.options`, `scalapb.field`), which shape the Scala output and\nproduce no TypeScript types. As a result, two files nothing uses were\ngenerated and committed:\n\n| File | Lines | Imported by |\n| --- | --- | --- |\n| `proto/google/protobuf/descriptor.ts` | 6824 | `scalapb.ts` only |\n| `proto/scalapb/scalapb.ts` | 2394 | nothing |\n\nChanges:\n\n| File | Change |\n| --- | --- |\n| `bin/frontend-proto-gen.sh` | Removes `proto/scalapb` and\n`proto/google` after `protoc` runs, so the files don\u0027t come back on the\nnext regeneration |\n| `frontend/src/app/common/type/proto/{google,scalapb}/` | Deleted |\n| `LICENSE` | Removes the `descriptor.ts` entry and the `scalapb.ts`\nline. The `scalapb.proto` entry stays because that file is still in the\nrepo |\n| `.licenserc.yaml` | Removes the license-check exclusions for the two\ndeleted files |\n\n```\nBefore:  protoc -\u003e workflow.ts, virtualidentity.ts, scalapb.ts, descriptor.ts (committed, unused)\nAfter:   protoc -\u003e workflow.ts, virtualidentity.ts\n```\n\nUser-facing behavior is unchanged.\n\n### Any related issues, documentation, discussions?\n\nCloses #9012 \n\nFollows #9010, which added the `LICENSE` entries for these generated\nfiles.\n\n### How was this PR tested?\n\n- `bash bin/frontend-proto-gen.sh`: the output folder contains only\n`org/apache/texera/amber/core/{virtualidentity,workflow}.ts`\n- `cd frontend \u0026\u0026 yarn build`: succeeds\n- `cd frontend \u0026\u0026 yarn test`: 237 test files passed; 6649 tests passed,\n1 skipped\n\nNo tests added: this removes dead generated code and nothing imports it.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nCo-authored by Claude-Code (helped with file and code deletion,\nnavigating repo, writing this PR description, and tests)"
    },
    {
      "commit": "a46ddc6eb6588491eb72b27bc975f060c4cb1a75",
      "tree": "644ec78de705e0d76592cfc98a3242b88558637f",
      "parents": [
        "3726dd7b1de85c649a3d953cfa4ee17479c89df6"
      ],
      "author": {
        "name": "yangzhang75",
        "email": "yangz75@uci.edu",
        "time": "Mon Oct 19 00:47:40 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 19 00:47:40 2026 +0000"
      },
      "message": "fix(workflow-form): keep the keyboard out of a read-only input card, not only the pointer (#9016)\n\n### What changes were proposed in this PR?\n\nCloses #8943. Part of the Form View feature (#8011); from the #8439\nrefinements (item 5).\n\nA read-only input card -- what a viewer without write access sees -- is\nlocked with `pointer-events: none`. That is hit testing only. The bound\nformly controls are disabled through `props.disabled`, but the controls\na custom widget draws of its own are not: the HuggingFace audio and\nimage uploaders each render a plain file input that nothing disables. A\nreader could Tab into one inside a locked card, open it with Enter and\nchoose a file.\n\nFor the audio input that is a real write. The widget POSTs the chosen\nfile to `/api/huggingface/upload-audio`, which authorises any signed-in\nuser and never asks who may write this workflow, so the file lands in\nthe server\u0027s temp store. Checked on a workflow shared read-only: two\npresses of Tab reach the uploader inside the locked card, Enter opens\nthe file dialog, and the POST comes back 200 with the stored path. The\nimage uploader is client-side, so there the reader only makes the card\ndisplay a picture of their choosing -- a read-only card wires no\nwrite-back and a reader\u0027s save is refused, so the operator keeps the\nauthor\u0027s value and a run still runs it.\n\nThe card now also keeps the keyboard out, through a small directive on\nit (`texeraReadOnlyCard`, applied as `[texeraReadOnlyCard]\u003d\"!canEdit\"`\nbeside the existing `read-only` class):\n\n- Every focusable descendant is taken out of the tab order\n(`tabindex\u003d\"-1\"`, its own value remembered) and marked\n`aria-disabled\u003d\"true\"`, so there is nothing for Tab to reach and\nassistive tech says why rather than going quiet.\n- Every control the browser will refuse outright -- button, input,\nselect, textarea -- is also disabled natively, its previous state\nremembered. Out of the tab order is not out of reach: `tabindex\u003d\"-1\"`\nends only sequential navigation and `aria-disabled` only announces, so a\nreader\u0027s assistive tech could still focus a widget\u0027s file input and\nactivate it, which for the audio one posts the file (Copilot).\n- A card that becomes editable gets its controls back, each with the\ntabindex and the disabled state it had, and only those this directive\ntook.\n- A control that leaves the card is let go of on the next pass: a widget\nredraws its own controls while the card lives on, so a set that only\ngrew held every detached node for as long as the reader stayed on the\npage (Copilot).\n- Widgets render their own controls after the card is built and redraw\nthem as they go, so the locking is re-applied on every change inside the\ncard: a control added, one whose own tabindex is written back (ng-zorro\nwrites one when it enables a control), and one a widget enables again\n(the audio uploader\u0027s `[disabled]\u003d\"isUploading\"`). The observer runs\noutside Angular and sets only what is not already set, so one pass\nsettles it.\n\n`inert` is what the step panel uses for its read-only mount, and the\nissue suggested following it; this does not, deliberately. `inert` also\nremoves the subtree from the accessibility tree, and a reader\u0027s card\nexists to be read -- the values are what a reader runs the workflow with\n-- so that would trade this bug for a worse one. Disabled controls stay\nin the accessibility tree and keep being announced. The directive\u0027s doc\ncomment says so, next to the code.\n\nNothing else changes: the pointer lock, the styles, the card\u0027s content\nand the author\u0027s editing path are untouched, and the directive does\nnothing at all while a card is editable.\n\n### Any related issues, documentation, discussions?\n\nCloses #8943, which re-files #8758 (closed). Part of #8439 (item 5) and\nthe Form View feature #8011. Raised by Copilot on #8437, #8438 and\n#8440.\n\nThree neighbouring things are deliberately left alone. The widgets\u0027 own\ncontrols still do not consult the field\u0027s disabled state in their own\nhandlers -- fixing that is per-widget work (the HuggingFace uploaders,\nthe dataset picker, the resource value selector), and the card-level\nlock covers every widget at once, including ones added later. The upload\nendpoint itself authorises on being signed in and nothing else\n(`@RolesAllowed(\"REGULAR\",\"ADMIN\")`, no workflow-access check), so it\nwould still accept a file posted by hand; closing the UI route does not\nclose that one, and it is worth its own issue. And the step panel\u0027s\n`inert` mount has the same accessibility-tree problem described above;\nchanging it is not this issue\u0027s scope, and it is worth its own look.\n\n### How was this PR tested?\n\nUnit tests (vitest). The directive\u0027s own spec, on a host shaped like a\ncard (a bound input, a widget\u0027s Browse button, a link, a span, a control\nwith its own `tabindex`): every focusable control in a read-only card is\nout of the tab order; each is marked `aria-disabled` while the card is\nnot inert and its text is still there; an editable card is left alone,\nkeeping a control\u0027s own `tabindex\u003d\"3\"`; a card that becomes editable\ngets that `3` back, the untouched control gets no `tabindex`, and the\n`aria-disabled` marks go; a control a widget adds after the card was\nbuilt is locked; a control whose widget writes its `tabindex` back, or\nenables again, is locked again; a click on a locked control dispatches\nno activation and the controls report disabled (jsdom does not model a\ndisabled control refusing focus, so that half is asserted through the\nproperty the browser acts on); the disabled state is given back on\nunlock; five rounds of a control being added and removed leave the\ntracked set where it started, rather than holding the detached nodes;\nthe observer is disconnected when the card goes away. The page\u0027s\nrendered spec wires it through the real template: a read-only viewer\u0027s\ncard, with a button appended the way a widget renders one, has it out of\nthe tab order and marked, and the card is not inert.\n\nBy hand, on two dev builds of the same base commit, one with this change\nand one without, signed in as a second account the workflow is shared\nread-only with. Before: from the view toggle, two presses of Tab land on\nthe uploader inside the locked card, Enter opens the file dialog, and\nchoosing a file POSTs it (200). After: the same two presses land on Run,\nthe card is skipped, and no request goes out. The mouse reaches nothing\nin either build, and the stored workflow is unchanged in both.\n\nEach guard was deletion-checked and turned a named test red (the\ndirective not applied; the tabindex write; the aria-disabled write; the\nnative disable; the editable check; the unlock; the original-tabindex\nrestore; the original-disabled restore; the release of what has left the\ncard; the childList and both attribute halves of the observer; the\ndisconnect). eslint, prettier and the production (AOT) build pass; every\nstatement, function and branch this PR adds is covered, and the full\nfrontend suite passes.\n\n#### Video\n\n**Before**\n\n\n\nhttps://github.com/user-attachments/assets/cd1b58ff-6cc4-4958-ad78-dd00bb86f14e\n\n\n\n**After**\n\n\nhttps://github.com/user-attachments/assets/8f524126-d370-48f3-bc70-68497791cf5f\n\n\n\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nYes. Generated-by: Claude Code (Anthropic). Co-authored with Claude,\nreviewed line by line by the author before submission.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "3726dd7b1de85c649a3d953cfa4ee17479c89df6",
      "tree": "03888dc0668b0a3d9c20640699b5df6cec299d35",
      "parents": [
        "57faa6b85c72bdd258b8e735c4be13171b5f8443"
      ],
      "author": {
        "name": "yangzhang75",
        "email": "yangz75@uci.edu",
        "time": "Sun Oct 18 02:58:35 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Oct 18 02:58:35 2026 +0000"
      },
      "message": "fix(workflow-form): rebuild the cards on compilation only when it changed something they show (#8845)\n\n### What changes were proposed in this PR?\n\nCloses #8844. Part of the Form View feature (#8011); from the #8439\nrefinements. Found on the #8761 demo (#8843).\n\nA compilation result rebuilt every card on the Form View, including the\ncompilation a card\u0027s own write triggers. Three things followed from\nthat, all visible with a Projection\u0027s drag-reorder list (#8761) and with\nany tick box: the controls were redrawn under the reader\u0027s eyes after\nevery click (the row buttons flicker); the keyboard focus went with the\nreplaced node, so a keyboard reader landed on the body about a second\nafter every Move up / Move down; and a click made in the last 150 ms\nbefore the rebuild was lost, since the rebuild ended that card\u0027s pending\ndebounced write and re-seeded the card from the operator, which still\nheld the previous state (the row \"jumps back\"). The canvas\u0027s property\npanel redraws only when an operator\u0027s schema changes.\n\nThe form now does the same:\n\n- A compilation rebuilds the cards only when it changed something they\nshow: a card\u0027s operator schema (the column enums compilation writes into\nit, which turn an attribute box into a dropdown), the set of inputs (an\noperator deleted on the canvas makes its card broken; a property exposed\nor removed), or an operator value a card does not hold (a co-editor\u0027s\nedit), including the operator\u0027s other properties, which a card is seeded\nwith as the context a custom widget reads to decide what it shows (the\nHuggingFace picker reads `task`): nothing but a rebuild re-seeds those,\nso a sibling changed on the canvas or by a co-editor would have left the\ncard showing the old one (Copilot). Every property an input is bound to\nis left out of that context, this card\u0027s own and any other card\u0027s on the\nsame step, since each is compared against the card that shows it:\ncounting them as context too would make one card\u0027s edit a change to\nevery other card of that step, and a form with two inputs from one step\nwould rebuild wholesale on every compilation its own typing triggers --\nthe churn this PR exists to stop (Copilot). The keys are compared\nsorted, so a rewrite that only reorders them is not a change, and a\ncard\u0027s own edit, written back or still on its way, is not a reason: the\ntwo agree once it is written. The result picker and the shown results\nstill follow the graph on every compilation.\n- Before any rebuild, from any source, a card\u0027s unwritten edit is\nwritten, so a rebuild can no longer lose one.\n- An empty string and an absent value count as the same value in the\ncomparison (formly\u0027s blank default for a property the operator never\nhad), so such a card is not rebuilt on every compilation.\n\n### Any related issues, documentation, discussions?\n\nCloses #8844. The drag-reorder list #8843 (#8761) brings to the form is\nwhere this is plain to see: every drop writes and compiles, and the rows\nredraw about a second later; a second drop made just before that redraw\nis undone. The cause is the form\u0027s own compile handling, present since\nthe cards were first built from the compiled schema; on main alone a\ntick box goes through the same redraw, focus drop and lost second click,\nwhich take a keyboard or a stopwatch to notice. The Before/After below\nis therefore recorded on top of #8843 (before: #8843 alone; after: #8843\nplus this); this PR does not depend on #8843 and applies to main as is.\nKnown limitation, unchanged: a card still shows a co-editor\u0027s edit of\nthe same property only after the rebuild that edit\u0027s compilation\ntriggers (tracked as a follow-up).\n\n### How was this PR tested?\n\nUnit tests (vitest), the form\u0027s spec: a compilation that changes nothing\na card shows leaves the cards alone (same card objects) while the result\npicker is still refreshed; a changed operator schema, an operator gone\nfrom the graph, an operator value changed under a card (a co-editor\u0027s\nedit), another property of a card\u0027s operator changed (the widget\ncontext), a changed set of inputs (one exposed; a shown one turned\nbroken) each rebuild; the same properties in another order do not, nor\ndoes a change to the card\u0027s own property while its edit is still on its\nway, nor one card\u0027s edit when two inputs come from the same step (both\ncard objects survive it); an author\u0027s broken card is left alone; the\ncard\u0027s own edit does not rebuild while pending nor once written;\nformly\u0027s blank and an absent value count as the same; an unwritten edit\nis written, once, before a rebuild from any source replaces the card; a\nread-only viewer\u0027s card has no write to flush; the typing hold still\nholds a needed rebuild until the focus leaves. Each guard was\ndeletion-checked (every compilation rebuilding; the schema check, the\ncontext check, the exclusion of every bound property from it, that the\nexclusion covers the other cards of the step and not only this one, the\ncontext\u0027s key sort, the pending check, the broken-set check, the blank\nnormalisation, the pre-rebuild flush, the pending mark, the pending\nreset and the result-picker refresh each removed; a broken card checked\nagainst a schema) and turned a named test red. eslint, prettier and the\nproduction (AOT) build pass; the full frontend suite passes; every\nstatement, function and branch this PR adds is covered.\n\nChecked on a flag-on instance (main-demo; before \u003d main, and main +\n#8843; after \u003d the same plus this), a Projection\u0027s columns and its Drop\nOption exposed on the form. The tick box on main: 0.3 s after a tick the\nbox still has the focus; 2.8 s later it is a new DOM node and the focus\nis on the body; two ticks 700 ms apart end in the state after the first\n(the second undone). With this change the box is the same node three\nseconds later, still focused, and both ticks land. The drag-reorder rows\non main + #8843: after a drop the rows are replaced about a second\nlater; with this change they are the same nodes, and the order still\nreaches a canvas tab open beside the form within a second, a drop made\non the canvas panel still reaches the form (a value the card does not\nhold rebuilds it), and the saved workflow carries the order.\n\n#### Video\n\n**Before**\n\n\nhttps://github.com/user-attachments/assets/eac466c3-c0c9-4969-b39a-a6da41ec54ff\n\n**After**\n\n\n\nhttps://github.com/user-attachments/assets/3ecd6342-7d6b-405c-bd83-f45415c2bcba\n\n\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nYes. Generated-by: Claude Code (Claude Fable 5.1, Anthropic).\nCo-authored with Claude, reviewed line by line by the author before\nsubmission.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Claude Fable 5.1 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "57faa6b85c72bdd258b8e735c4be13171b5f8443",
      "tree": "a5157687c74c527e64afceaecafd417471b0c71d",
      "parents": [
        "f03792080fc4324bf60fa262962220c2ac8edd4c"
      ],
      "author": {
        "name": "Meng Wang",
        "email": "mengw15@uci.edu",
        "time": "Fri Oct 16 00:43:22 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 16 00:43:22 2026 +0000"
      },
      "message": "fix(licensing): list the protobuf TypeScript generated from third-party .proto files in LICENSE (#9010)\n\n### What changes were proposed in this PR?\n\nThe frontend commits TypeScript that `bin/frontend-proto-gen.sh`\ngenerates from ScalaPB\u0027s `scalapb.proto` and, through it, Google\u0027s\n`descriptor.proto` (#8802). `descriptor.ts` carries about 850 lines of\nGoogle\u0027s BSD-3 documentation comments, but neither generated file was\nlisted in `LICENSE`.\n\nThis adds `descriptor.ts` under BSD 3-Clause with Google\u0027s copyright\nline, and lists `scalapb.ts` in the existing ScalaPB entry. Only\n`LICENSE` changes; the files themselves are untouched.\n\n### Any related issues, documentation, discussions?\n\nPart of #8802. The same files are on `release/v1.3` and `release/v1.2`.\n\n### How was this PR tested?\n\nLicense text only. The copyright line and license come from the header\nof `descriptor.proto` in protocolbuffers/protobuf.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (claude-opus-5-5)"
    },
    {
      "commit": "f03792080fc4324bf60fa262962220c2ac8edd4c",
      "tree": "39a4e86228fb57fcc7bc6573c5210f4b61421a07",
      "parents": [
        "d9c50f229e0b4f01170c1c61da37cbcc1fff6d6f"
      ],
      "author": {
        "name": "Meng Wang",
        "email": "mengw15@uci.edu",
        "time": "Fri Oct 16 00:33:52 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 16 00:33:52 2026 +0000"
      },
      "message": "fix(licensing): list the Jupyter logo and Material Symbols diagram icons in LICENSE (#8997)\n\n### What changes were proposed in this PR?\n\nThe notebook-migration diagrams in\n`frontend/src/assets/notebook_migration_tool/` bundle the Project\nJupyter logo (`tool_popup_diagram.png`) and three Material Symbols icons\n(all three diagrams). `frontend/LICENSE-binary` already lists them, but\nthe root `LICENSE`, which covers the source release, did not.\n\nThis adds the Jupyter logo to the BSD 3-Clause section (the license of\njupyter/design), with a trademark note like the ORCID entry\u0027s, and\nextends the existing Material Symbols entry to the diagrams. No images\nchange.\n\n`release/v1.3` gets a separate version of this fix rather than a\nbackport, because it still ships `jupyter-logo.svg` and has only one of\nthe diagrams.\n\n### Any related issues, documentation, discussions?\n\nPart of #8982 (the Jupyter item).\n\n### How was this PR tested?\n\nLicense text only. The entries mirror the ones already in\n`frontend/LICENSE-binary`, and the jupyter/design license and copyright\nline were checked at the source.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (claude-opus-5-5)"
    },
    {
      "commit": "d9c50f229e0b4f01170c1c61da37cbcc1fff6d6f",
      "tree": "99606b6126c93ca6ff76b61c5470475ad56181a5",
      "parents": [
        "e5d52e062ee7a0c148db4b6e96dcc44333917f25"
      ],
      "author": {
        "name": "Tanishq Gandhi",
        "email": "56472134+tanishqgandhi1908@users.noreply.github.com",
        "time": "Thu Oct 15 23:02:16 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 23:02:16 2026 +0000"
      },
      "message": "fix(k8s): make the computing-unit prepuller follow texeraImages.pullPolicy (#8973)\n\n### What changes were proposed in this PR?\n\nThe computing-unit prepull DaemonSet hardcoded imagePullPolicy: Always,\nso on clusters that load images into the nodes (kind, minikube,\nair-gapped) setting texeraImages.pullPolicy to IfNotPresent or Never had\nno effect on it. Its init container still tried to pull from the\nregistry and failed.\n\nIt now reads {{ .Values.texeraImages.pullPolicy }}, like the Jupyter\nprepull DaemonSet and every other template that pulls a Texera image.\ntexeraImages.pullPolicy defaults to Always, so default installs render\nexactly as before.\n\nRendered with helm template, before:\n```\npullPolicy\u003dAlways        | CU prepuller: Always | Jupyter prepuller: Always\npullPolicy\u003dIfNotPresent  | CU prepuller: Always | Jupyter prepuller: IfNotPresent\npullPolicy\u003dNever         | CU prepuller: Always | Jupyter prepuller: Never\n```\nAfter:\n```\npullPolicy\u003dAlways        | CU prepuller: Always       | Jupyter prepuller: Always\npullPolicy\u003dIfNotPresent  | CU prepuller: IfNotPresent | Jupyter prepuller: IfNotPresent\npullPolicy\u003dNever         | CU prepuller: Never        | Jupyter prepuller: Never\n```\n\n### Any related issues, documentation, discussions?\nCloses #8972\n\n### How was this PR tested?\n\nRendered the DaemonSet with helm template under each\ntexeraImages.pullPolicy value, before and after (output above), and with\nthe default values, which still give Always.\nbin/k8s/tests/test_helm_values.sh passes.\n\n### Was this PR authored or co-authored using generative AI tooling?\nGenerated-by: Claude Code (Claude Opus 5.5)\n\nCo-authored-by: Meng Wang \u003cmengw15@uci.edu\u003e"
    },
    {
      "commit": "e5d52e062ee7a0c148db4b6e96dcc44333917f25",
      "tree": "ded14938bd288c9e8adb803a3329d22c8090c1cf",
      "parents": [
        "154042ae219f20e8bdf54a5f2312f988cc80e627"
      ],
      "author": {
        "name": "Tanishq Gandhi",
        "email": "56472134+tanishqgandhi1908@users.noreply.github.com",
        "time": "Thu Oct 15 22:55:58 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 22:55:58 2026 +0000"
      },
      "message": "fix(frontend): show an error when a file preview fails to load, and drop a superseded file (#8932)\n\n### What changes were proposed in this PR?\n\nThe file preview on dataset and model detail pages subscribed to each\nfile request without an error handler and never cancelled it. So:\n\nA failed download (storage unreachable, expired link, network error)\nleft the preview on “File content is loading” forever.\nWhen a file was clicked before the previous one finished, the earlier\nfile could arrive last and replace the newer one’s content under the\nnewer file’s name.\n\nUserDatasetFileRendererComponent now keeps the current request and\ncancels it whenever a new file is loaded, and shows the existing “File\nloading encounter error” message when the request fails.\n\nBefore: a failed download keeps loading, and a slow earlier file\nreplaces the selected one:\n\n\u003cimg width\u003d\"1440\" height\u003d\"900\" alt\u003d\"before-1-download-failed\"\nsrc\u003d\"https://github.com/user-attachments/assets/ca24ccb0-e721-48c1-b18d-23dffc1996dc\"\n/\u003e\n\n\u003cimg width\u003d\"1440\" height\u003d\"900\" alt\u003d\"before-3-first-file-overwrites\"\nsrc\u003d\"https://github.com/user-attachments/assets/3522331f-1941-42ff-bc8a-11364342837c\"\n/\u003e\n\nAfter: the failed download shows the error, and the selected file stays:\n\n\u003cimg width\u003d\"1440\" height\u003d\"900\" alt\u003d\"after-1-download-failed\"\nsrc\u003d\"https://github.com/user-attachments/assets/6e3b9ded-910d-4d13-ae12-879918f82a4a\"\n/\u003e\n\n\u003cimg width\u003d\"1440\" height\u003d\"900\" alt\u003d\"after-2-second-file-kept\"\nsrc\u003d\"https://github.com/user-attachments/assets/782cf354-7963-4ebc-bdbb-4685aac03601\"\n/\u003e\n\n### Any related issues, documentation, discussions?\nCloses #8930\n\n### How was this PR tested?\n\nAdded two cases to user-dataset-file-renderer.component.spec.ts: a\nfailed fetch shows the loading error, and a slow file is dropped once\nanother file is selected. Both fail without the fix.\n\ncd frontend\nyarn ng test --watch\u003dfalse\n--include\u003d\u0027**/user-dataset-file-renderer.component.spec.ts\u0027\nTests  57 passed (57)\n\nAlso checked against a local stack: with the object store stopped,\nclicking a file shows the error; and with one file’s request delayed,\nclicking it and then another file keeps the second file’s content.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n---------\n\nCo-authored-by: Meng Wang \u003cmengw15@uci.edu\u003e"
    },
    {
      "commit": "154042ae219f20e8bdf54a5f2312f988cc80e627",
      "tree": "6e2863cc7547acd03630a17c231b2948d3146d08",
      "parents": [
        "707849a00fe581c02f3cc8c2c038e8f4e773403b"
      ],
      "author": {
        "name": "carloea2",
        "email": "carloea2@uci.edu",
        "time": "Thu Oct 15 22:28:57 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 22:28:57 2026 +0000"
      },
      "message": "feat(pyamber): reject invalid port booleans (#8240)\n\n### What changes were proposed in this PR?\n\nThe Python GlobalPortIdentity decoder now rejects invalid boolean tokens\ninstead of silently treating them as false. Valid mixed-case true and\nfalse values remain supported.\n\n### Any related issues, documentation, discussions?\n\nCloses #8239\n\n### How was this PR tested?\n\nRetested with Python 3.12 on Windows in a fresh detached worktree from\nupstream main at `7426431337`, which includes the merged loop-completion\nchange #8938. Regression before implementation: 2 failed, 48 passed.\nAfter implementation: 50 passed.\n\nGenerate protobufs with `bash bin/python-proto-gen.sh`, then run from\n`amber`:\n\n```text\npython -m pytest src/test/python/core/util/test_virtual_identity.py src/test/python/core/storage/test_vfs_uri_factory.py -q --tb\u003dline -p no:cacheprovider\npython -m ruff check src/main/python src/test/python\npython -m ruff format --check src/main/python src/test/python\n```\n\nRuff lint and formatting pass for all 217 Python files.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Codex"
    },
    {
      "commit": "707849a00fe581c02f3cc8c2c038e8f4e773403b",
      "tree": "4b955ae6f093fe3b199560786bef7b5f8acd8b90",
      "parents": [
        "1f9a921d8812ce6bd556e325bc189f338dd914f7"
      ],
      "author": {
        "name": "Meng Wang",
        "email": "mengw15@uci.edu",
        "time": "Thu Oct 15 22:00:52 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 22:00:52 2026 +0000"
      },
      "message": "fix(licensing): take the Iris example dataset from scikit-learn instead of UCI (#9000)\n\n### What changes were proposed in this PR?\n\nThe single-node examples ship `Iris.csv` in both the source release and\nthe docker-compose bundle, and `LICENSE` records it as CC BY 4.0 from\nthe UCI repository (#8803). ASF policy allows CC BY works only in binary\nform (\"only include them in binary form\",\nhttps://www.apache.org/legal/resolved.html), so the file can\u0027t be in a\nsource release under that licence.\n\nThis takes the dataset from the copy scikit-learn distributes under the\nBSD 3-Clause License instead. The CSV keeps its columns, row order and\nspecies names, so the example workflow is unaffected. Only rows 35 and\n38 change: they are the two known transcription errors in the UCI copy,\nwhich scikit-learn\u0027s copy corrects to Fisher\u0027s published values.\n\nThe `LICENSE` entries (root and `bin/single-node/`) move to BSD\n3-Clause, the compose bundle ships the BSD 3-Clause text instead of CC\nBY 4.0, the now-unused `licenses/LICENSE-CC-BY-4.0.txt` is removed, and\nthe dataset description names the new source. This conflicts with #8997\nin `LICENSE`, since both add the BSD 3-Clause section; whichever lands\nsecond merges the two entries.\n\n### Any related issues, documentation, discussions?\n\nFollows up #8803.\n\n### How was this PR tested?\n\nChecked that every row of the new `Iris.csv` matches scikit-learn\n1.7.2\u0027s `iris.csv`. Ran the bundle\u0027s `git archive` export step against\nthis commit to confirm it picks up the BSD 3-Clause text, and checked\nthat the new description still makes valid JSON in `load-examples.sh`,\nwhich inserts it unescaped.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (claude-opus-5-5)"
    },
    {
      "commit": "1f9a921d8812ce6bd556e325bc189f338dd914f7",
      "tree": "03a02dc70e27fcceb3896a602f8c567fd47c9c5b",
      "parents": [
        "91f47533b4d07852a52ad462f6c8023d0ee2845b"
      ],
      "author": {
        "name": "Suryaa Charan",
        "email": "122703005+sshiv012@users.noreply.github.com",
        "time": "Thu Oct 15 18:48:07 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 18:48:07 2026 +0000"
      },
      "message": "feat(pyamber): explain Python UDF load errors with cause and fix (#8768)\n\n### What changes were proposed in this PR?\n\nWhen a Python UDF fails to load, the error now says what to fix. The\nexisting \"There should be one and only one Operator defined\" sentence\nstays first, so anything matching on it still works.\n\nThe line number and fix are attached as a note to the original\nexception, so its type, message and attributes stay as raised. The RPC\nserver now includes exception notes in the `ControlError` message, which\nis what the Static Error tab shows.\n\n| Mistake | Message now adds |\n|---|---|\n| No class (e.g. the whole template left commented out) | `No Operator\nclass was found. Uncomment or write exactly one class...` |\n| Method doesn\u0027t match the base class | `WrapperClass subclasses\nUDFOperatorV2 but does not implement process_tuple. If you meant\nprocess_table, subclass UDFTableOperator instead.` |\n| Two classes | `Found 2: FirstOperator, SecondOperator. Keep one and\ndelete or comment out the others.` |\n| Missing `from pytexera import *` | `name \u0027UDFOperatorV2\u0027 is not\ndefined (line 2 of the UDF code). Add from pytexera import * at the top\nof the UDF.` |\n| `@overrides` on the wrong method | the base class to method pairing |\n| A class with two pytexera bases | `X uses more than one base class\n(UDFOperatorV2, UDFTableOperator). Subclass exactly one.` |\n| Any other load error | the line number in the user\u0027s code |\n\nBefore and after, in the Static Error tab. Before is the untouched\ntemplate; after is a class with the wrong method:\n\n| Before | After |\n|---|---|\n| \u003cimg width\u003d\"800\" height\u003d\"288\" alt\u003d\"load-before\"\nsrc\u003d\"https://github.com/user-attachments/assets/bd2ac22c-1953-435c-b3d5-0cf2e6f0ddda\"\n/\u003e| \u003cimg width\u003d\"800\" height\u003d\"348\" alt\u003d\"load-after\"\nsrc\u003d\"https://github.com/user-attachments/assets/53985c6f-9ad3-4d93-aed1-0974d14e85ad\"\n/\u003e |\n\nMissing import, after:\n\n\u003cimg width\u003d\"800\" height\u003d\"303\" alt\u003d\"load-after-import\"\nsrc\u003d\"https://github.com/user-attachments/assets/c1ed1322-f7d0-4937-8aa2-848917a115ba\"\n/\u003e\n\n\n### Any related issues, documentation, discussions?\n\nPart of #8736. Split out of #8737 as the reviewer asked.\n\n### How was this PR tested?\n\nNew tests in `test_executor_manager.py` cover each case above, plus a\nsyntax error, a `KeyError` and a custom exception at load time (both\nkeep their own message and get the hint as a note), a class alias, and a\n`LoopEndOperator` subclass. `test_async_rpc_server.py` covers notes in\n`ControlError`, and loads a broken UDF inside a handler to check the\nmessage that gets sent back.\n\n```\ncd amber\npytest -m \"not integration\" src/test/python/core/architecture/managers/test_executor_manager.py src/test/python/core/architecture/rpc/test_async_rpc_server.py\npytest -m \"not integration\"\nruff check src/main/python src/test/python \u0026\u0026 ruff format --check src/main/python src/test/python\n```\n\nThe screenshots are from a local Texera built from this branch. The\ndisplayed text for those cases is the same after the follow-up commit.\n\nKnown limitations: UI-parameter source-line mapping relies on the\ngenerated hook\u0027s reserved name and structure. Runtime traceback\nlocations (e.g., errors inside process_tuple) are not remapped.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n---------\n\nCo-authored-by: suryaacharan \u003csuryaacharan@suryaacharans-MacBook-Pro.local\u003e\nCo-authored-by: Claude Opus 5.5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "91f47533b4d07852a52ad462f6c8023d0ee2845b",
      "tree": "12b7107a9fa03b0f55f71b829a436040a2d19051",
      "parents": [
        "74264313370d747ac748300f0bbbb780297d7e65"
      ],
      "author": {
        "name": "Suryaa Charan",
        "email": "122703005+sshiv012@users.noreply.github.com",
        "time": "Thu Oct 15 18:22:52 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 18:22:52 2026 +0000"
      },
      "message": "feat(pyamber): clear errors for return-instead-of-yield and output mismatches (#8769)\n\n### What changes were proposed in this PR?\n\nClear messages for the common Python UDF mistakes that show up while the\nworkflow runs:\n\n- **`return` instead of `yield`** in `process_tuple`, `process_batch`,\n`process_table` or `produce` now says `process_table must yield results,\nnot return them. Replace return x with yield x.` Before, users saw\n`pampy.MatchError: \u0027_\u0027 not provided` or `\u0027NoneType\u0027 object is not\niterable`. Returning a list still works.\n- **`__init__` without `super().__init__()`** on a table or batch UDF no\nlonger crashes with `\u0027_TableOperator__table_data\u0027`. The buffers are\ncreated on first use, the same way `Operator` already creates its\ntemplate decoder.\n- **A DataFrame in a non-binary column** now says which column, and to\nyield the DataFrame itself or make the column binary. A DataFrame in a\nBINARY column is pickled as before.\n- **Output columns that don\u0027t match** keep the original message and\npoint to \"Retain input columns\" and \"Extra output column(s)\" (or\n\"Columns\" for a 1-out Python UDF).\n\nBefore and after, in the Console:\n\n| Before | After |\n|---|---|\n|\u003cimg width\u003d\"800\" height\u003d\"288\" alt\u003d\"runtime-before\"\nsrc\u003d\"https://github.com/user-attachments/assets/7f854ffe-f5eb-4013-8fe4-9eb3a9e740ff\"\n/\u003e | \u003cimg width\u003d\"800\" height\u003d\"288\" alt\u003d\"runtime-after\"\nsrc\u003d\"https://github.com/user-attachments/assets/fbaec933-683f-4dd2-b603-5d988b4f338d\"\n/\u003e |\n\n### Any related issues, documentation, discussions?\n\nPart of #8736. Split out of #8737.\n\n### How was this PR tested?\n\nNew tests in `test_operator.py` (each `return` case, a returned list\nstill working, table and batch UDFs with and without\n`super().__init__()`) and `test_data_processor.py` (`process_tuple` and\n`on_finish` returning a value, a DataFrame in BINARY, LARGE_BINARY and\nSTRING columns, a missing or misspelled column next to a DataFrame, a\nwrong column type).\n\n```\ncd amber\npytest -m \"not integration\" src/test/python/core/models/test_operator.py src/test/python/core/runnables/test_data_processor.py\npytest -m \"not integration\"\nruff check src/main/python src/test/python \u0026\u0026 ruff format --check src/main/python src/test/python\n```\n\nThe screenshots are from a local Texera built from this branch.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n---------\n\nCo-authored-by: suryaacharan \u003csuryaacharan@suryaacharans-MacBook-Pro.local\u003e\nCo-authored-by: Claude Opus 5.5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "74264313370d747ac748300f0bbbb780297d7e65",
      "tree": "fd73817f13f6c5f2623896e23437511d4a503829",
      "parents": [
        "988c655597f30e89cd2887dc8c7f27499ad0fef8"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Thu Oct 15 05:20:47 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 05:20:47 2026 +0000"
      },
      "message": "fix(workflow-core): resolve Windows drive paths as local files (#8950)\n\n### What changes were proposed in this PR?\n\n`FileResolver.isFileResolved` no longer counts a one-letter\n`java.net.URI` scheme as \"already a URI\". A one-letter scheme is a\nWindows drive letter, so `C:/Users/me/a.txt` now falls through to the\nlocal resolver and becomes `file:///C:/Users/me/a.txt`.\n\n**Root cause.** `isFileResolved` returned true for any non-empty scheme,\nand `new URI(\"C:/Users/me/a.txt\")` parses `C` as the scheme. `resolve`\ntherefore returned the path unchanged, and `DocumentFactory` rejected it\nwith `Unsupported URI scheme: C for creating the ReadonlyDocument`. File\nScan hit this in the worker; the CSV / JSONL / Arrow scans hit it at\ncompilation, during schema inference.\n\n```\nBefore:  \"C:/data/a.txt\" -\u003e isFileResolved \u003d true  -\u003e URI \"C:/data/a.txt\"                         -\u003e Unsupported URI scheme: C\nAfter:   \"C:/data/a.txt\" -\u003e isFileResolved \u003d false -\u003e local resolver -\u003e \"file:///C:/data/a.txt\" -\u003e read\n```\n\nEvery scheme Texera produces or reads (`file`, `dataset`, `model`,\n`vfs`, `s3`, `https`, ...) has more than one letter, so those are still\ntreated as resolved. The backslash form `C:\\data\\a.txt` was never\naffected: a backslash is illegal in a URI.\n\n### Any related issues, documentation, discussions?\n\nCloses #8949\n\n### How was this PR tested?\n\nNew cases in `FileResolverSpec`:\n\n| Input | Pinned behavior |\n| --- | --- |\n| `C:/x/y.txt`, `c:/x/y.txt`, `C:\\x\\y.txt` | `isFileResolved` is false |\n| `s3://`, `dataset:///`, `file:///C:/...`, `file:/tmp/...`, `vfs:///`,\n`https://` | `isFileResolved` is true |\n| an existing temp file\u0027s absolute path, written with `/` | `resolve`\nreturns that file\u0027s `file` URI |\n| `C:/x/y.txt` (does not exist) | `resolve` throws\n`FileNotFoundException` instead of returning `URI(\"C:/x/y.txt\")` |\n\nBefore the fix, the `C:/x/y.txt` cases (`isFileResolved` and `resolve`)\nfailed on every OS. The temp-file case failed on Windows, where the path\nstarts with a drive letter.\n\n```\nsbt \"WorkflowCore/testOnly *FileResolver*\"   # 26 passed\nsbt scalafmtCheckAll \"WorkflowCore/scalafixAll --check\"\n```\n\nCallers that go through `resolve` / `fileResolved()` also pass locally:\n`WorkflowCompiler/testOnly *LogicalPlanSpec *WorkflowCompilerSpec` (60\npassed), and `WorkflowOperator/testOnly *ScanSourceOpDescSpec\n*TestOperatorsSpec *FileScanSourceOpDescSpec *CSVScanSourceOpDescSpec\n*JSONLScanSourceOpDescSpec *FileScanOpExecSpec` (78 of 79 passed). The\none failure is `FileScanSourceOpDescSpec`\u0027s UTF-16 test. On Windows it\ncannot delete its temp file while the reader is still open, and it fails\nthe same way without this change.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Opus 5.5)"
    },
    {
      "commit": "988c655597f30e89cd2887dc8c7f27499ad0fef8",
      "tree": "ff488c2483b4f4c15c8430eab1e516995e5437ac",
      "parents": [
        "65a748ab664ea2e479fd291385514a8273c0c645"
      ],
      "author": {
        "name": "Matthew B.",
        "email": "mgball@uci.edu",
        "time": "Thu Oct 15 02:37:09 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 02:37:09 2026 +0000"
      },
      "message": "refactor(pyamber): extract shared base for indexed shuffle partitioners (#8920)\n\n### What changes were proposed in this PR?\n- Add `IndexedShufflePartitioner` (new\n`indexed_shuffle_partitioner.py`), a base that owns the shared shuffle\nmachinery: the `__init__` (batch size + per-worker receiver slots),\n`add_tuple_to_batch`, `flush`, and `flush_state`.\n- Reduce `RoundRobinPartitioner`, `HashBasedShufflePartitioner`, and\n`RangeBasedShufflePartitioner` to just their routing: an abstract\n`_route(tuple_) -\u003e int`, an `_advance()` hook (round-robin bumps its\nindex), and a `_clear_batch_on_flush` flag (round-robin drains a flushed\nslot; hash/range do not). Each subclass shrinks by roughly 50 lines.\n- The two round-robin-only quirks (index advance, clearing a flushed\nslot) are made explicit via the hook and flag rather than changed, so\nbehavior is preserved. `OneToOnePartitioner` and `BroadcastPartitioner`\nkeep their distinct single-batch structure and are untouched.\n### Any related issues, documentation, discussions?\nCloses: #8919\n### How was this PR tested?\n- Run the partitioner and output-manager suites from `amber/`: `python\n-m pytest\nsrc/test/python/core/architecture/sendsemantics/test_partitioners.py\nsrc/test/python/core/architecture/packaging/test_output_manager.py`.\nExpect all green: the 74 existing specs (which assert exact emitted\ntuples, residual slot state, `round_robin_index`, and\n`get_receiver_index` outputs) pass unchanged, serving as the\nbehavior-preservation anchor.\n- Two tests were added to pin the one genuine divergence: round-robin\nclears a flushed slot\u0027s batch, while hash/range leave it intact.\n### Was this PR authored or co-authored using generative AI tooling?\nCo-authored with Claude Opus 4.8 in compliance with ASF"
    },
    {
      "commit": "65a748ab664ea2e479fd291385514a8273c0c645",
      "tree": "cb5a8ae2f72eab26d56a017eadfb94d13c84bd31",
      "parents": [
        "cf754629795d15cbc2cdc7b159fbd372991be0d9"
      ],
      "author": {
        "name": "Prateek Ganigi",
        "email": "91584519+PG1204@users.noreply.github.com",
        "time": "Thu Oct 15 02:35:16 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 02:35:16 2026 +0000"
      },
      "message": "fix(workflow-operator): degrade instead of raising on malformed chat responses (#8617)\n\n### What changes were proposed in this PR?\n\nThe text-generation and QA/ranking codegens read a chat provider\u0027s reply\nby indexing straight into it:\n\n    return body[\"choices\"][0][\"message\"][\"content\"]\n\nThat assumes the response is a dict, that `choices` is non-empty, and\nthat the first choice carries `message.content`. When a provider returns\na 200 with anything else, the indexing raises, and since the parse step\nruns once per row, a single malformed response aborts the entire run.\n`TextGenCodegen` was the most exposed: it had no `isinstance` check\neither, so even a plain list body raised.\n\nAll four extractions (one in `TextGenCodegen`, three in\n`QaRankingCodegen`) now guard on a truthy `choices` and use `.get`\nchaining, falling back to the raw JSON body. That is the same idiom\n`ImageTaskCodegen` adopted in #7920, and it matches how the native\n`hf-inference` shapes beside it already degrade via `body.get(\"answer\",\njson.dumps(body))`. A bad response now lands in the result column as raw\nJSON instead of killing the run.\n\n### Any related issues?\n\nCloses #8486\n\n### How was this PR tested?\n\n145 tests pass in the Hugging Face suites,\n`PythonCodeRawInvalidTextSpec` py-compiles the generated Python for all\n117 operators, and `scalafmtCheck` and `scalafix --check` are clean.\nAdded a degradation test to `TextGenCodegenSpec` and\n`QaRankingCodegenSpec`, and updated the assertions in\n`HuggingFaceInferenceOpDescSpec` that pinned the old form.\n\nThe emitted Python was also run directly against the failing shapes,\ncomparing this branch with main across 33 task/response combinations: 16\nof them raised before (`IndexError` on an empty `choices` list,\n`KeyError` on a missing `message`/`content`, `TypeError` on a list body)\nand none raise now. Well-formed chat responses and native `hf-inference`\nresponses parse identically to before.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nYes, this PR was co-authored with Claude in compliance with ASF policy.\n\n---------\n\nCo-authored-by: Meng Wang \u003cmengw15@uci.edu\u003e"
    },
    {
      "commit": "cf754629795d15cbc2cdc7b159fbd372991be0d9",
      "tree": "e5317cfe75f2356cff430f34dcc452e1216ff71c",
      "parents": [
        "d99fb4d53ce60ebda28187b81df0d828abe9ccc3"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Thu Oct 15 02:28:54 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 02:28:54 2026 +0000"
      },
      "message": "refactor(amber): count a materialized input port as completed once its END is processed (#8938)\n\n### What changes were proposed in this PR?\n\n`InputManager.isPortCompleted` now treats a port read from\nmaterialization the same as a port fed by a link: it counts as completed\nonce END_CHANNEL has been processed on it. `EndChannelHandler` marks\nthat by setting `WorkerPort.completed`.\n\nBefore, such a port reported its reader thread\u0027s `finished` flag. The\nthread sets that flag only after enqueuing END. So a DP thread waiting\non the queue, typically the worker that got no tuples, could run\n`EndChannelHandler` before the flag was set. It then saw the port as not\ncompleted and skipped `finalizeOutput`. Nothing called it again, so the\nworker never finished and its region hung until the test deadline. That\nis the intermittent `TimeoutException: 1.minutes+30.seconds` in\n`LoopIntegrationSpec`.\n\n```\nBefore:  reader enqueues END -\u003e DP processes END, flag not set yet -\u003e output never finalized -\u003e region hangs\nAfter:   reader enqueues END -\u003e DP processes END, port completed   -\u003e output finalized       -\u003e region completes\n```\n\nTwo related effects of the change:\n\n- The flag could also be set while END was still queued. A worker with a\nsecond materialized input no longer finalizes before that port\u0027s END has\nbeen processed.\n- `startInputPortReaderThreads` uses the same check to skip ports that\nalready completed. The second `StartWorker` of a two-phase region\narrives only after the coordinator has the port\u0027s `PortCompleted`, which\nthe worker sends after processing END. So it skips the same ports as\nbefore.\n- Nothing reads the reader thread\u0027s `finished` flag any more, so it is\nremoved, and it can\u0027t stand in for port completion again. The\nreader-thread tests that read it now check the END_CHANNEL the reader\nenqueues instead.\n\n### Any related issues, documentation, discussions?\n\nCloses #8937. The two `LoopIntegrationSpec` cases added in #8639 hit the\nrace most often; the race itself dates from #3460.\n\n### How was this PR tested?\n\nTests first: the first commit adds the tests and fails on `main`, and\nthe second commit makes them pass.\n\n- `InputManagerSpec`: a materialized port is completed once END has been\nprocessed, even before its reader thread has returned. It is not\ncompleted while END is still queued, even after the thread has returned.\n- `EndChannelHandlerSpec`: when END arrives on a materialized input port\nbefore its reader thread has returned, the worker emits the output\n`FinalizePort` and `FinalizeExecutor`. On `main` it emits only the input\nport\u0027s `FinalizePort`, which is the hang.\n\n```\nsbt \"WorkflowExecutionService/testOnly *InputManagerSpec *EndChannelHandlerSpec *StartHandlerSpec *DataProcessorSpec *EndHandlerSpec *StartChannelHandlerSpec *AssignPortHandlerSpec *DPThreadSpec *WorkerSpec\"\nsbt \"WorkflowExecutionService/scalafmtCheckAll\" \"WorkflowExecutionService/scalafixAll --check\"\n```\n\n`InputPortMaterializationReaderThreadSpec` reads real Iceberg tables.\nLocally only its two cases that don\u0027t need storage ran; CI runs the\nrest.\n\n`LoopIntegrationSpec`, run locally on Windows with the sbt JVM and its\nPython workers pinned to 3 CPUs (affinity mask `0x7`), one case per JVM:\n\n| Case | `main` | This PR |\n|---|---|---|\n| bind a `$i` reference after two branches of the loop body meet again |\n3 of 5 runs hung on the first attempt; 1 also hung on the retry and\nfailed as on CI | 10 of 10 passed on the first attempt, 42–44 s each |\n| bind the inner loop\u0027s variable where it shadows the outer loop\u0027s |\n(fails on CI, see #8937) | 10 of 10 passed on the first attempt, 64–70 s\neach |\n\nUnpinned, the whole spec passes with this PR: 8 of 8 cases, 29–59 s\neach, no retries.\n\n```\nAMBER_TEST_FILTER\u003d STORAGE_ICEBERG_CATALOG_TYPE\u003dpostgres sbt \"WorkflowExecutionService/testOnly *LoopIntegrationSpec -- -z \\\"after two branches of the loop body meet again\\\"\"\nAMBER_TEST_FILTER\u003dintegration-only STORAGE_ICEBERG_CATALOG_TYPE\u003dpostgres sbt \"WorkflowExecutionService/testOnly *LoopIntegrationSpec\"\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "d99fb4d53ce60ebda28187b81df0d828abe9ccc3",
      "tree": "341b7cbbc9ae80b275aba725e84cf230f675ca42",
      "parents": [
        "40ced5bdb399d58aaa0535f5dc886be44a5f64e4"
      ],
      "author": {
        "name": "Mend Renovate",
        "email": "bot@renovateapp.com",
        "time": "Thu Oct 15 02:20:05 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 02:20:05 2026 +0000"
      },
      "message": "chore(deps, agent-service): update dependency @types/bun to v1.4.0 (#7894)\n\nThis PR contains the following updates:\n\n| Package | Change |\n[Age](https://docs.renovatebot.com/merge-confidence/) |\n[Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n|\n[@types/bun](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/bun)\n([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/bun))\n| [`1.3.14` →\n`1.4.0`](https://renovatebot.com/diffs/npm/@types%2fbun/1.3.14/1.4.0) |\n![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fbun/1.4.0?slim\u003dtrue)\n|\n![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fbun/1.3.14/1.4.0?slim\u003dtrue)\n|\n\n---\n\n### Configuration\n\n📅 **Schedule**: (in timezone Etc/UTC)\n\n- Branch creation\n  - \"before 8am on monday\"\n- Automerge\n  - At any time (no schedule defined)\n\n🚦 **Automerge**: Disabled by config. Please merge this manually once you\nare satisfied.\n\n♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the\nrebase/retry checkbox.\n\n🔕 **Ignore**: Close this PR and you won\u0027t be reminded about this update\nagain.\n\n---\n\n- [ ] \u003c!-- rebase-check --\u003eIf you want to rebase/retry this PR, check\nthis box\n\n---\n\nThis PR was generated by [Mend Renovate](https://mend.io/renovate/).\nView the [repository job\nlog](https://developer.mend.io/github/apache/texera).\n\n\u003c!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zOS4wIiwidXBkYXRlZEluVmVyIjoiNDQuMzkuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiZGVwZW5kZW5jaWVzIl19--\u003e\n\n---------\n\nCo-authored-by: Xinyuan Lin \u003cxinyual3@uci.edu\u003e"
    },
    {
      "commit": "40ced5bdb399d58aaa0535f5dc886be44a5f64e4",
      "tree": "17bfdab87a2b96de6901f91c65a603bd7b2243fc",
      "parents": [
        "6a101ad4623dcc81030e298a58341ec4e0d12b16"
      ],
      "author": {
        "name": "Kary Zheng",
        "email": "150742834+kz930@users.noreply.github.com",
        "time": "Thu Oct 15 01:26:57 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 01:26:57 2026 +0000"
      },
      "message": "feat(gui): export a workflow as Python, and read the schema\u0027s constraints in the panel (#8350)\n\n### What changes were proposed in this PR?\n\nThe browser side of the export.\n\nA button on the workflow toolbar asks the compiling service to translate\nthe canvas into a Python script and shows what comes back, with a copy\ncontrol so the script can be taken somewhere that runs it. The\ntranslation is a round trip, so the button disables itself while one is\nin flight, and a workflow the translator cannot express comes back with\na reason rather than an empty modal. The route is added in the two\nplaces a browser reaches the compiling service from: the dev server\u0027s\nproxy and the single-node nginx.\n\nA workflow that fails to compile cannot be executed either, so the run\nbutton reads the compilation state alongside the schema and port\nvalidation it already read. Running to one operator is offered only when\neverything upstream of it compiled too, not only the operator itself.\n\n### Any related issues, documentation, discussions?\n\nPart of #8325, 25 of 27; that issue lists the set in order.\n\nThe property panel\u0027s reading of the schema\u0027s constraints is in #8507.\nThis one stands alone. It touches no Scala, so it compiles and its tests\nrun on their own, and its CI is green today. The endpoint the button\ncalls is added in #8327: until that lands, clicking it reports that the\nrequest failed and nothing else changes, so the order here is a\npreference rather than a constraint.\n\nCloses #8427, the task this change is the whole of.\n\n### What it looks like\n\nThe toolbar without this change, and with it. The new control is the\nsixth, between the download and the info buttons.\n\n\u003cimg width\u003d\"549\" height\u003d\"48\" alt\u003d\"toolbar before\"\nsrc\u003d\"https://github.com/user-attachments/assets/434cd8d5-16ca-4ff1-ad4f-7244656110c3\"\n/\u003e\n\n\u003cimg width\u003d\"549\" height\u003d\"48\" alt\u003d\"toolbar after\"\nsrc\u003d\"https://github.com/user-attachments/assets/f2d3c617-71fa-44f6-ac7f-9cd854ebe36f\"\n/\u003e\n\nClicking it asks the compiling service to translate the canvas and shows\nwhat comes back, with a control that copies the script.\n\n\u003cimg width\u003d\"1354\" height\u003d\"896\" alt\u003d\"the export modal\"\nsrc\u003d\"https://github.com/user-attachments/assets/0b119b15-5ca9-43e8-afd1-098f5fa34f8b\"\n/\u003e\n\n### How was this PR tested?\n\n`yarn --cwd frontend run test:ci`, which is what CI runs; a single spec\nis `yarn --cwd frontend ng test --watch\u003dfalse --include\u003d\u003cpath\u003e`.\n\n`menu.component.spec.ts` covers the three ways the export click can end:\nthe script coming back, the translator refusing the plan, and the\nrequest failing. `context-menu.component.spec.ts` covers the\nexecute-to-here entry under a failed compilation.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Opus 5)\n\n---------\n\nCo-authored-by: Claude Opus 5 (1M context) \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "6a101ad4623dcc81030e298a58341ec4e0d12b16",
      "tree": "ce2ce4a2c47f27c26c3e4974db0052eaa294eb1b",
      "parents": [
        "2351cb856d8f67b3da3ee53f1e72381122ee7cf6"
      ],
      "author": {
        "name": "Kary Zheng",
        "email": "150742834+kz930@users.noreply.github.com",
        "time": "Thu Oct 15 01:21:40 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 01:21:40 2026 +0000"
      },
      "message": "feat(visualization): export the charts that draw over a table\u0027s columns (#8365)\n\n### What changes were proposed in this PR?\n\nSixteen plots whose shape comes from the columns they are pointed at:\nthe\nbar, line and pie, the histograms, the scatter family, the box and\nviolin,\nthe strip and the ECDF, the heat map, the candlestick, the funnel and\nthe\ndot plot.\n\nA line\u0027s series configuration and an error band\u0027s are one type extending\nthe other, so they travel together.\n\n### Any related issues, documentation, discussions?\n\nPart of #8325, 14 of 27; that issue lists the set in order. It needs\n#8327 for the trait, so it does not compile until that lands, and the\nrows these operators add to the verification runner follow with the\nharness rather than as whole new files here.\n\nCloses #8417, the task this change is the whole of.\n\n### How was this PR tested?\n\nEach operator asserts the block it emits in its own spec. Once the\nharness lands, each is also run through the engine and through its\ngenerated script, on every configuration its schema offers, and the two\nanswers compared.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Opus 5)\n\n---------\n\nCo-authored-by: Claude Opus 5 (1M context) \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "2351cb856d8f67b3da3ee53f1e72381122ee7cf6",
      "tree": "cad72d8d012eabca600083138ee0a5a96343f960",
      "parents": [
        "41848581d3343f2a9c0cb3bc483ab1aa65e0049c"
      ],
      "author": {
        "name": "yangzhang75",
        "email": "yangz75@uci.edu",
        "time": "Thu Oct 15 01:21:26 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 01:21:26 2026 +0000"
      },
      "message": "feat(workflow): serve the pinned copy to public viewers (#8575)\n\n### What changes were proposed in this PR?\n\nWith a version pinned, a workflow has two copies. This routes every read\nthat serves a viewer\nwithout granted access through the frozen one.\n\n- **The seam** — `WorkflowAccessResource.hasGrantedAccess(wid, uid)`:\ngranted access, as opposed\nto being able to read a workflow only because it is public. An owner or\na shared user keeps\ntracking the author\u0027s latest, because sharing is not publishing.\nEveryone else is here only\n  because the workflow is public, and gets the public copy.\n- **One copy, not four fields** — `WorkflowPublishService.PublicCopy`\ncarries the name, the\ndescription, the content and the default view together, and\n`publicCopyOf` hands them out as a\ngroup, so no surface can serve the published graph under a title the\nauthor never published, or\n  open a form view over a copy whose content carries no form.\n- **Routed through it** — opening a workflow, the hub\u0027s read of a public\nworkflow, Clone,\nDuplicate, `/workflow_name`, `/workflow_description`, and the size a\nlisting shows.\n- **The revision history is a door into the same room.** Replaying a\nversion folds deltas back\nfrom the author\u0027s *current* content, so listing or checking out versions\nwould hand a public\nviewer the drafts the pin is holding back. `canReadHistory` keeps the\nhistory open to anyone\nwith granted access, and to everyone while nothing is pinned — the\npublic copy is then the\nauthor\u0027s latest and its history is the history of what everyone can\nalready see.\n\n**A workflow that follows the author\u0027s latest — every workflow today —\nis served exactly what it\nis served now.** `publicCopyOf` returns the working copy when nothing is\nfrozen, so with no UI to\npin from yet (that arrives later in the series), nothing anyone can see\nchanges.\n\n### Any related issues, documentation, discussions?\n\nCloses #7939\nPart of #7828. Design discussion: #7128. Builds on #7853, now merged.\n\n### How was this PR tested?\n\n22 new cases in `WorkflowPublishSpec` (54 in the suite, 540 in the\ndashboard package):\n\n- the published version reaching a stranger while the author keeps their\nown working copy;\n- opening a pinned workflow serving the whole copy — its own title,\ndescription and view — and\n  the author still opening everything they have;\n- a collaborator with granted read access tracking the author\u0027s latest\nas they keep editing;\n- clone and duplicate taking the published copy, metadata included,\nwhile a private workflow\nstill clones its working copy and a copy starts with no publish state of\nits own;\n- the size each case reports;\n- the revision history: a public viewer is refused while a pin is in\nplace, a collaborator is\nnot, and a public workflow with nothing pinned keeps the history it has\ntoday;\n- a public copy of a workflow that is not public being refused rather\nthan falling through.\n\nThe history guard was checked by mutation: restoring `hasReadAccess`\nturns the leak case red,\nand the case was written from a reproduction — a stranger retrieving a\nversion of a pinned\nworkflow and getting back an unpublished draft.\n\n`scalafmtCheckAll` clean.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Opus 5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Claude Opus 5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "41848581d3343f2a9c0cb3bc483ab1aa65e0049c",
      "tree": "ecbc2d292c2f2ffbdbe619622274b17c6ce3ccdf",
      "parents": [
        "61d435d25109d29385d8d7ce6d9a03f099c18c2e"
      ],
      "author": {
        "name": "Tanishq Gandhi",
        "email": "56472134+tanishqgandhi1908@users.noreply.github.com",
        "time": "Wed Oct 14 23:50:22 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 23:50:22 2026 +0000"
      },
      "message": "fix(frontend): refresh the Datasets and Models list view after revoking your own access (#8965)\n\n### What changes were proposed in this PR?\n\nIn list view, the Datasets and Models pages bound the results list’s\n(refresh) to ngAfterViewInit(), which only subscribed to the user stream\nagain. The search it triggered saw the same filters and sort and\nreturned early, so the list was never reloaded. After revoking your own\naccess, the item stayed listed until a page reload, and each refresh\nadded another subscription that was never removed.\n\nBoth pages now bind (refresh)\u003d\"search(true)\", the forced search card\nview already uses.\n\nBefore: after revoking your own access to sales-2026, it is still\nlisted:\n\n\u003cimg width\u003d\"1440\" height\u003d\"900\" alt\u003d\"before-2-revoke-own-access\"\nsrc\u003d\"https://github.com/user-attachments/assets/0bd7c55a-a538-43ca-885f-7935f877f67a\"\n/\u003e\n\n\u003cimg width\u003d\"1440\" height\u003d\"900\" alt\u003d\"before-3-row-still-listed\"\nsrc\u003d\"https://github.com/user-attachments/assets/7a1a79ad-99fb-4972-8ca3-2b97762c740d\"\n/\u003e\n\nAfter: the item disappears right away on both pages:\n\n\u003cimg width\u003d\"1440\" height\u003d\"900\" alt\u003d\"after-2-datasets-row-gone\"\nsrc\u003d\"https://github.com/user-attachments/assets/2be72235-895e-457f-ba8d-1d70092d5ce0\"\n/\u003e\n\n\u003cimg width\u003d\"1440\" height\u003d\"900\" alt\u003d\"after-4-models-row-gone\"\nsrc\u003d\"https://github.com/user-attachments/assets/749ff178-a843-4ce5-9087-2c91feecace8\"\n/\u003e\n\n### Any related issues, documentation, discussions?\nCloses #8964\n\n### How was this PR tested?\n\nAdded a case to each of user-dataset.component.spec.ts and\nuser-model.component.spec.ts: a refresh from the results list runs a\nforced search. Both fail without the fix.\n\ncd frontend\nyarn ng test --watch\u003dfalse --include\u003d\u0027**/user-dataset.component.spec.ts\u0027\n--include\u003d\u0027**/user-model.component.spec.ts\u0027\nTests  65 passed (65)\n\nAlso checked against a local stack: as a WRITE collaborator in list\nview, revoking your own access removes the dataset or model from the\nlist on both pages.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\nCo-authored-by: Xuan Gu \u003c162244362+xuang7@users.noreply.github.com\u003e"
    },
    {
      "commit": "61d435d25109d29385d8d7ce6d9a03f099c18c2e",
      "tree": "7943f3ee6cfc76a19cb1866f62b5793ed7946cfc",
      "parents": [
        "ed724ebede6dba46f778e2adfd471ee07dcc251e"
      ],
      "author": {
        "name": "Prateek Ganigi",
        "email": "91584519+PG1204@users.noreply.github.com",
        "time": "Wed Oct 14 23:49:01 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 23:49:01 2026 +0000"
      },
      "message": "fix(workflow-operator): type-check provider values in the audio response parse (#8872)\n\n### What changes were proposed in this PR?\n\n`AudioTaskCodegen.parsePython` used whatever the provider returned\nwithout checking its type, so a malformed but valid-JSON 200 produced a\ncorrupt or non-string value in the result column instead of falling back\nto the body. A null `b64_json` became the literal\n`data:audio/mpeg;base64,None`; a numeric `url` was handed to\n`_url_to_data_url`; a numeric `text` was written to the cell as a\nnumber.\n\nEach value is now type-checked before use: `b64_json` must be a\nnon-empty string, `url` must be a string starting with `http` — the\nguard the sibling `output` branch already applied, `data` must be a list\nbefore being indexed, and `text` / `generated_text` must be strings.\nAnything else falls through to `json.dumps(body)`, which is what the\nbranch already did for unrecognised shapes.\n\nReading `text` and `generated_text` independently also fixes a smaller\nbug: a null `text` previously masked a valid `generated_text`.\n\nNot addressed: a `b64_json` that is a string but not valid base64 still\nyields an unplayable data URL. Detecting that requires decoding the\nvalue on every row, and corrupt-but-well-formed base64 would pass\nregardless, so the browser\u0027s rejection is the same either way.\n\n### Any related issues?\n\nCloses #8869\n\n### How was this PR tested?\n\nWritten test-first: four tests were added to `AudioTaskCodegenSpec` for\nthe `b64_json`, `url`, `data` and `text` guards, and they fail against\nthe current parse. The suite is at 158 tests,\n`PythonCodeRawInvalidTextSpec` py-compiles all 117 operators, and\n`scalafmtCheck` and `scalafix --check` are clean. One existing assertion\nwas updated where it pinned the old indexing form.\n\nThe generated parser was also run against each malformed shape: every\ncase in the issue now returns the serialized body, valid URL and base64\nenvelopes still resolve as before, and a null `text` alongside a valid\n`generated_text` now returns the latter.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nYes, this PR was co-authored with Claude in compliance with ASF policy.\n\nCo-authored-by: Xuan Gu \u003c162244362+xuang7@users.noreply.github.com\u003e"
    },
    {
      "commit": "ed724ebede6dba46f778e2adfd471ee07dcc251e",
      "tree": "93141953beaa79ac929985019233600ff1476206",
      "parents": [
        "ee1deb75fb16f0ead6c715fa9e52465157f85c51"
      ],
      "author": {
        "name": "Prateek Ganigi",
        "email": "91584519+PG1204@users.noreply.github.com",
        "time": "Wed Oct 14 23:45:58 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 23:45:58 2026 +0000"
      },
      "message": "fix(workflow-operator): require b64_json to be a string before building a data URL (#8885)\n\n### What changes were proposed in this PR?\n\n`ImageTaskCodegen.parsePython`\u0027s `image-to-image` branch built a data\nURL from the provider\u0027s `b64_json` without checking it, so a malformed\nbut valid-JSON 200 put an unrenderable value in the result column, a\nnull field became the literal `data:image/png;base64,None`, with nothing\nto indicate why the image was blank.\n\n`b64_json` must now be a non-empty string; anything else falls through\nto `json.dumps(body)`, which is what the branch already did for\nunrecognised shapes.\n\nScoped deliberately to `b64_json`, matching the issue. The sibling `url`\nlookups in the same branch have a comparable gap and are left for a\nseparate issue.\n\nNot addressed: a `b64_json` that is a string but not valid base64 still\nyields an unrenderable data URL. Detecting that means decoding the value\non every row, and corrupt-but-well-formed base64 would pass regardless,\nso the browser\u0027s rejection is unchanged either way. Same reasoning as\n#8872.\n\n### Any related issues?\n\nCloses #8870\n\n### How was this PR tested?\n\nWritten test-first: a test asserting the string guard was added to\n`ImageTaskCodegenSpec` and fails against the current parse. The suite is\nat 155 tests, `PythonCodeRawInvalidTextSpec` py-compiles all 117\noperators, and `scalafmtCheck` and `scalafix --check` are clean.\n\nThe generated parser was also run directly: a null or numeric `b64_json`\nnow returns the serialized body, and a valid base64 payload still\nproduces the same data URL as before.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nYes, this PR was co-authored with Claude in compliance with ASF policy.\n\nCo-authored-by: Xuan Gu \u003c162244362+xuang7@users.noreply.github.com\u003e"
    },
    {
      "commit": "ee1deb75fb16f0ead6c715fa9e52465157f85c51",
      "tree": "e8a31724df739ec753bf50c9b22af4434a532754",
      "parents": [
        "64818bc0012fd779875c3e9f6861a1cf1d9a6ab0"
      ],
      "author": {
        "name": "Meng Wang",
        "email": "mengw15@uci.edu",
        "time": "Wed Oct 14 23:39:19 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 23:39:19 2026 +0000"
      },
      "message": "fix(frontend): replace the Spider-Man sample image with an original drawing (#8987)\n\n### What changes were proposed in this PR?\n\nPer #8983, `frontend/src/assets/sample-image.png`, the picture shown in\nthe Hugging Face operator\u0027s task preview, depicts Spider-Man and has no\nrecorded source. This replaces it with an original flat illustration\ndrawn with PIL for this PR: a person leaping between two rooftops above\na city skyline at sunset. The image is project-made, so it needs no\n`LICENSE` entry. The new file is a real PNG; the old one was a JPEG with\na `.png` extension.\n\nThe preview captions and labels that described the old picture now match\nthe new one, and the token-classification example no longer uses \"Peter\nParker\".\n\n`sample-audio.wav` and `sample-video.mp4` are unchanged. Their author\nconfirmed in the review of #5568 that they are self-created.\n\n### Any related issues, documentation, discussions?\n\nCloses #8983. Part of #8800.\n\n### How was this PR tested?\n\nUpdated the one spec assertion on the image-classification labels.\n`operator-property-edit-frame.component.spec.ts` passes locally and\nfails with the old value. A repo-wide grep finds no remaining Spider-Man\nreferences.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (claude-opus-5-5)"
    },
    {
      "commit": "64818bc0012fd779875c3e9f6861a1cf1d9a6ab0",
      "tree": "cfd9452d22a9ea72fd1813b7e25f7ec0c245fe61",
      "parents": [
        "74c23f1f317b867db89ca96118485fd5628990da"
      ],
      "author": {
        "name": "carloea2",
        "email": "carloea2@uci.edu",
        "time": "Wed Oct 14 23:16:45 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 23:16:45 2026 +0000"
      },
      "message": "feat(pyamber): resolve unset input port zero (#8264)\n\n### What changes were proposed in this PR?\n\nNormalize unset protobuf port fields before the dictionary lookup,\nkeeping lookup O(1). This lets an unset port-zero identity find the\nregistered port and preserves a clear KeyError for unknown ports.\n\n### Any related issues, documentation, discussions?\n\nCloses #8263\n\n### How was this PR tested?\n\nThe untouched live probe showed equal port-zero identities with\ndifferent hashes and raised `KeyError`. After the fix it reported\n`lookup_succeeded\u003dTrue` with the hashes still different.\n\n`C:\\Users\\carlo\\texera\\texera\\.venv312\\Scripts\\python.exe -c \"import\nsys,pytest;\nsys.path[:0]\u003d[r\u0027C:\\Users\\carlo\\texera\\texera-worktrees\\investigate-bug68\\amber\\src\\main\\python\u0027,r\u0027C:\\Users\\carlo\\texera\\texera\\amber\\src\\main\\python\u0027];\nraise\nSystemExit(pytest.main([r\u0027amber/src/test/python/core/architecture/packaging/test_input_manager.py\u0027,\u0027-q\u0027,\u0027-p\u0027,\u0027no:cacheprovider\u0027]))\"`\n\n`C:\\Users\\carlo\\texera\\texera\\.venv312\\Scripts\\ruff.exe check\namber/src/main/python amber/src/test/python`\n\n`C:\\Users\\carlo\\texera\\texera\\.venv312\\Scripts\\ruff.exe format --check\namber/src/main/python/core/architecture/packaging/input_manager.py\namber/src/test/python/core/architecture/packaging/test_input_manager.py`\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Codex"
    },
    {
      "commit": "74c23f1f317b867db89ca96118485fd5628990da",
      "tree": "cf194d1acfc967a09d61704f463d1953f4644693",
      "parents": [
        "6a29c59c6312da95826b269fca2a6a14006fb34a"
      ],
      "author": {
        "name": "Prateek Ganigi",
        "email": "91584519+PG1204@users.noreply.github.com",
        "time": "Wed Oct 14 22:58:34 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 22:58:34 2026 +0000"
      },
      "message": "fix(amber, frontend): inline Hugging Face audio uploads as data URLs instead of a server temp file (#7790)\n\n### What changes were proposed in this PR?\n\nThe Hugging Face operator\u0027s **Audio Upload** widget now captures the\nselected file entirely in the browser and stores it as a self-contained\n`data:audio/…;base64,…` URL, instead of relying on a server-side temp\nfile.\n\nPreviously the upload ended up as a server-side temp file reference. In\na distributed deployment the Python worker that runs the inference is a\ndifferent process than the web server, so it could not read that path,\nthe uploaded audio never reached the model. The widget now reads the\nfile client-side (`FileReader.readAsDataURL`) and stores the data URL as\nthe operator\u0027s `audioInput` value, so it travels inside the workflow\nJSON and the generated Python\u0027s `_read_audio_input` decodes it directly.\nThis mirrors the existing **Image Upload** widget\u0027s data-URL approach.\n\nA 25 MB size cap and input guards (\"Choose an audio file.\", \"Audio file\nis too large (max 25 MB).\", \"Could not read this audio file.\") are added\nsince base64 inlining bloats the workflow JSON, along with an inline\n`\u003caudio\u003e` preview and a Clear button.\n\n\u003cimg width\u003d\"1275\" height\u003d\"549\" alt\u003d\"image\"\nsrc\u003d\"https://github.com/user-attachments/assets/2c43240d-86a8-4b64-9063-89a568a5444a\"\n/\u003e\n\n### Any related issues?\n\nCloses #6968 \n\n### How was this PR tested?\n\nFrontend unit tests, plus a manual UI check: on the\n`automatic-speech-recognition` task, selecting an audio file shows an\ninline player and stores the value as a `data:audio/…;base64,…` URL\n(verified in the console). The size cap, invalid-file guard, and Clear\nbutton all behave as expected.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nYes, this PR was co-authored with Claude in compliance with ASF policy.\n\n---------\n\nCo-authored-by: Xuan Gu \u003c162244362+xuang7@users.noreply.github.com\u003e"
    },
    {
      "commit": "6a29c59c6312da95826b269fca2a6a14006fb34a",
      "tree": "ebcbe9ac7a6ece10219f36671a4dd5e567fee689",
      "parents": [
        "9cf43f2de96c9a1a8a93579835b8b7de66243d80"
      ],
      "author": {
        "name": "carloea2",
        "email": "carloea2@uci.edu",
        "time": "Mon Oct 12 22:28:20 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 12 22:28:20 2026 +0000"
      },
      "message": "feat(pyamber): reject non-string state keys (#8959)\n\n### What changes were proposed in this PR?\n\nReject non-string state dictionary keys before serialization. Converting\nboth 1 and \"1\" to the same JSON key silently loses a value. This\nintroduces an explicit TypeError for non-string keys, including nested\nmappings.\n\n### Any related issues, documentation, discussions?\n\nCloses #8215\n\nReplaces #8216, which the stale bot closed. The original PR cannot be\nreopened by this account.\n\n### How was this PR tested?\n\nTested on freshly fetched main at\nd27b7b49877bcc52d80602e57f5b0e5f86291736 with Python 3.12 on Windows.\nThe regression failed before the source change and passed after it.\n\nFrom the amber directory, with generated protobuf bindings available on\nPYTHONPATH:\n\n```text\npython -m pytest src/test/python/core/models/test_state.py::TestState::test_to_json_rejects_non_string_keys -q --tb\u003dline -p no:cacheprovider\npython -m pytest src/test/python/core/models src/test/python/core/architecture/sendsemantics/test_partitioners.py --deselect src/test/python/core/models/test_tuple.py::TestTuple::test_hash -q --tb\u003dline -p no:cacheprovider\nruff check src/main/python src/test/python\nruff format --check src/main/python src/test/python\n```\n\nThe broader suites passed 351 tests with one expected failure. Ruff lint\nand formatting passed for all 216 Python files. The existing Windows\npre-epoch hash fixture was deselected; the new hash regressions were run\nseparately.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Codex (GPT-6)"
    },
    {
      "commit": "9cf43f2de96c9a1a8a93579835b8b7de66243d80",
      "tree": "2a8d271e6ed7fe95410cd97af1afe9793c7c23ea",
      "parents": [
        "fd25ce83c397021c42bd926d587c5d492a617475"
      ],
      "author": {
        "name": "Mend Renovate",
        "email": "bot@renovateapp.com",
        "time": "Mon Oct 12 03:53:21 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 12 03:53:21 2026 +0000"
      },
      "message": "chore(deps, pyright-language-service): update pyright-language-service minor updates (#8954)\n\nThis PR contains the following updates:\n\n| Package | Change |\n[Age](https://docs.renovatebot.com/merge-confidence/) |\n[Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n|\n[@types/node](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)\n([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))\n| [`26.2.0` →\n`26.6.5`](https://renovatebot.com/diffs/npm/@types%2fnode/26.2.0/26.6.5)\n|\n![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/26.6.5?slim\u003dtrue)\n|\n![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/26.2.0/26.6.5?slim\u003dtrue)\n|\n| [express](https://expressjs.com/)\n([source](https://redirect.github.com/expressjs/express)) | [`5.2.1` →\n`5.3.0`](https://renovatebot.com/diffs/npm/express/5.2.1/5.3.0) |\n![age](https://developer.mend.io/api/mc/badges/age/npm/express/5.3.0?slim\u003dtrue)\n|\n![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/express/5.2.1/5.3.0?slim\u003dtrue)\n|\n| [ws](https://redirect.github.com/websockets/ws) | [`8.21.3` →\n`8.22.0`](https://renovatebot.com/diffs/npm/ws/8.21.3/8.22.0) |\n![age](https://developer.mend.io/api/mc/badges/age/npm/ws/8.22.0?slim\u003dtrue)\n|\n![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/ws/8.21.3/8.22.0?slim\u003dtrue)\n|\n\n---\n\n### Release Notes\n\n\u003cdetails\u003e\n\u003csummary\u003eexpressjs/express (express)\u003c/summary\u003e\n\n###\n[`v5.3.0`](https://redirect.github.com/expressjs/express/blob/HEAD/History.md#530)\n\n[Compare\nSource](https://redirect.github.com/expressjs/express/compare/v5.2.1...v5.3.0)\n\n\\\u003d\u003d\u003d\u003d\u003d\n\n#### 🐞 Bug fixes\n\n- Fixed HTTP header conflict between Content-Length and\nTransfer-Encoding in res.send - by\n[@\u0026#8203;YuryShkoda](https://redirect.github.com/YuryShkoda) in\n[#\u0026#8203;4893](https://redirect.github.com/expressjs/express/pull/4893)\n\nFixed the behavior of `res.send()` to prevent conflicts between\n`Content-Length` and `Transfer-Encoding` HTTP headers in responses. The\n`Content-Length` header in `res.send()` is now only added when a\n`Transfer-Encoding` header is not present, complying with the HTTP\nspecification that states both headers should not coexist in the same\nresponse. ETag generation is unaffected by the presence of a\n`Transfer-Encoding` header - by\n[@\u0026#8203;cuishuang](https://redirect.github.com/cuishuang) in\n[#\u0026#8203;7459](https://redirect.github.com/expressjs/express/pull/7459)\n\n* Upgrade `qs` to `^6.16.0`, which fixes\n[CVE-2026-2391](https://www.cve.org/CVERecord?id\u003dCVE-2026-2391)\n([GHSA-w7fw-mjwx-w883](https://redirect.github.com/ljharb/qs/security/advisories/GHSA-w7fw-mjwx-w883)),\n[CVE-2026-82417](https://www.cve.org/CVERecord?id\u003dCVE-2026-82417)\n([GHSA-4mjr-xmp4-gh2g](https://redirect.github.com/advisories/GHSA-4mjr-xmp4-gh2g))\nand [CVE-2026-82562](https://www.cve.org/CVERecord?id\u003dCVE-2026-82562)\n([GHSA-x5fp-wj9c-mxmx](https://redirect.github.com/advisories/GHSA-x5fp-wj9c-mxmx)):\n`arrayLimit` bypasses in comma parsing and a denial of service via an\nattacker-controlled `isBuffer` - by\n[@\u0026#8203;davetashner](https://redirect.github.com/davetashner) in\n[#\u0026#8203;7057](https://redirect.github.com/expressjs/express/pull/7057)\nand\n[#\u0026#8203;7478](https://redirect.github.com/expressjs/express/pull/7478),\nand [@\u0026#8203;cyphercodes](https://redirect.github.com/cyphercodes) in\n[#\u0026#8203;7305](https://redirect.github.com/expressjs/express/pull/7305)\n\n* Upgrade `proxy-addr` to `^2.0.8`, which fixes\n[CVE-2026-90711](https://www.cve.org/CVERecord?id\u003dCVE-2026-90711) - by\n[@\u0026#8203;lazerg](https://redirect.github.com/lazerg) in\n[#\u0026#8203;7474](https://redirect.github.com/expressjs/express/pull/7474)\n\n#### 🚀 Improvements\n\n- Allow conditional revalidation for QUERY requests. `req.fresh`\npreviously only validated freshness for GET and HEAD requests, so QUERY\nresponses never returned 304 despite a matching validator. Since QUERY\nis a safe, idempotent, and cacheable method that supports conditional\nrequests, it is now included in the freshness check - by\n[@\u0026#8203;Cherry](https://redirect.github.com/Cherry) in\n[#\u0026#8203;7366](https://redirect.github.com/expressjs/express/pull/7366)\n\n  ```js\n  // QUERY /reports with If-None-Match: \"12345\"\n  app.query(\u0027/reports\u0027, (req, res) \u003d\u003e {\n    res.set(\u0027ETag\u0027, \u0027\"12345\"\u0027);\n    res.send(results); // now responds 304 Not Modified\n  });\n  ```\n\n- Improve HTML structure in `res.redirect()` responses when HTML format\nis accepted by adding `\u003c!DOCTYPE html\u003e`, `\u003ctitle\u003e`, and `\u003cbody\u003e` tags\nfor better browser compatibility - by\n[@\u0026#8203;Bernice55231](https://redirect.github.com/Bernice55231) in\n[#\u0026#8203;5167](https://redirect.github.com/expressjs/express/pull/5167)\n\n- When calling `app.render` with options set to null, the locals object\nis handled correctly, preventing unexpected errors and making the method\nbehave the same as when options is omitted or an empty object is passed\n- by [AkaHarshit](https://redirect.github.com/AkaHarshit) in\n[#\u0026#8203;6903](https://redirect.github.com/expressjs/express/pull/6903)\n\n  ```js\n  app.render(\u0027index\u0027, null, callback); // now works as expected\n  ```\n\n- Upgrade `content-type` to `^2.0.0`, bringing a faster parser (\\~1.5x\nquicker `Content-Type` parsing/formatting in `res.send()`) along with a\nbehavior change: `res.send()` now keeps any existing parameters when\nadding the charset and no longer throws on a `Content-Type` that fails\nto parse. `type-is` is upgraded to `^2.1.0` as part of the same change -\nby [@\u0026#8203;blakeembrey](https://redirect.github.com/blakeembrey) in\n[#\u0026#8203;7234](https://redirect.github.com/expressjs/express/pull/7234)\n\n  ```js\n  res.set(\u0027Content-Type\u0027, \u0027text/plain; foo\u003dbar\u0027).send(\u0027hey\u0027);\n  // -\u003e Content-Type: text/plain; foo\u003dbar; charset\u003dutf-8\n  ```\n\n- The default error handler now logs the full error object instead of\nonly its stack trace, so nested details such as `Error.cause` and\nlibrary-specific properties (e.g. Sequelize\u0027s `parent`/`original`) are\nno longer swallowed - by\n[@\u0026#8203;Nitin-Mohapatra](https://redirect.github.com/Nitin-Mohapatra)\nin\n[#\u0026#8203;6464](https://redirect.github.com/expressjs/express/pull/6464)\n\n- Upgrade `content-disposition` to `^2.0.1`, which changes the\n`Content-Disposition` header emitted by `res.download()`,\n`res.attachment()`, and `res.sendFile()`: file names that are valid HTTP\ntokens are no longer wrapped in quotes. This is equivalent per RFC 6266,\nbut applications asserting on the exact header bytes should update their\nexpectations - by\n[@\u0026#8203;blakeembrey](https://redirect.github.com/blakeembrey) in\n[#\u0026#8203;7233](https://redirect.github.com/expressjs/express/pull/7233)\n\n  ```js\n  res.attachment(\u0027user.html\u0027);\n  // before -\u003e Content-Disposition: attachment; filename\u003d\"user.html\"\n  // after  -\u003e Content-Disposition: attachment; filename\u003duser.html\n  ```\n\n- Upgrade `body-parser` to `^2.3.0`, which fixes\n[CVE-2026-12590](https://www.cve.org/CVERecord?id\u003dCVE-2026-12590)\n([GHSA-v422-hmwv-36x6](https://redirect.github.com/expressjs/body-parser/security/advisories/GHSA-v422-hmwv-36x6)):\nan invalid `limit` option value caused request body size enforcement to\nbe silently disabled (fail-open), allowing a denial of service via\narbitrarily large payloads. Invalid `limit` values now throw at parser\ninitialization instead of being ignored - by\n[@\u0026#8203;Mayvis](https://redirect.github.com/Mayvis) in\n[#\u0026#8203;7390](https://redirect.github.com/expressjs/express/pull/7390)\n\n#### ⚡ Performance\n\n- Avoid duplicate Content-Type header processing in `res.send()` when\nsending string responses without an explicit Content-Type header - by\n[@\u0026#8203;bjohansebas](https://redirect.github.com/bjohansebas) in\n[#\u0026#8203;6991](https://redirect.github.com/expressjs/express/pull/6991)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003ewebsockets/ws (ws)\u003c/summary\u003e\n\n###\n[`v8.22.0`](https://redirect.github.com/websockets/ws/releases/tag/8.22.0)\n\n[Compare\nSource](https://redirect.github.com/websockets/ws/compare/8.21.3...8.22.0)\n\n### Features\n\n- Introduced the `protocols` option\n([`8b918b0`](https://redirect.github.com/websockets/ws/commit/8b918b01)).\n\n### Bug fixes\n\n- Calling `websocket.close()` with invalid arguments no longer\ntransitions the\nstate to `WebSocket.CLOSING`\n([#\u0026#8203;2337](https://redirect.github.com/websockets/ws/issues/2337)).\n\n\u003c/details\u003e\n\n---\n\n### Configuration\n\n📅 **Schedule**: (in timezone Etc/UTC)\n\n- Branch creation\n  - \"before 8am on monday\"\n- Automerge\n  - At any time (no schedule defined)\n\n🚦 **Automerge**: Disabled by config. Please merge this manually once you\nare satisfied.\n\n♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the\nrebase/retry checkbox.\n\n👻 **Immortal**: This PR will be recreated if closed unmerged. Get\n[config\nhelp](https://redirect.github.com/renovatebot/renovate/discussions) if\nthat\u0027s undesired.\n\n---\n\n- [ ] \u003c!-- rebase-check --\u003eIf you want to rebase/retry this PR, check\nthis box\n\n---\n\nThis PR was generated by [Mend Renovate](https://mend.io/renovate/).\nView the [repository job\nlog](https://developer.mend.io/github/apache/texera).\n\n\u003c!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMzQuMSIsInVwZGF0ZWRJblZlciI6IjQ0LjEzNC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0\u003d--\u003e"
    },
    {
      "commit": "fd25ce83c397021c42bd926d587c5d492a617475",
      "tree": "21ddb6c9cc4d9d60d5b1b544ccc9b9e6530934b9",
      "parents": [
        "87eaf5c109d85d18a7f8e2729e23a9c059c18d8a"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Mon Oct 12 03:25:27 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 12 03:25:27 2026 +0000"
      },
      "message": "refactor(services): use the shared request-logging filter and SQL-state constant (#7796)\n\n### What changes were proposed in this PR?\n\nTwo places where a shared helper already existed but a local copy or\nliteral was used instead. **9 insertions, 27 deletions.**\n\n**1. `WorkflowCompilingService` now calls the shared\n`RequestLoggingFilter`.** It was the only Dropwizard-4 service still\ninlining its own anonymous request-logging filter; the other five\n(access-control, computing-unit-managing, config, file,\nnotebook-migration) all call\n`RequestLoggingFilter.register(environment.getApplicationContext)` at\nexactly this point.\n\nThe two implementations were compared line by line before swapping, not\nassumed equivalent. Normalising fully-qualified prefixes and the\nlogger\u0027s local name, every observable matches: logger name\n`\"org.eclipse.jetty.server.RequestLog\"`, the `isInfoEnabled` guard, the\nsame access-log format string, url pattern `\"/*\"`, and\n`EnumSet.allOf(classOf[DispatcherType])`. The inline copy also sat\nimmediately after `RoleAnnotationEnforcer.enforce`, which is exactly\nwhere the siblings place the `register` call — so this is a body-only\nreplacement.\n\n**2. Four sites now use `SqlStates.UNIQUE_VIOLATION` instead of the\nliteral `\"23505\"`.**\n\n| Site | Was |\n|---|---|\n| `PveResource.scala:110`, `:148` | `e.sqlState() \u003d\u003d \"23505\"` |\n| `NotebookMigrationResource.scala:404` | `e.sqlState \u003d\u003d \"23505\"` |\n| `JupyterProvisioner.scala:168` | `e.sqlState \u003d\u003d \"23505\"` |\n\nBoth modules can already see `common/dao`: `NotebookMigrationService`\nhas a direct DAO dependency, and amber reaches it transitively (`Auth →\nDAO`, and `WorkflowCompiler → WorkflowOperator → WorkflowCore → DAO`).\nNo build change was needed. The constant was already in use by\n`ExternalAuthProvisioner`, `LocalAuthProvisioner` and `ResourceNaming`.\n\nThe remaining `23505` occurrences are CSV test fixtures, a `yarn.lock`\nchecksum, `SqlStates.scala` itself, and three comments that explain what\nthe code means — those are left alone.\n\n\u003e **Updated after merging `main`.** The `DatasetResource.scala` site\noriginally in this PR is gone: `main` (#7760) moved that check into\n`ResourceNaming.failOnDuplicateName`, which already uses\n`SqlStates.UNIQUE_VIOLATION`, so `DatasetResource.scala` is now\nidentical to `main`. `main` also added a new literal in\n`JupyterProvisioner.register` (#8032), which this PR now converts as\nwell.\n\n### amber\u0027s two inline copies are deliberately untouched\n\nWorth recording so they are not \"fixed\" later: amber\u0027s remaining inline\nfilters **cannot** use the shared one. They are `javax.servlet`, because\namber pins Jetty 9.4.20, while `RequestLoggingFilter` is\n`jakarta.servlet`. Their existing TODO — replace once Dropwizard is\nupgraded — is accurate, and this PR does not touch them.\n\n### Verification\n\nRe-run on the branch after merging `main`:\n\n- `WorkflowCompilingService/test`: **5 suites, 55 tests, 0 failures.**\nThis matters because `WorkflowCompilingServiceRunSpec` has cases\nasserting the filter\u0027s registration, its dispatch set, and that it\nforwards the request while logging one access line. They read the filter\nback out of the captured `FilterHolder` rather than by class, so they\nsurvived the swap unchanged — and they are what confirms the shared\nfilter behaves identically in place.\n- `NotebookMigrationService/test`: **6 suites, 123 tests, 0 failures.**\n`NotebookMigrationResourceSpec` drives a real unique-constraint\nviolation against embedded Postgres, and its \"keep the winning row when\ntwo requests provision at once\" case exercises the `JupyterProvisioner`\nrace path.\n- `PveResourceSpec` fails the same 6 tests **both with and without this\nchange** (45 succeeded / 6 failed / 1 canceled either way, verified by\nswapping in `main`\u0027s `PveResource.scala` and re-running; identical\nfailing set). All 6 are `PveManager` venv/pip cases that are\npre-existing on this machine; none touch the `23505` → 409 paths.\n- `scalafmtCheckAll` and `scalafixAll --check` pass for\n`WorkflowCompilingService`, `NotebookMigrationService`, `FileService`\nand `WorkflowExecutionService`; no imports were left orphaned\n(`FilterHolder` removed, `RequestLoggingFilter` added).\n\n### Any related issues, documentation, discussions?\n\nCloses #7792\n\n### How was this PR tested?\n\n```\nsbt \"WorkflowCompilingService/test\" \"NotebookMigrationService/test\" \"WorkflowExecutionService/testOnly org.apache.texera.web.resource.pythonvirtualenvironment.PveResourceSpec\"\n```\n\n```\n[info] Tests: succeeded 55, failed 0, canceled 0, ignored 0, pending 0\n[info] Tests: succeeded 123, failed 0, canceled 0, ignored 0, pending 0\n[info] Tests: succeeded 45, failed 6, canceled 1, ignored 0, pending 0   (identical on main)\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Opus 5)"
    },
    {
      "commit": "87eaf5c109d85d18a7f8e2729e23a9c059c18d8a",
      "tree": "50b65e6fd8a31bc3d700a7fec7ddcfcbe429c1c7",
      "parents": [
        "a182a23e31f08e4f14d0d0beb405feb84f1e0431"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Mon Oct 12 03:24:20 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 12 03:24:20 2026 +0000"
      },
      "message": "refactor(frontend): remove the unused getCover (#8924)\n\n### What changes were proposed in this PR?\n\nRemoves `WorkflowCoverService.getCover`, which no production code has\ncalled since covers started arriving on the search and list responses.\nIt also drops the `of` / `catchError` / `map` imports that only\n`getCover` used. **+6/−31 lines.** There is no behaviour change.\n`setCoverFromFile` and `clearCover`, the service\u0027s live methods, stay.\n\nSpec changes:\n\n- **`workflow-cover.service.spec.ts`:** the two `getCover` cases are\ndeleted.\n- **`card-item.component.spec.ts`:** the `getCover` mock member is\ndropped. The two \"use the stored cover\" / \"fall back to the default\nimage\" cases keep their assertions. Their\n`expect(getCover).not.toHaveBeenCalled()` line was #6280\u0027s guard against\na per-card cover fetch, so it is replaced with an HTTP-level\n`expectNone` on `/cover`. That keeps the guard without naming a method\nthat no longer exists.\n- **`hub-search-result.component.spec.ts`:** the mock member is dropped.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #5704 (2026-07-04), \"feat(dashboard): add custom\ncover image for workflow cards\". Each card called it to load its cover |\n| **Usage removed by** | #6280 (2026-07-13), \"fix(workflow): include\ncoverImage in search and list API responses\". It fixed the N+1 fetch by\nputting the cover on the entry and deleted the card\u0027s call |\n\nIt has been unused for nearly three months.\n\n### Any related issues, documentation, discussions?\n\nCloses #8923\n\n### How was this PR tested?\n\nNo new tests. #6280\u0027s no-per-card-fetch guard is kept, now as an\nHTTP-level assertion.\n\nFrom `frontend/`:\n\n- `npx ng test --watch\u003dfalse --include\u003d\u0027**/card-item.component.spec.ts\u0027\n--include\u003d\u0027**/workflow-cover.service.spec.ts\u0027\n--include\u003d\u0027**/hub-search-result.component.spec.ts\u0027`: 3 files, 128 tests,\nall pass.\n- `yarn format:ci`: clean.\n- `npx ng build`: success.\n\nTo re-check:\n\n```\ngit grep -n -w \"getCover\" -- frontend   # no hits\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "a182a23e31f08e4f14d0d0beb405feb84f1e0431",
      "tree": "d46f318e969bafd21f959c574418bc72e8c3ee91",
      "parents": [
        "d27b7b49877bcc52d80602e57f5b0e5f86291736"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Mon Oct 12 03:23:08 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 12 03:23:08 2026 +0000"
      },
      "message": "refactor(frontend): remove unused dictionary URL constants (#8922)\n\n### What changes were proposed in this PR?\n\nRemoves two module-level constants from `operator-metadata.service.ts`\nthat nothing reads: `addDictionaryAPIAddress` and\n`getDictionaryAPIAddress`. **−3 lines.** There is no behaviour change.\nThe constants aren\u0027t exported, their URL strings\n(`/api/resources/dictionary/`, `/api/upload/dictionary/`) appear nowhere\nelse, and the backend has no route at either path.\n`OPERATOR_METADATA_ENDPOINT`, which the service does use, stays.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #696 (merged 2019-06-07), \"Add saved project and\ndictionary upload components in user panel\" |\n| **Usage removed by** | **never used**. No line has ever read either\nconstant. Later removals of similar dictionary URLs (e.g. in\n`user-dictionary.service.ts`) were different constants |\n\nThey have been unused for over six years.\n\n### Any related issues, documentation, discussions?\n\nCloses #8921\n\n### How was this PR tested?\n\nNo new tests; nothing referenced the constants.\n\nFrom `frontend/`:\n\n- `npx ng test --watch\u003dfalse`, covering\n`operator-metadata.service.spec.ts` plus the 40 other jsdom specs that\nimport the service: 1846 tests pass, 1 is skipped (an existing\n`it.skip`).\n- `npx ng run gui:test-browser --watch\u003dfalse\n--include\u003d\u0027**/code-editor.component.browser.spec.ts\u0027` (the one browser\nspec that imports it): 11 tests, all pass.\n- `yarn format:ci`: clean.\n- `npx ng build`: success.\n\nTo re-check:\n\n```\ngit grep -n -e DictionaryAPIAddress -e \"resources/dictionary\" -e \"upload/dictionary\"   # no hits\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "d27b7b49877bcc52d80602e57f5b0e5f86291736",
      "tree": "c9957f1904cc82db0ecca2b26491a95cb3438193",
      "parents": [
        "e4e324a207b4e6bce37e8845689c702a6b0cdc02"
      ],
      "author": {
        "name": "Kunwoo (Chris)",
        "email": "143021053+kunwp1@users.noreply.github.com",
        "time": "Mon Oct 12 03:15:54 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 12 03:15:54 2026 +0000"
      },
      "message": "feat(frontend): add admin computing unit terminate button (#8947)\n\n### What changes were proposed in this PR?\n\nProblem. An admin can list every computing unit on Admin \u003e Computing\nUnits (#8888) but cannot act on one. Freeing a stuck or idle unit on a\nfull Kubernetes cluster still means finding its pod and deleting it with\n`kubectl`. The backend already lets an ADMIN terminate any unit (`DELETE\n/computing-unit/{cuid}/terminate`, #7337), so only the UI is missing.\n\nFix. Adds a delete-icon button to every row, in a new Actions column. It\ncalls `ComputingUnitActionsService.confirmAndTerminate`, the\nconfirmation the user\u0027s own Computing Units page already uses, so the\ndialog follows the unit type: a \"results will be lost\" warning for a\nKubernetes unit and \"Disconnect\" for a local one. Cancelling the dialog\nor a failed request leaves the row alone. `confirmAndTerminate` gains an\noptional `onTerminated` callback that runs only after a successful\ntermination, and the page uses it to drop the row at once instead of\nshowing the unit as `Running` until the next 5 second poll.\n\nTwo details follow from an admin seeing other users\u0027 units. A poll that\nstarted before the `DELETE` can answer after it with the unit still\nlisted, so the page remembers the units it terminated and filters them\nout of every poll response. And ng-zorro renders the dialog and toast\ntext through `[innerHTML]` while any user can rename their unit, so\n`confirmAndTerminate` now HTML-escapes the unit name for every caller.\n\n```\nBefore:  admin finds a stuck unit on the page -\u003e finds its pod -\u003e kubectl delete pod\nAfter:   admin finds a stuck unit on the page -\u003e clicks its delete icon -\u003e confirms -\u003e row disappears\n```\n\nNot included. Telling the owner their unit was terminated (#6483) and\nthe cluster capacity panels (#6481, #6482) are separate issues. There is\nno backend change.\n\n### Any related issues, documentation, discussions?\n\nCloses #6480. Part of #6476.\n\nFollows #8888, which added the page.\n\n### How was this PR tested?\n\nTests were added for the button, the hand-off to the dialog and the name\nescaping. They cover a button on every row (Kubernetes and local), the\nclick confirming the clicked row\u0027s unit, the row leaving only after a\nsuccessful termination and staying on cancel or failure, a stale\nin-flight poll not bringing the row back, the detail row\u0027s `colspan`, a\nunit name holding markup in the dialog and the toast, and `onTerminated`\nfiring on success only. The tests were written first and watched fail,\nand breaking the code on purpose (name left unescaped, callback on every\noutcome, row dropped on click, poll responses left unfiltered) fails\nexactly the seven tests meant to catch it.\n\n```\ncd frontend \u0026\u0026 npx ng test --watch\u003dfalse --include\u003d\u0027**/admin-computing-unit.component.spec.ts\u0027 --include\u003d\u0027**/computing-unit-actions.service.spec.ts\u0027\ncd frontend \u0026\u0026 npx ng test --watch\u003dfalse\n```\n\nThe first command passes 53 tests and the second passes 6,622 (1\nskipped). `ngc -p src/tsconfig.app.json --noEmit`, `prettier-eslint` and\n`eslint` ran clean on the changed files.\n\n\nhttps://github.com/user-attachments/assets/a33ffa6f-439a-4f71-ae8f-7efe5d94daac\n\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code, Claude Sonnet 5.5"
    },
    {
      "commit": "e4e324a207b4e6bce37e8845689c702a6b0cdc02",
      "tree": "999aca965308e726a7d4da58fdc9efc75f18cba6",
      "parents": [
        "2faa5c507461a1dfb589cac0699602b4a82479c8"
      ],
      "author": {
        "name": "Mend Renovate",
        "email": "bot@renovateapp.com",
        "time": "Mon Oct 12 02:23:56 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 12 02:23:56 2026 +0000"
      },
      "message": "chore(deps, pyamber): update dependency pyyaml to v6.0.3 (#8952)\n\nThis PR contains the following updates:\n\n| Package | Change |\n[Age](https://docs.renovatebot.com/merge-confidence/) |\n[Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n| [PyYAML](https://pyyaml.org/)\n([source](https://redirect.github.com/yaml/pyyaml)) | `\u003d\u003d6.0.2` →\n`\u003d\u003d6.0.3` |\n![age](https://developer.mend.io/api/mc/badges/age/pypi/pyyaml/6.0.3?slim\u003dtrue)\n|\n![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/pyyaml/6.0.2/6.0.3?slim\u003dtrue)\n|\n\n---\n\n### Release Notes\n\n\u003cdetails\u003e\n\u003csummary\u003eyaml/pyyaml (PyYAML)\u003c/summary\u003e\n\n###\n[`v6.0.3`](https://redirect.github.com/yaml/pyyaml/releases/tag/6.0.3)\n\n[Compare\nSource](https://redirect.github.com/yaml/pyyaml/compare/6.0.2...6.0.3)\n\n#### What\u0027s Changed\n\n- Support for Python 3.14 and free-threading (experimental).\n\n**Full Changelog**:\n\u003chttps://github.com/yaml/pyyaml/compare/6.0.2...6.0.3\u003e\n\n\u003c/details\u003e\n\n---\n\n### Configuration\n\n📅 **Schedule**: (in timezone Etc/UTC)\n\n- Branch creation\n  - \"before 8am on monday\"\n- Automerge\n  - At any time (no schedule defined)\n\n🚦 **Automerge**: Disabled by config. Please merge this manually once you\nare satisfied.\n\n♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the\nrebase/retry checkbox.\n\n🔕 **Ignore**: Close this PR and you won\u0027t be reminded about this update\nagain.\n\n---\n\n- [ ] \u003c!-- rebase-check --\u003eIf you want to rebase/retry this PR, check\nthis box\n\n---\n\nThis PR was generated by [Mend Renovate](https://mend.io/renovate/).\nView the [repository job\nlog](https://developer.mend.io/github/apache/texera).\n\n\u003c!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMzQuMSIsInVwZGF0ZWRJblZlciI6IjQ0LjEzNC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0\u003d--\u003e"
    },
    {
      "commit": "2faa5c507461a1dfb589cac0699602b4a82479c8",
      "tree": "d31ce798869584cdeaa23e776051d971e641923a",
      "parents": [
        "27bc3b7703c7e044c03a8d76edeb708146441fce"
      ],
      "author": {
        "name": "Matthew B.",
        "email": "mgball@uci.edu",
        "time": "Mon Oct 12 00:41:15 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 12 00:41:15 2026 +0000"
      },
      "message": "refactor(frontend): extract HuggingFace field bindings into a helper (#8946)\n\n### What changes were proposed in this PR?\n- Extracted the ~185-line HuggingFace-specific field block out of\n`operator-property-edit-frame.component.ts` into a pure helper\n`applyHuggingFaceFieldBindings(field)` in\n`workspace/util/hugging-face-field-bindings.ts`, beside the existing\n`custom-formly-type.ts` that owns the sibling \"which widget a field\nrenders as\" concern.\n- The component now calls the helper under a single `operatorType \u003d\u003d\u003d\n\"HuggingFace\"` guard; the helper reproduces both original guards (`key\n\u003d\u003d\u003d \"task\"` hide, then the string-key gate), so the task lists, `hide`\nexpressions, required-validators, and `validation.show` flags are\nbyte-identical to before.\n- Added `hugging-face-field-bindings.spec.ts` with direct unit tests for\nthe hide/validator logic per task (image/audio inputs and their columns,\nprompt column, text-generation-only controls, context, candidate labels,\nsentences), coverage that was impossible while the logic was inline.\n### Any related issues, documentation, discussions?\nCloses: #8944\n### How was this PR tested?\n- Run `cd frontend \u0026\u0026 npx ng test\n--include\u003d\u0027**/hugging-face-field-bindings.spec.ts\u0027`, expect 15 tests to\npass.\n- Run `cd frontend \u0026\u0026 npx ng test\n--include\u003d\u0027**/operator-property-edit-frame.component.spec.ts\u0027`, expect\nthe existing suite to pass unchanged (262 pass, 1 pre-existing skip).\n- In the workflow editor, add a HuggingFace operator and change its\nTask: confirm the image upload / input image column appear only for\nimage tasks, the audio upload / input audio column only for audio tasks,\nthe prompt column hides for image-only and audio tasks,\nsystemPrompt/maxNewTokens/temperature show only for text-generation, and\nthe required-field validators still block running when a needed input is\nempty.\n### Was this PR authored or co-authored using generative AI tooling?\nCo-authored with Claude Opus 4.8 in compliance with ASF"
    },
    {
      "commit": "27bc3b7703c7e044c03a8d76edeb708146441fce",
      "tree": "122c5f2cad6dadb8fa32858401b4c14388999576",
      "parents": [
        "adc6a4ac4d79f0302534228d119ea2c22f393db7"
      ],
      "author": {
        "name": "carloea2",
        "email": "carloea2@uci.edu",
        "time": "Sun Oct 11 23:11:33 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Oct 11 23:11:33 2026 +0000"
      },
      "message": "feat(pyamber): skip duplicate output writers (#8278)\n\n### What changes were proposed in this PR?\n\nStart output storage writers only when the output port is first\nregistered. Duplicate registration keeps the existing port and writer\nset.\n\n### Any related issues, documentation, discussions?\n\nCloses #8277\n\n### How was this PR tested?\n\nAdded coverage proving that duplicate port registration does not start\nreplacement writers, alongside the existing positive writer-setup\ncoverage.\n\n`C:\\Users\\carlo\\texera\\texera\\.venv312\\Scripts\\python.exe -c \"import\nsys,pytest;\nsys.path[:0]\u003d[r\u0027C:\\Users\\carlo\\texera\\texera-worktrees\\investigate-bug74\\amber\\src\\main\\python\u0027,r\u0027C:\\Users\\carlo\\texera\\texera\\amber\\src\\main\\python\u0027];\nraise\nSystemExit(pytest.main([r\u0027amber\\src\\test\\python\\core\\architecture\\packaging\\test_output_manager.py\u0027,\u0027-p\u0027,\u0027no:cacheprovider\u0027,\u0027-q\u0027]))\"`\n\n`C:\\Users\\carlo\\texera\\texera\\.venv312\\Scripts\\ruff.exe check\namber/src/main/python/core/architecture/packaging/output_manager.py\namber/src/test/python/core/architecture/packaging/test_output_manager.py`\n\n`C:\\Users\\carlo\\texera\\texera\\.venv312\\Scripts\\ruff.exe format --check\namber/src/main/python/core/architecture/packaging/output_manager.py\namber/src/test/python/core/architecture/packaging/test_output_manager.py`\n\nAll 40 tests passed. Ruff checks passed.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Codex"
    },
    {
      "commit": "adc6a4ac4d79f0302534228d119ea2c22f393db7",
      "tree": "6502e02f81f4511b8d2c631ad207c3b14f2d2209",
      "parents": [
        "53114a7594c3ad9fa787b449e732a54946f5bf92"
      ],
      "author": {
        "name": "Kunwoo (Chris)",
        "email": "143021053+kunwp1@users.noreply.github.com",
        "time": "Sat Oct 10 22:43:11 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 10 22:43:11 2026 +0000"
      },
      "message": "fix(file-service, frontend): reject slash in version names (#8883)\n\n### What changes were proposed in this PR?\n\nRoot cause. `createDatasetVersion` names a version `v{N} -\n{description}` from whatever the user typed, and the UI accepted a `/`.\nThe version name is one segment of the logical path\n`/\u003cprefix\u003e/owner/resource/version/file`, and\n`FileResolver.parsePrefixedPath` splits that path on `/`. For the path\nin the issue, `/texera/bughunt-version-name/v3 - //file_name.png`, the\nversion becomes `v3 - ` and `/file_name.png` becomes the file path, so\nthe version lookup misses and `presign-download` returns a 500.\n`createModelVersion` builds its name the same way, so model versions\nhave the same problem.\n\nFix. `ResourceNaming.validateVersionDescription` rejects a description\ncontaining `/` with a 400. `createDatasetVersion` and\n`createModelVersion` call it right after the write-access check, before\nthe LakeFS commit, so the staged files stay staged and the user can fix\nthe description and retry. The version uploader, which datasets and\nmodels both use, shows the error under the input and disables Submit,\nand `Enter` no longer submits either.\n\n```\nBefore:  description \"/\"  -\u003e  version \"v3 - /\"  -\u003e  every file in it fails with presign-download 500\nAfter:   description \"/\"  -\u003e  400 \"Invalid version description\"  (UI: inline error, Submit disabled)\n```\n\nNot included. Versions already stored with a `/` in their name stay\nunopenable, and repairing them needs a data migration. A `%` or `+` in a\nname has a separate problem, because `resolveVersionedFile` URL-decodes\n`filePath` a second time.\n\n### Any related issues, documentation, discussions?\n\nCloses #8882\n\n### How was this PR tested?\n\nTests were added for the validator, for both resources, and for the\nversion uploader, and they were written first and failed against the old\ncode.\n\n```\nsbt \"FileService/testOnly org.apache.texera.service.resource.ResourceNamingSpec org.apache.texera.service.resource.DatasetResourceSpec org.apache.texera.service.resource.ModelUploadResourceSpec\"\ncd frontend \u0026\u0026 yarn ng test --watch\u003dfalse --include\u003d\u0027**/version-uploader.component.spec.ts\u0027\n```\n\nThe first command passes 177 tests and the second passes 73.\n`scalafixAll`, `scalafmtAll`, `prettier-eslint` and `eslint` ran clean\non the changed files.\n\n\nhttps://github.com/user-attachments/assets/8c7bb472-b845-4bed-9b51-da38ef3b3397\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code, Claude Sonnet 5.5"
    },
    {
      "commit": "53114a7594c3ad9fa787b449e732a54946f5bf92",
      "tree": "c104094ef9a08e2faeebc648dfc16e8b5b4d1bda",
      "parents": [
        "ea0fc10cd8478b3b7368910680bede73a3246e73"
      ],
      "author": {
        "name": "Kunwoo (Chris)",
        "email": "143021053+kunwp1@users.noreply.github.com",
        "time": "Sat Oct 10 22:17:54 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 10 22:17:54 2026 +0000"
      },
      "message": "feat(frontend): add admin computing units dashboard (#8888)\n\n### What changes were proposed in this PR?\n\nProblem. An admin cannot see computing units across users in the UI. On\na full Kubernetes cluster they run `kubectl` and match each pod\u0027s `cuid`\nto its `workflow_computing_unit` row by hand.\n\nFix. Adds an ADMIN-only Computing Units page, reached from Admin in the\ndashboard sidebar. It lists every active unit from the existing `GET\n/computing-unit/admin/list`, one row each with name, owner, type,\nstatus, creation time and a resource summary. A Kubernetes row expands\nto its CPU, memory, GPU, JVM memory and shared memory, while a local\nunit has no limits and does not expand. Type and status are filterable,\nstatus covers every state including `Failed`, `Unknown` and\n`Terminating`, and a failing unit\u0027s `statusReason` shows in the status\ntooltip.\n\nThe table polls every 5 seconds with `exhaustMap`, so a response slower\nthan the interval finishes instead of being cancelled by the next tick,\nand a failed poll shows a message and keeps polling.\n`parseDashboardUnit` now gives a `NULL` or malformed `resource` the\n`NaN` placeholder, so one bad row cannot break the table.\n\n```\nBefore:  admin -\u003e ssh -\u003e kubectl get pods -\u003e match cuid to a workflow_computing_unit row\nAfter:   admin -\u003e Admin \u003e Computing Units -\u003e filter by status -\u003e expand a row for its specs\n```\n\nNot included. Terminating a unit from the page (#6480), the cluster\ncapacity panel (#6481, #6482) and the owner notification (#6483) are\nseparate issues.\n\n### Any related issues, documentation, discussions?\n\nCloses #6479. Part of #6476.\n\nReplaces #7356, which the stale bot closed after 37 days without review\nactivity. This is the same change rebased onto current `main`.\n\n### How was this PR tested?\n\nTests were added for the page, for `listAllComputingUnits` and for the\nsidebar entry. They cover the poll (a failed poll, a slow response,\nteardown), the expander, the status filter, sorting, and a `NULL`,\n`\"null\"` or malformed `resource`.\n\n```\ncd frontend \u0026\u0026 npx ng test --watch\u003dfalse --include\u003d\u0027**/admin-computing-unit.component.spec.ts\u0027 --include\u003d\u0027**/dashboard.component.spec.ts\u0027 --include\u003d\u0027**/workflow-computing-unit-managing.service.spec.ts\u0027\ncd frontend \u0026\u0026 npx ng test --watch\u003dfalse\n```\n\nThe first command passes 59 tests and the second passes 6,600 (1\nskipped). `ngc -p src/tsconfig.app.json --noEmit`, `prettier-eslint` and\n`eslint` ran clean on the changed files.\n\nChecked in a browser against a local stack: sign in as an admin, open\nAdmin \u003e Computing Units, and the local unit lists with a green `Running`\nbadge. The first request fires at once and then every 5 seconds without\noverlap. No Kubernetes cluster was available, so the Kubernetes rows\n(expand, limits, `Pending`, `Failed`) are covered by unit tests only.\n\n\nhttps://github.com/user-attachments/assets/f91ce142-1f4e-46af-8560-4706bce984a4\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code, Claude Sonnet 5.5"
    },
    {
      "commit": "ea0fc10cd8478b3b7368910680bede73a3246e73",
      "tree": "503d54a59cc5d2420207954ddd90fcac43d48aef",
      "parents": [
        "8bfe034af17f88e8396b4961714658a48f79cff2"
      ],
      "author": {
        "name": "Kunwoo (Chris)",
        "email": "143021053+kunwp1@users.noreply.github.com",
        "time": "Sat Oct 10 21:59:26 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 10 21:59:26 2026 +0000"
      },
      "message": "fix(file-service): reject over-long dataset version names (#8875)\n\n### What changes were proposed in this PR?\n\nRoot cause. `createDatasetVersion` builds the name `v{N} -\n{description}` and commits to LakeFS first, then inserts the\n`dataset_version` row (`DatasetResource.scala`). `dataset_version.name`\nis `VARCHAR(128)`, so a long description makes the insert fail after the\ncommit, and the commit is outside the DB transaction. The request\nreturns a 500, the staged files are already committed with no version\nrow, and the dataset page then shows neither a pending change nor a\nversion until the next version is created.\n\nFix. `createDatasetVersion` now rejects a name longer than 128\ncharacters with a 400 before it creates the LakeFS commit, using the\nsame check `createModelVersion` already has. The length is counted in\ncode points rather than UTF-16 code units, since `VARCHAR(n)` counts\ncharacters and an emoji would otherwise be rejected early. The staged\nfiles stay pending, so the user can shorten the description and submit\nagain. The frontend already shows the message from the response, so it\nneeds no change.\n\n```\nBefore:  Submit -\u003e LakeFS commit -\u003e INSERT dataset_version fails -\u003e 500, files committed, no version row\nAfter:   Submit -\u003e name over 128 characters -\u003e 400 \"Version name is too long: ...\" -\u003e files stay pending\n```\n\n### Any related issues, documentation, discussions?\n\nCloses #8873\n\n### How was this PR tested?\n\nAdded five tests to `DatasetResourceSpec`: version naming (null, empty\nand non-empty description), a name of exactly 128 characters (accepted),\na name of 129 characters (rejected with a 400, nothing committed, and a\nretry succeeds), a 128-character name made of emoji (accepted) and a\n129-character one (rejected), and the existing no-staged-changes 400.\nBefore the fix, the over-long test failed with\n`org.jooq.exception.DataException` from the insert. A first version of\nthe guard that used `String.length` failed the emoji test, which is why\nthe length is counted in code points.\n\n`sbt \"FileService/testOnly *DatasetResourceSpec\"` gives 157 passed, 0\nfailed, and `scalafixAll` and `scalafmtAll` change nothing. This ran\nlocally with a MinIO container in place of the RustFS image, which could\nnot be pulled on that machine, so CI is the run against RustFS. It was\nnot exercised through the UI.\n\n\nhttps://github.com/user-attachments/assets/f3e5d22d-89fb-477a-88a0-37f77c4e09c7\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code, Claude Sonnet 5.5"
    },
    {
      "commit": "8bfe034af17f88e8396b4961714658a48f79cff2",
      "tree": "4f04bdc5930f0391dd753b7067df51376f16a14c",
      "parents": [
        "3fa608d04c124ec6c646e194f26f2cd391f9c6a9"
      ],
      "author": {
        "name": "Matthew B.",
        "email": "mgball@uci.edu",
        "time": "Sat Oct 10 08:50:21 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 10 08:50:21 2026 +0000"
      },
      "message": "refactor(frontend): extract shared VersionsFilesBrowser component (#8942)\n\n### What changes were proposed in this PR?\n- Extracted the duplicated \"Versions \u0026 Files\" tab from `dataset-detail`\nand `model-detail` into one shared presentational component,\n`texera-versions-files-browser` (template, SCSS, toolbar view-state,\nsider resize, and copy-path logic).\n- Both detail pages now render `\u003ctexera-versions-files-browser\u003e` with\ninputs/outputs and keep their own data loading and version-selection\nlogic.\n- Kept `isMaximized` and `isRightBarCollapsed` parent-owned as two-way\nbindings, since `isMaximized` also gates the page header outside the\ntab; the child reports toggles rather than owning the flags.\n- Moved the view-state unit tests (sider resize, animation-frame\nscheduling, copy-path, toggle emits) into the new component\u0027s spec;\nparent specs keep their integration coverage by rendering the real\nchild.\n### Any related issues, documentation, discussions?\nCloses: #8941\n### How was this PR tested?\n- Run `cd frontend \u0026\u0026 npx ng test\n--include\u003d\u0027**/versions-files-browser.component.spec.ts\u0027\n--include\u003d\u0027**/dataset-detail.component.spec.ts\u0027\n--include\u003d\u0027**/model-detail.component.spec.ts\u0027`, expect all 231 tests to\npass.\n- Open a dataset detail page, switch to the \"Versions \u0026 Files\" tab,\nconfirm the version picker, file tree, file renderer, resize handle,\nmaximize/minimize, hide/show right bar, copy-path, and zip download all\nbehave as before.\n- Repeat on a model detail page and confirm identical behavior, and\nconfirm the model Settings tab (which still uses nz-select) is\nunaffected.\n### Was this PR authored or co-authored using generative AI tooling?\nCo-authored with Claude Opus 4.8 in compliance with ASF\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "3fa608d04c124ec6c646e194f26f2cd391f9c6a9",
      "tree": "85a82b603b35d9929d74471b5892f82326c998df",
      "parents": [
        "05d48eb94ca39912a38100696bdc2a1478402ece"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Sat Oct 10 08:50:14 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 10 08:50:14 2026 +0000"
      },
      "message": "fix(amber): reject $i in settings the plan is built from (#8750)\n\n### What changes were proposed in this PR?\n\nRoot cause: inside a loop block, a loop-variable reference (#8639) is\nwritten into the operator\u0027s setting when the iteration\u0027s state arrives.\nThe compiler, however, builds the operator\u0027s output schema and its\npartitioning earlier, when the workflow compiles, from the reference\u0027s\nplaceholder. A reference in a property the plan is built from therefore\nnever reaches the schema or the partitioning.\n\n```\nBefore:  Loop Start (a \u003d \"x\") -\u003e Projection (alias $a) -\u003e Loop End\n         output column named \"$a\", null in every row\nAfter:   compile error: Projection cannot refer to loop variables (/attributes/0/alias -\u003e $a):\n         its output schema or partitioning is built from that property when the workflow is\n         compiled, before the loop runs\n```\n\n| Piece | What it does |\n|---|---|\n| `@NoLoopVariable` | Marks a descriptor property that can\u0027t hold a loop\nvariable because the plan is built from it: an output column\u0027s name or\ntype, or what an input is partitioned on. `LogicalOp`\u0027s documentation\nstates the rule for operator authors. |\n| `StateReferencing.noLoopVariableProperties` /\n`noLoopVariableReferences` | Name the marked properties by their JSON\nnames, and find the references under them at any depth. Both go through\nJackson\u0027s bean introspection, so renamed JSON names such as `\"result\nattribute\"` resolve. |\n| `OperatorMetadataGenerator` | Puts `\"noLoopVariable\": true` on each\nmarked property in the operator\u0027s JSON schema, from the same helper, so\nthe panel (#8640) can use the same list. |\n| `WorkflowCompiler` | Inside a loop block, a reference under a marked\nproperty is a compile error, reported before the physical plan is built\nso it is the operator\u0027s first error. Outside every block nothing\nchanges: a `$a` alias is still the literal column name. |\n| `ExecutionReconfigurationService` | Modifying an operator that refers\nto loop variables while the workflow runs is refused: `Limit refers to\nloop variables, so it can\u0027t be changed while the workflow runs.` Its\nrebuilt executor would never have the variables written into it. |\n\nMarked properties:\n\n| Operator | Properties |\n|---|---|\n| Projection | drop option, attributes |\n| Dictionary Matcher, Unnest String | result attribute |\n| Aggregate | aggregations, group-by keys |\n| File Scan From Input | attribute name, file-name column option (the\nattribute name is declared by the text-source trait, so File Scan and\nText Input carry the mark too; as sources they are never inside a loop\nblock) |\n| Type Casting | cast units |\n| Hash Join, Interval Join | the join attributes |\n| Sort Partitions | sort attribute, domain min and max |\n\n### Any related issues, documentation, discussions?\n\nCloses #8749\n\nRelated to #8635 and #8639.\n\n### How was this PR tested?\n\nNew tests, each run red against the pre-change code first:\n\n| Spec | Covers |\n|---|---|\n| `StateReferenceModuleSpec` | `noLoopVariableProperties` names each\nmarked property by its JSON name, a trait\u0027s included;\n`noLoopVariableReferences` picks the references under a marked property\nwhether it is renamed, escaped, nested or declared by a trait, and\nnothing from a descriptor with no marked property or no reference. |\n| `OperatorMetadataGeneratorSpec` | The schema marks exactly the\nannotated properties (renamed ones under their JSON names) and no\nothers, and for every operator the marked set equals\n`noLoopVariableProperties`. |\n| `WorkflowCompilerSpec` | Inside a loop block, a reference in each\nmarked property is a compile error, and it comes before the operator\u0027s\nother errors. A reference in a property the executor reads, on an\noperator whose plan is built from other properties, still binds. Outside\nevery block, a `$a` Projection alias stays the literal column name. |\n| `ExecutionReconfigurationServiceSpec` | An edit that makes an operator\ninside a loop block refer to a loop variable is refused, with the\nmessage above. An operator inside a block that refers to no loop\nvariable, and a `$x` literal outside every block, can still be modified.\n|\n\n```\nsbt \"WorkflowCore/testOnly org.apache.texera.amber.core.state.* org.apache.texera.amber.core.executor.*\"   # 75 passed\nsbt \"WorkflowCompiler/test\"                                                                                # 83 passed\nsbt \"WorkflowOperator/testOnly org.apache.texera.amber.operator.metadata.* ...projection.* ...aggregate.* \\\n  ...sortPartitions.* ...dictionary.* ...unneststring.* ...typecasting.* ...hashJoin.* ...intervalJoin.*\"                                                   # 467 passed\nsbt \"WorkflowExecutionService/testOnly org.apache.texera.web.service.ExecutionReconfigurationServiceSpec\"  # 18 passed\nsbt \"scalafmtCheckAll\" \"\u003cWorkflowCore|WorkflowOperator|WorkflowCompiler|WorkflowExecutionService\u003e/scalafixAll --check\"  # clean\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "05d48eb94ca39912a38100696bdc2a1478402ece",
      "tree": "69b59e07c02a707883736caebe75cf5db166541f",
      "parents": [
        "f01f63d95ab7d16a9adc2c4126b1f467c115b102"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Sat Oct 10 08:50:06 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 10 08:50:06 2026 +0000"
      },
      "message": "refactor(frontend): remove the unused hub accessLevel input (#8894)\n\n### What changes were proposed in this PR?\n\nRemoves the unused `@Input() public accessLevel` from\n`HubSearchResultComponent`, and `Input` from its `@angular/core` import,\nsince that was the file\u0027s only input. **+1/−2 lines.** There is no\nbehaviour change. The component is only reached through the three hub\nroutes, whose data carries only `entityType`. Router input binding\n(`withComponentInputBinding`) is not enabled, no template uses the\ncomponent\u0027s selector, and nothing creates it dynamically. Its own\ntemplate and code never read `accessLevel`.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #2838 (2024-09-25), \"Refactor Hub Workflow Search\nResults and Permission-Based Redirection\", copied along with other\ninputs from `UserWorkflowComponent` |\n| **Usage removed by** | **never used**. Nothing has ever bound,\nassigned or read it |\n\nIt has been unused for the year since it was added.\n\n### Any related issues, documentation, discussions?\n\nCloses #8893\n\n### How was this PR tested?\n\nNo new tests; no spec referenced the input.\n\nFrom `frontend/`:\n\n- `npx ng test --watch\u003dfalse\n--include\u003d\u0027**/hub-search-result.component.spec.ts\u0027`: 31 tests, all pass.\nNo other spec renders this component.\n- `yarn format:ci`: clean.\n- `npx ng build`: success.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "f01f63d95ab7d16a9adc2c4126b1f467c115b102",
      "tree": "81f6d94c1d0a0b230209d77cbee15fc281edb6d9",
      "parents": [
        "be65bf8564a32eea4196aa0190a04f73884bfe70"
      ],
      "author": {
        "name": "yangzhang75",
        "email": "yangz75@uci.edu",
        "time": "Sat Oct 10 08:48:36 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 10 08:48:36 2026 +0000"
      },
      "message": "feat(workflow): freeze a pinned version as the public copy (#7853)\n\n### What changes were proposed in this PR?\n\nA public workflow follows the author\u0027s latest content, as publishing has\nalways done: every\nsave reaches the Hub immediately. This adds the other state — the author\npins the version\nthey have now, and what the public sees stops moving until they pin\nagain.\n\n- **`WorkflowPublishService`** owns the two states and the moves between\nthem: `publish`,\n`pinLatest`, `unpin`, `unpublish`, `statusOf`. `is_public` stays the\non/off switch;\n  `published_content` is the pin, NULL while following.\n- **A pin freezes everything on public show** — the graph, the title,\nthe description and the\nview the workflow opens in — because a copy that froze only its graph\nwould still advertise\na title nobody published. The default view matters because a form\u0027s\ndefinition rides inside\nthe content: serving the author\u0027s live preference over a frozen graph\nwould open a form on a\n  copy that has none.\n- **A pin is one statement.** Each column is copied from its own row\n(`published_content \u003d content`\nand so on) rather than from a workflow read a moment earlier, so there\nis no window in which the\nauthor\u0027s next save lands and the pin freezes the version before it --\nwhich would have left them\n  reading \"you have unpublished changes\" the instant after they pinned.\n- **Three endpoints**:\n\n| Endpoint | Does |\n|---|---|\n| `POST /workflow/pin/{wid}` | freezes the author\u0027s current version as\nthe public copy; called again, moves the pin forward |\n| `DELETE /workflow/pin/{wid}` | drops the pin, back to following the\nlatest |\n| `GET /workflow/publish-status/{wid}` | published, pinned, and whether\na pin is holding edits back |\n\n- **Publishing and unpublishing move through the same service**, so\nunpublishing drops the pin\nrather than leaving a private workflow carrying one. Re-publishing\nstarts in the following\nstate: coming back should not silently put old public content on show\nagain.\n- **One writer for the publish columns.** Two paths could still write\nthem by accident, because\neach read a whole row (or took a whole `Workflow` from the client) and\nwrote it all back:\n- a **rename or description edit** wrote every column from a row it had\nread a moment\nearlier, so anything landing in between was silently rewritten to what\nthat read had seen:\na publish undone, a pin dropped, or — worst — a workflow the author had\njust unpublished\nput back on public show under its frozen copy. Each now writes only its\nown column.\n- **creating** a workflow clears the publish columns, so a request body\ncannot seed a\n    published copy of its own choosing.\n\nA plain **save** was the third, and #8498 has since narrowed it on main\nfor its own reasons,\nso nothing is needed here — the tests below still pin the behaviour from\nthis feature\u0027s side.\nTogether with `/set-default-view`, which already wrote only its column,\nevery endpoint now\nwrites what it owns and nothing else: outside creation,\n`WorkflowPublishService` is the only\n  writer of `is_public` and the frozen copy.\n\n**Nothing on screen changes.** No read path consults the pinned copy yet\nand there is no UI:\nevery workflow stays in the following state it is in today. The\nendpoints answer, and nothing\ncalls them.\n\n### Any related issues, documentation, discussions?\n\nCloses #7938\nPart of #7828. Design discussion: #7128. Schema: #7851.\n\n### How was this PR tested?\n\n32 cases in `WorkflowPublishSpec`:\n\n- the state machine — follow → pin → re-pin → unpin → unpublish →\nre-publish, and that a\n  re-publish does not resurrect the previous pin;\n- what a pin freezes — the name, the description and the default view\nalongside the content,\nand that each of them moving afterwards is reported as an unpublished\nchange;\n- the guards — no write access, not published, and a workflow that does\nnot exist;\n- that a create cannot inject publish columns, and that a save, a\ncollaborator\u0027s save and a\n  rename all leave the publish state alone;\n- that a publish or an unpublish landing while a rename is in flight\nsurvives it, and that a save\nlanding while a pin is in flight is the version that gets pinned. These\nthree drive the\ninterleaving off the statement itself rather than off a thread, so the\nordering is the same on\n  every run;\n- the ordinary states that are easy to forget: content that is not valid\nJSON is reported as\ndrift rather than throwing, a workflow with no description pins like any\nother,\nunpinning one that is already following is a no-op rather than an error,\nand publishing one that\n  is already public leaves its pin alone.\n\n`hasUnpublishedChanges` compares the two copies as parsed JSON rather\nthan as strings — the\nsame graph can come back with its keys in another order, and reporting\nthat as an edit is an\nalarm the author cannot clear. One case covers it.\n\nThe narrowed write paths were checked by mutation: restoring `is_public`\nto the save statement\nturns three cases red, one of them on the CHECK constraint itself, and\nrestoring the\nread-modify-write to the rename path turns its two interleaving cases\nred — one showing the\npublish reverted, the other showing the unpublished workflow back on\npublic show. Restoring the\nread-then-write to the pin turns the third red, showing the pin frozen\none save behind.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (claude-opus-5)\n\nCo-authored-by: Claude Opus 5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "be65bf8564a32eea4196aa0190a04f73884bfe70",
      "tree": "f63e38814a3f0b460b54a741ac16a01af11444e4",
      "parents": [
        "a42c573f7d4515fbaa4dcecbb4399b01829310ef"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Thu Oct 08 07:40:40 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 08 07:40:40 2026 +0000"
      },
      "message": "refactor(frontend): remove the unused loadFile output (#8892)\n\n### What changes were proposed in this PR?\n\nRemoves the unused `@Output() loadFile` from\n`UserDatasetFileRendererComponent`, along with `EventEmitter` and\n`Output` from its `@angular/core` import, since nothing else in the file\nuses them. **+1/−4 lines.** There is no behaviour change: the component\nnever emits `loadFile`, and its two hosts (`dataset-detail` and\n`model-detail`) bind only inputs on\n`\u003ctexera-user-dataset-file-renderer\u003e`.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #2413 (2024-02-26), \"Introduce Dataset GUI\", with\nthe file renderer itself |\n| **Usage removed by** | **never used**. No `(loadFile)` binding or\n`.emit` has ever existed |\n\nIt has been unused for the nineteen months since it was added.\n\n### Any related issues, documentation, discussions?\n\nCloses #8891\n\n### How was this PR tested?\n\nNo new tests; no spec referenced the output.\n\nFrom `frontend/`:\n\n- `npx ng test --watch\u003dfalse\n--include\u003d\u0027**/user-dataset-file-renderer.component.spec.ts\u0027\n--include\u003d\u0027**/dataset-detail.component.spec.ts\u0027\n--include\u003d\u0027**/model-detail.component.spec.ts\u0027`: 3 files, 286 tests, all\npass. The last two specs cover the renderer\u0027s two hosts.\n- `yarn format:ci`: clean.\n- `npx ng build`: success.\n\nTo re-check:\n\n```\ngit grep -n -w \"loadFile\" -- frontend/src   # no hits\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "a42c573f7d4515fbaa4dcecbb4399b01829310ef",
      "tree": "be4b0331e70e7569ef86d9c0a66e67ac34511f08",
      "parents": [
        "535b97a941131cb0ac3a57f112b4e4c60f059d7e"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Thu Oct 08 07:40:39 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 08 07:40:39 2026 +0000"
      },
      "message": "refactor(frontend): remove unused workflow endpoint constants (#8896)\n\n### What changes were proposed in this PR?\n\nRemoves three exported REST endpoint constants from\n`execute-workflow.service.ts` that nothing imports:\n`EXECUTE_WORKFLOW_ENDPOINT`, `PAUSE_WORKFLOW_ENDPOINT` and\n`RESUME_WORKFLOW_ENDPOINT`. **−5 lines.** There is no behaviour change.\nExecute, pause and resume are sent over the websocket\n(`WorkflowExecuteRequest` / `WorkflowPauseRequest` /\n`WorkflowResumeRequest`), and the backend has no `queryplan/execute`,\n`pause` or `resume` REST routes.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #622 (2018-06-21), the first execute-workflow\nservice: `EXECUTE_WORKFLOW_ENDPOINT`. #684 (2019-03-10), pause/resume\nbuttons: the other two |\n| **Usage removed by** | #811 (2020-08-21), the Amber merge, which moved\npause/resume to websocket requests and removed their `http.post` calls.\n#982 (2021-01-25), \"Improves multiple ports support in Texera operators\n(Step 4)\", which removed the last REST execute call |\n\nThe pause/resume constants have been unused for six years, and the\nexecute one for nearly five.\n\n### Any related issues, documentation, discussions?\n\nCloses #8895\n\n### How was this PR tested?\n\nNo new tests; no spec imported the constants.\n\nFrom `frontend/`:\n\n- `npx ng test --watch\u003dfalse`, covering\n`execute-workflow.service.spec.ts` plus all 17 specs that import the\nservice (18 files): 1363 tests pass, 1 is skipped (an existing\n`it.skip`).\n- `yarn format:ci`: clean.\n- `npx ng build`: success.\n\nTo re-check:\n\n```\ngit grep -n -w -E \"EXECUTE_WORKFLOW_ENDPOINT|PAUSE_WORKFLOW_ENDPOINT|RESUME_WORKFLOW_ENDPOINT\"   # no hits\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "535b97a941131cb0ac3a57f112b4e4c60f059d7e",
      "tree": "e45336dfa50a9ea386f8f9f5d2256eeef8e8a4f4",
      "parents": [
        "40b507df8a3d19ec0ed7bd169937b09e25d4f79d"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Thu Oct 08 07:40:38 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 08 07:40:38 2026 +0000"
      },
      "message": "refactor(frontend): remove dead styles from the About page (#8879)\n\n### What changes were proposed in this PR?\n\nRemoves two rules from the hub About page\u0027s stylesheet that style\nnothing: `#logo` and `.login-container`. **−11 lines.** There is no\nbehaviour change. The component uses emulated encapsulation, so these\nrules can only match its own template, and no element there uses either\nselector, statically or dynamically. No code adds them at runtime, and\nno other stylesheet relies on them.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #2324 (2024-01-24), \"Remove bootstrap from\nnavigation bars\": `#logo`. #3119 (2024-12-01), \"Update Texera Hub About\nPage\": `.login-container` |\n| **Usage removed by** | #2725 (2024-09-24), \"Add Hub\", removed the `\u003cli\nid\u003d\"logo\"\u003e` element; the stylesheet then moved with the component\nunchanged. #7339 (2026-08-10), \"consolidate login onto a dedicated\n/login page\", removed the embedded `\u003ctexera-local-login\nclass\u003d\"login-container\"\u003e` |\n\n`#logo` has been dead for two years and `.login-container` for two\nmonths.\n\n### Any related issues, documentation, discussions?\n\nCloses #8878\n\n### How was this PR tested?\n\nNo new tests; no spec referenced either selector.\n\nFrom `frontend/`:\n\n- `npx ng test --watch\u003dfalse --include\u003d\u0027**/about.component.spec.ts\u0027\n--include\u003d\u0027**/user-icon.component.spec.ts\u0027`: 2 files, 5 tests, all pass.\nThe user-icon spec routes to the About page.\n- `yarn format:ci`: clean.\n- `npx ng build`: success.\n\nTo re-check:\n\n```\ngit grep -n \"login-container\" -- frontend   # no hits\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "40b507df8a3d19ec0ed7bd169937b09e25d4f79d",
      "tree": "920dd13f6c73266fb004a77c31e687a67d3be4ce",
      "parents": [
        "b143a4fd72160f71ceb88fa80d790c5f8d146db6"
      ],
      "author": {
        "name": "carloea2",
        "email": "carloea2@uci.edu",
        "time": "Wed Oct 07 20:34:32 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 07 20:34:32 2026 +0000"
      },
      "message": "feat(pyamber): align VFS resource wire values (#8238)\n\n### What changes were proposed in this PR?\n\nAlign the Python runtime statistics and console message resource values\nwith the lowercase VFS wire format produced by Scala. The decoder keeps\nits existing case normalization.\n\nThe regression test uses literal Scala wire values instead of values\nread from the Python enum.\n\n### Any related issues, documentation, discussions?\n\nCloses #8237\n\n### How was this PR tested?\n\nRetested on upstream main at b143a4fd7216. The new regression cases fail\nbefore the change: 2 failed, 34 passed. With the change, all 36 tests\npass.\n\n```powershell\n\u0026 \u0027C:/Users/carlo/texera/venv312/Scripts/python.exe\u0027 -m pytest -q -p no:cacheprovider amber/src/test/python/core/storage/test_vfs_uri_factory.py amber/src/test/python/core/storage/test_document_factory.py\n\u0026 \u0027C:/Users/carlo/texera/venv312/Scripts/python.exe\u0027 -m ruff check amber/src/main/python amber/src/test/python\n\u0026 \u0027C:/Users/carlo/texera/venv312/Scripts/python.exe\u0027 -m ruff format --check amber/src/main/python amber/src/test/python\n```\n\nLint and formatting pass for all Python source and test files.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Codex"
    },
    {
      "commit": "b143a4fd72160f71ceb88fa80d790c5f8d146db6",
      "tree": "90beef9f763791e258ef27bad202c92ebea8a37c",
      "parents": [
        "397de92d779b3d8cb235116609cb4fe76d0c7da7"
      ],
      "author": {
        "name": "Ryan Zhang",
        "email": "97552093+zyratlo@users.noreply.github.com",
        "time": "Wed Oct 07 19:36:18 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 07 19:36:18 2026 +0000"
      },
      "message": "fix(notebook-migration): apply the jupyter panel\u0027s read-only setup before the notebook loads (#8909)\n\n### What changes were proposed in this PR?\n\nThe Jupyter panel\u0027s cells became editable as soon as a viewer clicked\ninto one. Classic Notebook resets each editor\u0027s `readOnly` from\n`cell.is_editable()` on every focus and re-enables the keyboard manager\nat the same time, so setting `readOnly` once from `custom.js` did not\nhold. That setup also raced the notebook: `custom.js` loads\nasynchronously and usually misses `notebook_loaded`, and only worked\nbecause it was bound to `kernel_ready` too.\n\nThis PR moves the setup into `custom-preload.js`, a hook Notebook 6.5\nprovides that `main.js` waits for before it builds the notebook.\nOverrides placed there are always in effect:\n\n* `Cell.prototype.is_editable` returns false, so Notebook itself keeps\nevery editor read only, including after focus.\n* `KeyboardManager.prototype.enable` is a no op, and the manager is\ndisabled once the notebook loads, so focusing a cell no longer brings\nback Shift+Enter, `d d` and the other shortcuts.\n* `KernelSelector.prototype._spec_not_found` continues without a kernel\ninstead of opening the \"Kernel not found\" dialog. The panel never runs\ncells, so a notebook whose kernel is not installed opens normally.\nPython notebooks still match `python3` and start their kernel as before.\n* The markdown `unrender` override moves over unchanged.\n\n`custom.js` keeps only the Texera messaging. Its cell click handler is\nnow delegated from `document` and bound immediately, rather than on\n`kernel_ready`, so clicking a cell to highlight its operator also works\nwhen no kernel starts. It stays in `custom.js` because it needs the\norigin `start-texera-jupyter.sh` substitutes.\n\n`jupyter.dockerfile` copies the new file, and the local dev README lists\nit among the files that need an image rebuild.\n\n### Any related issues, documentation, discussions?\n\nCloses #8908\nParent-issue #4301\n\nR support (#8009) depends on this: R notebooks open in the panel without\na kernel, which hit both the dialog and the editable cells.\n\n### How was this PR tested?\n\nThese files have no automated tests. Tested by hand in the Jupyter\ncontainer, with real keystrokes:\n\n* An R notebook (no kernel installed): no dialog. Typing, Enter,\nBackspace, Shift+Enter, `d d` and `b` change nothing. Double clicking a\nmarkdown heading leaves it rendered. R syntax highlighting is intact,\nand the cell click handler is bound.\n* A Python notebook: the kernel still starts, highlighting is unchanged,\nand an editor stays read only after focus (before this change it became\neditable).\n* `custom-preload.js` is served by the rebuilt image. A server that was\nalready running keeps serving Notebook\u0027s default stub until restarted,\nsince Notebook caches static file locations.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)"
    },
    {
      "commit": "397de92d779b3d8cb235116609cb4fe76d0c7da7",
      "tree": "5257e901410ef2e27b51c3c5f67074f12f23f6e2",
      "parents": [
        "4c982a7a8abba119b326b19456f4ef7fda78f059"
      ],
      "author": {
        "name": "yangzhang75",
        "email": "yangz75@uci.edu",
        "time": "Wed Oct 07 19:32:00 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 07 19:32:00 2026 +0000"
      },
      "message": "feat(workflow-form): render Projection\u0027s drag-reorder list in the form, with the drag (#8843)\n\n### What changes were proposed in this PR?\n\nCloses #8761. Part of the Form View feature (#8011); from the #8439\nrefinements (item 2).\n\nAn exposed drag-reorder property -- Projection\u0027s columns, formly type\n`repeat-section-dnd` -- fell back to a plain repeated list in the Form\nView (`CANVAS_ONLY_FORMLY_TYPES`): a reader could edit the rows but not\nreorder them, which is what the widget is for. The fallback assumed the\ndrag had nowhere to attach on a form; the widget carries its own CDK\ndrop list, and the row template it needs comes from the operator\u0027s own\nschema (the per-instance one, with the upstream columns), which the form\nalready builds.\n\n- `repeat-section-dnd` leaves `CANVAS_ONLY_FORMLY_TYPES`; the set now\nholds the code editor only. On the form the widget renders exactly as on\nthe operator property panel, drag handle and all, and a drop reaches the\noperator through the card\u0027s `valueChanges` write-back; the panel\u0027s\n`reorder` callback stays optional (the widget calls it only when the\nhost provides one), so the same widget serves both hosts without a\nform-specific branch. Nothing is added to the widget\u0027s UI.\n- Two defects in the widget itself, found while reviewing this and in\nreach of the form for the first time: every button now has\n`type\u003d\"button\"` -- `nz-button` sets no type, so inside a form (the\ncard\u0027s, the panel\u0027s) a typeless button is the submit button and Enter in\na row\u0027s input clicked it, removing the first row (the fallback the form\nused before had typed buttons; the panel has had this since the widget\nexists); and the rows are re-keyed to their positions after a drop, as\nformly\u0027s own `remove()` does -- formly keys rows by position and writes\na cell\u0027s value into the model by that key path, so a value typed into a\nmoved row landed on the row that used to be there (the same after a drag\non the panel, until the operator was re-selected).\n\n### Any related issues, documentation, discussions?\n\nCloses #8761. Raised by @mengw15 on #8436; filed from #8439. Builds on\nthe sub-field walk from #8438. #8760 (proper) also shrinks\n`CANVAS_ONLY_FORMLY_TYPES`; whichever lands second deletes the\nthen-empty set. Known limitation, not this PR\u0027s code: the Form View\nrebuilds every card on every compilation, including the one a card\u0027s own\nwrite triggers, so on the form a drop\u0027s write redraws the rows about a\nsecond later, and a second drop made in the last 150 ms before that\nredraw is undone. The canvas panel has no such rebuild. Filed as #8844\nand fixed in #8845 (the form rebuilds only when the schema, the set of\ninputs or a value it does not hold changed); this PR is independent of\nit. Other follow-ups: a card\u0027s model is seeded once and never re-seeded\nfrom a co-editor\u0027s edit of the same property, so a reorder writes the\nwhole array back over such an edit (pre-existing for every array/object\nproperty; a reorder is one more trigger); the HuggingFace and codearea\nwidgets also carry typeless buttons.\n\n### How was this PR tested?\n\nUnit tests (vitest). The widget\u0027s spec: a drop reorders the model, the\nfield configs and the form controls and then tells the parent; a section\nwithout a reorder callback still reorders; a keyless row\u0027s children are\nre-keyed to the row\u0027s new position, as formly\u0027s own remove() does; every\nbutton carries `type\u003d\"button\"`; the existing rendering tests (one row\nper entry, draggable rows, remove, add, disabled section) still hold. A\nsecond spec stands the widget up under real formly\n(`FormlyModule.forRoot`, a form, a model): a drop changes the model and\nthe cells and keeps the rows\u0027 keys in step with their positions, and a\nvalue typed into a moved row lands on that row\u0027s entry. The form\u0027s spec:\nProjection\u0027s `attributes` renders through `repeat-section-dnd`.\n`custom-formly-type`\u0027s spec pins the set. Each guard was\ndeletion-checked (the re-keying dropped; the callback called unguarded;\nthe remove button typeless; the type back in the canvas-only set) and\nturned a named test red. eslint, prettier and the production (AOT) build\npass; the full frontend suite passes; every statement, function and\nbranch this PR adds is covered.\n\nChecked on a flag-on instance (main-demo; a Python source with four\ncolumns feeding a Projection whose `attributes` is exposed), with the\ncanvas and the form open side by side: on main the card is a plain list\n(no handle); with this PR the card shows the drag handles, as the panel\ndoes. Dragging the last row to the top: the operator\u0027s order follows in\nthe canvas tab\u0027s panel within a second and in the saved workflow. An\nalias typed into the moved row lands on that column, not its neighbour;\nEnter in an alias input removes no row; a reload shows the same order. A\ndrop made on the canvas panel reaches the form within a second.\n\n#### Video\n\n**Before**\n\n\nhttps://github.com/user-attachments/assets/5a78f6f5-3b27-4b93-955e-bb15b40fd854\n\n\n\n**After**\n\n\nhttps://github.com/user-attachments/assets/b84c79fa-a0a4-4bbc-b734-e75147bdf0d6\n\n\n\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nYes. Generated-by: Claude Code (Claude Fable 5.1, Anthropic).\nCo-authored with Claude, reviewed line by line by the author before\nsubmission.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Claude Fable 5.1 \u003cnoreply@anthropic.com\u003e\nCo-authored-by: Meng Wang \u003cmengw15@uci.edu\u003e"
    },
    {
      "commit": "4c982a7a8abba119b326b19456f4ef7fda78f059",
      "tree": "1f63c75fb880d752288ccee5614c7b6e59ff0139",
      "parents": [
        "f16e7cdc287e6b044473ecf227f6b2251e188dc2"
      ],
      "author": {
        "name": "Suryaa Charan",
        "email": "122703005+sshiv012@users.noreply.github.com",
        "time": "Wed Oct 07 16:20:29 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 07 16:20:29 2026 +0000"
      },
      "message": "chore: ignore symlinks at the generated proto and node_modules paths (#8887)\n\n### What changes were proposed in this PR?\n\nTwo `.gitignore` patterns end in `/`, which only matches directories:\n\n```\namber/src/main/python/proto/\n**/node_modules/\n```\n\nA symlink at either path isn\u0027t ignored. This is easy to hit when you run\ntests in a second worktree and symlink the generated protos or\n`node_modules` from your main checkout instead of regenerating them. A\n`git add -A` then commits the symlink.\n\nThat happened to me in #8769: the symlink got committed, and CI\u0027s\n`bin/python-proto-gen.sh` failed with `mkdir: cannot create directory\n\u0027.../amber/src/main/python/proto\u0027: File exists`, so every job stopped\nbefore running tests.\n\nThis drops the trailing slash on both lines, so files, symlinks and\ndirectories at those paths are all ignored.\n\n### Any related issues, documentation, discussions?\n\nFound while working on #8769.\n\n### How was this PR tested?\n\nIn a scratch repo with a symlink at `amber/src/main/python/proto` and at\n`agent-service/node_modules`:\n\n- old patterns: both symlinks show up in `git status` as untracked\n- new patterns: both are ignored\n\nReal directories at those paths are still ignored, since a pattern\nwithout a trailing slash matches directories too.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\nCo-authored-by: suryaacharan \u003csuryaacharan@suryaacharans-MacBook-Pro.local\u003e\nCo-authored-by: Claude Opus 5.5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "f16e7cdc287e6b044473ecf227f6b2251e188dc2",
      "tree": "6ac5fd7828e8288a7170e6ad102d8c760ba0b3ed",
      "parents": [
        "9d768b7ba9c274eb1a2980162af4cda6ef6327ba"
      ],
      "author": {
        "name": "dzueck",
        "email": "dzueck@gmail.com",
        "time": "Wed Oct 07 15:03:49 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 07 15:03:49 2026 +0000"
      },
      "message": "feat: support for vm runtime configurations for compute units and texera micro services (#8572)\n\n\u003c!--\nThanks for sending a pull request (PR)! Here are some tips for you:\n1. If this is your first time, please read our contributor guidelines:\n[Contributing to\nTexera](https://github.com/apache/texera/blob/main/CONTRIBUTING.md)\n  2. Ensure you have added or run the appropriate tests for your PR\n  3. If the PR is work in progress, mark it a draft on GitHub.\n  4. Please write your PR title to summarize what this PR proposes, we\n    are following Conventional Commits style for PR titles as well:\n- `fix` is for behavior that worked before and no longer does; adding or\nremoving a functionality, or reworking one so that user-facing behavior\nintentionally changes, is a `feat`; a change that leaves the user-facing\n        behavior unchanged is a `refactor`.\n- A test-only PR is `test(\u003cmodule\u003e): ...`; repairing a broken test is\n        `fix(test, \u003cmodule\u003e): ...`.\n- A dependency bump is `fix(deps, \u003cmodule\u003e): ...` when it patches a CVE\nand `chore(deps, \u003cmodule\u003e): ...` otherwise; GitHub Actions bumps take\n        `ci` as their module, e.g. `chore(deps, ci): ...`.\n- A PR targeting a release branch appends the version as the last scope\n        component, e.g. `fix(deps, frontend, v1.2): ...`.\n    See CONTRIBUTING.md for the full convention.\n  5. Be sure to keep the PR description updated to reflect all changes.\n--\u003e\n\n### What changes were proposed in this PR?\n\u003c!--\nPlease clarify what changes you are proposing. The purpose of this\nsection\nis to outline the changes. Here are some tips for you:\n  1. If you propose a new API, clarify the use case for a new API.\n  2. If you fix a bug, you can clarify why it is a bug.\n  3. If it is a refactoring, clarify what has been changed.\n  3. It would be helpful to include a before-and-after comparison using \n     screenshots or GIFs.\n  4. Please consider writing useful notes for better and faster reviews.\n--\u003e\nAdds support for running compute units and micro services inside a vm\nusing [kata containers](https://katacontainers.io/). This is important\nfor security as arbitrary code submitted by users can run inside these\ncompute units. This PR adds the option to use VMs, but does not require\nit. It is only targeted at k8s deployments and was tested using RKE2.\nNote: k8s distributions like minikube may need additional steps to\nsupport VMs.\n\nTo enable VMs you must first install kata containers following [these\ninstructions](https://kata-containers.github.io/kata-containers/installation/).\nMake sure to follow the helm instructions. After this, you can enable\nCompute Units to use a VM by modifying these two lines in\nbin/k8s/values.yaml:\n  - name: KUBERNETES_COMPUTING_UNIT_RUNTIME_CLASS_CPU\n    value: \"kata-qemu-runtime-rs\"\n  - name: KUBERNETES_COMPUTING_UNIT_RUNTIME_CLASS_GPU\n    value: \"kata-qemu-nvidia-gpu-runtime-rs\"\n\nTo enable texera specific micro services to run in a VM modify this\nline:\nglobal:\n  texeraMicroServiceRuntimeClass: \"kata-qemu-runtime-rs\"\n\n### Any related issues, documentation, discussions?\n\u003c!--\nPlease use this section to link other resources if not mentioned\nalready.\n1. If this PR fixes an issue, please include `Fixes #1234`, `Resolves\n#1234`\nor `Closes #1234`. If it is only related, simply mention the issue\nnumber.\n  2. If there is design documentation, please add the link.\n  3. If there is a discussion in the mailing list, please add the link.\n--\u003e\nCloses #8545\nDiscussed in #8430\n\n### How was this PR tested?\n\u003c!--\nIf tests were added, say they were added here. Or simply mention that if\nthe PR\nis tested with existing test cases. Make sure to include/update test\ncases that\ncheck the changes thoroughly including negative and positive cases if\npossible.\nIf it was tested in a way different from regular unit tests, please\nclarify how\nyou tested step by step, ideally copy and paste-able, so that other\nreviewers can\ntest and check, and descendants can verify in the future. If tests were\nnot added,\nplease describe why they were not added and/or why it was difficult to\nadd.\n--\u003e\nPrimarily tested in v1.2.0 where performance tests were done with\nvarious micro benchmark workflows which can be seen in #8430. Additional\nfunctionality testing still needs to be done on the latest commits.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\u003c!--\nIf generative AI tooling has been used in the process of authoring this\nPR,\nplease include the phrase: \u0027Generated-by: \u0027 followed by the name of the\ntool\nand its version. If no, write \u0027No\u0027. \nPlease refer to the [ASF Generative Tooling\nGuidance](https://www.apache.org/legal/generative-tooling.html) for\ndetails.\n--\u003e\nGenerated-by: Gemini 4.1 Pro\n\n---------\n\nSigned-off-by: dzueck \u003cdzueck@gmail.com\u003e"
    },
    {
      "commit": "9d768b7ba9c274eb1a2980162af4cda6ef6327ba",
      "tree": "8702058eb52bccc19a1014ed62115581f0baafe4",
      "parents": [
        "3b370bfc2f79a1daf7143cc6a92a573291affa3b"
      ],
      "author": {
        "name": "Matthew B.",
        "email": "mgball@uci.edu",
        "time": "Wed Oct 07 10:06:49 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 07 10:06:49 2026 +0000"
      },
      "message": "refactor(pyamber): remove the unused FROM_PYOBJECT_MAPPING (#8904)\n\n### What changes were proposed in this PR?\n- Remove the unused `FROM_PYOBJECT_MAPPING` dict from\n`core/models/schema/attribute_type.py`.\n- It is referenced nowhere in the repo and is not exported; only its\nsibling `TO_PYOBJECT_MAPPING` is actually imported and used (in\n`core/models/tuple.py`). The `# Only single-directional mapping.`\ncomment stays with `TO_PYOBJECT_MAPPING`.\n### Any related issues, documentation, discussions?\nCloses: #8903\n### How was this PR tested?\n- Non-functional change (dead module-level dict removal); no behavior\nchanges, so no test added.\n- Confirm no references remain: run `rg -n \"FROM_PYOBJECT_MAPPING\"` and\nexpect no hits after removal.\n- Verify formatting from `amber/`: `ruff format --check\nsrc/main/python/core/models/schema/attribute_type.py`.\n### Was this PR authored or co-authored using generative AI tooling?\nCo-authored with Claude Opus 4.8 in compliance with ASF"
    },
    {
      "commit": "3b370bfc2f79a1daf7143cc6a92a573291affa3b",
      "tree": "5817df448e40507f322351058a3fc5e094b3bcdc",
      "parents": [
        "0972f58652d0aa1e6fcd58e7e75804d18929a8dc"
      ],
      "author": {
        "name": "Matthew B.",
        "email": "mgball@uci.edu",
        "time": "Wed Oct 07 09:29:35 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 07 09:29:35 2026 +0000"
      },
      "message": "refactor(frontend): remove dead workflow-editor panel styles (#8906)\n\n### What changes were proposed in this PR?\n- Remove two orphaned CSS rule blocks, `.panels-container` and\n`.code-panel-wrapper` (and their comments), from\n`workflow-editor.component.scss`.\n- Both are leftover styling from a removed inline-panel overlay and are\nreferenced nowhere in the component template, TypeScript, or anywhere in\n`frontend/src`; neighboring rules such as `.chat-popover-container` are\nuntouched.\n### Any related issues, documentation, discussions?\nCloses: #8905\n### How was this PR tested?\n- Non-functional change (CSS dead-code removal); no behavior changes, so\nno test added.\n- Confirm no references remain: run `rg -n\n\"panels-container|code-panel-wrapper\" frontend/src` and expect no hits\nafter removal.\n- Open a workflow in the editor and confirm the canvas, operator chat\npopover, and all overlays render unchanged.\n### Was this PR authored or co-authored using generative AI tooling?\nCo-authored with Claude Opus 4.8 in compliance with ASF"
    },
    {
      "commit": "0972f58652d0aa1e6fcd58e7e75804d18929a8dc",
      "tree": "7251902b006c8ee53fd0d2392b178caad10cafd9",
      "parents": [
        "e2238c442a9dbf9f58d9d4fa37b9c344d7cfaab4"
      ],
      "author": {
        "name": "Matthew B.",
        "email": "mgball@uci.edu",
        "time": "Wed Oct 07 09:27:58 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 07 09:27:58 2026 +0000"
      },
      "message": "refactor(amber): remove unused private updateLatestVersion (#8902)\n\n### What changes were proposed in this PR?\n- Remove the unused `private def updateLatestVersion` (and its Scaladoc)\nfrom `WorkflowVersionResource.scala`.\n- The method has zero call sites repo-wide and carries no JAX-RS\nannotation, so it is unreachable dead code; the helpers it called\n(`getLatestVersion`, `workflowVersionDao`) remain in use elsewhere.\n### Any related issues, documentation, discussions?\nCloses: #8901\n### How was this PR tested?\n- Non-functional change (dead private method removal); no behavior\nchanges, so no test added.\n- Confirm no call sites remain: run `rg -nw \"updateLatestVersion\"` and\nexpect no hits after removal.\n### Was this PR authored or co-authored using generative AI tooling?\nCo-authored with Claude Opus 4.8 in compliance with ASF"
    },
    {
      "commit": "e2238c442a9dbf9f58d9d4fa37b9c344d7cfaab4",
      "tree": "83670a353179b294c809a82520d7bb7ae824ed2a",
      "parents": [
        "404df27238ce46d8b9216fba1adcfa1b0a99a369"
      ],
      "author": {
        "name": "Matthew B.",
        "email": "mgball@uci.edu",
        "time": "Wed Oct 07 09:00:10 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 07 09:00:10 2026 +0000"
      },
      "message": "refactor(frontend): remove leftover result-table download-all styles (#8898)\n\n### What changes were proposed in this PR?\n- Remove four dead CSS rules from `result-table-frame.component.scss`:\n`td.data-size`, `.borderless-button` (and its `:hover`),\n`.table-footer`, and `.download-all-button`.\n- These are leftovers from the result table\u0027s old in-table download-all\n/ bulk binary download UI (#2869, #2931), which was later reworked into\nthe separate result-exportation component; the rules are referenced\nnowhere in the component template, TypeScript, or anywhere in\n`frontend/src`.\n- The still-live per-cell download styles (`.download-button`,\n`.table-row-hover`, `.table-container`) are untouched.\n### Any related issues, documentation, discussions?\nCloses: #8897\n### How was this PR tested?\n- Static, non-functional change (CSS dead-code removal); no behavior\nchanges, so no test added.\n- Verify no references exist: run `rg -n\n\"data-size|borderless-button|table-footer|download-all-button\"\nfrontend/src` and confirm there are no remaining hits.\n- Open the result panel table, hover a cell, and confirm the per-cell\ndownload icon and all table styling render unchanged.\n### Was this PR authored or co-authored using generative AI tooling?\nCo-authored with Claude Opus 4.8 in compliance with ASF"
    },
    {
      "commit": "404df27238ce46d8b9216fba1adcfa1b0a99a369",
      "tree": "0549c98c78bdee76c64c922028787a98ae688c61",
      "parents": [
        "2cd44ee0d8219a7cc0f16e8c4ee869c0bad9feec"
      ],
      "author": {
        "name": "Matthew B.",
        "email": "mgball@uci.edu",
        "time": "Wed Oct 07 08:59:41 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 07 08:59:41 2026 +0000"
      },
      "message": "refactor(workflow-operator): remove commented-out scorer-name helpers (#8900)\n\n### What changes were proposed in this PR?\n- Remove two fully commented-out private defs\n(`getClassificationScorerName`, `getRegressionScorerName`) from\n`MachineLearningScorerOpDesc.scala`.\n- Their logic is already provided by the live `getMetricName`, which\ndoes the same `getName()` dispatch across both metric types, so the\ncommented block was dead scaffolding.\n### Any related issues, documentation, discussions?\nCloses: #8899\n### How was this PR tested?\n- Non-functional change (removal of commented-out code only); no\nbehavior changes, so no test added.\n- Confirm the names are referenced nowhere: run `rg -nw\n\"getClassificationScorerName|getRegressionScorerName\"` and expect no\nhits.\n### Was this PR authored or co-authored using generative AI tooling?\nCo-authored with Claude Opus 4.8 in compliance with ASF"
    },
    {
      "commit": "2cd44ee0d8219a7cc0f16e8c4ee869c0bad9feec",
      "tree": "f03e4ebfd4df79ff768e0551ab9077bcd3946fbb",
      "parents": [
        "b76048948b64e9aa87509c627700f5573c955508"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Wed Oct 07 05:52:38 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 07 05:52:38 2026 +0000"
      },
      "message": "ci: flag PRs that close an issue someone else claimed (#8678)\n\n### What changes were proposed in this PR?\n\nAdds a check to `pr-assignment.yml` that flags a PR closing an issue\nsomeone else has already claimed. It also stops the merge-time credit\nstep from unassigning a claimant whose own PR is still open.\n\n```\nBefore:  #8267 open (claimant) ── #8339 \"Closes #8149\" ── (silence) ── #8339 merges\n         ── claimant unassigned from #8149, #8267 left with 0 changed files\nAfter:   #8267 open (claimant) ── #8339 \"Closes #8149\" ── comment on #8339 names the claimant + #8267\n                                                     ── #8339 merges ── claimant stays assigned while #8267 is open\n```\n\n| Where | Change |\n| --- | --- |\n| New step \"Flag linked issues someone else has claimed\" (PR `opened` /\n`edited`) | For each open same-repo issue in `closingIssuesReferences`,\nflags it when **(a)** it has an assignee other than the PR opener, or\n**(b)** its `closedByPullRequestsReferences` lists another `OPEN` PR by\na different author. Posts or updates one `\u003c!--\ntexera:issue-claim-conflict --\u003e` comment with an issue / claimant / PR\ntable, and deletes the comment once nothing matches. If overlapping runs\neach post a copy, every run keeps the oldest and deletes the others, so\nthey end up keeping the same comment (`claimCommentChanges`). A run can\nalso read the PR before an edit and write after a newer run has\nfinished, so after any write it reads the PR again and repeats until a\npass changes nothing (`syncClaimComment`, at most 3 passes). The last\nrun to write is then also the last to read, and it corrects a stale\nwrite. |\n| \"Credit issue assignees on PR merge\" | Keeps an assignee who has their\nown open PR on the issue. If that PR later closes without merging, the\nexisting close-without-merge step still unassigns them. |\n| `.github/scripts/issue-claims.js` | The decision logic, which both\nsteps `require`. It is checked out from the base branch, which is safe\nunder `pull_request_target`. The workflow now declares `contents: read`\nfor that checkout. |\n\n**(b) is needed on its own.** GitHub silently drops the opener\nself-assign for an outside contributor who never commented on the issue.\nFor example, #6674 shows no assignee but has the open PR #8603.\n\n**It posts a comment and does not fail a check:**\n\n| Reason | Detail |\n| --- | --- |\n| Both PRs match | The claimant\u0027s own PR matches the rule too: #8267\nwould flag #8339 back. A failing check would also land on the person the\nrule protects. |\n| Some takeovers are agreed | Only a person can tell a duplicate from an\nagreed takeover. One of the 2 PRs it would flag today (below), #8484, is\nan agreed takeover, and a failing check would block it. |\n| It would go stale | The check runs again only when this PR is opened\nor edited. Closing the other PR or unassigning someone doesn\u0027t re-run\nit, so a failed check would stay red until someone edits the PR. |\n\nOn its first post, the comment @-mentions the claimant, so they get a\nnotification. The #8149 claimant never got one. Closed issues are\nskipped, because the risk is two PRs in progress at once. Both queries\nread up to 100 linked PRs per issue. That is the GraphQL maximum; no\nissue in this repo has more than 5. There is no concurrency group: with\nthe default queue, a group cancels a waiting run, and the body-edit\nunassign and the merge credit need every event. One known limitation:\nthe comment is refreshed only when this PR is edited, not when the other\nPR closes.\n\n### Any related issues, documentation, discussions?\n\nCloses #8676\n\nComplements #8675, which adds an AGENTS.md rule to check claims before\ncoding. This PR catches the cases that rule misses.\n\n### How was this PR tested?\n\nUnit tests: 32 pass. Two of them replay the #8149 and #6674 incidents as\nGraphQL fixtures.\n\n```bash\nbash .github/scripts/test_issue_claims.sh   # tests 42, pass 42, fail 0\n```\n\nThe `infra` job picks these up through its `test_*.sh` discovery.\nMutation check: reverting the credit fix fails the #8149 merge test, and\ndropping (b) fails the #6674 test. For `claimCommentChanges`, removing\nany one of the id sort, the Bot-only filter, the deletion of extra\ncopies or the unchanged-body check fails at least one test. For\n`syncClaimComment`, limiting it to one pass fails both delayed-run\ntests.\n\n`pull_request_target` runs the workflow from `main`, so this PR can\u0027t\nrun its own steps. Instead, I ran both edited `github-script` steps,\nextracted from the YAML, in a local harness. GraphQL calls went to the\nlive API (read-only). Every REST write was recorded, not sent.\n\n| Scenario | Result |\n| --- | --- |\n| #8339 opened, fixture \u003d #8149 as of 2026-09-02 | posts 1 comment:\n`#8149 · \u003cclaimant\u003e (assignee) · #8267` |\n| edited, with an older bot comment and a human comment quoting the\nmarker | updates only the bot comment |\n| edited again, comment already current | no write |\n| edited after `Closes #8149` is removed | deletes the bot comment; the\nhuman comment is left alone |\n| live: #8603 opened (#6674) | no conflict, no writes |\n| live: #8484 edited | posts 1 comment naming the #6939 assignee |\n| credit step, fixture \u003d #8339\u0027s merge on 2026-09-25 | #8149 keeps its\nclaimant (`kept (own open PR)\u003d[…]`); an assignee without a PR on #8338\nis still removed |\n| credit step, live query on #8339 | query valid, no writes |\n| race: this run posts, then its re-list shows an older copy from\nanother run | deletes its own copy (and first updates the older one if\nit is stale) |\n| re-list after posting fails, or a delete returns 404 | logs a warning\nand stops; a 404 skips only that one delete |\n| edited, with two copies left by an earlier race | updates the oldest,\ndeletes the other |\n| delayed run: reads the claim, a newer run removes it, then the delayed\nrun posts | its re-read finds nothing to flag and deletes its own post |\n| delayed run: writes old text over a newer run\u0027s comment | its re-read\nrestores the newer text |\n| live: guard and credit queries with `first: 100` | both valid against\nthe schema |\n\nI also modelled two racing runs against one shared comment list and\ntried every ordering of their API calls, using the real\n`claimCommentChanges`. Whenever both runs see the same state, exactly\none up-to-date comment is left; 104 orderings for an open followed by a\nquick edit. When both runs find nothing to flag, no comment is left.\n\nDry run over every open PR: 218 open, 188 with closing references, **2\nflagged**. Both are real claims:\n\n| PR | Issue | Claim |\n| --- | --- | --- |\n| #5558 (draft) | #5422 | the issue\u0027s author assigned themselves |\n| #8484 | #6939 | a `/take` that was never released; a maintainer later\ntold #8484\u0027s author to go ahead |\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n---------\n\nCo-authored-by: Claude Opus 5.5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "b76048948b64e9aa87509c627700f5573c955508",
      "tree": "fa561e55a8fcf13df269e4f053660602062bc1ba",
      "parents": [
        "007bf4328a2d0fdc9b0930eb6478e800db28e90c"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Tue Oct 06 23:16:44 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Oct 06 23:16:44 2026 +0000"
      },
      "message": "refactor(pyamber): remove the unused R TypeVar (#8877)\n\n### What changes were proposed in this PR?\n\nRemoves the unused `R \u003d TypeVar(\"R\")` from pyamber\u0027s\n`async_rpc_client.py`, and drops `TypeVar` from its `typing` import,\nwhich only existed for it. **+1/−3 lines.** There is no behaviour\nchange: nothing in the file refers to `R`, and the module\u0027s two\nimporters (`main_loop.py` and its test) import only `AsyncRPCClient` and\n`async_run`.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #2950 (2024-10-31), \"Migrate scala control\nmessages to protobuf\", together with the `TypeVar` import |\n| **Usage removed by** | **never used**. No annotation, `Generic[R]` or\nstring annotation has ever referred to it |\n\nIt has been unused for the eleven months since it was added.\n\n### Any related issues, documentation, discussions?\n\nCloses #8876\n\n### How was this PR tested?\n\nNo new tests.\n\nFrom `amber/`:\n\n- `ruff check src/main/python src/test/python \u0026\u0026 ruff format --check\nsrc/main/python src/test/python`: clean.\n- `python -m pytest -m \"not integration\"\nsrc/test/python/core/architecture/rpc/test_async_rpc_client.py`: 12\ntests, all pass.\n\nTo re-check:\n\n```\ngit grep -n \u0027TypeVar(\"R\")\u0027   # no hits\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "007bf4328a2d0fdc9b0930eb6478e800db28e90c",
      "tree": "cdc55f52bb771e3f75448ad260117e7397e5ceee",
      "parents": [
        "9a427ccfc8f2821a5ecd4a6a502baacc45c6d1cb"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Tue Oct 06 23:16:23 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Oct 06 23:16:23 2026 +0000"
      },
      "message": "refactor(frontend): remove the dead console-frame error style (#8881)\n\n### What changes were proposed in this PR?\n\nRemoves the `.error-message` rule from the console panel\u0027s stylesheet\n(`console-frame.component.scss`), which styles nothing. **−10 lines.**\nThere is no behaviour change. The component uses emulated encapsulation,\nits template has no `error-message` class (static or dynamic), its TS\nadds no classes at runtime, and its ng-zorro children never render one.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #1304 (2021-08-20), \"Properly update ConsoleFrame\nwhen state changes\", with a `\u003cdiv class\u003d\"error-message\"\u003e` listing\noperator errors |\n| **Usage removed by** | #2195 (2023-11-09), \"Enhance frontend error\nreporting\". It moved error display out of the console frame and deleted\nthat element |\n\nIt has been dead for nearly three years.\n\n### Any related issues, documentation, discussions?\n\nCloses #8880\n\n### How was this PR tested?\n\nNo new tests; no spec referenced the class.\n\nFrom `frontend/`:\n\n- `npx ng test --watch\u003dfalse\n--include\u003d\u0027**/console-frame.component.spec.ts\u0027\n--include\u003d\u0027**/result-panel.component.spec.ts\u0027`: 2 files, 105 tests, all\npass. The result-panel spec renders the console frame.\n- `yarn format:ci`: clean.\n- `npx ng build`: success.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "9a427ccfc8f2821a5ecd4a6a502baacc45c6d1cb",
      "tree": "518de8b8e6778a306b2cc519fd957c25c4093c4b",
      "parents": [
        "b43d46520365a42e8a5df892520bead6b2fb6cfe"
      ],
      "author": {
        "name": "Tanishq Gandhi",
        "email": "56472134+tanishqgandhi1908@users.noreply.github.com",
        "time": "Tue Oct 06 21:48:31 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Oct 06 21:48:31 2026 +0000"
      },
      "message": "fix(frontend): list a version\u0027s files when the Versions \u0026 Files tab opens (#8838)\n\n### What changes were proposed in this PR?\n\nThe version file tree uses virtual scroll, which measures its viewport\nonce and then only on scroll. On the dataset and model detail pages the\ntree sits in the \"Versions \u0026 Files\" tab, which is hidden when the page\nloads. So the files arrived while the tree measured a 0px viewport, and\nit drew no rows until switching versions changed its height and forced a\nre-measure.\n\nThe tree now re-measures itself whenever its container is shown or\nresized, using a `ResizeObserver`. The fix is inside the tree component,\nso the dataset page, the model page and the two version pickers that\nreuse it are all covered. No change to the host pages.\n\n- `user-dataset-version-filetree.component.ts`: observe the container\nand call `tree.sizeChanged()` (past the library\u0027s throttle) on resize;\ndisconnect on destroy. The existing re-measure on a height change goes\nthrough the same helper.\n- `user-dataset-version-filetree.component.html`: `#container` ref on\nthe tree\u0027s container.\n\nBefore: dataset and model right after opening the tab:\n\n\u003cimg width\u003d\"1440\" height\u003d\"900\" alt\u003d\"annotated-before-dataset\"\nsrc\u003d\"https://github.com/user-attachments/assets/01d99d8c-179b-455f-ab03-68357b3164f3\"\n/\u003e\n\n\u003cimg width\u003d\"1440\" height\u003d\"900\" alt\u003d\"annotated-before-model\"\nsrc\u003d\"https://github.com/user-attachments/assets/01631a0b-0d66-428a-8161-17ba0568efe3\"\n/\u003e\n\n\nAfter: the same pages right after opening the tab:\n\n\u003cimg width\u003d\"1440\" height\u003d\"900\" alt\u003d\"annotated-after-dataset\"\nsrc\u003d\"https://github.com/user-attachments/assets/7c754657-b172-4b9f-a6a4-5c7fa53e54f7\"\n/\u003e\n\n\u003cimg width\u003d\"1440\" height\u003d\"900\" alt\u003d\"annotated-after-model\"\nsrc\u003d\"https://github.com/user-attachments/assets/747b0135-923d-4735-b0d8-62c2fed0b348\"\n/\u003e\n\n### Any related issues, documentation, discussions?\n\nCloses #8833\n\n### How was this PR tested?\n\nOne case added to\n`user-dataset-version-filetree.component.browser.spec.ts`: a tree filled\nwhile hidden renders its rows once shown. It fails without the fix (0\nrows) and passes with it.\n\n```\ncd frontend\nyarn ng run gui:test-browser --include\u003d\u0027**/user-dataset-version-filetree.component.browser.spec.ts\u0027\n# Tests  6 passed (6)\nyarn ng test --watch\u003dfalse --include\u003d\u0027**/user-dataset-version-filetree.component.spec.ts\u0027 --include\u003d\u0027**/dataset-detail.component.spec.ts\u0027 --include\u003d\u0027**/model-detail.component.spec.ts\u0027\n# Tests  249 passed (249)\n```\n\nAlso checked against a local stack: on a dataset and a model with two\nversions, the latest version\u0027s files are listed as soon as the \"Versions\n\u0026 Files\" tab opens, and switching versions still updates the list.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\nCo-authored-by: Meng Wang \u003cmengw15@uci.edu\u003e"
    },
    {
      "commit": "b43d46520365a42e8a5df892520bead6b2fb6cfe",
      "tree": "4cb03688576be80bc07dd5c8a6f06991e34c6b71",
      "parents": [
        "1df2c567ac0f4b81862586927320733dcff9dee9"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Tue Oct 06 05:32:13 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Oct 06 05:32:13 2026 +0000"
      },
      "message": "refactor(frontend): remove dead computing-unit modal leftovers (#8827)\n\n### What changes were proposed in this PR?\n\nRemoves two leftovers from `ComputingUnitCreateModalComponent`. **−2\nlines.** There is no behaviour change.\n\n- `\u003cng-template #addComputeUnitModalTitle\u003e`. The modal\u0027s title comes\nfrom `[nzTitle]\u003d\"getCreateModalTitle()\"`. Nothing else reads the\ntemplate: there is no `@ViewChild`, no outlet, and neither of the two\nhosts that open the modal passes it. `nz-modal` only picks up its\ntitle/content/footer directives, never a plain `#ref` template.\n- The `selectedShmSize` field. The create payload builds `shmSize` from\n`shmSizeValue` / `shmSizeUnit`, which stay.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #3315 (2025-03-13), \"Add computing unit manager\nfrontend\": the title template. #3451 (2025-05-28), \"Enable adjusting\nshared memory for the computing unit\": `selectedShmSize` |\n| **Usage removed by** | #3400 (2025-05-26) switched the title to\n`getCreateModalTitle()`. #4331 (2026-04-09), \"add full computing unit\ntab\", dropped the field\u0027s last write and read. #6082 later moved both,\nstill unread, into this shared component |\n\nThe title template has been unused for sixteen months, and the field for\nsix.\n\n### Any related issues, documentation, discussions?\n\nCloses #8826\n\n### How was this PR tested?\n\nNo new tests; no spec referenced either item.\n\nFrom `frontend/`:\n\n- `npx ng test --watch\u003dfalse\n--include\u003d\u0027**/computing-unit-create-modal.component.spec.ts\u0027\n--include\u003d\u0027**/user-computing-unit.component.spec.ts\u0027\n--include\u003d\u0027**/computing-unit-selection.component.spec.ts\u0027`: 3 files, 248\ntests, all pass. The other two specs cover the modal\u0027s two hosts.\n- `yarn format:ci`: clean.\n- `npx ng build`: success.\n\nTo re-check:\n\n```\ngit grep -n \"addComputeUnitModalTitle\\|selectedShmSize\" -- frontend   # no hits\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "1df2c567ac0f4b81862586927320733dcff9dee9",
      "tree": "a524b1e40c03133d1908d6a72d80055ba21873e0",
      "parents": [
        "e2bd0cdae31af7a1f05f150ce24da7214c4a429b"
      ],
      "author": {
        "name": "Meng Wang",
        "email": "mengw15@uci.edu",
        "time": "Mon Oct 05 23:34:18 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 05 23:34:18 2026 +0000"
      },
      "message": "fix(licensing): restore the ScalaPB notice on the vendored scalapb.proto (#8806)\n\n### What changes were proposed in this PR?\n\nPer the note at the end of #8802,\n`common/workflow-core/src/main/protobuf/scalapb/scalapb.proto` is\nvendored\nfrom ScalaPB (Apache-2.0) but carried the standard ASF header — the same\nclass of problem as #8775. Mirroring that fix:\n\n- `scalapb.proto`: ASF header → a vendored-from notice (upstream ships\nthe\nfile with no header; its license is the repository-level Apache-2.0, so\nno\n  separate license copy is needed);\n- root `LICENSE`: a ScalaPB entry next to the other Apache-2.0\nthird-party\n  entries (\"this LICENSE file\");\n- `.licenserc.yaml`: exempt the file from the ASF-header check.\n\nComment-only change to the proto; protoc output is unaffected. This\naddresses\nonly the vendored-file item in #8802 — the build-time-generation\nproposal\nstays open there.\n\n### Any related issues, documentation, discussions?\n\nAddresses the vendored scalapb.proto item in #8802. Same pattern as\n#8775/#8776.\n\n### How was this PR tested?\n\nLicense-metadata-only change; the Check License Headers CI job verifies\nthe\nexemption. The file is identical on main and both release branches.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (claude-fable-5)"
    },
    {
      "commit": "e2bd0cdae31af7a1f05f150ce24da7214c4a429b",
      "tree": "80b3b982fb0c66954fa5bd7bd22e20433d086e89",
      "parents": [
        "d69d740f2492cddf5826ac4279b328185c245455"
      ],
      "author": {
        "name": "Ryan Zhang",
        "email": "97552093+zyratlo@users.noreply.github.com",
        "time": "Mon Oct 05 23:08:10 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 05 23:08:10 2026 +0000"
      },
      "message": "feat(notebook-migration): support migrating local Python folders into workflows (#8767)\n\n### What changes were proposed in this PR?\n\nThe migration tool accepted a Jupyter notebook and a single Python file.\nIt now accepts a folder of Python files selected from disk, and produces\none workflow from all of them, with the same stored source and operator\nmapping that drive highlighting in the Jupyter panel.\n\nA folder is harder than a script for the same reason a script was harder\nthan a notebook: the mapping keys on cells, and there are none. This PR\ndoes not introduce a second mechanism for that. The folder\u0027s Python\nfiles are concatenated into one document, each behind a banner line\nnaming the file it came from, with line numbers running continuously\nacross the whole thing. The model then reports line ranges exactly as it\ndoes for a single script, and #8007\u0027s segmenter derives the cells. The\nmapping stays keyed on cell uuids, so storage, the Jupyter panel and the\nhighlight index never learn that folders exist. No backend, database,\nHelm, or dependency changes.\n\nThe alternative was to number each file separately and key the mapping\non file plus line range. That changes the stored mapping shape, which\npulls in the backend, the database and the panel, to buy provenance the\nbanner line already provides.\n\nMain pieces:\n\n* `folder-assembly.ts`, a new pure module: which files are in scope, the\norder they are joined in, the assembled document, the layout, the caps,\nand entry point resolution. It reuses the segmenter\u0027s own line\nsplitting, so assembling, numbering the prompt and slicing the cells all\nagree on what a line is.\n* `segmentScript` gains one optional argument, a list of caller-required\ncut points. Each file\u0027s banner joins the boundary set, so no cell holds\nlines from two files. Every invariant the module already documented\nholds unchanged.\n* An indented layout of the folder, sent as prompt text ahead of the\nnumbered document. It is deliberately not part of that document:\nnumbering it would shift every line the model reports, and the segmenter\nwould emit it as a cell of directory listing. It also names the folder\u0027s\nnon-Python files without reading them, so the model knows a dataset or a\nrequirements list exists.\n* Folder variants of the conversion prompt, the mapping prompt, and the\nworked example. `migration-prompts.ts` is 232 insertions and 10\ndeletions. All 232 insertions are the new folder constants. The 10\ndeletions are apostrophe fixes raised in review (`ID\u0027s` to `IDs`,\n`key\u0027s` to `keys`, `UDF\u0027s` to `UDFs` where it is a plural), applied\nuniformly to the notebook, script and folder prompts so the three do not\ndrift apart on wording. No other notebook or script prompt text changed.\n\nThe derived notebook holds the entry point alone, not every file. A\nfolder\u0027s other files are function definitions, and a notebook of all of\nthem reads as a wall of code rather than the story of what the project\ndoes. The model names the entry point in the conversion reply, so this\ncosts no extra round trip, and the mapping it reports is expressed in\nthat file\u0027s lines. Clicking an operator highlights the call that runs\nit. When the entry point cannot be resolved the notebook falls back to\nthe whole folder, which is worse to read but never empty.\n\nTwo caps refuse an oversized folder before any request is sent: 100\nfiles, and 60,000 characters of code. The binding constraint is the\nreply rather than the prompt, because the conversion asks the model to\nreturn every line of code as JSON-escaped strings and no output budget\nis set. A cap the model cannot meet would defeat the point of refusing\nup front, since the user would wait out a full conversion and get a JSON\nparse error from a truncated reply. A byte check runs before anything is\nread, so one enormous generated file cannot be loaded into memory first.\n\nDropping a folder onto the upload button is refused with a message.\nng-zorro binds a drop handler on the button whatever its type, and in\ndirectory mode it hands over one file at a time with no path attached,\nso accepting a drop would stage a single arbitrary file and convert it\nas if it were the whole project.\n\nThree things ride along:\n\n* The three import modal diagrams are normalized to one size. They were\nthe same layout exported at three resolutions with uneven whitespace, so\nthe tabs rendered at slightly different scales. Trimming each to its\ncontent and scaling to a common canvas touches two images from earlier\nPRs.\n* `LICENSE-binary` credits `snippet_folder` for the new diagram, and\nadds `python_file_diagram.png` to the Material Symbols paths. That\nsecond entry fills an attribution gap from #8007, where the same icons\nwere reused without extending the path list.\n* A final commit consolidates the folder caps and the\n`webkitRelativePath` parsing, which had spread across two files while\nthe feature was built.\n\n#### Demo video\n\n\nhttps://drive.google.com/file/d/1KtI2FVWgOwoGCFZfnIWXLGurBcXQmmkz/view?usp\u003dsharing\n\n### Any related issues, documentation, discussions?\n\nCloses #8008\nParent-issue #4301\n\nThe reasoning for keeping the mapping and Jupyter panel on an input\nwithout cells was settled for scripts in\nhttps://github.com/apache/texera/discussions/8489 and applies to folders\nunchanged.\n\nThe output budget argument behind the character cap applies just as much\nto a single `.py` and to a notebook, neither of which has a size cap\ntoday, and joining a project into one script is an easy way around the\nfolder cap. That is worth its own issue rather than widening this one.\n\n### How was this PR tested?\n\nUnit tests:\n\n* `folder-assembly.spec.ts`, new, 59 tests. File selection, ordering,\nassembly, the layout, the caps, entry point resolution and scoping. Two\ncases are worth naming. Directories sort by segment, so a sibling whose\nname sorts between a directory and its subdirectory (`src`, `src-old`,\n`src/utils`) cannot be rendered as the wrong parent. And an ambiguous\nentry point name resolves to null rather than to whichever file sorts\nfirst, because showing the wrong file is worse than falling back to the\nwhole folder.\n* `script-segmentation.spec.ts`, 32 to 36. Forced cut points, including\nthat out of range and non-integer boundaries are dropped rather than\nclamped.\n* `migration-llm.spec.ts`, 42 to 57. The layout is sent ahead of the\ncode and never numbered, cuts land on every file banner, a range\nstraddling a seam still maps to the cells on both sides, and the entry\npoint scopes the notebook with a fallback when it cannot be resolved.\n* `notebook-migration.service.spec.ts`, 48 to 65. Reading a selection,\nthe layout it produces, and each cap, including that the file count and\nbyte checks run before any file is read.\n* `notebook-import-modal.component.spec.ts`, 27 to 39. The third tab,\nthe directory picker, and the drop path modelled the way a real drop\narrives: one file per call, each in its own one-element list, with no\npath.\n* `user-workflow.component.spec.ts`, 81 to 87. Dispatch on selection\nshape, and that a folder names its workflow after itself.\n\nManually tested end to end against a live model with a small multi-file\nproject (a package with an entry point, two modules and a helpers-only\nmodule, plus non-Python files and a `__pycache__`).\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5)"
    },
    {
      "commit": "d69d740f2492cddf5826ac4279b328185c245455",
      "tree": "6876a819c5d8ba05c985f3b4c835bc34b8032e6b",
      "parents": [
        "e2e0225263bf5400b5f6d2d6c99475b9e836cc04"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Mon Oct 05 22:14:40 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 05 22:14:40 2026 +0000"
      },
      "message": "refactor(frontend): remove dead hub workflow detail markup (#8748)\n\n### What changes were proposed in this PR?\n\nRemoves three leftovers from `HubWorkflowDetailComponent`. **−24\nlines.** There is no behaviour change.\n\n- **Template:** the empty `\u003cng-template #codeEditor\u003e\u003c/ng-template\u003e`.\nNothing reads it: the component has no `@ViewChild`, and the only other\n`#codeEditor` in the app is the live one in `workspace.component.html`.\n- **Styles:** the `.workflow-steps`, `.workflow-step`, `.workflow-step\nh3` and `.workflow-step p` rules, which no markup uses.\n- **Styles:** the `body` rule. Under the default emulated encapsulation\nAngular compiles it to `body[_ngcontent-…]`, and the document `\u003cbody\u003e`\n(static in `index.html`) never carries that attribute, so it matches\nnothing.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #2725 (2024-09-24), \"Add Hub\": the step styles and\nthe `body` rule. #2873 (2024-09-27), \"Add workflow preview to hub\ndetails page\": the `#codeEditor` anchor |\n| **Usage removed by** | #3006 (2024-11-05), \"Remove home page and step\nfrom the detail page\": the step markup. #3007 (2024-11-05), \"Fix sharing\nissue of hub preview\": the `@ViewChild(\"codeEditor\")` that read the\nanchor. The `body` rule never matched anything |\n\nThe step styles and the anchor have been dead for nearly two years. The\n`body` rule never took effect.\n\n### Any related issues, documentation, discussions?\n\nCloses #8747\n\n### How was this PR tested?\n\nNo new tests.\n\nFrom `frontend/`:\n\n- `npx ng test --watch\u003dfalse\n--include\u003d\u0027**/hub-workflow-detail.component.spec.ts\u0027\n--include\u003d\u0027**/card-item.component.spec.ts\u0027\n--include\u003d\u0027**/list-item.component.spec.ts\u0027\n--include\u003d\u0027**/workspace.component.spec.ts\u0027`: 4 files, 221 tests, all\npass. The card-item and list-item specs open this component in a modal,\nand the workspace spec owns the live `#codeEditor`.\n- `yarn format:ci`: clean.\n- `npx ng build`: success.\n- After also removing the `body` rule: the hub-workflow-detail,\ncard-item and list-item specs pass (3 files, 186 tests), and `prettier\n--check` on the stylesheet is clean.\n\nTo re-check:\n\n```\ngit grep -n \"workflow-step\" -- frontend   # no hits\ngrep -n \"^body\" frontend/src/app/hub/component/workflow/detail/hub-workflow-detail.component.scss   # no hits\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\n---------\n\nCo-authored-by: Claude Opus 5.5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "e2e0225263bf5400b5f6d2d6c99475b9e836cc04",
      "tree": "9239e0c29f9c47f7188b07fcb5a3eef910079668",
      "parents": [
        "e848f945ca8b315b3bc3419e1354bf5928cd71fc"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Mon Oct 05 21:53:13 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 05 21:53:13 2026 +0000"
      },
      "message": "fix(frontend): restore the hub workflow view-count toggle (#8752)\n\n### What changes were proposed in this PR?\n\nClicking the eye (\"View\") button on the hub workflow detail page\nswitches the view count between the compact form (`1.2k`) and the exact\ncount (`1,234`) again. The button has done nothing since #3028.\n\n**Root cause.** Only one method read `displayPreciseViewCount`:\n`formatViewCount`. #3028 deleted it as a duplicate of the like-count\nformatter, but the two were not the same. `formatViewCount` skipped the\n`k` abbreviation while the flag was set. The button, its `(click)`\nhandler and the flag were all kept, so each click flipped a flag that\nnothing read.\n\n```\nBefore:  click eye -\u003e \"1.2k\";  click again -\u003e \"1.2k\"\nAfter:   click eye -\u003e \"1,234\"; click again -\u003e \"1.2k\"\n```\n\n`formatViewCount` comes back as a thin wrapper over the shared\n`formatCount`, and the view button\u0027s label uses it again. The exact\ncount is grouped by thousands with the app\u0027s `LOCALE_ID`, the same\nformatting as the `number` pipe used elsewhere in the UI. The app sets\nno `LOCALE_ID`, so it shows `1,234`. The like and clone counts still go\nthrough `formatCount` and stay compact.\n\n| | Default | After one click |\n| --- | --- | --- |\n| **Before** | ![before,\ndefault](https://raw.githubusercontent.com/aglinxinyuan/texera/630604d0570603be76e7caac68436e82575d6d1c/before-default.png)\n| ![before,\nclicked](https://raw.githubusercontent.com/aglinxinyuan/texera/630604d0570603be76e7caac68436e82575d6d1c/before-clicked.png)\n|\n| **After** | ![after,\ndefault](https://raw.githubusercontent.com/aglinxinyuan/texera/630604d0570603be76e7caac68436e82575d6d1c/after-default.png)\n| ![after,\nclicked](https://raw.githubusercontent.com/aglinxinyuan/texera/630604d0570603be76e7caac68436e82575d6d1c/after-clicked.png)\n|\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #2930 (2024-10-28), \"Add view count to workflow\":\nthe eye button, `changeViewDisplayStyle()`, `displayPreciseViewCount`,\nand `formatViewCount`, which read the flag. The PR\u0027s demo shows the\nexact count after a click |\n| **Usage removed by** | #3028 (2024-11-11), \"Remove duplicate and\nunnecessary code\": deleted `formatViewCount` and switched the label to\n`formatCount` |\n\nThe toggle worked for two weeks and has done nothing for almost two\nyears since. The dataset detail page\u0027s copy of the button is a different\ncase: #3269 added it after #3028, so it never worked there, and #8746\nremoves it.\n\n### Any related issues, documentation, discussions?\n\nCloses #8751\n\n### How was this PR tested?\n\nThe old spec case only checked that the flag flipped, and it passed\nwhile the button did nothing. It is replaced by:\n\n| Surface | Pinned |\n| --- | --- |\n| `formatViewCount` | Compact by default. Exact (`1,234`) after one\ntoggle, compact again after a second. `1000` shows as `1.0k` / `1,000`.\n`0`, `1` and `999` look the same in both styles. The compact style of\n`1234567` equals `formatCount`, and the exact style is `1,234,567`. With\n`LOCALE_ID` set to `de`, the exact style is `1.234` |\n| Rendered view button (real template) | Shows `1.2k` for 1234 views. A\nclick shows `1,234`, a second click `1.2k`. Same when the page opens as\na modal. The like count stays `2.5k` after the view button is clicked |\n\nThe rendered-button cases were run against `main`\u0027s component first and\nfail there with `expected \u00271.2k\u0027 to be \u00271,234\u0027`.\n\nFrom `frontend/`:\n\n- `npx ng test --watch\u003dfalse\n--include\u003d\u0027**/hub-workflow-detail.component.spec.ts\u0027`: 52 tests, all\npass.\n- `yarn format:ci`: clean.\n- `npx ng build`: success.\n\nScreenshots: `ng serve` against a stub API that reports 1234 views, 56\nlikes and 12 clones. Headless Chromium at 1280×720 via Playwright, with\nthe button row captured before and after one click on the eye.\n**Before** is the same page running `main`\u0027s component.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "e848f945ca8b315b3bc3419e1354bf5928cd71fc",
      "tree": "215dd55926513e1bf1091ab1d5ab9164bc882983",
      "parents": [
        "57763e763bef80a5a162bc7b594a4747852ca11e"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Mon Oct 05 21:42:16 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 05 21:42:16 2026 +0000"
      },
      "message": "docs: check issue claims before coding and closing (#8675)\n\n### What changes were proposed in this PR?\n\nAdds a claim check to the **Issues and PRs** section of `AGENTS.md`, so\na coding agent doesn\u0027t duplicate an issue someone else already claimed.\n\n```\nBefore:  file issue (unassigned) -\u003e contributor /takes it + opens PR\n         -\u003e agent\u0027s bundled PR also writes \"Closes #N\" -\u003e merges first\n         -\u003e merge-time credit step drops the contributor from the assignees\nAfter:   agent /takes what it files; before coding, and again before opening\n         the PR, it checks every issue its diff fixes, and leaves out any taken one\n```\n\n| Change | Where |\n| --- | --- |\n| `/take` step added to the issue → PR flow diagram | diagram |\n| \"Claim before coding\": an issue is **taken** if someone else is\nassigned, or a linked PR is `OPEN` and someone else wrote it; the three\n`gh` commands that check this | new bullet |\n| Re-check right before opening the PR, for every issue the diff fixes\n(closed or only related, each site of a bundled PR); if one is taken,\nleave out that issue and its code change | \"Reference the issue\" bullet\n|\n\nThe linked-PR half of the check matters: GitHub drops the PR-opener\nauto-assign for an outside contributor who never commented on the issue.\nSo an issue can show no assignee while it has an open PR (e.g. #6674 /\n#8603).\n\n### Any related issues, documentation, discussions?\n\nCloses #8677\n\nRelated to #8149 and #8267.\n\n### How was this PR tested?\n\nDocs-only. Ran the new text\u0027s commands against `apache/texera`:\n\n| Issue | Assignees | Linked PRs | Verdict |\n| --- | --- | --- | --- |\n| #6674 | none | #8603 (open, another author) | taken |\n| #8674 | none | none | not taken |\n\n`CONTRIBUTING.md#-comment-commands` resolves on the rendered page.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Opus 5.5)\n\nCo-authored-by: Claude Opus 5.5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "57763e763bef80a5a162bc7b594a4747852ca11e",
      "tree": "21b78a2100de95dc5cd092fd7c330670c6a5ce43",
      "parents": [
        "0fc6e789aa1298e19f3428101c5fd069c5309fa4"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Mon Oct 05 21:30:14 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 05 21:30:14 2026 +0000"
      },
      "message": "refactor(frontend): remove dead DatasetDetailComponent code (#8746)\n\n### What changes were proposed in this PR?\n\nRemoves dead code from `DatasetDetailComponent` that its template\nstopped using during the dataset page\u0027s redesigns. **+2/−46 lines.**\nThere is no behaviour change.\n\n- **Members:** `versionCreatorBaseVersion`, `displayPreciseViewCount` +\n`changeViewDisplayStyle()`, and the `formatTime` / `formatSpeed`\naliases. The `format.util` import narrows to `formatCount`.\n- **Styles:** `.tag-settings-btn`, `.tag-settings-title`,\n`.tag-settings-row` (with its `span` and `::ng-deep .ant-switch` rules),\nand `.description-section`.\n- **Spec:** the \"view flags\" case keeps its maximize / right-bar\nassertions and drops the three for the removed toggle. It is renamed to\nmatch.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #2413 (2024-02-26), \"Introduce Dataset GUI\":\n`versionCreatorBaseVersion`. #3269 (2025-02-19): the precise-view-count\ntoggle. #3662 (2025-08-19): the speed/time aliases. #4337 (2026-03-29),\n\"improve dataset detail page layout\": the `.tag-settings-*` and\n`.description-section` styles |\n| **Usage removed by** | #3296 (2025-03-10):\n`versionCreatorBaseVersion`. #4337 (2026-03-29): the view-count toggle.\n#6493 (2026-07-27): tag settings moved to a Settings tab. #7043\n(2026-07-30): the description moved to the Data Card tab. #8078\n(2026-08-31): the speed/time aliases |\n\nEach piece was left behind by a redesign that moved its markup\nelsewhere. The oldest has been dead for eighteen months.\n\n### Any related issues, documentation, discussions?\n\nCloses #8745\n\n### How was this PR tested?\n\nNo new tests. The kept spec cases cover the remaining members.\n\nFrom `frontend/`:\n\n- `npx ng test --watch\u003dfalse\n--include\u003d\u0027**/dataset-detail.component.spec.ts\u0027`: 150 tests, all pass.\n- `yarn format:ci`: clean.\n- `npx ng build`: success.\n\nTo re-check:\n\n```\ngit grep -n -E \"versionCreatorBaseVersion|tag-settings|description-section\" -- frontend   # no hits\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "0fc6e789aa1298e19f3428101c5fd069c5309fa4",
      "tree": "a131e04bc124b0c66cca8aa1d9a0e035a01ff199",
      "parents": [
        "82ab13483dff640e580850d6f534964ae2d68029"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Mon Oct 05 21:29:59 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 05 21:29:59 2026 +0000"
      },
      "message": "refactor(workflow-core, pyamber): remove unused removeOne (#8744)\n\n### What changes were proposed in this PR?\n\nRemoves `removeOne` / `remove_one` from the buffered-writer API in both\nlanguages. No production code calls it. **−64 lines.** There is no\nbehaviour change.\n\n- **Scala:** the `BufferedItemWriter.removeOne` trait method, the\n`IcebergTableWriter` override, the no-op override in\n`OutputPortStorageWriterThreadSpec`\u0027s `StubWriter`, and the\n`IcebergTableWriterSpec` case that called it.\n- **pyamber:** the abstract `BufferedItemWriter.remove_one`, the\n`IcebergTableWriter` implementation, and its two tests.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #2681 (2024-06-05), \"Add MongoDocument and\nMemoryDocument\": the Scala trait method. #3147 (2025-01-08): the Iceberg\noverride. #3224 (2025-01-30), \"Add Storage Layer In Python\": the pyamber\ncopy |\n| **Usage removed by** | #3295 (2025-03-09), \"Use Output Ports of an\nOperator to Write Storage\". It commented out the last live call,\n`writer.removeOne(tupleValue)` in the progressive sink\u0027s set-snapshot\nretraction branch, and #3312 later deleted the commented line. The\npyamber method was **never used** |\n\nIt has been dead for eighteen months. Every remaining call is in a test.\n\n### Any related issues, documentation, discussions?\n\nCloses #8743\n\n### How was this PR tested?\n\nNo new tests. The writer specs keep their cases for the surviving API.\n\nLocally, with Java 17:\n\n- `sbt \"WorkflowCore/Test/compile\" \"WorkflowCore/testOnly\n*IcebergTableWriterSpec\"`: 4 tests, all pass.\n- `sbt \"WorkflowExecutionService/Test/compile\"\n\"WorkflowExecutionService/testOnly *OutputPortStorageWriterThreadSpec\"`:\n6 tests, all pass.\n- `sbt \"WorkflowCore/scalafmtCheckAll\" \"WorkflowCore/scalafixAll\n--check\" \"WorkflowExecutionService/scalafmtCheckAll\"\n\"WorkflowExecutionService/scalafixAll --check\"`: clean.\n\nFrom `amber/`:\n\n- `python -m pytest -m \"not integration\"\nsrc/test/python/core/storage/iceberg/test_iceberg_table_writer.py`: 12\ntests, all pass.\n- `ruff check src/main/python src/test/python \u0026\u0026 ruff format --check\nsrc/main/python src/test/python`: clean.\n\nTo re-check:\n\n```\ngit grep -n -i -E \"remove_?one\"   # no hits\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "82ab13483dff640e580850d6f534964ae2d68029",
      "tree": "19605e576c5f68d23d2fdc37fc562d3e2c79df7c",
      "parents": [
        "1603fd7e92b9c187d922020b0e1f79728d78b30b"
      ],
      "author": {
        "name": "Meng Wang",
        "email": "mengw15@uci.edu",
        "time": "Mon Oct 05 07:57:22 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 05 07:57:22 2026 +0000"
      },
      "message": "fix(licensing): restore the MIT notice on the vendored inner.py (#8776)\n\n### What changes were proposed in this PR?\n\n`inner.py` is vendored from https://github.com/sebkeim/inner-class (MIT,\nCopyright (c) 2019 sebkeim) but carried the standard ASF header and was\nmissing from LICENSE — ASF policy forbids both\n(https://www.apache.org/legal/src-headers.html#3party). Mirroring the\nkjetland/formly pattern:\n\n- `inner.py`: ASF header → MIT notice (code untouched)\n- `LICENSE`: new entry in the MIT third-party section\n- `licenses-3rd-party-code/inner-class.txt`: upstream license text,\nverbatim\n- `.licenserc.yaml`: exempt the file from the ASF-header check\n\n### Any related issues, documentation, discussions?\n\nCloses #8775. Surfaced by the podling release-checker on the\n1.2.1-incubating\nRC1 review; the file is identical on main and both release branches,\nhence the\nbackport labels.\n\n### How was this PR tested?\n\nLicense-metadata-only change; the Check License Headers CI job verifies\nthe\n.licenserc.yaml exemption.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (claude-fable-5)"
    },
    {
      "commit": "1603fd7e92b9c187d922020b0e1f79728d78b30b",
      "tree": "c8a95bcb683d44b0a81e5b478d4b9c68062897f0",
      "parents": [
        "2082021a8073c26bc38aeac7d654bdc661d4ff87"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Mon Oct 05 07:43:47 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 05 07:43:47 2026 +0000"
      },
      "message": "refactor(frontend): remove execution-snapshot leftovers (#8837)\n\n### What changes were proposed in this PR?\n\nRemoves the leftovers of the execution-snapshot column from the workflow\nexecution-history modal. **−14 lines.** There is no behaviour change.\n\n- **Styles:** the `.version-sample` and `.workflow-snapshot` rules in\n`workflow-execution-history.component.scss`. Nothing uses either class:\nthe template has no static or dynamic use, the component uses emulated\nencapsulation, and no other stylesheet or `::ng-deep` relies on them.\n- **Column width:** the `\"Workflow Version Sample\"` entry in\n`customColumnWidth`. `executionsTableHeaders` no longer lists that\ncolumn, so the template\u0027s `customColumnWidth[column]` lookup never reads\nthe key.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #1634 (2022-10-04), \"Introduce execution\nsnapshot\". It added a \"Workflow Version Sample\" column showing a\nsnapshot per execution, styled by these classes and sized by this width\nentry |\n| **Usage removed by** | #1695 (2022-10-18), \"Remove snapshot feature\nand fix version pagination\". It deleted the column header and the markup\nthat used both classes, but kept the rules and the width entry |\n\nThey have been dead for nearly four years.\n\n### Any related issues, documentation, discussions?\n\nCloses #8836\n\n### How was this PR tested?\n\nNo new tests; no spec referenced any of them.\n\nFrom `frontend/`:\n\n- `npx ng test --watch\u003dfalse\n--include\u003d\u0027**/workflow-execution-history.component.spec.ts\u0027\n--include\u003d\u0027**/admin-execution.component.spec.ts\u0027\n--include\u003d\u0027**/left-panel.component.spec.ts\u0027`: 3 files, 138 tests, all\npass. The last two specs cover the components that host this modal.\n- `yarn format:ci`: clean.\n- `npx ng build`: success.\n\nTo re-check:\n\n```\ngit grep -n -E \"version-sample|workflow-snapshot|Version Sample\" -- frontend   # no hits\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "2082021a8073c26bc38aeac7d654bdc661d4ff87",
      "tree": "4de3a1af7a324a61035d8c02dec7934322d2fe28",
      "parents": [
        "b05b6206c031ebb1cd4fb7b5f1f318a28f5c51f7"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Sat Oct 03 23:42:05 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 03 23:42:05 2026 +0000"
      },
      "message": "refactor(frontend): remove the unreachable agent panel shadow (#8829)\n\n### What changes were proposed in this PR?\n\nRemoves a class binding in `AgentPanelComponent` that can never apply.\n**+1/−11 lines.** There is no behaviour change.\n\n`\u003cul id\u003d\"return-button\"\u003e` has `[ngClass]\u003d\"{\u0027shadow\u0027: !width}\"` and\n`*ngIf\u003d\"width\"` on the **same element**. `*ngIf` creates the element\nonly while `width` is truthy, and `!width` is then always `false`. So\n`shadow` is never set on a rendered element. `width` is a `number` that\nis only ever 0, the 400px minimum, a resize width, or a range-checked\nstored width, so there is no value that is both truthy and falsy.\n\nThe PR removes:\n\n- the binding;\n- the `.shadow` rule, which nothing else in this component\u0027s template\nuses (the styles are encapsulated);\n- `NgClass` from the imports, because this was the template\u0027s only\n`ngClass`.\n\nThe `*ngIf` and every live style on the element stay.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #4020 (2025-11-25), \"feat: introduce the LLM-based\nworkflow copilot\": the binding, the `*ngIf` and the `.shadow` rule\ntogether. #4873 (2026-05-03) later added the `NgClass` import when the\ncomponent became standalone |\n| **Usage removed by** | **never used**. The binding has been\nunreachable since the line was written. #4495 only moved the files |\n\nIt has never applied, in the ten months since it was added.\n\n### Any related issues, documentation, discussions?\n\nCloses #8828\n\n### How was this PR tested?\n\nNo new tests; no spec referenced the class.\n\nFrom `frontend/`:\n\n- `npx ng test --watch\u003dfalse\n--include\u003d\u0027**/agent-panel.component.spec.ts\u0027\n--include\u003d\u0027**/workspace.component.spec.ts\u0027`: 2 files, 86 tests, all\npass. These are the only specs that render the panel.\n- `yarn format:ci`: clean.\n- `npx ng build`: success.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "b05b6206c031ebb1cd4fb7b5f1f318a28f5c51f7",
      "tree": "2af21e1fca40d8d58a24d698b0a7e474c94fa610",
      "parents": [
        "5d2bd21debb15c89effe47e68e6c87bc3661b4fc"
      ],
      "author": {
        "name": "Meng Wang",
        "email": "mengw15@uci.edu",
        "time": "Sat Oct 03 10:22:02 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 03 10:22:02 2026 +0000"
      },
      "message": "fix(licensing): drop the TMDb example dataset and list the bundled Iris dataset in LICENSE (#8803)\n\n### What changes were proposed in this PR?\n\nResolves #8799 in full:\n\n- **Drop the TMDb example dataset**\n(`bin/single-node/examples/datasets/popular-movies-of-imdb/`) and its\ndemo\nworkflow (`[Example] Data Exploration on Movies Dataset.json`). The\ndataset\nis CC0 only per the Kaggle uploader; the data (including movie overview\n  text) comes from TMDb, whose terms restrict redistribution, so the CC0\n  claim does not hold up. The examples loader discovers datasets and\n  workflows by scanning directories, so no script change is needed; the\nsingle-node examples now ship the Iris dataset and its ML demo workflow.\n- **root `LICENSE`**: new CC0 section listing the bundled Iris dataset,\n  referencing `licenses/LICENSE-CC0-1.0.txt` (already in-tree).\n- **`bin/single-node/LICENSE`**: the same entry with the in-bundle path.\n- **`create-release-candidate.yml`**: the compose-bundle step now ships\n`licenses/LICENSE-CC0-1.0.txt`, so the LICENSE reference resolves inside\n  the bundle.\n\n### Any related issues, documentation, discussions?\n\nCloses #8799.\n\n### How was this PR tested?\n\nLicense-text, workflow-config and file removals; YAML parse verified.\nThe\nexamples loader scans `datasets/*/` and `workflows/*.json` (checked\nagainst\n`bin/single-node/examples/load-examples.sh`). The next RC dispatch\nexercises\nthe changed bundle step.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (claude-fable-5)"
    },
    {
      "commit": "5d2bd21debb15c89effe47e68e6c87bc3661b4fc",
      "tree": "4aeb4a8769fc32431b04bccdd580e82253774e63",
      "parents": [
        "e0fe77acf7506c2b6e185b9849cb71a5d5b4fdc6"
      ],
      "author": {
        "name": "Kary Zheng",
        "email": "150742834+kz930@users.noreply.github.com",
        "time": "Sat Oct 03 07:43:57 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 03 07:43:57 2026 +0000"
      },
      "message": "feat(operator): reject label types the ML Scorer cannot score (#8765)\n\n### What changes were proposed in this PR?\n\nThe Machine Learning Scorer\u0027s schema check let any two columns of the\nsame type through as a classification pair. For BINARY and LARGE_BINARY\npairs, every metric then failed inside scikit-learn. For TIMESTAMP\npairs, Precision, Recall and F1 failed the same way. The error did not\nname either column. The check now rejects these pairs and names the two\ncolumns and the metrics that cannot score them. A TIMESTAMP pair scored\nby Accuracy alone is still accepted, since scikit-learn scores it (it\nonly counts equal rows).\n\n### Any related issues, documentation, discussions?\n\nCloses #8756.\n\n### How was this PR tested?\n\nThree new cases in `MachineLearningScorerOpDescSpec`:\n- BINARY and LARGE_BINARY pairs are rejected.\n- A TIMESTAMP pair is rejected for F1 and not for Accuracy.\n- A TIMESTAMP pair with Accuracy alone passes.\n\nThe first two fail without the change. The runtime failures were\nreproduced first by running the operator\u0027s generated metric code under\nscikit-learn 1.7.2 on each column type.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Claude Opus 5.5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "e0fe77acf7506c2b6e185b9849cb71a5d5b4fdc6",
      "tree": "327790b5425f452b0a80b23134b2640710fa10a5",
      "parents": [
        "5db1ca0e7fa20647216cbe573792360a1d368c78"
      ],
      "author": {
        "name": "Kary Zheng",
        "email": "150742834+kz930@users.noreply.github.com",
        "time": "Sat Oct 03 07:43:18 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 03 07:43:18 2026 +0000"
      },
      "message": "feat(operator): refuse duplicate sklearn parameter rows on export too (#8764)\n\n### What changes were proposed in this PR?\n\nThe standalone export of the advanced sklearn trainers now runs the same\ndistinct-parameter check as the engine path. Two rows naming one\nparameter used to emit the keyword twice, so the export reported success\nand the script then failed with a SyntaxError. The export now fails and\nnames the parameter.\n\n### Any related issues, documentation, discussions?\n\nCloses #8757.\n\n### How was this PR tested?\n\nA new case in `SklearnAdvancedBaseDescSpec` exports an operator with two\nrows naming one parameter and expects the refusal. It fails without the\nchange.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Claude Opus 5.5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "5db1ca0e7fa20647216cbe573792360a1d368c78",
      "tree": "2089a1d35cc9f74e8320b9a4ca5d3e454c3415cb",
      "parents": [
        "4f36c15468317c18a72d9434d262f30c1e6c482c"
      ],
      "author": {
        "name": "Kary Zheng",
        "email": "150742834+kz930@users.noreply.github.com",
        "time": "Sat Oct 03 07:42:38 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 03 07:42:38 2026 +0000"
      },
      "message": "feat(workflow-operator): export the samplers, Split and the control-flow operators as Python (#8710)\n\n### What changes were proposed in this PR?\n\nThe two samplers, Split, and If, Dummy and Sleep implement\n`StandaloneCodeGenerator`.\n\nThe samplers need more than a pandas expression. A sampler decides per\nrow whether to keep it, so which rows survive is fixed by the exact\nsequence `java.util.Random` produces; seeding Python\u0027s own generator\nwith the same number selects a different set, and the script would then\nreport a different sample than the workflow it came from.\n`SamplingHelpers` transcribes the generator, and the three operators\nthat draw from one, the two samplers and Split, emit it once per script.\n\nIf cannot receive the condition the workflow sets upstream, since that\nonly exists at run time. The script takes the True branch as before, and\nnow says so on stderr. The message names the variable to set before the\nstep to take the False branch.\n\nReview then found two places where the transcribed generator answered a\nquestion the engine answers differently. It carried its rejection sum as\na Python integer where Java lets an int overflow, and never refused the\nbound of zero a reservoir of nothing hands it.\n\nThe edge values the shared table now carries found one more. The\nreservoir sampler rebuilt its output from the rows\u0027 values, so pandas\ninferred each column again and a timestamp past 2262 came back as an\nobject column. It now takes the rows from the input by position.\n\n### Any related issues, documentation, discussions?\n\nPart of #8325, step 11c; that issue lists the set in order.\n\nCloses #8708, the task this change is the whole of.\n\n### How was this PR tested?\n\nEach operator asserts the block it emits in its own spec. What the\nverify tables cannot reach stays here as executed tests: the samplers\u0027\ndraws against `java.util.Random`, a reservoir of nothing, and the\nwarning If prints when nothing sets its condition.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Claude Opus 5.5 (1M context) \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "4f36c15468317c18a72d9434d262f30c1e6c482c",
      "tree": "76de09a9eb462db40849c758f05f67b6f51301e8",
      "parents": [
        "d7ce3a6bff97a43a380ce71ff48f3bc016b261ae"
      ],
      "author": {
        "name": "Kary Zheng",
        "email": "150742834+kz930@users.noreply.github.com",
        "time": "Sat Oct 03 07:42:13 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 03 07:42:13 2026 +0000"
      },
      "message": "feat(operator): export the estimators and the Hugging Face models (#8368)\n\n### What changes were proposed in this PR?\n\nThe scikit-learn estimators are fitted on one port and score on the\nother, so\nthe script holds both frames and narrows each by the same rule: a fit\nand a\nscore taken on different columns would compare two different models.\n\nThe four Hugging Face models declare the column types they take, and the\niris\nregression keeps the row when a petal measurement is empty rather than\nending\nthe run on it.\n\nSklearn Prediction and Sklearn Testing each consume a fitted model on an\ninput port. The verification fits one in Python and hands the same model\nto both paths, so they are run both ways like the rest.\n\nReview also turned up three defects that this PR fixes rather than\nmirrors. `SklearnTesting` squeezed the feature frame before predicting,\nso a single feature column, or the single row a drop left behind,\nreached scikit-learn as one dimension and was rejected. That was the\nexecutor\u0027s own behaviour and the export had copied it, so both paths\npass the frame itself now. Separately, the three HuggingFace text\noperators guarded a missing cell with `is None`. Arrow normalizes an\nempty cell to null, so that held for the executor as long as the column\nreally was a string, but `attributeTypeRules` is a warning the editor\nprints rather than a filter, and the exported script reads a frame where\na column holding nothing else comes back as float64. Both paths ask\npandas now. Third, the iris regression\u0027s engine code checked a missing\nmeasurement with `is None`, so a NaN went on to the model and got a\nprediction the export leaves empty. It now asks `pd.isna` too, as the\nexport does.\n\n### Any related issues, documentation, discussions?\n\nPart of #8325, 20 of 27; that issue lists the set in order. It needs\n#8327 for the trait, so it does not compile until that lands, and the\nrows these operators add to the verification runner follow with the\nharness rather than as whole new files here.\n\nCloses #8316, closes #8056.\n\nCloses #8422, the task this change is the whole of.\n\n### How was this PR tested?\n\nEach operator asserts the block it emits in its own spec. Once the\nharness lands, each is also run through the engine and through its\ngenerated script, on every configuration its schema offers, and the two\nanswers compared.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Opus 5)\n\n---------\n\nCo-authored-by: Claude Opus 5 (1M context) \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "d7ce3a6bff97a43a380ce71ff48f3bc016b261ae",
      "tree": "f5b00ecc223e060b7a70d6eaf1bc2d04d01071c9",
      "parents": [
        "b7993fbafac472d0ef1b87d86169978c42343ac4"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Sat Oct 03 07:40:27 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 03 07:40:27 2026 +0000"
      },
      "message": "feat(amber): bind $i loop-variable references in operators (#8639)\n\n### What changes were proposed in this PR?\n\nInside a loop block (LoopStart ... LoopEnd), a property of a JVM\noperator may now hold `$i`, a reference to the loop variable `i`. This\nworks for string and numeric/boolean properties alike; the frontend\n(#8640) sends the literal `\"$i\"`, and the operator\u0027s own code does not\nchange. The reference is handled in three places:\n\n- **Parse.** When `\"$i\"` cannot be converted to a numeric or boolean\nproperty\u0027s type, a Jackson problem handler (`StateReferenceModule`) puts\nin a typed placeholder (0 / 0.0 / false) and records the property\u0027s JSON\npointer in a hidden `stateReferences` sidecar on `LogicalOp`. Strings\nare left alone.\n- **Compile.** The compiler works out which operators sit inside a loop\nblock (`LogicalPlan.enclosingLoopStarts`: each operator\u0027s Loop Starts,\nfrom folds over the plan\u0027s topological order). Inside a block it also\nrecords every whole-string `\"$i\"` literal. Outside every block, a typed\nreference is a compile error.\n- **Worker.** The operator\u0027s own executor is built and opened as usual,\nwith the placeholders in its setting: the descriptor its constructor\nparses. The worker registers every state message on the executor right\nbefore `processState` (`OperatorExecutor.registerState` and `state`, the\nJVM counterpart of Python\u0027s `self.state` in #8642). Until the operator\nfirst sees data, each referenced variable that a message carries is\nwritten into that setting, in place. Right before the first tuple, or\nthe end of input, the worker checks that every reference has a value,\nand the setting is not written after that. Copies of one loop\u0027s state\nthat disagree are an error; an inner loop\u0027s value shadows an outer one\u0027s\n(the worker passes each message\u0027s nesting depth).\n\n**Which settings can hold `$i`** (inside a loop block)\n\n| Setting | Holds `$i`? | What the user sees |\n|---|---|---|\n| Text read while the operator processes rows (a Filter\u0027s value or\ncolumn, ...) | Yes | The iteration\u0027s value, written into the setting\nbefore the operator\u0027s first row |\n| Number, integer or decimal (Limit\u0027s `limit`, Interval Join\u0027s constant,\n...) | Yes | The iteration\u0027s value, converted to the setting\u0027s type.\nBefore the run, the compiler sees the placeholder `0` / `0.0` |\n| True/false | Yes | Same as a number, with the placeholder `false` |\n| A setting the compiled plan is built from: an output column\u0027s name or\ntype, or what an input is partitioned on (Projection\u0027s columns and Drop\nOption, Unnest String\u0027s and Dictionary Matcher\u0027s result column,\nAggregate, join keys, Type Casting, Sort Partitions) | No | With #8750,\na compile error: `Projection cannot refer to loop variables (/isDrop -\u003e\n$drop): its output schema or partitioning is built from that property\nwhen the workflow is compiled, before the loop runs`. With this PR\nalone, a wrong result or the operator\u0027s own error (Projection\u0027s\nmissing-column message) |\n| Any setting of an operator that runs generated or user code: Python\nUDFs (code editor included), sklearn, Python charts, Sort | No | Compile\nerror: `Sort cannot refer to loop variables yet (/attributes/0/attribute\n-\u003e $col): its code is generated before the loop runs` |\n| A dropdown of fixed choices (an enum, e.g. a Filter\u0027s condition) | No;\nthe panel (#8640) doesn\u0027t offer `$i` there | If it is sent anyway (e.g.\nthrough `SyncExecutionResource`), the workflow fails to parse with\nJackson\u0027s `not one of the values accepted for Enum class` |\n\n**Other cases** (replaces the current Case / Behaviour table)\n\n| Case | Behaviour |\n|---|---|\n| Outside every loop block | A text `\"$AAPL\"` stays a literal, as on\nmain. A number or true/false `\"$n\"` is a compile error: `Limit refers to\nloop variables (/limit -\u003e $n), but is not inside a loop block` |\n| An input the operator reads first is fed, even by a single link, from\noutside one of the operator\u0027s loop blocks: from outside the loop, from\nan outer loop\u0027s body, or from a sibling block | Compile error: `Interval\nJoin refers to loop variables (/constant -\u003e $i), but its input \u0027left\ntable\u0027 is fed from outside the loop block, so tuples from there can\narrive before the loop state`. An input read only after one that carries\nthe state (a join\u0027s probe side) may come from anywhere |\n| A name no enclosing Loop Start assigns (the panel flags it;\n`SyncExecutionResource` doesn\u0027t) | Fails at the operator\u0027s first row, or\nat its finish if it gets no rows: `property /limit refers to loop\nvariable n, but no state message carried it` |\n| A value that doesn\u0027t fit the setting | Fails at the same point:\n`property /limit refers to loop variable n, but its value abc does not\nfit it: ...` |\n| Nested loops that name the same variable | The inner loop\u0027s value wins\n|\n| Copies of one loop\u0027s state that reach an operator disagree (e.g. a UDF\nchanged `i` on one branch, and the branches meet) | Fails: `loop\nvariable i got two different values in one iteration, 1 and 2: a loop\u0027s\nvariables must not change inside its body`. On a single path there is\nonly one copy, so the operators after the UDF get its changed value |\n| Editing the operator while the workflow runs | Refused, with #8750 |\n\nWhich operators are inside a block is decided on the plan the compiler\nreceives. That plan has no disabled operators, and for run-to-operator\nit keeps only the target\u0027s upstream. The panel decides on the whole\ncanvas.\n\n**The operator\u0027s lifecycle is unchanged.** The value is set in the\noperator\u0027s setting when the state arrives, so the operator runs exactly\nas it does outside a loop:\n\n```\nworker starts                 state messages arrive                        first tuple\nexecutor built and opened,    registered on the executor (state), and      every reference has a value, or the operator\nplaceholders in its setting   each variable written into the setting,      fails naming the missing ones;\n                              in place (a later message wins)              the setting is not written after this\n```\n\n`open()` runs at worker start, and `produceStateOnStart` and\n`processState` run on the operator itself, with what they return used.\nThree executors used to read their setting before a state can arrive,\nand now read it at first use: Reservoir Sampling in its constructor, and\nSplit and Dictionary Matcher in `open()`. Every other JVM executor\nalready reads its setting while it processes data.\n\n### Any related issues, documentation, discussions?\n\nCloses #8635\n\nLands together with #8750, which makes `$i` in a setting the compiled\nplan is built from a compile error. Frontend: #8640 (merges after this\nPR). Python operators: #8642 (independent). User-facing overview:\nhttps://github.com/apache/texera/discussions/8643\n\n### How was this PR tested?\n\n| Suite | Result |\n|---|---|\n| WorkflowCore: `org.apache.texera.amber.core.state.*` and\n`core.executor.*`, incl. `StateReferenceModuleSpec`,\n`StateReferenceBindingSpec`, `CoreExecutorReflectionSpec` | 71/71 |\n| WorkflowCompiler full `test`, incl. `LogicalPlanSpec` (loop-block\nmembership and enclosing Loop Starts, checked against a port of the\npanel\u0027s walk on every case and 400 random plans) and the loop-variable\ncases of `WorkflowCompilerSpec` (lenient and strict) | 80/80 |\n| WorkflowOperator: Reservoir Sampling, Split, Dictionary Matcher and\nmetadata specs | 260/260 |\n| workflow-compiling-service `test` | 55/55 |\n| amber: `Test/compile`, `DataProcessorSpec`, `DPThreadSpec`, the\nworker\u0027s promise handlers incl. `EndChannelHandlerSpec`,\n`ComputingUnitMasterSpec` | 116/116 |\n| Lint | `scalafixAll --check` and `scalafmtCheckAll` on all five\ntouched sbt projects |\n\n```\nsbt \"project WorkflowCore\" \"testOnly *StateReferenceModuleSpec *StateReferenceBindingSpec *CoreExecutorReflectionSpec\"\nsbt \"project WorkflowCompiler\" test\n```\n\nWhat the tests pin:\n- **End to end in unit form.** The frontend\u0027s\n`{\"limit\":\"$n\",\"operatorType\":\"Limit\"}` is compiled inside `TextInput -\u003e\nLoopStart -\u003e Limit -\u003e LoopEnd` and built through `ExecFactory`. After\nthe state `{n: 2}`, exactly 2 of 5 tuples pass.\n- **Parse handovers.** Typed placeholders get the right pointers whether\nthe object is parsed directly, with the type id first, in the middle or\nlast, or nested in another document.\n- **Compile rules.** Outside every block, Filter `\"$AAPL\"` stays a\nliteral and Limit `\"$n\"` is a compile error. Inside a block, a\nScala-built Filter `\"$i\"` gets its sidecar, while Sort `\"$col\"` is a\ncompile error, and so is an operator with a reference whose read-first\ninput has a link from outside one of its loop blocks (outside the loop,\nan outer loop\u0027s body, a sibling block, or one outside link next to an\ninside one).\n- **Worker.** The executor is built and opened at worker start.\n`produceStateOnStart` and `processState` run on the operator itself, and\nwhat `processState` returns is emitted. Each state message writes the\nvariables into the setting in place, into every property that names\nthem, top-level and nested pointers alike, keeping the object the\nexecutor holds; an outer `{i: 1}` followed by an inner `{i: 5}` leaves\n5. A tuple before any state fails, naming only the missing variables,\nand the setting is not written after the first tuple; an operator with\nno rows fails the same way at its finish. Copies of one loop\u0027s state\nwith different values fail, equal ones pass, and a deeper loop\u0027s value\nreplaces an outer one\u0027s in either arrival order. Values are coerced to\nthe property\u0027s type, and a null, a list or a map for a string property\nis refused.\n- **Executors.** Reservoir Sampling, Split and Dictionary Matcher use\nthe value written after construction and `open()`.\n- **Mappers.** Every Dropwizard application that parses workflows\nregisters the module through `JSONUtils.registerWorkflowModules`;\n`WorkflowCompilingServiceRunSpec` and `ComputingUnitMasterSpec` parse a\ntyped `\"$n\"` through each bootstrap mapper.\n\n`LoopIntegrationSpec` gains three `@IntegrationTest` runs, which CI\u0027s\n`amber-integration` job runs:\n- a number setting: `Limit($n)` with n \u003d 1, 2, 3 gives 1 + 2 + 3 \u003d 6\nrows;\n- nested loops that both name `i`: `Filter(line \u003d $i)` in the inner body\npasses all 2 x 2 rows only with the inner `i`;\n- a text setting on two branches meeting at a Union before `Filter(line\n\u003d $i)`: 2 copies x 3 iterations \u003d 6 rows (a constant or a `$i` that\nnever rebinds gives 2).\n\n**Run by hand.** On a local deployment of this PR together with #8642\nand #8640 (the test branch in #8645), a workflow `Text Input (1..6) -\u003e\nLoop Start (i \u003d 0, output table) -\u003e Limit ($i) -\u003e Loop End (i +\u003d 1 while\ni \u003c len(table))` runs to completion. Each iteration binds `$i` to its\nown `i`, so Loop End collects 0 + 1 + 2 + 3 + 4 + 5 \u003d 15 rows: `1`, then\n`1, 2`, then `1, 2, 3`, and so on. The Limit fed straight from Text\nInput, outside the loop, keeps its constant 3.\n\n| The Limit\u0027s property inside the loop | Loop End\u0027s result after the run\n|\n|---|---|\n| ![Limit inside the loop holding\n$i](https://raw.githubusercontent.com/aglinxinyuan/texera/390db38157491c992db75f25dc703bad05b4ab65/panel-after-inside-loop.png)\n| ![Loop End result: 15 rows, first page 1, 1, 2, 1,\n2](https://raw.githubusercontent.com/aglinxinyuan/texera/ca12ba98464825cb6d16ba1ba90316fac37ca6ca/loop-end-result-15-rows.png)\n|\n\n![The completed run: canvas, Loop End\u0027s update and condition, and its\n15-row\nresult](https://raw.githubusercontent.com/aglinxinyuan/texera/ca12ba98464825cb6d16ba1ba90316fac37ca6ca/loop-run-binds-i-per-iteration.png)\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Fable 5.1, Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "b7993fbafac472d0ef1b87d86169978c42343ac4",
      "tree": "5f8bdff3c5d64656eef3826d04502e6719359a7d",
      "parents": [
        "00cf017d8f5e70a8070e24dbee0176ee0f1b45f6"
      ],
      "author": {
        "name": "Suryaa Charan",
        "email": "122703005+sshiv012@users.noreply.github.com",
        "time": "Sat Oct 03 00:36:16 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 03 00:36:16 2026 +0000"
      },
      "message": "feat: add a delimiter picker with regex validation (#8644)\n\n### What changes were proposed in this PR?\n\nDelimiter properties were plain text boxes. A stored tab looked empty,\ntyping `\\t` stopped at the backslash, and Unnest String accepted invalid\nor degenerate regexes without a word. This replaces them with a\n**delimiter picker**: common delimiters by name, plus a **Custom…**\nentry. Each operator picks a mode through a schema hint\n(`@JsonSchemaInject(json \u003d UIWidget.UIWidgetCharDelimiter /\nUIWidgetRegexDelimiter)`).\n\n```\nCSV scans (char)      Comma  Tab  Semicolon  Pipe  Space          | Custom…       (1 char; typed \\t -\u003e tab)\nUnnest String (regex) Comma  Tab  Semicolon  Pipe (\\|)  Whitespace (\\s+)  New line | Custom regex… (validated)\n```\n\n| Area | Change |\n|---|---|\n| Frontend | New formly type `delimiter`\n(`frontend/src/app/common/formly/delimiter/`). Works in the canvas\nproperty panel and the Form View. Delimiter errors show immediately,\nincluding for invalid values loaded from a saved workflow. |\n| Regex check (browser) | Must compile, must not match the empty string\n(`\\|`, `\\s*`), must not match every character (`.`). The last is\n**exact**: it tests every BMP character other than line breaks, stopping\nat the first miss, so `[a0-]` or `[^,]` pass. Patterns using Java-only\nsyntax (inline flags, possessive quantifiers, `\\p{..}`, `\\x{..}`,\n`\\Q..\\E`, `\\e`, `\\h`, `\\z`, …) are left to the backend, because\nJavaScript can\u0027t parse them or reads them differently. |\n| Regex check (backend) | `UnnestStringOpDesc` makes the same checks\nwith Java\u0027s engine during schema propagation, so a bad pattern is a\n**compile error** instead of a runtime `PatternSyntaxException` or an\nempty result. |\n| CSV scans | `CSVFileScan`, `ParallelCSVFileScan`, `CSVOldFileScan` use\nthe char-mode widget. `maxLength: 1` is kept. |\n\n**Saved workflows:** the stored value is still the delimiter itself, so\nexisting workflows load unchanged and a stored tab shows as \"Tab\".\n\n**One intentional behavior change:** a saved Unnest String delimiter\nthat matches the empty string or every character (e.g. `|`, `.`) now\nfails to compile. Previously it ran and silently split every character\napart, or output only line breaks.\n\n#### Before / after\n\n\u003c!-- drag comparison/C1-csv-stored-tab.png here --\u003e\n\u003c!-- drag comparison/C2-csv-typing-tab.png here --\u003e\n\u003c!-- drag comparison/C3-csv-choices.png here --\u003e\n\u003c!-- drag comparison/C4-csv-legacy-value.png here --\u003e\n\u003c!-- drag comparison/C5-unnest-choices.png here --\u003e\n\u003c!-- drag comparison/C6-unnest-pipe.png here --\u003e\n\u003c!-- drag comparison/C7-unnest-dot.png here --\u003e\n\u003c!-- drag comparison/C8-unnest-invalid.png here --\u003e\n\u003c!-- drag comparison/C9-unnest-compile.png here --\u003e\n\u003cimg width\u003d\"1124\" height\u003d\"425\" alt\u003d\"C1-csv-stored-tab\"\nsrc\u003d\"https://github.com/user-attachments/assets/ab9ba44d-9598-4675-be5f-89f08325a576\"\n/\u003e\n\u003cimg width\u003d\"1124\" height\u003d\"425\" alt\u003d\"C2-csv-typing-tab\"\nsrc\u003d\"https://github.com/user-attachments/assets/29aac797-7da7-4b52-a300-cd64e22c3810\"\n/\u003e\n\u003cimg width\u003d\"1124\" height\u003d\"1030\" alt\u003d\"C3-csv-choices\"\nsrc\u003d\"https://github.com/user-attachments/assets/61fb0b71-3588-476c-9003-64cd2f0b9996\"\n/\u003e\n\u003cimg width\u003d\"1124\" height\u003d\"574\" alt\u003d\"C4-csv-legacy-value\"\nsrc\u003d\"https://github.com/user-attachments/assets/098d5824-22a1-4e9f-b96c-5c42ed750fe5\"\n/\u003e\n\u003cimg width\u003d\"1124\" height\u003d\"1018\" alt\u003d\"C5-unnest-choices\"\nsrc\u003d\"https://github.com/user-attachments/assets/babde8bb-faf3-4e0a-b46b-04da73496cdd\"\n/\u003e\n\u003cimg width\u003d\"1124\" height\u003d\"607\" alt\u003d\"C6-unnest-pipe\"\nsrc\u003d\"https://github.com/user-attachments/assets/1d7bf753-a114-40b4-bdec-62676530a443\"\n/\u003e\n\u003cimg width\u003d\"1124\" height\u003d\"651\" alt\u003d\"C7-unnest-dot\"\nsrc\u003d\"https://github.com/user-attachments/assets/e6157de3-5ff1-4eb1-80df-de1d9dd12da9\"\n/\u003e\n\u003cimg width\u003d\"1124\" height\u003d\"562\" alt\u003d\"C8-unnest-invalid\"\nsrc\u003d\"https://github.com/user-attachments/assets/d370d8af-86a4-4aaf-ae75-f1a722af5335\"\n/\u003e\n\u003cimg width\u003d\"1884\" height\u003d\"750\" alt\u003d\"C9-unnest-compile\"\nsrc\u003d\"https://github.com/user-attachments/assets/7de580fc-927a-4bdf-a5ba-43298c8fd48d\"\n/\u003e\n\n\n\n### Any related issues, documentation, discussions?\n\nCloses #8638\n\n### How was this PR tested?\n\n**Automated.** Tests were written first and seen failing, then made to\npass.\n\n| Suite | Result |\n|---|---|\n| Frontend, full (`ng test`) | 232 files, 6,376 passed |\n| Delimiter / formly specs (included above) | presets for both modes,\ncustom-regex validation (valid, invalid, empty-match, every-character,\nJava-only syntax), edge cases, and a rendered test that feeds the\nbackend\u0027s exact schema through formly-jsonschema |\n| `WorkflowOperator/test`, full | 2,602 passed |\n| New backend specs | each CSV preset read by all three CSV readers;\nUnnest String split with every regex preset and custom patterns;\ncompile-time rejection with Java semantics |\n| Lint / format / types / build | eslint, prettier-eslint, `tsc`, `ng\nbuild`, scalafmt: clean |\n\n**Manual, in the browser.** Local stack (`bin/local-dev.sh up`), Chrome\ndriven by Playwright, 1600×1000:\n1. Open a workflow with CSV File Scan and Unnest String, click each\noperator, and open the Delimiter picker.\n2. Pick each preset; choose Custom… and type `#`, `\\t`, `ab`.\n3. For Unnest String, choose Custom regex… and type `[,;]\\s*`, `(`,\n`[a-`, `a{2,1}`, `|`, `\\s*`, `.`, `\\.`, `,++`, then clear the field.\n4. Type `(?i)(` and `(?s).`: the browser leaves them to the backend, and\nthe Result Panel shows the compile error.\n\nAll 33 scripted checks pass. The before/after screenshots above come\nfrom this run and from the same flow on the base commit.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: suryaacharan \u003csuryaacharan@suryaacharans-MacBook-Pro.local\u003e\nCo-authored-by: Claude Opus 5.5 (1M context) \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "00cf017d8f5e70a8070e24dbee0176ee0f1b45f6",
      "tree": "06d6fb0b7f3471158af093ca8f8f8dae91e3e599",
      "parents": [
        "1fc75b1a2a961148e3b3479860627737d3fc1855"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Fri Oct 02 20:46:59 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 02 20:46:59 2026 +0000"
      },
      "message": "refactor(frontend): remove unused execute-workflow types (#8819)\n\n### What changes were proposed in this PR?\n\nRemoves three exported types from `execute-workflow.interface.ts` that\nnothing imports: `InputPort`, `OutputPort` and `WebOutputMode`. **−9\nlines.** There is no behaviour change: they are compile-time types with\nno reference anywhere in the repo, so they never reach the built\nJavaScript. `WebPaginationUpdate.mode` and `WebDataUpdate.mode` still\nname their mode types directly, as before.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #1214 (2021-07-05), \"Refactor frontend to handle\ndifferent incremental output mode\": `WebOutputMode`. #2299 (2024-01-20),\n\"Refactor backend ports in compiler\": `InputPort`, `OutputPort` |\n| **Usage removed by** | #7783 (2026-08-22). It deleted\n`OperatorAvailableResult`, whose `outputMode` field was the only use of\n`WebOutputMode`, and left the alias behind. `InputPort` / `OutputPort`\nwere **never used** |\n\nThe port types have been unused for the twenty months since they were\nadded.\n\n### Any related issues, documentation, discussions?\n\nCloses #8818\n\n### How was this PR tested?\n\nNo new tests; these are type-only deletions.\n\nFrom `frontend/`:\n\n- `npx ng test --watch\u003dfalse`, with one `--include` for the file\u0027s own\nspec plus each of the 21 specs that import it (22 files): 1412 tests\npass, 1 is skipped (an existing `it.skip` elsewhere).\n- `npx tsc --noEmit -p src/tsconfig.app.json`: clean.\n- `yarn format:ci`: clean.\n- `npx ng build`: success.\n\nTo re-check:\n\n```\ngit grep -n -w -E \"InputPort|OutputPort|WebOutputMode\" -- frontend \u0027:!frontend/src/app/common/type/proto\u0027   # no hits (the generated proto module has its own, unrelated InputPort/OutputPort)\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "1fc75b1a2a961148e3b3479860627737d3fc1855",
      "tree": "3e9774717f3fc3e16fc05d17ccb7e93cc74922bc",
      "parents": [
        "28dbb8885713f3f92d1c1e2114d57f2d1a8e4a75"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Fri Oct 02 20:46:53 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 02 20:46:53 2026 +0000"
      },
      "message": "refactor(frontend): remove the unused dictionaryChangedSubject (#8817)\n\n### What changes were proposed in this PR?\n\nRemoves `dictionaryChangedSubject` from `UserConfigService`: the private\nfield, its three `.next()` calls in `updateEntry` / `updateDict`, and\nthe now-unused rxjs `Subject` import. **+8/−49 lines.** There is no\nbehaviour change. The Subject was private with no getter, so nothing\ncould subscribe to it.\n\n`updateEntry` and `updateDict` keep their guards, deletes and\nassignments; only the emissions go. In the spec, two cases that only\ncounted emissions are deleted. Two others are kept, with their emission\nassertions replaced by behaviour checks, because they cover the\nsurviving guards: a repeated `set()` still issues a PUT and keeps the\nentry, and deleting an absent key leaves the dictionary untouched.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #1162 (2021-06-27), \"Add UserDictionaryService\n(User Presets Step 2)\". The field was private from the start, with no\ngetter or `asObservable()` |\n| **Usage removed by** | **never used**. The only readers were spec\ncases reaching the private field through `(service as any)` |\n\nIt has been unused for over five years.\n\n### Any related issues, documentation, discussions?\n\nCloses #8816\n\n### How was this PR tested?\n\nNo new tests. The two kept cases now pin the guards\u0027 behaviour instead\nof emission counts.\n\nFrom `frontend/`:\n\n- `npx ng test --watch\u003dfalse --include\u003d\u0027**/user-config.service.spec.ts\u0027\n--include\u003d\u0027**/preset.service.spec.ts\u0027`: 2 files, 68 tests, all pass.\n`PresetService` is the only production consumer of `UserConfigService`.\n- `yarn format:ci`: clean.\n- `npx ng build`: success.\n\nTo re-check:\n\n```\ngit grep -n -i \"dictionaryChanged\" -- frontend   # no hits\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "28dbb8885713f3f92d1c1e2114d57f2d1a8e4a75",
      "tree": "35bb85668749167e198faed9b32f5828a1e93c2c",
      "parents": [
        "3ae15e6428442ae77ed8b113392f122d746a87b5"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Fri Oct 02 20:46:44 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 02 20:46:44 2026 +0000"
      },
      "message": "refactor(amber): remove the unused cache.ccf (#8815)\n\n### What changes were proposed in this PR?\n\nDeletes `amber/src/main/resources/cache.ccf`, an Apache Commons JCS\ncache configuration that nothing loads. **−29 lines.** There is no\nbehaviour change. The `commons-jcs3-core` dependency stays, because\n`ComputingUnitMaster` / `ComputingUnitWorker` still import its\n`InvalidArgumentException`.\n\nJCS never names this file in code: it loads `/cache.ccf` from the\nclasspath implicitly, when the cache manager creates its first region.\nSo the check for this PR is whether anything can create a JCS cache, not\nwhether the file name appears anywhere. Nothing can:\n\n- **Source:** the only JCS class referenced in any module is\n`InvalidArgumentException`. Nothing calls `JCS.getInstance`,\n`CacheAccess`, `CompositeCacheManager` or `JCSWorker`.\n- **Bytecode:** after compiling amber and the common modules, the\ncompiled classes reference the same single exception class and no other\nJCS class.\n- **Dependencies:** no other jar on amber\u0027s runtime or test classpath\nreferences JCS.\n\n`InvalidArgumentException` is a plain `RuntimeException` subclass with\nno static initializer, so throwing it never reaches the cache manager.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #1328 (2021-09-08), \"[Operator Caching Step 3] add\noperator cache backend new files and config changes\", for\n`JCSOpResultStorage`\u0027s `JCS.getInstance(\"texera\")` |\n| **Usage removed by** | #1363 (2022-01-25), \"Sink operator result\nstorage abstraction and refactoring\". It deleted `JCSOpResultStorage`,\nthe only code that ever created a JCS cache |\n\nIt has been dead for over four and a half years.\n\n### Any related issues, documentation, discussions?\n\nCloses #8814\n\n### How was this PR tested?\n\nNo new tests; this deletes a resource file that nothing loads.\n\nLocally, from the repo root with Java 17:\n\n- `sbt \"WorkflowExecutionService/Test/compile\"`: success.\n\nTo re-check:\n\n```\ngit grep -n -i \"cache\\.ccf\\|JCS\\.getInstance\\|CompositeCacheManager\"   # no hits\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "3ae15e6428442ae77ed8b113392f122d746a87b5",
      "tree": "0b6fb6d275d2799e941942b0b8c93ea9f9bb2f61",
      "parents": [
        "e5c85111e1b026d0f6d726f99a895e1784f5c9d5"
      ],
      "author": {
        "name": "Suryaa Charan",
        "email": "122703005+sshiv012@users.noreply.github.com",
        "time": "Fri Oct 02 20:45:29 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 02 20:45:29 2026 +0000"
      },
      "message": "fix(amber): surface region launch failures instead of hanging (#8668)\n\n### What changes were proposed in this PR?\n\nA worker failing to initialize in a region\u0027s second (non-dependee)\nphase, e.g. a Python UDF after a HashJoin, used to leave the execution\n`RUNNING` forever with no error. See the issue for the full chain.\n\n- `WorkflowExecutionManager.advanceRegionExecutions`: keep the\n`syncStatusAndTransitionRegionExecutionPhase()` futures instead of\ndropping them in a `foreach`. The advance future now fails if any sync\nfails, so the existing `.onFailure → FatalError` in\n`AdvanceRegionExecutionsHandler` reports it. The rest of the method\nmoved unchanged into `advanceToNextRegions`.\n- `RegionExecutionManager`: a failed launch RPC (`initializeExecutor`,\n`assignPort`, `openExecutor`, `startWorker`) is wrapped as\n`WorkflowRuntimeException` with the target worker ID, so the\n`FatalError` names the failing worker and operator (review feedback).\n- `AsyncRPCClient.logControlReply`: log the `ControlError` message,\ndetails and stack trace. It isn\u0027t a `Throwable`, so the logger silently\ndropped it.\n\n| | Before | After |\n|---|---|---|\n| UDF missing `from pytexera import *` after a join | hangs, all 0\ntuples, no error | fails in ~1s with `name \u0027UDFTableOperator\u0027 is not\ndefined`, attributed to the UDF worker |\n| Log line | `received error from …` | `received error from …\n(controlID: N): \u003cmessage\u003e` |\n\nBehavior note: the future returned by `advanceRegionExecutions` now also\nwaits on, and fails with, the syncs it triggers.\n`AdvanceRegionExecutionsHandler` doesn\u0027t wait on it.\n`StartWorkflowHandler` has no unfinished regions at start, so nothing\nchanges there.\n\n### Any related issues, documentation, discussions?\n\nCloses #8667\n\n### How was this PR tested?\n\nAdded tests. Each new failing-case test fails before the fix and passes\nafter it.\n\n- `WorkflowExecutionManagerSpec`, 2 new tests: a region whose probe op\nhas a dependee port, followed by a UDF op.\n- The UDF\u0027s `initializeExecutor` returns a `ControlError` → the advance\nfails with that message.\n  - The UDF initializes fine → it is started.\n- `DataProcessingSpec`, 1 new e2e test on csv, csv → join → UDF: a Java\nUDF whose code doesn\u0027t compile, so the worker fails in\n`initializeExecutor`, the same step as a Python UDF with an import\nerror.\n- Before the fix it times out after 1 min; after, it fails in ~0.5s,\nnaming the UDF worker.\n  - It uses a Java UDF because CI\u0027s amber job has no Python environment.\n- `RegionExecutionManagerTestSupport`: `CoordinatorRpcProbe` takes an\noptional `initializeExecutorResponse`.\n\n```\nsbt \u0027WorkflowExecutionService/testOnly org.apache.texera.amber.engine.architecture.scheduling.WorkflowExecutionManagerSpec\u0027\nsbt \u0027WorkflowExecutionService/testOnly org.apache.texera.amber.engine.e2e.DataProcessingSpec -- -z \"fail, not hang\"\u0027\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\n---------\n\nCo-authored-by: suryaacharan \u003csuryaacharan@suryaacharans-MacBook-Pro.local\u003e\nCo-authored-by: Claude Opus 5.5 (1M context) \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "e5c85111e1b026d0f6d726f99a895e1784f5c9d5",
      "tree": "6128e02a04ca6010d814b5462709d12b4781d00f",
      "parents": [
        "d1955f3861aaa07486afe9c3732f569f478496bd"
      ],
      "author": {
        "name": "Meng Wang",
        "email": "mengw15@uci.edu",
        "time": "Fri Oct 02 05:48:55 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 02 05:48:55 2026 +0000"
      },
      "message": "fix(frontend): replace the Icons8 comment icon with an original drawing (#8804)\n\n### What changes were proposed in this PR?\n\nPer #8800, `frontend/src/assets/operator_images/icons8-chat_bubble.png`\n(the\nworkflow comment icon) comes from Icons8, whose license requires\nattribution\nwe never gave and does not grant the redistribution rights an Apache-2.0\nrelease promises downstream. Rather than record un-grantable terms, this\nreplaces it with an original drawing of the same visual role (blue\nrounded\nspeech bubble with an ellipsis, drawn with PIL for this PR), renamed\n`comment-bubble.png`. The only reference\n(`joint-ui.service.ts`) is updated; `git grep icons8` is now empty.\n\nThis addresses the Icons8 part of #8800 only; the vendor-logo and\nasset-provenance parts stay open there.\n\n### Any related issues, documentation, discussions?\n\nAddresses the Icons8 item in #8800.\n\n### How was this PR tested?\n\nAsset swap plus one path-constant change; no behavior change. The\nexisting\nfrontend suite covers joint-ui rendering in CI; verified repo-wide that\nno\nother reference to the old file remains.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (claude-fable-5)"
    },
    {
      "commit": "d1955f3861aaa07486afe9c3732f569f478496bd",
      "tree": "2900254dabed2d595711dc8285eb19b667dc8df9",
      "parents": [
        "566efb81eb33cdcaab1a759ee26951c5514f1b77"
      ],
      "author": {
        "name": "Meng Wang",
        "email": "mengw15@uci.edu",
        "time": "Fri Oct 02 05:27:15 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 02 05:27:15 2026 +0000"
      },
      "message": "fix(licensing): list the bundled Yarn release in LICENSE (#8805)\n\n### What changes were proposed in this PR?\n\nPer #8801, the source release bundles\n`frontend/.yarn/releases/yarn-4.14.1.cjs`\n(Yarn Berry, BSD-2-Clause) without a LICENSE entry. Taking the issue\u0027s\nfirst\nsuggested fix:\n\n- root `LICENSE`: new BSD 2-Clause section listing the bundled Yarn\nrelease\n  with its copyright line;\n- `licenses-3rd-party-code/yarn.txt`: Yarn\u0027s LICENSE.md, verbatim from\nthe\n  `@yarnpkg/cli/4.14.1` tag.\n\nThe issue\u0027s second suggestion (dropping the file from the source release\nvia\n`export-ignore` + corepack) touches the build chain and is left as a\npossible\nfollow-up for the next release line.\n\nThe filename is identical on main, release/v1.2 and release/v1.3, so the\nentry backports without adaptation.\n\n### Any related issues, documentation, discussions?\n\nCloses #8801.\n\n### How was this PR tested?\n\nLicense-text-only change; `.licenserc.yaml` already exempts\n`frontend/.yarn/**` from the header check, so no CI config changes.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (claude-fable-5)"
    },
    {
      "commit": "566efb81eb33cdcaab1a759ee26951c5514f1b77",
      "tree": "d4d06da14227c813c64f2c80db8d65b6d00c1a94",
      "parents": [
        "98d3d4b1ec8b02f611801d035c190fa31f56fa47"
      ],
      "author": {
        "name": "Eugene Gu",
        "email": "eugenegujing@outlook.com",
        "time": "Fri Oct 02 00:23:25 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 02 00:23:25 2026 +0000"
      },
      "message": "feat(workflow-operator): report scan rows that fail schema parsing (#6947)\n\n### What changes were proposed in this PR?\n\nCSV/JSONL scan sources infer each column\u0027s type from only the first\n`INFER_READ_LIMIT` (\u003d100) rows. When a later row held a value that did\nnot parse as the inferred type, the execs caught the error, mapped the\nrow to `null`/`None`, and filtered it out — silently dropping the entire\nrow with no error, warning, count, or log. Every downstream count,\naggregate, and join then ran on a silently truncated dataset. The bug is\nthe silence, not the rejection.\n\nFollowing the consensus in discussion #6324 (skip + surface, rather than\nthe fail-fast approach originally proposed in #6323), a scan now still\nskips the unparsable row — the run completes and existing workflows keep\nworking — but each skipped row is surfaced to the user as a console\nwarning naming the row number, offending value, column, and expected\ntype, for example:\n\n\u003e WARNING: skipped row 150 — value \u002755.5\u0027 in column \u0027age\u0027 cannot be read\nas INTEGER. Column types were inferred from an initial sample of 100\nrows, and this value does not match.\n\n\u003cimg width\u003d\"1137\" height\u003d\"788\" alt\u003d\"Screenshot 2026-08-05 at 2 10 49 PM\"\nsrc\u003d\"https://github.com/user-attachments/assets/171f741e-b11b-4567-8c62-d6939b9faa58\"\n/\u003e\n\nChanges:\n\n- Add `ScanRowParseError`, which builds the per-row warning by\nre-parsing the failing row\u0027s fields to identify the offending column,\nwith a generic fallback message when no single column can be identified\n(e.g. a malformed JSON line). The message names the inference sample\nsize actually used — `INFER_READ_LIMIT` capped by the user-set row limit\n(`ScanSourceOpDesc.inferSampleSize`) — rather than a hard-coded 100.\n- Add `SkippedRowReporter`, shared by all scan variants: it reports the\nfirst 100 skipped rows individually and then appends a single summary\nline carrying the true total, so a heavily malformed file cannot flood\nthe console or exhaust memory.\n- Record-and-skip in `CSVScanSourceOpExec`, `JSONLScanSourceOpExec`,\n`ParallelCSVScanSourceOpExec`, and `CSVOldScanSourceOpExec`. The\nlegitimate null paths (an empty cell parsed to null, a blank/all-null\nline, an exhausted block) are untouched and are not reported. Row\nnumbers: CSV reuses its existing counter, JSONL and csvOld gain absolute\nline/data-row numbers (a configured `offset` is added back in, so the\nreported number always matches the file), and ParallelCSV reports none\nbecause it is byte-partitioned across workers.\n- Add `OperatorExecutor.getWarnings` (defaults to empty), a generic\nnon-fatal warning channel that any executor can opt into.\n- Emit the warnings at `FinalizeExecutor` in `DataProcessor` as PRINT\nconsole messages via the new `ErrorUtils.mkPrintConsoleMessage`. The\ntitles keep the `WARNING: ` prefix the UI keys on, and, unlike the\nexecutor exception path, this does not pause the run.\n\nInference logic is unchanged (the 100-row sampling is untouched). Scala\nonly — no UI change.\n\nBehavior-change note for reviewers: workflows that previously ran to\ncompletion while silently discarding malformed rows now still complete,\nbut they surface a console warning for each skipped row (capped at 100\ndetailed entries plus a summary). One case worth calling out: a csvOld\nscan over a file with an empty cell in a numeric column previously\ndropped that row silently and will now report it — this is exactly the\nsilent loss this PR exists to surface, not a regression.\n\nKnown limitations: warnings are collected in the executor and emitted\nonly when it finalizes — a run that fails or is killed mid-scan does not\nsurface them, and nothing is shown while the scan is still running.\nStreaming emission as rows are skipped is possible follow-up work; the\nfinalize-only design follows the consensus in #6324.\n\n### Any related issues, documentation, discussions?\n\nCloses #6279. Design discussion: #6324. This supersedes the fail-fast\napproach in #6323, which will be closed in favor of this PR.\n\n### How was this PR tested?\n\nScan-operator unit tests (skip-and-report naming row/value/column/type,\nthe 100-detail cap with its summary line, empty-cell and blank-line\nnon-reporting, the malformed-JSON fallback, absolute line numbers when\nan `offset` is set, and the warning naming the actual inference sample\nsize when a row `limit` caps it):\n\n```\nsbt \"WorkflowOperator/testOnly \\\n  org.apache.texera.amber.operator.source.scan.csv.CSVScanSourceOpExecSpec \\\n  org.apache.texera.amber.operator.source.scan.json.JSONLScanSourceOpExecSpec \\\n  org.apache.texera.amber.operator.source.scan.csv.ParallelCSVScanSourceOpExecSpec \\\n  org.apache.texera.amber.operator.source.scan.csvOld.CSVOldScanSourceOpExecSpec\"\n```\n\nEngine-side emission path (`DataProcessorSpec`): a new test asserts the\nwarnings reach the coordinator as PRINT console messages at finalize and\nthat the run is not paused.\n\nFull local gate (lint + format + backend unit tests):\n\n```\nsbt \"scalafixAll --check\"   # pass\nsbt scalafmtCheckAll        # pass\nAMBER_TEST_FILTER\u003dskip-integration sbt WorkflowExecutionService/test   # pass\nsbt WorkflowOperator/test WorkflowCore/test WorkflowCompilingService/test   # pass\n```\n\nManual, in the Texera UI, over CSV and JSONL datasets derived from a\nreal 403-row file whose `age` column is inferred as INTEGER: verified a\nsingle bad row (skipped, one warning naming row/value/column/type), many\nbad rows (100 detailed warnings plus a summary line), the clean file\n(all rows, no warning), an empty cell (kept as a null row, no warning),\nand a malformed JSONL line (skipped, generic fallback warning). In every\ncase the scan completed instead of failing.\n\nRebased onto main after #7247 (the JSONL worker-slice offset fix) landed\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nCo-authored by: Claude Code (Fable 5)\n\n---------\n\nSigned-off-by: Eugene Gu \u003ceugenegujing@outlook.com\u003e\nCo-authored-by: Copilot Autofix powered by AI \u003c175728472+Copilot@users.noreply.github.com\u003e"
    },
    {
      "commit": "98d3d4b1ec8b02f611801d035c190fa31f56fa47",
      "tree": "5bb935a207aefe36e853af2f141c22fe5d6f236d",
      "parents": [
        "acc6dd1139d936d849e2aaa6abb288f8ef3e98ad"
      ],
      "author": {
        "name": "Kary Zheng",
        "email": "150742834+kz930@users.noreply.github.com",
        "time": "Wed Sep 30 06:11:49 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Sep 30 06:11:49 2026 +0000"
      },
      "message": "feat(source): bound a file scan\u0027s window at zero (#8514)\n\n### What changes were proposed in this PR?\n\nEvery file-scan source takes a Limit and an Offset from\n`ScanSourceOpDesc`, and neither field said it cannot be negative. Both\nnow declare `minimum: 0`.\n\nNeither value means anything below zero, and a negative one is not read\nthe same way twice. The executors take the window with Scala\u0027s `drop`\nand `take`, where a negative drop keeps every row and a negative take\nkeeps none. The scripts the export writes take the same window with\n`iloc`, which counts from the end instead. So `offset \u003d -1` is every row\non one side and the last row on the other, and `limit \u003d -1` is no rows\non one side and all but the last on the other.\n\nDeclaring the bound states what the operators already assume, and the\nproperty editor then refuses the value rather than passing it on. It\nreaches CSV, CSVOld, JSONL, Arrow and the file scans at once, all of\nwhich inherit the two fields.\n\nThe schema is not revalidated on the way in, though, so a plan posted to\nthe API or an imported workflow file still arrives with whatever the\nfield holds. Every reader now takes the window through two accessors on\nthe base class, `windowOffset` and `windowLimit`, which clamp at zero.\nThe fields themselves are left as they came, and the native readers\nbehave exactly as they did: `drop(-1)` and `drop(0)` both keep every\nrow, and `take(-1)` and `take(0)` both keep none. What the clamp settles\nis that a reader counting a negative from the end cannot answer\ndifferently from the one that does not.\n\n\nhttps://github.com/user-attachments/assets/4692ec26-1c93-4ca3-b3e8-d527cd0d0922\n\n### Any related issues, documentation, discussions?\n\nCloses #8513, the task this change is the whole of.\n\n### How was this PR tested?\n\nA case in `ScanSourceOpDescSpec` validates `-1`, `0` and `5` against the\ngenerated schema for both fields, through the same validator the\nproperty editor uses rather than restating the bound the schema\ndeclares. Two more deserialize a window through the same polymorphic\nmapper a saved workflow goes through, and check that a negative reaches\nthe fields intact while the accessors report the empty or the whole\nwindow, and that a non-negative one and an absent one pass through\nuntouched.\n\nThe executor is covered where the value can actually arrive:\n`CSVScanSourceOpExecSpec` builds the exec from the descriptor\u0027s JSON, as\na submitted plan does, and runs it over a real file with each negative\nin turn. A negative limit emits no rows and a negative offset emits all\nof them. The 166 tests across the scan-source specs pass.\n\nThe four numbers quoted above were read off the two runtimes rather than\nfrom memory: `Iterator(1,2,3,4,5).drop(-1)` keeps all five and\n`.take(-1)` keeps none, while pandas\u0027 `iloc[-1:]` is the last row and\n`iloc[:-1]` is the first four.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\n---------\n\nCo-authored-by: Claude Opus 5 (1M context) \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "acc6dd1139d936d849e2aaa6abb288f8ef3e98ad",
      "tree": "d4f49843c125061da740fad7f3b0bbc8e216a372",
      "parents": [
        "ce1b1023d9c5343c64591e41e6776cd8b07e26e2"
      ],
      "author": {
        "name": "Martin Vu",
        "email": "127065329+VuMartin@users.noreply.github.com",
        "time": "Mon Sep 28 22:08:03 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 28 22:08:03 2026 +0000"
      },
      "message": "refactor(test): extract shared DB provisioning helper (#8457)\n\n### What changes were proposed in this PR?\n\nExtract the shared test database provisioning logic from\n`TestUtils.initiateTexeraDBForTestCases` and\n`MockTexeraDB.initializeDBAndReplaceDSLContext` into a reusable\n`MockTexeraDB.createTestDatabase` helper.\n\nThe helper centralizes the creation of an isolated test database and\nexecution of the cached DDL script, while preserving the existing\ndatabase naming and connection/resource lifecycle behavior.\n\n### Any related issues, documentation, discussions?\n\nCloses #6421\n\n### How was this PR tested?\n\n- Ran `DAO / test` successfully.\n- Ran `PauseSpec` successfully.\n- Ran `ReconfigurationSpec` successfully.\n- Ran `DataProcessingSpec` successfully.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: ChatGPT (5.5 mini)\n\n---------\n\nSigned-off-by: Martin Vu \u003c127065329+VuMartin@users.noreply.github.com\u003e"
    },
    {
      "commit": "ce1b1023d9c5343c64591e41e6776cd8b07e26e2",
      "tree": "55d536bb48221acb6a2824bc2d3a7e10c07516f4",
      "parents": [
        "506397a5c2d8f392a1f8ceb85dc5f7a5416169b8"
      ],
      "author": {
        "name": "yangzhang75",
        "email": "yangz75@uci.edu",
        "time": "Mon Sep 28 21:42:44 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 28 21:42:44 2026 +0000"
      },
      "message": "fix(workflow): keep workflowSettings and formBinding in the shared model (#8351)\n\n### What changes were proposed in this PR?\n\n`workflowSettings` and the Form View definition (`formBinding`) were\nheld as per-client private fields on `WorkflowActionService`, outside\nthe Yjs shared document. Because autosave persists the whole workflow\ncontent, a co-editor whose private copy was stale would overwrite\nanother editor\u0027s change on their next canvas edit -- a lost update\n(#8315).\n\nThis moves both into the shared model:\n\n* A shared `contentMetaMap` (`Y.Map`, keyed `\"settings\"` /\n`\"formBinding\"`) is added to `SharedModel`, alongside the graph maps, so\nit syncs live and every autosave writes the current value rather than a\nstale copy. It is deliberately kept out of the undo manager, matching\nthe previous (non-undoable) behavior of these values.\n* `getWorkflowSettings` / `setWorkflowSettings` / `getFormBinding` /\n`setFormBinding` / `hydrateFormBinding` / `getWorkflowContent` now read\nand write the shared map.\n* An observer republishes a change -- from a local edit or a co-editor\n-- on `formBindingChanged$` for the definition, merged into\n`workflowChanged()` so the Form View re-renders and the existing\nautosave picks it up, and on the new `workflowSettingsChanged$` for the\nsettings, which the settings panel refreshes from alongside\n`workflowChanged()`. The settings stream is not merged into\n`workflowChanged()`: the panel persists a settings change itself, and\nthe autosave would save it a second time, cutting a second version; a\nlater autosave carries the current settings anyway, since the content\nreads them from the shared map.\n* Opening a workflow seeds the database\u0027s copy into the document, and\nthat seed is careful: it waits for the provider\u0027s first sync\n(immediately when the document is offline or already synced) and writes\nonly when the document says nothing about the key yet, leaving whatever\narrived from the room alone -- a co-editor\u0027s value, or the mark that the\nkey was cleared. Absence is explicit: a workflow opened or reloaded\nwithout a value marks the key cleared (`null`) rather than deleting it,\nso a room that cleared a key is told from one no client has seeded yet,\nand a joining client whose database copy has not caught up with the\nclearing cannot put the value back; opening a workflow that carries no\ndefinition does not take a co-editor\u0027s away either. Writing before the\nsync would have been a concurrent whole-value write that Yjs settles by\nclient id rather than by recency, which is the lost update this PR\nexists to prevent. While the seed waits, the database copy is held and\nread from, so the page shows it and an autosave in that window carries\nit instead of an empty one, presence included (a definition that is\npresent but empty stays in the content). The wait is not bounded: a copy\nwritten before the sync would be the concurrent write above, on a slow\nroom as much as on an unreachable one, and never writing it loses\nnothing, since nobody else was in that document either. A local edit of\nthe key while the seed waits cancels the seed and is held the same way:\nbefore the first sync a write into the document would be one more\nconcurrent whole-value write, settled by client id, so the edit is read\nfrom and announced at once and written after the sync, where it follows\nthe room\u0027s state and replaces it, as an edit should. The seed is not\nannounced as an edit, so opening a workflow does not save; clearing the\npage writes nothing into the destroyed document, and a blank workflow\nstarts on a fresh document, whose seed state (waiting copies, seeded\nkeys) starts empty. The room\u0027s precedence is for the first seed of a key\non a document, the one the workflow is opened with; a later reload into\nthe same document (a version shown or returned from, an agent\u0027s rewrite)\nreplaces the value, the room\u0027s included, or marks it cleared for a\nversion that carries none. A seed that waits listens for the sync and\nstops listening when it lands, is superseded or is cancelled.\n\nWhole-value last-writer-wins is accepted for now; field-level Y-types\nare a possible future refinement.\n\n### Any related issues, documentation, discussions?\n\nCloses #8315.\n\n### How was this PR tested?\n\nUnit tests (vitest): `workflow-action.service.spec`, driving the real\n`SharedModel`. Beyond the move itself (a co-editor\u0027s write to the shared\nmap reaches `formBindingChanged$` and `workflowChanged()`; the same for\nsettings; an unchanged value is not rewritten; opening a workflow stays\nsilent, driven through the real reload path), the seed is covered by a\nco-editor\u0027s value surviving both a seed and an open that carries none,\nby reads falling back to the database copy while the seed waits, by the\ncopy staying out of the document until the first sync however long that\ntakes, reads and saves carrying it meanwhile, by a definition written\nwhile the seed of a workflow opened without one waited surviving the\nsync, by a present but empty definition staying in the content while the\nseed waits, by clearing the page announcing nothing and writing nothing,\nby a later reload replacing and then clearing a value the room owned, by\na cleared mark from the room keeping a stale database copy out, by an\nedit made before the first sync being held, shown, announced exactly\nonce, and written after the sync over what the room held, by a settings\nchange reaching `workflowSettingsChanged$` and not `workflowChanged()`,\nand by the settings panel re-syncing from that stream without\npersisting, by one sync listener per waiting key that goes with the\nseed, by the deferred seed staying silent, by the seed going in at once\ninto a document that is not connecting or has already synced, by a later\nopen superseding a seed still waiting for the sync, and by a map change\nmade under the reloading flag staying silent. Each new guard was\ndeletion-checked (removing it turns the corresponding test red). The\nfull frontend suite, eslint, prettier and the production (AOT) build\npass; every line this PR adds is covered.\n\nTo verify by hand, with two browser windows on one workflow: in A, open\nthe Form View, enter edit mode and expose a field (or change a setting\nin the canvas\u0027s Settings panel), and wait for the save; in B, drag an\noperator on the canvas and wait for the autosave (about 5 s); reload A.\nBefore this change the exposed field (the setting) is gone, B\u0027s autosave\nhaving stored its stale copy; after it, the field is still there, and\nB\u0027s Form View or Settings panel showed the change live. A side-by-side\nbefore/after video is to be added here.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nYes. Generated-by: Claude Code (Claude Opus 5, Anthropic). Co-authored\nwith Claude, reviewed line by line by the author before submission.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nhttps://claude.ai/code/session_01FVvP3ttj22f9LB4p9u2anY\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "506397a5c2d8f392a1f8ceb85dc5f7a5416169b8",
      "tree": "7fd3467581c8261d58924a84a81124d17202ad87",
      "parents": [
        "6d0931cb9b193d87f477cca039c9c805126f452d"
      ],
      "author": {
        "name": "Kary Zheng",
        "email": "150742834+kz930@users.noreply.github.com",
        "time": "Mon Sep 28 21:35:20 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 28 21:35:20 2026 +0000"
      },
      "message": "feat(machine-learning): export the Machine Learning Scorer (#8367)\n\n### What changes were proposed in this PR?\n\nThe scorer reads one label through two columns, the actual and the\npredicted,\nand reports the metrics a task admits. The export says which task it is\nscoring the same way the operator does, so the two paths select the same\nmetrics from the same pair.\n\nTwo behaviour fixes travel with it. It reports the settings it cannot\nscore\nrather than failing deep inside the generated Python, and it scores the\nrows\nan empty cell leaves usable rather than ending the run on one.\n\n### Any related issues, documentation, discussions?\n\nPart of #8325, 19 of 27; that issue lists the set in order. It needs\n#8327 for the trait, so it does not compile until that lands, and the\nrows these operators add to the verification runner follow with the\nharness rather than as whole new files here.\n\nCloses #8302, closes #8058.\n\nCloses #8421, the task this change is the whole of.\n\n### How was this PR tested?\n\nEach operator asserts the block it emits in its own spec. Once the\nharness lands, each is also run through the engine and through its\ngenerated script, on every configuration its schema offers, and the two\nanswers compared.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Opus 5)\n\n---------\n\nCo-authored-by: Claude Opus 5 (1M context) \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "6d0931cb9b193d87f477cca039c9c805126f452d",
      "tree": "d9fa441319c891af905dc653bc386ced312ed15f",
      "parents": [
        "5127b78bc5dfd48a904894792c299ec72ba07ab9"
      ],
      "author": {
        "name": "Suryaa Charan",
        "email": "122703005+sshiv012@users.noreply.github.com",
        "time": "Mon Sep 28 21:32:34 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 28 21:32:34 2026 +0000"
      },
      "message": "feat(frontend): filter console messages by type (#8515)\n\n### What changes were proposed in this PR?\n\nThe console badges every message with its type but offers no way to act\non it. A Python UDF that prints per tuple buries a single ERROR under\nits output, and the panel auto-scrolls, pushing it out of view.\n\nAdds a filter menu beside the settings gear: a checkbox per message type\nplus a select-all, and a line above the list reporting how many messages\nare hidden. The gear keeps the display options it already had.\n\nEach filter option carries the same badge colour as the rows it\ncontrols. Every type is visible by default, and a type the console has\nnot seen before stays visible rather than being hidden by an\nunknown-type default.\n\nBoth toolbar controls become buttons so the menus can be reached by\nkeyboard — the settings gear could not be, as a bare `\u003ca\u003e` with no\n`href`. Verified by focusing the trigger and pressing Enter.\n\n### Any related issues, documentation, discussions?\n\nCloses #8495\n\n### How was this PR tested?\n\n42 unit tests in `console-frame.component.spec.ts`, up from 33 before\nthis change.\n\nVerified live against a `1-out Python UDF` emitting 23 PRINT messages,\none ERROR, plus COMMAND and DEBUGGER from the debug console — unticking\nPrint leaves the error alone at the top.\n\nThe DOM tests were checked by mutation: swapping two checkbox bindings,\nand replacing the hidden-count interpolation with a literal, each fail a\ntest.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nhttps://claude.ai/code/session_016m8VBHFdnbBvNovMonAK9t\n\n---------\n\nCo-authored-by: Claude Opus 5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "5127b78bc5dfd48a904894792c299ec72ba07ab9",
      "tree": "421c0c25b7b1c94502afdb7fbd17be3ddb9ef9de",
      "parents": [
        "004a524c27f7b30a2ed02154e203b6b9cda4fe7c"
      ],
      "author": {
        "name": "Kary Zheng",
        "email": "150742834+kz930@users.noreply.github.com",
        "time": "Mon Sep 28 21:28:12 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 28 21:28:12 2026 +0000"
      },
      "message": "feat(machine-learning): export the four advanced trainers (#8348)\n\n### What changes were proposed in this PR?\n\nThe four advanced trainers implement `StandaloneCodeGenerator`. Each\nreads its hyperparameters from a table the user fills in rather than\nfrom fields of its own, so the script has to resolve, for every row,\nwhich parameter was chosen and what converter its value passes through\nbefore it reaches the estimator.\n\n`JsonSchemaCustomizer` and its caller in `OperatorMetadataGenerator`\ncome along because these four implement it. The rules a hyperparameter\u0027s\nvalue follows — the set it may take, the bound it must respect — are\nwritten into the schema at generation time, and without the call the\nschema carries none of them.\n\nThe KNN, SVC and SVR parameter tables gain the accepted values and the\nbounds each parameter actually admits, read from scikit-learn\u0027s own\nconstraints rather than from recall.\n\n\n### Any related issues, documentation, discussions?\n\nPart of #8325, 18 of 27; that issue lists the set in order. It needs\n#8327 for the trait, so it does not compile until that lands, and the\nrows these operators add to the verification runner follow with the\nharness rather than as whole new files here.\n\nCloses #8010, the label column offered as one of its own inputs. Part of\n#7979, #7952 and #7936, whose remaining halves are in #8350.\n\nCloses #8420, the task this change is the whole of.\n\n### How was this PR tested?\n\nEach operator asserts the block it emits in its own spec. Once the\nverification lands it is also run through the engine and through its\ngenerated script, on every configuration its schema offers, and the two\nanswers compared; this branch is cut from main and does not carry that\nmachinery, so those runs are not on this diff\u0027s CI.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Opus 5)\n\n---------\n\nCo-authored-by: Claude Opus 5 (1M context) \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "004a524c27f7b30a2ed02154e203b6b9cda4fe7c",
      "tree": "11fa70ecc66c718831220792b2d7946d45e33cde",
      "parents": [
        "f30af7e7714fae1f7d55b2c1d4b14c13592329f5"
      ],
      "author": {
        "name": "Kary Zheng",
        "email": "150742834+kz930@users.noreply.github.com",
        "time": "Mon Sep 28 21:26:06 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 28 21:26:06 2026 +0000"
      },
      "message": "feat(visualization): export the hierarchy and graph charts as Python (#8344)\n\n### What changes were proposed in this PR?\n\nSeven visualizations implement `StandaloneCodeGenerator`: the ones that\ndraw a structure rather than a coordinate system — tree plot, network\ngraph, sankey, hierarchy chart, icicle chart, dendrogram — and the word\ncloud.\n\nA visualization emits a figure rather than a frame, so it is compared as\none: number by number after both paths have drawn, which catches a\ndifference in the data behind the picture without failing over a layout\ndetail that carries no meaning. The word cloud renders an image instead,\nso it is compared as the HTML that carries it.\n\nNetwork Graph and Word Cloud are verified here rather than withheld.\nBoth had been flagged for drawing a different picture on every run,\nwhich stopped being true once their placement was seeded, and lifting\nthose two rows showed three things the reason had been hiding.\n\nNetwork Graph never called `manipulateTable`, the method it already had\nfor dropping the rows that name no edge, so a null reached `add_node`,\nwhich refuses one outright. Word Cloud counted its words out of whatever\ncolumn it was given, and the filter that finds them uses pandas\u0027 `.str`,\nwhich refuses anything but text, so the operator now states that. And\nthe Tree Plot lays itself out without igraph, which is GPL v2 and\nCategory X under the ASF third-party licence policy.\n\nStating it is not enough on its own. An attribute type rule only warns:\nthe property editor prints the warning and lets the workflow run, so a\nuser still reaches the word cloud with a column of numbers, and `.str`\nends the run on a pandas error naming an accessor nobody wrote. Both\ngenerators now answer that the way they already answer an empty table\nand a column holding no words, with the operator\u0027s own error page. This\nchanges what the engine does with such a workflow: it used to fail, and\nnow it draws the reason. Both sides ask the same question in the same\nwords, so the two paths still agree on what they produce.\n\n\n### Any related issues, documentation, discussions?\n\nPart of #8325, 13 of 27; that issue lists the set in order. It needs\n#8327 for the trait, so it does not compile until that lands, and the\nrows these operators add to the verification runner follow with the\nharness rather than as whole new files here.\n\nCloses #7969, the Tree Plot\u0027s Category X dependency.\n\nCloses #8416, the task this change is the whole of.\n\n### How was this PR tested?\n\nEach operator asserts the block it emits in its own spec. Once the\nverification lands it is also run through the engine and through its\ngenerated script, on every configuration its schema offers, and the two\nanswers compared; this branch is cut from main and does not carry that\nmachinery, so those runs are not on this diff\u0027s CI. The word cloud\u0027s\nguard is compared on a table its column knob points at a numeric column,\nso the two paths are held to the same answer for input the type rule\nonly warned about; that row arrives with the verification harness, like\nthe others.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Opus 5)\n\n---------\n\nCo-authored-by: Claude Opus 5 (1M context) \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "f30af7e7714fae1f7d55b2c1d4b14c13592329f5",
      "tree": "90d8118c31196ac195988e1dd5b8851c782184dc",
      "parents": [
        "3afdeb0b492b832eeab1b0787820b80d117bfdf4"
      ],
      "author": {
        "name": "Meng Wang",
        "email": "mengw15@uci.edu",
        "time": "Mon Sep 28 21:12:36 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 28 21:12:36 2026 +0000"
      },
      "message": "feat: turn on per-user warehouses (#8713)\n\n### What changes were proposed in this PR?\n\nFlips `storage.warehouse.enabled` to `true`, enabling the per-user\nwarehouse feature that has been built behind it. All of #6870\u0027s Phase 0\nwork is merged; the switch is the last step. The comment above it is\nupdated too — it described a feature still being built.\n\nThe switch only takes effect where the Iceberg catalog is `rest`\n(Lakekeeper) — `StorageConfig` keeps the feature off for any other\ncatalog type, so deployments that do not run Lakekeeper are unaffected.\n\n### Any related issues, documentation, discussions?\n\nCloses #8712. Part of #6870. Proposed and demonstrated in discussion\n#8633, with no objections raised.\n\n### How was this PR tested?\n\n- Ran the engine\u0027s integration suite locally against a live Lakekeeper\nand MinIO, with the switch on and off. The same eight cases fail either\nway (Python UDF specs timing out in my environment), so the switch makes\nno difference to the suite. The `amber` unit job pins\n`STORAGE_ICEBERG_CATALOG_TYPE: postgres`, which keeps the feature off\nthere regardless of this flag.\n- Exercised the feature by hand on a local deployment with the switch\non: creating a warehouse from the dashboard tab and from the canvas\npicker, running a workflow into it, and confirming that a run with no\nwarehouse selected is refused rather than routed to shared storage.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (claude-opus-5, claude-fable-5)"
    },
    {
      "commit": "3afdeb0b492b832eeab1b0787820b80d117bfdf4",
      "tree": "81fd31cc4d835d12199be245cfb8c6cf9b0e3e94",
      "parents": [
        "c6495c5429d40170698088fee5e49ca17c4e4f64"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Mon Sep 28 21:05:51 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 28 21:05:51 2026 +0000"
      },
      "message": "refactor(deploy): remove the standalone python-language-server manifest (#8715)\n\n### What changes were proposed in this PR?\n\nDeletes `bin/pylsp/python-language-server.yaml`, a standalone Kubernetes\nDeployment + Service for the Python language server that nothing\napplies. It pulled a personal image (`jxzliu/pylsp:latest`) with a\n`regcred` pull secret into a hard-coded `texera` namespace. **−61\nlines.** There is no behaviour change: the Helm chart\u0027s own pylsp\ntemplate (`bin/k8s/templates/base/pylsp/pylsp.yaml`, image\n`texera/pylsp`) is what actually deploys the server.\n`bin/pylsp/Dockerfile` and `run_pylsp.sh`, which build that image, stay.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #3441 (2025-05-19), \"Add `share-editing-server`\nand `pylsp` dockerfiles to the deployment folder\". It was moved\nunchanged by #3883 and #3892 |\n| **Usage removed by** | **never used**. No script, CI job, doc or\nDockerfile applies or copies it. The Helm pylsp template from #3337\n(2025-04-05) predates it and has been the real deployment all along |\n\nIt has duplicated the Helm template since the day it was added, about\nsixteen months ago. Its Service name (`python-language-server-service`)\ndoesn\u0027t even match the one the gateway routes to\n(`python-language-server-svc`).\n\n### Any related issues, documentation, discussions?\n\nCloses #8714\n\n### How was this PR tested?\n\nNo new tests; this deletes a deployment file that nothing reads.\n\n- `bash bin/k8s/tests/test_helm_values.sh`: PASS (156 template value\nreferences checked across 53 files).\n- `git grep -n \"python-language-server\"`: the remaining hits are the\nHelm pylsp values, the gateway route, and the language-server path and\nport settings (`gui.conf`, the code editor, `pyright-language-service`).\nNone of them reference the deleted file.\n- `bin/build-images.sh` builds `pylsp/Dockerfile` with context\n`./pylsp`, and the Dockerfile copies only `run_pylsp.sh`, so the image\nnever contained the manifest.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "c6495c5429d40170698088fee5e49ca17c4e4f64",
      "tree": "25aa3074e8de41d25f1045900f8f707b8629e370",
      "parents": [
        "d1f7e8456daea543fa5e2c85dfc5727444e37e4f"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Mon Sep 28 21:05:45 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 28 21:05:45 2026 +0000"
      },
      "message": "refactor(frontend): remove dead WorkflowUtilService members (#8717)\n\n### What changes were proposed in this PR?\n\nDeletes four unused members of `WorkflowUtilService`, plus the rxjs\nimport and the three spec cases that existed only for them. **+1/−85\nlines.** There is no behaviour change. The constructor still fills\n`operatorSchemaList` from the metadata subscription; only the\n`.next(true)` to a Subject with no subscriber goes.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #712 (2019-06-06):\n`operatorSchemaListCreatedSubject` + getter. #754 (2020-12-11), \"Added\noperator grouping feature\": `getGroupRandomUUID`. #1309 (2021-08-28),\n\"Re-enabling breakpoints\": `getBreakpointRandomUUID`. #4020\n(2025-11-25), \"feat: introduce the LLM-based workflow copilot\":\n`getOperatorTypeList` |\n| **Usage removed by** | #1674 (2022-10-05), the Yjs shared-editing\nfrontend, removed the last live path to `getGroupRandomUUID` (#3033\nlater deleted its last textual call, inside a dead `getNewGroup`). #4495\n(2026-04-27) removed the copilot tool that called `getOperatorTypeList`.\nThe stream and `getBreakpointRandomUUID` were **never used** |\n\nThe oldest of these has been dead for seven years, and the newest for\nfive months.\n\n### Any related issues, documentation, discussions?\n\nCloses #8716\n\n### How was this PR tested?\n\nNo new tests. The 15 remaining service cases cover what is left.\n\nFrom `frontend/`:\n\n- `npx ng test --watch\u003dfalse`, with one `--include` per spec that\nimports `workflow-util.service` (20 files): 724 tests, all pass.\n- `yarn format:ci`: clean.\n- `npx ng build`: success.\n\nTo re-check:\n\n```\ngit grep -n -E \"getOperatorTypeList|getGroupRandomUUID|getBreakpointRandomUUID|OperatorSchemaListCreated\" -- frontend   # no hits\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "d1f7e8456daea543fa5e2c85dfc5727444e37e4f",
      "tree": "2b85ad3df8815f5048b04ccb9b26338d5ff57741",
      "parents": [
        "bcd0ec4f742264503114aa4388d82df8d35e9647"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Mon Sep 28 21:05:41 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 28 21:05:41 2026 +0000"
      },
      "message": "refactor(frontend): remove the unused AdminExecutionComponent filters (#8719)\n\n### What changes were proposed in this PR?\n\nDeletes `dataCheck` and `filterByStatus` from `AdminExecutionComponent`,\ntogether with the `NzTableFilterFn` import and the four spec cases that\nexercised them. **−58 lines.** There is no behaviour change: status\nfiltering happens on the server, and the Status column\u0027s\n`[nzFilterFn]\u003d\"true\"` is a literal flag, not a reference to\n`filterByStatus`.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #2131 (2023-09-07), \"Execution dashboard\nfrontend\". `filterByStatus` was the Status column filter; `dataCheck`\ngated the polling update of a row |\n| **Usage removed by** | #3105 (2025-01-15), \"Execution Dashboard\nBackend Pagination \u0026 Frontend Loading Icon\". It replaced\n`[nzFilterFn]\u003d\"filterByStatus\"` with `[nzFilterFn]\u003d\"true\"` and deleted\nthe only `this.dataCheck(...)` call |\n\nThey have been dead for about twenty months, with only spec cases\nkeeping them in use.\n\n### Any related issues, documentation, discussions?\n\nCloses #8718\n\n### How was this PR tested?\n\nNo new tests. The spec drops from 53 to 49 cases, losing only the four\ncases for the removed members.\n\nFrom `frontend/`:\n\n- `npx ng test --watch\u003dfalse\n--include\u003d\u0027**/admin-execution.component.spec.ts\u0027`: 49 tests, all pass.\n- `yarn format:ci`: clean.\n- `npx ng build`: success.\n\nTo re-check:\n\n```\ngit grep -n \"dataCheck\\|filterByStatus\" -- frontend   # no hits\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "bcd0ec4f742264503114aa4388d82df8d35e9647",
      "tree": "6b88faac6d29f90bfa4ff61f3fd024c2f76e0556",
      "parents": [
        "564070a56b0a184b1cb1dd4e61a943915a5e79d7"
      ],
      "author": {
        "name": "Meng Wang",
        "email": "mengw15@uci.edu",
        "time": "Sun Sep 27 23:45:05 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Sep 27 23:45:05 2026 +0000"
      },
      "message": "fix(deploy): load example datasets against the account\u0027s real email (#8723)\n\n### What changes were proposed in this PR?\n\n`bin/single-node/examples/load-examples.sh` derived the owner email that\nfile-service matches dataset lookups against by concatenating\n`@example.com`\nonto the username. On a single-node deployment that never matches: the\nadmin\nseeded from `USER_SYS_ADMIN_USERNAME` has the username itself as its\nemail\n(`AuthResource.createAdminUser`), so the loader logged in as that admin,\nskipped\nits register branch, and every example file upload failed with\n`400 Dataset not found`. Both example datasets were created but left\nwith no\nfiles and no version, so the two example workflows pointed at CSV paths\nthat do\nnot exist.\n\nThe owner email now comes from the access token\u0027s `email` claim, which\nis\nwhatever the server actually stored — correct for the seeded admin and\nfor an\naccount the script had to register itself. The register call keeps an\n`@`-shaped address, which the server\u0027s format check requires.\n\nSecond, the loader now exits non-zero once it has logged an error. Each\nfailure\nis still non-fatal so one bad file does not abandon the rest, but they\nused to\nleave no trace: the container printed `\u003d\u003d\u003d Example data loading complete\n\u003d\u003d\u003d`\nand exited 0. That is why the broken lookup went unnoticed for two\nmonths.\n\n### Any related issues, documentation, discussions?\n\nCloses #8721.\n\nIntroduced by #6402, which had to give the register call a regex-valid\naddress\nand changed the shared variable rather than splitting its two roles.\n`release/v1.3` carries it too.\n\n### How was this PR tested?\n\nNew `bin/single-node/tests/test_load_examples_sh.sh` (9 assertions,\npicked up\nautomatically by build.yml\u0027s shell-test discovery) drives the loader\nagainst a\nstub `curl` — no docker, no network, no sleeping. It pins the owner\nemail to the\ntoken\u0027s claim, asserts it is never `\u003cusername\u003e@example.com`, and asserts\nthat a\nfailed upload or version create exits non-zero. Both fixes were reverted\nindividually to confirm the relevant assertions go red and the suite\nexits 1.\n\nEnd to end on a fresh single-node deployment (`down --volumes` then\n`up --with-examples`): the loader now reports `Owner email resolved as\n\u0027texera\u0027`\nand uploads both files, `dataset_version` goes from 0 rows to 2 (both\n`v1`), and\npresigned download of the two paths the example workflows scan returns\nHTTP 200.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (claude-opus-5)"
    },
    {
      "commit": "564070a56b0a184b1cb1dd4e61a943915a5e79d7",
      "tree": "15dd81284984f6a5ad0b3ba537329b714bcb84ff",
      "parents": [
        "63db8e3f43cdbbc5c031321727bbf937fbbdc6ea"
      ],
      "author": {
        "name": "Xuan Gu",
        "email": "162244362+xuang7@users.noreply.github.com",
        "time": "Sun Sep 27 23:40:21 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Sep 27 23:40:21 2026 +0000"
      },
      "message": "fix(deploy): lift nginx\u0027s 1 MiB body cap that rejects dataset upload parts (#8722)\n\n### What changes were proposed in this PR?\n\nThis PR adds two lines in the single-node nginx config\u0027s /api/dataset\nlocation: client_max_body_size 0; and proxy_request_buffering off;.\n\nnginx defaults client_max_body_size to 1 MiB, and the config never set\nit, so every dataset upload part larger than 1 MiB (the frontend default\nis 50 MiB) is rejected with 413 before reaching file-service. The upload\nsize stays governed by the admin-configurable chunk setting; nginx no\nlonger imposes a second, hidden cap.\n\n### Any related issues, documentation, discussions?\n\nCloses #8720.\n\n### How was this PR tested?\n\nTested on single node deployment.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Fable 5\n\n---------\n\nCo-authored-by: Claude Fable 5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "63db8e3f43cdbbc5c031321727bbf937fbbdc6ea",
      "tree": "d7ae2e107bb76b0496107de7e8601c6cc11177fb",
      "parents": [
        "b928f82b90286b92f15efd8514134578fcb19577"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Sun Sep 27 22:08:55 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Sep 27 22:08:55 2026 +0000"
      },
      "message": "chore(frontend): remove dead search-results inputs and styles (#8661)\n\n### What changes were proposed in this PR?\n\nRemoves the three `SearchResultsComponent` inputs that it never reads\n(`searchKeywords`, `showResourceTypes`, `pid`), the parent code that\nstill computes and binds them, and the CSS in\n`search-results.component.scss` and `section-style.scss` that matches no\nelement it can reach. Pure deletion, no behaviour change: **−172 / +10\nlines**.\n\n### History\n\n| | |\n| --- | --- |\n| **Reads removed by** | #2793 (2024-08-20) — \"Generalize List Item\"\nreplaced the per-type list items, and the `nz-layout` / `nz-sider`\nresource-type icon around each one, with the generic\n`ListItemComponent`, deleting every template read of the three inputs |\n| **Never matched** | #2776 (2024-08-19) — `.section-title\n.management-panel` and `.section-title .go-back-button` arrived with the\nextraction of `section-style.scss` and never matched a template that\nincludes it |\n\n\u003e Reviewer note — the keyword chain. `searchKeywords` fed each old list\nitem\u0027s `[keywords]` input, which drove the search-term highlight.\n`SearchComponent` and `HubSearchResultComponent` kept recomputing it\nfrom the filter bar on every search and binding it into the results\nlist, where nothing read it. The field and its assignments go in both\nparents. The two `SearchComponent` tests that only pinned the field go\ntoo. The tests that asserted on it alongside something still live now\nassert on that: the `?q\u003d` tests check the filter bar\u0027s master list, the\nhub early-return test checks `getSearchFilterParameters`, and the hub\nbinding test checks `currentUid` alone.\n`FiltersComponent.getSearchKeywords()` stays, because the search\nrequests still call it.\n\n\u003e Reviewer note — `detectChanges()` stays.\n`SearchComponent.ngAfterViewInit` assigned the keywords and then called\n`this.cdr.detectChanges()`. Only the assignment goes. The call also\nre-renders after a `?q\u003d` param is pushed into the filter bar, so it is\nnot part of the dead chain.\n\n\u003e Reviewer note — the CSS. Component styles use Emulated encapsulation,\nso a rule in `search-results.component.scss` can only match that\ncomponent\u0027s own template: a card, a virtual-scroll list of\n`texera-list-item`s, and two text-only \"Load more\" buttons. `nz-sider`,\n`nz-content` and `.resource-type-icon` styled the wrapper #2793 removed.\n`.dataset-search-bar`, the `.dataset-list-item { … }` block,\n`.subsection-grid-container` and `.ant-btn-icon-only` match nothing\nthere. The last two also duplicate the identical rules in\n`section-style.scss`, which the stylesheet already `@use`s. In\n`section-style.scss`, none of the nine stylesheets that include it\nbelongs to a template containing `management-panel` or `go-back-button`.\nThe search page\u0027s back button is in `SearchComponent`, whose stylesheet\ndoes not include `section-style.scss`, and the hub detail page styles\nits own. The commented-out `.utility-button-group` rule goes too. The\nheader comment that called the layout \"shared between workflows and\nfiles section\" now says it is shared by the user dashboard\u0027s resource\nsections.\n\n### Any related issues, documentation, discussions?\n\nCloses #8660\n\n### How was this PR tested?\n\nExisting tests, updated where they asserted on the removed field or\ninputs.\n\nFrom `frontend/`:\n\n- `npx ng build` — **success**. This is the gate that matters: a\nleftover `[searchKeywords]` or `[showResourceTypes]` binding on\n`texera-search-results` fails only under AOT, since template diagnostics\nare AOT-only.\n- `npx ng test --watch\u003dfalse --include\u003d\u0027**/search.component.spec.ts\u0027\n--include\u003d\u0027**/hub-search-result.component.spec.ts\u0027\n--include\u003d\u0027**/search-results.component.spec.ts\u0027` — 81 tests pass (3\nfiles).\n- `yarn format:ci` — clean.\n\nVerification, re-runnable by a reviewer (both return nothing):\n\n```\ngit grep -n \"searchKeywords\\|showResourceTypes\" -- frontend/src\ngit grep -n \"resource-type-icon\\|dataset-search-bar\\|dataset-list-item\\|management-panel\" -- frontend/src\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5.5)"
    },
    {
      "commit": "b928f82b90286b92f15efd8514134578fcb19577",
      "tree": "e891946c3169ac5bd3ea761540a8626377242ef5",
      "parents": [
        "5bc7f49a75bcaee257fe24bf7dfd91a83224f9d0"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Sun Sep 27 22:08:44 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Sep 27 22:08:44 2026 +0000"
      },
      "message": "chore(amber): remove the unused UpdateRecoveryStatus and ResendOutputTo payloads (#8332)\n\n### What changes were proposed in this PR?\n\nDeletes two of the three `RecoveryPayload` subtypes —\n`UpdateRecoveryStatus` and `ResendOutputTo` — which have no sender and\nno handler. Pure deletion, no behaviour change: **−39 lines**.\n\n`NotifyFailedNode` is the only subtype still in use (sent from\n`AmberClient` when a cluster node fails), and it stays, as does the\nsealed trait.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | #1677 (2022-11-07) — \"Amber Fault Tolerance:\nGlobal Recovery and Detection\" |\n| **Usage removed by** | #2208 (2023-11-15) — \"Refactoring of amber\nengine\" removed the `case UpdateRecoveryStatus(...)` and `case\nResendOutputTo(...)` handler arms along with the old recovery path |\n\nDead for about three years. They picked up unit tests in #4829\n(2026-05-03) during the coverage work, which is why they look live.\n\nRemoving them also frees the `ActorRef` and `ActorVirtualIdentity`\nimports, which only `ResendOutputTo` used.\n\n\u003e Reviewer note — the spec is edited, not just trimmed.\n`AmberMessageEnvelopesSpec` used `UpdateRecoveryStatus` as the payload\nfixture in its \"WorkflowRecoveryMessage carries sender and payload\"\ntest; that now uses `NotifyFailedNode`, so the envelope contract stays\ncovered. The suite-local `ActorSystem` and its `afterAll` existed\n**only** to give the `ResendOutputTo` test a real `ActorRef`, so they go\nwith it — which also drops the `BeforeAndAfterAll` mixin and the pekko\n`ActorSystem`/`TestKit` imports. The remaining 10 tests pass.\n\n### Any related issues, documentation, discussions?\n\nCloses #8329\n\n### How was this PR tested?\n\nExisting tests only — this PR adds none; it removes two types and\nrewrites the assertions that referenced them.\n\nLocally, from the repo root with Java 17:\n\n- `sbt \"WorkflowExecutionService/Test/compile\"` — success.\n- `sbt \"WorkflowExecutionService/testOnly *AmberMessageEnvelopesSpec\"` —\n10 tests, all pass.\n- `sbt scalafmtCheckAll \"scalafixAll --check\"` — clean.\n\nVerification, re-runnable by a reviewer:\n\n```\ngit grep -n \"UpdateRecoveryStatus\\|ResendOutputTo\"   # only the deleted declarations and their assertions\ngit grep -n \"NotifyFailedNode\" -- amber/src/main     # the live subtype, untouched\n```\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5)"
    },
    {
      "commit": "5bc7f49a75bcaee257fe24bf7dfd91a83224f9d0",
      "tree": "cc9c82a78f87ddc3dacbdfc1ba094133c986c1a3",
      "parents": [
        "662387be647006356ed45e45ab988140bf178b94"
      ],
      "author": {
        "name": "Xinyuan Lin",
        "email": "xinyual3@uci.edu",
        "time": "Sun Sep 27 22:08:33 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Sep 27 22:08:33 2026 +0000"
      },
      "message": "chore(workflow-operator): remove the unreferenced PropertyNameConstants (#8333)\n\n### What changes were proposed in this PR?\n\n`PropertyNameConstants` declares 21 constants; only two are referenced\nanywhere outside its own spec. This removes the other 19. Pure deletion,\nno behaviour change: **−95 lines**.\n\n`LogicalOp` uses `OPERATOR_ID` and `OPERATOR_VERSION` as `@JsonProperty`\nannotation arguments — those are live and stay. Each of the other 19 has\nexactly three references, all inside `PropertyNameConstantsSpec`.\n\n### History\n\n| | |\n| --- | --- |\n| **Introduced by** | the initial amber import, commit `41a8a92017`\n(2020-08-20) — predates the PR workflow |\n| **Usage removed by** | **never adopted** — operator descriptors always\nspelled their JSON keys as raw string literals, and the wire format is\nanchored elsewhere (`@JsonTypeInfo(property \u003d \"operatorType\")` in\n`LogicalOp`, plus literals in `OperatorMetadataGenerator` and\n`WorkflowResource`) |\n\nThese constants were never the single source of truth they were meant to\nbe, which is why deleting them cannot change the serialized format.\n\n\u003e Reviewer note: `TABLE_NAME` **is** included. Its only qualified\nreferences are in the spec; the bare `TABLE_NAME` hits elsewhere are an\nunrelated SQL placeholder in `sql/misc/tweets.sql`. The spec keeps its\nthree tests, narrowed to the two surviving constants — including the\ndistinctness and whitespace checks, which still hold.\n\n### Any related issues, documentation, discussions?\n\nCloses #8330\n\n### How was this PR tested?\n\nExisting tests only — this PR adds none; it narrows the assertions to\nthe constants that remain.\n\nLocally, from the repo root with Java 17:\n\n- `sbt \"WorkflowExecutionService/Test/compile\"` — success.\n- `sbt \"WorkflowOperator/testOnly *PropertyNameConstantsSpec\"` — 3\ntests, all pass.\n- `sbt scalafmtCheckAll \"scalafixAll --check\"` — clean.\n\nVerification, re-runnable by a reviewer:\n\n```\ngit grep -oh \"PropertyNameConstants\\.[A-Z_]*\" -- . \u0027:!*PropertyNameConstants.scala\u0027 | sort | uniq -c\n```\n\nBefore this change every constant shows exactly 3 hits (its spec\nassertions) except `OPERATOR_ID` and `OPERATOR_VERSION`, which show 4 —\nthe extra one being `LogicalOp`.\n\n### Was this PR authored or co-authored using generative AI tooling?\n\nGenerated-by: Claude Code (Claude Opus 5)"
    }
  ],
  "next": "662387be647006356ed45e45ab988140bf178b94"
}
