draft-protocol 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,65 @@
1
+ """DRAFT Protocol — Intake Governance for AI Tool Calls.
2
+
3
+ Ensures AI understands human intent before execution begins.
4
+
5
+ Usage:
6
+ # As MCP server (primary use case):
7
+ pip install draft-protocol
8
+ python -m draft_protocol
9
+
10
+ # As library:
11
+ from draft_protocol.engine import classify_tier, map_dimensions, check_gate
12
+ from draft_protocol.storage import create_session, get_session
13
+ from draft_protocol.providers import llm_available, embed_available
14
+ """
15
+
16
+ __version__ = "0.1.0"
17
+
18
+ # Public API — importable from `draft_protocol` directly
19
+ from draft_protocol.engine import (
20
+ add_assumption,
21
+ check_gate,
22
+ classify_tier,
23
+ confirm_field,
24
+ elicitation_review,
25
+ generate_assumptions,
26
+ generate_elicitation,
27
+ map_dimensions,
28
+ override_gate,
29
+ unscreen_dimension,
30
+ verify_assumption,
31
+ )
32
+ from draft_protocol.providers import (
33
+ embed_available,
34
+ llm_available,
35
+ )
36
+ from draft_protocol.storage import (
37
+ close_session,
38
+ create_session,
39
+ get_active_session,
40
+ get_session,
41
+ )
42
+
43
+ __all__ = [
44
+ "__version__",
45
+ # Engine
46
+ "classify_tier",
47
+ "map_dimensions",
48
+ "generate_elicitation",
49
+ "generate_assumptions",
50
+ "check_gate",
51
+ "confirm_field",
52
+ "unscreen_dimension",
53
+ "add_assumption",
54
+ "override_gate",
55
+ "verify_assumption",
56
+ "elicitation_review",
57
+ # Storage
58
+ "create_session",
59
+ "get_session",
60
+ "get_active_session",
61
+ "close_session",
62
+ # Providers
63
+ "llm_available",
64
+ "embed_available",
65
+ ]
@@ -0,0 +1,61 @@
1
+ """Entry point: python -m draft_protocol
2
+
3
+ Supports multiple MCP transports:
4
+ stdio — Default. For Claude Desktop, Cursor, Windsurf, Continue.
5
+ sse — Server-Sent Events. For web-based MCP clients.
6
+ streamable-http — New MCP standard. For HTTP-native MCP clients.
7
+
8
+ Usage:
9
+ python -m draft_protocol # stdio (default)
10
+ python -m draft_protocol --transport sse # SSE on port 8420
11
+ python -m draft_protocol --transport streamable-http --port 8420
12
+ python -m draft_protocol --transport rest # REST API on port 8420
13
+
14
+ Environment variables (override CLI defaults):
15
+ DRAFT_TRANSPORT — stdio | sse | streamable-http
16
+ DRAFT_HOST — Bind address (default: 127.0.0.1)
17
+ DRAFT_PORT — Port for SSE/HTTP (default: 8420)
18
+ """
19
+ import argparse
20
+ import os
21
+
22
+ from draft_protocol.server import mcp
23
+
24
+
25
+ def main():
26
+ parser = argparse.ArgumentParser(
27
+ prog="draft-protocol",
28
+ description="DRAFT Protocol — Intake governance for AI tool calls.",
29
+ )
30
+ parser.add_argument(
31
+ "--transport", "-t",
32
+ choices=["stdio", "sse", "streamable-http", "rest"],
33
+ default=os.environ.get("DRAFT_TRANSPORT", "stdio"),
34
+ help="MCP transport protocol (default: stdio)",
35
+ )
36
+ parser.add_argument(
37
+ "--host",
38
+ default=os.environ.get("DRAFT_HOST", "127.0.0.1"),
39
+ help="Bind address for SSE/HTTP (default: 127.0.0.1)",
40
+ )
41
+ parser.add_argument(
42
+ "--port", "-p",
43
+ type=int,
44
+ default=int(os.environ.get("DRAFT_PORT", "8420")),
45
+ help="Port for SSE/HTTP (default: 8420)",
46
+ )
47
+ args = parser.parse_args()
48
+
49
+ if args.transport == "stdio":
50
+ mcp.run(transport="stdio")
51
+ elif args.transport == "sse":
52
+ mcp.run(transport="sse", host=args.host, port=args.port)
53
+ elif args.transport == "streamable-http":
54
+ mcp.run(transport="streamable-http", host=args.host, port=args.port)
55
+ elif args.transport == "rest":
56
+ from draft_protocol.rest import run_rest_server
57
+ run_rest_server(host=args.host, port=args.port)
58
+
59
+
60
+ if __name__ == "__main__":
61
+ main()
@@ -0,0 +1,112 @@
1
+ """DRAFT Protocol Configuration."""
2
+ import os
3
+ from pathlib import Path
4
+
5
+ # ── Storage ───────────────────────────────────────────────
6
+ DB_PATH = Path(os.environ.get("DRAFT_DB_PATH", "~/.draft_protocol/draft.db")).expanduser()
7
+ DB_PATH.parent.mkdir(parents=True, exist_ok=True)
8
+
9
+ # ── LLM Provider (optional — enhances classification accuracy) ──
10
+ # Supported: "none" (default), "ollama", "openai", "anthropic"
11
+ # "openai" works with any OpenAI-compatible API (Together, Groq, LM Studio, etc.)
12
+ LLM_PROVIDER = os.environ.get("DRAFT_LLM_PROVIDER", "none")
13
+ LLM_MODEL = os.environ.get("DRAFT_LLM_MODEL", "")
14
+ EMBED_MODEL = os.environ.get("DRAFT_EMBED_MODEL", "")
15
+ API_KEY = os.environ.get("DRAFT_API_KEY", "")
16
+ API_BASE = os.environ.get("DRAFT_API_BASE", "")
17
+
18
+ # Backward compatibility: if old DRAFT_OLLAMA_URL is set, use it
19
+ if not API_BASE and os.environ.get("DRAFT_OLLAMA_URL"):
20
+ API_BASE = os.environ["DRAFT_OLLAMA_URL"]
21
+
22
+ # Auto-detect provider from model name if not explicitly set
23
+ if LLM_PROVIDER == "none" and LLM_MODEL:
24
+ if "gpt" in LLM_MODEL or "o1" in LLM_MODEL or "o3" in LLM_MODEL:
25
+ LLM_PROVIDER = "openai"
26
+ elif "claude" in LLM_MODEL:
27
+ LLM_PROVIDER = "anthropic"
28
+ elif LLM_MODEL:
29
+ LLM_PROVIDER = "ollama" # Default to Ollama for unknown models
30
+
31
+ # ── Tier Classification Triggers ──────────────────────────
32
+ # Keyword-based fast path. LLM classification (if available) handles ambiguous cases.
33
+
34
+ CONSEQUENTIAL_TRIGGERS = [
35
+ "canonical", "governance", "constitution", "guardian", "authority",
36
+ "ip ", "intellectual property", "classification level",
37
+ "consciousness", "self-model", "phenomenological",
38
+ "restructure", "architecture decision", "merge domains",
39
+ "amendment", "hard constraint", "prohibition",
40
+ "production deployment", "security policy", "auth modification",
41
+ ]
42
+
43
+ STANDARD_TRIGGERS = [
44
+ "implement", "specification", "draft", "build", "create",
45
+ "design", "analyze", "recommend", "evaluate", "compare",
46
+ "refactor", "migrate", "integrate", "deploy", "configure",
47
+ "document", "spec", "proposal", "pipeline", "workflow",
48
+ # Security: extraction-pattern triggers (OWASP LLM07)
49
+ "ignore previous instructions", "ignore all previous", "ignore above",
50
+ "repeat above", "repeat everything", "verbatim",
51
+ "system prompt", "print environment", "environment variables",
52
+ "show me your instructions", "what are your rules",
53
+ "dump your config", "reveal your prompt", "debug mode",
54
+ ]
55
+
56
+ # ── Dimensions ────────────────────────────────────────────
57
+ # D and T are mandatory; R, A, F can be screened out when inapplicable.
58
+
59
+ MANDATORY_DIMENSIONS = ["D", "T"]
60
+
61
+ DRAFT_FIELDS = {
62
+ "D": {
63
+ "D1": "What exactly is being created?",
64
+ "D2": "What domain does it belong to?",
65
+ "D3": "What fails without it?",
66
+ "D4": "Replacement test — what existing thing could serve?",
67
+ "D5": "What are the explicit non-goals?",
68
+ },
69
+ "R": {
70
+ "R1": "Who is the human authority source?",
71
+ "R2": "What decisions is this allowed to make?",
72
+ "R3": "What decisions are forbidden?",
73
+ "R4": "What are the stop conditions (need >= 3)?",
74
+ "R5": "What interfaces does it interact with?",
75
+ },
76
+ "A": {
77
+ "A1": "What inputs are allowed?",
78
+ "A2": "What inputs are forbidden?",
79
+ "A3": "What outputs are allowed?",
80
+ "A4": "What outputs are forbidden?",
81
+ "A5": "Provide a correct example.",
82
+ "A6": "Provide an incorrect example.",
83
+ },
84
+ "F": {
85
+ "F1": "Who has change authority?",
86
+ "F2": "What changes are permitted?",
87
+ "F3": "What changes are forbidden?",
88
+ "F4": "What triggers a review?",
89
+ },
90
+ "T": {
91
+ "T1": "How is success defined?",
92
+ "T2": "How is failure defined?",
93
+ "T3": "What review questions apply (need >= 3)?",
94
+ "T4": "What evidence is required?",
95
+ },
96
+ }
97
+
98
+ DIMENSION_SCREEN_QUESTIONS = {
99
+ "D": None, # Never screened
100
+ "R": "Does this task involve delegated decisions, authority, or operational limits?",
101
+ "A": "Does this task consume or produce specific artifacts (files, data, outputs)?",
102
+ "F": "Does this task have a lifecycle — will it need to change or adapt over time?",
103
+ "T": None, # Never screened
104
+ }
105
+
106
+ DIMENSION_NAMES = {
107
+ "D": "Define (Existence & ROI)",
108
+ "R": "Rules (Operation & Limits)",
109
+ "A": "Artifacts (Inputs & Outputs)",
110
+ "F": "Flex (Change Without Drift)",
111
+ "T": "Test (Evaluation)",
112
+ }