ultimate-pi 0.2.3 → 0.2.5

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.
Files changed (57) hide show
  1. package/.pi/extensions/custom-header.ts +26 -2
  2. package/.pi/extensions/lib/harness-paths.ts +55 -0
  3. package/.pi/extensions/model-router-bootstrap.ts +174 -0
  4. package/.pi/extensions/sentrux-rules-sync.ts +28 -3
  5. package/.pi/harness/browser.json +5 -0
  6. package/.pi/harness/debates/README.md +9 -0
  7. package/.pi/harness/docs/adrs/0006-sentrux-dual-layer.md +1 -1
  8. package/.pi/harness/docs/adrs/0009-sentrux-rules-lifecycle.md +2 -2
  9. package/.pi/harness/incidents/README.md +6 -0
  10. package/.pi/harness/release-readiness-report.md +128 -0
  11. package/.pi/harness/router/proposals/canary-proposal.json +96 -0
  12. package/.pi/harness/runs/019e272f-3eef-7107-9712-ce281de55707-1778773891854/events.jsonl +2 -0
  13. package/.pi/harness/runs/019e272f-3eef-7107-9712-ce281de55707-1778773891854/trace.json +17 -0
  14. package/.pi/harness/runs/019e272f-3eef-7107-9712-ce281de55707-1778773912057/events.jsonl +2 -0
  15. package/.pi/harness/runs/019e272f-3eef-7107-9712-ce281de55707-1778773912057/trace.json +17 -0
  16. package/.pi/harness/runs/019e2732-8651-74e5-9f5d-4d06c3105f25-1778774086096/events.jsonl +6 -0
  17. package/.pi/harness/runs/019e2732-8651-74e5-9f5d-4d06c3105f25-1778774086096/trace.json +42 -0
  18. package/.pi/harness/runs/019e2732-8651-74e5-9f5d-4d06c3105f25-1778774136101/events.jsonl +1 -0
  19. package/.pi/harness/runs/019e2758-b332-771b-ad6f-54d0d8478768-1778776600591/events.jsonl +2 -0
  20. package/.pi/harness/runs/019e2758-b332-771b-ad6f-54d0d8478768-1778776600591/trace.json +17 -0
  21. package/.pi/harness/runs/README.md +6 -0
  22. package/.pi/harness/runs/budget-events.jsonl +4 -0
  23. package/.pi/harness/runs/canary-candidate-router.json +72 -0
  24. package/.pi/harness/runs/canary-evidence.json +9 -0
  25. package/.pi/harness/runs/index.jsonl +4 -0
  26. package/.pi/harness/sentrux/architecture.manifest.json +3 -3
  27. package/.pi/model-router.example.json +27 -0
  28. package/.pi/prompts/graphify.md +4 -8
  29. package/.pi/prompts/harness-setup.md +142 -92
  30. package/.pi/prompts/release.md +225 -0
  31. package/.pi/scripts/README.md +17 -0
  32. package/.pi/scripts/harness-cli-verify.sh +294 -0
  33. package/.pi/scripts/harness-graphify-bootstrap.sh +151 -0
  34. package/{scripts → .pi/scripts}/harness-verify.mjs +3 -3
  35. package/{scripts → .pi/scripts}/sentrux-rules-sync.mjs +2 -2
  36. package/.pi/settings.json +0 -2
  37. package/.sentrux/.harness-rules-meta.json +2 -2
  38. package/.sentrux/rules.toml +3 -3
  39. package/AGENTS.md +12 -0
  40. package/CHANGELOG.md +21 -0
  41. package/README.md +39 -350
  42. package/firecrawl/.env +53 -0
  43. package/package.json +16 -4
  44. package/.ckignore +0 -41
  45. package/.env.example +0 -21
  46. package/.gitattributes +0 -1
  47. package/.github/banner-v2.png +0 -0
  48. package/.github/workflows/lint.yml +0 -33
  49. package/.github/workflows/publish-github-packages.yml +0 -35
  50. package/.github/workflows/publish-npm.yml +0 -32
  51. package/CONTRIBUTING.md +0 -166
  52. package/lefthook.yml +0 -9
  53. package/scripts/__pycache__/merge_graphify_corpora.cpython-314.pyc +0 -0
  54. package/scripts/index_youtube_urls.py +0 -376
  55. package/scripts/merge_graphify_corpora.py +0 -398
  56. package/scripts/regen_graphify_html.py +0 -46
  57. package/test/harness-verify.test.mjs +0 -33
