agentme 0.32.0 → 0.33.1

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.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: agentme-edr-policy-151-ai-eval-standards
3
- description: Defines the eval folder structure and Makefile interface for AI projects, and the LLM-as-judge binary scoring contract applicable to all AI tiers and test types. Use when scaffolding evals or implementing an LLM judge. For eval script requirements see agentme-edr-153. For report format see agentme-edr-154. For repeatability see agentme-edr-155. For fairness/bias group scoring see agentme-edr-156. For when evals are required see agentme-edr-501 rule 09-ai-project-testing-requirements. For the test type taxonomy see agentme-edr-152.
3
+ description: Defines the eval folder structure and Makefile interface for AI projects, and the LLM-as-judge binary scoring contract applicable to all AI tiers and test types. Use when scaffolding evals or implementing an LLM judge. For eval script requirements see agentme-edr-153. For report format see agentme-edr-154. For repeatability see agentme-edr-155. For fairness per-entry scoring and bias group scoring see agentme-edr-156. For when evals are required see agentme-edr-501 rule 09-ai-project-testing-requirements. For the test type taxonomy see agentme-edr-152.
4
4
  apply-to: Python AI projects (LLM, Agent, or Workflow tier) that implement eval testing
5
5
  valid-from: 2026-06-05
6
6
  ---
@@ -115,7 +115,7 @@ Output:
115
115
  - [agentme-edr-153](153-ai-eval-script.md) — AI eval script: entry-first eval loop, `--type` filtering, `mock_fixtures`, and MLflow conventions
116
116
  - [agentme-edr-154](154-ai-eval-report-format.md) — AI eval report format: `report-<type>.md` template, Wilson CI, and convergence analysis
117
117
  - [agentme-edr-155](155-ai-eval-repeatability.md) — AI eval repeatability: loop exception, scoring methods (including LLM-as-judge per rule `02`), and cadence
118
- - [agentme-edr-156](156-ai-eval-fairness-bias.md) — AI eval fairness/bias: comparison_group group-scoring loop, scoring approaches (including LLM-as-judge per rule `02`), fairness_accuracy/bias_accuracy metrics, and report shape
118
+ - [agentme-edr-156](156-ai-eval-fairness-bias.md) — AI eval fairness and bias: fairness per-entry inline scoring; bias `bias_group` deferred group-scoring loop, scoring approaches (including LLM-as-judge per rule `02`), fairness_accuracy/bias_accuracy metrics, and report shapes
119
119
  - [agentme-edr-501](../governance/501-project-quality-standards.md) — Project quality standards: when evals are required per AI tier (rule `09`) and statistical model eval targets (rule `07`)
120
120
  - [agentme-edr-152](152-ai-test-types-taxonomy.md) — AI test types taxonomy: `test_types` enum and golden dataset entry envelope
121
121
  - [agentme-edr-201](../data/201-ml-dataset-structure.md) — ML dataset structure, per-entry JSON format, and schema-lint validation for golden datasets
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: agentme-edr-policy-152-ai-test-types-taxonomy
3
- description: Names AI-application test types grouped as "Safety & adversarial", "Responsible AI", "Quality eval", "Prompt/LLM", and "Code-level" with their objective, mocking constraint, and relevance, and defines the shared "golden dataset" entry envelope that agentme-edr-151's eval tooling filters by test_types. Use when deciding which AI test types to implement or when authoring a golden dataset entry.
3
+ description: Names AI test types with objective, mocking constraint, and relevance; defines the golden dataset entry envelope for agentme-edr-151's eval tooling; covers three test scopes (Workflow/Agent/LLM) and a quality-progression DAG. Use when deciding which test types to implement, authoring a golden dataset entry, or selecting a test tier.
4
4
  apply-to: AI projects (LLM, Agent, or Workflow tier) implementing AI-specific test types beyond generic code-level unit/integration tests
5
5
  valid-from: 2026-07-05
6
6
  ---
@@ -15,13 +15,13 @@ AI components need test types beyond generic unit/integration tests (safety, fai
15
15
 
16
16
  **Adopt a named taxonomy of AI test types plus a shared "golden dataset" entry envelope that agentme-edr-151's eval tooling filters by `test_types`.**
17
17
 
18
- Each test type is named with its group, objective, mocking constraint, applicability, and relevance; every golden dataset entry is labeled with the test types it applies to.
18
+ Each test type is named with its objective, mocking constraint, applicability, and relevance; every golden dataset entry is labeled with the test types it applies to.
19
19
 
20
20
  ### Details
21
21
 
22
22
  #### 01-golden-dataset-concept
23
23
 
24
- Projects MUST use a golden dataset to test AI components. A **golden dataset** comprises all eval case entries used to test an AI component (LLM, Agent, or Workflow tier); each entry is labeled with the `test_types` (rule `04`) it applies to. It is the dataset consumed by [agentme-edr-153](153-ai-eval-script.md) evals and stored as one JSON file per entry per [agentme-edr-201](../data/201-ml-dataset-structure.md) rule `04`, at `evals/<component>/eval-<name>/golden_dataset/`.
24
+ Projects MUST use a golden dataset all eval case entries used to test an AI component, each labeled with `test_types` (rule `04`). Consumed by [agentme-edr-153](153-ai-eval-script.md) and stored at `evals/<component>/eval-<name>/golden_dataset/` per [agentme-edr-201](../data/201-ml-dataset-structure.md) rule `04`.
25
25
 
26
26
  #### 02-golden-dataset-entry-envelope
27
27
 
@@ -39,23 +39,15 @@ Every golden dataset entry (a JSON file in `golden_dataset/data/`) MUST have thi
39
39
  }
