draft-protocol 0.1.0__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.
Files changed (54) hide show
  1. draft_protocol-0.1.0/.dockerignore +30 -0
  2. draft_protocol-0.1.0/.editorconfig +27 -0
  3. draft_protocol-0.1.0/.github/CODEOWNERS +10 -0
  4. draft_protocol-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +83 -0
  5. draft_protocol-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +55 -0
  6. draft_protocol-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +25 -0
  7. draft_protocol-0.1.0/.github/dependabot.yml +25 -0
  8. draft_protocol-0.1.0/.github/workflows/ci.yml +62 -0
  9. draft_protocol-0.1.0/.github/workflows/release.yml +71 -0
  10. draft_protocol-0.1.0/.gitignore +46 -0
  11. draft_protocol-0.1.0/.pre-commit-config.yaml +24 -0
  12. draft_protocol-0.1.0/AGENTS.md +49 -0
  13. draft_protocol-0.1.0/CHANGELOG.md +54 -0
  14. draft_protocol-0.1.0/CODE_OF_CONDUCT.md +40 -0
  15. draft_protocol-0.1.0/CONTRIBUTING.md +90 -0
  16. draft_protocol-0.1.0/Dockerfile +33 -0
  17. draft_protocol-0.1.0/LICENSE +189 -0
  18. draft_protocol-0.1.0/Makefile +57 -0
  19. draft_protocol-0.1.0/PKG-INFO +362 -0
  20. draft_protocol-0.1.0/README.md +325 -0
  21. draft_protocol-0.1.0/RULES.md +32 -0
  22. draft_protocol-0.1.0/SECURITY.md +42 -0
  23. draft_protocol-0.1.0/STRUCTURE.md +70 -0
  24. draft_protocol-0.1.0/docker-compose.example.yml +41 -0
  25. draft_protocol-0.1.0/docs/README.md +30 -0
  26. draft_protocol-0.1.0/docs/api.md +253 -0
  27. draft_protocol-0.1.0/docs/architecture.md +183 -0
  28. draft_protocol-0.1.0/examples/README.md +20 -0
  29. draft_protocol-0.1.0/examples/basic_usage.py +101 -0
  30. draft_protocol-0.1.0/extension/background.js +149 -0
  31. draft_protocol-0.1.0/extension/content.css +111 -0
  32. draft_protocol-0.1.0/extension/content.js +228 -0
  33. draft_protocol-0.1.0/extension/icons/icon128.png +0 -0
  34. draft_protocol-0.1.0/extension/icons/icon16.png +0 -0
  35. draft_protocol-0.1.0/extension/icons/icon48.png +0 -0
  36. draft_protocol-0.1.0/extension/manifest.json +48 -0
  37. draft_protocol-0.1.0/extension/popup.html +215 -0
  38. draft_protocol-0.1.0/extension/popup.js +111 -0
  39. draft_protocol-0.1.0/extension/sidepanel.html +227 -0
  40. draft_protocol-0.1.0/extension/sidepanel.js +251 -0
  41. draft_protocol-0.1.0/pyproject.toml +87 -0
  42. draft_protocol-0.1.0/src/draft_protocol/__init__.py +65 -0
  43. draft_protocol-0.1.0/src/draft_protocol/__main__.py +61 -0
  44. draft_protocol-0.1.0/src/draft_protocol/config.py +112 -0
  45. draft_protocol-0.1.0/src/draft_protocol/engine.py +724 -0
  46. draft_protocol-0.1.0/src/draft_protocol/providers.py +222 -0
  47. draft_protocol-0.1.0/src/draft_protocol/py.typed +0 -0
  48. draft_protocol-0.1.0/src/draft_protocol/rest.py +168 -0
  49. draft_protocol-0.1.0/src/draft_protocol/server.py +367 -0
  50. draft_protocol-0.1.0/src/draft_protocol/storage.py +130 -0
  51. draft_protocol-0.1.0/tests/conftest.py +6 -0
  52. draft_protocol-0.1.0/tests/test_draft_protocol.py +361 -0
  53. draft_protocol-0.1.0/tests/test_rest.py +130 -0
  54. draft_protocol-0.1.0/tests/test_security.py +170 -0
