anvil-dev-framework 0.1.6

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 (190) hide show
  1. package/README.md +719 -0
  2. package/VERSION +1 -0
  3. package/docs/ANVIL-REPO-IMPLEMENTATION-PLAN.md +441 -0
  4. package/docs/FIRST-SKILL-TUTORIAL.md +408 -0
  5. package/docs/INSTALLATION-RETRO-NOTES.md +458 -0
  6. package/docs/INSTALLATION.md +984 -0
  7. package/docs/anvil-hud.md +469 -0
  8. package/docs/anvil-init.md +255 -0
  9. package/docs/anvil-state.md +210 -0
  10. package/docs/boris-cherny-ralph-wiggum-insights.md +608 -0
  11. package/docs/command-reference.md +2022 -0
  12. package/docs/hooks-tts.md +368 -0
  13. package/docs/implementation-guide.md +810 -0
  14. package/docs/linear-github-integration.md +247 -0
  15. package/docs/local-issues.md +677 -0
  16. package/docs/patterns/README.md +419 -0
  17. package/docs/planning-responsibilities.md +139 -0
  18. package/docs/session-workflow.md +573 -0
  19. package/docs/simplification-plan-template.md +297 -0
  20. package/docs/simplification-principles.md +129 -0
  21. package/docs/specifications/CCS-RALPH-INTEGRATION-DESIGN.md +633 -0
  22. package/docs/specifications/CCS-RESEARCH-REPORT.md +169 -0
  23. package/docs/specifications/PLAN-ANV-verification-ralph-wiggum.md +403 -0
  24. package/docs/specifications/PLAN-parallel-tracks-anvil-memory-ccs.md +494 -0
  25. package/docs/specifications/SPEC-ANV-VRW/component-01-verify.md +208 -0
  26. package/docs/specifications/SPEC-ANV-VRW/component-02-stop-gate.md +226 -0
  27. package/docs/specifications/SPEC-ANV-VRW/component-03-posttooluse.md +209 -0
  28. package/docs/specifications/SPEC-ANV-VRW/component-04-ralph-wiggum.md +604 -0
  29. package/docs/specifications/SPEC-ANV-VRW/component-05-atomic-actions.md +311 -0
  30. package/docs/specifications/SPEC-ANV-VRW/component-06-verify-subagent.md +264 -0
  31. package/docs/specifications/SPEC-ANV-VRW/component-07-claude-md.md +363 -0
  32. package/docs/specifications/SPEC-ANV-VRW/index.md +182 -0
  33. package/docs/specifications/SPEC-ANV-anvil-memory.md +573 -0
  34. package/docs/specifications/SPEC-ANV-context-checkpoints.md +781 -0
  35. package/docs/specifications/SPEC-ANV-verification-ralph-wiggum.md +789 -0
  36. package/docs/sync.md +122 -0
  37. package/global/CLAUDE.md +140 -0
  38. package/global/agents/verify-app.md +164 -0
  39. package/global/commands/anvil-settings.md +527 -0
  40. package/global/commands/anvil-sync.md +121 -0
  41. package/global/commands/change.md +197 -0
  42. package/global/commands/clarify.md +252 -0
  43. package/global/commands/cleanup.md +292 -0
  44. package/global/commands/commit-push-pr.md +207 -0
  45. package/global/commands/decay-review.md +127 -0
  46. package/global/commands/discover.md +158 -0
  47. package/global/commands/doc-coverage.md +122 -0
  48. package/global/commands/evidence.md +307 -0
  49. package/global/commands/explore.md +121 -0
  50. package/global/commands/force-exit.md +135 -0
  51. package/global/commands/handoff.md +191 -0
  52. package/global/commands/healthcheck.md +302 -0
  53. package/global/commands/hud.md +84 -0
  54. package/global/commands/insights.md +319 -0
  55. package/global/commands/linear-setup.md +184 -0
  56. package/global/commands/lint-fix.md +198 -0
  57. package/global/commands/orient.md +510 -0
  58. package/global/commands/plan.md +228 -0
  59. package/global/commands/ralph.md +346 -0
  60. package/global/commands/ready.md +182 -0
  61. package/global/commands/release.md +305 -0
  62. package/global/commands/retro.md +96 -0
  63. package/global/commands/shard.md +166 -0
  64. package/global/commands/spec.md +227 -0
  65. package/global/commands/sprint.md +184 -0
  66. package/global/commands/tasks.md +228 -0
  67. package/global/commands/test-and-commit.md +151 -0
  68. package/global/commands/validate.md +132 -0
  69. package/global/commands/verify.md +251 -0
  70. package/global/commands/weekly-review.md +156 -0
  71. package/global/hooks/__pycache__/ralph_context_monitor.cpython-314.pyc +0 -0
  72. package/global/hooks/__pycache__/statusline_agent_sync.cpython-314.pyc +0 -0
  73. package/global/hooks/anvil_memory_observe.ts +322 -0
  74. package/global/hooks/anvil_memory_session.ts +166 -0
  75. package/global/hooks/anvil_memory_stop.ts +187 -0
  76. package/global/hooks/parse_transcript.py +116 -0
  77. package/global/hooks/post_merge_cleanup.sh +132 -0
  78. package/global/hooks/post_tool_format.sh +215 -0
  79. package/global/hooks/ralph_context_monitor.py +240 -0
  80. package/global/hooks/ralph_stop.sh +502 -0
  81. package/global/hooks/statusline.sh +1110 -0
  82. package/global/hooks/statusline_agent_sync.py +224 -0
  83. package/global/hooks/stop_gate.sh +250 -0
  84. package/global/lib/.claude/anvil-state.json +21 -0
  85. package/global/lib/__pycache__/agent_registry.cpython-314.pyc +0 -0
  86. package/global/lib/__pycache__/claim_service.cpython-314.pyc +0 -0
  87. package/global/lib/__pycache__/coderabbit_service.cpython-314.pyc +0 -0
  88. package/global/lib/__pycache__/config_service.cpython-314.pyc +0 -0
  89. package/global/lib/__pycache__/coordination_service.cpython-314.pyc +0 -0
  90. package/global/lib/__pycache__/doc_coverage_service.cpython-314.pyc +0 -0
  91. package/global/lib/__pycache__/gate_logger.cpython-314.pyc +0 -0
  92. package/global/lib/__pycache__/github_service.cpython-314.pyc +0 -0
  93. package/global/lib/__pycache__/hygiene_service.cpython-314.pyc +0 -0
  94. package/global/lib/__pycache__/issue_models.cpython-314.pyc +0 -0
  95. package/global/lib/__pycache__/issue_provider.cpython-314.pyc +0 -0
  96. package/global/lib/__pycache__/linear_data_service.cpython-314.pyc +0 -0
  97. package/global/lib/__pycache__/linear_provider.cpython-314.pyc +0 -0
  98. package/global/lib/__pycache__/local_provider.cpython-314.pyc +0 -0
  99. package/global/lib/__pycache__/quality_service.cpython-314.pyc +0 -0
  100. package/global/lib/__pycache__/ralph_state.cpython-314.pyc +0 -0
  101. package/global/lib/__pycache__/state_manager.cpython-314.pyc +0 -0
  102. package/global/lib/__pycache__/transcript_parser.cpython-314.pyc +0 -0
  103. package/global/lib/__pycache__/verification_runner.cpython-314.pyc +0 -0
  104. package/global/lib/__pycache__/verify_iteration.cpython-314.pyc +0 -0
  105. package/global/lib/__pycache__/verify_subagent.cpython-314.pyc +0 -0
  106. package/global/lib/agent_registry.py +995 -0
  107. package/global/lib/anvil-state.sh +435 -0
  108. package/global/lib/claim_service.py +515 -0
  109. package/global/lib/coderabbit_service.py +314 -0
  110. package/global/lib/config_service.py +423 -0
  111. package/global/lib/coordination_service.py +331 -0
  112. package/global/lib/doc_coverage_service.py +1305 -0
  113. package/global/lib/gate_logger.py +316 -0
  114. package/global/lib/github_service.py +310 -0
  115. package/global/lib/handoff_generator.py +775 -0
  116. package/global/lib/hygiene_service.py +712 -0
  117. package/global/lib/issue_models.py +257 -0
  118. package/global/lib/issue_provider.py +339 -0
  119. package/global/lib/linear_data_service.py +210 -0
  120. package/global/lib/linear_provider.py +987 -0
  121. package/global/lib/linear_provider.py.backup +671 -0
  122. package/global/lib/local_provider.py +486 -0
  123. package/global/lib/orient_fast.py +457 -0
  124. package/global/lib/quality_service.py +470 -0
  125. package/global/lib/ralph_prompt_generator.py +563 -0
  126. package/global/lib/ralph_state.py +1202 -0
  127. package/global/lib/state_manager.py +417 -0
  128. package/global/lib/transcript_parser.py +597 -0
  129. package/global/lib/verification_runner.py +557 -0
  130. package/global/lib/verify_iteration.py +490 -0
  131. package/global/lib/verify_subagent.py +250 -0
  132. package/global/skills/README.md +155 -0
  133. package/global/skills/quality-gates/SKILL.md +252 -0
  134. package/global/skills/skill-template/SKILL.md +109 -0
  135. package/global/skills/testing-strategies/SKILL.md +337 -0
  136. package/global/templates/CHANGE-template.md +105 -0
  137. package/global/templates/HANDOFF-template.md +63 -0
  138. package/global/templates/PLAN-template.md +111 -0
  139. package/global/templates/SPEC-template.md +93 -0
  140. package/global/templates/ralph/PROMPT.md.template +89 -0
  141. package/global/templates/ralph/fix_plan.md.template +31 -0
  142. package/global/templates/ralph/progress.txt.template +23 -0
  143. package/global/tests/__pycache__/test_doc_coverage.cpython-314.pyc +0 -0
  144. package/global/tests/test_doc_coverage.py +520 -0
  145. package/global/tests/test_issue_models.py +299 -0
  146. package/global/tests/test_local_provider.py +323 -0
  147. package/global/tools/README.md +178 -0
  148. package/global/tools/__pycache__/anvil-hud.cpython-314.pyc +0 -0
  149. package/global/tools/anvil-hud.py +3622 -0
  150. package/global/tools/anvil-hud.py.bak +3318 -0
  151. package/global/tools/anvil-issue.py +432 -0
  152. package/global/tools/anvil-memory/CLAUDE.md +49 -0
  153. package/global/tools/anvil-memory/README.md +42 -0
  154. package/global/tools/anvil-memory/bun.lock +25 -0
  155. package/global/tools/anvil-memory/bunfig.toml +9 -0
  156. package/global/tools/anvil-memory/package.json +23 -0
  157. package/global/tools/anvil-memory/src/__tests__/ccs/context-monitor.test.ts +535 -0
  158. package/global/tools/anvil-memory/src/__tests__/ccs/edge-cases.test.ts +645 -0
  159. package/global/tools/anvil-memory/src/__tests__/ccs/fixtures.ts +363 -0
  160. package/global/tools/anvil-memory/src/__tests__/ccs/index.ts +8 -0
  161. package/global/tools/anvil-memory/src/__tests__/ccs/integration.test.ts +417 -0
  162. package/global/tools/anvil-memory/src/__tests__/ccs/prompt-generator.test.ts +571 -0
  163. package/global/tools/anvil-memory/src/__tests__/ccs/ralph-stop.test.ts +440 -0
  164. package/global/tools/anvil-memory/src/__tests__/ccs/test-utils.ts +252 -0
  165. package/global/tools/anvil-memory/src/__tests__/commands.test.ts +657 -0
  166. package/global/tools/anvil-memory/src/__tests__/db.test.ts +641 -0
  167. package/global/tools/anvil-memory/src/__tests__/hooks.test.ts +272 -0
  168. package/global/tools/anvil-memory/src/__tests__/performance.test.ts +427 -0
  169. package/global/tools/anvil-memory/src/__tests__/test-utils.ts +113 -0
  170. package/global/tools/anvil-memory/src/commands/checkpoint.ts +197 -0
  171. package/global/tools/anvil-memory/src/commands/get.ts +115 -0
  172. package/global/tools/anvil-memory/src/commands/init.ts +94 -0
  173. package/global/tools/anvil-memory/src/commands/observe.ts +163 -0
  174. package/global/tools/anvil-memory/src/commands/search.ts +112 -0
  175. package/global/tools/anvil-memory/src/db.ts +638 -0
  176. package/global/tools/anvil-memory/src/index.ts +205 -0
  177. package/global/tools/anvil-memory/src/types.ts +122 -0
  178. package/global/tools/anvil-memory/tsconfig.json +29 -0
  179. package/global/tools/ralph-loop.sh +359 -0
  180. package/package.json +45 -0
  181. package/scripts/anvil +822 -0
  182. package/scripts/extract_patterns.py +222 -0
  183. package/scripts/init-project.sh +541 -0
  184. package/scripts/install.sh +229 -0
  185. package/scripts/postinstall.js +41 -0
  186. package/scripts/rollback.sh +188 -0
  187. package/scripts/sync.sh +623 -0
  188. package/scripts/test-statusline.sh +248 -0
  189. package/scripts/update_claude_md.py +224 -0
  190. package/scripts/verify.sh +255 -0
