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
@@ -0,0 +1,136 @@
1
+ ---
2
+ name: agentme-edr-policy-031-ai-eval-script
3
+ description: Defines eval.py script requirements for AI projects — entry-first eval loop, --type test-type filtering, mock_fixtures wiring, human entries, threshold enforcement, and MLflow experiment naming and port assignment. Use when implementing eval scripts. For eval folder structure see agentme-edr-028 rule 01. For the test type taxonomy and mock_fixtures envelope see agentme-edr-030. For mock file naming see agentme-edr-026 rule 10. For report format see agentme-edr-032. For repeatability loop exception see agentme-edr-033.
4
+ apply-to: Python AI projects (LLM, Agent, or Workflow tier) that implement eval testing
5
+ valid-from: 2026-07-07
6
+ ---
7
+
8
+ # agentme-edr-policy-031: AI eval script
9
+
10
+ ## Context and Problem Statement
11
+
12
+ Eval scripts execute entries from a golden dataset against a real AI component and measure output quality. Without a shared script contract, eval implementations diverge: some invoke components multiple times per entry (wasting LLM cost), some skip mock isolation, and some omit threshold enforcement — making results inconsistent and hard to trust across projects.
13
+
14
+ How should eval scripts load datasets, iterate entries, handle mocking, and produce metrics?
15
+
16
+ ## Decision Outcome
17
+
18
+ **Use an entry-first eval loop with `--type` filtering, fresh mock isolation per entry, real LLM providers, and MLflow-backed metrics with explicit per-type thresholds.**
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-script-requirements
25
+
26
+ Each `eval.py` script MUST:
27
+
28
+ - 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`).
29
+ - 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.
30
+ - 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 — MUST NOT invoke the component more than once per entry per run.
31
+ - 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 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.
32
+ - Run every component invocation against **real LLM providers** (not mocked responses), to capture model drift.
33
+ - 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.
34
+ - After all entries are processed, compute aggregate metrics per test type, log them to a local MLflow experiment (see rule `02`), write one `report-<type>.md` per evaluated test type ([agentme-edr-032](032-ai-eval-report-format.md) rule `01`), 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.
35
+ - Compare outputs to expected values using project-defined quality thresholds per test type. Thresholds and all other scoring parameters MUST be declared as constants in `eval.py` — they are design decisions about what constitutes acceptable quality for the component under test, not runtime configuration, and MUST NOT be passed via Makefile variables or CLI flags. Use one of two naming conventions, chosen consistently within an `eval.py`: (a) **per-type constants** — `EVAL_MIN_<METRIC>_<TYPE>` for each test type (e.g. `EVAL_MIN_ACCURACY_FUNCTIONAL = 0.85`, `EVAL_MIN_ACCURACY_REPEATABILITY = 0.8`); or (b) **dict constant** — `EVAL_MIN_<METRIC> = {<type>: <value>}` (e.g. `EVAL_MIN_ACCURACY = {"functional": 0.85, "smoke": 0.85}`). Per-type constants are preferred when each test type has a dedicated `eval.py`; the dict form is preferred when a single `eval.py` handles multiple types. In either convention, `EVAL_MIN_ACCURACY` (as a scalar) MAY be declared as a project-wide default and MUST be used as fallback when no per-type override is defined for the current test type. 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`).
36
+
37
+ **Example:**
38
+
39
+ ```python
40
+ import argparse
41
+ from collections import defaultdict
42
+ import mlflow
43
+ from my_package.app.workflows.document_review_workflow.graph import graph
44
+
45
+ # Per-type constants; fall back to EVAL_MIN_ACCURACY default when no override is defined
46
+ EVAL_MIN_ACCURACY = 0.85 # project-wide default
47
+ EVAL_MIN_ACCURACY_FUNCTIONAL = 0.85
48
+ EVAL_MIN_ACCURACY_SMOKE = 0.90
49
+ EVAL_MIN_ACCURACY_PER_TYPE = {"functional": EVAL_MIN_ACCURACY_FUNCTIONAL, "smoke": EVAL_MIN_ACCURACY_SMOKE}
50
+
51
+ def get_min_accuracy(test_type: str) -> float:
52
+ return EVAL_MIN_ACCURACY_PER_TYPE.get(test_type, EVAL_MIN_ACCURACY)
53
+
54
+ parser = argparse.ArgumentParser()
55
+ parser.add_argument("--type", required=True)
56
+ args = parser.parse_args()
57
+
58
+ entries = load_golden_dataset("golden_dataset/", test_type=args.type) # "all" loads every entry
59
+ resolved_types = resolve_types(args.type, entries)
60
+
61
+ mlflow.set_experiment("document-review/eval-basic")
62
+
63
+ with mlflow.start_run():
64
+ mlflow.set_tag("test_types", ",".join(sorted(resolved_types)))
65
+
66
+ results = defaultdict(list)
67
+ cumulative_metrics = defaultdict(lambda: {"accuracy": [], "f1": []}) # Track cumulative metrics
68
+
69
+ # Entry-first loop: invoke each entry exactly once
70
+ for idx, entry in enumerate(entries, start=1):
71
+ # Configure mock adapters from mock_fixtures before invocation
72
+ # (implementation left to the project — see agentme-edr-026 rule 10)
73
+ if entry.get("mock_fixtures"):
74
+ configure_mocks(entry["mock_fixtures"]) # project-defined helper
75
+
76
+ actual_output = invoke_component(entry, graph)
77
+
78
+ for test_type in [t for t in entry["test_types"] if t in resolved_types]:
79
+ if test_type == "human":
80
+ export_human_review(entry, actual_output)
81
+ continue
82
+
83
+ score_val = score(test_type, actual_output, entry["expected_output"])
84
+ results[test_type].append(score_val)
85
+
86
+ # Track cumulative metrics for convergence analysis
87
+ cumulative_accuracy = sum(results[test_type]) / len(results[test_type])
88
+ cumulative_f1 = compute_f1(results[test_type]) # project-defined
89
+ cumulative_metrics[test_type]["accuracy"].append(cumulative_accuracy)
90
+ cumulative_metrics[test_type]["f1"].append(cumulative_f1)
91
+
92
+ # Aggregate, report, and enforce thresholds per test type
93
+ for test_type in resolved_types:
94
+ if test_type == "human":
95
+ continue
96
+
97
+ accuracy = sum(results[test_type]) / len(results[test_type])
98
+ mlflow.log_metric(f"{test_type}_accuracy", accuracy)
99
+
100
+ # Generate convergence analysis
101
+ stability_window = min(10, len(results[test_type]))
102
+ acc_change = abs(cumulative_metrics[test_type]["accuracy"][-1] -
103
+ cumulative_metrics[test_type]["accuracy"][-stability_window])
104
+ f1_change = abs(cumulative_metrics[test_type]["f1"][-1] -
105
+ cumulative_metrics[test_type]["f1"][-stability_window])
106
+
107
+ write_eval_report(
108
+ test_type,
109
+ results[test_type],
110
+ cumulative_metrics=cumulative_metrics[test_type],
111
+ stability_window=stability_window,
112
+ thresholds={"accuracy": get_min_accuracy(test_type)}
113
+ )
114
+
115
+ if accuracy < get_min_accuracy(test_type):
116
+ raise SystemExit(f"Eval failed: {test_type} accuracy {accuracy:.2f} < {get_min_accuracy(test_type)}")
117
+ ```
118
+
119
+ #### 02-eval-mlflow-unique-port
120
+
121
+ 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).
122
+
123
+ 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.
124
+
125
+ 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.
126
+
127
+ ## References
128
+
129
+ - [agentme-edr-028](028-ai-eval-core-standards.md) — AI eval core standards: eval folder structure (rule `01`) and LLM-as-judge binary scoring contract (rule `02`)
130
+ - [agentme-edr-032](032-ai-eval-report-format.md) — AI eval report format: `report-<type>.md` template, Wilson CI, and convergence analysis
131
+ - [agentme-edr-033](033-ai-eval-repeatability.md) — AI eval repeatability: loop exception to rule `01`'s entry-first constraint, scoring methods, and cadence
132
+ - [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
133
+ - [agentme-edr-026](026-pragmatic-hexagonal-architecture.md) — Rule `10`: `_mock` file naming and placement convention for mock adapters used in `mock_fixtures`
134
+ - [agentme-edr-024](024-ml-dataset-structure.md) — ML dataset structure, per-entry JSON format, and schema-lint validation for golden datasets
135
+ - [agentme-edr-007](../principles/007-project-quality-standards.md) — Project quality standards: when evals are required per AI tier (rule `09`) and statistical model eval targets (rule `07`)
136
+ - [agentme-edr-008](../devops/008-common-targets.md) — `eval-<qualifier>` Makefile convention (rule `03`) and reserved MLflow port `5000` (rule `09`)
@@ -0,0 +1,171 @@
1
+ ---
2
+ name: agentme-edr-policy-032-ai-eval-report-format
3
+ description: Defines the eval report format for AI projects — report-<type>.md template, Wilson score confidence interval, convergence analysis, and the human-type checklist artifact. Use when generating eval reports from eval scripts. For the eval script that produces these reports see agentme-edr-031. For repeatability report shape see agentme-edr-033 rule 02.
4
+ apply-to: Python AI projects (LLM, Agent, or Workflow tier) that implement eval testing
5
+ valid-from: 2026-07-07
6
+ ---
7
+
8
+ # agentme-edr-policy-032: AI eval report format
9
+
10
+ ## Context and Problem Statement
11
+
12
+ Eval scripts produce output reports, but without a shared format these vary across projects: some omit confidence intervals, some skip convergence analysis, and some allow LLMs to write sections — making reports unreliable and non-comparable.
13
+
14
+ What format should eval reports follow, and what constraints apply to how they are generated?
15
+
16
+ ## Decision Outcome
17
+
18
+ **Use a standardized `report-<type>.md` template with a Wilson score confidence interval, a Mermaid convergence chart, and a strict no-LLM generation constraint for all metric values.**
19
+
20
+ ### Details
21
+
22
+ #### 01-eval-report-file
23
+
24
+ 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).
25
+
26
+ **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. This constraint applies to all report sections including Overall Results, Convergence Analysis, and Per-item Results — all metric values and convergence chart data points MUST be computed from actual evaluation results.
27
+
28
+ The report MUST follow this template:
29
+
30
+ ```markdown
31
+ # Eval Report: <name> — <type>
32
+
33
+ **Date:** <ISO date>
34
+ **Dataset:** golden_dataset/
35
+ **Script:** eval.py --type=<type>
36
+ **Thresholds:** accuracy ≥ <value>, F1 ≥ <value>
37
+
38
+ ## Overall Results
39
+
40
+ | Metric | Value | 95% CI | Threshold | Status |
41
+ |-----------|--------|----------------|-----------|---------|
42
+ | Accuracy | <val> | [<low>, <high>]| ≥ <thr> | ✓/✗ PASS/FAIL |
43
+ | F1 Score | <val> | — | ≥ <thr> | ✓/✗ PASS/FAIL |
44
+ | Precision | <val> | — | — | — |
45
+ | Recall | <val> | — | — | — |
46
+ | Samples | <n> | — | — | — |
47
+
48
+ **Overall: PASS / FAIL**
49
+
50
+ ## Convergence Analysis
51
+
52
+ ```mermaid
53
+ xychart-beta
54
+ title "Metric Evolution vs Sample Count"
55
+ x-axis "Samples" [<sample_points>]
56
+ y-axis "Score" 0.0 --> 1.0
57
+ line "Accuracy" [<accuracy_values>]
58
+ line "F1 Score" [<f1_values>]
59
+ ```
60
+
61
+ **Stability Analysis:**
62
+ - Accuracy change over last <window> samples: <change> percentage points
63
+ - F1 change over last <window> samples: <change> percentage points
64
+
65
+ **Recommendation:** <"Dataset appears sufficient for confident evaluation" | "Add more samples — metrics have not yet stabilized">
66
+
67
+ ## Per-item Results
68
+
69
+ | ID | Input Summary | Expected | Actual | Correct |
70
+ |-----|---------------|----------|--------|---------|
71
+ | 001 | <summary> | <label> | <label>| ✓ |
72
+ | 002 | <summary> | <label> | <label>| ✗ |
73
+
74
+ ## Notes
75
+
76
+ - <observations, failure patterns, MLflow run link>
77
+ ```
78
+
79
+ **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.
80
+
81
+ The Wilson score bounds at 95% confidence ($z = 1.96$) are:
82
+
83
+ $$\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}}$$
84
+
85
+ Where $\hat{p}$ is observed accuracy and $n$ is sample count. Accuracy and F1 are required; precision and recall are recommended.
86
+
87
+ **Convergence analysis:** The Convergence Analysis section shows whether adding more samples would likely change measured metrics. The section MUST include:
88
+
89
+ 1. **Mermaid xychart-beta** showing cumulative Accuracy and F1 evolution:
90
+ - X-axis: absolute cumulative sample count; Y-axis: metric value (0.0 to 1.0)
91
+ - Two lines: Accuracy and F1
92
+ - For datasets > 50 samples: sample at `floor(dataset_size / 10)` intervals (minimum 5), always include first and last points
93
+ - For datasets ≤ 50 samples: show all points
94
+
95
+ 2. **Stability analysis**: compute absolute change (percentage points) for both Accuracy and F1 over last `min(10, dataset_size)` samples. Example: Accuracy from 0.85 to 0.87 = 0.02 = 2 percentage points.
96
+
97
+ 3. **Recommendation**:
98
+ - Default threshold: both Accuracy AND F1 change ≤ 2 percentage points
99
+ - If both meet threshold: "Dataset appears sufficient for confident evaluation"
100
+ - If either exceeds: "Add more samples — metrics have not yet stabilized"
101
+ - Projects MAY customize threshold (document in Makefile/README)
102
+
103
+ Exclude from `report-human.md` (no automated metrics).
104
+
105
+ **Filled-in example** (`evals/workflow-document-review/eval-basic/report-functional.md` for a document review workflow):
106
+
107
+ ```markdown
108
+ # Eval Report: eval-basic — functional
109
+
110
+ **Date:** 2026-06-12
111
+ **Dataset:** golden_dataset/
112
+ **Script:** eval.py --type=functional
113
+ **Thresholds:** accuracy ≥ 0.85, F1 ≥ 0.80
114
+
115
+ ## Overall Results
116
+
117
+ | Metric | Value | 95% CI | Threshold | Status |
118
+ |-----------|-------|--------------|-----------|-------------|
119
+ | Accuracy | 0.88 | [0.69, 0.97] | ≥ 0.85 | ✓ PASS |
120
+ | F1 Score | 0.86 | — | ≥ 0.80 | ✓ PASS |
121
+ | Precision | 0.89 | — | — | — |
122
+ | Recall | 0.84 | — | — | — |
123
+ | Samples | 25 | — | — | — |
124
+
125
+ **Overall: PASS**
126
+
127
+ > Note: CI [0.69, 0.97] is wide — 25 samples may be insufficient for high confidence. Consider expanding the dataset.
128
+
129
+ ## Convergence Analysis
130
+
131
+ ```mermaid
132
+ xychart-beta
133
+ title "Metric Evolution vs Sample Count"
134
+ x-axis "Samples" [1, 5, 10, 15, 20, 25]
135
+ y-axis "Score" 0.0 --> 1.0
136
+ line "Accuracy" [0.60, 0.80, 0.85, 0.87, 0.88, 0.88]
137
+ line "F1 Score" [0.55, 0.78, 0.83, 0.85, 0.86, 0.86]
138
+ ```
139
+
140
+ **Stability Analysis:**
141
+ - Accuracy change over last 10 samples: 0.01 percentage points
142
+ - F1 change over last 10 samples: 0.01 percentage points
143
+
144
+ **Recommendation:** Dataset appears sufficient for confident evaluation
145
+
146
+ > Metrics stabilized after ~15 samples. Changes over last 10 samples are well below the 2 percentage point threshold.
147
+
148
+ ## Per-item Results
149
+
150
+ | ID | Input Summary | Expected | Actual | Correct |
151
+ |-----|--------------------------------------|----------|----------|---------|
152
+ | 001 | Contract renewal, 3 pages, standard | approve | approve | ✓ |
153
+ | 002 | NDA with unusual liability clause | escalate | escalate | ✓ |
154
+ | 003 | Vendor invoice, missing PO number | reject | reject | ✓ |
155
+ | 004 | Employment agreement, standard terms| approve | approve | ✓ |
156
+ | 005 | Amendment with redlined IP clause | escalate | approve | ✗ |
157
+
158
+ ## Notes
159
+
160
+ - Sample 005 misclassified: redlined IP clause not flagged as escalation trigger. Possible model drift.
161
+ - MLflow run: experiment `workflow-document-review/eval-basic`, tag `test_types=functional` — view with `mlflow ui`
162
+ ```
163
+ ```
164
+
165
+ **`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 MUST NOT be auto-scored.
166
+
167
+ ## References
168
+
169
+ - [agentme-edr-031](031-ai-eval-script.md) — AI eval script: the script that produces these reports (rule `01`)
170
+ - [agentme-edr-033](033-ai-eval-repeatability.md) — AI eval repeatability: rule `02` defines the adapted report shape for `report-repeatability.md`
171
+ - [agentme-edr-028](028-ai-eval-core-standards.md) — AI eval core standards: folder structure (rule `01`) and LLM-as-judge binary scoring (rule `02`)
@@ -0,0 +1,75 @@
1
+ ---
2
+ name: agentme-edr-policy-033-ai-eval-repeatability
3
+ description: Defines the repeatability test type for AI evals — REPEAT_COUNT loop exception to the entry-first constraint, semantic-similarity and LLM-as-judge scoring methods, repeatability_accuracy metric, and the repeatability report format and run cadence. Use when implementing repeatability evals. For the entry-first constraint see agentme-edr-031 rule 01. For LLM-as-judge binary output see agentme-edr-028 rule 02. For the base report template see agentme-edr-032 rule 01. For the repeatability test type definition see agentme-edr-030.
4
+ apply-to: Python AI projects (LLM, Agent, or Workflow tier) that implement repeatability eval testing
5
+ valid-from: 2026-07-07
6
+ ---
7
+
8
+ # agentme-edr-policy-033: AI eval repeatability
9
+
10
+ ## Context and Problem Statement
11
+
12
+ Some AI components must be tested for output consistency across multiple invocations with the same input — a property the standard entry-first eval loop cannot capture because it invokes each entry only once. Without a shared repeatability protocol, teams either skip this test or implement ad-hoc variations that produce incomparable results.
13
+
14
+ How should repeatability be measured in evals, and how should its results be reported?
15
+
16
+ ## Decision Outcome
17
+
18
+ **Exempt `repeatability` entries from the entry-first constraint, invoking each `REPEAT_COUNT` times and scoring via semantic-similarity or LLM-as-judge; schedule at release cadence rather than per-commit.**
19
+
20
+ For the `repeatability` test type definition and its disambiguation from `reproducibility`, see [agentme-edr-030](030-ai-test-types-taxonomy.md) rule `09`.
21
+
22
+ ### Details
23
+
24
+ #### 01-repeatability-eval-loop-exception
25
+
26
+ Entries whose `test_types` includes `repeatability` are exempt from [agentme-edr-031](031-ai-eval-script.md) rule `01`'s "invoke exactly once per entry" constraint. The following constants MUST be declared in `eval.py` and MUST NOT be exposed as Makefile variables, CLI flags, or stored as per-entry dataset fields:
27
+
28
+ - `REPEAT_COUNT` — number of times each repeatability entry is invoked. SHOULD default to 3-5 for routine CI runs and 10-20 for focused passes on decision-critical or previously-flagged components. Projects SHOULD calibrate the value once per component by plotting cumulative pass rate against repeat count for a few representative entries and picking the point where it plateaus, rather than guessing.
29
+ - `EVAL_MIN_ACCURACY_REPEATABILITY` — minimum fraction of repeatability entries that must PASS for the eval to exit 0.
30
+ - `REPEAT_SEMANTIC_SIMILARITY_SCORE` — minimum average pairwise cosine similarity for a single entry to PASS; declared only when using semantic-similarity scoring.
31
+
32
+ `eval.py` MUST invoke the component `REPEAT_COUNT` times for every repeatability entry and score the resulting outputs by comparing them to each other. `expected_output` is unused for repeatability entries and SHOULD be omitted or set to `null` in the dataset.
33
+
34
+ **Choosing the scoring method:** Two approaches are supported, declared as a constant in `eval.py`:
35
+
36
+ - **Semantic-similarity:** Embed all `REPEAT_COUNT` outputs for an entry into vectors and compute the average pairwise cosine similarity. The entry passes (score = 1) if the average similarity ≥ `REPEAT_SEMANTIC_SIMILARITY_SCORE`; otherwise it fails (score = 0). Use for classification or short structured outputs.
37
+ - **LLM-as-judge:** Provide all `REPEAT_COUNT` outputs for an entry to an LLM judge (kept at low/zero temperature) that returns 0 (fail) or 1 (pass) directly, based on whether the outputs are sufficiently consistent. No `REPEAT_SEMANTIC_SIMILARITY_SCORE` constant is needed. Use for free-text or complex structured outputs where vector distance is an unreliable proxy for agreement. The judge MUST follow [agentme-edr-028](028-ai-eval-core-standards.md) rule `02`'s binary output contract.
38
+
39
+ **`repeatability_accuracy`:** the fraction of repeatability entries that received PASS (score = 1), logged to MLflow as `repeatability_accuracy`. The eval exits non-zero if `repeatability_accuracy` < `EVAL_MIN_ACCURACY_REPEATABILITY`. Both `repeatability_accuracy` and `repeat_count` MUST be logged to MLflow and included in `report-repeatability.md` (rule `02`).
40
+
41
+ ```python
42
+ REPEAT_COUNT = 5
43
+ EVAL_MIN_ACCURACY_REPEATABILITY = 0.8
44
+ REPEAT_SEMANTIC_SIMILARITY_SCORE = 0.9 # only when using semantic-similarity scoring
45
+
46
+ for entry in repeatability_entries:
47
+ outputs = [invoke_component(entry, graph) for _ in range(REPEAT_COUNT)]
48
+ entry_pass = score_agreement(outputs) # returns 0 or 1; expected_output is not used
49
+ results["repeatability"].append(entry_pass) # 1 = PASS, 0 = FAIL
50
+
51
+ repeatability_accuracy = sum(results["repeatability"]) / len(results["repeatability"])
52
+ mlflow.log_metric("repeatability_accuracy", repeatability_accuracy)
53
+ mlflow.log_metric("repeat_count", REPEAT_COUNT)
54
+
55
+ if repeatability_accuracy < EVAL_MIN_ACCURACY_REPEATABILITY:
56
+ raise SystemExit(f"Eval failed: repeatability_accuracy {repeatability_accuracy:.2f} < {EVAL_MIN_ACCURACY_REPEATABILITY}")
57
+ ```
58
+
59
+ `mock_fixtures` configuration per [agentme-edr-031](031-ai-eval-script.md) rule `01` applies to each of the `REPEAT_COUNT` invocations. Any prompt or response caching (provider-side or gateway-side) MUST be bypassed for these invocations — a cache hit would return an identical cached response and falsely report perfect stability instead of measuring the model's actual variance.
60
+
61
+ **Scoping:** this test type MUST NOT be applied to components whose intended behavior is diverse or creative output (e.g. brainstorming, creative writing) — low agreement there is correct behavior, not a defect.
62
+
63
+ #### 02-repeatability-report-and-cadence
64
+
65
+ `--type=repeatability` MUST produce `report-repeatability.md` with a shape adapted from [agentme-edr-032](032-ai-eval-report-format.md) rule `01`'s template: the header MUST include a **Repeat count:** line stating the `REPEAT_COUNT` value used for the run, alongside the usual Date/Dataset/Script/Thresholds lines. The body MUST have an aggregate row reporting `repeatability_accuracy` (the fraction of entries that PASS — see rule `01`) with a Wilson score interval computed over the number of `repeatability` entries, plus a per-item table listing each entry's individual pass/fail result and, when using semantic-similarity, its computed average pairwise cosine similarity — instead of the `Expected | Actual | Correct` columns used by other types.
66
+
67
+ Because `repeatability` entries multiply real LLM-provider calls by `REPEAT_COUNT`, projects SHOULD schedule `make eval-repeatability` at release cadence rather than on every commit, aligned with the Workflow eval cadence in [agentme-edr-007](../principles/007-project-quality-standards.md) rule `09`, rather than treating it as a mandatory per-commit gate.
68
+
69
+ ## References
70
+
71
+ - [agentme-edr-031](031-ai-eval-script.md) — AI eval script: rule `01` defines the entry-first constraint this policy exempts for repeatability entries
72
+ - [agentme-edr-028](028-ai-eval-core-standards.md) — AI eval core standards: rule `02` defines the LLM-as-judge binary output contract used by the LLM-as-judge scoring method in rule `01`
73
+ - [agentme-edr-032](032-ai-eval-report-format.md) — AI eval report format: rule `01` defines the base report template that `report-repeatability.md` adapts
74
+ - [agentme-edr-030](030-ai-test-types-taxonomy.md) — AI test types taxonomy: `repeatability` test type definition and disambiguation from `reproducibility` (rule `09`)
75
+ - [agentme-edr-007](../principles/007-project-quality-standards.md) — Project quality standards: Workflow eval cadence (rule `09`) that repeatability runs align with
@@ -53,60 +53,60 @@ Module folder responsibilities, artifact locations, and test-folder conventions
53
53
  #### 02-application-folders
