docs: add AGENTS.md (AI-contributor guardrails) + AGENTS_USER_EXAMPLE.md#343
Conversation
There was a problem hiding this comment.
Pull request overview
Adds repository documentation intended to guide AI-assisted contributions and provide a copyable starter template for users writing OIE channel/template JavaScript.
Changes:
- Adds
CLAUDE.mdat the repo root with guardrails for AI-assisted work on the engine codebase. - Adds
CLAUDE_USER_EXAMPLE.mdas a copy-me starterCLAUDE.mdfor user-owned channel/template JavaScript repositories.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
CLAUDE.md |
Documents AI-contributor guardrails and contribution/build expectations for engine changes. |
CLAUDE_USER_EXAMPLE.md |
Provides a user-repo template describing Rhino/JS constraints and recommended patterns for deployed scripts. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - **Build + test** (what CI runs off `main`): `cd server && ant -f mirth-build.xml -DdisableSigning=true -Dcoverage=true` | ||
| (the signed build drops the flags and runs on `main`). JUnit results land under | ||
| `*/build/test-results/**/*.xml`. **A red build is not reviewable — never open a PR on one.** |
| ### Supported ES6 features (safe to use) | ||
| - `const` and `let` — prefer over `var`. `const` by default, `let` when reassignment is needed (but see the | ||
| Rhino loop-scoping bug below). | ||
| - Arrow functions `() => {}` — fine in callbacks, `.map()`, `.filter()`, etc. | ||
| - Object/array destructuring — `const { a, b } = options` | ||
| - `Object.keys()`, `Object.values()`, `Object.entries()`, `Object.assign()` | ||
| - Array methods: `.map()`, `.filter()`, `.reduce()`, `.forEach()`, `.find()`, `.some()`, `.every()` | ||
|
|
||
| ### Prohibited ES6+ features (will break at runtime in OIE) | ||
| - **Template literals** — NEVER use backtick strings. `` `Hello ${name}` `` fails at runtime. Use string | ||
| concatenation or `Array.join()` (see "String building"). | ||
| - **Optional chaining `?.`** — not supported; use a try/catch helper (see "Safe property access"). | ||
| - **Nullish coalescing `??`** — use `||` or an explicit ternary. | ||
| - **`async`/`await`** — not supported. Transformers are synchronous; use callbacks/retries. | ||
| - **`Promise`** — not available in the runtime. | ||
| - **ES6 classes (`class`/`extends`)** — use constructor functions with `.prototype` methods. | ||
| - **ES6 modules (`import`/`export`)** — share code via Code Templates plus `/* global */` and | ||
| `/* exported */` comments (see "Module/export pattern"). | ||
| - **Spread syntax `...args`** — minimal/unreliable support; avoid, especially in parameter lists. | ||
| - **`for...of` loops** — use `.forEach()` or a traditional indexed `for` loop. | ||
| - **Default parameters** — use `param = param || defaultValue` instead. |
|
Thanks for the review — both addressed in 1. CI build path — correct, fixed. The 2. Arrow functions — respectfully, this one I'd push back on. Rhino 1.7.13 does support arrow functions; the feature is gated on the |
| - Toolchain is pinned in [`.sdkmanrc`](./.sdkmanrc) — install [SDKMAN](https://sdkman.io/) and run | ||
| `sdk env install` in the repo root (the JavaFX-bundled JDK is required; the `client` GUI imports JavaFX). | ||
| - **Build + test** (run this locally; it's also the CI build on pull requests): | ||
| `cd server && ant -f mirth-build.xml -DdisableSigning=true -Dcoverage=true`. CI runs this unsigned + |
There was a problem hiding this comment.
This part must adapt to use the new gradle build
There was a problem hiding this comment.
Good catch, thanks — fixed in aa5ca2a. I also rebased the branch onto the post-Gradle main (it was still based on the Ant tree).
The build section now points at the wrapper and mirrors what CI actually invokes:
- PRs:
./gradlew build -PdisableSigning=true -Pcoverage=true main:./gradlew build(signed)
Everything else in the section checked out as still accurate against the new layout (.sdkmanrc/JavaFX JDK, and JUnit results still under */build/test-results/**/*.xml), and the other paths the file cites (server/license-header.txt, server/conf/mirth.properties) did not move.
While verifying I pulled two things out of your new CONTRIBUTING.md that seemed worth calling out to an agent specifically, since both fail CI in ways the diff does not explain — the cold-cache dependency-verification-metadata refresh, and the output-parity check on build-logic changes. I kept them to one line each and deferred the detail to CONTRIBUTING.md rather than duplicating it. Happy to drop them if you would rather that guidance live in exactly one place.
…EXAMPLE.md
CLAUDE.md: strict guidance for AI coding assistants working on the engine itself,
designed to protect the project from low-quality sprawling AI changes ("vibeslop").
- Push-back-first: for non-trivial work, state the change + any concrete disagreement
+ a better alternative BEFORE editing (calibrated to blast radius, so no theater).
- Anti-sprawl bounded in breadth AND depth (<=3 files; ~40-50 line / whole-method cap).
- Preserve behavior/compat incl. the subtle breaks (charset, tz/locale, HL7 delimiters);
golden-output test for donkey/serialization changes; red-green regression tests.
- Healthcare security: no PHI logging; no unsafe deserialization/XXE (documented RCE class).
- Issue-first-and-wait; MPL header copied from server/license-header.txt; no slop tells.
- Grounded in the repo (Java 17 + Ant server/mirth-build.xml, module map, CONTRIBUTING).
- No orchestration skill by design. Advisory; notes which gates belong in CI.
CLAUDE_USER_EXAMPLE.md: a copy-me starter CLAUDE.md for a user's own channel/template
repo (JS on the Rhino runtime) — Rhino/ES5 constraints, loop-scoping bug, Java interop,
engine globals, code patterns; points at oie-examples and the docs site.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…o ES6 default - Rename CLAUDE.md -> AGENTS.md and CLAUDE_USER_EXAMPLE.md -> AGENTS_USER_EXAMPLE.md, and drop the Claude-specific wording, per maintainer preference in OpenIntegrationEngine#342 for a vendor-neutral instructions file. - Fix the build note: the `-DdisableSigning=true -Dcoverage=true` build is what CI runs on PRs; on `main` CI runs the signed build (same target, without those flags). - Note that OIE defaults `rhino.languageversion = es6` (server/conf/mirth.properties), which is what makes arrow functions / `let` / `const` work on the bundled Rhino 1.7.13.
The Ant build was replaced by Gradle (24c96f5), so the build/test command in AGENTS.md was stale. Point it at the wrapper and mirror the CI invocation; add the two build traps that fail CI without an obvious cause (cold-cache dependency verification metadata, build-logic output parity), deferring the detail to CONTRIBUTING.md.
9af1d8c to
aa5ca2a
Compare
|
Strong PR. Before commenting I verified this against current main and against the actual Rhino we ship, and most of it holds up impressively well. The build section is fully accurate (wrapper, .sdkmanrc, the exact CI flags per branch vs PR, the cold-cache verification-metadata trap, the parity guard), the referenced files all exist, the utility-class list matches I ran the Rhino claims against the 1. The SQL example teaches injection. The "String building" section shows 2. Two caveats on the helper conventions. 3. The loop-scoping section is right but incomplete. Your const-in-loop description reproduces exactly ( var fns = [];
for (let i = 0; i < 3; i++) { fns.push(function() { return i; }); }
// spec: fns[0]()===0, fns[1]()===1, fns[2]()===2
// Rhino 1.7.13: all three return 3Same for 4. Split the rules into durable vs version-dependent, and stamp the version. Some of these are 8-year-old open Ecma-incompatibility bugs (rhino#326, #647, #939, #969 for the const/let family) and safe to state as hard rules. Others are version-scoped: template literals were implemented in Rhino 1.7.14 (Jan 2022 release notes, issue #243), so they're broken on our 1.7.13 and fine one version later. And rhino#1386 (initializer-less 5. Template literals: the failure is silent, not a runtime error. On our 1.7.13 backticks evaluate cleanly and skip interpolation: var mrn = '123456';
var filename = `result_${mrn}.hl7`;
// Expected: result_123456.hl7
// Actual: result_${mrn}.hl7 (literally, no error thrown)Nothing errors, the channel stays green, and a File Writer keyed on that value writes every patient's result to one literally-named file. Suggest changing "fails at runtime" to "evaluates without error and emits the raw uninterpolated text". An AI that tests a backtick, sees no exception, and concludes the doc is stale is exactly the failure mode you're guarding against. 6. 7. Map accessors: two missing, one wrong. The engine defines seven, not five ( 8. Drop the numeric caps in rule 2. This is my one real disagreement on the engine-side file. The ≤3-file / ~40-50-line caps, and the prime directive's "the project does not want large multi-file, single-PR agent changes", would have branded the Ant-to-Gradle migration (#326) unwanted, and that was a large agent-assisted PR that's now the foundation of the build. It also contradicts your own build section: a routine dependency bump regenerates Housekeeping: your enforcement note says the CI gates "would be a good first contribution", let's file those as actual issues at merge time so they don't stay prose. Happy to take you up on moving |
Closes #342.
Adds two documentation files to help contributors who use AI coding assistants.
AGENTS.md(repo root) — guardrails for AI-assisted work on the engineDesigned to keep AI contributions small, reviewable, and from degrading code quality in a production healthcare engine:
donkey//serialization changes.ObjectInputStream) / XXE, referencing this codebase's documented RCE history.server/license-header.txt, no slop tells.server/mirth-build.xml), the module map, andCONTRIBUTING.md. No orchestration/automation skill by design. Advisory — it also notes which rules belong in CI/PR-template as hard gates.AGENTS_USER_EXAMPLE.md— starter for a user's own channel/template repoA copy-me
AGENTS.mdfor JavaScript that runs on the Rhino runtime: ES5/Rhino constraints, the loop-scoping bug, Java-interop gotchas, engine globals, and code patterns. Points atoie-examplesand the docs site. (Could alternatively live inoie-examples— happy to move it.)Disclosure
Both files were drafted with AI assistance (Claude Code). The content reflects my years of hands-on Mirth/Connect experience and research, and I have reviewed both in full and stand behind them. Feedback and scope changes welcome.