Observal is a local registry and analytics platform for your AI components. Setup Observal, define the scope and share your Skills, MCPs and Agents.
This report presents the forensic synthetic code analysis of Observal/Observal, a Python project with 2,268 GitHub stars. SynthScan v2.0 examined 275,079 lines of code across 1211 source files, recording 6320 pattern matches distributed across 21 syntactic categories. The overall adjusted score of 39.3 places this repository in the Strong AI signal band.
The scanner applied 160+ deterministic lexical heuristics, multi-line block detectors, abstract syntax tree depth profilers, and a cross-file Jaccard similarity matrix to construct a statistically normalised synthetic code estimate. All matches are individually weighted by severity coefficient and contextual multiplier before summation, and the resulting headline score is temporally discounted to account for the repository's development history relative to the commercial emergence of large language model coding tooling (November 2022 onward).
Longitudinal tracking requires multiple scan runs. Once this repository is re-scanned after new commits land, this chart will visualise how the synthetic code signal evolves over time — enabling you to detect whether AI authorship is growing, stabilising, or being actively corrected by human engineers.
Classifies detected patterns by their diagnostic confidence and structural impact. CRITICAL patterns (coefficient 10) represent definitive synthetic signatures — hallucinated imports, explicit LLM attribution metadata — virtually never produced by human authors. HIGH (5) indicates strong structural tells such as cross-file repetition or cross-linguistic idioms. MEDIUM (2) covers recognisable conversational padding and AI-specific vocabulary. LOW (1) captures subtle indicators like tautological comments and generic boilerplate that require density to carry independent signal.
This horizontal bar chart decomposes the repository's raw synthetic code score by top-level directory, allowing you to pinpoint precisely which modules or components carry the highest AI authorship density. Directories with disproportionately high scores relative to their size warrant targeted manual review: concentrated AI signatures often trace back to mass-generated configuration layers, auto-ported test suites, LLM-scaffolded boilerplate classes, or entire subsystems authored under heavy copilot assistance. Use this view to prioritise your human code-review effort.
The scanner identified 6320 distinct pattern matches across 21 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a statistically significant AI authorship indicator. 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 diagnostic confidence level (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — comment-context matches receive a ×1.5 weight because LLMs systematically over-annotate. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier as dense clusters constitute far stronger evidence of synthetic authorship than isolated hits.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | install-server.sh | 24 | # ── Helpers ────────────────────────────────────────────────── | COMMENT |
| MEDIUM | install-server.sh | 34 | # ── Parse arguments ────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | install-server.sh | 104 | # ── Pre-flight ─────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | install-server.sh | 110 | # ── Resolve version ────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | install-server.sh | 120 | # ── Download ───────────────────────────────────────────────── | COMMENT |
| MEDIUM | install-server.sh | 138 | # ── Unpack ─────────────────────────────────────────────────── | COMMENT |
| MEDIUM | install-server.sh | 161 | # ── Run setup ─────────────────────────────────────────────── | COMMENT |
| MEDIUM | .pre-commit-config.yaml | 9 | # ── Python ───────────────────────────────────────────── | COMMENT |
| MEDIUM | .pre-commit-config.yaml | 17 | # ── YAML / TOML / JSON ──────────────────────────────── | COMMENT |
| MEDIUM | .pre-commit-config.yaml | 37 | # ── Secrets / .env guard ─────────────────────────────── | COMMENT |
| MEDIUM | .pre-commit-config.yaml | 46 | # ── Alembic migrations ───────────────────────────────── | COMMENT |
| MEDIUM | .pre-commit-config.yaml | 57 | # ── SPDX copyright update ────────────────────────────────────── | COMMENT |
| MEDIUM | .pre-commit-config.yaml | 68 | # ── 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 | 119 | # ── Pytest ─────────────────────────────────────────────── | COMMENT |
| MEDIUM | pyproject.toml | 125 | # ── 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 | 185 | # ── Cloud SQL ───────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/gcp/variables.tf | 209 | # ── Memorystore Redis ───────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/gcp/variables.tf | 227 | # ── Application config ──────────────────────────────────────────────────── | COMMENT |
| MEDIUM | infra/terraform/gcp/variables.tf | 266 | # ── 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 |
| 1596 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | observal_cli/config.py | 144 | def migrate_shimmed_mcp_configs(home: Path | None = None, cwd: Path | None = None) -> list[Path]: | CODE |
| LOW | observal_cli/cmd_uninstall.py | 89 | def _create_windows_cleanup_script( | CODE |
| LOW | observal_cli/client.py | 246 | def resolve_registry_reference(item_type: str, reference: str) -> str: | CODE |
| LOW | observal_cli/client.py | 415 | def get_registered_agents_only() -> bool: | CODE |
| LOW | observal_cli/client.py | 438 | def get_registered_agent_names() -> set[str]: | CODE |
| LOW | observal_cli/cmd_pull.py | 37 | def _warn_component_conflicts(harness: str, agent_name: str, components: list[dict]) -> None: | CODE |
| LOW | observal_cli/cmd_pull.py | 394 | def _rewrite_copilot_cli_hooks(content: dict, agent_id: str | None = None) -> dict: | CODE |
| LOW | observal_cli/cmd_doctor.py | 192 | def _check_observal_skill_missing() -> list[str]: | CODE |
| LOW | observal_cli/cmd_mcp.py | 65 | def _configure_env_vars_interactive(detected: list[dict]) -> list[dict]: | CODE |
| LOW | observal_cli/cmd_mcp.py | 256 | def _parse_server_json_manifest(cfg: dict) -> dict | None: | CODE |
| LOW | observal_cli/lockfile_reconcile.py | 81 | def plan_lockfile_reconciliation() -> LockfileReconciliation: | CODE |
| LOW⚡ | observal_cli/cmd_auth.py | 970 | def _generate_initial_layer_snapshot(): | CODE |
| LOW | observal_cli/cmd_auth.py | 80 | def _ensure_cli_matches_server(server_url: str) -> None: | CODE |
| LOW | observal_cli/cmd_insights.py | 275 | def _render_what_they_work_on(title: str, data: dict): | CODE |
| LOW | observal_cli/cmd_insights.py | 289 | def _render_interaction_style(title: str, data: dict): | CODE |
| LOW | observal_cli/cmd_insights.py | 396 | def _render_registry_match_note(summary: dict | None): | CODE |
| LOW | observal_cli/cmd_insights.py | 530 | def _render_version_comparison(title: str, data: dict): | CODE |
| LOW | observal_cli/cmd_server.py | 381 | 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 | 629 | 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 | 23 | def add_transfer_owner_command(app: typer.Typer, entity_type: str) -> None: | CODE |
| LOW⚡ | observal_cli/cmd_migrate.py | 121 | def _warn_clickhouse_cleartext(url: str) -> None: | CODE |
| LOW | observal_cli/main.py | 107 | def _migrate_legacy_mcp_configs() -> None: | CODE |
| LOW | observal_cli/tests/test_registry_namespace_cli.py | 9 | def test_listings_render_the_bare_name_over_an_at_handle(): | CODE |
| LOW | observal_cli/tests/test_registry_namespace_cli.py | 27 | def test_namespace_falls_back_to_the_qualified_name_and_degrades_without_one(): | CODE |
| LOW | observal_cli/tests/test_registry_namespace_cli.py | 35 | def test_dotted_namespaces_are_valid_but_flattened_in_local_install_names(tmp_path, monkeypatch): | CODE |
| LOW | observal_cli/tests/test_registry_namespace_cli.py | 58 | def test_qualified_reference_resolves_once(monkeypatch): | CODE |
| LOW | observal_cli/tests/test_registry_namespace_cli.py | 77 | def test_uuid_and_bare_references_do_not_call_resolver(monkeypatch): | CODE |
| LOW | observal_cli/tests/test_registry_namespace_cli.py | 84 | def test_local_name_changes_only_for_actual_same_slug_collision(tmp_path, monkeypatch): | CODE |
| LOW | observal_cli/tests/test_registry_namespace_cli.py | 121 | def test_nested_registries_are_isolated(tmp_path, monkeypatch): | CODE |
| LOW | observal_cli/tests/test_registry_namespace_cli.py | 154 | def test_reconciliation_updates_metadata_but_keeps_installed_version(tmp_path, monkeypatch): | CODE |
| LOW | observal_cli/tests/test_cmd_auth.py | 117 | def test_login_with_credentials_saves_config(self) -> None: | CODE |
| LOW | observal_cli/tests/test_cmd_auth.py | 150 | def test_login_strips_trailing_slash_from_server_url(self) -> None: | CODE |
| LOW | observal_cli/tests/test_cmd_auth.py | 175 | def test_login_with_invalid_credentials_exits_nonzero(self) -> None: | CODE |
| LOW | observal_cli/tests/test_cmd_auth.py | 214 | def test_login_when_server_unreachable_exits_nonzero(self) -> None: | CODE |
| LOW | observal_cli/tests/test_cmd_auth.py | 251 | def test_whoami_outputs_email_and_role(self) -> None: | CODE |
| LOW | observal_cli/tests/test_cmd_auth.py | 284 | def test_whoami_unset_username_is_handled(self) -> None: | CODE |
| LOW | observal_cli/tests/test_cmd_auth.py | 307 | def test_status_reports_ok_when_healthy(self) -> None: | CODE |
| LOW | observal_cli/tests/test_cmd_auth.py | 321 | def test_status_reports_unreachable_when_health_fails(self) -> None: | CODE |
| LOW | observal_cli/tests/test_cmd_auth.py | 333 | def test_status_reports_auth_not_set_when_no_token(self) -> None: | CODE |
| LOW⚡ | observal_cli/tests/test_cmd_auth.py | 352 | def test_opencode_detects_off_path_installer_binary(self, tmp_path, monkeypatch) -> None: | CODE |
| LOW | observal_cli/tests/test_cmd_auth.py | 371 | def test_doctor_patch_uses_current_flags(self) -> None: | CODE |
| LOW⚡ | observal_cli/tests/test_cmd_team.py | 33 | def test_team_list_calls_mine_endpoint(): | CODE |
| LOW⚡ | observal_cli/tests/test_cmd_team.py | 41 | def test_team_list_all_uses_all_endpoint(): | CODE |
| LOW⚡ | observal_cli/tests/test_cmd_team.py | 48 | def test_team_create_posts_handle_and_name(): | CODE |
| LOW⚡ | observal_cli/tests/test_cmd_team.py | 57 | def test_team_show_resolves_handle_to_id(): | CODE |
| LOW | observal_cli/tests/test_cmd_team.py | 74 | def test_team_show_accepts_uuid_directly(): | CODE |
| LOW | observal_cli/tests/test_cmd_team.py | 85 | def test_team_members_add_sends_email_or_username(): | CODE |
| LOW | observal_cli/tests/test_cmd_team.py | 96 | def test_team_members_add_username_strips_at_prefix(): | CODE |
| LOW | observal_cli/tests/test_cmd_team.py | 104 | def test_team_members_remove_resolves_member_by_username(): | CODE |
| LOW⚡ | observal_cli/tests/test_cmd_team.py | 116 | def test_team_members_remove_unknown_user_errors(): | CODE |
| LOW⚡ | observal_cli/tests/test_cmd_team.py | 124 | def test_team_delete_requires_confirmation_without_yes(): | CODE |
| LOW⚡ | observal_cli/tests/test_cmd_team.py | 132 | def test_team_leave_posts_leave_endpoint(): | CODE |
| LOW⚡ | observal_cli/tests/test_cmd_team.py | 140 | def test_team_invite_create_list_and_revoke(): | CODE |
| LOW | observal_cli/tests/test_cmd_team.py | 177 | def test_team_show_unknown_handle_errors(bad: str): | CODE |
| LOW | observal_cli/tests/test_cmd_team.py | 183 | def test_team_commands_do_not_probe_the_server_version(): | CODE |
| LOW | observal_cli/tests/test_cmd_agent_init_flags.py | 16 | def test_agent_init_flags_write_yaml(tmp_path): | CODE |
| 3046 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tools/release.py | 6 | CODE | |
| LOW | observal_cli/upgrade_executor.py | 9 | CODE | |
| LOW | observal_cli/cmd_recommend.py | 11 | CODE | |
| LOW | observal_cli/cmd_inbox.py | 14 | CODE | |
| LOW | observal_cli/cmd_team.py | 6 | 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/lockfile.py | 15 | 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_uninstall.py | 6 | CODE | |
| LOW | observal_cli/telemetry_buffer.py | 10 | CODE | |
| LOW | observal_cli/render.py | 8 | CODE | |
| LOW | observal_cli/cmd_ops.py | 10 | CODE | |
| LOW | observal_cli/cmd_component.py | 11 | 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/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 | 17 | 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 | 6 | 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/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/cmd_scan.py | 15 | CODE | |
| LOW | observal_cli/cmd_transfer.py | 6 | CODE | |
| LOW | observal_cli/cmd_migrate.py | 16 | CODE | |
| LOW | observal_cli/cmd_migrate.py | 53 | CODE | |
| LOW | observal_cli/cmd_migrate.py | 100 | CODE | |
| LOW | observal_cli/cmd_logs.py | 15 | CODE | |
| LOW | observal_cli/settings_reconciler.py | 15 | CODE | |
| LOW | observal_cli/harness_specs/antigravity_hooks_spec.py | 42 | CODE | |
| LOW | observal_cli/harness_specs/goose_hooks_spec.py | 26 | CODE | |
| LOW | observal_cli/harness_specs/claude_code_hooks_spec.py | 20 | CODE | |
| LOW | observal_cli/harness_specs/copilot_cli_hooks_spec.py | 14 | CODE | |
| LOW | observal_cli/harness_specs/codex_hooks_spec.py | 13 | CODE | |
| LOW | observal_cli/harness_specs/kiro_hooks_spec.py | 12 | CODE | |
| LOW | observal_cli/harness_specs/copilot_hooks_spec.py | 22 | CODE | |
| LOW | observal_cli/harness_specs/opencode_hooks_spec.py | 15 | CODE | |
| LOW | observal_cli/tests/test_cmd_auth.py | 14 | CODE | |
| LOW | observal_cli/tests/test_cmd_team.py | 6 | CODE | |
| LOW | observal_cli/tests/test_cmd_agent_init_flags.py | 4 | CODE | |
| 475 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | observal_cli/server/updater.py | 220 | " If the server is running, restart it: [cyan]observal server stop && observal server start[/cyan]" | CODE |
| HIGH | tests/test_observal_skill.py | 20 | 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 | 63 | assert.equal(state.pending, null); | STRING |
| HIGH | tests/test_opencode_session_delivery.py | 75 | assert.equal(repair.pending, null); | STRING |
| HIGH⚡ | tests/test_opencode_session_delivery.py | 117 | if (!options.method || options.method === "GET") { | STRING |
| HIGH⚡ | tests/test_opencode_session_delivery.py | 122 | ingestPayloads.push(payload); | STRING |
| HIGH⚡ | tests/test_opencode_session_delivery.py | 124 | if (repairFinalOnce && payload.final) { | STRING |
| HIGH | tests/test_opencode_session_delivery.py | 147 | assert.equal(delivery.pending, null); | STRING |
| HIGH | tests/test_opencode_session_delivery.py | 157 | assert.equal(recovered.pending, null); | STRING |
| HIGH | tests/test_opencode_session_delivery.py | 171 | assert.equal(large.pending, null); | STRING |
| 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_migration_frontend.py | 9 | cd web && pnpm test | STRING |
| HIGH | observal-server/tests/test_exec_dashboard.py | 8 | Run with: cd observal-server && pytest tests/test_exec_dashboard.py -v | STRING |
| 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/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 |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 334 | const usage = info.tokens || info.usage || {}; | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 336 | input_tokens: usage.input || usage.inputTokens || 0, | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 337 | output_tokens: usage.output || usage.outputTokens || 0, | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 338 | cache_read_input_tokens: usage.cacheRead || usage.cacheReadTokens || 0, | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 339 | cache_creation_input_tokens: usage.cacheWrite || usage.cacheWriteTokens || 0, | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 342 | lines.push(JSON.stringify(line)); | CODE |
| HIGH⚡ | …erval-shared/observal_shared/opencode_plugin_source.py | 348 | return event?.properties?.sessionID || event?.properties?.info?.id || ""; | CODE |
| 22 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 | 687 | except Exception: | STRING |
| MEDIUM | observal_cli/cmd_support.py | 175 | def _get_cli_version() -> str: | CODE |
| LOW⚡ | observal_cli/cmd_support.py | 180 | except Exception: | CODE |
| LOW | observal_cli/cmd_support.py | 103 | except Exception as exc: | CODE |
| LOW | observal_cli/cmd_support.py | 157 | except Exception: | CODE |
| LOW | observal_cli/cmd_support.py | 311 | except Exception as exc: | CODE |
| LOW | observal_cli/cmd_hook.py | 531 | except Exception: | CODE |
| LOW⚡ | observal_cli/cmd_hook.py | 587 | except Exception as exc: | CODE |
| LOW⚡ | observal_cli/cmd_hook.py | 595 | except Exception as exc: | CODE |
| LOW⚡ | observal_cli/cmd_hook.py | 598 | except Exception: | CODE |
| LOW | observal_cli/lockfile.py | 503 | 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/cmd_uninstall.py | 341 | except Exception as exc: | CODE |
| LOW | observal_cli/render.py | 73 | except Exception: | CODE |
| LOW | observal_cli/cmd_ops.py | 271 | except Exception: | CODE |
| LOW | observal_cli/cmd_ops.py | 537 | except Exception: | CODE |
| LOW | observal_cli/cmd_ops.py | 1427 | except Exception: | CODE |
| LOW | observal_cli/client.py | 39 | except Exception: | CODE |
| LOW | observal_cli/client.py | 186 | except Exception: | CODE |
| LOW | observal_cli/client.py | 295 | except Exception: | CODE |
| LOW | observal_cli/client.py | 434 | except Exception: | CODE |
| LOW | observal_cli/client.py | 456 | except Exception: | CODE |
| LOW | observal_cli/client.py | 479 | except Exception: | CODE |
| LOW | observal_cli/client.py | 495 | except Exception: | CODE |
| LOW | observal_cli/client.py | 511 | except Exception: | CODE |
| LOW | observal_cli/client.py | 521 | except Exception: | CODE |
| LOW⚡ | observal_cli/cmd_pull.py | 552 | except Exception: | CODE |
| LOW⚡ | observal_cli/cmd_pull.py | 565 | except Exception: | CODE |
| LOW | observal_cli/cmd_pull.py | 80 | except Exception: | CODE |
| LOW | observal_cli/cmd_pull.py | 930 | except Exception: | CODE |
| LOW | observal_cli/cmd_pull.py | 938 | except Exception: | CODE |
| LOW⚡ | observal_cli/cmd_doctor.py | 54 | except Exception: | CODE |
| LOW | observal_cli/cmd_doctor.py | 91 | except Exception as exc: | CODE |
| LOW | observal_cli/cmd_doctor.py | 247 | except Exception as e: | CODE |
| LOW | observal_cli/cmd_doctor.py | 318 | except Exception: | 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_mcp.py | 1178 | except Exception: | CODE |
| LOW⚡ | observal_cli/cmd_prompt.py | 369 | except Exception as exc: | CODE |
| LOW⚡ | observal_cli/cmd_prompt.py | 377 | except Exception as exc: | CODE |
| LOW⚡ | observal_cli/cmd_prompt.py | 380 | except Exception: | CODE |
| LOW⚡ | observal_cli/cmd_auth.py | 966 | except Exception: | CODE |
| LOW⚡ | observal_cli/cmd_auth.py | 980 | except Exception: | CODE |
| LOW | observal_cli/cmd_auth.py | 99 | except Exception: | CODE |
| LOW | observal_cli/cmd_auth.py | 178 | except Exception as e: | CODE |
| LOW | observal_cli/cmd_auth.py | 265 | except Exception: | CODE |
| LOW | observal_cli/cmd_auth.py | 354 | except Exception: | CODE |
| LOW | observal_cli/cmd_auth.py | 441 | except Exception: | CODE |
| LOW | observal_cli/cmd_auth.py | 484 | except Exception: | CODE |
| LOW | observal_cli/cmd_auth.py | 522 | except Exception as e: | CODE |
| LOW | observal_cli/cmd_auth.py | 533 | except Exception: | CODE |
| LOW | observal_cli/cmd_auth.py | 552 | except Exception: | CODE |
| LOW | observal_cli/cmd_auth.py | 614 | except Exception: | CODE |
| LOW | observal_cli/cmd_auth.py | 702 | except Exception: | CODE |
| LOW | observal_cli/cmd_auth.py | 914 | except Exception as e: | CODE |
| 296 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | observal_cli/cmd_hook.py | 480 | # Write/merge config into the harness's hooks config file | COMMENT |
| MEDIUM | observal_cli/cmd_agent.py | 868 | # Optional per-harness model overrides, e.g. {"kiro": "claude-haiku-4-5"}. | COMMENT |
| MEDIUM | observal_cli/lockfile.py | 179 | # Local names become harness config keys and on-disk names, where a dot reads | COMMENT |
| MEDIUM | observal_cli/lockfile.py | 558 | # We don't know which harness was used, default to claude-code | COMMENT |
| MEDIUM⚡ | observal_cli/render.py | 153 | # ── harness tag rendering ──────────────────────────────────── | COMMENT |
| MEDIUM | observal_cli/cmd_ops.py | 1428 | # Detail endpoint failed (e.g. no session parser for this harness) | COMMENT |
| MEDIUM⚡ | observal_cli/cmd_pull.py | 557 | # validates the candidate against the harness registry and falls | 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 | 700 | # MCP servers are harness-agnostic - config generation handles all harnesses. | 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 | 610 | # User-scope skill directories per harness (global install locations) | COMMENT |
| MEDIUM | observal_cli/cmd_scan.py | 35 | # ── harness home directory paths (for status display) ──────────────── | COMMENT |
| MEDIUM | observal_cli/cmd_scan.py | 78 | # Validate harness filter | COMMENT |
| MEDIUM | observal_cli/cmd_scan.py | 138 | # Determine status for this harness | COMMENT |
| MEDIUM | observal_cli/skill_installer.py | 52 | # Only install if the harness directory exists (harness is installed) | COMMENT |
| MEDIUM⚡ | observal_cli/tests/test_cmd_auth.py | 346 | # ── 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 | 728 | # Install harness hooks for telemetry (non-interactive) | COMMENT |
| MEDIUM⚡ | observal_cli/sessions/base.py | 805 | # Prefer a harness-scoped match, but fall back to an unscoped UUID | COMMENT |
| MEDIUM⚡ | observal_cli/sessions/base.py | 806 | # lookup. A UUID is globally unique, and the harness recorded at pull | COMMENT |
| MEDIUM⚡ | observal_cli/sessions/base.py | 809 | # defaults harness to "claude-code" when a caller sets payload["harness"] | COMMENT |
| MEDIUM | observal_cli/sessions/base.py | 686 | # Per-session layer_hash cache: avoids re-scanning harness dirs on every chunk | 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 | 437 | # Agent is stored only under the 'copilot' harness key. | COMMENT |
| MEDIUM⚡ | tests/test_copilot_integration.py | 444 | # harness reported by the push payload differs from the lockfile key | COMMENT |
| MEDIUM⚡ | tests/test_copilot_integration.py | 446 | # build_payload's default harness also differs | COMMENT |
| MEDIUM⚡ | tests/test_harness_config_e2e.py | 420 | # 3. harness COMPATIBILITY WARNINGS | COMMENT |
| MEDIUM⚡ | tests/test_harness_config_e2e.py | 625 | # 8. PULL — Full CLI flow (E2E per harness) | COMMENT |
| MEDIUM⚡ | tests/test_harness_config_e2e.py | 862 | # 9. CROSS-CUTTING — format correctness per harness spec | COMMENT |
| MEDIUM⚡ | tests/test_harness_config_e2e.py | 928 | # 10. DOCTOR — Copilot harness config checks | COMMENT |
| MEDIUM⚡ | tests/test_harness_config_e2e.py | 1037 | # 13. DOCTOR — OpenCode harness config checks | COMMENT |
| MEDIUM | tests/test_harness_config_e2e.py | 7 | """Comprehensive end-to-end tests for issue #434: first-class harness support. | STRING |
| MEDIUM | tests/test_antigravity_sessions.py | 203 | # ── Server harness adapter ──────────────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | observal-server/tests/test_agent_versions_api.py | 685 | # 5. harness config endpoint | COMMENT |
| MEDIUM | observal-server/tests/test_agent_versions_api.py | 720 | 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 | 30 | # ── harness / client names (hyphen-canonical) ─────────────────── | COMMENT |
| MEDIUM⚡ | observal-server/schemas/constants.py | 34 | # ── harness feature capabilities ────────────────────────────────── | COMMENT |
| MEDIUM | observal-server/schemas/dashboard.py | 101 | # --- harness usage --- | COMMENT |
| MEDIUM | observal-server/schemas/agent.py | 280 | # harness-specific install options (e.g. scope, model, tools, color for Claude Code) | COMMENT |
| MEDIUM | observal-server/api/routes/layer_snapshot.py | 298 | # Flatten {harnesses: {name: [files]}} to {"harness/path": file_dict} | STRING |
| MEDIUM | observal-server/api/routes/agent_versions.py | 140 | # A version carries the agent's prompt and generated harness config. Seeing the | COMMENT |
| MEDIUM | observal-server/api/routes/agent_versions.py | 185 | # A version carries the agent's prompt and generated harness config. Seeing the | COMMENT |
| MEDIUM | observal-server/api/routes/agent_versions.py | 302 | # Infer harness features from components | COMMENT |
| MEDIUM | observal-server/api/routes/agent_versions.py | 323 | # Pre-generate harness configs at release time (spec: no generation at request time) | COMMENT |
| MEDIUM | observal-server/api/routes/agent_versions.py | 330 | # Pre-generate harness configs for supported_harnesses (the user-declared list). | COMMENT |
| MEDIUM | observal-server/api/routes/agent_versions.py | 410 | # A version carries the agent's prompt and generated harness config. Seeing the | COMMENT |
| MEDIUM | observal-server/api/routes/agent_versions.py | 489 | # A version carries the agent's prompt and generated harness config. Seeing the | COMMENT |
| MEDIUM | observal-server/api/routes/inbox.py | 431 | # One notice per component, whichever harness reported it first. The same | COMMENT |
| MEDIUM | observal-server/api/routes/agent/draft.py | 201 | # Auto-infer harness features for draft (use request data, not ORM relationship) | COMMENT |
| 30 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | observal_cli/upgrade_executor.py | 33 | CODE | |
| LOW | observal_cli/upgrade_executor.py | 151 | CODE | |
| LOW | observal_cli/cmd_support.py | 188 | CODE | |
| LOW | observal_cli/cmd_support.py | 493 | CODE | |
| LOW | observal_cli/cmd_hook.py | 101 | CODE | |
| LOW | observal_cli/cmd_agent.py | 987 | CODE | |
| LOW | observal_cli/lockfile.py | 274 | CODE | |
| LOW | observal_cli/lockfile.py | 360 | CODE | |
| LOW | observal_cli/lockfile.py | 481 | CODE | |
| LOW | observal_cli/cmd_uninstall.py | 231 | CODE | |
| LOW | observal_cli/cmd_uninstall.py | 235 | CODE | |
| LOW | observal_cli/cmd_ops.py | 1403 | CODE | |
| LOW | observal_cli/client.py | 78 | CODE | |
| LOW | observal_cli/cmd_pull.py | 37 | CODE | |
| LOW | observal_cli/cmd_pull.py | 115 | CODE | |
| LOW | observal_cli/cmd_pull.py | 196 | CODE | |
| LOW | observal_cli/cmd_pull.py | 272 | CODE | |
| LOW | observal_cli/cmd_pull.py | 328 | CODE | |
| LOW | observal_cli/cmd_pull.py | 500 | CODE | |
| LOW | observal_cli/cmd_pull.py | 584 | CODE | |
| LOW | observal_cli/cmd_pull.py | 586 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 251 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 302 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 430 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 471 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 586 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 737 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 800 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 877 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 926 | CODE | |
| LOW | observal_cli/cmd_doctor.py | 1383 | CODE | |
| LOW | observal_cli/sandbox_runner.py | 248 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 256 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 322 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 425 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 476 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 1028 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 1514 | CODE | |
| LOW | observal_cli/upgrade_lock.py | 28 | CODE | |
| LOW | observal_cli/lockfile_reconcile.py | 46 | CODE | |
| LOW | observal_cli/lockfile_reconcile.py | 81 | CODE | |
| LOW | observal_cli/cmd_auth.py | 134 | CODE | |
| LOW | observal_cli/cmd_auth.py | 620 | CODE | |
| LOW | observal_cli/cmd_outdated.py | 23 | CODE | |
| LOW | observal_cli/cmd_outdated.py | 25 | CODE | |
| LOW | observal_cli/cmd_server.py | 67 | CODE | |
| LOW | observal_cli/cmd_server.py | 224 | CODE | |
| LOW | observal_cli/cmd_server.py | 381 | CODE | |
| LOW | observal_cli/cmd_server.py | 407 | CODE | |
| LOW | observal_cli/cmd_server.py | 449 | CODE | |
| LOW | observal_cli/cmd_server.py | 599 | CODE | |
| LOW | observal_cli/sandbox_mcp.py | 61 | CODE | |
| LOW | observal_cli/layer.py | 357 | CODE | |
| LOW | observal_cli/layer.py | 739 | CODE | |
| LOW | observal_cli/version_check.py | 413 | CODE | |
| LOW | observal_cli/version_check.py | 506 | CODE | |
| LOW | observal_cli/cmd_scan.py | 53 | CODE | |
| LOW | observal_cli/cmd_scan.py | 55 | CODE | |
| LOW | observal_cli/cmd_migrate.py | 266 | CODE | |
| LOW | observal_cli/cmd_migrate.py | 440 | CODE | |
| 142 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/test_device_auth.py | 492 | # Step 1: CLI requests device authorization | COMMENT |
| LOW⚡ | tests/test_device_auth.py | 499 | # Step 2: CLI polls -- should get authorization_pending | COMMENT |
| LOW⚡ | tests/test_device_auth.py | 510 | # Step 3: User confirms in browser | COMMENT |
| LOW⚡ | tests/test_device_auth.py | 518 | # Step 4: CLI polls again -- should get tokens | COMMENT |
| LOW | tests/test_device_auth.py | 534 | # Step 5: Polling again should return expired_token (keys cleaned up) | COMMENT |
| LOW⚡ | tests/test_migration_job_lifecycle.py | 80 | # Step 1: queued → running | COMMENT |
| LOW⚡ | tests/test_migration_job_lifecycle.py | 85 | # Step 2: running → completed | 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 | 144 | ## Step 3: Create CLI Adapter (Scanning) | COMMENT |
| LOW | docs/adding-a-harness.md | 316 | ## Step 4: Create Server-Side Config Generator (Install) | COMMENT |
| LOW | docs/adding-a-harness.md | 354 | ## Step 5: Create Hook Spec | COMMENT |
| LOW | docs/adding-a-harness.md | 396 | ## Step 6: Add the Session Source Adapter and Parser (required) | COMMENT |
| LOW | docs/adding-a-harness.md | 423 | ## Step 7: Configure the Shared Session Hook | COMMENT |
| LOW | docs/adding-a-harness.md | 433 | ## Step 8: Register Everything | COMMENT |
| LOW | docs/adding-a-harness.md | 452 | ## Step 9: Tests | COMMENT |
| LOW | docs/adding-a-harness.md | 526 | ## 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 |
|---|---|---|---|---|
| LOW | CHANGELOG.md | 702 | - fix reuse-lint and dependency-audit for fake-key fixture ([de356e7](https://github.com/Observal/Observal/commit/de356e | CODE |
| LOW | CHANGELOG.md | 2022 | - add secret_scanning.yml paths-ignore for fake-key test fixtures ([54faf17](https://github.com/Observal/Observal/commit | CODE |
| LOW | web/src/pages/admin/audit-log.tsx | 40 | // Supports quoted values: actor:"John Doe" action:"agent.pull" | COMMENT |
| LOW | web/src/pages/user/traces/index.tsx | 59 | // ── Search query parser (Discord-style: platform:kiro user:"John Doe") ─────── | COMMENT |
| 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_saml.py | 84 | assert email == "user@example.com" | CODE |
| LOW⚡ | tests/test_saml.py | 252 | mock_auth.get_nameid.return_value = "user@example.com" | CODE |
| LOW⚡ | tests/test_saml.py | 257 | mock_user.email = "user@example.com" | CODE |
| LOW⚡ | tests/test_saml.py | 263 | mock_user.sso_subject_id = "user@example.com" | CODE |
| LOW⚡ | tests/test_saml.py | 638 | mock_auth.get_nameid.return_value = "user@example.com" | CODE |
| LOW⚡ | tests/test_saml.py | 643 | mock_user.email = "user@example.com" | CODE |
| LOW⚡ | tests/test_saml.py | 649 | mock_user.sso_subject_id = "user@example.com" | CODE |
| LOW⚡ | tests/test_saml.py | 729 | mock_auth.get_nameid.return_value = "user@example.com" | CODE |
| LOW⚡ | tests/test_saml.py | 734 | mock_user.email = "user@example.com" | CODE |
| LOW⚡ | tests/test_saml.py | 740 | 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 | 514 | headers={"Authorization": "Bearer fake-token"}, | CODE |
| LOW | tests/test_device_auth.py | 346 | headers={"Authorization": "Bearer fake-token"}, | CODE |
| LOW | tests/test_device_auth.py | 376 | headers={"Authorization": "Bearer fake-token"}, | CODE |
| LOW | tests/test_device_auth.py | 414 | headers={"Authorization": "Bearer fake-token"}, | CODE |
| LOW | tests/test_device_auth.py | 451 | 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_scim.py | 138 | r = await ac.post("/api/v1/scim/Users", json={"userName": "test@test.com"}) | 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 |
| LOW⚡ | tests/test_github_oauth.py | 159 | fake_user.id = "u-1" | CODE |
| LOW⚡ | tests/test_github_oauth.py | 160 | fake_user.email = "alice@acme.com" | CODE |
| LOW⚡ | tests/test_github_oauth.py | 161 | fake_user.role = MagicMock(value="user") | CODE |
| LOW⚡ | tests/test_github_oauth.py | 163 | provision_mock = AsyncMock(return_value=fake_user) | CODE |
| LOW⚡ | tests/test_github_oauth.py | 191 | fake_user = MagicMock() | CODE |
| LOW⚡ | tests/test_github_oauth.py | 192 | fake_user.id = "u-1" | CODE |
| LOW⚡ | tests/test_github_oauth.py | 193 | fake_user.email = "backup@acme.com" | CODE |
| 9 more matches not shown… | ||||
| 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_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 |
|---|---|---|---|---|
| LOW⚡ | tests/test_device_auth.py | 492 | # Step 1: CLI requests device authorization | COMMENT |
| LOW⚡ | tests/test_device_auth.py | 499 | # Step 2: CLI polls -- should get authorization_pending | COMMENT |
| LOW⚡ | tests/test_device_auth.py | 510 | # Step 3: User confirms in browser | COMMENT |
| LOW⚡ | tests/test_device_auth.py | 518 | # Step 4: CLI polls again -- should get tokens | COMMENT |
| LOW | tests/test_device_auth.py | 534 | # Step 5: Polling again should return expired_token (keys cleaned up) | COMMENT |
| LOW⚡ | tests/test_migration_job_lifecycle.py | 80 | # Step 1: queued → running | COMMENT |
| LOW⚡ | tests/test_migration_job_lifecycle.py | 85 | # Step 2: running → completed | 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 | 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 | web/src/pages/user/inbox.tsx | 161 | 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 | 141 | # flushes as it goes: the Agent, then its version, then its | COMMENT |
| LOW | observal-server/api/routes/teams.py | 601 | raise HTTPException(status_code=409, detail="Personal teamspaces cannot be deleted") | COMMENT |
| LOW | observal-server/api/routes/__init__.py | 1 | # SPDX-FileCopyrightText: 2026 Subramania Raja <dhanpraja231@gmail.com> | COMMENT |
| LOW | observal-server/api/routes/review.py | 941 | rejected_version = pending_versions[0].version if pending_versions else "" | COMMENT |
| LOW | observal-server/api/routes/co_authors.py | 201 | # Transfer rewrites the namespace to the target user's handle, so a teamspace | 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 | .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 |
|---|---|---|---|---|
| HIGH | observal_cli/upgrade_lock.py | 29 | 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 | 171 | Scan the user's home directory for this harness's configuration. Args: home: Override home director | STRING |
| HIGH | observal_cli/harness/protocol.py | 193 | Scan a project directory for this harness's configuration. Args: project_dir: The project root to s | STRING |
| HIGH | observal_cli/harness/protocol.py | 224 | Generate hook configuration for telemetry collection. Args: observal_url: The Observal server URL. | STRING |
| HIGH | observal_cli/harness/protocol.py | 240 | Detect whether Observal hooks are already installed. Args: config_dir: harness-specific config dire | STRING |
| HIGH | observal-server/services/skill_validator.py | 209 | Fetch SKILL.md and validate its frontmatter. Args: git_url: Repository URL (GitHub or generic git host). | 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 | 157 | # Create a dummy tar.gz file | COMMENT |
| MEDIUM | observal_cli/server/orchestrator.py | 203 | # 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 | 509 | # Create a mock MCP listing with mcp_validated=False | COMMENT |
| MEDIUM | tests/test_migration_api.py | 188 | # 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 | infra/terraform/aws-ec2/deploy.sh | 73 | # Print output | COMMENT |
| LOW | infra/terraform/aws/variables.tf | 401 | # 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/client.py | 66 | # Check if current subcommand is exempt (handle flags before subcommand) | COMMENT |
| LOW | observal_cli/cmd_doctor.py | 266 | # Check if session push hooks are installed | COMMENT |
| LOW | observal_cli/cmd_doctor.py | 479 | # Check if VS Code / Copilot is even present | COMMENT |
| LOW | observal_cli/cmd_doctor.py | 1259 | # Check if already patched | COMMENT |
| LOW | observal_cli/cmd_doctor.py | 1404 | # Check if already patched | COMMENT |
| LOW | observal_cli/cmd_doctor.py | 1564 | # Check if running under /mnt/c/Users/<name>/... | COMMENT |
| LOW | observal_cli/cmd_doctor.py | 1614 | # Check if already patched | COMMENT |
| LOW | observal_cli/upgrade_lock.py | 49 | # Check if lock is stale (>30 minutes old) | COMMENT |
| LOW | observal_cli/cmd_server.py | 87 | # Check if port is available, try fallbacks if default | 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 | 314 | # 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 |
| LOW | …observal-shared/observal_shared/migration/ch_export.py | 269 | # Check if file is actually empty (edge case) | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | observal_cli/cmd_hook.py | 101 | CODE | |
| LOW | observal_cli/cmd_agent.py | 107 | CODE | |
| LOW | observal_cli/cmd_agent.py | 447 | CODE | |
| LOW | observal_cli/cmd_agent.py | 799 | CODE | |
| LOW | observal_cli/cmd_pull.py | 586 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 1251 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 1325 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 1446 | CODE | |
| LOW | observal_cli/cmd_mcp.py | 1514 | CODE | |
| LOW | observal_cli/cmd_prompt.py | 41 | CODE | |
| LOW | observal_cli/cmd_skill.py | 111 | CODE | |
| LOW | observal_cli/cmd_skill.py | 689 | CODE | |
| LOW | observal_cli/cmd_skill.py | 767 | CODE | |
| LOW | observal_cli/cmd_sandbox.py | 91 | CODE | |
| LOW | observal_cli/cmd_sandbox.py | 339 | CODE | |
| LOW | observal_cli/sessions/base.py | 469 | CODE | |
| LOW | observal-server/api/routes/skill.py | 195 | CODE | |
| LOW | observal-server/api/routes/sessions.py | 64 | CODE | |
| LOW | observal-server/api/routes/hook.py | 123 | CODE | |
| LOW | observal-server/api/routes/review.py | 1109 | CODE | |
| LOW | observal-server/api/routes/dashboard.py | 532 | CODE | |
| LOW | observal-server/api/routes/sandbox.py | 115 | CODE | |
| LOW | observal-server/api/routes/mcp.py | 224 | CODE | |
| LOW | observal-server/api/routes/inbox.py | 130 | CODE | |
| LOW | observal-server/api/routes/prompt.py | 114 | 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/crud.py | 253 | 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 | 168 | CODE | |
| LOW | observal-server/services/audit/event_handlers.py | 44 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tools/release.py | 396 | def set_version(path: Path, version: str) -> None: | CODE |
| LOW | observal_cli/config.py | 18 | logger = logging.getLogger(__name__) | CODE |
| LOW | observal_cli/client.py | 22 | logger = logging.getLogger(__name__) | CODE |
| LOW | observal_cli/cmd_server.py | 428 | 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 | 27 | __all__ = [ | CODE |
| LOW | observal-server/models/user.py | 58 | def set_password(self, password: str) -> None: | CODE |
| LOW | observal-server/models/__init__.py | 40 | __all__ = [ | 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 | 46 | __all__ = [ | CODE |
| LOW | observal-server/services/inbox/__init__.py | 24 | __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 |
|---|---|---|---|---|
| HIGH | AI_POLICY.md | 21 | The [US Copyright Office's January 2025 report on AI copyrightability](https://www.copyright.gov/ai/Copyright-and-Artifi | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | observal_cli/cmd_insights.py | 601 | rprint(" [cyan]observal admin set insights.api_key <your-api-key>[/cyan]") | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| 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 |
|---|---|---|---|---|
| LOW⚡ | infra/terraform/deploy.sh | 9 | # Usage: | COMMENT |
| LOW | infra/terraform/aws/deploy.sh | 11 | # Usage: | COMMENT |