Skip to content

feat(directive_detection): bench gate + candidate detector for #374 H1 - #377

Merged
robotrocketscience merged 1 commit into
mainfrom
feat/issue-374-directive-bench
May 3, 2026
Merged

feat(directive_detection): bench gate + candidate detector for #374 H1#377
robotrocketscience merged 1 commit into
mainfrom
feat/issue-374-directive-bench

Conversation

@yoshi280

@yoshi280 yoshi280 commented May 3, 2026

Copy link
Copy Markdown
Collaborator

What

Adds the H1 directive-detection re-entry harness so #374's bench-gate deferral can actually be evaluated. Does not implement H1 — the process_directive / TODO lifecycle / escalation / hook wiring stay deferred until the gate passes.

Why

Per docs/v2_enforcement.md § H1 (and the row in docs/V2_REENTRY_QUEUE.md), H1 reopens for implementation only when a labeled sample of ≥200 coding prompts shows ≥0.80 precision and ≥0.60 recall. Until this PR, that gate had no candidate detector to score and no schema entry in the v2.0 corpus contract — so the deferral was unfalsifiable. This PR makes the gate evaluable.

Changes

  • src/aelfrice/directive_detector.py — candidate regex detector. 29-imperative-verb alternation reconstructed from the spec exemplars, plus three filters: wh-leading question, trailing ?, hedge markers (maybe, I think, …), and habitual-narration ("I never X when Y" pattern from § H1's own counter-example). Pure stdlib re. ~85 LOC.
  • tests/corpus/v2_0/directive_detection/ — new corpus module dir (.gitkeep only — lab populates the labeled JSONL per directory-of-origin rule).
  • tests/corpus/v2_0/README.md — adds the module row, per-line shape (prompt: str, label directive|not_directive), and a "re-entry gate" subsection restating the P/R/n thresholds.
  • tests/test_corpus_schema.py — adds the new module to the MODULES validator dict.
  • tests/bench_gate/test_directive_detection.py — bench-gated; skips on public CI without AELFRICE_CORPUS_ROOT. With corpus mounted: scores detector, computes P/R, asserts P ≥ 0.80 ∧ R ≥ 0.60 ∧ n ≥ 200. Failure assertions cite docs/v2_enforcement.md § H1 so the next reader knows what re-deferring looks like.
  • tests/test_directive_detector.py — 18 public-CI-runnable sanity cases covering the four filter behaviors.

Out of scope

  • The labeled corpus itself. Synthetic-only per tests/corpus/v2_0/README.md and the directory-of-origin rule; lab populates aelfrice-lab/tests/corpus/v2_0/directive_detection/*.jsonl separately.
  • process_directive, the TODO lifecycle, repetition counter, escalation table, hook wiring. All gated on this gate passing.
  • The verb-bank membership is "best-effort reconstruction from spec exemplars". The gate scores whatever detector lives in directive_detector.py; if the corpus shows specific verbs over- or under-fire, tune in a follow-up.

Verification

  • uv run pytest -q — 2181 passed, 22 skipped (the new bench-gate test skips clean without corpus, as designed).
  • Discretion grep clean.
  • Signed.

Closes nothing — #374 stays open until the corpus lands and the gate either passes (→ implementation unblocks) or fails (→ stays deferred per § H1).

Summary by Sourcery

Add a candidate directive-detection detector and benchmark gate to make the H1 re-entry condition for #374 evaluable against a labeled corpus.

New Features:

  • Introduce a directive detection module exposing a boolean detect_directive helper for identifying durable imperative directives in prompts.
  • Add a bench-gated test that evaluates directive detection precision and recall against a lab corpus and enforces the H1 re-entry thresholds.
  • Define a new directive_detection corpus module with schema and re-entry gate documentation for labeled prompts.

Enhancements:

  • Extend the corpus schema validation to cover the new directive_detection module.

Tests:

  • Add public CI sanity tests for directive detection covering positive directives and filtered-out question, hedge, and narration cases.

Summary by CodeRabbit

  • New Features

    • Directive detection system with built-in quality gates for accuracy validation
  • Tests

    • Comprehensive test coverage including unit tests and performance benchmarks to ensure quality standards
  • Documentation

    • Updated corpus schema and documentation with new module definitions

@yoshi280 yoshi280 added the attn:review Needs review (PR open, awaiting reviewer) label May 3, 2026
@sourcery-ai

sourcery-ai Bot commented May 3, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds a candidate regex-based directive detector plus a benchmark gate and corpus schema wiring so H1 directive-detection can be quantitatively evaluated against a labeled corpus before implementation unblocks.

Sequence diagram for bench gate evaluation of directive detection

sequenceDiagram
    actor Dev
    participant Pytest as pytest
    participant BenchTest as test_directive_detection
    participant CorpusLoader as corpus_loader
    participant Detector as directive_detector
    participant Metrics as metrics

    Dev->>Pytest: run tests with AELFRICE_CORPUS_ROOT set
    Pytest->>BenchTest: execute bench gate test
    BenchTest->>CorpusLoader: load labeled prompts from corpus
    CorpusLoader-->>BenchTest: prompts_with_labels
    loop for each prompt
        BenchTest->>Detector: detect_directive(text)
        Detector-->>BenchTest: is_directive
        BenchTest->>Metrics: record prediction and gold label
    end
    BenchTest->>Metrics: compute precision, recall, n
    Metrics-->>BenchTest: P, R, n
    BenchTest->>BenchTest: assert P >= 0.80 and R >= 0.60 and n >= 200
    BenchTest-->>Pytest: pass or fail based on gate
    Pytest-->>Dev: report test results
Loading

Sequence diagram for detect_directive filtering logic

sequenceDiagram
    participant Caller
    participant Detector as directive_detector

    Caller->>Detector: detect_directive(text)
    alt empty or whitespace
        Detector-->>Caller: False
    else nonempty
        Detector->>Detector: stripped = text.strip()
        alt stripped endswith ?
            Detector-->>Caller: False
        else wh question leading
            Detector-->>Caller: False
        else narration pattern matches
            Detector-->>Caller: False
        else hedge pattern matches
            Detector-->>Caller: False
        else imperative verb pattern matches
            Detector-->>Caller: True
        else no imperative verb
            Detector-->>Caller: False
        end
    end
Loading

Class diagram for directive_detector module structure

classDiagram
    class directive_detector {
        <<module>>
        +tuple~str~ _IMPERATIVE_VERBS
        +Pattern _VERB_PATTERN
        +Pattern _HEDGE_PATTERN
        +Pattern _NARRATION_PATTERN
        +Pattern _WH_QUESTION_LEADING
        +bool detect_directive(text: str)
    }

    class re {
        <<stdlib_module>>
        +Pattern compile(pattern: str, flags: int)
        +str escape(text: str)
    }

    directive_detector ..> re : uses
Loading

File-Level Changes

Change Details Files
Introduce a regex-based directive detector implementing H1 candidate logic.
  • Add _IMPERATIVE_VERBS verb bank and build a single compiled alternation regex with length-sorted phrases.
  • Define hedge, narration, and wh-question-leading regex patterns to filter out questions, hedged statements, and habitual/reported speech.
  • Implement detect_directive(text: str) -> bool applying filters (empty, question, narration, hedge) before checking for imperative markers.
src/aelfrice/directive_detector.py
Wire directive_detection into the v2.0 corpus contract and schema validation.
  • Document the new directive_detection/ corpus module directory and its JSONL shape in the v2.0 corpus README.
  • Describe the H1 re-entry gate criteria (precision, recall, sample size, publication rules) in the corpus documentation.
  • Extend the corpus schema validator to include the directive_detection module with prompt and `directive
not_directive` labels.
Add a bench-gated test that evaluates the detector against the lab corpus and enforces the H1 re-entry thresholds.
  • Add a bench_gated pytest that loads the directive_detection corpus via AELFRICE_CORPUS_ROOT and skips when unavailable or under-sized.
  • Compute TP/FP/FN/TN, derive precision/recall, and assert they exceed the configured gates with descriptive failure messages referencing docs.
  • Enforce a minimum of 200 labeled rows before the gate can fire, per the H1 spec.
tests/bench_gate/test_directive_detection.py
Provide public CI sanity tests for the directive detector’s core behaviors.
  • Add positive test cases that should be classified as directives based on imperative markers.
  • Add negative test cases covering empty/whitespace input, questions, habitual narration, and hedged statements to exercise all filter branches.
tests/test_directive_detector.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented May 3, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@robotrocketscience has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 58 minutes and 56 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 52c7ed90-735d-4925-b1b4-879f20dfd8be

📥 Commits

Reviewing files that changed from the base of the PR and between 385b80c and e5ea00b.

📒 Files selected for processing (6)
  • src/aelfrice/directive_detector.py
  • tests/bench_gate/test_directive_detection.py
  • tests/corpus/v2_0/README.md
  • tests/corpus/v2_0/directive_detection/.gitkeep
  • tests/test_corpus_schema.py
  • tests/test_directive_detector.py
📝 Walkthrough

Walkthrough

This PR implements directive detection functionality for issue #374. A new detect_directive() function uses regex patterns to identify imperative directives, along with bench-gated corpus validation, unit tests, schema definitions, and documentation.

Changes

Directive Detection Implementation

Layer / File(s) Summary
Core Detector Implementation
src/aelfrice/directive_detector.py
New detect_directive() function with compiled regex patterns for 29 imperative verbs, hedging phrases, narration patterns, and WH-question filtering. Returns True when imperative markers are found and exclusion filters do not match.
Corpus Schema Definition
tests/test_corpus_schema.py
Added directive_detection module to MODULES with required labels (directive, not_directive) and extra field prompt (non-empty string).
Unit Tests
tests/test_directive_detector.py
Parameterized tests verifying detect_directive() returns True for directive examples and False for non-directives, empty inputs, and edge cases.
Bench-Gate Test
tests/bench_gate/test_directive_detection.py
Loads directive_detection corpus, computes TP/FP/FN/TN metrics, enforces ≥80% precision and ≥60% recall gates with detailed failure messaging; skips if corpus has fewer than 200 rows.
Documentation
tests/corpus/v2_0/README.md
Documents directive_detection module structure, module-specific JSONL fields, and the re-entry gate (#374) criteria and test reference.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

Suggested labels

author-Setr

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the primary change: adding a bench gate and candidate detector for the H1 directive-detection re-entry condition in issue #374.
Description check ✅ Passed The PR description fully addresses the template requirements with clear What/Why/Changes sections, linked issue (#374), type of change (feat), verification results, and detailed notes for reviewers.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-374-directive-bench

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 58 minutes and 56 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The precision/recall thresholds and minimum-row gate are hard-coded in the bench test; consider centralizing these (or importing from a single config/module) to avoid silent drift from the values documented in docs/v2_enforcement.md § H1.
  • The narration regex currently keys off any first-person deontic phrase followed by a linker (e.g. I must X when Y), which may be stricter than necessary; if the corpus shows over-filtering, consider tightening it to focus on clearly habitual formulations (e.g. including explicit frequency markers) rather than all such conditionals.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The precision/recall thresholds and minimum-row gate are hard-coded in the bench test; consider centralizing these (or importing from a single config/module) to avoid silent drift from the values documented in `docs/v2_enforcement.md` § H1.
- The narration regex currently keys off any first-person deontic phrase followed by a linker (e.g. `I must X when Y`), which may be stricter than necessary; if the corpus shows over-filtering, consider tightening it to focus on clearly habitual formulations (e.g. including explicit frequency markers) rather than all such conditionals.

## Individual Comments

### Comment 1
<location path="src/aelfrice/directive_detector.py" line_range="63-65" />
<code_context>
+
+# Build a single alternation regex. Sort by length desc so multi-word
+# phrases match before their single-word prefixes.
+_VERB_PATTERN = re.compile(
+    r"\b(?:" + "|".join(re.escape(v) for v in sorted(_IMPERATIVE_VERBS, key=len, reverse=True)) + r")\b",
+    re.IGNORECASE,
+)
+
</code_context>
<issue_to_address>
**issue:** Contraction handling is limited to ASCII apostrophes, which misses common Unicode variants in real inputs.

This will only match verbs with straight ASCII apostrophes ("don't", "can't"), so inputs using curly or other Unicode apostrophes (e.g., “don’t”) will be missed. If production text may include those, either normalize input (map Unicode quotes to ASCII before matching) or extend the regex to include common Unicode apostrophe characters.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +63 to +65
_VERB_PATTERN = re.compile(
r"\b(?:" + "|".join(re.escape(v) for v in sorted(_IMPERATIVE_VERBS, key=len, reverse=True)) + r")\b",
re.IGNORECASE,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Contraction handling is limited to ASCII apostrophes, which misses common Unicode variants in real inputs.

This will only match verbs with straight ASCII apostrophes ("don't", "can't"), so inputs using curly or other Unicode apostrophes (e.g., “don’t”) will be missed. If production text may include those, either normalize input (map Unicode quotes to ASCII before matching) or extend the regex to include common Unicode apostrophe characters.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/aelfrice/directive_detector.py`:
- Around line 87-90: The current WH-question leading regex _WH_QUESTION_LEADING
includes "when" which causes conditional directives like "when merging, always
squash" to be filtered out; remove "when" from the _WH_QUESTION_LEADING pattern
so it no longer treats leading "when" as an interrogative, and optionally add a
narrow check elsewhere (e.g., in the same directive detection flow or the
trailing-question filter) that specifically matches "when should|can|will|do"
(paired with a trailing '?' check) to still catch true "when" questions without
reintroducing directive false negatives; update any tests that assert behavior
of _WH_QUESTION_LEADING or the verb-question gating to reflect the new behavior.

In `@tests/bench_gate/test_directive_detection.py`:
- Around line 29-48: The test currently uses all rows (including seed rows) for
the MIN_ROWS guard and for computing TP/FP/FN/TN; fix by filtering out seed rows
first (e.g., create a filtered_rows = [r for r in rows if not r.get("seed")] or
similar) and use filtered_rows for the length check against MIN_ROWS and for the
scoring loop (replace usages of rows in the skip guard and the for row in rows
loop); keep detect_directive(...) and the tp/fp/fn/tn counters unchanged but
iterate only over non-seed examples so both the floor check and precision/recall
reflect real examples.

In `@tests/test_directive_detector.py`:
- Around line 31-47: The negative test list in test_directive_negatives doesn't
include a WH-leading sentence without a trailing question mark, so the
_WH_QUESTION_LEADING filter is never tested in isolation; update the
parameterized inputs in test_directive_negatives (which calls detect_directive)
to include at least one WH-leading negative example that lacks a trailing "?"
(e.g., "what does the staging gate check" or similar) so that
_WH_QUESTION_LEADING is exercised without the trailing-question filter firing
first.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9c0e99d6-e2f8-4abf-b2b7-c34880bafd88

📥 Commits

Reviewing files that changed from the base of the PR and between aa1aabb and 385b80c.

📒 Files selected for processing (6)
  • src/aelfrice/directive_detector.py
  • tests/bench_gate/test_directive_detection.py
  • tests/corpus/v2_0/README.md
  • tests/corpus/v2_0/directive_detection/.gitkeep
  • tests/test_corpus_schema.py
  • tests/test_directive_detector.py

Comment on lines +87 to +90
_WH_QUESTION_LEADING = re.compile(
r"^\s*(?:what|why|how|when|where|who|which|whose|whom)\b",
re.IGNORECASE,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

"when" in _WH_QUESTION_LEADING silently drops conditional directives, hurting recall.

"when" is the only entry in this list that commonly begins durable conditional rules rather than questions — e.g. "when merging, always squash", "when possible, avoid force-push". Every such directive is killed by filter 3 before the verb check fires, producing false negatives. The recall gate is already set at only 0.60; if the labeled corpus skews toward conditional form this filter alone can sink the gate.

The other WH-words (what, why, how, where, who, which, whose, whom) are genuinely interrogative and rarely open directives, so they can stay.

Consider removing when from this list and, if needed, adding a targeted check for "when should/can/will/do …" (paired with the existing trailing-? filter) to avoid re-introducing question false-positives.

💡 Suggested fix
 _WH_QUESTION_LEADING = re.compile(
-    r"^\s*(?:what|why|how|when|where|who|which|whose|whom)\b",
+    r"^\s*(?:what|why|how|where|who|which|whose|whom)\b",
     re.IGNORECASE,
 )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/aelfrice/directive_detector.py` around lines 87 - 90, The current
WH-question leading regex _WH_QUESTION_LEADING includes "when" which causes
conditional directives like "when merging, always squash" to be filtered out;
remove "when" from the _WH_QUESTION_LEADING pattern so it no longer treats
leading "when" as an interrogative, and optionally add a narrow check elsewhere
(e.g., in the same directive detection flow or the trailing-question filter)
that specifically matches "when should|can|will|do" (paired with a trailing '?'
check) to still catch true "when" questions without reintroducing directive
false negatives; update any tests that assert behavior of _WH_QUESTION_LEADING
or the verb-question gating to reflect the new behavior.

Comment on lines +29 to +48
if len(rows) < MIN_ROWS:
pytest.skip(
f"directive_detection corpus has {len(rows)} rows; gate requires "
f"≥{MIN_ROWS} per docs/v2_enforcement.md § H1"
)

from aelfrice.directive_detector import detect_directive

tp = fp = fn = tn = 0
for row in rows:
actual = row["label"] == "directive"
predicted = detect_directive(row["prompt"])
if predicted and actual:
tp += 1
elif predicted and not actual:
fp += 1
elif (not predicted) and actual:
fn += 1
else:
tn += 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Seed rows are included in both the MIN_ROWS floor check and the P/R computation.

load_corpus_module returns all rows, including entries marked "seed": true. Per the README, seed rows are "committed only to anchor the schema" and explicitly excluded from the v0.1 count target. Including them here means:

  1. The 200-row floor can be satisfied by synthetic seed rows, bypassing the intent of requiring 200 real coding-prompt examples before the gate fires.
  2. Precision/recall can be skewed by schema-anchoring examples that are not representative of the distribution the gate is designed to measure.

Both the skip guard and the scoring loop should operate on non-seed rows only:

🛡️ Proposed fix
     rows = load_corpus_module(aelfrice_corpus_root, "directive_detection")

+    # Seed rows anchor the schema only; exclude them from gate evaluation
+    # per README § "Seed rows do NOT count toward the v0.1 ≥50/module target".
+    rows = [r for r in rows if not r.get("seed")]
+
     if len(rows) < MIN_ROWS:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/bench_gate/test_directive_detection.py` around lines 29 - 48, The test
currently uses all rows (including seed rows) for the MIN_ROWS guard and for
computing TP/FP/FN/TN; fix by filtering out seed rows first (e.g., create a
filtered_rows = [r for r in rows if not r.get("seed")] or similar) and use
filtered_rows for the length check against MIN_ROWS and for the scoring loop
(replace usages of rows in the skip guard and the for row in rows loop); keep
detect_directive(...) and the tp/fp/fn/tn counters unchanged but iterate only
over non-seed examples so both the floor check and precision/recall reflect real
examples.

Comment on lines +31 to +47
@pytest.mark.parametrize(
"text",
[
"",
" ",
"what does the staging gate check?",
"should we rebase or merge here?",
"I never push to main when I'm tired",
"I always check git status because the worktrees confuse me",
"maybe we should never use force-push",
"I think we must rebase",
"the deploy ran fine",
"looks good",
],
)
def test_directive_negatives(text: str) -> None:
assert detect_directive(text) is False

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Filter 3 (_WH_QUESTION_LEADING) is never the sole gate in any negative test case.

Both negative cases that exercise WH-question detection ("what does the staging gate check?") also end with "?", so filter 2 (trailing ?) fires first and filter 3 is never reached. A regression that removes _WH_QUESTION_LEADING entirely would pass the current suite. Add at least one negative without a trailing ?:

     "I think we must rebase",
     "the deploy ran fine",
     "looks good",
+    "what the staging gate checks",       # WH-leading, no trailing ?
+    "why we run the bench gate",          # WH-leading, no trailing ?
 ],
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_directive_detector.py` around lines 31 - 47, The negative test
list in test_directive_negatives doesn't include a WH-leading sentence without a
trailing question mark, so the _WH_QUESTION_LEADING filter is never tested in
isolation; update the parameterized inputs in test_directive_negatives (which
calls detect_directive) to include at least one WH-leading negative example that
lacks a trailing "?" (e.g., "what does the staging gate check" or similar) so
that _WH_QUESTION_LEADING is exercised without the trailing-question filter
firing first.

@yoshi280

yoshi280 commented May 3, 2026

Copy link
Copy Markdown
Collaborator Author

[claim:merge:toug:2026-05-03T16:40:50Z]

@yoshi280

yoshi280 commented May 3, 2026

Copy link
Copy Markdown
Collaborator Author

[claim:review:Setr:2026-05-03T16:41:09Z]

@github-actions github-actions Bot added the attn:merge-conflict PR branch needs rebase label May 3, 2026
@github-actions

github-actions Bot commented May 3, 2026

Copy link
Copy Markdown

This PR is now behind main. Rebase locally so your commit signatures stay intact:

git fetch origin && git checkout 'feat/issue-374-directive-bench' && git rebase origin/main
# resolve conflicts if any, then
git push --force-with-lease

Auto-rebase was removed because the bot has no signing key; rebasing as the bot strips author signatures and the required_signatures rule on main then blocks the merge. See #341.

Adds the H1 re-entry harness so #374's deferral can actually be evaluated:

- src/aelfrice/directive_detector.py: candidate regex detector (29 imperative verbs, wh-question / hedging / habitual-narration filters). Spec at docs/v2_enforcement.md § H1.

- tests/corpus/v2_0/directive_detection/: new corpus module dir (lab-side fixtures, directory-of-origin rule).

- tests/corpus/v2_0/README.md: schema row + per-line shape (`prompt`: str; label `directive|not_directive`); re-entry-gate section restating P>=0.80 / R>=0.60 / n>=200.

- tests/test_corpus_schema.py: validate the new module shape.

- tests/bench_gate/test_directive_detection.py: bench-gated test, scores detector against corpus, asserts P>=0.80 + R>=0.60 + n>=200; skips on public CI without AELFRICE_CORPUS_ROOT.

- tests/test_directive_detector.py: 18 sanity cases for the four filter behaviors. Public-CI runnable.

Does not implement process_directive, the TODO lifecycle, escalation, or any hook wiring. Those stay deferred until the gate passes against a real labeled corpus.
@yoshi280

yoshi280 commented May 3, 2026

Copy link
Copy Markdown
Collaborator Author

[claim:review:Kulili:2026-05-03T16:42:01Z]

@yoshi280

yoshi280 commented May 3, 2026

Copy link
Copy Markdown
Collaborator Author

[release:review:Kulili:2026-05-03T16:42:06Z]

@robotrocketscience
robotrocketscience force-pushed the feat/issue-374-directive-bench branch 2 times, most recently from 0400820 to e5ea00b Compare May 3, 2026 16:42
@yoshi280
yoshi280 enabled auto-merge (rebase) May 3, 2026 16:43
@robotrocketscience
robotrocketscience merged commit e5ea00b into main May 3, 2026
18 checks passed
@robotrocketscience
robotrocketscience deleted the feat/issue-374-directive-bench branch May 3, 2026 16:47
@yoshi280

yoshi280 commented May 3, 2026

Copy link
Copy Markdown
Collaborator Author

[release:review:Setr:2026-05-03T16:47:46Z]

@yoshi280

yoshi280 commented May 3, 2026

Copy link
Copy Markdown
Collaborator Author

[release:merge:toug:2026-05-03T16:49:13Z]

robotrocketscience added a commit that referenced this pull request May 10, 2026
src/aelfrice/directive_detector.py landed via #374. Status block already
mentioned the harness (#377) but didn't acknowledge the detector module
itself. Add the in-tree pointer so readers can find the code; precision
gate verdict is unchanged.
robotrocketscience added a commit that referenced this pull request May 10, 2026
src/aelfrice/directive_detector.py landed via #374. Status block already
mentioned the harness (#377) but didn't acknowledge the detector module
itself. Add the in-tree pointer so readers can find the code; precision
gate verdict is unchanged.
robotrocketscience added a commit that referenced this pull request May 10, 2026
src/aelfrice/directive_detector.py landed via #374. Status block already
mentioned the harness (#377) but didn't acknowledge the detector module
itself. Add the in-tree pointer so readers can find the code; precision
gate verdict is unchanged.
robotrocketscience added a commit that referenced this pull request May 10, 2026
src/aelfrice/directive_detector.py landed via #374. Status block already
mentioned the harness (#377) but didn't acknowledge the detector module
itself. Add the in-tree pointer so readers can find the code; precision
gate verdict is unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

attn:merge-conflict PR branch needs rebase attn:review Needs review (PR open, awaiting reviewer)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants