@piagent/platform 1.5.5 → 1.6.1
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/CHANGELOG.md +166 -0
- package/README.md +25 -21
- package/README.vi.md +34 -5
- package/adapters/web-frontend/profile.json +2 -4
- package/architecture/layers.json +18 -3
- package/benchmarks/deep-logic-v1/SPECIALIST_PROTOCOL.vi.md +122 -0
- package/benchmarks/deep-logic-v1/grade.mjs +272 -10
- package/benchmarks/deep-logic-v1/project/apps/admin/src/billing-summary.js +3 -0
- package/benchmarks/deep-logic-v1/project/benchmark-contract/public-smoke.test.js +166 -0
- package/benchmarks/deep-logic-v1/project/package.json +1 -1
- package/benchmarks/deep-logic-v1/project/packages/billing/src/close-period.js +3 -0
- package/benchmarks/deep-logic-v1/project/packages/billing/src/plan-timeline.js +3 -0
- package/benchmarks/deep-logic-v1/project/test/smoke.test.js +7 -1
- package/benchmarks/deep-logic-v1/prompts/budgeted-context-graph.md +2 -0
- package/benchmarks/deep-logic-v1/prompts/fair-dependency-scheduler.md +2 -0
- package/benchmarks/deep-logic-v1/prompts/layered-policy-resolution.md +2 -0
- package/benchmarks/deep-logic-v1/prompts/resumable-stream-assembly.md +3 -1
- package/benchmarks/deep-logic-v1/prompts/revision-event-reconciliation.md +2 -0
- package/benchmarks/deep-logic-v1/prompts/temporal-usage-billing-close.md +123 -0
- package/benchmarks/deep-logic-v1/prompts/transactional-config-merge.md +2 -0
- package/benchmarks/deep-logic-v1/suite.json +51 -3
- package/benchmarks/deep-logic-v1/variant.mjs +22 -1
- package/benchmarks/production-v1/spend-control.v1.json +92 -0
- package/benchmarks/production-v1/suite.json +46 -3
- package/catalog/capabilities.json +18 -18
- package/docs/authority-manifest.md +1 -1
- package/docs/auto-delegation-policy.md +38 -73
- package/docs/command-reference-vietnamese.md +27 -35
- package/docs/context-engine.md +12 -4
- package/docs/context-window-policy.md +37 -1
- package/docs/distribution-standard.md +7 -7
- package/docs/en/architecture.md +27 -13
- package/docs/languages.json +4 -4
- package/docs/model-options.md +8 -5
- package/docs/operator-manual-vietnamese.md +27 -45
- package/docs/project-adapters.md +2 -2
- package/docs/publishing-for-teams.md +10 -0
- package/docs/quality-benchmark.md +427 -62
- package/docs/release-install-policy.md +10 -9
- package/docs/runtime-harness-standard.md +3 -3
- package/docs/runtime-policy-design.md +4 -4
- package/docs/runtime-quality-baseline.md +13 -6
- package/docs/security-threat-model.md +2 -2
- package/docs/subagent-orchestration-capabilities.md +19 -51
- package/docs/subagents-and-multiagent.md +21 -47
- package/docs/task-implementation-contract.md +3 -3
- package/docs/task-lifecycle-vietnamese.md +3 -3
- package/docs/team-onboarding.md +2 -2
- package/docs/usage-observability.md +7 -2
- package/docs/vi/architecture.md +27 -13
- package/docs-site/architecture.html +1 -1
- package/docs-site/benchmark.html +89 -95
- package/docs-site/commands.html +1 -1
- package/docs-site/content/benchmark.html +88 -94
- package/docs-site/content/en/benchmark.html +134 -90
- package/docs-site/content/en/index.html +19 -19
- package/docs-site/content/en/runtime.html +4 -4
- package/docs-site/content/en/whats-new.html +12 -1
- package/docs-site/content/en/workflows.html +2 -2
- package/docs-site/content/index.html +19 -19
- package/docs-site/content/runtime.html +4 -4
- package/docs-site/content/whats-new.html +12 -1
- package/docs-site/content/workflows.html +2 -2
- package/docs-site/context-engine.html +1 -1
- package/docs-site/en/architecture.html +1 -1
- package/docs-site/en/benchmark.html +135 -91
- package/docs-site/en/commands.html +1 -1
- package/docs-site/en/context-engine.html +1 -1
- package/docs-site/en/index.html +20 -20
- package/docs-site/en/mcp-approval.html +1 -1
- package/docs-site/en/mcp-auth.html +1 -1
- package/docs-site/en/mcp-servers.html +1 -1
- package/docs-site/en/mcp.html +1 -1
- package/docs-site/en/permissions.html +1 -1
- package/docs-site/en/profiles.html +1 -1
- package/docs-site/en/quickstart.html +1 -1
- package/docs-site/en/runtime.html +5 -5
- package/docs-site/en/scope.html +1 -1
- package/docs-site/en/security.html +1 -1
- package/docs-site/en/team.html +1 -1
- package/docs-site/en/whats-new.html +13 -2
- package/docs-site/en/workflows.html +3 -3
- package/docs-site/index.html +20 -20
- package/docs-site/mcp-approval.html +1 -1
- package/docs-site/mcp-auth.html +1 -1
- package/docs-site/mcp-servers.html +1 -1
- package/docs-site/mcp.html +1 -1
- package/docs-site/permissions.html +1 -1
- package/docs-site/profiles.html +1 -1
- package/docs-site/quickstart.html +1 -1
- package/docs-site/runtime.html +5 -5
- package/docs-site/scope.html +1 -1
- package/docs-site/security.html +1 -1
- package/docs-site/team.html +1 -1
- package/docs-site/whats-new.html +13 -2
- package/docs-site/workflows.html +3 -3
- package/evals/fixtures/benchmark-assurance-evidence.invalid.json +1 -1
- package/evals/fixtures/benchmark-assurance-evidence.valid.json +1 -1
- package/evals/fixtures/codex-relative-efficiency-v1.invalid.json +4 -0
- package/evals/fixtures/codex-relative-efficiency-v1.valid.json +94 -0
- package/evals/fixtures/helper-request.invalid.json +1 -1
- package/evals/fixtures/helper-request.valid.json +1 -1
- package/evals/fixtures/piagent-webui/session-live-state-v1.invalid.json +18 -0
- package/evals/fixtures/piagent-webui/session-live-state-v1.valid.json +27 -0
- package/evals/fixtures/piagent-webui/subagent-tree-v1.valid.json +7 -0
- package/evals/fixtures/task-authority-snapshot.valid.json +4 -4
- package/evals/fs4-readiness-matrix.v1.json +2 -2
- package/evals/fs5-causal-arm.v1.json +3 -3
- package/evals/fs5-pilot-protocol.v1.json +3 -3
- package/evals/fs5-pilot-protocol.v2.json +8 -8
- package/evals/fs5-pilot-protocol.v3.json +8 -8
- package/evals/fs5-pilot-protocol.v4.json +7 -6
- package/evals/fs5-pilot-protocol.v5.json +9 -7
- package/evals/private-holdout-v1/public-exposure.v1.json +1 -1
- package/evals/runtime-conformance-v1/README.md +43 -0
- package/evals/runtime-conformance-v1/evaluate-paid-canary.mjs +198 -0
- package/evals/runtime-conformance-v1/lane.json +57 -0
- package/evals/runtime-conformance-v1/paid-canary.json +31 -0
- package/evals/runtime-conformance-v1/runner.mjs +456 -0
- package/package.json +3 -1
- package/packages/piagent-core/README.md +13 -4
- package/packages/piagent-core/benchmark/benchmark-assurance.js +4 -1
- package/packages/piagent-core/benchmark/benchmark-bootstrap.js +91 -9
- package/packages/piagent-core/benchmark/benchmark-claim-restrictions.js +38 -7
- package/packages/piagent-core/benchmark/benchmark-cli.js +7 -7
- package/packages/piagent-core/benchmark/benchmark-codex-relative-efficiency.js +698 -0
- package/packages/piagent-core/benchmark/benchmark-codex.js +3 -1
- package/packages/piagent-core/benchmark/benchmark-comparison.js +271 -2
- package/packages/piagent-core/benchmark/benchmark-core.js +736 -664
- package/packages/piagent-core/benchmark/benchmark-execution-guard.js +7 -5
- package/packages/piagent-core/benchmark/benchmark-forensics.js +441 -4
- package/packages/piagent-core/benchmark/benchmark-host-readiness.js +639 -0
- package/packages/piagent-core/benchmark/benchmark-matrix.js +22 -4
- package/packages/piagent-core/benchmark/benchmark-normalized-cost.js +317 -0
- package/packages/piagent-core/benchmark/benchmark-preflight.js +5 -1
- package/packages/piagent-core/benchmark/benchmark-process.js +6 -5
- package/packages/piagent-core/benchmark/benchmark-provider-free-evidence.js +345 -0
- package/packages/piagent-core/benchmark/benchmark-provider-wire.js +126 -0
- package/packages/piagent-core/benchmark/benchmark-record-validation.js +252 -0
- package/packages/piagent-core/benchmark/benchmark-report.js +130 -12
- package/packages/piagent-core/benchmark/benchmark-resume-recovery.js +14 -0
- package/packages/piagent-core/benchmark/benchmark-runner-policy.js +26 -0
- package/packages/piagent-core/benchmark/benchmark-runtime-causal.js +244 -0
- package/packages/piagent-core/benchmark/benchmark-stage-diagnostic.js +979 -0
- package/packages/piagent-core/benchmark/benchmark-statistics.js +64 -0
- package/packages/piagent-core/benchmark/benchmark-stop-policy.js +8 -5
- package/packages/piagent-core/benchmark/benchmark-suite-identity.js +31 -0
- package/packages/piagent-core/benchmark/benchmark-suite-runtime.js +13 -9
- package/packages/piagent-core/benchmark/benchmark-suite.js +149 -2
- package/packages/piagent-core/benchmark/benchmark-summary-support.js +380 -0
- package/packages/piagent-core/benchmark/benchmark-timing-diagnostics.js +971 -0
- package/packages/piagent-core/benchmark/benchmark-usage.js +322 -0
- package/packages/piagent-core/benchmark/benchmark-workflow.js +166 -0
- package/packages/piagent-core/capabilities/runtime-integrity.js +3 -0
- package/packages/piagent-core/docs/context-efficiency-improvement-plan.md +1080 -0
- package/packages/piagent-core/extensions/acceptance-behavior-proof.js +806 -0
- package/packages/piagent-core/extensions/acceptance-contract-semantics.js +83 -69
- package/packages/piagent-core/extensions/acceptance-error-classes.js +160 -0
- package/packages/piagent-core/extensions/acceptance-executable-evidence.js +12 -9
- package/packages/piagent-core/extensions/acceptance-receipt.js +123 -59
- package/packages/piagent-core/extensions/acceptance-state-machine-evidence.js +518 -0
- package/packages/piagent-core/extensions/acceptance-test-binding-evidence.js +60 -0
- package/packages/piagent-core/extensions/context-efficiency-metrics.js +302 -0
- package/packages/piagent-core/extensions/context-efficiency-report.js +167 -0
- package/packages/piagent-core/extensions/context-engine.js +149 -156
- package/packages/piagent-core/extensions/context-evidence.js +48 -0
- package/packages/piagent-core/extensions/context-import-links.js +296 -0
- package/packages/piagent-core/extensions/context-index-policy.js +4 -0
- package/packages/piagent-core/extensions/context-query-paths.js +57 -0
- package/packages/piagent-core/extensions/context-telemetry-integrity.js +65 -0
- package/packages/piagent-core/extensions/criterion-context-pack.js +435 -7
- package/packages/piagent-core/extensions/criterion-graph.js +82 -9
- package/packages/piagent-core/extensions/fallback-base-policy.ts +101 -0
- package/packages/piagent-core/extensions/guard-types.ts +6 -0
- package/packages/piagent-core/extensions/javascript-regex-evidence.js +32 -0
- package/packages/piagent-core/extensions/piagent-guard.ts +420 -260
- package/packages/piagent-core/extensions/task-contract-view.js +17 -3
- package/packages/piagent-core/extensions/task-lifecycle.js +39 -2
- package/packages/piagent-core/extensions/task-state.js +109 -142
- package/packages/piagent-core/extensions/verification-intelligence.js +52 -13
- package/packages/piagent-core/extensions/workspace-evidence-roots.js +193 -0
- package/packages/piagent-core/package.json +1 -1
- package/packages/piagent-core/policies/base-policy.json +44 -2
- package/packages/piagent-core/policy/authority-manifest.v1.json +3 -3
- package/packages/piagent-core/prompts/be-to-fe.md +2 -8
- package/packages/piagent-core/prompts/plan.md +1 -1
- package/packages/piagent-core/prompts/platform-improve.md +2 -6
- package/packages/piagent-core/prompts/review.md +2 -7
- package/packages/piagent-core/prompts/scout.md +1 -1
- package/packages/piagent-core/prompts/task.md +4 -3
- package/packages/piagent-core/runtime/context/context-delivery.ts +103 -0
- package/packages/piagent-core/runtime/context/context-delta-shadow.ts +53 -0
- package/packages/piagent-core/runtime/context/context-efficiency-format.ts +47 -0
- package/packages/piagent-core/runtime/context/context-evidence-qualification.ts +32 -0
- package/packages/piagent-core/runtime/context/prefix-telemetry.ts +47 -0
- package/packages/piagent-core/runtime/context/repository-memory-hints.ts +27 -0
- package/packages/piagent-core/runtime/hooks/agent-prompt-telemetry.ts +56 -0
- package/packages/piagent-core/runtime/hooks/agent-start-hook.ts +162 -102
- package/packages/piagent-core/runtime/hooks/completion-hook.ts +12 -12
- package/packages/piagent-core/runtime/hooks/input-hook.ts +17 -1
- package/packages/piagent-core/runtime/hooks/session-hooks.ts +22 -2
- package/packages/piagent-core/runtime/hooks/session-start-hook.ts +107 -3
- package/packages/piagent-core/runtime/hooks/tool-result-content-guards.ts +95 -0
- package/packages/piagent-core/runtime/hooks/tool-result-hook.ts +134 -166
- package/packages/piagent-core/runtime/hooks/tool-result-value-helpers.ts +66 -0
- package/packages/piagent-core/runtime/inspection/activity-event-adapter.ts +4 -2
- package/packages/piagent-core/runtime/inspection/activity-recovery.ts +104 -0
- package/packages/piagent-core/runtime/inspection/bounded-emission-guard.ts +286 -0
- package/packages/piagent-core/runtime/inspection/runtime-event-store.ts +37 -7
- package/packages/piagent-core/runtime/inspection/task-compaction-history.ts +1 -1
- package/packages/piagent-core/runtime/inspection/task-handoff-history.ts +1 -1
- package/packages/piagent-core/runtime/inspection/task-subagent-tree.ts +27 -4
- package/packages/piagent-core/runtime/inspection/tool-failure-classification.ts +70 -0
- package/packages/piagent-core/runtime/inspection/webui-snapshot.ts +73 -9
- package/packages/piagent-core/runtime/model/authenticated-catalog.ts +17 -9
- package/packages/piagent-core/runtime/model/openai-codex-reasoning.ts +83 -0
- package/packages/piagent-core/runtime/model/provider-wire-fingerprint.ts +238 -0
- package/packages/piagent-core/runtime/orchestration/helper-lifecycle.ts +16 -12
- package/packages/piagent-core/runtime/orchestration/minimal-delegation-policy.ts +71 -0
- package/packages/piagent-core/runtime/orchestration/owned-work-budget.ts +28 -20
- package/packages/piagent-core/runtime/orchestration/role-policy.ts +27 -9
- package/packages/piagent-core/runtime/orchestration/subagent-tool-policy.ts +329 -0
- package/packages/piagent-core/runtime/policy/block-remedy.ts +0 -4
- package/packages/piagent-core/runtime/product/activity-inspector.ts +7 -2
- package/packages/piagent-core/runtime/product/efficiency-metrics.ts +7 -2
- package/packages/piagent-core/runtime/quality/edit-freshness-guard.ts +102 -0
- package/packages/piagent-core/runtime/quality/exact-output-contract.ts +22 -11
- package/packages/piagent-core/runtime/quality/performance-assurance-signals.ts +23 -0
- package/packages/piagent-core/runtime/quality/performance-assurance.ts +9 -5
- package/packages/piagent-core/runtime/recovery/continuation-budget.ts +1 -1
- package/packages/piagent-core/runtime/recovery/edit-recovery-context.ts +113 -0
- package/packages/piagent-core/runtime/recovery/edit-recovery-delivery.ts +42 -0
- package/packages/piagent-core/runtime/recovery/handoff-projection.ts +4 -1
- package/packages/piagent-core/runtime/recovery/pristine-task-policy-refresh.ts +91 -0
- package/packages/piagent-core/runtime/recovery/recovery-policy.ts +7 -4
- package/packages/piagent-core/runtime/recovery/resume-state.ts +112 -14
- package/packages/piagent-core/runtime/recovery/semantic-repair-handshake.ts +60 -13
- package/packages/piagent-core/runtime/recovery/semantic-repair-runtime.ts +55 -2
- package/packages/piagent-core/runtime/recovery/task-evidence-coverage-refresh.ts +217 -0
- package/packages/piagent-core/runtime/registration/context-commands.ts +82 -7
- package/packages/piagent-core/runtime/registration/knowledge-tools.ts +9 -5
- package/packages/piagent-core/runtime/registration/operator-request-intake.ts +49 -0
- package/packages/piagent-core/runtime/registration/policy-tools.ts +50 -15
- package/packages/piagent-core/runtime/registration/session-commands.ts +1 -1
- package/packages/piagent-core/runtime/registration/task-completion-tools.ts +61 -25
- package/packages/piagent-core/runtime/registration/task-evidence-tools.ts +21 -12
- package/packages/piagent-core/runtime/registration/task-start-guidance.ts +169 -0
- package/packages/piagent-core/runtime/registration/task-start-manifest.ts +54 -0
- package/packages/piagent-core/runtime/registration/task-start-retry-helpers.ts +37 -0
- package/packages/piagent-core/runtime/registration/task-start-tool.ts +108 -103
- package/packages/piagent-core/runtime/runtime-limits.ts +16 -2
- package/packages/piagent-core/runtime/session/adaptive-context-analysis.ts +461 -0
- package/packages/piagent-core/runtime/session/adaptive-context-governor.ts +464 -0
- package/packages/piagent-core/runtime/session/adaptive-context-ledger.ts +265 -0
- package/packages/piagent-core/runtime/session/message-signals.ts +7 -3
- package/packages/piagent-core/runtime/session/operator-request-carry.ts +44 -0
- package/packages/piagent-core/runtime/session/runtime-state.ts +161 -5
- package/packages/piagent-core/runtime/session/source-checkout-read-grants.ts +35 -0
- package/packages/piagent-core/runtime/session/system-prompt.ts +76 -14
- package/packages/piagent-core/runtime/session/task-contract-presentation.ts +39 -0
- package/packages/piagent-core/runtime/tools/apply-patch-tool.ts +500 -0
- package/packages/piagent-core/runtime/tools/phase-tools.ts +8 -8
- package/packages/piagent-core/runtime/tools/tool-groups.ts +12 -2
- package/packages/piagent-core/runtime/trajectory/trajectory-runtime.ts +2 -1
- package/packages/piagent-core/runtime/verification/exact-verifier-reuse.ts +101 -0
- package/packages/piagent-core/runtime/workflows/runtime-intake-compaction.ts +164 -0
- package/packages/piagent-core/runtime/workflows/task-intake.ts +207 -38
- package/packages/piagent-core/security/sensitive-data.js +13 -218
- package/packages/piagent-core/security/sensitive-project-file.js +42 -0
- package/packages/piagent-core/security/sensitive-source-expression.js +330 -0
- package/packages/piagent-core/security/sensitive-source-formats.js +394 -0
- package/packages/piagent-core/security/sensitive-text.js +234 -0
- package/packages/piagent-core/subagents/piagent-oracle.md +5 -3
- package/packages/piagent-core/subagents/piagent-planner.md +6 -4
- package/packages/piagent-core/subagents/piagent-reviewer.md +5 -3
- package/packages/piagent-core/subagents/piagent-scout.md +4 -2
- package/packages/piagent-core/subagents/piagent-worker.md +7 -5
- package/packages/piagent-webui/dist/client/assets/{MarkdownMessage-rD9WJKxs.js → MarkdownMessage-B4XehTCU.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/index-CgOEyRPG.js +176 -0
- package/packages/piagent-webui/dist/client/index.html +1 -1
- package/packages/piagent-webui/extension/piagent-webui.ts +3 -1
- package/packages/piagent-webui/extension/same-session-bridge.ts +1 -1
- package/packages/piagent-webui/extension/session-stream-adapter.ts +33 -10
- package/packages/piagent-webui/gateway/gateway-events.ts +109 -5
- package/packages/piagent-webui/gateway/gateway-service.ts +3 -0
- package/packages/piagent-webui/gateway/gateway-session-stream.ts +122 -20
- package/packages/piagent-webui/gateway/session-command-controller.ts +18 -3
- package/packages/piagent-webui/gateway/session-effective-options.ts +47 -0
- package/packages/piagent-webui/gateway/session-live-state.ts +21 -0
- package/packages/piagent-webui/gateway/session-operation-lifecycle.ts +237 -0
- package/packages/piagent-webui/gateway/session-operation-retry-control.ts +38 -0
- package/packages/piagent-webui/gateway/session-operation-start.ts +5 -1
- package/packages/piagent-webui/gateway/session-operation-watchdog.ts +165 -0
- package/packages/piagent-webui/gateway/session-runtime-factory.ts +45 -0
- package/packages/piagent-webui/gateway/session-runtime-supervisor.ts +141 -125
- package/packages/piagent-webui/ownership/session-lease-store.ts +5 -2
- package/packages/piagent-webui/server/core-inspection-provider.ts +2 -1
- package/packages/piagent-webui/server/loopback-server.ts +8 -0
- package/packages/piagent-webui/server/transcript-projection.ts +113 -9
- package/packages/piagent-webui/shared/text-visibility.ts +10 -0
- package/schemas/codex-relative-efficiency-v1.schema.json +155 -0
- package/schemas/piagent-webui/catalog-v1.json +9 -0
- package/schemas/piagent-webui/gateway-protocol-v1.schema.json +53 -3
- package/schemas/piagent-webui/runtime-event-v2.schema.json +15 -5
- package/schemas/piagent-webui/session-live-state-v1.schema.json +76 -0
- package/schemas/piagent-webui/subagent-tree-v1.schema.json +11 -1
- package/schemas/project-profile.schema.json +1 -1
- package/schemas/task-contract.schema.json +27 -1
- package/scripts/benchmark-runner-core.mjs +367 -363
- package/scripts/benchmark-runner-finalization.mjs +313 -0
- package/scripts/benchmark-runner-host-readiness.mjs +94 -0
- package/scripts/benchmark-runner-support.mjs +200 -0
- package/scripts/benchmark-session.mjs +95 -41
- package/scripts/configure-model-scope.sh +4 -3
- package/scripts/configure-subagents.sh +42 -34
- package/scripts/helper-evaluation.mjs +2 -2
- package/scripts/install-global.sh +2 -2
- package/scripts/pi-usage-history.mjs +37 -10
- package/scripts/setup.sh +2 -2
- package/scripts/team-doctor.sh +1 -1
- package/scripts/verify-local.sh +10 -1
- package/templates/global/settings.json +2 -1
- package/packages/piagent-webui/dist/client/assets/index-BZRFw1u6.js +0 -174
|
@@ -6,8 +6,9 @@ import {
|
|
|
6
6
|
acceptanceCriticalRecoveryProjection,
|
|
7
7
|
applyAcceptanceRecoveryProvenance
|
|
8
8
|
} from "../../extensions/acceptance-receipt.js";
|
|
9
|
+
import { hasDurableContextEvidence } from "../../extensions/context-evidence.js";
|
|
9
10
|
import type { TaskContract } from "../../extensions/guard-types.js";
|
|
10
|
-
import { runtimeLifecycleMode, workingTreeEvidenceDigest } from "../../extensions/task-lifecycle.js";
|
|
11
|
+
import { applyAssistedReadOnlyFinalHandoff, runtimeLifecycleMode, workingTreeEvidenceDigest } from "../../extensions/task-lifecycle.js";
|
|
11
12
|
import { recordCompletionAudit } from "../../extensions/task-runtime-audit.js";
|
|
12
13
|
import { workingTreeSnapshot } from "../../extensions/task-state.js";
|
|
13
14
|
import { taskDeltaFilesFromSnapshot } from "../../extensions/task-contract-view.js";
|
|
@@ -18,8 +19,7 @@ import {
|
|
|
18
19
|
looksLikeCompletionClaim,
|
|
19
20
|
looksLikeIncompleteHandoff
|
|
20
21
|
} from "../session/message-signals.ts";
|
|
21
|
-
import { RuntimeSessionState } from "../session/runtime-state.ts";
|
|
22
|
-
import type { ObservedTaskContext } from "../session/runtime-state.ts";
|
|
22
|
+
import { RuntimeSessionState, type ObservedTaskContext } from "../session/runtime-state.ts";
|
|
23
23
|
import type { RecoveryDecision } from "../recovery/recovery-policy.ts";
|
|
24
24
|
import { buildHandoffProjection, handoffProjectionPath, writeHandoffProjection } from "../recovery/handoff-projection.ts";
|
|
25
25
|
import { evaluateExactFinalOutputContract } from "../quality/exact-output-contract.ts";
|
|
@@ -177,7 +177,7 @@ export function registerCompletionHook(pi: ExtensionAPI, dependencies: Completio
|
|
|
177
177
|
let task = flushObservedTaskContext(
|
|
178
178
|
pi,
|
|
179
179
|
ctx,
|
|
180
|
-
state.
|
|
180
|
+
state.qualifiedTaskContext(ctx),
|
|
181
181
|
maxManifestFiles,
|
|
182
182
|
"context_observed_before_handoff"
|
|
183
183
|
) ?? activeTask(ctx);
|
|
@@ -187,7 +187,7 @@ export function registerCompletionHook(pi: ExtensionAPI, dependencies: Completio
|
|
|
187
187
|
const completionClaim = looksLikeCompletionClaim(text);
|
|
188
188
|
const incompleteHandoff = looksLikeIncompleteHandoff(text);
|
|
189
189
|
if (task.trace.outcome !== "pending") return;
|
|
190
|
-
const readOnlyEvidenceObserved = task.changeMode === "read-only"
|
|
190
|
+
const readOnlyEvidenceObserved = (task.changeMode === "read-only" || task.mutationPolicy === "forbidden") && hasDurableContextEvidence(task);
|
|
191
191
|
const latestExactVerifier = latestObservedVerification(task.verifyEvidence.filter((evidence) => evidence.matchedProfileCommand === true));
|
|
192
192
|
const potentiallyFinalEvidence = task.observedChangedFiles.length > 0
|
|
193
193
|
|| latestExactVerifier?.exitCode === 0
|
|
@@ -203,6 +203,7 @@ export function registerCompletionHook(pi: ExtensionAPI, dependencies: Completio
|
|
|
203
203
|
);
|
|
204
204
|
let completionGate: CompletionGate | undefined;
|
|
205
205
|
if (handoffAttempt) {
|
|
206
|
+
if (applyAssistedReadOnlyFinalHandoff(task, { durableReadEvidence: readOnlyEvidenceObserved, finalHandoffObserved: true }).changed) task = writeTask(ctx.cwd, task);
|
|
206
207
|
let projected = completionProjection(ctx.cwd, task, currentDigests);
|
|
207
208
|
const baseProjectedGate = evaluateGate(ctx.cwd, projected, currentDigests, currentDigest);
|
|
208
209
|
const exactOutput = evaluateExactFinalOutputContract(projected, text, ctx.cwd);
|
|
@@ -298,7 +299,6 @@ export function registerCompletionHook(pi: ExtensionAPI, dependencies: Completio
|
|
|
298
299
|
projected = withRecoveryProvenance(ctx, projected, projectedGate, currentDigests, null);
|
|
299
300
|
task = writeTask(ctx.cwd, projected);
|
|
300
301
|
observeTrajectorySync(ctx, syncTrajectory?.(ctx, task, { sourceHook: "completion" }), telemetry);
|
|
301
|
-
state.cacheTaskIdentity(ctx, task);
|
|
302
302
|
state.clearPerformanceReview(task.taskRunId);
|
|
303
303
|
state.clearObservedContext(ctx);
|
|
304
304
|
activateBaseTools(ctx);
|
|
@@ -378,20 +378,20 @@ export function registerCompletionHook(pi: ExtensionAPI, dependencies: Completio
|
|
|
378
378
|
? [
|
|
379
379
|
"Continue the same bounded task with one acceptance-proof repair pass.",
|
|
380
380
|
...criticalRecoveryGuidance,
|
|
381
|
-
"Add or correct focused
|
|
381
|
+
"Add or correct focused tests for every missing critical obligation. Assert exact boundary partitions and requested error classes; if a focused test exposes a defect, repair the evidence-backed source before rerunning verification.",
|
|
382
382
|
...verifierInstructions(gate.missingVerifyCommands),
|
|
383
|
-
"Do not
|
|
383
|
+
"Do not repeat a failed hypothesis, expand permission, or perform an external action."
|
|
384
384
|
]
|
|
385
385
|
: [
|
|
386
|
-
"Continue the same bounded task with one targeted
|
|
386
|
+
"Continue the same bounded task with one targeted evidence-backed source repair, then run every exact configured verifier.",
|
|
387
387
|
...verifierInstructions(gate.missingVerifyCommands),
|
|
388
|
-
"Do not
|
|
388
|
+
"Do not repeat a failed hypothesis, expand permission, or perform an external action."
|
|
389
389
|
]
|
|
390
|
-
: selectedRecovery.reasonCodes.includes("unknown-diagnostic-pass") || task.changeMode === "read-only"
|
|
390
|
+
: selectedRecovery.reasonCodes.includes("unknown-diagnostic-pass") || task.changeMode === "read-only" || task.mutationPolicy === "forbidden"
|
|
391
391
|
? [
|
|
392
392
|
...(gate.missingVerifyCommands.length > 0
|
|
393
393
|
? ["Run only the missing exact verifier commands against the current working tree.", ...verifierInstructions(gate.missingVerifyCommands)]
|
|
394
|
-
: ["Run one bounded diagnostic pass using targeted reads and report the concrete evidence or unknown."]),
|
|
394
|
+
: [(task.changeMode === "read-only" || task.mutationPolicy === "forbidden") && gate.missing.length > 0 && gate.missing.every((item) => /^completed work plan\b/i.test(item)) ? "Complete only the pending read-only review checkpoint, then re-emit the complete substantive assessment from the immediately preceding response; do not repeat repository reads or replace it with checkpoint evidence." : "Run one bounded diagnostic pass using targeted reads and report the concrete evidence or unknown."]),
|
|
395
395
|
"Do not mutate project source, expand permission, or perform an external action."
|
|
396
396
|
]
|
|
397
397
|
: [
|
|
@@ -9,8 +9,10 @@ import { LONG_INPUT_CHARS } from "../runtime-limits.ts";
|
|
|
9
9
|
import type { AuthorityResumeDecision } from "../policy/authority-resume-policy.ts";
|
|
10
10
|
import { buildHandoffProjection, writeHandoffProjection } from "../recovery/handoff-projection.ts";
|
|
11
11
|
import { buildContextPreflight, buildUsageSnapshot } from "../session/usage.ts";
|
|
12
|
+
import { registerAdaptiveContextGovernor } from "../session/adaptive-context-governor.ts";
|
|
12
13
|
import { activeTaskToolGroups, toolGroupsForPrompt } from "../tools/tool-groups.ts";
|
|
13
14
|
import type { PiagentToolGroup } from "../tools/tool-groups.ts";
|
|
15
|
+
import type { RuntimeSessionState } from "../session/runtime-state.ts";
|
|
14
16
|
import {
|
|
15
17
|
buildFreshCommand,
|
|
16
18
|
chooseFreshWorkflow,
|
|
@@ -26,6 +28,7 @@ import {
|
|
|
26
28
|
} from "../workflows/task-intake.ts";
|
|
27
29
|
|
|
28
30
|
type InputHookDependencies = {
|
|
31
|
+
state: RuntimeSessionState;
|
|
29
32
|
boilerplateCollapseChars: number;
|
|
30
33
|
activeTask: (ctx: ExtensionContext) => TaskContract | undefined;
|
|
31
34
|
authorityPolicy: (ctx: ExtensionContext, task: TaskContract) => AuthorityResumeDecision;
|
|
@@ -36,6 +39,11 @@ type InputHookDependencies = {
|
|
|
36
39
|
};
|
|
37
40
|
|
|
38
41
|
export function registerInputHook(pi: ExtensionAPI, dependencies: InputHookDependencies): void {
|
|
42
|
+
registerAdaptiveContextGovernor(pi, {
|
|
43
|
+
activeTask: dependencies.activeTask,
|
|
44
|
+
telemetry: dependencies.telemetry
|
|
45
|
+
});
|
|
46
|
+
|
|
39
47
|
pi.on("input", async (event, ctx) => {
|
|
40
48
|
const text = event.text.trim();
|
|
41
49
|
if (!text || isFreshOrUtilityInput(text)) return { action: "continue" };
|
|
@@ -44,7 +52,14 @@ export function registerInputHook(pi: ExtensionAPI, dependencies: InputHookDepen
|
|
|
44
52
|
}
|
|
45
53
|
|
|
46
54
|
const taskSignal = classifyContextTask(text);
|
|
47
|
-
const
|
|
55
|
+
const sessionTask = dependencies.activeTask(ctx);
|
|
56
|
+
if (sessionTask && sessionTask.trace.outcome !== "pending") dependencies.state.clearTaskBoundary(ctx, sessionTask.taskRunId);
|
|
57
|
+
else if (!sessionTask) {
|
|
58
|
+
const cachedTask = dependencies.state.taskIdentity(ctx);
|
|
59
|
+
if (cachedTask) dependencies.state.clearTaskBoundary(ctx, cachedTask.taskRunId);
|
|
60
|
+
}
|
|
61
|
+
const activeTask = sessionTask?.trace.outcome === "pending" ? sessionTask : undefined;
|
|
62
|
+
const turn = dependencies.state.beginTurn(ctx, taskSignal.promptHash);
|
|
48
63
|
const authorityPolicy = activeTask?.trace.outcome === "pending" ? dependencies.authorityPolicy(ctx, activeTask) : undefined;
|
|
49
64
|
let authorityHandoffReady = false;
|
|
50
65
|
if (activeTask && authorityPolicy?.disposition === "new-attempt-required") {
|
|
@@ -79,6 +94,7 @@ export function registerInputHook(pi: ExtensionAPI, dependencies: InputHookDepen
|
|
|
79
94
|
: promptGroups);
|
|
80
95
|
dependencies.telemetry(ctx, {
|
|
81
96
|
event: "user_input",
|
|
97
|
+
turnId: turn.turnId,
|
|
82
98
|
source: event.source,
|
|
83
99
|
promptHash: taskSignal.promptHash,
|
|
84
100
|
promptChars: taskSignal.promptChars,
|
|
@@ -4,6 +4,7 @@ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-a
|
|
|
4
4
|
import type { TaskContract } from "../../extensions/guard-types.js";
|
|
5
5
|
import { RuntimeSessionState } from "../session/runtime-state.ts";
|
|
6
6
|
import type { ObservedTaskContext } from "../session/runtime-state.ts";
|
|
7
|
+
import { confirmContextDelivery, contextDeliveryIdFromDetails } from "../context/context-delivery.ts";
|
|
7
8
|
|
|
8
9
|
type TelemetryWriter = (ctx: ExtensionContext, payload: Record<string, unknown>) => void;
|
|
9
10
|
|
|
@@ -39,6 +40,20 @@ export function registerSessionHooks(pi: ExtensionAPI, dependencies: SessionHook
|
|
|
39
40
|
flushObservedTaskContext
|
|
40
41
|
} = dependencies;
|
|
41
42
|
|
|
43
|
+
pi.on("message_start", async (event, ctx) => {
|
|
44
|
+
const message = event.message as unknown as { role?: unknown; details?: unknown };
|
|
45
|
+
if (message.role !== "custom") return;
|
|
46
|
+
const deliveryId = contextDeliveryIdFromDetails(message.details);
|
|
47
|
+
if (!deliveryId) return;
|
|
48
|
+
confirmContextDelivery(pi, ctx, deliveryId, {
|
|
49
|
+
state,
|
|
50
|
+
maxManifestFiles,
|
|
51
|
+
activeTask: (deliveryContext) => activeTask(deliveryContext.cwd, deliveryContext.sessionManager.getSessionId()),
|
|
52
|
+
flushObservedTaskContext,
|
|
53
|
+
telemetry
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
42
57
|
pi.on("session_info_changed", async (event, ctx) => {
|
|
43
58
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
44
59
|
const task = activeTask(ctx.cwd, sessionId);
|
|
@@ -58,6 +73,7 @@ export function registerSessionHooks(pi: ExtensionAPI, dependencies: SessionHook
|
|
|
58
73
|
|
|
59
74
|
pi.on("turn_end", async (event, ctx) => {
|
|
60
75
|
const message = event.message as unknown as { usage?: unknown; stopReason?: unknown; role?: unknown };
|
|
76
|
+
const task = activeTask(ctx.cwd, ctx.sessionManager.getSessionId());
|
|
61
77
|
telemetry(ctx, {
|
|
62
78
|
event: "turn_end",
|
|
63
79
|
turnIndex: event.turnIndex,
|
|
@@ -65,9 +81,13 @@ export function registerSessionHooks(pi: ExtensionAPI, dependencies: SessionHook
|
|
|
65
81
|
role: message.role,
|
|
66
82
|
stopReason: message.stopReason,
|
|
67
83
|
usage: message.usage,
|
|
68
|
-
contextUsage: ctx.getContextUsage()
|
|
84
|
+
contextUsage: ctx.getContextUsage(),
|
|
85
|
+
taskId: task?.taskId,
|
|
86
|
+
taskRunId: task?.taskRunId,
|
|
87
|
+
taskOutcome: task?.trace.outcome
|
|
69
88
|
});
|
|
70
89
|
dependencies.onTurnEnd?.(ctx);
|
|
90
|
+
if (task && task.trace.outcome !== "pending") state.clearTaskBoundary(ctx, task.taskRunId);
|
|
71
91
|
});
|
|
72
92
|
|
|
73
93
|
pi.on("agent_settled", async (_event, ctx) => {
|
|
@@ -96,7 +116,7 @@ export function registerSessionHooks(pi: ExtensionAPI, dependencies: SessionHook
|
|
|
96
116
|
flushObservedTaskContext(
|
|
97
117
|
pi,
|
|
98
118
|
ctx,
|
|
99
|
-
state.
|
|
119
|
+
state.qualifiedTaskContext(ctx),
|
|
100
120
|
maxManifestFiles,
|
|
101
121
|
"context_observed_before_shutdown"
|
|
102
122
|
);
|
|
@@ -21,6 +21,8 @@ import { buildContextPreflight, buildUsageSnapshot } from "../session/usage.ts";
|
|
|
21
21
|
import { toolResultCaptureRoot } from "../session/tool-result-compaction.ts";
|
|
22
22
|
import { ensureTaskAuthorityResumePolicy } from "../policy/authority-resume-policy.ts";
|
|
23
23
|
import { buildHandoffProjection, writeHandoffProjection } from "../recovery/handoff-projection.ts";
|
|
24
|
+
import { refreshPristineRuntimeTaskVerification } from "../recovery/pristine-task-policy-refresh.ts";
|
|
25
|
+
import { refreshLegacyHiddenWorkspaceEvidenceCoverage } from "../recovery/task-evidence-coverage-refresh.ts";
|
|
24
26
|
import { activeTaskToolGroups } from "../tools/tool-groups.ts";
|
|
25
27
|
import type { PiagentToolGroup } from "../tools/tool-groups.ts";
|
|
26
28
|
import { observeTrajectorySync } from "../trajectory/trajectory-observability.ts";
|
|
@@ -40,6 +42,7 @@ type SessionStartHookDependencies = {
|
|
|
40
42
|
resolveTaskAny: (cwd: string, reference: string) => TaskContract | undefined;
|
|
41
43
|
bindTask: (cwd: string, sessionId: string, sessionName: string | undefined, task: TaskContract) => unknown;
|
|
42
44
|
writeTask: (cwd: string, task: TaskContract) => TaskContract;
|
|
45
|
+
appendTrace: (cwd: string, payload: Record<string, unknown>) => void;
|
|
43
46
|
capabilityState: (ctx: ExtensionContext) => { ok: boolean; reason?: string; repinned?: string };
|
|
44
47
|
permissionProfile: (ctx: ExtensionContext, profile: ProjectProfile) => { mode: string; warning?: string };
|
|
45
48
|
legacyProjectWarning: (cwd: string) => string | undefined;
|
|
@@ -138,9 +141,107 @@ export function registerSessionStartHook(pi: ExtensionAPI, dependencies: Session
|
|
|
138
141
|
resumedTask = dependencies.writeTask(ctx.cwd, resumedTask);
|
|
139
142
|
dependencies.bindTask(ctx.cwd, sessionId, sessionName, resumedTask);
|
|
140
143
|
}
|
|
144
|
+
const capabilityState = dependencies.capabilityState(ctx);
|
|
145
|
+
if (resumedTask?.trace.outcome === "pending"
|
|
146
|
+
&& authorityPolicy?.disposition === "resume-pinned"
|
|
147
|
+
&& capabilityState.ok) {
|
|
148
|
+
// Re-read from the durable session binding immediately before the
|
|
149
|
+
// synchronous pristine-tree check and write. This prevents an earlier
|
|
150
|
+
// session-start projection from overwriting newer same-process task
|
|
151
|
+
// evidence or work-plan state.
|
|
152
|
+
const latestTask = dependencies.activeTask(ctx.cwd, sessionId);
|
|
153
|
+
if (latestTask?.taskRunId === resumedTask.taskRunId) {
|
|
154
|
+
resumedTask = latestTask;
|
|
155
|
+
let refreshTask = latestTask;
|
|
156
|
+
// Coverage reconciliation must precede resume inspection. Otherwise a
|
|
157
|
+
// path newly visible to the evidence collector looks like a task delta
|
|
158
|
+
// and can incorrectly block a valid dirty-task resume.
|
|
159
|
+
const coverage = refreshLegacyHiddenWorkspaceEvidenceCoverage(ctx.cwd, refreshTask);
|
|
160
|
+
if (coverage.refreshed) {
|
|
161
|
+
try {
|
|
162
|
+
resumedTask = dependencies.writeTask(ctx.cwd, coverage.task);
|
|
163
|
+
refreshTask = resumedTask;
|
|
164
|
+
try {
|
|
165
|
+
dependencies.appendTrace(ctx.cwd, {
|
|
166
|
+
event: "task_evidence_coverage_expanded",
|
|
167
|
+
taskId: resumedTask.taskId,
|
|
168
|
+
taskRunId: resumedTask.taskRunId,
|
|
169
|
+
sessionId,
|
|
170
|
+
sessionName,
|
|
171
|
+
reason: coverage.reason,
|
|
172
|
+
addedPathCount: coverage.addedPaths.length,
|
|
173
|
+
addedPathExamples: coverage.addedPaths.slice(0, 20),
|
|
174
|
+
retainedMutationPathCount: coverage.retainedMutationPaths.length,
|
|
175
|
+
retainedMutationPathExamples: coverage.retainedMutationPaths.slice(0, 20),
|
|
176
|
+
ambiguousPathCount: coverage.ambiguousPaths.length,
|
|
177
|
+
ambiguousPathExamples: coverage.ambiguousPaths.slice(0, 20),
|
|
178
|
+
previousBaselineDigest: coverage.previousBaselineDigest,
|
|
179
|
+
nextBaselineDigest: coverage.nextBaselineDigest
|
|
180
|
+
});
|
|
181
|
+
} catch (error) {
|
|
182
|
+
try {
|
|
183
|
+
ctx.ui.notify(`Piagent expanded legacy task evidence coverage, but its auxiliary trace could not be written: ${error instanceof Error ? error.message : String(error)}`, "warning");
|
|
184
|
+
} catch {
|
|
185
|
+
// UI availability is not part of the durable coverage commit.
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
} catch (error) {
|
|
189
|
+
try {
|
|
190
|
+
ctx.ui.notify(`Piagent kept the existing task baseline because its evidence-coverage refresh could not be persisted: ${error instanceof Error ? error.message : String(error)}`, "warning");
|
|
191
|
+
} catch {
|
|
192
|
+
// Continue startup with the last durably readable task.
|
|
193
|
+
}
|
|
194
|
+
refreshTask = dependencies.activeTask(ctx.cwd, sessionId) ?? latestTask;
|
|
195
|
+
resumedTask = refreshTask;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const refreshResume = dependencies.inspectResume(ctx.cwd, refreshTask, sessionId);
|
|
199
|
+
const refreshAllowed = refreshResume.enforcementSafe
|
|
200
|
+
&& refreshResume.decision !== "blocked"
|
|
201
|
+
&& refreshResume.decision !== "paused";
|
|
202
|
+
if (refreshAllowed) {
|
|
203
|
+
const refresh = refreshPristineRuntimeTaskVerification(ctx.cwd, refreshTask, profile);
|
|
204
|
+
if (refresh.refreshed) {
|
|
205
|
+
try {
|
|
206
|
+
resumedTask = dependencies.writeTask(ctx.cwd, refresh.task);
|
|
207
|
+
try {
|
|
208
|
+
dependencies.appendTrace(ctx.cwd, {
|
|
209
|
+
event: "task_pristine_verifier_refreshed",
|
|
210
|
+
taskId: resumedTask.taskId,
|
|
211
|
+
taskRunId: resumedTask.taskRunId,
|
|
212
|
+
sessionId,
|
|
213
|
+
sessionName,
|
|
214
|
+
reason: refresh.reason,
|
|
215
|
+
verifyGroup: refresh.verifyGroup,
|
|
216
|
+
previousCommands: refresh.previousCommands,
|
|
217
|
+
verifyCommands: refresh.nextCommands
|
|
218
|
+
});
|
|
219
|
+
} catch (error) {
|
|
220
|
+
// The contract write and its task journal entry are already
|
|
221
|
+
// durable. An auxiliary trace/notice failure must not abort
|
|
222
|
+
// session startup or roll the task back to stale commands.
|
|
223
|
+
try {
|
|
224
|
+
ctx.ui.notify(`Piagent refreshed the task verifier, but its auxiliary trace could not be written: ${error instanceof Error ? error.message : String(error)}`, "warning");
|
|
225
|
+
} catch {
|
|
226
|
+
// UI availability is not part of the durable refresh commit.
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
} catch (error) {
|
|
230
|
+
try {
|
|
231
|
+
ctx.ui.notify(`Piagent kept the existing task verifier because its pristine refresh could not be persisted: ${error instanceof Error ? error.message : String(error)}`, "warning");
|
|
232
|
+
} catch {
|
|
233
|
+
// Continue startup with the last durably readable task.
|
|
234
|
+
}
|
|
235
|
+
resumedTask = dependencies.activeTask(ctx.cwd, sessionId) ?? refreshTask;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
141
241
|
if (resumedTask?.workingTreeDigestMigration && resumedTask.workingTreeDigestMigration.status !== "refreshed") dependencies.state.clearDigestMigrationState(ctx, resumedTask.taskRunId, resumedTask.taskId);
|
|
142
|
-
dependencies.state.cacheTaskIdentity(ctx, resumedTask);
|
|
143
|
-
|
|
242
|
+
if (resumedTask?.trace.outcome === "pending") dependencies.state.cacheTaskIdentity(ctx, resumedTask);
|
|
243
|
+
else dependencies.state.clearSession(ctx);
|
|
244
|
+
const resumeState = resumedTask?.trace.outcome === "pending" ? dependencies.inspectResume(ctx.cwd, resumedTask, sessionId) : undefined;
|
|
144
245
|
if (resumeState) dependencies.state.rememberResumeState(resumeState);
|
|
145
246
|
if (resumedTask && resumeState?.enforcementSafe) observeTrajectorySync(ctx, dependencies.syncTrajectory?.(ctx, resumedTask), dependencies.telemetry);
|
|
146
247
|
let taskRecovery: Record<string, unknown> | undefined;
|
|
@@ -179,7 +280,6 @@ export function registerSessionStartHook(pi: ExtensionAPI, dependencies: Session
|
|
|
179
280
|
: " (run /onboard to select a profile)";
|
|
180
281
|
const snapshot = buildUsageSnapshot(ctx, String(pi.getThinkingLevel()));
|
|
181
282
|
const preflight = buildContextPreflight(snapshot, "task", 0);
|
|
182
|
-
const capabilityState = dependencies.capabilityState(ctx);
|
|
183
283
|
const permissionProfile = dependencies.permissionProfile(ctx, profile);
|
|
184
284
|
const executionBackend = resolveExecutionBackend();
|
|
185
285
|
const contextHint = preflight.recommendation === "fresh-session"
|
|
@@ -217,6 +317,10 @@ export function registerSessionStartHook(pi: ExtensionAPI, dependencies: Session
|
|
|
217
317
|
}
|
|
218
318
|
dependencies.telemetry(ctx, {
|
|
219
319
|
event: "session_start",
|
|
320
|
+
// Benchmark and efficiency projections must be able to distinguish a
|
|
321
|
+
// genuine zero-recovery session from telemetry produced before this
|
|
322
|
+
// receipt/result protocol existed.
|
|
323
|
+
editRecoveryContextTelemetryVersion: 1,
|
|
220
324
|
activeTools: pi.getActiveTools().length,
|
|
221
325
|
index: engineStatus,
|
|
222
326
|
taskMigration: migration,
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
|
|
4
|
+
import { matchesProtectedPath } from "../../extensions/policy-core.js";
|
|
5
|
+
|
|
6
|
+
function normalizeRelative(cwd: string, candidate: unknown): string | undefined {
|
|
7
|
+
if (typeof candidate !== "string" || candidate.trim().length === 0) return undefined;
|
|
8
|
+
let raw = candidate.trim();
|
|
9
|
+
try {
|
|
10
|
+
raw = decodeURIComponent(raw);
|
|
11
|
+
} catch {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
if (/^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(raw)) {
|
|
15
|
+
if (!raw.toLowerCase().startsWith("file://")) return undefined;
|
|
16
|
+
try {
|
|
17
|
+
raw = fileURLToPath(raw);
|
|
18
|
+
} catch {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const absolute = path.isAbsolute(raw) ? raw : path.resolve(cwd, raw);
|
|
23
|
+
return path.relative(cwd, absolute).split(path.sep).join("/");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function filterTextBlocks(
|
|
27
|
+
content: unknown,
|
|
28
|
+
blocked: (line: string) => boolean,
|
|
29
|
+
emptyText: string,
|
|
30
|
+
noticeText: (count: number) => string
|
|
31
|
+
): { changed: boolean; content?: unknown; redactedLines: number } {
|
|
32
|
+
if (!Array.isArray(content)) return { changed: false, redactedLines: 0 };
|
|
33
|
+
let changed = false;
|
|
34
|
+
let redactedLines = 0;
|
|
35
|
+
const filtered = content.map((block) => {
|
|
36
|
+
if (!block || typeof block !== "object") return block;
|
|
37
|
+
const text = (block as { type?: unknown; text?: unknown }).text;
|
|
38
|
+
if ((block as { type?: unknown }).type !== "text" || typeof text !== "string") return block;
|
|
39
|
+
const kept: string[] = [];
|
|
40
|
+
let blockRedactedLines = 0;
|
|
41
|
+
for (const line of text.split(/\r?\n/)) {
|
|
42
|
+
if (blocked(line)) {
|
|
43
|
+
changed = true;
|
|
44
|
+
redactedLines += 1;
|
|
45
|
+
blockRedactedLines += 1;
|
|
46
|
+
} else {
|
|
47
|
+
kept.push(line);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (blockRedactedLines === 0) return block;
|
|
51
|
+
const notice = noticeText(blockRedactedLines);
|
|
52
|
+
const nextText = kept.join("\n").trim().length > 0
|
|
53
|
+
? `${kept.join("\n")}\n${notice}`
|
|
54
|
+
: `${emptyText}\n${notice}`;
|
|
55
|
+
return { ...block, text: nextText };
|
|
56
|
+
});
|
|
57
|
+
return { changed, content: filtered, redactedLines };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function filterGrepProtectedContent(content: unknown, protectedPatterns: string[]) {
|
|
61
|
+
return filterTextBlocks(
|
|
62
|
+
content,
|
|
63
|
+
(line) => {
|
|
64
|
+
const linePath = line.match(/^(.+?)(?::\d+:|-\d+-)/)?.[1];
|
|
65
|
+
return Boolean(linePath && matchesProtectedPath(linePath, protectedPatterns));
|
|
66
|
+
},
|
|
67
|
+
"No matches found in non-protected paths.",
|
|
68
|
+
(count) => `[Piagent Pi guard redacted ${count} protected grep line${count === 1 ? "" : "s"}.]`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function filterProtectedPathListContent(
|
|
73
|
+
cwd: string,
|
|
74
|
+
content: unknown,
|
|
75
|
+
protectedPatterns: string[],
|
|
76
|
+
basePath: string,
|
|
77
|
+
toolName: string
|
|
78
|
+
) {
|
|
79
|
+
return filterTextBlocks(
|
|
80
|
+
content,
|
|
81
|
+
(line) => {
|
|
82
|
+
const trimmed = line.trim();
|
|
83
|
+
if (!trimmed || trimmed.startsWith("[") || trimmed.startsWith("No ") || trimmed === "(empty directory)") return false;
|
|
84
|
+
const entry = trimmed.replace(/[\\/]+$/, "");
|
|
85
|
+
const candidates = new Set<string>();
|
|
86
|
+
const direct = normalizeRelative(cwd, entry);
|
|
87
|
+
const underBase = normalizeRelative(cwd, path.posix.join(basePath || ".", entry));
|
|
88
|
+
if (direct !== undefined) candidates.add(direct);
|
|
89
|
+
if (underBase !== undefined) candidates.add(underBase);
|
|
90
|
+
return [...candidates].some((candidate) => matchesProtectedPath(candidate, protectedPatterns));
|
|
91
|
+
},
|
|
92
|
+
"No entries found in non-protected paths.",
|
|
93
|
+
(count) => `[Piagent Pi guard redacted ${count} protected ${toolName} line${count === 1 ? "" : "s"}.]`
|
|
94
|
+
);
|
|
95
|
+
}
|