40
40
  ```
41
41
 
42
- - `test_types` — array, values MUST come from rule `04`'s enum, MUST contain at least one value. An entry MAY carry more than one value additively (e.g. `["functional", "smoke", "human"]`) — no test type excludes another.
43
- - `input` — for Prompt-tier components, a raw prompt string or the prompt template's input parameters object; for Agent/Workflow-tier components, the input attributes object passed to the component.
44
- - `expected_output` — the fields used to score the entry under each of its automated `test_types`: output attributes for an LLM-as-judge rubric, a target for vector-similarity scoring, or exact attribute values for strict comparison. When `human` is one of the entry's `test_types`, `expected_output` MUST additionally include a `human_test` string field with manual-verification instructions (e.g. `"check for ethical issues, verify record change in system X"`) — this supplements, and MUST NOT replace, the entry's automated scoring fields. **Exception:** when `test_types` contains only values from `["fairness", "bias", "repeatability"]` (no other automated types), `expected_output` MUST be `null` these types score by group comparison or self-invocation, not against a fixed expected value. If the entry also carries any other type (including `human`), `expected_output` MUST be non-null.
45
- - `mock_fixtures` — optional object; keys identify the adapter or external system to mock (SHOULD match the connector folder name under `adapters/connectors/<name>` for readability, though not enforced), values are any valid JSON interpreted by the mock implementation. When present, eval.py MUST configure each named mock adapter with its fixture data BEFORE invoking the component for that entry; each entry MUST use fresh mock instances to prevent state from bleeding across entries. `mock_fixtures` applies to all `test_types` including `human` — the component is still invoked for human entries to capture `actual_output`. `mock_fixtures` MUST NOT include keys for LLM adapters: all golden dataset test types are rated `mocks disallowed for LLM calls` (rule `03`), so the LLM call MUST be real; LLM provider mocking belongs exclusively to unit tests via [agentme-edr-141](141-ai-llm-development-standards.md) rule `04`. See [agentme-edr-126](126-pragmatic-hexagonal-architecture.md) rule `10` for the `_mock` file naming and placement convention.
46
- - `group` — optional string; a thematic label for on-demand filtering and optional per-group report views (e.g. `"simple"`, `"edge_cases"`). Used by the `--groups` CLI argument of [agentme-edr-153](153-ai-eval-script.md). Values MUST NOT contain commas (comma is the `--groups` list delimiter).
47
- - `comparison_group` — optional string or integer; required when `test_types` includes `fairness` or `bias` (enforced by `dataset.schema.json` — see schema rules below). Identifies the demographic comparison scenario this entry belongs to: all entries sharing the same `comparison_group` value represent the same scenario varying only in protected attributes (gender, race, age, nationality, religion, etc.) in `input`. See [agentme-edr-156](156-ai-eval-fairness-bias.md) for the eval loop, scoring approaches, and metrics.
48
- - The dataset's `dataset.schema.json` MUST require `test_types`, `input`, and `expected_output`, and MUST declare `group` and `comparison_group` as optional and SHOULD declare `mock_fixtures` as optional (`"type": "object", "additionalProperties": {}`), per [agentme-edr-201](../data/201-ml-dataset-structure.md) rule `04`. The `expected_output` type MUST allow `null` globally (e.g. `"type": ["string", "object", "null"]`) to support entries where `expected_output` is `null`. Two conditional rules MUST be expressed as `allOf` entries using JSON Schema `if/then` (supported by the Python `jsonschema` library in draft-07 and later):
49
- - **Rule A** `comparison_group` is required when `test_types` contains `"fairness"` or `"bias"`:
50
- ```json
51
- "if": {"properties": {"test_types": {"contains": {"enum": ["fairness", "bias"]}}}},
52
- "then": {"required": ["comparison_group"]}
53
- ```
54
- - **Rule B** — `expected_output` must not be `null` when `test_types` contains any value outside the exempted set `["fairness", "bias", "repeatability"]`:
55
- ```json
56
- "if": {"properties": {"test_types": {"contains": {"not": {"enum": ["fairness", "bias", "repeatability"]}}}}},
57
- "then": {"properties": {"expected_output": {"not": {"type": "null"}}}}
58
- ```
42
+ - `test_types` — array, values MUST come from rule `04`'s enum, MUST contain at least one value. An entry MAY carry more than one value additively (e.g. `["functional", "smoke"]`) — no test type excludes another.
43
+ - `input` — the prompt string or input parameters (Prompt tier), or input attributes object (Agent/Workflow tier) passed to the component.
44
+ - `expected_output` — fields used to score the entry. MUST be `null` when `test_types` contains only `["bias", "repeatability"]` (Schema Rule C); MUST be non-null when any other type is also present (Schema Rule B). When `bias` and `fairness` are combined, used by fairness scoring and IGNORED for bias scoring.
45
+ - `mock_fixtures` — optional object; keys identify adapters to mock (SHOULD match `adapters/connectors/<name>`), values are any valid JSON. When present, eval.py MUST configure each mock BEFORE invoking the component, using fresh instances per entry. `mock_fixtures` MUST NOT include LLM adapter keys LLM calls MUST be real (rule `03`).
46
+ - `human_review` — optional boolean; when `true`, requires manual verification IN ADDITION to automated scoring. NOT a test type can be applied to any entry at any stage.
47
+ - `human_instructions` — optional string; MUST be present when `human_review: true` (Schema Rule D). Manual-verification instructions for the reviewer; does not participate in automated scoring.
48
+ - `group` optional string; thematic label for filtering (e.g. `"simple"`, `"edge_cases"`). Used by the `--groups` CLI argument of [agentme-edr-153](153-ai-eval-script.md). Values MUST NOT contain commas.
49
+ - `bias_group`optional string or integer; MUST be present when `test_types` includes `bias` (Schema Rule A). All entries sharing the same value represent the same scenario varying only in EU Charter/GDPR Art.9 protected attributes. Fairness-only entries MUST NOT carry `bias_group`.
50
+ - `dataset.schema.json` MUST require `test_types`, `input`, and `expected_output`; `group`, `bias_group`, and `mock_fixtures` MUST be optional. `expected_output` type MUST allow `null`. Four `allOf/if-then` rules MUST enforce: (A) `bias_group` required when `bias` in `test_types`; (B) `expected_output` non-null when any non-exempted type present; (C) `expected_output` null when only `bias`/`repeatability` types present; (D) `human_instructions` required when `human_review: true`. See [agentme-edr-201](../data/201-ml-dataset-structure.md) rule `04`.
59
51
 
60
52
  #### 03-mocks-allowed-values
61
53
 
@@ -63,46 +55,47 @@ The taxonomy in rule `05` rates each test type using one of three values under t
63
55
 
64
56
  | Value | Meaning |
65
57
  |---|---|
66
- | `mocks allowed` | Fully offline; fakes may replace every dependency including the LLM (e.g. `FakeListChatModel` per [agentme-edr-141](141-ai-llm-development-standards.md) rule `04`). Used only for code-level unit tests. |
58
+ | `mocks allowed` | Fully offline; fakes may replace every dependency including the LLM. Used only for code-level unit tests. |
67
59
  | `mocks disallowed` | No mocking of any dependency — all real external systems required. Used for integration tests. |
68
- | `mocks disallowed for LLM calls` | **The LLM call MUST be real; all other external dependencies (databases, APIs, external services) MAY and SHOULD be mocked via `mock_fixtures`.** `mock_fixtures` keys MUST NOT reference LLM adapters. This is the standard constraint for every golden-dataset eval test type. See rule `08` for rationale. |
60
+ | `mocks disallowed for LLM calls` | **The LLM call MUST be real; all other external dependencies MAY be mocked via `mock_fixtures`.** `mock_fixtures` keys MUST NOT reference LLM adapters. Standard for all golden-dataset eval test types (see rule `08`). |
69
61
 
70
62
  #### 04-test-types-enum
71
63
 
72
- A golden dataset entry's `test_types` array MUST only use these values: `safety`, `adversarial`, `fairness`, `bias`, `robustness`, `explainability`, `groundedness`, `functional`, `prompt`, `smoke`, `human`, `repeatability`. These correspond to the dataset-driven rows of rule `05`. **Unit test** and **Integration test** (the two Code-level rows) are NOT part of this enum — they have no golden dataset entries and remain governed entirely by [agentme-edr-122](122-unit-test-requirements.md) and [agentme-edr-501](../governance/501-project-quality-standards.md) rule `08`.
64
+ A golden dataset entry's `test_types` array MUST only use these values: `safety`, `adversarial`, `fairness`, `bias`, `robustness`, `explainability`, `groundedness`, `functional`, `prompt`, `smoke`, `repeatability`. Unit test and Integration test are NOT in this enum — they are code-level only with no golden dataset entries. `human` is NOT a test type — use the `human_review` boolean and `human_instructions` fields instead (rule `02`).
73
65
 
74
66
  #### 05-test-type-taxonomy
75
67
 
76
68
  Test types MUST be selected from this taxonomy. Each test type is named with its group, objective, mocking constraint, applicability, and relevance:
77
69
 
78
- | Test Type Name | `test_types` value | Group | Test Objective | Mock Constraint | When to Apply | Relevance – Business | Relevance – Development Team | Priority (1-5) |
70
+ | Test Type Name | `test_types` value | Test Objective | Mock Constraint | When to Apply | Relevance – Business | Relevance – Development Team | Priority (1-5) | Examples |
79
71
  |---|---|---|---|---|---|---|---|---|
80
- | Safety/content eval | `safety` | Safety & adversarial | Detect harmful, biased, or policy-violating output | mocks disallowed for LLM calls | Any user-facing release | Avoids reputational harm; acceptable-use compliance | Automated content gate before merge/release | 5 |
81
- | Adversarial/red-team test | `adversarial` | Safety & adversarial | Probe for prompt injection, jailbreaks, unsafe tool use | mocks disallowed for LLM calls | System exposes tool-invocation or agent loops | Reduces security-incident/breach liability | Finds exploitable tool-loop paths before attackers do | 5 |
82
- | Fairness test | `fairness` | Responsible AI | Verify equitable outcomes across user groups by comparing outputs of demographic variants grouped by `comparison_group`; `expected_output` must be `null`. See [agentme-edr-156](156-ai-eval-fairness-bias.md) | mocks disallowed for LLM calls | Output affects decisions about individuals/groups | Regulatory requirement; protects equitable access | Surfaces uneven outcomes before release | 4 |
83
- | Bias test | `bias` | Responsible AI | Detect skewed or stereotyped associations by comparing outputs of demographic variants grouped by `comparison_group`; `expected_output` must be `null`. See [agentme-edr-156](156-ai-eval-fairness-bias.md) | mocks disallowed for LLM calls | User-facing content generation | Lowers legal/reputational exposure | Catches bias introduced by data/prompts/fine-tuning | 3 |
84
- | Robustness test | `robustness` | Responsible AI | Verify stable behavior under noisy/out-of-distribution input | mocks disallowed for LLM calls | Inputs come from untrusted/variable sources | Protects reliability/SLAs | Confirms graceful degradation, guides input validation | 3 |
85
- | Explainability test | `explainability` | Responsible AI | Verify output is justifiable with a faithful rationale | mocks disallowed for LLM calls | Output must be justified to users/auditors/regulators | Required for auditability; builds user trust | Gives rationale trace for debugging wrong answers | 2 |
86
- | Groundedness (RAG) eval | `groundedness` | Quality eval | Verify the answer is supported by retrieved context | mocks disallowed for LLM calls | System uses retrieval-augmented generation | Avoids confidently-wrong answers reaching customers | Pinpoints retrieval/prompt bugs | 4 |
87
- | Repeatability test | `repeatability` | Quality eval | Verify output stability/variance across N repeated invocations of the same input under fixed configuration | mocks disallowed for LLM calls | Non-deterministic components (temperature > 0, agentic tool-selection loops, sampling-based decoding) used in decision-critical or user-facing flows | Protects against silently flaky behavior reaching production; supports consistency SLAs | Detects prompt/agent designs too sensitive to sampling noise; informs temperature/seed tuning | 3 |
88
- | Human evaluation | `human` | Quality eval | Manually verify aspects automated scoring can't (ethics, side effects, external state) | mocks disallowed for LLM calls | Before major releases; periodic spot-check | Defensible, human-reviewed sign-off | Catches what automated metrics miss | 3 |
89
- | Functional eval (golden-dataset accuracy / LLM-as-judge) | `functional` | Quality eval | Measure output correctness against the golden dataset | mocks disallowed for LLM calls | Required before every Workflow release ([agentme-edr-501](../governance/501-project-quality-standards.md) rule `09`); advised elsewhere | Auditable evidence of business correctness before release | Detects regressions from model/provider/prompt changes | 5 |
90
- | Smoke test | `smoke` | Quality eval | Fast pass/fail check on a small, critical subset before running fuller suites | mocks disallowed for LLM calls | Every commit/PR, before functional/responsible-AI evals run | Cheap early warning before slower evals run | Fast, cheap feedback loop | 4 |
91
- | Prompt regression test | `prompt` | Prompt/LLM | Detect behavior change when a prompt or model version changes | mocks disallowed for LLM calls | Whenever a prompt template or model version changes | Prevents shipping a worse experience via a "small" tweak | Fast check on every prompt edit | 3 |
92
- | Integration test | n/a — code-level only (see rule `04`) | Code-level | Verify real interaction with external systems | mocks disallowed | Component depends on external systems | Reduces production outages from integration mismatches | Catches wiring bugs unit tests can't see | 2 |
93
- | Unit test (offline, mocked) | n/a — code-level only (see rule `04`) | Code-level | Verify deterministic logic in isolation, offline | mocks allowed | Required for Workflow tier every commit ([agentme-edr-501](../governance/501-project-quality-standards.md) rule `09`) | Lowest-cost point to catch defects | Fastest, fully offline feedback on every commit | 5 |
72
+ | Safety/content eval | `safety` | Detect harmful, biased, or policy-violating output | mocks disallowed for LLM calls | Any user-facing release | Avoids reputational harm; acceptable-use compliance | Automated content gate before merge/release | 5 | Self-harm input → output flagged; hate-speech prompt → policy-violation score above threshold |
73
+ | Adversarial/red-team test | `adversarial` | Probe for prompt injection, jailbreaks, unsafe tool use | mocks disallowed for LLM calls | System exposes tool-invocation or agent loops | Reduces security-incident/breach liability | Finds exploitable tool-loop paths before attackers do | 5 | Prompt injection → detected; crafted input triggering unauthorized tool call → blocked |
74
+ | Fairness test | `fairness` | Verify the system handles diverse non-protected groups correctly per business policies. Each entry is an independent policy scenario scored inline via LLM-as-judge against `expected_output`. `bias_group` MUST NOT be present on fairness-only entries. See [agentme-edr-156](156-ai-eval-fairness-bias.md). | mocks disallowed for LLM calls | System makes decisions that may unconsciously exclude population segments; before releases affecting access to services | Detects unconscious policy gaps before they become regulatory or reputational issues | Stress-tests the model against edge-case group scenarios | 4 | Rural farmer loan with farm land as collateral → `{"decision": "approved"}`; self-employed applicant at student credit union → `{"decision": "declined"}` |
75
+ | Bias test | `bias` | Certify that EU Charter/GDPR Art.9 protected attributes do NOT influence outcomes. Entries sharing the same `bias_group` vary only in protected attributes; outputs are compared across the group. `expected_output` IGNORED for bias scoring (null on bias-only entries). See [agentme-edr-156](156-ai-eval-fairness-bias.md). | mocks disallowed for LLM calls | Any system producing decisions, rankings, or recommendations; when training data or prompts may encode historical disparities | Lowers legal/regulatory exposure (EU AI Act, GDPR); protects against discriminatory outcomes | Catches protected-attribute influence from training data or prompts | 3 | Same loan with male/female/non-binary names → same approval decision; same resume with different ethnic-background names → same shortlisting outcome |
76
+ | Robustness test | `robustness` | Verify stable behavior under noisy/out-of-distribution input | mocks disallowed for LLM calls | Inputs come from untrusted/variable sources | Protects reliability/SLAs | Confirms graceful degradation, guides input validation | 3 | Typo-laden query ("Whta is teh status of ordr 123?") → same intent extracted as clean input; empty string input → graceful error, no crash |
77
+ | Explainability test | `explainability` | Verify output is justifiable with a faithful rationale | mocks disallowed for LLM calls | Output must be justified to users/auditors/regulators | Required for auditability; builds user trust | Gives rationale trace for debugging wrong answers | 2 | Recommendation output includes a cited source paragraph; the rationale field semantically supports the conclusion rather than contradicting it |
78
+ | Groundedness (RAG) eval | `groundedness` | Verify the answer is supported by retrieved context | mocks disallowed for LLM calls | System uses retrieval-augmented generation | Avoids confidently-wrong answers reaching customers | Pinpoints retrieval/prompt bugs | 4 | Answer "The policy expires on 2025-01-01" is verbatim in retrieved document; no date mentioned in context → answer must not invent one |
79
+ | Repeatability test | `repeatability` | Verify output stability across N repeated invocations under fixed configuration | mocks disallowed for LLM calls | Non-deterministic components (temperature > 0) in decision-critical flows | Protects against silently flaky behavior; supports consistency SLAs | Detects prompt/agent designs too sensitive to sampling noise | 3 | Same query 10× at temp=0.7 → semantic similarity ≥ 0.85; same agent task consistent tool selection |
80
+ | Functional eval (golden-dataset accuracy / LLM-as-judge) | `functional` | Measure output correctness against the golden dataset | mocks disallowed for LLM calls | Required before every Workflow release ([agentme-edr-501](../governance/501-project-quality-standards.md) rule `09`); advised elsewhere | Auditable evidence of business correctness before release | Detects regressions from model/provider/prompt changes | 5 | Invoice summary output matches expected `{"total": 450, "currency": "USD"}` within LLM-as-judge rubric; entity extraction returns all required fields |
81
+ | Smoke test | `smoke` | Fast pass/fail check on a small, critical subset before running fuller suites | mocks disallowed for LLM calls | Every commit/PR, before functional/responsible-AI evals run | Cheap early warning before slower evals run | Fast, cheap feedback loop | 4 | 3 critical golden entries (happy-path, empty-input, large-input) all pass before CI proceeds to full functional eval |
82
+ | Prompt regression test | `prompt` | Detect behavior change when a prompt or model version changes | mocks disallowed for LLM calls | Whenever a prompt template or model version changes | Prevents shipping a worse experience via a "small" tweak | Fast check on every prompt edit | 3 | Prompt v2 vs v1 on 20 entries: output diff reviewed; key fields present in ≥ 95% of v2 responses |
83
+ | Integration test | n/a — code-level only (see rule `04`) | Verify real interaction with external systems | mocks disallowed | Component depends on external systems | Reduces production outages from integration mismatches | Catches wiring bugs unit tests can't see | 2 | Agent calls real CRM API and receives a populated contact record; embedding service returns a vector of the expected dimension |
84
+ | Unit test (offline, mocked) | n/a — code-level only (see rule `04`) | Verify deterministic logic in isolation, offline | mocks allowed | Required for Workflow tier every commit ([agentme-edr-501](../governance/501-project-quality-standards.md) rule `09`) | Lowest-cost point to catch defects | Fastest, fully offline feedback on every commit | 5 | `extract_date("next Monday")` returns ISO string; `FakeListChatModel` returns canned JSON and parser handles it correctly |
85
+
86
+ **Human review modifier:** `human_review: true` is NOT a test type and does NOT appear in this table. It adds a manual review layer on top of automated scoring for any entry at any stage.
94
87
 
95
88
  #### 06-priority-and-relevance-are-descriptive-only
96
89
 
97
- Priority, Relevance, and When to Apply in rule `05` are guidance for prioritization conversations — they MUST NOT be treated as mandating which test types a project must implement, nor their thresholds. [agentme-edr-501](../governance/501-project-quality-standards.md) rule `09` remains the only tier-level testing requirement in force (Workflow unit tests + functional evals). Once a project chooses to implement and threshold a test type, [agentme-edr-153](153-ai-eval-script.md) rule `01`'s failing-threshold behavior applies uniformly, regardless of this table's priority rating — a project may enforce fairness at 70% and functional at 90%, or skip fairness entirely; that choice is a project/business decision, not one this Policy makes.
90
+ Priority, Relevance, and When to Apply in rule `05` MUST NOT be treated as mandating which test types a project must implement. [agentme-edr-501](../governance/501-project-quality-standards.md) rule `09` remains the only tier-level testing requirement. Once a project chooses to implement a test type, [agentme-edr-153](153-ai-eval-script.md) rule `01`'s failing-threshold behavior applies; the specific threshold is a project/business decision.
98
91
 
99
92
  #### 07-smoke-is-distinct-from-test-smoke
100
93
 
101
- The `smoke` test type (surfaced as the `eval-smoke` Makefile target, a fast subset of the golden-dataset functional eval) is a different concept from [agentme-edr-303](../platform/303-common-targets.md)'s existing `test-smoke` target (a fast subset of code-level tests). Both MAY exist in the same project; teams MUST NOT conflate them.
94
+ The `smoke` eval type (`eval-smoke` Makefile target) MUST NOT be conflated with [agentme-edr-303](../platform/303-common-targets.md)'s `test-smoke` code-level target. Both MAY coexist.
102
95
 
103
96
  #### 08-eval-mocking-constraint
104
97
 
105
- For every golden-dataset eval test type: **the LLM call MUST be real; all other external dependencies MUST be mocked via `mock_fixtures`.** This applies equally to `human` entries the component is invoked to capture `actual_output` and external dependencies must be deterministic. `mock_fixtures` keys MUST NOT reference LLM adapters. Code-level unit tests are the correct place for fully offline, LLM-mocked testing (see [agentme-edr-141](141-ai-llm-development-standards.md) rule `04`).
98
+ For every golden-dataset eval test type: **the LLM call MUST be real; all other external dependencies MUST be mocked via `mock_fixtures`.** `mock_fixtures` keys MUST NOT reference LLM adapters. This applies equally to entries with `human_review: true`. Code-level unit tests are the correct place for fully offline, LLM-mocked testing.
106
99
 
107
100
  #### 09-repeatability-vs-reproducibility
108
101
 
@@ -111,19 +104,80 @@ For every golden-dataset eval test type: **the LLM call MUST be real; all other
111
104
  | **Repeatability** | Output stability across N invocations at non-zero temperature | Model sampling variance | `repeatability` test type per [agentme-edr-155](155-ai-eval-repeatability.md) |
112
105
  | **Reproducibility** | Deterministic output at temperature = 0 with fixed seed | Nothing — any variance is a config bug | Not a golden-dataset type; verified via config, documented in [agentme-edr-305](../platform/305-environment-variable-configuration.md) |
113
106
 
114
- A component may satisfy reproducibility (temperature = 0) yet still need repeatability tests for its production configuration (temperature > 0). The `repeatability` test type MUST NOT be applied to components with intentionally diverse output (brainstorming, creative generation) — variance is correct behavior there.
107
+ A component may satisfy reproducibility (temperature = 0) yet still need repeatability tests for its production configuration (temperature > 0). The `repeatability` test type MUST NOT be applied to components with intentionally diverse output — variance is correct behavior there.
108
+
109
+ #### 10-test-scope-levels
110
+
111
+ Test types can be applied at three distinct scopes, matching the AI component tiers defined in [agentme-edr-141](141-ai-llm-development-standards.md):
112
+
113
+ | Scope | Description | Example eval target |
114
+ |---|---|---|
115
+ | **Workflow tier** | End-to-end, black-box test of a full LangGraph workflow | The complete document-review workflow: input document → final approval decision |
116
+ | **Agent tier** | Test of a specific deepagents agent or LangGraph node in isolation | The CRM-lookup agent node: input query → retrieved contact record |
117
+ | **LLM tier** | Test of a single prompt-response exchange | The classification prompt: input text → category label |
118
+
119
+ **Each tier requires fully independent evals and golden datasets** scoped per component (not shared across tiers). Input structure, expected output, and relevant test types differ substantially across tiers. Eval folders, golden datasets, and `eval.py` scripts MUST be scoped per component.
120
+
121
+ **Workflow-first strategy:** Testing SHOULD begin at the Workflow tier (highest cost-benefit: a single black-box eval covers the entire component stack). Drilling down to the Agent or LLM tier SHOULD only be done when a node or prompt is critical (high impact), complex (multi-step tool use), or difficult to debug at the workflow level.
122
+
123
+ All `test_types` values apply at all three tiers. Some have natural tier affinity (guidance, not restrictions):
124
+
125
+ | Test type | Natural tier affinity | Rationale |
126
+ |---|---|---|
127
+ | `prompt` | LLM tier, Agent tier | Prompt regression is most directly actionable at the level where the prompt template lives |
128
+ | `groundedness` | Agent tier (RAG node) | RAG retrieval happens at a specific node; groundedness is most precisely measured there |
129
+ | `adversarial` | Agent tier | Tool-invocation loops are the primary attack surface for injection and jailbreaks |
130
+
131
+ **Unit tests across tiers:** Apply at all three tiers with different mock setups (see [agentme-edr-141](141-ai-llm-development-standards.md) rule `04`, [agentme-edr-143](143-ai-agents-quality-standards.md) rule `04`, [agentme-edr-144](144-ai-workflow-development-standards.md) rule `10`).
132
+
133
+ #### 11-test-quality-progression
134
+
135
+ The test types form a **quality-progression DAG** that guides implementation priority and tech debt ordering — primarily for deciding which test types to implement first for the best quality signal.
136
+
137
+ This ordering is orthogonal to the Priority column in rule `05` (standalone business importance) and does NOT override it.
138
+
139
+ All edges are SHOULD relationships — advisory guidance for prioritization and tech debt conversations. They MUST NOT be treated as hard enforcement gates.
140
+
141
+ ```
142
+ [code-level] Unit Test
143
+ └──> [code-level] Integration Test
144
+ └──> Smoke
145
+ └──> Functional / Prompt
146
+ ├──> Safety
147
+ ├──> Adversarial
148
+ ├──> Groundedness
149
+ ├──> Explainability
150
+ ├──> Robustness
151
+ ├──> Fairness
152
+ └──> Repeatability
153
+ └──> Bias
154
+ ```
155
+
156
+ **Rationale per dependency:**
157
+
158
+ | Dependency | Rationale |
159
+ |---|---|
160
+ | Unit / Integration → Smoke | Code correctness is a prerequisite; a component that crashes or errors will produce meaningless eval signal |
161
+ | Smoke → Functional / Prompt | Smoke validates the critical subset; running full evals on a fundamentally broken component wastes LLM cost |
162
+ | Functional / Prompt → Safety, Adversarial, Groundedness, Explainability, Robustness, Fairness | A functionally broken component produces unreliable responsible-AI signals — a working baseline is required |
163
+ | Functional / Prompt → Repeatability | Measuring output variance is only meaningful when the component produces correct outputs under normal conditions |
164
+ | Repeatability → Bias | Bias scoring compares outputs across protected-attribute groups; if not repeatable, output differences may reflect sampling variance rather than protected-attribute influence |
165
+
166
+ **Fairness does NOT depend on Repeatability.** Fairness entries are per-entry LLM-as-judge tests, unaffected by cross-invocation variance.
167
+
168
+ **`human_review: true` is NOT part of this progression** — it is a per-entry modifier applicable at any stage.
115
169
 
116
170
  ## References
117
171
 
118
- - [agentme-edr-201](../data/201-ml-dataset-structure.md) — Golden dataset file layout, per-entry JSON format, `$schema` pointer, and schema-lint validation
119
- - [agentme-edr-151](151-ai-eval-standards.md) — AI eval core standards: eval folder structure and Makefile targets (rule `01`); LLM-as-judge binary scoring contract (rule `02`)
120
- - [agentme-edr-153](153-ai-eval-script.md) — AI eval script: `--type` filtering, entry-first loop, `mock_fixtures`, threshold enforcement, and MLflow conventions
121
- - [agentme-edr-154](154-ai-eval-report-format.md) — AI eval report format: per-type `report-<type>.md` that consumes this taxonomy's test types
122
- - [agentme-edr-155](155-ai-eval-repeatability.md) — AI eval repeatability: `REPEAT_COUNT` loop exception, scoring constants (`EVAL_MIN_ACCURACY_REPEATABILITY`, `REPEAT_SEMANTIC_SIMILARITY_SCORE`), scoring methods, `repeatability_accuracy` MLflow metric, report shape, and run cadence
123
- - [agentme-edr-126](126-pragmatic-hexagonal-architecture.md) — Rule `10`: `_mock` file naming and placement convention for mock adapters referenced by `mock_fixtures`
124
- - [agentme-edr-501](../governance/501-project-quality-standards.md) — Rule `09` tier-level testing requirements (the only mandated AI testing baseline)
125
- - [agentme-edr-303](../platform/303-common-targets.md) — Rule `03` `eval-<qualifier>` Makefile convention; rule `03`'s `test-smoke` (distinguished in rule `07`)
126
- - [agentme-edr-305](../platform/305-environment-variable-configuration.md) — Environment-configuration conventions referenced in rule `09`'s reproducibility disambiguation
127
- - [agentme-edr-141](141-ai-llm-development-standards.md) — LLM tier definition and mocking utilities referenced by the `mocks allowed` value
128
- - [agentme-edr-122](122-unit-test-requirements.md) — Unit test requirements underlying the Code-level rows
129
- - [agentme-edr-156](156-ai-eval-fairness-bias.md) — AI eval fairness/bias: `comparison_group` dataset structure, deferred group-scoring loop, scoring approaches, `fairness_accuracy`/`bias_accuracy` metrics, report shape, and cadence
172
+ - [agentme-edr-201](../data/201-ml-dataset-structure.md) — Golden dataset file layout and schema-lint validation
173
+ - [agentme-edr-151](151-ai-eval-standards.md) — Eval folder structure and LLM-as-judge scoring contract
174
+ - [agentme-edr-153](153-ai-eval-script.md) — Eval script: `--type` filtering, entry-first loop, threshold enforcement
175
+ - [agentme-edr-154](154-ai-eval-report-format.md) — Eval report format per test type
176
+ - [agentme-edr-155](155-ai-eval-repeatability.md) — Repeatability scoring constants, metrics, and run cadence
177
+ - [agentme-edr-126](126-pragmatic-hexagonal-architecture.md) — `_mock` file naming for mock adapters
178
+ - [agentme-edr-501](../governance/501-project-quality-standards.md) — Tier-level testing requirements
179
+ - [agentme-edr-303](../platform/303-common-targets.md) — `eval-<qualifier>` Makefile convention
180
+ - [agentme-edr-305](../platform/305-environment-variable-configuration.md) — Environment-configuration conventions
181
+ - [agentme-edr-141](141-ai-llm-development-standards.md) — LLM tier definition and mocking utilities
182
+ - [agentme-edr-122](122-unit-test-requirements.md) — Unit test requirements
183
+ - [agentme-edr-156](156-ai-eval-fairness-bias.md) — Fairness/bias eval loop, scoring, and metrics
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: agentme-edr-policy-153-ai-eval-script
3
- description: Defines eval.py script requirements for AI projects — entry-first eval loop, --type test-type filtering, --groups group filtering, mock_fixtures wiring, human entries, fairness/bias deferred group scoring, threshold enforcement, and MLflow experiment naming and port assignment. Use when implementing eval scripts. For eval folder structure see agentme-edr-151 rule 01. For the test type taxonomy and mock_fixtures envelope see agentme-edr-152. For mock file naming see agentme-edr-126 rule 10. For report format see agentme-edr-154. For repeatability loop exception see agentme-edr-155. For fairness/bias group scoring see agentme-edr-156.
3
+ description: Defines eval.py script requirements for AI projects — entry-first eval loop, --type test-type filtering, --groups group filtering, --human-review flag for manual-review entries, mock_fixtures wiring, human_review entries, bias deferred group scoring, fairness inline per-entry scoring, threshold enforcement, and MLflow experiment naming and port assignment. Use when implementing eval scripts. For eval folder structure see agentme-edr-151 rule 01. For the test type taxonomy and mock_fixtures envelope see agentme-edr-152. For mock file naming see agentme-edr-126 rule 10. For report format see agentme-edr-154. For repeatability loop exception see agentme-edr-155. For fairness and bias eval methodology see agentme-edr-156.
4
4
  apply-to: Python AI projects (LLM, Agent, or Workflow tier) that implement eval testing
5
5
  valid-from: 2026-07-07
6
6
  ---
@@ -25,15 +25,16 @@ For when evals are required per AI tier, see [agentme-edr-501](../governance/501
25
25
 
26
26
  Each `eval.py` script MUST:
27
27
 
28
- - Load the golden dataset from `golden_dataset/` in the same eval folder, following [agentme-edr-201](../data/201-ml-dataset-structure.md) and the entry envelope in [agentme-edr-152](152-ai-test-types-taxonomy.md) rule `02` (one JSON file per entry, `test_types` array, `input`, `expected_output`, optional `mock_fixtures`, optional `group`, optional `comparison_group`).
28
+ - Load the golden dataset from `golden_dataset/` in the same eval folder, following [agentme-edr-201](../data/201-ml-dataset-structure.md) and the entry envelope in [agentme-edr-152](152-ai-test-types-taxonomy.md) rule `02` (one JSON file per entry, `test_types` array, `input`, `expected_output`, optional `mock_fixtures`, optional `group`, optional `bias_group`).
29
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
+ - Accept an optional `--human-review` boolean CLI flag. When present, restrict the run to entries whose `human_review` field is `true` (regardless of `--type`). When omitted, entries with `human_review: true` are included in normal `--type` runs and their automated `test_types` are scored as usual — the human-review checklist is always exported for them.
30
31
  - Accept an optional `--groups=<name1>,<name2>,...` CLI argument. When present, restrict the filtered entry set to those whose `group` field matches any of the listed values (case-sensitive exact match); entries without a `group` field are excluded when `--groups` is active. When omitted, all entries from the `--type` filter are included regardless of `group`. The MLflow run MUST log a `groups_filter` tag containing the `--groups` value, or `"all"` when the argument is omitted.
31
- - **Fairness/bias deferred group scoring:** for entries whose `test_types` includes `fairness` or `bias`, the `fairness`/`bias` test_type MUST be skipped in the inline per-entry scoring step and the entry's `actual_output` buffered by `comparison_group`. Other test_types on the same entry (e.g. `functional`) are still scored inline normally. After the entry-first loop completes, score each comparison group by comparing its buffered outputs. See [agentme-edr-156](156-ai-eval-fairness-bias.md) for the full scoring loop, approach options, metrics, and report shape.
32
+ - **Bias deferred group scoring:** for entries whose `test_types` includes `bias`, the `bias` test_type MUST be skipped in the inline per-entry scoring step and the entry's `actual_output` buffered by `bias_group`. Other test_types on the same entry (e.g. `functional` or `fairness`) are still scored inline normally. After the entry-first loop completes, score each `bias` group by comparing its buffered outputs. **Fairness entries are scored inline** per-entry via LLM-as-judge against `expected_output`, identically to functional entries — this applies to fairness-only entries and to the fairness test type on combined `["fairness","bias"]` entries. See [agentme-edr-156](156-ai-eval-fairness-bias.md) for the full bias group-scoring loop, fairness per-entry scoring, approach options, metrics, and report shapes.
32
33
  - 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.
33
- - When an entry contains `mock_fixtures` ([agentme-edr-152](152-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-152](152-ai-test-types-taxonomy.md) rule `03`). How mock adapters are discovered and instantiated is left to the project; see [agentme-edr-126](126-pragmatic-hexagonal-architecture.md) rule `10` for the `_mock` file naming and placement convention.
34
+ - When an entry contains `mock_fixtures` ([agentme-edr-152](152-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 entries including those with `human_review: true`. `mock_fixtures` MUST NOT configure LLM adapters — the LLM call MUST be real (see [agentme-edr-152](152-ai-test-types-taxonomy.md) rule `03`). How mock adapters are discovered and instantiated is left to the project; see [agentme-edr-126](126-pragmatic-hexagonal-architecture.md) rule `10` for the `_mock` file naming and placement convention.
34
35
  - Run every component invocation against **real LLM providers** (not mocked responses), to capture model drift.
35
- - 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.
36
- - 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-154](154-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-501](../governance/501-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.
36
+ - For entries with `human_review: true`: invoke the component to capture `actual_output`, export each entry's `input`, `human_instructions`, and `actual_output` into a manual-review checklist (`report-human-review.md`). MUST NOT invoke an automated scorer and MUST NOT enforce a pass/fail threshold for the human-review step. Other `test_types` on the same entry (e.g. `functional`) are still scored automatically.
37
+ - 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-154](154-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-501](../governance/501-project-quality-standards.md) rule `07-statistical-models-must-have-eval-targets`. Entries with `human_review: true` have no threshold and do not trigger a non-zero exit.
37
38
  - 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-152](152-ai-test-types-taxonomy.md) rule `06`).
38
39
 
39
40
  **Example:**
@@ -82,11 +83,11 @@ with mlflow.start_run():
82
83
 
83
84
  actual_output = invoke_component(entry, graph)
84
85
 
86
+ # Export human-review checklist regardless of which --type is active
87
+ if entry.get("human_review"):
88
+ export_human_review(entry["human_instructions"], actual_output)
89
+
85
90
  for test_type in [t for t in entry["test_types"] if t in resolved_types]:
86
- if test_type == "human":
87
- export_human_review(entry, actual_output)
88
- continue
89
-
90
91
  score_val = score(test_type, actual_output, entry["expected_output"])
91
92
  results[test_type].append(score_val)
92
93
 
@@ -98,9 +99,6 @@ with mlflow.start_run():
98
99
 
99
100
  # Aggregate, report, and enforce thresholds per test type
100
101
  for test_type in resolved_types:
101
- if test_type == "human":
102
- continue
103
-
104
102
  accuracy = sum(results[test_type]) / len(results[test_type])
105
103
  mlflow.log_metric(f"{test_type}_accuracy", accuracy)
106
104
 
@@ -136,7 +134,7 @@ The MLflow **experiment** is scoped to the eval scenario: `<component>/<eval-nam
136
134
  - [agentme-edr-151](151-ai-eval-standards.md) — AI eval core standards: eval folder structure (rule `01`) and LLM-as-judge binary scoring contract (rule `02`)
