agentme 0.32.0 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.xdrs/agentme/edrs/application/151-ai-eval-standards.md +2 -2
- package/.xdrs/agentme/edrs/application/152-ai-test-types-taxonomy.md +108 -54
- package/.xdrs/agentme/edrs/application/153-ai-eval-script.md +12 -14
- package/.xdrs/agentme/edrs/application/154-ai-eval-report-format.md +4 -4
- package/.xdrs/agentme/edrs/application/155-ai-eval-repeatability.md +1 -1
- package/.xdrs/agentme/edrs/application/156-ai-eval-fairness-bias.md +132 -53
- package/.xdrs/agentme/edrs/application/skills/050-create-javascript-project/SKILL.md +17 -9
- package/.xdrs/agentme/edrs/index.md +3 -2
- package/.xdrs/agentme/edrs/platform/302-github-pipelines.md +2 -2
- package/.xdrs/agentme/edrs/principles/skills/151-write-user-story/SKILL.md +144 -0
- package/.xdrs/agentme/edrs/principles/skills/151-write-user-story/SKILL.test.md +88 -0
- package/package.json +1 -1
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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"
|
|
43
|
-
- `input` —
|
|
44
|
-
- `expected_output` —
|
|
45
|
-
- `mock_fixtures` — optional object; keys identify
|
|
46
|
-
- `
|
|
47
|
-
- `
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
|
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
|
|
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`, `
|
|
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 |
|
|
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` |
|
|
81
|
-
| Adversarial/red-team test | `adversarial` |
|
|
82
|
-
| Fairness test | `fairness` |
|
|
83
|
-
| Bias test | `bias` |
|
|
84
|
-
| Robustness test | `robustness` |
|
|
85
|
-
| Explainability test | `explainability` |
|
|
86
|
-
| Groundedness (RAG) eval | `groundedness` |
|
|
87
|
-
| Repeatability test | `repeatability` |
|
|
88
|
-
|
|
|
89
|
-
|
|
|
90
|
-
|
|
|
91
|
-
|
|
|
92
|
-
|
|
|
93
|
-
|
|
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 5× → 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`
|
|
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`
|
|
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`.**
|
|
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
|
|
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
|
|
119
|
-
- [agentme-edr-151](151-ai-eval-standards.md) —
|
|
120
|
-
- [agentme-edr-153](153-ai-eval-script.md) —
|
|
121
|
-
- [agentme-edr-154](154-ai-eval-report-format.md) —
|
|
122
|
-
- [agentme-edr-155](155-ai-eval-repeatability.md) —
|
|
123
|
-
- [agentme-edr-126](126-pragmatic-hexagonal-architecture.md) —
|
|
124
|
-
- [agentme-edr-501](../governance/501-project-quality-standards.md) —
|
|
125
|
-
- [agentme-edr-303](../platform/303-common-targets.md) —
|
|
126
|
-
- [agentme-edr-305](../platform/305-environment-variable-configuration.md) — Environment-configuration conventions
|
|
127
|
-
- [agentme-edr-141](141-ai-llm-development-standards.md) — LLM tier definition and mocking utilities
|
|
128
|
-
- [agentme-edr-122](122-unit-test-requirements.md) — Unit test requirements
|
|
129
|
-
- [agentme-edr-156](156-ai-eval-fairness-bias.md) —
|
|
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,
|
|
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 `
|
|
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
|
-
- **
|
|
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
|
|
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 `
|
|
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`.
|
|
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
|
|
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-
|
|
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.
|
|
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
|
-
|
|
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`
|
|
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
|
|
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
|
|
12
|
+
Fairness and bias are two distinct responsible-AI test types that address different concerns and require different eval architectures:
|
|
13
13
|
|
|
14
|
-
|
|
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
|
-
**
|
|
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-
|
|
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
|
-
|
|
29
|
+
##### Fairness entries
|
|
25
30
|
|
|
26
|
-
|
|
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
|
-
-
|
|
29
|
-
- `expected_output` MUST be
|
|
30
|
-
- `group`
|
|
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
|
|
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": "
|
|
39
|
-
"
|
|
40
|
-
"
|
|
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 —
|
|
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": "
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
|
|
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
|
-
|
|
94
|
+
**Example — combined fairness + bias entry (policy check AND protected-attribute consistency):**
|
|
59
95
|
|
|
60
|
-
|
|
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,
|
|
65
|
-
2. After the entry-first loop completes: iterate over each `(
|
|
66
|
-
3. When `--groups` filtering ([agentme-edr-153](153-ai-eval-script.md) rule `01`) reduces a
|
|
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
|
|
72
|
-
|
|
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
|
|
80
|
-
# Buffer for deferred group scoring;
|
|
81
|
-
|
|
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
|
-
|
|
91
|
-
|
|
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:
|
|
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[
|
|
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
|
|
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`
|
|
114
|
-
- **`bias_accuracy`** =
|
|
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
|
|
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`
|
|
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 `
|
|
133
|
-
- **Per-
|
|
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
|
-
| `
|
|
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
|
|
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-
|
|
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`),
|
|
149
|
-
- [agentme-edr-153](153-ai-eval-script.md) — AI eval script: entry-first loop (rule `01`), `--groups` CLI argument, and deferred group-scoring
|
|
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:
|
|
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`)
|
|
@@ -205,16 +205,24 @@ Use this dependency set.
|
|
|
205
205
|
"homepage": "https://github.com/[owner]/[repo]#readme",
|
|
206
206
|
"devDependencies": {
|
|
207
207
|
"@eslint/eslintrc": "^3.3.1",
|
|
208
|
-
"@stutzlab/eslint-config": "^3.
|
|
208
|
+
"@stutzlab/eslint-config": "^4.3.0",
|
|
209
209
|
"@tsconfig/node24": "^24.0.1",
|
|
210
|
-
"@types/jest": "^
|
|
211
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
212
|
-
"@typescript-eslint/parser": "^8.
|
|
213
|
-
"esbuild": "^0.
|
|
214
|
-
"eslint": "^
|
|
215
|
-
"
|
|
216
|
-
"
|
|
217
|
-
"
|
|
210
|
+
"@types/jest": "^30.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-import-resolver-typescript": "^4.0.0",
|
|
216
|
+
"eslint-plugin-functional": "^10.0.0",
|
|
217
|
+
"eslint-plugin-import": "^2.32.0",
|
|
218
|
+
"eslint-plugin-jest": "^29.0.0",
|
|
219
|
+
"eslint-plugin-prettier": "^5.5.6",
|
|
220
|
+
"eslint-plugin-promise": "^7.0.0",
|
|
221
|
+
"eslint-plugin-unicorn": "^73.0.0",
|
|
222
|
+
"jest": "^30.4.2",
|
|
223
|
+
"prettier": "^3.9.6",
|
|
224
|
+
"ts-jest": "^29.4.12",
|
|
225
|
+
"typescript": "^6.0.3"
|
|
218
226
|
}
|
|
219
227
|
}
|
|
220
228
|
```
|
|
@@ -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
|
|
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
|
|
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@
|
|
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 && '--
|
|
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).
|