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
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
|
|
4
|
+
const LATENCY_LOG_DIR = path.join(process.cwd(), ".pi", "harness", ".lens");
|
|
5
|
+
const LATENCY_LOG_FILE = path.join(LATENCY_LOG_DIR, "latency.log");
|
|
6
|
+
|
|
7
|
+
try {
|
|
8
|
+
if (!fs.existsSync(LATENCY_LOG_DIR)) {
|
|
9
|
+
fs.mkdirSync(LATENCY_LOG_DIR, { recursive: true });
|
|
10
|
+
}
|
|
11
|
+
} catch {}
|
|
12
|
+
|
|
13
|
+
export interface LatencyEntry {
|
|
14
|
+
type: "runner" | "tool_result" | "phase";
|
|
15
|
+
/** ISO timestamp when this entry was written (= finish time for runners) */
|
|
16
|
+
ts?: string;
|
|
17
|
+
/** ISO timestamp when the runner/phase started — diff with ts = durationMs */
|
|
18
|
+
startedAt?: string;
|
|
19
|
+
toolName?: string;
|
|
20
|
+
filePath: string;
|
|
21
|
+
fullPath?: string;
|
|
22
|
+
phase?: string;
|
|
23
|
+
durationMs: number;
|
|
24
|
+
totalDurationMs?: number;
|
|
25
|
+
result?: string;
|
|
26
|
+
runnerId?: string;
|
|
27
|
+
status?: string;
|
|
28
|
+
diagnosticCount?: number;
|
|
29
|
+
semantic?: string;
|
|
30
|
+
/** Per-diagnostic summary when a runner produces findings — aids root-cause analysis */
|
|
31
|
+
diagnostics?: Array<{
|
|
32
|
+
rule?: string;
|
|
33
|
+
message: string;
|
|
34
|
+
line?: number;
|
|
35
|
+
semantic?: string;
|
|
36
|
+
}>;
|
|
37
|
+
/** For dispatch_complete: actual wall-clock time (groups run in parallel) */
|
|
38
|
+
wallClockMs?: number;
|
|
39
|
+
/** For dispatch_complete: sum of all individual runner durationMs */
|
|
40
|
+
sumMs?: number;
|
|
41
|
+
/** wallClockMs - sumMs ≥ 0 means parallelism saved this many ms */
|
|
42
|
+
parallelGainMs?: number;
|
|
43
|
+
metadata?: Record<string, unknown>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function logLatency(entry: LatencyEntry): void {
|
|
47
|
+
if (
|
|
48
|
+
process.env.PI_LENS_TEST_MODE === "1" ||
|
|
49
|
+
(process.env.VITEST && process.env.PI_LENS_TEST_MODE !== "0")
|
|
50
|
+
) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const line = `${JSON.stringify({ ts: new Date().toISOString(), ...entry })}\n`;
|
|
54
|
+
try {
|
|
55
|
+
fs.appendFileSync(LATENCY_LOG_FILE, line);
|
|
56
|
+
} catch {}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function getLatencyLogPath(): string {
|
|
60
|
+
return LATENCY_LOG_FILE;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function readLatencyLog(limit = 100): LatencyEntry[] {
|
|
64
|
+
try {
|
|
65
|
+
const content = fs.readFileSync(LATENCY_LOG_FILE, "utf-8");
|
|
66
|
+
const lines = content.trim().split(/\r?\n/).filter(Boolean);
|
|
67
|
+
return lines
|
|
68
|
+
.slice(-limit)
|
|
69
|
+
.map((line) => JSON.parse(line))
|
|
70
|
+
.reverse();
|
|
71
|
+
} catch {
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function clearLatencyLog(): void {
|
|
77
|
+
try {
|
|
78
|
+
fs.writeFileSync(LATENCY_LOG_FILE, "");
|
|
79
|
+
} catch {}
|
|
80
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
|
|
3
|
+
export interface PiLensGlobalConfig {
|
|
4
|
+
noLens?: boolean;
|
|
5
|
+
noLsp?: boolean;
|
|
6
|
+
noAutoformat?: boolean;
|
|
7
|
+
immediateFormat?: boolean;
|
|
8
|
+
lensGuard?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function loadPiLensGlobalConfig(): PiLensGlobalConfig {
|
|
12
|
+
const configPath = process.env.PI_LENS_CONFIG_PATH;
|
|
13
|
+
if (!configPath) return {};
|
|
14
|
+
try {
|
|
15
|
+
const raw = fs.readFileSync(configPath, "utf-8");
|
|
16
|
+
return JSON.parse(raw) as PiLensGlobalConfig;
|
|
17
|
+
} catch {
|
|
18
|
+
return {};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function resolvePiLensFlag(
|
|
23
|
+
name: string,
|
|
24
|
+
getFlag: (name: string) => boolean | string | undefined,
|
|
25
|
+
global: PiLensGlobalConfig,
|
|
26
|
+
): boolean | string | undefined {
|
|
27
|
+
const fromCli = getFlag(name);
|
|
28
|
+
if (fromCli !== undefined) return fromCli;
|
|
29
|
+
switch (name) {
|
|
30
|
+
case "no-lens":
|
|
31
|
+
return global.noLens;
|
|
32
|
+
case "no-lsp":
|
|
33
|
+
return global.noLsp;
|
|
34
|
+
case "no-autoformat":
|
|
35
|
+
return global.noAutoformat;
|
|
36
|
+
case "immediate-format":
|
|
37
|
+
return global.immediateFormat;
|
|
38
|
+
case "lens-guard":
|
|
39
|
+
return global.lensGuard;
|
|
40
|
+
default:
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
export interface LensDiagnostic {
|
|
2
|
+
id?: string;
|
|
3
|
+
message: string;
|
|
4
|
+
filePath?: string;
|
|
5
|
+
line?: number;
|
|
6
|
+
column?: number;
|
|
7
|
+
severity?: string;
|
|
8
|
+
semantic?: string;
|
|
9
|
+
tool?: string;
|
|
10
|
+
rule?: string;
|
|
11
|
+
defectClass?: string;
|
|
12
|
+
matchedText?: string;
|
|
13
|
+
fixSuggestion?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const LENS_EVENT_VERSION = 1;
|
|
17
|
+
|
|
18
|
+
export const LENS_EVENT_NAMES = {
|
|
19
|
+
analysisComplete: "pi-lens/analysis-complete",
|
|
20
|
+
findings: "pi-lens/findings",
|
|
21
|
+
turnFindings: "pi-lens/turn-findings",
|
|
22
|
+
} as const;
|
|
23
|
+
|
|
24
|
+
type LensEventName = (typeof LENS_EVENT_NAMES)[keyof typeof LENS_EVENT_NAMES];
|
|
25
|
+
|
|
26
|
+
type LensEventBus = {
|
|
27
|
+
emit?: (event: string, payload: unknown) => void;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export interface LensTelemetryPayload {
|
|
31
|
+
model: string;
|
|
32
|
+
sessionId: string;
|
|
33
|
+
turnIndex: number;
|
|
34
|
+
writeIndex: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface LensAnalysisPayload extends LensTelemetryPayload {
|
|
38
|
+
version: typeof LENS_EVENT_VERSION;
|
|
39
|
+
source: "pi-lens";
|
|
40
|
+
timestamp: string;
|
|
41
|
+
cwd: string;
|
|
42
|
+
filePath: string;
|
|
43
|
+
toolName: string;
|
|
44
|
+
diagnostics: LensDiagnostic[];
|
|
45
|
+
blockers: LensDiagnostic[];
|
|
46
|
+
warnings: LensDiagnostic[];
|
|
47
|
+
fixed: LensDiagnostic[];
|
|
48
|
+
resolvedCount: number;
|
|
49
|
+
hasBlockers: boolean;
|
|
50
|
+
fileModified: boolean;
|
|
51
|
+
changedFiles: string[];
|
|
52
|
+
durationMs: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface LensTurnFindingsPayload {
|
|
56
|
+
version: typeof LENS_EVENT_VERSION;
|
|
57
|
+
source: "pi-lens";
|
|
58
|
+
timestamp: string;
|
|
59
|
+
cwd: string;
|
|
60
|
+
filePaths: string[];
|
|
61
|
+
sessionId: string;
|
|
62
|
+
turnIndex: number;
|
|
63
|
+
blockerSections: number;
|
|
64
|
+
advisorySections: number;
|
|
65
|
+
content: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let lensEventBus: LensEventBus | undefined;
|
|
69
|
+
|
|
70
|
+
export function initLensEvents(pi: { events?: LensEventBus }): void {
|
|
71
|
+
lensEventBus = pi.events;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function truncateText(
|
|
75
|
+
value: string | undefined,
|
|
76
|
+
maxChars: number,
|
|
77
|
+
): string | undefined {
|
|
78
|
+
if (value === undefined) return undefined;
|
|
79
|
+
if (value.length <= maxChars) return value;
|
|
80
|
+
return `${value.slice(0, maxChars)}…`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function normalizeDiagnostic(diagnostic: LensDiagnostic): LensDiagnostic {
|
|
84
|
+
return {
|
|
85
|
+
...diagnostic,
|
|
86
|
+
message: truncateText(diagnostic.message, 1_000) ?? "",
|
|
87
|
+
matchedText: truncateText(diagnostic.matchedText, 500),
|
|
88
|
+
fixSuggestion: truncateText(diagnostic.fixSuggestion, 500),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function normalizeDiagnostics(diagnostics: LensDiagnostic[]): LensDiagnostic[] {
|
|
93
|
+
return diagnostics.map(normalizeDiagnostic);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function emitLensEvent(eventName: LensEventName, payload: unknown): void {
|
|
97
|
+
const emit = lensEventBus?.emit;
|
|
98
|
+
if (!emit) return;
|
|
99
|
+
|
|
100
|
+
setImmediate(() => {
|
|
101
|
+
try {
|
|
102
|
+
emit.call(lensEventBus, eventName, payload);
|
|
103
|
+
} catch {
|
|
104
|
+
// Inter-extension events are observational. A listener must never break
|
|
105
|
+
// the pi-lens hook path or delay agent progress with error handling noise.
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function emitLensAnalysisComplete(
|
|
111
|
+
payload: Omit<
|
|
112
|
+
LensAnalysisPayload,
|
|
113
|
+
| "version"
|
|
114
|
+
| "source"
|
|
115
|
+
| "timestamp"
|
|
116
|
+
| "diagnostics"
|
|
117
|
+
| "blockers"
|
|
118
|
+
| "warnings"
|
|
119
|
+
| "fixed"
|
|
120
|
+
> & {
|
|
121
|
+
diagnostics: LensDiagnostic[];
|
|
122
|
+
blockers: LensDiagnostic[];
|
|
123
|
+
warnings: LensDiagnostic[];
|
|
124
|
+
fixed: LensDiagnostic[];
|
|
125
|
+
},
|
|
126
|
+
): void {
|
|
127
|
+
const normalized: LensAnalysisPayload = {
|
|
128
|
+
version: LENS_EVENT_VERSION,
|
|
129
|
+
source: "pi-lens",
|
|
130
|
+
timestamp: new Date().toISOString(),
|
|
131
|
+
...payload,
|
|
132
|
+
diagnostics: normalizeDiagnostics(payload.diagnostics),
|
|
133
|
+
blockers: normalizeDiagnostics(payload.blockers),
|
|
134
|
+
warnings: normalizeDiagnostics(payload.warnings),
|
|
135
|
+
fixed: normalizeDiagnostics(payload.fixed),
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
emitLensEvent(LENS_EVENT_NAMES.analysisComplete, normalized);
|
|
139
|
+
if (
|
|
140
|
+
normalized.diagnostics.length > 0 ||
|
|
141
|
+
normalized.blockers.length > 0 ||
|
|
142
|
+
normalized.warnings.length > 0 ||
|
|
143
|
+
normalized.fixed.length > 0
|
|
144
|
+
) {
|
|
145
|
+
emitLensEvent(LENS_EVENT_NAMES.findings, normalized);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function emitLensTurnFindings(
|
|
150
|
+
payload: Omit<
|
|
151
|
+
LensTurnFindingsPayload,
|
|
152
|
+
"version" | "source" | "timestamp" | "content"
|
|
153
|
+
> & {
|
|
154
|
+
content: string;
|
|
155
|
+
},
|
|
156
|
+
): void {
|
|
157
|
+
emitLensEvent(LENS_EVENT_NAMES.turnFindings, {
|
|
158
|
+
version: LENS_EVENT_VERSION,
|
|
159
|
+
source: "pi-lens",
|
|
160
|
+
timestamp: new Date().toISOString(),
|
|
161
|
+
...payload,
|
|
162
|
+
content: truncateText(payload.content, 8_000) ?? "",
|
|
163
|
+
} satisfies LensTurnFindingsPayload);
|
|
164
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diagnostic Aggregation Utilities for pi-lens LSP
|
|
3
|
+
*
|
|
4
|
+
* Provides result-aware racing for multi-client diagnostic collection.
|
|
5
|
+
* Replaces the simple Promise.race + grace window pattern with one that
|
|
6
|
+
* only fires the grace window when a client actually returned diagnostics.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Race a set of promises to completion, resolving as soon as the
|
|
11
|
+
* `shouldComplete` predicate is satisfied by the accumulated results.
|
|
12
|
+
*
|
|
13
|
+
* Key difference from Promise.race: Promise.race resolves when ANY promise
|
|
14
|
+
* settles (even with an empty/useless result). raceToCompletion only resolves
|
|
15
|
+
* early when results meet a quality threshold, optionally with a grace window
|
|
16
|
+
* to let more results accumulate.
|
|
17
|
+
*
|
|
18
|
+
* @param promises - Array of promises producing results
|
|
19
|
+
* @param shouldComplete - Called after each settled promise with all results
|
|
20
|
+
* accumulated so far. Return true to trigger early completion.
|
|
21
|
+
* @param options.timeoutMs - Hard deadline; after this, resolve with whatever is ready
|
|
22
|
+
* @param options.graceMs - After shouldComplete returns true, wait this many ms
|
|
23
|
+
* for additional results before finalizing. 0 = finalize immediately.
|
|
24
|
+
*/
|
|
25
|
+
export async function raceToCompletion<T>(
|
|
26
|
+
promises: Promise<T>[],
|
|
27
|
+
shouldComplete: (results: T[]) => boolean,
|
|
28
|
+
options: { timeoutMs: number; graceMs?: number } = { timeoutMs: 1500 },
|
|
29
|
+
): Promise<T[]> {
|
|
30
|
+
const results: (T | undefined)[] = new Array(promises.length).fill(undefined);
|
|
31
|
+
let graceTimer: ReturnType<typeof setTimeout> | undefined;
|
|
32
|
+
let completed = false;
|
|
33
|
+
let remaining = promises.length;
|
|
34
|
+
|
|
35
|
+
return new Promise((resolve) => {
|
|
36
|
+
const timeout = setTimeout(() => {
|
|
37
|
+
completed = true;
|
|
38
|
+
if (graceTimer) clearTimeout(graceTimer);
|
|
39
|
+
resolve(results.filter((r): r is T => r !== undefined));
|
|
40
|
+
}, options.timeoutMs);
|
|
41
|
+
|
|
42
|
+
const finalize = () => {
|
|
43
|
+
if (completed) return;
|
|
44
|
+
completed = true;
|
|
45
|
+
clearTimeout(timeout);
|
|
46
|
+
if (graceTimer) clearTimeout(graceTimer);
|
|
47
|
+
resolve(results.filter((r): r is T => r !== undefined));
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const check = () => {
|
|
51
|
+
if (completed) return;
|
|
52
|
+
|
|
53
|
+
if (remaining === 0) {
|
|
54
|
+
finalize();
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const collected = results.filter((r): r is T => r !== undefined);
|
|
59
|
+
if (shouldComplete(collected)) {
|
|
60
|
+
if (
|
|
61
|
+
options.graceMs !== undefined &&
|
|
62
|
+
options.graceMs > 0 &&
|
|
63
|
+
!graceTimer
|
|
64
|
+
) {
|
|
65
|
+
// Start grace window — more results may arrive
|
|
66
|
+
graceTimer = setTimeout(() => finalize(), options.graceMs);
|
|
67
|
+
} else {
|
|
68
|
+
finalize();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
for (let i = 0; i < promises.length; i++) {
|
|
74
|
+
const index = i;
|
|
75
|
+
promises[i]
|
|
76
|
+
.then((result) => {
|
|
77
|
+
if (!completed) {
|
|
78
|
+
results[index] = result;
|
|
79
|
+
remaining--;
|
|
80
|
+
check();
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
.catch(() => {
|
|
84
|
+
if (!completed) {
|
|
85
|
+
remaining--;
|
|
86
|
+
check();
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|