synap-git 2.4.0__tar.gz → 2.4.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {synap_git-2.4.0 → synap_git-2.4.1}/.gitignore +1 -1
- {synap_git-2.4.0 → synap_git-2.4.1}/CHANGELOG.md +8 -1
- {synap_git-2.4.0 → synap_git-2.4.1}/PKG-INFO +1 -1
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/__init__.py +1 -1
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/cli/checkpoint.py +16 -2
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/cli/lessons.py +59 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/cli/main.py +425 -22
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/cli/memory.py +57 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/git/state.py +25 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/indexer/daemon.py +11 -1
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/indexer/engine.py +182 -27
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/mcp/server.py +7 -1
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/parser/registry.py +148 -16
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/storage/sqlite.py +156 -55
- {synap_git-2.4.0 → synap_git-2.4.1}/.synap.example/README.md +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/LICENSE.md +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/README.md +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/pyproject.toml +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/api/__init__.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/api/app.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/api/static/index.html +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/cli/__init__.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/cli/__main__.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/cli/usage.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/cli/wiki.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/config.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/diagnostics/__init__.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/diagnostics/logger.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/diagnostics/tracing.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/embeddings/__init__.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/git/__init__.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/indexer/__init__.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/indexer/scanner.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/indexer/wiki.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/mcp/__init__.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/parser/__init__.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/provider/__init__.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/provider/anthropic.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/provider/base.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/provider/factory.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/provider/gemini.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/provider/ollama.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/provider/openai.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/provider/openrouter.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/py.typed +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/retrieval/__init__.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/retrieval/engine.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/retrieval/memory.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/security/__init__.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/security/redactor.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/security/sanitizer.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/security/validator.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/storage/__init__.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/utils/__init__.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/src/synap_git/utils/serialization.py +0 -0
- {synap_git-2.4.0 → synap_git-2.4.1}/website/README.md +0 -0
|
@@ -5,7 +5,14 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [2.4.
|
|
8
|
+
## [2.4.1] - 2026-09-11
|
|
9
|
+
|
|
10
|
+
### Security, Protocol & Architecture Hardening (Audit Remediation)
|
|
11
|
+
- **MCP Stdio Transport Isolation**: Added dedicated `synap mcp serve` command operating cleanly over stdio with zero logging pollution, error JSON-RPC handling, and clean SIGTERM/EOF exits.
|
|
12
|
+
- **Structural Graph & Position-Independent Symbols**: Added stable symbol IDs unaffected by blank lines or docstrings, extended cross-file AST imports to 11 Tree-sitter grammars (TS/JS, Go, Rust, Java, C++, Ruby, PHP, C#), and hardened recursive CTE cycle handling with deduplication.
|
|
13
|
+
- **Data Integrity & Memory**: Fixed Git revert detection via tree-delta comparisons, secured `synap rollback` against dirty working tree overwrites, and introduced persistent mid-repair backups (`.synap/repair_backup.json`).
|
|
14
|
+
- **CLI Commands**: Added `synap lessons list [--json]` and `synap memory decisions [--json]`, with clean empty JSON array returns on uninitialized databases.
|
|
15
|
+
- **Documentation & Website Parity**: Aligned documentation and landing page with exact 10 MCP tools, methodology-backed benchmarks, and comprehensive web architecture guides.
|
|
9
16
|
|
|
10
17
|
### Performance & Latency
|
|
11
18
|
- **MCP Search Sub-10ms Retrieval (780x Speedup)**: Optimized MCP `search` latency from 7,200ms to 9.2ms by replacing slow synchronous LLM router calls with deterministic sub-millisecond intent classification, caching vector deserialization in SQLite, and providing direct context grounding for AI coding agents.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: synap-git
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.1
|
|
4
4
|
Summary: Persistent structural context infrastructure for AI coding agents.
|
|
5
5
|
Project-URL: Homepage, https://github.com/saahilpal/synapse
|
|
6
6
|
Project-URL: Repository, https://github.com/saahilpal/synapse
|
|
@@ -19,15 +19,29 @@ app = typer.Typer(help="Checkpoint commands.", no_args_is_help=True)
|
|
|
19
19
|
|
|
20
20
|
@app.command("create")
|
|
21
21
|
def checkpoint_create(
|
|
22
|
-
path: Annotated[str, typer.Argument(help="Repository path.")] = ".",
|
|
23
22
|
doing: Annotated[
|
|
24
|
-
str,
|
|
23
|
+
str,
|
|
24
|
+
typer.Argument(
|
|
25
|
+
help="What the agent is currently doing / checkpoint description.",
|
|
26
|
+
show_default=True,
|
|
27
|
+
),
|
|
25
28
|
] = "Manual snapshot",
|
|
29
|
+
path: Annotated[
|
|
30
|
+
str,
|
|
31
|
+
typer.Option("--path", "-p", help="Repository path."),
|
|
32
|
+
] = ".",
|
|
26
33
|
files: Annotated[str, typer.Option(help="Comma-separated list of changed files.")] = "",
|
|
27
34
|
next_step: Annotated[str, typer.Option(help="The next step to be taken.")] = "",
|
|
28
35
|
blockers: Annotated[str, typer.Option(help="Current blockers or obstacles.")] = "",
|
|
29
36
|
) -> None:
|
|
30
37
|
"""Create a new context checkpoint."""
|
|
38
|
+
from pathlib import Path as FilePath
|
|
39
|
+
|
|
40
|
+
# Backward compatibility: if doing is an existing directory path and not a message
|
|
41
|
+
if path == "." and FilePath(doing).is_dir() and doing != "Manual snapshot":
|
|
42
|
+
path = doing
|
|
43
|
+
doing = "Manual snapshot"
|
|
44
|
+
|
|
31
45
|
runtime = SynapRuntime(_settings(path))
|
|
32
46
|
|
|
33
47
|
checkpoint_id = str(uuid.uuid4())
|
|
@@ -5,8 +5,11 @@ from typing import Annotated
|
|
|
5
5
|
import questionary
|
|
6
6
|
import typer
|
|
7
7
|
from rich.panel import Panel
|
|
8
|
+
from rich.table import Table
|
|
8
9
|
|
|
9
10
|
from synap_git.cli.main import (
|
|
11
|
+
JSON_OPTION,
|
|
12
|
+
_emit,
|
|
10
13
|
_settings,
|
|
11
14
|
console,
|
|
12
15
|
)
|
|
@@ -15,6 +18,62 @@ from synap_git.indexer.engine import SynapRuntime
|
|
|
15
18
|
app = typer.Typer(help="Lessons commands.", no_args_is_help=True)
|
|
16
19
|
|
|
17
20
|
|
|
21
|
+
@app.command("list")
|
|
22
|
+
def lessons_list(
|
|
23
|
+
path: Annotated[str, typer.Argument(help="Repository path.")] = ".",
|
|
24
|
+
status: Annotated[
|
|
25
|
+
str,
|
|
26
|
+
typer.Option(
|
|
27
|
+
"--status",
|
|
28
|
+
"-s",
|
|
29
|
+
help="Filter by status: pending, approved, rejected, or all.",
|
|
30
|
+
),
|
|
31
|
+
] = "all",
|
|
32
|
+
json_output: Annotated[bool, JSON_OPTION] = False,
|
|
33
|
+
) -> None:
|
|
34
|
+
"""List recorded architectural lessons."""
|
|
35
|
+
runtime = SynapRuntime(_settings(path, json_output=json_output))
|
|
36
|
+
lessons = runtime.store.get_lessons(status)
|
|
37
|
+
|
|
38
|
+
if json_output:
|
|
39
|
+
_emit({"lessons": lessons}, json_output=True)
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
if not lessons:
|
|
43
|
+
console.print(f"[yellow]No lessons found matching status '{status}'.[/yellow]")
|
|
44
|
+
return
|
|
45
|
+
|
|
46
|
+
table = Table(title=f"Synap Lessons ({status})", show_header=True, header_style="bold cyan")
|
|
47
|
+
table.add_column("Lesson ID", style="dim")
|
|
48
|
+
table.add_column("Status")
|
|
49
|
+
table.add_column("What Failed")
|
|
50
|
+
table.add_column("Why / Lesson")
|
|
51
|
+
table.add_column("Revert Commit", style="dim")
|
|
52
|
+
|
|
53
|
+
for item in lessons:
|
|
54
|
+
item_status = item.get("status", "unknown")
|
|
55
|
+
if item_status == "approved":
|
|
56
|
+
status_style = "[green]approved[/green]"
|
|
57
|
+
elif item_status == "pending":
|
|
58
|
+
status_style = "[yellow]pending[/yellow]"
|
|
59
|
+
elif item_status == "rejected":
|
|
60
|
+
status_style = "[red]rejected[/red]"
|
|
61
|
+
else:
|
|
62
|
+
status_style = item_status
|
|
63
|
+
|
|
64
|
+
table.add_row(
|
|
65
|
+
item.get("lesson_id", "")[:12] + "…",
|
|
66
|
+
status_style,
|
|
67
|
+
(item.get("what_failed") or "")[:40]
|
|
68
|
+
+ ("…" if len(item.get("what_failed") or "") > 40 else ""),
|
|
69
|
+
(item.get("why_failed") or "")[:45]
|
|
70
|
+
+ ("…" if len(item.get("why_failed") or "") > 45 else ""),
|
|
71
|
+
(item.get("revert_commit") or "")[:8],
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
console.print(table)
|
|
75
|
+
|
|
76
|
+
|
|
18
77
|
@app.command("approve")
|
|
19
78
|
def lessons_approve(
|
|
20
79
|
lesson_id: Annotated[str, typer.Argument(help="The ID of the lesson to approve.")],
|