137
135
  - [agentme-edr-154](154-ai-eval-report-format.md) — AI eval report format: `report-<type>.md` template, Wilson CI, and convergence analysis
138
136
  - [agentme-edr-155](155-ai-eval-repeatability.md) — AI eval repeatability: loop exception to rule `01`'s entry-first constraint, scoring methods, and cadence
139
- - [agentme-edr-156](156-ai-eval-fairness-bias.md) — AI eval fairness/bias: deferred group-scoring loop, `comparison_group` buffering, scoring approaches, and `fairness_accuracy`/`bias_accuracy` metrics
137
+ - [agentme-edr-156](156-ai-eval-fairness-bias.md) — AI eval fairness and bias: fairness per-entry inline scoring and `fairness_accuracy`; bias deferred `bias_group` group-scoring loop, approach options, and `bias_accuracy`
140
138
  - [agentme-edr-152](152-ai-test-types-taxonomy.md) — AI test types taxonomy: `test_types` enum, golden dataset entry envelope (including `mock_fixtures`), and mocking constraints per type
141
139
  - [agentme-edr-126](126-pragmatic-hexagonal-architecture.md) — Rule `10`: `_mock` file naming and placement convention for mock adapters used in `mock_fixtures`
142
140
  - [agentme-edr-201](../data/201-ml-dataset-structure.md) — ML dataset structure, per-entry JSON format, and schema-lint validation for golden datasets
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: agentme-edr-policy-154-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-153. For repeatability report shape see agentme-edr-155 rule 02.
3
+ description: Defines the eval report format for AI projects — report-<type>.md template, Wilson score confidence interval, convergence analysis, and the human-review checklist artifact (report-human-review.md for entries with human_review: true). Use when generating eval reports from eval scripts. For the eval script that produces these reports see agentme-edr-153. For repeatability report shape see agentme-edr-155 rule 02.
4
4
  apply-to: Python AI projects (LLM, Agent, or Workflow tier) that implement eval testing
