@colin4k1024/tsp 2.5.0 → 2.5.2
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.
- package/README.md +67 -0
- package/commands/dashboard.md +105 -0
- package/commands/goal.md +142 -0
- package/commands/heartbeat.md +129 -0
- package/commands/triage.md +108 -0
- package/hooks/README.md +1 -1
- package/hooks/harness-context-monitor.js +4 -0
- package/hooks/hooks.json +27 -26
- package/hooks/strategic-compact/README.md +7 -5
- package/hooks/strategic-compact/suggest-compact.js +9 -174
- package/marketplace.json +7 -8
- package/package.json +1 -1
- package/schemas/goal.schema.json +172 -0
- package/scripts/harness-audit.js +7 -4
- package/scripts/hooks/session-start-goal-resume.js +95 -0
- package/scripts/hooks/suggest-compact.js +392 -62
- package/scripts/install-platform.js +68 -85
- package/scripts/lib/blame-attribution.js +210 -0
- package/scripts/lib/completion-oracle.js +351 -0
- package/scripts/lib/heartbeat-scheduler.js +265 -0
- package/scripts/lib/opencode/convert-agents.js +273 -0
- package/scripts/lib/opencode/convert-hooks.js +286 -0
- package/scripts/lib/opencode/generate-agents-md.js +361 -0
- package/scripts/lib/wave-cost-advisor.js +155 -0
- package/scripts/test-opencode-install.js +151 -0
- package/skills/goal-convergence/SKILL.md +150 -0
- package/skills/goframe-v2/examples/practices/quick-demo/manifest/config/config.yaml +14 -14
- package/skills/loop-heartbeat/SKILL.md +120 -0
- package/skills/mcp-connector-bridge/SKILL.md +132 -0
- package/skills/repo-scan/SKILL.md +63 -63
- package/skills/rework-loop/SKILL.md +131 -0
- package/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
- package/scripts/__pycache__/build_platform_artifacts.cpython-311.pyc +0 -0
- package/scripts/__pycache__/install_platform.cpython-311.pyc +0 -0
- package/scripts/__pycache__/langfuse_trace.cpython-311.pyc +0 -0
- package/scripts/__pycache__/query_audit_logs.cpython-311.pyc +0 -0
- package/scripts/__pycache__/scan_leaked_keys.cpython-311.pyc +0 -0
- package/scripts/__pycache__/team_skills_platform.cpython-311.pyc +0 -0
- package/scripts/__pycache__/team_skills_platform.cpython-313.pyc +0 -0
- package/scripts/__pycache__/validate_library.cpython-311.pyc +0 -0
- package/scripts/__pycache__/validate_workflow_state.cpython-311.pyc +0 -0
- package/scripts/evolution/__pycache__/__init__.cpython-311.pyc +0 -0
- package/scripts/evolution/__pycache__/store.cpython-311.pyc +0 -0
- package/scripts/hooks/__pycache__/__init__.cpython-311.pyc +0 -0
- package/scripts/hooks/__pycache__/mcp_health_check.cpython-311.pyc +0 -0
- package/scripts/hooks/__pycache__/observe.cpython-311.pyc +0 -0
- package/scripts/hooks/__pycache__/session_end.cpython-311.pyc +0 -0
- package/scripts/hooks/__pycache__/session_start.cpython-311.pyc +0 -0
- package/scripts/lib/__pycache__/audit_logger.cpython-311.pyc +0 -0
- package/scripts/lib/__pycache__/audit_query.cpython-311.pyc +0 -0
- package/scripts/lib/__pycache__/hook_contract.cpython-311.pyc +0 -0
- package/scripts/lib/__pycache__/memory_store.cpython-311.pyc +0 -0
- package/scripts/lib/__pycache__/utils.cpython-311.pyc +0 -0
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
node scripts/build-platform-artifacts.js
|
|
16
16
|
node scripts/install-apply.js --profile team --target claude
|
|
17
17
|
node scripts/install-apply.js --profile full --target codex
|
|
18
|
+
node scripts/install-apply.js --profile full --target opencode
|
|
18
19
|
```
|
|
19
20
|
|
|
20
21
|
## Who It's For / 适合谁
|
|
@@ -58,6 +59,72 @@ TSP 采用 **角色 + 技能 + Agent + 规则 + Hooks + Workflow 引擎** 六层
|
|
|
58
59
|
|
|
59
60
|
安装工具链公开主线支持 **3 个 code agent**:Claude Code、Codex、OpenCode。其他历史 target 保留为隐藏兼容路径,不再作为公开 onboarding 主线。
|
|
60
61
|
|
|
62
|
+
### OpenCode 集成
|
|
63
|
+
|
|
64
|
+
TSP 为 OpenCode 提供了完整的适配支持,包括:
|
|
65
|
+
|
|
66
|
+
- **AGENTS.md 自动生成**:包含完整的规则索引、角色索引、命令索引和技能索引
|
|
67
|
+
- **Agent 系统适配**:所有角色和 specialist agents 都添加了 YAML front matter 配置
|
|
68
|
+
- **Hooks 系统适配**:将 TSP hooks 转换为 OpenCode 插件格式
|
|
69
|
+
- **配置文件生成**:自动生成 `opencode.json` 配置文件
|
|
70
|
+
- **Skills 系统兼容**:所有 SKILL.md 文件都兼容 OpenCode 的 skill 工具
|
|
71
|
+
|
|
72
|
+
#### OpenCode 安装
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# 安装完整 OpenCode 配置
|
|
76
|
+
node scripts/install-apply.js --profile full --target opencode
|
|
77
|
+
|
|
78
|
+
# 或使用 npm 脚本
|
|
79
|
+
npm run install:opencode
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
#### OpenCode 配置
|
|
83
|
+
|
|
84
|
+
安装完成后,OpenCode 配置文件位于 `~/.config/opencode/opencode.json`,包含:
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"$schema": "https://opencode.ai/config.json",
|
|
89
|
+
"instructions": ["./AGENTS.md"],
|
|
90
|
+
"plugin": ["team-skills-platform"],
|
|
91
|
+
"permission": {
|
|
92
|
+
"edit": "allow",
|
|
93
|
+
"bash": "allow"
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### OpenCode 使用
|
|
99
|
+
|
|
100
|
+
1. **启动 OpenCode**:在项目目录运行 `opencode`
|
|
101
|
+
2. **查看可用角色**:AGENTS.md 中包含所有角色的索引
|
|
102
|
+
3. **切换角色**:使用 `@tech-lead`、`@frontend-engineer` 等方式切换角色
|
|
103
|
+
4. **执行命令**:使用 `/team-intake`、`/team-plan` 等团队命令
|
|
104
|
+
5. **加载技能**:使用 `skill` 工具加载 SKILL.md 文件
|
|
105
|
+
|
|
106
|
+
#### OpenCode 目录结构
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
~/.config/opencode/
|
|
110
|
+
├── AGENTS.md # 主配置文件(自动生成)
|
|
111
|
+
├── opencode.json # OpenCode 配置文件
|
|
112
|
+
├── agents/ # Agent 定义文件
|
|
113
|
+
│ ├── tech-lead.md
|
|
114
|
+
│ ├── product-manager.md
|
|
115
|
+
│ └── ...
|
|
116
|
+
├── command/ # 命令文件
|
|
117
|
+
│ ├── team-intake.md
|
|
118
|
+
│ ├── team-plan.md
|
|
119
|
+
│ └── ...
|
|
120
|
+
└── plugins/ # 插件目录
|
|
121
|
+
├── team-skills-platform/ # TSP 插件
|
|
122
|
+
│ ├── skills/ # 技能文件
|
|
123
|
+
│ ├── rules/ # 规则文件
|
|
124
|
+
│ └── ...
|
|
125
|
+
└── tsp-hooks.js # Hooks 插件
|
|
126
|
+
```
|
|
127
|
+
|
|
61
128
|
发布为 npm 包 `@colin4k1024/tsp`,内置 Rust bridge 预构建二进制,安装零依赖。
|
|
62
129
|
|
|
63
130
|
### 集成的开源框架与方法论
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Dashboard Command
|
|
2
|
+
|
|
3
|
+
Real-time progress visibility for goals, waves, and triage. Shows what the loop
|
|
4
|
+
is doing, how much budget remains, and what needs human attention.
|
|
5
|
+
|
|
6
|
+
## Usage
|
|
7
|
+
|
|
8
|
+
`/dashboard`
|
|
9
|
+
|
|
10
|
+
## Output
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
14
|
+
║ LOOP ENGINEERING DASHBOARD ║
|
|
15
|
+
╠══════════════════════════════════════════════════════════════╣
|
|
16
|
+
║ ║
|
|
17
|
+
║ ACTIVE GOALS ║
|
|
18
|
+
║ ───────────── ║
|
|
19
|
+
║ ▶ [goal-a1b2c3d4] "Fix all failing tests" ║
|
|
20
|
+
║ Iteration: 3/15 | Budget: $1.20/$10 | Time: 25m/2h ║
|
|
21
|
+
║ Last oracle: FAIL — 2 tests still failing in auth module ║
|
|
22
|
+
║ Next hint: Focus on token refresh mock ║
|
|
23
|
+
║ ║
|
|
24
|
+
║ ⏸ [goal-e5f6g7h8] "Achieve 80% coverage" ║
|
|
25
|
+
║ Iteration: 7/15 | Budget: $3.50/$10 | Paused ║
|
|
26
|
+
║ ║
|
|
27
|
+
║ HEARTBEAT ║
|
|
28
|
+
║ ───────────── ║
|
|
29
|
+
║ Status: Running (interval: 30m) ║
|
|
30
|
+
║ Last run: 12m ago — 2/3 passed, 1 goal created ║
|
|
31
|
+
║ Next run: 18m ║
|
|
32
|
+
║ Budget: $0.80/$2.00 per hour ║
|
|
33
|
+
║ ║
|
|
34
|
+
║ TRIAGE INBOX ║
|
|
35
|
+
║ ───────────── ║
|
|
36
|
+
║ [3 pending] [1 high] [2 medium] ║
|
|
37
|
+
║ • HIGH: sentry — 5 unresolved errors (2h ago) ║
|
|
38
|
+
║ • MED: lint — 4 new lint errors (30m ago) ║
|
|
39
|
+
║ • MED: deps — 2 moderate vulnerabilities (1d ago) ║
|
|
40
|
+
║ ║
|
|
41
|
+
║ WAVE EXECUTION ║
|
|
42
|
+
║ ───────────── ║
|
|
43
|
+
║ (No active waves) ║
|
|
44
|
+
║ ║
|
|
45
|
+
║ REWORK TRACKING ║
|
|
46
|
+
║ ───────────── ║
|
|
47
|
+
║ Persistent trouble spots: 1 ║
|
|
48
|
+
║ • src/auth/refresh.ts — 3 attempts, last: fail ║
|
|
49
|
+
║ ║
|
|
50
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Data Sources
|
|
54
|
+
|
|
55
|
+
The dashboard aggregates from:
|
|
56
|
+
|
|
57
|
+
| Source | Location |
|
|
58
|
+
|--------|----------|
|
|
59
|
+
| Active goals | `~/.claude/goals/*.json` |
|
|
60
|
+
| Heartbeat state | `~/.claude/heartbeat-last-run.json` |
|
|
61
|
+
| Triage inbox | `~/.claude/triage/inbox.jsonl` |
|
|
62
|
+
| Wave progress | Worker `status.md` files in coordination dirs |
|
|
63
|
+
| Rework tracking | `~/.claude/rework-tracking.json` |
|
|
64
|
+
| Cost tracking | Goal history `costDollars` fields |
|
|
65
|
+
|
|
66
|
+
## Sections
|
|
67
|
+
|
|
68
|
+
### Active Goals
|
|
69
|
+
- State icon: ▶ (active), ⏸ (paused), ✓ (converged), ⚠ (escalated)
|
|
70
|
+
- Progress: iteration/max, cost/budget, time/duration
|
|
71
|
+
- Last oracle verdict and hint
|
|
72
|
+
|
|
73
|
+
### Heartbeat
|
|
74
|
+
- Running/stopped status
|
|
75
|
+
- Last run results (passed/failed count)
|
|
76
|
+
- Time to next run
|
|
77
|
+
- Hourly budget usage
|
|
78
|
+
|
|
79
|
+
### Triage Inbox
|
|
80
|
+
- Pending count by severity
|
|
81
|
+
- Top 3 most recent items with source and age
|
|
82
|
+
- Action hint: "Use /triage to act on items"
|
|
83
|
+
|
|
84
|
+
### Wave Execution
|
|
85
|
+
- Active wave index / total waves
|
|
86
|
+
- Per-worker status and progress estimate
|
|
87
|
+
- Critical path and ETA (when workers report progress)
|
|
88
|
+
|
|
89
|
+
### Rework Tracking
|
|
90
|
+
- Persistent trouble spots (files with 3+ rework attempts)
|
|
91
|
+
- Escalation recommendations
|
|
92
|
+
|
|
93
|
+
## Integration
|
|
94
|
+
|
|
95
|
+
- **`/goal status`**: Dashboard includes goal details
|
|
96
|
+
- **`/heartbeat status`**: Dashboard includes heartbeat state
|
|
97
|
+
- **`/triage stats`**: Dashboard includes inbox summary
|
|
98
|
+
- **Wave execution**: Dashboard tracks parallel worker progress
|
|
99
|
+
|
|
100
|
+
## Arguments
|
|
101
|
+
|
|
102
|
+
$ARGUMENTS:
|
|
103
|
+
- (none) — Show full dashboard
|
|
104
|
+
- `--compact` — One-line summary per section
|
|
105
|
+
- `--json` — Machine-readable output
|
package/commands/goal.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Goal Command
|
|
2
|
+
|
|
3
|
+
Define and run a goal-oriented autonomous loop with an external completion oracle.
|
|
4
|
+
|
|
5
|
+
The goal primitive keeps iterating until verifiable stopping conditions are met,
|
|
6
|
+
checked by a SEPARATE model (the oracle) to eliminate author-bias.
|
|
7
|
+
|
|
8
|
+
## Usage
|
|
9
|
+
|
|
10
|
+
`/goal <subcommand> [args]`
|
|
11
|
+
|
|
12
|
+
## Subcommands
|
|
13
|
+
|
|
14
|
+
### Create & Start
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
/goal "make all tests pass"
|
|
18
|
+
/goal "achieve 80% coverage" --budget-iterations 10 --budget-dollars 5
|
|
19
|
+
/goal "fix lint errors in src/" --checker sonnet
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Creates a new goal, infers stopping conditions from the objective, and starts
|
|
23
|
+
the maker-oracle loop immediately.
|
|
24
|
+
|
|
25
|
+
**Auto-inferred stopping conditions:**
|
|
26
|
+
- "tests pass" → `npm test` exit code 0
|
|
27
|
+
- "coverage N%" → coverage report >= N
|
|
28
|
+
- "lint clean" → `npm run lint` exit code 0
|
|
29
|
+
- "build passes" → `npm run build` exit code 0
|
|
30
|
+
- Custom: specify with `--condition "command"`
|
|
31
|
+
|
|
32
|
+
### Status
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
/goal status
|
|
36
|
+
/goal status <goalId>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Show active goals with current iteration, oracle verdict history, budget usage,
|
|
40
|
+
and estimated remaining iterations.
|
|
41
|
+
|
|
42
|
+
### Resume
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
/goal resume
|
|
46
|
+
/goal resume <goalId>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Resume an active goal from a previous session. Reads state from
|
|
50
|
+
`~/.claude/goals/{goalId}.json` and re-enters the maker loop with the oracle's
|
|
51
|
+
last `nextHint` as guidance.
|
|
52
|
+
|
|
53
|
+
### Pause
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
/goal pause
|
|
57
|
+
/goal pause <goalId>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Pause without abandoning. State is persisted for later `/goal resume`.
|
|
61
|
+
|
|
62
|
+
### List
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
/goal list
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Show all goals (active, paused, converged, escalated) with summary stats.
|
|
69
|
+
|
|
70
|
+
## The Maker-Oracle Loop
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
┌─────────────────────────────────────────────────────┐
|
|
74
|
+
│ /goal "fix all tests" │
|
|
75
|
+
│ │
|
|
76
|
+
│ ┌─────────┐ ┌─────────┐ ┌──────────┐ │
|
|
77
|
+
│ │ MAKER │───▶│ ORACLE │───▶│ CONVERGE │ │
|
|
78
|
+
│ │(primary)│ │(checker)│ │ or LOOP │ │
|
|
79
|
+
│ └─────────┘ └─────────┘ └──────────┘ │
|
|
80
|
+
│ ▲ │ │ │
|
|
81
|
+
│ │ verdict: fail │ │
|
|
82
|
+
│ │ + nextHint │ │
|
|
83
|
+
│ └──────────────┘ │ │
|
|
84
|
+
│ │ │
|
|
85
|
+
│ Budget exhausted? ──▶ ESCALATE to triage│ │
|
|
86
|
+
└─────────────────────────────────────────────────────┘
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
1. **Maker** (your primary model) executes one iteration toward the objective
|
|
90
|
+
2. **Oracle** (different model, read-only) evaluates ALL stopping conditions
|
|
91
|
+
3. If all pass → goal state becomes `converged`
|
|
92
|
+
4. If any fail → oracle provides `nextHint` → maker iterates again
|
|
93
|
+
5. If budget exhausted → goal becomes `escalated` → lands in triage inbox
|
|
94
|
+
|
|
95
|
+
## Oracle Behavior
|
|
96
|
+
|
|
97
|
+
The oracle:
|
|
98
|
+
- Uses a DIFFERENT model than the maker (default: haiku for speed/cost)
|
|
99
|
+
- Has READ-ONLY tool access (Read, Bash without writes)
|
|
100
|
+
- Cannot modify code — only evaluate conditions
|
|
101
|
+
- Returns structured verdict: `{converged, reasons[], nextHint}`
|
|
102
|
+
- Is the reason you can walk away from a running loop
|
|
103
|
+
|
|
104
|
+
## Budget Controls
|
|
105
|
+
|
|
106
|
+
| Control | Default | Flag |
|
|
107
|
+
|---------|---------|------|
|
|
108
|
+
| Max iterations | 15 | `--budget-iterations N` |
|
|
109
|
+
| Max duration | 2h | `--budget-duration Nh` |
|
|
110
|
+
| Max cost | $10 | `--budget-dollars N` |
|
|
111
|
+
| Checker model | haiku | `--checker model` |
|
|
112
|
+
|
|
113
|
+
When ANY budget limit is hit, the goal escalates rather than continuing blindly.
|
|
114
|
+
|
|
115
|
+
## State Persistence
|
|
116
|
+
|
|
117
|
+
Goals persist to `~/.claude/goals/{goalId}.json` (follows goal.schema.json).
|
|
118
|
+
|
|
119
|
+
- Active goals survive session restarts
|
|
120
|
+
- SessionStart hook displays active goal reminder
|
|
121
|
+
- Full iteration history is preserved for debugging
|
|
122
|
+
|
|
123
|
+
## Integration
|
|
124
|
+
|
|
125
|
+
- **Triage inbox:** Escalated goals create triage items (`/triage`)
|
|
126
|
+
- **Heartbeat:** Heartbeat scans can auto-create goals (`/heartbeat`)
|
|
127
|
+
- **Checkpoint:** Each iteration creates an implicit checkpoint
|
|
128
|
+
- **Verification loop:** Oracle uses verification-loop patterns internally
|
|
129
|
+
|
|
130
|
+
## Arguments
|
|
131
|
+
|
|
132
|
+
$ARGUMENTS:
|
|
133
|
+
- `<objective>` — Natural language goal description (quoted string)
|
|
134
|
+
- `--budget-iterations N` — Max iterations (default 15)
|
|
135
|
+
- `--budget-duration Nm|Nh` — Max wall time (default 2h)
|
|
136
|
+
- `--budget-dollars N` — Max cost USD (default 10)
|
|
137
|
+
- `--checker model` — Oracle model (default haiku)
|
|
138
|
+
- `--condition "command"` — Additional stopping condition command
|
|
139
|
+
- `status [goalId]` — Show goal status
|
|
140
|
+
- `resume [goalId]` — Resume paused/interrupted goal
|
|
141
|
+
- `pause [goalId]` — Pause active goal
|
|
142
|
+
- `list` — List all goals
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Heartbeat Command
|
|
2
|
+
|
|
3
|
+
Run discovery scans on a schedule to find issues, auto-create goals, or surface
|
|
4
|
+
findings to the triage inbox. The heartbeat is what makes a loop an actual loop —
|
|
5
|
+
not a one-shot run.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
`/heartbeat <subcommand> [args]`
|
|
10
|
+
|
|
11
|
+
## Subcommands
|
|
12
|
+
|
|
13
|
+
### Start
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
/heartbeat start
|
|
17
|
+
/heartbeat start --interval 30m
|
|
18
|
+
/heartbeat start --scan test-health,lint-drift
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Registers a recurring CronCreate job that runs configured scans. Empty runs
|
|
22
|
+
(all scans pass) archive themselves silently.
|
|
23
|
+
|
|
24
|
+
### Stop
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
/heartbeat stop
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Cancels the recurring heartbeat job via CronDelete.
|
|
31
|
+
|
|
32
|
+
### Status
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
/heartbeat status
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Shows:
|
|
39
|
+
- Last scan time and results
|
|
40
|
+
- Next scheduled run
|
|
41
|
+
- Budget usage (cost per hour)
|
|
42
|
+
- Active scan configurations
|
|
43
|
+
|
|
44
|
+
### Run Once
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
/heartbeat run
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Execute all configured scans immediately (one-shot, no scheduling).
|
|
51
|
+
|
|
52
|
+
## Configuration
|
|
53
|
+
|
|
54
|
+
Heartbeat reads from `.claude/heartbeat.yaml` in the project root:
|
|
55
|
+
|
|
56
|
+
```yaml
|
|
57
|
+
heartbeat:
|
|
58
|
+
interval: "30m" # How often to tick (default: 30m)
|
|
59
|
+
scans:
|
|
60
|
+
- name: "test-health"
|
|
61
|
+
command: "npm test 2>&1 | tail -10"
|
|
62
|
+
onFailure: "auto-goal" # auto-create a goal to fix it
|
|
63
|
+
description: "Run test suite"
|
|
64
|
+
- name: "lint-drift"
|
|
65
|
+
command: "npm run lint -- --quiet 2>&1 | wc -l"
|
|
66
|
+
threshold: 0 # numeric threshold: pass if output <= threshold
|
|
67
|
+
onFailure: "triage" # surface to triage inbox for human
|
|
68
|
+
description: "Check lint errors"
|
|
69
|
+
- name: "dependency-audit"
|
|
70
|
+
command: "npm audit --production 2>&1 | grep -c 'vulnerabilities'"
|
|
71
|
+
threshold: 0
|
|
72
|
+
onFailure: "triage"
|
|
73
|
+
description: "Audit dependencies"
|
|
74
|
+
- name: "type-check"
|
|
75
|
+
command: "npx tsc --noEmit 2>&1; echo EXIT:$?"
|
|
76
|
+
onFailure: "auto-goal"
|
|
77
|
+
description: "TypeScript type checking"
|
|
78
|
+
budget:
|
|
79
|
+
maxDollarsPerHour: 2.0 # Pause heartbeat if cost exceeds this
|
|
80
|
+
pauseOnExhaust: true # Pause vs stop on budget exhaust
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Scan Classification
|
|
84
|
+
|
|
85
|
+
Each scan result is classified into an action:
|
|
86
|
+
|
|
87
|
+
| Action | Behavior |
|
|
88
|
+
|--------|----------|
|
|
89
|
+
| `auto-goal` | Create a goal automatically from the failure (e.g., "fix 3 failing tests") |
|
|
90
|
+
| `triage` | Append to triage inbox for human review |
|
|
91
|
+
| `notify` | Desktop notification only (informational) |
|
|
92
|
+
| `ignore` | Log silently, take no action |
|
|
93
|
+
|
|
94
|
+
## Flow
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
┌────────────────────────────────────────────┐
|
|
98
|
+
│ /heartbeat start │
|
|
99
|
+
│ │
|
|
100
|
+
│ CronCreate (every 30m) │
|
|
101
|
+
│ │ │
|
|
102
|
+
│ ▼ │
|
|
103
|
+
│ Run all scans │
|
|
104
|
+
│ │ │
|
|
105
|
+
│ ┌────┼────────┬──────────┐ │
|
|
106
|
+
│ ▼ ▼ ▼ ▼ │
|
|
107
|
+
│ PASS FAIL FAIL FAIL │
|
|
108
|
+
│ │ (goal) (triage) (notify) │
|
|
109
|
+
│ │ │ │ │ │
|
|
110
|
+
│ ▼ ▼ ▼ ▼ │
|
|
111
|
+
│ Skip /goal /triage Desktop │
|
|
112
|
+
│ create inbox notification │
|
|
113
|
+
└────────────────────────────────────────────┘
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Integration
|
|
117
|
+
|
|
118
|
+
- **`/goal`**: Heartbeat auto-creates goals from `auto-goal` scan failures
|
|
119
|
+
- **`/triage`**: Heartbeat populates triage inbox from `triage` scan failures
|
|
120
|
+
- **Budget**: Integrates with cost tracking; pauses if hourly budget exceeded
|
|
121
|
+
- **Hooks**: Uses CronCreate/CronDelete for scheduling (7-day auto-expiry applies)
|
|
122
|
+
|
|
123
|
+
## Arguments
|
|
124
|
+
|
|
125
|
+
$ARGUMENTS:
|
|
126
|
+
- `start [--interval Nm|Nh] [--scan name1,name2]` — Start recurring heartbeat
|
|
127
|
+
- `stop` — Cancel heartbeat
|
|
128
|
+
- `status` — Show heartbeat state
|
|
129
|
+
- `run` — Execute scans once (no scheduling)
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Triage Command
|
|
2
|
+
|
|
3
|
+
View and act on findings that the loop could not auto-resolve. The triage inbox
|
|
4
|
+
is where issues land when they need human judgment.
|
|
5
|
+
|
|
6
|
+
## Usage
|
|
7
|
+
|
|
8
|
+
`/triage [subcommand] [args]`
|
|
9
|
+
|
|
10
|
+
## Subcommands
|
|
11
|
+
|
|
12
|
+
### List (default)
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
/triage
|
|
16
|
+
/triage list
|
|
17
|
+
/triage list --source heartbeat
|
|
18
|
+
/triage list --severity high
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Show pending triage items with source, severity, and suggested actions.
|
|
22
|
+
|
|
23
|
+
### Act
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
/triage act <id> goal # Promote to a goal (auto-fix)
|
|
27
|
+
/triage act <id> dismiss # Dismiss (not actionable)
|
|
28
|
+
/triage act <id> defer # Defer to next session
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Take action on a triage item. `goal` creates a goal from the finding.
|
|
32
|
+
|
|
33
|
+
### Stats
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
/triage stats
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Show inbox health metrics: pending count, sources breakdown, age distribution.
|
|
40
|
+
|
|
41
|
+
### Clear
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
/triage clear --resolved
|
|
45
|
+
/triage clear --older-than 7d
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Remove resolved or stale items.
|
|
49
|
+
|
|
50
|
+
## Triage Item Structure
|
|
51
|
+
|
|
52
|
+
Each item in the inbox has:
|
|
53
|
+
|
|
54
|
+
| Field | Description |
|
|
55
|
+
|-------|-------------|
|
|
56
|
+
| `id` | Unique identifier (e.g., `triage-lq4x8`) |
|
|
57
|
+
| `source` | Where it came from (e.g., `heartbeat:lint-drift`, `goal:escalated`) |
|
|
58
|
+
| `severity` | `high`, `medium`, `low` |
|
|
59
|
+
| `summary` | One-line description |
|
|
60
|
+
| `detail` | Full scan output or error context |
|
|
61
|
+
| `suggestedActions` | What the system recommends |
|
|
62
|
+
| `createdAt` | When the item was created |
|
|
63
|
+
| `status` | `pending`, `acted`, `dismissed`, `deferred` |
|
|
64
|
+
|
|
65
|
+
## Sources
|
|
66
|
+
|
|
67
|
+
Items enter triage from:
|
|
68
|
+
|
|
69
|
+
1. **Heartbeat scans** with `onFailure: "triage"` classification
|
|
70
|
+
2. **Escalated goals** that exhausted their budget without converging
|
|
71
|
+
3. **Manual** items added by the user
|
|
72
|
+
4. **Connectors** (MCP) that discover issues from external tools
|
|
73
|
+
|
|
74
|
+
## Flow
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
┌──────────────┐ ┌─────────┐ ┌──────────────┐
|
|
78
|
+
│ Heartbeat │────▶│ TRIAGE │────▶│ /triage act │
|
|
79
|
+
│ Goal escape │ │ INBOX │ │ goal/dismiss│
|
|
80
|
+
│ Connectors │ │ (.jsonl)│ │ /defer │
|
|
81
|
+
└──────────────┘ └─────────┘ └──────────────┘
|
|
82
|
+
│
|
|
83
|
+
▼
|
|
84
|
+
Statusline: [Triage: N]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Storage
|
|
88
|
+
|
|
89
|
+
Inbox is stored as newline-delimited JSON at `~/.claude/triage/inbox.jsonl`.
|
|
90
|
+
This format is:
|
|
91
|
+
- Append-only (safe for concurrent writes)
|
|
92
|
+
- Human-readable (one JSON object per line)
|
|
93
|
+
- Easy to grep and filter
|
|
94
|
+
|
|
95
|
+
## Integration
|
|
96
|
+
|
|
97
|
+
- **`/heartbeat`**: Primary source of triage items
|
|
98
|
+
- **`/goal`**: Escalated goals create triage items; triage items can become goals
|
|
99
|
+
- **Statusline**: Hook shows `[Triage: N]` count when items are pending
|
|
100
|
+
- **Session start**: Active triage items mentioned in session context
|
|
101
|
+
|
|
102
|
+
## Arguments
|
|
103
|
+
|
|
104
|
+
$ARGUMENTS:
|
|
105
|
+
- `list [--source name] [--severity level]` — List pending items (default)
|
|
106
|
+
- `act <id> goal|dismiss|defer` — Take action on an item
|
|
107
|
+
- `stats` — Show inbox metrics
|
|
108
|
+
- `clear --resolved|--older-than Nd` — Clean up resolved/stale items
|
package/hooks/README.md
CHANGED
|
@@ -26,7 +26,7 @@ User request → Claude picks a tool → PreToolUse hook runs → Tool executes
|
|
|
26
26
|
| **Git push reminder** | `Bash` | Reminds to review changes before `git push` | 0 (warns) |
|
|
27
27
|
| **Pre-commit quality check** | `Bash` | Runs quality checks before `git commit`: lints staged files, validates commit message format when provided via `-m/--message`, detects console.log/debugger/secrets | 2 (blocks critical) / 0 (warns) |
|
|
28
28
|
| **Doc file warning** | `Write` | Warns about non-standard `.md`/`.txt` files (allows README, CLAUDE, CONTRIBUTING, CHANGELOG, LICENSE, SKILL, docs/, skills/); cross-platform path handling | 0 (warns) |
|
|
29
|
-
| **Strategic compact** |
|
|
29
|
+
| **Strategic compact** | `*` | Suggests `/compact` when context usage crosses 70/85/95% thresholds, using Claude context-window metrics when available | 0 (warns) |
|
|
30
30
|
| **InsAIts security monitor (opt-in)** | `Bash\|Write\|Edit\|MultiEdit` | Optional security scan for high-signal tool inputs. Disabled unless `ECC_ENABLE_INSAITS=1`. Blocks on critical findings, warns on non-critical, and writes audit log to `.insaits_audit_session.jsonl`. JS wrapper is the canonical hook entry; the Python monitor is an explicit third-party SDK exception. Requires `pip install insa-its`. [Details](../scripts/hooks/insaits-security-monitor.py) | 2 (blocks critical) / 0 (warns) |
|
|
31
31
|
|
|
32
32
|
### PostToolUse Hooks
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
// DEPRECATED: This hook's functionality has been merged into suggest-compact.js.
|
|
3
|
+
// The strategic-compact hook now covers all thresholds (65/70/85/95%).
|
|
4
|
+
// This file is retained for backward compatibility but is no longer registered in hooks.json.
|
|
5
|
+
//
|
|
2
6
|
// harness-context-monitor.js — PostToolUse hook (all tools)
|
|
3
7
|
// Reads context metrics from the bridge file written by harness-statusline.js
|
|
4
8
|
// and injects advisory warnings into agent context when usage is high.
|
package/hooks/hooks.json
CHANGED
|
@@ -69,15 +69,27 @@
|
|
|
69
69
|
"id": "pre:write:doc-file-warning"
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
|
-
"matcher": "
|
|
72
|
+
"matcher": "*",
|
|
73
73
|
"hooks": [
|
|
74
74
|
{
|
|
75
75
|
"type": "command",
|
|
76
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/
|
|
76
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/harness-statusline.js\""
|
|
77
77
|
}
|
|
78
78
|
],
|
|
79
|
-
"description": "
|
|
80
|
-
"id": "pre:
|
|
79
|
+
"description": "Display current role and context usage statusline (must run before strategic-compact to write bridge file)",
|
|
80
|
+
"id": "pre:all:harness-statusline"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"matcher": "*",
|
|
84
|
+
"hooks": [
|
|
85
|
+
{
|
|
86
|
+
"type": "command",
|
|
87
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/run-with-flags.js\" \"pre:all:strategic-compact\" \"scripts/hooks/suggest-compact.js\" \"standard,strict\"",
|
|
88
|
+
"timeout": 10
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
"description": "Suggest strategic context compaction when context usage crosses 65/70/85/95% thresholds",
|
|
92
|
+
"id": "pre:all:strategic-compact"
|
|
81
93
|
},
|
|
82
94
|
{
|
|
83
95
|
"matcher": "*",
|
|
@@ -151,28 +163,6 @@
|
|
|
151
163
|
"description": "Check MCP server health before MCP tool execution and block unhealthy MCP calls",
|
|
152
164
|
"id": "pre:mcp-health-check"
|
|
153
165
|
},
|
|
154
|
-
{
|
|
155
|
-
"matcher": "*",
|
|
156
|
-
"hooks": [
|
|
157
|
-
{
|
|
158
|
-
"type": "command",
|
|
159
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/harness-statusline.js\""
|
|
160
|
-
}
|
|
161
|
-
],
|
|
162
|
-
"description": "Display current role and context usage statusline",
|
|
163
|
-
"id": "pre:all:harness-statusline"
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
"matcher": "*",
|
|
167
|
-
"hooks": [
|
|
168
|
-
{
|
|
169
|
-
"type": "command",
|
|
170
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/harness-context-monitor.js\""
|
|
171
|
-
}
|
|
172
|
-
],
|
|
173
|
-
"description": "Monitor context budget, warn at 35%/25% thresholds",
|
|
174
|
-
"id": "pre:all:harness-context-monitor"
|
|
175
|
-
},
|
|
176
166
|
{
|
|
177
167
|
"matcher": "Bash",
|
|
178
168
|
"hooks": [
|
|
@@ -233,6 +223,17 @@
|
|
|
233
223
|
"description": "Load previous context and detect package manager on new session",
|
|
234
224
|
"id": "session:start"
|
|
235
225
|
},
|
|
226
|
+
{
|
|
227
|
+
"matcher": "*",
|
|
228
|
+
"hooks": [
|
|
229
|
+
{
|
|
230
|
+
"type": "command",
|
|
231
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/session-start-goal-resume.js\""
|
|
232
|
+
}
|
|
233
|
+
],
|
|
234
|
+
"description": "Check for active goals from previous sessions and inject resume reminder",
|
|
235
|
+
"id": "session:goal-resume"
|
|
236
|
+
},
|
|
236
237
|
{
|
|
237
238
|
"matcher": "*",
|
|
238
239
|
"hooks": [
|