@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
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { changedFileAcceptanceCorpus, emptyAcceptanceCorpus, isAcceptanceTestPath } from "./acceptance-language-adapters.js";
|
|
4
|
+
import { durableContextEvidenceEntries, hasDurableContextEvidence } from "./context-evidence.js";
|
|
4
5
|
import { matchesAnyPath, normalizePathCandidate } from "./policy-core.js";
|
|
5
6
|
import { baselineReturnRepresentationConflicts, returnRepresentationGuidance } from "./return-contract.js";
|
|
6
7
|
import { hasLengthPrefixedIdentityKey, tenantAssertionSignals } from "./tenant-contract.js";
|
|
8
|
+
import { criterionBehaviorProofDisposition, criterionRequiresBehavioralProof, durableBehaviorProofRequired, genericCriterionEvidence, genericFallbackEvidence, isVerificationOnlyCriterion, verifierCommandsCoverTests } from "./acceptance-behavior-proof.js";
|
|
7
9
|
import { latestObservedVerificationEvidence, meaningfulVerificationCommands, verificationEvidenceProvesStableTree } from "./verification-intelligence.js";
|
|
8
10
|
import {
|
|
9
11
|
acceptanceContractProofGuidance,
|
|
@@ -33,7 +35,7 @@ const EVIDENCE_FIELDS = new Set(["kind", "summary", "paths", "command", "exitCod
|
|
|
33
35
|
const PROVENANCE_FIELDS = new Set(["assurance", "disposition", "repairCount", "retryCount", "finalRecoveryDisposition", "failureRef", "recoveryRef", "handoffRef", "recordedAt"]);
|
|
34
36
|
const FAILURE_REF_FIELDS = new Set(["evidenceDigest", "category", "captureRef"]);
|
|
35
37
|
const RECOVERY_REF_FIELDS = new Set(["policyVersion", "action", "reasonCodes"]);
|
|
36
|
-
const HELPER_USAGE_FIELDS = new Set(["mode", "used", "reasonCodes", "helpers", "recordedAt"]);
|
|
38
|
+
const HELPER_USAGE_FIELDS = new Set(["mode", "used", "decision", "projectedSavingsRatio", "reasonCodes", "helpers", "recordedAt"]);
|
|
37
39
|
const HELPER_ENTRY_FIELDS = new Set(["role", "disposition", "requestRef", "outputDigest", "calls", "tokens"]);
|
|
38
40
|
const HELPER_ROLES = new Set(["retriever", "scout", "planner", "worker", "reviewer", "oracle", "researcher"]);
|
|
39
41
|
const RECEIPT_DISPOSITIONS = new Set(["first-pass-success", "repaired-success", "blocked", "partial", "failed", "pending"]);
|
|
@@ -42,7 +44,7 @@ const RECOVERY_ACTIONS = new Set(["repair", "retry", "fresh-session", "ask-opera
|
|
|
42
44
|
const FAILURE_CATEGORIES = new Set(["passed", "compile-typecheck", "test-assertion", "lint-format", "dependency-config", "environment", "provider-network", "permission-policy", "scope-protected-path", "flaky-infrastructure", "unknown"]);
|
|
43
45
|
const HASH = /^[a-f0-9]{64}$/;
|
|
44
46
|
const SAFE_REF = /^[a-z0-9.][a-z0-9:._/-]{0,511}$/i;
|
|
45
|
-
const READ_ONLY_BOUNDARY = /\b(?:read-only|no
|
|
47
|
+
const READ_ONLY_BOUNDARY = /\b(?:read-only|no\s+(?:code|source|project|file|workspace|repo(?:sitory)?)?\s*(?:edits?|changes?|mutations?)|do not\s+(?:edit|change|modify|mutate|touch)(?: files?| source| project| repo| workspace)?|leave\s+(?:the\s+)?(?:source|project|repo|workspace)\s+(?:unchanged|unmodified)|khong\s+(?:sua|edit|thay\s+doi)(?: file| source| project)?)\b/;
|
|
46
48
|
|
|
47
49
|
function sha256(value) {
|
|
48
50
|
return crypto.createHash("sha256").update(String(value ?? "")).digest("hex");
|
|
@@ -79,11 +81,9 @@ function normalizedText(value) {
|
|
|
79
81
|
.replace(/[\u0300-\u036f]/g, "")
|
|
80
82
|
.toLowerCase();
|
|
81
83
|
}
|
|
82
|
-
|
|
83
84
|
function includesAny(text, patterns) {
|
|
84
85
|
return patterns.some((pattern) => pattern.test(text));
|
|
85
86
|
}
|
|
86
|
-
|
|
87
87
|
function pathBoundaryMentioned(text, patterns) {
|
|
88
88
|
const value = normalizedText(text);
|
|
89
89
|
return uniqueStrings(patterns).some((pattern) => {
|
|
@@ -94,32 +94,70 @@ function pathBoundaryMentioned(text, patterns) {
|
|
|
94
94
|
return value.includes(lower) || (Boolean(basename) && value.includes(basename));
|
|
95
95
|
});
|
|
96
96
|
}
|
|
97
|
-
|
|
97
|
+
function readOnlyBoundaryTiedToPattern(text, patterns) {
|
|
98
|
+
return normalizedText(text)
|
|
99
|
+
.split(/(?:\r?\n+|[.!?;]+|\s+[—–]\s+)/)
|
|
100
|
+
.some((clause) => READ_ONLY_BOUNDARY.test(clause) && pathBoundaryMentioned(clause, patterns));
|
|
101
|
+
}
|
|
98
102
|
function changedFilesRespectBoundaries(changedFiles, boundaryPatterns) {
|
|
99
103
|
const patterns = uniqueStrings(boundaryPatterns);
|
|
100
104
|
if (patterns.length === 0) return true;
|
|
101
105
|
return uniqueStrings(changedFiles).every((file) => !matchesAnyPath(file, patterns));
|
|
102
106
|
}
|
|
107
|
+
function acceptanceReadOnlyInferenceOptions(input, text) {
|
|
108
|
+
const boundaryPatterns = uniqueStrings([
|
|
109
|
+
...(Array.isArray(input?.outOfScope) ? input.outOfScope : []),
|
|
110
|
+
...(Array.isArray(input?.protectedPaths) ? input.protectedPaths : [])
|
|
111
|
+
]);
|
|
112
|
+
return {
|
|
113
|
+
mutationPolicy: input?.mutationPolicy,
|
|
114
|
+
readOnlyBoundary: boundaryPatterns.length > 0
|
|
115
|
+
&& readOnlyBoundaryTiedToPattern(text, boundaryPatterns)
|
|
116
|
+
};
|
|
117
|
+
}
|
|
103
118
|
|
|
104
|
-
export function inferAcceptanceObligations(text, changeMode = "source-change") {
|
|
119
|
+
export function inferAcceptanceObligations(text, changeMode = "source-change", options = {}) {
|
|
105
120
|
const value = normalizedText(text);
|
|
121
|
+
const accessControlText = value
|
|
122
|
+
.replace(/`[^`\n]*`/g, " ")
|
|
123
|
+
.replace(/\b(?:[a-z0-9_.@-]+\/)+[a-z0-9_.@/-]+\b/g, " ");
|
|
106
124
|
const obligations = [];
|
|
107
|
-
if (changeMode === "read-only" ||
|
|
125
|
+
if (changeMode === "read-only" || options.mutationPolicy === "forbidden" || options.readOnlyBoundary === true) {
|
|
108
126
|
obligations.push("read-only-evidence");
|
|
109
127
|
}
|
|
110
|
-
const
|
|
111
|
-
/\
|
|
128
|
+
const actorAccessControl = includesAny(accessControlText, [
|
|
129
|
+
/\b(?:admins?|roles?|owners?|users?|callers?|resources?)\b[\s\S]{0,80}\b(?:access|allow(?:ed)?|deny|denied|block(?:ed)?|forbid(?:den)?|manag(?:e|es|ed|ing))\b/,
|
|
130
|
+
/\b(?:access|allow(?:ed)?|deny|denied|block(?:ed)?|forbid(?:den)?|manag(?:e|es|ed|ing))\b[\s\S]{0,80}\b(?:admins?|roles?|owners?|users?|callers?|resources?)\b/
|
|
112
131
|
]);
|
|
113
|
-
const
|
|
132
|
+
const explicitAuthorization = includesAny(accessControlText, [
|
|
133
|
+
/\bauth(?:orization)?\b/, /\bunauthoriz(?:ed|ation)\b/, /\bpermission\b/
|
|
134
|
+
]) || actorAccessControl;
|
|
135
|
+
const ownerAccessControl = /\bowner\b/.test(accessControlText) && includesAny(accessControlText, [
|
|
114
136
|
/\busers?\b/, /\bresources?\b/, /\baccess\b/, /\bmanag(?:e|es|ed|ing)\b/, /\bauth(?:orization)?\b/, /\bpermission\b/, /\broles?\b/
|
|
115
137
|
]);
|
|
116
138
|
if (explicitAuthorization || ownerAccessControl) {
|
|
117
139
|
obligations.push("authorization-deny-case");
|
|
118
140
|
}
|
|
119
|
-
|
|
120
|
-
|
|
141
|
+
const tenantMentioned = includesAny(value, [/\btenants?\b/, /\bcross[- ]tenant\b/, /\bsame[- ]tenant\b/, /\btenantid\b/]);
|
|
142
|
+
const tenantStorage = tenantMentioned && includesAny(value, [
|
|
143
|
+
/\bcache\b/, /\bcache[- ]?key\b/, /\bstorage\b/, /\bcollision\b/, /\bentity\b/, /\bsame tuple\b/
|
|
144
|
+
]);
|
|
145
|
+
const strongAuthorization = includesAny(accessControlText, [
|
|
146
|
+
/\bauth(?:orization)?\b/, /\bunauthoriz(?:ed|ation)\b/, /\bpermission\b/
|
|
147
|
+
]);
|
|
148
|
+
const tenantActorAccess = tenantMentioned && actorAccessControl;
|
|
149
|
+
const explicitTenantAccessBoundary = includesAny(value, [
|
|
150
|
+
/\bcross[- ]tenant\b/, /\bsame[- ]tenant\b/, /\btenant boundary\b/,
|
|
151
|
+
/\btenantid\b[\s\S]{0,100}\b(?:equal|match|same non-empty|access|allow|deny|block|forbid)/,
|
|
152
|
+
/\b(?:access|allow|deny|block|forbid)[\s\S]{0,100}\btenantid\b/
|
|
153
|
+
]) && includesAny(value, [
|
|
154
|
+
/\baccess\b/, /\ballow(?:ed)?\b/, /\b(?:deny|denied)\b/, /\bblock(?:ed)?\b/, /\bforbid(?:den)?\b/,
|
|
155
|
+
/\bequal\b/, /\bmatch(?:es|ed|ing)?\b/, /\bsame non-empty\b/
|
|
156
|
+
]);
|
|
157
|
+
if (tenantMentioned) {
|
|
158
|
+
if (tenantStorage) {
|
|
121
159
|
obligations.push("tenant-storage-isolation");
|
|
122
|
-
} else {
|
|
160
|
+
} else if (strongAuthorization || ownerAccessControl || tenantActorAccess || explicitTenantAccessBoundary) {
|
|
123
161
|
obligations.push("tenant-boundary");
|
|
124
162
|
}
|
|
125
163
|
}
|
|
@@ -167,7 +205,6 @@ const GENERATED_ACCEPTANCE_TEXTS = new Set([
|
|
|
167
205
|
"authorization-deny-case", "tenant-boundary", "tenant-storage-isolation", "invalid-input-rejection", "boundary-case",
|
|
168
206
|
"backward-compatibility", "read-only-evidence", "verification-evidence"
|
|
169
207
|
].map((obligation) => generatedCriterionForObligation(obligation)));
|
|
170
|
-
|
|
171
208
|
function acceptanceTaskText(task) {
|
|
172
209
|
return [
|
|
173
210
|
task?.summary,
|
|
@@ -203,8 +240,9 @@ function semanticConflictReasons(obligation, task, corpus, criterion) {
|
|
|
203
240
|
|
|
204
241
|
/**
|
|
205
242
|
* Surface a concrete existing return contract before implementation starts.
|
|
206
|
-
* This is intentionally source-derived and bounded to exact
|
|
207
|
-
*
|
|
243
|
+
* This is intentionally source-derived and bounded to exact known files; it
|
|
244
|
+
* does not turn the task's initial focus into write authority or guess from
|
|
245
|
+
* benchmark scenario names and hidden expectations.
|
|
208
246
|
*/
|
|
209
247
|
export function acceptanceBaselineGuidance(task, options = {}) {
|
|
210
248
|
if (!options.cwd) return [];
|
|
@@ -223,7 +261,11 @@ export function acceptanceSemanticConflicts(task, options = {}) {
|
|
|
223
261
|
: { ...emptyAcceptanceCorpus(changedFiles.length > 0 ? changedFiles : ["inline.js"]), sourceText: normalizedText(options.sourceText), allText: normalizedText(options.sourceText) };
|
|
224
262
|
if (!corpus.adapter.proofCapable) return [];
|
|
225
263
|
const obligations = task?.acceptanceReceipt?.criteria?.map((criterion) => criterion.obligation)
|
|
226
|
-
?? inferAcceptanceObligations(
|
|
264
|
+
?? inferAcceptanceObligations(
|
|
265
|
+
acceptanceTaskText(task),
|
|
266
|
+
task?.changeMode,
|
|
267
|
+
acceptanceReadOnlyInferenceOptions(task, acceptanceTaskText(task))
|
|
268
|
+
);
|
|
227
269
|
return uniqueStrings([
|
|
228
270
|
...obligations.flatMap((obligation) => semanticConflictReasons(obligation, task, corpus)),
|
|
229
271
|
...(options.cwd ? baselineReturnRepresentationConflicts(acceptanceTaskText(task), options.cwd, corpus.sourceFiles) : [])
|
|
@@ -234,7 +276,6 @@ function criterionId(text, obligation, index) {
|
|
|
234
276
|
const prefix = compactId(obligation ?? "criterion").slice(0, 24);
|
|
235
277
|
return `ac-${String(index + 1).padStart(2, "0")}-${prefix}-${sha256(text).slice(0, 8)}`.slice(0, 80);
|
|
236
278
|
}
|
|
237
|
-
|
|
238
279
|
export function buildAcceptanceReceipt(input = {}) {
|
|
239
280
|
const changeMode = input.changeMode === "read-only" ? "read-only" : "source-change";
|
|
240
281
|
const baseText = [
|
|
@@ -242,12 +283,20 @@ export function buildAcceptanceReceipt(input = {}) {
|
|
|
242
283
|
input.expectedOutput,
|
|
243
284
|
...(Array.isArray(input.acceptanceCriteria) ? input.acceptanceCriteria : [])
|
|
244
285
|
].filter(Boolean).join("\n");
|
|
245
|
-
const obligations = inferAcceptanceObligations(
|
|
286
|
+
const obligations = inferAcceptanceObligations(
|
|
287
|
+
baseText,
|
|
288
|
+
changeMode,
|
|
289
|
+
acceptanceReadOnlyInferenceOptions(input, baseText)
|
|
290
|
+
);
|
|
246
291
|
const texts = uniqueStrings(Array.isArray(input.acceptanceCriteria) ? input.acceptanceCriteria : []);
|
|
247
292
|
const generatedObligations = new Map();
|
|
248
293
|
for (const obligation of obligations) {
|
|
249
294
|
const generated = generatedCriterionForObligation(obligation);
|
|
250
|
-
if (!texts.some((text) => inferAcceptanceObligations(
|
|
295
|
+
if (!texts.some((text) => inferAcceptanceObligations(
|
|
296
|
+
text,
|
|
297
|
+
changeMode,
|
|
298
|
+
acceptanceReadOnlyInferenceOptions(input, text)
|
|
299
|
+
).includes(obligation))) {
|
|
251
300
|
texts.push(generated);
|
|
252
301
|
generatedObligations.set(generated, obligation);
|
|
253
302
|
}
|
|
@@ -258,17 +307,23 @@ export function buildAcceptanceReceipt(input = {}) {
|
|
|
258
307
|
: generatedCriterionForObligation("verification-evidence"));
|
|
259
308
|
}
|
|
260
309
|
const acceptanceCriteria = texts.slice(0, MAX_CRITERIA);
|
|
310
|
+
const durableBehaviorProof = durableBehaviorProofRequired(baseText, changeMode);
|
|
261
311
|
const criteria = acceptanceCriteria.map((text, index) => {
|
|
262
|
-
const inferred = inferAcceptanceObligations(
|
|
312
|
+
const inferred = inferAcceptanceObligations(
|
|
313
|
+
text,
|
|
314
|
+
changeMode,
|
|
315
|
+
acceptanceReadOnlyInferenceOptions(input, text)
|
|
316
|
+
);
|
|
263
317
|
const obligation = generatedObligations.get(text)
|
|
264
318
|
?? inferred.find((item) => item !== "verification-evidence" && item !== "backward-compatibility")
|
|
265
|
-
??
|
|
319
|
+
?? (isVerificationOnlyCriterion(text) ? "verification-evidence" : undefined)
|
|
320
|
+
?? (inferred.includes("backward-compatibility") ? "backward-compatibility" : undefined)
|
|
266
321
|
?? "requested-behavior";
|
|
267
322
|
return {
|
|
268
323
|
id: criterionId(text, obligation, index),
|
|
269
324
|
hash: sha256(text),
|
|
270
325
|
obligation,
|
|
271
|
-
priority: CRITICAL_OBLIGATIONS.has(obligation) ? "critical" : "normal",
|
|
326
|
+
priority: CRITICAL_OBLIGATIONS.has(obligation) || (durableBehaviorProof && obligation !== "verification-evidence") ? "critical" : "normal",
|
|
272
327
|
status: "pending",
|
|
273
328
|
evidence: []
|
|
274
329
|
};
|
|
@@ -327,20 +382,30 @@ export function normalizeAcceptanceReceipt(value) {
|
|
|
327
382
|
|
|
328
383
|
function normalizeHelperUsage(value) {
|
|
329
384
|
if (!isRecord(value) || !["off", "recommend", "on"].includes(value.mode)) return undefined;
|
|
330
|
-
const
|
|
385
|
+
const rawHelpers = Array.isArray(value.helpers) ? value.helpers.slice(0, 3).filter(isRecord) : [];
|
|
386
|
+
const helpers = rawHelpers.map((item) => ({
|
|
331
387
|
role: HELPER_ROLES.has(item.role) ? item.role : "scout",
|
|
332
388
|
disposition: compactId(item.disposition ?? "unknown"),
|
|
333
389
|
requestRef: HASH.test(String(item.requestRef)) ? item.requestRef : sha256(item.requestRef),
|
|
334
390
|
outputDigest: item.outputDigest === null || HASH.test(String(item.outputDigest)) ? item.outputDigest : null,
|
|
335
391
|
calls: Number.isInteger(item.calls) ? Math.max(0, Math.min(100, item.calls)) : 0,
|
|
336
392
|
tokens: Number.isInteger(item.tokens) ? Math.max(0, Math.min(100_000_000, item.tokens)) : 0
|
|
337
|
-
}))
|
|
338
|
-
|
|
393
|
+
}));
|
|
394
|
+
const used = helpers.some((item) => !["solo", "recommend", "unavailable", "blocked"].includes(item.disposition));
|
|
395
|
+
const helperDecision = rawHelpers.find((item) => ["dispatch", "skip"].includes(item.decision))?.decision;
|
|
396
|
+
const decision = ["dispatch", "skip"].includes(value.decision) ? value.decision : helperDecision ?? (used ? "dispatch" : "skip");
|
|
397
|
+
const rawProjectedSavings = typeof value.projectedSavingsRatio === "number"
|
|
398
|
+
? value.projectedSavingsRatio
|
|
399
|
+
: rawHelpers.find((item) => typeof item.projectedSavingsRatio === "number")?.projectedSavingsRatio;
|
|
400
|
+
const projectedSavingsRatio = typeof rawProjectedSavings === "number" && Number.isFinite(rawProjectedSavings)
|
|
401
|
+
? Math.max(-10, Math.min(1, rawProjectedSavings))
|
|
402
|
+
: null;
|
|
403
|
+
return { mode: value.mode, used, decision, projectedSavingsRatio, reasonCodes: uniqueStrings(value.reasonCodes).map(compactId).slice(0, 16), helpers, recordedAt: validTimestamp(value.recordedAt) ? value.recordedAt : new Date().toISOString() };
|
|
339
404
|
}
|
|
340
405
|
|
|
341
406
|
export function applyAcceptanceHelperUsage(task, input = {}) {
|
|
342
407
|
const receipt = normalizeAcceptanceReceipt(task?.acceptanceReceipt); if (!receipt) return task;
|
|
343
|
-
const helperUsage = normalizeHelperUsage({ mode: input.mode ?? "off", reasonCodes: input.reasonCodes ?? [], helpers: input.helpers ?? [], recordedAt: input.recordedAt ?? new Date().toISOString() });
|
|
408
|
+
const helperUsage = normalizeHelperUsage({ mode: input.mode ?? "off", decision: input.decision, projectedSavingsRatio: input.projectedSavingsRatio, reasonCodes: input.reasonCodes ?? [], helpers: input.helpers ?? [], recordedAt: input.recordedAt ?? new Date().toISOString() });
|
|
344
409
|
return { ...task, acceptanceReceipt: { ...receipt, criteria: structuredClone(task.acceptanceReceipt.criteria), helperUsage } };
|
|
345
410
|
}
|
|
346
411
|
|
|
@@ -609,8 +674,8 @@ function hasStructuredCompositeIdentity(sourceText) {
|
|
|
609
674
|
return jsonTuple || nestedLookup || hasLengthPrefixedIdentityKey(text);
|
|
610
675
|
}
|
|
611
676
|
|
|
612
|
-
function focusedContractEvidence(obligation, task, corpus, verifierEvidence, criterion) {
|
|
613
|
-
if (!verifierEvidence || corpus.sourceFiles.length === 0 || corpus.testFiles
|
|
677
|
+
function focusedContractEvidence(obligation, task, corpus, verifierEvidence, criterion, cwd) {
|
|
678
|
+
if (!verifierEvidence || corpus.sourceFiles.length === 0 || !verifierCommandsCoverTests(task, corpus.testFiles, cwd)) return undefined;
|
|
614
679
|
const targets = namedCodeTargets(task, criterion, corpus.sourceText);
|
|
615
680
|
const targetCoverage = targets.length === 0 || targets.every((target) => (
|
|
616
681
|
new RegExp(`\\b${escapeRegex(target.toLowerCase())}\\b`).test(corpus.testText)
|
|
@@ -657,7 +722,7 @@ function hasCurrentPassingVerifier(task, currentWorkingTreeDigest) {
|
|
|
657
722
|
});
|
|
658
723
|
}
|
|
659
724
|
|
|
660
|
-
function evidenceForObligation(obligation, task, corpus, currentWorkingTreeDigest, criterion) {
|
|
725
|
+
function evidenceForObligation(obligation, task, corpus, currentWorkingTreeDigest, criterion, cwd) {
|
|
661
726
|
const passingVerifier = hasCurrentPassingVerifier(task, currentWorkingTreeDigest);
|
|
662
727
|
const latestVerifyEvidence = latestObservedVerificationEvidence(task?.verifyEvidence);
|
|
663
728
|
const verifyEvidence = meaningfulVerificationCommands(task?.verifyCommands ?? [])
|
|
@@ -674,14 +739,14 @@ function evidenceForObligation(obligation, task, corpus, currentWorkingTreeDiges
|
|
|
674
739
|
if (semanticConflictReasons(obligation, task, corpus, criterion).length > 0) return undefined;
|
|
675
740
|
|
|
676
741
|
if (obligation === "read-only-evidence") {
|
|
677
|
-
const
|
|
742
|
+
const readOnlyEvidence = durableContextEvidenceEntries(task);
|
|
743
|
+
const readOnlyOk = (task.changeMode === "read-only" || task.mutationPolicy === "forbidden")
|
|
678
744
|
&& corpus.files.length === 0
|
|
679
|
-
&&
|
|
680
|
-
&& task.contextManifest.length > 0;
|
|
745
|
+
&& hasDurableContextEvidence(task);
|
|
681
746
|
if (readOnlyOk) return {
|
|
682
747
|
kind: "read-only-context",
|
|
683
748
|
summary: "Read-only context was observed and no project files changed.",
|
|
684
|
-
paths:
|
|
749
|
+
paths: readOnlyEvidence.map((item) => item.path).slice(0, 8)
|
|
685
750
|
};
|
|
686
751
|
if (task.changeMode === "source-change") {
|
|
687
752
|
const boundaryPatterns = uniqueStrings([...(task.outOfScope ?? []), ...(task.protectedPaths ?? [])]);
|
|
@@ -692,11 +757,10 @@ function evidenceForObligation(obligation, task, corpus, currentWorkingTreeDiges
|
|
|
692
757
|
].filter(Boolean).join("\n");
|
|
693
758
|
const combinedText = `${taskText}\n${corpus.allText}`;
|
|
694
759
|
const sourceChangeReadOnlyOk = corpus.files.length > 0
|
|
695
|
-
&&
|
|
760
|
+
&& boundaryPatterns.length > 0
|
|
761
|
+
&& readOnlyBoundaryTiedToPattern(combinedText, boundaryPatterns)
|
|
696
762
|
&& changedFilesRespectBoundaries(corpus.files, boundaryPatterns)
|
|
697
|
-
&& (
|
|
698
|
-
&& Array.isArray(task.contextManifest)
|
|
699
|
-
&& task.contextManifest.length > 0;
|
|
763
|
+
&& hasDurableContextEvidence(task);
|
|
700
764
|
if (sourceChangeReadOnlyOk) {
|
|
701
765
|
return {
|
|
702
766
|
kind: "source-change-read-only-boundary",
|
|
@@ -709,23 +773,21 @@ function evidenceForObligation(obligation, task, corpus, currentWorkingTreeDiges
|
|
|
709
773
|
return undefined;
|
|
710
774
|
}
|
|
711
775
|
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
return verifierEvidence;
|
|
715
|
-
}
|
|
776
|
+
const generic = genericCriterionEvidence({ obligation, task, criterion, taskText: acceptanceTaskText(task), corpus, verifierEvidence, passingVerifier, cwd });
|
|
777
|
+
if (generic.handled) return generic.evidence;
|
|
716
778
|
|
|
717
779
|
if (!corpus.adapter.proofCapable) return undefined;
|
|
718
780
|
|
|
719
781
|
if (obligation === "tenant-boundary") {
|
|
720
|
-
return focusedContractEvidence(obligation, task, corpus, verifierEvidence, criterion);
|
|
782
|
+
return focusedContractEvidence(obligation, task, corpus, verifierEvidence, criterion, cwd);
|
|
721
783
|
}
|
|
722
784
|
|
|
723
785
|
if (obligation === "tenant-storage-isolation") {
|
|
724
|
-
return focusedContractEvidence(obligation, task, corpus, verifierEvidence, criterion);
|
|
786
|
+
return focusedContractEvidence(obligation, task, corpus, verifierEvidence, criterion, cwd);
|
|
725
787
|
}
|
|
726
788
|
|
|
727
789
|
if (obligation === "authorization-deny-case") {
|
|
728
|
-
return focusedContractEvidence(obligation, task, corpus, verifierEvidence, criterion);
|
|
790
|
+
return focusedContractEvidence(obligation, task, corpus, verifierEvidence, criterion, cwd);
|
|
729
791
|
}
|
|
730
792
|
|
|
731
793
|
if (obligation === "invalid-input-rejection") {
|
|
@@ -738,7 +800,7 @@ function evidenceForObligation(obligation, task, corpus, currentWorkingTreeDiges
|
|
|
738
800
|
namedTargets: namedCodeTargets(task, criterion, corpus.sourceText),
|
|
739
801
|
provenanceTargets: explicitlyCallableTargets(task, criterion, corpus.sourceText)
|
|
740
802
|
});
|
|
741
|
-
if (passingVerifier && corpus.sourceFiles.length > 0 && corpus.testFiles
|
|
803
|
+
if (passingVerifier && corpus.sourceFiles.length > 0 && verifierCommandsCoverTests(task, corpus.testFiles, cwd) && sourceOk && testOk) {
|
|
742
804
|
return {
|
|
743
805
|
...verifierEvidence,
|
|
744
806
|
kind: "verifier-backed-focused-test",
|
|
@@ -756,7 +818,7 @@ function evidenceForObligation(obligation, task, corpus, currentWorkingTreeDiges
|
|
|
756
818
|
const sourceOk = /math\.ceil|ceil|clamp|min|max|round|zero|return\s+0|\?\?|nullish|falsey|falsy|default|retrylimit|enabled|label/.test(corpus.sourceText)
|
|
757
819
|
|| expirySourceOk
|
|
758
820
|
|| (passingVerifier && corpus.sourceFiles.length > 0 && testOk);
|
|
759
|
-
if (passingVerifier && corpus.sourceFiles.length > 0 && corpus.testFiles
|
|
821
|
+
if (passingVerifier && corpus.sourceFiles.length > 0 && verifierCommandsCoverTests(task, corpus.testFiles, cwd) && sourceOk && testOk) {
|
|
760
822
|
return {
|
|
761
823
|
...verifierEvidence,
|
|
762
824
|
kind: "verifier-backed-focused-test",
|
|
@@ -767,12 +829,12 @@ function evidenceForObligation(obligation, task, corpus, currentWorkingTreeDiges
|
|
|
767
829
|
return undefined;
|
|
768
830
|
}
|
|
769
831
|
|
|
770
|
-
return
|
|
832
|
+
return genericFallbackEvidence({ behavioral: generic.behavioral, corpus, verifierEvidence, passingVerifier });
|
|
771
833
|
}
|
|
772
834
|
|
|
773
835
|
export function refreshAcceptanceReceipt(task, options = {}) {
|
|
774
836
|
const receipt = normalizeAcceptanceReceipt(task?.acceptanceReceipt);
|
|
775
|
-
if (!receipt) return { task, missing: [], criticalMissing: [], changed: false };
|
|
837
|
+
if (!receipt) return { task, missing: [], criticalMissing: [], adapterAbstained: [], changed: false };
|
|
776
838
|
const cwd = options.cwd;
|
|
777
839
|
const changedFiles = uniqueStrings(options.changedFiles ?? task.changedFiles ?? task.observedChangedFiles ?? []);
|
|
778
840
|
const currentWorkingTreeDigest = options.currentWorkingTreeDigest;
|
|
@@ -787,7 +849,7 @@ export function refreshAcceptanceReceipt(task, options = {}) {
|
|
|
787
849
|
criterion.evidence = [];
|
|
788
850
|
const evidence = task?.workingTreeDigestAlgorithm === WORKING_TREE_DIGEST_ALGORITHM
|
|
789
851
|
&& isCurrentWorkingTreeDigest(currentWorkingTreeDigest)
|
|
790
|
-
? evidenceForObligation(criterion.obligation, task, corpus, currentWorkingTreeDigest, criterion)
|
|
852
|
+
? evidenceForObligation(criterion.obligation, task, corpus, currentWorkingTreeDigest, criterion, cwd)
|
|
791
853
|
: undefined;
|
|
792
854
|
if (evidence) addEvidence(criterion, evidence, recordedAt);
|
|
793
855
|
const nextEvidence = (criterion.evidence ?? []).map(evidenceKey);
|
|
@@ -795,17 +857,16 @@ export function refreshAcceptanceReceipt(task, options = {}) {
|
|
|
795
857
|
continue;
|
|
796
858
|
}
|
|
797
859
|
if (criterion.status === "satisfied") continue;
|
|
798
|
-
const evidence = evidenceForObligation(criterion.obligation, task, corpus, currentWorkingTreeDigest, criterion);
|
|
860
|
+
const evidence = evidenceForObligation(criterion.obligation, task, corpus, currentWorkingTreeDigest, criterion, cwd);
|
|
799
861
|
if (evidence) changed = addEvidence(criterion, evidence, recordedAt) || changed;
|
|
800
862
|
}
|
|
801
863
|
const missing = receipt.criteria.filter((criterion) => criterion.status !== "satisfied");
|
|
802
|
-
const
|
|
864
|
+
const passingVerifier = hasCurrentPassingVerifier(task, currentWorkingTreeDigest);
|
|
865
|
+
const adapterAbstained = missing.filter((criterion) => criterionBehaviorProofDisposition({ obligation: criterion.obligation, task, criterion, taskText: acceptanceTaskText(task), corpus, passingVerifier }) === "unknown");
|
|
866
|
+
const criticalMissing = missing.filter((criterion) => (criterion.priority === "critical" || criterionRequiresBehavioralProof(task, criterion, acceptanceTaskText(task))
|
|
867
|
+
));
|
|
803
868
|
return {
|
|
804
|
-
task: { ...task, acceptanceReceipt: receipt },
|
|
805
|
-
receipt,
|
|
806
|
-
missing,
|
|
807
|
-
criticalMissing,
|
|
808
|
-
changed
|
|
869
|
+
task: { ...task, acceptanceReceipt: receipt }, receipt, missing, criticalMissing, adapterAbstained, changed
|
|
809
870
|
};
|
|
810
871
|
}
|
|
811
872
|
|
|
@@ -827,9 +888,12 @@ export function acceptanceCriticalRecoveryProjection(task, options = {}) {
|
|
|
827
888
|
const verifierCurrent = hasCurrentPassingVerifier(task, currentWorkingTreeDigest);
|
|
828
889
|
const projections = [];
|
|
829
890
|
for (const criterion of receipt.criteria.filter((item) => item.priority === "critical")) {
|
|
891
|
+
const disposition = criterionBehaviorProofDisposition({ obligation: criterion.obligation, task, criterion, taskText: acceptanceTaskText(task), corpus, passingVerifier: verifierCurrent });
|
|
830
892
|
const criterionText = (Array.isArray(task?.acceptanceCriteria) ? task.acceptanceCriteria : [])
|
|
831
893
|
.find((text) => typeof text === "string" && sha256(text) === criterion.hash && !GENERATED_ACCEPTANCE_TEXTS.has(text));
|
|
832
|
-
if (!criterionText
|
|
894
|
+
if (!criterionText) continue;
|
|
895
|
+
if (disposition === "unknown") { projections.push({ criterionId: criterion.id, criterionHash: criterion.hash, criterionText: criterionText.slice(0, 700), targets: [], missingDimensions: ["adapter-linkage"], proofHints: ["Add a focused executable test with a direct relative import to the changed source, or configure a deterministic language adapter that resolves this helper/barrel path; then rerun the exact verifier."] }); continue; }
|
|
896
|
+
if (evidenceForObligation(criterion.obligation, task, corpus, currentWorkingTreeDigest, criterion, cwd)) continue;
|
|
833
897
|
const targets = namedCodeTargets(task, criterion, corpus.sourceText);
|
|
834
898
|
const missingDimensions = [];
|
|
835
899
|
if (!verifierCurrent) missingDimensions.push("current-verifier");
|
|
@@ -879,7 +943,7 @@ export function acceptanceReceiptValidationErrors(value) {
|
|
|
879
943
|
}
|
|
880
944
|
if (value.helperUsage !== undefined) {
|
|
881
945
|
const usage = value.helperUsage;
|
|
882
|
-
if (!isRecord(usage) || hasUnsupportedField(usage, HELPER_USAGE_FIELDS) || !["off", "recommend", "on"].includes(usage.mode) || typeof usage.used !== "boolean" || !Array.isArray(usage.reasonCodes) || usage.reasonCodes.length > 16 || usage.reasonCodes.some((item) => typeof item !== "string" || compactId(item) !== item) || !Array.isArray(usage.helpers) || usage.helpers.length > 3 || !validTimestamp(usage.recordedAt)) errors.push("acceptanceReceipt helperUsage is invalid");
|
|
946
|
+
if (!isRecord(usage) || hasUnsupportedField(usage, HELPER_USAGE_FIELDS) || !["off", "recommend", "on"].includes(usage.mode) || typeof usage.used !== "boolean" || (usage.decision !== undefined && !["dispatch", "skip"].includes(usage.decision)) || (usage.projectedSavingsRatio !== undefined && usage.projectedSavingsRatio !== null && (typeof usage.projectedSavingsRatio !== "number" || !Number.isFinite(usage.projectedSavingsRatio) || usage.projectedSavingsRatio < -10 || usage.projectedSavingsRatio > 1)) || !Array.isArray(usage.reasonCodes) || usage.reasonCodes.length > 16 || usage.reasonCodes.some((item) => typeof item !== "string" || compactId(item) !== item) || !Array.isArray(usage.helpers) || usage.helpers.length > 3 || !validTimestamp(usage.recordedAt)) errors.push("acceptanceReceipt helperUsage is invalid");
|
|
883
947
|
else for (const helper of usage.helpers) if (!isRecord(helper) || hasUnsupportedField(helper, HELPER_ENTRY_FIELDS) || !HELPER_ROLES.has(helper.role) || typeof helper.disposition !== "string" || compactId(helper.disposition) !== helper.disposition || !HASH.test(String(helper.requestRef)) || (helper.outputDigest !== null && !HASH.test(String(helper.outputDigest))) || !Number.isInteger(helper.calls) || helper.calls < 0 || helper.calls > 100 || !Number.isInteger(helper.tokens) || helper.tokens < 0 || helper.tokens > 100_000_000) errors.push("acceptanceReceipt helper entry is invalid");
|
|
884
948
|
}
|
|
885
949
|
if (!Array.isArray(value.criteria) || value.criteria.length === 0 || value.criteria.length > MAX_CRITERIA) {
|