Skip to content

refactor(core): restart Anchor from original drift detection architecture - #40

Merged
Tanishq1030 merged 1 commit into
mainfrom
rebuild/v1-foundation
Aug 3, 2026
Merged

refactor(core): restart Anchor from original drift detection architecture#40
Tanishq1030 merged 1 commit into
mainfrom
rebuild/v1-foundation

Conversation

@Tanishq1030

Copy link
Copy Markdown
Member

No description provided.

Copilot AI review requested due to automatic review settings August 3, 2026 07:23
@Tanishq1030
Tanishq1030 merged commit ad66677 into main Aug 3, 2026
1 check failed
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Anchor AI Governance Check Failed

Detailed report not found. The check may have crashed. Run anchor check locally to debug.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR pivots Anchor back toward the original “drift detection” architecture, simplifying the core implementation (AST-based parsing, history anchoring, usage extraction, deterministic verdicts) while updating docs/tests and project packaging metadata to reflect an in-progress rebuild.

Changes:

  • Replaces parts of the previous v5 governance-oriented engine with a smaller drift-auditing core (parser/history/contexts/verdicts) and an argparse-based CLI entrypoint.
  • Adds extensive Django manual-audit documentation and calibration artifacts (findings, invariants/contract, philosophy, fossils JSON).
  • Updates packaging/license/docs to reflect the rebuild direction and a slimmer distribution story.

Reviewed changes

Copilot reviewed 25 out of 30 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
USAGE.md Replaces CLI reference with a usage guide and examples for audit/list + agent output.
README.md Marks the repo as an active rebuild and points to archived v5 tag.
setup.py Resets package metadata/version and changes console entrypoint to anchor.cli:main.
requirements.txt Trims dependency list (but currently diverges from runtime imports).
LICENSE Switches from Apache-2.0 text to MIT.
manifest.in Adds a lowercase manifest file (note: setuptools uses MANIFEST.in).
.gitignore Simplifies ignores and adds brain.db / reports/ ignores.
anchor/__main__.py Updates module entry to call main().
anchor/__init__.py Removes prior package metadata content (now empty).
anchor/core/parser.py Moves to Python ast visitor for symbol discovery and repo walking.
anchor/core/history.py Simplifies git-history scanning and docstring extraction using ast.
anchor/core/contexts.py Simplifies usage extraction to Python-only AST scanning.
anchor/core/models.py Removes vNext metadata fields and keeps a smaller data model for audits.
anchor/core/verdicts.py Replaces the prior large verdict engine with a simpler role/vote rule engine and agent-facing remediation text.
tests/test_simple_demo.py Adds a demo test module (currently references missing APIs).
tests/test_djnago_validation.py Adds Django validation tests against expected manual-audit verdicts (currently environment-dependent).
examples/django_fossils.json Stores extracted “intent fossils” for Django calibration symbols.
docs/test_results_analysis.md Documents the current limitation: local-repo-only usage scanning fails for framework exports.
docs/philosophy.md Adds the project philosophy and deterministic-auditing principles.
docs/internal/invariants.md Adds the “detection contract” thresholds/criteria for verdicts.
docs/django_audit_findings.md Adds the consolidated Django audit report and rationale.
docs/audits/authenticate.md Adds a manual audit write-up for authenticate().
docs/audits/login.md Adds a manual audit write-up for login().
docs/audits/form.md Adds a manual audit write-up for Form.
docs/audits/modelform.md Adds a manual audit write-up (note: content appears to describe Form).
docs/audits/manager.md Adds a manual audit write-up for Manager.
docs/audits/user.md Adds a manual audit write-up for User.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +75 to +84
@pytest.fixture(scope="session")
def django_repo():
"""Fixture providing path to Django repository."""
# Use the Django repo cloned in D:/
django_path = Path("D:/django")

if not django_path.exists():
pytest.skip("Django repository not found at D:/django")

return str(django_path)
Comment thread anchor/core/parser.py
Comment on lines +3 to +10
from typing import Iterator, Optional
from anchor.core.models import CodeSymbol

# 1. Export Query and QueryCursor
try:
from tree_sitter import Query, QueryCursor
except ImportError:
print("❌ ERROR: Could not import Query/QueryCursor from tree_sitter.")
raise
class SymbolVisitor(ast.NodeVisitor):
def __init__(self, file_path: str):
self.file_path = file_path
self.symbols: list[CodeSymbol] = []
self.current_class: Optional[str] = None
Comment thread tests/test_simple_demo.py
Comment on lines +7 to +10
import pytest
from pathlib import Path
from anchor.repo import RepositoryAnalyzer