54
54
 
55
55
  - Represent a cohesive unit with its own lifecycle (e.g., `mymobileapp`, `graph-visualizer`).
56
- - **MUST** depend only on resources in `/shared/`. Direct cross-application dependencies are forbidden; use published artifacts (container images, published libraries) instead.
57
- - **MUST** contain a `README.md` with: purpose, architecture overview, how to build, and how to run.
58
- - **MAY** contain `examples/`, `tests_integration/`, and `tests_benchmark/` when those artifacts apply to multiple modules inside the application.
56
+ - MUST depend only on resources in `/shared/`. Direct cross-application dependencies are forbidden; use published artifacts (container images, published libraries) instead.
57
+ - MUST contain a `README.md` with: purpose, architecture overview, how to build, and how to run.
58
+ - MAY contain `examples/`, `tests_integration/`, and `tests_benchmark/` when those artifacts apply to multiple modules inside the application.
59
59
 
60
60
  #### 03-module-folders
61
61
 
62
62
  - A module is a subfolder inside an application that is independently compilable and produces a build artifact.
63
63
  - May depend on sibling modules within the same application or on `/shared/` resources.
64
- - **MUST NOT** depend on modules from other applications.
65
- - **MUST** contain its own `Makefile`, `README.md`, and language/tooling configuration.
66
- - **MUST** keep build outputs under `dist/` and persistent caches under `.cache/`, following [agentme-edr-016](../principles/016-cross-language-module-structure.md).
67
- - **MUST NOT** keep consumer examples inside the module folder; those belong in a sibling `examples/` folder at the nearest parent aggregation root.
64
+ - MUST NOT depend on modules from other applications.
65
+ - MUST contain its own `Makefile`, `README.md`, and language/tooling configuration.
66
+ - MUST keep build outputs under `dist/` and persistent caches under `.cache/`, following [agentme-edr-016](../principles/016-cross-language-module-structure.md).
67
+ - MUST NOT keep consumer examples inside the module folder; those belong in a sibling `examples/` folder at the nearest parent aggregation root.
68
68
 
