@piagent/platform 1.2.11 → 1.2.12
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 +37 -0
- package/README.md +9 -7
- package/benchmarks/production-v1/grade.mjs +220 -0
- package/benchmarks/production-v1/project/README.md +7 -0
- package/benchmarks/production-v1/project/config/service.json +4 -0
- package/benchmarks/production-v1/project/data/audit-ledger.jsonl +1 -0
- package/benchmarks/production-v1/project/docs/ops.md +3 -0
- package/benchmarks/production-v1/project/logs/incident.log +2 -0
- package/benchmarks/production-v1/project/package.json +11 -0
- package/benchmarks/production-v1/project/scripts/check.mjs +21 -0
- package/benchmarks/production-v1/project/src/backend/auth.js +3 -0
- package/benchmarks/production-v1/project/src/backend/cache.js +15 -0
- package/benchmarks/production-v1/project/src/backend/invoice.js +4 -0
- package/benchmarks/production-v1/project/src/data/csv.js +3 -0
- package/benchmarks/production-v1/project/src/data/dedup.js +5 -0
- package/benchmarks/production-v1/project/src/data/migration.js +9 -0
- package/benchmarks/production-v1/project/src/frontend/pagination.js +8 -0
- package/benchmarks/production-v1/project/src/frontend/search-state.js +8 -0
- package/benchmarks/production-v1/project/src/frontend/unicode-search.js +7 -0
- package/benchmarks/production-v1/project/src/platform/args.js +10 -0
- package/benchmarks/production-v1/project/src/platform/config.js +7 -0
- package/benchmarks/production-v1/project/src/platform/workspace.js +13 -0
- package/benchmarks/production-v1/project/src/reliability/expiry.js +5 -0
- package/benchmarks/production-v1/project/src/reliability/retry.js +15 -0
- package/benchmarks/production-v1/project/test/smoke.test.js +12 -0
- package/benchmarks/production-v1/project/vendor/README.md +1 -0
- package/benchmarks/production-v1/prompts/bounded-retry.md +7 -0
- package/benchmarks/production-v1/prompts/cli-double-dash.md +7 -0
- package/benchmarks/production-v1/prompts/config-precedence.md +6 -0
- package/benchmarks/production-v1/prompts/destructive-history-refusal.md +3 -0
- package/benchmarks/production-v1/prompts/expiry-boundary.md +7 -0
- package/benchmarks/production-v1/prompts/incident-diagnosis.md +4 -0
- package/benchmarks/production-v1/prompts/invoice-rounding.md +9 -0
- package/benchmarks/production-v1/prompts/pagination-boundary.md +7 -0
- package/benchmarks/production-v1/prompts/protected-env-refusal.md +2 -0
- package/benchmarks/production-v1/prompts/quoted-csv.md +6 -0
- package/benchmarks/production-v1/prompts/repository-prompt-injection.md +5 -0
- package/benchmarks/production-v1/prompts/schema-migration.md +6 -0
- package/benchmarks/production-v1/prompts/stable-dedup.md +6 -0
- package/benchmarks/production-v1/prompts/stale-search-response.md +6 -0
- package/benchmarks/production-v1/prompts/tenant-cache-isolation.md +6 -0
- package/benchmarks/production-v1/prompts/tenant-role-authorization.md +6 -0
- package/benchmarks/production-v1/prompts/unicode-search.md +6 -0
- package/benchmarks/production-v1/prompts/workspace-order.md +7 -0
- package/benchmarks/production-v1/suite.json +284 -0
- package/benchmarks/production-v1/variant.mjs +112 -0
- package/docs/command-reference-vietnamese.md +15 -6
- package/docs/distribution-standard.md +7 -7
- package/docs/operator-manual-vietnamese.md +29 -13
- package/docs/quality-benchmark.md +129 -18
- package/docs/release-install-policy.md +15 -11
- package/docs/runtime-policy-design.md +2 -1
- package/docs/runtime-quality-baseline.md +13 -2
- package/docs/security-threat-model.md +1 -1
- package/docs/team-onboarding.md +2 -2
- package/docs-site/architecture.html +1 -1
- package/docs-site/commands.html +1 -1
- package/docs-site/content/runtime.html +7 -1
- package/docs-site/context-engine.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 +8 -2
- package/docs-site/scope.html +1 -1
- package/docs-site/security.html +1 -1
- package/docs-site/team.html +1 -1
- package/docs-site/workflows.html +1 -1
- package/package.json +1 -1
- package/packages/piagent-core/benchmark/benchmark-core.js +325 -41
- package/packages/piagent-core/extensions/piagent-guard.ts +47 -12
- package/packages/piagent-core/package.json +1 -1
- package/scripts/benchmark-runner.mjs +328 -68
- package/scripts/verify-local.sh +4 -0
|
@@ -3959,6 +3959,10 @@ function taskScopeIncludesPath(scope: string[], file: string): boolean {
|
|
|
3959
3959
|
});
|
|
3960
3960
|
}
|
|
3961
3961
|
|
|
3962
|
+
function verifierCommandInstructions(commands: string[]): string[] {
|
|
3963
|
+
return commands.map((command, index) => `Verifier ${index + 1} (run as its own shell call): ${command}`);
|
|
3964
|
+
}
|
|
3965
|
+
|
|
3962
3966
|
function evaluateTaskGate(
|
|
3963
3967
|
cwd: string,
|
|
3964
3968
|
task: TaskContract | undefined,
|
|
@@ -3970,6 +3974,7 @@ function evaluateTaskGate(
|
|
|
3970
3974
|
): {
|
|
3971
3975
|
decision: "pass" | "fail";
|
|
3972
3976
|
missing: string[];
|
|
3977
|
+
missingVerifyCommands: string[];
|
|
3973
3978
|
warnings: string[];
|
|
3974
3979
|
changedFileEvidence?: ReturnType<typeof taskChangedFileEvidence>;
|
|
3975
3980
|
} {
|
|
@@ -3977,7 +3982,7 @@ function evaluateTaskGate(
|
|
|
3977
3982
|
const missing: string[] = [];
|
|
3978
3983
|
const warnings: string[] = [];
|
|
3979
3984
|
if (!task) {
|
|
3980
|
-
return { decision: "fail", missing: ["task contract"], warnings };
|
|
3985
|
+
return { decision: "fail", missing: ["task contract"], missingVerifyCommands: [], warnings };
|
|
3981
3986
|
}
|
|
3982
3987
|
const currentDigests = options.currentDigests ?? workingTreeSnapshot(cwd) as Record<string, string>;
|
|
3983
3988
|
const currentWorkingTreeDigest = options.currentWorkingTreeDigest ?? workingTreeEvidenceDigest(currentDigests);
|
|
@@ -4000,6 +4005,7 @@ function evaluateTaskGate(
|
|
|
4000
4005
|
))) {
|
|
4001
4006
|
warnings.push("Verification evidence from a different working-tree snapshot is stale and is ignored.");
|
|
4002
4007
|
}
|
|
4008
|
+
let missingVerifyCommands: string[] = [];
|
|
4003
4009
|
if (task.changeMode === "source-change" && finalGate.requirePassingVerify && plannedVerifyCommands.length > 0) {
|
|
4004
4010
|
const passingCommands = new Set(task.verifyEvidence
|
|
4005
4011
|
.filter((evidence) => (
|
|
@@ -4009,8 +4015,8 @@ function evaluateTaskGate(
|
|
|
4009
4015
|
&& evidence.workingTreeDigest === currentWorkingTreeDigest
|
|
4010
4016
|
))
|
|
4011
4017
|
.map((evidence) => evidence.command.trim()));
|
|
4012
|
-
|
|
4013
|
-
if (
|
|
4018
|
+
missingVerifyCommands = plannedVerifyCommands.filter((command) => !passingCommands.has(command.trim()));
|
|
4019
|
+
if (missingVerifyCommands.length > 0) missing.push(`observed passing verify evidence for every configured command (${missingVerifyCommands.length} missing)`);
|
|
4014
4020
|
}
|
|
4015
4021
|
if (finalGate.requireTrace && task.trace.outcome !== "completed") missing.push("completed final trace");
|
|
4016
4022
|
const incompleteSteps = (task.workPlan ?? []).filter((step) => step.status === "pending" || step.status === "in-progress" || step.status === "failed");
|
|
@@ -4027,7 +4033,7 @@ function evaluateTaskGate(
|
|
|
4027
4033
|
if (task.changeMode === "read-only" && changedFileEvidence.expected.length > 0) {
|
|
4028
4034
|
missing.push(`read-only task has observed changes (${changedFileEvidence.expected.join(", ")})`);
|
|
4029
4035
|
}
|
|
4030
|
-
return { decision: missing.length === 0 ? "pass" : "fail", missing, warnings, changedFileEvidence };
|
|
4036
|
+
return { decision: missing.length === 0 ? "pass" : "fail", missing, missingVerifyCommands, warnings, changedFileEvidence };
|
|
4031
4037
|
}
|
|
4032
4038
|
|
|
4033
4039
|
function assistantMessageText(message: unknown): string {
|
|
@@ -5143,6 +5149,16 @@ function automaticTaskIntakeEligible(prompt: string, readProtectedPaths: string[
|
|
|
5143
5149
|
return !signal.paths.some((candidate) => matchesProtectedPath(candidate, readProtectedPaths));
|
|
5144
5150
|
}
|
|
5145
5151
|
|
|
5152
|
+
function manualTaskIntakeEligible(prompt: string, readProtectedPaths: string[]): boolean {
|
|
5153
|
+
const text = String(prompt ?? "").trim();
|
|
5154
|
+
if (!text || text.length > LONG_INPUT_CHARS) return false;
|
|
5155
|
+
const signal = classifyContextTask(text);
|
|
5156
|
+
if (signal.workflow !== "task" || !AUTO_INTAKE_CHANGE_INTENT.test(text)) return false;
|
|
5157
|
+
if (AUTO_INTAKE_READ_ONLY_LEAD.test(text) || /\bpiagent_task_start\b/i.test(text)) return false;
|
|
5158
|
+
if (signal.paths.length === 0) return true;
|
|
5159
|
+
return signal.paths.some((candidate) => !matchesProtectedPath(candidate, readProtectedPaths));
|
|
5160
|
+
}
|
|
5161
|
+
|
|
5146
5162
|
function automaticTaskScope(prompt: string, context: Array<{ path: string }>): string[] {
|
|
5147
5163
|
const signal = classifyContextTask(prompt);
|
|
5148
5164
|
const explicit = signal.paths.filter((candidate) => candidate && candidate !== "." && !candidate.startsWith(".pi/"));
|
|
@@ -5212,7 +5228,9 @@ function semanticCompactionInstructions(cwd: string, sessionId: string): string
|
|
|
5212
5228
|
`Acceptance: ${task.acceptanceCriteria.join("; ") || "not recorded"}`,
|
|
5213
5229
|
`Scope: ${task.scope.join(", ") || "not recorded"}`,
|
|
5214
5230
|
`Changed files: ${task.changedFiles.join(", ") || "none recorded"}`,
|
|
5215
|
-
|
|
5231
|
+
task.verifyCommands.length > 0
|
|
5232
|
+
? ["Exact verify commands:", ...verifierCommandInstructions(task.verifyCommands)].join("\n")
|
|
5233
|
+
: "Exact verify commands: not recorded",
|
|
5216
5234
|
`Outcome/blocker: ${task.trace.outcome}${task.trace.friction ? `; ${task.trace.friction}` : ""}`
|
|
5217
5235
|
].join("\n")
|
|
5218
5236
|
: "No persisted task contract was found. Derive the current goal from the most recent user request.";
|
|
@@ -5574,12 +5592,16 @@ export default function piagentGuard(pi: ExtensionAPI) {
|
|
|
5574
5592
|
const activeTask = activeSessionTask(ctx.cwd, ctx.sessionManager.getSessionId()) as TaskContract | undefined;
|
|
5575
5593
|
const readProtectedPaths = effectiveProtectedPaths(policy, loadProfileFromContext(ctx)).readProtectedPaths;
|
|
5576
5594
|
const protectedTarget = taskSignal.paths.some((candidate) => matchesProtectedPath(candidate, readProtectedPaths));
|
|
5595
|
+
const protectedOnlyTarget = taskSignal.paths.length > 0
|
|
5596
|
+
&& taskSignal.paths.every((candidate) => matchesProtectedPath(candidate, readProtectedPaths));
|
|
5577
5597
|
const runtimeIntake = !activeTask && automaticTaskIntakeEligible(text, readProtectedPaths);
|
|
5578
|
-
const
|
|
5598
|
+
const manualIntake = !activeTask && !runtimeIntake && manualTaskIntakeEligible(text, readProtectedPaths);
|
|
5599
|
+
const promptGroups = protectedOnlyTarget
|
|
5579
5600
|
? []
|
|
5580
5601
|
: toolGroupsForPrompt(text).filter((group) => (
|
|
5581
5602
|
runtimeIntake ? group !== "intake" && group !== "task" : true
|
|
5582
5603
|
));
|
|
5604
|
+
if (manualIntake && !promptGroups.includes("intake")) promptGroups.push("intake");
|
|
5583
5605
|
activateToolGroups(ctx, activeTask?.trace.outcome === "pending"
|
|
5584
5606
|
? [...promptGroups.filter((group) => group !== "intake"), ...activeTaskToolGroups(activeTask)]
|
|
5585
5607
|
: promptGroups);
|
|
@@ -5592,6 +5614,8 @@ export default function piagentGuard(pi: ExtensionAPI) {
|
|
|
5592
5614
|
riskLane: taskSignal.lane,
|
|
5593
5615
|
intakeMode: runtimeIntake ? "runtime" : "model",
|
|
5594
5616
|
protectedTarget,
|
|
5617
|
+
protectedOnlyTarget,
|
|
5618
|
+
manualIntake,
|
|
5595
5619
|
explicitPathCount: taskSignal.paths.length,
|
|
5596
5620
|
termCount: taskSignal.terms.length
|
|
5597
5621
|
});
|
|
@@ -5660,10 +5684,11 @@ export default function piagentGuard(pi: ExtensionAPI) {
|
|
|
5660
5684
|
const signal = classifyContextTask(query);
|
|
5661
5685
|
const profile = loadProfileFromContext(ctx);
|
|
5662
5686
|
const readProtectedPaths = effectiveProtectedPaths(policy, profile).readProtectedPaths;
|
|
5663
|
-
const
|
|
5687
|
+
const protectedOnlyTarget = signal.paths.length > 0
|
|
5688
|
+
&& signal.paths.every((candidate) => matchesProtectedPath(candidate, readProtectedPaths));
|
|
5664
5689
|
const activeTask = activeSessionTask(ctx.cwd, ctx.sessionManager.getSessionId()) as TaskContract | undefined;
|
|
5665
5690
|
const runtimeIntake = !activeTask && automaticTaskIntakeEligible(query, readProtectedPaths);
|
|
5666
|
-
const compactMode =
|
|
5691
|
+
const compactMode = protectedOnlyTarget
|
|
5667
5692
|
? "protected"
|
|
5668
5693
|
: runtimeIntake || activeTask?.intakeMode === "runtime"
|
|
5669
5694
|
? "automatic"
|
|
@@ -5922,6 +5947,7 @@ export default function piagentGuard(pi: ExtensionAPI) {
|
|
|
5922
5947
|
]
|
|
5923
5948
|
: [
|
|
5924
5949
|
"Continue the same bounded task. Re-check the requested behavior against current source, make a relevant in-scope change when required, and run every exact configured verifier.",
|
|
5950
|
+
...verifierCommandInstructions(gate.missingVerifyCommands),
|
|
5925
5951
|
"A pre-existing passing test without a relevant source diff is not completion. Do not repeat diagnostic Piagent tools; use ordinary read/edit/bash work."
|
|
5926
5952
|
];
|
|
5927
5953
|
const recovery = [
|
|
@@ -5959,6 +5985,7 @@ export default function piagentGuard(pi: ExtensionAPI) {
|
|
|
5959
5985
|
`[Piagent completion gate: NOT APPROVED]`,
|
|
5960
5986
|
`Task ${task.taskId} (${task.taskRunId}) is still open.`,
|
|
5961
5987
|
`Missing: ${gate.missing.join(", ") || "a completed task trace"}.`,
|
|
5988
|
+
...verifierCommandInstructions(gate.missingVerifyCommands),
|
|
5962
5989
|
"The response below is preserved as work in progress and must not be treated as a completion report.",
|
|
5963
5990
|
""
|
|
5964
5991
|
].join("\n");
|
|
@@ -6784,6 +6811,7 @@ export default function piagentGuard(pi: ExtensionAPI) {
|
|
|
6784
6811
|
`decision: ${result.decision}`,
|
|
6785
6812
|
`mode: ${runtime.finalGate}`,
|
|
6786
6813
|
`missing: ${result.missing.join(", ") || "none"}`,
|
|
6814
|
+
...verifierCommandInstructions(result.missingVerifyCommands),
|
|
6787
6815
|
`warnings: ${result.warnings.join("; ") || "none"}`
|
|
6788
6816
|
].join("\n");
|
|
6789
6817
|
return { content: [{ type: "text", text }], details: { ...result, task: projected } };
|
|
@@ -7616,7 +7644,7 @@ export default function piagentGuard(pi: ExtensionAPI) {
|
|
|
7616
7644
|
text: [
|
|
7617
7645
|
`Task ${taskId} started (${params.riskLane}, ${lifecycleMode}; attempt ${attempt}/${maxAttempts}).`,
|
|
7618
7646
|
written.verifyCommands.length > 0
|
|
7619
|
-
?
|
|
7647
|
+
? ["Exact verifier commands:", ...verifierCommandInstructions(written.verifyCommands)].join("\n")
|
|
7620
7648
|
: "Verify: none (read-only).",
|
|
7621
7649
|
lifecycleMode === "automatic-readonly"
|
|
7622
7650
|
? "Runtime records targeted reads and final completion automatically. Stay read-only and report cited evidence."
|
|
@@ -7686,12 +7714,13 @@ export default function piagentGuard(pi: ExtensionAPI) {
|
|
|
7686
7714
|
text: "Piagent runtime intake did not persist a task contract. Use piagent_task_start once before mutation."
|
|
7687
7715
|
};
|
|
7688
7716
|
}
|
|
7689
|
-
const verify = task.verifyCommands.length > 0 ? task.verifyCommands.join(" | ") : "none";
|
|
7690
7717
|
return {
|
|
7691
7718
|
started: true,
|
|
7692
7719
|
task,
|
|
7693
7720
|
text: [
|
|
7694
|
-
`Piagent runtime task: ${task.taskId}; scope: ${task.scope.join(", ")}
|
|
7721
|
+
`Piagent runtime task: ${task.taskId}; scope: ${task.scope.join(", ")}.`,
|
|
7722
|
+
"Exact verifier commands:",
|
|
7723
|
+
...(task.verifyCommands.length > 0 ? verifierCommandInstructions(task.verifyCommands) : ["none"]),
|
|
7695
7724
|
"Root project instructions are loaded. Do not re-read root AGENTS.md or inspect Piagent/platform files; work directly in relevant source/tests with ordinary tools.",
|
|
7696
7725
|
"Finish intended edits, then run the exact verifier once; rerun only after a later mutation. Runtime records evidence and completion; do not call task-management tools."
|
|
7697
7726
|
].join("\n")
|
|
@@ -8212,7 +8241,13 @@ export default function piagentGuard(pi: ExtensionAPI) {
|
|
|
8212
8241
|
appendTrace(ctx.cwd, blockedTrace);
|
|
8213
8242
|
appendSessionTrace(pi, blockedTrace);
|
|
8214
8243
|
return {
|
|
8215
|
-
content: [{
|
|
8244
|
+
content: [{
|
|
8245
|
+
type: "text",
|
|
8246
|
+
text: [
|
|
8247
|
+
`Final gate blocked completion: missing ${gate.missing.join(", ")}`,
|
|
8248
|
+
...verifierCommandInstructions(gate.missingVerifyCommands)
|
|
8249
|
+
].join("\n")
|
|
8250
|
+
}],
|
|
8216
8251
|
details: { gate, task: nextTask },
|
|
8217
8252
|
isError: true
|
|
8218
8253
|
};
|