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.
- bpsai_pair/__init__.py +25 -0
- bpsai_pair/__main__.py +4 -0
- bpsai_pair/adapters.py +9 -0
- bpsai_pair/cli.py +514 -0
- bpsai_pair/config.py +310 -0
- bpsai_pair/data/cookiecutter-paircoder/cookiecutter.json +12 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.agentpackignore +1 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.editorconfig +17 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.github/PULL_REQUEST_TEMPLATE.md +47 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.github/workflows/ci.yml +90 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.github/workflows/project_tree.yml +33 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.gitignore +5 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.gitleaks.toml +17 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.pre-commit-config.yaml +38 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/CODEOWNERS +9 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/CONTRIBUTING.md +35 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/SECURITY.md +14 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/context/agents.md +6 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/context/agents.md.bak +196 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/context/development.md +1 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/context/development.md.bak +10 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/context/directory_notes/.gitkeep +1 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/context/project_tree.md +7 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/prompts/deep_research.yml +28 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/prompts/implementation.yml +25 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/prompts/roadmap.yml +14 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/scripts/README.md +11 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/src/.gitkeep +1 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/templates/adr.md +19 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/templates/directory_note.md +17 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/tests/example_contract/README.md +3 -0
- bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/tests/example_integration/README.md +3 -0
- bpsai_pair/init_bundled_cli.py +47 -0
- bpsai_pair/jsonio.py +6 -0
- bpsai_pair/ops.py +451 -0
- bpsai_pair/pyutils.py +26 -0
- bpsai_pair/utils.py +11 -0
- bpsai_pair-0.2.0.dist-info/METADATA +29 -0
- bpsai_pair-0.2.0.dist-info/RECORD +42 -0
- bpsai_pair-0.2.0.dist-info/WHEEL +5 -0
- bpsai_pair-0.2.0.dist-info/entry_points.txt +3 -0
- bpsai_pair-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# Agents Guide — AI Pair Coding Playbook
|
|
2
|
+
|
|
3
|
+
**Purpose:** Make GPT-5 / Claude / CodeX effective partners for {{ cookiecutter.primary_goal }} while improving modularity, maintainability, and testability.
|
|
4
|
+
|
|
5
|
+
**Audience:** Engineers, Tech Leads, and AI Agents connected to this repo.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 0) Ground Rules (READ FIRST)
|
|
10
|
+
|
|
11
|
+
* **Single Source of Truth:** This repository and the files in `/context` are canonical for all agent runs.
|
|
12
|
+
* **Safety First:** No destructive ops without backups and a PR. Agents must create `*.bak` or use Git branches.
|
|
13
|
+
* **Tests Before Changes:** Add/extend tests that fail *before* implementing a fix/refactor.
|
|
14
|
+
* **Small, Reviewable Diffs:** Keep changes scoped; open PRs early; link to the relevant roadmap task.
|
|
15
|
+
* **Update Context Every Run:** Always persist “Overall/Last/Next” (see §6) after actions.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 1) Repo Layout & Context Discipline
|
|
20
|
+
|
|
21
|
+
> Keep the agent’s attention on code that matters. Avoid token waste and blind spots.
|
|
22
|
+
|
|
23
|
+
* **Project Tree (authoritative sketch):**
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
.
|
|
27
|
+
├─ /src # Application code
|
|
28
|
+
├─ /tests # Unit/integration tests
|
|
29
|
+
├─ /services # External adapters, API clients
|
|
30
|
+
├─ /infra # IaC / deployment (optional)
|
|
31
|
+
├─ /docs # Human-readable docs
|
|
32
|
+
├─ /context # Agent context files (canonical)
|
|
33
|
+
│ ├─ development.md
|
|
34
|
+
│ ├─ agents.md
|
|
35
|
+
│ ├─ project_tree.md
|
|
36
|
+
│ └─ directory_notes/
|
|
37
|
+
├─ /assets/images # Large/media (EXCLUDED from agent context)
|
|
38
|
+
└─ ...
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
* **Explicit Exclusions:** `/assets/images`, `/dist`, `/build`, `/node_modules`, binaries, large JSON/CSV.
|
|
42
|
+
Agents must **assume these exist** and avoid recommending moves/rewrites.
|
|
43
|
+
|
|
44
|
+
* **Directory Notes (optional but powerful):**
|
|
45
|
+
Add `/context/directory_notes/<dir>.md` with:
|
|
46
|
+
|
|
47
|
+
* Purpose, entry points, invariants, dependency direction.
|
|
48
|
+
* “Do/Don’t” for this directory.
|
|
49
|
+
* Local glossary (domain terms, DTOs).
|
|
50
|
+
* Known pitfalls.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 2) Branching & PR Conventions
|
|
55
|
+
|
|
56
|
+
* **Branch names:** `feature/<short-goal>` or `refactor/<module>` or `fix/<ticket-id>`
|
|
57
|
+
* **Create branch from:** `main`
|
|
58
|
+
* **PR template must include:**
|
|
59
|
+
|
|
60
|
+
* Goal link to `<PHASE N TASK>`
|
|
61
|
+
* Risk level (Low/Med/High)
|
|
62
|
+
* Test plan (automated + manual)
|
|
63
|
+
* Rollback plan
|
|
64
|
+
* Context update diff (what changed in `/context` files)
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 3) Operating Modes
|
|
69
|
+
|
|
70
|
+
### A) Non-Scripted (Live Collaboration)
|
|
71
|
+
|
|
72
|
+
1. Create branch: `git checkout -b feature/<FEATURE>`
|
|
73
|
+
2. Connect agent (Claude or GPT-5) to repo URL.
|
|
74
|
+
3. Attach context: `/context/development.md`, `/context/agents.md`, relevant `/context/directory_notes/*`.
|
|
75
|
+
4. **Prompt:**
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
PHASE 1 GOAL: <PHASE 1 GOAL>
|
|
79
|
+
Constraints: preserve public APIs, add tests first, no destructive ops.
|
|
80
|
+
Output: stepwise plan + minimal diffs per step.
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### B) Scripted (One-Pass Implementation)
|
|
84
|
+
|
|
85
|
+
1. Create branch: `git checkout -b feature/<FEATURE>`
|
|
86
|
+
2. Attach **only** relevant context files.
|
|
87
|
+
3. **Prompt:**
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
Create a comprehensive script/commit plan to accomplish <PHASE 1 GOAL> in one pass.
|
|
91
|
+
Requirements:
|
|
92
|
+
- Zero breakage; create backups where needed.
|
|
93
|
+
- Generate/modify tests first to capture intended behavior.
|
|
94
|
+
- Respect repo conventions, linting, and formatting.
|
|
95
|
+
- Produce: (a) ordered commit plan, (b) code patches, (c) updated docs, (d) updated context (see §6).
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 4) Canonical Prompts
|
|
101
|
+
|
|
102
|
+
### 4.1 Deep Research (Kickoff)
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
You are a staff-level engineer embedded in this codebase.
|
|
106
|
+
Objective: Produce a comprehensive plan to improve modularity, maintainability, and achieve {{ cookiecutter.primary_goal }}.
|
|
107
|
+
Deliverables:
|
|
108
|
+
- Architecture review (current vs. target), explicit trade-offs.
|
|
109
|
+
- Refactoring map (by module), dependency inversion opportunities, interface boundaries.
|
|
110
|
+
- Test posture upgrade plan (unit/integration/contract), coverage deltas.
|
|
111
|
+
- Risks, complexity hotspots, and rollback strategies.
|
|
112
|
+
- 3-phase roadmap with measurable outcomes.
|
|
113
|
+
Constraints:
|
|
114
|
+
- Respect exclusions listed in agents.md.
|
|
115
|
+
- Assume assets exist where excluded.
|
|
116
|
+
- Prefer small, reversible changes; maximize seam creation for safe refactors.
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### 4.2 Roadmap → Files
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
Convert the roadmap into:
|
|
123
|
+
- /context/development.md (engineering tasks, test plans, risks)
|
|
124
|
+
- /context/agents.md (this file; update Operating Modes, Prompts if needed)
|
|
125
|
+
Ensure clear Phase 1/2/3 breakdown with milestone checklists and acceptance criteria.
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 4.3 Implementation Guardrails (per task)
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
For TASK: <task-name>
|
|
132
|
+
- Propose minimal diff solution.
|
|
133
|
+
- Add/adjust tests first to lock behavior.
|
|
134
|
+
- Provide code patches and commands to run tests/lints.
|
|
135
|
+
- Call out risks + rollback.
|
|
136
|
+
- Update context loop (Overall/Last/Next).
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## 5) Testing & Quality Gates
|
|
142
|
+
|
|
143
|
+
* **Unit tests:** focus on pure logic and interfaces.
|
|
144
|
+
* **Integration tests:** external boundaries (DB, queues, HTTP) via testcontainers/mocks.
|
|
145
|
+
* **Contract tests:** for service clients with provider/consumer pacts if applicable.
|
|
146
|
+
* **Coverage targets:** raise or maintain ≥ <TARGET>% lines/branches where practical.
|
|
147
|
+
* **CI gates:** lint, type-check, build, test, basic security scan (SAST/dep audit).
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 6) Context Loop (Mandatory)
|
|
152
|
+
|
|
153
|
+
Agents **must** persist this block at the end of every session in `/context/development.md` (and in any relevant directory note):
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
## Context Sync (AUTO-UPDATED)
|
|
157
|
+
Overall goal is: {{ cookiecutter.primary_goal }}
|
|
158
|
+
Last action was: <what changed and why> (commit SHA if available)
|
|
159
|
+
Next action will be: <smallest valuable step with owner>
|
|
160
|
+
Blockers/Risks: <if any>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## 7) Failure Modes & Rollback
|
|
166
|
+
|
|
167
|
+
* **If tests fail:** revert last commit or apply backup. Fix tests first, then code.
|
|
168
|
+
* **If unintended API change:** restore interface, add regression test.
|
|
169
|
+
* **If scope creep:** park in `Phase N Backlog` with rationale.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## 8) Example Exclusion Prompt
|
|
174
|
+
|
|
175
|
+
> *Drop into your agent prompt when large dirs are omitted.*
|
|
176
|
+
|
|
177
|
+
“Relevant image/media assets exist under `/assets/images` but are intentionally excluded from your context to conserve tokens. **Do not** propose changes that relocate, inline, or re-encode assets. Assume paths referenced in code are valid. Focus your analysis on `/src`, `/services`, and `/tests`. If a change seems to require asset inspection, propose an interface-level abstraction instead.”
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 9) Definitions
|
|
182
|
+
|
|
183
|
+
* **Seam:** a point in code where behavior can be changed without editing the code (e.g., via interface, DI, adapter).
|
|
184
|
+
* **Backwards compatibility window:** period where both old and new APIs coexist with deprecation notices.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## 10) Tools & Commands (fill per repo)
|
|
189
|
+
|
|
190
|
+
* **Install:** `<cmd>`
|
|
191
|
+
* **Format/Lint:** `<cmd>`
|
|
192
|
+
* **Test (unit):** `<cmd>`
|
|
193
|
+
* **Test (integration):** `<cmd>`
|
|
194
|
+
* **Type check:** `<cmd>`
|
|
195
|
+
* **Local CI bundle:** `<cmd>`
|
|
196
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Development Log\n\n**Phase:** (set by first feature)\n**Primary Goal:** (set by first feature)\n\n## Context Sync (AUTO-UPDATED)\n\n- **Overall goal is:** (set by feature)\n- **Last action was:** (set by feature)\n- **Next action will be:** (set by feature)\n- **Blockers:** (set by feature)\n
|
bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/context/development.md.bak
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Development Log
|
|
2
|
+
|
|
3
|
+
**Phase:** (set by first feature)
|
|
4
|
+
**Primary Goal:** (set by first feature)
|
|
5
|
+
|
|
6
|
+
## Context Sync (AUTO-UPDATED)
|
|
7
|
+
|
|
8
|
+
- **Overall goal is:** (set by feature)
|
|
9
|
+
- **Last action was:** (set by feature)
|
|
10
|
+
- **Next action will be:** (set by feature)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/prompts/deep_research.yml
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
id: deep_research
|
|
3
|
+
version: 0.1.0
|
|
4
|
+
inputs:
|
|
5
|
+
primary_goal: "<PRIMARY GOAL>"
|
|
6
|
+
exclusions: ["assets/images", "dist", "build", "node_modules"]
|
|
7
|
+
assumptions:
|
|
8
|
+
- Excluded paths exist and are valid.
|
|
9
|
+
- Prefer reversible changes and seam creation.
|
|
10
|
+
output:
|
|
11
|
+
- architecture_review
|
|
12
|
+
- refactor_map
|
|
13
|
+
- test_upgrade_plan
|
|
14
|
+
- risks_and_rollback
|
|
15
|
+
- three_phase_roadmap
|
|
16
|
+
prompt: |
|
|
17
|
+
You are a staff-level engineer embedded in this codebase.
|
|
18
|
+
Objective: Improve modularity, maintainability, and achieve {{ primary_goal }}.
|
|
19
|
+
Deliverables:
|
|
20
|
+
- Architecture review (current vs target) with trade-offs
|
|
21
|
+
- Refactoring map by module, DI boundaries, interfaces
|
|
22
|
+
- Test posture upgrade plan (unit/integration/contract)
|
|
23
|
+
- Risks, hotspots, rollback strategies
|
|
24
|
+
- 3-phase roadmap with measurable outcomes
|
|
25
|
+
Constraints:
|
|
26
|
+
- Respect exclusions: {{ exclusions | join(, ) }}
|
|
27
|
+
- Assume excluded assets exist
|
|
28
|
+
- Prefer small, reversible changes; maximize seams
|
bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/prompts/implementation.yml
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
|
|
2
|
+
id: implementation
|
|
3
|
+
version: 0.1.0
|
|
4
|
+
inputs:
|
|
5
|
+
phase_goal: "<PHASE 1 GOAL>"
|
|
6
|
+
guardrails:
|
|
7
|
+
- "Preserve public APIs unless explicitly approved"
|
|
8
|
+
- "Add/adjust tests first to lock behavior"
|
|
9
|
+
- "No destructive ops; create backups or checkpoint commits"
|
|
10
|
+
output:
|
|
11
|
+
- ordered_commit_plan
|
|
12
|
+
- code_patches
|
|
13
|
+
- updated_docs
|
|
14
|
+
- updated_context
|
|
15
|
+
prompt: |
|
|
16
|
+
Create a comprehensive commit plan to accomplish {{ phase_goal }} in one pass.
|
|
17
|
+
Respect guardrails:
|
|
18
|
+
{% for g in guardrails %}
|
|
19
|
+
- {{ g }}
|
|
20
|
+
{% endfor %}
|
|
21
|
+
Produce:
|
|
22
|
+
- Ordered commits with messages
|
|
23
|
+
- Patches per commit
|
|
24
|
+
- Doc updates
|
|
25
|
+
- Context Loop update (Overall/Last/Next)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
|
|
2
|
+
id: roadmap
|
|
3
|
+
version: 0.1.0
|
|
4
|
+
inputs:
|
|
5
|
+
primary_goal: "<PRIMARY GOAL>"
|
|
6
|
+
coverage_target: "<TARGET>%"
|
|
7
|
+
output:
|
|
8
|
+
- development_md
|
|
9
|
+
- agents_md_update
|
|
10
|
+
prompt: |
|
|
11
|
+
Convert the accepted plan into two files:
|
|
12
|
+
1) /context/development.md — engineering tasks, tests, risks with Phase 1/2/3 breakdown and acceptance criteria; coverage target {{ coverage_target }}.
|
|
13
|
+
2) /context/agents.md — update Operating Modes/Prompts if needed.
|
|
14
|
+
Ensure milestones are measurable. Keep diffs small and reversible.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Scripts directory (intentionally minimal)
|
|
2
|
+
|
|
3
|
+
This project uses the **PairCoder CLI** (Python) — no Bash scripts required.
|
|
4
|
+
Common commands:
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
bpsai-pair-init
|
|
8
|
+
bpsai-pair feature <name> --type feature|fix|refactor --primary "..." --phase "..."
|
|
9
|
+
bpsai-pair pack --out agent_pack.tgz
|
|
10
|
+
bpsai-pair context-sync --last "..." --next "..." --blockers "..."
|
|
11
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
# Architecture Decision Record Template
|
|
3
|
+
|
|
4
|
+
**Title:** <ADR Title>
|
|
5
|
+
|
|
6
|
+
**Status:** Draft | Proposed | Accepted | Deprecated
|
|
7
|
+
|
|
8
|
+
**Context:**
|
|
9
|
+
_<What is the issue that prompted this decision? Background, forces, requirements>_
|
|
10
|
+
|
|
11
|
+
**Decision:**
|
|
12
|
+
_<What is the chosen solution? Justify why._>
|
|
13
|
+
|
|
14
|
+
**Alternatives Considered:**
|
|
15
|
+
- _Option A... (pros/cons)_
|
|
16
|
+
- _Option B..._
|
|
17
|
+
|
|
18
|
+
**Consequences:**
|
|
19
|
+
_<What becomes easier or harder to do because of this decision? Any follow-up actions?>_
|
bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/templates/directory_note.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
|
|
2
|
+
# Directory Note — <dir>
|
|
3
|
+
|
|
4
|
+
**Purpose:** <why this directory exists>
|
|
5
|
+
**Entry Points:** <files/modules used externally>
|
|
6
|
+
**Invariants:** <constraints, contracts, side effects>
|
|
7
|
+
**Dependencies:** <allowed deps, forbidden deps>
|
|
8
|
+
|
|
9
|
+
## Do / Don’t
|
|
10
|
+
- Do: <guideline>
|
|
11
|
+
- Don’t: <pitfall>
|
|
12
|
+
|
|
13
|
+
## Gotchas
|
|
14
|
+
- <common issues>
|
|
15
|
+
|
|
16
|
+
## Glossary
|
|
17
|
+
- <term>: <definition>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import os, sys, stat, shutil
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
try:
|
|
5
|
+
from importlib.resources import files as res_files
|
|
6
|
+
except ImportError:
|
|
7
|
+
from importlib_resources import files as res_files # py<=3.8 fallback
|
|
8
|
+
|
|
9
|
+
APP_NAME = "bpsai-pair-init"
|
|
10
|
+
|
|
11
|
+
def copytree_non_destructive(src: Path, dst: Path) -> None:
|
|
12
|
+
# copy files/dirs only if missing; never overwrite existing files
|
|
13
|
+
for root, dirs, files in os.walk(src):
|
|
14
|
+
rel = Path(root).relative_to(src)
|
|
15
|
+
out_dir = dst / rel
|
|
16
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
17
|
+
for name in files:
|
|
18
|
+
s = Path(root) / name
|
|
19
|
+
d = out_dir / name
|
|
20
|
+
if not d.exists():
|
|
21
|
+
d.parent.mkdir(parents=True, exist_ok=True)
|
|
22
|
+
shutil.copy2(s, d)
|
|
23
|
+
# make scripts executable
|
|
24
|
+
scripts_dir = dst / "scripts"
|
|
25
|
+
if scripts_dir.exists():
|
|
26
|
+
for p in scripts_dir.glob("*.sh"):
|
|
27
|
+
mode = p.stat().st_mode
|
|
28
|
+
p.chmod(mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
|
|
29
|
+
|
|
30
|
+
def main(argv: list[str] | None = None) -> int:
|
|
31
|
+
argv = argv or sys.argv[1:]
|
|
32
|
+
# Resolve packaged template '{{cookiecutter.project_slug}}'
|
|
33
|
+
pkg_root = res_files("bpsai_pair") / "data" / "cookiecutter-paircoder"
|
|
34
|
+
# Find the one subdir under cookiecutter-paircoder (the cookiecutter slug dir)
|
|
35
|
+
candidates = [p for p in pkg_root.iterdir() if p.is_dir()]
|
|
36
|
+
if not candidates:
|
|
37
|
+
print(f"[{APP_NAME}] ERROR: packaged template not found", file=sys.stderr)
|
|
38
|
+
return 1
|
|
39
|
+
template_root = candidates[0] # '{{cookiecutter.project_slug}}'
|
|
40
|
+
# copy into current directory without clobber
|
|
41
|
+
dst = Path(".").resolve()
|
|
42
|
+
copytree_non_destructive(Path(template_root), dst)
|
|
43
|
+
print(f"[{APP_NAME}] Initialized repo with bundled scaffolding (non-destructive). Review diffs and commit.")
|
|
44
|
+
return 0
|
|
45
|
+
|
|
46
|
+
if __name__ == "__main__":
|
|
47
|
+
raise SystemExit(main())
|