Skip to content

Persistent home directory, skills seeding/update, and Telegram audit cards#40

Open
chinkan wants to merge 36 commits into
mainfrom
feature/telegram-plan-tool-visuals
Open

Persistent home directory, skills seeding/update, and Telegram audit cards#40
chinkan wants to merge 36 commits into
mainfrom
feature/telegram-plan-tool-visuals

Conversation

@chinkan
Copy link
Copy Markdown
Owner

@chinkan chinkan commented May 29, 2026

This PR introduces three interconnected features:

1. Persistent home directory model (~/.rustfox)

  • Resolved via RUSTFOX_HOME env → [general].home config → ~/.rustfox
  • All state lives under the home root: config.toml, rustfox.db, skills/, agents/, workspace/, artifacts/, user_model.md
  • Path resolution in src/home.rs + Config::resolve() — unset paths default under home, absolute overrides preserved, relative overrides emit legacy warnings

2. Skills/agents seeding and update engine (src/skills/)

  • Bundled skills/ and agents/ directories are seed-copied to the home on first run (seed_dir_if_empty)
  • /update-skills command re-syncs bundled content using content-hash lock files (skills-lock.json, agents-lock.json)
  • Locally-modified skills get backed up as *.bak before being overwritten

3. Telegram audit cards (ToolCallNotifier)

  • Persistent structured audit card showing plan checklist and tool activity, never mixed into the answer stream
  • Privacy-aware format_args_preview using allowlist/denylist model to avoid leaking secrets
  • Plan plan_create/plan_update parsed into a visual checklist with step status markers
  • Terminal Finished event persists a completed/failed summary card (or deletes if no activity)
  • Edit retry logic for rate-limit resilience

Additional changes

  • Comprehensive design spec and implementation plan documents
  • Regression tests for message flow, argument redaction, plan rendering, skill seeding/update
  • Integration test for sandbox-home isolation

Copilot AI review requested due to automatic review settings May 29, 2026 08:03
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 29, 2026

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors Telegram verbose-mode progress reporting into a single persistent "audit card" managed by ToolCallNotifier, and removes the duplicate path that previously streamed tool-status lines into the assistant answer. It also adds a privacy-aware argument preview formatter and a structured plan/tool display model.

Changes:

  • Adds a ToolDisplayState with plan checklist + tool activity rendering, parses plan_create/plan_update arguments, and tightens format_args_preview to an allowlist/denylist model.
  • Introduces ToolEvent::Finished and reworks ToolCallNotifier::finish to edit the live message into a persistent completed/failed card (or delete it when no activity occurred).
  • Removes the agent-side stream_status_tx path so tool status lines no longer enter the answer stream, and adds a source-inspection regression test.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/platform/tool_notifier.rs Adds display state, planning parsers, privacy-aware preview, persistent finish card, edit retry, and new tests.
src/platform/telegram.rs Forwards a terminal Finished event to the notifier and finalizes the notifier even if the channel closes unexpectedly.
src/agent.rs Removes duplicate tool-status streaming; sends raw arguments_json to the notifier; adds source-inspection regression test.
docs/superpowers/specs/2026-05-28-telegram-plan-tool-visuals-design.md New design spec for verbose-mode audit card.
docs/superpowers/plans/2026-05-28-telegram-plan-tool-visuals.md New implementation plan with step-by-step tasks.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

chinkan added 24 commits May 29, 2026 17:01
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

Claude encountered an error after 1s —— View job


I'll analyze this and get back to you.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 7 comments.

Comment thread src/main.rs Outdated
Comment on lines +121 to +125
if !lock_path.exists() {
let lock = rustfox::skills::update::SkillLock {
version: 1,
skills: rustfox::skills::seed::lock_map_for(&config.skills.directory),
};
Comment thread src/platform/telegram.rs Outdated
Comment on lines +219 to +223
.config
.resolved_home
.clone()
.map(|h| h.join("skills-lock.json"))
.unwrap_or_else(|| std::path::PathBuf::from("skills-lock.json"));
Comment thread src/skills/update.rs Outdated
impl UpdateReport {
pub fn summary(&self) -> String {
format!(
"Skill update: {} updated, {} backed-up, {} unchanged.",
Comment thread src/skills/update.rs Outdated
anyhow::bail!("No bundled skills found at {}", bundled.display());
}
let mut lock = read_lock(lock_path);
tokio::fs::create_dir_all(instance).await.ok();
Comment thread src/platform/tool_notifier.rs Outdated
}
}
s
text
Comment thread src/config.rs Outdated
Comment on lines +400 to +402
/// Resolve the home root and every data path, create directories, and write
/// the resolved absolute paths back into the config fields. Returns any
/// legacy-path warnings (relative overrides) for the caller to log.
Comment thread README.md
Comment on lines +72 to +75
> **Persistent home:** RustFox keeps all state under `~/.rustfox` by default
> (config, database, skills, agents, and a durable `workspace/` sandbox).
> Override with the `RUSTFOX_HOME` environment variable or `[general].home`.
> See [docs/persistent-home-directory.md](docs/persistent-home-directory.md).
@chinkan chinkan changed the title Add audit cards for Telegram plan tool Persistent home directory, skills seeding/update, and Telegram audit cards Jun 1, 2026
chinkan added 2 commits June 1, 2026 17:43
…nd bundled layers

- Introduced `SkillSource` enum to differentiate between instance and bundled skills.
- Refactored `SkillRegistry` to maintain separate maps for instance and bundled skills, along with a mapping for base directories.
- Updated `load_skills_from_dir` to accept a `SkillSource` parameter and adjusted all relevant calls.
- Added `bundled_directory` configuration fields to `SkillsConfig` and `AgentsConfig`.
- Enhanced agent tools to resolve skill and agent file paths using the new registry structure.
- Modified startup logic to load both instance and bundled skills, merging them appropriately.
- Updated tests to cover new functionality and ensure correct behavior of skill loading and resolution.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

Claude encountered an error after 1s —— View job


I'll analyze this and get back to you.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 34 out of 35 changed files in this pull request and generated 4 comments.

Comment thread src/agent.rs
Comment on lines +175 to +192
{
let mut skills = self.skills.write().await;
if let Ok(reg) = s_instance {
skills.instance_skills = reg.instance_skills;
for (k, v) in &reg.skill_base_dirs {
skills.skill_base_dirs.insert(k.clone(), v.clone());
}
}
if let Ok(reg) = s_bundled {
skills.bundled_skills = reg.bundled_skills;
for (k, v) in &reg.skill_base_dirs {
skills
.skill_base_dirs
.entry(k.clone())
.or_insert_with(|| v.clone());
}
}
}
Comment thread src/skills/update.rs
Comment on lines +99 to +102
if instance_hash.as_deref() == Some(bundled_hash.as_str()) {
report.skipped.push(name);
continue;
}
Comment thread src/skills/seed.rs
Comment on lines +8 to +17
pub fn hash_skill_dir(dir: &Path) -> Option<String> {
let primary = ["SKILL.md", "AGENT.md"]
.into_iter()
.map(|f| dir.join(f))
.find(|p| p.is_file())?;
let bytes = std::fs::read(&primary).ok()?;
let mut h = Sha256::new();
h.update(&bytes);
Some(format!("{:x}", h.finalize()))
}
Comment thread src/platform/tool_notifier.rs Outdated
Comment on lines +462 to +464
}
// Fallback: truncate raw JSON
crate::utils::strings::truncate_chars(args_json, 60)
let joined = parts.join(", ");
crate::utils::strings::truncate_chars(&joined, MAX_DISPLAY_FIELD_CHARS)
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 34 out of 35 changed files in this pull request and generated 3 comments.

Comment thread src/main.rs Outdated
Comment thread src/platform/telegram.rs Outdated
Comment thread src/skills/update.rs Outdated
Comment on lines +108 to +125
if !unmodified {
// Back up the primary file to a sibling path OUTSIDE the dir being replaced.
for f in ["SKILL.md", "AGENT.md"] {
let p = dst.join(f);
if p.is_file() {
let bak = instance.join(format!("{name}.{f}.bak.tmp"));
let _ = tokio::fs::copy(&p, &bak).await;
}
}
let _ = tokio::fs::remove_dir_all(&dst).await;
copy_dir_recursive_pub(&src, &dst).await?;
// Move the temp backups into the freshly-copied dir as <file>.bak
for f in ["SKILL.md", "AGENT.md"] {
let bak = instance.join(format!("{name}.{f}.bak.tmp"));
if bak.is_file() {
let _ = tokio::fs::rename(&bak, dst.join(format!("{f}.bak"))).await;
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in the latest commit. The backup logic now renames the entire instance directory to <name>.bak (removing a stale .bak dir first if one exists) instead of selectively copying only SKILL.md/AGENT.md. This preserves all user files. The docstring and test have been updated to match.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

Claude encountered an error after 1s —— View job


I'll analyze this and get back to you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants