aisupervisor 0.1.0b1__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.
- aisupervisor-0.1.0b1/MANIFEST.in +17 -0
- aisupervisor-0.1.0b1/PKG-INFO +99 -0
- aisupervisor-0.1.0b1/PYPI.md +83 -0
- aisupervisor-0.1.0b1/README.md +0 -0
- aisupervisor-0.1.0b1/aisupervisor.egg-info/PKG-INFO +99 -0
- aisupervisor-0.1.0b1/aisupervisor.egg-info/SOURCES.txt +49 -0
- aisupervisor-0.1.0b1/aisupervisor.egg-info/dependency_links.txt +1 -0
- aisupervisor-0.1.0b1/aisupervisor.egg-info/entry_points.txt +3 -0
- aisupervisor-0.1.0b1/aisupervisor.egg-info/top_level.txt +2 -0
- aisupervisor-0.1.0b1/pyproject.toml +36 -0
- aisupervisor-0.1.0b1/registry/__init__.py +1 -0
- aisupervisor-0.1.0b1/registry/__main__.py +5 -0
- aisupervisor-0.1.0b1/registry/cli.py +121 -0
- aisupervisor-0.1.0b1/registry/integrity.py +88 -0
- aisupervisor-0.1.0b1/registry/models.py +212 -0
- aisupervisor-0.1.0b1/registry/probes.py +585 -0
- aisupervisor-0.1.0b1/registry/seed/backend-implementer.json +30 -0
- aisupervisor-0.1.0b1/registry/seed/code-reviewer.json +25 -0
- aisupervisor-0.1.0b1/registry/seed/frontend-implementer.json +29 -0
- aisupervisor-0.1.0b1/registry/seed/overreaching-reviewer.json +29 -0
- aisupervisor-0.1.0b1/registry/seed/product-planner.json +25 -0
- aisupervisor-0.1.0b1/registry/seed/repo-analyst.json +25 -0
- aisupervisor-0.1.0b1/registry/seed/security-reviewer.json +25 -0
- aisupervisor-0.1.0b1/registry/seed/test-runner.json +25 -0
- aisupervisor-0.1.0b1/registry/seed/ui-designer.json +25 -0
- aisupervisor-0.1.0b1/registry/seed/ux-designer.json +25 -0
- aisupervisor-0.1.0b1/registry/server.py +95 -0
- aisupervisor-0.1.0b1/registry/store.py +112 -0
- aisupervisor-0.1.0b1/registry/verify.py +277 -0
- aisupervisor-0.1.0b1/registry/web/index.html +174 -0
- aisupervisor-0.1.0b1/setup.cfg +4 -0
- aisupervisor-0.1.0b1/supervisor/__init__.py +5 -0
- aisupervisor-0.1.0b1/supervisor/__main__.py +5 -0
- aisupervisor-0.1.0b1/supervisor/adapters/__init__.py +0 -0
- aisupervisor-0.1.0b1/supervisor/adapters/base.py +39 -0
- aisupervisor-0.1.0b1/supervisor/adapters/claude_code.py +151 -0
- aisupervisor-0.1.0b1/supervisor/analyze.py +132 -0
- aisupervisor-0.1.0b1/supervisor/artifacts.py +182 -0
- aisupervisor-0.1.0b1/supervisor/capability.py +209 -0
- aisupervisor-0.1.0b1/supervisor/cli.py +850 -0
- aisupervisor-0.1.0b1/supervisor/decide.py +143 -0
- aisupervisor-0.1.0b1/supervisor/display.py +295 -0
- aisupervisor-0.1.0b1/supervisor/metrics.py +63 -0
- aisupervisor-0.1.0b1/supervisor/permission.py +71 -0
- aisupervisor-0.1.0b1/supervisor/pipeline.py +773 -0
- aisupervisor-0.1.0b1/supervisor/registry_client.py +56 -0
- aisupervisor-0.1.0b1/supervisor/runner.py +328 -0
- aisupervisor-0.1.0b1/supervisor/shell.py +104 -0
- aisupervisor-0.1.0b1/supervisor/team.py +139 -0
- aisupervisor-0.1.0b1/supervisor/telemetry.py +221 -0
- aisupervisor-0.1.0b1/supervisor/workspace.py +141 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# 배포본에 무엇을 넣지 **않을지** 정한다.
|
|
2
|
+
#
|
|
3
|
+
# setuptools 의 sdist 는 기본으로 `tests/` 를 통째로 담는다. 그 안에는 이 제품과
|
|
4
|
+
# 무관한 하네스·company 시험 65개가 들어 있고, 올리면 내부 구조가 그대로 공개된다
|
|
5
|
+
# (실측: 638 KB sdist 안에 test_acp_*·test_company_* 가 전부 있었다).
|
|
6
|
+
#
|
|
7
|
+
# 제품은 `supervisor` 와 `registry` 두 패키지뿐이다. 그 밖은 담지 않는다.
|
|
8
|
+
prune tests
|
|
9
|
+
prune harness
|
|
10
|
+
prune company
|
|
11
|
+
prune projects
|
|
12
|
+
prune evolution
|
|
13
|
+
prune docs
|
|
14
|
+
prune beta
|
|
15
|
+
prune _workspace
|
|
16
|
+
prune research
|
|
17
|
+
exclude MEMORY.md CLAUDE.md
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aisupervisor
|
|
3
|
+
Version: 0.1.0b1
|
|
4
|
+
Summary: 목표만 주면 필요한 Agent 를 찾아 검증하고, 권한과 협업 순서까지 구성한다
|
|
5
|
+
Classifier: Development Status :: 4 - Beta
|
|
6
|
+
Classifier: Environment :: Console
|
|
7
|
+
Classifier: Intended Audience :: Developers
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
10
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
11
|
+
Classifier: Operating System :: MacOS
|
|
12
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
13
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# AI Supervisor — **Closed Beta (pre-release)**
|
|
18
|
+
|
|
19
|
+
> **이 판은 0.1.0b1, Closed Beta 시험판입니다.** 정식판이 아닙니다.
|
|
20
|
+
> 참가자 2명과 함께 「전문가 팀 방식이 값을 하는가」를 확인하는 중이고,
|
|
21
|
+
> 그 답에 따라 구조가 바뀔 수 있습니다. 업무에 그대로 의존하지 마십시오.
|
|
22
|
+
|
|
23
|
+
목표만 주면 **필요한 전문가 Agent 를 모아** 일을 시킵니다. Claude Code 를
|
|
24
|
+
대체하지 않고 그 위에서 돕니다.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install aisupervisor
|
|
28
|
+
|
|
29
|
+
cd ~/my-project # 당신의 git 저장소
|
|
30
|
+
supervisor
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
알아야 할 것은 위 두 줄뿐입니다. `init` 도, `--repo` 도, 작업 종류도 치지
|
|
34
|
+
않습니다. Supervisor 가 목표를 읽고 **무슨 일인지 · 혼자 할지 팀을 부를지 ·
|
|
35
|
+
누가 붙을지**를 정하고, 그 이유를 먼저 보여 줍니다.
|
|
36
|
+
|
|
37
|
+
## 무엇이 다른가
|
|
38
|
+
|
|
39
|
+
- **검증된 Agent 만 씁니다.** 처음 실행하면 이 기계의 격리된 임시 저장소에서
|
|
40
|
+
Agent 를 **실제로 돌려 보고**, 통과한 것만 일에 넣습니다. 다른 기계의 검증
|
|
41
|
+
결과를 그대로 믿지 않습니다.
|
|
42
|
+
- **작업마다 권한이 다릅니다.** 기획·설계는 읽기만, 구현자는 쓰기까지,
|
|
43
|
+
시험은 실행까지. 선언하지 않은 도구를 쓰려 하면 막습니다.
|
|
44
|
+
- **말이 아니라 증거로 판정합니다.** 바뀌었다는 파일이 정말 바뀌었는지,
|
|
45
|
+
통과했다는 시험이 **우리가 돌려도** 통과하는지 직접 확인합니다.
|
|
46
|
+
- **뒤 Agent 가 앞 Agent 를 그냥 믿지 않습니다.** 어긋난 것을 발견하면 그
|
|
47
|
+
단계로 되감아 다시 만듭니다.
|
|
48
|
+
|
|
49
|
+
## 지원 환경
|
|
50
|
+
|
|
51
|
+
| | |
|
|
52
|
+
|---|---|
|
|
53
|
+
| Python | **3.10 이상** |
|
|
54
|
+
| 함께 필요한 것 | `git`, [Claude Code CLI](https://docs.claude.com/en/docs/claude-code) (`claude` 명령) |
|
|
55
|
+
| 실측한 OS | **Linux 만** |
|
|
56
|
+
| **Windows** | **아직 실측하지 않았습니다.** 순수 파이썬 휠(`py3-none-any`)이고 배포 코드에 POSIX 전용 호출이 없어 설치는 될 구조지만, 저희가 돌려 본 적은 없습니다 |
|
|
57
|
+
| macOS | 실측하지 않았습니다 (Linux 와 같은 조건으로 봅니다) |
|
|
58
|
+
| 외부 의존성 | **0** — Python 표준 라이브러리만 씁니다 |
|
|
59
|
+
|
|
60
|
+
Claude Code CLI 사용량은 **사용자 본인 계정에서** 나갑니다. 실측: 작은 수정
|
|
61
|
+
30~60초·$0.2 안팎, 큰 기능 하나에 팀이 붙으면 **30~40분·$10 이상**.
|
|
62
|
+
|
|
63
|
+
## 알려진 한계
|
|
64
|
+
|
|
65
|
+
- **브라우저에서의 화면 동작 확인은 사람 몫입니다.** 서버가 준 HTML 은
|
|
66
|
+
확인하지만 클릭 이후는 자동 시험이 아닙니다
|
|
67
|
+
- **자동 재작업(되감기)은 한 실행에 2회**까지입니다. 넘으면 남은 지적은
|
|
68
|
+
기록만 되고 반영되지 않습니다
|
|
69
|
+
- **팀 방식은 느리고 비쌉니다.** 같은 앱을 혼자 344초·$1.86 에, 팀은
|
|
70
|
+
2562초·$10.86 에 만들었고 **둘 다 동작했습니다.** 작은 일은 알아서 혼자
|
|
71
|
+
처리하지만, 큰 일에 팀을 붙이는 판단이 늘 옳다고 보지 않습니다
|
|
72
|
+
- 시험이 없는 저장소에서는 완료를 판정할 수 없습니다 (`--test-command` 로
|
|
73
|
+
알려 주시면 이어서 판정합니다)
|
|
74
|
+
- 저장소 여러 개를 한 번에 다루지 못합니다
|
|
75
|
+
|
|
76
|
+
## 이번 판에서 **하지 않는** 일
|
|
77
|
+
|
|
78
|
+
- **운영 배포(`deploy.production`)**
|
|
79
|
+
- **비밀값 접근(`secret.read`)**
|
|
80
|
+
- **되돌리기 어려운 마이그레이션 · 파괴적 운영 작업**
|
|
81
|
+
|
|
82
|
+
Agent 가 이런 권한을 요구하면 **실행 전에 멈추고** 사람에게 알립니다.
|
|
83
|
+
승인해서 진행하는 경로는 이번 판에 없습니다.
|
|
84
|
+
|
|
85
|
+
## 소스 코드와 기록
|
|
86
|
+
|
|
87
|
+
- **코드는 당신의 기계를 떠나지 않습니다.** Supervisor 는 서버가 없고 계정도
|
|
88
|
+
로그인도 없습니다. 다만 Claude Code CLI 자체는 Anthropic API 와 통신하며,
|
|
89
|
+
그 범위는 평소 `claude` 를 쓰실 때와 **똑같습니다**
|
|
90
|
+
- 실행 기록은 `~/.supervisor/` 안에만 쌓입니다
|
|
91
|
+
- **기록에 소스 코드가 들어가지 않습니다** — 바뀐 파일의 **개수와 확장자만**
|
|
92
|
+
남고 경로도 내용도 남기지 않습니다. 목표 문장은 흔한 비밀값 모양
|
|
93
|
+
(토큰·비밀번호)을 지운 뒤 남습니다
|
|
94
|
+
- 저희가 기록을 자동으로 가져가지 않습니다. **직접 보내 주실 때만** 봅니다
|
|
95
|
+
(`supervisor report --out 파일`)
|
|
96
|
+
|
|
97
|
+
## 바뀐 코드는 커밋되지 않습니다
|
|
98
|
+
|
|
99
|
+
`git diff` 로 직접 보고 판단하십시오. Supervisor 는 커밋하지 않습니다.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# AI Supervisor — **Closed Beta (pre-release)**
|
|
2
|
+
|
|
3
|
+
> **이 판은 0.1.0b1, Closed Beta 시험판입니다.** 정식판이 아닙니다.
|
|
4
|
+
> 참가자 2명과 함께 「전문가 팀 방식이 값을 하는가」를 확인하는 중이고,
|
|
5
|
+
> 그 답에 따라 구조가 바뀔 수 있습니다. 업무에 그대로 의존하지 마십시오.
|
|
6
|
+
|
|
7
|
+
목표만 주면 **필요한 전문가 Agent 를 모아** 일을 시킵니다. Claude Code 를
|
|
8
|
+
대체하지 않고 그 위에서 돕니다.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pip install aisupervisor
|
|
12
|
+
|
|
13
|
+
cd ~/my-project # 당신의 git 저장소
|
|
14
|
+
supervisor
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
알아야 할 것은 위 두 줄뿐입니다. `init` 도, `--repo` 도, 작업 종류도 치지
|
|
18
|
+
않습니다. Supervisor 가 목표를 읽고 **무슨 일인지 · 혼자 할지 팀을 부를지 ·
|
|
19
|
+
누가 붙을지**를 정하고, 그 이유를 먼저 보여 줍니다.
|
|
20
|
+
|
|
21
|
+
## 무엇이 다른가
|
|
22
|
+
|
|
23
|
+
- **검증된 Agent 만 씁니다.** 처음 실행하면 이 기계의 격리된 임시 저장소에서
|
|
24
|
+
Agent 를 **실제로 돌려 보고**, 통과한 것만 일에 넣습니다. 다른 기계의 검증
|
|
25
|
+
결과를 그대로 믿지 않습니다.
|
|
26
|
+
- **작업마다 권한이 다릅니다.** 기획·설계는 읽기만, 구현자는 쓰기까지,
|
|
27
|
+
시험은 실행까지. 선언하지 않은 도구를 쓰려 하면 막습니다.
|
|
28
|
+
- **말이 아니라 증거로 판정합니다.** 바뀌었다는 파일이 정말 바뀌었는지,
|
|
29
|
+
통과했다는 시험이 **우리가 돌려도** 통과하는지 직접 확인합니다.
|
|
30
|
+
- **뒤 Agent 가 앞 Agent 를 그냥 믿지 않습니다.** 어긋난 것을 발견하면 그
|
|
31
|
+
단계로 되감아 다시 만듭니다.
|
|
32
|
+
|
|
33
|
+
## 지원 환경
|
|
34
|
+
|
|
35
|
+
| | |
|
|
36
|
+
|---|---|
|
|
37
|
+
| Python | **3.10 이상** |
|
|
38
|
+
| 함께 필요한 것 | `git`, [Claude Code CLI](https://docs.claude.com/en/docs/claude-code) (`claude` 명령) |
|
|
39
|
+
| 실측한 OS | **Linux 만** |
|
|
40
|
+
| **Windows** | **아직 실측하지 않았습니다.** 순수 파이썬 휠(`py3-none-any`)이고 배포 코드에 POSIX 전용 호출이 없어 설치는 될 구조지만, 저희가 돌려 본 적은 없습니다 |
|
|
41
|
+
| macOS | 실측하지 않았습니다 (Linux 와 같은 조건으로 봅니다) |
|
|
42
|
+
| 외부 의존성 | **0** — Python 표준 라이브러리만 씁니다 |
|
|
43
|
+
|
|
44
|
+
Claude Code CLI 사용량은 **사용자 본인 계정에서** 나갑니다. 실측: 작은 수정
|
|
45
|
+
30~60초·$0.2 안팎, 큰 기능 하나에 팀이 붙으면 **30~40분·$10 이상**.
|
|
46
|
+
|
|
47
|
+
## 알려진 한계
|
|
48
|
+
|
|
49
|
+
- **브라우저에서의 화면 동작 확인은 사람 몫입니다.** 서버가 준 HTML 은
|
|
50
|
+
확인하지만 클릭 이후는 자동 시험이 아닙니다
|
|
51
|
+
- **자동 재작업(되감기)은 한 실행에 2회**까지입니다. 넘으면 남은 지적은
|
|
52
|
+
기록만 되고 반영되지 않습니다
|
|
53
|
+
- **팀 방식은 느리고 비쌉니다.** 같은 앱을 혼자 344초·$1.86 에, 팀은
|
|
54
|
+
2562초·$10.86 에 만들었고 **둘 다 동작했습니다.** 작은 일은 알아서 혼자
|
|
55
|
+
처리하지만, 큰 일에 팀을 붙이는 판단이 늘 옳다고 보지 않습니다
|
|
56
|
+
- 시험이 없는 저장소에서는 완료를 판정할 수 없습니다 (`--test-command` 로
|
|
57
|
+
알려 주시면 이어서 판정합니다)
|
|
58
|
+
- 저장소 여러 개를 한 번에 다루지 못합니다
|
|
59
|
+
|
|
60
|
+
## 이번 판에서 **하지 않는** 일
|
|
61
|
+
|
|
62
|
+
- **운영 배포(`deploy.production`)**
|
|
63
|
+
- **비밀값 접근(`secret.read`)**
|
|
64
|
+
- **되돌리기 어려운 마이그레이션 · 파괴적 운영 작업**
|
|
65
|
+
|
|
66
|
+
Agent 가 이런 권한을 요구하면 **실행 전에 멈추고** 사람에게 알립니다.
|
|
67
|
+
승인해서 진행하는 경로는 이번 판에 없습니다.
|
|
68
|
+
|
|
69
|
+
## 소스 코드와 기록
|
|
70
|
+
|
|
71
|
+
- **코드는 당신의 기계를 떠나지 않습니다.** Supervisor 는 서버가 없고 계정도
|
|
72
|
+
로그인도 없습니다. 다만 Claude Code CLI 자체는 Anthropic API 와 통신하며,
|
|
73
|
+
그 범위는 평소 `claude` 를 쓰실 때와 **똑같습니다**
|
|
74
|
+
- 실행 기록은 `~/.supervisor/` 안에만 쌓입니다
|
|
75
|
+
- **기록에 소스 코드가 들어가지 않습니다** — 바뀐 파일의 **개수와 확장자만**
|
|
76
|
+
남고 경로도 내용도 남기지 않습니다. 목표 문장은 흔한 비밀값 모양
|
|
77
|
+
(토큰·비밀번호)을 지운 뒤 남습니다
|
|
78
|
+
- 저희가 기록을 자동으로 가져가지 않습니다. **직접 보내 주실 때만** 봅니다
|
|
79
|
+
(`supervisor report --out 파일`)
|
|
80
|
+
|
|
81
|
+
## 바뀐 코드는 커밋되지 않습니다
|
|
82
|
+
|
|
83
|
+
`git diff` 로 직접 보고 판단하십시오. Supervisor 는 커밋하지 않습니다.
|
|
Binary file
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aisupervisor
|
|
3
|
+
Version: 0.1.0b1
|
|
4
|
+
Summary: 목표만 주면 필요한 Agent 를 찾아 검증하고, 권한과 협업 순서까지 구성한다
|
|
5
|
+
Classifier: Development Status :: 4 - Beta
|
|
6
|
+
Classifier: Environment :: Console
|
|
7
|
+
Classifier: Intended Audience :: Developers
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
10
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
11
|
+
Classifier: Operating System :: MacOS
|
|
12
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
13
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# AI Supervisor — **Closed Beta (pre-release)**
|
|
18
|
+
|
|
19
|
+
> **이 판은 0.1.0b1, Closed Beta 시험판입니다.** 정식판이 아닙니다.
|
|
20
|
+
> 참가자 2명과 함께 「전문가 팀 방식이 값을 하는가」를 확인하는 중이고,
|
|
21
|
+
> 그 답에 따라 구조가 바뀔 수 있습니다. 업무에 그대로 의존하지 마십시오.
|
|
22
|
+
|
|
23
|
+
목표만 주면 **필요한 전문가 Agent 를 모아** 일을 시킵니다. Claude Code 를
|
|
24
|
+
대체하지 않고 그 위에서 돕니다.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install aisupervisor
|
|
28
|
+
|
|
29
|
+
cd ~/my-project # 당신의 git 저장소
|
|
30
|
+
supervisor
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
알아야 할 것은 위 두 줄뿐입니다. `init` 도, `--repo` 도, 작업 종류도 치지
|
|
34
|
+
않습니다. Supervisor 가 목표를 읽고 **무슨 일인지 · 혼자 할지 팀을 부를지 ·
|
|
35
|
+
누가 붙을지**를 정하고, 그 이유를 먼저 보여 줍니다.
|
|
36
|
+
|
|
37
|
+
## 무엇이 다른가
|
|
38
|
+
|
|
39
|
+
- **검증된 Agent 만 씁니다.** 처음 실행하면 이 기계의 격리된 임시 저장소에서
|
|
40
|
+
Agent 를 **실제로 돌려 보고**, 통과한 것만 일에 넣습니다. 다른 기계의 검증
|
|
41
|
+
결과를 그대로 믿지 않습니다.
|
|
42
|
+
- **작업마다 권한이 다릅니다.** 기획·설계는 읽기만, 구현자는 쓰기까지,
|
|
43
|
+
시험은 실행까지. 선언하지 않은 도구를 쓰려 하면 막습니다.
|
|
44
|
+
- **말이 아니라 증거로 판정합니다.** 바뀌었다는 파일이 정말 바뀌었는지,
|
|
45
|
+
통과했다는 시험이 **우리가 돌려도** 통과하는지 직접 확인합니다.
|
|
46
|
+
- **뒤 Agent 가 앞 Agent 를 그냥 믿지 않습니다.** 어긋난 것을 발견하면 그
|
|
47
|
+
단계로 되감아 다시 만듭니다.
|
|
48
|
+
|
|
49
|
+
## 지원 환경
|
|
50
|
+
|
|
51
|
+
| | |
|
|
52
|
+
|---|---|
|
|
53
|
+
| Python | **3.10 이상** |
|
|
54
|
+
| 함께 필요한 것 | `git`, [Claude Code CLI](https://docs.claude.com/en/docs/claude-code) (`claude` 명령) |
|
|
55
|
+
| 실측한 OS | **Linux 만** |
|
|
56
|
+
| **Windows** | **아직 실측하지 않았습니다.** 순수 파이썬 휠(`py3-none-any`)이고 배포 코드에 POSIX 전용 호출이 없어 설치는 될 구조지만, 저희가 돌려 본 적은 없습니다 |
|
|
57
|
+
| macOS | 실측하지 않았습니다 (Linux 와 같은 조건으로 봅니다) |
|
|
58
|
+
| 외부 의존성 | **0** — Python 표준 라이브러리만 씁니다 |
|
|
59
|
+
|
|
60
|
+
Claude Code CLI 사용량은 **사용자 본인 계정에서** 나갑니다. 실측: 작은 수정
|
|
61
|
+
30~60초·$0.2 안팎, 큰 기능 하나에 팀이 붙으면 **30~40분·$10 이상**.
|
|
62
|
+
|
|
63
|
+
## 알려진 한계
|
|
64
|
+
|
|
65
|
+
- **브라우저에서의 화면 동작 확인은 사람 몫입니다.** 서버가 준 HTML 은
|
|
66
|
+
확인하지만 클릭 이후는 자동 시험이 아닙니다
|
|
67
|
+
- **자동 재작업(되감기)은 한 실행에 2회**까지입니다. 넘으면 남은 지적은
|
|
68
|
+
기록만 되고 반영되지 않습니다
|
|
69
|
+
- **팀 방식은 느리고 비쌉니다.** 같은 앱을 혼자 344초·$1.86 에, 팀은
|
|
70
|
+
2562초·$10.86 에 만들었고 **둘 다 동작했습니다.** 작은 일은 알아서 혼자
|
|
71
|
+
처리하지만, 큰 일에 팀을 붙이는 판단이 늘 옳다고 보지 않습니다
|
|
72
|
+
- 시험이 없는 저장소에서는 완료를 판정할 수 없습니다 (`--test-command` 로
|
|
73
|
+
알려 주시면 이어서 판정합니다)
|
|
74
|
+
- 저장소 여러 개를 한 번에 다루지 못합니다
|
|
75
|
+
|
|
76
|
+
## 이번 판에서 **하지 않는** 일
|
|
77
|
+
|
|
78
|
+
- **운영 배포(`deploy.production`)**
|
|
79
|
+
- **비밀값 접근(`secret.read`)**
|
|
80
|
+
- **되돌리기 어려운 마이그레이션 · 파괴적 운영 작업**
|
|
81
|
+
|
|
82
|
+
Agent 가 이런 권한을 요구하면 **실행 전에 멈추고** 사람에게 알립니다.
|
|
83
|
+
승인해서 진행하는 경로는 이번 판에 없습니다.
|
|
84
|
+
|
|
85
|
+
## 소스 코드와 기록
|
|
86
|
+
|
|
87
|
+
- **코드는 당신의 기계를 떠나지 않습니다.** Supervisor 는 서버가 없고 계정도
|
|
88
|
+
로그인도 없습니다. 다만 Claude Code CLI 자체는 Anthropic API 와 통신하며,
|
|
89
|
+
그 범위는 평소 `claude` 를 쓰실 때와 **똑같습니다**
|
|
90
|
+
- 실행 기록은 `~/.supervisor/` 안에만 쌓입니다
|
|
91
|
+
- **기록에 소스 코드가 들어가지 않습니다** — 바뀐 파일의 **개수와 확장자만**
|
|
92
|
+
남고 경로도 내용도 남기지 않습니다. 목표 문장은 흔한 비밀값 모양
|
|
93
|
+
(토큰·비밀번호)을 지운 뒤 남습니다
|
|
94
|
+
- 저희가 기록을 자동으로 가져가지 않습니다. **직접 보내 주실 때만** 봅니다
|
|
95
|
+
(`supervisor report --out 파일`)
|
|
96
|
+
|
|
97
|
+
## 바뀐 코드는 커밋되지 않습니다
|
|
98
|
+
|
|
99
|
+
`git diff` 로 직접 보고 판단하십시오. Supervisor 는 커밋하지 않습니다.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
MANIFEST.in
|
|
2
|
+
PYPI.md
|
|
3
|
+
README.md
|
|
4
|
+
pyproject.toml
|
|
5
|
+
aisupervisor.egg-info/PKG-INFO
|
|
6
|
+
aisupervisor.egg-info/SOURCES.txt
|
|
7
|
+
aisupervisor.egg-info/dependency_links.txt
|
|
8
|
+
aisupervisor.egg-info/entry_points.txt
|
|
9
|
+
aisupervisor.egg-info/top_level.txt
|
|
10
|
+
registry/__init__.py
|
|
11
|
+
registry/__main__.py
|
|
12
|
+
registry/cli.py
|
|
13
|
+
registry/integrity.py
|
|
14
|
+
registry/models.py
|
|
15
|
+
registry/probes.py
|
|
16
|
+
registry/server.py
|
|
17
|
+
registry/store.py
|
|
18
|
+
registry/verify.py
|
|
19
|
+
registry/seed/backend-implementer.json
|
|
20
|
+
registry/seed/code-reviewer.json
|
|
21
|
+
registry/seed/frontend-implementer.json
|
|
22
|
+
registry/seed/overreaching-reviewer.json
|
|
23
|
+
registry/seed/product-planner.json
|
|
24
|
+
registry/seed/repo-analyst.json
|
|
25
|
+
registry/seed/security-reviewer.json
|
|
26
|
+
registry/seed/test-runner.json
|
|
27
|
+
registry/seed/ui-designer.json
|
|
28
|
+
registry/seed/ux-designer.json
|
|
29
|
+
registry/web/index.html
|
|
30
|
+
supervisor/__init__.py
|
|
31
|
+
supervisor/__main__.py
|
|
32
|
+
supervisor/analyze.py
|
|
33
|
+
supervisor/artifacts.py
|
|
34
|
+
supervisor/capability.py
|
|
35
|
+
supervisor/cli.py
|
|
36
|
+
supervisor/decide.py
|
|
37
|
+
supervisor/display.py
|
|
38
|
+
supervisor/metrics.py
|
|
39
|
+
supervisor/permission.py
|
|
40
|
+
supervisor/pipeline.py
|
|
41
|
+
supervisor/registry_client.py
|
|
42
|
+
supervisor/runner.py
|
|
43
|
+
supervisor/shell.py
|
|
44
|
+
supervisor/team.py
|
|
45
|
+
supervisor/telemetry.py
|
|
46
|
+
supervisor/workspace.py
|
|
47
|
+
supervisor/adapters/__init__.py
|
|
48
|
+
supervisor/adapters/base.py
|
|
49
|
+
supervisor/adapters/claude_code.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "aisupervisor"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "목표만 주면 필요한 Agent 를 찾아 검증하고, 권한과 협업 순서까지 구성한다"
|
|
9
|
+
readme = {file = "PYPI.md", content-type = "text/markdown"}
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 4 - Beta",
|
|
13
|
+
"Environment :: Console",
|
|
14
|
+
"Intended Audience :: Developers",
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
17
|
+
"Operating System :: POSIX :: Linux",
|
|
18
|
+
"Operating System :: MacOS",
|
|
19
|
+
"Topic :: Software Development :: Build Tools",
|
|
20
|
+
"Topic :: Software Development :: Quality Assurance",
|
|
21
|
+
]
|
|
22
|
+
# 외부 의존성 0 — stdlib 만 쓴다. 설치하는 사람이 치를 값이 없어야 한다.
|
|
23
|
+
dependencies = []
|
|
24
|
+
|
|
25
|
+
[project.scripts]
|
|
26
|
+
supervisor = "supervisor.cli:main"
|
|
27
|
+
agent-registry = "registry.cli:main"
|
|
28
|
+
|
|
29
|
+
[tool.setuptools.dynamic]
|
|
30
|
+
version = {attr = "supervisor.__version__"}
|
|
31
|
+
|
|
32
|
+
[tool.setuptools]
|
|
33
|
+
packages = ["supervisor", "supervisor.adapters", "registry"]
|
|
34
|
+
|
|
35
|
+
[tool.setuptools.package-data]
|
|
36
|
+
registry = ["seed/*.json", "web/*.html"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Verified Agent Registry — capability 와 permission 의 source of truth."""
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""Registry CLI — 등록·검증·조회."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import json
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from supervisor.adapters.claude_code import ClaudeCodeAdapter
|
|
10
|
+
|
|
11
|
+
from .models import REJECTED, REVIEW_REQUIRED, VERIFIED
|
|
12
|
+
from .store import Store, StoreError
|
|
13
|
+
from .verify import verify
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def cmd_list(args) -> int:
|
|
17
|
+
store = Store(args.home)
|
|
18
|
+
for agent in store.all():
|
|
19
|
+
v = agent.verification
|
|
20
|
+
mark = {VERIFIED: "✓", REVIEW_REQUIRED: "?", REJECTED: "✗"}.get(
|
|
21
|
+
v.status if v else "", "-")
|
|
22
|
+
status = v.status if v else "미검증"
|
|
23
|
+
print(f" {mark} {agent.agent_id:24s} v{agent.version:8s} {status:16s} "
|
|
24
|
+
f"{','.join(agent.capabilities)}")
|
|
25
|
+
return 0
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def cmd_show(args) -> int:
|
|
29
|
+
store = Store(args.home)
|
|
30
|
+
agent = store.get(args.agent_id)
|
|
31
|
+
if agent is None:
|
|
32
|
+
print(f"[registry] 없는 agent: {args.agent_id}", file=sys.stderr)
|
|
33
|
+
return 1
|
|
34
|
+
print(json.dumps(agent.as_dict(), ensure_ascii=False, indent=2))
|
|
35
|
+
return 0
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def cmd_register(args) -> int:
|
|
39
|
+
store = Store(args.home)
|
|
40
|
+
raw = json.loads(Path(args.file).read_text(encoding="utf-8"))
|
|
41
|
+
try:
|
|
42
|
+
agent = store.register(raw)
|
|
43
|
+
except StoreError as exc:
|
|
44
|
+
print(f"[registry] {exc}", file=sys.stderr)
|
|
45
|
+
return 1
|
|
46
|
+
print(f"등록: {agent.agent_id} v{agent.version} (아직 미검증)")
|
|
47
|
+
return 0
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def cmd_verify(args) -> int:
|
|
51
|
+
store = Store(args.home)
|
|
52
|
+
adapter = ClaudeCodeAdapter()
|
|
53
|
+
targets = ([store.get(args.agent_id)] if args.agent_id else store.all())
|
|
54
|
+
if any(t is None for t in targets):
|
|
55
|
+
print(f"[registry] 없는 agent: {args.agent_id}", file=sys.stderr)
|
|
56
|
+
return 1
|
|
57
|
+
worst = 0
|
|
58
|
+
for agent in targets:
|
|
59
|
+
#: 건너뛰는 조건은 **지금 이 기계에서 쓸 수 있는 상태**여야 한다.
|
|
60
|
+
#:
|
|
61
|
+
#: 버전만 보고 건너뛰던 판이 있었다. 그래서 새 기계에서는 패키지에
|
|
62
|
+
#: 담겨 온 결과(서명이 이 기계 키와 맞지 않는다)를 "이미 검증됨" 으로
|
|
63
|
+
#: 보고 넘어갔고, `init` 이 "쓸 수 있는 Agent 0개" 로 끝났다.
|
|
64
|
+
#: 설치 직후 아무것도 못 쓰는 것은 설치 실패와 같다.
|
|
65
|
+
already = (agent.is_usable()
|
|
66
|
+
or (agent.verification is not None
|
|
67
|
+
and agent.verification.status == REJECTED
|
|
68
|
+
and agent.verification.version == agent.version))
|
|
69
|
+
if already and not args.force:
|
|
70
|
+
print(f" = {agent.agent_id}: 이미 확인됨 "
|
|
71
|
+
f"({agent.verification.status})")
|
|
72
|
+
continue
|
|
73
|
+
result = verify(agent, adapter)
|
|
74
|
+
agent.verification = result
|
|
75
|
+
store.save(agent)
|
|
76
|
+
mark = {VERIFIED: "✓", REVIEW_REQUIRED: "?", REJECTED: "✗"}[result.status]
|
|
77
|
+
print(f" {mark} {agent.agent_id}: {result.status}")
|
|
78
|
+
for name, ok in result.checks.items():
|
|
79
|
+
print(f" {name:12s} {'통과' if ok else '탈락'} — "
|
|
80
|
+
f"{result.evidence.get(name, '')[:96]}")
|
|
81
|
+
for why in result.reasons:
|
|
82
|
+
print(f" ! {why}")
|
|
83
|
+
if result.status == REJECTED:
|
|
84
|
+
worst = max(worst, 1)
|
|
85
|
+
return worst
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def cmd_serve(args) -> int:
|
|
89
|
+
from .server import serve
|
|
90
|
+
srv = serve(args.host, args.port, args.home)
|
|
91
|
+
url = f"http://{args.host}:{args.port}/"
|
|
92
|
+
print(f"Verified Agent Catalog: {url}")
|
|
93
|
+
print(f" GET {url}api/agents GET {url}api/capabilities")
|
|
94
|
+
print(" Ctrl-C 로 멈춘다")
|
|
95
|
+
try:
|
|
96
|
+
srv.serve_forever()
|
|
97
|
+
except KeyboardInterrupt:
|
|
98
|
+
print("\n멈췄다")
|
|
99
|
+
return 0
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def main(argv=None) -> int:
|
|
103
|
+
parser = argparse.ArgumentParser(prog="python -m registry")
|
|
104
|
+
parser.add_argument("--home", help="Agent 저장 위치 (기본: registry/seed)")
|
|
105
|
+
sub = parser.add_subparsers(dest="cmd", required=True)
|
|
106
|
+
sub.add_parser("list").set_defaults(fn=cmd_list)
|
|
107
|
+
show = sub.add_parser("show"); show.add_argument("agent_id")
|
|
108
|
+
show.set_defaults(fn=cmd_show)
|
|
109
|
+
reg = sub.add_parser("register"); reg.add_argument("file")
|
|
110
|
+
reg.set_defaults(fn=cmd_register)
|
|
111
|
+
ver = sub.add_parser("verify")
|
|
112
|
+
ver.add_argument("agent_id", nargs="?")
|
|
113
|
+
ver.add_argument("--force", action="store_true",
|
|
114
|
+
help="이미 검증된 버전도 다시 돌린다")
|
|
115
|
+
ver.set_defaults(fn=cmd_verify)
|
|
116
|
+
srv = sub.add_parser("serve", help="Registry REST + Web Catalog 를 띄운다")
|
|
117
|
+
srv.add_argument("--host", default="127.0.0.1")
|
|
118
|
+
srv.add_argument("--port", type=int, default=8787)
|
|
119
|
+
srv.set_defaults(fn=cmd_serve)
|
|
120
|
+
args = parser.parse_args(argv)
|
|
121
|
+
return args.fn(args)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""검증 결과가 **손으로 쓰여지지 않았는가.**
|
|
2
|
+
|
|
3
|
+
## 왜 필요한가
|
|
4
|
+
|
|
5
|
+
실측(독립 리뷰): `registry/seed/*.json` 은 평범한 JSON 파일이고, 거기에
|
|
6
|
+
`"verification": {"status": "verified", ...}` 를 손으로 써 넣으면 Supervisor 가
|
|
7
|
+
그 Agent 를 **자동으로 쓴다.** 검증을 안 거치고도 Verified 가 된다.
|
|
8
|
+
|
|
9
|
+
Registry 가 "source of truth" 라고 말하려면 그 말이 참이어야 한다.
|
|
10
|
+
|
|
11
|
+
## 어떻게
|
|
12
|
+
|
|
13
|
+
검증기가 결과에 **서명**을 붙인다. 서명은 그 Agent 의 정체(id·version·
|
|
14
|
+
capability·permission)와 검증 내용(상태·검사 결과)에 걸린다. 하나라도 손으로
|
|
15
|
+
바꾸면 서명이 맞지 않고, `is_trusted()` 가 거짓이 된다.
|
|
16
|
+
|
|
17
|
+
## 한계 — 정직하게
|
|
18
|
+
|
|
19
|
+
키는 이 기계 안(`~/.supervisor/registry.key`)에 있다. **기계를 가진 사람은
|
|
20
|
+
서명도 만들 수 있다.** 이것이 막는 것은 "파일을 고쳐 검증을 위조하는 일" 이지
|
|
21
|
+
"기계를 장악한 상대" 가 아니다. 원격 Registry 가 생기면 서명 키는 서버로
|
|
22
|
+
가야 하고, 그때 이 함수의 자리는 그대로 두고 키의 출처만 바뀐다.
|
|
23
|
+
"""
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import hashlib
|
|
27
|
+
import hmac
|
|
28
|
+
import json
|
|
29
|
+
import os
|
|
30
|
+
import secrets
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def key_path() -> Path:
|
|
35
|
+
override = os.environ.get("REGISTRY_KEY_FILE")
|
|
36
|
+
if override:
|
|
37
|
+
return Path(override)
|
|
38
|
+
home = os.environ.get("SUPERVISOR_HOME")
|
|
39
|
+
base = Path(home) if home else Path.home() / ".supervisor"
|
|
40
|
+
return base / "registry.key"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def load_key() -> bytes:
|
|
44
|
+
"""없으면 만든다. 키가 바뀌면 이전 서명은 전부 무효가 된다 — 그것이 맞다."""
|
|
45
|
+
path = key_path()
|
|
46
|
+
if path.is_file():
|
|
47
|
+
return path.read_bytes()
|
|
48
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
49
|
+
material = secrets.token_bytes(32)
|
|
50
|
+
path.write_bytes(material)
|
|
51
|
+
try:
|
|
52
|
+
path.chmod(0o600)
|
|
53
|
+
except OSError:
|
|
54
|
+
pass
|
|
55
|
+
return material
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def payload(agent) -> bytes:
|
|
59
|
+
"""서명이 걸리는 내용.
|
|
60
|
+
|
|
61
|
+
**정체와 검증 결과 둘 다**에 건다. 정체만 걸면 검증 결과를 바꿔치기할 수
|
|
62
|
+
있고, 검증 결과만 걸면 다른 Agent 의 서명을 옮겨 붙일 수 있다.
|
|
63
|
+
"""
|
|
64
|
+
v = agent.verification
|
|
65
|
+
body = {
|
|
66
|
+
"agent_id": agent.agent_id,
|
|
67
|
+
"version": agent.version,
|
|
68
|
+
"capabilities": sorted(agent.capabilities),
|
|
69
|
+
"permissions": sorted(agent.permissions),
|
|
70
|
+
"human_only": sorted(agent.human_only),
|
|
71
|
+
"status": v.status if v else None,
|
|
72
|
+
"verified_at": v.verified_at if v else None,
|
|
73
|
+
"checks": dict(sorted((v.checks or {}).items())) if v else None,
|
|
74
|
+
"verification_version": v.version if v else None,
|
|
75
|
+
}
|
|
76
|
+
return json.dumps(body, ensure_ascii=False, sort_keys=True).encode("utf-8")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def sign(agent) -> str:
|
|
80
|
+
return hmac.new(load_key(), payload(agent), hashlib.sha256).hexdigest()
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def is_trusted(agent) -> bool:
|
|
84
|
+
"""이 검증 결과가 우리 검증기에서 나온 것인가."""
|
|
85
|
+
v = agent.verification
|
|
86
|
+
if v is None or not getattr(v, "signature", ""):
|
|
87
|
+
return False
|
|
88
|
+
return hmac.compare_digest(v.signature, sign(agent))
|