CtrlK
BlogDocsLog inGet started
Tessl Logo

giuseppe-trisciuoglio/developer-kit

Comprehensive developer toolkit providing reusable skills for Java/Spring Boot, TypeScript/NestJS/React/Next.js, Python, PHP, AWS CloudFormation, AI/RAG, DevOps, and more.

90

Quality

90%

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Risky

Do not use without reviewing

This version of the tile failed moderation
Moderation pipeline encountered an internal error
Overview
Quality
Evals
Security
Files

specs-task-tdd-handoff.pyplugins/developer-kit-specs/hooks/

#!/usr/bin/env python3
"""Prepare implementation handoff artifacts for /specs:task-tdd."""

from __future__ import annotations

import argparse
import importlib.util
import json
import sys
from dataclasses import asdict, dataclass, field
from datetime import datetime
from pathlib import Path
from typing import Any

DRIFT_DIR_NAME = "_drift"
HANDOFF_FILE_PREFIX = "tdd-handoff-"


class TddHandoffError(ValueError):
    """Raised when TDD handoff preparation cannot complete safely."""

    def __init__(self, message: str, *, code: str) -> None:
        super().__init__(message)
        self.code = code


@dataclass
class HandoffResult:
    task_path: str
    handoff_path: str
    implementation_command: str
    red_phase_confirmed: bool
    generated_test_count: int
    summary_lines: list[str]
    warnings: list[str] = field(default_factory=list)

    def to_json(self) -> str:
        return json.dumps(asdict(self), indent=2)


def load_sibling_module(filename: str, module_name: str):
    module_path = Path(__file__).with_name(filename)
    spec = importlib.util.spec_from_file_location(module_name, module_path)
    if spec is None or spec.loader is None:
        raise TddHandoffError(f"Unable to load module from {module_path}.", code="E3")

    module = importlib.util.module_from_spec(spec)
    sys.modules[module_name] = module
    spec.loader.exec_module(module)
    return module


def load_parser_module():
    return load_sibling_module("specs-task-tdd-parser.py", "specs_task_tdd_parser")


def read_task_parts(task_path: str) -> tuple[Any, str]:
    parser_module = load_parser_module()
    try:
        task_data = parser_module.parse_task_file(task_path)
        content = parser_module.read_task_file(task_path)
        _, body = parser_module.split_frontmatter(content)
        return task_data, body
    except parser_module.TaskFileError as exc:
        raise TddHandoffError(str(exc), code=exc.code) from exc


def parse_frontmatter_values(task_path: str) -> dict[str, Any]:
    parser_module = load_parser_module()
    try:
        content = parser_module.read_task_file(task_path)
        frontmatter, _ = parser_module.split_frontmatter(content)
    except parser_module.TaskFileError as exc:
        raise TddHandoffError(str(exc), code=exc.code) from exc

    values: dict[str, Any] = {}
    for raw_line in frontmatter.splitlines():
        line = raw_line.strip()
        if not line or line.startswith("#"):
            continue
        if ":" not in line:
            raise TddHandoffError(
                f"Invalid frontmatter line: '{raw_line}'. Expected 'key: value' format.",
                code="E3",
            )
        key, raw_value = line.split(":", 1)
        key = key.strip()
        value = raw_value.strip()
        if key in {"testReferences", "redPhase"}:
            try:
                values[key] = json.loads(value) if value else None
            except json.JSONDecodeError as exc:
                raise TddHandoffError(
                    f"Invalid JSON payload for frontmatter field '{key}'.",
                    code="E3",
                ) from exc
        else:
            values[key] = value.strip('"') if value else None

    return values


def extract_section(body: str, heading: str) -> str:
    lines = body.splitlines()
    capture = False
    collected: list[str] = []

    for line in lines:
        stripped = line.strip()
        if stripped == heading:
            capture = True
            continue
        if capture and stripped.startswith("## "):
            break
        if capture:
            collected.append(line.rstrip())

    return "\n".join(collected).strip()


def build_implementation_command(task_path: str, language: str | None) -> str:
    parts = ["/specs:task-implementation"]
    if language:
        parts.append(f"--lang={language}")
    parts.append(f'--task="{task_path}"')
    return " ".join(parts)