@@ -0,0 +1,42 @@
1
+ {
2
+ "schema_version": "1.0.0",
3
+ "contract_version": "1.0.0",
4
+ "run_id": "019e2732-8651-74e5-9f5d-4d06c3105f25-1778774086096",
5
+ "plan_id": "plan-unknown",
6
+ "agent_id": "019e2732-8651-74e5-9f5d-4d06c3105f25",
7
+ "phase": "plan",
8
+ "model": "auto",
9
+ "thinking_level": "off",
10
+ "tool_spans": [
11
+ {
12
+ "tool_call_id": "call_00_7UHDcydTHJHVR2dT5xpb0903",
13
+ "tool_name": "bash",
14
+ "started_at": "2026-05-14T15:54:59.108Z",
15
+ "ended_at": "2026-05-14T15:54:59.108Z"
16
+ },
17
+ {
18
+ "tool_call_id": "call_01_aNsry1whTl5hRf5Ew91t3142",
19
+ "tool_name": "bash",
20
+ "started_at": "2026-05-14T15:54:59.136Z",
21
+ "ended_at": "2026-05-14T15:54:59.136Z"
22
+ },
23
+ {
24
+ "tool_call_id": "call_02_N2e56Q6vKr6cAYzd4Z9q7953",
25
+ "tool_name": "bash",
26
+ "started_at": "2026-05-14T15:54:59.139Z",
27
+ "ended_at": "2026-05-14T15:54:59.139Z"
28
+ },
29
+ {
30
+ "tool_call_id": "call_00_wG71Rv3SKrf6R9K03EeS0264",
31
+ "tool_name": "ctx_batch_execute",
32
+ "started_at": "2026-05-14T15:55:11.541Z",
33
+ "ended_at": "2026-05-14T15:55:11.541Z"
34
+ }
35
+ ],
36
+ "artifact_refs": [],
37
+ "cost": {
38
+ "input_tokens": 16951,
39
+ "output_tokens": 1020,
40
+ "total_tokens": 17971
41
+ }
42
+ }
@@ -0,0 +1 @@
1
+ {"timestamp":"2026-05-14T15:55:36.107Z","type":"run_start","run_id":"019e2732-8651-74e5-9f5d-4d06c3105f25-1778774136101","plan_id":"plan-unknown","phase":"plan"}
@@ -0,0 +1,2 @@
1
+ {"timestamp":"2026-05-14T16:36:40.660Z","type":"run_start","run_id":"019e2758-b332-771b-ad6f-54d0d8478768-1778776600591","plan_id":"plan-unknown","phase":"plan"}
2
+ {"timestamp":"2026-05-14T16:36:47.570Z","type":"run_end","run_id":"019e2758-b332-771b-ad6f-54d0d8478768-1778776600591","phase":"plan","tool_span_count":0,"artifact_ref_count":0}
@@ -0,0 +1,17 @@
1
+ {
2
+ "schema_version": "1.0.0",
3
+ "contract_version": "1.0.0",
4
+ "run_id": "019e2758-b332-771b-ad6f-54d0d8478768-1778776600591",
5
+ "plan_id": "plan-unknown",
6
+ "agent_id": "019e2758-b332-771b-ad6f-54d0d8478768",
7
+ "phase": "plan",
8
+ "model": "auto",
9
+ "thinking_level": "off",
10
+ "tool_spans": [],
11
+ "artifact_refs": [],
12
+ "cost": {
13
+ "input_tokens": 21,
14
+ "output_tokens": 32,
15
+ "total_tokens": 53
16
+ }
17
+ }
@@ -0,0 +1,6 @@
1
+ # Harness Runs
2
+
3
+ Store lightweight run metadata and trace indexes here.
4
+
5
+ - Primary source of truth for full trace payloads remains external telemetry.
6
+ - Local files should contain run IDs, pointers, and replay metadata only.
@@ -0,0 +1,4 @@
1
+ {"timestamp":"2026-05-14T15:54:59.134Z","schema_version":"1.0.0","contract_version":"1.0.0","event_type":"budget_exhausted","run_id":"019e2732-8651-74e5-9f5d-4d06c3105f25","debate_id":"plan-budget-guard","round_count":1,"budget_used":16593,"exhaustion_reason":"debate_global_cap_exceeded","caps":{"max_rounds":6,"round_token_cap":2500,"debate_global_cap":35000},"minimum_evidence_confidence":0.6,"default_policy_outcome":"block","human_override_allowed":true}
2
+ {"timestamp":"2026-05-14T15:54:59.138Z","schema_version":"1.0.0","contract_version":"1.0.0","event_type":"budget_exhausted","run_id":"019e2732-8651-74e5-9f5d-4d06c3105f25","debate_id":"plan-budget-guard","round_count":1,"budget_used":16593,"exhaustion_reason":"debate_global_cap_exceeded","caps":{"max_rounds":6,"round_token_cap":2500,"debate_global_cap":35000},"minimum_evidence_confidence":0.6,"default_policy_outcome":"block","human_override_allowed":true}
3
+ {"timestamp":"2026-05-14T15:54:59.140Z","schema_version":"1.0.0","contract_version":"1.0.0","event_type":"budget_exhausted","run_id":"019e2732-8651-74e5-9f5d-4d06c3105f25","debate_id":"plan-budget-guard","round_count":1,"budget_used":16593,"exhaustion_reason":"debate_global_cap_exceeded","caps":{"max_rounds":6,"round_token_cap":2500,"debate_global_cap":35000},"minimum_evidence_confidence":0.6,"default_policy_outcome":"block","human_override_allowed":true}
4
+ {"timestamp":"2026-05-14T15:55:11.581Z","schema_version":"1.0.0","contract_version":"1.0.0","event_type":"budget_exhausted","run_id":"019e2732-8651-74e5-9f5d-4d06c3105f25","debate_id":"plan-budget-guard","round_count":1,"budget_used":17161,"exhaustion_reason":"debate_global_cap_exceeded","caps":{"max_rounds":6,"round_token_cap":2500,"debate_global_cap":35000},"minimum_evidence_confidence":0.6,"default_policy_outcome":"block","human_override_allowed":true}
@@ -0,0 +1,72 @@
1
+ {
2
+ "defaultProfile": "auto",
3
+ "debug": false,
4
+ "classifierModel": "opencode-go/qwen3.6-plus",
5
+ "phaseBias": 0.5,
6
+ "maxSessionBudget": 1.0,
7
+ "largeContextThreshold": 100000,
8
+ "rules": [
9
+ {
10
+ "matches": ["deploy", "production", "release"],
11
+ "tier": "high",
12
+ "reason": "Safety check for production tasks"
13
+ },
14
+ {
15
+ "matches": "changelog",
16
+ "tier": "low"
17
+ }
18
+ ],
19
+ "profiles": {
20
+ "auto": {
21
+ "high": {
22
+ "model": "opencode-go/deepseek-v4-pro",
23
+ "thinking": "high",
24
+ "fallbacks": ["opencode-go/qwen3.6-plus", "opencode-go/kimi-k2.6"]
25
+ },
26
+ "medium": {
27
+ "model": "opencode-go/qwen3.6-plus",
28
+ "thinking": "medium",
29
+ "fallbacks": ["opencode-go/deepseek-v4-pro"]
30
+ },
31
+ "low": {
32
+ "model": "opencode-go/deepseek-v4-flash",
33
+ "thinking": "low",
34
+ "fallbacks": ["opencode-go/qwen3.5-plus"]
35
+ }
36
+ },
37
+ "cheap": {
38
+ "high": {
39
+ "model": "opencode-go/qwen3.6-plus",
40
+ "thinking": "low",
41
+ "fallbacks": ["opencode-go/qwen3.5-plus"]
42
+ },
43
+ "medium": {
44
+ "model": "opencode-go/qwen3.5-plus",
45
+ "thinking": "off",
46
+ "fallbacks": ["opencode-go/deepseek-v4-flash"]
47
+ },
48
+ "low": {
49
+ "model": "opencode-go/deepseek-v4-flash",
50
+ "thinking": "off",
51
+ "fallbacks": ["opencode-go/qwen3.5-plus"]
52
+ }
53
+ },
54
+ "deep": {
55
+ "high": {
56
+ "model": "opencode-go/deepseek-v4-pro",
57
+ "thinking": "xhigh",
58
+ "fallbacks": ["opencode-go/kimi-k2.6"]
59
+ },
60
+ "medium": {
61
+ "model": "opencode-go/kimi-k2.6",
62
+ "thinking": "medium",
63
+ "fallbacks": ["opencode-go/deepseek-v4-pro"]
64
+ },
65
+ "low": {
66
+ "model": "opencode-go/qwen3.6-plus",
67
+ "thinking": "low",
68
+ "fallbacks": ["opencode-go/deepseek-v4-flash"]
69
+ }
70
+ }
71
+ }
72
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "sample_count": 24,
3
+ "min_sample_count": 12,
4
+ "success_rate_delta": 0.08,
5
+ "cost_per_task_delta": -0.04,
6
+ "regression_guard_passed": true,
7
+ "trace_refs": ["run-canary-001", "run-canary-002"],
8
+ "notes": "canary validation synthetic evidence"
9
+ }
@@ -0,0 +1,4 @@
1
+ {"timestamp":"2026-05-14T15:51:38.345Z","run_id":"019e272f-3eef-7107-9712-ce281de55707-1778773891854","plan_id":"plan-unknown","phase":"plan","trace_file":"/home/aryaniyaps/ai-projects/ultimate-pi/.pi/harness/runs/019e272f-3eef-7107-9712-ce281de55707-1778773891854/trace.json"}
2
+ {"timestamp":"2026-05-14T15:52:14.312Z","run_id":"019e272f-3eef-7107-9712-ce281de55707-1778773912057","plan_id":"plan-unknown","phase":"plan","trace_file":"/home/aryaniyaps/ai-projects/ultimate-pi/.pi/harness/runs/019e272f-3eef-7107-9712-ce281de55707-1778773912057/trace.json"}
3
+ {"timestamp":"2026-05-14T15:55:25.166Z","run_id":"019e2732-8651-74e5-9f5d-4d06c3105f25-1778774086096","plan_id":"plan-unknown","phase":"plan","trace_file":"/home/aryaniyaps/ai-projects/ultimate-pi/.pi/harness/runs/019e2732-8651-74e5-9f5d-4d06c3105f25-1778774086096/trace.json"}
4
+ {"timestamp":"2026-05-14T16:36:47.569Z","run_id":"019e2758-b332-771b-ad6f-54d0d8478768-1778776600591","plan_id":"plan-unknown","phase":"plan","trace_file":"/home/aryaniyaps/ai-projects/ultimate-pi/.pi/harness/runs/019e2758-b332-771b-ad6f-54d0d8478768-1778776600591/trace.json"}
@@ -34,9 +34,9 @@
34
34
  },
35
35
  {
36
36
  "name": "tooling",
37
- "paths": ["scripts/*", "test/*"],
37
+ "paths": [".pi/scripts/*", "test/*"],
38
38
  "order": 4,
39
- "description": "Deterministic scripts and tests"
39
+ "description": "Harness CLI scripts and tests"
40
40
  }
41
41
  ],
42
42
  "boundaries": [
@@ -61,7 +61,7 @@
61
61
  "reason": "Contracts are data-only JSON schemas; extensions implement behavior"
62
62
  },
63
63
  {
64
- "from": "scripts/*",
64
+ "from": ".pi/scripts/*",
65
65
  "to": ".agents/skills/*",
66
66
  "reason": "CLI scripts stay independent of skill markdown"
67
67
  }
@@ -0,0 +1,27 @@
1
+ {
2
+ "defaultProfile": "auto",
3
+ "debug": false,
4
+ "classifierModel": "opencode-go/qwen3.6-plus",
5
+ "phaseBias": 0.5,
6
+ "maxSessionBudget": 1.0,
7
+ "largeContextThreshold": 100000,
8
+ "rules": [
9
+ {
10
+ "matches": ["deploy", "production", "release"],
11
+ "tier": "high",
12
+ "reason": "Safety check for production tasks"
13
+ },
14
+ { "matches": "changelog", "tier": "low" }
15
+ ],
16
+ "profiles": {
17
+ "auto": {
18
+ "high": {
19
+ "model": "opencode-go/deepseek-v4-pro",
20
+ "thinking": "high",
21
+ "fallbacks": ["opencode-go/qwen3.6-plus"]
22
+ },
23
+ "medium": { "model": "opencode-go/qwen3.6-plus", "thinking": "medium" },
24
+ "low": { "model": "opencode-go/deepseek-v4-flash", "thinking": "low" }
25
+ }
26
+ }
27
+ }
@@ -5,13 +5,9 @@ argument-hint: "[directory]"
5
5
 
