{"id":50971300,"url":"https://github.com/iamvirul/nexora","last_synced_at":"2026-06-19T02:32:29.345Z","repository":{"id":359415955,"uuid":"1244495601","full_name":"iamvirul/nexora","owner":"iamvirul","description":"Nexora is a Java execution engine that turns a high-level goal into a set of steps and runs them. ","archived":false,"fork":false,"pushed_at":"2026-06-08T09:47:12.000Z","size":1528,"stargazers_count":3,"open_issues_count":28,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-08T10:15:49.789Z","etag":null,"topics":["event-bus","execution-engine","grafana","java","prometheus"],"latest_commit_sha":null,"homepage":"https://iamvirul.github.io/nexora/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iamvirul.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-20T10:15:05.000Z","updated_at":"2026-06-08T08:51:41.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/iamvirul/nexora","commit_stats":null,"previous_names":["iamvirul/nexora"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/iamvirul/nexora","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iamvirul%2Fnexora","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iamvirul%2Fnexora/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iamvirul%2Fnexora/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iamvirul%2Fnexora/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iamvirul","download_url":"https://codeload.github.com/iamvirul/nexora/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iamvirul%2Fnexora/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34515405,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-19T02:00:06.005Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["event-bus","execution-engine","grafana","java","prometheus"],"created_at":"2026-06-19T02:32:28.306Z","updated_at":"2026-06-19T02:32:29.336Z","avatar_url":"https://github.com/iamvirul.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Nexora\n\n[![CI](https://github.com/iamvirul/nexora/actions/workflows/ci.yml/badge.svg)](https://github.com/iamvirul/nexora/actions/workflows/ci.yml)\n[![Trivy Scan](https://github.com/iamvirul/nexora/actions/workflows/trivy.yml/badge.svg)](https://github.com/iamvirul/nexora/actions/workflows/trivy.yml)\n[![Java](https://img.shields.io/badge/Java-21%2B-blue.svg)](https://www.oracle.com/java/)\n[![License](https://img.shields.io/github/license/iamvirul/nexora)](https://github.com/iamvirul/nexora/blob/main/LICENSE)\n[![GitHub last commit](https://img.shields.io/github/last-commit/iamvirul/nexora)](https://github.com/iamvirul/nexora/commits/main)\n\nNexora is a Java execution engine that turns a high-level goal into a set of steps and runs them. You tell it what you want to happen, and it figures out the order, runs independent steps in parallel, and gives you back a result.\n\n\u003cimg width=\"1346\" height=\"1162\" alt=\"image\" src=\"https://github.com/user-attachments/assets/96b64472-26a5-42cf-93dd-990062c9ba23\" /\u003e\n\n\nThe idea is that you shouldn't have to hard-code execution logic. You declare capabilities (things the system can do), define which steps map to which goal keywords, and Nexora handles the rest: planning, scheduling, retrying on failure, and tracing what happened.\n\nThree things set it apart from every other workflow engine:\n\n- **Pluggable planner SPI** - the planner itself is a plugin. Swap in an LLM, a constraint solver, or your own rule engine. The built-in keyword matcher is just the default.\n- **Reactive plan amendment** - a step can reshape the remaining plan based on what it produced. Inject new steps, skip pending ones, or override inputs for downstream steps, all at runtime without touching the planner.\n- **Capability contracts with automatic fallback** - capabilities declare their expected latency and error rate. The engine monitors live call metrics and silently reroutes to a fallback capability when the primary starts breaching its contract.\n\n## How it works\n\nWhen you call `engine.execute(\"process order payment\", context)`:\n\n1. The **planner** matches the goal against registered step definitions and builds a DAG\n2. The **scheduler** walks the DAG and starts every step whose dependencies are already done; independent steps run in parallel on virtual threads\n3. Each step flows through an **interceptor pipeline** (tracing -\u003e retry -\u003e timeout) before hitting the actual capability\n4. If a step returns **plan amendments**, the scheduler applies them before any dependent step begins\n5. The **contract monitor** tracks every call outcome; if a capability breaches its declared SLA, traffic is rerouted to its fallback\n6. Events fire as steps start, complete, fail, or when the plan is amended; you can subscribe to any of them\n\nA concrete example: four steps, two run in parallel.\n\n```\nvalidate_order --+\n                 +--\u003e charge_card --\u003e send_receipt\nfetch_inventory -+\n```\n\n`validate_order` and `fetch_inventory` start at the same time. `charge_card` waits for `validate_order`. `send_receipt` waits for both. Nexora works all of this out from the `dependsOn` declarations. You don't schedule anything manually.\n\nAt runtime, `validate_order` can inject a new `audit_log` step into that DAG without the planner being involved at all.\n\n## Requirements\n\n- Java 21\n- Maven 3.9+\n\n## Build\n\n```bash\nmvn install -DskipTests\n```\n\nThe CLI fat JAR ends up at `nexora-cli/target/nexora.jar`.\n\n## Try it immediately\n\nNo config file needed. The `demo` command showcases all three differentiating features in a single run:\n\n```bash\njava -jar nexora-cli/target/nexora.jar demo\n```\n\n```\nNexora Feature Demo\n===================\n\nFeatures demonstrated:\n  1. Pluggable planner SPI  - rule-based planner wired via CompositePlanner\n  2. Reactive plan amendment - validate_order injects audit_log at runtime\n  3. Capability contracts    - charge_card declares p99 SLA + fallback\n\nInitial DAG (from planner):\n  validate_order --+\n                   +--\u003e charge_card --\u003e send_receipt\n  fetch_inventory -+\n\n  validate_order will amend the plan at runtime, injecting:\n  --\u003e audit_log (runs after validate_order, before send_receipt)\n\nExecution:\n  ✓ validate_order          37ms\n  ~ plan amended: ADD_STEP   -\u003e audit_log\n  ~ plan amended: MODIFY_INPUT -\u003e send_receipt\n  ✓ fetch_inventory         54ms\n  ✓ audit_log               16ms\n  ✓ charge_card             86ms\n  ✓ send_receipt            22ms\n\nResult:   COMPLETED\nSteps:    5 executed\n\nContract health (charge_card):\n  samples=1  error-rate=0%  p99=86ms\n```\n\nThe plan started with 4 steps and finished with 5. `validate_order` injected `audit_log` mid-run. `charge_card` was monitored against its declared p99=200ms SLA throughout.\n\n## CLI\n\n```\nnexora [--config \u003cfile\u003e] \u003ccommand\u003e\n```\n\n| Command | What it does |\n|---------|-------------|\n| `nexora run -g \"\u003cgoal\u003e\"` | Execute an intent and stream step results |\n| `nexora plan -g \"\u003cgoal\u003e\"` | Dry run: show the DAG without executing anything |\n| `nexora caps` | List all registered capabilities |\n| `nexora plugins` | List active plugins |\n| `nexora observe` | Start UI/API/metrics server for live process observability |\n| `nexora demo` | Run the built-in feature demo |\n| `nexora dlq list` | List dead letter queue entries (default: PENDING) |\n| `nexora dlq replay \u003cid\u003e` | Replay a dead-lettered execution |\n| `nexora dlq resolve \u003cid\u003e` | Mark a dead letter as resolved |\n\nPass `-c '{\"key\":\"value\"}'` to `run` to inject context values that steps can reference.\n\n## Config file\n\nBy default Nexora looks for `nexora.json` in the working directory. Point to a different one with `--config`.\n\n```json\n{\n  \"steps\": [\n    {\n      \"id\": \"validate_order\",\n      \"capabilityId\": \"validate_order\",\n      \"matchesGoalContains\": \"order\"\n    },\n    {\n      \"id\": \"charge_card\",\n      \"capabilityId\": \"charge_card\",\n      \"matchesGoalContains\": \"payment\"\n    }\n  ],\n  \"retry\": {\n    \"maxAttempts\": 3,\n    \"initialDelayMs\": 200,\n    \"multiplier\": 2.0,\n    \"maxDelayMs\": 10000\n  }\n}\n```\n\nA step is included in the plan when its `matchesGoalContains` string appears in the goal. Dependencies between steps are declared in code using `StepDefinition`'s `dependsOn` set.\n\n## Using it as a library\n\n```java\nNexoraEngine engine = NexoraEngine.builder()\n    .withPlugin(myPlugin)\n    .withStepDefinition(new StepDefinition(\n        \"validate_order\", \"validate_order\",\n        goal -\u003e goal.contains(\"order\")\n    ))\n    .build();\n\nengine.subscribe(StepCompletedEvent.class, e -\u003e\n    System.out.printf(\"done: %s in %dms%n\", e.stepId(), e.elapsed().toMillis()));\n\nExecutionResult result = engine\n    .execute(\"process order payment\", Map.of(\"orderId\", \"ORD-99\"))\n    .get();\n```\n\n## Pluggable planner\n\nThe planner that converts a goal string into a DAG is itself a plugin. Implement `Planner` and return it from `plannerProviders()` in your `NexoraPlugin`:\n\n```java\npublic class MySmartPlanner implements Planner {\n\n    @Override\n    public PlannerDescriptor descriptor() {\n        return new PlannerDescriptor(\"my-planner\", \"LLM-backed planner\", 100);\n    }\n\n    @Override\n    public boolean canPlan(Intent intent, PlanningContext context) {\n        return intent.getGoal().length() \u003e 20; // handle complex goals\n    }\n\n    @Override\n    public Plan plan(Intent intent, PlanningContext context) {\n        // use context.availableCapabilities() to see what's registered\n        // build and return a Plan\n    }\n}\n```\n\nThe engine tries planners in descending priority order. The built-in rule-based planner always sits last as the fallback. Registering a planner with priority 100 means it runs first; if `canPlan()` returns false, the next one is tried.\n\nYou can also register a planner directly without a plugin:\n\n```java\nNexoraEngine.builder()\n    .withPlanner(new MySmartPlanner())\n    .build();\n```\n\n## Reactive plan amendment\n\nA capability can reshape the remaining plan by returning amendments alongside its result:\n\n```java\nreturn CapabilityResult.success(\n    Map.of(\"valid\", true),\n    List.of(\n        // inject a new step that runs after this one\n        new AddStepAmendment(new Step(\"audit_log\", \"audit_log\",\n            Map.of(\"orderId\", InputBinding.literal(orderId)),\n            null, Set.of(\"validate_order\"), null, null)),\n\n        // override an input for a downstream step\n        new ModifyInputAmendment(\"send_receipt\", \"audited\", true),\n\n        // cancel a step that is no longer needed\n        new SkipStepAmendment(\"legacy_check\")\n    )\n);\n```\n\nAmendments are applied by the scheduler before any dependent step begins. A `PlanAmendedEvent` fires for each one so you can observe every mutation.\n\n## Capability contracts\n\n\u003e **Note**: Stateful circuit breaker options (`openDuration` and `probeInterval`) are currently **Unreleased**.\n\nCapabilities declare their expected operational behaviour. The engine monitors every call and reroutes traffic when a capability breaches its contract:\n\n```java\nnew CapabilityDescriptor(\n    \"charge_card\", \"Charges the customer card\",\n    List.of(), List.of(), false, false,\n    CapabilityContract.builder()\n        .p99Latency(Duration.ofMillis(200))\n        .maxErrorRate(0.05)\n        .windowSize(20)\n        .openDuration(Duration.ofSeconds(30))\n        .probeInterval(Duration.ofSeconds(10))\n        .fallback(\"charge_card_fallback\")\n        .build()\n)\n```\n\nIf `charge_card` starts exceeding 200ms p99 or failing more than 5% of the time over the last 20 calls, the engine silently opens the circuit and routes new calls to `charge_card_fallback`. The circuit remains `OPEN` for 30 seconds before transitioning to `HALF_OPEN`, where it probes the primary capability every 10 seconds. When the primary recovers, the circuit closes and traffic returns automatically. The caller sees a normal result either way.\n\nQuery live health at any time:\n\n```java\nNexoraEngine.HealthSnapshot health = NexoraEngine.HealthSnapshot.from(\n    engine.capabilityHealth(\"charge_card\"));\n// health.state(), health.sampleCount(), health.errorRate(), health.p99Latency()\n```\n\n## Writing a plugin\n\nA plugin is a JAR that implements `NexoraPlugin` and declares itself in `META-INF/services/com.nexora.spi.NexoraPlugin`.\n\n```java\npublic class MyPlugin implements NexoraPlugin {\n\n    @Override\n    public PluginDescriptor descriptor() {\n        return new PluginDescriptor(\"my-plugin\", \"1.0.0\", \"Does stuff\", List.of(), null);\n    }\n\n    @Override\n    public void initialize(PluginContext ctx) {}\n\n    @Override\n    public List\u003cCapabilityProvider\u003e capabilityProviders() {\n        return List.of(\n            new CapabilityProvider() {\n                public CapabilityDescriptor descriptor() {\n                    return new CapabilityDescriptor(\n                        \"my_capability\", \"My Capability\",\n                        List.of(), List.of(), true, false\n                    );\n                }\n                public Capability create(PluginContext ctx) {\n                    return request -\u003e CapabilityResult.success(Map.of(\"result\", \"ok\"));\n                }\n            }\n        );\n    }\n\n    @Override\n    public void shutdown() {}\n}\n```\n\nLoad a plugin JAR at runtime:\n\n```java\nengine.loadPlugin(Path.of(\"my-plugin.jar\"), \"my-plugin\");\n```\n\nOr wire it directly without a JAR (useful in tests):\n\n```java\nNexoraEngine.builder().withPlugin(new MyPlugin()).build();\n```\n\n## Events\n\nSubscribe to any event type:\n\n```java\nengine.subscribe(StepStartedEvent.class,   e -\u003e log.info(\"started: {}\", e.stepId()));\nengine.subscribe(StepCompletedEvent.class, e -\u003e log.info(\"done: {}\", e.stepId()));\nengine.subscribe(StepFailedEvent.class,    e -\u003e log.error(\"failed: {} {}\", e.stepId(), e.failureMessage()));\nengine.subscribe(PlanAmendedEvent.class,   e -\u003e log.info(\"plan mutated: {} -\u003e {}\", e.amendmentType(), e.targetStepId()));\nengine.subscribe(PlanCompletedEvent.class, e -\u003e metrics.record(e.elapsed()));\n```\n\nEvent handlers run on the engine's executor, not the caller's thread. A handler that throws does not affect execution or other handlers.\n\n## Retry\n\nThe default retry policy is no retry. Override it globally:\n\n```java\nNexoraEngine.builder()\n    .withDefaultRetryPolicy(\n        ExponentialBackoffPolicy.builder()\n            .maxAttempts(3)\n            .initialDelay(Duration.ofMillis(200))\n            .multiplier(2.0)\n            .maxDelay(Duration.ofSeconds(10))\n            .build()\n    )\n    .build();\n```\n\nBackoff includes ±25% jitter to avoid thundering herd on simultaneous failures.\n\n## Execution Deadline (Unreleased version)\n\nNexora allows you to set a plan-level wall-clock execution deadline. If the execution exceeds this duration, the entire plan is cancelled: running steps continue, but not-yet-started steps are suppressed, the terminal execution status is set to `TIMED_OUT`, and saga compensation is triggered for all successfully completed steps.\n\nYou can configure a global engine-wide default deadline using the builder:\n\n```java\nNexoraEngine engine = NexoraEngine.builder()\n    .withDefaultPlanDeadline(Duration.ofSeconds(5))\n    .build();\n```\n\nYou can also override the deadline per execution request:\n\n```java\n// Sets a 2-second deadline specifically for this execution\nCompletableFuture\u003cExecutionResult\u003e future = engine.execute(\n    \"process order payment notification\", \n    Map.of(\"orderId\", \"ORD-42\"), \n    Duration.ofSeconds(2)\n);\n```\n\nWhen a plan times out:\n1. The execution status resolves to `TIMED_OUT`.\n2. A `PlanTimedOutEvent` is published.\n3. Saga compensation runs for completed steps if saga is enabled.\n\n## Webhook Callbacks (Unreleased version)\n\nNexora allows you to register webhook URLs to be notified asynchronously when an execution reaches a terminal state (`COMPLETED`, `FAILED`, or `TIMED_OUT`). This is particularly useful when triggering executions remotely via the API and awaiting their outcome.\n\nTo use webhooks securely, configure an HMAC-SHA256 signature secret in your `nexora.json` or via the `NEXORA_WEBHOOK_SECRET` environment variable:\n\n```json\n{\n  \"webhookSecret\": \"your-secure-secret-here\",\n  \"steps\": []\n}\n```\n\nWhen invoking an execution, supply the `webhookUrl` and optionally filter which terminal `webhookEvents` trigger a callback:\n\n```bash\ncurl -X POST http://localhost:9464/api/execute \\\n  -H \"content-type: application/json\" \\\n  -d '{\n        \"goal\": \"process order payment\",\n        \"webhookUrl\": \"https://your-api.com/webhooks/nexora\",\n        \"webhookEvents\": [\"COMPLETED\", \"FAILED\", \"TIMED_OUT\"]\n      }'\n```\n\nNexora will dispatch a JSON payload to your endpoint with the execution outcome. It signs the payload using the configured secret and passes the signature in the `nexora-signature` HTTP header for validation. It also utilizes exponential backoff to retry deliveries up to 3 attempts. Delivery attempts are persisted in the `nexora_webhook_deliveries` database table and can be queried for auditability via the API.\n\n## Dead Letter Queue (Unreleased version)\n\nWhen a execution fails after exhausting all retries, Nexora writes a record to the `nexora_dead_letters` table and fires an `ExecutionDeadLetteredEvent` on the event bus. This gives operators a structured audit trail of every permanently failed execution and a way to replay or resolve them without querying the database directly.\n\nEach dead letter record carries:\n\n| Field | Description |\n|-------|-------------|\n| `id` | UUID of the dead letter record |\n| `executionId` | The original failed execution |\n| `goal` | The intent goal string |\n| `context` | The intent context (JSON) |\n| `failureCode` | Machine-readable failure code (e.g. `STEP_FAILED`) |\n| `failureMessage` | Human-readable error detail |\n| `failedAt` | When the failure occurred |\n| `reviewState` | `PENDING`, `RESOLVED`, or `REPLAYED` |\n\nSubscribe to the event for alerting:\n\n```java\nengine.subscribe(ExecutionDeadLetteredEvent.class, e -\u003e\n    alerting.notify(\"Execution dead-lettered: \" + e.executionId() + \" code=\" + e.failureCode()));\n```\n\nInspect and remediate via CLI:\n\n```bash\n# list all pending dead letters\nnexora dlq list\n\n# replay a failed execution (creates a new execution with the same goal and context)\nnexora dlq replay \u003cdead-letter-id\u003e\n\n# mark as resolved when no replay is needed\nnexora dlq resolve \u003cdead-letter-id\u003e --reason \"Root cause fixed in deployment 1.2.3\"\n```\n\nOr via the observability REST API:\n\n```bash\n# list PENDING (default)\ncurl http://localhost:9464/api/dead-letters\n\n# filter by state, paginate\ncurl \"http://localhost:9464/api/dead-letters?state=RESOLVED\u0026page=0\u0026size=10\"\n\n# replay\ncurl -X POST http://localhost:9464/api/dead-letters/\u003cid\u003e/replay\n\n# resolve\ncurl -X POST http://localhost:9464/api/dead-letters/\u003cid\u003e/resolve \\\n  -H \"content-type: application/json\" \\\n  -d '{\"reason\":\"investigated and closed\"}'\n```\n\n\u003e **Authentication**: DLQ endpoints will require a Bearer token once [#30](https://github.com/iamvirul/nexora/issues/30) lands.\n\n## Observability UI + Prometheus + Grafana\n\nStart Nexora's built-in observability server:\n\n```bash\njava -jar nexora-cli/target/nexora.jar observe --port 9464\n```\n\nThis exposes four endpoints with no external dependencies:\n\n| Endpoint | What it serves |\n|----------|---------------|\n| `GET /` | Live process UI showing active executions, step timelines, and plan amendments |\n| `GET /metrics` | Prometheus text format scrape endpoint |\n| `GET /api/process` | Raw process snapshot as JSON |\n| `POST /api/execute` | Trigger an execution remotely |\n| `GET /health/ready` | Check health of all capabilities (returns 503 if any circuit is OPEN/HALF_OPEN) |\n| `GET /api/webhook-deliveries/{id}` | Audit log of webhook delivery attempts for an execution |\n| `GET /api/dead-letters` | List dead letter queue entries (paginated, filterable by `?state=PENDING\\|RESOLVED\\|REPLAYED\\|ALL`) |\n| `POST /api/dead-letters/{id}/replay` | Create a new execution from a dead letter and mark it as `REPLAYED` |\n| `POST /api/dead-letters/{id}/resolve` | Mark a dead letter as `RESOLVED` with an optional `{\"reason\":\"...\"}` body |\n\n\u003e **Note**: The `/health/ready` endpoint is currently **Unreleased**.\n\nExample execute request:\n\n```bash\ncurl -X POST http://localhost:9464/api/execute \\\n  -H \"content-type: application/json\" \\\n  -d '{\"goal\":\"process order payment notification\",\"context\":{\"orderId\":\"ORD-99\"}}'\n```\n\nMetrics exposed include:\n\n- `nexora_plan_started_total`, `nexora_plan_completed_total`, `nexora_plan_failed_total`\n- `nexora_plan_duration_seconds` — histogram by status (completed/failed)\n- `nexora_step_started_total`, `nexora_step_completed_total`, `nexora_step_failed_total` — all by capability ID\n- `nexora_step_duration_seconds` — histogram by capability ID and terminal status\n- `nexora_plan_amendments_total` — by amendment type (ADD_STEP, SKIP_STEP, MODIFY_INPUT)\n- `nexora_active_executions` — current in-flight count\n\nBring up Prometheus, Grafana, and Alertmanager with the prebuilt stack:\n\n```bash\ncd observability\ndocker compose up -d\n```\n\n- Prometheus: `http://localhost:9090`\n- Alertmanager: `http://localhost:9093`\n- Grafana: `http://localhost:3000` (login: `admin` / `admin`)\n\nThe Grafana dashboard and alert rules are provisioned automatically. Provisioned assets:\n\n- `observability/prometheus/prometheus.yml`\n- `observability/prometheus/alerts.yml`\n- `observability/grafana/dashboards/nexora-overview.json`\n\nYou can also attach observability to an engine in your own application without the HTTP server:\n\n```java\nNexoraEngine engine = NexoraEngine.builder()...build();\n\ntry (NexoraObservability obs = NexoraObservability.attach(engine)) {\n    engine.execute(\"process order\", context).get();\n    String metrics = obs.scrapePrometheus();           // Prometheus text format\n    ProcessSnapshot snapshot = obs.processSnapshot();  // live execution state\n}\n```\n\n## Module layout\n\n```\nnexora-core           Domain types: Intent, Plan, Step, PlanAmendment, ExecutionContext\nnexora-plugin-spi     Plugin contract: NexoraPlugin, Capability, Planner, CapabilityRegistry\nnexora-registry       DefaultCapabilityRegistry (thread-safe, read-write locked)\nnexora-tracing        Tracer/Span interfaces + no-op implementation\nnexora-retry          RetryPolicy, ExponentialBackoffPolicy with jitter\nnexora-event          ExecutionEvent sealed hierarchy, InProcessEventBus\nnexora-executor       DAG scheduler with amendment support, interceptor pipeline, contract monitor\nnexora-plugin-loader  PluginClassLoader, PluginManager, lifecycle FSM\nnexora-planner        CompositePlanner, RulePlanner, StepDefinition, PlanRegistry\nnexora-runtime        ExecutionEngine (ties planner + scheduler together)\nnexora-api            NexoraEngine public facade, builder, NexoraObservability\nnexora-cli            PicoCLI command-line interface + ObserveCommand HTTP server\n```\n\nDependencies always point inward. `nexora-cli` knows about `nexora-api`. `nexora-api` knows about `nexora-runtime`. Neither knows anything about the CLI.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiamvirul%2Fnexora","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiamvirul%2Fnexora","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiamvirul%2Fnexora/lists"}