opsward 0.0.2__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 (67) hide show
  1. opsward-0.0.2/.gitattributes +1 -0
  2. opsward-0.0.2/.github/workflows/ci.yml +213 -0
  3. opsward-0.0.2/.gitignore +121 -0
  4. opsward-0.0.2/CLAUDE.md +174 -0
  5. opsward-0.0.2/LICENSE +21 -0
  6. opsward-0.0.2/PKG-INFO +135 -0
  7. opsward-0.0.2/README.md +113 -0
  8. opsward-0.0.2/misc/docs/ai_setup_meta_tooling.md +266 -0
  9. opsward-0.0.2/misc/docs/architecture.md +77 -0
  10. opsward-0.0.2/misc/docs/conventions.md +39 -0
  11. opsward-0.0.2/misc/docs/docs_catalog.md +83 -0
  12. opsward-0.0.2/misc/docs/docs_guide.md +15 -0
  13. opsward-0.0.2/misc/docs/known_issues.md +12 -0
  14. opsward-0.0.2/misc/docs/scoring_rubric.md +110 -0
  15. opsward-0.0.2/misc/docs/target_artifacts.md +131 -0
  16. opsward-0.0.2/opsward/__init__.py +18 -0
  17. opsward-0.0.2/opsward/__main__.py +13 -0
  18. opsward-0.0.2/opsward/base.py +204 -0
  19. opsward-0.0.2/opsward/cli.py +211 -0
  20. opsward-0.0.2/opsward/data/__init__.py +0 -0
  21. opsward-0.0.2/opsward/data/templates/__init__.py +0 -0
  22. opsward-0.0.2/opsward/data/templates/jsts/conventions.md +30 -0
  23. opsward-0.0.2/opsward/data/templates/jsts/testing.md +28 -0
  24. opsward-0.0.2/opsward/data/templates/python/conventions.md +33 -0
  25. opsward-0.0.2/opsward/data/templates/python/testing.md +29 -0
  26. opsward-0.0.2/opsward/data/templates/shared/architecture.md +21 -0
  27. opsward-0.0.2/opsward/data/templates/shared/claude_md.md +28 -0
  28. opsward-0.0.2/opsward/data/templates/shared/decisions/0000-template.md +17 -0
  29. opsward-0.0.2/opsward/data/templates/shared/dependencies.md +17 -0
  30. opsward-0.0.2/opsward/data/templates/shared/deployment.md +17 -0
  31. opsward-0.0.2/opsward/data/templates/shared/diagnose-setup/SKILL.md +22 -0
  32. opsward-0.0.2/opsward/data/templates/shared/docs_guide.md +24 -0
  33. opsward-0.0.2/opsward/data/templates/shared/glossary.md +7 -0
  34. opsward-0.0.2/opsward/data/templates/shared/known_issues.md +16 -0
  35. opsward-0.0.2/opsward/data/templates/shared/maintain-docs/SKILL.md +21 -0
  36. opsward-0.0.2/opsward/data/templates/shared/roadmap.md +17 -0
  37. opsward-0.0.2/opsward/data/templates/shared/session_log.md +10 -0
  38. opsward-0.0.2/opsward/data/templates/shared/setup-auditor.md +21 -0
  39. opsward-0.0.2/opsward/generate.py +422 -0
  40. opsward-0.0.2/opsward/maintain.py +237 -0
  41. opsward-0.0.2/opsward/scan.py +155 -0
  42. opsward-0.0.2/opsward/score.py +451 -0
  43. opsward-0.0.2/opsward/util.py +48 -0
  44. opsward-0.0.2/pyproject.toml +159 -0
  45. opsward-0.0.2/tests/__init__.py +0 -0
  46. opsward-0.0.2/tests/fixtures/jsts_project/package.json +1 -0
  47. opsward-0.0.2/tests/fixtures/jsts_project/tsconfig.json +1 -0
  48. opsward-0.0.2/tests/fixtures/python_project/.claude/agents/code-reviewer.md +3 -0
  49. opsward-0.0.2/tests/fixtures/python_project/.claude/hooks.json +1 -0
  50. opsward-0.0.2/tests/fixtures/python_project/.claude/rules/no-print.md +1 -0
  51. opsward-0.0.2/tests/fixtures/python_project/.claude/skills/my-skill/SKILL.md +5 -0
  52. opsward-0.0.2/tests/fixtures/python_project/CLAUDE.md +7 -0
  53. opsward-0.0.2/tests/fixtures/python_project/docs/architecture.md +3 -0
  54. opsward-0.0.2/tests/fixtures/python_project/docs/docs_guide.md +3 -0
  55. opsward-0.0.2/tests/fixtures/python_project/pyproject.toml +3 -0
  56. opsward-0.0.2/tests/fixtures/stale_project/CLAUDE.md +18 -0
  57. opsward-0.0.2/tests/fixtures/stale_project/docs/architecture.md +3 -0
  58. opsward-0.0.2/tests/fixtures/stale_project/docs/conventions.md +3 -0
  59. opsward-0.0.2/tests/fixtures/stale_project/docs/docs_guide.md +9 -0
  60. opsward-0.0.2/tests/fixtures/stale_project/docs/unlisted_doc.md +3 -0
  61. opsward-0.0.2/tests/fixtures/stale_project/pyproject.toml +3 -0
  62. opsward-0.0.2/tests/test_base.py +86 -0
  63. opsward-0.0.2/tests/test_cli.py +75 -0
  64. opsward-0.0.2/tests/test_generate.py +224 -0
  65. opsward-0.0.2/tests/test_maintain.py +156 -0
  66. opsward-0.0.2/tests/test_scan.py +140 -0
  67. opsward-0.0.2/tests/test_score.py +127 -0
