Observal is self-hosted registry for your coding agent extensions with a built in insight engine. Setup Observal, define the scope and share your Skills, MCPs and Agents with your peers.
This report summarizes scanner evidence for Observal/Observal, a Python project with 4,353 GitHub stars. SynthScan examined 413,138 lines of code across 1519 source files, recording 9920 pattern matches distributed across 22 syntactic categories. The legacy adjusted pattern signal is 35.9 (High pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Can maintainers explain intent, assumptions, and trade-offs? 6720 finding(s).
Are imports declared and package/API names verified? 855 finding(s).
Are wrappers, guards, and repeated structures necessary? 8519 finding(s).
Which changes need focused human review? 9920 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 9920 distinct pattern matches across 22 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | install-server.sh | 25 | # ── Helpers ────────────────────────────────────────────────── | COMMENT |
| MEDIUM | install-server.sh | 35 | # ── Parse arguments ────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | install-server.sh | 105 | # ── Pre-flight ─────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | install-server.sh | 111 | # ── Resolve version ────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | install-server.sh | 121 | # ── Download ───────────────────────────────────────────────── | COMMENT |
| MEDIUM | install-server.sh | 139 | # ── Stage and preserve previous package ──────────────────── | COMMENT |
| MEDIUM | install-server.sh | 208 | # ── Run setup and restore on ordinary failure ─────────────── | COMMENT |
| MEDIUM⚡ | .pre-commit-config.yaml | 10 | # ── Python ───────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | .pre-commit-config.yaml | 18 | # ── YAML / TOML / JSON ──────────────────────────────── | COMMENT |
| MEDIUM | .pre-commit-config.yaml | 42 | # ── Secrets / .env guard ─────────────────────────────── | COMMENT |
| MEDIUM | .pre-commit-config.yaml | 51 | # ── Alembic migrations ───────────────────────────────── | COMMENT |
| MEDIUM | .pre-commit-config.yaml | 62 | # ── SPDX copyright update ────────────────────────────────────── | COMMENT |
| MEDIUM | .pre-commit-config.yaml | 73 | # ── Docker ───────────────────────────────────────────── | COMMENT |
| MEDIUM | install.sh | 22 | # ── Helpers ────────────────────────────────────────────────── | COMMENT |
| MEDIUM | install.sh | 32 | # ── Parse arguments ────────────────────────────────────────── | COMMENT |
| MEDIUM | install.sh | 86 | # ── Detect platform ────────────────────────────────────────── | COMMENT |
| MEDIUM | install.sh | 108 | # ── Resolve version ────────────────────────────────────────── | COMMENT |
| MEDIUM | install.sh | 122 | # ── Download and verify ────────────────────────────────────── | COMMENT |
| MEDIUM | install.sh | 160 | # ── Install ────────────────────────────────────────────────── | COMMENT |
| MEDIUM | install.sh | 172 | # ── Write install metadata ────────────────────────────────── | COMMENT |
| MEDIUM | pyproject.toml | 73 | # ── Ruff ───────────────────────────────────────────────── | COMMENT |
| MEDIUM | pyproject.toml | 120 | # ── Pytest ─────────────────────────────────────────────── | COMMENT |
| MEDIUM | pyproject.toml | 126 | # ── Bandit ─────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | infra/terraform/deploy.sh | 6 | # ================================ | COMMENT |
| MEDIUM⚡ | infra/terraform/deploy.sh | 17 | # ── Output formatting ──────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/deploy.sh | 38 | # ── Help ───────────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/deploy.sh | 52 | # ── Banner ─────────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/deploy.sh | 58 | # ── Tier Selection ─────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/deploy.sh | 88 | # ── Pre-flight: Terraform ──────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/deploy.sh | 115 | # ── Pre-flight: AWS credentials ────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/deploy.sh | 132 | # ── terraform.tfvars setup ─────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/deploy.sh | 160 | # ── Validation loop ────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/deploy.sh | 319 | # ── Summary ────────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/deploy.sh | 328 | # ── Apply ──────────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/deploy.sh | 404 | # ── Post-apply ─────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/deploy.sh | 442 | # ── Final output ───────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/aws-ec2/deploy.sh | 13 | # ── Read Terraform outputs ─────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/aws-ec2/deploy.sh | 34 | # ── Helper: run command on instance via SSM ────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/aws-ec2/deploy.sh | 82 | # ── Wait for SSM agent to come online ──────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/aws-ec2/deploy.sh | 102 | # ── Wait for startup script to finish ──────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/aws-ec2/deploy.sh | 118 | # ── Deploy server package (pre-built images from GHCR) ─────────────────────── | COMMENT |
| MEDIUM | infra/terraform/aws-ec2/deploy.sh | 125 | # ── Configure .env ─────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/aws-ec2/deploy.sh | 150 | # ── Configure TLS (if domain set) ─────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/aws-ec2/deploy.sh | 157 | # ── Pull and start (pre-built images — fast) ──────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/aws-ec2/deploy.sh | 174 | # ── Health check ───────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/gcp/variables.tf | 28 | # ── Network ──────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/gcp/variables.tf | 42 | # ── DNS / TLS ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/gcp/variables.tf | 56 | # ── Container images ────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/gcp/variables.tf | 76 | # ── Cloud Run (api) ─────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/gcp/variables.tf | 102 | # ── Cloud Run (web) ─────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/gcp/variables.tf | 128 | # ── Cloud Run (worker) ──────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/gcp/variables.tf | 154 | # ── Data tier (ClickHouse on GCE) ───────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/gcp/variables.tf | 168 | # ── Cloud SQL ───────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/gcp/variables.tf | 192 | # ── Memorystore Redis ───────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/gcp/variables.tf | 210 | # ── Application config ──────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/gcp/variables.tf | 249 | # ── Backups ─────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/gcp/cloud-run.tf | 24 | # ── API service ─────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/gcp/cloud-run.tf | 165 | # ── Web service ─────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/gcp/cloud-run.tf | 209 | # ── Worker service ──────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/gcp/cloud-run.tf | 292 | # ── Init job (migrations) ───────────────────────────────────────────────── | COMMENT |
| 1715 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | conftest.py | 16 | def _isolated_registry_lockfile(tmp_path, monkeypatch): | CODE |
| LOW | observal_cli/skill_folder.py | 382 | def detect_destination_collisions( | CODE |
| LOW | observal_cli/cmd_team.py | 383 | def approve_visibility_request( | CODE |
| LOW | observal_cli/cmd_team.py | 404 | def reject_visibility_request( | CODE |
| LOW | observal_cli/cmd_agent.py | 271 | def _validate_agent_definition(data: dict, *, operation: str) -> dict: | CODE |
| LOW | observal_cli/cmd_agent.py | 1416 | def _components_from_capabilities(since: str, *, operation: str) -> tuple[list[dict], list[str], list[str]]: | CODE |
| LOW | observal_cli/cmd_share.py | 61 | def discover_repository_agents(directory: str = ".") -> tuple[Path, list[dict]]: | CODE |
| LOW | observal_cli/lockfile.py | 555 | def agent_entry_is_registry_backed(entry: dict | None) -> bool: | CODE |
| LOW | observal_cli/config.py | 146 | def migrate_shimmed_mcp_configs(home: Path | None = None, cwd: Path | None = None) -> list[Path]: | CODE |
| LOW | observal_cli/client.py | 327 | def resolve_registry_reference(item_type: str, reference: str) -> str: | CODE |
| LOW | observal_cli/client.py | 711 | def get_registered_agents_only() -> bool: | CODE |
| LOW | observal_cli/client.py | 734 | def get_registered_agent_names() -> set[str]: | CODE |
| LOW | observal_cli/cmd_pull.py | 269 | def _component_input_definitions(listing: dict, field: str, kind: str, component: str) -> list[dict]: | CODE |
| LOW | observal_cli/cmd_pull.py | 620 | def _rewrite_kiro_agent_profile(content: dict, agent_id: str | None = None) -> dict: | CODE |
| LOW | observal_cli/cmd_pull.py | 676 | def _rewrite_copilot_cli_hooks(content: dict, agent_id: str | None = None) -> dict: | CODE |
| LOW | observal_cli/cmd_pull.py | 794 | def _reports_written_sessions(paths: list[str]) -> bool: | CODE |
| LOW | observal_cli/cmd_pull.py | 1245 | def rewrite_observal_interpreter(value): | CODE |
| LOW | observal_cli/cmd_pull.py | 1278 | def _preflight_existing_managed_skill_paths( | CODE |
| LOW | observal_cli/cmd_pull.py | 1424 | def _record_managed_agent_component( | CODE |
| LOW | observal_cli/cmd_pull.py | 1523 | def _restore_prior_managed_agent_entry( | CODE |
| LOW | observal_cli/cmd_pull.py | 1565 | def _rollback_managed_agent_folders(applied: list[tuple[dict, dict]]) -> list[str]: | CODE |
| LOW | observal_cli/cmd_pull.py | 1597 | def _rollback_managed_agent_state( | CODE |
| LOW | observal_cli/cmd_doctor.py | 217 | def _check_observal_skill_missing() -> list[str]: | CODE |
| LOW | observal_cli/cmd_mcp.py | 102 | def _configure_env_vars_interactive(detected: list[dict]) -> list[dict]: | CODE |
| LOW | observal_cli/cmd_mcp.py | 293 | def _parse_server_json_manifest(cfg: dict) -> dict | None: | CODE |
| LOW | observal_cli/cmd_mcp.py | 1079 | def _install_input_definitions(listing: dict, field: str, kind: str) -> list[dict]: | CODE |
| LOW | observal_cli/lockfile_reconcile.py | 81 | def plan_lockfile_reconciliation() -> LockfileReconciliation: | CODE |
| LOW⚡ | observal_cli/cmd_auth.py | 1561 | def _generate_initial_layer_snapshot(): | CODE |
| LOW | observal_cli/cmd_auth.py | 235 | def _ensure_cli_matches_server(server_url: str) -> None: | CODE |
| LOW | observal_cli/cmd_auth.py | 1582 | def _install_or_check_pi_extension(): | CODE |
| LOW | observal_cli/cmd_insights.py | 364 | def _render_what_they_work_on(title: str, data: dict): | CODE |
| LOW | observal_cli/cmd_insights.py | 378 | def _render_interaction_style(title: str, data: dict): | CODE |
| LOW | observal_cli/cmd_insights.py | 485 | def _render_registry_match_note(summary: dict | None): | CODE |
| LOW | observal_cli/cmd_insights.py | 619 | def _render_version_comparison(title: str, data: dict): | CODE |
| LOW | observal_cli/cmd_archive.py | 31 | def _require_confirmation_bypass(output: OutputMode, yes: bool, operation: str) -> None: | CODE |
| LOW | observal_cli/cmd_server.py | 595 | def _get_current_server_version(compose_dir: Path) -> str: | CODE |
| LOW | observal_cli/layer.py | 467 | def _get_observal_managed_files(lockfile_data: dict, harness: str, project_dir: str | None) -> set[str]: | CODE |
| LOW | observal_cli/cmd_skill.py | 1294 | def _protect_legacy_skill_install( | CODE |
| LOW | observal_cli/cmd_skill.py | 1536 | def install_skill_registry_direct( | CODE |
| LOW | observal_cli/version_check.py | 307 | def fetch_available_server_images() -> list[str]: | CODE |
| LOW | observal_cli/version_check.py | 358 | def verify_server_image_exists(version: str) -> bool: | CODE |
| LOW⚡ | observal_cli/version_check.py | 546 | def check_version_compatibility(server_url: str) -> None: | CODE |
| LOW | observal_cli/cmd_transfer.py | 25 | def add_transfer_owner_command(app: typer.Typer, entity_type: str) -> None: | CODE |
| LOW | observal_cli/cmd_migrate.py | 141 | def _warn_clickhouse_cleartext(url: str, output: OutputMode) -> None: | CODE |
| LOW | observal_cli/main.py | 118 | def _migrate_legacy_mcp_configs() -> None: | CODE |
| LOW | observal_cli/pi_extension.py | 208 | def _is_observal_local_install(home: Path | None = None) -> bool: | CODE |
| LOW | observal_cli/skill_installer.py | 109 | def _remove_antigravity_legacy_files(source_dir: Path, skill_file: Path) -> None: | CODE |
| LOW | observal_cli/skill_installer.py | 137 | def _is_unchanged_bundled_copy(source_dir: Path, skill_file: Path) -> bool: | CODE |
| LOW | observal_cli/skill_installer.py | 200 | def _reconcile_observal_skills(home: Path, *, install_missing: bool) -> tuple[list[str], list[str]]: | CODE |
| LOW | observal_cli/skill_installer.py | 245 | def missing_observal_skill_harnesses(home: Path | None = None) -> list[str]: | CODE |
| LOW | observal_cli/discovery/normalize.py | 50 | def canonicalize_python_package_name(name: str) -> str: | CODE |
| LOW | observal_cli/discovery/normalize.py | 87 | def _split_python_requirement(requirement: str) -> tuple[str, str | None, str | None] | None: | CODE |
| LOW | observal_cli/discovery/normalize.py | 176 | def extract_mcp_launch_metadata(config: Mapping[str, object]) -> McpLaunchMetadata: | CODE |
| LOW | observal_cli/discovery/redact.py | 275 | def sanitize_diagnostic_message(message: object) -> str: | CODE |
| LOW⚡ | observal_cli/tests/test_public_access.py | 12 | def test_anonymous_read_defaults_to_public_server(): | CODE |
| LOW⚡ | observal_cli/tests/test_public_access.py | 21 | def test_token_without_server_does_not_fall_back_to_public_instance(): | CODE |
| LOW⚡ | observal_cli/tests/test_public_access.py | 27 | def test_optional_client_omits_authorization_header(): | CODE |
| LOW | observal_cli/tests/test_public_access.py | 45 | def test_optional_client_uses_token_when_available(): | CODE |
| LOW | observal_cli/tests/test_public_access.py | 60 | def test_post_public_uses_optional_auth_client(): | CODE |
| LOW | observal_cli/tests/test_registry_namespace_cli.py | 9 | def test_listings_render_the_bare_name_over_an_at_handle(): | CODE |
| 6058 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | observal_cli/upgrade_executor.py | 257 | except OSError: | CODE |
| HIGH | observal_cli/skill_folder.py | 540 | except OSError: | CODE |
| HIGH | observal_cli/lockfile.py | 682 | except Exception: | CODE |
| HIGH | observal_cli/lockfile.py | 769 | except OSError: | CODE |
| HIGH | observal_cli/telemetry_buffer.py | 103 | except OSError: | CODE |
| HIGH | observal_cli/render.py | 247 | except (ValueError, TypeError): | CODE |
| HIGH | observal_cli/cmd_ops.py | 760 | except ValueError: | CODE |
| HIGH | observal_cli/cmd_ops.py | 2072 | except InvalidVersion: | CODE |
| HIGH | observal_cli/cmd_ops.py | 2219 | except InvalidVersion: | CODE |
| HIGH | observal_cli/client.py | 367 | except ValueError: | CODE |
| HIGH | observal_cli/client.py | 380 | except Exception: | CODE |
| HIGH | observal_cli/client.py | 752 | except Exception: | CODE |
| HIGH | observal_cli/client.py | 775 | except Exception: | CODE |
| HIGH | observal_cli/sandbox_runner.py | 154 | except Exception: | CODE |
| HIGH | observal_cli/sandbox_runner.py | 203 | except OSError: | CODE |
| HIGH | observal_cli/cmd_auth.py | 539 | except (httpx.HTTPError, ValueError, TypeError): | CODE |
| HIGH | observal_cli/cmd_auth.py | 901 | except Exception: | CODE |
| HIGH | observal_cli/cmd_auth.py | 1503 | except (SystemExit, typer.Exit, typer.Abort): | CODE |
| HIGH | observal_cli/cmd_auth.py | 1557 | except Exception: | CODE |
| HIGH | observal_cli/cmd_auth.py | 1571 | except Exception: | CODE |
| HIGH | observal_cli/cmd_auth.py | 1736 | except Exception: | CODE |
| HIGH | observal_cli/cmd_auth.py | 1758 | except Exception: | CODE |
| HIGH | observal_cli/cmd_auth.py | 1782 | except Exception: | CODE |
| HIGH | observal_cli/cmd_auth.py | 1834 | except Exception: | CODE |
| HIGH | observal_cli/cmd_auth.py | 1536 | except (KeyError, NotSupportedError): | CODE |
| HIGH | observal_cli/layer.py | 314 | except OSError: | CODE |
| HIGH | observal_cli/layer.py | 541 | except (OSError, json.JSONDecodeError): | CODE |
| HIGH | observal_cli/layer.py | 551 | except (OSError, json.JSONDecodeError): | CODE |
| HIGH | observal_cli/layer.py | 570 | except OSError: | CODE |
| HIGH | observal_cli/version_check.py | 125 | except (FileNotFoundError, subprocess.TimeoutExpired, OSError): | CODE |
| HIGH | observal_cli/cmd_scan.py | 351 | except Exception: | CODE |
| HIGH | observal_cli/cmd_scan.py | 197 | except NotSupportedError: | CODE |
| HIGH | observal_cli/cmd_scan.py | 300 | except Exception: | CODE |
| HIGH | observal_cli/cmd_scan.py | 307 | except Exception: | CODE |
| HIGH | observal_cli/cmd_scan.py | 314 | except Exception: | CODE |
| HIGH | observal_cli/skill_installer.py | 288 | except (OSError, _json.JSONDecodeError): | CODE |
| HIGH | observal_cli/harness_specs/antigravity_hooks_spec.py | 77 | except Exception: | CODE |
| HIGH | observal_cli/harness_specs/goose_hooks_spec.py | 76 | except Exception: | CODE |
| HIGH | observal_cli/harness_specs/claude_code_hooks_spec.py | 42 | except Exception: | CODE |
| HIGH | observal_cli/harness_specs/copilot_cli_hooks_spec.py | 42 | except Exception: | CODE |
| HIGH | observal_cli/harness_specs/codex_hooks_spec.py | 33 | except Exception: | CODE |
| HIGH | observal_cli/harness_specs/kiro_hooks_spec.py | 54 | except Exception: | CODE |
| HIGH | observal_cli/server/backup.py | 222 | except (subprocess.TimeoutExpired, ValueError, OSError): | CODE |
| HIGH | observal_cli/server/updater.py | 88 | except (json.JSONDecodeError, KeyError): | CODE |
| HIGH | observal_cli/server/orchestrator.py | 63 | except (OSError, ValueError): | CODE |
| HIGH | observal_cli/server/orchestrator.py | 350 | except httpx.ConnectError: | CODE |
| HIGH | observal_cli/server/orchestrator.py | 373 | except (ProcessLookupError, ValueError): | CODE |
| HIGH | observal_cli/server/orchestrator.py | 450 | except (ProcessLookupError, ValueError): | CODE |
| HIGH | observal_cli/server/orchestrator.py | 575 | except (ProcessLookupError, ValueError): | CODE |
| HIGH | observal_cli/server/orchestrator.py | 636 | except (httpx.ConnectError, httpx.ReadTimeout): | CODE |
| HIGH | observal_cli/server/orchestrator.py | 790 | except Exception: | CODE |
| HIGH | observal_cli/shared/utils.py | 82 | except Exception: | CODE |
| HIGH | observal_cli/shared/utils.py | 100 | except Exception: | CODE |
| HIGH | observal_cli/delegation/local.py | 261 | except subprocess.TimeoutExpired: | CODE |
| HIGH | observal_cli/delegation/mcp_server.py | 245 | except KeyboardInterrupt: | CODE |
| HIGH | observal_cli/harness/goose.py | 424 | except OSError: | CODE |
| HIGH | observal_cli/harness/goose.py | 443 | except OSError: | CODE |
| HIGH | observal_cli/harness/copilot_cli.py | 201 | except (json.JSONDecodeError, OSError): | CODE |
| HIGH | observal_cli/harness/copilot_cli.py | 244 | except OSError: | CODE |
| HIGH | observal_cli/harness/copilot_cli.py | 277 | except OSError: | CODE |
| 105 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | conftest.py | 10 | CODE | |
| LOW | tools/release.py | 6 | CODE | |
| LOW | observal_cli/upgrade_executor.py | 9 | CODE | |
| LOW | observal_cli/project_lock.py | 16 | CODE | |
| LOW | observal_cli/cmd_recommend.py | 11 | CODE | |
| LOW | observal_cli/cmd_mcp_sync.py | 6 | CODE | |
| LOW | observal_cli/cmd_inbox.py | 6 | CODE | |
| LOW | observal_cli/skill_folder.py | 23 | CODE | |
| LOW | observal_cli/cmd_team.py | 6 | CODE | |
| LOW | observal_cli/cmd_discover.py | 25 | CODE | |
| LOW | observal_cli/cmd_support.py | 12 | CODE | |
| LOW | observal_cli/cmd_hook.py | 7 | CODE | |
| LOW | observal_cli/cmd_agent.py | 12 | CODE | |
| LOW | observal_cli/cmd_share.py | 7 | CODE | |
| LOW | observal_cli/lockfile.py | 18 | CODE | |
| LOW | observal_cli/cmd_delegate.py | 11 | CODE | |
| LOW | observal_cli/install_detector.py | 6 | CODE | |
| LOW | observal_cli/audit.py | 9 | CODE | |
| LOW | observal_cli/branding.py | 6 | CODE | |
| LOW | observal_cli/cmd_bulk.py | 6 | CODE | |
| LOW | observal_cli/telemetry_buffer.py | 10 | CODE | |
| LOW | observal_cli/render.py | 8 | CODE | |
| LOW | observal_cli/cmd_api.py | 6 | CODE | |
| LOW | observal_cli/cmd_ops.py | 10 | CODE | |
| LOW | observal_cli/cmd_component.py | 6 | CODE | |
| LOW | observal_cli/cmd_reconcile_cli.py | 6 | CODE | |
| LOW | observal_cli/cmd_pull.py | 14 | CODE | |
| LOW | observal_cli/constants.py | 16 | CODE | |
| LOW | observal_cli/analyzer.py | 6 | CODE | |
| LOW | observal_cli/sandbox_runner.py | 9 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 11 | CODE | |
| LOW | observal_cli/features.py | 17 | CODE | |
| LOW | observal_cli/error_context.py | 9 | CODE | |
| LOW | observal_cli/upgrade_lock.py | 10 | CODE | |
| LOW | observal_cli/lockfile_reconcile.py | 6 | CODE | |
| LOW | observal_cli/cmd_prompt.py | 10 | CODE | |
| LOW | observal_cli/prompts.py | 12 | CODE | |
| LOW | observal_cli/cmd_auth.py | 18 | CODE | |
| LOW | observal_cli/cmd_insights.py | 6 | CODE | |
| LOW | observal_cli/cmd_archive.py | 6 | CODE | |
| LOW | observal_cli/cmd_models.py | 8 | CODE | |
| LOW | observal_cli/cmd_outdated.py | 7 | CODE | |
| LOW | observal_cli/model_catalog.py | 8 | CODE | |
| LOW | observal_cli/cmd_server.py | 11 | CODE | |
| LOW | observal_cli/cmd_co_authors.py | 6 | CODE | |
| LOW | observal_cli/sandbox_mcp.py | 19 | CODE | |
| LOW | observal_cli/managed_skill.py | 11 | CODE | |
| LOW | observal_cli/layer.py | 15 | CODE | |
| LOW | observal_cli/optic.py | 16 | CODE | |
| LOW | observal_cli/cmd_skill.py | 10 | CODE | |
| LOW | observal_cli/cmd_sandbox.py | 9 | CODE | |
| LOW | observal_cli/version_check.py | 19 | CODE | |
| LOW | observal_cli/errors.py | 6 | CODE | |
| LOW | observal_cli/cmd_a2a.py | 7 | CODE | |
| LOW | observal_cli/cmd_scan.py | 15 | CODE | |
| LOW | observal_cli/cmd_transfer.py | 6 | CODE | |
| LOW | observal_cli/cmd_migrate.py | 15 | CODE | |
| LOW | observal_cli/cmd_migrate.py | 53 | CODE | |
| LOW | observal_cli/cmd_migrate.py | 101 | CODE | |
| LOW | observal_cli/capability_lock.py | 20 | CODE | |
| 628 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | observal_cli/server/updater.py | 222 | " If the server is running, restart it: [cyan]observal server stop && observal server start[/cyan]" | CODE |
| HIGH | tests/test_observal_skill.py | 19 | cd observal-server && uv run --with typer --with rich --with loguru \\ | STRING |
| HIGH | tests/test_pi_session_parser.py | 25 | MODEL_CHANGE = '{"type":"model_change","id":"d6ec41d1","parentId":null,"timestamp":"2026-05-24T09:04:17.964Z","provider" | CODE |
| HIGH | tests/test_observal_skill_sync.py | 9 | cd observal-server && uv run --with typer --with rich --with loguru \\ | STRING |
| HIGH | tests/test_opencode_session_delivery.py | 93 | assert.equal(state.pending, null); | STRING |
| HIGH | tests/test_opencode_session_delivery.py | 105 | assert.equal(repair.pending, null); | STRING |
| HIGH⚡ | tests/test_opencode_session_delivery.py | 147 | if (!options.method || options.method === "GET") { | STRING |
| HIGH⚡ | tests/test_opencode_session_delivery.py | 152 | ingestPayloads.push(payload); | STRING |
| HIGH⚡ | tests/test_opencode_session_delivery.py | 154 | if (repairFinalOnce && payload.final) { | STRING |
| HIGH | tests/test_opencode_session_delivery.py | 177 | assert.equal(delivery.pending, null); | STRING |
| HIGH | tests/test_opencode_session_delivery.py | 187 | assert.equal(recovered.pending, null); | STRING |
| HIGH | tests/test_opencode_session_delivery.py | 201 | assert.equal(large.pending, null); | STRING |
| HIGH⚡ | tests/test_managed_skill.py | 141 | ('{"lock_version": 2, "registries": {"https://example.org": null}}', "Invalid machine lockfile structure"), | CODE |
| HIGH⚡ | tests/test_managed_skill.py | 143 | '{"lock_version": 2, "registries": {"https://example.org": {"harnesses": {"pi": {"standalone": [null]}}}}}', | CODE |
| HIGH⚡ | tests/test_claude_code_session_parser.py | 23 | {"parentUuid":"user-1","isSidechain":false,"message":{"model":"claude-opus-4-6","id":"msg-1","type":"message","role":"as | CODE |
| HIGH⚡ | tests/test_claude_code_session_parser.py | 24 | {"parentUuid":"assistant-1","isSidechain":false,"message":{"model":"claude-opus-4-6","id":"msg-1","type":"message","role | CODE |
| HIGH⚡ | tests/test_claude_code_session_parser.py | 26 | {"parentUuid":"user-2","isSidechain":false,"message":{"model":"claude-opus-4-6","id":"msg-2","type":"message","role":"as | CODE |
| HIGH | tests/test_historical_component_columns_postgres.py | 70 | "SELECT column_name, data_type || CASE WHEN character_maximum_length IS NOT NULL " | CODE |
| HIGH | tests/test_dynamic_settings.py | 243 | AsyncMock(side_effect=["", "", "YES", "off", " alpha, beta ,, gamma ", "", "one | two || three"]), | CODE |
| HIGH | tests/test_migration_frontend.py | 9 | cd web && pnpm test | STRING |
| HIGH | tests/test_server_updater.py | 472 | " If the server is running, restart it: [cyan]observal server stop && observal server start[/cyan]", | CODE |
| HIGH | observal-server/tests/test_exec_dashboard.py | 8 | Run with: cd observal-server && pytest tests/test_exec_dashboard.py -v | STRING |
| HIGH | observal-server/schemas/skill.py | 107 | raise ValueError("extra_files cannot be null; use [] to clear") | CODE |
| HIGH | …l-server/alembic/versions/019_team_listing_restrict.py | 8 | null, and every member except the original submitter lost access. The application | STRING |
| HIGH | observal-server/services/component_version_extras.py | 245 | raise HTTPException(status_code=422, detail="extra_files cannot be null; use [] to clear") | CODE |
| HIGH | observal-server/services/insights/html_export.py | 632 | for(var ch of checks){{lines.push(ch.dataset.addition);lines.push('')}} | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 31 | if (!existsSync(CONFIG_PATH)) return null; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 33 | const token = cfg.api_key || cfg.access_token; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 34 | if (!cfg.server_url || !token || !cfg.user_id) return null; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 37 | return null; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 46 | return url.toString().replace(/\\/$/, ""); | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 52 | if (!config || !existsSync(LOCKFILE_PATH)) return null; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 54 | return data.registries?.[registryKey(config.server_url)] || null; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 56 | return null; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 61 | if (!agentName || BUILTIN_AGENTS.has(agentName)) return null; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 61 | if (!agentName || BUILTIN_AGENTS.has(agentName)) return null; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 63 | if (!Array.isArray(agents)) return null; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 64 | const matches = agents.filter((agent) => agent?.name === agentName || agent?.id === agentName); | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 65 | if (matches.length === 0) return null; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 70 | if (!chosen?.id) return null; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 71 | return { id: chosen.id, version: chosen.version || null }; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 71 | return { id: chosen.id, version: chosen.version || null }; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 199 | return null; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 204 | return null; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 209 | return null; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 306 | const info = msg.info || msg; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 311 | content.push({ type: "text", text: part.text || "" }); | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 313 | content.push({ type: "tool_use", id: part.toolInvocationId || part.id || "", name: part.toolName || part.name || | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 313 | content.push({ type: "tool_use", id: part.toolInvocationId || part.id || "", name: part.toolName || part.name || | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 315 | content.push({ type: "tool_result", tool_use_id: part.toolInvocationId || part.tool_use_id || "", content: part. | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 315 | content.push({ type: "tool_result", tool_use_id: part.toolInvocationId || part.tool_use_id || "", content: part. | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 317 | content.push({ type: "thinking", thinking: part.text || part.thinking || "" }); | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 317 | content.push({ type: "thinking", thinking: part.text || part.thinking || "" }); | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 322 | if (info.createdAt && typeof info.createdAt === "string") { ts = info.createdAt; } | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 323 | else if (info.time && typeof info.time === "object" && info.time.created) { ts = new Date(info.time.created).toISOSt | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 324 | else if (info.time && typeof info.time === "string") { ts = info.time; } | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 325 | else if (info.timestamp && typeof info.timestamp === "string") { ts = info.timestamp; } | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 330 | parentUuid: info.parentID || info.parentId || "", | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 331 | message: { role, content, model: info.modelID || info.model || "" }, | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 333 | if (info.tokens || info.usage) { | CODE |
| 29 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | observal_cli/cmd_agent.py | 1608 | # Optional per-harness model overrides, e.g. {"kiro": "claude-haiku-4-5"}. | COMMENT |
| MEDIUM | observal_cli/lockfile.py | 244 | # Local names become harness config keys and on-disk names, where a dot reads | COMMENT |
| MEDIUM | observal_cli/lockfile.py | 740 | # We don't know which harness was used, default to claude-code | COMMENT |
| MEDIUM⚡ | observal_cli/render.py | 179 | # ── harness tag rendering ──────────────────────────────────── | COMMENT |
| MEDIUM | observal_cli/cmd_pull.py | 1221 | # validates the candidate against the harness registry and falls | COMMENT |
| MEDIUM | observal_cli/cmd_pull.py | 2692 | # Run required harness registration before recording the pull as installed. | COMMENT |
| MEDIUM | observal_cli/cmd_doctor.py | 1329 | # no usable Kiro agents - otherwise the harness emits no telemetry at all. | COMMENT |
| MEDIUM⚡ | observal_cli/constants.py | 25 | # ── harness / client names (hyphen-canonical) ─────────────────── | COMMENT |
| MEDIUM⚡ | observal_cli/constants.py | 29 | # ── harness feature capabilities ────────────────────────────────── | COMMENT |
| MEDIUM | observal_cli/cmd_mcp.py | 748 | # MCP servers are harness-agnostic - config generation handles all harnesses. | COMMENT |
| MEDIUM | observal_cli/managed_skill.py | 557 | # One level up, so a crash can never leave a SKILL.md where a harness scans for skills, unless that | COMMENT |
| MEDIUM⚡ | observal_cli/layer.py | 40 | # Per-harness file discovery configuration | COMMENT |
| MEDIUM⚡ | observal_cli/layer.py | 43 | # Maps harness name → dict of scope → list of (base_dir, glob_patterns) | COMMENT |
| MEDIUM⚡ | observal_cli/layer.py | 480 | # Multi-harness layer hash computation | COMMENT |
| MEDIUM | observal_cli/layer.py | 424 | # Safety cap: max 200 files per manifest. If an harness config dir | COMMENT |
| MEDIUM | observal_cli/layer.py | 519 | # Prefix with harness name for uniqueness across harnesses | COMMENT |
| MEDIUM | observal_cli/layer.py | 625 | # Flatten local snapshot (structured by harness) | COMMENT |
| MEDIUM | observal_cli/layer.py | 751 | # Build lookup of actual file hashes for this harness | COMMENT |
| MEDIUM | observal_cli/cmd_skill.py | 1517 | # User-scope skill directories per harness (global install locations) | COMMENT |
| MEDIUM | observal_cli/cmd_scan.py | 36 | # ── harness home directory paths (for status display) ──────────────── | COMMENT |
| MEDIUM | observal_cli/cmd_scan.py | 99 | # Validate harness filter | COMMENT |
| MEDIUM | observal_cli/cmd_scan.py | 180 | # Determine status for this harness | COMMENT |
| MEDIUM | observal_cli/capability_lock.py | 42 | MODE_NEXT_SESSION = "next-session" # harness config written, effective after restart | CODE |
| MEDIUM⚡ | observal_cli/tests/test_cmd_auth.py | 630 | # ── post-login harness detection ─────────────────────────────── | COMMENT |
| MEDIUM | observal_cli/tests/test_cmd_scan.py | 83 | # The harness detection table should list kiro | COMMENT |
| MEDIUM | observal_cli/tests/test_cmd_scan.py | 109 | # Claude Code entry — should NOT appear under --harness kiro | COMMENT |
| MEDIUM | observal_cli/server/orchestrator.py | 746 | # Install harness hooks for telemetry (non-interactive) | COMMENT |
| MEDIUM | observal_cli/delegation/local.py | 76 | env["OBSERVAL_AGENT_VERSION"] = str(m["version"]) # read by harness extensions that attribute sessions | CODE |
| MEDIUM | observal_cli/delegation/local.py | 293 | # Some harness CLIs exit 0 after an auth or quota error, printing only to | COMMENT |
| MEDIUM⚡ | observal_cli/sessions/base.py | 938 | # Prefer a harness-scoped match, but fall back to an unscoped UUID | COMMENT |
| MEDIUM⚡ | observal_cli/sessions/base.py | 939 | # lookup. A UUID is globally unique, and the harness recorded at pull | COMMENT |
| MEDIUM⚡ | observal_cli/sessions/base.py | 942 | # defaults harness to "claude-code" when a caller sets payload["harness"] | COMMENT |
| MEDIUM | observal_cli/sessions/base.py | 725 | # harness creates the transcript. | COMMENT |
| MEDIUM | observal_cli/sessions/base.py | 813 | # Per-session layer_hash cache: avoids re-scanning harness dirs on every chunk | COMMENT |
| MEDIUM⚡ | tests/test_harness_registry.py | 102 | # These values were verified against harness docs or adapter code when they | COMMENT |
| MEDIUM⚡ | tests/test_harness_registry.py | 103 | # were recorded (see the per-harness comments in harness_registry.py). A | COMMENT |
| MEDIUM | tests/conftest.py | 10 | # harness config directories when they are imported, so a test that forgets to | COMMENT |
| MEDIUM | tests/conftest.py | 12 | # harness settings. Set before anything imports observal_cli. | COMMENT |
| MEDIUM⚡ | tests/test_copilot_integration.py | 91 | # Test that an unknown harness raises KeyError (not silently falls through) | COMMENT |
| MEDIUM⚡ | tests/test_copilot_integration.py | 476 | # Agent is stored only under the 'copilot' harness key. | COMMENT |
| MEDIUM⚡ | tests/test_copilot_integration.py | 483 | # harness reported by the push payload differs from the lockfile key | COMMENT |
| MEDIUM⚡ | tests/test_copilot_integration.py | 485 | # build_payload's default harness also differs | COMMENT |
| MEDIUM⚡ | tests/test_harness_config_e2e.py | 464 | # 3. harness COMPATIBILITY WARNINGS | COMMENT |
| MEDIUM⚡ | tests/test_harness_config_e2e.py | 669 | # 8. PULL — Full CLI flow (E2E per harness) | COMMENT |
| MEDIUM⚡ | tests/test_harness_config_e2e.py | 911 | # 9. CROSS-CUTTING — format correctness per harness spec | COMMENT |
| MEDIUM⚡ | tests/test_harness_config_e2e.py | 977 | # 10. DOCTOR — Copilot harness config checks | COMMENT |
| MEDIUM⚡ | tests/test_harness_config_e2e.py | 1086 | # 13. DOCTOR — OpenCode harness config checks | COMMENT |
| MEDIUM | tests/test_harness_config_e2e.py | 8 | """Comprehensive end-to-end tests for issue #434: first-class harness support. | STRING |
| MEDIUM⚡ | tests/test_skill_install_contract_fixture.py | 259 | return # These adapters have no user-scoped Agent profile in the harness registry. | CODE |
| MEDIUM⚡ | tests/test_skill_install_contract_fixture.py | 263 | # The pull client requires exactly one component naming the bundle and its destination, for every harness. | COMMENT |
| MEDIUM | tests/test_skill_cross_mode.py | 199 | # A no-write request avoids touching a harness, but still exercises | COMMENT |
| MEDIUM | tests/test_antigravity_sessions.py | 205 | # ── Server harness adapter ──────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | tests/test_managed_skill.py | 686 | assert stage.parent == target.parent.parent # never inside the directory a harness scans for skills | CODE |
| MEDIUM | tests/test_a2a_registry.py | 567 | assert json.dumps(entry) # serialisable into every harness config format | CODE |
| MEDIUM⚡ | observal-server/tests/test_agent_versions_api.py | 738 | # 5. harness config endpoint | COMMENT |
| MEDIUM | observal-server/tests/test_agent_versions_api.py | 773 | ver.harness_configs = {} # no cached config for requested harness | CODE |
| MEDIUM⚡ | observal-server/models/agent.py | 46 | # Per-harness model overrides: {"claude-code": "claude-sonnet-4-5", "kiro": "claude-opus-4-5", ...} | COMMENT |
| MEDIUM⚡ | observal-server/models/agent.py | 47 | # Empty dict means "use model_name as the default for every harness that accepts a model choice". | COMMENT |
| MEDIUM⚡ | observal-server/models/agent.py | 48 | # Missing key for an harness that accepts a choice means "emit auto sentinel". | COMMENT |
| MEDIUM⚡ | observal-server/schemas/constants.py | 32 | # ── harness / client names (hyphen-canonical) ─────────────────── | COMMENT |
| 54 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | infra/terraform/deploy.sh | 239 | except Exception: | CODE |
| LOW | infra/terraform/aws/deploy.sh | 178 | except Exception: | CODE |
| LOW | tools/release.py | 637 | except Exception: | STRING |
| LOW | tools/release.py | 867 | except Exception: | STRING |
| LOW | observal_cli/skill_folder.py | 352 | except Exception as e: | CODE |
| LOW | observal_cli/skill_folder.py | 533 | except Exception as e: | CODE |
| LOW | observal_cli/cmd_discover.py | 134 | except Exception: | CODE |
| LOW | observal_cli/cmd_support.py | 140 | except Exception as exc: | CODE |
| LOW | observal_cli/cmd_support.py | 194 | except Exception: | CODE |
| LOW⚡ | observal_cli/cmd_support.py | 217 | except Exception: | CODE |
| LOW | observal_cli/cmd_support.py | 386 | except Exception as exc: | CODE |
| MEDIUM | observal_cli/cmd_support.py | 212 | def _get_cli_version() -> str: | CODE |
| LOW | observal_cli/lockfile.py | 300 | except Exception as exc: | CODE |
| LOW | observal_cli/lockfile.py | 682 | except Exception: | CODE |
| LOW | observal_cli/audit.py | 62 | except Exception as e: | CODE |
| MEDIUM | observal_cli/audit.py | 50 | def _send(): | CODE |
| LOW | observal_cli/render.py | 87 | except Exception: | CODE |
| LOW | observal_cli/cmd_ops.py | 1962 | except Exception as error: | CODE |
| LOW | observal_cli/client.py | 42 | except Exception: | CODE |
| LOW | observal_cli/client.py | 258 | except Exception: | CODE |
| LOW | observal_cli/client.py | 380 | except Exception: | CODE |
| LOW | observal_cli/client.py | 730 | except Exception: | CODE |
| LOW | observal_cli/client.py | 752 | except Exception: | CODE |
| LOW | observal_cli/client.py | 775 | except Exception: | CODE |
| LOW | observal_cli/client.py | 791 | except Exception: | CODE |
| LOW | observal_cli/client.py | 807 | except Exception: | CODE |
| LOW | observal_cli/client.py | 817 | except Exception: | CODE |
| LOW | observal_cli/cmd_doctor.py | 154 | except Exception as error: | CODE |
| LOW | observal_cli/cmd_doctor.py | 250 | except Exception as e: | CODE |
| LOW | observal_cli/cmd_doctor.py | 321 | except Exception: | CODE |
| LOW | observal_cli/cmd_doctor.py | 918 | except Exception as exc: | CODE |
| LOW | observal_cli/analyzer.py | 132 | except Exception: | CODE |
| LOW⚡ | observal_cli/sandbox_runner.py | 147 | except Exception as e: | CODE |
| MEDIUM⚡ | observal_cli/sandbox_runner.py | 148 | print(f"Error: {e}", file=sys.stderr) | CODE |
| LOW⚡ | observal_cli/sandbox_runner.py | 154 | except Exception: | CODE |
| LOW⚡ | observal_cli/cmd_auth.py | 1557 | except Exception: | CODE |
| LOW⚡ | observal_cli/cmd_auth.py | 1571 | except Exception: | CODE |
| LOW | observal_cli/cmd_auth.py | 254 | except Exception: | CODE |
| LOW | observal_cli/cmd_auth.py | 361 | except Exception as error: | CODE |
| LOW | observal_cli/cmd_auth.py | 743 | except Exception as error: | CODE |
| LOW | observal_cli/cmd_auth.py | 882 | except Exception: | CODE |
| LOW | observal_cli/cmd_auth.py | 901 | except Exception: | CODE |
| LOW | observal_cli/cmd_auth.py | 1119 | except Exception: | CODE |
| LOW | observal_cli/cmd_auth.py | 1505 | except Exception as e: | CODE |
| LOW | observal_cli/cmd_auth.py | 1612 | except Exception as exc: | CODE |
| LOW | observal_cli/cmd_auth.py | 1638 | except Exception as e: | CODE |
| LOW | observal_cli/cmd_auth.py | 1661 | except Exception as e: | CODE |
| LOW | observal_cli/cmd_auth.py | 1684 | except Exception as e: | CODE |
| LOW | observal_cli/cmd_auth.py | 1707 | except Exception as e: | CODE |
| LOW | observal_cli/cmd_auth.py | 1736 | except Exception: | CODE |
| LOW | observal_cli/cmd_auth.py | 1758 | except Exception: | CODE |
| LOW | observal_cli/cmd_auth.py | 1782 | except Exception: | CODE |
| LOW | observal_cli/cmd_auth.py | 1815 | except Exception as e: | CODE |
| LOW | observal_cli/cmd_auth.py | 1834 | except Exception: | CODE |
| LOW | observal_cli/cmd_insights.py | 73 | except Exception: | CODE |
| LOW | observal_cli/cmd_server.py | 55 | except Exception as error: | CODE |
| LOW | observal_cli/sandbox_mcp.py | 263 | except Exception as e: | CODE |
| LOW | observal_cli/managed_skill.py | 678 | except Exception as exc: | CODE |
| LOW | observal_cli/managed_skill.py | 716 | except Exception as recovery_error: | CODE |
| LOW | observal_cli/managed_skill.py | 726 | except Exception as recovery_error: | CODE |
| 305 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tools/release.py | 881 | CODE | |
| LOW | observal_cli/upgrade_executor.py | 33 | CODE | |
| LOW | observal_cli/upgrade_executor.py | 166 | CODE | |
| LOW | observal_cli/skill_folder.py | 382 | CODE | |
| LOW | observal_cli/skill_folder.py | 441 | CODE | |
| LOW | observal_cli/cmd_support.py | 225 | CODE | |
| LOW | observal_cli/cmd_hook.py | 99 | CODE | |
| LOW | observal_cli/cmd_agent.py | 1831 | CODE | |
| LOW | observal_cli/lockfile.py | 392 | CODE | |
| LOW | observal_cli/lockfile.py | 504 | CODE | |
| LOW | observal_cli/lockfile.py | 660 | CODE | |
| LOW | observal_cli/cmd_ops.py | 1843 | CODE | |
| LOW | observal_cli/cmd_reconcile_cli.py | 36 | CODE | |
| LOW | observal_cli/cmd_reconcile_cli.py | 154 | CODE | |
| LOW | observal_cli/cmd_pull.py | 177 | CODE | |
| LOW | observal_cli/cmd_pull.py | 288 | CODE | |
| LOW | observal_cli/cmd_pull.py | 367 | CODE | |
| LOW | observal_cli/cmd_pull.py | 437 | CODE | |
| LOW | observal_cli/cmd_pull.py | 537 | CODE | |
| LOW | observal_cli/cmd_pull.py | 715 | CODE | |
| LOW | observal_cli/cmd_pull.py | 1162 | CODE | |
| LOW | observal_cli/cmd_pull.py | 1565 | CODE | |
| LOW | observal_cli/cmd_pull.py | 1625 | CODE | |
| LOW | observal_cli/cmd_pull.py | 2094 | CODE | |
| LOW | observal_cli/cmd_pull.py | 2096 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 95 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 254 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 305 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 393 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 434 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 549 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 793 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 852 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 982 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 1027 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 1283 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 1479 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 1518 | CODE | |
| LOW | observal_cli/sandbox_runner.py | 248 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 293 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 359 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 462 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 513 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 1099 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 1589 | CODE | |
| LOW | observal_cli/upgrade_lock.py | 30 | CODE | |
| LOW | observal_cli/lockfile_reconcile.py | 46 | CODE | |
| LOW | observal_cli/lockfile_reconcile.py | 81 | CODE | |
| LOW | observal_cli/cmd_auth.py | 285 | CODE | |
| LOW | observal_cli/cmd_auth.py | 1007 | CODE | |
| LOW | observal_cli/cmd_auth.py | 1582 | CODE | |
| LOW | observal_cli/cmd_insights.py | 665 | CODE | |
| LOW | observal_cli/cmd_outdated.py | 26 | CODE | |
| LOW | observal_cli/cmd_outdated.py | 28 | CODE | |
| LOW | observal_cli/cmd_server.py | 354 | CODE | |
| LOW | observal_cli/cmd_server.py | 595 | CODE | |
| LOW | observal_cli/cmd_server.py | 621 | CODE | |
| LOW | observal_cli/cmd_server.py | 669 | CODE | |
| LOW | observal_cli/cmd_server.py | 911 | CODE | |
| LOW | observal_cli/sandbox_mcp.py | 78 | CODE | |
| 202 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | CHANGELOG.md | 831 | - fix reuse-lint and dependency-audit for fake-key fixture ([de356e7](https://github.com/Observal/Observal/commit/de356e | CODE |
| LOW | CHANGELOG.md | 2151 | - add secret_scanning.yml paths-ignore for fake-key test fixtures ([54faf17](https://github.com/Observal/Observal/commit | CODE |
| LOW⚡ | .pre-commit-config.yaml | 25 | # Keep the pre-generated fake-key fixture byte-identical; staging its | COMMENT |
| LOW | web/src/pages/user/traces/index.tsx | 95 | // ── Search query parser (Discord-style: platform:kiro user:"John Doe") ─────── | COMMENT |
| LOW⚡ | tests/test_cli_errors.py | 934 | url = "https://fake-user:fake-password@registry.example.test:8443/api/v1/items" | CODE |
| LOW⚡ | tests/test_cli_errors.py | 943 | assert "fake-user" not in debug_calls | CODE |
| LOW⚡ | tests/test_google_oauth.py | 151 | fake_user = MagicMock() | CODE |
| LOW⚡ | tests/test_google_oauth.py | 152 | fake_user.id = "u-1" | CODE |
| LOW⚡ | tests/test_google_oauth.py | 153 | fake_user.email = "alice@acme.com" | CODE |
| LOW⚡ | tests/test_google_oauth.py | 154 | fake_user.role = MagicMock(value="user") | CODE |
| LOW⚡ | tests/test_google_oauth.py | 156 | provision_mock = AsyncMock(return_value=fake_user) | CODE |
| LOW | tests/test_demo_accounts.py | 17 | def _make_user(role=UserRole.user, is_demo=False, email="test@test.com"): | CODE |
| LOW | tests/test_cli_doctor_commands.py | 279 | {"access_token": "placeholder", "server_url": "https://server.test"}, | CODE |
| LOW⚡ | tests/test_saml.py | 814 | mock_auth.get_nameid.return_value = "user@example.com" | CODE |
| LOW⚡ | tests/test_saml.py | 819 | mock_user.email = "user@example.com" | CODE |
| LOW⚡ | tests/test_saml.py | 825 | mock_user.sso_subject_id = "user@example.com" | CODE |
| LOW⚡ | tests/test_saml.py | 1200 | mock_auth.get_nameid.return_value = "user@example.com" | CODE |
| LOW⚡ | tests/test_saml.py | 1205 | mock_user.email = "user@example.com" | CODE |
| LOW⚡ | tests/test_saml.py | 1211 | mock_user.sso_subject_id = "user@example.com" | CODE |
| LOW⚡ | tests/test_saml.py | 1291 | mock_auth.get_nameid.return_value = "user@example.com" | CODE |
| LOW⚡ | tests/test_saml.py | 1296 | mock_user.email = "user@example.com" | CODE |
| LOW⚡ | tests/test_saml.py | 1302 | mock_user.sso_subject_id = "user@example.com" | CODE |
| LOW⚡ | tests/test_sec028_sso_guards.py | 43 | "email": "admin@example.com", | CODE |
| LOW | tests/test_sec028_sso_guards.py | 91 | "email": "admin@example.com", | CODE |
| LOW | tests/test_retention_endpoints.py | 18 | user.email = "admin@example.com" | CODE |
| LOW⚡ | tests/test_device_auth.py | 566 | headers={"Authorization": "Bearer fake-token"}, | CODE |
| LOW | tests/test_device_auth.py | 398 | headers={"Authorization": "Bearer fake-token"}, | CODE |
| LOW | tests/test_device_auth.py | 428 | headers={"Authorization": "Bearer fake-token"}, | CODE |
| LOW | tests/test_device_auth.py | 466 | headers={"Authorization": "Bearer fake-token"}, | CODE |
| LOW | tests/test_device_auth.py | 503 | headers={"Authorization": "Bearer fake-token"}, | CODE |
| LOW | tests/test_sec006_password_policy.py | 221 | headers={"Authorization": "Bearer fake-token"}, | CODE |
| LOW | tests/test_audit_logging.py | 117 | actor_email="admin@example.com", | CODE |
| LOW | tests/test_audit_logging.py | 157 | actor_email="admin@example.com", | CODE |
| LOW | tests/test_audit_logging.py | 220 | "actor_email": "admin@example.com", | CODE |
| LOW | tests/test_audit_logging.py | 254 | assert result[0]["actor_email"] == "admin@example.com" | CODE |
| LOW | tests/test_audit_logging.py | 289 | "actor_email": "admin@example.com", | CODE |
| LOW | tests/test_audit_logging.py | 311 | actor="admin@example.com", | CODE |
| LOW | tests/test_audit_logging.py | 328 | assert params_arg["param_actor"] == "admin@example.com" | CODE |
| LOW⚡ | tests/test_auth2_security.py | 248 | headers={"Authorization": "Bearer fake-token"}, | CODE |
| LOW⚡ | tests/test_auth2_security.py | 325 | headers={"Authorization": "Bearer fake-token"}, | CODE |
| LOW | tests/test_auth2_security.py | 138 | headers={"Authorization": "Bearer fake-token"}, | CODE |
| LOW | tests/test_auth2_security.py | 165 | headers={"Authorization": "Bearer fake-token"}, | CODE |
| LOW | tests/test_auth2_security.py | 193 | headers={"Authorization": "Bearer fake-token"}, | CODE |
| LOW | tests/test_auth2_security.py | 221 | headers={"Authorization": "Bearer fake-token"}, | CODE |
| LOW | tests/test_auth2_security.py | 278 | headers={"Authorization": "Bearer fake-token"}, | CODE |
| LOW | tests/test_auth2_security.py | 301 | headers={"Authorization": "Bearer fake-token"}, | CODE |
| LOW⚡ | tests/test_saml_scim_integration.py | 35 | result = parse_scim_filter('userName eq "user@example.com"') | CODE |
| LOW⚡ | tests/test_saml_scim_integration.py | 39 | assert result.value == "user@example.com" | CODE |
| LOW⚡ | tests/test_saml_scim_integration.py | 98 | result = parse_scim_filter(' userName eq "user@example.com" ') | CODE |
| LOW⚡ | tests/test_saml_scim_integration.py | 102 | assert result.value == "user@example.com" | CODE |
| LOW⚡ | tests/test_saml_scim_integration.py | 107 | result = parse_scim_filter('userName EQ "user@example.com"') | CODE |
| LOW⚡ | tests/test_admin_sso_routes.py | 509 | _config(idp_entity_id="", sp_private_key_enc="", external_sp_private_key="external-fake-key") | CODE |
| LOW⚡ | tests/test_admin_sso_routes.py | 514 | sso._required_field_check(_config(sp_private_key_enc="", external_sp_private_key="external-fake-key")) is None | CODE |
| LOW⚡ | tests/test_auth_route_coverage.py | 287 | await auth.init_admin(InitRequest(email="admin@example.com", name="Admin"), initialized) | CODE |
| LOW⚡ | tests/test_auth_route_coverage.py | 293 | await auth.init_admin(InitRequest(email="admin@example.com", name="Admin"), invalid_name) | CODE |
| LOW⚡ | tests/test_auth_route_coverage.py | 300 | await auth.init_admin(InitRequest(email="admin@example.com", name="Admin"), conflict) | CODE |
| LOW | tests/test_auth_route_coverage.py | 313 | InitRequest(email="admin@example.com", name="Admin", password="Valid1!Password"), fresh | CODE |
| LOW | tests/test_git_mirror.py | 33 | subprocess.run(["git", "config", "user.email", "test@test.com"], cwd=str(path), capture_output=True, check=True) | CODE |
| LOW | tests/test_docker_detection.py | 362 | "JIRA_EMAIL": "user@example.com", | CODE |
| LOW⚡ | tests/test_github_oauth.py | 158 | fake_user = MagicMock() | CODE |
| 17 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/test_device_auth.py | 544 | # Step 1: CLI requests device authorization | COMMENT |
| LOW⚡ | tests/test_device_auth.py | 551 | # Step 2: CLI polls -- should get authorization_pending | COMMENT |
| LOW⚡ | tests/test_device_auth.py | 562 | # Step 3: User confirms in browser | COMMENT |
| LOW⚡ | tests/test_device_auth.py | 570 | # Step 4: CLI polls again -- should get tokens | COMMENT |
| LOW | tests/test_device_auth.py | 586 | # Step 5: Polling again should return expired_token (keys cleaned up) | COMMENT |
| LOW⚡ | observal-server/api/routes/auth.py | 627 | # Step 1: exchange the authorization code for tokens. | COMMENT |
| LOW⚡ | observal-server/api/routes/auth.py | 738 | # Step 5: user lookup / JIT. | COMMENT |
| LOW⚡ | observal-server/api/routes/auth.py | 812 | # Step 6: persist SSO groups (best-effort, never blocks login). | COMMENT |
| LOW⚡ | observal-server/api/routes/auth.py | 820 | # Step 7: issue tokens + commit. | COMMENT |
| LOW⚡ | observal-server/api/routes/auth.py | 833 | # Step 8: hand off via short-lived code in Redis. | COMMENT |
| LOW | observal-server/api/routes/auth.py | 655 | # Step 2: extract userinfo (merged ID-token + /userinfo claims by authlib). | COMMENT |
| LOW | observal-server/api/routes/auth.py | 671 | # Step 3: required email claim. | COMMENT |
| LOW | observal-server/api/routes/auth.py | 689 | # Step 4: name + groups (non-fatal absences are 'skip'). | COMMENT |
| LOW⚡ | observal-server/api/routes/sso_saml.py | 516 | # Step 1: decrypt SP signing key. | COMMENT |
| LOW⚡ | observal-server/api/routes/sso_saml.py | 533 | # Step 2: process the Response (signature, audience, conditions). | COMMENT |
| LOW⚡ | observal-server/api/routes/sso_saml.py | 658 | # Step 4: extract NameID + attributes. | COMMENT |
| LOW⚡ | observal-server/api/routes/sso_saml.py | 720 | # Step 5: user lookup / JIT (real-login mode). | COMMENT |
| LOW⚡ | observal-server/api/routes/sso_saml.py | 814 | # Step 6: issue tokens + commit. | COMMENT |
| LOW | observal-server/api/routes/sso_saml.py | 595 | # Step 3: replay protection. | COMMENT |
| LOW | observal-server/services/user_profile.py | 204 | # Step 1: user -> sessions, via the table that indexes user_id. | COMMENT |
| LOW | observal-server/services/user_profile.py | 232 | # Step 2: sessions -> tool usage, keyed on the indexed session_id column. | COMMENT |
| LOW | observal-server/services/user_profile.py | 261 | # Step 3: file extensions -> languages, from tool-call previews. | COMMENT |
| LOW | docs/adding-a-harness.md | 42 | ## Step 1: Research the harness | COMMENT |
| LOW | docs/adding-a-harness.md | 72 | ## Step 2: Add Harness Registry Entry | COMMENT |
| LOW | docs/adding-a-harness.md | 157 | ## Step 3: Create CLI Adapter (Scanning) | COMMENT |
| LOW | docs/adding-a-harness.md | 329 | ## Step 4: Create Server-Side Config Generator (Install) | COMMENT |
| LOW | docs/adding-a-harness.md | 367 | ## Step 5: Create Hook Spec | COMMENT |
| LOW | docs/adding-a-harness.md | 409 | ## Step 6: Add the Session Source Adapter and Parser (required) | COMMENT |
| LOW | docs/adding-a-harness.md | 436 | ## Step 7: Configure the Shared Session Hook | COMMENT |
| LOW | docs/adding-a-harness.md | 446 | ## Step 8: Register Everything | COMMENT |
| LOW | docs/adding-a-harness.md | 465 | ## Step 9: Tests | COMMENT |
| LOW | docs/adding-a-harness.md | 539 | ## Step 10: Verify | COMMENT |
| LOW | docs/self-hosting/okta-setup.md | 47 | ### Step 1 - Sign in to the Okta Admin Console | COMMENT |
| LOW | docs/self-hosting/okta-setup.md | 57 | ### Step 2 - Create the OIDC application | COMMENT |
| LOW | docs/self-hosting/okta-setup.md | 107 | ### Step 3 - Configure application sign-on settings (optional but recommended) | COMMENT |
| LOW | docs/self-hosting/okta-setup.md | 120 | ### Step 4 - Create groups (teams / departments) | COMMENT |
| LOW | docs/self-hosting/okta-setup.md | 141 | ### Step 5 - Create people (users) | COMMENT |
| LOW | docs/self-hosting/okta-setup.md | 161 | ### Step 6 - Add people to groups | COMMENT |
| LOW | docs/self-hosting/okta-setup.md | 177 | ### Step 7 - Assign groups to the Observal application | COMMENT |
| LOW | docs/self-hosting/okta-setup.md | 194 | ### Step 8 - Authentication policies (MFA and sign-on rules) | COMMENT |
| LOW | docs/self-hosting/okta-setup.md | 222 | ### Step 9 - Authorization server: `groups` scope and claim | COMMENT |
| LOW | docs/self-hosting/okta-setup.md | 267 | ### Step 10 - Trust and client authentication (verify defaults) | COMMENT |
| LOW | docs/self-hosting/okta-setup.md | 285 | ### Step 11 - Set OAuth in the SSO tab | COMMENT |
| LOW | docs/self-hosting/okta-setup.md | 305 | ### Step 12 - Set Frontend URL in Settings (must match Okta) | COMMENT |
| LOW | docs/self-hosting/okta-setup.md | 323 | ### Step 13 - Confirm SSO is enabled on the server | COMMENT |
| LOW | docs/self-hosting/okta-setup.md | 341 | ### Step 14 - Test SSO login (first user) | COMMENT |
| LOW | docs/self-hosting/okta-setup.md | 364 | ### Step 15 - Verify groups synced | COMMENT |
| LOW | docs/self-hosting/okta-setup.md | 374 | ### Step 16 - Promote the customer admin (required) | COMMENT |
| LOW | docs/self-hosting/okta-setup.md | 386 | ### Step 17 - Optional: lock to SSO only | COMMENT |
| LOW | docs/self-hosting/single-node-deploy.md | 79 | ## Step 1: Provision the VM | COMMENT |
| LOW | docs/self-hosting/single-node-deploy.md | 99 | ## Step 2: Install Docker | COMMENT |
| LOW | docs/self-hosting/single-node-deploy.md | 116 | ## Step 3: Clone and configure | COMMENT |
| LOW | docs/self-hosting/single-node-deploy.md | 152 | ## Step 4: Set up TLS | COMMENT |
| LOW | docs/self-hosting/single-node-deploy.md | 200 | ## Step 5: Start the stack | COMMENT |
| LOW | docs/self-hosting/single-node-deploy.md | 226 | ## Step 6: Survive reboots | COMMENT |
| LOW | docs/self-hosting/single-node-deploy.md | 243 | ## Step 7: Set up automated backups | COMMENT |
| LOW | docs/self-hosting/single-node-deploy.md | 290 | ## Step 8: First login | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | observal_cli/harness_specs/claude_code_hooks_spec.py | 0 | return python command with pythonpath set if needed. | STRING |
| HIGH | observal_cli/harness_specs/codex_hooks_spec.py | 0 | return python command with pythonpath set if needed. | STRING |
| HIGH | observal_cli/harness_specs/kiro_hooks_spec.py | 0 | return python command with pythonpath set if needed. | STRING |
| HIGH | tests/test_review_route_coverage.py | 0 | these routes run on a mocked session; the lock service has its own tests. | STRING |
| HIGH | tests/test_team_publishing.py | 0 | these routes run on a mocked session; the lock service has its own tests. | STRING |
| HIGH | tests/test_agent_review.py | 0 | these routes run on a mocked session; the lock service has its own tests. | STRING |
| HIGH | tests/test_draft_workflow.py | 0 | these routes run on a mocked session; the lock service has its own tests. | STRING |
| HIGH | tests/test_registry_types.py | 0 | compile a statement to a single-line sql string with bind values inlined. | STRING |
| HIGH | tests/test_dashboard_leaderboard.py | 0 | compile a statement to a single-line sql string with bind values inlined. | STRING |
| HIGH | tests/test_sec009_team_visibility.py | 0 | compile a statement to a single-line sql string with bind values inlined. | STRING |
| HIGH | tests/test_sec027_registry_sc.py | 0 | return a magicmock that looks like an agent orm instance. | STRING |
| HIGH | tests/test_agent_review.py | 0 | return a magicmock that looks like an agent orm instance. | STRING |
| HIGH | tests/test_draft_workflow.py | 0 | return a magicmock that looks like an agent orm instance. | STRING |
| HIGH | observal-server/api/routes/skill.py | 0 | refuse teamspace or visibility changes sent to the draft update route. visibility has exactly one authoritative path, pa | STRING |
| HIGH | observal-server/api/routes/hook.py | 0 | refuse teamspace or visibility changes sent to the draft update route. visibility has exactly one authoritative path, pa | STRING |
| HIGH | observal-server/api/routes/sandbox.py | 0 | refuse teamspace or visibility changes sent to the draft update route. visibility has exactly one authoritative path, pa | STRING |
| HIGH | observal-server/api/routes/mcp.py | 0 | refuse teamspace or visibility changes sent to the draft update route. visibility has exactly one authoritative path, pa | STRING |
| HIGH | observal-server/api/routes/prompt.py | 0 | refuse teamspace or visibility changes sent to the draft update route. visibility has exactly one authoritative path, pa | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | observal_cli/skill_folder.py | 194 | Validate a complete skill folder bundle from server response. Args: bundle: Raw bundle dict from server (st | STRING |
| HIGH | observal_cli/skill_folder.py | 448 | Install a validated bundle atomically with rollback support. Args: bundle: Validated bundle to install | STRING |
| HIGH | observal_cli/skill_folder.py | 626 | Capture an immutable snapshot of a skill directory. Reads all regular files, validates paths, and prepares content | STRING |
| HIGH | observal_cli/upgrade_lock.py | 31 | Acquire an upgrade lock for the given scope. Args: scope: Lock scope identifier (e.g., "cli", "server"). | STRING |
| HIGH | observal_cli/server/backup.py | 28 | Create a pre-upgrade backup of PostgreSQL + ClickHouse. Args: compose_dir: Directory containing docker-comp | STRING |
| HIGH | observal_cli/harness/protocol.py | 222 | Scan the user's home directory for this harness's configuration. Args: home: Override home director | STRING |
| HIGH | observal_cli/harness/protocol.py | 253 | Scan a project directory for this harness's configuration. Args: project_dir: The project root to s | STRING |
| HIGH | observal_cli/harness/protocol.py | 292 | Generate hook configuration for telemetry collection. Args: observal_url: The Observal server URL. | STRING |
| HIGH | observal_cli/harness/protocol.py | 308 | Detect whether Observal hooks are already installed. Args: config_dir: harness-specific config dire | STRING |
| HIGH | observal-server/services/skill_validator.py | 218 | Fetch SKILL.md and validate its frontmatter. Args: git_url: Repository URL (GitHub or generic git host). | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | observal_cli/cmd_inbox.py | 219 | CODE | |
| LOW | observal_cli/cmd_inbox.py | 254 | CODE | |
| LOW | observal_cli/cmd_hook.py | 99 | CODE | |
| LOW | observal_cli/cmd_agent.py | 347 | CODE | |
| LOW | observal_cli/cmd_agent.py | 902 | CODE | |
| LOW | observal_cli/cmd_agent.py | 1148 | CODE | |
| LOW | observal_cli/cmd_agent.py | 1454 | CODE | |
| LOW | observal_cli/cmd_agent.py | 1831 | CODE | |
| LOW | observal_cli/lockfile.py | 304 | CODE | |
| LOW | observal_cli/lockfile.py | 411 | CODE | |
| LOW | observal_cli/cmd_ops.py | 400 | CODE | |
| LOW | observal_cli/cmd_ops.py | 1154 | CODE | |
| LOW | observal_cli/cmd_ops.py | 1431 | CODE | |
| LOW | observal_cli/cmd_ops.py | 1505 | CODE | |
| LOW | observal_cli/cmd_component.py | 65 | CODE | |
| LOW | observal_cli/cmd_pull.py | 2096 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 1301 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 1389 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 1505 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 1589 | CODE | |
| LOW | observal_cli/cmd_prompt.py | 56 | CODE | |
| LOW | observal_cli/cmd_prompt.py | 412 | CODE | |
| LOW | observal_cli/cmd_auth.py | 285 | CODE | |
| LOW | observal_cli/cmd_skill.py | 239 | CODE | |
| LOW | observal_cli/cmd_skill.py | 828 | CODE | |
| LOW | observal_cli/cmd_skill.py | 1596 | CODE | |
| LOW | observal_cli/cmd_skill.py | 1663 | CODE | |
| LOW | observal_cli/cmd_skill.py | 1768 | CODE | |
| LOW | observal_cli/cmd_skill.py | 1854 | CODE | |
| LOW | observal_cli/cmd_skill.py | 2218 | CODE | |
| LOW | observal_cli/cmd_sandbox.py | 77 | CODE | |
| LOW | observal_cli/cmd_sandbox.py | 407 | CODE | |
| LOW | observal_cli/capability_lock.py | 120 | CODE | |
| LOW | observal_cli/discovery/normalize.py | 363 | CODE | |
| LOW | observal_cli/sessions/base.py | 474 | CODE | |
| LOW | tests/test_agent_crud_routes.py | 84 | CODE | |
| LOW | tests/test_skill_routes.py | 74 | CODE | |
| LOW | tests/test_mcp_routes.py | 74 | CODE | |
| LOW | tests/discovery_support.py | 86 | CODE | |
| LOW | observal-server/api/routes/skill.py | 250 | CODE | |
| LOW | observal-server/api/routes/sessions.py | 84 | CODE | |
| LOW | observal-server/api/routes/hook.py | 124 | CODE | |
| LOW | observal-server/api/routes/review.py | 1363 | CODE | |
| LOW | observal-server/api/routes/dashboard.py | 542 | CODE | |
| LOW | observal-server/api/routes/sandbox.py | 116 | CODE | |
| LOW | observal-server/api/routes/mcp.py | 225 | CODE | |
| LOW | observal-server/api/routes/inbox.py | 130 | CODE | |
| LOW | observal-server/api/routes/prompt.py | 116 | CODE | |
| LOW | observal-server/api/routes/audit_log.py | 61 | CODE | |
| LOW | observal-server/api/routes/audit_log.py | 144 | CODE | |
| LOW | observal-server/api/routes/agent/helpers.py | 98 | CODE | |
| LOW | observal-server/api/routes/agent/crud.py | 251 | CODE | |
| LOW | observal-server/services/model_display.py | 55 | CODE | |
| LOW | observal-server/services/insights/generator.py | 47 | CODE | |
| LOW | observal-server/services/harness/__init__.py | 170 | CODE | |
| LOW | observal-server/services/audit/event_handlers.py | 44 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/test_device_auth.py | 544 | # Step 1: CLI requests device authorization | COMMENT |
| LOW⚡ | tests/test_device_auth.py | 551 | # Step 2: CLI polls -- should get authorization_pending | COMMENT |
| LOW⚡ | tests/test_device_auth.py | 562 | # Step 3: User confirms in browser | COMMENT |
| LOW⚡ | tests/test_device_auth.py | 570 | # Step 4: CLI polls again -- should get tokens | COMMENT |
| LOW | tests/test_device_auth.py | 586 | # Step 5: Polling again should return expired_token (keys cleaned up) | COMMENT |
| LOW⚡ | observal-server/api/routes/auth.py | 627 | # Step 1: exchange the authorization code for tokens. | COMMENT |
| LOW⚡ | observal-server/api/routes/auth.py | 738 | # Step 5: user lookup / JIT. | COMMENT |
| LOW⚡ | observal-server/api/routes/auth.py | 812 | # Step 6: persist SSO groups (best-effort, never blocks login). | COMMENT |
| LOW⚡ | observal-server/api/routes/auth.py | 820 | # Step 7: issue tokens + commit. | COMMENT |
| LOW⚡ | observal-server/api/routes/auth.py | 833 | # Step 8: hand off via short-lived code in Redis. | COMMENT |
| LOW | observal-server/api/routes/auth.py | 655 | # Step 2: extract userinfo (merged ID-token + /userinfo claims by authlib). | COMMENT |
| LOW | observal-server/api/routes/auth.py | 671 | # Step 3: required email claim. | COMMENT |
| LOW | observal-server/api/routes/auth.py | 689 | # Step 4: name + groups (non-fatal absences are 'skip'). | COMMENT |
| LOW⚡ | observal-server/api/routes/sso_saml.py | 516 | # Step 1: decrypt SP signing key. | COMMENT |
| LOW⚡ | observal-server/api/routes/sso_saml.py | 533 | # Step 2: process the Response (signature, audience, conditions). | COMMENT |
| LOW⚡ | observal-server/api/routes/sso_saml.py | 658 | # Step 4: extract NameID + attributes. | COMMENT |
| LOW⚡ | observal-server/api/routes/sso_saml.py | 720 | # Step 5: user lookup / JIT (real-login mode). | COMMENT |
| LOW⚡ | observal-server/api/routes/sso_saml.py | 814 | # Step 6: issue tokens + commit. | COMMENT |
| LOW | observal-server/api/routes/sso_saml.py | 595 | # Step 3: replay protection. | COMMENT |
| LOW | observal-server/services/user_profile.py | 204 | # Step 1: user -> sessions, via the table that indexes user_id. | COMMENT |
| LOW | observal-server/services/user_profile.py | 232 | # Step 2: sessions -> tool usage, keyed on the indexed session_id column. | COMMENT |
| LOW | observal-server/services/user_profile.py | 261 | # Step 3: file extensions -> languages, from tool-call previews. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | install-server.sh | 1 | #!/usr/bin/env bash | COMMENT |
| LOW | install.sh | 1 | #!/usr/bin/env bash | COMMENT |
| LOW | infra/terraform/deploy.sh | 1 | #!/usr/bin/env bash | COMMENT |
| LOW | infra/terraform/aws/deploy.sh | 1 | #!/usr/bin/env bash | COMMENT |
| LOW | infra/terraform/aws/clickhouse.tf | 1 | # SPDX-FileCopyrightText: 2026 Apoorv Garg <apoorvgarg.21@gmail.com> | COMMENT |
| LOW | infra/terraform/aws/webhook-ingress.tf | 1 | # SPDX-FileCopyrightText: 2026 Lokesh Selvam <lokeshselvam7025@gmail.com> | COMMENT |
| LOW | infra/terraform/aws-standard/webhook-ingress.tf | 1 | # SPDX-FileCopyrightText: 2026 Lokesh Selvam <lokeshselvam7025@gmail.com> | COMMENT |
| LOW | docker/entrypoint.sh | 1 | #!/bin/bash | COMMENT |
| LOW | observal_cli/cmd_doctor.py | 1 | # SPDX-FileCopyrightText: 2026 Apoorv Garg <apoorvgarg.21@gmail.com> | COMMENT |
| LOW | observal_cli/__init__.py | 1 | # SPDX-FileCopyrightText: 2026 Subramania Raja <dhanpraja231@gmail.com> | COMMENT |
| LOW | observal_cli/cmd_auth.py | 1 | # SPDX-FileCopyrightText: 2026 Hemalatha Madeswaran <hemalathamadeswaran@gmail.com> | COMMENT |
| LOW | observal_cli/cmd_scan.py | 1 | # SPDX-FileCopyrightText: 2026 Aryan Iyappan <aryaniyappan2006@gmail.com> | COMMENT |
| LOW | observal_cli/tests/__init__.py | 1 | # SPDX-FileCopyrightText: 2026 Subramania Raja <dhanpraja231@gmail.com> | COMMENT |
| LOW | observal_cli/shared/__init__.py | 1 | # SPDX-FileCopyrightText: 2026 Hari Srinivasan <harisrini21@gmail.com> | COMMENT |
| LOW | web/src/hooks/use-insights-api.ts | 1 | // SPDX-FileCopyrightText: 2026 Aryan Iyappan <aryaniyappan2006@gmail.com> | COMMENT |
| LOW | web/src/lib/api.ts | 1 | COMMENT | |
| LOW | web/src/pages/admin/sso.tsx | 61 | COMMENT | |
| LOW | tests/__init__.py | 1 | # SPDX-FileCopyrightText: 2026 Hari Srinivasan <harisrini21@gmail.com> | COMMENT |
| LOW | observal-server/main.py | 1 | # SPDX-FileCopyrightText: 2026 Aryan Iyappan <aryaniyappan2006@gmail.com> | COMMENT |
| LOW | observal-server/tests/__init__.py | 1 | # SPDX-FileCopyrightText: 2026 Subramania Raja <dhanpraja231@gmail.com> | COMMENT |
| LOW | observal-server/schemas/__init__.py | 1 | # SPDX-FileCopyrightText: 2026 Subramania Raja <dhanpraja231@gmail.com> | COMMENT |
| LOW | observal-server/api/__init__.py | 1 | # SPDX-FileCopyrightText: 2026 Subramania Raja <dhanpraja231@gmail.com> | COMMENT |
| LOW | observal-server/api/middleware/__init__.py | 1 | # SPDX-FileCopyrightText: 2026 Subramania Raja <dhanpraja231@gmail.com> | COMMENT |
| LOW | observal-server/api/routes/bulk.py | 161 | # One SAVEPOINT per item, so "this item failed" and "this item was | COMMENT |
| LOW | observal-server/api/routes/teams.py | 821 | team_id: uuid.UUID, | COMMENT |
| LOW | observal-server/api/routes/__init__.py | 1 | # SPDX-FileCopyrightText: 2026 Subramania Raja <dhanpraja231@gmail.com> | COMMENT |
| LOW | observal-server/api/routes/co_authors.py | 201 | async def transfer_ownership( | COMMENT |
| LOW | observal-server/alembic/versions/018_team_publishing.py | 61 | ["team_id"], | COMMENT |
| LOW | observal-server/services/__init__.py | 1 | # SPDX-FileCopyrightText: 2026 Subramania Raja <dhanpraja231@gmail.com> | COMMENT |
| LOW | observal-server/services/shared/__init__.py | 1 | # SPDX-FileCopyrightText: 2026 Hari Srinivasan <harisrini21@gmail.com> | COMMENT |
| LOW | observal-server/services/harness/helpers.py | 1 | # SPDX-FileCopyrightText: 2026 Apoorv Garg <apoorvgarg.21@gmail.com> | COMMENT |
| LOW | scripts/test_xff_spoofing.sh | 1 | #!/usr/bin/env bash | COMMENT |
| LOW | …es/observal-shared/observal_shared/harness_registry.py | 1 | # SPDX-FileCopyrightText: 2026 Aryan Iyappan <aryaniyappan2006@gmail.com> | COMMENT |
| LOW | …es/observal-shared/observal_shared/harness_registry.py | 21 | # file written to a config file the harness reads natively | COMMENT |
| LOW | .github/secret_scanning.yml | 1 | # SPDX-FileCopyrightText: 2026 Hari Srinivasan <harisrini21@gmail.com> | COMMENT |
| LOW | .github/workflows/badge-ghcr-pulls.yml | 1 | # SPDX-FileCopyrightText: 2026 Hari Srinivasan <harisrini21@gmail.com> | COMMENT |
| LOW | .github/workflows/terraform.yml | 1 | # SPDX-FileCopyrightText: 2026 Apoorv Garg <apoorvgarg.21@gmail.com> | COMMENT |
| LOW | .github/workflows/ci.yml | 1 | # SPDX-FileCopyrightText: 2026 Hari Srinivasan <harisrini21@gmail.com> | COMMENT |
| LOW | fuzz/oss-fuzz/project.yaml | 1 | # SPDX-FileCopyrightText: 2026 RAWx18 <rawx18.dev@gmail.com> | COMMENT |
| LOW | fuzz/oss-fuzz/build.sh | 1 | #!/bin/bash -eu | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | infra/terraform/aws-ec2/deploy.sh | 73 | # Print output | COMMENT |
| LOW | infra/terraform/aws/variables.tf | 424 | # Set these to deploy into an existing VPC instead of creating a new one. | COMMENT |
| LOW | infra/terraform/aws/deploy.sh | 285 | # Check if ECS cluster already exists | COMMENT |
| LOW | observal_cli/skill_folder.py | 402 | # Check if target already exists | COMMENT |
| LOW | observal_cli/skill_folder.py | 407 | # Check if it's a managed skill folder | COMMENT |
| LOW | observal_cli/skill_folder.py | 766 | # Check if binary | COMMENT |
| LOW | observal_cli/client.py | 69 | # Check if current subcommand is exempt (handle flags before subcommand) | COMMENT |
| LOW | observal_cli/cmd_pull.py | 1943 | # Check if we have a complete bundle for this skill | COMMENT |
| LOW | observal_cli/cmd_doctor.py | 269 | # Check if session push hooks are installed | COMMENT |
| LOW | observal_cli/cmd_doctor.py | 442 | # Check if VS Code / Copilot is even present | COMMENT |
| LOW | observal_cli/cmd_doctor.py | 1397 | # Check if already patched | COMMENT |
| LOW | observal_cli/cmd_doctor.py | 1536 | # Check if already patched | COMMENT |
| LOW | observal_cli/cmd_doctor.py | 1690 | # Check if running under /mnt/c/Users/<name>/... | COMMENT |
| LOW | observal_cli/cmd_doctor.py | 1737 | # Check if already patched | COMMENT |
| LOW | observal_cli/upgrade_lock.py | 51 | # Check if lock is stale (>30 minutes old) | COMMENT |
| LOW | observal_cli/settings_reconciler.py | 79 | # Check if Observal groups match desired (by JSON equality) | COMMENT |
| LOW⚡ | observal_cli/harness_specs/antigravity_hooks_spec.py | 71 | # Check if observal_cli is importable without PYTHONPATH | COMMENT |
| LOW | tests/test_support_pbt.py | 327 | # Check if the intermediate result would trigger the entropy rule on any token | COMMENT |
| LOW | observal-server/api/routes/layer_snapshot.py | 108 | # Check if this hash already exists for this project | COMMENT |
| LOW | observal-server/api/routes/co_authors.py | 362 | # Check if already a co-author | COMMENT |
| LOW | observal-server/api/routes/insights.py | 208 | # Check if AWS credentials are set and valid (for Bedrock models) | COMMENT |
| LOW | observal-server/api/routes/insights.py | 306 | # Check if there are any sessions for this agent/version in the period. | COMMENT |
| LOW | observal-server/services/insights/batch.py | 375 | # Check if there's already a recent report (completed or in-progress) | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | infra/terraform/azure/.terraform.lock.hcl | 4 | # This file is maintained automatically by "terraform init". | COMMENT |
| MEDIUM | …a/terraform/azure/examples/minimal/.terraform.lock.hcl | 4 | # This file is maintained automatically by "terraform init". | COMMENT |
| MEDIUM⚡ | observal_cli/tests/test_cmd_migrate.py | 156 | # Create a dummy tar.gz file | COMMENT |
| MEDIUM | observal_cli/server/orchestrator.py | 211 | # Create the observal database if it doesn't exist | COMMENT |
| MEDIUM⚡ | tests/test_antigravity_adapter.py | 167 | # Create an empty hooks.json so the adapter uses tmp_path instead of falling back to real config | COMMENT |
| MEDIUM | tests/test_cmd_support.py | 272 | # Create a manifest that will cause serialization to fail | COMMENT |
| MEDIUM⚡ | tests/test_schema_redesign.py | 510 | # Create a mock MCP listing with mcp_validated=False | COMMENT |
| MEDIUM | tests/test_migration_api.py | 200 | # Create a fake tar.gz upload file | COMMENT |
| MEDIUM⚡ | tests/test_integration.py | 396 | # Create a uniquely named MCP | COMMENT |
| MEDIUM | observal-server/services/insights/batch.py | 433 | # Create a new report record | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tools/release.py | 406 | def set_version(path: Path, version: str) -> None: | CODE |
| LOW | observal_cli/config.py | 20 | logger = logging.getLogger(__name__) | CODE |
| LOW | observal_cli/client.py | 22 | logger = logging.getLogger(__name__) | CODE |
| LOW | observal_cli/cmd_server.py | 642 | def _update_env_version(compose_dir: Path, version: str) -> None: | CODE |
| LOW | observal_cli/layer.py | 574 | def set_last_uploaded_hash(layer_hash: str) -> None: | CODE |
| LOW | observal_cli/harness/__init__.py | 29 | __all__ = [ | CODE |
| LOW | tests/test_cmd_outdated.py | 64 | def _set_entries(monkeypatch: pytest.MonkeyPatch, entries: list[dict]) -> None: | CODE |
| LOW | observal-server/models/user.py | 58 | def set_password(self, password: str) -> None: | CODE |
| LOW | observal-server/models/__init__.py | 51 | __all__ = [ | CODE |
| LOW | observal-server/api/routes/ard.py | 468 | __all__ = ["router"] | CODE |
| LOW | observal-server/api/routes/ard_imports.py | 284 | __all__ = ["router"] | CODE |
| LOW | observal-server/services/download_tracker.py | 80 | async def _update_agent_counts(agent_id: uuid.UUID, db: AsyncSession) -> None: | CODE |
| LOW | observal-server/services/request_context.py | 30 | def set_request_context(request) -> None: | CODE |
| LOW | observal-server/services/insights/registry_match.py | 375 | __all__ = [ | CODE |
| LOW | observal-server/services/clickhouse/__init__.py | 47 | __all__ = [ | CODE |
| LOW | observal-server/services/inbox/__init__.py | 24 | __all__ = [ | CODE |
| LOW | observal-server/services/discovery/a2a.py | 493 | __all__ = [ | CODE |
| LOW | observal-server/services/discovery/hooks.py | 139 | def set_scheduler(scheduler: Scheduler | None) -> None: | CODE |
| LOW | observal-server/services/discovery/hooks.py | 176 | __all__ = [ | CODE |
| LOW | observal-server/services/discovery/projection.py | 408 | __all__ = [ | CODE |
| LOW | observal-server/services/audit/__init__.py | 11 | __all__ = ["AUDIT_ENABLED", "audit_detail", "setup_audit", "shutdown_audit"] | CODE |
| LOW | …/observal-shared/observal_shared/migration/__init__.py | 44 | __all__ = [ | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | observal_cli/cmd_agent.py | 318 | # its file between fork's preflight and this local scaffold write. | COMMENT |
| MEDIUM | observal_cli/cmd_agent.py | 1893 | # Preserve legacy YAML that omits these optional fields; a fork scaffold | COMMENT |
| MEDIUM | observal_cli/README.md | 50 | observal agent init # scaffold observal-agent.yaml | CODE |
| MEDIUM | docs/use-cases/share-agent-configs.md | 36 | observal agent init # scaffold observal-agent.yaml | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| CRITICAL | tests/test_migration_operation_enum_postgres.py | 60 | processor = MigrationJob.__table__.c.operation_type.type.bind_processor(engine.dialect) | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | infra/terraform/deploy.sh | 9 | # Usage: | COMMENT |
| LOW | infra/terraform/aws/deploy.sh | 11 | # Usage: | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | observal_cli/delegation/runner.py | 26 | def run_task(task_id: str) -> dict | None: | CODE |
| LOW | tests/test_mcp_validator.py | 405 | def helper(): | CODE |