ultimate-pi 0.18.1 → 0.19.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/harness-debate-plan/SKILL.md +1 -1
- package/.agents/skills/harness-decisions/SKILL.md +1 -2
- package/.agents/skills/harness-governor/SKILL.md +6 -5
- package/.pi/PACKAGING.md +4 -4
- package/.pi/SYSTEM.md +54 -120
- package/.pi/agents/harness/incident-recorder.md +0 -1
- package/.pi/agents/harness/planning/decompose.md +0 -2
- package/.pi/agents/harness/planning/execution-plan-author.md +0 -2
- package/.pi/agents/harness/planning/hypothesis-validator.md +0 -2
- package/.pi/agents/harness/planning/hypothesis.md +0 -2
- package/.pi/agents/harness/planning/implementation-researcher.md +0 -2
- package/.pi/agents/harness/planning/plan-adversary.md +0 -2
- package/.pi/agents/harness/planning/plan-evaluator.md +1 -3
- package/.pi/agents/harness/planning/planning-context.md +0 -2
- package/.pi/agents/harness/planning/review-integrator.md +0 -2
- package/.pi/agents/harness/planning/sprint-contract-auditor.md +0 -2
- package/.pi/agents/harness/planning/stack-researcher.md +0 -2
- package/.pi/agents/harness/reviewing/adversary.md +0 -2
- package/.pi/agents/harness/reviewing/evaluator.md +0 -2
- package/.pi/agents/harness/reviewing/tie-breaker.md +0 -2
- package/.pi/agents/harness/running/executor.md +0 -2
- package/.pi/agents/harness/sentrux-bootstrap.md +0 -1
- package/.pi/agents/harness/sentrux-steward.md +0 -2
- package/.pi/agents/harness/trace-librarian.md +0 -1
- package/.pi/extensions/00-posthog-network-bootstrap.ts +1 -1
- package/.pi/extensions/agt-kill-switch.ts +57 -0
- package/.pi/extensions/agt-prompt-guard.ts +32 -0
- package/.pi/extensions/custom-footer.ts +46 -145
- package/.pi/extensions/custom-header.ts +1 -1
- package/.pi/extensions/custom-system-prompt.ts +1 -1
- package/.pi/extensions/debate-orchestrator.ts +6 -6
- package/.pi/extensions/harness-ask-user.ts +7 -7
- package/.pi/extensions/harness-debate-tools.ts +26 -42
- package/.pi/extensions/harness-lens.ts +94 -0
- package/.pi/extensions/harness-plan-approval.ts +11 -11
- package/.pi/extensions/harness-run-context.ts +1070 -876
- package/.pi/extensions/harness-subagent-governance.ts +8 -0
- package/.pi/extensions/harness-subagent-submit.ts +34 -163
- package/.pi/extensions/harness-subagents.ts +3 -3
- package/.pi/extensions/harness-telemetry.ts +2 -2
- package/.pi/extensions/harness-web-tools.ts +2 -2
- package/.pi/extensions/policy-gate.ts +25 -5
- package/.pi/extensions/sentrux-rules-sync.ts +1 -1
- package/.pi/extensions/subagent-governance.ts +92 -0
- package/.pi/extensions/trace-recorder.ts +1 -1
- package/.pi/extensions/{ultimate-pi-vcc.ts → vcc-compaction.ts} +1 -1
- package/.pi/harness/README.md +6 -2
- package/.pi/harness/agents.manifest.json +22 -25
- package/.pi/harness/agents.policy.yaml +275 -0
- package/.pi/harness/docs/adrs/0030-inhouse-vcc-compaction.md +1 -1
- package/.pi/harness/docs/adrs/0035-plan-phase-review-gate.md +1 -1
- package/.pi/harness/docs/adrs/0045-harness-lens-minimal-contract.md +49 -0
- package/.pi/harness/docs/adrs/0046-agt-policy-engine.md +51 -0
- package/.pi/harness/docs/adrs/0047-agt-layered-security.md +39 -0
- package/.pi/harness/docs/adrs/0048-tool-call-hook-order.md +25 -0
- package/.pi/harness/docs/adrs/0049-agents-policy-manifest.md +36 -0
- package/.pi/harness/docs/adrs/README.md +5 -0
- package/.pi/harness/evolution/README.md +1 -2
- package/.pi/harness/examples/agents.policy.project.yaml +19 -0
- package/.pi/harness/examples/policies/custom-deny-bash.yaml +9 -0
- package/.pi/harness/policies/bash-denylists.yaml +5 -0
- package/.pi/harness/policies/defaults.yaml +51 -0
- package/.pi/harness/policies/orchestrator.yaml +18 -0
- package/.pi/harness/policies/phases.yaml +10 -0
- package/.pi/harness/policies/roles.yaml +5 -0
- package/.pi/harness/policies/web-guard.yaml +5 -0
- package/.pi/harness/policies/workflow-sequences.yaml +9 -0
- package/.pi/harness/sentrux/architecture.manifest.json +26 -4
- package/.pi/harness/specs/observation.schema.json +2 -1
- package/.pi/lib/agents-policy.d.mts +70 -0
- package/.pi/lib/agents-policy.mjs +325 -0
- package/.pi/lib/agents-policy.ts +19 -0
- package/.pi/lib/agt/audit-run-sink.ts +52 -0
- package/.pi/lib/agt/build-evaluation-context.ts +285 -0
- package/.pi/lib/agt/config.ts +28 -0
- package/.pi/lib/agt/delegation.ts +69 -0
- package/.pi/lib/agt/evaluate-policy.ts +56 -0
- package/.pi/lib/agt/identity-registry.ts +41 -0
- package/.pi/lib/agt/index.ts +55 -0
- package/.pi/lib/agt/kill-switch-state.ts +11 -0
- package/.pi/lib/agt/legacy-evaluate.ts +101 -0
- package/.pi/lib/agt/policy-engine.ts +154 -0
- package/.pi/lib/agt/rings.ts +21 -0
- package/.pi/lib/agt/sre-hooks.ts +45 -0
- package/.pi/lib/agt/trust-run-store.ts +26 -0
- package/.pi/lib/agt/workflow-history.ts +29 -0
- package/.pi/lib/agt-governance-active.ts +14 -0
- package/.pi/lib/agt-tool-guard.ts +78 -0
- package/.pi/lib/ask-user/dialog.ts +314 -0
- package/.pi/{extensions/lib → lib}/debate-bus-core.ts +10 -10
- package/.pi/{extensions/lib → lib}/debate-bus-state.ts +1 -1
- package/.pi/{extensions/lib → lib}/extension-load-guard.ts +13 -2
- package/.pi/lib/harness-agt-tool-guard.ts +5 -0
- package/.pi/{extensions/lib → lib}/harness-artifact-gate.ts +1 -1
- package/.pi/lib/harness-debate-core-deps.ts +14 -0
- package/.pi/lib/harness-debate-workflow-deps.ts +43 -0
- package/.pi/lib/harness-lens/.gitattributes +1 -0
- package/.pi/lib/harness-lens/clients/edit-autopatch.ts +88 -0
- package/.pi/lib/harness-lens/clients/file-kinds.ts +380 -0
- package/.pi/lib/harness-lens/clients/file-time.ts +215 -0
- package/.pi/lib/harness-lens/clients/file-utils.ts +484 -0
- package/.pi/lib/harness-lens/clients/format-service.ts +276 -0
- package/.pi/lib/harness-lens/clients/formatters.ts +1000 -0
- package/.pi/lib/harness-lens/clients/git-guard.ts +31 -0
- package/.pi/lib/harness-lens/clients/indent-retarget.ts +90 -0
- package/.pi/lib/harness-lens/clients/installer/index.ts +2368 -0
- package/.pi/lib/harness-lens/clients/latency-logger.ts +80 -0
- package/.pi/lib/harness-lens/clients/lens-config.ts +43 -0
- package/.pi/lib/harness-lens/clients/lens-events.ts +164 -0
- package/.pi/lib/harness-lens/clients/lsp/aggregation.ts +91 -0
- package/.pi/lib/harness-lens/clients/lsp/client.ts +1466 -0
- package/.pi/lib/harness-lens/clients/lsp/config.ts +216 -0
- package/.pi/lib/harness-lens/clients/lsp/edits.ts +297 -0
- package/.pi/lib/harness-lens/clients/lsp/index.ts +1355 -0
- package/.pi/lib/harness-lens/clients/lsp/interactive-install.ts +424 -0
- package/.pi/lib/harness-lens/clients/lsp/language.ts +223 -0
- package/.pi/lib/harness-lens/clients/lsp/launch.ts +939 -0
- package/.pi/lib/harness-lens/clients/lsp/lsp-index.ts +11 -0
- package/.pi/lib/harness-lens/clients/lsp/path-utils.ts +12 -0
- package/.pi/lib/harness-lens/clients/lsp/server-strategies.ts +81 -0
- package/.pi/lib/harness-lens/clients/lsp/server.ts +1971 -0
- package/.pi/lib/harness-lens/clients/path-utils.ts +182 -0
- package/.pi/lib/harness-lens/clients/pipeline.ts +360 -0
- package/.pi/lib/harness-lens/clients/project-profile.ts +117 -0
- package/.pi/lib/harness-lens/clients/runtime-agent-end.ts +112 -0
- package/.pi/lib/harness-lens/clients/runtime-config.ts +33 -0
- package/.pi/lib/harness-lens/clients/runtime-coordinator.ts +186 -0
- package/.pi/lib/harness-lens/clients/runtime-tool-result.ts +171 -0
- package/.pi/lib/harness-lens/clients/safe-spawn.ts +339 -0
- package/.pi/lib/harness-lens/clients/secrets-scanner.ts +214 -0
- package/.pi/lib/harness-lens/clients/tool-policy.ts +2072 -0
- package/.pi/lib/harness-lens/clients/types.ts +59 -0
- package/.pi/lib/harness-lens/clients/widget-state.ts +283 -0
- package/.pi/lib/harness-lens/index.ts +532 -0
- package/.pi/lib/harness-lens/tools/lsp-diagnostics.ts +706 -0
- package/.pi/lib/harness-lens/tools/lsp-navigation.ts +1246 -0
- package/.pi/{extensions/lib → lib}/harness-posthog.ts +3 -0
- package/.pi/lib/harness-run-context-responses.ts +9 -0
- package/.pi/lib/harness-run-context.ts +0 -2
- package/.pi/{extensions/lib/spawn-policy.ts → lib/harness-spawn-policy.ts} +1 -0
- package/.pi/{extensions/lib → lib}/harness-spawn-topology.ts +1 -1
- package/.pi/lib/harness-subagent-auth.ts +51 -0
- package/.pi/{extensions/lib → lib}/harness-subagent-precheck.ts +10 -7
- package/.pi/{extensions/lib → lib}/harness-subagent-submit-pipeline.ts +3 -3
- package/.pi/lib/harness-subagent-submit-register.ts +163 -0
- package/.pi/{extensions/lib → lib}/harness-subagent-submit-registry.ts +1 -37
- package/.pi/{extensions/lib → lib}/harness-subagents-bridge.ts +53 -14
- package/.pi/{extensions/lib → lib}/harness-subprocess-bootstrap.ts +1 -1
- package/.pi/{extensions/lib → lib}/plan-approval/create-plan.ts +2 -2
- package/.pi/{extensions/lib → lib}/plan-approval/format-plan.ts +2 -2
- package/.pi/{extensions/lib → lib}/plan-approval/plan-review.ts +162 -201
- package/.pi/{extensions/lib → lib}/plan-approval/render.ts +1 -1
- package/.pi/{extensions/lib → lib}/plan-approval/resolve-disk.ts +2 -2
- package/.pi/{extensions/lib → lib}/plan-approval/types.ts +1 -1
- package/.pi/{extensions/lib → lib}/plan-approval/validate.ts +3 -3
- package/.pi/{extensions/lib → lib}/plan-debate-envelope.ts +1 -1
- package/.pi/{extensions/lib → lib}/plan-debate-gate.ts +1 -1
- package/.pi/{extensions/lib → lib}/plan-debate-lane.ts +1 -4
- package/.pi/{extensions/lib → lib}/plan-messenger.ts +1 -1
- package/.pi/prompts/harness-plan.md +1 -1
- package/.pi/prompts/harness-setup.md +37 -64
- package/.pi/scripts/README.md +2 -5
- package/.pi/scripts/generate-agents-policy-yaml.mjs +148 -0
- package/.pi/scripts/harness-agents-manifest.mjs +60 -3
- package/.pi/scripts/harness-agt-doctor.ts +36 -0
- package/.pi/scripts/harness-cli-verify.sh +9 -2
- package/.pi/scripts/harness-verify.mjs +113 -39
- package/.pi/scripts/harness-web-policy-guard.mjs +2 -2
- package/.pi/scripts/validate-plan-dag.mjs +65 -74
- package/.pi/scripts/vendor-pi-vcc-settings.stub.ts +2 -2
- package/.pi/scripts/vendor-sync-pi-vcc.sh +1 -1
- package/.pi/skills/architecture/broker-domain/SKILL.md +65 -0
- package/.pi/skills/architecture/cqrs/SKILL.md +63 -0
- package/.pi/skills/architecture/event-driven/SKILL.md +60 -0
- package/.pi/skills/architecture/hexagonal-ports-adapters/SKILL.md +66 -0
- package/.pi/skills/architecture/layered/SKILL.md +68 -0
- package/.pi/skills/architecture/microkernel/SKILL.md +62 -0
- package/.pi/skills/architecture/microservices/SKILL.md +64 -0
- package/.pi/skills/architecture/modular-monolith/SKILL.md +65 -0
- package/.pi/skills/architecture/orchestration-driven-soa/SKILL.md +61 -0
- package/.pi/skills/architecture/pipeline/SKILL.md +63 -0
- package/.pi/skills/architecture/service-based/SKILL.md +64 -0
- package/.pi/skills/architecture/service-mesh/SKILL.md +60 -0
- package/.pi/skills/architecture/space-based/SKILL.md +60 -0
- package/.pi/skills/ast-grep/SKILL.md +40 -321
- package/.pi/skills/delivery/debugging-discipline/SKILL.md +36 -0
- package/.pi/skills/delivery/documentation-update/SKILL.md +33 -0
- package/.pi/skills/delivery/requirements-to-implementation/SKILL.md +34 -0
- package/.pi/skills/delivery/risk-based-verification/SKILL.md +43 -0
- package/.pi/skills/delivery/tradeoff-analysis/SKILL.md +34 -0
- package/.pi/skills/engineering/api-contract-design/SKILL.md +38 -0
- package/.pi/skills/engineering/cohesion-coupling/SKILL.md +43 -0
- package/.pi/skills/engineering/complexity-control/SKILL.md +31 -0
- package/.pi/skills/engineering/defensive-programming/SKILL.md +38 -0
- package/.pi/skills/engineering/dependency-management/SKILL.md +29 -0
- package/.pi/skills/engineering/domain-modeling/SKILL.md +32 -0
- package/.pi/skills/engineering/error-handling/SKILL.md +37 -0
- package/.pi/skills/engineering/legacy-code-seams/SKILL.md +35 -0
- package/.pi/skills/engineering/naming-and-intent/SKILL.md +29 -0
- package/.pi/skills/engineering/refactoring-safe-evolution/SKILL.md +35 -0
- package/.pi/skills/engineering/routine-function-design/SKILL.md +34 -0
- package/.pi/skills/engineering/small-change-discipline/SKILL.md +35 -0
- package/.pi/skills/lsp-navigation/SKILL.md +89 -0
- package/.pi/skills/quality/code-review-self-check/SKILL.md +35 -0
- package/.pi/skills/quality/privacy-data-handling/SKILL.md +26 -0
- package/.pi/skills/quality/security-review/SKILL.md +34 -0
- package/.pi/skills/quality/test-strategy/SKILL.md +33 -0
- package/.pi/skills/quality/testability-design/SKILL.md +33 -0
- package/.pi/skills/systems/concurrency-safety/SKILL.md +32 -0
- package/.pi/skills/systems/data-modeling-migrations/SKILL.md +31 -0
- package/.pi/skills/systems/observability-instrumentation/SKILL.md +32 -0
- package/.pi/skills/systems/performance-measurement/SKILL.md +35 -0
- package/.pi/skills/systems/reliability-design/SKILL.md +32 -0
- package/.sentrux/rules.toml +20 -4
- package/AGENTS.md +5 -0
- package/CHANGELOG.md +14 -0
- package/README.md +3 -12
- package/THIRD_PARTY_NOTICES.md +12 -21
- package/package.json +15 -7
- package/vendor/pi-subagents/src/agents.ts +45 -1
- package/vendor/pi-subagents/src/subagents.ts +866 -811
- package/vendor/pi-vcc/src/core/brief.ts +68 -99
- package/vendor/pi-vcc/src/core/settings.ts +2 -2
- package/.agents/skills/caveman/SKILL.md +0 -67
- package/.pi/agents/harness/meta-optimizer.md +0 -36
- package/.pi/extensions/lib/ask-user/dialog.ts +0 -260
- package/.pi/extensions/lib/harness-subagent-auth.ts +0 -207
- package/.pi/extensions/lib/harness-subagent-policy.ts +0 -236
- package/.pi/extensions/pi-model-router-harness.ts +0 -42
- package/.pi/harness/evolution/meta-optimizer.mjs +0 -99
- package/.pi/harness/specs/router-tuning-proposal.schema.json +0 -114
- package/.pi/model-router.example.json +0 -36
- package/.pi/prompts/harness-critic.md +0 -10
- package/.pi/prompts/harness-eval.md +0 -10
- package/.pi/prompts/harness-router-tune.md +0 -52
- package/.pi/scripts/harness-generate-model-router.mjs +0 -327
- package/.pi/scripts/harness-model-router-routing.test.mjs +0 -97
- package/.pi/scripts/harness-sync-model-router.mjs +0 -97
- package/.pi/scripts/vendor-sync-pi-model-router.sh +0 -47
- package/vendor/pi-model-router/.prettierignore +0 -4
- package/vendor/pi-model-router/.prettierrc +0 -5
- package/vendor/pi-model-router/AGENTS.md +0 -39
- package/vendor/pi-model-router/LICENSE +0 -21
- package/vendor/pi-model-router/README.md +0 -99
- package/vendor/pi-model-router/UPSTREAM_PIN.md +0 -10
- package/vendor/pi-model-router/docs/ARCHITECTURE.md +0 -54
- package/vendor/pi-model-router/extensions/commands.ts +0 -720
- package/vendor/pi-model-router/extensions/config.ts +0 -348
- package/vendor/pi-model-router/extensions/constants.ts +0 -1
- package/vendor/pi-model-router/extensions/index.ts +0 -478
- package/vendor/pi-model-router/extensions/provider.ts +0 -580
- package/vendor/pi-model-router/extensions/routing.ts +0 -564
- package/vendor/pi-model-router/extensions/state.ts +0 -52
- package/vendor/pi-model-router/extensions/types.ts +0 -95
- package/vendor/pi-model-router/extensions/ui.ts +0 -144
- package/vendor/pi-model-router/model-router.example.json +0 -48
- package/vendor/pi-model-router/package.json +0 -48
- package/vendor/pi-model-router/tsconfig.json +0 -16
- /package/.pi/{prompts → harness/docs}/planning-rubrics.md +0 -0
- /package/.pi/{extensions/lib → lib}/ask-user/fallback.ts +0 -0
- /package/.pi/{extensions/lib → lib}/ask-user/render.ts +0 -0
- /package/.pi/{extensions/lib → lib}/ask-user/schema.ts +0 -0
- /package/.pi/{extensions/lib → lib}/ask-user/types.ts +0 -0
- /package/.pi/{extensions/lib → lib}/ask-user/validate-core.mjs +0 -0
- /package/.pi/{extensions/lib → lib}/ask-user/validate.ts +0 -0
- /package/.pi/{extensions/lib → lib}/harness-cocoindex-refresh.ts +0 -0
- /package/.pi/{extensions/lib → lib}/harness-paths.ts +0 -0
- /package/.pi/{extensions/lib → lib}/harness-spawn-budget.ts +0 -0
- /package/.pi/{extensions/lib → lib}/harness-vcc-settings.ts +0 -0
- /package/.pi/{extensions/lib → lib}/harness-web/run-cli.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-approval/dialog.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-approval/schema.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-approval-readiness.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-debate-eligibility.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-debate-focus.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-debate-id.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-debate-lanes.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-debate-round-status.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-debate-write-guard.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-review-gate.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-review-integrator-rules.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-scope-guard.ts +0 -0
- /package/.pi/{extensions/lib → lib}/posthog-client.ts +0 -0
- /package/.pi/{extensions/lib → lib}/posthog-node.d.ts +0 -0
|
@@ -14,7 +14,6 @@ Bootstraps the complete ultimate-pi agentic harness: Graphify knowledge graph, C
|
|
|
14
14
|
| Pitfall | Correct approach |
|
|
15
15
|
|---------|------------------|
|
|
16
16
|
| `UP_PKG="$(pwd)"` in an **external** repo | Wrong — scripts live in the npm package. Resolve via `harness-resolve-up-pkg.mjs` (see Step 0). |
|
|
17
|
-
| Provider detection from `OPENAI_*` / `ANTHROPIC_*` env only | Wrong for pi users — keys live in `~/.pi/agent/auth.json`. Use `harness-generate-model-router.mjs` (Pi `ModelRegistry.getAvailable()`). |
|
|
18
17
|
| Re-running 2.1–2.8 manually after CLI verify | Wasteful — trust `harness-cli-verify.sh` output; only fix reported ✗ lines. |
|
|
19
18
|
| Overwriting `AGENTS.md` after graphify | Graphify appends a section — **merge**, do not replace (Step 4.3). |
|
|
20
19
|
| `sentrux-rules-sync` without project manifest | Use **`harness-sentrux-bootstrap.mjs`** (Step 4.2) — seeds manifest + idempotent rules sync. |
|
|
@@ -154,9 +153,9 @@ bash "$UP_PKG/.pi/scripts/harness-cli-verify.sh"
|
|
|
154
153
|
# Reinstall everything: bash "$UP_PKG/.pi/scripts/harness-cli-verify.sh" --force
|
|
155
154
|
```
|
|
156
155
|
|
|
157
|
-
**Required (script must exit 0):** scrapling + harness-web smoke, ctx7,
|
|
156
|
+
**Required (script must exit 0):** scrapling + harness-web smoke, ctx7, ast-grep (`sg`), sentrux (when harness manifest present).
|
|
158
157
|
|
|
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).
|
|
158
|
+
**Warnings allowed:** biome (optional; skipped for non-JS/TS repos or if install fails), 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
159
|
|
|
161
160
|
If the script reports **agent-browser shared library errors** on Linux/WSL, run the fix it prints, then re-verify:
|
|
162
161
|
|
|
@@ -251,21 +250,21 @@ ccc status
|
|
|
251
250
|
|
|
252
251
|
Verify: `ccc doctor` and `ccc search --limit 3 "export function"` (no `--refresh`).
|
|
253
252
|
|
|
254
|
-
### 2.5 — biome (
|
|
253
|
+
### 2.5 — biome (Optional, JS/TS-focused lint + format)
|
|
255
254
|
|
|
256
|
-
|
|
257
|
-
if ! command -v biome &>/dev/null || [ "$FORCE" = "true" ]; then
|
|
258
|
-
npm install -g @biomejs/biome
|
|
259
|
-
fi
|
|
260
|
-
```
|
|
255
|
+
Biome is **not a hard requirement** for harness setup. Install/use it when the target project is JS/TS (for example, has `package.json` or already uses `biome.json`). For other stacks, skip and use the repo's native formatter/linter.
|
|
261
256
|
|
|
262
|
-
Check if project already has biome config:
|
|
263
257
|
```bash
|
|
264
|
-
|
|
258
|
+
if [ -f package.json ] || [ -f biome.json ]; then
|
|
259
|
+
if ! command -v biome &>/dev/null || [ "$FORCE" = "true" ]; then
|
|
260
|
+
npm install -g @biomejs/biome
|
|
261
|
+
fi
|
|
262
|
+
biome --version
|
|
263
|
+
else
|
|
264
|
+
echo "Skipping biome (non-JS/TS repo; optional tool)"
|
|
265
|
+
fi
|
|
265
266
|
```
|
|
266
267
|
|
|
267
|
-
Verify: `biome --version`
|
|
268
|
-
|
|
269
268
|
### 2.6 — ast-grep (AST-Aware Structural Code Search)
|
|
270
269
|
|
|
271
270
|
```bash
|
|
@@ -327,7 +326,14 @@ sentrux plugin add-standard 2>/dev/null || echo "Plugins already installed or fa
|
|
|
327
326
|
|
|
328
327
|
## Step 3 — Pi Extension Packages
|
|
329
328
|
|
|
330
|
-
Bundled extensions load from the installed `ultimate-pi` package.
|
|
329
|
+
Bundled extensions load from the installed `ultimate-pi` package. The harness lens wrapper at `.pi/extensions/harness-lens.ts` loads `.pi/extensions/lib/harness-lens/` for edit autopatch, secrets blocking, deferred format, and LSP tools. Structural search uses shell `sg` (installed globally by setup); architecture gates use Sentrux. See [ADR 0045](.pi/harness/docs/adrs/0045-harness-lens-minimal-contract.md).
|
|
330
|
+
|
|
331
|
+
Harness lens findings are **complementary** to Sentrux:
|
|
332
|
+
|
|
333
|
+
- **Harness lens:** fast edit-time and turn-time code feedback; standalone lens widgets/health telemetry are disabled, and findings flow through the harness PostHog telemetry layer.
|
|
334
|
+
- **Sentrux:** architecture-quality signal and gate (`.sentrux/rules.toml`, `sentrux-signal.yaml`, harness review/evaluate inputs).
|
|
335
|
+
|
|
336
|
+
Do not treat harness lens as a replacement for Sentrux. If a future lens change adds architecture-boundary gating that duplicates Sentrux, keep Sentrux authoritative and disable/remove the overlapping lens path.
|
|
331
337
|
|
|
332
338
|
Optionally install the companion lockfile used in development:
|
|
333
339
|
|
|
@@ -341,51 +347,19 @@ else
|
|
|
341
347
|
fi
|
|
342
348
|
```
|
|
343
349
|
|
|
344
|
-
Merge extension entries from `$UP_PKG/.pi/settings.example.json` into this project's `.pi/settings.json` `packages` array (add any missing `npm:…` entries; keep existing user packages).
|
|
350
|
+
Merge extension entries from `$UP_PKG/.pi/settings.example.json` into this project's `.pi/settings.json` `packages` array (add any missing `npm:…` entries; keep existing user packages).
|
|
345
351
|
|
|
346
352
|
Verify each package:
|
|
347
353
|
|
|
348
354
|
| Package | Purpose | Phase |
|
|
349
355
|
|---------|---------|-------|
|
|
350
356
|
| `@posthog/pi` | Analytics event capture | F0 |
|
|
351
|
-
| `
|
|
357
|
+
| `context-mode` | Context runtime and MCP context-saving tools | F0 |
|
|
352
358
|
| `harness-subagents` (bundled extension) | L4 `subagent` tool, subprocess spawns, package agents | P16 |
|
|
353
359
|
| Vendored `pi-vcc` (`vendor/pi-vcc`, `.pi/extensions/ultimate-pi-vcc.ts`) | VCC compaction / `vcc_recall` — env-only: `HARNESS_VCC_COMPACTION` (default on), `HARNESS_VCC_DEBUG` | Shipped |
|
|
354
|
-
| `pi-
|
|
355
|
-
|
|
356
|
-
## Step 3.5 — Model Router Configuration (Dynamic)
|
|
357
|
-
|
|
358
|
-
`.pi/model-router.json` is **user-specific** (gitignored). Generate from **Pi authenticated providers** (`~/.pi/agent/auth.json`, OAuth, env) — **not** env-var guessing alone.
|
|
359
|
-
|
|
360
|
-
Pi API (see `packages/coding-agent` docs / SDK example `02-custom-model.ts`):
|
|
361
|
-
|
|
362
|
-
- `AuthStorage.create()` → credentials store
|
|
363
|
-
- `ModelRegistry.create(authStorage)` → registry
|
|
364
|
-
- `await modelRegistry.getAvailable()` → models with working auth (same as interactive pi)
|
|
365
|
-
|
|
366
|
-
```bash
|
|
367
|
-
# Verify vendored extension source ships with ultimate-pi
|
|
368
|
-
ls "$UP_PKG/vendor/pi-model-router/extensions/index.ts" 2>/dev/null \
|
|
369
|
-
&& echo "✓ vendored pi-model-router" \
|
|
370
|
-
|| echo "✗ missing vendor/pi-model-router"
|
|
371
|
-
|
|
372
|
-
# Generate from Pi registry (skips if .pi/model-router.json exists; --force to regenerate)
|
|
373
|
-
node "$UP_PKG/.pi/scripts/harness-generate-model-router.mjs"
|
|
374
|
-
# Preview only: node "$UP_PKG/.pi/scripts/harness-generate-model-router.mjs" --dry-run
|
|
375
|
-
|
|
376
|
-
# Merge router defaults after config exists (never adds npm packages — router is vendored)
|
|
377
|
-
node "$UP_PKG/.pi/scripts/harness-sync-model-router.mjs"
|
|
378
|
-
```
|
|
379
|
-
|
|
380
|
-
If generation prints "No authenticated Pi providers": warn in report — user should run **`/login`** in pi (or `pi login`) then re-run Step 3.5. Do **not** infer providers from `OPENAI_API_KEY` alone; pi sessions often use `opencode-go` via auth.json without those env vars.
|
|
381
|
-
|
|
382
|
-
Do NOT block setup. If no config is written, `harness-sync-model-router.mjs` clears a premature `defaultProvider: "router"` in `.pi/settings.json`.
|
|
383
|
-
|
|
384
|
-
**Router onboarding** — The vendored extension starts only after `.pi/model-router.json` appears. Running the script above prepares that file plus optional Pi defaults (**`router` / `auto`**, or whatever `defaultProfile` is) via `harness-sync-model-router.mjs` when `defaultProvider` was unset—then **`/reload`**. Generated profiles use **one model SKU per profile**; high/medium/low tiers differ in **thinking** only. Subagents resolve their subprocess model from the **agent system prompt** complexity (same lock rules).
|
|
385
|
-
|
|
386
|
-
Manual override: **`/router profile auto`** or **`/router profile opencode-go`** anytime after reload if they changed defaults.
|
|
360
|
+
| Harness lens (`.pi/extensions/harness-lens.ts` → `.pi/extensions/lib/harness-lens/index.ts`) | Edit autopatch, secrets block, deferred format, LSP tools; PostHog lens telemetry; Sentrux remains architecture gate; `sg` is shell-only | F0 |
|
|
387
361
|
|
|
388
|
-
## Step 3.
|
|
362
|
+
## Step 3.5 — Harness agents (package-resolved)
|
|
389
363
|
|
|
390
364
|
`harness-subagents` loads agents from the installed **`ultimate-pi`** package (`$UP_PKG/.pi/agents/**`) with namespaced ids (`harness/running/executor`, `harness/reviewing/evaluator`, `pi-pi/agent-expert`). **Do not copy** agents into the project unless you want a deliberate override.
|
|
391
365
|
|
|
@@ -500,10 +474,9 @@ Ensure `.gitignore` contains harness runtime entries (see repo root `.gitignore`
|
|
|
500
474
|
!.pi/harness/incidents/README.md
|
|
501
475
|
.pi/harness/debates/*
|
|
502
476
|
!.pi/harness/debates/README.md
|
|
503
|
-
.pi/harness/router/proposals/*
|
|
504
477
|
|
|
505
|
-
#
|
|
506
|
-
.pi/
|
|
478
|
+
# Harness lens runtime config/cache and local diagnostics state
|
|
479
|
+
.pi/harness/.lens/
|
|
507
480
|
|
|
508
481
|
# sentrux baselines and local meta (rules.toml is committed)
|
|
509
482
|
.sentrux/*
|
|
@@ -564,7 +537,7 @@ Created: $(date +%Y-%m-%d)
|
|
|
564
537
|
- .pi/harness/specs/ → Harness contracts and schema docs
|
|
565
538
|
- .pi/harness/incidents/ → Incident and override records
|
|
566
539
|
- `.agents/skills/` (npm package) → Harness skills (no copy into `.pi/skills/` needed)
|
|
567
|
-
- `.pi/agents/` → Optional per-repo agent overrides (package agents load automatically — see Step 3.
|
|
540
|
+
- `.pi/agents/` → Optional per-repo agent overrides (package agents load automatically — see Step 3.5)
|
|
568
541
|
|
|
569
542
|
## Graphify-First Workflow
|
|
570
543
|
|
|
@@ -580,7 +553,7 @@ Created: $(date +%Y-%m-%d)
|
|
|
580
553
|
- Decisions and incidents in `.pi/harness/` with structured artifacts
|
|
581
554
|
- `GRAPHIFY_VIZ_NODE_LIMIT=200000 graphify update .` after significant code changes
|
|
582
555
|
- ast-grep (`sg`) is the default code search tool — use `sg -p 'pattern'` for structural search, never grep for code
|
|
583
|
-
-
|
|
556
|
+
- Use shell `sg` for structural search; project-specific ast-grep rule dirs are optional in the **target repo**, not a harness template default
|
|
584
557
|
```
|
|
585
558
|
|
|
586
559
|
## Step 5 — Verification
|
|
@@ -627,10 +600,11 @@ print(f'✓ knowledge graph built ({n} nodes)' if n else '✗ graph.json has 0 n
|
|
|
627
600
|
" 2>/dev/null || echo "✗ no graph built yet"
|
|
628
601
|
graphify hook status 2>/dev/null && echo "✓ graphify git hooks installed" || echo "✗ graphify git hooks not installed"
|
|
629
602
|
|
|
630
|
-
#
|
|
631
|
-
ls "$UP_PKG
|
|
632
|
-
&& echo "✓
|
|
633
|
-
ls
|
|
603
|
+
# harness lens extension
|
|
604
|
+
ls "$UP_PKG/.pi/extensions/harness-lens.ts" 2>/dev/null \
|
|
605
|
+
&& echo "✓ harness lens wrapper" || echo "✗ harness lens wrapper missing"
|
|
606
|
+
ls "$UP_PKG/.pi/extensions/lib/harness-lens/index.ts" 2>/dev/null \
|
|
607
|
+
&& echo "✓ harness lens upstream pin" || echo "✗ harness lens upstream pin missing"
|
|
634
608
|
|
|
635
609
|
# raw folder for graphify sources
|
|
636
610
|
ls -d ./raw 2>/dev/null && echo "✓ ./raw directory exists" || echo "! ./raw directory missing"
|
|
@@ -672,13 +646,13 @@ Output summary table:
|
|
|
672
646
|
| ctx7 | ✓/✗ | Login: yes/no |
|
|
673
647
|
| agent-browser | ✓/✗ | Config: .pi/harness/browser.json |
|
|
674
648
|
| cocoindex-code | ✓/✗ | `ccc status`; index auto-refreshed before harness scouts |
|
|
675
|
-
| biome |
|
|
649
|
+
| biome | ✓/✗/skip | Optional; JS/TS-focused (skip on non-JS/TS stacks) |
|
|
676
650
|
| ast-grep | ✓/✗ | AST-aware code search (`sg`)
|
|
677
651
|
| gh CLI | ✓/✗ | Auth: yes/no |
|
|
678
652
|
| sentrux | ✓/✗ | CLI + plugins; rules via Step 4.2 bootstrap |
|
|
679
653
|
| Sentrux rules.toml | ✓/✗ | `.sentrux/rules.toml` synced from manifest |
|
|
680
|
-
| pi extensions | ✓/✗ |
|
|
681
|
-
|
|
|
654
|
+
| pi extensions | ✓/✗ | bundled extensions + harness lens wrapper |
|
|
655
|
+
| harness lens | ✓/✗ | `.pi/extensions/harness-lens.ts`; PostHog owns lens telemetry; complements Sentrux architecture signal |
|
|
682
656
|
| `.env` | ✓/✗/ask | Created / keys appended / user declined |
|
|
683
657
|
|
|
684
658
|
| .gitignore | ✓/✗ | entries added (incl. `.env`) |
|
|
@@ -728,11 +702,10 @@ Next steps:
|
|
|
728
702
|
| gh not installed | Show GitHub CLI install link. Skip label creation. |
|
|
729
703
|
| pi packages install fail | Show error output. Check npm permissions. |
|
|
730
704
|
| graph already exists | Report node count. Refresh with `graphify update .` unless user passed `--force`. |
|
|
731
|
-
| biome.json missing |
|
|
705
|
+
| biome.json missing | No action required. Biome is optional; use project-native tooling. |
|
|
732
706
|
| settings.json not writable | Warn. Settings won't persist across sessions. |
|
|
733
707
|
| No internet | Block for tool installs. Continue for graphify-only steps if `--skip-tools`. |
|
|
734
708
|
| sentrux install fails | Show install script output. Fallback: download from https://github.com/sentrux/sentrux/releases/latest |
|
|
735
|
-
| No model-router.json / "No authenticated Pi providers" | Run `/login` in pi, then `node "$UP_PKG/.pi/scripts/harness-generate-model-router.mjs" --force` |
|
|
736
709
|
| UP_PKG not found | `pi install npm:ultimate-pi` or `npm i -g ultimate-pi`; verify with `node "$UP_PKG/.pi/scripts/harness-resolve-up-pkg.mjs"` |
|
|
737
710
|
| No `.env` at project root | `ask_user` create vs skip; on create: `harness-sync-env.mjs --create-missing` |
|
|
738
711
|
|
package/.pi/scripts/README.md
CHANGED
|
@@ -14,7 +14,7 @@ UP_PKG="$(node -p "require('path').dirname(require.resolve('ultimate-pi/package.
|
|
|
14
14
|
|
|
15
15
|
**Developing this repo** (clone of `ultimate-pi`): from the repo root, `UP_PKG="$(pwd)"` (or the same `require.resolve` after `npm install`).
|
|
16
16
|
|
|
17
|
-
From **Typescript extensions**, use `resolveHarnessScript()` / `getHarnessPackageRoot()` in `.pi/
|
|
17
|
+
From **Typescript extensions**, use `resolveHarnessScript()` / `getHarnessPackageRoot()` in `.pi/lib/harness-paths.ts`.
|
|
18
18
|
|
|
19
19
|
## Invocations (from the consuming project root)
|
|
20
20
|
|
|
@@ -29,11 +29,8 @@ From **Typescript extensions**, use `resolveHarnessScript()` / `getHarnessPackag
|
|
|
29
29
|
| Sentrux rules drift check (CI) | `node "$UP_PKG/.pi/scripts/sentrux-rules-sync.mjs" --check` |
|
|
30
30
|
| Sentrux run/review check or gate (root-resolving) | `node "$UP_PKG/.pi/scripts/harness-sentrux-cli.mjs" check` / `gate [--save]` |
|
|
31
31
|
| Resolve package root (`UP_PKG`) | `node "$UP_PKG/.pi/scripts/harness-resolve-up-pkg.mjs"` |
|
|
32
|
-
| Model-router config (Pi auth) | `node "$UP_PKG/.pi/scripts/harness-generate-model-router.mjs"` |
|
|
33
32
|
| Project `.env` (append-only) | `node "$UP_PKG/.pi/scripts/harness-sync-env.mjs"` (`--create-missing` after user confirms) |
|
|
34
|
-
|
|
|
35
|
-
| Vendor router sync (this repo only) | `bash .pi/scripts/vendor-sync-pi-model-router.sh` or `npm run vendor:sync-router` |
|
|
36
|
-
| Meta-optimizer (JSONL proposals) | `node "$UP_PKG/.pi/harness/evolution/meta-optimizer.mjs"` |
|
|
33
|
+
| Harness lens extension | `.pi/extensions/harness-lens.ts` → `.pi/lib/harness-lens/index.ts` (loaded by `.pi/extensions`; PostHog owns lens telemetry) |
|
|
37
34
|
|
|
38
35
|
Pass `--force` to shell scripts that support it (e.g. `harness-graphify-bootstrap.sh --force`, `harness-cli-verify.sh --force`).
|
|
39
36
|
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Generate .pi/harness/agents.policy.yaml from harness agent .md frontmatter + submit registry.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
7
|
+
import { join, dirname } from "node:path";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
import { parse as parseYaml } from "yaml";
|
|
10
|
+
import { walkAgentsDir } from "../lib/harness-agent-discovery.mjs";
|
|
11
|
+
|
|
12
|
+
const ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
13
|
+
const AGENTS_DIR = join(ROOT, ".pi", "agents");
|
|
14
|
+
const OUT = join(ROOT, ".pi", "harness", "agents.policy.yaml");
|
|
15
|
+
|
|
16
|
+
const SUBMIT_BY_AGENT = {
|
|
17
|
+
"harness/planning/planning-context": ["submit_planning_context"],
|
|
18
|
+
"harness/planning/decompose": ["submit_decomposition_brief", "submit_human_required"],
|
|
19
|
+
"harness/planning/hypothesis": ["submit_hypothesis_brief"],
|
|
20
|
+
"harness/planning/hypothesis-validator": ["submit_hypothesis_validation"],
|
|
21
|
+
"harness/planning/plan-evaluator": ["submit_validation_turn"],
|
|
22
|
+
"harness/planning/plan-adversary": ["submit_adversary_brief"],
|
|
23
|
+
"harness/planning/sprint-contract-auditor": ["submit_sprint_audit"],
|
|
24
|
+
"harness/planning/review-integrator": ["submit_review_round_draft"],
|
|
25
|
+
"harness/planning/implementation-researcher": ["submit_implementation_research"],
|
|
26
|
+
"harness/planning/stack-researcher": ["submit_stack_brief"],
|
|
27
|
+
"harness/planning/execution-plan-author": ["submit_execution_plan_brief"],
|
|
28
|
+
"harness/running/executor": ["submit_executor_handoff"],
|
|
29
|
+
"harness/reviewing/evaluator": ["submit_eval_verdict"],
|
|
30
|
+
"harness/reviewing/adversary": ["submit_adversary_report"],
|
|
31
|
+
"harness/reviewing/tie-breaker": ["submit_human_required"],
|
|
32
|
+
"harness/trace-librarian": ["submit_human_required"],
|
|
33
|
+
"harness/incident-recorder": ["submit_human_required"],
|
|
34
|
+
"harness/sentrux-steward": ["submit_sentrux_manifest_proposal"],
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
function parseFrontmatter(content) {
|
|
38
|
+
const m = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
39
|
+
if (!m) return {};
|
|
40
|
+
return parseYaml(m[1]) ?? {};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function kindFor(id) {
|
|
44
|
+
if (id.startsWith("harness/planning/")) return "planner";
|
|
45
|
+
if (id === "harness/running/executor") return "executor";
|
|
46
|
+
if (id === "harness/reviewing/evaluator") return "evaluator";
|
|
47
|
+
if (id === "harness/reviewing/adversary") return "adversary";
|
|
48
|
+
if (id === "harness/reviewing/tie-breaker") return "tie_breaker";
|
|
49
|
+
if (id === "harness/trace-librarian") return "trace";
|
|
50
|
+
if (id === "harness/incident-recorder") return "incident";
|
|
51
|
+
if (id === "harness/sentrux-steward" || id === "harness/sentrux-bootstrap")
|
|
52
|
+
return "planner";
|
|
53
|
+
return "other";
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const KIND_BASE = {
|
|
57
|
+
planner: ["read", "grep", "find", "ls"],
|
|
58
|
+
executor: ["read", "write", "edit", "bash", "grep", "find", "ls"],
|
|
59
|
+
evaluator: ["read", "grep", "find", "ls"],
|
|
60
|
+
adversary: ["read", "grep", "find", "ls"],
|
|
61
|
+
tie_breaker: ["read", "grep", "find", "ls"],
|
|
62
|
+
trace: ["read", "grep", "find", "ls"],
|
|
63
|
+
incident: ["read", "grep", "find", "ls"],
|
|
64
|
+
other: ["read", "grep", "find", "ls"],
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
function csvTools(fm) {
|
|
68
|
+
const raw = fm.tools;
|
|
69
|
+
if (!raw) return [];
|
|
70
|
+
return String(raw)
|
|
71
|
+
.split(",")
|
|
72
|
+
.map((t) => t.trim())
|
|
73
|
+
.filter(Boolean);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async function main() {
|
|
77
|
+
const files = new Map();
|
|
78
|
+
walkAgentsDir(AGENTS_DIR, "package", files);
|
|
79
|
+
|
|
80
|
+
const kinds = {
|
|
81
|
+
planner: { tools: KIND_BASE.planner, extensions: false, read_only: true },
|
|
82
|
+
executor: { tools: KIND_BASE.executor, extensions: true, read_only: false },
|
|
83
|
+
evaluator: { tools: KIND_BASE.evaluator, extensions: false, read_only: true },
|
|
84
|
+
adversary: { tools: KIND_BASE.adversary, extensions: false, read_only: true },
|
|
85
|
+
tie_breaker: {
|
|
86
|
+
tools: KIND_BASE.tie_breaker,
|
|
87
|
+
extensions: false,
|
|
88
|
+
read_only: true,
|
|
89
|
+
},
|
|
90
|
+
trace: { tools: KIND_BASE.trace, extensions: false, read_only: true },
|
|
91
|
+
incident: { tools: KIND_BASE.incident, extensions: false, read_only: true },
|
|
92
|
+
other: { tools: KIND_BASE.other, extensions: false, read_only: true },
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const agents = {};
|
|
96
|
+
|
|
97
|
+
for (const [id, file] of files) {
|
|
98
|
+
if (!id.startsWith("harness/")) continue;
|
|
99
|
+
const fm = parseFrontmatter(file.content);
|
|
100
|
+
const kind = kindFor(id);
|
|
101
|
+
const base = new Set(KIND_BASE[kind] ?? KIND_BASE.other);
|
|
102
|
+
const fromFm = csvTools(fm);
|
|
103
|
+
const submit = SUBMIT_BY_AGENT[id] ?? [];
|
|
104
|
+
const toolsAdd = [...new Set([...fromFm, ...submit])].filter(
|
|
105
|
+
(t) => !base.has(t),
|
|
106
|
+
);
|
|
107
|
+
const entry = { kind };
|
|
108
|
+
if (toolsAdd.length > 0) entry.tools_add = toolsAdd;
|
|
109
|
+
if (fm.extensions === false) entry.extensions = false;
|
|
110
|
+
if (fm.extensions === true) entry.extensions = true;
|
|
111
|
+
if (typeof fm.max_turns === "number") entry.max_turns = fm.max_turns;
|
|
112
|
+
if (typeof fm.thinking === "string") entry.thinking = fm.thinking;
|
|
113
|
+
if (submit.length === 1) entry.submit_tool = submit[0];
|
|
114
|
+
agents[id] = entry;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// plan-synthesizer: parent-only, minimal policy for spawn if ever used
|
|
118
|
+
agents["harness/planning/plan-synthesizer"] = {
|
|
119
|
+
kind: "planner",
|
|
120
|
+
tools_add: [
|
|
121
|
+
"submit_decomposition_brief",
|
|
122
|
+
"submit_hypothesis_brief",
|
|
123
|
+
"submit_execution_plan_brief",
|
|
124
|
+
],
|
|
125
|
+
extensions: false,
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const doc = {
|
|
129
|
+
apiVersion: "harness.toolkit/v1",
|
|
130
|
+
kinds,
|
|
131
|
+
agents,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const yaml = [
|
|
135
|
+
"# Generated/maintained SSOT for harness agent tools (see ADR 0049).",
|
|
136
|
+
"# Regenerate hints: node .pi/scripts/generate-agents-policy-yaml.mjs",
|
|
137
|
+
"",
|
|
138
|
+
];
|
|
139
|
+
const { stringify } = await import("yaml");
|
|
140
|
+
yaml.push(stringify(doc));
|
|
141
|
+
await writeFile(OUT, yaml.join("\n"), "utf8");
|
|
142
|
+
console.log(`Wrote ${OUT} (${Object.keys(agents).length} harness agents)`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
main().catch((err) => {
|
|
146
|
+
console.error(err);
|
|
147
|
+
process.exit(1);
|
|
148
|
+
});
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* node .pi/scripts/harness-agents-manifest.mjs --check
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import { existsSync } from "node:fs";
|
|
10
11
|
import { readFile, writeFile } from "node:fs/promises";
|
|
11
12
|
import { join, dirname } from "node:path";
|
|
12
13
|
import { fileURLToPath } from "node:url";
|
|
@@ -15,6 +16,10 @@ import {
|
|
|
15
16
|
sha256Content,
|
|
16
17
|
walkAgentsDir,
|
|
17
18
|
} from "../lib/harness-agent-discovery.mjs";
|
|
19
|
+
import {
|
|
20
|
+
loadAgentsPolicyMerged,
|
|
21
|
+
packageAgentsPolicyPath,
|
|
22
|
+
} from "../lib/agents-policy.mjs";
|
|
18
23
|
|
|
19
24
|
const ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
20
25
|
const MANIFEST_PATH = join(ROOT, ".pi", "harness", "agents.manifest.json");
|
|
@@ -27,7 +32,7 @@ async function readPackageMeta() {
|
|
|
27
32
|
return { name: pkg.name ?? "ultimate-pi", version: pkg.version ?? "0.0.0" };
|
|
28
33
|
}
|
|
29
34
|
|
|
30
|
-
function buildManifest(packageFiles, packageName, packageVersion) {
|
|
35
|
+
async function buildManifest(packageFiles, packageName, packageVersion) {
|
|
31
36
|
const agents = {};
|
|
32
37
|
for (const f of packageFiles.values()) {
|
|
33
38
|
agents[f.id] = {
|
|
@@ -35,11 +40,17 @@ function buildManifest(packageFiles, packageName, packageVersion) {
|
|
|
35
40
|
sha256: sha256Content(f.content),
|
|
36
41
|
};
|
|
37
42
|
}
|
|
43
|
+
const policyPath = packageAgentsPolicyPath(ROOT);
|
|
44
|
+
let policy_sha256;
|
|
45
|
+
if (existsSync(policyPath)) {
|
|
46
|
+
policy_sha256 = sha256Content(await readFile(policyPath, "utf-8"));
|
|
47
|
+
}
|
|
38
48
|
return {
|
|
39
49
|
schema_version: "1.0.0",
|
|
40
50
|
package: packageName,
|
|
41
51
|
package_version: packageVersion,
|
|
42
52
|
generated_at: new Date().toISOString(),
|
|
53
|
+
...(policy_sha256 ? { policy_sha256 } : {}),
|
|
43
54
|
agents,
|
|
44
55
|
};
|
|
45
56
|
}
|
|
@@ -68,6 +79,37 @@ function getDriftReport(manifest, packageFiles) {
|
|
|
68
79
|
return { ok: items.length === 0, items };
|
|
69
80
|
}
|
|
70
81
|
|
|
82
|
+
function frontmatterHasToolLists(content) {
|
|
83
|
+
const m = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
84
|
+
if (!m) return false;
|
|
85
|
+
return /^tools:/m.test(m[1]) || /^disallowed_tools:/m.test(m[1]);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function verifyAgentsPolicy(packageFiles) {
|
|
89
|
+
const items = [];
|
|
90
|
+
const policyPath = packageAgentsPolicyPath(ROOT);
|
|
91
|
+
if (!existsSync(policyPath)) {
|
|
92
|
+
return { ok: false, items: [{ id: "*", kind: "missing_agents_policy_yaml" }] };
|
|
93
|
+
}
|
|
94
|
+
const merged = loadAgentsPolicyMerged(ROOT, ROOT);
|
|
95
|
+
for (const [id, file] of packageFiles) {
|
|
96
|
+
if (!id.startsWith("harness/")) continue;
|
|
97
|
+
if (frontmatterHasToolLists(file.content)) {
|
|
98
|
+
items.push({ id, kind: "frontmatter_tools" });
|
|
99
|
+
}
|
|
100
|
+
if (!merged.agents.has(id)) {
|
|
101
|
+
items.push({ id, kind: "missing_policy_entry" });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
for (const id of merged.agents.keys()) {
|
|
105
|
+
if (!id.startsWith("harness/")) continue;
|
|
106
|
+
if (!packageFiles.has(id)) {
|
|
107
|
+
items.push({ id, kind: "orphan_policy_entry" });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return { ok: items.length === 0, items };
|
|
111
|
+
}
|
|
112
|
+
|
|
71
113
|
async function loadPackageFiles() {
|
|
72
114
|
const files = new Map();
|
|
73
115
|
walkAgentsDir(PACKAGE_AGENTS, "package", files);
|
|
@@ -81,7 +123,7 @@ async function main() {
|
|
|
81
123
|
const mode = process.argv.includes("--check") ? "check" : "write";
|
|
82
124
|
const { name, version } = await readPackageMeta();
|
|
83
125
|
const packageFiles = await loadPackageFiles();
|
|
84
|
-
const built = buildManifest(packageFiles, name, version);
|
|
126
|
+
const built = await buildManifest(packageFiles, name, version);
|
|
85
127
|
|
|
86
128
|
if (mode === "write") {
|
|
87
129
|
await writeFile(MANIFEST_PATH, `${JSON.stringify(built, null, "\t")}\n`, "utf-8");
|
|
@@ -107,6 +149,19 @@ async function main() {
|
|
|
107
149
|
process.exit(1);
|
|
108
150
|
}
|
|
109
151
|
|
|
152
|
+
const policyCheck = verifyAgentsPolicy(packageFiles);
|
|
153
|
+
if (!policyCheck.ok) {
|
|
154
|
+
for (const item of policyCheck.items) {
|
|
155
|
+
console.error(`policy: ${item.id} (${item.kind})`);
|
|
156
|
+
}
|
|
157
|
+
process.exit(1);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (built.policy_sha256 && onDisk.policy_sha256 !== built.policy_sha256) {
|
|
161
|
+
console.error("policy_sha256 mismatch — regenerate manifest with --write");
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
|
|
110
165
|
if (onDisk.package_version !== version) {
|
|
111
166
|
console.error(
|
|
112
167
|
`package_version mismatch: manifest=${onDisk.package_version} package=${version}`,
|
|
@@ -114,7 +169,9 @@ async function main() {
|
|
|
114
169
|
process.exit(1);
|
|
115
170
|
}
|
|
116
171
|
|
|
117
|
-
console.log(
|
|
172
|
+
console.log(
|
|
173
|
+
`agents.manifest.json OK (${Object.keys(built.agents).length} agents, policy aligned)`,
|
|
174
|
+
);
|
|
118
175
|
}
|
|
119
176
|
|
|
120
177
|
main().catch((err) => {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { doctorHarnessPolicies } from "../lib/agt/policy-engine.js";
|
|
6
|
+
|
|
7
|
+
const ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
8
|
+
const doc = doctorHarnessPolicies(ROOT);
|
|
9
|
+
if (!doc.ok) {
|
|
10
|
+
console.error("AGT policy doctor failed:");
|
|
11
|
+
for (const e of doc.errors) console.error(` - ${e}`);
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
const pkg = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf-8")) as {
|
|
15
|
+
files?: string[];
|
|
16
|
+
};
|
|
17
|
+
const files = pkg.files ?? [];
|
|
18
|
+
if (
|
|
19
|
+
!files.some(
|
|
20
|
+
(f: string) =>
|
|
21
|
+
f === ".pi/harness/policies" || f.startsWith(".pi/harness/policies/"),
|
|
22
|
+
)
|
|
23
|
+
) {
|
|
24
|
+
console.error("package.json files[] missing .pi/harness/policies");
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
if (
|
|
28
|
+
!files.includes(".pi/lib") &&
|
|
29
|
+
!files.some((f) => f.startsWith(".pi/lib/"))
|
|
30
|
+
) {
|
|
31
|
+
console.error("package.json files[] missing .pi/lib (ships .pi/lib/agt)");
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
console.log(
|
|
35
|
+
`AGT doctor OK (${doc.loaded.length} policies at ${doc.policyDir})`,
|
|
36
|
+
);
|
|
@@ -262,11 +262,18 @@ verify_cocoindex() {
|
|
|
262
262
|
|
|
263
263
|
verify_biome() {
|
|
264
264
|
log "[biome]"
|
|
265
|
-
|
|
265
|
+
if [ ! -f "${ROOT}/package.json" ] && [ ! -f "${ROOT}/biome.json" ]; then
|
|
266
|
+
warn "biome skipped (non-JS/TS repo detected; optional tool)"
|
|
267
|
+
return
|
|
268
|
+
fi
|
|
269
|
+
npm_global_install "@biomejs/biome" "biome" || {
|
|
270
|
+
warn "biome npm install failed (optional — use your stack's formatter/linter)"
|
|
271
|
+
return
|
|
272
|
+
}
|
|
266
273
|
if biome --version &>/dev/null; then
|
|
267
274
|
pass "biome $(biome --version 2>/dev/null | head -1)"
|
|
268
275
|
else
|
|
269
|
-
|
|
276
|
+
warn "biome --version failed (optional — use your stack's formatter/linter)"
|
|
270
277
|
fi
|
|
271
278
|
}
|
|
272
279
|
|