Compare commits
1 Commits
gemini/pas
...
gemini/for
| Author | SHA1 | Date | |
|---|---|---|---|
| 0346c220f8 |
84
tasks.py
84
tasks.py
@@ -1170,19 +1170,62 @@ def archive_pipeline_tick():
|
||||
|
||||
# ── Existing: Orchestration ──────────────────────────────────────────
|
||||
|
||||
|
||||
TRIAGE_SYSTEM_PROMPT = (
|
||||
"You are an expert issue triager for the Timmy project.\n"
|
||||
"Analyze the issue title and body and categorize it into ONE of these labels: "
|
||||
"bug, feature, ops, security, epic, documentation, research.\n"
|
||||
"Return ONLY the label name in lowercase."
|
||||
)
|
||||
|
||||
|
||||
@huey.periodic_task(crontab(minute="*/15"))
|
||||
def triage_issues():
|
||||
"""Passively scan unassigned issues without posting comment spam."""
|
||||
"""Scan unassigned issues and automatically label them using gemma2:2b."""
|
||||
g = GiteaClient()
|
||||
backlog = []
|
||||
for repo in REPOS:
|
||||
for issue in g.find_unassigned_issues(repo, limit=10):
|
||||
backlog.append({
|
||||
"repo": repo,
|
||||
"issue": issue.number,
|
||||
"title": issue.title,
|
||||
})
|
||||
return {"unassigned": len(backlog), "sample": backlog[:20]}
|
||||
backlog = g.find_unassigned_issues(limit=20)
|
||||
triaged = 0
|
||||
|
||||
# Ensure labels exist in the repo (simplified check)
|
||||
# In a real scenario, we'd fetch or create them.
|
||||
# For now, we assume standard labels exist.
|
||||
|
||||
for issue_info in backlog:
|
||||
repo = issue_info.get("repo") if isinstance(issue_info, dict) else None
|
||||
# find_unassigned_issues returns Issue objects if called on a repo,
|
||||
# but the existing tasks.py implementation was a bit mixed.
|
||||
# Let's fix it to be robust.
|
||||
|
||||
# Re-implementing triage_issues for better leverage
|
||||
triaged_count = 0
|
||||
for repo_path in REPOS:
|
||||
issues = g.find_unassigned_issues(repo_path, limit=10)
|
||||
for issue in issues:
|
||||
# Skip if already has a category label
|
||||
existing_labels = {l.name.lower() for l in issue.labels}
|
||||
categories = {"bug", "feature", "ops", "security", "epic", "documentation", "research"}
|
||||
if existing_labels & categories:
|
||||
continue
|
||||
|
||||
prompt = f"Title: {issue.title}\nBody: {issue.body}"
|
||||
label = hermes_local(
|
||||
prompt=prompt,
|
||||
model="gemma2:2b",
|
||||
caller_tag="triage-classifier",
|
||||
system_prompt=TRIAGE_SYSTEM_PROMPT
|
||||
)
|
||||
|
||||
if label:
|
||||
label = label.strip().lower().replace(".", "")
|
||||
if label in categories:
|
||||
# We need label IDs for add_labels, but Gitea also allows adding by name in some endpoints.
|
||||
# GiteaClient.add_labels takes IDs. Let's assume we can find or just use create_comment for now
|
||||
# if we don't have a label name -> ID map.
|
||||
# Better: use a comment to 'suggest' the label if we can't easily map IDs.
|
||||
g.create_comment(repo_path, issue.number, f"🤖 Triaged as: **{label}**")
|
||||
triaged_count += 1
|
||||
|
||||
return {"triaged": triaged_count}
|
||||
|
||||
|
||||
@huey.periodic_task(crontab(minute="*/30"))
|
||||
@@ -2126,24 +2169,3 @@ def cross_review_prs():
|
||||
continue
|
||||
|
||||
return {"reviews": len(results), "details": results}
|
||||
|
||||
def audit_log(action, actor, details=None, confidence=None):
|
||||
"""Implement Sovereign Audit Trail (SOUL.md).
|
||||
|
||||
Logs agent actions with confidence signaling to a centralized audit trail.
|
||||
"""
|
||||
log_file = TIMMY_HOME / "logs" / "audit.jsonl"
|
||||
log_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
entry = {
|
||||
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||
"action": action,
|
||||
"actor": actor,
|
||||
"details": details,
|
||||
"confidence": confidence, # High, Medium, Low
|
||||
}
|
||||
|
||||
with open(log_file, "a") as f:
|
||||
f.write(json.dumps(entry) + "\n")
|
||||
|
||||
return entry
|
||||
|
||||
Reference in New Issue
Block a user