todo2code

todo2code

MCP server that extracts and links code, tasks, documentation, and git history into a graph, then diagnoses discrepancies and generates reports.

Category
Visit Server

README

todo2code (t2c)

todo2code buduje wspólny Intent Evidence DSL z poleceń, historii Git, aktualnego kodu, list zadań, changelogu i dokumentacji. Następnie łączy rekordy w graf przepływu wiedzy, wykrywa rozbieżności i generuje raport dla zespołu.

Projekt działa na Node.js/TypeScript. Wielojęzykowe fakty kodu dostarczają adaptery TypeScript/JavaScript, Python (ast), Go (go/ast), Java (JDK Compiler Tree API) i Rust (syn). Toolchainy poza Node są opcjonalne — brak narzędzia daje jawne ostrzeżenie tylko wtedy, gdy repo zawiera pasujące źródła. Integracje są dostępne przez CLI, MCP/stdio i A2A v1.0/JSON-RPC.

Stan projektu

Wersja 0.4.0 ma działającą ścieżkę źródła → kanoniczny DSL → graf → diagnostyka/Intent vs Reality → raport. Kontrakty t2c.conclusion/v1 i t2c.todo-proposal/v1 wraz z walidacją cytowań i provenance są wdrożone, a API biblioteki potrafi je syntetyzować z grafu i diagnostyki przez OpenRouter. Integracja DSL2TODO nie jest jeszcze kompletna: obecna lista następnych działań w raporcie pozostaje projekcją diagnostyki, a CLI/SDK i zatwierdzalny TODO.patch są kolejnymi punktami P0. API syntezy waliduje już zależności, priorytety, kryteria i klasyfikuje duplikaty względem istniejącego TODO.

Aktualna macierz komponentów, wyniki walidacji, znane ograniczenia i projekt docelowego DSL2TODO znajdują się w docs/PROJECT_STATUS.md. Priorytety implementacyjne są utrzymywane w TODO.md.

Komunikację zespołu można zapisywać append-only w project/<ticket>/. Konwerter zachowuje uczestnika i rolę human|agent, a t2c communication porównuje wypowiedzi z dowodami Git/AST osobno dla każdego uczestnika. Kontrakt plików i gotowe polecenia opisuje docs/TEAM_COMMUNICATION.md.

Praktyczny przebieg CLI — od instalacji przez tryb offline/LLM po diff, Intent vs Reality, komunikację i automatyczną kontrolę wszystkich przykładów — opisuje docs/CLI_GUIDE.md.

Reality vs Intent

reality.svg

GUI

history-ui.png

Granica LLM

Etap Mechanizm LLM
NL → DSL OpenRouter structured output; jawny fallback heurystyczny/TensorFlow tak, domyślnie preferowany
10 commitów Git → DSL git log, diff, heurystyki symboli nie
TypeScript/JavaScript/Python/Go/Java/Rust AST → DSL natywne parsery języków; Java Tree API, Rust syn nie
TODO + CHANGELOG → DSL deterministyczna struktura + audytowane wzbogacanie OpenRouter tak, domyślnie preferowany
Dokumentacja → DSL OpenRouter structured outputs tak
project/<ticket>/ komunikacja → DSL deterministyczny kontrakt uczestnika, roli i typu wypowiedzi nie
Linkowanie i diagnostyka deterministyczny graf relacji nie
Graf DSL → raport NL OpenRouter; wejściem jest tylko graf i diagnostyka tak

Moduły deterministyczne nie importują klienta OpenRouter. Sprawdzają to npm run verify:no-llm oraz bezcykliczny graf modułów npm run verify:modules. Kompletność i brak duplikatów zmiennych sprawdza npm run verify:env.

Szybki start

Wymagania: Node.js 20+ i Git. Opcjonalne adaptery wymagają odpowiednio Python 3.10+, Go, JDK 17+ lub Cargo/Rust.

cp .env.example .env
npm install
npm run build
node dist/src/cli.js doctor

Zwykłe npm install i make install instalują wyłącznie rdzeń, dla którego audyt z 2026-07-29 ma 0 podatności. make install-tf instaluje @tensorflow/tfjs-node@4.22.0 w odizolowanym adapters/tensorflow/node_modules; jego 8 zgłoszeń nie trafia do drzewa zależności rdzenia. Nie należy stosować npm audit fix --force, ponieważ proponuje niekompatybilny downgrade.