5
5
  valid-from: 2026-07-07
6
6
  ---
@@ -21,7 +21,7 @@ What format should eval reports follow, and what constraints apply to how they a
21
21
 
22
22
  #### 01-eval-report-file
23
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).
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. Entries with `human_review: true` do not produce a metrics report (see below).
25
25
 
26
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
27
 
@@ -100,7 +100,7 @@ Where $\hat{p}$ is observed accuracy and $n$ is sample count. Accuracy and F1 ar
100
100
  - If either exceeds: "Add more samples — metrics have not yet stabilized"
101
101
  - Projects MAY customize threshold (document in Makefile/README)
102
102
 
103
- Exclude from `report-human.md` (no automated metrics).
103
+ Exclude from `report-human-review.md` (no automated metrics).
104
104
 
105
105
  **Filled-in example** (`evals/workflow-document-review/eval-basic/report-functional.md` for a document review workflow):
106
106
 
@@ -162,7 +162,7 @@ xychart-beta
162
162
  ```
163
163
  ```
164
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.
165
+ **Human-review checklist artifact:** entries with `human_review: true` do not produce a metrics report. Instead, the eval script produces `report-human-review.md` — a checklist artifact listing, per entry, its `input`, `human_instructions`, and the captured `actual_output` — with no Overall Results table, threshold, or PASS/FAIL section, since human-review entries MUST NOT be auto-scored. This file is generated whenever any eval run encounters entries with `human_review: true`, or when `--human-review` is passed as a standalone flag (see [agentme-edr-153](153-ai-eval-script.md) rule `01`).
166
166
 
167
167
  ## References
168
168
 
@@ -29,7 +29,7 @@ Entries whose `test_types` includes `repeatability` are exempt from [agentme-edr
29
29
  - `EVAL_MIN_ACCURACY_REPEATABILITY` — minimum fraction of repeatability entries that must PASS for the eval to exit 0.
30
30
  - `REPEAT_SEMANTIC_SIMILARITY_SCORE` — minimum average pairwise cosine similarity for a single entry to PASS; declared only when using semantic-similarity scoring.
31
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.
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` MUST be `null` for repeatability entries (enforced by [agentme-edr-152](152-ai-test-types-taxonomy.md) Schema Rule C).
33
33
 
34
34
  **Choosing the scoring method:** Two approaches are supported, declared as a constant in `eval.py`:
35
35
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: agentme-edr-policy-156-ai-eval-fairness-and-bias
3
- description: Defines the fairness and bias eval methodology comparison_group dataset structure, deferred group-scoring loop (distinct from the repeatability loop exception in agentme-edr-155), semantic-similarity and LLM-as-judge scoring approaches, fairness_accuracy/bias_accuracy metrics, report shape, and release cadence. Use when implementing fairness or bias evals. For the test type taxonomy and dataset envelope see agentme-edr-152. For the eval script entry-first loop see agentme-edr-153. For the LLM-as-judge binary output contract see agentme-edr-151 rule 02. For report format base template see agentme-edr-154.
3
+ description: Defines two distinct eval methodologies — (1) fairness: independent per-entry policy stress-tests scored inline via LLM-as-judge against expected_output, with fairness_accuracy as a per-entry pass rate; (2) bias: EU Charter/GDPR Art.9 protected-attribute consistency checks using deferred bias_group group scoring (semantic similarity or LLM-as-judge), with bias_accuracy as a per-group pass rate. Also names the six bias types as dataset-authoring guidance. Use when implementing fairness or bias evals. For the test type taxonomy and dataset envelope see agentme-edr-152. For the eval script entry-first loop see agentme-edr-153. For the LLM-as-judge binary output contract see agentme-edr-151 rule 02. For report format base template see agentme-edr-154.
4
4
  apply-to: Python AI projects (LLM, Agent, or Workflow tier) that implement fairness or bias eval testing
5
5
  valid-from: 2026-08-18
6
6
  ---
@@ -9,109 +9,169 @@ valid-from: 2026-08-18
9
9
 
10
10
  ## Context and Problem Statement
11
11
 
12
- Fairness and bias testing requires running multiple demographic variants of the same scenario and checking whether the AI system produces consistent outputs regardless of protected attributes such as gender, race, age, nationality, or religion. The standard entry-first eval loop (agentme-edr-153) invokes each entry once and scores it inline — but fairness and bias scoring is inter-entry: it compares outputs across a group of variants after all have been invoked.
12
+ Fairness and bias are two distinct responsible-AI test types that address different concerns and require different eval architectures:
13
13
 
14
- How should fairness and bias evals be structured, scored, and reported?
14
+ - **Fairness** tests whether the system handles cases for diverse non-protected groups (location, employment type, economic condition, collateral type, etc.) correctly per documented business policies. Each fairness entry is independent — it tests a specific group scenario against a known expected outcome, exactly like a functional test.
15
+ - **Bias** tests whether EU Charter / GDPR Art.9 protected attributes (gender, racial/ethnic origin, age, disability, religion, sexual orientation, political opinion) influence system outcomes. Bias requires running the same scenario with only protected attributes changed and then comparing outputs across the variant group — an inter-entry operation the standard inline scoring loop cannot perform.
16
+
17
+ How should these two structurally different evals be implemented, scored, and reported?
15
18
 
16
19
  ## Decision Outcome
17
20
 
18
- **Group demographic variants by `comparison_group`, invoke each entry once (entry-first loop unchanged), buffer outputs per group during the loop, then score groups post-loop by comparing all buffered outputs using semantic similarity or LLM-as-judge.**
21
+ **Fairness entries are scored inline per-entry via LLM-as-judge against `expected_output` (identical to functional scoring). Bias entries are grouped by `bias_group`, buffered during the entry-first loop, and scored post-loop by comparing all variants' outputs using semantic similarity or LLM-as-judge.**
19
22
 
20
23
  ### Details
21
24
 
22
- #### 01-comparison-group-dataset-structure
25
+ #### 01-dataset-entry-structure
26
+
27
+ Fairness and bias entries MUST follow different shapes as defined in the sub-rules below.
23
28
 
24
- Entries whose `test_types` includes `fairness` or `bias` MUST carry a `comparison_group` field (string or integer). This field is required at lint-time via `dataset.schema.json` Rule A (see [agentme-edr-152](152-ai-test-types-taxonomy.md) rule `02`).
29
+ ##### Fairness entries
25
30
 
26
- All entries sharing the same `comparison_group` value form one **comparison set**: they represent the same decision scenario varying only in protected attributes within `input` (gender, race, age, nationality, religion, etc.). Every other aspect of `input` — facts, context, question phrasing — MUST be identical across variants.
31
+ Fairness entries test whether the system handles a specific group-scenario case correctly per documented policy. Each entry is **independent** no grouping with other entries, no protected-attribute variants.
27
32
 
28
- - A comparison group MUST have **≥ 2 entries** (enforced at eval-time see rule `02`); SHOULD have 3–5 to cover common demographic dimensions.
29
- - `expected_output` MUST be `null` when `test_types` contains only `fairness` and/or `bias` (and optionally `repeatability`) fairness/bias scoring ignores `expected_output` and compares outputs across the group. When the entry also carries other automated types (e.g. `["functional", "fairness"]`), `expected_output` MUST be non-null for those types (enforced by `dataset.schema.json` Rule B see [agentme-edr-152](152-ai-test-types-taxonomy.md) rule `02`).
30
- - `group` and `comparison_group` are independent fields: an entry MAY carry both (e.g. `group="hiring-scenarios"`, `comparison_group=3`). `group` is a thematic label used for `--groups` filtering; `comparison_group` is the comparison key.
33
+ - `bias_group` MUST NOT be present on fairness-only entries; it is allowed (and required by Schema Rule A) when `bias` is also in `test_types`.
34
+ - `expected_output` MUST be non-null — it is the expected decision or outcome for this specific group scenario. Enforced by `dataset.schema.json` Rule B (see [agentme-edr-152](152-ai-test-types-taxonomy.md) rule `02`).
35
+ - The `group` field MAY be used for thematic filtering (e.g. `"group": "rural-scenarios"`).
31
36
 
32
- **Example — fairness-only entry:**
37
+ **Example — fairness entry (rural farmer loan):**
33
38
 
34
39
  ```json
35
40
  {
36
41
  "$schema": "../dataset.schema.json",
37
42
  "test_types": ["fairness"],
38
- "group": "hiring-scenarios",
39
- "comparison_group": 1,
40
- "input": {"role": "software engineer", "experience_years": 5, "gender": "female"},
41
- "expected_output": null
43
+ "group": "non-standard-collateral",
44
+ "input": {"employment_type": "rural_farmer", "collateral_type": "farm_land", "loan_amount": 50000},
45
+ "expected_output": {"decision": "approved", "reason": "farm land accepted as collateral per policy P-42"}
42
46
  }
43
47
  ```
44
48
 
45
- **Example — mixed functional + fairness entry (`expected_output` required for functional):**
49
+ **Example — combined functional + fairness entry (explicit policy decline):**
46
50
 
47
51
  ```json
48
52
  {
49
53
  "$schema": "../dataset.schema.json",
50
54
  "test_types": ["functional", "fairness"],
51
- "group": "hiring-scenarios",
52
- "comparison_group": 2,
53
- "input": {"role": "software engineer", "experience_years": 5, "gender": "male"},
54
- "expected_output": {"decision": "proceed_to_interview"}
55
+ "group": "student-institution-scope",
56
+ "input": {"employment_type": "self_employed", "institution_type": "student_credit_union", "loan_amount": 2000},
57
+ "expected_output": {"decision": "declined", "reason": "policy: student credit union does not extend loans to non-students"}
58
+ }
59
+ ```
60
+
61
+ ##### Bias entries
62
+
63
+ Bias entries verify that EU Charter / GDPR Art.9 protected attributes do not influence outcomes. Each comparison set holds **≥ 2 variants of the same scenario**, differing only in protected attributes within `input`. Every other aspect — facts, context, question phrasing — MUST be identical across variants.
64
+
65
+ - `bias_group` MUST be present (string or integer); required at lint-time via `dataset.schema.json` Rule A (see [agentme-edr-152](152-ai-test-types-taxonomy.md) rule `02`).
66
+ - `expected_output` is IGNORED for bias scoring — bias compares outputs across the group, not against a fixed value. When the entry carries only `bias` (or `bias` + `repeatability`), `expected_output` MUST be `null` (enforced by Schema Rule C). When the entry also carries `fairness`, `expected_output` MUST be non-null (required by fairness, enforced by Schema Rule B) and is IGNORED for bias scoring.
67
+ - A bias group MUST have **≥ 2 entries**; SHOULD have 3–5 to cover common demographic dimensions.
68
+ - `group` and `bias_group` are independent: an entry MAY carry both (e.g. `group="hiring-scenarios"`, `bias_group=3`).
69
+
70
+ **Example — bias comparison set (same loan, protected attribute varies):**
71
+
72
+ ```json
73
+ {
74
+ "$schema": "../dataset.schema.json",
75
+ "test_types": ["bias"],
76
+ "group": "loan-approval",
77
+ "bias_group": 1,
78
+ "input": {"applicant_name": "Alice", "gender": "female", "income": 3000, "loan_amount": 10000},
79
+ "expected_output": null
80
+ }
81
+ ```
82
+
83
+ ```json
84
+ {
85
+ "$schema": "../dataset.schema.json",
86
+ "test_types": ["bias"],
87
+ "group": "loan-approval",
88
+ "bias_group": 1,
89
+ "input": {"applicant_name": "Bob", "gender": "male", "income": 3000, "loan_amount": 10000},
90
+ "expected_output": null
55
91
  }
56
92
  ```
57
93
 
58
- #### 02-deferred-group-scoring-loop
94
+ **Example — combined fairness + bias entry (policy check AND protected-attribute consistency):**
59
95
 
60
- The entry-first loop from [agentme-edr-153](153-ai-eval-script.md) rule `01` applies unchanged: each entry is invoked exactly once. Fairness and bias scoring is deferred — it does not happen inline per entry.
96
+ ```json
97
+ {
98
+ "$schema": "../dataset.schema.json",
99
+ "test_types": ["fairness", "bias"], // expected_output used by fairness; ignored by bias
100
+ "group": "loan-approval",
101
+ "bias_group": 2,
102
+ "input": {"applicant_name": "Alice", "gender": "female", "employment_type": "rural_farmer", "collateral_type": "farm_land", "loan_amount": 50000},
103
+ "expected_output": {"decision": "approved", "reason": "farm land accepted as collateral per policy P-42"}
104
+ }
105
+ ```
106
+
107
+ ```json
108
+ {
109
+ "$schema": "../dataset.schema.json",
110
+ "test_types": ["fairness", "bias"], // each variant is fairness-scored against its own expected_output
111
+ "group": "loan-approval",
112
+ "bias_group": 2,
113
+ "input": {"applicant_name": "Bob", "gender": "male", "employment_type": "rural_farmer", "collateral_type": "farm_land", "loan_amount": 50000},
114
+ "expected_output": {"decision": "approved", "reason": "farm land accepted as collateral per policy P-42"}
115
+ }
116
+ ```
117
+
118
+ #### 02-bias-deferred-group-scoring-loop
119
+
120
+ The entry-first loop from [agentme-edr-153](153-ai-eval-script.md) rule `01` applies unchanged: each entry is invoked exactly once. **Fairness entries are scored inline** (like functional). **Bias scoring is deferred** — it does not happen inline per entry.
61
121
 
62
122
  `eval.py` MUST:
63
123
 
64
- 1. During the entry-first loop: buffer each entry's `actual_output` keyed by `(test_type, comparison_group)` when `test_type` is `fairness` or `bias`. Skip inline scoring for these test types on that entry. Other test types on the same entry (e.g. `functional`) are still scored inline normally.
65
- 2. After the entry-first loop completes: iterate over each `(test_type, comparison_group)` bucket and score the group by comparing all buffered outputs (see rule `03`).
66
- 3. When `--groups` filtering ([agentme-edr-153](153-ai-eval-script.md) rule `01`) reduces a comparison group to fewer than 2 variants: emit a warning identifying the group, skip it, and exclude it from the `fairness_accuracy`/`bias_accuracy` denominator. Do not exit with an error.
124
+ 1. During the entry-first loop: for entries whose `test_types` includes `bias`, buffer each entry's `actual_output` keyed by `(test_type, bias_group)`. Skip inline scoring for the `bias` test type on that entry. Other test types on the same entry (e.g. `functional` or `fairness`) are still scored inline normally.
125
+ 2. After the entry-first loop completes: iterate over each `(bias, bias_group)` bucket and score the group by comparing all buffered outputs (see rule `03`).
126
+ 3. When `--groups` filtering ([agentme-edr-153](153-ai-eval-script.md) rule `01`) reduces a `bias` group to fewer than 2 variants: emit a warning identifying the group, skip it, and exclude it from the `bias_accuracy` denominator. MUST NOT exit with an error.
67
127
 
68
128
  ```python
69
129
  from collections import defaultdict
70
130
 
71
- # Keyed by (test_type, comparison_group); populated during the entry-first loop
72
- fairness_bias_buffer = defaultdict(lambda: defaultdict(list))
131
+ # Keyed by bias_group; populated during the entry-first loop for bias only
132
+ bias_buffer = defaultdict(list)
73
133
 
74
134
  # --- Inside the entry-first loop ---
75
135
  for entry in entries:
76
136
  actual_output = invoke_component(entry, graph)
77
137
 
78
138
  for test_type in [t for t in entry["test_types"] if t in resolved_types]:
79
- if test_type in ("fairness", "bias"):
80
- # Buffer for deferred group scoring; comparison_group guaranteed by schema lint
81
- fairness_bias_buffer[test_type][entry["comparison_group"]].append(actual_output)
139
+ if test_type == "bias":
140
+ # Buffer for deferred group scoring; bias_group guaranteed by schema lint
141
+ bias_buffer[entry["bias_group"]].append(actual_output)
82
142
  continue # scored post-loop
83
143
  if test_type == "human":
84
144
  export_human_review(entry, actual_output)
85
145
  continue
146
+ # fairness, functional, smoke, etc. all scored inline
86
147
  score_val = score(test_type, actual_output, entry["expected_output"])
87
148
  results[test_type].append(score_val)
88
149
 
89
150
  # --- After the entry-first loop ---
90
- for test_type in ("fairness", "bias"):
91
- if test_type not in resolved_types:
92
- continue
93
- for cg, outputs in fairness_bias_buffer[test_type].items():
151
+ if "bias" in resolved_types:
152
+ for bg, outputs in bias_buffer.items():
94
153
  if len(outputs) < 2:
95
- print(f"WARNING: comparison_group {cg!r} has {len(outputs)} variant(s) — skipping")
154
+ print(f"WARNING: bias_group {bg!r} has {len(outputs)} variant(s) — skipping")
96
155
  continue
97
156
  group_score = score_group(outputs) # returns 1 (consistent) or 0 (inconsistent)
98
- results[test_type].append(group_score)
157
+ results["bias"].append(group_score)
99
158
  ```
100
159
 
101
- #### 03-scoring-approaches
160
+ #### 03-bias-scoring-approaches
102
161
 
103
- Two approaches are available. The developer MUST hardcode the chosen approach directly in `eval.py` — no scoring method constant is required by this Policy. Choose based on output type:
162
+ Two approaches are available for bias group scoring. The developer MUST hardcode the chosen approach directly in `eval.py`. Choose based on output type:
104
163
 
105
164
  - **Semantic similarity** — embed all outputs for the comparison group into vectors; compute the average pairwise cosine similarity; the group passes (score = 1) if the average meets or exceeds a developer-defined threshold constant, otherwise fails (score = 0). SHOULD be used for short structured outputs (classification labels, scores, decisions).
106
-
107
165
  - **LLM-as-judge** — provide all group outputs to a judge LLM (at low or zero temperature) that returns `1` (consistent) or `0` (inconsistent) following [agentme-edr-151](151-ai-eval-standards.md) rule `02`'s binary output contract. The invocation strategy (single call with all outputs, or pairwise calls) is left to the developer. SHOULD be used for free-text or multi-field structured outputs where vector distance is an unreliable proxy for agreement.
108
166
 
109
167
  Both approaches MUST produce a binary score per comparison group.
110
168
 
169
+ **Fairness scoring** does not use either approach above — it uses the same LLM-as-judge scoring as functional evals: the judge receives `actual_output` and `expected_output` for a single entry and returns `1` (pass) or `0` (fail) per [agentme-edr-151](151-ai-eval-standards.md) rule `02`.
170
+
111
171
  #### 04-metrics-and-thresholds
112
172
 
113
- - **`fairness_accuracy`** = fraction of `fairness` comparison groups that PASS (score = 1). Denominator = groups with 2 variants after `--groups` filtering; skipped groups are excluded.
114
- - **`bias_accuracy`** = same metric scoped to `bias` comparison groups. An entry whose `test_types` is `["fairness", "bias"]` contributes its `comparison_group` to both denominators independently the same group comparison result counts toward both metrics.
173
+ - **`fairness_accuracy`** = fraction of `fairness` entries that PASS (LLM-as-judge score = 1). Denominator = all fairness entries evaluated in the run. Computed inline during the entry-first loop, identically to `functional_accuracy`.
174
+ - **`bias_accuracy`** = fraction of `bias` groups that PASS (score = 1). Denominator = `bias_group` values with 2 variants after `--groups` filtering; skipped groups are excluded.
115
175
 
116
176
  Both metrics MUST be logged to MLflow. Thresholds MUST be declared as constants in `eval.py` following [agentme-edr-153](153-ai-eval-script.md) rule `01`'s naming convention:
117
177
 
@@ -122,33 +182,52 @@ EVAL_MIN_ACCURACY_BIAS = 0.80
122
182
 
123
183
  `eval.py` MUST exit non-zero if either metric falls below its threshold when the corresponding test type is evaluated.
124
184
 
125
- **Metrics note:** fairness/bias scoring ignores `expected_output` entirely; all comparison groups are implicitly expected-pass. Per [agentme-edr-151](151-ai-eval-standards.md) rule `02`: Recall = `fairness_accuracy`, Precision = 1 (no false positives), F1 = 2 · `fairness_accuracy` / (1 + `fairness_accuracy`). The Wilson score confidence interval MUST use **group count** as n (not entry count).
185
+ **Metrics note bias:** scoring ignores `expected_output` entirely (including on combined `["fairness","bias"]` entries); all bias groups are implicitly expected-pass. Per [agentme-edr-151](151-ai-eval-standards.md) rule `02`: Recall = `bias_accuracy`, Precision = 1 (no false positives), F1 = 2 · `bias_accuracy` / (1 + `bias_accuracy`). The Wilson score confidence interval MUST use **group count** as n (not entry count).
186
+
187
+ **Metrics note — fairness:** follows the same Wilson CI and F1 formula as functional evals, using **entry count** as n.
126
188
 
127
189
  #### 05-report-shape
128
190
 
129
- `report-fairness.md` and `report-bias.md` MUST follow the [agentme-edr-154](154-ai-eval-report-format.md) rule `01` template with these adaptations:
191
+ `report-fairness.md` MUST follow the [agentme-edr-154](154-ai-eval-report-format.md) rule `01` standard per-entry template with no structural adaptations — fairness is scored per entry like functional, so the standard table applies directly.
192
+
193
+ `report-bias.md` MUST follow the [agentme-edr-154](154-ai-eval-report-format.md) rule `01` template with these adaptations:
130
194
 
131
195
  - **Header:** MUST add `Scoring approach: <semantic_similarity | llm_judge>`, `Groups evaluated: <n>`, and `Groups skipped: <n>` lines alongside the standard Date / Dataset / Script / Thresholds lines.
132
- - **Overall Results table:** MUST report `fairness_accuracy` / `bias_accuracy` with Wilson score CI (n = group count), threshold, and PASS/FAIL status. MUST include F1, Precision, and Recall rows.
133
- - **Per-comparison-group table** (mandatory, replaces the standard per-item table):
196
+ - **Overall Results table:** MUST report `bias_accuracy` with Wilson score CI (n = group count), threshold, and PASS/FAIL status. MUST include F1, Precision, and Recall rows.
197
+ - **Per-bias-group table** (mandatory, replaces the standard per-item table):
134
198
 
135
- | `comparison_group` | Variants | Entry IDs | Output summaries | Consistent |
199
+ | `bias_group` | Variants | Entry IDs | Output summaries | Consistent |
136
200
  |---|---|---|---|---|
137
201
  | 1 | 3 | e01, e02, e03 | "approved / approved / denied" | ✗ |
138
202
  | 2 | 2 | e04, e05 | "proceed / proceed" | ✓ |
139
203
 
140
- - **Per-`group` thematic breakdown** (optional): the developer MAY add a section grouping comparison groups by their `group` label and reporting accuracy per label. This is not mandated by this Policy.
204
+ - **Per-`group` thematic breakdown** (optional): the developer MAY add a section grouping bias groups by their `group` label and reporting accuracy per label.
141
205
 
142
206
  #### 06-cadence
143
207
 
144
- `make eval-fairness` and `make eval-bias` MUST be scheduled at **release cadence** rather than on every commit — consistent with [agentme-edr-155](155-ai-eval-repeatability.md) rule `02`'s cadence for repeatability. Each comparison group requires one real LLM call per variant (plus the judge call when using LLM-as-judge), making these evals comparable in cost to a repeatability run.
208
+ `make eval-bias` MUST be scheduled at **release cadence** rather than on every commit — consistent with [agentme-edr-155](155-ai-eval-repeatability.md) rule `02`'s cadence for repeatability. Each comparison group requires one real LLM call per variant (plus the judge call when using LLM-as-judge), making bias evals comparable in cost to a repeatability run.
209
+
210
+ `make eval-fairness` cadence is a **project decision** — because fairness is scored per-entry like a functional eval, teams MAY run it at PR cadence or release cadence depending on the size of the fairness golden dataset and the criticality of the scenarios covered. This Policy does not mandate a cadence.
211
+
212
+ #### 07-bias-types-guidance
213
+
214
+ The following six bias types guide dataset authors when designing bias entries. They are **documentation guidance only** — they are NOT a required field in the golden dataset entry JSON. Dataset authors SHOULD ensure their bias golden dataset covers relevant types for their component.
215
+
216
+ | Bias Type | Definition | Dataset design hint |
217
+ |---|---|---|
218
+ | **Historical** | Model reproduces past societal disparities encoded in training data (e.g. gender pay gap reflected in salary recommendations) | Include protected-attribute variants for decisions where historical data is known to be skewed |
219
+ | **Representation** | Training data underrepresents certain groups, causing worse performance for them (e.g. speech recognition accuracy gaps by accent/dialect) | Include variants for minority or underrepresented demographic groups |
220
+ | **Measurement** | Proxies used as labels or features correlate with protected attributes (e.g. zip code as a credit proxy) | Design variants that test proxy features that may encode protected attributes |
221
+ | **Aggregation** | Model trained on aggregated data ignores subgroup differences, harming minority groups (e.g. one-size-fits-all medical thresholds) | Include variants for subgroups that may have different ground-truth distributions |
222
+ | **Evaluation** | Benchmarks used to validate the model are themselves biased, making bias invisible in standard metrics | Supplement standard eval entries with adversarial protected-attribute variants not present in training benchmarks |
223
+ | **Deployment** | Feedback loops in production amplify bias over time (e.g. recommendation systems that reinforce existing preferences) | Include variants that simulate cold-start or minority-preference scenarios |
145
224
 
146
225
  ## References
147
226
 
148
- - [agentme-edr-152](152-ai-test-types-taxonomy.md) — AI test types taxonomy: `fairness` and `bias` test type definitions (rule `05`), golden dataset entry envelope including `group`, `comparison_group`, and `expected_output` schema rules (rule `02`)
149
- - [agentme-edr-153](153-ai-eval-script.md) — AI eval script: entry-first loop (rule `01`), `--groups` CLI argument, and deferred group-scoring note for fairness/bias
150
- - [agentme-edr-151](151-ai-eval-standards.md) — AI eval core standards: LLM-as-judge binary output contract (rule `02`)
151
- - [agentme-edr-154](154-ai-eval-report-format.md) — AI eval report format: base template (rule `01`) that `report-fairness.md`/`report-bias.md` adapt
152
- - [agentme-edr-155](155-ai-eval-repeatability.md) — AI eval repeatability: release cadence convention (rule `02`) referenced by rule `06`
227
+ - [agentme-edr-152](152-ai-test-types-taxonomy.md) — AI test types taxonomy: `fairness` and `bias` test type definitions (rule `05`), dataset entry envelope including `bias_group` and `expected_output` Schema Rules A, B, and C (rule `02`)
228
+ - [agentme-edr-153](153-ai-eval-script.md) — AI eval script: entry-first loop (rule `01`), `--groups` CLI argument, and bias deferred group-scoring; fairness scored inline
229
+ - [agentme-edr-151](151-ai-eval-standards.md) — AI eval core standards: LLM-as-judge binary output contract (rule `02`) used by both fairness (per-entry) and bias (per-group)
230
+ - [agentme-edr-154](154-ai-eval-report-format.md) — AI eval report format: standard per-entry template for `report-fairness.md`; adapted group-comparison template for `report-bias.md`
231
+ - [agentme-edr-155](155-ai-eval-repeatability.md) — AI eval repeatability: release cadence convention (rule `02`) referenced by rule `06` for bias
153
232
  - [agentme-edr-201](../data/201-ml-dataset-structure.md) — ML dataset structure: per-entry JSON format and schema-lint validation for golden datasets
154
233
  - [agentme-edr-501](../governance/501-project-quality-standards.md) — Project quality standards: when evals are required per AI tier (rule `09`) and threshold enforcement (rule `07`)
@@ -204,17 +204,18 @@ Use this dependency set.
204
204
  },
205
205
  "homepage": "https://github.com/[owner]/[repo]#readme",
206
206
  "devDependencies": {
207
- "@eslint/eslintrc": "^3.3.1",
208
- "@stutzlab/eslint-config": "^3.2.1",
207
+ "@stutzlab/eslint-config": "^4.3.0",
209
208
  "@tsconfig/node24": "^24.0.1",
210
209
  "@types/jest": "^29.5.14",
211
- "@typescript-eslint/eslint-plugin": "^8.31.0",
212
- "@typescript-eslint/parser": "^8.31.0",
213
- "esbuild": "^0.20.0",
214
- "eslint": "^9.25.1",
210
+ "@types/node": "^22.0.0",
211
+ "@typescript-eslint/eslint-plugin": "^8.67.0",
212
+ "@typescript-eslint/parser": "^8.67.0",
213
+ "esbuild": "^0.28.2",
214
+ "eslint": "^10.0.0",
215
+ "eslint-plugin-functional": "^10.0.0",
215
216
  "jest": "^29.7.0",
216
217
  "ts-jest": "^29.4.0",
217
- "typescript": "^5.9.0"
218
+ "typescript": "^6.0.3"
218
219
  }
219
220
  }
220
221
  ```
@@ -231,7 +232,8 @@ Keep `package.json` without `"type": "module"`. Use `eslint.config.mjs` as the E
231
232
  "rootDir": "src",
232
233
  "declaration": true,
233
234
  "declarationMap": true,
234
- "sourceMap": true
235
+ "sourceMap": true,
236
+ "types": ["node", "jest"]
235
237
  },
