diff options
| -rwxr-xr-x | scripts/newos4-feedback-collect.py | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/scripts/newos4-feedback-collect.py b/scripts/newos4-feedback-collect.py index 66f1653..e73238c 100755 --- a/scripts/newos4-feedback-collect.py +++ b/scripts/newos4-feedback-collect.py @@ -15,6 +15,7 @@ PLANS = os.path.join(ROOT, '.hermes/plans') TRIAGE = os.path.join(ROOT, 'admin/docs/newos4-triage-latest.json') STEER = os.path.join(ROOT, 'spaces/newos4/data/maintenance/steering.json') DECISIONS = os.path.join(ROOT, 'spaces/newos4/data/feedback/decisions.jsonl') +APPLIED = os.path.join(ROOT, 'spaces/newos4/data/feedback/applied.json') # ledger written by the applier def load(path, default): @@ -61,11 +62,22 @@ def plans_needing_decision(dec): continue name = os.path.basename(p) title = next((l.lstrip('# ').strip() for l in head.splitlines() if l.startswith('# ')), name) + try: + body = open(p, encoding='utf-8', errors='ignore').read() + except Exception: + body = '' + lines = body.splitlines() + # A decision turns on the plan's own text: the opening 60 lines carry Goal/Approach and the + # task headings show the shape of the work. The full file is 20-40 KB per plan — too much. + excerpt = '\n'.join(lines[:60])[:2400] + tasks = [l.lstrip('#').strip() for l in lines if re.match(r'^#{2,3}\s+Task\b', l)][:20] + status = [l.strip() for l in lines if l.startswith('## Status') or l.startswith('## Implementation')][:2] d = dec.get('plan:' + name, {}) items.append({ 'id': 'plan:' + name, 'kind': 'plan', 'title': title, 'path': p, 'size': os.path.getsize(p), 'mtime': datetime.fromtimestamp( os.path.getmtime(p), timezone.utc).isoformat(timespec='seconds'), + 'excerpt': excerpt, 'tasks': tasks, 'status': status, 'decision': d.get('decision'), 'decided_at': d.get('decided_at') or d.get('ts'), 'note': d.get('note', ''), }) @@ -82,12 +94,17 @@ def reports_needing_decision(dec): except Exception: continue rid = r.get('id') or os.path.basename(p)[:-5] + diag = r.get('diagnostics') or {} + errs = diag.get('errors') or [] d = dec.get('report:' + rid, {}) items.append({ 'id': 'report:' + rid, 'kind': 'report', 'title': (r.get('title') or rid)[:180], - 'created_at': r.get('created_at'), 'auto': bool((r.get('diagnostics') or {}).get('auto')), + 'created_at': r.get('created_at'), 'auto': bool(diag.get('auto')), 'new': rid in new_ids, 'decision': d.get('decision'), 'decided_at': d.get('decided_at') or d.get('ts'), 'note': d.get('note', ''), + 'message': (r.get('body') or '')[:1500], 'page': diag.get('url') or '', + 'version': diag.get('version') or '', 'ua': (diag.get('ua') or '')[:120], + 'errors': [str(e)[:300] for e in errs[:3]], }) items.sort(key=lambda x: (x.get('created_at') or ''), reverse=True) return items |