---
phase: 02-scanners
plan: 02
subsystem: scanners
tags: [tc-scanners, topic, toxicity, cyber, jailbreak, enum, guardline, package-api]

requires:
  - phase: 02-scanners
    plan: 01
    provides: BaseScanner, _StrValueMixin, PIIScanner, Guard.scan_input() multi-spec support

provides:
  - TopicLabel enum with 30 members + ALL sentinel
  - ToxicityLabel enum with 4 members + ALL sentinel
  - CyberLabel enum with 11 members + ALL sentinel
  - JailbreakLabel enum with 2 members + ALL sentinel
  - TopicScanner, ToxicityScanner, CyberScanner, JailbreakScanner classes
  - Full scanner re-exports from meshulash_guard.scanners and meshulash_guard

affects:
  - 03-server (TC head names: topic, hate_speech, cysecbench, jailbreak must match server)
  - 04-integration (all 5 scanner types now available for integration tests)

tech-stack:
  added: []
  patterns:
    - "TC scanner pattern: scoped label enum + _TC_HEAD class constant + to_guardline_spec() building tc-type specs"
    - "ALL sentinel expansion: any(lbl.value == '__ALL__') triggers expansion of all non-ALL members"
    - "TC spec structure: types.tc=True, required.tc=[[head, label], ...], k=0, no ner/regex"

key-files:
  created:
    - src/meshulash_guard/scanners/topic.py
    - src/meshulash_guard/scanners/toxicity.py
    - src/meshulash_guard/scanners/cyber.py
    - src/meshulash_guard/scanners/jailbreak.py
  modified:
    - src/meshulash_guard/scanners/__init__.py
    - src/meshulash_guard/__init__.py

key-decisions:
  - "TC head names hidden behind _TC_HEAD class constant — developers work with label enums, not raw strings"
  - "Label enum values are exact server strings (case-sensitive): 'hate speech', 'Malware Attacks', etc."
  - "ALL sentinel uses any() check on value == '__ALL__' then iterates over type(lbl[0]) to get all non-ALL members"
  - "k=0 for all TC scanners in v1 — not configurable at this stage"
  - "JailbreakScanner implemented as stub with docstring noting 'coming soon' server head"

patterns-established:
  - "TC scanner template: all four scanners share identical structure differing only in _TC_HEAD and label enum"
  - "Scoped label enums: each scanner owns its label enum preventing cross-scanner label confusion"
  - "Package re-export convention: scanners/__init__.py re-exports all scanners; package __init__.py re-exports from scanners"

duration: 2min
completed: 2026-02-26
---

# Phase 2 Plan 2: TC Scanners and Package Wiring Summary

**Four TC-based scanners (TopicScanner, ToxicityScanner, CyberScanner, JailbreakScanner) with scoped label enums wired into full package re-export hierarchy.**

## Performance

- **Duration:** 2min
- **Started:** 2026-02-26T18:19:39Z
- **Completed:** 2026-02-26T18:21:14Z
- **Tasks:** 2 completed
- **Files modified:** 6

## Accomplishments

- Created `TopicScanner` with `TopicLabel` enum (30 topic labels + ALL), `_TC_HEAD = "topic"` — each label value matches the exact server string from `label_config.json`
- Created `ToxicityScanner` with `ToxicityLabel` enum (4 labels + ALL), `_TC_HEAD = "hate_speech"` — including the space-containing value `"hate speech"` matching server exactly
- Created `CyberScanner` with `CyberLabel` enum (11 labels + ALL), `_TC_HEAD = "cysecbench"` — covering the full CySecBench threat taxonomy
- Created `JailbreakScanner` with `JailbreakLabel` enum (2 labels + ALL), `_TC_HEAD = "jailbreak"` — with docstring noting the server head is "coming soon"
- All four scanners share the identical TC pattern: scoped label enum, `_TC_HEAD` constant, `to_guardline_spec()` building `types.tc=True` specs with `[[head, label]]` pairs
- Updated `scanners/__init__.py` to re-export all 5 scanners and all 5 label enums
- Updated `meshulash_guard/__init__.py` to re-export all scanners at the top level, extending `__all__` with 10 new names while preserving all existing exports

## Task Commits

Each task was committed atomically:

1. **Task 1: Create TopicScanner, ToxicityScanner, CyberScanner, and JailbreakScanner** — `0970bfd` (feat)
2. **Task 2: Wire all scanners into package public API** — `0bf7ccc` (feat)

**Plan metadata:** (docs commit below)

## Files Created/Modified

- `src/meshulash_guard/scanners/topic.py` — TopicLabel enum (30 members + ALL), TopicScanner class
- `src/meshulash_guard/scanners/toxicity.py` — ToxicityLabel enum (4 members + ALL), ToxicityScanner class
- `src/meshulash_guard/scanners/cyber.py` — CyberLabel enum (11 members + ALL), CyberScanner class
- `src/meshulash_guard/scanners/jailbreak.py` — JailbreakLabel enum (2 members + ALL), JailbreakScanner class
- `src/meshulash_guard/scanners/__init__.py` — full re-exports of all 5 scanners and 5 label enums
- `src/meshulash_guard/__init__.py` — top-level scanner re-exports added; `__all__` extended with 10 new names

## Decisions Made

1. **TC head names hidden**: The `_TC_HEAD` class constant is an implementation detail. Developers only interact with `TopicLabel.HEALTH`, not `"topic"`. This shields the API from server-side naming changes.

2. **Exact server string values**: Label enum values are copied verbatim from the server's `label_config.json` — including mixed-case (`"Malware Attacks"`), lowercase with spaces (`"hate speech"`), and underscore variants (`"Identity_Attack"`). The `_StrValueMixin` ensures `str(label)` returns this exact value.

3. **ALL sentinel expansion**: The ALL check uses `any(lbl.value == "__ALL__")` then iterates `type(self._labels[0])` to collect all non-ALL members. This leverages Python enum iteration semantics without needing a separate constant.

4. **JailbreakScanner as forward-compatible stub**: The jailbreak TC head is "coming soon" on the server. The scanner is fully implemented and will work once the server deploys the head — the SDK does not need changes when the server is ready. The docstring and class note inform developers of the current status.

5. **k=0 fixed for TC scanners in v1**: The `k` field (for K_OF condition) is hardcoded to `0` as it is not user-configurable in the current release. This matches the server's expected format.

## Deviations from Plan

None — plan executed exactly as written.

## Issues Encountered

None.

## User Setup Required

None — no external service configuration required.

## Next Phase Readiness

- All 5 scanner types importable from both `meshulash_guard.scanners` and `meshulash_guard` directly
- `from meshulash_guard import Guard, PIIScanner, TopicScanner, Action` works in a single import line
- TC scanner specs are fully formed: `types.tc=True`, `required.tc=[[head, label]]`, `k=0`
- JailbreakScanner is API-ready and will activate automatically when server deploys jailbreak head
- Ready for Phase 3 (server integration) or Phase 4 (integration tests)
- The complete scanner suite is ready for documentation and user-facing examples

---
*Phase: 02-scanners*
*Completed: 2026-02-26*
