@piagent/platform 1.5.5 → 1.6.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/CHANGELOG.md +117 -0
- package/README.md +9 -8
- package/README.vi.md +9 -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 +68 -0
- package/benchmarks/production-v1/suite.json +42 -3
- package/catalog/capabilities.json +6 -6
- package/docs/command-reference-vietnamese.md +6 -6
- package/docs/context-engine.md +7 -1
- package/docs/distribution-standard.md +7 -7
- package/docs/en/architecture.md +1 -0
- package/docs/languages.json +4 -4
- package/docs/model-options.md +8 -5
- package/docs/operator-manual-vietnamese.md +13 -11
- package/docs/project-adapters.md +2 -2
- package/docs/publishing-for-teams.md +5 -0
- package/docs/quality-benchmark.md +271 -62
- package/docs/release-install-policy.md +10 -9
- 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/task-lifecycle-vietnamese.md +2 -2
- package/docs/team-onboarding.md +2 -2
- package/docs/usage-observability.md +7 -2
- package/docs/vi/architecture.md +1 -0
- package/docs-site/architecture.html +1 -1
- package/docs-site/benchmark.html +1 -1
- package/docs-site/commands.html +1 -1
- package/docs-site/context-engine.html +1 -1
- package/docs-site/en/architecture.html +1 -1
- package/docs-site/en/benchmark.html +1 -1
- package/docs-site/en/commands.html +1 -1
- package/docs-site/en/context-engine.html +1 -1
- package/docs-site/en/index.html +1 -1
- 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 +1 -1
- 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 +1 -1
- package/docs-site/en/workflows.html +1 -1
- package/docs-site/index.html +1 -1
- 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 +1 -1
- 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 +1 -1
- package/docs-site/workflows.html +1 -1
- package/evals/fixtures/benchmark-assurance-evidence.invalid.json +1 -1
- package/evals/fixtures/benchmark-assurance-evidence.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/fs4-readiness-matrix.v1.json +2 -2
- package/evals/fs5-causal-arm.v1.json +2 -2
- package/evals/fs5-pilot-protocol.v1.json +2 -2
- package/evals/fs5-pilot-protocol.v4.json +6 -5
- package/evals/fs5-pilot-protocol.v5.json +7 -6
- package/evals/private-holdout-v1/public-exposure.v1.json +1 -1
- package/package.json +3 -1
- 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.js +3 -1
- package/packages/piagent-core/benchmark/benchmark-comparison.js +271 -2
- package/packages/piagent-core/benchmark/benchmark-core.js +732 -661
- package/packages/piagent-core/benchmark/benchmark-execution-guard.js +7 -5
- package/packages/piagent-core/benchmark/benchmark-forensics.js +439 -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 +3 -1
- package/packages/piagent-core/benchmark/benchmark-process.js +6 -5
- package/packages/piagent-core/benchmark/benchmark-provider-wire.js +126 -0
- package/packages/piagent-core/benchmark/benchmark-record-validation.js +183 -0
- package/packages/piagent-core/benchmark/benchmark-report.js +116 -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-stage-diagnostic.js +782 -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 +128 -2
- package/packages/piagent-core/benchmark/benchmark-summary-support.js +376 -0
- package/packages/piagent-core/benchmark/benchmark-timing-diagnostics.js +971 -0
- package/packages/piagent-core/benchmark/benchmark-usage.js +311 -0
- package/packages/piagent-core/benchmark/benchmark-workflow.js +166 -0
- package/packages/piagent-core/docs/context-efficiency-improvement-plan.md +1080 -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 +34 -11
- 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 +148 -145
- 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-telemetry-integrity.js +65 -0
- package/packages/piagent-core/extensions/criterion-context-pack.js +422 -7
- package/packages/piagent-core/extensions/criterion-graph.js +78 -8
- package/packages/piagent-core/extensions/guard-types.ts +2 -0
- package/packages/piagent-core/extensions/javascript-regex-evidence.js +32 -0
- package/packages/piagent-core/extensions/piagent-guard.ts +233 -41
- package/packages/piagent-core/extensions/task-contract-view.js +17 -3
- package/packages/piagent-core/extensions/task-lifecycle.js +7 -2
- package/packages/piagent-core/extensions/task-state.js +40 -134
- package/packages/piagent-core/extensions/verification-intelligence.js +3 -1
- package/packages/piagent-core/extensions/workspace-evidence-roots.js +157 -0
- package/packages/piagent-core/package.json +1 -1
- package/packages/piagent-core/policies/base-policy.json +2 -0
- 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 +5 -6
- package/packages/piagent-core/runtime/hooks/input-hook.ts +11 -1
- package/packages/piagent-core/runtime/hooks/session-hooks.ts +22 -2
- package/packages/piagent-core/runtime/hooks/session-start-hook.ts +7 -2
- package/packages/piagent-core/runtime/hooks/tool-result-content-guards.ts +95 -0
- package/packages/piagent-core/runtime/hooks/tool-result-hook.ts +84 -102
- 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/task-compaction-history.ts +1 -1
- package/packages/piagent-core/runtime/inspection/task-handoff-history.ts +1 -1
- package/packages/piagent-core/runtime/inspection/tool-failure-classification.ts +53 -0
- package/packages/piagent-core/runtime/inspection/webui-snapshot.ts +34 -6
- 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/role-policy.ts +1 -1
- package/packages/piagent-core/runtime/product/activity-inspector.ts +7 -2
- package/packages/piagent-core/runtime/product/efficiency-metrics.ts +4 -2
- package/packages/piagent-core/runtime/quality/exact-output-contract.ts +2 -1
- package/packages/piagent-core/runtime/quality/performance-assurance-signals.ts +23 -0
- package/packages/piagent-core/runtime/quality/performance-assurance.ts +6 -2
- 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/semantic-repair-handshake.ts +55 -2
- package/packages/piagent-core/runtime/recovery/semantic-repair-runtime.ts +55 -2
- package/packages/piagent-core/runtime/registration/context-commands.ts +66 -5
- package/packages/piagent-core/runtime/registration/policy-tools.ts +46 -11
- package/packages/piagent-core/runtime/registration/task-completion-tools.ts +49 -16
- package/packages/piagent-core/runtime/registration/task-start-guidance.ts +163 -0
- package/packages/piagent-core/runtime/registration/task-start-retry-helpers.ts +37 -0
- package/packages/piagent-core/runtime/registration/task-start-tool.ts +67 -62
- package/packages/piagent-core/runtime/session/runtime-state.ts +154 -2
- package/packages/piagent-core/runtime/session/system-prompt.ts +4 -4
- package/packages/piagent-core/runtime/tools/apply-patch-tool.ts +500 -0
- package/packages/piagent-core/runtime/trajectory/trajectory-runtime.ts +2 -1
- package/packages/piagent-core/runtime/workflows/task-intake.ts +43 -2
- 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-worker.md +1 -1
- package/packages/piagent-webui/dist/client/assets/{MarkdownMessage-rD9WJKxs.js → MarkdownMessage-CxeZqTte.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/index-DynIMe8I.js +176 -0
- package/packages/piagent-webui/dist/client/index.html +1 -1
- 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 +93 -7
- 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-start.ts +5 -1
- package/packages/piagent-webui/gateway/session-operation-watchdog.ts +158 -0
- package/packages/piagent-webui/gateway/session-runtime-factory.ts +45 -0
- package/packages/piagent-webui/gateway/session-runtime-supervisor.ts +139 -124
- package/packages/piagent-webui/server/loopback-server.ts +8 -0
- package/packages/piagent-webui/server/transcript-projection.ts +22 -4
- package/packages/piagent-webui/shared/text-visibility.ts +10 -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/session-live-state-v1.schema.json +76 -0
- package/schemas/task-contract.schema.json +12 -1
- package/scripts/benchmark-runner-core.mjs +355 -359
- package/scripts/benchmark-runner-finalization.mjs +309 -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/helper-evaluation.mjs +1 -1
- package/scripts/install-global.sh +2 -2
- package/scripts/pi-usage-history.mjs +37 -10
- package/scripts/setup.sh +2 -2
- package/scripts/verify-local.sh +5 -1
- package/templates/global/settings.json +2 -1
- package/packages/piagent-webui/dist/client/assets/index-BZRFw1u6.js +0 -174
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
|
|
3
|
+
import type { TaskContract } from "../../extensions/guard-types.js";
|
|
4
|
+
import type { ObservedTaskContext, RuntimeSessionState } from "../session/runtime-state.ts";
|
|
5
|
+
|
|
6
|
+
type TaskIdentity = { taskId: string; taskRunId: string };
|
|
7
|
+
|
|
8
|
+
type ContextEvidenceQualificationDependencies = {
|
|
9
|
+
state: RuntimeSessionState;
|
|
10
|
+
activeTask: (ctx: ExtensionContext) => TaskContract | undefined;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function recordObservedContextEvidence(
|
|
14
|
+
ctx: ExtensionContext,
|
|
15
|
+
entry: ObservedTaskContext | undefined,
|
|
16
|
+
taskIdentity: TaskIdentity | undefined,
|
|
17
|
+
dependencies: ContextEvidenceQualificationDependencies
|
|
18
|
+
): void {
|
|
19
|
+
if (!entry) return;
|
|
20
|
+
dependencies.state.rememberObservedContext(ctx, entry);
|
|
21
|
+
const activeTask = dependencies.activeTask(ctx);
|
|
22
|
+
if (
|
|
23
|
+
taskIdentity
|
|
24
|
+
&& activeTask?.trace.outcome === "pending"
|
|
25
|
+
&& activeTask.taskId === taskIdentity.taskId
|
|
26
|
+
&& activeTask.taskRunId === taskIdentity.taskRunId
|
|
27
|
+
) {
|
|
28
|
+
dependencies.state.rememberQualifiedContextEvidence(ctx, taskIdentity.taskRunId, entry);
|
|
29
|
+
} else if (!activeTask || activeTask.trace.outcome !== "pending") {
|
|
30
|
+
dependencies.state.rememberPreTaskContext(ctx, entry);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
|
|
3
|
+
type ProviderToolMetadata = {
|
|
4
|
+
name: string;
|
|
5
|
+
description?: unknown;
|
|
6
|
+
parameters?: unknown;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
function canonicalValue(value: unknown): unknown {
|
|
10
|
+
if (value === null || ["string", "number", "boolean"].includes(typeof value)) return value;
|
|
11
|
+
if (Array.isArray(value)) return value.map((item) => canonicalValue(item));
|
|
12
|
+
if (!value || typeof value !== "object") return undefined;
|
|
13
|
+
return Object.fromEntries(
|
|
14
|
+
Object.entries(value as Record<string, unknown>)
|
|
15
|
+
.filter(([, item]) => item !== undefined && typeof item !== "function" && typeof item !== "symbol")
|
|
16
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
17
|
+
.map(([key, item]) => [key, canonicalValue(item)])
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function deepCanonicalJson(value: unknown): string {
|
|
22
|
+
return JSON.stringify(canonicalValue(value));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function hash(value: string): string {
|
|
26
|
+
return crypto.createHash("sha256").update(value).digest("hex");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function buildPrefixTelemetry(systemPrompt: string, tools: ProviderToolMetadata[]): {
|
|
30
|
+
systemPromptHash: string;
|
|
31
|
+
toolSchemaHash: string;
|
|
32
|
+
prefixSurfaceHash: string;
|
|
33
|
+
canonicalToolSurface: string;
|
|
34
|
+
} {
|
|
35
|
+
const providerSurface = tools
|
|
36
|
+
.map((tool) => ({ name: tool.name, description: tool.description, parameters: tool.parameters }))
|
|
37
|
+
.sort((left, right) => left.name.localeCompare(right.name));
|
|
38
|
+
const canonicalToolSurface = deepCanonicalJson(providerSurface);
|
|
39
|
+
const systemPromptHash = hash(systemPrompt);
|
|
40
|
+
const toolSchemaHash = hash(canonicalToolSurface);
|
|
41
|
+
return {
|
|
42
|
+
systemPromptHash,
|
|
43
|
+
toolSchemaHash,
|
|
44
|
+
prefixSurfaceHash: hash(`${systemPromptHash}\0${toolSchemaHash}`),
|
|
45
|
+
canonicalToolSurface
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { estimateContextTokens } from "../../extensions/context-engine.js";
|
|
2
|
+
|
|
3
|
+
type RepositoryMemoryCandidate = {
|
|
4
|
+
record: { id?: string; fact: string; citations: Array<{ path: string }> };
|
|
5
|
+
matchedTerms: string[];
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export function formatRepositoryMemoryHints(
|
|
9
|
+
candidates: RepositoryMemoryCandidate[],
|
|
10
|
+
budgetTokens: number
|
|
11
|
+
): { text: string; ids: string[] } {
|
|
12
|
+
if (budgetTokens < 80 || candidates.length === 0) return { text: "", ids: [] };
|
|
13
|
+
const lines = [
|
|
14
|
+
"[Piagent repository memory: advisory only]",
|
|
15
|
+
"Verify every hint against the cited current file before relying on it."
|
|
16
|
+
];
|
|
17
|
+
const ids: string[] = [];
|
|
18
|
+
for (const candidate of candidates) {
|
|
19
|
+
const paths = candidate.record.citations.slice(0, 4).map((citation) => citation.path).join(", ");
|
|
20
|
+
const line = `- ${candidate.record.fact.slice(0, 320)} [sources: ${paths}]`;
|
|
21
|
+
const proposed = [...lines, line].join("\n");
|
|
22
|
+
if (estimateContextTokens(proposed) > budgetTokens) break;
|
|
23
|
+
lines.push(line);
|
|
24
|
+
if (candidate.record.id) ids.push(candidate.record.id);
|
|
25
|
+
}
|
|
26
|
+
return ids.length > 0 ? { text: lines.join("\n"), ids } : { text: "", ids: [] };
|
|
27
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { RuntimeModelSnapshot } from "../model/runtime-snapshot.ts";
|
|
2
|
+
import { runtimeModelSnapshotDigest } from "../model/runtime-snapshot.ts";
|
|
3
|
+
import type { ModelRouteEvaluation } from "../model/model-route-runtime.ts";
|
|
4
|
+
import type { SolverShadowEvaluation } from "../solver/solver-shadow.ts";
|
|
5
|
+
|
|
6
|
+
export function runtimeSnapshotTelemetry(snapshot?: RuntimeModelSnapshot) {
|
|
7
|
+
if (!snapshot) return undefined;
|
|
8
|
+
return {
|
|
9
|
+
schemaVersion: snapshot.schemaVersion,
|
|
10
|
+
digest: runtimeModelSnapshotDigest(snapshot),
|
|
11
|
+
provider: snapshot.provider,
|
|
12
|
+
modelId: snapshot.modelId,
|
|
13
|
+
contextWindow: snapshot.contextWindow,
|
|
14
|
+
requestedThinkingLevel: snapshot.requestedThinkingLevel,
|
|
15
|
+
effectiveThinkingLevel: snapshot.effectiveThinkingLevel,
|
|
16
|
+
warningCount: snapshot.warnings.length
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function solverShadowTelemetry(evaluation?: SolverShadowEvaluation) {
|
|
21
|
+
if (evaluation?.status !== "ok") return evaluation;
|
|
22
|
+
return {
|
|
23
|
+
mode: evaluation.decision.mode,
|
|
24
|
+
route: evaluation.decision.route,
|
|
25
|
+
featureHash: evaluation.features.featureHash,
|
|
26
|
+
reasonCodes: evaluation.decision.reasonCodes,
|
|
27
|
+
confidence: evaluation.decision.confidence,
|
|
28
|
+
reused: evaluation.reused,
|
|
29
|
+
persisted: evaluation.persisted,
|
|
30
|
+
durationMs: evaluation.durationMs,
|
|
31
|
+
warnings: evaluation.warnings
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function modelRouteTelemetry(evaluation?: ModelRouteEvaluation) {
|
|
36
|
+
if (evaluation?.status !== "ok") return evaluation;
|
|
37
|
+
return {
|
|
38
|
+
mode: evaluation.decision.mode,
|
|
39
|
+
objective: evaluation.decision.objective,
|
|
40
|
+
capabilityBand: evaluation.decision.capabilityBand,
|
|
41
|
+
safetyFloor: evaluation.decision.safetyFloor,
|
|
42
|
+
disposition: evaluation.decision.disposition,
|
|
43
|
+
selectionSource: evaluation.decision.selectionSource,
|
|
44
|
+
provider: evaluation.decision.provider,
|
|
45
|
+
modelId: evaluation.decision.modelId,
|
|
46
|
+
effort: evaluation.decision.effort,
|
|
47
|
+
downgradeSteps: evaluation.decision.downgradeSteps,
|
|
48
|
+
enforced: evaluation.decision.enforced,
|
|
49
|
+
decisionDigest: evaluation.decision.decisionDigest,
|
|
50
|
+
reasonCodes: evaluation.decision.reasonCodes,
|
|
51
|
+
reused: evaluation.reused,
|
|
52
|
+
persisted: evaluation.persisted,
|
|
53
|
+
durationMs: evaluation.durationMs,
|
|
54
|
+
warnings: evaluation.warnings
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -7,7 +7,10 @@ import {
|
|
|
7
7
|
ensureContextIndexV2,
|
|
8
8
|
estimateContextTokens
|
|
9
9
|
} from "../../extensions/context-engine.js";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
buildSelectedContextPack,
|
|
12
|
+
composeCriterionContextEntries
|
|
13
|
+
} from "../../extensions/criterion-context-pack.js";
|
|
11
14
|
import { matchesProtectedPath } from "../../extensions/policy-core.js";
|
|
12
15
|
import { selectRepositoryMemoryFacts } from "../../extensions/repository-memory.js";
|
|
13
16
|
import type { TaskContract } from "../../extensions/guard-types.js";
|
|
@@ -15,9 +18,12 @@ import {
|
|
|
15
18
|
contextPlanAcceptsConfidence,
|
|
16
19
|
planAdaptiveContext
|
|
17
20
|
} from "../context/adaptive-planner.ts";
|
|
21
|
+
import { stageContextDelivery } from "../context/context-delivery.ts";
|
|
22
|
+
import { measureContextDeltaShadow, type ContextDeltaShadowMode } from "../context/context-delta-shadow.ts";
|
|
23
|
+
import { buildPrefixTelemetry } from "../context/prefix-telemetry.ts";
|
|
24
|
+
import { formatRepositoryMemoryHints } from "../context/repository-memory-hints.ts";
|
|
18
25
|
import { modelCapabilityFromContext } from "../model/capabilities.ts";
|
|
19
26
|
import type { RuntimeModelSnapshot } from "../model/runtime-snapshot.ts";
|
|
20
|
-
import { runtimeModelSnapshotDigest } from "../model/runtime-snapshot.ts";
|
|
21
27
|
import type { ModelRouteEvaluation } from "../model/model-route-runtime.ts";
|
|
22
28
|
import { buildTaskResumeContext } from "../recovery/resume-state.ts";
|
|
23
29
|
import { planRetrievalRoute } from "../context/retrieval-route-policy.ts";
|
|
@@ -25,7 +31,7 @@ import type { SolverShadowEvaluation } from "../solver/solver-shadow.ts";
|
|
|
25
31
|
import { observeTrajectorySync } from "../trajectory/trajectory-observability.ts";
|
|
26
32
|
import type { TrajectorySyncOptions, TrajectorySyncResult } from "../trajectory/trajectory-runtime.ts";
|
|
27
33
|
import { trajectoryRecommendationRef } from "../trajectory/trajectory-runtime.ts";
|
|
28
|
-
import { RuntimeSessionState } from "../session/runtime-state.ts";
|
|
34
|
+
import { RuntimeSessionState, type ContextInjectionItem } from "../session/runtime-state.ts";
|
|
29
35
|
import {
|
|
30
36
|
compactManagedProjectInstructions,
|
|
31
37
|
rewriteLegacyProjectInstructions
|
|
@@ -37,16 +43,20 @@ import {
|
|
|
37
43
|
automaticTaskIntakeMode
|
|
38
44
|
} from "../workflows/task-intake.ts";
|
|
39
45
|
import { CONTEXT_PACK_MAX_TOKENS } from "../runtime-limits.ts";
|
|
46
|
+
import { modelRouteTelemetry, runtimeSnapshotTelemetry, solverShadowTelemetry } from "./agent-prompt-telemetry.ts";
|
|
40
47
|
|
|
41
48
|
type RuntimeIntakeResult = {
|
|
42
49
|
started: boolean;
|
|
43
50
|
text: string;
|
|
44
51
|
task?: TaskContract;
|
|
52
|
+
plannedContext?: Array<{ path: string; reason: string }>;
|
|
53
|
+
plannedContextComplete?: boolean;
|
|
45
54
|
};
|
|
46
55
|
|
|
47
56
|
type AgentStartHookDependencies = {
|
|
48
57
|
state: RuntimeSessionState;
|
|
49
58
|
autoContextEnabled: boolean;
|
|
59
|
+
contextDeltaShadowMode: ContextDeltaShadowMode;
|
|
50
60
|
activeTask: (ctx: ExtensionContext) => TaskContract | undefined;
|
|
51
61
|
readProtectedPaths: (ctx: ExtensionContext) => string[];
|
|
52
62
|
contextExcludePatterns: (ctx: ExtensionContext) => string[];
|
|
@@ -71,36 +81,18 @@ type AgentStartHookDependencies = {
|
|
|
71
81
|
telemetry: (ctx: ExtensionContext, payload: Record<string, unknown>) => void;
|
|
72
82
|
};
|
|
73
83
|
|
|
74
|
-
function formatRepositoryMemoryHints(candidates: Array<{
|
|
75
|
-
record: { id?: string; fact: string; citations: Array<{ path: string }> };
|
|
76
|
-
matchedTerms: string[];
|
|
77
|
-
}>, budgetTokens: number): { text: string; ids: string[] } {
|
|
78
|
-
if (budgetTokens < 80 || candidates.length === 0) return { text: "", ids: [] };
|
|
79
|
-
const lines = [
|
|
80
|
-
"[Piagent repository memory: advisory only]",
|
|
81
|
-
"Verify every hint against the cited current file before relying on it."
|
|
82
|
-
];
|
|
83
|
-
const ids: string[] = [];
|
|
84
|
-
for (const candidate of candidates) {
|
|
85
|
-
const paths = candidate.record.citations.slice(0, 4).map((citation) => citation.path).join(", ");
|
|
86
|
-
const line = `- ${candidate.record.fact.slice(0, 320)} [sources: ${paths}]`;
|
|
87
|
-
const proposed = [...lines, line].join("\n");
|
|
88
|
-
if (estimateContextTokens(proposed) > budgetTokens) break;
|
|
89
|
-
lines.push(line);
|
|
90
|
-
if (candidate.record.id) ids.push(candidate.record.id);
|
|
91
|
-
}
|
|
92
|
-
return ids.length > 0 ? { text: lines.join("\n"), ids } : { text: "", ids: [] };
|
|
93
|
-
}
|
|
94
|
-
|
|
95
84
|
export function registerAgentStartHook(pi: ExtensionAPI, dependencies: AgentStartHookDependencies): void {
|
|
96
85
|
pi.on("before_agent_start", async (event, ctx) => {
|
|
97
86
|
const projectInstructions = rewriteLegacyProjectInstructions(event.systemPrompt);
|
|
98
87
|
const query = looksLikeGovernedBoilerplate(event.prompt) ? extractTaskRequest(event.prompt) : event.prompt.trim();
|
|
99
88
|
const signal = classifyContextTask(query);
|
|
89
|
+
const turn = dependencies.state.currentTurn(ctx, signal.promptHash) ?? dependencies.state.beginTurn(ctx, signal.promptHash);
|
|
100
90
|
const readProtectedPaths = dependencies.readProtectedPaths(ctx);
|
|
91
|
+
const protectedTarget = signal.paths.some((candidate) => matchesProtectedPath(candidate, readProtectedPaths));
|
|
101
92
|
const protectedOnlyTarget = signal.paths.length > 0
|
|
102
93
|
&& signal.paths.every((candidate) => matchesProtectedPath(candidate, readProtectedPaths));
|
|
103
|
-
const
|
|
94
|
+
const sessionTask = dependencies.activeTask(ctx);
|
|
95
|
+
const activeTask = sessionTask?.trace.outcome === "pending" ? sessionTask : undefined;
|
|
104
96
|
const runtimeIntakeMode = !activeTask ? automaticTaskIntakeMode(query, readProtectedPaths) : undefined;
|
|
105
97
|
const runtimeIntake = Boolean(runtimeIntakeMode);
|
|
106
98
|
const compactMode = protectedOnlyTarget
|
|
@@ -122,10 +114,10 @@ export function registerAgentStartHook(pi: ExtensionAPI, dependencies: AgentStar
|
|
|
122
114
|
.map((tool) => ({
|
|
123
115
|
name: tool.name,
|
|
124
116
|
description: tool.description,
|
|
125
|
-
parameters: tool.parameters
|
|
126
|
-
promptGuidelines: tool.promptGuidelines
|
|
117
|
+
parameters: tool.parameters
|
|
127
118
|
}));
|
|
128
|
-
const
|
|
119
|
+
const prefix = buildPrefixTelemetry(effectiveSystemPrompt, toolMetadata);
|
|
120
|
+
const toolSchemaTokens = estimateContextTokens(prefix.canonicalToolSurface);
|
|
129
121
|
const systemPromptTokens = estimateContextTokens(effectiveSystemPrompt);
|
|
130
122
|
const autoPackUseful = activeTask?.trace.outcome !== "pending"
|
|
131
123
|
&& (runtimeIntake || signal.paths.length === 0);
|
|
@@ -154,6 +146,7 @@ export function registerAgentStartHook(pi: ExtensionAPI, dependencies: AgentStar
|
|
|
154
146
|
if (activeTask) observeTrajectorySync(ctx, dependencies.syncTrajectory?.(ctx, activeTask, { sourceHook: "agent-start", recommendationRef }), dependencies.telemetry);
|
|
155
147
|
dependencies.telemetry(ctx, {
|
|
156
148
|
event: "agent_prompt",
|
|
149
|
+
turnId: turn.turnId,
|
|
157
150
|
promptHash: signal.promptHash,
|
|
158
151
|
promptChars: signal.promptChars,
|
|
159
152
|
workflow: signal.workflow,
|
|
@@ -162,56 +155,16 @@ export function registerAgentStartHook(pi: ExtensionAPI, dependencies: AgentStar
|
|
|
162
155
|
activePiagentTools: [...active].filter((toolName) => PIAGENT_TOOL_NAMES.has(toolName)).length,
|
|
163
156
|
toolSchemaTokens,
|
|
164
157
|
systemPromptTokens,
|
|
165
|
-
systemPromptHash:
|
|
158
|
+
systemPromptHash: prefix.systemPromptHash,
|
|
159
|
+
toolSchemaHash: prefix.toolSchemaHash,
|
|
160
|
+
prefixSurfaceHash: prefix.prefixSurfaceHash,
|
|
161
|
+
taskRunId: activeTask?.taskRunId,
|
|
166
162
|
legacyProjectInstructionsRewritten: projectInstructions.rewritten,
|
|
167
163
|
managedInstructionsCompacted: compactedInstructions.compacted,
|
|
168
164
|
contextUsage: ctx.getContextUsage(),
|
|
169
|
-
runtimeSnapshot: runtimeSnapshot
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
digest: runtimeModelSnapshotDigest(runtimeSnapshot),
|
|
173
|
-
provider: runtimeSnapshot.provider,
|
|
174
|
-
modelId: runtimeSnapshot.modelId,
|
|
175
|
-
contextWindow: runtimeSnapshot.contextWindow,
|
|
176
|
-
requestedThinkingLevel: runtimeSnapshot.requestedThinkingLevel,
|
|
177
|
-
effectiveThinkingLevel: runtimeSnapshot.effectiveThinkingLevel,
|
|
178
|
-
warningCount: runtimeSnapshot.warnings.length
|
|
179
|
-
}
|
|
180
|
-
: undefined,
|
|
181
|
-
solverShadow: solverShadow?.status === "ok"
|
|
182
|
-
? {
|
|
183
|
-
mode: solverShadow.decision.mode,
|
|
184
|
-
route: solverShadow.decision.route,
|
|
185
|
-
featureHash: solverShadow.features.featureHash,
|
|
186
|
-
reasonCodes: solverShadow.decision.reasonCodes,
|
|
187
|
-
confidence: solverShadow.decision.confidence,
|
|
188
|
-
reused: solverShadow.reused,
|
|
189
|
-
persisted: solverShadow.persisted,
|
|
190
|
-
durationMs: solverShadow.durationMs,
|
|
191
|
-
warnings: solverShadow.warnings
|
|
192
|
-
}
|
|
193
|
-
: solverShadow,
|
|
194
|
-
modelRoute: modelRoute?.status === "ok"
|
|
195
|
-
? {
|
|
196
|
-
mode: modelRoute.decision.mode,
|
|
197
|
-
objective: modelRoute.decision.objective,
|
|
198
|
-
capabilityBand: modelRoute.decision.capabilityBand,
|
|
199
|
-
safetyFloor: modelRoute.decision.safetyFloor,
|
|
200
|
-
disposition: modelRoute.decision.disposition,
|
|
201
|
-
selectionSource: modelRoute.decision.selectionSource,
|
|
202
|
-
provider: modelRoute.decision.provider,
|
|
203
|
-
modelId: modelRoute.decision.modelId,
|
|
204
|
-
effort: modelRoute.decision.effort,
|
|
205
|
-
downgradeSteps: modelRoute.decision.downgradeSteps,
|
|
206
|
-
enforced: modelRoute.decision.enforced,
|
|
207
|
-
decisionDigest: modelRoute.decision.decisionDigest,
|
|
208
|
-
reasonCodes: modelRoute.decision.reasonCodes,
|
|
209
|
-
reused: modelRoute.reused,
|
|
210
|
-
persisted: modelRoute.persisted,
|
|
211
|
-
durationMs: modelRoute.durationMs,
|
|
212
|
-
warnings: modelRoute.warnings
|
|
213
|
-
}
|
|
214
|
-
: modelRoute
|
|
165
|
+
runtimeSnapshot: runtimeSnapshotTelemetry(runtimeSnapshot),
|
|
166
|
+
solverShadow: solverShadowTelemetry(solverShadow),
|
|
167
|
+
modelRoute: modelRouteTelemetry(modelRoute)
|
|
215
168
|
});
|
|
216
169
|
|
|
217
170
|
const finishAgentStart = async (contextMessage?: {
|
|
@@ -225,36 +178,133 @@ export function registerAgentStartHook(pi: ExtensionAPI, dependencies: AgentStar
|
|
|
225
178
|
const intake = await dependencies.startAutomaticTask(query, ctx);
|
|
226
179
|
if (intake?.task) observeTrajectorySync(ctx, dependencies.syncTrajectory?.(ctx, intake.task, { sourceHook: "agent-start", recommendationRef }), dependencies.telemetry);
|
|
227
180
|
if (!selectedContext && !intake) return systemPromptUpdate;
|
|
228
|
-
const
|
|
229
|
-
?
|
|
230
|
-
|
|
181
|
+
const discoveryItems = selectedContext?.customType === "piagent-context-pack-v2" && Array.isArray(selectedContext.details.selectedItems)
|
|
182
|
+
? selectedContext.details.selectedItems as Array<Record<string, unknown>>
|
|
183
|
+
: [];
|
|
184
|
+
const discoveryPlan = selectedContext?.customType === "piagent-context-pack-v2"
|
|
185
|
+
&& selectedContext.details.contextPlan && typeof selectedContext.details.contextPlan === "object"
|
|
186
|
+
? selectedContext.details.contextPlan as { budgetTokens?: unknown; limit?: unknown }
|
|
187
|
+
: undefined;
|
|
188
|
+
const fallbackBudget = signal.paths.length === 0 ? 680 : signal.lane === "tiny" ? 420 : 560;
|
|
189
|
+
const criterionBudget = Number.isFinite(Number(discoveryPlan?.budgetTokens))
|
|
190
|
+
? Math.max(100, Math.min(CONTEXT_PACK_MAX_TOKENS, Math.trunc(Number(discoveryPlan?.budgetTokens))))
|
|
191
|
+
: fallbackBudget;
|
|
192
|
+
const criterionLimit = Number.isFinite(Number(discoveryPlan?.limit))
|
|
193
|
+
? Math.max(1, Math.min(6, Math.trunc(Number(discoveryPlan?.limit))))
|
|
194
|
+
: signal.paths.length > 0 ? 3 : 4;
|
|
195
|
+
const criterionMode = dependencies.autoContextEnabled && intake?.task?.criterionGraph?.mode === "criterion-graph";
|
|
196
|
+
const criterionEntries = intake?.task?.criterionGraph?.mode === "criterion-graph"
|
|
197
|
+
? composeCriterionContextEntries({
|
|
198
|
+
explicitPaths: signal.paths,
|
|
199
|
+
criteria: intake.task.acceptanceCriteria,
|
|
200
|
+
plannedEntries: intake.plannedContext ?? [],
|
|
201
|
+
plannedSelectionComplete: intake.plannedContextComplete === true,
|
|
202
|
+
retrievedItems: discoveryItems
|
|
203
|
+
}, { limit: criterionLimit })
|
|
204
|
+
: [];
|
|
205
|
+
const criterionContext = criterionMode
|
|
206
|
+
? buildSelectedContextPack(ctx.cwd, criterionEntries, {
|
|
207
|
+
budgetTokens: criterionBudget,
|
|
208
|
+
limit: criterionLimit,
|
|
209
|
+
focusText: [query, ...intake.task.acceptanceCriteria].join("\n"),
|
|
210
|
+
excludePatterns: dependencies.contextExcludePatterns(ctx)
|
|
231
211
|
})
|
|
232
212
|
: undefined;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
213
|
+
const criterionReasonCode = !dependencies.autoContextEnabled
|
|
214
|
+
? "auto-context-disabled"
|
|
215
|
+
: intake?.task?.criterionGraph?.mode !== "criterion-graph"
|
|
216
|
+
? "criterion-graph-unavailable"
|
|
217
|
+
: criterionEntries.length === 0
|
|
218
|
+
? "no-candidates"
|
|
219
|
+
: !criterionContext?.selected.length ? "no-readable-selection" : "selected";
|
|
220
|
+
if (intake?.task) dependencies.telemetry(ctx, {
|
|
221
|
+
event: "criterion_context_pack", turnId: turn.turnId, selected: criterionContext?.selected.length ?? 0,
|
|
222
|
+
candidates: criterionEntries.length,
|
|
223
|
+
budgetTokens: criterionBudget,
|
|
224
|
+
estimatedTokens: criterionContext?.estimatedTokens ?? 0,
|
|
225
|
+
reasonCode: criterionReasonCode,
|
|
226
|
+
selectedPaths: criterionContext?.selected.map((entry) => entry.path) ?? []
|
|
236
227
|
});
|
|
237
|
-
const
|
|
228
|
+
const composedContext = criterionContext?.selected.length ? criterionContext : undefined;
|
|
229
|
+
const deliveredSelectedContext = criterionMode ? undefined : selectedContext;
|
|
230
|
+
const content = [deliveredSelectedContext?.content, intake?.text, composedContext?.text].filter(Boolean).join("\n\n");
|
|
231
|
+
const deliveryTask = intake?.task ?? activeTask;
|
|
232
|
+
const selectedPackPaths = deliveredSelectedContext?.customType === "piagent-context-pack-v2" && Array.isArray(deliveredSelectedContext.details.paths)
|
|
233
|
+
? deliveredSelectedContext.details.paths.filter((value): value is string => typeof value === "string")
|
|
234
|
+
: [];
|
|
235
|
+
const criterionPaths = composedContext?.selected.map((entry) => entry.path) ?? [];
|
|
236
|
+
const selectedPackItems = (deliveredSelectedContext?.details.selectedItems as ContextInjectionItem[] | undefined)
|
|
237
|
+
?? selectedPackPaths.map((path) => ({ path, estimatedTokens: 0 }));
|
|
238
|
+
const injectionItems: ContextInjectionItem[] = composedContext?.selected ?? selectedPackItems;
|
|
239
|
+
const deliveryEntries = new Map<string, { path: string; reason: string }>();
|
|
240
|
+
for (const filePath of selectedPackPaths) {
|
|
241
|
+
deliveryEntries.set(filePath, {
|
|
242
|
+
path: filePath,
|
|
243
|
+
reason: "Runtime confirmed delivery of a bounded Context Engine navigation pack."
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
for (const filePath of criterionPaths) {
|
|
247
|
+
deliveryEntries.set(filePath, {
|
|
248
|
+
path: filePath,
|
|
249
|
+
reason: "Runtime confirmed delivery of criterion-selected context."
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
const deliveryId = deliveryTask && deliveryEntries.size > 0 ? crypto.randomUUID() : undefined;
|
|
253
|
+
if (deliveryTask && deliveryId) {
|
|
254
|
+
const retrievalKey = typeof deliveredSelectedContext?.details.retrievalKey === "string" ? deliveredSelectedContext.details.retrievalKey : undefined;
|
|
255
|
+
stageContextDelivery(ctx, {
|
|
256
|
+
deliveryId,
|
|
257
|
+
taskRunId: deliveryTask.taskRunId,
|
|
258
|
+
turnId: turn.turnId,
|
|
259
|
+
entries: [...deliveryEntries.values()],
|
|
260
|
+
pack: retrievalKey
|
|
261
|
+
? {
|
|
262
|
+
retrievalKey,
|
|
263
|
+
queryHash: String(deliveredSelectedContext?.details.queryHash ?? ""),
|
|
264
|
+
confidence: String(deliveredSelectedContext?.details.confidence ?? "unknown"),
|
|
265
|
+
estimatedTokens: Number(deliveredSelectedContext?.details.estimatedTokens ?? 0),
|
|
266
|
+
paths: selectedPackPaths
|
|
267
|
+
}
|
|
268
|
+
: undefined,
|
|
269
|
+
injection: {
|
|
270
|
+
source: composedContext ? "criterion-pack" : deliveredSelectedContext?.customType === "piagent-context-pack-v2" ? "auto-pack" : "criterion-seed",
|
|
271
|
+
queryHash: String(deliveredSelectedContext?.details.queryHash ?? signal.promptHash),
|
|
272
|
+
confidence: String(deliveredSelectedContext?.details.confidence ?? (criterionPaths.length > 0 ? "high" : "unknown")),
|
|
273
|
+
estimatedTokens: Number(deliveredSelectedContext?.details.estimatedTokens ?? composedContext?.estimatedTokens ?? 0),
|
|
274
|
+
selectedItems: injectionItems
|
|
275
|
+
}
|
|
276
|
+
}, { state: dependencies.state, telemetry: dependencies.telemetry });
|
|
277
|
+
}
|
|
238
278
|
return {
|
|
239
279
|
...(systemPromptUpdate ?? {}),
|
|
240
280
|
message: {
|
|
241
|
-
customType:
|
|
281
|
+
customType: deliveredSelectedContext?.customType ?? "piagent-runtime-task-intake",
|
|
242
282
|
content,
|
|
243
283
|
display: false,
|
|
244
284
|
details: {
|
|
245
|
-
...(
|
|
285
|
+
...(deliveredSelectedContext?.details ?? {}),
|
|
286
|
+
...(composedContext ? {
|
|
287
|
+
schemaVersion: 1,
|
|
288
|
+
queryHash: signal.promptHash,
|
|
289
|
+
estimatedTokens: composedContext.estimatedTokens,
|
|
290
|
+
paths: composedContext.selected.map((entry) => entry.path),
|
|
291
|
+
selectedItems: composedContext.selected
|
|
292
|
+
} : {}),
|
|
293
|
+
contextDelivery: deliveryId ? { schemaVersion: 1, deliveryId } : undefined,
|
|
246
294
|
runtimeTask: intake?.task
|
|
247
295
|
? {
|
|
248
296
|
taskId: intake.task.taskId,
|
|
249
297
|
taskRunId: intake.task.taskRunId,
|
|
298
|
+
changeMode: intake.task.changeMode,
|
|
299
|
+
mutationPolicy: intake.task.mutationPolicy,
|
|
250
300
|
scope: intake.task.scope,
|
|
251
301
|
verifyCommands: intake.task.verifyCommands,
|
|
252
302
|
criterionGraph: intake.task.criterionGraph ? { mode: intake.task.criterionGraph.mode, graphDigest: intake.task.criterionGraph.graphDigest, nodes: intake.task.criterionGraph.nodes.length } : null,
|
|
253
303
|
intakeMode: intake.task.intakeMode
|
|
254
304
|
}
|
|
255
305
|
: undefined,
|
|
256
|
-
criterionContext:
|
|
257
|
-
paths:
|
|
306
|
+
criterionContext: composedContext ? {
|
|
307
|
+
paths: composedContext.selected.map((entry) => entry.path), estimatedTokens: composedContext.estimatedTokens
|
|
258
308
|
} : undefined,
|
|
259
309
|
runtimeIntakeStarted: intake?.started ?? false
|
|
260
310
|
}
|
|
@@ -263,6 +313,9 @@ export function registerAgentStartHook(pi: ExtensionAPI, dependencies: AgentStar
|
|
|
263
313
|
};
|
|
264
314
|
|
|
265
315
|
const packKey = dependencies.promptPackKey(ctx, signal.promptHash);
|
|
316
|
+
if (!autoPackUseful && activeTask?.trace.outcome === "pending" && query.length >= 20 && signal.workflow !== "usage" && dependencies.autoContextEnabled) {
|
|
317
|
+
await measureContextDeltaShadow({ ctx, query, turnId: turn.turnId, task: activeTask, mode: dependencies.contextDeltaShadowMode, protectedTarget, excludePatterns: dependencies.contextExcludePatterns(ctx), telemetry: dependencies.telemetry });
|
|
318
|
+
}
|
|
266
319
|
if (
|
|
267
320
|
query.length < 20
|
|
268
321
|
|| signal.workflow === "usage"
|
|
@@ -304,6 +357,7 @@ export function registerAgentStartHook(pi: ExtensionAPI, dependencies: AgentStar
|
|
|
304
357
|
if (!status.exists || status.stale) {
|
|
305
358
|
dependencies.telemetry(ctx, {
|
|
306
359
|
event: "context_pack",
|
|
360
|
+
turnId: turn.turnId,
|
|
307
361
|
queryHash: signal.promptHash,
|
|
308
362
|
confidence: "none",
|
|
309
363
|
candidates: 0,
|
|
@@ -348,6 +402,7 @@ export function registerAgentStartHook(pi: ExtensionAPI, dependencies: AgentStar
|
|
|
348
402
|
});
|
|
349
403
|
dependencies.telemetry(ctx, {
|
|
350
404
|
event: "context_pack",
|
|
405
|
+
turnId: turn.turnId,
|
|
351
406
|
queryHash: pack.queryHash,
|
|
352
407
|
confidence: pack.confidence,
|
|
353
408
|
candidates: pack.candidates,
|
|
@@ -379,10 +434,12 @@ export function registerAgentStartHook(pi: ExtensionAPI, dependencies: AgentStar
|
|
|
379
434
|
}
|
|
380
435
|
if (!contextPlanAcceptsConfidence(plan, pack.confidence) || pack.selected.length === 0) return finishAgentStart();
|
|
381
436
|
const memoryBudgetTokens = Math.max(0, plan.budgetTokens - pack.estimatedTokens);
|
|
382
|
-
const memoryHints =
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
437
|
+
const memoryHints = runtimeIntake
|
|
438
|
+
? { text: "", ids: [] }
|
|
439
|
+
: formatRepositoryMemoryHints(
|
|
440
|
+
selectRepositoryMemoryFacts(ctx.cwd, query, { limit: 2, excludePatterns }),
|
|
441
|
+
memoryBudgetTokens
|
|
442
|
+
);
|
|
386
443
|
dependencies.telemetry(ctx, {
|
|
387
444
|
event: "repository_memory_selected",
|
|
388
445
|
queryHash: signal.promptHash,
|
|
@@ -392,27 +449,29 @@ export function registerAgentStartHook(pi: ExtensionAPI, dependencies: AgentStar
|
|
|
392
449
|
estimatedTokens: estimateContextTokens(memoryHints.text),
|
|
393
450
|
planReceipt: plan.receipt
|
|
394
451
|
});
|
|
395
|
-
dependencies.state.rememberInjectedContextPack(ctx, dependencies.retrievalKey(ctx, query), {
|
|
396
|
-
queryHash: pack.queryHash,
|
|
397
|
-
confidence: pack.confidence,
|
|
398
|
-
estimatedTokens: pack.estimatedTokens,
|
|
399
|
-
paths: pack.selected.map((item) => item.path)
|
|
400
|
-
});
|
|
401
|
-
for (const selected of pack.selected) {
|
|
402
|
-
dependencies.state.rememberObservedContext(ctx, {
|
|
403
|
-
path: selected.path,
|
|
404
|
-
reason: "Runtime injected a bounded Context Engine navigation pack."
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
452
|
return finishAgentStart({
|
|
408
453
|
customType: "piagent-context-pack-v2",
|
|
409
454
|
content: [pack.text, memoryHints.text].filter(Boolean).join("\n\n"),
|
|
410
455
|
details: {
|
|
411
456
|
schemaVersion: 2,
|
|
412
457
|
queryHash: pack.queryHash,
|
|
458
|
+
retrievalKey: dependencies.retrievalKey(ctx, query),
|
|
413
459
|
confidence: pack.confidence,
|
|
414
460
|
estimatedTokens: pack.estimatedTokens,
|
|
415
461
|
paths: pack.selected.map((item) => item.path),
|
|
462
|
+
selectedItems: pack.selected.map((item) => ({
|
|
463
|
+
path: item.path,
|
|
464
|
+
estimatedTokens: item.estimatedTokens,
|
|
465
|
+
sources: item.sources,
|
|
466
|
+
links: item.links,
|
|
467
|
+
fileContentHash: item.fileContentHash,
|
|
468
|
+
...(item.sanitizedContentDigest ? { sanitizedContentDigest: item.sanitizedContentDigest } : {}),
|
|
469
|
+
payloadHash: item.payloadHash,
|
|
470
|
+
representation: item.representation,
|
|
471
|
+
ranges: item.ranges,
|
|
472
|
+
generation: item.generation,
|
|
473
|
+
sensitiveContentRedacted: item.sensitiveContentRedacted
|
|
474
|
+
})),
|
|
416
475
|
repositoryMemoryIds: memoryHints.ids,
|
|
417
476
|
currentSnapshot: plan.currentSnapshot,
|
|
418
477
|
contextPlan: plan
|
|
@@ -421,6 +480,7 @@ export function registerAgentStartHook(pi: ExtensionAPI, dependencies: AgentStar
|
|
|
421
480
|
} catch (error) {
|
|
422
481
|
dependencies.telemetry(ctx, {
|
|
423
482
|
event: "context_pack",
|
|
483
|
+
turnId: turn.turnId,
|
|
424
484
|
queryHash: signal.promptHash,
|
|
425
485
|
confidence: "none",
|
|
426
486
|
candidates: 0,
|
|
@@ -6,6 +6,7 @@ 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
11
|
import { runtimeLifecycleMode, workingTreeEvidenceDigest } from "../../extensions/task-lifecycle.js";
|
|
11
12
|
import { recordCompletionAudit } from "../../extensions/task-runtime-audit.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
|
|
@@ -298,7 +298,6 @@ export function registerCompletionHook(pi: ExtensionAPI, dependencies: Completio
|
|
|
298
298
|
projected = withRecoveryProvenance(ctx, projected, projectedGate, currentDigests, null);
|
|
299
299
|
task = writeTask(ctx.cwd, projected);
|
|
300
300
|
observeTrajectorySync(ctx, syncTrajectory?.(ctx, task, { sourceHook: "completion" }), telemetry);
|
|
301
|
-
state.cacheTaskIdentity(ctx, task);
|
|
302
301
|
state.clearPerformanceReview(task.taskRunId);
|
|
303
302
|
state.clearObservedContext(ctx);
|
|
304
303
|
activateBaseTools(ctx);
|
|
@@ -387,7 +386,7 @@ export function registerCompletionHook(pi: ExtensionAPI, dependencies: Completio
|
|
|
387
386
|
...verifierInstructions(gate.missingVerifyCommands),
|
|
388
387
|
"Do not broaden task scope, repeat a failed hypothesis, expand permission, or perform an external action."
|
|
389
388
|
]
|
|
390
|
-
: selectedRecovery.reasonCodes.includes("unknown-diagnostic-pass") || task.changeMode === "read-only"
|
|
389
|
+
: selectedRecovery.reasonCodes.includes("unknown-diagnostic-pass") || task.changeMode === "read-only" || task.mutationPolicy === "forbidden"
|
|
391
390
|
? [
|
|
392
391
|
...(gate.missingVerifyCommands.length > 0
|
|
393
392
|
? ["Run only the missing exact verifier commands against the current working tree.", ...verifierInstructions(gate.missingVerifyCommands)]
|