diff --git a/docs/HERMES-LOOPS-PARITY-AUDIT.md b/docs/HERMES-LOOPS-PARITY-AUDIT.md index bab19a71..6a6ea8d7 100644 --- a/docs/HERMES-LOOPS-PARITY-AUDIT.md +++ b/docs/HERMES-LOOPS-PARITY-AUDIT.md @@ -1,7 +1,7 @@ # Hermes Self-Improvement Loops — Parity Audit Status: comparison audit, July 2026. Hermes agent codebase examined at -`/home/zack/projects/hermes-agent` (registered tracedecay project +`~/projects/hermes-agent` (registered tracedecay project "hermes-agent"). TraceDecay side examined at HEAD of the current TraceDecay worktree after dashboard automation work landed. @@ -320,7 +320,7 @@ either. ## 5. Source map -Hermes (`/home/zack/projects/hermes-agent`): +Hermes (`~/projects/hermes-agent`): - `agent/background_review.py` — review fork + prompts - `agent/turn_context.py:209`, `agent/turn_finalizer.py:375` — trigger logic @@ -330,7 +330,7 @@ Hermes (`/home/zack/projects/hermes-agent`): - `agent/curator.py` — weekly consolidation curator - `cron/jobs.py`, `cron/scheduler.py`, `cron/blueprint_catalog.py`, `cron/suggestions.py` — cron platform -TraceDecay (`/home/zack/projects/tracedecay`): +TraceDecay (`~/projects/tracedecay`): - `src/automation/{scheduler,lifecycle,run_ledger}.rs` — gates, locks, ledger - `src/automation/{runner,memory_curator,session_reflector,skill_writer}.rs` — the three tasks diff --git a/docs/SKILL-ADOPTION-RESEARCH.md b/docs/SKILL-ADOPTION-RESEARCH.md index 6a1ce6b8..24f37b26 100644 --- a/docs/SKILL-ADOPTION-RESEARCH.md +++ b/docs/SKILL-ADOPTION-RESEARCH.md @@ -6,7 +6,14 @@ TraceDecay plugins (`~/.cursor/plugins/local/tracedecay/`, `~/.codex/…`), the repo sources (`cursor-plugin/`, `codex-plugin/`, `src/hooks/`, `src/mcp/tools/definitions.rs`), and TraceDecay's own analytics (`http://127.0.0.1:7341/api/plugins/analytics/*`, -`~/.tracedecay/projects/proj_b4a8bbe4953823c4/hook_analytics.jsonl`).* +`~/.tracedecay/projects/proj_/hook_analytics.jsonl`).* + +> **Status (2026-07-03):** the P1 catalog consolidation recommended in §6 -- +> including the new `using-tracedecay` skill — was implemented by +> [PR #225](https://github.com/ScriptedAlchemy/tracedecay/pull/225) the day +> after this snapshot. Skill names, directory counts, and the +> `memorize-subject` duplication described below refer to the +> pre-restructure catalog. ## TL;DR @@ -168,7 +175,7 @@ Two structural notes: ## 3. The measured usage picture All numbers from the live dashboard (`/api/plugins/analytics/*`) and -`hook_analytics.jsonl` for project `proj_b4a8bbe4953823c4`, sampled 2026-07-02. +`hook_analytics.jsonl` for project `proj_`, sampled 2026-07-02. ### 3.1 MCP tool distribution: TraceDecay is used as a file reader diff --git a/src/agents/claude_agents/code-health-auditor.md b/src/agents/claude_agents/code-health-auditor.md index de673510..c85e5bed 100644 --- a/src/agents/claude_agents/code-health-auditor.md +++ b/src/agents/claude_agents/code-health-auditor.md @@ -15,7 +15,7 @@ You are a read-only audit subagent. You score and rank code health and return fi 1. Start with `tracedecay_health` (`details: true`) and let the weak dimensions drive the drill-down. 2. Drill only into weak dimensions or explicit asks: complexity/size -> `tracedecay_complexity`, `tracedecay_gini`, `tracedecay_god_class`, `tracedecay_largest`, `tracedecay_hotspots`; structure -> `tracedecay_coupling`, `tracedecay_dependency_depth`, `tracedecay_dsm`, `tracedecay_circular`, `tracedecay_recursion`; quality -> `tracedecay_redundancy`, `tracedecay_doc_coverage`, `tracedecay_unsafe_patterns`, `tracedecay_test_risk`. 3. Keep expensive scans scoped (`path`, `limit`, `max_pairs`) and stop once the ranked findings are actionable. -4. If the `tracedecay:code-health-report` skill is available, follow its full workflow. +4. If the `tracedecay:code-health` skill is available, follow its full workflow. ## Rules diff --git a/src/sessions/claude.rs b/src/sessions/claude.rs index 2e5c2417..e3441adc 100644 --- a/src/sessions/claude.rs +++ b/src/sessions/claude.rs @@ -126,9 +126,12 @@ impl TranscriptSource for ClaudeSource { messages.push(message); } } - if messages.is_empty() { - return None; - } + // No early return when `messages` is empty: this source scans every + // ~/.claude/projects slug and relies on the per-row cwd filter above, + // so transcripts belonging to other projects legitimately parse to + // zero messages. Returning the (empty) transcript lets `ingest_one` + // persist the advanced cursor; returning `None` would pin the cursor + // at 0 and re-read + re-filter the whole file on every sweep. let project = project_root.to_string_lossy().to_string(); let draft = SessionDraft { diff --git a/tests/transcript_ingest_suite/claude.rs b/tests/transcript_ingest_suite/claude.rs index f6d72870..b13b3ab5 100644 --- a/tests/transcript_ingest_suite/claude.rs +++ b/tests/transcript_ingest_suite/claude.rs @@ -228,7 +228,7 @@ async fn claude_transcript_for_other_project_is_skipped() { let other = tmp.path().join("other-project"); std::fs::create_dir_all(&other).unwrap(); // Transcript records a cwd that is NOT the project we ingest for. - write_claude_transcript(&home, &other, "claude-other"); + let path = write_claude_transcript(&home, &other, "claude-other"); let db = open_project_session_db(&project).await.unwrap(); let source = ClaudeSource::with_home(&home); @@ -238,6 +238,22 @@ async fn claude_transcript_for_other_project_is_skipped() { stats.messages_upserted, 0, "a transcript whose cwd is a different project must be skipped" ); + + // The cursor must still advance past the filtered-out content, or every + // future sweep re-reads and re-filters the whole foreign transcript. + let file_size = std::fs::metadata(&path).unwrap().len(); + let path_str = path.to_string_lossy(); + let mut offset = db.get_parse_offset(path_str.as_ref()).await; + if offset.is_none() && cfg!(windows) { + // The scanner stores native separators; the helper built this path + // with embedded forward slashes. + offset = db.get_parse_offset(&path_str.replace('/', "\\")).await; + } + let offset = offset.expect("skipped foreign transcript should persist a parse offset"); + assert_eq!( + offset.byte_offset, file_size, + "parse cursor should sit at EOF for a fully filtered transcript" + ); } #[tokio::test]