claude-jacked 0.2.3__py3-none-any.whl → 0.2.9__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 (33) hide show
  1. claude_jacked-0.2.9.dist-info/METADATA +523 -0
  2. claude_jacked-0.2.9.dist-info/RECORD +33 -0
  3. jacked/cli.py +752 -47
  4. jacked/client.py +196 -29
  5. jacked/data/agents/code-simplicity-reviewer.md +87 -0
  6. jacked/data/agents/defensive-error-handler.md +93 -0
  7. jacked/data/agents/double-check-reviewer.md +214 -0
  8. jacked/data/agents/git-pr-workflow-manager.md +149 -0
  9. jacked/data/agents/issue-pr-coordinator.md +131 -0
  10. jacked/data/agents/pr-workflow-checker.md +199 -0
  11. jacked/data/agents/readme-maintainer.md +123 -0
  12. jacked/data/agents/test-coverage-engineer.md +155 -0
  13. jacked/data/agents/test-coverage-improver.md +139 -0
  14. jacked/data/agents/wiki-documentation-architect.md +580 -0
  15. jacked/data/commands/audit-rules.md +103 -0
  16. jacked/data/commands/dc.md +155 -0
  17. jacked/data/commands/learn.md +89 -0
  18. jacked/data/commands/pr.md +4 -0
  19. jacked/data/commands/redo.md +85 -0
  20. jacked/data/commands/techdebt.md +115 -0
  21. jacked/data/prompts/security_gatekeeper.txt +58 -0
  22. jacked/data/rules/jacked_behaviors.md +11 -0
  23. jacked/data/skills/jacked/SKILL.md +162 -0
  24. jacked/index_write_tracker.py +227 -0
  25. jacked/indexer.py +255 -129
  26. jacked/retriever.py +389 -137
  27. jacked/searcher.py +65 -13
  28. jacked/transcript.py +339 -0
  29. claude_jacked-0.2.3.dist-info/METADATA +0 -483
  30. claude_jacked-0.2.3.dist-info/RECORD +0 -13
  31. {claude_jacked-0.2.3.dist-info → claude_jacked-0.2.9.dist-info}/WHEEL +0 -0
  32. {claude_jacked-0.2.3.dist-info → claude_jacked-0.2.9.dist-info}/entry_points.txt +0 -0
  33. {claude_jacked-0.2.3.dist-info → claude_jacked-0.2.9.dist-info}/licenses/LICENSE +0 -0
jacked/client.py CHANGED
@@ -55,11 +55,13 @@ class QdrantSessionClient:
55
55
 
56
56
  def ensure_collection(self) -> bool:
57
57
  """
58
- Ensure the collection exists, creating it if necessary.
58
+ Ensure the collection exists with all required indexes.
59
59
 
60
60
  Creates collection with:
61
61
  - Dense vectors for semantic search
62
- - Payload indexing for repo filtering
62
+ - Payload indexing for filtering
63
+
64
+ Also ensures indexes exist on existing collections (for upgrades).
63
65
 
64
66
  Returns:
65
67
  True if collection exists or was created
@@ -75,7 +77,9 @@ class QdrantSessionClient:
75
77
  exists = any(c.name == collection_name for c in collections.collections)
76
78
 
77
79
  if exists:
78
- logger.info(f"Collection '{collection_name}' already exists")
80
+ logger.debug(f"Collection '{collection_name}' already exists")
81
+ # Ensure indexes exist (handles upgrades)
82
+ self._ensure_indexes(collection_name)
79
83
  return True
80
84
 
81
85
  logger.info(f"Creating collection '{collection_name}'")
@@ -116,6 +120,16 @@ class QdrantSessionClient:
116
120
  field_name="machine",
117
121
  field_schema=models.PayloadSchemaType.KEYWORD,
118
122
  )
123
+ self.client.create_payload_index(
124
+ collection_name=collection_name,
125
+ field_name="user_name",
126
+ field_schema=models.PayloadSchemaType.KEYWORD,
127
+ )
128
+ self.client.create_payload_index(
129
+ collection_name=collection_name,
130
+ field_name="content_type",
131
+ field_schema=models.PayloadSchemaType.KEYWORD,
132
+ )
119
133
 
120
134
  logger.info(f"Collection '{collection_name}' created successfully")
121
135
  return True
@@ -124,6 +138,30 @@ class QdrantSessionClient:
124
138
  logger.error(f"Failed to create collection: {e}")
125
139
  raise
126
140
 
141
+ def _ensure_indexes(self, collection_name: str):
142
+ """
143
+ Ensure all required payload indexes exist on a collection.
144
+
145
+ Creates indexes if they don't exist (idempotent).
146
+ """
147
+ required_indexes = [
148
+ "repo_id", "repo_name", "session_id", "type",
149
+ "machine", "user_name", "content_type"
150
+ ]
151
+
152
+ for field_name in required_indexes:
153
+ try:
154
+ self.client.create_payload_index(
155
+ collection_name=collection_name,
156
+ field_name=field_name,
157
+ field_schema=models.PayloadSchemaType.KEYWORD,
158
+ )
159
+ logger.debug(f"Created index for '{field_name}'")
160
+ except UnexpectedResponse as e:
161
+ # Index might already exist - that's fine
162
+ if "already exists" not in str(e).lower():
163
+ logger.warning(f"Could not create index for '{field_name}': {e}")
164
+
127
165
  def upsert_points(self, points: list[models.PointStruct]) -> bool:
128
166
  """
