gwc-pybundle 0.4.2__tar.gz → 1.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.

Potentially problematic release.


This version of gwc-pybundle might be problematic. Click here for more details.

Files changed (67) hide show
  1. gwc_pybundle-1.4.1/PKG-INFO +857 -0
  2. gwc_pybundle-1.4.1/README.md +808 -0
  3. gwc_pybundle-1.4.1/gwc_pybundle.egg-info/PKG-INFO +857 -0
  4. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/gwc_pybundle.egg-info/SOURCES.txt +22 -1
  5. gwc_pybundle-1.4.1/pybundle/cli.py +365 -0
  6. gwc_pybundle-1.4.1/pybundle/context.py +362 -0
  7. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/doctor.py +47 -0
  8. gwc_pybundle-1.4.1/pybundle/filters.py +178 -0
  9. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/manifest.py +2 -3
  10. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/packaging.py +9 -5
  11. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/policy.py +44 -88
  12. gwc_pybundle-1.4.1/pybundle/profiles.py +276 -0
  13. gwc_pybundle-1.4.1/pybundle/roadmap_model.py +42 -0
  14. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/roadmap_scan.py +55 -22
  15. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/runner.py +8 -2
  16. gwc_pybundle-1.4.1/pybundle/steps/__init__.py +26 -0
  17. gwc_pybundle-1.4.1/pybundle/steps/bandit.py +72 -0
  18. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/steps/compileall.py +2 -2
  19. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/steps/copy_pack.py +108 -115
  20. gwc_pybundle-1.4.1/pybundle/steps/coverage.py +101 -0
  21. gwc_pybundle-1.4.1/pybundle/steps/cprofile_step.py +155 -0
  22. gwc_pybundle-1.4.1/pybundle/steps/dependency_sizes.py +120 -0
  23. gwc_pybundle-1.4.1/pybundle/steps/duplication.py +94 -0
  24. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/steps/handoff_md.py +7 -6
  25. gwc_pybundle-1.4.1/pybundle/steps/import_time.py +165 -0
  26. gwc_pybundle-1.4.1/pybundle/steps/interrogate.py +84 -0
  27. gwc_pybundle-1.4.1/pybundle/steps/license_scan.py +96 -0
  28. gwc_pybundle-1.4.1/pybundle/steps/line_profiler.py +108 -0
  29. gwc_pybundle-1.4.1/pybundle/steps/memory_profile.py +173 -0
  30. gwc_pybundle-1.4.1/pybundle/steps/mutation_testing.py +136 -0
  31. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/steps/mypy.py +2 -2
  32. gwc_pybundle-1.4.1/pybundle/steps/pip_audit.py +45 -0
  33. gwc_pybundle-1.4.1/pybundle/steps/pipdeptree.py +61 -0
  34. gwc_pybundle-1.4.1/pybundle/steps/pylance.py +562 -0
  35. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/steps/pytest.py +2 -2
  36. gwc_pybundle-1.4.1/pybundle/steps/radon.py +121 -0
  37. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/steps/rg_scans.py +2 -2
  38. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/steps/roadmap.py +50 -55
  39. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/steps/ruff.py +3 -3
  40. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/steps/shell.py +11 -4
  41. gwc_pybundle-1.4.1/pybundle/steps/slow_tests.py +170 -0
  42. gwc_pybundle-1.4.1/pybundle/steps/test_flakiness.py +172 -0
  43. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/steps/tree.py +12 -32
  44. gwc_pybundle-1.4.1/pybundle/steps/unused_deps.py +112 -0
  45. gwc_pybundle-1.4.1/pybundle/steps/vulture.py +82 -0
  46. gwc_pybundle-1.4.1/pybundle/tools.py +63 -0
  47. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pyproject.toml +3 -3
  48. gwc_pybundle-0.4.2/PKG-INFO +0 -476
  49. gwc_pybundle-0.4.2/README.md +0 -427
  50. gwc_pybundle-0.4.2/gwc_pybundle.egg-info/PKG-INFO +0 -476
  51. gwc_pybundle-0.4.2/pybundle/cli.py +0 -228
  52. gwc_pybundle-0.4.2/pybundle/context.py +0 -232
  53. gwc_pybundle-0.4.2/pybundle/profiles.py +0 -146
  54. gwc_pybundle-0.4.2/pybundle/roadmap_model.py +0 -38
  55. gwc_pybundle-0.4.2/pybundle/tools.py +0 -7
  56. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/LICENSE.md +0 -0
  57. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/gwc_pybundle.egg-info/dependency_links.txt +0 -0
  58. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/gwc_pybundle.egg-info/entry_points.txt +0 -0
  59. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/gwc_pybundle.egg-info/top_level.txt +0 -0
  60. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/__init__.py +0 -0
  61. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/__main__.py +0 -0
  62. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/root_detect.py +0 -0
  63. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/steps/base.py +0 -0
  64. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/steps/context_expand.py +0 -0
  65. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/steps/error_refs.py +0 -0
  66. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/pybundle/steps/repro_md.py +0 -0
  67. {gwc_pybundle-0.4.2 → gwc_pybundle-1.4.1}/setup.cfg +0 -0
