Skip to content

Latest commit

 

History

History
1054 lines (736 loc) · 17.4 KB

File metadata and controls

1054 lines (736 loc) · 17.4 KB

Tak — dokładnie tak bym to docelowo widział: Intract jako linter/validator kontraktów intencji uruchamiany przed commitem, a później jako jeden z validatorów w vallm.

Czyli nie tylko:

intract validate .

ale też:

intract check --staged

albo docelowo:

vallm intract --staged
vallm batch src --enable-intract

W przesłanym opisie vallm już ma dobrą bazę pod takie wdrożenie: istnieje CLI vallm, batch validation, validator pipeline, BaseValidator, scoring pipeline, cache walidacji plików, validatorzy syntax/imports/security/semantic oraz pyqual.yaml z quality gates i narzędziami vallm_src / vallm_verify.


1. Docelowa rola Intract w vallm

vallm powinien walidować jakość kodu wygenerowanego przez LLM:

syntax
imports
lint
complexity
security
regression
semantic
intract contracts

A Intract powinien być warstwą:

czy kod realizuje zadeklarowaną intencję?
czy zmieniony kod nie złamał kontraktu?
czy wymagane pod-intencje istnieją?
czy zmieniony fragment nie łamie forbid:network / forbid:write / forbid:db?
czy projekt zachowuje spójność intent.yaml?

Czyli Intract w vallm powinien działać jak:

linter kontraktów intencji

a nie jako osobny eksperyment.


2. Tryby działania

Tryb 1 — staged / pre-commit

Najważniejszy tryb.

vallm intract --staged

albo:

intract check --staged

Działa tylko na plikach z:

git diff --cached --name-only --diff-filter=ACMR

Czyli przed commitem sprawdza tylko to, co realnie idzie do commita.

Waliduje:

1. zmienione pliki,
2. zmienione funkcje,
3. zmienione kontrakty @intract.v1,
4. zmiany w intent.yaml,
5. naruszenia forbid,
6. brak wymaganych require,
7. minimalne pokrycie kontraktami dla zmienionych fragmentów.

Tryb 2 — changed / branch diff

Do pracy na branchu:

vallm intract --changed --base main

Sprawdza:

git diff --name-only main...HEAD

Dobre do CI na pull request.

Tryb 3 — folder/project

Do pełnej walidacji:

vallm intract src --recursive

albo:

intract validate .

Sprawdza cały projekt, graf intencji, intent.yaml, pokrycie i naruszenia.

Tryb 4 — fragment/hunk

Najbardziej zaawansowany:

vallm intract --staged --hunks

Logika:

1. pobierz git diff --cached --unified=0,
2. znajdź zmienione zakresy linii,
3. znajdź kontrakt najbliższy zakresowi,
4. jeśli zmieniona linia należy do funkcji z kontraktem, waliduj całą funkcję,
5. jeśli zmieniono intent.yaml, waliduj cały graf projektu.

3. Reguła działania pre-commit

W pre-commit Intract powinien być szybki i przewidywalny.

Proponowana polityka:

intract:
  mode: staged
  fail_on:
    - violation
    - missing_required_p1
    - invalid_manifest
  warn_on:
    - partial
    - missing_contract
    - low_coverage
  require_contract_for:
    - changed_public_function
    - changed_security_code
    - changed_api_handler
  ignore:
    - tests/**
    - docs/**

Czyli commit blokujesz tylko wtedy, gdy:

1. kod łamie forbid,
2. zmieniono kontrakt i jest niepoprawny,
3. brakuje wymaganej intencji P1,
4. intent.yaml jest niespójny,
5. zmieniona funkcja krytyczna nie ma kontraktu.

Nie blokujesz od razu wszystkiego, bo na początku byłoby za dużo tarcia.


4. Architektura integracji z vallm

Etap A — Intract jako osobna paczka

Na start zostawić Intract jako niezależną paczkę:

[project.optional-dependencies]
intract = ["intract>=0.1.0"]

W vallm:

pip install vallm[intract]

Plus:

try:
    import intract
except ImportError:
    intract = None

To minimalizuje ryzyko.

Etap B — Intract jako validator vallm

Dodać plik:

src/vallm/validators/intract.py

Klasa:

from vallm.validators.base import BaseValidator
from vallm.scoring import ValidationResult, Issue, Severity


class IntractValidator(BaseValidator):
    name = "intract"
    tier = 2

    def validate(self, proposal, context):
        ...

W środku:

from intract.project import validate_sources

i mapowanie wyników Intract na wyniki vallm.

Etap C — rejestracja w pipeline

W src/vallm/scoring.py istnieje pipeline inicjalizacji validatorów i domyślne validatory. Tam trzeba dopiąć IntractValidator jako opcjonalny validator, tak jak obecne syntax/imports/security/semantic.

Przykładowo:

if settings.enable_intract:
    validators.append(IntractValidator(settings))

5. Nowe ustawienia w vallm

W src/vallm/config.py dodać:

VALLM_ENABLE_INTRACT: bool = False
VALLM_INTRACT_MANIFEST: str = "intent.yaml"
VALLM_INTRACT_MODE: str = "changed"
VALLM_INTRACT_FAIL_ON: str = "violation,missing_required_p1,invalid_manifest"
VALLM_INTRACT_MIN_CHANGED_COVERAGE: float = 0.0
VALLM_INTRACT_REQUIRE_CHANGED_CONTRACTS: bool = False
VALLM_INTRACT_ALLOW_MISSING_CONTRACTS: bool = True

W .env.example:

VALLM_ENABLE_INTRACT=false
VALLM_INTRACT_MANIFEST=intent.yaml
VALLM_INTRACT_MODE=changed
VALLM_INTRACT_FAIL_ON=violation,missing_required_p1,invalid_manifest
VALLM_INTRACT_MIN_CHANGED_COVERAGE=0
VALLM_INTRACT_REQUIRE_CHANGED_CONTRACTS=false

Na początku ENABLE_INTRACT=false, żeby nie rozwalić istniejącego flow.


6. CLI w vallm

Obecny vallm ma validate_command, check_command, batch_command, info_command, a batch obsługuje ścieżki, recursive, include/exclude, semantic/security/regression itd.

Dodałbym nowy command:

vallm intract .

Opcje:

vallm intract . --recursive
vallm intract . --manifest intent.yaml
vallm intract . --staged
vallm intract . --changed --base main
vallm intract . --format json
vallm intract . --fail-on violation
vallm intract . --show-coverage

Oraz rozszerzyłbym batch:

vallm batch src --enable-intract

Dla pre-commit:

vallm intract --staged --format text

7. Pre-commit hook

Dodać plik:

.pre-commit-hooks.yaml

Treść:

- id: vallm-intract
  name: vallm intract contracts
  entry: vallm intract --staged
  language: python
  pass_filenames: false
  stages: [pre-commit]

Przykład użycia w projekcie:

repos:
  - repo: local
    hooks:
      - id: vallm-intract
        name: vallm intract contracts
        entry: vallm intract --staged
        language: system
        pass_filenames: false

Dlaczego pass_filenames: false?

Bo Intract powinien sam użyć:

git diff --cached --name-only
git diff --cached --unified=0

wtedy ma pełną kontrolę nad staged changes.


8. Algorytm staged validation

Krok 1 — pobierz zmienione pliki

git diff --cached --name-only --diff-filter=ACMR

Krok 2 — pobierz hunki

git diff --cached --unified=0 -- <file>

Krok 3 — zdecyduj zakres walidacji

Jeśli zmieniono intent.yaml:
  waliduj cały graf projektu.

Jeśli zmieniono plik z @intract:
  waliduj kontrakty w tym pliku.

Jeśli zmieniono funkcję z kontraktem:
  waliduj całą funkcję.

Jeśli zmieniono fragment bez kontraktu:
  sprawdź, czy dziedziczy kontrakt z file-level albo manifestu.

Jeśli plik jest nowy:
  sprawdź, czy powinien mieć kontrakt według polityki.

Krok 4 — wynik

Przykład:

INTRACT FAILED

Changed files: 3
Contracts checked: 5
Passed: 3
Partial: 1
Violations: 1

Violation:
src/auth/permissions.py:12
  validate.user_permission
  Declared forbid:network, but requests.get was detected.

Fix:
- remove network call, or
- change contract effect/forbid if network is intended

9. Jak mapować Intract na wynik vallm

vallm ma własne Issue, Severity, ValidationResult, PipelineResult w src/vallm/scoring.py.

Mapowanie:

Intract vallm
pass score 1.0
partial warning / medium
fail error
violation error / critical
unknown info / warning

Przykład adaptera:

def map_intract_result(result) -> Issue:
    if result.status == "violation":
        severity = Severity.ERROR
    elif result.status == "fail":
        severity = Severity.ERROR
    elif result.status == "partial":
        severity = Severity.WARNING
    else:
        severity = Severity.INFO

    return Issue(
        rule="intract.contract",
        message=f"{result.contract}: {result.status}",
        severity=severity,
        line=result.lines[0] if result.lines else None,
        filename=result.file_path,
    )

Score validatora:

score = passed / total

albo ostrzej:

if any(violation):
    score = 0.0
elif any(fail):
    score = 0.4
elif any(partial):
    score = 0.7
else:
    score = 1.0

10. Integracja z pyqual

W pyqual.yaml vallm już ma metrykę:

vallm_pass_min: 90

oraz custom tools vallm_src i vallm_verify, które uruchamiają vallm batch na src i weryfikację po fixach.

Dodałbym nową metrykę:

metrics:
  vallm_pass_min: 90
  intract_pass_min: 90
  intract_violations_max: 0
  intract_missing_p1_max: 0

I stage:

custom_tools:
  - name: intract_contracts
    binary: .venv/bin/vallm
    command: >-
      .venv/bin/vallm intract {workdir}/src
      --recursive
      --manifest {workdir}/intent.yaml
      --format toon
      --output ./project/intract
    output: ./project/intract/contracts.toon
    allow_failure: false

stages:
  - name: intract
    tool: intract_contracts
    optional: false
    timeout: 300

Albo w wersji przejściowej:

- name: intract
  run: .venv/bin/intract validate . --manifest intent.yaml --json > .pyqual/intract.json
  when: always

11. Integracja z istniejącym batch processor

vallm ma już BatchProcessor, który buduje listę plików, filtruje include/exclude, obsługuje gitignore, pokazuje progress i przetwarza pliki równolegle.

Nie pisałbym tego drugi raz.

Zamiast tego:

src/vallm/cli/batch_processor_impl.py

dodać:

enable_intract: bool = False
intract_manifest: str | None = None

i w _validate_single_file / validate_single_file dołączyć IntractValidator.

Ale uwaga: dla manifestu projektowego nie wystarczy pojedynczy plik, bo require wymaga grafu. Dlatego:

file-level validation     → w batch per file
project graph validation  → osobny krok po batch

Czyli batch powinien mieć dwa etapy:

1. validate every file
2. if enable_intract_project_graph:
     validate manifest + graph once

12. Dwie warstwy Intract w vallm

To jest ważne architektonicznie.

Warstwa A — File Contract Validator

Działa jak zwykły validator vallm:

Proposal(code, filename) → ValidationResult

Sprawdza:

@intract w danym pliku
forbid
input/output
return
lokalne kontrakty

Plik:

src/vallm/validators/intract.py

Warstwa B — Project Contract Validator

Działa na całym repo:

Project root + intent.yaml + changed files → ProjectReport

Sprawdza:

require
graf intencji
coverage
missing P1
duplikaty intencji
zmiany staged

Plik:

src/vallm/core/intract_project.py

albo:

src/vallm/validators/intract_project.py

Nie mieszać tych dwóch w jednej klasie.


13. Zmienione fragmenty, nie tylko pliki

Docelowo warto dodać:

src/vallm/core/git_diff.py

Funkcje:

def get_staged_files() -> list[Path]:
    ...

def get_changed_files(base: str = "main") -> list[Path]:
    ...

def get_staged_hunks(file: Path) -> list[ChangedHunk]:
    ...

def changed_contracts_in_file(file: Path, hunks: list[ChangedHunk]) -> list[Contract]:
    ...

def touched_contract_scope(file: Path, hunk: ChangedHunk) -> Scope:
    ...

Zasada:

Jeśli zmiana dotyka funkcji, waliduj funkcję.
Jeśli zmiana dotyka kontraktu, waliduj kontrakt.
Jeśli zmiana dotyka intent.yaml, waliduj projekt.
Jeśli zmiana dotyka importów/efektów, sprawdź forbid.

To sprawi, że Intract będzie szybki jak linter.


14. Fail policy

Dodać plik:

intract.toml

albo sekcję w pyproject.toml:

[tool.intract]
manifest = "intent.yaml"
mode = "staged"
min_changed_coverage = 0
require_contracts_for_public_functions = false

fail_on = [
  "violation",
  "invalid_manifest",
  "missing_required_p1"
]

warn_on = [
  "partial",
  "missing_contract",
  "unknown"
]

ignore = [
  "tests/**",
  "docs/**",
  "examples/**"
]

Dla vallm:

[tool.vallm.intract]
enabled = true
manifest = "intent.yaml"
mode = "staged"
fail_on = ["violation", "missing_required_p1"]

15. Komendy docelowe

Intract standalone

intract scan .
intract validate .
intract validate . --manifest intent.yaml
intract check --staged
intract check --changed --base main
intract coverage .
intract graph . --format mermaid
intract duplicates .

Vallm integration

vallm intract --staged
vallm intract . --recursive --manifest intent.yaml
vallm batch src --enable-intract
vallm check --enable-intract

Pre-commit

pre-commit run vallm-intract

CI

vallm intract --changed --base origin/main --format json

16. Etapy wdrożenia do vallm

Etap 1 — Intract jako osobna paczka

Do pyproject.toml vallm:

[project.optional-dependencies]
intract = ["intract>=0.1.0"]

Do dokumentacji:

pip install -e ".[intract]"

Etap 2 — wrapper CLI w vallm

Dodać:

src/vallm/cli/intract_command.py

Komenda:

vallm intract .

Na początku może tylko wywoływać API Intract.

Etap 3 — validator plikowy

Dodać:

src/vallm/validators/intract.py

i opcję:

vallm validate --enable-intract

Etap 4 — batch integration

Dodać:

vallm batch src --enable-intract

do istniejącego batch command, który już obsługuje ścieżki, recursive, include/exclude, format i fail-fast.

Etap 5 — staged/pre-commit

Dodać:

vallm intract --staged

oraz .pre-commit-hooks.yaml.

Etap 6 — project graph

Dodać walidację:

vallm intract . --project-graph

z intent.yaml.

Etap 7 — pyqual gate

Dodać stage intract do pyqual.yaml.

Etap 8 — MCP

vallm ma MCP tools dla validate_syntax, validate_imports, validate_security i validate_code.

Dodać narzędzia:

validate_intent_contracts
validate_intract_project
validate_intract_staged

17. Proponowany układ plików w vallm

src/vallm/
  validators/
    intract.py

  core/
    intract_adapter.py
    intract_project.py
    git_diff.py

  cli/
    intract_command.py
    command_handlers.py

  reporters/
    intract_reporter.py

tests/
  test_intract_validator.py
  test_intract_cli.py
  test_intract_staged.py
  test_intract_manifest.py

.pre-commit-hooks.yaml

Jeśli nie chcesz tworzyć nowych katalogów, minimalny MVP:

src/vallm/validators/intract.py
src/vallm/cli/command_handlers.py
src/vallm/config.py
tests/test_intract_validator.py

18. Najważniejsza zasada wdrożenia

Nie robić z Intract od razu „twardego wymogu” dla całego projektu.

Najpierw:

warn-only

Potem:

fail only on violation

Potem:

fail on missing required P1

Dopiero na końcu:

coverage gates

Czyli kolejność:

1. ostrzegaj,
2. blokuj naruszenia,
3. blokuj brak P1,
4. wymagaj pokrycia kontraktami.

19. Przykładowy pre-commit output

INTRACT CONTRACT CHECK

Mode: staged
Manifest: intent.yaml

Changed files:
- src/auth/permissions.py
- src/api/users.py

Checked contracts: 4

PASS
  src/auth/permissions.py:12 validate.user_permission

PARTIAL
  src/api/users.py:44 expose.user_api
  missing: require:validate.user_input

VIOLATION
  src/auth/permissions.py:12 validate.user_permission
  forbid:network violated by requests.get(...)

Result: FAILED

Commit nie przechodzi, bo jest VIOLATION.


20. Co Intract wniesie do vallm

Dzisiaj vallm odpowiada głównie na pytanie:

czy kod jest poprawny składniowo, importowo, jakościowo, bezpieczeństwa, semantycznie?

Intract doda pytanie:

czy kod realizuje zadeklarowaną intencję?

To jest bardzo dobre uzupełnienie vallm, bo walidacja LLM-generated code nie powinna kończyć się na składni i lintingu. Kod może być poprawny technicznie, ale robić nie to, co miał robić. Intract jest warstwą, która formalizuje „co miało być zrobione”.


21. Najbliższy praktyczny plan

Sprint 1

Dodać do Intract:

check --staged
check --changed --base main

Sprint 2

Dodać do vallm:

src/vallm/validators/intract.py
--enable-intract

Sprint 3

Dodać:

vallm intract --staged
.pre-commit-hooks.yaml

Sprint 4

Dodać:

intent.yaml graph validation
missing P1 gates

Sprint 5

Dodać do pyqual.yaml:

intract_pass_min
intract_violations_max

Sprint 6

Dodać MCP tools i raporty JSON/TOON/SARIF.


22. Finalna rekomendacja

Tak — Intract powinien działać jak pre-commit linter kontraktów intencji, a w vallm powinien być wdrożony jako:

1. osobny CLI command: vallm intract,
2. opcjonalny validator: --enable-intract,
3. stage w pyqual,
4. pre-commit hook,
5. project graph validator dla intent.yaml,
6. później MCP tool.

To dobrze pasuje do architektury vallm, bo projekt już ma batch validation, validator base, scoring pipeline, CLI, pyqual quality gates i MCP tools.