6
6
  Read the `graphify` skill. Then run the setup workflow:
7
7
 
8
- 1. Check if Graphify is installed (`pip show graphifyy`). If not, install it:
9
- ```bash
10
- pip install graphifyy && graphify install
11
- ```
12
- 2. Check if a graph already exists (`graphify-out/graph.json`). If yes, report
13
- current graph stats (nodes, edges, communities, last built).
14
- 3. If no graph exists, build one: `graphify ${ARGUMENTS:-.} --wiki`
8
+ 1. Check if Graphify is installed (`pip`/`pip3 show graphifyy`, `uv tool list`, or `command -v graphify`). If not, install (`uv tool install graphifyy` preferred) and `graphify install --platform pi`.
9
+ 2. Check if a valid graph exists (`graphify-out/graph.json` with ≥1 node and `GRAPH_REPORT.md`). If yes, report stats.
10
+ 3. If no valid graph, build: `GRAPHIFY_VIZ_NODE_LIMIT=200000 graphify update ${ARGUMENTS:-.}` (never `graphify . --wiki` — invalid CLI). For full semantic extraction when API keys exist: `graphify extract ${ARGUMENTS:-.}`.
15
11
  4. Read and summarize `graphify-out/GRAPH_REPORT.md` — show god nodes,
16
12
  surprising connections, and suggested questions.
17
13
  5. Tell user: "Graph built. Open `graphify-out/graph.html` for interactive
@@ -19,5 +15,5 @@ Read the `graphify` skill. Then run the setup workflow:
19
15
 
20
16
  If the graph already exists:
21
17
  - Report graph stats from `graph.json`
22
- - Offer to update: `graphify . --update`
18
+ - Offer to update: `graphify update .`
23
19
  - Show recent god nodes from GRAPH_REPORT.md
@@ -32,70 +32,51 @@ Block if node < 18, npm < 9, or git missing. Report versions and continue.
32
32
 
33
33
  Read `.pi/auto-commit.json` for co-author + branch config. Read `.pi/settings.json` for extension packages list.
34
34
 
35
- ## Step 0.5 — Graphify Setup
35
+ ## Step 0.5 — Graphify (skip if `--skip-graphify`)
36
36
 
37
- Check if Graphify is installed and set up:
37
+ **Critical:** `graphify . --wiki` and `graphify . --update` are **invalid** CLI (error: `unknown command '.'`). Use only:
38
38
 
39
- ```bash
40
- # Check Python 3.10+
41
- python3 --version | grep -q "3\.1[0-9]" && echo "✓ Python 3.10+" || echo "✗ Need Python 3.10+"
39
+ | Goal | Command |
40
+ |------|---------|
41
+ | Initial / refresh code graph (required, no LLM) | `GRAPHIFY_VIZ_NODE_LIMIT=200000 graphify update .` |
42
+ | Full semantic graph (optional, needs API key) | `graphify extract .` |
42
43
 
43
- # Check if Graphify is installed
44
- if pip show graphifyy &>/dev/null; then
45
- echo "✓ Graphify installed"
46
- GRAPHIFY_INSTALLED=true
47
- else
48
- echo "! Graphify not installed"
49
- GRAPHIFY_INSTALLED=false
50
- fi
44
+ On first `/harness-setup` in any project (including external repos), you **must** produce a valid `graphify-out/` with non-empty `graph.json` and `GRAPH_REPORT.md`. Do not ask the user whether to build — run the bootstrap script and **block** if it fails.
51
45
 
52
- # Check if graph already exists
53
- test -f graphify-out/graph.json && GRAPH_EXISTS=true || GRAPH_EXISTS=false
54
- ```
46
+ Run from the **project root** (the external repo root, not ultimate-pi unless that is the target):
55
47
 
