|
| 1 | +#!/usr/bin/env python3 |
| 2 | +"""Add explicit auto orchestration to the optional SOC LLM request.""" |
| 3 | + |
| 4 | +from __future__ import annotations |
| 5 | + |
| 6 | +import re |
| 7 | +from pathlib import Path |
| 8 | + |
| 9 | +root = Path(__file__).resolve().parents[1] |
| 10 | +source_path = root / "src" / "lib.rs" |
| 11 | +adr_path = root / "docs" / "adr" / "0010-adaptive-contextual-orchestrator-default.md" |
| 12 | +changelog_path = root / "CHANGELOG.md" |
| 13 | + |
| 14 | +source = source_path.read_text(encoding="utf-8") |
| 15 | +if "orchestration_mode" not in source: |
| 16 | + patterns = [ |
| 17 | + r'(?P<indent>[ \t]*)"model"\s*:\s*(?P<value>[^,\n}]+),\s*\n(?P=indent)"messages"\s*:', |
| 18 | + r'(?P<indent>[ \t]*)"model"\s*=>\s*(?P<value>[^,\n}]+),\s*\n(?P=indent)"messages"\s*=>', |
| 19 | + ] |
| 20 | + changed = False |
| 21 | + for pattern in patterns: |
| 22 | + match = re.search(pattern, source) |
| 23 | + if match is None: |
| 24 | + continue |
| 25 | + original = match.group(0) |
| 26 | + separator = ":" if '"model"' in original and ":" in original.splitlines()[0] else "=>" |
| 27 | + message_separator = ":" if separator == ":" else "=>" |
| 28 | + replacement = ( |
| 29 | + f'{match.group("indent")}"model"{separator}{match.group("value")},\n' |
| 30 | + f'{match.group("indent")}"orchestration_mode"{separator} "auto",\n' |
| 31 | + f'{match.group("indent")}"messages"{message_separator}' |
| 32 | + ) |
| 33 | + source = source[: match.start()] + replacement + source[match.end() :] |
| 34 | + changed = True |
| 35 | + break |
| 36 | + if not changed: |
| 37 | + # Flexible fallback for serde_json::json! blocks where formatting places |
| 38 | + # model and messages on one line. |
| 39 | + source, count = re.subn( |
| 40 | + r'("model"\s*:\s*[^,}]+,\s*)("messages"\s*:)', |
| 41 | + r'\1"orchestration_mode": "auto", \2', |
| 42 | + source, |
| 43 | + count=1, |
| 44 | + ) |
| 45 | + if count != 1: |
| 46 | + raise RuntimeError("could not locate the SOC model/messages JSON payload") |
| 47 | +source_path.write_text(source, encoding="utf-8") |
| 48 | + |
| 49 | +adr_path.parent.mkdir(parents=True, exist_ok=True) |
| 50 | +if not adr_path.exists(): |
| 51 | + adr_path.write_text( |
| 52 | + '''# ADR-0010: SOC analysis delegates default execution to contextual-orchestrator auto |
| 53 | +
|
| 54 | +- Status: Accepted |
| 55 | +- Date: 2026-08-16 |
| 56 | +
|
| 57 | +## Context |
| 58 | +
|
| 59 | +Wardnet's optional SOC analysis endpoint calls the organization LLM gateway, but a |
| 60 | +model/messages-only request leaves policy implicit and can collapse into a fixed |
| 61 | +single-worker path. Security analysis ranges from short enrichment to high-risk, |
| 62 | +multi-step investigation; the application should not hard-code one model or one |
| 63 | +workflow for all cases. |
| 64 | +
|
| 65 | +## Decision |
| 66 | +
|
| 67 | +The SOC request explicitly includes `orchestration_mode: "auto"`. The central |
| 68 | +orchestrator selects the quality-sufficient route, worker-plus-verifier path, or |
| 69 | +conducted workflow; known lower cost is used only after capability and safety |
| 70 | +requirements. Unpriced providers are not treated as free. |
| 71 | +
|
| 72 | +Wardnet retains WAF/IDS evidence collection, authorization, bounded request handling, |
| 73 | +audit records, security-domain validation, and operator presentation. Explicit fixed |
| 74 | +modes remain controlled orchestration experiments and rollback controls, not the |
| 75 | +product default. |
| 76 | +
|
| 77 | +## References |
| 78 | +
|
| 79 | +Omidvar, H., & Akhlaghi, V. (2026). *A communication-theoretic framework for LLM agents: Cost-aware adaptive reliability* [Preprint]. arXiv. https://doi.org/10.48550/arXiv.2605.09121 |
| 80 | +
|
| 81 | +Tang, Y., Cetin, E., Xu, J., Sun, Q., Nielsen, S., Richard, V., Goda, H., Tymchenko, I., Nguyen, N., Lee, H., Ashiga, M., Kotyan, S., Kuroki, S., & Clanuwat, T. (2026). *Sakana Fugu technical report* [Technical report]. arXiv. https://doi.org/10.48550/arXiv.2606.21228 |
| 82 | +''', |
| 83 | + encoding="utf-8", |
| 84 | + ) |
| 85 | + |
| 86 | +if changelog_path.exists(): |
| 87 | + changelog = changelog_path.read_text(encoding="utf-8") |
| 88 | + entry = ( |
| 89 | + "- Optional SOC LLM analysis now explicitly selects contextual-orchestrator " |
| 90 | + "`auto` instead of relying on a single-model default.\n" |
| 91 | + ) |
| 92 | + if entry not in changelog: |
| 93 | + marker = "## Unreleased\n" |
| 94 | + if marker in changelog: |
| 95 | + changelog = changelog.replace(marker, marker + "\n### Changed\n\n" + entry, 1) |
| 96 | + else: |
| 97 | + changelog = "## Unreleased\n\n### Changed\n\n" + entry + "\n" + changelog |
| 98 | + changelog_path.write_text(changelog, encoding="utf-8") |
0 commit comments