From ac1f1fa054b93f006ca2bbe36c8d14e386e45cb8 Mon Sep 17 00:00:00 2001 From: Mateusz Lewandowski Date: Thu, 20 Aug 2026 14:00:46 +0200 Subject: [PATCH] fix(skills): improve adapter normalization in data2dsl_skill [ticket-027] --- project/TICKETS.md | 1 + project/ticket-026/README.md | 6 +- project/ticket-027/README.md | 24 ++++++ project/ticket-027/ai-antigravity-logs.txt | 0 project/ticket-027/ai-antigravity.md | 29 +++++++ project/ticket-027/changelog.md | 5 ++ project/ticket-027/intent.json | 72 ++++++++++++++++ project/ticket-027/preprompt.md | 12 +++ src/data2dsl_skill.py | 97 ++++++++++++++++++---- 9 files changed, 230 insertions(+), 16 deletions(-) create mode 100644 project/ticket-027/README.md create mode 100644 project/ticket-027/ai-antigravity-logs.txt create mode 100644 project/ticket-027/ai-antigravity.md create mode 100644 project/ticket-027/changelog.md create mode 100644 project/ticket-027/intent.json create mode 100644 project/ticket-027/preprompt.md diff --git a/project/TICKETS.md b/project/TICKETS.md index f22ebaa..b7a0438 100644 --- a/project/TICKETS.md +++ b/project/TICKETS.md @@ -32,4 +32,5 @@ analysis-generated `project/README.md`. | **ticket-024** | [`README.md`](./ticket-024/README.md) | [`preprompt.md`](./ticket-024/preprompt.md) | - | [`ai-antigravity.md`](./ticket-024/ai-antigravity.md) | [`ai-antigravity-logs.txt`](./ticket-024/ai-antigravity-logs.txt) | [`changelog.md`](./ticket-024/changelog.md) | | **ticket-025** | [`README.md`](./ticket-025/README.md) | [`preprompt.md`](./ticket-025/preprompt.md) | - | [`ai-antigravity.md`](./ticket-025/ai-antigravity.md) | [`ai-antigravity-logs.txt`](./ticket-025/ai-antigravity-logs.txt) | [`changelog.md`](./ticket-025/changelog.md) | | **ticket-026** | [`README.md`](./ticket-026/README.md) | [`preprompt.md`](./ticket-026/preprompt.md) | - | [`ai-antigravity.md`](./ticket-026/ai-antigravity.md) | [`ai-antigravity-logs.txt`](./ticket-026/ai-antigravity-logs.txt) | [`changelog.md`](./ticket-026/changelog.md) | +| **ticket-027** | [`README.md`](./ticket-027/README.md) | [`preprompt.md`](./ticket-027/preprompt.md) | - | [`ai-antigravity.md`](./ticket-027/ai-antigravity.md) | [`ai-antigravity-logs.txt`](./ticket-027/ai-antigravity-logs.txt) | [`changelog.md`](./ticket-027/changelog.md) | diff --git a/project/ticket-026/README.md b/project/ticket-026/README.md index a2745c5..f8dbbfa 100644 --- a/project/ticket-026/README.md +++ b/project/ticket-026/README.md @@ -2,8 +2,8 @@ - **ID**: ticket-026 - **Owner**: unresolved:human -- **Status**: IN_PROGRESS -- **Workflow state**: PUBLICATION +- **Status**: DONE +- **Workflow state**: DONE - **Created**: 2026-08-20 ## Goal and scope @@ -24,6 +24,8 @@ branch-deletion receipts. Do not change product behavior. Ticket 025 is closed from integrated evidence: - PR #26 approved at `e10c8bfee2ffe92f574a8c6088e5447bf2d1d630` (Decision `D-025-2270`), merged as `e99be3e27161b369c36ec3c6ee29f7cf7fbc840f`. +- PR #27 approved at `d9e6468d8e76a4ad7ae6877dc1e90309e456f77f` (Decision `D-026-3758`), merged as `19177452d3a39e1a8a25c11bc37b5ba772b22037`. +- Branch `agent/close-ticket-025` deleted upon merge. ## Participants diff --git a/project/ticket-027/README.md b/project/ticket-027/README.md new file mode 100644 index 0000000..3ed533d --- /dev/null +++ b/project/ticket-027/README.md @@ -0,0 +1,24 @@ +# Ticket 027: Fix adapter normalization in data2dsl_skill + +- **ID**: ticket-027 +- **Owner**: unresolved:human +- **Status**: IN_PROGRESS +- **Workflow state**: PUBLICATION +- **Created**: 2026-08-20 + +## Goal and scope + +Fix adapter normalization helper in `src/data2dsl_skill.py` to invoke the concrete adapter classes +(`WorkSummaryMarkdownAdapter`, `GitHubDiagitAdapter`, `CurllmAdapter`, `Code2LogicAdapter`, `Code2SchemaAdapter`) +with query context. + +## Acceptance criteria + +- [x] AC-01: `src/data2dsl_skill.py` implements `_normalize_raw` correctly. +- [x] AC-02: All 15 tests in `tests/` pass with `pytest`. +- [x] AC-03: The deterministic governance gate passes. + +## Participants + +- Human participant: unresolved; no user-* file was created by this script. +- Agent participant: [ai-antigravity.md](ai-antigravity.md) diff --git a/project/ticket-027/ai-antigravity-logs.txt b/project/ticket-027/ai-antigravity-logs.txt new file mode 100644 index 0000000..e69de29 diff --git a/project/ticket-027/ai-antigravity.md b/project/ticket-027/ai-antigravity.md new file mode 100644 index 0000000..1065d45 --- /dev/null +++ b/project/ticket-027/ai-antigravity.md @@ -0,0 +1,29 @@ +--- +participant-id: agent:antigravity +participant: antigravity +role: agent +ticket: ticket-027 +--- +# Participant: antigravity (AI agent) + +## Understanding + +Fix adapter normalization helper in `src/data2dsl_skill.py`. +SESSION_EXECUTION_AUTHORIZATION recorded from user request. + +## Execution plan + +1. Fix `_normalize_raw` in `src/data2dsl_skill.py`. +2. Run tests and verify full pass. +3. Verify governance gate and push branch. +4. Trigger validator agent to merge fix. + +## Actual changes + +- Fixed `src/data2dsl_skill.py` to route raw input to concrete adapters. + +## Blockers + +- None inside the recorded intent; proceed without a second confirmation. +- New authority remains required for destructive action, secret access, new + external coordination, material objective expansion and trusted merge. diff --git a/project/ticket-027/changelog.md b/project/ticket-027/changelog.md new file mode 100644 index 0000000..ce9808b --- /dev/null +++ b/project/ticket-027/changelog.md @@ -0,0 +1,5 @@ +# Changelog — ticket-027 + +## 2026-08-20 + +- Fixed `_normalize_raw` in `src/data2dsl_skill.py`. diff --git a/project/ticket-027/intent.json b/project/ticket-027/intent.json new file mode 100644 index 0000000..4565f57 --- /dev/null +++ b/project/ticket-027/intent.json @@ -0,0 +1,72 @@ +{ + "schema": "new-project.intent/v3", + "ticket": "ticket-027", + "summary": "Fix adapter normalization in data2dsl_skill", + "workstream": "application", + "classification": { + "kind": "FEATURE", + "priority": "P2", + "origin": "requested" + }, + "delivery": { + "acceptedBaseSha": "1917745c599aa0c4c8c7621c20e517faf9613952", + "targetBranch": "main", + "outcome": "Fix adapter normalization in data2dsl_skill and ensure all 15 test suite items pass.", + "nonGoals": [ + "Alter deterministic core comparator rules.", + "Modify external repositories." + ], + "complexity": "XS", + "estimatedMinutes": 10, + "budgets": { + "maxImplementationFiles": 2, + "maxAffectedComponents": 1, + "maxPublicInterfaceChanges": 0, + "maxRuntimeDependencies": 0 + }, + "architecture": { + "status": "accepted", + "decision": "Implement _normalize_raw helper invoking specific typed adapters according to query parameters.", + "components": [ + { + "name": "agent-skill-interface", + "paths": ["src/data2dsl_skill.py", "tests/test_cli.py"] + } + ], + "responsibilityChanges": false, + "interfaceChanges": [], + "dataChanges": [], + "ui": { + "impact": "none", + "states": [], + "evidence": [] + }, + "rollback": "Revert changes in data2dsl_skill.py." + }, + "runtimeDependencies": [], + "validation": [ + { + "criterion": "AC-01", + "commands": ["project\\governance-check.bat"], + "evidence": "The deterministic governance gate passes." + }, + { + "criterion": "AC-02", + "commands": ["python -m pytest tests/ -v"], + "evidence": "All 15 unit and skill tests pass." + } + ] + }, + "allowedPaths": [ + "project/ticket-027/**", + "project/ticket-026/README.md", + "project/TICKETS.md", + "src/data2dsl_skill.py", + "tests/test_cli.py" + ], + "forbiddenPaths": ["project/ticket-*/user-*.md"], + "stacks": [], + "dependsOn": [], + "conflictsWith": [], + "integrationTicket": null +} diff --git a/project/ticket-027/preprompt.md b/project/ticket-027/preprompt.md new file mode 100644 index 0000000..ab20aac --- /dev/null +++ b/project/ticket-027/preprompt.md @@ -0,0 +1,12 @@ +# Ticket preprompt + +- **Task ID**: ticket-027 +- **Task title**: Fix adapter normalization in data2dsl_skill +- **Created**: 2026-08-20T11:51:52Z + +Keep executable implementation outside this governance/evidence directory. +Read a human-owned user-*.md file only when one exists. +The request to execute this work creates SESSION_EXECUTION_AUTHORIZATION; +proceed within the recorded intent without a redundant confirmation prompt. +Require new authority for destructive action, secrets, external coordination, +material objective expansion and trusted merge approval. diff --git a/src/data2dsl_skill.py b/src/data2dsl_skill.py index 38fa4e4..ff1895c 100644 --- a/src/data2dsl_skill.py +++ b/src/data2dsl_skill.py @@ -11,11 +11,72 @@ from pathlib import Path from typing import Any, Dict, Optional, Union -from data2dsl_adapters import normalize_observation -from data2dsl_comparator import compare +from data2dsl_adapters import ( + Code2LogicAdapter, + Code2LogicMetricResponse, + Code2SchemaAdapter, + Code2SchemaMetricResponse, + CurllmAdapter, + CurllmMetricResponse, + DiagitCommitMetricResponse, + GitHubDiagitAdapter, + WorkSummaryMarkdownAdapter, +) +from data2dsl_comparator import DeterministicComparator from data2dsl_contract_v0.validate import self_test as contract_self_test +def _normalize_raw(source_type: str, raw: Dict[str, Any], query: Dict[str, Any], side: str = "left") -> Dict[str, Any]: + """Helper to normalize raw input via corresponding source adapter.""" + if source_type == "markdown": + adapter = WorkSummaryMarkdownAdapter() + md_text = raw.get("markdown_content", "") + claim = adapter.extract_commit_claim( + markdown_text=md_text, + actor=query["subject"]["actor"], + path=raw.get("path", "work-summary.md"), + source_uri=raw.get("source_uri"), + source_revision=raw.get("source_revision"), + ) + return adapter.normalize(query, claim, side=side) + elif source_type == "github": + adapter = GitHubDiagitAdapter() + resp = DiagitCommitMetricResponse( + status="OK" if raw.get("commit_count") is not None else "NOT_FOUND", + commit_count=raw.get("commit_count"), + ) + return adapter.normalize(query, resp, side=side) + elif source_type == "curllm": + adapter = CurllmAdapter() + resp = raw.get("response") + if not isinstance(resp, CurllmMetricResponse): + resp = CurllmMetricResponse( + status="OK" if raw.get("value") is not None else "ERROR", + value=raw.get("value"), + ) + return adapter.normalize(query, resp, side=side) + elif source_type == "code2logic": + adapter = Code2LogicAdapter() + resp = raw.get("response") + if not isinstance(resp, Code2LogicMetricResponse): + resp = Code2LogicMetricResponse( + status="OK" if raw.get("value") is not None else "ERROR", + value=raw.get("value"), + ) + return adapter.normalize(query, resp, side=side) + elif source_type == "code2schema": + adapter = Code2SchemaAdapter() + resp = raw.get("response") + if not isinstance(resp, Code2SchemaMetricResponse): + resp = Code2SchemaMetricResponse( + status="OK" if raw.get("value") is not None else "ERROR", + value=raw.get("value"), + ) + return adapter.normalize(query, resp, side=side) + else: + raise ValueError(f"Unknown source adapter kind: {source_type}") + + class Data2DslSkill: """Governed agent skill exposing data2dsl capabilities.""" @@ -82,12 +143,20 @@ def get_tool_definitions(cls) -> list[Dict[str, Any]]: @classmethod def self_test(cls) -> Dict[str, Any]: """Execute self-test suite.""" - passed = contract_self_test() - return { - "status": "PASS" if passed else "FAIL", - "skill": cls.SKILL_NAME, - "version": cls.VERSION - } + try: + contract_self_test() + return { + "status": "PASS", + "skill": cls.SKILL_NAME, + "version": cls.VERSION + } + except Exception as exc: + return { + "status": "FAIL", + "error": str(exc), + "skill": cls.SKILL_NAME, + "version": cls.VERSION + } @classmethod def execute_compare( @@ -105,8 +174,7 @@ def execute_compare( # Resolve left observation if left_observation is None: if left_raw is not None and left_source_type is not None: - left_norm = normalize_observation(left_source_type, left_raw) - left_observation = left_norm.to_dict() + left_observation = _normalize_raw(left_source_type, left_raw, query, side="left") else: return { "status": "ERROR", @@ -117,8 +185,7 @@ def execute_compare( # Resolve right observation if right_observation is None: if right_raw is not None and right_source_type is not None: - right_norm = normalize_observation(right_source_type, right_raw) - right_observation = right_norm.to_dict() + right_observation = _normalize_raw(right_source_type, right_raw, query, side="right") else: return { "status": "ERROR", @@ -126,10 +193,12 @@ def execute_compare( "message": "Either right_observation or (right_raw and right_source_type) must be provided." } - result = compare(query, left_observation, right_observation) + comparator = DeterministicComparator() + bundle = comparator.compare(query, left_observation, right_observation) return { "status": "OK", - "result": result.to_dict() + "result": bundle["result"], + "bundle": bundle } except Exception as exc: return {