-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Feat/agent recommended additions #1661
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
SrihariLegend
wants to merge
2
commits into
Observal:main
Choose a base branch
from
SrihariLegend:feat/agent-recommended-additions
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
40 changes: 40 additions & 0 deletions
40
observal-server/alembic/versions/023_insight_analysis_payload.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| # SPDX-FileCopyrightText: 2026 The Observal Authors | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| """Persist insights analysis previously discarded each run. | ||
|
|
||
| Adds ``version_impact`` and ``registry_offer`` (JSON, nullable) to | ||
| ``insight_reports``. The pipeline already computes both every run — the | ||
| cross-user layer/config correlation analysis and the deterministic registry | ||
| component shortlist shown to the model — but historically folded them into the | ||
| LLM prompt and then discarded them. These columns persist that analysis so | ||
| downstream consumers (duplicate detection, pull-time recommendations, | ||
| governance drift signals) can read it without re-running the pipeline. | ||
|
|
||
| Both columns are nullable: pre-existing reports predate the columns (and never | ||
| had the data), and a run may legitimately produce no version impact or an | ||
| empty offer. No backfill is needed — null is the correct value for old rows. | ||
|
|
||
| Revision ID: 023_insight_analysis_payload | ||
| Revises: 022_user_recommendations | ||
| Create Date: 2026-08-03 | ||
| """ | ||
|
|
||
| import sqlalchemy as sa | ||
|
|
||
| from alembic import op | ||
|
|
||
| revision = "023_insight_analysis_payload" | ||
| down_revision = "022_user_recommendations" | ||
| branch_labels = None | ||
| depends_on = None | ||
|
|
||
|
|
||
| def upgrade() -> None: | ||
| op.add_column("insight_reports", sa.Column("version_impact", sa.JSON(), nullable=True)) | ||
| op.add_column("insight_reports", sa.Column("registry_offer", sa.JSON(), nullable=True)) | ||
|
|
||
|
|
||
| def downgrade() -> None: | ||
| op.drop_column("insight_reports", "registry_offer") | ||
| op.drop_column("insight_reports", "version_impact") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| # SPDX-FileCopyrightText: 2026 The Observal Authors | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| """Typed schema for the insights pipeline's analytical payload. | ||
|
|
||
| The pipeline computes a rich set of analysis *before* it writes any narrative | ||
| prose: deterministic metrics, LLM-extracted facets, cross-user version-impact | ||
| analysis, and a deterministic registry shortlist. Historically most of this | ||
| was stored as untyped JSON blobs on the ``InsightReport`` (``metrics``, | ||
| ``narrative``, ``aggregated_data``), while ``version_impact`` and | ||
| ``registry_offer`` were computed and then discarded every run. | ||
|
|
||
| This module defines the canonical top-level shape of that payload so there is | ||
| a single source of truth for what one pipeline run produces, and so structural | ||
| drift (a whole section going missing, a dict arriving as a list) is detectable | ||
| at write time instead of silently persisted. | ||
|
|
||
| The schema is intentionally permissive on nested fields: ``metrics``, | ||
| ``narrative`` and ``aggregated_data`` carry LLM-generated content whose exact | ||
| shape varies, so they are typed as ``dict`` rather than fully modelled. | ||
| Validation catches gross structural errors, not minor LLM output variance — a | ||
| report must never fail to persist because the model added an unexpected field. | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import structlog | ||
| from pydantic import BaseModel, ConfigDict, Field, ValidationError | ||
|
|
||
| logger = structlog.get_logger(__name__) | ||
|
|
||
|
|
||
| class InsightAnalysisPayload(BaseModel): | ||
| """The analytical output of one insights pipeline run. | ||
|
|
||
| Fields are grouped by how they were produced so a reader can tell | ||
| deterministic data apart from LLM-inferred content: | ||
|
|
||
| * Deterministic: ``metrics``, ``aggregated_data``, ``version_impact``, | ||
| ``registry_offer``, ``facets_summary`` (the last is an aggregate of | ||
| per-session LLM facets, but the aggregation itself is deterministic). | ||
| * Generated: ``narrative`` (the LLM-written report sections, including | ||
| ``suggestions``). | ||
| """ | ||
|
|
||
| model_config = ConfigDict(extra="allow") | ||
|
|
||
| # Deterministic metrics from ClickHouse (has ``rich`` / ``overview``). | ||
| metrics: dict = Field(default_factory=dict) | ||
| # LLM-generated narrative sections (including ``suggestions``). | ||
| narrative: dict = Field(default_factory=dict) | ||
| # Pre-existing roll-up: metrics + facets_summary + regressions + | ||
| # cross_user_patterns. Kept as a dict for back-compat with readers. | ||
| aggregated_data: dict = Field(default_factory=dict) | ||
| # Cross-user layer/config correlation analysis. Previously discarded | ||
| # after being folded into the LLM prompt; now persisted. | ||
| version_impact: dict | None = None | ||
| # Deterministic shortlist of registry components the agent does not yet | ||
| # use. Previously discarded after being shown to the model; now persisted | ||
| # so future consumers (duplicate detection, pull-time recs) can read it | ||
| # without re-running the pipeline. | ||
| registry_offer: dict | None = None | ||
| # Aggregate of per-session facets. | ||
| facets_summary: dict = Field(default_factory=dict) | ||
| # Number of sessions the run analysed. | ||
| sessions_analyzed: int = 0 | ||
|
|
||
|
|
||
| def validate_payload(content: dict) -> dict | None: | ||
| """Structurally validate a pipeline run's output. | ||
|
|
||
| Returns a validated ``InsightAnalysisPayload`` dict on success, or ``None`` | ||
| on structural mismatch. Failures are *never* fatal: callers persist the | ||
| raw ``content`` dict as a fallback so a schema mismatch cannot break | ||
| report generation. The mismatch is logged so drift is observable. | ||
| """ | ||
| try: | ||
| payload = InsightAnalysisPayload.model_validate(content) | ||
| except ValidationError as e: | ||
| # Log only loc/type/msg — never the raw input, which can carry | ||
| # LLM-generated narrative or session-derived text from ``content``. | ||
| safe = [{"loc": err["loc"], "type": err["type"], "msg": err["msg"]} for err in e.errors(include_input=False)] | ||
| logger.warning("insight_payload_validation_failed", errors=safe) | ||
| return None | ||
| return payload.model_dump() | ||
|
|
||
|
|
||
| __all__ = ["InsightAnalysisPayload", "validate_payload"] | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Use the required Loguru logger for validation events.
The new validation logs use
structlogorlogger. Usefrom loguru import logger as opticand positional formatting for these events.observal-server/schemas/insight_analysis.py#L27-L30: replace thestructlogimport and logger binding with the required Loguru alias.observal-server/schemas/insight_analysis.py#L83-L83: emit the sanitized validation errors withoptic.warning("insight_payload_validation_failed errors={}", safe).observal-server/services/insights/batch.py#L269-L275: emit validation metadata withoptic.info(...)and positional arguments.As per coding guidelines, use Loguru via
from loguru import logger as opticand pass positional arguments without f-strings.📍 Affects 2 files
observal-server/schemas/insight_analysis.py#L27-L30(this comment)observal-server/schemas/insight_analysis.py#L83-L83observal-server/services/insights/batch.py#L269-L275🤖 Prompt for AI Agents
Source: Coding guidelines