diff --git a/.github/workflows/supply-chain-audit.yml b/.github/workflows/supply-chain-audit.yml index b94e1dda4333..8653bef7420c 100644 --- a/.github/workflows/supply-chain-audit.yml +++ b/.github/workflows/supply-chain-audit.yml @@ -166,6 +166,7 @@ jobs: - name: Post warning comment if: steps.scan.outputs.found == 'true' + continue-on-error: true env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | diff --git a/cli.py b/cli.py index de21d81e502f..1e61acf0409d 100644 --- a/cli.py +++ b/cli.py @@ -3942,6 +3942,67 @@ def _parse_flags(tokens): print(f"(._.) Unknown cron command: {subcommand}") print(" Available: list, add, edit, pause, resume, run, remove") + def _handle_make_index_command(self, cmd: str): + """Handle /make-index command to generate vault topic indexes.""" + import subprocess + import shlex + + # Parse arguments + parts = shlex.split(cmd)[1:] if len(shlex.split(cmd)) > 1 else [] + folder = parts[0] if parts else "Clippings" + + # Handle stats option + if folder == "stats" or folder == "--stats": + result = subprocess.run( + ["python3", str(Path.home() / ".hermes/skills/make-index/script.py"), "--stats"], + capture_output=True, text=True + ) + print(result.stdout) + return + + # Run the index generator + result = subprocess.run( + ["python3", str(Path.home() / ".hermes/skills/make-index/script.py"), folder], + capture_output=True, text=True + ) + + if result.returncode == 0: + print(result.stdout) + print(f"\n✅ Index generated! Opening in Obsidian...") + # Open the INDEX.md file + vault_path = Path.home() / "Documents" / "great-vault" + index_path = vault_path / folder / "INDEX.md" + if index_path.exists(): + subprocess.run(["open", str(index_path)]) + else: + print(f"❌ Error: {result.stderr}") + + def _handle_kb_command(self, cmd: str): + """Handle /kb command for Knowledge Base v2.""" + import subprocess + import shlex + + # Parse arguments + parts = shlex.split(cmd)[1:] if len(shlex.split(cmd)) > 1 else [] + subcommand = parts[0] if parts else "status" + + # Build the command + vault_path = Path.home() / "Documents" / "great-vault" + kb_script = vault_path / ".kb" / "scripts" / "cli.py" + + # Run the KB CLI + result = subprocess.run( + ["python3", str(kb_script)] + parts, + capture_output=True, text=True + ) + + if result.returncode == 0: + print(result.stdout) + else: + print(f"❌ Error: {result.stderr}") + if result.stdout: + print(result.stdout) + def _handle_skills_command(self, cmd: str): """Handle /skills slash command — delegates to hermes_cli.skills_hub.""" from hermes_cli.skills_hub import handle_skills_slash @@ -4160,6 +4221,10 @@ def process_command(self, command: str) -> bool: elif canonical == "skills": with self._busy_command(self._slow_command_status(cmd_original)): self._handle_skills_command(cmd_original) + elif canonical == "make-index": + self._handle_make_index_command(cmd_original) + elif canonical == "kb": + self._handle_kb_command(cmd_original) elif canonical == "platforms": self._show_gateway_status() elif canonical == "statusbar": diff --git a/cron/scheduler.py b/cron/scheduler.py index 8a54520a14fb..a3db1561f378 100644 --- a/cron/scheduler.py +++ b/cron/scheduler.py @@ -234,17 +234,9 @@ def _build_job_prompt(job: dict) -> str: prompt = job.get("prompt", "") skills = job.get("skills") - # Always prepend [SILENT] guidance so the cron agent can suppress - # delivery when it has nothing new or noteworthy to report. - silent_hint = ( - "[SYSTEM: If you have a meaningful status report or findings, " - "send them — that is the whole point of this job. Only respond " - "with exactly \"[SILENT]\" (nothing else) when there is genuinely " - "nothing new to report. [SILENT] suppresses delivery to the user. " - "Never combine [SILENT] with content — either report your " - "findings normally, or say [SILENT] and nothing more.]\n\n" - ) - prompt = silent_hint + prompt + # NOTE: [SILENT] guidance removed - job prompts already contain their own + # delivery instructions. This was causing conflicts where jobs that should + # ALWAYS produce output were getting truncated due to mixed instructions. if skills is None: legacy = job.get("skill") skills = [legacy] if legacy else [] diff --git a/hermes_cli/commands.py b/hermes_cli/commands.py index 07a8f5e1ebfd..d443dc3381e3 100644 --- a/hermes_cli/commands.py +++ b/hermes_cli/commands.py @@ -123,6 +123,14 @@ class CommandDef: subcommands=("connect", "disconnect", "status")), CommandDef("plugins", "List installed plugins and their status", "Tools & Skills", cli_only=True), + CommandDef("make-index", "Generate topic index for vault folders", + "Tools & Skills", cli_only=True, + args_hint="[folder_name]", + subcommands=("Clippings", "DeepResearchReports", "YT Research Reports", "Personal Tech Deep Dives", "stats")), + CommandDef("kb", "Knowledge Base v2: compile, query, lint, stats", + "Tools & Skills", + args_hint="[command]", + subcommands=("compile", "query", "lint", "stats", "status", "output")), # Info CommandDef("commands", "Browse all commands and skills (paginated)", "Info", @@ -138,6 +146,18 @@ class CommandDef: CommandDef("update", "Update Hermes Agent to the latest version", "Info", gateway_only=True), + # GSD Workflow + CommandDef("gsd", "GSD project workflow commands", "Project", + subcommands=("init", "map", "autonomous", "executor", "verifier", "status", "next")), + CommandDef("gsd:init", "Initialize a new GSD project", "Project"), + CommandDef("gsd:map", "Analyze existing codebase before planning", "Project"), + CommandDef("gsd:autonomous", "Run all GSD phases autonomously", "Project", + args_hint="[--from N]"), + CommandDef("gsd:executor", "Execute GSD phase plans via subagents", "Project", + args_hint=""), + CommandDef("gsd:verifier", "Verify GSD phase against success criteria", "Project", + args_hint=""), + # Exit CommandDef("quit", "Exit the CLI", "Exit", cli_only=True, aliases=("exit", "q")),