@@ -0,0 +1,857 @@
1
+ Metadata-Version: 2.4
2
+ Name: gwc-pybundle
3
+ Version: 1.4.1
4
+ Summary: Deterministic Python project context bundling for humans, automation, and AI
5
+ Author-email: Jessica Brown <jessica@codenamejessica.com>
6
+ License: The MIT License (MIT)
7
+ =====================
8
+
9
+ Copyright © 2025 Jessica Brown
10
+
11
+ Permission is hereby granted, free of charge, to any person
12
+ obtaining a copy of this software and associated documentation
13
+ files (the “Software”), to deal in the Software without
14
+ restriction, including without limitation the rights to use,
15
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ copies of the Software, and to permit persons to whom the
17
+ Software is furnished to do so, subject to the following
18
+ conditions:
19
+
20
+ The above copyright notice and this permission notice shall be
21
+ included in all copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
24
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
25
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
27
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
28
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
30
+ OTHER DEALINGS IN THE SOFTWARE.
31
+ Project-URL: Homepage, https://github.com/girls-whocode/pybundle
32
+ Project-URL: Repository, https://github.com/girls-whocode/pybundle
33
+ Project-URL: Issues, https://github.com/girls-whocode/pybundle/issues
34
+ Classifier: Development Status :: 5 - Production/Stable
35
+ Classifier: Intended Audience :: Developers
36
+ Classifier: License :: OSI Approved :: MIT License
37
+ Classifier: Programming Language :: Python :: 3
38
+ Classifier: Programming Language :: Python :: 3.9
39
+ Classifier: Programming Language :: Python :: 3.10
40
+ Classifier: Programming Language :: Python :: 3.11
41
+ Classifier: Programming Language :: Python :: 3.12
42
+ Classifier: Topic :: Software Development :: Build Tools
43
+ Classifier: Topic :: Software Development :: Debuggers
44
+ Classifier: Topic :: Software Development :: Quality Assurance
45
+ Requires-Python: >=3.9
46
+ Description-Content-Type: text/markdown
47
+ License-File: LICENSE.md
48
+ Dynamic: license-file
49
+
50
+ # 🧳 pybundle ![PyPI - Version](https://img.shields.io/pypi/v/gwc-pybundle)
51
+
52
+ ![GitHub Release Date](https://img.shields.io/github/release-date/girls-whocode/pybundle?color=orange)
53
+
54
+ [![Python versions](https://img.shields.io/pypi/pyversions/gwc-pybundle.svg?color=3776AB)](https://pypi.org/project/gwc-pybundle/)
55
+ [![License](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE.md)
56
+ [![PyPI Downloads](https://static.pepy.tech/personalized-badge/gwc-pybundle?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLUE&right_color=GREY&left_text=downloads)](https://pepy.tech/projects/gwc-pybundle)
57
+ ![GitHub Sponsors](https://img.shields.io/github/sponsors/girls-whocode?color=ec4899)
58
+
59
+ [![CI](https://github.com/girls-whocode/pybundle/actions/workflows/publish.yml/badge.svg?color=fb923c)](https://github.com/girls-whocode/pybundle/actions)
60
+ [![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-14b8a6.svg)](https://github.com/astral-sh/ruff)
61
+ [![Type checked](https://img.shields.io/badge/type%20checked-mypy-0ea5e9.svg)](https://mypy-lang.org/)
62
+ ![Commit Activity](https://img.shields.io/github/commit-activity/t/girls-whocode/pybundle?color=f59e0b)
63
+
64
+
65
+ **pybundle** is a deterministic, automation-friendly CLI that captures Python project context into a single, reproducible bundle — ideal for debugging, CI artifacts, audits, and AI-assisted workflows.
66
+
67
+ It produces **machine-readable outputs first**, with optional human-readable summaries layered on top.
68
+
69
+ > Think “`git archive` + diagnostics + metadata”, without guessing or heuristics.
70
+
71
+ > **Note:** The PyPI package name is `gwc-pybundle`, but the tool is installed and used as `pybundle`.
72
+ ---
73
+
74
+ ## 🧠 Why pybundle exists
75
+
76
+ Modern software development compresses what used to be entire teams into a single role.
77
+
78
+ Today, one developer is often responsible for:
79
+ - application code
80
+ - build systems
81
+ - test tooling
82
+ - deployment logic
83
+ - CI/CD behavior
84
+ - environment differences
85
+ - security implications
86
+ - and increasingly, AI-assisted workflows
87
+
88
+ The problem is no longer *how* to write code.
89
+
90
+ It’s answering:
91
+
92
+ > **“Why is this system behaving the way it is?”**
93
+
94
+ That question is hard to answer when:
95
+ - context is scattered
96
+ - tooling output is ephemeral
97
+ - environment details are lost
98
+ - source snapshots are incomplete or noisy
99
+
100
+ AI didn’t create this problem - it exposed it.
101
+
102
+ Large language models don’t fail because they lack intelligence.
103
+ They fail because we give them **uncurated context**.
104
+
105
+ Humans don’t fail because they can’t debug.
106
+ They fail because the **cost of reconstructing context** exceeds the time they have.
107
+
108
+ **pybundle exists to reduce context debt.**
109
+
110
+ It captures *what matters*, ignores what doesn’t, and produces a deterministic artifact that explains:
111
+ - what code exists
112
+ - what tools ran
113
+ - what environment was used
114
+ - and why the outputs exist
115
+
116
+ For humans, automation, and AI alike.
117
+
118
+ ---
119
+
120
+ ## ✨ Features
121
+
122
+ * 📦 **Single archive output** (`.zip` or `.tar.gz`)
123
+ * 🧠 **Machine-readable manifest** (`MANIFEST.json`) for automation
124
+ * 🧾 **Structured summaries** (`SUMMARY.json`)
125
+ * 🧭 **Respects `.gitignore`** exactly when available
126
+ * 🛑 **Safely ignores virtualenvs and caches** (even with non-standard names)
127
+ * 🔍 Optional tooling checks (ruff, mypy, pytest, pylance, bandit, pip-audit, coverage)
128
+ * 🛡️ Security scanning (bandit for code issues, pip-audit for dependency CVEs)
129
+ * 🧪 Deterministic output (stable paths, timestamps, schemas)
130
+ * 🔒 Secret-safe (optional redaction)
131
+
132
+ ---
133
+
134
+ ## 📂 What’s in a pybundle archive?
135
+
136
+ At minimum, a bundle contains:
137
+
138
+ ```text
139
+ MANIFEST.json # stable, machine-readable metadata
140
+ SUMMARY.json # structured summary of collected data
141
+ src/ # filtered project source snapshot
142
+ logs/ # tool outputs (ruff, mypy, pytest, pylance, bandit, pip-audit, coverage, rg scans)
143
+ meta/ # environment + tool detection
144
+ ```
145
+
146
+ ### `MANIFEST.json` (automation fuel)
147
+
148
+ Includes:
149
+
150
+ * tool paths detected
151
+ * options used
152
+ * archive name + format
153
+ * git commit hash (if available)
154
+ * UTC timestamp
155
+ * schema version (stable)
156
+
157
+ Another script can fully understand a bundle **without reading markdown**.
158
+
159
+ ---
160
+
161
+ ## 🚀 Installation
162
+
163
+ We recommend using a Python virtual environment for development tooling.
164
+
165
+ ### Quick installation (pybundle tooling) - RECOMMENDED
166
+
167
+ Create a dedicated requirements file in the root of your project:
168
+
169
+ ```txt
170
+ # requirements-pybundle.txt
171
+ ruff
172
+ mypy
173
+ pytest
174
+ pytest-cov
175
+ bandit
176
+ pip-audit
177
+ gwc-pybundle==1.3.1
178
+ ```
179
+
180
+ Then install:
181
+
182
+ ```bash
183
+ pip install -r requirements-pybundle.txt
184
+ ```
185
+
186
+ > **System dependency:**
187
+ > pybundle uses `ripgrep (rg)` for source scanning and expects the system binary.
188
+ >
189
+ > * macOS: `brew install ripgrep`
190
+ > * Ubuntu/Debian: `sudo apt install ripgrep`
191
+ > * Fedora: `sudo dnf install ripgrep`
192
+
193
+ After installation, run:
194
+
195
+ ```bash
196
+ pybundle run analysis
197
+ ```
198
+
199
+ A new `artifacts/` directory will be created containing:
200
+
201
+ * the compressed bundle
202
+ * an extracted working directory
203
+ * machine-readable metadata (`MANIFEST.json`, `SUMMARY.json`)
204
+
205
+ See **Usage** for more details.
206
+
207
+ ---
208
+
209
+ ### Advanced installation
210
+
211
+ #### From GitHub
212
+
213
+ ```bash
214
+ pip install "gwc-pybundle @ git+https://github.com/girls-whocode/pybundle.git@v1.3.1"
215
+ ```
216
+
217
+ Pinning to a tag ensures reproducible behavior.
218
+
219
+ #### Editable install (for development)
220
+
221
+ ```bash
222
+ pip install -e .
223
+ ```
224
+
225
+ ---
226
+
227
+ ## 🧪 Usage
228
+
229
+ From the root of a Python project, run a profile using the `run` command:
230
+
231
+ ```bash
232
+ pybundle run analysis
233
+ ```
234
+
235
+ This builds a timestamped diagnostic bundle under the default `artifacts/` directory.
236
+
237
+ ### Profiles
238
+
239
+ Profiles define *what* pybundle collects and *which tools* are run.
240
+
241
+ Available profiles include:
242
+
243
+ * `analysis` - **full diagnostics** (lint, type-check, tests, scans)
244
+ * `debug` - **analysis + additional environment validation**
245
+ * `backup` - **minimal source + environment snapshot** (no analysis tools)
246
+ * `ai` - **AI-optimized context bundle** (lean, source-first)
247
+
248
+ To list all available profiles:
249
+
250
+ ```bash
251
+ pybundle list-profiles
252
+ ```
253
+
254
+ Profiles are always invoked via:
255
+
256
+ ```bash
257
+ pybundle run <profile>
258
+ ```
259
+
260
+ ---
261
+
262
+ ### 💾 Backup profile
263
+
264
+ The `backup` profile creates a minimal, lightweight snapshot ideal for version archival or disaster recovery.
265
+
266
+ Run it with:
267
+
268
+ ```bash
269
+ pybundle run backup
270
+ ```
271
+
272
+ #### What `backup` includes
273
+
274
+ * ✅ Full source code snapshot (respects `.gitignore`)
275
+ * ✅ Git status and diff (`meta/00_git_status.txt`, `meta/01_git_diff.txt`)
276
+ * ✅ Python version (`meta/20_python_version.txt`)
277
+ * ✅ Installed packages (`meta/22_pip_freeze.txt`)
278
+ * ✅ Copy manifest (`meta/50_copy_manifest.txt`)
279
+ * ❌ No linting, type-checking, or tests
280
+ * ❌ No security scanning
281
+ * ❌ No ripgrep scans
282
+
283
+ The result is a **fast, small, restorable archive** with just source code and environment context.
284
+
285
+ #### Restoring a backup
286
+
287
+ Backups are created as either `.zip` or `.tar.gz` archives (see Archive Format below).
288
+
289
+ To extract and inspect:
290
+
291
+ **For .zip archives:**
292
+ ```bash
293
+ # Look for filename with *_backup_<TIMESTAMP>.zip
294
+ unzip <FILENAME>.zip -d restored/
295
+ cd restored/<FILENAME>/
296
+ ```
297
+
298
+ **For .tar.gz archives:**
299
+ ```bash
300
+ # Look for filename with *_backup_<TIMESTAMP>.tar.gz
301
+ tar -xzf <FILENAME>.tar.gz -C restored/
302
+ cd restored/<FILENAME>/
303
+ ```
304
+
305
+ Inside the extracted directory:
306
+
307
+ ```text
308
+ src/ # Your project source code
309
+ meta/
310
+ 00_git_status.txt # Git working tree status at backup time
311
+ 01_git_diff.txt # Uncommitted changes (if any)
312
+ 20_python_version.txt # Python version used
313
+ 22_pip_freeze.txt # Exact package versions
314
+ 50_copy_manifest.txt # List of files included
315
+ MANIFEST.json # Machine-readable metadata
316
+ SUMMARY.json # Structured summary
317
+ RUN_LOG.txt # Execution log
318
+ ```
319
+
320
+ The `src/` directory contains your complete project structure.
321
+ The `meta/22_pip_freeze.txt` file can be used to recreate the exact environment:
322
+
323
+ ```bash
324
+ python -m venv venv
325
+ source venv/bin/activate # or venv\Scripts\activate on Windows
326
+ pip install -r meta/22_pip_freeze.txt
327
+ ```
328
+
329
+ Then copy your source code back:
330
+
331
+ ```bash
332
+ cp -r src/* /path/to/your/project/
333
+ ```
334
+
335
+ #### Archive format fallback
336
+
337
+ pybundle uses **zip** by default for maximum portability.
338
+
339
+ If the `zip` command is not available on your system, pybundle **automatically falls back to tar.gz** format without requiring configuration.
340
+
341
+ This ensures backups can be created on any system, regardless of installed compression tools.
342
+
343
+ To explicitly control the format:
344
+
345
+ ```bash
346
+ pybundle run backup --format zip # Force zip (requires zip command)
347
+ pybundle run backup --format tar.gz # Force tar.gz (requires tar command)
348
+ pybundle run backup --format auto # Auto-detect (default behavior)
349
+ ```
350
+
351
+ Both formats preserve the same internal structure and metadata.
352
+
353
+ ---
354
+
355
+ ### 🔍 Analysis Tools
356
+
357
+ The `analysis` and `debug` profiles run comprehensive quality and security checks:
358
+
359
+ #### Code Quality
360
+ * **ruff** - Fast Python linter and formatter checks
361
+ * **mypy** - Static type checking for type hints
362
+ * **pylance** - Syntax error detection and import analysis
363
+ * **vulture** - Dead code detection (v1.3.0+)
364
+ * **radon** - Cyclomatic complexity and maintainability metrics (v1.3.0+)
365
+ * **interrogate** - Docstring coverage analysis (v1.3.0+)
366
+ * **pylint duplication** - Code duplication detection (v1.3.0+)
367
+
368
+ #### Testing & Coverage
369
+ * **pytest** - Test execution and results
370
+ * **coverage** - Code coverage analysis (shows tested vs untested code)
371
+
372
+ #### Security
373
+ * **bandit** - Security vulnerability scanning for Python code
374
+ * **pip-audit** - Dependency vulnerability checking against known CVEs
375
+
376
+ #### Dependency Analysis (v1.3.1+)
377
+ * **pipdeptree** - Full dependency tree with conflict detection
378
+ * **unused dependencies** - Identify installed but unused packages
379
+ * **pip-licenses** - License scanning and compatibility warnings
380
+ * **dependency sizes** - Disk usage analysis per package
381
+
382
+ #### Performance Profiling (v1.4.0+)
383
+ * **cProfile** - CPU profiling to identify bottlenecks
384
+ * **import time analysis** - Detect slow module imports
385
+ * **tracemalloc** - Memory profiling (optional, via `--profile-memory`)
386
+ * **line_profiler** - Line-by-line profiling (optional, requires `@profile` decorators and `--enable-line-profiler`)
387
+
388
+ #### Test Quality & Coverage Enhancement (v1.4.1+)
389
+ * **Test flakiness detection** - Run tests multiple times to identify non-deterministic failures
390
+ * **Branch coverage** - Enhanced coverage.py integration showing missing branches, not just lines
391
+ * **Slow test identification** - Automatically identify and rank tests exceeding time threshold
392
+ * **Mutation testing** - Optional mutmut integration to measure test suite effectiveness (VERY SLOW - disabled by default)
393
+
394
+ #### Pattern Scanning
395
+ * **ripgrep scans** - TODO detection, print statements, bare excepts
396
+
397
+ All tools gracefully skip if not installed. Install recommended tools:
398
+
399
+ ```bash
400
+ pip install ruff mypy pytest pytest-cov bandit pip-audit vulture radon interrogate pylint pipdeptree pip-licenses
401
+ ```
402
+
403
+ For ripgrep (system dependency):
404
+ * macOS: `brew install ripgrep`
405
+ * Ubuntu/Debian: `sudo apt install ripgrep`
406
+
407
+ ---
408
+
409
+ ### 🤖 AI profile (NEW)
410
+
411
+ The `ai` profile is optimized for handing a project to AI tooling
412
+ (ChatGPT, local LLMs, code assistants, etc.).
413
+
414
+ It prioritizes **source code and reproducible context**, while skipping
415
+ expensive or noisy steps by default.
416
+
417
+ Run it with:
418
+
419
+ ```bash
420
+ pybundle run ai
421
+ ```
422
+
423
+ #### What `ai` does by default
424
+
425
+ * ✅ Includes full curated source snapshot (`src/`)
426
+ * ✅ Includes environment + git metadata
427
+ * ✅ Generates `REPRO.md` and `HANDOFF.md`
428
+ * ❌ Skips linting, type-checking, tests
429
+ * ❌ Skips ripgrep scans and error-context expansion
430
+ * ❌ Skips `compileall` unless explicitly enabled
431
+
432
+ The result is a **small, fast, AI-friendly bundle** that still preserves
433
+ determinism and traceability.
434
+
435
+ You may selectively re-enable tools:
436
+
437
+ ```bash
438
+ pybundle run ai --ruff --mypy
439
+ pybundle run ai --compileall
440
+ ```
441
+
442
+ This makes `ai` suitable for:
443
+
444
+ * AI-assisted refactoring
445
+ * Large-context summarization
446
+ * Code review handoff
447
+ * Offline or local LLM workflows
448
+
449
+ ---
450
+
451
+ ### Common options
452
+
453
+ Most usage customizations are done through flags on `pybundle run`.
454
+
455
+ Example:
456
+
457
+ ```bash
458
+ pybundle run analysis \
459
+ --format zip \
460
+ --outdir ./artifacts \
461
+ --name myproject-bundle \
462
+ --strict
463
+ ```
464
+
465
+ Commonly used options:
466
+
467
+ * `--format {auto,zip,tar.gz}` - archive format
468
+ * `--outdir PATH` - output directory (default: `<project>/artifacts`)
469
+ * `--name NAME` - override archive name prefix
470
+ * `--strict` - fail with non-zero exit code if any step fails
471
+ * `--redact / --no-redact` - control secret redaction
472
+
473
+ Tool execution can be selectively disabled:
474
+
475
+ ```bash
476
+ --no-ruff
477
+ --no-mypy
478
+ --no-pylance
479
+ --no-pytest
480
+ --no-bandit
481
+ --no-pip-audit
482
+ --no-coverage
483
+ --no-rg
484
+ --no-error-refs
485
+ --no-context
486
+ ```
487
+
488
+ For the full list of options:
489
+
490
+ ```bash
491
+ pybundle run --help
492
+ ```
493
+
494
+ ---
495
+
496
+ ### Doctor mode
497
+
498
+ To see which tools are available and what *would* run (without creating a bundle):
499
+
500
+ ```bash
501
+ pybundle doctor
502
+ ```
503
+
504
+ You may optionally specify a profile to preview:
505
+
506
+ ```bash
507
+ pybundle doctor analysis
508
+ ```
509
+
510
+ This is useful for validating environment readiness (CI, fresh machines, etc.).
511
+
512
+ ---
513
+
514
+ ### Version
515
+
516
+ To check the installed version:
517
+
518
+ ```bash
519
+ pybundle version
520
+ ```
521
+
522
+ ---
523
+
524
+ ## 🧠 Ignore behavior (important)
525
+
526
+ ### If inside a Git repository
527
+
528
+ pybundle uses **Git itself** to determine which files are included:
529
+
530
+ * `.gitignore`
531
+ * `.git/info/exclude`
532
+ * global gitignore rules
533
+
534
+ This guarantees pybundle sees the project **exactly as Git does**.
535
+
536
+ ### If Git is unavailable
537
+
538
+ pybundle falls back to safe structural rules:
539
+
540
+ * ignores `__pycache__`, `.ruff_cache`, `.mypy_cache`, `.pytest_cache`, etc.
541
+ * detects virtual environments by structure (`pyvenv.cfg`, `bin/activate`), not by name
542
+ → works with `.venv`, `.pybundle-venv`, `env-prod-2025`, etc.
543
+
544
+ ---
545
+
546
+ ## 🧾 Machine-Readable Output (`--json`)
547
+
548
+ All `pybundle` commands support a **machine-readable JSON output mode** via the `--json` flag.
549
+
550
+ When enabled, `pybundle` emits **exactly one JSON object to stdout**, with a **stable schema** intended for:
551
+
552
+ * CI pipelines
553
+ * automation scripts
554
+ * external tooling
555
+ * AI orchestration
556
+ * reproducible analysis
557
+
558
+ No human text or formatting are mixed into the output.
559
+
560
+ ### Example
561
+
562
+ ```bash
563
+ pybundle run analysis --json
564
+ ```
565
+
566
+ Output:
567
+
568
+ ```json
569
+ {
570
+ "status": "ok",
571
+ "command": "run",
572
+ "profile": "analysis",
573
+ "files_included": 39,
574
+ "files_excluded": 0,
575
+ "duration_ms": 394,
576
+ "bundle_path": "/home/jessica/repositories/python/pybundle/artifacts/pybundle_analysis_20260103T102440Z.zip"
577
+ }
578
+ ```
579
+
580
+ The same structure applies to **all profiles**:
581
+
582
+ ```bash
583
+ pybundle run ai --json
584
+ pybundle run debug --json
585
+ pybundle run backup --json
586
+ ```
587
+
588
+ ---
589
+
590
+ ### JSON Field Definitions
591
+
592
+ | Field | Description |
593
+ | ---------------- | -------------------------------------------------- |
594
+ | `status` | `"ok"` or `"fail"` based on execution result |
595
+ | `command` | The command executed (`run` or `doctor`) |
596
+ | `profile` | The profile used (`analysis`, `ai`, `debug`, etc.) |
597
+ | `files_included` | Number of files copied into the bundle |
598
+ | `files_excluded` | Number of *evaluated* files skipped by policy |
599
+ | `duration_ms` | Total execution time in milliseconds |
600
+ | `bundle_path` | Absolute path to the generated archive |
601
+
602
+ ---
603
+
604
+ ### Important Semantics: `files_excluded`
605
+
606
+ `files_excluded` **does not** mean “everything in the repository that was not bundled.”
607
+
608
+ Instead, it means:
609
+
610
+ > Files that were **eligible under the active profile’s policy** and were *explicitly skipped* after evaluation.
611
+
612
+ Files and directories that are **intentionally out of scope** — such as:
613
+
614
+ * `.git/`
615
+ * `node_modules/`
616
+ * virtual environments
617
+ * build artifacts
618
+ * caches
619
+
620
+ are **never considered**, and therefore are **not counted as excluded**.
621
+
622
+ This design keeps metrics honest and avoids inflating counts with known-irrelevant infrastructure.
623
+
624
+ A value of `files_excluded = 0` simply means:
625
+
626
+ > *Everything that was evaluated was worth keeping.*
627
+
628
+ This is expected and normal for clean, well-structured projects — especially in `ai` mode.
629
+
630
+ ---
631
+
632
+ ### JSON Stability Guarantee
633
+
634
+ The JSON schema emitted by `--json` is considered **part of the public API**.
635
+
636
+ Starting with **v1.0**, field names and meanings will remain stable.
637
+ New fields may be added, but existing fields will not be renamed or removed.
638
+
639
+ This allows `pybundle` to be safely embedded into:
640
+
641
+ * CI workflows
642
+ * automation scripts
643
+ * AI pipelines
644
+ * external tooling
645
+
646
+ without fear of breaking changes.
647
+
648
+ ---
649
+
650
+ ## 📜 Profiles
651
+
652
+ pybundle is profile-driven. Each profile defines:
653
+
654
+ * what files are collected
655
+ * which tools run
656
+ * what metadata is emitted
657
+
658
+ Example profiles:
659
+
660
+ * `analysis`
661
+ * `source`
662
+ * `minimal`
663
+
664
+ Profiles are extensible - add your own without modifying core logic.
665
+
666
+ ---
667
+
668
+ ## 🔐 Safety & Redaction
669
+
670
+ By default, pybundle:
671
+
672
+ * avoids scanning known secret locations
673
+ * supports optional redaction of sensitive strings in logs
674
+
675
+ Use `--redact / --no-redact` to control behavior.
676
+
677
+ ---
678
+ ## 🔒 Security Considerations
679
+
680
+ **pybundle** is a development tool designed for trusted environments.
681
+
682
+ ### Threat Model
683
+
684
+ * **Environment:** Development machines and CI/CD pipelines
685
+ * **Trust Boundary:** Assumes trusted development environment
686
+ * **Execution Context:** Runs external tools (git, ruff, mypy, pytest, etc.)
687
+ * **Input Sources:** Project files, git repository, installed packages
688
+
689
+ ### Security Posture
690
+
691
+ **Tool Path Resolution:**
692
+ - All external tools use full resolved paths (via `shutil.which()`)
693
+ - Tools are resolved at detection time and stored in `Tooling` dataclass
694
+ - No dynamic PATH manipulation or shell interpretation
695
+ - Eliminates partial path execution vulnerabilities (B607)
696
+ - **Optional strict-paths mode** for enhanced security (v1.2.0+)
697
+ - **Code quality tools** for dead code, complexity, docstrings, and duplication (v1.3.0+)
698
+ - **Dependency intelligence** for conflict detection, license scanning, and size analysis (v1.3.1+)
699
+
700
+ **Subprocess Execution:**
701
+ - All subprocess calls use `shell=False` (default, secure)
702
+ - Arguments passed as lists, never as strings
703
+ - No user-controlled command construction
704
+ - Commands are hardcoded in source code
705
+
706
+ **Data Handling:**
707
+ - Optional secret redaction for sensitive strings in logs
708
+ - Environment variables and paths logged for reproducibility
709
+ - All file operations respect `.gitignore` rules
710
+
711
+ ### Strict-Paths Mode (v1.2.0+)
712
+
713
+ For high-security environments, enable `--strict-paths` to enforce that all tools must be in trusted system directories:
714
+
715
+ ```bash
716
+ pybundle run analysis --strict-paths
717
+ ```
718
+
719
+ **Trusted directories** (configurable via `PYBUNDLE_TRUSTED_PATHS`):
720
+ - `/usr/bin/`, `/usr/local/bin/`, `/bin/`
721
+ - `/opt/homebrew/bin/` (macOS Homebrew)
722
+ - `/snap/bin/` (Ubuntu snaps)
723
+ - Virtual environment paths (`.venv`, `venv`, `.pybundle-venv`)
724
+
725
+ Tools outside trusted directories are excluded in strict mode. This prevents:
726
+ - Accidental execution of tools from user-writable directories
727
+ - PATH manipulation attacks
728
+ - Use of potentially compromised tool installations
729
+
730
+ **Example:** Verify tool paths before running:
731
+ ```bash
732
+ pybundle doctor --strict-paths
733
+ ```
734
+
735
+ Output shows trust status:
736
+ ```
737
+ 🔧 Tool Detection:
738
+ git ✅ /usr/bin/git
739
+ python ✅ /path/to/venv/bin/python
740
+ npm ⚠️ /home/user/.nvm/.../npm (untrusted in strict mode)
741
+ ```
742
+
743
+ **Configure custom trusted paths:**
744
+ ```bash
745
+ export PYBUNDLE_TRUSTED_PATHS="/opt/custom/bin:/company/tools/bin"
746
+ pybundle run debug --strict-paths
747
+ ```
748
+
749
+ ### Known Limitations
750
+
751
+ 1. **Requires Trusted Environment**
752
+ - Assumes developer controls their machine and installed tools
753
+ - Not designed for untrusted code execution or sandboxing
754
+ - Tool integrity depends on system package management
755
+
756
+ 2. **Tool Availability**
757
+ - External tools (git, ruff, mypy) are optional
758
+ - Missing tools result in SKIP status, not failure
759
+ - Use `pybundle doctor` to verify available tools
760
+
761
+ 3. **File System Access**
762
+ - Reads entire project tree (respecting ignore rules)
763
+ - Writes to `artifacts/` directory by default
764
+ - No privilege escalation or system modification
765
+
766
+ ### For Security Auditors
767
+
768
+ **Bandit Security Scan Results:**
769
+ - 33 low-severity findings (all expected for CLI tool)
770
+ - **B404** (subprocess import): Required for tool functionality
771
+ - **B603** (subprocess calls): Using secure pattern (shell=False, full paths)
772
+ - **B112** (try/except/continue): Acceptable error handling pattern
773
+
774
+ **Risk Classification:** LOW
775
+ - No user-controlled command injection
776
+ - No untrusted input in command execution
777
+ - Full path resolution prevents PATH manipulation attacks
778
+ - Standard development tool security posture
779
+
780
+ **Recommended Usage:**
781
+ ```bash
782
+ # Verify tool paths before execution
783
+ pybundle doctor
784
+
785
+ # Review what tools will be used
786
+ pybundle doctor analysis --json
787
+ ```
788
+
789
+ ---
790
+ ## 🧩 Why pybundle?
791
+
792
+ pybundle is designed for:
793
+
794
+ * handing a project to another engineer
795
+ * attaching context to a bug report
796
+ * feeding a codebase to AI tooling
797
+ * generating CI artifacts
798
+ * preserving “what exactly did we run?”
799
+ * producing **AI-consumable project context** without guesswork
800
+
801
+ It prioritizes **determinism, traceability, and automation** over clever heuristics.
802
+
803
+ ---
804
+
805
+ ## 🛠 Development Notes
806
+
807
+ * Python ≥ 3.9
808
+ * Uses modern tooling (ruff, mypy)
809
+ * Fully type-checked
810
+ * Formatter-clean
811
+ * No test suite *yet* (intentional; coming later)
812
+
813
+ During development, run:
814
+
815
+ ```bash
816
+ python -m pybundle ...
817
+ ```
818
+
819
+ to bypass shell caching.
820
+
821
+ ---
822
+
823
+ ## 📌 Versioning
824
+
825
+ pybundle follows **Semantic Versioning**.
826
+
827
+ Pinned Git tags are recommended when used as a dependency:
828
+
829
+ ```txt
830
+ gwc-pybundle @ git+https://github.com/girls-whocode/pybundle.git@v1.3.1
831
+ ```
832
+
833
+ ---
834
+
835
+ ## 🧠 Philosophy
836
+
837
+ > If a tool produces output, it should also produce metadata about **how** and **why** that output exists.
838
+
839
+ pybundle treats context as a first-class artifact.
840
+
841
+ ---
842
+
843
+ ## 📦 Package naming note
844
+
845
+ The distribution name on PyPI is **`gwc-pybundle`** to avoid conflicts with existing packages.
846
+
847
+ The project name, imports, and CLI remain **`pybundle`**.
848
+
849
+ ```bash
850
+ pip install gwc-pybundle
851
+ pybundle run analysis
852
+ ```
853
+ Look in the autocreated `artifacts/` folder.
854
+
855
+ ## 📄 License
856
+
857
+ MIT License