Demonstracja działania 0.4.0

Poniższa demonstracja używa wersjonowanego repozytorium examples/, nie wymaga klucza ani połączenia z OpenRouter i pozostawia jednoznaczny audyt. Uruchom:

make demo

Polecenie wykonuje kolejno NL → DSL, Git → DSL, AST → DSL, osobne konwertery TODO/CHANGELOG, linker, diagnostykę i deterministyczne podsumowanie. Następnie analizuje komunikację examples/project/DEMO-101 osobno dla ludzi i agentów. Wyniki trafiają do examples/.intent-demo/runs/<run-id>/ oraz examples/.intent-communication/. Stan ostatniego runu można wyświetlić bez dodatkowych narzędzi:

node --input-type=module <<'NODE'
import { readFile } from 'node:fs/promises';

const latest = JSON.parse(await readFile('examples/.intent-demo/latest.json', 'utf8'));
const manifest = JSON.parse(await readFile(`examples/${latest.runDirectory}/manifest.json`, 'utf8'));
const graph = JSON.parse(await readFile(`examples/${manifest.files.graph}`, 'utf8'));
const stages = Object.fromEntries(Object.entries(manifest.stages).map(([name, stage]) => [name, {
  status: stage.status,
  effectiveMode: stage.effectiveMode,
  reason: stage.reason?.code ?? null,
  runtimeVersion: stage.runtimeVersion,
}]));
console.log({ status: manifest.status, runtime: manifest.runtime, stages });
console.log({ records: graph.records.length, relations: graph.relations.length, bySource: graph.stats.bySource });
NODE

Weryfikowany wynik dla 0.4.0 ma 202 rekordy. Liczba relacji zależy również od ostatnich 10 commitów Git, dlatego po każdym commicie może się prawidłowo zmienić i należy odczytać ją z bieżącego grafu:

status: succeeded, runtime: todo2code 0.4.0
naturalLanguageExtraction: succeeded / deterministic
markdownExtraction:        succeeded / deterministic
documentationExtraction:   skipped / none
summary:                   skipped / deterministic / LLM_DISABLED
records: 202, relations: <zależne od ostatnich 10 commitów>
bySource: ast=180, changelog=2, git=10, nl=7, todo=3

Demo jawnie wyłącza LLM dokumentacji i podsumowania, więc nie korzysta z prywatnego .env, sieci ani fallbacku. Każdy audyt zawiera runtimeVersion, requested/effective mode, model, czas, licznik rekordów/ostrzeżeń, powód i bezpieczne parametry; apiKey nigdy nie jest zapisywany.

A2A, SDK i UI

Uruchom backend:

npm run a2a

Następnie otwórz http://localhost:8787/ui. Widok pobierze historię z GET /api/runs, domyślnie wybierze dwa ostatnie kompletne runy i pokaże ich diff SVG. Stan serwera można sprawdzić przez:

curl -fsS http://localhost:8787/healthz
# {"status":"ok","service":"todo2code","protocol":"A2A","version":"1.0"}

Ten sam runtime jest dostępny przez SDK. Przykład TypeScript wykonuje deterministyczne NL → DSL i sprawdza audyt, zamiast zakładać, że LLM zadziałał:

import { Todo2CodeClient } from 'todo2code/sdk';

const client = new Todo2CodeClient({ baseUrl: 'http://localhost:8787' });
const result = await client.extractNl('TASK.md', '.', 'deterministic');

console.log(result.records.length);                 // 10 dla bieżącego TASK.md
console.log(result.audit?.status);                  // succeeded
console.log(result.audit?.effectiveMode);           // deterministic
console.log(result.audit?.runtimeVersion);          // 0.4.0
console.log(result.audit?.configuration);           // bez apiKey

