SOC 직업 분류 기준
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/tomevault-io/skills-registry --skill signal-over-noise명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SKILL.md 표시 중
| Use when this capability is needed.
> Use when this capability is needed.
Review architecture and API design for the vfs-s3 project. Use when the user mentions @architect, asks to review an issue's design, discuss module boundaries, API shape, or architectural decisions for vfs-s3. Also trigger when the user wants to create an ADR (Architecture Decision Record) or evaluate a technical approach for the project. Intended for dispatch from Codex automation or Claude routines; GitHub trigger phrase: @vfs-s3-bot please prepare design doc Use when this capability is needed.
| name | signal-over-noise |
| description | > Use when this capability is needed. |
/signal-over-noiseA two-phase Python observability audit that improves the ratio of meaningful signal to noise in your error handling and logging. Each phase analyzes the codebase, presents a remediation plan for your review, and — after approval — executes the fixes.
--mode surface (default): uncovers suppressed exceptions that make failures invisible--mode tune: fixes logging anti-patterns that pollute or obscure your log stream/signal-over-noise # surface audit, current directory
/signal-over-noise packages/app-framework/src # surface audit, specific path
/signal-over-noise --mode surface # same as default
/signal-over-noise --mode tune # logging quality audit
/signal-over-noise --mode tune --severity high # HIGH + CRITICAL findings only
/signal-over-noise --mode surface packages/foo/src # surface audit, specific path
Argument parsing:
.--mode surface|tune: which phase to run. Default: surface--severity <level>: filter findings; levels: critical, high, medium, all. Default: allBoth modes follow the same two-stage structure:
Analysis — grep the codebase, read context, classify findings, build a remediation plan. Enter plan mode and present the plan for user review. The user can iterate on the plan.
Execution — after the user approves the plan, apply the agreed fixes. Run pre-commit on changed files. Leave all changes uncommitted for the user to review before committing.
Finds every pattern where exceptions are caught and silently discarded, converting failures into invisible state.
Detection is now delegated to the conformance suite (E-series). The E001–E018 checks run deterministically via
uv run atlan-application-sdk-conformance detect --repo . --series Eand produce SARIF output with one finding per rule violation. This skill retains its value for the remediation / fix-authoring pass (Stage 2) — the suite deliberately does not apply fixes. For a quick detection-only scan, prefer the suite runner; use this skill when you want a plan-mode review and automated fix application.
Pattern catalogue, severity criteria, fix templates, and linting rules are in:
.claude/skills/signal-over-noise/references/error-recovery-patterns.md
.claude/skills/signal-over-noise/references/error-recovery-patterns.md in full..claude/skills/signal-over-noise/references/typed-error-prescription.md in full.TARGET_PATH from arguments (default: current directory). Confirm it exists.SEVERITY_FILTER from --severity (default: all).Run all 13 grep searches in parallel against TARGET_PATH (*.py files only):
| # | Pattern ID | Grep |
|---|---|---|
| 1 | P1 | except\s*:\s*pass |
| 2 | P2 | except\s+\w.*:\s*pass |
| 3 | P3 | contextlib\.suppress\( |
| 4 | P4 | except\s+(Exception|BaseException)\s*: |
| 5 | P5 | logger\.(warning|error|critical)\( inside except blocks — collect hits for Step 1.3 |
| 6 | P6 | ^\s*except\s*: |
| 7 | P7 | except block with return and no log — collect hits for Step 1.3 |
| 8 | P8 | except\s+ImportError |
| 9 | P9 | except block with only an assignment — collect hits for Step 1.3 |
| 10 | P10 | return_exceptions=True |
| 11 | P11 | class\s+\w+.*logging\.Filter or def filter\(self inside a Filter subclass |
| 12 | P12 | raise\s+(ValueError|RuntimeError|Exception|TypeError|NotImplementedError|OSError|KeyError|LookupError)\b |
| 13 | P13 | raise\s+(ClientError|ApiError|OrchestratorError|WorkflowError|IOError|CommonError|DocGenError|ActivityError|AtlanError)\b |
For P5, P7, P9, P11, P12, P13: raw grep over-matches. Collect file:line hits and read context in Step 1.3.
P13 context note: IOError is also a Python builtin alias for OSError — confirm the hit imports from application_sdk.common.error_codes before classifying as legacy. Bare AtlanError raises (no constant) require litmus-test classification (§3 of typed-error-prescription.md).
Collect all hits as a flat list: (file, line_number, pattern_id, raw_snippet).
For each hit, read 10–15 lines of surrounding context.
Classify each finding:
genuine-bug or acceptable (from §Legitimacy in reference)silent-swallow, missing-traceback, overly-broad-catch,
error-to-return-value, suppress-operational, optional-import,
asyncio-unexamined, untyped-raise, legacy-raisegenuine-bug finding whose fix involves
a raise (FT-1b, FT-3b, FT-5b, FT-8, FT-9), look up the prescribed leaf and
code from references/typed-error-prescription.md. Record as Prescribed: on
the remediation entry so the user sees the target class in the plan.Apply SEVERITY_FILTER: discard findings below the threshold before proceeding.
P12 classification notes:
__post_init__, stdlib dataclass validators, or Pydantic @field_validator / @validator methods: check for a comment
explaining the stdlib-interop need. If present → acceptable. If absent →
flag as genuine-bug (MEDIUM — add the comment).@task-decorated activity body or @activity.defn-decorated function → escalate to CRITICAL.P13: confirmed hits are genuine-bug (HIGH). After context reading (see over-matches note above), use the §5 migration table from
typed-error-prescription.md for the Prescribed: field. When no matching legacy constant is present, use §3 litmus tests to select a leaf directly.
For each genuine-bug finding, produce a remediation entry. Include Prescribed:
whenever the fix involves raising an exception:
File: application_sdk/clients/sql.py:352
Severity: HIGH
Category: untyped-raise
Pattern: P12
Current:
raise ValueError("Engine is not initialized. Call load() first.")
Prescribed:
EngineNotInitializedError(InternalError) → code=INTERNAL_ENGINE_NOT_INITIALIZED
Subclass bakes message + component + invariant. Place in a sibling
module (e.g. _<area>_errors.py); see typed-error-prescription.md §4.
Fix (FT-8):
raise EngineNotInitializedError()
Auto-fixable: no (leaf + subclass choice needs context — manual review)
Priority: P1
For existing-pattern (P1–P11) findings whose fix re-raises, also include
Prescribed: with the leaf selected from typed-error-prescription.md §4.
Priority mapping:
Call EnterPlanMode.
Present the Surface Report as the plan:
# Surface Report — <TARGET_PATH>
## Executive Summary
- Files scanned: N
- Total findings: N (N genuine bugs, N acceptable patterns)
- By severity: CRITICAL: N | HIGH: N | MEDIUM: N | LOW: N
- By category: silent-swallow: N | missing-traceback: N | ...
- Auto-fixable: N | Needs manual review: N
## Findings
| # | File | Line | Severity | Category | Pattern | Auto-fixable | Notes |
|---|------|------|----------|----------|---------|--------------|-------|
## Remediation Plan
### P0 — Fix Immediately (CRITICAL)
[entries]
### P1 — Fix This Sprint (HIGH)
[entries]
### P2 — Fix When Touching (MEDIUM/LOW)
[entries]
## Acceptable Patterns (no action required)
| File | Line | Pattern | Justification |
|------|------|---------|---------------|
Call ExitPlanMode to request user approval. Wait for approval before proceeding to Stage 2.
Apply the remediation plan that was approved. Only fix what was listed in the approved plan.
exc_info=True to existing log call in except blockasyncio.gather(..., return_exceptions=True)contextlib.suppress(Exception) with logged try/except (best-effort)# TODO(signal-over-noise): [P4] narrow this catch# TODO(signal-over-noise): [P11] wrap filter body in try/exceptAppError): leaf from typed-error-prescription.md §4. Define a subclass for each distinct failure mode in a sibling errors module (SDK: application_sdk/<area>/errors.py or _<area>_errors.py; app: app/failures.py). Bake message and evidence-field defaults when they're stable across raise sites; for one-off sites, the subclass may just override code and let the raise site pass message.AtlanError raise to typed AppError): leaf from typed-error-prescription.md §5. Same subclassing rule applies when the same error recurs.TODO comment format for swallow/logging findings:
# TODO(signal-over-noise): [P2] silent swallow — add logging. See references/error-recovery-patterns.md#P2
TODO comment format for untyped/legacy raise findings — include the prescribed leaf:
# TODO(signal-over-noise): [P12] convert to typed AppError. Leaf: InternalError (wire code: INTERNAL_ENGINE_NOT_INITIALIZED). See typed-error-prescription.md §4
# TODO(signal-over-noise): [P13] legacy AtlanError — migrate to DependencyUnavailableError. See typed-error-prescription.md §5
Run pre-commit on every file that was changed:
uv run pre-commit run --files <file1> <file2> ...
If pre-commit is not available, skip this step (do not fail).
Leave all changes uncommitted — the user reviews before committing.
Report a brief summary: N files changed, N auto-fixes applied, N TODO comments added.
Then recommend the next step:
Next: Run
/signal-over-noise --mode tuneto audit logging quality (f-strings, missingexc_info, log levels, credential leaks, and more).
Finds logging anti-patterns that pollute your log stream, obscure structured fields, or create security risks.
Pattern catalogue, severity criteria, fix templates, and linting rules are in:
.claude/skills/signal-over-noise/references/logging-patterns.md — detectable patterns (L1–L23).claude/skills/signal-over-noise/references/logging-level-guidelines.md — level philosophy and framework awareness notesTARGET_PATH from arguments (default: current directory). Confirm it exists.SEVERITY_FILTER from --severity (default: all).Discover the project's logging framework — do not assume any specific one:
Grep for common logger factory patterns and count occurrences:
structlog\.get_logger\(logging\.getLogger\(loguru (import or usage)get_logger\( (custom wrapper)The factory with the highest count is CANONICAL_FACTORY.
Check pyproject.toml and requirements.txt / uv.lock for logging framework dependencies:
structlog in deps → LOGGER_FRAMEWORK = structlogloguru in deps → LOGGER_FRAMEWORK = loguruLOGGER_FRAMEWORK = stdlibDetermine SUPPORTS_KWARGS:
SUPPORTS_KWARGS = trueSUPPORTS_KWARGS = falseDetermine FRAMEWORK_SPECIFIC_PATTERNS — which additional patterns (L13–L23) to run:
Discover logger variable names — grep for assignments:
logger\s*=\s*
log\s*=\s*
_logger\s*=\s*
_log\s*=\s*
Collect distinct prefixes (e.g. logger, log, _logger). Build LOGGER_VAR_PATTERN by
joining them: (logger|log|_logger|_log)\. — use this in all Step 2.2 greps.
Run the universal patterns (L1–L12) plus FRAMEWORK_SPECIFIC_PATTERNS (L13–L23) in parallel
against TARGET_PATH. Use LOGGER_VAR_PATTERN in place of hardcoded logger\. in each pattern.
Universal patterns (all frameworks):
| Pattern | Grep | Type |
|---|---|---|
| L1 f-string | LOGGER_VAR_PATTERN\.\w+\(f["'] | mechanical |
| L2 inconsistent factory | Files not using CANONICAL_FACTORY | mechanical |
L3 extra={} | extra=\{ near a logger call | heuristic |
| L4 missing exc_info | multiline: except + log call without exc_info | heuristic |
| L5 print() | ^\s*print\( (exclude test files, CLI scripts) | mechanical |
| L6 INFO in loop | LOGGER_VAR_PATTERN\.info\( inside for/while | heuristic |
| L7 critical() | LOGGER_VAR_PATTERN\.critical\( | mechanical |
| L8 expensive debug | LOGGER_VAR_PATTERN\.debug\(.*(?:json\.dumps|repr|\.to_dict|\.model_dump) | heuristic |
| L9 warn-then-raise | multiline: log call within 3 lines before raise | heuristic |
| L10 credential in log | LOGGER_VAR_PATTERN\.\w+\(.*(?:password|secret|token|api_key|credential|bearer|private_key) (case-insensitive) | heuristic |
| L11 concatenation | LOGGER_VAR_PATTERN\.\w+\(["'].*["']\s*\+ | mechanical |
| L12 %-style (non-stdlib only) | LOGGER_VAR_PATTERN\.\w+\(["'].*%[sdfr] — skip if LOGGER_FRAMEWORK == stdlib | heuristic |
| L18 exception() outside except | LOGGER_VAR_PATTERN\.exception\( | heuristic |
| L24 kwargs in application log calls | LOGGER_VAR_PATTERN\.\w+\([^)]*,\s*\w+= (non-stdlib only) — collect hits for Step 2.3 | heuristic |
Framework-specific patterns (run only for the indicated framework):
| Pattern | Grep | Framework | Type |
|---|---|---|---|
| L13 extra reserved key | extra=\{ — check keys against 22 reserved list | stdlib | heuristic |
| L14 arbitrary kwargs | LOGGER_VAR_PATTERN\.\w+\([^)]*,\s*\w+= | stdlib | heuristic |
| L15 event= kwarg | LOGGER_VAR_PATTERN\.\w+\(.*event= | structlog | mechanical |
| L16 dictConfig disable_existing | dictConfig\( | stdlib | heuristic |
| L17 basicConfig no-op | basicConfig\( (collect all across codebase) | stdlib | heuristic |
| L19 bind() discarded | ^\s+\w+\.bind\( as bare statement | structlog/loguru | heuristic |
| L20 propagate=False | propagate\s*=\s*False | stdlib | heuristic |
| L21 logger.remove() | logger\.remove\(\s*\) (no args) | loguru | mechanical |
| L22 loguru kwargs as format | LOGGER_VAR_PATTERN\.\w+\("[^"]*"[^)]*,\s*\w+= | loguru | heuristic |
| L23 warn() deprecated | \.warn\( | stdlib | mechanical |
For heuristic patterns: collect file:line hits for Step 2.3 context reading.
For mechanical patterns (L1, L2, L5, L7, L11, L15, L21, L23): record directly as findings.
For each heuristic hit, read 10–15 lines of surrounding context.
Classify each hit:
logging-patterns.md)Universal framework adjustments:
LOGGER_FRAMEWORK == stdlib → ACCEPTABLE. If structlog/loguru → MEDIUM. Fix direction: %-style message body, not "unwrap to kwargs".LOGGER_FRAMEWORK == stdlib → ACCEPTABLE. If the log call goes through CANONICAL_FACTORY (e.g. get_logger()) AND that factory has a %-style bridge (look for _format_printf_args or similar in the adapter) → ACCEPTABLE. If the log call uses a direct loguru import (from loguru import logger / loguru.logger) even when a bridge adapter exists → HIGH (the bridge is bypassed; positional args are silently dropped because loguru uses str.format() not %). If vanilla loguru (no bridge) → HIGH. If vanilla structlog → MEDIUM.token_name=name is acceptable; token=value is CRITICAL..exception() call — if inside an except block → ACCEPTABLE.exc_info=True/False. Skip files that define the logging factory/adapter (the file containing get_logger or the logger adapter class). Flag all other kwargs as MEDIUM.Framework-specific classification rules:
extra={} dict literal. Flag CRITICAL for each key that matches any of the 22 reserved LogRecord attributes. Keys not in the reserved list → ACCEPTABLE.{exc_info, extra, stack_info, stacklevel}. Do NOT flag structlog or loguru projects.dictConfig(). If "disable_existing_loggers" is absent or True → HIGH. If False → ACCEPTABLE.basicConfig() calls across the codebase. If more than one → flag the second+ as HIGH. Single call in if __name__ == "__main__": → ACCEPTABLE..bind() call is a bare statement (result not assigned) → HIGH. If assigned (x = logger.bind(...)) → ACCEPTABLE.propagate = False. Check if addHandler() is called on the same logger. If no handler → HIGH. If handler present → ACCEPTABLE.{kwarg_name} placeholder in the message → MEDIUM. If all kwargs have placeholders → ACCEPTABLE (used for formatting).Apply SEVERITY_FILTER: drop findings below the threshold.
For each genuine finding, produce an entry:
file:linelogging-patterns.mdGroup into priority tiers:
Also compute linting recommendations: read pyproject.toml for existing ruff or flake8 rule
selections. List any missing rules from §Linting Rules in logging-patterns.md:
Include the minimal pyproject.toml diff and suggested lint-logging Makefile target in the plan.
Call EnterPlanMode.
Present the Tune Report as the plan:
# Tune Report — <TARGET_PATH>
## Project Logging Profile
- Framework: <LOGGER_FRAMEWORK>
- Canonical factory: <CANONICAL_FACTORY>
- Supports kwargs: <yes/no>
- Logger variable names found: logger, log, ...
## Executive Summary
- Files scanned: N
- Total hits: N (N genuine findings, N acceptable patterns)
- By severity: CRITICAL: N | HIGH: N | MEDIUM: N | LOW: N
- Auto-fixable: N | Needs manual review: N
## Logger Consistency
- Files using canonical factory: N
- Files using non-canonical factory: N (list)
## Findings
| # | File | Line | Severity | Pattern | Auto-fixable | Notes |
|---|------|------|----------|---------|--------------|-------|
## Remediation Plan
### P0 — Fix Immediately (CRITICAL)
[L10, L13, L14 findings with exact lines and fix template]
### P1 — Fix This Sprint (HIGH)
[L1, L2, L4, L15, L16, L17, L19, L20, L21 findings]
### P2 — Fix When Touching File (MEDIUM/LOW)
[L3, L5, L6, L7, L8, L9, L11, L12, L18, L22, L23 findings]
## Linting Recommendations
[pyproject.toml diff]
[Makefile target suggestion]
## Acceptable Patterns (no action required)
| File | Line | Pattern | Justification |
|------|------|---------|---------------|
Call ExitPlanMode to request user approval. Wait for approval before proceeding to Stage 2.
Apply the remediation plan that was approved. Only fix what was listed in the approved plan.
exc_info=True to logger.warning( / logger.error( in except blocksprint("...") → logger.info("...") using %-style for any embedded values.critical( → .error(extra={} (stdlib only)"disable_existing_loggers": False to dictConfig callbind() return value — logger.bind(...) → logger = logger.bind(...).warn( → .warning(exc_info=True)Do not auto-fix L10 (credential leak) — always flag for human review only.
TODO comment format:
# TODO(signal-over-noise): [L6] INFO inside loop — consider DEBUG + summary. See references/logging-patterns.md#L6
Update pyproject.toml with the recommended ruff rules.
Run pre-commit on every file that was changed:
uv run pre-commit run --files <file1> <file2> ...
If pre-commit is not available, skip this step (do not fail).
Leave all changes uncommitted — the user reviews before committing.
Report a brief summary: N files changed, N auto-fixes applied, N TODO comments added.
Plan mode is the fix gate. The user approves the remediation plan before any files are touched. The plan shows exact file:line locations, current code, and proposed fixes.
Two invocations, not one. Surface and Tune are separate --mode values. This keeps each
plan focused and reviewable. Run Surface first; its execution recommends Tune as the next step.
Framework-agnostic: Tune's Step 2.1 discovers the logging framework and canonical factory from the codebase itself. Nothing is hardcoded.
kwargs are a universal anti-pattern in application code: Always embed context in the
message body via %-style. Framework context (Temporal workflow_id, run_id, activity_type,
task_queue, attempt, etc.) is auto-injected by the logging adapter — never pass it manually.
All other application kwargs land in an unindexed JSON blob in the observability platform,
making them invisible to log stream scanning. The only accepted kwarg is exc_info=True.
L24 detects kwargs in application log calls (non-stdlib, outside the adapter file itself).
L3 and L12 are still framework-dependent for classification: extra={} is correct in
stdlib and wrong in structlog/loguru (use %-style body instead). %-style is the universal
preferred format; in vanilla loguru (without a custom adapter bridge) %-style args are
silently dropped — flag as HIGH. In stdlib and projects with a custom %-bridge adapter,
%-style is already correct.
L13 and L14 are crash-level stdlib patterns: extra={} key collisions with reserved
LogRecord attributes raise KeyError that propagates to the caller. Treat as P0.
L10 is security-critical: Never auto-fix credential patterns. Always flag for human review.
Phase ordering matters: Run Surface before Tune. A silent-swallow in an except block (P1/P2) overlaps with a missing-exc_info finding (L4). Surface fixes the structural problem; Tune then verifies the logging quality of the fix. Avoid double-reporting the same line.
Typed-error prescription is mandatory. Every fix that re-raises must name an AppError
leaf from application_sdk.errors. The skill never recommends raising a bare builtin or a
legacy AtlanError. The leaf catalogue (§2), litmus tests (§3), SDK-context cookbook (§4),
and exhaustive legacy-constant migration table (§5) all live in
references/typed-error-prescription.md. P12 (untyped builtin raises) and P13 (legacy
raises) fold the BLDX-1261 audit into surface mode — every finding gets a
entry naming the target leaf and suggested code string.
Source: atlanhq/application-sdk — distributed by TomeVault.
AtlanErrorPrescribed: