bpsai-pair 0.2.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.

Potentially problematic release.


This version of bpsai-pair might be problematic. Click here for more details.

Files changed (42) hide show
  1. bpsai_pair/__init__.py +25 -0
  2. bpsai_pair/__main__.py +4 -0
  3. bpsai_pair/adapters.py +9 -0
  4. bpsai_pair/cli.py +514 -0
  5. bpsai_pair/config.py +310 -0
  6. bpsai_pair/data/cookiecutter-paircoder/cookiecutter.json +12 -0
  7. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.agentpackignore +1 -0
  8. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.editorconfig +17 -0
  9. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.github/PULL_REQUEST_TEMPLATE.md +47 -0
  10. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.github/workflows/ci.yml +90 -0
  11. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.github/workflows/project_tree.yml +33 -0
  12. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.gitignore +5 -0
  13. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.gitleaks.toml +17 -0
  14. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.pre-commit-config.yaml +38 -0
  15. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/CODEOWNERS +9 -0
  16. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/CONTRIBUTING.md +35 -0
  17. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/SECURITY.md +14 -0
  18. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/context/agents.md +6 -0
  19. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/context/agents.md.bak +196 -0
  20. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/context/development.md +1 -0
  21. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/context/development.md.bak +10 -0
  22. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/context/directory_notes/.gitkeep +1 -0
  23. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/context/project_tree.md +7 -0
  24. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/prompts/deep_research.yml +28 -0
  25. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/prompts/implementation.yml +25 -0
  26. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/prompts/roadmap.yml +14 -0
  27. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/scripts/README.md +11 -0
  28. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/src/.gitkeep +1 -0
  29. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/templates/adr.md +19 -0
  30. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/templates/directory_note.md +17 -0
  31. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/tests/example_contract/README.md +3 -0
  32. bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/tests/example_integration/README.md +3 -0
  33. bpsai_pair/init_bundled_cli.py +47 -0
  34. bpsai_pair/jsonio.py +6 -0
  35. bpsai_pair/ops.py +451 -0
  36. bpsai_pair/pyutils.py +26 -0
  37. bpsai_pair/utils.py +11 -0
  38. bpsai_pair-0.2.0.dist-info/METADATA +29 -0
  39. bpsai_pair-0.2.0.dist-info/RECORD +42 -0
  40. bpsai_pair-0.2.0.dist-info/WHEEL +5 -0
  41. bpsai_pair-0.2.0.dist-info/entry_points.txt +3 -0
  42. bpsai_pair-0.2.0.dist-info/top_level.txt +1 -0
bpsai_pair/config.py ADDED
@@ -0,0 +1,310 @@
1
+ """
2
+ Configuration management for PairCoder.
3
+ """
4
+ from __future__ import annotations
5
+
6
+ import os
7
+ from pathlib import Path
8
+ from typing import Optional, Dict, Any
9
+ import yaml
10
+ import json
11
+ from dataclasses import dataclass, asdict, field
12
+
13
+
14
+ @dataclass
15
+ class Config:
16
+ """PairCoder configuration."""
17
+
18
+ # Project settings
19
+ project_name: str = "My Project"
20
+ primary_goal: str = "Build awesome software"
21
+ coverage_target: int = 80
22
+
23
+ # Branch settings
24
+ default_branch_type: str = "feature"
25
+ main_branch: str = "main"
26
+
27
+ # Context settings
28
+ context_dir: str = "context"
29
+
30
+ # Pack settings
31
+ default_pack_name: str = "agent_pack.tgz"
32
+ pack_excludes: list[str] = field(default_factory=lambda: [
33
+ ".git", ".venv", "__pycache__", "node_modules",
34
+ "dist", "build", "*.log", "*.bak"
35
+ ])
36
+
37
+ # CI settings
38
+ python_formatter: str = "ruff"
39
+ node_formatter: str = "prettier"
40
+
41
+ @classmethod
42
+ def load(cls, root: Path) -> "Config":
43
+ """Load configuration from .paircoder.yml or environment."""
44
+ config_file = root / ".paircoder.yml"
45
+
46
+ data = {}
47
+ if config_file.exists():
48
+ with open(config_file) as f:
49
+ yaml_data = yaml.safe_load(f) or {}
50
+
51
+ # Handle both flat and nested structures
52
+ if "version" in yaml_data:
53
+ # New nested structure
54
+ if "project" in yaml_data:
55
+ project = yaml_data["project"]
56
+ data["project_name"] = project.get("name", "My Project")
57
+ data["primary_goal"] = project.get("primary_goal", "Build awesome software")
58
+ data["coverage_target"] = project.get("coverage_target", 80)
59
+
60
+ if "workflow" in yaml_data:
61
+ workflow = yaml_data["workflow"]
62
+ data["default_branch_type"] = workflow.get("default_branch_type", "feature")
63
+ data["main_branch"] = workflow.get("main_branch", "main")
64
+ data["context_dir"] = workflow.get("context_dir", "context")
65
+
66
+ if "pack" in yaml_data:
67
+ pack = yaml_data["pack"]
68
+ data["default_pack_name"] = pack.get("default_name", "agent_pack.tgz")
69
+ data["pack_excludes"] = pack.get("excludes", [])
70
+
71
+ if "ci" in yaml_data:
72
+ ci = yaml_data["ci"]
73
+ data["python_formatter"] = ci.get("python_formatter", "ruff")
74
+ data["node_formatter"] = ci.get("node_formatter", "prettier")
75
+ else:
76
+ # Old flat structure (backwards compatibility)
77
+ data = yaml_data
78
+
79
+ # Override with environment variables
80
+ env_mappings = {
81
+ "PAIRCODER_MAIN_BRANCH": "main_branch",
82
+ "PAIRCODER_CONTEXT_DIR": "context_dir",
83
+ "PAIRCODER_DEFAULT_BRANCH": "default_branch_type",
84
+ "PAIRCODER_PROJECT_NAME": "project_name",
85
+ }
86
+
87
+ for env_var, config_key in env_mappings.items():
88
+ if env_value := os.getenv(env_var):
89
+ data[config_key] = env_value
90
+
91
+ # Create config with collected data
92
+ return cls(**{k: v for k, v in data.items() if k in cls.__annotations__})
93
+
94
+ def save(self, root: Path) -> None:
95
+ """Save configuration to .paircoder.yml."""
96
+ config_file = root / ".paircoder.yml"
97
+
98
+ data = {
99
+ "version": "0.1.3",
100
+ "project": {
101
+ "name": self.project_name,
102
+ "primary_goal": self.primary_goal,
103
+ "coverage_target": self.coverage_target,
104
+ },
105
+ "workflow": {
106
+ "default_branch_type": self.default_branch_type,
107
+ "main_branch": self.main_branch,
108
+ "context_dir": self.context_dir,
109
+ },
110
+ "pack": {
111
+ "default_name": self.default_pack_name,
112
+ "excludes": self.pack_excludes,
113
+ },
114
+ "ci": {
115
+ "python_formatter": self.python_formatter,
116
+ "node_formatter": self.node_formatter,
117
+ }
118
+ }
119
+
120
+ with open(config_file, 'w') as f:
121
+ yaml.dump(data, f, default_flow_style=False, sort_keys=False)
122
+
123
+ def to_dict(self) -> Dict[str, Any]:
124
+ """Convert to dictionary."""
125
+ return asdict(self)
126
+
127
+ def to_json(self) -> str:
128
+ """Convert to JSON string."""
129
+ return json.dumps(self.to_dict(), indent=2)
130
+
131
+
132
+ class ContextTemplate:
133
+ """Templates for context files."""
134
+
135
+ @staticmethod
136
+ def development_md(config: Config) -> str:
137
+ """Generate development.md template."""
138
+ return f"""# Development Log
139
+
140
+ **Project:** {config.project_name}
141
+ **Phase:** Phase 1: Initial Setup
142
+ **Primary Goal:** {config.primary_goal}
143
+
144
+ ## KPIs & Non-Functional Targets
145
+
146
+ - Test Coverage: ≥ {config.coverage_target}%
147
+ - Documentation: Complete for all public APIs
148
+ - Performance: Response time < 200ms (p95)
149
+
150
+ ## Phase 1 — Foundation (Weeks 1–2)
151
+
152
+ **Objectives**
153
+ - Set up project structure and CI/CD
154
+ - Define core architecture and interfaces
155
+ - Establish testing framework
156
+
157
+ **Tasks**
158
+ - [ ] Initialize repository with PairCoder
159
+ - [ ] Set up CI workflows
160
+ - [ ] Create initial project structure
161
+ - [ ] Write architectural decision records
162
+
163
+ **Testing Plan**
164
+ - Unit tests for all business logic
165
+ - Integration tests for external boundaries
166
+ - End-to-end tests for critical user flows
167
+
168
+ **Risks & Rollback**
169
+ - Risk: Incomplete requirements — Mitigation: Regular stakeholder reviews
170
+ - Rollback: Git revert with documented rollback procedures
171
+
172
+ ## Context Sync (AUTO-UPDATED)
173
+
174
+ - **Overall goal is:** {config.primary_goal}
175
+ - **Last action was:** Initialized project
176
+ - **Next action will be:** Set up CI/CD pipeline
177
+ - **Blockers:** None
178
+ """
179
+
180
+ @staticmethod
181
+ def agents_md(config: Config) -> str:
182
+ """Generate agents.md template."""
183
+ return f"""# Agents Guide — AI Pair Coding Playbook
184
+
185
+ **Project:** {config.project_name}
186
+ **Purpose:** {config.primary_goal}
187
+
188
+ ## Ground Rules
189
+
190
+ 1. **Context is King**: Always refer to `/context/development.md` for current state
191
+ 2. **Test First**: Write tests before implementation
192
+ 3. **Small Changes**: Keep PRs under 200 lines when possible
193
+ 4. **Update Loop**: Run `bpsai-pair context-sync` after every significant change
194
+
195
+ ## Project Structure
196
+
197
+ ```
198
+ .
199
+ ├── {config.context_dir}/ # Project context and memory
200
+ ├── src/ # Source code
201
+ ├── tests/ # Test suites
202
+ ├── docs/ # Documentation
203
+ └── .paircoder.yml # Configuration
204
+ ```
205
+
206
+ ## Workflow
207
+
208
+ 1. Check status: `bpsai-pair status`
209
+ 2. Create feature: `bpsai-pair feature <name> --primary "<goal>" --phase "<phase>"`
210
+ 3. Make changes (with tests)
211
+ 4. Update context: `bpsai-pair context-sync --last "<what>" --next "<next>"`
212
+ 5. Create pack: `bpsai-pair pack`
213
+ 6. Share with AI agent
214
+
215
+ ## Testing Requirements
216
+
217
+ - Minimum coverage: {config.coverage_target}%
218
+ - All new code must have tests
219
+ - Integration tests for external dependencies
220
+ - Performance tests for critical paths
221
+
222
+ ## Code Style
223
+
224
+ - Python: {config.python_formatter} for formatting and linting
225
+ - JavaScript: {config.node_formatter} for formatting
226
+ - Commit messages: Conventional Commits format
227
+ - Branch names: {config.default_branch_type}/<description>
228
+
229
+ ## Context Loop Protocol
230
+
231
+ After EVERY meaningful change:
232
+ ```bash
233
+ bpsai-pair context-sync \\
234
+ --last "What was just completed" \\
235
+ --next "The immediate next step" \\
236
+ --blockers "Any impediments"
237
+ ```
238
+
239
+ ## Excluded from Context
240
+
241
+ The following are excluded from agent packs (see `.agentpackignore`):
242
+ {chr(10).join(f'- {exclude}' for exclude in config.pack_excludes)}
243
+
244
+ ## Commands Reference
245
+
246
+ - `bpsai-pair init` - Initialize scaffolding
247
+ - `bpsai-pair feature` - Create feature branch
248
+ - `bpsai-pair pack` - Create context package
249
+ - `bpsai-pair sync` - Update context loop
250
+ - `bpsai-pair status` - Show current state
251
+ - `bpsai-pair validate` - Check structure
252
+ - `bpsai-pair ci` - Run local CI checks
253
+ """
254
+
255
+ @staticmethod
256
+ def gitignore() -> str:
257
+ """Generate .gitignore template."""
258
+ return """# PairCoder
259
+ .paircoder.yml.local
260
+ agent_pack*.tgz
261
+ *.bak
262
+
263
+ # Python
264
+ __pycache__/
265
+ *.py[cod]
266
+ *$py.class
267
+ *.so
268
+ .Python
269
+ .venv/
270
+ venv/
271
+ ENV/
272
+ env/
273
+ *.egg-info/
274
+ dist/
275
+ build/
276
+ .pytest_cache/
277
+ .mypy_cache/
278
+ .ruff_cache/
279
+ .coverage
280
+ htmlcov/
281
+
282
+ # Node
283
+ node_modules/
284
+ npm-debug.log*
285
+ yarn-debug.log*
286
+ yarn-error.log*
287
+ .npm
288
+ .yarn-integrity
289
+
290
+ # IDE
291
+ .idea/
292
+ .vscode/
293
+ *.swp
294
+ *.swo
295
+ *~
296
+ .DS_Store
297
+
298
+ # Environment
299
+ .env
300
+ .env.local
301
+ .env.*.local
302
+
303
+ # Logs
304
+ *.log
305
+ logs/
306
+
307
+ # OS
308
+ Thumbs.db
309
+ Desktop.ini
310
+ """
@@ -0,0 +1,12 @@
1
+
2
+ {
3
+ "project_name": "Paircoder Project",
4
+ "project_slug": "{{ cookiecutter.project_name | lower | replace(' ', '-') }}",
5
+ "primary_goal": "<PRIMARY GOAL>",
6
+ "coverage_target": "80%",
7
+ "owner_gh_handle": "<OWNER>",
8
+ "architect_gh_handle": "<ARCHITECT>",
9
+ "build_gh_handle": "<BUILD>",
10
+ "qa_gh_handle": "<QA>",
11
+ "sre_gh_handle": "<SRE>"
12
+ }
@@ -0,0 +1 @@
1
+ # Default agent pack exclusions\n.git/\n.venv/\n__pycache__/\nnode_modules/\ndist/\nbuild/\n*.log\n*.bak\n*.tgz\n*.tar.gz\n*.zip\n
@@ -0,0 +1,17 @@
1
+
2
+ root = true
3
+
4
+ [*]
5
+ end_of_line = lf
6
+ insert_final_newline = true
7
+ charset = utf-8
8
+ trim_trailing_whitespace = true
9
+ indent_style = space
10
+ indent_size = 2
11
+
12
+ [*.py]
13
+ indent_size = 4
14
+
15
+ [*.md]
16
+ max_line_length = off
17
+ trim_trailing_whitespace = false
@@ -0,0 +1,47 @@
1
+
2
+ ## Summary
3
+ - What change does this PR introduce and why?
4
+ - Link to the PRIMARY GOAL or tracked issue: <link>
5
+
6
+ ## Risk Level
7
+ - [ ] Low
8
+ - [ ] Medium
9
+ - [ ] High (requires explicit rollback plan & ADR)
10
+
11
+ ## Change Type
12
+ - [ ] Feature
13
+ - [ ] Refactor
14
+ - [ ] Fix
15
+ - [ ] Docs/Chore
16
+
17
+ ## Scope & Impact
18
+ - Affected modules/dirs: <list>
19
+ - Backwards compatibility: <preserved / changed (explain)>
20
+ - Breaking changes: <none / explain + migration>
21
+
22
+ ## Test Plan
23
+ - Unit tests added/updated: <list>
24
+ - Integration/Contract tests: <list>
25
+ - Manual verification steps: <commands + expected results>
26
+
27
+ ## Context Update (MANDATORY)
28
+ Paste the diff or summary of updates to `/context/*`:
29
+ ```
30
+ Overall goal is: <...>
31
+ Last action was: <...>
32
+ Next action will be: <...>
33
+ Blockers/Risks: <...>
34
+ ```
35
+
36
+ ## Rollback Plan
37
+ - Strategy: <revert commit SHA / feature flag / backup restore>
38
+ - Data/Schema implications: <if any>
39
+
40
+ ## Screenshots / Logs (optional)
41
+ <attach>
42
+
43
+ ## Checklist
44
+ - [ ] CI green (lint, type, tests, audit)
45
+ - [ ] Coverage ≥ target or unchanged
46
+ - [ ] ADR updated/added when design or contracts change
47
+ - [ ] No secrets/PII introduced; `.agentpackignore` updated if needed
@@ -0,0 +1,90 @@
1
+
2
+ name: CI
3
+
4
+ on:
5
+ push:
6
+ branches: [ main ]
7
+ pull_request:
8
+ branches: [ main ]
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ jobs:
14
+ node:
15
+ name: Node CI
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ - name: Detect package.json
20
+ id: detect
21
+ run: |
22
+ if [ -f package.json ]; then echo "has_node=true" >> $GITHUB_OUTPUT; else echo "has_node=false" >> $GITHUB_OUTPUT; fi
23
+ - name: Setup Node
24
+ if: steps.detect.outputs.has_node == true
25
+ uses: actions/setup-node@v4
26
+ with:
27
+ node-version: lts/*
28
+ cache: npm
29
+ - name: Install deps
30
+ if: steps.detect.outputs.has_node == true
31
+ run: npm ci --ignore-scripts
32
+ - name: Format & Lint
33
+ if: steps.detect.outputs.has_node == true
34
+ run: |
35
+ (npm run -s fmt || npx --yes prettier -c .) || true
36
+ (npm run -s lint || npx --yes eslint .)
37
+ - name: Type Check
38
+ if: steps.detect.outputs.has_node == true && hashFiles(tsconfig.json) !=
39
+ run: (npm run -s typecheck || npx --yes tsc -p . --noEmit)
40
+ - name: Test
41
+ if: steps.detect.outputs.has_node == true
42
+ run: |
43
+ npm test --silent || npm run -s test
44
+ - name: Audit (non-blocking)
45
+ if: steps.detect.outputs.has_node == true
46
+ run: npm audit --audit-level=high || true
47
+
48
+ python:
49
+ name: Python CI
50
+ runs-on: ubuntu-latest
51
+ steps:
52
+ - uses: actions/checkout@v4
53
+ - name: Detect Python project
54
+ id: detect
55
+ run: |
56
+ if [ -f requirements.txt ] || [ -f pyproject.toml ]; then echo "has_py=true" >> $GITHUB_OUTPUT; else echo "has_py=false" >> $GITHUB_OUTPUT; fi
57
+ - name: Setup Python
58
+ if: steps.detect.outputs.has_py == true
59
+ uses: actions/setup-python@v5
60
+ with:
61
+ python-version: 3.11
62
+ cache: pip
63
+ - name: Install deps
64
+ if: steps.detect.outputs.has_py == true
65
+ run: |
66
+ python -m pip install --upgrade pip
67
+ if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
68
+ pip install ruff pytest mypy pip-audit
69
+ - name: Format & Lint
70
+ if: steps.detect.outputs.has_py == true
71
+ run: |
72
+ ruff format --check . || true
73
+ ruff check .
74
+ - name: Type Check
75
+ if: steps.detect.outputs.has_py == true
76
+ run: mypy . || true
77
+ - name: Test
78
+ if: steps.detect.outputs.has_py == true
79
+ run: pytest -q
80
+ - name: Audit (non-blocking)
81
+ if: steps.detect.outputs.has_py == true
82
+ run: pip-audit || true
83
+
84
+ gates:
85
+ name: Quality Gates
86
+ runs-on: ubuntu-latest
87
+ needs: [node, python]
88
+ steps:
89
+ - name: All language jobs completed
90
+ run: echo "Downstream jobs succeeded"
@@ -0,0 +1,33 @@
1
+
2
+ name: Refresh Project Tree
3
+
4
+ on:
5
+ schedule:
6
+ - cron: 17 3 CODEOWNERS context CONTRIBUTING.md docs infra prompts scripts SECURITY.md services src templates tests tools CODEOWNERS context CONTRIBUTING.md docs infra prompts scripts SECURITY.md services src templates tests tools *
7
+ workflow_dispatch: {}
8
+
9
+ permissions:
10
+ contents: write
11
+
12
+ jobs:
13
+ refresh:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - name: Generate project tree
18
+ run: |
19
+ TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)
20
+ echo "# Project Tree (snapshot)" > context/project_tree.md
21
+ echo "_Generated: ${TS}_" >> context/project_tree.md
22
+ echo >> context/project_tree.md
23
+ echo >> context/project_tree.md
24
+ - name: Commit changes if any
25
+ run: |
26
+ git config user.name "github-actions"
27
+ git config user.email "actions@github.com"
28
+ git add context/project_tree.md || true
29
+ if ! git diff --cached --quiet; then
30
+ git commit -m "chore(context): refresh project_tree snapshot" && git push;
31
+ else
32
+ echo "No changes to commit.";
33
+ fi
@@ -0,0 +1,5 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.pyc
4
+ agent_pack.tgz
5
+ *.bak
@@ -0,0 +1,17 @@
1
+
2
+ title = "paircoder gitleaks config"
3
+
4
+ [allowlist]
5
+ description = "Allowed patterns"
6
+ files = [
7
+ "^context/project_tree.md$",
8
+ "^docs/adr/",
9
+ ]
10
+
11
+ [allowlist.regexes]
12
+ description = "Common false positives"
13
+ regexes = [
14
+ "(?i)example(_|-)secret",
15
+ "(?i)dummy(token|key)",
16
+ "\b[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\b",
17
+ ]
@@ -0,0 +1,38 @@
1
+
2
+ repos:
3
+ - repo: https://github.com/pre-commit/pre-commit-hooks
4
+ rev: v4.6.0
5
+ hooks:
6
+ - id: check-yaml
7
+ - id: check-json
8
+ - id: check-toml
9
+ - id: end-of-file-fixer
10
+ - id: trailing-whitespace
11
+ - repo: https://github.com/astral-sh/ruff-pre-commit
12
+ rev: v0.5.7
13
+ hooks:
14
+ - id: ruff
15
+ args: ["--fix"]
16
+ - id: ruff-format
17
+ - repo: https://github.com/igorshubovych/markdownlint-cli
18
+ rev: v0.42.0
19
+ hooks:
20
+ - id: markdownlint
21
+ args: ["--fix"]
22
+ - repo: https://github.com/pre-commit/mirrors-prettier
23
+ rev: v3.3.3
24
+ hooks:
25
+ - id: prettier
26
+ additional_dependencies: []
27
+ - repo: https://github.com/pre-commit/mirrors-eslint
28
+ rev: v9.9.1
29
+ hooks:
30
+ - id: eslint
31
+ additional_dependencies: []
32
+ files: \.(js|jsx|ts|tsx)$
33
+ args: ["--max-warnings", "0"]
34
+ - repo: local
35
+ hooks:
36
+ - id: gitleaks-scan
37
+ name: gitleaks scan
38
+ entry: bash -c gitleaks detect --no-banner --redact --config .gitleaks.toml
@@ -0,0 +1,9 @@
1
+
2
+ * @{{cookiecutter.owner_gh_handle}}
3
+ /context/* @{{cookiecutter.owner_gh_handle}} @{{cookiecutter.architect_gh_handle}}
4
+ /scripts/* @{{cookiecutter.owner_gh_handle}} @{{cookiecutter.build_gh_handle}}
5
+ /.github/* @{{cookiecutter.owner_gh_handle}} @{{cookiecutter.build_gh_handle}}
6
+ /prompts/* @{{cookiecutter.owner_gh_handle}} @{{cookiecutter.architect_gh_handle}}
7
+ /tests/** @{{cookiecutter.qa_gh_handle}} @{{cookiecutter.owner_gh_handle}}
8
+ /infra/** @{{cookiecutter.sre_gh_handle}} @{{cookiecutter.owner_gh_handle}}
9
+ /schemas/** @{{cookiecutter.architect_gh_handle}} @{{cookiecutter.owner_gh_handle}}
@@ -0,0 +1,35 @@
1
+
2
+ # Contributing Guide
3
+
4
+ Thanks for contributing! This repo is optimized for AI pair coding and human review.
5
+
6
+ ## Branching & Commits
7
+ - Branch from `main` using: `feature/<short-goal>`, `refactor/<module>`, or `fix/<ticket>`.
8
+ - Use Conventional Commits (feat, fix, refactor, docs, test, chore, build, ci).
9
+
10
+ ## Local Dev & CI
11
+ - Run local CI before pushing:
12
+ ```bash
13
+ scripts/ci_local.sh
14
+ ```
15
+ - Add/adjust tests **before** behavior changes.
16
+ - Keep diffs small and focused; open PRs early.
17
+
18
+ ## Context Discipline (MANDATORY)
19
+ - `/context/*` is canonical for agent runs. Update the Context Sync block in `context/development.md` after each change:
20
+ ```
21
+ ## Context Sync (AUTO-UPDATED)
22
+ Overall goal is: <PRIMARY GOAL>
23
+ Last action was: <what changed and why> (commit SHA)
24
+ Next action will be: <smallest valuable step with owner>
25
+ Blockers/Risks: <if any>
26
+ ```
27
+
28
+ ## Pull Requests
29
+ - Use the PR template (risk, test plan, rollback, context diff).
30
+ - Public API/infra changes require an ADR under `/docs/adr/`.
31
+ - High-risk PRs require CODEOWNERS sign-off.
32
+
33
+ ## Secrets & Data Safety
34
+ - Never commit secrets; provide `.env.example`.
35
+ - Do not include binaries/media in agent packs; maintain `.agentpackignore`.
@@ -0,0 +1,14 @@
1
+
2
+ # Security Policy
3
+
4
+ ## Supported Versions
5
+ We aim to keep `main` secure. Fixes are backported to the latest minor.
6
+
7
+ ## Reporting a Vulnerability
8
+ - Email: security@<your-domain> (or open a private GitHub security advisory)
9
+ - Include: affected versions/commit, reproduction, impact, proposed severity.
10
+ - We acknowledge within 2 business days and update until resolution.
11
+
12
+ ## Handling Sensitive Data
13
+ - No secrets in repo or agent packs.
14
+ - Use redacted fixtures/synthetic data for tests and context.
@@ -0,0 +1,6 @@
1
+ # Agents Guide\n\nThis project uses a **Context Loop**. Always keep these fields current:\n\n- **Overall goal is:** Single-sentence mission\n- **Last action was:** What just completed\n- **Next action will be:** The very next step\n- **Blockers:** Known issues or decisions needed\n\n### Working Rules for Agents\n- Do not modify or examine ignored directories (see `.agentpackignore`). Assume large assets exist even if excluded.\n- Prefer minimal, reversible changes.\n- After committing code, run `bpsai-pair context-sync` to update the loop.\n- Request a new context pack when the tree or docs change significantly.\n\n### Context Pack\nRun `bpsai-pair pack --out agent_pack.tgz` and upload to your session.\n
2
+ ---
3
+
4
+ ## Branch Discipline
5
+ - Use `--type feature|fix|refactor` when creating features.
6
+ - Conventional Commits recommended.