feat: export core Hermes skills

This commit is contained in:
2026-07-15 02:45:56 +00:00
parent a028b63eda
commit 54711fee2a
308 changed files with 41310 additions and 1 deletions
@@ -0,0 +1,88 @@
#!/usr/bin/env python3
"""Audit 待审查 and 任务交付 directories against tracker.
Usage:
python3 ~/.hermes/skills/legal/contract-pass-workflow/references/cleanup-audit.py
Prints a matrix showing which files are:
- In tracker (and their status/age/cleaned flag)
- NOT in tracker (orphans that will never be auto-cleaned)
- Should be cleaned (>24h + completed + cleaned=false)
Does NOT delete anything. Pure diagnostic.
"""
import json, os, subprocess
from datetime import datetime, timezone, timedelta
BJT = timezone(timedelta(hours=8))
now = datetime.now(BJT)
TRACKER = os.path.expanduser('~/.hermes/data/contract-tracker.json')
BASE = os.path.expanduser('~/nextcloud/data/data/doro/files/Doro合同审查任务')
待审查 = os.path.join(BASE, '待审查')
任务交付 = os.path.join(BASE, '任务交付')
def nc_ls(path):
"""List files in a Nextcloud-managed directory (needs sudo)."""
r = subprocess.run(['sudo', 'ls', path], capture_output=True, text=True)
return [f for f in r.stdout.strip().split('\n') if f] if r.stdout.strip() else []
def file_age_hours(path):
"""Get file age in hours from mtime."""
r = subprocess.run(['sudo', 'stat', '-c', '%Y', path], capture_output=True, text=True)
if r.stdout.strip():
mtime = int(r.stdout.strip())
return (now - datetime.fromtimestamp(mtime, tz=BJT)).total_seconds() / 3600
return -1
def main():
with open(TRACKER) as f:
tracker = json.load(f)
# Build lookup: filename -> list of tracker records
lookup = {}
for c in tracker['contracts']:
for key in ['delivered_filename', 'original_filename', 'converted_filename']:
fn = c.get(key, '')
if fn:
lookup.setdefault(fn, []).append(c)
orphans = []
for label, directory in [('待审查', 待审查), ('任务交付', 任务交付)]:
print(f"\n{'='*70}")
print(f" {label} ({directory})")
print(f"{'='*70}")
files = nc_ls(directory)
if not files:
print(" (empty)")
continue
for fn in sorted(files):
records = lookup.get(fn, [])
age = file_age_hours(os.path.join(directory, fn))
is_companion = any(k in fn for k in ['审查意见', '合同流程单'])
if records:
for r in records:
ts = r.get('xlsx_updated_at', '')
h = (now - datetime.fromisoformat(ts)).total_seconds() / 3600 if ts else -1
should = r['status'] == 'completed' and h > 24
flag = '🔴 SHOULD_CLEAN' if should else '⏳ waiting'
print(f" {fn}")
print(f" seq={r['seq']} | {h:.0f}h | cleaned={r.get('cleaned')} | {flag}")
else:
tag = '📋 COMPANION_ORPHAN' if is_companion else '⚠️ NOT_IN_TRACKER'
print(f" {fn}")
print(f" {tag} | age={age:.0f}h")
orphans.append((label, fn, age))
if orphans:
print(f"\n{'='*70}")
print(f" ORPHANS SUMMARY: {len(orphans)} files not tracked")
print(f"{'='*70}")
for label, fn, age in orphans:
print(f" [{label}] {fn} ({age:.0f}h old)")
if __name__ == '__main__':
main()