claude-code-generator 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. claude_code_generator-0.1.0.dist-info/METADATA +176 -0
  2. claude_code_generator-0.1.0.dist-info/RECORD +49 -0
  3. claude_code_generator-0.1.0.dist-info/WHEEL +5 -0
  4. claude_code_generator-0.1.0.dist-info/entry_points.txt +2 -0
  5. claude_code_generator-0.1.0.dist-info/licenses/LICENSE +21 -0
  6. claude_code_generator-0.1.0.dist-info/top_level.txt +1 -0
  7. code_generator/__init__.py +3 -0
  8. code_generator/agents.py +177 -0
  9. code_generator/cli.py +49 -0
  10. code_generator/commands/__init__.py +1 -0
  11. code_generator/commands/generate.py +252 -0
  12. code_generator/commands/init.py +72 -0
  13. code_generator/commands/review.py +117 -0
  14. code_generator/commands/status.py +83 -0
  15. code_generator/env.py +55 -0
  16. code_generator/gh.py +331 -0
  17. code_generator/logging_setup.py +73 -0
  18. code_generator/orchestrator/__init__.py +4 -0
  19. code_generator/orchestrator/cycle_loop.py +371 -0
  20. code_generator/orchestrator/phase0_complexity.py +159 -0
  21. code_generator/orchestrator/phase1_plan.py +170 -0
  22. code_generator/orchestrator/phase2_review.py +126 -0
  23. code_generator/orchestrator/phase3_4_implement.py +164 -0
  24. code_generator/orchestrator/phase5_closure.py +154 -0
  25. code_generator/orchestrator/phase6_test.py +98 -0
  26. code_generator/orchestrator/phase7_commit.py +167 -0
  27. code_generator/prompts/__init__.py +86 -0
  28. code_generator/prompts/prompt-phase-0-complexity.md +85 -0
  29. code_generator/prompts/prompt-phase-1-planning.md +209 -0
  30. code_generator/prompts/prompt-phase-2-issue-review.md +84 -0
  31. code_generator/prompts/prompt-phase-3-implementation.md +191 -0
  32. code_generator/prompts/prompt-phase-5-final-review.md +135 -0
  33. code_generator/prompts/prompt-phase-6-test.md +102 -0
  34. code_generator/prompts/prompt-phase-7-commit.md +103 -0
  35. code_generator/prompts/prompt-review.md +124 -0
  36. code_generator/runner/__init__.py +26 -0
  37. code_generator/runner/rate_limit.py +113 -0
  38. code_generator/runner/retry.py +165 -0
  39. code_generator/runner/sdk_runner.py +267 -0
  40. code_generator/runner/subprocess_runner.py +200 -0
  41. code_generator/state.py +178 -0
  42. code_generator/templates/__init__.py +1 -0
  43. code_generator/templates/angular.md +12 -0
  44. code_generator/templates/base.md +28 -0
  45. code_generator/templates/fastapi.md +12 -0
  46. code_generator/templates/finance.md +9 -0
  47. code_generator/templates/fullstack.md +24 -0
  48. code_generator/templates/nestjs.md +9 -0
  49. code_generator/templates/python-cli.md +9 -0
