ultimate-pi 0.12.0 → 0.13.0
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/.agents/skills/ck-search/SKILL.md +11 -87
- package/.agents/skills/cocoindex-search/SKILL.md +35 -0
- package/.agents/skills/harness-orchestration/SKILL.md +4 -4
- package/.pi/PACKAGING.md +1 -0
- package/.pi/SYSTEM.md +21 -20
- package/.pi/agents/harness/planning/scout-graphify.md +2 -0
- package/.pi/agents/harness/planning/scout-semantic.md +13 -6
- package/.pi/extensions/harness-run-context.ts +5 -0
- package/.pi/extensions/harness-subagents.ts +16 -5
- package/.pi/extensions/lib/harness-cocoindex-refresh.ts +49 -0
- package/.pi/extensions/lib/harness-subagent-policy.ts +5 -1
- package/.pi/extensions/lib/harness-subagents-bridge.ts +9 -63
- package/.pi/harness/docs/adrs/0033-parent-orchestrated-planning.md +1 -1
- package/.pi/prompts/harness-plan.md +10 -5
- package/.pi/prompts/harness-setup.md +15 -11
- package/.pi/scripts/README.md +1 -0
- package/.pi/scripts/harness-cli-verify.sh +24 -14
- package/.pi/scripts/harness-cocoindex-bootstrap.sh +182 -0
- package/.pi/scripts/harness-verify.mjs +10 -0
- package/.pi/skills/ast-grep/SKILL.md +2 -2
- package/.pi/skills/ccc/SKILL.md +142 -0
- package/.pi/skills/ccc/references/management.md +110 -0
- package/CHANGELOG.md +10 -0
- package/THIRD_PARTY_NOTICES.md +7 -0
- package/package.json +3 -2
- package/vendor/pi-subagents/LICENSE +21 -0
- package/vendor/pi-subagents/UPSTREAM_PIN.md +11 -0
- package/vendor/pi-subagents/src/agents.ts +357 -0
- package/vendor/pi-subagents/src/subagents.ts +1463 -0
|
@@ -1,99 +1,23 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ck-search
|
|
3
|
-
description: "
|
|
3
|
+
description: "DEPRECATED — ck-search was removed from ultimate-pi. Use cocoindex-search or /skill:ccc instead. Triggers retained for backward compatibility: ck, ck-search, semantic search."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# ck-search
|
|
6
|
+
# ck-search (deprecated)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
**`ck` / `@beaconbay/ck-search` is no longer used in this harness.**
|
|
9
9
|
|
|
10
|
-
Use
|
|
10
|
+
Use instead:
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
- **`/skill:cocoindex-search`** or **`/skill:ccc`** — CocoIndex Code (`ccc search`)
|
|
13
|
+
- **graphify** — architecture, callers, communities (`graphify query`, `explain`, `path`)
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
# Hybrid (best default — lexical + semantic fused via RRF)
|
|
16
|
-
ck --hybrid "query" .
|
|
17
|
-
|
|
18
|
-
# Semantic only (conceptual — finds by meaning)
|
|
19
|
-
ck --sem "concept" src/
|
|
20
|
-
|
|
21
|
-
# Lexical BM25 (phrase-based, better than grep for multi-word)
|
|
22
|
-
ck --lex "phrase" .
|
|
23
|
-
|
|
24
|
-
# Grep-compatible (exact match, same flags as grep)
|
|
25
|
-
ck "exact string" -rn src/
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Search Decision Tree
|
|
29
|
-
|
|
30
|
-
```
|
|
31
|
-
Agent needs to find code
|
|
32
|
-
├─ Exact literal string (error msg, function name) → grep/rg
|
|
33
|
-
├─ Conceptual / multi-word → ck --hybrid
|
|
34
|
-
├─ Find similar patterns → ck --sem
|
|
35
|
-
└─ Unsure → ck --hybrid (safe default)
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Key Flags
|
|
39
|
-
|
|
40
|
-
| Flag | Purpose | When |
|
|
41
|
-
|------|---------|------|
|
|
42
|
-
| `--hybrid` | BM25 + semantic RRF fusion | **Default for exploration** |
|
|
43
|
-
| `--sem` | Semantic only (embedding similarity) | Conceptual: "error handling", "auth flow" |
|
|
44
|
-
| `--lex` | BM25 lexical only | Phrase search without regex |
|
|
45
|
-
| `--limit N` | Top N results | Keep output lean (default 10) |
|
|
46
|
-
| `--threshold 0.7` | Min similarity score | Filter low-confidence results |
|
|
47
|
-
| `--json` | Machine-readable output | When piping to other tools |
|
|
48
|
-
| `-n` | Line numbers | Same as grep |
|
|
49
|
-
| `-C N` | Context lines | Same as grep |
|
|
50
|
-
| `-r` | Recursive | Same as grep |
|
|
51
|
-
| `-l` | Files with matches | List matching files only |
|
|
52
|
-
|
|
53
|
-
## Index Management
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
ck --status . # Check if index exists
|
|
57
|
-
ck index . # Build/rebuild full index
|
|
58
|
-
ck --add file.ts # Add single file to index
|
|
59
|
-
ck --clean . # Remove index (rebuild from scratch)
|
|
60
|
-
ck --switch-model MODEL # Rebuild with different embedding model
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
## Usage Patterns
|
|
15
|
+
## Migration
|
|
64
16
|
|
|
65
|
-
### Find related code
|
|
66
17
|
```bash
|
|
67
|
-
|
|
18
|
+
uv tool install 'cocoindex-code[full]'
|
|
19
|
+
bash "$UP_PKG/.pi/scripts/harness-cocoindex-bootstrap.sh"
|
|
20
|
+
ccc search --limit 10 "your query"
|
|
68
21
|
```
|
|
69
22
|
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
ck --sem "authentication middleware" src/ --limit 20
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### Find error handling patterns
|
|
76
|
-
```bash
|
|
77
|
-
ck --hybrid "error handling and recovery" src/ --limit 15
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### Find database code
|
|
81
|
-
```bash
|
|
82
|
-
ck --sem "database connection pool" src/
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### Exact function name (still use grep)
|
|
86
|
-
```bash
|
|
87
|
-
grep -rn "processPayment" src/
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
## Integration Notes
|
|
91
|
-
|
|
92
|
-
- **Index location**: `.ck/index/` in project root (gitignored)
|
|
93
|
-
- **First search auto-indexes**: `ck --sem` builds index on first run if missing
|
|
94
|
-
- **Fully offline**: No API keys, no network, embeddings run locally
|
|
95
|
-
- **MCP mode**: `ck --serve` exposes ck_search/ck_get/ck_info/ck_reindex as MCP tools (future integration)
|
|
96
|
-
|
|
97
|
-
## Token Efficiency
|
|
98
|
-
|
|
99
|
-
ck results are ranked and scored. Use `--limit` to cap output. A typical ck --hybrid call returns 10 results (~500-1000 tokens) vs raw grep which can return hundreds of unranked matches (~5000-20000 tokens).
|
|
23
|
+
Remove legacy index: `rm -rf .ck` (optional).
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cocoindex-search
|
|
3
|
+
description: "Semantic code search using CocoIndex Code (ccc). Use when exploring codebases, finding related implementation by meaning, or replacing legacy ck-search. Triggers on: semantic code search, ccc, cocoindex, cocoindex-code, find code related to, search the codebase for implementation, /skill:ck-search."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# cocoindex-search
|
|
7
|
+
|
|
8
|
+
CocoIndex Code (`ccc`) provides offline, AST-aware semantic search over the project codebase.
|
|
9
|
+
|
|
10
|
+
## Quick start
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
ccc search --limit 10 "harness subagent policy"
|
|
14
|
+
ccc status
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Full reference
|
|
18
|
+
|
|
19
|
+
Load the vendored skill: **`/skill:ccc`** (`.pi/skills/ccc/SKILL.md`).
|
|
20
|
+
|
|
21
|
+
## Harness lanes
|
|
22
|
+
|
|
23
|
+
| Question type | Tool |
|
|
24
|
+
|---------------|------|
|
|
25
|
+
| Callers, callees, cross-module paths | `graphify explain` / `graphify path` |
|
|
26
|
+
| Implementation by meaning | `ccc search --limit N "…"` |
|
|
27
|
+
| Structural patterns | `sg -p '…'` |
|
|
28
|
+
|
|
29
|
+
## Setup
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
bash "$UP_PKG/.pi/scripts/harness-cocoindex-bootstrap.sh"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Indexing before harness scouts is automatic — do not run `ccc index` or `ccc search --refresh` in `scout-semantic`.
|
|
@@ -36,7 +36,7 @@ LIMIT 30
|
|
|
36
36
|
1. **Parallel `tasks`** — one `subagent({ tasks: [...] })` for scouts, decompose+hypothesis, or review fan-in; subprocesses run in parallel upstream.
|
|
37
37
|
2. **Blocking calls** — each `subagent` returns when the subprocess exits; no `get_subagent_result` polling.
|
|
38
38
|
3. **Compact handoffs** — pass scout/decompose JSON only; never paste full subprocess message logs into the next spawn.
|
|
39
|
-
4. **Spawn caps** — bridge enforces **8** active + **12** total harness spawns per session
|
|
39
|
+
4. **Spawn caps** — bridge enforces **8** active + **12** total harness spawns per session. Do **not** pass `timeoutMs` unless the user wants a cap — subprocesses wait for natural exit (`PI_SUBAGENT_TIMEOUT_MS` optional env backstop only).
|
|
40
40
|
|
|
41
41
|
## Command → agent
|
|
42
42
|
|
|
@@ -71,9 +71,9 @@ Spawn `harness/evaluator` / `harness/adversary` via `subagent` in the **same** p
|
|
|
71
71
|
{
|
|
72
72
|
"agentScope": "both",
|
|
73
73
|
"tasks": [
|
|
74
|
-
{ "agent": "harness/planning/scout-graphify", "task": "…"
|
|
75
|
-
{ "agent": "harness/planning/scout-structure", "task": "…"
|
|
76
|
-
{ "agent": "harness/planning/scout-semantic", "task": "…"
|
|
74
|
+
{ "agent": "harness/planning/scout-graphify", "task": "…" },
|
|
75
|
+
{ "agent": "harness/planning/scout-structure", "task": "…" },
|
|
76
|
+
{ "agent": "harness/planning/scout-semantic", "task": "…" }
|
|
77
77
|
]
|
|
78
78
|
}
|
|
79
79
|
```
|
package/.pi/PACKAGING.md
CHANGED
|
@@ -24,6 +24,7 @@ We use an explicit allowlist (not the whole `.pi/` tree) so dev-only artifacts n
|
|
|
24
24
|
- Ship `.pi/settings.example.json`, not `.pi/settings.json` (dev checkout uses `".."` local package)
|
|
25
25
|
- Include **`vendor/pi-model-router/`** ([`pi-model-router`](https://github.com/yeliu84/pi-model-router), MIT) — see repo [`THIRD_PARTY_NOTICES.md`](../THIRD_PARTY_NOTICES.md); refresh with `npm run vendor:sync-router`
|
|
26
26
|
- Include **`vendor/pi-vcc/`** ([`pi-vcc`](https://github.com/sting8k/pi-vcc), MIT; inspired by [lllyasviel/VCC](https://github.com/lllyasviel/VCC)) — loaded via `.pi/extensions/ultimate-pi-vcc.ts`; refresh with `npm run vendor:sync-vcc`
|
|
27
|
+
- Include **`vendor/pi-subagents/`** (vendored from [narumiruna/pi-extensions](https://github.com/narumiruna/pi-extensions) `pi-subagents`) — loaded via `.pi/extensions/harness-subagents.ts`; refresh with `npm run vendor:sync-subagents`
|
|
27
28
|
|
|
28
29
|
## Settings
|
|
29
30
|
|
package/.pi/SYSTEM.md
CHANGED
|
@@ -81,41 +81,42 @@ edges at build time. Use these to answer call-graph questions without external t
|
|
|
81
81
|
- **How does `Auth` reach `Database`?** → `graphify path "Auth" "Database"` (shortest call chain)
|
|
82
82
|
- **Trace a dependency chain deep** → `graphify query "how does X depend on Y" --dfs`
|
|
83
83
|
|
|
84
|
-
**Semantic code search
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
84
|
+
**Semantic code search (two lanes):**
|
|
85
|
+
- **Architecture / relationships** → graphify (`query`, `explain`, `path`, `GRAPH_REPORT.md`)
|
|
86
|
+
- **Implementation by meaning** → CocoIndex Code (`ccc search --limit N "concept"`)
|
|
87
|
+
|
|
88
|
+
Examples:
|
|
89
|
+
- **Find code by meaning** → `ccc search --limit 10 "authentication session validation"`
|
|
90
|
+
- **Who calls X / cross-module path** → `graphify explain "X"` or `graphify path "A" "B"`
|
|
89
91
|
- **Cross-file surprises** → `graphify query "what unexpected connections exist"`
|
|
90
92
|
|
|
91
93
|
**Order of operations for codebase exploration:**
|
|
92
94
|
1. Read `graphify-out/GRAPH_REPORT.md` (god nodes, surprises, suggested questions)
|
|
93
|
-
2. Run `graphify query`
|
|
94
|
-
3. Use `
|
|
95
|
-
4. Use `
|
|
96
|
-
5. Read individual files last —
|
|
95
|
+
2. Run `graphify query` / `explain` / `path` for architecture and call graphs
|
|
96
|
+
3. Use `sg -p 'pattern'` for structural code search
|
|
97
|
+
4. Use `ccc search --limit N` for conceptual implementation chunks when graphify/sg are insufficient
|
|
98
|
+
5. Read individual files last — scouts and graph already narrowed the set
|
|
99
|
+
|
|
100
|
+
**Indexing:** Harness runs incremental `ccc index` before subagent spawns. Use `ccc search` only in agents; run `ccc index` at session start or after large edits on parent turns. Never use `ccc search --refresh` in scouts. `/skill:ccc` for full CLI reference.
|
|
97
101
|
|
|
98
102
|
### Fallback Search (when graph doesn't cover it)
|
|
99
103
|
|
|
100
|
-
> [!note] Graphify
|
|
101
|
-
> Graphify
|
|
102
|
-
>
|
|
103
|
-
> code exploration tools. Only fall back to `sg`/`ck`/`find` when the graph
|
|
104
|
-
> doesn't have the answer (e.g., not yet indexed, or you need exact raw text).
|
|
104
|
+
> [!note] Graphify + ccc split responsibilities
|
|
105
|
+
> Graphify owns call graphs and cross-module relationships. `ccc` owns AST-aware
|
|
106
|
+
> semantic chunks. Only fall back to `find`/`grep` for exact literals or non-code files.
|
|
105
107
|
|
|
106
108
|
| Tool | When | Command |
|
|
107
109
|
|------|------|---------|
|
|
108
|
-
| `sg -p` | **
|
|
110
|
+
| `sg -p` | **Structural code search** — AST pattern matching | `sg -p 'pattern' --lang typescript` |
|
|
109
111
|
| `sg scan` | Rule-based code scanning (use project rules in `sgconfig.yml`) | `sg scan` |
|
|
110
|
-
| `
|
|
111
|
-
| `ck --sem` | Purely conceptual searches (fallback after ast-grep) | `ck --sem "concept" src/` |
|
|
112
|
+
| `ccc search` | **Semantic chunks** — implementation by meaning | `ccc search --limit 10 "query"` |
|
|
112
113
|
| `find` | File discovery by name/glob only | `find . -name "*.ts"` |
|
|
113
114
|
| `grep` | **Last resort** — exact literal string matching in non-code files only | `grep -F "exact string"` |
|
|
114
115
|
|
|
115
|
-
- **Always prefer ast-grep (`sg`) over grep for code search.** ast-grep understands code structure via tree-sitter — it matches patterns, not strings.
|
|
116
|
+
- **Always prefer ast-grep (`sg`) over grep for code search.** ast-grep understands code structure via tree-sitter — it matches patterns, not strings.
|
|
116
117
|
- Never use grep for code search. grep is only for: log files, non-code text files, exact byte-level matching when AST patterns can't work.
|
|
117
|
-
- Always use `--limit N` on
|
|
118
|
-
- Graphify is primary. ast-grep is secondary.
|
|
118
|
+
- Always use `--limit N` on `ccc search` to cap output and save context.
|
|
119
|
+
- Graphify is primary for architecture. ast-grep is secondary for structure. ccc is semantic implementation search. grep is last resort.
|
|
119
120
|
- Do NOT install or use grepai/seagoat/mgrep for call-graph traces or semantic
|
|
120
121
|
search — graphify already handles both.
|
|
121
122
|
|
|
@@ -15,6 +15,8 @@ Explore the codebase via graphify for the task in `HarnessSpawnContext`. You do
|
|
|
15
15
|
|
|
16
16
|
Findings should feed **constraints, prior art, and tensions** for the decompose agent (existing patterns, god nodes, surprising connections).
|
|
17
17
|
|
|
18
|
+
**Lane contract:** you own **relationships and architecture** (`graphify query`, `explain`, `path`). `scout-semantic` owns implementation-by-meaning via `ccc search` — do not duplicate semantic chunk search here.
|
|
19
|
+
|
|
18
20
|
## Spawn context
|
|
19
21
|
|
|
20
22
|
Read `HarnessSpawnContext` in the spawn prompt (`task_summary`, `mode`, `plan_packet_path`, `risk_level`, `quick`). For `mode: revise`, read the existing plan at `plan_packet_path` first and focus findings on what changed or is at risk.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Plan-phase scout —
|
|
2
|
+
description: Plan-phase scout — CocoIndex semantic code search (read-only).
|
|
3
3
|
tools: read, bash, ls
|
|
4
4
|
disallowed_tools: write, edit, ask_user, approve_plan, create_plan, subagent, grep, find
|
|
5
5
|
extensions: false
|
|
@@ -11,7 +11,9 @@ You are the **Harness planning scout (semantic lane)**.
|
|
|
11
11
|
|
|
12
12
|
## Mission
|
|
13
13
|
|
|
14
|
-
Find conceptually related
|
|
14
|
+
Find conceptually related **implementation** via CocoIndex (`ccc search`) for the task in `HarnessSpawnContext`. You do **not** build the PlanPacket or mutate files.
|
|
15
|
+
|
|
16
|
+
**Lane contract:** `scout-graphify` owns relationships, callers, and communities. You own **meaning** — functions, classes, and chunks that implement the task.
|
|
15
17
|
|
|
16
18
|
## Spawn context
|
|
17
19
|
|
|
@@ -19,13 +21,18 @@ Read `HarnessSpawnContext` in the spawn prompt. For `mode: revise`, bias searche
|
|
|
19
21
|
|
|
20
22
|
## Process
|
|
21
23
|
|
|
22
|
-
1.
|
|
23
|
-
2.
|
|
24
|
-
3.
|
|
24
|
+
1. Run **2–3** task-focused queries: `ccc search "<query>" --limit 5` (add `--path` when spawn context names a directory).
|
|
25
|
+
2. The harness runs incremental `ccc index` before scouts spawn — **do not** run `ccc index`, `ccc init`, or `ccc search --refresh`.
|
|
26
|
+
3. If `ccc` is missing or the index is empty: `status: partial` and document in `findings`.
|
|
27
|
+
4. **Stop early** — top **5** most relevant paths only.
|
|
25
28
|
|
|
26
29
|
## Bash guardrails
|
|
27
30
|
|
|
28
|
-
Read-only only: no installs,
|
|
31
|
+
Read-only only: no installs, indexing, daemon control, or redirects.
|
|
32
|
+
|
|
33
|
+
**Allowed:** `ccc search`, `ccc status`, `ls`, `head`, `cat`, `sed -n` (read slices).
|
|
34
|
+
|
|
35
|
+
**Forbidden:** `ccc index`, `ccc init`, `ccc reset`, `ccc daemon`, `ccc search --refresh`, package installs.
|
|
29
36
|
|
|
30
37
|
## Output limits
|
|
31
38
|
|
|
@@ -55,6 +55,10 @@ import {
|
|
|
55
55
|
parseStructuredDocument,
|
|
56
56
|
writeYamlFile,
|
|
57
57
|
} from "../lib/harness-yaml.js";
|
|
58
|
+
import { claimExtensionLoad } from "./lib/extension-load-guard.js";
|
|
59
|
+
|
|
60
|
+
// @ts-expect-error pi extensions run as ESM
|
|
61
|
+
const MODULE_URL = import.meta.url;
|
|
58
62
|
|
|
59
63
|
interface SessionEntryLike {
|
|
60
64
|
type?: string;
|
|
@@ -191,6 +195,7 @@ function needsClarificationFollowUp(ctx: HarnessRunContext | null): boolean {
|
|
|
191
195
|
}
|
|
192
196
|
|
|
193
197
|
export default function harnessRunContext(pi: ExtensionAPI) {
|
|
198
|
+
if (!claimExtensionLoad("harness-run-context", MODULE_URL)) return;
|
|
194
199
|
let activeCtx: HarnessRunContext | null = null;
|
|
195
200
|
|
|
196
201
|
pi.on("session_start", async (_event, ctx) => {
|
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* harness-subagents — vendored pi-subagents with ultimate-pi discovery and policy gates.
|
|
3
|
+
*
|
|
4
|
+
* Dynamic-imports the bridge only after claimExtensionLoad so a stale global npm
|
|
5
|
+
* install (missing vendor/pi-subagents) does not crash local development in this repo.
|
|
3
6
|
*/
|
|
4
7
|
|
|
8
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
5
9
|
import { claimExtensionLoad } from "./lib/extension-load-guard.js";
|
|
6
|
-
import { getHarnessPackageRoot } from "./lib/harness-paths.js";
|
|
7
|
-
import { createHarnessSubagentsExtension } from "./lib/harness-subagents-bridge.js";
|
|
8
10
|
|
|
9
11
|
// @ts-expect-error pi extensions run as ESM
|
|
10
12
|
const MODULE_URL = import.meta.url;
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
async function loadHarnessSubagents(): Promise<(pi: ExtensionAPI) => void> {
|
|
15
|
+
if (!claimExtensionLoad("harness-subagents", MODULE_URL)) {
|
|
16
|
+
return () => {};
|
|
17
|
+
}
|
|
18
|
+
const { getHarnessPackageRoot } = await import("./lib/harness-paths.js");
|
|
19
|
+
const { createHarnessSubagentsExtension } = await import(
|
|
20
|
+
"./lib/harness-subagents-bridge.js"
|
|
21
|
+
);
|
|
22
|
+
return createHarnessSubagentsExtension(getHarnessPackageRoot(MODULE_URL));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default await loadHarnessSubagents();
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Incremental CocoIndex refresh before harness subagent batches (plan/execute).
|
|
3
|
+
* Agents use `ccc search` only; harness owns `ccc index`.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { spawnSync } from "node:child_process";
|
|
7
|
+
import { existsSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
|
|
10
|
+
const DEFAULT_TIMEOUT_MS = 120_000;
|
|
11
|
+
|
|
12
|
+
export function refreshHarnessCocoindexIndex(cwd: string): string | undefined {
|
|
13
|
+
if (process.env.HARNESS_COCOINDEX_REFRESH === "0") {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
const settingsPath = join(cwd, ".cocoindex_code", "settings.yml");
|
|
17
|
+
if (!existsSync(settingsPath)) {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const timeoutMs = Number(
|
|
22
|
+
process.env.HARNESS_COCOINDEX_REFRESH_TIMEOUT_MS ?? DEFAULT_TIMEOUT_MS,
|
|
23
|
+
);
|
|
24
|
+
const result = spawnSync("ccc", ["index"], {
|
|
25
|
+
cwd,
|
|
26
|
+
encoding: "utf8",
|
|
27
|
+
timeout: Number.isFinite(timeoutMs) ? timeoutMs : DEFAULT_TIMEOUT_MS,
|
|
28
|
+
stdio: "pipe",
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (result.error) {
|
|
32
|
+
const msg = `harness-cocoindex: ccc index failed (${result.error.message})`;
|
|
33
|
+
if (process.env.HARNESS_COCOINDEX_REFRESH_STRICT === "1") {
|
|
34
|
+
return msg;
|
|
35
|
+
}
|
|
36
|
+
return `${msg} — continuing`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (result.status !== 0) {
|
|
40
|
+
const stderr = (result.stderr ?? "").trim().slice(0, 500);
|
|
41
|
+
const msg = `harness-cocoindex: ccc index exited ${result.status ?? "?"}${stderr ? `: ${stderr}` : ""}`;
|
|
42
|
+
if (process.env.HARNESS_COCOINDEX_REFRESH_STRICT === "1") {
|
|
43
|
+
return msg;
|
|
44
|
+
}
|
|
45
|
+
return `${msg} — continuing`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
@@ -24,9 +24,13 @@ const PLANNING_BASH_DENY_PATTERNS = [
|
|
|
24
24
|
/\bgraphify\s+update\b/i,
|
|
25
25
|
/\bgraphify\s+extract\b/i,
|
|
26
26
|
/\bgraphify\s+install\b/i,
|
|
27
|
+
/\bccc\s+(index|init|reset|daemon)\b/i,
|
|
28
|
+
/\bccc\s+search\b.*--refresh/i,
|
|
27
29
|
/\bpip\s+install\b/i,
|
|
28
30
|
/\buv\s+tool\s+install\b/i,
|
|
29
31
|
/\bnpm\s+install\b/i,
|
|
32
|
+
/\bnpm\s+install\b.*cocoindex/i,
|
|
33
|
+
/\buv\s+tool\s+install\b.*cocoindex/i,
|
|
30
34
|
];
|
|
31
35
|
|
|
32
36
|
const BASH_MUTATION_PATTERNS = [
|
|
@@ -141,7 +145,7 @@ export function evaluateHarnessSubagentToolCall(
|
|
|
141
145
|
return {
|
|
142
146
|
action: "block",
|
|
143
147
|
reason:
|
|
144
|
-
"harness-subagent-policy: planning scouts may use read-only graphify/sg/
|
|
148
|
+
"harness-subagent-policy: planning scouts may use read-only graphify/sg/ccc commands only.",
|
|
145
149
|
};
|
|
146
150
|
}
|
|
147
151
|
}
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
type HarnessSubagentsOptions,
|
|
13
13
|
type SpawnAuthForward,
|
|
14
14
|
} from "../../../vendor/pi-subagents/src/subagents.js";
|
|
15
|
+
import { refreshHarnessCocoindexIndex } from "./harness-cocoindex-refresh.js";
|
|
15
16
|
import { captureHarnessEvent } from "./harness-posthog.js";
|
|
16
17
|
import {
|
|
17
18
|
checkHarnessSpawnBudget,
|
|
@@ -32,37 +33,6 @@ import {
|
|
|
32
33
|
const spawnBudget = createSpawnBudgetState();
|
|
33
34
|
let lastSessionId = "harness";
|
|
34
35
|
|
|
35
|
-
function maskApiKey(key: string | undefined): string | undefined {
|
|
36
|
-
if (!key) return undefined;
|
|
37
|
-
if (key.length <= 12) return "***";
|
|
38
|
-
return `${key.slice(0, 7)}…${key.slice(-4)}`;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// #region agent log
|
|
42
|
-
function agentDebugLog(
|
|
43
|
-
hypothesisId: string,
|
|
44
|
-
location: string,
|
|
45
|
-
message: string,
|
|
46
|
-
data: Record<string, unknown>,
|
|
47
|
-
): void {
|
|
48
|
-
fetch("http://127.0.0.1:7928/ingest/a5d40896-34cb-4f12-97db-df7ada0b22f0", {
|
|
49
|
-
method: "POST",
|
|
50
|
-
headers: {
|
|
51
|
-
"Content-Type": "application/json",
|
|
52
|
-
"X-Debug-Session-Id": "e762d5",
|
|
53
|
-
},
|
|
54
|
-
body: JSON.stringify({
|
|
55
|
-
sessionId: "e762d5",
|
|
56
|
-
hypothesisId,
|
|
57
|
-
location,
|
|
58
|
-
message,
|
|
59
|
-
data,
|
|
60
|
-
timestamp: Date.now(),
|
|
61
|
-
}),
|
|
62
|
-
}).catch(() => {});
|
|
63
|
-
}
|
|
64
|
-
// #endregion
|
|
65
|
-
|
|
66
36
|
async function resolveHarnessSpawnAuth(
|
|
67
37
|
ctx: ExtensionContext,
|
|
68
38
|
agent: AgentConfig,
|
|
@@ -72,43 +42,11 @@ async function resolveHarnessSpawnAuth(
|
|
|
72
42
|
: undefined;
|
|
73
43
|
const concrete = resolveConcreteSubagentModel(ctx.cwd, parentModel, agent);
|
|
74
44
|
if (!concrete) {
|
|
75
|
-
// #region agent log
|
|
76
|
-
agentDebugLog(
|
|
77
|
-
"D",
|
|
78
|
-
"harness-subagents-bridge.ts:resolveHarnessSpawnAuth",
|
|
79
|
-
"no concrete model",
|
|
80
|
-
{
|
|
81
|
-
agent: agent.name,
|
|
82
|
-
agentModel: agent.model,
|
|
83
|
-
parentModel: parentModel
|
|
84
|
-
? `${parentModel.provider}/${parentModel.id}`
|
|
85
|
-
: undefined,
|
|
86
|
-
},
|
|
87
|
-
);
|
|
88
|
-
// #endregion
|
|
89
45
|
return undefined;
|
|
90
46
|
}
|
|
91
47
|
const apiKey = await ctx.modelRegistry.getApiKeyForProvider(
|
|
92
48
|
concrete.provider,
|
|
93
49
|
);
|
|
94
|
-
// #region agent log
|
|
95
|
-
agentDebugLog(
|
|
96
|
-
"F",
|
|
97
|
-
"harness-subagents-bridge.ts:resolveHarnessSpawnAuth",
|
|
98
|
-
"concrete subprocess auth",
|
|
99
|
-
{
|
|
100
|
-
agent: agent.name,
|
|
101
|
-
parentModel: parentModel
|
|
102
|
-
? `${parentModel.provider}/${parentModel.id}`
|
|
103
|
-
: undefined,
|
|
104
|
-
concreteModel: concrete.modelRef,
|
|
105
|
-
routerProfile: concrete.routerProfile,
|
|
106
|
-
routerTier: concrete.routerTier,
|
|
107
|
-
apiKey: maskApiKey(apiKey),
|
|
108
|
-
usable: isUsableApiKey(apiKey),
|
|
109
|
-
},
|
|
110
|
-
);
|
|
111
|
-
// #endregion
|
|
112
50
|
if (!isUsableApiKey(apiKey)) return undefined;
|
|
113
51
|
return {
|
|
114
52
|
provider: concrete.provider,
|
|
@@ -145,6 +83,14 @@ export function createHarnessSubagentsExtension(
|
|
|
145
83
|
if (!pre.ok) {
|
|
146
84
|
return { ok: false, message: pre.message };
|
|
147
85
|
}
|
|
86
|
+
if (phase === "plan" || phase === "execute") {
|
|
87
|
+
const refreshMsg = refreshHarnessCocoindexIndex(ctx.cwd);
|
|
88
|
+
if (refreshMsg?.includes("continuing")) {
|
|
89
|
+
// warn-only path; do not block spawn
|
|
90
|
+
} else if (refreshMsg) {
|
|
91
|
+
return { ok: false, message: refreshMsg };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
148
94
|
}
|
|
149
95
|
return { ok: true };
|
|
150
96
|
},
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
### Positive
|
|
20
20
|
|
|
21
21
|
- Full plan visible in parent session; editor `plan-review.md` path surfaced from parent.
|
|
22
|
-
- Specialized scouts (graphify, ast-grep,
|
|
22
|
+
- Specialized scouts (graphify, ast-grep, cocoindex `ccc`) run in parallel with clear JSON contracts.
|
|
23
23
|
- Pre-approval adversary separate from post-run `harness/adversary`.
|
|
24
24
|
|
|
25
25
|
### Negative
|
|
@@ -30,8 +30,9 @@ Read **harness-debate-plan** skill before Review Gate rounds.
|
|
|
30
30
|
|
|
31
31
|
1. Use `subagent` with `agentScope: "both"` and parallel `tasks` where lanes are independent.
|
|
32
32
|
2. Each `subagent` call blocks until subprocesses finish — batch parallel scouts in one `tasks` array.
|
|
33
|
-
3.
|
|
34
|
-
4.
|
|
33
|
+
3. Do **not** set `timeoutMs` unless the user explicitly requests a cap — subagents run until natural completion (optional backstop: `PI_SUBAGENT_TIMEOUT_MS`).
|
|
34
|
+
4. Cap: **12** harness subagent invocations per parent session (extension-enforced).
|
|
35
|
+
5. Compact task text: embed `HarnessSpawnContext` JSON + lane-specific instructions only.
|
|
35
36
|
|
|
36
37
|
## Step 0 — Parse `$ARGUMENTS`
|
|
37
38
|
|
|
@@ -44,19 +45,23 @@ Read **harness-debate-plan** skill before Review Gate rounds.
|
|
|
44
45
|
|
|
45
46
|
Use `[HarnessActivePlan]` / `[HarnessRunContext]` only. On revise: preserve `plan_id` / `task_id`. Canonical paths: `plan-packet.yaml`, `research-brief.yaml`, `artifacts/*.yaml`.
|
|
46
47
|
|
|
48
|
+
## Phase 0 — Semantic index (automatic)
|
|
49
|
+
|
|
50
|
+
Do **not** run `ccc index` or `ccc search --refresh`. The harness runs incremental `ccc index` before subagent spawns. Proceed directly to Phase 1 scouts.
|
|
51
|
+
|
|
47
52
|
## Phase 1 — Parallel scouts
|
|
48
53
|
|
|
49
54
|
```json
|
|
50
55
|
{
|
|
51
56
|
"agentScope": "both",
|
|
52
57
|
"tasks": [
|
|
53
|
-
{ "agent": "harness/planning/scout-graphify", "task": "<HarnessSpawnContext + graphify lane>"
|
|
54
|
-
{ "agent": "harness/planning/scout-structure", "task": "<HarnessSpawnContext + structure lane>"
|
|
58
|
+
{ "agent": "harness/planning/scout-graphify", "task": "<HarnessSpawnContext + graphify lane>" },
|
|
59
|
+
{ "agent": "harness/planning/scout-structure", "task": "<HarnessSpawnContext + structure lane>" }
|
|
55
60
|
]
|
|
56
61
|
}
|
|
57
62
|
```
|
|
58
63
|
|
|
59
|
-
Add `harness/planning/scout-semantic` to `tasks` unless `--quick`. Require graphify + structure success.
|
|
64
|
+
Add `harness/planning/scout-semantic` to `tasks` unless `--quick`. Require graphify + structure success. Semantic lane uses `ccc search` only (see `scout-semantic` agent).
|
|
60
65
|
|
|
61
66
|
## Phase 2 & 3 — Decompose + hypothesis (parallel)
|
|
62
67
|
|
|
@@ -156,7 +156,7 @@ bash "$UP_PKG/.pi/scripts/harness-cli-verify.sh"
|
|
|
156
156
|
|
|
157
157
|
**Required (script must exit 0):** scrapling + harness-web smoke, ctx7, biome, ast-grep (`sg`), sentrux (when harness manifest present).
|
|
158
158
|
|
|
159
|
-
**Warnings allowed:** gh (if not authenticated), agent-browser (if OS libs need manual `sudo apt-get install`),
|
|
159
|
+
**Warnings allowed:** gh (if not authenticated), agent-browser (if OS libs need manual `sudo apt-get install`), cocoindex-code (empty corpus on tiny repos; first `[full]` install downloads local embedding model).
|
|
160
160
|
|
|
161
161
|
If the script reports **agent-browser shared library errors** on Linux/WSL, run the fix it prints, then re-verify:
|
|
162
162
|
|
|
@@ -232,20 +232,24 @@ if [ ! -f .pi/harness/browser.json ]; then
|
|
|
232
232
|
fi
|
|
233
233
|
```
|
|
234
234
|
|
|
235
|
-
### 2.4 —
|
|
235
|
+
### 2.4 — CocoIndex Code (semantic code search)
|
|
236
|
+
|
|
237
|
+
Offline semantic search via [CocoIndex Code](https://cocoindex.io/cocoindex-code/) (`ccc`). **CLI only** — do not register `ccc mcp` in harness setup (MCP defaults to refresh-before-search and is slower).
|
|
236
238
|
|
|
237
239
|
```bash
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
240
|
+
command -v uv &>/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
241
|
+
export PATH="$HOME/.local/bin:$PATH"
|
|
242
|
+
uv tool install 'cocoindex-code[full]' # or: pipx install 'cocoindex-code[full]'
|
|
243
|
+
bash "$UP_PKG/.pi/scripts/harness-cocoindex-bootstrap.sh"
|
|
244
|
+
# Rebuild index: bash "$UP_PKG/.pi/scripts/harness-cocoindex-bootstrap.sh" --force
|
|
245
|
+
ccc status
|
|
241
246
|
```
|
|
242
247
|
|
|
243
|
-
|
|
248
|
+
**Indexing before scouts is automatic:** `harness-subagents` runs incremental `ccc index` before plan/execute subagent batches. Agents use `ccc search` only.
|
|
244
249
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
```
|
|
250
|
+
**First install:** `[full]` pulls sentence-transformers + torch (~hundreds of MB–1GB+). Run bootstrap once; do not run `ccc index` inside scouts.
|
|
251
|
+
|
|
252
|
+
Verify: `ccc doctor` and `ccc search --limit 3 "export function"` (no `--refresh`).
|
|
249
253
|
|
|
250
254
|
### 2.5 — biome (Lint + Format Gate)
|
|
251
255
|
|
|
@@ -666,7 +670,7 @@ Output summary table:
|
|
|
666
670
|
| scrapling / harness-web | ✓/✗ | Auth: yes/no |
|
|
667
671
|
| ctx7 | ✓/✗ | Login: yes/no |
|
|
668
672
|
| agent-browser | ✓/✗ | Config: .pi/harness/browser.json |
|
|
669
|
-
|
|
|
673
|
+
| cocoindex-code | ✓/✗ | `ccc status`; index auto-refreshed before harness scouts |
|
|
670
674
|
| biome | ✓/✗ | Project config: found/default |
|
|
671
675
|
| ast-grep | ✓/✗ | AST-aware code search (`sg`)
|
|
672
676
|
| gh CLI | ✓/✗ | Auth: yes/no |
|
package/.pi/scripts/README.md
CHANGED
|
@@ -21,6 +21,7 @@ From **Typescript extensions**, use `resolveHarnessScript()` / `getHarnessPackag
|
|
|
21
21
|
| Action | Command |
|
|
22
22
|
|--------|---------|
|
|
23
23
|
| Graphify bootstrap | `bash "$UP_PKG/.pi/scripts/harness-graphify-bootstrap.sh"` |
|
|
24
|
+
| CocoIndex Code bootstrap | `bash "$UP_PKG/.pi/scripts/harness-cocoindex-bootstrap.sh"` |
|
|
24
25
|
| CLI tool install + smoke tests | `bash "$UP_PKG/.pi/scripts/harness-cli-verify.sh"` |
|
|
25
26
|
| Deterministic harness checks | `node "$UP_PKG/.pi/scripts/harness-verify.mjs"` |
|
|
26
27
|
| Sentrux rules bootstrap (harness-setup) | `node "$UP_PKG/.pi/scripts/harness-sentrux-bootstrap.mjs"` |
|