# AGENTS.md ## What this repo is `phorge-elasticsearch-modern` is a Phorge full-text search extension that replaces the bundled Elasticsearch 5.x engine with one that speaks the typeless Elasticsearch 7.x/8.x and OpenSearch REST API. It implements `PhabricatorFulltextStorageEngine` (via `PhabricatorElasticFulltextStorageEngine`) and is registered as a phutil library that Phorge loads at runtime. Current status: **v0.1.0 in active development**. Twelve `task/*` feature PRs are in flight, all stacked against `development`. The engine passes its 16-unit PhutilTestCase suite; live smoke tests (V1–V4) against a real Phorge + Elasticsearch cluster are the next milestone. Spec + plan: [Confluence page 891322369](https://vyos.atlassian.net/wiki/spaces/VYOS/pages/891322369) --- ## Repository layout ```text src/ host/ VyOSElasticModernHost.php # PhabricatorClusterSearchHost subclass (final) engine/ VyOSElasticModernFulltextStorageEngine.php # main engine class (final) __tests__/ VyOSElasticModernEngineTestCase.php # PhutilTestCase unit tests (16/16) __phutil_library_init__.php # phutil library registration __phutil_library_map__.php # phutil symbol map (generated by arc liberate) README.md VERIFICATION.md # planned — smoke-test guide LICENSE AGENTS.md # this file .github/ copilot-instructions.md # symlink → ../AGENTS.md .coderabbit.yaml .mergify.yml .arcconfig ``` --- ## Working directory and toolchain | Item | Value | |------|-------| | Repo path | `~/GitHub/phorge-elasticsearch-modern/` | | Parent Phorge clone | `~/GitHub/phorge/` (Phorge HEAD, used for class lookup and smoke tests) | | PHP | Homebrew `php@8.3` | | Arcanist | `~/GitHub/arcanist/bin/arc` | | PATH bootstrap | `/Users/syncer/GitHub/arcanist/bin:/opt/homebrew/opt/php@8.3/bin` | The local Phorge dev environment (Docker + MySQL) is needed for the V1–V4 smoke tests. Unit tests (PhutilTestCase only) do **not** require a running Phorge instance. --- ## Branch model | Branch | Purpose | |--------|---------| | `production` | Default branch; stable releases. Plumbing and governance land here directly. | | `development` | Integration branch; task PRs merge here via the stacked chain. | | `task/` | One per PR; stacked against `development`. | Promotion path: `development` → `production` via a promotion PR after the task stack closes. --- ## Test discipline ```bash # Run all unit tests (no Phorge daemon or MySQL needed) arc unit -- ``` Test base class: `PhutilTestCase`. Do **not** use `PhabricatorTestCase` — the latter bootstraps Phorge and requires a running MySQL instance. Current count: **16/16 passing**. --- ## Lint discipline ```bash arc lint -- ``` Clean except one advisory XHP132 warning (documented inline in the engine class). --- ## PR and review flow This repo follows the standard VyOS flow from `~/.claude/rules/global/vyos-github.md`: 1. Phase 0 — pre-PR `coderabbit review --base origin/ --agent` locally. 2. Phase 1 — draft PR; iterate `@copilot review` until silent. 3. Phase 2 — mark ready-for-review; CodeRabbit auto-reviews on the flip. 4. Adversarial review gate (Codex) fires after CodeRabbit threads are resolved, before merge. --- ## Key design constraints These are load-bearing decisions baked into the implementation. Do not silently reverse them. ### Class structure - `VyOSElasticModernFulltextStorageEngine` is **`final`** and lives at `src/engine/VyOSElasticModernFulltextStorageEngine.php`. Do not extend it; modify it in place. - `VyOSElasticModernHost` is **`final`** and lives at `src/host/VyOSElasticModernHost.php`. - `PhabricatorElasticsearchQueryBuilder` is **`final`** in upstream Phorge — use by composition (instantiate and call methods), never by subclassing. ### PHP visibility - **Do NOT redeclare `$service`** as a property in the engine or host class. The parent `PhabricatorFulltextStorageEngine` declares it `protected`; redeclaring as `private` in a `final` child class causes a PHP fatal: `Cannot redeclare $service as private`. ### Engine identifier - The identifier string `'elasticsearch-modern'` is load-bearing. Phorge's `cluster.search[].type` config key selects the engine by this string. Changing it requires a coordinated config migration on every deployment. ### Query semantics - The `exclude` saved-query parameter uses `bool.must_not.ids`, **not** the obsolete Elasticsearch 5.x `not` filter clause (removed in ES 6+). - All index operations use the typeless API (`//_doc/`), not the deprecated `///` form. ### Index lifecycle - The engine manages a single index per Phorge installation, named via `getIndexName()`. - `buildSpec()` returns a typeless index settings + mappings body compatible with ES 7+/ OpenSearch. --- ## Notes for future contributors - The `__phutil_library_map__.php` is generated by `arc liberate .` — do not edit it manually. Regenerate it whenever a new class is added. - Smoke tests V1–V4 require a live Phorge + Elasticsearch 7+ cluster. See `VERIFICATION.md` (planned) for the matrix. - No `arc diff` / Differential workflow — this repo uses GitHub PRs directly. - License: Apache 2.0 — see `LICENSE`.