@@ -0,0 +1 @@
1
+ *.ipynb linguist-documentation
@@ -0,0 +1,213 @@
1
+ name: Continuous Integration (2025-11)
2
+ on: [push, pull_request]
3
+
4
+ # Note: Environment variables (PROJECT_NAME and vars from [tool.wads.ci.env])
5
+ # are set by the read-ci-config action in the setup job and made available
6
+ # to all subsequent jobs via GITHUB_ENV
7
+
8
+ jobs:
9
+ # First job: Read configuration from pyproject.toml
10
+ setup:
11
+ name: Read Configuration
12
+ runs-on: ubuntu-latest
13
+ outputs:
14
+ project-name: ${{ steps.config.outputs.project-name }}
15
+ python-versions: ${{ steps.config.outputs.python-versions }}
16
+ pytest-args: ${{ steps.config.outputs.pytest-args }}
17
+ coverage-enabled: ${{ steps.config.outputs.coverage-enabled }}
18
+ exclude-paths: ${{ steps.config.outputs.exclude-paths }}
19
+ test-on-windows: ${{ steps.config.outputs.test-on-windows }}
20
+ build-sdist: ${{ steps.config.outputs.build-sdist }}
21
+ build-wheel: ${{ steps.config.outputs.build-wheel }}
22
+ metrics-enabled: ${{ steps.config.outputs.metrics-enabled }}
23
+ metrics-config-path: ${{ steps.config.outputs.metrics-config-path }}
24
+ metrics-storage-branch: ${{ steps.config.outputs.metrics-storage-branch }}
25
+ metrics-python-version: ${{ steps.config.outputs.metrics-python-version }}
26
+ metrics-force-run: ${{ steps.config.outputs.metrics-force-run }}
27
+
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+
31
+ - name: Read CI Config
32
+ id: config
33
+ uses: i2mint/wads/actions/read-ci-config@master
34
+ with:
35
+ pyproject-path: .
36
+
37
+ # Second job: Validation using the config
38
+ validation:
39
+ name: Validation
40
+ if: "!contains(github.event.head_commit.message, '[skip ci]')"
41
+ needs: setup
42
+ runs-on: ubuntu-latest
43
+ strategy:
44
+ matrix:
45
+ python-version: ${{ fromJson(needs.setup.outputs.python-versions) }}
46
+
47
+ steps:
48
+ - uses: actions/checkout@v4
49
+
50
+ - name: Set up Python ${{ matrix.python-version }}
51
+ uses: actions/setup-python@v6
52
+ with:
53
+ python-version: ${{ matrix.python-version }}
54
+
55
+ - name: Install System Dependencies
56
+ uses: i2mint/wads/actions/install-system-deps@master
57
+ with:
58
+ pyproject-path: .
59
+
60
+ - name: Install Dependencies
61
+ uses: i2mint/wads/actions/install-deps@master
62
+ with:
63
+ dependency-files: pyproject.toml
64
+ extras: dev,test
65
+
66
+ - name: Format Source Code
67
+ uses: i2mint/wads/actions/ruff-format@master
68
+ with:
69
+ line-length: 88
70
+ target-path: .
71
+
72
+ - name: Lint Validation
73
+ uses: i2mint/wads/actions/ruff-lint@master
74
+ with:
75
+ root-dir: ${{ needs.setup.outputs.project-name }}
76
+ output-format: github
77
+
78
+ - name: Run Tests
79
+ uses: i2mint/wads/actions/run-tests@master
80
+ with:
81
+ root-dir: ${{ needs.setup.outputs.project-name }}
82
+ exclude: ${{ needs.setup.outputs.exclude-paths }}
83
+ coverage: ${{ needs.setup.outputs.coverage-enabled }}
84
+ pytest-args: ${{ needs.setup.outputs.pytest-args }}
85
+
86
+ - name: Track Code Metrics
87
+ if: needs.setup.outputs.metrics-enabled == 'true'
88
+ uses: i2mint/umpyre/actions/track-metrics@master
89
+ continue-on-error: true
90
+ with:
91
+ github-token: ${{ secrets.GITHUB_TOKEN }}
92
+ config-path: ${{ needs.setup.outputs.metrics-config-path }}
93
+ storage-branch: ${{ needs.setup.outputs.metrics-storage-branch }}
94
+ python-version: ${{ needs.setup.outputs.metrics-python-version }}
95
+ force-run: ${{ needs.setup.outputs.metrics-force-run }}
96
+
97
+ # Optional Windows testing (if enabled in config)
98
+ windows-validation:
99
+ name: Windows Tests
100
+ if: "!contains(github.event.head_commit.message, '[skip ci]') && needs.setup.outputs.test-on-windows == 'true'"
101
+ needs: setup
102
+ runs-on: windows-latest
103
+ continue-on-error: true
104
+
105
+ steps:
106
+ - uses: actions/checkout@v4
107
+
108
+ - name: Set up Python
109
+ uses: actions/setup-python@v6
110
+ with:
111
+ python-version: ${{ fromJson(needs.setup.outputs.python-versions)[0] }}
112
+
113
+ - name: Install System Dependencies
114
+ uses: i2mint/wads/actions/install-system-deps@master
115
+ with:
116
+ pyproject-path: .
117
+
118
+ - name: Install Dependencies
119
+ uses: i2mint/wads/actions/install-deps@master
120
+ with:
121
+ dependency-files: pyproject.toml
122
+ extras: dev,test
123
+
124
+ - name: Run tests
125
+ id: test
126
+ continue-on-error: true
127
+ run: pytest
128
+
129
+ - name: Report test results
130
+ if: always()
131
+ run: |
132
+ if ("${{ steps.test.outcome }}" -eq "failure") {
133
+ echo "::warning::Windows tests failed but workflow continues"
134
+ echo "## ⚠️ Windows Tests Failed" >> $env:GITHUB_STEP_SUMMARY
135
+ echo "Tests failed on Windows but this is informational only." >> $env:GITHUB_STEP_SUMMARY
136
+ } else {
137
+ echo "## ✅ Windows Tests Passed" >> $env:GITHUB_STEP_SUMMARY
138
+ }
139
+
140
+ # Publishing job
141
+ publish:
142
+ name: Publish
143
+ permissions:
144
+ contents: write
145
+ if: "!contains(github.event.head_commit.message, '[skip ci]') && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main')"
146
+ needs: [setup, validation]
147
+ runs-on: ubuntu-latest
148
+
149
+ steps:
150
+ - uses: actions/checkout@v4
151
+ with:
152
+ fetch-depth: 0
153
+ token: ${{ secrets.GITHUB_TOKEN }}
154
+
155
+ - name: Set up Python
156
+ uses: actions/setup-python@v6
157
+ with:
158
+ python-version: ${{ fromJson(needs.setup.outputs.python-versions)[0] }}
159
+
160
+ - name: Format Source Code
161
+ uses: i2mint/wads/actions/ruff-format@master
162
+
163
+ - name: Update Version Number
164
+ id: version
165
+ uses: i2mint/isee/actions/bump-version-number@master
166
+
167
+ - name: Build Distribution
168
+ uses: i2mint/wads/actions/build-dist@master
169
+ with:
170
+ sdist: ${{ needs.setup.outputs.build-sdist }}
171
+ wheel: ${{ needs.setup.outputs.build-wheel }}
172
+
173
+ - name: Publish to PyPI
174
+ uses: i2mint/wads/actions/pypi-upload@master
175
+ with:
176
+ pypi-username: ${{ secrets.PYPI_USERNAME }}
177
+ pypi-password: ${{ secrets.PYPI_PASSWORD }}
178
+ skip-existing: false
179
+
180
+ - name: Force SSH for git remote
181
+ run: |
182
+ git remote set-url origin git@github.com:${{ github.repository }}.git
183
+
184
+ - name: Commit Changes
185
+ uses: i2mint/wads/actions/git-commit@master
186
+ with:
187
+ commit-message: "**CI** Formatted code + Updated version to ${{ env.VERSION }} [skip ci]"
188
+ ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
189
+ push: true
190
+
191
+ - name: Tag Repository
192
+ uses: i2mint/wads/actions/git-tag@master
193
+ with:
194
+ tag: ${{ env.VERSION }}
195
+ message: "Release version ${{ env.VERSION }}"
196
+ push: true
197
+
198
+ # Optional GitHub Pages
199
+ github-pages:
200
+ name: Publish GitHub Pages
201
+ permissions:
202
+ contents: write
203
+ pages: write
204
+ id-token: write
205
+ if: "!contains(github.event.head_commit.message, '[skip ci]') && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)"
206
+ needs: publish
207
+ runs-on: ubuntu-latest
208
+
209
+ steps:
210
+ - uses: i2mint/epythet/actions/publish-github-pages@master
211
+ with:
212
+ github-token: ${{ secrets.GITHUB_TOKEN }}
213
+ ignore: "tests/,scrap/,examples/"
@@ -0,0 +1,121 @@
1
+ wads_configs.json
2
+ data/wads_configs.json
3
+ wads/data/wads_configs.json
4
+
5
+ # Byte-compiled / optimized / DLL files
6
+ __pycache__/
7
+ *.py[cod]
8
+ *$py.class
9
+
10
+
11
+ .DS_Store
12
+ # C extensions
13
+ *.so
14
+
15
+ # TLS certificates
16
+ ## Ignore all PEM files anywhere
17
+ *.pem
18
+ ## Also ignore any certs directory
19
+ certs/
20
+
21
+ # Distribution / packaging
22
+ .Python
23
+ build/
24
+ develop-eggs/
25
+ dist/
26
+ downloads/
27
+ eggs/
28
+ .eggs/
29
+ lib/
30
+ lib64/
31
+ parts/
32
+ sdist/
33
+ var/
34
+ wheels/
35
+ *.egg-info/
36
+ .installed.cfg
37
+ *.egg
38
+ MANIFEST
39
+ _build
40
+
41
+ # PyInstaller
42
+ # Usually these files are written by a python script from a template
43
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
44
+ *.manifest
45
+ *.spec
46
+
47
+ # Installer logs
48
+ pip-log.txt
49
+ pip-delete-this-directory.txt
50
+
51
+ # Unit test / coverage reports
52
+ htmlcov/
53
+ .tox/
54
+ .coverage
55
+ .coverage.*
56
+ .cache
57
+ nosetests.xml
58
+ coverage.xml
59
+ *.cover
60
+ .hypothesis/
61
+ .pytest_cache/
62
+
63
+ # Translations
64
+ *.mo
65
+ *.pot
66
+
67
+ # Django stuff:
68
+ *.log
69
+ local_settings.py
70
+ db.sqlite3
71
+
72
+ # Flask stuff:
73
+ instance/
74
+ .webassets-cache
75
+
76
+ # Scrapy stuff:
77
+ .scrapy
78
+
79
+ # Sphinx documentation
80
+ docs/_build/
81
+ docs/*
82
+
83
+ # PyBuilder
84
+ target/
85
+
86
+ # Jupyter Notebook
87
+ .ipynb_checkpoints
88
+
89
+ # pyenv
90
+ .python-version
91
+
92
+ # celery beat schedule file
93
+ celerybeat-schedule
94
+
95
+ # SageMath parsed files
96
+ *.sage.py
97
+
98
+ # Environments
99
+ .env
100
+ .venv
101
+ env/
102
+ venv/
103
+ ENV/
104
+ env.bak/
105
+ venv.bak/
106
+
107
+ # Spyder project settings
108
+ .spyderproject
109
+ .spyproject
110
+
111
+ # Rope project settings
112
+ .ropeproject
113
+
114
+ # mkdocs documentation
115
+ /site
116
+
117
+ # mypy
118
+ .mypy_cache/
119
+
120
+ # PyCharm
121
+ .idea
@@ -0,0 +1,174 @@
1
+ # Opsward
2
+
3
+ Diagnose, generate, and maintain the AI agent setup of your projects — CLAUDE.md, skills, subagents, rules, and supporting docs.
4
+
5
+ ## Project Overview
6
+
7
+ Opsward is a Python CLI tool (and library) that treats a project's AI agent configuration as a first-class artifact. It scans project roots, reports what's missing or stale, scaffolds missing pieces from templates, and keeps everything current as the codebase evolves. It works on Python projects, JS/TS projects, and mixed repos.
8
+
9
+ There is also an `ow` PyPI package that is a thin re-export shim for `opsward`.
10
+
11
+ ## Tech Stack
12
+
13
+ - **Language:** Python 3.10+
14
+ - **CLI:** `argh` for dispatching functions to CLI commands
15
+ - **Templates:** String-based (`string.Template` or simple f-string/jinja2-minimal) — keep deps light
16
+ - **Data structures:** `dataclasses` for models, `Mapping`/`MutableMapping` where storage is involved
17
+ - **File access:** `importlib.resources.files` for bundled templates in `opsward/data/`
18
+ - **Testing:** `pytest`, doctests where practical
19
+ - **No heavy deps:** This is a lightweight diagnostic/scaffolding tool. Avoid pulling in large frameworks.
20
+
21
+ ## Documentation
22
+
23
+ For detailed project knowledge, see `misc/docs/docs_guide.md`.
24
+ Read it to discover which docs to consult for your current task.
25
+
26
+ Key docs to read before starting work:
27
+ - `misc/docs/ai_setup_meta_tooling.md` — the foundational research report (what exists, what we're building, why)
28
+ - `misc/docs/architecture.md` — system design, module responsibilities, data flow
29
+ - `misc/docs/conventions.md` — coding style and patterns for this project
30
+ - `misc/docs/target_artifacts.md` — complete spec of what opsward generates for target projects
31
+
32
+ ## Module Map
33
+
34
+ - `opsward/` — the main package
35
+ - `__init__.py` — public interface (the facade). Exports `diagnose`, `generate`, `maintain`, key types
36
+ - `base.py` — core data structures: `ProjectType`, `DiagnosisReport`, `DocSpec`, `SetupComponent`, scoring models
37
+ - `scan.py` — read-only filesystem scanning: detect project type, find CLAUDE.md, skills, agents, rules, hooks, docs
38
+ - `score.py` — quality scoring: CLAUDE.md rubric, skill validation, doc freshness, cross-reference checks
39
+ - `generate.py` — template rendering and file generation (never overwrites without confirmation)
40
+ - `maintain.py` — staleness detection, update suggestions, drift analysis
41
+ - `cli.py` — argh-based CLI entry point
42
+ - `util.py` — internal helpers (underscore-prefixed)
43
+ - `data/` — bundled package resources (accessed via `importlib.resources.files`)
44
+ - `templates/` — generation templates organized by target project type
45
+ - `shared/` — templates that work for any project type
46
+ - `python/` — Python-specific templates (paths use `misc/docs/`)
47
+ - `jsts/` — JS/TS-specific templates (paths use `docs/`)
48
+ - `rubrics/` — scoring criteria (YAML or TOML)
49
+ - `skills/` — Claude Code skill templates that opsward installs into target projects
50
+ - `tests/` — pytest tests
51
+
52
+ ## Commands
53
+
54
+ ```bash
55
+ # Install
56
+ pip install opsward # or: pip install ow
57
+
58
+ # CLI usage
59
+ python -m opsward diagnose /path/to/project # Diagnose AI setup
60
+ python -m opsward diagnose /path/to/proj1 /path/to/proj2 # Multi-project
61
+ python -m opsward generate /path/to/project # Generate missing pieces
62
+ python -m opsward maintain /path/to/project # Check for staleness/drift
63
+
64
+ # After pip install (via pyproject.toml [project.scripts]):
65
+ opsward diagnose .
66
+ opsward generate . --dry-run
67
+ opsward maintain .
68
+ ```
69
+
70
+ ## Conventions
71
+
72
+ ### Python Style
73
+
74
+ - Functional over OOP. Use dataclasses for data, plain functions for logic.
75
+ - Keyword-only arguments from the 3rd position onward.
76
+ - Small helper functions: inner if single-caller, underscore-prefixed if module-private.
77
+ - Minimal docstrings on everything. Simple doctests when practical.
78
+ - `yield` over `return list`. Generators for sequences.
79
+ - `Mapping`/`MutableMapping` for storage abstractions.
80
+ - Use `importlib.resources.files("opsward.data")` to access bundled templates — never hardcode filesystem paths to package data.
81
+
82
+ ### CLI Pattern
83
+
84
+ Follow the argh SSOT dispatch pattern:
85
+
86
+ ```python
87
+ # In cli.py
88
+ _dispatch_funcs = [diagnose, generate, maintain]
89
+
90
+ if __name__ == "__main__":
91
+ import argh
92
+ argh.dispatch_commands(_dispatch_funcs)
93
+ ```
94
+
95
+ ```python
96
+ # In __main__.py
97
+ from opsward.cli import _dispatch_funcs
98
+ import argh
99
+ argh.dispatch_commands(_dispatch_funcs)
100
+ ```
101
+
102
+ ### Template Pattern
103
+
104
+ Templates live in `opsward/data/templates/`. They are plain markdown files with `${variable}` placeholders (using `string.Template`). The generator reads them via `importlib.resources`, substitutes variables from the scan results, and writes to the target project.
105
+
106
+ ### Scoring Pattern
107
+
108
+ Scoring functions are pure: `(scan_result) -> score_dict`. No side effects. The rubric definitions live in `opsward/data/rubrics/` as YAML. Scoring dimensions for CLAUDE.md (inspired by community best practices):
109
+
110
+ 1. **Commands/Workflows** (0-20): Are build/test/run commands documented?
111
+ 2. **Architecture Clarity** (0-20): Is the module map present and accurate?
112
+ 3. **Conventions** (0-15): Are non-obvious patterns documented?
113
+ 4. **Conciseness** (0-15): Is it dense and scannable, not bloated?
114
+ 5. **Currency** (0-15): Do referenced paths/files actually exist?
115
+ 6. **Actionability** (0-15): Can an agent act on the instructions without guessing?
116
+
117
+ ### Project Type Detection
118
+
119
+ ```python
120
+ # Detection signals — check in this order:
121
+ PYTHON_SIGNALS = ("pyproject.toml", "setup.py", "setup.cfg", "Pipfile")
122
+ JSTS_SIGNALS = ("package.json", "tsconfig.json", "deno.json")
123
+
124
+ # Docs location by type:
125
+ # Python -> misc/docs/
126
+ # JS/TS -> docs/
127
+ # Mixed -> docs/ (JS/TS convention wins)
128
+ ```
129
+
130
+ ### What Opsward Generates for Target Projects
131
+
132
+ When generating for a target project, opsward can produce:
133
+
134
+ **Documentation layer** (the `docs/` or `misc/docs/` folder):
135
+ - `docs_guide.md` — always first. Entry point listing all other docs.
136
+ - `architecture.md`, `known_issues.md`, `conventions.md`, `roadmap.md`, `glossary.md`, `testing.md`, `dependencies.md`, `deployment.md`
137
+ - `decisions/` folder for MADR-style architectural decision records
138
+
139
+ **AI configuration layer** (the `.claude/` folder):
140
+ - `CLAUDE.md` at project root (or updates to existing one)
141
+ - `.claude/skills/diagnose-setup/SKILL.md` — the diagnostic skill
142
+ - `.claude/skills/maintain-docs/SKILL.md` — the doc maintenance skill
143
+ - `.claude/agents/setup-auditor.md` — read-only auditor subagent
144
+ - `.claude/rules/` files if appropriate
145
+
146
+ See `misc/docs/target_artifacts.md` for the full spec of generated artifacts.
147
+
148
+ ### Output Principles
149
+
150
+ - **Never overwrite** existing files without explicit confirmation.
151
+ - **Dry-run by default** for generate/maintain. Use `--write` or `--apply` to actually write.
152
+ - **Diff-first**: Show what would change before changing it.
153
+ - **Minimal generation**: Only suggest docs/skills that are genuinely useful for the detected project type. Don't generate a `deployment.md` template for a library with no deployment.
154
+
155
+ ## Non-Obvious Patterns
156
+
157
+ - Templates are **not** Jinja2. Use `string.Template` for simplicity and zero deps. If a template needs conditionals, split it into separate template files per variant.
158
+ - The `diagnose` function returns a `DiagnosisReport` dataclass that is both human-readable (via `__str__`) and machine-consumable (via dataclass fields). The CLI pretty-prints it; library users get structured data.
159
+ - The `scan.py` module must be **purely read-only** — it never modifies the target project. This is a hard invariant. It uses `pathlib.Path` and `os.walk`, never writes.
160
+ - For multi-project scanning, each project gets its own `DiagnosisReport`. There is also an aggregate `MultiProjectReport` that summarizes cross-project patterns.
161
+ - The `ow` shim package is a separate `pyproject.toml` / directory. It literally just does `from opsward import *` and declares `opsward` as a dependency.
162
+
163
+ ## Git Workflow
164
+
165
+ - Conventional Commits: `feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:`
166
+ - No AI attribution in commit messages.
167
+
168
+ ## Build & Test
169
+
170
+ ```bash
171
+ pip install -e ".[dev]" --break-system-packages
172
+ pytest
173
+ pytest --doctest-modules opsward/
174
+ ```
opsward-0.0.2/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Thor Whalen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
opsward-0.0.2/PKG-INFO ADDED
@@ -0,0 +1,135 @@
1
+ Metadata-Version: 2.4
2
+ Name: opsward
3
+ Version: 0.0.2
4
+ Summary: Diagnose, generate, and maintain the AI agent setup of your projects — CLAUDE.md, skills, subagents, rules, and supporting docs.
5
+ Project-URL: Homepage, https://github.com/thorwhalen/opsward
6
+ Project-URL: Repository, https://github.com/thorwhalen/opsward
7
+ Project-URL: Documentation, https://thorwhalen.github.io/opsward
8
+ Author: Thor Whalen
9
+ License: mit
10
+ License-File: LICENSE
11
+ Keywords: ai-agents,claude,code-quality,developer-tools,documentation
12
+ Requires-Python: >=3.10
13
+ Requires-Dist: argh>=0.31
14
+ Provides-Extra: dev
15
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
16
+ Requires-Dist: pytest>=7.0; extra == 'dev'
17
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
18
+ Provides-Extra: docs
19
+ Requires-Dist: sphinx-rtd-theme>=1.0; extra == 'docs'
20
+ Requires-Dist: sphinx>=6.0; extra == 'docs'
21
+ Description-Content-Type: text/markdown
22
+
23
+ # opsward
24
+
25
+ Diagnose, generate, and maintain the AI agent setup of your projects —
26
+ CLAUDE.md, skills, subagents, rules, and supporting docs.
27
+
28
+ ## Install
29
+
30
+ ```bash
31
+ pip install opsward
32
+ ```
33
+
34
+ ## Quick Start
35
+
36
+ ### Diagnose
37
+
38
+ Score your project's AI setup health:
39
+
40
+ ```bash
41
+ opsward diagnose-cmd .
42
+ ```
43
+
44
+ ```
45
+ Diagnosis Report: myproject
46
+ Project type: python
47
+ Overall score: 72/100 (Grade: C)
48
+
49
+ Components:
50
+ CLAUDE.md quality [################....] 81/100
51
+ Documentation [##############......] 70/100
52
+ Skills [############........] 60/100
53
+ Setup (rules/agents/hooks) [##########..........] 50/100
54
+ Cross-references [####################] 100/100
55
+
56
+ Missing:
57
+ [ ] docs_guide.md
58
+ [ ] docs/known_issues.md
59
+
60
+ Suggestions:
61
+ 1. Create a docs_guide.md to index your documentation
62
+ 2. Consider adding hooks in .claude/hooks.json
63
+ ```
64
+
65
+ ### Generate
66
+
67
+ Create missing artifacts (dry run by default):
68
+
69
+ ```bash
70
+ opsward generate-cmd .
71
+ opsward generate-cmd . --write # actually create files
72
+ ```
73
+
74
+ Generates CLAUDE.md, docs (architecture, conventions, known_issues, etc.),
75
+ skills (diagnose-setup, maintain-docs), and agents (setup-auditor) —
76
+ only what's missing, never overwrites existing files.
77
+
78
+ ### Maintain
79
+
80
+ Find stale references and drift:
81
+
82
+ ```bash
83
+ opsward maintain-cmd .
84
+ ```
85
+
86
+ ```
87
+ myproject: 3 issue(s)
88
+
89
+ [stale_path] CLAUDE.md references `src/old_module.py` but it does not exist
90
+ [sync_issue] `new_doc.md` exists in docs/ but is not listed in docs_guide.md
91
+ [empty_doc] `conventions.md` appears to be an empty stub (12 bytes)
92
+ ```
93
+
94
+ ## What It Checks
95
+
96
+ **CLAUDE.md quality** (6 dimensions):
97
+ - Commands & workflows — are build/test/lint commands documented?
98
+ - Architecture clarity — is there a module map with role descriptions?
99
+ - Conventions — are project-specific style rules present?
100
+ - Conciseness — is the file scannable, not bloated?
101
+ - Currency — do referenced paths actually exist?
102
+ - Actionability — are instructions specific enough to act on?
103
+
104
+ **Documentation completeness**: docs_guide.md, architecture.md, conventions.md,
105
+ known_issues.md, and content quality.
106
+
107
+ **Skills & agents**: SKILL.md presence, descriptions, setup-auditor agent.
108
+
109
+ **Cross-references**: paths in CLAUDE.md validated against the filesystem.
110
+
111
+ **Overall health**: weighted score (A–F grade) combining all components.
112
+
113
+ ## Output Formats
114
+
115
+ All commands support `--format json` for machine-parseable output:
116
+
117
+ ```bash
118
+ opsward diagnose-cmd . --format json
119
+ opsward generate-cmd . --format json
120
+ opsward maintain-cmd . --format json
121
+ ```
122
+
123
+ ## Python API
124
+
125
+ ```python
126
+ from opsward import scan, diagnose, generate, maintain
127
+
128
+ sr = scan('.')
129
+ report = diagnose(sr)
130
+ print(report) # human-readable report card
131
+ print(report.grade) # 'A', 'B', 'C', 'D', or 'F'
132
+
133
+ files = generate(sr) # list[GeneratedFile]
134
+ issues = maintain(sr) # list[MaintenanceSuggestion]
135
+ ```