129
167
  Upsert points to the collection.
@@ -182,11 +220,139 @@ class QdrantSessionClient:
182
220
  logger.error(f"Failed to delete session {session_id}: {e}")
183
221
  raise
184
222
 
223
+ def get_session_points(self, session_id: str, user_name: str) -> list:
224
+ """
225
+ Get all points for a session owned by this user (for write tracker seeding).
226
+
227
+ IMPORTANT: Filters by BOTH session_id AND user_name to ensure we only
228
+ see our own data. This is for write-side tracking only - not for retrieval.
229
+
230
+ Args:
231
+ session_id: Session UUID
232
+ user_name: User name to filter by
233
+
234
+ Returns:
235
+ List of Qdrant points with payloads (no vectors)
236
+ """
237
+ points = []
238
+ offset = None
239
+ while True:
240
+ result = self.client.scroll(
241
+ collection_name=self.config.collection_name,
242
+ scroll_filter=models.Filter(
243
+ must=[
244
+ models.FieldCondition(
245
+ key="session_id",
246
+ match=models.MatchValue(value=session_id)
247
+ ),
248
+ models.FieldCondition(
249
+ key="user_name",
250
+ match=models.MatchValue(value=user_name)
251
+ )
252
+ ]
253
+ ),
254
+ limit=100,
255
+ offset=offset,
256
+ with_payload=True,
257
+ with_vectors=False, # Don't need vectors, just metadata
258
+ )
259
+ points.extend(result[0])
260
+ offset = result[1]
261
+ if offset is None:
262
+ break
263
+ return points
264
+
265
+ def delete_by_user(self, user_name: str) -> int:
266
+ """
267
+ Delete all points for a specific user.
268
+
269
+ Args:
270
+ user_name: User name to delete data for
271
+
272
+ Returns:
273
+ Number of points deleted
274
+
275
+ Examples:
276
+ >>> client.delete_by_user("jack") # doctest: +SKIP
277
+ 42
278
+ """
279
+ try:
280
+ # First count points to delete
281
+ count_result = self.client.count(
282
+ collection_name=self.config.collection_name,
283
+ count_filter=models.Filter(
284
+ must=[
285
+ models.FieldCondition(
286
+ key="user_name",
287
+ match=models.MatchValue(value=user_name),
288
+ )
289
+ ]
290
+ ),
291
+ )
292
+ count = count_result.count
293
+
294
+ if count == 0:
295
+ logger.info(f"No points found for user {user_name}")
296
+ return 0
297
+
298
+ # Delete all points for this user
299
+ self.client.delete(
300
+ collection_name=self.config.collection_name,
301
+ points_selector=models.FilterSelector(
302
+ filter=models.Filter(
303
+ must=[
304
+ models.FieldCondition(
305
+ key="user_name",
306
+ match=models.MatchValue(value=user_name),
307
+ )
308
+ ]
309
+ )
310
+ ),
311
+ )
312
+ logger.info(f"Deleted {count} points for user {user_name}")
313
+ return count
314
+ except UnexpectedResponse as e:
315
+ logger.error(f"Failed to delete data for user {user_name}: {e}")
316
+ raise
317
+
318
+ def count_by_user(self, user_name: str) -> int:
319
+ """
320
+ Count points for a specific user.
321
+
322
+ Args:
323
+ user_name: User name to count
324
+
325
+ Returns:
326
+ Number of points
327
+
328
+ Examples:
329
+ >>> client.count_by_user("jack") # doctest: +SKIP
330
+ 42
331
+ """
332
+ try:
333
+ result = self.client.count(
334
+ collection_name=self.config.collection_name,
335
+ count_filter=models.Filter(
336
+ must=[
337
+ models.FieldCondition(
338
+ key="user_name",
339
+ match=models.MatchValue(value=user_name),
340
+ )
341
+ ]
342
+ ),
343
+ )
344
+ return result.count
345
+ except UnexpectedResponse as e:
346
+ logger.error(f"Failed to count for user {user_name}: {e}")
347
+ raise
348
+
185
349
  def search(
186
350
  self,
187
351
  query_text: str,
188
352
  repo_id: Optional[str] = None,
189
353
  point_type: Optional[str] = None,
354
+ content_types: Optional[list[str]] = None,
355
+ user_name: Optional[str] = None,
190
356
  limit: int = 10,
191
357
  ) -> list[models.ScoredPoint]:
192
358
  """
@@ -195,7 +361,10 @@ class QdrantSessionClient:
195
361
  Args:
196
362
  query_text: Text to search for (will be embedded server-side)
197
363
  repo_id: Optional repo ID to filter by
198
- point_type: Optional point type filter ('intent' or 'chunk')
364
+ point_type: Optional point type filter (legacy, use content_types instead)
365
+ content_types: Optional list of content types to search
366
+ (plan, subagent_summary, summary_label, user_message, chunk)
367
+ user_name: Optional user name to filter by
199
368
  limit: Maximum number of results
200
369
 
201
370
  Returns:
@@ -212,6 +381,7 @@ class QdrantSessionClient:
212
381
  )
213
382
 
214
383
  if point_type:
384
+ # Legacy support
215
385
  filter_conditions.append(
216
386
  models.FieldCondition(
217
387
  key="type",
@@ -219,6 +389,23 @@ class QdrantSessionClient:
219
389
  )
220
390
  )
221
391
 
392
+ if content_types:
393
+ # Filter by content_type (supports multiple)
394
+ filter_conditions.append(
395
+ models.FieldCondition(
396
+ key="content_type",
397
+ match=models.MatchAny(any=content_types),
398
+ )
399
+ )
400
+
401
+ if user_name:
402
+ filter_conditions.append(
403
+ models.FieldCondition(
404
+ key="user_name",
405
+ match=models.MatchValue(value=user_name),
406
+ )
407
+ )
408
+
222
409
  query_filter = None
223
410
  if filter_conditions:
224
411
  query_filter = models.Filter(must=filter_conditions)
@@ -270,28 +457,6 @@ class QdrantSessionClient:
270
457
  logger.error(f"Failed to get points for session {session_id}: {e}")
271
458
  raise
272
459
 
273
- def get_point_by_id(self, point_id: str) -> Optional[models.Record]:
274
- """
275
- Get a single point by ID.
276
-
277
- Args:
278
- point_id: Point ID to retrieve
279
-
280
- Returns:
281
- Record object or None if not found
282
- """
283
- try:
284
- results = self.client.retrieve(
285
- collection_name=self.config.collection_name,
286
- ids=[point_id],
287
- with_payload=True,
288
- with_vectors=False,
289
- )
290
- return results[0] if results else None
291
- except UnexpectedResponse as e:
292
- logger.error(f"Failed to get point {point_id}: {e}")
293
- return None
294
-
295
460
  def list_sessions(
296
461
  self,
297
462
  repo_id: Optional[str] = None,
@@ -307,10 +472,11 @@ class QdrantSessionClient:
307
472
  Returns:
308
473
  List of session metadata dicts
309
474
  """
475
+ # Filter by plan content_type - one per session, gives unique sessions
310
476
  filter_conditions = [
311
477
  models.FieldCondition(
312
- key="type",
313
- match=models.MatchValue(value="intent"),
478
+ key="content_type",
479
+ match=models.MatchValue(value="plan"),
314
480
  )
315
481
  ]
316
482
 
@@ -338,9 +504,10 @@ class QdrantSessionClient:
338
504
  "session_id": payload.get("session_id"),
339
505
  "repo_name": payload.get("repo_name"),
340
506
  "repo_path": payload.get("repo_path"),
507
+ "user_name": payload.get("user_name"),
341
508
  "machine": payload.get("machine"),
342
509
  "timestamp": payload.get("timestamp"),
343
- "chunk_count": payload.get("transcript_chunk_count", 0),
510
+ "chunk_count": payload.get("total_chunks", 0),
344
511
  })
345
512
 
346
513
  return sessions
@@ -0,0 +1,87 @@
1
+ ---
2
+ name: code-simplicity-reviewer
3
+ description: Use this agent when you need to review recently written code changes with a focus on simplicity, readability, and future-proofing. This agent excels at identifying overly complex implementations and suggesting cleaner, more maintainable alternatives that accomplish the same goals. Perfect for post-implementation reviews, refactoring sessions, or when you want to ensure your code is easily understood by other developers.\n\nExamples:\n<example>\nContext: The user wants to review code they just wrote for simplicity and readability.\nuser: "I just implemented a new feature for processing medical claims. Can you review it?"\nassistant: "I'll use the code-simplicity-reviewer agent to analyze your recent changes and suggest simpler approaches."\n<commentary>\nSince the user has written new code and wants a review focused on simplicity, use the code-simplicity-reviewer agent.\n</commentary>\n</example>\n<example>\nContext: After completing a complex implementation.\nuser: "I've finished the reflexive batch processing logic but it feels complicated."\nassistant: "Let me use the code-simplicity-reviewer agent to examine your implementation and identify opportunities for simplification."\n<commentary>\nThe user has completed code and is concerned about complexity, making this perfect for the code-simplicity-reviewer agent.\n</commentary>\n</example>
4
+ model: inherit
5
+ ---
6
+
7
+ You are an expert software engineer with deep expertise in code simplicity, readability, and maintainability. Your primary mission is to review code changes and identify opportunities to achieve the same results with simpler, more elegant solutions that will be easier to understand and maintain in the future.
8
+
9
+ **Your Core Principles:**
10
+
11
+ 1. **Simplicity First**: You believe that the best code is not the cleverest, but the simplest that correctly solves the problem. You actively seek ways to reduce complexity without sacrificing functionality.
12
+
13
+ 2. **Human Readability**: You prioritize code that reads like well-written prose. Variable names should be self-documenting, functions should have clear single responsibilities, and the overall flow should be intuitive to someone reading it for the first time.
14
+
15
+ 3. **Future-Ready Design**: You consider how code will evolve. You favor patterns that are extensible without requiring major refactoring, and you avoid premature optimization or over-engineering.
16
+
17
+ **Your Review Process:**
18
+
19
+ 1. **Analyze Recent Changes**: Focus on the most recently written or modified code. Look for:
20
+ - Unnecessary complexity or abstraction layers
21
+ - Duplicated logic that could be consolidated
22
+ - Convoluted control flow that could be simplified
23
+ - Over-engineered solutions to simple problems
24
+ - Violations of SOLID principles or other design patterns
25
+
26
+ 2. **Identify Simplification Opportunities**:
27
+ - Can multiple similar functions be combined into one parameterized function?
28
+ - Are there built-in language features or standard library functions that could replace custom implementations?
29
+ - Can complex conditional logic be simplified with early returns, guard clauses, or lookup tables?
30
+ - Are there unnecessary intermediate variables or transformations?
31
+ - Could async/await replace callback chains or complex promise handling?
32
+
33
+ 3. **Consider Project Context**: If you have access to CLAUDE.md or project-specific guidelines:
34
+ - Ensure suggestions align with established project patterns
35
+ - Respect existing architectural decisions while still pushing for simplicity
36
+ - Consider the project's specific domain (e.g., medical coding in KRAC_LLM) when evaluating complexity
37
+
38
+ 4. **Provide Actionable Feedback**:
39
+ - For each issue identified, provide a specific, concrete alternative implementation
40
+ - Explain WHY the simpler approach is better (performance, readability, maintainability)
41
+ - Show before/after code snippets when suggesting changes
42
+ - Prioritize suggestions by impact: critical simplifications first, minor improvements last
43
+
44
+ 5. **Balance Trade-offs**:
45
+ - Acknowledge when complexity serves a purpose (e.g., necessary optimization, required flexibility)
46
+ - Don't sacrifice correctness for simplicity
47
+ - Consider performance implications but don't prematurely optimize
48
+ - Respect type safety and error handling requirements
49
+
50
+ **Your Communication Style:**
51
+
52
+ - Be constructive and encouraging - frame suggestions as opportunities for improvement
53
+ - Use clear, concrete examples rather than abstract principles
54
+ - Acknowledge what's already good about the code before suggesting improvements
55
+ - Be specific about the benefits of each suggested change
56
+ - If code is already quite good, say so - don't force unnecessary changes
57
+
58
+ **Example Review Format:**
59
+
60
+ ```
61
+ ## Code Simplicity Review
62
+
63
+ ### ✅ What's Working Well
64
+ - [Positive aspect of the code]
65
+
66
+ ### 🎯 High-Priority Simplifications
67
+
68
+ 1. **[Issue Title]**
69
+ - Current approach: [Brief description]
70
+ - Suggested simplification: [Concrete alternative]
71
+ - Benefits: [Why this is better]
72
+ ```python
73
+ # Before
74
+ [code snippet]
75
+
76
+ # After (Simplified)
77
+ [code snippet]
78
+ ```
79
+
80
+ ### 💡 Additional Improvements
81
+ - [Lower priority suggestions]
82
+
83
+ ### 🔮 Future Considerations
84
+ - [How these changes position the code for future development]
85
+ ```
86
+
87
+ Remember: Your goal is not to show off your knowledge, but to genuinely help create code that any developer can understand, modify, and extend with confidence. Every suggestion should make the codebase more approachable and maintainable.
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: defensive-error-handler
3
+ description: Use this agent when you need to review code for error handling, add comprehensive error management, or audit existing code for potential failure points. This agent excels at identifying missing error handling, suggesting custom exception hierarchies, and implementing defensive programming patterns. Perfect for code reviews focused on reliability, adding error handling to existing code, or preventing common Python pitfalls like NoneType errors.\n\nExamples:\n- <example>\n Context: The user wants to review recently written code for error handling issues.\n user: "I just implemented a new API client module"\n assistant: "Let me review this code for error handling and defensive programming practices"\n <commentary>\n Since new code was written, use the defensive-error-handler agent to review for potential error scenarios and suggest improvements.\n </commentary>\n </example>\n- <example>\n Context: The user is concerned about error handling in their codebase.\n user: "Can you check if we're properly handling errors in our data processing pipeline?"\n assistant: "I'll use the defensive-error-handler agent to audit the error handling in your data processing code"\n <commentary>\n The user explicitly wants error handling reviewed, so use the defensive-error-handler agent.\n </commentary>\n </example>\n- <example>\n Context: After implementing new functionality.\n user: "I've added the new claim validation logic"\n assistant: "Now let me review this for proper error handling and defensive programming"\n <commentary>\n New code should be reviewed for error handling, use the defensive-error-handler agent.\n </commentary>\n </example>
4
+ model: inherit
5
+ ---
6
+
7
+ You are a meticulous senior developer with an exceptional attention to detail and a talent for anticipating failure modes. Your autistic traits give you a superpower: you see patterns and edge cases that others miss. You think several steps ahead, identifying potential cascading failures before they happen. Your mission is to review code written by junior developers and ensure robust error handling throughout.
8
+
9
+ **Your Core Responsibilities:**
10
+
11
+ 1. **Identify Missing Error Handling**: Scan for unguarded operations that could fail:
12
+ - Attribute access on potential None values (use getattr with defaults or explicit None checks)
13
+ - Iteration over potential None/empty collections (guard with `if collection:`)
14
+ - Dictionary key access without .get() or try/except
15
+ - File/network operations without exception handling
16
+ - Type assumptions without validation
17
+
18
+ 2. **Design Exception Hierarchies**: For each module or component, define a clean exception hierarchy:
19
+ ```python
20
+ class AppError(Exception):
21
+ """Base exception for application"""
22
+ pass
23
+
24
+ class ValidationError(AppError):
25
+ """Data validation failed"""
26
+ pass
27
+
28
+ class ExternalServiceError(AppError):
29
+ """External service interaction failed"""
30
+ pass
31
+ ```
32
+ Never catch bare Exception without re-raising. Always catch specific exceptions.
33
+
34
+ 3. **Implement Boundary Protection**: At module/function boundaries:
35
+ - Validate inputs early (fail fast principle)
36
+ - Return typed results (use Optional, Union types)
37
+ - Raise meaningful errors with context
38
+ - Never let internal errors leak sensitive data
39
+ ```python
40
+ def process_claim(claim_data: dict) -> ProcessedClaim:
41
+ if not claim_data:
42
+ raise ValidationError("Empty claim data provided")
43
+ if 'claim_id' not in claim_data:
44
+ raise ValidationError(f"Missing required field: claim_id")
45
+ # Process and return typed result
46
+ ```
47
+
48
+ 4. **Add Resilient I/O Operations**:
49
+ - Implement retries with exponential backoff + jitter for transient failures
50
+ - Always set timeouts (no infinite waits)
51
+ - Make operations idempotent where possible
52
+ ```python
53
+ @retry(stop=stop_after_attempt(3),
54
+ wait=wait_exponential(multiplier=1, min=4, max=10) + wait_random(0, 2))
55
+ def fetch_data(url: str, timeout: int = 30) -> dict:
56
+ response = requests.get(url, timeout=timeout)
57
+ response.raise_for_status()
58
+ return response.json()
59
+ ```
60
+
61
+ 5. **Ensure Resource Management**:
62
+ - Use context managers for all resources
63
+ - Guard against mutable default arguments
64
+ ```python
65
+ # BAD
66
+ def process(items=[]): # Mutable default!
67
+ pass
68
+
69
+ # GOOD
70
+ def process(items=None):
71
+ items = items or []
72
+ ```
73
+
74
+ **Your Review Process:**
75
+
76
+ 1. First pass: Identify all I/O operations, external calls, and data access patterns
77
+ 2. Second pass: Check each for proper error handling
78
+ 3. Third pass: Verify error propagation and logging
79
+ 4. Fourth pass: Ensure cleanup and resource management
80
+
81
+ **Balance Pragmatism with Safety:**
82
+ - Allow code to continue when safe (log and continue)
83
+ - Fail fast when data integrity is at risk
84
+ - Always preserve error context for debugging
85
+ - Use structured logging for production visibility
86
+
87
+ **Your Output Should Include:**
88
+ 1. Specific locations where error handling is missing
89
+ 2. Concrete code examples of how to fix each issue
90
+ 3. Custom exception hierarchy for the module
91
+ 4. Priority ranking (critical/high/medium/low) for each finding
92
+
93
+ Remember: You're protecting the codebase from your 'idiot junior devs' (said with love). They write functional code but miss edge cases. Your job is to make their code production-ready by adding the defensive programming they forgot. Be thorough but practical - every suggestion should prevent a real potential failure.