69
69
  #### 04-naming-conventions
70
70
 
71
- - All folder and file names **MUST** be **lowercase**.
71
+ - All folder and file names MUST be lowercase.
72
72
  - Use hyphens (`-`) to separate words (e.g., `data-loader`, `graph-visualizer`).
73
73
  - Avoid abbreviations unless universally understood in the domain (e.g., `cli`, `api`).
74
74
 
75
75
  #### 05-makefiles-at-every-level
76
76
 
77
- A `Makefile` **MUST** be present at the repository root, in every application folder, and in every module folder.
77
+ A `Makefile` MUST be present at the repository root, in every application folder, and in every module folder.
78
78
 
79
- All Makefiles **MUST** use the shared target vocabulary from [agentme-edr-008](008-common-targets.md).
79
+ All Makefiles MUST use the shared target vocabulary from [agentme-edr-008](008-common-targets.md).
80
80
 
81
- Repository, application, and module Makefiles **MUST** define at minimum: `all`, `build`, `lint`, `test`, and `clean`.
81
+ Repository, application, and module Makefiles MUST define at minimum: `all`, `build`, `lint`, `test`, and `clean`.
82
82
 
83
- Module Makefiles **SHOULD** also provide `lint-fix` and `install` when the underlying tooling supports them.
83
+ Module Makefiles SHOULD also provide `lint-fix` and `install` when the underlying tooling supports them.
84
84
 