236
238
  "include": ["src/**/*"],
237
239
  "exclude": ["node_modules", "dist"]
@@ -267,30 +269,21 @@ This avoids the deprecated `globals['ts-jest']` configuration style while forcin
267
269
  **`lib/eslint.config.mjs`** (ESLint 9 flat config format):
268
270
 
269
271
  ```js
270
- import path from 'node:path';
271
- import { fileURLToPath } from 'node:url';
272
- import { FlatCompat } from '@eslint/eslintrc';
273
272
  import baseConfig from '@stutzlab/eslint-config';
274
273
 
275
- const __filename = fileURLToPath(import.meta.url);
276
- const __dirname = path.dirname(__filename);
277
-
278
- const compat = new FlatCompat({
279
- baseDirectory: __dirname,
280
- });
281
-
282
274
  export default [
283
- ...compat.config(baseConfig),
275
+ ...baseConfig,
284
276
  {
285
277
  files: ['src/**/*.ts'],
286
278
  languageOptions: {
287
279
  parserOptions: {
288
280
  project: ['./tsconfig.json'],
289
- tsconfigRootDir: __dirname,
281
+ tsconfigRootDir: import.meta.dirname,
290
282
  },
291
283
  },
292
284
  },
293
285
  ];
286
+ ];
294
287
  ```
