sherparc 0.8.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.
- sherparc-0.8.1/LICENSE +161 -0
- sherparc-0.8.1/PKG-INFO +14 -0
- sherparc-0.8.1/README.md +289 -0
- sherparc-0.8.1/pyproject.toml +37 -0
- sherparc-0.8.1/setup.cfg +4 -0
- sherparc-0.8.1/src/sherpa/__init__.py +1 -0
- sherparc-0.8.1/src/sherpa/apply/__init__.py +614 -0
- sherparc-0.8.1/src/sherpa/apply/adopt.py +579 -0
- sherparc-0.8.1/src/sherpa/apply/assets/sherpa-outcome.py +258 -0
- sherparc-0.8.1/src/sherpa/apply/render.py +701 -0
- sherparc-0.8.1/src/sherpa/apply/state.py +129 -0
- sherparc-0.8.1/src/sherpa/apply/status.py +173 -0
- sherparc-0.8.1/src/sherpa/atomic.py +25 -0
- sherparc-0.8.1/src/sherpa/check.py +383 -0
- sherparc-0.8.1/src/sherpa/cli.py +463 -0
- sherparc-0.8.1/src/sherpa/config.py +130 -0
- sherparc-0.8.1/src/sherpa/doctor.py +231 -0
- sherparc-0.8.1/src/sherpa/gitinfo.py +144 -0
- sherparc-0.8.1/src/sherpa/model.py +229 -0
- sherparc-0.8.1/src/sherpa/plan/__init__.py +122 -0
- sherparc-0.8.1/src/sherpa/plan/rules.py +436 -0
- sherparc-0.8.1/src/sherpa/plan/yamlio.py +262 -0
- sherparc-0.8.1/src/sherpa/scan/__init__.py +70 -0
- sherparc-0.8.1/src/sherpa/scan/generators.py +370 -0
- sherparc-0.8.1/src/sherpa/scan/t0_git.py +256 -0
- sherparc-0.8.1/src/sherpa/scan/t1_modules.py +606 -0
- sherparc-0.8.1/src/sherpa/schema.py +86 -0
- sherparc-0.8.1/src/sherpa/schemas/codebase-model.schema.json +619 -0
- sherparc-0.8.1/src/sherpa/schemas/harness-plan.schema.json +171 -0
- sherparc-0.8.1/src/sherpa/schemas/harness-state.schema.json +37 -0
- sherparc-0.8.1/src/sherpa/update.py +327 -0
- sherparc-0.8.1/src/sherparc.egg-info/PKG-INFO +14 -0
- sherparc-0.8.1/src/sherparc.egg-info/SOURCES.txt +52 -0
- sherparc-0.8.1/src/sherparc.egg-info/dependency_links.txt +1 -0
- sherparc-0.8.1/src/sherparc.egg-info/entry_points.txt +2 -0
- sherparc-0.8.1/src/sherparc.egg-info/requires.txt +7 -0
- sherparc-0.8.1/src/sherparc.egg-info/top_level.txt +1 -0
- sherparc-0.8.1/tests/test_adopt.py +663 -0
- sherparc-0.8.1/tests/test_apply.py +1387 -0
- sherparc-0.8.1/tests/test_architecture_docs.py +51 -0
- sherparc-0.8.1/tests/test_check.py +287 -0
- sherparc-0.8.1/tests/test_cli.py +15 -0
- sherparc-0.8.1/tests/test_config.py +24 -0
- sherparc-0.8.1/tests/test_doctor.py +218 -0
- sherparc-0.8.1/tests/test_generators.py +137 -0
- sherparc-0.8.1/tests/test_gitinfo.py +94 -0
- sherparc-0.8.1/tests/test_plan.py +698 -0
- sherparc-0.8.1/tests/test_remove.py +178 -0
- sherparc-0.8.1/tests/test_render_demo.py +59 -0
- sherparc-0.8.1/tests/test_scan.py +171 -0
- sherparc-0.8.1/tests/test_schema.py +167 -0
- sherparc-0.8.1/tests/test_t0_git.py +172 -0
- sherparc-0.8.1/tests/test_t1_modules.py +521 -0
- sherparc-0.8.1/tests/test_update.py +500 -0
sherparc-0.8.1/LICENSE
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
Sherpa — Copyright (c) 2026 Andrei Chirila
|
|
2
|
+
|
|
3
|
+
Required Notice: Copyright Andrei Chirila (https://github.com/sherparc/Sherpa)
|
|
4
|
+
|
|
5
|
+
Sherpa is licensed under the PolyForm Small Business License 1.0.0 or the
|
|
6
|
+
PolyForm Noncommercial License 1.0.0, at your option
|
|
7
|
+
(SPDX: PolyForm-Small-Business-1.0.0 OR PolyForm-Noncommercial-1.0.0).
|
|
8
|
+
Both texts follow below, unchanged. In short: free for personal use, for
|
|
9
|
+
noncommercial organisations, and for companies with fewer than 100 people and
|
|
10
|
+
under USD 1M revenue; a company above those limits needs a commercial licence
|
|
11
|
+
— a.chirila87@gmail.com. Reasoning: docs/adr/0051-public-release-polyform-small-business-or-noncommercial.md.
|
|
12
|
+
|
|
13
|
+
Output exception (an additional permission granted by the licensor): files
|
|
14
|
+
that Sherpa generates in your repository — plans, state files, owner docs,
|
|
15
|
+
agent and skill definitions, and any other output of `sherpa plan` or
|
|
16
|
+
`sherpa apply` — belong to you. They carry no obligation under either licence,
|
|
17
|
+
regardless of how you obtained Sherpa.
|
|
18
|
+
|
|
19
|
+
================================================================================
|
|
20
|
+
|
|
21
|
+
# PolyForm Small Business License 1.0.0
|
|
22
|
+
|
|
23
|
+
<https://polyformproject.org/licenses/small-business/1.0.0>
|
|
24
|
+
|
|
25
|
+
## Acceptance
|
|
26
|
+
|
|
27
|
+
In order to get any license under these terms, you must agree to them as both strict obligations and conditions to all your licenses.
|
|
28
|
+
|
|
29
|
+
## Copyright License
|
|
30
|
+
|
|
31
|
+
The licensor grants you a copyright license for the software to do everything you might do with the software that would otherwise infringe the licensor's copyright in it for any permitted purpose. However, you may only distribute the software according to [Distribution License](#distribution-license) and make changes or new works based on the software according to [Changes and New Works License](#changes-and-new-works-license).
|
|
32
|
+
|
|
33
|
+
## Distribution License
|
|
34
|
+
|
|
35
|
+
The licensor grants you an additional copyright license to distribute copies of the software. Your license to distribute covers distributing the software with changes and new works permitted by [Changes and New Works License](#changes-and-new-works-license).
|
|
36
|
+
|
|
37
|
+
## Notices
|
|
38
|
+
|
|
39
|
+
You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms or the URL for them above, as well as copies of any plain-text lines beginning with `Required Notice:` that the licensor provided with the software. For example:
|
|
40
|
+
|
|
41
|
+
> Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
|
|
42
|
+
|
|
43
|
+
## Changes and New Works License
|
|
44
|
+
|
|
45
|
+
The licensor grants you an additional copyright license to make changes and new works based on the software for any permitted purpose.
|
|
46
|
+
|
|
47
|
+
## Patent License
|
|
48
|
+
|
|
49
|
+
The licensor grants you a patent license for the software that covers patent claims the licensor can license, or becomes able to license, that you would infringe by using the software.
|
|
50
|
+
|
|
51
|
+
## Fair Use
|
|
52
|
+
|
|
53
|
+
You may have "fair use" rights for the software under the law. These terms do not limit them.
|
|
54
|
+
|
|
55
|
+
## Small Business
|
|
56
|
+
|
|
57
|
+
Use of the software for the benefit of your company is use for a permitted purpose if your company has fewer than 100 total individuals working as employees and independent contractors, and less than 1,000,000 USD (2019) total revenue in the prior tax year. Adjust this revenue threshold for inflation according to the United States Bureau of Labor Statistics' consumer price index for all urban consumers, U.S. city average, for all items, not seasonally adjusted, with 1982–1984=100 reference base.
|
|
58
|
+
|
|
59
|
+
## No Other Rights
|
|
60
|
+
|
|
61
|
+
These terms do not allow you to sublicense or transfer any of your licenses to anyone else, or prevent the licensor from granting licenses to anyone else. These terms do not imply any other licenses.
|
|
62
|
+
|
|
63
|
+
## Patent Defense
|
|
64
|
+
|
|
65
|
+
If you make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
|
|
66
|
+
|
|
67
|
+
## Violations
|
|
68
|
+
|
|
69
|
+
The first time you are notified in writing that you have violated any of these terms, or done anything with the software not covered by your licenses, your licenses can nonetheless continue if you come into full compliance with these terms, and take practical steps to correct past violations, within 32 days of receiving notice. Otherwise, all your licenses end immediately.
|
|
70
|
+
|
|
71
|
+
## No Liability
|
|
72
|
+
|
|
73
|
+
***As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.***
|
|
74
|
+
|
|
75
|
+
## Definitions
|
|
76
|
+
|
|
77
|
+
The **licensor** is the individual or entity offering these terms, and the **software** is the software the licensor makes available under these terms.
|
|
78
|
+
|
|
79
|
+
**You** refers to the individual or entity agreeing to these terms.
|
|
80
|
+
|
|
81
|
+
**Your company** is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. **Control** means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
|
|
82
|
+
|
|
83
|
+
**Your licenses** are all the licenses granted to you for the software under these terms.
|
|
84
|
+
|
|
85
|
+
**Use** means anything you do with the software requiring one of your licenses.
|
|
86
|
+
|
|
87
|
+
================================================================================
|
|
88
|
+
|
|
89
|
+
# PolyForm Noncommercial License 1.0.0
|
|
90
|
+
|
|
91
|
+
<https://polyformproject.org/licenses/noncommercial/1.0.0>
|
|
92
|
+
|
|
93
|
+
## Acceptance
|
|
94
|
+
|
|
95
|
+
In order to get any license under these terms, you must agree to them as both strict obligations and conditions to all your licenses.
|
|
96
|
+
|
|
97
|
+
## Copyright License
|
|
98
|
+
|
|
99
|
+
The licensor grants you a copyright license for the software to do everything you might do with the software that would otherwise infringe the licensor's copyright in it for any permitted purpose. However, you may only distribute the software according to [Distribution License](#distribution-license) and make changes or new works based on the software according to [Changes and New Works License](#changes-and-new-works-license).
|
|
100
|
+
|
|
101
|
+
## Distribution License
|
|
102
|
+
|
|
103
|
+
The licensor grants you an additional copyright license to distribute copies of the software. Your license to distribute covers distributing the software with changes and new works permitted by [Changes and New Works License](#changes-and-new-works-license).
|
|
104
|
+
|
|
105
|
+
## Notices
|
|
106
|
+
|
|
107
|
+
You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms or the URL for them above, as well as copies of any plain-text lines beginning with `Required Notice:` that the licensor provided with the software. For example:
|
|
108
|
+
|
|
109
|
+
> Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
|
|
110
|
+
|
|
111
|
+
## Changes and New Works License
|
|
112
|
+
|
|
113
|
+
The licensor grants you an additional copyright license to make changes and new works based on the software for any permitted purpose.
|
|
114
|
+
|
|
115
|
+
## Patent License
|
|
116
|
+
|
|
117
|
+
The licensor grants you a patent license for the software that covers patent claims the licensor can license, or becomes able to license, that you would infringe by using the software.
|
|
118
|
+
|
|
119
|
+
## Noncommercial Purposes
|
|
120
|
+
|
|
121
|
+
Any noncommercial purpose is a permitted purpose.
|
|
122
|
+
|
|
123
|
+
## Personal Uses
|
|
124
|
+
|
|
125
|
+
Personal use for research, experiment, and testing for the benefit of public knowledge, personal study, private entertainment, hobby projects, amateur pursuits, or religious observance, without any anticipated commercial application, is use for a permitted purpose.
|
|
126
|
+
|
|
127
|
+
## Noncommercial Organizations
|
|
128
|
+
|
|
129
|
+
Use by any charitable organization, educational institution, public research organization, public safety or health organization, environmental protection organization, or government institution is use for a permitted purpose regardless of the source of funding or obligations resulting from the funding.
|
|
130
|
+
|
|
131
|
+
## Fair Use
|
|
132
|
+
|
|
133
|
+
You may have "fair use" rights for the software under the law. These terms do not limit them.
|
|
134
|
+
|
|
135
|
+
## No Other Rights
|
|
136
|
+
|
|
137
|
+
These terms do not allow you to sublicense or transfer any of your licenses to anyone else, or prevent the licensor from granting licenses to anyone else. These terms do not imply any other licenses.
|
|
138
|
+
|
|
139
|
+
## Patent Defense
|
|
140
|
+
|
|
141
|
+
If you make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
|
|
142
|
+
|
|
143
|
+
## Violations
|
|
144
|
+
|
|
145
|
+
The first time you are notified in writing that you have violated any of these terms, or done anything with the software not covered by your licenses, your licenses can nonetheless continue if you come into full compliance with these terms, and take practical steps to correct past violations, within 32 days of receiving notice. Otherwise, all your licenses end immediately.
|
|
146
|
+
|
|
147
|
+
## No Liability
|
|
148
|
+
|
|
149
|
+
***As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.***
|
|
150
|
+
|
|
151
|
+
## Definitions
|
|
152
|
+
|
|
153
|
+
The **licensor** is the individual or entity offering these terms, and the **software** is the software the licensor makes available under these terms.
|
|
154
|
+
|
|
155
|
+
**You** refers to the individual or entity agreeing to these terms.
|
|
156
|
+
|
|
157
|
+
**Your company** is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. **Control** means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
|
|
158
|
+
|
|
159
|
+
**Your licenses** are all the licenses granted to you for the software under these terms.
|
|
160
|
+
|
|
161
|
+
**Use** means anything you do with the software requiring one of your licenses.
|
sherparc-0.8.1/PKG-INFO
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sherparc
|
|
3
|
+
Version: 0.8.1
|
|
4
|
+
Summary: Generic AI-harness generator: scan the codebase, plan owner docs, agents and skills, create them after approval.
|
|
5
|
+
License-Expression: PolyForm-Small-Business-1.0.0 OR PolyForm-Noncommercial-1.0.0
|
|
6
|
+
Requires-Python: >=3.12
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Dist: pyyaml>=6
|
|
9
|
+
Provides-Extra: dev
|
|
10
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
11
|
+
Requires-Dist: pytest-cov>=5; extra == "dev"
|
|
12
|
+
Requires-Dist: jsonschema>=4; extra == "dev"
|
|
13
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
14
|
+
Dynamic: license-file
|
sherparc-0.8.1/README.md
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# Sherpa
|
|
4
|
+
|
|
5
|
+
<img src="assets/sherpa-mark.png" width="132" alt="Sherpa">
|
|
6
|
+
|
|
7
|
+
**Your repository grows. Your AI agents lose the plot.**
|
|
8
|
+
|
|
9
|
+
Sherpa analyses your codebase deterministically (like CodeScene) and plans the knowledge architecture for AI assistants from it (like Terraform): owner docs, specialised agents, skills, librarians, evals. You review the plan — Sherpa sets it up after your approval.
|
|
10
|
+
|
|
11
|
+
Sherpa reads your git history and gives a reason for every proposal — and for every no. It writes into the repository you already have, for the runtimes you already use: Claude Code natively, every `AGENTS.md` reader (Codex, Cursor, Copilot, Gemini CLI, OpenCode, Hermes) through one neutral core, one thin adapter per host on the roadmap.
|
|
12
|
+
|
|
13
|
+
[](https://github.com/sherparc/Sherpa/actions/workflows/ci.yml)
|
|
14
|
+

|
|
15
|
+

|
|
16
|
+
[](https://github.com/sherparc/Sherpa/releases)
|
|
17
|
+
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
<a href="assets/demo.svg"><img src="assets/demo.svg" alt="sherpa plan on the Sherpa repository itself: five proposals, three reasoned no's, every line with its evidence" width="100%"></a>
|
|
23
|
+
|
|
24
|
+
`sherpa plan .` on this repository — the real output, rendered as an SVG by [scripts/render-demo.py](scripts/render-demo.py) and refreshed with every release. An agent for the whole package was proposed, rejected by hand, and the rejection is kept (`[reject]`); two small modules get a reasoned no with the knob that would change it.
|
|
25
|
+
|
|
26
|
+
## From repo to AI harness in 60 seconds
|
|
27
|
+
|
|
28
|
+
Live today — real output on a test repo with five Python modules, Django migrations and a test suite
|
|
29
|
+
(`active_repo` in [tests/test_plan.py](tests/test_plan.py), frozen as a [golden](tests/goldens/active-console.txt)):
|
|
30
|
+
|
|
31
|
+
```console
|
|
32
|
+
$ sherpa plan .
|
|
33
|
+
harness-plan.yaml — 6 proposals, 4 reasoned no's
|
|
34
|
+
+ outcome shop mandatory: no harness without an outcome signal (ADR-0008) ✓
|
|
35
|
+
+ owner-doc pay 24 commits/90d, 1 dependents ✓ · 40 files ✓
|
|
36
|
+
+ owner-doc core 1 commits/90d, 2 dependents ✓ · 3 files ✓
|
|
37
|
+
+ agent pay rank 1/4 churn ✓ · 24 commits/90d ✓ · 40 files ✓ · 2 authors ✓
|
|
38
|
+
+ test-infra suite 26 commits/90d vs. 24 (pay) ✓
|
|
39
|
+
+ skill regenerate-django-migrations svc/pay/pay/migrations · 6 generated files, 1 configs ✓
|
|
40
|
+
- owner-doc web 1 commits/90d, 0 dependents ✓ · 3 files ✗
|
|
41
|
+
- owner-doc old 0 commits/90d, 0 dependents ✗ · 2 files ✗
|
|
42
|
+
- librarian pay rank 1/4 momentum ✓ · 24 commits/30d, 24/90d ✗
|
|
43
|
+
- librarian core rank 2/4 momentum ✓ · 1 commits/30d, 1/90d ✗
|
|
44
|
+
1 dormant units without owner doc (0 commits/90d, 0 dependents): old — the first commit turns them into a proposal; each is listed above as a no.
|
|
45
|
+
1 small units without owner doc (< 5 files, 0 dependents): web — listed above as no's; owner_doc_min_files in sherpa.toml [plan] moves the floor, a dependent overrides it.
|
|
46
|
+
not listed, out of reach: 2 units for agent (rank > 1 and < 20 commits/90d), 1 for librarian (rank > 2 and below both floors).
|
|
47
|
+
→ .sherpa/harness-plan.yaml
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Every line can be recomputed: the rank from the ranking in the plan header, the floors from `sherpa.toml [plan]`.
|
|
51
|
+
The migrations directory gets no agent but a skill with source, config and command — **generated code is
|
|
52
|
+
regenerated, not explained.** Dormant modules and everything out of reach show up in the notes; nothing disappears
|
|
53
|
+
silently.
|
|
54
|
+
|
|
55
|
+
Then `sherpa apply` — dry run first, like `terraform plan` (golden [active-apply-console.txt](tests/goldens/active-apply-console.txt)):
|
|
56
|
+
|
|
57
|
+
```console
|
|
58
|
+
$ sherpa apply .
|
|
59
|
+
targets: claude, agents-md · home: .agents
|
|
60
|
+
sherpa apply — plan origin/main@5db69c4ddd: 10 entries, 5 selected → 18 files
|
|
61
|
+
+ .agents/docs/modules/core.md owner-doc core new
|
|
62
|
+
+ .agents/docs/modules/pay.md owner-doc pay new
|
|
63
|
+
+ .agents/docs/modules/suite.md test-infra suite new
|
|
64
|
+
+ .agents/scripts/sherpa-check.py harness new
|
|
65
|
+
+ .agents/skills/regenerate-django-migrations/SKILL.md skill regenerate-django-migrations new
|
|
66
|
+
+ .claude/agents/pay.md agent pay new
|
|
67
|
+
+ .claude/hooks/sherpa-outcome.py harness new
|
|
68
|
+
+ .claude/settings.json harness new
|
|
69
|
+
+ .claude/skills/regenerate-django-migrations/SKILL.md skill regenerate-django-migrations new
|
|
70
|
+
+ .sherpa/telemetry/.gitignore harness new
|
|
71
|
+
+ AGENTS.md harness new
|
|
72
|
+
+ CLAUDE.md harness new
|
|
73
|
+
+ svc/core/AGENTS.md owner-doc core new
|
|
74
|
+
+ svc/core/CLAUDE.md owner-doc core new
|
|
75
|
+
+ svc/pay/AGENTS.md owner-doc pay new
|
|
76
|
+
+ svc/pay/CLAUDE.md owner-doc pay new
|
|
77
|
+
+ tests/suite/AGENTS.md test-infra suite new
|
|
78
|
+
+ tests/suite/CLAUDE.md test-infra suite new
|
|
79
|
+
18 to add, 0 to change, 0 unchanged, 0 skipped.
|
|
80
|
+
apply? [y/N] y
|
|
81
|
+
check: 0 FAIL, 0 WARN
|
|
82
|
+
18 files written · harness_rev c38498363846 → .sherpa/state.json
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The owner doc under `.agents/` gets a facts block from the scanner (path, LOC, commits, authors, dependencies,
|
|
86
|
+
dependents, tests, hotspots — [golden](tests/goldens/active-owner-doc-pay.md)); every module gets a nested
|
|
87
|
+
`AGENTS.md` with its facts ([golden](tests/goldens/active-agents-md-pay.md)) — the file Codex, Cursor, Gemini CLI
|
|
88
|
+
and Copilot load when they work there — and a `CLAUDE.md` that imports it; the Claude agent gets a knowledge
|
|
89
|
+
manifest that points at the owner doc ([golden](tests/goldens/active-agent-pay.md)); the migrations directory
|
|
90
|
+
gets its skill; the outcome hook labels every Claude Code execution with the harness version from day one. Run it again: eighteen `=`, `nothing to do.`
|
|
91
|
+
Sherpa owns only the marked blocks — write anything else into those files, it stays.
|
|
92
|
+
|
|
93
|
+
Already have a harness? `sherpa adopt` takes it into the state without changing a byte — like `terraform import`
|
|
94
|
+
(golden [active-adopt-console.txt](tests/goldens/active-adopt-console.txt)):
|
|
95
|
+
|
|
96
|
+
```console
|
|
97
|
+
$ sherpa adopt .
|
|
98
|
+
sherpa adopt — home .claude · targets claude: 7 harness files
|
|
99
|
+
a .claude/agents/ops.md agent no unit matches
|
|
100
|
+
a .claude/agents/pay-expert.md agent → agent pay (mentions svc/pay 170×)
|
|
101
|
+
a .claude/docs/modules/pay.md doc at sherpa's path, yours — covers the entry
|
|
102
|
+
? .claude/notes.txt unknown yours
|
|
103
|
+
· CLAUDE.md root no sherpa markers — `apply` appends its block (ADR-0016)
|
|
104
|
+
gaps:
|
|
105
|
+
- .claude/agents/pay-expert.md: 175 lines, no knowledge manifest — rotation candidate, facts belong in an owner doc
|
|
106
|
+
- .claude/docs/modules/legacy.md: no unit matches by name or path mentions — moved, renamed or not a module doc
|
|
107
|
+
state: 6 adopted, 0 rebuilt, 0 kept, 0 dropped · harness_rev 592b1a201d0c → .sherpa/state.json · 2 plan entries covered → .sherpa/harness-plan.yaml
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The next `sherpa plan` shows `[covered by .claude/agents/pay-expert.md]` on the agent entry and `apply` creates
|
|
111
|
+
nothing there ([golden](tests/goldens/active-plan-covered-console.txt)). The same command rebuilds a lost or torn
|
|
112
|
+
`.sherpa/state.json` from the files — same `harness_rev` as `apply` wrote (ADR-0017).
|
|
113
|
+
|
|
114
|
+
- `sherpa scan` 🟢 **Live** — deterministic codebase model (git churn, hotspots, modules, dependencies, generators)
|
|
115
|
+
- `sherpa plan` 🟢 **Live** — proposals and reasoned no's with evidence as YAML; decisions survive a re-plan or come from the command line (`--accept agent:pay`)
|
|
116
|
+
- `sherpa apply` 🟢 **Live** — dry run first, managed blocks, state file, outcome hook, checker with rollback; targets `claude` and `agents-md` from one neutral core
|
|
117
|
+
- `sherpa status` · `sherpa check` 🟢 **Live** — drift per file and block, structural rules, outcome labels per harness version
|
|
118
|
+
- `sherpa adopt` 🟢 **Live** — take an existing harness into the state without changing a byte; files that already fill a plan entry cover it, and a nested `AGENTS.md` at a unit's own path is its owner doc (no skeleton next to it); a lost state is rebuilt from the files
|
|
119
|
+
- `sherpa doctor` · `sherpa self-update` 🟢 **Live** — every prerequisite with a fix; the next release via the installer that owns this copy; a daily hint that never blocks
|
|
120
|
+
|
|
121
|
+
Documentation: [docs/index.md](docs/index.md) — [getting started](docs/getting-started.md), one reference page per command ([scan](docs/commands/scan.md), [plan](docs/commands/plan.md), [apply](docs/commands/apply.md), [adopt](docs/commands/adopt.md), [status](docs/commands/status.md), [check](docs/commands/check.md), [doctor](docs/commands/doctor.md), [self-update](docs/commands/self-update.md)), [configuration](docs/reference/configuration.md); milestones: [docs/plan.md](docs/plan.md).
|
|
122
|
+
|
|
123
|
+
## Quick start
|
|
124
|
+
|
|
125
|
+
One line, no clone — the wheel `sherparc` is on [PyPI](https://pypi.org/project/sherparc/) and attached to every [release](https://github.com/sherparc/Sherpa/releases); `sherpa self-update` fetches the next one:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
uv tool install sherparc # or: pipx install sherparc; from the repository: …install git+https://github.com/sherparc/Sherpa.git
|
|
129
|
+
sherpa doctor # Python, git, origin, trunk, runtime, layout, nested repositories, install, update — with a fix each
|
|
130
|
+
sherpa plan /path/to/repo # scans when needed → .sherpa/harness-plan.yaml
|
|
131
|
+
sherpa apply /path/to/repo # dry run, then asks → .claude/**, .sherpa/state.json
|
|
132
|
+
sherpa adopt /path/to/repo # an existing harness enters the state, not a byte changes
|
|
133
|
+
sherpa status /path/to/repo # drift, checks, outcome labels
|
|
134
|
+
sherpa check /path/to/repo # the structural rules alone (also as a deployed copy, no sherpa needed)
|
|
135
|
+
sherpa apply /path/to/repo --remove # the uninstall: takes back what sherpa wrote and nobody changed
|
|
136
|
+
sherpa scan /path/to/repo --out - # model only, JSON to stdout
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
For development, the classic way:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
git clone git@github.com:sherparc/Sherpa.git && cd Sherpa
|
|
143
|
+
python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Optional `sherpa.toml` in the target repo:
|
|
147
|
+
|
|
148
|
+
```toml
|
|
149
|
+
[scan]
|
|
150
|
+
trunk = "origin/develop" # otherwise: origin/HEAD, then main/master/dev/develop/trunk
|
|
151
|
+
hotspots = 20
|
|
152
|
+
generated = ["gen/**"] # own generator family, extends the built-in ones
|
|
153
|
+
|
|
154
|
+
[plan]
|
|
155
|
+
agent_top = 0.25 # top quartile by commits/90d …
|
|
156
|
+
agent_min_commits_90d = 20 # … and floors; all values in docs/reference/configuration.md
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## What the scanner measures
|
|
160
|
+
|
|
161
|
+
- **T0 git** — trunk detection, commits/authors in 90- and 30-day windows, LOC per file, hotspots (`commits_90d × loc`, generated files excluded), directory churn.
|
|
162
|
+
- **T1 modules** — from manifests for .NET (`.csproj`), Python (`pyproject.toml`), Node (`package.json`), Go (`go.mod`), Rust (`Cargo.toml`), Java (`pom.xml`, Gradle); in-repo dependencies in both directions, test modules and `tested_by`, module churn, conventions (languages, CI, containers).
|
|
163
|
+
- **Change coupling** — which modules change together (Tornhill's temporal coupling), measured only on commits below a size cap so squash-merge trunks stay honest; one row in every facts block: `changes together with: core (15 of 24 commits, 62 %)`. Sub-directories per module make a single-package repository a plan with units too.
|
|
164
|
+
- **Generator families** — EF/Django/Alembic migrations, protobuf, OpenAPI, GraphQL codegen, ResX, `go generate`, snapshots, bundles, lockfiles: per family output, sources, config, central place and regeneration command — by path only, in 30 ms for 15k files.
|
|
165
|
+
- **T2 language adapters** (M3b) — anchors and patterns per language; T0/T1 work without them.
|
|
166
|
+
|
|
167
|
+
All fields are described in the JSON schema: [codebase-model.schema.json](src/sherpa/schemas/codebase-model.schema.json). Details, decisions and interpretation: [docs/concepts/scan.md](docs/concepts/scan.md).
|
|
168
|
+
|
|
169
|
+
## What the planner decides
|
|
170
|
+
|
|
171
|
+
Thresholds are **relative with an absolute floor** — top quartile *and* at least 20 commits, 30 files, 2 authors
|
|
172
|
+
for an agent; top 2 by momentum *and* a floor for a librarian. A five-person repo gets an agent, a fifty-module
|
|
173
|
+
repo does not get thirty. Every no names what is missing and when it flips. Modules and directories without a
|
|
174
|
+
module (`infrastructure/`, `pipelines/`) rank on equal terms; test infrastructure is measured against the most
|
|
175
|
+
active business module. Rules, format and configuration: [docs/concepts/harness-plan.md](docs/concepts/harness-plan.md).
|
|
176
|
+
|
|
177
|
+
### Determinism guarantees
|
|
178
|
+
|
|
179
|
+
- Always against `origin/<trunk>`, never against the checked-out `HEAD` (local branches are invisible).
|
|
180
|
+
- `as_of` = committer date of the trunk rev → same rev, same model, byte-identical (tested).
|
|
181
|
+
- Sorted JSON output, no merge commits in the time windows, no LLM calls in the scanner.
|
|
182
|
+
|
|
183
|
+
## Why Sherpa
|
|
184
|
+
|
|
185
|
+
Why not just write a few `.md` files for Claude or Copilot?
|
|
186
|
+
|
|
187
|
+
- **No more guessing.** Sherpa builds on hard data — commits, authors, LOC, churn — not on gut feeling. Every proposal carries its evidence, every no its reason.
|
|
188
|
+
- **Infrastructure as code for knowledge.** `plan` → approval → `apply`, like Terraform. You see every file before it exists; Sherpa owns only marked blocks inside the files, the rest is yours and stays yours.
|
|
189
|
+
- **Does not wreck your repo.** Sherpa never overwrites what exists — it creates, appends and merges, and rewrites only its own unchanged bytes. Deterministic against `origin/trunk`, local branches invisible, idempotent with a state file, a checker that rolls back a bad write.
|
|
190
|
+
- **Measures itself.** Every `apply` installs the outcome hook first: each Claude Code execution gets a label (`success`, `failed`, `unknown`) stamped with the harness version. A harness change has a number to answer to.
|
|
191
|
+
- **Grows with you.** Librarians keep owner docs current, evals come from the dependency graph, and the outcome shows which harness parts really help — nothing on the market does that.
|
|
192
|
+
|
|
193
|
+
Where the patterns come from:
|
|
194
|
+
|
|
195
|
+
| Proven on the market | What Sherpa takes from it |
|
|
196
|
+
|---|---|
|
|
197
|
+
| Terraform `plan` / `apply` / `import` / state | proposal before change, approval, idempotency, `adopt` for existing harnesses |
|
|
198
|
+
| CodeScene / Tornhill hotspots | churn × complexity instead of gut feeling; relative thresholds with an absolute floor |
|
|
199
|
+
| Backstage catalog / scaffolder | modules as a catalogue, templates seeded once |
|
|
200
|
+
| `AGENTS.md` / Agent Skills (Codex, Cursor, Gemini CLI, Copilot, …) | proximity loading — the closest file wins — filled with measured facts and kept current instead of hand-written |
|
|
201
|
+
| Ansible `blockinfile` | managed blocks inside co-authored files instead of all-or-nothing ownership |
|
|
202
|
+
| Renovate | librarians as bots with scope and cadence |
|
|
203
|
+
| `brew doctor` | `sherpa doctor` for onboarding |
|
|
204
|
+
|
|
205
|
+
## Architecture
|
|
206
|
+
|
|
207
|
+
```mermaid
|
|
208
|
+
flowchart LR
|
|
209
|
+
R[(repo · origin/trunk)] -->|git, manifests| S[sherpa scan]
|
|
210
|
+
S --> M[codebase-model.json]
|
|
211
|
+
M --> P[sherpa plan]
|
|
212
|
+
P --> Y[harness-plan.yaml<br/>proposals + reasoned no's<br/>--accept / --reject]
|
|
213
|
+
Y -->|approval| A[sherpa apply]
|
|
214
|
+
A --> H["{home}/** owner docs · skills · checker<br/>(home = .agents or .claude)"]
|
|
215
|
+
A --> T["adapters per target<br/>claude: .claude/agents · hooks · CLAUDE.md<br/>agents-md: AGENTS.md root + nested<br/>planned, thin on agents-md: hermes · codex · opencode · copilot · cursor · gemini"]
|
|
216
|
+
A --> ST[.sherpa/state.json · harness_rev]
|
|
217
|
+
T -->|outcome hook| O[.sherpa/telemetry/outcomes.ndjson]
|
|
218
|
+
ST --> Q[sherpa status]
|
|
219
|
+
O --> Q
|
|
220
|
+
H --> C[sherpa check<br/>rollback on a new FAIL]
|
|
221
|
+
T --> C
|
|
222
|
+
H -.->|existing| AD[sherpa adopt] -.-> ST
|
|
223
|
+
P -. planned, M6-lite: comments only .-> L[LLM provider<br/>OpenAI-compatible · Anthropic]
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
- Python 3.12, stdlib-first, one runtime dependency (PyYAML for the plan).
|
|
227
|
+
- Scanner, planner and applier are deterministic today; no LLM call anywhere in the shipped pipeline.
|
|
228
|
+
- Planned (M6-lite): LLMs only in `plan` stage 2, enriching comments, never the entries themselves.
|
|
229
|
+
- Planned (M6-lite): a provider layer without LangChain — local vLLM/Ollama/OpenRouter via the OpenAI API plus Anthropic natively.
|
|
230
|
+
|
|
231
|
+
## Roadmap
|
|
232
|
+
|
|
233
|
+
| Milestone | Content | Status |
|
|
234
|
+
|---|---|---|
|
|
235
|
+
| M0 | skeleton, ADRs, the plan | ✅ |
|
|
236
|
+
| M1 | scanner T0 for every language: trunk, churn, hotspots, file tree, generated files, JSON schema | ✅ |
|
|
237
|
+
| M1a | scanner T1: modules from manifests (6 ecosystems), in-repo deps, `tested_by`, churn per module | ✅ |
|
|
238
|
+
| M2 | `plan` stage 1: units, rank + floor, generator families → skills, reasoned no's, decision keeping | ✅ |
|
|
239
|
+
| M3a | `apply`: dry run, managed blocks, state, outcome hook, checker with rollback; `status`, `check` | ✅ |
|
|
240
|
+
| M3t | target layer: neutral core under `.agents`/`.claude`, adapters `claude` and `agents-md`, nested proximity files | ✅ |
|
|
241
|
+
| M3c | `adopt`: existing harnesses taken over unchanged, covered entries, rebuildable state | ✅ |
|
|
242
|
+
| M2b | distribution: release wheel per tag, `doctor`, `self-update` (API with a token, `git ls-remote` without), daily hint | ✅ |
|
|
243
|
+
| M3d | retro fruit: stamp without rev, sub-units for single-manifest repos, change coupling with a size cap, `plan --accept/--reject`, capped root index | ✅ |
|
|
244
|
+
| M3e | review fruit: `status` names a stale plan, `status --json` and `doctor --json`, manifest tie-break by language share, coupling without the root catch-all, sub-units for a dominant root module, proximity-file budgets in the checker | ✅ |
|
|
245
|
+
| M3f | write safety: `apply` compares every file with the preview's read before writing, never writes through a symlink, writes each file whole or not at all and rolls back on a write error; `adopt` treats a differing base file as yours, takes a stale plan and rebuilds a torn state without a dead end; a dry run never refuses (two homes → assumes `.agents` and says so) and names a target directory that is a repository of its own | ✅ |
|
|
246
|
+
| M3i | the manager sees what exists and takes back what is sherpa's: refuses on a nested repository (`doctor` says it first), a hand-written `covered:` is kept like a decision, the checker fails only in sherpa's own files; `apply` removes a rejected entry's files when they are still sherpa's and `apply --remove` uninstalls — a clean repository is clean again | ✅ |
|
|
247
|
+
| M3j | owner docs where the team already writes them: a nested `AGENTS.md` at a unit's own path covers its owner-doc entry — `plan` sets it from the file, `adopt` reports it, `apply` writes the facts block into the team's file and no skeleton next to it (first slice, ADR-0049) | ✅ |
|
|
248
|
+
| M2c | public release: the licence flipped to PolyForm Small Business or Noncommercial (ADR-0051) ✅ · the contribution path — DCO checked on every pull request, code of conduct, security policy, templates (ADR-0052) ✅ · the wheel on PyPI as `sherparc` through trusted publishing, `self-update` and `doctor` read the index first (ADR-0053, ADR-0054) ✅ · the demo card at the top of this README, Sherpa on itself ✅ · still to do: a changelog, then the announcement | ⏳ |
|
|
249
|
+
| M3h | `hermes` target: Hermes Agent reads the harness (`AGENTS.md` chain, `.agents/skills`), outcome hook for both runtimes, `doctor` checks for trust and hook wiring | ⏳ |
|
|
250
|
+
| M3k | host adapters `codex`, `opencode`, `copilot`, `cursor`, `gemini` — thin on top of `agents-md` like `hermes`: `doctor` names the host, its native rule file only where `AGENTS.md` cannot carry it, the outcome hook where the host has hooks | ⏳ |
|
|
251
|
+
| M5 | outcome evaluation: `status` shows labels per `harness_rev` with `n` and the share of `unknown`; a comparison between revisions from 30 labelled executions each | ⏳ |
|
|
252
|
+
| M7a | runtime plugins: Sherpa installable inside Claude Code (plugin) and Hermes (bundle) — `/sherpa-plan` with per-entry approval, `/sherpa-apply`, `/sherpa-status`; thin, the CLI does the work | ⏳ |
|
|
253
|
+
| M6-lite | provider layer: thin, framework-free — bring your own key, local models via the OpenAI API, Anthropic natively | ⏳ |
|
|
254
|
+
| M4 | auto-evals from the dependency graph, `status` with a baseline | ⏳ |
|
|
255
|
+
| M6 | `plan` stage 2: LLM enrichment on top of the provider layer | ⏳ |
|
|
256
|
+
| M3b | language adapters `dotnet` + `python` (T2: anchors, patterns) | ⏳ |
|
|
257
|
+
| M7 | librarians, multi-repo | ⏳ |
|
|
258
|
+
|
|
259
|
+
Order from here: M3j's second slice → M3h → M3k → M5 → M7a → M6-lite → M4 → M6 → M3b → M7 (plan §7.3, §9, §9.1, §10, §13).
|
|
260
|
+
|
|
261
|
+
Complete with reasoning: [docs/plan.md](docs/plan.md) · every decision as an ADR: [docs/adr/](docs/adr/README.md)
|
|
262
|
+
|
|
263
|
+
## Related
|
|
264
|
+
|
|
265
|
+
| Project | What it is | Where Sherpa differs |
|
|
266
|
+
|---|---|---|
|
|
267
|
+
| [metaharness](https://github.com/ruvnet/metaharness) | a factory: scaffolds a new, branded agent-harness package (own `npx` CLI, MCP server, signed releases) from a static read of manifests, for ten hosts | Sherpa writes into the repository you have, from its git history, with a reason for every entry and every no, and keeps it current — `adopt`, `status`, outcome labels per harness version |
|
|
268
|
+
| Claude Code `/init`, auto-memory · Hermes Agent's self-written skills | the runtimes' own way to grow a harness: LLM prose, per person, unreviewed | facts from `git log`, deterministic, reviewed in the PR like code, per team and repository; runtime-neutral (plan §9) |
|
|
269
|
+
|
|
270
|
+
## License
|
|
271
|
+
|
|
272
|
+
[PolyForm Small Business 1.0.0](LICENSE) or [PolyForm Noncommercial 1.0.0](LICENSE), at your option: free for personal use, for noncommercial organisations and for companies under 100 people and USD 1M revenue; larger companies need a commercial licence. Everything Sherpa generates in your repo is yours, no strings attached. Reasoning in [ADR-0051](docs/adr/0051-public-release-polyform-small-business-or-noncommercial.md).
|
|
273
|
+
|
|
274
|
+
## Development
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
.venv/bin/pytest -q --cov=sherpa # 439 tests, ~97 % coverage, gate in CI: 90 %
|
|
278
|
+
.venv/bin/ruff check . && .venv/bin/ruff format --check .
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
CI runs with Python 3.12 and 3.13: Linux on every pull request, Linux and Windows on `main`, macOS weekly; a manual run covers all three. Test repos are built programmatically (no corpus in the repo). The repository carries its own harness — `sherpa status .` must be clean before a commit — and an architect agent under [.claude/agents/](.claude/agents/architect.md). Working rules for humans and agents: [CLAUDE.md](CLAUDE.md).
|
|
282
|
+
|
|
283
|
+
`main` changes only through pull requests with squash merge, every commit signed off (DCO). Once per clone, enable the hooks — the guard that refuses direct pushes to `main` and the one that adds the sign-off:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
git config core.hooksPath .githooks
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Contributions: [CONTRIBUTING.md](CONTRIBUTING.md) · security reports: [SECURITY.md](SECURITY.md) · conduct: [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "sherparc" # the PyPI name: "sherpa" is taken, the org name is one word (ADR-0054); import package and CLI stay "sherpa"
|
|
7
|
+
version = "0.8.1"
|
|
8
|
+
description = "Generic AI-harness generator: scan the codebase, plan owner docs, agents and skills, create them after approval."
|
|
9
|
+
license = "PolyForm-Small-Business-1.0.0 OR PolyForm-Noncommercial-1.0.0" # ADR-0051: free for individuals, noncommercial organisations and small companies
|
|
10
|
+
license-files = ["LICENSE"]
|
|
11
|
+
requires-python = ">=3.12"
|
|
12
|
+
dependencies = ["pyyaml>=6"] # the only runtime dependency (ADR-0005)
|
|
13
|
+
|
|
14
|
+
[project.scripts]
|
|
15
|
+
sherpa = "sherpa.cli:main"
|
|
16
|
+
|
|
17
|
+
[project.optional-dependencies]
|
|
18
|
+
dev = ["pytest>=8", "pytest-cov>=5", "jsonschema>=4", "ruff>=0.6"] # jsonschema: the reference the stdlib validator is tested against (ADR-0042), never a runtime dependency
|
|
19
|
+
|
|
20
|
+
[tool.setuptools.packages.find]
|
|
21
|
+
where = ["src"]
|
|
22
|
+
|
|
23
|
+
[tool.setuptools.package-data]
|
|
24
|
+
sherpa = ["schemas/*.json", "apply/assets/*.py"]
|
|
25
|
+
|
|
26
|
+
[tool.pytest.ini_options]
|
|
27
|
+
testpaths = ["tests"]
|
|
28
|
+
|
|
29
|
+
[tool.ruff]
|
|
30
|
+
line-length = 120
|
|
31
|
+
target-version = "py312"
|
|
32
|
+
|
|
33
|
+
[tool.ruff.lint]
|
|
34
|
+
select = ["E", "F", "W", "I", "B", "UP"]
|
|
35
|
+
|
|
36
|
+
[tool.ruff.lint.per-file-ignores]
|
|
37
|
+
"tests/*" = ["E501"] # fixture literals (manifest contents) are deliberately long
|
sherparc-0.8.1/setup.cfg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.8.1"
|