85
- The root `Makefile` **MUST** also define a `setup` target that guides a new contributor to prepare their machine.
86
- The root `setup` target **MUST** run `mise install` and any small repository bootstrap required before routine targets work.
85
+ The root `Makefile` MUST also define a `setup` target that guides a new contributor to prepare their machine.
86
+ The root `setup` target MUST run `mise install` and any small repository bootstrap required before routine targets work.
87
87
 
88
88
  #### 06-mise-for-tooling-management
89
89
 
90
- - [Mise](https://mise.jdx.dev/) **MUST** be used to pin all tool versions (compilers, runtimes, CLI tools).
91
- - A `.mise.toml` **MUST** exist at the repository root.
92
- - Every language runtime or CLI referenced by any module `Makefile`, CI workflow, or README command **MUST** be pinned in `.mise.toml`.
93
- - Contributors and CI run `make setup` after cloning or checkout; this target must call `mise install`.
94
- - Agents and contributors **MUST** check `.mise.toml` before using a system-installed compiler, runtime, or CLI.
95
- - When `.mise.toml` exists, all build, test, lint, and code-generation commands **MUST** run through `make <target>`, and the Makefile recipes **MUST** execute the underlying tools via `mise exec -- <command>`, following [agentme-edr-017](017-tool-execution-and-scripting.md).
96
- - If a required tool is missing, the first remediation step **MUST** be to update `.mise.toml` or run `mise install`, not to install ad-hoc global tools with language-specific installers such as `go install`, `npm install -g`, `pip install --user`, or `cargo install`.
97
- - Root and module `Makefile` targets **MUST** work when invoked as plain `make <target>` after `make setup`.
90
+ - [Mise](https://mise.jdx.dev/) MUST be used to pin all tool versions (compilers, runtimes, CLI tools).
91
+ - A `.mise.toml` MUST exist at the repository root.
92
+ - Every language runtime or CLI referenced by any module `Makefile`, CI workflow, or README command MUST be pinned in `.mise.toml`.
93
+ - Contributors and CI run `make setup` after cloning or checkout; this target MUST call `mise install`.
94
+ - Agents and contributors MUST check `.mise.toml` before using a system-installed compiler, runtime, or CLI.
95
+ - When `.mise.toml` exists, all build, test, lint, and code-generation commands MUST run through `make <target>`, and the Makefile recipes MUST execute the underlying tools via `mise exec -- <command>`, following [agentme-edr-017](017-tool-execution-and-scripting.md).
96
+ - If a required tool is missing, the first remediation step MUST be to update `.mise.toml` or run `mise install`, not to install ad-hoc global tools with language-specific installers such as `go install`, `npm install -g`, `pip install --user`, or `cargo install`.
97
+ - Root and module `Makefile` targets MUST work when invoked as plain `make <target>` after `make setup`.
98
98
 
99
99
  #### 07-root-readme
100
100
 
101
- The root `README.md` **MUST** include: overview, machine setup, quickstart, and a repository map.
101
+ The root `README.md` MUST include: overview, machine setup, quickstart, and a repository map.
102
102
 
103
103
  #### 08-root-gitignore
104
104
 
105
- The repository root **MUST** ignore `dist/` and `.cache/` so module artifacts and tool caches are never committed accidentally.
105
+ The repository root MUST ignore `dist/` and `.cache/` so module artifacts and tool caches MUST NOT be committed accidentally.
106
106
 
107
107
  #### 09-git-tagging-and-artifact-versioning
108
108
 
109
- All releases **MUST** be tagged using the format `<module-name>/<semver>` (e.g., `graphvisualizer/renderer/1.0.0`, `shared/libs/mylib/2.1.0`).
109
+ All releases MUST be tagged using the format `<module-name>/<semver>` (e.g., `graphvisualizer/renderer/1.0.0`, `shared/libs/mylib/2.1.0`).
110
110
 
111
111
  `<module-name>` is preferably the path-like identifier of the module being released. A custom name is allowed but the folder name is strongly preferred.
112
112
 
@@ -29,7 +29,7 @@ Separating these concerns eliminates accidental publishes from CI runs, ensures
29
29
  | `release.yml` | `workflow_dispatch` | Tag the next version using monotag |
30
30
  | `publish.yml` | `push` of tags matching `*` | Publish artifacts for the tagged version |
31
31
 
32
- All workflows run on `ubuntu-latest`. Tool versions MUST be managed by Mise via `jdx/mise-action`. Projects should have a .mise.toml file to configure it
32
+ All workflows run on `ubuntu-latest`. Tool versions MUST be managed by Mise via `jdx/mise-action`. Projects SHOULD have a `.mise.toml` file to configure it
33
33
 
34
34
  ---
35
35
 
@@ -69,7 +69,7 @@ File: `.github/workflows/release.yml`
69
69
 
70
70
  Projects MUST use this manually dispatched (`workflow_dispatch`) workflow. It calculates the next semantic version tag using **monotag** and pushes that tag to the repository. Pushing the tag then automatically triggers the publish workflow.
71
71
 
72
- The checkout step **must** use `fetch-depth: 0` so monotag can traverse the full commit history to determine the correct next version.
72
+ The checkout step MUST use `fetch-depth: 0` so monotag can traverse the full commit history to determine the correct next version.
73
73
 
74
74
  ```yaml
75
75
  name: release
@@ -23,18 +23,18 @@ Standardizing both the target names and the execution chain removes per-project
23
23
 
24
24
  #### 01-every-project-must-have-root-makefile
25
25
 
26
- The project root **MUST** contain a single authoritative `Makefile` that exposes the standard target names defined in rule 3. Developers and CI pipelines **MUST** invoke routine actions through this `Makefile`, **NEVER** by calling underlying tools directly in documentation, CI, or daily workflow commands.
26
+ The project root MUST contain a single authoritative `Makefile` that exposes the standard target names defined in rule 3. Developers and CI pipelines MUST invoke routine actions through this `Makefile`, MUST NOT call underlying tools directly in documentation, CI, or daily workflow commands.
27
27
 
28
28
  `make <target>` is the shared contract across projects and languages.
29
29
 
30
- - The root `Makefile` **MUST** be the entry point for both developers and pipelines.
31
- - The root `Makefile` **MUST** expose at minimum the common targets defined in this XDR.
32
- - Reverse-compatibility wrappers are allowed when an ecosystem expects them, but they **MUST** stay trivial.
30
+ - The root `Makefile` MUST be the entry point for both developers and pipelines.
31
+ - The root `Makefile` MUST expose at minimum the common targets defined in this XDR.
32
+ - Reverse-compatibility wrappers are allowed when an ecosystem expects them, but they MUST stay trivial.
33
33
  - Allowed: `package.json` script `"test": "make test"`
34
34
  - Not allowed: `make test` -> `npm run test` -> tool command
35
- - Project logic **MUST NOT** live in npm scripts, Mise tasks, shell wrappers, or other secondary runners when the same logic belongs in the `Makefile`.
35
+ - Project logic MUST NOT live in npm scripts, Mise tasks, shell wrappers, or other secondary runners when the same logic belongs in the `Makefile`.
36
36
 
37
- *Why:* The project entry point **MUST** stay language-agnostic and obvious. A developer **SHOULD** be able to inspect the `Makefile` and immediately see which real tool commands will run.
37
+ *Why:* The project entry point MUST stay language-agnostic and obvious. A developer SHOULD be able to inspect the `Makefile` and immediately see which real tool commands will run.
38
38
 
39
39
  #### 02-makefile-recipes-must-use-mise
40
40
 
@@ -47,10 +47,10 @@ make <target>
47
47
  -> explicit tool command
48
48
  ```
49
49
 
50
- - The `setup` target **MUST** run `mise install` and any small project-specific bootstrap needed before normal targets work.
51
- - Routine targets such as `build`, `lint`, `test`, `run`, and `publish` **MUST** be invoked as `make <target>` by both contributors and CI.
52
- - Each Makefile recipe **MUST** call the real underlying command through `mise exec --`, following [agentme-edr-017](017-tool-execution-and-scripting.md).
53
- - Makefile recipes **MUST NOT** add extra script layers such as `npm run`, `pnpm run`, `yarn run`, `mise run`, `mise tasks`, or shell aliases when those layers only forward to another command.
50
+ - The `setup` target MUST run `mise install` and any small project-specific bootstrap needed before normal targets work.
51
+ - Routine targets such as `build`, `lint`, `test`, `run`, and `publish` MUST be invoked as `make <target>` by both contributors and CI.
52
+ - Each Makefile recipe MUST call the real underlying command through `mise exec --`, following [agentme-edr-017](017-tool-execution-and-scripting.md).
53
+ - Makefile recipes MUST NOT add extra script layers such as `npm run`, `pnpm run`, `yarn run`, `mise run`, `mise tasks`, or shell aliases when those layers only forward to another command.
54
54
  - Calling the actual tool is allowed even when that tool itself launches another program as part of its normal interface.
55
55
  - Allowed: `mise exec -- pnpm exec eslint ./src`
56
56
  - Allowed: `mise exec -- go test -cover ./...`
@@ -66,7 +66,7 @@ make <target>
66
66
 
67
67
  #### 03-standard-target-groups-and-names
68
68
 
69
- Targets are organized into five lifecycle groups. Projects **MUST** use these names unchanged. Extensions are allowed (see rule 5) but the core names **MUST NOT** be repurposed.
69
+ Targets are organized into five lifecycle groups. Projects MUST use these names unchanged. Extensions are allowed (see rule 5) but the core names MUST NOT be repurposed.
70
70
 
71
71
  ##### Developer group
72
72
 
@@ -150,28 +150,6 @@ The prefix convention ensures developers can infer the purpose of any target wit
150
150
 
151
151
  ---
152
152
 
153
- #### 09-ai-project-dev-targets
154
-
155
- AI-based projects (LLM, Agent, and Workflow tiers as defined in [agentme-edr-018](../application/018-ai-llm-development-standards.md)) MUST expose a `dev-mlflow` target that starts a local MLflow tracking server for development inspection.
156
-
157
- **Example implementation:**
158
-
159
- ```makefile
160
- dev-mlflow:
161
- mise exec -- mlflow ui --host 0.0.0.0 --port 5000
162
- open http://localhost:5000/
163
- ```
164
-
165
- ---
166
-
167
- #### 08-default-targets-must-only-include-offline-subtargets
168
-
169
- `make all`, `make test`, and `make lint` **MUST** include every subtarget that runs **offline** — meaning it requires no external credentials, no running servers, no paid APIs, and no environment-specific configuration outside the repository.
170
-
171
- Subtargets that require external dependencies (e.g., `test-integration` against a live database, `test-e2e` against a staging environment, `lint-api` against a remote schema registry) **MUST** exist as named targets so developers can invoke them explicitly, but **MUST NOT** be invoked from `all`, `test`, or `lint`.
172
-
173
- ---
174
-
175
153
  #### 06-monorepo-usage
176
154
 
177
155
  In a monorepo, each module has its own `Makefile` with its own `build`, `lint`, `test`, and `deploy` targets scoped to that module. Parent-level Makefiles (at the application or repo root) delegate to child Makefiles in sequence. The parent Makefile **SHOULD** call `$(MAKE) -C <child> <target>` directly, while each child `Makefile` runs its actual tool commands through `mise exec --`.
@@ -238,6 +216,28 @@ make clean
238
216
  make all
239
217
  ```
240
218
 
219
+ ---
220
+
221
+ #### 08-default-targets-must-only-include-offline-subtargets
222
+
223
+ `make all`, `make test`, and `make lint` **MUST** include every subtarget that runs **offline** — meaning it requires no external credentials, no running servers, no paid APIs, and no environment-specific configuration outside the repository.
224
+
225
+ Subtargets that require external dependencies (e.g., `test-integration` against a live database, `test-e2e` against a staging environment, `lint-api` against a remote schema registry) **MUST** exist as named targets so developers can invoke them explicitly, but **MUST NOT** be invoked from `all`, `test`, or `lint`.
226
+
227
+ ---
228
+
229
+ #### 09-ai-project-dev-targets
230
+
231
+ AI-based projects (LLM, Agent, and Workflow tiers as defined in [agentme-edr-018](../application/018-ai-llm-development-standards.md)) MUST expose a `dev-mlflow` target that starts a local MLflow tracking server for development inspection.
232
+
233
+ **Example implementation:**
234
+
235
+ ```makefile
236
+ dev-mlflow:
237
+ mise exec -- mlflow ui --host 0.0.0.0 --port 5000
238
+ open http://localhost:5000/
239
+ ```
240
+
241
241
  ## Considered Options
242
242
 
243
243
  * (REJECTED) **Language-native entry points only** - Use `npm run`, `python -m`, `go run`, and similar tool-specific commands directly as the standard surface
@@ -24,7 +24,7 @@ This keeps local development and CI aligned, reduces indirection, and lets contr
24
24
  - Every project MUST use a root `Makefile` as the authoritative entry point for developer and pipeline commands.
25
25
  - The target names in that `Makefile` MUST follow [agentme-edr-008](008-common-targets.md).
26
26
  - CI pipelines MUST run `make <target>` from the relevant root instead of calling language-specific scripts such as `npm run`, `pnpm run`, shell wrappers, or secondary task runners.
27
- - A Makefile target MUST execute the real operation through `mise exec --` before invoking the tool itself, so it always uses the version pinned in `.mise.toml`. Avoid intermediate script layers that hide the actual command.
27
+ - A Makefile target MUST execute the real operation through `mise exec --` before invoking the tool itself, so it MUST use the version pinned in `.mise.toml`. Avoid intermediate script layers that hide the actual command.
28
28
  - Every Makefile target MUST start by echoing a concise summary of the target and folder or context, using fewer than 10 words. When delegating to another Makefile, echo the child path and delegated target before invoking it.
29
29
  - Direct delegation to another Makefile is allowed when traversing repo, app, or module boundaries, for example `$(MAKE) -C lib build`.
30
30
  - Calling the actual tool binary through its native executable launcher is allowed when that is the direct command under `mise exec --`, for example `mise exec -- pnpm exec eslint ./src`, `mise exec -- uv run ty check`, `mise exec -- go test`, or `mise exec -- npx -y monotag`.
@@ -17,9 +17,9 @@ How should projects manage environment variable configuration and CLI invocation
17
17
 
18
18
  ## Decision Outcome
19
19
 
20
- **Use YAML config files for CLI invocation configuration with multiple attributes; use `.env` files to supply environment variables to spawned processes and to hold uncommitted values referenced by config files. Load `.env` exclusively at process launch time — never inside application code.**
20
+ **Use YAML config files for CLI invocation configuration with multiple attributes; use `.env` files to supply environment variables to spawned processes and to hold uncommitted values referenced by config files. Load `.env` exclusively at process launch time — MUST NOT be loaded inside application code.**
21
21
 
22
- Secrets (API keys, passwords, tokens) must never be placed in `.env` files. Those are handled by [agentme-edr-022](../principles/022-secrets-management.md).
22
+ Secrets (API keys, passwords, tokens) MUST NOT be placed in `.env` files. Those are handled by [agentme-edr-022](../principles/022-secrets-management.md).
23
23
 
24
24
  ### Details
25
25
 
@@ -43,7 +43,7 @@ FEATURE_FLAG_NEW_UI=false
43
43
 
44
44
  #### 02-dotenv-not-committed
45
45
 
46
- `.env` MUST be listed in `.gitignore` and must never be committed to the repository. It is intended for local use in standalone projects and libraries that do not have a formal deployment pipeline.
46
+ `.env` MUST be listed in `.gitignore` and MUST NOT be committed to the repository. It is intended for local use in standalone projects and libraries that do not have a formal deployment pipeline.
47
47
 
48
48
  ---
49
49