56
- **Present to user:**
48
+ ```bash
49
+ mkdir -p ./raw .pi/harness/specs .pi/harness/runs .pi/harness/incidents .pi/harness/debates
57
50
 
58
- ### Case A: Graphify installed + graph exists
59
- > "Graphify ready. Existing graph: `graphify-out/`. Run `graphify . --update` to refresh."
51
+ # Bundled with ultimate-pi harness; copy path if bootstrap runs from a linked harness checkout
52
+ bash "$(node -p "require('path').join(require('path').dirname(require.resolve('ultimate-pi/package.json')),'.pi/scripts/harness-graphify-bootstrap.sh')")"
53
+ # In ultimate-pi checkout: npm run harness:graphify-bootstrap
60
54
 
61
- ### Case B: Graphify installed + no graph
62
- > "Graphify installed but no graph built yet. Build one now?"
55
+ # Pass --force when $ARGUMENTS contains --force to rebuild an existing graph:
56
+ # npm run harness:graphify-bootstrap -- --force
57
+ ```
63
58
 
64
- ### Case C: Graphify not installed
65
- > "Graphify not found. Install: `pip install graphifyy && graphify install`. Install now?"
59
+ If the bootstrap script is missing, run it from the installed ultimate-pi package (`.pi/scripts/` inside the npm package), or execute equivalent steps manually:
66
60
 
67
- ### Case D: Python too old
68
- > "Python 3.10+ required for Graphify. Current: `$(python3 --version)`. Install Python 3.10+ before continuing."
61
+ 1. Install `graphifyy` (`uv tool install` preferred; else `pip`/`pip3 install --user`)
62
+ 2. `graphify install --platform pi` (and `graphify cursor install` if `.cursor/` exists)
63
+ 3. `GRAPHIFY_VIZ_NODE_LIMIT=200000 graphify update .` — **required**; exits non-zero on failure
64
+ 4. If `GEMINI_API_KEY`, `GOOGLE_API_KEY`, `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `MOONSHOT_API_KEY` is set: `graphify extract .` for full semantic graph (optional enrichment)
65
+ 5. `graphify hook install` only when `.git/` exists
66
+ 6. Validate: `graphify-out/graph.json` has ≥1 node and `graphify-out/GRAPH_REPORT.md` exists
69
67
 
70
- ## Step 1 Build Knowledge Graph
68
+ **Do not continue** to Step 2+ until validation passes. Report node/edge counts from the script output.
71
69
 
72
- ```bash
73
- # Install if needed
74
- if [ "$GRAPHIFY_INSTALLED" != "true" ]; then
75
- pip install graphifyy && graphify install
76
- fi
70
+ Read and summarize `graphify-out/GRAPH_REPORT.md` — god nodes and surprising connections.
77
71
 
78
- # Build the graph (or update existing)
79
- if [ "$GRAPH_EXISTS" = "true" ]; then
80
- graphify . --update --wiki
81
- else
82
- graphify . --wiki
83
- fi
84
-
85
- # Install git hooks — auto-update graph on commit/checkout
86
- graphify hook install
72
+ ### Failure modes (report clearly)
87
73
 
88
- # Quick stats
89
- echo "Graph built. Output: graphify-out/"
90
- ls graphify-out/
91
- ```
92
-
93
- Read and summarize `graphify-out/GRAPH_REPORT.md` — show god nodes and surprising connections.
94
-
95
- Create project directories needed for graphify + harness workflow:
96
- ```bash
97
- mkdir -p ./raw .pi/harness/specs .pi/harness/runs .pi/harness/incidents .pi/harness/debates
98
- ```
74
+ | Symptom | Likely cause |
75
+ |---------|----------------|
76
+ | `unknown command '.'` | Wrong CLI — use `graphify update .`, never `graphify .` |
77
+ | Empty or missing `graphify-out/` | Build step skipped or failed; re-run bootstrap |
78
+ | `graph.json` exists but 0 nodes | Stale/partial output — re-run with `--force` |
79
+ | `graphify extract` fails | No API key code graph from `update` is still valid; note in report |
99
80
 
100
81
  ## Step 1.5 — Optional Self-Hosted Firecrawl
101
82
 
@@ -225,9 +206,36 @@ docker compose -f firecrawl/docker-compose.yaml ps
225
206
  If user chose **cloud**, skip all 1.5.x steps. Just note:
226
207
  > "Using cloud Firecrawl. Ensure `FIRECRAWL_API_KEY` is set. Run `firecrawl login` in Step 2.1."
227
208
 
228
- ## Step 2 — Install Global CLI Packages
209
+ ## Step 2 — Install & Verify Global CLI Tools (skip if `--skip-tools`)
210
+
211
+ Run the bundled verifier from the **project root**. It installs missing npm globals, fixes common **Linux system dependencies** (Chrome libs for `agent-browser`), runs smoke tests, and exits non-zero if a required tool fails.
229
212
 
230
- Check each package first. Install only if missing unless `--force` flag.
213
+ ```bash
214
+ npm run harness:cli-verify
215
+ # ultimate-pi checkout: npm run harness:cli-verify
216
+ # Reinstall everything: npm run harness:cli-verify -- --force
217
+ ```
218
+
219
+ **Required (script must exit 0):** firecrawl-cli, ctx7, biome, ast-grep (`sg`), sentrux (when harness manifest present).
220
+
221
+ **Warnings allowed:** gh (if not authenticated), agent-browser (if OS libs need manual `sudo apt-get install`), ck (empty corpus on tiny repos).
222
+
223
+ If the script reports **agent-browser shared library errors** on Linux/WSL, run the fix it prints, then re-verify:
224
+
225
+ ```bash
226
+ sudo apt-get update
227
+ sudo apt-get install -y libnss3 libnspr4 libgbm1 libatk1.0-0 libatk-bridge2.0-0 \
228
+ libcups2 libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 \
229
+ libasound2 libpango-1.0-0 libcairo2 libx11-6 libxcb1 libxext6 fonts-liberation
230
+ agent-browser install --with-deps
231
+ npm run harness:cli-verify
232
+ ```
233
+
234
+ **Do not continue** past Step 2 if `harness-cli-verify.sh` exits non-zero.
235
+
236
+ ### Manual reference (if script missing in target repo)
237
+
238
+ Use `npm run harness:cli-verify` from the installed ultimate-pi package, or install tools individually:
231
239
 
232
240
  ### 2.1 — firecrawl-cli (Web Search + Scrape + Crawl + Interact + Download + Parse)
233
241
 
@@ -260,9 +268,8 @@ firecrawl login --browser
260
268
  firecrawl login --api-key "<key>"
261
269
  ```
