sourcecode 1.30.4__py3-none-any.whl → 1.30.5__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.
- sourcecode/__init__.py +1 -1
- sourcecode/cli.py +2 -0
- sourcecode/flow_analyzer.py +335 -0
- sourcecode/prepare_context.py +13 -3
- {sourcecode-1.30.4.dist-info → sourcecode-1.30.5.dist-info}/METADATA +3 -3
- {sourcecode-1.30.4.dist-info → sourcecode-1.30.5.dist-info}/RECORD +9 -9
- {sourcecode-1.30.4.dist-info → sourcecode-1.30.5.dist-info}/WHEEL +0 -0
- {sourcecode-1.30.4.dist-info → sourcecode-1.30.5.dist-info}/entry_points.txt +0 -0
- {sourcecode-1.30.4.dist-info → sourcecode-1.30.5.dist-info}/licenses/LICENSE +0 -0
sourcecode/__init__.py
CHANGED
sourcecode/cli.py
CHANGED
|
@@ -1868,6 +1868,8 @@ def prepare_context_cmd(
|
|
|
1868
1868
|
out["suggested_review_order"] = output.suggested_review_order
|
|
1869
1869
|
if output.execution_paths:
|
|
1870
1870
|
out["execution_paths"] = output.execution_paths
|
|
1871
|
+
if output.behavioral_impact:
|
|
1872
|
+
out["behavioral_impact"] = output.behavioral_impact
|
|
1871
1873
|
if output.impact_summary:
|
|
1872
1874
|
out["impact_summary"] = output.impact_summary
|
|
1873
1875
|
if output.why_these_files:
|
sourcecode/flow_analyzer.py
CHANGED
|
@@ -177,6 +177,49 @@ def _has_code_evidence(clean: str, class_name: str) -> bool:
|
|
|
177
177
|
return False
|
|
178
178
|
|
|
179
179
|
|
|
180
|
+
_EVIDENCE_PRIORITY: dict[str, int] = {
|
|
181
|
+
"none": 0, "heuristic_only": 1, "direct_call": 2, "direct_injection": 3,
|
|
182
|
+
}
|
|
183
|
+
_EVIDENCE_STRONG = frozenset({"direct_call", "direct_injection"})
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _classify_evidence_type(clean: str, class_name: str) -> str:
|
|
187
|
+
"""Return how class_name is referenced in pre-stripped content."""
|
|
188
|
+
esc = re.escape(class_name)
|
|
189
|
+
if re.search(rf"\b(?:private|protected)\s+{esc}\b", clean, re.IGNORECASE):
|
|
190
|
+
return "direct_injection"
|
|
191
|
+
if re.search(rf"[,(]\s*{esc}\s+\w+", clean, re.IGNORECASE):
|
|
192
|
+
return "direct_injection"
|
|
193
|
+
if re.search(rf":\s*{esc}\b", clean, re.IGNORECASE):
|
|
194
|
+
return "direct_injection"
|
|
195
|
+
if re.search(rf"\bnew\s+{esc}\s*\(", clean, re.IGNORECASE):
|
|
196
|
+
return "direct_call"
|
|
197
|
+
if re.search(rf"\b{esc}\s*\(", clean):
|
|
198
|
+
return "direct_call"
|
|
199
|
+
non_import = re.search(
|
|
200
|
+
rf"^(?!\s*(?:import|require|from|//|#|\*)\b).*\b{esc}\b",
|
|
201
|
+
clean, re.IGNORECASE | re.MULTILINE,
|
|
202
|
+
)
|
|
203
|
+
if non_import:
|
|
204
|
+
return "heuristic_only"
|
|
205
|
+
return "none"
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def _worst_evidence(levels: list[str]) -> str:
|
|
209
|
+
return min(levels, key=lambda x: _EVIDENCE_PRIORITY.get(x, 0)) if levels else "none"
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def _compute_confidence(evidence_level: str, trace_len: int) -> str:
|
|
213
|
+
if evidence_level not in _EVIDENCE_STRONG:
|
|
214
|
+
return "low"
|
|
215
|
+
return "high" if trace_len >= 2 else "medium"
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _build_trace_step(source_class: str, target_class: str, evidence_type: str) -> str:
|
|
219
|
+
verb = "injects" if evidence_type == "direct_injection" else "calls"
|
|
220
|
+
return f"{source_class} {verb} {target_class}"
|
|
221
|
+
|
|
222
|
+
|
|
180
223
|
def _find_evidenced_ordered(
|
|
181
224
|
root: Path,
|
|
182
225
|
source_path: str,
|
|
@@ -307,4 +350,296 @@ def analyze_execution_paths(
|
|
|
307
350
|
"end_state": _detect_end_state([item["step"] for item in path_items]),
|
|
308
351
|
})
|
|
309
352
|
|
|
353
|
+
|
|
354
|
+
# ── Behavioral impact helpers ─────────────────────────────────────────────────
|
|
355
|
+
|
|
356
|
+
def _domain_from_class(class_name: str) -> str:
|
|
357
|
+
"""Extract human-readable domain noun from a class name."""
|
|
358
|
+
stripped = re.sub(
|
|
359
|
+
r"(?i)(?:repository|repo|dao|mapper|store|service|manager|handler|helper|"
|
|
360
|
+
r"impl|controller|api|resource|endpoint|facade)$",
|
|
361
|
+
"", class_name,
|
|
362
|
+
)
|
|
363
|
+
return re.sub(r"(?<=[a-z])(?=[A-Z])", " ", stripped).strip().lower()
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
def _impact_item(statement: str, support: str, certainty: str) -> dict:
|
|
367
|
+
return {"statement": statement, "support": support, "certainty": certainty}
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
def _impact_descriptions(
|
|
371
|
+
changed_class: str,
|
|
372
|
+
changed_type: str,
|
|
373
|
+
end_state: str,
|
|
374
|
+
ctrl_clean: str,
|
|
375
|
+
evidence_level: str,
|
|
376
|
+
) -> list[dict]:
|
|
377
|
+
domain = _domain_from_class(changed_class)
|
|
378
|
+
certainty = "medium" if evidence_level in _EVIDENCE_STRONG else "low"
|
|
379
|
+
items: list[dict] = []
|
|
380
|
+
|
|
381
|
+
if changed_type in _REPO_ARTIFACT_TYPES:
|
|
382
|
+
items.append(_impact_item(
|
|
383
|
+
f"{domain} persistence affected" if domain else "persistence affected",
|
|
384
|
+
f"{changed_class} is a repository in path",
|
|
385
|
+
certainty,
|
|
386
|
+
))
|
|
387
|
+
elif changed_type in _SERVICE_ARTIFACT_TYPES:
|
|
388
|
+
if end_state == "DB write":
|
|
389
|
+
items.append(_impact_item(
|
|
390
|
+
f"{domain} persistence affected" if domain else "persistence affected",
|
|
391
|
+
f"{changed_class} delegates to repository with DB write",
|
|
392
|
+
certainty,
|
|
393
|
+
))
|
|
394
|
+
else:
|
|
395
|
+
items.append(_impact_item(
|
|
396
|
+
f"{domain} behavior may change" if domain else "behavior may change",
|
|
397
|
+
f"{changed_class} is a service in path",
|
|
398
|
+
certainty,
|
|
399
|
+
))
|
|
400
|
+
else:
|
|
401
|
+
items.append(_impact_item(
|
|
402
|
+
f"{domain} behavior may change" if domain else "behavior may change",
|
|
403
|
+
f"{changed_class} is in path",
|
|
404
|
+
certainty,
|
|
405
|
+
))
|
|
406
|
+
|
|
407
|
+
if re.search(r"@PreAuthorize|@Secured|@RolesAllowed|hasRole\(|isAuthenticated", ctrl_clean, re.IGNORECASE):
|
|
408
|
+
items.append(_impact_item(
|
|
409
|
+
"authorization check present on entry point",
|
|
410
|
+
"security annotation detected on controller",
|
|
411
|
+
"high",
|
|
412
|
+
))
|
|
413
|
+
|
|
414
|
+
if re.search(r"@Transactional\b", ctrl_clean):
|
|
415
|
+
items.append(_impact_item(
|
|
416
|
+
"transactional boundary in path",
|
|
417
|
+
"@Transactional detected on entry point",
|
|
418
|
+
"high",
|
|
419
|
+
))
|
|
420
|
+
|
|
421
|
+
return items[:3]
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def _impact_descriptions_for_controller(
|
|
425
|
+
affected_path: list[str],
|
|
426
|
+
end_state: str,
|
|
427
|
+
ctrl_clean: str,
|
|
428
|
+
evidence_level: str,
|
|
429
|
+
) -> list[dict]:
|
|
430
|
+
certainty = "medium" if evidence_level in _EVIDENCE_STRONG else "low"
|
|
431
|
+
items: list[dict] = []
|
|
432
|
+
|
|
433
|
+
if end_state == "DB write":
|
|
434
|
+
domain = ""
|
|
435
|
+
for step in reversed(affected_path):
|
|
436
|
+
base = step.split(".")[0]
|
|
437
|
+
d = _domain_from_class(base)
|
|
438
|
+
if d:
|
|
439
|
+
domain = d
|
|
440
|
+
break
|
|
441
|
+
items.append(_impact_item(
|
|
442
|
+
f"{domain} persistence affected" if domain else "data persistence affected",
|
|
443
|
+
"repository with DB write detected in path",
|
|
444
|
+
certainty,
|
|
445
|
+
))
|
|
446
|
+
else:
|
|
447
|
+
items.append(_impact_item(
|
|
448
|
+
"request handler behavior may change",
|
|
449
|
+
"controller entry point modified",
|
|
450
|
+
certainty,
|
|
451
|
+
))
|
|
452
|
+
|
|
453
|
+
if re.search(r"@PreAuthorize|@Secured|@RolesAllowed|hasRole\(|isAuthenticated", ctrl_clean, re.IGNORECASE):
|
|
454
|
+
items.append(_impact_item(
|
|
455
|
+
"authorization check present on entry point",
|
|
456
|
+
"security annotation detected on controller",
|
|
457
|
+
"high",
|
|
458
|
+
))
|
|
459
|
+
|
|
460
|
+
if re.search(r"@Transactional\b", ctrl_clean):
|
|
461
|
+
items.append(_impact_item(
|
|
462
|
+
"transactional boundary in path",
|
|
463
|
+
"@Transactional detected on controller",
|
|
464
|
+
"high",
|
|
465
|
+
))
|
|
466
|
+
|
|
467
|
+
return items[:3]
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
def analyze_behavioral_impact(
|
|
471
|
+
changed_files: list[str],
|
|
472
|
+
all_paths: list[str],
|
|
473
|
+
root: Path,
|
|
474
|
+
classify_fn: Callable[[str], dict],
|
|
475
|
+
max_impacts: int = 3,
|
|
476
|
+
) -> list[dict]:
|
|
477
|
+
"""Build behavioral impact entries for PR review.
|
|
478
|
+
|
|
479
|
+
For changed controllers: forward traversal → service → repository.
|
|
480
|
+
For changed services/repos/domain: reverse lookup → find callers → build causal path.
|
|
481
|
+
|
|
482
|
+
Each entry: {entry_point, affected_path, impact, end_state}
|
|
483
|
+
All paths require direct code evidence — no naming/module inference.
|
|
484
|
+
Returns [] when no verifiable causal path exists.
|
|
485
|
+
"""
|
|
486
|
+
entry_changed = [f for f in changed_files if classify_fn(f)["artifact_type"] in _ENTRY_ARTIFACT_TYPES]
|
|
487
|
+
non_entry_changed = [f for f in changed_files if classify_fn(f)["artifact_type"] not in _ENTRY_ARTIFACT_TYPES]
|
|
488
|
+
|
|
489
|
+
all_entries = [p for p in all_paths if classify_fn(p)["artifact_type"] in _ENTRY_ARTIFACT_TYPES]
|
|
490
|
+
all_services = [p for p in all_paths if classify_fn(p)["artifact_type"] in _SERVICE_ARTIFACT_TYPES]
|
|
491
|
+
all_repos = [p for p in all_paths if classify_fn(p)["artifact_type"] in _REPO_ARTIFACT_TYPES]
|
|
492
|
+
|
|
493
|
+
result: list[dict] = []
|
|
494
|
+
seen_entries: set[str] = set()
|
|
495
|
+
|
|
496
|
+
# Case 1: changed controllers — forward traversal
|
|
497
|
+
for entry_path in entry_changed:
|
|
498
|
+
if len(result) >= max_impacts:
|
|
499
|
+
break
|
|
500
|
+
entry_class = Path(entry_path).stem
|
|
501
|
+
if entry_class in seen_entries:
|
|
502
|
+
continue
|
|
503
|
+
lang = _detect_lang(entry_path)
|
|
504
|
+
ctrl_content = _read_safe(root, entry_path)
|
|
505
|
+
if not ctrl_content:
|
|
506
|
+
continue
|
|
507
|
+
ctrl_clean = _strip_comments(ctrl_content, lang)
|
|
508
|
+
entry_method = _find_entry_method(ctrl_clean)
|
|
509
|
+
entry_str = _step_label(entry_class, entry_method)
|
|
510
|
+
|
|
511
|
+
evidenced_svcs = _find_evidenced_ordered(root, entry_path, all_services)
|
|
512
|
+
if not evidenced_svcs:
|
|
513
|
+
continue
|
|
514
|
+
|
|
515
|
+
svc_class, svc_method = evidenced_svcs[0]
|
|
516
|
+
svc_evidence = _classify_evidence_type(ctrl_clean, svc_class)
|
|
517
|
+
affected_path = [_step_label(svc_class, svc_method)]
|
|
518
|
+
trace = [_build_trace_step(entry_class, svc_class, svc_evidence)]
|
|
519
|
+
evidence_levels = [svc_evidence]
|
|
520
|
+
|
|
521
|
+
svc_path = next((p for p in all_services if Path(p).stem == svc_class), None)
|
|
522
|
+
if svc_path:
|
|
523
|
+
svc_content_raw = _read_safe(root, svc_path)
|
|
524
|
+
if svc_content_raw:
|
|
525
|
+
svc_clean_raw = _strip_comments(svc_content_raw, _detect_lang(svc_path))
|
|
526
|
+
evidenced_repos = _find_evidenced_ordered(root, svc_path, all_repos)
|
|
527
|
+
if evidenced_repos:
|
|
528
|
+
repo_class, repo_method = evidenced_repos[0]
|
|
529
|
+
repo_evidence = _classify_evidence_type(svc_clean_raw, repo_class)
|
|
530
|
+
affected_path.append(_step_label(repo_class, repo_method))
|
|
531
|
+
trace.append(_build_trace_step(svc_class, repo_class, repo_evidence))
|
|
532
|
+
evidence_levels.append(repo_evidence)
|
|
533
|
+
|
|
534
|
+
end_state = _detect_end_state(affected_path)
|
|
535
|
+
evidence_level = _worst_evidence(evidence_levels)
|
|
536
|
+
confidence = _compute_confidence(evidence_level, len(trace))
|
|
537
|
+
seen_entries.add(entry_class)
|
|
538
|
+
result.append({
|
|
539
|
+
"entry_point": entry_str,
|
|
540
|
+
"affected_path": affected_path,
|
|
541
|
+
"impact": _impact_descriptions_for_controller(affected_path, end_state, ctrl_clean, evidence_level),
|
|
542
|
+
"end_state": end_state,
|
|
543
|
+
"confidence": confidence,
|
|
544
|
+
"evidence_level": evidence_level,
|
|
545
|
+
"trace": trace,
|
|
546
|
+
})
|
|
547
|
+
|
|
548
|
+
# Case 2: changed non-controllers — reverse lookup
|
|
549
|
+
for changed_path in non_entry_changed:
|
|
550
|
+
if len(result) >= max_impacts:
|
|
551
|
+
break
|
|
552
|
+
changed_class = Path(changed_path).stem
|
|
553
|
+
changed_type = classify_fn(changed_path)["artifact_type"]
|
|
554
|
+
|
|
555
|
+
for ctrl_path in all_entries:
|
|
556
|
+
if len(result) >= max_impacts:
|
|
557
|
+
break
|
|
558
|
+
ctrl_class = Path(ctrl_path).stem
|
|
559
|
+
if ctrl_class in seen_entries:
|
|
560
|
+
continue
|
|
561
|
+
ctrl_content = _read_safe(root, ctrl_path)
|
|
562
|
+
if not ctrl_content:
|
|
563
|
+
continue
|
|
564
|
+
ctrl_lang = _detect_lang(ctrl_path)
|
|
565
|
+
ctrl_clean = _strip_comments(ctrl_content, ctrl_lang)
|
|
566
|
+
|
|
567
|
+
affected_path: list[str] = []
|
|
568
|
+
trace: list[str] = []
|
|
569
|
+
evidence_levels: list[str] = []
|
|
570
|
+
|
|
571
|
+
if _has_code_evidence(ctrl_clean, changed_class):
|
|
572
|
+
# Direct: controller → changed class
|
|
573
|
+
ctrl_to_changed = _classify_evidence_type(ctrl_clean, changed_class)
|
|
574
|
+
fmap = _build_field_map(ctrl_clean)
|
|
575
|
+
method = _find_called_method(ctrl_clean, changed_class, fmap)
|
|
576
|
+
affected_path.append(_step_label(changed_class, method))
|
|
577
|
+
trace.append(_build_trace_step(ctrl_class, changed_class, ctrl_to_changed))
|
|
578
|
+
evidence_levels.append(ctrl_to_changed)
|
|
579
|
+
|
|
580
|
+
if changed_type in _SERVICE_ARTIFACT_TYPES:
|
|
581
|
+
changed_content = _read_safe(root, changed_path)
|
|
582
|
+
changed_clean = _strip_comments(changed_content, _detect_lang(changed_path)) if changed_content else ""
|
|
583
|
+
evidenced_repos = _find_evidenced_ordered(root, changed_path, all_repos)
|
|
584
|
+
if evidenced_repos:
|
|
585
|
+
rclass, rmethod = evidenced_repos[0]
|
|
586
|
+
repo_evidence = _classify_evidence_type(changed_clean, rclass)
|
|
587
|
+
affected_path.append(_step_label(rclass, rmethod))
|
|
588
|
+
trace.append(_build_trace_step(changed_class, rclass, repo_evidence))
|
|
589
|
+
evidence_levels.append(repo_evidence)
|
|
590
|
+
else:
|
|
591
|
+
# Indirect: controller → mediating service → changed class
|
|
592
|
+
for svc_class, svc_method in _find_evidenced_ordered(root, ctrl_path, all_services):
|
|
593
|
+
svc_p = next((p for p in all_services if Path(p).stem == svc_class), None)
|
|
594
|
+
if not svc_p:
|
|
595
|
+
continue
|
|
596
|
+
svc_content = _read_safe(root, svc_p)
|
|
597
|
+
if not svc_content:
|
|
598
|
+
continue
|
|
599
|
+
svc_lang = _detect_lang(svc_p)
|
|
600
|
+
svc_clean = _strip_comments(svc_content, svc_lang)
|
|
601
|
+
if not _has_code_evidence(svc_clean, changed_class):
|
|
602
|
+
continue
|
|
603
|
+
|
|
604
|
+
ctrl_to_svc = _classify_evidence_type(ctrl_clean, svc_class)
|
|
605
|
+
svc_to_changed = _classify_evidence_type(svc_clean, changed_class)
|
|
606
|
+
fmap = _build_field_map(svc_clean)
|
|
607
|
+
method = _find_called_method(svc_clean, changed_class, fmap)
|
|
608
|
+
affected_path = [_step_label(svc_class, svc_method), _step_label(changed_class, method)]
|
|
609
|
+
trace = [
|
|
610
|
+
_build_trace_step(ctrl_class, svc_class, ctrl_to_svc),
|
|
611
|
+
_build_trace_step(svc_class, changed_class, svc_to_changed),
|
|
612
|
+
]
|
|
613
|
+
evidence_levels = [ctrl_to_svc, svc_to_changed]
|
|
614
|
+
|
|
615
|
+
if changed_type in _SERVICE_ARTIFACT_TYPES:
|
|
616
|
+
changed_content = _read_safe(root, changed_path)
|
|
617
|
+
changed_clean = _strip_comments(changed_content, _detect_lang(changed_path)) if changed_content else ""
|
|
618
|
+
evidenced_repos = _find_evidenced_ordered(root, changed_path, all_repos)
|
|
619
|
+
if evidenced_repos:
|
|
620
|
+
rclass, rmethod = evidenced_repos[0]
|
|
621
|
+
repo_evidence = _classify_evidence_type(changed_clean, rclass)
|
|
622
|
+
affected_path.append(_step_label(rclass, rmethod))
|
|
623
|
+
trace.append(_build_trace_step(changed_class, rclass, repo_evidence))
|
|
624
|
+
evidence_levels.append(repo_evidence)
|
|
625
|
+
break
|
|
626
|
+
|
|
627
|
+
if not affected_path:
|
|
628
|
+
continue
|
|
629
|
+
|
|
630
|
+
entry_method = _find_entry_method(ctrl_clean)
|
|
631
|
+
end_state = _detect_end_state(affected_path)
|
|
632
|
+
evidence_level = _worst_evidence(evidence_levels)
|
|
633
|
+
confidence = _compute_confidence(evidence_level, len(trace))
|
|
634
|
+
seen_entries.add(ctrl_class)
|
|
635
|
+
result.append({
|
|
636
|
+
"entry_point": _step_label(ctrl_class, entry_method),
|
|
637
|
+
"affected_path": affected_path,
|
|
638
|
+
"impact": _impact_descriptions(changed_class, changed_type, end_state, ctrl_clean, evidence_level),
|
|
639
|
+
"end_state": end_state,
|
|
640
|
+
"confidence": confidence,
|
|
641
|
+
"evidence_level": evidence_level,
|
|
642
|
+
"trace": trace,
|
|
643
|
+
})
|
|
644
|
+
|
|
310
645
|
return result
|
sourcecode/prepare_context.py
CHANGED
|
@@ -352,6 +352,7 @@ class TaskOutput:
|
|
|
352
352
|
review_hotspots: list[str] = field(default_factory=list)
|
|
353
353
|
suggested_review_order: list[str] = field(default_factory=list)
|
|
354
354
|
execution_paths: list[dict] = field(default_factory=list)
|
|
355
|
+
behavioral_impact: list[dict] = field(default_factory=list)
|
|
355
356
|
|
|
356
357
|
|
|
357
358
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -875,12 +876,20 @@ class TaskContextBuilder:
|
|
|
875
876
|
_pr_suggested_review_order.append(_f)
|
|
876
877
|
_seen_order.add(_f)
|
|
877
878
|
|
|
878
|
-
# ── 6d. review-pr: execution paths
|
|
879
|
+
# ── 6d. review-pr: execution paths + behavioral impact ──────────────
|
|
879
880
|
_execution_paths: list[dict] = []
|
|
881
|
+
_behavioral_impact: list[dict] = []
|
|
880
882
|
if task_name == "review-pr" and _delta_files:
|
|
881
|
-
from sourcecode.flow_analyzer import analyze_execution_paths
|
|
883
|
+
from sourcecode.flow_analyzer import analyze_execution_paths, analyze_behavioral_impact
|
|
884
|
+
_changed_sorted = sorted(_delta_files)
|
|
882
885
|
_execution_paths = analyze_execution_paths(
|
|
883
|
-
changed_files=
|
|
886
|
+
changed_files=_changed_sorted,
|
|
887
|
+
all_paths=all_paths,
|
|
888
|
+
root=self.root,
|
|
889
|
+
classify_fn=self._classify_changed_file,
|
|
890
|
+
)
|
|
891
|
+
_behavioral_impact = analyze_behavioral_impact(
|
|
892
|
+
changed_files=_changed_sorted,
|
|
884
893
|
all_paths=all_paths,
|
|
885
894
|
root=self.root,
|
|
886
895
|
classify_fn=self._classify_changed_file,
|
|
@@ -1117,6 +1126,7 @@ class TaskContextBuilder:
|
|
|
1117
1126
|
review_hotspots=_pr_review_hotspots,
|
|
1118
1127
|
suggested_review_order=_pr_suggested_review_order,
|
|
1119
1128
|
execution_paths=_execution_paths,
|
|
1129
|
+
behavioral_impact=_behavioral_impact,
|
|
1120
1130
|
)
|
|
1121
1131
|
|
|
1122
1132
|
def render_prompt(self, output: TaskOutput) -> str:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version: 1.30.
|
|
3
|
+
Version: 1.30.5
|
|
4
4
|
Summary: Deterministic codebase context for AI coding agents
|
|
5
5
|
License: Apache License
|
|
6
6
|
Version 2.0, January 2004
|
|
@@ -221,7 +221,7 @@ Description-Content-Type: text/markdown
|
|
|
221
221
|
|
|
222
222
|
**Deterministic, behavior-aware codebase context for AI agents and PR review.**
|
|
223
223
|
|
|
224
|
-

|
|
225
225
|

|
|
226
226
|
|
|
227
227
|
---
|
|
@@ -257,7 +257,7 @@ pipx install sourcecode
|
|
|
257
257
|
|
|
258
258
|
```bash
|
|
259
259
|
sourcecode version
|
|
260
|
-
# sourcecode 1.30.
|
|
260
|
+
# sourcecode 1.30.5
|
|
261
261
|
```
|
|
262
262
|
|
|
263
263
|
---
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
sourcecode/__init__.py,sha256=
|
|
1
|
+
sourcecode/__init__.py,sha256=7mzS6ap60mKtxcfyRLTvFJPqWtGX2Zskqn9qvjD_5Z4,103
|
|
2
2
|
sourcecode/adaptive_scanner.py,sha256=RTNExwWPXzjgLaRueT7UuxkPj5ZEToWjGbx1j0LSZ9E,10250
|
|
3
3
|
sourcecode/architecture_analyzer.py,sha256=MyBa0Hf5HmkudZQDLKrjcWDKETXETXl0mQX1swtTwAA,39091
|
|
4
4
|
sourcecode/architecture_summary.py,sha256=z34_6v7cSwy98cof2UVciGho7SCrZ93tiqMmq5WNzRQ,20405
|
|
5
5
|
sourcecode/ast_extractor.py,sha256=XgrZg2DcWcUm9r87cRG3KGO7IK2TIL_N-CvhSbUmmh4,49901
|
|
6
6
|
sourcecode/classifier.py,sha256=pYve2J1LqtYssU3lYLMDz18PT-CjN5c18QYE7R_IG1Q,7507
|
|
7
|
-
sourcecode/cli.py,sha256=
|
|
7
|
+
sourcecode/cli.py,sha256=mQEzR-IXcZAx4yl0Sh-m69CZYJc6UwlR8vmRODKzcPo,80878
|
|
8
8
|
sourcecode/code_notes_analyzer.py,sha256=y1MJBnPZHYp4i6cQCXUb9ATIyifS_qMQWjw_8lPkpsU,9215
|
|
9
9
|
sourcecode/confidence_analyzer.py,sha256=xw_Jv8pAd0wd8t2vvQlorw8Ih0rSF3YCoFS8K-_4aXg,15762
|
|
10
10
|
sourcecode/context_scorer.py,sha256=QpChSpsmaAYz91rXA4Ue5xzQmNz_ZboZN09YOHScq1U,14679
|
|
@@ -17,11 +17,11 @@ sourcecode/doc_analyzer.py,sha256=afA4uJFwXZ_uR2l4J0pQwbeTkRkGmKdN9KhRVYePBUw,24
|
|
|
17
17
|
sourcecode/entrypoint_classifier.py,sha256=gvKgl0f5T8ol1r4JMmkeqGHuZTfZJiOwFOWdc7EYwYw,4061
|
|
18
18
|
sourcecode/env_analyzer.py,sha256=GxCidahAAIptTdDFIlVB6URd4HBnBlIX_SqUov3MBRQ,22076
|
|
19
19
|
sourcecode/file_classifier.py,sha256=48ly5Z6exkzBy8lNy1AkdP4-oJqIA1zT3LZfffuTyDo,11572
|
|
20
|
-
sourcecode/flow_analyzer.py,sha256=
|
|
20
|
+
sourcecode/flow_analyzer.py,sha256=m29PJPdAwH4n3ZNqMidgi97csSUUtav5SM9lkDy_sr8,27219
|
|
21
21
|
sourcecode/git_analyzer.py,sha256=_pCg2V4d2aa17k9hayTzpexAj8syvyk4y9NYNvvgOAI,12802
|
|
22
22
|
sourcecode/graph_analyzer.py,sha256=iUK-7pSV-cvGqqD2hENdYmhnm0wcXFEyK-xnu5ul8OU,62515
|
|
23
23
|
sourcecode/metrics_analyzer.py,sha256=m0ENgtqKeBL17kUIK3fmGkgo7UfXBNHxCMj0H_Y5K7c,22750
|
|
24
|
-
sourcecode/prepare_context.py,sha256=
|
|
24
|
+
sourcecode/prepare_context.py,sha256=yd00J2MgFXw2aCgV9Fr2mAwn4GwpHxcXP16PtYRt7MU,130061
|
|
25
25
|
sourcecode/progress.py,sha256=qn30sWaHOkjTgXsSBmiPkz7Rsbwc5oSlIe6JNEMYp_k,3149
|
|
26
26
|
sourcecode/ranking_engine.py,sha256=virVglafZufioHpZpwktjMvUiL0TZELWQCQnQNV8dFo,9360
|
|
27
27
|
sourcecode/redactor.py,sha256=xuGcadGEHaPw4qZXlMDvzMCsr4VOkdp3oBQptHyJk8c,2884
|
|
@@ -62,8 +62,8 @@ sourcecode/telemetry/consent.py,sha256=wLMvGNJeSSyZoNkQXpoUioY6mMv4Qdvuw7S9jAEWn
|
|
|
62
62
|
sourcecode/telemetry/events.py,sha256=oEvvulfsv5GIDWG2174gSS6tNB95w38AIYiYeifGKlE,2294
|
|
63
63
|
sourcecode/telemetry/filters.py,sha256=Asa71oRl7q3Wt_FMwuufIZJFzSYdgRNKS8LHCIyFeYE,4805
|
|
64
64
|
sourcecode/telemetry/transport.py,sha256=KJeIPCPWMdmbCP3ySGs2iUlia34U6vWne2dZsUezesw,1560
|
|
65
|
-
sourcecode-1.30.
|
|
66
|
-
sourcecode-1.30.
|
|
67
|
-
sourcecode-1.30.
|
|
68
|
-
sourcecode-1.30.
|
|
69
|
-
sourcecode-1.30.
|
|
65
|
+
sourcecode-1.30.5.dist-info/METADATA,sha256=ZWdIFgPwcMYKHaeIpte8GlY4CkEgZMDiDtYgQh_FBTM,26770
|
|
66
|
+
sourcecode-1.30.5.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
67
|
+
sourcecode-1.30.5.dist-info/entry_points.txt,sha256=ex3F9rmbXeyDIoFQHtkEqTsKSaJow8F0LrVu8XfIktQ,57
|
|
68
|
+
sourcecode-1.30.5.dist-info/licenses/LICENSE,sha256=7DdHrU9Z_3e7dSvq4ISijZNjnuHo5NIHNiHDouMQ9JU,10491
|
|
69
|
+
sourcecode-1.30.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|