pr-architecture-review — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited pr-architecture-review (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Multidimensional code review of pull request changes against the documented service contracts for the Ansible Know MCP Server.
Load these reference materials before starting — they define the layer boundaries, allowed dependencies, and known violations:
docs/architecture/service-contracts.mddocs/architecture/adr/Pass the relevant sections to each subagent in Phase 2.
$ARGUMENTS if provided (PR numberor branch name). Otherwise use the current branch diffed against main.
git diff main...HEAD --name-only for branchreviews, or MCP GitHub pull_request_read with get_files / get_diff for PR reviews. If gh CLI fails (sandbox), fall back to MCP GitHub tools — see skill sandbox-git-github for guidance.
Skip files that don't map to any layer (README, pyproject.toml, CI).
Dispatch one subagent per review dimension. Each subagent receives the diff, the relevant checklist from below, and the service contracts as context. Dimensions are independent — run them in parallel.
| Dimension | Checklist | Relevant local skills |
|---|---|---|
| Layer dependencies | Steps 1–2 | — |
| Type contracts & API surface | Steps 3, 6 | python-tighten-types, python-contract-docstrings |
| Async/sync & state management | Steps 4–5 | python-try-except |
| PEP 8 & Python standards | Step 7 | python-alignment-chart, python-concept-analysis |
| Security | Step 8 | — |
Each subagent should load its listed local skills from skills/ for additional context. Instruct each to return structured findings using the Reporting format at the bottom of this skill.
Merge all subagent findings. Deduplicate (same file+line across dimensions). Sort by severity: Error → Warning → Info. Present a single consolidated report.
Classify each changed file into its architecture layer:
| File Pattern | Layer |
|---|---|
| Framework config, transport setup | Transport |
src/ansible_know/server.py | Orchestration |
src/ansible_know/parser.py | Domain |
src/ansible_know/skills.py | Domain |
src/ansible_know/collection_manifest.py | Domain |
src/ansible_know/docs.py | Domain |
src/ansible_know/galaxy.py | External Access |
src/ansible_know/collections.py | External Access |
src/ansible_know/readme_parser.py | External Access |
src/ansible_know/cache.py | Foundation |
src/ansible_know/config.py | Foundation |
src/ansible_know/galaxy_config.py | Foundation |
src/ansible_know/async_utils.py | Foundation |
src/ansible_know/state.py | Foundation |
src/ansible_know/tagging.py | Foundation |
src/ansible_know/validation.py | Foundation |
src/ansible_know/errors.py | Foundation |
src/ansible_know/types.py | Foundation |
src/ansible_know/templates/* | Domain (templates) |
tests/* | Test (check mirrors source layer) |
Files that do not match any pattern (e.g., README.md, pyproject.toml, CI configs) do not require architecture review.
For each changed file, verify that its imports respect the allowed dependency direction:
Transport → (framework-managed, no application code)
Orchestration → Domain, External Access, Foundation
Domain → Foundation ONLY
External → Foundation ONLY
Foundation → no internal dependencies#### What to look for
parser.pyimporting from galaxy.py or collections.py. Domain modules should only depend on Foundation (config, errors, types, validation).
galaxy.py importingfrom parser.py or skills.py. External Access should only depend on Foundation.
have zero dependencies on Orchestration, Domain, or External Access.
server.py shoulddelegate to Domain modules, not implement resolution strategies, data transformations, or caching logic directly.
#### Known existing violations (do not worsen)
server.py contains _resolve_module_doc() and _resolve_role_doc()(business logic in Orchestration — V-D7/V-L2).
server.py calls GalaxyClient directly (V-E1/V-L1).galaxy.py imports readme_parser (External → Domain — V-L3).parser.py imports collections (Domain → External — V-L4).Rule: do not add new violations. If a PR must cross a layer boundary, document why and file a follow-up issue.
For changes that modify function signatures or return types:
the TypedDict definitions from types.py (ModuleMetadata, RoleMetadata, DocProvenance), not bare dict[str, Any].
add a TypedDict to types.py rather than using dict[str, Any].
exception hierarchy from errors.py. Never raise bare Exception or ValueError — use AnsibleKnowError subclasses.
in the Orchestration layer (using validation.py functions) before being passed to Domain or External Access.
For changes that add or modify function calls between layers:
does I/O (subprocess, file system, network) MUST be wrapped in _run_in_executor() when called from an async handler. Never call blocking functions directly from a tool handler.
subprocess.run() withcapture_output=True, text=True, and a timeout parameter. Never use subprocess.Popen or os.system.
asyncio.get_running_loop() instead (PEP deprecated pattern).
For changes that add or modify module-level state:
dict, set, list,or mutable object at module scope MUST have explicit thread-safety documentation. If accessed from _run_in_executor() threads, it MUST use threading.Lock. If accessed from async code only, it SHOULD use asyncio.Lock.
BoundedCache fromcache.py (thread-safe, LRU-bounded, optional TTL). Do not introduce new ad-hoc OrderedDict + Lock patterns — use the shared abstraction. If BoundedCache does not fit the use case, document why.
set.add(), dict[key] = val,and similar mutations on module-level state are safe under the concurrency model being used.
For changes that add, rename, or remove public functions/classes:
__all__, verifythe new function/class is listed (if public) or prefixed with _ (if internal).
_private() functions. If access is needed, the function should be made public.
ToolAnnotations with appropriate hints (readOnlyHint, idempotentHint, destructiveHint). New resources must have descriptive names and descriptions.
For all Python changes, verify:
snake_case for functions/variables, CapWords forclasses, UPPER_CASE for constants, _leading_underscore for non-public names (PEP 8 Section 8).
x: int), spaces aroundarrows (-> int), spaces around = in annotated defaults (x: int = 0) (PEP 8 Sections 10-11).
is / is not, never == / !=(PEP 8 Section 9).
except:, use raise X from Yfor chaining, derive from Exception not BaseException (PEP 8 Section 9).
if not seq: instead ofif len(seq) == 0: (PEP 8 Section 9).
For changes that handle external input or subprocess calls:
FQCNs must match _FQCN_RE, namespaces _NAMESPACE_RE, etc.
validated with validate_path_containment() and validate_install_path().
through sanitize_error() to strip filesystem paths.
user input using string interpolation. Use list arguments to subprocess.run().
_sanitize_credential() to strip control characters.
truncate_response() to prevent memory exhaustion.
For each finding, report:
service-contracts.md if it matchesan existing violation, or assign a new one.
file follow-up issue), Info (note for future improvement).
| Severity | Criteria | Action |
|---|---|---|
| Error | Thread safety bug, layer skip introducing new coupling, security vulnerability, bare except:, None equality comparison | Block merge |
| Warning | Missing types at boundary, private function access across modules, missing validation, missing __all__, new untyped state | Fix or file issue before merge |
| Info | Loose typing (dict[str, Any] where TypedDict exists), minor naming inconsistencies, missing type annotations on internal functions | Note in review, fix opportunistically |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.