def render_handoff_markdown(
    task_data,
    *,
    body: str,
    task_path: str,
    handoff_generated_at: str,
    test_references: list[dict[str, Any]],
    red_phase: dict[str, Any],
    implementation_command: str,
    warnings: list[str],
) -> str:
    functional_description = ""
    for line in body.splitlines():
        stripped = line.strip()
        if stripped.startswith("**Functional Description**:"):
            functional_description = stripped.split(":", 1)[1].strip()
            break

    acceptance_criteria = extract_section(body, "## Acceptance Criteria")
    technical_context = extract_section(body, "## Technical Context (from Codebase Analysis)")

    lines = [
        f"# TDD Implementation Handoff — {task_data.metadata['id']}",
        "",
        f"**Generated**: {handoff_generated_at}",
        f"**Task**: {task_data.metadata['id']} — {task_data.metadata['title']}",
        f"**Task File**: `{task_path}`",
        f"**Spec**: `{task_data.metadata['spec']}`",
        "",
        "## RED Phase Status",
        "",
    ]

    if red_phase.get("verified"):
        lines.append(f"RED phase confirmed via `{red_phase.get('framework', 'unknown')}`.")
    else:
        lines.append("RED phase is not confirmed yet.")

    if red_phase.get("summary"):
        lines.append(f"Summary: {red_phase['summary']}")

    lines.extend(["", "## Generated Tests", ""])
    if test_references:
        for reference in test_references:
            path = reference.get("path", "unknown")
            test_type = reference.get("test_type", "unknown")
            language = reference.get("language", "unknown")
            scenario_count = reference.get("scenario_count", "unknown")
            lines.append(f"- `{path}` ({test_type}, {language}, scenarios: {scenario_count})")
    else:
        lines.append("- No generated tests were recorded in task metadata.")

    lines.extend(["", "## Implementation Focus", ""])
    if functional_description:
        lines.append(functional_description)
        lines.append("")
    if acceptance_criteria:
        lines.append(acceptance_criteria)
    else:
        lines.append("No acceptance criteria were extracted from the task body.")

    lines.extend(["", "## Context To Preserve", ""])
    if technical_context:
        lines.append(technical_context)
    else:
        lines.append(
            "Use the task specification and generated failing tests as the source of truth for GREEN phase work."
        )

    lines.extend(
        [
            "",
            "## Next Steps",
            "",
            "1. Review the generated failing tests and confirm they still describe the intended behavior.",
            f"2. Start GREEN phase with `{implementation_command}`.",
            "3. Implement the minimum code required to make the generated tests pass, then proceed to REFACTOR.",
        ]
    )

    if warnings:
        lines.extend(["", "## Warnings", ""])
        for warning in warnings:
            lines.append(f"- {warning}")

    return "\n".join(lines).rstrip() + "\n"


def prepare_handoff(
    task_path: str,
    *,
    language: str | None = None,
    project_root: str = ".",
) -> HandoffResult:
    task_data, body = read_task_parts(task_path)
    frontmatter_values = parse_frontmatter_values(task_path)

    test_references = frontmatter_values.get("testReferences") or []
    if not isinstance(test_references, list):
        raise TddHandoffError(
            "Invalid task metadata: testReferences must be a JSON array.",
            code="E3",
        )

    red_phase = frontmatter_values.get("redPhase") or {}
    if not isinstance(red_phase, dict):
        raise TddHandoffError(
            "Invalid task metadata: redPhase must be a JSON object.",
            code="E3",
        )

    effective_language = language or task_data.metadata.get("lang")
    implementation_command = build_implementation_command(task_path, effective_language)

    warnings: list[str] = []
    if not test_references:
        warnings.append("No generated test references were found in the task metadata.")
    if not red_phase.get("verified"):
        warnings.append("RED phase is not confirmed in task metadata.")

    spec_path = Path(str(task_data.metadata["spec"]))
    drift_dir = (Path(project_root) / spec_path.parent / DRIFT_DIR_NAME).resolve()
    try:
        drift_dir.mkdir(parents=True, exist_ok=True)
    except PermissionError as exc:
        raise TddHandoffError(
            f"Permission denied: cannot create handoff directory {drift_dir}",
            code="E4",
        ) from exc

    handoff_path = drift_dir / f"{HANDOFF_FILE_PREFIX}{str(task_data.metadata['id']).lower()}.md"
    generated_at = datetime.now().isoformat(timespec="seconds")
    content = render_handoff_markdown(
        task_data,
        body=body,
        task_path=task_path,
        handoff_generated_at=generated_at,
        test_references=test_references,
        red_phase=red_phase,
        implementation_command=implementation_command,
        warnings=warnings,
    )

    try:
        handoff_path.write_text(content, encoding="utf-8")
    except PermissionError as exc:
        raise TddHandoffError(
            f"Permission denied: cannot write handoff file {handoff_path}",
            code="E4",
        ) from exc

    summary_lines = [
        f"Generated tests: {len(test_references)}",
        f"RED phase confirmed: {'yes' if red_phase.get('verified') else 'no'}",
        f"Implementation command: {implementation_command}",
    ]

    return HandoffResult(
        task_path=task_path,
        handoff_path=str(handoff_path),
        implementation_command=implementation_command,
        red_phase_confirmed=bool(red_phase.get("verified")),
        generated_test_count=len(test_references),
        summary_lines=summary_lines,
        warnings=warnings,
    )


def build_arg_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        description="Prepare TDD implementation handoff documentation."
    )
    parser.add_argument("--task", required=True, help="Path to the task markdown file.")
    parser.add_argument("--lang", help="Override language from task frontmatter.")
    parser.add_argument(
        "--project-root",
        default=".",
        help="Project root used to resolve the spec folder for handoff artifacts.",
    )
    return parser


def main() -> int:
    parser = build_arg_parser()
    args = parser.parse_args()

    try:
        result = prepare_handoff(
            args.task,
            language=args.lang,
            project_root=args.project_root,
        )
    except TddHandoffError as exc:
        print(json.dumps({"error": {"code": exc.code, "message": str(exc)}}, indent=2))
        return 1

    print(result.to_json())
    return 0


if __name__ == "__main__":
    sys.exit(main())

plugins

CHANGELOG.md

context7.json

CONTRIBUTING.md

README_CN.md

README_ES.md

README_IT.md

README.md

tessl.json

tile.json