This is an automated email from the ASF dual-hosted git repository.

mattcasters pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new 83cf6ce835 General Hop software development guidelines for AI agents. 
(#8296)
83cf6ce835 is described below

commit 83cf6ce8350113d7041703eb3457ba2ef787a83e
Author: Matt Casters <[email protected]>
AuthorDate: Tue Sep 8 23:49:15 2026 +0200

    General Hop software development guidelines for AI agents. (#8296)
---
 AGENTS.md | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/AGENTS.md b/AGENTS.md
index ece27f79eb..ea81fcfd0d 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -44,3 +44,82 @@ Security model: [SECURITY.md](./SECURITY.md)
 
 Agents that scan this repository should consult `SECURITY.md` and the
 threat model it links before reporting issues.
+
+# Apache Commons VFS
+
+Unless there really is no other choice, files are read from or written to 
using Apache Commons VFS, HopVfs.getInputStream() or HopVfs.getOutputStream().  
Use of java.io.File is reserved for rare and exceptional cases. The default is 
to use org.apache.commons.vfs2.FileObject instead.
+
+# Build Apache Hop with isolated display
+
+When building the `ui` maven component make sure to do this with an isolated 
display to prevent instantiating focus-stealing UI artifacts on the developers 
display. Use tools/with-isolated-display.sh to do this, for example:
+
+```
+tools/with-isolated-display.sh mvn -T10 -pl ui clean install
+```
+
+or a full build of the Apache Hop assembly
+
+```
+tools/with-isolated-display.sh mvn -T10 clean install
+```
+
+# GUI-backed features
+
+We want to avoid building any functionality that is only expressed in a file 
and not in a GUI element.
+
+# Apache Hop GUI dialogs
+
+When building or changing a transform, action, metadata, or run-configuration 
dialog in Apache Hop (core or a plugin), **do not hand-layout FormAttachment 
rows on the shell first**. Start with annotated metadata widgets and a grouped 
`GuiCompositeWidgets` container.
+
+## Why groups
+
+A flat `createCompositeWidgets` / `addScrolledComposite` form cannot 
simultaneously:
+
+- keep the dialog resizable
+- keep OK/Cancel pinned to the bottom of the shell
+- keep those buttons strictly below the last widget
+
+The fields and the button bar fight for the same vertical space, so the 
buttons overlap the lower widgets. Putting `@GuiWidgetElement` fields in a 
**group** makes `GuiCompositeWidgets` build a container that fills the area 
between the name/header line and the button bar, with a **scrolled composite 
inside** (tabs, boxes, or list). Resize works; buttons stay put; overflow 
scrolls.
+
+## Default recipe
+
+1. Annotate the Meta (or equivalent) class with `@GuiPlugin` and Lombok 
`@Getter` / `@Setter`.
+2. Give the dialog a `GUI_PLUGIN_ELEMENT_PARENT_ID` constant.
+3. Annotate every user-visible field with `@HopMetadataProperty` **and** 
`@GuiWidgetElement`.
+4. Put every field in a group. Repeat `groupType` on each field (the first 
non-`NONE` value wins; mixed types fall back to tabs).
+   One options panel: `groupType = GuiWidgetGroupType.BOXES` and a single 
`group` (see `DataSetOutputMeta`).
+   Several sections: `GuiWidgetGroupType.TABS` with distinct `group` names and 
`groupOrder`.
+5. In the dialog `open()`: `createShell(...)`, 
`buildButtonBar().ok(...).cancel(...).build()`, then 
`GuiCompositeWidgets.addScrolledComposite(shell, variables, wTransformName, 
wOk, PARENT_ID, input)`.
+6. On OK, `widgets.getWidgetsContents(input, PARENT_ID)` and set the 
transform/action name. Do not copy fields by hand.
+
+```java
+@GuiWidgetElement(
+    id = WIDGET_DATA_SET_NAME,
+    order = "0100",
+    type = GuiElementType.METADATA,
+    metadata = DataSet.class,
+    label = "i18n::DataSetOutputMeta.DataSetName.Label",
+    toolTip = "i18n::DataSetOutputMeta.DataSetName.Tooltip",
+    parentId = GUI_PLUGIN_ELEMENT_PARENT_ID,
+    groupType = GuiWidgetGroupType.BOXES,
+    group = "Data Set")
+@HopMetadataProperty(hopMetadataPropertyType = 
HopMetadataPropertyType.PIPELINE_DATA_SET)
+private String dataSetName;
+```
+
+Use `GuiElementType` that matches the value: `METADATA`, `FOLDER`, `FILENAME`, 
`TEXT`, `CHECKBOX`, `COMBO`, and so on. Labels and tooltips live in the Meta's 
`messages_en_US.properties`; quote variable examples as 
`'${HOP_DATASETS_FOLDER}'`.
+
+## When not to flatten the form
+
+Hand-built SWT is for things annotations cannot express (canvas, custom 
painters). A `TableView` or similar extra composite belongs in the same grouped 
layout via `GuiCompositeWidgets.registerExtraGroup(...)`, not as a 
free-floating control under the button bar.
+
+Listeners (`IGuiPluginCompositeWidgetsListener`) are for enable/disable and 
`setChanged()`, not for creating the fields.
+
+# Hop i18n resource bundles
+
+Values defined in resource bundles (resource files in 
`messages/messages\*.properties` files) need to be properly escaped and quoted. 
 This means that variables expressions like `${VARIABLE}` really need to be 
surrounded with single quotes like this: `'${VARIABLE}'`.
+
+# Lombok
+
+Apache Hop and related projects should use Lombok for all classes to avoid 
cluttering classes with boilerplate getter/setter methods.
+

Reply via email to