262
270
 
263
- Install skills and run quick smoke test:
271
+ Quick smoke test (skills ship with `ultimate-pi` via npm — do **not** run `firecrawl setup skills`):
264
272
  ```bash
265
- firecrawl setup skills
266
273
  mkdir -p .firecrawl
267
274
  firecrawl scrape "https://firecrawl.dev" -o .firecrawl/install-check.md
268
275
  ```
@@ -404,7 +411,11 @@ Configure MCP server in `.pi/mcp.json` (see Step 4.3).
404
411
 
405
412
  Generate architectural rules from the harness manifest (creates/updates `.sentrux/rules.toml`):
406
413
  ```bash
414
+ # From ultimate-pi checkout:
415
+ npm run harness:sentrux-sync
416
+ # From an external project (after pi install npm:ultimate-pi):
407
417
  npm run harness:sentrux-sync
418
+ # Or in pi: /harness-sentrux-sync
408
419
  ```
409
420
 
410
421
  Edit layers/boundaries in `.pi/harness/sentrux/architecture.manifest.json` when the repo layout changes, then re-run sync. Custom TOML below the `harness:managed` markers is preserved.
@@ -476,27 +487,38 @@ function model(prefix, name) { return `${prefix}/${name}`; }
476
487
  // Best available high-end model per provider
477
488
  const highModel = hasOpenCode
478
489
  ? model('opencode-go', 'deepseek-v4-pro')
479
- : hasOpenAI
480
- ? model('openai', 'gpt-5.4-pro')
481
- : hasAnthropic
482
- ? 'anthropic/claude-3-5-sonnet-20241022'
483
- : 'google/gemini-2.5-flash-001';
490
+ : hasAnthropic
491
+ ? 'anthropic/claude-sonnet-4-20250514'
492
+ : hasGoogle
493
+ ? 'google/gemini-2.5-flash-001'
494
+ : hasOpenAI
495
+ ? model('openai', 'gpt-4o')
496
+ : null;
484
497
 
485
498
  const mediumModel = hasOpenCode
486
499
  ? model('opencode-go', 'qwen3.6-plus')
487
- : hasOpenAI
488
- ? model('openai', 'gpt-5.4-nano')
489
- : hasAnthropic
490
- ? 'anthropic/claude-3-5-sonnet-20241022'
491
- : 'google/gemini-flash-latest';
500
+ : hasAnthropic
501
+ ? 'anthropic/claude-sonnet-4-20250514'
502
+ : hasGoogle
503
+ ? 'google/gemini-flash-latest'
504
+ : hasOpenAI
505
+ ? model('openai', 'gpt-4o-mini')
506
+ : null;
492
507
 
493
508
  const lowModel = hasOpenCode
494
509
  ? model('opencode-go', 'deepseek-v4-flash')
495
- : hasOpenAI
496
- ? model('openai', 'gpt-5.4-nano')
497
- : hasAnthropic
498
- ? 'anthropic/claude-3-haiku-20240307'
499
- : 'google/gemini-flash-lite-latest';
510
+ : hasAnthropic
511
+ ? 'anthropic/claude-3-5-haiku-20241022'
512
+ : hasGoogle
513
+ ? 'google/gemini-flash-lite-latest'
514
+ : hasOpenAI
515
+ ? model('openai', 'gpt-4o-mini')
516
+ : null;
517
+
518
+ if (!highModel || !mediumModel || !lowModel) {
519
+ console.log('✗ No AI provider env detected — skip model-router.json (set OPENAI_API_BASE for opencode, or ANTHROPIC/GOOGLE/OPENAI keys)');
520
+ process.exit(0);
521
+ }
500
522
 
501
523
  const fallbacks = [];
502
524
  if (hasAnthropic && !highModel.startsWith('anthropic/')) fallbacks.push('anthropic/claude-3-5-sonnet-20241022');
@@ -552,7 +574,7 @@ fi
552
574
 
553
575
  Do NOT block. If generation fails, warn in report and continue.
554
576
 
