Skip to content

docs: say what a new operator owes beyond its own code - #8459

Open
kz930 wants to merge 7 commits into
apache:mainfrom
kz930:docs/guide-to-add-a-new-operator
Open

docs: say what a new operator owes beyond its own code#8459
kz930 wants to merge 7 commits into
apache:mainfrom
kz930:docs/guide-to-add-a-new-operator

Conversation

@kz930

@kz930 kz930 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

What changes were proposed in this PR?

A page for contributors adding an operator, covering what the existing Java and
Python guides do not: declaring the output schema, stating a constraint on every
config property, writing the standalone Python fragment the exporter needs,
getting a green verification run, and recording a run that cannot happen.

Two diagrams carry the shape of the translation and of the two compared paths.

AGENTS.md gains a line on the same footing: the Python venv has to be
rebuilt from the requirement files when they change, since CI builds its
interpreter from them on every run and a stale one tests versions the product
never sees.

Each rule here was read out of the code rather than recalled, which corrected
three things a reader would otherwise have been told wrong. Numeric bounds come
from a field's @JsonSchemaInject, not from @Min and @Max, which nothing in
the repository uses and whose upper bound the configuration generator never
reads. A pattern is read both by the browser and by that generator, and only
the second matches whole strings, so an unanchored one does not mean the same
thing to both. And WCS_TEST_FILTER is how CI splits its two jobs, not
something a local run sets.

Any related issues, documentation, discussions?

Part of #8325, 27 of 27; that issue lists the set in order.

Closes #8458, the task this change is the whole of.

The two guides this one sits beside are
guide-to-implement-java-operator and guide-to-implement-python-operator;
they cover the operator's own logic, and stop there. getOutputSchemas appears
in neither, although every operator must implement it, and a schema that
disagrees with what the executor emits fails at run time rather than at compile
time.

How was this PR tested?

Documentation only, so there is nothing to run. Every claim in it was checked
against the code it describes rather than against memory: the annotation names
against their declarations, the fill rules against ConfigGenerator, the
environment variables against build.sbt and the CI workflow, and the two
image references and two internal links against the files they name.

Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (Opus 5)

@github-actions github-actions Bot added docs Changes related to documentations platform Non-amber Scala service paths labels Sep 9, 2026
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Automated Reviewer Suggestions

Based on the git blame history of the changed files, we recommend the following reviewers:

  • Contributors with relevant context: @mengw15
    You can notify them by mentioning @mengw15 in a comment.

@codecov-commenter

codecov-commenter commented Sep 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.99%. Comparing base (7976744) to head (0c9255b).
⚠️ Report is 30 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #8459      +/-   ##
============================================
- Coverage     94.11%   93.99%   -0.13%     
- Complexity     4811     4862      +51     
============================================
  Files          1197     1204       +7     
  Lines         48813    49071     +258     
  Branches       5906     5945      +39     
============================================
+ Hits          45939    46122     +183     
- Misses         1420     1475      +55     
- Partials       1454     1474      +20     
Flag Coverage Δ *Carryforward flag
access-control-service 80.18% <ø> (-0.82%) ⬇️
agent-service 99.32% <ø> (ø) Carriedforward from 3848a02
amber 90.08% <ø> (ø) Carriedforward from 3848a02
computing-unit-managing-service 75.05% <ø> (+1.38%) ⬆️
config-service 87.12% <ø> (+0.12%) ⬆️
file-service 83.65% <ø> (-4.27%) ⬇️ Carriedforward from 3848a02
frontend 96.86% <ø> (ø) Carriedforward from 3848a02
notebook-migration-service 83.73% <ø> (+4.42%) ⬆️
pyamber 98.47% <ø> (ø) Carriedforward from 3848a02
workflow-compiling-service 77.19% <ø> (ø) Carriedforward from 3848a02

*This pull request uses carry forward flags. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

The Java and Python guides cover writing the operator. What they do not cover is
everything a new one has to satisfy afterwards: a stated constraint on each
config property, the standalone Python fragment the exporter needs, a green
verification run, and where to record a run that cannot happen.

Written from the code rather than from memory, so it names the mechanisms as
they are: bounds come from a field's JsonSchemaInject rather than from Min and
Max, which nothing here uses; a pattern is read by the browser and by the
verification generator, and only one of the two matches whole strings.

Two diagrams carry the shape of the translation and of the two compared paths.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@kz930
kz930 force-pushed the docs/guide-to-add-a-new-operator branch from 0c9255b to 334af61 Compare September 9, 2026 05:19
@github-actions github-actions Bot removed the platform Non-amber Scala service paths label Sep 9, 2026
kz930 and others added 3 commits September 9, 2026 17:38
The page said to implement `getOutputSchemas`. That is the Python operator's
way; a Java or Scala one declares its output through a `SchemaPropagationFunc`
inside `getPhysicalOp`, which is what 32 of the registered operators do.

And escaping has a second half. A `pyb` field has to reach the template whole,
so joining it to anything in Scala first defeats it — the protected value is
handed over as a plain string, and the placeholder leaks into the emitted
Python.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The page told a new operator to implement `generateStandaloneCode()` and
said nothing about the declared type, which is what decides how a column
becomes text. Adding the boolean column to the canonical table also made
the count of hostile-named columns wrong.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CI builds its interpreter from the requirement files on every run, so a
venv left behind locally tests library versions the product never sees,
and a failure only there reads like a defect in the code.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@kz930

kz930 commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

@carloea2 this one is documentation: what a new operator owes beyond its own code, written from what the last few operators actually needed. Would you take a look when you have a moment?

kz930 and others added 3 commits September 10, 2026 21:37
The guide described the empty-cell run and stopped there. The empty-table
run asks a different question: that table still has a value in every
column somewhere, so code reading a range or a quantile finds one, while
this one has nothing to read.

The venv line named one requirements file. An operator's libraries are in
the other.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The guide covered the canonical table and said only that source operators
bring their own file. A contributor adding one could not tell whether
SourceCategoryRunner needed editing, and for the common case it does not:
a scan source whose declared format already has an encoder is verified
with no code there at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Writing the Parquet source cost a debugging cycle on this: the file counts
from the epoch, a Texera TIMESTAMP is a wall clock, and reading the count
with `new Timestamp(millis)` moves it by the machine's own offset while
pandas reads the same number as UTC. The two paths then part by that
offset, and agree again on a machine set to UTC, so a CI that runs there
never shows it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Changes related to documentations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Say what a new operator owes beyond its own code

2 participants