Odpowiedniki extractNl/extractDocs są dostępne również w Pythonie, Go, Ruście i PHP; kompletne uruchamialne przykłady znajdują się w sdk/*/examples/.

Widoczna awaria LLM

require-llm nigdy nie przechodzi po cichu na parser deterministyczny. Ten kontrolowany test kończy się kodem procesu 1:

OPENROUTER_API_KEY= T2C_NL_MODE=require-llm \
node dist/src/cli.js pipeline examples \
  --task task.md --todo TODO.md --changelog CHANGELOG.md \
  --no-docs-llm --out .intent-failure-demo

Mimo błędu powstaje examples/.intent-failure-demo/runs/<run-id>/manifest.json:

{
  "status": "failed",
  "failure": {
    "stage": "naturalLanguageExtraction",
    "code": "LLM_NOT_CONFIGURED",
    "message": "OPENROUTER_API_KEY is not configured"
  },
  "graphFingerprint": null,
  "files": {}
}

Manifest zachowuje pełny audyt nieudanego etapu i wersję runtime, ale nie publikuje nieistniejącego grafu ani nie zmienia latest.json. Przy błędnym ID modelu kod LLM_INVALID_MODEL zawiera dodatkowo aktualną, posortowaną listę ID z endpointu OpenRouter /models.

Pełny pipeline bez połączeń LLM (również wtedy, gdy lokalny .env zawiera klucz):

node dist/src/cli.js pipeline examples \
  --task task.md \
  --todo TODO.md \
  --changelog CHANGELOG.md \
  --docs 'docs/**/*.md' \
  --nl-mode deterministic \
  --markdown-mode deterministic \
  --no-docs-llm \
  --no-summary-llm \
  --out .intent-demo

Pełny pipeline z OpenRouter:

# w .env:
# OPENROUTER_API_KEY=...
# T2C_NL_MODE=prefer-llm
# T2C_MARKDOWN_MODE=prefer-llm
# OPENROUTER_NL_MODEL=qwen/qwen3.7-plus
# OPENROUTER_MARKDOWN_MODEL=qwen/qwen3.7-plus
# OPENROUTER_DOC_MODEL=openrouter/auto-beta
# OPENROUTER_SUMMARY_MODEL=openrouter/auto-beta
# OPENROUTER_TASK_MODEL=qwen/qwen3.7-plus

node dist/src/cli.js pipeline /ścieżka/do/repo \
  --task project/ticket-014/README.md \
  --todo TODO.md \
  --changelog CHANGELOG.md \
  --docs 'README.md,docs/**/*.md,project/**/*.md'

Tryb ciągły skanuje repozytorium deterministycznie i generuje raport najwyżej raz na wskazany interwał:

node dist/src/cli.js watch . \
  --interval 60 \
  --scan-interval 2 \
  --no-docs-llm \
  --out .intent

Watcher scala reguły z .gitignore, .dockerignore i .intentignore, pomija symlinki oraz po raporcie odświeża snapshot, więc własne artefakty nie tworzą pętli. t2c init instaluje bazowy .intentignore; --no-initial-report pozwala czekać na pierwszą rzeczywistą zmianę.

CLI

t2c init [root]
t2c doctor

t2c extract nl <file> [--root .] [--out nl.intent.jsonl]
t2c extract git [--root .] [--count 10] [--out git.intent.jsonl]
t2c extract ast [root] [--out ast.intent.jsonl]
t2c extract markdown [--todo TODO.md] [--changelog CHANGELOG.md] [--markdown-mode deterministic|prefer-llm|require-llm]
t2c extract docs [--patterns 'README.md,docs/**/*.md']

t2c link <*.intent.jsonl>... --out intent.graph.json
t2c diagnose intent.graph.json --out diagnostics.json
t2c diff before.graph.json after.graph.json --out graph.diff.json --svg graph.diff.svg
t2c diff --mode files before.ts after.ts --svg files.diff.svg --html files.diff.html
t2c diff --mode git . --rev HEAD --svg worktree.diff.svg
t2c reality intent.graph.json --diagnostics diagnostics.json --svg reality.svg --md reality.md
t2c summarize intent.graph.json --diagnostics diagnostics.json --out team-summary.md
t2c watch [root] [--interval 60] [--scan-interval 2] [--no-initial-report]
t2c compare-workspace [root] [--base origin/main] [--task TASK.md] [--docs-llm]
t2c pipeline [root] --task TASK.md --todo TODO.md --changelog CHANGELOG.md
t2c mcp
t2c a2a

extract nl, extract markdown, extract docs i summarize mogą korzystać z OpenRouter. Dla NL oraz Markdown prefer-llm jest trybem domyślnym: awaria daje oznaczony fallback; require-llm kończy operację błędem, a deterministic świadomie pomija sieć. W Markdown LLM nie może zmienić checkboxa, lifecycle, wersji, daty, kategorii ani provenance — wzbogaca wyłącznie semantykę wpisu. Dokumentacja bez klucza jest pomijana, a raport może użyć oznaczonego fallbacku. Etap dokumentacji ma osobne limity fragmentu, liczby fragmentów, rekordów, współbieżności i timeoutu (T2C_DOC_*). Najpierw analizuje fragmenty pasujące do ścieżek, symboli, ticketów i wersji wykrytych w pozostałych źródłach; obcięcie budżetu zapisuje ostrzeżenie DOC_CHUNK_BUDGET.