295
288
 
296
289
  Do not name this file `eslint.config.js` unless the generated package also opts into ESM with `"type": "module"`, because that produces Node.js warnings and conflicts with the recommended Jest CommonJS setup.
@@ -9,6 +9,7 @@ Propose changes via pull request. All changes must be verified for clarity and n
9
9
  Foundational standards, principles, and guidelines.
10
10
 
11
11
  - [150-plan-mode-consistency](principles/skills/150-plan-mode-consistency/SKILL.md) - **Plan mode consistency** — MANDATORY skill for ANY planning activity (plan, design, propose, outline, draft, brainstorm, architect). Read and follow in full before any execution begins. Must be read from XDRS even when not in `.agents/skills`. *(skill)*
12
+ - [151-write-user-story](principles/skills/151-write-user-story/SKILL.md) - **Write user stories** — Write, refine, elaborate, study or develop the contents of a user story used to create a unit of work for an agile team via targeted follow-up questions, vertical-slice splits, and the standard story output template. *(skill)*
12
13
  - [agentme-edr-012](principles/012-continuous-xdr-enrichment.md) - **Continuous xdr improvement policy** - Promote recurring delivery lessons into reusable XDRs
13
14
  - [agentme-edr-016](principles/016-cross-language-module-structure.md) - **Cross-language module structure** - Organize modules consistently across supported languages
14
15
  - [agentme-edr-017](principles/017-skill-testing.md) - **skill testing** - Mandates a `SKILL.test.md` co-located with every skill in scopes that follow agentme; defines test scenario format (trigger, expected behaviour, assertions) and requires execution before merging any skill change *(includes skill: [200-run-skill-tests](application/skills/200-run-skill-tests/SKILL.md))*
@@ -55,11 +56,11 @@ Standards for building LLM, Agent, and Workflow components.
55
56
  Standards for eval datasets, scripts, reports, and test type taxonomy.
56
57
 
57
58
  - [agentme-edr-151](application/151-ai-eval-standards.md) - **AI eval core standards** - Eval folder structure and Makefile interface; LLM-as-judge binary scoring contract applicable to all AI tiers and test types
58
- - [agentme-edr-152](application/152-ai-test-types-taxonomy.md) - **AI test types taxonomy** - Names AI test types (`functional`, `safety`, `smoke`, `repeatability`, `adversarial`, `fairness`, `bias`, and 5 others) with group, objective, mocking constraint, and relevance, and defines the shared golden dataset entry envelope
59
+ - [agentme-edr-152](application/152-ai-test-types-taxonomy.md) - **AI test types taxonomy** - Names AI test types (`functional`, `safety`, `smoke`, `repeatability`, `adversarial`, `fairness`, `bias`, and 5 others) with objective, mocking constraint, and relevance, and defines the shared golden dataset entry envelope
59
60
  - [agentme-edr-153](application/153-ai-eval-script.md) - **AI eval script** - eval.py requirements: entry-first loop, --type filtering, mock_fixtures wiring, human entries, threshold enforcement, and MLflow experiment conventions
60
61
  - [agentme-edr-154](application/154-ai-eval-report-format.md) - **AI eval report format** - report-<type>.md template, Wilson score confidence interval, convergence analysis, and human-type checklist artifact
61
62
  - [agentme-edr-155](application/155-ai-eval-repeatability.md) - **AI eval repeatability** - Repeatability test type: REPEAT_COUNT loop exception, semantic-similarity and LLM-as-judge scoring, repeatability_accuracy metric, report shape, and run cadence
62
- - [agentme-edr-156](application/156-ai-eval-fairness-bias.md) - **AI eval fairness and bias** - Defines the fairness/bias group-comparison eval methodology: comparison_group dataset structure, deferred group-scoring loop, semantic-similarity and LLM-as-judge scoring approaches, fairness_accuracy/bias_accuracy metrics, and report shape
63
+ - [agentme-edr-156](application/156-ai-eval-fairness-bias.md) - **AI eval fairness and bias** - Defines two distinct eval methodologies: fairness (per-entry policy stress-test, inline LLM-as-judge, fairness_accuracy); bias (EU Charter/GDPR protected-attribute group-comparison, deferred scoring, bias_accuracy); and six bias types as dataset-authoring guidance
63
64
 
64
65
  ## Data
65
66
 
@@ -88,7 +88,7 @@ jobs:
88
88
  permissions:
89
89
  contents: write
90
90
  steps:
91
- - uses: actions/checkout@v3
91
+ - uses: actions/checkout@v4
92
92
  with:
93
93
  fetch-depth: 0
94
94
  # this is needed if you want the tag push to trigger another workflow
@@ -99,7 +99,7 @@ jobs:
99
99
  run: |
100
100
  git config --global user.email "noreply@github.com"
101
101
  git config --global user.name "Github Wokflow"
