agentme 0.25.2 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/.filedist-package.yml +1 -1
  2. package/.xdrs/agentme/edrs/application/003-javascript-project-tooling.md +4 -4
  3. package/.xdrs/agentme/edrs/application/010-golang-project-tooling.md +4 -4
  4. package/.xdrs/agentme/edrs/application/014-python-project-tooling.md +10 -10
  5. package/.xdrs/agentme/edrs/application/018-ai-llm-development-standards.md +4 -2
  6. package/.xdrs/agentme/edrs/application/019-ai-agents-development-standards.md +8 -8
  7. package/.xdrs/agentme/edrs/application/020-ai-agents-quality-standards.md +3 -1
  8. package/.xdrs/agentme/edrs/application/021-ai-workflow-development-standards.md +9 -9
  9. package/.xdrs/agentme/edrs/application/025-ai-agent-xdrs-knowledge-layer.md +1 -1
  10. package/.xdrs/agentme/edrs/application/026-pragmatic-hexagonal-architecture.md +2 -2
  11. package/.xdrs/agentme/edrs/application/028-ai-eval-core-standards.md +120 -0
  12. package/.xdrs/agentme/edrs/application/029-ai-workflow-naming-conventions.md +1 -1
  13. package/.xdrs/agentme/edrs/application/030-ai-test-types-taxonomy.md +43 -25
  14. package/.xdrs/agentme/edrs/application/031-ai-eval-script.md +136 -0
  15. package/.xdrs/agentme/edrs/application/032-ai-eval-report-format.md +171 -0
  16. package/.xdrs/agentme/edrs/application/033-ai-eval-repeatability.md +75 -0
  17. package/.xdrs/agentme/edrs/devops/005-monorepo-structure.md +25 -25
  18. package/.xdrs/agentme/edrs/devops/006-github-pipelines.md +2 -2
  19. package/.xdrs/agentme/edrs/devops/008-common-targets.md +33 -33
  20. package/.xdrs/agentme/edrs/devops/017-tool-execution-and-scripting.md +1 -1
  21. package/.xdrs/agentme/edrs/devops/027-environment-variable-configuration.md +3 -3
  22. package/.xdrs/agentme/edrs/governance/013-contributing-guide-requirements.md +35 -9
  23. package/.xdrs/agentme/edrs/index.md +20 -5
  24. package/.xdrs/agentme/edrs/observability/011-service-health-check-endpoint.md +1 -1
  25. package/.xdrs/agentme/edrs/principles/004-unit-test-requirements.md +6 -4
  26. package/.xdrs/agentme/edrs/principles/007-project-quality-standards.md +35 -30
  27. package/.xdrs/agentme/edrs/principles/009-error-handling.md +1 -1
  28. package/.xdrs/agentme/edrs/principles/012-continuous-xdr-enrichment.md +27 -9
  29. package/.xdrs/agentme/edrs/principles/016-cross-language-module-structure.md +1 -1
  30. package/.xdrs/agentme/edrs/principles/022-secrets-management.md +26 -24
  31. package/.xdrs/agentme/edrs/principles/023-coding-abstraction-practices.md +1 -1
  32. package/package.json +1 -1
  33. package/.xdrs/agentme/edrs/application/028-ai-eval-standards.md +0 -257