Origin vs bieżący workspace

Porównanie nie wykonuje checkoutu w katalogu użytkownika. Runtime rozwiązuje bazę do pełnego SHA, tworzy prywatny tymczasowy Git worktree i uruchamia ten sam TypeScript pipeline na bazie oraz aktualnym filesystemie:

node dist/src/cli.js compare-workspace . --base origin/main --out .intent

Stan workspace obejmuje lokalne commity, indeks, zmiany unstaged i pliki untracked. Wynik t2c.workspace-comparison/v1 zawiera ahead/behind, listę zmienionych plików, diff rekordów i relacji oraz zmianę metryk Intent vs Reality: pełne alignmentRate, pokrycie deklarowanej intencji implementacją, udział kodu posiadającego plan i dokumentację, gaps oraz liczniki diagnostyk. Trend może być improved, regressed, mixed albo unchanged. Artefakty trafiają do:

.intent/comparisons/<comparison-id>/
├── comparison.json
├── trend.md
├── intent-diff.svg
├── base.graph.json
├── workspace.graph.json
├── base-reality.md
├── workspace-reality.md
└── workspace-reality.svg

Narracyjne podsumowania obu przebiegów są zawsze deterministyczne i nie wykonują zbędnych zapytań LLM. Dokumentacja LLM po obu stronach jest opcjonalna, ponieważ podwaja liczbę zapytań i może wprowadzać niedeterministyczny szum. Jeśli podano --task, ekstrakcja NL respektuje T2C_NL_MODE i jest osobno audytowana:

t2c compare-workspace . --base origin/main --docs-llm \
  --docs 'README.md,docs/**/*.md,.intent/runs/<run-id>/team-summary.md' \
  --doc-excludes 'node_modules/**,.git/**,dist/**,TODO.md,CHANGELOG.md'

Usunięcie .intent/** z --doc-excludes jest wymagane tylko dla jawnie wskazanego historycznego raportu. Nie należy używać szerokiego .intent/**/*.md, bo bieżące raporty zaczęłyby zasilać kolejne runy.

Tryb obserwowania

t2c watch pilnuje lokalnych zmian i generuje świeży raport najwyżej raz na minutę:

node dist/src/cli.js watch . --task TASK.md --no-docs-llm

Obowiązują dwa niezależne czasy:

Opcja Domyślnie Znaczenie
--scan-interval 2 s jak szybko zmiana zostaje zauważona
--interval 60 s minimalny odstęp między dwoma raportami

Zmiany napływające częściej niż --interval są kumulowane, a nie kolejkowane: po upływie progu powstaje jeden raport obejmujący wszystko, co się zmieniło. Raport nigdy nie startuje, gdy poprzedni jeszcze trwa, więc wolny pipeline nie tworzy nakładających się runów. --no-initial-report pomija raport startowy i czeka na pierwszą realną zmianę.

Detekcja opiera się na cyklicznym skanowaniu (rozmiar + mtime), a nie na fs.watch, który zależy od platformy i gubi zdarzenia pod obciążeniem. Skan jest tani, bo katalogi wykluczone są odcinane przed odczytem — node_modules nigdy nie jest czytane.

Pliki ignorowane

Watch pomija ścieżki wymienione w trzech plikach, czytanych w tej kolejności:

  1. .gitignore
  2. .dockerignore
  3. .intentignore

Późniejszy plik wygrywa, więc .intentignore może przywrócić ścieżkę przez !wzorzec.

.intentignore jest zakładany przez t2c init i wyklucza m.in. wszystkie katalogi kropkowe (.*/.git, .idea, .venv, .github, .cache), katalog .intent/ z własnymi raportami, wyjścia buildu (node_modules/, dist/, target/, __pycache__/), lockfile'e oraz logi i pliki tymczasowe.