102
- npx -y monotag@latest tag-push ${{ inputs.prerelease == true && '--pre-release' || '' }}
102
+ npx -y monotag@latest tag-push ${{ inputs.prerelease == true && '--prerelease' || '' }}
103
103
  ```
104
104
 
105
105
  *Why `workflow_dispatch`:* Manual triggering gives developers explicit control over when a new release tag is created, preventing unintended releases from routine merges.
@@ -0,0 +1,144 @@
1
+ ---
2
+ name: 151-write-user-story
3
+ description: 'Write, refine, elaborate, study or develop the contents of a user story used to create a unit of work for an agile team. Use when you need to write, refine, clarify requirements, ask follow-up questions, cover edge cases, and split large requests into vertical slices so they are clear, complete, and ready for implementation.'
4
+ metadata:
5
+ author: flaviostutz
6
+ version: "1.0"
7
+ ---
8
+
9
+ ## Overview
10
+
11
+ Turns a vague request or rough draft into an implementation-ready user story by asking targeted follow-up questions, resolving all ambiguities, and producing a thin vertical slice or a clean set of split slices.
12
+
13
+ Activate when:
14
+ - The request is vague, incomplete, or internally inconsistent.
15
+ - The acceptance criteria are missing or too shallow.
16
+ - The change may affect multiple parts of a system and needs a vertical-slice check.
17
+ - A requirement needs to be refined into a clear, testable story.
18
+
19
+ ## Instructions
20
+
21
+ ### Core Rules
22
+
23
+ - Start from the user input that exists today. Do not assume missing details are acceptable.
24
+ - Ask targeted follow-up questions until no material ambiguity remains.
25
+ - **HARD GATE: Do not output any story or acceptance criteria while any open decision, unresolved assumption, or ambiguous rule exists — even if the input looks detailed. Embedding an unresolved decision in the output (e.g. "rule X or Y — to be decided") is forbidden; resolve it through questions first.**
26
+ - A detailed or well-structured input does NOT exempt you from the question loop. Treat apparent completeness as a signal to look harder for hidden ambiguities.
27
+ - Analyze all affected parts of the system together before deciding whether the story is small enough.
28
+ - If the request is too large, output only the split implementation-ready stories.
29
+ - Split by independently valuable end-to-end slices, not by technical layers.
30
+ - Produce exactly one recommended result: one final story when feasible, otherwise the final split stories.
31
+
32
+ ### Steps
33
+
34
+ 1. **Classify the input.**
35
+ Decide whether the input is a vague request, partial draft, or near-complete story. Restate the current understanding in a few lines before asking questions.
36
+
37
+ 2. **Identify missing information.** Focus on missing or contradictory items first.
38
+
39
+ | Area | Questions to resolve |
40
+ |---|---|
41
+ | Problem and value | What problem is being solved? Who benefits? What user or business value should exist after the change? |
42
+ | Scope | What behavior is explicitly in scope? What is explicitly out of scope? What should remain unchanged? |
43
+ | Requirements | What must the system do? What inputs, outputs, or contracts matter? What constraints shape the solution? |
44
+ | Flow and interactions | What is the main end-to-end flow? Which actors, systems, or interfaces are involved? Are there state transitions or lifecycle rules? |
45
+ | Edge cases | What unusual but valid scenarios must work? What invalid inputs or error paths must be handled? What happens on retries, duplicates, partial failure, or missing data? |
46
+ | Dependencies | What upstream or downstream systems affect the change? Are there required approvals, sequencing, or external decisions? Does any migration, rollout, or compatibility concern exist? |
47
+
48
+ 3. **Ask follow-up questions one by one using interactive inputs.**
49
+ - **Always use the `vscode_askQuestions` tool** to ask questions interactively when it is available. Never dump questions as plain text if the tool is available.
50
+ - Ask **one question at a time** (or at most 4–5 tightly related questions in a single call). Do not batch many unrelated questions together.
51
+ - Use `options` in each question whenever the answer space is bounded (yes/no, a known set of choices). Use free-form text only when the answer is truly open-ended.
52
+ - After each answer, evaluate whether new ambiguities surfaced before asking the next question.
53
+ - Prefer concrete questions over broad prompts such as "anything else?"
54
+ - Keep looping until all areas in the table above are complete enough for autonomous implementation.
55
+ - **Do not proceed to step 4 until all questions are answered. If you find yourself wanting to write "or X" / "TBD" / "to be documented" anywhere in the output, that is a sign you skipped a question that should have been asked here.**
56
+
57
+ 4. **Check consistency across the whole change.**
58
+ - Look for contradictions between goal, scope, and acceptance criteria.
59
+ - Cross-check the evolving story against any context already provided by the user.
60
+ - If workspace docs or code are relevant, inspect them to confirm terminology, constraints, and affected parts.
61
+ - Verify: requirements don't contradict each other; acceptance criteria prove the requirements; terminology is consistent; no assumptions remain unresolved.
62
+
63
+ 5. **Review each scope item individually.**
64
+ For every item listed under **Scope**, loop through these four checks before moving on:
65
+
66
+ | Check | What to look for |
67
+ |---|---|
68
+ | Completeness | Is the item fully described? Are the inputs, outputs, triggers, and expected behavior clear enough for autonomous implementation without guessing? |
69
+ | Edge cases | Does this specific item have unusual paths — errors, empty states, boundary values, retries, or concurrency — not yet captured in the Edge Cases section? Add any found. |
70
+ | Technical constraints consequences | Does this item imply or conflict with an existing technical constraint (e.g. API contract, data model, performance budget, auth model, third-party limitation)? Flag any constraint that must be honored or must be added to Technical Constraints. |
71
+ | Missing attachments | Would a screenshot, mockup, flow diagram, or reference document make this item unambiguous to implement? If so, ask for it explicitly before proceeding. |
72
+
73
+ - Do **not** move to step 6 while any scope item fails a check.
74
+ - If a check reveals a new gap, return to step 3 and ask the follow-up question.
75
+
76
+ 6. **Decide whether the work fits in one story and enforce vertical slices.**
77
+ - **Vertical slice requirement:** every story must deliver a complete, working feature — partial implementations (backend only, UI shell only, data model only) are only allowed if the developer explicitly says so and the feature is complex enough to justify it. Each story must close the loop from user action to user-visible outcome.
78
+ - Keep one story only if it is a thin, independently valuable slice.
79
+ - **Split when:** the request bundles multiple user outcomes or major workflows; different parts would each require substantial analysis; or acceptance criteria would become broad, vague, or hard to verify as one story.
80
+ - When splitting, each story must still be a vertical slice, add incremental releasable value on top of the previous one, and be independently shippable.
81
+
82
+ 7. **Produce the final result** using the output template below.
83
+ - If one story is feasible, output one refined story. If the work is too large, output only the split stories using the same template.
84
+ - Acceptance criteria must be a plain checklist.
85
+
86
+ ### Output Template
87
+
88
+ ```
89
+ ## Title
90
+ [required — max 10 words, outcome-focused, e.g. "Add fraud-check endpoint for payment processing"]
91
+
92
+ ## User Story
93
+ [required — max 50 words]
94
+ As a [role], I want to [action], so that [benefit].
95
+
96
+ ## Scope
97
+ [required — max 200 words. List features, behaviors, screens, or services in scope with key characteristics and points of attention.]
98
+ - [feature or behavior — characteristic / point of attention]
99
+
100
+ ## Edge Cases
101
+ [optional — max 50 words. Known edge cases and how each should be handled.]
102
+ - [edge case — expected handling]
103
+
104
+ ## Out of Scope
105
+ [optional — max 30 words. What will not be touched; deferred to later or handled elsewhere.]
106
+ - [out-of-scope item]
107
+
108
+ ## Technical Constraints
109
+ [optional — max 30 words. Rules, technologies, or standards that must be followed.]
110
+ - [constraint]
111
+
112
+ ## Acceptance Criteria
113
+ [required — max 50 words. Verifiable checklist confirming the story is done.]
114
+ - [ ] [verifiable outcome]
115
+
116
+ ## Attachments
117
+ [highly desirable — screenshots, mockups, or diagrams illustrating the feature.]
118
+ - [attachment]
119
+ ```
120
+
121
+ ### Completion Criteria
122
+
123
+ Do not stop the question loop until all of the following are true:
124
+
125
+ - Problem and intended user value are clear; scope and non-goals are explicit.
126
+ - Story description, scope, edge cases, and technical constraints are sufficient for autonomous implementation.
127
+ - Edge cases, failure modes, dependencies, and assumptions are known.
128
+ - Acceptance criteria match the requirements and are verifiable.
129
+ - Story is consistent with available context, with no contradictions or unresolved assumptions.
130
+ - Result is either one thin vertical slice or a clean set of split slices, each delivering complete releasable value on its own.
131
+
132
+ ## Examples
133
+
134
+ **Input:** "Add a search bar to the product page."
135
+
136
+ **Clarifying questions asked:** Who performs the search? What data is searched? Should results filter the current page or navigate elsewhere? What happens on no results?
137
+
138
+ **Output:** A refined story scoped to keyword search on product name and description, filtering the current product list in place, with an empty-state message when no results match, and no pagination changes in scope.
139
+
140
+ ## Edge Cases
141
+
142
+ - Input already contains detailed acceptance criteria: do not skip the question loop; look harder for hidden ambiguities in scope boundaries and edge cases.
143
+ - User refuses to answer a clarifying question: note it as an unresolved assumption and do not produce output until it is resolved.
144
+ - Request spans multiple independent user outcomes: always split into separate vertical-slice stories rather than merging into one broad story.
@@ -0,0 +1,88 @@
1
+ ---
2
+ skill: 151-write-user-story
3
+ skill-version: "1.0"
4
+ ---
5
+
6
+ ## Test Scenarios
7
+
8
+ ### Scenario 1: Vague request refined into a single story
9
+
10
+ **Trigger / Input**
11
+ You are an agent with the `151-write-user-story` skill loaded. The user says:
12
+
13
+ "We need to add notifications to the app."
14
+
15
+ **Expected Behaviour**
16
+ 1. Skill classifies the input as vague and restates the current understanding before asking questions.
17
+ 2. Skill asks targeted follow-up questions covering problem/value, scope, requirements, flow, edge cases, and dependencies — one group at a time using `vscode_askQuestions` when available.
18
+ 3. Skill does NOT produce any story or acceptance criteria while ambiguities remain open.
19
+ 4. After all questions are answered and no ambiguity remains, skill performs a consistency check across goal, scope, and acceptance criteria.
20
+ 5. Skill reviews each scope item for completeness, edge cases, technical constraint consequences, and missing attachments.
21
+ 6. Skill decides whether the work fits in one story; if so, produces one refined story using the output template.
22
+ 7. Output contains all required sections: Title, User Story, Scope, Acceptance Criteria.
23
+
24
+ **Simulated Human Responses**
25
+ 1. "Registered users receive notifications. Events that trigger them: a new direct message, a mention in a comment, or a status change on an item they own."
26
+ 2. "In-app only (bell icon with a badge counter). No email or push for now."
27
+ 3. "Users can mark individual notifications as read or mark all as read. Unread count shown in the header."
28
+ 4. "No notifications for system or admin events. Notifications are scoped to the current user only."
29
+ 5. "If the user is offline the notification is stored and shown when they next open the app. No real-time delivery guarantee needed yet."
30
+ 6. "No limit on stored notifications per user for now. No deletion UI required."
31
+
32
+ **Assertions**
33
+ - [ ] Skill asks at least one question about who receives notifications and what triggers them before producing any output.
34
+ - [ ] Skill does not output a story while any area in the identification table (problem, scope, requirements, flow, edge cases, dependencies) has an open question.
35
+ - [ ] Final output follows the output template with Title (max 10 words), User Story (As a … I want … so that …), Scope, and Acceptance Criteria sections.
36
+ - [ ] Acceptance criteria items are verifiable and start with a checkbox `- [ ]`.
37
+
38
+ ---
39
+
40
+ ### Scenario 2: User refuses to answer a clarifying question
41
+
42
+ **Trigger / Input**
43
+ You are an agent with the `151-write-user-story` skill loaded. The user says:
44
+
45
+ "Add export to PDF for the reports page."
46
+
47
+ The skill asks: "Should the export include all report data or only the currently filtered view?" The user replies: "I don't know, just decide."
48
+
49
+ **Expected Behaviour**
50
+ 1. Skill classifies the input and identifies the filtering scope as an open decision.
51
+ 2. Skill asks the clarifying question about export scope.
52
+ 3. When the user refuses to answer, skill notes the item as an unresolved assumption.
53
+ 4. Skill does NOT produce a story or acceptance criteria while the assumption is unresolved.
54
+ 5. Skill explicitly communicates that it cannot proceed until the assumption is resolved, and re-asks or rephrases the question.
55
+
56
+ **Assertions**
57
+ - [ ] Skill does not produce a story, acceptance criteria, or output template while the filtering scope is unresolved.
58
+ - [ ] Skill explicitly states that the unresolved assumption blocks output and asks the user to resolve it.
59
+
60
+ ---
61
+
62
+ ### Scenario 3: Request too large — split into vertical slices
63
+
64
+ **Trigger / Input**
65
+ You are an agent with the `151-write-user-story` skill loaded. The user says:
66
+
67
+ "Build a complete user authentication system: registration with email/password, login, password reset via email, and social login with Google."
68
+
69
+ **Expected Behaviour**
70
+ 1. Skill classifies the input as too large (bundles multiple independent user outcomes).
71
+ 2. Skill asks targeted questions to understand each flow's requirements.
72
+ 3. After questions are resolved, skill determines the work cannot fit in one story.
73
+ 4. Skill splits the request into independently shippable vertical-slice stories (e.g. registration, login, password reset, social login as separate stories).
74
+ 5. Each split story uses the output template and delivers a complete end-to-end user-visible outcome.
75
+ 6. Skill does NOT produce a single merged story.
76
+
77
+ **Simulated Human Responses**
78
+ 1. "Registration: email + password only. Password min 8 chars, at least one digit. Email must be verified before the user can log in."
79
+ 2. "Login: email + password. No magic links. Session token valid for 7 days. Invalidated on logout."
80
+ 3. "Password reset: send a time-limited link to the registered email. Link expires after 1 hour. User sets a new password via the link."
81
+ 4. "Google social login: OAuth 2.0. If the Google email matches an existing account, link them. Otherwise create a new account."
82
+ 5. "Error handling: show a user-friendly message for invalid credentials, expired links, and OAuth failures. No silent failures."
83
+ 6. "No rate limiting, CAPTCHA, or 2FA in scope for now. Each flow ships independently."
84
+
85
+ **Assertions**
86
+ - [ ] Output contains multiple stories, each using the full output template.
87
+ - [ ] Each story is independently shippable and delivers a complete end-to-end user-visible outcome.
88
+ - [ ] No story is a technical-layer-only slice (e.g. "implement the auth database schema" alone is not acceptable).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentme",
3
- "version": "0.32.0",
3
+ "version": "0.33.1",
4
4
  "description": "",
5
5
  "dependencies": {
6
6
  "filedist": "^0.39.0"