@@ -0,0 +1,222 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Extract patterns from recent git commits for CLAUDE.md updates.
4
+
5
+ Usage: python scripts/extract_patterns.py [--days N] [--min-occurrences N]
6
+
7
+ Output: JSON with extracted patterns to stdout
8
+ """
9
+
10
+ import subprocess
11
+ import json
12
+ import re
13
+ import argparse
14
+ from collections import Counter, defaultdict
15
+ from datetime import datetime, timedelta
16
+ from pathlib import Path
17
+
18
+
19
+ def get_recent_commits(days: int = 7) -> list[dict]:
20
+ """Get commits from the last N days."""
21
+ since = (datetime.now() - timedelta(days=days)).strftime('%Y-%m-%d')
22
+ result = subprocess.run(
23
+ ['git', 'log', f'--since={since}', '--pretty=format:%s||%h||%an||%ai'],
24
+ capture_output=True, text=True
25
+ )
26
+
27
+ if result.returncode != 0:
28
+ return []
29
+
30
+ commits = []
31
+ for line in result.stdout.strip().split('\n'):
32
+ if not line or '||' not in line:
33
+ continue
34
+ parts = line.split('||')
35
+ if len(parts) >= 4:
36
+ commits.append({
37
+ 'message': parts[0],
38
+ 'hash': parts[1],
39
+ 'author': parts[2],
40
+ 'date': parts[3]
41
+ })
42
+ return commits
43
+
44
+
45
+ def get_files_changed(commit_hash: str) -> list[str]:
46
+ """Get list of files changed in a commit."""
47
+ result = subprocess.run(
48
+ ['git', 'diff-tree', '--no-commit-id', '--name-only', '-r', commit_hash],
49
+ capture_output=True, text=True
50
+ )
51
+ if result.returncode != 0:
52
+ return []
53
+ return [f for f in result.stdout.strip().split('\n') if f]
54
+
55
+
56
+ def extract_commit_patterns(commits: list[dict], min_occurrences: int = 2) -> list[dict]:
57
+ """Identify patterns in commit messages."""
58
+ patterns = []
59
+
60
+ # Track various patterns
61
+ prefix_counter = Counter()
62
+ scope_counter = Counter()
63
+ issue_refs = Counter()
64
+ file_dir_counter = Counter()
65
+ fix_patterns = defaultdict(list) # Pattern name -> list of issue refs
66
+
67
+ for commit in commits:
68
+ msg = commit['message']
69
+ commit_hash = commit['hash']
70
+
71
+ # Extract conventional commit prefix (feat, fix, docs, etc.)
72
+ prefix_match = re.match(r'^(\w+)(?:\(([^)]+)\))?[!:]', msg)
73
+ if prefix_match:
74
+ prefix = prefix_match.group(1).lower()
75
+ prefix_counter[prefix] += 1
76
+
77
+ # Extract scope if present
78
+ scope = prefix_match.group(2)
79
+ if scope:
80
+ scope_counter[scope.lower()] += 1
81
+
82
+ # Extract issue references (ANV-XX, ENG-XX, etc.)
83
+ issues = re.findall(r'([A-Z]+-\d+)', msg)
84
+ for issue in issues:
85
+ issue_refs[issue] += 1
86
+
87
+ # Track fix patterns for "Verify X Before Y" type learnings
88
+ if msg.startswith('fix'):
89
+ # Look for common fix categories
90
+ if 'branch' in msg.lower():
91
+ fix_patterns['Verify Branch Before Read'].extend(issues)
92
+ if 'path' in msg.lower() or 'file' in msg.lower():
93
+ fix_patterns['Verify File Location First'].extend(issues)
94
+ if 'config' in msg.lower():
95
+ fix_patterns['Verify Config Before Use'].extend(issues)
96
+
97
+ # Track directory patterns from changed files
98
+ files = get_files_changed(commit_hash)
99
+ for f in files:
100
+ parts = Path(f).parts
101
+ if len(parts) > 1:
102
+ file_dir_counter[parts[0]] += 1
103
+
104
+ # Generate patterns from collected data
105
+
106
+ # 1. Commit type patterns (if dominant type exists)
107
+ total_commits = len(commits)
108
+ for prefix, count in prefix_counter.most_common(3):
109
+ if count >= min_occurrences:
110
+ percentage = (count / total_commits) * 100
111
+ if percentage >= 20: # At least 20% of commits
112
+ patterns.append({
113
+ 'name': f'{prefix.title()} Focus',
114
+ 'description': f'{count} {prefix} commits ({percentage:.0f}% of activity)',
115
+ 'evidence': ', '.join(list(issue_refs.keys())[:5]),
116
+ 'type': 'activity'
117
+ })
118
+
119
+ # 2. Scope patterns (frequently touched areas)
120
+ for scope, count in scope_counter.most_common(5):
121
+ if count >= min_occurrences:
122
+ patterns.append({
123
+ 'name': f'{scope.title()} Changes',
124
+ 'description': f'Frequent modifications to {scope} ({count} commits)',
125
+ 'evidence': ', '.join(list(issue_refs.keys())[:3]),
126
+ 'type': 'scope'
127
+ })
128
+
129
+ # 3. Fix patterns (potential learnings)
130
+ for pattern_name, issues in fix_patterns.items():
131
+ if len(issues) >= min_occurrences:
132
+ unique_issues = list(set(issues))[:5]
133
+ patterns.append({
134
+ 'name': pattern_name,
135
+ 'description': f'Pattern emerged from {len(issues)} related fixes',
136
+ 'evidence': ', '.join(unique_issues),
137
+ 'type': 'learning'
138
+ })
139
+
140
+ # 4. Directory focus patterns
141
+ for directory, count in file_dir_counter.most_common(3):
142
+ if count >= min_occurrences * 2 and directory not in ['.github', 'node_modules']:
143
+ patterns.append({
144
+ 'name': f'{directory}/ Development',
145
+ 'description': f'Active development in {directory}/ ({count} file changes)',
146
+ 'evidence': ', '.join(list(issue_refs.keys())[:3]),
147
+ 'type': 'focus'
148
+ })
149
+
150
+ return patterns
151
+
152
+
153
+ def extract_retro_patterns(days: int = 7) -> list[dict]:
154
+ """Extract patterns from recent retrospective files."""
155
+ patterns = []
156
+ retros_dir = Path('.claude/retros')
157
+
158
+ if not retros_dir.exists():
159
+ return patterns
160
+
161
+ cutoff = datetime.now() - timedelta(days=days)
162
+
163
+ for retro_file in retros_dir.rglob('*.md'):
164
+ try:
165
+ # Check file modification time
166
+ mtime = datetime.fromtimestamp(retro_file.stat().st_mtime)
167
+ if mtime < cutoff:
168
+ continue
169
+
170
+ content = retro_file.read_text()
171
+
172
+ # Extract key learning
173
+ learning_match = re.search(r'## Key Learning\s*\n+(.+?)(?:\n\n|\n##|$)', content, re.DOTALL)
174
+ if learning_match:
175
+ learning = learning_match.group(1).strip()
176
+ # Clean up the learning text
177
+ learning = re.sub(r'\s+', ' ', learning)[:100]
178
+
179
+ # Extract issue references from filename or content
180
+ issue_match = re.search(r'([A-Z]+-\d+)', retro_file.name)
181
+ evidence = issue_match.group(1) if issue_match else retro_file.stem
182
+
183
+ patterns.append({
184
+ 'name': learning[:50] + ('...' if len(learning) > 50 else ''),
185
+ 'description': 'From retrospective analysis',
186
+ 'evidence': evidence,
187
+ 'type': 'retro',
188
+ 'source': str(retro_file)
189
+ })
190
+ except Exception:
191
+ continue
192
+
193
+ return patterns
194
+
195
+
196
+ def main():
197
+ parser = argparse.ArgumentParser(description='Extract patterns from git commits')
198
+ parser.add_argument('--days', type=int, default=7, help='Number of days to analyze')
199
+ parser.add_argument('--min-occurrences', type=int, default=2, help='Minimum occurrences for a pattern')
200
+ parser.add_argument('--include-retros', action='store_true', help='Include retrospective patterns')
201
+ args = parser.parse_args()
202
+
203
+ commits = get_recent_commits(args.days)
204
+ patterns = extract_commit_patterns(commits, args.min_occurrences)
205
+
206
+ if args.include_retros:
207
+ retro_patterns = extract_retro_patterns(args.days)
208
+ patterns.extend(retro_patterns)
209
+
210
+ output = {
211
+ 'extracted_at': datetime.now().isoformat(),
212
+ 'analysis_period_days': args.days,
213
+ 'commit_count': len(commits),
214
+ 'pattern_count': len(patterns),
215
+ 'patterns': patterns
216
+ }
217
+
218
+ print(json.dumps(output, indent=2))
219
+
220
+
221
+ if __name__ == '__main__':
222
+ main()