@@ -1,257 +0,0 @@
1
- ---
2
- name: agentme-edr-policy-028-ai-eval-standards
3
- description: Defines how to structure, write, and run eval tests for AI projects — folder layout, golden dataset, --type test-type filtering, mock_fixtures wiring, entry-first eval loop, per-type Makefile targets and reports, and MLflow tracking. Use when implementing evals for LLM, Agent, or Workflow projects. For when evals are required see agentme-edr-007 rule 09-ai-project-testing-requirements. For the test type taxonomy and mock_fixtures envelope see agentme-edr-030. For mock file naming see agentme-edr-026 rule 10.
4
- apply-to: Python AI projects (LLM, Agent, or Workflow tier) that implement eval testing
5
- valid-from: 2026-06-05
6
- ---
7
-
8
- # agentme-edr-policy-028: AI eval standards
9
-
10
- ## Context and Problem Statement
11
-
12
- Eval tests measure AI component accuracy against expected outputs using real LLM providers. Without a shared folder layout and script convention, eval setups diverge across LLM, Agent, and Workflow projects, making them hard to run, compare, and integrate into CI/CD pipelines.
13
-
14
- How should eval tests be structured and run across all AI tiers?
15
-
16
- ## Decision Outcome
17
-
18
- **Use a per-component folder structure under `evals/` with a standardized Makefile interface and MLflow-backed scripts, applicable to LLM, Agent, and Workflow components.**
19
-
20
- For when evals are required per AI tier, see [agentme-edr-007](../principles/007-project-quality-standards.md) rule `09-ai-project-testing-requirements`.
21
-
22
- ### Details
23
-
24
- #### 01-eval-folder-structure
25
-
26
- Evals are grouped first by the component being evaluated, then by the specific evaluation scenario. Create one directory per component under `evals/`, and one directory per eval scenario inside it. Place `evals/` at the same level as `lib/` and `examples/`:
27
-
28
- ```text
29
- evals/
30
- <component>/ # the component being evaluated (e.g., workflow-x, agent-y, model-z)
31
- eval-<name>/
32
- golden_dataset/ # EDR-024 + EDR-030 compliant golden dataset (README.md, dataset.schema.json, data/)
33
- eval.py # evaluation script
34
- report-<type>.md # generated report, one per evaluated test type (overwritten on each run — see rule 03)
35
- Makefile # lint, eval, run, and eval-<type> targets
36
- eval-<name2>/
37
- ...
38
- <component2>/
39
- ...
40
- ```
41
-
42
- `<component>` MUST match the name of the component under evaluation and use lowercase hyphen-separated words (e.g., `workflow-document-review`, `agent-support`, `model-classifier`).
43
-
44
- `<name>` identifies the specific evaluation scenario using lowercase hyphen-separated words (e.g., `eval-basic`, `eval-complex`, `eval-edge-cases`). A scenario's `golden_dataset` MAY mix multiple test types across its entries: label each entry with its applicable `test_types` ([agentme-edr-030](030-ai-test-types-taxonomy.md) rule `04`) and use the `eval-<type>` targets below to run one type at a time.
45
-
46
- The `golden_dataset/` subfolder MUST be a valid [agentme-edr-024](024-ml-dataset-structure.md) dataset (`README.md`, `dataset.schema.json`, one JSON file per entry under `data/` per rule `04-complex-structured-datasets-must-use-per-entry-json-files`, lint-validated per rule `06`) whose entries follow the golden dataset envelope defined in [agentme-edr-030](030-ai-test-types-taxonomy.md) rule `02`.
47
-
48
- Each `evals/<component>/eval-<name>/Makefile` MUST declare a `TEST_TYPES` variable listing the `test_types` values present in its golden dataset, and define:
49
-
50
- | Target | Behaviour |
51
- |---|---|
52
- | `lint` | Validates every `golden_dataset/data/*.json` file against `golden_dataset/dataset.schema.json` per [agentme-edr-024](024-ml-dataset-structure.md) rule `06` |
53
- | `eval` | Depends on `lint`; runs `eval.py --type=all` with threshold enforcement; exits non-zero on failure (CI-safe) |
54
- | `run` | Depends on `lint`; runs `eval.py --type=all` without threshold enforcement (exploration / debugging) |
55
- | `eval-<type>` | Depends on `lint`; runs `eval.py --type=<type>` for one declared test type, following [agentme-edr-008](../devops/008-common-targets.md) rule `03`'s `eval-<qualifier>` convention |
56
-
57
- ```makefile
58
- TEST_TYPES := smoke functional safety
59
-
60
- lint:
61
- mise exec -- uv run --project . python lint_dataset.py golden_dataset/
62
-
63
- eval: lint
64
- mise exec -- uv run --project . python eval.py --type=all
65
-
66
- run: lint
67
- mise exec -- uv run --project . python eval.py --type=all --no-threshold
68
-
69
- eval-%: lint
70
- mise exec -- uv run --project . python eval.py --type=$*
71
- ```
72
-
73
- The module root Makefile MUST expose `make eval` and `make lint` targets that delegate to `eval` and `lint` respectively in every `evals/<component>/eval-<name>/Makefile`:
74
-
75
- ```makefile
76
- eval:
77
- $(MAKE) -C evals/workflow-document-review/eval-basic eval
78
- $(MAKE) -C evals/workflow-document-review/eval-complex eval
79
-
80
- lint:
81
- $(MAKE) -C evals/workflow-document-review/eval-basic lint
82
- $(MAKE) -C evals/workflow-document-review/eval-complex lint
83
- ```
84
-
85
- #### 02-eval-script-requirements
86
-
87
- Each `eval.py` script MUST:
88
-
89
- - Load the golden dataset from `golden_dataset/` in the same eval folder, following [agentme-edr-024](024-ml-dataset-structure.md) and the entry envelope in [agentme-edr-030](030-ai-test-types-taxonomy.md) rule `02` (one JSON file per entry, `test_types` array, `input`, `expected_output`, optional `mock_fixtures`).
90
- - Accept a required `--type=<test_type>|all` CLI argument and filter entries whose `test_types` array contains the requested value; `--type=all` includes every entry.
91
- - Iterate **entry-first**: for each entry in the filtered set, invoke the real component exactly once; then score that single `actual_output` for every `test_types` value the entry carries that falls within the current `--type` scope — never invoke the component more than once per entry per run.
92
- - When an entry contains `mock_fixtures` ([agentme-edr-030](030-ai-test-types-taxonomy.md) rule `02`), configure each named mock adapter with its fixture data BEFORE invoking the component for that entry. Each entry MUST use fresh mock instances so fixture state does not bleed across entries. `mock_fixtures` applies to all test types including `human`. `mock_fixtures` MUST NOT configure LLM adapters — the LLM call MUST always be real (see [agentme-edr-030](030-ai-test-types-taxonomy.md) rule `03`). How mock adapters are discovered and instantiated is left to the project; see [agentme-edr-026](026-pragmatic-hexagonal-architecture.md) rule `10` for the `_mock` file naming and placement convention.
93
- - Run every component invocation against **real LLM providers** (not mocked responses), to capture model drift.
94
- - For `human` entries: invoke the component to capture `actual_output`, export each entry's `input`, `expected_output.human_test` instructions, and `actual_output` into a manual-review checklist (`report-human.md`). MUST NOT invoke an automated scorer and MUST NOT enforce a pass/fail threshold for it. Other `test_types` on the same entry (e.g. `functional`) are still scored automatically.
95
- - After all entries are processed, compute aggregate metrics per test type, log them to a local MLflow experiment (see rule `04`), write one `report-<type>.md` per evaluated test type (rule `03`), and exit with a non-zero status when any metric falls below its defined threshold per [agentme-edr-007](../principles/007-project-quality-standards.md) rule `07-statistical-models-must-have-eval-targets`. The `human` type has no threshold and does not trigger a non-zero exit.
96
- - Compare outputs to expected values using project-defined quality thresholds per test type. Thresholds MUST be declared explicitly (e.g., in a Makefile variable or README) — this Policy does not mandate which test types a project must threshold or what value to use (see [agentme-edr-030](030-ai-test-types-taxonomy.md) rule `06`).
97
-
98
- **Example:**
99
-
100
- ```python
101
- import argparse
102
- from collections import defaultdict
103
- import mlflow
104
- from my_package.app.workflows.document_review_workflow.graph import graph
105
-
106
- EVAL_MIN_ACCURACY = {"functional": 0.85, "smoke": 0.85}
107
-
108
- parser = argparse.ArgumentParser()
109
- parser.add_argument("--type", required=True)
110
- args = parser.parse_args()
111
-
112
- entries = load_golden_dataset("golden_dataset/", test_type=args.type) # "all" loads every entry
113
- resolved_types = resolve_types(args.type, entries)
114
-
115
- mlflow.set_experiment("document-review/eval-basic")
116
-
117
- with mlflow.start_run():
118
- mlflow.set_tag("test_types", ",".join(sorted(resolved_types)))
119
-
120
- results = defaultdict(list)
121
-
122
- # Entry-first loop: invoke each entry exactly once
123
- for entry in entries:
124
- # Configure mock adapters from mock_fixtures before invocation
125
- # (implementation left to the project — see agentme-edr-026 rule 10)
126
- if entry.get("mock_fixtures"):
127
- configure_mocks(entry["mock_fixtures"]) # project-defined helper
128
-
129
- actual_output = invoke_component(entry, graph)
130
-
131
- for test_type in [t for t in entry["test_types"] if t in resolved_types]:
132
- if test_type == "human":
133
- export_human_review(entry, actual_output)
134
- continue
135
- results[test_type].append(score(test_type, actual_output, entry["expected_output"]))
136
-
137
- # Aggregate, report, and enforce thresholds per test type
138
- for test_type in resolved_types:
139
- if test_type == "human":
140
- continue
141
-
142
- accuracy = sum(results[test_type]) / len(results[test_type])
143
- mlflow.log_metric(f"{test_type}_accuracy", accuracy)
144
- write_eval_report(test_type, results[test_type], thresholds={"accuracy": EVAL_MIN_ACCURACY[test_type]})
145
-
146
- if accuracy < EVAL_MIN_ACCURACY[test_type]:
147
- raise SystemExit(f"Eval failed: {test_type} accuracy {accuracy:.2f} < {EVAL_MIN_ACCURACY[test_type]}")
148
- ```
149
-
150
- #### 03-eval-report-file
151
-
152
- Each eval script MUST produce one `report-<type>.md` per evaluated test type in the same `evals/<component>/eval-<name>/` folder and overwrite each on every run — only the types included in the current `--type` invocation are (re)written; report files for other types are left untouched. The `human` type does not produce a metrics report (see below).
153
-
154
- **Generation constraint:** The report MUST be produced programmatically, reading raw metric values directly from MLflow. No LLM or generative model may write, summarize, or paraphrase any section of the report, to prevent hallucinated metric values.
155
-
156
- The report MUST follow this template:
157
-
158
- ```markdown
159
- # Eval Report: <name> — <type>
160
-
161
- **Date:** <ISO date>
162
- **Dataset:** golden_dataset/
163
- **Script:** eval.py --type=<type>
164
- **Thresholds:** accuracy ≥ <value>, F1 ≥ <value>
165
-
166
- ## Overall Results
167
-
168
- | Metric | Value | 95% CI | Threshold | Status |
169
- |-----------|--------|----------------|-----------|---------|
170
- | Accuracy | <val> | [<low>, <high>]| ≥ <thr> | ✓/✗ PASS/FAIL |
171
- | F1 Score | <val> | — | ≥ <thr> | ✓/✗ PASS/FAIL |
172
- | Precision | <val> | — | — | — |
173
- | Recall | <val> | — | — | — |
174
- | Samples | <n> | — | — | — |
175
-
176
- **Overall: PASS / FAIL**
177
-
178
- ## Per-item Results
179
-
180
- | ID | Input Summary | Expected | Actual | Correct |
181
- |-----|---------------|----------|--------|---------|
182
- | 001 | <summary> | <label> | <label>| ✓ |
183
- | 002 | <summary> | <label> | <label>| ✗ |
184
-
185
- ## Notes
186
-
187
- - <observations, failure patterns, MLflow run link>
188
- ```
189
-
190
- **Confidence interval:** The 95% CI for accuracy MUST be computed using the **Wilson score interval** (preferred over the normal approximation for small $n$). A wide interval signals that the dataset is too small to support confident conclusions and the sample count should be increased.
191
-
192
- The Wilson score bounds at 95% confidence ($z = 1.96$) are:
193
-
194
- $$\frac{\hat{p} + \frac{z^2}{2n} \pm z\sqrt{\frac{\hat{p}(1-\hat{p})}{n} + \frac{z^2}{4n^2}}}{1 + \frac{z^2}{n}}$$
195
-
196
- Where $\hat{p}$ is observed accuracy and $n$ is sample count. Accuracy and F1 are required; precision and recall are recommended.
197
-
198
- **Filled-in example** (`evals/workflow-document-review/eval-basic/report-functional.md` for a document review workflow):
199
-
200
- ```markdown
201
- # Eval Report: eval-basic — functional
202
-
203
- **Date:** 2026-06-12
204
- **Dataset:** golden_dataset/
205
- **Script:** eval.py --type=functional
206
- **Thresholds:** accuracy ≥ 0.85, F1 ≥ 0.80
207
-
208
- ## Overall Results
209
-
210
- | Metric | Value | 95% CI | Threshold | Status |
211
- |-----------|-------|--------------|-----------|-------------|
212
- | Accuracy | 0.88 | [0.69, 0.97] | ≥ 0.85 | ✓ PASS |
213
- | F1 Score | 0.86 | — | ≥ 0.80 | ✓ PASS |
214
- | Precision | 0.89 | — | — | — |
215
- | Recall | 0.84 | — | — | — |
216
- | Samples | 25 | — | — | — |
217
-
218
- **Overall: PASS**
219
-
220
- > Note: CI [0.69, 0.97] is wide — 25 samples may be insufficient for high confidence. Consider expanding the dataset.
221
-
222
- ## Per-item Results
223
-
224
- | ID | Input Summary | Expected | Actual | Correct |
225
- |-----|--------------------------------------|----------|----------|---------|
226
- | 001 | Contract renewal, 3 pages, standard | approve | approve | ✓ |
227
- | 002 | NDA with unusual liability clause | escalate | escalate | ✓ |
228
- | 003 | Vendor invoice, missing PO number | reject | reject | ✓ |
229
- | 004 | Employment agreement, standard terms| approve | approve | ✓ |
230
- | 005 | Amendment with redlined IP clause | escalate | approve | ✗ |
231
-
232
- ## Notes
233
-
234
- - Sample 005 misclassified: redlined IP clause not flagged as escalation trigger. Possible model drift.
235
- - MLflow run: experiment `workflow-document-review/eval-basic`, tag `test_types=functional` — view with `mlflow ui`
236
- ```
237
-
238
- **`human` type artifact:** instead of `report-human.md` with metrics, `--type=human` produces a checklist artifact (still named `report-human.md`) listing, per entry, its `input`, `expected_output.human_test` instructions, and the captured `actual_output` — with no Overall Results table, threshold, or PASS/FAIL section, since this type is never auto-scored.
239
-
240
- #### 04-eval-mlflow-unique-port
241
-
242
- Each `evals/<component>/eval-<name>/Makefile` MUST start its MLflow tracking server on a **unique port** to prevent conflicts when multiple eval Makefiles are run concurrently or in parallel (e.g., in CI or across multiple terminal sessions).
243
-
244
- Ports MUST be statically assigned per eval scenario (not per test type) and MUST NOT reuse the default `5000` port (reserved for `dev-mlflow` per [agentme-edr-008](../devops/008-common-targets.md) rule `09-ai-project-dev-targets`). Assign ports starting at `5100` and incrementing by 1 for each additional eval scenario across the entire project.
245
-
246
- The MLflow **experiment** is scoped to the eval scenario: `<component>/<eval-name>` (e.g. `document-review/eval-basic`). Each `mlflow.start_run()` call MUST set a `test_types` tag listing the test types evaluated in that invocation (comma-separated, e.g. `"functional,smoke"` for `--type=all`, `"smoke"` for `--type=smoke`). A remote MLflow server MUST NOT be required — all tracking is local.
247
-
248
- ## References
249
-
250
- - [agentme-edr-007](../principles/007-project-quality-standards.md) — Project quality standards: when evals are required per AI tier (rule `09-ai-project-testing-requirements`) and statistical model eval targets (rule `07-statistical-models-must-have-eval-targets`)
251
- - [agentme-edr-030](030-ai-test-types-taxonomy.md) — AI test types taxonomy: `test_types` enum, golden dataset entry envelope (including `mock_fixtures`), and mocking constraints per type
252
- - [agentme-edr-026](026-pragmatic-hexagonal-architecture.md) — Rule `10`: `_mock` file naming and placement convention for mock adapters used in `mock_fixtures`
253
- - [agentme-edr-018](018-ai-llm-development-standards.md) — LLM development standards: LangChain framework and observability
254
- - [agentme-edr-019](019-ai-agents-development-standards.md) — Agent development standards
255
- - [agentme-edr-021](021-ai-workflow-development-standards.md) — Workflow development standards
256
- - [agentme-edr-024](024-ml-dataset-structure.md) — ML dataset structure, per-entry JSON format, and schema-lint validation for golden datasets
257
- - [agentme-edr-008](../devops/008-common-targets.md) — `eval-<qualifier>` Makefile convention (rule `03`) and Mise tool-execution flow (rule `02`)