Składnia jest zgodna z gitignore: komentarze #, negacja !, końcowy / ogranicza regułę do katalogów, wzorzec bez ukośnika dopasowuje się na dowolnej głębokości, a ** przechodzi przez katalogi. Reguły .dockerignore są interpretowane tą samą semantyką, czyli nieco szerzej niż robi to Docker (kotwiczący wzorce do korzenia kontekstu) — wpisy w tym pliku nazywają wyjścia buildu, więc wykluczenie zagnieżdżonej kopii jest zamierzone.

Artefakty runu

.intent/
├── latest.json
└── runs/<run-id>/
    ├── nl.intent.jsonl
    ├── git.intent.jsonl
    ├── ast.intent.jsonl
    ├── todo.intent.jsonl
    ├── changelog.intent.jsonl
    ├── document.intent.jsonl
    ├── intent.graph.json
    ├── diagnostics.json
    ├── team-summary.md
    └── manifest.json

Każdy rekord zawiera identyfikator, statement, lifecycle, dokładne źródło, hash treści, klasę epistemiczną, confidence i podstawy wnioskowania. Fakty AST mają confidence 1.0. Rekordy wygenerowane przez LLM są oznaczone jako llm_inference i mają pułap zależny od struktury źródła: 0.94 dla wzbogaconych pozycji TODO/CHANGELOG, 0.90 dla prozy NL i 0.85 dla dokumentacji. Żaden z nich nie sięga poziomu obserwacji deterministycznej — pełną tabelę zawiera docs/DSL.md.

manifest.json zapisuje również runtime.version, bezpieczny snapshot i fingerprint konfiguracji oraz statusy naturalLanguageExtraction, markdownExtraction, documentationExtraction i summary. Status runu degraded jest pokazywany w CLI, GET /api/runs i UI. Parametry obejmują modele, timeout, temperaturę, limit tokenów, budżet dokumentów, konfigurację adapterów i tryb structured output; klucz API nigdy nie jest zapisywany. Odpowiedzi LLM zapisują zwrócone przez provider responseId, resolved model/provider oraz usage/cost. Każdy audyt ekstrakcji zawiera też wersję runtime i bezpieczne parametry. Każda awaria pipeline po utworzeniu runu tworzy manifest status=failed z kodem i etapem, ale bez nieistniejącego grafu ani aktualizacji latest.json.

MCP

Uruchomienie serwera stdio:

node dist/src/interfaces/mcp.js

Przykładowa konfiguracja hosta MCP:

{
  "mcpServers": {
    "todo2code": {
      "command": "node",
      "args": ["/absolute/path/todo2code/dist/src/interfaces/mcp.js"],
      "env": {
        "T2C_ROOT": "/absolute/path/workspace",
        "OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}"
      }
    }
  }
}

Dostępne narzędzia: extract_nl, extract_git, extract_ast, extract_markdown, extract_docs, extract_communication, analyze_communication, link, diagnose, diff, diff_files, diff_git, reality, compare_workspace, summarize, pipeline. Serwer udostępnia też zasoby t2c://latest/*.

Diff DSL, SVG i SDK

Porównanie dwóch grafów zwraca kanoniczny t2c.diff/v1 z rekordami added, removed, changed i liczbą elementów bez zmian. --mode files tworzy deterministyczny diff linii t2c.filediff/v1, a --mode git stosuje ten sam silnik do rewizji, indeksu lub drzewa roboczego. Dostępne są widoki SVG, HTML oraz unified diff; nie wymagają bibliotek renderujących i nie wykonują treści pochodzącej z plików.

Polecenie t2c reality projektuje pojedynczy graf do t2c.reality/v1: zestawia deklaracje z taska, TODO i dokumentacji z faktami Git/AST, a rozbieżności pokazuje jako SVG albo tabelę Markdown.

Po uruchomieniu A2A dostępne są:

  • frontend: http://localhost:8787/ui — pobiera historię z .intent/runs, domyślnie wybiera dwa najnowsze kompletne runy i automatycznie pokazuje ich diff SVG;
  • historia runów: GET http://localhost:8787/api/runs;
  • REST diff: POST http://localhost:8787/api/diff;
  • A2A/MCP action: diff.

POST /api/diff domyślnie zwraca pełny t2c.diff/v1. Ustawienie compact: true zwraca projekcję przeznaczoną dla UI: fingerprinty, liczniki summary i opcjonalny SVG, bez pełnych tablic rekordów oraz relacji.

SDK TypeScript/JavaScript:

import { Todo2CodeClient } from 'todo2code/sdk';

