ultimate-pi 0.18.0 → 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 +2 -3
- package/.agents/skills/harness-governor/SKILL.md +6 -5
- package/.agents/skills/harness-orchestration/SKILL.md +4 -4
- package/.agents/skills/harness-review/SKILL.md +7 -7
- package/.agents/skills/harness-sentrux-setup/SKILL.md +4 -3
- package/.agents/skills/harness-steer/SKILL.md +1 -1
- package/.agents/skills/sentrux/SKILL.md +9 -9
- 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 +1 -3
- 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/{adversary.md → reviewing/adversary.md} +0 -2
- package/.pi/agents/harness/{evaluator.md → reviewing/evaluator.md} +0 -2
- package/.pi/agents/harness/{tie-breaker.md → reviewing/tie-breaker.md} +0 -2
- package/.pi/agents/harness/{executor.md → 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-harness-project-control.ts +133 -0
- 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/budget-guard.ts +2 -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 +7 -5
- package/.pi/extensions/harness-ask-user.ts +8 -8
- package/.pi/extensions/harness-debate-tools.ts +27 -43
- package/.pi/extensions/harness-lens.ts +94 -0
- package/.pi/extensions/harness-live-widget.ts +33 -2
- package/.pi/extensions/harness-plan-approval.ts +12 -12
- package/.pi/extensions/harness-run-context.ts +1214 -852
- package/.pi/extensions/harness-subagent-governance.ts +8 -0
- package/.pi/extensions/harness-subagent-submit.ts +36 -164
- package/.pi/extensions/harness-subagents.ts +4 -4
- package/.pi/extensions/harness-telemetry.ts +3 -1
- package/.pi/extensions/harness-web-tools.ts +3 -3
- package/.pi/extensions/observation-bus.ts +2 -0
- package/.pi/extensions/policy-gate.ts +27 -5
- package/.pi/extensions/review-integrity.ts +91 -10
- package/.pi/extensions/sentrux-rules-sync.ts +3 -1
- package/.pi/extensions/subagent-governance.ts +92 -0
- package/.pi/extensions/test-diff-integrity.ts +1 -0
- package/.pi/extensions/trace-recorder.ts +3 -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 +38 -49
- package/.pi/harness/agents.policy.yaml +275 -0
- package/.pi/harness/corpus/graphify-kb-updater.config.json +55 -0
- package/.pi/harness/docs/adrs/0006-sentrux-dual-layer.md +2 -1
- 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/0044-harness-steer-loop.md +3 -2
- package/.pi/harness/docs/adrs/0045-harness-lens-minimal-contract.md +49 -0
- package/.pi/harness/docs/adrs/0045-phase-scoped-agent-directories.md +33 -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 +6 -0
- package/.pi/harness/docs/graphify-kb-updater-runbook.md +11 -5
- package/.pi/harness/docs/practice-map.md +2 -2
- 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/harness-spawn-context.schema.json +1 -1
- 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 +21 -0
- package/.pi/lib/harness-agt-tool-guard.ts +5 -0
- package/.pi/{extensions/lib → lib}/harness-artifact-gate.ts +6 -16
- 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-project-config.ts +91 -0
- package/.pi/lib/harness-run-context-responses.ts +9 -0
- package/.pi/lib/harness-run-context.ts +1 -3
- package/.pi/{extensions/lib/spawn-policy.ts → lib/harness-spawn-policy.ts} +4 -3
- package/.pi/{extensions/lib → lib}/harness-spawn-topology.ts +5 -28
- package/.pi/lib/harness-subagent-auth.ts +51 -0
- package/.pi/{extensions/lib → lib}/harness-subagent-precheck.ts +13 -10
- 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 -55
- package/.pi/{extensions/lib → lib}/harness-subagents-bridge.ts +53 -14
- package/.pi/{extensions/lib → lib}/harness-subprocess-bootstrap.ts +1 -1
- package/.pi/lib/harness-ui-state.ts +27 -12
- 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-approval-readiness.ts +3 -52
- 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-auto.md +2 -2
- package/.pi/prompts/harness-plan.md +4 -6
- package/.pi/prompts/harness-review.md +9 -9
- package/.pi/prompts/harness-run.md +7 -7
- package/.pi/prompts/harness-setup.md +42 -68
- package/.pi/prompts/harness-steer.md +2 -2
- package/.pi/scripts/README.md +3 -5
- package/.pi/scripts/generate-agents-policy-yaml.mjs +148 -0
- package/.pi/scripts/graphify-kb-updater.mjs +48 -8
- package/.pi/scripts/harness-agents-manifest.mjs +61 -4
- package/.pi/scripts/harness-agt-doctor.ts +36 -0
- package/.pi/scripts/harness-cli-verify.sh +9 -2
- package/.pi/scripts/harness-project-toggle.mjs +129 -0
- package/.pi/scripts/harness-sentrux-cli.mjs +142 -0
- 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 +26 -0
- package/README.md +85 -58
- 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/agents/harness/planning/scout-graphify.md +0 -39
- package/.pi/agents/harness/planning/scout-semantic.md +0 -41
- package/.pi/agents/harness/planning/scout-structure.md +0 -37
- package/.pi/extensions/lib/ask-user/dialog.ts +0 -260
- package/.pi/extensions/lib/harness-subagent-auth.ts +0 -209
- 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-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
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Propose architecture.manifest.json changes from graphify evidence (read-only governance steward).
|
|
3
|
-
tools: read, grep, find, ls, bash, submit_sentrux_manifest_proposal
|
|
4
|
-
disallowed_tools: write, edit, ask_user, approve_plan, create_plan, subagent
|
|
5
3
|
extensions: false
|
|
6
4
|
thinking: high
|
|
7
5
|
max_turns: 16
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* harness-project-control — always-on enable/disable for harness governance.
|
|
3
|
+
*
|
|
4
|
+
* Writes `.pi/harness/project.json`, blocks workflow slash commands while disabled,
|
|
5
|
+
* and emits `harness-project-enabled:changed` so live TUI surfaces update immediately.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
ExtensionAPI,
|
|
10
|
+
ExtensionCommandContext,
|
|
11
|
+
} from "@earendil-works/pi-coding-agent";
|
|
12
|
+
import {
|
|
13
|
+
isHarnessProjectEnabled,
|
|
14
|
+
isHarnessWorkflowCommand,
|
|
15
|
+
readHarnessProjectConfig,
|
|
16
|
+
writeHarnessProjectEnabled,
|
|
17
|
+
} from "../lib/harness-project-config.js";
|
|
18
|
+
import { parseHarnessSlashInput } from "../lib/harness-run-context.js";
|
|
19
|
+
|
|
20
|
+
function showCommandMessage(
|
|
21
|
+
pi: ExtensionAPI,
|
|
22
|
+
ctx: ExtensionCommandContext,
|
|
23
|
+
text: string,
|
|
24
|
+
): void {
|
|
25
|
+
if (ctx.hasUI) {
|
|
26
|
+
ctx.ui.notify(text, "info");
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
pi.sendMessage({
|
|
30
|
+
customType: "harness-project-control",
|
|
31
|
+
content: text,
|
|
32
|
+
display: true,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function formatStatus(projectRoot: string): string {
|
|
37
|
+
const config = readHarnessProjectConfig(projectRoot);
|
|
38
|
+
const env = process.env.HARNESS_ENABLED?.trim();
|
|
39
|
+
const lines = [
|
|
40
|
+
`Harness governance: ${config.enabled ? "enabled" : "disabled"}`,
|
|
41
|
+
`Config: .pi/harness/project.json`,
|
|
42
|
+
];
|
|
43
|
+
if (env) {
|
|
44
|
+
lines.push(`Env override: HARNESS_ENABLED=${env}`);
|
|
45
|
+
}
|
|
46
|
+
if (config.updated_at) {
|
|
47
|
+
lines.push(`Updated: ${config.updated_at}`);
|
|
48
|
+
}
|
|
49
|
+
if (!config.enabled) {
|
|
50
|
+
lines.push(
|
|
51
|
+
"Workflow commands (/harness-plan, /harness-run, …) are blocked until you run /harness-enable.",
|
|
52
|
+
);
|
|
53
|
+
} else {
|
|
54
|
+
lines.push("Run /harness-disable to turn governance off.");
|
|
55
|
+
}
|
|
56
|
+
return lines.join("\n");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export default function harnessProjectControl(pi: ExtensionAPI) {
|
|
60
|
+
pi.on("input", async (event) => {
|
|
61
|
+
if (event.source === "extension") {
|
|
62
|
+
return { action: "continue" as const };
|
|
63
|
+
}
|
|
64
|
+
const parsed = parseHarnessSlashInput(event.text);
|
|
65
|
+
if (!parsed || !isHarnessWorkflowCommand(parsed.command)) {
|
|
66
|
+
return { action: "continue" as const };
|
|
67
|
+
}
|
|
68
|
+
if (isHarnessProjectEnabled()) {
|
|
69
|
+
return { action: "continue" as const };
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
action: "handled" as const,
|
|
73
|
+
message: [
|
|
74
|
+
`Harness governance is disabled — /${parsed.command} was not started.`,
|
|
75
|
+
"Run /harness-enable to restore the workflow command surface.",
|
|
76
|
+
].join("\n"),
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
pi.registerCommand("harness-enable", {
|
|
81
|
+
description: "Enable harness governance for this project",
|
|
82
|
+
handler: async (_args, ctx) => {
|
|
83
|
+
const projectRoot = process.cwd();
|
|
84
|
+
const config = writeHarnessProjectEnabled(projectRoot, true);
|
|
85
|
+
const effectiveConfig = readHarnessProjectConfig(projectRoot);
|
|
86
|
+
pi.events.emit("harness-project-enabled:changed", {
|
|
87
|
+
enabled: effectiveConfig.enabled,
|
|
88
|
+
projectRoot,
|
|
89
|
+
updated_at: config.updated_at,
|
|
90
|
+
});
|
|
91
|
+
showCommandMessage(
|
|
92
|
+
pi,
|
|
93
|
+
ctx,
|
|
94
|
+
[
|
|
95
|
+
"Harness governance enabled.",
|
|
96
|
+
`Wrote .pi/harness/project.json (enabled=true, updated ${config.updated_at}).`,
|
|
97
|
+
"Live TUI surfaces were refreshed.",
|
|
98
|
+
].join("\n"),
|
|
99
|
+
);
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
pi.registerCommand("harness-disable", {
|
|
104
|
+
description: "Disable harness governance for this project",
|
|
105
|
+
handler: async (_args, ctx) => {
|
|
106
|
+
const projectRoot = process.cwd();
|
|
107
|
+
const config = writeHarnessProjectEnabled(projectRoot, false);
|
|
108
|
+
const effectiveConfig = readHarnessProjectConfig(projectRoot);
|
|
109
|
+
pi.events.emit("harness-project-enabled:changed", {
|
|
110
|
+
enabled: effectiveConfig.enabled,
|
|
111
|
+
projectRoot,
|
|
112
|
+
updated_at: config.updated_at,
|
|
113
|
+
});
|
|
114
|
+
showCommandMessage(
|
|
115
|
+
pi,
|
|
116
|
+
ctx,
|
|
117
|
+
[
|
|
118
|
+
"Harness governance disabled.",
|
|
119
|
+
`Wrote .pi/harness/project.json (enabled=false, updated ${config.updated_at}).`,
|
|
120
|
+
"Workflow slash commands are blocked immediately.",
|
|
121
|
+
"Live TUI surfaces were refreshed.",
|
|
122
|
+
].join("\n"),
|
|
123
|
+
);
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
pi.registerCommand("harness-enabled-status", {
|
|
128
|
+
description: "Show whether harness governance is enabled for this project",
|
|
129
|
+
handler: async (_args, ctx) => {
|
|
130
|
+
showCommandMessage(pi, ctx, formatStatus(process.cwd()));
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Load before other extensions: IPv4-first fetch for *.posthog.com (@posthog/pi uses global fetch).
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { installPostHogFetchPatch } from "
|
|
5
|
+
import { installPostHogFetchPatch } from "../lib/posthog-client.js";
|
|
6
6
|
|
|
7
7
|
installPostHogFetchPatch();
|
|
8
8
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AGT kill switch — arms on harness-abort and repeated policy denies (ADR 0047).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
6
|
+
import { KillSwitch } from "@microsoft/agent-governance-sdk";
|
|
7
|
+
import { isHarnessProjectEnabled } from "../lib/harness-project-config.js";
|
|
8
|
+
import {
|
|
9
|
+
hasHarnessAbortSignal,
|
|
10
|
+
userVisiblePromptSlice,
|
|
11
|
+
} from "../lib/harness-run-context.js";
|
|
12
|
+
|
|
13
|
+
const killSwitch = new KillSwitch({ enabled: true });
|
|
14
|
+
|
|
15
|
+
import { recordHarnessPolicyDeny } from "../lib/agt/kill-switch-state.js";
|
|
16
|
+
|
|
17
|
+
export function getHarnessKillSwitch(): KillSwitch {
|
|
18
|
+
return killSwitch;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function recordHarnessPolicyDenyForKillSwitch(sessionId: string): void {
|
|
22
|
+
const n = recordHarnessPolicyDeny(sessionId);
|
|
23
|
+
if (n >= 5) {
|
|
24
|
+
void killSwitch.kill(sessionId, {
|
|
25
|
+
reason: "Repeated harness policy denials",
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default function agtKillSwitch(pi: ExtensionAPI) {
|
|
31
|
+
if (!isHarnessProjectEnabled()) return;
|
|
32
|
+
|
|
33
|
+
pi.on("before_agent_start", async (event, ctx) => {
|
|
34
|
+
const prompt = userVisiblePromptSlice(event.prompt);
|
|
35
|
+
if (hasHarnessAbortSignal(prompt)) {
|
|
36
|
+
const sessionId = ctx.sessionManager.getSessionId();
|
|
37
|
+
await killSwitch.kill(sessionId, {
|
|
38
|
+
reason: "harness-abort command",
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
pi.on("tool_call", async (_event, ctx) => {
|
|
45
|
+
const sessionId = ctx.sessionManager.getSessionId();
|
|
46
|
+
const history = killSwitch.getHistory();
|
|
47
|
+
const armed = history.some((h) => h.agentId === sessionId);
|
|
48
|
+
if (armed) {
|
|
49
|
+
return {
|
|
50
|
+
block: true,
|
|
51
|
+
reason:
|
|
52
|
+
"agt-kill-switch: harness session halted after abort or repeated policy breaches.",
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return undefined;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AGT PromptDefense heuristics on harness slash commands (ADR 0047).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
6
|
+
import { PromptDefenseEvaluator } from "@microsoft/agent-governance-sdk";
|
|
7
|
+
import { isHarnessProjectEnabled } from "../lib/harness-project-config.js";
|
|
8
|
+
import { userVisiblePromptSlice } from "../lib/harness-run-context.js";
|
|
9
|
+
|
|
10
|
+
const evaluator = new PromptDefenseEvaluator({ minGrade: "D" });
|
|
11
|
+
|
|
12
|
+
export default function agtPromptGuard(pi: ExtensionAPI) {
|
|
13
|
+
if (!isHarnessProjectEnabled()) return;
|
|
14
|
+
|
|
15
|
+
pi.on("before_agent_start", async (event) => {
|
|
16
|
+
const prompt = userVisiblePromptSlice(event.prompt);
|
|
17
|
+
if (!prompt.trim()) return undefined;
|
|
18
|
+
if (!/\/harness-/.test(prompt)) return undefined;
|
|
19
|
+
|
|
20
|
+
const report = evaluator.evaluate(prompt);
|
|
21
|
+
if (report.isBlocking("D")) {
|
|
22
|
+
return {
|
|
23
|
+
message: {
|
|
24
|
+
customType: "harness-policy-violation",
|
|
25
|
+
display: true,
|
|
26
|
+
content: `agt-prompt-guard: prompt defense grade ${report.grade} (${report.score}). Missing defenses: ${report.missing.join(", ") || "see findings"}.`,
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
isHarnessBudgetEnforceOn,
|
|
13
13
|
shouldEmitBlockingBudgetExhausted,
|
|
14
14
|
} from "../lib/harness-budget-enforce.js";
|
|
15
|
+
import { isHarnessProjectEnabled } from "../lib/harness-project-config.js";
|
|
15
16
|
import { getRunIdFromSession } from "../lib/harness-run-context.js";
|
|
16
17
|
|
|
17
18
|
type HarnessPhase = "plan" | "execute" | "evaluate" | "adversary" | "merge";
|
|
@@ -203,6 +204,7 @@ async function emitBudgetEvent(
|
|
|
203
204
|
const debouncedSoftLimit = new Map<string, boolean>();
|
|
204
205
|
|
|
205
206
|
export default function budgetGuard(pi: ExtensionAPI) {
|
|
207
|
+
if (!isHarnessProjectEnabled()) return;
|
|
206
208
|
pi.on("tool_call", async (_event, ctx) => {
|
|
207
209
|
const policy = getPolicyContext(ctx);
|
|
208
210
|
if (policy.phase === null || policy.budgetBypass) return undefined;
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
import type {
|
|
9
9
|
ExtensionAPI,
|
|
10
10
|
ExtensionContext,
|
|
11
|
-
ThemeColor,
|
|
12
11
|
} from "@earendil-works/pi-coding-agent";
|
|
13
12
|
import type { TUI } from "@earendil-works/pi-tui";
|
|
14
13
|
import {
|
|
@@ -17,56 +16,7 @@ import {
|
|
|
17
16
|
truncateToWidth,
|
|
18
17
|
visibleWidth,
|
|
19
18
|
} from "@earendil-works/pi-tui";
|
|
20
|
-
|
|
21
|
-
// ── router decision reader ──────────────────────────────────────────
|
|
22
|
-
|
|
23
|
-
/** Extract last routing decision from model-router session entries. */
|
|
24
|
-
function readRouterDecision(ctx: ExtensionContext): {
|
|
25
|
-
targetProvider: string;
|
|
26
|
-
targetModelId: string;
|
|
27
|
-
thinking: string;
|
|
28
|
-
profile: string;
|
|
29
|
-
enabled: boolean;
|
|
30
|
-
} | null {
|
|
31
|
-
try {
|
|
32
|
-
const entries = ctx.sessionManager.getEntries();
|
|
33
|
-
for (let i = entries.length - 1; i >= 0; i--) {
|
|
34
|
-
const e = entries[i];
|
|
35
|
-
if (
|
|
36
|
-
e.type === "custom" &&
|
|
37
|
-
(e as any).customType === "router-state" &&
|
|
38
|
-
(e as any).data
|
|
39
|
-
) {
|
|
40
|
-
const data = (e as any).data;
|
|
41
|
-
const d = data.lastDecision;
|
|
42
|
-
if (d?.targetProvider && d?.targetModelId) {
|
|
43
|
-
return {
|
|
44
|
-
targetProvider: d.targetProvider,
|
|
45
|
-
targetModelId: d.targetModelId,
|
|
46
|
-
thinking: d.thinking,
|
|
47
|
-
profile: data.selectedProfile ?? d.profile,
|
|
48
|
-
enabled: data.enabled ?? true,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
} catch {
|
|
54
|
-
// session not ready
|
|
55
|
-
}
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// ── profile colors ────────────────────────────────────────────────
|
|
60
|
-
|
|
61
|
-
const PROFILE_COLORS: Record<string, ThemeColor> = {
|
|
62
|
-
auto: "accent",
|
|
63
|
-
cheap: "success",
|
|
64
|
-
deep: "toolTitle",
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
function profileColor(profile: string): ThemeColor {
|
|
68
|
-
return PROFILE_COLORS[profile] ?? "muted";
|
|
69
|
-
}
|
|
19
|
+
import { getLSPService } from "../lib/harness-lens/clients/lsp/index.js";
|
|
70
20
|
|
|
71
21
|
// ── token formatting ──────────────────────────────────────────────
|
|
72
22
|
|
|
@@ -145,20 +95,6 @@ function modelInfo(ctx: ExtensionContext): ModelInfo {
|
|
|
145
95
|
const m = ctx.model;
|
|
146
96
|
if (!m) return { id: "no-model", provider: "unknown", reasoning: false };
|
|
147
97
|
|
|
148
|
-
// Router provider — extract actual model from routing decision
|
|
149
|
-
if (m.provider === "router") {
|
|
150
|
-
const decision = readRouterDecision(ctx);
|
|
151
|
-
if (decision) {
|
|
152
|
-
return {
|
|
153
|
-
id: decision.targetModelId,
|
|
154
|
-
provider: decision.targetProvider,
|
|
155
|
-
reasoning: true,
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
// No decision yet — show profile name so user knows router is active
|
|
159
|
-
return { id: m.id, provider: "router", reasoning: m.reasoning };
|
|
160
|
-
}
|
|
161
|
-
|
|
162
98
|
return { id: m.id, provider: m.provider, reasoning: m.reasoning };
|
|
163
99
|
}
|
|
164
100
|
|
|
@@ -190,8 +126,17 @@ function pathLabel(
|
|
|
190
126
|
|
|
191
127
|
// ── extension ─────────────────────────────────────────────────────
|
|
192
128
|
|
|
129
|
+
function lspAlive(): boolean {
|
|
130
|
+
try {
|
|
131
|
+
return getLSPService().getAliveClientCount() > 0;
|
|
132
|
+
} catch {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
193
137
|
export default function customFooter(pi: ExtensionAPI) {
|
|
194
138
|
let unsubBranch: (() => void) | null = null;
|
|
139
|
+
let lspInvalidateTimer: ReturnType<typeof setInterval> | null = null;
|
|
195
140
|
|
|
196
141
|
const state: {
|
|
197
142
|
tui: TUI | null;
|
|
@@ -204,8 +149,6 @@ export default function customFooter(pi: ExtensionAPI) {
|
|
|
204
149
|
modelProvider: string;
|
|
205
150
|
modelReasoning: boolean;
|
|
206
151
|
thinkingLevel: string | null;
|
|
207
|
-
routerProfile: string | null;
|
|
208
|
-
routerActive: boolean;
|
|
209
152
|
branch: string | null;
|
|
210
153
|
} = {
|
|
211
154
|
tui: null,
|
|
@@ -218,8 +161,6 @@ export default function customFooter(pi: ExtensionAPI) {
|
|
|
218
161
|
modelProvider: "…",
|
|
219
162
|
modelReasoning: false,
|
|
220
163
|
thinkingLevel: null,
|
|
221
|
-
routerProfile: null,
|
|
222
|
-
routerActive: false,
|
|
223
164
|
branch: null,
|
|
224
165
|
};
|
|
225
166
|
|
|
@@ -235,17 +176,7 @@ export default function customFooter(pi: ExtensionAPI) {
|
|
|
235
176
|
state.modelProvider = mi.provider;
|
|
236
177
|
state.modelReasoning = mi.reasoning;
|
|
237
178
|
|
|
238
|
-
|
|
239
|
-
if (ctx.model?.provider === "router") {
|
|
240
|
-
const routerDecision = readRouterDecision(ctx);
|
|
241
|
-
state.thinkingLevel = routerDecision?.thinking ?? pi.getThinkingLevel();
|
|
242
|
-
state.routerProfile = routerDecision?.profile ?? ctx.model?.id;
|
|
243
|
-
state.routerActive = routerDecision?.enabled ?? true;
|
|
244
|
-
} else {
|
|
245
|
-
state.thinkingLevel = pi.getThinkingLevel();
|
|
246
|
-
state.routerProfile = null;
|
|
247
|
-
state.routerActive = false;
|
|
248
|
-
}
|
|
179
|
+
state.thinkingLevel = pi.getThinkingLevel();
|
|
249
180
|
}
|
|
250
181
|
|
|
251
182
|
pi.on("session_start", (_event, ctx) => {
|
|
@@ -258,6 +189,10 @@ export default function customFooter(pi: ExtensionAPI) {
|
|
|
258
189
|
unsubBranch();
|
|
259
190
|
unsubBranch = null;
|
|
260
191
|
}
|
|
192
|
+
if (lspInvalidateTimer) {
|
|
193
|
+
clearInterval(lspInvalidateTimer);
|
|
194
|
+
lspInvalidateTimer = null;
|
|
195
|
+
}
|
|
261
196
|
|
|
262
197
|
state.tui = tui;
|
|
263
198
|
state.branch = footerData.getGitBranch();
|
|
@@ -274,12 +209,19 @@ export default function customFooter(pi: ExtensionAPI) {
|
|
|
274
209
|
state.box = box;
|
|
275
210
|
state.textLine = textLine;
|
|
276
211
|
|
|
212
|
+
lspInvalidateTimer = setInterval(invalidate, 2000);
|
|
213
|
+
lspInvalidateTimer.unref?.();
|
|
214
|
+
|
|
277
215
|
return {
|
|
278
216
|
dispose() {
|
|
279
217
|
if (unsubBranch) {
|
|
280
218
|
unsubBranch();
|
|
281
219
|
unsubBranch = null;
|
|
282
220
|
}
|
|
221
|
+
if (lspInvalidateTimer) {
|
|
222
|
+
clearInterval(lspInvalidateTimer);
|
|
223
|
+
lspInvalidateTimer = null;
|
|
224
|
+
}
|
|
283
225
|
state.tui = null;
|
|
284
226
|
state.box = null;
|
|
285
227
|
state.textLine = null;
|
|
@@ -328,59 +270,39 @@ export default function customFooter(pi: ExtensionAPI) {
|
|
|
328
270
|
const tl = thinkingLabel(state.thinkingLevel, state.modelReasoning);
|
|
329
271
|
const modelDisplay = tl ? `${state.modelId} ${tl}` : state.modelId;
|
|
330
272
|
|
|
331
|
-
|
|
332
|
-
const
|
|
333
|
-
?
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
state.routerProfile ?? "router",
|
|
338
|
-
);
|
|
339
|
-
const thinkingColorFn = theme.getThinkingBorderColor(
|
|
340
|
-
(state.thinkingLevel as any) ?? "medium",
|
|
341
|
-
);
|
|
342
|
-
const modelStr = thinkingColorFn(modelDisplay);
|
|
343
|
-
return `${profileStr} • ${modelStr}`;
|
|
344
|
-
})()
|
|
345
|
-
: `${state.modelProvider} • ${modelDisplay}`;
|
|
273
|
+
const lspActive = lspAlive();
|
|
274
|
+
const lspIndicator = theme.fg(
|
|
275
|
+
lspActive ? "success" : "error",
|
|
276
|
+
lspActive ? "LSP✓" : "LSP×",
|
|
277
|
+
);
|
|
278
|
+
const rightStr = `${state.modelProvider} • ${modelDisplay}`;
|
|
346
279
|
|
|
347
280
|
// ── compose single line ──
|
|
348
281
|
const colLeft = leftStr;
|
|
349
|
-
const
|
|
282
|
+
const contextDisplay = `${lspIndicator} ${barFull}`;
|
|
283
|
+
const finalRight = dim(rightStr);
|
|
350
284
|
const lw = visibleWidth(colLeft);
|
|
351
285
|
const rw = visibleWidth(finalRight);
|
|
352
|
-
const
|
|
286
|
+
const cw = visibleWidth(contextDisplay);
|
|
353
287
|
const gap = 2;
|
|
354
288
|
|
|
355
|
-
if (lw + gap +
|
|
356
|
-
const pad = innerW - lw - gap -
|
|
289
|
+
if (lw + gap + cw + gap + rw <= innerW) {
|
|
290
|
+
const pad = innerW - lw - gap - cw - gap - rw;
|
|
357
291
|
const line =
|
|
358
292
|
colLeft +
|
|
359
293
|
" ".repeat(gap + pad) +
|
|
360
|
-
|
|
294
|
+
contextDisplay +
|
|
361
295
|
" ".repeat(gap) +
|
|
362
296
|
finalRight;
|
|
363
297
|
textLine.setText(truncateToWidth(line, innerW));
|
|
364
298
|
} else {
|
|
365
|
-
// Priority: keep bar visible, keep left (cwd) intact, truncate modelId first
|
|
299
|
+
// Priority: keep LSP + context bar visible, keep left (cwd) intact, truncate modelId first
|
|
366
300
|
const tlNow = thinkingLabel(
|
|
367
301
|
state.thinkingLevel,
|
|
368
302
|
state.modelReasoning,
|
|
369
303
|
);
|
|
370
|
-
const thinkingColorFn = theme.getThinkingBorderColor(
|
|
371
|
-
(state.thinkingLevel as any) ?? "medium",
|
|
372
|
-
);
|
|
373
304
|
const buildRight = (mid: string) => {
|
|
374
305
|
const modelPart = tlNow ? `${mid} ${tlNow}` : mid;
|
|
375
|
-
if (state.routerActive) {
|
|
376
|
-
const pColor = profileColor(state.routerProfile ?? "router");
|
|
377
|
-
const profileStr = theme.fg(
|
|
378
|
-
pColor,
|
|
379
|
-
state.routerProfile ?? "router",
|
|
380
|
-
);
|
|
381
|
-
const modelStr = thinkingColorFn(modelPart);
|
|
382
|
-
return `${profileStr} • ${modelStr}`;
|
|
383
|
-
}
|
|
384
306
|
const parts: string[] = [state.modelProvider];
|
|
385
307
|
if (modelPart) parts.push(modelPart);
|
|
386
308
|
return dim(parts.join(" • "));
|
|
@@ -392,25 +314,25 @@ export default function customFooter(pi: ExtensionAPI) {
|
|
|
392
314
|
|
|
393
315
|
while (
|
|
394
316
|
truncMid.length > 0 &&
|
|
395
|
-
lw + gap +
|
|
317
|
+
lw + gap + cw + gap + rwNow > innerW
|
|
396
318
|
) {
|
|
397
319
|
truncMid = truncMid.slice(0, -1);
|
|
398
320
|
dimR = buildRight(truncMid);
|
|
399
321
|
rwNow = visibleWidth(dimR);
|
|
400
322
|
}
|
|
401
323
|
|
|
402
|
-
if (lw + gap +
|
|
403
|
-
const pad = innerW - lw - gap -
|
|
324
|
+
if (lw + gap + cw + gap + rwNow <= innerW) {
|
|
325
|
+
const pad = innerW - lw - gap - cw - gap - rwNow;
|
|
404
326
|
const line =
|
|
405
327
|
colLeft +
|
|
406
328
|
" ".repeat(gap + pad) +
|
|
407
|
-
|
|
329
|
+
contextDisplay +
|
|
408
330
|
" ".repeat(gap) +
|
|
409
331
|
dimR;
|
|
410
332
|
textLine.setText(truncateToWidth(line, innerW));
|
|
411
333
|
} else {
|
|
412
334
|
// ModelId gone, still overflows: truncate leftStr
|
|
413
|
-
const avail = innerW -
|
|
335
|
+
const avail = innerW - cw - rwNow - gap - gap;
|
|
414
336
|
if (avail < 1) {
|
|
415
337
|
textLine.setText(truncateToWidth(dimR, innerW));
|
|
416
338
|
} else {
|
|
@@ -418,7 +340,7 @@ export default function customFooter(pi: ExtensionAPI) {
|
|
|
418
340
|
const line =
|
|
419
341
|
truncLeft +
|
|
420
342
|
" ".repeat(gap) +
|
|
421
|
-
|
|
343
|
+
contextDisplay +
|
|
422
344
|
" ".repeat(gap) +
|
|
423
345
|
dimR;
|
|
424
346
|
textLine.setText(truncateToWidth(line, innerW));
|
|
@@ -442,32 +364,11 @@ export default function customFooter(pi: ExtensionAPI) {
|
|
|
442
364
|
});
|
|
443
365
|
|
|
444
366
|
// Track model changes
|
|
445
|
-
pi.on("model_select", (event
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
state.modelProvider = routerDecision.targetProvider;
|
|
451
|
-
state.modelReasoning = true;
|
|
452
|
-
state.thinkingLevel = routerDecision.thinking;
|
|
453
|
-
state.routerProfile = routerDecision.profile;
|
|
454
|
-
state.routerActive = routerDecision.enabled;
|
|
455
|
-
} else {
|
|
456
|
-
state.modelId = event.model.id ?? "…";
|
|
457
|
-
state.modelProvider = "router";
|
|
458
|
-
state.modelReasoning = event.model?.reasoning ?? false;
|
|
459
|
-
state.thinkingLevel = pi.getThinkingLevel();
|
|
460
|
-
state.routerProfile = event.model.id;
|
|
461
|
-
state.routerActive = true;
|
|
462
|
-
}
|
|
463
|
-
} else {
|
|
464
|
-
state.modelId = event.model?.id ?? "…";
|
|
465
|
-
state.modelProvider = event.model?.provider ?? "…";
|
|
466
|
-
state.modelReasoning = event.model?.reasoning ?? false;
|
|
467
|
-
state.thinkingLevel = pi.getThinkingLevel();
|
|
468
|
-
state.routerProfile = null;
|
|
469
|
-
state.routerActive = false;
|
|
470
|
-
}
|
|
367
|
+
pi.on("model_select", (event) => {
|
|
368
|
+
state.modelId = event.model?.id ?? "…";
|
|
369
|
+
state.modelProvider = event.model?.provider ?? "…";
|
|
370
|
+
state.modelReasoning = event.model?.reasoning ?? false;
|
|
371
|
+
state.thinkingLevel = pi.getThinkingLevel();
|
|
471
372
|
invalidate();
|
|
472
373
|
});
|
|
473
374
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
10
10
|
import { truncateToWidth } from "@earendil-works/pi-tui";
|
|
11
11
|
import * as JimpModule from "jimp";
|
|
12
|
-
import { resolveHarnessAsset } from "
|
|
12
|
+
import { resolveHarnessAsset } from "../lib/harness-paths.js";
|
|
13
13
|
|
|
14
14
|
/** Shipped next to this extension in the npm package — not the host project's .pi dir. */
|
|
15
15
|
const imagePath = resolveHarnessAsset(
|
|
@@ -15,7 +15,7 @@ import type {
|
|
|
15
15
|
ExtensionAPI,
|
|
16
16
|
} from "@earendil-works/pi-coding-agent";
|
|
17
17
|
import { formatSkillsForPrompt } from "@earendil-works/pi-coding-agent";
|
|
18
|
-
import { resolveHarnessAsset } from "
|
|
18
|
+
import { resolveHarnessAsset } from "../lib/harness-paths.js";
|
|
19
19
|
|
|
20
20
|
// @ts-expect-error pi extensions run as ESM
|
|
21
21
|
const MODULE_URL = import.meta.url;
|
|
@@ -6,19 +6,20 @@
|
|
|
6
6
|
|
|
7
7
|
import { join } from "node:path";
|
|
8
8
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
9
|
-
import { getRunIdFromSession } from "../lib/harness-run-context.js";
|
|
10
9
|
import {
|
|
11
10
|
acceptDebateRound,
|
|
12
11
|
finalizeDebateConsensus,
|
|
13
12
|
openDebateBus,
|
|
14
13
|
parseRoundEnvelope,
|
|
15
|
-
} from "
|
|
14
|
+
} from "../lib/debate-bus-core.js";
|
|
16
15
|
import {
|
|
17
16
|
getDebateState,
|
|
18
17
|
restoreDebateStateFromEntry,
|
|
19
|
-
} from "
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
18
|
+
} from "../lib/debate-bus-state.js";
|
|
19
|
+
import { isHarnessProjectEnabled } from "../lib/harness-project-config.js";
|
|
20
|
+
import { getRunIdFromSession } from "../lib/harness-run-context.js";
|
|
21
|
+
import { normalizePlanDebateId } from "../lib/plan-debate-id.js";
|
|
22
|
+
import { initPlanMessenger } from "../lib/plan-messenger.js";
|
|
22
23
|
|
|
23
24
|
function getRunId(ctx: {
|
|
24
25
|
sessionManager: { getEntries(): unknown[]; getSessionId(): string };
|
|
@@ -32,6 +33,7 @@ function getRunId(ctx: {
|
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
export default function debateOrchestrator(pi: ExtensionAPI) {
|
|
36
|
+
if (!isHarnessProjectEnabled()) return;
|
|
35
37
|
const hooks = {
|
|
36
38
|
appendEntry: (customType: string, data: unknown) =>
|
|
37
39
|
pi.appendEntry(customType, data),
|
|
@@ -4,27 +4,27 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
7
|
-
import { runAskDialog } from "
|
|
8
|
-
import { runAskFallback } from "
|
|
9
|
-
import { renderAskCall, renderAskResult } from "
|
|
7
|
+
import { runAskDialog } from "../lib/ask-user/dialog.js";
|
|
8
|
+
import { runAskFallback } from "../lib/ask-user/fallback.js";
|
|
9
|
+
import { renderAskCall, renderAskResult } from "../lib/ask-user/render.js";
|
|
10
10
|
import {
|
|
11
11
|
AskUserParamsSchema,
|
|
12
12
|
PROMPT_GUIDELINES,
|
|
13
13
|
PROMPT_SNIPPET,
|
|
14
|
-
} from "
|
|
15
|
-
import type { AskUserParams, DialogResult } from "
|
|
14
|
+
} from "../lib/ask-user/schema.js";
|
|
15
|
+
import type { AskUserParams, DialogResult } from "../lib/ask-user/types.js";
|
|
16
16
|
import {
|
|
17
17
|
formatResultText,
|
|
18
18
|
toToolDetails,
|
|
19
19
|
validateAskParams,
|
|
20
|
-
} from "
|
|
21
|
-
import {
|
|
20
|
+
} from "../lib/ask-user/validate.js";
|
|
21
|
+
import { claimHarnessGovernanceLoad } from "../lib/extension-load-guard.js";
|
|
22
22
|
|
|
23
23
|
// @ts-expect-error pi extensions run as ESM
|
|
24
24
|
const MODULE_URL = import.meta.url;
|
|
25
25
|
|
|
26
26
|
export default function harnessAskUser(pi: ExtensionAPI) {
|
|
27
|
-
if (!
|
|
27
|
+
if (!claimHarnessGovernanceLoad("harness-ask-user", MODULE_URL)) return;
|
|
28
28
|
pi.registerTool({
|
|
29
29
|
name: "ask_user",
|
|
30
30
|
label: "Ask User",
|