555
- **Router activation happens automatically** — the agent should output the following as its next message (this activates the router in the current session):
577
+ **Router is opt-in** — ultimate-pi no longer forces `defaultProvider: router` on install. After generating `model-router.json`, tell the user to enable routing when ready:
556
578
 
557
579
  > `/router profile auto`
558
580
 
@@ -616,16 +638,16 @@ Created: $(date +%Y-%m-%d)
616
638
 
617
639
  ## Structure
618
640
 
619
- - graphify-out/ → Knowledge graph (run `graphify .` to build)
641
+ - graphify-out/ → Knowledge graph (run `graphify update .` to build)
620
642
  - ./raw/ → Source documents for graphify ingestion
621
643
  - .pi/harness/specs/ → Harness contracts and schema docs
622
644
  - .pi/harness/incidents/ → Incident and override records
623
- - .pi/skills/Agent skills
645
+ - `.agents/skills/` (npm package) Harness skills (no copy into `.pi/skills/` needed)
624
646
  - .pi/agents/ → Specialized agents
625
647
 
626
648
  ## Graphify-First Workflow
627
649
 
628
- 1. Run `graphify . --wiki` to build the knowledge graph
650
+ 1. Run `graphify update .` to build/update the knowledge graph (AST, no API cost)
629
651
  2. Read `graphify-out/GRAPH_REPORT.md` for god nodes and surprising connections
630
652
  3. Query: `graphify query "question"`
631
653
  4. Harness contracts and governance records in `.pi/harness/specs/` and `.pi/harness/incidents/`
@@ -635,32 +657,52 @@ Created: $(date +%Y-%m-%d)
635
657
  - Graph before grep — always consult the knowledge graph first
636
658
  - ./raw/ is source storage for graphify
637
659
  - Decisions and incidents in `.pi/harness/` with structured artifacts
638
- - `graphify . --update` after significant changes
660
+ - `GRAPHIFY_VIZ_NODE_LIMIT=200000 graphify update .` after significant code changes
639
661
  - ast-grep (`sg`) is the default code search tool — use `sg -p 'pattern'` for structural search, never grep for code
640
662
  - Create `.sg/rules/` for project-wide code quality rules
641
663
  ```
642
664
 
643
665
  ## Step 5 — Verification
644
666
 
645
- Run full verification suite:
667
+ Re-run CLI verification (must pass unless `--skip-tools`):
646
668
 
647
669
  ```bash
648
- # CLI tools
649
- firecrawl --status 2>/dev/null && echo "✓ firecrawl" || echo "✗ firecrawl"
650
- ctx7 --help 2>/dev/null && echo "✓ ctx7" || echo "✗ ctx7"
651
- agent-browser --version 2>/dev/null && echo "✓ agent-browser" || echo "✗ agent-browser"
652
- ck --version 2>/dev/null && echo "✓ ck-search" || echo "✗ ck-search"
653
- biome --version 2>/dev/null && echo "✓ biome" || echo "✗ biome"
654
- sg --version 2>/dev/null && echo "✓ ast-grep" || echo "✗ ast-grep"
655
- gh --version 2>/dev/null && echo "✓ gh" || echo "✗ gh"
656
- sentrux --version 2>/dev/null && echo "✓ sentrux" || echo "✗ sentrux"
670
+ npm run harness:cli-verify
671
+ ```
672
+
673
+ Then run the remaining checks:
657
674
 
675
+ ```bash
658
676
  # pi extensions
659
677
  cd .pi/npm && npm ls 2>/dev/null && echo "✓ pi extensions" || echo "✗ pi extensions"
660
678
 
661
- # graphify knowledge graph
662
- pip show graphifyy 2>/dev/null && echo "✓ graphify installed" || echo "✗ graphify not installed"
663
- ls graphify-out/graph.json 2>/dev/null && echo "✓ knowledge graph built" || echo "✗ no graph built yet"
679
+ # graphify knowledge graph (pip/pip3, uv, apt, or PATH)
680
+ PIP_CMD=""
681
+ command -v pip &>/dev/null && PIP_CMD=pip
682
+ [ -z "$PIP_CMD" ] && command -v pip3 &>/dev/null && PIP_CMD=pip3
683
+
684
+ if command -v graphify &>/dev/null; then
685
+ echo "✓ graphify ($(command -v graphify))"
686
+ elif [ -n "$PIP_CMD" ] && $PIP_CMD show graphifyy &>/dev/null 2>&1; then
687
+ echo "✓ graphify ($PIP_CMD)"
688
+ elif command -v uv &>/dev/null && uv pip show graphifyy &>/dev/null 2>&1; then
689
+ echo "✓ graphify (uv pip)"
690
+ elif command -v uv &>/dev/null && uv tool list 2>/dev/null | grep -qE '(^|[[:space:]])graphifyy([[:space:]]|$)'; then
691
+ echo "✓ graphify (uv tool)"
692
+ elif dpkg -l 2>/dev/null | grep -qE '^ii[[:space:]]+(python3-)?graphify' || apt list --installed 2>/dev/null | grep -qi graphify; then
693
+ echo "✓ graphify (apt)"
694
+ else
695
+ echo "✗ graphify not installed"
696
+ fi
697
+ python3 -c "
698
+ import json, sys
699
+ from pathlib import Path
700
+ gj, gr = Path('graphify-out/graph.json'), Path('graphify-out/GRAPH_REPORT.md')
701
+ if not gj.is_file() or not gr.is_file():
702
+ print('✗ knowledge graph missing (need graph.json + GRAPH_REPORT.md)'); sys.exit(0)
703
+ n = len(json.loads(gj.read_text()).get('nodes') or [])
704
+ print(f'✓ knowledge graph built ({n} nodes)' if n else '✗ graph.json has 0 nodes — re-run harness-graphify-bootstrap.sh --force')
705
+ " 2>/dev/null || echo "✗ no graph built yet"
664
706
  graphify hook status 2>/dev/null && echo "✓ graphify git hooks installed" || echo "✗ graphify git hooks not installed"
