* updated commands * feat(backend): logparser pattern test endpoint with agent-exact semantics POST /api/rules/gather/test-pattern evaluates a logparser gather-rule regex against pasted sample lines exactly the way the agent would on the device. Motivated by a field incident: a customer verified a pattern with a PHP regex tester and the .NET engine matched differently. - CmTraceLogParser moves Agent -> AutopilotMonitor.Shared.Logging so agent (IME tracker, logparser collector, stall probe, IME matching mode) and backend run the SAME parsing implementation. Pure mechanical move, agent behavior unchanged (V2.Core suite 2147/2147 green). - TestLogPatternFunction mirrors LogParserCollector verbatim: Regex(Compiled, 1s timeout, NO IgnoreCase -> case-sensitive), first match per line, group "0" excluded / unsuccessful groups omitted, format cmtrace (default, match against parsed message) vs text (raw line), per-line outcomes incl. parse_failed/regex_timeout, and the agent's "set parameter format=text" hint verbatim. Pure compute, no tenant data. Caps: 200 lines, 8KB/line. - Policy: TenantAdminOrGlobalReader (same tier as the analyze dry-run). - Tests pin the parity showcases: case-sensitivity, envelope invisibility in cmtrace mode, optional-group omission, format hint, request validation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(mcp): test_log_pattern tool + logparser lint and guide hardening - test_log_pattern: wraps POST /api/rules/gather/test-pattern — tests a logparser regex against pasted sample lines with the agent-exact .NET semantics (case-sensitive, cmtrace/text mode). Description steers clients away from JS/PHP/Python regex testing. - validate_rule: logparser parameter lint (missing/non-compiling pattern, unknown format value = silently cmtrace on the agent) + info pointing to test_log_pattern; nextStep for valid logparser drafts routes there too. - rule_authoring_guide: logparser section now states the matching semantics (case-SENSITIVE, .NET, first match per line, cmtrace default) and two new pitfalls (engine mismatch, plain-text log under cmtrace default). - Catalog snapshot + handler/validator tests extended (MCP suite 532 green). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(okf): test-pattern endpoint + shared CmTraceLogParser in rule authoring surface Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
8.5 KiB
type, title, description, resource, tags, timestamp
| type | title | description | resource | tags | timestamp | ||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Concept | Rule Authoring Surface — MCP Resources, validate_rule, and the Analyze Dry-Run | How customer AIs author gather/analyze rules against the real contract: the baked authoring resources (guide, schemas, guardrails) generated by combine.js, the MCP-local validate_rule pre-flight, and the side-effect-free backend dry-run that traces a draft analyze rule against one session's events. | src/McpServer/autopilot-monitor-mcp/src/tools/rules.ts |
|
2026-08-05 |
Concept
Customers author rules with an AI connected to the MCP server. Retrieval
(search_docs) is deliberately NOT the knowledge source for authoring: chunked
top-K retrieval can silently omit an operator, a guardrail prefix, or an enum,
and the AI then produces a plausible-but-dead rule. The authoring surface is
therefore deterministic: three get_resource entries carry the complete
contract, a local validator rejects what production would reject or silently
ignore, and a backend dry-run evaluates a draft against real session events with
a full trace.
The intended loop: draft → validate_rule → test_analyze_rule against a real
session (one that should fire, one that should not) → iterate → create in the
portal. The author-rule MCP prompt walks a client through exactly this order.
Schema
Resources (deterministic authoring context)
| Resource | Content | Source |
|---|---|---|
rule_authoring_guide |
Hand-written complete authoring knowledge: collector types, triggers, condition sources, operators, confidence model incl. the exact factor DSL, {{token}} interpolation order, guardrail matching semantics, pitfalls |
src/rule-authoring-guide.ts |
rule_schemas |
Both JSON Schemas (2020-12) verbatim | generated |
rule_guardrails |
rules/guardrails.json verbatim |
generated |
Generation: node rules/scripts/combine.js bakes schemas + guardrails into
src/McpServer/autopilot-monitor-mcp/src/rule-authoring.generated.ts (same
pattern as the web's utils/guardrails.generated.ts; the tsconfig rootDir and
the Docker build's exclusion of rules/schema rule out importing the JSON
directly). Drift is closed twice: CI's guardrails-in-sync job re-runs
combine.js and fails on any diff, and rule-authoring-drift.test.ts pins
generated == repo source plus guide enums == schema enums.
validate_rule (MCP-local)
src/rule-validation.ts, no backend call. Three layers:
- Schema — ajv (draft 2020-12) against the baked schemas, validating the
single-rule
$defsentry directly (the top-level oneOf wrapper would double every error). - Guardrails — mirrors the AGENT's matching semantics from
GatherRuleGuards.cs(see gather-rule-guardrails.md): hive-stripped segment-bounded registry/file prefixes, whitespace-bounded WMI prefixes, EXACT command matching,/-bounded event-log channels, and the code-enforced hard blocks (Securityetc. channels,C:\Users,C:\Windows\System32\config). - Semantic lint — schema-valid-but-dead rules: unreachable
confidenceThreshold, factor conditions outside the three parseable shapes
(
exists,count >= N,phase_duration > N), unknown event types (warning;gather_*softened to info), unanchorednot_regexallow-lists, unresolvable{{token}}s, trigger cross-fields, outputEventType convention/collision checks.
The validator is advisory pre-flight only — the agent re-enforces guardrails on-device and the backend re-validates structure. It must never be stricter than production.
POST /api/rules/analyze/dryrun (backend)
DryRunAnalyzeRuleFunction → RuleEngine.DryRunRuleAsync. Body
{ sessionId, rule } (draft AnalyzeRule, 1 MB cap). Policy tier
TenantAdminOrGlobalReader — a POST by shape but a pure read in effect, so the
read-only Global Reader is admitted; platform-scope callers reach any tenant's
session via FindSessionTenantIdAsync (same pattern as GetRuleResultsFunction).
RuleEngine.DryRun.cs is a partial-class trace twin of EvaluateRule: it
shares the exact evaluators (EvaluatePrecondition / EvaluateCondition /
EvaluateConfidenceFactor) but evaluates all conditions instead of breaking
on the first failed required one — the full picture is the point of a dry run.
Verdicts: fired, skipped_by_precondition, required_condition_not_met,
no_conditions_matched, below_confidence_threshold, no_events. Each
condition entry carries matched, the production evidence dictionary (or the
evaluator's reason string) and matchingEventCount — how many session events
even have that eventType, the first thing to check on an unexpected miss.
Invariants, pinned by RuleEngineDryRunTests:
- Parity: verdict
fired⇔EvaluateRuleproduces a result, with identical confidence and evidence keys. Factor evaluation stays sequential against the accumulatingmatchedConditions(a factor can observe earlierfactor_*entries) — reordering would change results. - Side-effect freedom: exactly one strict event read; never a RuleResult
write, never
TryMarkSessionFailedFromRuleAsync, never a notification.wouldMarkSessionAsFailedis reported, not acted on.
test_analyze_rule (MCP) wraps the endpoint and adds the interpolated
explanation/remediation preview via the existing interpolate-rule-template.ts
against the returned matchedConditions.
POST /api/rules/gather/test-pattern (backend)
The logparser counterpart to the analyze dry-run, added after a field incident:
a customer verified a logparser regex with a PHP tester and the agent's .NET
engine matched differently. TestLogPatternFunction evaluates a pattern against
pasted sample lines with the AGENT's exact matching semantics:
- Regex construction identical to
LogParserCollector:Compiled, 1 s timeout, no IgnoreCase — logparser matching is case-sensitive (unlike analyze-rule regex conditions, which run IgnoreCase). formatbehaves exactly like the rule parameter:cmtrace(default) parses each line via the sharedCmTraceLogParserand matches against the parsed MESSAGE only;textmatches the raw line. First match per line (Regex.Match), group"0"excluded, unsuccessful groups omitted — the returnedgroupsare exactly the event-data fields the device would emit.- Mirrors the agent's diagnostics: per-line outcomes
(
matched | no_match | parse_failed | regex_timeout), the all-lines-parse-fail hint ("set parameter format=text") verbatim, and a case-sensitivity note on zero matches. - Pure compute on the request body — no tenant data touched. Same policy tier
as the dry-run (
TenantAdminOrGlobalReader); caps: 200 lines, 8 KB/line, 1 MB body.
Parity is structural, not duplicated: CmTraceLogParser moved from the agent
(Monitoring/Enrollment/Ime) to Shared (AutopilotMonitor.Shared.Logging)
so agent and backend run the SAME parsing implementation. Timestamp caveat:
bias-less CMTrace lines parse with AssumeLocal, which on the backend is the
server's timezone — the endpoint therefore reports match/parse results, never
timestamps. test_log_pattern (MCP) wraps the endpoint; validate_rule
additionally lints logparser parameters (missing/non-compiling pattern, unknown
format value) and its nextStep routes logparser drafts to test_log_pattern.
What is deliberately absent
- No gather-rule remote execution — gather rules run as SYSTEM on devices; session dry-run is analyze-only. Logparser authors get the pattern tester above; all gather authors get guardrail pre-flight plus the on-device debug log (gather-rule-debug-log).
- No rule write/deploy via MCP — creating rules stays in the portal.
Citations
src/Backend/AutopilotMonitor.Functions/Functions/Rules/TestLogPatternFunction.cs— logparser pattern testersrc/Shared/AutopilotMonitor.Shared/Logging/CmTraceLogParser.cs— shared CMTrace parser (agent + backend)src/Backend/AutopilotMonitor.Functions/Services/RuleEngine.DryRun.cs— trace twin + DTOssrc/Backend/AutopilotMonitor.Functions/Functions/Rules/DryRunAnalyzeRuleFunction.cs— endpoint + draft validationsrc/McpServer/autopilot-monitor-mcp/src/rule-validation.ts— validatorsrc/McpServer/autopilot-monitor-mcp/src/tools/rules.ts— validate_rule / test_analyze_rulesrc/McpServer/autopilot-monitor-mcp/src/rule-authoring-guide.ts— guide resourcerules/scripts/combine.js— MCP module generation