const client = new Todo2CodeClient({ baseUrl: 'http://localhost:8787' });
const result = await client.diffGraphs(beforeGraph, afterGraph);
console.log(result.diff.summary, result.svg);

const files = await client.diffTextFiles('before.ts', 'after.ts', { includeHtml: true });
const reality = await client.reality(afterGraph);
const comparison = await client.compareWorkspace({ root: '.', base: 'origin/main' });

SDK Python nie ma zewnętrznych zależności:

from sdk.python import Todo2CodeClient

client = Todo2CodeClient("http://localhost:8787")
result = client.diff_graphs(before_graph, after_graph)
print(result["diff"]["summary"])

files = client.diff_text_files("before.ts", "after.ts", include_html=True)
reality = client.reality(after_graph)
comparison = client.compare_workspace(root=".", base="origin/main")

Można go także zainstalować przez python3 -m pip install ./sdk/python i importować jako todo2code_sdk.

Uruchamialne przykłady znajdują się w examples/sdk/typescript.mjs i examples/sdk/python.py.

Pomiary oraz bezpieczne i semantycznie istotne dalsze optymalizacje opisuje docs/OPTIMIZATION.md.

SDK dla pięciu języków

Katalog sdk/ zawiera pełne klienty A2A v1.0 udostępniające wszystkie akcje runtime'u (nie tylko diff), wraz z typami Intent DSL:

Język Katalog Zależności Klasa
TypeScript / Node sdk/typescript/ brak T2CClient
Python 3.10+ sdk/python/ brak T2CClient
Go 1.21+ sdk/go/ brak todo2code.Client
Rust 1.70+ sdk/rust/ serde_json todo2code::Client
PHP 8.1+ sdk/php/ brak Todo2Code\Client

Każdy język ma uruchamialny przykład w sdk/<język>/examples/. Wszystkie przepuszczają ten sam zbiór rekordów przez link i muszą otrzymać identyczny fingerprint grafu — to test wierności round-tripu typów. Szczegóły: sdk/README.md.

Python udostępnia także lokalny TypeScriptRuntime. Nie kopiuje implementacji DSL do Pythona, tylko uruchamia przez Node.js skompilowany dist/src/cli.js:

make python-wheel
python3 -m pip install .intent-packages/python/todo2code_sdk-*.whl
T2C_TYPESCRIPT_CLI="$PWD/dist/src/cli.js" python3 sdk/python/examples/local_runtime.py

Most obsługuje pipeline, diagnose, graph diff oraz reality bez serwera A2A. Szczegóły i przykład API: sdk/python/README.md.

Przykładowe repozytoria

examples/backend (HTTP API bez zależności) i examples/frontend (panel DOM bez frameworka) to gotowe wejścia dla runtime'u DSL. Każde ma task.md, TODO.md, CHANGELOG.md, README.md i src/, i celowo zawiera rozbieżności plan↔kod, żeby t2c reality miał co pokazać:

node dist/src/cli.js pipeline examples/backend \
  --task task.md --todo TODO.md --changelog CHANGELOG.md \
  --docs 'README.md' --no-docs-llm --out .intent

node dist/src/cli.js reality examples/backend/.intent/runs/<run-id>/intent.graph.json \
  --diagnostics examples/backend/.intent/runs/<run-id>/diagnostics.json \
  --svg reality.svg --md reality.md

A2A v1.0

node dist/src/interfaces/a2a.js

Agent Card:

curl http://localhost:8787/.well-known/agent-card.json

Uruchomienie pipeline przez SendMessage:

curl -s http://localhost:8787/a2a \
  -H 'Content-Type: application/json' \
  -H 'A2A-Version: 1.0' \
  -d '{
    "jsonrpc":"2.0",
    "id":"req-1",
    "method":"SendMessage",
    "params":{
      "message":{
        "messageId":"msg-1",
        "role":"ROLE_USER",
        "parts":[{
          "data":{
            "action":"pipeline",
            "input":{
              "root":".",
              "task":"TASK.md",
              "includeDocsLlm":false
            }
          },
          "mediaType":"application/json"
        }]
      }
    }
  }'

Interfejs A2A jest v1-only: nagłówek A2A-Version: 1.0 (albo parametr zapytania o tej nazwie) jest wymagany. Brak nagłówka oznacza protokół 0.3 i jest odrzucany kodem -32009; aliasy metod v0.3 nie są przyjmowane. GetTask i CancelTask zwracają task bez wrappera, a ListTasks obsługuje filtry, cursor pagination, historyLength oraz includeArtifacts (domyślnie false).