665
707
 
666
708
  # model router
@@ -721,7 +763,7 @@ Output summary table:
721
763
 
722
764
  Next steps:
723
765
  1. If tools missing: re-run with `--force` or install individually
724
- 2. If graph not built: run `graphify . --wiki`
766
+ 2. If graph not built: run `npm run harness:graphify-bootstrap` (or `graphify update .` from project root)
725
767
  3. If hooks not installed: run `graphify hook install`
726
768
  4. If gh not authenticated: `gh auth login`
727
769
  5. If self-hosted Firecrawl unhealthy: `docker compose -f firecrawl/docker-compose.yaml logs`
@@ -731,7 +773,10 @@ Next steps:
731
773
  ## Guard Rails
732
774
 
733
775
  - **Internet required**: Several tools need npm registry access. Block if offline.
776
+ - **CLI verify script**: Step 2 and Step 5 use `npm run harness:cli-verify` (`.pi/scripts/harness-cli-verify.sh`) — installs npm globals, Linux Chrome system libs for `agent-browser`, and smoke-tests each tool. Block on non-zero exit.
734
777
  - **Graphify requires Python 3.10+**: Check `python3 --version`. Block if too old.
778
+ - **Graphify bootstrap is mandatory** (unless `--skip-graphify`): Run `npm run harness:graphify-bootstrap`. Never use `graphify . --wiki`. Initial setup must run `graphify update .` and verify `graphify-out/graph.json` has nodes.
779
+ - **Python packages (Graphify)**: Before install, detect via PATH, `pip`/`pip3 show graphifyy`, `uv`, or apt. Prefer `uv tool install graphifyy`.
735
780
  - **Node.js >= 18 required**: Some pi packages use modern Node APIs.
736
781
  - **Docker required for self-hosted**: Step 1.5 needs Docker Engine + Compose. Block if install fails.
737
782
  - **Sufficient RAM for self-hosted**: Firecrawl stack needs ~8GB+ free (API: 8G, Playwright: 4G, others).
@@ -748,12 +793,17 @@ Next steps:
748
793
  | Node < 18 | Block. Report required version. |
749
794
  | npm not found | Block. Suggest install method per OS. |
750
795
  | Python < 3.10 | Block. Report required Python version for Graphify. |
751
- | Graphify install fails | Show pip error output. Suggest `pip install --upgrade pip` and retry. |
796
+ | CLI verify script fails | Read per-tool lines. Re-run with `--force`. Fix agent-browser libs via apt (see Step 2). |
797
+ | agent-browser libnspr4 / shared library | `sudo apt-get install -y libnss3 libnspr4 libgbm1 ...` then `agent-browser install --with-deps`. |
798
+ | Graphify install fails | Show installer output. Retry `uv tool install graphifyy` or `pip3 install --user graphifyy`. Ensure `~/.local/bin` is on PATH. |
799
+ | `graphify update .` fails | Block setup. Corpus may have no code files, or graphify not on PATH. Show stderr. |
800
+ | Invalid `graphify .` usage | Replace with `graphify update .` — the `.` subcommand does not exist. |
801
+ | graphify-out empty / 0 nodes | Re-run `npm run harness:graphify-bootstrap -- --force` from project root. |
752
802
  | graphify hook install fails | Hooks need `.git/` directory. Verify inside git repo. Manual: `git config core.hooksPath .pi/git-hooks` |
753
803
  | firecrawl auth failed | Show manual login instructions. Continue with other tools. |
754
804
  | gh not installed | Show GitHub CLI install link. Skip label creation. |
755
805
  | pi packages install fail | Show error output. Check npm permissions. |
756
- | graph already exists | Report state. Offer `graphify . --update` to refresh. |
806
+ | graph already exists | Report node count. Refresh with `graphify update .` unless user passed `--force`. |
757
807
  | biome.json missing | Create minimal config. |
758
808
  | settings.json not writable | Warn. Settings won't persist across sessions. |
759
809
  | No internet | Block for tool installs. Continue for graphify-only steps if `--skip-tools`. |
@@ -767,7 +817,7 @@ Next steps:
767
817
 
768
818
  | Flag | Effect |
769
819
  |------|--------|
770
- | `--skip-graphify` | Skip Step 1 (graph build). Use when graph already exists. |
820
+ | `--skip-graphify` | Skip Step 0.5 (graph build). Only when a valid `graphify-out/graph.json` already exists. |
771
821
  | `--skip-tools` | Skip Step 2 (CLI tool installs). Use when tools already set up. |
772
822
  | `--skip-firecrawl-self` | Skip Step 1.5 (self-hosted Firecrawl). Always use cloud. |
773
823
  | `--force` | Reinstall all tools even if already present. Overwrite existing files. |