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.
@@ -1,99 +1,23 @@
1
1
  ---
2
2
  name: ck-search
3
- description: "Semantic code search using ck. Use when exploring codebases, finding related code, or searching by concept rather than exact text. Triggers on: search for, find code that, where is, look for patterns, find all files related to, find similar code, explore codebase, semantic search."
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: Semantic Code Search
6
+ # ck-search (deprecated)
7
7
 
8
- ## When to Use
8
+ **`ck` / `@beaconbay/ck-search` is no longer used in this harness.**
9
9
 
10
- Use `ck` instead of `grep`/`find` for **any codebase exploration**. Reserve raw grep for only: exact literal string match (specific error message, exact function name).
10
+ Use instead:
11
11
 
12
- ## Quick Reference
12
+ - **`/skill:cocoindex-search`** or **`/skill:ccc`** — CocoIndex Code (`ccc search`)
13
+ - **graphify** — architecture, callers, communities (`graphify query`, `explain`, `path`)
13
14
 
14
- ```bash
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
- ck --hybrid "retry logic with exponential backoff" .
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
- ### Find authentication code
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 (`PI_SUBAGENT_TIMEOUT_MS` / per-task `timeoutMs` for backstop).
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": "…", "timeoutMs": 90000 },
75
- { "agent": "harness/planning/scout-structure", "task": "…", "timeoutMs": 90000 },
76
- { "agent": "harness/planning/scout-semantic", "task": "…", "timeoutMs": 90000 }
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 via graphify:**
85
- Graphify already indexes the entire codebase as a knowledge graph. Use graphify
86
- for conceptual code search before falling back to `ck`:
87
- - **Find code by meaning** → `graphify query "where is authentication logic"`
88
- - **Find related concepts** → `graphify query "what connects to error handling"`
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` for domain-specific questions, call traces, and semantic search
94
- 3. Use `graphify explain "Concept"` for caller/callee/dependency deep dives
95
- 4. Use `sg -p 'pattern'` for structural code search, then `ck --hybrid` only if graph and ast-grep don't surface it
96
- 5. Read individual files last — the graph already told you what matters
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 handles semantic search and call graphs
101
- > Graphify already provides semantic code search and call-graph tracing. Use
102
- > `graphify query`, `graphify explain`, and `graphify path` as your primary
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` | **Primary code search** — AST-aware structural pattern matching | `sg -p 'pattern' --lang typescript` |
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
- | `ck --hybrid` | Lexical + semantic fusion search (fallback after ast-grep) | `ck --hybrid "query" .` |
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. Use it for: finding function calls, class definitions, import statements, variable usage, and any structural code query.
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 ck to cap output and save context.
118
- - Graphify is primary. ast-grep is secondary. ck/find are fallbacks. grep is last resort.
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 — ck semantic code search (read-only).
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 code via ck semantic search for the task in `HarnessSpawnContext`. You do **not** build the PlanPacket or mutate files.
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. Use `ck search` or `ck query` (or project-documented ck CLI) with task-focused queries.
23
- 2. If ck is unavailable, set `status: partial` and document in `findings`.
24
- 3. **Stop early** top **5** most relevant paths only.
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, index rebuilds that mutate disk, or redirects.
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
- export default claimExtensionLoad("harness-subagents", MODULE_URL)
13
- ? createHarnessSubagentsExtension(getHarnessPackageRoot(MODULE_URL))
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/ck commands only.",
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, ck) run in parallel with clear JSON contracts.
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. Cap: **12** harness subagent invocations per parent session (extension-enforced).
34
- 4. Compact task text: embed `HarnessSpawnContext` JSON + lane-specific instructions only.
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>", "timeoutMs": 90000 },
54
- { "agent": "harness/planning/scout-structure", "task": "<HarnessSpawnContext + structure lane>", "timeoutMs": 90000 }
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`), ck (empty corpus on tiny repos).
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 — ck-search (Semantic Code Search)
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
- if ! command -v ck &>/dev/null || [ "$FORCE" = "true" ]; then
239
- npm install -g @beaconbay/ck-search
240
- fi
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
- Verify: `ck --version`
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
- Register as MCP server (if Claude MCP available):
246
- ```bash
247
- claude mcp list 2>/dev/null && claude mcp add ck-search -s user -- ck --serve || echo "MCP not available — ck will be used as CLI only"
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
- | ck-search | ✓/✗ | MCP: registered/CLI-only |
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 |
@@ -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"` |