@@ -0,0 +1,30 @@
1
+ .git
2
+ .github
3
+ __pycache__
4
+ *.pyc
5
+ *.pyo
6
+ *.egg-info
7
+ dist
8
+ build
9
+ .pytest_cache
10
+ .mypy_cache
11
+ .ruff_cache
12
+ *.db
13
+ *.log
14
+ .env
15
+ .secrets-baseline.json
16
+ extension/
17
+ docs/
18
+ examples/
19
+ tests/
20
+ Makefile
21
+ .pre-commit-config.yaml
22
+ .editorconfig
23
+ AGENTS.md
24
+ RULES.md
25
+ STRUCTURE.md
26
+ CONTRIBUTING.md
27
+ CODE_OF_CONDUCT.md
28
+ SECURITY.md
29
+ CHANGELOG.md
30
+ docker-compose.example.yml
@@ -0,0 +1,27 @@
1
+ # .editorconfig — consistent formatting across editors
2
+ # https://editorconfig.org
3
+
4
+ root = true
5
+
6
+ [*]
7
+ indent_style = space
8
+ indent_size = 4
9
+ end_of_line = lf
10
+ charset = utf-8
11
+ trim_trailing_whitespace = true
12
+ insert_final_newline = true
13
+
14
+ [*.md]
15
+ trim_trailing_whitespace = false
16
+
17
+ [*.yml]
18
+ indent_size = 2
19
+
20
+ [*.yaml]
21
+ indent_size = 2
22
+
23
+ [*.toml]
24
+ indent_size = 4
25
+
26
+ [Makefile]
27
+ indent_style = tab
@@ -0,0 +1,10 @@
1
+ # CODEOWNERS — automatically request reviews
2
+ # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
3
+
4
+ # Default: founder reviews everything
5
+ * @georgegoytia
6
+
7
+ # Governance-critical files require explicit review
8
+ src/draft_protocol/engine.py @georgegoytia
9
+ src/draft_protocol/storage.py @georgegoytia
10
+ src/draft_protocol/config.py @georgegoytia
@@ -0,0 +1,83 @@
1
+ name: Bug Report
2
+ description: Report a bug in DRAFT Protocol
3
+ title: "[Bug]: "
4
+ labels: ["bug"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thanks for reporting! If this is a **governance bypass** (gate passed when it shouldn't have), please mark it as critical.
10
+
11
+ - type: textarea
12
+ id: description
13
+ attributes:
14
+ label: What happened?
15
+ description: Clear description of the bug.
16
+ placeholder: "When I called draft_gate after confirming all fields, it still returned BLOCKED..."
17
+ validations:
18
+ required: true
19
+
20
+ - type: textarea
21
+ id: expected
22
+ attributes:
23
+ label: Expected behavior
24
+ description: What should have happened instead?
25
+ validations:
26
+ required: true
27
+
28
+ - type: textarea
29
+ id: reproduce
30
+ attributes:
31
+ label: Steps to reproduce
32
+ description: Minimal steps to trigger the bug.
33
+ placeholder: |
34
+ 1. `pip install draft-protocol`
35
+ 2. `python -c "from draft_protocol import classify_tier; print(classify_tier('...'))"`
36
+ 3. See error...
37
+ validations:
38
+ required: true
39
+
40
+ - type: dropdown
41
+ id: transport
42
+ attributes:
43
+ label: Transport
44
+ options:
45
+ - stdio (MCP)
46
+ - SSE
47
+ - streamable-http
48
+ - REST API
49
+ - Library (import)
50
+ validations:
51
+ required: true
52
+
53
+ - type: dropdown
54
+ id: severity
55
+ attributes:
56
+ label: Severity
57
+ description: Is this a governance bypass?
58
+ options:
59
+ - Normal bug
60
+ - Governance bypass (gate failed to block)
61
+ - Security issue (see SECURITY.md instead)
62
+ validations:
63
+ required: true
64
+
65
+ - type: input
66
+ id: version
67
+ attributes:
68
+ label: Version
69
+ description: Output of `python -c "import draft_protocol; print(draft_protocol.__version__)"`
70
+ placeholder: "0.1.0"
71
+
72
+ - type: input
73
+ id: python
74
+ attributes:
75
+ label: Python version
76
+ placeholder: "3.13"
77
+
78
+ - type: textarea
79
+ id: logs
80
+ attributes:
81
+ label: Logs / error output
82
+ description: Paste any relevant error messages.
83
+ render: shell
@@ -0,0 +1,55 @@
1
+ name: Feature Request
2
+ description: Suggest a new feature or enhancement
3
+ title: "[Feature]: "
4
+ labels: ["enhancement"]
5
+ body:
6
+ - type: textarea
7
+ id: problem
8
+ attributes:
9
+ label: What problem does this solve?
10
+ description: What gap or limitation are you hitting?
11
+ placeholder: "I need DRAFT to support X because currently I have to..."
12
+ validations:
13
+ required: true
14
+
15
+ - type: textarea
16
+ id: solution
17
+ attributes:
18
+ label: Proposed solution
19
+ description: How should this work?
20
+ validations:
21
+ required: true
22
+
23
+ - type: textarea
24
+ id: alternatives
25
+ attributes:
26
+ label: Alternatives considered
27
+ description: Other approaches you've thought about.
28
+
29
+ - type: dropdown
30
+ id: area
31
+ attributes:
32
+ label: Area
33
+ options:
34
+ - MCP server (tools)
35
+ - REST API
36
+ - Chrome extension
37
+ - Engine (classification/mapping)
38
+ - Providers (LLM/embedding)
39
+ - Storage
40
+ - Documentation
41
+ - Docker/deployment
42
+ - Other
43
+ validations:
44
+ required: true
45
+
46
+ - type: dropdown
47
+ id: breaking
48
+ attributes:
49
+ label: Would this be a breaking change?
50
+ options:
51
+ - "No"
52
+ - "Yes"
53
+ - "Not sure"
54
+ validations:
55
+ required: true
@@ -0,0 +1,25 @@
1
+ ## What does this PR do?
2
+
3
+ <!-- Brief description of the change. -->
4
+
5
+ ## Type of change
6
+
7
+ - [ ] Bug fix (non-breaking change that fixes an issue)
8
+ - [ ] New feature (non-breaking change that adds functionality)
9
+ - [ ] Breaking change (fix or feature that would cause existing functionality to change)
10
+ - [ ] Documentation update
11
+ - [ ] Security fix (governance bypass or vulnerability)
12
+
13
+ ## Checklist
14
+
15
+ - [ ] Tests added/updated for this change
16
+ - [ ] `make lint` passes
17
+ - [ ] `make test` passes
18
+ - [ ] Documentation updated if needed
19
+ - [ ] CHANGELOG.md updated under `[Unreleased]`
20
+
21
+ ## Security considerations
22
+
23
+ <!-- If this touches the gate, classification, or confirmation logic: what governance implications does it have? -->
24
+
25
+ None / Describe below:
@@ -0,0 +1,25 @@
1
+ # Dependabot — automated dependency updates
2
+ # https://docs.github.com/en/code-security/dependabot/dependabot-version-updates
3
+
4
+ version: 2
5
+ updates:
6
+ - package-ecosystem: "pip"
7
+ directory: "/"
8
+ schedule:
9
+ interval: "weekly"
10
+ day: "monday"
11
+ labels:
12
+ - "dependencies"
13
+ commit-message:
14
+ prefix: "deps:"
15
+
16
+ - package-ecosystem: "github-actions"
17
+ directory: "/"
18
+ schedule:
19
+ interval: "weekly"
20
+ day: "monday"
21
+ labels:
22
+ - "dependencies"
23
+ - "ci"
24
+ commit-message:
25
+ prefix: "ci:"
@@ -0,0 +1,62 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
19
+
20
+ steps:
21
+ - uses: actions/checkout@v6
22
+
23
+ - name: Set up Python ${{ matrix.python-version }}
24
+ uses: actions/setup-python@v6
25
+ with:
26
+ python-version: ${{ matrix.python-version }}
27
+
28
+ - name: Install dependencies
29
+ run: |
30
+ python -m pip install --upgrade pip
31
+ pip install -e ".[dev]"
32
+
33
+ - name: Lint
34
+ run: ruff check src/ tests/
35
+
36
+ - name: Test with coverage
37
+ run: pytest tests/ -v --tb=short --cov=draft_protocol --cov-report=term-missing --cov-report=xml
38
+
39
+ - name: Upload coverage
40
+ if: matrix.python-version == '3.12'
41
+ uses: codecov/codecov-action@v5
42
+ with:
43
+ file: coverage.xml
44
+ fail_ci_if_error: false
45
+
46
+ type-check:
47
+ runs-on: ubuntu-latest
48
+ steps:
49
+ - uses: actions/checkout@v6
50
+
51
+ - name: Set up Python
52
+ uses: actions/setup-python@v6
53
+ with:
54
+ python-version: "3.12"
55
+
56
+ - name: Install dependencies
57
+ run: |
58
+ python -m pip install --upgrade pip
59
+ pip install -e ".[dev]"
60
+
61
+ - name: Type check
62
+ run: mypy src/draft_protocol/ --ignore-missing-imports --no-strict-optional
@@ -0,0 +1,71 @@
1
+ name: Release to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ permissions:
9
+ contents: write
10
+ id-token: write
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ matrix:
17
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
18
+ steps:
19
+ - uses: actions/checkout@v6
20
+
21
+ - name: Set up Python ${{ matrix.python-version }}
22
+ uses: actions/setup-python@v6
23
+ with:
24
+ python-version: ${{ matrix.python-version }}
25
+
26
+ - name: Install dependencies
27
+ run: |
28
+ python -m pip install --upgrade pip
29
+ pip install -e ".[dev]"
30
+
31
+ - name: Lint
32
+ run: ruff check src/ tests/
33
+
34
+ - name: Test
35
+ run: pytest tests/ -v --tb=short
36
+
37
+ publish:
38
+ needs: test
39
+ runs-on: ubuntu-latest
40
+ environment:
41
+ name: pypi
42
+ url: https://pypi.org/project/draft-protocol/
43
+ steps:
44
+ - uses: actions/checkout@v6
45
+
46
+ - name: Set up Python
47
+ uses: actions/setup-python@v6
48
+ with:
49
+ python-version: "3.12"
50
+
51
+ - name: Install build tools
52
+ run: pip install build
53
+
54
+ - name: Build package
55
+ run: python -m build
56
+
57
+ - name: Publish to PyPI
58
+ uses: pypa/gh-action-pypi-publish@release/v1
59
+
60
+ github-release:
61
+ needs: publish
62
+ runs-on: ubuntu-latest
63
+ permissions:
64
+ contents: write
65
+ steps:
66
+ - uses: actions/checkout@v6
67
+
68
+ - name: Create GitHub Release
69
+ uses: softprops/action-gh-release@v2
70
+ with:
71
+ generate_release_notes: true
@@ -0,0 +1,46 @@
1
+ # Python
2
+ __pycache__/
3
+ *.pyc
4
+ *.pyo
5
+ *.egg-info/
6
+ *.egg
7
+ dist/
8
+ build/
9
+ .eggs/
10
+
11
+ # Virtual environments
12
+ .venv/
13
+ venv/
14
+ env/
15
+
16
+ # Testing
17
+ *.db
18
+ .pytest_cache/
19
+ .coverage
20
+ coverage.xml
21
+ htmlcov/
22
+ .mypy_cache/
23
+
24
+ # Linting
25
+ .ruff_cache/
26
+
27
+ # IDE
28
+ .vscode/
29
+ .idea/
30
+ *.swp
31
+ *.swo
32
+ *~
33
+
34
+ # OS
35
+ .DS_Store
36
+ Thumbs.db
37
+
38
+ # Distribution
39
+ *.tar.gz
40
+ *.whl
41
+
42
+ # Security
43
+ .secrets-baseline.json
44
+
45
+ # Logs
46
+ *.log
@@ -0,0 +1,24 @@
1
+ # Pre-commit hooks — run before every commit
2
+ # Install: pre-commit install
3
+ # Run all: pre-commit run --all-files
4
+ # https://pre-commit.com
5
+
6
+ repos:
7
+ - repo: https://github.com/pre-commit/pre-commit-hooks
8
+ rev: v5.0.0
9
+ hooks:
10
+ - id: trailing-whitespace
11
+ - id: end-of-file-fixer
12
+ - id: check-yaml
13
+ - id: check-toml
14
+ - id: check-added-large-files
15
+ args: ["--maxkb=500"]
16
+ - id: check-merge-conflict
17
+ - id: debug-statements
18
+
19
+ - repo: https://github.com/astral-sh/ruff-pre-commit
20
+ rev: v0.9.6
21
+ hooks:
22
+ - id: ruff
23
+ args: [--fix]
24
+ - id: ruff-format
@@ -0,0 +1,49 @@
1
+ # AGENTS.md — AI Agent Instructions
2
+
3
+ > For AI coding assistants (Copilot, Cursor, Claude, etc.) working in this repo.
4
+
5
+ ## Project Overview
6
+
7
+ **DRAFT Protocol** is an open-source intake governance layer for AI tool calls. It ensures AI understands human intent before execution begins, using a structured 5-dimension elicitation protocol with three tiers of rigor.
8
+
9
+ **License:** Apache 2.0
10
+ **Language:** Python 3.10+
11
+ **Transport:** MCP (stdio, SSE, streamable-http) + REST API
12
+
13
+ ## Key Directories
14
+
15
+ ```
16
+ src/draft_protocol/ # Core library
17
+ engine.py # Classification + mapping logic
18
+ server.py # MCP server (FastMCP)
19
+ rest.py # REST API (FastAPI)
20
+ storage.py # SQLite persistence + audit trail
21
+ config.py # Environment config + LLM provider setup
22
+ providers.py # LLM provider abstraction (Ollama, OpenAI, Anthropic)
23
+ extension/ # Chrome extension (works on 8 AI chat platforms)
24
+ tests/ # pytest suite (46+ tests)
25
+ docs/ # Product documentation
26
+ ```
27
+
28
+ ## Conventions
29
+
30
+ - **Commits:** Conventional Commits (`feat:`, `fix:`, `docs:`, `chore:`, `test:`)
31
+ - **Style:** ruff for linting + formatting, mypy for type checking
32
+ - **Line length:** 120 characters
33
+ - **Tests:** pytest. Run `make test` before committing
34
+ - **Pre-commit:** Installed via `make dev`. Runs ruff + trailing whitespace + detect-secrets
35
+
36
+ ## What NOT to Do
37
+
38
+ - Do not commit secrets, API keys, or `.env` files
39
+ - Do not add dependencies without updating `pyproject.toml`
40
+ - Do not modify `engine.py` or `storage.py` without running the full test suite
41
+ - Do not bypass the DRAFT elicitation protocol in code — it's the product
42
+ - Do not add files larger than 5MB
43
+
44
+ ## Related Repos
45
+
46
+ | Repo | Purpose | Platform |
47
+ |------|---------|----------|
48
+ | vector-gate | Three-gate pipeline (product repo) | GitLab (private) |
49
+ | draft-protocol | This repo — Gate 1 intake governance | GitHub (Apache 2.0) |
@@ -0,0 +1,54 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+ - `docs/architecture.md` — system design, pipeline flow, security model, file layout
12
+ - `docs/api.md` — REST API reference with all endpoints, request/response examples
13
+ - `examples/basic_usage.py` — library usage example (no server needed)
14
+ - `tests/test_security.py` — prompt injection, bypass, input validation tests
15
+ - `tests/test_rest.py` — REST API endpoint tests with mock handler
16
+ - `Dockerfile` — production container (Python 3.13-slim, non-root, SSE default)
17
+ - `docker-compose.example.yml` — example stack with DRAFT + Ollama
18
+ - `.dockerignore` — keep Docker image clean
19
+ - `.github/ISSUE_TEMPLATE/bug_report.yml` — structured bug report template
20
+ - `.github/ISSUE_TEMPLATE/feature_request.yml` — structured feature request template
21
+ - `.github/PULL_REQUEST_TEMPLATE.md` — PR checklist
22
+
23
+ ### Fixed
24
+ - `rest.py` `/status` endpoint called nonexistent `storage.get_session_state()` — replaced with inline session + gate query
25
+
26
+ ### Changed
27
+ - `docs/README.md` updated to documentation index linking all docs
28
+ - `STRUCTURE.md` updated to reflect all new files
29
+
30
+ ## [0.1.0] - 2025-02-21
31
+
32
+ ### Added
33
+ - 15 MCP tools for structured intent elicitation via FastMCP
34
+ - Three-tier automatic classification: Casual, Standard, Consequential
35
+ - Five-dimension mapping: Define, Rules, Artifacts, Flex, Test
36
+ - Confirmation gate blocks execution until all fields verified
37
+ - Assumptions surfacing with Devil's Advocate support
38
+ - Dimension screening for non-mandatory dimensions (R, A, F)
39
+ - Gate override with audit trail for founder use
40
+ - Elicitation review with quality self-assessment
41
+ - Multi-provider LLM support: Ollama, OpenAI, Anthropic, any OpenAI-compatible API
42
+ - Auto-detection of provider from model name
43
+ - Graceful degradation to keyword heuristics without LLM
44
+ - Prompt extraction attack detection (OWASP LLM07)
45
+ - Empty/whitespace input rejection at all entry points
46
+ - Full SQLite audit trail
47
+ - REST API with CORS for Chrome extension and HTTP clients
48
+ - Chrome extension for any AI chat (ChatGPT, Claude, Gemini, etc.)
49
+ - 46 tests covering security, lifecycle, governance, and provider configuration
50
+ - AGENTS.md, RULES.md, STRUCTURE.md for AI agent compatibility
51
+ - Professional repo infrastructure: CONTRIBUTING, SECURITY, CODE_OF_CONDUCT
52
+
53
+ [Unreleased]: https://github.com/georgegoytia/draft-protocol/compare/v0.1.0...HEAD
54
+ [0.1.0]: https://github.com/georgegoytia/draft-protocol/releases/tag/v0.1.0
@@ -0,0 +1,40 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, caste, color, religion, or sexual
10
+ identity and orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to a positive environment:
15
+
16
+ * Using welcoming and inclusive language
17
+ * Being respectful of differing viewpoints and experiences
18
+ * Gracefully accepting constructive criticism
19
+ * Focusing on what is best for the community
20
+ * Showing empathy towards other community members
21
+
22
+ Examples of unacceptable behavior:
23
+
24
+ * The use of sexualized language or imagery, and sexual attention or advances of any kind
25
+ * Trolling, insulting or derogatory comments, and personal or political attacks
26
+ * Public or private harassment
27
+ * Publishing others' private information without explicit permission
28
+ * Other conduct which could reasonably be considered inappropriate in a professional setting
29
+
30
+ ## Enforcement
31
+
32
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
33
+ reported to the project maintainers. All complaints will be reviewed and
34
+ investigated promptly and fairly.
35
+
36
+ ## Attribution
37
+
38
+ This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/),
39
+ version 2.1, available at
40
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html](https://www.contributor-covenant.org/version/2/1/code_of_conduct.html).