Ustawienie T2C_A2A_TOKEN włącza Bearer authentication i izolację tasków według principalu. Domyślnie MCP i A2A nie mogą analizować ścieżek poza T2C_ROOT; wyjątek wymaga jawnego T2C_ALLOW_OUTSIDE_ROOT=true.

Domyślny task store A2A pozostaje pamięciowy. Aby zachować taski po restarcie i współdzielić je między replikami używającymi tego samego wolumenu, ustaw:

T2C_A2A_TASK_STORE=.intent/a2a-tasks.json

Snapshot jest zapisywany atomowo z uprawnieniami 0600. Blokada katalogowa chroni idempotency i aktualizacje między procesami; ścieżka podlega tym samym ograniczeniom T2C_ROOT co pozostałe operacje runtime'u.

OpenRouter

Runtime używa POST /api/v1/chat/completions. Ekstraktory NL i dokumentacji oraz synteza zadań proszą o response_format: json_schema, wymuszają provider.require_parameters, a przy braku wsparcia endpointu próbują kontrolowanego fallbacku json_object. Opcjonalny plugin response-healing jest sterowany przez .env. Osobny OPENROUTER_TASK_MODEL wybiera model dla graf + diagnostyka → zadania i domyślnie dziedziczy OPENROUTER_MODEL.

Klucz nie jest zapisywany do artefaktów, logów ani odpowiedzi MCP/A2A. doctor pokazuje jedynie status configured/not configured.

Do czasu dodania komendy propose-todo etap jest publicznym API TypeScript:

import { readFile } from 'node:fs/promises';
import { getConfig, synthesizeTodoProposals } from 'todo2code';

const graph = JSON.parse(await readFile('.intent/runs/<run>/intent.graph.json', 'utf8'));
const diagnostics = JSON.parse(await readFile('.intent/runs/<run>/diagnostics.json', 'utf8'));
const result = await synthesizeTodoProposals(graph, diagnostics, getConfig(), 'require-llm');
console.log(JSON.stringify(result, null, 2));

W prefer-llm awaria daje puste conclusions/proposals i osobne rawDiagnosticActions; nie są one oznaczane jako wynik semantycznej syntezy.

Opcjonalny TensorFlow

NL i Git zawsze mają deterministyczny klasyfikator słownikowy. Lokalny model TensorFlow można włączyć przez:

T2C_ENABLE_TF=true
T2C_TF_MODEL_PATH=/models/action/model.json
T2C_TF_MODULE_PATH=adapters/tensorflow/node_modules/@tensorflow/tfjs-node/dist/index.js
T2C_TF_LABELS=add,fix,remove,refactor,test,document,configure,analyze,unknown

Najpierw należy wykonać make install-tf. Obok model.json musi znajdować się vocabulary.json, czyli mapa token → indeks. Model powinien przyjmować tensor [1, vocabulary_size] i zwracać rozkład klas. Przy braku adaptera lub błędzie modelu runtime wraca do heurystyk i zapisuje heuristic_fallback:<powód>.

Docker i Makefile

make setup
make verify
make demo
make docker-build
make docker-up

Jedynym plikiem Compose jest docker-compose.yml. Montuje repozytorium T2C_WORKSPACE pod /workspace, wystawia kontenerowy port 8787 jako T2C_DOCKER_HOST_PORT i zachowuje .intent w analizowanym workspace. Przy zmianie portu hosta należy odpowiednio ustawić również publiczny T2C_A2A_PUBLIC_URL oraz kliencki T2C_A2A_URL.

Diagnostyka

Wbudowane klasy obejmują m.in.:

  • PLANNED_NOT_IMPLEMENTED;
  • IMPLEMENTED_NOT_PLANNED;
  • IMPLEMENTED_NOT_DOCUMENTED;
  • CHANGELOG_WITHOUT_IMPLEMENTATION;
  • CONFLICTING_INTENT;
  • AMBIGUOUS_REQUIREMENT;
  • UNLINKED_RECORD.

ALIGNED oznacza wyłącznie brak wykrytej blokującej rozbieżności w dostępnych źródłach. Nie nadaje automatycznie statusu DONE i nie zastępuje decyzji człowieka.

Dokumentacja projektu

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured