tigerharness 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tigerharness-0.1.0/.gitignore +13 -0
- tigerharness-0.1.0/CONTRIBUTING.md +140 -0
- tigerharness-0.1.0/LICENSE +21 -0
- tigerharness-0.1.0/PKG-INFO +191 -0
- tigerharness-0.1.0/README.md +146 -0
- tigerharness-0.1.0/docs/DESIGN.md +154 -0
- tigerharness-0.1.0/docs/slack-bridge.md +102 -0
- tigerharness-0.1.0/docs/task-runner.md +166 -0
- tigerharness-0.1.0/docs/tiger-memory.md +143 -0
- tigerharness-0.1.0/examples/env.example +21 -0
- tigerharness-0.1.0/examples/personas/researcher.md +19 -0
- tigerharness-0.1.0/examples/tiger-memory.config.yaml +41 -0
- tigerharness-0.1.0/pyproject.toml +98 -0
- tigerharness-0.1.0/skills/assign-task/SKILL.md +85 -0
- tigerharness-0.1.0/skills/lab-notebook-quarter-roll/SKILL.md +26 -0
- tigerharness-0.1.0/skills/slack-notify/SKILL.md +53 -0
- tigerharness-0.1.0/skills/tiger-memory-drill-down/SKILL.md +45 -0
- tigerharness-0.1.0/skills/tiger-memory-search/SKILL.md +28 -0
- tigerharness-0.1.0/src/tigerharness/__init__.py +9 -0
- tigerharness-0.1.0/src/tigerharness/agent_sdk/README.md +231 -0
- tigerharness-0.1.0/src/tigerharness/agent_sdk/__init__.py +131 -0
- tigerharness-0.1.0/src/tigerharness/agent_sdk/backends/__init__.py +5 -0
- tigerharness-0.1.0/src/tigerharness/agent_sdk/backends/_base.py +82 -0
- tigerharness-0.1.0/src/tigerharness/agent_sdk/backends/anthropic_sdk.py +567 -0
- tigerharness-0.1.0/src/tigerharness/agent_sdk/backends/claude_p.py +657 -0
- tigerharness-0.1.0/src/tigerharness/agent_sdk/backends/openai_sdk.py +43 -0
- tigerharness-0.1.0/src/tigerharness/agent_sdk/docs/HANDOFF.md +539 -0
- tigerharness-0.1.0/src/tigerharness/agent_sdk/docs/agent_sdk_comparison.md +727 -0
- tigerharness-0.1.0/src/tigerharness/agent_sdk/errors.py +38 -0
- tigerharness-0.1.0/src/tigerharness/agent_sdk/examples/__init__.py +0 -0
- tigerharness-0.1.0/src/tigerharness/agent_sdk/examples/basic.py +27 -0
- tigerharness-0.1.0/src/tigerharness/agent_sdk/examples/builtin_tools.py +58 -0
- tigerharness-0.1.0/src/tigerharness/agent_sdk/examples/multi_turn.py +36 -0
- tigerharness-0.1.0/src/tigerharness/agent_sdk/examples/streaming.py +59 -0
- tigerharness-0.1.0/src/tigerharness/agent_sdk/factory.py +86 -0
- tigerharness-0.1.0/src/tigerharness/agent_sdk/retry.py +125 -0
- tigerharness-0.1.0/src/tigerharness/agent_sdk/types.py +353 -0
- tigerharness-0.1.0/src/tigerharness/cli.py +60 -0
- tigerharness-0.1.0/src/tigerharness/init.py +182 -0
- tigerharness-0.1.0/src/tigerharness/py.typed +0 -0
- tigerharness-0.1.0/src/tigerharness/slack_bridge/__init__.py +5 -0
- tigerharness-0.1.0/src/tigerharness/slack_bridge/__main__.py +89 -0
- tigerharness-0.1.0/src/tigerharness/slack_bridge/bridge.py +346 -0
- tigerharness-0.1.0/src/tigerharness/slack_bridge/config.py +91 -0
- tigerharness-0.1.0/src/tigerharness/slack_bridge/downloader.py +163 -0
- tigerharness-0.1.0/src/tigerharness/slack_bridge/notify.py +337 -0
- tigerharness-0.1.0/src/tigerharness/slack_bridge/persistence.py +104 -0
- tigerharness-0.1.0/src/tigerharness/task_runner/__init__.py +6 -0
- tigerharness-0.1.0/src/tigerharness/task_runner/__main__.py +7 -0
- tigerharness-0.1.0/src/tigerharness/task_runner/cli.py +587 -0
- tigerharness-0.1.0/src/tigerharness/task_runner/notifier.py +307 -0
- tigerharness-0.1.0/src/tigerharness/task_runner/personas.py +213 -0
- tigerharness-0.1.0/src/tigerharness/task_runner/registry.py +211 -0
- tigerharness-0.1.0/src/tigerharness/task_runner/runner.py +1051 -0
- tigerharness-0.1.0/src/tigerharness/task_runner/stuck_watchdog.py +567 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/__init__.py +11 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/briefing.py +356 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/cli.py +158 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/config.py +336 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/drill.py +390 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/embedders.py +135 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/frontmatter.py +65 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/lifecycle.py +951 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/must_memorize.py +372 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/rag.py +204 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/sources/__init__.py +27 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/sources/base.py +40 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/sources/claude_transcript.py +310 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/sources/docs.py +97 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/state.py +123 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/store.py +330 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/summarizers/__init__.py +19 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/summarizers/anthropic.py +115 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/summarizers/base.py +45 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/summarizers/mock.py +28 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/summarizers/prompts/default/v1/daily_rollup.md +20 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/summarizers/prompts/default/v1/detailed_summary.md +40 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/summarizers/prompts/default/v1/longer_memory.md +24 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/summarizers/prompts/default/v1/monthly_rollup.md +30 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/summarizers/prompts/default/v1/must_memorize_extract.md +41 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/summarizers/prompts/default/v1/short_summary.md +30 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/summarizers/prompts/default/v1/weekly_rollup.md +27 -0
- tigerharness-0.1.0/src/tigerharness/tiger_memory/templates/briefing_readme.md +71 -0
- tigerharness-0.1.0/tests/__init__.py +0 -0
- tigerharness-0.1.0/tests/agent_sdk/__init__.py +0 -0
- tigerharness-0.1.0/tests/agent_sdk/_helpers.py +30 -0
- tigerharness-0.1.0/tests/agent_sdk/conftest.py +295 -0
- tigerharness-0.1.0/tests/agent_sdk/test_anthropic_sdk.py +1029 -0
- tigerharness-0.1.0/tests/agent_sdk/test_base.py +175 -0
- tigerharness-0.1.0/tests/agent_sdk/test_claude_p.py +889 -0
- tigerharness-0.1.0/tests/agent_sdk/test_errors.py +46 -0
- tigerharness-0.1.0/tests/agent_sdk/test_examples.py +22 -0
- tigerharness-0.1.0/tests/agent_sdk/test_factory.py +111 -0
- tigerharness-0.1.0/tests/agent_sdk/test_retry.py +174 -0
- tigerharness-0.1.0/tests/agent_sdk/test_stub_backends.py +29 -0
- tigerharness-0.1.0/tests/agent_sdk/test_types.py +313 -0
- tigerharness-0.1.0/tests/slack_bridge/__init__.py +0 -0
- tigerharness-0.1.0/tests/slack_bridge/test_bridge.py +280 -0
- tigerharness-0.1.0/tests/slack_bridge/test_bridge_coverage.py +140 -0
- tigerharness-0.1.0/tests/slack_bridge/test_bridge_extra.py +123 -0
- tigerharness-0.1.0/tests/slack_bridge/test_config.py +74 -0
- tigerharness-0.1.0/tests/slack_bridge/test_downloader.py +150 -0
- tigerharness-0.1.0/tests/slack_bridge/test_main_coverage.py +157 -0
- tigerharness-0.1.0/tests/slack_bridge/test_main_extra.py +62 -0
- tigerharness-0.1.0/tests/slack_bridge/test_notify.py +334 -0
- tigerharness-0.1.0/tests/slack_bridge/test_notify_extra.py +214 -0
- tigerharness-0.1.0/tests/slack_bridge/test_persistence.py +70 -0
- tigerharness-0.1.0/tests/slack_bridge/test_persistence_extra.py +33 -0
- tigerharness-0.1.0/tests/task_runner/__init__.py +0 -0
- tigerharness-0.1.0/tests/task_runner/test_cli.py +270 -0
- tigerharness-0.1.0/tests/task_runner/test_cli_coverage.py +161 -0
- tigerharness-0.1.0/tests/task_runner/test_cli_extra.py +148 -0
- tigerharness-0.1.0/tests/task_runner/test_notifier.py +381 -0
- tigerharness-0.1.0/tests/task_runner/test_notifier_coverage.py +96 -0
- tigerharness-0.1.0/tests/task_runner/test_notifier_extra.py +191 -0
- tigerharness-0.1.0/tests/task_runner/test_personas.py +140 -0
- tigerharness-0.1.0/tests/task_runner/test_registry.py +144 -0
- tigerharness-0.1.0/tests/task_runner/test_runner.py +647 -0
- tigerharness-0.1.0/tests/task_runner/test_runner_classify_close.py +67 -0
- tigerharness-0.1.0/tests/task_runner/test_runner_coverage.py +274 -0
- tigerharness-0.1.0/tests/task_runner/test_stuck_watchdog.py +881 -0
- tigerharness-0.1.0/tests/task_runner/test_stuck_watchdog_coverage.py +547 -0
- tigerharness-0.1.0/tests/task_runner/test_stuck_watchdog_integration.py +584 -0
- tigerharness-0.1.0/tests/test_branch_partials.py +251 -0
- tigerharness-0.1.0/tests/test_cli.py +61 -0
- tigerharness-0.1.0/tests/test_coverage_final2.py +254 -0
- tigerharness-0.1.0/tests/test_coverage_final3.py +359 -0
- tigerharness-0.1.0/tests/test_entry_points.py +21 -0
- tigerharness-0.1.0/tests/test_final_coverage.py +312 -0
- tigerharness-0.1.0/tests/test_init.py +112 -0
- tigerharness-0.1.0/tests/test_main_modules.py +64 -0
- tigerharness-0.1.0/tests/tiger_memory/__init__.py +0 -0
- tigerharness-0.1.0/tests/tiger_memory/conftest.py +66 -0
- tigerharness-0.1.0/tests/tiger_memory/test_anthropic_summarizer.py +117 -0
- tigerharness-0.1.0/tests/tiger_memory/test_briefing.py +123 -0
- tigerharness-0.1.0/tests/tiger_memory/test_briefing_coverage.py +148 -0
- tigerharness-0.1.0/tests/tiger_memory/test_briefing_read_filter.py +157 -0
- tigerharness-0.1.0/tests/tiger_memory/test_briefing_rebuild.py +215 -0
- tigerharness-0.1.0/tests/tiger_memory/test_briefing_rebuild_polish.py +155 -0
- tigerharness-0.1.0/tests/tiger_memory/test_briefing_stale.py +155 -0
- tigerharness-0.1.0/tests/tiger_memory/test_claude_transcript_extra.py +219 -0
- tigerharness-0.1.0/tests/tiger_memory/test_cli.py +175 -0
- tigerharness-0.1.0/tests/tiger_memory/test_config.py +146 -0
- tigerharness-0.1.0/tests/tiger_memory/test_coverage_push.py +289 -0
- tigerharness-0.1.0/tests/tiger_memory/test_docs_coverage.py +80 -0
- tigerharness-0.1.0/tests/tiger_memory/test_docs_source.py +123 -0
- tigerharness-0.1.0/tests/tiger_memory/test_drill.py +183 -0
- tigerharness-0.1.0/tests/tiger_memory/test_drill_coverage2.py +234 -0
- tigerharness-0.1.0/tests/tiger_memory/test_drill_extra.py +354 -0
- tigerharness-0.1.0/tests/tiger_memory/test_embedders.py +90 -0
- tigerharness-0.1.0/tests/tiger_memory/test_embedders_extra.py +85 -0
- tigerharness-0.1.0/tests/tiger_memory/test_frontmatter.py +33 -0
- tigerharness-0.1.0/tests/tiger_memory/test_frontmatter_extra.py +58 -0
- tigerharness-0.1.0/tests/tiger_memory/test_lifecycle.py +190 -0
- tigerharness-0.1.0/tests/tiger_memory/test_lifecycle_coverage.py +268 -0
- tigerharness-0.1.0/tests/tiger_memory/test_lifecycle_coverage2.py +384 -0
- tigerharness-0.1.0/tests/tiger_memory/test_lifecycle_full.py +608 -0
- tigerharness-0.1.0/tests/tiger_memory/test_must_memorize.py +188 -0
- tigerharness-0.1.0/tests/tiger_memory/test_must_memorize_extra.py +268 -0
- tigerharness-0.1.0/tests/tiger_memory/test_rag.py +176 -0
- tigerharness-0.1.0/tests/tiger_memory/test_remaining_coverage.py +293 -0
- tigerharness-0.1.0/tests/tiger_memory/test_sources.py +120 -0
- tigerharness-0.1.0/tests/tiger_memory/test_state.py +153 -0
- tigerharness-0.1.0/tests/tiger_memory/test_store.py +165 -0
- tigerharness-0.1.0/tests/tiger_memory/test_store_coverage.py +160 -0
- tigerharness-0.1.0/tests/tiger_memory/test_store_extra.py +166 -0
- tigerharness-0.1.0/tests/tiger_memory/test_store_lock.py +99 -0
- tigerharness-0.1.0/tests/tiger_memory/test_summarizers.py +30 -0
- tigerharness-0.1.0/tests/tiger_memory/test_transcript_coverage.py +76 -0
- tigerharness-0.1.0/tests/tiger_memory/test_v05_pass2.py +127 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Contributing to tigerharness
|
|
2
|
+
|
|
3
|
+
## Development setup
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
git clone https://github.com/DingyuZhou/TigerHarness.git
|
|
7
|
+
cd tigerharness
|
|
8
|
+
uv sync --extra all
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Running tests
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# All tests
|
|
15
|
+
uv run pytest
|
|
16
|
+
|
|
17
|
+
# With coverage report
|
|
18
|
+
uv run pytest --cov=tigerharness --cov-report=term-missing
|
|
19
|
+
|
|
20
|
+
# Single module
|
|
21
|
+
uv run pytest tests/tiger_memory/test_lifecycle_full.py -v
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Coverage threshold: **98.5%** (enforced in `pyproject.toml`). Current: **98.60%** (1088 tests).
|
|
25
|
+
|
|
26
|
+
## Project structure
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
src/tigerharness/
|
|
30
|
+
__init__.py Top-level package
|
|
31
|
+
cli.py Unified CLI entry point
|
|
32
|
+
init.py Project scaffolding (tigerharness init)
|
|
33
|
+
py.typed PEP 561 type stub marker
|
|
34
|
+
task_runner/ Iterative task execution
|
|
35
|
+
cli.py CLI subcommands (assign, list, cancel, logs)
|
|
36
|
+
runner.py Core iteration loop
|
|
37
|
+
notifier.py Slack DM notifications
|
|
38
|
+
personas.py Config-driven persona registry
|
|
39
|
+
registry.py Task state persistence
|
|
40
|
+
slack_bridge/ Slack Socket Mode bridge
|
|
41
|
+
bridge.py Event handler + dispatch
|
|
42
|
+
config.py Env-var-driven config loader
|
|
43
|
+
downloader.py File attachment download
|
|
44
|
+
notify.py Outbound DM/file CLI
|
|
45
|
+
persistence.py Thread -> session mapping
|
|
46
|
+
tiger_memory/ Persistent memory management
|
|
47
|
+
cli.py CLI (init, rebuild, search, drill, pin)
|
|
48
|
+
config.py YAML config loader
|
|
49
|
+
lifecycle.py Bootstrap / rebuild / resummarize engine
|
|
50
|
+
briefing.py Layered briefing rebuild
|
|
51
|
+
drill.py Read commands (drill, tree, raw, search)
|
|
52
|
+
store.py On-disk store + atomic write + locking
|
|
53
|
+
must_memorize.py Scored memo table with decay
|
|
54
|
+
rag.py Embedding-based semantic search
|
|
55
|
+
embedders.py Pluggable embedding backends
|
|
56
|
+
frontmatter.py YAML frontmatter parser/writer
|
|
57
|
+
sources/ Source adapters (claude_code, docs)
|
|
58
|
+
summarizers/ Summarizer backends (anthropic, mock)
|
|
59
|
+
templates/ Briefing README template
|
|
60
|
+
tests/
|
|
61
|
+
task_runner/ Task runner tests
|
|
62
|
+
slack_bridge/ Slack bridge tests
|
|
63
|
+
tiger_memory/ Tiger memory tests
|
|
64
|
+
test_main_modules.py __main__.py entrypoint tests
|
|
65
|
+
examples/
|
|
66
|
+
tiger-memory.config.yaml Sample memory config (annotated)
|
|
67
|
+
personas/researcher.md Sample persona prompt
|
|
68
|
+
env.example Slack bridge env template
|
|
69
|
+
docs/
|
|
70
|
+
DESIGN.md Architecture decisions + migration notes
|
|
71
|
+
task-runner.md Task runner module README
|
|
72
|
+
slack-bridge.md Slack bridge module README
|
|
73
|
+
tiger-memory.md Tiger memory module README
|
|
74
|
+
skills/ Claude Code SKILL.md definitions
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Adding a new module
|
|
78
|
+
|
|
79
|
+
1. Create `src/tigerharness/<module>/` with `__init__.py`.
|
|
80
|
+
2. Add tests in `tests/<module>/`.
|
|
81
|
+
3. If it has CLI commands, add a `cli.py` and wire into `src/tigerharness/cli.py`.
|
|
82
|
+
4. If it has optional dependencies, add an extra in `pyproject.toml`.
|
|
83
|
+
5. Write a module README in `docs/<module>.md`.
|
|
84
|
+
6. Run `uv run pytest --cov=tigerharness --cov-report=term-missing` and verify coverage.
|
|
85
|
+
|
|
86
|
+
## Adding a custom persona
|
|
87
|
+
|
|
88
|
+
1. Create a markdown file in your personas directory (e.g., `personas/analyst.md`).
|
|
89
|
+
2. Set `TIGERHARNESS_PERSONAS_DIR` to point to that directory.
|
|
90
|
+
3. Use `python -m tigerharness.task_runner assign --to analyst --prompt "..."`.
|
|
91
|
+
|
|
92
|
+
See `examples/personas/researcher.md` for a template.
|
|
93
|
+
|
|
94
|
+
## Adding a custom memory backend
|
|
95
|
+
|
|
96
|
+
Tiger-memory's summarizer is pluggable:
|
|
97
|
+
|
|
98
|
+
1. Subclass `tigerharness.tiger_memory.summarizers.base.Summarizer`.
|
|
99
|
+
2. Implement `summarize(prompt, max_words) -> str` and `cost_estimate_usd(...)`.
|
|
100
|
+
3. Register in `_build_summarizer()` in `lifecycle.py` (or propose a plugin hook).
|
|
101
|
+
|
|
102
|
+
## Code style
|
|
103
|
+
|
|
104
|
+
- Python 3.11+
|
|
105
|
+
- Type hints on all public APIs
|
|
106
|
+
- Docstrings on all modules and public functions
|
|
107
|
+
- No hardcoded paths -- everything via env vars or config
|
|
108
|
+
- Tests use `tmp_path` fixtures for filesystem isolation
|
|
109
|
+
- Mock external services (Slack, Anthropic, subprocess) in tests
|
|
110
|
+
|
|
111
|
+
## Commit conventions
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
<prefix>: <imperative summary, 72 chars max>
|
|
115
|
+
|
|
116
|
+
<body>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Prefix: `feat:`, `fix:`, `test:`, `docs:`, `refactor:`
|
|
120
|
+
|
|
121
|
+
## Running a single sub-package
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# Task runner
|
|
125
|
+
python -m tigerharness.task_runner --help
|
|
126
|
+
|
|
127
|
+
# Slack bridge (daemon)
|
|
128
|
+
python -m tigerharness.slack_bridge
|
|
129
|
+
|
|
130
|
+
# Tiger memory
|
|
131
|
+
tiger-memory --help
|
|
132
|
+
# or: python -m tigerharness.tiger_memory.cli --help
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Building
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
uv build
|
|
139
|
+
# Creates dist/tigerharness-0.1.0-py3-none-any.whl
|
|
140
|
+
```
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 tigerharness contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tigerharness
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A generic Claude Code agent harness: iterative task execution, Slack integration, and persistent memory management.
|
|
5
|
+
Project-URL: Repository, https://github.com/DingyuZhou/TigerHarness
|
|
6
|
+
Project-URL: Issues, https://github.com/DingyuZhou/TigerHarness/issues
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Keywords: agent,anthropic,claude,harness,memory,task-runner
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Provides-Extra: all
|
|
20
|
+
Requires-Dist: aiohttp>=3.9; extra == 'all'
|
|
21
|
+
Requires-Dist: claude-agent-sdk>=0.1.0; extra == 'all'
|
|
22
|
+
Requires-Dist: fastembed>=0.4; extra == 'all'
|
|
23
|
+
Requires-Dist: openai>=1.0; extra == 'all'
|
|
24
|
+
Requires-Dist: python-dotenv>=1.0; extra == 'all'
|
|
25
|
+
Requires-Dist: pyyaml>=6.0; extra == 'all'
|
|
26
|
+
Requires-Dist: slack-bolt<2.0,>=1.18; extra == 'all'
|
|
27
|
+
Requires-Dist: sqlite-vec>=0.1; extra == 'all'
|
|
28
|
+
Provides-Extra: anthropic
|
|
29
|
+
Requires-Dist: claude-agent-sdk>=0.1.0; extra == 'anthropic'
|
|
30
|
+
Provides-Extra: memory
|
|
31
|
+
Requires-Dist: pyyaml>=6.0; extra == 'memory'
|
|
32
|
+
Provides-Extra: memory-rag
|
|
33
|
+
Requires-Dist: fastembed>=0.4; extra == 'memory-rag'
|
|
34
|
+
Requires-Dist: pyyaml>=6.0; extra == 'memory-rag'
|
|
35
|
+
Requires-Dist: sqlite-vec>=0.1; extra == 'memory-rag'
|
|
36
|
+
Provides-Extra: memory-rag-openai
|
|
37
|
+
Requires-Dist: openai>=1.0; extra == 'memory-rag-openai'
|
|
38
|
+
Requires-Dist: pyyaml>=6.0; extra == 'memory-rag-openai'
|
|
39
|
+
Requires-Dist: sqlite-vec>=0.1; extra == 'memory-rag-openai'
|
|
40
|
+
Provides-Extra: slack
|
|
41
|
+
Requires-Dist: aiohttp>=3.9; extra == 'slack'
|
|
42
|
+
Requires-Dist: python-dotenv>=1.0; extra == 'slack'
|
|
43
|
+
Requires-Dist: slack-bolt<2.0,>=1.18; extra == 'slack'
|
|
44
|
+
Description-Content-Type: text/markdown
|
|
45
|
+
|
|
46
|
+
# tigerharness
|
|
47
|
+
|
|
48
|
+
A generic Claude Code agent harness: iterative task execution, Slack
|
|
49
|
+
integration, and persistent memory management.
|
|
50
|
+
|
|
51
|
+
## Sub-packages
|
|
52
|
+
|
|
53
|
+
| Package | Description |
|
|
54
|
+
|---|---|
|
|
55
|
+
| `tigerharness.agent_sdk` | Backend-agnostic agent SDK. Same caller code, swappable runtimes: `claude -p` subprocess, Anthropic's `claude-agent-sdk`, OpenAI's `openai-agents` (planned). |
|
|
56
|
+
| `tigerharness.task_runner` | Fire-and-forget iterative task execution. Drives a persona through N Claude turns with periodic `/compact`. |
|
|
57
|
+
| `tigerharness.slack_bridge` | Slack Socket Mode bridge. Forwards DMs to a `claude -p` backend and posts replies back to the thread. |
|
|
58
|
+
| `tigerharness.tiger_memory` | Persistent agent memory: archive, journal, briefing with lazy rebuild, kind-decay must-memorize, and drill-down. |
|
|
59
|
+
|
|
60
|
+
## Installation
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Core (claude -p backend only; Claude Code CLI must be on PATH)
|
|
64
|
+
pip install tigerharness
|
|
65
|
+
|
|
66
|
+
# With the official claude-agent-sdk backend
|
|
67
|
+
pip install tigerharness[anthropic]
|
|
68
|
+
|
|
69
|
+
# With Slack bridge support
|
|
70
|
+
pip install tigerharness[slack]
|
|
71
|
+
|
|
72
|
+
# With memory support
|
|
73
|
+
pip install tigerharness[memory]
|
|
74
|
+
|
|
75
|
+
# With memory + RAG (local embeddings, free)
|
|
76
|
+
pip install tigerharness[memory-rag]
|
|
77
|
+
|
|
78
|
+
# Everything
|
|
79
|
+
pip install tigerharness[all]
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Or with uv:
|
|
83
|
+
```bash
|
|
84
|
+
uv add tigerharness
|
|
85
|
+
uv add tigerharness --extra all
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Quick start
|
|
89
|
+
|
|
90
|
+
### Scaffold a new project
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Create config files in the current directory
|
|
94
|
+
tigerharness init --name researcher
|
|
95
|
+
|
|
96
|
+
# Or with tiger-memory support
|
|
97
|
+
tigerharness init --name researcher --memory
|
|
98
|
+
|
|
99
|
+
# This creates:
|
|
100
|
+
# personas/researcher.md -- edit your agent's instructions
|
|
101
|
+
# .env -- fill in Slack tokens
|
|
102
|
+
# tiger-memory.config.yaml -- (only with --memory)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Task runner
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# 1. Point tigerharness at your personas directory
|
|
109
|
+
export TIGERHARNESS_PERSONAS_DIR=./personas
|
|
110
|
+
|
|
111
|
+
# 2. Assign a task (5 iterations)
|
|
112
|
+
python -m tigerharness.task_runner assign \
|
|
113
|
+
--to researcher \
|
|
114
|
+
--prompt "Research the latest developments in solar energy" \
|
|
115
|
+
--iters 5
|
|
116
|
+
|
|
117
|
+
# 3. Check status
|
|
118
|
+
python -m tigerharness.task_runner list
|
|
119
|
+
|
|
120
|
+
# 4. View logs
|
|
121
|
+
python -m tigerharness.task_runner logs <task-id>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Slack bridge
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# 1. Fill in your Slack tokens in .env (from api.slack.com)
|
|
128
|
+
# SLACK_APP_TOKEN=xapp-...
|
|
129
|
+
# SLACK_BOT_TOKEN=xoxb-...
|
|
130
|
+
# ALLOWED_SLACK_USER_IDS=U0123ABC
|
|
131
|
+
|
|
132
|
+
# 2. Run the bridge
|
|
133
|
+
python -m tigerharness.slack_bridge
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Tiger memory
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# 1. Copy the example config
|
|
140
|
+
cp examples/tiger-memory.config.yaml tiger-memory.config.yaml
|
|
141
|
+
# Edit: set store.root and sources.project_path
|
|
142
|
+
|
|
143
|
+
# 2. Initialize the memory store
|
|
144
|
+
tiger-memory --config tiger-memory.config.yaml init
|
|
145
|
+
|
|
146
|
+
# 3. Bootstrap (one-time backfill from existing transcripts)
|
|
147
|
+
tiger-memory --config tiger-memory.config.yaml bootstrap --dry-run
|
|
148
|
+
tiger-memory --config tiger-memory.config.yaml bootstrap
|
|
149
|
+
|
|
150
|
+
# 4. Rebuild (incremental, run after each session)
|
|
151
|
+
tiger-memory --config tiger-memory.config.yaml rebuild
|
|
152
|
+
|
|
153
|
+
# 5. Search memory
|
|
154
|
+
tiger-memory --config tiger-memory.config.yaml search "solar energy"
|
|
155
|
+
|
|
156
|
+
# 6. Pin a must-memorize fact
|
|
157
|
+
tiger-memory --config tiger-memory.config.yaml pin "Prefers solar over wind"
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Configuration
|
|
161
|
+
|
|
162
|
+
All paths are resolved from environment variables -- no hardcoded paths.
|
|
163
|
+
|
|
164
|
+
| Variable | Default | Description |
|
|
165
|
+
|---|---|---|
|
|
166
|
+
| `TIGERHARNESS_STATE_DIR` | `~/.local/state/tigerharness-tasks/` | Task runner state directory |
|
|
167
|
+
| `TIGERHARNESS_PERSONAS_DIR` | (none) | Directory containing `<name>.md` prompt files |
|
|
168
|
+
| `TIGERHARNESS_SLACK_ENV` | `.env` | Path to slack-bridge .env file |
|
|
169
|
+
| `TIGERHARNESS_AGENT_CWD` | `.` | Working directory for the Claude agent |
|
|
170
|
+
| `TIGERHARNESS_AGENT_PROMPT` | (none) | Path to the agent's system prompt |
|
|
171
|
+
| `TIGERHARNESS_SLACK_BRIDGE_DIR` | (none) | Path to slack-bridge service dir (for notify CLI) |
|
|
172
|
+
| `TIGERHARNESS_ATTACHMENT_DIR` | `/tmp/slack-attachments` | Where to stage downloaded files |
|
|
173
|
+
| `TIGER_MEMORY_CONFIG` | (none) | Path to tiger-memory YAML config |
|
|
174
|
+
| `TIGER_MEMORY_CLI` | (none) | Path to tiger-memory CLI binary |
|
|
175
|
+
|
|
176
|
+
## Examples
|
|
177
|
+
|
|
178
|
+
See [`examples/`](examples/) for sample configs:
|
|
179
|
+
- [`tiger-memory.config.yaml`](examples/tiger-memory.config.yaml) -- annotated memory config
|
|
180
|
+
- [`personas/researcher.md`](examples/personas/researcher.md) -- sample persona prompt
|
|
181
|
+
- [`env.example`](examples/env.example) -- Slack bridge env template
|
|
182
|
+
|
|
183
|
+
## Requirements
|
|
184
|
+
|
|
185
|
+
- Python 3.11+
|
|
186
|
+
- For the default `claude_p` backend: the [Claude Code CLI](https://docs.claude.com/en/docs/claude-code) (`claude`) on `PATH`.
|
|
187
|
+
- For the `anthropic_sdk` backend: install with `[anthropic]` extra; pulls in [`claude-agent-sdk`](https://pypi.org/project/claude-agent-sdk/).
|
|
188
|
+
|
|
189
|
+
## License
|
|
190
|
+
|
|
191
|
+
MIT
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# tigerharness
|
|
2
|
+
|
|
3
|
+
A generic Claude Code agent harness: iterative task execution, Slack
|
|
4
|
+
integration, and persistent memory management.
|
|
5
|
+
|
|
6
|
+
## Sub-packages
|
|
7
|
+
|
|
8
|
+
| Package | Description |
|
|
9
|
+
|---|---|
|
|
10
|
+
| `tigerharness.agent_sdk` | Backend-agnostic agent SDK. Same caller code, swappable runtimes: `claude -p` subprocess, Anthropic's `claude-agent-sdk`, OpenAI's `openai-agents` (planned). |
|
|
11
|
+
| `tigerharness.task_runner` | Fire-and-forget iterative task execution. Drives a persona through N Claude turns with periodic `/compact`. |
|
|
12
|
+
| `tigerharness.slack_bridge` | Slack Socket Mode bridge. Forwards DMs to a `claude -p` backend and posts replies back to the thread. |
|
|
13
|
+
| `tigerharness.tiger_memory` | Persistent agent memory: archive, journal, briefing with lazy rebuild, kind-decay must-memorize, and drill-down. |
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Core (claude -p backend only; Claude Code CLI must be on PATH)
|
|
19
|
+
pip install tigerharness
|
|
20
|
+
|
|
21
|
+
# With the official claude-agent-sdk backend
|
|
22
|
+
pip install tigerharness[anthropic]
|
|
23
|
+
|
|
24
|
+
# With Slack bridge support
|
|
25
|
+
pip install tigerharness[slack]
|
|
26
|
+
|
|
27
|
+
# With memory support
|
|
28
|
+
pip install tigerharness[memory]
|
|
29
|
+
|
|
30
|
+
# With memory + RAG (local embeddings, free)
|
|
31
|
+
pip install tigerharness[memory-rag]
|
|
32
|
+
|
|
33
|
+
# Everything
|
|
34
|
+
pip install tigerharness[all]
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Or with uv:
|
|
38
|
+
```bash
|
|
39
|
+
uv add tigerharness
|
|
40
|
+
uv add tigerharness --extra all
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quick start
|
|
44
|
+
|
|
45
|
+
### Scaffold a new project
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Create config files in the current directory
|
|
49
|
+
tigerharness init --name researcher
|
|
50
|
+
|
|
51
|
+
# Or with tiger-memory support
|
|
52
|
+
tigerharness init --name researcher --memory
|
|
53
|
+
|
|
54
|
+
# This creates:
|
|
55
|
+
# personas/researcher.md -- edit your agent's instructions
|
|
56
|
+
# .env -- fill in Slack tokens
|
|
57
|
+
# tiger-memory.config.yaml -- (only with --memory)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Task runner
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# 1. Point tigerharness at your personas directory
|
|
64
|
+
export TIGERHARNESS_PERSONAS_DIR=./personas
|
|
65
|
+
|
|
66
|
+
# 2. Assign a task (5 iterations)
|
|
67
|
+
python -m tigerharness.task_runner assign \
|
|
68
|
+
--to researcher \
|
|
69
|
+
--prompt "Research the latest developments in solar energy" \
|
|
70
|
+
--iters 5
|
|
71
|
+
|
|
72
|
+
# 3. Check status
|
|
73
|
+
python -m tigerharness.task_runner list
|
|
74
|
+
|
|
75
|
+
# 4. View logs
|
|
76
|
+
python -m tigerharness.task_runner logs <task-id>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Slack bridge
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# 1. Fill in your Slack tokens in .env (from api.slack.com)
|
|
83
|
+
# SLACK_APP_TOKEN=xapp-...
|
|
84
|
+
# SLACK_BOT_TOKEN=xoxb-...
|
|
85
|
+
# ALLOWED_SLACK_USER_IDS=U0123ABC
|
|
86
|
+
|
|
87
|
+
# 2. Run the bridge
|
|
88
|
+
python -m tigerharness.slack_bridge
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Tiger memory
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# 1. Copy the example config
|
|
95
|
+
cp examples/tiger-memory.config.yaml tiger-memory.config.yaml
|
|
96
|
+
# Edit: set store.root and sources.project_path
|
|
97
|
+
|
|
98
|
+
# 2. Initialize the memory store
|
|
99
|
+
tiger-memory --config tiger-memory.config.yaml init
|
|
100
|
+
|
|
101
|
+
# 3. Bootstrap (one-time backfill from existing transcripts)
|
|
102
|
+
tiger-memory --config tiger-memory.config.yaml bootstrap --dry-run
|
|
103
|
+
tiger-memory --config tiger-memory.config.yaml bootstrap
|
|
104
|
+
|
|
105
|
+
# 4. Rebuild (incremental, run after each session)
|
|
106
|
+
tiger-memory --config tiger-memory.config.yaml rebuild
|
|
107
|
+
|
|
108
|
+
# 5. Search memory
|
|
109
|
+
tiger-memory --config tiger-memory.config.yaml search "solar energy"
|
|
110
|
+
|
|
111
|
+
# 6. Pin a must-memorize fact
|
|
112
|
+
tiger-memory --config tiger-memory.config.yaml pin "Prefers solar over wind"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Configuration
|
|
116
|
+
|
|
117
|
+
All paths are resolved from environment variables -- no hardcoded paths.
|
|
118
|
+
|
|
119
|
+
| Variable | Default | Description |
|
|
120
|
+
|---|---|---|
|
|
121
|
+
| `TIGERHARNESS_STATE_DIR` | `~/.local/state/tigerharness-tasks/` | Task runner state directory |
|
|
122
|
+
| `TIGERHARNESS_PERSONAS_DIR` | (none) | Directory containing `<name>.md` prompt files |
|
|
123
|
+
| `TIGERHARNESS_SLACK_ENV` | `.env` | Path to slack-bridge .env file |
|
|
124
|
+
| `TIGERHARNESS_AGENT_CWD` | `.` | Working directory for the Claude agent |
|
|
125
|
+
| `TIGERHARNESS_AGENT_PROMPT` | (none) | Path to the agent's system prompt |
|
|
126
|
+
| `TIGERHARNESS_SLACK_BRIDGE_DIR` | (none) | Path to slack-bridge service dir (for notify CLI) |
|
|
127
|
+
| `TIGERHARNESS_ATTACHMENT_DIR` | `/tmp/slack-attachments` | Where to stage downloaded files |
|
|
128
|
+
| `TIGER_MEMORY_CONFIG` | (none) | Path to tiger-memory YAML config |
|
|
129
|
+
| `TIGER_MEMORY_CLI` | (none) | Path to tiger-memory CLI binary |
|
|
130
|
+
|
|
131
|
+
## Examples
|
|
132
|
+
|
|
133
|
+
See [`examples/`](examples/) for sample configs:
|
|
134
|
+
- [`tiger-memory.config.yaml`](examples/tiger-memory.config.yaml) -- annotated memory config
|
|
135
|
+
- [`personas/researcher.md`](examples/personas/researcher.md) -- sample persona prompt
|
|
136
|
+
- [`env.example`](examples/env.example) -- Slack bridge env template
|
|
137
|
+
|
|
138
|
+
## Requirements
|
|
139
|
+
|
|
140
|
+
- Python 3.11+
|
|
141
|
+
- For the default `claude_p` backend: the [Claude Code CLI](https://docs.claude.com/en/docs/claude-code) (`claude`) on `PATH`.
|
|
142
|
+
- For the `anthropic_sdk` backend: install with `[anthropic]` extra; pulls in [`claude-agent-sdk`](https://pypi.org/project/claude-agent-sdk/).
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
MIT
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# tigerharness Design Document
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
tigerharness is a standalone, open-source Python package that provides a
|
|
6
|
+
generic Claude Code agent harness: iterative task execution, Slack
|
|
7
|
+
integration, and persistent memory management. Extracted from the
|
|
8
|
+
tigerleap workspace's `services/` directory.
|
|
9
|
+
|
|
10
|
+
## Package structure decision: single package with sub-modules
|
|
11
|
+
|
|
12
|
+
**Chosen: monolithic package with sub-modules** (not a uv workspace /
|
|
13
|
+
monorepo with separate packages).
|
|
14
|
+
|
|
15
|
+
Rationale:
|
|
16
|
+
1. All three services share `agent-sdk` as a core dependency.
|
|
17
|
+
2. `task-runner` already cross-references `slack-bridge` for notifications.
|
|
18
|
+
3. A single `pip install tigerharness` is simpler for adopters than
|
|
19
|
+
coordinating three separate packages.
|
|
20
|
+
4. Optional extras (`[slack]`, `[memory]`, `[memory-rag]`) let users
|
|
21
|
+
install only what they need.
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
tigerharness/
|
|
25
|
+
pyproject.toml # single package, extras for slack/memory/rag
|
|
26
|
+
src/
|
|
27
|
+
tigerharness/
|
|
28
|
+
__init__.py
|
|
29
|
+
task_runner/ # iterative task execution loop
|
|
30
|
+
slack_bridge/ # Slack Socket Mode bridge to Claude
|
|
31
|
+
tiger_memory/ # persistent memory: archive, journal, briefing
|
|
32
|
+
tests/
|
|
33
|
+
task_runner/
|
|
34
|
+
slack_bridge/
|
|
35
|
+
tiger_memory/
|
|
36
|
+
skills/ # Claude Code skill definitions (SKILL.md files)
|
|
37
|
+
assign-task/
|
|
38
|
+
slack-notify/
|
|
39
|
+
lab-notebook-quarter-roll/
|
|
40
|
+
tiger-memory-drill-down/
|
|
41
|
+
tiger-memory-search/
|
|
42
|
+
docs/
|
|
43
|
+
DESIGN.md # this file
|
|
44
|
+
task-runner.md
|
|
45
|
+
slack-bridge.md
|
|
46
|
+
tiger-memory.md
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Decoupling strategy
|
|
50
|
+
|
|
51
|
+
### 1. task-runner decoupling
|
|
52
|
+
|
|
53
|
+
| Original coupling | Resolution |
|
|
54
|
+
|---|---|
|
|
55
|
+
| `WORKSPACE_ROOT = Path(__file__).parents[3]` in personas.py | Replace with config-driven persona registry. Personas defined in a YAML/Python config the user provides, not hardcoded. |
|
|
56
|
+
| `tigerleap-tasks` state dir name | Rename to `tigerharness-tasks` (configurable via env). |
|
|
57
|
+
| `_BRIDGE_ENV_PATH` hardcoded parents[3] path | Resolve `.env` from `SLACK_BRIDGE_ENV` env var or colocated `.env` |
|
|
58
|
+
| `_SLACK_THREAD_NOTICE` hardcoded path `/home/tigerleap/projects/...` | Template that uses `TIGERHARNESS_SLACK_BRIDGE_DIR` or auto-discovers |
|
|
59
|
+
| Persona system prompt files at `personas/<role>.md` | Configurable `TIGERHARNESS_PERSONAS_DIR` or pass prompt text directly |
|
|
60
|
+
| Hardcoded 5 persona names (sai, chief, scout, quartermaster, inquisitor) | Ship as example/default config; users register their own personas |
|
|
61
|
+
|
|
62
|
+
### 2. slack-bridge decoupling
|
|
63
|
+
|
|
64
|
+
| Original coupling | Resolution |
|
|
65
|
+
|---|---|
|
|
66
|
+
| `_WORKSPACE_ROOT = Path(__file__).parents[3]` | Remove; all paths from env/config |
|
|
67
|
+
| `_SAI_PROMPT_PATH = _WORKSPACE_ROOT / "personas" / "sai.md"` | `TIGERHARNESS_PERSONA_PROMPT` env var or config file |
|
|
68
|
+
| `load_dotenv(… / "sandbox" / "slack-bridge" / ".env")` | Standard dotenv from CWD or explicit path |
|
|
69
|
+
| `tiger-memory` venv path hardcoded | `TIGER_MEMORY_CLI` env var or PATH lookup |
|
|
70
|
+
|
|
71
|
+
### 3. tiger-memory decoupling
|
|
72
|
+
|
|
73
|
+
Already fully config-driven! No tigerleap references in code.
|
|
74
|
+
Only change: move it into the `tigerharness` namespace.
|
|
75
|
+
|
|
76
|
+
## Dependency map
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
tigerharness (core)
|
|
80
|
+
requires: agent-sdk (will be vendored or declared as git dep initially)
|
|
81
|
+
|
|
82
|
+
tigerharness[slack]
|
|
83
|
+
adds: slack-bolt, aiohttp, python-dotenv
|
|
84
|
+
|
|
85
|
+
tigerharness[memory]
|
|
86
|
+
adds: pyyaml
|
|
87
|
+
|
|
88
|
+
tigerharness[memory-rag]
|
|
89
|
+
adds: fastembed, sqlite-vec
|
|
90
|
+
|
|
91
|
+
tigerharness[memory-rag-openai]
|
|
92
|
+
adds: openai, sqlite-vec
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Configuration model
|
|
96
|
+
|
|
97
|
+
All hardcoded paths are replaced with a layered config:
|
|
98
|
+
|
|
99
|
+
1. **Environment variables** (highest priority):
|
|
100
|
+
- `TIGERHARNESS_STATE_DIR` — XDG state (default: `~/.local/state/tigerharness/`)
|
|
101
|
+
- `TIGERHARNESS_PERSONAS_DIR` — directory of `<name>.md` prompt files
|
|
102
|
+
- `TIGERHARNESS_SLACK_BRIDGE_DIR` — where slack-bridge runs (for notify CLI)
|
|
103
|
+
- `TIGER_MEMORY_CONFIG` — path to tiger-memory YAML config
|
|
104
|
+
|
|
105
|
+
2. **Config file** (`tigerharness.yaml` or per-service configs)
|
|
106
|
+
|
|
107
|
+
3. **Sensible defaults** that work out of the box for a fresh install.
|
|
108
|
+
|
|
109
|
+
## Persona system redesign
|
|
110
|
+
|
|
111
|
+
The original has 5 hardcoded personas. The new design:
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
# User provides a personas.yaml or Python dict:
|
|
115
|
+
personas:
|
|
116
|
+
- name: assistant
|
|
117
|
+
aliases: [ai, helper]
|
|
118
|
+
cwd: /path/to/project
|
|
119
|
+
prompt_file: personas/assistant.md # relative to TIGERHARNESS_PERSONAS_DIR
|
|
120
|
+
permission_mode: bypassPermissions
|
|
121
|
+
disallowed_tools: ["Bash(sudo:*)"]
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
A `register_persona()` API and CLI `--persona-config` flag allow
|
|
125
|
+
runtime configuration. The package ships with NO default personas
|
|
126
|
+
(unlike tigerleap's 5) — users define their own.
|
|
127
|
+
|
|
128
|
+
## Skills extraction
|
|
129
|
+
|
|
130
|
+
Skills are Claude Code `.claude/skills/` SKILL.md files. They contain
|
|
131
|
+
no executable code — just documentation for Claude to follow. We:
|
|
132
|
+
|
|
133
|
+
1. Copy them into `tigerharness/skills/`
|
|
134
|
+
2. Replace all hardcoded paths with generic placeholders
|
|
135
|
+
3. Add an install script / docs explaining how to symlink them into a
|
|
136
|
+
project's `.claude/skills/`
|
|
137
|
+
|
|
138
|
+
## Test strategy
|
|
139
|
+
|
|
140
|
+
- All existing tests migrate with minimal changes (mock paths, remove
|
|
141
|
+
tigerleap assumptions).
|
|
142
|
+
- New tests fill gaps in:
|
|
143
|
+
- Persona config loading (new YAML-driven system)
|
|
144
|
+
- Config resolution (env var precedence)
|
|
145
|
+
- Integration between task-runner and slack-bridge notify
|
|
146
|
+
- Target: 100% line coverage via `pytest-cov`.
|
|
147
|
+
|
|
148
|
+
## Migration path for tigerleap
|
|
149
|
+
|
|
150
|
+
After tigerharness is stable:
|
|
151
|
+
1. `tigerleap` adds `tigerharness` as a dependency
|
|
152
|
+
2. `tigerleap/services/` becomes thin wrappers (or is deleted)
|
|
153
|
+
3. A `tigerharness.yaml` at tigerleap root configures the personas,
|
|
154
|
+
paths, and memory
|