diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..9b04d12 --- /dev/null +++ b/.flake8 @@ -0,0 +1,11 @@ +[flake8] +max-line-length = 88 +extend-ignore = E203, W503 +per-file-ignores = + tests/*:E501,F841 +exclude = + .venv, + build, + dist, + .git, + __pycache__ \ No newline at end of file diff --git a/.gitea/ISSUE_TEMPLATE/bug_report.md b/.gitea/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..c9da631 --- /dev/null +++ b/.gitea/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,35 @@ +--- +name: Bug report +about: Report a defect in kaizen-agentic +title: "[bug] " +labels: bug +--- + +## Summary + + + +## Steps to reproduce + +1. +2. +3. + +## Expected behavior + +## Actual behavior + +## Environment + +- OS: +- Python version: +- kaizen-agentic version (`kaizen-agentic --version`): +- Install method (pip / editable / other): + +## Logs or CLI output + +``` +(paste relevant output) +``` + +## Additional context \ No newline at end of file diff --git a/.gitea/ISSUE_TEMPLATE/config.yaml b/.gitea/ISSUE_TEMPLATE/config.yaml new file mode 100644 index 0000000..d0db62a --- /dev/null +++ b/.gitea/ISSUE_TEMPLATE/config.yaml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Feedback guide + url: https://gitea.coulomb.social/coulomb/kaizen-agentic/src/branch/main/docs/FEEDBACK.md + about: How to submit feedback, bugs, and feature ideas + - name: Contributing guide + url: https://gitea.coulomb.social/coulomb/kaizen-agentic/src/branch/main/CONTRIBUTING.md + about: Development workflow and code standards \ No newline at end of file diff --git a/.gitea/ISSUE_TEMPLATE/feature_request.md b/.gitea/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..1ded630 --- /dev/null +++ b/.gitea/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,23 @@ +--- +name: Feature request +about: Suggest an enhancement for kaizen-agentic +title: "[feature] " +labels: enhancement +--- + +## Problem or opportunity + + + +## Proposed solution + +## Alternatives considered + +## Scope + +- [ ] CLI / framework (`src/kaizen_agentic/`) +- [ ] Agent definitions (`agents/`) +- [ ] Documentation / wiki +- [ ] Ecosystem integration (activity-core, artifact-store, agentic-resources) + +## Additional context \ No newline at end of file diff --git a/.gitea/ISSUE_TEMPLATE/feedback.md b/.gitea/ISSUE_TEMPLATE/feedback.md new file mode 100644 index 0000000..fb6c212 --- /dev/null +++ b/.gitea/ISSUE_TEMPLATE/feedback.md @@ -0,0 +1,21 @@ +--- +name: General feedback +about: Share experience, ideas, or adoption feedback +title: "[feedback] " +labels: feedback +--- + +## Context + + + +## What worked well + +## What was confusing or friction-heavy + +## Suggestions + +## Optional: metrics / telemetry context + +If relevant, note whether you use project metrics (`.kaizen/metrics/`) or Helix Forge +fleet capture โ€” helps us prioritize integration improvements. \ No newline at end of file diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..9c4f709 --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,31 @@ +name: ci + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.10", "3.12"] + steps: + - name: Check out source + uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install package and dev tools + run: python -m pip install --upgrade pip && python -m pip install -e ".[dev]" + + - name: Format check (black) + run: black --check src tests + + - name: Run tests + run: pytest tests/ -q --ignore=tests/test_cli_error_handling.py \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..1f6e034 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,20 @@ +# Pre-commit hooks for kaizen-agentic (WP-0001 T02) +# Install: pip install pre-commit && pre-commit install + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + args: [--unsafe] + - id: check-added-large-files + args: [--maxkb=512] + + - repo: https://github.com/psf/black + rev: 24.10.0 + hooks: + - id: black + language_version: python3 + diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b14dcb..5532419 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - **sys-medic agent**: Linux/Kubernetes node health assessment agent integrated as a standard kaizen-agentic infrastructure agent (KAIZEN-WP-0002 Part 1) - **Ecosystem integration (WP-0004)**: Helix Forge correlation (`metrics correlate`, `HELIX_SESSION_UID` env), artifact-store publish (`metrics publish`), activity-core ActivityDefinition references, integration patterns docs +- **Community engagement (WP-0001 partial)**: `kaizen-agentic feedback` CLI, Gitea issue templates, `.gitea/workflows/ci.yml`, `.pre-commit-config.yaml`, `docs/FEEDBACK.md`, `docs/TELEMETRY.md` - **Project metrics convention (ADR-004)**: `.kaizen/metrics//` storage via `MetricsStore` and `OptimizerStore` - **Metrics CLI**: `kaizen-agentic metrics record|show|list|export|optimize` for per-execution records and optimizer analysis - **Optimizer integration**: `OptimizationLoop.from_metrics_store()` wired to project metrics; `memory brief` includes `## Performance Summary` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 07e6739..2a3d512 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -63,6 +63,8 @@ This repository follows PythonVibes best practices: - **Linting**: Flake8 (`flake8 .`) - **Type Checking**: MyPy (`mypy src/`) - **Testing**: Pytest (`pytest`) +- **Pre-commit**: `pip install pre-commit && pre-commit install` (see `.pre-commit-config.yaml`) +- **CI**: Gitea Actions workflow `.gitea/workflows/ci.yml` runs on push/PR to `main` ### Agent Development Standards For contributing new agents or improving existing ones: @@ -114,6 +116,17 @@ We welcome various types of contributions: - **Testing**: New tests, test improvements, bug reports - **Performance**: Optimization improvements and measurements +## Feedback + +We welcome bugs, feature ideas, and adoption experience reports. + +- **CLI:** `kaizen-agentic feedback` โ€” lists channels and issue templates +- **Guide:** [docs/FEEDBACK.md](docs/FEEDBACK.md) +- **Templates:** `.gitea/ISSUE_TEMPLATE/` (bug, feature, general feedback) + +For cross-repo coordination between custodian agents, use State Hub messages +(`POST /messages/`) โ€” see session protocol in `.claude/rules/session-protocol.md`. + ## Issue Reporting When reporting bugs, please include: diff --git a/Makefile b/Makefile index 280fb74..ff2ccc3 100644 --- a/Makefile +++ b/Makefile @@ -567,11 +567,19 @@ format: $(VENV)/bin/activate clean: @echo "๐Ÿงน Cleaning build artifacts and cache..." @rm -rf build/ dist/ *.egg-info/ .pytest_cache/ __pycache__/ .coverage htmlcov/ + @rm -rf agents_backup_*/ @find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true @find . -type f -name "*.pyc" -delete 2>/dev/null || true @find . -type f -name "*.pyo" -delete 2>/dev/null || true @echo "โœ… Cleanup completed" +# Install pre-commit hooks (WP-0001 T02) +pre-commit-install: $(VENV)/bin/activate + @echo "๐Ÿ”ง Installing pre-commit hooks..." + @$(VENV_PIP) install pre-commit + @$(VENV)/bin/pre-commit install + @echo "โœ… pre-commit installed โ€” run 'pre-commit run --all-files' to verify" + # ============================================================================ # Standards Compliance Targets # ============================================================================ diff --git a/README.md b/README.md index a623d63..2cc91fa 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,9 @@ Read in this order for strategic context: 5. [SCOPE.md](SCOPE.md) โ€” repository boundaries and current state 6. [history/](history/) โ€” persisted assessments and gap analyses -Active workplans: [WP-0003](workplans/kaizen-agentic-WP-0003-measurement-loop.md) (measurement loop), [WP-0004](workplans/kaizen-agentic-WP-0004-ecosystem-integration.md) (ecosystem integration). +Active workplans: [WP-0001](workplans/kaizen-agentic-WP-0001-community-engagement.md) (community engagement โ€” in progress). + +Feedback: `kaizen-agentic feedback` ยท [docs/FEEDBACK.md](docs/FEEDBACK.md) ## Features diff --git a/docs/FEEDBACK.md b/docs/FEEDBACK.md new file mode 100644 index 0000000..9d80ec9 --- /dev/null +++ b/docs/FEEDBACK.md @@ -0,0 +1,41 @@ +# Feedback + +How to share bugs, ideas, and adoption experience for kaizen-agentic. + +## Quick channels + +| Channel | Use for | +|---------|---------| +| **Gitea Issues** | Bugs, features, general feedback (templates below) | +| **`kaizen-agentic feedback`** | Print links and template guidance from the CLI | +| **Pull requests** | Code and agent-definition contributions (see CONTRIBUTING.md) | +| **State Hub messages** | Cross-repo coordination between custodian agents (advanced) | + +## Gitea issue templates + +Choose a template when opening a new issue: + +- **Bug report** โ€” reproducible defects +- **Feature request** โ€” enhancements with proposed scope +- **General feedback** โ€” experience and adoption notes + +Repository: [coulomb/kaizen-agentic](https://gitea.coulomb.social/coulomb/kaizen-agentic/issues) + +## CLI + +```bash +kaizen-agentic feedback # human-readable channel list +kaizen-agentic feedback --json # machine-readable for tooling +``` + +## What helps us most + +- Python version and `kaizen-agentic --version` +- Minimal reproduction steps for bugs +- Which agents you used and whether memory/metrics were enabled +- For integration issues: whether artifact-store, Helix Forge, or activity-core is involved + +## Privacy + +Do not include secrets, tokens, or private project content in public issues. Redact +`.kaizen/` memory contents unless you intentionally share sanitized examples. \ No newline at end of file diff --git a/docs/TELEMETRY.md b/docs/TELEMETRY.md new file mode 100644 index 0000000..9312bb0 --- /dev/null +++ b/docs/TELEMETRY.md @@ -0,0 +1,48 @@ +# Telemetry and Agent Effectiveness Tracking + +WP-0001 T04 design โ€” aligned with ADR-004 and WP-0004 ecosystem integration. + +## Two layers (do not merge) + +| Layer | Question | Mechanism | +|-------|----------|-----------| +| **Project** | How is agent *X* performing in *this repo*? | `kaizen-agentic metrics record` โ†’ `.kaizen/metrics/` | +| **Fleet** | How are coding sessions performing *across repos*? | agentic-resources Helix Forge | + +kaizen-agentic **does not** ship a parallel session transcript ingestion pipeline. + +## Project telemetry (implemented) + +Memory-enabled agents record per-session outcomes at close: + +```bash +kaizen-agentic metrics record --success --time --quality <0-1> +kaizen-agentic metrics optimize [agent] +kaizen-agentic memory brief # includes Performance Summary +``` + +Optional fleet correlation via `HELIX_SESSION_UID` (see +[integrations/helix-forge-correlation.md](integrations/helix-forge-correlation.md)). + +## Fleet telemetry (agentic-resources) + +Helix Forge owns session capture, digest storage, baselines, and weekly retro. +kaizen-agentic consumes correlation fields only. + +## CLI install / usage analytics (future) + +Potential v1.1 additions (not yet implemented): + +- Opt-in anonymous counters on `install` / `memory init` (no PII, no project paths) +- Aggregate effectiveness reports via `metrics list` across a monorepo checkout + +## tele-mcp evaluation (deferred) + +[tele-mcp](https://gitea.coulomb.social/coulomb/tele-mcp) is a candidate MCP adapter +for IDE-level telemetry (WP-0001 note). Assess before depending on it. Project and +fleet layers above satisfy INTENT's "measurable agents" requirement without tele-mcp. + +## Feedback loop + +User experience feedback uses [FEEDBACK.md](FEEDBACK.md) and Gitea issue templates โ€” +separate from execution metrics. \ No newline at end of file diff --git a/src/kaizen_agentic/cli.py b/src/kaizen_agentic/cli.py index b710f76..9d6e64d 100644 --- a/src/kaizen_agentic/cli.py +++ b/src/kaizen_agentic/cli.py @@ -2,7 +2,6 @@ import json import sys -import subprocess import contextlib import io import click @@ -69,17 +68,22 @@ def safe_cli_wrapper(): affected_commands = len(sys.argv) >= 2 and sys.argv[1] in ["install", "update"] try: - with contextlib.redirect_stderr(stderr_capture), contextlib.redirect_stdout(stdout_capture): + with contextlib.redirect_stderr(stderr_capture), contextlib.redirect_stdout( + stdout_capture + ): cli(standalone_mode=False) except click.UsageError as e: if affected_commands and "Got unexpected extra argument" in str(e): # This is the spurious error for install/update commands # Check if we got some stdout output indicating success captured_stdout = stdout_capture.getvalue() - success_indicators = ["Installing agents to:", "Updating all installed agents:"] + success_indicators = [ + "Installing agents to:", + "Updating all installed agents:", + ] if any(indicator in captured_stdout for indicator in success_indicators): # The command was actually executing, show the real output - print(captured_stdout, end='') + print(captured_stdout, end="") sys.exit(0) else: # This might be a real error @@ -96,29 +100,45 @@ def safe_cli_wrapper(): if e.code == 0: # Successful exit - print(captured_stdout, end='') + print(captured_stdout, end="") else: # Error exit - show both stdout and stderr unless it's the spurious error if affected_commands and "Got unexpected extra argument" in captured_stderr: # Show only stdout for install/update commands with spurious errors - print(captured_stdout, end='') - success_indicators = ["Installing agents to:", "Updating all installed agents:"] - if any(indicator in captured_stdout for indicator in success_indicators): + print(captured_stdout, end="") + success_indicators = [ + "Installing agents to:", + "Updating all installed agents:", + ] + if any( + indicator in captured_stdout for indicator in success_indicators + ): sys.exit(0) # Override error exit if we see success indicators else: # Show everything for other commands - print(captured_stdout, end='') - print(captured_stderr, end='', file=sys.stderr) + print(captured_stdout, end="") + print(captured_stderr, end="", file=sys.stderr) sys.exit(e.code) except Exception as e: print(f"Error: {e}") sys.exit(1) # If we get here, show captured output - print(stdout_capture.getvalue(), end='') + print(stdout_capture.getvalue(), end="") stderr_content = stderr_capture.getvalue() - if stderr_content and not (affected_commands and "Got unexpected extra argument" in stderr_content): - print(stderr_content, end='', file=sys.stderr) + if stderr_content and not ( + affected_commands and "Got unexpected extra argument" in stderr_content + ): + print(stderr_content, end="", file=sys.stderr) + + +_FEEDBACK_CHANNELS = { + "issues": "https://gitea.coulomb.social/coulomb/kaizen-agentic/issues", + "issue_templates": "https://gitea.coulomb.social/coulomb/kaizen-agentic/issues/new/choose", + "feedback_guide": "https://gitea.coulomb.social/coulomb/kaizen-agentic/src/branch/main/docs/FEEDBACK.md", + "contributing": "https://gitea.coulomb.social/coulomb/kaizen-agentic/src/branch/main/CONTRIBUTING.md", +} + @click.group() @click.version_option() @@ -127,6 +147,32 @@ def cli(): pass +@cli.command("feedback") +@click.option("--json", "as_json", is_flag=True, help="Emit machine-readable JSON") +def feedback(as_json: bool): + """Show how to submit bugs, ideas, and adoption feedback.""" + payload = { + "channels": _FEEDBACK_CHANNELS, + "templates": ["bug_report", "feature_request", "feedback"], + "cli_hint": "Use Gitea issue templates or State Hub messages for cross-repo coordination", + } + if as_json: + click.echo(json.dumps(payload, indent=2, sort_keys=True)) + return + + click.echo("Kaizen Agentic โ€” feedback channels") + click.echo("=" * 40) + click.echo(f"Issues: {_FEEDBACK_CHANNELS['issues']}") + click.echo(f"New issue: {_FEEDBACK_CHANNELS['issue_templates']}") + click.echo(f"Feedback guide: {_FEEDBACK_CHANNELS['feedback_guide']}") + click.echo(f"Contributing: {_FEEDBACK_CHANNELS['contributing']}") + click.echo() + click.echo("Templates: bug report ยท feature request ยท general feedback") + click.echo( + "Tip: include Python version and `kaizen-agentic --version` in bug reports." + ) + + @cli.command("list") @click.option( "--category", @@ -842,7 +888,9 @@ session_count: 0 registry = _get_registry() protocols_dir = registry.agents_dir / "protocols" / agent_name if protocols_dir.exists(): - slugs = [f.stem for f in sorted(protocols_dir.glob("*.md")) if f.name != "README.md"] + slugs = [ + f.stem for f in sorted(protocols_dir.glob("*.md")) if f.name != "README.md" + ] if slugs: click.echo(f" Protocols available for '{agent_name}':") for slug in slugs: @@ -852,7 +900,9 @@ session_count: 0 @memory.command("brief") @click.argument("agent_name") @click.option("--target", "-t", default=".", help="Project root (default: current)") -@click.option("--raw", is_flag=True, help="Dump raw memory files without synthesis header") +@click.option( + "--raw", is_flag=True, help="Dump raw memory files without synthesis header" +) def memory_brief(agent_name: str, target: str, raw: bool): """Print a coach-synthesised orientation for an agent. @@ -889,6 +939,7 @@ def memory_brief(agent_name: str, target: str, raw: bool): return from datetime import date as _date + today = _date.today().isoformat() sources = ([agent_name] if own_memory else []) + list(other_memories.keys()) @@ -918,7 +969,9 @@ def memory_brief(agent_name: str, target: str, raw: bool): click.echo("### Your Memory") click.echo(own_memory) else: - click.echo(f"### Your Memory\n(none โ€” run: kaizen-agentic memory init {agent_name})\n") + click.echo( + f"### Your Memory\n(none โ€” run: kaizen-agentic memory init {agent_name})\n" + ) # Cross-agent context if other_memories: @@ -928,17 +981,23 @@ def memory_brief(agent_name: str, target: str, raw: bool): click.echo(f"--- {name} ---") click.echo(content) else: - click.echo("### Context From Other Agents\nNo other agent memories found in this project.\n") + click.echo( + "### Context From Other Agents\nNo other agent memories found in this project.\n" + ) click.echo("---") - click.echo("Tip: Load agents/agent-coach.md in your Claude session and pass this output") + click.echo( + "Tip: Load agents/agent-coach.md in your Claude session and pass this output" + ) click.echo(" for a full cross-agent synthesis and orientation brief.") @memory.command("clear") @click.argument("agent_name") @click.option("--target", "-t", default=".", help="Project root (default: current)") -@click.confirmation_option(prompt="This will permanently delete the agent memory. Continue?") +@click.confirmation_option( + prompt="This will permanently delete the agent memory. Continue?" +) def memory_clear(agent_name: str, target: str): """Wipe agent memory for the current project.""" memory_path = _memory_path(target, agent_name) @@ -964,13 +1023,19 @@ def metrics(): @metrics.command("record") @click.argument("agent_name") @click.option("--target", "-t", default=".", help="Project root (default: current)") -@click.option("--success", "outcome_success", is_flag=True, help="Record successful execution") -@click.option("--failure", "outcome_failure", is_flag=True, help="Record failed execution") +@click.option( + "--success", "outcome_success", is_flag=True, help="Record successful execution" +) +@click.option( + "--failure", "outcome_failure", is_flag=True, help="Record failed execution" +) @click.option("--time", "execution_time", type=float, help="Execution time in seconds") @click.option("--quality", type=float, help="Quality score 0.0โ€“1.0") @click.option("--session-id", help="Optional session identifier") @click.option("--idempotency-key", help="Skip append if this key was already recorded") -@click.option("--json", "json_input", is_flag=True, help="Read full record JSON from stdin") +@click.option( + "--json", "json_input", is_flag=True, help="Read full record JSON from stdin" +) def metrics_record( agent_name: str, target: str, @@ -995,7 +1060,9 @@ def metrics_record( click.echo("Error: use only one of --success or --failure", err=True) sys.exit(1) if not outcome_success and not outcome_failure: - click.echo("Error: specify --success or --failure (or use --json)", err=True) + click.echo( + "Error: specify --success or --failure (or use --json)", err=True + ) sys.exit(1) payload = {"success": outcome_success} if execution_time is not None: @@ -1010,13 +1077,17 @@ def metrics_record( if store.append(payload, idempotency_key=idempotency_key): click.echo(f"Recorded metrics for '{agent_name}'") else: - click.echo(f"Skipped duplicate record for '{agent_name}' (idempotency key exists)") + click.echo( + f"Skipped duplicate record for '{agent_name}' (idempotency key exists)" + ) @metrics.command("show") @click.argument("agent_name") @click.option("--target", "-t", default=".", help="Project root (default: current)") -@click.option("--limit", "-n", default=5, show_default=True, help="Recent executions to show") +@click.option( + "--limit", "-n", default=5, show_default=True, help="Recent executions to show" +) def metrics_show(agent_name: str, target: str, limit: int): """Print metrics summary and recent executions for an agent.""" store = MetricsStore(_project_root(target), agent_name) @@ -1073,7 +1144,9 @@ def metrics_optimize(agent_name: Optional[str], target: str, min_samples: int): if not agents: click.echo("No agent metrics found to optimize.") - click.echo(" Record executions with: kaizen-agentic metrics record --success") + click.echo( + " Record executions with: kaizen-agentic metrics record --success" + ) return optimizer_store = OptimizerStore(project_root) @@ -1287,6 +1360,7 @@ def _memory_path(target: str, agent_name: str) -> Path: def _today() -> str: from datetime import date + return date.today().isoformat() @@ -1312,14 +1386,20 @@ def _get_registry() -> AgentRegistry: # Try relative to package agents_dir = Path(kaizen_agentic.__file__).parent / "data" / "agents" except ImportError: - click.echo("Error: Could not find agents directory") - click.echo( - "Make sure you're in a kaizen-agentic project or have the package installed" - ) + click.echo("Error: kaizen-agentic package is not installed.", err=True) + click.echo(" Fix: pip install -e . (from repo root)", err=True) + click.echo(" Or: run from a project with an agents/ directory", err=True) sys.exit(1) if not agents_dir.exists(): - click.echo(f"Error: Agents directory not found: {agents_dir}") + click.echo(f"Error: agents directory not found: {agents_dir}", err=True) + click.echo( + " Fix: cd into a kaizen-agentic checkout or a project with agents/", + err=True, + ) + click.echo( + " Or: kaizen-agentic install