Comment thread manifest.in
Comment on lines +1 to +3
include README.md
include USAGE.md
include LICENSE No newline at end of file
Comment thread setup.py
Comment on lines 29 to 33
packages=find_packages(),
include_package_data=True,
package_data={
"anchor": [
"core/resources/*.example",
"core/resources/*.png",
"governance/**/*.anchor",
"governance/examples/*",
"governance/mitigation.anchor",
"governance/constitution.anchor",
],
},
install_requires=[
"click",
"pyyaml",
"tree-sitter>=0.22.0",
"tree-sitter-python",
"tree-sitter-typescript",
"tree-sitter-go",
"tree-sitter-java",
"tree-sitter-rust",
"pydantic-settings>=2.0.0",
"wrapt",
"requests",
"GitPython",
"pyahocorasick",
"cryptography>=41.0.0",
"GitPython>=3.1.0",
],
Comment thread anchor/core/history.py
Comment on lines 33 to +36
try:
blob = commit.tree / git_path
file_content = blob.data_stream.read().decode('utf-8')

Comment thread anchor/core/verdicts.py
Comment on lines 8 to 18
total_usages = len(contexts)
symbol_layer = classify_architectural_layer(anchor.original_file_path or "")
file_importance = get_file_importance_multiplier(anchor.original_file_path or "")
confidence_level, requires_review = _confidence_level_from_score(anchor.confidence_score)

# -----------------------------------------------------------------------
# Governance Drift — checked first, highest priority
# -----------------------------------------------------------------------
if anchor.original_file_path:
has_gov_drift, detected_caps, missing_ctrl, cap_class = check_governance_drift(
anchor.original_file_path, repo_path
)
if has_gov_drift:
verdict = VerdictType.GOVERNANCE_DRIFT
rationale = (
f"High-risk capabilities detected ({', '.join(detected_caps)}) "
f"in {anchor.original_file_path!r} with missing governance controls: "
f"{', '.join(missing_ctrl)}. Capability class: {cap_class}."
)
remediation = _build_remediation(
verdict, symbol_name, anchor, [],
missing_controls=missing_ctrl,
detected_capabilities=detected_caps,
capability_class=cap_class,
)
priority = _compute_priority_score(verdict, symbol_layer,
anchor.original_file_path)
return AuditResult(
symbol=symbol_name, anchor=anchor, observed_roles=[],
verdict=verdict, rationale=rationale,
evidence=[f"Capability: {c} ({cap_class})" for c in detected_caps],
remediation=remediation,
priority_score=priority,
confidence_level=confidence_level,
requires_human_review=requires_review,
detected_capabilities=detected_caps,
missing_controls=missing_ctrl,
)

# -----------------------------------------------------------------------
# Guard: not enough usage data
# -----------------------------------------------------------------------

if total_usages == 0:
priority = _compute_priority_score(VerdictType.CONFIDENCE_TOO_LOW,
symbol_layer, anchor.original_file_path or "")
return AuditResult(
symbol=symbol_name, anchor=anchor, observed_roles=[],
verdict=VerdictType.CONFIDENCE_TOO_LOW,
rationale="No call sites found in the local repository. "
"Cannot issue a verdict without usage context.",
evidence=[], remediation=None,
priority_score=priority,
confidence_level=confidence_level,
requires_human_review=True,
)

if anchor.intent_description in ("", "No docstring found in early history."):
priority = _compute_priority_score(VerdictType.CONFIDENCE_TOO_LOW,
symbol_layer, anchor.original_file_path or "")
return AuditResult(
symbol=symbol_name, anchor=anchor, observed_roles=[],
symbol=symbol_name,
anchor=anchor,
observed_roles=[],
verdict=VerdictType.CONFIDENCE_TOO_LOW,
rationale="Symbol has no documented intent in early git history. "
"Cannot determine whether current usage is aligned.",
evidence=[], remediation=None,
priority_score=priority,
confidence_level=confidence_level,
requires_human_review=True,
rationale="No usages found in codebase.",
evidence=[]
)
Comment thread anchor/core/verdicts.py
Comment on lines +35 to +50
module_counts: Dict[str, int] = {}
for ctx in contexts:
parts = ctx.file_path.replace("\\", "/").split("/")
if len(parts) > 2:
# Heuristic: sdks/python -> sdks.python
domain = f"{parts[0]}.{parts[1]}"
else:
domain = "root"
module_counts[domain] = module_counts.get(domain, 0) + 1

for domain, count in module_counts.items():
ratio = count / total_usages
# Heuristic: Compatible if it lives in the same root module
is_compatible = True # Simplified for generic case
roles.append(SemanticRole(f"Caller: {domain}", "Module-based usage", count, ratio, is_compatible))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants