Compare commits

..

3 Commits

Author SHA1 Message Date
2a4e73aa03 Merge pull request 'fix: session_pair_harvester uses role/content format (#91)' (#240) from step35/91-feat-session-transcript-trai into main
Some checks failed
Test / pytest (push) Failing after 31s
2026-05-04 00:23:19 +00:00
Rockachopa
4b5a675355 feat: add PR complexity scorer — estimate review effort\n\nImplements issue #135: a script that analyzes open PRs and computes\na complexity score (1-10) based on files changed, lines added/removed,\ndependency changes, and test coverage delta. Also estimates review time.\n\nThe scorer can be run with --dry-run to preview or --apply to post\nscore comments directly on PRs.\n\nOutput: metrics/pr_complexity.json with full analysis.\n\nCloses #135
Some checks failed
Test / pytest (push) Failing after 10s
2026-04-26 09:34:57 -04:00
Alex Payne
b1a728f5f4 feat: fix session_pair_harvester to use role/content format (#91)
Some checks failed
Test / pytest (pull_request) Failing after 8s
- Harvester used old message fields (from/value) but Hermes sessions use role/content
- Import session_reader to normalize conversations properly
- Update extract function to operate on normalized role/content messages
- Change predecessor lookup from "human"/"gpt" to "user"/"assistant"
- Add comprehensive smoke tests (8 tests, all pass)
- Verify extraction from test_sessions: 11 pairs, avg ratio 8.13
2026-04-26 00:19:56 -04:00
8 changed files with 926 additions and 1838 deletions

View File

@@ -1,540 +0,0 @@
---
domain: global
category: pattern
version: 1
last_updated: '2026-04-26T11:22:05.449323+00:00'
facts:
- id: cross-repo:connection:001
fact: "hermes-agent references compounding-intelligence via issue #229: [ATLAS]\
\ Steal the highest-leverage ecosystem patterns into the sovereign stack \u2192\
\ [compounding-intelligence#229] [ATLAS][Telemetry] Build local token and cost\
\ ingestion using Tokscale core patterns"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:21:56.905616+00:00'
last_confirmed: '2026-04-26T11:21:56.905641+00:00'
related: []
- id: cross-repo:connection:002
fact: "hermes-agent references compounding-intelligence via issue #231: [ATLAS]\
\ Steal the highest-leverage ecosystem patterns into the sovereign stack \u2192\
\ [compounding-intelligence#231] [ATLAS][Wiki] Build the LLM Wiki layer: ingest,\
\ query, lint, and session crystallization into durabl"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:21:57.230615+00:00'
last_confirmed: '2026-04-26T11:21:57.230632+00:00'
related: []
- id: cross-repo:connection:003
fact: "hermes-agent references compounding-intelligence via issue #232: [ATLAS]\
\ Steal the highest-leverage ecosystem patterns into the sovereign stack \u2192\
\ [compounding-intelligence#232] [ATLAS][Research] Solve the swarm-memory gap\
\ for concurrent subagents"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:21:57.415552+00:00'
last_confirmed: '2026-04-26T11:21:57.415580+00:00'
related: []
- id: cross-repo:connection:004
fact: "hermes-agent references fleet-ops via issue #410: [ATLAS] Steal the highest-leverage\
\ ecosystem patterns into the sovereign stack \u2192 [fleet-ops#410] [ATLAS][Safety]\
\ Deploy a virtual-credential and DLP sidecar for sovereign agent runs"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:21:57.716479+00:00'
last_confirmed: '2026-04-26T11:21:57.716488+00:00'
related: []
- id: cross-repo:connection:005
fact: "hermes-agent references the-nexus via issue #893: [CONSOLIDATED] Fleet SITREP\
\ \u2014 Allegro 7-Task Execution + Ezra Deliverables \u2192 [the-nexus#893] [AUDIT]\
\ System Formalization \u2014 OSS Replacements & Cleanup Candidates"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:21:57.961498+00:00'
last_confirmed: '2026-04-26T11:21:57.961510+00:00'
related: []
- id: cross-repo:connection:006
fact: "hermes-agent references the-nexus via issue #1695: [ATLAS] Steal the highest-leverage\
\ ecosystem patterns into the sovereign stack \u2192 [the-nexus#1695] [ATLAS][Cockpit]\
\ Build the operator inspector rail and session shell patterns worth stealing"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:21:58.130733+00:00'
last_confirmed: '2026-04-26T11:21:58.130745+00:00'
related: []
- id: cross-repo:connection:007
fact: "hermes-agent references timmy-config via issue #875: [ATLAS] Steal the highest-leverage\
\ ecosystem patterns into the sovereign stack \u2192 [timmy-config#875] [ATLAS][Skills]\
\ Import Karpathy-style cognitive principles and GStack-style role commands as\
\ native "
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:21:58.327960+00:00'
last_confirmed: '2026-04-26T11:21:58.327972+00:00'
related: []
- id: cross-repo:connection:008
fact: "hermes-agent references timmy-dispatch via issue #18: [ATLAS] Steal the highest-leverage\
\ ecosystem patterns into the sovereign stack \u2192 [timmy-dispatch#18] [ATLAS][Dispatch]\
\ Add Mission Control-style dispatch ledger, capacity model, and heartbeat tracking"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:21:58.502966+00:00'
last_confirmed: '2026-04-26T11:21:58.502981+00:00'
related: []
- id: cross-repo:connection:009
fact: "hermes-agent references timmy-home via issue #568: [DISPATCH] Ezra \u2014\
\ Investigate & Install MemPalace on Hermes VPS \u2192 [timmy-home#568] [EVALUATION]\
\ MemPalace v3.0.0 Integration \u2014 Before/After Metrics + Recommendation"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:21:58.967894+00:00'
last_confirmed: '2026-04-26T11:21:58.967906+00:00'
related: []
- id: cross-repo:connection:010
fact: "the-nexus references hermes-agent via issue #984: [ATLAS][Cockpit] Build\
\ the operator inspector rail and session shell patterns worth stealing \u2192\
\ [hermes-agent#984] [ATLAS] Steal the highest-leverage ecosystem patterns into\
\ the sovereign stack"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:21:59.445454+00:00'
last_confirmed: '2026-04-26T11:21:59.445470+00:00'
related: []
- id: cross-repo:connection:011
fact: "timmy-config references the-nexus via issue #501: \u2600\uFE0F Good Morning\
\ Report \u2014 2026-03-26 (Thursday) \u2192 [the-nexus#501] [claude] Re-implement\
\ gravity anomaly zones (#478)"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:21:59.975253+00:00'
last_confirmed: '2026-04-26T11:21:59.975291+00:00'
related: []
- id: cross-repo:connection:012
fact: "timmy-config references the-nexus via issue #502: \u2600\uFE0F Good Morning\
\ Report \u2014 2026-03-26 (Thursday) \u2192 [the-nexus#502] [claude] Time-lapse\
\ replay mode (#484)"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:00.193542+00:00'
last_confirmed: '2026-04-26T11:22:00.193552+00:00'
related: []
- id: cross-repo:connection:013
fact: "timmy-config references the-nexus via issue #503: \u2600\uFE0F Good Morning\
\ Report \u2014 2026-03-26 (Thursday) \u2192 [the-nexus#503] [claude] InstancedMesh\
\ optimizations for repeated geometry (#482)"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:00.515208+00:00'
last_confirmed: '2026-04-26T11:22:00.515229+00:00'
related: []
- id: cross-repo:connection:014
fact: "timmy-config references the-nexus via issue #552: \u2600\uFE0F Good Morning\
\ Report \u2014 2026-03-26 (Thursday) \u2192 [the-nexus#552] [HEARTBEAT] Apprentice\
\ protocol \u2014 episodic memory logging of desktop activity"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:00.658814+00:00'
last_confirmed: '2026-04-26T11:22:00.658829+00:00'
related: []
- id: cross-repo:connection:015
fact: "timmy-config references the-nexus via issue #554: \u2600\uFE0F Good Morning\
\ Report \u2014 2026-03-26 (Thursday) \u2192 [the-nexus#554] [ECONOMY] Stand up\
\ Cashu Mint on Lightning"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:01.089278+00:00'
last_confirmed: '2026-04-26T11:22:01.089287+00:00'
related: []
- id: cross-repo:connection:016
fact: "timmy-config references the-nexus via issue #555: \u2600\uFE0F Good Morning\
\ Report \u2014 2026-03-26 (Thursday) \u2192 [the-nexus#555] [ECONOMY] Prototype\
\ Bannerlord Denar \u2192 Cashu token Harmony patch"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:01.297062+00:00'
last_confirmed: '2026-04-26T11:22:01.297069+00:00'
related: []
- id: cross-repo:connection:017
fact: "timmy-config references the-nexus via issue #613: \u2600\uFE0F Good Morning\
\ Report \u2014 2026-03-28 (Saturday) \u2192 [the-nexus#613] [gemini] [HARNESS]\
\ Shadow Context Manager \u2014 auto-generated brain dump for session continuity\
\ (#608)"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:01.814895+00:00'
last_confirmed: '2026-04-26T11:22:01.814905+00:00'
related: []
- id: cross-repo:connection:018
fact: "timmy-config references the-nexus via issue #673: \u2600\uFE0F Good Morning\
\ Report \u2014 2026-03-28 (Saturday) \u2192 [the-nexus#673] [PORTAL] Deterministic\
\ Morrowind pilot loop with world-state proof"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:02.118691+00:00'
last_confirmed: '2026-04-26T11:22:02.118711+00:00'
related: []
- id: cross-repo:connection:019
fact: "timmy-config references the-nexus via issue #674: \u2600\uFE0F Good Morning\
\ Report \u2014 2026-03-28 (Saturday) \u2192 [the-nexus#674] [PORTAL] Reflex tactical\
\ layer and semantic trajectory logging"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:02.261655+00:00'
last_confirmed: '2026-04-26T11:22:02.261669+00:00'
related: []
- id: cross-repo:connection:020
fact: "timmy-config references the-nexus via issue #675: \u2600\uFE0F Good Morning\
\ Report \u2014 2026-03-28 (Saturday) \u2192 [the-nexus#675] [HARNESS] Deterministic\
\ context compaction for long local sessions"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:02.403879+00:00'
last_confirmed: '2026-04-26T11:22:02.403922+00:00'
related: []
- id: cross-repo:connection:021
fact: "timmy-config references the-nexus via issue #676: \u2600\uFE0F Good Morning\
\ Report \u2014 2026-03-28 (Saturday) \u2192 [the-nexus#676] [gemini] [PORTAL]\
\ Reflex tactical layer and semantic trajectory logging (#674)"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:02.545921+00:00'
last_confirmed: '2026-04-26T11:22:02.545931+00:00'
related: []
- id: cross-repo:connection:022
fact: "timmy-config references the-nexus via issue #677: \u2600\uFE0F Good Morning\
\ Report \u2014 2026-03-28 (Saturday) \u2192 [the-nexus#677] [gemini] [HARNESS]\
\ Deterministic context compaction for long local sessions (#675)"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:02.691982+00:00'
last_confirmed: '2026-04-26T11:22:02.691988+00:00'
related: []
- id: cross-repo:connection:023
fact: "timmy-config references the-nexus via issue #730: \u2600\uFE0F Good Morning\
\ Report \u2014 2026-03-29 (Sunday) \u2192 [the-nexus#730] [VISUAL] Give Workshop,\
\ Archive, Chapel, Courtyard, and Gate distinct Nexus visual identities"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:03.030374+00:00'
last_confirmed: '2026-04-26T11:22:03.030404+00:00'
related: []
- id: cross-repo:connection:024
fact: "timmy-config references the-nexus via issue #731: \u2600\uFE0F Good Morning\
\ Report \u2014 2026-03-29 (Sunday) \u2192 [the-nexus#731] [VALIDATION] Browser\
\ smoke + visual proof for the Evennia-fed Nexus shell"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:03.245877+00:00'
last_confirmed: '2026-04-26T11:22:03.245885+00:00'
related: []
- id: cross-repo:connection:025
fact: "timmy-config references the-nexus via issue #736: \u2600\uFE0F Good Morning\
\ Report \u2014 2026-03-29 (Sunday) \u2192 [the-nexus#736] Perplexity review"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:03.471514+00:00'
last_confirmed: '2026-04-26T11:22:03.471536+00:00'
related: []
- id: cross-repo:connection:026
fact: "timmy-config references the-nexus via issue #785: \u2600\uFE0F Good Morning\
\ Report \u2014 2026-03-30 (Monday) \u2192 [the-nexus#785] Implement SharedArrayBuffer\
\ for Zero-Copy Data Sharing"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:03.598910+00:00'
last_confirmed: '2026-04-26T11:22:03.598925+00:00'
related: []
- id: cross-repo:connection:027
fact: "timmy-config references the-nexus via issue #786: \u2600\uFE0F Good Morning\
\ Report \u2014 2026-03-30 (Monday) \u2192 [the-nexus#786] Implement GPU-Accelerated\
\ Knowledge Graph Queries"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:03.762768+00:00'
last_confirmed: '2026-04-26T11:22:03.762779+00:00'
related: []
- id: cross-repo:connection:028
fact: "timmy-config references the-nexus via issue #787: \u2600\uFE0F Good Morning\
\ Report \u2014 2026-03-30 (Monday) \u2192 [the-nexus#787] Implement Hierarchical\
\ L1/L2 Cache for Meta-Reasoning"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:03.917083+00:00'
last_confirmed: '2026-04-26T11:22:03.917092+00:00'
related: []
- id: cross-repo:connection:029
fact: "timmy-home references hermes-agent via issue #72: \U0001F525 Burn Report\
\ #5 \u2014 2026-04-01 \u2014 Crisis Safety Test Infrastructure \u2192 [hermes-agent#72]\
\ [RED TEAM] Full Jailbreak Audit - Claude Opus 4.6 - 2026-03-30"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:04.071933+00:00'
last_confirmed: '2026-04-26T11:22:04.071949+00:00'
related: []
- id: cross-repo:connection:030
fact: "timmy-home references hermes-agent via issue #74: [BURN REPORT] SHIELD Security\
\ Implementation - Issues #72/#74/#75 \u2192 [hermes-agent#74] [RED TEAM] ULTRAPLINIAN\
\ Crisis Stress Test \u2014 22 CRITICAL Failures \u2014 2026-03-31"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:04.214487+00:00'
last_confirmed: '2026-04-26T11:22:04.214499+00:00'
related: []
- id: cross-repo:connection:031
fact: "timmy-home references hermes-agent via issue #75: [BURN REPORT] SHIELD Security\
\ Implementation - Issues #72/#74/#75 \u2192 [hermes-agent#75] [SHIELD] Jailbreak\
\ Input Detection Module \u2014 Built Overnight From Red Team Findings"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:04.369176+00:00'
last_confirmed: '2026-04-26T11:22:04.369184+00:00'
related: []
- id: cross-repo:connection:032
fact: "timmy-home references hermes-agent via issue #79: \U0001F525 Burn Report\
\ #5 \u2014 2026-04-01 \u2014 Crisis Safety Test Infrastructure \u2192 [hermes-agent#79]\
\ [SECURITY] [CRITICAL] Test og_godmode template against crisis/suicide safety\
\ queries"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:04.884029+00:00'
last_confirmed: '2026-04-26T11:22:04.884062+00:00'
related: []
- id: cross-repo:connection:033
fact: "timmy-home references hermes-agent via issue #80: \U0001F525 Burn Report\
\ #5 \u2014 2026-04-01 \u2014 Crisis Safety Test Infrastructure \u2192 [hermes-agent#80]\
\ [SECURITY] [HIGH] Implement input sanitization for GODMODE jailbreak patterns"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:05.116347+00:00'
last_confirmed: '2026-04-26T11:22:05.116357+00:00'
related: []
- id: cross-repo:connection:034
fact: "timmy-home references hermes-agent via issue #81: \U0001F525 Burn Report\
\ #5 \u2014 2026-04-01 \u2014 Crisis Safety Test Infrastructure \u2192 [hermes-agent#81]\
\ [SECURITY] [MEDIUM] ULTRAPLINIAN follow-up: Red team fallback chain (Kimi, Gemini,\
\ Grok, Llama)"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:05.279272+00:00'
last_confirmed: '2026-04-26T11:22:05.279284+00:00'
related: []
- id: cross-repo:connection:035
fact: "timmy-home references the-nexus via issue #859: [AGENDA] Next burn night\
\ \u2014 amplify bounded quick wins, proof-first comments, and overnight leverage\
\ \u2192 [the-nexus#859] [AUTOGENESIS][Phase I] Hermes v2.0 architecture spec\
\ + successor fork spec"
category: pattern
domain: global
confidence: 0.9
tags:
- cross-repo
- issue-reference
- connection
source_count: 1
first_seen: '2026-04-26T11:22:05.448200+00:00'
last_confirmed: '2026-04-26T11:22:05.448207+00:00'
related: []

File diff suppressed because it is too large Load Diff

View File

@@ -1,57 +0,0 @@
# Cross-Repo Connection Report
Generated: 2026-04-26T11:22:05.466516+00:00
Org: Timmy_Foundation
Repos scanned: 21
## Connections
### hermes-agent
- hermes-agent references compounding-intelligence via issue #229: [ATLAS] Steal the highest-leverage ecosystem patterns into the sovereign stack → [compounding-intelligence#229] [ATLAS][Telemetry] Build local token and cost ingestion using Tokscale core patterns
- hermes-agent references compounding-intelligence via issue #231: [ATLAS] Steal the highest-leverage ecosystem patterns into the sovereign stack → [compounding-intelligence#231] [ATLAS][Wiki] Build the LLM Wiki layer: ingest, query, lint, and session crystallization into durabl
- hermes-agent references compounding-intelligence via issue #232: [ATLAS] Steal the highest-leverage ecosystem patterns into the sovereign stack → [compounding-intelligence#232] [ATLAS][Research] Solve the swarm-memory gap for concurrent subagents
- hermes-agent references fleet-ops via issue #410: [ATLAS] Steal the highest-leverage ecosystem patterns into the sovereign stack → [fleet-ops#410] [ATLAS][Safety] Deploy a virtual-credential and DLP sidecar for sovereign agent runs
- hermes-agent references the-nexus via issue #893: [CONSOLIDATED] Fleet SITREP — Allegro 7-Task Execution + Ezra Deliverables → [the-nexus#893] [AUDIT] System Formalization — OSS Replacements & Cleanup Candidates
- hermes-agent references the-nexus via issue #1695: [ATLAS] Steal the highest-leverage ecosystem patterns into the sovereign stack → [the-nexus#1695] [ATLAS][Cockpit] Build the operator inspector rail and session shell patterns worth stealing
- hermes-agent references timmy-config via issue #875: [ATLAS] Steal the highest-leverage ecosystem patterns into the sovereign stack → [timmy-config#875] [ATLAS][Skills] Import Karpathy-style cognitive principles and GStack-style role commands as native
- hermes-agent references timmy-dispatch via issue #18: [ATLAS] Steal the highest-leverage ecosystem patterns into the sovereign stack → [timmy-dispatch#18] [ATLAS][Dispatch] Add Mission Control-style dispatch ledger, capacity model, and heartbeat tracking
- hermes-agent references timmy-home via issue #568: [DISPATCH] Ezra — Investigate & Install MemPalace on Hermes VPS → [timmy-home#568] [EVALUATION] MemPalace v3.0.0 Integration — Before/After Metrics + Recommendation
### the-nexus
- the-nexus references hermes-agent via issue #984: [ATLAS][Cockpit] Build the operator inspector rail and session shell patterns worth stealing → [hermes-agent#984] [ATLAS] Steal the highest-leverage ecosystem patterns into the sovereign stack
### timmy-config
- timmy-config references the-nexus via issue #501: ☀️ Good Morning Report — 2026-03-26 (Thursday) → [the-nexus#501] [claude] Re-implement gravity anomaly zones (#478)
- timmy-config references the-nexus via issue #502: ☀️ Good Morning Report — 2026-03-26 (Thursday) → [the-nexus#502] [claude] Time-lapse replay mode (#484)
- timmy-config references the-nexus via issue #503: ☀️ Good Morning Report — 2026-03-26 (Thursday) → [the-nexus#503] [claude] InstancedMesh optimizations for repeated geometry (#482)
- timmy-config references the-nexus via issue #552: ☀️ Good Morning Report — 2026-03-26 (Thursday) → [the-nexus#552] [HEARTBEAT] Apprentice protocol — episodic memory logging of desktop activity
- timmy-config references the-nexus via issue #554: ☀️ Good Morning Report — 2026-03-26 (Thursday) → [the-nexus#554] [ECONOMY] Stand up Cashu Mint on Lightning
- timmy-config references the-nexus via issue #555: ☀️ Good Morning Report — 2026-03-26 (Thursday) → [the-nexus#555] [ECONOMY] Prototype Bannerlord Denar → Cashu token Harmony patch
- timmy-config references the-nexus via issue #613: ☀️ Good Morning Report — 2026-03-28 (Saturday) → [the-nexus#613] [gemini] [HARNESS] Shadow Context Manager — auto-generated brain dump for session continuity (#608)
- timmy-config references the-nexus via issue #673: ☀️ Good Morning Report — 2026-03-28 (Saturday) → [the-nexus#673] [PORTAL] Deterministic Morrowind pilot loop with world-state proof
- timmy-config references the-nexus via issue #674: ☀️ Good Morning Report — 2026-03-28 (Saturday) → [the-nexus#674] [PORTAL] Reflex tactical layer and semantic trajectory logging
- timmy-config references the-nexus via issue #675: ☀️ Good Morning Report — 2026-03-28 (Saturday) → [the-nexus#675] [HARNESS] Deterministic context compaction for long local sessions
- timmy-config references the-nexus via issue #676: ☀️ Good Morning Report — 2026-03-28 (Saturday) → [the-nexus#676] [gemini] [PORTAL] Reflex tactical layer and semantic trajectory logging (#674)
- timmy-config references the-nexus via issue #677: ☀️ Good Morning Report — 2026-03-28 (Saturday) → [the-nexus#677] [gemini] [HARNESS] Deterministic context compaction for long local sessions (#675)
- timmy-config references the-nexus via issue #730: ☀️ Good Morning Report — 2026-03-29 (Sunday) → [the-nexus#730] [VISUAL] Give Workshop, Archive, Chapel, Courtyard, and Gate distinct Nexus visual identities
- timmy-config references the-nexus via issue #731: ☀️ Good Morning Report — 2026-03-29 (Sunday) → [the-nexus#731] [VALIDATION] Browser smoke + visual proof for the Evennia-fed Nexus shell
- timmy-config references the-nexus via issue #736: ☀️ Good Morning Report — 2026-03-29 (Sunday) → [the-nexus#736] Perplexity review
- timmy-config references the-nexus via issue #785: ☀️ Good Morning Report — 2026-03-30 (Monday) → [the-nexus#785] Implement SharedArrayBuffer for Zero-Copy Data Sharing
- timmy-config references the-nexus via issue #786: ☀️ Good Morning Report — 2026-03-30 (Monday) → [the-nexus#786] Implement GPU-Accelerated Knowledge Graph Queries
- timmy-config references the-nexus via issue #787: ☀️ Good Morning Report — 2026-03-30 (Monday) → [the-nexus#787] Implement Hierarchical L1/L2 Cache for Meta-Reasoning
### timmy-home
- timmy-home references hermes-agent via issue #72: 🔥 Burn Report #5 — 2026-04-01 — Crisis Safety Test Infrastructure → [hermes-agent#72] [RED TEAM] Full Jailbreak Audit - Claude Opus 4.6 - 2026-03-30
- timmy-home references hermes-agent via issue #74: [BURN REPORT] SHIELD Security Implementation - Issues #72/#74/#75 → [hermes-agent#74] [RED TEAM] ULTRAPLINIAN Crisis Stress Test — 22 CRITICAL Failures — 2026-03-31
- timmy-home references hermes-agent via issue #75: [BURN REPORT] SHIELD Security Implementation - Issues #72/#74/#75 → [hermes-agent#75] [SHIELD] Jailbreak Input Detection Module — Built Overnight From Red Team Findings
- timmy-home references hermes-agent via issue #79: 🔥 Burn Report #5 — 2026-04-01 — Crisis Safety Test Infrastructure → [hermes-agent#79] [SECURITY] [CRITICAL] Test og_godmode template against crisis/suicide safety queries
- timmy-home references hermes-agent via issue #80: 🔥 Burn Report #5 — 2026-04-01 — Crisis Safety Test Infrastructure → [hermes-agent#80] [SECURITY] [HIGH] Implement input sanitization for GODMODE jailbreak patterns
- timmy-home references hermes-agent via issue #81: 🔥 Burn Report #5 — 2026-04-01 — Crisis Safety Test Infrastructure → [hermes-agent#81] [SECURITY] [MEDIUM] ULTRAPLINIAN follow-up: Red team fallback chain (Kimi, Gemini, Grok, Llama)
- timmy-home references the-nexus via issue #859: [AGENDA] Next burn night — amplify bounded quick wins, proof-first comments, and overnight leverage → [the-nexus#859] [AUTOGENESIS][Phase I] Hermes v2.0 architecture spec + successor fork spec
Total connections: 35

View File

@@ -1,375 +0,0 @@
#!/usr/bin/env python3
"""
Cross-Repo Connector — Issue Reference Scanner (8.4)
Scans all repos in an org for cross-repo issue references. Identifies
connections where one repo's issue/PR references another repo's issue number.
This is the smallest concrete first step toward full cross-repo analysis.
Future: extend to code imports, similar patterns.
Usage:
python3 scripts/cross_repo_connector.py --org Timmy_Foundation --dry-run
python3 scripts/cross_repo_connector.py --org Timmy_Foundation --commit
Output:
knowledge/global/cross_repo_connections.yaml — new facts
knowledge/index.json — updated index
metrics/cross_repo_report.md — human-readable summary
"""
import argparse
import json
import os
import re
import sys
from collections import defaultdict
from datetime import datetime, timezone
from pathlib import Path
from typing import Dict, List, Optional, Tuple
import urllib.request
import urllib.error
GITEA_URL = "https://forge.alexanderwhitestone.com"
# ── GiteaClient (lifted from priority_rebalancer.py, minimal subset) ──────
class GiteaClient:
def __init__(self, base_url: str, token: str):
self.base_url = base_url.rstrip("/")
self.token = token
def _request(self, path: str, params: dict = None) -> any:
url = f"{self.base_url}/api/v1{path}"
if params:
qs = "&".join(f"{k}={v}" for k, v in params.items() if v is not None)
url += f"?{qs}"
req = urllib.request.Request(url)
req.add_header("Authorization", f"token {self.token}")
req.add_header("Content-Type", "application/json")
try:
with urllib.request.urlopen(req, timeout=30) as resp:
return json.loads(resp.read().decode())
except urllib.error.HTTPError as e:
print(f"API error {e.code} for {path}: {e.read().decode()[:200]}", file=sys.stderr)
return None
def get_org_repos(self, org: str) -> List[dict]:
repos = []
page = 1
while True:
batch = self._request(f"/orgs/{org}/repos", {"limit": 50, "page": page})
if not batch:
break
repos.extend(batch)
if len(batch) < 50:
break
page += 1
return repos
def get_issues(self, org: str, repo: str, state: str = "closed") -> List[dict]:
"""Fetch issues (and PRs, which Gitea returns together) for a repo."""
issues = []
page = 1
while True:
batch = self._request(
f"/repos/{org}/{repo}/issues",
{"state": state, "limit": 50, "page": page, "type": "issues"}
)
if not batch:
break
issues.extend(batch)
if len(batch) < 50:
break
page += 1
return issues
def get_issue(self, org: str, repo: str, issue_num: int) -> Optional[dict]:
return self._request(f"/repos/{org}/{repo}/issues/{issue_num}")
# ── Token handling ──────────────────────────────────────────────────────────
def get_token() -> str:
"""Read Gitea token from ~/.config/gitea/token or $GITEA_TOKEN."""
token_path = Path.home() / ".config" / "gitea" / "token"
if token_path.exists():
return token_path.read_text().strip()
env_token = os.environ.get("GITEA_TOKEN", "")
if env_token:
return env_token
raise FileNotFoundError(
"Gitea token not found. Create ~/.config/gitea/token or set $GITEA_TOKEN."
)
# ── Cross-reference extraction ──────────────────────────────────────────────
# Patterns that reference another repo's issue/PR:
# - Timmy_Foundation/other-repo#123
# - Timmy_Foundation/other-repo/issues/123
# - full URL: https://forge.../Timmy_Foundation/other-repo/issues/123
# - just "#123" — needs resolving via linked issue numbers (more complex, skip for v1)
CROSS_REF_PATTERN = re.compile(
r"(?:Timmy_Foundation/([\w.-]+)#(\d+))"
r"|(?:Timmy_Foundation/([\w.-]+)/issues/(\d+))"
r"|(?:https?://[^/]+/Timmy_Foundation/([\w.-]+)/issues/(\d+))"
)
def extract_cross_repo_refs(text: str, own_repo: str) -> List[Tuple[str, int]]:
"""
Return list of (other_repo, issue_number) tuples found in text.
Excludes references to the same repo.
"""
matches = []
for m in CROSS_REF_PATTERN.finditer(text or ""):
repo = m.group(1) or m.group(3) or m.group(5)
num = m.group(2) or m.group(4) or m.group(6)
if repo and num:
repo = repo.lower().replace("_", "-")
if repo != own_repo.lower().replace("_", "-"):
matches.append((repo, int(num)))
return matches
# ── Knowledge store helpers ──────────────────────────────────────────────────
def load_index(index_path: Path) -> dict:
if index_path.exists():
with index_path.open() as f:
return json.load(f)
return {"version": 1, "last_updated": "", "total_facts": 0, "facts": []}
def save_index(index: dict, index_path: Path) -> None:
index["version"] = 1
index["last_updated"] = datetime.now(timezone.utc).isoformat()
index["total_facts"] = len(index["facts"])
with index_path.open("w") as f:
json.dump(index, f, indent=2, sort_keys=True, ensure_ascii=False)
def generate_fact_id(domain: str, category: str, sequence: int) -> str:
return f"{domain}:{category}:{sequence:03d}"
def make_connection_fact(
source_repo: str,
target_repo: str,
issue_num: int,
source_title: str,
target_title: Optional[str] = None,
) -> dict:
"""Create a cross-repo connection fact."""
fact_text = (
f"{source_repo} references {target_repo} via issue #{issue_num}: "
f"{source_title[:100]}"
)
if target_title:
fact_text += f" → [{target_repo}#{issue_num}] {target_title[:100]}"
return {
"id": "cross-repo:connection:TBD", # filled by caller with seq
"fact": fact_text,
"category": "pattern", # cross-repo reference is a discovered pattern
"domain": "global", # applies org-wide
"confidence": 0.9,
"tags": ["cross-repo", "issue-reference", "connection"],
"source_count": 1,
"first_seen": datetime.now(timezone.utc).isoformat(),
"last_confirmed": datetime.now(timezone.utc).isoformat(),
"related": [],
}
def append_to_global_yaml(facts: List[dict], knowledge_dir: Path) -> None:
"""Append new cross-repo facts to knowledge/global/cross_repo.yaml."""
global_dir = knowledge_dir / "global"
global_dir.mkdir(parents=True, exist_ok=True)
yaml_path = global_dir / "cross_repo.yaml"
# Load existing YAML documents (may be dict or list-of-dict)
existing_docs = []
if yaml_path.exists():
with yaml_path.open() as f:
try:
import yaml
existing_docs = list(yaml.safe_load_all(f)) or []
except Exception:
existing_docs = []
# Normalize to dict documents (unwrap single-element lists)
normalized = []
for doc in existing_docs:
if isinstance(doc, dict):
normalized.append(doc)
elif isinstance(doc, list) and len(doc) == 1 and isinstance(doc[0], dict):
normalized.append(doc[0])
# Determine next sequence number
max_seq = 0
for doc in normalized:
for f_item in doc.get("facts", []):
fid = f_item.get("id", "")
if fid.startswith("cross-repo:"):
try:
seq = int(fid.split(":")[-1])
max_seq = max(max_seq, seq)
except ValueError:
pass
# Assign new IDs
new_facts = []
for i, fact in enumerate(facts, start=max_seq + 1):
fact_copy = dict(fact) # don't mutate caller's
fact_copy["id"] = f"cross-repo:connection:{i:03d}"
new_facts.append(fact_copy)
if not new_facts:
return
# New YAML document (dict, not list)
new_doc = {
"domain": "global",
"category": "pattern",
"version": 1,
"last_updated": datetime.now(timezone.utc).isoformat(),
"facts": new_facts,
}
# Append document
with yaml_path.open("a") as f:
f.write("\n---\n")
import yaml
yaml.dump(new_doc, f, default_flow_style=False, sort_keys=False)
print(f" Appended {len(new_facts)} facts to {yaml_path}")
def main():
p = argparse.ArgumentParser(description="Cross-repo issue reference connector")
p.add_argument("--org", default="Timmy_Foundation", help="Org to scan")
p.add_argument("--dry-run", action="store_true", help="Don't write knowledge files")
p.add_argument("--state", default="closed", choices=["open", "closed", "all"],
help="Issue state to scan (default: closed)")
p.add_argument("--limit-repos", type=int, help="Max repos to process (dev)")
p.add_argument("--limit-issues", type=int, help="Max issues per repo (dev)")
args = p.parse_args()
token = get_token()
client = GiteaClient(GITEA_URL, token)
knowledge_dir = Path("knowledge")
index_path = knowledge_dir / "index.json"
print(f"Fetching org repos…")
repos = client.get_org_repos(args.org)
print(f"Found {len(repos)} repos in {args.org}")
if args.limit_repos:
repos = repos[:args.limit_repos]
print(f" (limited to {args.limit_repos})")
# Build repo name -> info map
repo_info = {r["name"].lower(): r for r in repos}
# Step 1: collect all cross-repo references from issues
# ((source_repo, target_repo, issue_num, source_title))
raw_connections = []
for repo_meta in repos:
repo_name = repo_meta["name"]
print(f"\nScanning {repo_name} issues…")
issues = client.get_issues(args.org, repo_name, state=args.state)
print(f" {len(issues)} {args.state} issues")
if args.limit_issues:
issues = issues[:args.limit_issues]
for issue in issues:
body = issue.get("body", "") or ""
title = issue.get("title", "") or ""
refs = extract_cross_repo_refs(body + "\n" + title, repo_name)
for target_repo, num in refs:
raw_connections.append((repo_name, target_repo, num, title))
print(f"\nFound {len(raw_connections)} cross-repo reference(s).")
# Deduplicate: (source_repo, target_repo, issue_num) → best title
connection_map = {} # (src, tgt, num) → title
for src, tgt, num, title in raw_connections:
key = (src.lower(), tgt.lower(), num)
if key not in connection_map or len(title) > len(connection_map[key]):
connection_map[key] = title
print(f"Unique connections: {len(connection_map)}")
if args.dry_run:
print("\nDry-run — not writing knowledge files.")
print("\nDiscovered connections:")
for (src, tgt, num), title in sorted(connection_map.items()):
print(f" {src}{tgt}#{num}: {title[:80]}")
return 0
# Step 2: For each unique connection, try to resolve target issue title
# to enrich the fact text
resolved_facts = []
for (src, tgt, num), src_title in sorted(connection_map.items()):
target_title = None
try:
target_issue = client.get_issue(args.org, tgt, num)
if target_issue:
target_title = target_issue.get("title", "")
except Exception as e:
print(f" Could not fetch {tgt}#{num}: {e}", file=sys.stderr)
fact = make_connection_fact(src, tgt, num, src_title, target_title)
# Temporary ID — will be assigned when we know sequence
resolved_facts.append(fact)
# Step 3: Update index.json
index = load_index(index_path)
next_seq = max(
[int(f["id"].split(":")[-1]) for f in index["facts"]
if f["id"].startswith("cross-repo:")]
) + 1 if any(f["id"].startswith("cross-repo:") for f in index["facts"]) else 1
for i, fact in enumerate(resolved_facts):
fact["id"] = f"cross-repo:connection:{next_seq + i:03d}"
index["facts"].append(fact)
save_index(index, index_path)
print(f"\n✓ Updated knowledge/index.json (+{len(resolved_facts)} facts)")
# Step 4: Write to global YAML
append_to_global_yaml(resolved_facts, knowledge_dir)
# Step 5: Generate metrics/report
metrics_dir = Path("metrics")
metrics_dir.mkdir(exist_ok=True)
report_path = metrics_dir / "cross_repo_report.md"
with report_path.open("w") as f:
f.write(f"# Cross-Repo Connection Report\n\n")
f.write(f"Generated: {datetime.now(timezone.utc).isoformat()}\n")
f.write(f"Org: {args.org}\n")
f.write(f"Repos scanned: {len(repos)}\n")
f.write(f"\n## Connections\n\n")
by_source = defaultdict(list)
for fact in resolved_facts:
src = fact["fact"].split(" ")[0]
by_source[src].append(fact)
for src in sorted(by_source.keys()):
f.write(f"### {src}\n\n")
for fact in by_source[src]:
f.write(f"- {fact['fact']}\n")
f.write("\n")
f.write(f"\nTotal connections: {len(resolved_facts)}\n")
print(f"✓ Wrote {report_path}")
print(f"\nDone. Next: run validation:")
print(f" python3 scripts/validate_knowledge.py")
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@@ -0,0 +1,351 @@
#!/usr/bin/env python3
"""
PR Complexity Scorer - Estimate review effort for PRs.
"""
import argparse
import json
import os
import re
import sys
from dataclasses import dataclass, asdict
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Dict, List, Optional
import urllib.request
import urllib.error
GITEA_BASE = "https://forge.alexanderwhitestone.com/api/v1"
DEPENDENCY_FILES = {
"requirements.txt", "pyproject.toml", "setup.py", "setup.cfg",
"Pipfile", "poetry.lock", "package.json", "yarn.lock", "Gemfile",
"go.mod", "Cargo.toml", "pom.xml", "build.gradle"
}
TEST_PATTERNS = [
r"tests?/.*\.py$", r".*_test\.py$", r"test_.*\.py$",
r"spec/.*\.rb$", r".*_spec\.rb$",
r"__tests__/", r".*\.test\.(js|ts|jsx|tsx)$"
]
WEIGHT_FILES = 0.25
WEIGHT_LINES = 0.25
WEIGHT_DEPS = 0.30
WEIGHT_TEST_COV = 0.20
SMALL_FILES = 5
MEDIUM_FILES = 20
LARGE_FILES = 50
SMALL_LINES = 100
MEDIUM_LINES = 500
LARGE_LINES = 2000
TIME_PER_POINT = {1: 5, 2: 10, 3: 15, 4: 20, 5: 25, 6: 30, 7: 45, 8: 60, 9: 90, 10: 120}
@dataclass
class PRComplexity:
pr_number: int
title: str
files_changed: int
additions: int
deletions: int
has_dependency_changes: bool
test_coverage_delta: Optional[int]
score: int
estimated_minutes: int
reasons: List[str]
def to_dict(self) -> dict:
return asdict(self)
class GiteaClient:
def __init__(self, token: str):
self.token = token
self.base_url = GITEA_BASE.rstrip("/")
def _request(self, path: str, params: Dict = None) -> Any:
url = f"{self.base_url}{path}"
if params:
qs = "&".join(f"{k}={v}" for k, v in params.items() if v is not None)
url += f"?{qs}"
req = urllib.request.Request(url)
req.add_header("Authorization", f"token {self.token}")
req.add_header("Content-Type", "application/json")
try:
with urllib.request.urlopen(req, timeout=30) as resp:
return json.loads(resp.read().decode())
except urllib.error.HTTPError as e:
print(f"API error {e.code}: {e.read().decode()[:200]}", file=sys.stderr)
return None
except urllib.error.URLError as e:
print(f"Network error: {e}", file=sys.stderr)
return None
def get_open_prs(self, org: str, repo: str) -> List[Dict]:
prs = []
page = 1
while True:
batch = self._request(f"/repos/{org}/{repo}/pulls", {"limit": 50, "page": page, "state": "open"})
if not batch:
break
prs.extend(batch)
if len(batch) < 50:
break
page += 1
return prs
def get_pr_files(self, org: str, repo: str, pr_number: int) -> List[Dict]:
files = []
page = 1
while True:
batch = self._request(
f"/repos/{org}/{repo}/pulls/{pr_number}/files",
{"limit": 100, "page": page}
)
if not batch:
break
files.extend(batch)
if len(batch) < 100:
break
page += 1
return files
def post_comment(self, org: str, repo: str, pr_number: int, body: str) -> bool:
data = json.dumps({"body": body}).encode("utf-8")
req = urllib.request.Request(
f"{self.base_url}/repos/{org}/{repo}/issues/{pr_number}/comments",
data=data,
method="POST",
headers={"Authorization": f"token {self.token}", "Content-Type": "application/json"}
)
try:
with urllib.request.urlopen(req, timeout=30) as resp:
return resp.status in (200, 201)
except urllib.error.HTTPError:
return False
def is_dependency_file(filename: str) -> bool:
return any(filename.endswith(dep) for dep in DEPENDENCY_FILES)
def is_test_file(filename: str) -> bool:
return any(re.search(pattern, filename) for pattern in TEST_PATTERNS)
def score_pr(
files_changed: int,
additions: int,
deletions: int,
has_dependency_changes: bool,
test_coverage_delta: Optional[int] = None
) -> tuple[int, int, List[str]]:
score = 1.0
reasons = []
# Files changed
if files_changed <= SMALL_FILES:
fscore = 1.0
reasons.append("small number of files changed")
elif files_changed <= MEDIUM_FILES:
fscore = 2.0
reasons.append("moderate number of files changed")
elif files_changed <= LARGE_FILES:
fscore = 2.5
reasons.append("large number of files changed")
else:
fscore = 3.0
reasons.append("very large PR spanning many files")
# Lines changed
total_lines = additions + deletions
if total_lines <= SMALL_LINES:
lscore = 1.0
reasons.append("small change size")
elif total_lines <= MEDIUM_LINES:
lscore = 2.0
reasons.append("moderate change size")
elif total_lines <= LARGE_LINES:
lscore = 3.0
reasons.append("large change size")
else:
lscore = 4.0
reasons.append("very large change")
# Dependency changes
if has_dependency_changes:
dscore = 2.5
reasons.append("dependency changes (architectural impact)")
else:
dscore = 0.0
# Test coverage delta
tscore = 0.0
if test_coverage_delta is not None:
if test_coverage_delta > 0:
reasons.append(f"test additions (+{test_coverage_delta} test files)")
tscore = -min(2.0, test_coverage_delta / 2.0)
elif test_coverage_delta < 0:
reasons.append(f"test removals ({abs(test_coverage_delta)} test files)")
tscore = min(2.0, abs(test_coverage_delta) * 0.5)
else:
reasons.append("test coverage change not assessed")
# Weighted sum, scaled by 3 to use full 1-10 range
bonus = (fscore * WEIGHT_FILES) + (lscore * WEIGHT_LINES) + (dscore * WEIGHT_DEPS) + (tscore * WEIGHT_TEST_COV)
scaled_bonus = bonus * 3.0
score = 1.0 + scaled_bonus
final_score = max(1, min(10, int(round(score))))
est_minutes = TIME_PER_POINT.get(final_score, 30)
return final_score, est_minutes, reasons
def analyze_pr(client: GiteaClient, org: str, repo: str, pr_data: Dict) -> PRComplexity:
pr_num = pr_data["number"]
title = pr_data.get("title", "")
files = client.get_pr_files(org, repo, pr_num)
additions = sum(f.get("additions", 0) for f in files)
deletions = sum(f.get("deletions", 0) for f in files)
filenames = [f.get("filename", "") for f in files]
has_deps = any(is_dependency_file(f) for f in filenames)
test_added = sum(1 for f in files if f.get("status") == "added" and is_test_file(f.get("filename", "")))
test_removed = sum(1 for f in files if f.get("status") == "removed" and is_test_file(f.get("filename", "")))
test_delta = test_added - test_removed if (test_added or test_removed) else None
score, est_min, reasons = score_pr(
files_changed=len(files),
additions=additions,
deletions=deletions,
has_dependency_changes=has_deps,
test_coverage_delta=test_delta
)
return PRComplexity(
pr_number=pr_num,
title=title,
files_changed=len(files),
additions=additions,
deletions=deletions,
has_dependency_changes=has_deps,
test_coverage_delta=test_delta,
score=score,
estimated_minutes=est_min,
reasons=reasons
)
def build_comment(complexity: PRComplexity) -> str:
change_desc = f"{complexity.files_changed} files, +{complexity.additions}/-{complexity.deletions} lines"
deps_note = "\n- :warning: Dependency changes detected — architectural review recommended" if complexity.has_dependency_changes else ""
test_note = ""
if complexity.test_coverage_delta is not None:
if complexity.test_coverage_delta > 0:
test_note = f"\n- :+1: {complexity.test_coverage_delta} test file(s) added"
elif complexity.test_coverage_delta < 0:
test_note = f"\n- :warning: {abs(complexity.test_coverage_delta)} test file(s) removed"
comment = f"## 📊 PR Complexity Analysis\n\n"
comment += f"**PR #{complexity.pr_number}: {complexity.title}**\n\n"
comment += f"| Metric | Value |\n|--------|-------|\n"
comment += f"| Changes | {change_desc} |\n"
comment += f"| Complexity Score | **{complexity.score}/10** |\n"
comment += f"| Estimated Review Time | ~{complexity.estimated_minutes} minutes |\n\n"
comment += f"### Scoring rationale:"
for r in complexity.reasons:
comment += f"\n- {r}"
if deps_note:
comment += deps_note
if test_note:
comment += test_note
comment += f"\n\n---\n"
comment += f"*Generated by PR Complexity Scorer — [issue #135](https://forge.alexanderwhitestone.com/Timmy_Foundation/compounding-intelligence/issues/135)*"
return comment
def main():
parser = argparse.ArgumentParser(description="PR Complexity Scorer")
parser.add_argument("--org", default="Timmy_Foundation")
parser.add_argument("--repo", default="compounding-intelligence")
parser.add_argument("--token", default=os.environ.get("GITEA_TOKEN") or os.path.expanduser("~/.config/gitea/token"))
parser.add_argument("--dry-run", action="store_true")
parser.add_argument("--apply", action="store_true")
parser.add_argument("--output", default="metrics/pr_complexity.json")
args = parser.parse_args()
token_path = args.token
if os.path.exists(token_path):
with open(token_path) as f:
token = f.read().strip()
else:
token = args.token
if not token:
print("ERROR: No Gitea token provided", file=sys.stderr)
sys.exit(1)
client = GiteaClient(token)
print(f"Fetching open PRs for {args.org}/{args.repo}...")
prs = client.get_open_prs(args.org, args.repo)
if not prs:
print("No open PRs found.")
sys.exit(0)
print(f"Found {len(prs)} open PR(s). Analyzing...")
results = []
Path(args.output).parent.mkdir(parents=True, exist_ok=True)
for pr in prs:
pr_num = pr["number"]
title = pr.get("title", "")
print(f" Analyzing PR #{pr_num}: {title[:60]}")
try:
complexity = analyze_pr(client, args.org, args.repo, pr)
results.append(complexity.to_dict())
comment = build_comment(complexity)
if args.dry_run:
print(f" → Score: {complexity.score}/10, Est: {complexity.estimated_minutes}min [DRY-RUN]")
elif args.apply:
success = client.post_comment(args.org, args.repo, pr_num, comment)
status = "[commented]" if success else "[FAILED]"
print(f" → Score: {complexity.score}/10, Est: {complexity.estimated_minutes}min {status}")
else:
print(f" → Score: {complexity.score}/10, Est: {complexity.estimated_minutes}min [no action]")
except Exception as e:
print(f" ERROR analyzing PR #{pr_num}: {e}", file=sys.stderr)
with open(args.output, "w") as f:
json.dump({
"org": args.org,
"repo": args.repo,
"timestamp": datetime.now(timezone.utc).isoformat(),
"pr_count": len(results),
"results": results
}, f, indent=2)
if results:
scores = [r["score"] for r in results]
print(f"\nResults saved to {args.output}")
print(f"Summary: {len(results)} PRs, scores range {min(scores):.0f}-{max(scores):.0f}")
else:
print("\nNo results to save.")
if __name__ == "__main__":
main()

View File

@@ -22,114 +22,95 @@ import sys
from pathlib import Path
from typing import Optional
from session_reader import extract_conversation, read_session
def compute_hash(text: str) -> str:
"""Content hash for deduplication."""
return hashlib.sha256(text.encode()).hexdigest()[:16]
def extract_pairs_from_session(session_data: dict, min_ratio: float = 1.5,
def extract_pairs_from_conversation(conversation: list, session_id: str, model: str,
min_ratio: float = 1.5,
min_response_words: int = 20) -> list:
"""Extract terse→rich pairs from a single session object."""
"""Extract terse→rich pairs from a normalized conversation."""
pairs = []
conversations = session_data.get("conversations", [])
session_id = session_data.get("id", "unknown")
model = session_data.get("model", "unknown")
seen_hashes = set()
for i, msg in enumerate(conversations):
# Look for assistant/gpt responses
if msg.get("from") not in ("gpt", "assistant"):
for i, msg in enumerate(conversation):
# Look for assistant responses
if msg.get('role') != 'assistant':
continue
response_text = msg.get("value", "")
response_text = msg.get('content', '')
if not response_text or len(response_text.split()) < min_response_words:
continue
# Find the preceding human message
# Find the preceding user message
prompt_text = ""
for j in range(i - 1, -1, -1):
if conversations[j].get("from") == "human":
prompt_text = conversations[j].get("value", "")
if conversation[j].get('role') == 'user':
prompt_text = conversation[j].get('content', '')
break
if not prompt_text:
continue
# Filter: skip tool results, system messages embedded as human
if prompt_text.startswith("{") and "output" in prompt_text[:100]:
continue # likely a tool result
if prompt_text.startswith("# SOUL.md") or prompt_text.startswith("You are"):
continue # system prompt leak
if prompt_text.startswith('{') and 'output' in prompt_text[:100]:
continue
if prompt_text.startswith('# SOUL.md') or prompt_text.startswith('You are'):
continue
# Quality filters
prompt_words = len(prompt_text.split())
response_words = len(response_text.split())
# Must have meaningful length ratio
if prompt_words == 0 or response_words == 0:
continue
ratio = response_words / prompt_words
if ratio < min_ratio:
continue
# Skip responses that are mostly code
code_blocks = response_text.count("```")
if code_blocks >= 4 and len(response_text.replace("```", "").strip()) < 50:
code_blocks = response_text.count('```')
if code_blocks >= 4 and len(response_text.replace('```', '').strip()) < 50:
continue
# Skip responses with tool call artifacts
if "tool_call" in response_text[:100] or "function_call" in response_text[:100]:
if 'tool_call' in response_text[:100] or 'function_call' in response_text[:100]:
continue
# Deduplicate by content hash
content_hash = compute_hash(prompt_text + response_text[:200])
if content_hash in seen_hashes:
continue
seen_hashes.add(content_hash)
# Clean up response: remove markdown headers if too many
clean_response = response_text
pairs.append({
"terse": prompt_text.strip(),
"rich": clean_response.strip(),
"source": session_id,
"model": model,
"prompt_words": prompt_words,
"response_words": response_words,
"ratio": round(ratio, 2),
'terse': prompt_text.strip(),
'rich': clean_response.strip(),
'source': session_id,
'model': model,
'prompt_words': prompt_words,
'response_words': response_words,
'ratio': round(ratio, 2),
})
return pairs
def extract_from_jsonl_file(filepath: str, **kwargs) -> list:
"""Extract pairs from a session JSONL file."""
pairs = []
path = Path(filepath)
if not path.exists():
print(f"Warning: {filepath} not found", file=sys.stderr)
return pairs
content = path.read_text()
lines = content.strip().split("\n")
for line in lines:
line = line.strip()
if not line:
continue
try:
session = json.loads(line)
except json.JSONDecodeError:
continue
session_pairs = extract_pairs_from_session(session, **kwargs)
pairs.extend(session_pairs)
return pairs
def extract_from_jsonl_file(path: str, **kwargs) -> list:
"""Read a session file and extract training pairs using normalized conversation."""
session_messages = read_session(path)
if not session_messages:
return []
conversation = extract_conversation(session_messages)
# Derive session_id and model from first real message metadata
first_msg = next((m for m in session_messages if m.get('role') or m.get('from')), {})
session_id = first_msg.get('meta_session_id', Path(path).name)
model = first_msg.get('model', 'unknown')
return extract_pairs_from_conversation(conversation, session_id, model, **kwargs)
def deduplicate_pairs(pairs: list) -> list:

View File

@@ -0,0 +1,170 @@
#!/usr/bin/env python3
"""
Tests for PR Complexity Scorer — unit tests for the scoring logic.
"""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent))
from pr_complexity_scorer import (
score_pr,
is_dependency_file,
is_test_file,
TIME_PER_POINT,
SMALL_FILES,
MEDIUM_FILES,
LARGE_FILES,
SMALL_LINES,
MEDIUM_LINES,
LARGE_LINES,
)
PASS = 0
FAIL = 0
def test(name):
def decorator(fn):
global PASS, FAIL
try:
fn()
PASS += 1
print(f" [PASS] {name}")
except AssertionError as e:
FAIL += 1
print(f" [FAIL] {name}: {e}")
except Exception as e:
FAIL += 1
print(f" [FAIL] {name}: Unexpected error: {e}")
return decorator
def assert_eq(a, b, msg=""):
if a != b:
raise AssertionError(f"{msg} expected {b!r}, got {a!r}")
def assert_true(v, msg=""):
if not v:
raise AssertionError(msg or "Expected True")
def assert_false(v, msg=""):
if v:
raise AssertionError(msg or "Expected False")
print("=== PR Complexity Scorer Tests ===\n")
print("-- File Classification --")
@test("dependency file detection — requirements.txt")
def _():
assert_true(is_dependency_file("requirements.txt"))
assert_true(is_dependency_file("src/requirements.txt"))
assert_false(is_dependency_file("requirements_test.txt"))
@test("dependency file detection — pyproject.toml")
def _():
assert_true(is_dependency_file("pyproject.toml"))
assert_false(is_dependency_file("myproject.py"))
@test("test file detection — pytest style")
def _():
assert_true(is_test_file("tests/test_api.py"))
assert_true(is_test_file("test_module.py"))
assert_true(is_test_file("src/module_test.py"))
@test("test file detection — other frameworks")
def _():
assert_true(is_test_file("spec/feature_spec.rb"))
assert_true(is_test_file("__tests__/component.test.js"))
assert_false(is_test_file("testfixtures/helper.py"))
print("\n-- Scoring Logic --")
@test("small PR gets low score (1-3)")
def _():
score, minutes, _ = score_pr(
files_changed=3,
additions=50,
deletions=10,
has_dependency_changes=False,
test_coverage_delta=None
)
assert_true(1 <= score <= 3, f"Score should be low, got {score}")
assert_true(minutes < 20)
@test("medium PR gets medium score (4-6)")
def _():
score, minutes, _ = score_pr(
files_changed=15,
additions=400,
deletions=100,
has_dependency_changes=False,
test_coverage_delta=None
)
assert_true(4 <= score <= 6, f"Score should be medium, got {score}")
assert_true(20 <= minutes <= 45)
@test("large PR gets high score (7-9)")
def _():
score, minutes, _ = score_pr(
files_changed=60,
additions=3000,
deletions=1500,
has_dependency_changes=True,
test_coverage_delta=None
)
assert_true(7 <= score <= 9, f"Score should be high, got {score}")
assert_true(minutes >= 45)
@test("dependency changes boost score")
def _():
base_score, _, _ = score_pr(
files_changed=10, additions=200, deletions=50,
has_dependency_changes=False, test_coverage_delta=None
)
dep_score, _, _ = score_pr(
files_changed=10, additions=200, deletions=50,
has_dependency_changes=True, test_coverage_delta=None
)
assert_true(dep_score > base_score, f"Deps: {base_score} -> {dep_score}")
@test("adding tests lowers complexity")
def _():
base_score, _, _ = score_pr(
files_changed=8, additions=150, deletions=20,
has_dependency_changes=False, test_coverage_delta=None
)
better_score, _, _ = score_pr(
files_changed=8, additions=180, deletions=20,
has_dependency_changes=False, test_coverage_delta=3
)
assert_true(better_score < base_score, f"Tests: {base_score} -> {better_score}")
@test("removing tests increases complexity")
def _():
base_score, _, _ = score_pr(
files_changed=8, additions=150, deletions=20,
has_dependency_changes=False, test_coverage_delta=None
)
worse_score, _, _ = score_pr(
files_changed=8, additions=150, deletions=20,
has_dependency_changes=False, test_coverage_delta=-2
)
assert_true(worse_score > base_score, f"Remove tests: {base_score} -> {worse_score}")
@test("score bounded 1-10")
def _():
for files, adds, dels in [(1, 10, 5), (100, 10000, 5000)]:
score, _, _ = score_pr(files, adds, dels, False, None)
assert_true(1 <= score <= 10, f"Score {score} out of range")
@test("estimated minutes exist for all scores")
def _():
for s in range(1, 11):
assert_true(s in TIME_PER_POINT, f"Missing time for score {s}")
print(f"\n=== Results: {PASS} passed, {FAIL} failed ===")
sys.exit(0 if FAIL == 0 else 1)

View File

@@ -0,0 +1,118 @@
"""
Tests for session_pair_harvester — training pair extraction from sessions.
"""
import json
import tempfile
import unittest
from pathlib import Path
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent / "scripts"))
from session_pair_harvester import (
extract_pairs_from_conversation,
extract_from_jsonl_file,
deduplicate_pairs,
compute_hash,
)
class TestSessionPairHarvester(unittest.TestCase):
def test_compute_hash_consistent(self):
h1 = compute_hash("hello world")
h2 = compute_hash("hello world")
self.assertEqual(h1, h2)
self.assertEqual(len(h1), 16)
def test_extract_simple_qa_pair(self):
"""A simple user→assistant exchange produces one pair."""
conversation = [
{"role": "user", "content": "What is the capital of France?"},
{"role": "assistant", "content": "The capital of France is Paris. It is a major European city renowned for its art, fashion, gastronomy, cultural heritage, and historical significance. The city attracts millions of tourists annually."},
]
pairs = extract_pairs_from_conversation(conversation, "test_session", "test-model")
self.assertEqual(len(pairs), 1)
self.assertEqual(pairs[0]["terse"], "What is the capital of France?")
self.assertIn("Paris", pairs[0]["rich"])
self.assertEqual(pairs[0]["source"], "test_session")
def test_min_ratio_filter(self):
"""Very short responses are filtered out."""
conversation = [
{"role": "user", "content": "Yes"},
{"role": "assistant", "content": "No."},
]
# Default min_ratio = 1.5, min_words = 20 for response
pairs = extract_pairs_from_conversation(conversation, "s", "m", min_response_words=3)
self.assertEqual(len(pairs), 0)
def test_min_words_filter(self):
"""Assistant responses below min word count are skipped."""
conversation = [
{"role": "user", "content": "Explain the project architecture in detail"},
{"role": "assistant", "content": "OK."},
]
pairs = extract_pairs_from_conversation(conversation, "s", "m", min_response_words=5)
self.assertEqual(len(pairs), 0)
def test_skip_non_assistant_messages(self):
"""System and tool messages are ignored."""
conversation = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": "Hi there! How can I help you today?"},
]
pairs = extract_pairs_from_conversation(conversation, "s", "m", min_response_words=3)
self.assertEqual(len(pairs), 1)
self.assertEqual(pairs[0]["terse"], "Hello")
def test_multiple_pairs_from_one_session(self):
"""A conversation with several Q&A turns yields multiple pairs."""
conversation = [
{"role": "user", "content": "First question?"},
{"role": "assistant", "content": "Here is a detailed and comprehensive answer that thoroughly explores multiple aspects of the subject. It provides background context and practical implications for the reader."},
{"role": "user", "content": "Second?"},
{"role": "assistant", "content": "Another comprehensive response with detailed examples. This includes practical code blocks and thorough explanations to ensure deep understanding of the topic at hand."},
]
pairs = extract_pairs_from_conversation(conversation, "s", "m", min_ratio=1.0)
self.assertEqual(len(pairs), 2)
def test_deduplication_removes_duplicates(self):
"""Identical pairs across sessions are deduplicated."""
pairs = [
{"terse": "q1", "rich": "a1", "source": "s1", "model": "m"},
{"terse": "q1", "rich": "a1", "source": "s2", "model": "m"},
{"terse": "q2", "rich": "a2", "source": "s1", "model": "m"},
]
unique = deduplicate_pairs(pairs)
self.assertEqual(len(unique), 2)
sources = {p["source"] for p in unique}
# First unique pair can be from either s1 or s2
self.assertIn("s1", sources)
def test_integration_with_test_sessions(self):
"""Harvester finds pairs in real test session files."""
repo_root = Path(__file__).parent.parent
test_sessions_dir = repo_root / "test_sessions"
if not test_sessions_dir.exists():
self.skipTest("test_sessions not found")
pairs = []
for jsonl_file in sorted(test_sessions_dir.glob("*.jsonl")):
pairs.extend(extract_from_jsonl_file(str(jsonl_file)))
self.assertGreater(len(pairs), 0, "Should extract at least one pair from test_sessions")
for p in pairs:
self.assertIn("terse", p)
self.assertIn("rich", p)
self.assertIn("source", p)
self.assertIn("model", p)
# Verify content exists
self.assertGreater(len(p["terse"]), 0)
self.assertGreater(len(p["rich"]), 0)
if __name__ == "__main__":
unittest.main()