@@ -0,0 +1,178 @@
1
+ """Atomic state persistence for the code-generator orchestrator.
2
+
3
+ State is serialized to JSON and written via a tmp-file + os.replace() pattern
4
+ so a crash mid-write cannot corrupt the existing state file.
5
+
6
+ Non-negotiables #5 (wait-and-resume) and #7 (atomic writes).
7
+ """
8
+
9
+ import dataclasses
10
+ import json
11
+ import os
12
+ import time
13
+ from dataclasses import dataclass, field
14
+ from datetime import UTC, datetime
15
+ from pathlib import Path
16
+ from typing import Literal
17
+
18
+
19
+ @dataclass
20
+ class IssueState:
21
+ """Lightweight record for a single GitHub issue within a phase."""
22
+
23
+ number: int
24
+ status: Literal["open", "closed"]
25
+ agent: str
26
+
27
+
28
+ @dataclass
29
+ class CycleState:
30
+ """State for one generation cycle (maps 1-to-1 with a GitHub Milestone)."""
31
+
32
+ id: int
33
+ name: str
34
+ milestone_number: int | None
35
+ milestone_title: str
36
+ status: str
37
+ phase: int
38
+ issues: list[IssueState]
39
+ commit_sha: str | None
40
+ depends_on: list[int] = field(default_factory=list)
41
+ scope: str = ""
42
+
43
+
44
+ @dataclass
45
+ class State:
46
+ """Root state object persisted to .code-generator/state.json."""
47
+
48
+ mode: Literal["single", "multi-cycle", "unknown"]
49
+ started_at: str
50
+ updated_at: str
51
+ current_cycle: int | None = None
52
+ cycles: list[CycleState] = field(default_factory=list)
53
+ phase: int | None = None
54
+ issues: list[IssueState] = field(default_factory=list)
55
+ session_id: str | None = None
56
+ paused_until: int | None = None
57
+ rate_limit_type: str | None = None
58
+ last_error: str | None = None
59
+
60
+
61
+ def _utc_now() -> str:
62
+ return datetime.now(tz=UTC).strftime("%Y-%m-%dT%H:%M:%SZ")
63
+
64
+
65
+ def _issue_from_dict(d: dict) -> IssueState: # type: ignore[type-arg]
66
+ return IssueState(number=d["number"], status=d["status"], agent=d["agent"])
67
+
68
+
69
+ def _cycle_from_dict(d: dict) -> CycleState: # type: ignore[type-arg]
70
+ return CycleState(
71
+ id=d["id"],
72
+ name=d["name"],
73
+ milestone_number=d.get("milestone_number"),
74
+ milestone_title=d["milestone_title"],
75
+ status=d["status"],
76
+ phase=d["phase"],
77
+ issues=[_issue_from_dict(i) for i in d.get("issues", [])],
78
+ commit_sha=d.get("commit_sha"),
79
+ depends_on=d.get("depends_on", []),
80
+ scope=d.get("scope", ""),
81
+ )
82
+
83
+
84
+ def load_state(path: Path) -> State:
85
+ """Load state from path, or return a fresh default when the file is missing.
86
+
87
+ Args:
88
+ path: Location of state.json (need not exist).
89
+
90
+ Returns:
91
+ Deserialized State, or a default single-mode State if the file is absent.
92
+ """
93
+ if not path.exists():
94
+ now = _utc_now()
95
+ return State(mode="unknown", started_at=now, updated_at=now)
96
+
97
+ raw = json.loads(path.read_text(encoding="utf-8"))
98
+ return State(
99
+ mode=raw["mode"],
100
+ started_at=raw["started_at"],
101
+ updated_at=raw["updated_at"],
102
+ current_cycle=raw.get("current_cycle"),
103
+ cycles=[_cycle_from_dict(c) for c in raw.get("cycles", [])],
104
+ phase=raw.get("phase"),
105
+ issues=[_issue_from_dict(i) for i in raw.get("issues", [])],
106
+ session_id=raw.get("session_id"),
107
+ paused_until=raw.get("paused_until"),
108
+ rate_limit_type=raw.get("rate_limit_type"),
109
+ last_error=raw.get("last_error"),
110
+ )
111
+
112
+
113
+ def save_state(path: Path, state: State) -> None:
114
+ """Atomically persist state to path.
115
+
116
+ Updates state.updated_at, serializes to JSON with 2-space indentation,
117
+ writes to a sibling .tmp file, then replaces the target via os.replace()
118
+ so no partial write is ever visible.
119
+
120
+ Args:
121
+ path: Destination for state.json.
122
+ state: State object to persist.
123
+ """
124
+ state.updated_at = _utc_now()
125
+ path.parent.mkdir(parents=True, exist_ok=True)
126
+
127
+ tmp = Path(str(path) + ".tmp")
128
+ data = json.dumps(dataclasses.asdict(state), indent=2)
129
+ tmp.write_text(data, encoding="utf-8")
130
+ os.replace(tmp, path)
131
+
132
+
133
+ def mark_paused(
134
+ state: State,
135
+ *,
136
+ resets_at: int,
137
+ rate_limit_type: str,
138
+ session_id: str | None,
139
+ ) -> None:
140
+ """Record a rate-limit pause in the state object (in-memory only).
141
+
142
+ Caller must call save_state() afterwards to persist.
143
+
144
+ Args:
145
+ state: State to mutate.
146
+ resets_at: Unix timestamp when the rate-limit window resets.
147
+ rate_limit_type: Identifier for the type of rate limit hit.
148
+ session_id: SDK session ID to resume from, if available.
149
+ """
150
+ state.paused_until = resets_at
151
+ state.rate_limit_type = rate_limit_type
152
+ state.session_id = session_id
153
+
154
+
155
+ def clear_pause(state: State) -> None:
156
+ """Clear pause fields after the rate-limit window has passed.
157
+
158
+ Args:
159
+ state: State to mutate in place.
160
+ """
161
+ state.paused_until = None
162
+ state.rate_limit_type = None
163
+
164
+
165
+ def is_paused(state: State, *, now: float | None = None) -> bool:
166
+ """Return True when the state indicates an active rate-limit pause.
167
+
168
+ Args:
169
+ state: State to inspect.
170
+ now: Override for the current time (seconds since epoch). Defaults to
171
+ time.time() when omitted.
172
+
173
+ Returns:
174
+ True if paused_until is set and lies in the future.
175
+ """
176
+ if state.paused_until is None:
177
+ return False
178
+ return state.paused_until > (now if now is not None else time.time())
@@ -0,0 +1 @@
1
+ """Template files for `code-generator init`."""
@@ -0,0 +1,12 @@
1
+
2
+ ## Pages and Routing
3
+ <!-- List the main routes -->
4
+ | Path | Component | Description |
5
+ |------|-----------|-------------|
6
+ | / | HomePage | ... |
7
+
8
+ ## State and Data
9
+ <!-- How to manage state: signals, ngrx, service-based -->
10
+
11
+ ## Design System
12
+ <!-- Tailwind / Material / custom, color palette, typography -->
@@ -0,0 +1,28 @@
1
+ # Project Name
2
+
3
+ ## Description
4
+ <!-- Describe the project in 2-3 sentences: what it does, for whom, why -->
5
+
6
+ ## Tech Stack
7
+ <!-- The tool uses this information to select the right agents -->
8
+ - **Language**: [Python / TypeScript / ...]
9
+ - **Framework**: [FastAPI / Angular / NestJS / ...]
10
+ - **Database**: [PostgreSQL / Supabase / MongoDB / none]
11
+ - **Deploy**: [Fly.io / Vercel / Docker / local]
12
+ - **Tests**: [pytest / vitest / jest / ...]
13
+
14
+ ## Features
15
+ <!-- List the features. Each entry becomes a GitHub Issue -->
16
+ 1. ...
17
+ 2. ...
18
+ 3. ...
19
+
20
+ ## Non-functional Requirements
21
+ <!-- Performance, security, scalability, accessibility -->
22
+ - ...
23
+
24
+ ## Project Structure
25
+ <!-- Optional: folder structure preferences -->
26
+
27
+ ## Additional Notes
28
+ <!-- Particular constraints, external integrations, third-party APIs -->
@@ -0,0 +1,12 @@
1
+
2
+ ## API Endpoints
3
+ <!-- List the REST endpoints: method, path, description -->
4
+ | Method | Path | Description |
5
+ |--------|------|-------------|
6
+ | GET | /api/v1/... | ... |
7
+
8
+ ## Database Models
9
+ <!-- List the main entities and their relationships -->
10
+
11
+ ## Authentication
12
+ <!-- JWT / OAuth2 / API key / none -->
@@ -0,0 +1,9 @@
1
+
2
+ ## Data Sources
3
+ <!-- Market data providers, APIs, file formats -->
4
+
5
+ ## Portfolio Models
6
+ <!-- Mean-Variance, Black-Litterman, Risk Parity, etc. -->
7
+
8
+ ## Risk Measures
9
+ <!-- VaR, CVaR, Sharpe, Sortino, max drawdown, etc. -->
@@ -0,0 +1,24 @@
1
+
2
+ ## API Endpoints
3
+ <!-- List the REST endpoints: method, path, description -->
4
+ | Method | Path | Description |
5
+ |--------|------|-------------|
6
+ | GET | /api/v1/... | ... |
7
+
8
+ ## Database Models
9
+ <!-- List the main entities and their relationships -->
10
+
11
+ ## Authentication
12
+ <!-- JWT / OAuth2 / API key / none -->
13
+
14
+ ## Pages and Routing
15
+ <!-- List the main routes -->
16
+ | Path | Component | Description |
17
+ |------|-----------|-------------|
18
+ | / | HomePage | ... |
19
+
20
+ ## State and Data
21
+ <!-- How to manage state: signals, ngrx, service-based -->
22
+
23
+ ## Design System
24
+ <!-- Tailwind / Material / custom, color palette, typography -->
@@ -0,0 +1,9 @@
1
+
2
+ ## Modules
3
+ <!-- List the main NestJS modules -->
4
+
5
+ ## Authentication and Guards
6
+ <!-- Passport / JWT / roles and permissions -->
7
+
8
+ ## Database
9
+ <!-- Prisma / TypeORM, main entities -->
@@ -0,0 +1,9 @@
1
+
2
+ ## CLI Commands
3
+ <!-- List the commands and their arguments/flags -->
4
+
5
+ ## Configuration
6
+ <!-- Config files, environment variables, defaults -->
7
+
8
+ ## Output format
9
+ <!-- Text, JSON, rich tables, etc. -->